diff options
author | Roy Chan <roy.chan@amd.com> | 2022-01-23 21:20:09 +0300 |
---|---|---|
committer | Alex Deucher <alexander.deucher@amd.com> | 2022-01-26 02:00:35 +0300 |
commit | 5f2c1192eba42f6926253a1f2c9b18da05b3c31f (patch) | |
tree | dabc720d7160493af22c37238943c231658699db /drivers/gpu/drm/amd/display/dc/dc_helper.c | |
parent | 9cc370435cde6b672b6e2221115c2f535e8bd4ec (diff) | |
download | linux-5f2c1192eba42f6926253a1f2c9b18da05b3c31f.tar.xz |
drm/amd/display: Support synchronized indirect reg access
[Why]
indirect register index/data pair may be used by multi-threads. when it
happens, it would cause register access issue that is hard to trace.
[How]
Using cgs service, which provide a sync indirect reg access api.
Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
Reviewed-by: Aric Cyr <Aric.Cyr@amd.com>
Acked-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
Signed-off-by: Roy Chan <roy.chan@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers/gpu/drm/amd/display/dc/dc_helper.c')
-rw-r--r-- | drivers/gpu/drm/amd/display/dc/dc_helper.c | 60 |
1 files changed, 60 insertions, 0 deletions
diff --git a/drivers/gpu/drm/amd/display/dc/dc_helper.c b/drivers/gpu/drm/amd/display/dc/dc_helper.c index ab6bc5d79012..f43cce16bb6c 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_helper.c +++ b/drivers/gpu/drm/amd/display/dc/dc_helper.c @@ -588,6 +588,66 @@ uint32_t generic_indirect_reg_update_ex(const struct dc_context *ctx, return reg_val; } + +uint32_t generic_indirect_reg_update_ex_sync(const struct dc_context *ctx, + uint32_t index, uint32_t reg_val, int n, + uint8_t shift1, uint32_t mask1, uint32_t field_value1, + ...) +{ + uint32_t shift, mask, field_value; + int i = 1; + + va_list ap; + + va_start(ap, field_value1); + + reg_val = set_reg_field_value_ex(reg_val, field_value1, mask1, shift1); + + while (i < n) { + shift = va_arg(ap, uint32_t); + mask = va_arg(ap, uint32_t); + field_value = va_arg(ap, uint32_t); + + reg_val = set_reg_field_value_ex(reg_val, field_value, mask, shift); + i++; + } + + dm_write_index_reg(ctx, CGS_IND_REG__PCIE, index, reg_val); + va_end(ap); + + return reg_val; +} + +uint32_t generic_indirect_reg_get_sync(const struct dc_context *ctx, + uint32_t index, int n, + uint8_t shift1, uint32_t mask1, uint32_t *field_value1, + ...) +{ + uint32_t shift, mask, *field_value; + uint32_t value = 0; + int i = 1; + + va_list ap; + + va_start(ap, field_value1); + + value = dm_read_index_reg(ctx, CGS_IND_REG__PCIE, index); + *field_value1 = get_reg_field_value_ex(value, mask1, shift1); + + while (i < n) { + shift = va_arg(ap, uint32_t); + mask = va_arg(ap, uint32_t); + field_value = va_arg(ap, uint32_t *); + + *field_value = get_reg_field_value_ex(value, mask, shift); + i++; + } + + va_end(ap); + + return value; +} + void reg_sequence_start_gather(const struct dc_context *ctx) { /* if reg sequence is supported and enabled, set flag to |