Skip to content

Commit e6bcca0

Browse files
Enric Balletbo i SerraLee Jones
authored andcommitted
backlight: pwm_bl: Switch to using "atomic" PWM API
The "atomic" API allows us to configure PWM period and duty_cycle and enable it in one call. The patch also moves the pwm_init_state just before any use of the pwm_state struct, this fixes a potential bug where pwm_get_state can be called before pwm_init_state. Signed-off-by: Enric Balletbo i Serra <enric.balletbo@collabora.com> Reviewed-by: Daniel Thompson <daniel.thompson@linaro.org> Tested-by: Heiko Stuebner <heiko@sntech.de> Signed-off-by: Lee Jones <lee.jones@linaro.org>
1 parent 0b19340 commit e6bcca0

File tree

1 file changed

+42
-39
lines changed

1 file changed

+42
-39
lines changed

drivers/video/backlight/pwm_bl.c

Lines changed: 42 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,8 @@
2828
struct pwm_bl_data {
2929
struct pwm_device *pwm;
3030
struct device *dev;
31-
unsigned int period;
3231
unsigned int lth_brightness;
3332
unsigned int *levels;
34-
bool enabled;
3533
struct regulator *power_supply;
3634
struct gpio_desc *enable_gpio;
3735
unsigned int scale;
@@ -46,31 +44,35 @@ struct pwm_bl_data {
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

53-
if (pb->enabled)
52+
pwm_get_state(pb->pwm, &state);
53+
if (state.enabled)
5454
return;
5555

5656
err = regulator_enable(pb->power_supply);
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);
6465

6566
if (pb->enable_gpio)
6667
gpiod_set_value_cansleep(pb->enable_gpio, 1);
67-
68-
pb->enabled = true;
6968
}
7069

7170
static void pwm_backlight_power_off(struct pwm_bl_data *pb)
7271
{
73-
if (!pb->enabled)
72+
struct pwm_state state;
73+
74+
pwm_get_state(pb->pwm, &state);
75+
if (!state.enabled)
7476
return;
7577

7678
if (pb->enable_gpio)
@@ -79,24 +81,27 @@ static void pwm_backlight_power_off(struct pwm_bl_data *pb)
7981
if (pb->pwm_off_delay)
8082
msleep(pb->pwm_off_delay);
8183

82-
pwm_config(pb->pwm, 0, pb->period);
83-
pwm_disable(pb->pwm);
84+
state.enabled = false;
85+
state.duty_cycle = 0;
86+
pwm_apply_state(pb->pwm, &state);
8487

8588
regulator_disable(pb->power_supply);
86-
pb->enabled = false;
8789
}
8890

8991
static int compute_duty_cycle(struct pwm_bl_data *pb, int brightness)
9092
{
9193
unsigned int lth = pb->lth_brightness;
94+
struct pwm_state state;
9295
u64 duty_cycle;
9396

97+
pwm_get_state(pb->pwm, &state);
98+
9499
if (pb->levels)
95100
duty_cycle = pb->levels[brightness];
96101
else
97102
duty_cycle = brightness;
98103

99-
duty_cycle *= pb->period - lth;
104+
duty_cycle *= state.period - lth;
100105
do_div(duty_cycle, pb->scale);
101106

102107
return duty_cycle + lth;
@@ -106,7 +111,7 @@ static int pwm_backlight_update_status(struct backlight_device *bl)
106111
{
107112
struct pwm_bl_data *pb = bl_get_data(bl);
108113
int brightness = bl->props.brightness;
109-
int duty_cycle;
114+
struct pwm_state state;
110115

111116
if (bl->props.power != FB_BLANK_UNBLANK ||
112117
bl->props.fb_blank != FB_BLANK_UNBLANK ||
@@ -117,9 +122,10 @@ static int pwm_backlight_update_status(struct backlight_device *bl)
117122
brightness = pb->notify(pb->dev, brightness);
118123

119124
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);
125+
pwm_get_state(pb->pwm, &state);
126+
state.duty_cycle = compute_duty_cycle(pb, brightness);
127+
pwm_apply_state(pb->pwm, &state);
128+
pwm_backlight_power_on(pb);
123129
} else
124130
pwm_backlight_power_off(pb);
125131

@@ -447,7 +453,6 @@ static int pwm_backlight_probe(struct platform_device *pdev)
447453
struct device_node *node = pdev->dev.of_node;
448454
struct pwm_bl_data *pb;
449455
struct pwm_state state;
450-
struct pwm_args pargs;
451456
unsigned int i;
452457
int ret;
453458

@@ -478,7 +483,6 @@ static int pwm_backlight_probe(struct platform_device *pdev)
478483
pb->check_fb = data->check_fb;
479484
pb->exit = data->exit;
480485
pb->dev = &pdev->dev;
481-
pb->enabled = false;
482486
pb->post_pwm_on_delay = data->post_pwm_on_delay;
483487
pb->pwm_off_delay = data->pwm_off_delay;
484488

@@ -539,10 +543,26 @@ static int pwm_backlight_probe(struct platform_device *pdev)
539543

540544
dev_dbg(&pdev->dev, "got pwm for backlight\n");
541545

542-
if (!data->levels) {
543-
/* Get the PWM period (in nanoseconds) */
544-
pwm_get_state(pb->pwm, &state);
546+
/* Sync up PWM state. */
547+
pwm_init_state(pb->pwm, &state);
545548

549+
/*
550+
* The DT case will set the pwm_period_ns field to 0 and store the
551+
* period, parsed from the DT, in the PWM device. For the non-DT case,
552+
* set the period from platform data if it has not already been set
553+
* via the PWM lookup table.
554+
*/
555+
if (!state.period && (data->pwm_period_ns > 0))
556+
state.period = data->pwm_period_ns;
557+
558+
ret = pwm_apply_state(pb->pwm, &state);
559+
if (ret) {
560+
dev_err(&pdev->dev, "failed to apply initial PWM state: %d\n",
561+
ret);
562+
goto err_alloc;
563+
}
564+
565+
if (!data->levels) {
546566
ret = pwm_backlight_brightness_default(&pdev->dev, data,
547567
state.period);
548568
if (ret < 0) {
@@ -559,24 +579,7 @@ static int pwm_backlight_probe(struct platform_device *pdev)
559579
pb->levels = data->levels;
560580
}
561581

562-
/*
563-
* FIXME: pwm_apply_args() should be removed when switching to
564-
* the atomic PWM API.
565-
*/
566-
pwm_apply_args(pb->pwm);
567-
568-
/*
569-
* The DT case will set the pwm_period_ns field to 0 and store the
570-
* period, parsed from the DT, in the PWM device. For the non-DT case,
571-
* set the period from platform data if it has not already been set
572-
* via the PWM lookup table.
573-
*/
574-
pwm_get_args(pb->pwm, &pargs);
575-
pb->period = pargs.period;
576-
if (!pb->period && (data->pwm_period_ns > 0))
577-
pb->period = data->pwm_period_ns;
578-
579-
pb->lth_brightness = data->lth_brightness * (pb->period / pb->scale);
582+
pb->lth_brightness = data->lth_brightness * (state.period / pb->scale);
580583

581584
memset(&props, 0, sizeof(struct backlight_properties));
582585
props.type = BACKLIGHT_RAW;

0 commit comments

Comments
 (0)