video: rockchip: vop: 3399: update for CABC
[firefly-linux-kernel-4.4.55.git] / drivers / video / rockchip / lcdc / rk322x_lcdc.c
index e8f03f882094697afe88c24b27e6b3a5c2690a04..9e321afce5ad18d289e564eb616b367b5f3b8cc9 100644 (file)
@@ -49,17 +49,65 @@ module_param(dbg_thresd, int, S_IRUGO | S_IWUSR);
        } while (0)
 
 static struct rk_lcdc_win rk322x_vop_win[] = {
-       { .name = "win0", .id = VOP_WIN0},
-       { .name = "win1", .id = VOP_WIN1},
-       { .name = "hwc",  .id = VOP_HWC}
+       { .name = "win0",
+         .id = VOP_WIN0,
+         .property.feature = SUPPORT_WIN_IDENTIFY | SUPPORT_HW_EXIST |
+                               SUPPORT_SCALE | SUPPORT_YUV |
+                               SUPPORT_YUV10BIT,
+         .property.max_input_x = 4096,
+         .property.max_input_y = 2304},
+       { .name = "win1",
+         .id = VOP_WIN1,
+         .property.feature = SUPPORT_WIN_IDENTIFY | SUPPORT_HW_EXIST |
+                               SUPPORT_SCALE | SUPPORT_YUV |
+                               SUPPORT_YUV10BIT,
+         .property.max_input_x = 4096,
+         .property.max_input_y = 2304},
+       {
+         .name = "hwc",
+         .id = VOP_HWC,
+         .property.feature = SUPPORT_WIN_IDENTIFY | SUPPORT_HW_EXIST |
+                               SUPPORT_HWC_LAYER,
+         .property.max_input_x = 128,
+         .property.max_input_y = 128
+       }
 };
 
 static struct rk_lcdc_win rk3399_vop_win[] = {
-       { .name = "win0", .id = VOP_WIN0},
-       { .name = "win1", .id = VOP_WIN1},
-       { .name = "win2", .id = VOP_WIN2},
-       { .name = "win3", .id = VOP_WIN3},
-       { .name = "hwc",  .id = VOP_HWC}
+       { .name = "win0",
+         .id = VOP_WIN0,
+         .property.feature = SUPPORT_WIN_IDENTIFY | SUPPORT_HW_EXIST |
+                               SUPPORT_SCALE | SUPPORT_YUV |
+                               SUPPORT_YUV10BIT,
+         .property.max_input_x = 4096,
+         .property.max_input_y = 2304},
+       { .name = "win1",
+         .id = VOP_WIN1,
+         .property.feature = SUPPORT_WIN_IDENTIFY | SUPPORT_HW_EXIST |
+                               SUPPORT_SCALE | SUPPORT_YUV |
+                               SUPPORT_YUV10BIT,
+         .property.max_input_x = 4096,
+         .property.max_input_y = 2304},
+       { .name = "win2",
+         .id = VOP_WIN2,
+         .property.feature = SUPPORT_WIN_IDENTIFY | SUPPORT_HW_EXIST |
+                               SUPPORT_MULTI_AREA,
+         .property.max_input_x = 4096,
+         .property.max_input_y = 2304},
+       { .name = "win3",
+         .id = VOP_WIN3,
+         .property.feature = SUPPORT_WIN_IDENTIFY | SUPPORT_HW_EXIST |
+                               SUPPORT_MULTI_AREA,
+         .property.max_input_x = 4096,
+         .property.max_input_y = 2304},
+       {
+         .name = "hwc",
+         .id = VOP_HWC,
+         .property.feature = SUPPORT_WIN_IDENTIFY | SUPPORT_HW_EXIST |
+                               SUPPORT_HWC_LAYER,
+         .property.max_input_x = 128,
+         .property.max_input_y = 128
+       }
 };
 
 static const struct vop_data rk322x_data = {
@@ -656,36 +704,36 @@ static int rk3399_vop_win_csc_cfg(struct rk_lcdc_driver *dev_drv)
                        } else if (win->colorspace == CSC_BT2020) {
                                val |= V_WIN0_YUV2YUV_EN(1);
                                LOAD_CSC(vop_dev, Y2R, csc_y2r_bt2020, i);
-                               LOAD_CSC(vop_dev, 3x3, csc_r2r_bt2020to709, i);
+                               LOAD_CSC(vop_dev, R2R, csc_r2r_bt2020to709, i);
                        }
                } else if (output_color == COLOR_YCBCR ||
                                output_color == COLOR_YCBCR_BT709) {
                        if (!(IS_YUV(win->area[0].fmt_cfg) ||
                              win->area[0].yuyv_fmt)) {
                                val |= V_WIN0_YUV2YUV_R2Y_EN(1);
-                               LOAD_CSC(vop_dev, R2Y, csc_r2y_bt709_full, i);
+                               LOAD_CSC(vop_dev, R2Y, csc_r2y_bt709_full_10, i);
                        } else if (win->colorspace == CSC_BT2020) {
                                val |= V_WIN0_YUV2YUV_EN(1) |
                                        V_WIN0_YUV2YUV_Y2R_EN(1) |
                                        V_WIN0_YUV2YUV_R2Y_EN(1);
-                               LOAD_CSC(vop_dev, R2Y, csc_y2r_bt2020, i);
-                               LOAD_CSC(vop_dev, R2Y, csc_r2r_bt2020to709, i);
-                               LOAD_CSC(vop_dev, R2Y, csc_r2y_bt709_full, i);
+                               LOAD_CSC(vop_dev, Y2R, csc_y2r_bt2020, i);
+                               LOAD_CSC(vop_dev, R2R, csc_r2r_bt2020to709, i);
+                               LOAD_CSC(vop_dev, R2Y, csc_r2y_bt709_full_10, i);
                        }
                } else if (output_color == COLOR_YCBCR_BT2020) {
                        if (!(IS_YUV(win->area[0].fmt_cfg) ||
                              win->area[0].yuyv_fmt)) {
                                val |= V_WIN0_YUV2YUV_R2Y_EN(1) |
                                        V_WIN0_YUV2YUV_EN(1);
-                               LOAD_CSC(vop_dev, R2Y, csc_r2r_bt709to2020, i);
+                               LOAD_CSC(vop_dev, R2R, csc_r2r_bt709to2020, i);
                                LOAD_CSC(vop_dev, R2Y, csc_r2y_bt2020, i);
                        } else if (win->colorspace == CSC_BT601 ||
                                        win->colorspace == CSC_BT709) {
                                val |= V_WIN0_YUV2YUV_Y2R_EN(1) |
                                        V_WIN0_YUV2YUV_R2Y_EN(1) |
                                        V_WIN0_YUV2YUV_EN(1);
-                               LOAD_CSC(vop_dev, R2Y, csc_y2r_bt709_full, i);
-                               LOAD_CSC(vop_dev, R2Y, csc_r2r_bt709to2020, i);
+                               LOAD_CSC(vop_dev, Y2R, csc_y2r_bt709_full_10, i);
+                               LOAD_CSC(vop_dev, R2R, csc_r2r_bt709to2020, i);
                                LOAD_CSC(vop_dev, R2Y, csc_r2y_bt2020, i);
                        }
                }
