summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.c
diff options
context:
space:
mode:
authorCharlene Liu <charlene.liu@amd.com>2019-02-04 22:36:13 +0300
committerAlex Deucher <alexander.deucher@amd.com>2019-03-05 23:09:32 +0300
commit2750160bccab4d7a4017197a3f0d75ee8cc4c6af (patch)
treea290f9f12ab1aa23bea8fb58f555acaeb49f46f4 /drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.c
parent46f81fc4af81b6523cf2a538b0d2e531ee1477b1 (diff)
downloadlinux-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.c46
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,