From patchwork Tue Sep 1 18:51:30 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Cristian Ciocaltea X-Patchwork-Id: 3125 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 99BBA1C0247 for ; Tue, 1 Sep 2026 21:47:09 +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-25455-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-25455-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 E4FDA1425E4 for ; Tue, 1 Sep 2026 18:58:26 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id BAE8E4AA00D; Tue, 1 Sep 2026 18:51:36 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=collabora.com header.i=@collabora.com header.b="c57xhHIF" 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 7DAD84A5EBC for ; Tue, 1 Sep 2026 18:51:32 +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=1788288695; cv=none; b=jsERV8swlIxrpAr4GZ5o4NSTMyzVlLj9ICVO6J+b6fonysom67Wv03h3e07HmpmUh8YBHtaAUro/uYPxtqTc/jYFEllYDYiDbPUl0vsdj/I2oL1DLZHV3sFm5O+GCfr2Pz1D1SKLVXUZPBagkf5yWB43ximCt5SNBdfgeUm2ps0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788288695; c=relaxed/simple; bh=kA6nVSOFOk0yymzKaCCJLaqlyDMieIsqeSwOvsCsQw8=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=bjOIshNZffp3x/itLm7dANsVpAx2iEg1jqhZ821KYDXVVy6mgN0ekIiwdITVxGX3UplDGPywUiYK6KVntxoEPFR9P5jZwSKUG8cu1sCG2XFnw5sYlI+GIKvKR65/hv2WPBgdwUM9ZxEjvpi+mtM+6pejuqRg+6yqLjjg+Tmyxc0= 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=c57xhHIF; 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=1788288689; bh=kA6nVSOFOk0yymzKaCCJLaqlyDMieIsqeSwOvsCsQw8=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=c57xhHIFq3DY9IHh4Hg/QyaXNkgTQfPfL1l8uzFPTN5oOX8HY68DcCmeq4StTiACY F9Cnzu6tNikSDvu/tEwHBEY+h1zz1bUwLNqWQ/0UTSjcS/3f5FVorHz6i0iw7/ShuA 5mIVpVhPg5pBOJf63PJ/M5G4fc9qL9CVoJFjV247OaCm1gHTWCPEXlvLE3/1ItLB5/ aTh7YRJRnpaHjovLBvbcCan5izg1pslEDHJWYezDJ/2BjDwUKOxEmRahJbNqUPmsnw eVNkN5PoJWIWiFBq4Ye19jizfG8q6ZjZFAI0AoFJD9edhXXySofL8uh6ZPYoDbOf7J O8Kc5fHzwfJtQ== 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 9E5A317E3C99; Tue, 01 Sep 2026 20:51:29 +0200 (CEST) From: Cristian Ciocaltea Date: Tue, 01 Sep 2026 21:51:30 +0300 Subject: [PATCH v11 66/74] 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: <20260901-dw-hdmi-qp-scramb-v11-66-bc12954a0688@collabora.com> References: <20260901-dw-hdmi-qp-scramb-v11-0-bc12954a0688@collabora.com> In-Reply-To: <20260901-dw-hdmi-qp-scramb-v11-0-bc12954a0688@collabora.com> To: Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , David Airlie , Simona Vetter , Dave Stevenson , Dmitry Baryshkov , Andrzej Hajda , Neil Armstrong , Robert Foss , Laurent Pinchart , Jonas Karlman , Jernej Skrabec , Luca Ceresoli , Chen-Yu Tsai , Samuel Holland , =?utf-8?q?Ma=C3=ADra_Canal?= , Raspberry Pi Kernel Maintenance , Raphael Gallais-Pou , Sandy Huang , =?utf-8?q?Heiko_St=C3=BCbner?= , Andy Yan , Algea Cao , Daniel Stone , Liu Ying , Phong LE , Helge Deller 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, linux-fbdev@vger.kernel.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 f35dc31326bc..6d648332aa15 100644 --- a/drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c +++ b/drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c @@ -190,6 +190,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 = @@ -2753,6 +2779,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 @@ -2843,6 +2956,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),