From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from smtpout-04.galae.net (smtpout-04.galae.net [185.171.202.116]) (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 F12483A5E64 for ; Wed, 22 Apr 2026 16:50:17 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.171.202.116 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776876622; cv=none; b=aepHAVzh9k9dh8sIeNtimRm6TCf1dxOysLqqJoy6UH2hydkBpVg7PxEj2CTX7YIRaB5TxLRU7TblLoa0dUN0SDV6NccIyvJ9siiLLb0Ie8Dkxx0wHYE4VTz2/MgNj+tCLguLhYWsxtuLFjrdZZBoO82SptXd2dC/ws991EKIJWs= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776876622; c=relaxed/simple; bh=Ykt0+eDcFLZKhRF0U9iVPfGtUL9KKZviCkUdgczlf64=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=tkiACeLLNE2hg+GUkDHNdx9/AI8PHtP3nP8BxhNI28lQ8vNvlmwG7jf89+VBvkLrSayFE8s0fVZFogkVkprAYDNk+ZQPBi+fAfxdNLtZvmXcsVg1Cp4zkBUdbsikXeACC6HT3sZuC9Y7OJLKxas7+pVBsSTu1NGEL3C0qoa1gMU= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com; spf=pass smtp.mailfrom=bootlin.com; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b=PneZKtW0; arc=none smtp.client-ip=185.171.202.116 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=bootlin.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="PneZKtW0" Received: from smtpout-01.galae.net (smtpout-01.galae.net [212.83.139.233]) by smtpout-04.galae.net (Postfix) with ESMTPS id 776FCC5EF07; Wed, 22 Apr 2026 16:50:56 +0000 (UTC) Received: from mail.galae.net (mail.galae.net [212.83.136.155]) by smtpout-01.galae.net (Postfix) with ESMTPS id 949085FA8F; Wed, 22 Apr 2026 16:50:15 +0000 (UTC) Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id 15A7F10460C21; Wed, 22 Apr 2026 18:50:12 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=dkim; t=1776876614; h=from:subject:date:message-id:to:cc:mime-version:content-type: content-transfer-encoding:in-reply-to:references; bh=Qdj2x9CZWyS1GVhOOvBsSsRVbE5RxHKj8IrNu4MfsUE=; b=PneZKtW02oDA4rS9q7gFgJK7DFk+XVyMmkCs8e8SV/dy2Cfs6aRXACIAlCNm4oJBVek3b4 h8TNuLLDwdN2knevDcJusIWoG44sj0tRZlhqbEF7KvBUJqpCB8jVqP0DjD0uJFQMHjw5NB uMENOi7mS1Uduru93cNa4Dku66DbVj7pVenX+CiLjB1eaHwTk5NOTopn/+voldV/vPG1Ym BvbtuHDNaLndNliVk2MtsPqHHb6Z0IqUboY3a6KqyrZQhf4+XAiydmWnnRnixiSJvw/K6h nsMBRx6giN7+4guMvCkkH3+AlAp7Qe2JIkHDYpoJf6d9YhmIuH3au9Ad2t9GOw== From: Louis Chauvet Date: Wed, 22 Apr 2026 18:48:28 +0200 Subject: [PATCH v4 31/37] drm/vkms: Introduce config for connector EDID Precedence: bulk X-Mailing-List: linux-doc@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit Message-Id: <20260422-vkms-all-config-v4-31-dbb52e9aadc3@bootlin.com> References: <20260422-vkms-all-config-v4-0-dbb52e9aadc3@bootlin.com> In-Reply-To: <20260422-vkms-all-config-v4-0-dbb52e9aadc3@bootlin.com> To: Haneen Mohammed , Simona Vetter , Melissa Wen , Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , David Airlie , jose.exposito89@gmail.com, Jonathan Corbet , Shuah Khan , Miguel Ojeda , Nathan Chancellor , Nick Desaulniers , Bill Wendling , Justin Stitt Cc: victoria@system76.com, sebastian.wick@redhat.com, victoria@system76.com, airlied@gmail.com, thomas.petazzoni@bootlin.com, dri-devel@lists.freedesktop.org, linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org, Louis Chauvet , llvm@lists.linux.dev, Luca Ceresoli X-Mailer: b4 0.16-dev X-Last-TLS-Session-Version: TLSv1.3 Allows configuration of EDID for each connector. Reviewed-by: Luca Ceresoli Signed-off-by: Louis Chauvet --- drivers/gpu/drm/vkms/tests/vkms_config_test.c | 2 + drivers/gpu/drm/vkms/vkms_config.c | 6 +++ drivers/gpu/drm/vkms/vkms_config.h | 75 +++++++++++++++++++++++++++ drivers/gpu/drm/vkms/vkms_connector.c | 50 ++++++++++++++++-- 4 files changed, 129 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/vkms/tests/vkms_config_test.c b/drivers/gpu/drm/vkms/tests/vkms_config_test.c index a31fd230c1d4..2b49745ee026 100644 --- a/drivers/gpu/drm/vkms/tests/vkms_config_test.c +++ b/drivers/gpu/drm/vkms/tests/vkms_config_test.c @@ -218,6 +218,8 @@ static void vkms_config_test_default_config(struct kunit *test) KUNIT_EXPECT_EQ(test, vkms_config_connector_get_supported_colorspaces(connector_cfg), 0); + KUNIT_EXPECT_EQ(test, vkms_config_connector_get_edid_enabled(connector_cfg), + false); } KUNIT_EXPECT_TRUE(test, vkms_config_is_valid(config)); diff --git a/drivers/gpu/drm/vkms/vkms_config.c b/drivers/gpu/drm/vkms/vkms_config.c index b0511e6fc64d..eee6401a3e4f 100644 --- a/drivers/gpu/drm/vkms/vkms_config.c +++ b/drivers/gpu/drm/vkms/vkms_config.c @@ -538,6 +538,7 @@ static int vkms_config_show(struct seq_file *m, void *data) struct drm_device *dev = entry->dev; struct vkms_device *vkmsdev = drm_device_to_vkms_device(dev); const char *dev_name; + int edid_len; struct vkms_config_plane *plane_cfg; struct vkms_config_crtc *crtc_cfg; struct vkms_config_encoder *encoder_cfg; @@ -608,6 +609,11 @@ static int vkms_config_show(struct seq_file *m, void *data) show_bitfield(m, vkms_config_connector_get_supported_colorspaces(connector_cfg), drm_get_colorspace_name); seq_puts(m, "\n"); + vkms_config_connector_get_edid(connector_cfg, &edid_len); + seq_printf(m, "\tEDID=%s (len=%d)\n", + str_enabled_disabled(vkms_config_connector_get_edid_enabled(connector_cfg)), + edid_len + ); } return 0; diff --git a/drivers/gpu/drm/vkms/vkms_config.h b/drivers/gpu/drm/vkms/vkms_config.h index e62bb6603a69..3489c682b4af 100644 --- a/drivers/gpu/drm/vkms/vkms_config.h +++ b/drivers/gpu/drm/vkms/vkms_config.h @@ -136,6 +136,9 @@ struct vkms_config_encoder { * are the sames as ones accepted by * drm_mode_create_hdmi_colorspace_property() and * drm_mode_create_dp_colorspace_property() + * @edid_enabled: If true, create the EDID property + * @edid: Stores the current EDID. The value will be ignored if @edid_enabled is false + * @edid_len: Current EDID length. The value will be ignored if @edid_enabled is false * @possible_encoders: Array of encoders that can be used with this connector * @connector: Internal usage. This pointer should never be considered as valid. * It can be used to store a temporary reference to a VKMS connector @@ -149,6 +152,9 @@ struct vkms_config_connector { int type; enum drm_connector_status status; u32 supported_colorspaces; + bool edid_enabled; + u8 *edid; + unsigned int edid_len; struct xarray possible_encoders; /* Internal usage */ @@ -273,6 +279,75 @@ vkms_config_connector_get_supported_colorspaces(const struct vkms_config_connect return connector_cfg->supported_colorspaces; } +/** + * vkms_config_connector_get_edid_enabled() - Check if EDID is enabled for a connector + * @connector_cfg: Connector configuration to check + * + * Returns: + * True if EDID is enabled for this connector, false otherwise. + */ +static inline bool +vkms_config_connector_get_edid_enabled(const struct vkms_config_connector *connector_cfg) +{ + return connector_cfg->edid_enabled; +} + +/** + * vkms_config_connector_set_edid_enabled() - Enable or disable EDID for a connector + * @connector_cfg: Connector configuration to modify + * @enabled: Whether to enable EDID for this connector + */ +static inline void +vkms_config_connector_set_edid_enabled(struct vkms_config_connector *connector_cfg, + bool enabled) +{ + connector_cfg->edid_enabled = enabled; +} + +/** + * vkms_config_connector_get_edid() - Get the EDID data for a connector + * @connector_cfg: Connector configuration to get the EDID from + * @len: Pointer to store the length of the EDID data + * + * Returns: + * Pointer to the EDID data buffer, or NULL if no EDID is set. + * The length of the EDID data is stored in @len. + */ +static inline const u8 * +vkms_config_connector_get_edid(const struct vkms_config_connector *connector_cfg, int *len) +{ + *len = connector_cfg->edid_len; + return connector_cfg->edid; +} + +/** + * vkms_config_connector_set_edid() - Set the EDID data for a connector + * @connector_cfg: Connector configuration to modify + * @edid: Pointer to the EDID data buffer + * @len: Length of the EDID data + * + * If @len is 0, the EDID data will be cleared and @edid ignored. If + * memory allocation fails, the existing EDID data will be preserved. + */ +static inline void +vkms_config_connector_set_edid(struct vkms_config_connector *connector_cfg, + const u8 *edid, unsigned int len) +{ + if (len) { + void *edid_tmp = krealloc(connector_cfg->edid, len, GFP_KERNEL); + + if (edid_tmp) { + connector_cfg->edid = edid_tmp; + memcpy(connector_cfg->edid, edid, len); + connector_cfg->edid_len = len; + } + } else { + kfree(connector_cfg->edid); + connector_cfg->edid = NULL; + connector_cfg->edid_len = len; + } +} + /** * vkms_config_get_device_name() - Return the name of the device * @config: Configuration to get the device name from diff --git a/drivers/gpu/drm/vkms/vkms_connector.c b/drivers/gpu/drm/vkms/vkms_connector.c index a1f08167def1..fe42ab2ba7b1 100644 --- a/drivers/gpu/drm/vkms/vkms_connector.c +++ b/drivers/gpu/drm/vkms/vkms_connector.c @@ -42,13 +42,55 @@ static const struct drm_connector_funcs vkms_connector_funcs = { .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, }; +static int vkms_connector_read_block(void *context, u8 *buf, unsigned int block, size_t len) +{ + struct vkms_config_connector *config = context; + unsigned int edid_len; + const u8 *edid = vkms_config_connector_get_edid(config, &edid_len); + + if (block * len + len > edid_len) + return 1; + memcpy(buf, &edid[block * len], len); + return 0; +} + static int vkms_conn_get_modes(struct drm_connector *connector) { - int count; + struct vkms_connector *vkms_connector = drm_connector_to_vkms_connector(connector); + const struct drm_edid *drm_edid = NULL; + int count = 0; + struct vkms_config_connector *context = NULL; + struct drm_device *dev = connector->dev; + struct vkms_device *vkmsdev = drm_device_to_vkms_device(dev); + struct vkms_config_connector *connector_cfg; - /* Use the default modes list from DRM */ - count = drm_add_modes_noedid(connector, XRES_MAX, YRES_MAX); - drm_set_preferred_mode(connector, XRES_DEF, YRES_DEF); + vkms_config_for_each_connector(vkmsdev->config, connector_cfg) { + if (connector_cfg->connector == vkms_connector) { + context = connector_cfg; + break; + } + } + if (context) { + if (vkms_config_connector_get_edid_enabled(context)) { + drm_edid = drm_edid_read_custom(connector, + vkms_connector_read_block, context); + + /* + * Unconditionally update the connector. If the EDID was read + * successfully, fill in the connector information derived from the + * EDID. Otherwise, if the EDID is NULL, clear the connector + * information. + */ + drm_edid_connector_update(connector, drm_edid); + + count = drm_edid_connector_add_modes(connector); + + drm_edid_free(drm_edid); + } else { + count = drm_add_modes_noedid(connector, XRES_MAX, YRES_MAX); + drm_set_preferred_mode(connector, XRES_DEF, YRES_DEF); + } + } return count; } -- 2.54.0