From: Felipe Balbi <felipe.balbi@nokia.com>
To: linux-omap@vger.kernel.org
Cc: David Brownell <dbrownell@users.sourceforge.net>,
Felipe Balbi <felipe.balbi@nokia.com>
Subject: [PATCH 4/6] i2c: lp5521: move to LED framework
Date: Fri, 13 Feb 2009 14:43:50 +0200 [thread overview]
Message-ID: <1234529032-25354-5-git-send-email-felipe.balbi@nokia.com> (raw)
In-Reply-To: <1234529032-25354-4-git-send-email-felipe.balbi@nokia.com>
Register three separate leds for lp5521 and allow
them to be controlled separately while keeping
backwards compatibility with userspace programs
based on old implementation.
Signed-off-by: Felipe Balbi <felipe.balbi@nokia.com>
---
drivers/i2c/chips/lp5521.c | 172 ++++++++++++++++++++++++++++++++++++++++---
include/linux/i2c/lp5521.h | 43 +++++++++++
2 files changed, 203 insertions(+), 12 deletions(-)
create mode 100644 include/linux/i2c/lp5521.h
diff --git a/drivers/i2c/chips/lp5521.c b/drivers/i2c/chips/lp5521.c
index 9e94ff8..b3ba52a 100644
--- a/drivers/i2c/chips/lp5521.c
+++ b/drivers/i2c/chips/lp5521.c
@@ -4,6 +4,7 @@
* Copyright (C) 2007 Nokia Corporation
*
* Written by Mathias Nyman <mathias.nyman@nokia.com>
+ * Updated by Felipe Balbi <felipe.balbi@nokia.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -23,7 +24,10 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/i2c.h>
+#include <linux/leds.h>
#include <linux/mutex.h>
+#include <linux/workqueue.h>
+#include <linux/i2c/lp5521.h>
#define LP5521_DRIVER_NAME "lp5521"
@@ -65,17 +69,21 @@
#define LP5521_PROGRAM_LENGTH 32 /* in bytes */
-enum lp5521_mode {
- LP5521_MODE_LOAD,
- LP5521_MODE_RUN,
- LP5521_MODE_DIRECT_CONTROL,
-};
-
struct lp5521_chip {
/* device lock */
struct mutex lock;
struct i2c_client *client;
+
+ struct work_struct red_work;
+ struct work_struct green_work;
+ struct work_struct blue_work;
+
+ struct led_classdev ledr;
+ struct led_classdev ledg;
+ struct led_classdev ledb;
+
enum lp5521_mode mode;
+
int red;
int green;
int blue;
@@ -489,6 +497,87 @@ static int lp5521_set_mode(struct lp5521_chip *chip, enum lp5521_mode mode)
return ret;
}
+static void lp5521_red_work(struct work_struct *work)
+{
+ struct lp5521_chip *chip = container_of(work, struct lp5521_chip, red_work);
+ int ret;
+
+ ret = lp5521_configure(chip->client);
+ if (ret) {
+ dev_dbg(&chip->client->dev, "could not configure lp5521, %d\n",
+ ret);
+ return;
+ }
+
+ ret = lp5521_write(chip->client, LP5521_REG_R_PWM, chip->red);
+ if (ret)
+ dev_dbg(&chip->client->dev, "could not set brightness, %d\n",
+ ret);
+}
+
+static void lp5521_red_set(struct led_classdev *led,
+ enum led_brightness value)
+{
+ struct lp5521_chip *chip = container_of(led, struct lp5521_chip, ledr);
+
+ chip->red = value;
+ schedule_work(&chip->red_work);
+}
+
+static void lp5521_green_work(struct work_struct *work)
+{
+ struct lp5521_chip *chip = container_of(work, struct lp5521_chip, green_work);
+ int ret;
+
+ ret = lp5521_configure(chip->client);
+ if (ret) {
+ dev_dbg(&chip->client->dev, "could not configure lp5521, %d\n",
+ ret);
+ return;
+ }
+
+ ret = lp5521_write(chip->client, LP5521_REG_G_PWM, chip->green);
+ if (ret)
+ dev_dbg(&chip->client->dev, "could not set brightness, %d\n",
+ ret);
+}
+
+static void lp5521_green_set(struct led_classdev *led,
+ enum led_brightness value)
+{
+ struct lp5521_chip *chip = container_of(led, struct lp5521_chip, ledg);
+
+ chip->green = value;
+ schedule_work(&chip->green_work);
+}
+
+static void lp5521_blue_work(struct work_struct *work)
+{
+ struct lp5521_chip *chip = container_of(work, struct lp5521_chip, blue_work);
+ int ret;
+
+ ret = lp5521_configure(chip->client);
+ if (ret) {
+ dev_dbg(&chip->client->dev, "could not configure lp5521, %d\n",
+ ret);
+ return;
+ }
+
+ ret = lp5521_write(chip->client, LP5521_REG_B_PWM, chip->blue);
+ if (ret)
+ dev_dbg(&chip->client->dev, "could not set brightness, %d\n",
+ ret);
+}
+
+static void lp5521_blue_set(struct led_classdev *led,
+ enum led_brightness value)
+{
+ struct lp5521_chip *chip = container_of(led, struct lp5521_chip, ledb);
+
+ chip->blue = value;
+ schedule_work(&chip->blue_work);
+}
+
/*--------------------------------------------------------------*/
/* Probe, Attach, Remove */
/*--------------------------------------------------------------*/
@@ -496,9 +585,16 @@ static int lp5521_set_mode(struct lp5521_chip *chip, enum lp5521_mode mode)
static int __init lp5521_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
+ struct lp5521_platform_data *pdata = client->dev.platform_data;
struct lp5521_chip *chip;
+ char name[16];
int ret = 0;
+ if (!pdata) {
+ dev_err(&client->dev, "platform_data is missing\n");
+ return -EINVAL;
+ }
+
chip = kzalloc(sizeof(*chip), GFP_KERNEL);
if (!chip)
return -ENOMEM;
@@ -509,6 +605,10 @@ static int __init lp5521_probe(struct i2c_client *client,
mutex_init(&chip->lock);
+ INIT_WORK(&chip->red_work, lp5521_red_work);
+ INIT_WORK(&chip->green_work, lp5521_green_work);
+ INIT_WORK(&chip->blue_work, lp5521_blue_work);
+
ret = lp5521_configure(client);
if (ret < 0) {
dev_err(&client->dev, "lp5521 error configuring chip \n");
@@ -516,19 +616,61 @@ static int __init lp5521_probe(struct i2c_client *client,
}
/* Set default values */
- chip->mode = LP5521_MODE_DIRECT_CONTROL;
- chip->red = 1;
- chip->green = 1;
- chip->blue = 1;
+ chip->mode = pdata->mode;
+ chip->red = pdata->red_present;
+ chip->green = pdata->green_present;
+ chip->blue = pdata->blue_present;
+
+ chip->ledr.brightness_set = lp5521_red_set;
+ chip->ledr.default_trigger = NULL;
+ snprintf(name, sizeof(name), "%s::red", pdata->label);
+ chip->ledr.name = name;
+ ret = led_classdev_register(&client->dev, &chip->ledr);
+ if (ret < 0) {
+ dev_dbg(&client->dev, "failed to register led %s, %d\n",
+ chip->ledb.name, ret);
+ goto fail1;
+ }
+
+ chip->ledg.brightness_set = lp5521_green_set;
+ chip->ledg.default_trigger = NULL;
+ snprintf(name, sizeof(name), "%s::green", pdata->label);
+ chip->ledg.name = name;
+ ret = led_classdev_register(&client->dev, &chip->ledg);
+ if (ret < 0) {
+ dev_dbg(&client->dev, "failed to register led %s, %d\n",
+ chip->ledb.name, ret);
+ goto fail2;
+ }
+
+ chip->ledb.brightness_set = lp5521_blue_set;
+ chip->ledb.default_trigger = NULL;
+ snprintf(name, sizeof(name), "%s::blue", pdata->label);
+ chip->ledb.name = name;
+ ret = led_classdev_register(&client->dev, &chip->ledb);
+ if (ret < 0) {
+ dev_dbg(&client->dev, "failed to register led %s, %d\n", chip->ledb.name, ret);
+ goto fail3;
+ }
ret = lp5521_register_sysfs(client);
- if (ret)
+ if (ret) {
dev_err(&client->dev, "lp5521 registering sysfs failed \n");
+ goto fail4;
+ }
- return ret;
+ return 0;
+fail4:
+ led_classdev_unregister(&chip->ledb);
+fail3:
+ led_classdev_unregister(&chip->ledg);
+fail2:
+ led_classdev_unregister(&chip->ledr);
fail1:
+ i2c_set_clientdata(client, NULL);
kfree(chip);
+
return ret;
}
@@ -537,6 +679,12 @@ static int __exit lp5521_remove(struct i2c_client *client)
struct lp5521_chip *chip = i2c_get_clientdata(client);
lp5521_unregister_sysfs(client);
+ i2c_set_clientdata(client, NULL);
+
+ led_classdev_unregister(&chip->ledb);
+ led_classdev_unregister(&chip->ledg);
+ led_classdev_unregister(&chip->ledr);
+
kfree(chip);
return 0;
diff --git a/include/linux/i2c/lp5521.h b/include/linux/i2c/lp5521.h
new file mode 100644
index 0000000..070e8be
--- /dev/null
+++ b/include/linux/i2c/lp5521.h
@@ -0,0 +1,43 @@
+/*
+ * lp5521.h - header for LP5521 LED driver
+ *
+ * Copyright (C) 2009 Nokia Corporation
+ *
+ * Contact: Felipe Balbi <felipe.balbi@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#ifndef __LP5521_H_
+#define __LP5521_H_
+
+enum lp5521_mode {
+ LP5521_MODE_LOAD,
+ LP5521_MODE_RUN,
+ LP5521_MODE_DIRECT_CONTROL,
+};
+
+struct lp5521_platform_data {
+ enum lp5521_mode mode;
+
+ unsigned red_present:1;
+ unsigned green_present:1;
+ unsigned blue_present:1;
+
+ const char *label;
+};
+
+#endif /* End of __LP5521_H */
--
1.6.1.265.g9a013
next prev parent reply other threads:[~2009-02-13 12:58 UTC|newest]
Thread overview: 27+ messages / expand[flat|nested] mbox.gz Atom feed top
2009-02-10 12:15 [PATCH 0/8] updates to two nokia drivers Felipe Balbi
2009-02-10 12:15 ` [PATCH 1/8] i2c: lp5521: remove dead code Felipe Balbi
2009-02-10 12:15 ` [PATCH 2/8] i2c: lp5521: cosmetic fixes Felipe Balbi
2009-02-10 12:16 ` [PATCH 3/8] i2c: lp5521: simplify mode setting Felipe Balbi
2009-02-10 12:16 ` [PATCH 4/8] i2c: lp5521: move to LED framework Felipe Balbi
2009-02-10 12:16 ` [PATCH 5/8] leds: lp5521: move to drivers/leds Felipe Balbi
2009-02-10 12:16 ` [PATCH 6/8] input: lm8323: get rid of global pdata pointer Felipe Balbi
2009-02-10 12:16 ` [PATCH 7/8] input: lm8323: get rid of useless debug macro Felipe Balbi
2009-02-10 12:16 ` [PATCH 8/8] input: lm8323: general clean up Felipe Balbi
2009-02-12 22:18 ` [PATCH 4/8] i2c: lp5521: move to LED framework David Brownell
2009-02-13 0:00 ` Felipe Balbi
2009-02-13 12:43 ` [RESEND] lp5521 patches Felipe Balbi
2009-02-13 12:43 ` [PATCH 1/6] i2c: lp5521: remove dead code Felipe Balbi
2009-02-13 12:43 ` [PATCH 2/6] i2c: lp5521: cosmetic fixes Felipe Balbi
2009-02-13 12:43 ` [PATCH 3/6] i2c: lp5521: simplify mode setting Felipe Balbi
2009-02-13 12:43 ` Felipe Balbi [this message]
2009-02-13 12:43 ` [PATCH 5/6] leds: lp5521: move to drivers/leds Felipe Balbi
2009-02-13 12:43 ` [PATCH 6/6] arm: omap: n810: add lp5521 platform_data Felipe Balbi
2009-02-13 20:49 ` [PATCH 5/6] leds: lp5521: move to drivers/leds David Brownell
2009-02-13 22:36 ` Felipe Balbi
2009-02-13 23:54 ` David Brownell
2009-02-14 0:07 ` Felipe Balbi
2009-02-17 21:38 ` [RESEND] lp5521 patches Otto Solares
2009-02-17 23:07 ` Felipe Balbi
2009-02-17 23:29 ` Felipe Balbi
2009-02-17 23:44 ` Tony Lindgren
2009-02-17 23:50 ` Felipe Balbi
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1234529032-25354-5-git-send-email-felipe.balbi@nokia.com \
--to=felipe.balbi@nokia.com \
--cc=dbrownell@users.sourceforge.net \
--cc=linux-omap@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.