From: Ivan Lipski <ivan.lip...@amd.com>

[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.

Reviewed-by: Sun peng (Leo) Li <sunpeng...@amd.com>
Signed-off-by: Ivan Lipski <ivan.lip...@amd.com>
Signed-off-by: Alex Hung <alex.h...@amd.com>
Tested-by: Dan Wheeler <daniel.whee...@amd.com>
---
 .../drm/amd/display/dc/dpp/dcn10/dcn10_dpp.c  |  9 +++
 .../drm/amd/display/dc/dpp/dcn10/dcn10_dpp.h  |  2 +
 .../drm/amd/display/dc/dpp/dcn30/dcn30_dpp.c  |  1 +
 .../amd/display/dc/hwss/dcn314/dcn314_hwseq.c | 72 +++++++++++++++++++
 .../amd/display/dc/hwss/dcn314/dcn314_hwseq.h |  2 +
 .../amd/display/dc/hwss/dcn314/dcn314_init.c  |  1 +
 drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h   |  3 +
 7 files changed, 90 insertions(+)

diff --git a/drivers/gpu/drm/amd/display/dc/dpp/dcn10/dcn10_dpp.c 
b/drivers/gpu/drm/amd/display/dc/dpp/dcn10/dcn10_dpp.c
index 75fb77bca83b..01480a04f85e 100644
--- a/drivers/gpu/drm/amd/display/dc/dpp/dcn10/dcn10_dpp.c
+++ b/drivers/gpu/drm/amd/display/dc/dpp/dcn10/dcn10_dpp.c
@@ -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,
diff --git a/drivers/gpu/drm/amd/display/dc/dpp/dcn10/dcn10_dpp.h 
b/drivers/gpu/drm/amd/display/dc/dpp/dcn10/dcn10_dpp.h
index c48139bed11f..f466182963f7 100644
--- a/drivers/gpu/drm/amd/display/dc/dpp/dcn10/dcn10_dpp.h
+++ b/drivers/gpu/drm/amd/display/dc/dpp/dcn10/dcn10_dpp.h
@@ -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
diff --git a/drivers/gpu/drm/amd/display/dc/dpp/dcn30/dcn30_dpp.c 
b/drivers/gpu/drm/amd/display/dc/dpp/dcn30/dcn30_dpp.c
index 2d70586cef40..09be2a90cc79 100644
--- a/drivers/gpu/drm/amd/display/dc/dpp/dcn30/dcn30_dpp.c
+++ b/drivers/gpu/drm/amd/display/dc/dpp/dcn30/dcn30_dpp.c
@@ -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,
 };
 
 
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_hwseq.c 
b/drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_hwseq.c
index e68f21fd5f0f..560984533950 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_hwseq.c
@@ -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;
+       }
+}
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_hwseq.h 
b/drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_hwseq.h
index 2305ad282f21..6c072d0274ea 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_hwseq.h
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_hwseq.h
@@ -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__ */
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_init.c 
b/drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_init.c
index a99145a30230..79faab1125d4 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_init.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_init.c
@@ -142,6 +142,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,
diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h 
b/drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h
index 0c5675d1c593..1b7c085dc2cc 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h
@@ -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);
+
 };
 
 
-- 
2.43.0

Reply via email to