mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-12-26 21:55:36 +07:00
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>
This commit is contained in:
parent
2425347697
commit
14b2584636
@ -3665,7 +3665,7 @@ dm_crtc_duplicate_state(struct drm_crtc *crtc)
|
||||
state->abm_level = cur->abm_level;
|
||||
state->vrr_supported = cur->vrr_supported;
|
||||
state->freesync_config = cur->freesync_config;
|
||||
state->crc_enabled = cur->crc_enabled;
|
||||
state->crc_src = cur->crc_src;
|
||||
state->cm_has_degamma = cur->cm_has_degamma;
|
||||
state->cm_is_degamma_srgb = cur->cm_is_degamma_srgb;
|
||||
|
||||
@ -5975,6 +5975,7 @@ static void amdgpu_dm_enable_crtc_interrupts(struct drm_device *dev,
|
||||
struct drm_crtc *crtc;
|
||||
struct drm_crtc_state *old_crtc_state, *new_crtc_state;
|
||||
int i;
|
||||
enum amdgpu_dm_pipe_crc_source source;
|
||||
|
||||
for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state,
|
||||
new_crtc_state, i) {
|
||||
@ -6000,9 +6001,13 @@ static void amdgpu_dm_enable_crtc_interrupts(struct drm_device *dev,
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
/* The stream has changed so CRC capture needs to re-enabled. */
|
||||
if (dm_new_crtc_state->crc_enabled) {
|
||||
dm_new_crtc_state->crc_enabled = false;
|
||||
amdgpu_dm_crtc_set_crc_source(crtc, "auto");
|
||||
source = dm_new_crtc_state->crc_src;
|
||||
if (amdgpu_dm_is_valid_crc_source(source)) {
|
||||
dm_new_crtc_state->crc_src = AMDGPU_DM_PIPE_CRC_SOURCE_NONE;
|
||||
if (source == AMDGPU_DM_PIPE_CRC_SOURCE_CRTC)
|
||||
amdgpu_dm_crtc_set_crc_source(crtc, "crtc");
|
||||
else if (source == AMDGPU_DM_PIPE_CRC_SOURCE_DPRX)
|
||||
amdgpu_dm_crtc_set_crc_source(crtc, "dprx");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@ -6058,7 +6063,7 @@ static int amdgpu_dm_atomic_commit(struct drm_device *dev,
|
||||
* Drop the extra vblank reference added by CRC
|
||||
* capture if applicable.
|
||||
*/
|
||||
if (dm_new_crtc_state->crc_enabled)
|
||||
if (amdgpu_dm_is_valid_crc_source(dm_new_crtc_state->crc_src))
|
||||
drm_crtc_vblank_put(crtc);
|
||||
|
||||
/*
|
||||
@ -6066,7 +6071,7 @@ static int amdgpu_dm_atomic_commit(struct drm_device *dev,
|
||||
* still a stream for the CRTC.
|
||||
*/
|
||||
if (!dm_new_crtc_state->stream)
|
||||
dm_new_crtc_state->crc_enabled = false;
|
||||
dm_new_crtc_state->crc_src = AMDGPU_DM_PIPE_CRC_SOURCE_NONE;
|
||||
|
||||
manage_dm_interrupts(adev, acrtc, false);
|
||||
}
|
||||
|
@ -50,6 +50,7 @@
|
||||
|
||||
#include "irq_types.h"
|
||||
#include "signal_types.h"
|
||||
#include "amdgpu_dm_crc.h"
|
||||
|
||||
/* Forward declarations */
|
||||
struct amdgpu_device;
|
||||
@ -313,7 +314,7 @@ struct dm_crtc_state {
|
||||
bool interrupts_enabled;
|
||||
|
||||
int crc_skip_count;
|
||||
bool crc_enabled;
|
||||
enum amdgpu_dm_pipe_crc_source crc_src;
|
||||
|
||||
bool freesync_timing_changed;
|
||||
bool freesync_vrr_info_changed;
|
||||
@ -380,19 +381,6 @@ void dm_restore_drm_connector_state(struct drm_device *dev,
|
||||
void amdgpu_dm_update_freesync_caps(struct drm_connector *connector,
|
||||
struct edid *edid);
|
||||
|
||||
/* amdgpu_dm_crc.c */
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
int amdgpu_dm_crtc_set_crc_source(struct drm_crtc *crtc, const char *src_name);
|
||||
int amdgpu_dm_crtc_verify_crc_source(struct drm_crtc *crtc,
|
||||
const char *src_name,
|
||||
size_t *values_cnt);
|
||||
void amdgpu_dm_crtc_handle_crc_irq(struct drm_crtc *crtc);
|
||||
#else
|
||||
#define amdgpu_dm_crtc_set_crc_source NULL
|
||||
#define amdgpu_dm_crtc_verify_crc_source NULL
|
||||
#define amdgpu_dm_crtc_handle_crc_irq(x)
|
||||
#endif
|
||||
|
||||
#define MAX_COLOR_LUT_ENTRIES 4096
|
||||
/* Legacy gamm LUT users such as X doesn't like large LUT sizes */
|
||||
#define MAX_COLOR_LEGACY_LUT_ENTRIES 256
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
56
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.h
Normal file
56
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.h
Normal file
@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright 2019 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* Authors: AMD
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef AMD_DAL_DEV_AMDGPU_DM_AMDGPU_DM_CRC_H_
|
||||
#define AMD_DAL_DEV_AMDGPU_DM_AMDGPU_DM_CRC_H_
|
||||
|
||||
enum amdgpu_dm_pipe_crc_source {
|
||||
AMDGPU_DM_PIPE_CRC_SOURCE_NONE = 0,
|
||||
AMDGPU_DM_PIPE_CRC_SOURCE_CRTC,
|
||||
AMDGPU_DM_PIPE_CRC_SOURCE_DPRX,
|
||||
AMDGPU_DM_PIPE_CRC_SOURCE_MAX,
|
||||
AMDGPU_DM_PIPE_CRC_SOURCE_INVALID = -1,
|
||||
};
|
||||
|
||||
static inline bool amdgpu_dm_is_valid_crc_source(enum amdgpu_dm_pipe_crc_source source)
|
||||
{
|
||||
return (source == AMDGPU_DM_PIPE_CRC_SOURCE_CRTC) ||
|
||||
(source == AMDGPU_DM_PIPE_CRC_SOURCE_DPRX);
|
||||
}
|
||||
|
||||
/* amdgpu_dm_crc.c */
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
int amdgpu_dm_crtc_set_crc_source(struct drm_crtc *crtc, const char *src_name);
|
||||
int amdgpu_dm_crtc_verify_crc_source(struct drm_crtc *crtc,
|
||||
const char *src_name,
|
||||
size_t *values_cnt);
|
||||
void amdgpu_dm_crtc_handle_crc_irq(struct drm_crtc *crtc);
|
||||
#else
|
||||
#define amdgpu_dm_crtc_set_crc_source NULL
|
||||
#define amdgpu_dm_crtc_verify_crc_source NULL
|
||||
#define amdgpu_dm_crtc_handle_crc_irq(x)
|
||||
#endif
|
||||
|
||||
#endif /* AMD_DAL_DEV_AMDGPU_DM_AMDGPU_DM_CRC_H_ */
|
Loading…
Reference in New Issue
Block a user