aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c')
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c48
1 files changed, 27 insertions, 21 deletions
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c
index f088ac585978..a10e3a50d9ef 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c
@@ -64,8 +64,10 @@ amdgpu_dm_crtc_verify_crc_source(struct drm_crtc *crtc, const char *src_name,
int amdgpu_dm_crtc_set_crc_source(struct drm_crtc *crtc, const char *src_name)
{
+ struct amdgpu_device *adev = crtc->dev->dev_private;
struct dm_crtc_state *crtc_state = to_dm_crtc_state(crtc->state);
struct dc_stream_state *stream_state = crtc_state->stream;
+ bool enable;
enum amdgpu_dm_pipe_crc_source source = dm_parse_crc_source(src_name);
@@ -80,29 +82,33 @@ int amdgpu_dm_crtc_set_crc_source(struct drm_crtc *crtc, const char *src_name)
return -EINVAL;
}
- /* When enabling CRC, we should also disable dithering. */
- if (source == AMDGPU_DM_PIPE_CRC_SOURCE_AUTO) {
- if (dc_stream_configure_crc(stream_state->ctx->dc,
- stream_state,
- true, true)) {
- crtc_state->crc_enabled = true;
- dc_stream_set_dither_option(stream_state,
- DITHER_OPTION_TRUN8);
- }
- else
- return -EINVAL;
- } else {
- if (dc_stream_configure_crc(stream_state->ctx->dc,
- stream_state,
- false, false)) {
- crtc_state->crc_enabled = false;
- dc_stream_set_dither_option(stream_state,
- DITHER_OPTION_DEFAULT);
- }
- else
- return -EINVAL;
+ enable = (source == AMDGPU_DM_PIPE_CRC_SOURCE_AUTO);
+
+ mutex_lock(&adev->dm.dc_lock);
+ if (!dc_stream_configure_crc(stream_state->ctx->dc, stream_state,
+ enable, enable)) {
+ mutex_unlock(&adev->dm.dc_lock);
+ return -EINVAL;
}
+ /* When enabling CRC, we should also disable dithering. */
+ dc_stream_set_dither_option(stream_state,
+ enable ? DITHER_OPTION_TRUN8
+ : DITHER_OPTION_DEFAULT);
+
+ mutex_unlock(&adev->dm.dc_lock);
+
+ /*
+ * Reading the CRC requires the vblank interrupt handler to be
+ * enabled. Keep a reference until CRC capture stops.
+ */
+ if (!crtc_state->crc_enabled && enable)
+ drm_crtc_vblank_get(crtc);
+ else if (crtc_state->crc_enabled && !enable)
+ drm_crtc_vblank_put(crtc);
+
+ crtc_state->crc_enabled = enable;
+
/* Reset crc_skipped on dm state */
crtc_state->crc_skip_count = 0;
return 0;