static int rk3288_lcdc_set_bcsh(struct rk_lcdc_driver *dev_drv,
bool enable);
+struct fb_info *rk_get_fb(int fb_id);
/*#define WAIT_FOR_SYNC 1*/
static int rk3288_lcdc_get_id(u32 phy_base)
u32 v,r,g,b;
struct lcdc_device *lcdc_dev = container_of(dev_drv,
struct lcdc_device,driver);
- lcdc_msk_reg(lcdc_dev, DSP_CTRL1, m_DSP_LUT_EN, v_DSP_LUT_EN(0));
+ if (dev_drv->cur_screen->dsp_lut)
+ lcdc_msk_reg(lcdc_dev, DSP_CTRL1, m_DSP_LUT_EN,
+ v_DSP_LUT_EN(0));
+ if ((dev_drv->cur_screen->cabc_lut) &&
+ (dev_drv->version == VOP_FULL_RK3288_V1_1))
+ lcdc_msk_reg(lcdc_dev, CABC_CTRL1, m_CABC_LUT_EN,
+ v_CABC_LUT_EN(0));
lcdc_cfg_done(lcdc_dev);
mdelay(25);
- for (i = 0; i < 256; i++) {
- v = dev_drv->cur_screen->dsp_lut[i];
- c = lcdc_dev->dsp_lut_addr_base + (i << 2);
- b = (v & 0xff) << 2;
- g = (v & 0xff00) << 4;
- r = (v & 0xff0000) << 6;
- v = r + g + b;
- for (j = 0; j < 4; j++) {
- writel_relaxed(v, c);
- v += (1 + (1 << 10) + (1 << 20)) ;
- c++;
+ if (dev_drv->cur_screen->dsp_lut) {
+ for (i = 0; i < 256; i++) {
+ v = dev_drv->cur_screen->dsp_lut[i];
+ c = lcdc_dev->dsp_lut_addr_base + (i << 2);
+ b = (v & 0xff) << 2;
+ g = (v & 0xff00) << 4;
+ r = (v & 0xff0000) << 6;
+ v = r + g + b;
+ for (j = 0; j < 4; j++) {
+ writel_relaxed(v, c);
+ v += (1 + (1 << 10) + (1 << 20));
+ c++;
+ }
}
+ lcdc_msk_reg(lcdc_dev, DSP_CTRL1, m_DSP_LUT_EN,
+ v_DSP_LUT_EN(1));
+ }
+ if ((dev_drv->cur_screen->cabc_lut) &&
+ (dev_drv->version == VOP_FULL_RK3288_V1_1)) {
+ for (i = 0; i < 128; i++) {
+ v = dev_drv->cur_screen->cabc_lut[i];
+ lcdc_writel(lcdc_dev, i * 4 + CABC_LUT_ADDR, v);
+ }
+ lcdc_msk_reg(lcdc_dev, CABC_CTRL1, m_CABC_LUT_EN,
+ v_CABC_LUT_EN(1));
}
- lcdc_msk_reg(lcdc_dev, DSP_CTRL1, m_DSP_LUT_EN, v_DSP_LUT_EN(1));
return 0;
struct rk_lcdc_win *win0 = lcdc_dev->driver.win[0];
spin_lock(&lcdc_dev->reg_lock);
+ memcpy(lcdc_dev->regsbak, lcdc_dev->regs, FRC_LOWER11_1);
for (reg = 0; reg < FRC_LOWER11_1; reg += 4) {
val = lcdc_readl(lcdc_dev, reg);
switch (reg) {
+ case VERSION_INFO:
+ lcdc_dev->driver.version = val;
+ break;
case WIN0_ACT_INFO:
win0->area[0].xact =
(val & m_WIN0_ACT_WIDTH) + 1;
case WIN0_CBR_MST:
win0->area[0].cbr_start = val;
break;
+ case DSP_VACT_ST_END:
+ if (support_uboot_display()) {
+ screen->mode.yres =
+ (val & 0x1fff) - ((val >> 16) & 0x1fff);
+ win0->area[0].ypos =
+ st_y - ((val >> 16) & 0x1fff);
+ }
+ break;
+ case DSP_HACT_ST_END:
+ if (support_uboot_display()) {
+ screen->mode.xres =
+ (val & 0x1fff) - ((val >> 16) & 0x1fff);
+ win0->area[0].xpos =
+ st_x - ((val >> 16) & 0x1fff);
+ }
+ break;
default:
break;
}
struct rk_lcdc_win *win = dev_drv->win[win_id];
unsigned int mask, val, off;
off = win_id * 0x40;
- if(win->win_lb_mode == 5)
+ if((win->win_lb_mode == 5) &&
+ (dev_drv->version == VOP_FULL_RK3288_V1_0))
win->win_lb_mode = 4;
if(win->state == 1){
struct rk_lcdc_win *win = dev_drv->win[win_id];
struct rk_screen *screen = dev_drv->cur_screen;
unsigned int mask, val, off;
+ struct fb_info *fb0 = rk_get_fb(0);
+
off = (win_id-2) * 0x50;
if((screen->y_mirror == 1)&&(win->area_num > 1)){
rk3288_lcdc_area_swap(win,win->area_num);
mask = m_WIN2_MST0_EN;
val = v_WIN2_MST0_EN(0);
lcdc_msk_reg(lcdc_dev,WIN2_CTRL0+off,mask,val);
+ lcdc_writel(lcdc_dev, WIN2_MST0 + off,
+ fb0->fix.smem_start);
}
/*area 1*/
if(win->area[1].state == 1){
mask = m_WIN2_MST1_EN;
val = v_WIN2_MST1_EN(0);
lcdc_msk_reg(lcdc_dev,WIN2_CTRL0+off,mask,val);
+ lcdc_writel(lcdc_dev, WIN2_MST1 + off,
+ fb0->fix.smem_start);
}
/*area 2*/
if(win->area[2].state == 1){
mask = m_WIN2_MST2_EN;
val = v_WIN2_MST2_EN(0);
lcdc_msk_reg(lcdc_dev,WIN2_CTRL0+off,mask,val);
+ lcdc_writel(lcdc_dev, WIN2_MST2 + off,
+ fb0->fix.smem_start);
}
/*area 3*/
if(win->area[3].state == 1){
mask = m_WIN2_MST3_EN;
val = v_WIN2_MST3_EN(0);
lcdc_msk_reg(lcdc_dev,WIN2_CTRL0+off,mask,val);
+ lcdc_writel(lcdc_dev, WIN2_MST3 + off,
+ fb0->fix.smem_start);
}
if(win->alpha_en == 1)
pr_info("%s,clk_on = %d\n", __func__, lcdc_dev->clk_on);
return 0;
}
-#if defined(CONFIG_ROCKCHIP_IOMMU)
if (dev_drv->iommu_enabled) {
if (!lcdc_dev->iommu_status && dev_drv->mmu_dev) {
rockchip_iovmm_activate(dev_drv->dev);
}
}
-#endif
return 0;
}
}
+static void rk3288_lcdc_bcsh_path_sel(struct rk_lcdc_driver *dev_drv)
+{
+ struct lcdc_device *lcdc_dev =
+ container_of(dev_drv, struct lcdc_device, driver);
+ u32 bcsh_color_bar;
+
+ if (dev_drv->output_color == COLOR_RGB) {
+ bcsh_color_bar = lcdc_readl(lcdc_dev, BCSH_COLOR_BAR);
+ if (((bcsh_color_bar & m_BCSH_EN) == 1) ||
+ (dev_drv->bcsh.enable == 1))/*bcsh enabled */
+ lcdc_msk_reg(lcdc_dev, BCSH_CTRL,
+ m_BCSH_R2Y_EN | m_BCSH_Y2R_EN,
+ v_BCSH_R2Y_EN(1) | v_BCSH_Y2R_EN(1));
+ else
+ lcdc_msk_reg(lcdc_dev, BCSH_CTRL,
+ m_BCSH_R2Y_EN | m_BCSH_Y2R_EN,
+ v_BCSH_R2Y_EN(0) | v_BCSH_Y2R_EN(0));
+ } else { /* RGB2YUV */
+ lcdc_msk_reg(lcdc_dev, BCSH_CTRL,
+ m_BCSH_R2Y_EN | m_BCSH_Y2R_EN,
+ v_BCSH_R2Y_EN(1) | v_BCSH_Y2R_EN(0));
+ }
+}
+
static int rk3288_get_dspbuf_info(struct rk_lcdc_driver *dev_drv, u16 *xact,
- u16 *yact, int *format, u32 *dsp_addr)
+ u16 *yact, int *format, u32 *dsp_addr,
+ int *ymirror)
{
struct lcdc_device *lcdc_dev = container_of(dev_drv,
struct lcdc_device, driver);
}
static int rk3288_post_dspbuf(struct rk_lcdc_driver *dev_drv, u32 rgb_mst,
- int format, u16 xact, u16 yact, u16 xvir)
+ int format, u16 xact, u16 yact, u16 xvir,
+ int ymirror)
{
struct lcdc_device *lcdc_dev = container_of(dev_drv,
struct lcdc_device, driver);
u32 val, mask;
+ struct rk_lcdc_win *win = dev_drv->win[0];
int swap = (format == RGB888) ? 1 : 0;
mask = m_WIN0_DATA_FMT | m_WIN0_RB_SWAP;
lcdc_writel(lcdc_dev, WIN0_YRGB_MST, rgb_mst);
lcdc_cfg_done(lcdc_dev);
+ win->state = 1;
+ win->last_state = 1;
return 0;
}
static int rk3288_load_screen(struct rk_lcdc_driver *dev_drv, bool initscreen)
{
u16 face = 0;
+ u16 dclk_ddr = 0;
u32 v=0;
struct lcdc_device *lcdc_dev =
container_of(dev_drv, struct lcdc_device, driver);
u16 y_res = screen->mode.yres;
u32 mask, val;
u16 h_total,v_total;
+ int ret = 0;
+ int hdmi_dclk_out_en = 0;
+
if (unlikely(!lcdc_dev->clk_on)) {
pr_info("%s,clk_on = %d\n", __func__, lcdc_dev->clk_on);
return 0;
v_PRE_DITHER_DOWN_EN(1);
lcdc_msk_reg(lcdc_dev, DSP_CTRL1, mask, val);
break;
+ case OUT_YUV_420:
+ hdmi_dclk_out_en = 1;
+ face = OUT_YUV_420;
+ dclk_ddr = 1;
+ mask = m_DITHER_DOWN_EN | m_DITHER_UP_EN |
+ m_PRE_DITHER_DOWN_EN;
+ val = v_DITHER_DOWN_EN(0) | v_DITHER_UP_EN(1) |
+ v_PRE_DITHER_DOWN_EN(1);
+ lcdc_msk_reg(lcdc_dev, DSP_CTRL1, mask, val);
+ break;
+ case OUT_YUV_420_10BIT:
+ hdmi_dclk_out_en = 1;
+ face = OUT_YUV_420;
+ dclk_ddr = 1;
+ mask = m_DITHER_DOWN_EN | m_DITHER_UP_EN |
+ m_PRE_DITHER_DOWN_EN;
+ val = v_DITHER_DOWN_EN(0) | v_DITHER_UP_EN(1) |
+ v_PRE_DITHER_DOWN_EN(0);
+ lcdc_msk_reg(lcdc_dev, DSP_CTRL1, mask, val);
+ break;
case OUT_P101010:
face = OUT_P101010;
mask = m_DITHER_DOWN_EN | m_DITHER_UP_EN |
v |= (lcdc_dev->id << 3);
break;
case SCREEN_HDMI:
- face = OUT_P101010;/*RGB 101010 output*/
+ if ((screen->face == OUT_P888) ||
+ (screen->face == OUT_P101010))
+ face = OUT_P101010;/*RGB 101010 output*/
mask = m_HDMI_OUT_EN;
val = v_HDMI_OUT_EN(1);
break;
mask = m_EDP_OUT_EN;
val = v_EDP_OUT_EN(1);
break;
+ default:
+ mask = 0;
+ val = 0;
+ pr_info("unknow screen type: %d\n", screen->type);
+ break;
+ }
+ if (dev_drv->version == VOP_FULL_RK3288_V1_1) {
+ mask |= m_HDMI_DCLK_OUT_EN;
+ val |= v_HDMI_DCLK_OUT_EN(hdmi_dclk_out_en);
}
lcdc_msk_reg(lcdc_dev, SYS_CTRL, mask, val);
#ifndef CONFIG_RK_FPGA
m_DSP_DEN_POL | m_DSP_DCLK_POL | m_DSP_BG_SWAP |
m_DSP_RB_SWAP | m_DSP_RG_SWAP | m_DSP_DELTA_SWAP |
m_DSP_DUMMY_SWAP | m_DSP_OUT_ZERO | m_DSP_BLANK_EN |
- m_DSP_BLACK_EN | m_DSP_X_MIR_EN | m_DSP_Y_MIR_EN;
+ m_DSP_BLACK_EN | m_DSP_X_MIR_EN | m_DSP_Y_MIR_EN |
+ m_DSP_DCLK_DDR;
val = v_DSP_OUT_MODE(face) | v_DSP_HSYNC_POL(screen->pin_hsync) |
v_DSP_VSYNC_POL(screen->pin_vsync) |
v_DSP_DEN_POL(screen->pin_den) | v_DSP_DCLK_POL(screen->pin_dclk) |
v_DSP_DELTA_SWAP(screen->swap_delta) |
v_DSP_DUMMY_SWAP(screen->swap_dumy) | v_DSP_OUT_ZERO(0) |
v_DSP_BLANK_EN(0) | v_DSP_BLACK_EN(0) |
- v_DSP_X_MIR_EN(screen->x_mirror) | v_DSP_Y_MIR_EN(screen->y_mirror);
+ v_DSP_X_MIR_EN(screen->x_mirror) |
+ v_DSP_Y_MIR_EN(screen->y_mirror) |
+ v_DSP_DCLK_DDR(dclk_ddr);
lcdc_msk_reg(lcdc_dev, DSP_CTRL0, mask, val);
mask = m_DSP_BG_BLUE | m_DSP_BG_GREEN | m_DSP_BG_RED;
mask = m_DSP_LINE_FLAG_NUM;
val = v_DSP_LINE_FLAG_NUM(vsync_len + upper_margin + y_res);
lcdc_msk_reg(lcdc_dev, INTR_CTRL0, mask, val);
+ dev_drv->output_color = screen->color_mode;
+ if (dev_drv->version == VOP_FULL_RK3288_V1_1) {
+ rk3288_lcdc_bcsh_path_sel(dev_drv);
+ } else {
+ if (dev_drv->output_color != COLOR_RGB) {
+ pr_err("vop ver:%x,unsupport output color:%d\n",
+ dev_drv->version, dev_drv->output_color);
+ ret = -1;
+ }
+ }
}
spin_unlock(&lcdc_dev->reg_lock);
rk3288_lcdc_set_dclk(dev_drv, 1);
if (screen->init)
screen->init();
- return 0;
+ return ret;
}
/*enable layer,open:1,enable;0 disable*/
rk3288_lcdc_pre_init(dev_drv);
rk3288_lcdc_clk_enable(lcdc_dev);
rk3288_lcdc_enable_irq(dev_drv);
-#if defined(CONFIG_ROCKCHIP_IOMMU)
if (dev_drv->iommu_enabled) {
if (!dev_drv->mmu_dev) {
dev_drv->mmu_dev =
}
}
}
-#endif
rk3288_lcdc_reg_restore(lcdc_dev);
/*if (dev_drv->iommu_enabled)
rk3368_lcdc_mmu_en(dev_drv); */
if (dev_drv->bcsh.enable)
rk3288_lcdc_set_bcsh(dev_drv, 1);
spin_lock(&lcdc_dev->reg_lock);
- if (dev_drv->cur_screen->dsp_lut)
- rk3288_lcdc_set_lut(dev_drv);
+ rk3288_lcdc_set_lut(dev_drv);
spin_unlock(&lcdc_dev->reg_lock);
}
if ((!open) && (!lcdc_dev->atv_layer_cnt)) {
rk3288_lcdc_disable_irq(lcdc_dev);
rk3288_lcdc_reg_update(dev_drv);
-#if defined(CONFIG_ROCKCHIP_IOMMU)
if (dev_drv->iommu_enabled) {
- if (dev_drv->mmu_dev)
+ if (dev_drv->mmu_dev) {
rockchip_iovmm_deactivate(dev_drv->dev);
+ lcdc_dev->iommu_status = 0;
+ }
}
-#endif
rk3288_lcdc_clk_disable(lcdc_dev);
rockchip_clear_system_status(sys_status);
}
for(i=0;i<win->area_num;i++)
win->area[i].y_addr =
win->area[i].smem_start + win->area[i].y_offset;
- lcdc_writel(lcdc_dev,WIN2_MST0,win->area[0].y_addr);
- lcdc_writel(lcdc_dev,WIN2_MST1,win->area[1].y_addr);
- lcdc_writel(lcdc_dev,WIN2_MST2,win->area[2].y_addr);
- lcdc_writel(lcdc_dev,WIN2_MST3,win->area[3].y_addr);
+ if (win->area[0].state)
+ lcdc_writel(lcdc_dev, WIN2_MST0,
+ win->area[0].y_addr);
+ if (win->area[1].state)
+ lcdc_writel(lcdc_dev, WIN2_MST1,
+ win->area[1].y_addr);
+ if (win->area[2].state)
+ lcdc_writel(lcdc_dev, WIN2_MST2,
+ win->area[2].y_addr);
+ if (win->area[3].state)
+ lcdc_writel(lcdc_dev, WIN2_MST3,
+ win->area[3].y_addr);
}
spin_unlock(&lcdc_dev->reg_lock);
return 0;
for(i=0;i<win->area_num;i++)
win->area[i].y_addr =
win->area[i].smem_start + win->area[i].y_offset;
- lcdc_writel(lcdc_dev,WIN3_MST0,win->area[0].y_addr);
- lcdc_writel(lcdc_dev,WIN3_MST1,win->area[1].y_addr);
- lcdc_writel(lcdc_dev,WIN3_MST2,win->area[2].y_addr);
- lcdc_writel(lcdc_dev,WIN3_MST3,win->area[3].y_addr);
+ if (win->area[0].state)
+ lcdc_writel(lcdc_dev, WIN3_MST0,
+ win->area[0].y_addr);
+ if (win->area[1].state)
+ lcdc_writel(lcdc_dev, WIN3_MST1,
+ win->area[1].y_addr);
+ if (win->area[2].state)
+ lcdc_writel(lcdc_dev, WIN3_MST2,
+ win->area[2].y_addr);
+ if (win->area[3].state)
+ lcdc_writel(lcdc_dev, WIN3_MST3,
+ win->area[3].y_addr);
}
spin_unlock(&lcdc_dev->reg_lock);
return 0;
screen->mode.upper_margin +
screen->mode.vsync_len;
}
- }
- if ((win->area[i].xact != win->area[i].xsize) ||
- (win->area[i].yact != win->area[i].ysize)) {
- pr_err("win[%d]->area[%d],not support scale\n",
- win->id, i);
- pr_err("xact=%d,yact=%d,xsize=%d,ysize=%d\n",
- win->area[i].xact,win->area[i].yact,
- win->area[i].xsize,win->area[i].ysize);
- win->area[i].xsize = win->area[i].xact;
- win->area[i].ysize = win->area[i].yact;
+ if ((win->area[i].xact != win->area[i].xsize) ||
+ (win->area[i].yact != win->area[i].ysize)) {
+ pr_err("win[%d]->area[%d],not support scale\n",
+ win->id, i);
+ pr_err("xact=%d,yact=%d,xsize=%d,ysize=%d\n",
+ win->area[i].xact, win->area[i].yact,
+ win->area[i].xsize, win->area[i].ysize);
+ win->area[i].xsize = win->area[i].xact;
+ win->area[i].ysize = win->area[i].yact;
+ }
}
}
rk3288_win_2_3_reg_update(&lcdc_dev->driver,3);
{
struct lcdc_device *lcdc_dev =
container_of(dev_drv, struct lcdc_device, driver);
- int i, j;
- int __iomem *c;
- int v, r, g, b;
if (!dev_drv->suspend_flag)
return 0;
rk3288_lcdc_reg_restore(lcdc_dev);
spin_lock(&lcdc_dev->reg_lock);
- if (dev_drv->cur_screen->dsp_lut) {
- lcdc_msk_reg(lcdc_dev, DSP_CTRL1, m_DSP_LUT_EN,
- v_DSP_LUT_EN(0));
- lcdc_cfg_done(lcdc_dev);
- mdelay(25);
- for (i = 0; i < 256; i++) {
- v = dev_drv->cur_screen->dsp_lut[i];
- c = lcdc_dev->dsp_lut_addr_base + (i << 2);
- b = (v & 0xff) << 2;
- g = (v & 0xff00) << 4;
- r = (v & 0xff0000) << 6;
- v = r + g + b;
- for (j = 0; j < 4; j++) {
- writel_relaxed(v, c);
- v += (1 + (1 << 10) + (1 << 20)) ;
- c++;
- }
- }
- lcdc_msk_reg(lcdc_dev, DSP_CTRL1, m_DSP_LUT_EN,
- v_DSP_LUT_EN(1));
- }
+ rk3288_lcdc_set_lut(dev_drv);
lcdc_msk_reg(lcdc_dev, DSP_CTRL0, m_DSP_OUT_ZERO,
v_DSP_OUT_ZERO(0));
int i;
unsigned int mask, val;
struct rk_lcdc_win *win = NULL;
+ struct fb_info *fb0 = rk_get_fb(0);
+
spin_lock(&lcdc_dev->reg_lock);
lcdc_msk_reg(lcdc_dev, SYS_CTRL, m_STANDBY_EN,
v_STANDBY_EN(lcdc_dev->standby));
if ((win->state == 0)&&(win->last_state == 1)) {
switch (win->id) {
case 0:
- lcdc_writel(lcdc_dev,WIN0_CTRL1,0x0);
+ if (dev_drv->version == VOP_FULL_RK3288_V1_0)
+ lcdc_writel(lcdc_dev, WIN0_CTRL1, 0x0);
mask = m_WIN0_EN;
val = v_WIN0_EN(0);
lcdc_msk_reg(lcdc_dev, WIN0_CTRL0, mask,val);
break;
case 1:
- lcdc_writel(lcdc_dev,WIN1_CTRL1,0x0);
+ if (dev_drv->version == VOP_FULL_RK3288_V1_0)
+ lcdc_writel(lcdc_dev, WIN1_CTRL1, 0x0);
mask = m_WIN1_EN;
val = v_WIN1_EN(0);
lcdc_msk_reg(lcdc_dev, WIN1_CTRL0, mask,val);
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_writel(lcdc_dev,WIN2_DSP_INFO0,0);
+ lcdc_writel(lcdc_dev,WIN2_DSP_INFO1,0);
+ lcdc_writel(lcdc_dev,WIN2_DSP_INFO2,0);
+ lcdc_writel(lcdc_dev,WIN2_DSP_INFO3,0);
+ lcdc_writel(lcdc_dev,WIN2_MST0, fb0->fix.smem_start);
+ lcdc_writel(lcdc_dev,WIN2_MST1, fb0->fix.smem_start);
+ lcdc_writel(lcdc_dev,WIN2_MST2, fb0->fix.smem_start);
+ lcdc_writel(lcdc_dev,WIN2_MST3, fb0->fix.smem_start);
break;
case 3:
mask = m_WIN3_EN | m_WIN3_MST0_EN | m_WIN3_MST1_EN |
val = v_WIN3_EN(0) | v_WIN3_MST0_EN(0) | v_WIN3_MST1_EN(0) |
v_WIN3_MST2_EN(0) | v_WIN3_MST3_EN(0);
lcdc_msk_reg(lcdc_dev, WIN3_CTRL0, mask,val);
+ lcdc_writel(lcdc_dev,WIN3_DSP_INFO0,0);
+ lcdc_writel(lcdc_dev,WIN3_DSP_INFO1,0);
+ lcdc_writel(lcdc_dev,WIN3_DSP_INFO2,0);
+ lcdc_writel(lcdc_dev,WIN3_DSP_INFO3,0);
+ lcdc_writel(lcdc_dev,WIN3_MST0, fb0->fix.smem_start);
+ lcdc_writel(lcdc_dev,WIN3_MST1, fb0->fix.smem_start);
+ lcdc_writel(lcdc_dev,WIN3_MST2, fb0->fix.smem_start);
+ lcdc_writel(lcdc_dev,WIN3_MST3, fb0->fix.smem_start);
break;
default:
break;
return 0;
}
-static struct lcdc_cabc_mode cabc_mode[4] = {
-/* pixel_num, stage_up, stage_down */
- {5, 128, 0}, /*mode 1*/
- {10, 128, 0}, /*mode 2*/
- {15, 128, 0}, /*mode 3*/
- {20, 128, 0}, /*mode 4*/
-};
-
-static int __maybe_unused
-rk3288_lcdc_set_dsp_cabc(struct rk_lcdc_driver *dev_drv, int mode)
+static int rk3288_lcdc_set_dsp_cabc(struct rk_lcdc_driver *dev_drv,
+ int mode, int calc, int up,
+ int down, int global)
{
struct lcdc_device *lcdc_dev =
container_of(dev_drv, struct lcdc_device, driver);
struct rk_screen *screen = dev_drv->cur_screen;
- u32 total_pixel, calc_pixel, stage_up, stage_down, pixel_num;
- u32 mask = 0, val = 0, cabc_en = 0;
- u32 max_mode_num = sizeof(cabc_mode) / sizeof(struct lcdc_cabc_mode);
-
- dev_drv->cabc_mode = mode;
+ u32 total_pixel, calc_pixel, stage_up, stage_down;
+ u32 pixel_num, global_dn;
+ u32 mask = 0, val = 0;
- /* iomux connect to vop or pwm */
- if (mode == 0) {
- DBG(3, "close cabc and select rk pwm\n");
- val = 0x30001;
- writel_relaxed(val, RK_GRF_VIRT + RK3288_GRF_GPIO7A_IOMUX);
- cabc_en = 0;
- } else if (mode > 0 && mode <= max_mode_num) {
- DBG(3, "open cabc and select vop pwm\n");
- val = (dev_drv->id == 0) ? 0x30002 : 0x30003;
- writel_relaxed(val, RK_GRF_VIRT + RK3288_GRF_GPIO7A_IOMUX);
- cabc_en = 1;
- } else if (mode > 0x10 && mode <= (max_mode_num + 0x10)) {
- DBG(3, "open cabc and select rk pwm\n");
- val = 0x30001;
- writel_relaxed(val, RK_GRF_VIRT + RK3288_GRF_GPIO7A_IOMUX);
- cabc_en = 1;
- mode -= 0x10;
- } else if (mode == 0xff) {
- DBG(3, "close cabc and select vop pwm\n");
- val = (dev_drv->id == 0) ? 0x30002 : 0x30003;
- writel_relaxed(val, RK_GRF_VIRT + RK3288_GRF_GPIO7A_IOMUX);
- cabc_en = 0;
- } else {
- dev_err(lcdc_dev->dev, "invalid cabc mode value:%d", mode);
+ if (dev_drv->version != VOP_FULL_RK3288_V1_1) {
+ pr_err("vop version:%x, not supoort cabc\n", dev_drv->version);
return 0;
}
-
- if (cabc_en == 0) {
+ if (!screen->cabc_lut) {
+ pr_err("screen cabc lut not config, so not open cabc\n");
+ return 0;
+ }
+ dev_drv->cabc_mode = mode;
+ if (!dev_drv->cabc_mode) {
spin_lock(&lcdc_dev->reg_lock);
- if(lcdc_dev->clk_on) {
- lcdc_msk_reg(lcdc_dev, CABC_CTRL0, m_CABC_EN, v_CABC_EN(0));
+ if (lcdc_dev->clk_on) {
+ lcdc_msk_reg(lcdc_dev, CABC_CTRL0,
+ m_CABC_HANDLE_EN | m_CABC_EN,
+ v_CABC_EN(0) | v_CABC_HANDLE_EN(0));
lcdc_cfg_done(lcdc_dev);
}
+ pr_info("mode = 0, close cabc\n");
spin_unlock(&lcdc_dev->reg_lock);
return 0;
}
total_pixel = screen->mode.xres * screen->mode.yres;
- pixel_num = 1000 - (cabc_mode[mode - 1].pixel_num);
+ pixel_num = 1000 - calc;
calc_pixel = (total_pixel * pixel_num) / 1000;
- stage_up = cabc_mode[mode - 1].stage_up;
- stage_down = cabc_mode[mode - 1].stage_down;
-
+ stage_up = up;
+ stage_down = down;
+ global_dn = global;
+ pr_info("enable cabc:mode=%d, calc=%d, up=%d, down=%d, global=%d\n",
+ mode, calc, stage_up, stage_down, global_dn);
+
spin_lock(&lcdc_dev->reg_lock);
- if(lcdc_dev->clk_on) {
- mask = m_CABC_TOTAL_NUM | m_CABC_STAGE_DOWN;
- val = v_CABC_TOTAL_NUM(total_pixel) | v_CABC_STAGE_DOWN(stage_down);
+ if (lcdc_dev->clk_on) {
+ mask = m_CABC_EN | m_CABC_HANDLE_EN | m_PWM_CONFIG_MODE |
+ m_CABC_CALC_PIXEL_NUM;
+ val = v_CABC_EN(1) | v_CABC_HANDLE_EN(1) |
+ v_PWM_CONFIG_MODE(STAGE_BY_STAGE) |
+ v_CABC_CALC_PIXEL_NUM(calc_pixel);
+ lcdc_msk_reg(lcdc_dev, CABC_CTRL0, mask, val);
+
+ mask = m_CABC_LUT_EN | m_CABC_TOTAL_PIXEL_NUM;
+ val = v_CABC_LUT_EN(1) | v_CABC_TOTAL_PIXEL_NUM(total_pixel);
lcdc_msk_reg(lcdc_dev, CABC_CTRL1, mask, val);
- mask = m_CABC_EN | m_CABC_CALC_PIXEL_NUM |
- m_CABC_STAGE_UP;
- val = v_CABC_EN(1) | v_CABC_CALC_PIXEL_NUM(calc_pixel) |
- v_CABC_STAGE_UP(stage_up);
- lcdc_msk_reg(lcdc_dev, CABC_CTRL0, mask, val);
+ mask = m_CABC_STAGE_DOWN | m_CABC_STAGE_UP |
+ m_CABC_STAGE_MODE | m_MAX_SCALE_CFG_VALUE |
+ m_MAX_SCALE_CFG_ENABLE;
+ val = v_CABC_STAGE_DOWN(stage_down) |
+ v_CABC_STAGE_UP(stage_up) |
+ v_CABC_STAGE_MODE(0) | v_MAX_SCALE_CFG_VALUE(1) |
+ v_MAX_SCALE_CFG_ENABLE(0);
+ lcdc_msk_reg(lcdc_dev, CABC_CTRL2, mask, val);
+
+ mask = m_CABC_GLOBAL_DN | m_CABC_GLOBAL_DN_LIMIT_EN;
+ val = v_CABC_GLOBAL_DN(global_dn) |
+ v_CABC_GLOBAL_DN_LIMIT_EN(1);
+ lcdc_msk_reg(lcdc_dev, CABC_CTRL3, mask, val);
lcdc_cfg_done(lcdc_dev);
}
spin_unlock(&lcdc_dev->reg_lock);
return 0;
}
+
/*
a:[-30~0]:
sin_hue = sin(a)*256 +0x100;
lcdc_writel(lcdc_dev,BCSH_COLOR_BAR,0x1);
lcdc_writel(lcdc_dev,BCSH_BCS,0xd0010000);
lcdc_writel(lcdc_dev,BCSH_H,0x01000000);
+ dev_drv->bcsh.enable = 1;
} else {
mask = m_BCSH_EN;
val = v_BCSH_EN(0);
lcdc_msk_reg(lcdc_dev, BCSH_COLOR_BAR, mask, val);
+ dev_drv->bcsh.enable = 0;
}
+ if (dev_drv->version == VOP_FULL_RK3288_V1_1)
+ rk3288_lcdc_bcsh_path_sel(dev_drv);
lcdc_cfg_done(lcdc_dev);
}
spin_unlock(&lcdc_dev->reg_lock);
.dpi_win_sel = rk3288_lcdc_dpi_win_sel,
.dpi_status = rk3288_lcdc_dpi_status,
.get_dsp_addr = rk3288_lcdc_get_dsp_addr,
- /*.set_dsp_cabc = rk3288_lcdc_set_dsp_cabc,*/
+ .set_dsp_cabc = rk3288_lcdc_set_dsp_cabc,
.set_dsp_bcsh_hue = rk3288_lcdc_set_bcsh_hue,
.set_dsp_bcsh_bcs = rk3288_lcdc_set_bcsh_bcs,
.get_dsp_bcsh_hue = rk3288_lcdc_get_bcsh_hue,
complete(&(lcdc_dev->driver.frame_done));
spin_unlock(&(lcdc_dev->driver.cpl_lock));
}
-#ifdef CONFIG_DRM_ROCKCHIP
- lcdc_dev->driver.irq_call_back(&lcdc_dev->driver);
-#endif
lcdc_dev->driver.vsync_info.timestamp = timestamp;
wake_up_interruptible_all(&lcdc_dev->driver.vsync_info.wait);
dev_drv->bcsh.cos_hue = (val >> 8) & 0xff;
}
-#if defined(CONFIG_ROCKCHIP_IOMMU)
if (of_property_read_u32(np, "rockchip,iommu-enabled", &val))
dev_drv->iommu_enabled = 0;
else
dev_drv->iommu_enabled = val;
-#else
- dev_drv->iommu_enabled = 0;
-#endif
+
+ if (of_property_read_u32(np, "rockchip,dsp_mode", &val))
+ dev_drv->dsp_mode = DEFAULT_MODE;
+ else
+ dev_drv->dsp_mode = val;
+
return 0;
}