From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4666581ACD; Fri, 9 Oct 2026 14:53:25 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1791557607; cv=none; b=CkNgM6f3H00UQqR0w+639rRcEUo3Eet8dX6HckS7kkXUFGO9eJ0IMLFltZ/wmXRenoW5LVjracqVL8LzfdayPx8pEqIM6pdudimOTvW/Hywyy8z7GDZrhPkAJHZDk0lJH1kjmmwFASr8z7Jne8zRdOgoe9Kwgnt51YdPwkh09vE= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1791557607; c=relaxed/simple; bh=+ugto1PhGQpgA85hQ0Q2kl+3QK6nmfxUzrhcsIevIx8=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=RPvvUEW7L2UF3jZFD7lOIX1QeNfXt6gPGI1eD+3f3Coaa1qCjBDlr0yvDuFSkRdND1RPNelRbms3f9L/yZ0PueUBOiReXruYL+xQvcbYrAnukgMmcB3hnsLQKiMD6fZ3wMF2s9aie1eW1Y93LQJR6HoMrUbxdYl1pV+8BCDx2pU= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linuxfoundation.org header.i=@linuxfoundation.org header.b=OhBH8Hlc; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linuxfoundation.org header.i=@linuxfoundation.org header.b="OhBH8Hlc" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 567F71F000FF; Fri, 9 Oct 2026 14:53:25 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linuxfoundation.org; s=korg; t=1791557605; bh=hoWaMahotIuZ3Hwg2vV4+34uSWVtP4fVadDYtpdq2pY=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=OhBH8Hlc9jdu1seJT6Q+55O+g4AmqQ67S9wJ4eO3m6hE7RP/BmdPZGRQxlLmqygqw NmFghnk0n/m58ucWSNiuYhmMrf4ACo8V/tUgi4luMeXyD/XfUwZNK020eTsFsIdlvf pDQ//2rBv2Yg1KVkmLbmobjXcPpSQtkt8UgyCTIU= From: Greg Kroah-Hartman To: stable@vger.kernel.org Cc: Greg Kroah-Hartman , patches@lists.linux.dev, Ray Wu , Fangzhi Zuo , "ChiaHsuan (Tom) Chung" , Dan Wheeler , Alex Deucher , Sasha Levin Subject: [PATCH 7.2 418/428] drm/amd/display: map PWM brightness through custom backlight curve Date: Fri, 9 Oct 2026 16:12:35 +0200 Message-ID: <20261009140955.417515365@linuxfoundation.org> X-Mailer: git-send-email 2.56.0 In-Reply-To: <20261009140946.008206689@linuxfoundation.org> References: <20261009140946.008206689@linuxfoundation.org> User-Agent: quilt/0.69 X-stable: review X-Patchwork-Hint: ignore Precedence: bulk X-Mailing-List: patches@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit 7.2-stable review patch. If anyone has any objections, please let me know. ------------------ From: Ray Wu [ Upstream commit 51cc916648d1421e0271090fb4fa86550a7a96d9 ] [Why/How] On the PWM path, convert the userspace brightness to an input signal and derive the target luminance from the custom backlight curve, then pass the resulting millipercent to the power module. This keeps PWM programming and backlight curve mapping in the power module, aligning the Linux path with the Windows behavior. Closes: https://gitlab.freedesktop.org/drm/amd/-/issues/5723 Fixes: 3c108046e1d6 ("drm/amd/display: Add power module on Linux") Assisted-by: Cursor:Claude-Opus-4.8 Signed-off-by: Ray Wu Signed-off-by: Fangzhi Zuo Reviewed-by: ChiaHsuan (Tom) Chung Tested-by: Dan Wheeler Signed-off-by: Alex Deucher (cherry picked from commit bc4e099caa85e8d4c3555851a0feb07058c4a1fe) Cc: stable@vger.kernel.org [ sashal: Relocated the changes into the existing display manager code because the backlight code had not been split out. ] Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 92 +++++++++++++++++++--- 1 file changed, 80 insertions(+), 12 deletions(-) --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -70,6 +70,7 @@ #include "ivsrcid/ivsrcid_vislands30.h" #include +#include #include #include #include @@ -1974,6 +1975,8 @@ static int amdgpu_dm_init_power_module(s init_data[i].use_custom_backlight_caps = false; init_data[i].custom_backlight_caps_config_no = 0; init_data[i].use_linear_backlight_curve = false; + if (amdgpu_dc_debug_mask & DC_DISABLE_CUSTOM_BRIGHTNESS_CURVE) + init_data[i].use_linear_backlight_curve = true; init_data[i].def_varibright_enable = 0; init_data[i].varibright_level = 0; /* @@ -5304,6 +5307,68 @@ static inline u32 scale_fw_to_input(int return min + DIV_ROUND_CLOSEST_ULL(input * (max - min), AMDGPU_MAX_BL_LEVEL); } +static u32 backlight_signal_to_luminance(const struct amdgpu_dm_backlight_caps *caps, + u32 signal) +{ + u32 lower_signal, upper_signal; + u32 lower_lum, upper_lum; + int i; + + if (!caps->data_points) + return DIV_ROUND_CLOSEST(signal * 100, AMDGPU_MAX_BL_LEVEL); + + if (signal < caps->luminance_data[0].input_signal) { + lower_signal = 0; + lower_lum = 0; + upper_signal = caps->luminance_data[0].input_signal; + upper_lum = caps->luminance_data[0].luminance; + } else if (signal >= + caps->luminance_data[caps->data_points - 1].input_signal) { + lower_signal = caps->luminance_data[caps->data_points - 1].input_signal; + lower_lum = caps->luminance_data[caps->data_points - 1].luminance; + upper_signal = caps->max_input_signal; + upper_lum = 100; + } else { + for (i = 1; + i < caps->data_points && + signal > caps->luminance_data[i].input_signal; + i++) + ; + + lower_signal = caps->luminance_data[i - 1].input_signal; + upper_signal = caps->luminance_data[i].input_signal; + lower_lum = caps->luminance_data[i - 1].luminance; + upper_lum = caps->luminance_data[i].luminance; + } + + if (upper_signal == lower_signal) + return upper_lum; + + return lower_lum + DIV_ROUND_CLOSEST((upper_lum - lower_lum) * + (signal - lower_signal), + upper_signal - lower_signal); +} + +static u32 convert_brightness_to_millipercent(const struct amdgpu_dm_backlight_caps *caps, + u32 user_brightness) +{ + unsigned int min, max; + u32 signal, luminance; + + if (!get_brightness_range(caps, &min, &max)) + return DIV_ROUND_CLOSEST_ULL((u64)user_brightness * 100000, + MAX_BACKLIGHT_LEVEL); + + user_brightness = clamp(user_brightness, min, max); + if (amdgpu_dc_debug_mask & DC_DISABLE_CUSTOM_BRIGHTNESS_CURVE) + return DIV_ROUND_CLOSEST_ULL((u64)user_brightness * 100000, max); + + signal = scale_input_to_fw(max, user_brightness); + luminance = backlight_signal_to_luminance(caps, signal); + + return min_t(u32, luminance * 1000, 100000); +} + static void convert_custom_brightness(const struct amdgpu_dm_backlight_caps *caps, unsigned int min, unsigned int max, uint32_t *user_brightness) @@ -5421,10 +5486,10 @@ static void amdgpu_dm_backlight_set_leve struct amdgpu_dm_backlight_caps *caps; struct dc_link *link; u32 brightness = 0; + u32 millipercent = 0; bool rc = false, reallow_idle = false; struct drm_connector *connector; struct dc_stream_state *stream; - unsigned int min, max; list_for_each_entry(connector, &dm->ddev->mode_config.connector_list, head) { struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector); @@ -5447,12 +5512,21 @@ static void amdgpu_dm_backlight_set_leve /* update scratch register */ if (bl_idx == 0) amdgpu_atombios_scratch_regs_set_backlight_level(dm->adev, dm->brightness[bl_idx]); - brightness = convert_brightness_from_user(caps, dm->brightness[bl_idx]); + link = (struct dc_link *)dm->backlight_link[bl_idx]; + stream = dm_find_stream_with_link(dm, link); + if (!stream) + return; - /* Apply brightness quirk */ - if (caps->brightness_mask) - brightness |= caps->brightness_mask; + if (caps->aux_support) { + brightness = convert_brightness_from_user(caps, dm->brightness[bl_idx]); + /* Apply brightness quirk */ + if (caps->brightness_mask) + brightness |= caps->brightness_mask; + } else { + millipercent = convert_brightness_to_millipercent(caps, + user_brightness); + } if (trace_amdgpu_dm_brightness_enabled()) { trace_amdgpu_dm_brightness(__builtin_return_address(0), @@ -5462,10 +5536,6 @@ static void amdgpu_dm_backlight_set_leve power_supply_is_system_supplied() > 0); } - stream = dm_find_stream_with_link(dm, link); - if (!stream) - return; - mutex_lock(&dm->dc_lock); if (dm->dc->caps.ips_support && dm->dc->ctx->dmub_srv->idle_allowed) { dc_allow_idle_optimizations(dm->dc, false); @@ -5477,10 +5547,8 @@ static void amdgpu_dm_backlight_set_leve AUX_BL_DEFAULT_TRANSITION_TIME_MS, false, true); } else { /* power module uses millipercent */ - get_brightness_range(caps, &min, &max); - brightness = DIV_ROUND_CLOSEST(brightness * 100, (max - min)) * 1000; rc = mod_power_set_backlight_percent(dm->power_module, stream, - brightness, 0, false); + millipercent, 0, false); } /*