video: rockchip: vop: 3399: add win lite supprt afbdc abgr format
[firefly-linux-kernel-4.4.55.git] / drivers / video / rockchip / lcdc / rk322x_lcdc.c
index cb7a4cf8e2b31a4640138ea9307d65da80071a1c..52421aa868356d4dfdd169e0857c671eae90d916 100644 (file)
@@ -383,7 +383,7 @@ static int vop_clk_disable(struct vop_device *vop_dev)
                spin_unlock(&vop_dev->reg_lock);
                mdelay(25);
 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0))
-               pm_runtime_put(vop_dev->dev);
+               pm_runtime_put_sync(vop_dev->dev);
 #endif
                clk_disable_unprepare(vop_dev->dclk);
                clk_disable_unprepare(vop_dev->hclk);
@@ -473,6 +473,8 @@ static int vop_win_direct_en(struct rk_lcdc_driver *drv,
 {
        struct vop_device *vop_dev =
            container_of(drv, struct vop_device, driver);
+
+       drv->win[win_id]->state = en;
        if (win_id == 0)
                win0_enable(vop_dev, en);
        else if (win_id == 1)
@@ -856,7 +858,7 @@ static int vop_post_csc_cfg(struct rk_lcdc_driver *dev_drv)
        struct vop_device *vop_dev =
            container_of(dev_drv, struct vop_device, driver);
        int output_color = dev_drv->output_color;
-       int win_csc, overlay_mode;
+       int win_csc = 0, overlay_mode = 0;
        u64 val;
 
        if (VOP_CHIP(vop_dev) == VOP_RK322X) {
@@ -1095,9 +1097,10 @@ static int vop_alpha_cfg(struct rk_lcdc_driver *dev_drv, int win_id)
        struct alpha_config alpha_config;
        u64 val;
        int ppixel_alpha = 0, global_alpha = 0, i;
-       u32 src_alpha_ctl, dst_alpha_ctl;
+       u32 src_alpha_ctl = 0, dst_alpha_ctl = 0;
        int alpha_en = 1;
 
+       memset(&alpha_config, 0, sizeof(struct alpha_config));
        for (i = 0; i < win->area_num; i++) {
                ppixel_alpha |= ((win->area[i].format == ARGB888) ||
                                 (win->area[i].format == FBDC_ARGB_888) ||
@@ -1336,10 +1339,10 @@ static int vop_init_fbdc_config(struct vop_device *vop_dev, int win_id)
                return 0;
        }
 
-       win->area[0].fbdc_mb_width = win->area[0].xact;
+       win->area[0].fbdc_mb_width = win->area[0].xvir;
        win->area[0].fbdc_mb_height = win->area[0].yact;
        win->area[0].fbdc_cor_en = 0; /* hreg_block_split */
-       win->area[0].fbdc_fmt_cfg |= 0 << 4;
+       win->area[0].fbdc_fmt_cfg |= AFBDC_YUV_COLOR_TRANSFORM << 4;
 
        return 0;
 }
@@ -1452,13 +1455,6 @@ static int vop_win_0_1_reg_update(struct rk_lcdc_driver *dev_drv, int win_id)
                val = V_WIN0_HS_FACTOR_CBR(win->scale_cbcr_x) |
                    V_WIN0_VS_FACTOR_CBR(win->scale_cbcr_y);
                vop_writel(vop_dev, WIN0_SCL_FACTOR_CBR + off, val);
-               if (win->alpha_en == 1) {
-                       vop_alpha_cfg(dev_drv, win_id);
-               } else {
-                       val = V_WIN0_SRC_ALPHA_EN(0);
-                       vop_msk_reg(vop_dev, WIN0_SRC_ALPHA_CTRL + off, val);
-               }
-
        } else {
                val = V_WIN0_EN(win->state);
                vop_msk_reg(vop_dev, WIN0_CTRL0 + off, val);
@@ -1592,13 +1588,6 @@ static int vop_win_2_3_reg_update(struct rk_lcdc_driver *dev_drv, int win_id)
                        val = V_WIN2_MST3_EN(0);
                        vop_msk_reg(vop_dev, WIN2_CTRL0 + off, val);
                }
-
-               if (win->alpha_en == 1) {
-                       vop_alpha_cfg(dev_drv, win_id);
-               } else {
-                       val = V_WIN2_SRC_ALPHA_EN(0);
-                       vop_msk_reg(vop_dev, WIN2_SRC_ALPHA_CTRL + off, val);
-               }
        } else {
                val = V_WIN2_EN(win->state) | V_WIN2_MST0_EN(0) |
                    V_WIN2_MST1_EN(0) | V_WIN2_MST2_EN(0) | V_WIN2_MST3_EN(0);
@@ -1643,13 +1632,6 @@ static int vop_hwc_reg_update(struct rk_lcdc_driver *dev_drv, int win_id)
                val = V_HWC_DSP_XST(win->area[0].dsp_stx) |
                    V_HWC_DSP_YST(win->area[0].dsp_sty);
                vop_msk_reg(vop_dev, HWC_DSP_ST, val);
-
-               if (win->alpha_en == 1) {
-                       vop_alpha_cfg(dev_drv, win_id);
-               } else {
-                       val = V_WIN2_SRC_ALPHA_EN(0);
-                       vop_msk_reg(vop_dev, HWC_SRC_ALPHA_CTRL, val);
-               }
        } else {
                val = V_HWC_EN(win->state);
                vop_msk_reg(vop_dev, HWC_CTRL0, val);
@@ -1807,6 +1789,10 @@ static int vop_config_timing(struct rk_lcdc_driver *dev_drv)
                vop_msk_reg(vop_dev, LINE_FLAG, val);
        }
        vop_post_cfg(dev_drv);
+       if ((x_res <= VOP_INPUT_MAX_WIDTH / 2) && (vop_dev->id == 0))
+               vop_msk_reg(vop_dev, SYS_CTRL, V_POST_LB_MODE(1));
+       else
+               vop_msk_reg(vop_dev, SYS_CTRL, V_POST_LB_MODE(0));
 
        return 0;
 }
