From: Alex Hung <[email protected]>

[WHAT]
Add KUnit tests for the stream scaling path: a disable-underscan case
for is_scaling_state_different, and coverage of
amdgpu_dm_update_stream_scaling_settings across the full-screen
default, RMX_FULL, RMX_ASPECT pillarbox/letterbox, RMX_CENTER and
underscan paths.

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 |   1 +
 .../display/amdgpu_dm/tests/amdgpu_dm_test.c  | 231 ++++++++++++++++++
 2 files changed, 232 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 7806b3405c3d..fc1a73435203 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -3456,6 +3456,7 @@ void amdgpu_dm_update_stream_scaling_settings(struct 
drm_device *dev,
                    dst.x, dst.y, dst.width, dst.height);
 
 }
+EXPORT_IF_KUNIT(amdgpu_dm_update_stream_scaling_settings);
 
 static int dm_update_mst_vcpi_slots_for_dsc(struct drm_atomic_state *state,
                                            struct dc_state *dc_state,
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 92056f4147d3..724d03db2736 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
@@ -830,6 +830,28 @@ static void dm_test_scaling_state_underscan_enabled(struct 
kunit *test)
        KUNIT_EXPECT_TRUE(test, is_scaling_state_different(new_state, 
old_state));
 }
 
+/**
+ * dm_test_scaling_state_underscan_disabled - Test disabling underscan with 
borders differs
+ * @test: The KUnit test context
+ */
+static void dm_test_scaling_state_underscan_disabled(struct kunit *test)
+{
+       struct dm_connector_state *old_state;
+       struct dm_connector_state *new_state;
+
+       old_state = kunit_kzalloc(test, sizeof(*old_state), GFP_KERNEL);
+       new_state = kunit_kzalloc(test, sizeof(*new_state), GFP_KERNEL);
+       KUNIT_ASSERT_NOT_NULL(test, old_state);
+       KUNIT_ASSERT_NOT_NULL(test, new_state);
+
+       old_state->underscan_enable = true;
+       old_state->underscan_hborder = 16;
+       old_state->underscan_vborder = 16;
+       new_state->underscan_enable = false;
+
+       KUNIT_EXPECT_TRUE(test, is_scaling_state_different(new_state, 
old_state));
+}
+
 /**
  * dm_test_scaling_state_underscan_border_changed - Test changed underscan 
borders differ
  * @test: The KUnit test context
@@ -1203,6 +1225,206 @@ static void 
dm_test_master_stream_defaults_to_first(struct kunit *test)
                            stream0);
 }
 
+/* Tests for amdgpu_dm_update_stream_scaling_settings() */
+
+/**
+ * dm_test_update_scaling_null_mode - Test NULL mode leaves the stream rects 
untouched
+ * @test: The KUnit test context
+ */
+static void dm_test_update_scaling_null_mode(struct kunit *test)
+{
+       struct amdgpu_device *adev = dm_kunit_alloc_adev(test);
+       struct dc_stream_state *stream = dm_kunit_alloc_stream(test, NULL);
+
+       stream->timing.h_addressable = 1920;
+       stream->timing.v_addressable = 1080;
+
+       amdgpu_dm_update_stream_scaling_settings(&adev->ddev, NULL, NULL, 
stream);
+
+       /* NULL mode: early return before touching src/dst */
+       KUNIT_EXPECT_EQ(test, stream->src.width, 0);
+       KUNIT_EXPECT_EQ(test, stream->dst.width, 0);
+}
+
+/**
+ * dm_test_update_scaling_fullscreen_default - Test full-screen default with 
no dm_state
+ * @test: The KUnit test context
+ */
+static void dm_test_update_scaling_fullscreen_default(struct kunit *test)
+{
+       struct amdgpu_device *adev = dm_kunit_alloc_adev(test);
+       struct dc_stream_state *stream = dm_kunit_alloc_stream(test, NULL);
+       struct drm_display_mode mode = { 0 };
+
+       mode.hdisplay = 1920;
+       mode.vdisplay = 1080;
+       stream->timing.h_addressable = 2560;
+       stream->timing.v_addressable = 1440;
+
+       amdgpu_dm_update_stream_scaling_settings(&adev->ddev, &mode, NULL, 
stream);
+
+       /* src = mode, dst = timing addressable, no centering without dm_state 
*/
+       KUNIT_EXPECT_EQ(test, stream->src.width, 1920);
+       KUNIT_EXPECT_EQ(test, stream->src.height, 1080);
+       KUNIT_EXPECT_EQ(test, stream->dst.width, 2560);
+       KUNIT_EXPECT_EQ(test, stream->dst.height, 1440);
+       KUNIT_EXPECT_EQ(test, stream->dst.x, 0);
+       KUNIT_EXPECT_EQ(test, stream->dst.y, 0);
+}
+
+/**
+ * dm_test_update_scaling_rmx_full - Test RMX_FULL keeps a full-size, centered 
dst
+ * @test: The KUnit test context
+ */
+static void dm_test_update_scaling_rmx_full(struct kunit *test)
+{
+       struct amdgpu_device *adev = dm_kunit_alloc_adev(test);
+       struct dc_stream_state *stream = dm_kunit_alloc_stream(test, NULL);
+       struct dm_connector_state *dm_state;
+       struct drm_display_mode mode = { 0 };
+
+       dm_state = kunit_kzalloc(test, sizeof(*dm_state), GFP_KERNEL);
+       KUNIT_ASSERT_NOT_NULL(test, dm_state);
+
+       mode.hdisplay = 1280;
+       mode.vdisplay = 720;
+       stream->timing.h_addressable = 1920;
+       stream->timing.v_addressable = 1080;
+       dm_state->scaling = RMX_FULL;
+
+       amdgpu_dm_update_stream_scaling_settings(&adev->ddev, &mode, dm_state, 
stream);
+
+       /* RMX_FULL: dst stays full addressable, offset 0 */
+       KUNIT_EXPECT_EQ(test, stream->dst.width, 1920);
+       KUNIT_EXPECT_EQ(test, stream->dst.height, 1080);
+       KUNIT_EXPECT_EQ(test, stream->dst.x, 0);
+       KUNIT_EXPECT_EQ(test, stream->dst.y, 0);
+}
+
+/**
+ * dm_test_update_scaling_rmx_aspect_pillarbox - Test RMX_ASPECT preserves 
aspect ratio
+ * @test: The KUnit test context
+ */
+static void dm_test_update_scaling_rmx_aspect_pillarbox(struct kunit *test)
+{
+       struct amdgpu_device *adev = dm_kunit_alloc_adev(test);
+       struct dc_stream_state *stream = dm_kunit_alloc_stream(test, NULL);
+       struct dm_connector_state *dm_state;
+       struct drm_display_mode mode = { 0 };
+
+       dm_state = kunit_kzalloc(test, sizeof(*dm_state), GFP_KERNEL);
+       KUNIT_ASSERT_NOT_NULL(test, dm_state);
+
+       /* 4:3 source on a 16:9 panel -> pillarboxed */
+       mode.hdisplay = 1024;
+       mode.vdisplay = 768;
+       stream->timing.h_addressable = 1920;
+       stream->timing.v_addressable = 1080;
+       dm_state->scaling = RMX_ASPECT;
+
+       amdgpu_dm_update_stream_scaling_settings(&adev->ddev, &mode, dm_state, 
stream);
+
+       /*
+        * src.width*dst.height (1024*1080) < src.height*dst.width (768*1920):
+        * width scaled to src.width*dst.height/src.height = 1440, height stays
+        * 1080, centered horizontally at (1920-1440)/2 = 240.
+        */
+       KUNIT_EXPECT_EQ(test, stream->dst.width, 1440);
+       KUNIT_EXPECT_EQ(test, stream->dst.height, 1080);
+       KUNIT_EXPECT_EQ(test, stream->dst.x, 240);
+       KUNIT_EXPECT_EQ(test, stream->dst.y, 0);
+}
+
+/**
+ * dm_test_update_scaling_rmx_aspect_letterbox - Test RMX_ASPECT letterboxes 
wide sources
+ * @test: The KUnit test context
+ */
+static void dm_test_update_scaling_rmx_aspect_letterbox(struct kunit *test)
+{
+       struct amdgpu_device *adev = dm_kunit_alloc_adev(test);
+       struct dc_stream_state *stream = dm_kunit_alloc_stream(test, NULL);
+       struct dm_connector_state *dm_state;
+       struct drm_display_mode mode = { 0 };
+
+       dm_state = kunit_kzalloc(test, sizeof(*dm_state), GFP_KERNEL);
+       KUNIT_ASSERT_NOT_NULL(test, dm_state);
+
+       /* 16:9 source on a 4:3 panel -> letterboxed */
+       mode.hdisplay = 1920;
+       mode.vdisplay = 1080;
+       stream->timing.h_addressable = 1024;
+       stream->timing.v_addressable = 768;
+       dm_state->scaling = RMX_ASPECT;
+
+       amdgpu_dm_update_stream_scaling_settings(&adev->ddev, &mode, dm_state, 
stream);
+
+       KUNIT_EXPECT_EQ(test, stream->dst.width, 1024);
+       KUNIT_EXPECT_EQ(test, stream->dst.height, 576);
+       KUNIT_EXPECT_EQ(test, stream->dst.x, 0);
+       KUNIT_EXPECT_EQ(test, stream->dst.y, 96);
+}
+
+/**
+ * dm_test_update_scaling_rmx_center - Test RMX_CENTER centers a 1:1 dst
+ * @test: The KUnit test context
+ */
+static void dm_test_update_scaling_rmx_center(struct kunit *test)
+{
+       struct amdgpu_device *adev = dm_kunit_alloc_adev(test);
+       struct dc_stream_state *stream = dm_kunit_alloc_stream(test, NULL);
+       struct dm_connector_state *dm_state;
+       struct drm_display_mode mode = { 0 };
+
+       dm_state = kunit_kzalloc(test, sizeof(*dm_state), GFP_KERNEL);
+       KUNIT_ASSERT_NOT_NULL(test, dm_state);
+
+       mode.hdisplay = 1280;
+       mode.vdisplay = 720;
+       stream->timing.h_addressable = 1920;
+       stream->timing.v_addressable = 1080;
+       dm_state->scaling = RMX_CENTER;
+
+       amdgpu_dm_update_stream_scaling_settings(&adev->ddev, &mode, dm_state, 
stream);
+
+       /* RMX_CENTER: dst = src, centered on the addressable area */
+       KUNIT_EXPECT_EQ(test, stream->dst.width, 1280);
+       KUNIT_EXPECT_EQ(test, stream->dst.height, 720);
+       KUNIT_EXPECT_EQ(test, stream->dst.x, 320);
+       KUNIT_EXPECT_EQ(test, stream->dst.y, 180);
+}
+
+/**
+ * dm_test_update_scaling_underscan - Test underscan borders shrink and offset 
dst
+ * @test: The KUnit test context
+ */
+static void dm_test_update_scaling_underscan(struct kunit *test)
+{
+       struct amdgpu_device *adev = dm_kunit_alloc_adev(test);
+       struct dc_stream_state *stream = dm_kunit_alloc_stream(test, NULL);
+       struct dm_connector_state *dm_state;
+       struct drm_display_mode mode = { 0 };
+
+       dm_state = kunit_kzalloc(test, sizeof(*dm_state), GFP_KERNEL);
+       KUNIT_ASSERT_NOT_NULL(test, dm_state);
+
+       mode.hdisplay = 1920;
+       mode.vdisplay = 1080;
+       stream->timing.h_addressable = 1920;
+       stream->timing.v_addressable = 1080;
+       dm_state->scaling = RMX_FULL;
+       dm_state->underscan_enable = true;
+       dm_state->underscan_hborder = 64;
+       dm_state->underscan_vborder = 32;
+
+       amdgpu_dm_update_stream_scaling_settings(&adev->ddev, &mode, dm_state, 
stream);
+
+       /* Full dst, then underscan: x/y += border/2, width/height -= border */
+       KUNIT_EXPECT_EQ(test, stream->dst.x, 32);
+       KUNIT_EXPECT_EQ(test, stream->dst.y, 16);
+       KUNIT_EXPECT_EQ(test, stream->dst.width, 1856);
+       KUNIT_EXPECT_EQ(test, stream->dst.height, 1048);
+}
+
 static struct kunit_case amdgpu_dm_tests[] = {
        /* Simple DM callbacks */
        KUNIT_CASE(dm_test_is_idle),
@@ -1254,6 +1476,7 @@ static struct kunit_case amdgpu_dm_tests[] = {
        KUNIT_CASE(dm_test_scaling_state_same),
        KUNIT_CASE(dm_test_scaling_state_scaling_changed),
        KUNIT_CASE(dm_test_scaling_state_underscan_enabled),
+       KUNIT_CASE(dm_test_scaling_state_underscan_disabled),
        KUNIT_CASE(dm_test_scaling_state_underscan_border_changed),
        /* is_timing_unchanged_for_freesync */
        KUNIT_CASE(dm_test_timing_unchanged_null_args),
@@ -1274,6 +1497,14 @@ static struct kunit_case amdgpu_dm_tests[] = {
        /* set_master_stream */
        KUNIT_CASE(dm_test_master_stream_highest_refresh),
        KUNIT_CASE(dm_test_master_stream_defaults_to_first),
+       /* amdgpu_dm_update_stream_scaling_settings */
+       KUNIT_CASE(dm_test_update_scaling_null_mode),
+       KUNIT_CASE(dm_test_update_scaling_fullscreen_default),
+       KUNIT_CASE(dm_test_update_scaling_rmx_full),
+       KUNIT_CASE(dm_test_update_scaling_rmx_aspect_pillarbox),
+       KUNIT_CASE(dm_test_update_scaling_rmx_aspect_letterbox),
+       KUNIT_CASE(dm_test_update_scaling_rmx_center),
+       KUNIT_CASE(dm_test_update_scaling_underscan),
        {}
 };
 
-- 
2.43.0

Reply via email to