From patchwork Tue Sep 1 18:51:38 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Cristian Ciocaltea X-Patchwork-Id: 3112 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 3A8241C3C0F for ; Tue, 1 Sep 2026 21:17:28 +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-25464-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-25464-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 988EA14355D for ; Tue, 1 Sep 2026 18:59:15 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id A9A724AA41D; Tue, 1 Sep 2026 18:51:44 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=collabora.com header.i=@collabora.com header.b="IkpTEUb6" 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 09F364AA01F for ; Tue, 1 Sep 2026 18:51:37 +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=1788288703; cv=none; b=o/dJgavJvUfy3GndROYekFd+YekJ+GVHgR6ZmbY64iW+q+TrepWZalqTqQ+jQoitStjS8xYMa9C6u2wPePViGhppB6KGRGniypmK3a/yY22U5kStukfj3QoLgE/NIsQjMytb3ddodEkQpt0rXV4uzsb93G8vI1jhs4nmbT1eKvE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788288703; c=relaxed/simple; bh=cihigF4VnR53Ld2/oM7OfeYgsP2+G6E2xvoDukRhIWk=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=I9eH9TRc70gqiI/FbMbSOZhMdTWNe5rcm55qZpGXxAS4sYkxx8+rga54m2dHtW0rmNj8RZs6BqWlwXI3w5oYXxBSfx76d4U0o53PQUCxUoe/ktALGQ9abUnPRRMXFjosNVQLq5vF4qhinDFzzTqLeq10KSMtZ40aNIr6HjyGIdc= 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=IkpTEUb6; 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=1788288695; bh=cihigF4VnR53Ld2/oM7OfeYgsP2+G6E2xvoDukRhIWk=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=IkpTEUb6bF0P7+vfKu6YN5lXXxM1DUVGzB+Yuadf0Kr5klRniY5bc/k97wSFu5aLF 5uXVeEItUgakdpz+080O6B84iGh9YnK9IVrMYv3+Gh0E2KC3bxctEQMSXqxg9+ZTLH x795Dco/PhLNHuz9pJPJt1cSRiPlYy+FhRwJfBdcHBxyCd7oZrlsSpV952u5SFHNS+ j1XQo0Qi8YM7ImZYEle6mfBHBA0rx9PEwpOmTRyyqIVGKa8aWtAi8+UPdzvZ0lGccx +G+QN5aAxOga9DfwngAr+NuJS/GbErWNh6wZAkRNDRrqquvYILeztOWG87qG9Cc+ne gy3IXM928jFsw== 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 7B59717E3CAB; Tue, 01 Sep 2026 20:51:35 +0200 (CEST) From: Cristian Ciocaltea Date: Tue, 01 Sep 2026 21:51:38 +0300 Subject: [PATCH v11 74/74] drm/tests: hdmi: Add SPD InfoFrame vendor/product 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-74-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?= The vendor and product strings provided through struct drm_connector_hdmi_funcs end up in the SPD InfoFrame, whose fields are defined by the HDMI specification as fixed-size: 8 bytes for the vendor name and 16 bytes for the product description, padded with zeros and left without any trailing NUL when a name spans the whole field. Nothing exercises that so far, since the SPD InfoFrame is only generated for connectors implementing the related hooks, which none of the existing test funcs provides. Add a connector variant supplying those hooks, along with parametrized tests covering both the padded and the exact length cases. Signed-off-by: Cristian Ciocaltea --- drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c | 164 ++++++++++++++++++++- 1 file changed, 163 insertions(+), 1 deletion(-) 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 68b442c32a2a..415d82e75eaa 100644 --- a/drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c +++ b/drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c @@ -3205,6 +3205,167 @@ static void drm_test_check_infoframes(struct kunit *test) drm_modeset_acquire_fini(&ctx); } +struct drm_hdmi_spd_infoframe_test { + const char *name; + const char *vendor; + const char *product; + unsigned char expected_vendor[HDMI_SPD_INFOFRAME_VENDOR_LEN]; + unsigned char expected_product[HDMI_SPD_INFOFRAME_PRODUCT_LEN]; +}; + +static const struct drm_hdmi_spd_infoframe_test drm_hdmi_spd_infoframe_tests[] = { + { + .name = "shorter-than-field", + .vendor = "Vend", + .product = "Prod", + .expected_vendor = { 'V', 'e', 'n', 'd' }, + .expected_product = { 'P', 'r', 'o', 'd' }, + }, + { + .name = "whole-field", + .vendor = "VendorVe", + .product = "ProductProductPr", + .expected_vendor = { + 'V', 'e', 'n', 'd', 'o', 'r', 'V', 'e', + }, + .expected_product = { + 'P', 'r', 'o', 'd', 'u', 'c', 't', + 'P', 'r', 'o', 'd', 'u', 'c', 't', + 'P', 'r', + }, + }, +}; + +static void drm_hdmi_spd_infoframe_desc(const struct drm_hdmi_spd_infoframe_test *t, + char *desc) +{ + strscpy(desc, t->name, KUNIT_PARAM_DESC_SIZE); +} + +KUNIT_ARRAY_PARAM(drm_hdmi_spd_infoframe, drm_hdmi_spd_infoframe_tests, + drm_hdmi_spd_infoframe_desc); + +/* + * The SPD InfoFrame is only generated for connectors implementing the + * related hooks, hence the SPD tests cannot rely on the plain dummy funcs. + */ +static const struct drm_connector_hdmi_funcs dummy_connector_hdmi_spd_funcs = { + .vendor = "Vendor", + .product = "Product", + .supported_hdmi_ver = HDMI_VERSION_1_4, + .supported_formats = BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444), + .max_bpc = 8, + .avi = { + .clear_infoframe = accept_infoframe_clear_infoframe, + .write_infoframe = accept_infoframe_write_infoframe, + }, + .spd = { + .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, + }, +}; + +/* + * Test that the vendor and product names end up in the SPD InfoFrame padded + * with zeros, and without any trailing NUL when spanning the whole field. + */ +static void drm_test_check_spd_infoframe(struct kunit *test) +{ + const struct drm_hdmi_spd_infoframe_test *param = test->param_value; + struct drm_connector_hdmi_funcs hdmi_funcs = dummy_connector_hdmi_spd_funcs; + 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_commit *state; + struct drm_display_mode *preferred; + struct hdmi_spd_infoframe *frame; + struct drm_connector *conn; + struct drm_device *drm; + struct drm_crtc *crtc; + int ret; + + hdmi_funcs.vendor = param->vendor; + hdmi_funcs.product = param->product; + + priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test, + &hdmi_funcs, + test_edid_hdmi_1080p_rgb_max_200mhz); + KUNIT_ASSERT_NOT_NULL(test, priv); + + drm = &priv->drm; + crtc = priv->crtc; + conn = &priv->connector; + + preferred = find_preferred_mode(conn); + KUNIT_ASSERT_NOT_NULL(test, preferred); + + 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_ASSERT_EQ(test, ret, 0); + + 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_commit_clear(state); + ret = drm_modeset_backoff(&ctx); + if (!ret) + goto retry_crtc_state; + } + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc_state); + + crtc_state->mode_changed = true; + + ret = drm_atomic_check_only(state); + if (ret == -EDEADLK) { + drm_atomic_commit_clear(state); + ret = drm_modeset_backoff(&ctx); + if (!ret) + goto retry_crtc_state; + } + KUNIT_ASSERT_EQ(test, ret, 0); + + ret = drm_atomic_commit(state); + if (ret == -EDEADLK) { + drm_atomic_commit_clear(state); + ret = drm_modeset_backoff(&ctx); + if (!ret) + goto retry_crtc_state; + } + KUNIT_ASSERT_EQ(test, ret, 0); + + conn_state = conn->state; + KUNIT_ASSERT_NOT_NULL(test, conn_state); + KUNIT_ASSERT_TRUE(test, conn_state->hdmi.infoframes.spd.set); + + frame = &conn_state->hdmi.infoframes.spd.data.spd; + + KUNIT_EXPECT_MEMEQ(test, frame->vendor, param->expected_vendor, + sizeof(frame->vendor)); + KUNIT_EXPECT_MEMEQ(test, frame->product, param->expected_product, + sizeof(frame->product)); + + drm_modeset_drop_locks(&ctx); + drm_modeset_acquire_fini(&ctx); +} + static int reject_infoframe_write_infoframe(struct drm_connector *connector, const u8 *buffer, size_t len) { @@ -3723,9 +3884,10 @@ static void drm_test_check_reject_audio_infoframe(struct kunit *test) drm_modeset_acquire_fini(&ctx); } - static struct kunit_case drm_atomic_helper_connector_hdmi_infoframes_tests[] = { KUNIT_CASE(drm_test_check_infoframes), + KUNIT_CASE_PARAM(drm_test_check_spd_infoframe, + drm_hdmi_spd_infoframe_gen_params), KUNIT_CASE(drm_test_check_reject_avi_infoframe), KUNIT_CASE(drm_test_check_reject_hdr_infoframe_bpc_8), KUNIT_CASE(drm_test_check_reject_hdr_infoframe_bpc_10),