dri-devel Archive on lore.kernel.org
 help / color / mirror / Atom feed
From: Sasha Levin <sashal@kernel.org>
To: linux-kernel@vger.kernel.org, stable@vger.kernel.org
Cc: Sasha Levin <sashal@kernel.org>,
	Wesley Chalmers <Wesley.Chalmers@amd.com>,
	Anson Jacob <Anson.Jacob@amd.com>,
	amd-gfx@lists.freedesktop.org,
	Daniel Wheeler <daniel.wheeler@amd.com>,
	Dmytro Laktyushkin <Dmytro.Laktyushkin@amd.com>,
	dri-devel@lists.freedesktop.org,
	Alex Deucher <alexander.deucher@amd.com>
Subject: [PATCH AUTOSEL 5.13 112/189] drm/amd/display: Cover edge-case when changing DISPCLK WDIVIDER
Date: Tue,  6 Jul 2021 07:12:52 -0400	[thread overview]
Message-ID: <20210706111409.2058071-112-sashal@kernel.org> (raw)
In-Reply-To: <20210706111409.2058071-1-sashal@kernel.org>

From: Wesley Chalmers <Wesley.Chalmers@amd.com>

[ Upstream commit 78ebca321999699f30ea19029726d1a3908b395f ]

[WHY]
When changing the DISPCLK_WDIVIDER value from 126 to 127, the change in
clock rate is too great for the FIFOs to handle. This can cause visible
corruption during clock change.

HW has handed down this register sequence to fix the issue.

[HOW]
The sequence, from HW:
a.	127 -> 126
Read  DIG_FIFO_CAL_AVERAGE_LEVEL
FIFO level N = DIG_FIFO_CAL_AVERAGE_LEVEL / 4
Set DCCG_FIFO_ERRDET_OVR_EN = 1
Write 1 to OTGx_DROP_PIXEL for (N-4) times
Set DCCG_FIFO_ERRDET_OVR_EN = 0
Write DENTIST_DISPCLK_RDIVIDER = 126

Because of frequency stepping, sequence a can be executed to change the
divider from 127 to any other divider value.

b.	126 -> 127
Read  DIG_FIFO_CAL_AVERAGE_LEVEL
FIFO level N = DIG_FIFO_CAL_AVERAGE_LEVEL / 4
Set DCCG_FIFO_ERRDET_OVR_EN = 1
Write 1 to OTGx_ADD_PIXEL for (12-N) times
Set DCCG_FIFO_ERRDET_OVR_EN = 0
Write DENTIST_DISPCLK_RDIVIDER = 127

Because of frequency stepping, divider must first be set from any other
divider value to 126 before executing sequence b.

Signed-off-by: Wesley Chalmers <Wesley.Chalmers@amd.com>
Reviewed-by: Dmytro Laktyushkin <Dmytro.Laktyushkin@amd.com>
Acked-by: Anson Jacob <Anson.Jacob@amd.com>
Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 .../display/dc/clk_mgr/dcn20/dcn20_clk_mgr.c  | 68 ++++++++++++++++++-
 .../display/dc/clk_mgr/dcn20/dcn20_clk_mgr.h  |  3 +-
 .../display/dc/clk_mgr/dcn30/dcn30_clk_mgr.c  |  4 +-
 3 files changed, 69 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn20/dcn20_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn20/dcn20_clk_mgr.c
index 372d53b5a34d..3d335b4e9891 100644
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn20/dcn20_clk_mgr.c
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn20/dcn20_clk_mgr.c
@@ -123,7 +123,7 @@ void dcn20_update_clocks_update_dpp_dto(struct clk_mgr_internal *clk_mgr,
 	}
 }
 
