From nobody Fri Apr 3 03:14:52 2026 Received: from sender4-pp-f112.zoho.com (sender4-pp-f112.zoho.com [136.143.188.112]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 678A2370D74; Tue, 24 Mar 2026 16:04:42 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=pass smtp.client-ip=136.143.188.112 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774368283; cv=pass; b=gwIPwMDaC0sjpbRvc1iPIJATj3uJohcvGBbe2g36HYigSn7CZgt5zzBnwEYxc2O3mbmNOfUUjMmzORcJX5DWfxZcietLWuMG47DOhNQu66I+YcmGvn/SHJ+qvMkE1A+/6nLvh/LXDvoyaz9wfx7V7M5BQYeoluy9+Gr/tueJykc= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774368283; c=relaxed/simple; bh=7i8f4Csa8L49OxZvBjIK2AYm9iejmy8gZ7fL8wGe4p4=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=XWN85ruVQZDlwi4UezQCnc1IrO1/Oq7G5FFP+aT4K6hxdNwzn/CDzTpUmPH6XsceBvro6/rL4yo38drnCkWLhDnq1wXILGwbIbC4KZXSC6WicO3D6cKQ5KpdqUvFiB5i7xvB70S/tbmivkDMeYyPP1zw6V+MT+aveosL26gW1jw= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=collabora.com; spf=pass smtp.mailfrom=collabora.com; dkim=pass (1024-bit key) header.d=collabora.com header.i=nicolas.frattaroli@collabora.com header.b=JSx0zmRJ; arc=pass smtp.client-ip=136.143.188.112 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=collabora.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=collabora.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=collabora.com header.i=nicolas.frattaroli@collabora.com header.b="JSx0zmRJ" ARC-Seal: i=1; a=rsa-sha256; t=1774368234; cv=none; d=zohomail.com; s=zohoarc; b=a3YB+azfm2i6C4cKjKeAuxzId2ta/CwkDWWjxZD3M63ew8XLsIHXVIERwIS5twfb20ukSPD1/Uh0yLWcuZJU+zEqHVuoof84J6DIgjIjRq+hY0/F6yQhjt88DXr1eN1kqGuz6JDzNoPnMJDpkY0EQIDdI/a2Mt3gDkn4a25vbxw= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1774368234; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:MIME-Version:Message-ID:References:Subject:Subject:To:To:Message-Id:Reply-To; bh=oBUEH9z6fnnMMO3qVEtl/mVjCKKVwrQw2lUD6hVHl4g=; b=BciR0mosBcbqJ/54EoSPAoEYiCEfgAsRSRKWgaEVB0O1LE46gZY+1bHQhTViSl7gKLeuCnNCG//12x1nASQpDfq/io9A8ur6nFWXpkC3PwSbbg1BNzYOg4QNHqAW0RhrpWWmXyl7aLnso7vOM47/QzXduPE6MJigjzGWUzM1a8M= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass header.i=collabora.com; spf=pass smtp.mailfrom=nicolas.frattaroli@collabora.com; dmarc=pass header.from= DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; t=1774368234; s=zohomail; d=collabora.com; i=nicolas.frattaroli@collabora.com; h=From:From:Date:Date:Subject:Subject:MIME-Version:Content-Type:Content-Transfer-Encoding:Message-Id:Message-Id:References:In-Reply-To:To:To:Cc:Cc:Reply-To; bh=oBUEH9z6fnnMMO3qVEtl/mVjCKKVwrQw2lUD6hVHl4g=; b=JSx0zmRJQ85ngE/KMCsvgvsytvW/x1dPeOGPg7KzZ8KykqjOOBnDndO0PlohXOEx EUn2OJUFau55k7Ud3WqMz8usvRVLVSvdyAPQsok+ah3I9aOM7SyI1dU3yhSRvf7oQTi OSaCfNepQms6ArhK4LiAPZIOTyWcoFqagoPoj4go= Received: by mx.zohomail.com with SMTPS id 17743682325191.3806001487951107; Tue, 24 Mar 2026 09:03:52 -0700 (PDT) From: Nicolas Frattaroli Date: Tue, 24 Mar 2026 17:01:22 +0100 Subject: [PATCH v11 18/22] drm/tests: hdmi: Add tests for the color_format property Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260324-color-format-v11-18-605559af4fb4@collabora.com> References: <20260324-color-format-v11-0-605559af4fb4@collabora.com> In-Reply-To: <20260324-color-format-v11-0-605559af4fb4@collabora.com> To: Harry Wentland , Leo Li , Rodrigo Siqueira , Alex Deucher , =?utf-8?q?Christian_K=C3=B6nig?= , David Airlie , Simona Vetter , Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , Andrzej Hajda , Neil Armstrong , Robert Foss , Laurent Pinchart , Jonas Karlman , Jernej Skrabec , Sandy Huang , =?utf-8?q?Heiko_St=C3=BCbner?= , Andy Yan , Jani Nikula , Rodrigo Vivi , Joonas Lahtinen , Tvrtko Ursulin , Dmitry Baryshkov , Sascha Hauer , Rob Herring , Jonathan Corbet , Shuah Khan Cc: kernel@collabora.com, amd-gfx@lists.freedesktop.org, dri-devel@lists.freedesktop.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-rockchip@lists.infradead.org, intel-gfx@lists.freedesktop.org, intel-xe@lists.freedesktop.org, linux-doc@vger.kernel.org, Nicolas Frattaroli X-Mailer: b4 0.15.0 Add some KUnit tests to check the color_format property is working as expected with the HDMI state helper. Existing tests are extended to also test the DRM_CONNECTOR_COLOR_FORMAT_AUTO case, in order to avoid duplicating test cases. For the explicitly selected color format cases, parameterized tests are added. Reviewed-by: Maxime Ripard Signed-off-by: Nicolas Frattaroli --- drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c | 236 +++++++++++++++++= ++++ 1 file changed, 236 insertions(+) diff --git a/drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c b/drivers/g= pu/drm/tests/drm_hdmi_state_helper_test.c index a4357efaa983..3444c93c615f 100644 --- a/drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c +++ b/drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c @@ -60,6 +60,23 @@ static struct drm_display_mode *find_preferred_mode(stru= ct drm_connector *connec return preferred; } =20 +static struct drm_display_mode *find_420_only_mode(struct drm_connector *c= onnector) +{ + struct drm_device *drm =3D connector->dev; + struct drm_display_mode *mode; + + mutex_lock(&drm->mode_config.mutex); + list_for_each_entry(mode, &connector->modes, head) { + if (drm_mode_is_420_only(&connector->display_info, mode)) { + mutex_unlock(&drm->mode_config.mutex); + return mode; + } + } + mutex_unlock(&drm->mode_config.mutex); + + return NULL; +} + static int set_connector_edid(struct kunit *test, struct drm_connector *co= nnector, const void *edid, size_t edid_len) { @@ -1547,6 +1564,7 @@ static void drm_test_check_max_tmds_rate_bpc_fallback= _yuv420(struct kunit *test) * RGB/10bpc * - The chosen mode has a TMDS character rate lower than the display * supports in YUV422/12bpc. + * - The HDMI connector state's color format property is unset (i.e. AUTO) * * Then we will prefer to keep the RGB format with a lower bpc over * picking YUV422. @@ -1609,6 +1627,7 @@ static void drm_test_check_max_tmds_rate_bpc_fallback= _ignore_yuv422(struct kunit =20 conn_state =3D conn->state; KUNIT_ASSERT_NOT_NULL(test, conn_state); + KUNIT_ASSERT_EQ(test, conn_state->color_format, DRM_CONNECTOR_COLOR_FORMA= T_AUTO); =20 KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_bpc, 10); KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_format, DRM_OUTPUT_COLOR_FO= RMAT_RGB444); @@ -1626,6 +1645,7 @@ static void drm_test_check_max_tmds_rate_bpc_fallback= _ignore_yuv422(struct kunit * RGB/8bpc * - The chosen mode has a TMDS character rate lower than the display * supports in YUV420/12bpc. + * - The HDMI connector state's color format property is unset (i.e. AUTO) * * Then we will prefer to keep the RGB format with a lower bpc over * picking YUV420. @@ -1687,6 +1707,7 @@ static void drm_test_check_max_tmds_rate_bpc_fallback= _ignore_yuv420(struct kunit =20 conn_state =3D conn->state; KUNIT_ASSERT_NOT_NULL(test, conn_state); + KUNIT_ASSERT_EQ(test, conn_state->color_format, DRM_CONNECTOR_COLOR_FORMA= T_AUTO); =20 KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_bpc, 8); KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_format, DRM_OUTPUT_COLOR_FO= RMAT_RGB444); @@ -2198,6 +2219,217 @@ static void drm_test_check_disable_connector(struct= kunit *test) drm_modeset_acquire_fini(&ctx); } =20 +struct color_format_test_param { + enum drm_connector_color_format fmt; + enum drm_output_color_format expected; + int expected_ret; + const char *desc; +}; + +/* Test that if: + * - an HDMI connector supports RGB, YUV444, YUV422, and YUV420 + * - the display supports RGB, YUV444, YUV422, and YUV420 + * - the "color format" property is set + * then, for the preferred mode, for a given "color format" option: + * - DRM_CONNECTOR_COLOR_FORMAT_AUTO results in an output format of RGB + * - DRM_CONNECTOR_COLOR_FORMAT_YCBCR422 results in an output format of YU= V422 + * - DRM_CONNECTOR_COLOR_FORMAT_YCBCR420 results in an output format of YU= V420 + * - DRM_CONNECTOR_COLOR_FORMAT_YCBCR444 results in an output format of YU= V444 + * - DRM_CONNECTOR_COLOR_FORMAT_RGB results in an HDMI output format of RGB + */ +static void drm_test_check_hdmi_color_format(struct kunit *test) +{ + const struct color_format_test_param *param =3D test->param_value; + struct drm_atomic_helper_connector_hdmi_priv *priv; + struct drm_connector_state *conn_state; + struct drm_modeset_acquire_ctx ctx; + struct drm_crtc_state *crtc_state; + struct drm_atomic_state *state; + struct drm_display_info *info; + struct drm_display_mode *preferred; + int ret; + + priv =3D drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test, + BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444) | + BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR422) | + BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR420) | + BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR444), + 12, + &dummy_connector_hdmi_funcs, + test_edid_hdmi_4k_rgb_yuv420_dc_max_340mhz); + KUNIT_ASSERT_NOT_NULL(test, priv); + + drm_modeset_acquire_init(&ctx, 0); + + KUNIT_ASSERT_TRUE(test, priv->connector.ycbcr_420_allowed); + + info =3D &priv->connector.display_info; + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, info); + preferred =3D find_preferred_mode(&priv->connector); + KUNIT_ASSERT_TRUE(test, drm_mode_is_420(info, preferred)); + + state =3D drm_kunit_helper_atomic_state_alloc(test, &priv->drm, &ctx); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state); + + conn_state =3D drm_atomic_get_connector_state(state, &priv->connector); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state); + + conn_state->color_format =3D param->fmt; + + ret =3D drm_atomic_set_crtc_for_connector(conn_state, priv->crtc); + KUNIT_ASSERT_EQ(test, ret, 0); + + crtc_state =3D drm_atomic_get_crtc_state(state, priv->crtc); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc_state); + + ret =3D drm_atomic_set_mode_for_crtc(crtc_state, preferred); + KUNIT_ASSERT_EQ(test, ret, 0); + + crtc_state->enable =3D true; + crtc_state->active =3D true; + + ret =3D drm_atomic_check_only(state); + KUNIT_EXPECT_EQ(test, ret, param->expected_ret); + KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_format, param->expected); + + drm_modeset_drop_locks(&ctx); + drm_modeset_acquire_fini(&ctx); +} + +static const struct color_format_test_param hdmi_color_format_params[] =3D= { + { + .fmt =3D DRM_CONNECTOR_COLOR_FORMAT_AUTO, + .expected =3D DRM_OUTPUT_COLOR_FORMAT_RGB444, + .expected_ret =3D 0, + .desc =3D "AUTO -> RGB" + }, + { + .fmt =3D DRM_CONNECTOR_COLOR_FORMAT_YCBCR422, + .expected =3D DRM_OUTPUT_COLOR_FORMAT_YCBCR422, + .expected_ret =3D 0, + .desc =3D "YCBCR422 -> YUV422" + }, + { + .fmt =3D DRM_CONNECTOR_COLOR_FORMAT_YCBCR420, + .expected =3D DRM_OUTPUT_COLOR_FORMAT_YCBCR420, + .expected_ret =3D 0, + .desc =3D "YCBCR420 -> YUV420" + }, + { + .fmt =3D DRM_CONNECTOR_COLOR_FORMAT_YCBCR444, + .expected =3D DRM_OUTPUT_COLOR_FORMAT_YCBCR444, + .expected_ret =3D 0, + .desc =3D "YCBCR444 -> YUV444" + }, + { + .fmt =3D DRM_CONNECTOR_COLOR_FORMAT_RGB444, + .expected =3D DRM_OUTPUT_COLOR_FORMAT_RGB444, + .expected_ret =3D 0, + .desc =3D "RGB -> RGB" + }, +}; + +KUNIT_ARRAY_PARAM_DESC(check_hdmi_color_format, hdmi_color_format_params, = desc); + +/* Test that if: + * - the HDMI connector supports RGB, YUV422, YUV420, and YUV444 + * - the display has a YUV420-only mode + * - the "color format" property is explicitly set (i.e. !AUTO) + * then: + * - color format DRM_CONNECTOR_COLOR_FORMAT_RGB444 will fail + * drm_atomic_check_only for the YUV420-only mode with -EINVAL + * - color format DRM_CONNECTOR_COLOR_FORMAT_YCBCR444 will fail + * drm_atomic_check_only for the YUV420-only mode with -EINVAL + * - color format DRM_CONNECTOR_COLOR_FORMAT_YCBCR422 will fail + * drm_atomic_check_only for the YUV420-only mode with -EINVAL + * - color format DRM_CONNECTOR_COLOR_FORMAT_YCBCR420 passes + * drm_atomic_check_only for the YUV420-only mode + */ +static void drm_test_check_hdmi_color_format_420_only(struct kunit *test) +{ + const struct color_format_test_param *param =3D test->param_value; + struct drm_atomic_helper_connector_hdmi_priv *priv; + struct drm_connector_state *conn_state; + struct drm_modeset_acquire_ctx ctx; + struct drm_crtc_state *crtc_state; + struct drm_atomic_state *state; + struct drm_display_mode *dank; + int ret; + + priv =3D drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test, + BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444) | + BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR422) | + BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR420) | + BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR444), + 12, + &dummy_connector_hdmi_funcs, + test_edid_hdmi_1080p_rgb_yuv_4k_yuv420_dc_max_200mhz); + KUNIT_ASSERT_NOT_NULL(test, priv); + + drm_modeset_acquire_init(&ctx, 0); + + dank =3D find_420_only_mode(&priv->connector); + KUNIT_ASSERT_NOT_NULL(test, dank); + + state =3D drm_kunit_helper_atomic_state_alloc(test, &priv->drm, &ctx); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state); + + conn_state =3D drm_atomic_get_connector_state(state, &priv->connector); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state); + + conn_state->color_format =3D param->fmt; + + ret =3D drm_atomic_set_crtc_for_connector(conn_state, priv->crtc); + KUNIT_ASSERT_EQ(test, ret, 0); + + crtc_state =3D drm_atomic_get_crtc_state(state, priv->crtc); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc_state); + + ret =3D drm_atomic_set_mode_for_crtc(crtc_state, dank); + KUNIT_ASSERT_EQ(test, ret, 0); + + crtc_state->enable =3D true; + crtc_state->active =3D true; + + ret =3D drm_atomic_check_only(state); + KUNIT_EXPECT_EQ(test, ret, param->expected_ret); + if (!param->expected_ret) + KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_format, param->expected); + + drm_modeset_drop_locks(&ctx); + drm_modeset_acquire_fini(&ctx); +}; + +static const struct color_format_test_param hdmi_color_format_420_only_par= ams[] =3D { + { + .fmt =3D DRM_CONNECTOR_COLOR_FORMAT_RGB444, + .expected =3D DRM_OUTPUT_COLOR_FORMAT_RGB444, + .expected_ret =3D -EINVAL, + .desc =3D "RGB should fail" + }, + { + .fmt =3D DRM_CONNECTOR_COLOR_FORMAT_YCBCR444, + .expected =3D DRM_OUTPUT_COLOR_FORMAT_YCBCR444, + .expected_ret =3D -EINVAL, + .desc =3D "YUV444 should fail" + }, + { + .fmt =3D DRM_CONNECTOR_COLOR_FORMAT_YCBCR422, + .expected =3D DRM_OUTPUT_COLOR_FORMAT_YCBCR422, + .expected_ret =3D -EINVAL, + .desc =3D "YUV422 should fail" + }, + { + .fmt =3D DRM_CONNECTOR_COLOR_FORMAT_YCBCR420, + .expected =3D DRM_OUTPUT_COLOR_FORMAT_YCBCR420, + .expected_ret =3D 0, + .desc =3D "YUV420 should work" + }, +}; + +KUNIT_ARRAY_PARAM_DESC(check_hdmi_color_format_420_only, + hdmi_color_format_420_only_params, desc); + static struct kunit_case drm_atomic_helper_connector_hdmi_check_tests[] = =3D { KUNIT_CASE(drm_test_check_broadcast_rgb_auto_cea_mode), KUNIT_CASE(drm_test_check_broadcast_rgb_auto_cea_mode_vic_1), @@ -2227,6 +2459,10 @@ static struct kunit_case drm_atomic_helper_connector= _hdmi_check_tests[] =3D { KUNIT_CASE(drm_test_check_tmds_char_rate_rgb_8bpc), KUNIT_CASE(drm_test_check_tmds_char_rate_rgb_10bpc), KUNIT_CASE(drm_test_check_tmds_char_rate_rgb_12bpc), + KUNIT_CASE_PARAM(drm_test_check_hdmi_color_format, + check_hdmi_color_format_gen_params), + KUNIT_CASE_PARAM(drm_test_check_hdmi_color_format_420_only, + check_hdmi_color_format_420_only_gen_params), /* * TODO: We should have tests to check that a change in the * format triggers a CRTC mode change just like we do for the --=20 2.53.0