public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH v5 00/13] drm/bridge: cdns-dsi: Fix the color-shift issue
@ 2024-10-19 19:53 Aradhya Bhatia
  2024-10-19 19:53 ` [PATCH v5 01/13] drm/bridge: cdns-dsi: Fix connecting to next bridge Aradhya Bhatia
                   ` (7 more replies)
  0 siblings, 8 replies; 26+ messages in thread
From: Aradhya Bhatia @ 2024-10-19 19:53 UTC (permalink / raw)
  To: Tomi Valkeinen, Dmitry Baryshkov, Laurent Pinchart, Andrzej Hajda,
	Neil Armstrong, Robert Foss, Jonas Karlman, Jernej Skrabec,
	Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
	Simona Vetter
  Cc: Dominik Haller, Sam Ravnborg, Kieran Bingham, Nishanth Menon,
	Vignesh Raghavendra, Devarsh Thakkar, Praneeth Bajjuri,
	Udit Kumar, Jayesh Choudhary, DRI Development List,
	Linux Kernel List, Aradhya Bhatia

Hello all,

This series provides some crucial fixes and improvements for the Cadence's DSI
TX (cdns-dsi) controller found commonly in Texas Instruments' J7 family of SoCs
as well as in AM62P.

Along with that, this series aims to fix the color-shift issue that has been
going on with the DSI controller. This controller requires to be enabled before
the previous entity enables its stream[0]. It's a strict requirement which, if
not followed, causes the colors to "shift" on the display. The fix happens in
2 steps.

    1. The bridge pre_enable calls have been shifted before the crtc_enable and
       the bridge post_disable calls have been shifted after the crtc_disable.
       This has been done as per the definition of bridge pre_enable.

       "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.

       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.


    2. The cdns-dsi enable / disable sequences have now been moved to pre_enable
       and post_disable sequences. This is the only way to have cdns-dsi drivers
       be up and ready before the previous entity is enables its streaming.

The DSI also spec requires the Clock and Data Lanes be ready before the DSI TX
enables its stream[0]. A patch has been added to make the code wait for that to
happen. Going ahead with further DSI (and DSS configuration), while the lanes
are not ready, has been found to be another reason for shift in colors.

These patches have been tested with J721E based BeagleboneAI64 along with a
RaspberryPi 7" DSI panel. The extra patches can be found in the
"next_dsi_test-v5" branch of my github fork[1] for anyone who would like to test
them.


* Important note about the authorship of patches *

All the patches in the previous revisions of this series, as well as a majority
of this revision too have been authored when I owned a "ti.com" based email id,
i.e. <a-bhatia1@ti.com>. This email id is not in use anymore, and all the work
done later has been part of my personal work. Since the original patches were
authored using TI's email id, I have maintained the original authorships as they
are, as well as their sign offs.

I have further added another another sign off that uses my current (and
personal) email id, the one that is being used to send this revision,
i.e. <aradhya.bhatia@linux.dev>.

Thanks,
Aradhya


[0]: Section 12.6.5.7.3: "Start-up Procedure" [For DSI TX controller]
     in TDA4VM Technical Reference Manual https://www.ti.com/lit/zip/spruil1

[1]: https://github.com/aradhya07/linux-ab/tree/next_dsi_test-v5


Change Log:
  - Changes in v5:
    - Fix subject and description in patch 1/13.
    - Add patch to check the return value of
      phy_mipi_dphy_get_default_config() (patch: 6/13).
    - Change the Clk and Data Lane ready timeout from forever to 5s.
    - Print an error instead of calling WARN_ON_ONCE in patch 7/13.
    - Drop patch v4-07/11: "drm/bridge: cdns-dsi: Reset the DCS write FIFO".
      There has been some inconsistencies found with this patch upon further
      testing. This patch was being used to enable a DSI panel based on ILITEK
      ILI9881C bridge. This will be debugged separately.
    - Add patch to move the DSI mode check from _atomic_enable() to
      _atomic_check() (patch: 10/13).
    - Split patch v4-10/11 into 2 patches - 11/13 and 12/13.
      Patch 11/13 separates out the Encoder-Bridge operations into a helper
      function *without* changing the logic. Patch 12/13 then changes the order
      of the encoder-bridge operations as was intended in the original patch.
    - Add detailed comment for patch 13/13.
    - Add Tomi Valkeinen's R-b in patches 1, 2, 4, 5, 7, 8, 9, 13.

  - Changes in v4:
    - Add new patch, "drm/bridge: cdns-dsi: Move to devm_drm_of_get_bridge()",
      to update to an auto-managed way of finding next bridge in the chain.
    - Drop patch "drm/bridge: cdns-dsi: Fix the phy_initialized variable" and
      add "drm/bridge: cdns-dsi: Fix Phy _init() and _exit()" that properly
      de-initializes the Phy and maintains the initialization state.
    - Reword patch "drm/bridge: cdns-dsi: Reset the DCS write FIFO" to explain
      the HW concerns better.
    - Add R-b tag from Dmitry Baryshkov for patches 1/11 and 8/11.

  - Changes in v3:
    - Reword the commit message for patch "drm/bridge: cdns-dsi: Fix OF node
      pointer".
    - Add a new helper API to figure out DSI host input pixel format
      in patch "drm/mipi-dsi: Add helper to find input format".
    - Use a common function for bridge pre-enable and enable, and bridge disable
      and post-disable, to avoid code duplication.
    - Add T-b tag from Dominik Haller in patch 5/10. (Missed to add it in v2).
    - Add R-b tag from Dmitry Baryshkov for patch 8/10.

  - Changes in v2:
    - Drop patch "drm/tidss: Add CRTC mode_fixup"
    - Split patch "drm/bridge: cdns-dsi: Fix minor bugs" into 4 separate ones
    - Drop support for early_enable/late_disable APIs and instead re-order the
      pre_enable / post_disable APIs to be called before / after crtc_enable /
      crtc_disable.
    - Drop support for early_enable/late_disable in cdns-dsi and use
      pre_enable/post_disable APIs instead to do bridge enable/disable.


Previous versions:

v1: https://lore.kernel.org/all/20240511153051.1355825-1-a-bhatia1@ti.com/
v2: https://lore.kernel.org/all/20240530093621.1925863-1-a-bhatia1@ti.com/
v3: https://lore.kernel.org/all/20240617105311.1587489-1-a-bhatia1@ti.com/
v4: https://lore.kernel.org/all/20240622110929.3115714-1-a-bhatia1@ti.com/

Aradhya Bhatia (13):
  drm/bridge: cdns-dsi: Fix connecting to next bridge
  drm/bridge: cdns-dsi: Move to devm_drm_of_get_bridge()
  drm/bridge: cdns-dsi: Fix Phy _init() and _exit()
  drm/bridge: cdns-dsi: Fix the link and phy init order
  drm/bridge: cdns-dsi: Fix the clock variable for mode_valid()
  drm/bridge: cdns-dsi: Check return value when getting default PHY
    config
  drm/bridge: cdns-dsi: Wait for Clk and Data Lanes to be ready
  drm/mipi-dsi: Add helper to find input format
  drm/bridge: cdns-dsi: Support atomic bridge APIs
  drm/bridge: cdns-dsi: Move DSI mode check to _atomic_check()
  drm/atomic-helper: Separate out Encoder-Bridge enable and disable
  drm/atomic-helper: Re-order bridge chain pre-enable and post-disable
  drm/bridge: cdns-dsi: Use pre_enable/post_disable to enable/disable

 .../gpu/drm/bridge/cadence/cdns-dsi-core.c    | 159 +++++++++++------
 .../gpu/drm/bridge/cadence/cdns-dsi-core.h    |   3 +-
 drivers/gpu/drm/drm_atomic_helper.c           | 163 +++++++++++-------
 drivers/gpu/drm/drm_mipi_dsi.c                |  37 ++++
 include/drm/drm_atomic_helper.h               |   5 +
 include/drm/drm_mipi_dsi.h                    |   1 +
 6 files changed, 255 insertions(+), 113 deletions(-)


base-commit: f2493655d2d3d5c6958ed996b043c821c23ae8d3
-- 
2.34.1


^ permalink raw reply	[flat|nested] 26+ messages in thread

* [PATCH v5 01/13] drm/bridge: cdns-dsi: Fix connecting to next bridge
  2024-10-19 19:53 [PATCH v5 00/13] drm/bridge: cdns-dsi: Fix the color-shift issue Aradhya Bhatia
@ 2024-10-19 19:53 ` Aradhya Bhatia
  2024-10-19 19:54 ` [PATCH v5 02/13] drm/bridge: cdns-dsi: Move to devm_drm_of_get_bridge() Aradhya Bhatia
                   ` (6 subsequent siblings)
  7 siblings, 0 replies; 26+ messages in thread
From: Aradhya Bhatia @ 2024-10-19 19:53 UTC (permalink / raw)
  To: Tomi Valkeinen, Dmitry Baryshkov, Laurent Pinchart, Andrzej Hajda,
	Neil Armstrong, Robert Foss, Jonas Karlman, Jernej Skrabec,
	Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
	Simona Vetter
  Cc: Dominik Haller, Sam Ravnborg, Kieran Bingham, Nishanth Menon,
	Vignesh Raghavendra, Devarsh Thakkar, Praneeth Bajjuri,
	Udit Kumar, Jayesh Choudhary, DRI Development List,
	Linux Kernel List, Aradhya Bhatia

From: Aradhya Bhatia <a-bhatia1@ti.com>

Fix the OF node pointer passed to the of_drm_find_bridge() call to find
the next bridge in the display chain.

The code to find the next panel (and create its panel-bridge) works
fine, but to find the next (non-panel) bridge does not.

To find the next bridge in the pipeline, we need to pass "np" - the OF
node pointer of the next entity in the devicetree chain. Passing
"of_node" to of_drm_find_bridge (which is what the code does currently)
will fetch the bridge for the cdns-dsi which is not what's required.

Fix that.

Fixes: e19233955d9e ("drm/bridge: Add Cadence DSI driver")
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
Reviewed-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
Signed-off-by: Aradhya Bhatia <a-bhatia1@ti.com>
Signed-off-by: Aradhya Bhatia <aradhya.bhatia@linux.dev>
---
 drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
index 7457d38622b0..b016f2ba06bb 100644
--- a/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
+++ b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
@@ -952,7 +952,7 @@ static int cdns_dsi_attach(struct mipi_dsi_host *host,
 		bridge = drm_panel_bridge_add_typed(panel,
 						    DRM_MODE_CONNECTOR_DSI);
 	} else {
-		bridge = of_drm_find_bridge(dev->dev.of_node);
+		bridge = of_drm_find_bridge(np);
 		if (!bridge)
 			bridge = ERR_PTR(-EINVAL);
 	}
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH v5 02/13] drm/bridge: cdns-dsi: Move to devm_drm_of_get_bridge()
  2024-10-19 19:53 [PATCH v5 00/13] drm/bridge: cdns-dsi: Fix the color-shift issue Aradhya Bhatia
  2024-10-19 19:53 ` [PATCH v5 01/13] drm/bridge: cdns-dsi: Fix connecting to next bridge Aradhya Bhatia
@ 2024-10-19 19:54 ` Aradhya Bhatia
  2024-10-20 10:49   ` Dmitry Baryshkov
  2024-10-19 19:54 ` [PATCH v5 03/13] drm/bridge: cdns-dsi: Fix Phy _init() and _exit() Aradhya Bhatia
                   ` (5 subsequent siblings)
  7 siblings, 1 reply; 26+ messages in thread
From: Aradhya Bhatia @ 2024-10-19 19:54 UTC (permalink / raw)
  To: Tomi Valkeinen, Dmitry Baryshkov, Laurent Pinchart, Andrzej Hajda,
	Neil Armstrong, Robert Foss, Jonas Karlman, Jernej Skrabec,
	Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
	Simona Vetter
  Cc: Dominik Haller, Sam Ravnborg, Kieran Bingham, Nishanth Menon,
	Vignesh Raghavendra, Devarsh Thakkar, Praneeth Bajjuri,
	Udit Kumar, Jayesh Choudhary, DRI Development List,
	Linux Kernel List, Aradhya Bhatia

From: Aradhya Bhatia <a-bhatia1@ti.com>

Instead of manually finding the next bridge/panel, and maintaining the
panel-bridge (in-case the next entity is a panel), switch to using the
automatically managing devm_drm_of_get_bridge() API.

Drop the drm_panel support completely from the driver while at it.

Reviewed-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
Signed-off-by: Aradhya Bhatia <a-bhatia1@ti.com>
Signed-off-by: Aradhya Bhatia <aradhya.bhatia@linux.dev>
---
 .../gpu/drm/bridge/cadence/cdns-dsi-core.c    | 28 ++-----------------
 .../gpu/drm/bridge/cadence/cdns-dsi-core.h    |  2 --
 2 files changed, 3 insertions(+), 27 deletions(-)