@@ -1298,10 +1346,17 @@ static int vop_win_0_1_reg_update(struct rk_lcdc_driver *dev_drv, int win_id)
        u64 val;
        u32 off;
        int format;
+       struct rk_win_property *win_property =
+                               &dev_drv->win[win_id]->property;
 
        off = win_id * 0x40;
 
        if (win->state == 1) {
+               if (!(win_property->feature & SUPPORT_HW_EXIST)) {
+                       pr_err("vop[%d] win[%d] hardware unsupport\n",
+                              vop_dev->id, win_id);
+                       return 0;
+               }
                vop_axi_gather_cfg(vop_dev, win);
                if (win->area[0].fbdc_en)
                        vop_fbdc_reg_update(vop_dev, win_id);
@@ -1434,11 +1489,18 @@ static int vop_win_2_3_reg_update(struct rk_lcdc_driver *dev_drv, int win_id)
        struct rk_lcdc_win *win = dev_drv->win[win_id];
        unsigned int off;
        u64 val;
+       struct rk_win_property *win_property =
+                               &dev_drv->win[win_id]->property;
 
        off = (win_id - 2) * 0x50;
        area_xst(win, win->area_num);
 
        if (win->state == 1) {
+               if (!(win_property->feature & SUPPORT_HW_EXIST)) {
+                       pr_err("vop[%d] win[%d] hardware unsupport\n",
+                              vop_dev->id, win_id);
+                       return 0;
+               }
                vop_axi_gather_cfg(vop_dev, win);
                if (win->area[0].fbdc_en)
                        vop_fbdc_reg_update(vop_dev, win_id);
@@ -1934,6 +1996,9 @@ static int vop_load_screen(struct rk_lcdc_driver *dev_drv, bool initscreen)
                        vop_msk_reg(vop_dev, SYS_CTRL, val);
                        break;
                case SCREEN_HDMI:
+                       if ((screen->face == OUT_P888) ||
+                           (screen->face == OUT_P101010))
+                               face = OUT_P101010; /*RGB 101010 output*/
                        val = V_HDMI_OUT_EN(1) | V_SW_UV_OFFSET_EN(0);
                        vop_msk_reg(vop_dev, SYS_CTRL, val);
                        break;
@@ -3121,6 +3186,8 @@ static int vop_set_writeback(struct rk_lcdc_driver *dev_drv)
                return 0;
        }
        wb_data = &dev_drv->wb_data;
+       if ((wb_data->xsize == 0) || (wb_data->ysize == 0))
+               return 0;
 
        xsize = wb_data->xsize;
        ysize = wb_data->ysize;
@@ -3144,12 +3211,17 @@ static int vop_set_writeback(struct rk_lcdc_driver *dev_drv)
 
        switch (wb_data->data_format) {
        case ARGB888:
+       case ABGR888:
+       case XRGB888:
+       case XBGR888:
                fmt_cfg = 0;
                break;
        case RGB888:
+       case BGR888:
                fmt_cfg = 1;
                break;
        case RGB565:
+       case BGR565:
                fmt_cfg = 2;
                break;
        case YUV420:
@@ -4574,13 +4646,14 @@ static irqreturn_t vop_isr(int irq, void *dev_id)
 
        if (intr_status & INTR_FS) {
                timestamp = ktime_get();
-               if (vop_dev->wb_on) {
+               if (vop_dev->driver.wb_data.state) {
                        u32 wb_status;
 
                        spin_lock_irqsave(&vop_dev->irq_lock, flags);
                        wb_status = vop_read_bit(vop_dev, WB_CTRL0, V_WB_EN(0));
+
                        if (wb_status)
-                               vop_set_bit(vop_dev, WB_CTRL0, V_WB_EN(0));
+                               vop_clr_bit(vop_dev, WB_CTRL0, V_WB_EN(0));
 
                        vop_cfg_done(vop_dev);
                        vop_dev->driver.wb_data.state = 0;
@@ -4740,7 +4813,8 @@ static int vop_probe(struct platform_device *pdev)
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        vop_dev->reg_phy_base = res->start;
        vop_dev->len = resource_size(res);
-       vop_dev->regs = devm_ioremap_resource(dev, res);
+       vop_dev->regs = devm_ioremap(&pdev->dev, res->start,
+                                    resource_size(res));
        if (IS_ERR(vop_dev->regs))
                return PTR_ERR(vop_dev->regs);
 
@@ -4799,6 +4873,18 @@ static int vop_probe(struct platform_device *pdev)
                                       VOPL_IOMMU_COMPATIBLE_NAME);
                }
        }
+       if (VOP_CHIP(vop_dev) == VOP_RK3399)
+               dev_drv->property.feature |= SUPPORT_WRITE_BACK | SUPPORT_AFBDC;
+       dev_drv->property.feature |= SUPPORT_VOP_IDENTIFY |
+                                       SUPPORT_YUV420_OUTPUT;
+       dev_drv->property.max_output_x = 4096;
+       dev_drv->property.max_output_y = 2160;
+
+       if ((VOP_CHIP(vop_dev) == VOP_RK3399) && (vop_dev->id == 1)) {
+               vop_dev->data->win[1].property.feature &= ~SUPPORT_HW_EXIST;
+               vop_dev->data->win[3].property.feature &= ~SUPPORT_HW_EXIST;
+       }
+
        ret = rk_fb_register(dev_drv, vop_dev->data->win, vop_dev->id);
        if (ret < 0) {
                dev_err(dev, "register fb for lcdc%d failed!\n", vop_dev->id);