@@ -1915,7 +1901,7 @@ static int vop_load_screen(struct rk_lcdc_driver *dev_drv, bool initscreen)
        struct vop_device *vop_dev =
            container_of(dev_drv, struct vop_device, driver);
        struct rk_screen *screen = dev_drv->cur_screen;
-       u64 val;
+       u64 val = 0;
 
        if (unlikely(!vop_dev->clk_on)) {
                pr_info("%s,clk_on = %d\n", __func__, vop_dev->clk_on);
@@ -1974,6 +1960,20 @@ static int vop_load_screen(struct rk_lcdc_driver *dev_drv, bool initscreen)
                                V_DITHER_DOWN_SEL(0) |
                                V_DITHER_DOWN_MODE(0);
                        break;
+               case OUT_YUV_422:
+                       face = OUT_YUV_422;
+                       val = V_DITHER_DOWN_EN(0) | V_DITHER_UP_EN(1) |
+                               V_PRE_DITHER_DOWN_EN(1) |
+                               V_DITHER_DOWN_SEL(0) |
+                               V_DITHER_DOWN_MODE(0);
+                       break;
+               case OUT_YUV_422_10BIT:
+                       face = OUT_YUV_422;
+                       val = V_DITHER_DOWN_EN(0) | V_DITHER_UP_EN(1) |
+                               V_PRE_DITHER_DOWN_EN(0) |
+                               V_DITHER_DOWN_SEL(0) |
+                               V_DITHER_DOWN_MODE(0);
+                       break;
                case OUT_P101010:
                        face = OUT_P101010;
                        val = V_DITHER_DOWN_EN(0) | V_DITHER_UP_EN(1) |
@@ -2012,6 +2012,12 @@ static int vop_load_screen(struct rk_lcdc_driver *dev_drv, bool initscreen)
                        }
                        val = V_HDMI_OUT_EN(1) | V_SW_UV_OFFSET_EN(0);
                        vop_msk_reg(vop_dev, SYS_CTRL, val);
