drm/amd/display: Expose new CRC window property
[Why] Instead of calculating CRC on whole frame, add flexibility to calculate CRC on specific frame region. [How] Add few crc window coordinate properties. By default, CRC is calculated on whole frame unless user space specifies the CRC calculation window. Signed-off-by: Wayne Lin <Wayne.Lin@amd.com> Acked-by: Bindu Ramamurthy <bindu.r@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
parent
c88840f342
commit
c920888c60
@ -943,6 +943,41 @@ static void mmhub_read_system_context(struct amdgpu_device *adev, struct dc_phy_
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_DEBUG_FS
|
||||||
|
static int create_crtc_crc_properties(struct amdgpu_display_manager *dm)
|
||||||
|
{
|
||||||
|
dm->crc_win_x_start_property =
|
||||||
|
drm_property_create_range(adev_to_drm(dm->adev),
|
||||||
|
DRM_MODE_PROP_ATOMIC,
|
||||||
|
"AMD_CRC_WIN_X_START", 0, U16_MAX);
|
||||||
|
if (!dm->crc_win_x_start_property)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
dm->crc_win_y_start_property =
|
||||||
|
drm_property_create_range(adev_to_drm(dm->adev),
|
||||||
|
DRM_MODE_PROP_ATOMIC,
|
||||||
|
"AMD_CRC_WIN_Y_START", 0, U16_MAX);
|
||||||
|
if (!dm->crc_win_y_start_property)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
dm->crc_win_x_end_property =
|
||||||
|
drm_property_create_range(adev_to_drm(dm->adev),
|
||||||
|
DRM_MODE_PROP_ATOMIC,
|
||||||
|
"AMD_CRC_WIN_X_END", 0, U16_MAX);
|
||||||
|
if (!dm->crc_win_x_end_property)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
dm->crc_win_y_end_property =
|
||||||
|
drm_property_create_range(adev_to_drm(dm->adev),
|
||||||
|
DRM_MODE_PROP_ATOMIC,
|
||||||
|
"AMD_CRC_WIN_Y_END", 0, U16_MAX);
|
||||||
|
if (!dm->crc_win_y_end_property)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static int amdgpu_dm_init(struct amdgpu_device *adev)
|
static int amdgpu_dm_init(struct amdgpu_device *adev)
|
||||||
{
|
{
|
||||||
struct dc_init_data init_data;
|
struct dc_init_data init_data;
|
||||||
@ -1084,6 +1119,10 @@ static int amdgpu_dm_init(struct amdgpu_device *adev)
|
|||||||
|
|
||||||
dc_init_callbacks(adev->dm.dc, &init_params);
|
dc_init_callbacks(adev->dm.dc, &init_params);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef CONFIG_DEBUG_FS
|
||||||
|
if (create_crtc_crc_properties(&adev->dm))
|
||||||
|
DRM_ERROR("amdgpu: failed to create crc property.\n");
|
||||||
#endif
|
#endif
|
||||||
if (amdgpu_dm_initialize_drm_device(adev)) {
|
if (amdgpu_dm_initialize_drm_device(adev)) {
|
||||||
DRM_ERROR(
|
DRM_ERROR(
|
||||||
@ -5250,12 +5289,64 @@ dm_crtc_duplicate_state(struct drm_crtc *crtc)
|
|||||||
state->crc_src = cur->crc_src;
|
state->crc_src = cur->crc_src;
|
||||||
state->cm_has_degamma = cur->cm_has_degamma;
|
state->cm_has_degamma = cur->cm_has_degamma;
|
||||||
state->cm_is_degamma_srgb = cur->cm_is_degamma_srgb;
|
state->cm_is_degamma_srgb = cur->cm_is_degamma_srgb;
|
||||||
|
#ifdef CONFIG_DEBUG_FS
|
||||||
|
state->crc_window = cur->crc_window;
|
||||||
|
#endif
|
||||||
/* TODO Duplicate dc_stream after objects are stream object is flattened */
|
/* TODO Duplicate dc_stream after objects are stream object is flattened */
|
||||||
|
|
||||||
return &state->base;
|
return &state->base;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_DEBUG_FS
|
||||||
|
int amdgpu_dm_crtc_atomic_set_property(struct drm_crtc *crtc,
|
||||||
|
struct drm_crtc_state *crtc_state,
|
||||||
|
struct drm_property *property,
|
||||||
|
uint64_t val)
|
||||||
|
{
|
||||||
|
struct drm_device *dev = crtc->dev;
|
||||||
|
struct amdgpu_device *adev = drm_to_adev(dev);
|
||||||
|
struct dm_crtc_state *dm_new_state =
|
||||||
|
to_dm_crtc_state(crtc_state);
|
||||||
|
|
||||||
|
if (property == adev->dm.crc_win_x_start_property)
|
||||||
|
dm_new_state->crc_window.x_start = val;
|
||||||
|
else if (property == adev->dm.crc_win_y_start_property)
|
||||||
|
dm_new_state->crc_window.y_start = val;
|
||||||
|
else if (property == adev->dm.crc_win_x_end_property)
|
||||||
|
dm_new_state->crc_window.x_end = val;
|
||||||
|
else if (property == adev->dm.crc_win_y_end_property)
|
||||||
|
dm_new_state->crc_window.y_end = val;
|
||||||
|
else
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int amdgpu_dm_crtc_atomic_get_property(struct drm_crtc *crtc,
|
||||||
|
const struct drm_crtc_state *state,
|
||||||
|
struct drm_property *property,
|
||||||
|
uint64_t *val)
|
||||||
|
{
|
||||||
|
struct drm_device *dev = crtc->dev;
|
||||||
|
struct amdgpu_device *adev = drm_to_adev(dev);
|
||||||
|
struct dm_crtc_state *dm_state =
|
||||||
|
to_dm_crtc_state(state);
|
||||||
|
|
||||||
|
if (property == adev->dm.crc_win_x_start_property)
|
||||||
|
*val = dm_state->crc_window.x_start;
|
||||||
|
else if (property == adev->dm.crc_win_y_start_property)
|
||||||
|
*val = dm_state->crc_window.y_start;
|
||||||
|
else if (property == adev->dm.crc_win_x_end_property)
|
||||||
|
*val = dm_state->crc_window.x_end;
|
||||||
|
else if (property == adev->dm.crc_win_y_end_property)
|
||||||
|
*val = dm_state->crc_window.y_end;
|
||||||
|
else
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static inline int dm_set_vupdate_irq(struct drm_crtc *crtc, bool enable)
|
static inline int dm_set_vupdate_irq(struct drm_crtc *crtc, bool enable)
|
||||||
{
|
{
|
||||||
enum dc_irq_source irq_source;
|
enum dc_irq_source irq_source;
|
||||||
@ -5322,6 +5413,10 @@ static const struct drm_crtc_funcs amdgpu_dm_crtc_funcs = {
|
|||||||
.enable_vblank = dm_enable_vblank,
|
.enable_vblank = dm_enable_vblank,
|
||||||
.disable_vblank = dm_disable_vblank,
|
.disable_vblank = dm_disable_vblank,
|
||||||
.get_vblank_timestamp = drm_crtc_vblank_helper_get_vblank_timestamp,
|
.get_vblank_timestamp = drm_crtc_vblank_helper_get_vblank_timestamp,
|
||||||
|
#ifdef CONFIG_DEBUG_FS
|
||||||
|
.atomic_set_property = amdgpu_dm_crtc_atomic_set_property,
|
||||||
|
.atomic_get_property = amdgpu_dm_crtc_atomic_get_property,
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
static enum drm_connector_status
|
static enum drm_connector_status
|
||||||
@ -6519,6 +6614,25 @@ static int amdgpu_dm_plane_init(struct amdgpu_display_manager *dm,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_DEBUG_FS
|
||||||
|
static void attach_crtc_crc_properties(struct amdgpu_display_manager *dm,
|
||||||
|
struct amdgpu_crtc *acrtc)
|
||||||
|
{
|
||||||
|
drm_object_attach_property(&acrtc->base.base,
|
||||||
|
dm->crc_win_x_start_property,
|
||||||
|
0);
|
||||||
|
drm_object_attach_property(&acrtc->base.base,
|
||||||
|
dm->crc_win_y_start_property,
|
||||||
|
0);
|
||||||
|
drm_object_attach_property(&acrtc->base.base,
|
||||||
|
dm->crc_win_x_end_property,
|
||||||
|
0);
|
||||||
|
drm_object_attach_property(&acrtc->base.base,
|
||||||
|
dm->crc_win_y_end_property,
|
||||||
|
0);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static int amdgpu_dm_crtc_init(struct amdgpu_display_manager *dm,
|
static int amdgpu_dm_crtc_init(struct amdgpu_display_manager *dm,
|
||||||
struct drm_plane *plane,
|
struct drm_plane *plane,
|
||||||
uint32_t crtc_index)
|
uint32_t crtc_index)
|
||||||
@ -6566,7 +6680,9 @@ static int amdgpu_dm_crtc_init(struct amdgpu_display_manager *dm,
|
|||||||
drm_crtc_enable_color_mgmt(&acrtc->base, MAX_COLOR_LUT_ENTRIES,
|
drm_crtc_enable_color_mgmt(&acrtc->base, MAX_COLOR_LUT_ENTRIES,
|
||||||
true, MAX_COLOR_LUT_ENTRIES);
|
true, MAX_COLOR_LUT_ENTRIES);
|
||||||
drm_mode_crtc_set_gamma_size(&acrtc->base, MAX_COLOR_LEGACY_LUT_ENTRIES);
|
drm_mode_crtc_set_gamma_size(&acrtc->base, MAX_COLOR_LEGACY_LUT_ENTRIES);
|
||||||
|
#ifdef CONFIG_DEBUG_FS
|
||||||
|
attach_crtc_crc_properties(dm, acrtc);
|
||||||
|
#endif
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
@ -8190,6 +8306,7 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)
|
|||||||
*/
|
*/
|
||||||
for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) {
|
for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) {
|
||||||
struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc);
|
struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc);
|
||||||
|
bool configure_crc = false;
|
||||||
|
|
||||||
dm_new_crtc_state = to_dm_crtc_state(new_crtc_state);
|
dm_new_crtc_state = to_dm_crtc_state(new_crtc_state);
|
||||||
|
|
||||||
@ -8199,21 +8316,30 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)
|
|||||||
dc_stream_retain(dm_new_crtc_state->stream);
|
dc_stream_retain(dm_new_crtc_state->stream);
|
||||||
acrtc->dm_irq_params.stream = dm_new_crtc_state->stream;
|
acrtc->dm_irq_params.stream = dm_new_crtc_state->stream;
|
||||||
manage_dm_interrupts(adev, acrtc, true);
|
manage_dm_interrupts(adev, acrtc, true);
|
||||||
|
}
|
||||||
#ifdef CONFIG_DEBUG_FS
|
#ifdef CONFIG_DEBUG_FS
|
||||||
|
if (new_crtc_state->active &&
|
||||||
|
amdgpu_dm_is_valid_crc_source(dm_new_crtc_state->crc_src)) {
|
||||||
/**
|
/**
|
||||||
* Frontend may have changed so reapply the CRC capture
|
* Frontend may have changed so reapply the CRC capture
|
||||||
* settings for the stream.
|
* settings for the stream.
|
||||||
*/
|
*/
|
||||||
dm_new_crtc_state = to_dm_crtc_state(new_crtc_state);
|
dm_new_crtc_state = to_dm_crtc_state(new_crtc_state);
|
||||||
|
dm_old_crtc_state = to_dm_crtc_state(old_crtc_state);
|
||||||
|
|
||||||
if (amdgpu_dm_is_valid_crc_source(dm_new_crtc_state->crc_src)) {
|
if (amdgpu_dm_crc_window_is_default(dm_new_crtc_state)) {
|
||||||
amdgpu_dm_crtc_configure_crc_source(
|
if (!old_crtc_state->active || drm_atomic_crtc_needs_modeset(new_crtc_state))
|
||||||
crtc, dm_new_crtc_state,
|
configure_crc = true;
|
||||||
dm_new_crtc_state->crc_src);
|
} else {
|
||||||
|
if (amdgpu_dm_crc_window_changed(dm_new_crtc_state, dm_old_crtc_state))
|
||||||
|
configure_crc = true;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
if (configure_crc)
|
||||||
|
amdgpu_dm_crtc_configure_crc_source(
|
||||||
|
crtc, dm_new_crtc_state, dm_new_crtc_state->crc_src);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
for_each_new_crtc_in_state(state, crtc, new_crtc_state, j)
|
for_each_new_crtc_in_state(state, crtc, new_crtc_state, j)
|
||||||
|
@ -336,6 +336,13 @@ struct amdgpu_display_manager {
|
|||||||
*/
|
*/
|
||||||
const struct gpu_info_soc_bounding_box_v1_0 *soc_bounding_box;
|
const struct gpu_info_soc_bounding_box_v1_0 *soc_bounding_box;
|
||||||
|
|
||||||
|
#ifdef CONFIG_DEBUG_FS
|
||||||
|
/* set the crc calculation window*/
|
||||||
|
struct drm_property *crc_win_x_start_property;
|
||||||
|
struct drm_property *crc_win_y_start_property;
|
||||||
|
struct drm_property *crc_win_x_end_property;
|
||||||
|
struct drm_property *crc_win_y_end_property;
|
||||||
|
#endif
|
||||||
/**
|
/**
|
||||||
* @mst_encoders:
|
* @mst_encoders:
|
||||||
*
|
*
|
||||||
@ -422,6 +429,15 @@ struct dm_plane_state {
|
|||||||
struct dc_plane_state *dc_state;
|
struct dc_plane_state *dc_state;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifdef CONFIG_DEBUG_FS
|
||||||
|
struct crc_rec {
|
||||||
|
uint16_t x_start;
|
||||||
|
uint16_t y_start;
|
||||||
|
uint16_t x_end;
|
||||||
|
uint16_t y_end;
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
struct dm_crtc_state {
|
struct dm_crtc_state {
|
||||||
struct drm_crtc_state base;
|
struct drm_crtc_state base;
|
||||||
struct dc_stream_state *stream;
|
struct dc_stream_state *stream;
|
||||||
@ -444,6 +460,9 @@ struct dm_crtc_state {
|
|||||||
struct dc_info_packet vrr_infopacket;
|
struct dc_info_packet vrr_infopacket;
|
||||||
|
|
||||||
int abm_level;
|
int abm_level;
|
||||||
|
#ifdef CONFIG_DEBUG_FS
|
||||||
|
struct crc_rec crc_window;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
#define to_dm_crtc_state(x) container_of(x, struct dm_crtc_state, base)
|
#define to_dm_crtc_state(x) container_of(x, struct dm_crtc_state, base)
|
||||||
|
@ -81,6 +81,33 @@ const char *const *amdgpu_dm_crtc_get_crc_sources(struct drm_crtc *crtc,
|
|||||||
return pipe_crc_sources;
|
return pipe_crc_sources;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool amdgpu_dm_crc_window_is_default(struct dm_crtc_state *dm_crtc_state)
|
||||||
|
{
|
||||||
|
bool ret = true;
|
||||||
|
|
||||||
|
if ((dm_crtc_state->crc_window.x_start != 0) ||
|
||||||
|
(dm_crtc_state->crc_window.y_start != 0) ||
|
||||||
|
(dm_crtc_state->crc_window.x_end != 0) ||
|
||||||
|
(dm_crtc_state->crc_window.y_end != 0))
|
||||||
|
ret = false;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool amdgpu_dm_crc_window_changed(struct dm_crtc_state *dm_new_crtc_state,
|
||||||
|
struct dm_crtc_state *dm_old_crtc_state)
|
||||||
|
{
|
||||||
|
bool ret = false;
|
||||||
|
|
||||||
|
if ((dm_new_crtc_state->crc_window.x_start != dm_old_crtc_state->crc_window.x_start) ||
|
||||||
|
(dm_new_crtc_state->crc_window.y_start != dm_old_crtc_state->crc_window.y_start) ||
|
||||||
|
(dm_new_crtc_state->crc_window.x_end != dm_old_crtc_state->crc_window.x_end) ||
|
||||||
|
(dm_new_crtc_state->crc_window.y_end != dm_old_crtc_state->crc_window.y_end))
|
||||||
|
ret = true;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
amdgpu_dm_crtc_verify_crc_source(struct drm_crtc *crtc, const char *src_name,
|
amdgpu_dm_crtc_verify_crc_source(struct drm_crtc *crtc, const char *src_name,
|
||||||
size_t *values_cnt)
|
size_t *values_cnt)
|
||||||
@ -105,6 +132,7 @@ int amdgpu_dm_crtc_configure_crc_source(struct drm_crtc *crtc,
|
|||||||
struct dc_stream_state *stream_state = dm_crtc_state->stream;
|
struct dc_stream_state *stream_state = dm_crtc_state->stream;
|
||||||
bool enable = amdgpu_dm_is_valid_crc_source(source);
|
bool enable = amdgpu_dm_is_valid_crc_source(source);
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
struct crc_params *crc_window = NULL, tmp_window;
|
||||||
|
|
||||||
/* Configuration will be deferred to stream enable. */
|
/* Configuration will be deferred to stream enable. */
|
||||||
if (!stream_state)
|
if (!stream_state)
|
||||||
@ -114,8 +142,21 @@ int amdgpu_dm_crtc_configure_crc_source(struct drm_crtc *crtc,
|
|||||||
|
|
||||||
/* Enable CRTC CRC generation if necessary. */
|
/* Enable CRTC CRC generation if necessary. */
|
||||||
if (dm_is_crc_source_crtc(source)) {
|
if (dm_is_crc_source_crtc(source)) {
|
||||||
|
if (!amdgpu_dm_crc_window_is_default(dm_crtc_state)) {
|
||||||
|
crc_window = &tmp_window;
|
||||||
|
|
||||||
|
tmp_window.windowa_x_start = dm_crtc_state->crc_window.x_start;
|
||||||
|
tmp_window.windowa_y_start = dm_crtc_state->crc_window.y_start;
|
||||||
|
tmp_window.windowa_x_end = dm_crtc_state->crc_window.x_end;
|
||||||
|
tmp_window.windowa_y_end = dm_crtc_state->crc_window.y_end;
|
||||||
|
tmp_window.windowb_x_start = dm_crtc_state->crc_window.x_start;
|
||||||
|
tmp_window.windowb_y_start = dm_crtc_state->crc_window.y_start;
|
||||||
|
tmp_window.windowb_x_end = dm_crtc_state->crc_window.x_end;
|
||||||
|
tmp_window.windowb_y_end = dm_crtc_state->crc_window.y_end;
|
||||||
|
}
|
||||||
|
|
||||||
if (!dc_stream_configure_crc(stream_state->ctx->dc,
|
if (!dc_stream_configure_crc(stream_state->ctx->dc,
|
||||||
stream_state, NULL, enable, enable)) {
|
stream_state, crc_window, enable, enable)) {
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
goto unlock;
|
goto unlock;
|
||||||
}
|
}
|
||||||
|
@ -47,6 +47,9 @@ static inline bool amdgpu_dm_is_valid_crc_source(enum amdgpu_dm_pipe_crc_source
|
|||||||
|
|
||||||
/* amdgpu_dm_crc.c */
|
/* amdgpu_dm_crc.c */
|
||||||
#ifdef CONFIG_DEBUG_FS
|
#ifdef CONFIG_DEBUG_FS
|
||||||
|
bool amdgpu_dm_crc_window_is_default(struct dm_crtc_state *dm_crtc_state);
|
||||||
|
bool amdgpu_dm_crc_window_changed(struct dm_crtc_state *dm_new_crtc_state,
|
||||||
|
struct dm_crtc_state *dm_old_crtc_state);
|
||||||
int amdgpu_dm_crtc_configure_crc_source(struct drm_crtc *crtc,
|
int amdgpu_dm_crtc_configure_crc_source(struct drm_crtc *crtc,
|
||||||
struct dm_crtc_state *dm_crtc_state,
|
struct dm_crtc_state *dm_crtc_state,
|
||||||
enum amdgpu_dm_pipe_crc_source source);
|
enum amdgpu_dm_pipe_crc_source source);
|
||||||
|
@ -3259,6 +3259,9 @@ void core_link_enable_stream(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(CONFIG_DRM_AMD_DC_DCN3_0)
|
||||||
|
#endif
|
||||||
|
|
||||||
dc->hwss.enable_audio_stream(pipe_ctx);
|
dc->hwss.enable_audio_stream(pipe_ctx);
|
||||||
|
|
||||||
/* turn off otg test pattern if enable */
|
/* turn off otg test pattern if enable */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user