]> www.infradead.org Git - users/griffoul/linux.git/commitdiff
drm/amd/display: Clear the CUR_ENABLE register on DCN314 w/out DPP PG
authorIvan Lipski <ivan.lipski@amd.com>
Wed, 20 Aug 2025 19:46:52 +0000 (15:46 -0400)
committerAlex Deucher <alexander.deucher@amd.com>
Fri, 29 Aug 2025 15:15:08 +0000 (11:15 -0400)
[Why&How]
ON DCN314, clearing DPP SW structure without power gating it can cause a
double cursor in full screen with non-native scaling.

A W/A that clears CURSOR0_CONTROL cursor_enable flag if
dcn10_plane_atomic_power_down is called and DPP power gating is disabled.

Closes: https://gitlab.freedesktop.org/drm/amd/-/issues/4168
Reviewed-by: Sun peng (Leo) Li <sunpeng.li@amd.com>
Signed-off-by: Ivan Lipski <ivan.lipski@amd.com>
Signed-off-by: Alex Hung <alex.hung@amd.com>
Tested-by: Dan Wheeler <daniel.wheeler@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
(cherry picked from commit 645f74f1dc119dad5a2c7bbc05cc315e76883011)
Cc: stable@vger.kernel.org
drivers/gpu/drm/amd/display/dc/dpp/dcn10/dcn10_dpp.c
drivers/gpu/drm/amd/display/dc/dpp/dcn10/dcn10_dpp.h
drivers/gpu/drm/amd/display/dc/dpp/dcn30/dcn30_dpp.c
drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_hwseq.c
drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_hwseq.h
drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_init.c
drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h

index 75fb77bca83ba23f027d093645a928556aa17f37..01480a04f85ef52680bc0eb2bb946ea36b42c72e 100644 (file)
@@ -520,6 +520,15 @@ void dpp1_dppclk_control(
                REG_UPDATE(DPP_CONTROL, DPP_CLOCK_ENABLE, 0);
 }
 
