@@ -8877,7 +8877,12 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)
(struct drm_checksum_region *)new_crtc_state->checksum_region.region_blob->data;
if (region_data->checksum_region_enable) {
+ struct secure_display_context *secure_display_ctx =
+ &dm->secure_display_ctxs[acrtc->crtc_id];
+
if (!amdgpu_dm_crc_window_is_activated(crtc)) {
+ init_completion(&secure_display_ctx->crc.completion);
+
/* Enable secure display: set crc source to "crtc" */
amdgpu_dm_crtc_set_secure_display_crc_source(crtc, "crtc");
@@ -8887,7 +8892,8 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)
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);
- }
+ } else
+ reinit_completion(&secure_display_ctx->crc.completion);
/* Update ROI: copy ROI from crtc_state to dm_irq_params */
spin_lock_irqsave(&adev_to_drm(adev)->event_lock, flags);
@@ -529,6 +529,8 @@ void amdgpu_dm_crtc_handle_crc_window_irq(struct drm_crtc *crtc)
struct amdgpu_crtc *acrtc = NULL;
struct amdgpu_device *adev = NULL;
struct secure_display_context *secure_display_ctx = NULL;
+ bool reset_crc_frame_count = false, crc_is_updated = false;
+ uint32_t crc[3] = {0};
unsigned long flags1;
if (crtc == NULL)
@@ -543,15 +545,14 @@ void amdgpu_dm_crtc_handle_crc_window_irq(struct drm_crtc *crtc)
/* Early return if CRC capture is not enabled. */
if (!amdgpu_dm_is_valid_crc_source(cur_crc_src) ||
- !dm_is_crc_source_crtc(cur_crc_src))
- goto cleanup;
-
- if (!acrtc->dm_irq_params.window_param.activated)
- goto cleanup;
+ !dm_is_crc_source_crtc(cur_crc_src)) {
+ spin_unlock_irqrestore(&drm_dev->event_lock, flags1);
+ return;
+ }
- if (acrtc->dm_irq_params.window_param.skip_frame_cnt) {
- acrtc->dm_irq_params.window_param.skip_frame_cnt -= 1;
- goto cleanup;
+ if (!acrtc->dm_irq_params.window_param.activated) {
+ spin_unlock_irqrestore(&drm_dev->event_lock, flags1);
+ return;
}
secure_display_ctx = &adev->dm.secure_display_ctxs[acrtc->crtc_id];
@@ -562,16 +563,23 @@ void amdgpu_dm_crtc_handle_crc_window_irq(struct drm_crtc *crtc)
secure_display_ctx->crtc = crtc;
}
+ if (acrtc->dm_irq_params.window_param.skip_frame_cnt) {
+ acrtc->dm_irq_params.window_param.skip_frame_cnt -= 1;
+ goto cleanup;
+ }
+
if (acrtc->dm_irq_params.window_param.update_win) {
/* prepare work for dmub to update ROI */
secure_display_ctx->rect.x = acrtc->dm_irq_params.window_param.x_start;
secure_display_ctx->rect.y = acrtc->dm_irq_params.window_param.y_start;
secure_display_ctx->rect.width = acrtc->dm_irq_params.window_param.x_end -
- acrtc->dm_irq_params.window_param.x_start;
+ acrtc->dm_irq_params.window_param.x_start;
secure_display_ctx->rect.height = acrtc->dm_irq_params.window_param.y_end -
- acrtc->dm_irq_params.window_param.y_start;
+ acrtc->dm_irq_params.window_param.y_start;
schedule_work(&secure_display_ctx->forward_roi_work);
+ reset_crc_frame_count = true;
+
acrtc->dm_irq_params.window_param.update_win = false;
/* Statically skip 1 frame, because we may need to wait below things
@@ -582,12 +590,39 @@ void amdgpu_dm_crtc_handle_crc_window_irq(struct drm_crtc *crtc)
acrtc->dm_irq_params.window_param.skip_frame_cnt = 1;
} else {
+ struct dc_stream_state *stream_state = to_dm_crtc_state(crtc->state)->stream;
+
+ if (!dc_stream_get_crc(stream_state->ctx->dc, stream_state,
+ &crc[0], &crc[1], &crc[2]))
+ DRM_ERROR("Secure Display: fail to get crc\n");
+ else
+ crc_is_updated = true;
+
/* prepare work for psp to read ROI/CRC and send to I2C */
schedule_work(&secure_display_ctx->notify_ta_work);
}
cleanup:
spin_unlock_irqrestore(&drm_dev->event_lock, flags1);
+
+ spin_lock_irqsave(&secure_display_ctx->crc.lock, flags1);
+
+ if (reset_crc_frame_count || secure_display_ctx->crc.frame_count == UINT_MAX)
+ /* Reset the reference frame count after user update the ROI
+ * or it reaches the maximum value.
+ */
+ secure_display_ctx->crc.frame_count = 0;
+ else
+ secure_display_ctx->crc.frame_count += 1;
+
+ if (crc_is_updated) {
+ secure_display_ctx->crc.crc_R = crc[0];
+ secure_display_ctx->crc.crc_G = crc[1];
+ secure_display_ctx->crc.crc_B = crc[2];
+ complete_all(&secure_display_ctx->crc.completion);
+ }
+
+ spin_unlock_irqrestore(&secure_display_ctx->crc.lock, flags1);
}
struct secure_display_context *
@@ -40,6 +40,15 @@ enum amdgpu_dm_pipe_crc_source {
};
#ifdef CONFIG_DRM_AMD_SECURE_DISPLAY
+struct crc_data {
+ uint32_t crc_R;
+ uint32_t crc_G;
+ uint32_t crc_B;
+ uint32_t frame_count;
+ spinlock_t lock;
+ struct completion completion;
+};
+
struct crc_window_param {
uint16_t x_start;
uint16_t y_start;
@@ -64,6 +73,8 @@ struct secure_display_context {
/* Region of Interest (ROI) */
struct rect rect;
+
+ struct crc_data crc;
};
#endif
@@ -280,6 +280,50 @@ static void dm_crtc_reset_state(struct drm_crtc *crtc)
__drm_atomic_helper_crtc_reset(crtc, &state->base);
}
+#ifdef CONFIG_DRM_AMD_SECURE_DISPLAY
+static bool amdgpu_dm_crtc_update_checksum_region_crc(struct drm_crtc *crtc)
+{
+ struct amdgpu_device *adev = drm_to_adev(crtc->dev);
+ struct drm_crtc_state *crtc_state = crtc->state;
+ struct secure_display_context *secure_display_ctx =
+ &adev->dm.secure_display_ctxs[crtc->index];
+ struct drm_checksum_crc *new_data;
+ struct drm_property_blob *new_blob, **old_blob;
+ unsigned long flag;
+
+ if (!amdgpu_dm_crc_window_is_activated(crtc))
+ goto fail;
+
+ wait_for_completion_interruptible_timeout(
+ &secure_display_ctx->crc.completion, 10 * HZ);
+
+ new_blob = drm_property_create_blob(crtc->dev,
+ sizeof(struct drm_checksum_crc),
+ NULL);
+ if (IS_ERR(new_blob))
+ goto fail;
+
+ /* save new value to blob */
+ new_data = (struct drm_checksum_crc *) new_blob->data;
+ spin_lock_irqsave(&secure_display_ctx->crc.lock, flag);
+ new_data->crc_r = secure_display_ctx->crc.crc_R;
+ new_data->crc_g = secure_display_ctx->crc.crc_G;
+ new_data->crc_b = secure_display_ctx->crc.crc_B;
+ new_data->frame_count = secure_display_ctx->crc.frame_count;
+ spin_unlock_irqrestore(&secure_display_ctx->crc.lock, flag);
+
+ old_blob = &crtc_state->checksum_region.crc_blob;
+ if (!drm_property_replace_blob(old_blob, new_blob))
+ goto fail;
+
+ return true;
+
+fail:
+ DRM_WARN("Checksum Region: fail to update checksum_region CRC\n");
+ return false;
+}
+#endif
+
#ifdef CONFIG_DEBUG_FS
static int amdgpu_dm_crtc_late_register(struct drm_crtc *crtc)
{
@@ -307,6 +351,9 @@ static const struct drm_crtc_funcs amdgpu_dm_crtc_funcs = {
#if defined(CONFIG_DEBUG_FS)
.late_register = amdgpu_dm_crtc_late_register,
#endif
+#ifdef CONFIG_DRM_AMD_SECURE_DISPLAY
+ .update_checksum_region_crc = amdgpu_dm_crtc_update_checksum_region_crc,
+#endif
};
static void dm_crtc_helper_disable(struct drm_crtc *crtc)
Retrieve and store checksum_region's CRC data from the DC hardware in vline0 irq handler. A new function amdgpu_dm_crtc_update_checksum_region_crc() is implemented and hooked to CRTC callback for updating the latest CRC values to the checksum CRC blob. Signed-off-by: Alan Liu <HaoPing.Liu@amd.com> --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 8 ++- .../drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c | 55 +++++++++++++++---- .../drm/amd/display/amdgpu_dm/amdgpu_dm_crc.h | 11 ++++ .../amd/display/amdgpu_dm/amdgpu_dm_crtc.c | 47 ++++++++++++++++ 4 files changed, 110 insertions(+), 11 deletions(-)