aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/leds/backlight/pwm-backlight.txt34
-rw-r--r--drivers/video/backlight/adp8860_bl.c1
-rw-r--r--drivers/video/backlight/pwm_bl.c232
-rw-r--r--include/linux/backlight.h1
4 files changed, 247 insertions, 21 deletions
diff --git a/Documentation/devicetree/bindings/leds/backlight/pwm-backlight.txt b/Documentation/devicetree/bindings/leds/backlight/pwm-backlight.txt
index 310810906613..64fa2fbd98c9 100644
--- a/Documentation/devicetree/bindings/leds/backlight/pwm-backlight.txt
+++ b/Documentation/devicetree/bindings/leds/backlight/pwm-backlight.txt
@@ -3,13 +3,6 @@ pwm-backlight bindings
3Required properties: 3Required properties:
4 - compatible: "pwm-backlight" 4 - compatible: "pwm-backlight"
5 - pwms: OF device-tree PWM specification (see PWM binding[0]) 5 - pwms: OF device-tree PWM specification (see PWM binding[0])
6 - brightness-levels: Array of distinct brightness levels. Typically these
7 are in the range from 0 to 255, but any range starting at 0 will do.
8 The actual brightness level (PWM duty cycle) will be interpolated
9 from these values. 0 means a 0% duty cycle (darkest/off), while the
10 last value in the array represents a 100% duty cycle (brightest).
11 - default-brightness-level: the default brightness level (index into the
12 array defined by the "brightness-levels" property)
13 - power-supply: regulator for supply voltage 6 - power-supply: regulator for supply voltage
14 7
15Optional properties: 8Optional properties:
@@ -21,6 +14,19 @@ Optional properties:
21 and enabling the backlight using GPIO. 14 and enabling the backlight using GPIO.
22 - pwm-off-delay-ms: Delay in ms between disabling the backlight using GPIO 15 - pwm-off-delay-ms: Delay in ms between disabling the backlight using GPIO
23 and setting PWM value to 0. 16 and setting PWM value to 0.
17 - brightness-levels: Array of distinct brightness levels. Typically these
18 are in the range from 0 to 255, but any range starting at
19 0 will do. The actual brightness level (PWM duty cycle)
20 will be interpolated from these values. 0 means a 0% duty
21 cycle (darkest/off), while the last value in the array
22 represents a 100% duty cycle (brightest).
23 - default-brightness-level: The default brightness level (index into the
24 array defined by the "brightness-levels" property).
25 - num-interpolated-steps: Number of interpolated steps between each value
26 of brightness-levels table. This way a high
27 resolution pwm duty cycle can be used without
28 having to list out every possible value in the
29 brightness-level array.
24 30
25[0]: Documentation/devicetree/bindings/pwm/pwm.txt 31[0]: Documentation/devicetree/bindings/pwm/pwm.txt
26[1]: Documentation/devicetree/bindings/gpio/gpio.txt 32[1]: Documentation/devicetree/bindings/gpio/gpio.txt
@@ -39,3 +45,17 @@ Example:
39 post-pwm-on-delay-ms = <10>; 45 post-pwm-on-delay-ms = <10>;
40 pwm-off-delay-ms = <10>; 46 pwm-off-delay-ms = <10>;
41 }; 47 };
48
49Example using num-interpolation-steps:
50
51 backlight {
52 compatible = "pwm-backlight";
53 pwms = <&pwm 0 5000000>;
54
55 brightness-levels = <0 2048 4096 8192 16384 65535>;
56 num-interpolated-steps = <2048>;
57 default-brightness-level = <4096>;
58
59 power-supply = <&vdd_bl_reg>;
60 enable-gpios = <&gpio 58 0>;
61 };
diff --git a/drivers/video/backlight/adp8860_bl.c b/drivers/video/backlight/adp8860_bl.c
index 16119bde9750..f1dc41cf19e3 100644
--- a/drivers/video/backlight/adp8860_bl.c
+++ b/drivers/video/backlight/adp8860_bl.c
@@ -690,6 +690,7 @@ static int adp8860_probe(struct i2c_client *client,
690 switch (ADP8860_MANID(reg_val)) { 690 switch (ADP8860_MANID(reg_val)) {
691 case ADP8863_MANUFID: 691 case ADP8863_MANUFID:
692 data->gdwn_dis = !!pdata->gdwn_dis; 692 data->gdwn_dis = !!pdata->gdwn_dis;
693 /* fall through */
693 case ADP8860_MANUFID: 694 case ADP8860_MANUFID:
694 data->en_ambl_sens = !!pdata->en_ambl_sens; 695 data->en_ambl_sens = !!pdata->en_ambl_sens;
695 break; 696 break;
diff --git a/drivers/video/backlight/pwm_bl.c b/drivers/video/backlight/pwm_bl.c
index 44ac5bde4e9d..bdfcc0a71db1 100644
--- a/drivers/video/backlight/pwm_bl.c
+++ b/drivers/video/backlight/pwm_bl.c
@@ -143,11 +143,116 @@ static const struct backlight_ops pwm_backlight_ops = {
143}; 143};
144 144
145#ifdef CONFIG_OF 145#ifdef CONFIG_OF
146#define PWM_LUMINANCE_SCALE 10000 /* luminance scale */
147
148/* An integer based power function */
149static u64 int_pow(u64 base, int exp)
150{
151 u64 result = 1;
152
153 while (exp) {
154 if (exp & 1)
155 result *= base;
156 exp >>= 1;
157 base *= base;
158 }
159
160 return result;
161}
162
163/*
164 * CIE lightness to PWM conversion.
165 *
166 * The CIE 1931 lightness formula is what actually describes how we perceive
167 * light:
168 * Y = (L* / 902.3) if L* ≤ 0.08856
169 * Y = ((L* + 16) / 116)^3 if L* > 0.08856
170 *
171 * Where Y is the luminance, the amount of light coming out of the screen, and
172 * is a number between 0.0 and 1.0; and L* is the lightness, how bright a human
173 * perceives the screen to be, and is a number between 0 and 100.
174 *
175 * The following function does the fixed point maths needed to implement the
176 * above formula.
177 */
178static u64 cie1931(unsigned int lightness, unsigned int scale)
179{
180 u64 retval;
181
182 lightness *= 100;
183 if (lightness <= (8 * scale)) {
184 retval = DIV_ROUND_CLOSEST_ULL(lightness * 10, 9023);
185 } else {
186 retval = int_pow((lightness + (16 * scale)) / 116, 3);
187 retval = DIV_ROUND_CLOSEST_ULL(retval, (scale * scale));
188 }
189
190 return retval;
191}
192
193/*
194 * Create a default correction table for PWM values to create linear brightness
195 * for LED based backlights using the CIE1931 algorithm.
196 */
197static
198int pwm_backlight_brightness_default(struct device *dev,
199 struct platform_pwm_backlight_data *data,
200 unsigned int period)
201{
202 unsigned int counter = 0;
203 unsigned int i, n;
204 u64 retval;
205
206 /*
207 * Count the number of bits needed to represent the period number. The
208 * number of bits is used to calculate the number of levels used for the
209 * brightness-levels table, the purpose of this calculation is have a
210 * pre-computed table with enough levels to get linear brightness
211 * perception. The period is divided by the number of bits so for a
212 * 8-bit PWM we have 255 / 8 = 32 brightness levels or for a 16-bit PWM
213 * we have 65535 / 16 = 4096 brightness levels.
214 *
215 * Note that this method is based on empirical testing on different
216 * devices with PWM of 8 and 16 bits of resolution.
217 */
218 n = period;
219 while (n) {
220 counter += n % 2;
221 n >>= 1;
222 }
223
224 data->max_brightness = DIV_ROUND_UP(period, counter);
225 data->levels = devm_kcalloc(dev, data->max_brightness,
226 sizeof(*data->levels), GFP_KERNEL);
227 if (!data->levels)
228 return -ENOMEM;
229
230 /* Fill the table using the cie1931 algorithm */
231 for (i = 0; i < data->max_brightness; i++) {
232 retval = cie1931((i * PWM_LUMINANCE_SCALE) /
233 data->max_brightness, PWM_LUMINANCE_SCALE) *
234 period;
235 retval = DIV_ROUND_CLOSEST_ULL(retval, PWM_LUMINANCE_SCALE);
236 if (retval > UINT_MAX)
237 return -EINVAL;
238 data->levels[i] = (unsigned int)retval;
239 }
240
241 data->dft_brightness = data->max_brightness / 2;
242 data->max_brightness--;
243
244 return 0;
245}
246
146static int pwm_backlight_parse_dt(struct device *dev, 247static int pwm_backlight_parse_dt(struct device *dev,
147 struct platform_pwm_backlight_data *data) 248 struct platform_pwm_backlight_data *data)
148{ 249{
149 struct device_node *node = dev->of_node; 250 struct device_node *node = dev->of_node;
251 unsigned int num_levels = 0;
252 unsigned int levels_count;
253 unsigned int num_steps = 0;
150 struct property *prop; 254 struct property *prop;
255 unsigned int *table;
151 int length; 256 int length;
152 u32 value; 257 u32 value;
153 int ret; 258 int ret;
@@ -157,16 +262,20 @@ static int pwm_backlight_parse_dt(struct device *dev,
157 262
158 memset(data, 0, sizeof(*data)); 263 memset(data, 0, sizeof(*data));
159 264
160 /* determine the number of brightness levels */ 265 /*
266 * Determine the number of brightness levels, if this property is not
267 * set a default table of brightness levels will be used.
268 */
161 prop = of_find_property(node, "brightness-levels", &length); 269 prop = of_find_property(node, "brightness-levels", &length);
162 if (!prop) 270 if (!prop)
163 return -EINVAL; 271 return 0;
164 272
165 data->max_brightness = length / sizeof(u32); 273 data->max_brightness = length / sizeof(u32);
166 274
167 /* read brightness levels from DT property */ 275 /* read brightness levels from DT property */
168 if (data->max_brightness > 0) { 276 if (data->max_brightness > 0) {
169 size_t size = sizeof(*data->levels) * data->max_brightness; 277 size_t size = sizeof(*data->levels) * data->max_brightness;
278 unsigned int i, j, n = 0;
170 279
171 data->levels = devm_kzalloc(dev, size, GFP_KERNEL); 280 data->levels = devm_kzalloc(dev, size, GFP_KERNEL);
172 if (!data->levels) 281 if (!data->levels)
@@ -184,6 +293,84 @@ static int pwm_backlight_parse_dt(struct device *dev,
184 return ret; 293 return ret;
185 294
186 data->dft_brightness = value; 295 data->dft_brightness = value;
296
297 /*
298 * This property is optional, if is set enables linear
299 * interpolation between each of the values of brightness levels
300 * and creates a new pre-computed table.
301 */
302 of_property_read_u32(node, "num-interpolated-steps",
303 &num_steps);
304
305 /*
306 * Make sure that there is at least two entries in the
307 * brightness-levels table, otherwise we can't interpolate
308 * between two points.
309 */
310 if (num_steps) {
311 if (data->max_brightness < 2) {
312 dev_err(dev, "can't interpolate\n");
313 return -EINVAL;
314 }
315
316 /*
317 * Recalculate the number of brightness levels, now
318 * taking in consideration the number of interpolated
319 * steps between two levels.
320 */
321 for (i = 0; i < data->max_brightness - 1; i++) {
322 if ((data->levels[i + 1] - data->levels[i]) /
323 num_steps)
324 num_levels += num_steps;
325 else
326 num_levels++;
327 }
328 num_levels++;
329 dev_dbg(dev, "new number of brightness levels: %d\n",
330 num_levels);
331
332 /*
333 * Create a new table of brightness levels with all the
334 * interpolated steps.
335 */
336 size = sizeof(*table) * num_levels;
337 table = devm_kzalloc(dev, size, GFP_KERNEL);
338 if (!table)
339 return -ENOMEM;
340
341 /* Fill the interpolated table. */
342 levels_count = 0;
343 for (i = 0; i < data->max_brightness - 1; i++) {
344 value = data->levels[i];
345 n = (data->levels[i + 1] - value) / num_steps;
346 if (n > 0) {
347 for (j = 0; j < num_steps; j++) {
348 table[levels_count] = value;
349 value += n;
350 levels_count++;
351 }
352 } else {
353 table[levels_count] = data->levels[i];
354 levels_count++;
355 }
356 }
357 table[levels_count] = data->levels[i];
358
359 /*
360 * As we use interpolation lets remove current
361 * brightness levels table and replace for the
362 * new interpolated table.
363 */
364 devm_kfree(dev, data->levels);
365 data->levels = table;
366
367 /*
368 * Reassign max_brightness value to the new total number
369 * of brightness levels.
370 */
371 data->max_brightness = num_levels;
372 }
373
187 data->max_brightness--; 374 data->max_brightness--;
188 } 375 }
189 376
@@ -211,6 +398,14 @@ static int pwm_backlight_parse_dt(struct device *dev,
211{ 398{
212 return -ENODEV; 399 return -ENODEV;
213} 400}
401
402static
403int pwm_backlight_brightness_default(struct device *dev,
404 struct platform_pwm_backlight_data *data,
405 unsigned int period)
406{
407 return -ENODEV;
408}
214#endif 409#endif
215 410
216static int pwm_backlight_initial_power_state(const struct pwm_bl_data *pb) 411static int pwm_backlight_initial_power_state(const struct pwm_bl_data *pb)
@@ -251,7 +446,9 @@ static int pwm_backlight_probe(struct platform_device *pdev)
251 struct backlight_device *bl; 446 struct backlight_device *bl;
252 struct device_node *node = pdev->dev.of_node; 447 struct device_node *node = pdev->dev.of_node;
253 struct pwm_bl_data *pb; 448 struct pwm_bl_data *pb;
449 struct pwm_state state;
254 struct pwm_args pargs; 450 struct pwm_args pargs;
451 unsigned int i;
255 int ret; 452 int ret;
256 453
257 if (!data) { 454 if (!data) {
@@ -276,17 +473,6 @@ static int pwm_backlight_probe(struct platform_device *pdev)
276 goto err_alloc; 473 goto err_alloc;
277 } 474 }
278 475
279 if (data->levels) {
280 unsigned int i;
281
282 for (i = 0; i <= data->max_brightness; i++)
283 if (data->levels[i] > pb->scale)
284 pb->scale = data->levels[i];
285
286 pb->levels = data->levels;
287 } else
288 pb->scale = data->max_brightness;
289
290 pb->notify = data->notify; 476 pb->notify = data->notify;
291 pb->notify_after = data->notify_after; 477 pb->notify_after = data->notify_after;
292 pb->check_fb = data->check_fb; 478 pb->check_fb = data->check_fb;
@@ -353,6 +539,26 @@ static int pwm_backlight_probe(struct platform_device *pdev)
353 539
354 dev_dbg(&pdev->dev, "got pwm for backlight\n"); 540 dev_dbg(&pdev->dev, "got pwm for backlight\n");
355 541
542 if (!data->levels) {
543 /* Get the PWM period (in nanoseconds) */
544 pwm_get_state(pb->pwm, &state);
545
546 ret = pwm_backlight_brightness_default(&pdev->dev, data,
547 state.period);
548 if (ret < 0) {
549 dev_err(&pdev->dev,
550 "failed to setup default brightness table\n");
551 goto err_alloc;
552 }
553 }
554
555 for (i = 0; i <= data->max_brightness; i++) {
556 if (data->levels[i] > pb->scale)
557 pb->scale = data->levels[i];
558
559 pb->levels = data->levels;
560 }
561
356 /* 562 /*
357 * FIXME: pwm_apply_args() should be removed when switching to 563 * FIXME: pwm_apply_args() should be removed when switching to
358 * the atomic PWM API. 564 * the atomic PWM API.
diff --git a/include/linux/backlight.h b/include/linux/backlight.h
index 7fbf0539e14a..0b5897446dca 100644
--- a/include/linux/backlight.h
+++ b/include/linux/backlight.h
@@ -79,7 +79,6 @@ struct backlight_properties {
79 /* Backlight type */ 79 /* Backlight type */
80 enum backlight_type type; 80 enum backlight_type type;
81 /* Flags used to signal drivers of state changes */ 81 /* Flags used to signal drivers of state changes */
82 /* Upper 4 bits are reserved for driver internal use */
83 unsigned int state; 82 unsigned int state;
84 83
85#define BL_CORE_SUSPENDED (1 << 0) /* backlight is suspended */ 84#define BL_CORE_SUSPENDED (1 << 0) /* backlight is suspended */