From patchwork Thu Jul 23 01:35:45 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Cristian Ciocaltea X-Patchwork-Id: 2779 Return-Path: X-Original-To: noreply@patchwork.local Delivered-To: noreply@patchwork.local Received: from sea.lore.kernel.org (sea.lore.kernel.org [172.234.253.10]) by mxe881.netcup.net (Postfix) with ESMTPS id C922E1C2B5B for ; Thu, 23 Jul 2026 03:46:08 +0200 (CEST) Authentication-Results: mxe881; dkim=pass header.d=collabora.com; spf=pass (sender IP is 172.234.253.10) smtp.mailfrom=linux-sunxi+bounces-24696-noreply=patchwork.local@lists.linux.dev smtp.helo=sea.lore.kernel.org Received-SPF: pass (mxe881: domain of lists.linux.dev designates 172.234.253.10 as permitted sender) client-ip=172.234.253.10; envelope-from=linux-sunxi+bounces-24696-noreply=patchwork.local@lists.linux.dev; helo=sea.lore.kernel.org; Received: from smtp.subspace.kernel.org (conduit.subspace.kernel.org [100.90.174.1]) by sea.lore.kernel.org (Postfix) with ESMTP id 2E18330E058E for ; Thu, 23 Jul 2026 01:40:00 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id BE6203812F1; Thu, 23 Jul 2026 01:35:45 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=collabora.com header.i=@collabora.com header.b="Yaznco3S" X-Original-To: linux-sunxi@lists.linux.dev Received: from bali.collaboradmins.com (bali.collaboradmins.com [148.251.105.195]) (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 E3AD237DEA4 for ; Thu, 23 Jul 2026 01:35:42 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=148.251.105.195 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784770545; cv=none; b=U8+evl2vePjtQFLQGr/psrg82qNmBG9GFOdXWoL09WMsQWCRxaDN1nv4TWqYitYZPC9KYFj041xdCIi/pNYGctzO/jBB0CLDmHfdyt/0+TTR8Xde4X0v2i+y+rDZhfG5yfGIgZ0pUu6UJYeXz7G1uIyrquKWRGzbdj1Yv8O4ujw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784770545; c=relaxed/simple; bh=1Vzn7su6rOQ52y73RK6RVJhKKl0bPsG7lJ3gcEDnl2w=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=rdqDKIEtCv7o91gmjTunsxbSANCn8RNtgcEh5bHtrZFcajBU+UO7ONIa+rCqODzjKxpX43rTH4UIsKVM+j28rUNKS6MH/Gj3EgZIAPXdjvXnFX6RHHPEPQ/lEwXdQ0Tth2M+mBOnbHynrooLn8+chlx3u5HP5seFRj2cIgxRayw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=collabora.com; spf=pass smtp.mailfrom=collabora.com; dkim=pass (2048-bit key) header.d=collabora.com header.i=@collabora.com header.b=Yaznco3S; arc=none smtp.client-ip=148.251.105.195 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 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=collabora.com; s=mail; t=1784770541; bh=1Vzn7su6rOQ52y73RK6RVJhKKl0bPsG7lJ3gcEDnl2w=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=Yaznco3S6ClKua9KFEbmIqEHoIlj5CSdw+xwqWojr4os+YCa2OLwqRcZ7S2wu2C8F Ljs3jC4MlBjI7Clf5tLj1RSDQI6VwHTnhBeFJIozPGGLo7sM3+DRqcsyj3eZwZLojv XHFodnFzc0TK6CFAj6Rbxw1Cv4qSYsIlcVQhKQIvZW6myknrtdBD7VnIOptk6l9Ula z+NO3VL/zqQjzomoI53epz4TEZVXAT2XEr/NcKlmtvxC3UhfkR+A/dgIj9VhyTySfP KU5B0k2NWSbATiwluRW/NRDIGGLZzpxa9e7u0apHi3xJfmVR9hVRnCLHSIEs2cbxg3 FX+myUkDFrDeA== Received: from localhost (unknown [100.64.0.241]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange secp256r1 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) (Authenticated sender: cristicc) by bali.collaboradmins.com (Postfix) with ESMTPSA id 1886017E0857; Thu, 23 Jul 2026 03:35:41 +0200 (CEST) From: Cristian Ciocaltea Date: Thu, 23 Jul 2026 04:35:45 +0300 Subject: [PATCH v9 56/61] drm/tests: hdmi_state_helper: Add connector-provided max_tmds_char_rate coverage Precedence: bulk X-Mailing-List: linux-sunxi@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20260723-dw-hdmi-qp-scramb-v9-56-4fb12ea22ac9@collabora.com> References: <20260723-dw-hdmi-qp-scramb-v9-0-4fb12ea22ac9@collabora.com> In-Reply-To: <20260723-dw-hdmi-qp-scramb-v9-0-4fb12ea22ac9@collabora.com> To: Andrzej Hajda , Neil Armstrong , Robert Foss , Laurent Pinchart , Jonas Karlman , Jernej Skrabec , Luca Ceresoli , Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , David Airlie , Simona Vetter , Chen-Yu Tsai , Samuel Holland , Dave Stevenson , =?utf-8?q?Ma=C3=ADra_Canal?= , Raspberry Pi Kernel Maintenance , Sandy Huang , =?utf-8?q?Heiko_St=C3=BCbner?= , Andy Yan , Algea Cao , Daniel Stone , Liu Ying , Phong LE Cc: kernel@collabora.com, linux-kernel@vger.kernel.org, dri-devel@lists.freedesktop.org, linux-arm-kernel@lists.infradead.org, linux-sunxi@lists.linux.dev, linux-rockchip@lists.infradead.org X-Mailer: b4 0.15.2 X-MORS-Enabled: yes X-MORS-DOMAIN: patchwork.local X-MORS-HOSTING: hosting172546 X-MORS-USER: hosting172546 X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= Test the hdmi_clock_valid() logic that rejects modes whose TMDS character rate exceeds connector->hdmi.max_tmds_char_rate. Exercise both an explicit limit set through drm_connector_hdmi_funcs' supported_tmds_char_rate and the limit inferred from supported_hdmi_ver. Also verify that a driver hook can further restrict the connector limit. Signed-off-by: Cristian Ciocaltea --- drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c | 116 +++++++++++++++++++++ 1 file changed, 116 insertions(+) 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 478c4b6c6207..6410eca57a99 100644 --- a/drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c +++ b/drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c @@ -189,6 +189,32 @@ static const struct drm_connector_hdmi_funcs reject_100mhz_connector_hdmi_funcs }, }; +static enum drm_mode_status +accept_any_connector_tmds_char_rate_valid(const struct drm_connector *connector, + const struct drm_display_mode *mode, + unsigned long long tmds_rate) +{ + return MODE_OK; +} + +static const struct drm_connector_hdmi_funcs reject_over_165mhz_connector_hdmi_funcs = { + .vendor = "Vendor", + .product = "Product", + .supported_hdmi_ver = HDMI_VERSION_1_3, + .supported_tmds_char_rate = HDMI_1_0_TMDS_CHAR_RATE_MAX_HZ, + .supported_formats = BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444), + .max_bpc = 8, + .tmds_char_rate_valid = accept_any_connector_tmds_char_rate_valid, + .avi = { + .clear_infoframe = accept_infoframe_clear_infoframe, + .write_infoframe = accept_infoframe_write_infoframe, + }, + .hdmi = { + .clear_infoframe = accept_infoframe_clear_infoframe, + .write_infoframe = accept_infoframe_write_infoframe, + }, +}; + static int dummy_connector_get_modes(struct drm_connector *connector) { struct drm_atomic_helper_connector_hdmi_priv *priv = @@ -2751,6 +2777,93 @@ static void drm_test_check_mode_valid_reject_max_clock(struct kunit *test) KUNIT_EXPECT_EQ(test, preferred->clock, 25200); } +/* + * Test that the max_tmds_char_rate inferred from caps.supported_hdmi_ver + * is applied as a mode-filtering limit: with an HDMI 1.3 connector and no + * driver hook, drm_hdmi_connector_mode_valid() will reject modes whose TMDS + * character rate exceeds 340 MHz, even though the sink itself advertises + * a higher limit (600 MHz). + */ +static void +drm_test_check_mode_valid_reject_inferred_max_tmds_char_rate(struct kunit *test) +{ + struct drm_connector_hdmi_funcs hdmi_funcs = dummy_connector_hdmi_funcs; + struct drm_atomic_helper_connector_hdmi_priv *priv; + struct drm_display_mode *preferred; + + hdmi_funcs.supported_hdmi_ver = HDMI_VERSION_1_3; + + priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test, &hdmi_funcs, + test_edid_hdmi_4k_rgb_yuv420_dc_max_600mhz); + KUNIT_ASSERT_NOT_NULL(test, priv); + + KUNIT_ASSERT_EQ(test, priv->connector.hdmi.max_tmds_char_rate, + HDMI_1_3_TMDS_CHAR_RATE_MAX_HZ); + + preferred = find_preferred_mode(&priv->connector); + KUNIT_ASSERT_NOT_NULL(test, preferred); + KUNIT_EXPECT_EQ(test, preferred->hdisplay, 2560); + KUNIT_EXPECT_EQ(test, preferred->vdisplay, 1600); + KUNIT_EXPECT_EQ(test, preferred->clock, 268500); +} + +/* + * Test that a connector-provided max_tmds_char_rate limit (165 MHz) takes + * precedence over a permissive .tmds_char_rate_valid() driver hook and + * drm_hdmi_connector_mode_valid() will reject modes whose computed TMDS + * character exceeds the connector limit. + */ +static void +drm_test_check_mode_valid_connector_max_tmds_char_rate_precedes_driver_hook(struct kunit *test) +{ + struct drm_atomic_helper_connector_hdmi_priv *priv; + struct drm_display_mode *preferred; + + priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test, + &reject_over_165mhz_connector_hdmi_funcs, + test_edid_hdmi_4k_rgb_yuv420_dc_max_600mhz); + KUNIT_ASSERT_NOT_NULL(test, priv); + + KUNIT_ASSERT_EQ(test, priv->connector.hdmi.max_tmds_char_rate, + HDMI_1_0_TMDS_CHAR_RATE_MAX_HZ); + + preferred = find_preferred_mode(&priv->connector); + KUNIT_ASSERT_NOT_NULL(test, preferred); + KUNIT_EXPECT_EQ(test, preferred->hdisplay, 2048); + KUNIT_EXPECT_EQ(test, preferred->vdisplay, 1152); + KUNIT_EXPECT_EQ(test, preferred->clock, 162000); +} + +/* + * Test that a connector-provided max_tmds_char_rate (165 MHz) can be further + * limited by a more restrictive (100 MHz) .tmds_char_rate_valid() driver hook + * and drm_hdmi_connector_mode_valid() will reject modes whose computed TMDS + * character exceeds the hook limit. + */ +static void +drm_test_check_mode_valid_driver_hook_limits_connector_max_tmds_char_rate(struct kunit *test) +{ + struct drm_connector_hdmi_funcs hdmi_funcs = reject_100mhz_connector_hdmi_funcs; + struct drm_atomic_helper_connector_hdmi_priv *priv; + struct drm_display_mode *preferred; + + hdmi_funcs.supported_hdmi_ver = HDMI_VERSION_1_3; + hdmi_funcs.supported_tmds_char_rate = HDMI_1_0_TMDS_CHAR_RATE_MAX_HZ; + + priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test, &hdmi_funcs, + test_edid_hdmi_4k_rgb_yuv420_dc_max_600mhz); + KUNIT_ASSERT_NOT_NULL(test, priv); + + KUNIT_ASSERT_EQ(test, priv->connector.hdmi.max_tmds_char_rate, + HDMI_1_0_TMDS_CHAR_RATE_MAX_HZ); + + preferred = find_preferred_mode(&priv->connector); + KUNIT_ASSERT_NOT_NULL(test, preferred); + KUNIT_EXPECT_EQ(test, preferred->hdisplay, 1440); + KUNIT_EXPECT_EQ(test, preferred->vdisplay, 900); + KUNIT_EXPECT_EQ(test, preferred->clock, 88750); +} + /* * Test that drm_hdmi_connector_mode_valid() will accept modes that require a * 4:2:0 chroma subsampling, even if said mode would violate maximum clock @@ -2841,6 +2954,9 @@ static struct kunit_case drm_atomic_helper_connector_hdmi_mode_valid_tests[] = { KUNIT_CASE(drm_test_check_mode_valid_reject), KUNIT_CASE(drm_test_check_mode_valid_reject_rate), KUNIT_CASE(drm_test_check_mode_valid_reject_max_clock), + KUNIT_CASE(drm_test_check_mode_valid_reject_inferred_max_tmds_char_rate), + KUNIT_CASE(drm_test_check_mode_valid_connector_max_tmds_char_rate_precedes_driver_hook), + KUNIT_CASE(drm_test_check_mode_valid_driver_hook_limits_connector_max_tmds_char_rate), KUNIT_CASE(drm_test_check_mode_valid_yuv420_only_max_clock), KUNIT_CASE(drm_test_check_mode_valid_reject_yuv420_only_connector), KUNIT_CASE(drm_test_check_mode_valid_accept_yuv420_also_connector_rgb),