diff options
author | Ilya Bakoulin <Ilya.Bakoulin@amd.com> | 2024-09-16 14:38:19 -0400 |
---|---|---|
committer | Alex Deucher <alexander.deucher@amd.com> | 2024-10-15 11:23:12 -0400 |
commit | df60dcf5b58a642e531609d0d673bb63a11ed06e (patch) | |
tree | a2d2e8cdf6cf97a1e05e87b26def080eb33ddf0b /drivers/gpu/drm/amd/display/dc/optc | |
parent | f79f4dd6001acd1e6ea6aae8e219060a566409b2 (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.c | 31 |
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) |