Skip to content

drivers: mipi dsi: Add dsi dwc driver support #93134

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions boards/nxp/imx95_evk/imx95_evk-pinctrl.dtsi
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,17 @@
};
};

lpi2c2_default: lpi2c2_default {
group0 {
pinmux = <&iomuxc_i2c2_scl_lpi2c_scl_lpi2c2_scl>,
<&iomuxc_i2c2_sda_lpi2c_sda_lpi2c2_sda>;
drive-open-drain;
slew-rate = "slightly_fast";
drive-strength = "x4";
input-enable;
};
};

lpi2c5_default: lpi2c5_default {
group0 {
pinmux = <&iomuxc_gpio_io23_lpi2c_scl_lpi2c5_scl>,
Expand Down
56 changes: 55 additions & 1 deletion boards/nxp/imx95_evk/imx95_evk_mimx9596_m7.dts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2024 NXP
* Copyright 2024-2025 NXP
*
* SPDX-License-Identifier: Apache-2.0
*/
Expand Down Expand Up @@ -90,6 +90,25 @@
};
};

&lpi2c2 {
pinctrl-0 = <&lpi2c2_default>;
pinctrl-names = "default";
status = "okay";
mfd0:adp5585@34 {
compatible = "adi,adp5585";
reg = <0x34>;
status = "okay";
gpio_exp0: adp5585_gpio {
compatible = "adi,adp5585-gpio";
gpio-controller;
#gpio-cells = <2>;
ngpios = <13>;
gpio-reserved-ranges = <5 3>;
status = "okay";
};
};
};

