160 lines
5.6 KiB
Diff
160 lines
5.6 KiB
Diff
|
From ebf27e5ead012a1627a3f19f3bb2212b0aede3eb Mon Sep 17 00:00:00 2001
|
||
|
From: Ondrej Jirman <megi@xff.cz>
|
||
|
Date: Mon, 28 Mar 2022 19:04:23 +0200
|
||
|
Subject: [PATCH 299/389] drm: bridge: dw-mipi-dsi: Fix enable/disable of dsi
|
||
|
controller
|
||
|
|
||
|
The driver had it all wrong. mode_set is not for enabling the
|
||
|
DSI controller, that should be done in pre_enable so that
|
||
|
panel driver can initialize the panel (working dsi controller
|
||
|
is needed for that). Having dsi powerup in mode_set led to
|
||
|
all kind of fun, because disable would be called more often
|
||
|
than mode_set.
|
||
|
|
||
|
The whole panel/dsi enable/disable dance is such (for future
|
||
|
reference):
|
||
|
|
||
|
- dsi: mode set
|
||
|
- panel: prepare (we turn on panel power)
|
||
|
- dsi: pre enable (we enable and setup DSI)
|
||
|
- dsi: enable (we enable video data)
|
||
|
- panel: enable (we configure and turn on the display)
|
||
|
|
||
|
For disable:
|
||
|
|
||
|
- panel: disable (we turn off the display nicely)
|
||
|
- dsi: disable (we disable DSI)
|
||
|
- dsi: post disable
|
||
|
- panel: unprepare (we power off display power, panel should
|
||
|
be safely sleeping now)
|
||
|
|
||
|
Signed-off-by: Ondrej Jirman <megi@xff.cz>
|
||
|
|
||
|
# Conflicts:
|
||
|
# drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c
|
||
|
---
|
||
|
drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c | 51 +++++++++++++------
|
||
|
1 file changed, 36 insertions(+), 15 deletions(-)
|
||
|
|
||
|
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c
|
||
|
index b2efecf7d160..6e2007688dec 100644
|
||
|
--- a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c
|
||
|
+++ b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c
|
||
|
@@ -265,6 +265,7 @@ struct dw_mipi_dsi {
|
||
|
struct dw_mipi_dsi *master; /* dual-dsi master ptr */
|
||
|
struct dw_mipi_dsi *slave; /* dual-dsi slave ptr */
|
||
|
|
||
|
+ struct drm_display_mode mode;
|
||
|
const struct dw_mipi_dsi_plat_data *plat_data;
|
||
|
};
|
||
|
|
||
|
@@ -571,6 +572,8 @@ static void dw_mipi_dsi_set_mode(struct dw_mipi_dsi *dsi,
|
||
|
{
|
||
|
u32 val;
|
||
|
|
||
|
+ dev_info(dsi->dev, "mode %d\n", (int)mode_flags);
|
||
|
+
|
||
|
dsi_write(dsi, DSI_PWR_UP, RESET);
|
||
|
|
||
|
if (mode_flags & MIPI_DSI_MODE_VIDEO) {
|
||
|
@@ -845,12 +848,22 @@ static void dw_mipi_dsi_clear_err(struct dw_mipi_dsi *dsi)
|
||
|
dsi_write(dsi, DSI_INT_MSK1, 0);
|
||
|
}
|
||
|
|
||
|
-static void dw_mipi_dsi_bridge_post_atomic_disable(struct drm_bridge *bridge,
|
||
|
+static void dw_mipi_dsi_bridge_atomic_disable(struct drm_bridge *bridge,
|
||
|
+ struct drm_bridge_state *old_bridge_state)
|
||
|
+{
|
||
|
+ struct dw_mipi_dsi *dsi = bridge_to_dsi(bridge);
|
||
|
+
|
||
|
+ dev_info(dsi->dev, "disable\n");
|
||
|
+}
|
||
|
+
|
||
|
+static void dw_mipi_dsi_bridge_atomic_post_disable(struct drm_bridge *bridge,
|
||
|
struct drm_bridge_state *old_bridge_state)
|
||
|
{
|
||
|
struct dw_mipi_dsi *dsi = bridge_to_dsi(bridge);
|
||
|
const struct dw_mipi_dsi_phy_ops *phy_ops = dsi->plat_data->phy_ops;
|
||
|
|
||
|
+ dev_info(dsi->dev, "post disable\n");
|
||
|
+
|
||
|
/*
|
||
|
* Switch to command mode before panel-bridge post_disable &
|
||
|
* panel unprepare.
|
||
|
@@ -859,15 +872,6 @@ static void dw_mipi_dsi_bridge_post_atomic_disable(struct drm_bridge *bridge,
|
||
|
*/
|
||
|
dw_mipi_dsi_set_mode(dsi, 0);
|
||
|
|
||
|
- /*
|
||
|
- * TODO Only way found to call panel-bridge post_disable &
|
||
|
- * panel unprepare before the dsi "final" disable...
|
||
|
- * This needs to be fixed in the drm_bridge framework and the API
|
||
|
- * needs to be updated to manage our own call chains...
|
||
|
- */
|
||
|
- if (dsi->panel_bridge->funcs->post_disable)
|
||
|
- dsi->panel_bridge->funcs->post_disable(dsi->panel_bridge);
|
||
|
-
|
||
|
if (phy_ops->power_off)
|
||
|
phy_ops->power_off(dsi->plat_data->priv_data);
|
||
|
|
||
|
@@ -896,7 +900,7 @@ static unsigned int dw_mipi_dsi_get_lanes(struct dw_mipi_dsi *dsi)
|
||
|
return dsi->lanes;
|
||
|
}
|
||
|
|
||
|
-static void dw_mipi_dsi_mode_set(struct dw_mipi_dsi *dsi,
|
||
|
+static void dw_mipi_dsi_enable(struct dw_mipi_dsi *dsi,
|
||
|
const struct drm_display_mode *adjusted_mode)
|
||
|
{
|
||
|
const struct dw_mipi_dsi_phy_ops *phy_ops = dsi->plat_data->phy_ops;
|
||
|
@@ -948,9 +952,23 @@ static void dw_mipi_dsi_bridge_mode_set(struct drm_bridge *bridge,
|
||
|
{
|
||
|
struct dw_mipi_dsi *dsi = bridge_to_dsi(bridge);
|
||
|
|
||
|
- dw_mipi_dsi_mode_set(dsi, adjusted_mode);
|
||
|
+ dev_info(dsi->dev, "mode set\n");
|
||
|
+
|
||
|
+ /* Store the display mode for plugin/DKMS poweron events */
|
||
|
+ memcpy(&dsi->mode, mode, sizeof(dsi->mode));
|
||
|
+}
|
||
|
+
|
||
|
+static void dw_mipi_dsi_bridge_atomic_pre_enable(struct drm_bridge *bridge,
|
||
|
+ struct drm_bridge_state *old_bridge_state)
|
||
|
+{
|
||
|
+ struct dw_mipi_dsi *dsi = bridge_to_dsi(bridge);
|
||
|
+
|
||
|
+ dev_info(dsi->dev, "pre enable\n");
|
||
|
+
|
||
|
+ /* power up the dsi ctl into a command mode */
|
||
|
+ dw_mipi_dsi_enable(dsi, &dsi->mode);
|
||
|
if (dsi->slave)
|
||
|
- dw_mipi_dsi_mode_set(dsi->slave, adjusted_mode);
|
||
|
+ dw_mipi_dsi_enable(dsi->slave, &dsi->mode);
|
||
|
}
|
||
|
|
||
|
static void dw_mipi_dsi_bridge_atomic_enable(struct drm_bridge *bridge,
|
||
|
@@ -958,7 +976,8 @@ static void dw_mipi_dsi_bridge_atomic_enable(struct drm_bridge *bridge,
|
||
|
{
|
||
|
struct dw_mipi_dsi *dsi = bridge_to_dsi(bridge);
|
||
|
|
||
|
- /* Switch to video mode for panel-bridge enable & panel enable */
|
||
|
+ dev_info(dsi->dev, "enable\n");
|
||
|
+
|
||
|
dw_mipi_dsi_set_mode(dsi, MIPI_DSI_MODE_VIDEO);
|
||
|
if (dsi->slave)
|
||
|
dw_mipi_dsi_set_mode(dsi->slave, MIPI_DSI_MODE_VIDEO);
|
||
|
@@ -1004,8 +1023,10 @@ static const struct drm_bridge_funcs dw_mipi_dsi_bridge_funcs = {
|
||
|
.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_pre_enable = dw_mipi_dsi_bridge_atomic_pre_enable,
|
||
|
.atomic_enable = dw_mipi_dsi_bridge_atomic_enable,
|
||
|
- .atomic_post_disable = dw_mipi_dsi_bridge_post_atomic_disable,
|
||
|
+ .atomic_disable = dw_mipi_dsi_bridge_atomic_disable,
|
||
|
+ .atomic_post_disable = dw_mipi_dsi_bridge_atomic_post_disable,
|
||
|
.mode_set = dw_mipi_dsi_bridge_mode_set,
|
||
|
.mode_valid = dw_mipi_dsi_bridge_mode_valid,
|
||
|
.attach = dw_mipi_dsi_bridge_attach,
|
||
|
--
|
||
|
2.35.3
|
||
|
|