hc
2024-12-19 9370bb92b2d16684ee45cf24e879c93c509162da
kernel/drivers/video/backlight/pwm_bl.c
....@@ -1,18 +1,12 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
2
- * linux/drivers/video/backlight/pwm_bl.c
3
- *
4
- * simple PWM based backlight control, board code has to setup
3
+ * Simple PWM based backlight control, board code has to setup
54 * 1) pin configuration so PWM waveforms can output
65 * 2) platform_data being correctly configured
7
- *
8
- * This program is free software; you can redistribute it and/or modify
9
- * it under the terms of the GNU General Public License version 2 as
10
- * published by the Free Software Foundation.
116 */
127
138 #include <linux/delay.h>
149 #include <linux/gpio/consumer.h>
15
-#include <linux/gpio.h>
1610 #include <linux/module.h>
1711 #include <linux/kernel.h>
1812 #include <linux/init.h>
....@@ -25,10 +19,14 @@
2519 #include <linux/regulator/consumer.h>
2620 #include <linux/slab.h>
2721
22
+static bool bl_quiescent;
23
+module_param_named(quiescent, bl_quiescent, bool, 0600);
24
+MODULE_PARM_DESC(quiescent,
25
+ "pwm bl quiescent when reboot quiescent [default=false]");
26
+
2827 struct pwm_bl_data {
2928 struct pwm_device *pwm;
3029 struct device *dev;
31
- unsigned int period;
3230 unsigned int lth_brightness;
3331 unsigned int *levels;
3432 bool enabled;
....@@ -46,10 +44,12 @@
4644 void (*exit)(struct device *);
4745 };
4846
49
-static void pwm_backlight_power_on(struct pwm_bl_data *pb, int brightness)
47
+static void pwm_backlight_power_on(struct pwm_bl_data *pb)
5048 {
49
+ struct pwm_state state;
5150 int err;
5251
52
+ pwm_get_state(pb->pwm, &state);
5353 if (pb->enabled)
5454 return;
5555
....@@ -57,7 +57,8 @@
5757 if (err < 0)
5858 dev_err(pb->dev, "failed to enable power supply\n");
5959
60
- pwm_enable(pb->pwm);
60
+ state.enabled = true;
61
+ pwm_apply_state(pb->pwm, &state);
6162
6263 if (pb->post_pwm_on_delay)
6364 msleep(pb->post_pwm_on_delay);
....@@ -70,7 +71,10 @@
7071
7172 static void pwm_backlight_power_off(struct pwm_bl_data *pb)
7273 {
73
- if (!pb->enabled)
74
+ struct pwm_state state;
75
+
76
+ pwm_get_state(pb->pwm, &state);
77
+ if (!pb->enabled && !state.enabled)
7478 return;
7579
7680 if (pb->enable_gpio)
....@@ -79,8 +83,9 @@
7983 if (pb->pwm_off_delay)
8084 msleep(pb->pwm_off_delay);
8185
82
- pwm_config(pb->pwm, 0, pb->period);
83
- pwm_disable(pb->pwm);
86
+ state.enabled = false;
87
+ state.duty_cycle = 0;
88
+ pwm_apply_state(pb->pwm, &state);
8489
8590 regulator_disable(pb->power_supply);
8691 pb->enabled = false;
....@@ -89,14 +94,17 @@
8994 static int compute_duty_cycle(struct pwm_bl_data *pb, int brightness)
9095 {
9196 unsigned int lth = pb->lth_brightness;
97
+ struct pwm_state state;
9298 u64 duty_cycle;
99
+
100
+ pwm_get_state(pb->pwm, &state);
93101
94102 if (pb->levels)
95103 duty_cycle = pb->levels[brightness];
96104 else
97105 duty_cycle = brightness;
98106
99
- duty_cycle *= pb->period - lth;
107
+ duty_cycle *= state.period - lth;
100108 do_div(duty_cycle, pb->scale);
101109
102110 return duty_cycle + lth;
....@@ -105,23 +113,20 @@
105113 static int pwm_backlight_update_status(struct backlight_device *bl)
106114 {
107115 struct pwm_bl_data *pb = bl_get_data(bl);
108
- int brightness = bl->props.brightness;
109
- int duty_cycle;
110
-
111
- if (bl->props.power != FB_BLANK_UNBLANK ||
112
- bl->props.fb_blank != FB_BLANK_UNBLANK ||
113
- bl->props.state & BL_CORE_FBBLANK)
114
- brightness = 0;
116
+ int brightness = backlight_get_brightness(bl);
117
+ struct pwm_state state;
115118
116119 if (pb->notify)
117120 brightness = pb->notify(pb->dev, brightness);
118121
119122 if (brightness > 0) {
120
- duty_cycle = compute_duty_cycle(pb, brightness);
121
- pwm_config(pb->pwm, duty_cycle, pb->period);
122
- pwm_backlight_power_on(pb, brightness);
123
- } else
123
+ pwm_get_state(pb->pwm, &state);
124
+ state.duty_cycle = compute_duty_cycle(pb, brightness);
125
+ pwm_apply_state(pb->pwm, &state);
126
+ pwm_backlight_power_on(pb);
127
+ } else {
124128 pwm_backlight_power_off(pb);
129
+ }
125130
126131 if (pb->notify_after)
127132 pb->notify_after(pb->dev, brightness);
....@@ -143,30 +148,16 @@
143148 };
144149
145150 #ifdef CONFIG_OF
146
-#define PWM_LUMINANCE_SCALE 10000 /* luminance scale */
147
-
148
-/* An integer based power function */
149
-static 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
-}
151
+#define PWM_LUMINANCE_SHIFT 16
152
+#define PWM_LUMINANCE_SCALE (1 << PWM_LUMINANCE_SHIFT) /* luminance scale */
162153
163154 /*
164155 * CIE lightness to PWM conversion.
165156 *
166157 * The CIE 1931 lightness formula is what actually describes how we perceive
167158 * light:
168
- * Y = (L* / 902.3) if L* ≤ 0.08856
169
- * Y = ((L* + 16) / 116)^3 if L* > 0.08856
159
+ * Y = (L* / 903.3) if L* ≤ 8
160
+ * Y = ((L* + 16) / 116)^3 if L* > 8
170161 *
171162 * Where Y is the luminance, the amount of light coming out of the screen, and
172163 * is a number between 0.0 and 1.0; and L* is the lightness, how bright a human
....@@ -175,16 +166,25 @@
175166 * The following function does the fixed point maths needed to implement the
176167 * above formula.
177168 */
178
-static u64 cie1931(unsigned int lightness, unsigned int scale)
169
+static u64 cie1931(unsigned int lightness)
179170 {
180171 u64 retval;
181172
173
+ /*
174
+ * @lightness is given as a number between 0 and 1, expressed
175
+ * as a fixed-point number in scale
176
+ * PWM_LUMINANCE_SCALE. Convert to a percentage, still
177
+ * expressed as a fixed-point number, so the above formulas
178
+ * can be applied.
179
+ */
182180 lightness *= 100;
183
- if (lightness <= (8 * scale)) {
184
- retval = DIV_ROUND_CLOSEST_ULL(lightness * 10, 9023);
181
+ if (lightness <= (8 * PWM_LUMINANCE_SCALE)) {
182
+ retval = DIV_ROUND_CLOSEST(lightness * 10, 9033);
185183 } else {
186
- retval = int_pow((lightness + (16 * scale)) / 116, 3);
187
- retval = DIV_ROUND_CLOSEST_ULL(retval, (scale * scale));
184
+ retval = (lightness + (16 * PWM_LUMINANCE_SCALE)) / 116;
185
+ retval *= retval * retval;
186
+ retval += 1ULL << (2*PWM_LUMINANCE_SHIFT - 1);
187
+ retval >>= 2*PWM_LUMINANCE_SHIFT;
188188 }
189189
190190 return retval;
....@@ -218,8 +218,7 @@
218218 /* Fill the table using the cie1931 algorithm */
219219 for (i = 0; i < data->max_brightness; i++) {
220220 retval = cie1931((i * PWM_LUMINANCE_SCALE) /
221
- data->max_brightness, PWM_LUMINANCE_SCALE) *
222
- period;
221
+ data->max_brightness) * period;
223222 retval = DIV_ROUND_CLOSEST_ULL(retval, PWM_LUMINANCE_SCALE);
224223 if (retval > UINT_MAX)
225224 return -EINVAL;
....@@ -257,8 +256,6 @@
257256 of_property_read_u32(node, "post-pwm-on-delay-ms",
258257 &data->post_pwm_on_delay);
259258 of_property_read_u32(node, "pwm-off-delay-ms", &data->pwm_off_delay);
260
-
261
- data->enable_gpio = -EINVAL;
262259
263260 /*
264261 * Determine the number of brightness levels, if this property is not
....@@ -397,6 +394,31 @@
397394 }
398395 #endif
399396
397
+static bool pwm_backlight_is_linear(struct platform_pwm_backlight_data *data)
398
+{
399
+ unsigned int nlevels = data->max_brightness + 1;
400
+ unsigned int min_val = data->levels[0];
401
+ unsigned int max_val = data->levels[nlevels - 1];
402
+ /*
403
+ * Multiplying by 128 means that even in pathological cases such
404
+ * as (max_val - min_val) == nlevels the error at max_val is less
405
+ * than 1%.
406
+ */
407
+ unsigned int slope = (128 * (max_val - min_val)) / nlevels;
408
+ unsigned int margin = (max_val - min_val) / 20; /* 5% */
409
+ int i;
410
+
411
+ for (i = 1; i < nlevels; i++) {
412
+ unsigned int linear_value = min_val + ((i * slope) / 128);
413
+ unsigned int delta = abs(linear_value - data->levels[i]);
414
+
415
+ if (delta > margin)
416
+ return false;
417
+ }
418
+
419
+ return true;
420
+}
421
+
400422 static int pwm_backlight_initial_power_state(const struct pwm_bl_data *pb)
401423 {
402424 struct device_node *node = pb->dev->of_node;
....@@ -450,7 +472,6 @@
450472 struct device_node *node = pdev->dev.of_node;
451473 struct pwm_bl_data *pb;
452474 struct pwm_state state;
453
- struct pwm_args pargs;
454475 unsigned int i;
455476 int ret;
456477
....@@ -492,22 +513,6 @@
492513 goto err_alloc;
493514 }
494515
495
- /*
496
- * Compatibility fallback for drivers still using the integer GPIO
497
- * platform data. Must go away soon.
498
- */
499
- if (!pb->enable_gpio && gpio_is_valid(data->enable_gpio)) {
500
- ret = devm_gpio_request_one(&pdev->dev, data->enable_gpio,
501
- GPIOF_OUT_INIT_HIGH, "enable");
502
- if (ret < 0) {
503
- dev_err(&pdev->dev, "failed to request GPIO#%d: %d\n",
504
- data->enable_gpio, ret);
505
- goto err_alloc;
506
- }
507
-
508
- pb->enable_gpio = gpio_to_desc(data->enable_gpio);
509
- }
510
-
511516 pb->power_supply = devm_regulator_get(&pdev->dev, "power");
512517 if (IS_ERR(pb->power_supply)) {
513518 ret = PTR_ERR(pb->power_supply);
....@@ -530,7 +535,52 @@
530535
531536 dev_dbg(&pdev->dev, "got pwm for backlight\n");
532537
533
- if (!data->levels) {
538
+ /* Sync up PWM state. */
539
+ pwm_init_state(pb->pwm, &state);
540
+
541
+ /*
542
+ * The DT case will set the pwm_period_ns field to 0 and store the
543
+ * period, parsed from the DT, in the PWM device. For the non-DT case,
544
+ * set the period from platform data if it has not already been set
545
+ * via the PWM lookup table.
546
+ */
547
+ if (!state.period && (data->pwm_period_ns > 0))
548
+ state.period = data->pwm_period_ns;
549
+
550
+ ret = pwm_apply_state(pb->pwm, &state);
551
+ if (ret) {
552
+ dev_err(&pdev->dev, "failed to apply initial PWM state: %d\n",
553
+ ret);
554
+ goto err_alloc;
555
+ }
556
+
557
+ memset(&props, 0, sizeof(struct backlight_properties));
558
+
559
+ if (data->levels) {
560
+ pb->levels = data->levels;
561
+
562
+ /*
563
+ * For the DT case, only when brightness levels is defined
564
+ * data->levels is filled. For the non-DT case, data->levels
565
+ * can come from platform data, however is not usual.
566
+ */
567
+ for (i = 0; i <= data->max_brightness; i++)
568
+ if (data->levels[i] > pb->scale)
569
+ pb->scale = data->levels[i];
570
+
571
+ if (pwm_backlight_is_linear(data))
572
+ props.scale = BACKLIGHT_SCALE_LINEAR;
573
+ else
574
+ props.scale = BACKLIGHT_SCALE_NON_LINEAR;
575
+ } else if (!data->max_brightness) {
576
+ /*
577
+ * If no brightness levels are provided and max_brightness is
578
+ * not set, use the default brightness table. For the DT case,
579
+ * max_brightness is set to 0 when brightness levels is not
580
+ * specified. For the non-DT case, max_brightness is usually
581
+ * set to some value.
582
+ */
583
+
534584 /* Get the PWM period (in nanoseconds) */
535585 pwm_get_state(pb->pwm, &state);
536586
....@@ -541,31 +591,28 @@
541591 "failed to setup default brightness table\n");
542592 goto err_alloc;
543593 }
544
- }
545594
546
- for (i = 0; i <= data->max_brightness; i++) {
547
- if (data->levels[i] > pb->scale)
548
- pb->scale = data->levels[i];
595
+ for (i = 0; i <= data->max_brightness; i++) {
596
+ if (data->levels[i] > pb->scale)
597
+ pb->scale = data->levels[i];
549598
550
- pb->levels = data->levels;
599
+ pb->levels = data->levels;
600
+ }
601
+
602
+ props.scale = BACKLIGHT_SCALE_NON_LINEAR;
603
+ } else {
604
+ /*
605
+ * That only happens for the non-DT case, where platform data
606
+ * sets the max_brightness value.
607
+ */
608
+ pb->scale = data->max_brightness;
551609 }
552610
553611 pwm_adjust_config(pb->pwm);
554612
555
- /*
556
- * The DT case will set the pwm_period_ns field to 0 and store the
557
- * period, parsed from the DT, in the PWM device. For the non-DT case,
558
- * set the period from platform data if it has not already been set
559
- * via the PWM lookup table.
560
- */
561
- pwm_get_args(pb->pwm, &pargs);
562
- pb->period = pargs.period;
563
- if (!pb->period && (data->pwm_period_ns > 0))
564
- pb->period = data->pwm_period_ns;
613
+ pb->lth_brightness = data->lth_brightness * (div_u64(state.period,
614
+ pb->scale));
565615
566
- pb->lth_brightness = data->lth_brightness * (pb->period / pb->scale);
567
-
568
- memset(&props, 0, sizeof(struct backlight_properties));
569616 props.type = BACKLIGHT_RAW;
570617 props.max_brightness = data->max_brightness;
571618 bl = backlight_device_register(dev_name(&pdev->dev), &pdev->dev, pb,
....@@ -585,7 +632,12 @@
585632 data->dft_brightness = data->max_brightness;
586633 }
587634
588
- bl->props.brightness = data->dft_brightness;
635
+ /* set brightness 0, when boot quiescent */
636
+ if (bl_quiescent)
637
+ bl->props.brightness = 0;
638
+ else
639
+ bl->props.brightness = data->dft_brightness;
640
+
589641 bl->props.power = pwm_backlight_initial_power_state(pb);
590642 backlight_update_status(bl);
591643
....@@ -628,9 +680,6 @@
628680 struct backlight_device *bl = dev_get_drvdata(dev);
629681 struct pwm_bl_data *pb = bl_get_data(bl);
630682
631
- if (mem_sleep_current == PM_SUSPEND_MEM_LITE)
632
- return 0;
633
-
634683 if (pb->notify)
635684 pb->notify(pb->dev, 0);
636685
....@@ -645,9 +694,6 @@
645694 static int pwm_backlight_resume(struct device *dev)
646695 {
647696 struct backlight_device *bl = dev_get_drvdata(dev);
648
-
649
- if (mem_sleep_current == PM_SUSPEND_MEM_LITE)
650
- return 0;
651697
652698 backlight_update_status(bl);
653699
....@@ -678,5 +724,5 @@
678724 module_platform_driver(pwm_backlight_driver);
679725
680726 MODULE_DESCRIPTION("PWM based Backlight Driver");
681
-MODULE_LICENSE("GPL");
727
+MODULE_LICENSE("GPL v2");
682728 MODULE_ALIAS("platform:pwm-backlight");