diff --git a/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
index b016f2ba06bb..5159c3f0853e 100644
--- a/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
+++ b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
@@ -920,8 +920,6 @@ static int cdns_dsi_attach(struct mipi_dsi_host *host,
 	struct cdns_dsi_output *output = &dsi->output;
 	struct cdns_dsi_input *input = &dsi->input;
 	struct drm_bridge *bridge;
-	struct drm_panel *panel;
-	struct device_node *np;
 	int ret;
 
 	/*
@@ -939,26 +937,10 @@ static int cdns_dsi_attach(struct mipi_dsi_host *host,
 	/*
 	 * The host <-> device link might be described using an OF-graph
 	 * representation, in this case we extract the device of_node from
-	 * this representation, otherwise we use dsidev->dev.of_node which
-	 * should have been filled by the core.
+	 * this representation.
 	 */
-	np = of_graph_get_remote_node(dsi->base.dev->of_node, DSI_OUTPUT_PORT,
-				      dev->channel);
-	if (!np)
-		np = of_node_get(dev->dev.of_node);
-
-	panel = of_drm_find_panel(np);
-	if (!IS_ERR(panel)) {
-		bridge = drm_panel_bridge_add_typed(panel,
-						    DRM_MODE_CONNECTOR_DSI);
-	} else {
-		bridge = of_drm_find_bridge(np);
-		if (!bridge)
-			bridge = ERR_PTR(-EINVAL);
-	}
-
-	of_node_put(np);
-
+	bridge = devm_drm_of_get_bridge(dsi->base.dev, dsi->base.dev->of_node,
+					DSI_OUTPUT_PORT, dev->channel);
 	if (IS_ERR(bridge)) {
 		ret = PTR_ERR(bridge);
 		dev_err(host->dev, "failed to add DSI device %s (err = %d)",
@@ -968,7 +950,6 @@ static int cdns_dsi_attach(struct mipi_dsi_host *host,
 
 	output->dev = dev;
 	output->bridge = bridge;
-	output->panel = panel;
 
 	/*
 	 * The DSI output has been properly configured, we can now safely
@@ -984,12 +965,9 @@ static int cdns_dsi_detach(struct mipi_dsi_host *host,
 			   struct mipi_dsi_device *dev)
 {
 	struct cdns_dsi *dsi = to_cdns_dsi(host);
-	struct cdns_dsi_output *output = &dsi->output;
 	struct cdns_dsi_input *input = &dsi->input;
 
 	drm_bridge_remove(&input->bridge);
-	if (output->panel)
-		drm_panel_bridge_remove(output->bridge);
 
 	return 0;
 }
diff --git a/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.h b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.h
index ca7ea2da635c..5db5dbbbcaad 100644
--- a/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.h
+++ b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.h
@@ -10,7 +10,6 @@
 
 #include <drm/drm_bridge.h>
 #include <drm/drm_mipi_dsi.h>
-#include <drm/drm_panel.h>
 
 #include <linux/bits.h>
 #include <linux/completion.h>
@@ -21,7 +20,6 @@ struct reset_control;
 
 struct cdns_dsi_output {
 	struct mipi_dsi_device *dev;
-	struct drm_panel *panel;
 	struct drm_bridge *bridge;
 	union phy_configure_opts phy_opts;
 };
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH v5 03/13] drm/bridge: cdns-dsi: Fix Phy _init() and _exit()
  2024-10-19 19:53 [PATCH v5 00/13] drm/bridge: cdns-dsi: Fix the color-shift issue Aradhya Bhatia
  2024-10-19 19:53 ` [PATCH v5 01/13] drm/bridge: cdns-dsi: Fix connecting to next bridge Aradhya Bhatia
  2024-10-19 19:54 ` [PATCH v5 02/13] drm/bridge: cdns-dsi: Move to devm_drm_of_get_bridge() Aradhya Bhatia
@ 2024-10-19 19:54 ` Aradhya Bhatia
  2024-10-20 11:34   ` Dmitry Baryshkov
  2024-10-19 19:54 ` [PATCH v5 04/13] drm/bridge: cdns-dsi: Fix the link and phy init order Aradhya Bhatia
                   ` (4 subsequent siblings)
  7 siblings, 1 reply; 26+ messages in thread
From: Aradhya Bhatia @ 2024-10-19 19:54 UTC (permalink / raw)
  To: Tomi Valkeinen, Dmitry Baryshkov, Laurent Pinchart, Andrzej Hajda,
	Neil Armstrong, Robert Foss, Jonas Karlman, Jernej Skrabec,
	Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
	Simona Vetter
  Cc: Dominik Haller, Sam Ravnborg, Kieran Bingham, Nishanth Menon,
	Vignesh Raghavendra, Devarsh Thakkar, Praneeth Bajjuri,
	Udit Kumar, Jayesh Choudhary, DRI Development List,
	Linux Kernel List, Aradhya Bhatia

From: Aradhya Bhatia <a-bhatia1@ti.com>

Initialize the Phy during the cdns-dsi _resume(), and de-initialize it
during the _suspend().

Also power-off the Phy from bridge_disable.

Fixes: fced5a364dee ("drm/bridge: cdns: Convert to phy framework")
Signed-off-by: Aradhya Bhatia <a-bhatia1@ti.com>
Signed-off-by: Aradhya Bhatia <aradhya.bhatia@linux.dev>
---
 drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
index 5159c3f0853e..d89c32bae2b9 100644
--- a/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
+++ b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
@@ -672,6 +672,10 @@ static void cdns_dsi_bridge_disable(struct drm_bridge *bridge)
 	if (dsi->platform_ops && dsi->platform_ops->disable)
 		dsi->platform_ops->disable(dsi);
 
+	phy_power_off(dsi->dphy);
+	dsi->link_initialized = false;
+	dsi->phy_initialized = false;
+
 	pm_runtime_put(dsi->base.dev);
 }
 
@@ -698,7 +702,6 @@ static void cdns_dsi_hs_init(struct cdns_dsi *dsi)
 	       DPHY_CMN_PDN | DPHY_PLL_PDN,
 	       dsi->regs + MCTL_DPHY_CFG0);
 
-	phy_init(dsi->dphy);
 	phy_set_mode(dsi->dphy, PHY_MODE_MIPI_DPHY);
 	phy_configure(dsi->dphy, &output->phy_opts);
 	phy_power_on(dsi->dphy);
@@ -1120,6 +1123,8 @@ static int __maybe_unused cdns_dsi_resume(struct device *dev)
 	clk_prepare_enable(dsi->dsi_p_clk);
 	clk_prepare_enable(dsi->dsi_sys_clk);
 
+	phy_init(dsi->dphy);
+
 	return 0;
 }
 
@@ -1127,10 +1132,11 @@ static int __maybe_unused cdns_dsi_suspend(struct device *dev)
 {
 	struct cdns_dsi *dsi = dev_get_drvdata(dev);
 
+	phy_exit(dsi->dphy);
+
 	clk_disable_unprepare(dsi->dsi_sys_clk);
 	clk_disable_unprepare(dsi->dsi_p_clk);
 	reset_control_assert(dsi->dsi_p_rst);
-	dsi->link_initialized = false;
 	return 0;
 }
 
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH v5 04/13] drm/bridge: cdns-dsi: Fix the link and phy init order
  2024-10-19 19:53 [PATCH v5 00/13] drm/bridge: cdns-dsi: Fix the color-shift issue Aradhya Bhatia
                   ` (2 preceding siblings ...)
  2024-10-19 19:54 ` [PATCH v5 03/13] drm/bridge: cdns-dsi: Fix Phy _init() and _exit() Aradhya Bhatia
@ 2024-10-19 19:54 ` Aradhya Bhatia
  2024-10-19 19:54 ` [PATCH v5 05/13] drm/bridge: cdns-dsi: Fix the clock variable for mode_valid() Aradhya Bhatia
                   ` (3 subsequent siblings)
  7 siblings, 0 replies; 26+ messages in thread
From: Aradhya Bhatia @ 2024-10-19 19:54 UTC (permalink / raw)
  To: Tomi Valkeinen, Dmitry Baryshkov, Laurent Pinchart, Andrzej Hajda,
	Neil Armstrong, Robert Foss, Jonas Karlman, Jernej Skrabec,
	Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
	Simona Vetter
  Cc: Dominik Haller, Sam Ravnborg, Kieran Bingham, Nishanth Menon,
	Vignesh Raghavendra, Devarsh Thakkar, Praneeth Bajjuri,
	Udit Kumar, Jayesh Choudhary, DRI Development List,
	Linux Kernel List, Aradhya Bhatia

From: Aradhya Bhatia <a-bhatia1@ti.com>

The order of init of DSI link and DSI phy is wrong. The DSI link needs
to be configured before the DSI phy is getting configured. Otherwise,
the D-Phy is unable to lock in on the incoming PLL Reference clock[0].

Fix the order of inits.

[0]: See section 12.6.5.7.3 "Start-up Procedure" in J721E SoC TRM
     TRM Link: http://www.ti.com/lit/pdf/spruil1

Fixes: fced5a364dee ("drm/bridge: cdns: Convert to phy framework")
Reviewed-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
Signed-off-by: Aradhya Bhatia <a-bhatia1@ti.com>
Signed-off-by: Aradhya Bhatia <aradhya.bhatia@linux.dev>
---
 drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
index d89c32bae2b9..03a5af52ec0b 100644
--- a/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
+++ b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
@@ -778,8 +778,8 @@ static void cdns_dsi_bridge_enable(struct drm_bridge *bridge)
 
 	WARN_ON_ONCE(cdns_dsi_check_conf(dsi, mode, &dsi_cfg, false));
 
-	cdns_dsi_hs_init(dsi);
 	cdns_dsi_init_link(dsi);
+	cdns_dsi_hs_init(dsi);
 
 	writel(HBP_LEN(dsi_cfg.hbp) | HSA_LEN(dsi_cfg.hsa),
 	       dsi->regs + VID_HSIZE1);
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH v5 05/13] drm/bridge: cdns-dsi: Fix the clock variable for mode_valid()
  2024-10-19 19:53 [PATCH v5 00/13] drm/bridge: cdns-dsi: Fix the color-shift issue Aradhya Bhatia
                   ` (3 preceding siblings ...)
  2024-10-19 19:54 ` [PATCH v5 04/13] drm/bridge: cdns-dsi: Fix the link and phy init order Aradhya Bhatia
@ 2024-10-19 19:54 ` Aradhya Bhatia
  2024-10-19 19:54 ` [PATCH v5 06/13] drm/bridge: cdns-dsi: Check return value when getting default PHY config Aradhya Bhatia
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 26+ messages in thread
From: Aradhya Bhatia @ 2024-10-19 19:54 UTC (permalink / raw)
  To: Tomi Valkeinen, Dmitry Baryshkov, Laurent Pinchart, Andrzej Hajda,
	Neil Armstrong, Robert Foss, Jonas Karlman, Jernej Skrabec,
	Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
	Simona Vetter
  Cc: Dominik Haller, Sam Ravnborg, Kieran Bingham, Nishanth Menon,
	Vignesh Raghavendra, Devarsh Thakkar, Praneeth Bajjuri,
	Udit Kumar, Jayesh Choudhary, DRI Development List,
	Linux Kernel List, Aradhya Bhatia

From: Aradhya Bhatia <a-bhatia1@ti.com>

Allow the D-Phy config checks to use mode->clock instead of
mode->crtc_clock during mode_valid checks, like everywhere else in the
driver.

Fixes: fced5a364dee ("drm/bridge: cdns: Convert to phy framework")
Reviewed-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
Signed-off-by: Aradhya Bhatia <a-bhatia1@ti.com>
Signed-off-by: Aradhya Bhatia <aradhya.bhatia@linux.dev>
---
 drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
index 03a5af52ec0b..2fc24352d989 100644
--- a/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
+++ b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
@@ -568,13 +568,14 @@ static int cdns_dsi_check_conf(struct cdns_dsi *dsi,
 	struct phy_configure_opts_mipi_dphy *phy_cfg = &output->phy_opts.mipi_dphy;
 	unsigned long dsi_hss_hsa_hse_hbp;
 	unsigned int nlanes = output->dev->lanes;
+	int mode_clock = (mode_valid_check ? mode->clock : mode->crtc_clock);
 	int ret;
 
 	ret = cdns_dsi_mode2cfg(dsi, mode, dsi_cfg, mode_valid_check);
 	if (ret)
 		return ret;
 
-	phy_mipi_dphy_get_default_config(mode->crtc_clock * 1000,
+	phy_mipi_dphy_get_default_config(mode_clock * 1000,
 					 mipi_dsi_pixel_format_to_bpp(output->dev->format),
 					 nlanes, phy_cfg);
 
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH v5 06/13] drm/bridge: cdns-dsi: Check return value when getting default PHY config
  2024-10-19 19:53 [PATCH v5 00/13] drm/bridge: cdns-dsi: Fix the color-shift issue Aradhya Bhatia
                   ` (4 preceding siblings ...)
  2024-10-19 19:54 ` [PATCH v5 05/13] drm/bridge: cdns-dsi: Fix the clock variable for mode_valid() Aradhya Bhatia
@ 2024-10-19 19:54 ` Aradhya Bhatia
  2024-11-18 14:12   ` Tomi Valkeinen
  2024-10-19 19:54 ` [PATCH v5 07/13] drm/bridge: cdns-dsi: Wait for Clk and Data Lanes to be ready Aradhya Bhatia
  2024-10-19 20:05 ` [PATCH v5 08/13] drm/mipi-dsi: Add helper to find input format Aradhya Bhatia
  7 siblings, 1 reply; 26+ messages in thread
From: Aradhya Bhatia @ 2024-10-19 19:54 UTC (permalink / raw)
  To: Tomi Valkeinen, Dmitry Baryshkov, Laurent Pinchart, Andrzej Hajda,
	Neil Armstrong, Robert Foss, Jonas Karlman, Jernej Skrabec,
	Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
	Simona Vetter
  Cc: Dominik Haller, Sam Ravnborg, Kieran Bingham, Nishanth Menon,
	Vignesh Raghavendra, Devarsh Thakkar, Praneeth Bajjuri,
	Udit Kumar, Jayesh Choudhary, DRI Development List,
	Linux Kernel List, Aradhya Bhatia

From: Aradhya Bhatia <a-bhatia1@ti.com>

Check for the return value of the phy_mipi_dphy_get_default_config()
call, and incase of an error, return back the same.

Fixes: fced5a364dee ("drm/bridge: cdns: Convert to phy framework")
Signed-off-by: Aradhya Bhatia <a-bhatia1@ti.com>
Signed-off-by: Aradhya Bhatia <aradhya.bhatia@linux.dev>
---
 drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
index 2fc24352d989..e4c0968313af 100644
--- a/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
+++ b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
@@ -575,9 +575,11 @@ static int cdns_dsi_check_conf(struct cdns_dsi *dsi,
 	if (ret)
 		return ret;
 
-	phy_mipi_dphy_get_default_config(mode_clock * 1000,
-					 mipi_dsi_pixel_format_to_bpp(output->dev->format),
-					 nlanes, phy_cfg);
+	ret = phy_mipi_dphy_get_default_config(mode_clock * 1000,
+					       mipi_dsi_pixel_format_to_bpp(output->dev->format),
+					       nlanes, phy_cfg);
+	if (ret)
+		return ret;
 
 	ret = cdns_dsi_adjust_phy_config(dsi, dsi_cfg, phy_cfg, mode, mode_valid_check);
 	if (ret)
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH v5 07/13] drm/bridge: cdns-dsi: Wait for Clk and Data Lanes to be ready
  2024-10-19 19:53 [PATCH v5 00/13] drm/bridge: cdns-dsi: Fix the color-shift issue Aradhya Bhatia
                   ` (5 preceding siblings ...)
  2024-10-19 19:54 ` [PATCH v5 06/13] drm/bridge: cdns-dsi: Check return value when getting default PHY config Aradhya Bhatia
@ 2024-10-19 19:54 ` Aradhya Bhatia
  2024-10-22  6:25   ` Devarsh Thakkar
  2024-10-19 20:05 ` [PATCH v5 08/13] drm/mipi-dsi: Add helper to find input format Aradhya Bhatia
  7 siblings, 1 reply; 26+ messages in thread
From: Aradhya Bhatia @ 2024-10-19 19:54 UTC (permalink / raw)
  To: Tomi Valkeinen, Dmitry Baryshkov, Laurent Pinchart, Andrzej Hajda,
	Neil Armstrong, Robert Foss, Jonas Karlman, Jernej Skrabec,
	Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
	Simona Vetter
  Cc: Dominik Haller, Sam Ravnborg, Kieran Bingham, Nishanth Menon,
	Vignesh Raghavendra, Devarsh Thakkar, Praneeth Bajjuri,
	Udit Kumar, Jayesh Choudhary, DRI Development List,
	Linux Kernel List, Aradhya Bhatia

From: Aradhya Bhatia <a-bhatia1@ti.com>

Once the DSI Link and DSI Phy are initialized, the code needs to wait
for Clk and Data Lanes to be ready, before continuing configuration.
This is in accordance with the DSI Start-up procedure, found in the
Technical Reference Manual of Texas Instrument's J721E SoC[0] which
houses this DSI TX controller.

If the previous bridge (or crtc/encoder) are configured pre-maturely,
the input signal FIFO gets corrupt. This introduces a color-shift on the
display.

Allow the driver to wait for the clk and data lanes to get ready during
DSI enable.

[0]: See section 12.6.5.7.3 "Start-up Procedure" in J721E SoC TRM
     TRM Link: http://www.ti.com/lit/pdf/spruil1

Fixes: e19233955d9e ("drm/bridge: Add Cadence DSI driver")
Tested-by: Dominik Haller <d.haller@phytec.de>
Reviewed-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
Signed-off-by: Aradhya Bhatia <a-bhatia1@ti.com>
Signed-off-by: Aradhya Bhatia <aradhya.bhatia@linux.dev>
---
 drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c | 15 ++++++++++++++-
 1 file changed, 14 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
index e4c0968313af..284c468db6c3 100644
--- a/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
+++ b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
@@ -767,7 +767,7 @@ static void cdns_dsi_bridge_enable(struct drm_bridge *bridge)
 	struct phy_configure_opts_mipi_dphy *phy_cfg = &output->phy_opts.mipi_dphy;
 	unsigned long tx_byte_period;
 	struct cdns_dsi_cfg dsi_cfg;
-	u32 tmp, reg_wakeup, div;
+	u32 tmp, reg_wakeup, div, status;
 	int nlanes;
 
 	if (WARN_ON(pm_runtime_get_sync(dsi->base.dev) < 0))
@@ -784,6 +784,19 @@ static void cdns_dsi_bridge_enable(struct drm_bridge *bridge)
 	cdns_dsi_init_link(dsi);
 	cdns_dsi_hs_init(dsi);
 
+	/*
+	 * Now that the DSI Link and DSI Phy are initialized,
+	 * wait for the CLK and Data Lanes to be ready.
+	 */
+	tmp = CLK_LANE_RDY;
+	for (int i = 0; i < nlanes; i++)
+		tmp |= DATA_LANE_RDY(i);
+
+	if (readl_poll_timeout(dsi->regs + MCTL_MAIN_STS, status,
+			       status & tmp, 100, 500000))
+		dev_err(dsi->base.dev,
+			"Timed Out: DSI-DPhy Clock and Data Lanes not ready.\n");
+
 	writel(HBP_LEN(dsi_cfg.hbp) | HSA_LEN(dsi_cfg.hsa),
 	       dsi->regs + VID_HSIZE1);
 	writel(HFP_LEN(dsi_cfg.hfp) | HACT_LEN(dsi_cfg.hact),
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH v5 08/13] drm/mipi-dsi: Add helper to find input format
  2024-10-19 19:53 [PATCH v5 00/13] drm/bridge: cdns-dsi: Fix the color-shift issue Aradhya Bhatia
                   ` (6 preceding siblings ...)
  2024-10-19 19:54 ` [PATCH v5 07/13] drm/bridge: cdns-dsi: Wait for Clk and Data Lanes to be ready Aradhya Bhatia
@ 2024-10-19 20:05 ` Aradhya Bhatia
  2024-10-19 20:05   ` [PATCH v5 09/13] drm/bridge: cdns-dsi: Support atomic bridge APIs Aradhya Bhatia
                     ` (4 more replies)
  7 siblings, 5 replies; 26+ messages in thread
From: Aradhya Bhatia @ 2024-10-19 20:05 UTC (permalink / raw)
  To: Tomi Valkeinen, Dmitry Baryshkov, Laurent Pinchart, Andrzej Hajda,
	Neil Armstrong, Robert Foss, Jonas Karlman, Jernej Skrabec,
	Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
	Simona Vetter
  Cc: Dominik Haller, Sam Ravnborg, Kieran Bingham, Nishanth Menon,
	Vignesh Raghavendra, Devarsh Thakkar, Praneeth Bajjuri,
	Udit Kumar, Jayesh Choudhary, DRI Development List,
	Linux Kernel List, Aradhya Bhatia

From: Aradhya Bhatia <a-bhatia1@ti.com>

Add a helper API that can be used by the DSI hosts to find the required
input bus format for the given output dsi pixel format.

Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
Reviewed-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
Signed-off-by: Aradhya Bhatia <a-bhatia1@ti.com>
Signed-off-by: Aradhya Bhatia <aradhya.bhatia@linux.dev>
---
 drivers/gpu/drm/drm_mipi_dsi.c | 37 ++++++++++++++++++++++++++++++++++
 include/drm/drm_mipi_dsi.h     |  1 +
 2 files changed, 38 insertions(+)

diff --git a/drivers/gpu/drm/drm_mipi_dsi.c b/drivers/gpu/drm/drm_mipi_dsi.c
index 5e5c5f84daac..076826f2445a 100644
--- a/drivers/gpu/drm/drm_mipi_dsi.c
+++ b/drivers/gpu/drm/drm_mipi_dsi.c
@@ -36,6 +36,8 @@
 #include <drm/drm_mipi_dsi.h>
 #include <drm/drm_print.h>
 
+#include <linux/media-bus-format.h>
+
 #include <video/mipi_display.h>
 
 /**
@@ -870,6 +872,41 @@ ssize_t mipi_dsi_generic_read(struct mipi_dsi_device *dsi, const void *params,
 }
 EXPORT_SYMBOL(mipi_dsi_generic_read);
 
+/**
+ * drm_mipi_dsi_get_input_bus_fmt() - Get the required MEDIA_BUS_FMT_* based
+ *				      input pixel format for a given DSI output
+ *				      pixel format
+ * @dsi_format: pixel format that a DSI host needs to output
+ *
+ * Various DSI hosts can use this function during their
+ * &drm_bridge_funcs.atomic_get_input_bus_fmts operation to ascertain
+ * the MEDIA_BUS_FMT_* pixel format required as input.
+ *
+ * RETURNS:
+ * a 32-bit MEDIA_BUS_FMT_* value on success or 0 in case of failure.
+ */
+u32 drm_mipi_dsi_get_input_bus_fmt(enum mipi_dsi_pixel_format dsi_format)
+{
+	switch (dsi_format) {
+	case MIPI_DSI_FMT_RGB888:
+		return MEDIA_BUS_FMT_RGB888_1X24;
+
+	case MIPI_DSI_FMT_RGB666:
+		return MEDIA_BUS_FMT_RGB666_1X24_CPADHI;
+
+	case MIPI_DSI_FMT_RGB666_PACKED:
+		return MEDIA_BUS_FMT_RGB666_1X18;
+
+	case MIPI_DSI_FMT_RGB565:
+		return MEDIA_BUS_FMT_RGB565_1X16;
+
+	default:
+		/* Unsupported DSI Format */
+		return 0;
+	}
+}
+EXPORT_SYMBOL(drm_mipi_dsi_get_input_bus_fmt);
+
 /**
  * mipi_dsi_dcs_write_buffer() - transmit a DCS command with payload
  * @dsi: DSI peripheral device
diff --git a/include/drm/drm_mipi_dsi.h b/include/drm/drm_mipi_dsi.h
index 94400a78031f..9e2804e3a2b0 100644
--- a/include/drm/drm_mipi_dsi.h
+++ b/include/drm/drm_mipi_dsi.h
@@ -293,6 +293,7 @@ void mipi_dsi_generic_write_multi(struct mipi_dsi_multi_context *ctx,
 				  const void *payload, size_t size);
 ssize_t mipi_dsi_generic_read(struct mipi_dsi_device *dsi, const void *params,
 			      size_t num_params, void *data, size_t size);
+u32 drm_mipi_dsi_get_input_bus_fmt(enum mipi_dsi_pixel_format dsi_format);
 
 #define mipi_dsi_msleep(ctx, delay)	\
 	do {				\
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH v5 09/13] drm/bridge: cdns-dsi: Support atomic bridge APIs
  2024-10-19 20:05 ` [PATCH v5 08/13] drm/mipi-dsi: Add helper to find input format Aradhya Bhatia
@ 2024-10-19 20:05   ` Aradhya Bhatia
  2024-10-19 20:05   ` [PATCH v5 10/13] drm/bridge: cdns-dsi: Move DSI mode check to _atomic_check() Aradhya Bhatia
                     ` (3 subsequent siblings)
  4 siblings, 0 replies; 26+ messages in thread
From: Aradhya Bhatia @ 2024-10-19 20:05 UTC (permalink / raw)
  To: Tomi Valkeinen, Dmitry Baryshkov, Laurent Pinchart, Andrzej Hajda,
	Neil Armstrong, Robert Foss, Jonas Karlman, Jernej Skrabec,
	Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
	Simona Vetter
  Cc: Dominik Haller, Sam Ravnborg, Kieran Bingham, Nishanth Menon,
	Vignesh Raghavendra, Devarsh Thakkar, Praneeth Bajjuri,
	Udit Kumar, Jayesh Choudhary, DRI Development List,
	Linux Kernel List, Aradhya Bhatia

From: Aradhya Bhatia <a-bhatia1@ti.com>

Change the existing (and deprecated) bridge hooks, to the bridge
atomic APIs.

Add drm helpers for duplicate_state, destroy_state, and bridge_reset
bridge hooks.

Further add support for the input format negotiation hook.

Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
Reviewed-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
Signed-off-by: Aradhya Bhatia <a-bhatia1@ti.com>
Signed-off-by: Aradhya Bhatia <aradhya.bhatia@linux.dev>
---
 .../gpu/drm/bridge/cadence/cdns-dsi-core.c    | 51 ++++++++++++++++---
 1 file changed, 43 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
index 284c468db6c3..7341e609dc8b 100644
--- a/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
+++ b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
@@ -658,7 +658,8 @@ cdns_dsi_bridge_mode_valid(struct drm_bridge *bridge,
 	return MODE_OK;
 }
 
-static void cdns_dsi_bridge_disable(struct drm_bridge *bridge)
+static void cdns_dsi_bridge_atomic_disable(struct drm_bridge *bridge,
+					   struct drm_bridge_state *old_bridge_state)
 {
 	struct cdns_dsi_input *input = bridge_to_cdns_dsi_input(bridge);
 	struct cdns_dsi *dsi = input_to_dsi(input);
@@ -682,7 +683,8 @@ static void cdns_dsi_bridge_disable(struct drm_bridge *bridge)
 	pm_runtime_put(dsi->base.dev);
 }
 
-static void cdns_dsi_bridge_post_disable(struct drm_bridge *bridge)
+static void cdns_dsi_bridge_atomic_post_disable(struct drm_bridge *bridge,
+						struct drm_bridge_state *old_bridge_state)
 {
 	struct cdns_dsi_input *input = bridge_to_cdns_dsi_input(bridge);
 	struct cdns_dsi *dsi = input_to_dsi(input);
@@ -758,7 +760,8 @@ static void cdns_dsi_init_link(struct cdns_dsi *dsi)
 	dsi->link_initialized = true;
 }
 
-static void cdns_dsi_bridge_enable(struct drm_bridge *bridge)
+static void cdns_dsi_bridge_atomic_enable(struct drm_bridge *bridge,
+					  struct drm_bridge_state *old_bridge_state)
 {
 	struct cdns_dsi_input *input = bridge_to_cdns_dsi_input(bridge);
 	struct cdns_dsi *dsi = input_to_dsi(input);
@@ -911,7 +914,8 @@ static void cdns_dsi_bridge_enable(struct drm_bridge *bridge)
 	writel(tmp, dsi->regs + MCTL_MAIN_EN);
 }
 
-static void cdns_dsi_bridge_pre_enable(struct drm_bridge *bridge)
+static void cdns_dsi_bridge_atomic_pre_enable(struct drm_bridge *bridge,
+					      struct drm_bridge_state *old_bridge_state)
 {
 	struct cdns_dsi_input *input = bridge_to_cdns_dsi_input(bridge);
 	struct cdns_dsi *dsi = input_to_dsi(input);
@@ -923,13 +927,44 @@ static void cdns_dsi_bridge_pre_enable(struct drm_bridge *bridge)
 	cdns_dsi_hs_init(dsi);
 }
 
+static u32 *cdns_dsi_bridge_get_input_bus_fmts(struct drm_bridge *bridge,
+					       struct drm_bridge_state *bridge_state,
+					       struct drm_crtc_state *crtc_state,
+					       struct drm_connector_state *conn_state,
+					       u32 output_fmt,
+					       unsigned int *num_input_fmts)
+{
+	struct cdns_dsi_input *input = bridge_to_cdns_dsi_input(bridge);
+	struct cdns_dsi *dsi = input_to_dsi(input);
+	struct cdns_dsi_output *output = &dsi->output;
+	u32 *input_fmts;
+
+	*num_input_fmts = 0;
+
+	input_fmts = kzalloc(sizeof(*input_fmts), GFP_KERNEL);
+	if (!input_fmts)
+		return NULL;
+
+	input_fmts[0] = drm_mipi_dsi_get_input_bus_fmt(output->dev->format);
+	if (!input_fmts[0])
+		return NULL;
+
+	*num_input_fmts = 1;
+
+	return input_fmts;
+}
+
 static const struct drm_bridge_funcs cdns_dsi_bridge_funcs = {
 	.attach = cdns_dsi_bridge_attach,
 	.mode_valid = cdns_dsi_bridge_mode_valid,
-	.disable = cdns_dsi_bridge_disable,
-	.pre_enable = cdns_dsi_bridge_pre_enable,
-	.enable = cdns_dsi_bridge_enable,
-	.post_disable = cdns_dsi_bridge_post_disable,
+	.atomic_disable = cdns_dsi_bridge_atomic_disable,
+	.atomic_pre_enable = cdns_dsi_bridge_atomic_pre_enable,
+	.atomic_enable = cdns_dsi_bridge_atomic_enable,
+	.atomic_post_disable = cdns_dsi_bridge_atomic_post_disable,
+	.atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
+	.atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
+	.atomic_reset = drm_atomic_helper_bridge_reset,
+	.atomic_get_input_bus_fmts = cdns_dsi_bridge_get_input_bus_fmts,
 };
 
 static int cdns_dsi_attach(struct mipi_dsi_host *host,
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH v5 10/13] drm/bridge: cdns-dsi: Move DSI mode check to _atomic_check()
  2024-10-19 20:05 ` [PATCH v5 08/13] drm/mipi-dsi: Add helper to find input format Aradhya Bhatia
  2024-10-19 20:05   ` [PATCH v5 09/13] drm/bridge: cdns-dsi: Support atomic bridge APIs Aradhya Bhatia
@ 2024-10-19 20:05   ` Aradhya Bhatia
  2024-10-20 11:42     ` Dmitry Baryshkov
  2024-10-19 20:05   ` [PATCH v5 11/13] drm/atomic-helper: Separate out Encoder-Bridge enable and disable Aradhya Bhatia
                     ` (2 subsequent siblings)
  4 siblings, 1 reply; 26+ messages in thread
From: Aradhya Bhatia @ 2024-10-19 20:05 UTC (permalink / raw)
  To: Tomi Valkeinen, Dmitry Baryshkov, Laurent Pinchart, Andrzej Hajda,
	Neil Armstrong, Robert Foss, Jonas Karlman, Jernej Skrabec,
	Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
	Simona Vetter
  Cc: Dominik Haller, Sam Ravnborg, Kieran Bingham, Nishanth Menon,
	Vignesh Raghavendra, Devarsh Thakkar, Praneeth Bajjuri,
	Udit Kumar, Jayesh Choudhary, DRI Development List,
	Linux Kernel List, Aradhya Bhatia

From: Aradhya Bhatia <a-bhatia1@ti.com>

At present, the DSI mode configuration check happens during the
_atomic_enable() phase, which is not really the best place for this.
Moreover, if the mode is not valid, the driver gives a warning and
continues the hardware configuration.

Move the DSI mode configuration check to _atomic_check() instead, which
can properly report back any invalid mode, before the _enable phase even
begins.

Signed-off-by: Aradhya Bhatia <a-bhatia1@ti.com>
Signed-off-by: Aradhya Bhatia <aradhya.bhatia@linux.dev>
---
 drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c | 18 +++++++++++++++---
 drivers/gpu/drm/bridge/cadence/cdns-dsi-core.h |  1 +
 2 files changed, 16 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
index 7341e609dc8b..79d8c2264c14 100644
--- a/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
+++ b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
@@ -769,7 +769,7 @@ static void cdns_dsi_bridge_atomic_enable(struct drm_bridge *bridge,
 	struct drm_display_mode *mode;
 	struct phy_configure_opts_mipi_dphy *phy_cfg = &output->phy_opts.mipi_dphy;
 	unsigned long tx_byte_period;
-	struct cdns_dsi_cfg dsi_cfg;
+	struct cdns_dsi_cfg dsi_cfg = dsi->dsi_cfg;
 	u32 tmp, reg_wakeup, div, status;
 	int nlanes;
 
@@ -782,8 +782,6 @@ static void cdns_dsi_bridge_atomic_enable(struct drm_bridge *bridge,
 	mode = &bridge->encoder->crtc->state->adjusted_mode;
 	nlanes = output->dev->lanes;
 
-	WARN_ON_ONCE(cdns_dsi_check_conf(dsi, mode, &dsi_cfg, false));
-
 	cdns_dsi_init_link(dsi);
 	cdns_dsi_hs_init(dsi);
 
@@ -954,6 +952,19 @@ static u32 *cdns_dsi_bridge_get_input_bus_fmts(struct drm_bridge *bridge,
 	return input_fmts;
 }
 
+static int cdns_dsi_bridge_atomic_check(struct drm_bridge *bridge,
+					struct drm_bridge_state *bridge_state,
+					struct drm_crtc_state *crtc_state,
+					struct drm_connector_state *conn_state)
+{
+	struct cdns_dsi_input *input = bridge_to_cdns_dsi_input(bridge);
+	struct cdns_dsi *dsi = input_to_dsi(input);
+	struct drm_display_mode *mode = &crtc_state->mode;
+	struct cdns_dsi_cfg *dsi_cfg = &dsi->dsi_cfg;
+
+	return cdns_dsi_check_conf(dsi, mode, dsi_cfg, false);
+}
+
 static const struct drm_bridge_funcs cdns_dsi_bridge_funcs = {
 	.attach = cdns_dsi_bridge_attach,
 	.mode_valid = cdns_dsi_bridge_mode_valid,
@@ -961,6 +972,7 @@ static const struct drm_bridge_funcs cdns_dsi_bridge_funcs = {
 	.atomic_pre_enable = cdns_dsi_bridge_atomic_pre_enable,
 	.atomic_enable = cdns_dsi_bridge_atomic_enable,
 	.atomic_post_disable = cdns_dsi_bridge_atomic_post_disable,
+	.atomic_check = cdns_dsi_bridge_atomic_check,
 	.atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
 	.atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
 	.atomic_reset = drm_atomic_helper_bridge_reset,
diff --git a/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.h b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.h
index 5db5dbbbcaad..b785df45bc59 100644
--- a/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.h
+++ b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.h
@@ -77,6 +77,7 @@ struct cdns_dsi {
 	bool link_initialized;
 	bool phy_initialized;
 	struct phy *dphy;
+	struct cdns_dsi_cfg dsi_cfg;
 };
 
 #endif /* !__CDNS_DSI_H__ */
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH v5 11/13] drm/atomic-helper: Separate out Encoder-Bridge enable and disable
  2024-10-19 20:05 ` [PATCH v5 08/13] drm/mipi-dsi: Add helper to find input format Aradhya Bhatia
  2024-10-19 20:05   ` [PATCH v5 09/13] drm/bridge: cdns-dsi: Support atomic bridge APIs Aradhya Bhatia
  2024-10-19 20:05   ` [PATCH v5 10/13] drm/bridge: cdns-dsi: Move DSI mode check to _atomic_check() Aradhya Bhatia
@ 2024-10-19 20:05   ` Aradhya Bhatia
  2024-10-20 11:47     ` Dmitry Baryshkov
  2024-10-19 20:05   ` [PATCH v5 12/13] drm/atomic-helper: Re-order bridge chain pre-enable and post-disable Aradhya Bhatia
  2024-10-19 20:05   ` [PATCH v5 13/13] drm/bridge: cdns-dsi: Use pre_enable/post_disable to enable/disable Aradhya Bhatia
  4 siblings, 1 reply; 26+ messages in thread
From: Aradhya Bhatia @ 2024-10-19 20:05 UTC (permalink / raw)
  To: Tomi Valkeinen, Dmitry Baryshkov, Laurent Pinchart, Andrzej Hajda,
	Neil Armstrong, Robert Foss, Jonas Karlman, Jernej Skrabec,
	Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
	Simona Vetter
  Cc: Dominik Haller, Sam Ravnborg, Kieran Bingham, Nishanth Menon,
	Vignesh Raghavendra, Devarsh Thakkar, Praneeth Bajjuri,
	Udit Kumar, Jayesh Choudhary, DRI Development List,
	Linux Kernel List, Aradhya Bhatia

From: Aradhya Bhatia <a-bhatia1@ti.com>

The way any singular display pipeline, in need of a modeset, gets
enabled is as follows -

	CRTC Enable
	All Bridge Pre-Enable
	Encoder Enable
	All Bridge Enable

- and the disable path is exactly the reverse of this.

The CRTC enable/disable occurs by looping over the old and new CRTC
states, while the bridge pre-enable, encoder enable, and bridge enable
occur by looping through the new connector states of the display
pipelines.

At the moment, the encoder and bridge operations are grouped together
and occur under the same loops.

Separate out the enable/disable loops of the encoder and bridge
operations into a different function, to make way for the re-ordering of
the enable and disable sequence of all these display elements.

This patch doesn't alter in any way the ordering of CRTC/encoder/bridge
enable and disable, but merely helps to cleanly set up for the next
patch and to make sure that the bisectibility remains intact.

Signed-off-by: Aradhya Bhatia <a-bhatia1@ti.com>
Signed-off-by: Aradhya Bhatia <aradhya.bhatia@linux.dev>
---
 drivers/gpu/drm/drm_atomic_helper.c | 97 +++++++++++++++++------------
 1 file changed, 57 insertions(+), 40 deletions(-)

diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
index 5186d2114a50..7741fbcc8fc7 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -1122,11 +1122,10 @@ crtc_needs_disable(struct drm_crtc_state *old_state,
 }
 
 static void
-disable_outputs(struct drm_device *dev, struct drm_atomic_state *old_state)
+encoder_bridge_chain_disable(struct drm_device *dev, struct drm_atomic_state *old_state)
 {
 	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;
 
@@ -1189,6 +1188,16 @@ disable_outputs(struct drm_device *dev, struct drm_atomic_state *old_state)
 
 		drm_atomic_bridge_chain_post_disable(bridge, old_state);
 	}
+}
+
+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;
+
+	encoder_bridge_chain_disable(dev, old_state);
 
 	for_each_oldnew_crtc_in_state(old_state, crtc, old_crtc_state, new_crtc_state, i) {
 		const struct drm_crtc_helper_funcs *funcs;
@@ -1445,6 +1454,51 @@ static void drm_atomic_helper_commit_writebacks(struct drm_device *dev,
 	}
 }
 
+static void
+encoder_bridge_chain_enable(struct drm_device *dev, struct drm_atomic_state *old_state)
+{
+	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 = new_conn_state->best_encoder;
+		funcs = 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 = 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);
+	}
+}
+
 /**
  * drm_atomic_helper_commit_modeset_enables - modeset commit to enable outputs
  * @dev: DRM device
@@ -1465,8 +1519,6 @@ void drm_atomic_helper_commit_modeset_enables(struct 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;
 
 	for_each_oldnew_crtc_in_state(old_state, crtc, old_crtc_state, new_crtc_state, i) {
@@ -1491,42 +1543,7 @@ void drm_atomic_helper_commit_modeset_enables(struct drm_device *dev,
 		}
 	}
 
-	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 = new_conn_state->best_encoder;
-		funcs = 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 = 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);
-	}
+	encoder_bridge_chain_enable(dev, old_state);
 
 	drm_atomic_helper_commit_writebacks(dev, old_state);
 }
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH v5 12/13] drm/atomic-helper: Re-order bridge chain pre-enable and post-disable
  2024-10-19 20:05 ` [PATCH v5 08/13] drm/mipi-dsi: Add helper to find input format Aradhya Bhatia
                     ` (2 preceding siblings ...)
  2024-10-19 20:05   ` [PATCH v5 11/13] drm/atomic-helper: Separate out Encoder-Bridge enable and disable Aradhya Bhatia
@ 2024-10-19 20:05   ` Aradhya Bhatia
  2024-10-20 11:58     ` Dmitry Baryshkov
  2024-10-19 20:05   ` [PATCH v5 13/13] drm/bridge: cdns-dsi: Use pre_enable/post_disable to enable/disable Aradhya Bhatia
  4 siblings, 1 reply; 26+ messages in thread
From: Aradhya Bhatia @ 2024-10-19 20:05 UTC (permalink / raw)
  To: Tomi Valkeinen, Dmitry Baryshkov, Laurent Pinchart, Andrzej Hajda,
	Neil Armstrong, Robert Foss, Jonas Karlman, Jernej Skrabec,
	Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
	Simona Vetter
  Cc: Dominik Haller, Sam Ravnborg, Kieran Bingham, Nishanth Menon,
	Vignesh Raghavendra, Devarsh Thakkar, Praneeth Bajjuri,
	Udit Kumar, Jayesh Choudhary, DRI Development List,
	Linux Kernel List, Aradhya Bhatia

From: Aradhya Bhatia <a-bhatia1@ti.com>

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 <a-bhatia1@ti.com>
Signed-off-by: Aradhya Bhatia <aradhya.bhatia@linux.dev>
---
 drivers/gpu/drm/drm_atomic_helper.c | 102 ++++++++++++++++++----------
 include/drm/drm_atomic_helper.h     |   5 ++
 2 files changed, 71 insertions(+), 36 deletions(-)

diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
index 7741fbcc8fc7..6ebd869df79b 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -1122,7 +1122,8 @@ crtc_needs_disable(struct drm_crtc_state *old_state,
 }
 
 static void
-encoder_bridge_chain_disable(struct drm_device *dev, struct drm_atomic_state *old_state)
+encoder_bridge_chain_disable(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 *old_conn_state, *new_conn_state;
@@ -1162,31 +1163,43 @@ encoder_bridge_chain_disable(struct drm_device *dev, struct drm_atomic_state *ol
 		if (WARN_ON(!encoder))
 			continue;
 
-		funcs = 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 = drm_bridge_chain_get_first_bridge(encoder);
-		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);
-		}
+		switch (op_type) {
+		case DRM_BRIDGE_ENABLE_DISABLE:
+			funcs = 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);
+			}
 
-		drm_atomic_bridge_chain_post_disable(bridge, old_state);
+			break;
+
+		case DRM_BRIDGE_PRE_ENABLE_POST_DISABLE:
+			drm_atomic_bridge_chain_post_disable(bridge, old_state);
+			break;
+
+		default:
+			drm_err(dev, "Unrecognized Encoder/Bridge Operation (%d).\n", op_type);
+			break;
+		}
 	}
 }
 
@@ -1197,7 +1210,7 @@ disable_outputs(struct drm_device *dev, struct drm_atomic_state *old_state)
 	struct drm_crtc_state *old_crtc_state, *new_crtc_state;
 	int i;
 
-	encoder_bridge_chain_disable(dev, old_state);
+	encoder_bridge_chain_disable(dev, old_state, DRM_BRIDGE_ENABLE_DISABLE);
 
 	for_each_oldnew_crtc_in_state(old_state, crtc, old_crtc_state, new_crtc_state, i) {
 		const struct drm_crtc_helper_funcs *funcs;
@@ -1243,6 +1256,8 @@ disable_outputs(struct drm_device *dev, struct drm_atomic_state *old_state)
 		if (ret == 0)
 			drm_crtc_vblank_put(crtc);
 	}
+
+	encoder_bridge_chain_disable(dev, old_state, DRM_BRIDGE_PRE_ENABLE_POST_DISABLE);
 }
 
 /**
@@ -1455,7 +1470,8 @@ static void drm_atomic_helper_commit_writebacks(struct drm_device *dev,
 }
 
 static void
-encoder_bridge_chain_enable(struct drm_device *dev, struct drm_atomic_state *old_state)
+encoder_bridge_chain_enable(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;
@@ -1474,28 +1490,40 @@ encoder_bridge_chain_enable(struct drm_device *dev, struct drm_atomic_state *old
 			continue;
 
 		encoder = new_conn_state->best_encoder;
-		funcs = 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 = 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);
-		}
+		switch (op_type) {
+		case DRM_BRIDGE_PRE_ENABLE_POST_DISABLE:
+			drm_atomic_bridge_chain_pre_enable(bridge, old_state);
+			break;
+
+		case DRM_BRIDGE_ENABLE_DISABLE:
+			funcs = encoder->helper_private;
+
+			drm_dbg_atomic(dev, "enabling [ENCODER:%d:%s]\n",
+				       encoder->base.id, encoder->name);
 
-		drm_atomic_bridge_chain_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);
+			break;
+
+		default:
+			drm_err(dev, "Unrecognized Encoder/Bridge Operation (%d).\n", op_type);
+			break;
+		}
 	}
 }
 
@@ -1521,6 +1549,8 @@ void drm_atomic_helper_commit_modeset_enables(struct drm_device *dev,
 	struct drm_crtc_state *new_crtc_state;
 	int i;
 
+	encoder_bridge_chain_enable(dev, old_state, DRM_BRIDGE_PRE_ENABLE_POST_DISABLE);
+
 	for_each_oldnew_crtc_in_state(old_state, crtc, old_crtc_state, new_crtc_state, i) {
 		const struct drm_crtc_helper_funcs *funcs;
 
@@ -1543,7 +1573,7 @@ void drm_atomic_helper_commit_modeset_enables(struct drm_device *dev,
 		}
 	}
 
-	encoder_bridge_chain_enable(dev, old_state);
+	encoder_bridge_chain_enable(dev, old_state, DRM_BRIDGE_ENABLE_DISABLE);
 
 	drm_atomic_helper_commit_writebacks(dev, old_state);
 }
diff --git a/include/drm/drm_atomic_helper.h b/include/drm/drm_atomic_helper.h
index 9aa0a05aa072..92a5812adc6c 100644
--- a/include/drm/drm_atomic_helper.h
+++ b/include/drm/drm_atomic_helper.h
@@ -43,6 +43,11 @@
  */
 #define DRM_PLANE_NO_SCALING (1<<16)
 
+enum bridge_chain_operation_type {
+	DRM_BRIDGE_PRE_ENABLE_POST_DISABLE,
+	DRM_BRIDGE_ENABLE_DISABLE,
+};
+
 struct drm_atomic_state;
 struct drm_private_obj;
 struct drm_private_state;
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH v5 13/13] drm/bridge: cdns-dsi: Use pre_enable/post_disable to enable/disable
  2024-10-19 20:05 ` [PATCH v5 08/13] drm/mipi-dsi: Add helper to find input format Aradhya Bhatia
                     ` (3 preceding siblings ...)
  2024-10-19 20:05   ` [PATCH v5 12/13] drm/atomic-helper: Re-order bridge chain pre-enable and post-disable Aradhya Bhatia
@ 2024-10-19 20:05   ` Aradhya Bhatia
  2024-10-20 11:57     ` Dmitry Baryshkov
  4 siblings, 1 reply; 26+ messages in thread
From: Aradhya Bhatia @ 2024-10-19 20:05 UTC (permalink / raw)
  To: Tomi Valkeinen, Dmitry Baryshkov, Laurent Pinchart, Andrzej Hajda,
	Neil Armstrong, Robert Foss, Jonas Karlman, Jernej Skrabec,
	Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
	Simona Vetter
  Cc: Dominik Haller, Sam Ravnborg, Kieran Bingham, Nishanth Menon,
	Vignesh Raghavendra, Devarsh Thakkar, Praneeth Bajjuri,
	Udit Kumar, Jayesh Choudhary, DRI Development List,
	Linux Kernel List, Aradhya Bhatia

From: Aradhya Bhatia <a-bhatia1@ti.com>

The cdns-dsi controller requires that it be turned on completely before
the input DPI's source has begun streaming[0]. Not having that, allows
for a small window before cdns-dsi enable and after cdns-dsi disable
where the previous entity (in this case tidss's videoport) to continue
streaming DPI video signals. This small window where cdns-dsi is
disabled but is still receiving signals causes the input FIFO of
cdns-dsi to get corrupted. This causes the colors to shift on the output
display. The colors can either shift by one color component (R->G, G->B,
B->R), or by two color components (R->B, G->R, B->G).

Since tidss's videoport starts streaming via crtc enable hooks, we need
cdns-dsi to be up and running before that. Now that the bridges are
pre_enabled before crtc is enabled, and post_disabled after crtc is
disabled, use the pre_enable and post_disable hooks to get cdns-dsi
ready and running before the tidss videoport to get pass the color shift
issues.

[0]: See section 12.6.5.7.3 "Start-up Procedure" in J721E SoC TRM
     TRM Link: http://www.ti.com/lit/pdf/spruil1

Reviewed-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
Signed-off-by: Aradhya Bhatia <a-bhatia1@ti.com>
Signed-off-by: Aradhya Bhatia <aradhya.bhatia@linux.dev>
---
 .../gpu/drm/bridge/cadence/cdns-dsi-core.c    | 62 ++++++++++---------
 1 file changed, 34 insertions(+), 28 deletions(-)

diff --git a/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
index 79d8c2264c14..dfeb53841ebc 100644
--- a/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
+++ b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
@@ -658,13 +658,28 @@ cdns_dsi_bridge_mode_valid(struct drm_bridge *bridge,
 	return MODE_OK;
 }
 
-static void cdns_dsi_bridge_atomic_disable(struct drm_bridge *bridge,
-					   struct drm_bridge_state *old_bridge_state)
+static void cdns_dsi_bridge_atomic_post_disable(struct drm_bridge *bridge,
+						struct drm_bridge_state *old_bridge_state)
 {
 	struct cdns_dsi_input *input = bridge_to_cdns_dsi_input(bridge);
 	struct cdns_dsi *dsi = input_to_dsi(input);
 	u32 val;
 
+	/*
+	 * The cdns-dsi controller needs to be disabled after it's DPI source
+	 * has stopped streaming. If this is not followed, there is a brief
+	 * window before DPI source is disabled and after cdns-dsi controller
+	 * has been disabled where the DPI stream is still on, but the cdns-dsi
+	 * controller is not ready anymore to accept the incoming signals. This
+	 * is one of the reasons why a shift in pixel colors is observed on
+	 * displays that have cdns-dsi as one of the bridges.
+	 *
+	 * To mitigate this, disable this bridge from the bridge post_disable()
+	 * hook, instead of the bridge _disable() hook. The bridge post_disable()
+	 * hook gets called after the CRTC disable, where often many DPI sources
+	 * disable their streams.
+	 */
+
 	val = readl(dsi->regs + MCTL_MAIN_DATA_CTL);
 	val &= ~(IF_VID_SELECT_MASK | IF_VID_MODE | VID_EN | HOST_EOT_GEN |
 		 DISP_EOT_GEN);
@@ -683,15 +698,6 @@ static void cdns_dsi_bridge_atomic_disable(struct drm_bridge *bridge,
 	pm_runtime_put(dsi->base.dev);
 }
 
-static void cdns_dsi_bridge_atomic_post_disable(struct drm_bridge *bridge,
-						struct drm_bridge_state *old_bridge_state)
-{
-	struct cdns_dsi_input *input = bridge_to_cdns_dsi_input(bridge);
-	struct cdns_dsi *dsi = input_to_dsi(input);
-
-	pm_runtime_put(dsi->base.dev);
-}
-
 static void cdns_dsi_hs_init(struct cdns_dsi *dsi)
 {
 	struct cdns_dsi_output *output = &dsi->output;
@@ -760,8 +766,8 @@ static void cdns_dsi_init_link(struct cdns_dsi *dsi)
 	dsi->link_initialized = true;
 }
 
-static void cdns_dsi_bridge_atomic_enable(struct drm_bridge *bridge,
-					  struct drm_bridge_state *old_bridge_state)
+static void cdns_dsi_bridge_atomic_pre_enable(struct drm_bridge *bridge,
+					      struct drm_bridge_state *old_bridge_state)
 {
 	struct cdns_dsi_input *input = bridge_to_cdns_dsi_input(bridge);
 	struct cdns_dsi *dsi = input_to_dsi(input);
@@ -776,6 +782,21 @@ static void cdns_dsi_bridge_atomic_enable(struct drm_bridge *bridge,
 	if (WARN_ON(pm_runtime_get_sync(dsi->base.dev) < 0))
 		return;
 
+	/*
+	 * The cdns-dsi controller needs to be enabled before it's DPI source
+	 * has begun streaming. If this is not followed, there is a brief window
+	 * after DPI source enable and before cdns-dsi controller enable where
+	 * the DPI stream is on, but the cdns-dsi controller is not ready to
+	 * accept the incoming signals. This is one of the reasons why a shift
+	 * in pixel colors is observed on displays that have cdns-dsi as one of
+	 * the bridges.
+	 *
+	 * To mitigate this, enable this bridge from the bridge pre_enable()
+	 * hook, instead of the bridge _enable() hook. The bridge pre_enable()
+	 * hook gets called before the CRTC enable, where often many DPI sources
+	 * enable their streams.
+	 */
+
 	if (dsi->platform_ops && dsi->platform_ops->enable)
 		dsi->platform_ops->enable(dsi);
 
@@ -912,19 +933,6 @@ static void cdns_dsi_bridge_atomic_enable(struct drm_bridge *bridge,
 	writel(tmp, dsi->regs + MCTL_MAIN_EN);
 }
 
-static void cdns_dsi_bridge_atomic_pre_enable(struct drm_bridge *bridge,
-					      struct drm_bridge_state *old_bridge_state)
-{
-	struct cdns_dsi_input *input = bridge_to_cdns_dsi_input(bridge);
-	struct cdns_dsi *dsi = input_to_dsi(input);
-
-	if (WARN_ON(pm_runtime_get_sync(dsi->base.dev) < 0))
-		return;
-
-	cdns_dsi_init_link(dsi);
-	cdns_dsi_hs_init(dsi);
-}
-
 static u32 *cdns_dsi_bridge_get_input_bus_fmts(struct drm_bridge *bridge,
 					       struct drm_bridge_state *bridge_state,
 					       struct drm_crtc_state *crtc_state,
@@ -968,9 +976,7 @@ static int cdns_dsi_bridge_atomic_check(struct drm_bridge *bridge,
 static const struct drm_bridge_funcs cdns_dsi_bridge_funcs = {
 	.attach = cdns_dsi_bridge_attach,
 	.mode_valid = cdns_dsi_bridge_mode_valid,
-	.atomic_disable = cdns_dsi_bridge_atomic_disable,
 	.atomic_pre_enable = cdns_dsi_bridge_atomic_pre_enable,
-	.atomic_enable = cdns_dsi_bridge_atomic_enable,
 	.atomic_post_disable = cdns_dsi_bridge_atomic_post_disable,
 	.atomic_check = cdns_dsi_bridge_atomic_check,
 	.atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* Re: [PATCH v5 02/13] drm/bridge: cdns-dsi: Move to devm_drm_of_get_bridge()
  2024-10-19 19:54 ` [PATCH v5 02/13] drm/bridge: cdns-dsi: Move to devm_drm_of_get_bridge() Aradhya Bhatia
