This is an automated email from the ASF dual-hosted git repository. linguini1 pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/nuttx.git
commit 2bf531b3f4f424b18f846e2b9dbbe179c04e0ae0 Author: Filipe Cavalcanti <[email protected]> AuthorDate: Wed Aug 5 22:32:12 2026 -0300 boards/risc-v: LCD support on esp32p4-tab5 Adds support for st7121 and st7123 variants for LCD support on the esp32p4-tab5 board. Includes power management though IO expander under 'hmi_power' and new board KConfig options. Signed-off-by: Filipe Cavalcanti <[email protected]> --- boards/risc-v/esp32p4/esp32p4-tab5/Kconfig | 67 +++ boards/risc-v/esp32p4/esp32p4-tab5/include/board.h | 38 +- .../risc-v/esp32p4/esp32p4-tab5/src/CMakeLists.txt | 15 +- boards/risc-v/esp32p4/esp32p4-tab5/src/Make.defs | 13 + .../risc-v/esp32p4/esp32p4-tab5/src/esp32p4-tab5.h | 109 +++++ .../esp32p4/esp32p4-tab5/src/esp32p4_bringup.c | 65 ++- .../esp32p4/esp32p4-tab5/src/esp32p4_display.c | 485 +++++++++++++++++++++ .../esp32p4/esp32p4-tab5/src/esp32p4_hmi_power.c | 187 ++++++++ .../esp32p4/esp32p4-tab5/src/esp32p4_lcd_st7121.c | 375 ++++++++++++++++ .../esp32p4/esp32p4-tab5/src/esp32p4_lcd_st7121.h | 75 ++++ .../esp32p4/esp32p4-tab5/src/esp32p4_lcd_st7123.c | 425 ++++++++++++++++++ .../esp32p4/esp32p4-tab5/src/esp32p4_lcd_st7123.h | 74 ++++ .../esp32p4/esp32p4-tab5/src/esp32p4_mipi_dpi.c | 69 +++ 13 files changed, 1990 insertions(+), 7 deletions(-) diff --git a/boards/risc-v/esp32p4/esp32p4-tab5/Kconfig b/boards/risc-v/esp32p4/esp32p4-tab5/Kconfig index ed922979b37..64cbc517d40 100644 --- a/boards/risc-v/esp32p4/esp32p4-tab5/Kconfig +++ b/boards/risc-v/esp32p4/esp32p4-tab5/Kconfig @@ -5,6 +5,10 @@ if ARCH_BOARD_ESP32P4_TAB5 +config ESP32P4_TAB5_HMI_POWER + bool + default n + config ESP32P4_TAB5_IOEXPANDER bool "Enable the Tab5 board IO Expander" default n @@ -31,4 +35,67 @@ if ESP32P4_TAB5_IOEXPANDER Enable the second IO Expander. endif +config ESP32P4_TAB5_LCD_POWER + bool "LCD / MIPI PHY power and reset path" + default n + select ESP32P4_TAB5_IOEXPANDER + select ESP32P4_TAB5_HMI_POWER + ---help--- + At board bring-up (after I2C0 init), enable on-chip LDO channel 3 + at 2500 mV for VDD_MIPI_DPHY and raise LCD_EN on expander pin P4. + + This does NOT initialize the MIPI-DSI host, the LCD panel, or + /dev/fb0 by itself. Enable ESP32P4_TAB5_MIPI_DSI (and + ESPRESSIF_MIPI_DSI) to register the host after this power path. + Enable ESP32P4_TAB5_LCD for panel initialization + /dev/fb0. + +config ESP32P4_TAB5_MIPI_DSI + bool "Register MIPI-DSI host at bring-up" + default n + depends on ESP32P4_TAB5_LCD_POWER && ESPRESSIF_MIPI_DSI + ---help--- + After the LCD power path succeeds, call + esp_mipi_dsi_initialize() so the generic MIPI-DSI host is + registered (LP DCS/generic transfer ready). + + Does NOT run panel initialization or create /dev/fb0 by itself; + enable ESP32P4_TAB5_LCD for that. + +config ESP32P4_TAB5_LCD + bool "LCD panel and /dev/fb0" + default n + depends on ESP32P4_TAB5_MIPI_DSI + select DRIVERS_VIDEO + select VIDEO_FB + select FB_UPDATE + ---help--- + Bring up the selected Tab5 MIPI-DSI panel (M5Stack init table and + 720×1280 RGB565 timings), allocate a PSRAM framebuffer, bind it + to the DSI bridge via DW-GDMA, and register /dev/fb0. + +config ESP32P4_TAB5_LCD_APO_TEST + bool "All-Pixels-On flash after FB bring-up" + default y + depends on ESP32P4_TAB5_LCD + ---help--- + After /dev/fb0 is ready, force All-Pixels-On for ~1 s, then + All-Pixels-Off and restore the solid red test fill. + +choice + prompt "Tab5 LCD panel controller" + default ESP32P4_TAB5_LCD_ST7121 + depends on ESP32P4_TAB5_LCD + +config ESP32P4_TAB5_LCD_ST7121 + bool "ST7121" + ---help--- + Use the ST7121 initialization table and display timings. + +config ESP32P4_TAB5_LCD_ST7123 + bool "ST7123" + ---help--- + Use the ST7123 initialization table and display timings. + +endchoice + endif # ARCH_BOARD_ESP32P4_TAB5 diff --git a/boards/risc-v/esp32p4/esp32p4-tab5/include/board.h b/boards/risc-v/esp32p4/esp32p4-tab5/include/board.h index 7dea43e0b41..07b0b78f387 100644 --- a/boards/risc-v/esp32p4/esp32p4-tab5/include/board.h +++ b/boards/risc-v/esp32p4/esp32p4-tab5/include/board.h @@ -55,18 +55,46 @@ #define BUTTON_BOOT 35 -/* Display - MIPI-DSI ILI9881C (NOT implemented; pins documented only) +/* Display - MIPI-DSI ST7121/ST7123 (M5Stack Tab5 reference timings) * * The DSI data/clock lanes are dedicated MIPI pins (not GPIO-muxed) powered - * by VDD_MIPI_DPHY; only the backlight enable is a GPIO. Panel reset is the - * board power-on reset (BSP_LCD_RST = NC) driven by IO expander 0x43 P4. + * by VDD_MIPI_DPHY (LDO ch3 @ 2500 mV). Backlight enable is GPIO22. + * BSP_LCD_RST is NC; LCD_EN / reset control is PI4IOE5V6408 @0x43 P4. + * + * Enable /dev/fb0 with CONFIG_ESP32P4_TAB5_LCD (see configs/lcd), which + * selects power + MIPI host + VIDEO_FB. Select the matching panel with + * CONFIG_ESP32P4_TAB5_LCD_ST7121 or CONFIG_ESP32P4_TAB5_LCD_ST7123. */ #define TAB5_GPIO_LCD_BL_EN 22 /* Backlight enable -> ME2212 boost EN */ -/* Touch - GT911 (NOT implemented; pins documented only) */ +#define TAB5_MIPI_DSI_H_RES 720 +#define TAB5_MIPI_DSI_V_RES 1280 +#define TAB5_MIPI_DSI_DPI_CLK_MHZ 70 +#define TAB5_MIPI_DSI_HSYNC_PULSE_WIDTH 2 +#define TAB5_MIPI_DSI_HSYNC_BACK_PORCH 40 +#define TAB5_MIPI_DSI_HSYNC_FRONT_PORCH 40 +#define TAB5_MIPI_DSI_LANES 2 + +#ifdef CONFIG_ESP32P4_TAB5_LCD_ST7123 +# define TAB5_LCD_PANEL_NAME "ST7123" +# define TAB5_MIPI_DSI_VSYNC_PULSE_WIDTH 2 +# define TAB5_MIPI_DSI_VSYNC_BACK_PORCH 8 +# define TAB5_MIPI_DSI_VSYNC_FRONT_PORCH 220 +# define TAB5_MIPI_DSI_LANE_BITRATE_MBPS 1000 +#else +# define TAB5_LCD_PANEL_NAME "ST7121" +# define TAB5_MIPI_DSI_VSYNC_PULSE_WIDTH 20 +# define TAB5_MIPI_DSI_VSYNC_BACK_PORCH 24 +# define TAB5_MIPI_DSI_VSYNC_FRONT_PORCH 200 +# define TAB5_MIPI_DSI_LANE_BITRATE_MBPS 965 +#endif + +/* Touch - ST7121/ST7123 TDDI @0x55 (NOT implemented; INT GPIO23). Older + * ILI9881 units used GT911 @0x14 on the same INT pin. + */ -#define TAB5_GPIO_TP_INT 23 /* GT911 touch interrupt */ +#define TAB5_GPIO_TP_INT 23 /* Touch interrupt */ /* Audio - ES8388 codec (out) + ES7210 mic array (in), I2S (pins only) */ diff --git a/boards/risc-v/esp32p4/esp32p4-tab5/src/CMakeLists.txt b/boards/risc-v/esp32p4/esp32p4-tab5/src/CMakeLists.txt index 3ee63748b93..1461f115824 100644 --- a/boards/risc-v/esp32p4/esp32p4-tab5/src/CMakeLists.txt +++ b/boards/risc-v/esp32p4/esp32p4-tab5/src/CMakeLists.txt @@ -24,7 +24,20 @@ set(SRCS esp32p4_boot.c esp32p4_bringup.c) if(CONFIG_ESP32P4_TAB5_IOEXPANDER) list(APPEND SRCS esp32p4_ioexpander.c) -endif +endif() + +if(CONFIG_ESP32P4_TAB5_HMI_POWER) + list(APPEND SRCS esp32p4_hmi_power.c) +endif() + +if(CONFIG_ESP32P4_TAB5_LCD) + list(APPEND SRCS esp32p4_display.c esp32p4_mipi_dpi.c) + if(CONFIG_ESP32P4_TAB5_LCD_ST7121) + list(APPEND SRCS esp32p4_lcd_st7121.c) + elseif(CONFIG_ESP32P4_TAB5_LCD_ST7123) + list(APPEND SRCS esp32p4_lcd_st7123.c) + endif() +endif() if(CONFIG_BOARDCTL) if(CONFIG_BOARDCTL_RESET) diff --git a/boards/risc-v/esp32p4/esp32p4-tab5/src/Make.defs b/boards/risc-v/esp32p4/esp32p4-tab5/src/Make.defs index 7a99aee61fc..46f7f7281fb 100644 --- a/boards/risc-v/esp32p4/esp32p4-tab5/src/Make.defs +++ b/boards/risc-v/esp32p4/esp32p4-tab5/src/Make.defs @@ -28,6 +28,19 @@ ifeq ($(CONFIG_ESP32P4_TAB5_IOEXPANDER),y) CSRCS += esp32p4_ioexpander.c endif +ifeq ($(CONFIG_ESP32P4_TAB5_HMI_POWER),y) + CSRCS += esp32p4_hmi_power.c +endif + +ifeq ($(CONFIG_ESP32P4_TAB5_LCD),y) + CSRCS += esp32p4_display.c esp32p4_mipi_dpi.c + ifeq ($(CONFIG_ESP32P4_TAB5_LCD_ST7121),y) + CSRCS += esp32p4_lcd_st7121.c + else ifeq ($(CONFIG_ESP32P4_TAB5_LCD_ST7123),y) + CSRCS += esp32p4_lcd_st7123.c + endif +endif + ifeq ($(CONFIG_BOARDCTL),y) ifeq ($(CONFIG_BOARDCTL_RESET),y) CSRCS += esp32p4_reset.c diff --git a/boards/risc-v/esp32p4/esp32p4-tab5/src/esp32p4-tab5.h b/boards/risc-v/esp32p4/esp32p4-tab5/src/esp32p4-tab5.h index 8718f84a56f..5c7950cda82 100644 --- a/boards/risc-v/esp32p4/esp32p4-tab5/src/esp32p4-tab5.h +++ b/boards/risc-v/esp32p4/esp32p4-tab5/src/esp32p4-tab5.h @@ -28,6 +28,13 @@ ****************************************************************************/ #include <nuttx/config.h> +#include <nuttx/compiler.h> + +#include <stdbool.h> + +#ifdef CONFIG_ESPRESSIF_MIPI_DSI +# include "espressif/esp_mipi_dsi.h" +#endif /**************************************************************************** * Public Data @@ -56,6 +63,108 @@ int esp_bringup(void); +#ifdef CONFIG_ESP32P4_TAB5_LCD_POWER + +/**************************************************************************** + * Name: tab5_mipi_phy_power + * + * Description: + * Enable or disable LDO channel 3 (VDD_MIPI_DPHY @ 2500 mV). + * + * Input Parameters: + * on - True to enable the LDO channel, false to disable it. + * + * Returned Value: + * Zero on success, -1 on failure. + * + ****************************************************************************/ + +int tab5_mipi_phy_power(bool on); + +/**************************************************************************** + * Name: tab5_lcd_enable + * + * Description: + * Drive PI4IOE P4 (BSP_LCD_EN). true = enable (high). + * + * Input Parameters: + * enable - True to enable the LCD rail, false to disable it. + * + * Returned Value: + * Zero on success, -1 on failure. + * + ****************************************************************************/ + +int tab5_lcd_enable(bool enable); + +/**************************************************************************** + * Name: tab5_lcd_backlight + * + * Description: + * Drive backlight enable GPIO22 (ME2212 boost EN). + * + * Input Parameters: + * on - True to enable the backlight, false to disable it. + * + * Returned Value: + * Zero on success, -1 on failure. + * + ****************************************************************************/ + +int tab5_lcd_backlight(bool on); + +/**************************************************************************** + * Name: tab5_lcd_power_init + * + * Description: + * Power MIPI PHY LDO, init PI4IOE, and enable LCD (P4 high). + * + * Returned Value: + * Zero on success, -1 on failure. + * + ****************************************************************************/ + +int tab5_lcd_power_init(void); + +#endif /* CONFIG_ESP32P4_TAB5_LCD_POWER */ + +#ifdef CONFIG_ESP32P4_TAB5_LCD + +/**************************************************************************** + * Name: tab5_fb_reload_test_pattern + * + * Description: + * Re-fill the plane with the bring-up test color and cache write-back. + * Call after fb_register(): the generic FB driver memset()s the plane + * and would otherwise leave a black DMA buffer. + * + * Returned Value: + * Zero on success, -1 on failure. + * + ****************************************************************************/ + +int tab5_fb_reload_test_pattern(void); + +/**************************************************************************** + * Name: tab5_mipi_dsi_dpi_config + * + * Description: + * Fill DPI timing for the selected Tab5 ST712x panel. Arch + * host has no panel defaults — board code supplies this to + * esp_mipi_dsi_configure_dpi(). + * + * Input Parameters: + * cfg - Pointer to the DPI configuration structure. + * + * Returned Value: + * Zero on success, -1 on failure. + * + ****************************************************************************/ + +void tab5_mipi_dsi_dpi_config(FAR struct esp_mipi_dsi_dpi_config_s *cfg); + +#endif /* CONFIG_ESP32P4_TAB5_LCD */ + #ifdef CONFIG_ESP32P4_TAB5_IOEXPANDER /**************************************************************************** * Name: tab5_pi4ioe_init diff --git a/boards/risc-v/esp32p4/esp32p4-tab5/src/esp32p4_bringup.c b/boards/risc-v/esp32p4/esp32p4-tab5/src/esp32p4_bringup.c index 8de05b13a2d..ebfae61ee92 100644 --- a/boards/risc-v/esp32p4/esp32p4-tab5/src/esp32p4_bringup.c +++ b/boards/risc-v/esp32p4/esp32p4-tab5/src/esp32p4_bringup.c @@ -42,6 +42,14 @@ # include "esp_board_i2c.h" #endif +#ifdef CONFIG_ESP32P4_TAB5_MIPI_DSI +# include "espressif/esp_mipi_dsi.h" +#endif + +#ifdef CONFIG_ESP32P4_TAB5_LCD +# include <nuttx/video/fb.h> +#endif + #include <arch/board/board.h> #include "esp32p4-tab5.h" @@ -103,11 +111,66 @@ int esp_bringup(void) ret = tab5_pi4ioe_init(); if (ret < 0) { - syslog(LOG_ERR, "Failed to initialize Tab5 IO expanders: %d\n", ret); + syslog(LOG_ERR, "ERROR: failed to init IO expanders: %d\n", ret); + return ret; + } +#endif + +#ifdef CONFIG_ESP32P4_TAB5_LCD_POWER + /* MIPI PHY LDO + PI4IOE LCD_EN (before optional DSI host) */ + + ret = tab5_lcd_power_init(); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: failed to init LCD power path: %d\n", ret); return ret; } #endif +#ifdef CONFIG_ESP32P4_TAB5_MIPI_DSI + /* Tab5 ST712x bus: 2 lanes @ board.h bitrate. */ + + struct esp_mipi_dsi_bus_config_s bus_cfg = + { + .num_data_lanes = TAB5_MIPI_DSI_LANES, + .lane_bit_rate_mbps = TAB5_MIPI_DSI_LANE_BITRATE_MBPS, + }; + + ret = esp_mipi_dsi_initialize(&bus_cfg); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: failed to init MIPI-DSI host: %d\n", + ret); + return ret; + } + + syslog(LOG_INFO, "Tab5: MIPI-DSI host registered\n"); +#endif + +#ifdef CONFIG_ESP32P4_TAB5_LCD + /* Selected panel DCS + DPI + DW-GDMA FB → /dev/fb0 */ + + ret = fb_register(0, 0); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: failed to register /dev/fb0: %d\n", ret); + } + else + { + /* fb_register() clears the plane; restore test red for DMA. */ + + ret = tab5_fb_reload_test_pattern(); + if (ret < 0) + { + syslog(LOG_ERR, + "ERROR: failed to reload FB test pattern: %d\n", ret); + } + + syslog(LOG_INFO, "/dev/fb0 registered (%s)\n", + TAB5_LCD_PANEL_NAME); + } +#endif + #ifdef CONFIG_FS_TMPFS /* Mount the tmpfs file system */ diff --git a/boards/risc-v/esp32p4/esp32p4-tab5/src/esp32p4_display.c b/boards/risc-v/esp32p4/esp32p4-tab5/src/esp32p4_display.c new file mode 100644 index 00000000000..7225b722d06 --- /dev/null +++ b/boards/risc-v/esp32p4/esp32p4-tab5/src/esp32p4_display.c @@ -0,0 +1,485 @@ +/**************************************************************************** + * boards/risc-v/esp32p4/esp32p4-tab5/src/esp32p4_display.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/* Tab5 display / framebuffer glue (PinePhone-style up_fbinitialize split). + * + * Sequence (ESP-IDF DPI panel + selected ST712x controller): + * 1. Allocate RGB565 FB (PSRAM) + * 2. Host already registered by bringup + * 3. configure_dpi -> panel DCS -> bind FB -> video_start -> display_on + * 4. Backlight on + * 5. Optional All-Pixels-On bring-up flash + */ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> + +#include <errno.h> +#include <debug.h> +#include <string.h> +#include <syslog.h> + +#include <nuttx/arch.h> +#include <nuttx/compiler.h> +#include <nuttx/kmalloc.h> +#include <nuttx/video/fb.h> +#include <nuttx/video/mipi_display.h> +#include <nuttx/video/mipi_dsi.h> + +#include <arch/board/board.h> + +#include "espressif/esp_mipi_dsi.h" + +#include "esp32p4-tab5.h" + +#ifdef CONFIG_ESP32P4_TAB5_LCD_ST7123 +# include "esp32p4_lcd_st7123.h" +# define tab5_panel_initialize tab5_st7123_initialize +#else +# include "esp32p4_lcd_st7121.h" +# define tab5_panel_initialize tab5_st7121_initialize +#endif + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define TAB5_FB_BPP 16 +#define TAB5_FB_WIDTH TAB5_MIPI_DSI_H_RES +#define TAB5_FB_HEIGHT TAB5_MIPI_DSI_V_RES +#define TAB5_FB_STRIDE (TAB5_FB_WIDTH * (TAB5_FB_BPP / 8)) +#define TAB5_FB_SIZE (TAB5_FB_STRIDE * TAB5_FB_HEIGHT) + +#define TAB5_FB_TEST_COLOR 0xf800 + +#define TAB5_DCS_ALL_PIXELS_ON 0x23 +#define TAB5_DCS_ALL_PIXELS_OFF 0x22 +#define TAB5_APO_TEST_MS 1000 + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static int tab5_getvideoinfo(FAR struct fb_vtable_s *vtable, + FAR struct fb_videoinfo_s *vinfo); +static int tab5_getplaneinfo(FAR struct fb_vtable_s *vtable, int planeno, + FAR struct fb_planeinfo_s *pinfo); +#ifdef CONFIG_FB_UPDATE +static int tab5_updatearea(FAR struct fb_vtable_s *vtable, + FAR const struct fb_area_s *area); +#endif + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static struct fb_vtable_s g_tab5_vtable = +{ + .getvideoinfo = tab5_getvideoinfo, + .getplaneinfo = tab5_getplaneinfo, +#ifdef CONFIG_FB_UPDATE + .updatearea = tab5_updatearea, +#endif +}; + +static struct fb_videoinfo_s g_tab5_video = +{ + .fmt = FB_FMT_RGB16_565, + .xres = TAB5_FB_WIDTH, + .yres = TAB5_FB_HEIGHT, + .nplanes = 1, +}; + +static struct fb_planeinfo_s g_tab5_plane = +{ + .fbmem = NULL, + .fblen = TAB5_FB_SIZE, + .stride = TAB5_FB_STRIDE, + .display = 0, + .bpp = TAB5_FB_BPP, + .xres_virtual = TAB5_FB_WIDTH, + .yres_virtual = TAB5_FB_HEIGHT, + .xoffset = 0, + .yoffset = 0, +}; + +static FAR uint16_t *g_tab5_fb; +static bool g_tab5_fb_ready; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: tab5_getvideoinfo + * + * Description: + * Return the video information. + * + * Input Parameters: + * vtable - The vtable. + * vinfo - The video information. + * + * Returned Value: + * Zero on success. + * + ****************************************************************************/ + +static int tab5_getvideoinfo(FAR struct fb_vtable_s *vtable, + FAR struct fb_videoinfo_s *vinfo) +{ + DEBUGASSERT(vtable != NULL && vtable == &g_tab5_vtable && vinfo != NULL); + memcpy(vinfo, &g_tab5_video, sizeof(*vinfo)); + return OK; +} + +/**************************************************************************** + * Name: tab5_getplaneinfo + * + * Description: + * Return the plane information. + * + * Input Parameters: + * vtable - The vtable. + * planeno - The plane number. + * pinfo - The plane information. + * + * Returned Value: + * Zero on success, -EINVAL if the plane number is invalid. + * + ****************************************************************************/ + +static int tab5_getplaneinfo(FAR struct fb_vtable_s *vtable, int planeno, + FAR struct fb_planeinfo_s *pinfo) +{ + DEBUGASSERT(vtable != NULL && vtable == &g_tab5_vtable && pinfo != NULL); + + if (planeno != 0 || g_tab5_plane.fbmem == NULL) + { + return -EINVAL; + } + + memcpy(pinfo, &g_tab5_plane, sizeof(*pinfo)); + return OK; +} + +#ifdef CONFIG_FB_UPDATE +/**************************************************************************** + * Name: tab5_updatearea + * + * Description: + * Update a region of the framebuffer. + * + * Input Parameters: + * vtable - The vtable. + * area - The area to update. + * + * Returned Value: + * Zero on success, -EAGAIN if the framebuffer is not ready, + * -EINVAL if the area is out of bounds. + ****************************************************************************/ + +static int tab5_updatearea(FAR struct fb_vtable_s *vtable, + FAR const struct fb_area_s *area) +{ + size_t offset; + size_t len; + + DEBUGASSERT(vtable != NULL && vtable == &g_tab5_vtable); + + if (g_tab5_fb == NULL) + { + return -EAGAIN; + } + + if (area == NULL) + { + return esp_mipi_dsi_flush_framebuffer(g_tab5_fb, TAB5_FB_SIZE); + } + + if (area->y >= TAB5_FB_HEIGHT || area->x >= TAB5_FB_WIDTH) + { + return OK; + } + + offset = (size_t)area->y * TAB5_FB_STRIDE + + (size_t)area->x * (TAB5_FB_BPP / 8); + len = (size_t)area->h * TAB5_FB_STRIDE; + if (offset + len > TAB5_FB_SIZE) + { + len = TAB5_FB_SIZE - offset; + } + + return esp_mipi_dsi_flush_framebuffer((FAR uint8_t *)g_tab5_fb + offset, + len); +} +#endif /* CONFIG_FB_UPDATE */ + +/**************************************************************************** + * Name: tab5_fb_fill + * + * Description: + * Fill the framebuffer with a given color. + * + * Input Parameters: + * color - The color to fill the framebuffer with. + * + * Returned Value: + * None. + * + ****************************************************************************/ + +static void tab5_fb_fill(uint16_t color) +{ + size_t i; + size_t npix = (size_t)TAB5_FB_WIDTH * TAB5_FB_HEIGHT; + int ret; + + for (i = 0; i < npix; i++) + { + g_tab5_fb[i] = color; + } + + ret = esp_mipi_dsi_flush_framebuffer(g_tab5_fb, TAB5_FB_SIZE); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: FB cache C2M sync failed: %d\n", ret); + } +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_fbinitialize + * + * Description: + * Initialize the framebuffer. + * + * Input Parameters: + * display - The display number. + * + * Returned Value: + * Zero on success, -ENODEV on failure. + * + ****************************************************************************/ + +int up_fbinitialize(int display) +{ + FAR struct mipi_dsi_host *host; + FAR struct mipi_dsi_device *device; + struct esp_mipi_dsi_dpi_config_s dpi; + int ret; + + if (display != 0) + { + return -ENODEV; + } + + if (g_tab5_fb_ready) + { + return OK; + } + + g_tab5_fb = kumm_memalign(64, TAB5_FB_SIZE); + if (g_tab5_fb == NULL) + { + syslog(LOG_ERR, + "ERROR: FB alloc failed (%u bytes; enable PSRAM)\n", + (unsigned int)TAB5_FB_SIZE); + return -ENOMEM; + } + + memset(g_tab5_fb, 0, TAB5_FB_SIZE); + g_tab5_plane.fbmem = g_tab5_fb; + + host = esp_mipi_dsi_host_get(); + if (host == NULL) + { + syslog(LOG_ERR, + "ERROR: MIPI-DSI host not ready " + "(enable ESP32P4_TAB5_MIPI_DSI)\n"); + ret = -EAGAIN; + goto errout_fb; + } + + /* IDF order: DPI config before panel DCS; display_on after video_start. */ + + syslog(LOG_INFO, "Configuring DPI...\n"); + tab5_mipi_dsi_dpi_config(&dpi); + ret = esp_mipi_dsi_configure_dpi(&dpi); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: configure_dpi failed: %d\n", ret); + goto errout_fb; + } + + syslog(LOG_INFO, "%s panel init...\n", + TAB5_LCD_PANEL_NAME); + device = tab5_panel_initialize(host); + if (device == NULL) + { + ret = -EIO; + goto errout_fb; + } + + ret = esp_mipi_dsi_bind_framebuffer(g_tab5_fb, TAB5_FB_SIZE, + TAB5_FB_WIDTH, TAB5_FB_HEIGHT, + TAB5_FB_BPP); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: bind_framebuffer failed: %d\n", ret); + goto errout_fb; + } + + tab5_fb_fill(TAB5_FB_TEST_COLOR); + + ret = mipi_dsi_dcs_exit_sleep_mode(device); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: pre-video sleep_out failed: %d\n", + ret); + goto errout_fb; + } + + up_mdelay(120); + + syslog(LOG_INFO, "Starting video...\n"); + ret = esp_mipi_dsi_video_start(); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: video_start failed: %d\n", ret); + goto errout_fb; + } + + ret = mipi_dsi_dcs_set_display_on(device); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: post-video display_on failed: %d\n", + ret); + goto errout_fb; + } + + tab5_fb_fill(TAB5_FB_TEST_COLOR); + + ret = tab5_lcd_backlight(true); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: backlight failed: %d\n", ret); + } + + g_tab5_fb_ready = true; + syslog(LOG_INFO, + "/dev/fb0 ready %ux%u RGB565 @ %p\n", + TAB5_FB_WIDTH, TAB5_FB_HEIGHT, g_tab5_fb); + +#ifdef CONFIG_ESP32P4_TAB5_LCD_APO_TEST + /* White flash proves DCS/BL; then restore normal mode + red FB. */ + + mipi_dsi_dcs_write(device, TAB5_DCS_ALL_PIXELS_ON, NULL, 0); + up_mdelay(TAB5_APO_TEST_MS); + mipi_dsi_dcs_write(device, TAB5_DCS_ALL_PIXELS_OFF, NULL, 0); + mipi_dsi_dcs_write(device, MIPI_DCS_ENTER_NORMAL_MODE, NULL, 0); + mipi_dsi_dcs_set_display_on(device); + tab5_fb_fill(TAB5_FB_TEST_COLOR); +#endif + + return OK; + +errout_fb: + kumm_free(g_tab5_fb); + g_tab5_fb = NULL; + g_tab5_plane.fbmem = NULL; + return ret; +} + +/**************************************************************************** + * Name: up_fbgetvplane + * + * Description: + * Return the framebuffer vtable. + * + * Input Parameters: + * display - The display number. + * vplane - The vplane number. + * + * Returned Value: + * Pointer to the vtable on success, NULL on failure. + * + ****************************************************************************/ + +FAR struct fb_vtable_s *up_fbgetvplane(int display, int vplane) +{ + if (display != 0 || vplane != 0 || !g_tab5_fb_ready) + { + return NULL; + } + + return &g_tab5_vtable; +} + +/**************************************************************************** + * Name: up_fbuninitialize + * + * Description: + * Uninitialize the framebuffer. + * + * Input Parameters: + * display - The display number. + * + * Returned Value: + * None. + * + ****************************************************************************/ + +void up_fbuninitialize(int display) +{ + UNUSED(display); +} + +/**************************************************************************** + * Name: tab5_fb_reload_test_pattern + * + * Description: + * Call after fb_register(): the generic FB driver memset()s the + * framebuffer and would otherwise leave a black DMA buffer. + * This sets the framebuffer to the test color (red). + * + * Returned Value: + * Zero on success, -EAGAIN on failure. + * + ****************************************************************************/ + +int tab5_fb_reload_test_pattern(void) +{ + if (!g_tab5_fb_ready || g_tab5_fb == NULL) + { + return -EAGAIN; + } + + tab5_fb_fill(TAB5_FB_TEST_COLOR); + return OK; +} diff --git a/boards/risc-v/esp32p4/esp32p4-tab5/src/esp32p4_hmi_power.c b/boards/risc-v/esp32p4/esp32p4-tab5/src/esp32p4_hmi_power.c new file mode 100644 index 00000000000..267a3a16976 --- /dev/null +++ b/boards/risc-v/esp32p4/esp32p4-tab5/src/esp32p4_hmi_power.c @@ -0,0 +1,187 @@ +/**************************************************************************** + * boards/risc-v/esp32p4/esp32p4-tab5/src/esp32p4_hmi_power.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> + +#include <stdbool.h> +#include <stdint.h> +#include <syslog.h> + +#include <errno.h> +#include <nuttx/sched.h> + +#include "espressif/esp_ldo.h" +#include "espressif/esp_gpio.h" + +#include "esp32p4-tab5.h" +#include <arch/board/board.h> + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* MIPI PHY LDO channel and voltage */ + +#define ESP_LDO_MIPI_PHY_CHAN 3 +#define ESP_LDO_MIPI_PHY_VOLTAGE_MV 2500 + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static struct esp_ldo_config_t g_mipi_phy_ldo_config = +{ + .chan_id = ESP_LDO_MIPI_PHY_CHAN, + .voltage_mv = ESP_LDO_MIPI_PHY_VOLTAGE_MV, + .handler = NULL, +}; + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: tab5_mipi_phy_power + * + * Description: + * Enable or disable the MIPI PHY LDO. + * + * Input Parameters: + * on - True to enable the MIPI PHY LDO, false to disable it. + * + * Returned Value: + * Zero on success, -1 on failure. + * + ****************************************************************************/ + +int tab5_mipi_phy_power(bool on) +{ + int ret = OK; + if (on) + { + ret = esp_ldo_channel_acquire(&g_mipi_phy_ldo_config); + } + else + { + ret = esp_ldo_channel_release(&g_mipi_phy_ldo_config); + } + + return ret; +} + +/**************************************************************************** + * Name: tab5_lcd_enable + * + * Description: + * Enable or disable the LCD rail via IO Expander (low). + * + * Input Parameters: + * enable - True to enable the LCD rail, false to disable it. + * + * Returned Value: + * Zero on success, -1 on failure. + * + ****************************************************************************/ + +int tab5_lcd_enable(bool enable) +{ + int ret; + + ret = tab5_pi4ioe_low_write_pin(TAB5_LCD_EN_PIN, enable); + if (ret < 0) + { + syslog(LOG_ERR, + "ERROR: failed to write LCD_EN pin: %d\n", ret); + return ret; + } + + syslog(LOG_INFO, "LCD %s\n", enable ? "enabled" : "disabled"); + return OK; +} + +/**************************************************************************** + * Name: tab5_lcd_backlight + * + * Description: + * Configure GPIO22 as output and drive the backlight enable. + * + * Input Parameters: + * on - True to enable the backlight, false to disable it. + * + * Returned Value: + * Zero on success, -1 on failure. + * + ****************************************************************************/ + +int tab5_lcd_backlight(bool on) +{ + int ret; + + ret = esp_configgpio(TAB5_GPIO_LCD_BL_EN, OUTPUT); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: failed to configure backlight GPIO%d: %d\n", + TAB5_GPIO_LCD_BL_EN, ret); + return ret; + } + + esp_gpiowrite(TAB5_GPIO_LCD_BL_EN, on); + syslog(LOG_INFO, "Backlight %s\n", on ? "enabled" : "disabled"); + return OK; +} + +/**************************************************************************** + * Name: tab5_lcd_power_init + * + * Description: + * Power MIPI PHY LDO, init PI4IOE, and enable LCD (P4 high). + * + * Returned Value: + * Zero on success, -1 on failure. + * + ****************************************************************************/ + +int tab5_lcd_power_init(void) +{ + int ret; + + ret = tab5_mipi_phy_power(true); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: failed to power on MIPI PHY: %d\n", ret); + return ret; + } + + ret = tab5_lcd_enable(true); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: failed to enable LCD rail: %d\n", ret); + return ret; + } + + syslog(LOG_INFO, "LCD power/reset path ready\n"); + return OK; +} diff --git a/boards/risc-v/esp32p4/esp32p4-tab5/src/esp32p4_lcd_st7121.c b/boards/risc-v/esp32p4/esp32p4-tab5/src/esp32p4_lcd_st7121.c new file mode 100644 index 00000000000..f49baf5963f --- /dev/null +++ b/boards/risc-v/esp32p4/esp32p4-tab5/src/esp32p4_lcd_st7121.c @@ -0,0 +1,375 @@ +/**************************************************************************** + * boards/risc-v/esp32p4/esp32p4-tab5/src/esp32p4_lcd_st7121.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/* ST7121 panel bring-up for M5Stack Tab5. + * + * Init init table sourced from https://github.com/espressif/esp-iot-solution + * under components/display/lcd/esp_lcd_st7121/esp_lcd_st7121.c. + */ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> + +#include <errno.h> +#include <syslog.h> + +#include <nuttx/arch.h> +#include <nuttx/video/mipi_dsi.h> + +#include <arch/board/board.h> + +#include "esp32p4-tab5.h" +#include "esp32p4_lcd_st7121.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define ST7121_NAME "st7121" +#define ST7121_COMMAND_DELAY_MS 5 + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct st7121_init_cmd_s +{ + uint8_t cmd; + FAR const uint8_t *data; + uint8_t len; + uint16_t delay_ms; +}; + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const uint8_t g_st7121_cmd_60a[] = +{ + 0x71, 0x21, 0xa2 +}; + +static const uint8_t g_st7121_cmd_60b[] = +{ + 0x71, 0x21, 0xa3 +}; + +static const uint8_t g_st7121_cmd_60c[] = +{ + 0x71, 0x21, 0xa4 +}; + +static const uint8_t g_st7121_cmd_78[] = +{ + 0x21 +}; + +static const uint8_t g_st7121_cmd_79[] = +{ + 0xef +}; + +static const uint8_t g_st7121_cmd_a4[] = +{ + 0x31 +}; + +static const uint8_t g_st7121_cmd_b7[] = +{ + 0x00, 0x00, 0x5f, 0x5f, 0x44, 0x1a +}; + +static const uint8_t g_st7121_cmd_b0[] = +{ + 0x22, 0x6b, 0x11, 0x89, 0x25, 0x43, 0x43 +}; + +static const uint8_t g_st7121_cmd_bf[] = +{ + 0xa7, 0xa7 +}; + +static const uint8_t g_st7121_cmd_a5[] = +{ + 0xf0, 0x03 +}; + +static const uint8_t g_st7121_cmd_d7[] = +{ + 0x10, 0x2c, 0x14, 0x2a, 0x80, 0x80 +}; + +static const uint8_t g_st7121_cmd_90[] = +{ + 0x71, 0x23, 0x5a, 0x20, 0x24, 0x11, 0x21 +}; + +static const uint8_t g_st7121_cmd_a3[] = +{ + 0x80, 0x01, 0x8c, 0xff, 0x45, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x00, + 0x00, 0x1e, 0x5c, 0x1e, 0x80, 0x10, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x46, 0x00, 0x00, 0x1e, 0x5c, 0x1e, 0x80, 0x10, 0xef, 0x58, 0x00, + 0x00, 0x00, 0xff +}; + +static const uint8_t g_st7121_cmd_a6[] = +{ + 0x0a, 0x00, 0x24, 0x71, 0x36, 0x00, 0x00, 0x00, 0x68, 0x68, 0x91, 0xff, + 0x00, 0x24, 0x71, 0x37, 0x00, 0x00, 0x00, 0x68, 0x68, 0x91, 0xff, 0x00, + 0x24, 0x71, 0x00, 0x00, 0x00, 0x00, 0x68, 0x68, 0x91, 0xff, 0x00, 0x2c, + 0x71, 0x00, 0x01, 0x00, 0x00, 0x68, 0x68, 0xff, 0xff, 0x00, 0x08, 0x80, + 0x08, 0x80, 0x06, 0x00, 0x00, 0x00, 0x00 +}; + +static const uint8_t g_st7121_cmd_a7[] = +{ + 0x1a, 0x1a, 0xc0, 0x64, 0x40, 0x04, 0x15, 0x40, 0x00, 0x40, 0x00, 0x68, + 0x68, 0x91, 0xff, 0x08, 0x80, 0x64, 0x40, 0x26, 0x37, 0x40, 0x00, 0x00, + 0x00, 0x68, 0x68, 0x91, 0xff, 0x08, 0x80, 0x64, 0x40, 0x8c, 0x9d, 0x40, + 0x00, 0x00, 0x00, 0x68, 0x68, 0x91, 0xff, 0x08, 0x80, 0x64, 0x40, 0xae, + 0xbf, 0x00, 0x00, 0x20, 0x00, 0x68, 0x68, 0x91, 0xff, 0x08, 0x80, 0x79 +}; + +static const uint8_t g_st7121_cmd_ac[] = +{ + 0x1d, 0x18, 0x19, 0x1d, 0x18, 0x19, 0x04, 0x1c, 0x1d, 0x08, 0x0a, 0x10, + 0x12, 0x0c, 0x0e, 0x14, 0x16, 0x00, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x18, + 0x19, 0x1d, 0x18, 0x19, 0x06, 0x1c, 0x1d, 0x09, 0x0b, 0x11, 0x13, 0x0d, + 0x0f, 0x15, 0x17, 0x02, 0x1d, 0x1d, 0x1d, 0x1d +}; + +static const uint8_t g_st7121_cmd_ad[] = +{ + 0x0c, 0x40, 0x46, 0x00, 0x07, 0x4b, 0x4b, 0xff, 0xff, 0xf0, 0x40, 0x0e, + 0x01, 0x07, 0x42, 0x42, 0xff, 0xff, 0x01, 0x00, 0x00, 0xff, 0xff, 0xff, + 0xff +}; + +static const uint8_t g_st7121_cmd_ae[] = +{ + 0xf0, 0xff, 0x03, 0xf0, 0xff, 0x03, 0x00 +}; + +static const uint8_t g_st7121_cmd_b2[] = +{ + 0x15, 0x19, 0x05, 0x23, 0x49, 0x2d, 0x03, 0x2e, 0x5c, 0xd2, 0xff, 0x10, + 0x60, 0xfd, 0x20, 0xc0, 0x00 +}; + +static const uint8_t g_st7121_cmd_e8[] = +{ + 0x20, 0x60, 0x04, 0x8e, 0x8e, 0x3e, 0x04, 0xdc, 0xdc, 0x3e, 0x06, 0xfa, + 0x26, 0x3e +}; + +static const uint8_t g_st7121_cmd_75[] = +{ + 0x03, 0x04 +}; + +static const uint8_t g_st7121_cmd_e7[] = +{ + 0x4b, 0x00, 0x00, 0xbe, 0x4b, 0x8c, 0x20, 0x1a, 0xf0, 0x7d, 0x14, 0x7d, + 0x14, 0x7d, 0x14, 0x7d, 0x14, 0xff, 0x00, 0x32, 0x30, 0x73, 0x00, 0x00, + 0xc8, 0x6a, 0xff, 0x5a, 0x64, 0x38, 0x88, 0x15, 0xb1, 0x01, 0x01, 0x64, + 0x01, 0x01, 0x7c, 0xff, 0x1a, 0x51 +}; + +static const uint8_t g_st7121_cmd_e1[] = +{ + 0x0c, 0x0c +}; + +static const uint8_t g_st7121_cmd_ea[] = +{ + 0x15, 0x00, 0x01 +}; + +static const uint8_t g_st7121_cmd_c8[] = +{ + 0x00, 0x00, 0x04, 0x08, 0x10, 0x00, 0x1f, 0x01, 0x39, 0x3e, 0x00, 0x78, + 0x06, 0xe2, 0x02, 0x11, 0x33, 0x01, 0x7a, 0x0d, 0x21, 0xc4, 0x0b, 0x19, + 0x08, 0x32, 0xa0, 0x08, 0x1a, 0x0a, 0xf3, 0x7f, 0x0e, 0xc5, 0xe8, 0x03, + 0xff +}; + +static const uint8_t g_st7121_cmd_c9[] = +{ + 0x00, 0x00, 0x04, 0x08, 0x10, 0x00, 0x1f, 0x01, 0x39, 0x3e, 0x00, 0x78, + 0x06, 0xe2, 0x02, 0x11, 0x33, 0x01, 0x7a, 0x0d, 0x21, 0xc4, 0x0b, 0x19, + 0x08, 0x32, 0xa0, 0x08, 0x1a, 0x0a, 0xf3, 0x7f, 0x0e, 0xc5, 0xe8, 0x03, + 0xff +}; + +static const uint8_t g_st7121_cmd_60d[] = +{ + 0x71, 0x21, 0x00 +}; + +static const uint8_t g_st7121_cmd_35[] = +{ + 0x00 +}; + +static const struct st7121_init_cmd_s g_st7121_init[] = +{ + {0x60, g_st7121_cmd_60a, sizeof(g_st7121_cmd_60a), 0}, + {0x60, g_st7121_cmd_60b, sizeof(g_st7121_cmd_60b), 0}, + {0x60, g_st7121_cmd_60c, sizeof(g_st7121_cmd_60c), 0}, + {0x78, g_st7121_cmd_78, sizeof(g_st7121_cmd_78), 0}, + {0x79, g_st7121_cmd_79, sizeof(g_st7121_cmd_79), 0}, + {0xa4, g_st7121_cmd_a4, sizeof(g_st7121_cmd_a4), 0}, + {0xb7, g_st7121_cmd_b7, sizeof(g_st7121_cmd_b7), 0}, + {0xb0, g_st7121_cmd_b0, sizeof(g_st7121_cmd_b0), 0}, + {0xbf, g_st7121_cmd_bf, sizeof(g_st7121_cmd_bf), 0}, + {0xa5, g_st7121_cmd_a5, sizeof(g_st7121_cmd_a5), 0}, + {0xd7, g_st7121_cmd_d7, sizeof(g_st7121_cmd_d7), 0}, + {0x90, g_st7121_cmd_90, sizeof(g_st7121_cmd_90), 0}, + {0xa3, g_st7121_cmd_a3, sizeof(g_st7121_cmd_a3), 0}, + {0xa6, g_st7121_cmd_a6, sizeof(g_st7121_cmd_a6), 0}, + {0xa7, g_st7121_cmd_a7, sizeof(g_st7121_cmd_a7), 0}, + {0xac, g_st7121_cmd_ac, sizeof(g_st7121_cmd_ac), 0}, + {0xad, g_st7121_cmd_ad, sizeof(g_st7121_cmd_ad), 0}, + {0xae, g_st7121_cmd_ae, sizeof(g_st7121_cmd_ae), 0}, + {0xb2, g_st7121_cmd_b2, sizeof(g_st7121_cmd_b2), 0}, + {0xe8, g_st7121_cmd_e8, sizeof(g_st7121_cmd_e8), 0}, + {0x75, g_st7121_cmd_75, sizeof(g_st7121_cmd_75), 0}, + {0xe7, g_st7121_cmd_e7, sizeof(g_st7121_cmd_e7), 0}, + {0xe1, g_st7121_cmd_e1, sizeof(g_st7121_cmd_e1), 0}, + {0xea, g_st7121_cmd_ea, sizeof(g_st7121_cmd_ea), 0}, + {0xc8, g_st7121_cmd_c8, sizeof(g_st7121_cmd_c8), 0}, + {0xc9, g_st7121_cmd_c9, sizeof(g_st7121_cmd_c9), 0}, + {0x60, g_st7121_cmd_60d, sizeof(g_st7121_cmd_60d), 0}, + {0x11, NULL, 0, 80}, + {0x29, NULL, 0, 800}, + {0x35, g_st7121_cmd_35, sizeof(g_st7121_cmd_35), 0}, +}; + +#define ST7121_INIT_COUNT (sizeof(g_st7121_init) / sizeof(g_st7121_init[0])) + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: st7121_send_init + ****************************************************************************/ + +static int st7121_send_init(FAR struct mipi_dsi_device *device) +{ + unsigned int i; + ssize_t n; + + for (i = 0; i < ST7121_INIT_COUNT; i++) + { + FAR const struct st7121_init_cmd_s *cmd = &g_st7121_init[i]; + + n = mipi_dsi_dcs_write(device, cmd->cmd, cmd->data, cmd->len); + if (n < 0) + { + syslog(LOG_ERR, + "ERROR: DCS 0x%02x failed: %zd (cmd %u/%u)\n", + cmd->cmd, n, i + 1, ST7121_INIT_COUNT); + return (int)n; + } + + if (cmd->delay_ms > 0) + { + up_mdelay(cmd->delay_ms); + } + + up_mdelay(ST7121_COMMAND_DELAY_MS); + } + + return OK; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: tab5_st7121_initialize + ****************************************************************************/ + +FAR struct mipi_dsi_device *tab5_st7121_initialize( + FAR struct mipi_dsi_host *host) +{ + FAR struct mipi_dsi_device *device; + int ret; + + if (host == NULL) + { + return NULL; + } + + tab5_lcd_backlight(false); + + ret = tab5_lcd_enable(true); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: LCD_EN enable failed: %d\n", ret); + return NULL; + } + + device = mipi_dsi_device_register(host, ST7121_NAME, 0); + if (device == NULL) + { + syslog(LOG_ERR, "ERROR: mipi_dsi_device_register failed\n"); + return NULL; + } + + device->lanes = TAB5_MIPI_DSI_LANES; + device->format = MIPI_DSI_FMT_RGB565; + device->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST | + MIPI_DSI_MODE_LPM; + device->hs_rate = TAB5_MIPI_DSI_LANE_BITRATE_MBPS * 1000000UL; + device->lp_rate = 0; + + ret = mipi_dsi_attach(device); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: attach failed: %d\n", ret); + return NULL; + } + + ret = mipi_dsi_dcs_soft_reset(device); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: soft reset failed: %d\n", ret); + return NULL; + } + + up_mdelay(120); + + ret = st7121_send_init(device); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: DCS init failed: %d\n", ret); + return NULL; + } + + return device; +} diff --git a/boards/risc-v/esp32p4/esp32p4-tab5/src/esp32p4_lcd_st7121.h b/boards/risc-v/esp32p4/esp32p4-tab5/src/esp32p4_lcd_st7121.h new file mode 100644 index 00000000000..e2f672c54ab --- /dev/null +++ b/boards/risc-v/esp32p4/esp32p4-tab5/src/esp32p4_lcd_st7121.h @@ -0,0 +1,75 @@ +/**************************************************************************** + * boards/risc-v/esp32p4/esp32p4-tab5/src/esp32p4_lcd_st7121.h + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __BOARDS_RISCV_ESP32P4_ESP32P4_TAB5_SRC_ESP32P4_LCD_ST7121_H +#define __BOARDS_RISCV_ESP32P4_ESP32P4_TAB5_SRC_ESP32P4_LCD_ST7121_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> + +#include <nuttx/video/mipi_dsi.h> + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Name: tab5_st7121_initialize + * + * Description: + * Register the ST7121 as a mipi_dsi_device, attach to the Espressif host, + * power-cycle LCD_EN (BSP_LCD_RST is NC), issue DCS soft-reset, and send + * the M5Stack Tab5 ST7121 vendor DCS initialization table. Does not start + * video; board code calls display_on after video_start. + * + * Input Parameters: + * host - Registered MIPI-DSI host (esp_mipi_dsi_host_get()) + * + * Returned Value: + * Pointer to the registered device on success; NULL on failure. + * + ****************************************************************************/ +#ifdef CONFIG_ESP32P4_TAB5_LCD_ST7121 +FAR struct mipi_dsi_device *tab5_st7121_initialize( + FAR struct mipi_dsi_host *host); +#endif + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* __BOARDS_RISCV_ESP32P4_ESP32P4_TAB5_SRC_ESP32P4_LCD_ST7121_H */ diff --git a/boards/risc-v/esp32p4/esp32p4-tab5/src/esp32p4_lcd_st7123.c b/boards/risc-v/esp32p4/esp32p4-tab5/src/esp32p4_lcd_st7123.c new file mode 100644 index 00000000000..1b3d120ce6f --- /dev/null +++ b/boards/risc-v/esp32p4/esp32p4-tab5/src/esp32p4_lcd_st7123.c @@ -0,0 +1,425 @@ +/**************************************************************************** + * boards/risc-v/esp32p4/esp32p4-tab5/src/esp32p4_lcd_st7123.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/* ST7123 panel bring-up for M5Stack Tab5. + * + * Init init table sourced from https://github.com/espressif/esp-iot-solution + * under components/display/lcd/esp_lcd_st7123/esp_lcd_st7123.c. + */ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> + +#include <errno.h> +#include <syslog.h> +#include <string.h> + +#include <nuttx/arch.h> +#include <nuttx/video/mipi_dsi.h> + +#include <arch/board/board.h> + +#include "esp32p4-tab5.h" +#include "esp32p4_lcd_st7123.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define ST7123_NAME "st7123" + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct st7123_init_cmd_s +{ + uint8_t cmd; + FAR const uint8_t *data; + uint8_t len; + uint16_t delay_ms; +}; + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* ESP-BSP Tab5 ST7123 vendor table (disp_init_data_st7123). */ + +static const uint8_t g_st7123_cmd_60a[] = +{ + 0x71, 0x23, 0xa2 +}; + +static const uint8_t g_st7123_cmd_60b[] = +{ + 0x71, 0x23, 0xa3 +}; + +static const uint8_t g_st7123_cmd_60c[] = +{ + 0x71, 0x23, 0xa4 +}; + +static const uint8_t g_st7123_cmd_a4[] = +{ + 0x31 +}; + +static const uint8_t g_st7123_cmd_d7[] = +{ + 0x10, 0x0a, 0x10, 0x2a, 0x80, 0x80 +}; + +static const uint8_t g_st7123_cmd_90[] = +{ + 0x71, 0x23, 0x5a, 0x20, 0x24, 0x09, 0x09 +}; + +static const uint8_t g_st7123_cmd_a3[] = +{ + 0x80, 0x01, 0x88, 0x30, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x00, + 0x00, 0x1e, 0x5c, 0x1e, 0x80, 0x00, 0x4f, 0x05, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x46, 0x00, 0x00, 0x1e, 0x5c, 0x1e, 0x80, 0x00, 0x6f, 0x58, 0x00, + 0x00, 0x00, 0xff +}; + +static const uint8_t g_st7123_cmd_a6[] = +{ + 0x03, 0x00, 0x24, 0x55, 0x36, 0x00, 0x39, 0x00, 0x6e, 0x6e, 0x91, 0xff, + 0x00, 0x24, 0x55, 0x38, 0x00, 0x37, 0x00, 0x6e, 0x6e, 0x91, 0xff, 0x00, + 0x24, 0x11, 0x00, 0x00, 0x00, 0x00, 0x6e, 0x6e, 0x91, 0xff, 0x00, 0xec, + 0x11, 0x00, 0x03, 0x00, 0x03, 0x6e, 0x6e, 0xff, 0xff, 0x00, 0x08, 0x80, + 0x08, 0x80, 0x06, 0x00, 0x00, 0x00, 0x00 +}; + +static const uint8_t g_st7123_cmd_a7[] = +{ + 0x19, 0x19, 0x80, 0x64, 0x40, 0x07, 0x16, 0x40, 0x00, 0x44, 0x03, 0x6e, + 0x6e, 0x91, 0xff, 0x08, 0x80, 0x64, 0x40, 0x25, 0x34, 0x40, 0x00, 0x02, + 0x01, 0x6e, 0x6e, 0x91, 0xff, 0x08, 0x80, 0x64, 0x40, 0x00, 0x00, 0x40, + 0x00, 0x00, 0x00, 0x6e, 0x6e, 0x91, 0xff, 0x08, 0x80, 0x64, 0x40, 0x00, + 0x00, 0x00, 0x00, 0x20, 0x00, 0x6e, 0x6e, 0x84, 0xff, 0x08, 0x80, 0x44 +}; + +static const uint8_t g_st7123_cmd_ac[] = +{ + 0x03, 0x19, 0x19, 0x18, 0x18, 0x06, 0x13, 0x13, 0x11, 0x11, 0x08, 0x08, + 0x0a, 0x0a, 0x1c, 0x1c, 0x07, 0x07, 0x00, 0x00, 0x02, 0x02, 0x01, 0x19, + 0x19, 0x18, 0x18, 0x06, 0x12, 0x12, 0x10, 0x10, 0x09, 0x09, 0x0b, 0x0b, + 0x1c, 0x1c, 0x07, 0x07, 0x03, 0x03, 0x01, 0x01 +}; + +static const uint8_t g_st7123_cmd_ad[] = +{ + 0xf0, 0x00, 0x46, 0x00, 0x03, 0x50, 0x50, 0xff, 0xff, 0xf0, 0x40, 0x06, + 0x01, 0x07, 0x42, 0x42, 0xff, 0xff, 0x01, 0x00, 0x00, 0xff, 0xff, 0xff, + 0xff +}; + +static const uint8_t g_st7123_cmd_ae[] = +{ + 0xfe, 0x3f, 0x3f, 0xfe, 0x3f, 0x3f, 0x00 +}; + +static const uint8_t g_st7123_cmd_b2[] = +{ + 0x15, 0x19, 0x05, 0x23, 0x49, 0xaf, 0x03, 0x2e, 0x5c, 0xd2, 0xff, 0x10, + 0x20, 0xfd, 0x20, 0xc0, 0x00 +}; + +static const uint8_t g_st7123_cmd_e8[] = +{ + 0x20, 0x6f, 0x04, 0x97, 0x97, 0x3e, 0x04, 0xdc, 0xdc, 0x3e, 0x06, 0xfa, + 0x26, 0x3e +}; + +static const uint8_t g_st7123_cmd_75[] = +{ + 0x03, 0x04 +}; + +static const uint8_t g_st7123_cmd_e7[] = +{ + 0x3b, 0x00, 0x00, 0x7c, 0xa1, 0x8c, 0x20, 0x1a, 0xf0, 0xb1, 0x50, 0x00, + 0x50, 0xb1, 0x50, 0xb1, 0x50, 0xd8, 0x00, 0x55, 0x00, 0xb1, 0x00, 0x45, + 0xc9, 0x6a, 0xff, 0x5a, 0xd8, 0x18, 0x88, 0x15, 0xb1, 0x01, 0x01, 0x77 +}; + +static const uint8_t g_st7123_cmd_ea[] = +{ + 0x13, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x2c +}; + +static const uint8_t g_st7123_cmd_b0[] = +{ + 0x22, 0x43, 0x11, 0x61, 0x25, 0x43, 0x43 +}; + +static const uint8_t g_st7123_cmd_b7[] = +{ + 0x00, 0x00, 0x73, 0x73 +}; + +static const uint8_t g_st7123_cmd_bf[] = +{ + 0xa6, 0xaa +}; + +static const uint8_t g_st7123_cmd_a9[] = +{ + 0x00, 0x00, 0x73, 0xff, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03 +}; + +static const uint8_t g_st7123_cmd_c8[] = +{ + 0x00, 0x00, 0x10, 0x1f, 0x36, 0x00, 0x5d, 0x04, 0x9d, 0x05, 0x10, 0xf2, + 0x06, 0x60, 0x03, 0x11, 0xad, 0x00, 0xef, 0x01, 0x22, 0x2e, 0x0e, 0x74, + 0x08, 0x32, 0xdc, 0x09, 0x33, 0x0f, 0xf3, 0x77, 0x0d, 0xb0, 0xdc, 0x03, + 0xff +}; + +static const uint8_t g_st7123_cmd_c9[] = +{ + 0x00, 0x00, 0x10, 0x1f, 0x36, 0x00, 0x5d, 0x04, 0x9d, 0x05, 0x10, 0xf2, + 0x06, 0x60, 0x03, 0x11, 0xad, 0x00, 0xef, 0x01, 0x22, 0x2e, 0x0e, 0x74, + 0x08, 0x32, 0xdc, 0x09, 0x33, 0x0f, 0xf3, 0x77, 0x0d, 0xb0, 0xdc, 0x03, + 0xff +}; + +static const uint8_t g_st7123_cmd_36[] = +{ + 0x03 +}; + +static const uint8_t g_st7123_cmd_35[] = +{ + 0x00 +}; + +static const struct st7123_init_cmd_s g_st7123_init[] = +{ + { + 0x60, g_st7123_cmd_60a, sizeof(g_st7123_cmd_60a), 0 + }, + { + 0x60, g_st7123_cmd_60b, sizeof(g_st7123_cmd_60b), 0 + }, + { + 0x60, g_st7123_cmd_60c, sizeof(g_st7123_cmd_60c), 0 + }, + { + 0xa4, g_st7123_cmd_a4, sizeof(g_st7123_cmd_a4), 0 + }, + { + 0xd7, g_st7123_cmd_d7, sizeof(g_st7123_cmd_d7), 0 + }, + { + 0x90, g_st7123_cmd_90, sizeof(g_st7123_cmd_90), 0 + }, + { + 0xa3, g_st7123_cmd_a3, sizeof(g_st7123_cmd_a3), 0 + }, + { + 0xa6, g_st7123_cmd_a6, sizeof(g_st7123_cmd_a6), 0 + }, + { + 0xa7, g_st7123_cmd_a7, sizeof(g_st7123_cmd_a7), 0 + }, + { + 0xac, g_st7123_cmd_ac, sizeof(g_st7123_cmd_ac), 0 + }, + { + 0xad, g_st7123_cmd_ad, sizeof(g_st7123_cmd_ad), 0 + }, + { + 0xae, g_st7123_cmd_ae, sizeof(g_st7123_cmd_ae), 0 + }, + { + 0xb2, g_st7123_cmd_b2, sizeof(g_st7123_cmd_b2), 0 + }, + { + 0xe8, g_st7123_cmd_e8, sizeof(g_st7123_cmd_e8), 0 + }, + { + 0x75, g_st7123_cmd_75, sizeof(g_st7123_cmd_75), 0 + }, + { + 0xe7, g_st7123_cmd_e7, sizeof(g_st7123_cmd_e7), 0 + }, + { + 0xea, g_st7123_cmd_ea, sizeof(g_st7123_cmd_ea), 0 + }, + { + 0xb0, g_st7123_cmd_b0, sizeof(g_st7123_cmd_b0), 0 + }, + { + 0xb7, g_st7123_cmd_b7, sizeof(g_st7123_cmd_b7), 0 + }, + { + 0xbf, g_st7123_cmd_bf, sizeof(g_st7123_cmd_bf), 0 + }, + { + 0xa9, g_st7123_cmd_a9, sizeof(g_st7123_cmd_a9), 0 + }, + { + 0xc8, g_st7123_cmd_c8, sizeof(g_st7123_cmd_c8), 0 + }, + { + 0xc9, g_st7123_cmd_c9, sizeof(g_st7123_cmd_c9), 0 + }, + { + 0x36, g_st7123_cmd_36, sizeof(g_st7123_cmd_36), 0 + }, + + /* 0x11 / 0x29: 0-param DCS (dummy 0x00 as 1-param broke sleep-out). + * Delays match ESP-BSP disp_init_data_st7123 (120 / 50). + */ + + { + 0x11, NULL, 0, 120 + }, + { + 0x29, NULL, 0, 50 + }, + { + 0x35, g_st7123_cmd_35, sizeof(g_st7123_cmd_35), 0 + }, +}; + +#define ST7123_INIT_COUNT (sizeof(g_st7123_init) / sizeof(g_st7123_init[0])) + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: st7123_send_init + * + * Description: + * Send the ST7123 vendor init table. + * + * Input Parameters: + * device - Pointer to the MIPI-DSI device structure. + * + * Returned Value: + * Zero on success, -1 on failure. + ****************************************************************************/ + +static int st7123_send_init(FAR struct mipi_dsi_device *device) +{ + unsigned int i; + ssize_t n; + + for (i = 0; i < ST7123_INIT_COUNT; i++) + { + FAR const struct st7123_init_cmd_s *cmd = &g_st7123_init[i]; + + n = mipi_dsi_dcs_write(device, cmd->cmd, cmd->data, cmd->len); + if (n < 0) + { + syslog(LOG_ERR, + "ERROR: DCS 0x%02x failed: %zd (cmd %u/%u)\n", + cmd->cmd, n, i + 1, ST7123_INIT_COUNT); + return (int)n; + } + + if (cmd->delay_ms > 0) + { + up_mdelay(cmd->delay_ms); + } + } + + return OK; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: tab5_st7123_initialize + * + * Description: + * Register the ST7123 as a mipi_dsi_device, attach to the Espressif host, + * pulse LCD reset via PI4IOE, and send the ESP-BSP Tab5 vendor DCS init + * table (disp_init_data_st7123[]). Does not start video; board code + * calls display_on after video_start. + * + * Input Parameters: + * host - Pointer to the MIPI-DSI host structure. + * + * Returned Value: + * Pointer to the MIPI-DSI device structure on success, NULL on failure. + ****************************************************************************/ + +FAR struct mipi_dsi_device *tab5_st7123_initialize( + FAR struct mipi_dsi_host *host) +{ + FAR struct mipi_dsi_device *device; + int ret; + + if (host == NULL) + { + return NULL; + } + + ret = tab5_lcd_enable(true); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: LCD_EN enable failed: %d\n", ret); + return NULL; + } + + device = mipi_dsi_device_register(host, ST7123_NAME, 0); + if (device == NULL) + { + syslog(LOG_ERR, "ERROR: mipi_dsi_device_register failed\n"); + return NULL; + } + + device->lanes = TAB5_MIPI_DSI_LANES; + device->format = MIPI_DSI_FMT_RGB565; + device->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST | + MIPI_DSI_MODE_LPM; + device->hs_rate = TAB5_MIPI_DSI_LANE_BITRATE_MBPS * 1000000UL; + device->lp_rate = 0; + + ret = mipi_dsi_attach(device); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: attach failed: %d\n", ret); + return NULL; + } + + ret = st7123_send_init(device); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: DCS init failed: %d\n", ret); + return NULL; + } + + return device; +} diff --git a/boards/risc-v/esp32p4/esp32p4-tab5/src/esp32p4_lcd_st7123.h b/boards/risc-v/esp32p4/esp32p4-tab5/src/esp32p4_lcd_st7123.h new file mode 100644 index 00000000000..b3ba31785ab --- /dev/null +++ b/boards/risc-v/esp32p4/esp32p4-tab5/src/esp32p4_lcd_st7123.h @@ -0,0 +1,74 @@ +/**************************************************************************** + * boards/risc-v/esp32p4/esp32p4-tab5/src/esp32p4_lcd_st7123.h + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __BOARDS_RISCV_ESP32P4_ESP32P4_TAB5_SRC_ESP32P4_LCD_ST7123_H +#define __BOARDS_RISCV_ESP32P4_ESP32P4_TAB5_SRC_ESP32P4_LCD_ST7123_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> + +#include <nuttx/video/mipi_dsi.h> + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Name: tab5_st7123_initialize + * + * Description: + * Register the ST7123 as a mipi_dsi_device, attach to the Espressif host, + * pulse LCD reset via PI4IOE, and send the ESP-BSP Tab5 vendor DCS init + * table (disp_init_data_st7123[]). Does not start video; board code + * calls display_on after video_start. + * + * Input Parameters: + * host - Registered MIPI-DSI host (esp_mipi_dsi_host_get()) + * + * Returned Value: + * Pointer to the registered device on success; NULL on failure. + * + ****************************************************************************/ +#ifdef CONFIG_ESP32P4_TAB5_LCD_ST7123 +FAR struct mipi_dsi_device *tab5_st7123_initialize( + FAR struct mipi_dsi_host *host); +#endif +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* __BOARDS_RISCV_ESP32P4_ESP32P4_TAB5_SRC_ESP32P4_LCD_ST7123_H */ diff --git a/boards/risc-v/esp32p4/esp32p4-tab5/src/esp32p4_mipi_dpi.c b/boards/risc-v/esp32p4/esp32p4-tab5/src/esp32p4_mipi_dpi.c new file mode 100644 index 00000000000..c03c62c2fde --- /dev/null +++ b/boards/risc-v/esp32p4/esp32p4-tab5/src/esp32p4_mipi_dpi.c @@ -0,0 +1,69 @@ +/**************************************************************************** + * boards/risc-v/esp32p4/esp32p4-tab5/src/esp32p4_mipi_dpi.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> + +#include <assert.h> + +#include <nuttx/video/mipi_dsi.h> + +#include <arch/board/board.h> + +#include "esp32p4-tab5.h" + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: tab5_mipi_dsi_dpi_config + * + * Description: + * Configure the MIPI-DSI DPI configuration. + * + * Input Parameters: + * cfg - Pointer to the MIPI-DSI DPI configuration structure. + * + * Returned Value: + * None. + ****************************************************************************/ + +void tab5_mipi_dsi_dpi_config(FAR struct esp_mipi_dsi_dpi_config_s *cfg) +{ + DEBUGASSERT(cfg != NULL); + + cfg->h_res = TAB5_MIPI_DSI_H_RES; + cfg->v_res = TAB5_MIPI_DSI_V_RES; + cfg->hsync_pulse_width = TAB5_MIPI_DSI_HSYNC_PULSE_WIDTH; + cfg->hsync_back_porch = TAB5_MIPI_DSI_HSYNC_BACK_PORCH; + cfg->hsync_front_porch = TAB5_MIPI_DSI_HSYNC_FRONT_PORCH; + cfg->vsync_pulse_width = TAB5_MIPI_DSI_VSYNC_PULSE_WIDTH; + cfg->vsync_back_porch = TAB5_MIPI_DSI_VSYNC_BACK_PORCH; + cfg->vsync_front_porch = TAB5_MIPI_DSI_VSYNC_FRONT_PORCH; + cfg->dpi_clock_freq_mhz = TAB5_MIPI_DSI_DPI_CLK_MHZ; + cfg->virtual_channel = 0; + cfg->format = MIPI_DSI_FMT_RGB565; +}
