rk3036 lcdc: add support hwc layer
authorhjc <hjc@rock-chips.com>
Mon, 22 Sep 2014 06:00:18 +0000 (14:00 +0800)
committerhjc <hjc@rock-chips.com>
Mon, 22 Sep 2014 06:06:00 +0000 (14:06 +0800)
arch/arm/boot/dts/rk3036.dtsi
drivers/video/rockchip/lcdc/rk3036_lcdc.c
drivers/video/rockchip/lcdc/rk3036_lcdc.h

index 640409b4d3870cc4fa802b10dfdbbfcb450e0d9d..38ef3d7d0d9a22d4fcba1a901e460bc18210f249 100755 (executable)
 
        lcdc: lcdc@10118000 {
                compatible = "rockchip,rk3036-lcdc";
-               reg = <0x10118000 0x200>;
+               reg = <0x10118000 0x1000>;
                interrupts = <GIC_SPI 43 IRQ_TYPE_LEVEL_HIGH>;
                status = "disabled";
                clocks = <&clk_gates9 6>, <&dclk_lcdc1>, <&clk_gates9 5>;
index 1c7ff77443656802451669a558858739e8d730a5..b0dd1294a4d6d7577935601279861bdc1df2e1b1 100755 (executable)
@@ -221,6 +221,21 @@ static int rk3036_lcdc_alpha_cfg(struct lcdc_device *lcdc_dev)
                val = v_WIN0_ALPHA_EN(0) | v_WIN1_ALPHA_EN(0);
                lcdc_msk_reg(lcdc_dev, ALPHA_CTRL, mask, val);
        }
+
+       if(lcdc_dev->driver.win[2]->state == 1) {
+               mask =  m_HWC_ALPAH_EN;
+               val = v_HWC_ALPAH_EN(1);
+               lcdc_msk_reg(lcdc_dev, ALPHA_CTRL, mask, val);
+
+               mask =  m_HWC_ALPHA_MODE;
+               val = v_HWC_ALPHA_MODE(1);
+               lcdc_msk_reg(lcdc_dev, DSP_CTRL0, mask, val);
+       } else {
+               mask =  m_HWC_ALPAH_EN;
+               val = v_HWC_ALPAH_EN(0);
+               lcdc_msk_reg(lcdc_dev, ALPHA_CTRL, mask, val);
+       }
+
        return 0;
 }
 
@@ -228,6 +243,7 @@ static void lcdc_layer_update_regs(struct lcdc_device *lcdc_dev,
                                   struct rk_lcdc_win *win)
 {
        u32 mask, val;
+       int hwc_size;
 
        if (win->state == 1) {
                if (win->id == 0) {
@@ -282,8 +298,22 @@ static void lcdc_layer_update_regs(struct lcdc_device *lcdc_dev,
                                    v_DSP_STX(win->area[0].dsp_stx) |
                                    v_DSP_STY(win->area[0].dsp_sty));
                        lcdc_writel(lcdc_dev, WIN1_MST, win->area[0].y_addr);
-               } /* else if (win->id == 2) {
-               }*/
+               } else if (win->id == 2) {
+                       mask = m_HWC_EN | m_HWC_LODAD_EN;
+                       val = v_HWC_EN(win->state) | v_HWC_LODAD_EN(1);
+                       lcdc_msk_reg(lcdc_dev, SYS_CTRL, mask, val);
+                       if((win->area[0].xsize == 32) &&(win->area[0].ysize == 32))
+                               hwc_size = 0;
+                       else if((win->area[0].xsize == 64) &&(win->area[0].ysize == 64))
+                               hwc_size = 1;
+                       else
+                               dev_err(lcdc_dev->dev,"unsupport hwc size:x=%d,y=%d\n",
+                                       win->area[0].xsize,win->area[0].ysize);
+                       lcdc_writel(lcdc_dev, HWC_DSP_ST,
+                                   v_DSP_STX(win->area[0].dsp_stx) |
+                                   v_DSP_STY(win->area[0].dsp_sty));
+                       lcdc_writel(lcdc_dev, HWC_MST, win->area[0].y_addr);
+               }
        } else {
                win->area[0].y_addr = 0;
                win->area[0].uv_addr = 0;
@@ -392,6 +422,35 @@ static void rk3036_lcdc_mmu_en(struct rk_lcdc_driver *dev_drv)
        spin_unlock(&lcdc_dev->reg_lock);
 }
 