&lpi2c5 {
pinctrl-0 = <&lpi2c5_default>;
pinctrl-names = "default";
Expand Down Expand Up @@ -140,3 +159,38 @@
&edma2 {
status = "okay";
};

&dpu {
status = "okay";
width = <1080>;
height = <2340>;
hsw = <4>;
hfp = <12>;
hbp = <8>;
vsw = <4>;
vfp = <10>;
vbp = <10>;
};

&mipi_dsi {
status = "okay";
compatible = "nxp,mipi-dsi-dwc";
dpi-color-coding = "24-bit";
dpi-video-mode = "non-burst-sync-pulse";
dphy-ref-frequency = <24000000>;
data-rate-clock = <890666664>;
nxp,dc = <&dpu>;
width = <1080>;
height = <2340>;
rm692c9@0 {
status = "okay";
compatible = "raydium,rm692c9";
reg = <0x0>;
width = <1080>;
height = <2340>;
reset-gpios = <&gpio_exp0 8 GPIO_ACTIVE_HIGH>;
bl-gpios = <&gpio_exp0 4 GPIO_ACTIVE_HIGH>;
data-lanes = <4>;
pixel-format = <0>;
};
};
1 change: 1 addition & 0 deletions drivers/display/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ zephyr_library_sources_ifdef(CONFIG_ST7796S display_st7796s.c)
zephyr_library_sources_ifdef(CONFIG_STM32_LTDC display_stm32_ltdc.c)
zephyr_library_sources_ifdef(CONFIG_RM68200 display_rm68200.c)
zephyr_library_sources_ifdef(CONFIG_RM67162 display_rm67162.c)
zephyr_library_sources_ifdef(CONFIG_RM692C9 display_rm692c9.c)
zephyr_library_sources_ifdef(CONFIG_HX8394 display_hx8394.c)
zephyr_library_sources_ifdef(CONFIG_GC9X01X display_gc9x01x.c)
zephyr_library_sources_ifdef(CONFIG_LED_STRIP_MATRIX display_led_strip_matrix.c)
Expand Down
1 change: 1 addition & 0 deletions drivers/display/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ source "drivers/display/Kconfig.dummy"
source "drivers/display/Kconfig.ls0xx"
source "drivers/display/Kconfig.rm67162"
source "drivers/display/Kconfig.rm68200"
source "drivers/display/Kconfig.rm692c9"
source "drivers/display/Kconfig.max7219"
source "drivers/display/Kconfig.intel_multibootfb"
source "drivers/display/Kconfig.mcux_dcnano_lcdif"
Expand Down
10 changes: 10 additions & 0 deletions drivers/display/Kconfig.rm692c9
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Copyright 2025, NXP
# SPDX-License-Identifier: Apache-2.0

config RM692C9
bool "RM692C9 display driver"
default y
select MIPI_DSI
depends on DT_HAS_RAYDIUM_RM692C9_ENABLED
help
Enable driver for RM692C9 display driver.
188 changes: 188 additions & 0 deletions drivers/display/display_rm692c9.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
/*
* Copyright 2025, NXP
*
* SPDX-License-Identifier: Apache-2.0
*/

#define DT_DRV_COMPAT raydium_rm692c9

#include <zephyr/drivers/display.h>
#include <zephyr/drivers/mipi_dsi.h>
#include <zephyr/drivers/gpio.h>
#include <zephyr/device.h>
#include <zephyr/kernel.h>
#include <zephyr/logging/log.h>
#include <zephyr/pm/policy.h>
#include <zephyr/pm/device.h>
#include <zephyr/sys/byteorder.h>

LOG_MODULE_REGISTER(rm692c9, CONFIG_DISPLAY_LOG_LEVEL);

#define MIPI_DCS_SET_DSI_MODE 0xC2
/*
* These commands are taken from NXP's MCUXpresso SDK.
* Additional documentation is added where possible, but the
* Manufacture command set pages are not described in the datasheet
*/
static const struct {
uint8_t cmd;
uint8_t param;
} rm692c9_init_1080x2340[] = {
/* CMD Mode switch, select manufacture command set page 0 */
{.cmd = 0xFE, .param = 0x00},
{.cmd = 0xC2, .param = 0x08},
{.cmd = 0x35, .param = 0x00},
};

struct rm692c9_config {
const struct device *mipi_dsi;
uint8_t channel;
uint8_t num_of_lanes;
uint8_t pixel_format;
const struct gpio_dt_spec reset_gpio;
const struct gpio_dt_spec bl_gpio;
uint16_t panel_width;
uint16_t panel_height;
};

static int rm692c9_init(const struct device *dev)
{
const struct rm692c9_config *config = dev->config;
struct mipi_dsi_device mdev = {0};
int ret;
uint32_t i;
uint8_t cmd, param;

/* Attach to MIPI DSI host */
mdev.data_lanes = config->num_of_lanes;

ret = mipi_dsi_attach(config->mipi_dsi, config->channel, &mdev);
if (ret < 0) {
LOG_ERR("Could not attach to MIPI-DSI host");
return ret;
}

if (config->reset_gpio.port != NULL) {
ret = gpio_pin_configure_dt(&config->reset_gpio, GPIO_OUTPUT_INACTIVE);
if (ret < 0) {
LOG_ERR("Could not configure reset GPIO (%d)", ret);
return ret;
}

/*
* Power to the display has been enabled via the regulator fixed api during
* regulator init. Per datasheet, we must wait at least 10ms before
* starting reset sequence after power on.
*/
k_sleep(K_MSEC(10));
/* Start reset sequence */
ret = gpio_pin_set_dt(&config->reset_gpio, 0);
if (ret < 0) {
LOG_ERR("Could not pull reset low (%d)", ret);
return ret;
}
/* Per datasheet, reset low pulse width should be at least 10usec */
k_sleep(K_USEC(30));
gpio_pin_set_dt(&config->reset_gpio, 1);
if (ret < 0) {
LOG_ERR("Could not pull reset high (%d)", ret);
return ret;
}
/*
* It is necessary to wait at least 120msec after releasing reset,
* before sending additional commands. This delay can be 5msec
* if we are certain the display module is in SLEEP IN state,
* but this is not guaranteed (for example, with a warm reset)
*/
k_sleep(K_MSEC(150));
}
if (config->bl_gpio.port != NULL) {
ret = gpio_pin_configure_dt(&config->bl_gpio, GPIO_OUTPUT_ACTIVE);
if (ret < 0) {
LOG_ERR("Could not configure bl GPIO (%d)", ret);
return ret;
}
}

/* Now, write initialization settings for display, running at */
for (i = 0; i < ARRAY_SIZE(rm692c9_init_1080x2340); i++) {
cmd = rm692c9_init_1080x2340[i].cmd;
param = rm692c9_init_1080x2340[i].param;
ret = mipi_dsi_dcs_write(config->mipi_dsi, config->channel, cmd, &param, 1);
if (ret < 0) {
return ret;
}
}
k_sleep(K_MSEC(80));

ret = mipi_dsi_dcs_write(config->mipi_dsi, config->channel, MIPI_DCS_SOFT_RESET, NULL, 0);
if (ret < 0) {
return ret;
}

/* Delay 80 ms before enter DSI mode */
k_sleep(K_MSEC(80));

/* need to set DSI MODE and brightness */
param = 0x0B;
ret = mipi_dsi_dcs_write(config->mipi_dsi, config->channel, MIPI_DCS_SET_DSI_MODE, &param,
1);
if (ret < 0) {
return ret;
}

param = 0xFF;
ret = mipi_dsi_dcs_write(config->mipi_dsi, config->channel, MIPI_DCS_SET_DISPLAY_BRIGHTNESS,
&param, 1);
if (ret < 0) {
return ret;
}

/* Delay 50 ms before exiting sleep mode */
k_sleep(K_MSEC(50));

ret = mipi_dsi_dcs_write(config->mipi_dsi, config->channel, MIPI_DCS_EXIT_SLEEP_MODE, NULL,
0);
if (ret < 0) {
return ret;
}
/*
* We must wait 5 ms after exiting sleep mode before sending additional
* commands. If we intend to enter sleep mode, we must delay
* 120 ms before sending that command. To be safe, delay 150ms
*/
k_sleep(K_MSEC(150));

/* Now, enable display */
ret = mipi_dsi_dcs_write(config->mipi_dsi, config->channel, MIPI_DCS_SET_DISPLAY_ON, NULL,
0);
if (ret < 0) {
return ret;
}

k_sleep(K_MSEC(100));

ret = mipi_dsi_detach(config->mipi_dsi, config->channel, &mdev);
if (ret < 0) {
LOG_ERR("Could not detach to MIPI-DSI host");
return ret;
}

return 0;
}

#define RM692C9_PANEL(id) \
static const struct rm692c9_config rm692c9_config_##id = { \
.mipi_dsi = DEVICE_DT_GET(DT_INST_BUS(id)), \
.reset_gpio = GPIO_DT_SPEC_INST_GET_OR(id, reset_gpios, {0}), \
.bl_gpio = GPIO_DT_SPEC_INST_GET_OR(id, bl_gpios, {0}), \
.channel = DT_INST_REG_ADDR(id), \
.panel_width = DT_INST_PROP(id, width), \
.pixel_format = DT_INST_PROP(id, pixel_format), \
.panel_height = DT_INST_PROP(id, height), \
.num_of_lanes = DT_INST_PROP_BY_IDX(id, data_lanes, 0), \
}; \
DEVICE_DT_INST_DEFINE(id, &rm692c9_init, NULL, NULL, &rm692c9_config_##id, POST_KERNEL, \
CONFIG_APPLICATION_INIT_PRIORITY, NULL);

