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

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


The following commit(s) were added to refs/heads/master by this push:
     new 45651ea6e52 drivers/lcd: Refactor ST7796 to use Kconfig and add Power 
Management
45651ea6e52 is described below

commit 45651ea6e52165ca50ca3d84c7fc088ec68f40cc
Author: vrmay23 <[email protected]>
AuthorDate: Sat Mar 7 17:54:56 2026 +0100

    drivers/lcd: Refactor ST7796 to use Kconfig and add Power Management
    
    Previously, the ST7796 driver required the board to pass a struct
    st7796_config_s at initialization time, carrying display resolution,
    color depth, orientation (MADCTL), BGR flag, SPI frequency, and
    initial rotation.
    
    All of these are chip-level properties, not board wiring details.
    This created an awkward split: board code computed MADCTL values,
    selected BPP, and derived effective resolution depending on orientation
    (knowledge that belongs exclusively in the generic driver).
    
    This commit removes that split entirely, following the same pattern used
    by the ST7789 driver in drivers/lcd/Kconfig. It also implements the
    getpower/setpower interface for standard framebuffer power management.
    
    What was changed (per file):
    
    drivers/lcd/Kconfig:
    - Added a full 'if LCD_ST7796' ... 'endif # LCD_ST7796' block containing
      all chip-level configuration.
    - Includes LCD_ST7796_XRES/YRES, LCD_ST7796_BPP, LCD_ST7796_FREQUENCY,
      LCD_ST7796_SPIMODE, LCD_ST7796_BGR, LCD_ST7796_INVCOLOR,
      and orientation/rotation choices.
    
    drivers/lcd/st7796.c:
    - Removed struct st7796_config_s from struct st7796_dev_s.
    - Moved struct st7796_cmd_s from public header to Private Types.
    - Added compile-time macros derived from Kconfig:
      ST7796_XRES/YRES (swapped for landscape),
      ST7796_MADCTL_BASE,
      ST7796_SPIMODE,
      ST7796_BYTESPP,
      ST7796_COLORFMT.
    
    - Implemented st7796_getpower() and st7796_setpower() using the
      st7796_board_power() board callback.
    - Registered power functions in st7796_fbinitialize() vtable.
    - Updated st7796_init_display() to make INVON/INVOFF conditional on
      CONFIG_LCD_ST7796_INVCOLOR.
    - Simplified st7796_fbinitialize() signature to only take
      'struct spi_dev_s *spi'.
    
    include/nuttx/lcd/st7796.h:
    - Removed legacy macros (ST7796_XRES_RAW, etc.) and configuration
      structures.
    - Updated st7796_fbinitialize() prototype.
    - Added st7796_board_power() callback prototype.
    - Removed private implementation details from the public header.
    
    boards/arm/stm32h7/nucleo-h753zi/Kconfig:
    - Removed chip-level menus (settings, orientation) now handled by the
      generic driver.
    - Retained only board-specific wiring concerns (pins and SPI bus).
    
    boards/.../stm32_st7796.c:
    - Removed g_st7796_config and associated board-side macros.
    - Updated st7796_fbinitialize() call to the new signature.
    - stm32_st7796_flush_fb() now queries effective resolution
      via g_fb_vtable->getvideoinfo().
    
    Verified on nucleo-h753zi:
    Orientation: Landscape (480x320),
    Rotation: 180 deg,
    BGR: enabled,
    INVCOLOR: disabled,
    BPP: RGB565,
    Frequency: 40 MHz.
    Making INVCOLOR a Kconfig option (default n) fixes cases where panels
    previously showed inverted colors due to hardcoded INVON.
    
    Signed-off-by: vrmay23 <[email protected]>
---
 drivers/lcd/Kconfig        | 143 ++++++++++++++++++++++++
 drivers/lcd/st7796.c       | 271 +++++++++++++++++++++++++++++++++------------
 include/nuttx/lcd/st7796.h |  91 ++++-----------
 3 files changed, 367 insertions(+), 138 deletions(-)

diff --git a/drivers/lcd/Kconfig b/drivers/lcd/Kconfig
index ef216e5568b..d13ca55fa79 100644
--- a/drivers/lcd/Kconfig
+++ b/drivers/lcd/Kconfig
@@ -835,6 +835,149 @@ config LCD_ST7796
        ---help---
                Enable support for ST7796 LCD display driver.
 
