From: Bhawanpreet Lakha <[email protected]>

Add KUnit tests for amdgpu_dm_connector_get_modes() covering the
no-EDID default modes, the extra modes added for 128b/132b and analog
links, and the path that adds modes from a valid EDID.

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   |   5 +-
 .../display/amdgpu_dm/amdgpu_dm_connector.h   |   1 +
 .../tests/amdgpu_dm_connector_test.c          | 178 ++++++++++++++++++
 3 files changed, 182 insertions(+), 2 deletions(-)

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 44c223b178c50..45ac4e2b5029b 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
@@ -256,7 +256,7 @@ STATIC_IFN_KUNIT void update_subconnector_property(struct 
amdgpu_dm_connector *a
 }
 EXPORT_IF_KUNIT(update_subconnector_property);
 
-static int amdgpu_dm_connector_get_modes(struct drm_connector *connector);
+STATIC_IFN_KUNIT int amdgpu_dm_connector_get_modes(struct drm_connector 
*connector);
 
 STATIC_IFN_KUNIT void amdgpu_dm_fbc_init(struct drm_connector *connector)
 {
@@ -3038,7 +3038,7 @@ STATIC_IFN_KUNIT void 
amdgpu_dm_connector_add_freesync_modes(struct drm_connecto
 }
 EXPORT_IF_KUNIT(amdgpu_dm_connector_add_freesync_modes);
 
-static int amdgpu_dm_connector_get_modes(struct drm_connector *connector)
+STATIC_IFN_KUNIT int amdgpu_dm_connector_get_modes(struct drm_connector 
*connector)
 {
        struct amdgpu_dm_connector *amdgpu_dm_connector =
                        to_amdgpu_dm_connector(connector);
@@ -3077,6 +3077,7 @@ static int amdgpu_dm_connector_get_modes(struct 
drm_connector *connector)
 
        return amdgpu_dm_connector->num_modes;
 }
+EXPORT_IF_KUNIT(amdgpu_dm_connector_get_modes);
 
 static const u32 supported_colorspaces =
        BIT(DRM_MODE_COLORIMETRY_BT709_YCC) |
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 3571378654fd7..91b8434ba591d 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
@@ -168,6 +168,7 @@ void amdgpu_dm_connector_add_common_modes(struct 
drm_encoder *encoder,
                                          struct drm_connector *connector);
 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);
 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 3a5edf84fbc0a..fc6b6013d1188 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
@@ -7171,6 +7171,179 @@ static void dm_test_funcs_force_reads_edid(struct kunit 
*test)
        ctx->aconnector->drm_edid = NULL;
 }
 
