drivers: mipi dsi: Add dsi nxp dwc driver support
Added mipi dsi nxp dwc driver support
Signed-off-by: Ruoshan Shi <ruoshan.shi@nxp.com>
diff --git a/drivers/mipi_dsi/CMakeLists.txt b/drivers/mipi_dsi/CMakeLists.txt
index eb28fb9..614e860 100644
--- a/drivers/mipi_dsi/CMakeLists.txt
+++ b/drivers/mipi_dsi/CMakeLists.txt
@@ -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_NXP_DWC dsi_nxp_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)
diff --git a/drivers/mipi_dsi/Kconfig.mcux b/drivers/mipi_dsi/Kconfig.mcux
index af624e6..7388060 100644
--- a/drivers/mipi_dsi/Kconfig.mcux
+++ b/drivers/mipi_dsi/Kconfig.mcux
@@ -43,3 +43,10 @@
endif # MIPI_DSI_MCUX_2L
+
+config MIPI_DSI_NXP_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
diff --git a/drivers/mipi_dsi/dsi_nxp_dwc.c b/drivers/mipi_dsi/dsi_nxp_dwc.c
new file mode 100644
index 0000000..886e060
--- /dev/null
+++ b/drivers/mipi_dsi/dsi_nxp_dwc.c
@@ -0,0 +1,201 @@
+/*
+ * Copyright 2025 NXP
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#define DT_DRV_COMPAT nxp_mipi_dsi_dwc
+
+#include <fsl_clock.h>
+#include <fsl_mipi_dsi.h>
+#include <soc.h>
+#include <zephyr/drivers/clock_control.h>
+#include <zephyr/drivers/mipi_dsi.h>
+#include <zephyr/kernel.h>
+#include <zephyr/logging/log.h>
+
+LOG_MODULE_REGISTER(dsi_dwc, CONFIG_MIPI_DSI_LOG_LEVEL);
+
+struct dwc_mipi_dsi_config {
+ MIPI_DSI_Type *base;
+ dsi_dpi_config_t dpi_config;
+ bool noncontinuous_hs_clk;
+ dsi_config_t dsi_config;
+ uint32_t dphy_ref_frequency;
+ uint32_t data_rate_clock;
+ const struct device *dev;
+};
+
+struct dwc_mipi_dsi_data {
+ uint16_t flags;
+ uint8_t lane_mask;
+};
+
+static int dsi_dwc_attach(const struct device *dev, uint8_t channel,
+ const struct mipi_dsi_device *mdev)
+{
+ const struct dwc_mipi_dsi_config *config = dev->config;
+ dsi_dphy_config_t dphy_config;
+ dsi_config_t dsi_config;
+ uint32_t phy_hsfreqrange;
+
+ DSI_GetDefaultConfig(&dsi_config);
+ dphy_config.numLanes = mdev->data_lanes;
+ dsi_config.enableNoncontinuousClk = config->noncontinuous_hs_clk;
+
+ /* Init the DSI module. */
+ DSI_Init(config->base, &dsi_config);
+
+ DSI_SetDpiConfig(config->base, &config->dpi_config, mdev->data_lanes);
+
+ /* Calculate data rate per line */
+ DSI_GetDefaultDphyConfig(&dphy_config, config->data_rate_clock * mdev->data_lanes / 8,
+ mdev->data_lanes);
+ DSI_InitDphy(config->base, &dphy_config);
+ phy_hsfreqrange = Pll_Set_Hs_Freqrange(config->data_rate_clock);
+#if CONFIG_SOC_MIMX9596_M7
+ CAMERA__DSI_OR_CSI_PHY_CSR->COMBO_PHY_FREQ_CONTROL =
+ CAMERA_DSI_OR_CSI_PHY_CSR_COMBO_PHY_FREQ_CONTROL_Phy_hsfreqrange(phy_hsfreqrange) |
+ CAMERA_DSI_OR_CSI_PHY_CSR_COMBO_PHY_FREQ_CONTROL_Phy_cfgclkfreqrange(0x1CU);
+ CAMERA__DSI_MASTER_CSR->DSI_PIXEL_LINK_CONTROL =
+ CAMERA_DSI_MASTER_CSR_DSI_PIXEL_LINK_CONTROL_Pixel_link_sel(0x0);
+ DISPLAY__BLK_CTRL_DISPLAYMIX->PIXEL_LINK_CTRL =
+ (DISPLAY_BLK_CTRL_DISPLAYMIX_PIXEL_LINK_CTRL_PL0_enable(0x1) |
+ DISPLAY_BLK_CTRL_DISPLAYMIX_PIXEL_LINK_CTRL_PL0_valid(0x1));
+ CAMERA__DSI_OR_CSI_PHY_CSR->COMBO_PHY_MODE_CONTROL = 0x3U;
+#endif
+ DSI_ConfigDphy(config->base, config->dphy_ref_frequency, config->data_rate_clock);
+ status_t result = DSI_PowerUp(config->base);
+
+ if (result != 0U) {
+ LOG_ERR("DSI PHY init failed.\r\n");
+ }
+
+ return result;
+}
+
+static ssize_t dsi_dwc_transfer(const struct device *dev, uint8_t channel, struct mipi_dsi_msg *msg)
+{
+ const struct dwc_mipi_dsi_config *config = dev->config;
+ dsi_transfer_t dsi_xfer = {0};
+ status_t status;
+
+ dsi_xfer.virtualChannel = channel;
+ dsi_xfer.txDataSize = msg->tx_len;
+ dsi_xfer.txData = msg->tx_buf;
+ dsi_xfer.rxDataSize = msg->rx_len;
+ dsi_xfer.rxData = msg->rx_buf;
+ switch (msg->type) {
+ case MIPI_DSI_DCS_READ:
+ LOG_ERR("DCS Read not yet implemented or used");
+ return -ENOTSUP;
+ case MIPI_DSI_DCS_SHORT_WRITE:
+ dsi_xfer.sendDcsCmd = true;
+ dsi_xfer.dcsCmd = msg->cmd;
+ dsi_xfer.txDataType = kDSI_TxDataDcsShortWrNoParam;
+ break;
+ case MIPI_DSI_DCS_SHORT_WRITE_PARAM:
+ dsi_xfer.sendDcsCmd = true;
+ dsi_xfer.dcsCmd = msg->cmd;
+ dsi_xfer.txDataType = kDSI_TxDataDcsShortWrOneParam;
+ break;
+ case MIPI_DSI_DCS_LONG_WRITE:
+ dsi_xfer.sendDcsCmd = true;
+ dsi_xfer.dcsCmd = msg->cmd;
+ dsi_xfer.txDataType = kDSI_TxDataDcsLongWr;
+ break;
+ case MIPI_DSI_GENERIC_SHORT_WRITE_0_PARAM:
+ dsi_xfer.txDataType = kDSI_TxDataGenShortWrNoParam;
+ break;
+ case MIPI_DSI_GENERIC_SHORT_WRITE_1_PARAM:
+ dsi_xfer.txDataType = kDSI_TxDataGenShortWrOneParam;
+ break;
+ case MIPI_DSI_GENERIC_SHORT_WRITE_2_PARAM:
+ dsi_xfer.txDataType = kDSI_TxDataGenShortWrTwoParam;
+ break;
+ case MIPI_DSI_GENERIC_LONG_WRITE:
+ dsi_xfer.txDataType = kDSI_TxDataGenLongWr;
+ break;
+ case MIPI_DSI_GENERIC_READ_REQUEST_0_PARAM:
+ __fallthrough;
+ case MIPI_DSI_GENERIC_READ_REQUEST_1_PARAM:
+ __fallthrough;
+ case MIPI_DSI_GENERIC_READ_REQUEST_2_PARAM:
+ LOG_ERR("Generic Read not yet implemented or used");
+ return -ENOTSUP;
+ default:
+ LOG_ERR("Unsupported message type (%d)", msg->type);
+ return -ENOTSUP;
+ }
+
+ status = DSI_TransferBlocking(config->base, &dsi_xfer);
+
+ if (status != kStatus_Success) {
+ LOG_ERR("Transmission failed");
+ return -EIO;
+ }
+
+ if (msg->rx_len != 0) {
+ /* Return rx_len on a read */
+ return dsi_xfer.rxDataSize;
+ }
+
+ /* Return tx_len on a write */
+ return dsi_xfer.txDataSize;
+}
+
+static int dsi_dwc_detach(const struct device *dev, uint8_t channel,
+ const struct mipi_dsi_device *mdev)
+{
+ const struct dwc_mipi_dsi_config *config = dev->config;
+
+ DSI_EnableCommandMode(config->base, false);
+
+ return 0;
+}
+
+static DEVICE_API(mipi_dsi, dsi_dwc_api) = {
+ .attach = dsi_dwc_attach,
+ .transfer = dsi_dwc_transfer,
+ .detach = dsi_dwc_detach,
+};
+
+static int dwc_mipi_dsi_init(const struct device *dev)
+{
+ return 0;
+}
+
+#define DWC_DSI_DPI_CONFIG(id) \
+ IF_ENABLED(DT_NODE_HAS_PROP(DT_DRV_INST(id), nxp_dc), \
+ (.dpi_config = { \
+ .virtualChannel = 0U, \
+ .colorCoding = DT_INST_ENUM_IDX(id, dpi_color_coding), \
+ .videoMode = DT_INST_ENUM_IDX(id, dpi_video_mode), \
+ .pixelPayloadSize = DT_INST_PROP_BY_PHANDLE(id, nxp_dc, width), \
+ .panelHeight = DT_INST_PROP_BY_PHANDLE(id, nxp_dc, height), \
+ .enableAck = false, \
+ .enablelpSwitch = true, \
+ .pattern = kDSI_PatternDisable, \
+ .polarityFlags = (kDSI_DpiVsyncActiveLow | kDSI_DpiHsyncActiveLow), \
+ .hfp = DT_INST_PROP_BY_PHANDLE(id, nxp_dc, hfp), \
+ .hbp = DT_INST_PROP_BY_PHANDLE(id, nxp_dc, hbp), \
+ .hsw = DT_INST_PROP_BY_PHANDLE(id, nxp_dc, hsw), \
+ .vfp = DT_INST_PROP_BY_PHANDLE(id, nxp_dc, vfp), \
+ .vbp = DT_INST_PROP_BY_PHANDLE(id, nxp_dc, vbp), \
+ .vsw = DT_INST_PROP_BY_PHANDLE(id, nxp_dc, vsw), \
+ }))
+
+#define DWC_MIPI_DSI_DEVICE(id) \
+ static const struct dwc_mipi_dsi_config mipi_dsi_config_##id = { \
+ .base = (MIPI_DSI_Type *)DT_INST_REG_ADDR(id), \
+ .data_rate_clock = DT_INST_PROP(id, data_rate_clock), \
+ .dphy_ref_frequency = DT_INST_PROP(id, dphy_ref_frequency), \
+ DWC_DSI_DPI_CONFIG(id), \
+ }; \
+ \
+ static struct dwc_mipi_dsi_data mipi_dsi_data_##id; \
+ DEVICE_DT_INST_DEFINE(id, &dwc_mipi_dsi_init, NULL, &mipi_dsi_data_##id, \
+ &mipi_dsi_config_##id, POST_KERNEL, CONFIG_MIPI_DSI_INIT_PRIORITY, \
+ &dsi_dwc_api);
+
+DT_INST_FOREACH_STATUS_OKAY(DWC_MIPI_DSI_DEVICE)
diff --git a/dts/bindings/mipi-dsi/nxp,mipi-dsi-dwc.yaml b/dts/bindings/mipi-dsi/nxp,mipi-dsi-dwc.yaml
new file mode 100644
index 0000000..d830780
--- /dev/null
+++ b/dts/bindings/mipi-dsi/nxp,mipi-dsi-dwc.yaml
@@ -0,0 +1,54 @@
+#
+# Copyright 2025 NXP
+#
+# SPDX-License-Identifier: Apache-2.0
+#
+description: NXP MCUX MIPI DSI DWC
+
+compatible: "nxp,mipi-dsi-dwc"
+
+include: [mipi-dsi-host.yaml, display-controller.yaml]
+
+properties:
+ interrupts:
+ required: true
+
+ nxp,dc:
+ type: phandle
+ description:
+ Instance of the display controller peripheral. Only required when using the MIPI
+ in video mode
+
+ dpi-color-coding:
+ type: string
+ enum:
+ - "16-bit-config-1"
+ - "16-bit-config-2"
+ - "16-bit-config-3"
+ - "18-bit-config-1"
+ - "18-bit-config-2"
+ - "24-bit"
+ description:
+ MIPI DPI interface color coding. Sets the distribution of RGB bits within
+ the 24-bit d bus, as specified by the DPI specification.
+
+ dpi-video-mode:
+ type: string
+ enum:
+ - "non-burst-sync-pulse"
+ - "non-burst-sync-event"
+ - "burst"
+ description:
+ DPI video mode.
+
+ dphy-ref-frequency:
+ type: int
+ required: true
+ description:
+ Maximum clock speed supported by the device, in Hz.
+
+ data-rate-clock:
+ type: int
+ description:
+ MIPI data rate clock frequency. Should be set to ensure clock frequency is equal to
+ (pixel clock * bits per pixel) / number of mipi data lanes
diff --git a/modules/hal_nxp/mcux/mcux-sdk-ng/drivers/drivers.cmake b/modules/hal_nxp/mcux/mcux-sdk-ng/drivers/drivers.cmake
index 9d3c620..6f47146 100644
--- a/modules/hal_nxp/mcux/mcux-sdk-ng/drivers/drivers.cmake
+++ b/modules/hal_nxp/mcux/mcux-sdk-ng/drivers/drivers.cmake
@@ -121,6 +121,7 @@
set_variable_ifdef(CONFIG_IMX_USDHC CONFIG_MCUX_COMPONENT_driver.usdhc)
set_variable_ifdef(CONFIG_MIPI_DSI_MCUX CONFIG_MCUX_COMPONENT_driver.mipi_dsi_split)
set_variable_ifdef(CONFIG_MIPI_DSI_MCUX_2L CONFIG_MCUX_COMPONENT_driver.mipi_dsi)
+set_variable_ifdef(CONFIG_MIPI_DSI_NXP_DWC CONFIG_MCUX_COMPONENT_driver.mipi_dsi_imx)
set_variable_ifdef(CONFIG_MCUX_SDIF CONFIG_MCUX_COMPONENT_driver.sdif)
set_variable_ifdef(CONFIG_MCUX_XBARA CONFIG_MCUX_COMPONENT_driver.xbara)
set_variable_ifdef(CONFIG_MCUX_XBARB CONFIG_MCUX_COMPONENT_driver.xbarb)