@ 2024-10-20 10:49   ` Dmitry Baryshkov
  0 siblings, 0 replies; 26+ messages in thread
From: Dmitry Baryshkov @ 2024-10-20 10:49 UTC (permalink / raw)
  To: Aradhya Bhatia
  Cc: Tomi Valkeinen, Laurent Pinchart, Andrzej Hajda, Neil Armstrong,
	Robert Foss, Jonas Karlman, Jernej Skrabec, Maarten Lankhorst,
	Maxime Ripard, Thomas Zimmermann, David Airlie, Simona Vetter,
	Dominik Haller, Sam Ravnborg, Kieran Bingham, Nishanth Menon,
	Vignesh Raghavendra, Devarsh Thakkar, Praneeth Bajjuri,
	Udit Kumar, Jayesh Choudhary, DRI Development List,
	Linux Kernel List

On Sun, Oct 20, 2024 at 01:24:00AM +0530, Aradhya Bhatia wrote:
> From: Aradhya Bhatia <a-bhatia1@ti.com>
> 
> Instead of manually finding the next bridge/panel, and maintaining the
> panel-bridge (in-case the next entity is a panel), switch to using the
> automatically managing devm_drm_of_get_bridge() API.
> 
> Drop the drm_panel support completely from the driver while at it.
> 
> Reviewed-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
> Signed-off-by: Aradhya Bhatia <a-bhatia1@ti.com>
> Signed-off-by: Aradhya Bhatia <aradhya.bhatia@linux.dev>
> ---

Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>

-- 
With best wishes
Dmitry

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH v5 03/13] drm/bridge: cdns-dsi: Fix Phy _init() and _exit()
  2024-10-19 19:54 ` [PATCH v5 03/13] drm/bridge: cdns-dsi: Fix Phy _init() and _exit() Aradhya Bhatia
