]> git.hungrycats.org Git - linux/commitdiff
drm/amd/display: Fix VABC Init and OLED Support
authorIswara Nagulendran <Iswara.Nagulendran@amd.com>
Tue, 16 Jun 2026 19:31:03 +0000 (15:31 -0400)
committerAlex Deucher <alexander.deucher@amd.com>
Wed, 15 Jul 2026 13:15:39 +0000 (09:15 -0400)
[Why]
TCONs supporting VESA AUX Backlight does not always
support VESA Smooth Brightness. Driver software
needs to implement smooth brightness by periodically
updating the brightness by small steps. Driver
implementation is completed and verified on LCD
panels but solution is missing for OLED panels.

[How]
Updated driver to include smooth brightness for
OLED panels using VESA Aux Backlight.
Revert original workaround for VABC on oled issue,
as it is no longer needed.
Add VABC backlight Initialization sequence from
driver side.
Add fix to remove conflict between FW and driver
backlight programming for future ASIC.
Enable VABC for all future asic revisions.

Reviewed-by: Anthony Koo <anthony.koo@amd.com>
Reviewed-by: Dillon Varone <dillon.varone@amd.com>
Signed-off-by: Iswara Nagulendran <Iswara.Nagulendran@amd.com>
Signed-off-by: George Zhang <george.zhang@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/display/dc/hwss/dcn31/dcn31_hwseq.c
drivers/gpu/drm/amd/display/dc/hwss/dcn42/dcn42_hwseq.c
drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.c
drivers/gpu/drm/amd/display/modules/power/power_abm.c

index e72e10c276de0b04463c09c870257aa926ac1ff6..b6f3c0480ab6c0f5cd79e83d07547045a54fd5ec 100644 (file)
@@ -719,6 +719,34 @@ static void dmub_abm_set_backlight(struct dc_context *dc,
        dc_wake_and_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
 }
 
+static bool dmub_cacp_set_backlight(struct dc_context *dc,
+       struct set_backlight_level_params *backlight_level_params,
+       unsigned int panel_inst)
+{
+       union dmub_rb_cmd cmd;
+
+       memset(&cmd, 0, sizeof(cmd));
+       cmd.cacp_set_backlight.header.type = DMUB_CMD__CACP;
+       cmd.cacp_set_backlight.header.sub_type = DMUB_CMD__CACP_SET_BACKLIGHT;
+       cmd.cacp_set_backlight.cacp_set_backlight_data.aux_inst = backlight_level_params->aux_inst;
+       cmd.cacp_set_backlight.cacp_set_backlight_data.frame_ramp = backlight_level_params->frame_ramp;
+       cmd.cacp_set_backlight.cacp_set_backlight_data.backlight_user_level =
+               backlight_level_params->backlight_pwm_u16_16;
+       cmd.cacp_set_backlight.cacp_set_backlight_data.backlight_control_type =
+               (enum dmub_backlight_control_type)backlight_level_params->control_type;
+       cmd.cacp_set_backlight.cacp_set_backlight_data.min_luminance = backlight_level_params->min_luminance;
+       cmd.cacp_set_backlight.cacp_set_backlight_data.max_luminance = backlight_level_params->max_luminance;
+       cmd.cacp_set_backlight.cacp_set_backlight_data.min_backlight_pwm = backlight_level_params->min_backlight_pwm;
+       cmd.cacp_set_backlight.cacp_set_backlight_data.max_backlight_pwm = backlight_level_params->max_backlight_pwm;
+       cmd.cacp_set_backlight.cacp_set_backlight_data.version = DMUB_CMD_CACP_CONTROL_VERSION_1;
+       cmd.cacp_set_backlight.cacp_set_backlight_data.panel_mask = (0x01 << panel_inst);
+       cmd.cacp_set_backlight.header.payload_bytes = sizeof(struct dmub_cmd_cacp_set_backlight_data);
+
+       dc_wake_and_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
+
+       return true;
+}
+
 bool dcn31_set_backlight_level(struct pipe_ctx *pipe_ctx,
        struct set_backlight_level_params *backlight_level_params)
 {
@@ -746,8 +774,19 @@ bool dcn31_set_backlight_level(struct pipe_ctx *pipe_ctx,
                        panel_cntl->inst,
                        panel_cntl->pwrseq_inst);
 
-       if (backlight_level_params->control_type != BACKLIGHT_CONTROL_AMD_AUX)
+       if (link && link->panel_type == PANEL_TYPE_OLED) {
+               /* For OLED panel with AMD AUX, skip set backlight call */
+               if (backlight_level_params->control_type == BACKLIGHT_CONTROL_VESA_AUX)
+                       dmub_cacp_set_backlight(dc, backlight_level_params, panel_cntl->inst);
+       } else if (link && link->panel_type == PANEL_TYPE_MINILED) {
+               /* For MiniLED panel we need to check if CACP or ABM is being used */
+               if (link->panel_config.cacp.cacp_supported)
+                       dmub_cacp_set_backlight(dc, backlight_level_params, panel_cntl->inst);
+               else
+                       dmub_abm_set_backlight(dc, backlight_level_params, panel_cntl->inst);
+       } else {
                dmub_abm_set_backlight(dc, backlight_level_params, panel_cntl->inst);
+       }
 
        return true;
 }
