From patchwork Thu Aug 8 15:11:33 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Boris Brezillon X-Patchwork-Id: 11084369 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id E52A014E5 for ; Thu, 8 Aug 2019 15:12:17 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id D4FDC28B58 for ; Thu, 8 Aug 2019 15:12:17 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id C9B8A28B62; Thu, 8 Aug 2019 15:12:17 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-5.2 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id BE8F228B59 for ; Thu, 8 Aug 2019 15:12:12 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 73CA86E867; Thu, 8 Aug 2019 15:12:07 +0000 (UTC) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from bhuna.collabora.co.uk (bhuna.collabora.co.uk [IPv6:2a00:1098:0:82:1000:25:2eeb:e3e3]) by gabe.freedesktop.org (Postfix) with ESMTPS id 8F1DD6E85C for ; Thu, 8 Aug 2019 15:11:58 +0000 (UTC) Received: from localhost.localdomain (unknown [IPv6:2a01:e0a:2c:6930:5cf4:84a1:2763:fe0d]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) (Authenticated sender: bbrezillon) by bhuna.collabora.co.uk (Postfix) with ESMTPSA id A20CB28C524; Thu, 8 Aug 2019 16:11:56 +0100 (BST) From: Boris Brezillon To: dri-devel@lists.freedesktop.org Subject: [PATCH RFC 02/19] drm: Support custom encoder/bridge enable/disable sequences officially Date: Thu, 8 Aug 2019 17:11:33 +0200 Message-Id: <20190808151150.16336-3-boris.brezillon@collabora.com> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20190808151150.16336-1-boris.brezillon@collabora.com> References: <20190808151150.16336-1-boris.brezillon@collabora.com> MIME-Version: 1.0 X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Jernej Skrabec , Laurent Pinchart , Neil Armstrong , Jonas Karlman , Seung-Woo Kim , Kyungmin Park , Thierry Reding , Chris Healy , Boris Brezillon , kernel@collabora.com, Sam Ravnborg Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" X-Virus-Scanned: ClamAV using ClamSMTP The VC4 and Exynos DSI encoder drivers need a custom enable/disable sequence and manually set encoder->bridge to NULL to prevent the core from calling the bridge hooks. Let's provide a more official way to support custom bridge/encoder enable/disable sequences. Signed-off-by: Boris Brezillon --- drivers/gpu/drm/drm_atomic_helper.c | 13 +++++++--- drivers/gpu/drm/drm_crtc_helper.c | 38 ++++++++++++++++++----------- include/drm/drm_encoder.h | 9 +++++++ 3 files changed, 42 insertions(+), 18 deletions(-) diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 4706439fb490..15ea61877122 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -1030,7 +1030,8 @@ disable_outputs(struct drm_device *dev, struct drm_atomic_state *old_state) * Each encoder has at most one connector (since we always steal * it away), so we won't call disable hooks twice. */ - drm_atomic_bridge_disable(encoder->bridge, old_state); + if (!encoder->custom_bridge_enable_disable_seq) + drm_atomic_bridge_disable(encoder->bridge, old_state); /* Right function depends upon target state. */ if (funcs) { @@ -1044,7 +1045,9 @@ disable_outputs(struct drm_device *dev, struct drm_atomic_state *old_state) funcs->dpms(encoder, DRM_MODE_DPMS_OFF); } - drm_atomic_bridge_post_disable(encoder->bridge, old_state); + if (!encoder->custom_bridge_enable_disable_seq) + drm_atomic_bridge_post_disable(encoder->bridge, + old_state); } for_each_oldnew_crtc_in_state(old_state, crtc, old_crtc_state, new_crtc_state, i) { @@ -1342,7 +1345,8 @@ void drm_atomic_helper_commit_modeset_enables(struct drm_device *dev, * Each encoder has at most one connector (since we always steal * it away), so we won't call enable hooks twice. */ - drm_atomic_bridge_pre_enable(encoder->bridge, old_state); + if (!encoder->custom_bridge_enable_disable_seq) + drm_atomic_bridge_pre_enable(encoder->bridge, old_state); if (funcs) { if (funcs->atomic_enable) @@ -1353,7 +1357,8 @@ void drm_atomic_helper_commit_modeset_enables(struct drm_device *dev, funcs->commit(encoder); } - drm_atomic_bridge_enable(encoder->bridge, old_state); + if (!encoder->custom_bridge_enable_disable_seq) + drm_atomic_bridge_enable(encoder->bridge, old_state); } drm_atomic_helper_commit_writebacks(dev, old_state); diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c index fa3694836c22..87dae37fec12 100644 --- a/drivers/gpu/drm/drm_crtc_helper.c +++ b/drivers/gpu/drm/drm_crtc_helper.c @@ -160,14 +160,16 @@ drm_encoder_disable(struct drm_encoder *encoder) if (!encoder_funcs) return; - drm_bridge_disable(encoder->bridge); + if (!encoder->custom_bridge_enable_disable_seq) + drm_bridge_disable(encoder->bridge); if (encoder_funcs->disable) (*encoder_funcs->disable)(encoder); else if (encoder_funcs->dpms) (*encoder_funcs->dpms)(encoder, DRM_MODE_DPMS_OFF); - drm_bridge_post_disable(encoder->bridge); + if (!encoder->custom_bridge_enable_disable_seq) + drm_bridge_post_disable(encoder->bridge); } static void __drm_helper_disable_unused_functions(struct drm_device *dev) @@ -365,13 +367,15 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc, if (!encoder_funcs) continue; - drm_bridge_disable(encoder->bridge); + if (!encoder->custom_bridge_enable_disable_seq) + drm_bridge_disable(encoder->bridge); /* Disable the encoders as the first thing we do. */ if (encoder_funcs->prepare) encoder_funcs->prepare(encoder); - drm_bridge_post_disable(encoder->bridge); + if (!encoder->custom_bridge_enable_disable_seq) + drm_bridge_post_disable(encoder->bridge); } drm_crtc_prepare_encoders(dev); @@ -414,12 +418,14 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc, if (!encoder_funcs) continue; - drm_bridge_pre_enable(encoder->bridge); + if (!encoder->custom_bridge_enable_disable_seq) + drm_bridge_pre_enable(encoder->bridge); if (encoder_funcs->commit) encoder_funcs->commit(encoder); - drm_bridge_enable(encoder->bridge); + if (!encoder->custom_bridge_enable_disable_seq) + drm_bridge_enable(encoder->bridge); } /* Calculate and store various constants which @@ -825,18 +831,22 @@ static void drm_helper_encoder_dpms(struct drm_encoder *encoder, int mode) if (!encoder_funcs) return; - if (mode == DRM_MODE_DPMS_ON) - drm_bridge_pre_enable(bridge); - else - drm_bridge_disable(bridge); + if (!encoder->custom_bridge_enable_disable_seq) { + if (mode == DRM_MODE_DPMS_ON) + drm_bridge_pre_enable(bridge); + else + drm_bridge_disable(bridge); + } if (encoder_funcs->dpms) encoder_funcs->dpms(encoder, mode); - if (mode == DRM_MODE_DPMS_ON) - drm_bridge_enable(bridge); - else - drm_bridge_post_disable(bridge); + if (!encoder->custom_bridge_enable_disable_seq) { + if (mode == DRM_MODE_DPMS_ON) + drm_bridge_enable(bridge); + else + drm_bridge_post_disable(bridge); + } } static int drm_helper_choose_crtc_dpms(struct drm_crtc *crtc) diff --git a/include/drm/drm_encoder.h b/include/drm/drm_encoder.h index 70cfca03d812..d986ff1197ce 100644 --- a/include/drm/drm_encoder.h +++ b/include/drm/drm_encoder.h @@ -175,6 +175,15 @@ struct drm_encoder { struct drm_bridge *bridge; const struct drm_encoder_funcs *funcs; const struct drm_encoder_helper_funcs *helper_private; + + /** + * @custom_bridge_enable_disable_seq: Set to true if the encoder needs + * a custom bridge/encoder enable/disable sequence. In that case the + * driver is responsible for calling the + * drm[_atomic]_bridge_{pre_enable,enable,disable,post_disable}() + * functions as part of its encoder enable/disable handling. + */ + uint32_t custom_bridge_enable_disable_seq : 1; }; #define obj_to_encoder(x) container_of(x, struct drm_encoder, base)