Linux-PWM Archive on lore.kernel.org
 help / color / Atom feed
* [PATCH 0/3] PWM backlight interpolation adjustments
@ 2020-07-21  4:25 Alexandru Stan
  2020-07-21  4:25 ` [PATCH 1/3] backlight: pwm_bl: Fix interpolation Alexandru Stan
                   ` (2 more replies)
  0 siblings, 3 replies; 5+ messages in thread
From: Alexandru Stan @ 2020-07-21  4:25 UTC (permalink / raw)
  To: Thierry Reding, Uwe Kleine-König, Lee Jones,
	Daniel Thompson, Jingoo Han, Bartlomiej Zolnierkiewicz,
	Heiko Stuebner, Rob Herring
  Cc: Matthias Kaehlcke, Douglas Anderson, Enric Balletbo i Serra,
	Alexandru Stan, devicetree-u79uwXL29TY76Z2rM5mHXA,
	dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-fbdev-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-pwm-u79uwXL29TY76Z2rM5mHXA,
	linux-rockchip-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r

I was trying to adjust the brightness for a new chromebook:
https://chromium-review.googlesource.com/c/chromiumos/third_party/kernel/+/2291209
Like a lot of panels, the low end needs to be cropped,
and now that we have the interpolation stuff I wanted to make use of it
and bake in even the curve.

I found the behavior a little unintuitive and non-linear. See patch 1
for a suggested fix for this.

Unfortunatelly a few veyron dts files were relying on this
(perhaps weird) behavior. Those devices also want a minimum brightness.
The issue is that they also want the 0% point for turning off the
display.
https://github.com/torvalds/linux/commit/6233269bce47bd450196a671ab28eb1ec5eb88d9#diff-e401ae20091bbfb311a062c464f4f47fL23

So the idea here is to change those dts files to only say <3 255> (patch
3), and add in a virtual 0% point at the bottom of the scale (patch 2).

We have to do this conditionally because it seems some devices like to
have the scale inverted:
  % git grep "brightness-levels\s*=\s*<\s*[1-9]"|cat
  arch/arm/boot/dts/tegra124-apalis-eval.dts:             brightness-levels = <255 231 223 207 191 159 127 0>;


Alexandru Stan (3):
  backlight: pwm_bl: Fix interpolation
  backlight: pwm_bl: Artificially add 0% during interpolation
  ARM: dts: rockchip: Remove 0 point in backlight

 arch/arm/boot/dts/rk3288-veyron-jaq.dts    |  2 +-
 arch/arm/boot/dts/rk3288-veyron-minnie.dts |  2 +-
 arch/arm/boot/dts/rk3288-veyron-tiger.dts  |  2 +-
 drivers/video/backlight/pwm_bl.c           | 78 +++++++++++-----------
 4 files changed, 42 insertions(+), 42 deletions(-)

-- 
2.27.0

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH 1/3] backlight: pwm_bl: Fix interpolation
  2020-07-21  4:25 [PATCH 0/3] PWM backlight interpolation adjustments Alexandru Stan