+if LCD_ST7796
+
+config LCD_ST7796_XRES
+       int "ST7796 X Resolution (raw panel width)"
+       default 320
+       ---help---
+               Raw horizontal resolution of the ST7796 panel in pixels.
+               For the ST7796S this is 320. Effective display width
+               depends on the selected orientation.
+
+config LCD_ST7796_YRES
+       int "ST7796 Y Resolution (raw panel height)"
+       default 480
+       ---help---
+               Raw vertical resolution of the ST7796 panel in pixels.
+               For the ST7796S this is 480. Effective display height
+               depends on the selected orientation.
+
+choice
+       prompt "ST7796 Color Depth"
+       default LCD_ST7796_RGB565
+
+config LCD_ST7796_RGB444
+       bool "12-bit RGB444"
+       ---help---
+               12-bit color depth (4096 colors).
+               Lower memory usage but reduced color quality.
+
+config LCD_ST7796_RGB565
+       bool "16-bit RGB565"
+       ---help---
+               16-bit color depth (65536 colors).
+               Good balance between color quality and memory usage.
+
+config LCD_ST7796_RGB666
+       bool "18-bit RGB666"
+       ---help---
+               18-bit color depth (262144 colors).
+               Higher quality but more memory and slower SPI transfers.
+
+endchoice
+
+config LCD_ST7796_BPP
+       int
+       default 12 if LCD_ST7796_RGB444
+       default 16 if LCD_ST7796_RGB565
+       default 18 if LCD_ST7796_RGB666
+
+config LCD_ST7796_FREQUENCY
+       int "ST7796 SPI Frequency (Hz)"
+       default 40000000
+       range 1000000 80000000
+       ---help---
+               SPI bus frequency for ST7796 communication in Hz.
+               40 MHz is the recommended safe default.
+               Higher values require good signal integrity.
+
+config LCD_ST7796_SPIMODE
+       int "ST7796 SPI Mode"
+       default 0
+       ---help---
+               SPI mode for ST7796 (CPOL/CPHA).
+               ST7796 uses Mode 0 (CPOL=0, CPHA=0).
+
+config LCD_ST7796_BGR
+       bool "ST7796 Use BGR color order instead of RGB"
+       default n
+       ---help---
+               Enable if colors appear swapped (red shown as blue).
+               Sets the BGR bit in the MADCTL register.
+
+config LCD_ST7796_INVCOLOR
+       bool "ST7796 Invert display colors"
+       default n
+       ---help---
+               Send INVON command during initialization to invert all
+               display colors. Disable to send INVOFF instead.
+
+choice
+       prompt "ST7796 Display Orientation"
+       default LCD_ST7796_PORTRAIT
+
+config LCD_ST7796_PORTRAIT
+       bool "Portrait (320x480)"
+       ---help---
+               Natural portrait orientation: 320 pixels wide,
+               480 pixels tall.
+
+config LCD_ST7796_LANDSCAPE
+       bool "Landscape (480x320)"
+       ---help---
+               Landscape orientation: 480 pixels wide, 320 pixels tall.
+
+config LCD_ST7796_RPORTRAIT
+       bool "Reverse Portrait (320x480)"
+       ---help---
+               Reverse portrait: 320 wide, 480 tall, rotated 180 degrees
+               from normal portrait.
+
+config LCD_ST7796_RLANDSCAPE
+       bool "Reverse Landscape (480x320)"
+       ---help---
+               Reverse landscape: 480 wide, 320 tall, rotated 270 degrees
+               from normal portrait.
+
+endchoice
+
+choice
+       prompt "ST7796 Display Rotation"
+       default LCD_ST7796_ROTATION_0
+
+config LCD_ST7796_ROTATION_0
+       bool "0 degrees (no additional flip)"
+       ---help---
+               No additional rotation applied after base orientation.
+
+config LCD_ST7796_ROTATION_180
+       bool "180 degrees (flip)"
+       ---help---
+               Additional 180-degree flip after the base orientation.
+               Use when the display is mounted upside down.
+
+endchoice
+
+config LCD_ST7796_ROTATION
+       int
+       default 0   if LCD_ST7796_ROTATION_0
+       default 180 if LCD_ST7796_ROTATION_180
+
+config LCD_ST7796_FB_SIZE
+       int "ST7796 Framebuffer size (KB)"
+       depends on VIDEO_FB
+       default 300
+       range 150 600
+       ---help---
+               Framebuffer allocation size in kilobytes.
+               Full-screen requirements at 320x480:
+                 RGB444 (12-bit): 225 KB
+                 RGB565 (16-bit): 300 KB
+                 RGB666 (18-bit): 450 KB
+
+endif # LCD_ST7796
+
 config LCD_GC9A01
        bool "Galaxycore GC9A01 TFT Controller"
        default n
diff --git a/drivers/lcd/st7796.c b/drivers/lcd/st7796.c
index ea006519518..dff491638d0 100644
--- a/drivers/lcd/st7796.c
+++ b/drivers/lcd/st7796.c
@@ -30,7 +30,6 @@
 #include <sys/ioctl.h>
 #include <stdint.h>
 #include <stdbool.h>
