video: rockchip: vop: 3399: fix afbdc abnormal
[firefly-linux-kernel-4.4.55.git] / drivers / video / rockchip / lcdc / rk3036_lcdc.c
index c278bb51d82f4910b91836e1091d481a5e074e16..dbaf15bfafe4c72448ba72d43f2e2296315629a2 100755 (executable)
@@ -180,8 +180,8 @@ static int rk3036_lcdc_alpha_cfg(struct lcdc_device *lcdc_dev)
 {
        int win0_top = 0;
        u32 mask, val;
-       enum data_format win0_format = lcdc_dev->driver.win[0]->format;
-       enum data_format win1_format = lcdc_dev->driver.win[1]->format;
+       enum data_format win0_format = lcdc_dev->driver.win[0]->area[0].format;
+       enum data_format win1_format = lcdc_dev->driver.win[1]->area[0].format;
 
        int win0_alpha_en = ((win0_format == ARGB888) ||
                                (win0_format == ABGR888)) ? 1 : 0;
@@ -252,8 +252,8 @@ static void lcdc_layer_update_regs(struct lcdc_device *lcdc_dev,
                if (win->id == 0) {
                        mask = m_WIN0_EN | m_WIN0_FORMAT | m_WIN0_RB_SWAP;
                        val = v_WIN0_EN(win->state) |
-                             v_WIN0_FORMAT(win->fmt_cfg) |
-                             v_WIN0_RB_SWAP(win->swap_rb);
+                             v_WIN0_FORMAT(win->area[0].fmt_cfg) |
+                             v_WIN0_RB_SWAP(win->area[0].swap_rb);
                        lcdc_msk_reg(lcdc_dev, SYS_CTRL, mask, val);
                        lcdc_writel(lcdc_dev, WIN0_SCL_FACTOR_YRGB,
                                    v_X_SCL_FACTOR(win->scale_yrgb_x) |
@@ -282,8 +282,8 @@ static void lcdc_layer_update_regs(struct lcdc_device *lcdc_dev,
                } else if (win->id == 1) {
                        mask = m_WIN1_EN | m_WIN1_FORMAT | m_WIN1_RB_SWAP;
                        val = v_WIN1_EN(win->state) |
-                             v_WIN1_FORMAT(win->fmt_cfg) |
-                             v_WIN1_RB_SWAP(win->swap_rb);
+                             v_WIN1_FORMAT(win->area[0].fmt_cfg) |
+                             v_WIN1_RB_SWAP(win->area[0].swap_rb);
                        lcdc_msk_reg(lcdc_dev, SYS_CTRL, mask, val);
                        lcdc_writel(lcdc_dev, WIN1_SCL_FACTOR_YRGB,
                                    v_X_SCL_FACTOR(win->scale_yrgb_x) |
@@ -324,15 +324,23 @@ static void lcdc_layer_update_regs(struct lcdc_device *lcdc_dev,
        } else {
                win->area[0].y_addr = 0;
                win->area[0].uv_addr = 0;
-               if (win->id == 0)
+               if (win->id == 0) {
                        lcdc_msk_reg(lcdc_dev,
                                     SYS_CTRL, m_WIN0_EN, v_WIN0_EN(0));
-               else if (win->id == 1)
+                       lcdc_writel(lcdc_dev, WIN0_YRGB_MST,
+                                   win->area[0].y_addr);
+                       lcdc_writel(lcdc_dev, WIN0_CBR_MST,
+                                   win->area[0].uv_addr);
+               } else if (win->id == 1) {
                        lcdc_msk_reg(lcdc_dev,
                                     SYS_CTRL, m_WIN1_EN, v_WIN1_EN(0));
-               else if (win->id == 2)
+                       lcdc_writel(lcdc_dev, WIN1_MST, win->area[0].y_addr);
+               } else if (win->id == 2) {
                        lcdc_msk_reg(lcdc_dev,
-                                    SYS_CTRL, m_HWC_EN, v_HWC_EN(0));
+                                    SYS_CTRL, m_HWC_EN | m_HWC_LODAD_EN,
+                                    v_HWC_EN(0) | v_HWC_LODAD_EN(0));
+                       lcdc_writel(lcdc_dev, HWC_MST, win->area[0].y_addr);
+               }
        }
        rk3036_lcdc_alpha_cfg(lcdc_dev);
 }
@@ -349,9 +357,9 @@ static void lcdc_layer_enable(struct lcdc_device *lcdc_dev,
                                         "wakeup from standby!\n");
                                lcdc_dev->standby = 0;
                        }
-                       lcdc_dev->atv_layer_cnt++;
-               } else if ((lcdc_dev->atv_layer_cnt > 0) && (!open)) {
-                       lcdc_dev->atv_layer_cnt--;
+                       lcdc_dev->atv_layer_cnt |= (1 << win_id);
+               } else if ((lcdc_dev->atv_layer_cnt & (1 << win_id)) && (!open)) {
+                       lcdc_dev->atv_layer_cnt &= ~(1 << win_id);
                }
                lcdc_dev->driver.win[win_id]->state = open;
                if (!open) {
@@ -508,6 +516,9 @@ static int rk3036_lcdc_pre_init(struct rk_lcdc_driver *dev_drv)
 
        /*backup reg config at uboot*/
        rk_lcdc_read_reg_defalut_cfg(lcdc_dev);
+       if (lcdc_readl(lcdc_dev, AXI_BUS_CTRL) & m_TVE_DAC_DCLK_EN)
+               dev_drv->cur_screen->type = SCREEN_TVOUT;
+
        lcdc_msk_reg(lcdc_dev, SYS_CTRL, m_AUTO_GATING_EN,
                     v_AUTO_GATING_EN(0));
        lcdc_cfg_done(lcdc_dev);
@@ -615,7 +626,7 @@ static int rk3036_load_screen(struct rk_lcdc_driver *dev_drv, bool initscreen)
                    v_HASP(screen->mode.hsync_len + left_margin);
                lcdc_writel(lcdc_dev, DSP_HACT_ST_END, val);
 
-               if (screen->mode.vmode == FB_VMODE_INTERLACED) {
+               if (screen->mode.vmode & FB_VMODE_INTERLACED) {
                        /*First Field Timing*/
                        lcdc_writel(lcdc_dev, DSP_VTOTAL_VS_END,
                                    v_VSYNC(screen->mode.vsync_len) |
@@ -717,7 +728,6 @@ static int rk3036_lcdc_open(struct rk_lcdc_driver *dev_drv, int win_id,
        if ((open) && (!lcdc_dev->atv_layer_cnt)) {
                rk3036_lcdc_pre_init(dev_drv);
                rk3036_lcdc_clk_enable(lcdc_dev);
-       #if defined(CONFIG_ROCKCHIP_IOMMU)
                if (dev_drv->iommu_enabled) {
                        if (!dev_drv->mmu_dev) {
                                dev_drv->mmu_dev =
@@ -734,7 +744,6 @@ static int rk3036_lcdc_open(struct rk_lcdc_driver *dev_drv, int win_id,
                                }
                        }
                }
-       #endif
                rk3036_lcdc_reg_restore(lcdc_dev);
                /*if (dev_drv->iommu_enabled)
                        rk3036_lcdc_mmu_en(dev_drv);*/
@@ -756,12 +765,10 @@ static int rk3036_lcdc_open(struct rk_lcdc_driver *dev_drv, int win_id,
        if ((!open) && (!lcdc_dev->atv_layer_cnt)) {
                rk3036_lcdc_disable_irq(lcdc_dev);
                rk3036_lcdc_reg_update(dev_drv);
-               #if defined(CONFIG_ROCKCHIP_IOMMU)
                if (dev_drv->iommu_enabled) {
                        if (dev_drv->mmu_dev)
                                rockchip_iovmm_deactivate(dev_drv->dev);
                }
-               #endif
                rk3036_lcdc_clk_disable(lcdc_dev);
        }
 */
@@ -810,7 +817,7 @@ static int rk3036_lcdc_set_par(struct rk_lcdc_driver *dev_drv, int win_id)
 
        win->area[0].dsp_stx = win->post_cfg.xpos + screen->mode.left_margin +
                                screen->mode.hsync_len;
-       if (screen->mode.vmode == FB_VMODE_INTERLACED) {
+       if (screen->mode.vmode & FB_VMODE_INTERLACED) {
                win->post_cfg.ysize /= 2;
                win->area[0].dsp_sty = win->post_cfg.ypos/2 +
                                        screen->mode.upper_margin +
@@ -823,35 +830,35 @@ static int rk3036_lcdc_set_par(struct rk_lcdc_driver *dev_drv, int win_id)
        win->scale_yrgb_x = calscale(win->area[0].xact, win->post_cfg.xsize);
        win->scale_yrgb_y = calscale(win->area[0].yact, win->post_cfg.ysize);
 
-       switch (win->format) {
+       switch (win->area[0].format) {
        case ARGB888:
-               win->fmt_cfg = VOP_FORMAT_ARGB888;
-               win->swap_rb = 0;
+               win->area[0].fmt_cfg = VOP_FORMAT_ARGB888;
+               win->area[0].swap_rb = 0;
                break;
        case XBGR888:
-               win->fmt_cfg = VOP_FORMAT_ARGB888;
-               win->swap_rb = 1;
+               win->area[0].fmt_cfg = VOP_FORMAT_ARGB888;
+               win->area[0].swap_rb = 1;
                break;
        case ABGR888:
-               win->fmt_cfg = VOP_FORMAT_ARGB888;
-               win->swap_rb = 1;
+               win->area[0].fmt_cfg = VOP_FORMAT_ARGB888;
+               win->area[0].swap_rb = 1;
                break;
        case RGB888:
-               win->fmt_cfg = VOP_FORMAT_RGB888;
-               win->swap_rb = 0;
+               win->area[0].fmt_cfg = VOP_FORMAT_RGB888;
+               win->area[0].swap_rb = 0;
                break;
        case RGB565:
-               win->fmt_cfg = VOP_FORMAT_RGB565;
-               win->swap_rb = 0;
+               win->area[0].fmt_cfg = VOP_FORMAT_RGB565;
+               win->area[0].swap_rb = 0;
                break;
        case YUV444:
                if (win_id == 0) {
-                       win->fmt_cfg = VOP_FORMAT_YCBCR444;
+                       win->area[0].fmt_cfg = VOP_FORMAT_YCBCR444;
                        win->scale_cbcr_x = calscale(win->area[0].xact,
                                                     win->post_cfg.xsize);
                        win->scale_cbcr_y = calscale(win->area[0].yact,
                                                     win->post_cfg.ysize);
-                       win->swap_rb = 0;
+                       win->area[0].swap_rb = 0;
                } else {
                        dev_err(lcdc_dev->driver.dev,
                                "%s:un supported format!\n",
@@ -860,12 +867,12 @@ static int rk3036_lcdc_set_par(struct rk_lcdc_driver *dev_drv, int win_id)
                break;
        case YUV422:
                if (win_id == 0) {
-                       win->fmt_cfg = VOP_FORMAT_YCBCR422;
+                       win->area[0].fmt_cfg = VOP_FORMAT_YCBCR422;
                        win->scale_cbcr_x = calscale((win->area[0].xact / 2),
                                                     win->post_cfg.xsize);
                        win->scale_cbcr_y = calscale(win->area[0].yact,
                                                     win->post_cfg.ysize);
-                       win->swap_rb = 0;
+                       win->area[0].swap_rb = 0;
                } else {
                        dev_err(lcdc_dev->driver.dev,
                                "%s:un supported format!\n",
@@ -874,12 +881,12 @@ static int rk3036_lcdc_set_par(struct rk_lcdc_driver *dev_drv, int win_id)
                break;
        case YUV420:
                if (win_id == 0) {
-                       win->fmt_cfg = VOP_FORMAT_YCBCR420;
+                       win->area[0].fmt_cfg = VOP_FORMAT_YCBCR420;
                        win->scale_cbcr_x = calscale(win->area[0].xact / 2,
                                                     win->post_cfg.xsize);
                        win->scale_cbcr_y = calscale(win->area[0].yact / 2,
                                                     win->post_cfg.ysize);
-                       win->swap_rb = 0;
+                       win->area[0].swap_rb = 0;
                } else {
                        dev_err(lcdc_dev->driver.dev,
                                "%s:un supported format!\n",
@@ -896,7 +903,7 @@ static int rk3036_lcdc_set_par(struct rk_lcdc_driver *dev_drv, int win_id)
        DBG(2, "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),
+               __func__, get_format_string(win->area[0].format, fmt),
                win->area[0].xact, win->area[0].yact, win->post_cfg.xsize,
                win->post_cfg.ysize, win->area[0].xvir, win->area[0].yvir,
                win->post_cfg.xpos, win->post_cfg.ypos);
@@ -1000,7 +1007,8 @@ static int rk3036_lcdc_get_win_id(struct rk_lcdc_driver *dev_drv,
 }
 
 static int rk3036_lcdc_get_win_state(struct rk_lcdc_driver *dev_drv,
-                                    int win_id)
+                                    int win_id,
+                                    int area_id)
 {
        return dev_drv->win[win_id]->state;
 }
@@ -1015,7 +1023,9 @@ static int rk3036_lcdc_ovl_mgr(struct rk_lcdc_driver *dev_drv, int swap,
        int ovl, needswap = 0;
 
        if (!swap) {
-               if (win0->z_order > win1->z_order)
+               if (win0->z_order >= 0 &&
+                   win1->z_order >= 0 &&
+                   win0->z_order > win1->z_order)
                        needswap = 1;
                else
                        needswap = 0;
@@ -1138,12 +1148,10 @@ static int rk3036_lcdc_cfg_done(struct rk_lcdc_driver *dev_drv)
        struct lcdc_device *lcdc_dev =
            container_of(dev_drv, struct lcdc_device, driver);
        int i;
-       unsigned int mask, val;
        struct rk_lcdc_win *win = NULL;
 
        spin_lock(&lcdc_dev->reg_lock);
        if (lcdc_dev->clk_on) {
-               #if defined(CONFIG_ROCKCHIP_IOMMU)
                if (dev_drv->iommu_enabled) {
                        if (!lcdc_dev->iommu_status && dev_drv->mmu_dev) {
                                lcdc_dev->iommu_status = 1;
@@ -1161,35 +1169,12 @@ static int rk3036_lcdc_cfg_done(struct rk_lcdc_driver *dev_drv)
                                rk3036_lcdc_mmu_en(dev_drv);
                        }
                }
-               #endif
                lcdc_msk_reg(lcdc_dev, SYS_CTRL, m_LCDC_STANDBY,
                             v_LCDC_STANDBY(lcdc_dev->standby));
                for (i = 0; i < ARRAY_SIZE(lcdc_win); i++) {
                        win = dev_drv->win[i];
-                       if ((win->state == 0) && (win->last_state == 1)) {
-                               switch (win->id) {
-                               case 0:
-                                       mask =  m_WIN0_EN;
-                                       val  =  v_WIN0_EN(0);
-                                       lcdc_msk_reg(lcdc_dev, SYS_CTRL,
-                                                    mask, val);
-                                       break;
-                               case 1:
-                                       mask =  m_WIN1_EN;
-                                       val  =  v_WIN1_EN(0);
-                                       lcdc_msk_reg(lcdc_dev, SYS_CTRL,
-                                                    mask, val);
-                                       break;
-                               case 2:
-                                       mask =  m_HWC_EN;
-                                       val  =  v_HWC_EN(0);
-                                       lcdc_msk_reg(lcdc_dev, SYS_CTRL,
-                                                    mask, val);
-                                       break;
-                               default:
-                                       break;
-                               }
-                       }
+                       if ((win->state == 0) && (win->last_state == 1))
+                               lcdc_layer_update_regs(lcdc_dev, win);
                        win->last_state = win->state;
                }
                lcdc_cfg_done(lcdc_dev);
@@ -1460,14 +1445,14 @@ static int rk3036_lcdc_poll_vblank(struct rk_lcdc_driver *dev_drv)
 }
 
 static int rk3036_lcdc_get_dsp_addr(struct rk_lcdc_driver *dev_drv,
-                                   unsigned int *dsp_addr)
+                                   unsigned int dsp_addr[][4])
 {
        struct lcdc_device *lcdc_dev =
            container_of(dev_drv, struct lcdc_device, driver);
 
        if (lcdc_dev->clk_on) {
-               dsp_addr[0] = lcdc_readl(lcdc_dev, WIN0_YRGB_MST);
-               dsp_addr[1] = lcdc_readl(lcdc_dev, WIN1_MST);
+               dsp_addr[0][0] = lcdc_readl(lcdc_dev, WIN0_YRGB_MST);
+               dsp_addr[1][0] = lcdc_readl(lcdc_dev, WIN1_MST);
        }
        return 0;
 }
@@ -1487,7 +1472,7 @@ static ssize_t rk3036_lcdc_get_disp_info(struct rk_lcdc_driver *dev_drv,
        }
 
        size = snprintf(buf, PAGE_SIZE, "win%d: %s\n", win_id,
-                       get_format_string(win->format, fmt));
+                       get_format_string(win->area[0].format, fmt));
        size += snprintf(buf + size, PAGE_SIZE - size,
                         "      xact %d yact %d xvir %d yvir %d\n",
                win->area[0].xact, win->area[0].yact,
@@ -1560,14 +1545,10 @@ static int rk3036_lcdc_parse_dt(struct lcdc_device *lcdc_dev)
        struct device_node *np = lcdc_dev->dev->of_node;
        int val;
 
-#if defined(CONFIG_ROCKCHIP_IOMMU)
        if (of_property_read_u32(np, "rockchip,iommu-enabled", &val))
                lcdc_dev->driver.iommu_enabled = 0;
        else
                lcdc_dev->driver.iommu_enabled = val;
-#else
-       lcdc_dev->driver.iommu_enabled = 0;
-#endif
        if (of_property_read_u32(np, "rockchip,fb-win-map", &val))
                lcdc_dev->driver.fb_win_map = FB_DEFAULT_ORDER;
        else