drm/amd/display: Defer GAMCOR and DSCL power down sequence to vupdate
authorMichael Strauss <michael.strauss@amd.com>
Wed, 6 Oct 2021 19:50:10 +0000 (15:50 -0400)
committerAlex Deucher <alexander.deucher@amd.com>
Thu, 28 Oct 2021 18:26:15 +0000 (14:26 -0400)
[WHY]
Every other CM LUT power down sequence is deferred to next vupdate as
memory powerdown updates immediately while selecting LUTs is double
buffered.  Previous update to defer LUT power down missed GAMCOR and
DSCL, causing some visible flicker when entering/exiting fullscreen
video playback.

[HOW]
Update dpp deferred update loop to check for valid DPPs in res_pool
instead of referencing dcn_ip which turns out to not be populated during
runtime.  Move GAMCOR and DSCL powerdown to dpp deferred updates.

Reviewed-by: Haonan Wang <Haonan.Wang2@amd.com>
Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
Acked-by: Agustin Gutierrez <agustin.gutierrez@amd.com>
Signed-off-by: Michael Strauss <michael.strauss@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/display/dc/core/dc.c
drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c
drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dpp.c
drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dpp_cm.c
drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c
drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h

index 7def73b1c2620eb75321cbb435b42a0a00caff59..580aa3f1e4a40b1fe723c6082b20f024cbd76b1e 100644 (file)
@@ -1897,12 +1897,14 @@ static bool is_flip_pending_in_pipes(struct dc *dc, struct dc_state *context)
 static void process_deferred_updates(struct dc *dc)
 {
 #ifdef CONFIG_DRM_AMD_DC_DCN
-       int i;
+       int i = 0;
 
-       if (dc->debug.enable_mem_low_power.bits.cm)
+       if (dc->debug.enable_mem_low_power.bits.cm) {
+               ASSERT(dc->dcn_ip->max_num_dpp);
                for (i = 0; i < dc->dcn_ip->max_num_dpp; i++)
                        if (dc->res_pool->dpps[i]->funcs->dpp_deferred_update)
                                dc->res_pool->dpps[i]->funcs->dpp_deferred_update(dc->res_pool->dpps[i]);
+       }
 #endif
 }
 
index cb9767ddf93d3863190e414e4df57aaa96100cbb..44293d66b46bd66d7e28290da78a23996f7203f4 100644 (file)
@@ -205,9 +205,17 @@ static void dpp1_power_on_dscl(
        struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base);
 
        if (dpp->tf_regs->DSCL_MEM_PWR_CTRL) {
-               REG_UPDATE(DSCL_MEM_PWR_CTRL, LUT_MEM_PWR_FORCE, power_on ? 0 : 3);
-               if (power_on)
+               if (power_on) {
+                       REG_UPDATE(DSCL_MEM_PWR_CTRL, LUT_MEM_PWR_FORCE, 0);
                        REG_WAIT(DSCL_MEM_PWR_STATUS, LUT_MEM_PWR_STATE, 0, 1, 5);
+               } else {
+                       if (dpp->base.ctx->dc->debug.enable_mem_low_power.bits.dscl) {
+                               dpp->base.ctx->dc->optimized_required = true;
+                               dpp->base.deferred_reg_writes.bits.disable_dscl = true;
+                       } else {
+                               REG_UPDATE(DSCL_MEM_PWR_CTRL, LUT_MEM_PWR_FORCE, 3);
+                       }
+               }
        }
 }
 
index ef5f6da5248a7c715289f86e7c33d4601354e474..c1d967ed6551138ea5b836e8c53abff8a8d6924a 100644 (file)
@@ -494,6 +494,20 @@ void dpp3_deferred_update(
        int bypass_state;
        struct dcn3_dpp *dpp = TO_DCN30_DPP(dpp_base);
 
+       if (dpp_base->deferred_reg_writes.bits.disable_dscl) {
+               REG_UPDATE(DSCL_MEM_PWR_CTRL, LUT_MEM_PWR_FORCE, 3);
+               dpp_base->deferred_reg_writes.bits.disable_dscl = false;
+       }
+
+       if (dpp_base->deferred_reg_writes.bits.disable_gamcor) {
+               REG_GET(CM_GAMCOR_CONTROL, CM_GAMCOR_MODE_CURRENT, &bypass_state);
+               if (bypass_state == 0) {        // only program if bypass was latched
+                       REG_UPDATE(CM_MEM_PWR_CTRL, GAMCOR_MEM_PWR_FORCE, 3);
+               } else
+                       ASSERT(0); // LUT select was updated again before vupdate
+               dpp_base->deferred_reg_writes.bits.disable_gamcor = false;
+       }
+
        if (dpp_base->deferred_reg_writes.bits.disable_blnd_lut) {
                REG_GET(CM_BLNDGAM_CONTROL, CM_BLNDGAM_MODE_CURRENT, &bypass_state);
                if (bypass_state == 0) {        // only program if bypass was latched
index 72c5687adc681c9a2b3edcd03580af178a988d53..387eec6161629e236f35d93d8655dc2b70ec7f1c 100644 (file)
@@ -136,9 +136,13 @@ static void dpp3_power_on_gamcor_lut(
        struct dcn3_dpp *dpp = TO_DCN30_DPP(dpp_base);
 
        if (dpp_base->ctx->dc->debug.enable_mem_low_power.bits.cm) {
-               REG_UPDATE(CM_MEM_PWR_CTRL, GAMCOR_MEM_PWR_FORCE, power_on ? 0 : 3);
-               if (power_on)
+               if (power_on) {
+                       REG_UPDATE(CM_MEM_PWR_CTRL, GAMCOR_MEM_PWR_FORCE, 0);
                        REG_WAIT(CM_MEM_PWR_STATUS, GAMCOR_MEM_PWR_STATE, 0, 1, 5);
+               } else {
+                       dpp_base->ctx->dc->optimized_required = true;
+                       dpp_base->deferred_reg_writes.bits.disable_gamcor = true;
+               }
        } else
                REG_SET(CM_MEM_PWR_CTRL, 0,
                                GAMCOR_MEM_PWR_DIS, power_on == true ? 0:1);
index 4f60b36000cbb62b782a2bae22107352bb66688b..6d812d5a1368fca2e67fe9d12beaf689eea97269 100644 (file)
@@ -2460,6 +2460,8 @@ static bool dcn31_resource_construct(
 
        dc->cap_funcs = cap_funcs;
 
+       dc->dcn_ip->max_num_dpp = dcn3_1_ip.max_num_dpp;
+
        DC_FP_END();
 
        return true;
index 9f12792b7e590148ec652bec3864e16d59b85e68..3ef7faa920528df154890487fda76531f5d8c02f 100644 (file)
@@ -34,6 +34,8 @@ union defer_reg_writes {
                bool disable_blnd_lut:1;
                bool disable_3dlut:1;
                bool disable_shaper:1;
+               bool disable_gamcor:1;
+               bool disable_dscl:1;
        } bits;
        uint32_t raw;
 };