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: <20240506-tc358775-fix-powerup-v1-19-545dcf00b8dd@kernel.org>
Date: Mon, 06 May 2024 15:34:48 +0200
From: Michael Walle <mwalle@...nel.org>
To: 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>, 
 Chun-Kuang Hu <chunkuang.hu@...nel.org>, 
 Philipp Zabel <p.zabel@...gutronix.de>, 
 Matthias Brugger <matthias.bgg@...il.com>, 
 AngeloGioacchino Del Regno <angelogioacchino.delregno@...labora.com>, 
 Sam Ravnborg <sam@...nborg.org>, Vinay Simha BN <simhavcs@...il.com>, 
 Tony Lindgren <tony@...mide.com>
Cc: Daniel Semkowicz <dse@...umatec.com>, dri-devel@...ts.freedesktop.org, 
 linux-kernel@...r.kernel.org, linux-mediatek@...ts.infradead.org, 
 linux-arm-kernel@...ts.infradead.org, Michael Walle <mwalle@...nel.org>
Subject: [PATCH 19/20] drm/bridge: tc358775: fix power-up sequencing

The reset line of this bridge must be released while the DSI data lanes
and DSI clock lane are in LP-11 mode. After that the DSI clock has to be
turned on, which is a requirement to have I2C work.

To achieve this, use the new .lp11_notify() callback where the reset
line is released. Set .pre_enable_prev_first to make sure, there is a
valid DSI clock during the .pre_enabe() op. In .pre_enable() the bridge
will be fully configured but the LVDS transmitter will remain disabled.
It will eventually be enabled in the .enable() op.

With the correct initialization sequence we don't need the additional
reset, nor the additional write to VFUEN. With that fixed, the init
sequence is exactly how the vendor is requiring it.

Signed-off-by: Michael Walle <mwalle@...nel.org>
---
 drivers/gpu/drm/bridge/tc358775.c | 62 +++++++++++++++++++++++----------------
 1 file changed, 37 insertions(+), 25 deletions(-)

diff --git a/drivers/gpu/drm/bridge/tc358775.c b/drivers/gpu/drm/bridge/tc358775.c
index 99dbbb1fee78..31f89b7d5a3a 100644
--- a/drivers/gpu/drm/bridge/tc358775.c
+++ b/drivers/gpu/drm/bridge/tc358775.c
@@ -239,6 +239,9 @@ static void tc358775_power_up(struct tc_data *tc)
 	struct device *dev = &tc->dsi->dev;
 	int ret;
 
+	if (tc->powered)
+		return;
+
 	ret = regulator_enable(tc->vddio);
 	if (ret < 0)
 		dev_err(dev, "regulator vddio enable failed, %d\n", ret);
@@ -252,6 +255,8 @@ static void tc358775_power_up(struct tc_data *tc)
 
 	gpiod_set_value(tc->reset_gpio, 0);
 	usleep_range(200, 250);
+
+	tc->powered = true;
 }
 
 static void tc358775_power_down(struct tc_data *tc)
@@ -271,20 +276,8 @@ static void tc358775_power_down(struct tc_data *tc)
 	ret = regulator_disable(tc->vddio);
 	if (ret < 0)
 		dev_err(dev, "regulator vddio disable failed, %d\n", ret);
-}
 
-static void tc_bridge_pre_enable(struct drm_bridge *bridge)
-{
-	struct tc_data *tc = bridge_to_tc(bridge);
-
-	tc358775_power_up(tc);
-}
-
-static void tc_bridge_post_disable(struct drm_bridge *bridge)
-{
-	struct tc_data *tc = bridge_to_tc(bridge);
-
-	tc358775_power_down(tc);
+	tc->powered = false;
 }
 
 /* helper function to access bus_formats */
@@ -474,12 +467,25 @@ static void tc358775_configure_lvds_clock(struct tc_data *tc)
 	regmap_write(tc->regmap, LVCFG, val);
 }
 
-static void tc358775_bridge_enable(struct drm_bridge *bridge)
+static void tc358775_dsi_lp11_notify(struct drm_bridge *bridge)
 {
 	struct tc_data *tc = bridge_to_tc(bridge);
-	unsigned int val = 0;
-	struct drm_display_mode *mode;
+
+	tc358775_power_up(tc);
+}
+
+static void tc358775_bridge_pre_enable(struct drm_bridge *bridge)
+{
 	struct drm_connector *connector = get_connector(bridge->encoder);
+	struct tc_data *tc = bridge_to_tc(bridge);
+	struct drm_display_mode *mode;
+	unsigned int val = 0;
+
+	/*
+	 * Legacy behavior, make sure this bridge is powered even if
+	 * drm_bridge_dsi_lp11_notify() isn't called by the DSI host
+	 */
+	tc358775_power_up(tc);
 
 	mode = &bridge->encoder->crtc->state->adjusted_mode;
 
@@ -488,22 +494,27 @@ static void tc358775_bridge_enable(struct drm_bridge *bridge)
 	dev_info(tc->dev, "DSI2LVDS Chip ID.%02x Revision ID. %02x **\n",
 		 (val >> 8) & 0xFF, val & 0xFF);
 
-	regmap_write(tc->regmap, SYSRST,
-		     SYS_RST_REG | SYS_RST_DSIRX | SYS_RST_BM | SYS_RST_LCD |
-		     SYS_RST_I2CM);
-	usleep_range(30000, 40000);
-
 	tc358775_configure_dsi(tc, mode->crtc_clock);
 	tc358775_configure_lvds_timings(tc, mode);
 	tc358775_configure_pll(tc, mode->crtc_clock);
 	tc358775_configure_color_mapping(tc, connector->display_info.bus_formats[0]);
-	regmap_write(tc->regmap, VFUEN, VFUEN_VFUEN);
 	tc358775_configure_lvds_clock(tc);
+}
+
+static void tc358775_bridge_enable(struct drm_bridge *bridge)
+{
+	struct tc_data *tc = bridge_to_tc(bridge);
 
-	/* Finally, enable the LVDS transmitter */
 	regmap_update_bits(tc->regmap, LVCFG, LVCFG_LVEN, LVCFG_LVEN);
 }
 
+static void tc358775_bridge_post_disable(struct drm_bridge *bridge)
+{
+	struct tc_data *tc = bridge_to_tc(bridge);
+
+	tc358775_power_down(tc);
+}
+
 /*
  * According to the datasheet, the horizontal back porch, front porch and sync
  * length must be a multiple of 2 and the minimal horizontal pulse width is 8.
@@ -634,11 +645,12 @@ static int tc_bridge_attach(struct drm_bridge *bridge,
 
 static const struct drm_bridge_funcs tc_bridge_funcs = {
 	.attach = tc_bridge_attach,
-	.pre_enable = tc_bridge_pre_enable,
+	.dsi_lp11_notify = tc358775_dsi_lp11_notify,
+	.pre_enable = tc358775_bridge_pre_enable,
 	.enable = tc358775_bridge_enable,
+	.post_disable = tc358775_bridge_post_disable,
 	.mode_fixup = tc_mode_fixup,
 	.mode_valid = tc_mode_valid,
-	.post_disable = tc_bridge_post_disable,
 };
 
 static int tc_attach_host(struct tc_data *tc)

-- 
2.39.2


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