mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-07 19:30:30 +09:00
rk312x lcdc: add support hwc layer
This commit is contained in:
@@ -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";
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user