+/* Tests for amdgpu_dm_connector_get_modes() */
+
+static enum dp_link_encoding dm_test_gm_enc_8b10b(const struct 
dc_link_settings *s)
+{
+       return DP_8b_10b_ENCODING;
+}
+
+static enum dp_link_encoding dm_test_gm_enc_128b(const struct dc_link_settings 
*s)
+{
+       return DP_128b_132b_ENCODING;
+}
+
+/*
+ * Build an amdgpu_dm_connector on an amdgpu_device-backed drm device (so
+ * drm_to_adev() resolves for amdgpu_dm_fbc_init()) with an attached encoder
+ * and a dc/dc_link whose link_srv reports a non-128b encoding by default. The
+ * fbc compressor is left NULL so amdgpu_dm_fbc_init() early-returns.
+ */
+struct dm_test_gm_ctx {
+       struct amdgpu_device *adev;
+       struct drm_device *drm;
+       struct amdgpu_dm_connector *aconnector;
+       struct amdgpu_encoder *aenc;
+       struct dc *dc;
+       struct link_service *link_srv;
+       struct dc_link *link;
+};
+
+static struct dm_test_gm_ctx *
+dm_test_gm_ctx_alloc(struct kunit *test, int connector_type)
+{
+       struct dm_test_gm_ctx *ctx;
+       struct device *dev;
+       int ret;
+
+       ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL);
+       KUNIT_ASSERT_NOT_NULL(test, ctx);
+
+       dev = drm_kunit_helper_alloc_device(test);
+       KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dev);
+
+       ctx->drm = __drm_kunit_helper_alloc_drm_device(test, dev,
+                                                      sizeof(*ctx->adev),
+                                                      offsetof(struct 
amdgpu_device, ddev),
+                                                      DRIVER_MODESET);
+       KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx->drm);
+       ctx->adev = drm_to_adev(ctx->drm);
+
+       ctx->aconnector = drmm_kzalloc(ctx->drm, sizeof(*ctx->aconnector),
+                                      GFP_KERNEL);
+       KUNIT_ASSERT_NOT_NULL(test, ctx->aconnector);
+       ret = drmm_connector_init(ctx->drm, &ctx->aconnector->base,
+                                 &dm_test_connector_funcs, connector_type,
+                                 NULL);
+       KUNIT_ASSERT_EQ(test, ret, 0);
+
+       ctx->aenc = drmm_kzalloc(ctx->drm, sizeof(*ctx->aenc), GFP_KERNEL);
+       KUNIT_ASSERT_NOT_NULL(test, ctx->aenc);
+       ret = drmm_encoder_init(ctx->drm, &ctx->aenc->base, NULL,
+                               DRM_MODE_ENCODER_TMDS, NULL);
+       KUNIT_ASSERT_EQ(test, ret, 0);
+       ret = drm_connector_attach_encoder(&ctx->aconnector->base,
+                                          &ctx->aenc->base);
+       KUNIT_ASSERT_EQ(test, ret, 0);
+
+       ctx->dc = kunit_kzalloc(test, sizeof(*ctx->dc), GFP_KERNEL);
+       KUNIT_ASSERT_NOT_NULL(test, ctx->dc);
+       ctx->link_srv = kunit_kzalloc(test, sizeof(*ctx->link_srv), GFP_KERNEL);
+       KUNIT_ASSERT_NOT_NULL(test, ctx->link_srv);
+       ctx->link = kunit_kzalloc(test, sizeof(*ctx->link), GFP_KERNEL);
+       KUNIT_ASSERT_NOT_NULL(test, ctx->link);
+
+       ctx->link_srv->dp_get_encoding_format = dm_test_gm_enc_8b10b;
+       ctx->dc->link_srv = ctx->link_srv;
+       ctx->adev->dm.dc = ctx->dc;
+       ctx->link->dc = ctx->dc;
+       ctx->aconnector->dc_link = ctx->link;
+
+       return ctx;
+}
+
+/**
+ * dm_test_get_modes_noedid_default - Test synthesized modes without an EDID
+ * @test: The KUnit test context
+ *
+ * With no cached EDID and a non-128b link, get_modes() synthesizes the default
+ * 640x480 fallback mode(s) and reports a non-zero count.
+ */
+static void dm_test_get_modes_noedid_default(struct kunit *test)
+{
+       struct dm_test_gm_ctx *ctx =
+               dm_test_gm_ctx_alloc(test, DRM_MODE_CONNECTOR_DisplayPort);
+
+       KUNIT_EXPECT_GT(test,
+                       amdgpu_dm_connector_get_modes(&ctx->aconnector->base), 
0);
+}
+
+/**
+ * dm_test_get_modes_noedid_128b_adds_more - Test 128b links add 1080p modes
+ * @test: The KUnit test context
+ *
+ * A 128b/132b link synthesizes the extra 1920x1080 fallback modes, so the mode
+ * count is strictly greater than for an 8b/10b link.
+ */
+static void dm_test_get_modes_noedid_128b_adds_more(struct kunit *test)
+{
+       struct dm_test_gm_ctx *ctx =
+               dm_test_gm_ctx_alloc(test, DRM_MODE_CONNECTOR_DisplayPort);
+       int n_8b, n_128b;
+
+       n_8b = amdgpu_dm_connector_get_modes(&ctx->aconnector->base);
+
+       ctx->link_srv->dp_get_encoding_format = dm_test_gm_enc_128b;
+       n_128b = amdgpu_dm_connector_get_modes(&ctx->aconnector->base);
+
+       KUNIT_EXPECT_GT(test, n_128b, n_8b);
+}
+
+/**
+ * dm_test_get_modes_noedid_analog_adds_common - Test analog sinks add common 
modes
+ * @test: The KUnit test context
+ *
+ * An analog VGA sink detected by load detection adds the common fallback modes
+ * on top of the default 640x480 mode(s).
+ */
+static void dm_test_get_modes_noedid_analog_adds_common(struct kunit *test)
+{
+       struct dm_test_gm_ctx *ctx =
+               dm_test_gm_ctx_alloc(test, DRM_MODE_CONNECTOR_VGA);
+       struct dc_sink *sink;
+       int n_base, n_analog;
+
+       n_base = amdgpu_dm_connector_get_modes(&ctx->aconnector->base);
+
+       sink = kunit_kzalloc(test, sizeof(*sink), GFP_KERNEL);
+       KUNIT_ASSERT_NOT_NULL(test, sink);
+       sink->edid_caps.analog = true;
+       ctx->aconnector->dc_sink = sink;
+       ctx->link->link_id.id = CONNECTOR_ID_VGA;
+
+       n_analog = amdgpu_dm_connector_get_modes(&ctx->aconnector->base);
+
+       KUNIT_EXPECT_GT(test, n_analog, n_base);
+}
+
+/**
+ * dm_test_get_modes_with_edid - Test the cached-EDID path adds common modes
+ * @test: The KUnit test context
+ *
+ * With a cached EDID on an eDP connector, get_modes() takes the DDC path and
+ * adds the common downscaled modes derived from the encoder native mode.
+ */
+static void dm_test_get_modes_with_edid(struct kunit *test)
+{
+       struct dm_test_gm_ctx *ctx =
+               dm_test_gm_ctx_alloc(test, DRM_MODE_CONNECTOR_eDP);
+       const struct drm_edid *drm_edid;
+
+       drm_edid = drm_edid_alloc(dm_test_uad_edid, sizeof(dm_test_uad_edid));
+       KUNIT_ASSERT_NOT_NULL(test, drm_edid);
+       drm_edid_connector_update(&ctx->aconnector->base, drm_edid);
+       ctx->aconnector->drm_edid = drm_edid;
+
+       ctx->aenc->native_mode.hdisplay = 1920;
+       ctx->aenc->native_mode.vdisplay = 1200;
+
+       KUNIT_EXPECT_GT(test,
+                       amdgpu_dm_connector_get_modes(&ctx->aconnector->base), 
0);
+
+       drm_edid_free(drm_edid);
+       ctx->aconnector->drm_edid = NULL;
+}
+
 /* Tests for amdgpu_dm_update_stream_scaling_settings() */
 
 /**
@@ -7634,6 +7807,11 @@ static struct kunit_case amdgpu_dm_connector_tests[] = {
        /* amdgpu_dm_connector_funcs_force */
        KUNIT_CASE(dm_test_funcs_force_no_edid),
        KUNIT_CASE(dm_test_funcs_force_reads_edid),
+       /* amdgpu_dm_connector_get_modes */
+       KUNIT_CASE(dm_test_get_modes_noedid_default),
+       KUNIT_CASE(dm_test_get_modes_noedid_128b_adds_more),
+       KUNIT_CASE(dm_test_get_modes_noedid_analog_adds_common),
+       KUNIT_CASE(dm_test_get_modes_with_edid),
        /* 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

Reply via email to