diff options
author | Charlene Liu <charlene.liu@amd.com> | 2019-02-04 22:36:13 +0300 |
---|---|---|
committer | Alex Deucher <alexander.deucher@amd.com> | 2019-03-05 23:09:32 +0300 |
commit | 2750160bccab4d7a4017197a3f0d75ee8cc4c6af (patch) | |
tree | a290f9f12ab1aa23bea8fb58f555acaeb49f46f4 /drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.c | |
parent | 46f81fc4af81b6523cf2a538b0d2e531ee1477b1 (diff) | |
download | linux-2750160bccab4d7a4017197a3f0d75ee8cc4c6af.tar.xz |
drm/amd/display: dcn add check surface in_use
Driver need to poll the SURFACE_INUSE register to determine when to
start the new task and write data to the checked surface.
Implement the wait functions, and add the necessary hubbub registers.
Signed-off-by: Charlene Liu <charlene.liu@amd.com>
Reviewed-by: Dmytro Laktyushkin <Dmytro.Laktyushkin@amd.com>
Acked-by: Leo Li <sunpeng.li@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.c')
-rw-r--r-- | drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.c | 46 |
1 files changed, 46 insertions, 0 deletions
diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.c index e161ad836812..9c6217b99692 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.c @@ -642,6 +642,50 @@ void hubbub1_soft_reset(struct hubbub *hubbub, bool reset) DCHUBBUB_GLOBAL_SOFT_RESET, reset_en); } +static bool hubbub1_is_surf_still_in_update(struct hubbub *hubbub, uint32_t hbup_inst) +{ + struct dcn10_hubbub *hubbub1 = TO_DCN10_HUBBUB(hubbub); + uint32_t still_used_by_dcn = 0; + + switch (hbup_inst) { + case 0: + REG_GET(SURFACE_CHECK0_ADDRESS_MSB, + CHECKER0_SURFACE_INUSE, + &still_used_by_dcn); + break; + case 1: + REG_GET(SURFACE_CHECK1_ADDRESS_MSB, + CHECKER1_SURFACE_INUSE, + &still_used_by_dcn); + break; + case 2: + REG_GET(SURFACE_CHECK2_ADDRESS_MSB, + CHECKER2_SURFACE_INUSE, + &still_used_by_dcn); + break; + case 3: + REG_GET(SURFACE_CHECK3_ADDRESS_MSB, + CHECKER3_SURFACE_INUSE, + &still_used_by_dcn); + break; + default: + break; + } + return (still_used_by_dcn == 1); +} + +void hubbub1_wait_for_safe_surf_update(struct hubbub *hubbub, uint32_t hbup_inst) +{ + uint32_t still_used_by_dcn = 0, count = 0; + + do { + still_used_by_dcn = hubbub1_is_surf_still_in_update(hubbub, hbup_inst); + udelay(1); + count++; + } while (still_used_by_dcn == 1 && count < 100); + ASSERT(count < 100); +} + static bool hubbub1_dcc_support_swizzle( enum swizzle_mode_values swizzle, unsigned int bytes_per_element, @@ -860,12 +904,14 @@ static bool hubbub1_get_dcc_compression_cap(struct hubbub *hubbub, return true; } + static const struct hubbub_funcs hubbub1_funcs = { .update_dchub = hubbub1_update_dchub, .dcc_support_swizzle = hubbub1_dcc_support_swizzle, .dcc_support_pixel_format = hubbub1_dcc_support_pixel_format, .get_dcc_compression_cap = hubbub1_get_dcc_compression_cap, .wm_read_state = hubbub1_wm_read_state, + .wait_for_surf_safe_update = hubbub1_wait_for_safe_surf_update, }; void hubbub1_construct(struct hubbub *hubbub, |