linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Daniel Thompson <daniel.thompson@linaro.org>
To: Enric Balletbo i Serra <enric.balletbo@collabora.com>
Cc: Doug Anderson <dianders@google.com>, Pavel Machek <pavel@ucw.cz>,
	Rob Herring <robh+dt@kernel.org>,
	Jingoo Han <jingoohan1@gmail.com>,
	Richard Purdie <rpurdie@rpsys.net>,
	Jacek Anaszewski <jacek.anaszewski@gmail.com>,
	Brian Norris <briannorris@google.com>,
	Guenter Roeck <groeck@google.com>,
	Lee Jones <lee.jones@linaro.org>,
	Alexandru Stan <amstan@google.com>,
	linux-leds@vger.kernel.org, devicetree@vger.kernel.org,
	linux-kernel@vger.kernel.org, kernel@collabora.com
Subject: Re: [PATCH v3 1/4] backlight: pwm_bl: linear interpolation between brightness-levels
Date: Fri, 6 Apr 2018 16:46:32 +0100	[thread overview]
Message-ID: <20180406154632.ttt5qgsbwsveipwh@holly.lan> (raw)
In-Reply-To: <20180208113032.27810-2-enric.balletbo@collabora.com>

On Thu, Feb 08, 2018 at 12:30:29PM +0100, Enric Balletbo i Serra wrote:
> Setting num-interpolated-steps in the dts will allow you to have linear
> interpolation between values of brightness-levels. This way a high
> resolution pwm duty cycle can be used without having to list out every
> possible value in the dts. This system also allows for gamma corrected
> values.
> 
> The most simple example is interpolate between two brightness values a
> number of steps, this can be done setting the following in the dts:
> 
>   brightness-levels = <0 65535>;
>   num-interpolated-steps = <1024>;
>   default-brightness-level = <512>;
> 
> This will create a brightness-level table with the following values:
> 
>   <0 63 126 189 252 315 378 441 ... 64260 64323 64386 64449 65535>
> 
> Another use case can be describe a gamma corrected curve, as we have
> better sensitivity at low luminance than high luminance we probably
> want have smaller steps for low brightness levels values and bigger
> steps for high brightness levels values. This can be achieved with
> the following in the dts:
> 
>   brightness-levels = <0 4096 65535>;
>   num-interpolated-steps = <1024>;
>   default-brightness-level = <512>;
> 
> This will create a brightness-levels table with the following values:
> 
>   <0 4 8 12 16 20 ... 4096 4156 4216 4276 ... 65535>
> 
> Signed-off-by: Enric Balletbo i Serra <enric.balletbo@collabora.com>

Acked-by: Daniel Thompson <daniel.thompson@linaro.org>

> ---
> Changes since v2:
> Requested by Daniel Thompson:
>  - Use a devres alloc for table creatiion and then just swap pointers.
>  - No need to use calloc because the loop initializes every element.
> Changes since v1:
> - None.
> 
>  drivers/video/backlight/pwm_bl.c | 83 ++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 83 insertions(+)
> 
> diff --git a/drivers/video/backlight/pwm_bl.c b/drivers/video/backlight/pwm_bl.c
> index 8e3f1245f5c5..f0a108ab570a 100644
> --- a/drivers/video/backlight/pwm_bl.c
> +++ b/drivers/video/backlight/pwm_bl.c
> @@ -147,7 +147,11 @@ 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_steps;
>  	struct property *prop;
> +	unsigned int *table;
>  	int length;
>  	u32 value;
>  	int ret;
> @@ -167,6 +171,7 @@ static int pwm_backlight_parse_dt(struct device *dev,
>  	/* 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;
>  
>  		data->levels = devm_kzalloc(dev, size, GFP_KERNEL);
>  		if (!data->levels)
> @@ -184,6 +189,84 @@ static int pwm_backlight_parse_dt(struct device *dev,
>  			return ret;
>  
>  		data->dft_brightness = value;
> +
> +		/*
> +		 * This property is optional, if is set enables linear
> +		 * interpolation between each of the values of brightness levels
> +		 * and creates a new pre-computed table.
> +		 */
> +		of_property_read_u32(node, "num-interpolated-steps",
> +				     &num_steps);
> +
> +		/*
> +		 * Make sure that there is at least two entries in the
> +		 * brightness-levels table, otherwise we can't interpolate
> +		 * between two points.
> +		 */
> +		if (num_steps) {
> +			if (data->max_brightness < 2) {
> +				dev_err(dev, "can't interpolate\n");
> +				return -EINVAL;
> +			}
> +
> +			/*
> +			 * Recalculate the number of brightness levels, now
> +			 * 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++;
> +			dev_dbg(dev, "new number of brightness levels: %d\n",
> +				num_levels);
> +
> +			/*
> +			 * Create a new table of brightness levels with all the
> +			 * interpolated steps.
> +			 */
> +			size = sizeof(*table) * num_levels;
> +			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++;
> +				}
> +			}
> +			table[levels_count] = data->levels[i];
> +
> +			/*
> +			 * As we use interpolation lets remove current
> +			 * brightness levels table and replace for the
> +			 * new interpolated table.
> +			 */
> +			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--;
>  	}
>  
> -- 
> 2.15.1
> 

  reply	other threads:[~2018-04-06 15:46 UTC|newest]

