MLK-15324-3 imx8: Add LVDS and DC setup common functions
authorYe Li <ye.li@nxp.com>
Mon, 3 Jul 2017 08:58:22 +0000 (03:58 -0500)
committerJason Liu <jason.hui.liu@nxp.com>
Thu, 2 Nov 2017 18:37:00 +0000 (02:37 +0800)
Add common functions for LVDS/DC setup, video framebuffer init/disable,
LVDS to HDMI card settings, etc. Refactor it from video_imxdpuv1.c.
1. Add power, clocks, PLL relevant setup for LVDS and DC.
2. Configure the LVDS and its PHY settings for the display format and pixel link.
3. Setup the LVDS to HDMI card.
4. Implement the video_hw_init by calling DC driver API to output data to
   specified display panel.

Signed-off-by: Oliver Brown <oliver.brown@nxp.com>
Signed-off-by: Ye Li <ye.li@nxp.com>
arch/arm/cpu/armv8/imx8/Makefile
arch/arm/cpu/armv8/imx8/cpu.c
arch/arm/cpu/armv8/imx8/video_common.c [new file with mode: 0644]
arch/arm/imx-common/Makefile
arch/arm/imx-common/video.c
arch/arm/include/asm/arch-imx8/imx-regs.h
arch/arm/include/asm/arch-imx8/imx8_lvds.h [new file with mode: 0644]
arch/arm/include/asm/arch-imx8/imx8_mipi_dsi.h [new file with mode: 0644]
arch/arm/include/asm/arch-imx8/video_common.h [new file with mode: 0644]
arch/arm/include/asm/imx-common/video.h

index 62ccac1..eaf6614 100644 (file)
@@ -9,3 +9,4 @@ obj-y += clock.o
 obj-y += fsl_mu_hal.o
 obj-y += fuse.o
 obj-y += iomux.o
+obj-$(CONFIG_VIDEO_IMXDPUV1) += video_common.o
index ead175f..f28f66a 100644 (file)
@@ -17,6 +17,7 @@
 #include <asm/arch/sid.h>
 #include <asm/arch-imx/cpu.h>
 #include <asm/arch/sys_proto.h>
+#include <asm/arch/video_common.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -603,12 +604,18 @@ sc_err_t imx8_config_smmu_sid(struct smmu_sid *dev_sids, int size)
 
        return SC_ERR_NONE;
 }
+#endif
 
 void arch_preboot_os(void)
 {
+#if defined(CONFIG_VIDEO_IMXDPUV1)
+       imxdpuv1_fb_disable();
+#endif
+#ifdef CONFIG_IMX_SMMU
        imx8_config_smmu_sid(dev_sids, ARRAY_SIZE(dev_sids));
-}
 #endif
