From: Bhawanpreet Lakha <[email protected]> Add KUnit tests for amdgpu_dm_prune_primary_tile_modes() covering the no-sink, no panel-patch and non-tiled early returns, a secondary tile, and the primary-tile path that prunes per-tile modes.
Assisted-by: Copilot:Claude-Opus-4.8 Reviewed-by: Alex Hung <[email protected]> Signed-off-by: Bhawanpreet Lakha <[email protected]> Signed-off-by: Ivan Lipski <[email protected]> --- .../display/amdgpu_dm/amdgpu_dm_connector.c | 3 +- .../display/amdgpu_dm/amdgpu_dm_connector.h | 1 + .../tests/amdgpu_dm_connector_test.c | 172 ++++++++++++++++++ 3 files changed, 175 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_connector.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_connector.c index ddefef1debf25..a473218f4d75c 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_connector.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_connector.c @@ -2853,7 +2853,7 @@ EXPORT_IF_KUNIT(amdgpu_set_panel_orientation); * per-tile timing from the primary connector so compositors only pick the full * 5K mode. */ -static void amdgpu_dm_prune_primary_tile_modes(struct drm_connector *connector) +STATIC_IFN_KUNIT void amdgpu_dm_prune_primary_tile_modes(struct drm_connector *connector) { struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector); struct drm_display_mode *mode, *t; @@ -2886,6 +2886,7 @@ static void amdgpu_dm_prune_primary_tile_modes(struct drm_connector *connector) aconnector->num_modes--; } } +EXPORT_IF_KUNIT(amdgpu_dm_prune_primary_tile_modes); STATIC_IFN_KUNIT void amdgpu_dm_connector_ddc_get_modes(struct drm_connector *connector, const struct drm_edid *drm_edid) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_connector.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_connector.h index 91b8434ba591d..a86d5c879b646 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_connector.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_connector.h @@ -169,6 +169,7 @@ void amdgpu_dm_connector_add_common_modes(struct drm_encoder *encoder, void amdgpu_dm_connector_ddc_get_modes(struct drm_connector *connector, const struct drm_edid *drm_edid); int amdgpu_dm_connector_get_modes(struct drm_connector *connector); +void amdgpu_dm_prune_primary_tile_modes(struct drm_connector *connector); uint add_fs_modes(struct amdgpu_dm_connector *aconnector); void amdgpu_dm_connector_add_freesync_modes(struct drm_connector *connector, const struct drm_edid *drm_edid); diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_connector_test.c b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_connector_test.c index e63202fc7ba9f..e022f93c36cf5 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_connector_test.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_connector_test.c @@ -7540,6 +7540,172 @@ static void dm_test_panel_orientation_applies_quirk(struct kunit *test) DRM_MODE_PANEL_ORIENTATION_UNKNOWN); } +/* Tests for amdgpu_dm_prune_primary_tile_modes() */ + +struct dm_test_prune_ctx { + struct drm_device *drm; + struct amdgpu_dm_connector *aconnector; + struct dc_sink *sink; +}; + +/* + * Build a connector configured as the primary tile of an Apple Studio Display: + * a dc_sink requesting the second-tile patch, has_tile set, tile location (0,0) + * and a per-tile timing of tile_h_size x tile_v_size. Individual tests relax a + * single precondition to exercise the early-return guards. + */ +static struct dm_test_prune_ctx * +dm_test_prune_ctx_alloc(struct kunit *test) +{ + struct dm_test_prune_ctx *ctx; + + ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL); + KUNIT_ASSERT_NOT_NULL(test, ctx); + + ctx->drm = dm_test_alloc_drm(test); + ctx->aconnector = dm_test_add_connector(test, ctx->drm, + DRM_MODE_CONNECTOR_DisplayPort); + + ctx->sink = kunit_kzalloc(test, sizeof(*ctx->sink), GFP_KERNEL); + KUNIT_ASSERT_NOT_NULL(test, ctx->sink); + ctx->sink->edid_caps.panel_patch.disable_second_tile = true; + ctx->aconnector->dc_sink = ctx->sink; + + ctx->aconnector->base.has_tile = true; + ctx->aconnector->base.tile_h_size = 2560; + ctx->aconnector->base.tile_v_size = 2880; + + return ctx; +} + +static struct drm_display_mode * +dm_test_prune_add_mode(struct kunit *test, struct drm_connector *connector, + int hdisplay, int vdisplay) +{ + struct drm_display_mode *mode = drm_mode_create(connector->dev); + + KUNIT_ASSERT_NOT_NULL(test, mode); + mode->hdisplay = hdisplay; + mode->vdisplay = vdisplay; + list_add_tail(&mode->head, &connector->probed_modes); + + return mode; +} + +static int dm_test_prune_count(struct drm_connector *connector) +{ + struct drm_display_mode *mode; + int n = 0; + + list_for_each_entry(mode, &connector->probed_modes, head) + n++; + + return n; +} + +/** + * dm_test_prune_no_sink - Test a connector without a sink is left untouched + * @test: The KUnit test context + */ +static void dm_test_prune_no_sink(struct kunit *test) +{ + struct dm_test_prune_ctx *ctx = dm_test_prune_ctx_alloc(test); + + ctx->aconnector->dc_sink = NULL; + dm_test_prune_add_mode(test, &ctx->aconnector->base, 2560, 2880); + ctx->aconnector->num_modes = 1; + + amdgpu_dm_prune_primary_tile_modes(&ctx->aconnector->base); + + KUNIT_EXPECT_EQ(test, dm_test_prune_count(&ctx->aconnector->base), 1); + KUNIT_EXPECT_EQ(test, ctx->aconnector->num_modes, 1); +} + +/** + * dm_test_prune_no_patch - Test the patch flag being unset skips pruning + * @test: The KUnit test context + */ +static void dm_test_prune_no_patch(struct kunit *test) +{ + struct dm_test_prune_ctx *ctx = dm_test_prune_ctx_alloc(test); + + ctx->sink->edid_caps.panel_patch.disable_second_tile = false; + dm_test_prune_add_mode(test, &ctx->aconnector->base, 2560, 2880); + ctx->aconnector->num_modes = 1; + + amdgpu_dm_prune_primary_tile_modes(&ctx->aconnector->base); + + KUNIT_EXPECT_EQ(test, dm_test_prune_count(&ctx->aconnector->base), 1); + KUNIT_EXPECT_EQ(test, ctx->aconnector->num_modes, 1); +} + +/** + * dm_test_prune_no_tile - Test a non-tiled connector skips pruning + * @test: The KUnit test context + */ +static void dm_test_prune_no_tile(struct kunit *test) +{ + struct dm_test_prune_ctx *ctx = dm_test_prune_ctx_alloc(test); + + ctx->aconnector->base.has_tile = false; + dm_test_prune_add_mode(test, &ctx->aconnector->base, 2560, 2880); + ctx->aconnector->num_modes = 1; + + amdgpu_dm_prune_primary_tile_modes(&ctx->aconnector->base); + + KUNIT_EXPECT_EQ(test, dm_test_prune_count(&ctx->aconnector->base), 1); + KUNIT_EXPECT_EQ(test, ctx->aconnector->num_modes, 1); +} + +/** + * dm_test_prune_secondary_tile - Test a secondary tile is left untouched + * @test: The KUnit test context + * + * Only the primary tile (location 0,0) is pruned; a secondary tile keeps its + * per-tile timing. + */ +static void dm_test_prune_secondary_tile(struct kunit *test) +{ + struct dm_test_prune_ctx *ctx = dm_test_prune_ctx_alloc(test); + + ctx->aconnector->base.tile_h_loc = 1; + dm_test_prune_add_mode(test, &ctx->aconnector->base, 2560, 2880); + ctx->aconnector->num_modes = 1; + + amdgpu_dm_prune_primary_tile_modes(&ctx->aconnector->base); + + KUNIT_EXPECT_EQ(test, dm_test_prune_count(&ctx->aconnector->base), 1); + KUNIT_EXPECT_EQ(test, ctx->aconnector->num_modes, 1); +} + +/** + * dm_test_prune_removes_per_tile - Test the per-tile timing is pruned + * @test: The KUnit test context + * + * On the primary tile the per-tile (tile_h_size x tile_v_size) timing is + * dropped while the full-resolution mode is kept and num_modes is decremented. + */ +static void dm_test_prune_removes_per_tile(struct kunit *test) +{ + struct dm_test_prune_ctx *ctx = dm_test_prune_ctx_alloc(test); + struct drm_display_mode *mode; + bool has_tile_mode = false; + + dm_test_prune_add_mode(test, &ctx->aconnector->base, 2560, 2880); + dm_test_prune_add_mode(test, &ctx->aconnector->base, 5120, 2880); + ctx->aconnector->num_modes = 2; + + amdgpu_dm_prune_primary_tile_modes(&ctx->aconnector->base); + + KUNIT_EXPECT_EQ(test, dm_test_prune_count(&ctx->aconnector->base), 1); + KUNIT_EXPECT_EQ(test, ctx->aconnector->num_modes, 1); + + list_for_each_entry(mode, &ctx->aconnector->base.probed_modes, head) + if (mode->hdisplay == 2560 && mode->vdisplay == 2880) + has_tile_mode = true; + KUNIT_EXPECT_FALSE(test, has_tile_mode); +} + /* Tests for amdgpu_dm_update_stream_scaling_settings() */ /** @@ -8015,6 +8181,12 @@ static struct kunit_case amdgpu_dm_connector_tests[] = { KUNIT_CASE(dm_test_panel_orientation_non_edp), KUNIT_CASE(dm_test_panel_orientation_no_native_mode), KUNIT_CASE(dm_test_panel_orientation_applies_quirk), + /* amdgpu_dm_prune_primary_tile_modes */ + KUNIT_CASE(dm_test_prune_no_sink), + KUNIT_CASE(dm_test_prune_no_patch), + KUNIT_CASE(dm_test_prune_no_tile), + KUNIT_CASE(dm_test_prune_secondary_tile), + KUNIT_CASE(dm_test_prune_removes_per_tile), /* dm_validate_stream_and_context */ KUNIT_CASE(dm_test_validate_stream_null_stream), KUNIT_CASE(dm_test_validate_stream_dc_ok_no_pipe), -- 2.43.0
