From patchwork Thu Jul 23 01:34:52 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Cristian Ciocaltea X-Patchwork-Id: 2739 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 0001C1C2E7B for ; Thu, 23 Jul 2026 03:37:07 +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-24645-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-24645-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 2D020306B7A1 for ; Thu, 23 Jul 2026 01:35:10 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 35B0B3002B9; Thu, 23 Jul 2026 01:35:09 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=collabora.com header.i=@collabora.com header.b="Mna4Sb5Y" 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 D460B2F8EB5 for ; Thu, 23 Jul 2026 01:35:05 +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=1784770509; cv=none; b=Rl1BCs8/4aUWcCDC5SiSnuVp+0hEMF/9phgMfn/+pDjwW+KL9VyqaVgVWT7xEy43qOAFfs3djIFDdrTdLXxJMAr3qstZhCXbBH6oWwkP8ylha7h5wP12JmVEHBU2/08IKE4Fzj7vvEA/hHhz0enjXC6Cbzb8pri5hyuhgIv15OQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784770509; c=relaxed/simple; bh=bxcqggTgwYlwm9SZjxThDpBmGD27PheA8QIcyOm6YPU=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=l4YtFYbjgod9D/zMpqa6qwq8uriUN+KMV28oa0iyozXQjt+V2mllL1XHj9GxtMAyiy6ZI5pfwz9fOQPQkZ5XOb2FGellchvuV9GWKbnZdZ+HLTLCc0NKlQ9FyIrpAqjCe1+iQj2aua4DvQb4gQlb8M5tLLxIyxazxZZje/259fI= 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=Mna4Sb5Y; 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=1784770504; bh=bxcqggTgwYlwm9SZjxThDpBmGD27PheA8QIcyOm6YPU=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=Mna4Sb5YLW073s5HsSZ2SY8AMFXXvBqp5baSGZVkeyk1ocmJrERAzECBEwemEnefQ Rh6HghYZWGqyQ7eDNkQ/A/jDTS9lj802DRwYTb017VrXhwCy8ah6L/IS0iXoeNrBl3 1AsHD587jFkOzFxS0ezFV3uy9MkM5DXeWZVOxnzHQRVgCP2xceek+LhDX4Aa4sq+l3 4Rvriau1Ji+XPDAKJ7HL5BTvNjnGwGinxo+W6m8CJrHo/XLwYSYSKrvoEiys3/gJXN KPP2GuAggdZmHzy9xIhEA1wBm+0SApRcLT/q4XZkoXzVOBIkONURoV7FCzpjC8a7ND O7hsWL2Ve93Aw== 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 261A817E1274; Thu, 23 Jul 2026 03:35:04 +0200 (CEST) From: Cristian Ciocaltea Date: Thu, 23 Jul 2026 04:34:52 +0300 Subject: [PATCH v9 03/61] drm/connector: Add drmm_connector_hdmi_init() with new signature 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-3-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-Rspamd-Server: rspamd-worker-8404 X-Spamd-Result: default: False [-2.16 / 15.00]; BAYES_HAM(-5.50)[100.00%]; RBL_SENDERSCORE(2.00)[172.234.253.10:from]; SUSPICIOUS_RECIPS(1.50)[]; MAILLIST(-0.15)[generic]; MIME_GOOD(-0.10)[text/plain]; BAD_REP_POLICIES(0.10)[]; HAS_LIST_UNSUB(-0.01)[]; DBL_BLOCKED_OPENRESOLVER(0.00)[sea.lore.kernel.org:rdns,sea.lore.kernel.org:helo,collabora.com:email,collabora.com:dkim]; TAGGED_RCPT(0.00)[]; PRECEDENCE_BULK(0.00)[]; RCPT_COUNT_TWELVE(0.00)[30]; FUZZY_BLOCKED(0.00)[rspamd.com]; FROM_HAS_DN(0.00)[]; MID_RHS_MATCH_FROM(0.00)[]; RCVD_COUNT_FIVE(0.00)[5]; R_DKIM_ALLOW(0.00)[collabora.com:s=mail]; FROM_NEQ_ENVFROM(0.00)[cristian.ciocaltea@collabora.com,linux-sunxi@lists.linux.dev]; DMARC_POLICY_ALLOW(0.00)[collabora.com,none]; FREEMAIL_TO(0.00)[intel.com,linaro.org,kernel.org,ideasonboard.com,kwiboo.se,gmail.com,bootlin.com,linux.intel.com,suse.de,ffwll.ch,sholland.org,raspberrypi.com,igalia.com,rock-chips.com,sntech.de,collabora.com,nxp.com,baylibre.com]; DKIM_TRACE(0.00)[collabora.com:+]; TO_DN_SOME(0.00)[]; R_SPF_ALLOW(0.00)[+ip4:172.234.253.10]; FORGED_SENDER_MAILLIST(0.00)[]; FORGED_RECIPIENTS_MAILLIST(0.00)[]; RCVD_TLS_LAST(0.00)[]; ARC_ALLOW(0.00)[subspace.kernel.org:s=arc-20240116:i=1]; MIME_TRACE(0.00)[0:+]; TAGGED_FROM(0.00)[bounces-24645-noreply=patchwork.local]; ASN(0.00)[asn:63949, ipnet:172.234.224.0/19, country:SG]; RCVD_VIA_SMTP_AUTH(0.00)[] X-Rspamd-Queue-Id: 0001C1C2E7B 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?= In preparation for providing HDMI 2.x source capabilities, move the vendor, product, supported_formats and max_bpc parameters out of the init function into struct drm_connector_hdmi_funcs, and add new supported_hdmi_ver and supported_tmds_char_rate fields there as well. Appending more HDMI-specific arguments to that function would not scale well, hence introduce drmm_connector_hdmi_init() with the reduced signature. Additionally, add the max_tmds_char_rate field to struct drm_connector_hdmi and use the supported HDMI version to determinate the maximum TMDS character rate allowed by the specification. Some controllers, however, may support a lower rate than that version would imply. A non-zero supported_tmds_char_rate lets drivers override this default with the actual controller capability. A value of zero keeps the limit inferred from supported_hdmi_ver. Callers are converted in the following patches, while the old and now renamed *_ini2() helper is removed at the end of the series. No functional changes expected for existing callers. Signed-off-by: Cristian Ciocaltea --- drivers/gpu/drm/drm_connector.c | 134 ++++++++++++++++++++++++++++++++++++++++ include/drm/drm_connector.h | 62 ++++++++++++++++++- 2 files changed, 195 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c index a112a522807e..72b630434802 100644 --- a/drivers/gpu/drm/drm_connector.c +++ b/drivers/gpu/drm/drm_connector.c @@ -542,6 +542,140 @@ int drmm_connector_init(struct drm_device *dev, } EXPORT_SYMBOL(drmm_connector_init); +/** + * drmm_connector_hdmi_init - Init a preallocated HDMI connector + * @dev: DRM device + * @connector: A pointer to the HDMI connector to init + * @funcs: callbacks for this connector + * @hdmi_funcs: HDMI-related callbacks and capabilities for this connector + * @connector_type: user visible type of the connector + * @ddc: optional pointer to the associated ddc adapter + * + * Initialises a preallocated HDMI connector. Connectors can be + * subclassed as part of driver connector objects. + * + * Cleanup is automatically handled with a call to + * drm_connector_cleanup() in a DRM-managed action. + * + * The connector structure should be allocated with drmm_kzalloc(). + * + * The @drm_connector_funcs.destroy hook must be NULL. + * + * Returns: + * Zero on success, error code on failure. + */ +int drmm_connector_hdmi_init(struct drm_device *dev, + struct drm_connector *connector, + const struct drm_connector_funcs *funcs, + const struct drm_connector_hdmi_funcs *hdmi_funcs, + int connector_type, + struct i2c_adapter *ddc) +{ + int ret; + + if (!hdmi_funcs) + return -EINVAL; + + if (!hdmi_funcs->vendor || !hdmi_funcs->product) + return -EINVAL; + + if ((strlen(hdmi_funcs->vendor) > DRM_CONNECTOR_HDMI_VENDOR_LEN) || + (strlen(hdmi_funcs->product) > DRM_CONNECTOR_HDMI_PRODUCT_LEN)) + return -EINVAL; + + if (!hdmi_funcs->supported_formats || + !(hdmi_funcs->supported_formats & BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444))) + return -EINVAL; + + if (connector->ycbcr_420_allowed != + !!(hdmi_funcs->supported_formats & BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR420))) + return -EINVAL; + + if (!(hdmi_funcs->max_bpc == 8 || + hdmi_funcs->max_bpc == 10 || + hdmi_funcs->max_bpc == 12)) + return -EINVAL; + + if (!hdmi_funcs->avi.clear_infoframe || + !hdmi_funcs->avi.write_infoframe || + !hdmi_funcs->hdmi.clear_infoframe || + !hdmi_funcs->hdmi.write_infoframe) + return -EINVAL; + + if (!(connector_type == DRM_MODE_CONNECTOR_HDMIA || + connector_type == DRM_MODE_CONNECTOR_HDMIB)) + return -EINVAL; + + ret = drmm_connector_init(dev, connector, funcs, connector_type, ddc); + if (ret) + return ret; + + /* TODO: remove after conversion to new drmm_connector_hdmi_init() */ + connector->hdmi.supported_formats = hdmi_funcs->supported_formats; + + /* + * The supported HDMI version can be used to determinate the maximum + * TMDS character rate allowed by the specification. Some controllers, + * however, may support a lower rate than that version would imply. + * + * A non-zero caps->max_tmds_char_rate lets drivers override this + * default with the actual controller capability. A value of zero keeps + * the limit inferred from supported_hdmi_ver. + */ + if (hdmi_funcs->supported_hdmi_ver >= HDMI_VERSION_2_0) + connector->hdmi.max_tmds_char_rate = HDMI_2_0_TMDS_CHAR_RATE_MAX_HZ; + else if (hdmi_funcs->supported_hdmi_ver >= HDMI_VERSION_1_3) + connector->hdmi.max_tmds_char_rate = HDMI_1_3_TMDS_CHAR_RATE_MAX_HZ; + else if (hdmi_funcs->supported_hdmi_ver >= HDMI_VERSION_1_0) + connector->hdmi.max_tmds_char_rate = HDMI_1_0_TMDS_CHAR_RATE_MAX_HZ; + + if (hdmi_funcs->supported_tmds_char_rate) { + if (hdmi_funcs->supported_tmds_char_rate > connector->hdmi.max_tmds_char_rate) { + drm_err(dev, "Enforced max_tmds_char_rate exceeds %llu spec limit\n", + connector->hdmi.max_tmds_char_rate); + return -EINVAL; + } + connector->hdmi.max_tmds_char_rate = hdmi_funcs->supported_tmds_char_rate; + } + + /* TODO: remove after conversion to new drmm_connector_hdmi_init() */ + strtomem_pad(connector->hdmi.vendor, hdmi_funcs->vendor, 0); + strtomem_pad(connector->hdmi.product, hdmi_funcs->product, 0); + + /* + * drm_connector_attach_max_bpc_property() requires the + * connector to have a state. + */ + if (connector->funcs->atomic_create_state) { + struct drm_connector_state *state; + + state = connector->funcs->atomic_create_state(connector); + if (IS_ERR(state)) + return PTR_ERR(state); + + connector->state = state; + } else if (connector->funcs->reset) { + connector->funcs->reset(connector); + } + + drm_connector_attach_max_bpc_property(connector, 8, hdmi_funcs->max_bpc); + /* TODO: remove after conversion to new drmm_connector_hdmi_init() */ + connector->max_bpc = hdmi_funcs->max_bpc; + + if (hdmi_funcs->max_bpc > 8) + drm_connector_attach_hdr_output_metadata_property(connector); + + ret = drm_connector_attach_color_format_property(connector, + hdmi_funcs->supported_formats); + if (ret) + return ret; + + connector->hdmi.funcs = hdmi_funcs; + + return 0; +} +EXPORT_SYMBOL(drmm_connector_hdmi_init); + /** * drmm_connector_hdmi_ini2 - Init a preallocated HDMI connector * @dev: DRM device diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h index 2e7d75cb0adf..2a49c4d55f77 100644 --- a/include/drm/drm_connector.h +++ b/include/drm/drm_connector.h @@ -1403,8 +1403,50 @@ struct drm_connector_infoframe_funcs { /** * struct drm_connector_hdmi_funcs - drm_hdmi_connector control functions + * and controller capabilities */ struct drm_connector_hdmi_funcs { + /** + * @vendor: HDMI Controller Vendor name. + */ + const char *vendor; + + /** + * @product: HDMI Controller Product name + */ + const char *product; + + /** + * @supported_hdmi_ver: + * + * Maximum HDMI specification version supported by the controller side + * of this connector. This describes the controller capability only; + * the effective link capabilities may be further restricted by the + * sink, bridge, or mode validation. + */ + enum hdmi_version supported_hdmi_ver; + + /** + * @supported_tmds_char_rate: + * + * Maximum TMDS character rate supported by the controller, in Hz. + * A value of 0 means the core should use the default limit implied by + * @supported_hdmi_ver. + */ + unsigned long long supported_tmds_char_rate; + + /** + * @supported_formats: + * + * Bitmask of @drm_output_color_format listing supported output formats. + */ + unsigned long supported_formats; + + /** + * @max_bpc: Maximum bits per char the HDMI connector supports. + */ + unsigned int max_bpc; + /** * @tmds_char_rate_valid: * @@ -2052,7 +2094,19 @@ struct drm_connector_hdmi { unsigned long supported_formats; /** - * @funcs: HDMI connector Control Functions + * @max_tmds_char_rate: Maximum TMDS character rate, in Hz, + * supported by the controller. + * + * This is inferred from &drm_connector_hdmi_funcs.supported_hdmi_ver, + * by default. However, controllers may support a lower rate than that + * specification version would imply. If that is the case, drivers are + * expected to set &drm_connector_hdmi_funcs.supported_tmds_char_rate + * to a non-zero value indicating the actual limit. + */ + unsigned long long max_tmds_char_rate; + + /** + * @funcs: HDMI connector Control Functions and controller capabilities */ const struct drm_connector_hdmi_funcs *funcs; @@ -2549,6 +2603,12 @@ int drmm_connector_init(struct drm_device *dev, const struct drm_connector_funcs *funcs, int connector_type, struct i2c_adapter *ddc); +int drmm_connector_hdmi_init(struct drm_device *dev, + struct drm_connector *connector, + const struct drm_connector_funcs *funcs, + const struct drm_connector_hdmi_funcs *hdmi_funcs, + int connector_type, + struct i2c_adapter *ddc); int drmm_connector_hdmi_ini2(struct drm_device *dev, struct drm_connector *connector, const char *vendor, const char *product,