From: Bhawanpreet Lakha <[email protected]>

Add KUnit coverage for update_subconnector_property() on the
amdgpu_dm_connector suite:

- DP connector with a sink: subconnector property is resolved from
  the dongle type (VGA converter -> VGA).
- DP connector without a sink: dongle type is ignored and the
  property stays Unknown.
- Non-DP connector: function early-returns and leaves a pre-seeded
  property value untouched.

Assisted-by: Copilot:Claude-Opus-4.8
Reviewed-by: Alex Hung <[email protected]>
Signed-off-by: Bhawanpreet Lakha <[email protected]>
Signed-off-by: George Zhang <[email protected]>
---
 .../display/amdgpu_dm/amdgpu_dm_connector.c   |   3 +-
 .../display/amdgpu_dm/amdgpu_dm_connector.h   |   1 +
 .../tests/amdgpu_dm_connector_test.c          | 142 ++++++++++++++++++
 3 files changed, 145 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 96f7bf446570..4ae58d5c5264 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
@@ -235,7 +235,7 @@ STATIC_IFN_KUNIT enum drm_mode_subconnector 
get_subconnector_type(struct dc_link
 }
 EXPORT_IF_KUNIT(get_subconnector_type);
 
-static void update_subconnector_property(struct amdgpu_dm_connector 
*aconnector)
+STATIC_IFN_KUNIT void update_subconnector_property(struct amdgpu_dm_connector 
*aconnector)
 {
        struct dc_link *link = aconnector->dc_link;
        struct drm_connector *connector = &aconnector->base;
@@ -251,6 +251,7 @@ static void update_subconnector_property(struct 
amdgpu_dm_connector *aconnector)
                        connector->dev->mode_config.dp_subconnector_property,
                        subconnector);
 }
+EXPORT_IF_KUNIT(update_subconnector_property);
 
 static int amdgpu_dm_connector_get_modes(struct drm_connector *connector);
 
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 e9ee4a4ad30e..10fe0bf48c02 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
@@ -147,6 +147,7 @@ int amdgpu_dm_encoder_init(struct drm_device *dev,
 
 #if IS_ENABLED(CONFIG_DRM_AMD_DC_KUNIT_TEST)
 enum drm_mode_subconnector get_subconnector_type(struct dc_link *link);
+void update_subconnector_property(struct amdgpu_dm_connector *aconnector);
 enum display_content_type
 get_output_content_type(const struct drm_connector_state *connector_state);
 bool adjust_colour_depth_from_display_info(struct dc_crtc_timing *timing_out,
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 91f9543dd7bb..782a22e4f074 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
@@ -2527,6 +2527,144 @@ static void 
dm_test_set_panel_type_defaults_to_lcd(struct kunit *test)
                        (int)PANEL_TYPE_LCD);
 }
 
