rk312x lcdc: add support hwc layer

This commit is contained in:
hjc
2014-09-03 18:15:13 +08:00
parent 5d262198bb
commit 9e5568c68a
5 changed files with 120 additions and 5 deletions

View File

@@ -704,7 +704,7 @@
lcdc: lcdc@1010e000 {
compatible = "rockchip,rk312x-lcdc";
rockchip,prop = <PRMRY>;
reg = <0x1010e000 0x0300>;
reg = <0x1010e000 0x1000>;
interrupts = <GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clk_gates6 0>, <&dclk_lcdc0>, <&clk_gates6 1>, <&sclk_lcdc0>, <&pd_vop>, <&clk_cpll>;
clock-names = "aclk_lcdc", "dclk_lcdc", "hclk_lcdc", "sclk_lcdc", "pd_lcdc", "sclk_pll";

View File

@@ -255,6 +255,20 @@ static int rk312x_lcdc_alpha_cfg(struct lcdc_device *lcdc_dev)
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;
}
@@ -307,6 +321,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 (lcdc_dev->soc_type == VOP_RK312X)
@@ -380,6 +395,21 @@ static void lcdc_layer_update_regs(struct lcdc_device *lcdc_dev,
} else if (win->id == 2) {
mask = m_HWC_EN;
val = v_HWC_EN(win->state);
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;
@@ -488,7 +518,34 @@ static void rk312x_lcdc_mmu_en(struct rk_lcdc_driver *dev_drv)
}
spin_unlock(&lcdc_dev->reg_lock);
}
static int rk312x_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<<2;
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 rk312x_lcdc_set_lut(struct rk_lcdc_driver *dev_drv)
{
int i = 0;
@@ -503,7 +560,7 @@ static int rk312x_lcdc_set_lut(struct rk_lcdc_driver *dev_drv)
mdelay(25);
for (i = 0; i < 256; i++) {
v = dev_drv->cur_screen->dsp_lut[i];
c = lcdc_dev->dsp_lut_addr_base + i;
c = lcdc_dev->dsp_lut_addr_base + i<<2;
writel_relaxed(v, c);
}
@@ -1198,6 +1255,8 @@ static int rk312x_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;
@@ -1312,7 +1371,9 @@ static int rk312x_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;
}
@@ -1473,6 +1534,8 @@ static int rk312x_lcdc_early_resume(struct rk_lcdc_driver *dev_drv)
/* set screen lut */
if (dev_drv->cur_screen->dsp_lut)
rk312x_lcdc_set_lut(dev_drv);
/*set hwc lut*/
rk312x_lcdc_set_hwc_lut(dev_drv, dev_drv->hwc_lut, 0);
spin_lock(&lcdc_dev->reg_lock);
@@ -2033,6 +2096,7 @@ static struct rk_lcdc_drv_ops lcdc_drv_ops = {
.get_dsp_bcsh_bcs = rk312x_lcdc_get_bcsh_bcs,
.open_bcsh = rk312x_lcdc_open_bcsh,
.set_screen_scaler = rk312x_lcdc_set_scaler,
.set_hwc_lut = rk312x_lcdc_set_hwc_lut,
};
#if 0
static const struct rk_lcdc_drvdata rk3036_lcdc_drvdata = {
@@ -2125,7 +2189,8 @@ static int rk312x_lcdc_probe(struct platform_device *pdev)
ret = PTR_ERR(lcdc_dev->regsbak);
goto err_remap_reg;
}
lcdc_dev->hwc_lut_addr_base = (lcdc_dev->regs + HWC_LUT_ADDR);
lcdc_dev->dsp_lut_addr_base = (lcdc_dev->regs + DSP_LUT_ADDR);
dev_set_name(lcdc_dev->dev, "lcdc%d", lcdc_dev->id);
dev_drv = &lcdc_dev->driver;
dev_drv->dev = dev;

View File

@@ -667,7 +667,8 @@ struct lcdc_device {
u32 reg_phy_base; /* physical basic address of lcdc register */
u32 len; /* physical map length of lcdc register */
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;
int prop; /* used for primary or extended display device */

View File

@@ -247,6 +247,52 @@ static ssize_t set_fb_win_map(struct device *dev, struct device_attribute *attr,
return count;
}
static ssize_t show_hwc_lut(struct device *dev,
struct device_attribute *attr, char *buf)
{
return 0;
}
static ssize_t set_hwc_lut(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
int hwc_lut[256];
const char *start = buf;
int i = 256, temp;
int space_max = 10;
struct fb_info *fbi = dev_get_drvdata(dev);
struct rk_lcdc_driver *dev_drv =
(struct rk_lcdc_driver *)fbi->par;
/*printk("count:%d\n>>%s\n\n",count,start);*/
for (i = 0; i < 256; i++) {
space_max = 10; /*max space number 10*/
temp = simple_strtoul(start, NULL, 10);
hwc_lut[i] = temp;
do {
start++;
space_max--;
} while ((*start != ' ') && space_max);
if (!space_max)
break;
else
start++;
}
#if 0
for (i = 0; i < 16; i++) {
for (j = 0; j < 16; j++)
printk("0x%08x ", hwc_lut[i * 16 + j]);
printk("\n");
}
#endif
if(dev_drv->ops->set_hwc_lut)
dev_drv->ops->set_hwc_lut(dev_drv, hwc_lut, 1);
return count;
}
static ssize_t show_dsp_lut(struct device *dev,
struct device_attribute *attr, char *buf)
{
@@ -525,6 +571,7 @@ static struct device_attribute rkfb_attrs[] = {
__ATTR(fps, S_IRUGO | S_IWUSR, show_fps, set_fps),
__ATTR(map, S_IRUGO | S_IWUSR, show_fb_win_map, set_fb_win_map),
__ATTR(dsp_lut, S_IRUGO | S_IWUSR, show_dsp_lut, set_dsp_lut),
__ATTR(hwc_lut, S_IRUGO | S_IWUSR, show_hwc_lut, set_hwc_lut),
__ATTR(cabc, S_IRUGO | S_IWUSR, show_dsp_cabc, set_dsp_cabc),
__ATTR(bcsh, S_IRUGO | S_IWUSR, show_dsp_bcsh, set_dsp_bcsh),
__ATTR(scale, S_IRUGO | S_IWUSR, show_scale, set_scale),

View File

@@ -418,6 +418,7 @@ struct rk_lcdc_drv_ops {
int (*fb_win_remap) (struct rk_lcdc_driver *dev_drv,
u16 fb_win_map_order);
int (*set_dsp_lut) (struct rk_lcdc_driver *dev_drv, int *lut);
int (*set_hwc_lut) (struct rk_lcdc_driver *dev_drv, int *hwc_lut, int mode);
int (*read_dsp_lut) (struct rk_lcdc_driver *dev_drv, int *lut);
int (*lcdc_hdmi_process) (struct rk_lcdc_driver *dev_drv, int mode); /*some lcdc need to some process in hdmi mode*/
int (*set_irq_to_cpu)(struct rk_lcdc_driver *dev_drv,int enable);
@@ -589,6 +590,7 @@ struct rk_lcdc_driver {
#endif
struct overscan overscan;
struct rk_lcdc_bcsh bcsh;
int *hwc_lut;
};
/*disp_mode: dual display mode