backlight_millipercent_to_pwm_legacy() takes the floor index into
backlight_lut, which has one entry per percent of luminance. Any request
between two whole percents gets the PWM of the lower one, so a PWM panel
has at most 101 brightness levels however fine the request is

Interpolate linearly between the entries on each side of the request.
Whole percents still give the LUT entry. The result never decreases as
the request grows, since validate_ext_backlight_caps() only accepts a
curve whose signals and luminances strictly increase, so the LUT never
decreases either. The linear curve bypass and the 100% case are
unchanged

Signed-off-by: Hugo Sales <[email protected]>
---
amdgpu_dm only hands the power module whole percents until patch 4, so
on its own this patch changes no PWM for it. Coming first keeps patch 4
from dropping a level to the whole percent below

With patch 4 too, on the GV301QH curve with minimum 12, the 62452 levels
from user_min to user_max reach the panel as 57821 different PWM values.
Without the series they give 99, and patch 4 without this patch would
give 100. The bottom tenth of the scale goes from 18 PWM values to 5434

BACKLIGHT_MILLIPERCENT_MAX is defined at the top of power_abm.c as
100 * 1000. mod_power_create() sets num_backlight_levels to at least
101 and allocates backlight_lut with that many entries, and nothing
changes it afterwards, so index + 1 stays within the LUT. The function
still returns early with fewer than 2 levels, as
backlight_pwm_to_millipercent_legacy() already does

KUnit: dm_test_pwm_lut_between_percents, dm_test_pwm_lut_monotonic and
dm_test_pwm_lut_min_input_signal from patch 6 fail without this patch
and pass with it
---
 .../gpu/drm/amd/display/modules/power/power_abm.c  | 29 ++++++++++++++++++----
 1 file changed, 24 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/modules/power/power_abm.c 
b/drivers/gpu/drm/amd/display/modules/power/power_abm.c
index 5e86889eaa841..d9c1f1401b604 100644
--- a/drivers/gpu/drm/amd/display/modules/power/power_abm.c
+++ b/drivers/gpu/drm/amd/display/modules/power/power_abm.c
@@ -524,6 +524,9 @@ static unsigned int backlight_millipercent_to_pwm_legacy(
 {
        unsigned int pwm = (unsigned int)-1;
        unsigned int index = 0;
+       unsigned int lower, upper;
+       unsigned long long scaled;
+       unsigned int remainder;
 
        if (core_power == NULL)
                return 0;
@@ -541,17 +544,33 @@ static unsigned int backlight_millipercent_to_pwm_legacy(
                return pwm;
        }
 
-       if (millipercent >= (100 * 1000))
+       if (millipercent >= BACKLIGHT_MILLIPERCENT_MAX)
                return 
core_power->bl_prop[inst].backlight_lut[core_power->bl_prop[inst].num_backlight_levels
 - 1];
 
-       /* This will give the floor index. */
-       index = ((core_power->bl_prop[inst].num_backlight_levels - 1) *
-                                               millipercent) / 100000;
        /* Null check otherwise eDP doesn't lightup when connected to DP1 */
        if (core_power->bl_prop[inst].backlight_lut == NULL)
                return pwm;
 
-       pwm = core_power->bl_prop[inst].backlight_lut[index];
+       if (core_power->bl_prop[inst].num_backlight_levels < 2)
+               return pwm;
+
+       /*
+        * Interpolate between the two LUT entries around millipercent.
+        * backlight_lut has num_backlight_levels entries, and millipercent is
+        * below BACKLIGHT_MILLIPERCENT_MAX here, so index + 1 stays within it
+        */
+       scaled = (unsigned long 
long)(core_power->bl_prop[inst].num_backlight_levels - 1) *
+                millipercent;
+       index = (unsigned int)div_u64_rem(scaled, BACKLIGHT_MILLIPERCENT_MAX, 
&remainder);
+       lower = core_power->bl_prop[inst].backlight_lut[index];
+       upper = core_power->bl_prop[inst].backlight_lut[index + 1];
+
+       if (upper <= lower)
+               return lower;
+
+       pwm = lower + (unsigned int)div_u64((unsigned long long)(upper - lower) 
* remainder +
+                                           BACKLIGHT_MILLIPERCENT_MAX / 2,
+                                           BACKLIGHT_MILLIPERCENT_MAX);
 
        return pwm;
 }

-- 
2.56.0

Reply via email to