diff options
-rw-r--r-- | drivers/leds/leds-pwm.c | 29 | ||||
-rw-r--r-- | include/linux/leds_pwm.h | 20 |
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 |