Check if there is a new ROI update during the atomic commit and process it. A new function amdgpu_dm_crtc_set_secure_display_crc_source() is implemented to control the state of CRC engine in hardware. Signed-off-by: Alan Liu <HaoPing.Liu@xxxxxxx> --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 38 +++++++++++++ .../drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c | 57 +++++++++++++++++++ .../drm/amd/display/amdgpu_dm/amdgpu_dm_crc.h | 3 + 3 files changed, 98 insertions(+) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 14b296e1d0f6..ee016d5be7ac 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -8857,6 +8857,44 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state) } } #endif + +#ifdef CONFIG_DRM_AMD_SECURE_DISPLAY + if (new_crtc_state->active && dm_new_crtc_state->secure_display_state.roi_changed) { + struct drm_roi *roi_data = + (struct drm_roi *)dm_new_crtc_state->secure_display_state.roi_blob->data; + + if (roi_data->secure_display_enable) { + if (!amdgpu_dm_crc_window_is_activated(crtc)) { + /* Enable secure display: set crc source to "crtc" */ + amdgpu_dm_crtc_set_secure_display_crc_source(crtc, "crtc"); + + /* wait 1 more frame for CRC engine to start */ + acrtc->dm_irq_params.window_param.skip_frame_cnt = 1; + + spin_lock_irqsave(&adev_to_drm(adev)->event_lock, flags); + acrtc->dm_irq_params.window_param.activated = true; + spin_unlock_irqrestore(&adev_to_drm(adev)->event_lock, flags); + } + + /* Update ROI: copy ROI from dm_crtc_state to dm_irq_params */ + spin_lock_irqsave(&adev_to_drm(adev)->event_lock, flags); + acrtc->dm_irq_params.window_param.x_start = roi_data->x_start; + acrtc->dm_irq_params.window_param.y_start = roi_data->y_start; + acrtc->dm_irq_params.window_param.x_end = roi_data->x_end; + acrtc->dm_irq_params.window_param.y_end = roi_data->y_end; + acrtc->dm_irq_params.window_param.update_win = true; + spin_unlock_irqrestore(&adev_to_drm(adev)->event_lock, flags); + + } else { + if (amdgpu_dm_crc_window_is_activated(crtc)) { + /* Disable secure display: set crc source to "none" */ + amdgpu_dm_crtc_set_secure_display_crc_source(crtc, "none"); + } + } + + dm_new_crtc_state->secure_display_state.roi_changed = false; + } +#endif } for_each_new_crtc_in_state(state, crtc, new_crtc_state, j) 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 a83cabb9b1a6..81e9995183ad 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 @@ -465,6 +465,63 @@ void amdgpu_dm_crtc_handle_crc_irq(struct drm_crtc *crtc) } #if defined(CONFIG_DRM_AMD_SECURE_DISPLAY) +int amdgpu_dm_crtc_set_secure_display_crc_source(struct drm_crtc *crtc, const char *src_name) +{ + enum amdgpu_dm_pipe_crc_source source = dm_parse_crc_source(src_name); + enum amdgpu_dm_pipe_crc_source cur_crc_src; + struct dm_crtc_state *crtc_state; + struct drm_device *drm_dev = crtc->dev; + struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); + bool enable = false; + bool enabled = false; + int ret = 0; + unsigned long flag; + + if (source < 0) { + DRM_DEBUG_DRIVER("Unknown CRC source %s for CRTC%d\n", + src_name, crtc->index); + return -EINVAL; + } + + enable = amdgpu_dm_is_valid_crc_source(source); + crtc_state = to_dm_crtc_state(crtc->state); + spin_lock_irqsave(&drm_dev->event_lock, flag); + cur_crc_src = acrtc->dm_irq_params.crc_src; + spin_unlock_irqrestore(&drm_dev->event_lock, flag); + + /* Reset secure_display when we change crc source */ + amdgpu_dm_set_crc_window_default(crtc, crtc_state->stream); + + if (amdgpu_dm_crtc_configure_crc_source(crtc, crtc_state, source)) { + ret = -EINVAL; + goto cleanup; + } + + /* + * Reading the CRC requires the vblank interrupt handler to be + * enabled. Keep a reference until CRC capture stops. + */ + enabled = amdgpu_dm_is_valid_crc_source(cur_crc_src); + if (!enabled && enable) { + ret = drm_crtc_vblank_get(crtc); + if (ret) + goto cleanup; + + } else if (enabled && !enable) { + drm_crtc_vblank_put(crtc); + } + + spin_lock_irqsave(&drm_dev->event_lock, flag); + acrtc->dm_irq_params.crc_src = source; + spin_unlock_irqrestore(&drm_dev->event_lock, flag); + + /* Reset crc_skipped on dm state */ + crtc_state->crc_skip_count = 0; + +cleanup: + return ret; +} + void amdgpu_dm_crtc_handle_crc_window_irq(struct drm_crtc *crtc) { struct drm_device *drm_dev = NULL; diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.h index f2def8c20d83..1b85d60488b6 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.h @@ -110,12 +110,15 @@ struct secure_display_context *amdgpu_dm_crtc_secure_display_create_contexts( int amdgpu_dm_crtc_create_secure_display_properties(struct amdgpu_device *adev); void amdgpu_dm_crtc_attach_secure_display_properties(struct amdgpu_device *adev, struct drm_crtc *crtc); +int amdgpu_dm_crtc_set_secure_display_crc_source(struct drm_crtc *crtc, + const char *src_name); #else #define amdgpu_dm_crc_window_is_activated(x) #define amdgpu_dm_crtc_handle_crc_window_irq(x) #define amdgpu_dm_crtc_secure_display_create_contexts(x) #define amdgpu_dm_crtc_create_secure_display_properties(x) #define amdgpu_dm_crtc_attach_secure_display_properties(x) +#define amdgpu_dm_crtc_set_secure_display_crc_source(x) #endif #endif /* AMD_DAL_DEV_AMDGPU_DM_AMDGPU_DM_CRC_H_ */ -- 2.34.1