From 48ccf21fa8dc595c8aa4f1d347b593dcae0727d0 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Tue, 8 Apr 2025 16:07:58 +0200 Subject: drm/tests: shmem: Fix memleak The drm_gem_shmem_test_get_pages_sgt() gets a scatter-gather table using the drm_gem_shmem_get_sg_table() function and rightfully calls sg_free_table() on it. However, it's also supposed to kfree() the returned sg_table, but doesn't. This leads to a memory leak, reported by kmemleak. Fix it by adding a kunit action to kfree the sgt when the test ends. Reported-by: Philipp Stanner Closes: https://lore.kernel.org/dri-devel/a7655158a6367ac46194d57f4b7433ef0772a73e.camel@mailbox.org/ Fixes: 93032ae634d4 ("drm/test: add a test suite for GEM objects backed by shmem") Reviewed-by: Javier Martinez Canillas Link: https://lore.kernel.org/r/20250408140758.1831333-1-mripard@kernel.org Signed-off-by: Maxime Ripard --- drivers/gpu/drm/tests/drm_gem_shmem_test.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/gpu/drm/tests') diff --git a/drivers/gpu/drm/tests/drm_gem_shmem_test.c b/drivers/gpu/drm/tests/drm_gem_shmem_test.c index fd4215e2f982..925fbc2cda70 100644 --- a/drivers/gpu/drm/tests/drm_gem_shmem_test.c +++ b/drivers/gpu/drm/tests/drm_gem_shmem_test.c @@ -216,6 +216,9 @@ static void drm_gem_shmem_test_get_pages_sgt(struct kunit *test) KUNIT_ASSERT_NOT_ERR_OR_NULL(test, sgt); KUNIT_EXPECT_NULL(test, shmem->sgt); + ret = kunit_add_action_or_reset(test, kfree_wrapper, sgt); + KUNIT_ASSERT_EQ(test, ret, 0); + ret = kunit_add_action_or_reset(test, sg_free_table_wrapper, sgt); KUNIT_ASSERT_EQ(test, ret, 0); -- cgit v1.2.3 From 90642d9de4776ebb0403ef7d8e621def70ade1f2 Mon Sep 17 00:00:00 2001 From: Cristian Ciocaltea Date: Tue, 27 May 2025 15:11:15 +0300 Subject: drm/tests: hdmi: Replace '[_]MHz' with 'mhz' Improve consistency throughout drm_hdmi_state_helper_test.c by replacing the two occurrences of '[_]MHz' substring with 'mhz'. As a bonus, this also helps getting rid of checkpatch.pl complaint: CHECK: Avoid CamelCase: Reviewed-by: Dmitry Baryshkov Signed-off-by: Cristian Ciocaltea Reviewed-by: Maxime Ripard Link: https://lore.kernel.org/r/20250527-hdmi-conn-yuv-v5-7-74c9c4a8ac0c@collabora.com Signed-off-by: Maxime Ripard --- drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/gpu/drm/tests') diff --git a/drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c b/drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c index 7ffd666753b1..c8dc6fa0f925 100644 --- a/drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c +++ b/drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c @@ -89,15 +89,15 @@ static const struct drm_connector_hdmi_funcs reject_connector_hdmi_funcs = { }; static enum drm_mode_status -reject_100MHz_connector_tmds_char_rate_valid(const struct drm_connector *connector, +reject_100mhz_connector_tmds_char_rate_valid(const struct drm_connector *connector, const struct drm_display_mode *mode, unsigned long long tmds_rate) { return (tmds_rate > 100ULL * 1000 * 1000) ? MODE_BAD : MODE_OK; } -static const struct drm_connector_hdmi_funcs reject_100_MHz_connector_hdmi_funcs = { - .tmds_char_rate_valid = reject_100MHz_connector_tmds_char_rate_valid, +static const struct drm_connector_hdmi_funcs reject_100mhz_connector_hdmi_funcs = { + .tmds_char_rate_valid = reject_100mhz_connector_tmds_char_rate_valid, }; static int dummy_connector_get_modes(struct drm_connector *connector) @@ -1934,7 +1934,7 @@ static void drm_test_check_mode_valid_reject_rate(struct kunit *test) priv = drm_kunit_helper_connector_hdmi_init_funcs(test, BIT(HDMI_COLORSPACE_RGB), 8, - &reject_100_MHz_connector_hdmi_funcs); + &reject_100mhz_connector_hdmi_funcs); KUNIT_ASSERT_NOT_NULL(test, priv); conn = &priv->connector; -- cgit v1.2.3 From 7ca78aa0d5411d62b672ef4f5266e9913ee07920 Mon Sep 17 00:00:00 2001 From: Cristian Ciocaltea Date: Tue, 27 May 2025 15:11:16 +0300 Subject: drm/tests: hdmi: Switch to 'void *' type for EDID data Replace 'const char *' with 'const void *' type for current_edid member in struct drm_atomic_helper_connector_hdmi_priv, as well as for the edid parameter of set_connector_edid() function. Suggested-by: Jani Nikula Signed-off-by: Cristian Ciocaltea Reviewed-by: Maxime Ripard Link: https://lore.kernel.org/r/20250527-hdmi-conn-yuv-v5-8-74c9c4a8ac0c@collabora.com Signed-off-by: Maxime Ripard --- drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm/tests') diff --git a/drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c b/drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c index c8dc6fa0f925..00576f747f1f 100644 --- a/drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c +++ b/drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c @@ -33,7 +33,7 @@ struct drm_atomic_helper_connector_hdmi_priv { struct drm_encoder encoder; struct drm_connector connector; - const char *current_edid; + const void *current_edid; size_t current_edid_len; }; @@ -56,7 +56,7 @@ static struct drm_display_mode *find_preferred_mode(struct drm_connector *connec } static int set_connector_edid(struct kunit *test, struct drm_connector *connector, - const char *edid, size_t edid_len) + const void *edid, size_t edid_len) { struct drm_atomic_helper_connector_hdmi_priv *priv = connector_to_priv(connector); -- cgit v1.2.3 From a08fd207d60ecff74a5a4d09d1b1acda1f863a49 Mon Sep 17 00:00:00 2001 From: Cristian Ciocaltea Date: Tue, 27 May 2025 15:11:17 +0300 Subject: drm/tests: hdmi: Add macro to simplify EDID setup Factor out the HDMI connector initialization from drm_kunit_helper_connector_hdmi_init_funcs() into a common __connector_hdmi_init() function, while extending its functionality to allow setting custom (i.e. non-default) EDID data. Introduce a macro as a wrapper over the new helper to allow dropping the open coded EDID setup from all test cases. The actual conversion will be handled separately; for now just apply it to drm_kunit_helper_connector_hdmi_init() helper. Reviewed-by: Maxime Ripard Signed-off-by: Cristian Ciocaltea Link: https://lore.kernel.org/r/20250527-hdmi-conn-yuv-v5-9-74c9c4a8ac0c@collabora.com Signed-off-by: Maxime Ripard --- drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c | 46 +++++++++++++--------- 1 file changed, 28 insertions(+), 18 deletions(-) (limited to 'drivers/gpu/drm/tests') diff --git a/drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c b/drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c index 00576f747f1f..beee73e7a4d2 100644 --- a/drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c +++ b/drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c @@ -140,10 +140,11 @@ static const struct drm_connector_funcs dummy_connector_funcs = { static struct drm_atomic_helper_connector_hdmi_priv * -drm_kunit_helper_connector_hdmi_init_funcs(struct kunit *test, - unsigned int formats, - unsigned int max_bpc, - const struct drm_connector_hdmi_funcs *hdmi_funcs) +__connector_hdmi_init(struct kunit *test, + unsigned int formats, + unsigned int max_bpc, + const struct drm_connector_hdmi_funcs *hdmi_funcs, + const void *edid_data, size_t edid_len) { struct drm_atomic_helper_connector_hdmi_priv *priv; struct drm_connector *conn; @@ -197,29 +198,38 @@ drm_kunit_helper_connector_hdmi_init_funcs(struct kunit *test, drm_mode_config_reset(drm); + if (edid_data && edid_len) { + ret = set_connector_edid(test, &priv->connector, edid_data, edid_len); + KUNIT_ASSERT_GT(test, ret, 0); + } + return priv; } +static +struct drm_atomic_helper_connector_hdmi_priv * +drm_kunit_helper_connector_hdmi_init_funcs(struct kunit *test, + unsigned int formats, + unsigned int max_bpc, + const struct drm_connector_hdmi_funcs *hdmi_funcs) +{ + return __connector_hdmi_init(test, formats, max_bpc, hdmi_funcs, NULL, 0); +} + +#define drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test, formats, max_bpc, funcs, edid) \ + __connector_hdmi_init(test, formats, max_bpc, funcs, edid, ARRAY_SIZE(edid)) + static struct drm_atomic_helper_connector_hdmi_priv * drm_kunit_helper_connector_hdmi_init(struct kunit *test, unsigned int formats, unsigned int max_bpc) { - struct drm_atomic_helper_connector_hdmi_priv *priv; - int ret; - - priv = drm_kunit_helper_connector_hdmi_init_funcs(test, - formats, max_bpc, - &dummy_connector_hdmi_funcs); - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv); - - ret = set_connector_edid(test, &priv->connector, - test_edid_hdmi_1080p_rgb_max_200mhz, - ARRAY_SIZE(test_edid_hdmi_1080p_rgb_max_200mhz)); - KUNIT_ASSERT_GT(test, ret, 0); - - return priv; + return drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test, + formats, + max_bpc, + &dummy_connector_hdmi_funcs, + test_edid_hdmi_1080p_rgb_max_200mhz); } /* -- cgit v1.2.3 From 74e98941b926a3ecc29d3098475a5a0940f2ada2 Mon Sep 17 00:00:00 2001 From: Cristian Ciocaltea Date: Tue, 27 May 2025 15:11:18 +0300 Subject: drm/tests: hdmi: Replace open coded EDID setup Make use of the recently introduced macros to reduce boilerplate code around EDID setup. This also helps dropping the redundant calls to set_connector_edid(). No functional changes intended. Acked-by: Maxime Ripard Signed-off-by: Cristian Ciocaltea Link: https://lore.kernel.org/r/20250527-hdmi-conn-yuv-v5-10-74c9c4a8ac0c@collabora.com Signed-off-by: Maxime Ripard --- drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c | 234 ++++++++------------- 1 file changed, 92 insertions(+), 142 deletions(-) (limited to 'drivers/gpu/drm/tests') diff --git a/drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c b/drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c index beee73e7a4d2..b8f4dc677be7 100644 --- a/drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c +++ b/drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c @@ -762,19 +762,16 @@ static void drm_test_check_output_bpc_crtc_mode_changed(struct kunit *test) struct drm_crtc *crtc; int ret; - priv = drm_kunit_helper_connector_hdmi_init(test, - BIT(HDMI_COLORSPACE_RGB), - 10); + priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test, + BIT(HDMI_COLORSPACE_RGB), + 10, + &dummy_connector_hdmi_funcs, + test_edid_hdmi_1080p_rgb_yuv_dc_max_200mhz); KUNIT_ASSERT_NOT_NULL(test, priv); drm = &priv->drm; crtc = priv->crtc; conn = &priv->connector; - ret = set_connector_edid(test, conn, - test_edid_hdmi_1080p_rgb_yuv_dc_max_200mhz, - ARRAY_SIZE(test_edid_hdmi_1080p_rgb_yuv_dc_max_200mhz)); - KUNIT_ASSERT_GT(test, ret, 0); - preferred = find_preferred_mode(conn); KUNIT_ASSERT_NOT_NULL(test, preferred); @@ -841,19 +838,16 @@ static void drm_test_check_output_bpc_crtc_mode_not_changed(struct kunit *test) struct drm_crtc *crtc; int ret; - priv = drm_kunit_helper_connector_hdmi_init(test, - BIT(HDMI_COLORSPACE_RGB), - 10); + priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test, + BIT(HDMI_COLORSPACE_RGB), + 10, + &dummy_connector_hdmi_funcs, + test_edid_hdmi_1080p_rgb_yuv_dc_max_200mhz); KUNIT_ASSERT_NOT_NULL(test, priv); drm = &priv->drm; crtc = priv->crtc; conn = &priv->connector; - ret = set_connector_edid(test, conn, - test_edid_hdmi_1080p_rgb_yuv_dc_max_200mhz, - ARRAY_SIZE(test_edid_hdmi_1080p_rgb_yuv_dc_max_200mhz)); - KUNIT_ASSERT_GT(test, ret, 0); - preferred = find_preferred_mode(conn); KUNIT_ASSERT_NOT_NULL(test, preferred); @@ -915,21 +909,18 @@ static void drm_test_check_output_bpc_dvi(struct kunit *test) struct drm_crtc *crtc; int ret; - priv = drm_kunit_helper_connector_hdmi_init(test, - BIT(HDMI_COLORSPACE_RGB) | - BIT(HDMI_COLORSPACE_YUV422) | - BIT(HDMI_COLORSPACE_YUV444), - 12); + priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test, + BIT(HDMI_COLORSPACE_RGB) | + BIT(HDMI_COLORSPACE_YUV422) | + BIT(HDMI_COLORSPACE_YUV444), + 12, + &dummy_connector_hdmi_funcs, + test_edid_dvi_1080p); KUNIT_ASSERT_NOT_NULL(test, priv); drm = &priv->drm; crtc = priv->crtc; conn = &priv->connector; - ret = set_connector_edid(test, conn, - test_edid_dvi_1080p, - ARRAY_SIZE(test_edid_dvi_1080p)); - KUNIT_ASSERT_GT(test, ret, 0); - info = &conn->display_info; KUNIT_ASSERT_FALSE(test, info->is_hdmi); @@ -969,19 +960,16 @@ static void drm_test_check_tmds_char_rate_rgb_8bpc(struct kunit *test) struct drm_crtc *crtc; int ret; - priv = drm_kunit_helper_connector_hdmi_init(test, - BIT(HDMI_COLORSPACE_RGB), - 8); + priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test, + BIT(HDMI_COLORSPACE_RGB), + 8, + &dummy_connector_hdmi_funcs, + test_edid_hdmi_1080p_rgb_max_200mhz); KUNIT_ASSERT_NOT_NULL(test, priv); drm = &priv->drm; crtc = priv->crtc; conn = &priv->connector; - ret = set_connector_edid(test, conn, - test_edid_hdmi_1080p_rgb_max_200mhz, - ARRAY_SIZE(test_edid_hdmi_1080p_rgb_max_200mhz)); - KUNIT_ASSERT_GT(test, ret, 0); - preferred = find_preferred_mode(conn); KUNIT_ASSERT_NOT_NULL(test, preferred); KUNIT_ASSERT_FALSE(test, preferred->flags & DRM_MODE_FLAG_DBLCLK); @@ -1021,19 +1009,16 @@ static void drm_test_check_tmds_char_rate_rgb_10bpc(struct kunit *test) struct drm_crtc *crtc; int ret; - priv = drm_kunit_helper_connector_hdmi_init(test, - BIT(HDMI_COLORSPACE_RGB), - 10); + priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test, + BIT(HDMI_COLORSPACE_RGB), + 10, + &dummy_connector_hdmi_funcs, + test_edid_hdmi_1080p_rgb_yuv_dc_max_340mhz); KUNIT_ASSERT_NOT_NULL(test, priv); drm = &priv->drm; crtc = priv->crtc; conn = &priv->connector; - ret = set_connector_edid(test, conn, - test_edid_hdmi_1080p_rgb_yuv_dc_max_340mhz, - ARRAY_SIZE(test_edid_hdmi_1080p_rgb_yuv_dc_max_340mhz)); - KUNIT_ASSERT_GT(test, ret, 0); - preferred = find_preferred_mode(conn); KUNIT_ASSERT_NOT_NULL(test, preferred); KUNIT_ASSERT_FALSE(test, preferred->flags & DRM_MODE_FLAG_DBLCLK); @@ -1073,19 +1058,16 @@ static void drm_test_check_tmds_char_rate_rgb_12bpc(struct kunit *test) struct drm_crtc *crtc; int ret; - priv = drm_kunit_helper_connector_hdmi_init(test, - BIT(HDMI_COLORSPACE_RGB), - 12); + priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test, + BIT(HDMI_COLORSPACE_RGB), + 12, + &dummy_connector_hdmi_funcs, + test_edid_hdmi_1080p_rgb_yuv_dc_max_340mhz); KUNIT_ASSERT_NOT_NULL(test, priv); drm = &priv->drm; crtc = priv->crtc; conn = &priv->connector; - ret = set_connector_edid(test, conn, - test_edid_hdmi_1080p_rgb_yuv_dc_max_340mhz, - ARRAY_SIZE(test_edid_hdmi_1080p_rgb_yuv_dc_max_340mhz)); - KUNIT_ASSERT_GT(test, ret, 0); - preferred = find_preferred_mode(conn); KUNIT_ASSERT_NOT_NULL(test, preferred); KUNIT_ASSERT_FALSE(test, preferred->flags & DRM_MODE_FLAG_DBLCLK); @@ -1191,19 +1173,16 @@ static void drm_test_check_max_tmds_rate_bpc_fallback(struct kunit *test) struct drm_crtc *crtc; int ret; - priv = drm_kunit_helper_connector_hdmi_init(test, - BIT(HDMI_COLORSPACE_RGB), - 12); + priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test, + BIT(HDMI_COLORSPACE_RGB), + 12, + &dummy_connector_hdmi_funcs, + test_edid_hdmi_1080p_rgb_yuv_dc_max_200mhz); KUNIT_ASSERT_NOT_NULL(test, priv); drm = &priv->drm; crtc = priv->crtc; conn = &priv->connector; - ret = set_connector_edid(test, conn, - test_edid_hdmi_1080p_rgb_yuv_dc_max_200mhz, - ARRAY_SIZE(test_edid_hdmi_1080p_rgb_yuv_dc_max_200mhz)); - KUNIT_ASSERT_GT(test, ret, 0); - info = &conn->display_info; KUNIT_ASSERT_TRUE(test, info->is_hdmi); KUNIT_ASSERT_GT(test, info->max_tmds_clock, 0); @@ -1263,21 +1242,18 @@ static void drm_test_check_max_tmds_rate_format_fallback(struct kunit *test) struct drm_crtc *crtc; int ret; - priv = drm_kunit_helper_connector_hdmi_init(test, - BIT(HDMI_COLORSPACE_RGB) | - BIT(HDMI_COLORSPACE_YUV422) | - BIT(HDMI_COLORSPACE_YUV444), - 12); + priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test, + BIT(HDMI_COLORSPACE_RGB) | + BIT(HDMI_COLORSPACE_YUV422) | + BIT(HDMI_COLORSPACE_YUV444), + 12, + &dummy_connector_hdmi_funcs, + test_edid_hdmi_1080p_rgb_yuv_dc_max_200mhz); KUNIT_ASSERT_NOT_NULL(test, priv); drm = &priv->drm; crtc = priv->crtc; conn = &priv->connector; - ret = set_connector_edid(test, conn, - test_edid_hdmi_1080p_rgb_yuv_dc_max_200mhz, - ARRAY_SIZE(test_edid_hdmi_1080p_rgb_yuv_dc_max_200mhz)); - KUNIT_ASSERT_GT(test, ret, 0); - info = &conn->display_info; KUNIT_ASSERT_TRUE(test, info->is_hdmi); KUNIT_ASSERT_GT(test, info->max_tmds_clock, 0); @@ -1331,20 +1307,17 @@ static void drm_test_check_output_bpc_format_vic_1(struct kunit *test) struct drm_crtc *crtc; int ret; - priv = drm_kunit_helper_connector_hdmi_init(test, - BIT(HDMI_COLORSPACE_RGB) | - BIT(HDMI_COLORSPACE_YUV422) | - BIT(HDMI_COLORSPACE_YUV444), - 12); + priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test, + BIT(HDMI_COLORSPACE_RGB) | + BIT(HDMI_COLORSPACE_YUV422) | + BIT(HDMI_COLORSPACE_YUV444), + 12, + &dummy_connector_hdmi_funcs, + test_edid_hdmi_1080p_rgb_yuv_dc_max_200mhz); KUNIT_ASSERT_NOT_NULL(test, priv); drm = &priv->drm; conn = &priv->connector; - ret = set_connector_edid(test, conn, - test_edid_hdmi_1080p_rgb_yuv_dc_max_200mhz, - ARRAY_SIZE(test_edid_hdmi_1080p_rgb_yuv_dc_max_200mhz)); - KUNIT_ASSERT_GT(test, ret, 0); - info = &conn->display_info; KUNIT_ASSERT_TRUE(test, info->is_hdmi); KUNIT_ASSERT_GT(test, info->max_tmds_clock, 0); @@ -1398,19 +1371,16 @@ static void drm_test_check_output_bpc_format_driver_rgb_only(struct kunit *test) struct drm_crtc *crtc; int ret; - priv = drm_kunit_helper_connector_hdmi_init(test, - BIT(HDMI_COLORSPACE_RGB), - 12); + priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test, + BIT(HDMI_COLORSPACE_RGB), + 12, + &dummy_connector_hdmi_funcs, + test_edid_hdmi_1080p_rgb_yuv_dc_max_200mhz); KUNIT_ASSERT_NOT_NULL(test, priv); drm = &priv->drm; crtc = priv->crtc; conn = &priv->connector; - ret = set_connector_edid(test, conn, - test_edid_hdmi_1080p_rgb_yuv_dc_max_200mhz, - ARRAY_SIZE(test_edid_hdmi_1080p_rgb_yuv_dc_max_200mhz)); - KUNIT_ASSERT_GT(test, ret, 0); - info = &conn->display_info; KUNIT_ASSERT_TRUE(test, info->is_hdmi); KUNIT_ASSERT_GT(test, info->max_tmds_clock, 0); @@ -1468,21 +1438,18 @@ static void drm_test_check_output_bpc_format_display_rgb_only(struct kunit *test struct drm_crtc *crtc; int ret; - priv = drm_kunit_helper_connector_hdmi_init(test, - BIT(HDMI_COLORSPACE_RGB) | - BIT(HDMI_COLORSPACE_YUV422) | - BIT(HDMI_COLORSPACE_YUV444), - 12); + priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test, + BIT(HDMI_COLORSPACE_RGB) | + BIT(HDMI_COLORSPACE_YUV422) | + BIT(HDMI_COLORSPACE_YUV444), + 12, + &dummy_connector_hdmi_funcs, + test_edid_hdmi_1080p_rgb_max_200mhz); KUNIT_ASSERT_NOT_NULL(test, priv); drm = &priv->drm; crtc = priv->crtc; conn = &priv->connector; - ret = set_connector_edid(test, conn, - test_edid_hdmi_1080p_rgb_max_200mhz, - ARRAY_SIZE(test_edid_hdmi_1080p_rgb_max_200mhz)); - KUNIT_ASSERT_GT(test, ret, 0); - info = &conn->display_info; KUNIT_ASSERT_TRUE(test, info->is_hdmi); KUNIT_ASSERT_GT(test, info->max_tmds_clock, 0); @@ -1541,19 +1508,16 @@ static void drm_test_check_output_bpc_format_driver_8bpc_only(struct kunit *test struct drm_crtc *crtc; int ret; - priv = drm_kunit_helper_connector_hdmi_init(test, - BIT(HDMI_COLORSPACE_RGB), - 8); + priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test, + BIT(HDMI_COLORSPACE_RGB), + 8, + &dummy_connector_hdmi_funcs, + test_edid_hdmi_1080p_rgb_yuv_dc_max_340mhz); KUNIT_ASSERT_NOT_NULL(test, priv); drm = &priv->drm; crtc = priv->crtc; conn = &priv->connector; - ret = set_connector_edid(test, conn, - test_edid_hdmi_1080p_rgb_yuv_dc_max_340mhz, - ARRAY_SIZE(test_edid_hdmi_1080p_rgb_yuv_dc_max_340mhz)); - KUNIT_ASSERT_GT(test, ret, 0); - info = &conn->display_info; KUNIT_ASSERT_TRUE(test, info->is_hdmi); KUNIT_ASSERT_GT(test, info->max_tmds_clock, 0); @@ -1604,21 +1568,18 @@ static void drm_test_check_output_bpc_format_display_8bpc_only(struct kunit *tes struct drm_crtc *crtc; int ret; - priv = drm_kunit_helper_connector_hdmi_init(test, - BIT(HDMI_COLORSPACE_RGB) | - BIT(HDMI_COLORSPACE_YUV422) | - BIT(HDMI_COLORSPACE_YUV444), - 12); + priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test, + BIT(HDMI_COLORSPACE_RGB) | + BIT(HDMI_COLORSPACE_YUV422) | + BIT(HDMI_COLORSPACE_YUV444), + 12, + &dummy_connector_hdmi_funcs, + test_edid_hdmi_1080p_rgb_max_340mhz); KUNIT_ASSERT_NOT_NULL(test, priv); drm = &priv->drm; crtc = priv->crtc; conn = &priv->connector; - ret = set_connector_edid(test, conn, - test_edid_hdmi_1080p_rgb_max_340mhz, - ARRAY_SIZE(test_edid_hdmi_1080p_rgb_max_340mhz)); - KUNIT_ASSERT_GT(test, ret, 0); - info = &conn->display_info; KUNIT_ASSERT_TRUE(test, info->is_hdmi); KUNIT_ASSERT_GT(test, info->max_tmds_clock, 0); @@ -1937,28 +1898,20 @@ static void drm_test_check_mode_valid(struct kunit *test) static void drm_test_check_mode_valid_reject_rate(struct kunit *test) { struct drm_atomic_helper_connector_hdmi_priv *priv; - struct drm_connector *conn; struct drm_display_mode *preferred; - int ret; - priv = drm_kunit_helper_connector_hdmi_init_funcs(test, - BIT(HDMI_COLORSPACE_RGB), - 8, - &reject_100mhz_connector_hdmi_funcs); + priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test, + BIT(HDMI_COLORSPACE_RGB), + 8, + &reject_100mhz_connector_hdmi_funcs, + test_edid_hdmi_1080p_rgb_max_200mhz); KUNIT_ASSERT_NOT_NULL(test, priv); - conn = &priv->connector; - - ret = set_connector_edid(test, conn, - test_edid_hdmi_1080p_rgb_max_200mhz, - ARRAY_SIZE(test_edid_hdmi_1080p_rgb_max_200mhz)); - KUNIT_ASSERT_GT(test, ret, 0); - /* * Unlike the drm_test_check_mode_valid() here 1080p is rejected, but * 480p is allowed. */ - preferred = find_preferred_mode(conn); + preferred = find_preferred_mode(&priv->connector); KUNIT_ASSERT_NOT_NULL(test, preferred); KUNIT_EXPECT_EQ(test, preferred->hdisplay, 640); KUNIT_EXPECT_EQ(test, preferred->vdisplay, 480); @@ -1976,12 +1929,14 @@ static void drm_test_check_mode_valid_reject(struct kunit *test) struct drm_atomic_helper_connector_hdmi_priv *priv; struct drm_connector *conn; struct drm_display_mode *preferred; + unsigned char no_edid[] = {}; int ret; - priv = drm_kunit_helper_connector_hdmi_init_funcs(test, - BIT(HDMI_COLORSPACE_RGB), - 8, - &reject_connector_hdmi_funcs); + priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test, + BIT(HDMI_COLORSPACE_RGB), + 8, + &reject_connector_hdmi_funcs, + no_edid); KUNIT_ASSERT_NOT_NULL(test, priv); conn = &priv->connector; @@ -2006,20 +1961,15 @@ static void drm_test_check_mode_valid_reject_max_clock(struct kunit *test) struct drm_atomic_helper_connector_hdmi_priv *priv; struct drm_connector *conn; struct drm_display_mode *preferred; - int ret; - priv = drm_kunit_helper_connector_hdmi_init(test, - BIT(HDMI_COLORSPACE_RGB), - 8); + priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test, + BIT(HDMI_COLORSPACE_RGB), + 8, + &dummy_connector_hdmi_funcs, + test_edid_hdmi_1080p_rgb_max_100mhz); KUNIT_ASSERT_NOT_NULL(test, priv); conn = &priv->connector; - - ret = set_connector_edid(test, conn, - test_edid_hdmi_1080p_rgb_max_100mhz, - ARRAY_SIZE(test_edid_hdmi_1080p_rgb_max_100mhz)); - KUNIT_ASSERT_GT(test, ret, 0); - KUNIT_ASSERT_EQ(test, conn->display_info.max_tmds_clock, 100 * 1000); preferred = find_preferred_mode(conn); -- cgit v1.2.3 From 95f0f68fc13d03a6b8c0ca09ca9fe4122e6e51ed Mon Sep 17 00:00:00 2001 From: Cristian Ciocaltea Date: Tue, 27 May 2025 15:11:19 +0300 Subject: drm/tests: hdmi: Drop unused drm_kunit_helper_connector_hdmi_init_funcs() After updating the code to make use of the new EDID setup helper, drm_kunit_helper_connector_hdmi_init_funcs() became unused, hence drop it. Acked-by: Maxime Ripard Signed-off-by: Cristian Ciocaltea Link: https://lore.kernel.org/r/20250527-hdmi-conn-yuv-v5-11-74c9c4a8ac0c@collabora.com Signed-off-by: Maxime Ripard --- drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c | 10 ---------- 1 file changed, 10 deletions(-) (limited to 'drivers/gpu/drm/tests') diff --git a/drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c b/drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c index b8f4dc677be7..64037110bcaa 100644 --- a/drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c +++ b/drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c @@ -206,16 +206,6 @@ __connector_hdmi_init(struct kunit *test, return priv; } -static -struct drm_atomic_helper_connector_hdmi_priv * -drm_kunit_helper_connector_hdmi_init_funcs(struct kunit *test, - unsigned int formats, - unsigned int max_bpc, - const struct drm_connector_hdmi_funcs *hdmi_funcs) -{ - return __connector_hdmi_init(test, formats, max_bpc, hdmi_funcs, NULL, 0); -} - #define drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test, formats, max_bpc, funcs, edid) \ __connector_hdmi_init(test, formats, max_bpc, funcs, edid, ARRAY_SIZE(edid)) -- cgit v1.2.3 From 8deb5bd34858b0ac165d6a56e65a64bc5367e361 Mon Sep 17 00:00:00 2001 From: Cristian Ciocaltea Date: Tue, 27 May 2025 15:11:20 +0300 Subject: drm/tests: hdmi: Setup ycbcr_420_allowed before initializing connector Initializing HDMI connector via drmm_connector_hdmi_init() requires its ->ycbcr_420_allowed flag to be adjusted according to the supported formats passed as function argument, prior to the actual invocation. In order to allow providing test coverage for YUV420 modes, ensure the flag is properly setup. Reviewed-by: Maxime Ripard Signed-off-by: Cristian Ciocaltea Link: https://lore.kernel.org/r/20250527-hdmi-conn-yuv-v5-12-74c9c4a8ac0c@collabora.com Signed-off-by: Maxime Ripard --- drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/gpu/drm/tests') diff --git a/drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c b/drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c index 64037110bcaa..e3e2878d29ea 100644 --- a/drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c +++ b/drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c @@ -183,6 +183,8 @@ __connector_hdmi_init(struct kunit *test, enc->possible_crtcs = drm_crtc_mask(priv->crtc); conn = &priv->connector; + conn->ycbcr_420_allowed = !!(formats & BIT(HDMI_COLORSPACE_YUV420)); + ret = drmm_connector_hdmi_init(drm, conn, "Vendor", "Product", &dummy_connector_funcs, -- cgit v1.2.3 From 723d5a70d1de14b34fabcd98ba697de17fa251c4 Mon Sep 17 00:00:00 2001 From: Cristian Ciocaltea Date: Tue, 27 May 2025 15:11:21 +0300 Subject: drm/tests: hdmi: Switch to drm_atomic_get_new_connector_state() where possible Replace the calls to drm_atomic_get_connector_state() with drm_atomic_get_new_connector_state() for cases which do not require allocating the connector state, e.g. after drm_atomic_check_only() when the intent is to only read the new connector state. The rational is to avoid the need to handle the potential EDEADLK error returned by the former helper, which would require restarting the entire atomic sequence. Acked-by: Maxime Ripard Signed-off-by: Cristian Ciocaltea Link: https://lore.kernel.org/r/20250527-hdmi-conn-yuv-v5-13-74c9c4a8ac0c@collabora.com Signed-off-by: Maxime Ripard --- drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/gpu/drm/tests') diff --git a/drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c b/drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c index e3e2878d29ea..168fe25529e5 100644 --- a/drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c +++ b/drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c @@ -416,7 +416,7 @@ static void drm_test_check_broadcast_rgb_auto_cea_mode(struct kunit *test) ret = drm_atomic_check_only(state); KUNIT_ASSERT_EQ(test, ret, 0); - conn_state = drm_atomic_get_connector_state(state, conn); + conn_state = drm_atomic_get_new_connector_state(state, conn); KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state); KUNIT_EXPECT_TRUE(test, conn_state->hdmi.is_limited_range); @@ -476,7 +476,7 @@ static void drm_test_check_broadcast_rgb_auto_cea_mode_vic_1(struct kunit *test) ret = drm_atomic_check_only(state); KUNIT_ASSERT_EQ(test, ret, 0); - conn_state = drm_atomic_get_connector_state(state, conn); + conn_state = drm_atomic_get_new_connector_state(state, conn); KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state); KUNIT_EXPECT_FALSE(test, conn_state->hdmi.is_limited_range); @@ -535,7 +535,7 @@ static void drm_test_check_broadcast_rgb_full_cea_mode(struct kunit *test) ret = drm_atomic_check_only(state); KUNIT_ASSERT_EQ(test, ret, 0); - conn_state = drm_atomic_get_connector_state(state, conn); + conn_state = drm_atomic_get_new_connector_state(state, conn); KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state); KUNIT_ASSERT_EQ(test, @@ -597,7 +597,7 @@ static void drm_test_check_broadcast_rgb_full_cea_mode_vic_1(struct kunit *test) ret = drm_atomic_check_only(state); KUNIT_ASSERT_EQ(test, ret, 0); - conn_state = drm_atomic_get_connector_state(state, conn); + conn_state = drm_atomic_get_new_connector_state(state, conn); KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state); KUNIT_ASSERT_EQ(test, @@ -660,7 +660,7 @@ static void drm_test_check_broadcast_rgb_limited_cea_mode(struct kunit *test) ret = drm_atomic_check_only(state); KUNIT_ASSERT_EQ(test, ret, 0); - conn_state = drm_atomic_get_connector_state(state, conn); + conn_state = drm_atomic_get_new_connector_state(state, conn); KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state); KUNIT_ASSERT_EQ(test, @@ -722,7 +722,7 @@ static void drm_test_check_broadcast_rgb_limited_cea_mode_vic_1(struct kunit *te ret = drm_atomic_check_only(state); KUNIT_ASSERT_EQ(test, ret, 0); - conn_state = drm_atomic_get_connector_state(state, conn); + conn_state = drm_atomic_get_new_connector_state(state, conn); KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state); KUNIT_ASSERT_EQ(test, -- cgit v1.2.3 From 58fe1d78605e78e94341b89b98a47f1aca944441 Mon Sep 17 00:00:00 2001 From: Cristian Ciocaltea Date: Tue, 27 May 2025 15:11:22 +0300 Subject: drm/tests: hdmi: Provide EDID supporting 4K@30Hz with YUV420 only Create a test EDID advertising the following capabilities: Max resolution: - 1920x1080@60Hz with RGB, YUV444, YUV422 - 3840x2160@30Hz with YUV420 only Max BPC: 16 for all modes Max TMDS clock: 200 MHz Acked-by: Maxime Ripard Signed-off-by: Cristian Ciocaltea Link: https://lore.kernel.org/r/20250527-hdmi-conn-yuv-v5-14-74c9c4a8ac0c@collabora.com Signed-off-by: Maxime Ripard --- drivers/gpu/drm/tests/drm_kunit_edid.h | 118 +++++++++++++++++++++++++++++++++ 1 file changed, 118 insertions(+) (limited to 'drivers/gpu/drm/tests') diff --git a/drivers/gpu/drm/tests/drm_kunit_edid.h b/drivers/gpu/drm/tests/drm_kunit_edid.h index 6358397a5d7a..027d8aa5bccd 100644 --- a/drivers/gpu/drm/tests/drm_kunit_edid.h +++ b/drivers/gpu/drm/tests/drm_kunit_edid.h @@ -583,4 +583,122 @@ static const unsigned char test_edid_hdmi_1080p_rgb_yuv_dc_max_340mhz[] = { 0x00, 0x00, 0x00, 0x8c }; +/* + * Max resolution: + * - 1920x1080@60Hz with RGB, YUV444, YUV422 + * - 3840x2160@30Hz with YUV420 only + * Max BPC: 16 for all modes + * Max TMDS clock: 200 MHz + * + * edid-decode (hex): + * + * 00 ff ff ff ff ff ff 00 31 d8 34 00 00 00 00 00 + * ff 23 01 03 80 60 36 78 0f ee 91 a3 54 4c 99 26 + * 0f 50 54 20 00 00 01 01 01 01 01 01 01 01 01 01 + * 01 01 01 01 01 01 02 3a 80 18 71 38 2d 40 58 2c + * 45 00 c0 1c 32 00 00 1e 00 00 00 fc 00 54 65 73 + * 74 20 45 44 49 44 0a 20 20 20 00 00 00 fd 00 18 + * 55 18 5e 11 00 0a 20 20 20 20 20 20 00 00 00 10 + * 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 bb + * + * 02 03 29 31 42 90 5f 6c 03 0c 00 10 00 78 28 20 + * 00 00 01 03 6d d8 5d c4 01 28 80 07 00 00 00 00 + * 00 00 e3 0f 00 00 e2 0e 5f 00 00 00 00 00 00 00 + * 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + * 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + * 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + * 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + * 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ca + * + * ---------------- + * + * Block 0, Base EDID: + * EDID Structure Version & Revision: 1.3 + * Vendor & Product Identification: + * Manufacturer: LNX + * Model: 52 + * Model year: 2025 + * Basic Display Parameters & Features: + * Digital display + * Maximum image size: 96 cm x 54 cm + * Gamma: 2.20 + * RGB color display + * Default (sRGB) color space is primary color space + * First detailed timing is the preferred timing + * Supports GTF timings within operating range + * Color Characteristics: + * Red : 0.6396, 0.3300 + * Green: 0.2998, 0.5996 + * Blue : 0.1503, 0.0595 + * White: 0.3125, 0.3291 + * Established Timings I & II: + * DMT 0x04: 640x480 59.940476 Hz 4:3 31.469 kHz 25.175000 MHz + * Standard Timings: none + * Detailed Timing Descriptors: + * DTD 1: 1920x1080 60.000000 Hz 16:9 67.500 kHz 148.500000 MHz (960 mm x 540 mm) + * Hfront 88 Hsync 44 Hback 148 Hpol P + * Vfront 4 Vsync 5 Vback 36 Vpol P + * Display Product Name: 'Test EDID' + * Display Range Limits: + * Monitor ranges (GTF): 24-85 Hz V, 24-94 kHz H, max dotclock 170 MHz + * Dummy Descriptor: + * Extension blocks: 1 + * Checksum: 0xbb + * + * ---------------- + * + * Block 1, CTA-861 Extension Block: + * Revision: 3 + * Supports YCbCr 4:4:4 + * Supports YCbCr 4:2:2 + * Native detailed modes: 1 + * Video Data Block: + * VIC 16: 1920x1080 60.000000 Hz 16:9 67.500 kHz 148.500000 MHz (native) + * VIC 95: 3840x2160 30.000000 Hz 16:9 67.500 kHz 297.000000 MHz + * Vendor-Specific Data Block (HDMI), OUI 00-0C-03: + * Source physical address: 1.0.0.0 + * DC_48bit + * DC_36bit + * DC_30bit + * DC_Y444 + * Maximum TMDS clock: 200 MHz + * Extended HDMI video details: + * Vendor-Specific Data Block (HDMI Forum), OUI C4-5D-D8: + * Version: 1 + * Maximum TMDS Character Rate: 200 MHz + * SCDC Present + * Supports 16-bits/component Deep Color 4:2:0 Pixel Encoding + * Supports 12-bits/component Deep Color 4:2:0 Pixel Encoding + * Supports 10-bits/component Deep Color 4:2:0 Pixel Encoding + * YCbCr 4:2:0 Capability Map Data Block: + * Empty Capability Map + * YCbCr 4:2:0 Video Data Block: + * VIC 95: 3840x2160 30.000000 Hz 16:9 67.500 kHz 297.000000 MHz + * Checksum: 0xca + */ +static const unsigned char test_edid_hdmi_1080p_rgb_yuv_4k_yuv420_dc_max_200mhz[] = { + 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x31, 0xd8, 0x34, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0x23, 0x01, 0x03, 0x80, 0x60, 0x36, 0x78, + 0x0f, 0xee, 0x91, 0xa3, 0x54, 0x4c, 0x99, 0x26, 0x0f, 0x50, 0x54, 0x20, + 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x3a, 0x80, 0x18, 0x71, 0x38, + 0x2d, 0x40, 0x58, 0x2c, 0x45, 0x00, 0xc0, 0x1c, 0x32, 0x00, 0x00, 0x1e, + 0x00, 0x00, 0x00, 0xfc, 0x00, 0x54, 0x65, 0x73, 0x74, 0x20, 0x45, 0x44, + 0x49, 0x44, 0x0a, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x18, + 0x55, 0x18, 0x5e, 0x11, 0x00, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xbb, 0x02, 0x03, 0x29, 0x31, + 0x42, 0x90, 0x5f, 0x6c, 0x03, 0x0c, 0x00, 0x10, 0x00, 0x78, 0x28, 0x20, + 0x00, 0x00, 0x01, 0x03, 0x6d, 0xd8, 0x5d, 0xc4, 0x01, 0x28, 0x80, 0x07, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe3, 0x0f, 0x00, 0x00, 0xe2, 0x0e, + 0x5f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xca +}; + #endif // DRM_KUNIT_EDID_H_ -- cgit v1.2.3 From 8138078dc048c5160d59b55a33f618688b5fe74b Mon Sep 17 00:00:00 2001 From: Cristian Ciocaltea Date: Tue, 27 May 2025 15:11:23 +0300 Subject: drm/tests: hdmi: Add limited range tests for YUV420 mode Provide tests to verify that drm_atomic_helper_connector_hdmi_check() helper behaviour when using YUV420 output format is to always set the limited RGB quantization range to 'limited', no matter what the value of Broadcast RGB property is. Acked-by: Maxime Ripard Signed-off-by: Cristian Ciocaltea Link: https://lore.kernel.org/r/20250527-hdmi-conn-yuv-v5-15-74c9c4a8ac0c@collabora.com Signed-off-by: Maxime Ripard --- drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c | 108 ++++++++++++++++++++- 1 file changed, 103 insertions(+), 5 deletions(-) (limited to 'drivers/gpu/drm/tests') diff --git a/drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c b/drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c index 168fe25529e5..8015e4c46904 100644 --- a/drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c +++ b/drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c @@ -735,6 +735,107 @@ static void drm_test_check_broadcast_rgb_limited_cea_mode_vic_1(struct kunit *te drm_modeset_acquire_fini(&ctx); } +/* + * Test that for an HDMI connector, with an HDMI monitor, we will + * get a limited RGB Quantization Range with a YUV420 mode, no + * matter what the value of the Broadcast RGB property is set to. + */ +static void drm_test_check_broadcast_rgb_cea_mode_yuv420(struct kunit *test) +{ + struct drm_atomic_helper_connector_hdmi_priv *priv; + enum drm_hdmi_broadcast_rgb broadcast_rgb; + struct drm_modeset_acquire_ctx ctx; + struct drm_connector_state *conn_state; + struct drm_atomic_state *state; + struct drm_display_mode *mode; + struct drm_connector *conn; + struct drm_device *drm; + struct drm_crtc *crtc; + int ret; + + broadcast_rgb = *(enum drm_hdmi_broadcast_rgb *)test->param_value; + + priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test, + BIT(HDMI_COLORSPACE_RGB) | + BIT(HDMI_COLORSPACE_YUV420), + 8, + &dummy_connector_hdmi_funcs, + test_edid_hdmi_1080p_rgb_yuv_4k_yuv420_dc_max_200mhz); + KUNIT_ASSERT_NOT_NULL(test, priv); + + drm = &priv->drm; + crtc = priv->crtc; + conn = &priv->connector; + KUNIT_ASSERT_TRUE(test, conn->display_info.is_hdmi); + + mode = drm_kunit_display_mode_from_cea_vic(test, drm, 95); + KUNIT_ASSERT_NOT_NULL(test, mode); + + drm_modeset_acquire_init(&ctx, 0); + +retry_conn_enable: + ret = drm_kunit_helper_enable_crtc_connector(test, drm, crtc, conn, + mode, &ctx); + if (ret == -EDEADLK) { + ret = drm_modeset_backoff(&ctx); + if (!ret) + goto retry_conn_enable; + } + KUNIT_ASSERT_EQ(test, ret, 0); + + state = drm_kunit_helper_atomic_state_alloc(test, drm, &ctx); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state); + +retry_conn_state: + conn_state = drm_atomic_get_connector_state(state, conn); + if (PTR_ERR(conn_state) == -EDEADLK) { + drm_atomic_state_clear(state); + ret = drm_modeset_backoff(&ctx); + if (!ret) + goto retry_conn_state; + } + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state); + + conn_state->hdmi.broadcast_rgb = broadcast_rgb; + + ret = drm_atomic_check_only(state); + if (ret == -EDEADLK) { + drm_atomic_state_clear(state); + ret = drm_modeset_backoff(&ctx); + if (!ret) + goto retry_conn_state; + } + KUNIT_ASSERT_EQ(test, ret, 0); + + conn_state = drm_atomic_get_new_connector_state(state, conn); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state); + + KUNIT_ASSERT_EQ(test, conn_state->hdmi.broadcast_rgb, broadcast_rgb); + KUNIT_ASSERT_EQ(test, conn_state->hdmi.output_format, HDMI_COLORSPACE_YUV420); + + KUNIT_EXPECT_TRUE(test, conn_state->hdmi.is_limited_range); + + drm_modeset_drop_locks(&ctx); + drm_modeset_acquire_fini(&ctx); +} + +static const enum drm_hdmi_broadcast_rgb check_broadcast_rgb_cea_mode_yuv420_tests[] = { + DRM_HDMI_BROADCAST_RGB_AUTO, + DRM_HDMI_BROADCAST_RGB_FULL, + DRM_HDMI_BROADCAST_RGB_LIMITED, +}; + +static void +check_broadcast_rgb_cea_mode_yuv420_desc(const enum drm_hdmi_broadcast_rgb *broadcast_rgb, + char *desc) +{ + sprintf(desc, "%s", drm_hdmi_connector_get_broadcast_rgb_name(*broadcast_rgb)); +} + +KUNIT_ARRAY_PARAM(check_broadcast_rgb_cea_mode_yuv420, + check_broadcast_rgb_cea_mode_yuv420_tests, + check_broadcast_rgb_cea_mode_yuv420_desc); + /* * Test that if we change the maximum bpc property to a different value, * we trigger a mode change on the connector's CRTC, which will in turn @@ -1667,11 +1768,8 @@ static struct kunit_case drm_atomic_helper_connector_hdmi_check_tests[] = { KUNIT_CASE(drm_test_check_broadcast_rgb_full_cea_mode_vic_1), KUNIT_CASE(drm_test_check_broadcast_rgb_limited_cea_mode), KUNIT_CASE(drm_test_check_broadcast_rgb_limited_cea_mode_vic_1), - /* - * TODO: When we'll have YUV output support, we need to check - * that the limited range is always set to limited no matter - * what the value of Broadcast RGB is. - */ + KUNIT_CASE_PARAM(drm_test_check_broadcast_rgb_cea_mode_yuv420, + check_broadcast_rgb_cea_mode_yuv420_gen_params), KUNIT_CASE(drm_test_check_broadcast_rgb_crtc_mode_changed), KUNIT_CASE(drm_test_check_broadcast_rgb_crtc_mode_not_changed), KUNIT_CASE(drm_test_check_disable_connector), -- cgit v1.2.3 From a3d1bfc174dc304d2166a3cca069882faa370658 Mon Sep 17 00:00:00 2001 From: Cristian Ciocaltea Date: Tue, 27 May 2025 15:11:24 +0300 Subject: drm/tests: hdmi: Rename max TMDS rate fallback tests In preparation to extend the max TMDS rate fallback tests for covering YUV420 output, update the rather generic function names drm_test_check_max_tmds_rate_{bpc|format}_fallback() to properly indicate the intended test cases. Acked-by: Maxime Ripard Signed-off-by: Cristian Ciocaltea Link: https://lore.kernel.org/r/20250527-hdmi-conn-yuv-v5-16-74c9c4a8ac0c@collabora.com Signed-off-by: Maxime Ripard --- drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/gpu/drm/tests') diff --git a/drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c b/drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c index 8015e4c46904..c6f7c33f5f71 100644 --- a/drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c +++ b/drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c @@ -1253,7 +1253,7 @@ static void drm_test_check_hdmi_funcs_reject_rate(struct kunit *test) * Then we will pick the latter, and the computed TMDS character rate * will be equal to 1.25 times the mode pixel clock. */ -static void drm_test_check_max_tmds_rate_bpc_fallback(struct kunit *test) +static void drm_test_check_max_tmds_rate_bpc_fallback_rgb(struct kunit *test) { struct drm_atomic_helper_connector_hdmi_priv *priv; struct drm_modeset_acquire_ctx ctx; @@ -1322,7 +1322,7 @@ static void drm_test_check_max_tmds_rate_bpc_fallback(struct kunit *test) * Then we will prefer to keep the RGB format with a lower bpc over * picking YUV422. */ -static void drm_test_check_max_tmds_rate_format_fallback(struct kunit *test) +static void drm_test_check_max_tmds_rate_bpc_fallback_ignore_yuv422(struct kunit *test) { struct drm_atomic_helper_connector_hdmi_priv *priv; struct drm_modeset_acquire_ctx ctx; @@ -1774,8 +1774,8 @@ static struct kunit_case drm_atomic_helper_connector_hdmi_check_tests[] = { KUNIT_CASE(drm_test_check_broadcast_rgb_crtc_mode_not_changed), KUNIT_CASE(drm_test_check_disable_connector), KUNIT_CASE(drm_test_check_hdmi_funcs_reject_rate), - KUNIT_CASE(drm_test_check_max_tmds_rate_bpc_fallback), - KUNIT_CASE(drm_test_check_max_tmds_rate_format_fallback), + KUNIT_CASE(drm_test_check_max_tmds_rate_bpc_fallback_rgb), + KUNIT_CASE(drm_test_check_max_tmds_rate_bpc_fallback_ignore_yuv422), KUNIT_CASE(drm_test_check_output_bpc_crtc_mode_changed), KUNIT_CASE(drm_test_check_output_bpc_crtc_mode_not_changed), KUNIT_CASE(drm_test_check_output_bpc_dvi), -- cgit v1.2.3 From 54a5f1c4d5f84af18a971c665df751ee3f0423dc Mon Sep 17 00:00:00 2001 From: Cristian Ciocaltea Date: Tue, 27 May 2025 15:11:25 +0300 Subject: drm/tests: hdmi: Provide EDID supporting 4K@30Hz with RGB/YUV Create a test EDID advertising the following capabilities: Max resolution: 3840x2160@30Hz with RGB, YUV444, YUV422, YUV420 Max BPC: 16 for all modes Max TMDS clock: 340 MHz Acked-by: Maxime Ripard Signed-off-by: Cristian Ciocaltea Link: https://lore.kernel.org/r/20250527-hdmi-conn-yuv-v5-17-74c9c4a8ac0c@collabora.com Signed-off-by: Maxime Ripard --- drivers/gpu/drm/tests/drm_kunit_edid.h | 114 +++++++++++++++++++++++++++++++++ 1 file changed, 114 insertions(+) (limited to 'drivers/gpu/drm/tests') diff --git a/drivers/gpu/drm/tests/drm_kunit_edid.h b/drivers/gpu/drm/tests/drm_kunit_edid.h index 027d8aa5bccd..02e2761b3b1f 100644 --- a/drivers/gpu/drm/tests/drm_kunit_edid.h +++ b/drivers/gpu/drm/tests/drm_kunit_edid.h @@ -701,4 +701,118 @@ static const unsigned char test_edid_hdmi_1080p_rgb_yuv_4k_yuv420_dc_max_200mhz[ 0x00, 0x00, 0x00, 0xca }; +/* + * Max resolution: 3840x2160@30Hz with RGB, YUV444, YUV422, YUV420 + * Max BPC: 16 for all modes + * Max TMDS clock: 340 MHz + * + * edid-decode (hex): + * + * 00 ff ff ff ff ff ff 00 31 d8 34 00 00 00 00 00 + * ff 23 01 03 80 60 36 78 0f ee 91 a3 54 4c 99 26 + * 0f 50 54 20 00 00 01 01 01 01 01 01 01 01 01 01 + * 01 01 01 01 01 01 04 74 00 30 f2 70 5a 80 b0 58 + * 8a 00 40 84 63 00 00 1e 00 00 00 fc 00 54 65 73 + * 74 20 45 44 49 44 0a 20 20 20 00 00 00 fd 00 18 + * 55 18 5e 22 00 0a 20 20 20 20 20 20 00 00 00 10 + * 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 ce + * + * 02 03 27 31 41 5f 6c 03 0c 00 10 00 78 44 20 00 + * 00 01 03 6d d8 5d c4 01 44 80 07 00 00 00 00 00 + * 00 e3 0f 01 00 e1 0e 00 00 00 00 00 00 00 00 00 + * 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + * 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + * 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + * 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + * 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 84 + * + * ---------------- + * + * Block 0, Base EDID: + * EDID Structure Version & Revision: 1.3 + * Vendor & Product Identification: + * Manufacturer: LNX + * Model: 52 + * Model year: 2025 + * Basic Display Parameters & Features: + * Digital display + * Maximum image size: 96 cm x 54 cm + * Gamma: 2.20 + * RGB color display + * Default (sRGB) color space is primary color space + * First detailed timing is the preferred timing + * Supports GTF timings within operating range + * Color Characteristics: + * Red : 0.6396, 0.3300 + * Green: 0.2998, 0.5996 + * Blue : 0.1503, 0.0595 + * White: 0.3125, 0.3291 + * Established Timings I & II: + * DMT 0x04: 640x480 59.940476 Hz 4:3 31.469 kHz 25.175000 MHz + * Standard Timings: none + * Detailed Timing Descriptors: + * DTD 1: 3840x2160 30.000000 Hz 16:9 67.500 kHz 297.000000 MHz (1600 mm x 900 mm) + * Hfront 176 Hsync 88 Hback 296 Hpol P + * Vfront 8 Vsync 10 Vback 72 Vpol P + * Display Product Name: 'Test EDID' + * Display Range Limits: + * Monitor ranges (GTF): 24-85 Hz V, 24-94 kHz H, max dotclock 340 MHz + * Dummy Descriptor: + * Extension blocks: 1 + * Checksum: 0xce + * + * ---------------- + * + * Block 1, CTA-861 Extension Block: + * Revision: 3 + * Supports YCbCr 4:4:4 + * Supports YCbCr 4:2:2 + * Native detailed modes: 1 + * Video Data Block: + * VIC 95: 3840x2160 30.000000 Hz 16:9 67.500 kHz 297.000000 MHz + * Vendor-Specific Data Block (HDMI), OUI 00-0C-03: + * Source physical address: 1.0.0.0 + * DC_48bit + * DC_36bit + * DC_30bit + * DC_Y444 + * Maximum TMDS clock: 340 MHz + * Extended HDMI video details: + * Vendor-Specific Data Block (HDMI Forum), OUI C4-5D-D8: + * Version: 1 + * Maximum TMDS Character Rate: 340 MHz + * SCDC Present + * Supports 16-bits/component Deep Color 4:2:0 Pixel Encoding + * Supports 12-bits/component Deep Color 4:2:0 Pixel Encoding + * Supports 10-bits/component Deep Color 4:2:0 Pixel Encoding + * YCbCr 4:2:0 Capability Map Data Block: + * VIC 95: 3840x2160 30.000000 Hz 16:9 67.500 kHz 297.000000 MHz + * YCbCr 4:2:0 Video Data Block: + * Checksum: 0x84 + */ +static const unsigned char test_edid_hdmi_4k_rgb_yuv420_dc_max_340mhz[] = { + 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x31, 0xd8, 0x34, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0x23, 0x01, 0x03, 0x80, 0x60, 0x36, 0x78, + 0x0f, 0xee, 0x91, 0xa3, 0x54, 0x4c, 0x99, 0x26, 0x0f, 0x50, 0x54, 0x20, + 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x04, 0x74, 0x00, 0x30, 0xf2, 0x70, + 0x5a, 0x80, 0xb0, 0x58, 0x8a, 0x00, 0x40, 0x84, 0x63, 0x00, 0x00, 0x1e, + 0x00, 0x00, 0x00, 0xfc, 0x00, 0x54, 0x65, 0x73, 0x74, 0x20, 0x45, 0x44, + 0x49, 0x44, 0x0a, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x18, + 0x55, 0x18, 0x5e, 0x22, 0x00, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xce, 0x02, 0x03, 0x27, 0x31, + 0x41, 0x5f, 0x6c, 0x03, 0x0c, 0x00, 0x10, 0x00, 0x78, 0x44, 0x20, 0x00, + 0x00, 0x01, 0x03, 0x6d, 0xd8, 0x5d, 0xc4, 0x01, 0x44, 0x80, 0x07, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xe3, 0x0f, 0x01, 0x00, 0xe1, 0x0e, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x84 +}; + #endif // DRM_KUNIT_EDID_H_ -- cgit v1.2.3 From e271ecaaa570d4c956ba079b0724aa5194c0b617 Mon Sep 17 00:00:00 2001 From: Cristian Ciocaltea Date: Tue, 27 May 2025 15:11:26 +0300 Subject: drm/tests: hdmi: Add max TMDS rate fallback tests for YUV420 mode Provide tests to verify drm_atomic_helper_connector_hdmi_check() helper fallback behavior when using YUV420 output format. Acked-by: Maxime Ripard Signed-off-by: Cristian Ciocaltea Link: https://lore.kernel.org/r/20250527-hdmi-conn-yuv-v5-18-74c9c4a8ac0c@collabora.com Signed-off-by: Maxime Ripard --- drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c | 154 +++++++++++++++++++++ 1 file changed, 154 insertions(+) (limited to 'drivers/gpu/drm/tests') diff --git a/drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c b/drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c index c6f7c33f5f71..d98fb9803b46 100644 --- a/drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c +++ b/drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c @@ -1309,6 +1309,80 @@ static void drm_test_check_max_tmds_rate_bpc_fallback_rgb(struct kunit *test) drm_modeset_acquire_fini(&ctx); } +/* + * Test that if: + * - We have an HDMI connector and a display supporting both RGB and YUV420 + * - The chosen mode can be supported in YUV420 output format only + * - The chosen mode has a TMDS character rate higher than the display + * supports in YUV420/12bpc + * - The chosen mode has a TMDS character rate lower than the display + * supports in YUV420/10bpc. + * + * Then we will pick the latter, and the computed TMDS character rate + * will be equal to 1.25 * 0.5 times the mode pixel clock. + */ +static void drm_test_check_max_tmds_rate_bpc_fallback_yuv420(struct kunit *test) +{ + struct drm_atomic_helper_connector_hdmi_priv *priv; + struct drm_modeset_acquire_ctx ctx; + struct drm_connector_state *conn_state; + struct drm_display_info *info; + struct drm_display_mode *yuv420_only_mode; + unsigned long long rate; + struct drm_connector *conn; + struct drm_device *drm; + struct drm_crtc *crtc; + int ret; + + priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test, + BIT(HDMI_COLORSPACE_RGB) | + BIT(HDMI_COLORSPACE_YUV420), + 12, + &dummy_connector_hdmi_funcs, + test_edid_hdmi_1080p_rgb_yuv_4k_yuv420_dc_max_200mhz); + KUNIT_ASSERT_NOT_NULL(test, priv); + + drm = &priv->drm; + crtc = priv->crtc; + conn = &priv->connector; + info = &conn->display_info; + KUNIT_ASSERT_TRUE(test, info->is_hdmi); + KUNIT_ASSERT_GT(test, info->max_tmds_clock, 0); + KUNIT_ASSERT_TRUE(test, conn->ycbcr_420_allowed); + + yuv420_only_mode = drm_kunit_display_mode_from_cea_vic(test, drm, 95); + KUNIT_ASSERT_NOT_NULL(test, yuv420_only_mode); + KUNIT_ASSERT_TRUE(test, drm_mode_is_420_only(info, yuv420_only_mode)); + + rate = drm_hdmi_compute_mode_clock(yuv420_only_mode, 12, HDMI_COLORSPACE_YUV420); + KUNIT_ASSERT_GT(test, rate, info->max_tmds_clock * 1000); + + rate = drm_hdmi_compute_mode_clock(yuv420_only_mode, 10, HDMI_COLORSPACE_YUV420); + KUNIT_ASSERT_LT(test, rate, info->max_tmds_clock * 1000); + + drm_modeset_acquire_init(&ctx, 0); + +retry_conn_enable: + ret = drm_kunit_helper_enable_crtc_connector(test, drm, crtc, conn, + yuv420_only_mode, &ctx); + if (ret == -EDEADLK) { + ret = drm_modeset_backoff(&ctx); + if (!ret) + goto retry_conn_enable; + } + KUNIT_EXPECT_EQ(test, ret, 0); + + conn_state = conn->state; + KUNIT_ASSERT_NOT_NULL(test, conn_state); + + KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_bpc, 10); + KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_format, HDMI_COLORSPACE_YUV420); + KUNIT_EXPECT_EQ(test, conn_state->hdmi.tmds_char_rate, yuv420_only_mode->clock * 625); + + drm_modeset_drop_locks(&ctx); + drm_modeset_acquire_fini(&ctx); +} + /* * Test that if: * - We have an HDMI connector supporting both RGB and YUV422 and up to @@ -1382,6 +1456,84 @@ static void drm_test_check_max_tmds_rate_bpc_fallback_ignore_yuv422(struct kunit drm_modeset_acquire_fini(&ctx); } +/* + * Test that if: + * - We have an HDMI connector supporting both RGB and YUV420 and up to + * 12 bpc + * - The chosen mode has a TMDS character rate higher than the display + * supports in RGB/10bpc but lower than the display supports in + * RGB/8bpc + * - The chosen mode has a TMDS character rate lower than the display + * supports in YUV420/12bpc. + * + * Then we will prefer to keep the RGB format with a lower bpc over + * picking YUV420. + */ +static void drm_test_check_max_tmds_rate_bpc_fallback_ignore_yuv420(struct kunit *test) +{ + struct drm_atomic_helper_connector_hdmi_priv *priv; + struct drm_modeset_acquire_ctx ctx; + struct drm_connector_state *conn_state; + struct drm_display_info *info; + struct drm_display_mode *preferred; + unsigned long long rate; + struct drm_connector *conn; + struct drm_device *drm; + struct drm_crtc *crtc; + int ret; + + priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test, + BIT(HDMI_COLORSPACE_RGB) | + BIT(HDMI_COLORSPACE_YUV420), + 12, + &dummy_connector_hdmi_funcs, + test_edid_hdmi_4k_rgb_yuv420_dc_max_340mhz); + KUNIT_ASSERT_NOT_NULL(test, priv); + + drm = &priv->drm; + crtc = priv->crtc; + conn = &priv->connector; + info = &conn->display_info; + KUNIT_ASSERT_TRUE(test, info->is_hdmi); + KUNIT_ASSERT_GT(test, info->max_tmds_clock, 0); + KUNIT_ASSERT_TRUE(test, conn->ycbcr_420_allowed); + + preferred = find_preferred_mode(conn); + KUNIT_ASSERT_NOT_NULL(test, preferred); + KUNIT_ASSERT_FALSE(test, preferred->flags & DRM_MODE_FLAG_DBLCLK); + KUNIT_ASSERT_TRUE(test, drm_mode_is_420_also(info, preferred)); + + rate = drm_hdmi_compute_mode_clock(preferred, 8, HDMI_COLORSPACE_RGB); + KUNIT_ASSERT_LT(test, rate, info->max_tmds_clock * 1000); + + rate = drm_hdmi_compute_mode_clock(preferred, 10, HDMI_COLORSPACE_RGB); + KUNIT_ASSERT_GT(test, rate, info->max_tmds_clock * 1000); + + rate = drm_hdmi_compute_mode_clock(preferred, 12, HDMI_COLORSPACE_YUV420); + KUNIT_ASSERT_LT(test, rate, info->max_tmds_clock * 1000); + + drm_modeset_acquire_init(&ctx, 0); + +retry_conn_enable: + ret = drm_kunit_helper_enable_crtc_connector(test, drm, crtc, conn, + preferred, &ctx); + if (ret == -EDEADLK) { + ret = drm_modeset_backoff(&ctx); + if (!ret) + goto retry_conn_enable; + } + KUNIT_EXPECT_EQ(test, ret, 0); + + conn_state = conn->state; + KUNIT_ASSERT_NOT_NULL(test, conn_state); + + KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_bpc, 8); + KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_format, HDMI_COLORSPACE_RGB); + + drm_modeset_drop_locks(&ctx); + drm_modeset_acquire_fini(&ctx); +} + /* * Test that if a driver and screen supports RGB and YUV formats, and we * try to set the VIC 1 mode, we end up with 8bpc RGB even if we could @@ -1775,7 +1927,9 @@ static struct kunit_case drm_atomic_helper_connector_hdmi_check_tests[] = { KUNIT_CASE(drm_test_check_disable_connector), KUNIT_CASE(drm_test_check_hdmi_funcs_reject_rate), KUNIT_CASE(drm_test_check_max_tmds_rate_bpc_fallback_rgb), + KUNIT_CASE(drm_test_check_max_tmds_rate_bpc_fallback_yuv420), KUNIT_CASE(drm_test_check_max_tmds_rate_bpc_fallback_ignore_yuv422), + KUNIT_CASE(drm_test_check_max_tmds_rate_bpc_fallback_ignore_yuv420), KUNIT_CASE(drm_test_check_output_bpc_crtc_mode_changed), KUNIT_CASE(drm_test_check_output_bpc_crtc_mode_not_changed), KUNIT_CASE(drm_test_check_output_bpc_dvi), -- cgit v1.2.3 From e42a3c203c95cc6362d78aaff3c478695e6719aa Mon Sep 17 00:00:00 2001 From: Cristian Ciocaltea Date: Tue, 27 May 2025 15:11:27 +0300 Subject: drm/tests: hdmi: Add test for unsuccessful fallback to YUV420 Provide test to verify a mandatory fallback to YUV420 output cannot succeed when driver doesn't advertise YUV420 support. Acked-by: Maxime Ripard Signed-off-by: Cristian Ciocaltea Link: https://lore.kernel.org/r/20250527-hdmi-conn-yuv-v5-19-74c9c4a8ac0c@collabora.com Signed-off-by: Maxime Ripard --- drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c | 87 ++++++++++++++++++++++ 1 file changed, 87 insertions(+) (limited to 'drivers/gpu/drm/tests') diff --git a/drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c b/drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c index d98fb9803b46..8bd412735000 100644 --- a/drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c +++ b/drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c @@ -1534,6 +1534,92 @@ retry_conn_enable: drm_modeset_acquire_fini(&ctx); } +/* + * Test that if a driver supports only RGB, but the chosen mode can be + * supported by the screen only in YUV420 output format, we end up with + * unsuccessful fallback attempts. + */ +static void drm_test_check_driver_unsupported_fallback_yuv420(struct kunit *test) +{ + struct drm_atomic_helper_connector_hdmi_priv *priv; + struct drm_modeset_acquire_ctx ctx; + struct drm_connector_state *conn_state; + struct drm_crtc_state *crtc_state; + struct drm_atomic_state *state; + struct drm_display_info *info; + struct drm_display_mode *preferred, *yuv420_only_mode; + struct drm_connector *conn; + struct drm_device *drm; + struct drm_crtc *crtc; + int ret; + + priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test, + BIT(HDMI_COLORSPACE_RGB), + 12, + &dummy_connector_hdmi_funcs, + test_edid_hdmi_1080p_rgb_yuv_4k_yuv420_dc_max_200mhz); + KUNIT_ASSERT_NOT_NULL(test, priv); + + drm = &priv->drm; + crtc = priv->crtc; + conn = &priv->connector; + info = &conn->display_info; + KUNIT_ASSERT_TRUE(test, info->is_hdmi); + KUNIT_ASSERT_FALSE(test, conn->ycbcr_420_allowed); + + preferred = find_preferred_mode(conn); + KUNIT_ASSERT_NOT_NULL(test, preferred); + KUNIT_ASSERT_FALSE(test, drm_mode_is_420_also(info, preferred)); + + yuv420_only_mode = drm_kunit_display_mode_from_cea_vic(test, drm, 95); + KUNIT_ASSERT_NOT_NULL(test, yuv420_only_mode); + KUNIT_ASSERT_TRUE(test, drm_mode_is_420_only(info, yuv420_only_mode)); + + drm_modeset_acquire_init(&ctx, 0); + +retry_conn_enable: + ret = drm_kunit_helper_enable_crtc_connector(test, drm, crtc, conn, + preferred, &ctx); + if (ret == -EDEADLK) { + ret = drm_modeset_backoff(&ctx); + if (!ret) + goto retry_conn_enable; + } + KUNIT_EXPECT_EQ(test, ret, 0); + + conn_state = conn->state; + KUNIT_ASSERT_NOT_NULL(test, conn_state); + KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_format, HDMI_COLORSPACE_RGB); + + state = drm_kunit_helper_atomic_state_alloc(test, drm, &ctx); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state); + +retry_crtc_state: + crtc_state = drm_atomic_get_crtc_state(state, crtc); + if (PTR_ERR(crtc_state) == -EDEADLK) { + drm_atomic_state_clear(state); + ret = drm_modeset_backoff(&ctx); + if (!ret) + goto retry_crtc_state; + } + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc_state); + + ret = drm_atomic_set_mode_for_crtc(crtc_state, yuv420_only_mode); + KUNIT_EXPECT_EQ(test, ret, 0); + + ret = drm_atomic_check_only(state); + if (ret == -EDEADLK) { + drm_atomic_state_clear(state); + ret = drm_modeset_backoff(&ctx); + if (!ret) + goto retry_crtc_state; + } + KUNIT_ASSERT_LT(test, ret, 0); + + drm_modeset_drop_locks(&ctx); + drm_modeset_acquire_fini(&ctx); +} + /* * Test that if a driver and screen supports RGB and YUV formats, and we * try to set the VIC 1 mode, we end up with 8bpc RGB even if we could @@ -1930,6 +2016,7 @@ static struct kunit_case drm_atomic_helper_connector_hdmi_check_tests[] = { KUNIT_CASE(drm_test_check_max_tmds_rate_bpc_fallback_yuv420), KUNIT_CASE(drm_test_check_max_tmds_rate_bpc_fallback_ignore_yuv422), KUNIT_CASE(drm_test_check_max_tmds_rate_bpc_fallback_ignore_yuv420), + KUNIT_CASE(drm_test_check_driver_unsupported_fallback_yuv420), KUNIT_CASE(drm_test_check_output_bpc_crtc_mode_changed), KUNIT_CASE(drm_test_check_output_bpc_crtc_mode_not_changed), KUNIT_CASE(drm_test_check_output_bpc_dvi), -- cgit v1.2.3 From 1ee7e69292a6f296b2d78393ab409a5bdd65d4e0 Mon Sep 17 00:00:00 2001 From: Luca Ceresoli Date: Fri, 6 Jun 2025 10:41:19 +0200 Subject: drm/tests: bridge: convert to devm_drm_bridge_alloc() API Use the new DRM bridge allocation API, which is the only supported now, for the kunit tests. This change is more massive than for the typical DRM bridge driver because struct drm_bridge_init_priv currently embeds a struct drm_bridge, which is not supported anymore. We now have to use devm_drm_bridge_alloc() to dynamically allocate a "private driver struct", which is a bit awkward here because there is no real bridge driver. Thus let's add a "dummy" DRM bridge struct to represent it. As a nice cleanup we can now move the enable_count and disable_count members, which are counting bridge-specific events, into the new "private driver struct" (and avoid adding new unnecessary indirections). Also add a trivial bridge_to_dummy_bridge() function just like many drivers do. Signed-off-by: Luca Ceresoli Link: https://lore.kernel.org/r/20250606-drm-bridge-alloc-doc-test-v9-1-b5bf7b43ed92@bootlin.com Signed-off-by: Maxime Ripard --- drivers/gpu/drm/tests/drm_bridge_test.c | 87 +++++++++++++++++++-------------- 1 file changed, 51 insertions(+), 36 deletions(-) (limited to 'drivers/gpu/drm/tests') diff --git a/drivers/gpu/drm/tests/drm_bridge_test.c b/drivers/gpu/drm/tests/drm_bridge_test.c index ff88ec2e911c..af1b9f9694b0 100644 --- a/drivers/gpu/drm/tests/drm_bridge_test.c +++ b/drivers/gpu/drm/tests/drm_bridge_test.c @@ -10,29 +10,43 @@ #include +/* + * Mimick the typical "private" struct defined by a bridge driver, which + * embeds a bridge plus other fields. + * + * Having at least one member before @bridge ensures we test non-zero + * @bridge offset. + */ +struct drm_bridge_priv { + unsigned int enable_count; + unsigned int disable_count; + struct drm_bridge bridge; +}; + struct drm_bridge_init_priv { struct drm_device drm; struct drm_plane *plane; struct drm_crtc *crtc; struct drm_encoder encoder; - struct drm_bridge bridge; + struct drm_bridge_priv *test_bridge; struct drm_connector *connector; - unsigned int enable_count; - unsigned int disable_count; }; +static struct drm_bridge_priv *bridge_to_priv(struct drm_bridge *bridge) +{ + return container_of(bridge, struct drm_bridge_priv, bridge); +} + static void drm_test_bridge_enable(struct drm_bridge *bridge) { - struct drm_bridge_init_priv *priv = - container_of(bridge, struct drm_bridge_init_priv, bridge); + struct drm_bridge_priv *priv = bridge_to_priv(bridge); priv->enable_count++; } static void drm_test_bridge_disable(struct drm_bridge *bridge) { - struct drm_bridge_init_priv *priv = - container_of(bridge, struct drm_bridge_init_priv, bridge); + struct drm_bridge_priv *priv = bridge_to_priv(bridge); priv->disable_count++; } @@ -45,8 +59,7 @@ static const struct drm_bridge_funcs drm_test_bridge_legacy_funcs = { static void drm_test_bridge_atomic_enable(struct drm_bridge *bridge, struct drm_atomic_state *state) { - struct drm_bridge_init_priv *priv = - container_of(bridge, struct drm_bridge_init_priv, bridge); + struct drm_bridge_priv *priv = bridge_to_priv(bridge); priv->enable_count++; } @@ -54,8 +67,7 @@ static void drm_test_bridge_atomic_enable(struct drm_bridge *bridge, static void drm_test_bridge_atomic_disable(struct drm_bridge *bridge, struct drm_atomic_state *state) { - struct drm_bridge_init_priv *priv = - container_of(bridge, struct drm_bridge_init_priv, bridge); + struct drm_bridge_priv *priv = bridge_to_priv(bridge); priv->disable_count++; } @@ -102,6 +114,10 @@ drm_test_bridge_init(struct kunit *test, const struct drm_bridge_funcs *funcs) if (IS_ERR(priv)) return ERR_CAST(priv); + priv->test_bridge = devm_drm_bridge_alloc(dev, struct drm_bridge_priv, bridge, funcs); + if (IS_ERR(priv->test_bridge)) + return ERR_CAST(priv->test_bridge); + drm = &priv->drm; priv->plane = drm_kunit_helper_create_primary_plane(test, drm, NULL, @@ -125,9 +141,8 @@ drm_test_bridge_init(struct kunit *test, const struct drm_bridge_funcs *funcs) enc->possible_crtcs = drm_crtc_mask(priv->crtc); - bridge = &priv->bridge; + bridge = &priv->test_bridge->bridge; bridge->type = DRM_MODE_CONNECTOR_VIRTUAL; - bridge->funcs = funcs; ret = drm_kunit_bridge_add(test, bridge); if (ret) @@ -173,7 +188,7 @@ static void drm_test_drm_bridge_get_current_state_atomic(struct kunit *test) KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state); retry_commit: - bridge = &priv->bridge; + bridge = &priv->test_bridge->bridge; bridge_state = drm_atomic_get_bridge_state(state, bridge); KUNIT_ASSERT_NOT_ERR_OR_NULL(test, bridge_state); @@ -228,7 +243,7 @@ static void drm_test_drm_bridge_get_current_state_legacy(struct kunit *test) * locking. The function would return NULL in all cases anyway, * so we don't really have any concurrency to worry about. */ - bridge = &priv->bridge; + bridge = &priv->test_bridge->bridge; KUNIT_EXPECT_NULL(test, drm_bridge_get_current_state(bridge)); } @@ -253,7 +268,7 @@ static void drm_test_drm_bridge_helper_reset_crtc_atomic(struct kunit *test) struct drm_modeset_acquire_ctx ctx; struct drm_bridge_init_priv *priv; struct drm_display_mode *mode; - struct drm_bridge *bridge; + struct drm_bridge_priv *bridge_priv; int ret; priv = drm_test_bridge_init(test, &drm_test_bridge_atomic_funcs); @@ -279,14 +294,14 @@ retry_commit: drm_modeset_drop_locks(&ctx); drm_modeset_acquire_fini(&ctx); - bridge = &priv->bridge; - KUNIT_ASSERT_EQ(test, priv->enable_count, 1); - KUNIT_ASSERT_EQ(test, priv->disable_count, 0); + bridge_priv = priv->test_bridge; + KUNIT_ASSERT_EQ(test, bridge_priv->enable_count, 1); + KUNIT_ASSERT_EQ(test, bridge_priv->disable_count, 0); drm_modeset_acquire_init(&ctx, 0); retry_reset: - ret = drm_bridge_helper_reset_crtc(bridge, &ctx); + ret = drm_bridge_helper_reset_crtc(&bridge_priv->bridge, &ctx); if (ret == -EDEADLK) { drm_modeset_backoff(&ctx); goto retry_reset; @@ -296,8 +311,8 @@ retry_reset: drm_modeset_drop_locks(&ctx); drm_modeset_acquire_fini(&ctx); - KUNIT_EXPECT_EQ(test, priv->enable_count, 2); - KUNIT_EXPECT_EQ(test, priv->disable_count, 1); + KUNIT_EXPECT_EQ(test, bridge_priv->enable_count, 2); + KUNIT_EXPECT_EQ(test, bridge_priv->disable_count, 1); } /* @@ -309,7 +324,7 @@ static void drm_test_drm_bridge_helper_reset_crtc_atomic_disabled(struct kunit * struct drm_modeset_acquire_ctx ctx; struct drm_bridge_init_priv *priv; struct drm_display_mode *mode; - struct drm_bridge *bridge; + struct drm_bridge_priv *bridge_priv; int ret; priv = drm_test_bridge_init(test, &drm_test_bridge_atomic_funcs); @@ -318,14 +333,14 @@ static void drm_test_drm_bridge_helper_reset_crtc_atomic_disabled(struct kunit * mode = drm_kunit_display_mode_from_cea_vic(test, &priv->drm, 16); KUNIT_ASSERT_NOT_ERR_OR_NULL(test, mode); - bridge = &priv->bridge; - KUNIT_ASSERT_EQ(test, priv->enable_count, 0); - KUNIT_ASSERT_EQ(test, priv->disable_count, 0); + bridge_priv = priv->test_bridge; + KUNIT_ASSERT_EQ(test, bridge_priv->enable_count, 0); + KUNIT_ASSERT_EQ(test, bridge_priv->disable_count, 0); drm_modeset_acquire_init(&ctx, 0); retry_reset: - ret = drm_bridge_helper_reset_crtc(bridge, &ctx); + ret = drm_bridge_helper_reset_crtc(&bridge_priv->bridge, &ctx); if (ret == -EDEADLK) { drm_modeset_backoff(&ctx); goto retry_reset; @@ -335,8 +350,8 @@ retry_reset: drm_modeset_drop_locks(&ctx); drm_modeset_acquire_fini(&ctx); - KUNIT_EXPECT_EQ(test, priv->enable_count, 0); - KUNIT_EXPECT_EQ(test, priv->disable_count, 0); + KUNIT_EXPECT_EQ(test, bridge_priv->enable_count, 0); + KUNIT_EXPECT_EQ(test, bridge_priv->disable_count, 0); } /* @@ -348,7 +363,7 @@ static void drm_test_drm_bridge_helper_reset_crtc_legacy(struct kunit *test) struct drm_modeset_acquire_ctx ctx; struct drm_bridge_init_priv *priv; struct drm_display_mode *mode; - struct drm_bridge *bridge; + struct drm_bridge_priv *bridge_priv; int ret; priv = drm_test_bridge_init(test, &drm_test_bridge_legacy_funcs); @@ -374,14 +389,14 @@ retry_commit: drm_modeset_drop_locks(&ctx); drm_modeset_acquire_fini(&ctx); - bridge = &priv->bridge; - KUNIT_ASSERT_EQ(test, priv->enable_count, 1); - KUNIT_ASSERT_EQ(test, priv->disable_count, 0); + bridge_priv = priv->test_bridge; + KUNIT_ASSERT_EQ(test, bridge_priv->enable_count, 1); + KUNIT_ASSERT_EQ(test, bridge_priv->disable_count, 0); drm_modeset_acquire_init(&ctx, 0); retry_reset: - ret = drm_bridge_helper_reset_crtc(bridge, &ctx); + ret = drm_bridge_helper_reset_crtc(&bridge_priv->bridge, &ctx); if (ret == -EDEADLK) { drm_modeset_backoff(&ctx); goto retry_reset; @@ -391,8 +406,8 @@ retry_reset: drm_modeset_drop_locks(&ctx); drm_modeset_acquire_fini(&ctx); - KUNIT_EXPECT_EQ(test, priv->enable_count, 2); - KUNIT_EXPECT_EQ(test, priv->disable_count, 1); + KUNIT_EXPECT_EQ(test, bridge_priv->enable_count, 2); + KUNIT_EXPECT_EQ(test, bridge_priv->disable_count, 1); } static struct kunit_case drm_bridge_helper_reset_crtc_tests[] = { -- cgit v1.2.3 From d3b88721fa24ab0a5a72c2d53989dab784794056 Mon Sep 17 00:00:00 2001 From: Luca Ceresoli Date: Fri, 6 Jun 2025 10:41:21 +0200 Subject: drm/tests: bridge: add KUnit tests for devm_drm_bridge_alloc() Add KUnit tests for the newly introduced devm_drm_bridge_alloc(). Signed-off-by: Luca Ceresoli Link: https://lore.kernel.org/r/20250606-drm-bridge-alloc-doc-test-v9-3-b5bf7b43ed92@bootlin.com Signed-off-by: Maxime Ripard --- drivers/gpu/drm/tests/drm_bridge_test.c | 89 +++++++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) (limited to 'drivers/gpu/drm/tests') diff --git a/drivers/gpu/drm/tests/drm_bridge_test.c b/drivers/gpu/drm/tests/drm_bridge_test.c index af1b9f9694b0..887020141c7f 100644 --- a/drivers/gpu/drm/tests/drm_bridge_test.c +++ b/drivers/gpu/drm/tests/drm_bridge_test.c @@ -8,6 +8,7 @@ #include #include +#include #include /* @@ -21,15 +22,19 @@ struct drm_bridge_priv { unsigned int enable_count; unsigned int disable_count; struct drm_bridge bridge; + void *data; }; struct drm_bridge_init_priv { struct drm_device drm; + /** @dev: device, only for tests not needing a whole drm_device */ + struct device *dev; struct drm_plane *plane; struct drm_crtc *crtc; struct drm_encoder encoder; struct drm_bridge_priv *test_bridge; struct drm_connector *connector; + bool destroyed; }; static struct drm_bridge_priv *bridge_to_priv(struct drm_bridge *bridge) @@ -37,6 +42,14 @@ static struct drm_bridge_priv *bridge_to_priv(struct drm_bridge *bridge) return container_of(bridge, struct drm_bridge_priv, bridge); } +static void drm_test_bridge_priv_destroy(struct drm_bridge *bridge) +{ + struct drm_bridge_priv *bridge_priv = bridge_to_priv(bridge); + struct drm_bridge_init_priv *priv = (struct drm_bridge_init_priv *)bridge_priv->data; + + priv->destroyed = true; +} + static void drm_test_bridge_enable(struct drm_bridge *bridge) { struct drm_bridge_priv *priv = bridge_to_priv(bridge); @@ -52,6 +65,7 @@ static void drm_test_bridge_disable(struct drm_bridge *bridge) } static const struct drm_bridge_funcs drm_test_bridge_legacy_funcs = { + .destroy = drm_test_bridge_priv_destroy, .enable = drm_test_bridge_enable, .disable = drm_test_bridge_disable, }; @@ -73,6 +87,7 @@ static void drm_test_bridge_atomic_disable(struct drm_bridge *bridge, } static const struct drm_bridge_funcs drm_test_bridge_atomic_funcs = { + .destroy = drm_test_bridge_priv_destroy, .atomic_enable = drm_test_bridge_atomic_enable, .atomic_disable = drm_test_bridge_atomic_disable, .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state, @@ -118,6 +133,8 @@ drm_test_bridge_init(struct kunit *test, const struct drm_bridge_funcs *funcs) if (IS_ERR(priv->test_bridge)) return ERR_CAST(priv->test_bridge); + priv->test_bridge->data = priv; + drm = &priv->drm; priv->plane = drm_kunit_helper_create_primary_plane(test, drm, NULL, @@ -422,11 +439,83 @@ static struct kunit_suite drm_bridge_helper_reset_crtc_test_suite = { .test_cases = drm_bridge_helper_reset_crtc_tests, }; +static int drm_test_bridge_alloc_init(struct kunit *test) +{ + struct drm_bridge_init_priv *priv; + + priv = kunit_kzalloc(test, sizeof(*priv), GFP_KERNEL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv); + + priv->dev = kunit_device_register(test, "drm-bridge-dev"); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv->dev); + + test->priv = priv; + + priv->test_bridge = devm_drm_bridge_alloc(priv->dev, struct drm_bridge_priv, bridge, + &drm_test_bridge_atomic_funcs); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv->test_bridge); + + priv->test_bridge->data = priv; + + KUNIT_ASSERT_FALSE(test, priv->destroyed); + + return 0; +} + +/* + * Test that a bridge is freed when the device is destroyed in lack of + * other drm_bridge_get/put() operations. + */ +static void drm_test_drm_bridge_alloc_basic(struct kunit *test) +{ + struct drm_bridge_init_priv *priv = test->priv; + + KUNIT_ASSERT_FALSE(test, priv->destroyed); + + kunit_device_unregister(test, priv->dev); + KUNIT_EXPECT_TRUE(test, priv->destroyed); +} + +/* + * Test that a bridge is not freed when the device is destroyed when there + * is still a reference to it, and freed when that reference is put. + */ +static void drm_test_drm_bridge_alloc_get_put(struct kunit *test) +{ + struct drm_bridge_init_priv *priv = test->priv; + + KUNIT_ASSERT_FALSE(test, priv->destroyed); + + drm_bridge_get(&priv->test_bridge->bridge); + KUNIT_EXPECT_FALSE(test, priv->destroyed); + + kunit_device_unregister(test, priv->dev); + KUNIT_EXPECT_FALSE(test, priv->destroyed); + + drm_bridge_put(&priv->test_bridge->bridge); + KUNIT_EXPECT_TRUE(test, priv->destroyed); +} + +static struct kunit_case drm_bridge_alloc_tests[] = { + KUNIT_CASE(drm_test_drm_bridge_alloc_basic), + KUNIT_CASE(drm_test_drm_bridge_alloc_get_put), + { } +}; + +static struct kunit_suite drm_bridge_alloc_test_suite = { + .name = "drm_bridge_alloc", + .init = drm_test_bridge_alloc_init, + .test_cases = drm_bridge_alloc_tests, +}; + kunit_test_suites( &drm_bridge_get_current_state_test_suite, &drm_bridge_helper_reset_crtc_test_suite, + &drm_bridge_alloc_test_suite, ); MODULE_AUTHOR("Maxime Ripard "); +MODULE_AUTHOR("Luca Ceresoli "); + MODULE_DESCRIPTION("Kunit test for drm_bridge functions"); MODULE_LICENSE("GPL"); -- cgit v1.2.3 From b04e69b2636b19f6ad8803a1873a565c7c419ac6 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Fri, 13 Jun 2025 13:16:46 +0200 Subject: drm/format-helper: Update tests after BT.601 changes Commit a979a54165c2 ("drm/format-helper: Normalize BT.601 factors to 256") improved rounding precision of the BT.601 calculation, which impacts the results of soem of the format-helper tests. Adapt the test to the new results. v2: - fix spelling in commit description Signed-off-by: Thomas Zimmermann Fixes: a979a54165c2 ("drm/format-helper: Normalize BT.601 factors to 256") Cc: Thomas Zimmermann Cc: Javier Martinez Canillas Cc: Maarten Lankhorst Cc: Maxime Ripard Acked-by: Javier Martinez Canillas Link: https://lore.kernel.org/r/20250613111711.136993-1-tzimmermann@suse.de --- drivers/gpu/drm/tests/drm_format_helper_test.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/gpu/drm/tests') diff --git a/drivers/gpu/drm/tests/drm_format_helper_test.c b/drivers/gpu/drm/tests/drm_format_helper_test.c index 35cd3405d045..5aa8543ceb29 100644 --- a/drivers/gpu/drm/tests/drm_format_helper_test.c +++ b/drivers/gpu/drm/tests/drm_format_helper_test.c @@ -279,9 +279,9 @@ static struct convert_xrgb8888_case convert_xrgb8888_cases[] = { .dst_pitch = TEST_USE_DEFAULT_PITCH, .expected = { 0xFF, 0x00, - 0x4C, 0x99, - 0x19, 0x66, - 0xE5, 0xB2, + 0x4C, 0x95, + 0x1C, 0x69, + 0xE2, 0xB2, }, }, .rgb332_result = { @@ -430,9 +430,9 @@ static struct convert_xrgb8888_case convert_xrgb8888_cases[] = { .gray8_result = { .dst_pitch = 5, .expected = { - 0x3C, 0x33, 0xC4, 0x00, 0x00, - 0xBB, 0x3C, 0x33, 0x00, 0x00, - 0x34, 0xBB, 0x3C, 0x00, 0x00, + 0x3D, 0x32, 0xC1, 0x00, 0x00, + 0xBA, 0x3D, 0x32, 0x00, 0x00, + 0x34, 0xBA, 0x3D, 0x00, 0x00, }, }, .rgb332_result = { -- cgit v1.2.3 From 09cba36cc840f39fb1d712193593083edd7a46e1 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Thu, 12 Jun 2025 14:09:56 +0200 Subject: drm: Include MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix the compile-time warnings drivers/gpu/drm/drm_atomic.c: warning: EXPORT_SYMBOL() is used, but #include is missing drivers/gpu/drm/drm_atomic_helper.c: warning: EXPORT_SYMBOL() is used, but #include is missing drivers/gpu/drm/drm_atomic_state_helper.c: warning: EXPORT_SYMBOL() is used, but #include is missing drivers/gpu/drm/drm_atomic_uapi.c: warning: EXPORT_SYMBOL() is used, but #include is missing drivers/gpu/drm/drm_auth.c: warning: EXPORT_SYMBOL() is used, but #include is missing drivers/gpu/drm/drm_buddy.c: warning: EXPORT_SYMBOL() is used, but #include is missing drivers/gpu/drm/drm_color_mgmt.c: warning: EXPORT_SYMBOL() is used, but #include is missing drivers/gpu/drm/drm_connector.c: warning: EXPORT_SYMBOL() is used, but #include is missing drivers/gpu/drm/drm_damage_helper.c: warning: EXPORT_SYMBOL() is used, but #include is missing drivers/gpu/drm/drm_debugfs_crc.c: warning: EXPORT_SYMBOL() is used, but #include is missing drivers/gpu/drm/drm_drv.c: warning: EXPORT_SYMBOL() is used, but #include is missing drivers/gpu/drm/drm_edid.c: warning: EXPORT_SYMBOL() is used, but #include is missing drivers/gpu/drm/drm_exec.c: warning: EXPORT_SYMBOL() is used, but #include is missing drivers/gpu/drm/drm_fb_dma_helper.c: warning: EXPORT_SYMBOL() is used, but #include is missing drivers/gpu/drm/drm_file.c: warning: EXPORT_SYMBOL() is used, but #include is missing drivers/gpu/drm/drm_flip_work.c: warning: EXPORT_SYMBOL() is used, but #include is missing drivers/gpu/drm/drm_format_helper.c: warning: EXPORT_SYMBOL() is used, but #include is missing drivers/gpu/drm/drm_gpusvm.c: warning: EXPORT_SYMBOL() is used, but #include is missing drivers/gpu/drm/drm_gpuvm.c: warning: EXPORT_SYMBOL() is used, but #include is missing drivers/gpu/drm/drm_managed.c: warning: EXPORT_SYMBOL() is used, but #include is missing drivers/gpu/drm/drm_mipi_dbi.c: warning: EXPORT_SYMBOL() is used, but #include is missing drivers/gpu/drm/drm_mipi_dsi.c: warning: EXPORT_SYMBOL() is used, but #include is missing drivers/gpu/drm/drm_mode_config.c: warning: EXPORT_SYMBOL() is used, but #include is missing drivers/gpu/drm/drm_modeset_helper.c: warning: EXPORT_SYMBOL() is used, but #include is missing drivers/gpu/drm/drm_modeset_lock.c: warning: EXPORT_SYMBOL() is used, but #include is missing drivers/gpu/drm/drm_panic.c: warning: EXPORT_SYMBOL() is used, but #include is missing drivers/gpu/drm/drm_plane.c: warning: EXPORT_SYMBOL() is used, but #include is missing drivers/gpu/drm/drm_plane_helper.c: warning: EXPORT_SYMBOL() is used, but #include is missing drivers/gpu/drm/drm_print.c: warning: EXPORT_SYMBOL() is used, but #include is missing drivers/gpu/drm/drm_privacy_screen.c: warning: EXPORT_SYMBOL() is used, but #include is missing drivers/gpu/drm/drm_self_refresh_helper.c: warning: EXPORT_SYMBOL() is used, but #include is missing drivers/gpu/drm/drm_simple_kms_helper.c: warning: EXPORT_SYMBOL() is used, but #include is missing drivers/gpu/drm/drm_suballoc.c: warning: EXPORT_SYMBOL() is used, but #include is missing drivers/gpu/drm/drm_syncobj.c: warning: EXPORT_SYMBOL() is used, but #include is missing drivers/gpu/drm/drm_vblank_work.c: warning: EXPORT_SYMBOL() is used, but #include is missing drivers/gpu/drm/drm_vma_manager.c: warning: EXPORT_SYMBOL() is used, but #include is missing drivers/gpu/drm/drm_writeback.c: warning: EXPORT_SYMBOL() is used, but #include is missing drivers/gpu/drm/lib/drm_random.c: warning: EXPORT_SYMBOL() is used, but #include is missing drivers/gpu/drm/tests/drm_kunit_helpers.c: warning: EXPORT_SYMBOL() is used, but #include is missing Signed-off-by: Thomas Zimmermann Fixes: a934a57a42f6 ("scripts/misc-check: check missing #include when W=1") Reviewed-by: André Almeida Cc: Masahiro Yamada Cc: Nathan Chancellor Link: https://lore.kernel.org/r/20250612121633.229222-3-tzimmermann@suse.de --- drivers/gpu/drm/drm_atomic.c | 2 +- drivers/gpu/drm/drm_atomic_helper.c | 1 + drivers/gpu/drm/drm_atomic_state_helper.c | 1 + drivers/gpu/drm/drm_atomic_uapi.c | 1 + drivers/gpu/drm/drm_auth.c | 1 + drivers/gpu/drm/drm_buddy.c | 1 + drivers/gpu/drm/drm_color_mgmt.c | 1 + drivers/gpu/drm/drm_connector.c | 1 + drivers/gpu/drm/drm_damage_helper.c | 2 ++ drivers/gpu/drm/drm_debugfs_crc.c | 1 + drivers/gpu/drm/drm_drv.c | 1 + drivers/gpu/drm/drm_edid.c | 1 + drivers/gpu/drm/drm_exec.c | 2 ++ drivers/gpu/drm/drm_fb_dma_helper.c | 2 ++ drivers/gpu/drm/drm_file.c | 1 + drivers/gpu/drm/drm_flip_work.c | 1 + drivers/gpu/drm/drm_format_helper.c | 1 + drivers/gpu/drm/drm_gpusvm.c | 1 + drivers/gpu/drm/drm_gpuvm.c | 1 + drivers/gpu/drm/drm_managed.c | 1 + drivers/gpu/drm/drm_mipi_dbi.c | 1 + drivers/gpu/drm/drm_mipi_dsi.c | 1 + drivers/gpu/drm/drm_mode_config.c | 1 + drivers/gpu/drm/drm_modeset_helper.c | 2 ++ drivers/gpu/drm/drm_modeset_lock.c | 2 ++ drivers/gpu/drm/drm_panic.c | 1 + drivers/gpu/drm/drm_plane.c | 1 + drivers/gpu/drm/drm_plane_helper.c | 1 + drivers/gpu/drm/drm_print.c | 1 + drivers/gpu/drm/drm_privacy_screen.c | 1 + drivers/gpu/drm/drm_self_refresh_helper.c | 1 + drivers/gpu/drm/drm_simple_kms_helper.c | 1 + drivers/gpu/drm/drm_suballoc.c | 2 ++ drivers/gpu/drm/drm_syncobj.c | 1 + drivers/gpu/drm/drm_vblank_work.c | 2 ++ drivers/gpu/drm/drm_vma_manager.c | 1 + drivers/gpu/drm/drm_writeback.c | 1 + drivers/gpu/drm/lib/drm_random.c | 1 + drivers/gpu/drm/tests/drm_kunit_helpers.c | 1 + 39 files changed, 46 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm/tests') diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c index 0138cf0b8b63..cd15cf52f0c9 100644 --- a/drivers/gpu/drm/drm_atomic.c +++ b/drivers/gpu/drm/drm_atomic.c @@ -26,7 +26,7 @@ * Daniel Vetter */ - +#include #include #include diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 2fe6c91910a1..ef56b474acf5 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -25,6 +25,7 @@ * Daniel Vetter */ +#include #include #include diff --git a/drivers/gpu/drm/drm_atomic_state_helper.c b/drivers/gpu/drm/drm_atomic_state_helper.c index 519228eb1095..7142e163e618 100644 --- a/drivers/gpu/drm/drm_atomic_state_helper.c +++ b/drivers/gpu/drm/drm_atomic_state_helper.c @@ -37,6 +37,7 @@ #include #include +#include #include #include diff --git a/drivers/gpu/drm/drm_atomic_uapi.c b/drivers/gpu/drm/drm_atomic_uapi.c index c2726af6698e..ecc73d52bfae 100644 --- a/drivers/gpu/drm/drm_atomic_uapi.c +++ b/drivers/gpu/drm/drm_atomic_uapi.c @@ -36,6 +36,7 @@ #include #include +#include #include #include #include diff --git a/drivers/gpu/drm/drm_auth.c b/drivers/gpu/drm/drm_auth.c index d6bf605b4b90..a2556d16bed6 100644 --- a/drivers/gpu/drm/drm_auth.c +++ b/drivers/gpu/drm/drm_auth.c @@ -28,6 +28,7 @@ * OTHER DEALINGS IN THE SOFTWARE. */ +#include #include #include diff --git a/drivers/gpu/drm/drm_buddy.c b/drivers/gpu/drm/drm_buddy.c index 241c855f891f..a1e652b7631d 100644 --- a/drivers/gpu/drm/drm_buddy.c +++ b/drivers/gpu/drm/drm_buddy.c @@ -5,6 +5,7 @@ #include +#include #include #include #include diff --git a/drivers/gpu/drm/drm_color_mgmt.c b/drivers/gpu/drm/drm_color_mgmt.c index 5399c111c51f..37a3270bc3c2 100644 --- a/drivers/gpu/drm/drm_color_mgmt.c +++ b/drivers/gpu/drm/drm_color_mgmt.c @@ -20,6 +20,7 @@ * OF THIS SOFTWARE. */ +#include #include #include diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c index 395e1bf006bd..0167e0e0d425 100644 --- a/drivers/gpu/drm/drm_connector.c +++ b/drivers/gpu/drm/drm_connector.c @@ -33,6 +33,7 @@ #include #include +#include #include #include #include diff --git a/drivers/gpu/drm/drm_damage_helper.c b/drivers/gpu/drm/drm_damage_helper.c index 44a5a36806e3..6a49e7a0ab84 100644 --- a/drivers/gpu/drm/drm_damage_helper.c +++ b/drivers/gpu/drm/drm_damage_helper.c @@ -30,6 +30,8 @@ * **************************************************************************/ +#include + #include #include #include diff --git a/drivers/gpu/drm/drm_debugfs_crc.c b/drivers/gpu/drm/drm_debugfs_crc.c index bbc3bc4ba844..6b43b1cf2327 100644 --- a/drivers/gpu/drm/drm_debugfs_crc.c +++ b/drivers/gpu/drm/drm_debugfs_crc.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c index 56dd61f8e05a..bb291c4ac4d5 100644 --- a/drivers/gpu/drm/drm_drv.c +++ b/drivers/gpu/drm/drm_drv.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 74e77742b2bd..4b4f27896161 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include diff --git a/drivers/gpu/drm/drm_exec.c b/drivers/gpu/drm/drm_exec.c index 18e366cc4993..8d0601400182 100644 --- a/drivers/gpu/drm/drm_exec.c +++ b/drivers/gpu/drm/drm_exec.c @@ -2,7 +2,9 @@ #include #include + #include +#include /** * DOC: Overview diff --git a/drivers/gpu/drm/drm_fb_dma_helper.c b/drivers/gpu/drm/drm_fb_dma_helper.c index 2c4dc7ebc0c3..fd71969d2fb1 100644 --- a/drivers/gpu/drm/drm_fb_dma_helper.c +++ b/drivers/gpu/drm/drm_fb_dma_helper.c @@ -17,7 +17,9 @@ #include #include #include + #include +#include #include /** diff --git a/drivers/gpu/drm/drm_file.c b/drivers/gpu/drm/drm_file.c index 818630ba6e0d..3952e27447ee 100644 --- a/drivers/gpu/drm/drm_file.c +++ b/drivers/gpu/drm/drm_file.c @@ -33,6 +33,7 @@ #include #include +#include #include #include #include diff --git a/drivers/gpu/drm/drm_flip_work.c b/drivers/gpu/drm/drm_flip_work.c index 8c6090a90d56..f5889dd8e7aa 100644 --- a/drivers/gpu/drm/drm_flip_work.c +++ b/drivers/gpu/drm/drm_flip_work.c @@ -21,6 +21,7 @@ * SOFTWARE. */ +#include #include #include diff --git a/drivers/gpu/drm/drm_format_helper.c b/drivers/gpu/drm/drm_format_helper.c index d36e6cacc575..0c04247ef702 100644 --- a/drivers/gpu/drm/drm_format_helper.c +++ b/drivers/gpu/drm/drm_format_helper.c @@ -8,6 +8,7 @@ * (at your option) any later version. */ +#include #include #include #include diff --git a/drivers/gpu/drm/drm_gpusvm.c b/drivers/gpu/drm/drm_gpusvm.c index 735bfdf4322f..3b0c3886a2d0 100644 --- a/drivers/gpu/drm/drm_gpusvm.c +++ b/drivers/gpu/drm/drm_gpusvm.c @@ -7,6 +7,7 @@ */ #include +#include #include #include #include diff --git a/drivers/gpu/drm/drm_gpuvm.c b/drivers/gpu/drm/drm_gpuvm.c index f9eb56f24bef..e89b932e987c 100644 --- a/drivers/gpu/drm/drm_gpuvm.c +++ b/drivers/gpu/drm/drm_gpuvm.c @@ -27,6 +27,7 @@ #include +#include #include #include diff --git a/drivers/gpu/drm/drm_managed.c b/drivers/gpu/drm/drm_managed.c index cc4c463daae7..247f468731de 100644 --- a/drivers/gpu/drm/drm_managed.c +++ b/drivers/gpu/drm/drm_managed.c @@ -7,6 +7,7 @@ #include +#include #include #include #include diff --git a/drivers/gpu/drm/drm_mipi_dbi.c b/drivers/gpu/drm/drm_mipi_dbi.c index a4cd476f9b30..ba4be6be5d28 100644 --- a/drivers/gpu/drm/drm_mipi_dbi.c +++ b/drivers/gpu/drm/drm_mipi_dbi.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include diff --git a/drivers/gpu/drm/drm_mipi_dsi.c b/drivers/gpu/drm/drm_mipi_dsi.c index e5184a0c2465..a00d76443128 100644 --- a/drivers/gpu/drm/drm_mipi_dsi.c +++ b/drivers/gpu/drm/drm_mipi_dsi.c @@ -26,6 +26,7 @@ */ #include +#include #include #include #include diff --git a/drivers/gpu/drm/drm_mode_config.c b/drivers/gpu/drm/drm_mode_config.c index b4239fd04e9d..25f376869b3a 100644 --- a/drivers/gpu/drm/drm_mode_config.c +++ b/drivers/gpu/drm/drm_mode_config.c @@ -20,6 +20,7 @@ * OF THIS SOFTWARE. */ +#include #include #include diff --git a/drivers/gpu/drm/drm_modeset_helper.c b/drivers/gpu/drm/drm_modeset_helper.c index 5565464c1734..ef32f6af10d4 100644 --- a/drivers/gpu/drm/drm_modeset_helper.c +++ b/drivers/gpu/drm/drm_modeset_helper.c @@ -20,6 +20,8 @@ * OF THIS SOFTWARE. */ +#include + #include #include #include diff --git a/drivers/gpu/drm/drm_modeset_lock.c b/drivers/gpu/drm/drm_modeset_lock.c index 7694b85e75e3..beb91a13a312 100644 --- a/drivers/gpu/drm/drm_modeset_lock.c +++ b/drivers/gpu/drm/drm_modeset_lock.c @@ -21,6 +21,8 @@ * OTHER DEALINGS IN THE SOFTWARE. */ +#include + #include #include #include diff --git a/drivers/gpu/drm/drm_panic.c b/drivers/gpu/drm/drm_panic.c index b4de79583805..1d6312fa1429 100644 --- a/drivers/gpu/drm/drm_panic.c +++ b/drivers/gpu/drm/drm_panic.c @@ -6,6 +6,7 @@ * Tux Ascii art taken from cowsay written by Tony Monroe */ +#include #include #include #include diff --git a/drivers/gpu/drm/drm_plane.c b/drivers/gpu/drm/drm_plane.c index 04992dfd4c79..38f82391bfda 100644 --- a/drivers/gpu/drm/drm_plane.c +++ b/drivers/gpu/drm/drm_plane.c @@ -20,6 +20,7 @@ * OF THIS SOFTWARE. */ +#include #include #include diff --git a/drivers/gpu/drm/drm_plane_helper.c b/drivers/gpu/drm/drm_plane_helper.c index 7982be4b0306..747d248aaf02 100644 --- a/drivers/gpu/drm/drm_plane_helper.c +++ b/drivers/gpu/drm/drm_plane_helper.c @@ -23,6 +23,7 @@ * SOFTWARE. */ +#include #include #include diff --git a/drivers/gpu/drm/drm_print.c b/drivers/gpu/drm/drm_print.c index 79517bd4418f..ded9461df5f2 100644 --- a/drivers/gpu/drm/drm_print.c +++ b/drivers/gpu/drm/drm_print.c @@ -25,6 +25,7 @@ #include #include +#include #include #include #include diff --git a/drivers/gpu/drm/drm_privacy_screen.c b/drivers/gpu/drm/drm_privacy_screen.c index 6cc39e30781f..8959f7084e0b 100644 --- a/drivers/gpu/drm/drm_privacy_screen.c +++ b/drivers/gpu/drm/drm_privacy_screen.c @@ -7,6 +7,7 @@ */ #include +#include #include #include #include diff --git a/drivers/gpu/drm/drm_self_refresh_helper.c b/drivers/gpu/drm/drm_self_refresh_helper.c index dd33fec5aabd..c0948586b7fd 100644 --- a/drivers/gpu/drm/drm_self_refresh_helper.c +++ b/drivers/gpu/drm/drm_self_refresh_helper.c @@ -7,6 +7,7 @@ */ #include #include +#include #include #include diff --git a/drivers/gpu/drm/drm_simple_kms_helper.c b/drivers/gpu/drm/drm_simple_kms_helper.c index 250819fbc5ce..fcbcaaa36b5f 100644 --- a/drivers/gpu/drm/drm_simple_kms_helper.c +++ b/drivers/gpu/drm/drm_simple_kms_helper.c @@ -3,6 +3,7 @@ * Copyright (C) 2016 Noralf Trønnes */ +#include #include #include diff --git a/drivers/gpu/drm/drm_suballoc.c b/drivers/gpu/drm/drm_suballoc.c index 38cc7a123819..879ea33dbbc4 100644 --- a/drivers/gpu/drm/drm_suballoc.c +++ b/drivers/gpu/drm/drm_suballoc.c @@ -42,6 +42,8 @@ #include #include + +#include #include #include #include diff --git a/drivers/gpu/drm/drm_syncobj.c b/drivers/gpu/drm/drm_syncobj.c index 636cd83ca29e..e1b0fa4000cd 100644 --- a/drivers/gpu/drm/drm_syncobj.c +++ b/drivers/gpu/drm/drm_syncobj.c @@ -195,6 +195,7 @@ #include #include #include +#include #include #include #include diff --git a/drivers/gpu/drm/drm_vblank_work.c b/drivers/gpu/drm/drm_vblank_work.c index 9cc71120246f..e4e1873f0e1e 100644 --- a/drivers/gpu/drm/drm_vblank_work.c +++ b/drivers/gpu/drm/drm_vblank_work.c @@ -2,6 +2,8 @@ #include +#include + #include #include #include diff --git a/drivers/gpu/drm/drm_vma_manager.c b/drivers/gpu/drm/drm_vma_manager.c index 83229a031af0..58659c16874c 100644 --- a/drivers/gpu/drm/drm_vma_manager.c +++ b/drivers/gpu/drm/drm_vma_manager.c @@ -23,6 +23,7 @@ * OTHER DEALINGS IN THE SOFTWARE. */ +#include #include #include #include diff --git a/drivers/gpu/drm/drm_writeback.c b/drivers/gpu/drm/drm_writeback.c index edbeab88ff2b..ace8c98c3e04 100644 --- a/drivers/gpu/drm/drm_writeback.c +++ b/drivers/gpu/drm/drm_writeback.c @@ -10,6 +10,7 @@ */ #include +#include #include #include diff --git a/drivers/gpu/drm/lib/drm_random.c b/drivers/gpu/drm/lib/drm_random.c index 31b5a3e21911..0e9dba1ef4af 100644 --- a/drivers/gpu/drm/lib/drm_random.c +++ b/drivers/gpu/drm/lib/drm_random.c @@ -1,5 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 #include +#include #include #include #include diff --git a/drivers/gpu/drm/tests/drm_kunit_helpers.c b/drivers/gpu/drm/tests/drm_kunit_helpers.c index 5f7257840d8e..04edb6079c0d 100644 --- a/drivers/gpu/drm/tests/drm_kunit_helpers.c +++ b/drivers/gpu/drm/tests/drm_kunit_helpers.c @@ -13,6 +13,7 @@ #include #include +#include #include #define KUNIT_DEVICE_NAME "drm-kunit-mock-device" -- cgit v1.2.3 From 5a4856e0e38109ba994f369962f054ecb445c098 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Mon, 16 Jun 2025 10:37:04 +0200 Subject: drm/tests: Do not use drm_fb_blit() in format-helper tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Export additional helpers from the format-helper library and open-code drm_fb_blit() in tests. Prepares for the removal of drm_fb_blit(). Only sysfb drivers use drm_fb_blit(). The function will soon be removed from format helpers and be refactored within sysfb helpers. Signed-off-by: Thomas Zimmermann Reviewed-by: José Expósito Acked-by: Maxime Ripard Link: https://lore.kernel.org/r/20250616083846.221396-2-tzimmermann@suse.de --- drivers/gpu/drm/drm_format_helper.c | 108 ++++++++++++++++++++++--- drivers/gpu/drm/drm_format_internal.h | 8 ++ drivers/gpu/drm/tests/drm_format_helper_test.c | 108 ++++--------------------- include/drm/drm_format_helper.h | 9 +++ 4 files changed, 131 insertions(+), 102 deletions(-) (limited to 'drivers/gpu/drm/tests') diff --git a/drivers/gpu/drm/drm_format_helper.c b/drivers/gpu/drm/drm_format_helper.c index 0c04247ef702..63dc46f9fc49 100644 --- a/drivers/gpu/drm/drm_format_helper.c +++ b/drivers/gpu/drm/drm_format_helper.c @@ -858,11 +858,33 @@ static void drm_fb_xrgb8888_to_abgr8888_line(void *dbuf, const void *sbuf, unsig drm_fb_xfrm_line_32to32(dbuf, sbuf, pixels, drm_pixel_xrgb8888_to_abgr8888); } -static void drm_fb_xrgb8888_to_abgr8888(struct iosys_map *dst, const unsigned int *dst_pitch, - const struct iosys_map *src, - const struct drm_framebuffer *fb, - const struct drm_rect *clip, - struct drm_format_conv_state *state) +/** + * drm_fb_xrgb8888_to_abgr8888 - Convert XRGB8888 to ABGR8888 clip buffer + * @dst: Array of ABGR8888 destination buffers + * @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines + * within @dst; can be NULL if scanlines are stored next to each other. + * @src: Array of XRGB8888 source buffer + * @fb: DRM framebuffer + * @clip: Clip rectangle area to copy + * @state: Transform and conversion state + * + * This function copies parts of a framebuffer to display memory and converts the + * color format during the process. The parameters @dst, @dst_pitch and @src refer + * to arrays. Each array must have at least as many entries as there are planes in + * @fb's format. Each entry stores the value for the format's respective color plane + * at the same index. + * + * This function does not apply clipping on @dst (i.e. the destination is at the + * top-left corner). + * + * Drivers can use this function for ABGR8888 devices that don't support XRGB8888 + * natively. It sets an opaque alpha channel as part of the conversion. + */ +void drm_fb_xrgb8888_to_abgr8888(struct iosys_map *dst, const unsigned int *dst_pitch, + const struct iosys_map *src, + const struct drm_framebuffer *fb, + const struct drm_rect *clip, + struct drm_format_conv_state *state) { static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = { 4, @@ -871,17 +893,40 @@ static void drm_fb_xrgb8888_to_abgr8888(struct iosys_map *dst, const unsigned in drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false, state, drm_fb_xrgb8888_to_abgr8888_line); } +EXPORT_SYMBOL(drm_fb_xrgb8888_to_abgr8888); static void drm_fb_xrgb8888_to_xbgr8888_line(void *dbuf, const void *sbuf, unsigned int pixels) { drm_fb_xfrm_line_32to32(dbuf, sbuf, pixels, drm_pixel_xrgb8888_to_xbgr8888); } -static void drm_fb_xrgb8888_to_xbgr8888(struct iosys_map *dst, const unsigned int *dst_pitch, - const struct iosys_map *src, - const struct drm_framebuffer *fb, - const struct drm_rect *clip, - struct drm_format_conv_state *state) +/** + * drm_fb_xrgb8888_to_xbgr8888 - Convert XRGB8888 to XBGR8888 clip buffer + * @dst: Array of XBGR8888 destination buffers + * @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines + * within @dst; can be NULL if scanlines are stored next to each other. + * @src: Array of XRGB8888 source buffer + * @fb: DRM framebuffer + * @clip: Clip rectangle area to copy + * @state: Transform and conversion state + * + * This function copies parts of a framebuffer to display memory and converts the + * color format during the process. The parameters @dst, @dst_pitch and @src refer + * to arrays. Each array must have at least as many entries as there are planes in + * @fb's format. Each entry stores the value for the format's respective color plane + * at the same index. + * + * This function does not apply clipping on @dst (i.e. the destination is at the + * top-left corner). + * + * Drivers can use this function for XBGR8888 devices that don't support XRGB8888 + * natively. + */ +void drm_fb_xrgb8888_to_xbgr8888(struct iosys_map *dst, const unsigned int *dst_pitch, + const struct iosys_map *src, + const struct drm_framebuffer *fb, + const struct drm_rect *clip, + struct drm_format_conv_state *state) { static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = { 4, @@ -890,6 +935,49 @@ static void drm_fb_xrgb8888_to_xbgr8888(struct iosys_map *dst, const unsigned in drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false, state, drm_fb_xrgb8888_to_xbgr8888_line); } +EXPORT_SYMBOL(drm_fb_xrgb8888_to_xbgr8888); + +static void drm_fb_xrgb8888_to_bgrx8888_line(void *dbuf, const void *sbuf, unsigned int pixels) +{ + drm_fb_xfrm_line_32to32(dbuf, sbuf, pixels, drm_pixel_xrgb8888_to_bgrx8888); +} + +/** + * drm_fb_xrgb8888_to_bgrx8888 - Convert XRGB8888 to BGRX8888 clip buffer + * @dst: Array of BGRX8888 destination buffers + * @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines + * within @dst; can be NULL if scanlines are stored next to each other. + * @src: Array of XRGB8888 source buffer + * @fb: DRM framebuffer + * @clip: Clip rectangle area to copy + * @state: Transform and conversion state + * + * This function copies parts of a framebuffer to display memory and converts the + * color format during the process. The parameters @dst, @dst_pitch and @src refer + * to arrays. Each array must have at least as many entries as there are planes in + * @fb's format. Each entry stores the value for the format's respective color plane + * at the same index. + * + * This function does not apply clipping on @dst (i.e. the destination is at the + * top-left corner). + * + * Drivers can use this function for BGRX8888 devices that don't support XRGB8888 + * natively. + */ +void drm_fb_xrgb8888_to_bgrx8888(struct iosys_map *dst, const unsigned int *dst_pitch, + const struct iosys_map *src, + const struct drm_framebuffer *fb, + const struct drm_rect *clip, + struct drm_format_conv_state *state) +{ + static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = { + 4, + }; + + drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false, state, + drm_fb_xrgb8888_to_bgrx8888_line); +} +EXPORT_SYMBOL(drm_fb_xrgb8888_to_bgrx8888); static void drm_fb_xrgb8888_to_xrgb2101010_line(void *dbuf, const void *sbuf, unsigned int pixels) { diff --git a/drivers/gpu/drm/drm_format_internal.h b/drivers/gpu/drm/drm_format_internal.h index 3020ff267513..9428d5cfebc5 100644 --- a/drivers/gpu/drm/drm_format_internal.h +++ b/drivers/gpu/drm/drm_format_internal.h @@ -111,6 +111,14 @@ static inline u32 drm_pixel_xrgb8888_to_xbgr8888(u32 pix) ((pix & 0x000000ff) << 16); } +static inline u32 drm_pixel_xrgb8888_to_bgrx8888(u32 pix) +{ + return ((pix & 0xff000000) >> 24) | /* also copy filler bits */ + ((pix & 0x00ff0000) >> 8) | + ((pix & 0x0000ff00) << 8) | + ((pix & 0x000000ff) << 24); +} + static inline u32 drm_pixel_xrgb8888_to_abgr8888(u32 pix) { return GENMASK(31, 24) | /* fill alpha bits */ diff --git a/drivers/gpu/drm/tests/drm_format_helper_test.c b/drivers/gpu/drm/tests/drm_format_helper_test.c index 5aa8543ceb29..7fd4eac3c55e 100644 --- a/drivers/gpu/drm/tests/drm_format_helper_test.c +++ b/drivers/gpu/drm/tests/drm_format_helper_test.c @@ -748,14 +748,9 @@ static void drm_test_fb_xrgb8888_to_rgb565(struct kunit *test) buf = dst.vaddr; memset(buf, 0, dst_size); - int blit_result = 0; - - blit_result = drm_fb_blit(&dst, dst_pitch, DRM_FORMAT_RGB565, &src, &fb, ¶ms->clip, - &fmtcnv_state); - + drm_fb_xrgb8888_to_rgb565(&dst, dst_pitch, &src, &fb, ¶ms->clip, + &fmtcnv_state, false); buf = le16buf_to_cpu(test, (__force const __le16 *)buf, dst_size / sizeof(__le16)); - - KUNIT_EXPECT_FALSE(test, blit_result); KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size); } @@ -795,14 +790,8 @@ static void drm_test_fb_xrgb8888_to_xrgb1555(struct kunit *test) buf = dst.vaddr; /* restore original value of buf */ memset(buf, 0, dst_size); - int blit_result = 0; - - blit_result = drm_fb_blit(&dst, dst_pitch, DRM_FORMAT_XRGB1555, &src, &fb, ¶ms->clip, - &fmtcnv_state); - + drm_fb_xrgb8888_to_xrgb1555(&dst, dst_pitch, &src, &fb, ¶ms->clip, &fmtcnv_state); buf = le16buf_to_cpu(test, (__force const __le16 *)buf, dst_size / sizeof(__le16)); - - KUNIT_EXPECT_FALSE(test, blit_result); KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size); } @@ -842,14 +831,8 @@ static void drm_test_fb_xrgb8888_to_argb1555(struct kunit *test) buf = dst.vaddr; /* restore original value of buf */ memset(buf, 0, dst_size); - int blit_result = 0; - - blit_result = drm_fb_blit(&dst, dst_pitch, DRM_FORMAT_ARGB1555, &src, &fb, ¶ms->clip, - &fmtcnv_state); - + drm_fb_xrgb8888_to_argb1555(&dst, dst_pitch, &src, &fb, ¶ms->clip, &fmtcnv_state); buf = le16buf_to_cpu(test, (__force const __le16 *)buf, dst_size / sizeof(__le16)); - - KUNIT_EXPECT_FALSE(test, blit_result); KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size); } @@ -889,14 +872,8 @@ static void drm_test_fb_xrgb8888_to_rgba5551(struct kunit *test) buf = dst.vaddr; /* restore original value of buf */ memset(buf, 0, dst_size); - int blit_result = 0; - - blit_result = drm_fb_blit(&dst, dst_pitch, DRM_FORMAT_RGBA5551, &src, &fb, ¶ms->clip, - &fmtcnv_state); - + drm_fb_xrgb8888_to_rgba5551(&dst, dst_pitch, &src, &fb, ¶ms->clip, &fmtcnv_state); buf = le16buf_to_cpu(test, (__force const __le16 *)buf, dst_size / sizeof(__le16)); - - KUNIT_EXPECT_FALSE(test, blit_result); KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size); } @@ -939,12 +916,7 @@ static void drm_test_fb_xrgb8888_to_rgb888(struct kunit *test) buf = dst.vaddr; /* restore original value of buf */ memset(buf, 0, dst_size); - int blit_result = 0; - - blit_result = drm_fb_blit(&dst, dst_pitch, DRM_FORMAT_RGB888, &src, &fb, ¶ms->clip, - &fmtcnv_state); - - KUNIT_EXPECT_FALSE(test, blit_result); + drm_fb_xrgb8888_to_rgb888(&dst, dst_pitch, &src, &fb, ¶ms->clip, &fmtcnv_state); KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size); } @@ -985,12 +957,8 @@ static void drm_test_fb_xrgb8888_to_bgr888(struct kunit *test) buf = dst.vaddr; /* restore original value of buf */ memset(buf, 0, dst_size); - int blit_result = 0; - - blit_result = drm_fb_blit(&dst, &result->dst_pitch, DRM_FORMAT_BGR888, &src, &fb, ¶ms->clip, + drm_fb_xrgb8888_to_bgr888(&dst, &result->dst_pitch, &src, &fb, ¶ms->clip, &fmtcnv_state); - - KUNIT_EXPECT_FALSE(test, blit_result); KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size); } @@ -1030,14 +998,8 @@ static void drm_test_fb_xrgb8888_to_argb8888(struct kunit *test) buf = dst.vaddr; /* restore original value of buf */ memset(buf, 0, dst_size); - int blit_result = 0; - - blit_result = drm_fb_blit(&dst, dst_pitch, DRM_FORMAT_ARGB8888, &src, &fb, ¶ms->clip, - &fmtcnv_state); - + drm_fb_xrgb8888_to_argb8888(&dst, dst_pitch, &src, &fb, ¶ms->clip, &fmtcnv_state); buf = le32buf_to_cpu(test, (__force const __le32 *)buf, dst_size / sizeof(u32)); - - KUNIT_EXPECT_FALSE(test, blit_result); KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size); } @@ -1077,12 +1039,7 @@ static void drm_test_fb_xrgb8888_to_xrgb2101010(struct kunit *test) buf = dst.vaddr; /* restore original value of buf */ memset(buf, 0, dst_size); - int blit_result = 0; - - blit_result = drm_fb_blit(&dst, dst_pitch, DRM_FORMAT_XRGB2101010, &src, &fb, - ¶ms->clip, &fmtcnv_state); - - KUNIT_EXPECT_FALSE(test, blit_result); + drm_fb_xrgb8888_to_xrgb2101010(&dst, dst_pitch, &src, &fb, ¶ms->clip, &fmtcnv_state); KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size); } @@ -1122,14 +1079,8 @@ static void drm_test_fb_xrgb8888_to_argb2101010(struct kunit *test) buf = dst.vaddr; /* restore original value of buf */ memset(buf, 0, dst_size); - int blit_result = 0; - - blit_result = drm_fb_blit(&dst, dst_pitch, DRM_FORMAT_ARGB2101010, &src, &fb, - ¶ms->clip, &fmtcnv_state); - + drm_fb_xrgb8888_to_argb2101010(&dst, dst_pitch, &src, &fb, ¶ms->clip, &fmtcnv_state); buf = le32buf_to_cpu(test, (__force const __le32 *)buf, dst_size / sizeof(u32)); - - KUNIT_EXPECT_FALSE(test, blit_result); KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size); } @@ -1202,23 +1153,15 @@ static void drm_test_fb_swab(struct kunit *test) buf = dst.vaddr; /* restore original value of buf */ memset(buf, 0, dst_size); - int blit_result; - - blit_result = drm_fb_blit(&dst, dst_pitch, DRM_FORMAT_XRGB8888 | DRM_FORMAT_BIG_ENDIAN, - &src, &fb, ¶ms->clip, &fmtcnv_state); + drm_fb_swab(&dst, dst_pitch, &src, &fb, ¶ms->clip, false, &fmtcnv_state); buf = le32buf_to_cpu(test, (__force const __le32 *)buf, dst_size / sizeof(u32)); - - KUNIT_EXPECT_FALSE(test, blit_result); KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size); buf = dst.vaddr; memset(buf, 0, dst_size); - blit_result = drm_fb_blit(&dst, dst_pitch, DRM_FORMAT_BGRX8888, &src, &fb, ¶ms->clip, - &fmtcnv_state); + drm_fb_xrgb8888_to_bgrx8888(&dst, dst_pitch, &src, &fb, ¶ms->clip, &fmtcnv_state); buf = le32buf_to_cpu(test, (__force const __le32 *)buf, dst_size / sizeof(u32)); - - KUNIT_EXPECT_FALSE(test, blit_result); KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size); buf = dst.vaddr; @@ -1229,11 +1172,8 @@ static void drm_test_fb_swab(struct kunit *test) mock_format.format |= DRM_FORMAT_BIG_ENDIAN; fb.format = &mock_format; - blit_result = drm_fb_blit(&dst, dst_pitch, DRM_FORMAT_XRGB8888, &src, &fb, ¶ms->clip, - &fmtcnv_state); + drm_fb_swab(&dst, dst_pitch, &src, &fb, ¶ms->clip, false, &fmtcnv_state); buf = le32buf_to_cpu(test, (__force const __le32 *)buf, dst_size / sizeof(u32)); - - KUNIT_EXPECT_FALSE(test, blit_result); KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size); } @@ -1266,14 +1206,8 @@ static void drm_test_fb_xrgb8888_to_abgr8888(struct kunit *test) const unsigned int *dst_pitch = (result->dst_pitch == TEST_USE_DEFAULT_PITCH) ? NULL : &result->dst_pitch; - int blit_result = 0; - - blit_result = drm_fb_blit(&dst, dst_pitch, DRM_FORMAT_ABGR8888, &src, &fb, ¶ms->clip, - &fmtcnv_state); - + drm_fb_xrgb8888_to_abgr8888(&dst, dst_pitch, &src, &fb, ¶ms->clip, &fmtcnv_state); buf = le32buf_to_cpu(test, (__force const __le32 *)buf, dst_size / sizeof(u32)); - - KUNIT_EXPECT_FALSE(test, blit_result); KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size); } @@ -1306,14 +1240,8 @@ static void drm_test_fb_xrgb8888_to_xbgr8888(struct kunit *test) const unsigned int *dst_pitch = (result->dst_pitch == TEST_USE_DEFAULT_PITCH) ? NULL : &result->dst_pitch; - int blit_result = 0; - - blit_result = drm_fb_blit(&dst, dst_pitch, DRM_FORMAT_XBGR8888, &src, &fb, ¶ms->clip, - &fmtcnv_state); - + drm_fb_xrgb8888_to_xbgr8888(&dst, dst_pitch, &src, &fb, ¶ms->clip, &fmtcnv_state); buf = le32buf_to_cpu(test, (__force const __le32 *)buf, dst_size / sizeof(u32)); - - KUNIT_EXPECT_FALSE(test, blit_result); KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size); } @@ -1910,12 +1838,8 @@ static void drm_test_fb_memcpy(struct kunit *test) memset(buf[i], 0, dst_size[i]); } - int blit_result; - - blit_result = drm_fb_blit(dst, dst_pitches, params->format, src, &fb, ¶ms->clip, - &fmtcnv_state); + drm_fb_memcpy(dst, dst_pitches, src, &fb, ¶ms->clip); - KUNIT_EXPECT_FALSE(test, blit_result); for (size_t i = 0; i < fb.format->num_planes; i++) { expected[i] = cpubuf_to_le32(test, params->expected[i], TEST_BUF_SIZE); KUNIT_EXPECT_MEMEQ_MSG(test, buf[i], expected[i], dst_size[i], diff --git a/include/drm/drm_format_helper.h b/include/drm/drm_format_helper.h index d8539174ca11..49a2e09155d1 100644 --- a/include/drm/drm_format_helper.h +++ b/include/drm/drm_format_helper.h @@ -102,6 +102,15 @@ void drm_fb_xrgb8888_to_bgr888(struct iosys_map *dst, const unsigned int *dst_pi void drm_fb_xrgb8888_to_argb8888(struct iosys_map *dst, const unsigned int *dst_pitch, const struct iosys_map *src, const struct drm_framebuffer *fb, const struct drm_rect *clip, struct drm_format_conv_state *state); +void drm_fb_xrgb8888_to_abgr8888(struct iosys_map *dst, const unsigned int *dst_pitch, + const struct iosys_map *src, const struct drm_framebuffer *fb, + const struct drm_rect *clip, struct drm_format_conv_state *state); +void drm_fb_xrgb8888_to_xbgr8888(struct iosys_map *dst, const unsigned int *dst_pitch, + const struct iosys_map *src, const struct drm_framebuffer *fb, + const struct drm_rect *clip, struct drm_format_conv_state *state); +void drm_fb_xrgb8888_to_bgrx8888(struct iosys_map *dst, const unsigned int *dst_pitch, + const struct iosys_map *src, const struct drm_framebuffer *fb, + const struct drm_rect *clip, struct drm_format_conv_state *state); void drm_fb_xrgb8888_to_xrgb2101010(struct iosys_map *dst, const unsigned int *dst_pitch, const struct iosys_map *src, const struct drm_framebuffer *fb, const struct drm_rect *clip, -- cgit v1.2.3 From 4f522a44d9e4f630cca73b88fe59d5f7975c8379 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Mon, 16 Jun 2025 10:37:05 +0200 Subject: drm/tests: Test drm_fb_build_fourcc_list() in separate test suite MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Only sysfb drivers use drm_fb_build_fourcc_list(). The helper will be moved from format helpers to sysfb helpers. Moving the related tests to their own test suite. v3: - rename tests according to filename (José) v2: - rename filename to match tested code (Maxime) Signed-off-by: Thomas Zimmermann Reviewed-by: José Expósito Acked-by: Maxime Ripard Link: https://lore.kernel.org/r/20250616083846.221396-3-tzimmermann@suse.de --- drivers/gpu/drm/tests/Makefile | 3 +- drivers/gpu/drm/tests/drm_format_helper_test.c | 142 --------------------- drivers/gpu/drm/tests/drm_sysfb_modeset_test.c | 166 +++++++++++++++++++++++++ 3 files changed, 168 insertions(+), 143 deletions(-) create mode 100644 drivers/gpu/drm/tests/drm_sysfb_modeset_test.c (limited to 'drivers/gpu/drm/tests') diff --git a/drivers/gpu/drm/tests/Makefile b/drivers/gpu/drm/tests/Makefile index 3afd6587df08..c0e952293ad0 100644 --- a/drivers/gpu/drm/tests/Makefile +++ b/drivers/gpu/drm/tests/Makefile @@ -23,6 +23,7 @@ obj-$(CONFIG_DRM_KUNIT_TEST) += \ drm_modes_test.o \ drm_plane_helper_test.o \ drm_probe_helper_test.o \ - drm_rect_test.o + drm_rect_test.o \ + drm_sysfb_modeset_test.o CFLAGS_drm_mm_test.o := $(DISABLE_STRUCTLEAK_PLUGIN) diff --git a/drivers/gpu/drm/tests/drm_format_helper_test.c b/drivers/gpu/drm/tests/drm_format_helper_test.c index 7fd4eac3c55e..ad06762db671 100644 --- a/drivers/gpu/drm/tests/drm_format_helper_test.c +++ b/drivers/gpu/drm/tests/drm_format_helper_test.c @@ -1335,147 +1335,6 @@ static void drm_test_fb_clip_offset(struct kunit *test) KUNIT_EXPECT_EQ(test, offset, params->expected_offset); } -struct fb_build_fourcc_list_case { - const char *name; - u32 native_fourccs[TEST_BUF_SIZE]; - size_t native_fourccs_size; - u32 expected[TEST_BUF_SIZE]; - size_t expected_fourccs_size; -}; - -static struct fb_build_fourcc_list_case fb_build_fourcc_list_cases[] = { - { - .name = "no native formats", - .native_fourccs = { }, - .native_fourccs_size = 0, - .expected = { DRM_FORMAT_XRGB8888 }, - .expected_fourccs_size = 1, - }, - { - .name = "XRGB8888 as native format", - .native_fourccs = { DRM_FORMAT_XRGB8888 }, - .native_fourccs_size = 1, - .expected = { DRM_FORMAT_XRGB8888 }, - .expected_fourccs_size = 1, - }, - { - .name = "remove duplicates", - .native_fourccs = { - DRM_FORMAT_XRGB8888, - DRM_FORMAT_XRGB8888, - DRM_FORMAT_RGB888, - DRM_FORMAT_RGB888, - DRM_FORMAT_RGB888, - DRM_FORMAT_XRGB8888, - DRM_FORMAT_RGB888, - DRM_FORMAT_RGB565, - DRM_FORMAT_RGB888, - DRM_FORMAT_XRGB8888, - DRM_FORMAT_RGB565, - DRM_FORMAT_RGB565, - DRM_FORMAT_XRGB8888, - }, - .native_fourccs_size = 11, - .expected = { - DRM_FORMAT_XRGB8888, - DRM_FORMAT_RGB888, - DRM_FORMAT_RGB565, - }, - .expected_fourccs_size = 3, - }, - { - .name = "convert alpha formats", - .native_fourccs = { - DRM_FORMAT_ARGB1555, - DRM_FORMAT_ABGR1555, - DRM_FORMAT_RGBA5551, - DRM_FORMAT_BGRA5551, - DRM_FORMAT_ARGB8888, - DRM_FORMAT_ABGR8888, - DRM_FORMAT_RGBA8888, - DRM_FORMAT_BGRA8888, - DRM_FORMAT_ARGB2101010, - DRM_FORMAT_ABGR2101010, - DRM_FORMAT_RGBA1010102, - DRM_FORMAT_BGRA1010102, - }, - .native_fourccs_size = 12, - .expected = { - DRM_FORMAT_XRGB1555, - DRM_FORMAT_XBGR1555, - DRM_FORMAT_RGBX5551, - DRM_FORMAT_BGRX5551, - DRM_FORMAT_XRGB8888, - DRM_FORMAT_XBGR8888, - DRM_FORMAT_RGBX8888, - DRM_FORMAT_BGRX8888, - DRM_FORMAT_XRGB2101010, - DRM_FORMAT_XBGR2101010, - DRM_FORMAT_RGBX1010102, - DRM_FORMAT_BGRX1010102, - }, - .expected_fourccs_size = 12, - }, - { - .name = "random formats", - .native_fourccs = { - DRM_FORMAT_Y212, - DRM_FORMAT_ARGB1555, - DRM_FORMAT_ABGR16161616F, - DRM_FORMAT_C8, - DRM_FORMAT_BGR888, - DRM_FORMAT_XRGB1555, - DRM_FORMAT_RGBA5551, - DRM_FORMAT_BGR565_A8, - DRM_FORMAT_R10, - DRM_FORMAT_XYUV8888, - }, - .native_fourccs_size = 10, - .expected = { - DRM_FORMAT_Y212, - DRM_FORMAT_XRGB1555, - DRM_FORMAT_ABGR16161616F, - DRM_FORMAT_C8, - DRM_FORMAT_BGR888, - DRM_FORMAT_RGBX5551, - DRM_FORMAT_BGR565_A8, - DRM_FORMAT_R10, - DRM_FORMAT_XYUV8888, - DRM_FORMAT_XRGB8888, - }, - .expected_fourccs_size = 10, - }, -}; - -static void fb_build_fourcc_list_case_desc(struct fb_build_fourcc_list_case *t, char *desc) -{ - strscpy(desc, t->name, KUNIT_PARAM_DESC_SIZE); -} - -KUNIT_ARRAY_PARAM(fb_build_fourcc_list, fb_build_fourcc_list_cases, fb_build_fourcc_list_case_desc); - -static void drm_test_fb_build_fourcc_list(struct kunit *test) -{ - const struct fb_build_fourcc_list_case *params = test->param_value; - u32 fourccs_out[TEST_BUF_SIZE] = {0}; - size_t nfourccs_out; - struct drm_device *drm; - struct device *dev; - - 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); - - nfourccs_out = drm_fb_build_fourcc_list(drm, params->native_fourccs, - params->native_fourccs_size, - fourccs_out, TEST_BUF_SIZE); - - KUNIT_EXPECT_EQ(test, nfourccs_out, params->expected_fourccs_size); - KUNIT_EXPECT_MEMEQ(test, fourccs_out, params->expected, TEST_BUF_SIZE); -} - struct fb_memcpy_case { const char *name; u32 format; @@ -1864,7 +1723,6 @@ static struct kunit_case drm_format_helper_test_cases[] = { KUNIT_CASE_PARAM(drm_test_fb_xrgb8888_to_xbgr8888, convert_xrgb8888_gen_params), KUNIT_CASE_PARAM(drm_test_fb_xrgb8888_to_abgr8888, convert_xrgb8888_gen_params), KUNIT_CASE_PARAM(drm_test_fb_clip_offset, clip_offset_gen_params), - KUNIT_CASE_PARAM(drm_test_fb_build_fourcc_list, fb_build_fourcc_list_gen_params), KUNIT_CASE_PARAM(drm_test_fb_memcpy, fb_memcpy_gen_params), {} }; diff --git a/drivers/gpu/drm/tests/drm_sysfb_modeset_test.c b/drivers/gpu/drm/tests/drm_sysfb_modeset_test.c new file mode 100644 index 000000000000..5104fb21c6bc --- /dev/null +++ b/drivers/gpu/drm/tests/drm_sysfb_modeset_test.c @@ -0,0 +1,166 @@ +// SPDX-License-Identifier: GPL-2.0+ + +#include + +#include +#include +#include + +#define TEST_BUF_SIZE 50 + +struct fb_build_fourcc_list_case { + const char *name; + u32 native_fourccs[TEST_BUF_SIZE]; + size_t native_fourccs_size; + u32 expected[TEST_BUF_SIZE]; + size_t expected_fourccs_size; +}; + +static struct fb_build_fourcc_list_case fb_build_fourcc_list_cases[] = { + { + .name = "no native formats", + .native_fourccs = { }, + .native_fourccs_size = 0, + .expected = { DRM_FORMAT_XRGB8888 }, + .expected_fourccs_size = 1, + }, + { + .name = "XRGB8888 as native format", + .native_fourccs = { DRM_FORMAT_XRGB8888 }, + .native_fourccs_size = 1, + .expected = { DRM_FORMAT_XRGB8888 }, + .expected_fourccs_size = 1, + }, + { + .name = "remove duplicates", + .native_fourccs = { + DRM_FORMAT_XRGB8888, + DRM_FORMAT_XRGB8888, + DRM_FORMAT_RGB888, + DRM_FORMAT_RGB888, + DRM_FORMAT_RGB888, + DRM_FORMAT_XRGB8888, + DRM_FORMAT_RGB888, + DRM_FORMAT_RGB565, + DRM_FORMAT_RGB888, + DRM_FORMAT_XRGB8888, + DRM_FORMAT_RGB565, + DRM_FORMAT_RGB565, + DRM_FORMAT_XRGB8888, + }, + .native_fourccs_size = 11, + .expected = { + DRM_FORMAT_XRGB8888, + DRM_FORMAT_RGB888, + DRM_FORMAT_RGB565, + }, + .expected_fourccs_size = 3, + }, + { + .name = "convert alpha formats", + .native_fourccs = { + DRM_FORMAT_ARGB1555, + DRM_FORMAT_ABGR1555, + DRM_FORMAT_RGBA5551, + DRM_FORMAT_BGRA5551, + DRM_FORMAT_ARGB8888, + DRM_FORMAT_ABGR8888, + DRM_FORMAT_RGBA8888, + DRM_FORMAT_BGRA8888, + DRM_FORMAT_ARGB2101010, + DRM_FORMAT_ABGR2101010, + DRM_FORMAT_RGBA1010102, + DRM_FORMAT_BGRA1010102, + }, + .native_fourccs_size = 12, + .expected = { + DRM_FORMAT_XRGB1555, + DRM_FORMAT_XBGR1555, + DRM_FORMAT_RGBX5551, + DRM_FORMAT_BGRX5551, + DRM_FORMAT_XRGB8888, + DRM_FORMAT_XBGR8888, + DRM_FORMAT_RGBX8888, + DRM_FORMAT_BGRX8888, + DRM_FORMAT_XRGB2101010, + DRM_FORMAT_XBGR2101010, + DRM_FORMAT_RGBX1010102, + DRM_FORMAT_BGRX1010102, + }, + .expected_fourccs_size = 12, + }, + { + .name = "random formats", + .native_fourccs = { + DRM_FORMAT_Y212, + DRM_FORMAT_ARGB1555, + DRM_FORMAT_ABGR16161616F, + DRM_FORMAT_C8, + DRM_FORMAT_BGR888, + DRM_FORMAT_XRGB1555, + DRM_FORMAT_RGBA5551, + DRM_FORMAT_BGR565_A8, + DRM_FORMAT_R10, + DRM_FORMAT_XYUV8888, + }, + .native_fourccs_size = 10, + .expected = { + DRM_FORMAT_Y212, + DRM_FORMAT_XRGB1555, + DRM_FORMAT_ABGR16161616F, + DRM_FORMAT_C8, + DRM_FORMAT_BGR888, + DRM_FORMAT_RGBX5551, + DRM_FORMAT_BGR565_A8, + DRM_FORMAT_R10, + DRM_FORMAT_XYUV8888, + DRM_FORMAT_XRGB8888, + }, + .expected_fourccs_size = 10, + }, +}; + +static void fb_build_fourcc_list_case_desc(struct fb_build_fourcc_list_case *t, char *desc) +{ + strscpy(desc, t->name, KUNIT_PARAM_DESC_SIZE); +} + +KUNIT_ARRAY_PARAM(fb_build_fourcc_list, fb_build_fourcc_list_cases, fb_build_fourcc_list_case_desc); + +static void drm_test_fb_build_fourcc_list(struct kunit *test) +{ + const struct fb_build_fourcc_list_case *params = test->param_value; + u32 fourccs_out[TEST_BUF_SIZE] = {0}; + size_t nfourccs_out; + struct drm_device *drm; + struct device *dev; + + 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); + + nfourccs_out = drm_fb_build_fourcc_list(drm, params->native_fourccs, + params->native_fourccs_size, + fourccs_out, TEST_BUF_SIZE); + + KUNIT_EXPECT_EQ(test, nfourccs_out, params->expected_fourccs_size); + KUNIT_EXPECT_MEMEQ(test, fourccs_out, params->expected, TEST_BUF_SIZE); +} + +static struct kunit_case drm_sysfb_modeset_test_cases[] = { + KUNIT_CASE_PARAM(drm_test_fb_build_fourcc_list, fb_build_fourcc_list_gen_params), + {} +}; + +static struct kunit_suite drm_sysfb_modeset_test_suite = { + .name = "drm_sysfb_modeset_test", + .test_cases = drm_sysfb_modeset_test_cases, +}; + +kunit_test_suite(drm_sysfb_modeset_test_suite); + +MODULE_DESCRIPTION("KUnit tests for the drm_sysfb_modeset APIs"); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("José Expósito "); -- cgit v1.2.3 From 1a45ef022f0364186d4fb2f4e5255dcae1ff638a Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Mon, 16 Jun 2025 10:37:06 +0200 Subject: drm/format-helper: Move drm_fb_build_fourcc_list() to sysfb helpers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Only sysfb drivers use drm_fb_build_fourcc_list(). Move the function to sysfb helpers and rename it accordingly. Update drivers and tests. v3: - update naming in tests v2: - select DRM_SYSFB_HELPER (kernel test robot) Signed-off-by: Thomas Zimmermann Reviewed-by: José Expósito Acked-by: Maxime Ripard Acked-by: Javier Martinez Canillas Link: https://lore.kernel.org/r/20250616083846.221396-4-tzimmermann@suse.de --- drivers/gpu/drm/Kconfig.debug | 1 + drivers/gpu/drm/drm_format_helper.c | 138 ------------------------- drivers/gpu/drm/sysfb/drm_sysfb_helper.h | 4 + drivers/gpu/drm/sysfb/drm_sysfb_modeset.c | 138 +++++++++++++++++++++++++ drivers/gpu/drm/sysfb/efidrm.c | 4 +- drivers/gpu/drm/sysfb/ofdrm.c | 5 +- drivers/gpu/drm/sysfb/simpledrm.c | 5 +- drivers/gpu/drm/sysfb/vesadrm.c | 4 +- drivers/gpu/drm/tests/drm_sysfb_modeset_test.c | 24 +++-- include/drm/drm_format_helper.h | 4 - 10 files changed, 164 insertions(+), 163 deletions(-) (limited to 'drivers/gpu/drm/tests') diff --git a/drivers/gpu/drm/Kconfig.debug b/drivers/gpu/drm/Kconfig.debug index fa6ee76f4d3c..05dc43c0b8c5 100644 --- a/drivers/gpu/drm/Kconfig.debug +++ b/drivers/gpu/drm/Kconfig.debug @@ -70,6 +70,7 @@ config DRM_KUNIT_TEST select DRM_GEM_SHMEM_HELPER select DRM_KUNIT_TEST_HELPERS select DRM_LIB_RANDOM + select DRM_SYSFB_HELPER select PRIME_NUMBERS default KUNIT_ALL_TESTS help diff --git a/drivers/gpu/drm/drm_format_helper.c b/drivers/gpu/drm/drm_format_helper.c index 63dc46f9fc49..99d9f7bbc261 100644 --- a/drivers/gpu/drm/drm_format_helper.c +++ b/drivers/gpu/drm/drm_format_helper.c @@ -1339,141 +1339,3 @@ void drm_fb_xrgb8888_to_mono(struct iosys_map *dst, const unsigned int *dst_pitc } } EXPORT_SYMBOL(drm_fb_xrgb8888_to_mono); - -static uint32_t drm_fb_nonalpha_fourcc(uint32_t fourcc) -{ - /* only handle formats with depth != 0 and alpha channel */ - switch (fourcc) { - case DRM_FORMAT_ARGB1555: - return DRM_FORMAT_XRGB1555; - case DRM_FORMAT_ABGR1555: - return DRM_FORMAT_XBGR1555; - case DRM_FORMAT_RGBA5551: - return DRM_FORMAT_RGBX5551; - case DRM_FORMAT_BGRA5551: - return DRM_FORMAT_BGRX5551; - case DRM_FORMAT_ARGB8888: - return DRM_FORMAT_XRGB8888; - case DRM_FORMAT_ABGR8888: - return DRM_FORMAT_XBGR8888; - case DRM_FORMAT_RGBA8888: - return DRM_FORMAT_RGBX8888; - case DRM_FORMAT_BGRA8888: - return DRM_FORMAT_BGRX8888; - case DRM_FORMAT_ARGB2101010: - return DRM_FORMAT_XRGB2101010; - case DRM_FORMAT_ABGR2101010: - return DRM_FORMAT_XBGR2101010; - case DRM_FORMAT_RGBA1010102: - return DRM_FORMAT_RGBX1010102; - case DRM_FORMAT_BGRA1010102: - return DRM_FORMAT_BGRX1010102; - } - - return fourcc; -} - -static bool is_listed_fourcc(const uint32_t *fourccs, size_t nfourccs, uint32_t fourcc) -{ - const uint32_t *fourccs_end = fourccs + nfourccs; - - while (fourccs < fourccs_end) { - if (*fourccs == fourcc) - return true; - ++fourccs; - } - return false; -} - -/** - * drm_fb_build_fourcc_list - Filters a list of supported color formats against - * the device's native formats - * @dev: DRM device - * @native_fourccs: 4CC codes of natively supported color formats - * @native_nfourccs: The number of entries in @native_fourccs - * @fourccs_out: Returns 4CC codes of supported color formats - * @nfourccs_out: The number of available entries in @fourccs_out - * - * This function create a list of supported color format from natively - * supported formats and additional emulated formats. - * At a minimum, most userspace programs expect at least support for - * XRGB8888 on the primary plane. Devices that have to emulate the - * format, and possibly others, can use drm_fb_build_fourcc_list() to - * create a list of supported color formats. The returned list can - * be handed over to drm_universal_plane_init() et al. Native formats - * will go before emulated formats. Native formats with alpha channel - * will be replaced by such without, as primary planes usually don't - * support alpha. Other heuristics might be applied - * to optimize the order. Formats near the beginning of the list are - * usually preferred over formats near the end of the list. - * - * Returns: - * The number of color-formats 4CC codes returned in @fourccs_out. - */ -size_t drm_fb_build_fourcc_list(struct drm_device *dev, - const u32 *native_fourccs, size_t native_nfourccs, - u32 *fourccs_out, size_t nfourccs_out) -{ - /* - * XRGB8888 is the default fallback format for most of userspace - * and it's currently the only format that should be emulated for - * the primary plane. Only if there's ever another default fallback, - * it should be added here. - */ - static const uint32_t extra_fourccs[] = { - DRM_FORMAT_XRGB8888, - }; - static const size_t extra_nfourccs = ARRAY_SIZE(extra_fourccs); - - u32 *fourccs = fourccs_out; - const u32 *fourccs_end = fourccs_out + nfourccs_out; - size_t i; - - /* - * The device's native formats go first. - */ - - for (i = 0; i < native_nfourccs; ++i) { - /* - * Several DTs, boot loaders and firmware report native - * alpha formats that are non-alpha formats instead. So - * replace alpha formats by non-alpha formats. - */ - u32 fourcc = drm_fb_nonalpha_fourcc(native_fourccs[i]); - - if (is_listed_fourcc(fourccs_out, fourccs - fourccs_out, fourcc)) { - continue; /* skip duplicate entries */ - } else if (fourccs == fourccs_end) { - drm_warn(dev, "Ignoring native format %p4cc\n", &fourcc); - continue; /* end of available output buffer */ - } - - drm_dbg_kms(dev, "adding native format %p4cc\n", &fourcc); - - *fourccs = fourcc; - ++fourccs; - } - - /* - * The extra formats, emulated by the driver, go second. - */ - - for (i = 0; (i < extra_nfourccs) && (fourccs < fourccs_end); ++i) { - u32 fourcc = extra_fourccs[i]; - - if (is_listed_fourcc(fourccs_out, fourccs - fourccs_out, fourcc)) { - continue; /* skip duplicate and native entries */ - } else if (fourccs == fourccs_end) { - drm_warn(dev, "Ignoring emulated format %p4cc\n", &fourcc); - continue; /* end of available output buffer */ - } - - drm_dbg_kms(dev, "adding emulated format %p4cc\n", &fourcc); - - *fourccs = fourcc; - ++fourccs; - } - - return fourccs - fourccs_out; -} -EXPORT_SYMBOL(drm_fb_build_fourcc_list); diff --git a/drivers/gpu/drm/sysfb/drm_sysfb_helper.h b/drivers/gpu/drm/sysfb/drm_sysfb_helper.h index cb08a88242cc..1424b63dde99 100644 --- a/drivers/gpu/drm/sysfb/drm_sysfb_helper.h +++ b/drivers/gpu/drm/sysfb/drm_sysfb_helper.h @@ -93,6 +93,10 @@ static inline struct drm_sysfb_device *to_drm_sysfb_device(struct drm_device *de * Plane */ +size_t drm_sysfb_build_fourcc_list(struct drm_device *dev, + const u32 *native_fourccs, size_t native_nfourccs, + u32 *fourccs_out, size_t nfourccs_out); + int drm_sysfb_plane_helper_atomic_check(struct drm_plane *plane, struct drm_atomic_state *new_state); void drm_sysfb_plane_helper_atomic_update(struct drm_plane *plane, diff --git a/drivers/gpu/drm/sysfb/drm_sysfb_modeset.c b/drivers/gpu/drm/sysfb/drm_sysfb_modeset.c index ffaa2522ab96..1bcdb5ee8f09 100644 --- a/drivers/gpu/drm/sysfb/drm_sysfb_modeset.c +++ b/drivers/gpu/drm/sysfb/drm_sysfb_modeset.c @@ -47,6 +47,144 @@ EXPORT_SYMBOL(drm_sysfb_mode); * Plane */ +static u32 to_nonalpha_fourcc(u32 fourcc) +{ + /* only handle formats with depth != 0 and alpha channel */ + switch (fourcc) { + case DRM_FORMAT_ARGB1555: + return DRM_FORMAT_XRGB1555; + case DRM_FORMAT_ABGR1555: + return DRM_FORMAT_XBGR1555; + case DRM_FORMAT_RGBA5551: + return DRM_FORMAT_RGBX5551; + case DRM_FORMAT_BGRA5551: + return DRM_FORMAT_BGRX5551; + case DRM_FORMAT_ARGB8888: + return DRM_FORMAT_XRGB8888; + case DRM_FORMAT_ABGR8888: + return DRM_FORMAT_XBGR8888; + case DRM_FORMAT_RGBA8888: + return DRM_FORMAT_RGBX8888; + case DRM_FORMAT_BGRA8888: + return DRM_FORMAT_BGRX8888; + case DRM_FORMAT_ARGB2101010: + return DRM_FORMAT_XRGB2101010; + case DRM_FORMAT_ABGR2101010: + return DRM_FORMAT_XBGR2101010; + case DRM_FORMAT_RGBA1010102: + return DRM_FORMAT_RGBX1010102; + case DRM_FORMAT_BGRA1010102: + return DRM_FORMAT_BGRX1010102; + } + + return fourcc; +} + +static bool is_listed_fourcc(const u32 *fourccs, size_t nfourccs, u32 fourcc) +{ + const u32 *fourccs_end = fourccs + nfourccs; + + while (fourccs < fourccs_end) { + if (*fourccs == fourcc) + return true; + ++fourccs; + } + return false; +} + +/** + * drm_sysfb_build_fourcc_list - Filters a list of supported color formats against + * the device's native formats + * @dev: DRM device + * @native_fourccs: 4CC codes of natively supported color formats + * @native_nfourccs: The number of entries in @native_fourccs + * @fourccs_out: Returns 4CC codes of supported color formats + * @nfourccs_out: The number of available entries in @fourccs_out + * + * This function create a list of supported color format from natively + * supported formats and additional emulated formats. + * At a minimum, most userspace programs expect at least support for + * XRGB8888 on the primary plane. Sysfb devices that have to emulate + * the format should use drm_sysfb_build_fourcc_list() to create a list + * of supported color formats. The returned list can be handed over to + * drm_universal_plane_init() et al. Native formats will go before + * emulated formats. Native formats with alpha channel will be replaced + * by equal formats without alpha channel, as primary planes usually + * don't support alpha. Other heuristics might be applied to optimize + * the sorting order. Formats near the beginning of the list are usually + * preferred over formats near the end of the list. + * + * Returns: + * The number of color-formats 4CC codes returned in @fourccs_out. + */ +size_t drm_sysfb_build_fourcc_list(struct drm_device *dev, + const u32 *native_fourccs, size_t native_nfourccs, + u32 *fourccs_out, size_t nfourccs_out) +{ + /* + * XRGB8888 is the default fallback format for most of userspace + * and it's currently the only format that should be emulated for + * the primary plane. Only if there's ever another default fallback, + * it should be added here. + */ + static const u32 extra_fourccs[] = { + DRM_FORMAT_XRGB8888, + }; + static const size_t extra_nfourccs = ARRAY_SIZE(extra_fourccs); + + u32 *fourccs = fourccs_out; + const u32 *fourccs_end = fourccs_out + nfourccs_out; + size_t i; + + /* + * The device's native formats go first. + */ + + for (i = 0; i < native_nfourccs; ++i) { + /* + * Several DTs, boot loaders and firmware report native + * alpha formats that are non-alpha formats instead. So + * replace alpha formats by non-alpha formats. + */ + u32 fourcc = to_nonalpha_fourcc(native_fourccs[i]); + + if (is_listed_fourcc(fourccs_out, fourccs - fourccs_out, fourcc)) { + continue; /* skip duplicate entries */ + } else if (fourccs == fourccs_end) { + drm_warn(dev, "Ignoring native format %p4cc\n", &fourcc); + continue; /* end of available output buffer */ + } + + drm_dbg_kms(dev, "adding native format %p4cc\n", &fourcc); + + *fourccs = fourcc; + ++fourccs; + } + + /* + * The extra formats, emulated by the driver, go second. + */ + + for (i = 0; (i < extra_nfourccs) && (fourccs < fourccs_end); ++i) { + u32 fourcc = extra_fourccs[i]; + + if (is_listed_fourcc(fourccs_out, fourccs - fourccs_out, fourcc)) { + continue; /* skip duplicate and native entries */ + } else if (fourccs == fourccs_end) { + drm_warn(dev, "Ignoring emulated format %p4cc\n", &fourcc); + continue; /* end of available output buffer */ + } + + drm_dbg_kms(dev, "adding emulated format %p4cc\n", &fourcc); + + *fourccs = fourcc; + ++fourccs; + } + + return fourccs - fourccs_out; +} +EXPORT_SYMBOL(drm_sysfb_build_fourcc_list); + int drm_sysfb_plane_helper_atomic_check(struct drm_plane *plane, struct drm_atomic_state *new_state) { diff --git a/drivers/gpu/drm/sysfb/efidrm.c b/drivers/gpu/drm/sysfb/efidrm.c index a8b1305b6e13..1883c4a8604c 100644 --- a/drivers/gpu/drm/sysfb/efidrm.c +++ b/drivers/gpu/drm/sysfb/efidrm.c @@ -271,8 +271,8 @@ static struct efidrm_device *efidrm_device_create(struct drm_driver *drv, /* Primary plane */ - nformats = drm_fb_build_fourcc_list(dev, &format->format, 1, - efi->formats, ARRAY_SIZE(efi->formats)); + nformats = drm_sysfb_build_fourcc_list(dev, &format->format, 1, + efi->formats, ARRAY_SIZE(efi->formats)); primary_plane = &efi->primary_plane; ret = drm_universal_plane_init(dev, primary_plane, 0, &efidrm_primary_plane_funcs, diff --git a/drivers/gpu/drm/sysfb/ofdrm.c b/drivers/gpu/drm/sysfb/ofdrm.c index c9415f0cb3ed..8d8ab39c5f36 100644 --- a/drivers/gpu/drm/sysfb/ofdrm.c +++ b/drivers/gpu/drm/sysfb/ofdrm.c @@ -15,7 +15,6 @@ #include #include #include -#include #include #include #include @@ -1015,8 +1014,8 @@ static struct ofdrm_device *ofdrm_device_create(struct drm_driver *drv, /* Primary plane */ - nformats = drm_fb_build_fourcc_list(dev, &format->format, 1, - odev->formats, ARRAY_SIZE(odev->formats)); + nformats = drm_sysfb_build_fourcc_list(dev, &format->format, 1, + odev->formats, ARRAY_SIZE(odev->formats)); primary_plane = &odev->primary_plane; ret = drm_universal_plane_init(dev, primary_plane, 0, &ofdrm_primary_plane_funcs, diff --git a/drivers/gpu/drm/sysfb/simpledrm.c b/drivers/gpu/drm/sysfb/simpledrm.c index a1c3119330de..8530a3ef8a7a 100644 --- a/drivers/gpu/drm/sysfb/simpledrm.c +++ b/drivers/gpu/drm/sysfb/simpledrm.c @@ -18,7 +18,6 @@ #include #include #include -#include #include #include #include @@ -765,8 +764,8 @@ static struct simpledrm_device *simpledrm_device_create(struct drm_driver *drv, /* Primary plane */ - nformats = drm_fb_build_fourcc_list(dev, &format->format, 1, - sdev->formats, ARRAY_SIZE(sdev->formats)); + nformats = drm_sysfb_build_fourcc_list(dev, &format->format, 1, + sdev->formats, ARRAY_SIZE(sdev->formats)); primary_plane = &sdev->primary_plane; ret = drm_universal_plane_init(dev, primary_plane, 0, &simpledrm_primary_plane_funcs, diff --git a/drivers/gpu/drm/sysfb/vesadrm.c b/drivers/gpu/drm/sysfb/vesadrm.c index c5216dbe21ec..2b107958942c 100644 --- a/drivers/gpu/drm/sysfb/vesadrm.c +++ b/drivers/gpu/drm/sysfb/vesadrm.c @@ -402,8 +402,8 @@ static struct vesadrm_device *vesadrm_device_create(struct drm_driver *drv, /* Primary plane */ - nformats = drm_fb_build_fourcc_list(dev, &format->format, 1, - vesa->formats, ARRAY_SIZE(vesa->formats)); + nformats = drm_sysfb_build_fourcc_list(dev, &format->format, 1, + vesa->formats, ARRAY_SIZE(vesa->formats)); primary_plane = &vesa->primary_plane; ret = drm_universal_plane_init(dev, primary_plane, 0, &vesadrm_primary_plane_funcs, diff --git a/drivers/gpu/drm/tests/drm_sysfb_modeset_test.c b/drivers/gpu/drm/tests/drm_sysfb_modeset_test.c index 5104fb21c6bc..e875d876118f 100644 --- a/drivers/gpu/drm/tests/drm_sysfb_modeset_test.c +++ b/drivers/gpu/drm/tests/drm_sysfb_modeset_test.c @@ -2,13 +2,14 @@ #include -#include #include #include +#include "../sysfb/drm_sysfb_helper.h" + #define TEST_BUF_SIZE 50 -struct fb_build_fourcc_list_case { +struct sysfb_build_fourcc_list_case { const char *name; u32 native_fourccs[TEST_BUF_SIZE]; size_t native_fourccs_size; @@ -16,7 +17,7 @@ struct fb_build_fourcc_list_case { size_t expected_fourccs_size; }; -static struct fb_build_fourcc_list_case fb_build_fourcc_list_cases[] = { +static struct sysfb_build_fourcc_list_case sysfb_build_fourcc_list_cases[] = { { .name = "no native formats", .native_fourccs = { }, @@ -120,16 +121,17 @@ static struct fb_build_fourcc_list_case fb_build_fourcc_list_cases[] = { }, }; -static void fb_build_fourcc_list_case_desc(struct fb_build_fourcc_list_case *t, char *desc) +static void sysfb_build_fourcc_list_case_desc(struct sysfb_build_fourcc_list_case *t, char *desc) { strscpy(desc, t->name, KUNIT_PARAM_DESC_SIZE); } -KUNIT_ARRAY_PARAM(fb_build_fourcc_list, fb_build_fourcc_list_cases, fb_build_fourcc_list_case_desc); +KUNIT_ARRAY_PARAM(sysfb_build_fourcc_list, sysfb_build_fourcc_list_cases, + sysfb_build_fourcc_list_case_desc); -static void drm_test_fb_build_fourcc_list(struct kunit *test) +static void drm_test_sysfb_build_fourcc_list(struct kunit *test) { - const struct fb_build_fourcc_list_case *params = test->param_value; + const struct sysfb_build_fourcc_list_case *params = test->param_value; u32 fourccs_out[TEST_BUF_SIZE] = {0}; size_t nfourccs_out; struct drm_device *drm; @@ -141,16 +143,16 @@ static void drm_test_fb_build_fourcc_list(struct kunit *test) drm = __drm_kunit_helper_alloc_drm_device(test, dev, sizeof(*drm), 0, DRIVER_MODESET); KUNIT_ASSERT_NOT_ERR_OR_NULL(test, drm); - nfourccs_out = drm_fb_build_fourcc_list(drm, params->native_fourccs, - params->native_fourccs_size, - fourccs_out, TEST_BUF_SIZE); + nfourccs_out = drm_sysfb_build_fourcc_list(drm, params->native_fourccs, + params->native_fourccs_size, + fourccs_out, TEST_BUF_SIZE); KUNIT_EXPECT_EQ(test, nfourccs_out, params->expected_fourccs_size); KUNIT_EXPECT_MEMEQ(test, fourccs_out, params->expected, TEST_BUF_SIZE); } static struct kunit_case drm_sysfb_modeset_test_cases[] = { - KUNIT_CASE_PARAM(drm_test_fb_build_fourcc_list, fb_build_fourcc_list_gen_params), + KUNIT_CASE_PARAM(drm_test_sysfb_build_fourcc_list, sysfb_build_fourcc_list_gen_params), {} }; diff --git a/include/drm/drm_format_helper.h b/include/drm/drm_format_helper.h index 49a2e09155d1..0d3ee2a1313f 100644 --- a/include/drm/drm_format_helper.h +++ b/include/drm/drm_format_helper.h @@ -134,8 +134,4 @@ void drm_fb_xrgb8888_to_mono(struct iosys_map *dst, const unsigned int *dst_pitc const struct iosys_map *src, const struct drm_framebuffer *fb, const struct drm_rect *clip, struct drm_format_conv_state *state); -size_t drm_fb_build_fourcc_list(struct drm_device *dev, - const u32 *native_fourccs, size_t native_nfourccs, - u32 *fourccs_out, size_t nfourccs_out); - #endif /* __LINUX_DRM_FORMAT_HELPER_H */ -- cgit v1.2.3