@ 2020-07-21  4:25 ` Alexandru Stan
  2020-07-21  4:25 ` [PATCH 2/3] backlight: pwm_bl: Artificially add 0% during interpolation Alexandru Stan
  2020-08-05 21:04 ` [PATCH 0/3] PWM backlight interpolation adjustments Alexandru M Stan
  2 siblings, 0 replies; 5+ messages in thread
From: Alexandru Stan @ 2020-07-21  4:25 UTC (permalink / raw)
  To: Thierry Reding, Uwe Kleine-König, Lee Jones,
	Daniel Thompson, Jingoo Han, Bartlomiej Zolnierkiewicz,
	Heiko Stuebner, Rob Herring
  Cc: Matthias Kaehlcke, Douglas Anderson, Enric Balletbo i Serra,
	Alexandru Stan, dri-devel, linux-fbdev, linux-kernel, linux-pwm

Whenever num-interpolated-steps was larger than the distance
between 2 consecutive brightness levels the table would get really
discontinuous. The slope of the interpolation would stick with
integers only and if it was 0 the whole line segment would get skipped.

Example settings:
	brightness-levels = <0 1 2 4 8 16 32 64 128 256>;
	num-interpolated-steps = <16>;

The distances between 1 2 4 and 8 would be 1, and only starting with 16
it would start to interpolate properly.

Let's change it so there's always interpolation happening, even if
there's no enough points available (read: values in the table would
appear more than once). This should match the expected behavior much
more closely.

Reviewed-by: Douglas Anderson <dianders@chromium.org>
Reviewed-by: Matthias Kaehlcke <mka@chromium.org>
Signed-off-by: Alexandru Stan <amstan@chromium.org>
---

 drivers/video/backlight/pwm_bl.c | 70 ++++++++++++++------------------
 1 file changed, 31 insertions(+), 39 deletions(-)

diff --git a/drivers/video/backlight/pwm_bl.c b/drivers/video/backlight/pwm_bl.c
index 82b8d7594701..5193a72305a2 100644
--- a/drivers/video/backlight/pwm_bl.c
+++ b/drivers/video/backlight/pwm_bl.c
@@ -235,8 +235,7 @@ static int pwm_backlight_parse_dt(struct device *dev,
 				  struct platform_pwm_backlight_data *data)
 {
 	struct device_node *node = dev->of_node;
-	unsigned int num_levels = 0;
-	unsigned int levels_count;
+	unsigned int num_levels;
 	unsigned int num_steps = 0;
 	struct property *prop;
 	unsigned int *table;
@@ -265,12 +264,11 @@ static int pwm_backlight_parse_dt(struct device *dev,
 	if (!prop)
 		return 0;
 
-	data->max_brightness = length / sizeof(u32);
+	num_levels = length / sizeof(u32);
 
 	/* read brightness levels from DT property */
-	if (data->max_brightness > 0) {
-		size_t size = sizeof(*data->levels) * data->max_brightness;
-		unsigned int i, j, n = 0;
+	if (num_levels > 0) {
+		size_t size = sizeof(*data->levels) * num_levels;
 
 		data->levels = devm_kzalloc(dev, size, GFP_KERNEL);
 		if (!data->levels)
@@ -278,7 +276,7 @@ static int pwm_backlight_parse_dt(struct device *dev,
 
 		ret = of_property_read_u32_array(node, "brightness-levels",
 						 data->levels,
-						 data->max_brightness);
+						 num_levels);
 		if (ret < 0)
 			return ret;
 
@@ -303,7 +301,13 @@ static int pwm_backlight_parse_dt(struct device *dev,
 		 * between two points.
 		 */
 		if (num_steps) {
-			if (data->max_brightness < 2) {
+			unsigned int num_input_levels = num_levels;
+			unsigned int i;
+			u32 x1, x2, x;
+			u32 y1, y2;
+			s64 dx, dy;
+
+			if (num_input_levels < 2) {
 				dev_err(dev, "can't interpolate\n");
 				return -EINVAL;
 			}
@@ -313,14 +317,7 @@ static int pwm_backlight_parse_dt(struct device *dev,
 			 * taking in consideration the number of interpolated
 			 * steps between two levels.
 			 */
-			for (i = 0; i < data->max_brightness - 1; i++) {
-				if ((data->levels[i + 1] - data->levels[i]) /
-				   num_steps)
-					num_levels += num_steps;
-				else
-					num_levels++;
-			}
-			num_levels++;
+			num_levels = (num_input_levels - 1) * num_steps + 1;
 			dev_dbg(dev, "new number of brightness levels: %d\n",
 				num_levels);
 
@@ -332,24 +329,25 @@ static int pwm_backlight_parse_dt(struct device *dev,
 			table = devm_kzalloc(dev, size, GFP_KERNEL);
 			if (!table)
 				return -ENOMEM;
-
-			/* Fill the interpolated table. */
-			levels_count = 0;
-			for (i = 0; i < data->max_brightness - 1; i++) {
-				value = data->levels[i];
-				n = (data->levels[i + 1] - value) / num_steps;
-				if (n > 0) {
-					for (j = 0; j < num_steps; j++) {
-						table[levels_count] = value;
-						value += n;
-						levels_count++;
-					}
-				} else {
-					table[levels_count] = data->levels[i];
-					levels_count++;
+			/*
+			 * Fill the interpolated table[x] = y
+			 * by draw lines between each (x1, y1) to (x2, y2).
+			 */
+			dx = num_steps;
+			for (i = 0; i < num_input_levels - 1; i++) {
+				x1 = i * dx;
+				x2 = x1 + dx;
+				y1 = data->levels[i];
+				y2 = data->levels[i + 1];
+				dy = y2 - y1;
+
+				for (x = x1; x < x2; x++) {
+					table[x] = y1 +
+						div_s64(dy * (x - x1), dx);
 				}
 			}
-			table[levels_count] = data->levels[i];
+			/* Fill in the last point, since no line starts here. */
+			table[x2] = y2;
 
 			/*
 			 * As we use interpolation lets remove current
@@ -358,15 +356,9 @@ static int pwm_backlight_parse_dt(struct device *dev,
 			 */
 			devm_kfree(dev, data->levels);
 			data->levels = table;
-
-			/*
-			 * Reassign max_brightness value to the new total number
-			 * of brightness levels.
-			 */
-			data->max_brightness = num_levels;
 		}
 
-		data->max_brightness--;
+		data->max_brightness = num_levels - 1;
 	}
 
 	return 0;
-- 
2.27.0

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH 2/3] backlight: pwm_bl: Artificially add 0% during interpolation
  2020-07-21  4:25 [PATCH 0/3] PWM backlight interpolation adjustments Alexandru Stan
  2020-07-21  4:25 ` [PATCH 1/3] backlight: pwm_bl: Fix interpolation Alexandru Stan
