From nobody Mon Oct 13 23:13:25 2025 Received: from lelv0143.ext.ti.com (lelv0143.ext.ti.com [198.47.23.248]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7DF3415699D for ; Sat, 22 Jun 2024 11:10:12 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.47.23.248 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1719054614; cv=none; b=QaLKN8Reu99XynRj117qcPvy67s4NreuCKw8WPkdHoPlsw1DuyVRVCN61H710RRjw//UJlhUgC8G/MXKMMy98pyw+zYRKHNe6ehVZj+59UBG2dJF18fu34g4JrHc7+Rh0KWLJNCGm5GL5a6LO+ss7QdOLMruTHMUYLOJUiDPplw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1719054614; c=relaxed/simple; bh=BPiGT9+jkX3i7cQYnEXcuTTHvTMc0SMgkEVFVMe7Q5s=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=Ytssar0KLMMibmkTrpjbe9sZ7hx0vV88t5gp9yGDLQjiuI0JWr5guJJVcRudAEQe86u/VHF7WpJMEbVtuN9FE4ze+FzKaw6HbzIrfPgygHI4o2WrBTDe2gcrr3/OnSjiIsvLOn8siOnJ2jkdRCa9jDxqkKZEpHhGTqx+lrCYcmY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=ti.com; spf=pass smtp.mailfrom=ti.com; dkim=pass (1024-bit key) header.d=ti.com header.i=@ti.com header.b=RQsL7WaV; arc=none smtp.client-ip=198.47.23.248 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=ti.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=ti.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=ti.com header.i=@ti.com header.b="RQsL7WaV" Received: from fllv0035.itg.ti.com ([10.64.41.0]) by lelv0143.ext.ti.com (8.15.2/8.15.2) with ESMTP id 45MB9j5C033223; Sat, 22 Jun 2024 06:09:45 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ti.com; s=ti-com-17Q1; t=1719054585; bh=3Ak0cYY9/Ktqpij4a7CVob7W84NwWWlob/wDNvIKk/I=; h=From:To:CC:Subject:Date:In-Reply-To:References; b=RQsL7WaVtwPnTE3OB2S63y/wONsZlaGNKkhlMsFRCQR6by3ZlY2Bxv2q6+XHP3ngB TAQY+/87XDP5VR4ofNgIzJW5Fg2LABi9wm/AoKjM2cOb9P1S/8MFgJejQYGDX+hzVM JWoXNs6wEWHabgGPRCJlHS7p+j0eNwnovgFABfpM= Received: from DLEE115.ent.ti.com (dlee115.ent.ti.com [157.170.170.26]) by fllv0035.itg.ti.com (8.15.2/8.15.2) with ESMTPS id 45MB9jSf112668 (version=TLSv1.2 cipher=AES256-GCM-SHA384 bits=256 verify=FAIL); Sat, 22 Jun 2024 06:09:45 -0500 Received: from DLEE110.ent.ti.com (157.170.170.21) by DLEE115.ent.ti.com (157.170.170.26) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.2507.23; Sat, 22 Jun 2024 06:09:45 -0500 Received: from lelvsmtp6.itg.ti.com (10.180.75.249) by DLEE110.ent.ti.com (157.170.170.21) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.2507.23 via Frontend Transport; Sat, 22 Jun 2024 06:09:45 -0500 Received: from localhost (uda0496377.dhcp.ti.com [172.24.227.31]) by lelvsmtp6.itg.ti.com (8.15.2/8.15.2) with ESMTP id 45MB9iVw023263; Sat, 22 Jun 2024 06:09:45 -0500 From: Aradhya Bhatia To: Dmitry Baryshkov , Tomi Valkeinen , Andrzej Hajda , Neil Armstrong , Robert Foss , Laurent Pinchart , Jonas Karlman , Jernej Skrabec , Maarten Lankhorst , Maxime Ripard , Jyri Sarha , Thomas Zimmermann , David Airlie , Daniel Vetter CC: DRI Development List , Linux Kernel List , Dominik Haller , Sam Ravnborg , Thierry Reding , Kieran Bingham , Nishanth Menon , Vignesh Raghavendra , Praneeth Bajjuri , Udit Kumar , Devarsh Thakkar , Jayesh Choudhary , Jai Luthra , Aradhya Bhatia Subject: [PATCH v4 10/11] drm/atomic-helper: Re-order bridge chain pre-enable and post-disable Date: Sat, 22 Jun 2024 16:39:28 +0530 Message-ID: <20240622110929.3115714-11-a-bhatia1@ti.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240622110929.3115714-1-a-bhatia1@ti.com> References: <20240622110929.3115714-1-a-bhatia1@ti.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-EXCLAIMER-MD-CONFIG: e1e8a2fd-e40a-4ac6-ac9b-f7e9cc9ee180 Content-Type: text/plain; charset="utf-8" Move the bridge pre_enable call before crtc enable, and the bridge post_disable call after the crtc disable. The sequence of enable after this patch will look like: bridge[n]_pre_enable ... bridge[1]_pre_enable crtc_enable encoder_enable bridge[1]_enable ... bridge[n]__enable and vice-versa for the bridge chain disable sequence. The definition of bridge pre_enable hook says that, "The display pipe (i.e. clocks and timing signals) feeding this bridge will not yet be running when this callback is called". Since CRTC is also a source feeding the bridge, it should not be enabled before the bridges in the pipeline are pre_enabled. Fix that by re-ordering the sequence of bridge pre_enable and bridge post_disable. Signed-off-by: Aradhya Bhatia --- drivers/gpu/drm/drm_atomic_helper.c | 165 ++++++++++++++++++---------- include/drm/drm_atomic_helper.h | 7 ++ 2 files changed, 114 insertions(+), 58 deletions(-) diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atom= ic_helper.c index fb97b51b38f1..e8ad08634f58 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -74,6 +74,7 @@ * also shares the &struct drm_plane_helper_funcs function table with the = plane * helpers. */ + static void drm_atomic_helper_plane_changed(struct drm_atomic_state *state, struct drm_plane_state *old_plane_state, @@ -1122,11 +1123,11 @@ crtc_needs_disable(struct drm_crtc_state *old_state, } =20 static void -disable_outputs(struct drm_device *dev, struct drm_atomic_state *old_state) +disable_encoder_brige_chain(struct drm_device *dev, struct drm_atomic_stat= e *old_state, + enum bridge_chain_operation_type op_type) { struct drm_connector *connector; struct drm_connector_state *old_conn_state, *new_conn_state; - struct drm_crtc *crtc; struct drm_crtc_state *old_crtc_state, *new_crtc_state; int i; =20 @@ -1163,32 +1164,55 @@ disable_outputs(struct drm_device *dev, struct drm_= atomic_state *old_state) if (WARN_ON(!encoder)) continue; =20 - funcs =3D encoder->helper_private; - - drm_dbg_atomic(dev, "disabling [ENCODER:%d:%s]\n", - encoder->base.id, encoder->name); - /* * Each encoder has at most one connector (since we always steal * it away), so we won't call disable hooks twice. */ bridge =3D drm_bridge_chain_get_first_bridge(encoder); - drm_atomic_bridge_chain_disable(bridge, old_state); =20 - /* Right function depends upon target state. */ - if (funcs) { - if (funcs->atomic_disable) - funcs->atomic_disable(encoder, old_state); - else if (new_conn_state->crtc && funcs->prepare) - funcs->prepare(encoder); - else if (funcs->disable) - funcs->disable(encoder); - else if (funcs->dpms) - funcs->dpms(encoder, DRM_MODE_DPMS_OFF); - } + switch (op_type) { + case DRM_ENCODER_BRIDGE_DISABLE: + funcs =3D encoder->helper_private; + + drm_dbg_atomic(dev, "disabling [ENCODER:%d:%s]\n", + encoder->base.id, encoder->name); + + drm_atomic_bridge_chain_disable(bridge, old_state); + + /* Right function depends upon target state. */ + if (funcs) { + if (funcs->atomic_disable) + funcs->atomic_disable(encoder, old_state); + else if (new_conn_state->crtc && funcs->prepare) + funcs->prepare(encoder); + else if (funcs->disable) + funcs->disable(encoder); + else if (funcs->dpms) + funcs->dpms(encoder, DRM_MODE_DPMS_OFF); + } + + break; + + case DRM_BRIDGE_POST_DISABLE: + drm_atomic_bridge_chain_post_disable(bridge, old_state); =20 - drm_atomic_bridge_chain_post_disable(bridge, old_state); + break; + + default: + drm_err(dev, "Unrecognized Encoder/Bridge Operation (%d).\n", op_type); + break; + } } +} + +static void +disable_outputs(struct drm_device *dev, struct drm_atomic_state *old_state) +{ + struct drm_crtc *crtc; + struct drm_crtc_state *old_crtc_state, *new_crtc_state; + int i; + + disable_encoder_brige_chain(dev, old_state, DRM_ENCODER_BRIDGE_DISABLE); =20 for_each_oldnew_crtc_in_state(old_state, crtc, old_crtc_state, new_crtc_s= tate, i) { const struct drm_crtc_helper_funcs *funcs; @@ -1234,6 +1258,8 @@ disable_outputs(struct drm_device *dev, struct drm_at= omic_state *old_state) if (ret =3D=3D 0) drm_crtc_vblank_put(crtc); } + + disable_encoder_brige_chain(dev, old_state, DRM_BRIDGE_POST_DISABLE); } =20 /** @@ -1445,6 +1471,64 @@ static void drm_atomic_helper_commit_writebacks(stru= ct drm_device *dev, } } =20 +static void +enable_encoder_brige_chain(struct drm_device *dev, struct drm_atomic_state= *old_state, + enum bridge_chain_operation_type op_type) +{ + struct drm_connector *connector; + struct drm_connector_state *new_conn_state; + int i; + + for_each_new_connector_in_state(old_state, connector, new_conn_state, i) { + const struct drm_encoder_helper_funcs *funcs; + struct drm_encoder *encoder; + struct drm_bridge *bridge; + + if (!new_conn_state->best_encoder) + continue; + + if (!new_conn_state->crtc->state->active || + !drm_atomic_crtc_needs_modeset(new_conn_state->crtc->state)) + continue; + + encoder =3D new_conn_state->best_encoder; + + /* + * Each encoder has at most one connector (since we always steal + * it away), so we won't call enable hooks twice. + */ + bridge =3D drm_bridge_chain_get_first_bridge(encoder); + + switch (op_type) { + case DRM_BRIDGE_PRE_ENABLE: + drm_atomic_bridge_chain_pre_enable(bridge, old_state); + break; + + case DRM_ENCODER_BRIDGE_ENABLE: + funcs =3D encoder->helper_private; + + drm_dbg_atomic(dev, "enabling [ENCODER:%d:%s]\n", + encoder->base.id, encoder->name); + + if (funcs) { + if (funcs->atomic_enable) + funcs->atomic_enable(encoder, old_state); + else if (funcs->enable) + funcs->enable(encoder); + else if (funcs->commit) + funcs->commit(encoder); + } + + drm_atomic_bridge_chain_enable(bridge, old_state); + break; + + default: + drm_err(dev, "Unrecognized Encoder/Bridge Operation (%d).\n", op_type); + break; + } + } +} + /** * drm_atomic_helper_commit_modeset_enables - modeset commit to enable out= puts * @dev: DRM device @@ -1465,10 +1549,10 @@ void drm_atomic_helper_commit_modeset_enables(struc= t drm_device *dev, struct drm_crtc *crtc; struct drm_crtc_state *old_crtc_state; struct drm_crtc_state *new_crtc_state; - struct drm_connector *connector; - struct drm_connector_state *new_conn_state; int i; =20 + enable_encoder_brige_chain(dev, old_state, DRM_BRIDGE_PRE_ENABLE); + for_each_oldnew_crtc_in_state(old_state, crtc, old_crtc_state, new_crtc_s= tate, i) { const struct drm_crtc_helper_funcs *funcs; =20 @@ -1491,42 +1575,7 @@ void drm_atomic_helper_commit_modeset_enables(struct= drm_device *dev, } } =20 - for_each_new_connector_in_state(old_state, connector, new_conn_state, i) { - const struct drm_encoder_helper_funcs *funcs; - struct drm_encoder *encoder; - struct drm_bridge *bridge; - - if (!new_conn_state->best_encoder) - continue; - - if (!new_conn_state->crtc->state->active || - !drm_atomic_crtc_needs_modeset(new_conn_state->crtc->state)) - continue; - - encoder =3D new_conn_state->best_encoder; - funcs =3D encoder->helper_private; - - drm_dbg_atomic(dev, "enabling [ENCODER:%d:%s]\n", - encoder->base.id, encoder->name); - - /* - * Each encoder has at most one connector (since we always steal - * it away), so we won't call enable hooks twice. - */ - bridge =3D drm_bridge_chain_get_first_bridge(encoder); - drm_atomic_bridge_chain_pre_enable(bridge, old_state); - - if (funcs) { - if (funcs->atomic_enable) - funcs->atomic_enable(encoder, old_state); - else if (funcs->enable) - funcs->enable(encoder); - else if (funcs->commit) - funcs->commit(encoder); - } - - drm_atomic_bridge_chain_enable(bridge, old_state); - } + enable_encoder_brige_chain(dev, old_state, DRM_ENCODER_BRIDGE_ENABLE); =20 drm_atomic_helper_commit_writebacks(dev, old_state); } diff --git a/include/drm/drm_atomic_helper.h b/include/drm/drm_atomic_helpe= r.h index 9aa0a05aa072..b45a175a9f8a 100644 --- a/include/drm/drm_atomic_helper.h +++ b/include/drm/drm_atomic_helper.h @@ -43,6 +43,13 @@ */ #define DRM_PLANE_NO_SCALING (1<<16) =20 +enum bridge_chain_operation_type { + DRM_BRIDGE_PRE_ENABLE, + DRM_BRIDGE_POST_DISABLE, + DRM_ENCODER_BRIDGE_ENABLE, + DRM_ENCODER_BRIDGE_DISABLE, +}; + struct drm_atomic_state; struct drm_private_obj; struct drm_private_state; --=20 2.34.1