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 <diand...@chromium.org>
Reviewed-by: Matthias Kaehlcke <m...@chromium.org>
Signed-off-by: Alexandru Stan <ams...@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

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

Reply via email to