lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20231016165355.1327217-6-dmitry.baryshkov@linaro.org>
Date:   Mon, 16 Oct 2023 19:53:50 +0300
From:   Dmitry Baryshkov <dmitry.baryshkov@...aro.org>
To:     Dave Stevenson <dave.stevenson@...pberrypi.com>,
        Andrzej Hajda <andrzej.hajda@...el.com>,
        Neil Armstrong <neil.armstrong@...aro.org>,
        Robert Foss <rfoss@...nel.org>,
        Laurent Pinchart <Laurent.pinchart@...asonboard.com>,
        Jonas Karlman <jonas@...boo.se>,
        Jernej Skrabec <jernej.skrabec@...il.com>,
        Maarten Lankhorst <maarten.lankhorst@...ux.intel.com>,
        Maxime Ripard <mripard@...nel.org>,
        Thomas Zimmermann <tzimmermann@...e.de>,
        David Airlie <airlied@...il.com>,
        Daniel Vetter <daniel@...ll.ch>,
        Douglas Anderson <dianders@...omium.org>,
        Rob Clark <robdclark@...il.com>,
        Abhinav Kumar <quic_abhinavk@...cinc.com>,
        Dmitry Baryshkov <dmitry.baryshkov@...aro.org>,
        Sean Paul <sean@...rly.run>,
        Marijn Suijten <marijn.suijten@...ainline.org>,
        Konrad Dybcio <konrad.dybcio@...aro.org>,
        Jessica Zhang <quic_jesszhan@...cinc.com>
Cc:     Marek Vasut <marex@...x.de>, dri-devel@...ts.freedesktop.org,
        linux-kernel@...r.kernel.org, linux-arm-msm@...r.kernel.org,
        freedreno@...ts.freedesktop.org
Subject: [RFC PATCH 05/10] drm/msm/dsi: implement manual power control

Implement new API for tight control over the DSI link's power state.
This allows bridge and panel drivers to send DSI commands at a proper
time.

Note, this also brings back the ps8640 workaround (to be removed later,
once ps8640 driver sets up the MIPI_DSI_MANUAL_POWERUP flag).. We have
to make sure that the DSI link stays disabled in case of this bridge,
otherwise it will not work.

Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@...aro.org>
---
 drivers/gpu/drm/msm/dsi/dsi.h         |  4 ++
 drivers/gpu/drm/msm/dsi/dsi_host.c    | 44 +++++++++++++++++
 drivers/gpu/drm/msm/dsi/dsi_manager.c | 68 +++++++++++++++++++++++----
 3 files changed, 106 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/msm/dsi/dsi.h b/drivers/gpu/drm/msm/dsi/dsi.h
index a01c326774a6..e0ae2cb144de 100644
--- a/drivers/gpu/drm/msm/dsi/dsi.h
+++ b/drivers/gpu/drm/msm/dsi/dsi.h
@@ -63,6 +63,8 @@ bool msm_dsi_manager_cmd_xfer_trigger(int id, u32 dma_base, u32 len);
 int msm_dsi_manager_register(struct msm_dsi *msm_dsi);
 void msm_dsi_manager_unregister(struct msm_dsi *msm_dsi);
 void msm_dsi_manager_tpg_enable(void);
+int msm_dsi_manager_power_up(int id);
+void msm_dsi_manager_power_down(int id);
 
 /* msm dsi */
 static inline bool msm_dsi_device_connected(struct msm_dsi *msm_dsi)
