]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
drm/amd/display: fix root clock disabled when DSC power gate disabled for DCN314
authorJing Zhou <Jing.Zhou@amd.com>
Thu, 16 Apr 2026 05:47:52 +0000 (13:47 +0800)
committerAlex Deucher <alexander.deucher@amd.com>
Tue, 28 Apr 2026 18:30:43 +0000 (14:30 -0400)
[Why]
When set debug.disable_dsc_power_gate = true, the original code
uses an early return to skip the power gate sequence and root
clock enable and disable.

For this case, install new driver without uninstall old driver.
The sequence like below:
1. On the power-off path, the old driver will power gate dsc and
   disable_dsc() (root clock disable) due to
   debug.disable_dsc_power_gate = false.
2. On the power-on path, the new driver will force power on dsc but skip
   enable_dsc() (root clock enable) due to
   debug.disable_dsc_power_gate = true.

Finally, when mode needs DSC but the root clock is disabled, underflow
happened.

[How]
- Moving enable_dsc() before the disable_dsc_power_gate check so the
  root clock is always enabled on the power-on path.
- Replacing the early return with a goto that skips only the power gate
  register writes, allowing disable_dsc() to still execute on the
  power-off path.

Reviewed-by: Aric Cyr <aric.cyr@amd.com>
Signed-off-by: Jing Zhou <Jing.Zhou@amd.com>
Signed-off-by: Tom Chung <chiahsuan.chung@amd.com>
Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_hwseq.c

index 1e856ee508f1237d1210e761ba62d4f329d8ef43..408d417318c286da1747292f64ce48fb60352b37 100644 (file)
@@ -232,60 +232,60 @@ void dcn314_dsc_pg_control(
        uint32_t pwr_status = power_on ? 0 : 2;
        uint32_t org_ip_request_cntl = 0;
 
-       if (hws->ctx->dc->debug.disable_dsc_power_gate)
-               return;
-
        if (hws->ctx->dc->debug.root_clock_optimization.bits.dsc &&
                hws->ctx->dc->res_pool->dccg->funcs->enable_dsc &&
                power_on)
                hws->ctx->dc->res_pool->dccg->funcs->enable_dsc(
                        hws->ctx->dc->res_pool->dccg, dsc_inst);
 
-       REG_GET(DC_IP_REQUEST_CNTL, IP_REQUEST_EN, &org_ip_request_cntl);
-       if (org_ip_request_cntl == 0)
-               REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 1);
-
-       switch (dsc_inst) {
-       case 0: /* DSC0 */
-               REG_UPDATE(DOMAIN16_PG_CONFIG,
-                               DOMAIN_POWER_GATE, power_gate);
-
-               REG_WAIT(DOMAIN16_PG_STATUS,
-                               DOMAIN_PGFSM_PWR_STATUS, pwr_status,
-                               1, 1000);
-               break;
-       case 1: /* DSC1 */
-               REG_UPDATE(DOMAIN17_PG_CONFIG,
-                               DOMAIN_POWER_GATE, power_gate);
-
-               REG_WAIT(DOMAIN17_PG_STATUS,
-                               DOMAIN_PGFSM_PWR_STATUS, pwr_status,
-                               1, 1000);
-               break;
-       case 2: /* DSC2 */
-               REG_UPDATE(DOMAIN18_PG_CONFIG,
-                               DOMAIN_POWER_GATE, power_gate);
-
-               REG_WAIT(DOMAIN18_PG_STATUS,
-                               DOMAIN_PGFSM_PWR_STATUS, pwr_status,
-                               1, 1000);
-               break;
-       case 3: /* DSC3 */
-               REG_UPDATE(DOMAIN19_PG_CONFIG,
-                               DOMAIN_POWER_GATE, power_gate);
+       if (!hws->ctx->dc->debug.disable_dsc_power_gate) {
+
+               REG_GET(DC_IP_REQUEST_CNTL, IP_REQUEST_EN, &org_ip_request_cntl);
+               if (org_ip_request_cntl == 0)
+                       REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 1);
+
+               switch (dsc_inst) {
+               case 0: /* DSC0 */
+                       REG_UPDATE(DOMAIN16_PG_CONFIG,
+                                       DOMAIN_POWER_GATE, power_gate);
+
+                       REG_WAIT(DOMAIN16_PG_STATUS,
+                                       DOMAIN_PGFSM_PWR_STATUS, pwr_status,
+                                       1, 1000);
+                       break;
+               case 1: /* DSC1 */
+                       REG_UPDATE(DOMAIN17_PG_CONFIG,
+                                       DOMAIN_POWER_GATE, power_gate);
+
+                       REG_WAIT(DOMAIN17_PG_STATUS,
+                                       DOMAIN_PGFSM_PWR_STATUS, pwr_status,
+                                       1, 1000);
+                       break;
+               case 2: /* DSC2 */
+                       REG_UPDATE(DOMAIN18_PG_CONFIG,
+                                       DOMAIN_POWER_GATE, power_gate);
+
+                       REG_WAIT(DOMAIN18_PG_STATUS,
+                                       DOMAIN_PGFSM_PWR_STATUS, pwr_status,
+                                       1, 1000);
+                       break;
+               case 3: /* DSC3 */
+                       REG_UPDATE(DOMAIN19_PG_CONFIG,
+                                       DOMAIN_POWER_GATE, power_gate);
+
+                       REG_WAIT(DOMAIN19_PG_STATUS,
+                                       DOMAIN_PGFSM_PWR_STATUS, pwr_status,
+                                       1, 1000);
+                       break;
+               default:
+                       BREAK_TO_DEBUGGER();
+                       break;
+               }
 
-               REG_WAIT(DOMAIN19_PG_STATUS,
-                               DOMAIN_PGFSM_PWR_STATUS, pwr_status,
-                               1, 1000);
-               break;
-       default:
-               BREAK_TO_DEBUGGER();
-               break;
+               if (org_ip_request_cntl == 0)
+                       REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 0);
        }
 
-       if (org_ip_request_cntl == 0)
-               REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 0);
-
        if (hws->ctx->dc->debug.root_clock_optimization.bits.dsc) {
                if (hws->ctx->dc->res_pool->dccg->funcs->disable_dsc && !power_on)
                        hws->ctx->dc->res_pool->dccg->funcs->disable_dsc(