Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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 <mripard@kernel.org>
Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
Link: https://lore.kernel.org/r/20250527-hdmi-conn-yuv-v5-18-74c9c4a8ac0c@collabora.com
Signed-off-by: Maxime Ripard <mripard@kernel.org>

authored by

Cristian Ciocaltea and committed by
Maxime Ripard
e271ecaa 54a5f1c4

+154
+154
drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c
··· 1311 1311 1312 1312 /* 1313 1313 * Test that if: 1314 + * - We have an HDMI connector and a display supporting both RGB and YUV420 1315 + * - The chosen mode can be supported in YUV420 output format only 1316 + * - The chosen mode has a TMDS character rate higher than the display 1317 + * supports in YUV420/12bpc 1318 + * - The chosen mode has a TMDS character rate lower than the display 1319 + * supports in YUV420/10bpc. 1320 + * 1321 + * Then we will pick the latter, and the computed TMDS character rate 1322 + * will be equal to 1.25 * 0.5 times the mode pixel clock. 1323 + */ 1324 + static void drm_test_check_max_tmds_rate_bpc_fallback_yuv420(struct kunit *test) 1325 + { 1326 + struct drm_atomic_helper_connector_hdmi_priv *priv; 1327 + struct drm_modeset_acquire_ctx ctx; 1328 + struct drm_connector_state *conn_state; 1329 + struct drm_display_info *info; 1330 + struct drm_display_mode *yuv420_only_mode; 1331 + unsigned long long rate; 1332 + struct drm_connector *conn; 1333 + struct drm_device *drm; 1334 + struct drm_crtc *crtc; 1335 + int ret; 1336 + 1337 + priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test, 1338 + BIT(HDMI_COLORSPACE_RGB) | 1339 + BIT(HDMI_COLORSPACE_YUV420), 1340 + 12, 1341 + &dummy_connector_hdmi_funcs, 1342 + test_edid_hdmi_1080p_rgb_yuv_4k_yuv420_dc_max_200mhz); 1343 + KUNIT_ASSERT_NOT_NULL(test, priv); 1344 + 1345 + drm = &priv->drm; 1346 + crtc = priv->crtc; 1347 + conn = &priv->connector; 1348 + info = &conn->display_info; 1349 + KUNIT_ASSERT_TRUE(test, info->is_hdmi); 1350 + KUNIT_ASSERT_GT(test, info->max_tmds_clock, 0); 1351 + KUNIT_ASSERT_TRUE(test, conn->ycbcr_420_allowed); 1352 + 1353 + yuv420_only_mode = drm_kunit_display_mode_from_cea_vic(test, drm, 95); 1354 + KUNIT_ASSERT_NOT_NULL(test, yuv420_only_mode); 1355 + KUNIT_ASSERT_TRUE(test, drm_mode_is_420_only(info, yuv420_only_mode)); 1356 + 1357 + rate = drm_hdmi_compute_mode_clock(yuv420_only_mode, 12, HDMI_COLORSPACE_YUV420); 1358 + KUNIT_ASSERT_GT(test, rate, info->max_tmds_clock * 1000); 1359 + 1360 + rate = drm_hdmi_compute_mode_clock(yuv420_only_mode, 10, HDMI_COLORSPACE_YUV420); 1361 + KUNIT_ASSERT_LT(test, rate, info->max_tmds_clock * 1000); 1362 + 1363 + drm_modeset_acquire_init(&ctx, 0); 1364 + 1365 + retry_conn_enable: 1366 + ret = drm_kunit_helper_enable_crtc_connector(test, drm, crtc, conn, 1367 + yuv420_only_mode, &ctx); 1368 + if (ret == -EDEADLK) { 1369 + ret = drm_modeset_backoff(&ctx); 1370 + if (!ret) 1371 + goto retry_conn_enable; 1372 + } 1373 + KUNIT_EXPECT_EQ(test, ret, 0); 1374 + 1375 + conn_state = conn->state; 1376 + KUNIT_ASSERT_NOT_NULL(test, conn_state); 1377 + 1378 + KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_bpc, 10); 1379 + KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_format, HDMI_COLORSPACE_YUV420); 1380 + KUNIT_EXPECT_EQ(test, conn_state->hdmi.tmds_char_rate, yuv420_only_mode->clock * 625); 1381 + 1382 + drm_modeset_drop_locks(&ctx); 1383 + drm_modeset_acquire_fini(&ctx); 1384 + } 1385 + 1386 + /* 1387 + * Test that if: 1314 1388 * - We have an HDMI connector supporting both RGB and YUV422 and up to 1315 1389 * 12 bpc 1316 1390 * - The chosen mode has a TMDS character rate higher than the display ··· 1450 1376 KUNIT_ASSERT_NOT_NULL(test, conn_state); 1451 1377 1452 1378 KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_bpc, 10); 1379 + KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_format, HDMI_COLORSPACE_RGB); 1380 + 1381 + drm_modeset_drop_locks(&ctx); 1382 + drm_modeset_acquire_fini(&ctx); 1383 + } 1384 + 1385 + /* 1386 + * Test that if: 1387 + * - We have an HDMI connector supporting both RGB and YUV420 and up to 1388 + * 12 bpc 1389 + * - The chosen mode has a TMDS character rate higher than the display 1390 + * supports in RGB/10bpc but lower than the display supports in 1391 + * RGB/8bpc 1392 + * - The chosen mode has a TMDS character rate lower than the display 1393 + * supports in YUV420/12bpc. 1394 + * 1395 + * Then we will prefer to keep the RGB format with a lower bpc over 1396 + * picking YUV420. 1397 + */ 1398 + static void drm_test_check_max_tmds_rate_bpc_fallback_ignore_yuv420(struct kunit *test) 1399 + { 1400 + struct drm_atomic_helper_connector_hdmi_priv *priv; 1401 + struct drm_modeset_acquire_ctx ctx; 1402 + struct drm_connector_state *conn_state; 1403 + struct drm_display_info *info; 1404 + struct drm_display_mode *preferred; 1405 + unsigned long long rate; 1406 + struct drm_connector *conn; 1407 + struct drm_device *drm; 1408 + struct drm_crtc *crtc; 1409 + int ret; 1410 + 1411 + priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test, 1412 + BIT(HDMI_COLORSPACE_RGB) | 1413 + BIT(HDMI_COLORSPACE_YUV420), 1414 + 12, 1415 + &dummy_connector_hdmi_funcs, 1416 + test_edid_hdmi_4k_rgb_yuv420_dc_max_340mhz); 1417 + KUNIT_ASSERT_NOT_NULL(test, priv); 1418 + 1419 + drm = &priv->drm; 1420 + crtc = priv->crtc; 1421 + conn = &priv->connector; 1422 + info = &conn->display_info; 1423 + KUNIT_ASSERT_TRUE(test, info->is_hdmi); 1424 + KUNIT_ASSERT_GT(test, info->max_tmds_clock, 0); 1425 + KUNIT_ASSERT_TRUE(test, conn->ycbcr_420_allowed); 1426 + 1427 + preferred = find_preferred_mode(conn); 1428 + KUNIT_ASSERT_NOT_NULL(test, preferred); 1429 + KUNIT_ASSERT_FALSE(test, preferred->flags & DRM_MODE_FLAG_DBLCLK); 1430 + KUNIT_ASSERT_TRUE(test, drm_mode_is_420_also(info, preferred)); 1431 + 1432 + rate = drm_hdmi_compute_mode_clock(preferred, 8, HDMI_COLORSPACE_RGB); 1433 + KUNIT_ASSERT_LT(test, rate, info->max_tmds_clock * 1000); 1434 + 1435 + rate = drm_hdmi_compute_mode_clock(preferred, 10, HDMI_COLORSPACE_RGB); 1436 + KUNIT_ASSERT_GT(test, rate, info->max_tmds_clock * 1000); 1437 + 1438 + rate = drm_hdmi_compute_mode_clock(preferred, 12, HDMI_COLORSPACE_YUV420); 1439 + KUNIT_ASSERT_LT(test, rate, info->max_tmds_clock * 1000); 1440 + 1441 + drm_modeset_acquire_init(&ctx, 0); 1442 + 1443 + retry_conn_enable: 1444 + ret = drm_kunit_helper_enable_crtc_connector(test, drm, crtc, conn, 1445 + preferred, &ctx); 1446 + if (ret == -EDEADLK) { 1447 + ret = drm_modeset_backoff(&ctx); 1448 + if (!ret) 1449 + goto retry_conn_enable; 1450 + } 1451 + KUNIT_EXPECT_EQ(test, ret, 0); 1452 + 1453 + conn_state = conn->state; 1454 + KUNIT_ASSERT_NOT_NULL(test, conn_state); 1455 + 1456 + KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_bpc, 8); 1453 1457 KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_format, HDMI_COLORSPACE_RGB); 1454 1458 1455 1459 drm_modeset_drop_locks(&ctx); ··· 1927 1775 KUNIT_CASE(drm_test_check_disable_connector), 1928 1776 KUNIT_CASE(drm_test_check_hdmi_funcs_reject_rate), 1929 1777 KUNIT_CASE(drm_test_check_max_tmds_rate_bpc_fallback_rgb), 1778 + KUNIT_CASE(drm_test_check_max_tmds_rate_bpc_fallback_yuv420), 1930 1779 KUNIT_CASE(drm_test_check_max_tmds_rate_bpc_fallback_ignore_yuv422), 1780 + KUNIT_CASE(drm_test_check_max_tmds_rate_bpc_fallback_ignore_yuv420), 1931 1781 KUNIT_CASE(drm_test_check_output_bpc_crtc_mode_changed), 1932 1782 KUNIT_CASE(drm_test_check_output_bpc_crtc_mode_not_changed), 1933 1783 KUNIT_CASE(drm_test_check_output_bpc_dvi),