@@ -108,6 +110,8 @@ void msm_dsi_host_get_phy_clk_req(struct mipi_dsi_host *host,
 void msm_dsi_host_destroy(struct mipi_dsi_host *host);
 int msm_dsi_host_modeset_init(struct mipi_dsi_host *host,
 					struct drm_device *dev);
+bool msm_dsi_host_auto_powerup(struct mipi_dsi_host *host);
+bool msm_dsi_host_early_powerup(struct mipi_dsi_host *host);
 int msm_dsi_host_init(struct msm_dsi *msm_dsi);
 int msm_dsi_runtime_suspend(struct device *dev);
 int msm_dsi_runtime_resume(struct device *dev);
diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c
index fd2201cb62db..7010a6f17c5f 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_host.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_host.c
@@ -1671,10 +1671,54 @@ static ssize_t dsi_host_transfer(struct mipi_dsi_host *host,
 	return ret;
 }
 
+static bool msm_dsi_host_manual_powerup(struct mipi_dsi_host *host)
+{
+	struct msm_dsi_host *msm_host = to_msm_dsi_host(host);
+
+	return msm_host->mode_flags & MIPI_DSI_MANUAL_POWERUP;
+}
+
+bool msm_dsi_host_auto_powerup(struct mipi_dsi_host *host)
+{
+	struct msm_dsi_host *msm_host = to_msm_dsi_host(host);
+
+	return msm_host->mode_flags & MIPI_DSI_AUTO_POWERUP;
+}
+
+bool msm_dsi_host_early_powerup(struct mipi_dsi_host *host)
+{
+	struct msm_dsi_host *msm_host = to_msm_dsi_host(host);
+
+	return !msm_dsi_host_manual_powerup(host) &&
+		!msm_dsi_host_auto_powerup(host);
+}
+
+static int msm_dsi_host_power_up(struct mipi_dsi_host *host)
+{
+	struct msm_dsi_host *msm_host = to_msm_dsi_host(host);
+
+	if (msm_dsi_host_auto_powerup(host))
+		return 0;
+
+	return msm_dsi_manager_power_up(msm_host->id);
+}
+
+static void msm_dsi_host_power_down(struct mipi_dsi_host *host)
+{
+	struct msm_dsi_host *msm_host = to_msm_dsi_host(host);
+
+	if (!msm_dsi_host_manual_powerup(host))
+		return;
+
+	msm_dsi_manager_power_down(msm_host->id);
+}
+
 static const struct mipi_dsi_host_ops dsi_host_ops = {
 	.attach = dsi_host_attach,
 	.detach = dsi_host_detach,
 	.transfer = dsi_host_transfer,
+	.power_up = msm_dsi_host_power_up,
+	.power_down = msm_dsi_host_power_down,
 };
 
 /*
diff --git a/drivers/gpu/drm/msm/dsi/dsi_manager.c b/drivers/gpu/drm/msm/dsi/dsi_manager.c
index 9fa1f29ec11a..2d7040d21239 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_manager.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_manager.c
@@ -198,6 +198,44 @@ static int dsi_mgr_bridge_get_id(struct drm_bridge *bridge)
 	return dsi_bridge->id;
 }
 
+/*
+ * If the next bridge in the chain is the Parade ps8640 bridge chip then don't
+ * power on early since it seems to violate the expectations of the firmware
+ * that the bridge chip is running.
+ */
+static bool dsi_mgr_next_is_ps8640(struct drm_bridge *bridge)
+{
+	struct drm_bridge *next_bridge = drm_bridge_get_next_bridge(bridge);
+
+	return next_bridge &&
+		next_bridge->of_node &&
+		of_device_is_compatible(next_bridge->of_node, "parade,ps8640");
+}
+
+static bool dsi_mgr_auto_powerup(struct drm_bridge *bridge)
+{
+	int id = dsi_mgr_bridge_get_id(bridge);
+	struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
+	struct mipi_dsi_host *host = msm_dsi->host;
+
+	if (dsi_mgr_next_is_ps8640(bridge))
+		return true;
+
+	return msm_dsi_host_auto_powerup(host);
+}
+
+static bool dsi_mgr_early_powerup(struct drm_bridge *bridge)
+{
+	int id = dsi_mgr_bridge_get_id(bridge);
+	struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
+	struct mipi_dsi_host *host = msm_dsi->host;
+
+	if (dsi_mgr_next_is_ps8640(bridge))
+		return false;
+
+	return msm_dsi_host_early_powerup(host);
+}
+
 static void msm_dsi_manager_set_split_display(u8 id)
 {
 	struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
@@ -228,9 +266,8 @@ static void msm_dsi_manager_set_split_display(u8 id)
 	}
 }
 
