From patchwork Tue Oct 31 16:48: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: 96533 Received: from vger.kernel.org ([23.128.96.18]) by www.linuxtv.org with esmtp (Exim 4.92) (envelope-from ) id 1qxrvY-00CngH-7F; Tue, 31 Oct 2023 16:49:16 +0000 Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1346684AbjJaQtQ (ORCPT + 1 other); Tue, 31 Oct 2023 12:49:16 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:44624 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1346780AbjJaQtD (ORCPT ); Tue, 31 Oct 2023 12:49:03 -0400 Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 1A0839F; Tue, 31 Oct 2023 09:49:01 -0700 (PDT) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 6423FC433C7; Tue, 31 Oct 2023 16:49:00 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1698770940; bh=iDaUgbnIqeP+1FMLYDm44gKRVkWJLdisydNiZ0kJ3HQ=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=OXgk2ab2AjPbHH5Dn2Wi+euvAX7dev6EHwTbbOvKML2OD+YGvKf7y+puh2AcXg6m3 Or+4NF1NL8iHqeoSPnEwiZUTcuApaL1YW+Qmy101oeF8gEXHhHMo1Af45gf9R3dydb Ip0IpbWUuaqU0wHt+m1zeuo3/RlZZNSUF9XMtCONzgWfmLtPn03B+fmPaXahXB3wjZ iGvOO4pCIyrjywkcPlfZ8Bp/1FIYGW824ZdgnYoKd9MrTvzO43ZaaUojT9xC4F9GkT 30eeXxKnVLwUy8O681Fcmjh2SSPd0lAu5tilGV7nUAIM240TjNDyB3D0ksLoypKxZk mKaH8hrD0cT6Q== From: Maxime Ripard Date: Tue, 31 Oct 2023 17:48:22 +0100 Subject: [PATCH RFC v3 09/37] drm/connector: hdmi: Add custom hook to filter TMDS character rate MIME-Version: 1.0 Message-Id: <20231031-kms-hdmi-connector-state-v3-9-328b0fae43a7@kernel.org> References: <20231031-kms-hdmi-connector-state-v3-0-328b0fae43a7@kernel.org> In-Reply-To: <20231031-kms-hdmi-connector-state-v3-0-328b0fae43a7@kernel.org> To: Maarten Lankhorst , Thomas Zimmermann , David Airlie , Daniel Vetter , Emma Anholt , Jonathan Corbet , Sandy Huang , =?utf-8?q?Heiko_St=C3=BCbner?= , Chen-Yu Tsai , Jernej Skrabec , Samuel Holland Cc: Hans Verkuil , dri-devel@lists.freedesktop.org, linux-arm-kernel@lists.infradead.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-media@vger.kernel.org, linux-rockchip@lists.infradead.org, linux-sunxi@lists.linux.dev, Maxime Ripard X-Mailer: b4 0.12.3 X-Developer-Signature: v=1; a=openpgp-sha256; l=4682; i=mripard@kernel.org; h=from:subject:message-id; bh=iDaUgbnIqeP+1FMLYDm44gKRVkWJLdisydNiZ0kJ3HQ=; b=owGbwMvMwCX2+D1vfrpE4FHG02pJDKmO+vdm6El8XZbTsHHj9Lt3p5g7bNHXEOpuf932asdMi 8CgGRVRHaUsDGJcDLJiiiwxwuZL4k7Net3JxjcPZg4rE8gQBi5OAZjIHTdGhlvT2m5ZOrVYSfgf XLSYeZ/QcZdz5ioFocu1Y65NcHsmepWRoffn75JfCa/nX3QL7f//ucJGZypL//LCiWqzzr+7/iT jID8A X-Developer-Key: i=mripard@kernel.org; a=openpgp; fpr=BE5675C37E818C8B5764241C254BCFC56BF6CE8D X-Spam-Status: No, score=-4.9 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_MED, SPF_HELO_NONE,SPF_PASS,T_SCC_BODY_TEXT_LINE 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-media@vger.kernel.org X-LSpam-Score: -5.4 (-----) X-LSpam-Report: No, score=-5.4 required=5.0 tests=BAYES_00=-1.9,DKIMWL_WL_HIGH=0.001,DKIM_SIGNED=0.1,DKIM_VALID=-0.1,DKIM_VALID_AU=-0.1,DKIM_VALID_EF=-0.1,MAILING_LIST_MULTI=-1,RCVD_IN_DNSWL_MED=-2.3 autolearn=ham autolearn_force=no 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_atomic_state_helper.c | 9 +++++++++ drivers/gpu/drm/drm_connector.c | 4 ++++ include/drm/drm_connector.h | 30 ++++++++++++++++++++++++++++++ 3 files changed, 43 insertions(+) diff --git a/drivers/gpu/drm/drm_atomic_state_helper.c b/drivers/gpu/drm/drm_atomic_state_helper.c index 480fa3445f40..0dd1dad99cce 100644 --- a/drivers/gpu/drm/drm_atomic_state_helper.c +++ b/drivers/gpu/drm/drm_atomic_state_helper.c @@ -675,11 +675,20 @@ hdmi_clock_valid(const struct drm_connector *connector, const struct drm_display_mode *mode, unsigned long long clock) { + const struct drm_connector_hdmi_funcs *funcs = connector->hdmi.funcs; 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) { + enum drm_mode_status status; + + status = funcs->tmds_char_rate_valid(connector, mode, clock); + if (status != MODE_OK) + return status; + } + return MODE_OK; } diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c index a96c9b54c554..6dd5a82df884 100644 --- a/drivers/gpu/drm/drm_connector.c +++ b/drivers/gpu/drm/drm_connector.c @@ -457,6 +457,7 @@ EXPORT_SYMBOL(drmm_connector_init); * @dev: DRM device * @connector: A pointer to the HDMI connector to init * @funcs: callbacks for this connector + * @hdmi_funcs: HDMI-related callbacks for this connector * @connector_type: user visible type of the connector * @ddc: optional pointer to the associated ddc adapter * @supported_formats: Bitmask of @hdmi_colorspace listing supported output formats @@ -476,6 +477,7 @@ EXPORT_SYMBOL(drmm_connector_init); int drmm_connector_hdmi_init(struct drm_device *dev, struct drm_connector *connector, const struct drm_connector_funcs *funcs, + const struct drm_connector_hdmi_funcs *hdmi_funcs, int connector_type, struct i2c_adapter *ddc, unsigned long supported_formats, @@ -509,6 +511,8 @@ int drmm_connector_hdmi_init(struct drm_device *dev, connector->max_bpc = max_bpc; } + connector->hdmi.funcs = hdmi_funcs; + return 0; } EXPORT_SYMBOL(drmm_connector_hdmi_init); diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h index 93613c57c6de..5005b4c196ac 100644 --- a/include/drm/drm_connector.h +++ b/include/drm/drm_connector.h @@ -1080,6 +1080,30 @@ struct drm_connector_state { } hdmi; }; +/** + * struct drm_connector_hdmi_funcs - drm_hdmi_connector control functions + */ +struct drm_connector_hdmi_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_connector *connector, + const struct drm_display_mode *mode, + unsigned long long tmds_rate); +}; + /** * struct drm_connector_funcs - control connectors on a given device * @@ -1950,6 +1974,11 @@ struct drm_connector { * supported by the controller. */ unsigned long supported_formats; + + /** + * @funcs: HDMI connector Control Functions + */ + const struct drm_connector_hdmi_funcs *funcs; } hdmi; }; @@ -1972,6 +2001,7 @@ int drmm_connector_init(struct drm_device *dev, int drmm_connector_hdmi_init(struct drm_device *dev, struct drm_connector *connector, const struct drm_connector_funcs *funcs, + const struct drm_connector_hdmi_funcs *hdmi_funcs, int connector_type, struct i2c_adapter *ddc, unsigned long supported_formats,