@@ -8870,6 +8870,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 && new_crtc_state->checksum_region.region_changed) {
+ struct drm_checksum_region *region_data =
+ (struct drm_checksum_region *)new_crtc_state->checksum_region.region_blob->data;
+
+ if (region_data->checksum_region_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 crtc_state to dm_irq_params */
+ spin_lock_irqsave(&adev_to_drm(adev)->event_lock, flags);
+ acrtc->dm_irq_params.window_param.x_start = region_data->x_start;
+ acrtc->dm_irq_params.window_param.y_start = region_data->y_start;
+ acrtc->dm_irq_params.window_param.x_end = region_data->x_end;
+ acrtc->dm_irq_params.window_param.y_end = region_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");
+ }
+ }
+
+ new_crtc_state->checksum_region.region_changed = false;
+ }
+#endif
}
for_each_new_crtc_in_state(state, crtc, new_crtc_state, j)
@@ -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;
@@ -97,10 +97,13 @@ bool amdgpu_dm_crc_window_is_activated(struct drm_crtc *crtc);
void amdgpu_dm_crtc_handle_crc_window_irq(struct drm_crtc *crtc);
struct secure_display_context *amdgpu_dm_crtc_secure_display_create_contexts(
struct amdgpu_device *adev);
+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_set_secure_display_crc_source(x)
#endif
#endif /* AMD_DAL_DEV_AMDGPU_DM_AMDGPU_DM_CRC_H_ */
@@ -461,6 +461,11 @@ int amdgpu_dm_crtc_init(struct amdgpu_display_manager *dm,
dm->adev->mode_info.crtcs[crtc_index] = acrtc;
+#ifdef CONFIG_DRM_AMD_SECURE_DISPLAY
+ if (drm_crtc_create_checksum_region_properties(&acrtc->base))
+ DRM_ERROR("amdgpu: failed to create checksum region properties.\n");
+#endif
+
/* Don't enable DRM CRTC degamma property for DCE since it doesn't
* support programmable degamma anywhere.
*/
This commit creates checksum_region properties at CRTC initialization, and update the new region during the atomic atomic. A new function amdgpu_dm_crtc_set_secure_display_crc_source() is implemented to control the state of CRC engine of DC hardware. Signed-off-by: Alan Liu <HaoPing.Liu@amd.com> --- .../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 + .../amd/display/amdgpu_dm/amdgpu_dm_crtc.c | 5 ++ 4 files changed, 103 insertions(+)