+/* Tests for update_subconnector_property() */
+
+/**
+ * dm_test_update_subconnector_dp_with_sink - Test subconnector property is set
+ * from the dongle type for a DisplayPort connector with a sink
+ * @test: The KUnit test context
+ */
+static void dm_test_update_subconnector_dp_with_sink(struct kunit *test)
+{
+       struct device *dev;
+       struct drm_device *drm;
+       struct amdgpu_dm_connector *aconnector;
+       struct dc_link *link;
+       uint64_t val = 0;
+
+       dev = drm_kunit_helper_alloc_device(test);
+       KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dev);
+
+       drm = __drm_kunit_helper_alloc_drm_device(test, dev,
+                                                  sizeof(*drm), 0,
+                                                  DRIVER_MODESET);
+       KUNIT_ASSERT_NOT_ERR_OR_NULL(test, drm);
+
+       aconnector = kunit_kzalloc(test, sizeof(*aconnector), GFP_KERNEL);
+       KUNIT_ASSERT_NOT_NULL(test, aconnector);
+       link = kunit_kzalloc(test, sizeof(*link), GFP_KERNEL);
+       KUNIT_ASSERT_NOT_NULL(test, link);
+
+       drmm_connector_init(drm, &aconnector->base, &dm_test_connector_funcs,
+                           DRM_MODE_CONNECTOR_DisplayPort, NULL);
+       drm_connector_attach_dp_subconnector_property(&aconnector->base);
+
+       link->dpcd_caps.dongle_type = DISPLAY_DONGLE_DP_VGA_CONVERTER;
+       aconnector->dc_link = link;
+       /* Any non-NULL sink enables dongle-type resolution */
+       aconnector->dc_sink = kunit_kzalloc(test, sizeof(*aconnector->dc_sink), 
GFP_KERNEL);
+       KUNIT_ASSERT_NOT_NULL(test, aconnector->dc_sink);
+
+       update_subconnector_property(aconnector);
+
+       KUNIT_EXPECT_EQ(test, 
drm_object_property_get_value(&aconnector->base.base,
+                               
aconnector->base.dev->mode_config.dp_subconnector_property,
+                               &val), 0);
+       KUNIT_EXPECT_EQ(test, (int)val, (int)DRM_MODE_SUBCONNECTOR_VGA);
+}
+
+/**
+ * dm_test_update_subconnector_dp_no_sink - Test subconnector property stays
+ * unknown for a DisplayPort connector without a sink
+ * @test: The KUnit test context
+ */
+static void dm_test_update_subconnector_dp_no_sink(struct kunit *test)
+{
+       struct device *dev;
+       struct drm_device *drm;
+       struct amdgpu_dm_connector *aconnector;
+       struct dc_link *link;
+       uint64_t val = 0;
+
+       dev = drm_kunit_helper_alloc_device(test);
+       KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dev);
+
+       drm = __drm_kunit_helper_alloc_drm_device(test, dev,
+                                                  sizeof(*drm), 0,
+                                                  DRIVER_MODESET);
+       KUNIT_ASSERT_NOT_ERR_OR_NULL(test, drm);
+
+       aconnector = kunit_kzalloc(test, sizeof(*aconnector), GFP_KERNEL);
+       KUNIT_ASSERT_NOT_NULL(test, aconnector);
+       link = kunit_kzalloc(test, sizeof(*link), GFP_KERNEL);
+       KUNIT_ASSERT_NOT_NULL(test, link);
+
+       drmm_connector_init(drm, &aconnector->base, &dm_test_connector_funcs,
+                           DRM_MODE_CONNECTOR_DisplayPort, NULL);
+       drm_connector_attach_dp_subconnector_property(&aconnector->base);
+
+       /* Dongle type is set, but no sink means it must not be consulted */
+       link->dpcd_caps.dongle_type = DISPLAY_DONGLE_DP_HDMI_CONVERTER;
+       aconnector->dc_link = link;
+       aconnector->dc_sink = NULL;
+
+       update_subconnector_property(aconnector);
+
+       KUNIT_EXPECT_EQ(test, 
drm_object_property_get_value(&aconnector->base.base,
+                               
aconnector->base.dev->mode_config.dp_subconnector_property,
+                               &val), 0);
+       KUNIT_EXPECT_EQ(test, (int)val, (int)DRM_MODE_SUBCONNECTOR_Unknown);
+}
+
+/**
+ * dm_test_update_subconnector_non_dp_noop - Test non-DisplayPort connector is
+ * left untouched (early return)
+ * @test: The KUnit test context
+ */
+static void dm_test_update_subconnector_non_dp_noop(struct kunit *test)
+{
+       struct device *dev;
+       struct drm_device *drm;
+       struct amdgpu_dm_connector *aconnector;
+       struct dc_link *link;
+       uint64_t val = 0;
+
+       dev = drm_kunit_helper_alloc_device(test);
+       KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dev);
+
+       drm = __drm_kunit_helper_alloc_drm_device(test, dev,
+                                                  sizeof(*drm), 0,
+                                                  DRIVER_MODESET);
+       KUNIT_ASSERT_NOT_ERR_OR_NULL(test, drm);
+
+       aconnector = kunit_kzalloc(test, sizeof(*aconnector), GFP_KERNEL);
+       KUNIT_ASSERT_NOT_NULL(test, aconnector);
+       link = kunit_kzalloc(test, sizeof(*link), GFP_KERNEL);
+       KUNIT_ASSERT_NOT_NULL(test, link);
+
+       drmm_connector_init(drm, &aconnector->base, &dm_test_connector_funcs,
+                           DRM_MODE_CONNECTOR_HDMIA, NULL);
+       drm_connector_attach_dp_subconnector_property(&aconnector->base);
+
+       /* Pre-seed the property to a non-default value */
+       drm_object_property_set_value(&aconnector->base.base,
+                       
aconnector->base.dev->mode_config.dp_subconnector_property,
+                       DRM_MODE_SUBCONNECTOR_VGA);
+
+       link->dpcd_caps.dongle_type = DISPLAY_DONGLE_DP_HDMI_CONVERTER;
+       aconnector->dc_link = link;
+       aconnector->dc_sink = kunit_kzalloc(test, sizeof(*aconnector->dc_sink), 
GFP_KERNEL);
+       KUNIT_ASSERT_NOT_NULL(test, aconnector->dc_sink);
+
+       update_subconnector_property(aconnector);
+
+       /* Non-DP connector: value must remain what we seeded */
+       KUNIT_EXPECT_EQ(test, 
drm_object_property_get_value(&aconnector->base.base,
+                               
aconnector->base.dev->mode_config.dp_subconnector_property,
+                               &val), 0);
+       KUNIT_EXPECT_EQ(test, (int)val, (int)DRM_MODE_SUBCONNECTOR_VGA);
+}
+
 static struct kunit_case amdgpu_dm_connector_tests[] = {
        /* get_subconnector_type */
        KUNIT_CASE(dm_test_subconnector_type_none),
@@ -2664,6 +2802,10 @@ static struct kunit_case amdgpu_dm_connector_tests[] = {
        KUNIT_CASE(dm_test_is_freesync_video_mode_null_mode),
        KUNIT_CASE(dm_test_is_freesync_video_mode_match),
        KUNIT_CASE(dm_test_is_freesync_video_mode_no_match),
+       /* update_subconnector_property */
+       KUNIT_CASE(dm_test_update_subconnector_dp_with_sink),
+       KUNIT_CASE(dm_test_update_subconnector_dp_no_sink),
+       KUNIT_CASE(dm_test_update_subconnector_non_dp_noop),
        /* amdgpu_dm_update_cacp_caps */
        KUNIT_CASE(dm_test_cacp_caps_unsupported_ip),
        KUNIT_CASE(dm_test_cacp_caps_excluded_ip_316),
-- 
2.55.0

Reply via email to