summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_dccg.c
diff options
context:
space:
mode:
authorYongqiang Sun <yongqiang.sun@amd.com>2020-11-01 13:05:11 -0500
committerAlex Deucher <alexander.deucher@amd.com>2020-11-10 14:26:18 -0500
commit880af2eaedd3f63d413a439ef29edcc0a5fbdc73 (patch)
tree69f4e83a0bc2aa02ccb6a10d3d326d04b9a309f4 /drivers/gpu/drm/amd/display/dc/dcn21/dcn21_dccg.c
parent4b0b1d05265b044472a23b76d5fda8d7fb218144 (diff)
downloadlinux-stable-880af2eaedd3f63d413a439ef29edcc0a5fbdc73.tar.gz
linux-stable-880af2eaedd3f63d413a439ef29edcc0a5fbdc73.tar.bz2
linux-stable-880af2eaedd3f63d413a439ef29edcc0a5fbdc73.zip
drm/amd/display: cap dpp dto phase not more than modulo.
[Why] 4K monitor shows corruption if dpp dto phase is larger than modulo. [How] cap phase value never larger than modulo. Signed-off-by: Yongqiang Sun <yongqiang.sun@amd.com> Acked-by: Bindu Ramamurthy <bindu.r@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers/gpu/drm/amd/display/dc/dcn21/dcn21_dccg.c')
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn21/dcn21_dccg.c46
1 files changed, 25 insertions, 21 deletions
diff --git a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_dccg.c b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_dccg.c
index f9e3a2337fbf..60cf3ff68cb0 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_dccg.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_dccg.c
@@ -50,43 +50,47 @@ void dccg21_update_dpp_dto(struct dccg *dccg, int dpp_inst, int req_dppclk)
if (dccg->ref_dppclk) {
int ref_dppclk = dccg->ref_dppclk;
int modulo = ref_dppclk / 10000;
+ int phase;
if (req_dppclk) {
- int phase;
-
/*
* program DPP DTO phase and modulo as below
- * phase = dpp_pipe_clk_mhz / 10
- * module = dpp_global_clk_mhz / 10
- * dmub FW will read phase value to
- * determine minimum dpp clk and notify smu
- * to set clks for more power saving in PSR state
+ * phase = ceiling(dpp_pipe_clk_mhz / 10)
+ * module = trunc(dpp_global_clk_mhz / 10)
+ *
+ * storing frequencies in registers allow dmcub fw
+ * to run time lower clocks when possible for power saving
+ *
+ * ceiling phase and truncate modulo guarentees the divided
+ * down per pipe dpp clock has high enough frequency
*/
phase = (req_dppclk + 9999) / 10000;
- if (phase > 0xff) {
- ASSERT(false);
- phase = 0xff;
+ if (phase > modulo) {
+ /* phase > modulo result in screen corruption
+ * ie phase = 30, mod = 29 for 4k@60 HDMI
+ * in these case we don't want pipe clock to be divided
+ */
+ phase = modulo;
}
-
- REG_SET_2(DPPCLK_DTO_PARAM[dpp_inst], 0,
- DPPCLK0_DTO_PHASE, phase,
- DPPCLK0_DTO_MODULO, modulo);
- REG_UPDATE(DPPCLK_DTO_CTRL,
- DPPCLK_DTO_ENABLE[dpp_inst], 1);
} else {
/*
* set phase to 10 if dpp isn't used to
* prevent hard hang if access dpp register
* on unused pipe
+ *
+ * DTO should be on to divide down un-used
+ * pipe clock for power saving
*/
- REG_SET_2(DPPCLK_DTO_PARAM[dpp_inst], 0,
- DPPCLK0_DTO_PHASE, 10,
+ phase = 10;
+ }
+
+ REG_SET_2(DPPCLK_DTO_PARAM[dpp_inst], 0,
+ DPPCLK0_DTO_PHASE, phase,
DPPCLK0_DTO_MODULO, modulo);
- REG_UPDATE(DPPCLK_DTO_CTRL,
- DPPCLK_DTO_ENABLE[dpp_inst], 0);
- }
+ REG_UPDATE(DPPCLK_DTO_CTRL,
+ DPPCLK_DTO_ENABLE[dpp_inst], 1);
}
dccg->pipe_dppclk_khz[dpp_inst] = req_dppclk;