-static int dsi_mgr_bridge_power_on(struct drm_bridge *bridge)
+int msm_dsi_manager_power_up(int id)
 {
-	int id = dsi_mgr_bridge_get_id(bridge);
 	struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
 	struct msm_dsi *msm_dsi1 = dsi_mgr_get_dsi(DSI_1);
 	struct mipi_dsi_host *host = msm_dsi->host;
@@ -240,6 +277,10 @@ static int dsi_mgr_bridge_power_on(struct drm_bridge *bridge)
 
 	DBG("id=%d", id);
 
+	/* Do nothing with the host if it is slave-DSI in case of bonded DSI */
+	if (is_bonded_dsi && !IS_MASTER_DSI_LINK(id))
+		return 0;
+
 	ret = dsi_mgr_phy_enable(id, phy_shared_timings);
 	if (ret)
 		goto phy_en_fail;
@@ -278,9 +319,8 @@ static int dsi_mgr_bridge_power_on(struct drm_bridge *bridge)
 	return ret;
 }
 
-static void dsi_mgr_bridge_power_off(struct drm_bridge *bridge)
+void msm_dsi_manager_power_down(int id)
 {
-	int id = dsi_mgr_bridge_get_id(bridge);
 	struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
 	struct msm_dsi *msm_dsi1 = dsi_mgr_get_dsi(DSI_1);
 	struct mipi_dsi_host *host = msm_dsi->host;
@@ -312,10 +352,12 @@ static void dsi_mgr_bridge_pre_enable(struct drm_bridge *bridge)
 	if (is_bonded_dsi && !IS_MASTER_DSI_LINK(id))
 		return;
 
-	ret = dsi_mgr_bridge_power_on(bridge);
-	if (ret) {
-		dev_err(&msm_dsi->pdev->dev, "Power on failed: %d\n", ret);
-		return;
+	if (dsi_mgr_auto_powerup(bridge)) {
+		ret = msm_dsi_manager_power_up(id);
+		if (ret) {
+			dev_err(&msm_dsi->pdev->dev, "Power on failed: %d\n", ret);
+			return;
+		}
 	}
 
 	ret = msm_dsi_host_enable(host);
@@ -337,7 +379,8 @@ static void dsi_mgr_bridge_pre_enable(struct drm_bridge *bridge)
 host1_en_fail:
 	msm_dsi_host_disable(host);
 host_en_fail:
-	dsi_mgr_bridge_power_off(bridge);
+	if (dsi_mgr_auto_powerup(bridge))
+		msm_dsi_manager_power_down(id);
 }
 
 void msm_dsi_manager_tpg_enable(void)
@@ -390,7 +433,9 @@ static void dsi_mgr_bridge_post_disable(struct drm_bridge *bridge)
 	/* Save PHY status if it is a clock source */
 	msm_dsi_phy_pll_save_state(msm_dsi->phy);
 
-	dsi_mgr_bridge_power_off(bridge);
+	if (dsi_mgr_auto_powerup(bridge) ||
+	    dsi_mgr_early_powerup(bridge))
+		msm_dsi_manager_power_down(id);
 }
 
 static void dsi_mgr_bridge_mode_set(struct drm_bridge *bridge,
@@ -411,6 +456,9 @@ static void dsi_mgr_bridge_mode_set(struct drm_bridge *bridge,
 	msm_dsi_host_set_display_mode(host, adjusted_mode);
 	if (is_bonded_dsi && other_dsi)
 		msm_dsi_host_set_display_mode(other_dsi->host, adjusted_mode);
+
+	if (dsi_mgr_early_powerup(bridge))
+		msm_dsi_manager_power_up(id);
 }
 
 static enum drm_mode_status dsi_mgr_bridge_mode_valid(struct drm_bridge *bridge,
-- 
2.42.0

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