rk3368 lcdc: reset lcdc when switch screen video mode
authorhjc <hjc@rock-chips.com>
Thu, 9 Apr 2015 03:27:15 +0000 (11:27 +0800)
committerhjc <hjc@rock-chips.com>
Thu, 9 Apr 2015 03:30:35 +0000 (11:30 +0800)
Signed-off-by: hjc <hjc@rock-chips.com>
arch/arm64/boot/dts/rk3368.dtsi
drivers/video/rockchip/lcdc/rk3368_lcdc.c
drivers/video/rockchip/lcdc/rk3368_lcdc.h

index 49bf12e0bb1d7b485283f2cc8be513d68211342f..ce2cd49698215b6072fb81030ef793f5c77ca138 100755 (executable)
                 compatible = "rockchip,rk3368-lcdc";
                 rockchip,grf = <&grf>;
                 rockchip,pmugrf = <&pmugrf>;
+                rockchip,cru = <&cru>;
                 rockchip,prop = <PRMRY>;
                 rockchip,pwr18 = <0>;
                 rockchip,iommu-enabled = <0>;
index 7b1c6a054d1bc62a1f0c8be86395900800726fb8..14e969f7b5754d75e7be813bb149b49a50e6d595 100755 (executable)
@@ -1720,6 +1720,60 @@ static int rk3368_post_dspbuf(struct rk_lcdc_driver *dev_drv, u32 rgb_mst,
        return 0;
 }
 
+static int lcdc_reset(struct rk_lcdc_driver *dev_drv, bool initscreen)
+{
+       struct lcdc_device *lcdc_dev =
+           container_of(dev_drv, struct lcdc_device, driver);
+       u32 mask, val;
+       u32 v;
+        /*printk("0407:standby=%d,initscreen=%d,dev_drv->first_frame=%d\n",
+                lcdc_dev->standby,initscreen,dev_drv->first_frame);*/
+       if (!lcdc_dev->standby && initscreen && (dev_drv->first_frame != 1)) {
+               mdelay(150);
+               mask = m_WIN0_EN;
+               val = v_WIN0_EN(0);
+               lcdc_msk_reg(lcdc_dev, WIN0_CTRL0, mask, val);
+
+               lcdc_msk_reg(lcdc_dev, WIN1_CTRL0, mask, val);
+
+               mask = m_WIN2_EN | m_WIN2_MST0_EN |
+                       m_WIN2_MST1_EN |
+                       m_WIN2_MST2_EN | m_WIN2_MST3_EN;
+               val = v_WIN2_EN(0) | v_WIN2_MST0_EN(0) |
+                       v_WIN2_MST1_EN(0) |
+                       v_WIN2_MST2_EN(0) | v_WIN2_MST3_EN(0);
+               lcdc_msk_reg(lcdc_dev, WIN2_CTRL0, mask, val);
+               lcdc_msk_reg(lcdc_dev, WIN3_CTRL0, mask, val);
+               mask = m_HDMI_OUT_EN;
+               val = v_HDMI_OUT_EN(0);
+               lcdc_msk_reg(lcdc_dev, SYS_CTRL, mask, val);
+               lcdc_cfg_done(lcdc_dev);
+               mdelay(50);
+               writel_relaxed(0, lcdc_dev->regs + REG_CFG_DONE);
+               if (dev_drv->iommu_enabled) {
+                       if (dev_drv->mmu_dev)
+                               rockchip_iovmm_deactivate(dev_drv->dev);
+               }
+               lcdc_cru_writel(lcdc_dev->cru_base, 0x0318,
+                               (1 << 4)  | (1 << 5)  | (1 << 6) |
+                               (1 << 20) | (1 << 21) | (1 << 22));
+               udelay(100);
+               v = lcdc_cru_readl(lcdc_dev->cru_base, 0x0318);
+               pr_info("cru read = 0x%x\n", v);
+               lcdc_cru_writel(lcdc_dev->cru_base, 0x0318,
+                               (0 << 4)  | (0 << 5)  | (0 << 6) |
+                               (1 << 20) | (1 << 21) | (1 << 22));
+               mdelay(100);
+               if (dev_drv->iommu_enabled) {
+                       if (dev_drv->mmu_dev)
+                               rockchip_iovmm_activate(dev_drv->dev);
+               }
+               mdelay(50);
+               rk3368_lcdc_reg_restore(lcdc_dev);
+               mdelay(50);
+       }
+       return 0;
+}
 
 static int rk3368_load_screen(struct rk_lcdc_driver *dev_drv, bool initscreen)
 {
@@ -1734,12 +1788,16 @@ static int rk3368_load_screen(struct rk_lcdc_driver *dev_drv, bool initscreen)
        spin_lock(&lcdc_dev->reg_lock);
        if (likely(lcdc_dev->clk_on)) {
                dev_drv->overlay_mode = VOP_RGB_DOMAIN;
+#if 0
                if (!lcdc_dev->standby && !initscreen) {
                        lcdc_msk_reg(lcdc_dev, SYS_CTRL, m_STANDBY_EN,
                                     v_STANDBY_EN(1));
                        lcdc_cfg_done(lcdc_dev);
                        mdelay(50);
                }
+#else
+        lcdc_reset(dev_drv, initscreen);
+#endif
                switch (screen->face) {
                case OUT_P565:
                        face = OUT_P565;
@@ -1917,7 +1975,9 @@ static int rk3368_load_screen(struct rk_lcdc_driver *dev_drv, bool initscreen)
        }
        spin_unlock(&lcdc_dev->reg_lock);
        rk3368_lcdc_set_dclk(dev_drv, 1);
-       if (screen->type != SCREEN_HDMI && dev_drv->trsm_ops &&
+       if (screen->type != SCREEN_HDMI &&
+           screen->type != SCREEN_TVOUT &&
+           dev_drv->trsm_ops &&
            dev_drv->trsm_ops->enable)
                dev_drv->trsm_ops->enable();
        if (screen->init)
@@ -2072,7 +2132,7 @@ static int rk3368_lcdc_open(struct rk_lcdc_driver *dev_drv, int win_id,
           rockchip_clear_system_status(sys_status);
           #endif
           } */
-
+        dev_drv->first_frame = 0;
        return 0;
 }
 
@@ -2184,11 +2244,6 @@ static int rk3368_lcdc_pan_display(struct rk_lcdc_driver *dev_drv, int win_id)
                return -EINVAL;
        }
 
-       /*this is the first frame of the system ,enable frame start interrupt */
-       if ((dev_drv->first_frame)) {
-               dev_drv->first_frame = 0;
-               rk3368_lcdc_enable_irq(dev_drv);
-       }
 #if defined(WAIT_FOR_SYNC)
        spin_lock_irqsave(&dev_drv->cpl_lock, flags);
        init_completion(&dev_drv->frame_done);
@@ -4624,6 +4679,13 @@ static int rk3368_lcdc_probe(struct platform_device *pdev)
                return PTR_ERR(lcdc_dev->pmugrf_base);
        }
 
