diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-06-13 00:08:09 +0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-06-13 00:08:09 +0400 |
commit | 7c574cf6aeb75920ba4d3af937bb1b3c42785ac4 (patch) | |
tree | 336586614fcbba9fb8fc6095d23f87d8ce11b559 /drivers/leds/leds-pwm.c | |
parent | af76004cf8b4f368583bda22d7e348e40a338b91 (diff) | |
parent | 0c9a03b68511daf078256367e7a98d7ff3b7dfcb (diff) | |
download | linux-7c574cf6aeb75920ba4d3af937bb1b3c42785ac4.tar.xz |
Merge branch 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/cooloney/linux-leds
Pull LED updates from Bryan Wu:
"I just found merge window is open and I'm quite busy and almost forget
to send out this pull request. Thanks Russell and Alexandre ping me
about this.
So basically we got some clean up and leds-pwm fixing patches from
Russell"
* 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/cooloney/linux-leds:
leds: Remove duplicated OOM message for individual driver
drivers/leds: Replace __get_cpu_var use through this_cpu_ptr
leds: lp55xx: add DT bindings for LP55231
leds: 88pm860x: Fix missing refcount decrement for parent of_node
leds: 88pm860x: Use of_get_child_by_name
leds: leds-pwm: add DT support for LEDs wired to supply
leds: leds-pwm: implement PWM inversion
leds: leds-pwm: convert OF parsing code to use led_pwm_add()
leds: leds-pwm: provide a common function to setup a single led-pwm device
leds: pca9685: Remove leds-pca9685 driver
dell-led: add mic mute led interface
Diffstat (limited to 'drivers/leds/leds-pwm.c')
-rw-r--r-- | drivers/leds/leds-pwm.c | 150 |
1 files changed, 73 insertions, 77 deletions
diff --git a/drivers/leds/leds-pwm.c b/drivers/leds/leds-pwm.c index aa770ec1e892..d672bb4480f6 100644 --- a/drivers/leds/leds-pwm.c +++ b/drivers/leds/leds-pwm.c @@ -69,6 +69,10 @@ static void led_pwm_set(struct led_classdev *led_cdev, duty *= brightness; do_div(duty, max); + + if (led_dat->active_low) + duty = led_dat->period - duty; + led_dat->duty = duty; if (led_dat->can_sleep) @@ -92,55 +96,78 @@ static void led_pwm_cleanup(struct led_pwm_priv *priv) } } -static int led_pwm_create_of(struct platform_device *pdev, - struct led_pwm_priv *priv) +static int led_pwm_add(struct device *dev, struct led_pwm_priv *priv, + struct led_pwm *led, struct device_node *child) { - struct device_node *child; + struct led_pwm_data *led_data = &priv->leds[priv->num_leds]; int ret; - for_each_child_of_node(pdev->dev.of_node, child) { - struct led_pwm_data *led_dat = &priv->leds[priv->num_leds]; + led_data->active_low = led->active_low; + led_data->cdev.name = led->name; + led_data->cdev.default_trigger = led->default_trigger; + led_data->cdev.brightness_set = led_pwm_set; + led_data->cdev.brightness = LED_OFF; + led_data->cdev.max_brightness = led->max_brightness; + led_data->cdev.flags = LED_CORE_SUSPENDRESUME; - led_dat->cdev.name = of_get_property(child, "label", - NULL) ? : child->name; + if (child) + led_data->pwm = devm_of_pwm_get(dev, child, NULL); + else + led_data->pwm = devm_pwm_get(dev, led->name); + if (IS_ERR(led_data->pwm)) { + ret = PTR_ERR(led_data->pwm); + dev_err(dev, "unable to request PWM for %s: %d\n", + led->name, ret); + return ret; + } - led_dat->pwm = devm_of_pwm_get(&pdev->dev, child, NULL); - if (IS_ERR(led_dat->pwm)) { - dev_err(&pdev->dev, "unable to request PWM for %s\n", - led_dat->cdev.name); - ret = PTR_ERR(led_dat->pwm); - goto err; - } - /* Get the period from PWM core when n*/ - led_dat->period = pwm_get_period(led_dat->pwm); + if (child) + led_data->period = pwm_get_period(led_data->pwm); - led_dat->cdev.default_trigger = of_get_property(child, - "linux,default-trigger", NULL); - of_property_read_u32(child, "max-brightness", - &led_dat->cdev.max_brightness); + led_data->can_sleep = pwm_can_sleep(led_data->pwm); + if (led_data->can_sleep) + INIT_WORK(&led_data->work, led_pwm_work); - led_dat->cdev.brightness_set = led_pwm_set; - led_dat->cdev.brightness = LED_OFF; - led_dat->cdev.flags |= LED_CORE_SUSPENDRESUME; + led_data->period = pwm_get_period(led_data->pwm); + if (!led_data->period && (led->pwm_period_ns > 0)) + led_data->period = led->pwm_period_ns; - led_dat->can_sleep = pwm_can_sleep(led_dat->pwm); - if (led_dat->can_sleep) - INIT_WORK(&led_dat->work, led_pwm_work); + ret = led_classdev_register(dev, &led_data->cdev); + if (ret == 0) { + priv->num_leds++; + } else { + dev_err(dev, "failed to register PWM led for %s: %d\n", + led->name, ret); + } + + return ret; +} - ret = led_classdev_register(&pdev->dev, &led_dat->cdev); - if (ret < 0) { - dev_err(&pdev->dev, "failed to register for %s\n", - led_dat->cdev.name); +static int led_pwm_create_of(struct device *dev, struct led_pwm_priv *priv) +{ + struct device_node *child; + struct led_pwm led; + int ret = 0; + + memset(&led, 0, sizeof(led)); + + for_each_child_of_node(dev->of_node, child) { + led.name = of_get_property(child, "label", NULL) ? : + child->name; + + led.default_trigger = of_get_property(child, + "linux,default-trigger", NULL); + led.active_low = of_property_read_bool(child, "active-low"); + of_property_read_u32(child, "max-brightness", + &led.max_brightness); + + ret = led_pwm_add(dev, priv, &led, child); + if (ret) { of_node_put(child); - goto err; + break; } - priv->num_leds++; } - return 0; -err: - led_pwm_cleanup(priv); - return ret; } @@ -166,54 +193,23 @@ static int led_pwm_probe(struct platform_device *pdev) if (pdata) { for (i = 0; i < count; i++) { - struct led_pwm *cur_led = &pdata->leds[i]; - struct led_pwm_data *led_dat = &priv->leds[i]; - - led_dat->pwm = devm_pwm_get(&pdev->dev, cur_led->name); - if (IS_ERR(led_dat->pwm)) { - ret = PTR_ERR(led_dat->pwm); - dev_err(&pdev->dev, - "unable to request PWM for %s\n", - cur_led->name); - goto err; - } - - 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->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->can_sleep = pwm_can_sleep(led_dat->pwm); - if (led_dat->can_sleep) - INIT_WORK(&led_dat->work, led_pwm_work); - - led_dat->period = pwm_get_period(led_dat->pwm); - if (!led_dat->period && (cur_led->pwm_period_ns > 0)) - led_dat->period = cur_led->pwm_period_ns; - - ret = led_classdev_register(&pdev->dev, &led_dat->cdev); - if (ret < 0) - goto err; + ret = led_pwm_add(&pdev->dev, priv, &pdata->leds[i], + NULL); + if (ret) + break; } - priv->num_leds = count; } else { - ret = led_pwm_create_of(pdev, priv); - if (ret) - return ret; + ret = led_pwm_create_of(&pdev->dev, priv); + } + + if (ret) { + led_pwm_cleanup(priv); + return ret; } platform_set_drvdata(pdev, priv); return 0; - -err: - priv->num_leds = i; - led_pwm_cleanup(priv); - - return ret; } static int led_pwm_remove(struct platform_device *pdev) |