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
