You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by ac...@apache.org on 2021/09/16 11:39:41 UTC

[incubator-nuttx] branch master updated: drivers/lcd: Add GC9A01 driver and refine ST7735

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/incubator-nuttx.git


The following commit(s) were added to refs/heads/master by this push:
     new a5406c6  drivers/lcd: Add GC9A01 driver and refine ST7735
a5406c6 is described below

commit a5406c63cb57686492cd052afd732db58e6a8c86
Author: Peter Bee <bi...@xiaomi.com>
AuthorDate: Thu Sep 16 11:55:39 2021 +0800

    drivers/lcd: Add GC9A01 driver and refine ST7735
    
    Added custom resolution, offset and BGR mode for ST7735 driver
    Added GC9A01 driver (based on ST7789 driver)
    
    Signed-off-by: Peter Bee <bi...@xiaomi.com>
---
 drivers/lcd/Kconfig                |  97 ++++++-
 drivers/lcd/Make.defs              |   4 +
 drivers/lcd/{st7735.c => gc9a01.c} | 503 +++++++++++++++++++++++++------------
 drivers/lcd/gc9a01.h               |  71 ++++++
 drivers/lcd/st7735.c               |  95 +++++--
 drivers/lcd/st7735.h               |  11 +
 include/nuttx/lcd/gc9a01.h         |  72 ++++++
 7 files changed, 668 insertions(+), 185 deletions(-)

diff --git a/drivers/lcd/Kconfig b/drivers/lcd/Kconfig
index bd8f6d6..58bbf4c 100644
--- a/drivers/lcd/Kconfig
+++ b/drivers/lcd/Kconfig
@@ -569,12 +569,52 @@ config LCD_ST7735
 	default n
 
 if LCD_ST7735
-	config LCD_ST7735_GM00
-		bool "132x162 Display Resolution"
+	choice
+		prompt "LCD Preset Resolutions"
+		optional
+
+		config LCD_ST7735_GM11
+			bool "128x160"
+
+		config LCD_ST7735_GM00
+			bool "132x162"
+
+		config LCD_ST7735_GM01
+			bool "132x132"
+
+	endchoice
+
+if  !LCD_ST7735_GM00 && !LCD_ST7735_GM01 && !LCD_ST7735_GM11
+
+	config LCD_ST7735_XRES
+	int "ST7735 X Resolution"
+	default 128
+	---help---
+		Specifies the X resolution of the LCD.
+
+	config LCD_ST7735_YRES
+	int "ST7735 Y Resolution"
+	default 160
+	---help---
+		Specifies the Y resolution of the LCD.
+
+	config LCD_ST7735_XOFFSET
+	int "ST7735 X Offset"
+	default 0
+	---help---
+		Specifies the X offset of the LCD.
+
+	config LCD_ST7735_YOFFSET
+	int "ST7735 Y Offset"
+	default 0
+	---help---
+		Specifies the Y offset of the LCD.
+
+endif
+
+	config LCD_ST7735_BGR
+		bool "Swap R & B channel"
 		default n
-		---help---
-			Two resolutions are available, either the 132x162 or
-			the 128x160
 
 	config LCD_ST7735_BPP
 		int "Bit Per Pixel (12, 16 or 18)"
@@ -633,6 +673,53 @@ if LCD_ST7789
 
 endif # LCD_ST7789
 
+config LCD_GC9A01
+	bool "Galaxycore GC9A01 TFT Controller"
+	default n
+
+if LCD_GC9A01
+	config LCD_GC9A01_XRES
+		int "GC9A01 X Resolution"
+		default 240
+		---help---
+			Specifies the X resolution of the LCD.
+
+	config LCD_GC9A01_YRES
+		int "GC9A01 Y Resolution"
+		default 240
+		---help---
+			Specifies the Y resolution of the LCD.
+
+	config LCD_GC9A01_XOFFSET
+		int "GC9A01 X Offset"
+		default 0
+		---help---
+			Specifies the X offset of the LCD.
+
+	config LCD_GC9A01_YOFFSET
+		int "GC9A01 Y Offset"
+		default 0
+		---help---
+			Specifies the Y offset of the LCD.
+
+	config LCD_GC9A01_BGR
+		bool "Swap R & B channel"
+		default n
+
+	config LCD_GC9A01_BPP
+		int "Bit Per Pixel (12 or 16)"
+		default 16
+
+	config LCD_GC9A01_SPIMODE
+		int "SPI Mode"
+		default 0
+
+	config LCD_GC9A01_FREQUENCY
+		int "SPI Frequency"
+		default 1000000
+
+endif # LCD_GC9A01
+
 config LCD_PCD8544
 	bool "Nokia 5110 LCD Display (Philips PCD8544)"
 	default n
diff --git a/drivers/lcd/Make.defs b/drivers/lcd/Make.defs
index 058c497..4f59a45 100644
--- a/drivers/lcd/Make.defs
+++ b/drivers/lcd/Make.defs
@@ -133,6 +133,10 @@ ifeq ($(CONFIG_LCD_ST7789),y)
   CSRCS += st7789.c
 endif
 
+ifeq ($(CONFIG_LCD_GC9A01),y)
+  CSRCS += gc9a01.c
+endif
+
 endif # CONFIG_LCD
 
 ifeq ($(CONFIG_SLCD),y)
diff --git a/drivers/lcd/st7735.c b/drivers/lcd/gc9a01.c
similarity index 50%
copy from drivers/lcd/st7735.c
copy to drivers/lcd/gc9a01.c
index e663409..6f8de70 100644
--- a/drivers/lcd/st7735.c
+++ b/drivers/lcd/gc9a01.c
@@ -1,5 +1,5 @@
 /****************************************************************************
- * drivers/lcd/st7735.c
+ * drivers/lcd/gc9a01.c
  *
  * Licensed to the Apache Software Foundation (ASF) under one or more
  * contributor license agreements.  See the NOTICE file distributed with
@@ -35,11 +35,11 @@
 #include <nuttx/arch.h>
 #include <nuttx/spi/spi.h>
 #include <nuttx/lcd/lcd.h>
-#include <nuttx/lcd/st7735.h>
+#include <nuttx/lcd/gc9a01.h>
 
-#include "st7735.h"
+#include "gc9a01.h"
 
-#ifdef CONFIG_LCD_ST7735
+#ifdef CONFIG_LCD_GC9A01
 
 /****************************************************************************
  * Pre-processor Definitions
@@ -47,14 +47,14 @@
 
 /* Verify that all configuration requirements have been met */
 
-#ifndef CONFIG_LCD_ST7735_SPIMODE
-#  define CONFIG_LCD_ST7735_SPIMODE SPIDEV_MODE0
+#ifndef CONFIG_LCD_GC9A01_SPIMODE
+#  define CONFIG_LCD_GC9A01_SPIMODE SPIDEV_MODE0
 #endif
 
 /* SPI frequency */
 
-#ifndef CONFIG_LCD_ST7735_FREQUENCY
-#  define CONFIG_LCD_ST7735_FREQUENCY 3000000
+#ifndef CONFIG_LCD_GC9A01_FREQUENCY
+#  define CONFIG_LCD_GC9A01_FREQUENCY 1000000
 #endif
 
 /* Check contrast selection */
@@ -94,43 +94,43 @@
 
 /* Display Resolution */
 
-#ifdef CONFIG_LCD_ST7735_GM00
-#  define CONFIG_ST7735_XRES 132
-#  define CONFIG_ST7735_YRES 162
-#  define ST7735_LUT_SIZE    162
-#else
-#  define CONFIG_ST7735_XRES 128
-#  define CONFIG_ST7735_YRES 160
-#  define ST7735_LUT_SIZE    160
+#if !defined(CONFIG_LCD_GC9A01_XRES)
+#  define CONFIG_LCD_GC9A01_XRES 240
+#endif
+
+#if !defined(CONFIG_LCD_GC9A01_YRES)
+#  define CONFIG_LCD_GC9A01_YRES 320
 #endif
 
+#define GC9A01_LUT_SIZE    CONFIG_LCD_GC9A01_YRES
+
 #if defined(CONFIG_LCD_LANDSCAPE) || defined(CONFIG_LCD_RLANDSCAPE)
-#  define ST7735_XRES       CONFIG_ST7735_YRES
-#  define ST7735_YRES       CONFIG_ST7735_XRES
+#  define GC9A01_XRES       CONFIG_LCD_GC9A01_YRES
+#  define GC9A01_YRES       CONFIG_LCD_GC9A01_XRES
+#  define GC9A01_XOFFSET    CONFIG_LCD_GC9A01_YOFFSET
+#  define GC9A01_YOFFSET    CONFIG_LCD_GC9A01_XOFFSET
 #else
-#  define ST7735_XRES       CONFIG_ST7735_XRES
-#  define ST7735_YRES       CONFIG_ST7735_YRES
+#  define GC9A01_XRES       CONFIG_LCD_GC9A01_XRES
+#  define GC9A01_YRES       CONFIG_LCD_GC9A01_YRES
+#  define GC9A01_XOFFSET    CONFIG_LCD_GC9A01_XOFFSET
+#  define GC9A01_YOFFSET    CONFIG_LCD_GC9A01_YOFFSET
 #endif
 
 /* Color depth and format */
 
-#ifdef CONFIG_LCD_ST7735_BPP
-#  if (CONFIG_LCD_ST7735_BPP == 12)
-#    define ST7735_BPP           12
-#    define ST7735_COLORFMT      FB_FMT_RGB12_444
-#    define ST7735_BYTESPP       2
-#  elif (CONFIG_LCD_ST7735_BPP == 16)
-#    define ST7735_BPP           16
-#    define ST7735_COLORFMT      FB_FMT_RGB16_565
-#    define ST7735_BYTESPP       2
-#  elif (CONFIG_LCD_ST7735_BPP == 18)
-#    define ST7735_BPP           18
-#    define ST7735_COLORFMT      FB_FMT_RGB16_666
-#    define ST7735_BYTESPP       3
+#ifdef CONFIG_LCD_GC9A01_BPP
+#  if (CONFIG_LCD_GC9A01_BPP == 12)
+#    define GC9A01_BPP           12
+#    define GC9A01_COLORFMT      FB_FMT_RGB12_444
+#    define GC9A01_BYTESPP       2
+#  elif (CONFIG_LCD_GC9A01_BPP == 16)
+#    define GC9A01_BPP           16
+#    define GC9A01_COLORFMT      FB_FMT_RGB16_565
+#    define GC9A01_BYTESPP       2
 #  else
-#    define ST7735_BPP           16
-#    define ST7735_COLORFMT      FB_FMT_RGB16_565
-#    define ST7735_BYTESPP       2
+#    define GC9A01_BPP           16
+#    define GC9A01_COLORFMT      FB_FMT_RGB16_565
+#    define GC9A01_BYTESPP       2
 #    warning "Invalid color depth.  Falling back to 16bpp"
 #  endif
 #endif
@@ -141,7 +141,7 @@
 
 /* This structure describes the state of this driver */
 
-struct st7735_dev_s
+struct gc9a01_dev_s
 {
   /* Publicly visible device structure */
 
@@ -165,7 +165,7 @@ struct st7735_dev_s
    * buffers.
    */
 
-  uint16_t runbuffer[ST7735_LUT_SIZE];
+  uint16_t runbuffer[GC9A01_LUT_SIZE];
 };
 
 /****************************************************************************
@@ -174,59 +174,68 @@ struct st7735_dev_s
 
 /* Misc. Helpers */
 
-static void st7735_select(FAR struct spi_dev_s *spi, int bits);
-static void st7735_deselect(FAR struct spi_dev_s *spi);
-
-static inline void st7735_sendcmd(FAR struct st7735_dev_s *dev, uint8_t cmd);
-static void st7735_sleep(FAR struct st7735_dev_s *dev, bool sleep);
-static void st7735_display(FAR struct st7735_dev_s *dev, bool on);
-static void st7735_setarea(FAR struct st7735_dev_s *dev,
+static void gc9a01_select(FAR struct spi_dev_s *spi, int bits);
+static void gc9a01_deselect(FAR struct spi_dev_s *spi);
+
+static inline void gc9a01_sendcmd(FAR struct gc9a01_dev_s *dev, uint8_t cmd);
+static void gc9a01_cmddata(FAR struct gc9a01_dev_s *dev, uint8_t cmd,
+                               const uint8_t *data, int len);
+static void gc9a01_init(FAR struct gc9a01_dev_s *dev);
+static void gc9a01_sleep(FAR struct gc9a01_dev_s *dev, bool sleep);
+static void gc9a01_setorientation(FAR struct gc9a01_dev_s *dev);
+static void gc9a01_display(FAR struct gc9a01_dev_s *dev, bool on);
+static void gc9a01_setarea(FAR struct gc9a01_dev_s *dev,
                            uint16_t x0, uint16_t y0,
                            uint16_t x1, uint16_t y1);
-static void st7735_bpp(FAR struct st7735_dev_s *dev, int bpp);
-static void st7735_wrram(FAR struct st7735_dev_s *dev,
+static void gc9a01_bpp(FAR struct gc9a01_dev_s *dev, int bpp);
+static void gc9a01_wrram(FAR struct gc9a01_dev_s *dev,
                          FAR const uint16_t *buff, size_t size);
-static void st7735_rdram(FAR struct st7735_dev_s *dev,
+#ifndef CONFIG_LCD_NOGETRUN
+static void gc9a01_rdram(FAR struct gc9a01_dev_s *dev,
                          FAR uint16_t *buff, size_t size);
-static void st7735_fill(FAR struct st7735_dev_s *dev, uint16_t color);
+#endif
+static void gc9a01_fill(FAR struct gc9a01_dev_s *dev, uint16_t color);
 
 /* LCD Data Transfer Methods */
 
-static int st7735_putrun(fb_coord_t row, fb_coord_t col,
+static int gc9a01_putrun(fb_coord_t row, fb_coord_t col,
                          FAR const uint8_t *buffer, size_t npixels);
+static int gc9a01_putarea(fb_coord_t row_start, fb_coord_t row_end,
+                          fb_coord_t col_start, fb_coord_t col_end,
+                          FAR const uint8_t *buffer);
 #ifndef CONFIG_LCD_NOGETRUN
-static int st7735_getrun(fb_coord_t row, fb_coord_t col,
+static int gc9a01_getrun(fb_coord_t row, fb_coord_t col,
                          FAR uint8_t *buffer, size_t npixels);
 #endif
 
 /* LCD Configuration */
 
-static int st7735_getvideoinfo(FAR struct lcd_dev_s *dev,
+static int gc9a01_getvideoinfo(FAR struct lcd_dev_s *dev,
                                FAR struct fb_videoinfo_s *vinfo);
-static int st7735_getplaneinfo(FAR struct lcd_dev_s *dev,
+static int gc9a01_getplaneinfo(FAR struct lcd_dev_s *dev,
                                unsigned int planeno,
                                FAR struct lcd_planeinfo_s *pinfo);
 
 /* LCD Specific Controls */
 
-static int st7735_getpower(FAR struct lcd_dev_s *dev);
-static int st7735_setpower(FAR struct lcd_dev_s *dev, int power);
-static int st7735_getcontrast(FAR struct lcd_dev_s *dev);
-static int st7735_setcontrast(FAR struct lcd_dev_s *dev,
+static int gc9a01_getpower(FAR struct lcd_dev_s *dev);
+static int gc9a01_setpower(FAR struct lcd_dev_s *dev, int power);
+static int gc9a01_getcontrast(FAR struct lcd_dev_s *dev);
+static int gc9a01_setcontrast(FAR struct lcd_dev_s *dev,
                               unsigned int contrast);
 
 /****************************************************************************
  * Private Data
  ****************************************************************************/
 
-static struct st7735_dev_s g_lcddev;
+static struct gc9a01_dev_s g_lcddev;
 
 /****************************************************************************
  * Private Functions
  ****************************************************************************/
 
 /****************************************************************************
- * Name: st7735_select
+ * Name: gc9a01_select
  *
  * Description:
  *   Select the SPI, locking and  re-configuring if necessary
@@ -242,26 +251,26 @@ static struct st7735_dev_s g_lcddev;
  *
  ****************************************************************************/
 
-static void st7735_select(FAR struct spi_dev_s *spi, int bits)
+static void gc9a01_select(FAR struct spi_dev_s *spi, int bits)
 {
-  /* Select ST7735 chip (locking the SPI bus in case there are multiple
+  /* Select GC9A01 chip (locking the SPI bus in case there are multiple
    * devices competing for the SPI bus
    */
 
   SPI_LOCK(spi, true);
   SPI_SELECT(spi, SPIDEV_DISPLAY(0), true);
 
-  /* Now make sure that the SPI bus is configured for the ST7735 (it
+  /* Now make sure that the SPI bus is configured for the GC9A01 (it
    * might have gotten configured for a different device while unlocked)
    */
 
-  SPI_SETMODE(spi, CONFIG_LCD_ST7735_SPIMODE);
+  SPI_SETMODE(spi, CONFIG_LCD_GC9A01_SPIMODE);
   SPI_SETBITS(spi, bits);
-  SPI_SETFREQUENCY(spi, CONFIG_LCD_ST7735_FREQUENCY);
+  SPI_SETFREQUENCY(spi, CONFIG_LCD_GC9A01_FREQUENCY);
 }
 
 /****************************************************************************
- * Name: st7735_deselect
+ * Name: gc9a01_deselect
  *
  * Description:
  *   De-select the SPI
@@ -276,96 +285,226 @@ static void st7735_select(FAR struct spi_dev_s *spi, int bits)
  *
  ****************************************************************************/
 
-static void st7735_deselect(FAR struct spi_dev_s *spi)
+static void gc9a01_deselect(FAR struct spi_dev_s *spi)
 {
-  /* De-select ST7735 chip and relinquish the SPI bus. */
+  /* De-select GC9A01 chip and relinquish the SPI bus. */
 
   SPI_SELECT(spi, SPIDEV_DISPLAY(0), false);
   SPI_LOCK(spi, false);
 }
 
 /****************************************************************************
- * Name: st7735_sendcmd
+ * Name: gc9a01_sendcmd
  *
  * Description:
  *   Send a command to the driver.
  *
  ****************************************************************************/
 
-static inline void st7735_sendcmd(FAR struct st7735_dev_s *dev, uint8_t cmd)
+static inline void gc9a01_sendcmd(FAR struct gc9a01_dev_s *dev, uint8_t cmd)
+{
+  gc9a01_select(dev->spi, 8);
+  SPI_CMDDATA(dev->spi, SPIDEV_DISPLAY(0), true);
+  SPI_SEND(dev->spi, cmd);
+  SPI_CMDDATA(dev->spi, SPIDEV_DISPLAY(0), false);
+  gc9a01_deselect(dev->spi);
+}
+
+/****************************************************************************
+ * Name: gc9a01_cmddata
+ *
+ * Description:
+ *   Send a command and a series of data to the driver.
+ *
+ ****************************************************************************/
+
+static void gc9a01_cmddata(FAR struct gc9a01_dev_s *dev, uint8_t cmd,
+                                      const uint8_t *data, int len)
 {
-  st7735_select(dev->spi, 8);
+  gc9a01_select(dev->spi, 8);
   SPI_CMDDATA(dev->spi, SPIDEV_DISPLAY(0), true);
   SPI_SEND(dev->spi, cmd);
   SPI_CMDDATA(dev->spi, SPIDEV_DISPLAY(0), false);
-  st7735_deselect(dev->spi);
+  SPI_SNDBLOCK(dev->spi, data, len);
+  gc9a01_deselect(dev->spi);
 }
 
 /****************************************************************************
- * Name: st7735_sleep
+ * Name: gc9a01_init
+ *
+ * Description:
+ *   Send gc9a01 internal init commands.
+ *
+ ****************************************************************************/
+
+static void gc9a01_init(FAR struct gc9a01_dev_s *dev)
+{
+  gc9a01_sendcmd(dev, GC9A01_SWRESET);
+  up_mdelay(120);
+  gc9a01_sendcmd(dev, GC9A01_ENIREG2);
+  gc9a01_cmddata(dev, 0xeb, (const uint8_t *) "\x14", 1);
+  gc9a01_sendcmd(dev, GC9A01_ENIREG1);
+  gc9a01_sendcmd(dev, GC9A01_ENIREG2);
+  gc9a01_cmddata(dev, 0xeb, (const uint8_t *) "\x14", 1);
+  gc9a01_cmddata(dev, 0x84, (const uint8_t *) "\x40", 1);
+  gc9a01_cmddata(dev, 0x85, (const uint8_t *) "\xFF", 1);
+  gc9a01_cmddata(dev, 0x86, (const uint8_t *) "\xFF", 1);
+  gc9a01_cmddata(dev, 0x87, (const uint8_t *) "\xFF", 1);
+  gc9a01_cmddata(dev, 0x88, (const uint8_t *) "\x0A", 1);
+  gc9a01_cmddata(dev, 0x89, (const uint8_t *) "\x21", 1);
+  gc9a01_cmddata(dev, 0x8a, (const uint8_t *) "\x00", 1);
+  gc9a01_cmddata(dev, 0x8b, (const uint8_t *) "\x80", 1);
+  gc9a01_cmddata(dev, 0x8c, (const uint8_t *) "\x01", 1);
+  gc9a01_cmddata(dev, 0x8d, (const uint8_t *) "\x01", 1);
+  gc9a01_cmddata(dev, 0x8e, (const uint8_t *) "\xFF", 1);
+  gc9a01_cmddata(dev, 0x8f, (const uint8_t *) "\xFF", 1);
+  gc9a01_cmddata(dev, 0xb6, (const uint8_t *) "\x00\x00", 2);
+  gc9a01_cmddata(dev, 0x3a, (const uint8_t *) "\x55", 1);
+  gc9a01_cmddata(dev, 0x90, (const uint8_t *) "\x08\x08\x08\x08", 4);
+  gc9a01_cmddata(dev, 0xbd, (const uint8_t *) "\x06", 1);
+  gc9a01_cmddata(dev, 0xbc, (const uint8_t *) "\x00", 1);
+  gc9a01_cmddata(dev, 0xff, (const uint8_t *) "\x60\x01\x04", 3);
+  gc9a01_cmddata(dev, 0xc3, (const uint8_t *) "\x13", 1);
+  gc9a01_cmddata(dev, 0xc4, (const uint8_t *) "\x13", 1);
+  gc9a01_cmddata(dev, 0xc9, (const uint8_t *) "\x22", 1);
+  gc9a01_cmddata(dev, 0xbe, (const uint8_t *) "\x11", 1);
+  gc9a01_cmddata(dev, 0xe1, (const uint8_t *) "\x10\x0E", 2);
+  gc9a01_cmddata(dev, 0xdf, (const uint8_t *) "\x21\x0c\x02", 3);
+  gc9a01_cmddata(dev, 0xf0, (const uint8_t *) "\x45\x09\x08\x08\x26\x2A", 6);
+  gc9a01_cmddata(dev, 0xf1, (const uint8_t *) "\x43\x70\x72\x36\x37\x6F", 6);
+  gc9a01_cmddata(dev, 0xf2, (const uint8_t *) "\x45\x09\x08\x08\x26\x2A", 6);
+  gc9a01_cmddata(dev, 0xf3, (const uint8_t *) "\x43\x70\x72\x36\x37\x6F", 6);
+  gc9a01_cmddata(dev, 0xed, (const uint8_t *) "\x1B\x0B", 2);
+  gc9a01_cmddata(dev, 0xae, (const uint8_t *) "\x77", 1);
+  gc9a01_cmddata(dev, 0xcd, (const uint8_t *) "\x63", 1);
+  gc9a01_cmddata(dev, 0x70, (const uint8_t *)
+                 "\x07\x07\x04\x0E\x0F\x09\x07\x08\x03", 9);
+  gc9a01_cmddata(dev, 0xe8, (const uint8_t *) "\x34", 1);
+  gc9a01_cmddata(dev, 0x62, (const uint8_t *)
+                 "\x18\x0D\x71\xED\x70\x70\x18\x0F\x71\xEF\x70\x70", 12);
+  gc9a01_cmddata(dev, 0x63, (const uint8_t *)
+                 "\x18\x11\x71\xF1\x70\x70\x18\x13\x71\xF3\x70\x70", 12);
+  gc9a01_cmddata(dev, 0x64, (const uint8_t *)
+                 "\x28\x29\xF1\x01\xF1\x00\x07", 7);
+  gc9a01_cmddata(dev, 0x66, (const uint8_t *)
+                 "\x3C\x00\xCD\x67\x45\x45\x10\x00\x00\x00", 10);
+  gc9a01_cmddata(dev, 0x67, (const uint8_t *)
+                 "\x00\x3C\x00\x00\x00\x01\x54\x10\x32\x98", 10);
+  gc9a01_cmddata(dev, 0x74, (const uint8_t *)
+                 "\x10\x85\x80\x00\x00\x4E\x00", 7);
+  gc9a01_cmddata(dev, 0x98, (const uint8_t *) "\x3e\x07", 2);
+  gc9a01_sendcmd(dev, GC9A01_TEON);
+  up_mdelay(120);
+}
+
+/****************************************************************************
+ * Name: gc9a01_sleep
  *
  * Description:
  *   Sleep or wake up the driver.
  *
  ****************************************************************************/
 
-static void st7735_sleep(FAR struct st7735_dev_s *dev, bool sleep)
+static void gc9a01_sleep(FAR struct gc9a01_dev_s *dev, bool sleep)
 {
-  st7735_sendcmd(dev, sleep ? ST7735_SLPIN : ST7735_SLPOUT);
+  gc9a01_sendcmd(dev, sleep ? GC9A01_SLPIN : GC9A01_SLPOUT);
   up_mdelay(120);
 }
 
 /****************************************************************************
- * Name: st7735_display
+ * Name: gc9a01_display
  *
  * Description:
  *   Turn on or off the display.
  *
  ****************************************************************************/
 
-static void st7735_display(FAR struct st7735_dev_s *dev, bool on)
+static void gc9a01_display(FAR struct gc9a01_dev_s *dev, bool on)
+{
+  gc9a01_sendcmd(dev, on ? GC9A01_DISPON : GC9A01_DISPOFF);
+  gc9a01_sendcmd(dev, GC9A01_INVON);
+}
+
+/****************************************************************************
+ * Name: gc9a01_setorientation
+ *
+ * Description:
+ *   Set screen orientation.
+ *
+ ****************************************************************************/
+
+static void gc9a01_setorientation(FAR struct gc9a01_dev_s *dev)
 {
-  st7735_sendcmd(dev, on ? ST7735_DISPON : ST7735_DISPOFF);
+  uint8_t reg = GC9A01_MADCTL_MX;
+  gc9a01_sendcmd(dev, GC9A01_MADCTL);
+  gc9a01_select(dev->spi, 8);
+
+#if !defined(CONFIG_LCD_PORTRAIT) || defined(CONFIG_LCD_GC9A01_BGR)
+
+#  if defined(CONFIG_LCD_RLANDSCAPE)
+
+  reg = GC9A01_MADCTL_MX | GC9A01_MADCTL_MY | GC9A01_MADCTL_MV;
+
+#  elif defined(CONFIG_LCD_LANDSCAPE)
+
+  reg = GC9A01_MADCTL_MV;
+
+#  elif defined(CONFIG_LCD_RPORTRAIT)
+
+  reg = GC9A01_MADCTL_MY;
+
+#  endif
+
+#  if defined(CONFIG_LCD_GC9A01_BGR)
+
+  reg |= GC9A01_MADCTL_BGR;
+
+#  endif
+
+#endif
+
+  SPI_SEND(dev->spi, reg);
+  gc9a01_deselect(dev->spi);
 }
 
 /****************************************************************************
- * Name: st7735_setarea
+ * Name: gc9a01_setarea
  *
  * Description:
  *   Set the rectangular area for an upcoming read or write from RAM.
  *
  ****************************************************************************/
 
-static void st7735_setarea(FAR struct st7735_dev_s *dev,
+static void gc9a01_setarea(FAR struct gc9a01_dev_s *dev,
                            uint16_t x0, uint16_t y0,
                            uint16_t x1, uint16_t y1)
 {
   /* Set row address */
 
-  st7735_sendcmd(dev, ST7735_RASET);
-  st7735_select(dev->spi, 16);
-  SPI_SEND(dev->spi, y0);
-  SPI_SEND(dev->spi, y1);
-  st7735_deselect(dev->spi);
+  gc9a01_sendcmd(dev, GC9A01_RASET);
+  gc9a01_select(dev->spi, 16);
+  SPI_SEND(dev->spi, y0 + GC9A01_YOFFSET);
+  SPI_SEND(dev->spi, y1 + GC9A01_YOFFSET);
+  gc9a01_deselect(dev->spi);
 
   /* Set column address */
 
-  st7735_sendcmd(dev, ST7735_CASET);
-  st7735_select(dev->spi, 16);
-  SPI_SEND(dev->spi, x0);
-  SPI_SEND(dev->spi, x1);
-  st7735_deselect(dev->spi);
+  gc9a01_sendcmd(dev, GC9A01_CASET);
+  gc9a01_select(dev->spi, 16);
+  SPI_SEND(dev->spi, x0 + GC9A01_XOFFSET);
+  SPI_SEND(dev->spi, x1 + GC9A01_XOFFSET);
+  gc9a01_deselect(dev->spi);
 }
 
 /****************************************************************************
- * Name: st7735_bpp
+ * Name: gc9a01_bpp
  *
  * Description:
  *   Set the color depth of the device.
  *
  ****************************************************************************/
 
-static void st7735_bpp(FAR struct st7735_dev_s *dev, int bpp)
+static void gc9a01_bpp(FAR struct gc9a01_dev_s *dev, int bpp)
 {
   uint8_t depth;
 
@@ -373,13 +512,11 @@ static void st7735_bpp(FAR struct st7735_dev_s *dev, int bpp)
 
   if (dev->bpp != bpp)
     {
-      /* REVISIT: Works only for 12 and 16 bpp! */
-
-      depth = bpp >> 2 | 1;
-      st7735_sendcmd(dev, ST7735_COLMOD);
-      st7735_select(dev->spi, 8);
+      depth = bpp / 2 - 3;
+      gc9a01_sendcmd(dev, GC9A01_COLMOD);
+      gc9a01_select(dev->spi, 8);
       SPI_SEND(dev->spi, depth);
-      st7735_deselect(dev->spi);
+      gc9a01_deselect(dev->spi);
 
       /* Cache the new BPP */
 
@@ -388,68 +525,70 @@ static void st7735_bpp(FAR struct st7735_dev_s *dev, int bpp)
 }
 
 /****************************************************************************
- * Name: st7735_wrram
+ * Name: gc9a01_wrram
  *
  * Description:
  *   Write to the driver's RAM.
  *
  ****************************************************************************/
 
-static void st7735_wrram(FAR struct st7735_dev_s *dev,
+static void gc9a01_wrram(FAR struct gc9a01_dev_s *dev,
                          FAR const uint16_t *buff, size_t size)
 {
-  st7735_sendcmd(dev, ST7735_RAMWR);
+  gc9a01_sendcmd(dev, GC9A01_RAMWR);
 
-  st7735_select(dev->spi, ST7735_BYTESPP * 8);
+  gc9a01_select(dev->spi, GC9A01_BYTESPP * 8);
   SPI_SNDBLOCK(dev->spi, buff, size);
-  st7735_deselect(dev->spi);
+  gc9a01_deselect(dev->spi);
 }
 
 /****************************************************************************
- * Name: st7735_rdram
+ * Name: gc9a01_rdram
  *
  * Description:
  *   Read from the driver's RAM.
  *
  ****************************************************************************/
 
-static void st7735_rdram(FAR struct st7735_dev_s *dev,
+#ifndef CONFIG_LCD_NOGETRUN
+static void gc9a01_rdram(FAR struct gc9a01_dev_s *dev,
                          FAR uint16_t *buff, size_t size)
 {
-  st7735_sendcmd(dev, ST7735_RAMRD);
+  gc9a01_sendcmd(dev, GC9A01_RAMRD);
 
-  st7735_select(dev->spi, ST7735_BYTESPP * 8);
+  gc9a01_select(dev->spi, GC9A01_BYTESPP * 8);
   SPI_RECVBLOCK(dev->spi, buff, size);
-  st7735_deselect(dev->spi);
+  gc9a01_deselect(dev->spi);
 }
+#endif
 
 /****************************************************************************
- * Name: st7735_fill
+ * Name: gc9a01_fill
  *
  * Description:
  *   Fill the display with the specified color.
  *
  ****************************************************************************/
 
-static void st7735_fill(FAR struct st7735_dev_s *dev, uint16_t color)
+static void gc9a01_fill(FAR struct gc9a01_dev_s *dev, uint16_t color)
 {
   int i;
 
-  st7735_setarea(dev, 0, 0, ST7735_XRES - 1, ST7735_YRES - 1);
+  gc9a01_setarea(dev, 0, 0, GC9A01_XRES - 1, GC9A01_YRES - 1);
 
-  st7735_sendcmd(dev, ST7735_RAMWR);
-  st7735_select(dev->spi, ST7735_BYTESPP * 8);
+  gc9a01_sendcmd(dev, GC9A01_RAMWR);
+  gc9a01_select(dev->spi, GC9A01_BYTESPP *8);
 
-  for (i = 0; i < ST7735_XRES * ST7735_YRES; i++)
+  for (i = 0; i < GC9A01_XRES * GC9A01_YRES; i++)
     {
       SPI_SEND(dev->spi, color);
     }
 
-  st7735_deselect(dev->spi);
+  gc9a01_deselect(dev->spi);
 }
 
 /****************************************************************************
- * Name:  st7735_putrun
+ * Name:  gc9a01_putrun
  *
  * Description:
  *   This method can be used to write a partial raster line to the LCD:
@@ -462,23 +601,57 @@ static void st7735_fill(FAR struct st7735_dev_s *dev, uint16_t color)
  *
  ****************************************************************************/
 
-static int st7735_putrun(fb_coord_t row, fb_coord_t col,
+static int gc9a01_putrun(fb_coord_t row, fb_coord_t col,
                          FAR const uint8_t *buffer, size_t npixels)
 {
-  FAR struct st7735_dev_s *priv = &g_lcddev;
+  FAR struct gc9a01_dev_s *priv = &g_lcddev;
   FAR const uint16_t *src = (FAR const uint16_t *)buffer;
 
   ginfo("row: %d col: %d npixels: %d\n", row, col, npixels);
   DEBUGASSERT(buffer && ((uintptr_t)buffer & 1) == 0);
 
-  st7735_setarea(priv, col, row, col + npixels - 1, row);
-  st7735_wrram(priv, src, npixels);
+  gc9a01_setarea(priv, col, row, col + npixels - 1, row);
+  gc9a01_wrram(priv, src, npixels);
 
   return OK;
 }
 
 /****************************************************************************
- * Name:  st7735_getrun
+ * Name:  gc9a01_putarea
+ *
+ * Description:
+ *   This method can be used to write a partial area to the LCD:
+ *
+ *   row_start - Starting row to write to (range: 0 <= row < yres)
+ *   row_end   - Ending row to write to (range: row_start <= row < yres)
+ *   col_start - Starting column to write to (range: 0 <= col <= xres)
+ *   col_end   - Ending column to write to
+ *               (range: col_start <= col_end < xres)
+ *   buffer    - The buffer containing the area to be written to the LCD
+ *
+ ****************************************************************************/
+
+static int gc9a01_putarea(fb_coord_t row_start, fb_coord_t row_end,
+                          fb_coord_t col_start, fb_coord_t col_end,
+                          FAR const uint8_t *buffer)
+{
+  FAR struct gc9a01_dev_s *priv = &g_lcddev;
+  FAR const uint16_t *src = (FAR const uint16_t *)buffer;
+
+  ginfo("row_start: %d row_end: %d col_start: %d col_end: %d\n",
+         row_start, row_end, col_start, col_end);
+
+  DEBUGASSERT(buffer && ((uintptr_t)buffer & 1) == 0);
+
+  gc9a01_setarea(priv, col_start, row_start, col_end, row_end);
+  gc9a01_wrram(priv, src,
+               (row_end - row_start + 1) * (col_end - col_start + 1));
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name:  gc9a01_getrun
  *
  * Description:
  *   This method can be used to read a partial raster line from the LCD:
@@ -492,64 +665,65 @@ static int st7735_putrun(fb_coord_t row, fb_coord_t col,
  ****************************************************************************/
 
 #ifndef CONFIG_LCD_NOGETRUN
-static int st7735_getrun(fb_coord_t row, fb_coord_t col, FAR uint8_t *buffer,
+static int gc9a01_getrun(fb_coord_t row, fb_coord_t col, FAR uint8_t *buffer,
                          size_t npixels)
 {
-  FAR struct st7735_dev_s *priv = &g_lcddev;
+  FAR struct gc9a01_dev_s *priv = &g_lcddev;
   FAR uint16_t *dest = (FAR uint16_t *)buffer;
 
   ginfo("row: %d col: %d npixels: %d\n", row, col, npixels);
   DEBUGASSERT(buffer && ((uintptr_t)buffer & 1) == 0);
 
-  st7735_setarea(priv, col, row, col + npixels - 1, row);
-  st7735_rdram(priv, dest, npixels);
+  gc9a01_setarea(priv, col, row, col + npixels - 1, row);
+  gc9a01_rdram(priv, dest, npixels);
 
   return OK;
 }
 #endif
 
 /****************************************************************************
- * Name:  st7735_getvideoinfo
+ * Name:  gc9a01_getvideoinfo
  *
  * Description:
  *   Get information about the LCD video controller configuration.
  *
  ****************************************************************************/
 
-static int st7735_getvideoinfo(FAR struct lcd_dev_s *dev,
+static int gc9a01_getvideoinfo(FAR struct lcd_dev_s *dev,
                                FAR struct fb_videoinfo_s *vinfo)
 {
   DEBUGASSERT(dev && vinfo);
   lcdinfo("fmt: %d xres: %d yres: %d nplanes: 1\n",
-          ST7735_COLORFMT, ST7735_XRES, ST7735_YRES);
+          GC9A01_COLORFMT, GC9A01_XRES, GC9A01_YRES);
 
-  vinfo->fmt     = ST7735_COLORFMT;    /* Color format: RGB16-565: RRRR RGGG GGGB BBBB */
-  vinfo->xres    = ST7735_XRES;        /* Horizontal resolution in pixel columns */
-  vinfo->yres    = ST7735_YRES;        /* Vertical resolution in pixel rows */
+  vinfo->fmt     = GC9A01_COLORFMT;    /* Color format: RGB16-565: RRRR RGGG GGGB BBBB */
+  vinfo->xres    = GC9A01_XRES;        /* Horizontal resolution in pixel columns */
+  vinfo->yres    = GC9A01_YRES;        /* Vertical resolution in pixel rows */
   vinfo->nplanes = 1;                  /* Number of color planes supported */
   return OK;
 }
 
 /****************************************************************************
- * Name:  st7735_getplaneinfo
+ * Name:  gc9a01_getplaneinfo
  *
  * Description:
  *   Get information about the configuration of each LCD color plane.
  *
  ****************************************************************************/
 
-static int st7735_getplaneinfo(FAR struct lcd_dev_s *dev,
+static int gc9a01_getplaneinfo(FAR struct lcd_dev_s *dev,
                                unsigned int planeno,
                                FAR struct lcd_planeinfo_s *pinfo)
 {
-  FAR struct st7735_dev_s *priv = (FAR struct st7735_dev_s *)dev;
+  FAR struct gc9a01_dev_s *priv = (FAR struct gc9a01_dev_s *)dev;
 
   DEBUGASSERT(dev && pinfo && planeno == 0);
-  lcdinfo("planeno: %d bpp: %d\n", planeno, ST7735_BPP);
+  lcdinfo("planeno: %d bpp: %d\n", planeno, GC9A01_BPP);
 
-  pinfo->putrun = st7735_putrun;                  /* Put a run into LCD memory */
+  pinfo->putrun = gc9a01_putrun;                  /* Put a run into LCD memory */
+  pinfo->putarea = gc9a01_putarea;                /* Put an area into LCD */
 #ifndef CONFIG_LCD_NOGETRUN
-  pinfo->getrun = st7735_getrun;                  /* Get a run from LCD memory */
+  pinfo->getrun = gc9a01_getrun;                  /* Get a run from LCD memory */
 #endif
   pinfo->buffer = (FAR uint8_t *)priv->runbuffer; /* Run scratch buffer */
   pinfo->bpp    = priv->bpp;                      /* Bits-per-pixel */
@@ -557,24 +731,24 @@ static int st7735_getplaneinfo(FAR struct lcd_dev_s *dev,
 }
 
 /****************************************************************************
- * Name:  st7735_getpower
+ * Name:  gc9a01_getpower
  ****************************************************************************/
 
-static int st7735_getpower(FAR struct lcd_dev_s *dev)
+static int gc9a01_getpower(FAR struct lcd_dev_s *dev)
 {
-  FAR struct st7735_dev_s *priv = (FAR struct st7735_dev_s *)dev;
+  FAR struct gc9a01_dev_s *priv = (FAR struct gc9a01_dev_s *)dev;
 
   lcdinfo("power: %d\n", priv->power);
   return priv->power;
 }
 
 /****************************************************************************
- * Name:  st7735_setpower
+ * Name:  gc9a01_setpower
  ****************************************************************************/
 
-static int st7735_setpower(FAR struct lcd_dev_s *dev, int power)
+static int gc9a01_setpower(FAR struct lcd_dev_s *dev, int power)
 {
-  FAR struct st7735_dev_s *priv = (FAR struct st7735_dev_s *)dev;
+  FAR struct gc9a01_dev_s *priv = (FAR struct gc9a01_dev_s *)dev;
 
   lcdinfo("power: %d\n", power);
   DEBUGASSERT((unsigned)power <= CONFIG_LCD_MAXPOWER);
@@ -585,7 +759,7 @@ static int st7735_setpower(FAR struct lcd_dev_s *dev, int power)
     {
       /* Turn on the display */
 
-      st7735_display(priv, true);
+      gc9a01_display(priv, true);
 
       /* Save the power */
 
@@ -595,7 +769,7 @@ static int st7735_setpower(FAR struct lcd_dev_s *dev, int power)
     {
       /* Turn off the display */
 
-      st7735_display(priv, false);
+      gc9a01_display(priv, false);
 
       /* Save the power */
 
@@ -606,28 +780,28 @@ static int st7735_setpower(FAR struct lcd_dev_s *dev, int power)
 }
 
 /****************************************************************************
- * Name:  st7735_getcontrast
+ * Name:  gc9a01_getcontrast
  *
  * Description:
  *   Get the current contrast setting (0-CONFIG_LCD_MAXCONTRAST).
  *
  ****************************************************************************/
 
-static int st7735_getcontrast(FAR struct lcd_dev_s *dev)
+static int gc9a01_getcontrast(FAR struct lcd_dev_s *dev)
 {
   lcdinfo("Not implemented\n");
   return -ENOSYS;
 }
 
 /****************************************************************************
- * Name:  st7735_setcontrast
+ * Name:  gc9a01_setcontrast
  *
  * Description:
  *   Set LCD panel contrast (0-CONFIG_LCD_MAXCONTRAST).
  *
  ****************************************************************************/
 
-static int st7735_setcontrast(FAR struct lcd_dev_s *dev,
+static int gc9a01_setcontrast(FAR struct lcd_dev_s *dev,
                               unsigned int contrast)
 {
   lcdinfo("contrast: %d\n", contrast);
@@ -639,10 +813,10 @@ static int st7735_setcontrast(FAR struct lcd_dev_s *dev,
  ****************************************************************************/
 
 /****************************************************************************
- * Name:  st7735_initialize
+ * Name:  gc9a01_initialize
  *
  * Description:
- *   Initialize the ST7735 video hardware.  The initial state of the
+ *   Initialize the GC9A01 video hardware.  The initial state of the
  *   LCD is fully initialized, display memory cleared, and the LCD ready
  *   to use, but with the power setting at 0 (full off == sleep mode).
  *
@@ -653,29 +827,30 @@ static int st7735_setcontrast(FAR struct lcd_dev_s *dev,
  *
  ****************************************************************************/
 
-FAR struct lcd_dev_s *st7735_lcdinitialize(FAR struct spi_dev_s *spi)
+FAR struct lcd_dev_s *gc9a01_lcdinitialize(FAR struct spi_dev_s *spi)
 {
-  FAR struct st7735_dev_s *priv = &g_lcddev;
+  FAR struct gc9a01_dev_s *priv = &g_lcddev;
 
   /* Initialize the driver data structure */
 
-  priv->dev.getvideoinfo = st7735_getvideoinfo;
-  priv->dev.getplaneinfo = st7735_getplaneinfo;
-  priv->dev.getpower     = st7735_getpower;
-  priv->dev.setpower     = st7735_setpower;
-  priv->dev.getcontrast  = st7735_getcontrast;
-  priv->dev.setcontrast  = st7735_setcontrast;
+  priv->dev.getvideoinfo = gc9a01_getvideoinfo;
+  priv->dev.getplaneinfo = gc9a01_getplaneinfo;
+  priv->dev.getpower     = gc9a01_getpower;
+  priv->dev.setpower     = gc9a01_setpower;
+  priv->dev.getcontrast  = gc9a01_getcontrast;
+  priv->dev.setcontrast  = gc9a01_setcontrast;
   priv->spi              = spi;
 
   /* Init the hardware and clear the display */
 
-  st7735_sleep(priv, false);
-  st7735_bpp(priv, ST7735_BPP);
-  st7735_display(priv, true);
-  st7735_fill(priv, 0xffff);
+  gc9a01_init(priv);
+  gc9a01_sleep(priv, false);
+  gc9a01_bpp(priv, GC9A01_BPP);
+  gc9a01_setorientation(priv);
+  gc9a01_display(priv, true);
+  gc9a01_fill(priv, 0xffff);
 
   return &priv->dev;
 }
 
-#endif /* CONFIG_LCD_ST7735 */
-
+#endif /* CONFIG_LCD_GC9A01 */
diff --git a/drivers/lcd/gc9a01.h b/drivers/lcd/gc9a01.h
new file mode 100644
index 0000000..858f9ad
--- /dev/null
+++ b/drivers/lcd/gc9a01.h
@@ -0,0 +1,71 @@
+/****************************************************************************
+ * drivers/lcd/gc9a01.h
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+#ifndef __DRIVERS_LCD_GC9A01_H
+#define __DRIVERS_LCD_GC9A01_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define GC9A01_NOP       0x00   /* No Operation */
+#define GC9A01_SWRESET   0x01   /* Software Reset */
+#define GC9A01_RDDID     0x04   /* Read Display ID */
+#define GC9A01_RDDST     0x09   /* Read Display Status */
+
+#define GC9A01_SLPIN     0x10   /* Sleep In & Booster Off */
+#define GC9A01_SLPOUT    0x11   /* Sleep Out & Booster On */
+#define GC9A01_PTLON     0x12   /* Partial Mode On */
+#define GC9A01_NORON     0x13   /* Partial Mode Off */
+
+#define GC9A01_INVOFF    0x20   /* Display Inversion Off */
+#define GC9A01_INVON     0x21   /* Display Inversion On */
+#define GC9A01_DISPOFF   0x28   /* Display Off */
+#define GC9A01_DISPON    0x29   /* Display On */
+#define GC9A01_CASET     0x2a   /* Column Address Set */
+#define GC9A01_RASET     0x2b   /* Row Address Set */
+#define GC9A01_RAMWR     0x2c   /* Memory Write */
+#define GC9A01_RAMRD     0x2e   /* Memory Read */
+
+#define GC9A01_PTLAR     0x30   /* Partial Area */
+#define GC9A01_VSCRDEF   0x33   /* Vertical Scrolling Definition */
+#define GC9A01_TEON      0x35   /* Tering Effect Line On */
+#define GC9A01_MADCTL    0x36   /* Memory Data Access Control */
+
+#define GC9A01_MADCTL_MY  (1<<7)  /* Page Address Order */
+#define GC9A01_MADCTL_MX  (1<<6)  /* Column Address Order */
+#define GC9A01_MADCTL_MV  (1<<5)  /* Page/Column Order */
+#define GC9A01_MADCTL_ML  (1<<4)  /* Line Address Order */
+#define GC9A01_MADCTL_BGR (1<<3)  /* Set Panel Order BGR */
+#define GC9A01_MADCTL_MH  (1<<2)  /* Display Data Latch Order */
+
+#define GC9A01_VSCSAD    0x37   /* Vertical Scrolling Start Address */
+#define GC9A01_IDMOFF    0x38   /* Idle Mode Off */
+#define GC9A01_IDMON     0x39   /* Idle Mode On */
+#define GC9A01_COLMOD    0x3a   /* Interface Pixel Format */
+
+#define GC9A01_ENIREG1   0xFE   /* Enable internal register 1 */
+#define GC9A01_ENIREG2   0xEF   /* Enable internal register 2 */
+
+#endif /* __DRIVERS_LCD_GC9A01_H */
diff --git a/drivers/lcd/st7735.c b/drivers/lcd/st7735.c
index e663409..b3b7eed 100644
--- a/drivers/lcd/st7735.c
+++ b/drivers/lcd/st7735.c
@@ -45,6 +45,8 @@
  * Pre-processor Definitions
  ****************************************************************************/
 
+#define MAX(a,b)    ((a)>(b)?(a):(b))
+
 /* Verify that all configuration requirements have been met */
 
 #ifndef CONFIG_LCD_ST7735_SPIMODE
@@ -94,24 +96,37 @@
 
 /* Display Resolution */
 
-#ifdef CONFIG_LCD_ST7735_GM00
-#  define CONFIG_ST7735_XRES 132
-#  define CONFIG_ST7735_YRES 162
-#  define ST7735_LUT_SIZE    162
-#else
-#  define CONFIG_ST7735_XRES 128
-#  define CONFIG_ST7735_YRES 160
-#  define ST7735_LUT_SIZE    160
+#if defined(CONFIG_LCD_ST7735_GM00)
+#  define CONFIG_LCD_ST7735_XRES 132
+#  define CONFIG_LCD_ST7735_YRES 162
+#  define CONFIG_LCD_ST7735_XOFFSET 0
+#  define CONFIG_LCD_ST7735_YOFFSET 0
+#elif defined(CONFIG_LCD_ST7735_GM01)
+#  define CONFIG_LCD_ST7735_XRES 132
+#  define CONFIG_LCD_ST7735_YRES 132
+#  define CONFIG_LCD_ST7735_XOFFSET 0
+#  define CONFIG_LCD_ST7735_YOFFSET 0
+#elif defined(CONFIG_LCD_ST7735_GM11)
+#  define CONFIG_LCD_ST7735_XRES 128
+#  define CONFIG_LCD_ST7735_YRES 160
+#  define CONFIG_LCD_ST7735_XOFFSET 0
+#  define CONFIG_LCD_ST7735_YOFFSET 0
 #endif
 
 #if defined(CONFIG_LCD_LANDSCAPE) || defined(CONFIG_LCD_RLANDSCAPE)
-#  define ST7735_XRES       CONFIG_ST7735_YRES
-#  define ST7735_YRES       CONFIG_ST7735_XRES
+#  define ST7735_XRES       CONFIG_LCD_ST7735_YRES
+#  define ST7735_YRES       CONFIG_LCD_ST7735_XRES
+#  define ST7735_XOFFSET    CONFIG_LCD_ST7735_YOFFSET
+#  define ST7735_YOFFSET    CONFIG_LCD_ST7735_XOFFSET
 #else
-#  define ST7735_XRES       CONFIG_ST7735_XRES
-#  define ST7735_YRES       CONFIG_ST7735_YRES
+#  define ST7735_XRES       CONFIG_LCD_ST7735_XRES
+#  define ST7735_YRES       CONFIG_LCD_ST7735_YRES
+#  define ST7735_XOFFSET    CONFIG_LCD_ST7735_XOFFSET
+#  define ST7735_YOFFSET    CONFIG_LCD_ST7735_YOFFSET
 #endif
 
+#define ST7735_LUT_SIZE   MAX(CONFIG_LCD_ST7735_XRES, CONFIG_LCD_ST7735_YRES)
+
 /* Color depth and format */
 
 #ifdef CONFIG_LCD_ST7735_BPP
@@ -180,6 +195,7 @@ static void st7735_deselect(FAR struct spi_dev_s *spi);
 static inline void st7735_sendcmd(FAR struct st7735_dev_s *dev, uint8_t cmd);
 static void st7735_sleep(FAR struct st7735_dev_s *dev, bool sleep);
 static void st7735_display(FAR struct st7735_dev_s *dev, bool on);
+static void st7735_setorientation(FAR struct st7735_dev_s *dev);
 static void st7735_setarea(FAR struct st7735_dev_s *dev,
                            uint16_t x0, uint16_t y0,
                            uint16_t x1, uint16_t y1);
@@ -329,6 +345,52 @@ static void st7735_display(FAR struct st7735_dev_s *dev, bool on)
 }
 
 /****************************************************************************
+ * Name: st7735_setorientation
+ *
+ * Description:
+ *   Set screen orientation.
+ *
+ ****************************************************************************/
+
+static void st7735_setorientation(FAR struct st7735_dev_s *dev)
+{
+  /* No need to change the orientation in PORTRAIT mode and RGB panel */
+
+#if !defined(CONFIG_LCD_PORTRAIT) || defined(CONFIG_LCD_ST7735_BGR)
+
+  uint8_t reg = 0x00;
+  st7735_sendcmd(dev, ST7735_MADCTL);
+  st7735_select(dev->spi, 8);
+
+#  if defined(CONFIG_LCD_RLANDSCAPE)
+  /* RLANDSCAPE : MY=1 MV=1 */
+
+  reg = ST7735_MADCTL_MY | ST7735_MADCTL_MV;
+
+#  elif defined(CONFIG_LCD_LANDSCAPE)
+  /* LANDSCAPE : MX=1 MV=1 */
+
+  reg = ST7735_MADCTL_MX | ST7735_MADCTL_MV;
+
+#  elif defined(CONFIG_LCD_RPORTRAIT)
+  /* RPORTRAIT : MX=1 MY=1 */
+
+  reg = ST7735_MADCTL_MX | ST7735_MADCTL_MY;
+
+#  endif
+
+#  if defined(CONFIG_LCD_ST7735_BGR)
+
+  reg |= ST7735_MADCTL_BGR;
+
+#  endif
+
+  SPI_SEND(dev->spi, reg);
+  st7735_deselect(dev->spi);
+#endif
+}
+
+/****************************************************************************
  * Name: st7735_setarea
  *
  * Description:
@@ -344,16 +406,16 @@ static void st7735_setarea(FAR struct st7735_dev_s *dev,
 
   st7735_sendcmd(dev, ST7735_RASET);
   st7735_select(dev->spi, 16);
-  SPI_SEND(dev->spi, y0);
-  SPI_SEND(dev->spi, y1);
+  SPI_SEND(dev->spi, y0 + ST7735_YOFFSET);
+  SPI_SEND(dev->spi, y1 + ST7735_YOFFSET);
   st7735_deselect(dev->spi);
 
   /* Set column address */
 
   st7735_sendcmd(dev, ST7735_CASET);
   st7735_select(dev->spi, 16);
-  SPI_SEND(dev->spi, x0);
-  SPI_SEND(dev->spi, x1);
+  SPI_SEND(dev->spi, x0 + ST7735_XOFFSET);
+  SPI_SEND(dev->spi, x1 + ST7735_XOFFSET);
   st7735_deselect(dev->spi);
 }
 
@@ -671,6 +733,7 @@ FAR struct lcd_dev_s *st7735_lcdinitialize(FAR struct spi_dev_s *spi)
 
   st7735_sleep(priv, false);
   st7735_bpp(priv, ST7735_BPP);
+  st7735_setorientation(priv);
   st7735_display(priv, true);
   st7735_fill(priv, 0xffff);
 
diff --git a/drivers/lcd/st7735.h b/drivers/lcd/st7735.h
index d7cd525..057b2ff 100644
--- a/drivers/lcd/st7735.h
+++ b/drivers/lcd/st7735.h
@@ -46,8 +46,19 @@
 #define ST7735_RASET     0x2b   /* Row Address Set */
 #define ST7735_RAMWR     0x2c   /* Memory Write */
 #define ST7735_RAMRD     0x2e   /* Memory Read */
+#define ST7735_MADCTL    0x36   /* Memory Data Access Control */
+
+#define ST7735_MADCTL_MY  (1<<7)  /* Page Address Order */
+#define ST7735_MADCTL_MX  (1<<6)  /* Column Address Order */
+#define ST7735_MADCTL_MV  (1<<5)  /* Page/Column Order */
+#define ST7735_MADCTL_ML  (1<<4)  /* Line Address Order */
+#define ST7735_MADCTL_BGR (1<<3)  /* Set Panel Order BGR */
+#define ST7735_MADCTL_MH  (1<<2)  /* Display Data Latch Order */
+
 #define ST7735_IDMOFF    0x38   /* Idle Mode Off */
 #define ST7735_IDMON     0x39   /* Idle Mode On */
 #define ST7735_COLMOD    0x3a   /* Interface Pixel Format */
 
+FAR struct lcd_dev_s *st7735_lcdinitialize(FAR struct spi_dev_s *spi);
+
 #endif /* __DRIVERS_LCD_ST7735_H */
diff --git a/include/nuttx/lcd/gc9a01.h b/include/nuttx/lcd/gc9a01.h
new file mode 100644
index 0000000..6717eb1
--- /dev/null
+++ b/include/nuttx/lcd/gc9a01.h
@@ -0,0 +1,72 @@
+/****************************************************************************
+ * include/nuttx/lcd/gc9a01.h
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+#ifndef __INCLUDE_NUTTX_GC9A01_H
+#define __INCLUDE_NUTTX_GC9A01_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <stdbool.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Types
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name:  gc9a01_initialize
+ *
+ * Description:
+ *   Initialize the GC9A01 video hardware.  The initial state of the
+ *   LCD is fully initialized, display memory cleared, and the LCD ready
+ *   to use, but with the power setting at 0 (full off == sleep mode).
+ *
+ * Returned Value:
+ *
+ *   On success, this function returns a reference to the LCD object for
+ *   the specified LCD.  NULL is returned on any failure.
+ *
+ ****************************************************************************/
+
+FAR struct lcd_dev_s *gc9a01_lcdinitialize(FAR struct spi_dev_s *spi);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __INCLUDE_NUTTX_GC9A01_H */