[PATCH 1/2] drm/mipi-dbi: Lock SPI bus before setting D/C GPIO

Otto Pflüger otto.pflueger at abscue.de
Wed Jul 19 09:53:42 UTC 2023


Multiple displays may be connected to the same bus and share a D/C GPIO,
so the display driver needs exclusive access to the bus to ensure that
it can control the D/C GPIO safely.

Signed-off-by: Otto Pflüger <otto.pflueger at abscue.de>
---
 drivers/gpu/drm/drm_mipi_dbi.c | 22 +++++++++++++++++-----
 include/drm/drm_mipi_dbi.h     |  2 +-
 2 files changed, 18 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/drm_mipi_dbi.c b/drivers/gpu/drm/drm_mipi_dbi.c
index c871d9f096b8..c205b7594571 100644
--- a/drivers/gpu/drm/drm_mipi_dbi.c
+++ b/drivers/gpu/drm/drm_mipi_dbi.c
@@ -1140,10 +1140,13 @@ static int mipi_dbi_typec3_command_read(struct mipi_dbi *dbi, u8 *cmd,
 		return -ENOMEM;
 
 	tr[1].rx_buf = buf;
+
+	spi_bus_lock(spi->controller);
 	gpiod_set_value_cansleep(dbi->dc, 0);
 
 	spi_message_init_with_transfers(&m, tr, ARRAY_SIZE(tr));
-	ret = spi_sync(spi, &m);
+	ret = spi_sync_locked(spi, &m);
+	spi_bus_unlock(spi->controller);
 	if (ret)
 		goto err_free;
 
@@ -1177,19 +1180,24 @@ static int mipi_dbi_typec3_command(struct mipi_dbi *dbi, u8 *cmd,
 
 	MIPI_DBI_DEBUG_COMMAND(*cmd, par, num);
 
+	spi_bus_lock(spi->controller);
 	gpiod_set_value_cansleep(dbi->dc, 0);
 	speed_hz = mipi_dbi_spi_cmd_max_speed(spi, 1);
-	ret = mipi_dbi_spi_transfer(spi, speed_hz, 8, cmd, 1);
+	ret = mipi_dbi_spi_transfer(spi, speed_hz, 8, cmd, 1, true);
+	spi_bus_unlock(spi->controller);
 	if (ret || !num)
 		return ret;
 
 	if (*cmd == MIPI_DCS_WRITE_MEMORY_START && !dbi->swap_bytes)
 		bpw = 16;
 
+	spi_bus_lock(spi->controller);
 	gpiod_set_value_cansleep(dbi->dc, 1);
 	speed_hz = mipi_dbi_spi_cmd_max_speed(spi, num);
 
-	return mipi_dbi_spi_transfer(spi, speed_hz, bpw, par, num);
+	ret = mipi_dbi_spi_transfer(spi, speed_hz, bpw, par, num, true);
+	spi_bus_unlock(spi->controller);
+	return ret;
 }
 
 /**
@@ -1269,6 +1277,7 @@ EXPORT_SYMBOL(mipi_dbi_spi_init);
  * @bpw: Bits per word
  * @buf: Buffer to transfer
  * @len: Buffer length
+ * @is_locked: Is the SPI bus locked?
  *
  * This SPI transfer helper breaks up the transfer of @buf into chunks which
  * the SPI controller driver can handle.
@@ -1277,7 +1286,7 @@ EXPORT_SYMBOL(mipi_dbi_spi_init);
  * Zero on success, negative error code on failure.
  */
 int mipi_dbi_spi_transfer(struct spi_device *spi, u32 speed_hz,
-			  u8 bpw, const void *buf, size_t len)
+			  u8 bpw, const void *buf, size_t len, bool is_locked)
 {
 	size_t max_chunk = spi_max_transfer_size(spi);
 	struct spi_transfer tr = {
@@ -1305,7 +1314,10 @@ int mipi_dbi_spi_transfer(struct spi_device *spi, u32 speed_hz,
 		buf += chunk;
 		len -= chunk;
 
-		ret = spi_sync(spi, &m);
+		if (is_locked)
+			ret = spi_sync_locked(spi, &m);
+		else
+			ret = spi_sync(spi, &m);
 		if (ret)
 			return ret;
 	}
diff --git a/include/drm/drm_mipi_dbi.h b/include/drm/drm_mipi_dbi.h
index 816f196b3d4c..da632288aff9 100644
--- a/include/drm/drm_mipi_dbi.h
+++ b/include/drm/drm_mipi_dbi.h
@@ -185,7 +185,7 @@ int mipi_dbi_poweron_conditional_reset(struct mipi_dbi_dev *dbidev);
 
 u32 mipi_dbi_spi_cmd_max_speed(struct spi_device *spi, size_t len);
 int mipi_dbi_spi_transfer(struct spi_device *spi, u32 speed_hz,
-			  u8 bpw, const void *buf, size_t len);
+			  u8 bpw, const void *buf, size_t len, bool is_locked);
 
 int mipi_dbi_command_read(struct mipi_dbi *dbi, u8 cmd, u8 *val);
 int mipi_dbi_command_buf(struct mipi_dbi *dbi, u8 cmd, u8 *data, size_t len);
-- 
2.39.1


More information about the dri-devel mailing list