@ 2024-10-20 11:34   ` Dmitry Baryshkov
  0 siblings, 0 replies; 26+ messages in thread
From: Dmitry Baryshkov @ 2024-10-20 11:34 UTC (permalink / raw)
  To: Aradhya Bhatia
  Cc: Tomi Valkeinen, Laurent Pinchart, Andrzej Hajda, Neil Armstrong,
	Robert Foss, Jonas Karlman, Jernej Skrabec, Maarten Lankhorst,
	Maxime Ripard, Thomas Zimmermann, David Airlie, Simona Vetter,
	Dominik Haller, Sam Ravnborg, Kieran Bingham, Nishanth Menon,
	Vignesh Raghavendra, Devarsh Thakkar, Praneeth Bajjuri,
	Udit Kumar, Jayesh Choudhary, DRI Development List,
	Linux Kernel List

On Sun, Oct 20, 2024 at 01:24:01AM +0530, Aradhya Bhatia wrote:
> From: Aradhya Bhatia <a-bhatia1@ti.com>
> 
> Initialize the Phy during the cdns-dsi _resume(), and de-initialize it
> during the _suspend().
> 
> Also power-off the Phy from bridge_disable.

Please describe why, not what. Especially, if it is considered a fix.

> 
> Fixes: fced5a364dee ("drm/bridge: cdns: Convert to phy framework")
> Signed-off-by: Aradhya Bhatia <a-bhatia1@ti.com>
> Signed-off-by: Aradhya Bhatia <aradhya.bhatia@linux.dev>
> ---
>  drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c | 10 ++++++++--
>  1 file changed, 8 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
> index 5159c3f0853e..d89c32bae2b9 100644
> --- a/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
> +++ b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
> @@ -672,6 +672,10 @@ static void cdns_dsi_bridge_disable(struct drm_bridge *bridge)
>  	if (dsi->platform_ops && dsi->platform_ops->disable)
>  		dsi->platform_ops->disable(dsi);
>  
> +	phy_power_off(dsi->dphy);
> +	dsi->link_initialized = false;
> +	dsi->phy_initialized = false;
> +
>  	pm_runtime_put(dsi->base.dev);
>  }
>  
> @@ -698,7 +702,6 @@ static void cdns_dsi_hs_init(struct cdns_dsi *dsi)
>  	       DPHY_CMN_PDN | DPHY_PLL_PDN,
>  	       dsi->regs + MCTL_DPHY_CFG0);
>  
> -	phy_init(dsi->dphy);

This moves the call order, moving phy_init() before
platform_ops->enable(). It should be documented with the clear pointer
that it considered to be safe.

>  	phy_set_mode(dsi->dphy, PHY_MODE_MIPI_DPHY);
>  	phy_configure(dsi->dphy, &output->phy_opts);
>  	phy_power_on(dsi->dphy);
> @@ -1120,6 +1123,8 @@ static int __maybe_unused cdns_dsi_resume(struct device *dev)
>  	clk_prepare_enable(dsi->dsi_p_clk);
>  	clk_prepare_enable(dsi->dsi_sys_clk);
>  
> +	phy_init(dsi->dphy);
> +
>  	return 0;
>  }
>  
> @@ -1127,10 +1132,11 @@ static int __maybe_unused cdns_dsi_suspend(struct device *dev)
>  {
>  	struct cdns_dsi *dsi = dev_get_drvdata(dev);
>  
> +	phy_exit(dsi->dphy);
> +
>  	clk_disable_unprepare(dsi->dsi_sys_clk);
>  	clk_disable_unprepare(dsi->dsi_p_clk);
>  	reset_control_assert(dsi->dsi_p_rst);
> -	dsi->link_initialized = false;
>  	return 0;
>  }
>  
> -- 
> 2.34.1
> 

-- 
With best wishes
Dmitry

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH v5 10/13] drm/bridge: cdns-dsi: Move DSI mode check to _atomic_check()
  2024-10-19 20:05   ` [PATCH v5 10/13] drm/bridge: cdns-dsi: Move DSI mode check to _atomic_check() Aradhya Bhatia