+void dpp_force_disable_cursor(struct dpp *dpp_base)
+{
+       struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base);
+
+       /* Force disable cursor */
+       REG_UPDATE(CURSOR0_CONTROL, CUR0_ENABLE, 0);
+       dpp_base->pos.cur0_ctl.bits.cur0_enable = 0;
+}
+
 static const struct dpp_funcs dcn10_dpp_funcs = {
                .dpp_read_state = dpp_read_state,
                .dpp_reset = dpp_reset,
index c48139bed11f513df8accf89e3d4aaf1f1e04c9b..f466182963f756ff275c69b935b1de0eb19960d3 100644 (file)
@@ -1525,4 +1525,6 @@ void dpp1_construct(struct dcn10_dpp *dpp1,
 
 void dpp1_cm_get_gamut_remap(struct dpp *dpp_base,
                             struct dpp_grph_csc_adjustment *adjust);
+void dpp_force_disable_cursor(struct dpp *dpp_base);
+
 #endif
index 2d70586cef4027d0bc21b2eba595248f29dae9af..09be2a90cc79dcdcbdd3f9d394c550ec2d2cc838 100644 (file)
@@ -1494,6 +1494,7 @@ static struct dpp_funcs dcn30_dpp_funcs = {
        .dpp_dppclk_control             = dpp1_dppclk_control,
        .dpp_set_hdr_multiplier         = dpp3_set_hdr_multiplier,
        .dpp_get_gamut_remap            = dpp3_cm_get_gamut_remap,
+       .dpp_force_disable_cursor       = dpp_force_disable_cursor,
 };
 
 
index e68f21fd5f0fb498699d8ecd688fb552e1577a86..5609845339505538c137a22cc056b3b6fe03cb8c 100644 (file)
@@ -528,3 +528,75 @@ void dcn314_disable_link_output(struct dc_link *link,
 
        apply_symclk_on_tx_off_wa(link);
 }
+
+/**
+ * dcn314_dpp_pg_control - DPP power gate control.
+ *
+ * @hws: dce_hwseq reference.
+ * @dpp_inst: DPP instance reference.
+ * @power_on: true if we want to enable power gate, false otherwise.
+ *
+ * Enable or disable power gate in the specific DPP instance.
+ * If power gating is disabled, will force disable cursor in the DPP instance.
+ */
+void dcn314_dpp_pg_control(
+               struct dce_hwseq *hws,
+               unsigned int dpp_inst,
+               bool power_on)
+{
+       uint32_t power_gate = power_on ? 0 : 1;
+       uint32_t pwr_status = power_on ? 0 : 2;
+
+
+       if (hws->ctx->dc->debug.disable_dpp_power_gate) {
+               /* Workaround for DCN314 with disabled power gating */
+               if (!power_on) {
+
+                       /* Force disable cursor if power gating is disabled */
+                       struct dpp *dpp = hws->ctx->dc->res_pool->dpps[dpp_inst];
+                       if (dpp && dpp->funcs->dpp_force_disable_cursor)
+                               dpp->funcs->dpp_force_disable_cursor(dpp);
+               }
+               return;
+       }
+       if (REG(DOMAIN1_PG_CONFIG) == 0)
+               return;
+
+       switch (dpp_inst) {
+       case 0: /* DPP0 */
+               REG_UPDATE(DOMAIN1_PG_CONFIG,
+                               DOMAIN1_POWER_GATE, power_gate);
+
+               REG_WAIT(DOMAIN1_PG_STATUS,
+                               DOMAIN1_PGFSM_PWR_STATUS, pwr_status,
+                               1, 1000);
+               break;
+       case 1: /* DPP1 */
+               REG_UPDATE(DOMAIN3_PG_CONFIG,
+                               DOMAIN3_POWER_GATE, power_gate);
+
+               REG_WAIT(DOMAIN3_PG_STATUS,
+                               DOMAIN3_PGFSM_PWR_STATUS, pwr_status,
+                               1, 1000);
+               break;
+       case 2: /* DPP2 */
+               REG_UPDATE(DOMAIN5_PG_CONFIG,
+                               DOMAIN5_POWER_GATE, power_gate);
+
+               REG_WAIT(DOMAIN5_PG_STATUS,
+                               DOMAIN5_PGFSM_PWR_STATUS, pwr_status,
+                               1, 1000);
+               break;
+       case 3: /* DPP3 */
+               REG_UPDATE(DOMAIN7_PG_CONFIG,
+                               DOMAIN7_POWER_GATE, power_gate);
+
+               REG_WAIT(DOMAIN7_PG_STATUS,
+                               DOMAIN7_PGFSM_PWR_STATUS, pwr_status,
+                               1, 1000);
+               break;
+       default:
+               BREAK_TO_DEBUGGER();
+               break;
+       }
+}
index 2305ad282f218b3d304ca92b0e5e7e2d61695d6a..6c072d0274ea373c1aa98f7624b6fe3068a53b3b 100644 (file)
@@ -47,4 +47,6 @@ void dcn314_dpp_root_clock_control(struct dce_hwseq *hws, unsigned int dpp_inst,
 
 void dcn314_disable_link_output(struct dc_link *link, const struct link_resource *link_res, enum signal_type signal);
 
+void dcn314_dpp_pg_control(struct dce_hwseq *hws, unsigned int dpp_inst, bool power_on);
+
 #endif /* __DC_HWSS_DCN314_H__ */
index f5112742edf9b4e7722bbbbb041e81551644e121..9f454fa90e65db408d9e85a33702a51f1d62c290 100644 (file)
@@ -141,6 +141,7 @@ static const struct hwseq_private_funcs dcn314_private_funcs = {
        .enable_power_gating_plane = dcn314_enable_power_gating_plane,
        .dpp_root_clock_control = dcn314_dpp_root_clock_control,
        .hubp_pg_control = dcn31_hubp_pg_control,
+       .dpp_pg_control = dcn314_dpp_pg_control,
        .program_all_writeback_pipes_in_tree = dcn30_program_all_writeback_pipes_in_tree,
        .update_odm = dcn314_update_odm,
        .dsc_pg_control = dcn314_dsc_pg_control,
index 0c5675d1c5936843862b88229d029ee60a5ecdbf..1b7c085dc2cc1e578caedac783d390fb812fb582 100644 (file)
@@ -349,6 +349,9 @@ struct dpp_funcs {
                struct dpp *dpp_base,
                enum dc_color_space color_space,
                struct dc_csc_transform cursor_csc_color_matrix);
+
+       void (*dpp_force_disable_cursor)(struct dpp *dpp_base);
+
 };