+                       val = V_HDMI_HSYNC_POL(screen->pin_hsync) |
+                               V_HDMI_VSYNC_POL(screen->pin_vsync) |
+                               V_HDMI_DEN_POL(screen->pin_den) |
+                               V_HDMI_DCLK_POL(screen->pin_dclk);
+                       /*hsync vsync den dclk polo,dither */
+                       vop_msk_reg(vop_dev, DSP_CTRL1, val);
                        break;
                case SCREEN_RGB:
                case SCREEN_LVDS:
@@ -2021,10 +2027,22 @@ static int vop_load_screen(struct rk_lcdc_driver *dev_drv, bool initscreen)
                case SCREEN_MIPI:
                        val = V_MIPI_OUT_EN(1);
                        vop_msk_reg(vop_dev, SYS_CTRL, val);
+                       val = V_MIPI_HSYNC_POL(screen->pin_hsync) |
+                               V_MIPI_VSYNC_POL(screen->pin_vsync) |
+                               V_MIPI_DEN_POL(screen->pin_den) |
+                               V_MIPI_DCLK_POL(screen->pin_dclk);
+                       /*hsync vsync den dclk polo,dither */
+                       vop_msk_reg(vop_dev, DSP_CTRL1, val);
                        break;
                case SCREEN_DUAL_MIPI:
                        val = V_MIPI_OUT_EN(1) | V_MIPI_DUAL_CHANNEL_EN(1);
                        vop_msk_reg(vop_dev, SYS_CTRL, val);
+                       val = V_MIPI_HSYNC_POL(screen->pin_hsync) |
+                               V_MIPI_VSYNC_POL(screen->pin_vsync) |
+                               V_MIPI_DEN_POL(screen->pin_den) |
+                               V_MIPI_DCLK_POL(screen->pin_dclk);
+                       /*hsync vsync den dclk polo,dither */
+                       vop_msk_reg(vop_dev, DSP_CTRL1, val);
                        break;
                case SCREEN_EDP:
                        if ((VOP_CHIP(vop_dev) == VOP_RK3399) &&
@@ -2032,18 +2050,37 @@ static int vop_load_screen(struct rk_lcdc_driver *dev_drv, bool initscreen)
                                face = OUT_P101010;
                        val = V_EDP_OUT_EN(1);
                        vop_msk_reg(vop_dev, SYS_CTRL, val);
+                       val = V_EDP_HSYNC_POL(screen->pin_hsync) |
+                               V_EDP_VSYNC_POL(screen->pin_vsync) |
+                               V_EDP_DEN_POL(screen->pin_den) |
+                               V_EDP_DCLK_POL(screen->pin_dclk);
+                       /*hsync vsync den dclk polo,dither */
+                       vop_msk_reg(vop_dev, DSP_CTRL1, val);
+                       break;
+               case SCREEN_DP:
+                       dclk_ddr = 0;
+                       if ((VOP_CHIP(vop_dev) == VOP_RK3399) &&
+                           ((screen->face == OUT_P888) ||
+                            (screen->face == OUT_P101010))) {
+                               if (vop_dev->id == 0)
+                                       face = OUT_P101010;
+                               else
+                                       face = OUT_P888;
+                       }
+                       val = V_DP_OUT_EN(1);
+                       vop_msk_reg(vop_dev, SYS_CTRL, val);
+                       val = V_DP_HSYNC_POL(screen->pin_hsync) |
+                               V_DP_VSYNC_POL(screen->pin_vsync) |
+                               V_DP_DEN_POL(screen->pin_den) |
+                               V_DP_DCLK_POL(screen->pin_dclk);
+                       /*hsync vsync den dclk polo,dither */
+                       vop_msk_reg(vop_dev, DSP_CTRL1, val);
                        break;
                default:
                        dev_err(vop_dev->dev, "un supported interface[%d]!\n",
                                screen->type);
                        break;
                }
