--- /dev/null
+/*
+ * Copyright 2017 NXP
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <asm/io.h>
+#include <linux/errno.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/imx-regs.h>
+#include <asm/imx-common/sci/sci.h>
+#include <i2c.h>
+#include <asm/arch/sys_proto.h>
+
+#include <imxdpuv1.h>
+#include <imxdpuv1_registers.h>
+#include <imxdpuv1_events.h>
+#include <asm/arch/imx8_lvds.h>
+#include <video_fb.h>
+#include <asm/arch/imx8_mipi_dsi.h>
+#include <asm/arch/video_common.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static struct imxdpuv1_videomode gmode;
+static int8_t gdisp, gdc;
+static uint32_t gpixfmt;
+static GraphicDevice panel;
+
+static int hdmi_i2c_reg_write(struct udevice *dev, uint addr, uint mask, uint data)
+{
+ uint8_t valb;
+ int err;
+
+ if (mask != 0xff) {
+ err = dm_i2c_read(dev, addr, &valb, 1);
+ if (err)
+ return err;
+
+ valb &= ~mask;
+ valb |= data;
+ } else {
+ valb = data;
+ }
+
+ err = dm_i2c_write(dev, addr, &valb, 1);
+ return err;
+}
+
+static int hdmi_i2c_reg_read(struct udevice *dev, uint8_t addr, uint8_t *data)
+{
+ uint8_t valb;
+ int err;
+
+ err = dm_i2c_read(dev, addr, &valb, 1);
+ if (err)
+ return err;
+
+ *data = (int)valb;
+ return 0;
+}
+
+/* On 8QXP ARM2, the LVDS1 signals are connected to LVDS2HDMI card's LVDS2 channel,
+ * LVDS0 signals are connected to LVDS2HDMI card's LVDS4 channel.
+ * There totally 6 channels on the cards, from 0-5.
+ */
+int lvds2hdmi_setup(int i2c_bus)
+{
+ struct udevice *bus, *dev;
+ uint8_t chip = 0x4c;
+ uint8_t data;
+ int ret;
+
+ ret = uclass_get_device_by_seq(UCLASS_I2C, i2c_bus, &bus);
+ if (ret) {
+ printf("%s: No bus %d\n", __func__, i2c_bus);
+ return ret;
+ }
+
+ ret = dm_i2c_probe(bus, chip, 0, &dev);
+ if (ret) {
+ printf("%s: Can't find device id=0x%x, on bus %d\n",
+ __func__, chip, i2c_bus);
+ return ret;
+ }
+
+ /* InitIT626X(): start */
+ hdmi_i2c_reg_write(dev, 0x04, 0xff, 0x3d);
+ hdmi_i2c_reg_write(dev, 0x0f, 0xff, 0x00);
+ hdmi_i2c_reg_write(dev, 0x05, 0xff, 0x40);
+ hdmi_i2c_reg_write(dev, 0x04, 0xff, 0x15);
+ hdmi_i2c_reg_write(dev, 0x0f, 0xff, 0x00);
+ hdmi_i2c_reg_write(dev, 0x1d, 0xff, 0x66);
+ hdmi_i2c_reg_write(dev, 0x1e, 0xff, 0x01);
+
+ hdmi_i2c_reg_write(dev, 0x61, 0xff, 0x30);
+ hdmi_i2c_reg_read(dev, 0xf3, &data); /* -> 0x00 */
+ hdmi_i2c_reg_write(dev, 0xf3, 0xff, data & ~0x30);
+ hdmi_i2c_reg_read(dev, 0xf3, &data); /* -> 0x00 */
+ hdmi_i2c_reg_write(dev, 0xf3, 0xff, data | 0x20);
+
+ hdmi_i2c_reg_write(dev, 0x09, 0xff, 0x30);
+ hdmi_i2c_reg_write(dev, 0x0a, 0xff, 0xf8);
+ hdmi_i2c_reg_write(dev, 0x0b, 0xff, 0x37);
+ hdmi_i2c_reg_write(dev, 0x0f, 0xff, 0x00);
+ hdmi_i2c_reg_write(dev, 0xc9, 0xff, 0x00);
+ hdmi_i2c_reg_write(dev, 0xca, 0xff, 0x00);
+ hdmi_i2c_reg_write(dev, 0xcb, 0xff, 0x00);
+ hdmi_i2c_reg_write(dev, 0xcc, 0xff, 0x00);
+ hdmi_i2c_reg_write(dev, 0xcd, 0xff, 0x00);
+ hdmi_i2c_reg_write(dev, 0xce, 0xff, 0x00);
+ hdmi_i2c_reg_write(dev, 0xcf, 0xff, 0x00);
+ hdmi_i2c_reg_write(dev, 0xd0, 0xff, 0x00);
+ hdmi_i2c_reg_write(dev, 0x0f, 0xff, 0x01);
+
+ hdmi_i2c_reg_read(dev, 0x58, &data); /* -> 0x00 */
+ hdmi_i2c_reg_write(dev, 0x58, 0xff, data & ~(3 << 5));
+
+ hdmi_i2c_reg_write(dev, 0x0f, 0xff, 0x00);
+ hdmi_i2c_reg_write(dev, 0xe1, 0xff, 0x00);
+ hdmi_i2c_reg_write(dev, 0x0c, 0xff, 0xff);
+ hdmi_i2c_reg_write(dev, 0x0d, 0xff, 0xff);
+ hdmi_i2c_reg_read(dev, 0x0e, &data); /* -> 0x00 */
+ hdmi_i2c_reg_write(dev, 0x0e, 0xff, (data | 0x3));
+ hdmi_i2c_reg_write(dev, 0x0e, 0xff, (data & 0xfe));
+ hdmi_i2c_reg_write(dev, 0x0f, 0xff, 0x01);
+ hdmi_i2c_reg_write(dev, 0x33, 0xff, 0x00);
+ hdmi_i2c_reg_write(dev, 0x34, 0xff, 0x18);
+ hdmi_i2c_reg_write(dev, 0x35, 0xff, 0x00);
+ hdmi_i2c_reg_write(dev, 0x0f, 0xff, 0x00);
+ hdmi_i2c_reg_write(dev, 0xc4, 0xff, 0xfe);
+ hdmi_i2c_reg_read(dev, 0xc5, &data); /* -> 0x00 */
+ hdmi_i2c_reg_write(dev, 0xc5, 0xff, data | 0x30);
+ /* InitIT626X end */
+
+ hdmi_i2c_reg_write(dev, 0x0f, 0xff, 0x00);
+ hdmi_i2c_reg_write(dev, 0x04, 0xff, 0x3d);
+ hdmi_i2c_reg_write(dev, 0x04, 0xff, 0x15);
+ hdmi_i2c_reg_write(dev, 0x0f, 0xff, 0x00);
+ hdmi_i2c_reg_write(dev, 0x1d, 0xff, 0x66);
+ hdmi_i2c_reg_write(dev, 0x1e, 0xff, 0x01);
+
+ hdmi_i2c_reg_read(dev, 0xc1, &data); /* -> 0x00 */
+ hdmi_i2c_reg_write(dev, 0x61, 0xff, 0x10);
+
+ /* SetupAFE(): */
+ hdmi_i2c_reg_write(dev, 0x62, 0xff, 0x88);
+ hdmi_i2c_reg_write(dev, 0x63, 0xff, 0x10);
+ hdmi_i2c_reg_write(dev, 0x64, 0xff, 0x84);
+ /* SetupAFE(): end */
+
+ hdmi_i2c_reg_read(dev, 0x04, &data); /* -> 0x00 */
+ hdmi_i2c_reg_write(dev, 0x04, 0xff, 0x1d);
+
+ hdmi_i2c_reg_read(dev, 0x04, &data); /* -> 0x00 */
+ hdmi_i2c_reg_write(dev, 0x04, 0xff, 0x15);
+
+ hdmi_i2c_reg_read(dev, 0x0e, &data); /* -> 0x00 */
+
+ /* Wait video stable */
+ hdmi_i2c_reg_read(dev, 0x0e, &data); /* -> 0x00 */
+
+ /* Reset Video */
+ hdmi_i2c_reg_read(dev, 0x0d, &data); /* -> 0x00 */
+ hdmi_i2c_reg_write(dev, 0x0d, 0xff, 0x40);
+ hdmi_i2c_reg_read(dev, 0x0e, &data); /* -> 0x00 */
+ hdmi_i2c_reg_write(dev, 0x0e, 0xff, 0x7d);
+ hdmi_i2c_reg_write(dev, 0x0e, 0xff, 0x7c);
+ hdmi_i2c_reg_write(dev, 0x0f, 0xff, 0x00);
+ hdmi_i2c_reg_write(dev, 0x61, 0xff, 0x00);
+ hdmi_i2c_reg_read(dev, 0x61, &data); /* -> 0x00 */
+ hdmi_i2c_reg_read(dev, 0x62, &data); /* -> 0x00 */
+ hdmi_i2c_reg_read(dev, 0x63, &data); /* -> 0x00 */
+ hdmi_i2c_reg_read(dev, 0x64, &data); /* -> 0x00 */
+ hdmi_i2c_reg_read(dev, 0x65, &data); /* -> 0x00 */
+ hdmi_i2c_reg_read(dev, 0x66, &data); /* -> 0x00 */
+ hdmi_i2c_reg_read(dev, 0x67, &data); /* -> 0x00 */
+ hdmi_i2c_reg_write(dev, 0x0f, 0xff, 0x00);
+ hdmi_i2c_reg_read(dev, 0xc1, &data); /* -> 0x00 */
+ hdmi_i2c_reg_write(dev, 0xc1, 0xff, 0x00);
+ hdmi_i2c_reg_write(dev, 0xc6, 0xff, 0x03);
+ /* Clear AV mute */
+
+ return 0;
+}
+
+
+int lvds_soc_setup(int lvds_id, sc_pm_clock_rate_t pixel_clock)
+{
+ sc_err_t err;
+ sc_rsrc_t lvds_rsrc, mipi_rsrc;
+ sc_ipc_t ipcHndl = gd->arch.ipc_channel_handle;
+
+ if (lvds_id == 0) {
+ lvds_rsrc = SC_R_LVDS_0;
+ mipi_rsrc = SC_R_MIPI_0;
+ } else {
+ lvds_rsrc = SC_R_LVDS_1;
+ mipi_rsrc = SC_R_MIPI_1;
+ }
+ /* Power up LVDS */
+ err = sc_pm_set_resource_power_mode(ipcHndl, lvds_rsrc, SC_PM_PW_MODE_ON);
+ if (err != SC_ERR_NONE) {
+ printf("LVDS Power up failed! (error = %d)\n", err);
+ return -EIO;
+ }
+
+ /* Setup clocks */
+ err = sc_pm_set_clock_rate(ipcHndl, lvds_rsrc, SC_PM_CLK_BYPASS, &pixel_clock);
+ if (err != SC_ERR_NONE) {
+ printf("LVDS set rate SC_PM_CLK_BYPASS failed! (error = %d)\n", err);
+ return -EIO;
+ }
+
+ err = sc_pm_set_clock_rate(ipcHndl, lvds_rsrc, SC_PM_CLK_PER, &pixel_clock);
+ if (err != SC_ERR_NONE) {
+ printf("LVDS set rate SC_PM_CLK_BYPASS failed! (error = %d)\n", err);
+ return -EIO;
+ }
+
+ err = sc_pm_set_clock_rate(ipcHndl, lvds_rsrc, SC_PM_CLK_PHY, &pixel_clock);
+ if (err != SC_ERR_NONE) {
+ printf("LVDS set rate SC_PM_CLK_BYPASS failed! (error = %d)\n", err);
+ return -EIO;
+ }
+
+ if (is_imx8qxp()) {
+ /* For QXP, there is only one DC, and two pixel links to each LVDS with a mux provided.
+ * We connect LVDS0 to pixel link 0, lVDS1 to pixel link 1 from DC
+ */
+
+ /* Configure to LVDS mode not MIPI DSI */
+ err = sc_misc_set_control(ipcHndl, mipi_rsrc, SC_C_MODE, 1);
+ if (err != SC_ERR_NONE) {
+ printf("LVDS sc_misc_set_control SC_C_MODE failed! (error = %d)\n", err);
+ return -EIO;
+ }
+
+ /* Configure to LVDS mode with single channel */
+ err = sc_misc_set_control(ipcHndl, mipi_rsrc, SC_C_DUAL_MODE, 0);
+ if (err != SC_ERR_NONE) {
+ printf("LVDS sc_misc_set_control SC_C_DUAL_MODE failed! (error = %d)\n", err);
+ return -EIO;
+ }
+
+ err = sc_misc_set_control(ipcHndl, mipi_rsrc, SC_C_PXL_LINK_SEL, lvds_id);
+ if (err != SC_ERR_NONE) {
+ printf("LVDS sc_misc_set_control SC_C_PXL_LINK_SEL failed! (error = %d)\n", err);
+ return -EIO;
+ }
+ }
+
+ err = sc_pm_clock_enable(ipcHndl, lvds_rsrc, SC_PM_CLK_BYPASS, true, false);
+ if (err != SC_ERR_NONE) {
+ printf("LVDS enable clock SC_PM_CLK_BYPASS failed! (error = %d)\n", err);
+ return -EIO;
+ }
+
+ err = sc_pm_clock_enable(ipcHndl, lvds_rsrc, SC_PM_CLK_PER, true, false);
+ if (err != SC_ERR_NONE) {
+ printf("LVDS enable clock SC_PM_CLK_PER failed! (error = %d)\n", err);
+ return -EIO;
+ }
+
+ err = sc_pm_clock_enable(ipcHndl, lvds_rsrc, SC_PM_CLK_PHY, true, false);
+ if (err != SC_ERR_NONE) {
+ printf("LVDS enable clock SC_PM_CLK_PHY failed! (error = %d)\n", err);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+void lvds_configure(int lvds_id)
+{
+ void __iomem *lvds_base;
+ void __iomem *mipi_base;
+ uint32_t phy_setting;
+ uint32_t mode;
+
+ if (lvds_id == 0) {
+ lvds_base = (void __iomem *)LVDS0_PHYCTRL_BASE;
+ mipi_base = (void __iomem *)MIPI0_SS_BASE;
+ } else {
+ lvds_base = (void __iomem *)LVDS1_PHYCTRL_BASE;
+ mipi_base = (void __iomem *)MIPI1_SS_BASE;
+ }
+
+ if (is_imx8qm()) {
+ mode =
+ IMX_LVDS_SET_FIELD(LVDS_CTRL_CH0_MODE, LVDS_CTRL_CH0_MODE__DI0) |
+ IMX_LVDS_SET_FIELD(LVDS_CTRL_CH0_DATA_WIDTH, LVDS_CTRL_CH0_DATA_WIDTH__24BIT) |
+ IMX_LVDS_SET_FIELD(LVDS_CTRL_CH0_BIT_MAP, LVDS_CTRL_CH0_BIT_MAP__JEIDA) |
+ IMX_LVDS_SET_FIELD(LVDS_CTRL_CH0_10BIT_ENABLE, LVDS_CTRL_CH0_10BIT_ENABLE__10BIT) |
+ IMX_LVDS_SET_FIELD(LVDS_CTRL_DI0_DATA_WIDTH, LVDS_CTRL_DI0_DATA_WIDTH__USE_30BIT);
+
+ writel(mode, lvds_base + LVDS_CTRL);
+
+ phy_setting =
+ LVDS_PHY_CTRL_RFB_MASK |
+ LVDS_PHY_CTRL_CH0_EN_MASK |
+ (0 << LVDS_PHY_CTRL_M_SHIFT) |
+ (0x04 << LVDS_PHY_CTRL_CCM_SHIFT) |
+ (0x04 << LVDS_PHY_CTRL_CA_SHIFT);
+ writel(phy_setting, lvds_base + LVDS_PHY_CTRL);
+ } else if (is_imx8qxp()) {
+ mode =
+ IMX_LVDS_SET_FIELD(LVDS_CTRL_CH0_MODE, LVDS_CTRL_CH0_MODE__DI0) |
+ IMX_LVDS_SET_FIELD(LVDS_CTRL_CH0_DATA_WIDTH, LVDS_CTRL_CH0_DATA_WIDTH__24BIT) |
+ IMX_LVDS_SET_FIELD(LVDS_CTRL_CH0_BIT_MAP, LVDS_CTRL_CH0_BIT_MAP__JEIDA);
+
+ phy_setting = 0x4 << 5 | 0x4 << 2 | 1 << 1 | 0x1;
+ writel(phy_setting, lvds_base + 0 /* PHY_CTRL*/);
+ writel(mode, lvds_base + LVDS_CTRL);
+ writel(0, lvds_base + MIPIv2_CSR_TX_ULPS);
+ writel(MIPI_CSR_PXL2DPI_24_BIT, lvds_base + MIPIv2_CSR_PXL2DPI);
+
+ /* Power up PLL in MIPI DSI PHY */
+ writel(0, mipi_base + MIPI_DSI_OFFSET + DPHY_PD_PLL);
+ writel(0, mipi_base + MIPI_DSI_OFFSET + DPHY_PD_TX);
+ }
+}
+
+int display_controller_setup(sc_pm_clock_rate_t pixel_clock)
+{
+ sc_err_t err;
+ sc_rsrc_t dc_rsrc, pll0_rsrc, pll1_rsrc;
+ sc_pm_clock_rate_t pll_clk;
+ sc_ipc_t ipcHndl = gd->arch.ipc_channel_handle;
+
+ int dc_id = gdc;
+
+ if (dc_id == 0) {
+ dc_rsrc = SC_R_DC_0;
+ pll0_rsrc = SC_R_DC_0_PLL_0;
+ pll1_rsrc = SC_R_DC_0_PLL_1;
+ } else {
+ dc_rsrc = SC_R_DC_1;
+ pll0_rsrc = SC_R_DC_1_PLL_0;
+ pll1_rsrc = SC_R_DC_1_PLL_1;
+ }
+
+ /* Power up DC */
+ err = sc_pm_set_resource_power_mode(ipcHndl, dc_rsrc, SC_PM_PW_MODE_ON);
+ if (err != SC_ERR_NONE) {
+ printf("DC Power up failed! (error = %d)\n", err);
+ return -EIO;
+ }
+
+ /* Power up PLL1 (user PLL) */
+ err = sc_pm_set_resource_power_mode(ipcHndl, pll0_rsrc, SC_PM_PW_MODE_ON);
+ if (err != SC_ERR_NONE) {
+ printf("PLL0 Power up failed! (error = %d)\n", err);
+ return -EIO;
+ }
+
+ /* Power up PLL2 */
+ err = sc_pm_set_resource_power_mode(ipcHndl, pll1_rsrc, SC_PM_PW_MODE_ON);
+ if (err != SC_ERR_NONE) {
+ printf("PLL1 Power up failed! (error = %d)\n", err);
+ return -EIO;
+ }
+
+ /* Setup the pll1/2 and DISP0/1 clock */
+ if (pixel_clock >= 40000000)
+ pll_clk = 1188000000;
+ else
+ pll_clk = 675000000;
+
+ err = sc_pm_set_clock_rate(ipcHndl, pll0_rsrc, SC_PM_CLK_PLL, &pll_clk);
+ if (err != SC_ERR_NONE) {
+ printf("PLL0 set clock rate failed! (error = %d)\n", err);
+ return -EIO;
+ }
+
+ err = sc_pm_set_clock_rate(ipcHndl, pll1_rsrc, SC_PM_CLK_PLL, &pll_clk);
+ if (err != SC_ERR_NONE) {
+ printf("PLL1 set clock rate failed! (error = %d)\n", err);
+ return -EIO;
+ }
+
+ err = sc_pm_set_clock_rate(ipcHndl, dc_rsrc, SC_PM_CLK_MISC0, &pixel_clock);
+ if (err != SC_ERR_NONE) {
+ printf("DISP0 set clock rate failed! (error = %d)\n", err);
+ return -EIO;
+ }
+
+ err = sc_pm_set_clock_rate(ipcHndl, dc_rsrc, SC_PM_CLK_MISC1, &pixel_clock);
+ if (err != SC_ERR_NONE) {
+ printf("DISP1 set clock rate failed! (error = %d)\n", err);
+ return -EIO;
+ }
+
+ err = sc_pm_clock_enable(ipcHndl, pll0_rsrc, SC_PM_CLK_PLL, true, false);
+ if (err != SC_ERR_NONE) {
+ printf("PLL0 clock enable failed! (error = %d)\n", err);
+ return -EIO;
+ }
+
+ err = sc_pm_clock_enable(ipcHndl, pll1_rsrc, SC_PM_CLK_PLL, true, false);
+ if (err != SC_ERR_NONE) {
+ printf("PLL1 clock enable failed! (error = %d)\n", err);
+ return -EIO;
+ }
+
+ err = sc_pm_clock_enable(ipcHndl, dc_rsrc, SC_PM_CLK_MISC0, true, false);
+ if (err != SC_ERR_NONE) {
+ printf("DISP0 clock enable failed! (error = %d)\n", err);
+ return -EIO;
+ }
+
+ err = sc_pm_clock_enable(ipcHndl, dc_rsrc, SC_PM_CLK_MISC1, true, false);
+ if (err != SC_ERR_NONE) {
+ printf("DISP1 clock enable failed! (error = %d)\n", err);
+ return -EIO;
+ }
+
+ err = sc_misc_set_control(ipcHndl, dc_rsrc, SC_C_PXL_LINK_MST1_ADDR, 0);
+ if (err != SC_ERR_NONE) {
+ printf("DC Set control fSC_C_PXL_LINK_MST1_ADDR ailed! (error = %d)\n", err);
+ return -EIO;
+ }
+
+ err = sc_misc_set_control(ipcHndl, dc_rsrc, SC_C_PXL_LINK_MST1_ENB, 1);
+ if (err != SC_ERR_NONE) {
+ printf("DC Set control SC_C_PXL_LINK_MST1_ENB failed! (error = %d)\n", err);
+ return -EIO;
+ }
+
+ err = sc_misc_set_control(ipcHndl, dc_rsrc, SC_C_PXL_LINK_MST1_VLD, 1);
+ if (err != SC_ERR_NONE) {
+ printf("DC Set control SC_C_PXL_LINK_MST1_VLD failed! (error = %d)\n", err);
+ return -EIO;
+ }
+
+ err = sc_misc_set_control(ipcHndl, dc_rsrc, SC_C_PXL_LINK_MST2_ADDR, 0);
+ if (err != SC_ERR_NONE) {
+ printf("DC Set control SC_C_PXL_LINK_MST2_ADDR ailed! (error = %d)\n", err);
+ return -EIO;
+ }
+
+ err = sc_misc_set_control(ipcHndl, dc_rsrc, SC_C_PXL_LINK_MST2_ENB, 1);
+ if (err != SC_ERR_NONE) {
+ printf("DC Set control SC_C_PXL_LINK_MST2_ENB failed! (error = %d)\n", err);
+ return -EIO;
+ }
+
+ err = sc_misc_set_control(ipcHndl, dc_rsrc, SC_C_PXL_LINK_MST2_VLD, 1);
+ if (err != SC_ERR_NONE) {
+ printf("DC Set control SC_C_PXL_LINK_MST2_VLD failed! (error = %d)\n", err);
+ return -EIO;
+ }
+
+ err = sc_misc_set_control(ipcHndl, dc_rsrc, SC_C_SYNC_CTRL0, 1);
+ if (err != SC_ERR_NONE) {
+ printf("DC Set control SC_C_SYNC_CTRL0 failed! (error = %d)\n", err);
+ return -EIO;
+ }
+
+ err = sc_misc_set_control(ipcHndl, dc_rsrc, SC_C_SYNC_CTRL1, 1);
+ if (err != SC_ERR_NONE) {
+ printf("DC Set control SC_C_SYNC_CTRL1 failed! (error = %d)\n", err);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+void *video_hw_init(void)
+{
+ imxdpuv1_channel_params_t channel;
+ imxdpuv1_layer_t layer;
+ void *fb;
+
+ int8_t imxdpuv1_id = gdc;
+
+ if (imxdpuv1_id != 0 || (imxdpuv1_id == 1 && !is_imx8qm())) {
+ printf("%s(): invalid imxdpuv1_id %d", __func__, imxdpuv1_id);
+ return NULL;
+ }
+
+ panel.winSizeX = gmode.hlen;
+ panel.winSizeY = gmode.vlen;
+ panel.plnSizeX = gmode.hlen;
+ panel.plnSizeY = gmode.vlen;
+
+ panel.gdfBytesPP = 4;
+ panel.gdfIndex = GDF_32BIT_X888RGB;
+
+ panel.memSize = gmode.hlen * gmode.vlen * panel.gdfBytesPP;
+
+ /* Allocate framebuffer */
+ fb = memalign(0x1000,
+ roundup(panel.memSize, 0x1000));
+ if (!fb) {
+ printf("IMXDPUv1: Error allocating framebuffer!\n");
+ return NULL;
+ }
+
+ /* Wipe framebuffer */
+ memset(fb, 0, panel.memSize);
+
+ panel.frameAdrs = (ulong)fb;
+
+ imxdpuv1_init(imxdpuv1_id);
+ imxdpuv1_disp_enable_frame_gen(imxdpuv1_id, 0, IMXDPUV1_FALSE);
+ imxdpuv1_disp_enable_frame_gen(imxdpuv1_id, 1, IMXDPUV1_FALSE);
+
+ imxdpuv1_disp_setup_frame_gen(imxdpuv1_id, gdisp,
+ (const struct imxdpuv1_videomode *)&gmode,
+ 0x3ff, 0, 0, 1, IMXDPUV1_DISABLE);
+ imxdpuv1_disp_init(imxdpuv1_id, gdisp);
+ imxdpuv1_disp_setup_constframe(imxdpuv1_id,
+ gdisp, 0, 0, 0xff, 0); /* blue */
+
+ if (gdisp == 0)
+ channel.common.chan = IMXDPUV1_CHAN_VIDEO_0;
+ else
+ channel.common.chan = IMXDPUV1_CHAN_VIDEO_1;
+ channel.common.src_pixel_fmt = gpixfmt;
+ channel.common.dest_pixel_fmt = gpixfmt;
+ channel.common.src_width = gmode.hlen;
+ channel.common.src_height = gmode.vlen;
+
+ channel.common.clip_width = 0;
+ channel.common.clip_height = 0;
+ channel.common.clip_top = 0;
+ channel.common.clip_left = 0;
+
+ channel.common.dest_width = gmode.hlen;
+ channel.common.dest_height = gmode.vlen;
+ channel.common.dest_top = 0;
+ channel.common.dest_left = 0;
+ channel.common.stride =
+ gmode.hlen * imxdpuv1_bytes_per_pixel(IMXDPUV1_PIX_FMT_BGRA32);
+ channel.common.disp_id = gdisp;
+ channel.common.const_color = 0;
+ channel.common.use_global_alpha = 0;
+ channel.common.use_local_alpha = 0;
+ imxdpuv1_init_channel(imxdpuv1_id, &channel);
+
+ imxdpuv1_init_channel_buffer(imxdpuv1_id,
+ channel.common.chan,
+ gmode.hlen * imxdpuv1_bytes_per_pixel(IMXDPUV1_PIX_FMT_RGB32),
+ IMXDPUV1_ROTATE_NONE,
+ (dma_addr_t)fb,
+ 0,
+ 0);
+
+ layer.enable = IMXDPUV1_TRUE;
+ layer.secondary = get_channel_blk(channel.common.chan);
+
+ if (gdisp == 0) {
+ layer.stream = IMXDPUV1_DISPLAY_STREAM_0;
+ layer.primary = IMXDPUV1_ID_CONSTFRAME0;
+ } else {
+ layer.stream = IMXDPUV1_DISPLAY_STREAM_1;
+ layer.primary = IMXDPUV1_ID_CONSTFRAME1;
+ }
+
+ imxdpuv1_disp_setup_layer(
+ imxdpuv1_id, &layer, IMXDPUV1_LAYER_0, 1);
+ imxdpuv1_disp_set_layer_global_alpha(
+ imxdpuv1_id, IMXDPUV1_LAYER_0, 0xff);
+
+ imxdpuv1_disp_set_layer_position(
+ imxdpuv1_id, IMXDPUV1_LAYER_0, 0, 0);
+ imxdpuv1_disp_set_chan_position(
+ imxdpuv1_id, channel.common.chan, 0, 0);
+
+ imxdpuv1_disp_enable_frame_gen(imxdpuv1_id, gdisp, IMXDPUV1_ENABLE);
+
+ debug("IMXDPU display start ...\n");
+
+ return &panel;
+}
+
+void imxdpuv1_fb_disable(void)
+{
+ /* Disable video only when video init is done */
+ if (panel.frameAdrs)
+ imxdpuv1_disp_enable_frame_gen(gdc, gdisp, IMXDPUV1_DISABLE);
+}
+
+int imxdpuv1_fb_init(struct fb_videomode const *mode,
+ uint8_t disp, uint32_t pixfmt)
+{
+ if (disp > 1) {
+ printf("Invalid disp parameter %d for imxdpuv1_fb_init\n", disp);
+ return -EINVAL;
+ }
+
+ memset(&gmode, 0, sizeof(struct imxdpuv1_videomode));
+ gmode.pixelclock = PS2KHZ(mode->pixclock) * 1000;
+ gmode.hlen = mode->xres;
+ gmode.hbp = mode->left_margin;
+ gmode.hfp = mode->right_margin;
+
+ gmode.vlen = mode->yres;
+ gmode.vbp = mode->upper_margin;
+ gmode.vfp = mode->lower_margin;
+
+ gmode.hsync = mode->hsync_len;
+ gmode.vsync = mode->vsync_len;
+ gmode.flags = IMXDPUV1_MODE_FLAGS_HSYNC_POL | IMXDPUV1_MODE_FLAGS_VSYNC_POL | IMXDPUV1_MODE_FLAGS_DE_POL;
+
+ if (is_imx8qm()) { /* QM has two DCs each contains one LVDS as secondary display output */
+ gdisp = 1;
+ gdc = disp;
+ } else if (is_imx8qxp()) { /* QXP has one DC which contains 2 LVDS/MIPI_DSI combo */
+ gdisp = disp;
+ gdc = 0;
+ } else {
+ printf("Unsupported SOC for imxdpuv1_fb_init\n");
+ return -EPERM;
+ }
+
+ gpixfmt = pixfmt;
+
+ debug("imxdpuv1_fb_init, dc=%d, disp=%d\n", gdc, gdisp);
+
+ return 0;
+}
+
--- /dev/null
+/*
+ * Copyright 2015-2017 Freescale Semiconductor, Inc.
+ * Copyright 2017 NXP
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#ifndef _IMX8_MIPI_DSI_H_
+#define _IMX8_MIPI_DSI_H_
+
+#define MIPI_CSR_OFFSET 0x1000 /* Subsystem Control Status Registers (CSR) */
+#define MIPI_CSR_TX_ULPS 0x0
+#define MIPIv2_CSR_TX_ULPS 0x30
+#define MIPI_CSR_TX_ULPS_VALUE 0x1F
+
+#define MIPI_CSR_PXL2DPI 0x4
+#define MIPIv2_CSR_PXL2DPI 0x40
+
+#define MIPI_CSR_PXL2DPI_16_BIT_PACKED 0x0
+#define MIPI_CSR_PXL2DPI_16_BIT_565_ALIGNED 0x1
+#define MIPI_CSR_PXL2DPI_16_BIT_565_SHIFTED 0x2
+#define MIPI_CSR_PXL2DPI_18_BIT_PACKED 0x3
+#define MIPI_CSR_PXL2DPI_18_BIT_ALIGNED 0x4
+#define MIPI_CSR_PXL2DPI_24_BIT 0x5
+
+#define DSI_CMD_BUF_MAXSIZE (128)
+
+#define MIPI_DSI_OFFSET 0x8000 /* MIPI DSI Controller */
+
+/* DPI interface pixel color coding map */
+enum mipi_dsi_dpi_fmt {
+ MIPI_RGB565_PACKED = 0,
+ MIPI_RGB565_LOOSELY,
+ MIPI_RGB565_CONFIG3,
+ MIPI_RGB666_PACKED,
+ MIPI_RGB666_LOOSELY,
+ MIPI_RGB888,
+};
+
+struct mipi_dsi_context {
+ char *NAME;
+ uint32_t REGS_BASE;
+ uint32_t CSR_REGS_BASE;
+};
+
+struct dsi_cfg_csr_object {
+ uint32_t dsi_host_cfg_num_lanes;
+ uint32_t dsi_host_cfg_noncont_clk;
+ uint32_t dsi_host_cfg_t_pre;
+ uint32_t dsi_host_cfg_t_post;
+ uint32_t dsi_host_cfg_tx_gap;
+ uint32_t dsi_host_cfg_autoinsert_eotp;
+ uint32_t dsi_host_cfg_extrcmd_after_eotp;
+ uint32_t dsi_host_cfg_htx_to_cnt;
+ uint32_t dsi_host_cfg_lrx_h_to_cnt;
+ uint32_t dsi_host_cfg_bta_h_to_cnt;
+ uint32_t dsi_host_cfg_twakeup;
+};
+
+struct dsi_cfg_dpi_object {
+ uint32_t dsi_host_cfg_dpi_pxl_payld_size;
+ uint32_t dsi_host_cfg_dpi_pxl_fifo_send_lev;
+ uint32_t dsi_host_cfg_dpi_if_color_coding;
+ uint32_t dsi_host_cfg_dpi_pxl_format;
+ uint32_t dsi_host_cfg_dpi_vsync_pol;
+ uint32_t dsi_host_cfg_dpi_hsync_pol;
+ uint32_t dsi_host_cfg_dpi_video_mode;
+ uint32_t dsi_host_cfg_dpi_hfp;
+ uint32_t dsi_host_cfg_dpi_hbp;
+ uint32_t dsi_host_cfg_dpi_hsa;
+ uint32_t dsi_host_cfg_dpi_en_mult_pkt;
+ uint32_t dsi_host_cfg_dpi_vbp;
+ uint32_t dsi_host_cfg_dpi_vfp;
+ uint32_t dsi_host_cfg_dpi_bllp_mode;
+ uint32_t dsi_host_cfg_dpi_null_pkt_bllp;
+ uint32_t dsi_host_cfg_dpi_vactive;
+ uint32_t dsi_host_cfg_dpi_vc;
+};
+
+struct dsi_cfg_pkt_object {
+ uint32_t dsi_host_pkt_ctrl;
+ uint32_t dsi_host_send_pkt;
+ uint32_t dsi_host_irq_mask;
+ uint32_t dsi_host_irq_mask2;
+};
+
+struct dsi_cfg_dphy_object {
+ uint32_t dphy_pd_tx;
+ uint32_t dphy_m_prg_hs_prepare;
+ uint32_t dphy_mc_prg_hs_prepare;
+ uint32_t dphy_m_prg_hs_zero;
+ uint32_t dphy_mc_prg_hs_zero;
+ uint32_t dphy_m_prg_hs_trial;
+ uint32_t dphy_mc_prg_hs_trial;
+ uint32_t dphy_pd_pll;
+ uint32_t dphy_tst;
+ uint32_t dphy_cn;
+ uint32_t dphy_cm;
+ uint32_t dphy_co;
+ uint32_t dphy_lock;
+ uint32_t dphy_lock_byp;
+ uint32_t dphy_tx_rcal;
+ uint32_t dphy_auto_pd_en;
+ uint32_t dphy_rxlprp;
+ uint32_t dphy_rxcdrp;
+};
+
+/* dphy */
+#define DPHY_PD_TX 0x300
+#define DPHY_M_PRG_HS_PREPARE 0x304
+#define DPHY_MC_PRG_HS_PREPARE 0x308
+#define DPHY_M_PRG_HS_ZERO 0x30c
+#define DPHY_MC_PRG_HS_ZERO 0x310
+#define DPHY_M_PRG_HS_TRAIL 0x314
+#define DPHY_MC_PRG_HS_TRAIL 0x318
+#define DPHY_PD_PLL 0x31c
+#define DPHY_TST 0x320
+#define DPHY_CN 0x324
+#define DPHY_CM 0x328
+#define DPHY_CO 0x32c
+#define DPHY_LOCK 0x330
+#define DPHY_LOCK_BYP 0x334
+#define DPHY_RTERM_SEL 0x338
+#define DPHY_AUTO_PD_EN 0x33c
+#define DPHY_RXLPRP 0x340
+#define DPHY_RXCDRP 0x344
+
+/* host */
+#define HOST_CFG_NUM_LANES 0x0
+#define HOST_CFG_NONCONTINUOUS_CLK 0x4
+#define HOST_CFG_T_PRE 0x8
+#define HOST_CFG_T_POST 0xc
+#define HOST_CFG_TX_GAP 0x10
+#define HOST_CFG_AUTOINSERT_EOTP 0x14
+#define HOST_CFG_EXTRA_CMDS_AFTER_EOTP 0x18
+#define HOST_CFG_HTX_TO_COUNT 0x1c
+#define HOST_CFG_LRX_H_TO_COUNT 0x20
+#define HOST_CFG_BTA_H_TO_COUNT 0x24
+#define HOST_CFG_TWAKEUP 0x28
+#define HOST_CFG_STATUS_OUT 0x2c
+#define HOST_RX_ERROR_STATUS 0x30
+
+/* dpi */
+#define DPI_PIXEL_PAYLOAD_SIZE 0x200
+#define DPI_PIXEL_FIFO_SEND_LEVEL 0x204
+#define DPI_INTERFACE_COLOR_CODING 0x208
+#define DPI_PIXEL_FORMAT 0x20c
+#define DPI_VSYNC_POLARITY 0x210
+#define DPI_HSYNC_POLARITY 0x214
+#define DPI_VIDEO_MODE 0x218
+#define DPI_HFP 0x21c
+#define DPI_HBP 0x220
+#define DPI_HSA 0x224
+#define DPI_ENABLE_MULT_PKTS 0x228
+#define DPI_VBP 0x22c
+#define DPI_VFP 0x230
+#define DPI_BLLP_MODE 0x234
+#define DPI_USE_NULL_PKT_BLLP 0x238
+#define DPI_VACTIVE 0x23c
+#define DPI_VC 0x240
+
+/* apb pkt */
+#define HOST_TX_PAYLOAD 0x280
+
+#define HOST_PKT_CONTROL 0x284
+#define HOST_PKT_CONTROL_WC(x) (((x) & 0xffff) << 0)
+#define HOST_PKT_CONTROL_VC(x) (((x) & 0x3) << 16)
+#define HOST_PKT_CONTROL_DT(x) (((x) & 0x3f) << 18)
+#define HOST_PKT_CONTROL_HS_SEL(x) (((x) & 0x1) << 24)
+#define HOST_PKT_CONTROL_BTA_TX(x) (((x) & 0x1) << 25)
+#define HOST_PKT_CONTROL_BTA_NO_TX(x) (((x) & 0x1) << 26)
+
+#define HOST_SEND_PACKET 0x288
+#define HOST_PKT_STATUS 0x28c
+#define HOST_PKT_FIFO_WR_LEVEL 0x290
+#define HOST_PKT_FIFO_RD_LEVEL 0x294
+#define HOST_PKT_RX_PAYLOAD 0x298
+
+#define HOST_PKT_RX_PKT_HEADER 0x29c
+#define HOST_PKT_RX_PKT_HEADER_WC(x) (((x) & 0xffff) << 0)
+#define HOST_PKT_RX_PKT_HEADER_DT(x) (((x) & 0x3f) << 16)
+#define HOST_PKT_RX_PKT_HEADER_VC(x) (((x) & 0x3) << 22)
+
+#define HOST_IRQ_STATUS 0x2a0
+#define HOST_IRQ_STATUS_SM_NOT_IDLE (1 << 0)
+#define HOST_IRQ_STATUS_TX_PKT_DONE (1 << 1)
+#define HOST_IRQ_STATUS_DPHY_DIRECTION (1 << 2)
+#define HOST_IRQ_STATUS_TX_FIFO_OVFLW (1 << 3)
+#define HOST_IRQ_STATUS_TX_FIFO_UDFLW (1 << 4)
+#define HOST_IRQ_STATUS_RX_FIFO_OVFLW (1 << 5)
+#define HOST_IRQ_STATUS_RX_FIFO_UDFLW (1 << 6)
+#define HOST_IRQ_STATUS_RX_PKT_HDR_RCVD (1 << 7)
+#define HOST_IRQ_STATUS_RX_PKT_PAYLOAD_DATA_RCVD (1 << 8)
+#define HOST_IRQ_STATUS_HOST_BTA_TIMEOUT (1 << 29)
+#define HOST_IRQ_STATUS_LP_RX_TIMEOUT (1 << 30)
+#define HOST_IRQ_STATUS_HS_TX_TIMEOUT (1 << 31)
+
+#define HOST_IRQ_STATUS2 0x2a4
+#define HOST_IRQ_STATUS2_SINGLE_BIT_ECC_ERR (1 << 0)
+#define HOST_IRQ_STATUS2_MULTI_BIT_ECC_ERR (1 << 1)
+#define HOST_IRQ_STATUS2_CRC_ERR (1 << 2)
+
+#define HOST_IRQ_MASK 0x2a8
+#define HOST_IRQ_MASK_SM_NOT_IDLE_MASK (1 << 0)
+#define HOST_IRQ_MASK_TX_PKT_DONE_MASK (1 << 1)
+#define HOST_IRQ_MASK_DPHY_DIRECTION_MASK (1 << 2)
+#define HOST_IRQ_MASK_TX_FIFO_OVFLW_MASK (1 << 3)
+#define HOST_IRQ_MASK_TX_FIFO_UDFLW_MASK (1 << 4)
+#define HOST_IRQ_MASK_RX_FIFO_OVFLW_MASK (1 << 5)
+#define HOST_IRQ_MASK_RX_FIFO_UDFLW_MASK (1 << 6)
+#define HOST_IRQ_MASK_RX_PKT_HDR_RCVD_MASK (1 << 7)
+#define HOST_IRQ_MASK_RX_PKT_PAYLOAD_DATA_RCVD_MASK (1 << 8)
+#define HOST_IRQ_MASK_HOST_BTA_TIMEOUT_MASK (1 << 29)
+#define HOST_IRQ_MASK_LP_RX_TIMEOUT_MASK (1 << 30)
+#define HOST_IRQ_MASK_HS_TX_TIMEOUT_MASK (1 << 31)
+
+#define HOST_IRQ_MASK2 0x2ac
+#define HOST_IRQ_MASK2_SINGLE_BIT_ECC_ERR_MASK (1 << 0)
+#define HOST_IRQ_MASK2_MULTI_BIT_ECC_ERR_MASK (1 << 1)
+#define HOST_IRQ_MASK2_CRC_ERR_MASK (1 << 2)
+
+/* ------------------------------------- end -------------------------------- */
+#define BITSLICE(x, a, b) (((x) >> (b)) & ((1 << ((a)-(b)+1)) - 1))
+
+#ifdef DEBUG
+#define W32(reg, val) \
+do {printf("%s():%d reg 0x%p val 0x%08x\n",\
+ __func__, __LINE__, reg, val);\
+ __raw_writel(val, reg); } while (0)
+#else
+#define W32(reg, val) __raw_writel(val, reg)
+#endif
+
+#define R32(reg) __raw_readl(reg)
+
+/* helper functions */
+inline void dsi_host_ctrl_csr_setup(void __iomem *base,
+ struct dsi_cfg_csr_object *dsi_config,
+ uint16_t csr_setup_mask)
+{
+ if (BITSLICE(csr_setup_mask, 0, 0))
+ W32(base + HOST_CFG_NUM_LANES,
+ dsi_config->dsi_host_cfg_num_lanes);
+ if (BITSLICE(csr_setup_mask, 1, 1))
+ W32(base + HOST_CFG_NONCONTINUOUS_CLK,
+ dsi_config->dsi_host_cfg_noncont_clk);
+ if (BITSLICE(csr_setup_mask, 2, 2))
+ W32(base + HOST_CFG_T_PRE, dsi_config->dsi_host_cfg_t_pre);
+ if (BITSLICE(csr_setup_mask, 3, 3))
+ W32(base + HOST_CFG_T_POST,
+ dsi_config->dsi_host_cfg_t_post);
+ if (BITSLICE(csr_setup_mask, 4, 4))
+ W32(base + HOST_CFG_TX_GAP,
+ dsi_config->dsi_host_cfg_tx_gap);
+ if (BITSLICE(csr_setup_mask, 5, 5))
+ W32(base + HOST_CFG_AUTOINSERT_EOTP,
+ dsi_config->dsi_host_cfg_autoinsert_eotp);
+ if (BITSLICE(csr_setup_mask, 6, 6))
+ W32(base + HOST_CFG_EXTRA_CMDS_AFTER_EOTP,
+ dsi_config->dsi_host_cfg_extrcmd_after_eotp);
+ if (BITSLICE(csr_setup_mask, 7, 7))
+ W32(base + HOST_CFG_HTX_TO_COUNT,
+ dsi_config->dsi_host_cfg_htx_to_cnt);
+ if (BITSLICE(csr_setup_mask, 8, 8))
+ W32(base + HOST_CFG_LRX_H_TO_COUNT,
+ dsi_config->dsi_host_cfg_lrx_h_to_cnt);
+ if (BITSLICE(csr_setup_mask, 9, 9))
+ W32(base + HOST_CFG_BTA_H_TO_COUNT,
+ dsi_config->dsi_host_cfg_bta_h_to_cnt);
+ if (BITSLICE(csr_setup_mask, 10, 10))
+ W32(base + HOST_CFG_TWAKEUP,
+ dsi_config->dsi_host_cfg_twakeup);
+}
+
+inline void dsi_host_ctrl_dpi_setup(void __iomem *base,
+ struct dsi_cfg_dpi_object *dsi_config,
+ uint32_t dpi_setup_mask)
+{
+ if (BITSLICE(dpi_setup_mask, 0, 0))
+ W32(base + DPI_PIXEL_PAYLOAD_SIZE,
+ dsi_config->dsi_host_cfg_dpi_pxl_payld_size);
+ if (BITSLICE(dpi_setup_mask, 1, 1))
+ W32(base + DPI_PIXEL_FIFO_SEND_LEVEL,
+ dsi_config->dsi_host_cfg_dpi_pxl_fifo_send_lev);
+ if (BITSLICE(dpi_setup_mask, 2, 2))
+ W32(base + DPI_INTERFACE_COLOR_CODING,
+ dsi_config->dsi_host_cfg_dpi_if_color_coding);
+ if (BITSLICE(dpi_setup_mask, 3, 3))
+ W32(base + DPI_PIXEL_FORMAT,
+ dsi_config->dsi_host_cfg_dpi_pxl_format);
+ if (BITSLICE(dpi_setup_mask, 4, 4))
+ W32(base + DPI_VSYNC_POLARITY,
+ dsi_config->dsi_host_cfg_dpi_vsync_pol);
+ if (BITSLICE(dpi_setup_mask, 5, 5))
+ W32(base + DPI_HSYNC_POLARITY,
+ dsi_config->dsi_host_cfg_dpi_hsync_pol);
+ if (BITSLICE(dpi_setup_mask, 6, 6))
+ W32(base + DPI_VIDEO_MODE,
+ dsi_config->dsi_host_cfg_dpi_video_mode);
+ if (BITSLICE(dpi_setup_mask, 7, 7))
+ W32(base + DPI_HFP, dsi_config->dsi_host_cfg_dpi_hfp);
+ if (BITSLICE(dpi_setup_mask, 8, 8))
+ W32(base + DPI_HBP, dsi_config->dsi_host_cfg_dpi_hbp);
+ if (BITSLICE(dpi_setup_mask, 9, 9))
+ W32(base + DPI_HSA, dsi_config->dsi_host_cfg_dpi_hsa);
+ if (BITSLICE(dpi_setup_mask, 10, 10))
+ W32(base + DPI_ENABLE_MULT_PKTS,
+ dsi_config->dsi_host_cfg_dpi_en_mult_pkt);
+ if (BITSLICE(dpi_setup_mask, 11, 11))
+ W32(base + DPI_VBP, dsi_config->dsi_host_cfg_dpi_vbp);
+ if (BITSLICE(dpi_setup_mask, 12, 12))
+ W32(base + DPI_VFP, dsi_config->dsi_host_cfg_dpi_vfp);
+ if (BITSLICE(dpi_setup_mask, 13, 13))
+ W32(base + DPI_BLLP_MODE,
+ dsi_config->dsi_host_cfg_dpi_bllp_mode);
+ if (BITSLICE(dpi_setup_mask, 14, 14))
+ W32(base + DPI_USE_NULL_PKT_BLLP,
+ dsi_config->dsi_host_cfg_dpi_null_pkt_bllp);
+ if (BITSLICE(dpi_setup_mask, 15, 15))
+ W32(base + DPI_VACTIVE,
+ dsi_config->dsi_host_cfg_dpi_vactive);
+ if (BITSLICE(dpi_setup_mask, 16, 16))
+ W32(base + DPI_VC, dsi_config->dsi_host_cfg_dpi_vc);
+}
+
+inline void dsi_host_ctrl_pkt_setup(void __iomem *base,
+ struct dsi_cfg_pkt_object *dsi_config,
+ uint8_t pkt_setup_mask)
+{
+ if (BITSLICE(pkt_setup_mask, 0, 0))
+ W32(base + HOST_PKT_CONTROL,
+ dsi_config->dsi_host_pkt_ctrl);
+ if (BITSLICE(pkt_setup_mask, 2, 2))
+ W32(base + HOST_IRQ_MASK, dsi_config->dsi_host_irq_mask);
+ if (BITSLICE(pkt_setup_mask, 3, 3))
+ W32(base + HOST_IRQ_MASK2, dsi_config->dsi_host_irq_mask2);
+ if (BITSLICE(pkt_setup_mask, 1, 1))
+ W32(base + HOST_SEND_PACKET,
+ dsi_config->dsi_host_send_pkt);
+}
+
+inline void dsi_host_ctrl_dphy_setup(void __iomem *base,
+ struct dsi_cfg_dphy_object *dsi_config,
+ uint32_t dphy_setup_mask)
+{
+ int i;
+
+ if (BITSLICE(dphy_setup_mask, 8, 8))
+ W32(base + DPHY_TST, dsi_config->dphy_tst);
+ if (BITSLICE(dphy_setup_mask, 9, 9))
+ W32(base + DPHY_CN, dsi_config->dphy_cn);
+ if (BITSLICE(dphy_setup_mask, 10, 10))
+ W32(base + DPHY_CM, dsi_config->dphy_cm);
+ if (BITSLICE(dphy_setup_mask, 11, 11))
+ W32(base + DPHY_CO, dsi_config->dphy_co);
+ if (BITSLICE(dphy_setup_mask, 7, 7))
+ W32(base + DPHY_PD_PLL, dsi_config->dphy_pd_pll);
+ /* todo: disable on zebu */
+ /*Polling of DPHY Lock status / wait for PLL lock */
+ for (i = 0; i < 100; i++) {
+ u32 lock;
+ udelay(10);
+ /*todo: zebu abort when reading DPHY LOCK */
+ lock = R32(DPHY_LOCK);
+ printf("DPHY PLL Lock = 0x%08x\n", lock);
+ }
+ /*todo: Need to wait for lock here */
+
+ if (BITSLICE(dphy_setup_mask, 1, 1))
+ W32(base + DPHY_M_PRG_HS_PREPARE,
+ dsi_config->dphy_m_prg_hs_prepare);
+ if (BITSLICE(dphy_setup_mask, 2, 2))
+ W32(base + DPHY_MC_PRG_HS_PREPARE,
+ dsi_config->dphy_mc_prg_hs_prepare);
+ if (BITSLICE(dphy_setup_mask, 3, 3))
+ W32(base + DPHY_M_PRG_HS_ZERO,
+ dsi_config->dphy_m_prg_hs_zero);
+ if (BITSLICE(dphy_setup_mask, 4, 4))
+ W32(base + DPHY_MC_PRG_HS_ZERO,
+ dsi_config->dphy_mc_prg_hs_zero);
+ if (BITSLICE(dphy_setup_mask, 5, 5))
+ W32(base + DPHY_M_PRG_HS_TRAIL,
+ dsi_config->dphy_m_prg_hs_trial);
+ if (BITSLICE(dphy_setup_mask, 6, 6))
+ W32(base + DPHY_MC_PRG_HS_TRAIL,
+ dsi_config->dphy_mc_prg_hs_trial);
+ if (BITSLICE(dphy_setup_mask, 0, 0))
+ W32(base + DPHY_PD_TX, dsi_config->dphy_pd_tx);
+ if (BITSLICE(dphy_setup_mask, 12, 12))
+ W32(base + DPHY_LOCK, dsi_config->dphy_lock);
+ if (BITSLICE(dphy_setup_mask, 13, 13))
+ W32(base + DPHY_LOCK_BYP, dsi_config->dphy_lock_byp);
+}
+#endif /* _IMX8_MIPI_DSI_H_ */