This is an automated email from the ASF dual-hosted git repository.

xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git

commit 908ce01386a4fbd03249e670bc9b1f58d0489cdb
Author: Jiri Vlasak <[email protected]>
AuthorDate: Fri Nov 7 14:32:45 2025 +0100

    lcd/lcddrv: Implement 3-wire 9-bit SPI
    
    Some display drivers, like ILI9341, support 3-wire 9-bit SPI. In
    contrast to 4-wire 8-bit SPI, which uses dedicated CMD/DATA pin to
    distinguish between CMD and DATA, 3-wire 9-bit SPI uses MSB of 9-bit
    frame for this purpose.
    
    Signed-off-by: Jiri Vlasak <[email protected]>
---
 drivers/lcd/Kconfig        | 11 +++++++++++
 drivers/lcd/lcddrv_spiif.c | 31 +++++++++++++++++++++++++++++++
 2 files changed, 42 insertions(+)

diff --git a/drivers/lcd/Kconfig b/drivers/lcd/Kconfig
index 7ff1feb1398..b6894163a31 100644
--- a/drivers/lcd/Kconfig
+++ b/drivers/lcd/Kconfig
@@ -1589,6 +1589,17 @@ config LCD_LCDDRV_SPEED
                quite limited, but people have had success with much faster
                speeds than the spec sheets say. YMMV.
 
+config LCD_LCDDRV_3WIRE
+       bool "Use 3-wire 9-bit SPI."
+       default n
+       depends on LCD_LCDDRV_SPIIF
+       ---help---
+               Specifies whether 3-wire or 4-wire (default) SPI is used.
+
+               3-wire 9-bit SPI uses MSB to distinguish between CMD (0) or
+               DATA (1). 4-wire 8-bit SPI uses dedicated CMD/DATA pin to
+               distinguish between CMD and DATA.
+
 config LCD_RA8875
        bool "RA8875 LCD Display Controller"
        default n
diff --git a/drivers/lcd/lcddrv_spiif.c b/drivers/lcd/lcddrv_spiif.c
index 0ad4fc0b02d..9f1eea4dbe5 100644
--- a/drivers/lcd/lcddrv_spiif.c
+++ b/drivers/lcd/lcddrv_spiif.c
@@ -39,6 +39,13 @@
 #include <nuttx/spi/spi.h>
 #include <nuttx/lcd/lcddrv_spiif.h>
 
+/* Define conversions for DATA and CMD when 3-wire 9-bit SPI is used. */
+
+#ifdef CONFIG_LCD_LCDDRV_3WIRE
+#  define LCD_LCDDRV_3WIRE_DATA(wd) ((1 << 8) | (wd))
+#  define LCD_LCDDRV_3WIRE_CMD(wd)  ((0 << 8) | (wd))
+#endif
+
 /****************************************************************************
  * Private Types
  ****************************************************************************/
@@ -117,7 +124,9 @@ static void lcddrv_spiif_deselect(FAR struct lcddrv_lcd_s 
*lcd)
 {
   FAR struct lcddrv_spiif_lcd_s *priv = (FAR struct lcddrv_spiif_lcd_s *)lcd;
 
+#ifndef CONFIG_LCD_LCDDRV_3WIRE
   SPI_CMDDATA(priv->spi, SPIDEV_DISPLAY(0), false);
+#endif
   SPI_SELECT(priv->spi, SPIDEV_DISPLAY(0), false);
   SPI_LOCK(priv->spi, false);
 }
@@ -144,11 +153,21 @@ static int lcddrv_spiif_sendmulti(FAR struct lcddrv_lcd_s 
*lcd,
   uint32_t t;
   FAR struct lcddrv_spiif_lcd_s *priv = (FAR struct lcddrv_spiif_lcd_s *)lcd;
 
+#ifdef CONFIG_LCD_LCDDRV_3WIRE
+  SPI_SETBITS(priv->spi, 9);
+  for (t = 0; t < nwords; t++)
+    {
+      SPI_SEND(priv->spi, LCD_LCDDRV_3WIRE_DATA((*wd & 0xff00) >> 8));
+      SPI_SEND(priv->spi, LCD_LCDDRV_3WIRE_DATA((*wd & 0x00ff) >> 0));
+      wd++;
+    }
+#else
   SPI_SETBITS(priv->spi, 16);
   for (t = 0; t < nwords; t++)
     {
       SPI_SEND(priv->spi, *wd++);
     }
+#endif
 
   SPI_SETBITS(priv->spi, 8);
 
@@ -201,7 +220,13 @@ static int lcddrv_spiif_send(FAR struct lcddrv_lcd_s *lcd,
   uint8_t r;
   FAR struct lcddrv_spiif_lcd_s *priv = (FAR struct lcddrv_spiif_lcd_s *)lcd;
 
+#ifdef CONFIG_LCD_LCDDRV_3WIRE
+  SPI_SETBITS(priv->spi, 9);
+  r = SPI_SEND(priv->spi, LCD_LCDDRV_3WIRE_DATA(param));
+  SPI_SETBITS(priv->spi, 8);
+#else
   r = SPI_SEND(priv->spi, param);
+#endif
   return r;
 }
 
@@ -227,9 +252,15 @@ static int lcddrv_spiif_sendcmd(FAR struct lcddrv_lcd_s 
*lcd,
   FAR struct lcddrv_spiif_lcd_s *priv = (FAR struct lcddrv_spiif_lcd_s *)lcd;
 
   lcdinfo("param=%04x\n", param);
+#ifdef CONFIG_LCD_LCDDRV_3WIRE
+  SPI_SETBITS(priv->spi, 9);
+  r = SPI_SEND(priv->spi, LCD_LCDDRV_3WIRE_CMD(param));
+  SPI_SETBITS(priv->spi, 8);
+#else
   SPI_CMDDATA(priv->spi, SPIDEV_DISPLAY(0), true);
   r = SPI_SEND(priv->spi, param);
   SPI_CMDDATA(priv->spi, SPIDEV_DISPLAY(0), false);
+#endif
   return r;
 }
 

Reply via email to