@ 2020-07-21  4:25 ` Alexandru Stan
  2020-08-07  8:21   ` daniel
  2020-08-05 21:04 ` [PATCH 0/3] PWM backlight interpolation adjustments Alexandru M Stan
  2 siblings, 1 reply; 5+ messages in thread
From: Alexandru Stan @ 2020-07-21  4:25 UTC (permalink / raw)
  To: Thierry Reding, Uwe Kleine-König, Lee Jones,
	Daniel Thompson, Jingoo Han, Bartlomiej Zolnierkiewicz,
	Heiko Stuebner, Rob Herring
  Cc: Matthias Kaehlcke, Douglas Anderson, Enric Balletbo i Serra,
	Alexandru Stan, dri-devel, linux-fbdev, linux-kernel, linux-pwm

Some displays need the low end of the curve cropped in order to make
them happy. In that case we still want to have the 0% point, even though
anything between 0% and 5%(example) would be skipped.

Signed-off-by: Alexandru Stan <amstan@chromium.org>
---

 drivers/video/backlight/pwm_bl.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/drivers/video/backlight/pwm_bl.c b/drivers/video/backlight/pwm_bl.c
index 5193a72305a2..b24711ddf504 100644
--- a/drivers/video/backlight/pwm_bl.c
+++ b/drivers/video/backlight/pwm_bl.c
@@ -349,6 +349,14 @@ static int pwm_backlight_parse_dt(struct device *dev,
 			/* Fill in the last point, since no line starts here. */
 			table[x2] = y2;
 
+			/*
+			 * If we don't start at 0 yet we're increasing, assume
+			 * the dts wanted to crop the low end of the range, so
+			 * insert a 0 to provide a display off mode.
+			 */
+			if (table[0] > 0 && table[0] < table[num_levels - 1])
+				table[0] = 0;
+
 			/*
 			 * As we use interpolation lets remove current
 			 * brightness levels table and replace for the
-- 
2.27.0

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH 0/3] PWM backlight interpolation adjustments
  2020-07-21  4:25 [PATCH 0/3] PWM backlight interpolation adjustments Alexandru Stan
  2020-07-21  4:25 ` [PATCH 1/3] backlight: pwm_bl: Fix interpolation Alexandru Stan
  2020-07-21  4:25 ` [PATCH 2/3] backlight: pwm_bl: Artificially add 0% during interpolation Alexandru Stan
@ 2020-08-05 21:04 ` Alexandru M Stan
  2 siblings, 0 replies; 5+ messages in thread
From: Alexandru M Stan @ 2020-08-05 21:04 UTC (permalink / raw)
  To: Thierry Reding, Uwe Kleine-König, Lee Jones,
	Daniel Thompson, Jingoo Han, Bartlomiej Zolnierkiewicz,
	Heiko Stuebner, Rob Herring
  Cc: Matthias Kaehlcke, Douglas Anderson, Enric Balletbo i Serra,
	devicetree, dri-devel, linux-arm-kernel, linux-fbdev,
	linux-kernel, linux-pwm, open list:ARM/Rockchip SoC...

On Mon, Jul 20, 2020 at 9:27 PM Alexandru Stan <amstan@chromium.org> wrote:
>
> I was trying to adjust the brightness for a new chromebook:
> https://chromium-review.googlesource.com/c/chromiumos/third_party/kernel/+/2291209
> Like a lot of panels, the low end needs to be cropped,
> and now that we have the interpolation stuff I wanted to make use of it
> and bake in even the curve.
>
> I found the behavior a little unintuitive and non-linear. See patch 1
> for a suggested fix for this.
>
> Unfortunatelly a few veyron dts files were relying on this
> (perhaps weird) behavior. Those devices also want a minimum brightness.
> The issue is that they also want the 0% point for turning off the
> display.
> https://github.com/torvalds/linux/commit/6233269bce47bd450196a671ab28eb1ec5eb88d9#diff-e401ae20091bbfb311a062c464f4f47fL23
>
> So the idea here is to change those dts files to only say <3 255> (patch
> 3), and add in a virtual 0% point at the bottom of the scale (patch 2).
>
> We have to do this conditionally because it seems some devices like to
> have the scale inverted:
>   % git grep "brightness-levels\s*=\s*<\s*[1-9]"|cat
>   arch/arm/boot/dts/tegra124-apalis-eval.dts:             brightness-levels = <255 231 223 207 191 159 127 0>;
>
>
> Alexandru Stan (3):
>   backlight: pwm_bl: Fix interpolation
>   backlight: pwm_bl: Artificially add 0% during interpolation
>   ARM: dts: rockchip: Remove 0 point in backlight
>
>  arch/arm/boot/dts/rk3288-veyron-jaq.dts    |  2 +-
>  arch/arm/boot/dts/rk3288-veyron-minnie.dts |  2 +-
>  arch/arm/boot/dts/rk3288-veyron-tiger.dts  |  2 +-
>  drivers/video/backlight/pwm_bl.c           | 78 +++++++++++-----------
>  4 files changed, 42 insertions(+), 42 deletions(-)
>
> --
> 2.27.0
>