+static int rk3036_lcdc_set_hwc_lut(struct rk_lcdc_driver *dev_drv, int *hwc_lut,int mode)
+{
+       int i = 0;
+       int __iomem *c;
+       int v;
+       int len=256*4;
+       struct lcdc_device *lcdc_dev =
+                container_of(dev_drv, struct lcdc_device, driver);
+       if(dev_drv->hwc_lut == NULL) {
+               dev_drv->hwc_lut = devm_kzalloc(lcdc_dev->dev, len, GFP_KERNEL);
+       }
+       spin_lock(&lcdc_dev->reg_lock);
+       lcdc_msk_reg(lcdc_dev, SYS_CTRL, m_HWC_LUT_EN, v_HWC_LUT_EN(0));
+       lcdc_cfg_done(lcdc_dev);
+       mdelay(25);
+       for (i = 0; i < 256; i++) {
+               if(mode == 1)
+                       dev_drv->hwc_lut[i] = hwc_lut[i];
+               v = dev_drv->hwc_lut[i];
+               c = lcdc_dev->hwc_lut_addr_base + i;
+               writel_relaxed(v, c);
+       }
+       lcdc_msk_reg(lcdc_dev, SYS_CTRL, m_HWC_LUT_EN, v_HWC_LUT_EN(1));
+        lcdc_cfg_done(lcdc_dev);
+        spin_unlock(&lcdc_dev->reg_lock);
+
+       return 0;
+
+}
 static int rk3036_lcdc_set_dclk(struct rk_lcdc_driver *dev_drv)
 {
 #ifdef CONFIG_RK_FPGA
@@ -718,6 +777,8 @@ static int rk3036_lcdc_set_par(struct rk_lcdc_driver *dev_drv, int win_id)
                win = dev_drv->win[0];
        } else if (win_id == 1) {
                win = dev_drv->win[1];
+       } else if (win_id == 2) {
+               win = dev_drv->win[2];
        } else {
                dev_err(dev_drv->dev, "un supported win number:%d\n", win_id);
                return -EINVAL;
@@ -850,7 +911,9 @@ static int rk3036_lcdc_pan_display(struct rk_lcdc_driver *dev_drv, int win_id)
                win = dev_drv->win[0];
        } else if (win_id == 1) {
                win = dev_drv->win[1];
-       } else {
+       } else if (win_id == 2) {
+               win = dev_drv->win[2];
+       }else {
                dev_err(dev_drv->dev, "invalid win number:%d!\n", win_id);
                return -EINVAL;
        }
@@ -1007,6 +1070,8 @@ static int rk3036_lcdc_early_resume(struct rk_lcdc_driver *dev_drv)
        if (lcdc_dev->atv_layer_cnt) {
                rk3036_lcdc_clk_enable(lcdc_dev);
                rk3036_lcdc_reg_restore(lcdc_dev);
+               /*set hwc lut*/
+               rk3036_lcdc_set_hwc_lut(dev_drv, dev_drv->hwc_lut, 0);
 
                spin_lock(&lcdc_dev->reg_lock);
 
@@ -1404,6 +1469,7 @@ static struct rk_lcdc_drv_ops lcdc_drv_ops = {
        .get_dsp_bcsh_bcs       = rk3036_lcdc_get_bcsh_bcs,
        .open_bcsh              = rk3036_lcdc_open_bcsh,
        .set_overscan           = rk3036_lcdc_set_overscan,
+       .set_hwc_lut            = rk3036_lcdc_set_hwc_lut,
 };
 
 static int rk3036_lcdc_parse_dt(struct lcdc_device *lcdc_dev)
@@ -1456,6 +1522,8 @@ static int rk3036_lcdc_probe(struct platform_device *pdev)
        if (IS_ERR(lcdc_dev->regsbak))
                return PTR_ERR(lcdc_dev->regsbak);
 
+       lcdc_dev->hwc_lut_addr_base = (lcdc_dev->regs + HWC_LUT_ADDR);
+
        dev_set_name(lcdc_dev->dev, "lcdc%d", lcdc_dev->id);
        dev_drv = &lcdc_dev->driver;
        dev_drv->dev = dev;
@@ -1553,4 +1621,4 @@ static void __exit rk3036_lcdc_module_exit(void)
 }
 
 fs_initcall(rk3036_lcdc_module_init);
-module_exit(rk3036_lcdc_module_exit);
\ No newline at end of file
+module_exit(rk3036_lcdc_module_exit);
index 83d90299583faf5ec7ada06e9db6578118e0aa9d..b2b75e125cfdb03c464abe898fd5f76be3af322d 100755 (executable)
@@ -481,6 +481,7 @@ struct lcdc_device {
        spinlock_t  reg_lock;   /* one time only one process allowed to
                                   config the register*/
 
+       int __iomem *hwc_lut_addr_base;
        int __iomem *dsp_lut_addr_base;