From: Alex Hung <[email protected]> [WHAT] Add KUnit tests for is_content_protection_different using a shared connector/crtc fixture. Cover the content-type change, ENABLED->DESIRED re-enable (with and without modeset), UNDESIRED and DESIRED steady states, the update_hdcp hot-plug and stream re-enable paths, and the S3/DESIRED/UNDESIRED enable transitions.
Assisted-by: Copilot:Claude-Opus-4.8 Reviewed-by: Bhawanpreet Lakha <[email protected]> Signed-off-by: Alex Hung <[email protected]> Signed-off-by: Wayne Lin <[email protected]> --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 14 +- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 7 + .../display/amdgpu_dm/tests/amdgpu_dm_test.c | 237 ++++++++++++++++++ 3 files changed, 252 insertions(+), 6 deletions(-) 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 fc1a73435203..03b9079ce818 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -3653,12 +3653,13 @@ is_scaling_state_different(const struct dm_connector_state *dm_state, } EXPORT_IF_KUNIT(is_scaling_state_different); -static bool is_content_protection_different(struct drm_crtc_state *new_crtc_state, - struct drm_crtc_state *old_crtc_state, - struct drm_connector_state *new_conn_state, - struct drm_connector_state *old_conn_state, - const struct drm_connector *connector, - struct hdcp_workqueue *hdcp_w) +STATIC_IFN_KUNIT bool +is_content_protection_different(struct drm_crtc_state *new_crtc_state, + struct drm_crtc_state *old_crtc_state, + struct drm_connector_state *new_conn_state, + struct drm_connector_state *old_conn_state, + const struct drm_connector *connector, + struct hdcp_workqueue *hdcp_w) { struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector); struct dm_connector_state *dm_con_state = to_dm_connector_state(connector->state); @@ -3772,6 +3773,7 @@ static bool is_content_protection_different(struct drm_crtc_state *new_crtc_stat pr_debug("[HDCP_DM] DESIRED->ENABLED %s :false\n", __func__); return false; } +EXPORT_IF_KUNIT(is_content_protection_different); static void remove_stream(struct amdgpu_device *adev, struct amdgpu_crtc *acrtc, diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h index bef9663caf6e..c508f0be1b55 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h @@ -1178,6 +1178,13 @@ bool is_dc_timing_adjust_needed(struct dm_crtc_state *old_state, struct dm_crtc_state *new_state); void set_multisync_trigger_params(struct dc_stream_state *stream); void set_master_stream(struct dc_stream_state *stream_set[], int stream_count); +struct hdcp_workqueue; +bool is_content_protection_different(struct drm_crtc_state *new_crtc_state, + struct drm_crtc_state *old_crtc_state, + struct drm_connector_state *new_conn_state, + struct drm_connector_state *old_conn_state, + const struct drm_connector *connector, + struct hdcp_workqueue *hdcp_w); #endif #endif /* __AMDGPU_DM_H__ */ diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_test.c b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_test.c index 724d03db2736..1caacad43106 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_test.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_test.c @@ -1425,6 +1425,231 @@ static void dm_test_update_scaling_underscan(struct kunit *test) KUNIT_EXPECT_EQ(test, stream->dst.height, 1048); } +/* Tests for is_content_protection_different() */ + +struct dm_test_cp_ctx { + struct amdgpu_dm_connector *aconnector; + struct dm_connector_state *new_dm; /* also connector->state */ + struct dm_connector_state *old_dm; + struct drm_crtc_state *new_crtc; + struct drm_crtc_state *old_crtc; +}; + +static struct dm_test_cp_ctx *dm_test_cp_ctx_alloc(struct kunit *test) +{ + struct dm_test_cp_ctx *ctx; + + ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL); + KUNIT_ASSERT_NOT_NULL(test, ctx); + + ctx->aconnector = kunit_kzalloc(test, sizeof(*ctx->aconnector), GFP_KERNEL); + KUNIT_ASSERT_NOT_NULL(test, ctx->aconnector); + ctx->new_dm = kunit_kzalloc(test, sizeof(*ctx->new_dm), GFP_KERNEL); + KUNIT_ASSERT_NOT_NULL(test, ctx->new_dm); + ctx->old_dm = kunit_kzalloc(test, sizeof(*ctx->old_dm), GFP_KERNEL); + KUNIT_ASSERT_NOT_NULL(test, ctx->old_dm); + ctx->new_crtc = kunit_kzalloc(test, sizeof(*ctx->new_crtc), GFP_KERNEL); + KUNIT_ASSERT_NOT_NULL(test, ctx->new_crtc); + ctx->old_crtc = kunit_kzalloc(test, sizeof(*ctx->old_crtc), GFP_KERNEL); + KUNIT_ASSERT_NOT_NULL(test, ctx->old_crtc); + + /* connector->state must be the new dm connector state */ + ctx->aconnector->base.state = &ctx->new_dm->base; + ctx->aconnector->base.dpms = DRM_MODE_DPMS_ON; + + return ctx; +} + +static bool dm_test_cp_diff(struct dm_test_cp_ctx *ctx) +{ + return is_content_protection_different(ctx->new_crtc, ctx->old_crtc, + &ctx->new_dm->base, + &ctx->old_dm->base, + &ctx->aconnector->base, NULL); +} + +/** + * dm_test_cp_diff_hdcp_type_change - Test an HDCP content-type change forces true + * @test: The KUnit test context + */ +static void dm_test_cp_diff_hdcp_type_change(struct kunit *test) +{ + struct dm_test_cp_ctx *ctx = dm_test_cp_ctx_alloc(test); + + ctx->old_dm->base.hdcp_content_type = 0; + ctx->new_dm->base.hdcp_content_type = 1; + ctx->new_dm->base.content_protection = DRM_MODE_CONTENT_PROTECTION_ENABLED; + + KUNIT_EXPECT_TRUE(test, dm_test_cp_diff(ctx)); + KUNIT_EXPECT_EQ(test, (int)ctx->new_dm->base.content_protection, + (int)DRM_MODE_CONTENT_PROTECTION_DESIRED); +} + +/** + * dm_test_cp_diff_reenable_mode_changed - Test ENABLED->DESIRED with modeset forces true + * @test: The KUnit test context + */ +static void dm_test_cp_diff_reenable_mode_changed(struct kunit *test) +{ + struct dm_test_cp_ctx *ctx = dm_test_cp_ctx_alloc(test); + + ctx->old_dm->base.content_protection = DRM_MODE_CONTENT_PROTECTION_ENABLED; + ctx->new_dm->base.content_protection = DRM_MODE_CONTENT_PROTECTION_DESIRED; + ctx->new_crtc->mode_changed = true; + + KUNIT_EXPECT_TRUE(test, dm_test_cp_diff(ctx)); + KUNIT_EXPECT_EQ(test, (int)ctx->new_dm->base.content_protection, + (int)DRM_MODE_CONTENT_PROTECTION_DESIRED); +} + +/** + * dm_test_cp_diff_reenable_no_change - Test ENABLED->DESIRED without modeset restores ENABLED + * @test: The KUnit test context + */ +static void dm_test_cp_diff_reenable_no_change(struct kunit *test) +{ + struct dm_test_cp_ctx *ctx = dm_test_cp_ctx_alloc(test); + + ctx->old_dm->base.content_protection = DRM_MODE_CONTENT_PROTECTION_ENABLED; + ctx->new_dm->base.content_protection = DRM_MODE_CONTENT_PROTECTION_DESIRED; + ctx->new_crtc->mode_changed = false; + + KUNIT_EXPECT_FALSE(test, dm_test_cp_diff(ctx)); + KUNIT_EXPECT_EQ(test, (int)ctx->new_dm->base.content_protection, + (int)DRM_MODE_CONTENT_PROTECTION_ENABLED); +} + +/** + * dm_test_cp_diff_undesired - Test UNDESIRED->UNDESIRED needs no update + * @test: The KUnit test context + */ +static void dm_test_cp_diff_undesired(struct kunit *test) +{ + struct dm_test_cp_ctx *ctx = dm_test_cp_ctx_alloc(test); + + ctx->old_dm->base.content_protection = DRM_MODE_CONTENT_PROTECTION_UNDESIRED; + ctx->new_dm->base.content_protection = DRM_MODE_CONTENT_PROTECTION_UNDESIRED; + + KUNIT_EXPECT_FALSE(test, dm_test_cp_diff(ctx)); +} + +/** + * dm_test_cp_diff_desired_mode_changed - Test DESIRED->DESIRED with modeset forces true + * @test: The KUnit test context + */ +static void dm_test_cp_diff_desired_mode_changed(struct kunit *test) +{ + struct dm_test_cp_ctx *ctx = dm_test_cp_ctx_alloc(test); + + ctx->old_dm->base.content_protection = DRM_MODE_CONTENT_PROTECTION_DESIRED; + ctx->new_dm->base.content_protection = DRM_MODE_CONTENT_PROTECTION_DESIRED; + ctx->new_crtc->mode_changed = true; + + KUNIT_EXPECT_TRUE(test, dm_test_cp_diff(ctx)); +} + +/** + * dm_test_cp_diff_desired_no_change - Test steady DESIRED->DESIRED needs no update + * @test: The KUnit test context + */ +static void dm_test_cp_diff_desired_no_change(struct kunit *test) +{ + struct dm_test_cp_ctx *ctx = dm_test_cp_ctx_alloc(test); + + ctx->old_dm->base.content_protection = DRM_MODE_CONTENT_PROTECTION_DESIRED; + ctx->new_dm->base.content_protection = DRM_MODE_CONTENT_PROTECTION_DESIRED; + ctx->new_crtc->mode_changed = false; + + KUNIT_EXPECT_FALSE(test, dm_test_cp_diff(ctx)); +} + +/** + * dm_test_cp_diff_update_hdcp_hotplug - Test the update_hdcp hot-plug path forces true + * @test: The KUnit test context + */ +static void dm_test_cp_diff_update_hdcp_hotplug(struct kunit *test) +{ + struct dm_test_cp_ctx *ctx = dm_test_cp_ctx_alloc(test); + struct dc_sink *sink = kunit_kzalloc(test, sizeof(*sink), GFP_KERNEL); + + KUNIT_ASSERT_NOT_NULL(test, sink); + + ctx->old_dm->base.content_protection = DRM_MODE_CONTENT_PROTECTION_DESIRED; + ctx->new_dm->base.content_protection = DRM_MODE_CONTENT_PROTECTION_DESIRED; + ctx->new_dm->update_hdcp = true; + ctx->aconnector->base.dpms = DRM_MODE_DPMS_ON; + ctx->aconnector->dc_sink = sink; + + KUNIT_EXPECT_TRUE(test, dm_test_cp_diff(ctx)); + KUNIT_EXPECT_FALSE(test, ctx->new_dm->update_hdcp); +} + +/** + * dm_test_cp_diff_stream_reenabled - Test the stream removed-and-re-enabled path forces true + * @test: The KUnit test context + */ +static void dm_test_cp_diff_stream_reenabled(struct kunit *test) +{ + struct dm_test_cp_ctx *ctx = dm_test_cp_ctx_alloc(test); + struct drm_crtc *crtc = kunit_kzalloc(test, sizeof(*crtc), GFP_KERNEL); + + KUNIT_ASSERT_NOT_NULL(test, crtc); + crtc->enabled = true; + + ctx->old_dm->base.content_protection = DRM_MODE_CONTENT_PROTECTION_DESIRED; + ctx->new_dm->base.content_protection = DRM_MODE_CONTENT_PROTECTION_DESIRED; + ctx->new_dm->update_hdcp = true; + ctx->old_dm->base.crtc = NULL; + ctx->new_dm->base.crtc = crtc; + + KUNIT_EXPECT_TRUE(test, dm_test_cp_diff(ctx)); + KUNIT_EXPECT_FALSE(test, ctx->new_dm->update_hdcp); +} + +/** + * dm_test_cp_diff_s3_undesired_to_enabled - Test the S3 UNDESIRED->ENABLED path forces true + * @test: The KUnit test context + */ +static void dm_test_cp_diff_s3_undesired_to_enabled(struct kunit *test) +{ + struct dm_test_cp_ctx *ctx = dm_test_cp_ctx_alloc(test); + + ctx->old_dm->base.content_protection = DRM_MODE_CONTENT_PROTECTION_UNDESIRED; + ctx->new_dm->base.content_protection = DRM_MODE_CONTENT_PROTECTION_ENABLED; + + KUNIT_EXPECT_TRUE(test, dm_test_cp_diff(ctx)); + KUNIT_EXPECT_EQ(test, (int)ctx->new_dm->base.content_protection, + (int)DRM_MODE_CONTENT_PROTECTION_DESIRED); +} + +/** + * dm_test_cp_diff_desired_to_enabled - Test DESIRED->ENABLED needs no update + * @test: The KUnit test context + */ +static void dm_test_cp_diff_desired_to_enabled(struct kunit *test) +{ + struct dm_test_cp_ctx *ctx = dm_test_cp_ctx_alloc(test); + + ctx->old_dm->base.content_protection = DRM_MODE_CONTENT_PROTECTION_DESIRED; + ctx->new_dm->base.content_protection = DRM_MODE_CONTENT_PROTECTION_ENABLED; + + KUNIT_EXPECT_FALSE(test, dm_test_cp_diff(ctx)); +} + +/** + * dm_test_cp_diff_desired_to_undesired - Test DESIRED->UNDESIRED forces update + * @test: The KUnit test context + */ +static void dm_test_cp_diff_desired_to_undesired(struct kunit *test) +{ + struct dm_test_cp_ctx *ctx = dm_test_cp_ctx_alloc(test); + + ctx->old_dm->base.content_protection = DRM_MODE_CONTENT_PROTECTION_DESIRED; + ctx->new_dm->base.content_protection = DRM_MODE_CONTENT_PROTECTION_UNDESIRED; + + KUNIT_EXPECT_TRUE(test, dm_test_cp_diff(ctx)); +} + static struct kunit_case amdgpu_dm_tests[] = { /* Simple DM callbacks */ KUNIT_CASE(dm_test_is_idle), @@ -1505,6 +1730,18 @@ static struct kunit_case amdgpu_dm_tests[] = { KUNIT_CASE(dm_test_update_scaling_rmx_aspect_letterbox), KUNIT_CASE(dm_test_update_scaling_rmx_center), KUNIT_CASE(dm_test_update_scaling_underscan), + /* is_content_protection_different */ + KUNIT_CASE(dm_test_cp_diff_hdcp_type_change), + KUNIT_CASE(dm_test_cp_diff_reenable_mode_changed), + KUNIT_CASE(dm_test_cp_diff_reenable_no_change), + KUNIT_CASE(dm_test_cp_diff_undesired), + KUNIT_CASE(dm_test_cp_diff_desired_mode_changed), + KUNIT_CASE(dm_test_cp_diff_desired_no_change), + KUNIT_CASE(dm_test_cp_diff_update_hdcp_hotplug), + KUNIT_CASE(dm_test_cp_diff_stream_reenabled), + KUNIT_CASE(dm_test_cp_diff_s3_undesired_to_enabled), + KUNIT_CASE(dm_test_cp_diff_desired_to_enabled), + KUNIT_CASE(dm_test_cp_diff_desired_to_undesired), {} }; -- 2.43.0
