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;
val = v_WIN##id##_EN(en); \
lcdc_msk_reg(lcdc_dev, WIN##id##_CTRL0, msk, val); \
lcdc_cfg_done(lcdc_dev); \
- val = lcdc_read_bit(lcdc_dev, WIN##id##_CTRL0, msk); \
+ /*val = lcdc_read_bit(lcdc_dev, WIN##id##_CTRL0, msk); \
while (val != (!!en)) { \
val = lcdc_read_bit(lcdc_dev, WIN##id##_CTRL0, msk); \
- } \
+ }*/ \
spin_unlock(&lcdc_dev->reg_lock); \
return 0; \
}
{
int reg = 0;
u32 val = 0;
+ struct rk_screen *screen = lcdc_dev->driver.cur_screen;
+ u32 h_pw_bp = screen->mode.hsync_len + screen->mode.left_margin;
+ u32 v_pw_bp = screen->mode.vsync_len + screen->mode.upper_margin;
+ u32 st_x, st_y;
struct rk_lcdc_win *win0 = lcdc_dev->driver.win[0];
spin_lock(&lcdc_dev->reg_lock);
- for (reg = 0; reg < 0x1a0; reg+= 4) {
+ 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;
- win0->area[0].yact = ((val & m_WIN0_ACT_HEIGHT)>>16)+1;
+ win0->area[0].xact =
+ (val & m_WIN0_ACT_WIDTH) + 1;
+ win0->area[0].yact =
+ ((val & m_WIN0_ACT_HEIGHT) >> 16) + 1;
+ break;
+ case WIN0_DSP_INFO:
+ win0->area[0].xsize =
+ (val & m_WIN0_DSP_WIDTH) + 1;
+ win0->area[0].ysize =
+ ((val & m_WIN0_DSP_HEIGHT) >> 16) + 1;
+ break;
+ case WIN0_DSP_ST:
+ st_x = val & m_WIN0_DSP_XST;
+ st_y = (val & m_WIN0_DSP_YST) >> 16;
+ win0->area[0].xpos = st_x - h_pw_bp;
+ win0->area[0].ypos = st_y - v_pw_bp;
+ break;
+ case WIN0_CTRL0:
+ win0->state = val & m_WIN0_EN;
+ win0->area[0].fmt_cfg =
+ (val & m_WIN0_DATA_FMT) >> 1;
+ win0->fmt_10 = (val & m_WIN0_FMT_10) >> 4;
+ win0->area[0].format = win0->area[0].fmt_cfg;
+ break;
+ case WIN0_VIR:
+ win0->area[0].y_vir_stride =
+ val & m_WIN0_VIR_STRIDE;
+ win0->area[0].uv_vir_stride =
+ (val & m_WIN0_VIR_STRIDE_UV) >> 16;
+ if (win0->area[0].format == ARGB888)
+ win0->area[0].xvir =
+ win0->area[0].y_vir_stride;
+ else if (win0->area[0].format == RGB888)
+ win0->area[0].xvir =
+ win0->area[0].y_vir_stride * 4 / 3;
+ else if (win0->area[0].format == RGB565)
+ win0->area[0].xvir =
+ 2 * win0->area[0].y_vir_stride;
+ else /* YUV */
+ win0->area[0].xvir =
+ 4 * win0->area[0].y_vir_stride;
+ break;
+ case WIN0_YRGB_MST:
+ win0->area[0].smem_start = val;
+ break;
+ 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;
}
dev_err(lcdc_dev->dev, "failed to get lcdc%d clk source\n",
lcdc_dev->id);
}
-
- rk_disp_pwr_enable(dev_drv);
+ if (!support_uboot_display())
+ rk_disp_pwr_enable(dev_drv);
rk3288_lcdc_clk_enable(lcdc_dev);
/*backup reg config at uboot*/
lcdc_read_reg_defalut_cfg(lcdc_dev);
+ v = 0;
#ifndef CONFIG_RK_FPGA
if (lcdc_dev->pwr18 == true) {
v = 0x00010001; /*bit14: 1,1.8v;0,3.3v*/
val = v_AUTO_GATING_EN(0);
lcdc_msk_reg(lcdc_dev, SYS_CTRL, mask,val);
lcdc_cfg_done(lcdc_dev);
- if (dev_drv->iommu_enabled) /*disable win0 to workaround iommu pagefault*/
- win0_enable(lcdc_dev, 0);
+ /*disable win0 to workaround iommu pagefault */
+ /*if (dev_drv->iommu_enabled) */
+ /* win0_enable(lcdc_dev, 0); */
lcdc_dev->pre_init = true;
u16 post_dsp_vact_st_f1,post_dsp_vact_end_f1;
u16 post_h_fac,post_v_fac;
+ screen->post_dsp_stx = x_res * (100 - dev_drv->overscan.left) / 200;
+ screen->post_dsp_sty = y_res * (100 - dev_drv->overscan.top) / 200;
+ screen->post_xsize = x_res *
+ (dev_drv->overscan.left + dev_drv->overscan.right) / 200;
+ screen->post_ysize = y_res *
+ (dev_drv->overscan.top + dev_drv->overscan.bottom) / 200;
h_total = screen->mode.hsync_len+screen->mode.left_margin +
x_res + screen->mode.right_margin;
v_total = screen->mode.vsync_len+screen->mode.upper_margin +
u32 mask, val;
int ppixel_alpha,global_alpha;
u32 src_alpha_ctl,dst_alpha_ctl;
- ppixel_alpha = ((win->format == ARGB888)||(win->format == ABGR888)) ? 1 : 0;
+ ppixel_alpha = ((win->area[0].format == ARGB888) ||
+ (win->area[0].format == ABGR888)) ? 1 : 0;
global_alpha = (win->g_alpha_val == 0) ? 0 : 1;
alpha_config.src_global_alpha_val = win->g_alpha_val;
win->alpha_mode = AB_SRC_OVER;
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){
mask = m_WIN0_EN | m_WIN0_DATA_FMT | m_WIN0_FMT_10 |
- m_WIN0_LB_MODE | m_WIN0_RB_SWAP;
- val = v_WIN0_EN(win->state) | v_WIN0_DATA_FMT(win->fmt_cfg) |
+ m_WIN0_LB_MODE | m_WIN0_RB_SWAP | m_WIN0_UV_SWAP;
+ val = v_WIN0_EN(win->state) |
+ v_WIN0_DATA_FMT(win->area[0].fmt_cfg) |
v_WIN0_FMT_10(win->fmt_10) |
v_WIN0_LB_MODE(win->win_lb_mode) |
- v_WIN0_RB_SWAP(win->swap_rb);
+ v_WIN0_RB_SWAP(win->area[0].swap_rb) |
+ v_WIN0_UV_SWAP(win->area[0].swap_uv);
lcdc_msk_reg(lcdc_dev, WIN0_CTRL0+off, mask,val);
mask = m_WIN0_BIC_COE_SEL |
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);
if(win->state == 1){
mask = m_WIN2_EN | m_WIN2_DATA_FMT | m_WIN2_RB_SWAP;
- val = v_WIN2_EN(1) | v_WIN2_DATA_FMT(win->fmt_cfg) |
- v_WIN2_RB_SWAP(win->swap_rb);
+ val = v_WIN2_EN(1) |
+ v_WIN2_DATA_FMT(win->area[0].fmt_cfg) |
+ v_WIN2_RB_SWAP(win->area[0].swap_rb);
lcdc_msk_reg(lcdc_dev,WIN2_CTRL0+off,mask,val);
/*area 0*/
if(win->area[0].state == 1){
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)
static int rk3288_lcdc_reg_restore(struct lcdc_device *lcdc_dev)
{
- if (lcdc_dev->driver.iommu_enabled)
- memcpy((u8 *) lcdc_dev->regs, (u8 *) lcdc_dev->regsbak, 0x330);
- else
- memcpy((u8 *) lcdc_dev->regs, (u8 *) lcdc_dev->regsbak, 0x1fc);
+ memcpy((u8 *) lcdc_dev->regs, (u8 *) lcdc_dev->regsbak, 0x1fc);
return 0;
}
static int rk3288_lcdc_mmu_en(struct rk_lcdc_driver *dev_drv)
u32 mask,val;
struct lcdc_device *lcdc_dev =
container_of(dev_drv, struct lcdc_device, driver);
- spin_lock(&lcdc_dev->reg_lock);
- if (likely(lcdc_dev->clk_on)) {
- mask = m_MMU_EN;
- val = v_MMU_EN(1);
- lcdc_msk_reg(lcdc_dev, SYS_CTRL, mask, val);
- mask = m_AXI_MAX_OUTSTANDING_EN | m_AXI_OUTSTANDING_MAX_NUM;
- val = v_AXI_OUTSTANDING_MAX_NUM(31) | v_AXI_MAX_OUTSTANDING_EN(1);
- lcdc_msk_reg(lcdc_dev, SYS_CTRL1, mask, val);
+
+ if (unlikely(!lcdc_dev->clk_on)) {
+ pr_info("%s,clk_on = %d\n", __func__, lcdc_dev->clk_on);
+ return 0;
+ }
+ if (dev_drv->iommu_enabled) {
+ if (!lcdc_dev->iommu_status && dev_drv->mmu_dev) {
+
+ if (likely(lcdc_dev->clk_on)) {
+ spin_lock(&lcdc_dev->reg_lock);
+ mask = m_MMU_EN;
+ val = v_MMU_EN(1);
+ lcdc_msk_reg(lcdc_dev, SYS_CTRL, mask, val);
+ mask = m_AXI_MAX_OUTSTANDING_EN | m_AXI_OUTSTANDING_MAX_NUM;
+ val = v_AXI_OUTSTANDING_MAX_NUM(31) | v_AXI_MAX_OUTSTANDING_EN(1);
+ lcdc_msk_reg(lcdc_dev, SYS_CTRL1, mask, val);
+ spin_unlock(&lcdc_dev->reg_lock);
+ }
+ lcdc_dev->iommu_status = 1;
+ rockchip_iovmm_activate(dev_drv->dev);
+ }
}
- spin_unlock(&lcdc_dev->reg_lock);
return 0;
}
-static int rk3288_lcdc_set_dclk(struct rk_lcdc_driver *dev_drv)
+static int rk3288_lcdc_set_dclk(struct rk_lcdc_driver *dev_drv, int reset_rate)
{
#ifdef CONFIG_RK_FPGA
return 0;
#endif
- int ret,fps;
+ int ret = 0,fps;
struct lcdc_device *lcdc_dev =
container_of(dev_drv, struct lcdc_device, driver);
struct rk_screen *screen = dev_drv->cur_screen;
- ret = clk_set_rate(lcdc_dev->dclk, screen->mode.pixclock);
+ if (reset_rate)
+ ret = clk_set_rate(lcdc_dev->dclk, screen->mode.pixclock);/*set pll */
if (ret)
dev_err(dev_drv->dev, "set lcdc%d dclk failed\n", lcdc_dev->id);
lcdc_dev->pixclock =
}
+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,
+ int *ymirror)
+{
+ struct lcdc_device *lcdc_dev = container_of(dev_drv,
+ struct lcdc_device, driver);
+ u32 val;
+
+ spin_lock(&lcdc_dev->reg_lock);
+
+ val = lcdc_readl(lcdc_dev, WIN0_ACT_INFO);
+ *xact = (val & m_WIN0_ACT_WIDTH) + 1;
+ *yact = ((val & m_WIN0_ACT_HEIGHT)>>16) + 1;
+
+ val = lcdc_readl(lcdc_dev, WIN0_CTRL0);
+ *format = (val & m_WIN0_DATA_FMT) >> 1;
+ *dsp_addr = lcdc_readl(lcdc_dev, WIN0_YRGB_MST);
+
+ spin_unlock(&lcdc_dev->reg_lock);
+
+ return 0;
+}
+
+static int rk3288_post_dspbuf(struct rk_lcdc_driver *dev_drv, u32 rgb_mst,
+ 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;
+ val = v_WIN0_DATA_FMT(format) | v_WIN0_RB_SWAP(swap);
+ lcdc_msk_reg(lcdc_dev, WIN0_CTRL0, mask, val);
+
+ lcdc_msk_reg(lcdc_dev, WIN0_VIR, m_WIN0_VIR_STRIDE,
+ v_WIN0_VIR_STRIDE(xvir));
+ lcdc_writel(lcdc_dev, WIN0_ACT_INFO, v_WIN0_ACT_WIDTH(xact) |
+ v_WIN0_ACT_HEIGHT(yact));
+
+ 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;
+ }
h_total = hsync_len + left_margin + x_res + right_margin;
v_total = vsync_len + upper_margin + y_res + lower_margin;
case OUT_P565:
face = OUT_P565;
mask = m_DITHER_DOWN_EN | m_DITHER_DOWN_MODE |
- m_DITHER_DOWN_SEL;
+ m_DITHER_DOWN_SEL | m_DITHER_UP_EN |
+ m_PRE_DITHER_DOWN_EN;
val = v_DITHER_DOWN_EN(1) | v_DITHER_DOWN_MODE(0) |
- v_DITHER_DOWN_SEL(1);
+ v_DITHER_DOWN_SEL(1) | v_DITHER_UP_EN(1) |
+ v_PRE_DITHER_DOWN_EN(1);
lcdc_msk_reg(lcdc_dev, DSP_CTRL1, mask, val);
break;
case OUT_P666:
face = OUT_P666;
mask = m_DITHER_DOWN_EN | m_DITHER_DOWN_MODE |
- m_DITHER_DOWN_SEL;
+ m_DITHER_DOWN_SEL | m_DITHER_UP_EN |
+ m_PRE_DITHER_DOWN_EN;
val = v_DITHER_DOWN_EN(1) | v_DITHER_DOWN_MODE(1) |
- v_DITHER_DOWN_SEL(1);
+ v_DITHER_DOWN_SEL(1) | v_DITHER_UP_EN(1) |
+ v_PRE_DITHER_DOWN_EN(1);
lcdc_msk_reg(lcdc_dev, DSP_CTRL1, mask, val);
break;
case OUT_D888_P565:
face = OUT_P888;
mask = m_DITHER_DOWN_EN | m_DITHER_DOWN_MODE |
- m_DITHER_DOWN_SEL;
+ m_DITHER_DOWN_SEL | m_DITHER_UP_EN |
+ m_PRE_DITHER_DOWN_EN;
val = v_DITHER_DOWN_EN(1) | v_DITHER_DOWN_MODE(0) |
- v_DITHER_DOWN_SEL(1);
+ v_DITHER_DOWN_SEL(1) | v_DITHER_UP_EN(1) |
+ v_PRE_DITHER_DOWN_EN(1);
lcdc_msk_reg(lcdc_dev, DSP_CTRL1, mask, val);
break;
case OUT_D888_P666:
face = OUT_P888;
mask = m_DITHER_DOWN_EN | m_DITHER_DOWN_MODE |
- m_DITHER_DOWN_SEL;
+ m_DITHER_DOWN_SEL | m_DITHER_UP_EN |
+ m_PRE_DITHER_DOWN_EN;
val = v_DITHER_DOWN_EN(1) | v_DITHER_DOWN_MODE(1) |
- v_DITHER_DOWN_SEL(1);
+ v_DITHER_DOWN_SEL(1) | v_DITHER_UP_EN(1) |
+ v_PRE_DITHER_DOWN_EN(1);
lcdc_msk_reg(lcdc_dev, DSP_CTRL1, mask, val);
break;
case OUT_P888:
face = OUT_P888;
- mask = m_DITHER_DOWN_EN | m_DITHER_UP_EN;
- val = v_DITHER_DOWN_EN(0) | v_DITHER_UP_EN(0);
+ 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:
+ 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 |
+ 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;
default:
switch(screen->type){
case SCREEN_RGB:
case SCREEN_LVDS:
- case SCREEN_DUAL_LVDS:
+ case SCREEN_DUAL_LVDS:
+ case SCREEN_LVDS_10BIT:
+ case SCREEN_DUAL_LVDS_10BIT:
mask = m_RGB_OUT_EN;
val = v_RGB_OUT_EN(1);
v = 1 << (3+16);
v |= (lcdc_dev->id << 3);
- break;
+ break;
case SCREEN_HDMI:
- face = OUT_RGB_AAA;
+ 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);
+ val = v_HDMI_OUT_EN(1);
break;
case SCREEN_MIPI:
mask = m_MIPI_OUT_EN;
val = v_MIPI_OUT_EN(1) | v_DOUB_CHANNEL_EN(1);
break;
case SCREEN_EDP:
- face = OUT_RGB_AAA; /*RGB AAA output*/
- mask = m_DITHER_DOWN_EN | m_DITHER_UP_EN;
- val = v_DITHER_DOWN_EN(0) | v_DITHER_UP_EN(0);
- lcdc_msk_reg(lcdc_dev, DSP_CTRL1, mask, val);
+ face = OUT_P101010; /*RGB 101010 output*/
mask = m_EDP_OUT_EN;
- val = v_EDP_OUT_EN(1);
+ 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
writel_relaxed(v, RK_GRF_VIRT + RK3288_GRF_SOC_CON6);
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;
lcdc_msk_reg(lcdc_dev, DSP_VACT_ST_END, mask, val);
rk3288_lcdc_post_cfg(dev_drv);
+ 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);
- if (dev_drv->trsm_ops && dev_drv->trsm_ops->enable)
+ rk3288_lcdc_set_dclk(dev_drv, 1);
+ if (screen->type != SCREEN_HDMI && dev_drv->trsm_ops &&
+ dev_drv->trsm_ops->enable)
dev_drv->trsm_ops->enable();
if (screen->init)
screen->init();
- return 0;
+ return ret;
}
/*enable layer,open:1,enable;0 disable*/
struct lcdc_device *lcdc_dev = container_of(dev_drv,
struct lcdc_device, driver);
u32 mask,val;
- struct rk_screen *screen = dev_drv->cur_screen;
mask = m_FS_INTR_CLR | m_FS_INTR_EN | m_LINE_FLAG_INTR_CLR |
m_LINE_FLAG_INTR_EN | m_BUS_ERROR_INTR_CLR |
- m_BUS_ERROR_INTR_EN | m_DSP_LINE_FLAG_NUM;
+ m_BUS_ERROR_INTR_EN;
val = v_FS_INTR_CLR(1) | v_FS_INTR_EN(1) | v_LINE_FLAG_INTR_CLR(1) |
- v_LINE_FLAG_INTR_EN(1) | v_BUS_ERROR_INTR_CLR(1) | v_BUS_ERROR_INTR_EN(0) |
- v_DSP_LINE_FLAG_NUM(screen->mode.vsync_len + screen->mode.upper_margin +
- screen->mode.yres);
+ v_LINE_FLAG_INTR_EN(1) | v_BUS_ERROR_INTR_CLR(1) | v_BUS_ERROR_INTR_EN(0);
lcdc_msk_reg(lcdc_dev, INTR_CTRL0, mask, val);
#ifdef LCDC_IRQ_EMPTY_DEBUG
mask = m_WIN0_EMPTY_INTR_EN | m_WIN1_EMPTY_INTR_EN | m_WIN2_EMPTY_INTR_EN |
rockchip_set_system_status(sys_status);
rk3288_lcdc_pre_init(dev_drv);
rk3288_lcdc_clk_enable(lcdc_dev);
-#if defined(CONFIG_ROCKCHIP_IOMMU)
+ rk3288_lcdc_enable_irq(dev_drv);
if (dev_drv->iommu_enabled) {
if (!dev_drv->mmu_dev) {
dev_drv->mmu_dev =
return -1;
}
}
- if (dev_drv->mmu_dev)
- rockchip_iovmm_activate(dev_drv->dev);
}
-#endif
rk3288_lcdc_reg_restore(lcdc_dev);
- if (dev_drv->iommu_enabled)
- rk3288_lcdc_mmu_en(dev_drv);
+ /*if (dev_drv->iommu_enabled)
+ rk3368_lcdc_mmu_en(dev_drv); */
if ((support_uboot_display()&&(lcdc_dev->prop == PRMRY))) {
- rk3288_lcdc_set_dclk(dev_drv);
- rk3288_lcdc_enable_irq(dev_drv);
+ rk3288_lcdc_set_dclk(dev_drv, 0);
+ /* rk3288_lcdc_enable_irq(dev_drv); */
} else {
rk3288_load_screen(dev_drv, 1);
}
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;
yrgb_srcH = srcH;
yrgb_dstW = dstW;
yrgb_dstH = dstH;
- if ((yrgb_dstW >= yrgb_srcW*8) || (yrgb_dstH >= yrgb_srcH*8) ||
- (yrgb_dstW*8 <= yrgb_srcW) || (yrgb_dstH*8 <= yrgb_srcH)) {
+ if ((yrgb_dstW*8 <= yrgb_srcW) || (yrgb_dstH*8 <= yrgb_srcH)) {
pr_err("ERROR: yrgb scale exceed 8,"
"srcW=%d,srcH=%d,dstW=%d,dstH=%d\n",
yrgb_srcW,yrgb_srcH,yrgb_dstW,yrgb_dstH);
}
/*cbcr scl mode*/
- switch (win->format) {
+ switch (win->area[0].format) {
case YUV422:
case YUV422_A:
cbcr_srcW = srcW/2;
break;
}
if (yuv_fmt) {
- if ((cbcr_dstW >= cbcr_srcW*8) || (cbcr_dstH >= cbcr_srcH*8) ||
- (cbcr_dstW*8 <= cbcr_srcW)||(cbcr_dstH*8 <= cbcr_srcH)) {
+ if ((cbcr_dstW*8 <= cbcr_srcW) || (cbcr_dstH*8 <= cbcr_srcH)) {
pr_err("ERROR: cbcr scale exceed 8,"
"srcW=%d,srcH=%d,dstW=%d,dstH=%d\n",
cbcr_srcW,cbcr_srcH,cbcr_dstW,cbcr_dstH);
win->cbr_hor_scl_mode,win->cbr_ver_scl_mode);
/*line buffer mode*/
- if((win->format == YUV422) || (win->format == YUV420) || (win->format == YUV422_A) || (win->format == YUV420_A)){
- if(win->cbr_hor_scl_mode == SCALE_DOWN){
+ if ((win->area[0].format == YUV422) ||
+ (win->area[0].format == YUV420) ||
+ (win->area[0].format == YUV422_A) ||
+ (win->area[0].format == YUV420_A)) {
+ if (win->cbr_hor_scl_mode == SCALE_DOWN) {
if ((cbcr_dstW > 3840) || (cbcr_dstW == 0)) {
pr_err("ERROR cbcr_dstW = %d\n",cbcr_dstW);
- }else if(cbcr_dstW > 2560){
+ } else if (cbcr_dstW > 2560) {
win->win_lb_mode = LB_RGB_3840X2;
- }else if(cbcr_dstW > 1920){
- if(win->yrgb_hor_scl_mode == SCALE_DOWN){
+ } else if (cbcr_dstW > 1920) {
+ if (win->yrgb_hor_scl_mode == SCALE_DOWN) {
if(yrgb_dstW > 3840){
pr_err("ERROR yrgb_dst_width exceeds 3840\n");
}else if(yrgb_dstW > 2560){
}else{
pr_err("ERROR never run here!yrgb_dstW<1920 ==> cbcr_dstW>1920\n");
}
- }
- }else if(cbcr_dstW > 1280){
+ }
+ } else if (cbcr_dstW > 1280) {
win->win_lb_mode = LB_YUV_3840X5;
- }else{
+ } else {
win->win_lb_mode = LB_YUV_2560X8;
}
- } else { /*SCALE_UP or SCALE_NONE*/
+ } else { /*SCALE_UP or SCALE_NONE*/
if ((cbcr_srcW > 3840) || (cbcr_srcW == 0)) {
pr_err("ERROR cbcr_srcW = %d\n",cbcr_srcW);
}else if(cbcr_srcW > 2560){
struct rk_screen *screen, struct rk_lcdc_win *win)
{
u32 xact,yact,xvir, yvir,xpos, ypos;
- u8 fmt_cfg = 0;
+ u8 fmt_cfg = 0, swap_rb, swap_uv = 0;
char fmt[9] = "NULL";
xpos = win->area[0].xpos + screen->mode.left_margin + screen->mode.hsync_len;
spin_lock(&lcdc_dev->reg_lock);
if(likely(lcdc_dev->clk_on)){
rk3288_lcdc_cal_scl_fac(win);/*fac,lb,gt2,gt4*/
- switch (win->format){
+ switch (win->area[0].format) {
case ARGB888:
fmt_cfg = 0;
- win->swap_rb = 0;
+ swap_rb = 0;
win->fmt_10 = 0;
break;
case XBGR888:
case ABGR888:
fmt_cfg = 0;
- win->swap_rb = 1;
+ swap_rb = 1;
win->fmt_10 = 0;
break;
case RGB888:
fmt_cfg = 1;
- win->swap_rb = 0;
+ swap_rb = 0;
win->fmt_10 = 0;
break;
case RGB565:
fmt_cfg = 2;
- win->swap_rb = 0;
+ swap_rb = 0;
win->fmt_10 = 0;
break;
case YUV422:
fmt_cfg = 5;
- win->swap_rb = 0;
+ swap_rb = 0;
win->fmt_10 = 0;
break;
case YUV420:
fmt_cfg = 4;
- win->swap_rb = 0;
+ swap_rb = 0;
win->fmt_10 = 0;
break;
+ case YUV420_NV21:
+ fmt_cfg = 4;
+ swap_rb = 0;
+ swap_uv = 1;
+ win->fmt_10 = 0;
+ break;
case YUV444:
fmt_cfg = 6;
- win->swap_rb = 0;
+ swap_rb = 0;
win->fmt_10 = 0;
case YUV422_A:
fmt_cfg = 5;
- win->swap_rb = 0;
+ swap_rb = 0;
win->fmt_10 = 1;
break;
case YUV420_A:
fmt_cfg = 4;
- win->swap_rb = 0;
+ swap_rb = 0;
win->fmt_10 = 1;
break;
case YUV444_A:
fmt_cfg = 6;
- win->swap_rb = 0;
+ swap_rb = 0;
win->fmt_10 = 1;
break;
default:
__func__);
break;
}
- win->fmt_cfg = fmt_cfg;
+ win->area[0].fmt_cfg = fmt_cfg;
+ win->area[0].swap_rb = swap_rb;
win->area[0].dsp_stx = xpos;
win->area[0].dsp_sty = ypos;
+ win->area[0].swap_uv = swap_uv;
xact = win->area[0].xact;
yact = win->area[0].yact;
xvir = win->area[0].xvir;
DBG(1, "lcdc%d>>%s\n>>format:%s>>>xact:%d>>yact:%d>>xsize:%d>>ysize:%d\n"
">>xvir:%d>>yvir:%d>>xpos:%d>>ypos:%d>>\n", lcdc_dev->id,
- __func__, get_format_string(win->format, fmt), xact,
+ __func__, get_format_string(win->area[0].format, fmt), xact,
yact, win->area[0].xsize, win->area[0].ysize, xvir, yvir, xpos, ypos);
return 0;
static int win1_set_par(struct lcdc_device *lcdc_dev,
struct rk_screen *screen, struct rk_lcdc_win *win)
{
- u32 xact,yact,xvir, yvir,xpos, ypos;
- u8 fmt_cfg = 0;
+ u32 xact, yact, xvir, yvir, xpos, ypos;
+ u8 fmt_cfg = 0, swap_rb, swap_uv = 0;
char fmt[9] = "NULL";
xpos = win->area[0].xpos + screen->mode.left_margin + screen->mode.hsync_len;
ypos = win->area[0].ypos + screen->mode.upper_margin + screen->mode.vsync_len;
spin_lock(&lcdc_dev->reg_lock);
- if(likely(lcdc_dev->clk_on)){
+ if (likely(lcdc_dev->clk_on)) {
rk3288_lcdc_cal_scl_fac(win);/*fac,lb,gt2,gt4*/
- switch (win->format){
+ switch (win->area[0].format) {
case ARGB888:
fmt_cfg = 0;
- win->swap_rb = 0;
+ swap_rb = 0;
win->fmt_10 = 0;
break;
case XBGR888:
case ABGR888:
fmt_cfg = 0;
- win->swap_rb = 1;
+ swap_rb = 1;
win->fmt_10 = 0;
break;
case RGB888:
fmt_cfg = 1;
- win->swap_rb = 0;
+ swap_rb = 0;
win->fmt_10 = 0;
break;
case RGB565:
fmt_cfg = 2;
- win->swap_rb = 0;
+ swap_rb = 0;
win->fmt_10 = 0;
break;
case YUV422:
fmt_cfg = 5;
- win->swap_rb = 0;
+ swap_rb = 0;
win->fmt_10 = 0;
break;
case YUV420:
fmt_cfg = 4;
- win->swap_rb = 0;
+ swap_rb = 0;
+ win->fmt_10 = 0;
+ break;
+ case YUV420_NV21:
+ fmt_cfg = 4;
+ swap_rb = 0;
+ swap_uv = 1;
win->fmt_10 = 0;
break;
case YUV444:
fmt_cfg = 6;
- win->swap_rb = 0;
+ swap_rb = 0;
win->fmt_10 = 0;
break;
case YUV422_A:
fmt_cfg = 5;
- win->swap_rb = 0;
+ swap_rb = 0;
win->fmt_10 = 1;
break;
case YUV420_A:
fmt_cfg = 4;
- win->swap_rb = 0;
+ swap_rb = 0;
win->fmt_10 = 1;
break;
case YUV444_A:
fmt_cfg = 6;
- win->swap_rb = 0;
+ swap_rb = 0;
win->fmt_10 = 1;
break;
default:
__func__);
break;
}
- win->fmt_cfg = fmt_cfg;
+ win->area[0].fmt_cfg = fmt_cfg;
+ win->area[0].swap_rb = swap_rb;
win->area[0].dsp_stx = xpos;
win->area[0].dsp_sty = ypos;
+ win->area[0].swap_uv = swap_uv;
xact = win->area[0].xact;
yact = win->area[0].yact;
xvir = win->area[0].xvir;
DBG(1, "lcdc%d>>%s\n>>format:%s>>>xact:%d>>yact:%d>>xsize:%d>>ysize:%d\n"
">>xvir:%d>>yvir:%d>>xpos:%d>>ypos:%d>>\n", lcdc_dev->id,
- __func__, get_format_string(win->format, fmt), xact,
+ __func__, get_format_string(win->area[0].format, fmt), xact,
yact, win->area[0].xsize, win->area[0].ysize, xvir, yvir, xpos, ypos);
return 0;
struct rk_screen *screen, struct rk_lcdc_win *win)
{
int i;
- u8 fmt_cfg;
+ u8 fmt_cfg, swap_rb;
spin_lock(&lcdc_dev->reg_lock);
- if(likely(lcdc_dev->clk_on)){
- for(i=0;i<win->area_num;i++){
- switch (win->format){
+ if (likely(lcdc_dev->clk_on)) {
+ for (i = 0; i < win->area_num; i++) {
+ switch (win->area[i].format) {
case ARGB888:
fmt_cfg = 0;
- win->swap_rb = 0;
+ swap_rb = 0;
break;
case XBGR888:
case ABGR888:
fmt_cfg = 0;
- win->swap_rb = 1;
+ swap_rb = 1;
break;
case RGB888:
fmt_cfg = 1;
- win->swap_rb = 0;
+ swap_rb = 0;
break;
case RGB565:
fmt_cfg = 2;
- win->swap_rb = 0;
+ swap_rb = 0;
break;
default:
dev_err(lcdc_dev->driver.dev,
__func__);
break;
}
- win->fmt_cfg = fmt_cfg;
+ win->area[i].fmt_cfg = fmt_cfg;
+ win->area[i].swap_rb = swap_rb;
win->area[i].dsp_stx = win->area[i].xpos +
screen->mode.left_margin +
screen->mode.hsync_len;
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;
+ }
}
}
rk3288_win_2_3_reg_update(&lcdc_dev->driver,2);
{
int i;
- u8 fmt_cfg;
+ u8 fmt_cfg, swap_rb;
spin_lock(&lcdc_dev->reg_lock);
- if(likely(lcdc_dev->clk_on)){
- for(i=0;i<win->area_num;i++){
- switch (win->format){
+ if (likely(lcdc_dev->clk_on)) {
+ for (i = 0; i < win->area_num; i++) {
+ switch (win->area[i].format) {
case ARGB888:
fmt_cfg = 0;
- win->swap_rb = 0;
+ swap_rb = 0;
break;
case XBGR888:
case ABGR888:
fmt_cfg = 0;
- win->swap_rb = 1;
+ swap_rb = 1;
break;
case RGB888:
fmt_cfg = 1;
- win->swap_rb = 0;
+ swap_rb = 0;
break;
case RGB565:
fmt_cfg = 2;
- win->swap_rb = 0;
+ swap_rb = 0;
break;
default:
dev_err(lcdc_dev->driver.dev,
__func__);
break;
}
- win->fmt_cfg = fmt_cfg;
+ win->area[i].fmt_cfg = fmt_cfg;
+ win->area[i].swap_rb = swap_rb;
win->area[i].dsp_stx = win->area[i].xpos +
screen->mode.left_margin +
screen->mode.hsync_len;
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;
+ }
}
}
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));
return 0;
}
-static int rk3288_lcdc_get_win_state(struct rk_lcdc_driver *dev_drv, int win_id)
+static int rk3288_lcdc_get_win_state(struct rk_lcdc_driver *dev_drv,
+ int win_id, int area_id)
{
- return 0;
+ struct lcdc_device *lcdc_dev =
+ container_of(dev_drv, struct lcdc_device, driver);
+ u32 win_ctrl = 0;
+ u32 area_status = 0;
+
+ switch (win_id) {
+ case 0:
+ win_ctrl = lcdc_readl(lcdc_dev, WIN0_CTRL0);
+ area_status = win_ctrl & m_WIN0_EN;
+ break;
+ case 1:
+ win_ctrl = lcdc_readl(lcdc_dev, WIN1_CTRL0);
+ area_status = win_ctrl & m_WIN1_EN;
+ break;
+ case 2:
+ win_ctrl = lcdc_readl(lcdc_dev, WIN2_CTRL0);
+ if (area_id == 0)
+ area_status = win_ctrl & m_WIN2_MST0_EN;
+ if (area_id == 1)
+ area_status = win_ctrl & m_WIN2_MST1_EN;
+ if (area_id == 2)
+ area_status = win_ctrl & m_WIN2_MST2_EN;
+ if (area_id == 3)
+ area_status = win_ctrl & m_WIN2_MST3_EN;
+ break;
+ case 3:
+ win_ctrl = lcdc_readl(lcdc_dev, WIN3_CTRL0);
+ if (area_id == 0)
+ area_status = win_ctrl & m_WIN3_MST0_EN;
+ if (area_id == 1)
+ area_status = win_ctrl & m_WIN3_MST1_EN;
+ if (area_id == 2)
+ area_status = win_ctrl & m_WIN3_MST2_EN;
+ if (area_id == 3)
+ area_status = win_ctrl & m_WIN3_MST3_EN;
+ break;
+ case 4:
+ win_ctrl = lcdc_readl(lcdc_dev, HWC_CTRL0);
+ area_status = win_ctrl & m_HWC_EN;
+ break;
+ default:
+ pr_err("!!!%s,win[%d]area[%d],unsupport!!!\n",__func__,win_id,area_id);
+ break;
+ }
+ return area_status;
+}
+
+static int rk3288_lcdc_get_area_num(struct rk_lcdc_driver *dev_drv,
+ unsigned int *area_support)
+{
+ area_support[0] = 1;
+ area_support[1] = 1;
+ area_support[2] = 4;
+ area_support[3] = 4;
+
+ return 0;
}
/*overlay will be do at regupdate*/
u32 pixclock;
u32 x_total, y_total;
if (set) {
+ if (fps == 0) {
+ dev_info(dev_drv->dev, "unsupport set fps=0\n");
+ return 0;
+ }
ft = div_u64(1000000000000llu, fps);
x_total =
screen->mode.upper_margin + screen->mode.lower_margin +
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 ret;
}
-static int rk3288_lcdc_get_dsp_addr(struct rk_lcdc_driver *dev_drv,unsigned int *dsp_addr)
+
+static int rk3288_lcdc_get_dsp_addr(struct rk_lcdc_driver *dev_drv,
+ unsigned int dsp_addr[][4])
{
struct lcdc_device *lcdc_dev =
container_of(dev_drv, struct lcdc_device, driver);
spin_lock(&lcdc_dev->reg_lock);
- if(lcdc_dev->clk_on){
- dsp_addr[0] = lcdc_readl(lcdc_dev, WIN0_YRGB_MST);
- dsp_addr[1] = lcdc_readl(lcdc_dev, WIN1_YRGB_MST);
- dsp_addr[2] = lcdc_readl(lcdc_dev, WIN2_MST0);
- dsp_addr[3] = lcdc_readl(lcdc_dev, WIN3_MST0);
+ if (lcdc_dev->clk_on) {
+ dsp_addr[0][0] = lcdc_readl(lcdc_dev, WIN0_YRGB_MST);
+ dsp_addr[1][0] = lcdc_readl(lcdc_dev, WIN1_YRGB_MST);
+ dsp_addr[2][0] = lcdc_readl(lcdc_dev, WIN2_MST0);
+ dsp_addr[2][1] = lcdc_readl(lcdc_dev, WIN2_MST1);
+ dsp_addr[2][2] = lcdc_readl(lcdc_dev, WIN2_MST2);
+ dsp_addr[2][3] = lcdc_readl(lcdc_dev, WIN2_MST3);
+ dsp_addr[3][0] = lcdc_readl(lcdc_dev, WIN3_MST0);
+ dsp_addr[3][1] = lcdc_readl(lcdc_dev, WIN3_MST1);
+ dsp_addr[3][2] = lcdc_readl(lcdc_dev, WIN3_MST2);
+ dsp_addr[3][3] = lcdc_readl(lcdc_dev, WIN3_MST3);
}
spin_unlock(&lcdc_dev->reg_lock);
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 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);
+ u32 total_pixel, calc_pixel, stage_up, stage_down;
+ u32 pixel_num, global_dn;
+ u32 mask = 0, val = 0;
- dev_drv->cabc_mode = mode;
-
- /* 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);
return 0;
}
+static int rk3288_lcdc_set_overscan(struct rk_lcdc_driver *dev_drv,
+ struct overscan *overscan)
+{
+ struct lcdc_device *lcdc_dev =
+ container_of(dev_drv, struct lcdc_device, driver);
+
+ if (unlikely(!lcdc_dev->clk_on)) {
+ pr_info("%s,clk_on = %d\n", __func__, lcdc_dev->clk_on);
+ return 0;
+ }
+ rk3288_lcdc_post_cfg(dev_drv);
+
+ return 0;
+}
+
static struct rk_lcdc_win lcdc_win[] = {
[0] = {
.name = "win0",
.open = rk3288_lcdc_open,
.win_direct_en = rk3288_lcdc_win_direct_en,
.load_screen = rk3288_load_screen,
+ .get_dspbuf_info = rk3288_get_dspbuf_info,
+ .post_dspbuf = rk3288_post_dspbuf,
.set_par = rk3288_lcdc_set_par,
.pan_display = rk3288_lcdc_pan_display,
.direct_set_addr = rk3288_lcdc_direct_set_win_addr,
.suspend = rk3288_lcdc_early_suspend,
.resume = rk3288_lcdc_early_resume,
.get_win_state = rk3288_lcdc_get_win_state,
+ .area_support_num = rk3288_lcdc_get_area_num,
.ovl_mgr = rk3288_lcdc_ovl_mgr,
.get_disp_info = rk3288_lcdc_get_disp_info,
.fps_mgr = rk3288_lcdc_fps_mgr,
.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,
.dump_reg = rk3288_lcdc_reg_dump,
.cfg_done = rk3288_lcdc_config_done,
.set_irq_to_cpu = rk3288_lcdc_set_irq_to_cpu,
+ .mmu_en = rk3288_lcdc_mmu_en,
+ .set_overscan = rk3288_lcdc_set_overscan,
+
};
#ifdef LCDC_IRQ_DEBUG
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;
}