-#include <string.h>
 #include <assert.h>
 #include <errno.h>
 #include <debug.h>
@@ -43,10 +42,6 @@
 #include <nuttx/signal.h>
 #include <nuttx/lcd/st7796.h>
 
-#ifndef CONFIG_SPI_CMDDATA
-#  error "CONFIG_SPI_CMDDATA must be enabled for ST7796"
-#endif
-
 /****************************************************************************
  * Pre-processor Definitions
  ****************************************************************************/
@@ -62,7 +57,7 @@
 #define ST7796_PTLON            0x12  /* Partial Display Mode On */
 #define ST7796_NORON            0x13  /* Normal Display Mode On */
 #define ST7796_RDIMGFMT         0x0a  /* Read Display Image Format */
-#define ST7796_RDSELFDIAG       0x0f  /* Read Display Self-Diagnostic Result */
+#define ST7796_RDSELFDIAG       0x0f  /* Read Display Self-Diagnostic */
 #define ST7796_INVOFF           0x20  /* Display Inversion Off */
 #define ST7796_INVON            0x21  /* Display Inversion On */
 #define ST7796_GAMMASET         0x26  /* Gamma Set */
@@ -113,18 +108,80 @@
 #define ST7796_MADCTL_BGR       0x08  /* BGR color filter panel */
 #define ST7796_MADCTL_MH        0x04  /* Horizontal Refresh Order */
 
-/* Force SPI MODE 0 (CPOL=0, CPHA=0) - Standard for ST7796 */
+/* Pre-defined MADCTL values for common orientations */
+
+#define ST7796_MADCTL_PORTRAIT       (ST7796_MADCTL_MX)
+#define ST7796_MADCTL_PORTRAIT_BGR   (ST7796_MADCTL_MX | ST7796_MADCTL_BGR)
+#define ST7796_MADCTL_RPORTRAIT      (ST7796_MADCTL_MY)
+#define ST7796_MADCTL_RPORTRAIT_BGR  (ST7796_MADCTL_MY | ST7796_MADCTL_BGR)
+#define ST7796_MADCTL_LANDSCAPE      (ST7796_MADCTL_MV)
+#define ST7796_MADCTL_LANDSCAPE_BGR  (ST7796_MADCTL_MV | ST7796_MADCTL_BGR)
+#define ST7796_MADCTL_RLANDSCAPE     (ST7796_MADCTL_MY | ST7796_MADCTL_MX | \
+                                      ST7796_MADCTL_MV)
+#define ST7796_MADCTL_RLANDSCAPE_BGR (ST7796_MADCTL_MY | ST7796_MADCTL_MX | \
+                                      ST7796_MADCTL_MV | ST7796_MADCTL_BGR)
+
+/* Effective resolution from raw panel size and orientation */
+
+#if defined(CONFIG_LCD_ST7796_LANDSCAPE) || \
+    defined(CONFIG_LCD_ST7796_RLANDSCAPE)
+#  define ST7796_XRES  CONFIG_LCD_ST7796_YRES
+#  define ST7796_YRES  CONFIG_LCD_ST7796_XRES
+#else
+#  define ST7796_XRES  CONFIG_LCD_ST7796_XRES
+#  define ST7796_YRES  CONFIG_LCD_ST7796_YRES
+#endif
 
-#define ST7796_SPIMODE SPIDEV_MODE0
+/* Base MADCTL from orientation and BGR Kconfig settings */
+
+#if defined(CONFIG_LCD_ST7796_LANDSCAPE)
+#  ifdef CONFIG_LCD_ST7796_BGR
+#    define ST7796_MADCTL_BASE  ST7796_MADCTL_LANDSCAPE_BGR
+#  else
+#    define ST7796_MADCTL_BASE  ST7796_MADCTL_LANDSCAPE
+#  endif
+#elif defined(CONFIG_LCD_ST7796_RPORTRAIT)
+#  ifdef CONFIG_LCD_ST7796_BGR
+#    define ST7796_MADCTL_BASE  ST7796_MADCTL_RPORTRAIT_BGR
+#  else
+#    define ST7796_MADCTL_BASE  ST7796_MADCTL_RPORTRAIT
+#  endif
+#elif defined(CONFIG_LCD_ST7796_RLANDSCAPE)
+#  ifdef CONFIG_LCD_ST7796_BGR
+#    define ST7796_MADCTL_BASE  ST7796_MADCTL_RLANDSCAPE_BGR
+#  else
+#    define ST7796_MADCTL_BASE  ST7796_MADCTL_RLANDSCAPE
+#  endif
+#else /* Portrait (default) */
+#  ifdef CONFIG_LCD_ST7796_BGR
+#    define ST7796_MADCTL_BASE  ST7796_MADCTL_PORTRAIT_BGR
+#  else
+#    define ST7796_MADCTL_BASE  ST7796_MADCTL_PORTRAIT
+#  endif
+#endif
+
+/* SPI mode: map Kconfig integer to NuttX enum value */
+
+#if CONFIG_LCD_ST7796_SPIMODE == 0
+#  define ST7796_SPIMODE  SPIDEV_MODE0
+#elif CONFIG_LCD_ST7796_SPIMODE == 1
+#  define ST7796_SPIMODE  SPIDEV_MODE1
+#elif CONFIG_LCD_ST7796_SPIMODE == 2
+#  define ST7796_SPIMODE  SPIDEV_MODE2
+#elif CONFIG_LCD_ST7796_SPIMODE == 3
+#  define ST7796_SPIMODE  SPIDEV_MODE3
+#else
+#  error "Invalid CONFIG_LCD_ST7796_SPIMODE (must be 0-3)"
+#endif
 
