initial commit
This commit is contained in:
378
components/ExternLib/codec_board/lcd_init.c
Normal file
378
components/ExternLib/codec_board/lcd_init.c
Normal file
@@ -0,0 +1,378 @@
|
||||
#include "codec_board.h"
|
||||
#include "esp_lcd_panel_io.h"
|
||||
#include "esp_lcd_panel_ops.h"
|
||||
#include "tca9554.h"
|
||||
#include "esp_log.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "driver/spi_common.h"
|
||||
#include "esp_idf_version.h"
|
||||
|
||||
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 3, 0)
|
||||
#include "esp_lcd_panel_dev.h"
|
||||
#include "esp_lcd_panel_st7789.h"
|
||||
#else
|
||||
#include "esp_lcd_panel_vendor.h"
|
||||
#endif
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32P4
|
||||
#include "esp_lcd_panel_ops.h"
|
||||
#include "esp_lcd_mipi_dsi.h"
|
||||
#include "esp_lcd_ili9881c.h"
|
||||
#include "esp_ldo_regulator.h"
|
||||
#include "soc/mipi_dsi_bridge_struct.h"
|
||||
#include "esp_lcd_ek79007.h"
|
||||
#endif
|
||||
|
||||
#include "freertos/FreeRTOS.h"
|
||||
|
||||
#define TAG "LCD_INIT"
|
||||
|
||||
#define RETURN_ON_ERR(ret) if (ret != 0) { \
|
||||
ESP_LOGE(TAG, "Fail to run on %d ret %d", __LINE__, ret); \
|
||||
return ret; \
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
int (*init)(lcd_cfg_t *cfg);
|
||||
int (*set_dir)(int16_t gpio, bool output);
|
||||
int (*set_gpio)(int16_t gpio, bool high);
|
||||
} extend_io_ops_t;
|
||||
|
||||
static extend_io_ops_t extend_io_ops;
|
||||
static esp_lcd_panel_handle_t panel_handle = NULL;
|
||||
|
||||
static int tca9554_io_init(lcd_cfg_t *cfg)
|
||||
{
|
||||
return tca9554_init(cfg->io_i2c_port);
|
||||
}
|
||||
|
||||
static int tca9554_io_set_dir(int16_t gpio, bool output)
|
||||
{
|
||||
gpio = (1 << gpio);
|
||||
tca9554_set_io_config(gpio, output ? TCA9554_IO_OUTPUT : TCA9554_IO_INPUT);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tca9554_io_set(int16_t gpio, bool high)
|
||||
{
|
||||
gpio = (1 << gpio);
|
||||
return tca9554_set_output_state(gpio, high ? TCA9554_IO_HIGH : TCA9554_IO_LOW);
|
||||
}
|
||||
|
||||
static void register_tca9554(void)
|
||||
{
|
||||
extend_io_ops.init = tca9554_io_init;
|
||||
extend_io_ops.set_dir = tca9554_io_set_dir;
|
||||
extend_io_ops.set_gpio = tca9554_io_set;
|
||||
}
|
||||
|
||||
static int init_extend_io(lcd_cfg_t *cfg)
|
||||
{
|
||||
if (cfg->io_type == EXTENT_IO_TYPE_NONE) {
|
||||
return 0;
|
||||
}
|
||||
switch (cfg->io_type) {
|
||||
case EXTENT_IO_TYPE_TCA9554:
|
||||
register_tca9554();
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
return extend_io_ops.init(cfg);
|
||||
}
|
||||
|
||||
static int set_pin_dir(int16_t pin, bool output)
|
||||
{
|
||||
if (pin & BOARD_EXTEND_IO_START) {
|
||||
pin &= ~BOARD_EXTEND_IO_START;
|
||||
extend_io_ops.set_dir(pin, output);
|
||||
} else {
|
||||
gpio_config_t bk_gpio_config = {
|
||||
.mode = output ? GPIO_MODE_OUTPUT : GPIO_MODE_INPUT,
|
||||
.pin_bit_mask = pin > 0 ? 1ULL << pin : 0ULL,
|
||||
};
|
||||
gpio_config(&bk_gpio_config);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int set_pin_state(int16_t pin, bool high)
|
||||
{
|
||||
if (pin & BOARD_EXTEND_IO_START) {
|
||||
extend_io_ops.set_gpio(pin, high);
|
||||
} else {
|
||||
gpio_set_level(pin, true);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int16_t get_hw_gpio(int16_t pin)
|
||||
{
|
||||
if (pin == -1) {
|
||||
return pin;
|
||||
}
|
||||
if (pin & BOARD_EXTEND_IO_START) {
|
||||
return -1;
|
||||
}
|
||||
return pin;
|
||||
}
|
||||
|
||||
static void sleep_ms(int ms)
|
||||
{
|
||||
vTaskDelay(ms / portTICK_PERIOD_MS);
|
||||
}
|
||||
|
||||
static int _lcd_rest(lcd_cfg_t *cfg)
|
||||
{
|
||||
if (cfg->reset_pin >= 0) {
|
||||
set_pin_state(cfg->reset_pin, false);
|
||||
sleep_ms(100);
|
||||
set_pin_state(cfg->reset_pin, true);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _init_spi_lcd(lcd_cfg_t *cfg)
|
||||
{
|
||||
int ret = 0;
|
||||
if (cfg->spi_cfg.cs & BOARD_EXTEND_IO_START) {
|
||||
set_pin_dir(cfg->spi_cfg.cs, true);
|
||||
sleep_ms(10);
|
||||
set_pin_dir(cfg->spi_cfg.cs, false);
|
||||
sleep_ms(10);
|
||||
}
|
||||
spi_bus_config_t buscfg = {
|
||||
.sclk_io_num = cfg->spi_cfg.clk,
|
||||
.mosi_io_num = cfg->spi_cfg.mosi,
|
||||
.miso_io_num = -1,
|
||||
.quadwp_io_num = -1,
|
||||
.quadhd_io_num = -1,
|
||||
.max_transfer_sz = cfg->width * cfg->height * 2,
|
||||
};
|
||||
#if SOC_SPI_SUPPORT_OCT
|
||||
if (cfg->spi_cfg.d[6] >= 0) {
|
||||
buscfg.data1_io_num = cfg->spi_cfg.d[0];
|
||||
buscfg.data2_io_num = cfg->spi_cfg.d[1];
|
||||
;
|
||||
buscfg.data3_io_num = cfg->spi_cfg.d[2];
|
||||
;
|
||||
buscfg.data4_io_num = cfg->spi_cfg.d[3];
|
||||
;
|
||||
buscfg.data5_io_num = cfg->spi_cfg.d[4];
|
||||
;
|
||||
buscfg.data6_io_num = cfg->spi_cfg.d[5];
|
||||
;
|
||||
buscfg.data7_io_num = cfg->spi_cfg.d[6];
|
||||
;
|
||||
buscfg.flags = SPICOMMON_BUSFLAG_OCTAL;
|
||||
}
|
||||
#endif
|
||||
int bus_id = SPI1_HOST + (cfg->spi_cfg.spi_bus - 1);
|
||||
ret = spi_bus_initialize(bus_id, &buscfg, SPI_DMA_CH_AUTO);
|
||||
ESP_LOGI(TAG, "CLK %d MOSI %d CS:%d DC: %d Bus:%d",
|
||||
cfg->spi_cfg.clk, cfg->spi_cfg.mosi,
|
||||
get_hw_gpio(cfg->spi_cfg.cs), cfg->spi_cfg.dc,
|
||||
bus_id);
|
||||
RETURN_ON_ERR(ret);
|
||||
esp_lcd_panel_io_spi_config_t io_config = {
|
||||
.dc_gpio_num = cfg->spi_cfg.dc,
|
||||
.cs_gpio_num = get_hw_gpio(cfg->spi_cfg.cs),
|
||||
.pclk_hz = cfg->spi_cfg.pclk_clk ? cfg->spi_cfg.pclk_clk : 60 * 1000 * 1000,
|
||||
.spi_mode = 0,
|
||||
.trans_queue_depth = 10,
|
||||
.lcd_cmd_bits = cfg->spi_cfg.cmd_bits ? cfg->spi_cfg.cmd_bits : 8,
|
||||
.lcd_param_bits = cfg->spi_cfg.param_bits ? cfg->spi_cfg.param_bits : 8,
|
||||
.on_color_trans_done = NULL,
|
||||
.user_ctx = NULL,
|
||||
};
|
||||
#if SOC_SPI_SUPPORT_OCT
|
||||
if (cfg->spi_cfg.d[6] >= 0) {
|
||||
io_config.flags.octal_mode = 1;
|
||||
io_config.spi_mode = 3;
|
||||
}
|
||||
#endif
|
||||
esp_lcd_panel_io_handle_t io_handle;
|
||||
ret = esp_lcd_new_panel_io_spi((esp_lcd_spi_bus_handle_t)bus_id, &io_config, &io_handle);
|
||||
RETURN_ON_ERR(ret);
|
||||
esp_lcd_panel_dev_config_t panel_config = {
|
||||
.reset_gpio_num = get_hw_gpio(cfg->reset_pin),
|
||||
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 3, 0)
|
||||
.rgb_ele_order = ESP_LCD_COLOR_SPACE_BGR,
|
||||
#else
|
||||
.rgb_endian = LCD_RGB_ENDIAN_BGR,
|
||||
#endif
|
||||
.bits_per_pixel = 16,
|
||||
};
|
||||
switch (cfg->controller) {
|
||||
default:
|
||||
return -1;
|
||||
case LCD_CONTROLLER_TYPE_ST7789:
|
||||
ret = esp_lcd_new_panel_st7789(io_handle, &panel_config, &panel_handle);
|
||||
RETURN_ON_ERR(ret);
|
||||
ESP_LOGI(TAG, "Init driver ST7789 finished");
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32P4
|
||||
static int power_on_dsi(lcd_mipi_cfg_t *mipi_cfg)
|
||||
{
|
||||
esp_ldo_channel_handle_t ldo_mipi_phy = NULL;
|
||||
esp_ldo_channel_config_t ldo_mipi_phy_config = {
|
||||
.chan_id = mipi_cfg->ldo_chan,
|
||||
.voltage_mv = mipi_cfg->ldo_voltage,
|
||||
};
|
||||
return esp_ldo_acquire_channel(&ldo_mipi_phy_config, &ldo_mipi_phy);
|
||||
}
|
||||
|
||||
static int _init_mipi_lcd(lcd_cfg_t *cfg)
|
||||
{
|
||||
int ret = 0;
|
||||
lcd_mipi_cfg_t *mipi_cfg = &cfg->mipi_cfg;
|
||||
power_on_dsi(mipi_cfg);
|
||||
// create MIPI DSI bus first, it will initialize the DSI PHY as well
|
||||
esp_lcd_dsi_bus_handle_t mipi_dsi_bus;
|
||||
esp_lcd_dsi_bus_config_t bus_config = {
|
||||
.bus_id = 0,
|
||||
.num_data_lanes = mipi_cfg->lane_num,
|
||||
.phy_clk_src = MIPI_DSI_PHY_CLK_SRC_DEFAULT,
|
||||
.lane_bit_rate_mbps = mipi_cfg->lane_bitrate,
|
||||
};
|
||||
ret = esp_lcd_new_dsi_bus(&bus_config, &mipi_dsi_bus);
|
||||
RETURN_ON_ERR(ret);
|
||||
ESP_LOGI(TAG, "Install MIPI DSI LCD control panel");
|
||||
esp_lcd_panel_io_handle_t mipi_dbi_io;
|
||||
// we use DBI interface to send LCD commands and parameters
|
||||
esp_lcd_dbi_io_config_t dbi_config = {
|
||||
.virtual_channel = 0,
|
||||
.lcd_cmd_bits = 8,
|
||||
.lcd_param_bits = 8,
|
||||
};
|
||||
ret = esp_lcd_new_panel_io_dbi(mipi_dsi_bus, &dbi_config, &mipi_dbi_io);
|
||||
RETURN_ON_ERR(ret);
|
||||
esp_lcd_dpi_panel_config_t dpi_config = {
|
||||
.num_fbs = mipi_cfg->fb_num,
|
||||
.virtual_channel = 0,
|
||||
.dpi_clk_src = MIPI_DSI_DPI_CLK_SRC_DEFAULT,
|
||||
.dpi_clock_freq_mhz = mipi_cfg->dpi_clk,
|
||||
.pixel_format = mipi_cfg->bit_depth == 24 ? LCD_COLOR_PIXEL_FORMAT_RGB888 : LCD_COLOR_PIXEL_FORMAT_RGB565,
|
||||
.video_timing = {
|
||||
.h_size = cfg->width,
|
||||
.v_size = cfg->height,
|
||||
.hsync_back_porch = mipi_cfg->dsi_hbp,
|
||||
.hsync_pulse_width = mipi_cfg->dsi_hsync,
|
||||
.hsync_front_porch = mipi_cfg->dsi_hfp,
|
||||
.vsync_back_porch = mipi_cfg->dsi_vbp,
|
||||
.vsync_pulse_width = mipi_cfg->dsi_vsync,
|
||||
.vsync_front_porch = mipi_cfg->dsi_vfp,
|
||||
},
|
||||
.flags.use_dma2d = true,
|
||||
};
|
||||
esp_lcd_panel_dev_config_t panel_config = {
|
||||
.bits_per_pixel = mipi_cfg->bit_depth,
|
||||
.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB,
|
||||
.reset_gpio_num = cfg->reset_pin,
|
||||
};
|
||||
if (cfg->width == 1024 && cfg->height == 600) {
|
||||
ESP_LOGI(TAG, "Install EK79007 LCD control panel");
|
||||
esp_lcd_dpi_panel_config_t dpi_config = EK79007_1024_600_PANEL_60HZ_CONFIG(LCD_COLOR_PIXEL_FORMAT_RGB565);
|
||||
ek79007_vendor_config_t vendor_config = {
|
||||
.mipi_config = {
|
||||
.dsi_bus = mipi_dsi_bus,
|
||||
.dpi_config = &dpi_config,
|
||||
},
|
||||
};
|
||||
panel_config.vendor_config = &vendor_config;
|
||||
ret = esp_lcd_new_panel_ek79007(mipi_dbi_io, &panel_config, &panel_handle);
|
||||
RETURN_ON_ERR(ret);
|
||||
} else {
|
||||
ili9881c_vendor_config_t vendor_config = {
|
||||
.mipi_config = {
|
||||
.dsi_bus = mipi_dsi_bus,
|
||||
.dpi_config = &dpi_config,
|
||||
.lane_num = mipi_cfg->lane_num,
|
||||
},
|
||||
};
|
||||
panel_config.vendor_config = &vendor_config;
|
||||
ret = esp_lcd_new_panel_ili9881c(mipi_dbi_io, &panel_config, &panel_handle);
|
||||
}
|
||||
RETURN_ON_ERR(ret);
|
||||
esp_lcd_panel_reset(panel_handle);
|
||||
ESP_LOGI(TAG, "Install MIPI DSI LCD data panel");
|
||||
return ret;
|
||||
}
|
||||
#else
|
||||
|
||||
static int _init_mipi_lcd(lcd_cfg_t *cfg)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static int _init_lcd(lcd_cfg_t *cfg)
|
||||
{
|
||||
int ret = 0;
|
||||
if (cfg->io_type != EXTENT_IO_TYPE_NONE) {
|
||||
ret = init_extend_io(cfg);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
// Config reset and ctrl gpio dir
|
||||
if (cfg->reset_pin >= 0) {
|
||||
set_pin_dir(cfg->reset_pin, true);
|
||||
}
|
||||
if (cfg->ctrl_pin >= 0) {
|
||||
set_pin_dir(cfg->ctrl_pin, true);
|
||||
}
|
||||
if (cfg->bus_type == LCD_BUS_TYPE_SPI) {
|
||||
if (cfg->spi_cfg.cs >= 0) {
|
||||
set_pin_dir(cfg->spi_cfg.cs, true);
|
||||
}
|
||||
}
|
||||
_lcd_rest(cfg);
|
||||
if (cfg->ctrl_pin >= 0) {
|
||||
set_pin_dir(cfg->ctrl_pin, true);
|
||||
}
|
||||
if (cfg->bus_type == LCD_BUS_TYPE_SPI) {
|
||||
ret = _init_spi_lcd(cfg);
|
||||
} else if (cfg->bus_type == LCD_BUS_TYPE_MIPI) {
|
||||
ret = _init_mipi_lcd(cfg);
|
||||
}
|
||||
if (panel_handle) {
|
||||
ret = esp_lcd_panel_init(panel_handle);
|
||||
RETURN_ON_ERR(ret);
|
||||
if (cfg->color_inv) {
|
||||
ret = esp_lcd_panel_invert_color(panel_handle, cfg->color_inv);
|
||||
}
|
||||
// ret = esp_lcd_panel_set_gap(panel_handle, 0, 0);
|
||||
if (cfg->swap_xy) {
|
||||
ret = esp_lcd_panel_swap_xy(panel_handle, cfg->swap_xy);
|
||||
}
|
||||
if (cfg->mirror_x || cfg->mirror_y) {
|
||||
ret = esp_lcd_panel_mirror(panel_handle, cfg->mirror_x, cfg->mirror_y);
|
||||
}
|
||||
ret = esp_lcd_panel_disp_on_off(panel_handle, true);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int board_lcd_init(void)
|
||||
{
|
||||
lcd_cfg_t cfg = { 0 };
|
||||
int ret = get_lcd_cfg(&cfg);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
return _init_lcd(&cfg);
|
||||
}
|
||||
|
||||
void *board_get_lcd_handle(void)
|
||||
{
|
||||
if (panel_handle) {
|
||||
return panel_handle;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
Reference in New Issue
Block a user