drivers: mipi dsi: Update dsi nxp dwc driver to support i.MX93 A55
Updated dsi nxp dwc driver and enabled runtime mmio configuration. Signed-off-by: Ruoshan Shi <ruoshan.shi@nxp.com> Signed-off-by: Winteri Wang <dongjie.wang@nxp.com> Signed-off-by: Jiafei Pan <Jiafei.Pan@nxp.com>
This commit is contained in:
committed by
Chris Friedt
parent
a541647a6e
commit
b815f5f481
@@ -16,42 +16,93 @@
|
||||
|
||||
LOG_MODULE_REGISTER(dsi_dwc, CONFIG_MIPI_DSI_LOG_LEVEL);
|
||||
|
||||
/* Required by DEVICE_MMIO_NAMED_* macros */
|
||||
#define DEV_CFG(_dev) ((const struct dwc_mipi_dsi_config *)(_dev)->config)
|
||||
#define DEV_DATA(_dev) ((struct dwc_mipi_dsi_data *)(_dev)->data)
|
||||
|
||||
struct dwc_mipi_dsi_config {
|
||||
MIPI_DSI_Type *base;
|
||||
DEVICE_MMIO_NAMED_ROM(reg_base);
|
||||
|
||||
const struct device *phy_cfg_clk_dev;
|
||||
clock_control_subsys_t phy_cfg_clk_subsys;
|
||||
struct _clock_root_config_t phy_cfg_clk_config;
|
||||
|
||||
dsi_dpi_config_t dpi_config;
|
||||
bool noncontinuous_hs_clk;
|
||||
dsi_config_t dsi_config;
|
||||
dsi_command_config_t command_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;
|
||||
DEVICE_MMIO_NAMED_RAM(reg_base);
|
||||
const struct device *dev;
|
||||
};
|
||||
|
||||
static int dsi_dwc_attach(const struct device *dev, uint8_t channel,
|
||||
const struct mipi_dsi_device *mdev)
|
||||
{
|
||||
MIPI_DSI_Type *base = (MIPI_DSI_Type *)DEVICE_MMIO_NAMED_GET(dev, reg_base);
|
||||
const struct dwc_mipi_dsi_config *config = dev->config;
|
||||
dsi_dphy_config_t dphy_config;
|
||||
dsi_config_t dsi_config;
|
||||
dsi_dpi_config_t dpi_config = config->dpi_config;
|
||||
dsi_command_config_t command_config = config->command_config;
|
||||
uint32_t phy_hsfreqrange;
|
||||
uint32_t m;
|
||||
uint32_t n;
|
||||
uint32_t vco_freq;
|
||||
|
||||
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);
|
||||
if (mdev->mode_flags & MIPI_DSI_MODE_VIDEO) {
|
||||
dsi_config.mode = kDSI_VideoMode;
|
||||
} else {
|
||||
dsi_config.mode = kDSI_CommandMode;
|
||||
}
|
||||
|
||||
DSI_SetDpiConfig(config->base, &config->dpi_config, mdev->data_lanes);
|
||||
/* Init the DSI module. */
|
||||
DSI_Init(base, &dsi_config);
|
||||
|
||||
DSI_SetDpiConfig(base, &dpi_config, mdev->data_lanes);
|
||||
|
||||
#if CONFIG_SOC_MIMX9352_A55
|
||||
uint32_t phyByteClkFreq_Hz = config->data_rate_clock * mdev->data_lanes / 8;
|
||||
|
||||
DSI_SetCommandModeConfig(base, &command_config, phyByteClkFreq_Hz);
|
||||
|
||||
vco_freq = Pll_Set_Pll_Vco_Freq(config->data_rate_clock / 2);
|
||||
|
||||
/* Get the divider value to set to the mediamix block. */
|
||||
DSI_DphyGetPllDivider(&m, &n, config->dphy_ref_frequency, vco_freq);
|
||||
|
||||
/* MEDIAMIX */
|
||||
/* Clear the bit to reset the clock logic */
|
||||
BLK_CTRL_MEDIAMIX->CLK_RESETN.RESET &= ~(MEDIAMIX_BLK_CTRL_RESET_dsi_apb_en_MASK |
|
||||
MEDIAMIX_BLK_CTRL_RESET_ref_clk_en_MASK);
|
||||
|
||||
BLK_CTRL_MEDIAMIX->CLK_RESETN.RESET |=
|
||||
(MEDIAMIX_BLK_CTRL_RESET_dsi_apb_en_MASK | MEDIAMIX_BLK_CTRL_RESET_ref_clk_en_MASK);
|
||||
|
||||
BLK_CTRL_MEDIAMIX->MIPI.DSI_W0 =
|
||||
MEDIAMIX_BLK_CTRL_DSI_W0_PROP_CNTRL(
|
||||
Pll_Set_Pll_Prop_Param(config->data_rate_clock / MHZ(2))) |
|
||||
MEDIAMIX_BLK_CTRL_DSI_W0_VCO_CNTRL(
|
||||
Pll_Set_Pll_Vco_Param(config->data_rate_clock / MHZ(2))) |
|
||||
MEDIAMIX_BLK_CTRL_DSI_W0_N(n) | MEDIAMIX_BLK_CTRL_DSI_W0_M(m);
|
||||
|
||||
BLK_CTRL_MEDIAMIX->MIPI.DSI_W1 =
|
||||
MEDIAMIX_BLK_CTRL_DSI_W1_CPBIAS_CNTRL(0x10) | MEDIAMIX_BLK_CTRL_DSI_W1_GMP_CNTRL(1);
|
||||
|
||||
#endif
|
||||
|
||||
/* 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);
|
||||
DSI_InitDphy(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 =
|
||||
@@ -63,9 +114,18 @@ static int dsi_dwc_attach(const struct device *dev, uint8_t channel,
|
||||
(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;
|
||||
|
||||
DSI_ConfigDphy(base, config->dphy_ref_frequency, config->data_rate_clock);
|
||||
#endif
|
||||
DSI_ConfigDphy(config->base, config->dphy_ref_frequency, config->data_rate_clock);
|
||||
status_t result = DSI_PowerUp(config->base);
|
||||
|
||||
#if CONFIG_SOC_MIMX9352_A55
|
||||
BLK_CTRL_MEDIAMIX->MIPI.DSI = MEDIAMIX_BLK_CTRL_DSI_updatepll(1) |
|
||||
MEDIAMIX_BLK_CTRL_DSI_HSFREQRANGE(phy_hsfreqrange) |
|
||||
MEDIAMIX_BLK_CTRL_DSI_CLKSEL(1) |
|
||||
MEDIAMIX_BLK_CTRL_DSI_CFGCLKFREQRANGE(0x1c);
|
||||
|
||||
#endif
|
||||
status_t result = DSI_PowerUp(base);
|
||||
|
||||
if (result != 0U) {
|
||||
LOG_ERR("DSI PHY init failed.\r\n");
|
||||
@@ -76,7 +136,7 @@ static int dsi_dwc_attach(const struct device *dev, uint8_t channel,
|
||||
|
||||
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;
|
||||
MIPI_DSI_Type *base = (MIPI_DSI_Type *)DEVICE_MMIO_NAMED_GET(dev, reg_base);
|
||||
dsi_transfer_t dsi_xfer = {0};
|
||||
status_t status;
|
||||
|
||||
@@ -128,7 +188,7 @@ static ssize_t dsi_dwc_transfer(const struct device *dev, uint8_t channel, struc
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
status = DSI_TransferBlocking(config->base, &dsi_xfer);
|
||||
status = DSI_TransferBlocking(base, &dsi_xfer);
|
||||
|
||||
if (status != kStatus_Success) {
|
||||
LOG_ERR("Transmission failed");
|
||||
@@ -147,9 +207,9 @@ static ssize_t dsi_dwc_transfer(const struct device *dev, uint8_t channel, struc
|
||||
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;
|
||||
MIPI_DSI_Type *base = (MIPI_DSI_Type *)DEVICE_MMIO_NAMED_GET(dev, reg_base);
|
||||
|
||||
DSI_EnableCommandMode(config->base, false);
|
||||
DSI_EnableCommandMode(base, false);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -162,12 +222,18 @@ static DEVICE_API(mipi_dsi, dsi_dwc_api) = {
|
||||
|
||||
static int dwc_mipi_dsi_init(const struct device *dev)
|
||||
{
|
||||
const struct dwc_mipi_dsi_config *config = dev->config;
|
||||
|
||||
DEVICE_MMIO_NAMED_MAP(dev, reg_base, K_MEM_CACHE_NONE | K_MEM_DIRECT_MAP);
|
||||
|
||||
clock_control_set_rate(config->phy_cfg_clk_dev, config->phy_cfg_clk_subsys,
|
||||
(clock_control_subsys_rate_t)&config->dphy_ref_frequency);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define DWC_DSI_DPI_CONFIG(id) \
|
||||
IF_ENABLED(DT_NODE_HAS_PROP(DT_DRV_INST(id), nxp_dc), \
|
||||
(.dpi_config = { \
|
||||
(.dpi_config = { \
|
||||
.virtualChannel = 0U, \
|
||||
.colorCoding = DT_INST_ENUM_IDX(id, dpi_color_coding), \
|
||||
.videoMode = DT_INST_ENUM_IDX(id, dpi_video_mode), \
|
||||
@@ -177,20 +243,50 @@ static int dwc_mipi_dsi_init(const struct device *dev)
|
||||
.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), \
|
||||
}))
|
||||
.hfp = DT_PROP(DT_CHILD(DT_INST_PHANDLE(id, nxp_dc), \
|
||||
display_timings), hfront_porch), \
|
||||
.hbp = DT_PROP(DT_CHILD(DT_INST_PHANDLE(id, nxp_dc), \
|
||||
display_timings), hback_porch), \
|
||||
.hsw = DT_PROP(DT_CHILD(DT_INST_PHANDLE(id, nxp_dc), \
|
||||
display_timings), hsync_len), \
|
||||
.vfp = DT_PROP(DT_CHILD(DT_INST_PHANDLE(id, nxp_dc), \
|
||||
display_timings), vfront_porch), \
|
||||
.vbp = DT_PROP(DT_CHILD(DT_INST_PHANDLE(id, nxp_dc), \
|
||||
display_timings), vback_porch), \
|
||||
.vsw = DT_PROP(DT_CHILD(DT_INST_PHANDLE(id, nxp_dc), \
|
||||
display_timings), vsync_len), \
|
||||
},))
|
||||
|
||||
#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), \
|
||||
DEVICE_MMIO_NAMED_ROM_INIT(reg_base, DT_DRV_INST(id)), \
|
||||
.phy_cfg_clk_dev = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR_BY_IDX(id, 0)), \
|
||||
.phy_cfg_clk_subsys = \
|
||||
(clock_control_subsys_t)DT_INST_CLOCKS_CELL_BY_IDX(id, 0, name), \
|
||||
.phy_cfg_clk_config = \
|
||||
{ \
|
||||
.clockOff = false, \
|
||||
}, \
|
||||
DWC_DSI_DPI_CONFIG(id).dsi_config = \
|
||||
{ \
|
||||
.mode = kDSI_VideoMode, \
|
||||
.packageFlags = \
|
||||
kDSI_DpiEnableBta | kDSI_DpiEnableEcc | kDSI_DpiEnableCrc, \
|
||||
.enableNoncontinuousClk = false, \
|
||||
.HsRxDeviceReady_ByteClk = 0U, \
|
||||
.lpRxDeviceReady_ByteClk = 0U, \
|
||||
.HsTxDeviceReady_ByteClk = 0U, \
|
||||
.lpTxDeviceReady_ByteClk = 0U, \
|
||||
}, \
|
||||
.command_config = \
|
||||
{ \
|
||||
.escClkFreq_Hz = 20000000, \
|
||||
.btaTo_Ns = 10000, \
|
||||
.hsTxTo_Ns = 60000, \
|
||||
.lpRxTo_Ns = 60000, \
|
||||
}, \
|
||||
.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; \
|
||||
|
||||
@@ -7,7 +7,7 @@ description: NXP MCUX MIPI DSI DWC
|
||||
|
||||
compatible: "nxp,mipi-dsi-dwc"
|
||||
|
||||
include: [mipi-dsi-host.yaml, display-controller.yaml]
|
||||
include: mipi-dsi-host.yaml
|
||||
|
||||
properties:
|
||||
interrupts:
|
||||
|
||||
Reference in New Issue
Block a user