From: hjc Date: Mon, 22 Sep 2014 06:00:18 +0000 (+0800) Subject: rk3036 lcdc: add support hwc layer X-Git-Tag: firefly_0821_release~4644 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=72f51bac1e679a8aacaf76ea5775d89e4490a76d;p=firefly-linux-kernel-4.4.55.git rk3036 lcdc: add support hwc layer --- diff --git a/arch/arm/boot/dts/rk3036.dtsi b/arch/arm/boot/dts/rk3036.dtsi index 640409b4d387..38ef3d7d0d9a 100755 --- a/arch/arm/boot/dts/rk3036.dtsi +++ b/arch/arm/boot/dts/rk3036.dtsi @@ -602,7 +602,7 @@ lcdc: lcdc@10118000 { compatible = "rockchip,rk3036-lcdc"; - reg = <0x10118000 0x200>; + reg = <0x10118000 0x1000>; interrupts = ; status = "disabled"; clocks = <&clk_gates9 6>, <&dclk_lcdc1>, <&clk_gates9 5>; diff --git a/drivers/video/rockchip/lcdc/rk3036_lcdc.c b/drivers/video/rockchip/lcdc/rk3036_lcdc.c index 1c7ff7744365..b0dd1294a4d6 100755 --- a/drivers/video/rockchip/lcdc/rk3036_lcdc.c +++ b/drivers/video/rockchip/lcdc/rk3036_lcdc.c @@ -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); diff --git a/drivers/video/rockchip/lcdc/rk3036_lcdc.h b/drivers/video/rockchip/lcdc/rk3036_lcdc.h index 83d90299583f..b2b75e125cfd 100755 --- a/drivers/video/rockchip/lcdc/rk3036_lcdc.h +++ b/drivers/video/rockchip/lcdc/rk3036_lcdc.h @@ -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;