@ 2024-10-20 11:42     ` Dmitry Baryshkov
  0 siblings, 0 replies; 26+ messages in thread
From: Dmitry Baryshkov @ 2024-10-20 11:42 UTC (permalink / raw)
  To: Aradhya Bhatia
  Cc: Tomi Valkeinen, Laurent Pinchart, Andrzej Hajda, Neil Armstrong,
	Robert Foss, Jonas Karlman, Jernej Skrabec, Maarten Lankhorst,
	Maxime Ripard, Thomas Zimmermann, David Airlie, Simona Vetter,
	Dominik Haller, Sam Ravnborg, Kieran Bingham, Nishanth Menon,
	Vignesh Raghavendra, Devarsh Thakkar, Praneeth Bajjuri,
	Udit Kumar, Jayesh Choudhary, DRI Development List,
	Linux Kernel List

On Sun, Oct 20, 2024 at 01:35:27AM +0530, Aradhya Bhatia wrote:
> From: Aradhya Bhatia <a-bhatia1@ti.com>
> 
> At present, the DSI mode configuration check happens during the
> _atomic_enable() phase, which is not really the best place for this.
> Moreover, if the mode is not valid, the driver gives a warning and
> continues the hardware configuration.
> 
> Move the DSI mode configuration check to _atomic_check() instead, which
> can properly report back any invalid mode, before the _enable phase even
> begins.
> 
> Signed-off-by: Aradhya Bhatia <a-bhatia1@ti.com>
> Signed-off-by: Aradhya Bhatia <aradhya.bhatia@linux.dev>
> ---
>  drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c | 18 +++++++++++++++---
>  drivers/gpu/drm/bridge/cadence/cdns-dsi-core.h |  1 +
>  2 files changed, 16 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
> index 7341e609dc8b..79d8c2264c14 100644
> --- a/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
> +++ b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
> @@ -769,7 +769,7 @@ static void cdns_dsi_bridge_atomic_enable(struct drm_bridge *bridge,
>  	struct drm_display_mode *mode;
>  	struct phy_configure_opts_mipi_dphy *phy_cfg = &output->phy_opts.mipi_dphy;
>  	unsigned long tx_byte_period;
> -	struct cdns_dsi_cfg dsi_cfg;
> +	struct cdns_dsi_cfg dsi_cfg = dsi->dsi_cfg;
>  	u32 tmp, reg_wakeup, div, status;
>  	int nlanes;
>  
> @@ -782,8 +782,6 @@ static void cdns_dsi_bridge_atomic_enable(struct drm_bridge *bridge,
>  	mode = &bridge->encoder->crtc->state->adjusted_mode;
>  	nlanes = output->dev->lanes;
>  
> -	WARN_ON_ONCE(cdns_dsi_check_conf(dsi, mode, &dsi_cfg, false));
> -
>  	cdns_dsi_init_link(dsi);
>  	cdns_dsi_hs_init(dsi);
>  
> @@ -954,6 +952,19 @@ static u32 *cdns_dsi_bridge_get_input_bus_fmts(struct drm_bridge *bridge,
>  	return input_fmts;
>  }
>  
> +static int cdns_dsi_bridge_atomic_check(struct drm_bridge *bridge,
> +					struct drm_bridge_state *bridge_state,
> +					struct drm_crtc_state *crtc_state,
> +					struct drm_connector_state *conn_state)
> +{
> +	struct cdns_dsi_input *input = bridge_to_cdns_dsi_input(bridge);
> +	struct cdns_dsi *dsi = input_to_dsi(input);
> +	struct drm_display_mode *mode = &crtc_state->mode;
> +	struct cdns_dsi_cfg *dsi_cfg = &dsi->dsi_cfg;

This makes .atomic_check store data in the non-state structure. However
it is not guaranteed that each atomic_check() will result in the
atomic_commit(). So in addition to moving the check to the
atomic_check() callback you also have to move the cdns_dsi_cfg and all
other structures written during the check to the new structure, wrapping
drm_bridge_state.

> +
> +	return cdns_dsi_check_conf(dsi, mode, dsi_cfg, false);
> +}
> +
>  static const struct drm_bridge_funcs cdns_dsi_bridge_funcs = {
>  	.attach = cdns_dsi_bridge_attach,
>  	.mode_valid = cdns_dsi_bridge_mode_valid,
> @@ -961,6 +972,7 @@ static const struct drm_bridge_funcs cdns_dsi_bridge_funcs = {
>  	.atomic_pre_enable = cdns_dsi_bridge_atomic_pre_enable,
>  	.atomic_enable = cdns_dsi_bridge_atomic_enable,
>  	.atomic_post_disable = cdns_dsi_bridge_atomic_post_disable,
> +	.atomic_check = cdns_dsi_bridge_atomic_check,
>  	.atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
>  	.atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
>  	.atomic_reset = drm_atomic_helper_bridge_reset,
> diff --git a/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.h b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.h
> index 5db5dbbbcaad..b785df45bc59 100644
> --- a/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.h
> +++ b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.h
> @@ -77,6 +77,7 @@ struct cdns_dsi {
>  	bool link_initialized;
>  	bool phy_initialized;
>  	struct phy *dphy;
> +	struct cdns_dsi_cfg dsi_cfg;
>  };
>  
>  #endif /* !__CDNS_DSI_H__ */
> -- 
> 2.34.1
> 

-- 
With best wishes
Dmitry

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH v5 11/13] drm/atomic-helper: Separate out Encoder-Bridge enable and disable
  2024-10-19 20:05   ` [PATCH v5 11/13] drm/atomic-helper: Separate out Encoder-Bridge enable and disable Aradhya Bhatia