-               val = V_HDMI_HSYNC_POL(screen->pin_hsync) |
-                       V_HDMI_VSYNC_POL(screen->pin_vsync) |
-                       V_HDMI_DEN_POL(screen->pin_den) |
-                       V_HDMI_DCLK_POL(screen->pin_dclk);
-               /*hsync vsync den dclk polo,dither */
-               vop_msk_reg(vop_dev, DSP_CTRL1, val);
 
                if (screen->color_mode == COLOR_RGB)
                        dev_drv->overlay_mode = VOP_RGB_DOMAIN;
@@ -2108,6 +2145,8 @@ static int vop_load_screen(struct rk_lcdc_driver *dev_drv, bool initscreen)
        return 0;
 }
 
+static int vop_early_suspend(struct rk_lcdc_driver *dev_drv);
+static int vop_early_resume(struct rk_lcdc_driver *dev_drv);
 /*enable layer,open:1,enable;0 disable*/
 static void vop_layer_enable(struct vop_device *vop_dev,
                             unsigned int win_id, bool open)
@@ -2132,14 +2171,21 @@ static void vop_layer_enable(struct vop_device *vop_dev,
                                              vop_dev->driver.win[win_id]);
                        vop_cfg_done(vop_dev);
                }
-               /* if no layer used,disable lcdc */
-               if (!vop_dev->atv_layer_cnt) {
+       }
+       spin_unlock(&vop_dev->reg_lock);
+       /* if no layer used,disable lcdc */
+       if (vop_dev->prop == EXTEND) {
+               if (!vop_dev->atv_layer_cnt && !open) {
+                       vop_early_suspend(&vop_dev->driver);
                        dev_info(vop_dev->dev,
                                 "no layer is used,go to standby!\n");
                        vop_dev->standby = 1;
+               } else if (open) {
+                       vop_early_resume(&vop_dev->driver);
+                       dev_info(vop_dev->dev, "wake up from standby!\n");
                }
        }
-       spin_unlock(&vop_dev->reg_lock);
+
 }
 
 static int vop_enable_irq(struct rk_lcdc_driver *dev_drv)
@@ -2154,8 +2200,9 @@ static int vop_enable_irq(struct rk_lcdc_driver *dev_drv)
        val = INTR_FS | INTR_LINE_FLAG0 | INTR_BUS_ERROR | INTR_LINE_FLAG1 |
                INTR_WIN0_EMPTY | INTR_WIN1_EMPTY | INTR_HWC_EMPTY |
                INTR_POST_BUF_EMPTY;
+       val |= val << 16;
 
-       vop_mask_writel(vop_dev, INTR_EN0, INTR_MASK, val);
+       vop_msk_reg(vop_dev, INTR_EN0, val);
 
        return 0;
 }
