summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c
diff options
context:
space:
mode:
authorNicholas Kazlauskas <nicholas.kazlauskas@amd.com>2019-08-20 10:16:14 -0400
committerAlex Deucher <alexander.deucher@amd.com>2019-08-21 22:18:25 -0500
commit57638021b711de052df781001bd6fd35804c3646 (patch)
tree2a3834fc70bd0cc95f5b9e102a6bea45bae964fc /drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c
parentdf61eae4b87ac4dfb9c4fceea2f223a29466507b (diff)
drm/amd/display: Split out DC programming for CRC capture
[Why] Calling amdgpu_dm_crtc_set_crc_source in amdgpu_dm directly has the consequence of adding additional vblank references or starting DPRX CRC capture more than once without calling stop first. Vblank references for CRC capture should be managed entirely by opening and closing the CRC file from userspace. Stream state also shouldn't be required on the CRC so we can close the file after the CRTC has been disabled. [How] Do DC programming required for configuring CRC capture separately from setting the source. Whenever we re-enable or reset a CRC this programming should be reapplied. CRC vblank reference handling in amdgpu_dm can be entirely dropped after this. Stream state also no longer needs to be required since we can just defer the programming to when the stream is actually enabled. Signed-off-by: Nicholas Kazlauskas <nicholas.kazlauskas@amd.com> Reviewed-by: David Francis <David.Francis@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
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.c62
1 files changed, 39 insertions, 23 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 513e40667f8f..d2cdf3002365 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
@@ -97,11 +97,46 @@ amdgpu_dm_crtc_verify_crc_source(struct drm_crtc *crtc, const char *src_name,
return 0;
}
-int amdgpu_dm_crtc_set_crc_source(struct drm_crtc *crtc, const char *src_name)
+int amdgpu_dm_crtc_configure_crc_source(struct drm_crtc *crtc,
+ struct dm_crtc_state *dm_crtc_state,
+ enum amdgpu_dm_pipe_crc_source source)
{
struct amdgpu_device *adev = crtc->dev->dev_private;
+ struct dc_stream_state *stream_state = dm_crtc_state->stream;
+ bool enable = amdgpu_dm_is_valid_crc_source(source);
+ int ret = 0;
+
+ /* Configuration will be deferred to stream enable. */
+ if (!stream_state)
+ return 0;
+
+ mutex_lock(&adev->dm.dc_lock);
+
+ /* Enable CRTC CRC generation if necessary. */
+ if (dm_is_crc_source_crtc(source)) {
+ if (!dc_stream_configure_crc(stream_state->ctx->dc,
+ stream_state, enable, enable)) {
+ ret = -EINVAL;
+ goto unlock;
+ }
+ }
+
+ /* Configure dithering */
+ if (!dm_need_crc_dither(source))
+ dc_stream_set_dither_option(stream_state, DITHER_OPTION_TRUN8);
+ else
+ dc_stream_set_dither_option(stream_state,
+ DITHER_OPTION_DEFAULT);
+
+unlock:
+ mutex_unlock(&adev->dm.dc_lock);
+
+ return ret;
+}
+
+int amdgpu_dm_crtc_set_crc_source(struct drm_crtc *crtc, const char *src_name)
+{
struct dm_crtc_state *crtc_state = to_dm_crtc_state(crtc->state);
- struct dc_stream_state *stream_state = crtc_state->stream;
struct drm_dp_aux *aux = NULL;
bool enable = false;
bool enabled = false;
@@ -115,14 +150,8 @@ int amdgpu_dm_crtc_set_crc_source(struct drm_crtc *crtc, const char *src_name)
return -EINVAL;
}
- if (!stream_state) {
- DRM_ERROR("No stream state for CRTC%d\n", crtc->index);
- return -EINVAL;
- }
-
enable = amdgpu_dm_is_valid_crc_source(source);
- mutex_lock(&adev->dm.dc_lock);
/*
* USER REQ SRC | CURRENT SRC | BEHAVIOR
* -----------------------------
@@ -155,7 +184,6 @@ int amdgpu_dm_crtc_set_crc_source(struct drm_crtc *crtc, const char *src_name)
if (!aconn) {
DRM_DEBUG_DRIVER("No amd connector matching CRTC-%d\n", crtc->index);
- mutex_unlock(&adev->dm.dc_lock);
return -EINVAL;
}
@@ -163,24 +191,12 @@ int amdgpu_dm_crtc_set_crc_source(struct drm_crtc *crtc, const char *src_name)
if (!aux) {
DRM_DEBUG_DRIVER("No dp aux for amd connector\n");
- mutex_unlock(&adev->dm.dc_lock);
- return -EINVAL;
- }
- } else if (dm_is_crc_source_crtc(source)) {
- if (!dc_stream_configure_crc(stream_state->ctx->dc, stream_state,
- enable, enable)) {
- mutex_unlock(&adev->dm.dc_lock);
return -EINVAL;
}
}
- /* configure dithering */
- if (!dm_need_crc_dither(source))
- dc_stream_set_dither_option(stream_state, DITHER_OPTION_TRUN8);
- else if (!dm_need_crc_dither(crtc_state->crc_src))
- dc_stream_set_dither_option(stream_state, DITHER_OPTION_DEFAULT);
-
- mutex_unlock(&adev->dm.dc_lock);
+ if (amdgpu_dm_crtc_configure_crc_source(crtc, crtc_state, source))
+ return -EINVAL;
/*
* Reading the CRC requires the vblank interrupt handler to be