Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/amd/display: On clock init, maintain DISPCLK freq

[Why]
On init if a display is connected, we need to maintain the DISPCLK
frequency Even though DPG_EN=1, the display still requires the correct
timing or it could cause audio corruption (if DISPCLK freq is reduced).

[How]
Read the current DISPCLK freq and request the same value to ensure the
timing is valid and unchanged.

Reviewed-by: Alvin Lee <alvin.lee2@amd.com>
Acked-by: Hamza Mahfooz <hamza.mahfooz@amd.com>
Signed-off-by: Chris Park <chris.park@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>

authored by

Chris Park and committed by
Alex Deucher
3838c673 3a69c170

+27 -1
+17
drivers/gpu/drm/amd/display/dc/clk_mgr/dcn401/dcn401_clk_mgr.c
··· 1459 1459 return dtb_ref_clk_khz; 1460 1460 } 1461 1461 1462 + static int dcn401_get_dispclk_from_dentist(struct clk_mgr *clk_mgr_base) 1463 + { 1464 + struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base); 1465 + uint32_t dispclk_wdivider; 1466 + int disp_divider; 1467 + 1468 + REG_GET(DENTIST_DISPCLK_CNTL, DENTIST_DISPCLK_WDIVIDER, &dispclk_wdivider); 1469 + disp_divider = dentist_get_divider_from_did(dispclk_wdivider); 1470 + 1471 + /* Return DISPCLK freq in Khz */ 1472 + if (disp_divider) 1473 + return (DENTIST_DIVIDER_RANGE_SCALE_FACTOR * clk_mgr->base.dentist_vco_freq_khz) / disp_divider; 1474 + 1475 + return 0; 1476 + } 1477 + 1462 1478 static struct clk_mgr_funcs dcn401_funcs = { 1463 1479 .get_dp_ref_clk_frequency = dce12_get_dp_ref_freq_khz, 1464 1480 .get_dtb_ref_clk_frequency = dcn401_get_dtb_ref_freq_khz, ··· 1488 1472 .are_clock_states_equal = dcn401_are_clock_states_equal, 1489 1473 .enable_pme_wa = dcn401_enable_pme_wa, 1490 1474 .is_smu_present = dcn401_is_smu_present, 1475 + .get_dispclk_from_dentist = dcn401_get_dispclk_from_dentist, 1491 1476 }; 1492 1477 1493 1478 struct clk_mgr_internal *dcn401_clk_mgr_construct(
+10 -1
drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c
··· 57 57 clocks->socclk_khz = dc->clk_mgr->bw_params->clk_table.entries[0].socclk_mhz * 1000; 58 58 clocks->dramclk_khz = dc->clk_mgr->bw_params->clk_table.entries[0].memclk_mhz * 1000; 59 59 clocks->dppclk_khz = dc->clk_mgr->bw_params->clk_table.entries[0].dppclk_mhz * 1000; 60 - clocks->dispclk_khz = dc->clk_mgr->bw_params->clk_table.entries[0].dispclk_mhz * 1000; 60 + if (dc->debug.disable_boot_optimizations) { 61 + clocks->dispclk_khz = dc->clk_mgr->bw_params->clk_table.entries[0].dispclk_mhz * 1000; 62 + } else { 63 + /* Even though DPG_EN = 1 for the connected display, it still requires the 64 + * correct timing so we cannot set DISPCLK to min freq or it could cause 65 + * audio corruption. Read current DISPCLK from DENTIST and request the same 66 + * freq to ensure that the timing is valid and unchanged. 67 + */ 68 + clocks->dispclk_khz = dc->clk_mgr->funcs->get_dispclk_from_dentist(dc->clk_mgr); 69 + } 61 70 clocks->ref_dtbclk_khz = dc->clk_mgr->bw_params->clk_table.entries[0].dtbclk_mhz * 1000; 62 71 clocks->fclk_p_state_change_support = true; 63 72 clocks->p_state_change_support = true;