+       lcdc_dev->cru_base =
+               syscon_regmap_lookup_by_phandle(np, "rockchip,cru");
+       if (IS_ERR(lcdc_dev->cru_base)) {
+               dev_err(&pdev->dev, "can't find lcdc cru_base property\n");
+               return PTR_ERR(lcdc_dev->cru_base);
+       }
+
        lcdc_dev->id = 0;
        dev_set_name(lcdc_dev->dev, "lcdc%d", lcdc_dev->id);
        dev_drv = &lcdc_dev->driver;
index 5db9ec588d3baa50432c1a7cba53454fb03d067f..a4c9b9bbf723fa2726683444bb147f52277e9add 100755 (executable)
@@ -1744,6 +1744,7 @@ struct lcdc_device {
        u32 reg_phy_base;       /* physical basic address of lcdc register*/
        struct regmap *grf_base;
        struct regmap *pmugrf_base;
+       struct regmap *cru_base;
        u32 len;                /* physical map length of lcdc register*/
        /*one time only one process allowed to config the register*/
        spinlock_t reg_lock;
@@ -1879,6 +1880,24 @@ static inline int lcdc_grf_writel(struct regmap *base,
        return 0;
 }
 
+static inline int lcdc_cru_writel(struct regmap *base,
+                                 u32 offset, u32 val)
+{
+       regmap_write(base, offset, val);
+       dsb(sy);
+
+       return 0;
+}
+
+static inline int lcdc_cru_readl(struct regmap *base,
+                                 u32 offset)
+{
+       u32 v;
+       regmap_read(base, offset, &v);
+
+       return v;
+}
+
 #define CUBIC_PRECISE  0
 #define CUBIC_SPLINE   1
 #define CUBIC_CATROM   2