leds-pm8xxx: Pass LED flags from board file
Instead of hard coding the flag into led driver, pass it
from board file.
While at it, re-factor the code to separate led upstream
core data with board specific data.
Signed-off-by: Jay Chokshi <jchokshi@codeaurora.org>
Conflicts:
drivers/mfd/pm8921-core.c
diff --git a/arch/arm/mach-msm/board-msm8960.c b/arch/arm/mach-msm/board-msm8960.c
index 365121c..ae85aff 100644
--- a/arch/arm/mach-msm/board-msm8960.c
+++ b/arch/arm/mach-msm/board-msm8960.c
@@ -3896,40 +3896,41 @@
#define PM8921_LC_LED_MAX_CURRENT 4 /* I = 4mA */
-/**
- * 'flag' stores three values; led id, led mode, and max current of led.
- * The bit packing format is as follow,
- * reserved (1 byte) | max_current (2 bytes) | led_mode (1 nibble) |
- * led_id (1 nibble)
- */
-#define PM8XXX_SET_FLAG(led_id, led_mode, led_max_current) \
- (((led_id << PM8XXX_LED_ID_SHIFT) & PM8XXX_LED_ID_MASK) |\
- ((led_mode << PM8XXX_LED_MODE_SHIFT) & PM8XXX_LED_MODE_MASK) |\
- ((led_max_current << PM8XXX_LED_MAX_CURRENT_SHIFT) & \
- PM8XXX_LED_MAX_CURRENT_MASK))
-
static struct led_info pm8921_led_info[] = {
[0] = {
.name = "led:usb",
.default_trigger = "usb-online",
- .flags = PM8XXX_SET_FLAG(PM8XXX_ID_LED_0,
- PM8XXX_LED_MODE_MANUAL,
- PM8921_LC_LED_MAX_CURRENT),
},
[1] = {
.name = "led:ac",
.default_trigger = "ac-online",
- .flags = PM8XXX_SET_FLAG(PM8XXX_ID_LED_1,
- PM8XXX_LED_MODE_MANUAL,
- PM8921_LC_LED_MAX_CURRENT),
},
};
-static struct led_platform_data pm8xxx_leds_pdata = {
+static struct led_platform_data pm8921_led_core_pdata = {
.num_leds = ARRAY_SIZE(pm8921_led_info),
.leds = pm8921_led_info,
};
+static struct pm8xxx_led_config pm8921_led_configs[] = {
+ [0] = {
+ .id = PM8XXX_ID_LED_0,
+ .mode = PM8XXX_LED_MODE_MANUAL,
+ .max_current = PM8921_LC_LED_MAX_CURRENT,
+ },
+ [1] = {
+ .id = PM8XXX_ID_LED_1,
+ .mode = PM8XXX_LED_MODE_MANUAL,
+ .max_current = PM8921_LC_LED_MAX_CURRENT,
+ },
+};
+
+static struct pm8xxx_led_platform_data pm8xxx_leds_pdata = {
+ .led_core = &pm8921_led_core_pdata,
+ .configs = pm8921_led_configs,
+ .num_configs = ARRAY_SIZE(pm8921_led_configs),
+};
+
static struct pm8921_platform_data pm8921_platform_data __devinitdata = {
.irq_pdata = &pm8xxx_irq_pdata,
.gpio_pdata = &pm8xxx_gpio_pdata,
diff --git a/drivers/leds/leds-pm8xxx.c b/drivers/leds/leds-pm8xxx.c
index 47ac04d..94af3ce 100644
--- a/drivers/leds/leds-pm8xxx.c
+++ b/drivers/leds/leds-pm8xxx.c
@@ -54,13 +54,6 @@
#define PM8XXX_LED_OFFSET(id) ((id) - PM8XXX_ID_LED_0)
-#define PM8XXX_GET_LED_ID(flag) (flag & PM8XXX_LED_ID_MASK >> \
- PM8XXX_LED_ID_SHIFT)
-#define PM8XXX_GET_LED_MODE(flag) ((flag & PM8XXX_LED_MODE_MASK) >> \
- PM8XXX_LED_MODE_SHIFT)
-#define PM8XXX_GET_LED_MAX_CURRENT(flag) ((flag & PM8XXX_LED_MAX_CURRENT_MASK)\
- >> PM8XXX_LED_MAX_CURRENT_SHIFT)
-
/**
* struct pm8xxx_led_data - internal led data structure
* @led_classdev - led class device
@@ -279,30 +272,38 @@
static int __devinit pm8xxx_led_probe(struct platform_device *pdev)
{
- const struct led_platform_data *pdata = pdev->dev.platform_data;
+ const struct pm8xxx_led_platform_data *pdata = pdev->dev.platform_data;
+ const struct led_platform_data *pcore_data;
struct led_info *curr_led;
struct pm8xxx_led_data *led, *led_dat;
- int rc, i, led_mode;
+ struct pm8xxx_led_config *led_cfg;
+ int rc, i;
if (pdata == NULL) {
dev_err(&pdev->dev, "platform data not supplied\n");
return -EINVAL;
}
- /* Let the last member of the list be zero to
- * mark the end of the list.
- */
- led = kcalloc(pdata->num_leds + 1, sizeof(*led), GFP_KERNEL);
+ pcore_data = pdata->led_core;
+
+ if (pcore_data->num_leds != pdata->num_configs) {
+ dev_err(&pdev->dev, "#no. of led configs and #no. of led"
+ "entries are not equal\n");
+ return -EINVAL;
+ }
+
+ led = kcalloc(pcore_data->num_leds, sizeof(*led), GFP_KERNEL);
if (led == NULL) {
dev_err(&pdev->dev, "failed to alloc memory\n");
return -ENOMEM;
}
- for (i = 0; i < pdata->num_leds; i++) {
- curr_led = &pdata->leds[i];
+ for (i = 0; i < pcore_data->num_leds; i++) {
+ curr_led = &pcore_data->leds[i];
led_dat = &led[i];
- /* the flags variable is used for led-id */
- led_dat->id = PM8XXX_GET_LED_ID(curr_led->flags);
+ led_cfg = &pdata->configs[i];
+
+ led_dat->id = led_cfg->id;
if (!((led_dat->id >= PM8XXX_ID_LED_KB_LIGHT) &&
(led_dat->id <= PM8XXX_ID_FLASH_LED_1))) {
@@ -317,17 +318,15 @@
led_dat->cdev.brightness_set = pm8xxx_led_set;
led_dat->cdev.brightness_get = pm8xxx_led_get;
led_dat->cdev.brightness = LED_OFF;
- led_dat->cdev.flags = LED_CORE_SUSPENDRESUME;
+ led_dat->cdev.flags = curr_led->flags;
led_dat->dev = &pdev->dev;
rc = get_init_value(led_dat, &led_dat->reg);
if (rc < 0)
goto fail_id_check;
- led_mode = PM8XXX_GET_LED_MODE(curr_led->flags);
-
- rc = pm8xxx_set_led_mode_and_max_brightness(led_dat, led_mode,
- PM8XXX_GET_LED_MAX_CURRENT(curr_led->flags));
+ rc = pm8xxx_set_led_mode_and_max_brightness(led_dat,
+ led_cfg->mode, led_cfg->max_current);
if (rc < 0)
goto fail_id_check;
@@ -341,7 +340,7 @@
goto fail_id_check;
}
- if (led_mode != PM8XXX_LED_MODE_MANUAL)
+ if (led_cfg->mode != PM8XXX_LED_MODE_MANUAL)
__pm8xxx_led_work(led_dat,
led_dat->cdev.max_brightness);
else
diff --git a/drivers/mfd/pm8921-core.c b/drivers/mfd/pm8921-core.c
index fa07d6b..f05fb8e 100644
--- a/drivers/mfd/pm8921-core.c
+++ b/drivers/mfd/pm8921-core.c
@@ -529,7 +529,7 @@
if (pdata->leds_pdata) {
leds_cell.platform_data = pdata->leds_pdata;
- leds_cell.pdata_size = sizeof(struct led_platform_data);
+ leds_cell.pdata_size = sizeof(struct pm8xxx_led_platform_data);
ret = mfd_add_devices(pmic->dev, 0, &leds_cell, 1, NULL, 0);
if (ret) {
pr_err("Failed to add leds subdevice ret=%d\n", ret);
diff --git a/include/linux/leds-pm8xxx.h b/include/linux/leds-pm8xxx.h
index 4096355..edd3c28 100644
--- a/include/linux/leds-pm8xxx.h
+++ b/include/linux/leds-pm8xxx.h
@@ -13,16 +13,10 @@
#ifndef __LEDS_PM8XXX_H__
#define __LEDS_PM8XXX_H__
+#include <linux/kernel.h>
#define PM8XXX_LEDS_DEV_NAME "pm8xxx-led"
-#define PM8XXX_LED_ID_SHIFT 0
-#define PM8XXX_LED_MODE_SHIFT 4
-#define PM8XXX_LED_MAX_CURRENT_SHIFT 8
-#define PM8XXX_LED_ID_MASK 0xF
-#define PM8XXX_LED_MODE_MASK 0xF0
-#define PM8XXX_LED_MAX_CURRENT_MASK 0xFFFF00
-
/**
* enum pm8xxx_leds - PMIC8XXX supported led ids
* @PM8XXX_ID_LED_KB_LIGHT - keyboard backlight led
@@ -55,4 +49,30 @@
PM8XXX_LED_MODE_DTEST4
};
+/**
+ * pm8xxx_led_config - led configuration parameters
+ * id - LED id
+ * mode - LED mode
+ * max_current - maximum current that LED can sustain
+ */
+struct pm8xxx_led_config {
+ u8 id;
+ u8 mode;
+ u16 max_current;
+};
+
+/**
+ * pm8xxx_led_platform_data - platform data for LED
+ * led_core - array of LEDs. Each datum in array contains
+ * core data for the LED
+ * configs - array of platform configuration parameters
+ * for each LED. It maps one-to-one with
+ * array of LEDs
+ * num_configs - count of members of configs array
+ */
+struct pm8xxx_led_platform_data {
+ struct led_platform_data *led_core;
+ struct pm8xxx_led_config *configs;
+ u32 num_configs;
+};
#endif /* __LEDS_PM8XXX_H__ */
diff --git a/include/linux/mfd/pm8xxx/pm8921.h b/include/linux/mfd/pm8xxx/pm8921.h
index bde5bbc..64bdab1 100644
--- a/include/linux/mfd/pm8xxx/pm8921.h
+++ b/include/linux/mfd/pm8xxx/pm8921.h
@@ -33,7 +33,7 @@
#include <linux/mfd/pm8xxx/pm8921-charger.h>
#include <linux/mfd/pm8xxx/pm8921-adc.h>
#include <linux/mfd/pm8xxx/pm8921-bms.h>
-#include <linux/leds.h>
+#include <linux/leds-pm8xxx.h>
#include <linux/mfd/pm8xxx/vibrator.h>
#define PM8921_NR_IRQS 256
@@ -126,7 +126,7 @@
struct pm8921_regulator_platform_data *regulator_pdatas;
int num_regulators;
struct pm8921_adc_platform_data *adc_pdata;
- struct led_platform_data *leds_pdata;
+ struct pm8xxx_led_platform_data *leds_pdata;
struct pm8xxx_vibrator_platform_data *vibrator_pdata;
};