@ 2024-10-20 11:47     ` Dmitry Baryshkov
  0 siblings, 0 replies; 26+ messages in thread
From: Dmitry Baryshkov @ 2024-10-20 11:47 UTC (permalink / raw)
  To: Aradhya Bhatia
  Cc: Tomi Valkeinen, Laurent Pinchart, Andrzej Hajda, Neil Armstrong,
	Robert Foss, Jonas Karlman, Jernej Skrabec, Maarten Lankhorst,
	Maxime Ripard, Thomas Zimmermann, David Airlie, Simona Vetter,
	Dominik Haller, Sam Ravnborg, Kieran Bingham, Nishanth Menon,
	Vignesh Raghavendra, Devarsh Thakkar, Praneeth Bajjuri,
	Udit Kumar, Jayesh Choudhary, DRI Development List,
	Linux Kernel List

On Sun, Oct 20, 2024 at 01:35:28AM +0530, Aradhya Bhatia wrote:
> From: Aradhya Bhatia <a-bhatia1@ti.com>
> 
> The way any singular display pipeline, in need of a modeset, gets
> enabled is as follows -
> 
> 	CRTC Enable
> 	All Bridge Pre-Enable
> 	Encoder Enable
> 	All Bridge Enable
> 
> - and the disable path is exactly the reverse of this.
> 
> The CRTC enable/disable occurs by looping over the old and new CRTC
> states, while the bridge pre-enable, encoder enable, and bridge enable
> occur by looping through the new connector states of the display
> pipelines.
> 
> At the moment, the encoder and bridge operations are grouped together
> and occur under the same loops.
> 
> Separate out the enable/disable loops of the encoder and bridge
> operations into a different function, to make way for the re-ordering of
> the enable and disable sequence of all these display elements.
> 
> This patch doesn't alter in any way the ordering of CRTC/encoder/bridge
> enable and disable, but merely helps to cleanly set up for the next
> patch and to make sure that the bisectibility remains intact.
> 
> Signed-off-by: Aradhya Bhatia <a-bhatia1@ti.com>
> Signed-off-by: Aradhya Bhatia <aradhya.bhatia@linux.dev>
> ---
>  drivers/gpu/drm/drm_atomic_helper.c | 97 +++++++++++++++++------------
>  1 file changed, 57 insertions(+), 40 deletions(-)
> 
> diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
> index 5186d2114a50..7741fbcc8fc7 100644
> --- a/drivers/gpu/drm/drm_atomic_helper.c
> +++ b/drivers/gpu/drm/drm_atomic_helper.c
> @@ -1122,11 +1122,10 @@ crtc_needs_disable(struct drm_crtc_state *old_state,
>  }
>  
>  static void
> -disable_outputs(struct drm_device *dev, struct drm_atomic_state *old_state)
> +encoder_bridge_chain_disable(struct drm_device *dev, struct drm_atomic_state *old_state)
>  {
>  	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;
>  
> @@ -1189,6 +1188,16 @@ disable_outputs(struct drm_device *dev, struct drm_atomic_state *old_state)
>  
>  		drm_atomic_bridge_chain_post_disable(bridge, old_state);
>  	}
> +}
> +
> +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;
> +
> +	encoder_bridge_chain_disable(dev, old_state);
>  
>  	for_each_oldnew_crtc_in_state(old_state, crtc, old_crtc_state, new_crtc_state, i) {
>  		const struct drm_crtc_helper_funcs *funcs;
> @@ -1445,6 +1454,51 @@ static void drm_atomic_helper_commit_writebacks(struct drm_device *dev,
>  	}
>  }
>  
> +static void
> +encoder_bridge_chain_enable(struct drm_device *dev, struct drm_atomic_state *old_state)
> +{
> +	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 = new_conn_state->best_encoder;
> +		funcs = 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 = 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);
> +	}
> +}
> +
>  /**
>   * drm_atomic_helper_commit_modeset_enables - modeset commit to enable outputs
>   * @dev: DRM device
> @@ -1465,8 +1519,6 @@ void drm_atomic_helper_commit_modeset_enables(struct 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;
>  
>  	for_each_oldnew_crtc_in_state(old_state, crtc, old_crtc_state, new_crtc_state, i) {
> @@ -1491,42 +1543,7 @@ void drm_atomic_helper_commit_modeset_enables(struct drm_device *dev,
>  		}
>  	}

I'd say, if you want for it to be cleaner, split both loops from
drm_atomic_helper_commit_modeset_enables() and call them separately.
This save you from the code move, which is harder to review (and also
helps with the function complexity).

>  
> -	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 = new_conn_state->best_encoder;
> -		funcs = 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 = 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);
> -	}
> +	encoder_bridge_chain_enable(dev, old_state);
>  
>  	drm_atomic_helper_commit_writebacks(dev, old_state);
>  }
> -- 
> 2.34.1
> 

-- 
With best wishes
Dmitry

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH v5 13/13] drm/bridge: cdns-dsi: Use pre_enable/post_disable to enable/disable
  2024-10-19 20:05   ` [PATCH v5 13/13] drm/bridge: cdns-dsi: Use pre_enable/post_disable to enable/disable Aradhya Bhatia
@ 2024-10-20 11:57     ` Dmitry Baryshkov
  2024-10-21 17:07       ` Aradhya Bhatia
  0 siblings, 1 reply; 26+ messages in thread
From: Dmitry Baryshkov @ 2024-10-20 11:57 UTC (permalink / raw)
  To: Aradhya Bhatia
  Cc: Tomi Valkeinen, Laurent Pinchart, Andrzej Hajda, Neil Armstrong,
	Robert Foss, Jonas Karlman, Jernej Skrabec, Maarten Lankhorst,
	Maxime Ripard, Thomas Zimmermann, David Airlie, Simona Vetter,
	Dominik Haller, Sam Ravnborg, Kieran Bingham, Nishanth Menon,
	Vignesh Raghavendra, Devarsh Thakkar, Praneeth Bajjuri,
	Udit Kumar, Jayesh Choudhary, DRI Development List,
	Linux Kernel List