-/* Bytes per pixel based on BPP */
+/* Bytes per pixel */
 
-#define ST7796_BYTESPP(bpp)     (((bpp) == 18) ? 3 : 2)
+#define ST7796_BYTESPP   ((CONFIG_LCD_ST7796_BPP == 18) ? 3 : 2)
 
-/* Color format based on BPP */
+/* Color format */
 
-#define ST7796_COLORFMT(bpp)    (((bpp) == 18) ? FB_FMT_RGB24 : \
-                                 FB_FMT_RGB16_565)
+#define ST7796_COLORFMT  ((CONFIG_LCD_ST7796_BPP == 18) ? \
+                          FB_FMT_RGB24 : FB_FMT_RGB16_565)
 
 /****************************************************************************
  * Private Types
@@ -145,9 +202,8 @@ struct st7796_dev_s
   struct fb_vtable_s vtable;
   FAR struct spi_dev_s *spi;
   FAR uint8_t *fbmem;
-  FAR uint16_t *swap_buf;             /* Persistent buffer for byte-swapping */
-  struct st7796_config_s config;      /* Board-provided configuration */
-  uint16_t rotation;                  /* Current rotation in degrees */
+  FAR uint16_t *swap_buf;  /* Persistent buffer for byte-swapping */
+  uint16_t rotation;       /* Current rotation in degrees */
   bool power;
 };
 
@@ -161,6 +217,9 @@ static int st7796_getplaneinfo(FAR struct fb_vtable_s 
*vtable, int planeno,
                                FAR struct fb_planeinfo_s *pinfo);
 static int st7796_updatearea(FAR struct fb_vtable_s *vtable,
                              FAR const struct fb_area_s *area);
+static int st7796_getpower(FAR struct fb_vtable_s *vtable);
+static int st7796_setpower(FAR struct fb_vtable_s *vtable,
+                           int power);
 static int st7796_ioctl(FAR struct fb_vtable_s *vtable, int cmd,
                         unsigned long arg);
 static void st7796_select(FAR struct st7796_dev_s *priv);
@@ -311,7 +370,7 @@ static void st7796_select(FAR struct st7796_dev_s *priv)
   SPI_LOCK(priv->spi, true);
   SPI_SETMODE(priv->spi, ST7796_SPIMODE);
   SPI_SETBITS(priv->spi, 8);
-  SPI_SETFREQUENCY(priv->spi, priv->config.frequency);
+  SPI_SETFREQUENCY(priv->spi, CONFIG_LCD_ST7796_FREQUENCY);
   SPI_SELECT(priv->spi, SPIDEV_DISPLAY(0), true);
 }
 
@@ -354,8 +413,12 @@ static void st7796_deselect(FAR struct st7796_dev_s *priv)
 
 static void st7796_sendcmd(FAR struct st7796_dev_s *priv, uint8_t cmd)
 {
+#ifdef CONFIG_SPI_CMDDATA
   SPI_CMDDATA(priv->spi, SPIDEV_DISPLAY(0), true);
   SPI_SEND(priv->spi, cmd);
+#else
+#  error "CONFIG_SPI_CMDDATA must be enabled for ST7796"
+#endif
 }
 
 /****************************************************************************
@@ -380,8 +443,12 @@ static void st7796_senddata(FAR struct st7796_dev_s *priv,
 {
   if (len > 0 && data != NULL)
     {
+#ifdef CONFIG_SPI_CMDDATA
       SPI_CMDDATA(priv->spi, SPIDEV_DISPLAY(0), false);
       SPI_SNDBLOCK(priv->spi, data, len);
+#else
+#  error "CONFIG_SPI_CMDDATA must be enabled for ST7796"
+#endif
     }
 }
 
@@ -415,7 +482,6 @@ static void st7796_send_sequence(FAR struct st7796_dev_s 
*priv,
   for (i = 0; i < count; i++)
     {
       st7796_sendcmd(priv, seq[i].cmd);
-
       if (seq[i].data != NULL && seq[i].len > 0)
         {
           st7796_senddata(priv, seq[i].data, seq[i].len);
@@ -493,9 +559,9 @@ static void st7796_apply_rotation(FAR struct st7796_dev_s 
*priv)
   uint8_t madctl;
   uint8_t data[1];
 
-  /* Start with base MADCTL from config */
+  /* Start with base MADCTL from orientation and BGR config */
 
