diff options
-rw-r--r-- | Documentation/devicetree/bindings/video/backlight/pwm-backlight.txt | 5 | ||||
-rw-r--r-- | drivers/video/backlight/pwm_bl.c | 57 |
2 files changed, 55 insertions, 7 deletions
diff --git a/Documentation/devicetree/bindings/video/backlight/pwm-backlight.txt b/Documentation/devicetree/bindings/video/backlight/pwm-backlight.txt index 1e4fc727f3b1..72810cc2dbc1 100644 --- a/Documentation/devicetree/bindings/video/backlight/pwm-backlight.txt +++ b/Documentation/devicetree/bindings/video/backlight/pwm-backlight.txt | |||
@@ -14,8 +14,11 @@ Required properties: | |||
14 | Optional properties: | 14 | Optional properties: |
15 | - pwm-names: a list of names for the PWM devices specified in the | 15 | - pwm-names: a list of names for the PWM devices specified in the |
16 | "pwms" property (see PWM binding[0]) | 16 | "pwms" property (see PWM binding[0]) |
17 | - enable-gpios: contains a single GPIO specifier for the GPIO which enables | ||
18 | and disables the backlight (see GPIO binding[1]) | ||
17 | 19 | ||
18 | [0]: Documentation/devicetree/bindings/pwm/pwm.txt | 20 | [0]: Documentation/devicetree/bindings/pwm/pwm.txt |
21 | [1]: Documentation/devicetree/bindings/gpio/gpio.txt | ||
19 | 22 | ||
20 | Example: | 23 | Example: |
21 | 24 | ||
@@ -25,4 +28,6 @@ Example: | |||
25 | 28 | ||
26 | brightness-levels = <0 4 8 16 32 64 128 255>; | 29 | brightness-levels = <0 4 8 16 32 64 128 255>; |
27 | default-brightness-level = <6>; | 30 | default-brightness-level = <6>; |
31 | |||
32 | enable-gpios = <&gpio 58 0>; | ||
28 | }; | 33 | }; |
diff --git a/drivers/video/backlight/pwm_bl.c b/drivers/video/backlight/pwm_bl.c index 51a802fff50d..18b885497289 100644 --- a/drivers/video/backlight/pwm_bl.c +++ b/drivers/video/backlight/pwm_bl.c | |||
@@ -10,6 +10,8 @@ | |||
10 | * published by the Free Software Foundation. | 10 | * published by the Free Software Foundation. |
11 | */ | 11 | */ |
12 | 12 | ||
13 | #include <linux/gpio.h> | ||
14 | #include <linux/of_gpio.h> | ||
13 | #include <linux/module.h> | 15 | #include <linux/module.h> |
14 | #include <linux/kernel.h> | 16 | #include <linux/kernel.h> |
15 | #include <linux/init.h> | 17 | #include <linux/init.h> |
@@ -28,6 +30,8 @@ struct pwm_bl_data { | |||
28 | unsigned int lth_brightness; | 30 | unsigned int lth_brightness; |
29 | unsigned int *levels; | 31 | unsigned int *levels; |
30 | bool enabled; | 32 | bool enabled; |
33 | int enable_gpio; | ||
34 | unsigned long enable_gpio_flags; | ||
31 | int (*notify)(struct device *, | 35 | int (*notify)(struct device *, |
32 | int brightness); | 36 | int brightness); |
33 | void (*notify_after)(struct device *, | 37 | void (*notify_after)(struct device *, |
@@ -56,6 +60,14 @@ static void pwm_backlight_power_on(struct pwm_bl_data *pb, int brightness, | |||
56 | pb->lth_brightness; | 60 | pb->lth_brightness; |
57 | 61 | ||
58 | pwm_config(pb->pwm, duty_cycle, pb->period); | 62 | pwm_config(pb->pwm, duty_cycle, pb->period); |
63 | |||
64 | if (gpio_is_valid(pb->enable_gpio)) { | ||
65 | if (pb->enable_gpio_flags & PWM_BACKLIGHT_GPIO_ACTIVE_LOW) | ||
66 | gpio_set_value(pb->enable_gpio, 0); | ||
67 | else | ||
68 | gpio_set_value(pb->enable_gpio, 1); | ||
69 | } | ||
70 | |||
59 | pwm_enable(pb->pwm); | 71 | pwm_enable(pb->pwm); |
60 | pb->enabled = true; | 72 | pb->enabled = true; |
61 | } | 73 | } |
@@ -68,6 +80,13 @@ static void pwm_backlight_power_off(struct pwm_bl_data *pb) | |||
68 | pwm_config(pb->pwm, 0, pb->period); | 80 | pwm_config(pb->pwm, 0, pb->period); |
69 | pwm_disable(pb->pwm); | 81 | pwm_disable(pb->pwm); |
70 | 82 | ||
83 | if (gpio_is_valid(pb->enable_gpio)) { | ||
84 | if (pb->enable_gpio_flags & PWM_BACKLIGHT_GPIO_ACTIVE_LOW) | ||
85 | gpio_set_value(pb->enable_gpio, 1); | ||
86 | else | ||
87 | gpio_set_value(pb->enable_gpio, 0); | ||
88 | } | ||
89 | |||
71 | pb->enabled = false; | 90 | pb->enabled = false; |
72 | } | 91 | } |
73 | 92 | ||
@@ -120,6 +139,7 @@ static int pwm_backlight_parse_dt(struct device *dev, | |||
120 | struct platform_pwm_backlight_data *data) | 139 | struct platform_pwm_backlight_data *data) |
121 | { | 140 | { |
122 | struct device_node *node = dev->of_node; | 141 | struct device_node *node = dev->of_node; |
142 | enum of_gpio_flags flags; | ||
123 | struct property *prop; | 143 | struct property *prop; |
124 | int length; | 144 | int length; |
125 | u32 value; | 145 | u32 value; |
@@ -160,11 +180,13 @@ static int pwm_backlight_parse_dt(struct device *dev, | |||
160 | data->max_brightness--; | 180 | data->max_brightness--; |
161 | } | 181 | } |
162 | 182 | ||
163 | /* | 183 | data->enable_gpio = of_get_named_gpio_flags(node, "enable-gpios", 0, |
164 | * TODO: Most users of this driver use a number of GPIOs to control | 184 | &flags); |
165 | * backlight power. Support for specifying these needs to be | 185 | if (data->enable_gpio == -EPROBE_DEFER) |
166 | * added. | 186 | return -EPROBE_DEFER; |
167 | */ | 187 | |
188 | if (gpio_is_valid(data->enable_gpio) && (flags & OF_GPIO_ACTIVE_LOW)) | ||
189 | data->enable_gpio_flags |= PWM_BACKLIGHT_GPIO_ACTIVE_LOW; | ||
168 | 190 | ||
169 | return 0; | 191 | return 0; |
170 | } | 192 | } |
@@ -252,6 +274,8 @@ static int pwm_backlight_probe(struct platform_device *pdev) | |||
252 | } else | 274 | } else |
253 | max = data->max_brightness; | 275 | max = data->max_brightness; |
254 | 276 | ||
277 | pb->enable_gpio = data->enable_gpio; | ||
278 | pb->enable_gpio_flags = data->enable_gpio_flags; | ||
255 | pb->notify = data->notify; | 279 | pb->notify = data->notify; |
256 | pb->notify_after = data->notify_after; | 280 | pb->notify_after = data->notify_after; |
257 | pb->check_fb = np ? pwm_backlight_check_fb_dt : data->check_fb; | 281 | pb->check_fb = np ? pwm_backlight_check_fb_dt : data->check_fb; |
@@ -259,6 +283,22 @@ static int pwm_backlight_probe(struct platform_device *pdev) | |||
259 | pb->dev = &pdev->dev; | 283 | pb->dev = &pdev->dev; |
260 | pb->enabled = false; | 284 | pb->enabled = false; |
261 | 285 | ||
286 | if (gpio_is_valid(pb->enable_gpio)) { | ||
287 | unsigned long flags; | ||
288 | |||
289 | if (pb->enable_gpio_flags & PWM_BACKLIGHT_GPIO_ACTIVE_LOW) | ||
290 | flags = GPIOF_OUT_INIT_HIGH; | ||
291 | else | ||
292 | flags = GPIOF_OUT_INIT_LOW; | ||
293 | |||
294 | ret = gpio_request_one(pb->enable_gpio, flags, "enable"); | ||
295 | if (ret < 0) { | ||
296 | dev_err(&pdev->dev, "failed to request GPIO#%d: %d\n", | ||
297 | pb->enable_gpio, ret); | ||
298 | goto err_alloc; | ||
299 | } | ||
300 | } | ||
301 | |||
262 | pb->pwm = devm_pwm_get(&pdev->dev, NULL); | 302 | pb->pwm = devm_pwm_get(&pdev->dev, NULL); |
263 | if (IS_ERR(pb->pwm)) { | 303 | if (IS_ERR(pb->pwm)) { |
264 | dev_err(&pdev->dev, "unable to request PWM, trying legacy API\n"); | 304 | dev_err(&pdev->dev, "unable to request PWM, trying legacy API\n"); |
@@ -267,7 +307,7 @@ static int pwm_backlight_probe(struct platform_device *pdev) | |||
267 | if (IS_ERR(pb->pwm)) { | 307 | if (IS_ERR(pb->pwm)) { |
268 | dev_err(&pdev->dev, "unable to request legacy PWM\n"); | 308 | dev_err(&pdev->dev, "unable to request legacy PWM\n"); |
269 | ret = PTR_ERR(pb->pwm); | 309 | ret = PTR_ERR(pb->pwm); |
270 | goto err_alloc; | 310 | goto err_gpio; |
271 | } | 311 | } |
272 | } | 312 | } |
273 | 313 | ||
@@ -292,7 +332,7 @@ static int pwm_backlight_probe(struct platform_device *pdev) | |||
292 | if (IS_ERR(bl)) { | 332 | if (IS_ERR(bl)) { |
293 | dev_err(&pdev->dev, "failed to register backlight\n"); | 333 | dev_err(&pdev->dev, "failed to register backlight\n"); |
294 | ret = PTR_ERR(bl); | 334 | ret = PTR_ERR(bl); |
295 | goto err_alloc; | 335 | goto err_gpio; |
296 | } | 336 | } |
297 | 337 | ||
298 | if (data->dft_brightness > data->max_brightness) { | 338 | if (data->dft_brightness > data->max_brightness) { |
@@ -308,6 +348,9 @@ static int pwm_backlight_probe(struct platform_device *pdev) | |||
308 | platform_set_drvdata(pdev, bl); | 348 | platform_set_drvdata(pdev, bl); |
309 | return 0; | 349 | return 0; |
310 | 350 | ||
351 | err_gpio: | ||
352 | if (gpio_is_valid(pb->enable_gpio)) | ||
353 | gpio_free(pb->enable_gpio); | ||
311 | err_alloc: | 354 | err_alloc: |
312 | if (data->exit) | 355 | if (data->exit) |
313 | data->exit(&pdev->dev); | 356 | data->exit(&pdev->dev); |