aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/leds/leds-pwm.c29
-rw-r--r--include/linux/leds_pwm.h20
2 files changed, 44 insertions, 5 deletions
diff --git a/drivers/leds/leds-pwm.c b/drivers/leds/leds-pwm.c
index da3fa8dcdf5..ee9c7085664 100644
--- a/drivers/leds/leds-pwm.c
+++ b/drivers/leds/leds-pwm.c
@@ -26,8 +26,8 @@
struct led_pwm_data {
struct led_classdev cdev;
struct pwm_device *pwm;
- unsigned int active_low;
- unsigned int period;
+ struct led_pwm *led;
+ struct device *parent;
};
static void led_pwm_set(struct led_classdev *led_cdev,
@@ -35,8 +35,13 @@ static void led_pwm_set(struct led_classdev *led_cdev,
{
struct led_pwm_data *led_dat =
container_of(led_cdev, struct led_pwm_data, cdev);
+ struct device *parent = led_dat->parent;
+ struct led_pwm_platform_data *pdata = parent->platform_data;
unsigned int max = led_dat->cdev.max_brightness;
- unsigned int period = led_dat->period;
+ unsigned int period = led_dat->led->pwm_period_ns;
+
+ if (pdata->notify)
+ brightness = pdata->notify(parent, led_dat->led, brightness);
if (brightness == 0) {
pwm_config(led_dat->pwm, 0, period);
@@ -76,18 +81,28 @@ static int led_pwm_probe(struct platform_device *pdev)
led_dat->cdev.name = cur_led->name;
led_dat->cdev.default_trigger = cur_led->default_trigger;
- led_dat->active_low = cur_led->active_low;
- led_dat->period = cur_led->pwm_period_ns;
led_dat->cdev.brightness_set = led_pwm_set;
led_dat->cdev.brightness = LED_OFF;
led_dat->cdev.max_brightness = cur_led->max_brightness;
led_dat->cdev.flags |= LED_CORE_SUSPENDRESUME;
+ led_dat->led = cur_led;
+ led_dat->parent = &pdev->dev;
+
ret = led_classdev_register(&pdev->dev, &led_dat->cdev);
if (ret < 0) {
pwm_free(led_dat->pwm);
goto err;
}
+
+ if (pdata->init) {
+ ret = pdata->init(&pdev->dev, cur_led);
+ if (ret < 0) {
+ led_classdev_unregister(&led_dat->cdev);
+ pwm_free(led_dat->pwm);
+ goto err;
+ }
+ }
}
platform_set_drvdata(pdev, leds_data);
@@ -97,6 +112,8 @@ static int led_pwm_probe(struct platform_device *pdev)
err:
if (i > 0) {
for (i = i - 1; i >= 0; i--) {
+ if (pdata->exit)
+ pdata->exit(&pdev->dev, &pdata->leds[i]);
led_classdev_unregister(&leds_data[i].cdev);
pwm_free(leds_data[i].pwm);
}
@@ -116,6 +133,8 @@ static int __devexit led_pwm_remove(struct platform_device *pdev)
leds_data = platform_get_drvdata(pdev);
for (i = 0; i < pdata->num_leds; i++) {
+ if (pdata->exit)
+ pdata->exit(&pdev->dev, &pdata->leds[i]);
led_classdev_unregister(&leds_data[i].cdev);
pwm_free(leds_data[i].pwm);
}
diff --git a/include/linux/leds_pwm.h b/include/linux/leds_pwm.h
index 33a07116748..42d49694cbd 100644
--- a/include/linux/leds_pwm.h
+++ b/include/linux/leds_pwm.h
@@ -16,6 +16,26 @@ struct led_pwm {
struct led_pwm_platform_data {
int num_leds;
struct led_pwm *leds;
+
+ /* @init: The init callback is called after the pwm device for a led has
+ * been successfully configured. If the return value is negative it will be
+ * seen as an error and initzalisation of the leds-pwm device will fail.
+ */
+ int (*init)(struct device *dev, struct led_pwm *led);
+
+ /* @notify: The notify callback is called whenever the brightness of a led
+ * is changed.
+ * The return value of the callback will be the brightness which is used to
+ * configure the pwm device.
+ */
+ enum led_brightness (*notify)(struct device *dev, struct led_pwm *led,
+ enum led_brightness brightness);
+
+ /* @exit: The exit callback is called, whenever a led device registered by
+ * the leds-pwm device is unregistered. It will be called prior to freeing
+ * the pwm device.
+ */
+ void (*exit)(struct device *dev, struct led_pwm *led);
};
#endif