-  madctl = priv->config.madctl;
+  madctl = ST7796_MADCTL_BASE;
 
   /* Apply rotation by modifying MX/MY bits */
 
@@ -567,13 +633,11 @@ static void st7796_apply_rotation(FAR struct st7796_dev_s 
*priv)
 static int st7796_getvideoinfo(FAR struct fb_vtable_s *vtable,
                                FAR struct fb_videoinfo_s *vinfo)
 {
-  FAR struct st7796_dev_s *priv = (FAR struct st7796_dev_s *)vtable;
-
   lcdinfo("ST7796: getvideoinfo\n");
 
-  vinfo->fmt     = ST7796_COLORFMT(priv->config.bpp);
-  vinfo->xres    = priv->config.xres;
-  vinfo->yres    = priv->config.yres;
+  vinfo->fmt     = ST7796_COLORFMT;
+  vinfo->xres    = ST7796_XRES;
+  vinfo->yres    = ST7796_YRES;
   vinfo->nplanes = 1;
 
   return OK;
@@ -607,15 +671,15 @@ static int st7796_getplaneinfo(FAR struct fb_vtable_s 
*vtable, int planeno,
 
   lcdinfo("ST7796: getplaneinfo - plane %d\n", planeno);
 
-  bytespp = ST7796_BYTESPP(priv->config.bpp);
-  fbsize = priv->config.xres * priv->config.yres * bytespp;
+  bytespp = ST7796_BYTESPP;
+  fbsize = ST7796_XRES * ST7796_YRES * bytespp;
 
   pinfo->fbmem        = priv->fbmem;
   pinfo->fblen        = fbsize;
-  pinfo->stride       = priv->config.xres * bytespp;
-  pinfo->bpp          = priv->config.bpp;
-  pinfo->xres_virtual = priv->config.xres;
-  pinfo->yres_virtual = priv->config.yres;
+  pinfo->stride       = ST7796_XRES * bytespp;
+  pinfo->bpp          = CONFIG_LCD_ST7796_BPP;
+  pinfo->xres_virtual = ST7796_XRES;
+  pinfo->yres_virtual = ST7796_YRES;
   pinfo->xoffset      = 0;
   pinfo->yoffset      = 0;
 
@@ -655,7 +719,7 @@ static int st7796_updatearea(FAR struct fb_vtable_s *vtable,
   lcdinfo("ST7796: updatearea - x=%d y=%d w=%d h=%d\n",
           area->x, area->y, area->w, area->h);
 
-  bytespp = ST7796_BYTESPP(priv->config.bpp);
+  bytespp = ST7796_BYTESPP;
 
   st7796_select(priv);
   st7796_setarea(priv, area->x, area->y,
@@ -664,12 +728,14 @@ static int st7796_updatearea(FAR struct fb_vtable_s 
*vtable,
 
   st7796_sendcmd(priv, ST7796_RAMWR);
 
+#ifdef CONFIG_SPI_CMDDATA
   SPI_CMDDATA(priv->spi, SPIDEV_DISPLAY(0), false);
+#endif
 
   row_size_pixels = area->w;
   src_fbptr = (FAR uint16_t *)
               (priv->fbmem +
-               (area->y * priv->config.xres + area->x) * bytespp);
+               (area->y * ST7796_XRES + area->x) * bytespp);
 
   for (row = 0; row < area->h; row++)
     {
@@ -682,7 +748,7 @@ static int st7796_updatearea(FAR struct fb_vtable_s *vtable,
       SPI_SNDBLOCK(priv->spi, (FAR const uint8_t *)priv->swap_buf,
                    row_size_pixels * bytespp);
 
-      src_fbptr += priv->config.xres;
+      src_fbptr += ST7796_XRES;
     }
 
   st7796_deselect(priv);
@@ -690,6 +756,54 @@ static int st7796_updatearea(FAR struct fb_vtable_s 
*vtable,
   return OK;
 }
 
+/****************************************************************************
+ * Name: st7796_getpower
+ *
+ * Description:
+ *   Get current panel power state.
+ *
+ * Returned Value:
+ *   Current power level (0 = off, 1 = on).
+ ****************************************************************************/
+
+static int st7796_getpower(FAR struct fb_vtable_s *vtable)
+{
+  FAR struct st7796_dev_s *priv =
+      (FAR struct st7796_dev_s *)vtable;
+
+  return priv->power ? 1 : 0;
+}
+
+/****************************************************************************
+ * Name: st7796_setpower
+ *
+ * Description:
+ *   Enable or disable panel power (backlight).
+ *   Delegates to st7796_board_power() which the board must
+ *   implement to control the backlight GPIO.
+ *
+ * Input Parameters:
+ *   vtable - Reference to the framebuffer virtual table
+ *   power  - 0 to turn off, >0 to turn on
+ *
+ * Returned Value:
+ *   OK on success.
+ ****************************************************************************/
+
+static int st7796_setpower(FAR struct fb_vtable_s *vtable,
+                           int power)
+{
+  FAR struct st7796_dev_s *priv =
+      (FAR struct st7796_dev_s *)vtable;
+
+  priv->power = (power > 0);
+  st7796_board_power(priv->power);
+
+  lcdinfo("ST7796: power %s\n", priv->power ? "ON" : "OFF");
+
+  return OK;
+}
+
 /****************************************************************************
  * Name: st7796_ioctl
  *
@@ -800,9 +914,9 @@ static void st7796_init_display(FAR struct st7796_dev_s 
*priv)
 {
   uint8_t madctl_data[1];
 
-  /* MADCTL value from board configuration */
+  /* MADCTL value from orientation and BGR Kconfig settings */
 
-  madctl_data[0] = priv->config.madctl;
+  madctl_data[0] = ST7796_MADCTL_BASE;
 
   /* Initialization sequence - Part 1: Reset and wake */
 
@@ -818,20 +932,25 @@ static void st7796_init_display(FAR struct st7796_dev_s 
*priv)
 
   static const struct st7796_cmd_s init_seq_part2[] =
   {
-    { ST7796_PIXFMT,   g_pixfmt_data,   1,  0   },
-    { ST7796_INVCTR,   g_invctr_data,   1,  0   },
-    { ST7796_DFC,      g_dfc_data,      3,  0   },
-    { 0xe8,            g_cmd_e8_data,   8,  0   },
-    { ST7796_PWCTRL2,  g_pwctrl2_data,  1,  0   },
-    { ST7796_PWCTRL3,  g_pwctrl3_data,  1,  0   },
-    { ST7796_VCOM,     g_vcom_data,     1,  0   },
-    { ST7796_GAMMAPOS, g_gammapos_data, 14, 0   },
-    { ST7796_GAMMANEG, g_gammaneg_data, 14, 0   },
-    { ST7796_CSCON,    g_cscon3_data,   1,  0   },
-    { ST7796_CSCON,    g_cscon4_data,   1,  0   },
-    { ST7796_INVON,    NULL,            0,  10  },
-    { ST7796_NORON,    NULL,            0,  10  },
-    { ST7796_DISPON,   NULL,            0,  120 },
+    { ST7796_PIXFMT,   g_pixfmt_data,   1,  0 },
+    { ST7796_INVCTR,   g_invctr_data,   1,  0 },
+    { ST7796_DFC,      g_dfc_data,      3,  0 },
+    { 0xe8,            g_cmd_e8_data,   8,  0 },
+    { ST7796_PWCTRL2,  g_pwctrl2_data,  1,  0 },
+    { ST7796_PWCTRL3,  g_pwctrl3_data,  1,  0 },
+    { ST7796_VCOM,     g_vcom_data,     1,  0 },
+    { ST7796_GAMMAPOS, g_gammapos_data, 14, 0 },
+    { ST7796_GAMMANEG, g_gammaneg_data, 14, 0 },
+    { ST7796_CSCON,    g_cscon3_data,   1,  0 },
+    { ST7796_CSCON,    g_cscon4_data,   1,  0 },
+  };
+
+  /* Initialization sequence - Part 3: Enable */
+
+  static const struct st7796_cmd_s init_seq_part3[] =
+  {
+    { ST7796_NORON,  NULL, 0, 10  },
+    { ST7796_DISPON, NULL, 0, 120 },
   };
 
   st7796_select(priv);
@@ -846,15 +965,31 @@ static void st7796_init_display(FAR struct st7796_dev_s 
*priv)
   st7796_sendcmd(priv, ST7796_MADCTL);
   st7796_senddata(priv, madctl_data, 1);
 
-  /* Send part 2: Configuration and enable */
+  /* Send part 2: Configuration */
 
   st7796_send_sequence(priv, init_seq_part2,
-                       sizeof(init_seq_part2) / sizeof(struct st7796_cmd_s));
+                       sizeof(init_seq_part2) /
+                       sizeof(struct st7796_cmd_s));
+
+  /* Apply color inversion from Kconfig */
+
+#ifdef CONFIG_LCD_ST7796_INVCOLOR
+  st7796_sendcmd(priv, ST7796_INVON);
+#else
+  st7796_sendcmd(priv, ST7796_INVOFF);
+#endif
+  nxsig_usleep(10 * 1000);
+
+  /* Send part 3: Enable display */
+
+  st7796_send_sequence(priv, init_seq_part3,
+                       sizeof(init_seq_part3) /
+                       sizeof(struct st7796_cmd_s));
 
   st7796_deselect(priv);
 
   lcdinfo("ST7796: Display initialized (MADCTL=0x%02x)\n",
-          priv->config.madctl);
+          ST7796_MADCTL_BASE);
 
   /* Apply initial rotation if configured */
 
@@ -888,36 +1023,30 @@ static void st7796_init_display(FAR struct st7796_dev_s 
*priv)
  *
  ****************************************************************************/
 
-FAR struct fb_vtable_s *st7796_fbinitialize(FAR struct spi_dev_s *spi,
-                                            FAR const struct st7796_config_s
-                                            *config)
+FAR struct fb_vtable_s *st7796_fbinitialize(FAR struct spi_dev_s *spi)
 {
   FAR struct st7796_dev_s *priv = &g_st7796dev;
   size_t fbsize;
   uint8_t bytespp;
 
-  DEBUGASSERT(spi != NULL && config != NULL);
+  DEBUGASSERT(spi != NULL);
 
   lcdinfo("ST7796: Initializing framebuffer driver\n");
   lcdinfo("ST7796: Resolution: %dx%d @ %d bpp\n",
-          config->xres, config->yres, config->bpp);
+          ST7796_XRES, ST7796_YRES, CONFIG_LCD_ST7796_BPP);
   lcdinfo("ST7796: SPI Frequency: %lu Hz\n",
-          (unsigned long)config->frequency);
+          (unsigned long)CONFIG_LCD_ST7796_FREQUENCY);
   lcdinfo("ST7796: MADCTL: 0x%02x, Rotation: %d\n",
-          config->madctl, config->rotation);
-
-  /* Copy configuration */
-
-  memcpy(&priv->config, config, sizeof(struct st7796_config_s));
+          ST7796_MADCTL_BASE, CONFIG_LCD_ST7796_ROTATION);
 
-  /* Set initial rotation from config */
+  /* Set initial rotation from Kconfig */
 
-  priv->rotation = config->rotation;
+  priv->rotation = CONFIG_LCD_ST7796_ROTATION;
 
-  /* Calculate sizes */
+  /* Calculate framebuffer size */
 
-  bytespp = ST7796_BYTESPP(config->bpp);
-  fbsize = config->xres * config->yres * bytespp;
+  bytespp = ST7796_BYTESPP;
+  fbsize = ST7796_XRES * ST7796_YRES * bytespp;
 
   /* Allocate framebuffer memory */
 
@@ -930,7 +1059,7 @@ FAR struct fb_vtable_s *st7796_fbinitialize(FAR struct 
spi_dev_s *spi,
 
   /* Allocate persistent row swap buffer to avoid malloc in updatearea */
 
-  priv->swap_buf = (FAR uint16_t *)kmm_malloc(config->xres * bytespp);
+  priv->swap_buf = (FAR uint16_t *)kmm_malloc(ST7796_XRES * bytespp);
   if (priv->swap_buf == NULL)
     {
       lcderr("ERROR: Failed to allocate swap buffer\n");
@@ -943,6 +1072,8 @@ FAR struct fb_vtable_s *st7796_fbinitialize(FAR struct 
spi_dev_s *spi,
   priv->vtable.getvideoinfo = st7796_getvideoinfo;
   priv->vtable.getplaneinfo = st7796_getplaneinfo;
   priv->vtable.updatearea   = st7796_updatearea;
+  priv->vtable.getpower     = st7796_getpower;
+  priv->vtable.setpower     = st7796_setpower;
   priv->vtable.ioctl        = st7796_ioctl;
   priv->spi                 = spi;
   priv->power               = false;
diff --git a/include/nuttx/lcd/st7796.h b/include/nuttx/lcd/st7796.h
index 8950cf2e2bb..a68cdad0426 100644
--- a/include/nuttx/lcd/st7796.h
+++ b/include/nuttx/lcd/st7796.h
@@ -31,71 +31,12 @@
 #include <stdint.h>
 #include <stdbool.h>
 
-/****************************************************************************
- * Pre-processor Definitions
- ****************************************************************************/
-
-/* Display raw dimensions (before orientation transform)
- *
- * These must be in the public header because board code needs them to
- * calculate the effective xres/yres based on Kconfig orientation settings
- * at compile-time. Without these, boards would need to hardcode dimensions.
- */
-
-#define ST7796_XRES_RAW         320
-#define ST7796_YRES_RAW         480
-
-/* Default SPI frequency
- *
- * Must be in the public header because board code uses this as a safe
- * default when the user hasn't specified a custom frequency via Kconfig.
- * Centralizes the datasheet specification to prevent duplication.
- */
-
-#define ST7796_SPI_MAXFREQUENCY 40000000
-
-/* Pre-defined MADCTL values for common orientations
- *
- * These must be in the public header because board code selects the
- * appropriate MADCTL value based on hardware orientation and RGB/BGR
- * panel type configured via Kconfig. This abstracts the internal MADCTL
- * bit manipulation from board code. Values are absolute to eliminate
- * dependency on internal bit definitions.
- */
-
-#define ST7796_MADCTL_PORTRAIT           0x40
-#define ST7796_MADCTL_PORTRAIT_BGR       0x48
-#define ST7796_MADCTL_RPORTRAIT          0x80
-#define ST7796_MADCTL_RPORTRAIT_BGR      0x88
-#define ST7796_MADCTL_LANDSCAPE          0x20
-#define ST7796_MADCTL_LANDSCAPE_BGR      0x28
-#define ST7796_MADCTL_RLANDSCAPE         0xe0
-#define ST7796_MADCTL_RLANDSCAPE_BGR     0xe8
-
 /****************************************************************************
  * Public Types
  ****************************************************************************/
 
 #ifndef __ASSEMBLY__
 
-/* Board-specific configuration passed to driver at initialization.
- *
- * This structure must be in the public header because it defines the
- * driver's configuration API. Board code instantiates and populates this
- * structure to configure the driver without requiring board-specific
- * Kconfig options in the generic driver.
- */
-
-struct st7796_config_s
-{
-  uint32_t frequency;       /* SPI clock frequency in Hz */
-  uint16_t xres;            /* Horizontal resolution (after orientation) */
-  uint16_t yres;            /* Vertical resolution (after orientation) */
-  uint16_t rotation;        /* Initial rotation: 0, 90, 180, or 270 */
-  uint8_t bpp;              /* Bits per pixel: 16 (RGB565) or 18 (RGB666) */
-  uint8_t madctl;           /* Base MADCTL register value for orientation */
-};
-
 /****************************************************************************
  * Public Function Prototypes
  ****************************************************************************/
@@ -111,14 +52,14 @@ extern "C"
  * Description:
  *   Initialize the ST7796 LCD controller as a framebuffer device.
  *
- *   This function initializes the ST7796 display controller using the
- *   provided configuration and returns a framebuffer virtual table.
- *   The driver uses CONFIG_SPI_CMDDATA to control the DC (Data/Command)
- *   pin automatically via the SPI driver.
+ *   This function initializes the ST7796 display controller and returns
+ *   a framebuffer virtual table. Display parameters (resolution, color
+ *   depth, orientation, frequency) are taken from CONFIG_LCD_ST7796_*
+ *   Kconfig options. The driver uses CONFIG_SPI_CMDDATA to control the
+ *   DC (Data/Command) pin automatically via the SPI driver.
  *
  * Input Parameters:
- *   spi    - SPI device instance configured for the ST7796
- *   config - Board-specific configuration (frequency, resolution, etc.)
+ *   spi - SPI device instance configured for the ST7796
  *
  * Returned Value:
  *   Pointer to framebuffer vtable on success; NULL on failure.
@@ -131,9 +72,7 @@ extern "C"
  *
  ****************************************************************************/
 
-FAR struct fb_vtable_s *st7796_fbinitialize(FAR struct spi_dev_s *spi,
-                                            FAR const struct st7796_config_s
-                                            *config);
+FAR struct fb_vtable_s *st7796_fbinitialize(FAR struct spi_dev_s *spi);
 
 /****************************************************************************
  * Name: st7796_setrotation
@@ -170,6 +109,22 @@ int st7796_setrotation(FAR struct fb_vtable_s *vtable, 
uint16_t rotation);
 
 uint16_t st7796_getrotation(FAR struct fb_vtable_s *vtable);
 
+/****************************************************************************
+ * Name: st7796_board_power
+ *
+ * Description:
+ *   Board-level callback to control display backlight/power.
+ *   Called by the ST7796 driver when FBIOSET_POWER ioctl is
+ *   received. The board must implement this function to
+ *   control the backlight GPIO pin.
+ *
+ * Input Parameters:
+ *   on - true to turn backlight on, false to turn off
+ *
+ ****************************************************************************/
+
+void st7796_board_power(bool on);
+
 #ifdef __cplusplus
 }
 #endif

Reply via email to