On Sun, Oct 20, 2024 at 01:35:30AM +0530, Aradhya Bhatia wrote:
> From: Aradhya Bhatia <a-bhatia1@ti.com>
> 
> The cdns-dsi controller requires that it be turned on completely before
> the input DPI's source has begun streaming[0]. Not having that, allows
> for a small window before cdns-dsi enable and after cdns-dsi disable
> where the previous entity (in this case tidss's videoport) to continue
> streaming DPI video signals. This small window where cdns-dsi is
> disabled but is still receiving signals causes the input FIFO of
> cdns-dsi to get corrupted. This causes the colors to shift on the output
> display. The colors can either shift by one color component (R->G, G->B,
> B->R), or by two color components (R->B, G->R, B->G).
> 
> Since tidss's videoport starts streaming via crtc enable hooks, we need
> cdns-dsi to be up and running before that. Now that the bridges are
> pre_enabled before crtc is enabled, and post_disabled after crtc is
> disabled, use the pre_enable and post_disable hooks to get cdns-dsi
> ready and running before the tidss videoport to get pass the color shift
> issues.
> 

Not being an expert in the TI DSS driver, would it be more proper to
handle that in the TI driver instead? I mean, sending out DPI signals
isn't a part of the CRTC setup, it's a job of the encoder.

> [0]: See section 12.6.5.7.3 "Start-up Procedure" in J721E SoC TRM
>      TRM Link: http://www.ti.com/lit/pdf/spruil1
> 
> Reviewed-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
> Signed-off-by: Aradhya Bhatia <a-bhatia1@ti.com>
> Signed-off-by: Aradhya Bhatia <aradhya.bhatia@linux.dev>
> ---
>  .../gpu/drm/bridge/cadence/cdns-dsi-core.c    | 62 ++++++++++---------
>  1 file changed, 34 insertions(+), 28 deletions(-)
> 
> diff --git a/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
> index 79d8c2264c14..dfeb53841ebc 100644
> --- a/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
> +++ b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
> @@ -658,13 +658,28 @@ cdns_dsi_bridge_mode_valid(struct drm_bridge *bridge,
>  	return MODE_OK;
>  }
>  
> -static void cdns_dsi_bridge_atomic_disable(struct drm_bridge *bridge,
> -					   struct drm_bridge_state *old_bridge_state)
> +static void cdns_dsi_bridge_atomic_post_disable(struct drm_bridge *bridge,
> +						struct drm_bridge_state *old_bridge_state)
>  {
>  	struct cdns_dsi_input *input = bridge_to_cdns_dsi_input(bridge);
>  	struct cdns_dsi *dsi = input_to_dsi(input);
>  	u32 val;
>  
> +	/*
> +	 * The cdns-dsi controller needs to be disabled after it's DPI source
> +	 * has stopped streaming. If this is not followed, there is a brief
> +	 * window before DPI source is disabled and after cdns-dsi controller
> +	 * has been disabled where the DPI stream is still on, but the cdns-dsi
> +	 * controller is not ready anymore to accept the incoming signals. This
> +	 * is one of the reasons why a shift in pixel colors is observed on
> +	 * displays that have cdns-dsi as one of the bridges.
> +	 *
> +	 * To mitigate this, disable this bridge from the bridge post_disable()
> +	 * hook, instead of the bridge _disable() hook. The bridge post_disable()
> +	 * hook gets called after the CRTC disable, where often many DPI sources
> +	 * disable their streams.
> +	 */
> +
>  	val = readl(dsi->regs + MCTL_MAIN_DATA_CTL);
>  	val &= ~(IF_VID_SELECT_MASK | IF_VID_MODE | VID_EN | HOST_EOT_GEN |
>  		 DISP_EOT_GEN);
> @@ -683,15 +698,6 @@ static void cdns_dsi_bridge_atomic_disable(struct drm_bridge *bridge,
>  	pm_runtime_put(dsi->base.dev);
>  }
>  
> -static void cdns_dsi_bridge_atomic_post_disable(struct drm_bridge *bridge,
> -						struct drm_bridge_state *old_bridge_state)
> -{
> -	struct cdns_dsi_input *input = bridge_to_cdns_dsi_input(bridge);
> -	struct cdns_dsi *dsi = input_to_dsi(input);
> -
> -	pm_runtime_put(dsi->base.dev);
> -}
> -
>  static void cdns_dsi_hs_init(struct cdns_dsi *dsi)
>  {
>  	struct cdns_dsi_output *output = &dsi->output;
> @@ -760,8 +766,8 @@ static void cdns_dsi_init_link(struct cdns_dsi *dsi)
>  	dsi->link_initialized = true;
>  }
>  
> -static void cdns_dsi_bridge_atomic_enable(struct drm_bridge *bridge,
> -					  struct drm_bridge_state *old_bridge_state)
> +static void cdns_dsi_bridge_atomic_pre_enable(struct drm_bridge *bridge,
> +					      struct drm_bridge_state *old_bridge_state)
>  {
>  	struct cdns_dsi_input *input = bridge_to_cdns_dsi_input(bridge);
>  	struct cdns_dsi *dsi = input_to_dsi(input);
> @@ -776,6 +782,21 @@ static void cdns_dsi_bridge_atomic_enable(struct drm_bridge *bridge,
>  	if (WARN_ON(pm_runtime_get_sync(dsi->base.dev) < 0))
>  		return;
>  
> +	/*
> +	 * The cdns-dsi controller needs to be enabled before it's DPI source
> +	 * has begun streaming. If this is not followed, there is a brief window
> +	 * after DPI source enable and before cdns-dsi controller enable where
> +	 * the DPI stream is on, but the cdns-dsi controller is not ready to
> +	 * accept the incoming signals. This is one of the reasons why a shift
> +	 * in pixel colors is observed on displays that have cdns-dsi as one of
> +	 * the bridges.
> +	 *
> +	 * To mitigate this, enable this bridge from the bridge pre_enable()
> +	 * hook, instead of the bridge _enable() hook. The bridge pre_enable()
> +	 * hook gets called before the CRTC enable, where often many DPI sources
> +	 * enable their streams.
> +	 */
> +
>  	if (dsi->platform_ops && dsi->platform_ops->enable)
>  		dsi->platform_ops->enable(dsi);
>  
> @@ -912,19 +933,6 @@ static void cdns_dsi_bridge_atomic_enable(struct drm_bridge *bridge,
>  	writel(tmp, dsi->regs + MCTL_MAIN_EN);
>  }
>  
> -static void cdns_dsi_bridge_atomic_pre_enable(struct drm_bridge *bridge,
> -					      struct drm_bridge_state *old_bridge_state)
> -{
> -	struct cdns_dsi_input *input = bridge_to_cdns_dsi_input(bridge);
> -	struct cdns_dsi *dsi = input_to_dsi(input);
> -
> -	if (WARN_ON(pm_runtime_get_sync(dsi->base.dev) < 0))
> -		return;
> -
> -	cdns_dsi_init_link(dsi);
> -	cdns_dsi_hs_init(dsi);
> -}
> -
>  static u32 *cdns_dsi_bridge_get_input_bus_fmts(struct drm_bridge *bridge,
>  					       struct drm_bridge_state *bridge_state,
>  					       struct drm_crtc_state *crtc_state,
> @@ -968,9 +976,7 @@ static int cdns_dsi_bridge_atomic_check(struct drm_bridge *bridge,
>  static const struct drm_bridge_funcs cdns_dsi_bridge_funcs = {
>  	.attach = cdns_dsi_bridge_attach,
>  	.mode_valid = cdns_dsi_bridge_mode_valid,
> -	.atomic_disable = cdns_dsi_bridge_atomic_disable,
>  	.atomic_pre_enable = cdns_dsi_bridge_atomic_pre_enable,
> -	.atomic_enable = cdns_dsi_bridge_atomic_enable,
>  	.atomic_post_disable = cdns_dsi_bridge_atomic_post_disable,
>  	.atomic_check = cdns_dsi_bridge_atomic_check,
>  	.atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
> -- 
> 2.34.1
> 

-- 
With best wishes
Dmitry

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH v5 12/13] drm/atomic-helper: Re-order bridge chain pre-enable and post-disable
  2024-10-19 20:05   ` [PATCH v5 12/13] drm/atomic-helper: Re-order bridge chain pre-enable and post-disable Aradhya Bhatia
@ 2024-10-20 11:58     ` Dmitry Baryshkov
  0 siblings, 0 replies; 26+ messages in thread
From: Dmitry Baryshkov @ 2024-10-20 11:58 UTC (permalink / raw)
  To: Aradhya Bhatia
  Cc: Tomi Valkeinen, Laurent Pinchart, Andrzej Hajda, Neil Armstrong,
	Robert Foss, Jonas Karlman, Jernej Skrabec, Maarten Lankhorst,
	Maxime Ripard, Thomas Zimmermann, David Airlie, Simona Vetter,
	Dominik Haller, Sam Ravnborg, Kieran Bingham, Nishanth Menon,
	Vignesh Raghavendra, Devarsh Thakkar, Praneeth Bajjuri,
	Udit Kumar, Jayesh Choudhary, DRI Development List,
	Linux Kernel List

On Sun, Oct 20, 2024 at 01:35:29AM +0530, Aradhya Bhatia wrote:
> From: Aradhya Bhatia <a-bhatia1@ti.com>
> 
> 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 <a-bhatia1@ti.com>
> Signed-off-by: Aradhya Bhatia <aradhya.bhatia@linux.dev>
> ---
>  drivers/gpu/drm/drm_atomic_helper.c | 102 ++++++++++++++++++----------
>  include/drm/drm_atomic_helper.h     |   5 ++
>  2 files changed, 71 insertions(+), 36 deletions(-)
> 
> diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
> index 7741fbcc8fc7..6ebd869df79b 100644
> --- a/drivers/gpu/drm/drm_atomic_helper.c
> +++ b/drivers/gpu/drm/drm_atomic_helper.c
> @@ -1122,7 +1122,8 @@ crtc_needs_disable(struct drm_crtc_state *old_state,
>  }
>  
>  static void
> -encoder_bridge_chain_disable(struct drm_device *dev, struct drm_atomic_state *old_state)
> +encoder_bridge_chain_disable(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 *old_conn_state, *new_conn_state;
> @@ -1162,31 +1163,43 @@ encoder_bridge_chain_disable(struct drm_device *dev, struct drm_atomic_state *ol
>  		if (WARN_ON(!encoder))
>  			continue;
>  
> -		funcs = 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 = drm_bridge_chain_get_first_bridge(encoder);
> -		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);
> -		}
> +		switch (op_type) {
> +		case DRM_BRIDGE_ENABLE_DISABLE:
> +			funcs = 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);
> +			}
>  
> -		drm_atomic_bridge_chain_post_disable(bridge, old_state);
> +			break;
> +
> +		case DRM_BRIDGE_PRE_ENABLE_POST_DISABLE:
> +			drm_atomic_bridge_chain_post_disable(bridge, old_state);
> +			break;
> +
> +		default:
> +			drm_err(dev, "Unrecognized Encoder/Bridge Operation (%d).\n", op_type);
> +			break;
> +		}
>  	}
>  }
>  
> @@ -1197,7 +1210,7 @@ disable_outputs(struct drm_device *dev, struct drm_atomic_state *old_state)
>  	struct drm_crtc_state *old_crtc_state, *new_crtc_state;
>  	int i;
>  
> -	encoder_bridge_chain_disable(dev, old_state);
> +	encoder_bridge_chain_disable(dev, old_state, DRM_BRIDGE_ENABLE_DISABLE);
>  
>  	for_each_oldnew_crtc_in_state(old_state, crtc, old_crtc_state, new_crtc_state, i) {
>  		const struct drm_crtc_helper_funcs *funcs;
> @@ -1243,6 +1256,8 @@ disable_outputs(struct drm_device *dev, struct drm_atomic_state *old_state)
>  		if (ret == 0)
>  			drm_crtc_vblank_put(crtc);
>  	}
> +
> +	encoder_bridge_chain_disable(dev, old_state, DRM_BRIDGE_PRE_ENABLE_POST_DISABLE);
>  }
>  
>  /**
> @@ -1455,7 +1470,8 @@ static void drm_atomic_helper_commit_writebacks(struct drm_device *dev,
>  }
>  
>  static void
> -encoder_bridge_chain_enable(struct drm_device *dev, struct drm_atomic_state *old_state)
> +encoder_bridge_chain_enable(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;
> @@ -1474,28 +1490,40 @@ encoder_bridge_chain_enable(struct drm_device *dev, struct drm_atomic_state *old
>  			continue;
>  
>  		encoder = new_conn_state->best_encoder;
> -		funcs = 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 = 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);
> -		}
> +		switch (op_type) {
> +		case DRM_BRIDGE_PRE_ENABLE_POST_DISABLE:
> +			drm_atomic_bridge_chain_pre_enable(bridge, old_state);
> +			break;
> +
> +		case DRM_BRIDGE_ENABLE_DISABLE:
> +			funcs = encoder->helper_private;
> +
> +			drm_dbg_atomic(dev, "enabling [ENCODER:%d:%s]\n",
> +				       encoder->base.id, encoder->name);
>  
> -		drm_atomic_bridge_chain_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);
> +			break;
> +
> +		default:
> +			drm_err(dev, "Unrecognized Encoder/Bridge Operation (%d).\n", op_type);
> +			break;
> +		}
>  	}
>  }
>  
> @@ -1521,6 +1549,8 @@ void drm_atomic_helper_commit_modeset_enables(struct drm_device *dev,
>  	struct drm_crtc_state *new_crtc_state;
>  	int i;
>  
> +	encoder_bridge_chain_enable(dev, old_state, DRM_BRIDGE_PRE_ENABLE_POST_DISABLE);
> +
>  	for_each_oldnew_crtc_in_state(old_state, crtc, old_crtc_state, new_crtc_state, i) {
>  		const struct drm_crtc_helper_funcs *funcs;
>  
> @@ -1543,7 +1573,7 @@ void drm_atomic_helper_commit_modeset_enables(struct drm_device *dev,
>  		}
>  	}
>  
> -	encoder_bridge_chain_enable(dev, old_state);
> +	encoder_bridge_chain_enable(dev, old_state, DRM_BRIDGE_ENABLE_DISABLE);
>  
>  	drm_atomic_helper_commit_writebacks(dev, old_state);
>  }
> diff --git a/include/drm/drm_atomic_helper.h b/include/drm/drm_atomic_helper.h
> index 9aa0a05aa072..92a5812adc6c 100644
> --- a/include/drm/drm_atomic_helper.h
> +++ b/include/drm/drm_atomic_helper.h
> @@ -43,6 +43,11 @@
>   */
>  #define DRM_PLANE_NO_SCALING (1<<16)
>  
> +enum bridge_chain_operation_type {
> +	DRM_BRIDGE_PRE_ENABLE_POST_DISABLE,
> +	DRM_BRIDGE_ENABLE_DISABLE,
> +};
> +

The enum doesn't need to be public, does it?

>  struct drm_atomic_state;
>  struct drm_private_obj;
>  struct drm_private_state;
> -- 
> 2.34.1
> 

-- 
With best wishes
Dmitry

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH v5 13/13] drm/bridge: cdns-dsi: Use pre_enable/post_disable to enable/disable
  2024-10-20 11:57     ` Dmitry Baryshkov
@ 2024-10-21 17:07       ` Aradhya Bhatia
  2024-10-21 18:39         ` Dmitry Baryshkov
  0 siblings, 1 reply; 26+ messages in thread
From: Aradhya Bhatia @ 2024-10-21 17:07 UTC (permalink / raw)
  To: Dmitry Baryshkov
  Cc: Tomi Valkeinen, Laurent Pinchart, Andrzej Hajda, Neil Armstrong,
	Robert Foss, Jonas Karlman, Jernej Skrabec, Maarten Lankhorst,
	Maxime Ripard, Thomas Zimmermann, David Airlie, Simona Vetter,
	Dominik Haller, Sam Ravnborg, Kieran Bingham, Nishanth Menon,
	Vignesh Raghavendra, Devarsh Thakkar, Praneeth Bajjuri,
	Udit Kumar, Jayesh Choudhary, DRI Development List,
	Linux Kernel List

Hi Dmitry,

Thank you for reviewing the patches!

On 10/20/24 17:27, Dmitry Baryshkov wrote:
> On Sun, Oct 20, 2024 at 01:35:30AM +0530, Aradhya Bhatia wrote:
>> From: Aradhya Bhatia <a-bhatia1@ti.com>
>>
>> The cdns-dsi controller requires that it be turned on completely before
>> the input DPI's source has begun streaming[0]. Not having that, allows
>> for a small window before cdns-dsi enable and after cdns-dsi disable
>> where the previous entity (in this case tidss's videoport) to continue
>> streaming DPI video signals. This small window where cdns-dsi is
>> disabled but is still receiving signals causes the input FIFO of
>> cdns-dsi to get corrupted. This causes the colors to shift on the output
>> display. The colors can either shift by one color component (R->G, G->B,
>> B->R), or by two color components (R->B, G->R, B->G).
>>
>> Since tidss's videoport starts streaming via crtc enable hooks, we need
>> cdns-dsi to be up and running before that. Now that the bridges are
>> pre_enabled before crtc is enabled, and post_disabled after crtc is
>> disabled, use the pre_enable and post_disable hooks to get cdns-dsi
>> ready and running before the tidss videoport to get pass the color shift
>> issues.
>>
> 
> Not being an expert in the TI DSS driver, would it be more proper to
> handle that in the TI driver instead? I mean, sending out DPI signals
> isn't a part of the CRTC setup, it's a job of the encoder.

I haven't done a feasibility analysis of moving the CRTC bits of TIDSS
into the encoder, but even if it were possible, it wouldn't solve the
issue.

The bridge_enable() sequence gets called _after_ the encoder has been
enabled - causing the TIDSS's DPI (enabled from encoder) to still be
up and running before the DSI has had a chance to be ready.

Regards
Aradhya


> 
>> [0]: See section 12.6.5.7.3 "Start-up Procedure" in J721E SoC TRM
>>      TRM Link: http://www.ti.com/lit/pdf/spruil1
>>
>> Reviewed-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
>> Signed-off-by: Aradhya Bhatia <a-bhatia1@ti.com>
>> Signed-off-by: Aradhya Bhatia <aradhya.bhatia@linux.dev>
>> ---
>>  .../gpu/drm/bridge/cadence/cdns-dsi-core.c    | 62 ++++++++++---------
>>  1 file changed, 34 insertions(+), 28 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
>> index 79d8c2264c14..dfeb53841ebc 100644
>> --- a/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
>> +++ b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
>> @@ -658,13 +658,28 @@ cdns_dsi_bridge_mode_valid(struct drm_bridge *bridge,
>>  	return MODE_OK;
>>  }
>>  
>> -static void cdns_dsi_bridge_atomic_disable(struct drm_bridge *bridge,
>> -					   struct drm_bridge_state *old_bridge_state)
>> +static void cdns_dsi_bridge_atomic_post_disable(struct drm_bridge *bridge,
>> +						struct drm_bridge_state *old_bridge_state)
>>  {
>>  	struct cdns_dsi_input *input = bridge_to_cdns_dsi_input(bridge);
>>  	struct cdns_dsi *dsi = input_to_dsi(input);
>>  	u32 val;
>>  
>> +	/*
>> +	 * The cdns-dsi controller needs to be disabled after it's DPI source
>> +	 * has stopped streaming. If this is not followed, there is a brief
>> +	 * window before DPI source is disabled and after cdns-dsi controller
>> +	 * has been disabled where the DPI stream is still on, but the cdns-dsi
>> +	 * controller is not ready anymore to accept the incoming signals. This
>> +	 * is one of the reasons why a shift in pixel colors is observed on
>> +	 * displays that have cdns-dsi as one of the bridges.
>> +	 *
>> +	 * To mitigate this, disable this bridge from the bridge post_disable()
>> +	 * hook, instead of the bridge _disable() hook. The bridge post_disable()
>> +	 * hook gets called after the CRTC disable, where often many DPI sources
>> +	 * disable their streams.
>> +	 */
>> +
>>  	val = readl(dsi->regs + MCTL_MAIN_DATA_CTL);
>>  	val &= ~(IF_VID_SELECT_MASK | IF_VID_MODE | VID_EN | HOST_EOT_GEN |
>>  		 DISP_EOT_GEN);
>> @@ -683,15 +698,6 @@ static void cdns_dsi_bridge_atomic_disable(struct drm_bridge *bridge,
>>  	pm_runtime_put(dsi->base.dev);
>>  }
>>  
>> -static void cdns_dsi_bridge_atomic_post_disable(struct drm_bridge *bridge,
>> -						struct drm_bridge_state *old_bridge_state)
>> -{
>> -	struct cdns_dsi_input *input = bridge_to_cdns_dsi_input(bridge);
>> -	struct cdns_dsi *dsi = input_to_dsi(input);
>> -
>> -	pm_runtime_put(dsi->base.dev);
>> -}
>> -
>>  static void cdns_dsi_hs_init(struct cdns_dsi *dsi)
>>  {
>>  	struct cdns_dsi_output *output = &dsi->output;
>> @@ -760,8 +766,8 @@ static void cdns_dsi_init_link(struct cdns_dsi *dsi)
>>  	dsi->link_initialized = true;
>>  }
>>  
>> -static void cdns_dsi_bridge_atomic_enable(struct drm_bridge *bridge,
>> -					  struct drm_bridge_state *old_bridge_state)
>> +static void cdns_dsi_bridge_atomic_pre_enable(struct drm_bridge *bridge,
>> +					      struct drm_bridge_state *old_bridge_state)
>>  {
>>  	struct cdns_dsi_input *input = bridge_to_cdns_dsi_input(bridge);
>>  	struct cdns_dsi *dsi = input_to_dsi(input);
>> @@ -776,6 +782,21 @@ static void cdns_dsi_bridge_atomic_enable(struct drm_bridge *bridge,
>>  	if (WARN_ON(pm_runtime_get_sync(dsi->base.dev) < 0))
>>  		return;
>>  
>> +	/*
>> +	 * The cdns-dsi controller needs to be enabled before it's DPI source
>> +	 * has begun streaming. If this is not followed, there is a brief window
>> +	 * after DPI source enable and before cdns-dsi controller enable where
>> +	 * the DPI stream is on, but the cdns-dsi controller is not ready to
>> +	 * accept the incoming signals. This is one of the reasons why a shift
>> +	 * in pixel colors is observed on displays that have cdns-dsi as one of
>> +	 * the bridges.
>> +	 *
>> +	 * To mitigate this, enable this bridge from the bridge pre_enable()
>> +	 * hook, instead of the bridge _enable() hook. The bridge pre_enable()
>> +	 * hook gets called before the CRTC enable, where often many DPI sources
>> +	 * enable their streams.
>> +	 */
>> +
>>  	if (dsi->platform_ops && dsi->platform_ops->enable)
>>  		dsi->platform_ops->enable(dsi);
>>  
>> @@ -912,19 +933,6 @@ static void cdns_dsi_bridge_atomic_enable(struct drm_bridge *bridge,
>>  	writel(tmp, dsi->regs + MCTL_MAIN_EN);
>>  }
>>  
>> -static void cdns_dsi_bridge_atomic_pre_enable(struct drm_bridge *bridge,
>> -					      struct drm_bridge_state *old_bridge_state)
>> -{
>> -	struct cdns_dsi_input *input = bridge_to_cdns_dsi_input(bridge);
>> -	struct cdns_dsi *dsi = input_to_dsi(input);
>> -
>> -	if (WARN_ON(pm_runtime_get_sync(dsi->base.dev) < 0))
>> -		return;
>> -
>> -	cdns_dsi_init_link(dsi);
>> -	cdns_dsi_hs_init(dsi);
>> -}
>> -
>>  static u32 *cdns_dsi_bridge_get_input_bus_fmts(struct drm_bridge *bridge,
>>  					       struct drm_bridge_state *bridge_state,
>>  					       struct drm_crtc_state *crtc_state,
>> @@ -968,9 +976,7 @@ static int cdns_dsi_bridge_atomic_check(struct drm_bridge *bridge,
>>  static const struct drm_bridge_funcs cdns_dsi_bridge_funcs = {
>>  	.attach = cdns_dsi_bridge_attach,
>>  	.mode_valid = cdns_dsi_bridge_mode_valid,
>> -	.atomic_disable = cdns_dsi_bridge_atomic_disable,
>>  	.atomic_pre_enable = cdns_dsi_bridge_atomic_pre_enable,
>> -	.atomic_enable = cdns_dsi_bridge_atomic_enable,
>>  	.atomic_post_disable = cdns_dsi_bridge_atomic_post_disable,
>>  	.atomic_check = cdns_dsi_bridge_atomic_check,
>>  	.atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
>> -- 
>> 2.34.1
>>
> 

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH v5 13/13] drm/bridge: cdns-dsi: Use pre_enable/post_disable to enable/disable
  2024-10-21 17:07       ` Aradhya Bhatia
@ 2024-10-21 18:39         ` Dmitry Baryshkov
  2024-10-22 17:19           ` Aradhya Bhatia
  0 siblings, 1 reply; 26+ messages in thread
From: Dmitry Baryshkov @ 2024-10-21 18:39 UTC (permalink / raw)
  To: Aradhya Bhatia
  Cc: Tomi Valkeinen, Laurent Pinchart, Andrzej Hajda, Neil Armstrong,
	Robert Foss, Jonas Karlman, Jernej Skrabec, Maarten Lankhorst,
	Maxime Ripard, Thomas Zimmermann, David Airlie, Simona Vetter,
	Dominik Haller, Sam Ravnborg, Kieran Bingham, Nishanth Menon,
	Vignesh Raghavendra, Devarsh Thakkar, Praneeth Bajjuri,
	Udit Kumar, Jayesh Choudhary, DRI Development List,
	Linux Kernel List