-void dcn20_update_clocks_update_dentist(struct clk_mgr_internal *clk_mgr)
+void dcn20_update_clocks_update_dentist(struct clk_mgr_internal *clk_mgr, struct dc_state *context)
 {
 	int dpp_divider = DENTIST_DIVIDER_RANGE_SCALE_FACTOR
 			* clk_mgr->base.dentist_vco_freq_khz / clk_mgr->base.clks.dppclk_khz;
@@ -132,6 +132,68 @@ void dcn20_update_clocks_update_dentist(struct clk_mgr_internal *clk_mgr)
 
 	uint32_t dppclk_wdivider = dentist_get_did_from_divider(dpp_divider);
 	uint32_t dispclk_wdivider = dentist_get_did_from_divider(disp_divider);
+	uint32_t current_dispclk_wdivider;
+	uint32_t i;
+
+	REG_GET(DENTIST_DISPCLK_CNTL,
+			DENTIST_DISPCLK_WDIVIDER, &current_dispclk_wdivider);
+
+	/* When changing divider to or from 127, some extra programming is required to prevent corruption */
+	if (current_dispclk_wdivider == 127 && dispclk_wdivider != 127) {
+		for (i = 0; i < clk_mgr->base.ctx->dc->res_pool->pipe_count; i++) {
+			struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
+			uint32_t fifo_level;
+			struct dccg *dccg = clk_mgr->base.ctx->dc->res_pool->dccg;
+			struct stream_encoder *stream_enc = pipe_ctx->stream_res.stream_enc;
+			int32_t N;
+			int32_t j;
+
+			if (!pipe_ctx->stream)
+				continue;
+			/* Virtual encoders don't have this function */
+			if (!stream_enc->funcs->get_fifo_cal_average_level)
+				continue;
+			fifo_level = stream_enc->funcs->get_fifo_cal_average_level(
+					stream_enc);
+			N = fifo_level / 4;
+			dccg->funcs->set_fifo_errdet_ovr_en(
+					dccg,
+					true);
+			for (j = 0; j < N - 4; j++)
+				dccg->funcs->otg_drop_pixel(
+						dccg,
+						pipe_ctx->stream_res.tg->inst);
+			dccg->funcs->set_fifo_errdet_ovr_en(
+					dccg,
+					false);
+		}
+	} else if (dispclk_wdivider == 127 && current_dispclk_wdivider != 127) {
+		REG_UPDATE(DENTIST_DISPCLK_CNTL,
+				DENTIST_DISPCLK_WDIVIDER, 126);
+		REG_WAIT(DENTIST_DISPCLK_CNTL, DENTIST_DISPCLK_CHG_DONE, 1, 50, 100);
+		for (i = 0; i < clk_mgr->base.ctx->dc->res_pool->pipe_count; i++) {
+			struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
+			struct dccg *dccg = clk_mgr->base.ctx->dc->res_pool->dccg;
+			struct stream_encoder *stream_enc = pipe_ctx->stream_res.stream_enc;
+			uint32_t fifo_level;
+			int32_t N;
+			int32_t j;
+
+			if (!pipe_ctx->stream)
+				continue;
+			/* Virtual encoders don't have this function */
+			if (!stream_enc->funcs->get_fifo_cal_average_level)
+				continue;
+			fifo_level = stream_enc->funcs->get_fifo_cal_average_level(
+					stream_enc);
+			N = fifo_level / 4;
+			dccg->funcs->set_fifo_errdet_ovr_en(dccg, true);
+			for (j = 0; j < 12 - N; j++)
+				dccg->funcs->otg_add_pixel(dccg,
+						pipe_ctx->stream_res.tg->inst);
+			dccg->funcs->set_fifo_errdet_ovr_en(dccg, false);
+		}
+	}
 
 	REG_UPDATE(DENTIST_DISPCLK_CNTL,
 			DENTIST_DISPCLK_WDIVIDER, dispclk_wdivider);
@@ -251,11 +313,11 @@ void dcn2_update_clocks(struct clk_mgr *clk_mgr_base,
 		if (dpp_clock_lowered) {
 			// if clock is being lowered, increase DTO before lowering refclk
 			dcn20_update_clocks_update_dpp_dto(clk_mgr, context, safe_to_lower);
-			dcn20_update_clocks_update_dentist(clk_mgr);
+			dcn20_update_clocks_update_dentist(clk_mgr, context);
 		} else {
 			// if clock is being raised, increase refclk before lowering DTO
 			if (update_dppclk || update_dispclk)
-				dcn20_update_clocks_update_dentist(clk_mgr);
+				dcn20_update_clocks_update_dentist(clk_mgr, context);
 			// always update dtos unless clock is lowered and not safe to lower
 			dcn20_update_clocks_update_dpp_dto(clk_mgr, context, safe_to_lower);
 		}
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn20/dcn20_clk_mgr.h b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn20/dcn20_clk_mgr.h
index 0b9c045b0c8e..d254d0b6fba1 100644
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn20/dcn20_clk_mgr.h
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn20/dcn20_clk_mgr.h
@@ -50,7 +50,8 @@ void dcn2_get_clock(struct clk_mgr *clk_mgr,
 			enum dc_clock_type clock_type,
 			struct dc_clock_config *clock_cfg);
 
-void dcn20_update_clocks_update_dentist(struct clk_mgr_internal *clk_mgr);
+void dcn20_update_clocks_update_dentist(struct clk_mgr_internal *clk_mgr,
+					struct dc_state *context);
 
 void dcn2_read_clocks_from_hw_dentist(struct clk_mgr *clk_mgr_base);
 
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_clk_mgr.c
index 652fa89fae5f..513676a6f52b 100644
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_clk_mgr.c
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_clk_mgr.c
@@ -334,11 +334,11 @@ static void dcn3_update_clocks(struct clk_mgr *clk_mgr_base,
 		if (dpp_clock_lowered) {
 			/* if clock is being lowered, increase DTO before lowering refclk */
 			dcn20_update_clocks_update_dpp_dto(clk_mgr, context, safe_to_lower);
-			dcn20_update_clocks_update_dentist(clk_mgr);
+			dcn20_update_clocks_update_dentist(clk_mgr, context);
 		} else {
 			/* if clock is being raised, increase refclk before lowering DTO */
 			if (update_dppclk || update_dispclk)
-				dcn20_update_clocks_update_dentist(clk_mgr);
+				dcn20_update_clocks_update_dentist(clk_mgr, context);
 			/* There is a check inside dcn20_update_clocks_update_dpp_dto which ensures
 			 * that we do not lower dto when it is not safe to lower. We do not need to
 			 * compare the current and new dppclk before calling this function.*/
-- 
2.30.2


  parent reply	other threads:[~2021-07-06 11:16 UTC|newest]

Thread overview: 61+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-07-06 11:11 [PATCH AUTOSEL 5.13 001/189] drm/etnaviv: fix NULL check before some freeing functions is not needed Sasha Levin
2021-07-06 11:11 ` [PATCH AUTOSEL 5.13 002/189] drm/mxsfb: Don't select DRM_KMS_FB_HELPER Sasha Levin
2021-07-06 11:11 ` [PATCH AUTOSEL 5.13 003/189] drm/zte: " Sasha Levin
2021-07-06 11:11 ` [PATCH AUTOSEL 5.13 004/189] drm/ast: Fixed CVE for DP501 Sasha Levin
2021-07-06 11:11 ` [PATCH AUTOSEL 5.13 005/189] drm/amd/display: fix HDCP reset sequence on reinitialize Sasha Levin
2021-07-06 11:11 ` [PATCH AUTOSEL 5.13 006/189] drm/amd/display: Revert wait vblank on update dpp clock Sasha Levin
2021-07-06 11:11 ` [PATCH AUTOSEL 5.13 007/189] drm/amd/display: Fix BSOD with NULL check Sasha Levin
2021-07-06 11:11 ` [PATCH AUTOSEL 5.13 008/189] drm/amd/amdgpu/sriov disable all ip hw status by default Sasha Levin
2021-07-06 11:11 ` [PATCH AUTOSEL 5.13 009/189] drm/vc4: fix argument ordering in vc4_crtc_get_margins() Sasha Levin
2021-07-06 11:11 ` [PATCH AUTOSEL 5.13 010/189] drm/bridge: nwl-dsi: Force a full modeset when crtc_state->active is changed to be true Sasha Levin
2021-07-06 11:11 ` [PATCH AUTOSEL 5.13 011/189] drm/imx: ipuv3-plane: do not advertise YUV formats on planes without CSC Sasha Levin
2021-07-06 11:11 ` [PATCH AUTOSEL 5.13 012/189] drm/imx: Add 8 pixel alignment fix Sasha Levin
2021-07-06 11:11 ` [PATCH AUTOSEL 5.13 014/189] drm/amd/display: fix potential gpu reset deadlock Sasha Levin
2021-07-06 11:11 ` [PATCH AUTOSEL 5.13 015/189] drm/amdgpu: change the default timeout for kernel compute queues Sasha Levin
2021-07-06 11:11 ` [PATCH AUTOSEL 5.13 016/189] drm/amd/display: Fix clock table filling logic Sasha Levin
2021-07-06 11:11 ` [PATCH AUTOSEL 5.13 017/189] drm/amd/display: fix use_max_lb flag for 420 pixel formats Sasha Levin
2021-07-06 11:11 ` [PATCH AUTOSEL 5.13 025/189] drm/mediatek: Fix PM reference leak in mtk_crtc_ddp_hw_init() Sasha Levin
2021-07-06 11:11 ` [PATCH AUTOSEL 5.13 026/189] drm/panfrost: devfreq: Disable devfreq when num_supplies > 1 Sasha Levin
2021-07-06 11:11 ` [PATCH AUTOSEL 5.13 028/189] drm/bridge: lt9611: Add missing MODULE_DEVICE_TABLE Sasha Levin
2021-07-06 11:11 ` [PATCH AUTOSEL 5.13 030/189] drm/virtio: Fixes a potential NULL pointer dereference on probe failure Sasha Levin
2021-07-06 11:11 ` [PATCH AUTOSEL 5.13 031/189] drm/virtio: Fix double free " Sasha Levin
2021-07-06 11:11 ` [PATCH AUTOSEL 5.13 037/189] drm/amdgpu/display: restore the backlight on modeset (v2) Sasha Levin
2021-07-06 11:11 ` [PATCH AUTOSEL 5.13 038/189] drm/scheduler: Fix hang when sched_entity released Sasha Levin
2021-07-06 11:11 ` [PATCH AUTOSEL 5.13 039/189] drm/sched: Avoid data corruptions Sasha Levin
2021-07-06 11:11 ` [PATCH AUTOSEL 5.13 042/189] drm/amd/pm: fix return value in aldebaran_set_mp1_state() Sasha Levin
2021-07-06 11:11 ` [PATCH AUTOSEL 5.13 043/189] drm/vc4: Fix clock source for VEC PixelValve on BCM2711 Sasha Levin
2021-07-06 11:11 ` [PATCH AUTOSEL 5.13 044/189] drm/vc4: hdmi: Fix PM reference leak in vc4_hdmi_encoder_pre_crtc_co() Sasha Levin
2021-07-06 11:11 ` [PATCH AUTOSEL 5.13 048/189] drm/bridge: cdns: Fix PM reference leak in cdns_dsi_transfer() Sasha Levin
2021-07-06 11:11 ` [PATCH AUTOSEL 5.13 050/189] drm/amd/display: fix odm scaling Sasha Levin
2021-07-06 11:11 ` [PATCH AUTOSEL 5.13 051/189] drm/amdgpu/swsmu/aldebaran: fix check in is_dpm_running Sasha Levin
2021-07-06 11:11 ` [PATCH AUTOSEL 5.13 054/189] drm: rockchip: add missing registers for RK3188 Sasha Levin
2021-07-06 11:11 ` [PATCH AUTOSEL 5.13 055/189] drm: rockchip: add missing registers for RK3066 Sasha Levin
2021-07-06 11:11 ` [PATCH AUTOSEL 5.13 058/189] drm/tegra: hub: Fix YUV support Sasha Levin
2021-07-06 11:12 ` [PATCH AUTOSEL 5.13 061/189] drm: bridge: cdns-mhdp8546: Fix PM reference leak in Sasha Levin
2021-07-06 11:12 ` [PATCH AUTOSEL 5.13 066/189] drm/amdgpu: fix metadata_size for ubo ioctl queries Sasha Levin
2021-07-06 11:12 ` [PATCH AUTOSEL 5.13 067/189] drm/amdgpu: fix sdma firmware version error in sriov Sasha Levin
2021-07-06 11:12 ` [PATCH AUTOSEL 5.13 068/189] drm/amd/display: Avoid HDCP over-read and corruption Sasha Levin
2021-07-06 11:12 ` [PATCH AUTOSEL 5.13 069/189] drm/amdgpu: remove unsafe optimization to drop preamble ib Sasha Levin
2021-07-06 11:12 ` [PATCH AUTOSEL 5.13 088/189] drm/amd/display: Fix DCN 3.01 DSCCLK validation Sasha Levin
2021-07-06 11:12 ` [PATCH AUTOSEL 5.13 089/189] drm/amd/display: Revert "Fix clock table filling logic" Sasha Levin
2021-07-06 11:12 ` [PATCH AUTOSEL 5.13 090/189] drm/amd/display: Update scaling settings on modeset Sasha Levin
2021-07-06 11:12 ` [PATCH AUTOSEL 5.13 091/189] drm/amd/display: Release MST resources on switch from MST to SST Sasha Levin
2021-07-06 11:12 ` [PATCH AUTOSEL 5.13 092/189] drm/amd/display: Set DISPCLK_MAX_ERRDET_CYCLES to 7 Sasha Levin
2021-07-06 11:12 ` [PATCH AUTOSEL 5.13 093/189] drm/amd/display: Fix off-by-one error in DML Sasha Levin
2021-07-06 11:12 ` [PATCH AUTOSEL 5.13 094/189] drm/amd/display: Fix crash during MPO + ODM combine mode recalculation Sasha Levin
2021-07-06 11:12 ` [PATCH AUTOSEL 5.13 098/189] drm/amdkfd: use allowed domain for vmbo validation Sasha Levin
2021-07-06 11:12 ` [PATCH AUTOSEL 5.13 103/189] drm/amd/display: Verify Gamma & Degamma LUT sizes in amdgpu_dm_atomic_check Sasha Levin
2021-07-06 11:12 ` [PATCH AUTOSEL 5.13 111/189] drm/amdkfd: fix circular locking on get_wave_state Sasha Levin
2021-07-06 11:12 ` Sasha Levin [this message]
2021-07-06 11:12 ` [PATCH AUTOSEL 5.13 113/189] drm/amdgpu/gfx9: fix the doorbell missing when in CGPG issue Sasha Levin
2021-07-06 21:44   ` Alex Deucher
2021-07-06 23:09     ` Felix Kuehling
2021-07-07 10:46       ` Sasha Levin
2021-07-06 11:12 ` [PATCH AUTOSEL 5.13 114/189] drm/amdkfd: Fix circular lock in nocpsch path Sasha Levin
2021-07-06 11:13 ` [PATCH AUTOSEL 5.13 128/189] drm/amdgpu: fix bad address translation for sienna_cichlid Sasha Levin
2021-07-06 11:13 ` [PATCH AUTOSEL 5.13 129/189] drm/amdkfd: Walk through list with dqm lock hold Sasha Levin
2021-07-06 11:13 ` [PATCH AUTOSEL 5.13 146/189] Revert "drm/amdgpu/gfx9: fix the doorbell missing when in CGPG issue." Sasha Levin
2021-07-06 11:13 ` [PATCH AUTOSEL 5.13 147/189] drm/amd/display: Fix edp_bootup_bl_level initialization issue Sasha Levin
2021-07-07 10:52 ` [PATCH AUTOSEL 5.13 001/189] drm/etnaviv: fix NULL check before some freeing functions is not needed Lucas Stach
2021-07-07 11:50   ` Christian König
2021-07-14 16:45     ` Sasha Levin

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20210706111409.2058071-112-sashal@kernel.org \
    --to=sashal@kernel.org \
    --cc=Anson.Jacob@amd.com \
    --cc=Dmytro.Laktyushkin@amd.com \
    --cc=Wesley.Chalmers@amd.com \
    --cc=alexander.deucher@amd.com \
    --cc=amd-gfx@lists.freedesktop.org \
    --cc=daniel.wheeler@amd.com \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=stable@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox