From: Mario Limonciello Date: Fri, 28 Feb 2025 18:51:44 +0000 (-0600) Subject: drm/amd/display: Add support for custom brightness curve X-Git-Tag: v6.15-rc1~120^2~12^2~47 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=578df37b1b6a5bc41602cdab3d982072e5688222;p=thirdparty%2Flinux.git drm/amd/display: Add support for custom brightness curve Some systems specify in the firmware a brightness curve that better reflects the characteristics of the panel used. This is done in the form of data points and matching luminance percentage. When converting a userspace requested brightness value use that curve to convert to a firmware intended brightness value. Reviewed-by: Alex Hung Link: https://lore.kernel.org/r/20250228185145.186319-5-mario.limonciello@amd.com Signed-off-by: Mario Limonciello Signed-off-by: Alex Deucher --- diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 8d5daa96eeaea..5e049b8f877dc 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -4750,10 +4750,35 @@ static u32 convert_brightness_from_user(const struct amdgpu_dm_backlight_caps *c uint32_t brightness) { unsigned int min, max; + u8 prev_signal = 0, prev_lum = 0; if (!get_brightness_range(caps, &min, &max)) return brightness; + for (int i = 0; i < caps->data_points; i++) { + u8 signal, lum; + + signal = caps->luminance_data[i].input_signal; + lum = caps->luminance_data[i].luminance; + + /* + * brightness == signal: luminance is percent numerator + * brightness < signal: interpolate between previous and current luminance numerator + * brightness > signal: find next data point + */ + if (brightness < signal) + lum = prev_lum + DIV_ROUND_CLOSEST((lum - prev_lum) * + (brightness - prev_signal), + signal - prev_signal); + else if (brightness > signal) { + prev_signal = signal; + prev_lum = lum; + continue; + } + brightness = DIV_ROUND_CLOSEST(lum * brightness, 101); + break; + } + // Rescale 0..255 to min..max return min + DIV_ROUND_CLOSEST((max - min) * brightness, AMDGPU_MAX_BL_LEVEL);