On Mon, 21 Oct 2024 at 20:07, Aradhya Bhatia <aradhya.bhatia@linux.dev> wrote:
>
> Hi Dmitry,
>
> Thank you for reviewing the patches!
>
> On 10/20/24 17:27, Dmitry Baryshkov wrote:
> > On Sun, Oct 20, 2024 at 01:35:30AM +0530, Aradhya Bhatia wrote:
> >> From: Aradhya Bhatia <a-bhatia1@ti.com>
> >>
> >> The cdns-dsi controller requires that it be turned on completely before
> >> the input DPI's source has begun streaming[0]. Not having that, allows
> >> for a small window before cdns-dsi enable and after cdns-dsi disable
> >> where the previous entity (in this case tidss's videoport) to continue
> >> streaming DPI video signals. This small window where cdns-dsi is
> >> disabled but is still receiving signals causes the input FIFO of
> >> cdns-dsi to get corrupted. This causes the colors to shift on the output
> >> display. The colors can either shift by one color component (R->G, G->B,
> >> B->R), or by two color components (R->B, G->R, B->G).
> >>
> >> Since tidss's videoport starts streaming via crtc enable hooks, we need
> >> cdns-dsi to be up and running before that. Now that the bridges are
> >> pre_enabled before crtc is enabled, and post_disabled after crtc is
> >> disabled, use the pre_enable and post_disable hooks to get cdns-dsi
> >> ready and running before the tidss videoport to get pass the color shift
> >> issues.
> >>
> >
> > Not being an expert in the TI DSS driver, would it be more proper to
> > handle that in the TI driver instead? I mean, sending out DPI signals
> > isn't a part of the CRTC setup, it's a job of the encoder.
>
> I haven't done a feasibility analysis of moving the CRTC bits of TIDSS
> into the encoder, but even if it were possible, it wouldn't solve the
> issue.
>
> The bridge_enable() sequence gets called _after_ the encoder has been
> enabled - causing the TIDSS's DPI (enabled from encoder) to still be
> up and running before the DSI has had a chance to be ready.

But then you can move CDSI setup to pre_enable, so that all setup
happens before encoder's (= DPI) being enabled.


-- 
With best wishes
Dmitry

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH v5 07/13] drm/bridge: cdns-dsi: Wait for Clk and Data Lanes to be ready
  2024-10-19 19:54 ` [PATCH v5 07/13] drm/bridge: cdns-dsi: Wait for Clk and Data Lanes to be ready Aradhya Bhatia
@ 2024-10-22  6:25   ` Devarsh Thakkar
  2024-10-22 17:25     ` Aradhya Bhatia
  0 siblings, 1 reply; 26+ messages in thread
From: Devarsh Thakkar @ 2024-10-22  6:25 UTC (permalink / raw)
  To: Aradhya Bhatia, Tomi Valkeinen, Dmitry Baryshkov,
	Laurent Pinchart, Andrzej Hajda, Neil Armstrong, Robert Foss,
	Jonas Karlman, Jernej Skrabec, Maarten Lankhorst, Maxime Ripard,
	Thomas Zimmermann, David Airlie, Simona Vetter
  Cc: Dominik Haller, Sam Ravnborg, Kieran Bingham, Nishanth Menon,
	Vignesh Raghavendra, Praneeth Bajjuri, Udit Kumar,
	Jayesh Choudhary, DRI Development List, Linux Kernel List

Hi Aradhya,

Thanks for the patch.

On 20/10/24 01:24, Aradhya Bhatia wrote:
> From: Aradhya Bhatia <a-bhatia1@ti.com>

[...]

> +	/*
> +	 * Now that the DSI Link and DSI Phy are initialized,
> +	 * wait for the CLK and Data Lanes to be ready.
> +	 */
> +	tmp = CLK_LANE_RDY;
> +	for (int i = 0; i < nlanes; i++)
> +		tmp |= DATA_LANE_RDY(i);
> +
> +	if (readl_poll_timeout(dsi->regs + MCTL_MAIN_STS, status,
> +			       status & tmp, 100, 500000))

The above would mark the condition as true even if one data lane gets ready. I
think we need to poll until all data lanes are marked as ready. Also good to
give a warning in case we time out.

IMHO below should fix this:
        WARN_ON_ONCE(readl_poll_timeout(dsi->regs + MCTL_MAIN_STS, status,
                                       (tmp == (status & tmp)), 100, 0));

Regards
Devarsh

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH v5 13/13] drm/bridge: cdns-dsi: Use pre_enable/post_disable to enable/disable
  2024-10-21 18:39         ` Dmitry Baryshkov
@ 2024-10-22 17:19           ` Aradhya Bhatia
  0 siblings, 0 replies; 26+ messages in thread
From: Aradhya Bhatia @ 2024-10-22 17:19 UTC (permalink / raw)
  To: Dmitry Baryshkov
  Cc: Tomi Valkeinen, Laurent Pinchart, Andrzej Hajda, Neil Armstrong,
	Robert Foss, Jonas Karlman, Jernej Skrabec, Maarten Lankhorst,
	Maxime Ripard, Thomas Zimmermann, David Airlie, Simona Vetter,
	Dominik Haller, Sam Ravnborg, Kieran Bingham, Nishanth Menon,
	Vignesh Raghavendra, Devarsh Thakkar, Praneeth Bajjuri,
	Udit Kumar, Jayesh Choudhary, DRI Development List,
	Linux Kernel List



On 10/22/24 00:09, Dmitry Baryshkov wrote:
> On Mon, 21 Oct 2024 at 20:07, Aradhya Bhatia <aradhya.bhatia@linux.dev> wrote:
>>
>> Hi Dmitry,
>>
>> Thank you for reviewing the patches!
>>
>> On 10/20/24 17:27, Dmitry Baryshkov wrote:
>>> On Sun, Oct 20, 2024 at 01:35:30AM +0530, Aradhya Bhatia wrote:
>>>> From: Aradhya Bhatia <a-bhatia1@ti.com>
>>>>
>>>> The cdns-dsi controller requires that it be turned on completely before
>>>> the input DPI's source has begun streaming[0]. Not having that, allows
>>>> for a small window before cdns-dsi enable and after cdns-dsi disable
>>>> where the previous entity (in this case tidss's videoport) to continue
>>>> streaming DPI video signals. This small window where cdns-dsi is
>>>> disabled but is still receiving signals causes the input FIFO of
>>>> cdns-dsi to get corrupted. This causes the colors to shift on the output
>>>> display. The colors can either shift by one color component (R->G, G->B,
>>>> B->R), or by two color components (R->B, G->R, B->G).
>>>>
>>>> Since tidss's videoport starts streaming via crtc enable hooks, we need
>>>> cdns-dsi to be up and running before that. Now that the bridges are
>>>> pre_enabled before crtc is enabled, and post_disabled after crtc is
>>>> disabled, use the pre_enable and post_disable hooks to get cdns-dsi
>>>> ready and running before the tidss videoport to get pass the color shift
>>>> issues.
>>>>
>>>
>>> Not being an expert in the TI DSS driver, would it be more proper to
>>> handle that in the TI driver instead? I mean, sending out DPI signals
>>> isn't a part of the CRTC setup, it's a job of the encoder.
>>
>> I haven't done a feasibility analysis of moving the CRTC bits of TIDSS
>> into the encoder, but even if it were possible, it wouldn't solve the
>> issue.
>>
>> The bridge_enable() sequence gets called _after_ the encoder has been
>> enabled - causing the TIDSS's DPI (enabled from encoder) to still be
>> up and running before the DSI has had a chance to be ready.
> 
> But then you can move CDSI setup to pre_enable, so that all setup
> happens before encoder's (= DPI) being enabled.
> 
> 

Ah! I did not realize that you were suggesting against moving
_bridge_pre_enable() to before crtc_enable().

I think, despite its initial complexity, it is a good idea to move the
_bridge_pre_enable() before the crtc_enable().

The boundary between an encoder and a CRTC in the modern display
hardware seems to have blurred a bit. Maybe the tidss / cdns-dsi is a
unique case (only for now), but of course, tidss is not
the only one generating the DPI signal from the CRTC.

And bridges should be allowed an option to get _some_ configuration done
before the CRTC and encoder are up and running, and I think that's where
the re-ordering is of the essence.

My initial version did suggest creating a new API[0], "_early_enable()"
that allowed _pre_enable() to remain where it is, all the while allowing
the bridges to have the option of configuring before the signals start
getting generated in the pipeline. That idea was then translated into
the current one.


Regards
Aradhya


[0]: https://lore.kernel.org/all/20240511153051.1355825-7-a-bhatia1@ti.com/

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH v5 07/13] drm/bridge: cdns-dsi: Wait for Clk and Data Lanes to be ready
  2024-10-22  6:25   ` Devarsh Thakkar
@ 2024-10-22 17:25     ` Aradhya Bhatia
  0 siblings, 0 replies; 26+ messages in thread
From: Aradhya Bhatia @ 2024-10-22 17:25 UTC (permalink / raw)
  To: Devarsh Thakkar, Tomi Valkeinen, Dmitry Baryshkov,
	Laurent Pinchart, Andrzej Hajda, Neil Armstrong, Robert Foss,
	Jonas Karlman, Jernej Skrabec, Maarten Lankhorst, Maxime Ripard,
	Thomas Zimmermann, David Airlie, Simona Vetter
  Cc: Dominik Haller, Sam Ravnborg, Kieran Bingham, Nishanth Menon,
	Vignesh Raghavendra, Praneeth Bajjuri, Udit Kumar,
	Jayesh Choudhary, DRI Development List, Linux Kernel List



On 22/10/24 11:55, Devarsh Thakkar wrote:
> Hi Aradhya,
> 
> Thanks for the patch.
> 
> On 20/10/24 01:24, Aradhya Bhatia wrote:
>> From: Aradhya Bhatia <a-bhatia1@ti.com>
> 
> [...]
> 
>> +	/*
>> +	 * Now that the DSI Link and DSI Phy are initialized,
>> +	 * wait for the CLK and Data Lanes to be ready.
>> +	 */
>> +	tmp = CLK_LANE_RDY;
>> +	for (int i = 0; i < nlanes; i++)
>> +		tmp |= DATA_LANE_RDY(i);
>> +
>> +	if (readl_poll_timeout(dsi->regs + MCTL_MAIN_STS, status,
>> +			       status & tmp, 100, 500000))
> 
> The above would mark the condition as true even if one data lane gets ready. I
> think we need to poll until all data lanes are marked as ready. Also good to
> give a warning in case we time out.
> 
> IMHO below should fix this:
>         WARN_ON_ONCE(readl_poll_timeout(dsi->regs + MCTL_MAIN_STS, status,
>                                        (tmp == (status & tmp)), 100, 0));
> 

That's how the condition should be, yes! Thanks for the catch!

I would still prefer to keep dev_err instead of WARN_ON_ONCE, because
the latter stack-dumps during boot once, and then can never be seen
again during multiple modesets. The noise in the dmesg is not worth
the issue either.

With dev_err, it can show a clear print once every time it times out.

-- 
Regards
Aradhya


^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH v5 06/13] drm/bridge: cdns-dsi: Check return value when getting default PHY config
  2024-10-19 19:54 ` [PATCH v5 06/13] drm/bridge: cdns-dsi: Check return value when getting default PHY config Aradhya Bhatia
@ 2024-11-18 14:12   ` Tomi Valkeinen
  0 siblings, 0 replies; 26+ messages in thread
From: Tomi Valkeinen @ 2024-11-18 14:12 UTC (permalink / raw)
  To: Aradhya Bhatia, Dmitry Baryshkov, Laurent Pinchart, Andrzej Hajda,
	Neil Armstrong, Robert Foss, Jonas Karlman, Jernej Skrabec,
	Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
	Simona Vetter
  Cc: Dominik Haller, Sam Ravnborg, Kieran Bingham, Nishanth Menon,
	Vignesh Raghavendra, Devarsh Thakkar, Praneeth Bajjuri,
	Udit Kumar, Jayesh Choudhary, DRI Development List,
	Linux Kernel List

On 19/10/2024 22:54, Aradhya Bhatia wrote:
> From: Aradhya Bhatia <a-bhatia1@ti.com>
> 
> Check for the return value of the phy_mipi_dphy_get_default_config()
> call, and incase of an error, return back the same.
> 
> Fixes: fced5a364dee ("drm/bridge: cdns: Convert to phy framework")
> Signed-off-by: Aradhya Bhatia <a-bhatia1@ti.com>
> Signed-off-by: Aradhya Bhatia <aradhya.bhatia@linux.dev>
> ---
>   drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c | 8 +++++---
>   1 file changed, 5 insertions(+), 3 deletions(-)

Reviewed-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>

  Tomi

> diff --git a/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
> index 2fc24352d989..e4c0968313af 100644
> --- a/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
> +++ b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
> @@ -575,9 +575,11 @@ static int cdns_dsi_check_conf(struct cdns_dsi *dsi,
>   	if (ret)
>   		return ret;
>   
> -	phy_mipi_dphy_get_default_config(mode_clock * 1000,
> -					 mipi_dsi_pixel_format_to_bpp(output->dev->format),
> -					 nlanes, phy_cfg);
> +	ret = phy_mipi_dphy_get_default_config(mode_clock * 1000,
> +					       mipi_dsi_pixel_format_to_bpp(output->dev->format),
> +					       nlanes, phy_cfg);
> +	if (ret)
> +		return ret;
>   
>   	ret = cdns_dsi_adjust_phy_config(dsi, dsi_cfg, phy_cfg, mode, mode_valid_check);
>   	if (ret)


^ permalink raw reply	[flat|nested] 26+ messages in thread

end of thread, other threads:[~2024-11-18 14:12 UTC | newest]

Thread overview: 26+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-10-19 19:53 [PATCH v5 00/13] drm/bridge: cdns-dsi: Fix the color-shift issue Aradhya Bhatia
2024-10-19 19:53 ` [PATCH v5 01/13] drm/bridge: cdns-dsi: Fix connecting to next bridge Aradhya Bhatia
2024-10-19 19:54 ` [PATCH v5 02/13] drm/bridge: cdns-dsi: Move to devm_drm_of_get_bridge() Aradhya Bhatia
2024-10-20 10:49   ` Dmitry Baryshkov
2024-10-19 19:54 ` [PATCH v5 03/13] drm/bridge: cdns-dsi: Fix Phy _init() and _exit() Aradhya Bhatia
2024-10-20 11:34   ` Dmitry Baryshkov
2024-10-19 19:54 ` [PATCH v5 04/13] drm/bridge: cdns-dsi: Fix the link and phy init order Aradhya Bhatia
2024-10-19 19:54 ` [PATCH v5 05/13] drm/bridge: cdns-dsi: Fix the clock variable for mode_valid() Aradhya Bhatia
2024-10-19 19:54 ` [PATCH v5 06/13] drm/bridge: cdns-dsi: Check return value when getting default PHY config Aradhya Bhatia
2024-11-18 14:12   ` Tomi Valkeinen
2024-10-19 19:54 ` [PATCH v5 07/13] drm/bridge: cdns-dsi: Wait for Clk and Data Lanes to be ready Aradhya Bhatia
2024-10-22  6:25   ` Devarsh Thakkar
2024-10-22 17:25     ` Aradhya Bhatia
2024-10-19 20:05 ` [PATCH v5 08/13] drm/mipi-dsi: Add helper to find input format Aradhya Bhatia
2024-10-19 20:05   ` [PATCH v5 09/13] drm/bridge: cdns-dsi: Support atomic bridge APIs Aradhya Bhatia
2024-10-19 20:05   ` [PATCH v5 10/13] drm/bridge: cdns-dsi: Move DSI mode check to _atomic_check() Aradhya Bhatia
2024-10-20 11:42     ` Dmitry Baryshkov
2024-10-19 20:05   ` [PATCH v5 11/13] drm/atomic-helper: Separate out Encoder-Bridge enable and disable Aradhya Bhatia
2024-10-20 11:47     ` Dmitry Baryshkov
2024-10-19 20:05   ` [PATCH v5 12/13] drm/atomic-helper: Re-order bridge chain pre-enable and post-disable Aradhya Bhatia
2024-10-20 11:58     ` Dmitry Baryshkov
2024-10-19 20:05   ` [PATCH v5 13/13] drm/bridge: cdns-dsi: Use pre_enable/post_disable to enable/disable Aradhya Bhatia
2024-10-20 11:57     ` Dmitry Baryshkov
2024-10-21 17:07       ` Aradhya Bhatia
2024-10-21 18:39         ` Dmitry Baryshkov
2024-10-22 17:19           ` Aradhya Bhatia

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox