From 55a4029885af46f98b7c029669e7ed3f0e1ff9f2 Mon Sep 17 00:00:00 2001 From: Alin Jerpelea Date: Wed, 3 Jul 2019 12:24:13 +0000 Subject: [PATCH] Merged in alinjerpelea/nuttx (pull request #928) configs: spresense: add basic LCD configuration * arch: arm: cxd56xx: add Graphics Engine Add driver for hardware image processor device to enable the hardware image processor set CXD56_GE2D=true Signed-off-by: Alin Jerpelea * drivers: lcd: add ILI9340 LCD Single Chip Driver LCD Single Chip Driver, ILI9340, ILI Technology Corp. Required LCD driver settings: LCD_MAXCONTRAST should be 255, but any value >0 and <=255 will be accepted. LCD_MAXPOWER should be 1: 0=off, 1=on Signed-off-by: Alin Jerpelea * drivers: lcd: JDI LPM013M091A LCD Driver JDI LPM013M091A LCD Driver. This driver doesn't support reading data. Recommended to use DMA to transfer data or displayed image would be broken. Signed-off-by: Alin Jerpelea * configs: spresense: add basic LCD configuration add basic LCD configuration for spresense board Signed-off-by: Alin Jerpelea * configs: spresense: add lpm013m091a LCD add device configuration for lpm013m091a LCD on spresense board Signed-off-by: Alin Jerpelea * configs: spresense: add ili9340 LCD add device configuration for ili9340 LCD on spresense board Signed-off-by: Alin Jerpelea * configs: spresense: add defconfig with LCD add defconfig with LCD for spresense board Signed-off-by: Alin Jerpelea Approved-by: Gregory Nutt --- arch/arm/src/cxd56xx/Kconfig | 6 + arch/arm/src/cxd56xx/Make.defs | 4 + arch/arm/src/cxd56xx/cxd56_ge2d.c | 283 +++++ arch/arm/src/cxd56xx/hardware/cxd56_ge2d.h | 82 ++ configs/spresense/Kconfig | 20 + configs/spresense/include/board.h | 22 + configs/spresense/lcd/defconfig | 90 ++ configs/spresense/src/Makefile | 8 + configs/spresense/src/cxd56_ili9340.c | 398 +++++++ configs/spresense/src/cxd56_lpm013m091a.c | 398 +++++++ drivers/lcd/Kconfig | 126 ++ drivers/lcd/Make.defs | 8 + drivers/lcd/ili9340.c | 1240 ++++++++++++++++++++ drivers/lcd/lpm013m091a.c | 611 ++++++++++ include/nuttx/lcd/ili9340.h | 316 +++++ include/nuttx/lcd/lpm013m091a.h | 138 +++ 16 files changed, 3750 insertions(+) create mode 100644 arch/arm/src/cxd56xx/cxd56_ge2d.c create mode 100644 arch/arm/src/cxd56xx/hardware/cxd56_ge2d.h create mode 100644 configs/spresense/lcd/defconfig create mode 100644 configs/spresense/src/cxd56_ili9340.c create mode 100644 configs/spresense/src/cxd56_lpm013m091a.c create mode 100644 drivers/lcd/ili9340.c create mode 100644 drivers/lcd/lpm013m091a.c create mode 100644 include/nuttx/lcd/ili9340.h create mode 100644 include/nuttx/lcd/lpm013m091a.h diff --git a/arch/arm/src/cxd56xx/Kconfig b/arch/arm/src/cxd56xx/Kconfig index c2baf4047c..db0f66b304 100644 --- a/arch/arm/src/cxd56xx/Kconfig +++ b/arch/arm/src/cxd56xx/Kconfig @@ -1172,4 +1172,10 @@ config CXD56_EMMC Emmc driver for cxd56xx chip endmenu + +config CXD56_GE2D + bool "Graphics Engine" + default n + ---help--- + A hardware image processor device. endmenu diff --git a/arch/arm/src/cxd56xx/Make.defs b/arch/arm/src/cxd56xx/Make.defs index ed1bf71ff6..2e562d9655 100644 --- a/arch/arm/src/cxd56xx/Make.defs +++ b/arch/arm/src/cxd56xx/Make.defs @@ -156,6 +156,10 @@ ifeq ($(CONFIG_CXD56_CHARGER),y) CHIP_CSRCS += cxd56_charger.c endif +ifeq ($(CONFIG_CXD56_GE2D),y) +CHIP_CSRCS += cxd56_ge2d.c +endif + ifeq ($(CONFIG_CXD56_SCU),y) CHIP_CSRCS += cxd56_scu.c cxd56_scufifo.c ifeq ($(CONFIG_CXD56_ADC),y) diff --git a/arch/arm/src/cxd56xx/cxd56_ge2d.c b/arch/arm/src/cxd56xx/cxd56_ge2d.c new file mode 100644 index 0000000000..86ae1cc19c --- /dev/null +++ b/arch/arm/src/cxd56xx/cxd56_ge2d.c @@ -0,0 +1,283 @@ +/**************************************************************************** + * arch/arm/src/cxd56xx/cxd56_ge2d.c + * + * Copyright 2018 Sony Semiconductor Solutions Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name of Sony Semiconductor Solutions Corporation nor + * the names of its contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "up_arch.h" +#include "chip.h" +#include "cxd56_clock.h" + +#include "hardware/cxd56_ge2d.h" + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static int ge2d_open(FAR struct file *filep); +static int ge2d_close(FAR struct file *filep); +static ssize_t ge2d_read(FAR struct file *filep, FAR char *buffer, + size_t len); +static ssize_t ge2d_write(FAR struct file *filep, FAR const char *buffer, + size_t len); +static int ge2d_ioctl(FAR struct file *filep, int cmd, unsigned long arg); +static int ge2d_semtake(sem_t *id); +static void ge2d_semgive(sem_t *id); +static int ge2d_irqhandler(int irq, FAR void *context, FAR void *arg); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const struct file_operations g_ge2dfops = +{ + .open = ge2d_open, + .close = ge2d_close, + .read = ge2d_read, + .write = ge2d_write, + .seek = 0, + .ioctl = ge2d_ioctl, +}; + +static sem_t g_wait; +static sem_t g_lock; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: ge2d_semtake + ****************************************************************************/ + +static int ge2d_semtake(sem_t *id) +{ + while (sem_wait(id) != 0) + { + ASSERT(errno == EINTR); + } + return OK; +} + +/**************************************************************************** + * Name: ge2d_semgive + ****************************************************************************/ + +static void ge2d_semgive(sem_t *id) +{ + sem_post(id); +} + +/**************************************************************************** + * Name: ge2d_open + ****************************************************************************/ + +static int ge2d_open(FAR struct file *filep) +{ + return 0; +} + +/**************************************************************************** + * Name: ge2d_close + ****************************************************************************/ + +static int ge2d_close(FAR struct file *filep) +{ + return 0; +} + +/**************************************************************************** + * Name: ge2d_read + ****************************************************************************/ + +static ssize_t ge2d_read(FAR struct file *filep, FAR char *buffer, size_t len) +{ + return 0; +} + +/**************************************************************************** + * Name: ge2d_write + ****************************************************************************/ + +static ssize_t ge2d_write(FAR struct file *filep, + FAR const char *buffer, + size_t len) +{ + uint32_t bits; + + /* GE2D wants 16 byte aligned address for operation buffer. */ + + if (((uintptr_t)buffer & 0xf) != 0) + { + set_errno(EINVAL); + return 0; + } + + /* Get exclusive access */ + + ge2d_semtake(&g_lock); + + /* Set operation buffer and start processing. + * Descriptor start address bit 0 is select to bus, always 1 (memory), + * can't set except 1 in this chip. + */ + + putreg32((uint32_t)(uintptr_t)buffer | 1, GE2D_ADDRESS_DESCRIPTOR_START); + putreg32(GE2D_EXEC, GE2D_CMD_DESCRIPTOR); + + /* Enable error and completion interrupts. */ + + bits = GE2D_INTR_WR_ERR | GE2D_INTR_RD_ERR | GE2D_INTR_NDE | GE2D_INTR_DSD | + GE2D_INTR_NDF; + putreg32(bits, GE2D_INTR_ENABLE); + + /* Wait for interrupts for processing done. */ + + ge2d_semtake(&g_wait); + + /* Disable interrupts */ + + putreg32(0, GE2D_INTR_ENABLE); + + ge2d_semgive(&g_lock); + + return len; +} + +/**************************************************************************** + * Name: ge2d_ioctl + ****************************************************************************/ + +static int ge2d_ioctl(FAR struct file *filep, int cmd, unsigned long arg) +{ + int ret = -ENOTTY; + + /* TODO: Should be implement features: + * + * - stop execution + * - debug for raster operation + */ + + switch (cmd) + { + default: + break; + } + + return ret; +} + +/**************************************************************************** + * Name: ge2d_irqhandler + ****************************************************************************/ + +static int ge2d_irqhandler(int irq, FAR void *context, FAR void *arg) +{ + uint32_t stat; + + /* Clear interrupts */ + + stat = getreg32(GE2D_INTR_STAT); + putreg32(stat, GE2D_INTR_STAT); + + /* TODO: output status to syslog */ + + /* Release semaphore anyway */ + + ge2d_semgive(&g_wait); + + return OK; +} + +/**************************************************************************** + * Name: cxd56_ge2dinitialize + ****************************************************************************/ + +int cxd56_ge2dinitialize(FAR const char *devname) +{ + int ret; + + sem_init(&g_lock, 0, 1); + sem_init(&g_wait, 0, 0); + sem_setprotocol(&g_wait, SEM_PRIO_NONE); + + ret = register_driver(devname, &g_ge2dfops, 0666, NULL); + if (ret != 0) + { + return ERROR; + } + + cxd56_img_ge2d_clock_enable(); + + /* Disable interrupts */ + + putreg32(0, GE2D_INTR_ENABLE); + + irq_attach(CXD56_IRQ_GE2D, ge2d_irqhandler, NULL); + up_enable_irq(CXD56_IRQ_GE2D); + + return OK; +} + +/**************************************************************************** + * Name: cxd56_ge2duninitialize + ****************************************************************************/ + +void cxd56_ge2duninitialize(FAR const char *devname) +{ + up_disable_irq(CXD56_IRQ_GE2D); + irq_detach(CXD56_IRQ_GE2D); + + cxd56_img_ge2d_clock_disable(); + + sem_destroy(&g_lock); + sem_destroy(&g_wait); + + unregister_driver(devname); +} diff --git a/arch/arm/src/cxd56xx/hardware/cxd56_ge2d.h b/arch/arm/src/cxd56xx/hardware/cxd56_ge2d.h new file mode 100644 index 0000000000..f16575f787 --- /dev/null +++ b/arch/arm/src/cxd56xx/hardware/cxd56_ge2d.h @@ -0,0 +1,82 @@ +/**************************************************************************** + * arch/arm/src/cxd56xx/hardware/cxd56_ge2d.h + * + * Copyright 2018 Sony Semiconductor Solutions Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name of Sony Semiconductor Solutions Corporation nor + * the names of its contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __SRC_CHIP_CXD56_GE2D_H +#define __SRC_CHIP_CXD56_GE2D_H + +#include "hardware/cxd5602_memorymap.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define GE2D_INTR_ENABLE (CXD56_GE2D_BASE+0x00) +#define GE2D_INTR_STAT (CXD56_GE2D_BASE+0x04) +#define GE2D_ADDRESS_DESCRIPTOR_START (CXD56_GE2D_BASE+0x08) +#define GE2D_STATUS (CXD56_GE2D_BASE+0x0c) /* Read */ +#define GE2D_CMD_DESCRIPTOR (CXD56_GE2D_BASE+0x0c) /* Write */ +#define GE2D_STAT_NORMAL_DESCRIPTOR_ADDRESS (CXD56_GE2D_BASE+0x10) +#define GE2D_STAT_CURRENT_DESCRIPTOR_ADDRESS (CXD56_GE2D_BASE+0x14) +#define GE2D_AHB_BURST_MODE (CXD56_GE2D_BASE+0x40) + +/* Interrupt bits */ + +#define GE2D_INTR_WR_ERR (1 << 17) +#define GE2D_INTR_RD_ERR (1 << 16) +#define GE2D_INTR_DSD (1 << 8) +#define GE2D_INTR_NDE (1 << 3) +#define GE2D_INTR_NDB (1 << 2) +#define GE2D_INTR_NDF (1 << 1) +#define GE2D_INTR_HPU (1 << 0) + +#define GE2D_INTR_ALL (GE2D_INTR_WR_ERR | GE2D_INTR_RD_ERR | \ + GE2D_INTR_DSD | GE2D_INTR_NDE | GE2D_INTR_NDB | \ + GE2D_INTR_NDF | GE2D_INTR_HPU) + +/* Status bits */ + +#define GE2D_STAT_ISER (1 << 24) +#define GE2D_STAT_NDCR (1 << 8) +#define GE2D_STAT_SREQ (1 << 2) +#define GE2D_STAT_PREQ (1 << 1) +#define GE2D_STAT_NREQ (1 << 0) + +/* Running control */ + +#define GE2D_NOP 0 +#define GE2D_EXEC 1 +#define GE2D_STOP 3 + +#endif /* __SRC_CHIP_CXD56_GE2D_H */ diff --git a/configs/spresense/Kconfig b/configs/spresense/Kconfig index 7af7de405f..f1b337d2e1 100644 --- a/configs/spresense/Kconfig +++ b/configs/spresense/Kconfig @@ -36,4 +36,24 @@ endchoice # "TXS02612 port" endif # SDCARD_TXS02612 +if LCD + +choice + prompt "LCD SPI connection" + default LCD_ON_EXTENSION_BOARD + +config LCD_ON_EXTENSION_BOARD + bool "Extension board: SPI4" + select CXD56_SPI4 + ---help--- + Display connected to extension board. + +config LCD_ON_MAIN_BOARD + bool "Main board: SPI5" + select CXD56_SPI5 + ---help--- + Display connected to main board. + +endchoice +endif endif diff --git a/configs/spresense/include/board.h b/configs/spresense/include/board.h index 9e9634418f..9095a0cd82 100644 --- a/configs/spresense/include/board.h +++ b/configs/spresense/include/board.h @@ -217,6 +217,28 @@ enum board_power_device POWER_IMAGE_SENSOR = PMIC_GPO(4) | PMIC_GPO(5) | PMIC_GPO(7), }; +/* LCD Display clocking ****************************************************/ + +#define ILI9340_SPI_MAXFREQUENCY 40000000 + +/* Display device pin definitions ******************************************/ + +#if defined(CONFIG_LCD_ON_MAIN_BOARD) /* Display connected to main board. */ + +#define DISPLAY_RST PIN_I2S0_BCK +#define DISPLAY_DC PIN_I2S0_LRCK + +#define DISPLAY_SPI 5 + +#else /* Display is connected through extension board. */ + +#define DISPLAY_RST PIN_SPI2_MISO +#define DISPLAY_DC PIN_PWM2 + +#define DISPLAY_SPI 4 + +#endif + /* * Set signal id for notify USB device connection status and * supply current value. diff --git a/configs/spresense/lcd/defconfig b/configs/spresense/lcd/defconfig new file mode 100644 index 0000000000..200848042a --- /dev/null +++ b/configs/spresense/lcd/defconfig @@ -0,0 +1,90 @@ +# +# This file is autogenerated: PLEASE DO NOT EDIT IT. +# +# You can use "make menuconfig" to make any modifications to the installed .config file. +# You can then do "make savedefconfig" to generate a new defconfig file that includes your +# modifications. +# +# CONFIG_CXD56_I2C0_SCUSEQ is not set +# CONFIG_MMCSD_HAVE_WRITEPROTECT is not set +# CONFIG_MMCSD_SPI is not set +# CONFIG_STANDARD_SERIAL is not set +CONFIG_ARCH="arm" +CONFIG_ARCH_BOARD="spresense" +CONFIG_ARCH_BOARD_SPRESENSE=y +CONFIG_ARCH_CHIP_CXD56XX=y +CONFIG_ARCH_STACKDUMP=y +CONFIG_ARMV7M_USEBASEPRI=y +CONFIG_BOARD_LOOPSPERMSEC=5434 +CONFIG_BOOT_RUNFROMISRAM=y +CONFIG_BUILTIN=y +CONFIG_CDCACM=y +CONFIG_CDCACM_COMPOSITE=y +CONFIG_CLOCK_MONOTONIC=y +CONFIG_COMPOSITE_IAD=y +CONFIG_COMPOSITE_MSFT_OS_DESCRIPTORS=y +CONFIG_COMPOSITE_PRODUCTID=0x0bc2 +CONFIG_COMPOSITE_VENDORID=0x054c +CONFIG_COMPOSITE_VENDORSTR="Sony" +CONFIG_CXD56_DMAC_SPI4_RX=y +CONFIG_CXD56_DMAC_SPI4_TX=y +CONFIG_CXD56_I2C0=y +CONFIG_CXD56_I2C=y +CONFIG_CXD56_SDIO=y +CONFIG_CXD56_SPI4=y +CONFIG_CXD56_SPI5=y +CONFIG_CXD56_SPI=y +CONFIG_CXD56_USBDEV=y +CONFIG_DEBUG_FULLOPT=y +CONFIG_DEBUG_SYMBOLS=y +CONFIG_FAT_LCNAMES=y +CONFIG_FAT_LFN=y +CONFIG_FAT_MAXFNAME=64 +CONFIG_FS_FAT=y +CONFIG_FS_PROCFS=y +CONFIG_FS_PROCFS_REGISTER=y +CONFIG_HAVE_CXX=y +CONFIG_HAVE_CXXINITIALIZE=y +CONFIG_I2C=y +CONFIG_LCD=y +CONFIG_LCD_ILI9340=y +CONFIG_LCD_ILI9340_IFACE0=y +CONFIG_MAX_TASKS=16 +CONFIG_MAX_WDOGPARMS=2 +CONFIG_MMCSD=y +CONFIG_MMCSD_SDIO=y +CONFIG_NFILE_DESCRIPTORS=8 +CONFIG_NFILE_STREAMS=8 +CONFIG_NSH_ARCHINIT=y +CONFIG_NSH_BUILTIN_APPS=y +CONFIG_NSH_READLINE=y +CONFIG_PREALLOC_MQ_MSGS=4 +CONFIG_PREALLOC_TIMERS=4 +CONFIG_PREALLOC_WDOGS=16 +CONFIG_RAM_SIZE=1572864 +CONFIG_RAM_START=0x0d000000 +CONFIG_READLINE_CMD_HISTORY=y +CONFIG_RR_INTERVAL=200 +CONFIG_RTC=y +CONFIG_RTC_DRIVER=y +CONFIG_SCHED_WAITPID=y +CONFIG_SDCLONE_DISABLE=y +CONFIG_SPI=y +CONFIG_START_DAY=6 +CONFIG_START_MONTH=12 +CONFIG_START_YEAR=2011 +CONFIG_SYSTEM_CDCACM=y +CONFIG_SYSTEM_CLE=y +CONFIG_SYSTEM_COMPOSITE=y +CONFIG_SYSTEM_NSH=y +CONFIG_SYSTEM_NSH_CXXINITIALIZE=y +CONFIG_SYSTEM_USBMSC=y +CONFIG_UART1_SERIAL_CONSOLE=y +CONFIG_USBDEV=y +CONFIG_USBDEV_COMPOSITE=y +CONFIG_USBDEV_DMA=y +CONFIG_USBDEV_DUALSPEED=y +CONFIG_USBMSC=y +CONFIG_USBMSC_COMPOSITE=y +CONFIG_USBMSC_REMOVABLE=y +CONFIG_USER_ENTRYPOINT="nsh_main" diff --git a/configs/spresense/src/Makefile b/configs/spresense/src/Makefile index ebbf27cde5..a602db996a 100644 --- a/configs/spresense/src/Makefile +++ b/configs/spresense/src/Makefile @@ -124,4 +124,12 @@ ifeq ($(CONFIG_CXD56_I2C_DRIVER),y) CSRCS += cxd56_i2cdev.c endif +ifeq ($(CONFIG_LCD_LPM013M091A),y) +CSRCS += cxd56_lpm013m091a.c +endif + +ifeq ($(CONFIG_LCD_ILI9340),y) +CSRCS += cxd56_ili9340.c +endif + include $(TOPDIR)/configs/Board.mk diff --git a/configs/spresense/src/cxd56_ili9340.c b/configs/spresense/src/cxd56_ili9340.c new file mode 100644 index 0000000000..c689bf89b9 --- /dev/null +++ b/configs/spresense/src/cxd56_ili9340.c @@ -0,0 +1,398 @@ +/**************************************************************************** + * configs/spresense/src/cxd56_ili9340.c + * + * Copyright 2018 Sony Semiconductor Solutions Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name of Sony Semiconductor Solutions Corporation nor + * the names of its contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "cxd56_gpio.h" +#include "cxd56_spi.h" +#include "cxd56_pinconfig.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Check if the following are defined in the board.h */ + +#ifndef DISPLAY_RST +# error "DISPLAY_RST must be defined in board.h !!" +#endif +#ifndef DISPLAY_DC +# error "DISPLAY_DC must be defined in board.h !!" +#endif +#ifndef DISPLAY_SPI +# error "DISPLAY_SPI must be defined in board.h !!" +#endif + +/**************************************************************************** + * Private Type Definition + ****************************************************************************/ + +#ifndef ILI9340_SPI_MAXFREQUENCY +# define ILI9340_SPI_MAXFREQUENCY 20000000 +#endif + +/**************************************************************************** + * Private Function Protototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +struct ili93404ws_lcd_s +{ + struct ili9340_lcd_s dev; + struct spi_dev_s *spi; +}; +static struct ili93404ws_lcd_s g_lcddev; +static struct lcd_dev_s *g_lcd = NULL; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: cxd56_ili93404ws_select + * + * Description: + * Select the SPI, locking and re-configuring if necessary + * + * Input Parameters: + * spi - Reference to the public driver structure + * + * Returned Value: + * + ****************************************************************************/ + +static void cxd56_ili93404ws_select(FAR struct ili9340_lcd_s *lcd) +{ + FAR struct ili93404ws_lcd_s *priv = (FAR struct ili93404ws_lcd_s *)lcd; + + SPI_LOCK(priv->spi, true); + SPI_SELECT(priv->spi, SPIDEV_DISPLAY(0), true); +} + +/**************************************************************************** + * Name: cxd56_ili93404ws_deselect + * + * Description: + * De-select the SPI + * + * Input Parameters: + * spi - Reference to the public driver structure + * + * Returned Value: + * + ****************************************************************************/ + +static void cxd56_ili93404ws_deselect(FAR struct ili9340_lcd_s *lcd) +{ + FAR struct ili93404ws_lcd_s *priv = (FAR struct ili93404ws_lcd_s *)lcd; + + SPI_SELECT(priv->spi, SPIDEV_DISPLAY(0), false); + SPI_LOCK(priv->spi, false); +} + +/**************************************************************************** + * Name: cxd56_ili93404ws_backlight + * + * Description: + * Set the backlight level of the connected display. + * + * Input Parameters: + * spi - Reference to the public driver structure + * level - backligth level + * + * Returned Value: + * OK - On Success + * + ****************************************************************************/ + +static int cxd56_ili93404ws_backlight(FAR struct ili9340_lcd_s *lcd, + int level) +{ + if (level > 0) + { + lcd->sendcmd(lcd, ILI9340_WRITE_CTRL_DISPLAY); + lcd->sendparam(lcd, 0x24); + } + else + { + lcd->sendcmd(lcd, ILI9340_WRITE_CTRL_DISPLAY); + lcd->sendparam(lcd, 0x0); + } + + return OK; +} + +/**************************************************************************** + * Name: cxd56_ili93404ws_sendcmd + * + * Description: + * Send a command to the lcd driver. + * + * Input Parameters: + * lcd - Reference to the ili9340_lcd_s driver structure + * cmd - command to send + * + * Returned Value: + * On success - OK + * + ****************************************************************************/ + +static int cxd56_ili93404ws_sendcmd(FAR struct ili9340_lcd_s *lcd, + const uint8_t cmd) +{ + FAR struct ili93404ws_lcd_s *priv = (FAR struct ili93404ws_lcd_s *)lcd; + + lcdinfo("%02x\n", cmd); + + SPI_SETBITS(priv->spi, 8); + + /* FIXME: This function can be replaced with SPI_CMDDATA(). + * This feature is needed to enable CONFIG_SPI_CMDDATA and board specific + * cmddata() function. + */ + + cxd56_gpio_write(DISPLAY_DC, false); /* Indicate CMD */ + (void) SPI_SEND(priv->spi, cmd); + cxd56_gpio_write(DISPLAY_DC, true); /* Indicate DATA */ + + return OK; +} + +/**************************************************************************** + * Name: cxd56_ili93404ws_sendparam + * + * Description: + * Send a parameter to the lcd driver. + * + * Input Parameters: + * lcd - Reference to the ili9340_lcd_s driver structure + * param - parameter to send + * + * Returned Value: + * OK - On Success + * + ****************************************************************************/ + +static int cxd56_ili93404ws_sendparam(FAR struct ili9340_lcd_s *lcd, + const uint8_t param) +{ + FAR struct ili93404ws_lcd_s *priv = (FAR struct ili93404ws_lcd_s *)lcd; + + cxd56_gpio_write(DISPLAY_DC, true); /* Indicate DATA */ + (void) SPI_SEND(priv->spi, param); + + return OK; +} + +/**************************************************************************** + * Name: cxd56_ili93404ws_sendgram + * + * Description: + * Send a number of pixel words to the lcd driver gram. + * + * Input Parameters: + * lcd - Reference to the ili9340_lcd_s driver structure + * wd - Reference to the words to send + * nwords - number of words to send + * + * Returned Value: + * OK - On Success + * + ****************************************************************************/ + +static int cxd56_ili93404ws_sendgram(FAR struct ili9340_lcd_s *lcd, + const uint16_t *wd, uint32_t nwords) +{ + FAR struct ili93404ws_lcd_s *priv = (FAR struct ili93404ws_lcd_s *)lcd; + + lcdinfo("lcd:%p, wd=%p, nwords=%d\n", lcd, wd, nwords); + + SPI_SETBITS(priv->spi, 16); + (void) SPI_SNDBLOCK(priv->spi, wd, nwords); + + return OK; +} + +/**************************************************************************** + * Name: cxd56_ili93404ws_recvparam + * + * Description: + * Receive a parameter from the lcd driver. + * + * Input Parameters: + * lcd - Reference to the ili9340_lcd_s driver structure + * param - Reference to where parameter receive + * + * Returned Value: + * OK - On Success + * + ****************************************************************************/ + +static int cxd56_ili93404ws_recvparam(FAR struct ili9340_lcd_s *lcd, + uint8_t *param) +{ + FAR struct ili93404ws_lcd_s *priv = (FAR struct ili93404ws_lcd_s *)lcd; + + cxd56_gpio_write(DISPLAY_DC, true); /* Indicate DATA */ + *param = (uint8_t)(SPI_SEND(priv->spi, param) & 0xff); + + return OK; +} + +/**************************************************************************** + * Name: cxd56_ili93404ws_recvgram + * + * Description: + * Receive pixel words from the lcd driver gram. + * + * Input Parameters: + * lcd - Reference to the public driver structure + * wd - Reference to where the pixel words receive + * nwords - number of pixel words to receive + * + * Returned Value: + * OK - On Success + * + ****************************************************************************/ + +static int cxd56_ili93404ws_recvgram(FAR struct ili9340_lcd_s *lcd, + uint16_t *wd, uint32_t nwords) +{ + lcdinfo("wd=%p, nwords=%d\n", wd, nwords); + + return OK; +}; + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: board_lcd_initialize + * + * Description: + * Initialize the LCD 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). + * + ****************************************************************************/ + +int board_lcd_initialize(void) +{ + FAR struct ili93404ws_lcd_s *priv = &g_lcddev; + FAR struct spi_dev_s *spi; + + lcdinfo("Initializing lcd\n"); + + if (g_lcd == NULL) + { + spi = cxd56_spibus_initialize(DISPLAY_SPI); + if (!spi) + { + lcderr("ERROR: Failed to initialize spi bus.\n"); + return -ENODEV; + } + priv->spi = spi; + + /* Reset ILI9340 */ + + up_mdelay(10); + cxd56_gpio_write(DISPLAY_RST, false); + up_mdelay(10); + cxd56_gpio_write(DISPLAY_RST, true); + up_mdelay(50); + + /* Configure SPI */ + + SPI_SETMODE(priv->spi, SPIDEV_MODE3); + SPI_SETBITS(priv->spi, 8); + (void)SPI_HWFEATURES(priv->spi, 0); + (void)SPI_SETFREQUENCY(priv->spi, ILI9340_SPI_MAXFREQUENCY); + + /* Initialize ILI9340 driver with necessary methods */ + + priv->dev.select = cxd56_ili93404ws_select; + priv->dev.deselect = cxd56_ili93404ws_deselect; + priv->dev.sendcmd = cxd56_ili93404ws_sendcmd; + priv->dev.sendparam = cxd56_ili93404ws_sendparam; + priv->dev.recvparam = cxd56_ili93404ws_recvparam; + priv->dev.sendgram = cxd56_ili93404ws_sendgram; + priv->dev.recvgram = cxd56_ili93404ws_recvgram; + priv->dev.backlight = cxd56_ili93404ws_backlight; + + g_lcd = ili9340_initialize(&priv->dev, 0); + } + + return OK; +} + +/**************************************************************************** + * Name: board_lcd_getdev + * + * Description: + * Return a a reference to the LCD object for the specified LCD. This + * allows support for multiple LCD devices. + * + ****************************************************************************/ + +FAR struct lcd_dev_s *board_lcd_getdev(int lcddev) +{ + if (lcddev == 0) + { + return g_lcd; + } + return NULL; +} diff --git a/configs/spresense/src/cxd56_lpm013m091a.c b/configs/spresense/src/cxd56_lpm013m091a.c new file mode 100644 index 0000000000..8a4d3a43ad --- /dev/null +++ b/configs/spresense/src/cxd56_lpm013m091a.c @@ -0,0 +1,398 @@ +/**************************************************************************** + * configs/spresense/src/cxd56_lpm013m091a.c + * + * Copyright 2018 Sony Semiconductor Solutions Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name of Sony Semiconductor Solutions Corporation nor + * the names of its contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "cxd56_gpio.h" +#include "cxd56_spi.h" +#include "cxd56_pinconfig.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Check if the following are defined in the board.h */ + +#ifndef DISPLAY_RST +# error "DISPLAY_RST must be defined in board.h !!" +#endif +#ifndef DISPLAY_DC +# error "DISPLAY_DC must be defined in board.h !!" +#endif +#ifndef DISPLAY_SPI +# error "DISPLAY_SPI must be defined in board.h !!" +#endif + +/**************************************************************************** + * Private Type Definition + ****************************************************************************/ + +#ifndef LPM013M091A_SPI_MAXFREQUENCY +# define LPM013M091A_SPI_MAXFREQUENCY 20000000 +#endif + +/**************************************************************************** + * Private Function Protototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +struct lpm013m091a_lcd_s +{ + struct lpm013m091a_lcd_s dev; + struct spi_dev_s *spi; +}; +static struct lpm013m091a_lcd_s g_lcddev; +static struct lcd_dev_s *g_lcd = NULL; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: cxd56_lpm013m091a4ws_select + * + * Description: + * Select the SPI, locking and re-configuring if necessary + * + * Input Parameters: + * spi - Reference to the public driver structure + * + * Returned Value: + * + ****************************************************************************/ + +static void cxd56_lpm013m091a4ws_select(FAR struct lpm013m091a_lcd_s *lcd) +{ + FAR struct lpm013m091a_lcd_s *priv = (FAR struct lpm013m091a_lcd_s *)lcd; + + SPI_LOCK(priv->spi, true); + SPI_SELECT(priv->spi, SPIDEV_DISPLAY(0), true); +} + +/**************************************************************************** + * Name: cxd56_lpm013m091a4ws_deselect + * + * Description: + * De-select the SPI + * + * Input Parameters: + * spi - Reference to the public driver structure + * + * Returned Value: + * + ****************************************************************************/ + +static void cxd56_lpm013m091a4ws_deselect(FAR struct lpm013m091a_lcd_s *lcd) +{ + FAR struct lpm013m091a_lcd_s *priv = (FAR struct lpm013m091a_lcd_s *)lcd; + + SPI_SELECT(priv->spi, SPIDEV_DISPLAY(0), false); + SPI_LOCK(priv->spi, false); +} + +/**************************************************************************** + * Name: cxd56_lpm013m091a4ws_backlight + * + * Description: + * Set the backlight level of the connected display. + * + * Input Parameters: + * spi - Reference to the public driver structure + * level - backligth level + * + * Returned Value: + * OK - On Success + * + ****************************************************************************/ + +static int cxd56_lpm013m091a4ws_backlight(FAR struct lpm013m091a_lcd_s *lcd, + int level) +{ + if (level > 0) + { + lcd->sendcmd(lcd, 0x53); + lcd->sendparam(lcd, 0x24); + } + else + { + lcd->sendcmd(lcd, 0x53); + lcd->sendparam(lcd, 0x0); + } + + return OK; +} + +/**************************************************************************** + * Name: cxd56_lpm013m091a4ws_sendcmd + * + * Description: + * Send a command to the lcd driver. + * + * Input Parameters: + * lcd - Reference to the lpm013m091a_lcd_s driver structure + * cmd - command to send + * + * Returned Value: + * On success - OK + * + ****************************************************************************/ + +static int cxd56_lpm013m091a4ws_sendcmd(FAR struct lpm013m091a_lcd_s *lcd, + const uint8_t cmd) +{ + FAR struct lpm013m091a_lcd_s *priv = (FAR struct lpm013m091a_lcd_s *)lcd; + + lcdinfo("%02x\n", cmd); + + SPI_SETBITS(priv->spi, 8); + + /* FIXME: This function can be replaced with SPI_CMDDATA(). + * This feature is needed to enable CONFIG_SPI_CMDDATA and board specific + * cmddata() function. + */ + + cxd56_gpio_write(DISPLAY_DC, false); /* Indicate CMD */ + (void) SPI_SEND(priv->spi, cmd); + cxd56_gpio_write(DISPLAY_DC, true); /* Indicate DATA */ + + return OK; +} + +/**************************************************************************** + * Name: cxd56_lpm013m091a4ws_sendparam + * + * Description: + * Send a parameter to the lcd driver. + * + * Input Parameters: + * lcd - Reference to the lpm013m091a_lcd_s driver structure + * param - parameter to send + * + * Returned Value: + * OK - On Success + * + ****************************************************************************/ + +static int cxd56_lpm013m091a4ws_sendparam(FAR struct lpm013m091a_lcd_s *lcd, + const uint8_t param) +{ + FAR struct lpm013m091a_lcd_s *priv = (FAR struct lpm013m091a_lcd_s *)lcd; + + cxd56_gpio_write(DISPLAY_DC, true); /* Indicate DATA */ + (void) SPI_SEND(priv->spi, param); + + return OK; +} + +/**************************************************************************** + * Name: cxd56_lpm013m091a4ws_sendgram + * + * Description: + * Send a number of pixel words to the lcd driver gram. + * + * Input Parameters: + * lcd - Reference to the lpm013m091a_lcd_s driver structure + * wd - Reference to the words to send + * nwords - number of words to send + * + * Returned Value: + * OK - On Success + * + ****************************************************************************/ + +static int cxd56_lpm013m091a4ws_sendgram(FAR struct lpm013m091a_lcd_s *lcd, + const uint16_t *wd, uint32_t nwords) +{ + FAR struct lpm013m091a_lcd_s *priv = (FAR struct lpm013m091a_lcd_s *)lcd; + + lcdinfo("lcd:%p, wd=%p, nwords=%d\n", lcd, wd, nwords); + + SPI_SETBITS(priv->spi, 16); + (void) SPI_SNDBLOCK(priv->spi, wd, nwords); + + return OK; +} + +/**************************************************************************** + * Name: cxd56_lpm013m091a4ws_recvparam + * + * Description: + * Receive a parameter from the lcd driver. + * + * Input Parameters: + * lcd - Reference to the lpm013m091a_lcd_s driver structure + * param - Reference to where parameter receive + * + * Returned Value: + * OK - On Success + * + ****************************************************************************/ + +static int cxd56_lpm013m091a4ws_recvparam(FAR struct lpm013m091a_lcd_s *lcd, + uint8_t *param) +{ + FAR struct lpm013m091a_lcd_s *priv = (FAR struct lpm013m091a_lcd_s *)lcd; + + cxd56_gpio_write(DISPLAY_DC, true); /* Indicate DATA */ + *param = (uint8_t)(SPI_SEND(priv->spi, param) & 0xff); + + return OK; +} + +/**************************************************************************** + * Name: cxd56_lpm013m091a4ws_recvgram + * + * Description: + * Receive pixel words from the lcd driver gram. + * + * Input Parameters: + * lcd - Reference to the public driver structure + * wd - Reference to where the pixel words receive + * nwords - number of pixel words to receive + * + * Returned Value: + * OK - On Success + * + ****************************************************************************/ + +static int cxd56_lpm013m091a4ws_recvgram(FAR struct lpm013m091a_lcd_s *lcd, + uint16_t *wd, uint32_t nwords) +{ + lcdinfo("wd=%p, nwords=%d\n", wd, nwords); + + return OK; +}; + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: board_lcd_initialize + * + * Description: + * Initialize the LCD 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). + * + ****************************************************************************/ + +int board_lcd_initialize(void) +{ + FAR struct lpm013m091a_lcd_s *priv = &g_lcddev; + FAR struct spi_dev_s *spi; + + lcdinfo("Initializing lcd\n"); + + if (g_lcd == NULL) + { + spi = cxd56_spibus_initialize(DISPLAY_SPI); + if (!spi) + { + lcderr("ERROR: Failed to initialize spi bus.\n"); + return -ENODEV; + } + priv->spi = spi; + + /* Reset LPM013M091A */ + + up_mdelay(10); + cxd56_gpio_write(DISPLAY_RST, false); + up_mdelay(10); + cxd56_gpio_write(DISPLAY_RST, true); + up_mdelay(50); + + /* Configure SPI */ + + SPI_SETMODE(priv->spi, SPIDEV_MODE3); + SPI_SETBITS(priv->spi, 8); + (void)SPI_HWFEATURES(priv->spi, 0); + (void)SPI_SETFREQUENCY(priv->spi, LPM013M091A_SPI_MAXFREQUENCY); + + /* Initialize LPM013M091A driver with necessary methods */ + + priv->dev.select = cxd56_lpm013m091a4ws_select; + priv->dev.deselect = cxd56_lpm013m091a4ws_deselect; + priv->dev.sendcmd = cxd56_lpm013m091a4ws_sendcmd; + priv->dev.sendparam = cxd56_lpm013m091a4ws_sendparam; + priv->dev.recvparam = cxd56_lpm013m091a4ws_recvparam; + priv->dev.sendgram = cxd56_lpm013m091a4ws_sendgram; + priv->dev.recvgram = cxd56_lpm013m091a4ws_recvgram; + priv->dev.backlight = cxd56_lpm013m091a4ws_backlight; + + g_lcd = lpm013m091a_initialize(&priv->dev, 0); + } + + return OK; +} + +/**************************************************************************** + * Name: board_lcd_getdev + * + * Description: + * Return a a reference to the LCD object for the specified LCD. This + * allows support for multiple LCD devices. + * + ****************************************************************************/ + +FAR struct lcd_dev_s *board_lcd_getdev(int lcddev) +{ + if (lcddev == 0) + { + return g_lcd; + } + return NULL; +} diff --git a/drivers/lcd/Kconfig b/drivers/lcd/Kconfig index 52dd23352d..c2738e4c94 100644 --- a/drivers/lcd/Kconfig +++ b/drivers/lcd/Kconfig @@ -890,6 +890,132 @@ config LCD_RLANDSCAPE endchoice +config LCD_LPM013M091A + bool "JDI LPM013M091A LCD Driver" + default n + ---help--- + JDI LPM013M091A LCD Driver. + This driver doesn't support reading data. + Recommended to use DMA to transfer data or displayed image would be + broken. + +config LCD_ILI9340 + bool "ILI9340 LCD Single Chip Driver" + default n + ---help--- + LCD Single Chip Driver, ILI9340, ILI Technology Corp. + + Required LCD driver settings: + LCD_MAXCONTRAST should be 255, but any value >0 and <=255 will be accepted. + LCD_MAXPOWER should be 1: 0=off, 1=on + +config LCD_ILI9340_NINTERFACES + int "Number of supported display driver" + range 1 2 + default 1 + depends on LCD_ILI9340 + ---help--- + Define the number of supported displays driven by a ili9340 LCD Single + Chip Driver. + +config LCD_ILI9340_IFACE0 + bool "(1) LCD Display" + depends on LCD_ILI9340_NINTERFACES = 1 || LCD_ILI9340_NINTERFACES = 2 + ---help--- + Configure first LCD Display. + +if LCD_ILI9340_IFACE0 +choice + prompt "LCD Orientation" + default LCD_ILI9340_IFACE0_LANDSCAPE + ---help--- + Configure display orientation. + +config LCD_ILI9340_IFACE0_LANDSCAPE + bool "Landscape orientation" + ---help--- + Define for "landscape" orientation support. + +config LCD_ILI9340_IFACE0_PORTRAIT + bool "Portrait orientation" + ---help--- + Define for "portrait" orientation support. + +config LCD_ILI9340_IFACE0_RLANDSCAPE + bool "Reverse landscape orientation" + ---help--- + Define for "reverse landscape" orientation support. + +config LCD_ILI9340_IFACE0_RPORTRAIT + bool "Reverse portrait display" + ---help--- + Define for "reverse portrait" orientation support. + +endchoice + +choice + prompt "Color format" + default LCD_ILI9340_IFACE0_RGB565 + ---help--- + LCD color format. + +config LCD_ILI9340_IFACE0_RGB565 + bool "16 bpp RGB565 color format" + ---help--- + 16 bpp RGB565 color format + +endchoice +endif + +config LCD_ILI9340_IFACE1 + bool "(2) LCD Display" + depends on LCD_ILI9340_NINTERFACES = 2 + ---help--- + Configure second LCD Display. + +if LCD_ILI9340_IFACE1 +choice + prompt "LCD Orientation" + default LCD_ILI9340_IFACE1_LANDSCAPE + ---help--- + Configure display orientation. + +config LCD_ILI9340_IFACE1_LANDSCAPE + bool "Landscape orientation" + ---help--- + Define for "landscape" orientation support. + +config LCD_ILI9340_IFACE1_PORTRAIT + bool "Portrait orientation" + ---help--- + Define for "portrait" orientation support. + +config LCD_ILI9340_IFACE1_RLANDSCAPE + bool "Reverse landscape orientation" + ---help--- + Define for "reverse landscape" orientation support. + +config LCD_ILI9340_IFACE1_RPORTRAIT + bool "Reverse portrait display" + ---help--- + Define for "reverse portrait" orientation support. + +endchoice + +choice + prompt "Color format" + default LCD_ILI9340_IFACE1_RGB565 + ---help--- + LCD color format. + +config LCD_ILI9340_IFACE1_RGB565 + bool "16 bpp RGB565 color format" + ---help--- + 16 bpp RGB565 color format + +endchoice +endif + config LCD_ILI9341 bool "ILI9341 LCD Single Chip Driver" default n diff --git a/drivers/lcd/Make.defs b/drivers/lcd/Make.defs index 21535fcba7..bfc50baed8 100644 --- a/drivers/lcd/Make.defs +++ b/drivers/lcd/Make.defs @@ -52,6 +52,10 @@ else ifeq ($(CONFIG_LCD_FT80X_I2C),y) endif endif +ifeq ($(CONFIG_LCD_LPM013M091A),y) + CSRCS += lpm013m091a.c +endif + ifeq ($(CONFIG_LCD_P14201),y) CSRCS += p14201.c endif @@ -112,6 +116,10 @@ ifeq ($(CONFIG_LCD_SHARP_MEMLCD),y) CSRCS += memlcd.c endif +ifeq ($(CONFIG_LCD_ILI9340),y) + CSRCS += ili9340.c +endif + ifeq ($(CONFIG_LCD_ILI9341),y) CSRCS += ili9341.c endif diff --git a/drivers/lcd/ili9340.c b/drivers/lcd/ili9340.c new file mode 100644 index 0000000000..1926f36209 --- /dev/null +++ b/drivers/lcd/ili9340.c @@ -0,0 +1,1240 @@ +/**************************************************************************** + * drivers/lcd/ili9340.c + * + * LCD driver for the ILI9340 LCD Single Chip Driver + * + * Copyright (C) 2014 Marco Krahl. All rights reserved. + * Author: Marco Krahl + * + * References: ILI9340_DS_V1.10.pdf (Rev: 1.10), "a-Si TFT LCD Single Chip + * Driver 240RGBx320 Resolution and 262K color", + * ILI TECHNOLOGY CORP., www.ilitek.com. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior writen permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* This is the generic lcd driver interface for the ili9340 Single Chip LCD + * driver. The driver supports multiple displays, each connected with an own + * ili9340 Single Chip LCD driver. The communication with the LCD single chip + * driver must be provide by a subdriver accessable trough the ili9340_dev_s + * structure which is platform and MCU interface specific. + * + * Supported MCU interfaces (planed to support) + * + * Interface I + * + * 8080 MCU 8-bit bus interface + * 8080 MCU 16-bit bus interface + * 8080 MCU 9-bit bus interface + * 8080 MCU 18-bit bus interface + * 3-wire 9-bit data serial interface + * 4-wire 8-bit data serial interface + * + * Interface II + * + * 8080 MCU 8-bit bus interface + * 8080 MCU 16-bit bus interface + * 8080 MCU 9-bit bus interface + * 8080 MCU 18-bit bus interface + * 3-wire 9-bit data serial Interface + * 4-wire 8-bit data serial Interface + * + * Note! RGB interface will not supported by the lcd driver. + * It should be use with the platform specific RGB grapic controller and the + * nuttx framebuffer interface. + * + */ + +/* Fundamental command and parameter definition */ + +/* Interface control (IFCTL) + * + * + * Parameter 1: 0x0001 + * + * MY_EOR: 0 + * MX_EOR: 0 + * MV_EOR: 0 + * BGR_EOR: 0 + * WEMODE: 1 Reset column and page if data transfer exceeds + */ +#define ILI9340_IFCTL_MYEOR 0 +#define ILI9340_IFCTL_MXEOR 0 +#define ILI9340_IFCTL_MVEOR 0 +#define ILI9340_IFCTL_BGREOR 0 +#define ILI9340_IFCTL_WEMODE ILI9340_INTERFACE_CONTROL_WEMODE + +#define ILI9340_IFCTL_PARAM1 ILI9340_IFCTL_MYEOR | ILI9340_IFCTL_MXEOR | \ + ILI9340_IFCTL_MVEOR | ILI9340_IFCTL_BGREOR | \ + ILI9340_IFCTL_WEMODE + +/* Parameter 2: 0x0000 + * + * EPF: 0 65k color format for RGB interface, not used set to default + * MDT: 0 Display data transfer mode, not used + * + * Note! + * If RGB666 and 16-bit 8080-I interface supported by the driver, MDT must + * be defined for each selected driver instance. Leave it empty for now. + */ + +#define ILI9340_IFCTL_EPF ILI9340_INTERFACE_CONTROL_EPF(0) +#define ILI9340_IFCTL_MDT ILI9340_INTERFACE_CONTROL_MDT(0) + +#define ILI9340_IFCTL_PARAM2 ILI9340_IFCTL_EPF | ILI9340_IFCTL_MDT + +/* Parameter 3: 0x0000/0x0020 + * + * ENDIAN: 0/1 Depending on endian mode of the mcu? + * DM: 0 Internal clock operation + * RM: 0 System interface/VSYNC interface + * RIM: 0 RGB interface mode, unimportant set to default + * + */ + +#ifdef CONFIG_ENDIAN_BIG +# define ILI9340_IFCTL_ENDIAN 0 +#else +# define ILI9340_IFCTL_ENDIAN ILI9340_INTERFACE_CONTROL_ENDIAN +#endif +#define ILI9340_IFCTL_DM ILI9340_INTERFACE_CONTROL_DM(0) +#define ILI9340_IFCTL_RM 0 +#define ILI9340_IFCTL_RIM 0 + +#define ILI9340_IFCTL_PARAM3 ILI9340_IFCTL_RIM | ILI9340_IFCTL_RM | \ + ILI9340_IFCTL_DM | ILI9340_IFCTL_ENDIAN + +/* Memory access control (MADCTL) */ + +/* Landscape: 00100000 / 00101000 / h28 + * + * MY: 0 + * MX: 0 + * MV: 1 + * ML: 0 + * BGR: 0/1 Depending on endian mode of the mcu? + * MH: 0 + */ + +#define ILI9340_MADCTL_LANDSCAPE_MY 0 +#define ILI9340_MADCTL_LANDSCAPE_MX 0 +#define ILI9340_MADCTL_LANDSCAPE_MV ILI9340_MEMORY_ACCESS_CONTROL_MV +#define ILI9340_MADCTL_LANDSCAPE_ML 0 +#ifdef CONFIG_BIG_ENDIAN +# define ILI9340_MADCTL_LANDSCAPE_BGR 0 +#else +# define ILI9340_MADCTL_LANDSCAPE_BGR ILI9340_MEMORY_ACCESS_CONTROL_BGR +#endif +#define ILI9340_MADCTL_LANDSCAPE_MH 0 + +#define ILI9340_MADCTL_LANDSCAPE_PARAM1 (ILI9340_MADCTL_LANDSCAPE_MY | \ + ILI9340_MADCTL_LANDSCAPE_MX | \ + ILI9340_MADCTL_LANDSCAPE_MV | \ + ILI9340_MADCTL_LANDSCAPE_ML | \ + ILI9340_MADCTL_LANDSCAPE_BGR | \ + ILI9340_MADCTL_LANDSCAPE_MH) + +/* Portrait: 00000000 / 00001000 / h08 + * + * MY: 0 + * MX: 0 + * MV: 0 + * ML: 0 + * BGR: 0/1 Depending on endian mode of the mcu? + * MH: 0 + */ + +#define ILI9340_MADCTL_PORTRAIT_MY 0 +#define ILI9340_MADCTL_PORTRAIT_MX ILI9340_MEMORY_ACCESS_CONTROL_MX +#define ILI9340_MADCTL_PORTRAIT_MV 0 +#define ILI9340_MADCTL_PORTRAIT_ML ILI9340_MEMORY_ACCESS_CONTROL_ML +#ifdef CONFIG_BIG_ENDIAN +# define ILI9340_MADCTL_PORTRAIT_BGR 0 +#else +# define ILI9340_MADCTL_PORTRAIT_BGR ILI9340_MEMORY_ACCESS_CONTROL_BGR +#endif +#define ILI9340_MADCTL_PORTRAIT_MH 0 + +#define ILI9340_MADCTL_PORTRAIT_PARAM1 (ILI9340_MADCTL_PORTRAIT_MY | \ + ILI9340_MADCTL_PORTRAIT_MX | \ + ILI9340_MADCTL_PORTRAIT_MV | \ + ILI9340_MADCTL_PORTRAIT_ML | \ + ILI9340_MADCTL_PORTRAIT_BGR | \ + ILI9340_MADCTL_PORTRAIT_MH) +/* RLandscape: 01100000 / 01101000 / h68 + * + * MY: 0 + * MX: 1 + * MV: 1 + * ML: 0 + * BGR: 0/1 Depending on endian mode of the mcu? + * MH: 0 + */ + +#define ILI9340_MADCTL_RLANDSCAPE_MY ILI9340_MEMORY_ACCESS_CONTROL_MY +#define ILI9340_MADCTL_RLANDSCAPE_MX ILI9340_MEMORY_ACCESS_CONTROL_MX +#define ILI9340_MADCTL_RLANDSCAPE_MV ILI9340_MEMORY_ACCESS_CONTROL_MV +#define ILI9340_MADCTL_RLANDSCAPE_ML 0 +#ifdef CONFIG_BIG_ENDIAN +# define ILI9340_MADCTL_RLANDSCAPE_BGR 0 +#else +# define ILI9340_MADCTL_RLANDSCAPE_BGR ILI9340_MEMORY_ACCESS_CONTROL_BGR +#endif +#define ILI9340_MADCTL_RLANDSCAPE_MH 0 + +#define ILI9340_MADCTL_RLANDSCAPE_PARAM1 \ + (ILI9340_MADCTL_RLANDSCAPE_MY | \ + ILI9340_MADCTL_RLANDSCAPE_MX | \ + ILI9340_MADCTL_RLANDSCAPE_MV | \ + ILI9340_MADCTL_RLANDSCAPE_ML | \ + ILI9340_MADCTL_RLANDSCAPE_BGR | \ + ILI9340_MADCTL_RLANDSCAPE_MH) + +/* RPortrait: 11000000 / 11001000 / hc8 + * + * MY: 1 + * MX: 1 + * MV: 0 + * ML: 0 + * BGR: 0/1 Depending on endian mode of the mcu? + * MH: 0 + * + */ + +#define ILI9340_MADCTL_RPORTRAIT_MY ILI9340_MEMORY_ACCESS_CONTROL_MY +#define ILI9340_MADCTL_RPORTRAIT_MX 0 +#define ILI9340_MADCTL_RPORTRAIT_MV 0 +#define ILI9340_MADCTL_RPORTRAIT_ML ILI9340_MEMORY_ACCESS_CONTROL_ML +#ifdef CONFIG_BIG_ENDIAN +# define ILI9340_MADCTL_RPORTRAIT_BGR 0 +#else +# define ILI9340_MADCTL_RPORTRAIT_BGR ILI9340_MEMORY_ACCESS_CONTROL_BGR +#endif +#define ILI9340_MADCTL_RPORTRAIT_MH 0 + +#define ILI9340_MADCTL_RPORTRAIT_PARAM1 (ILI9340_MADCTL_RPORTRAIT_MY | \ + ILI9340_MADCTL_RPORTRAIT_MX | \ + ILI9340_MADCTL_RPORTRAIT_MV | \ + ILI9340_MADCTL_RPORTRAIT_ML | \ + ILI9340_MADCTL_RPORTRAIT_BGR | \ + ILI9340_MADCTL_RPORTRAIT_MH) + +/* Pixel Format Set (COLMOD) + * + * Note! RGB interface settings (DPI) is unimportant for the MCU interface + * mode but set the register to the defined state equal to the MCU interface + * pixel format. + * + * 16 Bit MCU: 01010101 / h55 + * + * DPI: 5 (RGB16-565 RGB interface, not used) + * DBI: 5 (RGB16-565 MCU interface + */ + +#define ILI9340_PIXSET_16BITDPI ILI9340_PIXEL_FORMAT_SET_DPI(5) +#define ILI9340_PIXSET_16BITDBI ILI9340_PIXEL_FORMAT_SET_DBI(5) + +#define ILI9340_PIXSET_16BITMCU_PARAM1 (ILI9340_PIXSET_16BITDPI | \ + ILI9340_PIXSET_16BITDBI) + +/* 18-bit MCU: 01100110 / h66 (not supported by nuttx until now) + * + * DPI: 6 (RGB18-666 RGB interface) + * DBI: 6 (RGB18-666 MCU interface) + */ + +#define ILI9340_PIXSET_18BITDPI ILI9340_PIXEL_FORMAT_SET_DPI(6) +#define ILI9340_PIXSET_18BITDBI ILI9340_PIXEL_FORMAT_SET_DBI(6) + +#define ILI9340_PIXSET_18BITMCU_PARAM1 (ILI9340_PIXSET_18BITDPI | \ + ILI9340_PIXSET_18BITDBI) + +/* General fix display resolution */ + +#define ILI9340_XRES 240 +#define ILI9340_YRES 320 + +/* Validate configuration */ + +#if CONFIG_LCD_ILI9340_NINTERFACES < 1 +# undef CONFIG_LCD_ILI9340_IFACE0 +#elif CONFIG_LCD_ILI9340_NINTERFACES < 2 +# undef CONFIG_LCD_ILI9340_IFACE1 +#endif + +/* First LCD display */ + +#ifdef CONFIG_LCD_ILI9340_IFACE0 +# if defined(CONFIG_LCD_ILI9340_IFACE0_LANDSCAPE) +# define ILI9340_IFACE0_ORIENT ILI9340_MADCTL_LANDSCAPE_PARAM1 +# define ILI9340_IFACE0_STRIDE ILI9340_YRES +# elif defined(CONFIG_LCD_ILI9340_IFACE0_PORTRAIT) +# define ILI9340_IFACE0_ORIENT ILI9340_MADCTL_PORTRAIT_PARAM1 +# define ILI9340_IFACE0_STRIDE ILI9340_XRES +# elif defined(CONFIG_LCD_ILI9340_IFACE0_RLANDSCAPE) +# define ILI9340_IFACE0_ORIENT ILI9340_MADCTL_RLANDSCAPE_PARAM1 +# define ILI9340_IFACE0_STRIDE ILI9340_YRES +# elif defined(CONFIG_LCD_ILI9340_IFACE0_RPORTRAIT) +# define ILI9340_IFACE0_ORIENT ILI9340_MADCTL_RPORTRAIT_PARAM1 +# define ILI9340_IFACE0_STRIDE ILI9340_XRES +# endif +# ifdef CONFIG_LCD_ILI9340_IFACE0_RGB565 +# define ILI9340_IFACE0_PXFMT FB_FMT_RGB16_565 +# define ILI9340_IFACE0_BPP 16 +# define ILI9340_IFACE0_BUFFER ILI9340_IFACE0_STRIDE +# else +# error "undefined pixel format for lcd interface 0" +# endif +#endif + +/* Second LCD display */ + +#ifdef CONFIG_LCD_ILI9340_IFACE1 +# ifdef CONFIG_LCD_ILI9340_IFACE1_LANDSCAPE +# define ILI9340_IFACE1_ORIENT ILI9340_MADCTL_LANDSCAPE_PARAM1 +# define ILI9340_IFACE1_STRIDE ILI9340_YRES +# elif CONFIG_LCD_ILI9340_IFACE1_PORTRAIT +# define ILI9340_IFACE1_ORIENT ILI9340_MADCTL_PORTRAIT_PARAM1 +# define ILI9340_IFACE1_STRIDE ILI9340_XRES +# elif CONFIG_LCD_ILI9340_IFACE1_RLANDSCAPE +# define ILI9340_IFACE1_ORIENT ILI9340_MADCTL_RLANDSCAPE_PARAM1 +# define ILI9340_IFACE1_STRIDE ILI9340_YRES +# elif CONFIG_LCD_ILI9340_IFACE1_RPORTRAIT +# define ILI9340_IFACE1_ORIENT ILI9340_MADCTL_RPORTRAIT_PARAM1 +# define ILI9340_IFACE1_STRIDE ILI9340_XRES +# endif +# ifdef CONFIG_LCD_ILI9340_IFACE1_RGB565 +# define ILI9340_IFACE1_PXFMT FB_FMT_RGB16_565 +# define ILI9340_IFACE1_BPP 16 +# define ILI9340_IFACE1_BUFFER ILI9340_IFACE1_STRIDE +# else +# error "undefined pixel format for lcd interface 1" +# endif +#endif + +/**************************************************************************** + * Private Type Definition + ****************************************************************************/ + +/* Each single connected ili9340 LCD driver needs an own driver instance + * to provide a unique getrun and putrun method. Also store fundamental + * parameter in driver internal structure. This minimal overhead should be + * acceptable. + */ + +struct ili9340_dev_s +{ + /* Publically visible device structure */ + + struct lcd_dev_s dev; + + /* Private driver-specific information follows */ + + FAR struct ili9340_lcd_s *lcd; + + /* Driver specific putrun function */ + + int (*putrun)(fb_coord_t row, fb_coord_t col, + FAR const uint8_t * buffer, size_t npixels); +#ifndef CONFIG_LCD_NOGETRUN + /* Driver specific getrun function */ + + int (*getrun)(fb_coord_t row, fb_coord_t col, + FAR uint8_t * buffer, size_t npixels); +#endif + /* Run buffer for the device */ + + uint16_t *runbuffer; + + /* Display orientation, e.g. Landscape, Portrait */ + + uint8_t orient; + + /* LCD driver pixel format */ + + uint8_t pxfmt; + + /* LCD driver color depth */ + + uint8_t bpp; + + /* Current power state of the device */ + + uint8_t power; +}; + +/**************************************************************************** + * Private Function Protototypes + ****************************************************************************/ + +/* Internal low level helpers */ + +static inline uint16_t ili9340_getxres(FAR struct ili9340_dev_s *dev); +static inline uint16_t ili9340_getyres(FAR struct ili9340_dev_s *dev); + +/* lcd data transfer methods */ + +static int ili9340_putrun(int devno, fb_coord_t row, fb_coord_t col, + FAR const uint8_t * buffer, size_t npixels); +#ifndef CONFIG_LCD_NOGETRUN +static int ili9340_getrun(int devno, fb_coord_t row, fb_coord_t col, + FAR uint8_t * buffer, size_t npixels); +#endif + +/* Definition of the public visible getrun / putrun methods + * each for a single LCD driver + */ + +#ifdef CONFIG_LCD_ILI9340_IFACE0 +static int ili9340_putrun0(fb_coord_t row, fb_coord_t col, + FAR const uint8_t *buffer, size_t npixsels); +#endif +#ifdef CONFIG_LCD_ILI9340_IFACE1 +static int ili9340_putrun1(fb_coord_t row, fb_coord_t col, + FAR const uint8_t * buffer, size_t npixsels); +#endif + +#ifndef CONFIG_LCD_NOGETRUN +# ifdef CONFIG_LCD_ILI9340_IFACE0 +static int ili9340_getrun0(fb_coord_t row, fb_coord_t col, + FAR uint8_t * buffer, size_t npixsels); +# endif +# ifdef CONFIG_LCD_ILI9340_IFACE1 +static int ili9340_getrun1(fb_coord_t row, fb_coord_t col, + FAR uint8_t * buffer, size_t npixsels); +# endif +#endif + +/* lcd configuration */ + +static int ili9340_getvideoinfo(FAR struct lcd_dev_s *dev, + FAR struct fb_videoinfo_s *vinfo); +static int ili9340_getplaneinfo(FAR struct lcd_dev_s *dev, + unsigned int planeno, + FAR struct lcd_planeinfo_s *pinfo); + +/* lcd specific controls */ + +static int ili9340_getpower(struct lcd_dev_s *dev); +static int ili9340_setpower(struct lcd_dev_s *dev, int power); +static int ili9340_getcontrast(struct lcd_dev_s *dev); +static int ili9340_setcontrast(struct lcd_dev_s *dev, unsigned int contrast); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* Initialize driver instance 1 < LCD_ILI9340_NINTERFACES */ + +#ifdef CONFIG_LCD_ILI9340_IFACE0 +static uint16_t g_runbuffer0[ILI9340_IFACE0_BUFFER]; +#endif +#ifdef CONFIG_LCD_ILI9340_IFACE1 +static uint16_t g_runbuffer1[ILI9340_IFACE1_BUFFER]; +#endif + +static struct ili9340_dev_s g_lcddev[CONFIG_LCD_ILI9340_NINTERFACES] = +{ +#ifdef CONFIG_LCD_ILI9340_IFACE0 + { + .lcd = 0, + .putrun = ili9340_putrun0, +# ifndef CONFIG_LCD_NOGETRUN + .getrun = ili9340_getrun0, +# endif + .runbuffer = g_runbuffer0, + .orient = ILI9340_IFACE0_ORIENT, + .pxfmt = ILI9340_IFACE0_PXFMT, + .bpp = ILI9340_IFACE0_BPP, + .power = 0, + }, +#endif +#ifdef CONFIG_LCD_ILI9340_IFACE1 + { + .lcd = 0, + .putrun = ili9340_putrun1, +# ifndef CONFIG_LCD_NOGETRUN + .getrun = ili9340_getrun1, +# endif + .runbuffer = g_runbuffer1, + .orient = ILI9340_IFACE1_ORIENT, + .pxfmt = ILI9340_IFACE1_PXFMT, + .bpp = ILI9340_IFACE1_BPP, + .power = 0, + }, +#endif +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: ili9340_getxres + * + * Description: + * Get horicontal resolution of the connected LCD driver depending on the + * configured display orientation. + * + * Parameters: + * dev - Reference to private driver structure + * + * Return Value: + * + * Horicontal resolution + * + ****************************************************************************/ + +static inline uint16_t ili9340_getxres(FAR struct ili9340_dev_s *dev) +{ + if (dev->orient == ILI9340_MADCTL_LANDSCAPE_PARAM1 || + dev->orient == ILI9340_MADCTL_RLANDSCAPE_PARAM1) + { + return ILI9340_YRES; + } + + return ILI9340_XRES; +} + +/**************************************************************************** + * Name: ili9340_getyres + * + * Description: + * Get vertical resolution of the connected LCD driver depending on the + * configured display orientation. + * + * Parameter: + * dev - Reference to private driver structure + * + * Return Value: + * + * Vertical resolution + * + ****************************************************************************/ + +static inline uint16_t ili9340_getyres(FAR struct ili9340_dev_s *dev) +{ + if (dev->orient == ILI9340_MADCTL_LANDSCAPE_PARAM1 || + dev->orient == ILI9340_MADCTL_RLANDSCAPE_PARAM1) + { + return ILI9340_XRES; + } + + return ILI9340_YRES; +} + +/**************************************************************************** + * Name: ili9340_selectarea + * + * Description: + * Select the active area for displaying pixel + * + * Parameter: + * lcd - Reference to private driver structure + * x0 - Start x position + * y0 - Start y position + * x1 - End x position + * y1 - End y position + * + ****************************************************************************/ + +static void ili9340_selectarea(FAR struct ili9340_lcd_s *lcd, + uint16_t x0, uint16_t y0, + uint16_t x1, uint16_t y1) +{ + /* Select column */ + + lcd->sendcmd(lcd, ILI9340_COLUMN_ADDRESS_SET); + lcd->sendparam(lcd, (x0 >> 8)); + lcd->sendparam(lcd, (x0 & 0xff)); + lcd->sendparam(lcd, (x1 >> 8)); + lcd->sendparam(lcd, (x1 & 0xff)); + + /* Select page */ + + lcd->sendcmd(lcd, ILI9340_PAGE_ADDRESS_SET); + lcd->sendparam(lcd, (y0 >> 8)); + lcd->sendparam(lcd, (y0 & 0xff)); + lcd->sendparam(lcd, (y1 >> 8)); + lcd->sendparam(lcd, (y1 & 0xff)); +} + +/**************************************************************************** + * Name: ili9340_putrun + * + * Description: + * Write a partial raster line to the LCD. + * + * Parameters: + * devno - Number of lcd device + * row - Starting row to write to (range: 0 <= row < yres) + * col - Starting column to write to (range: 0 <= col <= xres-npixels) + * buffer - The buffer containing the run to be writen to the LCD + * npixels - The number of pixels to write to the + * (range: 0 < npixels <= xres-col) + * + * Returned Value: + * + * On success - OK + * On error - -EINVAL + * + ****************************************************************************/ + +static int ili9340_putrun(int devno, fb_coord_t row, fb_coord_t col, + FAR const uint8_t * buffer, size_t npixels) +{ + FAR struct ili9340_dev_s *dev = &g_lcddev[devno]; + FAR struct ili9340_lcd_s *lcd = dev->lcd; + FAR const uint16_t *src = (FAR const uint16_t *)buffer; + + DEBUGASSERT(buffer && ((uintptr_t)buffer & 1) == 0); + + /* Check if position outside of area */ + + if (col + npixels > ili9340_getxres(dev) || row > ili9340_getyres(dev)) + { + return -EINVAL; + } + + /* Select lcd driver */ + + lcd->select(lcd); + + /* Select column and area similar to the partial raster line */ + + ili9340_selectarea(lcd, col, row, col + npixels - 1, row); + + /* Send memory write cmd */ + + lcd->sendcmd(lcd, ILI9340_MEMORY_WRITE); + + /* Send pixel to gram */ + + lcd->sendgram(lcd, src, npixels); + + /* Deselect the lcd driver */ + + lcd->deselect(lcd); + + return OK; +} + +/**************************************************************************** + * Name: ili9340_getrun + * + * Description: + * Read a partial raster line from the LCD. + * + * Parameter: + * devno - Number of the lcd device + * row - Starting row to read from (range: 0 <= row < yres) + * col - Starting column to read read (range: 0 <= col <= xres-npixels) + * buffer - The buffer in which to return the run read from the LCD + * npixels - The number of pixels to read from the LCD + * (range: 0 < npixels <= xres-col) + * + * Returned Value: + * + * On success - OK + * On error - -EINVAL + * + ****************************************************************************/ + +# ifndef CONFIG_LCD_NOGETRUN +static int ili9340_getrun(int devno, fb_coord_t row, fb_coord_t col, + FAR uint8_t * buffer, size_t npixels) +{ + FAR struct ili9340_dev_s *dev = &g_lcddev[devno]; + FAR struct ili9340_lcd_s *lcd = dev->lcd; + FAR uint16_t *dest = (FAR uint16_t *)buffer; + + DEBUGASSERT(buffer && ((uintptr_t)buffer & 1) == 0); + + /* Check if position outside of area */ + + if (col + npixels > ili9340_getxres(dev) || row > ili9340_getyres(dev)) + { + return -EINVAL; + } + + /* Select lcd driver */ + + lcd->select(lcd); + + /* Select column and area similar to the partial raster line */ + + ili9340_selectarea(lcd, col, row, col + npixels - 1, row); + + /* Send memory read cmd */ + + lcd->sendcmd(lcd, ILI9340_MEMORY_READ); + + /* Receive pixel to gram */ + + lcd->recvgram(lcd, dest, npixels); + + /* Deselect the lcd driver */ + + lcd->deselect(lcd); + + return OK; +} +#endif + +/**************************************************************************** + * Name: ili9340_hwinitialize + * + * Description: + * Initialize and configure the ILI9340 LCD driver hardware. + * + * Parameter: + * dev - A reference to the driver specific structure + * + * Returned Value: + * + * On success - OK + * On error - EINVAL + * + ****************************************************************************/ + +static int ili9340_hwinitialize(FAR struct ili9340_dev_s *dev) +{ +#ifdef CONFIG_DEBUG_LCD_INFO + uint8_t param; +#endif + FAR struct ili9340_lcd_s *lcd = dev->lcd; + + /* Select spi device */ + + lcdinfo("Initialize lcd driver\n"); + lcd->select(lcd); + +#ifdef CONFIG_DEBUG_LCD_INFO + /* Read display identification */ + + lcd->sendcmd(lcd, ILI9340_READ_ID1); + lcd->recvparam(lcd, ¶m); + lcdinfo("ili9340 LCD driver: LCD modules manufacturer ID: %d\n", param); + + lcd->sendcmd(lcd, ILI9340_READ_ID2); + lcd->recvparam(lcd, ¶m); + lcdinfo("ili9340 LCD driver: LCD modules driver version ID: %d\n", param); + + lcd->sendcmd(lcd, ILI9340_READ_ID3); + lcd->recvparam(lcd, ¶m); + lcdinfo("ili9340 LCD driver: LCD modules driver ID: %d\n", param); +#endif + + /* Reset the lcd display to the default state */ + + lcdinfo("ili9340 LCD driver: Software Reset\n"); + lcd->sendcmd(lcd, ILI9340_SOFTWARE_RESET); + up_mdelay(5); + + lcdinfo("ili9340 LCD driver: set Memory Access Control: %04x\n", + dev->orient); + lcd->sendcmd(lcd, ILI9340_MEMORY_ACCESS_CONTROL); + lcd->sendparam(lcd, dev->orient); + + /* Select column and area */ + + ili9340_selectarea(lcd, 0, 0, ILI9340_XRES, ILI9340_YRES); + + /* Pixel Format set */ + + lcd->sendcmd(lcd, ILI9340_PIXEL_FORMAT_SET); + + /* 16 bit RGB565 */ + + lcdinfo("ili9340 LCD driver: Set Pixel Format: %04x\n", + ILI9340_PIXSET_16BITMCU_PARAM1); + lcd->sendparam(lcd, ILI9340_PIXSET_16BITMCU_PARAM1); + + /* 18 bit RGB666, add settings here */ + + lcdinfo("ili9340 LCD driver: Set Interface control\n"); + lcd->sendcmd(lcd, ILI9340_INTERFACE_CONTROL); + lcd->sendparam(lcd, ILI9340_IFCTL_PARAM1); + lcd->sendparam(lcd, ILI9340_IFCTL_PARAM2); + lcd->sendparam(lcd, ILI9340_IFCTL_PARAM3); + + /* Sleep out */ + + lcdinfo("ili9340 LCD driver: Sleep Out\n"); + lcd->sendcmd(lcd, ILI9340_SLEEP_OUT); + up_mdelay(120); + + /* Deselect the device */ + + lcd->deselect(lcd); + + /* Switch display off */ + + ili9340_setpower(&dev->dev, 0); + + return OK; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: ili9340_putrunx + * + * Description: + * Write a partial raster line to the LCD. + * + * Parameter: + * row - Starting row to write to (range: 0 <= row < yres) + * col - Starting column to write to (range: 0 <= col <= xres-npixels) + * buffer - The buffer containing the run to be writen to the LCD + * npixels - The number of pixels to write to the + * (range: 0 < npixels <= xres-col) + * + * Returned Value: + * + * On success - OK + * On error - -EINVAL + * + ****************************************************************************/ + +#ifdef CONFIG_LCD_ILI9340_IFACE0 +static int ili9340_putrun0(fb_coord_t row, fb_coord_t col, + FAR const uint8_t * buffer, size_t npixels) +{ + return ili9340_putrun(0, row, col, buffer, npixels); +} +#endif + +#ifdef CONFIG_LCD_ILI9340_IFACE1 +static int ili9340_putrun1(fb_coord_t row, fb_coord_t col, + FAR const uint8_t * buffer, size_t npixels) +{ + return ili9340_putrun(1, row, col, buffer, npixels); +} +#endif + +/**************************************************************************** + * Name: ili9340_getrunx + * + * Description: + * Read a partial raster line from the LCD. + * + * Parameter: + * row - Starting row to read from (range: 0 <= row < yres) + * col - Starting column to read from (range: 0 <= col <= xres-npixels) + * buffer - The buffer containing the run to be writen to the LCD + * npixels - The number of pixels to read from the + * (range: 0 < npixels <= xres-col) + * + * Returned Value: + * + * On success - OK + * On error - -EINVAL + * + ****************************************************************************/ + +#ifndef CONFIG_LCD_NOGETRUN +# ifdef CONFIG_LCD_ILI9340_IFACE0 +static int ili9340_getrun0(fb_coord_t row, fb_coord_t col, + FAR uint8_t * buffer, size_t npixels) +{ + return ili9340_getrun(0, row, col, buffer, npixels); +} +# endif + +# ifdef CONFIG_LCD_ILI9340_IFACE1 +static int ili9340_getrun1(fb_coord_t row, fb_coord_t col, + FAR uint8_t * buffer, size_t npixels) +{ + return ili9340_getrun(1, row, col, buffer, npixels); +} +# endif +#endif + +/**************************************************************************** + * Name: ili9340_getvideoinfo + * + * Description: + * Get information about the LCD video controller configuration. + * + * Parameter: + * dev - A reference to the driver specific structure + * vinfo - A reference to the videoinfo structure + * + * Returned Value: + * + * On success - OK + * On error - -EINVAL + * + ****************************************************************************/ + +static int ili9340_getvideoinfo(FAR struct lcd_dev_s *dev, + FAR struct fb_videoinfo_s *vinfo) +{ + if (dev && vinfo) + { + FAR struct ili9340_dev_s *priv = (FAR struct ili9340_dev_s *)dev; + + vinfo->fmt = priv->pxfmt; + vinfo->xres = ili9340_getxres(priv); + vinfo->yres = ili9340_getyres(priv); + vinfo->nplanes = 1; + + lcdinfo("fmt: %d xres: %d yres: %d nplanes: %d\n", + vinfo->fmt, vinfo->xres, vinfo->yres, vinfo->nplanes); + + return OK; + } + + return -EINVAL; +} + +/**************************************************************************** + * Name: ili9340_getplaneinfo + * + * Description: + * Get information about the configuration of each LCD color plane. + * + * Parameter: + * dev - A reference to the driver specific structure + * planeno - The plane number + * pinfo - A reference to the planeinfo structure + * + * Returned Value: + * + * On success - OK + * On error - -EINVAL + * + ****************************************************************************/ + +static int ili9340_getplaneinfo(FAR struct lcd_dev_s *dev, + unsigned int planeno, + FAR struct lcd_planeinfo_s *pinfo) +{ + if (dev && pinfo && planeno == 0) + { + FAR struct ili9340_dev_s *priv = (FAR struct ili9340_dev_s *)dev; + + pinfo->putrun = priv->putrun; +#ifndef CONFIG_LCD_NOGETRUN + pinfo->getrun = priv->getrun; +#endif + pinfo->bpp = priv->bpp; + pinfo->buffer = (FAR uint8_t *)priv->runbuffer; /* Run scratch buffer */ + + lcdinfo("planeno: %d bpp: %d\n", planeno, pinfo->bpp); + + return OK; + } + + return -EINVAL; +} + +/**************************************************************************** + * Name: ili9340_getpower + * + * Description: + * Get the LCD panel power status + * (0: full off - CONFIG_LCD_MAXPOWER: full on. + * On backlit LCDs, this setting may correspond to the backlight setting. + * + * Parameter: + * dev - A reference to the driver specific structure + * + * Returned Value: + * + * On success - OK + * On error - -EINVAL + * + ****************************************************************************/ + +static int ili9340_getpower(FAR struct lcd_dev_s *dev) +{ + FAR struct ili9340_dev_s *priv = (FAR struct ili9340_dev_s *)dev; + + if (priv) + { + lcdinfo("%d\n", priv->power); + + return priv->power; + } + + return -EINVAL; +} + +/**************************************************************************** + * Name: ili9340_setpower + * + * Description: + * Enable/disable LCD panel power + * (0: full off - CONFIG_LCD_MAXPOWER: full on). + * On backlight LCDs, this setting may correspond to the backlight setting. + * + * Parameter: + * dev - A reference to the driver specific structure + * power - Value of the power + * + * Returned Value: + * + * On success - OK + * On error - -EINVAL + * + ****************************************************************************/ + +static int ili9340_setpower(FAR struct lcd_dev_s *dev, int power) +{ + FAR struct ili9340_dev_s *priv = (FAR struct ili9340_dev_s *)dev; + FAR struct ili9340_lcd_s *lcd = priv->lcd; + + if (dev) + { + lcdinfo("%d\n", power); + + lcd->select(lcd); + + if (power > 0) + { + /* Set backlight level */ + + lcd->backlight(lcd, power); + + /* And switch LCD on */ + + lcd->sendcmd(lcd, ILI9340_DISPLAY_ON); + up_mdelay(120); + } + else + { + /* Switch LCD off */ + + lcd->sendcmd(lcd, ILI9340_DISPLAY_OFF); + } + + lcd->deselect(lcd); + + priv->power = power; + + return OK; + } + + return -EINVAL; +} + +/**************************************************************************** + * Name: ili9340_getcontrast + * + * Description: + * Get the current contrast setting (0-CONFIG_LCD_MAXCONTRAST). + * + * Parameter: + * dev - A reference to the lcd driver structure + * + * Returned Value: + * + * On success - current contrast value + * On error - -ENOSYS, not supported by the ili9340. + * + ****************************************************************************/ + +static int ili9340_getcontrast(struct lcd_dev_s *dev) +{ + lcdinfo("Not implemented\n"); + return -ENOSYS; +} + +/**************************************************************************** + * Name: ili9340_setcontrast + * + * Description: + * Set LCD panel contrast (0-CONFIG_LCD_MAXCONTRAST). + * + * Parameter: + * dev - A reference to the lcd driver structure + * + * Returned Value: + * + * On success - OK + * On error - -ENOSYS, not supported by the ili9340. + * + ****************************************************************************/ + +static int ili9340_setcontrast(struct lcd_dev_s *dev, unsigned int contrast) +{ + lcdinfo("contrast: %d\n", contrast); + return -ENOSYS; +} + +/**************************************************************************** + * Name: ili9340_initialize + * + * Description: + * Initialize the LCD video driver internal sturcture. Also initialize the + * lcd hardware if not done. The control of the LCD driver is depend on the + * selected MCU interface and part of the platform specific subdriver (see + * config/stm32f429i-disco/src/stm32_ili93404ws.c) + * + * Input Parameters: + * + * lcd - A reference to the platform specific driver instance to control the + * ili9340 display driver. + * devno - A value in the range of 0 through CONFIG_ILI9340_NINTERFACES-1. + * This allows support for multiple LCD devices. + * + * Returned Value: + * + * On success, this function returns a reference to the LCD driver object for + * the specified LCD driver. NULL is returned on any failure. + * + ****************************************************************************/ + +FAR struct lcd_dev_s *ili9340_initialize( + FAR struct ili9340_lcd_s *lcd, int devno) +{ + if (lcd && devno >= 0 && devno < CONFIG_LCD_ILI9340_NINTERFACES) + { + FAR struct ili9340_dev_s *priv = &g_lcddev[devno]; + + /* Check if initialized */ + + if (!priv->lcd) + { + FAR struct lcd_dev_s *dev = &priv->dev; + int ret; + + /* Initialize internal structure */ + + dev->getvideoinfo = ili9340_getvideoinfo; + dev->getplaneinfo = ili9340_getplaneinfo; + dev->getpower = ili9340_getpower; + dev->setpower = ili9340_setpower; + dev->getcontrast = ili9340_getcontrast; + dev->setcontrast = ili9340_setcontrast; + priv->lcd = lcd; + + /* Initialze the LCD driver */ + + ret = ili9340_hwinitialize(priv); + + if (ret == OK) + { + return &priv->dev; + } + + errno = EINVAL; + } + } + + return NULL; +} + +/**************************************************************************** + * Name: ili9340_clear + * + * Description: + * This is a non-standard LCD interface. Because of the various rotations, + * clearing the display in the normal way by writing a sequences of runs that + * covers the entire display can be very slow. Here the display is cleared by + * simply setting all GRAM memory to the specified color. + * + * Parameter: + * dev - A reference to the lcd driver structure + * color - The background color + * + * Returned Value: + * + * On success - OK + * On error - -EINVAL + * + ****************************************************************************/ + +int ili9340_clear(FAR struct lcd_dev_s *dev, uint16_t color) +{ + FAR struct ili9340_dev_s *priv = (FAR struct ili9340_dev_s *)dev; + FAR struct ili9340_lcd_s *lcd = priv->lcd; + uint16_t xres = ili9340_getxres(priv); + uint16_t yres = ili9340_getyres(priv); + uint32_t n; + + if (!lcd) + { + return -EINVAL; + } + + /* Select lcd driver */ + + lcd->select(lcd); + + /* Select column and area similar to the visible area */ + + ili9340_selectarea(lcd, 0, 0, xres, yres); + + /* Send memory write cmd */ + + lcd->sendcmd(lcd, ILI9340_MEMORY_WRITE); + + /* clear the visible area */ + + for (n = 0; n < xres * yres; n++) + { + /* Send pixel to gram */ + + lcd->sendgram(lcd, &color, 1); + } + + /* Deselect the lcd driver */ + + lcd->deselect(lcd); + + return OK; +} diff --git a/drivers/lcd/lpm013m091a.c b/drivers/lcd/lpm013m091a.c new file mode 100644 index 0000000000..5443d5c77d --- /dev/null +++ b/drivers/lcd/lpm013m091a.c @@ -0,0 +1,611 @@ +/**************************************************************************** + * drivers/lcd/lpm013m091a.c + * + * Driver for LPM013M091A LCD based on ili9341.c. + * + * Copyright (C) 2014 Marco Krahl. All rights reserved. + * Author: Marco Krahl + * + * Copyright 2018 Sony Semiconductor Solutions Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Display resolution */ + +#define LPM013M091A_XRES 320 +#define LPM013M091A_YRES 300 + +/* TODO: Stride should be configurable by LCD orientation */ + +#define LPM013M091A_STRIDE LPM013M091A_XRES + +/* Dolor depth and format */ + +#define LPM013M091A_BPP 16 +#define LPM013M091A_COLORFMT FB_FMT_RGB16_565 + +/**************************************************************************** + * Private types + ****************************************************************************/ + +struct lpm013m091a_dev_s +{ + /* Publically visible device structure */ + + struct lcd_dev_s dev; + + /* Private lcd-specific information follows */ + + struct lpm013m091a_lcd_s* lcd; + + uint8_t power; /* Current power setting */ +}; + +/**************************************************************************** + * Private Function Protototypes + ****************************************************************************/ + +static void lpm013m091a_selectarea(FAR struct lpm013m091a_lcd_s *lcd, + uint16_t x0, int16_t y0, + uint16_t x1, int16_t y1); +static int lpm013m091a_hwinitialize(FAR struct lpm013m091a_dev_s *dev); + +/* lcd data transfer methods */ + +static int lpm013m091a_putrun(fb_coord_t row, fb_coord_t col, + FAR const uint8_t *buffer, size_t npixels); +#ifndef CONFIG_LCD_NOGETRUN +static int lpm013m091a_getrun(fb_coord_t row, fb_coord_t col, + FAR uint8_t *buffer, + size_t npixels); +#endif + +/* lcd configuration */ + +static int lpm013m091a_getvideoinfo(FAR struct lcd_dev_s *dev, + FAR struct fb_videoinfo_s *vinfo); +static int lpm013m091a_getplaneinfo(FAR struct lcd_dev_s *dev, + unsigned int planeno, + FAR struct lcd_planeinfo_s *pinfo); + +/* lcd specific controls */ + +static int lpm013m091a_getpower(FAR struct lcd_dev_s *dev); +static int lpm013m091a_setpower(FAR struct lcd_dev_s *dev, int power); +static int lpm013m091a_getcontrast(FAR struct lcd_dev_s *dev); +static int lpm013m091a_setcontrast(FAR struct lcd_dev_s *dev, + unsigned int contrast); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static uint16_t g_runbuffer[LPM013M091A_STRIDE]; + +/* This structure describes the overall lcd video controller */ + +static const struct fb_videoinfo_s g_videoinfo = +{ + .fmt = LPM013M091A_COLORFMT, /* Color format: rgb16-565: rrrr rggg gggb bbbb */ + .xres = LPM013M091A_XRES, /* Horizontal resolution in pixel columns */ + .yres = LPM013M091A_YRES, /* Vertical resolution in pixel rows */ + .nplanes = 1, /* Number of color planes supported */ +}; + +/* This is the standard, nuttx plane information object */ + +static const struct lcd_planeinfo_s g_planeinfo = +{ + .putrun = lpm013m091a_putrun, /* Put a run into lcd memory */ +#ifndef CONFIG_LCD_NOGETRUN + .getrun = lpm013m091a_getrun, /* Get a run from lcd memory */ +#endif + .buffer = (uint8_t *) g_runbuffer, /* Run scratch buffer */ + .bpp = LPM013M091A_BPP, /* Bits-per-pixel */ +}; + +static struct lpm013m091a_dev_s g_lpm013m091a_dev = +{ + .dev = + { + /* lcd configuration */ + + .getvideoinfo = lpm013m091a_getvideoinfo, + .getplaneinfo = lpm013m091a_getplaneinfo, + + /* lcd specific controls */ + + .getpower = lpm013m091a_getpower, + .setpower = lpm013m091a_setpower, + .getcontrast = lpm013m091a_getcontrast, + .setcontrast = lpm013m091a_setcontrast, + }, + .lcd = 0, +}; + +/**************************************************************************** + * Name: lpm013m091a_selectarea + * + * Description: + * Select the active area for displaying pixel + * + * Parameter: + * lcd - Reference to private driver structure + * x0 - Start x position + * y0 - Start y position + * x1 - End x position + * y1 - End y position + * + ****************************************************************************/ + +static void lpm013m091a_selectarea(FAR struct lpm013m091a_lcd_s *lcd, + uint16_t x0, int16_t y0, + uint16_t x1, int16_t y1) +{ + lcd->sendcmd(lcd, LPM013M091A_CASET); + lcd->sendparam(lcd, x0 >> 8); + lcd->sendparam(lcd, x0 & 0xff); + lcd->sendparam(lcd, x1 >> 8); + lcd->sendparam(lcd, x1 & 0xff); + + lcd->sendcmd(lcd, LPM013M091A_PASET); + lcd->sendparam(lcd, y0 >> 8); + lcd->sendparam(lcd, y0 & 0xff); + lcd->sendparam(lcd, y1 >> 8); + lcd->sendparam(lcd, y1 & 0xff); +} + +/**************************************************************************** + * Name: lpm013m091a_hwinitialize + * + * Description: + * Initialize and configure the LPM013M091A LCD driver hardware. + * + * Parameter: + * dev - A reference to the driver specific structure + * + * Returned Value: + * + * On success - OK + * On error - EINVAL + * + ****************************************************************************/ + +static int lpm013m091a_hwinitialize(FAR struct lpm013m091a_dev_s *dev) +{ + FAR struct lpm013m091a_lcd_s *lcd = dev->lcd; + + /* soft reset */ + + lcd->sendcmd(lcd, LPM013M091A_SWRESET); + up_mdelay(10); + + /* Analog mode */ + + lcd->sendcmd(lcd, 0xb3); + lcd->sendparam(lcd, 0x02); + + /* Set Display Mode */ + + lcd->sendcmd(lcd, 0xbb); + lcd->sendparam(lcd, 0x10); + + /* SPI GRAM access enable */ + + lcd->sendcmd(lcd, 0xf3); + lcd->sendparam(lcd, 0x02); + + /* Bright Level Max */ + + lcd->sendcmd(lcd, 0x51); + lcd->sendparam(lcd, 0xff); + + /* Backlight ON */ + + lcd->sendcmd(lcd, 0x53); + lcd->sendparam(lcd, 0x24); + + /* Frame rate 60Hz */ + + lcd->sendcmd(lcd, 0xff); + lcd->sendparam(lcd, 0x24); + lcd->sendcmd(lcd, 0xd8); + lcd->sendparam(lcd, 0x41); + lcd->sendcmd(lcd, 0xd9); + lcd->sendparam(lcd, 0x1e); + + lcd->sendcmd(lcd, 0xff); + lcd->sendparam(lcd, 0x10); + + /* Set the color format (18bit:0x06, 16bit:0x05) */ + + lcd->sendcmd(lcd, LPM013M091A_PIXFMT); + lcd->sendparam(lcd, 0x05); + + /* Sleep out */ + + lcd->sendcmd(lcd, LPM013M091A_SLPOUT); + up_mdelay(10); + + /* Display on */ + + lcd->sendcmd(lcd, LPM013M091A_DISPON); + up_mdelay(120); + + return OK; +} + +/**************************************************************************** + * Name: lpm013m091a_putrun + * + * Description: + * Write a partial raster line to the LCD. + * + * Parameters: + * devno - Number of lcd device + * row - Starting row to write to (range: 0 <= row < yres) + * col - Starting column to write to (range: 0 <= col <= xres-npixels) + * buffer - The buffer containing the run to be writen to the LCD + * npixels - The number of pixels to write to the + * (range: 0 < npixels <= xres-col) + * + * Returned Value: + * + * On success - OK + * On error - -EINVAL + * + ****************************************************************************/ + +static int lpm013m091a_putrun(fb_coord_t row, fb_coord_t col, + FAR const uint8_t *buffer, size_t npixels) +{ + FAR struct lpm013m091a_dev_s *dev = (FAR struct lpm013m091a_dev_s *) + &g_lpm013m091a_dev; + FAR struct lpm013m091a_lcd_s *lcd = dev->lcd; + FAR const uint16_t *src = (FAR const uint16_t *)buffer; + + DEBUGASSERT(buffer && ((uintptr_t)buffer & 1) == 0); + + /* Check if position outside of area */ + + if (col + npixels > LPM013M091A_XRES || row > LPM013M091A_YRES) + { + return -EINVAL; + } + + /* Select lcd driver */ + + lcd->select(lcd); + + /* Select column and area similar to the partial raster line */ + + lpm013m091a_selectarea(lcd, col, row, col + npixels - 1, row); + + /* Send memory write cmd */ + + lcd->sendcmd(lcd, LPM013M091A_RAMWR); + + /* Send pixel to gram */ + + lcd->sendgram(lcd, src, npixels); + + /* Deselect the lcd driver */ + + lcd->deselect(lcd); + + return OK; +} + +/**************************************************************************** + * Name: lpm013m091a_getrun + * + * Description: + * Read a partial raster line from the LCD. + * + * Parameter: + * devno - Number of the lcd device + * row - Starting row to read from (range: 0 <= row < yres) + * col - Starting column to read read (range: 0 <= col <= xres-npixels) + * buffer - The buffer in which to return the run read from the LCD + * npixels - The number of pixels to read from the LCD + * (range: 0 < npixels <= xres-col) + * + * Returned Value: + * + * On success - OK + * On error - -EINVAL + * + ****************************************************************************/ + +#ifndef CONFIG_LCD_NOGETRUN +int lpm013m091a_getrun(fb_coord_t row, fb_coord_t col, FAR uint8_t * buffer, + size_t npixels) +{ + lcderr("getrun is not supported for now.\n"); + return -ENOSYS; +} +#endif + +/**************************************************************************** + * Name: lpm013m091a_getvideoinfo + * + * Description: + * Get information about the LCD video controller configuration. + * + * Parameter: + * dev - A reference to the driver specific structure + * vinfo - A reference to the videoinfo structure + * + * Returned Value: + * + * On success - OK + * On error - -EINVAL + * + ****************************************************************************/ + +static int lpm013m091a_getvideoinfo(FAR struct lcd_dev_s *dev, + FAR struct fb_videoinfo_s *vinfo) +{ + if (dev && vinfo) + { + memcpy(vinfo, &g_videoinfo, sizeof(struct fb_videoinfo_s)); + + lcdinfo("fmt: %d xres: %d yres: %d nplanes: %d\n", + vinfo->fmt, vinfo->xres, vinfo->yres, vinfo->nplanes); + + return OK; + } + + return -EINVAL; +} + +/**************************************************************************** + * Name: lpm013m091a_getplaneinfo + * + * Description: + * Get information about the configuration of each LCD color plane. + * + * Parameter: + * dev - A reference to the driver specific structure + * planeno - The plane number + * pinfo - A reference to the planeinfo structure + * + * Returned Value: + * + * On success - OK + * On error - -EINVAL + * + ****************************************************************************/ + +static int lpm013m091a_getplaneinfo(FAR struct lcd_dev_s *dev, + unsigned int planeno, + FAR struct lcd_planeinfo_s *pinfo) +{ + if (dev && pinfo && planeno == 0) + { + memcpy(pinfo, &g_planeinfo, sizeof(struct lcd_planeinfo_s)); + + lcdinfo("planeno: %d bpp: %d\n", planeno, pinfo->bpp); + + return OK; + } + + return -EINVAL; +} + +/**************************************************************************** + * Name: lpm013m091a_getpower + * + * Description: + * Get the LCD panel power status + * 0: full off - CONFIG_LCD_MAXPOWER: full on. + * On backlit LCDs, this setting may correspond to the backlight setting. + * + * Parameter: + * dev - A reference to the driver specific structure + * + * Returned Value: + * + * On success - OK + * On error - -EINVAL + * + ****************************************************************************/ + +static int lpm013m091a_getpower(FAR struct lcd_dev_s *dev) +{ + FAR struct lpm013m091a_dev_s *priv = (FAR struct lpm013m091a_dev_s *)dev; + + lcdinfo("%d\n", priv->power); + return priv->power; +} + +/**************************************************************************** + * Name: lpm013m091a_setpower + * + * Description: + * Enable/disable LCD panel power + * (0: full off - CONFIG_LCD_MAXPOWER: full on). + * On backlight LCDs, this setting may correspond to the backlight setting. + * + * Parameter: + * dev - A reference to the driver specific structure + * power - Value of the power + * + * Returned Value: + * + * On success - OK + * On error - -EINVAL + * + ****************************************************************************/ + +static int lpm013m091a_setpower(FAR struct lcd_dev_s *dev, int power) +{ + FAR struct lpm013m091a_dev_s *priv = (FAR struct lpm013m091a_dev_s *)dev; + FAR struct lpm013m091a_lcd_s *lcd = priv->lcd; + + if (!dev) + { + return -EINVAL; + } + + lcdinfo("%d\n", power); + + lcd->select(lcd); + + if (power > 0) + { + lcd->backlight(lcd, power); + + lcd->sendcmd(lcd, LPM013M091A_DISPON); + up_mdelay(120); + } + else + { + lcd->sendcmd(lcd, LPM013M091A_DISPOFF); + } + + lcd->deselect(lcd); + + priv->power = power; + + return OK; +} + +/**************************************************************************** + * Name: ili9340_getcontrast + * + * Description: + * Get the current contrast setting (0-CONFIG_LCD_MAXCONTRAST). + * + * Parameter: + * dev - A reference to the lcd driver structure + * + * Returned Value: + * + * On success - current contrast value + * On error - -ENOSYS, not supported by the ili9340. + * + ****************************************************************************/ + +static int lpm013m091a_getcontrast(FAR struct lcd_dev_s *dev) +{ + lcdinfo("Not implemented\n"); + return -ENOSYS; +} + +/**************************************************************************** + * Name: ili9340_setcontrast + * + * Description: + * Set LCD panel contrast (0-CONFIG_LCD_MAXCONTRAST). + * + * Parameter: + * dev - A reference to the lcd driver structure + * + * Returned Value: + * + * On success - OK + * On error - -ENOSYS, not supported by the ili9340. + * + ****************************************************************************/ + +static int lpm013m091a_setcontrast(FAR struct lcd_dev_s *dev, + unsigned int contrast) +{ + lcdinfo("Not implemented\n"); + return -ENOSYS; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Initialize LCD + ****************************************************************************/ + +FAR struct lcd_dev_s* lpm013m091a_initialize(FAR struct lpm013m091a_lcd_s *lcd, + int devno) +{ + FAR struct lpm013m091a_dev_s *priv = &g_lpm013m091a_dev; + + if (lcd && devno == 0) + { + if (!priv->lcd) + { + FAR struct lcd_dev_s *dev = &priv->dev; + int ret; + + /* Initialize internal structure */ + + dev->getvideoinfo = lpm013m091a_getvideoinfo; + dev->getplaneinfo = lpm013m091a_getplaneinfo; + dev->getpower = lpm013m091a_getpower; + dev->setpower = lpm013m091a_setpower; + dev->getcontrast = lpm013m091a_getcontrast; + dev->setcontrast = lpm013m091a_setcontrast; + priv->lcd = lcd; + + /* Initialze the LCD driver */ + + ret = lpm013m091a_hwinitialize(priv); + + if (ret == OK) + { + return &priv->dev; + } + + errno = EINVAL; + } + } + + return NULL; +} diff --git a/include/nuttx/lcd/ili9340.h b/include/nuttx/lcd/ili9340.h new file mode 100644 index 0000000000..3a585db6a7 --- /dev/null +++ b/include/nuttx/lcd/ili9340.h @@ -0,0 +1,316 @@ +/**************************************************************************** + * include/nuttx/lcd/ili9340.h + * + * Copyright (C) 2014 Gregory Nutt. All rights reserved. + * Authors: Gregory Nutt + * Marco Krahl + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __INCLUDE_NUTTX_LCD_ILI9340_H +#define __INCLUDE_NUTTX_LCD_ILI9340_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* ILI9340 ID code */ + +#define ILI9340_DEVICE_CODE 0x9340 + +/* ILI9340 LCD Register Addresses *******************************************/ + +/* Level 1 commands */ + +#define ILI9340_NOP 0x00 /* Nop operation */ +#define ILI9340_SOFTWARE_RESET 0x01 /* Software reset */ +#define ILI9340_READ_DISP_ID 0x04 /* Read Display Identification information */ +#define ILI9340_READ_DISP_STATUS 0x09 /* Read display status*/ +#define ILI9340_READ_DISP_POWER_MODE 0x0a /* Read display power mode */ +#define ILI9340_READ_DISP_MADCTRL 0x0b /* Read display MADCTL */ +#define ILI9340_READ_DISP_PIXEL_FORMAT 0x0c /* Read display pixel forma */ +#define ILI9340_READ_DISP_IMAGE_FORMAT 0x0d /* Read display image format */ +#define ILI9340_READ_DISP_SIGNAL_MODE 0x0e /* Read display signal mode */ +#define ILI9340_READ_DISP_SELF_DIAGNOSTIC 0x0f /* Read display self-diagnostic result */ +#define ILI9340_ENTER_SLEEP_MODE 0x10 /* Enter sleep mode */ +#define ILI9340_SLEEP_OUT 0x11 /* Sleep out */ +#define ILI9340_PARTIAL_MODE_ON 0x12 /* Partial mode on */ +#define ILI9340_NORMAL_DISP_MODE_ON 0x13 /* Normal display mode on */ +#define ILI9340_DISP_INVERSION_OFF 0x20 /* Display inversion off */ +#define ILI9340_DISP_INVERSION_ON 0x21 /* Display inversion on */ +#define ILI9340_GAMMA_SET 0x26 /* Gamma set */ +#define ILI9340_DISPLAY_OFF 0x28 /* Display off */ +#define ILI9340_DISPLAY_ON 0x29 /* Display on */ +#define ILI9340_COLUMN_ADDRESS_SET 0x2a /* Column address set */ +#define ILI9340_PAGE_ADDRESS_SET 0x2b /* Page address set */ +#define ILI9340_MEMORY_WRITE 0x2c /* Memory write */ +#define ILI9340_COLOR_SET 0x2d /* Color set */ +#define ILI9340_MEMORY_READ 0x2e /* Memory read */ +#define ILI9340_PARTIAL_AREA 0x30 /* Partial area */ +#define ILI9340_VERT_SCROLL_DEFINITION 0x33 /* Vertical scrolling definition */ +#define ILI9340_TEARING_EFFECT_LINE_OFF 0x34 /* Tearing effect line off */ +#define ILI9340_TEARING_EFFECT_LINE_ON 0x35 /* Tearing effect line on */ +#define ILI9340_MEMORY_ACCESS_CONTROL 0x36 /* Memory Access control */ +#define ILI9340_VERT_SCROLL_START_ADDRESS 0x37 /* Vertical scrolling start address */ +#define ILI9340_IDLE_MODE_OFF 0x38 /* Idle mode off */ +#define ILI9340_IDLE_MODE_ON 0x39 /* Idle mode on */ +#define ILI9340_PIXEL_FORMAT_SET 0x3a /* Pixel Format set */ +#define ILI9340_WRITE_MEMORY_CONTINUE 0x3c /* Write memory continue */ +#define ILI9340_READ_MEMORY_CONTINUE 0x3e /* Read memory continue */ +#define ILI9340_SET_TEAR_SCANLINE 0x44 /* Set tear scanline */ +#define ILI9340_GET_SCANLINE 0x45 /* Get scanline */ +#define ILI9340_WRITE_DISPLAY_BRIGHTNESS 0x51 /* Write display brightness */ +#define ILI9340_READ_DISPLAY_BRIGHTNESS 0x52 /* Read display brightness */ +#define ILI9340_WRITE_CTRL_DISPLAY 0x53 /* Write control display */ +#define ILI9340_READ_CTRL_DISPLAY 0x54 /* Read control display */ +#define ILI9340_WRITE_CONTENT_ADAPT_BRIGHTNESS 0x55 /* write content adaptive brightness control */ +#define ILI9340_READ_CONTENT_ADAPT_BRIGHTNESS 0x56 /* Read content adaptive brightness control */ +#define ILI9340_WRITE_MIN_CAB_LEVEL 0x5e /* Write CABC minimum brightness */ +#define ILI9340_READ_MIN_CAB_LEVEL 0x5f /* Read CABC minimum brightness */ +#define ILI9340_READ_ID1 0xda /* Read ID1 */ +#define ILI9340_READ_ID2 0xdb /* Read ID2 */ +#define ILI9340_READ_ID3 0xdc /* Read ID3 */ + +/* Level 2 Commands */ + +#define ILI9340_RGB_SIGNAL_CONTROL 0xb0 /* RGB interface signal control */ +#define ILI9340_FRAME_RATE_CONTROL_NORMAL 0xb1 /* Frame control */ +#define ILI9340_FRAME_RATE_CONTROL_IDLE_8COLOR 0xb2 /* Frame control in idle mode */ +#define ILI9340_FRAME_RATE_CONTROL_PARTIAL 0xb3 /* Frame control in partial mode */ +#define ILI9340_DISPLAY_INVERSION_CONTROL 0xb4 /* Display inversion control */ +#define ILI9340_BLANKING_PORCH_CONTROL 0xb5 /* Blanking porch control */ +#define ILI9340_DISPLAY_FUNCTION_CTL 0xb6 /* Display function control */ +#define ILI9340_ENTRY_MODE_SET 0xb7 /* Entry mode set */ +#define ILI9340_BACKLIGHT_CONTROL_1 0xb8 /* Backlight control1 */ +#define ILI9340_BACKLIGHT_CONTROL_2 0xb9 /* Backlight control2 */ +#define ILI9340_BACKLIGHT_CONTROL_3 0xba /* Backlight control3 */ +#define ILI9340_BACKLIGHT_CONTROL_4 0xbb /* Backlight control 4 */ +#define ILI9340_BACKLIGHT_CONTROL_5 0xbc /* Backlight control 5 */ +#define ILI9340_BACKLIGHT_CONTROL_7 0xbe /* Backlight control 7 */ +#define ILI9340_BACKLIGHT_CONTROL_8 0xbf /* Backlight control 8 */ +#define ILI9340_POWER_CONTROL_1 0xc0 /* Power control 1 */ +#define ILI9340_POWER_CONTROL_2 0xc1 /* Power control 2 */ +#define ILI9340_VCOM_CONTROL_1 0xc5 /* VCOM control 1 */ +#define ILI9340_VCOM_CONTROL_2 0xc7 /* VCOM control 2 */ +#define ILI9340_POWER_CONTROL_A 0xcb /* Power control A */ +#define ILI9340_POWER_CONTROL_B 0xcf /* Power control B */ +#define ILI9340_NVMEM_WRITE 0xd0 /* NV memory write */ +#define ILI9340_NVMEM_PROTECTION_KEY 0xd1 /* NV memory protection key */ +#define ILI9340_NVMEM_STATUS_READ 0xd2 /* NV memory status read */ +#define ILI9340_READ_ID4 0xd3 /* Read ID4 */ +#define ILI9340_POSITIVE_GAMMA_CORRECTION 0xe0 /* Positive gamma correction */ +#define ILI9340_NEGATIVE_GAMMA_CORRECTION 0xe1 /* Negative gamma correction */ +#define ILI9340_DIGITAL_GAMMA_CONTROL_1 0xe2 /* Digital gamma control 1 */ +#define ILI9340_DIGITAL_GAMMA_CONTROL_2 0xe3 /* Digital gamma control 2 */ +#define ILI9340_DRIVER_TIMING_CTL_A 0xe8 /* Driver timing control A */ +#define ILI9340_DRIVER_TIMING_CTL_B 0xea /* Driver timing control B */ +#define ILI9340_POWER_ON_SEQUENCE_CONTROL 0xed /* Power-on sequence control */ +#define ILI9340_ENABLE_3_GAMMA_CONTROL 0xf2 /* Enable 3g gamma control */ +#define ILI9340_INTERFACE_CONTROL 0xf6 /* Interface control */ +#define ILI9340_PUMP_RATIO_CONTROL 0xf7 /* Pump ration control */ + +/* ILI9340 LCD Register Bit Definitions *************************************/ + +/* Pixel format set */ + +#define ILI9340_PIXEL_FORMAT_SET_DPI_SHIFT (4) +#define ILI9340_PIXEL_FORMAT_SET_DPI_MASK (7 << ILI9340_PIXEL_FORMAT_SET_DPI_SHIFT) +#define ILI9340_PIXEL_FORMAT_SET_DPI(n) ((n) << ILI9340_PIXEL_FORMAT_SET_DPI_SHIFT) +#define ILI9340_PIXEL_FORMAT_SET_DBI_SHIFT (0) +#define ILI9340_PIXEL_FORMAT_SET_DBI_MASK (7 << ILI9340_PIXEL_FORMAT_SET_DBI_SHIFT) +#define ILI9340_PIXEL_FORMAT_SET_DBI(n) ((n) << ILI9340_PIXEL_FORMAT_SET_DBI_SHIFT) + +/* Memory Access control */ + +#define ILI9340_MEMORY_ACCESS_CONTROL_MH (1 << 2) /* Horizontal refresh order */ +#define ILI9340_MEMORY_ACCESS_CONTROL_BGR (1 << 3) /* RGB/BGR order */ +#define ILI9340_MEMORY_ACCESS_CONTROL_ML (1 << 4) /* Vertical refresh order */ +#define ILI9340_MEMORY_ACCESS_CONTROL_MV (1 << 5) /* Row/column exchange */ +#define ILI9340_MEMORY_ACCESS_CONTROL_MX (1 << 6) /* Column address order */ +#define ILI9340_MEMORY_ACCESS_CONTROL_MY (1 << 7) /* Row address order */ + +/* Display function control */ + +#define ILI9340_DISP_FUNC_CTL_ISC_SHIFT (0) +#define ILI9340_DISP_FUNC_CTL_ISC_MASK (15 << ILI9340_DISP_FUNC_CTL_ISC_SHIFT) +# define ILI9340_DISP_FUNC_CTL_ISC(n) ((n) << ILI9340_DISP_FUNC_CTL_ISC_SHIFT) +#define ILI9340_DISP_FUNC_CTL_SM (1 << 4) +#define ILI9340_DISP_FUNC_CTL_SS (1 << 5) +#define ILI9340_DISP_FUNC_CTL_GS (1 << 6) +#define ILI9340_DISP_FUNC_CTL_REV (1 << 7) + +/* Interface function control */ + +#define ILI9340_INTERFACE_CONTROL_WEMODE (1) +#define ILI9340_INTERFACE_CONTROL_BGREOR (1 << 3) +#define ILI9340_INTERFACE_CONTROL_MVEOR (1 << 5) +#define ILI9340_INTERFACE_CONTROL_MXEOR (1 << 6) +#define ILI9340_INTERFACE_CONTROL_MYEOR (1 << 7) + +#define ILI9340_INTERFACE_CONTROL_MDT_SHIFT (0) +#define ILI9340_INTERFACE_CONTROL_MDT_MASK (3 << ILI9340_INTERFACE_CONTROL_MDT_SHIFT) +#define ILI9340_INTERFACE_CONTROL_MDT(n) ((n) << ILI9340_INTERFACE_CONTROL_MDT_SHIFT) +#define ILI9340_INTERFACE_CONTROL_EPF_SHIFT (4) +#define ILI9340_INTERFACE_CONTROL_EPF_MASK (3 << ILI9340_INTERFACE_CONTROL_EPF_SHIFT) +#define ILI9340_INTERFACE_CONTROL_EPF(n) ((n) << ILI9340_INTERFACE_CONTROL_EPF_SHIFT) + +#define ILI9340_INTERFACE_CONTROL_RIM (1) +#define ILI9340_INTERFACE_CONTROL_RM (1 << 1) +#define ILI9340_INTERFACE_CONTROL_DM_SHIFT (4) +#define ILI9340_INTERFACE_CONTROL_DM_MASK (2 << ILI9340_INTERFACE_CONTROL_DM_SHIFT) +#define ILI9340_INTERFACE_CONTROL_DM(n) ((n) << ILI9340_INTERFACE_CONTROL_DM_SHIFT) +#define ILI9340_INTERFACE_CONTROL_ENDIAN (1 << 5) + +/* Interface Mode control */ + +#define ILI9340_INTERFACE_CONTROL_EPL (1) +#define ILI9340_INTERFACE_CONTROL_DPL (1 << 1) +#define ILI9340_INTERFACE_CONTROL_HSPL (1 << 2) +#define ILI9340_INTERFACE_CONTROL_VSPL (1 << 3) +#define ILI9340_INTERFACE_CONTROL_RCM_SHIFT (5) +#define ILI9340_INTERFACE_CONTROL_RCM_MASK (2 << ILI9340_INTERFACE_CONTROL_RCM_SHIFT) +#define ILI9340_INTERFACE_CONTROL_RCM(n) ((n) << ILI9340_INTERFACE_CONTROL_RCM_SHIFT) +#define ILI9340_INTERFACE_CONTROL_BPASS (1 << 7) + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +struct ili9340_lcd_s +{ + /* Interface to control the ILI9340 lcd driver + * + * - select Select the device (as neccessary) before performing any + * operations. + * - deselect Deselect the device (as necessary). + * - sendcmd Send specific command to the LCD driver. + * - sendparam Send specific parameter to the LCD driver. + * - recvparam Receive specific parameter from the LCD driver. + * - sendgram Send pixel data to the LCD drivers gram. + * - recvgram Receive pixel data from the LCD drivers gram. + * - backlight Change the backlight level of the connected display. + * In the context of the ili9340 that means change the + * backlight level of the connected LED driver. + * The implementation in detail is part of the platform + * specific sub driver. + * + */ + + void (*select)(FAR struct ili9340_lcd_s *lcd); + void (*deselect)(FAR struct ili9340_lcd_s *lcd); + int (*sendcmd)(FAR struct ili9340_lcd_s *lcd, const uint8_t cmd); + int (*sendparam)(FAR struct ili9340_lcd_s *lcd, const uint8_t param); + int (*recvparam)(FAR struct ili9340_lcd_s *lcd, uint8_t *param); + int (*recvgram)(FAR struct ili9340_lcd_s *lcd, + uint16_t *wd, uint32_t nwords); + int (*sendgram)(FAR struct ili9340_lcd_s *lcd, + const uint16_t *wd, uint32_t nwords); + int (*backlight)(FAR struct ili9340_lcd_s *lcd, int level); + + /* mcu interface specific data following */ +}; + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: ili9340_initialize + * + * Description: + * Initialize the LCD video driver internal sturcture. Also initialize the + * lcd hardware if not done. The control of the LCD driver is depend on the + * selected MCU interface and part of the platform specific subdriver (see + * config/stm32f429i-disco/src/stm32_ili93404ws.c) + * + * Input Parameters: + * + * lcd - A reference to the platform specific driver instance to control + * the ili9340 display driver. + * devno - A value in the range of 0 through CONFIG_ILI9340_NINTERFACES-1. + * This allows support for multiple LCD devices. + * + * Returned Value: + * + * On success, this function returns a reference to the LCD driver object + * for the specified LCD driver. NULL is returned on any failure. + * + ****************************************************************************/ + +FAR struct lcd_dev_s *ili9340_initialize(FAR struct ili9340_lcd_s *lcd, + int devno); + +/**************************************************************************** + * Name: ili9340_clear + * + * Description: + * This is a non-standard LCD interface. Because of the various rotations, + * clearing the display in the normal way by writing a sequences of runs + * that covers the entire display can be very slow. + * Here the display is cleared by simply setting all GRAM memory to the + * specified color. + * + * Parameter: + * dev - A reference to the lcd driver structure + * color - The background color + * + * Returned Value: + * + * On success - OK + * On error - -EINVAL + * + ****************************************************************************/ + +int ili9340_clear(FAR struct lcd_dev_s *dev, uint16_t color); + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* __INCLUDE_NUTTX_LCD_ILI9340_H */ diff --git a/include/nuttx/lcd/lpm013m091a.h b/include/nuttx/lcd/lpm013m091a.h new file mode 100644 index 0000000000..c680b31249 --- /dev/null +++ b/include/nuttx/lcd/lpm013m091a.h @@ -0,0 +1,138 @@ +/**************************************************************************** + * include/nuttx/lcd/lpm013m091a.h + * + * Copyright 2018 Sony Semiconductor Solutions Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name of Sony Semiconductor Solutions Corporation nor + * the names of its contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __INCLUDE_NUTTX_LCD_LPM013M091A_H +#define __INCLUDE_NUTTX_LCD_LPM013M091A_H + +/* Command set. */ + +#define LPM013M091A_SWRESET 0x01 + +#define LPM013M091A_SLPIN 0x10 +#define LPM013M091A_SLPOUT 0x11 + +#define LPM013M091A_DISPOFF 0x28 +#define LPM013M091A_DISPON 0x29 +#define LPM013M091A_CASET 0x2A +#define LPM013M091A_PASET 0x2B +#define LPM013M091A_RAMWR 0x2C + +#define LPM013M091A_PIXFMT 0x3A + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Response CODE + ****************************************************************************/ + +struct lpm013m091a_lcd_s +{ + /* Interface to control the LPM013M091A lcd driver + * + * - select Select the device (as neccessary) before performing + * any operations. + * - deselect Deselect the device (as necessary). + * - sendcmd Send specific command to the LCD driver. + * - sendparam Send specific parameter to the LCD driver. + * - recvparam Receive specific parameter from the LCD driver. + * - sendgram Send pixel data to the LCD drivers gram. + * - recvgram Receive pixel data from the LCD drivers gram. + * - backlight Change the backlight level of the connected display. + * In the context of the lpm013m091a that means change the + * backlight level of the connected LED driver. + * The implementation in detail is part of the platform + * specific sub driver. + * + */ + + void (*select)(FAR struct lpm013m091a_lcd_s *lcd); + void (*deselect)(FAR struct lpm013m091a_lcd_s *lcd); + int (*sendcmd)(FAR struct lpm013m091a_lcd_s *lcd, const uint8_t cmd); + int (*sendparam)(FAR struct lpm013m091a_lcd_s *lcd, const uint8_t param); + int (*recvparam)(FAR struct lpm013m091a_lcd_s *lcd, uint8_t *param); + int (*recvgram)(FAR struct lpm013m091a_lcd_s *lcd, + uint16_t *wd, uint32_t nwords); + int (*sendgram)(FAR struct lpm013m091a_lcd_s *lcd, + const uint16_t *wd, uint32_t nwords); + int (*backlight)(FAR struct lpm013m091a_lcd_s *lcd, int level); + + /* mcu interface specific data following */ +}; + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: lpm013m091a_initialize + * + * Description: + * Initialize the LCD video driver internal sturcture. Also initialize the + * lcd hardware if not done. The control of the LCD driver is depend on the + * selected MCU interface and part of the platform specific subdriver + * + * + * Input Parameters: + * + * lcd - A reference to the platform specific driver instance to control the + * lpm013m091a display driver. + * devno - This is for compat. must be zero. + * + * Returned Value: + * + * On success, this function returns a reference to the LCD driver object + * for the specified LCD driver. NULL is returned on any failure. + * + ****************************************************************************/ + +FAR struct lcd_dev_s* lpm013m091a_initialize(struct lpm013m091a_lcd_s *lcd, + int devno); + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* __INCLUDE_NUTTX_LCD_LPM013M091A_H */