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
