From nobody Mon Feb 9 13:38:43 2026 Received: from mx0a-0031df01.pphosted.com (mx0a-0031df01.pphosted.com [205.220.168.131]) (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 EF73A3559EB for ; Wed, 7 Jan 2026 18:15:08 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=205.220.168.131 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1767809711; cv=none; b=AKBGFTBKsn08Gv3U5tzmrrJ7dyOnwvcO9GsoSyo7AyZ09OGQhFoBLMUuBmMYdqJcw7e8SAfWa19kkHeoBGCKvAaiwUrtHMI0WAxgZyrAGSet9gstd9mjN3s17JlbthJ5xdPrqxsn7Lw6tY7gekiDuO83dOhyBOULfyekl7WPmss= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1767809711; c=relaxed/simple; bh=XZUiI+P1J2mQYMmzuj2kKLbF6PlyfBdfsh+uTUhKM3o=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=sqT7ZdRZpxn+lYygEUy3ImjRvptQqA3h7cFAsaOspw41FSNyK8aR9ZdffODJAW/Fg1aK5lk853H2F87F7UIoLjqmu2i3KCGstRmIWMqNJGgOokM5nQXDcn6J7Zr/G6hxtdbXX1uH/ArWX7zh6oqEercjd2Nk7A+ubZ0zb5Cug/I= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=oss.qualcomm.com; spf=pass smtp.mailfrom=oss.qualcomm.com; dkim=pass (2048-bit key) header.d=qualcomm.com header.i=@qualcomm.com header.b=XjdPzI+v; dkim=pass (2048-bit key) header.d=oss.qualcomm.com header.i=@oss.qualcomm.com header.b=jx/I/W70; arc=none smtp.client-ip=205.220.168.131 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=oss.qualcomm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=oss.qualcomm.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=qualcomm.com header.i=@qualcomm.com header.b="XjdPzI+v"; dkim=pass (2048-bit key) header.d=oss.qualcomm.com header.i=@oss.qualcomm.com header.b="jx/I/W70" Received: from pps.filterd (m0279866.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id 607H3vch3049898 for ; Wed, 7 Jan 2026 18:15:08 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=qualcomm.com; h= cc:content-transfer-encoding:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to; s=qcppdkim1; bh= pPEqdfktaAHE/Jjjjm6RwHrVcZ7AZ3stnlHc40P42b8=; b=XjdPzI+vprat0Amv gwL3eg4VCPgxWlfP8SP+gmGcQl0yvekPl5SWJ98dXB9sRWjAFvjVdTlLxe8EsDSa bCbSdg7e/6q1v+hHAmq4FOhGOMqEm8eC0vubYxM8GJOK1yBCU/+errTsYHLWBhIk SFPQ4E2fTMzd2tn97gEbpm63rCCzXLmxJ8fjRb4dljA39rjJzOk3p/bPKBc/vyq8 qMbVmKT2l6RFKdu7HoY5DkvrKKkyxuMxaoYPucTRUJI5xhq1v5KKECgSmo+ZDHto nL4i/tijX5o6Fw3wwCPH4i+Bgdnp1Qo1AS/xhUU6LQ28J/eDkz8qaF+rDPVZz9CJ KR6m0A== Received: from mail-qk1-f200.google.com (mail-qk1-f200.google.com [209.85.222.200]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 4bhujeg8ha-1 (version=TLSv1.3 cipher=TLS_AES_128_GCM_SHA256 bits=128 verify=NOT) for ; Wed, 07 Jan 2026 18:15:07 +0000 (GMT) Received: by mail-qk1-f200.google.com with SMTP id af79cd13be357-8c1fa4a1c18so565760285a.3 for ; Wed, 07 Jan 2026 10:15:07 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=oss.qualcomm.com; s=google; t=1767809707; x=1768414507; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=pPEqdfktaAHE/Jjjjm6RwHrVcZ7AZ3stnlHc40P42b8=; b=jx/I/W70CMD585oBD7B5ZACwusYTCyqoKfkUVkd+pVhYGzkzB+udCnkl11nGzS4wHM qbJTrZNYS+r9SvDRd52OZBVtdDRJNiRdUNDw02lsN/9VEgazNoESpY9T1Bcmc/6VWuTR KqhCUXf8uKECXGNCSE3oLklKX+SCHjDaTBMZ+77btg+Vq3K6s2Eo85bkCmlqKcZ8m2X7 n3fWp73d/NCS2nXQi59knW+KReIwKGEfEEDqREJyxFrzWqhUQKs9+TFZfwwqcywTZ14o YqHorpfDqn90ggRC6G0KpEZteqos895l/ASGUNt5Y6en7gKMXxOYcoaaCmUxxKTyiYrm axrA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1767809707; x=1768414507; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to; bh=pPEqdfktaAHE/Jjjjm6RwHrVcZ7AZ3stnlHc40P42b8=; b=pQfFxsVkFFlKZ9z7p7o6Ou9ZCgd5krl9qyctkgUSsfvM0y8oaMZ60EyLA9oXkDofYr L24Tsm22FkD72mXX3E1s+zQodIUjh0lkze/0yGAAyY9+CKQhpcbxxF061PSdIHtRnTfS vf7Hhsw4qGdf59FbfU3J/l5bhJ1Sp/kHtM/dsUFwFvq4BMhsoXIWeKH5WqiDv/5E0d8M GKL1bNQ6QLnSAv98L15PzFExjZisZpcFXMcGHwVMFDpsVS39pyBiZ2jmRFkN2jJTFFfe FpTUK9Rl+JhPkVKcHZVKc/D45YXswZoFucUthRAAVmfdL77jQ348zI4UtXBcNn9uFxHo a3MQ== X-Forwarded-Encrypted: i=1; AJvYcCWbys5tNQymL5k2mx+7lWxHWrldJBejX5b4hm46jFf9LsqTHNGsahK4rR/2VpnKVPbHJx/1K/2jLIVF9g0=@vger.kernel.org X-Gm-Message-State: AOJu0YymHlZT3ROMKPVZziSmFo7ckEEXZZLXyHic2vWMi6cf9+IFzyn6 c1MXir4w+yQTGADlZ6cIzth5EH8zyO+KBR9d+gC92ABosTv6qeoz8UIQHRHzj39hzHDRZDSYdJq ZufSckX2lgZ8SVwXvxHRBPAY4Cm6qK1rRJK15+IinQS/SfZWWH9GJywoZDuJr3/6TWzA= X-Gm-Gg: AY/fxX5b4vBGDcIYiARc6tBjuOJGxlnW15SRH2HcSMBSKY8wBDYJJiRKNyoFtEbk1NK CD3fxhKrtWZNErf0rIbKt2+gDCwaV/xlbGpi0o8f306iIx1eSl6Mo4BcOncQAI5BaRH8AAqz/3Y lORgbr71ftjEJE/MwBf9r9o6dEPK9vJcMpPm/efGfgyHMvjte+ms2KM7qhqtaZnaxd8itC8Yw8k 6T8aAv21hJ/V+LRhsbTMdJnSVhzY/YF510LvCnONrHeRSXLdLhnHYR5XCjy4CmtYsdAlpxU3nb3 pEksCJWws6sSP8MGy3Fem4i01Acmk9UBhJc96Xm9WWA2teS6RtUp1ZshEHCwBrj6caKKM6Mh+JW DzMWVtB0mVjy4rLRWbJoHX2yQgvJjQL3dPbRZDcr/DyHfEmpaOPvZxQzlh8EM2yYIzsjbkHltew nu4gyAEjsR9QXLyWnS1mhy7+g= X-Received: by 2002:a05:620a:711c:b0:8c0:cca6:8522 with SMTP id af79cd13be357-8c38939ce29mr472851085a.37.1767809706532; Wed, 07 Jan 2026 10:15:06 -0800 (PST) X-Google-Smtp-Source: AGHT+IE0AzgUocYSZpm2KC5Ln3K9tzKrPT4erDK/yC4UWYZHbUCAGZhC15uqj5QHGP7DsMDQRvR3PA== X-Received: by 2002:a05:620a:711c:b0:8c0:cca6:8522 with SMTP id af79cd13be357-8c38939ce29mr472830885a.37.1767809704473; Wed, 07 Jan 2026 10:15:04 -0800 (PST) Received: from umbar.lan (2001-14ba-a073-af00-264b-feff-fe8b-be8a.rev.dnainternet.fi. [2001:14ba:a073:af00:264b:feff:fe8b:be8a]) by smtp.gmail.com with ESMTPSA id 2adb3069b0e04-59b65d6988asm1436884e87.80.2026.01.07.10.15.03 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 07 Jan 2026 10:15:03 -0800 (PST) From: Dmitry Baryshkov Date: Wed, 07 Jan 2026 20:14:58 +0200 Subject: [PATCH v4 01/10] drm/tests: hdmi: check the infoframes behaviour 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: <20260107-limit-infoframes-2-v4-1-213d0d3bd490@oss.qualcomm.com> References: <20260107-limit-infoframes-2-v4-0-213d0d3bd490@oss.qualcomm.com> In-Reply-To: <20260107-limit-infoframes-2-v4-0-213d0d3bd490@oss.qualcomm.com> To: Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , David Airlie , Simona Vetter , Dave Stevenson , =?utf-8?q?Ma=C3=ADra_Canal?= , Raspberry Pi Kernel Maintenance , Chen-Yu Tsai , Jernej Skrabec , Samuel Holland , Andrzej Hajda , Neil Armstrong , Robert Foss , Laurent Pinchart , Jonas Karlman , Liu Ying , Chun-Kuang Hu , Philipp Zabel , Matthias Brugger , AngeloGioacchino Del Regno , Rob Clark , Dmitry Baryshkov , Abhinav Kumar , Jessica Zhang , Sean Paul , Marijn Suijten , Sandy Huang , =?utf-8?q?Heiko_St=C3=BCbner?= , Andy Yan Cc: dri-devel@lists.freedesktop.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-sunxi@lists.linux.dev, linux-mediatek@lists.infradead.org, linux-arm-msm@vger.kernel.org, freedreno@lists.freedesktop.org, linux-rockchip@lists.infradead.org X-Mailer: b4 0.14.3 X-Developer-Signature: v=1; a=openpgp-sha256; l=26900; i=dmitry.baryshkov@oss.qualcomm.com; h=from:subject:message-id; bh=XZUiI+P1J2mQYMmzuj2kKLbF6PlyfBdfsh+uTUhKM3o=; b=owEBbQGS/pANAwAKAYs8ij4CKSjVAcsmYgBpXqKk/8Nl7ok1dk6fEgJIBY2eHmOcgrrVbCdGg 4G/w01IwRGJATMEAAEKAB0WIQRMcISVXLJjVvC4lX+LPIo+Aiko1QUCaV6ipAAKCRCLPIo+Aiko 1WqSB/0VrgfS9rAIG9Uf20YH0OIYY4ndo3LeHhBOi8y+NVnkkrgy2GYB7/rQtaNP7nFjGfA4cmL vbob0bl/yFwoZQmX5PkeiPuoQSoaXRP7AtTHFBeRCi8Rj9oXqeEBUvIHu+aQBv/49k7WQadCRsL mUZovgX/I4GjOMOxM5h0ygkXgQO3MvIU+0mML823mquPoOjHaRJ3jIOUUziNm5KhauTTSv8bEZm nSoWmvCvTd8ktElS/MnI/p7rdGaiBmxxWtJifxx6QQ4NVYcjP/iEq3BtdhrWCen/IWD7BodYU3K Hmu1TnqjIt4tgMI702qK4C1kVfoT8MkuGsTjtWOwHZpujBeq X-Developer-Key: i=dmitry.baryshkov@oss.qualcomm.com; a=openpgp; fpr=8F88381DD5C873E4AE487DA5199BF1243632046A X-Authority-Analysis: v=2.4 cv=WKNyn3sR c=1 sm=1 tr=0 ts=695ea2ac cx=c_pps a=hnmNkyzTK/kJ09Xio7VxxA==:117 a=xqWC_Br6kY4A:10 a=IkcTkHD0fZMA:10 a=vUbySO9Y5rIA:10 a=s4-Qcg_JpJYA:10 a=VkNPw1HP01LnGYTKEx00:22 a=EUspDBNiAAAA:8 a=VwQbUJbxAAAA:8 a=8CpnO3W62F676OTI3Z8A:9 a=QEXdDO2ut3YA:10 a=PEH46H7Ffwr30OY-TuGO:22 X-Proofpoint-GUID: Z2iLPt8Q7spr7oJ0WwBDulKGqHeyMweC X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwMTA3MDE0NCBTYWx0ZWRfX+Rxjeao9dPes FHAtHKuEZt2uyV5uRIBUDEzTYf2M+j+gA+3qq2a72VKrvLkI6BBq2PuWnJ2esAJ0qBbyDPxMEjn Q0bp4H6EqzJt8feWa7xwfQeL2U3b1P8jm+1JMavhevU7fe3d37lQvPXs29aFB92Uf32K9SyZo6U FIAGxxyd5hjzGK7/ustbqKA8xjTgPPqfflXY2f6mQ5q1JSDE296Rwl5pMJghffmz2cLy7pW6np7 CCG85NLDpGO7MpDUGZ/oVTQDUC8AsJpk+61Wg/VsCz5hgApdwn7+9as3V9s3Y4rGjsq/Z/QuAoR kgBL97rv4MX3nC4Mh42JThgdoU5GhwRDnVlWEX4usj4p3CL2+59EHiO4r/INtchuUhfinQnHZ8v xCQyUVgi0F8becGUENJrNkDyh2MA9/KkN23QqBseogznGfGtxOy+r/mQIRwdoHlJ7KE0nCXxbQh MuDi21/ePhlEdUKk2Eg== X-Proofpoint-ORIG-GUID: Z2iLPt8Q7spr7oJ0WwBDulKGqHeyMweC X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1121,Hydra:6.1.9,FMLib:17.12.100.49 definitions=2026-01-07_03,2026-01-06_01,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 clxscore=1015 spamscore=0 malwarescore=0 bulkscore=0 priorityscore=1501 lowpriorityscore=0 adultscore=0 impostorscore=0 phishscore=0 suspectscore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2512120000 definitions=main-2601070144 Verify the InfoFrames behaviour. Check that reporting InfoFrame as unsupported doesn't result in a commit error. Also check that HDR and Audio InfoFrames are not triggered if corresponding features are not enabled. Signed-off-by: Dmitry Baryshkov Acked-by: Maxime Ripard --- drivers/gpu/drm/tests/drm_client_modeset_test.c | 3 + drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c | 627 +++++++++++++++++= ++++ drivers/gpu/drm/tests/drm_kunit_edid.h | 119 ++++ 3 files changed, 749 insertions(+) diff --git a/drivers/gpu/drm/tests/drm_client_modeset_test.c b/drivers/gpu/= drm/tests/drm_client_modeset_test.c index 3f44fe5e92e4..ec58fe064d86 100644 --- a/drivers/gpu/drm/tests/drm_client_modeset_test.c +++ b/drivers/gpu/drm/tests/drm_client_modeset_test.c @@ -5,6 +5,7 @@ =20 #include =20 +#include #include #include #include @@ -48,6 +49,8 @@ static const struct drm_connector_helper_funcs drm_client= _modeset_connector_help }; =20 static const struct drm_connector_funcs drm_client_modeset_connector_funcs= =3D { + .atomic_destroy_state =3D drm_atomic_helper_connector_destroy_state, + .atomic_duplicate_state =3D drm_atomic_helper_connector_duplicate_state }; =20 static int drm_client_modeset_test_init(struct kunit *test) 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 8bd412735000..80f819a9ff5b 100644 --- a/drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c +++ b/drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c @@ -35,11 +35,16 @@ struct drm_atomic_helper_connector_hdmi_priv { =20 const void *current_edid; size_t current_edid_len; + + int hdmi_update_failures; }; =20 #define connector_to_priv(c) \ container_of_const(c, struct drm_atomic_helper_connector_hdmi_priv, conne= ctor) =20 +#define encoder_to_priv(e) \ + container_of_const(e, struct drm_atomic_helper_connector_hdmi_priv, encod= er) + static struct drm_display_mode *find_preferred_mode(struct drm_connector *= connector) { struct drm_device *drm =3D connector->dev; @@ -138,6 +143,22 @@ static const struct drm_connector_funcs dummy_connecto= r_funcs =3D { .reset =3D dummy_hdmi_connector_reset, }; =20 +static void test_encoder_atomic_enable(struct drm_encoder *encoder, + struct drm_atomic_state *state) +{ + struct drm_atomic_helper_connector_hdmi_priv *priv =3D + encoder_to_priv(encoder); + int ret; + + ret =3D drm_atomic_helper_connector_hdmi_update_infoframes(&priv->connect= or, state); + if (ret) + priv->hdmi_update_failures++; +} + +static const struct drm_encoder_helper_funcs test_encoder_helper_funcs =3D= { + .atomic_enable =3D test_encoder_atomic_enable, +}; + static struct drm_atomic_helper_connector_hdmi_priv * __connector_hdmi_init(struct kunit *test, @@ -2323,10 +2344,616 @@ static struct kunit_suite drm_atomic_helper_connec= tor_hdmi_mode_valid_test_suite .test_cases =3D drm_atomic_helper_connector_hdmi_mode_valid_tests, }; =20 +/* + * Test that the default behaviour works without errors. We expect that + * infoframe-related hooks are called and there are no errors raised. + */ +static void drm_test_check_infoframes(struct kunit *test) +{ + struct drm_atomic_helper_connector_hdmi_priv *priv; + struct drm_modeset_acquire_ctx ctx; + struct drm_crtc_state *crtc_state; + struct drm_atomic_state *state; + struct drm_display_mode *preferred; + struct drm_connector *conn; + struct drm_device *drm; + struct drm_crtc *crtc; + int old_hdmi_update_failures; + int ret; + + priv =3D drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test, + BIT(HDMI_COLORSPACE_RGB), + 8, + &dummy_connector_hdmi_funcs, + test_edid_hdmi_1080p_rgb_max_200mhz); + KUNIT_ASSERT_NOT_NULL(test, priv); + + drm =3D &priv->drm; + crtc =3D priv->crtc; + conn =3D &priv->connector; + + preferred =3D find_preferred_mode(conn); + KUNIT_ASSERT_NOT_NULL(test, preferred); + + drm_modeset_acquire_init(&ctx, 0); + +retry_conn_enable: + ret =3D drm_kunit_helper_enable_crtc_connector(test, drm, + crtc, conn, + preferred, + &ctx); + if (ret =3D=3D -EDEADLK) { + ret =3D drm_modeset_backoff(&ctx); + if (!ret) + goto retry_conn_enable; + } + KUNIT_ASSERT_EQ(test, ret, 0); + + state =3D drm_kunit_helper_atomic_state_alloc(test, drm, &ctx); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state); + +retry_crtc_state: + crtc_state =3D drm_atomic_get_crtc_state(state, crtc); + if (PTR_ERR(crtc_state) =3D=3D -EDEADLK) { + drm_atomic_state_clear(state); + ret =3D drm_modeset_backoff(&ctx); + if (!ret) + goto retry_crtc_state; + } + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc_state); + + crtc_state->mode_changed =3D true; + + old_hdmi_update_failures =3D priv->hdmi_update_failures; + + ret =3D drm_atomic_check_only(state); + if (ret =3D=3D -EDEADLK) { + drm_atomic_state_clear(state); + ret =3D drm_modeset_backoff(&ctx); + if (!ret) + goto retry_crtc_state; + } + KUNIT_ASSERT_EQ(test, ret, 0); + + ret =3D drm_atomic_commit(state); + if (ret =3D=3D -EDEADLK) { + drm_atomic_state_clear(state); + ret =3D drm_modeset_backoff(&ctx); + if (!ret) + goto retry_crtc_state; + } + KUNIT_ASSERT_EQ(test, ret, 0); + + KUNIT_EXPECT_GE(test, old_hdmi_update_failures, priv->hdmi_update_failure= s); + + drm_modeset_drop_locks(&ctx); + drm_modeset_acquire_fini(&ctx); +} + +static int reject_avi_infoframe_write_infoframe(struct drm_connector *conn= ector, + enum hdmi_infoframe_type type, + const u8 *buffer, size_t len) +{ + if (type =3D=3D HDMI_INFOFRAME_TYPE_AVI) + return -EOPNOTSUPP; + + return 0; +} + +static const struct drm_connector_hdmi_funcs reject_avi_infoframe_hdmi_fun= cs =3D { + .write_infoframe =3D reject_avi_infoframe_write_infoframe, +}; + +/* + * Test that the rejection of AVI InfoFrame results in the failure of + * drm_atomic_helper_connector_hdmi_update_infoframes(). + */ +static void drm_test_check_reject_avi_infoframe(struct kunit *test) +{ + struct drm_atomic_helper_connector_hdmi_priv *priv; + struct drm_modeset_acquire_ctx ctx; + struct drm_atomic_state *state; + struct drm_crtc_state *crtc_state; + struct drm_display_mode *preferred; + struct drm_connector *conn; + struct drm_device *drm; + struct drm_crtc *crtc; + int old_hdmi_update_failures; + int ret; + + priv =3D drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test, + BIT(HDMI_COLORSPACE_RGB), + 8, + &reject_avi_infoframe_hdmi_funcs, + test_edid_hdmi_1080p_rgb_max_200mhz); + KUNIT_ASSERT_NOT_NULL(test, priv); + + drm =3D &priv->drm; + crtc =3D priv->crtc; + conn =3D &priv->connector; + + preferred =3D find_preferred_mode(conn); + KUNIT_ASSERT_NOT_NULL(test, preferred); + + drm_modeset_acquire_init(&ctx, 0); + +retry_conn_enable: + ret =3D drm_kunit_helper_enable_crtc_connector(test, drm, + crtc, conn, + preferred, + &ctx); + if (ret =3D=3D -EDEADLK) { + ret =3D drm_modeset_backoff(&ctx); + if (!ret) + goto retry_conn_enable; + } + KUNIT_ASSERT_EQ(test, ret, 0); + + drm_encoder_helper_add(&priv->encoder, &test_encoder_helper_funcs); + + state =3D drm_kunit_helper_atomic_state_alloc(test, drm, &ctx); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state); + +retry_crtc_state: + crtc_state =3D drm_atomic_get_crtc_state(state, crtc); + if (PTR_ERR(crtc_state) =3D=3D -EDEADLK) { + drm_atomic_state_clear(state); + ret =3D drm_modeset_backoff(&ctx); + if (!ret) + goto retry_crtc_state; + } + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc_state); + + crtc_state->mode_changed =3D true; + + old_hdmi_update_failures =3D priv->hdmi_update_failures; + + ret =3D drm_atomic_check_only(state); + if (ret =3D=3D -EDEADLK) { + drm_atomic_state_clear(state); + ret =3D drm_modeset_backoff(&ctx); + if (!ret) + goto retry_crtc_state; + } + KUNIT_ASSERT_EQ(test, ret, 0); + + ret =3D drm_atomic_commit(state); + if (ret =3D=3D -EDEADLK) { + drm_atomic_state_clear(state); + ret =3D drm_modeset_backoff(&ctx); + if (!ret) + goto retry_crtc_state; + } + KUNIT_ASSERT_EQ(test, ret, 0); + + KUNIT_EXPECT_NE(test, old_hdmi_update_failures, priv->hdmi_update_failure= s); + + drm_modeset_drop_locks(&ctx); + drm_modeset_acquire_fini(&ctx); +} + +static int reject_hdr_infoframe_write_infoframe(struct drm_connector *conn= ector, + enum hdmi_infoframe_type type, + const u8 *buffer, size_t len) +{ + if (type =3D=3D HDMI_INFOFRAME_TYPE_DRM) + return -EOPNOTSUPP; + + return 0; +} + +static const struct drm_connector_hdmi_funcs reject_hdr_infoframe_hdmi_fun= cs =3D { + .write_infoframe =3D reject_hdr_infoframe_write_infoframe, +}; + +/* + * Test that the HDR InfoFrame isn't programmed in + * drm_atomic_helper_connector_hdmi_update_infoframes() if the max_bpc is = 8. + */ +static void drm_test_check_reject_hdr_infoframe_bpc_8(struct kunit *test) +{ + struct drm_atomic_helper_connector_hdmi_priv *priv; + struct drm_modeset_acquire_ctx ctx; + struct drm_atomic_state *state; + struct drm_connector_state *new_conn_state; + struct drm_crtc_state *crtc_state; + struct drm_display_mode *preferred; + struct drm_connector *conn; + struct drm_device *drm; + struct drm_crtc *crtc; + int old_hdmi_update_failures; + int ret; + + priv =3D drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test, + BIT(HDMI_COLORSPACE_RGB), + 8, + &reject_hdr_infoframe_hdmi_funcs, + test_edid_hdmi_1080p_rgb_max_200mhz_hdr); + KUNIT_ASSERT_NOT_NULL(test, priv); + + drm =3D &priv->drm; + crtc =3D priv->crtc; + conn =3D &priv->connector; + + preferred =3D find_preferred_mode(conn); + KUNIT_ASSERT_NOT_NULL(test, preferred); + + drm_modeset_acquire_init(&ctx, 0); + +retry_conn_enable: + ret =3D drm_kunit_helper_enable_crtc_connector(test, drm, + crtc, conn, + preferred, + &ctx); + if (ret =3D=3D -EDEADLK) { + ret =3D drm_modeset_backoff(&ctx); + if (!ret) + goto retry_conn_enable; + } + KUNIT_ASSERT_EQ(test, ret, 0); + + drm_encoder_helper_add(&priv->encoder, &test_encoder_helper_funcs); + + state =3D drm_kunit_helper_atomic_state_alloc(test, drm, &ctx); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state); + +retry_conn_state: + new_conn_state =3D drm_atomic_get_connector_state(state, conn); + if (PTR_ERR(new_conn_state) =3D=3D -EDEADLK) { + drm_atomic_state_clear(state); + ret =3D drm_modeset_backoff(&ctx); + if (!ret) + goto retry_conn_state; + } + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, new_conn_state); + + crtc_state =3D drm_atomic_get_crtc_state(state, crtc); + if (PTR_ERR(crtc_state) =3D=3D -EDEADLK) { + drm_atomic_state_clear(state); + ret =3D drm_modeset_backoff(&ctx); + if (!ret) + goto retry_conn_state; + } + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc_state); + + /* Verify that there is no HDR property, so "userspace" can't set it. */ + for (int i =3D 0; i < conn->base.properties->count; i++) + KUNIT_ASSERT_PTR_NE(test, + drm->mode_config.hdr_output_metadata_property, + conn->base.properties->properties[i]); + + crtc_state->mode_changed =3D true; + + old_hdmi_update_failures =3D priv->hdmi_update_failures; + + ret =3D drm_atomic_check_only(state); + if (ret =3D=3D -EDEADLK) { + drm_atomic_state_clear(state); + ret =3D drm_modeset_backoff(&ctx); + if (!ret) + goto retry_conn_state; + } + KUNIT_ASSERT_EQ(test, ret, 0); + + ret =3D drm_atomic_commit(state); + if (ret =3D=3D -EDEADLK) { + drm_atomic_state_clear(state); + ret =3D drm_modeset_backoff(&ctx); + if (!ret) + goto retry_conn_state; + } + KUNIT_ASSERT_EQ(test, ret, 0); + + KUNIT_EXPECT_EQ(test, old_hdmi_update_failures, priv->hdmi_update_failure= s); + + new_conn_state =3D conn->state; + KUNIT_ASSERT_NOT_NULL(test, new_conn_state); + + KUNIT_ASSERT_EQ(test, new_conn_state->hdmi.output_bpc, 8); + KUNIT_ASSERT_EQ(test, new_conn_state->hdmi.infoframes.hdr_drm.set, false); + + drm_modeset_drop_locks(&ctx); + drm_modeset_acquire_fini(&ctx); +} + +/* + * Test that the rejection of HDR InfoFrame results in the failure of + * drm_atomic_helper_connector_hdmi_update_infoframes() in the high bpc is + * supported. + */ +static void drm_test_check_reject_hdr_infoframe_bpc_10(struct kunit *test) +{ + struct drm_atomic_helper_connector_hdmi_priv *priv; + struct drm_modeset_acquire_ctx ctx; + struct drm_atomic_state *state; + struct drm_connector_state *new_conn_state; + struct drm_crtc_state *crtc_state; + struct drm_display_mode *preferred; + struct drm_connector *conn; + struct drm_device *drm; + struct drm_crtc *crtc; + int old_hdmi_update_failures; + struct hdr_output_metadata hdr_data; + struct drm_property_blob *hdr_blob; + bool replaced; + int ret; + + priv =3D drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test, + BIT(HDMI_COLORSPACE_RGB), + 10, + &reject_hdr_infoframe_hdmi_funcs, + test_edid_hdmi_1080p_rgb_max_200mhz_hdr); + KUNIT_ASSERT_NOT_NULL(test, priv); + + drm =3D &priv->drm; + crtc =3D priv->crtc; + conn =3D &priv->connector; + + preferred =3D find_preferred_mode(conn); + KUNIT_ASSERT_NOT_NULL(test, preferred); + + drm_modeset_acquire_init(&ctx, 0); + +retry_conn_enable: + ret =3D drm_kunit_helper_enable_crtc_connector(test, drm, + crtc, conn, + preferred, + &ctx); + if (ret =3D=3D -EDEADLK) { + ret =3D drm_modeset_backoff(&ctx); + if (!ret) + goto retry_conn_enable; + } + KUNIT_ASSERT_EQ(test, ret, 0); + + drm_encoder_helper_add(&priv->encoder, &test_encoder_helper_funcs); + + state =3D drm_kunit_helper_atomic_state_alloc(test, drm, &ctx); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state); + +retry_conn_state: + new_conn_state =3D drm_atomic_get_connector_state(state, conn); + if (PTR_ERR(new_conn_state) =3D=3D -EDEADLK) { + drm_atomic_state_clear(state); + ret =3D drm_modeset_backoff(&ctx); + if (!ret) + goto retry_conn_state; + } + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, new_conn_state); + + crtc_state =3D drm_atomic_get_crtc_state(state, crtc); + if (PTR_ERR(crtc_state) =3D=3D -EDEADLK) { + drm_atomic_state_clear(state); + ret =3D drm_modeset_backoff(&ctx); + if (!ret) + goto retry_conn_state; + } + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc_state); + + hdr_data.metadata_type =3D HDMI_STATIC_METADATA_TYPE1; + hdr_data.hdmi_metadata_type1.eotf =3D HDMI_EOTF_TRADITIONAL_GAMMA_SDR; + hdr_data.hdmi_metadata_type1.metadata_type =3D HDMI_STATIC_METADATA_TYPE1; + + hdr_blob =3D drm_property_create_blob(drm, sizeof(hdr_data), &hdr_data); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, hdr_blob); + + ret =3D drm_property_replace_blob_from_id(drm, + &new_conn_state->hdr_output_metadata, + hdr_blob->base.id, + sizeof(struct hdr_output_metadata), -1, + &replaced); + KUNIT_ASSERT_EQ(test, ret, 0); + KUNIT_ASSERT_EQ(test, replaced, true); + + crtc_state->mode_changed =3D true; + + old_hdmi_update_failures =3D priv->hdmi_update_failures; + + ret =3D drm_atomic_check_only(state); + if (ret =3D=3D -EDEADLK) { + drm_atomic_state_clear(state); + ret =3D drm_modeset_backoff(&ctx); + if (!ret) + goto retry_conn_state; + } + KUNIT_ASSERT_EQ(test, ret, 0); + + ret =3D drm_atomic_commit(state); + if (ret =3D=3D -EDEADLK) { + drm_atomic_state_clear(state); + ret =3D drm_modeset_backoff(&ctx); + if (!ret) + goto retry_conn_state; + } + KUNIT_ASSERT_EQ(test, ret, 0); + + KUNIT_EXPECT_LE(test, old_hdmi_update_failures, priv->hdmi_update_failure= s); + + new_conn_state =3D conn->state; + KUNIT_ASSERT_NOT_NULL(test, new_conn_state); + + KUNIT_ASSERT_EQ(test, new_conn_state->hdmi.output_bpc, 10); + KUNIT_ASSERT_EQ(test, new_conn_state->hdmi.infoframes.hdr_drm.set, true); + + drm_modeset_drop_locks(&ctx); + drm_modeset_acquire_fini(&ctx); +} + +static int reject_audio_infoframe_write_infoframe(struct drm_connector *co= nnector, + enum hdmi_infoframe_type type, + const u8 *buffer, size_t len) +{ + if (type =3D=3D HDMI_INFOFRAME_TYPE_AUDIO) + return -EOPNOTSUPP; + + return 0; +} + +static const struct drm_connector_hdmi_funcs reject_audio_infoframe_hdmi_f= uncs =3D { + .write_infoframe =3D reject_audio_infoframe_write_infoframe, +}; + +/* + * Test that Audio InfoFrame is only programmed if we call a corresponding= API, + * thus the drivers can safely assume that they won't get Audio InfoFrames= if + * they don't call it. + */ +static void drm_test_check_reject_audio_infoframe(struct kunit *test) +{ + struct drm_atomic_helper_connector_hdmi_priv *priv; + struct drm_modeset_acquire_ctx ctx; + struct drm_atomic_state *state; + struct drm_crtc_state *crtc_state; + struct drm_display_mode *preferred; + struct drm_connector *conn; + struct drm_device *drm; + struct drm_crtc *crtc; + int old_hdmi_update_failures; + struct hdmi_audio_infoframe cea; + int ret; + + priv =3D drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test, + BIT(HDMI_COLORSPACE_RGB), + 8, + &reject_audio_infoframe_hdmi_funcs, + test_edid_hdmi_1080p_rgb_max_200mhz); + KUNIT_ASSERT_NOT_NULL(test, priv); + + drm =3D &priv->drm; + crtc =3D priv->crtc; + conn =3D &priv->connector; + + preferred =3D find_preferred_mode(conn); + KUNIT_ASSERT_NOT_NULL(test, preferred); + + drm_modeset_acquire_init(&ctx, 0); + +retry_conn_enable: + ret =3D drm_kunit_helper_enable_crtc_connector(test, drm, + crtc, conn, + preferred, + &ctx); + if (ret =3D=3D -EDEADLK) { + ret =3D drm_modeset_backoff(&ctx); + if (!ret) + goto retry_conn_enable; + } + KUNIT_ASSERT_EQ(test, ret, 0); + + drm_encoder_helper_add(&priv->encoder, &test_encoder_helper_funcs); + + state =3D drm_kunit_helper_atomic_state_alloc(test, drm, &ctx); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state); + +retry_crtc_state: + crtc_state =3D drm_atomic_get_crtc_state(state, crtc); + if (PTR_ERR(crtc_state) =3D=3D -EDEADLK) { + drm_atomic_state_clear(state); + ret =3D drm_modeset_backoff(&ctx); + if (!ret) + goto retry_crtc_state; + } + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc_state); + + crtc_state->mode_changed =3D true; + + old_hdmi_update_failures =3D priv->hdmi_update_failures; + + ret =3D drm_atomic_check_only(state); + if (ret =3D=3D -EDEADLK) { + drm_atomic_state_clear(state); + ret =3D drm_modeset_backoff(&ctx); + if (!ret) + goto retry_crtc_state; + } + KUNIT_ASSERT_EQ(test, ret, 0); + + ret =3D drm_atomic_commit(state); + if (ret =3D=3D -EDEADLK) { + drm_atomic_state_clear(state); + ret =3D drm_modeset_backoff(&ctx); + if (!ret) + goto retry_crtc_state; + } + KUNIT_ASSERT_EQ(test, ret, 0); + + KUNIT_EXPECT_EQ(test, old_hdmi_update_failures, priv->hdmi_update_failure= s); + + /* + * So, it works without Audio InfoFrame, let's fail with it in place, + * checking that writing the infofraem actually gets triggered. + */ + + hdmi_audio_infoframe_init(&cea); + cea.channels =3D 2; + cea.coding_type =3D HDMI_AUDIO_CODING_TYPE_STREAM; + cea.sample_size =3D HDMI_AUDIO_SAMPLE_SIZE_STREAM; + cea.sample_frequency =3D HDMI_AUDIO_SAMPLE_FREQUENCY_STREAM; + + ret =3D drm_atomic_helper_connector_hdmi_update_audio_infoframe(conn, &ce= a); + KUNIT_ASSERT_EQ(test, ret, -EOPNOTSUPP); + + state =3D drm_kunit_helper_atomic_state_alloc(test, drm, &ctx); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state); + +retry_crtc_state_2: + crtc_state =3D drm_atomic_get_crtc_state(state, crtc); + if (PTR_ERR(crtc_state) =3D=3D -EDEADLK) { + drm_atomic_state_clear(state); + ret =3D drm_modeset_backoff(&ctx); + if (!ret) + goto retry_crtc_state_2; + } + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc_state); + + crtc_state->mode_changed =3D true; + + old_hdmi_update_failures =3D priv->hdmi_update_failures; + + ret =3D drm_atomic_check_only(state); + if (ret =3D=3D -EDEADLK) { + drm_atomic_state_clear(state); + ret =3D drm_modeset_backoff(&ctx); + if (!ret) + goto retry_crtc_state_2; + } + KUNIT_ASSERT_EQ(test, ret, 0); + + ret =3D drm_atomic_commit(state); + if (ret =3D=3D -EDEADLK) { + drm_atomic_state_clear(state); + ret =3D drm_modeset_backoff(&ctx); + if (!ret) + goto retry_crtc_state_2; + } + KUNIT_ASSERT_EQ(test, ret, 0); + + KUNIT_EXPECT_LE(test, old_hdmi_update_failures, priv->hdmi_update_failure= s); + + drm_modeset_drop_locks(&ctx); + drm_modeset_acquire_fini(&ctx); +} + + +static struct kunit_case drm_atomic_helper_connector_hdmi_infoframes_tests= [] =3D { + KUNIT_CASE(drm_test_check_infoframes), + 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), + KUNIT_CASE(drm_test_check_reject_audio_infoframe), + { } +}; + +static struct kunit_suite drm_atomic_helper_connector_hdmi_infoframes_test= _suite =3D { + .name =3D "drm_atomic_helper_connector_hdmi_infoframes", + .test_cases =3D drm_atomic_helper_connector_hdmi_infoframes_tests, +}; + kunit_test_suites( &drm_atomic_helper_connector_hdmi_check_test_suite, &drm_atomic_helper_connector_hdmi_reset_test_suite, &drm_atomic_helper_connector_hdmi_mode_valid_test_suite, + &drm_atomic_helper_connector_hdmi_infoframes_test_suite, ); =20 MODULE_AUTHOR("Maxime Ripard "); diff --git a/drivers/gpu/drm/tests/drm_kunit_edid.h b/drivers/gpu/drm/tests= /drm_kunit_edid.h index c59c8528a3f7..f4923157f5bf 100644 --- a/drivers/gpu/drm/tests/drm_kunit_edid.h +++ b/drivers/gpu/drm/tests/drm_kunit_edid.h @@ -293,6 +293,125 @@ static const unsigned char test_edid_hdmi_1080p_rgb_m= ax_200mhz[] =3D { 0x00, 0x00, 0x00, 0xfc }; =20 +/* + * edid-decode (hex): + * + * 00 ff ff ff ff ff ff 00 31 d8 2a 00 00 00 00 00 + * 00 21 01 03 81 a0 5a 78 02 00 00 00 00 00 00 00 + * 00 00 00 20 00 00 01 01 01 01 01 01 01 01 01 01 + * 01 01 01 01 01 01 02 3a 80 18 71 38 2d 40 58 2c + * 45 00 40 84 63 00 00 1e 00 00 00 fc 00 54 65 73 + * 74 20 45 44 49 44 0a 20 20 20 00 00 00 fd 00 32 + * 46 1e 46 0f 00 0a 20 20 20 20 20 20 00 00 00 10 + * 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 92 + * + * 02 03 1c 81 e3 05 c0 20 41 10 e2 00 4a 67 03 0c + * 00 12 34 00 28 e6 06 05 01 52 52 51 00 00 00 00 + * 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + * 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + * 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + * 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + * 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + * 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 4e + * + * ---------------- + * + * Block 0, Base EDID: + * EDID Structure Version & Revision: 1.3 + * Vendor & Product Identification: + * Manufacturer: LNX + * Model: 42 + * Made in: 2023 + * Basic Display Parameters & Features: + * Digital display + * DFP 1.x compatible TMDS + * Maximum image size: 160 cm x 90 cm + * Gamma: 2.20 + * Monochrome or grayscale display + * First detailed timing is the preferred timing + * Color Characteristics: + * Red : 0.0000, 0.0000 + * Green: 0.0000, 0.0000 + * Blue : 0.0000, 0.0000 + * White: 0.0000, 0.0000 + * Established Timings I & II: + * DMT 0x04: 640x480 59.940476 Hz 4:3 31.469 kHz 25.175= 000 MHz + * Standard Timings: none + * Detailed Timing Descriptors: + * DTD 1: 1920x1080 60.000000 Hz 16:9 67.500 kHz 148.500000= MHz (1600 mm x 900 mm) + * Hfront 88 Hsync 44 Hback 148 Hpol P + * Vfront 4 Vsync 5 Vback 36 Vpol P + * Display Product Name: 'Test EDID' + * Display Range Limits: + * Monitor ranges (GTF): 50-70 Hz V, 30-70 kHz H, max dotclock 150 M= Hz + * Dummy Descriptor: + * Extension blocks: 1 + * Checksum: 0x92 + * + * ---------------- + * + * Block 1, CTA-861 Extension Block: + * Revision: 3 + * Underscans IT Video Formats by default + * Native detailed modes: 1 + * Colorimetry Data Block: + * BT2020YCC + * BT2020RGB + * sRGB + * Video Data Block: + * VIC 16: 1920x1080 60.000000 Hz 16:9 67.500 kHz 148.5000= 00 MHz + * Video Capability Data Block: + * YCbCr quantization: No Data + * RGB quantization: Selectable (via AVI Q) + * PT scan behavior: No Data + * IT scan behavior: Always Underscanned + * CE scan behavior: Always Underscanned + * Vendor-Specific Data Block (HDMI), OUI 00-0C-03: + * Source physical address: 1.2.3.4 + * Maximum TMDS clock: 200 MHz + * HDR Static Metadata Data Block: + * Electro optical transfer functions: + * Traditional gamma - SDR luminance range + * SMPTE ST2084 + * Supported static metadata descriptors: + * Static metadata type 1 + * Desired content max luminance: 82 (295.365 cd/m^2) + * Desired content max frame-average luminance: 82 (295.365 cd/m^2) + * Desired content min luminance: 81 (0.298 cd/m^2) + * Checksum: 0x4e Unused space in Extension Block: 99 bytes + * + * ---------------- + * + * edid-decode 1.31.0-5387 + * edid-decode SHA: 5508bc4301ac 2025-08-25 08:14:22 + * + * EDID conformity: PASS + */ +static const unsigned char test_edid_hdmi_1080p_rgb_max_200mhz_hdr[] =3D { + 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x31, 0xd8, 0x2a, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x01, 0x03, 0x81, 0xa0, 0x5a, 0x78, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, + 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x3a, 0x80, 0x18, 0x71, 0x38, + 0x2d, 0x40, 0x58, 0x2c, 0x45, 0x00, 0x40, 0x84, 0x63, 0x00, 0x00, 0x1e, + 0x00, 0x00, 0x00, 0xfc, 0x00, 0x54, 0x65, 0x73, 0x74, 0x20, 0x45, 0x44, + 0x49, 0x44, 0x0a, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x32, + 0x46, 0x1e, 0x46, 0x0f, 0x00, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x92, 0x02, 0x03, 0x1c, 0x81, + 0xe3, 0x05, 0xc0, 0x20, 0x41, 0x10, 0xe2, 0x00, 0x4a, 0x67, 0x03, 0x0c, + 0x00, 0x12, 0x34, 0x78, 0x28, 0xe6, 0x06, 0x05, 0x01, 0x52, 0x52, 0x51, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xd6, +}; + /* * edid-decode (hex): * --=20 2.47.3