From 27800c2fd7ff6fd80bb8ae1ca0da882e152b8ca7 Mon Sep 17 00:00:00 2001 From: Mahesh Mahadevan Date: Mon, 4 Apr 2022 13:23:53 -0500 Subject: [PATCH] drivers: mipi: Add MIPI DSI driver for MXRT devices Add a MIPI DSI driver for the MIPI controller on NXP MXRT SoC'sUpdate MIPI_DSI Signed-off-by: Mahesh Mahadevan --- drivers/mipi_dsi/CMakeLists.txt | 1 + drivers/mipi_dsi/Kconfig | 2 + drivers/mipi_dsi/Kconfig.mcux | 11 ++ drivers/mipi_dsi/dsi_mcux.c | 207 ++++++++++++++++++++ dts/arm/nxp/nxp_rt11xx.dtsi | 2 +- dts/bindings/mipi-dsi/nxp,imx-mipi-dsi.yaml | 72 +++++++ 6 files changed, 294 insertions(+), 1 deletion(-) create mode 100644 drivers/mipi_dsi/Kconfig.mcux create mode 100644 drivers/mipi_dsi/dsi_mcux.c create mode 100644 dts/bindings/mipi-dsi/nxp,imx-mipi-dsi.yaml diff --git a/drivers/mipi_dsi/CMakeLists.txt b/drivers/mipi_dsi/CMakeLists.txt index f4ce3640bbe..14d40b3fb11 100644 --- a/drivers/mipi_dsi/CMakeLists.txt +++ b/drivers/mipi_dsi/CMakeLists.txt @@ -1 +1,2 @@ zephyr_sources_ifdef(CONFIG_MIPI_DSI mipi_dsi.c) +zephyr_sources_ifdef(CONFIG_MIPI_DSI_MCUX dsi_mcux.c) diff --git a/drivers/mipi_dsi/Kconfig b/drivers/mipi_dsi/Kconfig index 1eda786fc3e..35307b76558 100644 --- a/drivers/mipi_dsi/Kconfig +++ b/drivers/mipi_dsi/Kconfig @@ -21,4 +21,6 @@ config MIPI_DSI_INIT_PRIORITY help MIPI-DSI Host Controllers initialization priority. +source "drivers/mipi_dsi/Kconfig.mcux" + endif diff --git a/drivers/mipi_dsi/Kconfig.mcux b/drivers/mipi_dsi/Kconfig.mcux new file mode 100644 index 00000000000..690c936a72f --- /dev/null +++ b/drivers/mipi_dsi/Kconfig.mcux @@ -0,0 +1,11 @@ +# Copyright (c) 2022, NXP +# SPDX-License-Identifier: Apache-2.0 + +DT_COMPAT_MCUX_MIPI_DSI := nxp,imx-mipi-dsi + +config MIPI_DSI_MCUX + bool "NXP MCUX MIPI-DSI Host Controller" + depends on HAS_MCUX_MIPI_DSI + default $(dt_compat_enabled,$(DT_COMPAT_MCUX_MIPI_DSI)) + help + NXP MIPI DSI controller driver diff --git a/drivers/mipi_dsi/dsi_mcux.c b/drivers/mipi_dsi/dsi_mcux.c new file mode 100644 index 00000000000..79916dcfc9f --- /dev/null +++ b/drivers/mipi_dsi/dsi_mcux.c @@ -0,0 +1,207 @@ +/* + * Copyright 2022, NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT nxp_imx_mipi_dsi + +#include +#include +#include +#include + +LOG_MODULE_REGISTER(dsi_mcux, CONFIG_MIPI_DSI_LOG_LEVEL); + +#define MIPI_DPHY_REF_CLK DT_INST_PROP(0, dphy_ref_frequency) + +/* + * The DPHY bit clock must be fast enough to send out the pixels, it should be + * larger than: + * + * (Pixel clock * bit per output pixel) / number of MIPI data lane + * + * Here the desired DPHY bit clock multiplied by ( 9 / 8 = 1.125) to ensure + * it is fast enough. + */ +#define MIPI_DPHY_BIT_CLK_ENLARGE(origin) (((origin) / 8) * 9) + +struct display_mcux_mipi_dsi_config { + MIPI_DSI_Type base; + dsi_dpi_config_t dpi_config; + bool auto_insert_eotp; +}; + +struct display_mcux_mipi_dsi_data { + const struct device *dev; +}; + +static int dsi_mcux_attach(const struct device *dev, + uint8_t channel, + const struct mipi_dsi_device *mdev) +{ + const struct display_mcux_mipi_dsi_config *config = dev->config; + dsi_dphy_config_t dphy_config; + dsi_config_t dsi_config; + uint32_t mipi_dsi_esc_clk_hz; + uint32_t mipi_dsi_tx_esc_clk_hz; + uint32_t mipi_dsi_dphy_ref_clk_hz = MIPI_DPHY_REF_CLK; + + DSI_GetDefaultConfig(&dsi_config); + dsi_config.numLanes = mdev->data_lanes; + dsi_config.autoInsertEoTp = config->auto_insert_eotp; + + /* Init the DSI module. */ + DSI_Init((MIPI_DSI_Type *)&config->base, &dsi_config); + + /* Init DPHY. + * + * The DPHY bit clock must be fast enough to send out the pixels, it should be + * larger than: + * + * (Pixel clock * bit per output pixel) / number of MIPI data lane + * + * Here the desired DPHY bit clock multiplied by ( 9 / 8 = 1.125) to ensure + * it is fast enough. + * + * Note that the DSI output pixel is 24bit per pixel. + */ + uint32_t mipi_dsi_dpi_clk_hz = CLOCK_GetRootClockFreq(kCLOCK_Root_Lcdif); + uint32_t mipi_dsi_dphy_bit_clk_hz = mipi_dsi_dpi_clk_hz * (24 / mdev->data_lanes); + + mipi_dsi_dphy_bit_clk_hz = MIPI_DPHY_BIT_CLK_ENLARGE(mipi_dsi_dphy_bit_clk_hz); + + mipi_dsi_esc_clk_hz = CLOCK_GetRootClockFreq(kCLOCK_Root_Mipi_Esc); + mipi_dsi_tx_esc_clk_hz = mipi_dsi_esc_clk_hz / 3; + + DSI_GetDphyDefaultConfig(&dphy_config, mipi_dsi_dphy_bit_clk_hz, mipi_dsi_tx_esc_clk_hz); + + mipi_dsi_dphy_bit_clk_hz = DSI_InitDphy((MIPI_DSI_Type *)&config->base, + &dphy_config, mipi_dsi_dphy_ref_clk_hz); + + /* Init DPI interface. */ + DSI_SetDpiConfig((MIPI_DSI_Type *)&config->base, &config->dpi_config, mdev->data_lanes, + mipi_dsi_dpi_clk_hz, mipi_dsi_dphy_bit_clk_hz); + + imxrt_post_init_display_interface(); + + return 0; +} + +static ssize_t dsi_mcux_transfer(const struct device *dev, uint8_t channel, + struct mipi_dsi_msg *msg) +{ + const struct display_mcux_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.sendDscCmd = true; + dsi_xfer.dscCmd = msg->cmd; + dsi_xfer.txDataType = kDSI_TxDataDcsShortWrNoParam; + break; + case MIPI_DSI_DCS_SHORT_WRITE_PARAM: + __fallthrough; + case MIPI_DSI_DCS_LONG_WRITE: + dsi_xfer.sendDscCmd = true; + dsi_xfer.dscCmd = msg->cmd; + dsi_xfer.txDataType = kDSI_TxDataDcsShortWrOneParam; + 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_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 msg->rx_len; + } + + /* Return tx_len on a write */ + return msg->tx_len; + +} + +static struct mipi_dsi_driver_api dsi_mcux_api = { + .attach = dsi_mcux_attach, + .transfer = dsi_mcux_transfer, +}; + +static int display_mcux_mipi_dsi_init(const struct device *dev) +{ + imxrt_pre_init_display_interface(); + + return 0; +} + +#define MCUX_MIPI_DSI_DEVICE(id) \ + static const struct display_mcux_mipi_dsi_config display_mcux_mipi_dsi_config_##id = { \ + .base = { \ + .host = (DSI_HOST_Type *)DT_INST_REG_ADDR_BY_IDX(id, 0), \ + .dpi = (DSI_HOST_DPI_INTFC_Type *)DT_INST_REG_ADDR_BY_IDX(id, 1), \ + .apb = (DSI_HOST_APB_PKT_IF_Type *)DT_INST_REG_ADDR_BY_IDX(id, 2), \ + .dphy = (DSI_HOST_NXP_FDSOI28_DPHY_INTFC_Type *) \ + DT_INST_REG_ADDR_BY_IDX(id, 3), \ + }, \ + .dpi_config = { \ + .dpiColorCoding = DT_INST_ENUM_IDX(id, dpi_color_coding), \ + .pixelPacket = DT_INST_ENUM_IDX(id, dpi_pixel_packet), \ + .videoMode = DT_INST_ENUM_IDX(id, dpi_video_mode), \ + .bllpMode = DT_INST_ENUM_IDX(id, dpi_bllp_mode), \ + .pixelPayloadSize = DT_INST_PROP_BY_PHANDLE(id, nxp_lcdif, width), \ + .panelHeight = DT_INST_PROP_BY_PHANDLE(id, nxp_lcdif, height), \ + .polarityFlags = DT_INST_PROP_BY_PHANDLE_IDX( \ + id, nxp_lcdif, id, polarity) >> 2, \ + .hfp = DT_INST_PROP_BY_PHANDLE(id, nxp_lcdif, hfp), \ + .hbp = DT_INST_PROP_BY_PHANDLE(id, nxp_lcdif, hbp), \ + .hsw = DT_INST_PROP_BY_PHANDLE(id, nxp_lcdif, hsync), \ + .vfp = DT_INST_PROP_BY_PHANDLE(id, nxp_lcdif, vfp), \ + .vbp = DT_INST_PROP_BY_PHANDLE(id, nxp_lcdif, vbp), \ + }, \ + .auto_insert_eotp = DT_INST_PROP(id, autoinsert_eotp), \ + }; \ + static struct display_mcux_mipi_dsi_data display_mcux_mipi_dsi_data_##id; \ + DEVICE_DT_INST_DEFINE(id, \ + &display_mcux_mipi_dsi_init, \ + NULL, \ + &display_mcux_mipi_dsi_data_##id, \ + &display_mcux_mipi_dsi_config_##id, \ + POST_KERNEL, \ + CONFIG_MIPI_DSI_INIT_PRIORITY, \ + &dsi_mcux_api); + +DT_INST_FOREACH_STATUS_OKAY(MCUX_MIPI_DSI_DEVICE) diff --git a/dts/arm/nxp/nxp_rt11xx.dtsi b/dts/arm/nxp/nxp_rt11xx.dtsi index 19aba5e47fe..1db818eaeed 100644 --- a/dts/arm/nxp/nxp_rt11xx.dtsi +++ b/dts/arm/nxp/nxp_rt11xx.dtsi @@ -11,7 +11,7 @@ #include #include #include - +#include / { cpus { #address-cells = <1>; diff --git a/dts/bindings/mipi-dsi/nxp,imx-mipi-dsi.yaml b/dts/bindings/mipi-dsi/nxp,imx-mipi-dsi.yaml new file mode 100644 index 00000000000..5f46b337f2b --- /dev/null +++ b/dts/bindings/mipi-dsi/nxp,imx-mipi-dsi.yaml @@ -0,0 +1,72 @@ +# +# Copyright 2022, NXP +# +# SPDX-License-Identifier: Apache-2.0 +# +description: NXP MCUX MIPI DSI + +compatible: "nxp,imx-mipi-dsi" + +include: mipi-dsi-host.yaml + +properties: + interrupts: + required: true + + nxp,lcdif: + type: phandle + required: true + description: + Instance of the LCDIF peripheral. + + 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-pixel-packet: + type: string + enum: + - "16-bit" + - "18-bit" + - "18-bit-loose" + - "24-bit" + description: + MIPI DSI pixel packet type send through DPI interface. + + dpi-video-mode: + type: string + enum: + - "non-burst-sync-pulse" + - "non-burst-sync-event" + - "burst" + description: + DPI video mode. + + dpi-bllp-mode: + type: string + enum: + - "low-power" + - "blank" + - "null" + description: + Behavior in BLLP (Blanking or Low-Power Interval). + + autoinsert-eotp: + type: boolean + description: + Automatically insert an EoTp short packet when switching from HS to LP mode. + + dphy-ref-frequency: + type: int + required: true + description: + Maximum clock speed supported by the device, in Hz.