Hello,

Friendly ping.
Let me know if you would like me to make any changes to my patches.

Thanks,
Alexandru M Stan

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH 2/3] backlight: pwm_bl: Artificially add 0% during interpolation
  2020-07-21  4:25 ` [PATCH 2/3] backlight: pwm_bl: Artificially add 0% during interpolation Alexandru Stan
@ 2020-08-07  8:21   ` daniel
  0 siblings, 0 replies; 5+ messages in thread
From: daniel @ 2020-08-07  8:21 UTC (permalink / raw)
  Cc: Thierry Reding, Uwe Kleine-König, Lee Jones,
	Daniel Thompson, Jingoo Han, Bartlomiej Zolnierkiewicz,
	Heiko Stuebner, Rob Herring, linux-pwm, linux-fbdev,
	Douglas Anderson, dri-devel, linux-kernel, Matthias Kaehlcke,
	Enric Balletbo i Serra

On Mon, Jul 20, 2020 at 09:25:21PM -0700, Alexandru Stan wrote:
> Some displays need the low end of the curve cropped in order to make
> them happy. In that case we still want to have the 0% point, even though
> anything between 0% and 5%(example) would be skipped.
> 
> Signed-off-by: Alexandru Stan <amstan@chromium.org>
> ---
> 
>  drivers/video/backlight/pwm_bl.c | 8 ++++++++
>  1 file changed, 8 insertions(+)
> 
> diff --git a/drivers/video/backlight/pwm_bl.c b/drivers/video/backlight/pwm_bl.c
> index 5193a72305a2..b24711ddf504 100644
> --- a/drivers/video/backlight/pwm_bl.c
> +++ b/drivers/video/backlight/pwm_bl.c
> @@ -349,6 +349,14 @@ static int pwm_backlight_parse_dt(struct device *dev,
>  			/* Fill in the last point, since no line starts here. */
>  			table[x2] = y2;
>  
> +			/*
> +			 * If we don't start at 0 yet we're increasing, assume
> +			 * the dts wanted to crop the low end of the range, so
> +			 * insert a 0 to provide a display off mode.
> +			 */
> +			if (table[0] > 0 && table[0] < table[num_levels - 1])
> +				table[0] = 0;

Isn't that what the enable/disable switch in backlights are for? There's
lots of backligh drivers (mostly the firmware variety) where setting the
backlight to 0 does not shut it off, it's just the lowest setting.

But I've not been involved in the details of these discussions.
-Daniel

> +
>  			/*
>  			 * As we use interpolation lets remove current
>  			 * brightness levels table and replace for the
> -- 
> 2.27.0
> 
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, back to index

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-07-21  4:25 [PATCH 0/3] PWM backlight interpolation adjustments Alexandru Stan
2020-07-21  4:25 ` [PATCH 1/3] backlight: pwm_bl: Fix interpolation Alexandru Stan
2020-07-21  4:25 ` [PATCH 2/3] backlight: pwm_bl: Artificially add 0% during interpolation Alexandru Stan
2020-08-07  8:21   ` daniel
2020-08-05 21:04 ` [PATCH 0/3] PWM backlight interpolation adjustments Alexandru M Stan

Linux-PWM Archive on lore.kernel.org

Archives are clonable:
	git clone --mirror https://lore.kernel.org/linux-pwm/0 linux-pwm/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 linux-pwm linux-pwm/ https://lore.kernel.org/linux-pwm \
		linux-pwm@vger.kernel.org
	public-inbox-index linux-pwm

Example config snippet for mirrors

Newsgroup available over NNTP:
	nntp://nntp.lore.kernel.org/org.kernel.vger.linux-pwm


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git