diff options
author | Dingchen Zhang <dingchen.zhang@amd.com> | 2019-05-15 17:15:05 -0400 |
---|---|---|
committer | Alex Deucher <alexander.deucher@amd.com> | 2019-07-18 14:18:09 -0500 |
commit | 14b2584636c66efbb9a8dd1c702d5da73ecf620d (patch) | |
tree | cfea1dc3f6ff7f9f41a8696bea8db3643fdda6e6 /drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c | |
parent | 24253476977af5456af962bbaaf53e9f1dae5cc1 (diff) | |
download | linux-14b2584636c66efbb9a8dd1c702d5da73ecf620d.tar.gz linux-14b2584636c66efbb9a8dd1c702d5da73ecf620d.tar.bz2 linux-14b2584636c66efbb9a8dd1c702d5da73ecf620d.zip |
drm/amd/display: add functionality to grab DPRX CRC entries.
[Why]
We need to compare DPRX CRCs with framebuffer CRCs for digital bypass mode.
[How]
Hook into DRM to grab DP receiver CRCs through drm_dp_start_crc.
Signed-off-by: Dingchen Zhang <dingchen.zhang@amd.com>
Reviewed-by: Harry Wentland <Harry.Wentland@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/amdgpu_dm/amdgpu_dm_crc.c')
-rw-r--r-- | drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c | 91 |
1 files changed, 67 insertions, 24 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 bc67e6502733..9af270161a0e 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 @@ -30,19 +30,14 @@ #include "amdgpu_dm.h" #include "dc.h" -enum amdgpu_dm_pipe_crc_source { - AMDGPU_DM_PIPE_CRC_SOURCE_NONE = 0, - AMDGPU_DM_PIPE_CRC_SOURCE_AUTO, - AMDGPU_DM_PIPE_CRC_SOURCE_MAX, - AMDGPU_DM_PIPE_CRC_SOURCE_INVALID = -1, -}; - static enum amdgpu_dm_pipe_crc_source dm_parse_crc_source(const char *source) { if (!source || !strcmp(source, "none")) return AMDGPU_DM_PIPE_CRC_SOURCE_NONE; - if (!strcmp(source, "auto")) - return AMDGPU_DM_PIPE_CRC_SOURCE_AUTO; + if (!strcmp(source, "auto") || !strcmp(source, "crtc")) + return AMDGPU_DM_PIPE_CRC_SOURCE_CRTC; + if (!strcmp(source, "dprx")) + return AMDGPU_DM_PIPE_CRC_SOURCE_DPRX; return AMDGPU_DM_PIPE_CRC_SOURCE_INVALID; } @@ -68,7 +63,10 @@ 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; + struct amdgpu_dm_connector *aconn; + struct drm_dp_aux *aux = NULL; + bool enable = false; + bool enabled = false; enum amdgpu_dm_pipe_crc_source source = dm_parse_crc_source(src_name); @@ -83,13 +81,42 @@ int amdgpu_dm_crtc_set_crc_source(struct drm_crtc *crtc, const char *src_name) return -EINVAL; } - enable = (source == AMDGPU_DM_PIPE_CRC_SOURCE_AUTO); + enable = amdgpu_dm_is_valid_crc_source(source); 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; + /* + * USER REQ SRC | CURRENT SRC | BEHAVIOR + * ----------------------------- + * None | None | Do nothing + * None | CRTC | Disable CRTC CRC + * None | DPRX | Disable DPRX CRC, need 'aux' + * CRTC | XXXX | Enable CRTC CRC, configure DC strm + * DPRX | XXXX | Enable DPRX CRC, need 'aux' + */ + if (source == AMDGPU_DM_PIPE_CRC_SOURCE_DPRX || + (source == AMDGPU_DM_PIPE_CRC_SOURCE_NONE && + crtc_state->crc_src == AMDGPU_DM_PIPE_CRC_SOURCE_DPRX)) { + aconn = stream_state->link->priv; + + if (!aconn) { + DRM_DEBUG_DRIVER("No amd connector matching CRTC-%d\n", crtc->index); + mutex_unlock(&adev->dm.dc_lock); + return -EINVAL; + } + + aux = &aconn->dm_dp_aux.aux; + + if (!aux) { + DRM_DEBUG_DRIVER("No dp aux for amd connector\n"); + mutex_unlock(&adev->dm.dc_lock); + return -EINVAL; + } + } else if (source == AMDGPU_DM_PIPE_CRC_SOURCE_CRTC) { + 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. */ @@ -103,12 +130,26 @@ int amdgpu_dm_crtc_set_crc_source(struct drm_crtc *crtc, const char *src_name) * Reading the CRC requires the vblank interrupt handler to be * enabled. Keep a reference until CRC capture stops. */ - if (!crtc_state->crc_enabled && enable) + enabled = amdgpu_dm_is_valid_crc_source(crtc_state->crc_src); + if (!enabled && enable) { drm_crtc_vblank_get(crtc); - else if (crtc_state->crc_enabled && !enable) + if (source == AMDGPU_DM_PIPE_CRC_SOURCE_DPRX) { + if (drm_dp_start_crc(aux, crtc)) { + DRM_DEBUG_DRIVER("dp start crc failed\n"); + return -EINVAL; + } + } + } else if (enabled && !enable) { drm_crtc_vblank_put(crtc); + if (crtc_state->crc_src == AMDGPU_DM_PIPE_CRC_SOURCE_DPRX) { + if (drm_dp_stop_crc(aux)) { + DRM_DEBUG_DRIVER("dp stop crc failed\n"); + return -EINVAL; + } + } + } - crtc_state->crc_enabled = enable; + crtc_state->crc_src = source; /* Reset crc_skipped on dm state */ crtc_state->crc_skip_count = 0; @@ -135,7 +176,7 @@ void amdgpu_dm_crtc_handle_crc_irq(struct drm_crtc *crtc) stream_state = crtc_state->stream; /* Early return if CRC capture is not enabled. */ - if (!crtc_state->crc_enabled) + if (!amdgpu_dm_is_valid_crc_source(crtc_state->crc_src)) return; /* @@ -149,10 +190,12 @@ void amdgpu_dm_crtc_handle_crc_irq(struct drm_crtc *crtc) return; } - if (!dc_stream_get_crc(stream_state->ctx->dc, stream_state, - &crcs[0], &crcs[1], &crcs[2])) - return; + if (crtc_state->crc_src == AMDGPU_DM_PIPE_CRC_SOURCE_CRTC) { + if (!dc_stream_get_crc(stream_state->ctx->dc, stream_state, + &crcs[0], &crcs[1], &crcs[2])) + return; - drm_crtc_add_crc_entry(crtc, true, - drm_crtc_accurate_vblank_count(crtc), crcs); + drm_crtc_add_crc_entry(crtc, true, + drm_crtc_accurate_vblank_count(crtc), crcs); + } } |