From patchwork Mon Aug 14 13:56:13 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Maxime Ripard X-Patchwork-Id: 135490 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:b824:0:b0:3f2:4152:657d with SMTP id z4csp2797065vqi; Mon, 14 Aug 2023 07:54:38 -0700 (PDT) X-Google-Smtp-Source: AGHT+IGrvtYZwa+uWigDUjG9j5e/WjvFcD25uQHXVIr6F7/9spJCYvsuKx4JsWl5iqU0uMg1FgNT X-Received: by 2002:a05:6a00:2ea4:b0:675:8f71:290a with SMTP id fd36-20020a056a002ea400b006758f71290amr13581312pfb.34.1692024878348; Mon, 14 Aug 2023 07:54:38 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1692024878; cv=none; d=google.com; s=arc-20160816; b=U6V5CORp8O3XVVozdrVExrR5fCrmeGsEtXLTRpuI+MpKggUHH5LOG4DnTLAc/nPCet pKB4IeSwXPu72+v/94I9t9r4n7pOHYqZwneCOsNJ3CtTC370V32PDc/qu9GtO+9hut5t +VI6FTM1oZM/bGstV6Cvw8f3o6YjhIJAwn6iBdFq10eJBKw+fnJj4wNywAZxEcPFNqd+ wvWunIsir0w1nKxBcGs0VHoDKr4+9iTOSP01ZyOQW8CH2Sw89b7WAXYW5QfGEBnXR7x7 Xlt8UyCtHfln/MbtLwcR0AhHvgPlsNfeK4nJGrOoI4L3XpYN/sGvUOA3u5/3EQHenkg5 vPZw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:cc:to:in-reply-to:references:message-id :content-transfer-encoding:mime-version:subject:date:from :dkim-signature; bh=NVjUTx9x4rj5s7W87ZjmeVhYbioq7zTCpIXFAHPoO+w=; fh=XsS7fCnS6jyV48OHq4AWazZQaFUKJmjcq7fZaQkmGOY=; b=epu7c8wunhX66J7UXhx1Bc+GDOzxsH8PHkS/FDGK0u+RHvA5DfFU679p7MVn80YZ9D UIy8UremqPWLETG2BOeX6+r4GzW3/zhn+0vJz+u8eni/wM4EOTOJhHoCqSkPI+LSSc97 gjcV1Dsax1KNWhJt4205NjZmJ/n4C0zwamIZiDCpaK4IsrBiJKGOqDViPCxAU8X5pE7Z c+8GdwThkOCParFXBpmEdwdB2CyNy7PnkCDMKRYDOGNnB1cUoHrJsDa2zDtGNAURvXkc kXQvKt2tLr1GmBL00/u4s8dWKtKe9XyM27I3sUOSDLr5nmBQcABvwC1+gn43abkBhfrf XsRQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=oUwTESRp; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id u11-20020a056a00124b00b00682759c6440si8245903pfi.40.2023.08.14.07.54.24; Mon, 14 Aug 2023 07:54:38 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=oUwTESRp; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231685AbjHNN4y (ORCPT + 99 others); Mon, 14 Aug 2023 09:56:54 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:58632 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231716AbjHNN4a (ORCPT ); Mon, 14 Aug 2023 09:56:30 -0400 Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 05568E7D for ; Mon, 14 Aug 2023 06:56:30 -0700 (PDT) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id 888BA61A55 for ; Mon, 14 Aug 2023 13:56:29 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 94BE4C433CA; Mon, 14 Aug 2023 13:56:28 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1692021388; bh=IFS4dquHs0GVQ0YNk9O4KF71KLDK2GvWdi33+XtiI0Y=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=oUwTESRpQHmK/itub/LZ+yB+K/0T9hdRxVopaO1pGG12CA51ovVKS+ys8I9gEEX6u wPbZSYDhyAfFNYSX3OA6rOzExjD1gyi8Xzi273+JtKKZQPxCCn3yNpTPSfIhiN6vJK 15+MJslTwQU0UcBRsQc6zma3lWDGYvi0TaCBk5G9sQDllJqXiwIvAWKNJEM4V+Hjwf iIefVgX4WVaLyJaFIBb0XoqhihHwyWdgN5fsf9svxVATi3NMRPkOBEQXJAMt0Zr27N 946oBF87lL3++VgVdJEEdyd17KwBC0/IF3RlbHWDwe2UORPNbBbUZN+0UYDujzCa+f /CMFqgzbl+FKA== From: Maxime Ripard Date: Mon, 14 Aug 2023 15:56:13 +0200 Subject: [PATCH RFC 01/13] drm/connector: Introduce an HDMI connector MIME-Version: 1.0 Message-Id: <20230814-kms-hdmi-connector-state-v1-1-048054df3654@kernel.org> References: <20230814-kms-hdmi-connector-state-v1-0-048054df3654@kernel.org> In-Reply-To: <20230814-kms-hdmi-connector-state-v1-0-048054df3654@kernel.org> To: Maarten Lankhorst , Thomas Zimmermann , David Airlie , Daniel Vetter , Emma Anholt Cc: Hans Verkuil , linux-kernel@vger.kernel.org, dri-devel@lists.freedesktop.org, Maxime Ripard X-Mailer: b4 0.12.3 X-Developer-Signature: v=1; a=openpgp-sha256; l=3846; i=mripard@kernel.org; h=from:subject:message-id; bh=IFS4dquHs0GVQ0YNk9O4KF71KLDK2GvWdi33+XtiI0Y=; b=owGbwMvMwCX2+D1vfrpE4FHG02pJDCm3jNqOT/5y68KHkJUz06rK3v+QmXf8rArb+dm3Tua+f PTC5Qn3qo5SFgYxLgZZMUWWGGHzJXGnZr3uZOObBzOHlQlkCAMXpwBM5Ho6I8OSDXrpB15depz6 YNbsK1V8DyvevJj80Crza3r4/Es/XronMPwvEnLtu6p1q5DrxMKma9OuO9Wcj93zfs604+tulYV xOxhxAQA= X-Developer-Key: i=mripard@kernel.org; a=openpgp; fpr=BE5675C37E818C8B5764241C254BCFC56BF6CE8D X-Spam-Status: No, score=-7.1 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_HI, SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1774216678721503254 X-GMAIL-MSGID: 1774216678721503254 A lot of the various HDMI drivers duplicate some logic that depends on the HDMI spec itself and not really a particular hardware implementation. Output BPC or format selection, infoframe generation are good examples of such areas. This creates a lot of boilerplate, with a lot of variations, which makes it hard for userspace to rely on, and makes it difficult to get it right for drivers. Let's create a new connector variant specifically dedicated to HDMI controllers that will allow to abstract away the duplicated logic. Hopefully, this will make drivers simpler to handle, and their behaviour more consistent. Signed-off-by: Maxime Ripard --- drivers/gpu/drm/Makefile | 1 + drivers/gpu/drm/drm_hdmi_connector.c | 45 ++++++++++++++++++++++++++++++++++++ include/drm/drm_connector.h | 16 +++++++++++++ 3 files changed, 62 insertions(+) diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile index 7a09a89b493b..1520d4ccd3d7 100644 --- a/drivers/gpu/drm/Makefile +++ b/drivers/gpu/drm/Makefile @@ -27,6 +27,7 @@ drm-y := \ drm_fourcc.o \ drm_framebuffer.o \ drm_gem.o \ + drm_hdmi_connector.o \ drm_ioctl.o \ drm_lease.o \ drm_managed.o \ diff --git a/drivers/gpu/drm/drm_hdmi_connector.c b/drivers/gpu/drm/drm_hdmi_connector.c new file mode 100644 index 000000000000..62f01dd2e6df --- /dev/null +++ b/drivers/gpu/drm/drm_hdmi_connector.c @@ -0,0 +1,45 @@ +// SPDX-License-Identifier: GPL-2.0+ + +#include +#include + +#include + +/** + * drmm_hdmi_connector_init - Init a preallocated HDMI connector + * @dev: DRM device + * @hdmi_connector: A pointer to the HDMI connector to init + * @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(). + * + * Returns: + * Zero on success, error code on failure. + */ +int drmm_hdmi_connector_init(struct drm_device *dev, + struct drm_hdmi_connector *hdmi_connector, + const struct drm_connector_funcs *funcs, + int connector_type, + struct i2c_adapter *ddc) +{ + struct drm_connector *connector = &hdmi_connector->base; + int ret; + + 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; + + return 0; +} +EXPORT_SYMBOL(drmm_hdmi_connector_init); diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h index d300fde6c1a4..1859b74083f5 100644 --- a/include/drm/drm_connector.h +++ b/include/drm/drm_connector.h @@ -2042,6 +2042,22 @@ void drm_connector_attach_privacy_screen_provider( struct drm_connector *connector, struct drm_privacy_screen *priv); void drm_connector_update_privacy_screen(const struct drm_connector_state *connector_state); +struct drm_hdmi_connector { + /** + * @base: Base Connector + */ + struct drm_connector base; +}; + +#define connector_to_hdmi_connector(connector) \ + container_of_const(connector, struct drm_hdmi_connector, base) + +int drmm_hdmi_connector_init(struct drm_device *dev, + struct drm_hdmi_connector *hdmi_connector, + const struct drm_connector_funcs *funcs, + int connector_type, + struct i2c_adapter *ddc); + /** * struct drm_tile_group - Tile group metadata * @refcount: reference count From patchwork Mon Aug 14 13:56:14 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Maxime Ripard X-Patchwork-Id: 135458 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:b824:0:b0:3f2:4152:657d with SMTP id z4csp2773174vqi; Mon, 14 Aug 2023 07:13:52 -0700 (PDT) X-Google-Smtp-Source: AGHT+IGeKtt4D5Suf5yYoSqlE+cLBxJp6RjDPcVWu8TwRB+2Vl4eDfqszr8hBShr+iJvBh5yYCgK X-Received: by 2002:a17:90b:a17:b0:268:fb85:3b2 with SMTP id gg23-20020a17090b0a1700b00268fb8503b2mr5507761pjb.7.1692022432579; Mon, 14 Aug 2023 07:13:52 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1692022432; cv=none; d=google.com; s=arc-20160816; b=aNaF63Qs2seA3OW6hSjk5SycdKjf3nqLYTRShiD1wtAO1+ulLMw7IpPnB7M3PhjaQe 6/CRtFOm9hW7RQ7hyrUtnpkPoYvWgI5GbRZhv3OSY8UdarXqNeGOkm7LZvUy3MTi2TC9 h7gIWtEam03k2zaECxqNFoRFyBTMB0ruwB1EEGyIPevxq+3lz1ZG6teTs8/SoFGyoxAF zXCZXrQc18TpKVjyIJBPMbC3xe2dsLyItOw/gm7PBumi+9Sb0Ehhe6vWR1eCFmTMwW/i mZtDj9N7vVcw8ovXjyhTzkeQWgb0896PI+K5By0W+hF1xCZmO9Vnrkssmj1eqQzj5rAB C75Q== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:cc:to:in-reply-to:references:message-id :content-transfer-encoding:mime-version:subject:date:from :dkim-signature; bh=luB6djCERiTaO6DssuTNjwuzyXAr0uAUxShBER+FVmI=; fh=XsS7fCnS6jyV48OHq4AWazZQaFUKJmjcq7fZaQkmGOY=; b=mEfXOIPBbi2jVtOTEYC2NYUlcVCQ/XYIr+6x0aHK7Bva2d7rys6/t1sYUH2XrN8yAy xwamUE9fSHscvBZmjaC6QUB0RAPI9wXr6/qpP1RplFEqWMK88KYVpjzSfzq2KuDE4vZE s0wKnC0YRR3+L/2rzFoXi1EZ9Pxt32zVckPjMpMgbd+gI6wY0acUaRx06ZugsCPEE6XV ylp+oZ+1Y4In7tW0Ea8lelL8pFL22M4MLsWz5wYcrt8pH9GIv1yZRBfi0QkXRbAIViPV B0UELZVoBA4JMzSV2AUMLf6Xve1cNx+xWq+Yjjc+9K4ToWssAbccb4rIK5EFYmSAMw2h jIoQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=aculld8D; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id f4-20020a17090a9b0400b00262de4b0d87si8135206pjp.16.2023.08.14.07.13.39; Mon, 14 Aug 2023 07:13:52 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=aculld8D; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231697AbjHNN4z (ORCPT + 99 others); Mon, 14 Aug 2023 09:56:55 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:58682 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231650AbjHNN4e (ORCPT ); Mon, 14 Aug 2023 09:56:34 -0400 Received: from dfw.source.kernel.org (dfw.source.kernel.org [IPv6:2604:1380:4641:c500::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id DFA0110D5 for ; Mon, 14 Aug 2023 06:56:32 -0700 (PDT) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id 7316D61B36 for ; Mon, 14 Aug 2023 13:56:32 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 852F1C433C8; Mon, 14 Aug 2023 13:56:31 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1692021391; bh=x4pLT4i5FibUotLimiVEBeM0gsJhjBOcMTmrY0w2qmc=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=aculld8D7BcKHRQygtDTdI3aSfkcwfGFlmh0hRuWcM/e/Gl4IpVhlTFRuraPDqxdn o5v5trXZj8+1OuC0B3JAJzmy0xialXb/NZfONnmFjITHtxn5HWszITCMyinrwCTRiR AZsnIw7WW4OwO7j3WYLbvgk18akYcJQy22ubo0p1+bQuB+QK0KlDpzud5Tlckvck/x SndbnjQdte8kP8quANc3A79vJiri35z4PSc2xTk7L20x8/n6n9M8NXy4CLSJpysdi8 vHgVVAd/m0uAhQcFiAIlX6h+IRDm7h4BghhgXt28v7cgnfdBrIKL4w23M3ZTCzFuJy yyMEtLVCfYLsg== From: Maxime Ripard Date: Mon, 14 Aug 2023 15:56:14 +0200 Subject: [PATCH RFC 02/13] drm/connector: hdmi: Create a custom state MIME-Version: 1.0 Message-Id: <20230814-kms-hdmi-connector-state-v1-2-048054df3654@kernel.org> References: <20230814-kms-hdmi-connector-state-v1-0-048054df3654@kernel.org> In-Reply-To: <20230814-kms-hdmi-connector-state-v1-0-048054df3654@kernel.org> To: Maarten Lankhorst , Thomas Zimmermann , David Airlie , Daniel Vetter , Emma Anholt Cc: Hans Verkuil , linux-kernel@vger.kernel.org, dri-devel@lists.freedesktop.org, Maxime Ripard X-Mailer: b4 0.12.3 X-Developer-Signature: v=1; a=openpgp-sha256; l=8341; i=mripard@kernel.org; h=from:subject:message-id; bh=x4pLT4i5FibUotLimiVEBeM0gsJhjBOcMTmrY0w2qmc=; b=owGbwMvMwCX2+D1vfrpE4FHG02pJDCm3jNoMNy5+vEWst8j9w/31qV8va57LZdJb/TMi36xmR mMN3+E3HaUsDGJcDLJiiiwxwuZL4k7Net3JxjcPZg4rE8gQBi5OAZjI1mZGhmcTttSI7lv+wWGz 21ee9Q++Nk677/80hPvK6lUbF1+JdFzNyDBhdcgfjvthnBLbVm9Yayx9U3Jd5UT7Q0cnWRXzNf7 ilmcHAA== X-Developer-Key: i=mripard@kernel.org; a=openpgp; fpr=BE5675C37E818C8B5764241C254BCFC56BF6CE8D X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF, RCVD_IN_DNSWL_BLOCKED,SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1774214114210194787 X-GMAIL-MSGID: 1774214114210194787 The next features we will need to share across drivers will need to store some parameters for drivers to use, such as the selected output format. Let's create a new connector state dedicated to HDMI controllers, that will eventually store everything we need. Signed-off-by: Maxime Ripard --- drivers/gpu/drm/drm_hdmi_connector.c | 145 +++++++++++++++++++++++++++++++++++ include/drm/drm_connector.h | 26 +++++++ 2 files changed, 171 insertions(+) diff --git a/drivers/gpu/drm/drm_hdmi_connector.c b/drivers/gpu/drm/drm_hdmi_connector.c index 62f01dd2e6df..ff825c053b27 100644 --- a/drivers/gpu/drm/drm_hdmi_connector.c +++ b/drivers/gpu/drm/drm_hdmi_connector.c @@ -1,10 +1,155 @@ // SPDX-License-Identifier: GPL-2.0+ +#include #include #include #include +/** + * __drm_atomic_helper_hdmi_connector_reset() - Initializes all @drm_hdmi_connector_state resources + * @hdmi_connector: the connector this state refers to + * @new_hdmi_state: the HDMI connector state to initialize + * + * Initializes all relevant resources from a @drm_hdmi_connector_state + * without actually allocating it. This is useful for drivers that + * subclass @drm_hdmi_connector_state. + */ +void __drm_atomic_helper_hdmi_connector_reset(struct drm_hdmi_connector *hdmi_connector, + struct drm_hdmi_connector_state *new_hdmi_state) +{ + struct drm_connector *connector = &hdmi_connector->base; + + __drm_atomic_helper_connector_reset(connector, &new_hdmi_state->base); +} +EXPORT_SYMBOL(__drm_atomic_helper_hdmi_connector_reset); + +/** + * drm_atomic_helper_hdmi_connector_reset() - Create a @drm_hdmi_connector_state object + * @connector: the parent connector + * + * This helper is meant to be the default &drm_connector_funcs.reset + * implementation for @drm_hdmi_connector that don't subclass + * @drm_hdmi_connector_state. + */ +void drm_atomic_helper_hdmi_connector_reset(struct drm_connector *connector) +{ + struct drm_hdmi_connector *hdmi_connector = + connector_to_hdmi_connector(connector); + struct drm_connector_state *old_state = connector->state; + struct drm_hdmi_connector_state *old_hdmi_state = + connector_state_to_hdmi_connector_state(old_state); + struct drm_hdmi_connector_state *new_hdmi_state; + + if (old_state) + __drm_atomic_helper_connector_destroy_state(old_state); + + kfree(old_hdmi_state); + + new_hdmi_state = kzalloc(sizeof(*new_hdmi_state), GFP_KERNEL); + if (!new_hdmi_state) + return; + + __drm_atomic_helper_hdmi_connector_reset(hdmi_connector, new_hdmi_state); +} +EXPORT_SYMBOL(drm_atomic_helper_hdmi_connector_reset); + +/** + * __drm_atomic_helper_hdmi_connector_duplicate_state() - Copies all @drm_hdmi_connector_state resources + * @hdmi_connector: the connector this state refers to + * @new_hdmi_state: the HDMI connector state to copy to + * + * Copies all relevant resources from a @drm_hdmi_connector_state to a + * new one without actually allocating it. This is useful for drivers + * that subclass @drm_hdmi_connector_state. + */ +void +__drm_atomic_helper_hdmi_connector_duplicate_state(struct drm_hdmi_connector *hdmi_connector, + struct drm_hdmi_connector_state *new_hdmi_state) +{ + struct drm_connector *connector = &hdmi_connector->base; + + __drm_atomic_helper_connector_duplicate_state(connector, &new_hdmi_state->base); +} +EXPORT_SYMBOL(__drm_atomic_helper_hdmi_connector_duplicate_state); + +/** + * drm_atomic_helper_hdmi_connector_duplicate_state() - Duplicate a @drm_hdmi_connector_state object + * @connector: the parent connector this state refers to + * + * This helper is meant to be the default + * &drm_connector_funcs.atomic_duplicate_state implementation for + * @drm_hdmi_connector that don't subclass @drm_hdmi_connector_state. + */ +struct drm_connector_state * +drm_atomic_helper_hdmi_connector_duplicate_state(struct drm_connector *connector) +{ + struct drm_hdmi_connector *hdmi_connector = + connector_to_hdmi_connector(connector); + struct drm_hdmi_connector_state *new_hdmi_state; + + new_hdmi_state = kzalloc(sizeof(*new_hdmi_state), GFP_KERNEL); + if (!new_hdmi_state) + return NULL; + + __drm_atomic_helper_hdmi_connector_duplicate_state(hdmi_connector, new_hdmi_state); + + return &new_hdmi_state->base; +} +EXPORT_SYMBOL(drm_atomic_helper_hdmi_connector_duplicate_state); + +/** + * __drm_atomic_helper_hdmi_connector_destroy_state() - Releases all @drm_hdmi_connector_state resources + * @hdmi_state: the HDMI connector state to release + * + * Release all resources stored in @drm_hdmi_connector_state without + * actually freeing it. This is useful for drivers that subclass + * @drm_hdmi_connector_state. + */ +void __drm_atomic_helper_hdmi_connector_destroy_state(struct drm_hdmi_connector_state *hdmi_state) +{ + __drm_atomic_helper_connector_destroy_state(&hdmi_state->base); +} +EXPORT_SYMBOL(__drm_atomic_helper_hdmi_connector_destroy_state); + +/** + * drm_atomic_helper_hdmi_connector_destroy_state() - Destroy a @drm_hdmi_connector_state object + * @connector: the parent connector this state refers to + * @state: the parent connector state to destroy + * + * Destroys an HDMI connector state previously created by + * &drm_atomic_helper_hdmi_connector_reset() or + * &drm_atomic_helper_hdmi_connector_duplicate_state(). + * + * This helper is meant to be the default + * &drm_connector_funcs.atomic_destroy_state implementation for + * @drm_hdmi_connector that don't subclass @drm_hdmi_connector_state. + */ +void drm_atomic_helper_hdmi_connector_destroy_state(struct drm_connector *connector, + struct drm_connector_state *state) +{ + struct drm_hdmi_connector_state *hdmi_state = + connector_state_to_hdmi_connector_state(state); + + __drm_atomic_helper_hdmi_connector_destroy_state(hdmi_state); + kfree(hdmi_state); +} +EXPORT_SYMBOL(drm_atomic_helper_hdmi_connector_destroy_state); + +/** + * drm_atomic_helper_hdmi_connector_print_state - Prints a @drm_hdmi_connector_state + * @p: output printer + * @state: Connector state to print + * + * Default implementation of @drm_connector_funcs.atomic_print_state for + * a @drm_hdmi_connector_state. + */ +void drm_atomic_helper_hdmi_connector_print_state(struct drm_printer *p, + const struct drm_connector_state *state) +{ +} +EXPORT_SYMBOL(drm_atomic_helper_hdmi_connector_print_state); + /** * drmm_hdmi_connector_init - Init a preallocated HDMI connector * @dev: DRM device diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h index 1859b74083f5..0aa662e0a6ea 100644 --- a/include/drm/drm_connector.h +++ b/include/drm/drm_connector.h @@ -2042,6 +2042,32 @@ void drm_connector_attach_privacy_screen_provider( struct drm_connector *connector, struct drm_privacy_screen *priv); void drm_connector_update_privacy_screen(const struct drm_connector_state *connector_state); +struct drm_hdmi_connector_state { + /** + * @base: Base Connector State + */ + struct drm_connector_state base; +}; + +#define connector_state_to_hdmi_connector_state(state) \ + container_of_const(state, struct drm_hdmi_connector_state, base) + +struct drm_hdmi_connector; + +void __drm_atomic_helper_hdmi_connector_reset(struct drm_hdmi_connector *hdmi_connector, + struct drm_hdmi_connector_state *new_hdmi_state); +void drm_atomic_helper_hdmi_connector_reset(struct drm_connector *connector); +void +__drm_atomic_helper_hdmi_connector_duplicate_state(struct drm_hdmi_connector *hdmi_connector, + struct drm_hdmi_connector_state *new_hdmi_state); +struct drm_connector_state * +drm_atomic_helper_hdmi_connector_duplicate_state(struct drm_connector *connector); +void __drm_atomic_helper_hdmi_connector_destroy_state(struct drm_hdmi_connector_state *hdmi_state); +void drm_atomic_helper_hdmi_connector_destroy_state(struct drm_connector *connector, + struct drm_connector_state *state); +void drm_atomic_helper_hdmi_connector_print_state(struct drm_printer *p, + const struct drm_connector_state *state); + struct drm_hdmi_connector { /** * @base: Base Connector From patchwork Mon Aug 14 13:56:15 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Maxime Ripard X-Patchwork-Id: 135487 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:b824:0:b0:3f2:4152:657d with SMTP id z4csp2795855vqi; Mon, 14 Aug 2023 07:52:31 -0700 (PDT) X-Google-Smtp-Source: AGHT+IFiooD2eaD2nPVz7LwrHJ/5rknjFfkh/aCOTVhOgDxSqhmOIxZVvFA6evJjBuIGApGq4c8d X-Received: by 2002:a17:90a:dc10:b0:26b:513a:30b0 with SMTP id i16-20020a17090adc1000b0026b513a30b0mr5280398pjv.10.1692024751533; Mon, 14 Aug 2023 07:52:31 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1692024751; cv=none; d=google.com; s=arc-20160816; b=VHZn+8qpUKPPPslv9lhNqbzd5KBgWbfWmNuuI5gdol1Mk6RUJ2ggNSKoCXckZWmtUE PkvBLFfRwr7kS70Dhfc86Su7QyeuPyIYxVJAIsRZy8M0mV1QtWhSrmLHqQvb2Tp8FDAh yUSabK0cyxNKoGvAoV6gm+BGrXWwR1UbdF29azsjxP8ZxwliKZh1QEsuKtM35RLHJrTV jOpEH88aHJY8m5kXbeDvQfI1KYH6dz1v5DvZQpdZsIh05QfpOtFRVTb0n+y7F1fvDrqn LUUjr+w5A1D3bRVFQBLnEKYOpqxWelWkrEytzoHy5Dvzuv0e3G4gHuk4jTWiwbskwVJ4 rAng== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:cc:to:in-reply-to:references:message-id :content-transfer-encoding:mime-version:subject:date:from :dkim-signature; bh=OVVLeNLmzdjgpiLwP2zeFxaSQhwktwxhrMv01NsgdE8=; fh=XsS7fCnS6jyV48OHq4AWazZQaFUKJmjcq7fZaQkmGOY=; b=GJhP5lsUOaQBkt/Da38UswlU9OBlOygoyfUoV6DQjhpGyNGNJvC8K1ggHsCgojqRAy CQK9QXO2fYJwDwgKyECX4mPN2g4rVE18r8CiTAqA06IKtMYTfgpN1HQGTjrj8e1TIO1R q1i+19+R4bRYoNpG4xA8Eu6amXz7Jcvw3GnOf4WJEF9R4AIcRmRwsLCr5MlfCBZp/i6P 4TwNaXvUVmNSm0aaPbY4IAmwTZLmBvRW1GRQn7NTu1U2wAvy3v647PtEa1JIHEwdHa7z kCaVFOAPjl+JIxHwyCt9QQii+AcIzU1s7YvZSPKMzyGpsuUNHBeRcyydNFz8lOTQrwBE s3ig== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=oLanxg81; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id kz7-20020a170902f9c700b001bbd2599ac7si280595plb.53.2023.08.14.07.52.17; Mon, 14 Aug 2023 07:52:31 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=oLanxg81; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231706AbjHNN45 (ORCPT + 99 others); Mon, 14 Aug 2023 09:56:57 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:58726 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231734AbjHNN4h (ORCPT ); Mon, 14 Aug 2023 09:56:37 -0400 Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id BB4BDE7D for ; Mon, 14 Aug 2023 06:56:35 -0700 (PDT) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id 49CA4614E1 for ; Mon, 14 Aug 2023 13:56:35 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 5BB09C433C7; Mon, 14 Aug 2023 13:56:34 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1692021394; bh=KCNRKYbOYvcCK2lDhLtKnqx5BWVVyZgtzNzIZsf31hw=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=oLanxg81h8wzxSFfjiMBt1yoiSu8YSvc9srjoFWe0LfBiHGqoHmhc5pKZ3SopmXuF r91joWrWfmZmsdkZjrPNFOi6MA0MsgGMHDruwZlS3PZ6ZvsfsjY7VsHx6XM2U+WY0e iHx+csgQTr51bFy8mbt056mEhbfU1qRPjwAwm15cOIz7N8iSu5dLO/y5tOUwJbTZg8 o/980R/wAJ5kZ0OV2JxU4nyaRFhZ6ippQc7nVfPYz0vCMyrJgbL9NcW8C6Hykq5KWW hh/IPz1YUUNUvxpoulM8FhO81PTt2qDHdCC3ppdngbyA7uMpNTICbNM0oaAqUqlCGt wTl545/ZmlGkQ== From: Maxime Ripard Date: Mon, 14 Aug 2023 15:56:15 +0200 Subject: [PATCH RFC 03/13] drm/connector: hdmi: Add Broadcast RGB property MIME-Version: 1.0 Message-Id: <20230814-kms-hdmi-connector-state-v1-3-048054df3654@kernel.org> References: <20230814-kms-hdmi-connector-state-v1-0-048054df3654@kernel.org> In-Reply-To: <20230814-kms-hdmi-connector-state-v1-0-048054df3654@kernel.org> To: Maarten Lankhorst , Thomas Zimmermann , David Airlie , Daniel Vetter , Emma Anholt Cc: Hans Verkuil , linux-kernel@vger.kernel.org, dri-devel@lists.freedesktop.org, Maxime Ripard X-Mailer: b4 0.12.3 X-Developer-Signature: v=1; a=openpgp-sha256; l=11678; i=mripard@kernel.org; h=from:subject:message-id; bh=KCNRKYbOYvcCK2lDhLtKnqx5BWVVyZgtzNzIZsf31hw=; b=owGbwMvMwCX2+D1vfrpE4FHG02pJDCm3jNreOuz1d1po68Ete/mWSVJyx+dD610/LE+x7rj4J tfk03H9jlIWBjEuBlkxRZYYYfMlcadmve5k45sHM4eVCWQIAxenAEykzpaR4ckiEdmovKn7Vj36 1HFh7eXNzJOf9cSUPtWadyCb/6DRrAWMDC/FeDOW/1Q/YrDmW5/1HXNhm4i1GSa7ll3Z82fmzb7 3v/kA X-Developer-Key: i=mripard@kernel.org; a=openpgp; fpr=BE5675C37E818C8B5764241C254BCFC56BF6CE8D X-Spam-Status: No, score=-7.1 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_HI, SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1774216545850156847 X-GMAIL-MSGID: 1774216545850156847 The i915 driver has a property to force the RGB range of an HDMI output. The vc4 driver then implemented the same property with the same semantics. KWin has support for it, and a PR for mutter is also there to support it. Both drivers implementing the same property with the same semantics, plus the userspace having support for it, is proof enough that it's pretty much a de-facto standard now and we can provide helpers for it. Let's plumb it into the newly created HDMI connector. Signed-off-by: Maxime Ripard --- drivers/gpu/drm/drm_hdmi_connector.c | 167 +++++++++++++++++++++++++++++++++++ include/drm/drm_connector.h | 49 ++++++++++ 2 files changed, 216 insertions(+) diff --git a/drivers/gpu/drm/drm_hdmi_connector.c b/drivers/gpu/drm/drm_hdmi_connector.c index ff825c053b27..2b6b9d444774 100644 --- a/drivers/gpu/drm/drm_hdmi_connector.c +++ b/drivers/gpu/drm/drm_hdmi_connector.c @@ -1,8 +1,11 @@ // SPDX-License-Identifier: GPL-2.0+ +#include #include #include +#include #include +#include #include @@ -21,6 +24,8 @@ void __drm_atomic_helper_hdmi_connector_reset(struct drm_hdmi_connector *hdmi_co struct drm_connector *connector = &hdmi_connector->base; __drm_atomic_helper_connector_reset(connector, &new_hdmi_state->base); + + new_hdmi_state->broadcast_rgb = DRM_HDMI_BROADCAST_RGB_AUTO; } EXPORT_SYMBOL(__drm_atomic_helper_hdmi_connector_reset); @@ -68,7 +73,11 @@ __drm_atomic_helper_hdmi_connector_duplicate_state(struct drm_hdmi_connector *hd struct drm_hdmi_connector_state *new_hdmi_state) { struct drm_connector *connector = &hdmi_connector->base; + struct drm_connector_state *old_state = connector->state; + struct drm_hdmi_connector_state *old_hdmi_state = + connector_state_to_hdmi_connector_state(old_state); + new_hdmi_state->broadcast_rgb = old_hdmi_state->broadcast_rgb; __drm_atomic_helper_connector_duplicate_state(connector, &new_hdmi_state->base); } EXPORT_SYMBOL(__drm_atomic_helper_hdmi_connector_duplicate_state); @@ -136,6 +145,143 @@ void drm_atomic_helper_hdmi_connector_destroy_state(struct drm_connector *connec } EXPORT_SYMBOL(drm_atomic_helper_hdmi_connector_destroy_state); +/** + * drm_atomic_helper_hdmi_connector_get_property() - Reads out HDMI connector properties + * @connector: the parent connector this state refers to + * @state: the parent connector state to destroy + * @property: Property instance being queried + * @val: Raw value of the property to read into + * + * Read out a @drm_connector_state property value. + * + * This helper is meant to be the default + * &drm_connector_funcs.atomic_get_property implementation for + * @drm_hdmi_connector. + */ +int drm_atomic_helper_hdmi_connector_get_property(struct drm_connector *connector, + const struct drm_connector_state *state, + struct drm_property *property, + uint64_t *val) +{ + const struct drm_hdmi_connector *hdmi_connector = + connector_to_hdmi_connector(connector); + const struct drm_hdmi_connector_state *hdmi_state = + connector_state_to_hdmi_connector_state(state); + struct drm_device *drm = connector->dev; + + if (property == hdmi_connector->broadcast_rgb_property) { + *val = hdmi_state->broadcast_rgb; + } else { + drm_dbg(drm, "Unknown property [PROP:%d:%s]\n", + property->base.id, property->name); + return -EINVAL; + } + + return 0; +} +EXPORT_SYMBOL(drm_atomic_helper_hdmi_connector_get_property); + +/** + * drm_atomic_helper_hdmi_connector_set_property() - Decodes HDMI connector properties + * @connector: the parent connector this state refers to + * @state: the parent connector state to destroy + * @property: Property instance being queried + * @val: Raw value of the property to decode + * + * Decodes a property into an @drm_connector_state. + * + * This helper is meant to be the default + * &drm_connector_funcs.atomic_set_property implementation for + * @drm_hdmi_connector. + */ +int drm_atomic_helper_hdmi_connector_set_property(struct drm_connector *connector, + struct drm_connector_state *state, + struct drm_property *property, + uint64_t val) +{ + const struct drm_hdmi_connector *hdmi_connector = + connector_to_hdmi_connector(connector); + struct drm_hdmi_connector_state *hdmi_state = + connector_state_to_hdmi_connector_state(state); + struct drm_device *drm = connector->dev; + + if (property == hdmi_connector->broadcast_rgb_property) { + hdmi_state->broadcast_rgb = val; + } else { + drm_dbg(drm, "Unknown property [PROP:%d:%s]\n", + property->base.id, property->name); + return -EINVAL; + } + + return 0; +} +EXPORT_SYMBOL(drm_atomic_helper_hdmi_connector_set_property); + +/** + * drm_atomic_helper_hdmi_connector_atomic_check() - Helper to check HDMI connector atomic state + * @connector: the parent connector this state refers to + * @state: the parent connector state to check + * + * Provides a default connector state check handler for HDMI connectors. + * Checks that a desired connector update is valid, and updates various + * fields of derived state. + * + * Drivers that subclass @drm_hdmi_connector_state may still wish to + * call this function to avoid duplication of error checking code. + * + * RETURNS: + * Zero on success, or an errno code otherwise. + */ +int drm_atomic_helper_hdmi_connector_atomic_check(struct drm_connector *connector, + struct drm_atomic_state *state) +{ + struct drm_connector_state *old_state = + drm_atomic_get_old_connector_state(state, connector); + struct drm_hdmi_connector_state *old_hdmi_state = + connector_state_to_hdmi_connector_state(old_state); + struct drm_connector_state *new_state = + drm_atomic_get_new_connector_state(state, connector); + struct drm_hdmi_connector_state *new_hdmi_state = + connector_state_to_hdmi_connector_state(new_state); + + if (old_hdmi_state->broadcast_rgb != new_hdmi_state->broadcast_rgb) { + struct drm_crtc *crtc = new_state->crtc; + struct drm_crtc_state *crtc_state; + + crtc_state = drm_atomic_get_crtc_state(state, crtc); + if (IS_ERR(crtc_state)) + return PTR_ERR(crtc_state); + + crtc_state->mode_changed = true; + } + + return 0; +} +EXPORT_SYMBOL(drm_atomic_helper_hdmi_connector_atomic_check); + +static const struct drm_prop_enum_list broadcast_rgb_names[] = { + { DRM_HDMI_BROADCAST_RGB_AUTO, "Automatic" }, + { DRM_HDMI_BROADCAST_RGB_FULL, "Full" }, + { DRM_HDMI_BROADCAST_RGB_LIMITED, "Limited 16:235" }, +}; + +/* + * drm_hdmi_connector_get_broadcast_rgb_name - Return a string for HDMI connector RGB broadcast selection + * @broadcast_rgb: Broadcast RGB selection to compute name of + * + * Returns: the name of the Broadcast RGB selection, or NULL if the type + * is not valid. + */ +const char * +drm_hdmi_connector_get_broadcast_rgb_name(enum drm_hdmi_broadcast_rgb broadcast_rgb) +{ + if (broadcast_rgb > DRM_HDMI_BROADCAST_RGB_LIMITED) + return NULL; + + return broadcast_rgb_names[broadcast_rgb].name; +} +EXPORT_SYMBOL(drm_hdmi_connector_get_broadcast_rgb_name); + /** * drm_atomic_helper_hdmi_connector_print_state - Prints a @drm_hdmi_connector_state * @p: output printer @@ -147,6 +293,11 @@ EXPORT_SYMBOL(drm_atomic_helper_hdmi_connector_destroy_state); void drm_atomic_helper_hdmi_connector_print_state(struct drm_printer *p, const struct drm_connector_state *state) { + const struct drm_hdmi_connector_state *hdmi_state = + connector_state_to_hdmi_connector_state(state); + + drm_printf(p, "\tbroadcast_rgb=%s\n", + drm_hdmi_connector_get_broadcast_rgb_name(hdmi_state->broadcast_rgb)); } EXPORT_SYMBOL(drm_atomic_helper_hdmi_connector_print_state); @@ -175,6 +326,7 @@ int drmm_hdmi_connector_init(struct drm_device *dev, struct i2c_adapter *ddc) { struct drm_connector *connector = &hdmi_connector->base; + struct drm_property *prop; int ret; if (connector_type != DRM_MODE_CONNECTOR_HDMIA || @@ -185,6 +337,21 @@ int drmm_hdmi_connector_init(struct drm_device *dev, if (ret) return ret; + prop = hdmi_connector->broadcast_rgb_property; + if (!prop) { + prop = drm_property_create_enum(dev, DRM_MODE_PROP_ENUM, + "Broadcast RGB", + broadcast_rgb_names, + ARRAY_SIZE(broadcast_rgb_names)); + if (!prop) + return -EINVAL; + + hdmi_connector->broadcast_rgb_property = prop; + } + + drm_object_attach_property(&connector->base, prop, + DRM_HDMI_BROADCAST_RGB_AUTO); + return 0; } EXPORT_SYMBOL(drmm_hdmi_connector_init); diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h index 0aa662e0a6ea..24a0d33e5148 100644 --- a/include/drm/drm_connector.h +++ b/include/drm/drm_connector.h @@ -2042,11 +2042,44 @@ void drm_connector_attach_privacy_screen_provider( struct drm_connector *connector, struct drm_privacy_screen *priv); void drm_connector_update_privacy_screen(const struct drm_connector_state *connector_state); +/** + * enum drm_hdmi_broadcast_rgb - Broadcast RGB Selection for a @drm_hdmi_connector + * + * This enum is used to track broadcast RGB selection. There are no + * separate #defines for the uapi! + */ +enum drm_hdmi_broadcast_rgb { + /** + * @DRM_HDMI_BROADCAST_RGB_AUTO: The RGB range is selected + * automatically based on the mode. + */ + DRM_HDMI_BROADCAST_RGB_AUTO, + + /** + * @DRM_HDMI_BROADCAST_RGB_FULL: Full range RGB is forced. + */ + DRM_HDMI_BROADCAST_RGB_FULL, + + /** + * @DRM_HDMI_BROADCAST_RGB_FULL: Limited range RGB is forced. + */ + DRM_HDMI_BROADCAST_RGB_LIMITED, +}; + +const char * +drm_hdmi_connector_get_broadcast_rgb_name(enum drm_hdmi_broadcast_rgb broadcast_rgb); + struct drm_hdmi_connector_state { /** * @base: Base Connector State */ struct drm_connector_state base; + + /** + * @broadcast_rgb: Connector property to pass the Broadcast RGB + * selection value. + */ + enum drm_hdmi_broadcast_rgb broadcast_rgb; }; #define connector_state_to_hdmi_connector_state(state) \ @@ -2065,6 +2098,16 @@ drm_atomic_helper_hdmi_connector_duplicate_state(struct drm_connector *connector void __drm_atomic_helper_hdmi_connector_destroy_state(struct drm_hdmi_connector_state *hdmi_state); void drm_atomic_helper_hdmi_connector_destroy_state(struct drm_connector *connector, struct drm_connector_state *state); +int drm_atomic_helper_hdmi_connector_get_property(struct drm_connector *connector, + const struct drm_connector_state *state, + struct drm_property *property, + uint64_t *val); +int drm_atomic_helper_hdmi_connector_set_property(struct drm_connector *connector, + struct drm_connector_state *state, + struct drm_property *property, + uint64_t val); +int drm_atomic_helper_hdmi_connector_atomic_check(struct drm_connector *connector, + struct drm_atomic_state *state); void drm_atomic_helper_hdmi_connector_print_state(struct drm_printer *p, const struct drm_connector_state *state); @@ -2073,6 +2116,12 @@ struct drm_hdmi_connector { * @base: Base Connector */ struct drm_connector base; + + /** + * @broadcast_rgb_property: Connector property to set the + * Broadcast RGB selection to output with. + */ + struct drm_property *broadcast_rgb_property; }; #define connector_to_hdmi_connector(connector) \ From patchwork Mon Aug 14 13:56:16 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Maxime Ripard X-Patchwork-Id: 135489 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:b824:0:b0:3f2:4152:657d with SMTP id z4csp2796084vqi; Mon, 14 Aug 2023 07:52:54 -0700 (PDT) X-Google-Smtp-Source: AGHT+IFxJHkOrpEhsdq4GMzElt/JrpvGw34ZB/E6qbbACVxZuxT1A2EZelHGxMXlCf6AfCFQMHlX X-Received: by 2002:a05:6a20:970e:b0:133:bc8:e362 with SMTP id hr14-20020a056a20970e00b001330bc8e362mr8174387pzc.24.1692024773667; Mon, 14 Aug 2023 07:52:53 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1692024773; cv=none; d=google.com; s=arc-20160816; b=cmRuvOjzPUAMh7+Bq6wzciFLhc4ygVzqVUYH0of/GuV1WPf2e/kuH+3K2YgVt+4R44 QIEi3Du9iIdQ8uU+TFnuCTBYMj6+sVE7T25ENsiVamR+7zgQSr2iOhoCuMtmYVeJMYOq 3Ed91NWjg6LNQ8K0onXqUy8sau5VjMxVFz0odJMwJ8jTIbWC2jpSuOXsqNuuN4XIo7lj fvf/8oG3ymiEA3oRVqaVG7/D4WrW58vyQmVlZBaBI8kkoJJfiiy73AKnT2eaD+/NOGT9 HpcSXhp95INqSP9TOpnXVEZot+d2I3OBy+9nN4KXKVnsogfTih+8Lh+caktvLkxwZFZu gCoQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:cc:to:in-reply-to:references:message-id :content-transfer-encoding:mime-version:subject:date:from :dkim-signature; bh=YuICyHvY5msHZ70KbazpnakoRQ4X2nf7oZdsJ8qCMrg=; fh=XsS7fCnS6jyV48OHq4AWazZQaFUKJmjcq7fZaQkmGOY=; b=G3ue3u9d22Qujqom8NgC54UEaY3TyW3ob6kS4QChrZ9wPSIE0bpyriPnHSgBpEBo6r V+IHMJPtPVf9HwdoWCaoRCuKyE85gvy28Zb6ZIopG9DHJRwojoEUWuQHvMnQzP40V4ZF IzTkdrziEjYks/H+Vt5La/ih0AQDf7IXLJGYHJDUJjXVq+LdexibAcWyZAo6G33k/ZFp SDzfK4ud+wQ+0IXcqhlVJ08riKrSsqmK49KW1QUeXSMp1TJQL6w1VVLYpECFsuhh7lDW f0BWMch9WRgpwSQJeNN8jABBHTE5KpEJ6v5idM6RZwXpak3K9f+3nmqhdgZTnNA6/TxC o2Qg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=tFOUcoCE; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id bg26-20020a056a02011a00b00565d39bd2fasi225221pgb.888.2023.08.14.07.52.39; Mon, 14 Aug 2023 07:52:53 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=tFOUcoCE; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231730AbjHNN47 (ORCPT + 99 others); Mon, 14 Aug 2023 09:56:59 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:58732 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231736AbjHNN4j (ORCPT ); Mon, 14 Aug 2023 09:56:39 -0400 Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 954ABE7D for ; Mon, 14 Aug 2023 06:56:38 -0700 (PDT) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id 2C7FB60EB3 for ; Mon, 14 Aug 2023 13:56:38 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 3CF3BC433C8; Mon, 14 Aug 2023 13:56:37 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1692021397; bh=xncxvAN3MA7dUdThQOc9ObR8DlJZbK6zrzIZ9Rr5e+g=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=tFOUcoCEblzCovC6vIAmcu6VvgwiC1seZybo15XnOrWKEOdXTeK2U2HBHsjUjyLtt kyZb7RIAWXDMNx9ryc+Eap46C6QsEuuWJOtd7T7kbA3fHXCxVpjFtSJgm7G9oNHedD 5bGA6zrGqmubVE/k423o1ulQs05hDE0e/DRuDZwwZ0iG7AjvEKxY4eB5KaIgUatPNL XiEULINTY5sIOv8ssZ6nzpht6n7QzFxPPQPldMbZeOAEWaJyXw54uRUiVku9bNW38N sxLA+XeEYwyyydS3w19JEv1quii/x2t7Fu/9Sl48FwOT6QGWzE0kzPNXuF0eeh+qKm gMyNn73KNQs8Q== From: Maxime Ripard Date: Mon, 14 Aug 2023 15:56:16 +0200 Subject: [PATCH RFC 04/13] drm/connector: hdmi: Add helper to get the RGB range MIME-Version: 1.0 Message-Id: <20230814-kms-hdmi-connector-state-v1-4-048054df3654@kernel.org> References: <20230814-kms-hdmi-connector-state-v1-0-048054df3654@kernel.org> In-Reply-To: <20230814-kms-hdmi-connector-state-v1-0-048054df3654@kernel.org> To: Maarten Lankhorst , Thomas Zimmermann , David Airlie , Daniel Vetter , Emma Anholt Cc: Hans Verkuil , linux-kernel@vger.kernel.org, dri-devel@lists.freedesktop.org, Maxime Ripard X-Mailer: b4 0.12.3 X-Developer-Signature: v=1; a=openpgp-sha256; l=3563; i=mripard@kernel.org; h=from:subject:message-id; bh=xncxvAN3MA7dUdThQOc9ObR8DlJZbK6zrzIZ9Rr5e+g=; b=owGbwMvMwCX2+D1vfrpE4FHG02pJDCm3jNp2KO/YWH/ShOOa4b0u7Q8rg56u0Xc91fEs1vzi8 fY2zSf/OkpZGMS4GGTFFFlihM2XxJ2a9bqTjW8ezBxWJpAhDFycAjARUWlGhlt7D5bl2Emo7dn9 +rlCAONJNSGulErfN3ITzrclSV3z3MbIsPVHRua6XtV/1rufbRUrDnn/tefvgzo95gDjyymC111 4mQE= X-Developer-Key: i=mripard@kernel.org; a=openpgp; fpr=BE5675C37E818C8B5764241C254BCFC56BF6CE8D X-Spam-Status: No, score=-7.1 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_HI, SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1774216569255727013 X-GMAIL-MSGID: 1774216569255727013 HDMI controller drivers will need to figure out the RGB range they need to configure based on a given atomic state. Let's provide a helper to provide that information. Signed-off-by: Maxime Ripard --- drivers/gpu/drm/drm_hdmi_connector.c | 41 ++++++++++++++++++++++++++++++++++++ include/drm/drm_connector.h | 4 ++++ 2 files changed, 45 insertions(+) diff --git a/drivers/gpu/drm/drm_hdmi_connector.c b/drivers/gpu/drm/drm_hdmi_connector.c index 2b6b9d444774..1fe3f3ebf719 100644 --- a/drivers/gpu/drm/drm_hdmi_connector.c +++ b/drivers/gpu/drm/drm_hdmi_connector.c @@ -4,6 +4,7 @@ #include #include #include +#include #include #include @@ -217,6 +218,15 @@ int drm_atomic_helper_hdmi_connector_set_property(struct drm_connector *connecto } EXPORT_SYMBOL(drm_atomic_helper_hdmi_connector_set_property); +static const struct drm_display_mode * +connector_state_get_adjusted_mode(const struct drm_connector_state *state) +{ + struct drm_crtc *crtc = state->crtc; + struct drm_crtc_state *crtc_state = crtc->state; + + return &crtc_state->adjusted_mode; +} + /** * drm_atomic_helper_hdmi_connector_atomic_check() - Helper to check HDMI connector atomic state * @connector: the parent connector this state refers to @@ -259,6 +269,37 @@ int drm_atomic_helper_hdmi_connector_atomic_check(struct drm_connector *connecto } EXPORT_SYMBOL(drm_atomic_helper_hdmi_connector_atomic_check); +/** + * drm_atomic_helper_hdmi_connector_is_full_range() - Checks whether a state uses Full-Range RGB + * @hdmi_connector: the HDMI connector this state refers to + * @hdmi_state: the HDMI connector state to check + * + * RETURNS: + * True if @hdmi_state requires a Full range RGB output, False otherwise + */ +bool +drm_atomic_helper_hdmi_connector_is_full_range(const struct drm_hdmi_connector *hdmi_connector, + const struct drm_hdmi_connector_state *hdmi_state) +{ + const struct drm_connector *connector = &hdmi_connector->base; + const struct drm_connector_state *conn_state = &hdmi_state->base; + const struct drm_display_mode *mode = + connector_state_get_adjusted_mode(conn_state); + const struct drm_display_info *display = &connector->display_info; + + if (hdmi_state->broadcast_rgb == DRM_HDMI_BROADCAST_RGB_FULL) + return true; + + if (hdmi_state->broadcast_rgb == DRM_HDMI_BROADCAST_RGB_LIMITED) + return false; + + if (!display->is_hdmi) + return true; + + return drm_default_rgb_quant_range(mode); +} +EXPORT_SYMBOL(drm_atomic_helper_hdmi_connector_is_full_range); + static const struct drm_prop_enum_list broadcast_rgb_names[] = { { DRM_HDMI_BROADCAST_RGB_AUTO, "Automatic" }, { DRM_HDMI_BROADCAST_RGB_FULL, "Full" }, diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h index 24a0d33e5148..dff95e6e2b48 100644 --- a/include/drm/drm_connector.h +++ b/include/drm/drm_connector.h @@ -2111,6 +2111,10 @@ int drm_atomic_helper_hdmi_connector_atomic_check(struct drm_connector *connecto void drm_atomic_helper_hdmi_connector_print_state(struct drm_printer *p, const struct drm_connector_state *state); +bool +drm_atomic_helper_hdmi_connector_is_full_range(const struct drm_hdmi_connector *hdmi_connector, + const struct drm_hdmi_connector_state *hdmi_state); + struct drm_hdmi_connector { /** * @base: Base Connector From patchwork Mon Aug 14 13:56:17 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Maxime Ripard X-Patchwork-Id: 135460 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:b824:0:b0:3f2:4152:657d with SMTP id z4csp2773371vqi; Mon, 14 Aug 2023 07:14:11 -0700 (PDT) X-Google-Smtp-Source: AGHT+IHMKLBr9W75WkLXMC1UEYnTUqDU6RxOMFp45xig7YB15Z2p7zO8CFhI2MPVwnhvtSekex4t X-Received: by 2002:a17:902:e84b:b0:1b8:af7f:6331 with SMTP id t11-20020a170902e84b00b001b8af7f6331mr9428995plg.55.1692022451195; Mon, 14 Aug 2023 07:14:11 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1692022451; cv=none; d=google.com; s=arc-20160816; b=0zkIKH+vwCf+MRCEhIX/XzI4q9i6gS8pPfbBgfyHObBwg9smxVmKbV1jJj3fGSF/9f nye4JWfDwhdw5kUqacyZo8knjsW5LgyVReZm1svAWwfcO4M4D5ksKdBo0b+xrrljC1Lz ZjeS0mqENZAsV+DcFXgNkhxyuUR4YE40TTSt231d5nmYtVxncp9kscybhQsn6KEiY279 f2AhVs5uwXUXFNgMabRBrVICjqG54XKqEHGR3T67jJf0HMqon+xqDIcu/1WsA9CiSKLP sokhKMKQ3zGY94GZeAt2VbOgNX1BtKggLEd3693DFQNu1n40kN0vFB9WQsmTsSw91EIq eyrA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:cc:to:in-reply-to:references:message-id :content-transfer-encoding:mime-version:subject:date:from :dkim-signature; bh=6ycZmtCMKjv+bWCUF4WWaG8yX+TKOIhyEnFY8FyTcHM=; fh=XsS7fCnS6jyV48OHq4AWazZQaFUKJmjcq7fZaQkmGOY=; b=isWacHF+TBLo5kbIsZt5SlAtBy8HFLDwaOyH7FJguVSj6DLRy166lC8odNuWXlN6CV qt/D0lzgFVXEhHXjdcYnTnjbUtZ+K4qMZGB8pdL9CtaNXX0LRBLTKC5KwtS6GVMtuYC5 UBmLN3XW4CirqzugD0Ssfb3g6B0z170qVngEXI2gGsOhf+2r3VYOu3iY1mbz92dXvOLa Uy27K+x3JeWBw8VESvlu9ccHoKt0w+wEipfnxrZzffLzOxyLZCvFM340DTtMefHk39vK 4HffBLq68yS8nl6J1+S7zg6lp1MJt1jGmWwvudat4b4X4xi26/w8LnmIvJRpuvjpAHfr s9RA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=DqSrboWq; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id u7-20020a170902b28700b001bb9d6794d3si8092214plr.72.2023.08.14.07.13.57; Mon, 14 Aug 2023 07:14:11 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=DqSrboWq; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231750AbjHNN5B (ORCPT + 99 others); Mon, 14 Aug 2023 09:57:01 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:55520 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231494AbjHNN4m (ORCPT ); Mon, 14 Aug 2023 09:56:42 -0400 Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 51162E6D for ; Mon, 14 Aug 2023 06:56:41 -0700 (PDT) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id E325260EB3 for ; Mon, 14 Aug 2023 13:56:40 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id F0C79C433CA; Mon, 14 Aug 2023 13:56:39 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1692021400; bh=oWUDOi4NfdQFSp0O5CoIevtT3gTEWUAlM+FIqPYfeaU=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=DqSrboWq+iUh8KA2DjsHy6RX2Tg2W7xKKlty5uSJEilpYePLA6Rk8+FGRU4ZDKROj galX+EsAcFXAE8KXpKlq6FOdSg+Jj+MuHPrYThAQDPBg8CI3z3SW7n3BCEVGsUzATj Hhz7yxHaqzhBJmxZ954lN+3BMthy4Mp+fT8sxJdSyPfwh5+La64ktyQEezuxbemCoa 7Ti4q7Fc80yQqZ4VjYHsvjex4q1f3QdU6p0mHmlsm7t2TKMWVUrv3ObQ16y7Mm+/a9 KAfjqnYisC5CSU3sGVTWJh1vd+b3u+S3oWcZAszA+okhWKccXQPteey2sl/y79RCxy g2NN+KFFS35Yg== From: Maxime Ripard Date: Mon, 14 Aug 2023 15:56:17 +0200 Subject: [PATCH RFC 05/13] drm/connector: hdmi: Add output BPC to the connector state MIME-Version: 1.0 Message-Id: <20230814-kms-hdmi-connector-state-v1-5-048054df3654@kernel.org> References: <20230814-kms-hdmi-connector-state-v1-0-048054df3654@kernel.org> In-Reply-To: <20230814-kms-hdmi-connector-state-v1-0-048054df3654@kernel.org> To: Maarten Lankhorst , Thomas Zimmermann , David Airlie , Daniel Vetter , Emma Anholt Cc: Hans Verkuil , linux-kernel@vger.kernel.org, dri-devel@lists.freedesktop.org, Maxime Ripard X-Mailer: b4 0.12.3 X-Developer-Signature: v=1; a=openpgp-sha256; l=4839; i=mripard@kernel.org; h=from:subject:message-id; bh=oWUDOi4NfdQFSp0O5CoIevtT3gTEWUAlM+FIqPYfeaU=; b=owGbwMvMwCX2+D1vfrpE4FHG02pJDCm3jNq+zLuQt/ZF2JTgDS9+Sm8rUHP1EDUJaYyXXinOH qCzIGViRykLgxgXg6yYIkuMsPmSuFOzXney8c2DmcPKBDKEgYtTACYyPYqR4ZZl1Ovi92v+nsiz v3xjRQmD7fSfPbfniHxcF3v1X+K3GyKMDNd9tzHWxQoeuKu6ON/54KJ6J8Hq/TvFw/mSOi3sdzj JMQIA X-Developer-Key: i=mripard@kernel.org; a=openpgp; fpr=BE5675C37E818C8B5764241C254BCFC56BF6CE8D X-Spam-Status: No, score=-7.1 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_HI, SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1774214133689091635 X-GMAIL-MSGID: 1774214133689091635 We'll add automatic selection of the output BPC in a following patch, but let's add it to the HDMI connector state already. Signed-off-by: Maxime Ripard --- drivers/gpu/drm/drm_hdmi_connector.c | 21 +++++++++++++++++++-- include/drm/drm_connector.h | 13 ++++++++++++- 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/drm_hdmi_connector.c b/drivers/gpu/drm/drm_hdmi_connector.c index 1fe3f3ebf719..6d5535e613c6 100644 --- a/drivers/gpu/drm/drm_hdmi_connector.c +++ b/drivers/gpu/drm/drm_hdmi_connector.c @@ -26,6 +26,9 @@ void __drm_atomic_helper_hdmi_connector_reset(struct drm_hdmi_connector *hdmi_co __drm_atomic_helper_connector_reset(connector, &new_hdmi_state->base); + new_hdmi_state->base.max_bpc = 8; + new_hdmi_state->base.max_requested_bpc = 8; + new_hdmi_state->output_bpc = 8; new_hdmi_state->broadcast_rgb = DRM_HDMI_BROADCAST_RGB_AUTO; } EXPORT_SYMBOL(__drm_atomic_helper_hdmi_connector_reset); @@ -78,6 +81,7 @@ __drm_atomic_helper_hdmi_connector_duplicate_state(struct drm_hdmi_connector *hd struct drm_hdmi_connector_state *old_hdmi_state = connector_state_to_hdmi_connector_state(old_state); + new_hdmi_state->output_bpc = old_hdmi_state->output_bpc; new_hdmi_state->broadcast_rgb = old_hdmi_state->broadcast_rgb; __drm_atomic_helper_connector_duplicate_state(connector, &new_hdmi_state->base); } @@ -254,7 +258,8 @@ int drm_atomic_helper_hdmi_connector_atomic_check(struct drm_connector *connecto struct drm_hdmi_connector_state *new_hdmi_state = connector_state_to_hdmi_connector_state(new_state); - if (old_hdmi_state->broadcast_rgb != new_hdmi_state->broadcast_rgb) { + if (old_hdmi_state->broadcast_rgb != new_hdmi_state->broadcast_rgb || + old_hdmi_state->output_bpc != new_hdmi_state->output_bpc) { struct drm_crtc *crtc = new_state->crtc; struct drm_crtc_state *crtc_state; @@ -339,6 +344,7 @@ void drm_atomic_helper_hdmi_connector_print_state(struct drm_printer *p, drm_printf(p, "\tbroadcast_rgb=%s\n", drm_hdmi_connector_get_broadcast_rgb_name(hdmi_state->broadcast_rgb)); + drm_printf(p, "\toutput_bpc=%u\n", hdmi_state->output_bpc); } EXPORT_SYMBOL(drm_atomic_helper_hdmi_connector_print_state); @@ -348,6 +354,7 @@ EXPORT_SYMBOL(drm_atomic_helper_hdmi_connector_print_state); * @hdmi_connector: A pointer to the HDMI connector to init * @connector_type: user visible type of the connector * @ddc: optional pointer to the associated ddc adapter + * @max_bpc: Maximum bits per char the HDMI connector supports * * Initialises a preallocated HDMI connector. Connectors can be * subclassed as part of driver connector objects. @@ -364,7 +371,8 @@ int drmm_hdmi_connector_init(struct drm_device *dev, struct drm_hdmi_connector *hdmi_connector, const struct drm_connector_funcs *funcs, int connector_type, - struct i2c_adapter *ddc) + struct i2c_adapter *ddc, + unsigned int max_bpc) { struct drm_connector *connector = &hdmi_connector->base; struct drm_property *prop; @@ -393,6 +401,15 @@ int drmm_hdmi_connector_init(struct drm_device *dev, drm_object_attach_property(&connector->base, prop, DRM_HDMI_BROADCAST_RGB_AUTO); + if (max_bpc) { + if (!(max_bpc == 8 || max_bpc == 10 || max_bpc == 12)) + return -EINVAL; + + drm_connector_attach_hdr_output_metadata_property(connector); + drm_connector_attach_max_bpc_property(connector, 8, max_bpc); + hdmi_connector->max_bpc = max_bpc; + } + return 0; } EXPORT_SYMBOL(drmm_hdmi_connector_init); diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h index dff95e6e2b48..353aa8e5a117 100644 --- a/include/drm/drm_connector.h +++ b/include/drm/drm_connector.h @@ -2075,6 +2075,11 @@ struct drm_hdmi_connector_state { */ struct drm_connector_state base; + /** + * @output_bpc: Bits per character to output. + */ + unsigned int output_bpc; + /** * @broadcast_rgb: Connector property to pass the Broadcast RGB * selection value. @@ -2121,6 +2126,11 @@ struct drm_hdmi_connector { */ struct drm_connector base; + /** + * @max_bpc: Maximum bits per character the connector supports. + */ + unsigned int max_bpc; + /** * @broadcast_rgb_property: Connector property to set the * Broadcast RGB selection to output with. @@ -2135,7 +2145,8 @@ int drmm_hdmi_connector_init(struct drm_device *dev, struct drm_hdmi_connector *hdmi_connector, const struct drm_connector_funcs *funcs, int connector_type, - struct i2c_adapter *ddc); + struct i2c_adapter *ddc, + unsigned int max_bpc); /** * struct drm_tile_group - Tile group metadata From patchwork Mon Aug 14 13:56:18 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Maxime Ripard X-Patchwork-Id: 135462 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:b824:0:b0:3f2:4152:657d with SMTP id z4csp2773789vqi; Mon, 14 Aug 2023 07:14:51 -0700 (PDT) X-Google-Smtp-Source: AGHT+IFjLLn78BetCxtinev217LZt0l7PO+EJr0IVG+83CzJj+K9nGhCstME9YaDnIcYjg0Z73Hy X-Received: by 2002:a17:903:1249:b0:1bc:2bd:852a with SMTP id u9-20020a170903124900b001bc02bd852amr15113311plh.42.1692022491449; Mon, 14 Aug 2023 07:14:51 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1692022491; cv=none; d=google.com; s=arc-20160816; b=rPQiV3hLAIQkFt8GbnAzhGB+/b2V4P4QRwqhrSExNLIHvLgRI8WQzTkav5gEuTQhZW PFYr4EkPPVXp+1jqTdsDANAdneCZa8l3BAX7tWbMcG+VR0rZaxGRwiH3kBZVKNXjV7Sd m4YWXPrF9X6QAmB00YgmZ1TwLkp8GJyrbUBnM9HOZ/vtHwOqM9dz0Fp51lCew14ozPC6 WmRXQpcBUDirq6ZK7yErUywXd6icJmiUyFzrQQOJtAis0dGPlyuhCIPRh2pVjYZ7eFDC HcXQAjAGavKG9E0M7gb35aVyQaFQDsy+gVJofAo2K2Kb6rWiCJESAWtLiLfah7O1sbK7 k3jA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:cc:to:in-reply-to:references:message-id :content-transfer-encoding:mime-version:subject:date:from :dkim-signature; bh=01u7mAvXA6nHtMyFxwBbiaSjPsZwNks1KcD6mZznXJE=; fh=XsS7fCnS6jyV48OHq4AWazZQaFUKJmjcq7fZaQkmGOY=; b=JdPcRaAtWMDMKrmhGsbhteweyL3p+LThkXPBe+mNRb3HkoxUH+qpuEZ1OvggnxAB92 r4QqpsldmK3Z5BvoFIgnfsbEfglZF4KpxJ7pr6Vty5twXx0frrUJywUr4iC8sFX/utYN cSeGAHRi+L/r7mH5Q8v/tFrLTJnOChxK49TFiQu1OWvWRaMMTA0cI2OiNrxfr01QQZn+ mKVe1zNNV35THRfY7A5oB3SJQP1KGVQuRKkf7O+IqDT+t8zaK3D4pVvf6ZycD62BjrGr /8Auz01YV8G7AVvfnUV32aZu9OxqMyb2tsSIqm+TwPk2LJmd3O6qiG0FqTfe5XxHa61O lrfw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=eadwZtiC; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id e10-20020a170902b78a00b001b9e39f8e21si8100176pls.127.2023.08.14.07.14.37; Mon, 14 Aug 2023 07:14:51 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=eadwZtiC; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231759AbjHNN5D (ORCPT + 99 others); Mon, 14 Aug 2023 09:57:03 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:55532 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231267AbjHNN4o (ORCPT ); Mon, 14 Aug 2023 09:56:44 -0400 Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 2AEC7E6D for ; Mon, 14 Aug 2023 06:56:44 -0700 (PDT) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id BDEE260EB3 for ; Mon, 14 Aug 2023 13:56:43 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id D3945C433C8; Mon, 14 Aug 2023 13:56:42 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1692021403; bh=pEBIIxPM9wHqohnSBbI/wG/es129PtwIxcG2qf1ek3Y=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=eadwZtiCo59Eo5VViEHS3pAyPR7T+5giEv03vEjLG2WLaJswzSa0apilc4e2q5rNK ++icSIFjNhGuRyPIolHvCdg9VXDf4Pun3zKZ/P223Sxg8njRxP92JTijpyz8rCgiM7 SDvTmb8BVWthHZKDE1b3G5AqA07+Rx9OkIk7obH5ZSWd1KrKl0IDjIRNuzkDw6Uymv riP06t8q/hIf7ubAVxROfiL6B8TeP0TePpIxMzXHxm4vC5X8qIUR+/uIln8jRAGz+K AL7aNEy+vEw1VMU7gGSXquUM09LdpfUUzoecPKl8sNxL1uxVlz775+vhUNFtUAjuHc JabJLO412gayQ== From: Maxime Ripard Date: Mon, 14 Aug 2023 15:56:18 +0200 Subject: [PATCH RFC 06/13] drm/connector: hdmi: Add support for output format MIME-Version: 1.0 Message-Id: <20230814-kms-hdmi-connector-state-v1-6-048054df3654@kernel.org> References: <20230814-kms-hdmi-connector-state-v1-0-048054df3654@kernel.org> In-Reply-To: <20230814-kms-hdmi-connector-state-v1-0-048054df3654@kernel.org> To: Maarten Lankhorst , Thomas Zimmermann , David Airlie , Daniel Vetter , Emma Anholt Cc: Hans Verkuil , linux-kernel@vger.kernel.org, dri-devel@lists.freedesktop.org, Maxime Ripard X-Mailer: b4 0.12.3 X-Developer-Signature: v=1; a=openpgp-sha256; l=3872; i=mripard@kernel.org; h=from:subject:message-id; bh=pEBIIxPM9wHqohnSBbI/wG/es129PtwIxcG2qf1ek3Y=; b=owGbwMvMwCX2+D1vfrpE4FHG02pJDCm3jNoO7r920ks89qX17AynpkJf1g4twx2bTl5i8b723 PfOzTksHaUsDGJcDLJiiiwxwuZL4k7Net3JxjcPZg4rE8gQBi5OAZjIwSyG/yE/N7/j6rANlXbX 2brIYlHEuh8rd88v+y8SaPpQ/8oh3WSG/8U3tyXMDZy+Y9733Du3ZWbt6EtTUVTZJ/7i6rSsr1e ++DIBAA== X-Developer-Key: i=mripard@kernel.org; a=openpgp; fpr=BE5675C37E818C8B5764241C254BCFC56BF6CE8D X-Spam-Status: No, score=-7.1 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_HI, SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1774214176042451097 X-GMAIL-MSGID: 1774214176042451097 Just like BPC, we'll add support for automatic selection of the output format for HDMI connectors. Let's add the needed defaults and fields for now. Signed-off-by: Maxime Ripard --- drivers/gpu/drm/drm_hdmi_connector.c | 29 +++++++++++++++++++++++++++++ include/drm/drm_connector.h | 5 +++++ 2 files changed, 34 insertions(+) diff --git a/drivers/gpu/drm/drm_hdmi_connector.c b/drivers/gpu/drm/drm_hdmi_connector.c index 6d5535e613c6..55f685c0095b 100644 --- a/drivers/gpu/drm/drm_hdmi_connector.c +++ b/drivers/gpu/drm/drm_hdmi_connector.c @@ -29,6 +29,7 @@ void __drm_atomic_helper_hdmi_connector_reset(struct drm_hdmi_connector *hdmi_co new_hdmi_state->base.max_bpc = 8; new_hdmi_state->base.max_requested_bpc = 8; new_hdmi_state->output_bpc = 8; + new_hdmi_state->output_format = HDMI_COLORSPACE_RGB; new_hdmi_state->broadcast_rgb = DRM_HDMI_BROADCAST_RGB_AUTO; } EXPORT_SYMBOL(__drm_atomic_helper_hdmi_connector_reset); @@ -82,6 +83,7 @@ __drm_atomic_helper_hdmi_connector_duplicate_state(struct drm_hdmi_connector *hd connector_state_to_hdmi_connector_state(old_state); new_hdmi_state->output_bpc = old_hdmi_state->output_bpc; + new_hdmi_state->output_format = old_hdmi_state->output_format; new_hdmi_state->broadcast_rgb = old_hdmi_state->broadcast_rgb; __drm_atomic_helper_connector_duplicate_state(connector, &new_hdmi_state->base); } @@ -222,6 +224,30 @@ int drm_atomic_helper_hdmi_connector_set_property(struct drm_connector *connecto } EXPORT_SYMBOL(drm_atomic_helper_hdmi_connector_set_property); +static const char * const output_format_str[] = { + [HDMI_COLORSPACE_RGB] = "RGB", + [HDMI_COLORSPACE_YUV420] = "YUV 4:2:0", + [HDMI_COLORSPACE_YUV422] = "YUV 4:2:2", + [HDMI_COLORSPACE_YUV444] = "YUV 4:4:4", +}; + +/* + * drm_hdmi_connector_get_output_format_name() - Return a string for HDMI connector output format + * @fmt: Output format to compute name of + * + * Returns: the name of the output format, or NULL if the type is not + * valid. + */ +const char * +drm_hdmi_connector_get_output_format_name(enum hdmi_colorspace fmt) +{ + if (fmt >= ARRAY_SIZE(output_format_str)) + return NULL; + + return output_format_str[fmt]; +} +EXPORT_SYMBOL(drm_hdmi_connector_get_output_format_name); + static const struct drm_display_mode * connector_state_get_adjusted_mode(const struct drm_connector_state *state) { @@ -259,6 +285,7 @@ int drm_atomic_helper_hdmi_connector_atomic_check(struct drm_connector *connecto connector_state_to_hdmi_connector_state(new_state); if (old_hdmi_state->broadcast_rgb != new_hdmi_state->broadcast_rgb || + old_hdmi_state->output_format != new_hdmi_state->output_format || old_hdmi_state->output_bpc != new_hdmi_state->output_bpc) { struct drm_crtc *crtc = new_state->crtc; struct drm_crtc_state *crtc_state; @@ -345,6 +372,8 @@ void drm_atomic_helper_hdmi_connector_print_state(struct drm_printer *p, drm_printf(p, "\tbroadcast_rgb=%s\n", drm_hdmi_connector_get_broadcast_rgb_name(hdmi_state->broadcast_rgb)); drm_printf(p, "\toutput_bpc=%u\n", hdmi_state->output_bpc); + drm_printf(p, "\toutput_format=%s\n", + drm_hdmi_connector_get_output_format_name(hdmi_state->output_format)); } EXPORT_SYMBOL(drm_atomic_helper_hdmi_connector_print_state); diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h index 353aa8e5a117..995700110a16 100644 --- a/include/drm/drm_connector.h +++ b/include/drm/drm_connector.h @@ -2080,6 +2080,11 @@ struct drm_hdmi_connector_state { */ unsigned int output_bpc; + /** + * @output_format: Pixel format to output in. + */ + enum hdmi_colorspace output_format; + /** * @broadcast_rgb: Connector property to pass the Broadcast RGB * selection value. From patchwork Mon Aug 14 13:56:19 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Maxime Ripard X-Patchwork-Id: 135461 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:b824:0:b0:3f2:4152:657d with SMTP id z4csp2773785vqi; Mon, 14 Aug 2023 07:14:51 -0700 (PDT) X-Google-Smtp-Source: AGHT+IEUDPVdph62lESPo0QaCa9+OtBJSx3u5sxlLY+0CB19fo/+WJa/7hbEvTkTN7EoMoulqmTP X-Received: by 2002:a05:6a00:3a12:b0:687:3e8f:2211 with SMTP id fj18-20020a056a003a1200b006873e8f2211mr9279552pfb.34.1692022490935; Mon, 14 Aug 2023 07:14:50 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1692022490; cv=none; d=google.com; s=arc-20160816; b=mCYk5TseeTXYGL8F4RMCyDZ2NP51mYZCU7nWNlnrs1JoRxNeSkjkJiAHoFRMAZtF90 KEhqWlZCmRpPyiTupz1NyxK1evh2/G3LfrgZj3dyJd3FV3X5Z6pSV+RrIK1GJZIcMm+H CXsEP7NhOmhhn2nP2HCnjJatfOATMdu20xIqHIcsfSOG6/bOVnUJHduDqGZ6CMBmgzHe 4nh+XrblJOWTLyF9QUwCl1r3CUUabmr5mmjA3v2RsXDwQ2o2BXOITdHKZPToJO67AEut 2Z9ul3b0Jih9C/sBA+o/6RqWSzNtSLAJgt5MCXEA6X/OFIZRz6Wne9h2+r+SsjjriNq3 7uYA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:cc:to:in-reply-to:references:message-id :content-transfer-encoding:mime-version:subject:date:from :dkim-signature; bh=IUCwVjl17ef7K3E0V4gDRNmSEKh4Av+4TQFxRwCSrWk=; fh=XsS7fCnS6jyV48OHq4AWazZQaFUKJmjcq7fZaQkmGOY=; b=O69m1FNxkHb2tPG9QRTdrYnBdEY0zgazeIx9a1c0/BFScD/T+YieEgWOOsDogphKEn XNdOiJ3WdeZBMK+9BDHaGqz56tXxlclJlegUSw48wSboPgKumocFFg3ZOosnDHMBI942 mjxT7dJ6QovrfsmKpZ04tCQ+OyFZni0dNZcqUFFbOJrxpY8qMawXebdXTmp/EjHyaDHr istpb+By3ckTMT06O3+hTM3aP/zoQlWcHyJc4le3vu9RUkpK64RRrPNyVMpIJWcKWQaO s5m5lbScfWRqSBN6VQ+zx00ZzSQ88UbYy0yfW/+JqDUgmnSy3INAFCIaXLVy1tSP81IC r7Iw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=NVcCWJ8p; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id v135-20020a63618d000000b005641fc2684bsi8242334pgb.527.2023.08.14.07.14.37; Mon, 14 Aug 2023 07:14:50 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=NVcCWJ8p; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231768AbjHNN5F (ORCPT + 99 others); Mon, 14 Aug 2023 09:57:05 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:55540 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229668AbjHNN4s (ORCPT ); Mon, 14 Aug 2023 09:56:48 -0400 Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id EA796E6D for ; Mon, 14 Aug 2023 06:56:46 -0700 (PDT) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id 7AAB260EB3 for ; Mon, 14 Aug 2023 13:56:46 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 8D5F3C433C8; Mon, 14 Aug 2023 13:56:45 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1692021405; bh=ui9S2zLXIqp7a7NZ2j9yfURvaM6ingzVBOVAHsIfZMI=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=NVcCWJ8pGVtPfaYsPyATGrGUOAw64t/qcPKTHvhl6mokcB3pm324tqVQihxiGRVmH z9TrtUKpVe6oFIo+H5Z0wFsogWUzcqijJlbrvcsfWWNqkBqY2YmyljeDGzCCZWaUJt CDyPaJRbcQCUPplgEYPqVIaVNJlKoei0cGOv/qbbcIOdLzBcay5JGQ4FdipWvxuAdT rk4jrcljBx6XLmH8igrvPdjdvKTlHzjBflJld9NjUXWoCQR002gWNClwU/KXUksS7f SNwUhuCvh4HCYJgeMzx0YHN3ffRi2G05ZWeyP/PXUDANVo61Vlt7nbEd77GrzJPgJS 2Zx36GTum+q+A== From: Maxime Ripard Date: Mon, 14 Aug 2023 15:56:19 +0200 Subject: [PATCH RFC 07/13] drm/connector: hdmi: Calculate TMDS character rate MIME-Version: 1.0 Message-Id: <20230814-kms-hdmi-connector-state-v1-7-048054df3654@kernel.org> References: <20230814-kms-hdmi-connector-state-v1-0-048054df3654@kernel.org> In-Reply-To: <20230814-kms-hdmi-connector-state-v1-0-048054df3654@kernel.org> To: Maarten Lankhorst , Thomas Zimmermann , David Airlie , Daniel Vetter , Emma Anholt Cc: Hans Verkuil , linux-kernel@vger.kernel.org, dri-devel@lists.freedesktop.org, Maxime Ripard X-Mailer: b4 0.12.3 X-Developer-Signature: v=1; a=openpgp-sha256; l=6299; i=mripard@kernel.org; h=from:subject:message-id; bh=ui9S2zLXIqp7a7NZ2j9yfURvaM6ingzVBOVAHsIfZMI=; b=owGbwMvMwCX2+D1vfrpE4FHG02pJDCm3jNrsLWZW3MpO3VK3v2qzj4bdlCj/F6kCGyavP2y4o qXzwnbljlIWBjEuBlkxRZYYYfMlcadmve5k45sHM4eVCWQIAxenAEyk14KR4UYwW/m3pR2TNMw5 Q95La3179vs8+4fPP5kP5wdv+OtaMIWRYbvvvi/1jB0LemXEmAPn9XGy2a+esS8kkjFt855Kjfb zzAA= X-Developer-Key: i=mripard@kernel.org; a=openpgp; fpr=BE5675C37E818C8B5764241C254BCFC56BF6CE8D X-Spam-Status: No, score=-7.1 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_HI, SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1774214175373080636 X-GMAIL-MSGID: 1774214175373080636 Most HDMI drivers have some code to calculate the TMDS character rate, usually to adjust an internal clock to match what the mode requires. Since the TMDS character rates mostly depends on the resolution, whether we need to repeat pixels or not, the bpc count and the format, we can now derive it from the HDMI connector state that stores all those infos and remove the duplication from drivers. Signed-off-by: Maxime Ripard --- drivers/gpu/drm/drm_hdmi_connector.c | 77 ++++++++++++++++++++++++++++++++++++ include/drm/drm_connector.h | 11 ++++++ 2 files changed, 88 insertions(+) diff --git a/drivers/gpu/drm/drm_hdmi_connector.c b/drivers/gpu/drm/drm_hdmi_connector.c index 55f685c0095b..e49782a284a5 100644 --- a/drivers/gpu/drm/drm_hdmi_connector.c +++ b/drivers/gpu/drm/drm_hdmi_connector.c @@ -82,6 +82,7 @@ __drm_atomic_helper_hdmi_connector_duplicate_state(struct drm_hdmi_connector *hd struct drm_hdmi_connector_state *old_hdmi_state = connector_state_to_hdmi_connector_state(old_state); + new_hdmi_state->tmds_char_rate = old_hdmi_state->tmds_char_rate; new_hdmi_state->output_bpc = old_hdmi_state->output_bpc; new_hdmi_state->output_format = old_hdmi_state->output_format; new_hdmi_state->broadcast_rgb = old_hdmi_state->broadcast_rgb; @@ -257,6 +258,69 @@ connector_state_get_adjusted_mode(const struct drm_connector_state *state) return &crtc_state->adjusted_mode; } +static enum drm_mode_status +drm_hdmi_connector_clock_valid(const struct drm_hdmi_connector *hdmi_connector, + const struct drm_display_mode *mode, + unsigned long long clock) +{ + const struct drm_connector *connector = &hdmi_connector->base; + const struct drm_display_info *info = &connector->display_info; + + if (info->max_tmds_clock && clock > info->max_tmds_clock * 1000) + return MODE_CLOCK_HIGH; + + return MODE_OK; +} + +/** + * drm_hdmi_connector_compute_mode_clock() - Computes the TMDS Character Rate + * @mode: Display mode to compute the clock for + * @bpc: Bits per character + * @fmt: Output Pixel Format used + * + * Returns the TMDS Character Rate for a given mode, bpc count and output format. + * + * RETURNS: + * The TMDS Character Rate, in Hertz + */ +unsigned long long +drm_hdmi_connector_compute_mode_clock(const struct drm_display_mode *mode, + unsigned int bpc, + enum hdmi_colorspace fmt) +{ + unsigned long long clock = mode->clock * 1000ULL; + + if (mode->flags & DRM_MODE_FLAG_DBLCLK) + clock = clock * 2; + + if (fmt == HDMI_COLORSPACE_YUV422) + bpc = 8; + + clock = clock * bpc; + do_div(clock, 8); + + return clock; +} +EXPORT_SYMBOL(drm_hdmi_connector_compute_mode_clock); + +static int +drm_hdmi_connector_compute_clock(const struct drm_hdmi_connector *hdmi_connector, + struct drm_hdmi_connector_state *hdmi_state, + const struct drm_display_mode *mode, + unsigned int bpc, + enum hdmi_colorspace fmt) +{ + unsigned long long clock; + + clock = drm_hdmi_connector_compute_mode_clock(mode, bpc, fmt); + if (!drm_hdmi_connector_clock_valid(hdmi_connector, mode, clock) != MODE_OK) + return -EINVAL; + + hdmi_state->tmds_char_rate = clock; + + return 0; +} + /** * drm_atomic_helper_hdmi_connector_atomic_check() - Helper to check HDMI connector atomic state * @connector: the parent connector this state refers to @@ -275,6 +339,8 @@ connector_state_get_adjusted_mode(const struct drm_connector_state *state) int drm_atomic_helper_hdmi_connector_atomic_check(struct drm_connector *connector, struct drm_atomic_state *state) { + struct drm_hdmi_connector *hdmi_connector = + connector_to_hdmi_connector(connector); struct drm_connector_state *old_state = drm_atomic_get_old_connector_state(state, connector); struct drm_hdmi_connector_state *old_hdmi_state = @@ -283,6 +349,16 @@ int drm_atomic_helper_hdmi_connector_atomic_check(struct drm_connector *connecto drm_atomic_get_new_connector_state(state, connector); struct drm_hdmi_connector_state *new_hdmi_state = connector_state_to_hdmi_connector_state(new_state); + const struct drm_display_mode *mode = + connector_state_get_adjusted_mode(new_state); + int ret; + + ret = drm_hdmi_connector_compute_clock(hdmi_connector, new_hdmi_state, + mode, + new_hdmi_state->output_bpc, + new_hdmi_state->output_format); + if (!ret) + return ret; if (old_hdmi_state->broadcast_rgb != new_hdmi_state->broadcast_rgb || old_hdmi_state->output_format != new_hdmi_state->output_format || @@ -374,6 +450,7 @@ void drm_atomic_helper_hdmi_connector_print_state(struct drm_printer *p, drm_printf(p, "\toutput_bpc=%u\n", hdmi_state->output_bpc); drm_printf(p, "\toutput_format=%s\n", drm_hdmi_connector_get_output_format_name(hdmi_state->output_format)); + drm_printf(p, "\ttmds_char_rate=%llu\n", hdmi_state->tmds_char_rate); } EXPORT_SYMBOL(drm_atomic_helper_hdmi_connector_print_state); diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h index 995700110a16..03c5af34323d 100644 --- a/include/drm/drm_connector.h +++ b/include/drm/drm_connector.h @@ -38,6 +38,7 @@ struct drm_connector_helper_funcs; struct drm_modeset_acquire_ctx; struct drm_device; struct drm_crtc; +struct drm_display_mode; struct drm_encoder; struct drm_panel; struct drm_property; @@ -2085,6 +2086,11 @@ struct drm_hdmi_connector_state { */ enum hdmi_colorspace output_format; + /** + * @tmds_char_rate: TMDS Character Rate, in Hz. + */ + unsigned long long tmds_char_rate; + /** * @broadcast_rgb: Connector property to pass the Broadcast RGB * selection value. @@ -2146,6 +2152,11 @@ struct drm_hdmi_connector { #define connector_to_hdmi_connector(connector) \ container_of_const(connector, struct drm_hdmi_connector, base) +unsigned long long +drm_hdmi_connector_compute_mode_clock(const struct drm_display_mode *mode, + unsigned int bpc, + enum hdmi_colorspace fmt); + int drmm_hdmi_connector_init(struct drm_device *dev, struct drm_hdmi_connector *hdmi_connector, const struct drm_connector_funcs *funcs, From patchwork Mon Aug 14 13:56:20 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Maxime Ripard X-Patchwork-Id: 135463 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:b824:0:b0:3f2:4152:657d with SMTP id z4csp2773846vqi; Mon, 14 Aug 2023 07:14:55 -0700 (PDT) X-Google-Smtp-Source: AGHT+IEVedpkdY7eg4OkIU63y/bUkez9Ub/Bo2XeIZ0FZDzcMbaMta1LueGOtrtucScoQYZ7O0hT X-Received: by 2002:a17:902:a407:b0:1bd:aeb0:f031 with SMTP id p7-20020a170902a40700b001bdaeb0f031mr8222637plq.42.1692022495504; Mon, 14 Aug 2023 07:14:55 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1692022495; cv=none; d=google.com; s=arc-20160816; b=B2IAddtPGn8W9+6A5IvWCRR+itEtEKtfpQQasaGO5mi01aZ/V1CP3Cg9ob0eOvsOip YouRRwLF8YR8u/3Ca/9evXayWKTrvXohvipblJfG0NXQSZbn6xqSung/AW8a3ykDqKsD 2z0lPDrcd/i3giK6VCAhF+S+IMxH5WIcaNW8I0Uj695tkw6z6S40ZaPqox+b+mXUN0TX YMsCz/X5NmiPFZXJjAdaCLxWKKMM05aAbgTCEDsHilzZR/S41UsNGgj7OmG0Z2j/yGKw Xy+zyfBeFuPrBx1hXd1hNoJFu+AkIt99nVl1y7D+5r8IlViKcf797mcZCX+2GaycrgDB uxtw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:cc:to:in-reply-to:references:message-id :content-transfer-encoding:mime-version:subject:date:from :dkim-signature; bh=NbQZDba3p7juKXoLS2GecWA6OZFC83nq3LgoHH0IIhU=; fh=XsS7fCnS6jyV48OHq4AWazZQaFUKJmjcq7fZaQkmGOY=; b=k0SJdSMsK95v+gZJZl9WDDxPw5X70rXhTqXc/+f11UBg22gYb3Q2jEde6AVfwhATgn OyHnRk8zk3W5bIDmbarBxAXqU/WLvBekyCVYvbzI7t8tPPVJ7+Sjo0IoULjE/HU0wXeV srswVG47rzNjs4gphd5OpATiqWafWNLoeOb/ohzdC2CHvaMRXvUte20A/rJEmjBKXFpp X/H/qZyW9aAYsGmMh0iEdSsZeopnvVwxU1s8PnmeDK0ZzYPWsdhRKeO8nVNvTSYVU0Dj OKEklB6A+klEXOmFlmDhInugYz79qGFkydpFgzHP/Q69aojUCMKt5xppQDYY50uPkWn8 jntA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=jbdTAUfN; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id u12-20020a170902e80c00b001bb935754f0si8300624plg.444.2023.08.14.07.14.41; Mon, 14 Aug 2023 07:14:55 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=jbdTAUfN; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231682AbjHNN5V (ORCPT + 99 others); Mon, 14 Aug 2023 09:57:21 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:56188 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231540AbjHNN4u (ORCPT ); Mon, 14 Aug 2023 09:56:50 -0400 Received: from dfw.source.kernel.org (dfw.source.kernel.org [IPv6:2604:1380:4641:c500::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A8D73E6D for ; Mon, 14 Aug 2023 06:56:49 -0700 (PDT) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id 2F08460ECA for ; Mon, 14 Aug 2023 13:56:49 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 4047FC433C9; Mon, 14 Aug 2023 13:56:48 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1692021408; bh=g++ofW1dWzrJFCe/PqAHGgE6yXVKaJFsc5QCbk7jsYE=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=jbdTAUfNdH0v7148wd7Q+sEg+/Y5cgdrTeFOcx6EcKK7GPttIkCW9Q3UqXsbgdRtq KFcNuhCBqaFWf2Ou7flX/RHfYkNgoPvXyxYTxNKuCPJaEKpzqYcVRkcnulwR0GqqpI RN7nEvR313fPfYvpFuiq8Re/pb5CieYSUSgaWtXeeWBkDB/C5YF6FnyXON3tpBfifg lVm7B8e895RRdjIr5XeaizcF48eJsaS457iBNDR5lz6CfT27lWpTN2T9jevD6VoDmj mkw8Jjj2jPJbdegMPA/C0+DXUlb8sJizzYrjM5dHRyfEhWxuR1j6EtEZStaRY5V458 /2x/oLYRQBjPQ== From: Maxime Ripard Date: Mon, 14 Aug 2023 15:56:20 +0200 Subject: [PATCH RFC 08/13] drm/connector: hdmi: Add custom hook to filter TMDS character rate MIME-Version: 1.0 Message-Id: <20230814-kms-hdmi-connector-state-v1-8-048054df3654@kernel.org> References: <20230814-kms-hdmi-connector-state-v1-0-048054df3654@kernel.org> In-Reply-To: <20230814-kms-hdmi-connector-state-v1-0-048054df3654@kernel.org> To: Maarten Lankhorst , Thomas Zimmermann , David Airlie , Daniel Vetter , Emma Anholt Cc: Hans Verkuil , linux-kernel@vger.kernel.org, dri-devel@lists.freedesktop.org, Maxime Ripard X-Mailer: b4 0.12.3 X-Developer-Signature: v=1; a=openpgp-sha256; l=4570; i=mripard@kernel.org; h=from:subject:message-id; bh=g++ofW1dWzrJFCe/PqAHGgE6yXVKaJFsc5QCbk7jsYE=; b=owGbwMvMwCX2+D1vfrpE4FHG02pJDCm3jNomvVjKu6qR09b37rmdDxt1Lnp4zz/6uuih5fGTF 57sTPxxqKOUhUGMi0FWTJElRth8SdypWa872fjmwcxhZQIZwsDFKQATcfRj+M2yUmnNFvd7U+Im TeMwmhF7MP3AOpEZh7U2XLTZ1irzizOE4X/00ezuxOAI/Z3umuvXfr+3egl/qE/YCSaGas/oebl CxewA X-Developer-Key: i=mripard@kernel.org; a=openpgp; fpr=BE5675C37E818C8B5764241C254BCFC56BF6CE8D X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF, RCVD_IN_DNSWL_BLOCKED,SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1774214180402929707 X-GMAIL-MSGID: 1774214180402929707 Most of the HDMI controllers have an upper TMDS character rate limit they can't exceed. On "embedded"-grade display controllers, it will typically be lower than what high-grade monitors can provide these days, so drivers will filter the TMDS character rate based on the controller capabilities. To make that easier to handle for drivers, let's provide an optional hook to be implemented by drivers so they can tell the HDMI controller helpers if a given TMDS character rate is reachable for them or not. This will then be useful to figure out the best format and bpc count for a given mode. Signed-off-by: Maxime Ripard --- drivers/gpu/drm/drm_hdmi_connector.c | 8 ++++++++ include/drm/drm_connector.h | 30 ++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/drivers/gpu/drm/drm_hdmi_connector.c b/drivers/gpu/drm/drm_hdmi_connector.c index e49782a284a5..d94ceeb6a8ef 100644 --- a/drivers/gpu/drm/drm_hdmi_connector.c +++ b/drivers/gpu/drm/drm_hdmi_connector.c @@ -263,12 +263,16 @@ drm_hdmi_connector_clock_valid(const struct drm_hdmi_connector *hdmi_connector, const struct drm_display_mode *mode, unsigned long long clock) { + const struct drm_hdmi_connector_funcs *funcs = hdmi_connector->funcs; const struct drm_connector *connector = &hdmi_connector->base; const struct drm_display_info *info = &connector->display_info; if (info->max_tmds_clock && clock > info->max_tmds_clock * 1000) return MODE_CLOCK_HIGH; + if (funcs && funcs->tmds_char_rate_valid) + return funcs->tmds_char_rate_valid(hdmi_connector, mode, clock); + return MODE_OK; } @@ -458,6 +462,7 @@ EXPORT_SYMBOL(drm_atomic_helper_hdmi_connector_print_state); * drmm_hdmi_connector_init - Init a preallocated HDMI connector * @dev: DRM device * @hdmi_connector: A pointer to the HDMI connector to init + * @funcs: callbacks for this connector * @connector_type: user visible type of the connector * @ddc: optional pointer to the associated ddc adapter * @max_bpc: Maximum bits per char the HDMI connector supports @@ -476,6 +481,7 @@ EXPORT_SYMBOL(drm_atomic_helper_hdmi_connector_print_state); int drmm_hdmi_connector_init(struct drm_device *dev, struct drm_hdmi_connector *hdmi_connector, const struct drm_connector_funcs *funcs, + const struct drm_hdmi_connector_funcs *hdmi_funcs, int connector_type, struct i2c_adapter *ddc, unsigned int max_bpc) @@ -516,6 +522,8 @@ int drmm_hdmi_connector_init(struct drm_device *dev, hdmi_connector->max_bpc = max_bpc; } + hdmi_connector->funcs = hdmi_funcs; + return 0; } EXPORT_SYMBOL(drmm_hdmi_connector_init); diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h index 03c5af34323d..6e25a16420e4 100644 --- a/include/drm/drm_connector.h +++ b/include/drm/drm_connector.h @@ -2131,12 +2131,41 @@ bool drm_atomic_helper_hdmi_connector_is_full_range(const struct drm_hdmi_connector *hdmi_connector, const struct drm_hdmi_connector_state *hdmi_state); +/** + * struct drm_hdmi_connector_funcs - drm_hdmi_connector control functions + */ +struct drm_hdmi_connector_funcs { + /** + * @tmds_char_rate_valid: + * + * This callback is invoked at atomic_check time to figure out + * whether a particular TMDS character rate is supported by the + * driver. + * + * The @tmds_char_rate_valid callback is optional. + * + * Returns: + * + * Either &drm_mode_status.MODE_OK or one of the failure reasons + * in &enum drm_mode_status. + */ + enum drm_mode_status + (*tmds_char_rate_valid)(const struct drm_hdmi_connector *connector, + const struct drm_display_mode *mode, + unsigned long long tmds_rate); +}; + struct drm_hdmi_connector { /** * @base: Base Connector */ struct drm_connector base; + /** + * @funcs: HDMI connector Control Functions + */ + const struct drm_hdmi_connector_funcs *funcs; + /** * @max_bpc: Maximum bits per character the connector supports. */ @@ -2160,6 +2189,7 @@ drm_hdmi_connector_compute_mode_clock(const struct drm_display_mode *mode, int drmm_hdmi_connector_init(struct drm_device *dev, struct drm_hdmi_connector *hdmi_connector, const struct drm_connector_funcs *funcs, + const struct drm_hdmi_connector_funcs *hdmi_funcs, int connector_type, struct i2c_adapter *ddc, unsigned int max_bpc); From patchwork Mon Aug 14 13:56:21 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Maxime Ripard X-Patchwork-Id: 135464 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:b824:0:b0:3f2:4152:657d with SMTP id z4csp2774601vqi; Mon, 14 Aug 2023 07:16:03 -0700 (PDT) X-Google-Smtp-Source: AGHT+IH27WF+1jFiD92iU/co3j03ojNLzjX8h6VI6O/0YbBxseaWyRLKOaClfOpXSpLCg3Q9fxpA X-Received: by 2002:a05:6a21:1f30:b0:137:9622:17d0 with SMTP id ry48-20020a056a211f3000b00137962217d0mr7873960pzb.58.1692022563225; Mon, 14 Aug 2023 07:16:03 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1692022563; cv=none; d=google.com; s=arc-20160816; b=nEW9Emo502/8g6iwpdabrctqzIxsPBmEWXVb/fvIFQWn4o9KmxsD0liT3NgWKz5vzk 86PQe8cJH85Ts5bmdPzVeoFRm4e/m76GigSgAgK+Q1cvCPXMLKIiI+jeJYA+NjqsWyhv 3PsgLTUYb8YMmHyJTy4evHOtNvuv9l4wOwQl9KQivzwXolWPTnAXguLsZx2irsIqaqy3 YyqqVh5rfHrQJv1JOQmz+BfKWX3R/JP4iTLvGVIor5BsqSkB9NzDOcOtennWuKyvp9Wi yj7uViaNISoN/YbXyrFsaqLw/DkJHkKB1p6ndGTZrbq7Ugf3I06apidx1/AEmqQuhCGE iFqA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:cc:to:in-reply-to:references:message-id :content-transfer-encoding:mime-version:subject:date:from :dkim-signature; bh=dBegZVTBQumT3pbeTF2tTv25/2xmuIyMFF2r/Ob2j7M=; fh=XsS7fCnS6jyV48OHq4AWazZQaFUKJmjcq7fZaQkmGOY=; b=pUPWRp+xGql85VkY77A/7aMgNDqtfW8+rfPZJDyPkS/RHBR0RdzOkt1PG+DnuPiOL+ cKaDFgxBoy7cqzcOWGl+pc7NI+OJmytoEvnZCJBKM7oN/RrTu4Y6UMpYchWp5gq+H2rq Tx1ri/C52egJ9ZTTE0+evH6pM+JSD5kc12HphCzCggsvhXSyTxiyyJBa/IicfBF4mt1l k4StA5XJdz/TNy+M6ETrz3bOoAtHpvvk4kxpVC2E9U5YvWPHgNiZOxHPt08DiuwlQgk5 xBOHaxW1b9xge+TQGNYJOH9BVSf7VCxKAI+f8qTNqMK+CnGBPxPDvZgnxrs2/qNz0g2y rHBw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=UrLEtfa3; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id v135-20020a63618d000000b005641fc2684bsi8242334pgb.527.2023.08.14.07.15.49; Mon, 14 Aug 2023 07:16:03 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=UrLEtfa3; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231775AbjHNN50 (ORCPT + 99 others); Mon, 14 Aug 2023 09:57:26 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:56204 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231691AbjHNN4z (ORCPT ); Mon, 14 Aug 2023 09:56:55 -0400 Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 825F710D5 for ; Mon, 14 Aug 2023 06:56:52 -0700 (PDT) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id 11CA961796 for ; Mon, 14 Aug 2023 13:56:52 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 24ECCC433C7; Mon, 14 Aug 2023 13:56:50 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1692021411; bh=5FwIWakECN1Fb8VdEDsYOpvXNTYQGx7JKvYanIQ8ciM=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=UrLEtfa3ndkkl9o39vjy3XqAnLqKAgiL0Z0S+hr1T0xLP5/2txg0cu+Fuy7UkyNt6 71qiEYLzFXGj6B8QgXaX6k4c9SFODQSQ5mqHacMqqu2xPhIk6UYZbhMXynCeFqCRR5 kK92mVoDjyZjtlvzhY+mVy0h2biK3c+UCLUcurB5NUQ0dmbi7ADejDfMXfTwoSwq/K URRRi6BPFRGcqHL9FcNOijWl1A0BkhZbcghXfQHPZL2fKpwxX5w+1JOrsanDqlWZth 0A9ldENcKAkG3O44gGgqtAOnOvAtwTybFELOUVWoZwVYFc4X8nhHafBth9O3zEEmmM NW/5cAVz6ZFOg== From: Maxime Ripard Date: Mon, 14 Aug 2023 15:56:21 +0200 Subject: [PATCH RFC 09/13] drm/connector: hdmi: Compute bpc and format automatically MIME-Version: 1.0 Message-Id: <20230814-kms-hdmi-connector-state-v1-9-048054df3654@kernel.org> References: <20230814-kms-hdmi-connector-state-v1-0-048054df3654@kernel.org> In-Reply-To: <20230814-kms-hdmi-connector-state-v1-0-048054df3654@kernel.org> To: Maarten Lankhorst , Thomas Zimmermann , David Airlie , Daniel Vetter , Emma Anholt Cc: Hans Verkuil , linux-kernel@vger.kernel.org, dri-devel@lists.freedesktop.org, Maxime Ripard X-Mailer: b4 0.12.3 X-Developer-Signature: v=1; a=openpgp-sha256; l=7067; i=mripard@kernel.org; h=from:subject:message-id; bh=5FwIWakECN1Fb8VdEDsYOpvXNTYQGx7JKvYanIQ8ciM=; b=owGbwMvMwCX2+D1vfrpE4FHG02pJDCm3jNrerOP5daLYesOKX95d3t8lX57fc3rxlsLye/n6O ZoCfE/XdZSyMIhxMciKKbLECJsviTs163UnG988mDmsTCBDGLg4BWAiF5IY/qkkaFXs27dnUs6V lW4b0yd6rFKZo/9CdHf8xinH247cnbaLkWHqpjc5Be+in68xcX+2LEZw3WfDio2nUzLOq+Q8coi 7a8sFAA== X-Developer-Key: i=mripard@kernel.org; a=openpgp; fpr=BE5675C37E818C8B5764241C254BCFC56BF6CE8D X-Spam-Status: No, score=-7.1 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_HI, SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1774214251048244962 X-GMAIL-MSGID: 1774214251048244962 Now that we have all the infrastructure needed, we can add some code that will, for a given connector state and mode, compute the best output format and bpc. The algorithm is the same one than the one already found in i915 and vc4. Signed-off-by: Maxime Ripard --- drivers/gpu/drm/drm_hdmi_connector.c | 182 ++++++++++++++++++++++++++++++++++- 1 file changed, 177 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/drm_hdmi_connector.c b/drivers/gpu/drm/drm_hdmi_connector.c index d94ceeb6a8ef..22c49906dfb5 100644 --- a/drivers/gpu/drm/drm_hdmi_connector.c +++ b/drivers/gpu/drm/drm_hdmi_connector.c @@ -258,6 +258,91 @@ connector_state_get_adjusted_mode(const struct drm_connector_state *state) return &crtc_state->adjusted_mode; } +static bool +sink_supports_format_bpc(const struct drm_hdmi_connector *hdmi_connector, + const struct drm_display_info *info, + const struct drm_display_mode *mode, + unsigned int format, unsigned int bpc) +{ + const struct drm_connector *connector = &hdmi_connector->base; + struct drm_device *dev = connector->dev; + u8 vic = drm_match_cea_mode(mode); + + if (vic == 1 && bpc != 8) { + drm_dbg(dev, "VIC1 requires a bpc of 8, got %u\n", bpc); + return false; + } + + if (!info->is_hdmi && + (format != HDMI_COLORSPACE_RGB || bpc != 8)) { + drm_dbg(dev, "DVI Monitors require an RGB output at 8 bpc\n"); + return false; + } + + switch (format) { + case HDMI_COLORSPACE_RGB: + drm_dbg(dev, "RGB Format, checking the constraints.\n"); + + if (!(info->color_formats & DRM_COLOR_FORMAT_RGB444)) + return false; + + if (bpc == 10 && !(info->edid_hdmi_rgb444_dc_modes & DRM_EDID_HDMI_DC_30)) { + drm_dbg(dev, "10 BPC but sink doesn't support Deep Color 30.\n"); + return false; + } + + if (bpc == 12 && !(info->edid_hdmi_rgb444_dc_modes & DRM_EDID_HDMI_DC_36)) { + drm_dbg(dev, "12 BPC but sink doesn't support Deep Color 36.\n"); + return false; + } + + drm_dbg(dev, "RGB format supported in that configuration.\n"); + + return true; + + case HDMI_COLORSPACE_YUV422: + drm_dbg(dev, "YUV422 format, checking the constraints.\n"); + + if (!(info->color_formats & DRM_COLOR_FORMAT_YCBCR422)) { + drm_dbg(dev, "Sink doesn't support YUV422.\n"); + return false; + } + + if (bpc != 12) { + drm_dbg(dev, "YUV422 only supports 12 bpc.\n"); + return false; + } + + drm_dbg(dev, "YUV422 format supported in that configuration.\n"); + + return true; + + case HDMI_COLORSPACE_YUV444: + drm_dbg(dev, "YUV444 format, checking the constraints.\n"); + + if (!(info->color_formats & DRM_COLOR_FORMAT_YCBCR444)) { + drm_dbg(dev, "Sink doesn't support YUV444.\n"); + return false; + } + + if (bpc == 10 && !(info->edid_hdmi_ycbcr444_dc_modes & DRM_EDID_HDMI_DC_30)) { + drm_dbg(dev, "10 BPC but sink doesn't support Deep Color 30.\n"); + return false; + } + + if (bpc == 12 && !(info->edid_hdmi_ycbcr444_dc_modes & DRM_EDID_HDMI_DC_36)) { + drm_dbg(dev, "12 BPC but sink doesn't support Deep Color 36.\n"); + return false; + } + + drm_dbg(dev, "YUV444 format supported in that configuration.\n"); + + return true; + } + + return false; +} + static enum drm_mode_status drm_hdmi_connector_clock_valid(const struct drm_hdmi_connector *hdmi_connector, const struct drm_display_mode *mode, @@ -325,6 +410,95 @@ drm_hdmi_connector_compute_clock(const struct drm_hdmi_connector *hdmi_connector return 0; } +static bool +drm_hdmi_connector_try_format_bpc(const struct drm_hdmi_connector *hdmi_connector, + struct drm_hdmi_connector_state *hdmi_state, + const struct drm_display_mode *mode, + unsigned int bpc, enum hdmi_colorspace fmt) +{ + const struct drm_connector *connector = &hdmi_connector->base; + const struct drm_display_info *info = &connector->display_info; + struct drm_device *dev = connector->dev; + int ret; + + drm_dbg(dev, "Trying output format %s\n", + drm_hdmi_connector_get_output_format_name(fmt)); + + if (!sink_supports_format_bpc(hdmi_connector, info, mode, fmt, bpc)) + return false; + + ret = drm_hdmi_connector_compute_clock(hdmi_connector, hdmi_state, + mode, bpc, fmt); + if (ret) + return false; + + return true; +} + +static int +drm_hdmi_connector_compute_format(const struct drm_hdmi_connector *hdmi_connector, + struct drm_hdmi_connector_state *hdmi_state, + const struct drm_display_mode *mode, + unsigned int bpc) +{ + const struct drm_connector *connector = &hdmi_connector->base; + struct drm_device *dev = connector->dev; + + if (drm_hdmi_connector_try_format_bpc(hdmi_connector, hdmi_state, + mode, bpc, HDMI_COLORSPACE_RGB)) { + hdmi_state->output_format = HDMI_COLORSPACE_RGB; + return 0; + } + + if (drm_hdmi_connector_try_format_bpc(hdmi_connector, hdmi_state, + mode, bpc, HDMI_COLORSPACE_YUV422)) { + hdmi_state->output_format = HDMI_COLORSPACE_YUV422; + return 0; + } + + drm_dbg(dev, "Failed. No Format Supported for that bpc count.\n"); + + return -EINVAL; +} + +static int +drm_hdmi_connector_compute_config(const struct drm_hdmi_connector *hdmi_connector, + struct drm_hdmi_connector_state *hdmi_state, + const struct drm_display_mode *mode) +{ + const struct drm_connector *connector = &hdmi_connector->base; + struct drm_connector_state *conn_state = &hdmi_state->base; + struct drm_device *dev = connector->dev; + unsigned int max_bpc = clamp_t(unsigned int, + conn_state->max_bpc, + 8, hdmi_connector->max_bpc); + unsigned int bpc; + int ret; + + for (bpc = max_bpc; bpc >= 8; bpc -= 2) { + drm_dbg(dev, "Trying with a %d bpc output\n", bpc); + + ret = drm_hdmi_connector_compute_format(hdmi_connector, + hdmi_state, + mode, bpc); + if (ret) + continue; + + hdmi_state->output_bpc = bpc; + + drm_dbg(dev, + "Mode %ux%u @ %uHz: Found configuration: bpc: %u, fmt: %s, clock: %llu\n", + mode->hdisplay, mode->vdisplay, drm_mode_vrefresh(mode), + hdmi_state->output_bpc, + drm_hdmi_connector_get_output_format_name(hdmi_state->output_format), + hdmi_state->tmds_char_rate); + + return 0; + } + + return -EINVAL; +} + /** * drm_atomic_helper_hdmi_connector_atomic_check() - Helper to check HDMI connector atomic state * @connector: the parent connector this state refers to @@ -357,11 +531,9 @@ int drm_atomic_helper_hdmi_connector_atomic_check(struct drm_connector *connecto connector_state_get_adjusted_mode(new_state); int ret; - ret = drm_hdmi_connector_compute_clock(hdmi_connector, new_hdmi_state, - mode, - new_hdmi_state->output_bpc, - new_hdmi_state->output_format); - if (!ret) + ret = drm_hdmi_connector_compute_config(hdmi_connector, new_hdmi_state, + mode); + if (ret) return ret; if (old_hdmi_state->broadcast_rgb != new_hdmi_state->broadcast_rgb || From patchwork Mon Aug 14 13:56:22 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Maxime Ripard X-Patchwork-Id: 135468 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:b824:0:b0:3f2:4152:657d with SMTP id z4csp2783546vqi; Mon, 14 Aug 2023 07:31:19 -0700 (PDT) X-Google-Smtp-Source: AGHT+IHEQrOxHkXFgDgymL+pspDHChIQmuzZ6tWhYVDd8CWH9HsmZv6qxa7GF6ScajHgdjfdSqNB X-Received: by 2002:a17:90a:280d:b0:268:798:a28b with SMTP id e13-20020a17090a280d00b002680798a28bmr16338391pjd.23.1692023479009; Mon, 14 Aug 2023 07:31:19 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1692023478; cv=none; d=google.com; s=arc-20160816; b=LXDjWRKZGX/0InEpu1DTVzWtdXBKWFrcoE33x5LviWz6dNnZn7Gj0j6m0LFcYGcmeM 6Yk2YTVdCpo6G/DkPxpM8feZpqm/C3Nc7WEoio1obFaxYB7Ej+n1Vnhi3fj9ORFeRd4X GRg6Wq8dbkeEWvReWxb56r779vIKSOz+9yxv6704j4Vp4EtR1Zn3sSb7bNgqK3MFZawH C0T8gPj4iVTXRQQ6z5Km0aXcpzAb4dPG4IlKyxqp6aP6iD7Q2W06K/nvHUaIRgn8lZd/ /i8NFiDkKsz9BzuZoNp6vTCBLKvo79BrE7T+dO4GRTBfb8sf3G/qPAkJJM5qi5wXppKo 9zNg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:cc:to:in-reply-to:references:message-id :content-transfer-encoding:mime-version:subject:date:from :dkim-signature; bh=t2neVuZrAPLssZEuJu0/Jj3DHJfVRn4lEju1AJnvOHM=; fh=XsS7fCnS6jyV48OHq4AWazZQaFUKJmjcq7fZaQkmGOY=; b=E0XiTBF3BJ0MHjHb/to2WDeyP4Q8xaFGIjlDHEHOkkjPz7CCOInZ4x/Huoeyp/7esd HdME9NJ89c5OvY/KW4nBS6OMwo+VDwjHgW88+8JQ5s3vPBnlkNPuKRW69NMbPisidSJE 0Lz02VrnbaLy7WpS8Crs2IuweE7O1gXMQgZkzrAOoNcY+TmvPsnxN3AZQDWlmlf8TfVq p5TKktaq7R1V9C7jx2mxRAhdfvVNGpIqH+L9gZj588Sv5Vxtwm/FIvBZSAiqksR2U0W5 HwuohxXTdnPcvdlSFxpoFC9vZj+NAdhFDLJOZ/N8n0ItCSjPIFgvBGlgbn2/TGGUCqKL CPhQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=tid9fnCU; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id k93-20020a17090a3ee600b0026b421129a3si3736866pjc.77.2023.08.14.07.31.05; Mon, 14 Aug 2023 07:31:18 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=tid9fnCU; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231786AbjHNN53 (ORCPT + 99 others); Mon, 14 Aug 2023 09:57:29 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:56248 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231650AbjHNN44 (ORCPT ); Mon, 14 Aug 2023 09:56:56 -0400 Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 43E2DE7D for ; Mon, 14 Aug 2023 06:56:55 -0700 (PDT) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id C931D60EB3 for ; Mon, 14 Aug 2023 13:56:54 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id DC478C433C9; Mon, 14 Aug 2023 13:56:53 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1692021414; bh=TwReaH998r0w+lDww/DOcrQ1JLUr2wYXkauLvm1hQok=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=tid9fnCU8+hamXnyiGxiIfRxjjDiaQF9gvadMkXm3RjXALVLFVUkaPJhUZhwyjJEg rTbhgriHjLnDk8BZYvNHMPMafBrjHFrVhi15PZl3e5qwUukyeWdNn0pmV429xe/CW5 +RYJkVqGK5Rzsqt6nqDkMQZN9c2Q8oKRxk8CfcAQY+NmOPr0VajUmSkUsPy/cxsV9K 8vOjlCfHN592FPEfFw9Wk9KN7nLFQXYItTIY6KOON7+qn+aBs9IU/k5+1Q9iLHKzlJ tVhsHCgzeYmuryuAjHS1f/gPszq1JbdNg/HsSHzpXkugMskwGMT8CVoF7fS+57iG+p 4i+OD8nOwpRLg== From: Maxime Ripard Date: Mon, 14 Aug 2023 15:56:22 +0200 Subject: [PATCH RFC 10/13] drm/connector: hdmi: Add Infoframes generation MIME-Version: 1.0 Message-Id: <20230814-kms-hdmi-connector-state-v1-10-048054df3654@kernel.org> References: <20230814-kms-hdmi-connector-state-v1-0-048054df3654@kernel.org> In-Reply-To: <20230814-kms-hdmi-connector-state-v1-0-048054df3654@kernel.org> To: Maarten Lankhorst , Thomas Zimmermann , David Airlie , Daniel Vetter , Emma Anholt Cc: Hans Verkuil , linux-kernel@vger.kernel.org, dri-devel@lists.freedesktop.org, Maxime Ripard X-Mailer: b4 0.12.3 X-Developer-Signature: v=1; a=openpgp-sha256; l=15699; i=mripard@kernel.org; h=from:subject:message-id; bh=TwReaH998r0w+lDww/DOcrQ1JLUr2wYXkauLvm1hQok=; b=owGbwMvMwCX2+D1vfrpE4FHG02pJDCm3jNoE/sptM+I1vsh1SMZbx93XKKRW94bsHceN3yf0O C1c3/a2o5SFQYyLQVZMkSVG2HxJ3KlZrzvZ+ObBzGFlAhnCwMUpABMpFWL4H+u8oevva7PfJ/zj T32XPvRmbdqVkx1z3lt+NM584+wrqMfwP9BqTcDTA/oCwV+fXLDklG/cr/Qp6nBYlPyCcwYHzxo 4cQEA X-Developer-Key: i=mripard@kernel.org; a=openpgp; fpr=BE5675C37E818C8B5764241C254BCFC56BF6CE8D X-Spam-Status: No, score=-7.1 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_HI, SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1774215211301804018 X-GMAIL-MSGID: 1774215211301804018 Infoframes in KMS is usually handled by a bunch of low-level helpers that require quite some boilerplate for drivers. This leads to discrepancies with how drivers generate them, and which are actually sent. Now that we have everything needed to generate them in the HDMI connector state, we can generate them in our common logic so that drivers can simply reuse what we precomputed. Signed-off-by: Maxime Ripard --- drivers/gpu/drm/drm_hdmi_connector.c | 287 +++++++++++++++++++++++++++++++++++ include/drm/drm_connector.h | 100 ++++++++++++ 2 files changed, 387 insertions(+) diff --git a/drivers/gpu/drm/drm_hdmi_connector.c b/drivers/gpu/drm/drm_hdmi_connector.c index 22c49906dfb5..46cafb17def7 100644 --- a/drivers/gpu/drm/drm_hdmi_connector.c +++ b/drivers/gpu/drm/drm_hdmi_connector.c @@ -5,8 +5,10 @@ #include #include #include +#include #include #include +#include #include @@ -499,6 +501,131 @@ drm_hdmi_connector_compute_config(const struct drm_hdmi_connector *hdmi_connecto return -EINVAL; } +static int +drm_hdmi_connector_generate_avi_infoframe(const struct drm_hdmi_connector *hdmi_connector, + struct drm_hdmi_connector_state *hdmi_state) +{ + const struct drm_connector *connector = &hdmi_connector->base; + const struct drm_connector_state *state = &hdmi_state->base; + const struct drm_display_mode *mode = + connector_state_get_adjusted_mode(state); + struct hdmi_avi_infoframe *frame = &hdmi_state->infoframes.avi; + bool is_lim_range = + drm_atomic_helper_hdmi_connector_is_full_range(hdmi_connector, + hdmi_state); + enum hdmi_quantization_range rgb_quant_range = + is_lim_range ? HDMI_QUANTIZATION_RANGE_FULL : HDMI_QUANTIZATION_RANGE_LIMITED; + int ret; + + ret = drm_hdmi_avi_infoframe_from_display_mode(frame, connector, mode); + if (ret) + return ret; + + frame->colorspace = hdmi_state->output_format; + + drm_hdmi_avi_infoframe_quant_range(frame, connector, mode, rgb_quant_range); + drm_hdmi_avi_infoframe_colorimetry(frame, state); + drm_hdmi_avi_infoframe_bars(frame, state); + + return 0; +} + +static int +drm_hdmi_connector_generate_spd_infoframe(const struct drm_hdmi_connector *hdmi_connector, + struct drm_hdmi_connector_state *hdmi_state) +{ + struct hdmi_spd_infoframe *frame = &hdmi_state->infoframes.spd; + int ret; + + ret = hdmi_spd_infoframe_init(frame, + hdmi_connector->vendor, + hdmi_connector->product); + if (ret) + return ret; + + frame->sdi = HDMI_SPD_SDI_PC; + + return 0; +} + +static int +drm_hdmi_connector_generate_hdr_infoframe(const struct drm_hdmi_connector *hdmi_connector, + struct drm_hdmi_connector_state *hdmi_state) +{ + const struct drm_connector_state *state = &hdmi_state->base; + struct hdmi_drm_infoframe *frame = &hdmi_state->infoframes.drm; + int ret; + + if (hdmi_connector->max_bpc < 10) + return 0; + + if (!state->hdr_output_metadata) + return 0; + + ret = drm_hdmi_infoframe_set_hdr_metadata(frame, state); + if (ret) + return ret; + + return 0; +} + +static int +drm_hdmi_connector_generate_vendor_infoframe(const struct drm_hdmi_connector *hdmi_connector, + struct drm_hdmi_connector_state *hdmi_state) +{ + const struct drm_connector *connector = &hdmi_connector->base; + const struct drm_connector_state *state = &hdmi_state->base; + const struct drm_display_mode *mode = + connector_state_get_adjusted_mode(state); + struct hdmi_vendor_infoframe *frame = &hdmi_state->infoframes.vendor; + int ret; + + ret = drm_hdmi_vendor_infoframe_from_display_mode(frame, connector, mode); + if (ret == -EINVAL) + return 0; + else + return ret; + + return 0; +} + +static int +drm_hdmi_connector_generate_infoframes(const struct drm_hdmi_connector *hdmi_connector, + struct drm_hdmi_connector_state *hdmi_state) +{ + const struct drm_connector *connector = &hdmi_connector->base; + const struct drm_display_info *info = &connector->display_info; + int ret; + + if (!info->is_hdmi) + return 0; + + if (!info->has_hdmi_infoframe) + return 0; + + ret = drm_hdmi_connector_generate_avi_infoframe(hdmi_connector, hdmi_state); + if (ret) + return ret; + + ret = drm_hdmi_connector_generate_spd_infoframe(hdmi_connector, hdmi_state); + if (ret) + return ret; + + /* + * Audio Infoframes will be generated by ALSA. + */ + + ret = drm_hdmi_connector_generate_hdr_infoframe(hdmi_connector, hdmi_state); + if (ret) + return ret; + + ret = drm_hdmi_connector_generate_vendor_infoframe(hdmi_connector, hdmi_state); + if (ret) + return ret; + + return 0; +} + /** * drm_atomic_helper_hdmi_connector_atomic_check() - Helper to check HDMI connector atomic state * @connector: the parent connector this state refers to @@ -536,6 +663,10 @@ int drm_atomic_helper_hdmi_connector_atomic_check(struct drm_connector *connecto if (ret) return ret; + ret = drm_hdmi_connector_generate_infoframes(hdmi_connector, new_hdmi_state); + if (ret) + return ret; + if (old_hdmi_state->broadcast_rgb != new_hdmi_state->broadcast_rgb || old_hdmi_state->output_format != new_hdmi_state->output_format || old_hdmi_state->output_bpc != new_hdmi_state->output_bpc) { @@ -553,6 +684,152 @@ int drm_atomic_helper_hdmi_connector_atomic_check(struct drm_connector *connecto } EXPORT_SYMBOL(drm_atomic_helper_hdmi_connector_atomic_check); +#define HDMI_MAX_INFOFRAME_SIZE 29 + +static int write_infoframe(struct drm_hdmi_connector *hdmi_connector, + union hdmi_infoframe *frame) +{ + const struct drm_hdmi_connector_funcs *funcs = hdmi_connector->funcs; + u8 buffer[HDMI_MAX_INFOFRAME_SIZE]; + int len; + + if (!funcs || !funcs->write_infoframe) + return -ENOSYS; + + len = hdmi_infoframe_pack(frame, buffer, sizeof(buffer)); + if (len < 0) + return len; + + return funcs->write_infoframe(hdmi_connector, frame->any.type, buffer, len); +} + +static int update_infoframe(struct drm_hdmi_connector *hdmi_connector, + union hdmi_infoframe *frame) +{ + int ret; + + ret = write_infoframe(hdmi_connector, frame); + if (ret) + return ret; + + switch (frame->any.type) { + case HDMI_INFOFRAME_TYPE_AVI: + memcpy(&hdmi_connector->infoframes.avi, &frame->avi, + sizeof(hdmi_connector->infoframes.avi)); + break; + case HDMI_INFOFRAME_TYPE_DRM: + memcpy(&hdmi_connector->infoframes.drm, &frame->drm, + sizeof(hdmi_connector->infoframes.drm)); + break; + case HDMI_INFOFRAME_TYPE_SPD: + memcpy(&hdmi_connector->infoframes.spd, &frame->spd, + sizeof(hdmi_connector->infoframes.spd)); + break; + case HDMI_INFOFRAME_TYPE_VENDOR: + memcpy(&hdmi_connector->infoframes.vendor, &frame->vendor, + sizeof(hdmi_connector->infoframes.vendor)); + break; + default: + return -EINVAL; + } + + return 0; +} + +#define UPDATE_INFOFRAME(c, i) \ + update_infoframe(c, (union hdmi_infoframe *)&(c)->infoframes.i) + +/** + * drm_atomic_helper_hdmi_connector_update_infoframes - Update the Infoframes + * @hdmi_connector: A pointer to the HDMI connector + * @hdmi_state: The HDMI connector state to generate the infoframe from + * + * This function is meant for HDMI connector drivers to write their + * infoframes. It will typically be used in a + * @drm_connector_helper_funcs.atomic_enable implementation. + * + * Returns: + * Zero on success, error code on failure. + */ +int drm_atomic_helper_hdmi_connector_update_infoframes(struct drm_hdmi_connector *hdmi_connector, + struct drm_hdmi_connector_state *hdmi_state) +{ + struct drm_connector *connector = &hdmi_connector->base; + struct drm_display_info *info = &connector->display_info; + int ret; + + if (!info->is_hdmi) + return 0; + + if (!info->has_hdmi_infoframe) + return 0; + + mutex_lock(&hdmi_connector->infoframes.lock); + + ret = UPDATE_INFOFRAME(hdmi_connector, avi); + if (ret) + goto out; + + ret = UPDATE_INFOFRAME(hdmi_connector, audio); + if (ret) + goto out; + + ret = UPDATE_INFOFRAME(hdmi_connector, drm); + if (ret) + goto out; + + ret = UPDATE_INFOFRAME(hdmi_connector, spd); + if (ret) + goto out; + + ret = UPDATE_INFOFRAME(hdmi_connector, vendor); + if (ret) + goto out; + +out: + mutex_unlock(&hdmi_connector->infoframes.lock); + return ret; +} +EXPORT_SYMBOL(drm_atomic_helper_hdmi_connector_update_infoframes); + +#undef UPDATE_INFOFRAME + +/** + * drm_atomic_helper_hdmi_connector_update_audio_infoframe - Update the Audio Infoframe + * @hdmi_connector: A pointer to the HDMI connector + * @frame: A pointer to the audio infoframe to write + * + * This function is meant for HDMI connector drivers to update their + * audio infoframe. It will typically be used in one of the ALSA hooks + * (most likely prepare). + * + * Returns: + * Zero on success, error code on failure. + */ +int +drm_atomic_helper_hdmi_connector_update_audio_infoframe(struct drm_hdmi_connector *hdmi_connector, + struct hdmi_audio_infoframe *frame) +{ + struct drm_connector *connector = &hdmi_connector->base; + struct drm_display_info *info = &connector->display_info; + int ret; + + if (!info->is_hdmi) + return 0; + + if (!info->has_hdmi_infoframe) + return 0; + + mutex_lock(&hdmi_connector->infoframes.lock); + + ret = update_infoframe(hdmi_connector, (union hdmi_infoframe *)frame); + + mutex_unlock(&hdmi_connector->infoframes.lock); + + return ret; +} +EXPORT_SYMBOL(drm_atomic_helper_hdmi_connector_update_audio_infoframe); + /** * drm_atomic_helper_hdmi_connector_is_full_range() - Checks whether a state uses Full-Range RGB * @hdmi_connector: the HDMI connector this state refers to @@ -634,6 +911,8 @@ EXPORT_SYMBOL(drm_atomic_helper_hdmi_connector_print_state); * drmm_hdmi_connector_init - Init a preallocated HDMI connector * @dev: DRM device * @hdmi_connector: A pointer to the HDMI connector to init + * @vendor: HDMI Controller Vendor name + * @product: HDMI Controller Product name * @funcs: callbacks for this connector * @connector_type: user visible type of the connector * @ddc: optional pointer to the associated ddc adapter @@ -652,6 +931,7 @@ EXPORT_SYMBOL(drm_atomic_helper_hdmi_connector_print_state); */ int drmm_hdmi_connector_init(struct drm_device *dev, struct drm_hdmi_connector *hdmi_connector, + const char *vendor, const char *product, const struct drm_connector_funcs *funcs, const struct drm_hdmi_connector_funcs *hdmi_funcs, int connector_type, @@ -670,6 +950,13 @@ int drmm_hdmi_connector_init(struct drm_device *dev, if (ret) return ret; + strscpy(hdmi_connector->vendor, vendor, sizeof(hdmi_connector->vendor)); + strscpy(hdmi_connector->product, product, sizeof(hdmi_connector->product)); + + ret = drmm_mutex_init(dev, &hdmi_connector->infoframes.lock); + if (ret) + return ret; + prop = hdmi_connector->broadcast_rgb_property; if (!prop) { prop = drm_property_create_enum(dev, DRM_MODE_PROP_ENUM, diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h index 6e25a16420e4..21da6f428101 100644 --- a/include/drm/drm_connector.h +++ b/include/drm/drm_connector.h @@ -2096,6 +2096,32 @@ struct drm_hdmi_connector_state { * selection value. */ enum drm_hdmi_broadcast_rgb broadcast_rgb; + + /** + * @infoframes: HDMI Infoframes matching that state + */ + struct { + /** + * @avi: AVI Infoframes structure matching our state. + */ + struct hdmi_avi_infoframe avi; + + /** + * @drm: DRM Infoframes structure matching our state. + */ + struct hdmi_drm_infoframe drm; + + /** + * @spd: SPD Infoframes structure matching our state. + */ + struct hdmi_spd_infoframe spd; + + /** + * @vendor: Vendor Infoframes structure matching our + * state. + */ + struct hdmi_vendor_infoframe vendor; + } infoframes; }; #define connector_state_to_hdmi_connector_state(state) \ @@ -2127,6 +2153,11 @@ int drm_atomic_helper_hdmi_connector_atomic_check(struct drm_connector *connecto void drm_atomic_helper_hdmi_connector_print_state(struct drm_printer *p, const struct drm_connector_state *state); +int drm_atomic_helper_hdmi_connector_update_infoframes(struct drm_hdmi_connector *hdmi_connector, + struct drm_hdmi_connector_state *hdmi_state); +int drm_atomic_helper_hdmi_connector_update_audio_infoframe(struct drm_hdmi_connector *hdmi_connector, + struct hdmi_audio_infoframe *frame); + bool drm_atomic_helper_hdmi_connector_is_full_range(const struct drm_hdmi_connector *hdmi_connector, const struct drm_hdmi_connector_state *hdmi_state); @@ -2153,6 +2184,23 @@ struct drm_hdmi_connector_funcs { (*tmds_char_rate_valid)(const struct drm_hdmi_connector *connector, const struct drm_display_mode *mode, unsigned long long tmds_rate); + + /** + * @write_infoframe: + * + * This callback is invoked through + * @drm_atomic_helper_hdmi_connector_update_infoframes during a + * commit to program the infoframes into the hardware. It will + * be called multiple times, once for every infoframe type. + * + * The @write_infoframe callback is mandatory. + * + * Returns: + * 0 on success, a negative error code otherwise + */ + int (*write_infoframe)(struct drm_hdmi_connector *connector, + enum hdmi_infoframe_type type, + const u8 *buffer, size_t len); }; struct drm_hdmi_connector { @@ -2161,6 +2209,16 @@ struct drm_hdmi_connector { */ struct drm_connector base; + /** + * @vendor: HDMI Controller Vendor Name + */ + char vendor[8]; + + /** + * @product: HDMI Controller Product Name + */ + char product[16]; + /** * @funcs: HDMI connector Control Functions */ @@ -2176,6 +2234,47 @@ struct drm_hdmi_connector { * Broadcast RGB selection to output with. */ struct drm_property *broadcast_rgb_property; + + /** + * @infoframes: Current Infoframes output by the connector + */ + struct { + /** + * @lock: Mutex protecting against concurrent access to + * the infoframes, most notably between KMS and ALSA. + */ + struct mutex lock; + + /** + * @audio: Current Audio Infoframes structure. Protected + * by @lock. + */ + struct hdmi_audio_infoframe audio; + + /** + * @avi: Current AVI Infoframes structure. Protected by + * @lock. + */ + struct hdmi_avi_infoframe avi; + + /** + * @drm: Current DRM Infoframes structure. Protected by + * @lock. + */ + struct hdmi_drm_infoframe drm; + + /** + * @spd: Current SPD Infoframes structure. Protected by + * @lock. + */ + struct hdmi_spd_infoframe spd; + + /** + * @vendor: Current Vendor Infoframes structure. + * Protected by @lock. + */ + struct hdmi_vendor_infoframe vendor; + } infoframes; }; #define connector_to_hdmi_connector(connector) \ @@ -2188,6 +2287,7 @@ drm_hdmi_connector_compute_mode_clock(const struct drm_display_mode *mode, int drmm_hdmi_connector_init(struct drm_device *dev, struct drm_hdmi_connector *hdmi_connector, + const char *vendor, const char *product, const struct drm_connector_funcs *funcs, const struct drm_hdmi_connector_funcs *hdmi_funcs, int connector_type, From patchwork Mon Aug 14 13:56:23 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Maxime Ripard X-Patchwork-Id: 135472 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:b824:0:b0:3f2:4152:657d with SMTP id z4csp2787646vqi; Mon, 14 Aug 2023 07:37:59 -0700 (PDT) X-Google-Smtp-Source: AGHT+IGWqa517EvAI2CFK+Ao3JWsjnFqnLELAl90RRji9Al7iAIq2B6W9fqiXQDwbwWGuLkjbYr3 X-Received: by 2002:a17:902:70c6:b0:1bd:a50a:e2d0 with SMTP id l6-20020a17090270c600b001bda50ae2d0mr8989830plt.66.1692023879449; Mon, 14 Aug 2023 07:37:59 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1692023879; cv=none; d=google.com; s=arc-20160816; b=L61OgUkNcqWOlm6AQtYYzY70RP5LtLTz0KMrHjb5+HGvyQ3jSvbPqahrqCAaSZs55S tV/+DWYcdVjMvAQ3CNpA/Z3fyZg4H1yc0slMOeW0MHoNmZ78q++z0X4p5nUIUhrQ+JDB DYl35iLH5UEyrsrfroRUWSJTohqjCwRtT9Ap0EFAsSG5qxqBAYiSulygjL9YHya7gHOJ /VXVHCRfaPb2Y9xdHfJFj8ksTpaxzafpUMjEY7lFVhsGnzLtFQbIsVrstM/VBDlb/3Sg 0QXGqYudwEMBgGTM2LwdBeM9mUnkqV4CxjgdlaeGkkbHhSOU1VDkYD6EPnGXxGw2WdM/ 9z0w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:cc:to:in-reply-to:references:message-id :content-transfer-encoding:mime-version:subject:date:from :dkim-signature; bh=gNapfuC3AQKxaICeEHqxjOa3S+vK6zNOHb8B483b/O4=; fh=XsS7fCnS6jyV48OHq4AWazZQaFUKJmjcq7fZaQkmGOY=; b=xPiqFZ5y4PvCLG/JpSXLNEr7wi6STWbqIMGkMt7Fx42cYlAwERni8W3CuPSQGZ43aK jBuZKt1dgbm9OFdl0VoWHQxKO0jI7oytLglKOQOh/6fDZGemW+1LPugWHAhT7TpGGxgv /bcgWCOXbuXtWYDsdHG5My4AP9aV1pHr+E3Xb3k9CjlhfduFou8688tJ6ns1GBLKDdfN ZGjo7TTmOBk/D3x17Vfg4BJoYAdjPg1J7MPZtULtjgTZ+eZBladXUR0LsDcDpAQFm7tf yICG+AP5RKsR7g57vpQIrqlS52rmOKP+Rz/FySQyLtn1Km/O4eGplNTTER3xpSuFnoPm 6znQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=Fog9q62h; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id i2-20020a170902c94200b001bdd58f685fsi3386811pla.85.2023.08.14.07.37.44; Mon, 14 Aug 2023 07:37:59 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=Fog9q62h; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231801AbjHNN5b (ORCPT + 99 others); Mon, 14 Aug 2023 09:57:31 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:56292 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231724AbjHNN47 (ORCPT ); Mon, 14 Aug 2023 09:56:59 -0400 Received: from dfw.source.kernel.org (dfw.source.kernel.org [IPv6:2604:1380:4641:c500::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 20719E6D for ; Mon, 14 Aug 2023 06:56:58 -0700 (PDT) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id A9314617F7 for ; Mon, 14 Aug 2023 13:56:57 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id B9043C433C8; Mon, 14 Aug 2023 13:56:56 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1692021417; bh=nN7A8aX650BJayqTH47PuZ20wjfgMPZ8NkgLMf28J08=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=Fog9q62hsfReC7FGCvqSNnMF1whoWFVhYEG9/nafcBXtHi2+RdzOUOvBe1zfcU0eC 5tBO3GLSKjyZTpIJtWn8TD38IloC6/SirAA63RdpxgtX6Bwpu+UnTyEP9rjzxSYuvk 1LllQgoGyDv/HHI67lH1//CEiywsiAcrvnMZM+we8EYhj5hDwZ9CMWr61GGwFXLPH6 f9q6JqcBiY9wVF3wUVGH8bylZFcEKOnFdAWMCS+1dnd/j1qbavn70n62+yD1ILfrhb VTueLBY1PiJbeUfBFU3ZtIXsm7StVNnalgB8FfUAtpFe41hw/Dt2vrJAMlbLxvkjoA rH5BEpshpnNaA== From: Maxime Ripard Date: Mon, 14 Aug 2023 15:56:23 +0200 Subject: [PATCH RFC 11/13] drm/connector: hdmi: Create Infoframe DebugFS entries MIME-Version: 1.0 Message-Id: <20230814-kms-hdmi-connector-state-v1-11-048054df3654@kernel.org> References: <20230814-kms-hdmi-connector-state-v1-0-048054df3654@kernel.org> In-Reply-To: <20230814-kms-hdmi-connector-state-v1-0-048054df3654@kernel.org> To: Maarten Lankhorst , Thomas Zimmermann , David Airlie , Daniel Vetter , Emma Anholt Cc: Hans Verkuil , linux-kernel@vger.kernel.org, dri-devel@lists.freedesktop.org, Maxime Ripard X-Mailer: b4 0.12.3 X-Developer-Signature: v=1; a=openpgp-sha256; l=5070; i=mripard@kernel.org; h=from:subject:message-id; bh=nN7A8aX650BJayqTH47PuZ20wjfgMPZ8NkgLMf28J08=; b=owGbwMvMwCX2+D1vfrpE4FHG02pJDCm3jNp0zn/at0gv6fEib6aQwIP+0xssXsyVaYh8tTVdO sVbyFiso5SFQYyLQVZMkSVG2HxJ3KlZrzvZ+ObBzGFlAhnCwMUpABMRFWFk+P5fdjrHhG0/JZ9O fZhi6ucwaRrPO/cAYRPFMwqXVDVP7mX4nxhdpP10wV7NyPhm5qvxB1kX170PCZe7wPXtglzz3tL bfAA= X-Developer-Key: i=mripard@kernel.org; a=openpgp; fpr=BE5675C37E818C8B5764241C254BCFC56BF6CE8D X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF, RCVD_IN_DNSWL_BLOCKED,SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1774215631443549877 X-GMAIL-MSGID: 1774215631443549877 There has been some discussions recently about the infoframes sent by drivers and if they were properly generated. In parallel, there's been some interest in creating an infoframe-decode tool similar to edid-decode. Both would be much easier if we were to expose the infoframes programmed in the hardware. It won't be perfect since we have no guarantee that it's actually what goes through the wire, but it's the best we can do. Signed-off-by: Maxime Ripard --- drivers/gpu/drm/drm_hdmi_connector.c | 124 +++++++++++++++++++++++++++++++++++ include/drm/drm_connector.h | 4 ++ 2 files changed, 128 insertions(+) diff --git a/drivers/gpu/drm/drm_hdmi_connector.c b/drivers/gpu/drm/drm_hdmi_connector.c index 46cafb17def7..dcc45b1080f9 100644 --- a/drivers/gpu/drm/drm_hdmi_connector.c +++ b/drivers/gpu/drm/drm_hdmi_connector.c @@ -907,6 +907,130 @@ void drm_atomic_helper_hdmi_connector_print_state(struct drm_printer *p, } EXPORT_SYMBOL(drm_atomic_helper_hdmi_connector_print_state); +struct debugfs_wrapper { + struct drm_hdmi_connector *hdmi_connector; + union hdmi_infoframe *frame; +}; + +static ssize_t +infoframe_read(struct file *filp, char __user *ubuf, size_t count, loff_t *ppos) +{ + const struct debugfs_wrapper *wrapper = filp->private_data; + struct drm_hdmi_connector *hdmi_connector = wrapper->hdmi_connector; + union hdmi_infoframe *frame = wrapper->frame; + u8 buf[HDMI_MAX_INFOFRAME_SIZE]; + ssize_t len; + + len = hdmi_infoframe_pack(frame, buf, sizeof(buf)); + if (len < 0) + return len; + + mutex_lock(&hdmi_connector->infoframes.lock); + len = simple_read_from_buffer(ubuf, count, ppos, buf, len); + mutex_unlock(&hdmi_connector->infoframes.lock); + + return len; +} + +static const struct file_operations infoframe_fops = { + .owner = THIS_MODULE, + .open = simple_open, + .read = infoframe_read, +}; + +static int create_debugfs_infoframe_file(struct drm_hdmi_connector *hdmi_connector, + struct dentry *parent, + const char *filename, + union hdmi_infoframe *frame) +{ + struct drm_device *dev = hdmi_connector->base.dev; + struct debugfs_wrapper *wrapper; + struct dentry *file; + + wrapper = drmm_kzalloc(dev, sizeof(*wrapper), GFP_KERNEL); + if (!wrapper) + return -ENOMEM; + + wrapper->hdmi_connector = hdmi_connector; + wrapper->frame = frame; + + file = debugfs_create_file(filename, 0400, parent, wrapper, &infoframe_fops); + if (IS_ERR(file)) + return PTR_ERR(file); + + return 0; +} + +#define CREATE_INFOFRAME_FILE(c, p, i) \ + create_debugfs_infoframe_file(c, p, #i, (union hdmi_infoframe *)&(c)->infoframes.i) + +static int create_debugfs_infoframe_files(struct drm_hdmi_connector *hdmi_connector, + struct dentry *parent) +{ + int ret; + + ret = CREATE_INFOFRAME_FILE(hdmi_connector, parent, audio); + if (ret) + return ret; + + ret = CREATE_INFOFRAME_FILE(hdmi_connector, parent, avi); + if (ret) + return ret; + + ret = CREATE_INFOFRAME_FILE(hdmi_connector, parent, drm); + if (ret) + return ret; + + ret = CREATE_INFOFRAME_FILE(hdmi_connector, parent, spd); + if (ret) + return ret; + + ret = CREATE_INFOFRAME_FILE(hdmi_connector, parent, vendor); + if (ret) + return ret; + + return 0; +} + +#undef CREATE_INFOFRAME_FILE + +static void remove_debugfs_dir(struct drm_device *dev, void *data) +{ + struct dentry *dir = data; + + debugfs_remove_recursive(dir); +} + +/** + * drm_helper_hdmi_connector_debugfs_init - DebugFS init for HDMI connectors + * @connector: Parent Connector + * @dentry: DebugFS root dentry + * + * Provides a default implementation for + * @drm_connector_helper_funcs.debugfs_init that will create all the + * files relevant for a @drm_hdmi_connector. + */ +void drm_helper_hdmi_connector_debugfs_init(struct drm_connector *connector, + struct dentry *root) +{ + struct drm_hdmi_connector *hdmi_connector = + connector_to_hdmi_connector(connector); + struct drm_device *dev = hdmi_connector->base.dev; + struct dentry *dir; + int ret; + + dir = debugfs_create_dir("infoframes", root); + if (IS_ERR(dir)) + return; + + ret = drmm_add_action_or_reset(dev, remove_debugfs_dir, dir); + if (ret) + return; + + create_debugfs_infoframe_files(hdmi_connector, dir); +} +EXPORT_SYMBOL(drm_helper_hdmi_connector_debugfs_init); + /** * drmm_hdmi_connector_init - Init a preallocated HDMI connector * @dev: DRM device diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h index 21da6f428101..e5faaeb35a9d 100644 --- a/include/drm/drm_connector.h +++ b/include/drm/drm_connector.h @@ -2294,6 +2294,10 @@ int drmm_hdmi_connector_init(struct drm_device *dev, struct i2c_adapter *ddc, unsigned int max_bpc); +void drm_helper_hdmi_connector_debugfs_init(struct drm_connector *connector, + struct dentry *root); + + /** * struct drm_tile_group - Tile group metadata * @refcount: reference count From patchwork Mon Aug 14 13:56:24 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Maxime Ripard X-Patchwork-Id: 135466 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:b824:0:b0:3f2:4152:657d with SMTP id z4csp2775785vqi; Mon, 14 Aug 2023 07:17:55 -0700 (PDT) X-Google-Smtp-Source: AGHT+IFpizdrtZ+2C64Ia2O3wYK8sV8Y8oa0guOEQW7iG2vlYat7InB4N+9hIytuHDATLYfsOPil X-Received: by 2002:a17:902:ec8c:b0:1bb:7d2f:7c19 with SMTP id x12-20020a170902ec8c00b001bb7d2f7c19mr11701831plg.64.1692022674631; Mon, 14 Aug 2023 07:17:54 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1692022674; cv=none; d=google.com; s=arc-20160816; b=dF4C5UuttxYyM5m5m4QIWvipY9xNYOt4QQYi1l2+1GfACoIT+jXjtuNnFq3zgkoQje LdKPAbkRQ3NsPb524+pgOHXqhMn4YFX3wmuZwO7ocS9PO98W75sZFhbMpmavo2GssWXv q5MfEgJj+ZKWqlRVJvh6l3khUowOj3+jQFsVmhDcmBgPYRuyTDo02brcVJJuWuaxdzyg 7IQw9UlkVDaJTppfOSnsSb0gw2YGCUJqtqtEmJ9NNd4WEl42XOxkikGy5GbRRJ/fkGoH gvnYNMK3+UVXtq58kZIEPF8G1oGrhWfdTu8uacvPSchXdvK3ObSIT/bvSGaASwVzNhxU nE0g== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:cc:to:in-reply-to:references:message-id :content-transfer-encoding:mime-version:subject:date:from :dkim-signature; bh=VsMQMC+dqNT198uO/C6rBaW5Ng8QZ1OTjc+4QAAjIwU=; fh=XsS7fCnS6jyV48OHq4AWazZQaFUKJmjcq7fZaQkmGOY=; b=utr61a14kkrziBCTHEmu3KHYOOZfgnuB5Aq6/MB23uNTq6VjxrUhatIcZKV5O/jr8g OTwGypj4BWZ8hnVmQUwZxM/lDxThx9adrAlaiDizH6FKVEXoibsozVg9Im0bk9LRp8mx iP5thf8h25NrfIMehqavIhc6HT55qqCMqnjAldy60AxOILlGNN7E+lmSsyBAoUeqzZtK a0nAQx74fF4HXpiCT+LPsWKJL5KIdKU5S0MA5Rz61oiZYoJcCGqHFyd6ahRO7Q8yGFhF 94qFCTytCiWPPam+FD2OhwC7MdXG6zCEMn3XeK+k3lF6SJRh62UJe7Nebv6Ra+maMilF Wzlw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=jcBvQE5M; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id u12-20020a170902e80c00b001bb935754f0si8300624plg.444.2023.08.14.07.17.40; Mon, 14 Aug 2023 07:17:54 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=jcBvQE5M; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231814AbjHNN5d (ORCPT + 99 others); Mon, 14 Aug 2023 09:57:33 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:45904 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231744AbjHNN5B (ORCPT ); Mon, 14 Aug 2023 09:57:01 -0400 Received: from dfw.source.kernel.org (dfw.source.kernel.org [IPv6:2604:1380:4641:c500::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id E3622E7D for ; Mon, 14 Aug 2023 06:57:00 -0700 (PDT) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id 776A961796 for ; Mon, 14 Aug 2023 13:57:00 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 897AEC433C8; Mon, 14 Aug 2023 13:56:59 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1692021419; bh=0EIFvA5+tRKt9U3IH9IJeiJikcR9vpCTg2DVlFki8rM=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=jcBvQE5MgxAtWYsKgfg1Wli1ztakkvC+/9bj6uYYd3VIZgzdxLanbFVjuHJR47qwm b2fDhc2lEHSSmX2B+0SU2b9aaoQ+Yc/66d2+muQC5rhn611nN4Be9kFwJpuwqAqWN8 Cdp5q6m8QiPptSqECfPYMOUm6ML57WQT38KWoriVB8ZfBi7yknhhUvLB0N28JHTgYh ut0fyDaXkrMb/pERj+FFygZAAqzwPaAfZNR8NKXdKbflQvfUStGxx4d7PzrpHYEiwl oiOSqWhPR+XjouVlMeYjHZkxRZFvQwZ0R1Y5P6G7vvBvXJ2oOu1RgNOVtAGsc84odF Wj7NgTFv/ro1A== From: Maxime Ripard Date: Mon, 14 Aug 2023 15:56:24 +0200 Subject: [PATCH RFC 12/13] drm/vc4: hdmi: Create destroy state implementation MIME-Version: 1.0 Message-Id: <20230814-kms-hdmi-connector-state-v1-12-048054df3654@kernel.org> References: <20230814-kms-hdmi-connector-state-v1-0-048054df3654@kernel.org> In-Reply-To: <20230814-kms-hdmi-connector-state-v1-0-048054df3654@kernel.org> To: Maarten Lankhorst , Thomas Zimmermann , David Airlie , Daniel Vetter , Emma Anholt Cc: Hans Verkuil , linux-kernel@vger.kernel.org, dri-devel@lists.freedesktop.org, Maxime Ripard X-Mailer: b4 0.12.3 X-Developer-Signature: v=1; a=openpgp-sha256; l=1292; i=mripard@kernel.org; h=from:subject:message-id; bh=0EIFvA5+tRKt9U3IH9IJeiJikcR9vpCTg2DVlFki8rM=; b=owGbwMvMwCX2+D1vfrpE4FHG02pJDCm3jNr0jlw2e/rjJ8/vmqCvxvEuQXv+1PAsW7apT5hf/ 3iJzNbsjhIWBjEuBlkxRZYYYfMlcadmve5k45sHM4eVCWQIAxenAEzkSjbDj18ObaYXn6yRMJUX Pf77T+SmiOvzDr2dsLUw6fne6U2dMgz/g3v3fJsz4cmRU/4+wVf3rJHaaHR+h+gRRTmWwH1/Li3 8yAsA X-Developer-Key: i=mripard@kernel.org; a=openpgp; fpr=BE5675C37E818C8B5764241C254BCFC56BF6CE8D X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF, RCVD_IN_DNSWL_BLOCKED,SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1774214368004806174 X-GMAIL-MSGID: 1774214368004806174 Signed-off-by: Maxime Ripard --- drivers/gpu/drm/vc4/vc4_hdmi.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index 5261526d286f..ac5debd47e99 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -672,11 +672,21 @@ vc4_hdmi_connector_duplicate_state(struct drm_connector *connector) return &new_state->base; } +static void vc4_hdmi_connector_destroy_state(struct drm_connector *connector, + struct drm_connector_state *state) +{ + struct vc4_hdmi_connector_state *vc4_state = + conn_state_to_vc4_hdmi_conn_state(state); + + __drm_atomic_helper_connector_destroy_state(state); + kfree(vc4_state); +} + static const struct drm_connector_funcs vc4_hdmi_connector_funcs = { .fill_modes = drm_helper_probe_single_connector_modes, .reset = vc4_hdmi_connector_reset, .atomic_duplicate_state = vc4_hdmi_connector_duplicate_state, - .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, + .atomic_destroy_state = vc4_hdmi_connector_destroy_state, .atomic_get_property = vc4_hdmi_connector_get_property, .atomic_set_property = vc4_hdmi_connector_set_property, }; From patchwork Mon Aug 14 13:56:25 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Maxime Ripard X-Patchwork-Id: 135469 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:b824:0:b0:3f2:4152:657d with SMTP id z4csp2784787vqi; Mon, 14 Aug 2023 07:33:21 -0700 (PDT) X-Google-Smtp-Source: AGHT+IEr+99rG1FmhlrnCOsRyNHAOL4II0mDUd1geYZAZ1yfTr9y2rSLSjBEE2tA1tBjS/ezcLQq X-Received: by 2002:a17:907:2cd3:b0:997:ea67:cb2f with SMTP id hg19-20020a1709072cd300b00997ea67cb2fmr8249118ejc.48.1692023600694; Mon, 14 Aug 2023 07:33:20 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1692023600; cv=none; d=google.com; s=arc-20160816; b=dc5/x/yosXONj5f1/A0jW3SXlvyKIuX35TvpDIdCDwUoRqYBRE74/W8Gtbf6/8hs13 esA6svyqzI/6YbjT3V9kL7Vzu7hS1HrO8Bn/SbMenEWJNoq6KjKC6NjmJtUcKr2q01/J vymgFDRoQsf93OxeRKvr0W3a13rfYVAGZCzom8W294HCe7irmoibdEKOYFZEqgLcv7Eg hqTDJHwq8UVk1MVnhSWcI//9HjL5SmUzDBkuttbJq8AW62h0TDvHQIXnXq7swHE66ivL ABzt0xbocI5w1XbjnLrYcEC8p7Cz9LzLZmI1UzQlKsVkt2jAhDHdLmXdS2b9aY7OXs/g HZTw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:cc:to:in-reply-to:references:message-id :content-transfer-encoding:mime-version:subject:date:from :dkim-signature; bh=nWnkvEsyzG8cAZoUImBaDQWamQlUfNq8gK/4L7whnDk=; fh=XsS7fCnS6jyV48OHq4AWazZQaFUKJmjcq7fZaQkmGOY=; b=FjDWuNkgJlWyujdjZ6qg1k15lDIIx1/6YJU1SNIujtWu5BQc9E3YSYrWq5RkyzQ9sE DCkC+6MzY9R4TLaxpY8+qkN8fq5JRdlqRfbFCrhYL3fFSJAhCswZVmAiGscGnk9HaGx1 tSM6d0vCadhZKjwCAdaZQ4d2ElXfLmdHGJuCzkXoWP+i67Q02XKiPS0F0uxkFnFGzcQZ blY6Jk0T8qYUKYuUQonL+zZzX75jPl/pwkYxWo8En0JP/APbgwlkMp/bUp8wMwVnwPEZ XT4zYyX6ODfbgRqdaLKot3Z6VJkS11q628ldp/2QGx5krBD6dKe3W3skSttR41MoHkLM 4ZXA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=JXLrycuM; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id i7-20020a17090685c700b0099bcf14bc06si8051001ejy.859.2023.08.14.07.32.55; Mon, 14 Aug 2023 07:33:20 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=JXLrycuM; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231826AbjHNN5h (ORCPT + 99 others); Mon, 14 Aug 2023 09:57:37 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:45956 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229668AbjHNN5H (ORCPT ); Mon, 14 Aug 2023 09:57:07 -0400 Received: from dfw.source.kernel.org (dfw.source.kernel.org [IPv6:2604:1380:4641:c500::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 016AEE6D for ; Mon, 14 Aug 2023 06:57:04 -0700 (PDT) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id 60B8062615 for ; Mon, 14 Aug 2023 13:57:03 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 45D23C433C9; Mon, 14 Aug 2023 13:57:02 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1692021422; bh=JPQX2x+iI21IAczs4dC2NfI3O3fRHsco0qFR057uzd0=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=JXLrycuMRm+lVnb004gLMNtCTs2WTIGNO9BuLJMeVVZ3fxUSqs46crusEg9WK7hCM NOeCc4yclfegJVFC9QxDeK/bhpiw2Ftpsp12gcvBTJkQoFm1i7x7QQH0+lZTx5p2aK fjMdSnVUBnT8nwynKGyDK07+CafukAj7jvPd4awTQxECYG2HBXrgm+h2B3VbcW9LEc ZjpQkS0X9PwFo/VSW0GdfJDK4qqahSXhyRXKG3IMgT9qSOAdXjMixiRU2o0fgt9KO4 itZi2DgegGxdHsRXlhExQSP9liAcjAC+sq9B322zYT/BBA+H2dU+IGyCQNfzuJX2rR 8k9RNy1vENoDA== From: Maxime Ripard Date: Mon, 14 Aug 2023 15:56:25 +0200 Subject: [PATCH RFC 13/13] drm/vc4: hdmi: Switch to HDMI connector MIME-Version: 1.0 Message-Id: <20230814-kms-hdmi-connector-state-v1-13-048054df3654@kernel.org> References: <20230814-kms-hdmi-connector-state-v1-0-048054df3654@kernel.org> In-Reply-To: <20230814-kms-hdmi-connector-state-v1-0-048054df3654@kernel.org> To: Maarten Lankhorst , Thomas Zimmermann , David Airlie , Daniel Vetter , Emma Anholt Cc: Hans Verkuil , linux-kernel@vger.kernel.org, dri-devel@lists.freedesktop.org, Maxime Ripard X-Mailer: b4 0.12.3 X-Developer-Signature: v=1; a=openpgp-sha256; l=49401; i=mripard@kernel.org; h=from:subject:message-id; bh=JPQX2x+iI21IAczs4dC2NfI3O3fRHsco0qFR057uzd0=; b=owGbwMvMwCX2+D1vfrpE4FHG02pJDCm3jNpUf3+svssneVg4iePr3Ykt2ok6/3xO1O1PkTJoP WqRfLy9o5SFQYyLQVZMkSVG2HxJ3KlZrzvZ+ObBzGFlAhnCwMUpABPpkmH4716w3zDQKdiUK+/O /I7kl11ZXJnns4vWpU9ceY7jXGzdeYZ/9q8+Kmk/3hSyfVmdYpvYUYPXQj08YpeUWItUkqVj2vf yAwA= X-Developer-Key: i=mripard@kernel.org; a=openpgp; fpr=BE5675C37E818C8B5764241C254BCFC56BF6CE8D X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF, RCVD_IN_DNSWL_BLOCKED,SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1774215339245618989 X-GMAIL-MSGID: 1774215339245618989 The new HDMI connector infrastructure allows us to remove a lot of boilerplate, so let's switch to it. Signed-off-by: Maxime Ripard --- drivers/gpu/drm/vc4/vc4_hdmi.c | 730 +++++++------------------------------ drivers/gpu/drm/vc4/vc4_hdmi.h | 37 +- drivers/gpu/drm/vc4/vc4_hdmi_phy.c | 4 +- 3 files changed, 139 insertions(+), 632 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index ac5debd47e99..9a17e5d64b4c 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -109,28 +109,10 @@ #define HDMI_14_MAX_TMDS_CLK (340 * 1000 * 1000) -static const char * const output_format_str[] = { - [VC4_HDMI_OUTPUT_RGB] = "RGB", - [VC4_HDMI_OUTPUT_YUV420] = "YUV 4:2:0", - [VC4_HDMI_OUTPUT_YUV422] = "YUV 4:2:2", - [VC4_HDMI_OUTPUT_YUV444] = "YUV 4:4:4", -}; - -static const char *vc4_hdmi_output_fmt_str(enum vc4_hdmi_output_format fmt) -{ - if (fmt >= ARRAY_SIZE(output_format_str)) - return "invalid"; - - return output_format_str[fmt]; -} - -static unsigned long long -vc4_hdmi_encoder_compute_mode_clock(const struct drm_display_mode *mode, - unsigned int bpc, enum vc4_hdmi_output_format fmt); - static bool vc4_hdmi_supports_scrambling(struct vc4_hdmi *vc4_hdmi) { - struct drm_display_info *display = &vc4_hdmi->connector.display_info; + struct drm_connector *connector = &vc4_hdmi->connector.base; + struct drm_display_info *display = &connector->display_info; lockdep_assert_held(&vc4_hdmi->mutex); @@ -148,31 +130,16 @@ static bool vc4_hdmi_mode_needs_scrambling(const struct drm_display_mode *mode, unsigned int bpc, enum vc4_hdmi_output_format fmt) { - unsigned long long clock = vc4_hdmi_encoder_compute_mode_clock(mode, bpc, fmt); + unsigned long long clock = drm_hdmi_connector_compute_mode_clock(mode, bpc, fmt); return clock > HDMI_14_MAX_TMDS_CLK; } -static bool vc4_hdmi_is_full_range(struct vc4_hdmi *vc4_hdmi, - struct vc4_hdmi_connector_state *vc4_state) -{ - const struct drm_display_mode *mode = &vc4_hdmi->saved_adjusted_mode; - struct drm_display_info *display = &vc4_hdmi->connector.display_info; - - if (vc4_state->broadcast_rgb == VC4_HDMI_BROADCAST_RGB_LIMITED) - return false; - else if (vc4_state->broadcast_rgb == VC4_HDMI_BROADCAST_RGB_FULL) - return true; - - return !display->is_hdmi || - drm_default_rgb_quant_range(mode) == HDMI_QUANTIZATION_RANGE_FULL; -} - static int vc4_hdmi_debugfs_regs(struct seq_file *m, void *unused) { struct drm_debugfs_entry *entry = m->private; struct vc4_hdmi *vc4_hdmi = entry->file.data; - struct drm_device *drm = vc4_hdmi->connector.dev; + struct drm_device *drm = vc4_hdmi->connector.base.dev; struct drm_printer p = drm_seq_file_printer(m); int idx; @@ -195,7 +162,7 @@ static int vc4_hdmi_debugfs_regs(struct seq_file *m, void *unused) static void vc4_hdmi_reset(struct vc4_hdmi *vc4_hdmi) { - struct drm_device *drm = vc4_hdmi->connector.dev; + struct drm_device *drm = vc4_hdmi->connector.base.dev; unsigned long flags; int idx; @@ -228,7 +195,7 @@ static void vc4_hdmi_reset(struct vc4_hdmi *vc4_hdmi) static void vc5_hdmi_reset(struct vc4_hdmi *vc4_hdmi) { - struct drm_device *drm = vc4_hdmi->connector.dev; + struct drm_device *drm = vc4_hdmi->connector.base.dev; unsigned long flags; int idx; @@ -257,7 +224,7 @@ static void vc5_hdmi_reset(struct vc4_hdmi *vc4_hdmi) #ifdef CONFIG_DRM_VC4_HDMI_CEC static void vc4_hdmi_cec_update_clk_div(struct vc4_hdmi *vc4_hdmi) { - struct drm_device *drm = vc4_hdmi->connector.dev; + struct drm_device *drm = vc4_hdmi->connector.base.dev; unsigned long cec_rate; unsigned long flags; u16 clk_cnt; @@ -410,7 +377,7 @@ static void vc4_hdmi_handle_hotplug(struct vc4_hdmi *vc4_hdmi, struct drm_modeset_acquire_ctx *ctx, enum drm_connector_status status) { - struct drm_connector *connector = &vc4_hdmi->connector; + struct drm_connector *connector = &vc4_hdmi->connector.base; struct edid *edid; int ret; @@ -534,12 +501,8 @@ static int vc4_hdmi_connector_atomic_check(struct drm_connector *connector, { struct drm_connector_state *old_state = drm_atomic_get_old_connector_state(state, connector); - struct vc4_hdmi_connector_state *old_vc4_state = - conn_state_to_vc4_hdmi_conn_state(old_state); struct drm_connector_state *new_state = drm_atomic_get_new_connector_state(state, connector); - struct vc4_hdmi_connector_state *new_vc4_state = - conn_state_to_vc4_hdmi_conn_state(new_state); struct drm_crtc *crtc = new_state->crtc; if (!crtc) @@ -571,9 +534,7 @@ static int vc4_hdmi_connector_atomic_check(struct drm_connector *connector, return ret; } - if (old_state->colorspace != new_state->colorspace || - old_vc4_state->broadcast_rgb != new_vc4_state->broadcast_rgb || - !drm_connector_atomic_hdr_metadata_equal(old_state, new_state)) { + if (old_state->colorspace != new_state->colorspace) { struct drm_crtc_state *crtc_state; crtc_state = drm_atomic_get_crtc_state(state, crtc); @@ -583,112 +544,23 @@ static int vc4_hdmi_connector_atomic_check(struct drm_connector *connector, crtc_state->mode_changed = true; } - return 0; -} - -static int vc4_hdmi_connector_get_property(struct drm_connector *connector, - const struct drm_connector_state *state, - struct drm_property *property, - uint64_t *val) -{ - struct drm_device *drm = connector->dev; - struct vc4_hdmi *vc4_hdmi = - connector_to_vc4_hdmi(connector); - const struct vc4_hdmi_connector_state *vc4_conn_state = - conn_state_to_vc4_hdmi_conn_state(state); - - if (property == vc4_hdmi->broadcast_rgb_property) { - *val = vc4_conn_state->broadcast_rgb; - } else { - drm_dbg(drm, "Unknown property [PROP:%d:%s]\n", - property->base.id, property->name); - return -EINVAL; - } - - return 0; -} - -static int vc4_hdmi_connector_set_property(struct drm_connector *connector, - struct drm_connector_state *state, - struct drm_property *property, - uint64_t val) -{ - struct drm_device *drm = connector->dev; - struct vc4_hdmi *vc4_hdmi = - connector_to_vc4_hdmi(connector); - struct vc4_hdmi_connector_state *vc4_conn_state = - conn_state_to_vc4_hdmi_conn_state(state); - - if (property == vc4_hdmi->broadcast_rgb_property) { - vc4_conn_state->broadcast_rgb = val; - return 0; - } - - drm_dbg(drm, "Unknown property [PROP:%d:%s]\n", - property->base.id, property->name); - return -EINVAL; + return drm_atomic_helper_hdmi_connector_atomic_check(connector, state); } static void vc4_hdmi_connector_reset(struct drm_connector *connector) { - struct vc4_hdmi_connector_state *old_state = - conn_state_to_vc4_hdmi_conn_state(connector->state); - struct vc4_hdmi_connector_state *new_state = - kzalloc(sizeof(*new_state), GFP_KERNEL); - - if (connector->state) - __drm_atomic_helper_connector_destroy_state(connector->state); - - kfree(old_state); - __drm_atomic_helper_connector_reset(connector, &new_state->base); - - if (!new_state) - return; - - new_state->base.max_bpc = 8; - new_state->base.max_requested_bpc = 8; - new_state->output_format = VC4_HDMI_OUTPUT_RGB; - new_state->broadcast_rgb = VC4_HDMI_BROADCAST_RGB_AUTO; + drm_atomic_helper_hdmi_connector_reset(connector); drm_atomic_helper_connector_tv_margins_reset(connector); } -static struct drm_connector_state * -vc4_hdmi_connector_duplicate_state(struct drm_connector *connector) -{ - struct drm_connector_state *conn_state = connector->state; - struct vc4_hdmi_connector_state *vc4_state = conn_state_to_vc4_hdmi_conn_state(conn_state); - struct vc4_hdmi_connector_state *new_state; - - new_state = kzalloc(sizeof(*new_state), GFP_KERNEL); - if (!new_state) - return NULL; - - new_state->tmds_char_rate = vc4_state->tmds_char_rate; - new_state->output_bpc = vc4_state->output_bpc; - new_state->output_format = vc4_state->output_format; - new_state->broadcast_rgb = vc4_state->broadcast_rgb; - __drm_atomic_helper_connector_duplicate_state(connector, &new_state->base); - - return &new_state->base; -} - -static void vc4_hdmi_connector_destroy_state(struct drm_connector *connector, - struct drm_connector_state *state) -{ - struct vc4_hdmi_connector_state *vc4_state = - conn_state_to_vc4_hdmi_conn_state(state); - - __drm_atomic_helper_connector_destroy_state(state); - kfree(vc4_state); -} - static const struct drm_connector_funcs vc4_hdmi_connector_funcs = { .fill_modes = drm_helper_probe_single_connector_modes, .reset = vc4_hdmi_connector_reset, - .atomic_duplicate_state = vc4_hdmi_connector_duplicate_state, - .atomic_destroy_state = vc4_hdmi_connector_destroy_state, - .atomic_get_property = vc4_hdmi_connector_get_property, - .atomic_set_property = vc4_hdmi_connector_set_property, + .atomic_duplicate_state = drm_atomic_helper_hdmi_connector_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_hdmi_connector_destroy_state, + .atomic_get_property = drm_atomic_helper_hdmi_connector_get_property, + .atomic_set_property = drm_atomic_helper_hdmi_connector_set_property, + .debugfs_init = drm_helper_hdmi_connector_debugfs_init, }; static const struct drm_connector_helper_funcs vc4_hdmi_connector_helper_funcs = { @@ -697,44 +569,23 @@ static const struct drm_connector_helper_funcs vc4_hdmi_connector_helper_funcs = .atomic_check = vc4_hdmi_connector_atomic_check, }; -static const struct drm_prop_enum_list broadcast_rgb_names[] = { - { VC4_HDMI_BROADCAST_RGB_AUTO, "Automatic" }, - { VC4_HDMI_BROADCAST_RGB_FULL, "Full" }, - { VC4_HDMI_BROADCAST_RGB_LIMITED, "Limited 16:235" }, -}; - -static void -vc4_hdmi_attach_broadcast_rgb_property(struct drm_device *dev, - struct vc4_hdmi *vc4_hdmi) -{ - struct drm_property *prop = vc4_hdmi->broadcast_rgb_property; - - if (!prop) { - prop = drm_property_create_enum(dev, DRM_MODE_PROP_ENUM, - "Broadcast RGB", - broadcast_rgb_names, - ARRAY_SIZE(broadcast_rgb_names)); - if (!prop) - return; - - vc4_hdmi->broadcast_rgb_property = prop; - } - - drm_object_attach_property(&vc4_hdmi->connector.base, prop, - VC4_HDMI_BROADCAST_RGB_AUTO); -} +static const struct drm_hdmi_connector_funcs vc4_hdmi_hdmi_connector_funcs; static int vc4_hdmi_connector_init(struct drm_device *dev, struct vc4_hdmi *vc4_hdmi) { - struct drm_connector *connector = &vc4_hdmi->connector; + struct drm_hdmi_connector *hdmi_connector = &vc4_hdmi->connector; + struct drm_connector *connector = &hdmi_connector->base; struct drm_encoder *encoder = &vc4_hdmi->encoder.base; int ret; - ret = drmm_connector_init(dev, connector, - &vc4_hdmi_connector_funcs, - DRM_MODE_CONNECTOR_HDMIA, - vc4_hdmi->ddc); + ret = drmm_hdmi_connector_init(dev, hdmi_connector, + "Broadcom", "Videocore", + &vc4_hdmi_connector_funcs, + &vc4_hdmi_hdmi_connector_funcs, + DRM_MODE_CONNECTOR_HDMIA, + vc4_hdmi->ddc, + 12); if (ret) return ret; @@ -758,7 +609,6 @@ static int vc4_hdmi_connector_init(struct drm_device *dev, drm_connector_attach_colorspace_property(connector); drm_connector_attach_tv_margin_properties(connector); - drm_connector_attach_max_bpc_property(connector, 8, 12); connector->polled = (DRM_CONNECTOR_POLL_CONNECT | DRM_CONNECTOR_POLL_DISCONNECT); @@ -767,22 +617,16 @@ static int vc4_hdmi_connector_init(struct drm_device *dev, connector->doublescan_allowed = 0; connector->stereo_allowed = 1; - if (vc4_hdmi->variant->supports_hdr) - drm_connector_attach_hdr_output_metadata_property(connector); - - vc4_hdmi_attach_broadcast_rgb_property(dev, vc4_hdmi); - drm_connector_attach_encoder(connector, encoder); return 0; } -static int vc4_hdmi_stop_packet(struct drm_encoder *encoder, +static int vc4_hdmi_stop_packet(struct vc4_hdmi *vc4_hdmi, enum hdmi_infoframe_type type, bool poll) { - struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); - struct drm_device *drm = vc4_hdmi->connector.dev; + struct drm_device *drm = vc4_hdmi->connector.base.dev; u32 packet_id = type - 0x80; unsigned long flags; int ret = 0; @@ -805,12 +649,13 @@ static int vc4_hdmi_stop_packet(struct drm_encoder *encoder, return ret; } -static void vc4_hdmi_write_infoframe(struct drm_encoder *encoder, - union hdmi_infoframe *frame) +static int vc4_hdmi_write_infoframe(struct drm_hdmi_connector *hdmi_connector, + enum hdmi_infoframe_type type, + const u8 *buffer, size_t len) { - struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); - struct drm_device *drm = vc4_hdmi->connector.dev; - u32 packet_id = frame->any.type - 0x80; + struct vc4_hdmi *vc4_hdmi = hdmi_connector_to_vc4_hdmi(hdmi_connector); + struct drm_device *drm = vc4_hdmi->connector.base.dev; + u32 packet_id = type - 0x80; const struct vc4_hdmi_register *ram_packet_start = &vc4_hdmi->variant->registers[HDMI_RAM_PACKET_START]; u32 packet_reg = ram_packet_start->offset + VC4_HDMI_PACKET_STRIDE * packet_id; @@ -818,24 +663,19 @@ static void vc4_hdmi_write_infoframe(struct drm_encoder *encoder, VC4_HDMI_PACKET_STRIDE * (packet_id + 1); void __iomem *base = __vc4_hdmi_get_field_base(vc4_hdmi, ram_packet_start->reg); - uint8_t buffer[VC4_HDMI_PACKET_STRIDE] = {}; unsigned long flags; - ssize_t len, i; + ssize_t i; int ret; int idx; if (!drm_dev_enter(drm, &idx)) - return; + return 0; WARN_ONCE(!(HDMI_READ(HDMI_RAM_PACKET_CONFIG) & VC4_HDMI_RAM_PACKET_ENABLE), "Packet RAM has to be on to store the packet."); - len = hdmi_infoframe_pack(frame, buffer, sizeof(buffer)); - if (len < 0) - goto out; - - ret = vc4_hdmi_stop_packet(encoder, frame->any.type, true); + ret = vc4_hdmi_stop_packet(vc4_hdmi, type, true); if (ret) { DRM_ERROR("Failed to wait for infoframe to go idle: %d\n", ret); goto out; @@ -877,130 +717,7 @@ static void vc4_hdmi_write_infoframe(struct drm_encoder *encoder, out: drm_dev_exit(idx); -} - -static void vc4_hdmi_avi_infoframe_colorspace(struct hdmi_avi_infoframe *frame, - enum vc4_hdmi_output_format fmt) -{ - switch (fmt) { - case VC4_HDMI_OUTPUT_RGB: - frame->colorspace = HDMI_COLORSPACE_RGB; - break; - - case VC4_HDMI_OUTPUT_YUV420: - frame->colorspace = HDMI_COLORSPACE_YUV420; - break; - - case VC4_HDMI_OUTPUT_YUV422: - frame->colorspace = HDMI_COLORSPACE_YUV422; - break; - - case VC4_HDMI_OUTPUT_YUV444: - frame->colorspace = HDMI_COLORSPACE_YUV444; - break; - - default: - break; - } -} - -static void vc4_hdmi_set_avi_infoframe(struct drm_encoder *encoder) -{ - struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); - struct drm_connector *connector = &vc4_hdmi->connector; - struct drm_connector_state *cstate = connector->state; - struct vc4_hdmi_connector_state *vc4_state = - conn_state_to_vc4_hdmi_conn_state(cstate); - const struct drm_display_mode *mode = &vc4_hdmi->saved_adjusted_mode; - union hdmi_infoframe frame; - int ret; - - lockdep_assert_held(&vc4_hdmi->mutex); - - ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, - connector, mode); - if (ret < 0) { - DRM_ERROR("couldn't fill AVI infoframe\n"); - return; - } - - drm_hdmi_avi_infoframe_quant_range(&frame.avi, - connector, mode, - vc4_hdmi_is_full_range(vc4_hdmi, vc4_state) ? - HDMI_QUANTIZATION_RANGE_FULL : - HDMI_QUANTIZATION_RANGE_LIMITED); - drm_hdmi_avi_infoframe_colorimetry(&frame.avi, cstate); - vc4_hdmi_avi_infoframe_colorspace(&frame.avi, vc4_state->output_format); - drm_hdmi_avi_infoframe_bars(&frame.avi, cstate); - - vc4_hdmi_write_infoframe(encoder, &frame); -} - -static void vc4_hdmi_set_spd_infoframe(struct drm_encoder *encoder) -{ - union hdmi_infoframe frame; - int ret; - - ret = hdmi_spd_infoframe_init(&frame.spd, "Broadcom", "Videocore"); - if (ret < 0) { - DRM_ERROR("couldn't fill SPD infoframe\n"); - return; - } - - frame.spd.sdi = HDMI_SPD_SDI_PC; - - vc4_hdmi_write_infoframe(encoder, &frame); -} - -static void vc4_hdmi_set_audio_infoframe(struct drm_encoder *encoder) -{ - struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); - struct hdmi_audio_infoframe *audio = &vc4_hdmi->audio.infoframe; - union hdmi_infoframe frame; - - memcpy(&frame.audio, audio, sizeof(*audio)); - - if (vc4_hdmi->packet_ram_enabled) - vc4_hdmi_write_infoframe(encoder, &frame); -} - -static void vc4_hdmi_set_hdr_infoframe(struct drm_encoder *encoder) -{ - struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); - struct drm_connector *connector = &vc4_hdmi->connector; - struct drm_connector_state *conn_state = connector->state; - union hdmi_infoframe frame; - - lockdep_assert_held(&vc4_hdmi->mutex); - - if (!vc4_hdmi->variant->supports_hdr) - return; - - if (!conn_state->hdr_output_metadata) - return; - - if (drm_hdmi_infoframe_set_hdr_metadata(&frame.drm, conn_state)) - return; - - vc4_hdmi_write_infoframe(encoder, &frame); -} - -static void vc4_hdmi_set_infoframes(struct drm_encoder *encoder) -{ - struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); - - lockdep_assert_held(&vc4_hdmi->mutex); - - vc4_hdmi_set_avi_infoframe(encoder); - vc4_hdmi_set_spd_infoframe(encoder); - /* - * If audio was streaming, then we need to reenabled the audio - * infoframe here during encoder_enable. - */ - if (vc4_hdmi->audio.streaming) - vc4_hdmi_set_audio_infoframe(encoder); - - vc4_hdmi_set_hdr_infoframe(encoder); + return ret; } #define SCRAMBLING_POLLING_DELAY_MS 1000 @@ -1008,7 +725,7 @@ static void vc4_hdmi_set_infoframes(struct drm_encoder *encoder) static void vc4_hdmi_enable_scrambling(struct drm_encoder *encoder) { struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); - struct drm_connector *connector = &vc4_hdmi->connector; + struct drm_connector *connector = &vc4_hdmi->connector.base; struct drm_device *drm = connector->dev; const struct drm_display_mode *mode = &vc4_hdmi->saved_adjusted_mode; unsigned long flags; @@ -1046,7 +763,7 @@ static void vc4_hdmi_enable_scrambling(struct drm_encoder *encoder) static void vc4_hdmi_disable_scrambling(struct drm_encoder *encoder) { struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); - struct drm_connector *connector = &vc4_hdmi->connector; + struct drm_connector *connector = &vc4_hdmi->connector.base; struct drm_device *drm = connector->dev; unsigned long flags; int idx; @@ -1080,7 +797,7 @@ static void vc4_hdmi_scrambling_wq(struct work_struct *work) struct vc4_hdmi *vc4_hdmi = container_of(to_delayed_work(work), struct vc4_hdmi, scrambling_work); - struct drm_connector *connector = &vc4_hdmi->connector; + struct drm_connector *connector = &vc4_hdmi->connector.base; if (drm_scdc_get_scrambling_status(connector)) return; @@ -1096,7 +813,7 @@ static void vc4_hdmi_encoder_post_crtc_disable(struct drm_encoder *encoder, struct drm_atomic_state *state) { struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); - struct drm_device *drm = vc4_hdmi->connector.dev; + struct drm_device *drm = vc4_hdmi->connector.base.dev; unsigned long flags; int idx; @@ -1134,7 +851,7 @@ static void vc4_hdmi_encoder_post_crtc_powerdown(struct drm_encoder *encoder, struct drm_atomic_state *state) { struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); - struct drm_device *drm = vc4_hdmi->connector.dev; + struct drm_device *drm = vc4_hdmi->connector.base.dev; unsigned long flags; int ret; int idx; @@ -1169,9 +886,13 @@ static void vc4_hdmi_csc_setup(struct vc4_hdmi *vc4_hdmi, struct drm_connector_state *state, const struct drm_display_mode *mode) { - struct vc4_hdmi_connector_state *vc4_state = - conn_state_to_vc4_hdmi_conn_state(state); - struct drm_device *drm = vc4_hdmi->connector.dev; + struct drm_hdmi_connector *hdmi_connector = &vc4_hdmi->connector; + struct drm_hdmi_connector_state *hdmi_state = + connector_state_to_hdmi_connector_state(state); + struct drm_device *drm = vc4_hdmi->connector.base.dev; + bool is_lim_range = + drm_atomic_helper_hdmi_connector_is_full_range(hdmi_connector, + hdmi_state); unsigned long flags; u32 csc_ctl; int idx; @@ -1184,7 +905,7 @@ static void vc4_hdmi_csc_setup(struct vc4_hdmi *vc4_hdmi, csc_ctl = VC4_SET_FIELD(VC4_HD_CSC_CTL_ORDER_BGR, VC4_HD_CSC_CTL_ORDER); - if (!vc4_hdmi_is_full_range(vc4_hdmi, vc4_state)) { + if (!is_lim_range) { /* CEA VICs other than #1 requre limited range RGB * output unless overridden by an AVI infoframe. * Apply a colorspace conversion to squash 0-255 down @@ -1406,10 +1127,13 @@ static void vc5_hdmi_csc_setup(struct vc4_hdmi *vc4_hdmi, struct drm_connector_state *state, const struct drm_display_mode *mode) { - struct drm_device *drm = vc4_hdmi->connector.dev; - struct vc4_hdmi_connector_state *vc4_state = - conn_state_to_vc4_hdmi_conn_state(state); - unsigned int lim_range = vc4_hdmi_is_full_range(vc4_hdmi, vc4_state) ? 0 : 1; + struct drm_hdmi_connector *hdmi_connector = &vc4_hdmi->connector; + struct drm_device *drm = vc4_hdmi->connector.base.dev; + struct drm_hdmi_connector_state *hdmi_state = + connector_state_to_hdmi_connector_state(state); + unsigned int lim_range = + drm_atomic_helper_hdmi_connector_is_full_range(hdmi_connector, + hdmi_state) ? 0 : 1; unsigned long flags; const u16 (*csc)[4]; u32 if_cfg = 0; @@ -1424,14 +1148,14 @@ static void vc5_hdmi_csc_setup(struct vc4_hdmi *vc4_hdmi, spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); - switch (vc4_state->output_format) { - case VC4_HDMI_OUTPUT_YUV444: + switch (hdmi_state->output_format) { + case HDMI_COLORSPACE_YUV444: csc = vc5_hdmi_find_yuv_csc_coeffs(vc4_hdmi, state->colorspace, !!lim_range); vc5_hdmi_set_csc_coeffs_swap(vc4_hdmi, csc); break; - case VC4_HDMI_OUTPUT_YUV422: + case HDMI_COLORSPACE_YUV422: csc = vc5_hdmi_find_yuv_csc_coeffs(vc4_hdmi, state->colorspace, !!lim_range); csc_ctl |= VC4_SET_FIELD(VC5_MT_CP_CSC_CTL_FILTER_MODE_444_TO_422_STANDARD, @@ -1448,7 +1172,7 @@ static void vc5_hdmi_csc_setup(struct vc4_hdmi *vc4_hdmi, vc5_hdmi_set_csc_coeffs(vc4_hdmi, csc); break; - case VC4_HDMI_OUTPUT_RGB: + case HDMI_COLORSPACE_RGB: if_xbar = 0x354021; vc5_hdmi_set_csc_coeffs(vc4_hdmi, vc5_hdmi_csc_full_rgb_to_rgb[lim_range]); @@ -1472,7 +1196,7 @@ static void vc4_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi, struct drm_connector_state *state, const struct drm_display_mode *mode) { - struct drm_device *drm = vc4_hdmi->connector.dev; + struct drm_device *drm = vc4_hdmi->connector.base.dev; bool hsync_pos = mode->flags & DRM_MODE_FLAG_PHSYNC; bool vsync_pos = mode->flags & DRM_MODE_FLAG_PVSYNC; bool interlaced = mode->flags & DRM_MODE_FLAG_INTERLACE; @@ -1536,9 +1260,9 @@ static void vc5_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi, struct drm_connector_state *state, const struct drm_display_mode *mode) { - struct drm_device *drm = vc4_hdmi->connector.dev; - const struct vc4_hdmi_connector_state *vc4_state = - conn_state_to_vc4_hdmi_conn_state(state); + struct drm_device *drm = vc4_hdmi->connector.base.dev; + const struct drm_hdmi_connector_state *hdmi_state = + connector_state_to_hdmi_connector_state(state); bool hsync_pos = mode->flags & DRM_MODE_FLAG_PHSYNC; bool vsync_pos = mode->flags & DRM_MODE_FLAG_PVSYNC; bool interlaced = mode->flags & DRM_MODE_FLAG_INTERLACE; @@ -1590,7 +1314,7 @@ static void vc5_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi, HDMI_WRITE(HDMI_VERTB0, vertb_even); HDMI_WRITE(HDMI_VERTB1, vertb); - switch (vc4_state->output_bpc) { + switch (hdmi_state->output_bpc) { case 12: gcp = 6; break; @@ -1607,7 +1331,7 @@ static void vc5_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi, * YCC422 is always 36-bit and not considered deep colour so * doesn't signal in GCP. */ - if (vc4_state->output_format == VC4_HDMI_OUTPUT_YUV422) { + if (hdmi_state->output_format == HDMI_COLORSPACE_YUV422) { gcp = 0; } @@ -1643,7 +1367,7 @@ static void vc5_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi, static void vc4_hdmi_recenter_fifo(struct vc4_hdmi *vc4_hdmi) { - struct drm_device *drm = vc4_hdmi->connector.dev; + struct drm_device *drm = vc4_hdmi->connector.base.dev; unsigned long flags; u32 drift; int ret; @@ -1687,14 +1411,14 @@ static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder, struct drm_atomic_state *state) { struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); - struct drm_device *drm = vc4_hdmi->connector.dev; - struct drm_connector *connector = &vc4_hdmi->connector; + struct drm_device *drm = vc4_hdmi->connector.base.dev; + struct drm_connector *connector = &vc4_hdmi->connector.base; struct drm_connector_state *conn_state = drm_atomic_get_new_connector_state(state, connector); - struct vc4_hdmi_connector_state *vc4_conn_state = - conn_state_to_vc4_hdmi_conn_state(conn_state); + struct drm_hdmi_connector_state *hdmi_conn_state = + connector_state_to_hdmi_connector_state(conn_state); const struct drm_display_mode *mode = &vc4_hdmi->saved_adjusted_mode; - unsigned long tmds_char_rate = vc4_conn_state->tmds_char_rate; + unsigned long tmds_char_rate = hdmi_conn_state->tmds_char_rate; unsigned long bvb_rate, hsm_rate; unsigned long flags; int ret; @@ -1771,7 +1495,7 @@ static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder, } if (vc4_hdmi->variant->phy_init) - vc4_hdmi->variant->phy_init(vc4_hdmi, vc4_conn_state); + vc4_hdmi->variant->phy_init(vc4_hdmi, hdmi_conn_state); spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); @@ -1806,8 +1530,8 @@ static void vc4_hdmi_encoder_pre_crtc_enable(struct drm_encoder *encoder, struct drm_atomic_state *state) { struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); - struct drm_device *drm = vc4_hdmi->connector.dev; - struct drm_connector *connector = &vc4_hdmi->connector; + struct drm_connector *connector = &vc4_hdmi->connector.base; + struct drm_device *drm = connector->dev; const struct drm_display_mode *mode = &vc4_hdmi->saved_adjusted_mode; struct drm_connector_state *conn_state = drm_atomic_get_new_connector_state(state, connector); @@ -1836,9 +1560,15 @@ static void vc4_hdmi_encoder_post_crtc_enable(struct drm_encoder *encoder, struct drm_atomic_state *state) { struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); - struct drm_device *drm = vc4_hdmi->connector.dev; + struct drm_hdmi_connector *hdmi_connector = &vc4_hdmi->connector; + struct drm_connector *connector = &hdmi_connector->base; + struct drm_connector_state *new_conn_state = + drm_atomic_get_new_connector_state(state, connector); + struct drm_hdmi_connector_state *new_hdmi_state = + connector_state_to_hdmi_connector_state(new_conn_state); + struct drm_device *drm = connector->dev; const struct drm_display_mode *mode = &vc4_hdmi->saved_adjusted_mode; - struct drm_display_info *display = &vc4_hdmi->connector.display_info; + struct drm_display_info *display = &connector->display_info; bool hsync_pos = mode->flags & DRM_MODE_FLAG_PHSYNC; bool vsync_pos = mode->flags & DRM_MODE_FLAG_PVSYNC; unsigned long flags; @@ -1901,10 +1631,11 @@ static void vc4_hdmi_encoder_post_crtc_enable(struct drm_encoder *encoder, spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); vc4_hdmi->packet_ram_enabled = true; - - vc4_hdmi_set_infoframes(encoder); } + drm_atomic_helper_hdmi_connector_update_infoframes(hdmi_connector, + new_hdmi_state); + vc4_hdmi_recenter_fifo(vc4_hdmi); vc4_hdmi_enable_scrambling(encoder); @@ -1919,109 +1650,25 @@ static void vc4_hdmi_encoder_atomic_mode_set(struct drm_encoder *encoder, struct drm_connector_state *conn_state) { struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); - struct vc4_hdmi_connector_state *vc4_state = - conn_state_to_vc4_hdmi_conn_state(conn_state); + const struct drm_hdmi_connector_state *hdmi_state = + connector_state_to_hdmi_connector_state(conn_state); mutex_lock(&vc4_hdmi->mutex); drm_mode_copy(&vc4_hdmi->saved_adjusted_mode, &crtc_state->adjusted_mode); - vc4_hdmi->output_bpc = vc4_state->output_bpc; - vc4_hdmi->output_format = vc4_state->output_format; + vc4_hdmi->output_bpc = hdmi_state->output_bpc; + vc4_hdmi->output_format = hdmi_state->output_format; mutex_unlock(&vc4_hdmi->mutex); } -static bool -vc4_hdmi_sink_supports_format_bpc(const struct vc4_hdmi *vc4_hdmi, - const struct drm_display_info *info, - const struct drm_display_mode *mode, - unsigned int format, unsigned int bpc) -{ - struct drm_device *dev = vc4_hdmi->connector.dev; - u8 vic = drm_match_cea_mode(mode); - - if (vic == 1 && bpc != 8) { - drm_dbg(dev, "VIC1 requires a bpc of 8, got %u\n", bpc); - return false; - } - - if (!info->is_hdmi && - (format != VC4_HDMI_OUTPUT_RGB || bpc != 8)) { - drm_dbg(dev, "DVI Monitors require an RGB output at 8 bpc\n"); - return false; - } - - switch (format) { - case VC4_HDMI_OUTPUT_RGB: - drm_dbg(dev, "RGB Format, checking the constraints.\n"); - - if (!(info->color_formats & DRM_COLOR_FORMAT_RGB444)) - return false; - - if (bpc == 10 && !(info->edid_hdmi_rgb444_dc_modes & DRM_EDID_HDMI_DC_30)) { - drm_dbg(dev, "10 BPC but sink doesn't support Deep Color 30.\n"); - return false; - } - - if (bpc == 12 && !(info->edid_hdmi_rgb444_dc_modes & DRM_EDID_HDMI_DC_36)) { - drm_dbg(dev, "12 BPC but sink doesn't support Deep Color 36.\n"); - return false; - } - - drm_dbg(dev, "RGB format supported in that configuration.\n"); - - return true; - - case VC4_HDMI_OUTPUT_YUV422: - drm_dbg(dev, "YUV422 format, checking the constraints.\n"); - - if (!(info->color_formats & DRM_COLOR_FORMAT_YCBCR422)) { - drm_dbg(dev, "Sink doesn't support YUV422.\n"); - return false; - } - - if (bpc != 12) { - drm_dbg(dev, "YUV422 only supports 12 bpc.\n"); - return false; - } - - drm_dbg(dev, "YUV422 format supported in that configuration.\n"); - - return true; - - case VC4_HDMI_OUTPUT_YUV444: - drm_dbg(dev, "YUV444 format, checking the constraints.\n"); - - if (!(info->color_formats & DRM_COLOR_FORMAT_YCBCR444)) { - drm_dbg(dev, "Sink doesn't support YUV444.\n"); - return false; - } - - if (bpc == 10 && !(info->edid_hdmi_ycbcr444_dc_modes & DRM_EDID_HDMI_DC_30)) { - drm_dbg(dev, "10 BPC but sink doesn't support Deep Color 30.\n"); - return false; - } - - if (bpc == 12 && !(info->edid_hdmi_ycbcr444_dc_modes & DRM_EDID_HDMI_DC_36)) { - drm_dbg(dev, "12 BPC but sink doesn't support Deep Color 36.\n"); - return false; - } - - drm_dbg(dev, "YUV444 format supported in that configuration.\n"); - - return true; - } - - return false; -} - static enum drm_mode_status -vc4_hdmi_encoder_clock_valid(const struct vc4_hdmi *vc4_hdmi, - const struct drm_display_mode *mode, - unsigned long long clock) +vc4_hdmi_connector_clock_valid(const struct drm_hdmi_connector *hdmi_connector, + const struct drm_display_mode *mode, + unsigned long long clock) { - const struct drm_connector *connector = &vc4_hdmi->connector; - const struct drm_display_info *info = &connector->display_info; - struct vc4_dev *vc4 = to_vc4_dev(connector->dev); + const struct drm_connector *connector = &hdmi_connector->base; + const struct vc4_hdmi *vc4_hdmi = connector_to_vc4_hdmi(connector); + const struct vc4_dev *vc4 = to_vc4_dev(connector->dev); if (clock > vc4_hdmi->variant->max_pixel_clock) return MODE_CLOCK_HIGH; @@ -2035,125 +1682,13 @@ vc4_hdmi_encoder_clock_valid(const struct vc4_hdmi *vc4_hdmi, drm_mode_vrefresh(mode) >= 50) return MODE_CLOCK_HIGH; - if (info->max_tmds_clock && clock > (info->max_tmds_clock * 1000)) - return MODE_CLOCK_HIGH; - return MODE_OK; } -static unsigned long long -vc4_hdmi_encoder_compute_mode_clock(const struct drm_display_mode *mode, - unsigned int bpc, - enum vc4_hdmi_output_format fmt) -{ - unsigned long long clock = mode->clock * 1000ULL; - - if (mode->flags & DRM_MODE_FLAG_DBLCLK) - clock = clock * 2; - - if (fmt == VC4_HDMI_OUTPUT_YUV422) - bpc = 8; - - clock = clock * bpc; - do_div(clock, 8); - - return clock; -} - -static int -vc4_hdmi_encoder_compute_clock(const struct vc4_hdmi *vc4_hdmi, - struct vc4_hdmi_connector_state *vc4_state, - const struct drm_display_mode *mode, - unsigned int bpc, unsigned int fmt) -{ - unsigned long long clock; - - clock = vc4_hdmi_encoder_compute_mode_clock(mode, bpc, fmt); - if (vc4_hdmi_encoder_clock_valid(vc4_hdmi, mode, clock) != MODE_OK) - return -EINVAL; - - vc4_state->tmds_char_rate = clock; - - return 0; -} - -static int -vc4_hdmi_encoder_compute_format(const struct vc4_hdmi *vc4_hdmi, - struct vc4_hdmi_connector_state *vc4_state, - const struct drm_display_mode *mode, - unsigned int bpc) -{ - struct drm_device *dev = vc4_hdmi->connector.dev; - const struct drm_connector *connector = &vc4_hdmi->connector; - const struct drm_display_info *info = &connector->display_info; - unsigned int format; - - drm_dbg(dev, "Trying with an RGB output\n"); - - format = VC4_HDMI_OUTPUT_RGB; - if (vc4_hdmi_sink_supports_format_bpc(vc4_hdmi, info, mode, format, bpc)) { - int ret; - - ret = vc4_hdmi_encoder_compute_clock(vc4_hdmi, vc4_state, - mode, bpc, format); - if (!ret) { - vc4_state->output_format = format; - return 0; - } - } - - drm_dbg(dev, "Failed, Trying with an YUV422 output\n"); - - format = VC4_HDMI_OUTPUT_YUV422; - if (vc4_hdmi_sink_supports_format_bpc(vc4_hdmi, info, mode, format, bpc)) { - int ret; - - ret = vc4_hdmi_encoder_compute_clock(vc4_hdmi, vc4_state, - mode, bpc, format); - if (!ret) { - vc4_state->output_format = format; - return 0; - } - } - - drm_dbg(dev, "Failed. No Format Supported for that bpc count.\n"); - - return -EINVAL; -} - -static int -vc4_hdmi_encoder_compute_config(const struct vc4_hdmi *vc4_hdmi, - struct vc4_hdmi_connector_state *vc4_state, - const struct drm_display_mode *mode) -{ - struct drm_device *dev = vc4_hdmi->connector.dev; - struct drm_connector_state *conn_state = &vc4_state->base; - unsigned int max_bpc = clamp_t(unsigned int, conn_state->max_bpc, 8, 12); - unsigned int bpc; - int ret; - - for (bpc = max_bpc; bpc >= 8; bpc -= 2) { - drm_dbg(dev, "Trying with a %d bpc output\n", bpc); - - ret = vc4_hdmi_encoder_compute_format(vc4_hdmi, vc4_state, - mode, bpc); - if (ret) - continue; - - vc4_state->output_bpc = bpc; - - drm_dbg(dev, - "Mode %ux%u @ %uHz: Found configuration: bpc: %u, fmt: %s, clock: %llu\n", - mode->hdisplay, mode->vdisplay, drm_mode_vrefresh(mode), - vc4_state->output_bpc, - vc4_hdmi_output_fmt_str(vc4_state->output_format), - vc4_state->tmds_char_rate); - - break; - } - - return ret; -} +static const struct drm_hdmi_connector_funcs vc4_hdmi_hdmi_connector_funcs = { + .tmds_char_rate_valid = vc4_hdmi_connector_clock_valid, + .write_infoframe = vc4_hdmi_write_infoframe, +}; #define WIFI_2_4GHz_CH1_MIN_FREQ 2400000000ULL #define WIFI_2_4GHz_CH1_MAX_FREQ 2422000000ULL @@ -2163,16 +1698,9 @@ static int vc4_hdmi_encoder_atomic_check(struct drm_encoder *encoder, struct drm_connector_state *conn_state) { struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); - struct drm_connector *connector = &vc4_hdmi->connector; - struct drm_connector_state *old_conn_state = - drm_atomic_get_old_connector_state(conn_state->state, connector); - struct vc4_hdmi_connector_state *old_vc4_state = - conn_state_to_vc4_hdmi_conn_state(old_conn_state); - struct vc4_hdmi_connector_state *vc4_state = conn_state_to_vc4_hdmi_conn_state(conn_state); struct drm_display_mode *mode = &crtc_state->adjusted_mode; unsigned long long tmds_char_rate = mode->clock * 1000; unsigned long long tmds_bit_rate; - int ret; if (vc4_hdmi->variant->unsupported_odd_h_timings) { if (mode->flags & DRM_MODE_FLAG_DBLCLK) { @@ -2208,15 +1736,6 @@ static int vc4_hdmi_encoder_atomic_check(struct drm_encoder *encoder, tmds_char_rate = mode->clock * 1000; } - ret = vc4_hdmi_encoder_compute_config(vc4_hdmi, vc4_state, mode); - if (ret) - return ret; - - /* vc4_hdmi_encoder_compute_config may have changed output_bpc and/or output_format */ - if (vc4_state->output_bpc != old_vc4_state->output_bpc || - vc4_state->output_format != old_vc4_state->output_format) - crtc_state->mode_changed = true; - return 0; } @@ -2225,6 +1744,7 @@ vc4_hdmi_encoder_mode_valid(struct drm_encoder *encoder, const struct drm_display_mode *mode) { struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); + struct drm_hdmi_connector *hdmi_connector = &vc4_hdmi->connector; if (vc4_hdmi->variant->unsupported_odd_h_timings && !(mode->flags & DRM_MODE_FLAG_DBLCLK) && @@ -2232,7 +1752,7 @@ vc4_hdmi_encoder_mode_valid(struct drm_encoder *encoder, (mode->hsync_end % 2) || (mode->htotal % 2))) return MODE_H_ILLEGAL; - return vc4_hdmi_encoder_clock_valid(vc4_hdmi, mode, mode->clock * 1000); + return vc4_hdmi_connector_clock_valid(hdmi_connector, mode, mode->clock * 1000); } static const struct drm_encoder_helper_funcs vc4_hdmi_encoder_helper_funcs = { @@ -2283,7 +1803,7 @@ static u32 vc5_hdmi_channel_map(struct vc4_hdmi *vc4_hdmi, u32 channel_mask) static bool vc5_hdmi_hp_detect(struct vc4_hdmi *vc4_hdmi) { - struct drm_device *drm = vc4_hdmi->connector.dev; + struct drm_device *drm = vc4_hdmi->connector.base.dev; unsigned long flags; u32 hotplug; int idx; @@ -2304,7 +1824,7 @@ static bool vc5_hdmi_hp_detect(struct vc4_hdmi *vc4_hdmi) static void vc4_hdmi_audio_set_mai_clock(struct vc4_hdmi *vc4_hdmi, unsigned int samplerate) { - struct drm_device *drm = vc4_hdmi->connector.dev; + struct drm_device *drm = vc4_hdmi->connector.base.dev; u32 hsm_clock; unsigned long flags; unsigned long n, m; @@ -2366,7 +1886,8 @@ static inline struct vc4_hdmi *dai_to_hdmi(struct snd_soc_dai *dai) static bool vc4_hdmi_audio_can_stream(struct vc4_hdmi *vc4_hdmi) { - struct drm_display_info *display = &vc4_hdmi->connector.display_info; + struct drm_connector *connector = &vc4_hdmi->connector.base; + struct drm_display_info *display = &connector->display_info; lockdep_assert_held(&vc4_hdmi->mutex); @@ -2383,7 +1904,7 @@ static bool vc4_hdmi_audio_can_stream(struct vc4_hdmi *vc4_hdmi) static int vc4_hdmi_audio_startup(struct device *dev, void *data) { struct vc4_hdmi *vc4_hdmi = dev_get_drvdata(dev); - struct drm_device *drm = vc4_hdmi->connector.dev; + struct drm_device *drm = vc4_hdmi->connector.base.dev; unsigned long flags; int ret = 0; int idx; @@ -2424,7 +1945,6 @@ static int vc4_hdmi_audio_startup(struct device *dev, void *data) static void vc4_hdmi_audio_reset(struct vc4_hdmi *vc4_hdmi) { - struct drm_encoder *encoder = &vc4_hdmi->encoder.base; struct device *dev = &vc4_hdmi->pdev->dev; unsigned long flags; int ret; @@ -2432,7 +1952,7 @@ static void vc4_hdmi_audio_reset(struct vc4_hdmi *vc4_hdmi) lockdep_assert_held(&vc4_hdmi->mutex); vc4_hdmi->audio.streaming = false; - ret = vc4_hdmi_stop_packet(encoder, HDMI_INFOFRAME_TYPE_AUDIO, false); + ret = vc4_hdmi_stop_packet(vc4_hdmi, HDMI_INFOFRAME_TYPE_AUDIO, false); if (ret) dev_err(dev, "Failed to stop audio infoframe: %d\n", ret); @@ -2448,7 +1968,7 @@ static void vc4_hdmi_audio_reset(struct vc4_hdmi *vc4_hdmi) static void vc4_hdmi_audio_shutdown(struct device *dev, void *data) { struct vc4_hdmi *vc4_hdmi = dev_get_drvdata(dev); - struct drm_device *drm = vc4_hdmi->connector.dev; + struct drm_device *drm = vc4_hdmi->connector.base.dev; unsigned long flags; int idx; @@ -2522,8 +2042,8 @@ static int vc4_hdmi_audio_prepare(struct device *dev, void *data, struct hdmi_codec_params *params) { struct vc4_hdmi *vc4_hdmi = dev_get_drvdata(dev); - struct drm_device *drm = vc4_hdmi->connector.dev; - struct drm_encoder *encoder = &vc4_hdmi->encoder.base; + struct drm_hdmi_connector *hdmi_connector = &vc4_hdmi->connector; + struct drm_device *drm = hdmi_connector->base.dev; unsigned int sample_rate = params->sample_rate; unsigned int channels = params->channels; unsigned long flags; @@ -2600,8 +2120,10 @@ static int vc4_hdmi_audio_prepare(struct device *dev, void *data, spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); - memcpy(&vc4_hdmi->audio.infoframe, ¶ms->cea, sizeof(params->cea)); - vc4_hdmi_set_audio_infoframe(encoder); + ret = drm_atomic_helper_hdmi_connector_update_audio_infoframe(hdmi_connector, + ¶ms->cea); + if (ret) + goto out_dev_exit; out_dev_exit: drm_dev_exit(idx); @@ -2649,7 +2171,7 @@ static int vc4_hdmi_audio_get_eld(struct device *dev, void *data, uint8_t *buf, size_t len) { struct vc4_hdmi *vc4_hdmi = dev_get_drvdata(dev); - struct drm_connector *connector = &vc4_hdmi->connector; + struct drm_connector *connector = &vc4_hdmi->connector.base; mutex_lock(&vc4_hdmi->mutex); memcpy(buf, connector->eld, min(sizeof(connector->eld), len)); @@ -2832,7 +2354,7 @@ static int vc4_hdmi_audio_init(struct vc4_hdmi *vc4_hdmi) static irqreturn_t vc4_hdmi_hpd_irq_thread(int irq, void *priv) { struct vc4_hdmi *vc4_hdmi = priv; - struct drm_connector *connector = &vc4_hdmi->connector; + struct drm_connector *connector = &vc4_hdmi->connector.base; struct drm_device *dev = connector->dev; if (dev && dev->registered) @@ -2843,7 +2365,7 @@ static irqreturn_t vc4_hdmi_hpd_irq_thread(int irq, void *priv) static int vc4_hdmi_hotplug_init(struct vc4_hdmi *vc4_hdmi) { - struct drm_connector *connector = &vc4_hdmi->connector; + struct drm_connector *connector = &vc4_hdmi->connector.base; struct platform_device *pdev = vc4_hdmi->pdev; int ret; @@ -2916,7 +2438,7 @@ static irqreturn_t vc4_cec_irq_handler_thread(int irq, void *priv) static void vc4_cec_read_msg(struct vc4_hdmi *vc4_hdmi, u32 cntrl1) { - struct drm_device *dev = vc4_hdmi->connector.dev; + struct drm_device *dev = vc4_hdmi->connector.base.dev; struct cec_msg *msg = &vc4_hdmi->cec_rx_msg; unsigned int i; @@ -3056,7 +2578,7 @@ static irqreturn_t vc4_cec_irq_handler(int irq, void *priv) static int vc4_hdmi_cec_enable(struct cec_adapter *adap) { struct vc4_hdmi *vc4_hdmi = cec_get_drvdata(adap); - struct drm_device *drm = vc4_hdmi->connector.dev; + struct drm_device *drm = vc4_hdmi->connector.base.dev; /* clock period in microseconds */ const u32 usecs = 1000000 / CEC_CLOCK_FREQ; unsigned long flags; @@ -3123,7 +2645,7 @@ static int vc4_hdmi_cec_enable(struct cec_adapter *adap) static int vc4_hdmi_cec_disable(struct cec_adapter *adap) { struct vc4_hdmi *vc4_hdmi = cec_get_drvdata(adap); - struct drm_device *drm = vc4_hdmi->connector.dev; + struct drm_device *drm = vc4_hdmi->connector.base.dev; unsigned long flags; int idx; @@ -3167,7 +2689,7 @@ static int vc4_hdmi_cec_adap_enable(struct cec_adapter *adap, bool enable) static int vc4_hdmi_cec_adap_log_addr(struct cec_adapter *adap, u8 log_addr) { struct vc4_hdmi *vc4_hdmi = cec_get_drvdata(adap); - struct drm_device *drm = vc4_hdmi->connector.dev; + struct drm_device *drm = vc4_hdmi->connector.base.dev; unsigned long flags; int idx; @@ -3196,7 +2718,7 @@ static int vc4_hdmi_cec_adap_transmit(struct cec_adapter *adap, u8 attempts, u32 signal_free_time, struct cec_msg *msg) { struct vc4_hdmi *vc4_hdmi = cec_get_drvdata(adap); - struct drm_device *dev = vc4_hdmi->connector.dev; + struct drm_device *dev = vc4_hdmi->connector.base.dev; unsigned long flags; u32 val; unsigned int i; @@ -3273,7 +2795,7 @@ static int vc4_hdmi_cec_init(struct vc4_hdmi *vc4_hdmi) if (ret < 0) return ret; - cec_fill_conn_info_from_drm(&conn_info, &vc4_hdmi->connector); + cec_fill_conn_info_from_drm(&conn_info, &vc4_hdmi->connector.base); cec_s_conn_info(vc4_hdmi->cec_adap, &conn_info); if (vc4_hdmi->variant->external_irq_controller) { diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h index 934d5d61485a..1e2752798bbb 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.h +++ b/drivers/gpu/drm/vc4/vc4_hdmi.h @@ -76,7 +76,7 @@ struct vc4_hdmi_variant { /* Callback to initialize the PHY according to the connector state */ void (*phy_init)(struct vc4_hdmi *vc4_hdmi, - struct vc4_hdmi_connector_state *vc4_conn_state); + struct drm_hdmi_connector_state *vc4_conn_state); /* Callback to disable the PHY */ void (*phy_disable)(struct vc4_hdmi *vc4_hdmi); @@ -117,12 +117,6 @@ enum vc4_hdmi_output_format { VC4_HDMI_OUTPUT_YUV420, }; -enum vc4_hdmi_broadcast_rgb { - VC4_HDMI_BROADCAST_RGB_AUTO, - VC4_HDMI_BROADCAST_RGB_FULL, - VC4_HDMI_BROADCAST_RGB_LIMITED, -}; - /* General HDMI hardware state. */ struct vc4_hdmi { struct vc4_hdmi_audio audio; @@ -131,12 +125,10 @@ struct vc4_hdmi { const struct vc4_hdmi_variant *variant; struct vc4_encoder encoder; - struct drm_connector connector; + struct drm_hdmi_connector connector; struct delayed_work scrambling_work; - struct drm_property *broadcast_rgb_property; - struct i2c_adapter *ddc; void __iomem *hdmicore_regs; void __iomem *hd_regs; @@ -218,8 +210,8 @@ struct vc4_hdmi { bool scdc_enabled; /** - * @output_bpc: Copy of @vc4_connector_state.output_bpc for use - * outside of KMS hooks. Protected by @mutex. + * @output_bpc: Copy of @drm_hdmi_connector_state.output_bpc for + * use outside of KMS hooks. Protected by @mutex. */ unsigned int output_bpc; @@ -230,9 +222,13 @@ struct vc4_hdmi { enum vc4_hdmi_output_format output_format; }; -#define connector_to_vc4_hdmi(_connector) \ +#define hdmi_connector_to_vc4_hdmi(_connector) \ container_of_const(_connector, struct vc4_hdmi, connector) +#define connector_to_vc4_hdmi(_connector) \ + container_of_const(_connector, struct vc4_hdmi, connector.base) + + static inline struct vc4_hdmi * encoder_to_vc4_hdmi(struct drm_encoder *encoder) { @@ -240,25 +236,14 @@ encoder_to_vc4_hdmi(struct drm_encoder *encoder) return container_of_const(_encoder, struct vc4_hdmi, encoder); } -struct vc4_hdmi_connector_state { - struct drm_connector_state base; - unsigned long long tmds_char_rate; - unsigned int output_bpc; - enum vc4_hdmi_output_format output_format; - enum vc4_hdmi_broadcast_rgb broadcast_rgb; -}; - -#define conn_state_to_vc4_hdmi_conn_state(_state) \ - container_of_const(_state, struct vc4_hdmi_connector_state, base) - void vc4_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi, - struct vc4_hdmi_connector_state *vc4_conn_state); + struct drm_hdmi_connector_state *conn_state); void vc4_hdmi_phy_disable(struct vc4_hdmi *vc4_hdmi); void vc4_hdmi_phy_rng_enable(struct vc4_hdmi *vc4_hdmi); void vc4_hdmi_phy_rng_disable(struct vc4_hdmi *vc4_hdmi); void vc5_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi, - struct vc4_hdmi_connector_state *vc4_conn_state); + struct drm_hdmi_connector_state *conn_state); void vc5_hdmi_phy_disable(struct vc4_hdmi *vc4_hdmi); void vc5_hdmi_phy_rng_enable(struct vc4_hdmi *vc4_hdmi); void vc5_hdmi_phy_rng_disable(struct vc4_hdmi *vc4_hdmi); diff --git a/drivers/gpu/drm/vc4/vc4_hdmi_phy.c b/drivers/gpu/drm/vc4/vc4_hdmi_phy.c index ec24999bf96d..54deb30306df 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi_phy.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi_phy.c @@ -128,7 +128,7 @@ #define OSCILLATOR_FREQUENCY 54000000 void vc4_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi, - struct vc4_hdmi_connector_state *conn_state) + struct drm_hdmi_connector_state *conn_state) { unsigned long flags; @@ -361,7 +361,7 @@ static void vc5_hdmi_reset_phy(struct vc4_hdmi *vc4_hdmi) } void vc5_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi, - struct vc4_hdmi_connector_state *conn_state) + struct drm_hdmi_connector_state *conn_state) { const struct phy_lane_settings *chan0_settings, *chan1_settings, *chan2_settings, *clock_settings; const struct vc4_hdmi_variant *variant = vc4_hdmi->variant;