diff options
-rw-r--r-- | drivers/video/backlight/pwm_bl.c | 39 | ||||
-rw-r--r-- | include/linux/pwm_backlight.h | 3 |
2 files changed, 35 insertions, 7 deletions
diff --git a/drivers/video/backlight/pwm_bl.c b/drivers/video/backlight/pwm_bl.c index 9637f5e08cb6..8346dfc01cf6 100644 --- a/drivers/video/backlight/pwm_bl.c +++ b/drivers/video/backlight/pwm_bl.c | |||
@@ -23,6 +23,7 @@ | |||
23 | struct pwm_bl_data { | 23 | struct pwm_bl_data { |
24 | struct pwm_device *pwm; | 24 | struct pwm_device *pwm; |
25 | unsigned int period; | 25 | unsigned int period; |
26 | int (*notify)(int brightness); | ||
26 | }; | 27 | }; |
27 | 28 | ||
28 | static int pwm_backlight_update_status(struct backlight_device *bl) | 29 | static int pwm_backlight_update_status(struct backlight_device *bl) |
@@ -37,6 +38,9 @@ static int pwm_backlight_update_status(struct backlight_device *bl) | |||
37 | if (bl->props.fb_blank != FB_BLANK_UNBLANK) | 38 | if (bl->props.fb_blank != FB_BLANK_UNBLANK) |
38 | brightness = 0; | 39 | brightness = 0; |
39 | 40 | ||
41 | if (pb->notify) | ||
42 | brightness = pb->notify(brightness); | ||
43 | |||
40 | if (brightness == 0) { | 44 | if (brightness == 0) { |
41 | pwm_config(pb->pwm, 0, pb->period); | 45 | pwm_config(pb->pwm, 0, pb->period); |
42 | pwm_disable(pb->pwm); | 46 | pwm_disable(pb->pwm); |
@@ -62,30 +66,39 @@ static int pwm_backlight_probe(struct platform_device *pdev) | |||
62 | struct platform_pwm_backlight_data *data = pdev->dev.platform_data; | 66 | struct platform_pwm_backlight_data *data = pdev->dev.platform_data; |
63 | struct backlight_device *bl; | 67 | struct backlight_device *bl; |
64 | struct pwm_bl_data *pb; | 68 | struct pwm_bl_data *pb; |
69 | int ret; | ||
65 | 70 | ||
66 | if (!data) | 71 | if (!data) |
67 | return -EINVAL; | 72 | return -EINVAL; |
68 | 73 | ||
74 | if (data->init) { | ||
75 | ret = data->init(&pdev->dev); | ||
76 | if (ret < 0) | ||
77 | return ret; | ||
78 | } | ||
79 | |||
69 | pb = kzalloc(sizeof(*pb), GFP_KERNEL); | 80 | pb = kzalloc(sizeof(*pb), GFP_KERNEL); |
70 | if (!pb) | 81 | if (!pb) { |
71 | return -ENOMEM; | 82 | ret = -ENOMEM; |
83 | goto err_alloc; | ||
84 | } | ||
72 | 85 | ||
73 | pb->period = data->pwm_period_ns; | 86 | pb->period = data->pwm_period_ns; |
87 | pb->notify = data->notify; | ||
74 | 88 | ||
75 | pb->pwm = pwm_request(data->pwm_id, "backlight"); | 89 | pb->pwm = pwm_request(data->pwm_id, "backlight"); |
76 | if (pb->pwm == NULL) { | 90 | if (pb->pwm == NULL) { |
77 | dev_err(&pdev->dev, "unable to request PWM for backlight\n"); | 91 | dev_err(&pdev->dev, "unable to request PWM for backlight\n"); |
78 | kfree(pb); | 92 | ret = -EBUSY; |
79 | return -EBUSY; | 93 | goto err_pwm; |
80 | } | 94 | } |
81 | 95 | ||
82 | bl = backlight_device_register(pdev->name, &pdev->dev, | 96 | bl = backlight_device_register(pdev->name, &pdev->dev, |
83 | pb, &pwm_backlight_ops); | 97 | pb, &pwm_backlight_ops); |
84 | if (IS_ERR(bl)) { | 98 | if (IS_ERR(bl)) { |
85 | dev_err(&pdev->dev, "failed to register backlight\n"); | 99 | dev_err(&pdev->dev, "failed to register backlight\n"); |
86 | pwm_free(pb->pwm); | 100 | ret = PTR_ERR(bl); |
87 | kfree(pb); | 101 | goto err_bl; |
88 | return PTR_ERR(bl); | ||
89 | } | 102 | } |
90 | 103 | ||
91 | bl->props.max_brightness = data->max_brightness; | 104 | bl->props.max_brightness = data->max_brightness; |
@@ -94,10 +107,20 @@ static int pwm_backlight_probe(struct platform_device *pdev) | |||
94 | 107 | ||
95 | platform_set_drvdata(pdev, bl); | 108 | platform_set_drvdata(pdev, bl); |
96 | return 0; | 109 | return 0; |
110 | |||
111 | err_bl: | ||
112 | pwm_free(pb->pwm); | ||
113 | err_pwm: | ||
114 | kfree(pb); | ||
115 | err_alloc: | ||
116 | if (data->exit) | ||
117 | data->exit(&pdev->dev); | ||
118 | return ret; | ||
97 | } | 119 | } |
98 | 120 | ||
99 | static int pwm_backlight_remove(struct platform_device *pdev) | 121 | static int pwm_backlight_remove(struct platform_device *pdev) |
100 | { | 122 | { |
123 | struct platform_pwm_backlight_data *data = pdev->dev.platform_data; | ||
101 | struct backlight_device *bl = platform_get_drvdata(pdev); | 124 | struct backlight_device *bl = platform_get_drvdata(pdev); |
102 | struct pwm_bl_data *pb = dev_get_drvdata(&bl->dev); | 125 | struct pwm_bl_data *pb = dev_get_drvdata(&bl->dev); |
103 | 126 | ||
@@ -106,6 +129,8 @@ static int pwm_backlight_remove(struct platform_device *pdev) | |||
106 | pwm_disable(pb->pwm); | 129 | pwm_disable(pb->pwm); |
107 | pwm_free(pb->pwm); | 130 | pwm_free(pb->pwm); |
108 | kfree(pb); | 131 | kfree(pb); |
132 | if (data->exit) | ||
133 | data->exit(&pdev->dev); | ||
109 | return 0; | 134 | return 0; |
110 | } | 135 | } |
111 | 136 | ||
diff --git a/include/linux/pwm_backlight.h b/include/linux/pwm_backlight.h index aeeffedbe822..7a9754c96775 100644 --- a/include/linux/pwm_backlight.h +++ b/include/linux/pwm_backlight.h | |||
@@ -9,6 +9,9 @@ struct platform_pwm_backlight_data { | |||
9 | unsigned int max_brightness; | 9 | unsigned int max_brightness; |
10 | unsigned int dft_brightness; | 10 | unsigned int dft_brightness; |
11 | unsigned int pwm_period_ns; | 11 | unsigned int pwm_period_ns; |
12 | int (*init)(struct device *dev); | ||
13 | int (*notify)(int brightness); | ||
14 | void (*exit)(struct device *dev); | ||
12 | }; | 15 | }; |
13 | 16 | ||
14 | #endif | 17 | #endif |