Thread overview: 30+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-02-08 11:30 [PATCH v3 0/4] backlight: pwm_bl: support linear interpolation and brightness to human eye Enric Balletbo i Serra
2018-02-08 11:30 ` [PATCH v3 1/4] backlight: pwm_bl: linear interpolation between brightness-levels Enric Balletbo i Serra
2018-04-06 15:46   ` Daniel Thompson [this message]
2018-02-08 11:30 ` [PATCH v3 2/4] dt-bindings: pwm-backlight: add a num-interpolation-steps property Enric Balletbo i Serra
2018-02-18 22:49   ` Rob Herring
2018-02-08 11:30 ` [PATCH v3 3/4] backlight: pwm_bl: compute brightness of LED linearly to human eye Enric Balletbo i Serra
2018-04-06 15:51   ` Daniel Thompson
2019-06-07 22:19   ` Matthias Kaehlcke
2019-06-08 21:02     ` Pavel Machek
2019-06-10 10:00       ` Enric Balletbo i Serra
2019-06-10 20:39         ` Matthias Kaehlcke
2019-06-10 21:02           ` Enric Balletbo i Serra
2019-06-10 21:54             ` Matthias Kaehlcke
2019-06-10 20:52       ` Matthias Kaehlcke
2019-06-11 10:49         ` Daniel Thompson
2019-06-11 16:55           ` Brian Norris
2019-06-11 22:30             ` Matthias Kaehlcke
2019-06-12  9:54               ` Pavel Machek
2019-06-12 11:03               ` Daniel Thompson
2019-06-12 19:26                 ` Matthias Kaehlcke
2019-06-12 19:47                   ` Daniel Thompson
2019-06-12 21:59                     ` Matthias Kaehlcke
2019-06-17 13:01                   ` Pavel Machek
2019-06-17 20:03                     ` Matthias Kaehlcke
2018-02-08 11:30 ` [PATCH v3 4/4] dt-bindings: pwm-backlight: move brightness-levels to optional Enric Balletbo i Serra
2018-03-19 16:04 ` [PATCH v3 0/4] backlight: pwm_bl: support linear interpolation and brightness to human eye Enric Balletbo Serra
2018-03-20 11:22   ` Daniel Thompson
2018-03-20 12:13     ` Enric Balletbo Serra
2018-04-06 15:54       ` Daniel Thompson
2018-04-09  8:17 ` Lee Jones

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20180406154632.ttt5qgsbwsveipwh@holly.lan \
    --to=daniel.thompson@linaro.org \
    --cc=amstan@google.com \
    --cc=briannorris@google.com \
    --cc=devicetree@vger.kernel.org \
    --cc=dianders@google.com \
    --cc=enric.balletbo@collabora.com \
    --cc=groeck@google.com \
    --cc=jacek.anaszewski@gmail.com \
    --cc=jingoohan1@gmail.com \
    --cc=kernel@collabora.com \
    --cc=lee.jones@linaro.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-leds@vger.kernel.org \
    --cc=pavel@ucw.cz \
    --cc=robh+dt@kernel.org \
    --cc=rpurdie@rpsys.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).