+}
+
 
 enum boot_device get_boot_device(void)
 {
diff --git a/arch/arm/cpu/armv8/imx8/video_common.c b/arch/arm/cpu/armv8/imx8/video_common.c
new file mode 100644 (file)
index 0000000..458370b
--- /dev/null
@@ -0,0 +1,626 @@
+/*
+ * 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;
+}
+
index 7e3b303..bfc737b 100644 (file)
@@ -51,6 +51,7 @@ endif
 ifeq ($(SOC),$(filter $(SOC),imx8))
 obj-$(CONFIG_HAVE_SC_FIRMWARE) += sci/
 obj-$(CONFIG_IMX_BOOTAUX) += imx_bootaux.o
+obj-$(CONFIG_IMX_VIDEO_SKIP) += video.o
 endif
 ifneq ($(CONFIG_SPL_BUILD),y)
 obj-$(CONFIG_CMD_BMODE) += cmd_bmode.o
index 0f61593..7eed32c 100644 (file)
@@ -39,6 +39,9 @@ int board_video_skip(void)
 #if defined(CONFIG_VIDEO_IPUV3)
                ret = ipuv3_fb_init(&displays[i].mode, displays[i].di ? 1 : 0,
                                    displays[i].pixfmt);
+#elif defined(CONFIG_VIDEO_IMXDPUV1)
+               ret = imxdpuv1_fb_init(&displays[i].mode, displays[i].bus,
+                                       displays[i].pixfmt);
 #elif defined(CONFIG_VIDEO_MXS)
                ret = mxs_lcd_panel_setup(displays[i].mode,
                                        displays[i].pixfmt,
@@ -56,7 +59,8 @@ int board_video_skip(void)
                        printf("LCD %s cannot be configured: %d\n",
                               displays[i].mode.name, ret);
        } else {
-               printf("unsupported panel %s\n", panel);
+               if (strcmp(panel, "NULL"))
+                       printf("unsupported panel %s\n", panel);
                return -EINVAL;
        }
 
index 78c44a4..12d0f81 100644 (file)
 #define LPI2C4_BASE_ADDR       0x5A830000
 #define LPI2C5_BASE_ADDR       0x5A840000
 
+#ifdef CONFIG_IMX8QXP
+#define LVDS0_PHYCTRL_BASE 0x56221000
+#define LVDS1_PHYCTRL_BASE 0x56241000
+#define MIPI0_SS_BASE 0x56220000
+#define MIPI1_SS_BASE 0x56240000
+#endif
+
+#ifdef CONFIG_IMX8QM
+#define LVDS0_PHYCTRL_BASE 0x56241000
+#define LVDS1_PHYCTRL_BASE 0x57241000
+#define MIPI0_SS_BASE 0x56220000
+#define MIPI1_SS_BASE 0x57220000
+#endif
+
 #ifdef CONFIG_LPUART
 #define LPUART_BASE            SCU_LPUART_BASE
 #endif
diff --git a/arch/arm/include/asm/arch-imx8/imx8_lvds.h b/arch/arm/include/asm/arch-imx8/imx8_lvds.h
new file mode 100644 (file)
index 0000000..68fbf6d
--- /dev/null
@@ -0,0 +1,115 @@
+/*
+ * Copyright 2015-2016 Freescale Semiconductor, Inc.
+ * Copyright 2017 NXP
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#ifndef _IMX8_LVDS_H_
+#define _IMX8_LVDS_H_
+
+#define IMX_LVDS_SET_FIELD(__field__, __value__) (((__value__) << (__field__ ## _SHIFT)) & (__field__ ## _MASK))
+#define IMX_LVDS_GET_FIELD(__field__, __reg__) (((__reg__) & (__field__ ## _MASK)) >> (__field__  ## _SHIFT))
+
+#define IMX_LVDS_SET(__reg__)   (reg+0x4)
+#define IMX_LVDS_CLEAR(__reg__) (reg+0x8)
+#define IMX_LVDS_TOGGLE(__reg__)(reg+0x4)
+
+#define LVDS_CTRL                     0x0e0
+#define LVDS_CTRL_CH0_MODE_MASK       0x03U
+#define LVDS_CTRL_CH0_MODE_SHIFT      0U
+#define LVDS_CTRL_CH0_MODE__DISABLED  0x00U
+#define LVDS_CTRL_CH0_MODE__DI0       0x01U
+#define LVDS_CTRL_CH0_MODE__RESERVED  0x02U
+#define LVDS_CTRL_CH0_MODE__DI1       0x03U
+
+#define LVDS_CTRL_CH1_MODE_MASK       0x0cU
+#define LVDS_CTRL_CH1_MODE_SHIFT      2U
+#define LVDS_CTRL_CH1_MODE__DISABLED  0x00U
+#define LVDS_CTRL_CH1_MODE__DI0       0x01U
+#define LVDS_CTRL_CH1_MODE__RESERVED  0x02U
+#define LVDS_CTRL_CH1_MODE__DI1       0x03U
+
+#define LVDS_CTRL_SPLIT_MODE_MASK      0x10U
+#define LVDS_CTRL_SPLIT_MODE_SHIFT     4U
+#define LVDS_CTRL_SPLIT_MODE__DISABLE  0x00U
+#define LVDS_CTRL_SPLIT_MODE__ENABLE   0x01U
+
+#define LVDS_CTRL_CH0_DATA_WIDTH_MASK   0x20U
+#define LVDS_CTRL_CH0_DATA_WIDTH_SHIFT  5U
+#define LVDS_CTRL_CH0_DATA_WIDTH__18BIT 0x00U
+#define LVDS_CTRL_CH0_DATA_WIDTH__24BIT 0x01U
+
+#define LVDS_CTRL_CH0_BIT_MAP_MASK   0x40U
+#define LVDS_CTRL_CH0_BIT_MAP_SHIFT  6U
+#define LVDS_CTRL_CH0_BIT_MAP__SWWG  0x00U
+#define LVDS_CTRL_CH0_BIT_MAP__JEIDA 0x01U
+
+#define LVDS_CTRL_CH1_DATA_WIDTH_MASK   0x80U
+#define LVDS_CTRL_CH1_DATA_WIDTH_SHIFT  7U
+#define LVDS_CTRL_CH1_DATA_WIDTH__18BIT 0x00U
+#define LVDS_CTRL_CH1_DATA_WIDTH__24BIT 0x01U
+
+#define LVDS_CTRL_CH1_BIT_MAP_MASK  0x100U
+#define LVDS_CTRL_CH1_BIT_MAP_SHIFT  8U
+#define LVDS_CTRL_CH1_BIT_MAP__SWWG  0x00U
+#define LVDS_CTRL_CH1_BIT_MAP__JEIDA 0x01U
+
+#define LVDS_CTRL_DI0_VSYNC_POL_MASK        0x200U
+#define LVDS_CTRL_DI0_VSYNC_POL_SHIFT        9U
+#define LVDS_CTRL_DI0_VSYNC_POL__ACTIVE_LOW  0x00U
+#define LVDS_CTRL_DI0_VSYNC_POL__ACTIVE_HIGH 0x01U
+
+#define LVDS_CTRL_DI1_VSYNC_POL_MASK        0x400U
+#define LVDS_CTRL_DI1_VSYNC_POL_SHIFT        10U
+#define LVDS_CTRL_DI1_VSYNC_POL__ACTIVE_LOW  0x00U
+#define LVDS_CTRL_DI1_VSYNC_POL__ACTIVE_HIGH 0x01U
+
+#define LVDS_CTRL_CH0_10BIT_ENABLE_MASK         0x400000U
+#define LVDS_CTRL_CH0_10BIT_ENABLE_SHIFT           22U
+#define LVDS_CTRL_CH0_10BIT_ENABLE__USE_DATA_WIDTH 0x00U
+#define LVDS_CTRL_CH0_10BIT_ENABLE__10BIT          0x01U
+
+#define LVDS_CTRL_CH1_10BIT_ENABLE_MASK         0x800000U
+#define LVDS_CTRL_CH1_10BIT_ENABLE_SHIFT           23U
+#define LVDS_CTRL_CH1_10BIT_ENABLE__USE_DATA_WIDTH 0x00U
+#define LVDS_CTRL_CH1_10BIT_ENABLE__10BIT          0x01U
+
+#define LVDS_CTRL_DI0_DATA_WIDTH_MASK         0x03000000U
+#define LVDS_CTRL_DI0_DATA_WIDTH_SHIFT        24U
+#define LVDS_CTRL_DI0_DATA_WIDTH__USE_18BIT   0x00U
+#define LVDS_CTRL_DI0_DATA_WIDTH__USE_24BIT   0x1U
+#define LVDS_CTRL_DI0_DATA_WIDTH__USE_30BIT   0x2U
+
+#define LVDS_CTRL_DI1_DATA_WIDTH_MASK         0x0C000000U
+#define LVDS_CTRL_DI1_DATA_WIDTH_SHIFT        26U
+#define LVDS_CTRL_DI1_DATA_WIDTH__USE_18BIT   0x00U
+#define LVDS_CTRL_DI1_DATA_WIDTH__USE_24BIT   0x1U
+#define LVDS_CTRL_DI1_DATA_WIDTH__USE_30BIT   0x2U
+
+#define LVDS_PHY_CTRL         (0x0)
+
+#define LVDS_PHY_CTRL_PD_MASK       (1<<0)
+#define LVDS_PHY_CTRL_PD_SHIFT      (0)
+#define LVDS_PHY_CTRL_RFB_MASK      (1<<1)
+#define LVDS_PHY_CTRL_RFB_SHIFT     (1)
+#define LVDS_PHY_CTRL_NB_MASK       (1<<2)
+#define LVDS_PHY_CTRL_NB_SHIFT      (2)
+#define LVDS_PHY_CTRL_CH0_EN_MASK   (1<<3)
+#define LVDS_PHY_CTRL_CH0_EN_SHIFT  (3)
+#define LVDS_PHY_CTRL_CH1_EN_MASK   (1<<4)
+#define LVDS_PHY_CTRL_CH1_EN_SHIFT  (4)
+
+#define LVDS_PHY_CTRL_TST_MASK      (0x3f<<5)
+#define LVDS_PHY_CTRL_TST_SHIFT     (5)
+
+#define LVDS_PHY_CTRL_CA_MASK       (0x7<<11)
+#define LVDS_PHY_CTRL_CA_SHIFT      (11)
+
+#define LVDS_PHY_CTRL_CCM_MASK      (0x7<<14)
+#define LVDS_PHY_CTRL_CCM_SHIFT     (14)
+
+#define LVDS_PHY_CTRL_M_MASK        (0x3<<17)
+#define LVDS_PHY_CTRL_M_SHIFT       (17)
+
+#endif /* _IMX8_LVDS_H_ */
diff --git a/arch/arm/include/asm/arch-imx8/imx8_mipi_dsi.h b/arch/arm/include/asm/arch-imx8/imx8_mipi_dsi.h
new file mode 100644 (file)
index 0000000..63024f3
--- /dev/null
@@ -0,0 +1,394 @@
+/*
+ * 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_ */
diff --git a/arch/arm/include/asm/arch-imx8/video_common.h b/arch/arm/include/asm/arch-imx8/video_common.h
new file mode 100644 (file)
index 0000000..7fd10df
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2017 NXP
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ *
+ */
+
+#ifndef __ASM_ARCH_VIDEO_COMMON_H__
+#define __ASM_ARCH_VIDEO_COMMON_H__
+
+#include <asm/imx-common/sci/sci.h>
+#include <linux/fb.h>
+
+#define        PS2KHZ(ps)      (1000000000UL / (ps))
+
+int lvds2hdmi_setup(int i2c_bus);
+int lvds_soc_setup(int lvds_id, sc_pm_clock_rate_t pixel_clock);
+void lvds_configure(int lvds_id);
+int display_controller_setup(sc_pm_clock_rate_t pixel_clock);
+int imxdpuv1_fb_init(struct fb_videomode const *mode, uint8_t disp, uint32_t pixfmt);
+void imxdpuv1_fb_disable(void);
+
+#endif /* __ASM_ARCH_VIDEO_COMMON_H__ */
index 92b164a..36147fe 100644 (file)
@@ -10,6 +10,9 @@
 #include <linux/fb.h>
 #if defined(CONFIG_VIDEO_IPUV3)
 #include <ipu_pixfmt.h>
+#elif defined(CONFIG_VIDEO_IMXDPUV1)
+#include <imxdpuv1.h>
+#include <asm/arch/video_common.h>
 #elif defined(CONFIG_VIDEO_MXS)
 #include <mxsfb.h>
 #endif