Strange behavior with ST7123 (MIPI-DSI) and P4
Posted: Mon Jul 20, 2026 8:04 pm
Hi everyone! I recently bought an M5Stack Tab5 with the ST7123 (MIPI) display. While it works fine with the demo firmware, it won't work at all when I try to use the IDF library (`esp_lcd_st7123`) and LVGL (IDF v6.0.1, P4 v1.3).
I’ve tried hundreds of different parameters, but nothing gets it working correctly; the display always ends up flickering, showing a black screen, or looking weird. The closest I’ve come to success was a blue screen with a rectangle in the middle, but something is clearly wrong—there’s a black line between the pixels that shouldn't be there.
Can anyone help? I’ve never worked with the P4 chip or complex displays in embedded systems before; I bought this specifically to learn, but I’m already stuck at the LCD initialization stage. I’ve tried following the library examples and various repositories, but none of them worked.
Black lines in image: https://www.pasteboard.co/bZsb6OQ2qyeH.png
I’ve tried hundreds of different parameters, but nothing gets it working correctly; the display always ends up flickering, showing a black screen, or looking weird. The closest I’ve come to success was a blue screen with a rectangle in the middle, but something is clearly wrong—there’s a black line between the pixels that shouldn't be there.
Can anyone help? I’ve never worked with the P4 chip or complex displays in embedded systems before; I bought this specifically to learn, but I’m already stuck at the LCD initialization stage. I’ve tried following the library examples and various repositories, but none of them worked.
Black lines in image: https://www.pasteboard.co/bZsb6OQ2qyeH.png
Code: Select all
ESP_LOGI(__func__, "Init MIPI DSI PHY");
esp_ldo_channel_handle_t ldo_mipi_phy = {};
esp_ldo_channel_config_t ldo_mipi_phy_config;
memset(&ldo_mipi_phy_config, 0, sizeof(esp_ldo_channel_config_t));
ldo_mipi_phy_config.chan_id = 3;
ldo_mipi_phy_config.voltage_mv = 2500;
ESP_ERROR_CHECK(esp_ldo_acquire_channel(&ldo_mipi_phy_config, &ldo_mipi_phy));
//Reset display
expa1.write(4, 0); expa1.write(5, 0);
delay_ms(200);
expa1.write(4, 1); expa1.write(5, 1); delay_ms(200);
ESP_LOGI(__func__, "Init MIPI DSI bus");
esp_lcd_dsi_bus_handle_t mipi_dsi_bus = {};
esp_lcd_dsi_bus_config_t bus_config;
memset(&bus_config, 0, sizeof(esp_lcd_dsi_bus_config_t));
bus_config.bus_id = 0;
bus_config.num_data_lanes = 2;
bus_config.lane_bit_rate_mbps = 1300;
bus_config.phy_clk_src = MIPI_DSI_PHY_PLLREF_CLK_SRC_DEFAULT_LEGACY;
bus_config.flags.clock_lane_force_hs = true;
ESP_ERROR_CHECK(esp_lcd_new_dsi_bus(&bus_config, &mipi_dsi_bus));
ESP_LOGI(__func__, "Init panel IO");
esp_lcd_panel_io_handle_t mipi_dbi_io = {};
esp_lcd_dbi_io_config_t dbi_config = ST7123_PANEL_IO_DBI_CONFIG();
ESP_ERROR_CHECK(esp_lcd_new_panel_io_dbi(mipi_dsi_bus, &dbi_config, &mipi_dbi_io));
ESP_LOGI(__func__, "Init panel driver");
//esp_lcd_panel_handle_t panel_handle = {};
esp_lcd_dpi_panel_config_t dpi_config;
memset(&dpi_config, 0, sizeof(esp_lcd_dpi_panel_config_t));
//ST7123
dpi_config.virtual_channel = 0;
dpi_config.dpi_clk_src = MIPI_DSI_DPI_CLK_SRC_DEFAULT;
dpi_config.dpi_clock_freq_mhz = 78;
dpi_config.in_color_format = LCD_COLOR_FMT_RGB888;
dpi_config.out_color_format = LCD_COLOR_FMT_RGB888;
dpi_config.num_fbs = 2;
dpi_config.video_timing.h_size = 720;
dpi_config.video_timing.v_size = 1280;
dpi_config.video_timing.hsync_pulse_width = 2;
dpi_config.video_timing.hsync_back_porch = 40;
dpi_config.video_timing.hsync_front_porch = 40;
dpi_config.video_timing.vsync_pulse_width = 2;
dpi_config.video_timing.vsync_back_porch = 4;
dpi_config.video_timing.vsync_front_porch = 320;
dpi_config.flags.disable_lp = false;
st7123_vendor_config_t vendor_config;
memset(&vendor_config, 0, sizeof(st7123_vendor_config_t));
vendor_config.init_cmds = NULL;
vendor_config.init_cmds_size = 0;
//vendor_config.init_cmds = lcd_init_cmds;
//vendor_config.init_cmds_size = sizeof(vendor_specific_init_default) / sizeof(st7123_lcd_init_cmd_t);
vendor_config.mipi_config.dsi_bus = mipi_dsi_bus;
vendor_config.mipi_config.dpi_config = &dpi_config;
esp_lcd_panel_dev_config_t panel_config;
memset(&panel_config, 0, sizeof(esp_lcd_panel_dev_config_t));
panel_config.data_endian = LCD_RGB_DATA_ENDIAN_BIG;
panel_config.reset_gpio_num = GPIO_NUM_NC;
panel_config.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB;
panel_config.bits_per_pixel = 24;
panel_config.vendor_config = &vendor_config;
ESP_ERROR_CHECK(esp_lcd_new_panel_st7123(mipi_dbi_io, &panel_config, &panel_handle));
ESP_ERROR_CHECK(esp_lcd_panel_reset(panel_handle));
ESP_ERROR_CHECK(esp_lcd_panel_init(panel_handle));
ESP_ERROR_CHECK(esp_lcd_panel_disp_on_off(panel_handle, true));
Code: Select all
lv_init();
// 2. Aloca um buffer simples em RAM (ex: 1/10 da tela)
size_t buf_size = 720 * 1280 * sizeof(lv_color_t);
uint8_t *buf = (uint8_t *)heap_caps_malloc(buf_size, MALLOC_CAP_SPIRAM);
memset(buf, 0, buf_size);
// 3. Cria a interface do display no LVGL
lv_display_t *disp = lv_display_create(720, 1280);
lv_display_set_color_format(disp, LV_COLOR_FORMAT_RGB888);
lv_display_set_buffers(disp, buf, NULL, buf_size, LV_DISPLAY_RENDER_MODE_PARTIAL);
lv_display_set_flush_cb(disp, lvgl_flush_cb);
lv_display_set_user_data(disp, panel_handle);
// 4. Desenha elementos básicos na tela ativa
lv_obj_t *scr = lv_screen_active();
// Fundo Vermelho Sólido
lv_obj_set_style_bg_color(scr, lv_palette_main(LV_PALETTE_BLUE), 0);
lv_obj_set_style_bg_opa(scr, LV_OPA_COVER, 0);
// Caixinha Branca no Centro
lv_obj_t *box = lv_obj_create(scr);
lv_obj_set_size(box, 300, 150);
lv_obj_align(box, LV_ALIGN_CENTER, 0, 0);
// Texto dentro da caixinha
lv_obj_t *label = lv_label_create(box);
lv_label_set_text(label, "LVGL OK!");
lv_obj_align(label, LV_ALIGN_CENTER, 0, 0);