DT_INST_FOREACH_STATUS_OKAY(RM692C9_PANEL)
1 change: 1 addition & 0 deletions drivers/mipi_dsi/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
zephyr_sources_ifdef(CONFIG_MIPI_DSI mipi_dsi.c)
zephyr_sources_ifdef(CONFIG_MIPI_DSI_MCUX dsi_mcux.c)
zephyr_sources_ifdef(CONFIG_MIPI_DSI_MCUX_2L dsi_mcux_2l.c)
zephyr_sources_ifdef(CONFIG_MIPI_DSI_DWC dsi_dwc.c)
zephyr_sources_ifdef(CONFIG_MIPI_DSI_STM32 dsi_stm32.c)
zephyr_sources_ifdef(CONFIG_MIPI_DSI_TEST dsi_test.c)
zephyr_sources_ifdef(CONFIG_MIPI_DSI_RENESAS_RA dsi_renesas_ra.c)
7 changes: 7 additions & 0 deletions drivers/mipi_dsi/Kconfig.mcux
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,10 @@ config MIPI_DSI_MCUX_2L_SWAP16


endif # MIPI_DSI_MCUX_2L

config MIPI_DSI_DWC
bool "NXP DWC MIPI-DSI Host Controller"
default y
depends on DT_HAS_NXP_MIPI_DSI_DWC_ENABLED
help
NXP MIPI DSI DWC controller driver
Loading