summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/amd/display/dc/optc
diff options
context:
space:
mode:
authorIlya Bakoulin <Ilya.Bakoulin@amd.com>2024-09-16 14:38:19 -0400
committerAlex Deucher <alexander.deucher@amd.com>2024-10-15 11:23:12 -0400
commitdf60dcf5b58a642e531609d0d673bb63a11ed06e (patch)
treea2d2e8cdf6cf97a1e05e87b26def080eb33ddf0b /drivers/gpu/drm/amd/display/dc/optc
parentf79f4dd6001acd1e6ea6aae8e219060a566409b2 (diff)
drm/amd/display: Add 3DLUT FL HW bug workaround
[Why] There is a known HW bug that causes the internal 3DLUT fetch signal to be lost at VREADY, regardless of whether the OTG lock is being held or not. A workaround is necessary to make sure that this internal signal stays up after OTG unlock. [How] Set the 3DLUT_ENABLE bit immediately before and after the unlock. Also use VUPDATE_KEEPOUT to prevent lock transition in the region between VSTARTUP and VREADY, which could cause issues with this WA sequence. Also including misc. 3DLUT DMA-related sequence fixes to address a few regressions causing corruption. Reviewed-by: Dillon Varone <dillon.varone@amd.com> Signed-off-by: Ilya Bakoulin <Ilya.Bakoulin@amd.com> Signed-off-by: Roman Li <roman.li@amd.com> Tested-by: Daniel Wheeler <daniel.wheeler@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers/gpu/drm/amd/display/dc/optc')
-rw-r--r--drivers/gpu/drm/amd/display/dc/optc/dcn401/dcn401_optc.c31
1 files changed, 31 insertions, 0 deletions
diff --git a/drivers/gpu/drm/amd/display/dc/optc/dcn401/dcn401_optc.c b/drivers/gpu/drm/amd/display/dc/optc/dcn401/dcn401_optc.c
index db670fc17264..783ca9acc762 100644
--- a/drivers/gpu/drm/amd/display/dc/optc/dcn401/dcn401_optc.c
+++ b/drivers/gpu/drm/amd/display/dc/optc/dcn401/dcn401_optc.c
@@ -430,6 +430,35 @@ static void optc401_program_global_sync(
REG_UPDATE(OTG_PSTATE_REGISTER, OTG_PSTATE_KEEPOUT_START, pstate_keepout);
}
+static void optc401_set_vupdate_keepout(struct timing_generator *tg, bool enable)
+{
+ struct optc *optc1 = DCN10TG_FROM_TG(tg);
+
+ REG_SET_3(OTG_VUPDATE_KEEPOUT, 0,
+ MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_START_OFFSET, 0,
+ MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_END_OFFSET, optc1->vready_offset + 10,
+ OTG_MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_EN, enable);
+
+ return;
+}
+
+static bool optc401_wait_update_lock_status(struct timing_generator *tg, bool locked)
+{
+ struct optc *optc1 = DCN10TG_FROM_TG(tg);
+ uint32_t lock_status = 0;
+
+ REG_WAIT(OTG_MASTER_UPDATE_LOCK,
+ UPDATE_LOCK_STATUS, locked,
+ 1, 150000);
+
+ REG_GET(OTG_MASTER_UPDATE_LOCK, UPDATE_LOCK_STATUS, &lock_status);
+
+ if (lock_status != locked)
+ return false;
+
+ return true;
+}
+
static struct timing_generator_funcs dcn401_tg_funcs = {
.validate_timing = optc1_validate_timing,
.program_timing = optc1_program_timing,
@@ -496,6 +525,8 @@ static struct timing_generator_funcs dcn401_tg_funcs = {
.get_optc_double_buffer_pending = optc3_get_optc_double_buffer_pending,
.get_otg_double_buffer_pending = optc3_get_otg_update_pending,
.get_pipe_update_pending = optc3_get_pipe_update_pending,
+ .set_vupdate_keepout = optc401_set_vupdate_keepout,
+ .wait_update_lock_status = optc401_wait_update_lock_status,
};
void dcn401_timing_generator_init(struct optc *optc1)