aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/video/backlight/pwm-backlight.txt5
-rw-r--r--drivers/video/backlight/pwm_bl.c57
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:
14Optional properties: 14Optional 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
20Example: 23Example:
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
351err_gpio:
352 if (gpio_is_valid(pb->enable_gpio))
353 gpio_free(pb->enable_gpio);
311err_alloc: 354err_alloc:
312 if (data->exit) 355 if (data->exit)
313 data->exit(&pdev->dev); 356 data->exit(&pdev->dev);