JC4880P443 - unable to setup

I followed instructions from here: [mipi_dsi] add guition JC4880P443 display by 23900 · Pull Request #12068 · esphome/esphome · GitHub

This is my config:

esphome:
  name: "lvgl2xl"
  friendly_name: LVGL2XL

esp32:
  board: esp32-p4-evboard
  cpu_frequency: 400MHz
  flash_size: 16MB
  framework:
    type: esp-idf
    advanced:
      enable_idf_experimental_features: yes 

display:
  - platform: mipi_dsi
    id: device_display
    model: JC4880P443
    byte_order: little_endian

When I try to install via USB from ESPHome I get this:

Configuration does not match the platform of the connected device. Expected an UNKNOWN device.

I get the option to Retry or Close, Retry gives me the same pop-up. On the USB side I’m able to select the correct port without issues.

Anything I’m missing?

Was it already merged to main?
Can you test it with this workaround: [mipi_dsi] add guition JC4880P443 display by 23900 · Pull Request #12068 · esphome/esphome · GitHub

Yes this device is mentioned in the 2025.12 ESPHome release notes.

And does it compile of you leave the display section out (commented)?

Try
variant: esp32p4

Instead of board.
(And clean build files)

Turns out that I needed more configuration items than what was provided in the documentation I linked and also the backlight does not turn on by default so I needed to fix that. Without backlight nothing shows up! I will post an updated yaml for reference so anyone stumbling on to this thread will have something to work with.

Ok perfect and if something is missing from the esphome docs, consider updating them.

Here’s a working configuration as promised:

esphome:
  name: "JC4880P443"
  friendly_name: JC4880P443
logger:
  level: DEBUG

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password

web_server:
  port: 80

ota:
  - platform: esphome

api:
  on_client_connected:
    - globals.set:
        id: homeassistant_ip
        value: !lambda return client_address;
font:
  - file: "gfonts://Montserrat"
    id: montserrat_28
    size: 28

output:
  - id: gpio_backlight_pwm
    platform: ledc
    pin: 23

light:
  - id: backlight
    name: Backlight
    platform: monochromatic
    output: gpio_backlight_pwm
    restore_mode: ALWAYS_ON


switch:
  - platform: restart
    name: Restart

binary_sensor:
  - platform: status
    name: Status

number:
  - platform: template
    name: Screen timeout
    optimistic: true
    id: display_timeout
    unit_of_measurement: "m"
    initial_value: 5 #minutes
    restore_value: true
    min_value: 0 #0 is no timeout
    max_value: 99
    step: 1
    mode: box


sensor:
  - id: wifi_signal_db
    name: WiFi Signal
    platform: wifi_signal
    update_interval: 60s
    entity_category: diagnostic

  - id: wifi_signal_strength
    name: WiFi Strength
    platform: copy
    source_id: wifi_signal_db
    filters:
      - lambda: return min(max(2 * (x + 100.0), 0.0), 100.0);
    unit_of_measurement: "%"
    entity_category: diagnostic

text_sensor:
  - platform: wifi_info
    ip_address:
      name: IP Address
      entity_category: diagnostic
    ssid:
      name: Connected SSID
      entity_category: diagnostic
    mac_address:
      name: Mac Address
      entity_category: diagnostic

globals:
  - id: homeassistant_ip
    type: std::string
  - id: backlight_brightness_level
    type: float
    restore_value: yes
    initial_value: '0.5'  # 50% default brightness

esp32:
  board: esp32-p4-evboard
  cpu_frequency: 400MHz
  flash_size: 16MB
  framework:
    type: esp-idf
    advanced:
      enable_idf_experimental_features: yes 

display:
  - platform: mipi_dsi
    id: device_display
    model: JC4880P443
    byte_order: little_endian
    rotation: 90
    lambda: |-
      it.fill(Color::BLACK);
      it.print(340, 100, id(montserrat_28), Color(0,255,0), TextAlign::LEFT, "Hello World1");
      it.print(340, 200, id(montserrat_28), Color::WHITE, TextAlign::LEFT, "Hello World2");
      it.print(340, 300, id(montserrat_28), Color(255,0,0), TextAlign::LEFT, "Hello World3");
touchscreen:
  platform: gt911
  i2c_id: i2c_bus
  id: device_touchscreen
  reset_pin: GPIO3
  update_interval: 100ms
  transform: #This is for 90 degree display rotation
    swap_xy: true
    mirror_x: false
    mirror_y: true
  on_update:
    then:
      - lambda: |-
          if (touches.size() > 0) {
            auto touch = touches[0];
            ESP_LOGI("TOUCH", "X=%d Y=%d", touch.x, touch.y);
          }
esp_ldo:
  - channel: 3
    voltage: 2.5V

psram:
  mode: hex
  speed: 200MHz

preferences:
  flash_write_interval: 5min

esp32_hosted:
  variant: ESP32C6
  reset_pin: GPIO54
  cmd_pin: GPIO19
  clk_pin: GPIO18
  d0_pin: GPIO14
  d1_pin: GPIO15
  d2_pin: GPIO16
  d3_pin: GPIO17
  active_high: true

i2c:
  id: i2c_bus
  sda: 7
  scl: 8
  scan: false
  frequency: 400kHz

# Audio section
audio_dac:
  - platform: es8311
    id: esp7311_dac
    address: 0x18
    i2c_id: i2c_bus

i2s_audio:
  - id: i2s_bus
    i2s_lrclk_pin: GPIO10 # WS / LRCK
    i2s_bclk_pin: GPIO12  # BCLK
    i2s_mclk_pin: GPIO13  # ES8311 usually requires a Master Clock

microphone:
  - platform: i2s_audio
    id: es8311_mic
    i2s_audio_id: i2s_bus
    i2s_din_pin: GPIO48  # Data In from the Codec
    adc_type: external
    pdm: false           # ES8311 uses standard I2S, not PDM
    channel: left

speaker:
  - platform: i2s_audio
    id: es8311_hardware_out
    i2s_audio_id: i2s_bus
    i2s_dout_pin: GPIO9
    dac_type: external
    audio_dac: esp7311_dac
  - platform: mixer
    id: audio_mixer
    output_speaker: es8311_hardware_out
    source_speakers:
      - id: spk_announcement
      - id: spk_media

media_player:
  - platform: speaker
    name: "XL Speaker"
    id: xl_media_player
    # This section is now mandatory for the 'speaker' platform
    announcement_pipeline:
      speaker: spk_announcement
    media_pipeline:
      speaker: spk_media

2 Likes

Here’s a sliding case for the board at thingiverse.