index f415473517d4c0f83d3ea96f88304a812634299d..cc8e96ffe7d1d99162bbf8f82b95779731c87d7c 100644 (file)
@@ -281,6 +281,8 @@ void dcn42_init_hw(struct dc *dc)
                dc->caps.dmub_caps.psr = dc->ctx->dmub_srv->dmub->feature_caps.psr;
                dc->caps.dmub_caps.mclk_sw = dc->ctx->dmub_srv->dmub->feature_caps.fw_assisted_mclk_switch_ver > 0;
                dc->caps.dmub_caps.fams_ver = dc->ctx->dmub_srv->dmub->feature_caps.fw_assisted_mclk_switch_ver;
+               dc->caps.dmub_caps.aux_backlight_support =
+                       dc->ctx->dmub_srv->dmub->feature_caps.abm_aux_backlight_support;
 
                /* sw and fw FAMS versions must match for support */
                dc->debug.fams2_config.bits.enable &=
index baf57692bbb5dac674c7332a9a02729bf54d585d..16951a9550f25d3dbb68483d0df09120693c8c5d 100644 (file)
@@ -161,9 +161,7 @@ bool edp_set_backlight_level_nits(struct dc_link *link,
        if (link->is_dds && !link->dpcd_caps.panel_luminance_control)
                return true;
 
-       // use internal backlight control if dmub capabilities are not present
-       if (link->backlight_control_type == BACKLIGHT_CONTROL_VESA_AUX &&
-               !link->dc->caps.dmub_caps.aux_backlight_support) {
+       if (link->backlight_control_type == BACKLIGHT_CONTROL_VESA_AUX) {
                uint8_t backlight_enable = 0;
                struct target_luminance_value *target_luminance = NULL;
 
@@ -273,10 +271,11 @@ bool edp_backlight_enable_aux(struct dc_link *link, bool enable)
 
        if (link->is_dds)
                return true;
-       if (core_link_write_dpcd(link, DP_SOURCE_BACKLIGHT_ENABLE,
-               &backlight_enable, 1) != DC_OK)
-               return false;
-
+       if (!link->dpcd_caps.panel_luminance_control) {
+               if (core_link_write_dpcd(link, DP_SOURCE_BACKLIGHT_ENABLE,
+                       &backlight_enable, 1) != DC_OK)
+                       return false;
+       }
        return true;
 }
 
index 5b972f04bf7ae189e8b6b6fcc5c28a901050db9b..b26ceaba940d290d1c0e30d1777a53197f78ad35 100644 (file)
@@ -716,8 +716,9 @@ void mod_power_update_backlight_on_mode_change(
 {
     struct set_backlight_level_params backlight_level_params = { 0 };
 
-               if (link->dpcd_sink_ext_caps.bits.hdr_aux_backlight_control == 1 ||
-                       link->dpcd_sink_ext_caps.bits.sdr_aux_backlight_control == 1)
+               if ((link->dpcd_sink_ext_caps.bits.hdr_aux_backlight_control == 1 ||
+                       link->dpcd_sink_ext_caps.bits.sdr_aux_backlight_control == 1) &&
+                       link->backlight_control_type == BACKLIGHT_CONTROL_AMD_AUX)
                        dc_link_set_backlight_level_nits(link, core_power->bl_state[panel_inst].isHDR,
                                core_power->bl_state[panel_inst].backlight_millinit, 0);
 
@@ -746,6 +747,11 @@ static bool set_backlight_millinits_aux(struct core_power *core_power,
 
        link = dc_stream_get_link(stream);
 
+       // only use internal backlight control if dmub capabilities are not present
+       if (link->backlight_control_type == BACKLIGHT_CONTROL_VESA_AUX &&
+               link->dc->caps.dmub_caps.aux_backlight_support)
+               return true;
+
        return dc_link_set_backlight_level_nits(link, core_power->bl_state[inst].isHDR,
                        backlight_millinits, transition_time_millisec);
 }