drm/mipi-dbi: Lock SPI bus before setting D/C GPIO
authorOtto Pflüger <otto.pflueger@abscue.de>
Mon, 24 Jul 2023 06:56:53 +0000 (08:56 +0200)
committerNoralf Trønnes <noralf@tronnes.org>
Wed, 2 Aug 2023 11:18:07 +0000 (13:18 +0200)
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@abscue.de>
Reviewed-by: Noralf Trønnes <noralf@tronnes.org>
Acked-by: David Lechner <david@lechnology.com>
Signed-off-by: Noralf Trønnes <noralf@tronnes.org>
Link: https://patchwork.freedesktop.org/patch/msgid/20230724065654.5269-2-otto.pflueger@abscue.de
drivers/gpu/drm/drm_mipi_dbi.c
drivers/gpu/drm/tiny/ili9225.c
drivers/gpu/drm/tiny/ili9486.c

index c871d9f..e90f0bf 100644 (file)
@@ -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);
+       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);
+       ret = mipi_dbi_spi_transfer(spi, speed_hz, bpw, par, num);
+       spi_bus_unlock(spi->controller);
 
-       return mipi_dbi_spi_transfer(spi, speed_hz, bpw, par, num);
+       return ret;
 }
 
 /**
@@ -1271,7 +1279,8 @@ EXPORT_SYMBOL(mipi_dbi_spi_init);
  * @len: Buffer length
  *
  * This SPI transfer helper breaks up the transfer of @buf into chunks which
- * the SPI controller driver can handle.
+ * the SPI controller driver can handle. The SPI bus must be locked when
+ * calling this.
  *
  * Returns:
  * Zero on success, negative error code on failure.
@@ -1305,7 +1314,7 @@ int mipi_dbi_spi_transfer(struct spi_device *spi, u32 speed_hz,
                buf += chunk;
                len -= chunk;
 
-               ret = spi_sync(spi, &m);
+               ret = spi_sync_locked(spi, &m);
                if (ret)
                        return ret;
        }
index 077c6ff..4ceb68f 100644 (file)
@@ -316,19 +316,24 @@ static int ili9225_dbi_command(struct mipi_dbi *dbi, u8 *cmd, u8 *par,
        u32 speed_hz;
        int ret;
 
+       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);
+       spi_bus_unlock(spi->controller);
        if (ret || !num)
                return ret;
 
        if (*cmd == ILI9225_WRITE_DATA_TO_GRAM && !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);
+       ret = mipi_dbi_spi_transfer(spi, speed_hz, bpw, par, num);
+       spi_bus_unlock(spi->controller);
 
-       return mipi_dbi_spi_transfer(spi, speed_hz, bpw, par, num);
+       return ret;
 }
 
 static const struct drm_simple_display_pipe_funcs ili9225_pipe_funcs = {
index 02265c8..938bcee 100644 (file)
@@ -59,9 +59,11 @@ static int waveshare_command(struct mipi_dbi *mipi, u8 *cmd, u8 *par,
         * before being transferred as 8-bit on the big endian SPI bus.
         */
        buf[0] = cpu_to_be16(*cmd);
+       spi_bus_lock(spi->controller);
        gpiod_set_value_cansleep(mipi->dc, 0);
        speed_hz = mipi_dbi_spi_cmd_max_speed(spi, 2);
        ret = mipi_dbi_spi_transfer(spi, speed_hz, 8, buf, 2);
+       spi_bus_unlock(spi->controller);
        if (ret || !num)
                goto free;
 
@@ -79,9 +81,11 @@ static int waveshare_command(struct mipi_dbi *mipi, u8 *cmd, u8 *par,
        if (*cmd == MIPI_DCS_WRITE_MEMORY_START && !mipi->swap_bytes)
                bpw = 16;
 
+       spi_bus_lock(spi->controller);
        gpiod_set_value_cansleep(mipi->dc, 1);
        speed_hz = mipi_dbi_spi_cmd_max_speed(spi, num);
        ret = mipi_dbi_spi_transfer(spi, speed_hz, bpw, data, num);
+       spi_bus_unlock(spi->controller);
  free:
        kfree(buf);