@@ -2319,27 +2366,27 @@ static int vop_pan_display(struct rk_lcdc_driver *dev_drv, int win_id)
 
 static int vop_cal_scl_fac(struct rk_lcdc_win *win, struct rk_screen *screen)
 {
-       u16 srcW;
-       u16 srcH;
-       u16 dstW;
-       u16 dstH;
-       u16 yrgb_srcW;
-       u16 yrgb_srcH;
-       u16 yrgb_dstW;
-       u16 yrgb_dstH;
-       u32 yrgb_vscalednmult;
-       u32 yrgb_xscl_factor;
-       u32 yrgb_yscl_factor;
+       u16 srcW = 0;
+       u16 srcH = 0;
+       u16 dstW = 0;
+       u16 dstH = 0;
+       u16 yrgb_srcW = 0;
+       u16 yrgb_srcH = 0;
+       u16 yrgb_dstW = 0;
+       u16 yrgb_dstH = 0;
+       u32 yrgb_vscalednmult = 0;
+       u32 yrgb_xscl_factor = 0;
+       u32 yrgb_yscl_factor = 0;
        u8 yrgb_vsd_bil_gt2 = 0;
        u8 yrgb_vsd_bil_gt4 = 0;
 
-       u16 cbcr_srcW;
-       u16 cbcr_srcH;
-       u16 cbcr_dstW;
-       u16 cbcr_dstH;
-       u32 cbcr_vscalednmult;
-       u32 cbcr_xscl_factor;
-       u32 cbcr_yscl_factor;
+       u16 cbcr_srcW = 0;
+       u16 cbcr_srcH = 0;
+       u16 cbcr_dstW = 0;
+       u16 cbcr_dstH = 0;
+       u32 cbcr_vscalednmult = 0;
+       u32 cbcr_xscl_factor = 0;
+       u32 cbcr_yscl_factor = 0;
        u8 cbcr_vsd_bil_gt2 = 0;
        u8 cbcr_vsd_bil_gt4 = 0;
        u8 yuv_fmt = 0;
@@ -2854,8 +2901,8 @@ static int dsp_y_pos(int mirror_en, struct rk_screen *screen,
 static int win_0_1_set_par(struct vop_device *vop_dev,
                           struct rk_screen *screen, struct rk_lcdc_win *win)
 {
-       u32 xact, yact, xvir, yvir, xpos, ypos;
-       u8 fmt_cfg = 0, swap_rb, swap_uv = 0;
+       u32 xact = 0, yact = 0, xvir = 0, yvir = 0, xpos = 0, ypos = 0;
+       u8 fmt_cfg = 0, swap_rb = 0, swap_uv = 0;
        char fmt[9] = "NULL";
 
        xpos = dsp_x_pos(win->xmirror, screen, &win->area[0]);
@@ -3008,7 +3055,7 @@ static int win_2_3_set_par(struct vop_device *vop_dev,
                           struct rk_screen *screen, struct rk_lcdc_win *win)
 {
        int i;
-       u8 fmt_cfg, swap_rb;
+       u8 fmt_cfg = 0, swap_rb = 0;
        char fmt[9] = "NULL";
 
        if (VOP_CHIP(vop_dev) == VOP_RK322X) {
@@ -3028,19 +3075,25 @@ static int win_2_3_set_par(struct vop_device *vop_dev,
                                fmt_cfg = 2;
                                swap_rb = 0;
                                win->fmt_10 = 0;
-                               win->area[0].fbdc_fmt_cfg = 0x05;
+                               win->area[0].fbdc_fmt_cfg = AFBDC_FMT_RGB565;
                                break;
                        case FBDC_ARGB_888:
+                               fmt_cfg = 0;
+                               swap_rb = 1;
+                               win->fmt_10 = 0;
+                               win->area[0].fbdc_fmt_cfg = AFBDC_FMT_U8U8U8U8;
+                               break;
+                       case FBDC_ABGR_888:
                                fmt_cfg = 0;
                                swap_rb = 0;
                                win->fmt_10 = 0;
-                               win->area[0].fbdc_fmt_cfg = 0x0c;
+                               win->area[0].fbdc_fmt_cfg = AFBDC_FMT_U8U8U8U8;
                                break;
                        case FBDC_RGBX_888:
                                fmt_cfg = 0;
                                swap_rb = 0;
                                win->fmt_10 = 0;
-                               win->area[0].fbdc_fmt_cfg = 0x3a;
+                               win->area[0].fbdc_fmt_cfg = AFBDC_FMT_U8U8U8U8;
                                break;
                        case ARGB888:
                                fmt_cfg = 0;
@@ -3098,8 +3151,8 @@ static int win_2_3_set_par(struct vop_device *vop_dev,
 static int hwc_set_par(struct vop_device *vop_dev,
                       struct rk_screen *screen, struct rk_lcdc_win *win)
 {
-       u32 xact, yact, xvir, yvir, xpos, ypos;
-       u8 fmt_cfg = 0, swap_rb;
+       u32 xact = 0, yact = 0, xvir = 0, yvir = 0, xpos = 0, ypos = 0;
+       u8 fmt_cfg = 0, swap_rb = 0;
        char fmt[9] = "NULL";
 
        xpos = win->area[0].xpos + screen->mode.left_margin +
@@ -3524,10 +3577,10 @@ static int vop_ovl_mgr(struct rk_lcdc_driver *dev_drv, int swap, bool set)
        struct vop_device *vop_dev =
            container_of(dev_drv, struct vop_device, driver);
        struct rk_lcdc_win *win = NULL;
-       int i, ovl;
+       int i, ovl = 0;
        u64 val;
        int z_order_num = 0;
-       int layer0_sel, layer1_sel, layer2_sel, layer3_sel;
+       int layer0_sel = 0, layer1_sel = 1, layer2_sel = 2, layer3_sel = 3;
 
        if (swap == 0) {
                for (i = 0; i < dev_drv->lcdc_win_num; i++) {
@@ -3871,7 +3924,7 @@ static ssize_t vop_get_disp_info(struct rk_lcdc_driver *dev_drv,
        spin_unlock(&vop_dev->reg_lock);
        size += snprintf(dsp_buf, 80,
                "z-order:\n  win[%d]\n  win[%d]\n  win[%d]\n  win[%d]\n",
-               layer1_sel, layer0_sel, layer2_sel, layer3_sel);
+               layer3_sel, layer2_sel, layer1_sel, layer0_sel);
        strcat(buf, dsp_buf);
        memset(dsp_buf, 0, sizeof(dsp_buf));
        /* win0 */
@@ -4134,7 +4187,10 @@ static int vop_config_done(struct rk_lcdc_driver *dev_drv)
        vop_msk_reg(vop_dev, SYS_CTRL, V_VOP_STANDBY_EN(vop_dev->standby));
        for (i = 0; i < dev_drv->lcdc_win_num; i++) {
                win = dev_drv->win[i];
+               vop_alpha_cfg(dev_drv, i);
                fbdc_en |= win->area[0].fbdc_en;
+               vop_dev->atv_layer_cnt &= ~(1 << win->id);
+               vop_dev->atv_layer_cnt |= (win->state << win->id);
                if ((win->state == 0) && (win->last_state == 1)) {
                        switch (win->id) {
                        case 0:
@@ -4217,7 +4273,7 @@ static int vop_set_irq_to_cpu(struct rk_lcdc_driver *dev_drv, int enable)
        if (enable)
                enable_irq(vop_dev->irq);
        else
-               disable_irq(vop_dev->irq);
+               disable_irq_nosync(vop_dev->irq);
        return 0;
 }
 
@@ -4296,7 +4352,7 @@ static int vop_get_bcsh_hue(struct rk_lcdc_driver *dev_drv, bcsh_hue_mode mode)
 {
        struct vop_device *vop_dev =
            container_of(dev_drv, struct vop_device, driver);
-       u32 val;
+       u32 val = 0;
 
        spin_lock(&vop_dev->reg_lock);
        if (vop_dev->clk_on) {
@@ -4410,7 +4466,7 @@ static int vop_set_bcsh_bcs(struct rk_lcdc_driver *dev_drv,
 {
        struct vop_device *vop_dev =
            container_of(dev_drv, struct vop_device, driver);
-       u64 val;
+       u64 val = 0;
 
        spin_lock(&vop_dev->reg_lock);
        if (vop_dev->clk_on) {
@@ -4446,7 +4502,7 @@ static int vop_get_bcsh_bcs(struct rk_lcdc_driver *dev_drv, bcsh_bcs_mode mode)
 {
        struct vop_device *vop_dev =
            container_of(dev_drv, struct vop_device, driver);
-       u64 val;
+       u64 val = 0;
 
        spin_lock(&vop_dev->reg_lock);
        if (vop_dev->clk_on) {