Merge branch develop-3.10
[firefly-linux-kernel-4.4.55.git] / drivers / video / rockchip / rk_fb.c
index 6b9d8082d590d92a376158a2070889e69e463c18..8f3afff60d239943cca9d9630c6df1268c935fbf 100755 (executable)
@@ -451,6 +451,7 @@ int rk_fb_video_mode_from_timing(const struct display_timing *dt,
        screen->face = dt->face;
        screen->color_mode = dt->color_mode;
        screen->dsp_lut = dt->dsp_lut;
+       screen->cabc_lut = dt->cabc_lut;
 
        if (dt->flags & DISPLAY_FLAGS_PIXDATA_POSEDGE)
                screen->pin_dclk = 1;
@@ -1320,7 +1321,8 @@ static int rk_fb_pan_display(struct fb_var_screeninfo *var,
        }
 
        /* x y mirror ,jump line */
-       if (screen->y_mirror == 1) {
+       if ((screen->y_mirror == 1) ||
+           (win->mirror_en == 1)) {
                if (screen->interlace == 1) {
                        win->area[0].y_offset = yoffset * stride * 2 +
                            ((win->area[0].yact - 1) * 2 + 1) * stride +
@@ -1340,7 +1342,8 @@ static int rk_fb_pan_display(struct fb_var_screeninfo *var,
                }
        }
        if (is_pic_yuv == 1) {
-               if (screen->y_mirror == 1) {
+               if ((screen->y_mirror == 1) ||
+                   (win->mirror_en == 1)) {
                        if (screen->interlace == 1) {
                                win->area[0].c_offset =
                                    uv_y_off * uv_stride * 2 +
@@ -1375,7 +1378,9 @@ static int rk_fb_pan_display(struct fb_var_screeninfo *var,
        if (video_data_to_mirroring)
                video_data_to_mirroring(info, NULL);
 #endif
-       dev_drv->ops->cfg_done(dev_drv);
+        /*if not want the config effect,set reserved[3] bit[0] 1*/
+        if (likely((var->reserved[3] & 0x1) == 0))
+               dev_drv->ops->cfg_done(dev_drv);
 
        return 0;
 }
@@ -1555,6 +1560,7 @@ static void rk_fb_update_win(struct rk_lcdc_driver *dev_drv,
                                win->area[i].smem_start =
                                        reg_win_data->reg_area_data[i].smem_start;
                                 if (inf->disp_mode == DUAL ||
+                                    inf->disp_mode == NO_DUAL ||
                                     inf->disp_policy == DISPLAY_POLICY_BOX) {
                                        win->area[i].xpos =
                                                reg_win_data->reg_area_data[i].xpos;
@@ -1830,7 +1836,8 @@ static int rk_fb_set_win_buffer(struct fb_info *info,
        struct fb_fix_screeninfo *fix = &info->fix;
        struct rk_fb_par *fb_par = (struct rk_fb_par *)info->par;
        struct rk_lcdc_driver *dev_drv = fb_par->lcdc_drv;
-       struct rk_screen *screen = dev_drv->cur_screen;
+       /*if hdmi size move to hwc,screen should point to cur_screen*/
+       struct rk_screen *screen = dev_drv->screen0;/*cur_screen;*/
        struct fb_info *fbi;
        int i, ion_fd, acq_fence_fd;
        u32 xvir, yvir;
@@ -2872,51 +2879,6 @@ static int rk_fb_set_par(struct fb_info *info)
                break;
        }
 
-       /* x y mirror ,jump line */
-       if (screen->y_mirror == 1) {
-               if (screen->interlace == 1) {
-                       win->area[0].y_offset = yoffset * stride * 2 +
-                           ((win->area[0].yact - 1) * 2 + 1) * stride +
-                           xoffset * pixel_width / 8;
-               } else {
-                       win->area[0].y_offset = yoffset * stride +
-                           (win->area[0].yact - 1) * stride +
-                           xoffset * pixel_width / 8;
-               }
-       } else {
-               if (screen->interlace == 1) {
-                       win->area[0].y_offset =
-                           yoffset * stride * 2 + xoffset * pixel_width / 8;
-               } else {
-                       win->area[0].y_offset =
-                           yoffset * stride + xoffset * pixel_width / 8;
-               }
-       }
-       if (is_pic_yuv == 1) {
-               if (screen->y_mirror == 1) {
-                       if (screen->interlace == 1) {
-                               win->area[0].c_offset =
-                                   uv_y_off * uv_stride * 2 +
-                                   ((uv_y_act - 1) * 2 + 1) * uv_stride +
-                                   uv_x_off * pixel_width / 8;
-                       } else {
-                               win->area[0].c_offset = uv_y_off * uv_stride +
-                                   (uv_y_act - 1) * uv_stride +
-                                   uv_x_off * pixel_width / 8;
-                       }
-               } else {
-                       if (screen->interlace == 1) {
-                               win->area[0].c_offset =
-                                   uv_y_off * uv_stride * 2 +
-                                   uv_x_off * pixel_width / 8;
-                       } else {
-                               win->area[0].c_offset =
-                                   uv_y_off * uv_stride +
-                                   uv_x_off * pixel_width / 8;
-                       }
-               }
-       }
-
        win->area[0].format = fb_data_fmt;
        win->area[0].y_vir_stride = stride >> 2;
        win->area[0].uv_vir_stride = uv_stride >> 2;
@@ -3013,6 +2975,7 @@ static struct fb_ops fb_ops = {
        .fb_set_par = rk_fb_set_par,
        .fb_blank = rk_fb_blank,
        .fb_ioctl = rk_fb_ioctl,
+       .fb_compat_ioctl = rk_fb_ioctl,
        .fb_pan_display = rk_fb_pan_display,
        .fb_read = rk_fb_read,
        .fb_write = rk_fb_write,
@@ -3176,11 +3139,17 @@ int rk_fb_switch_screen(struct rk_screen *screen, int enable, int lcdc_id)
        if (enable == 2 /*&& dev_drv->enable*/)
                return 0;
 
-       if (rk_fb->disp_mode == ONE_DUAL) {
+       if ((rk_fb->disp_mode == ONE_DUAL) ||
+           (rk_fb->disp_mode == NO_DUAL)) {
+               if ((dev_drv->ops->backlight_close) &&
+                   (rk_fb->disp_policy != DISPLAY_POLICY_BOX))
+                       dev_drv->ops->backlight_close(dev_drv, 1);
                if (dev_drv->ops->dsp_black)
                        dev_drv->ops->dsp_black(dev_drv, 1);
-               if (dev_drv->ops->set_screen_scaler)
-                       dev_drv->ops->set_screen_scaler(dev_drv, dev_drv->screen0, 0);
+               if ((dev_drv->ops->set_screen_scaler) &&
+                   (rk_fb->disp_policy != DISPLAY_POLICY_BOX))
+                       dev_drv->ops->set_screen_scaler(dev_drv,
+                                                       dev_drv->screen0, 0);
        }
        if (dev_drv->uboot_logo && (screen->type != dev_drv->cur_screen->type))
                dev_drv->uboot_logo = 0;
@@ -3190,7 +3159,8 @@ int rk_fb_switch_screen(struct rk_screen *screen, int enable, int lcdc_id)
                        return 0;
 
                /* if used one lcdc to dual disp, no need to close win */
-               if (rk_fb->disp_mode == ONE_DUAL) {
+               if ((rk_fb->disp_mode == ONE_DUAL) ||
+                   (rk_fb->disp_mode == NO_DUAL)) {
                        dev_drv->cur_screen = dev_drv->screen0;
                        dev_drv->ops->load_screen(dev_drv, 1);
 
@@ -3207,6 +3177,9 @@ int rk_fb_switch_screen(struct rk_screen *screen, int enable, int lcdc_id)
 
                        if (dev_drv->ops->dsp_black)
                                dev_drv->ops->dsp_black(dev_drv, 0);
+                       if ((dev_drv->ops->backlight_close) &&
+                           (rk_fb->disp_policy != DISPLAY_POLICY_BOX))
+                               dev_drv->ops->backlight_close(dev_drv, 0);
                } else if (rk_fb->num_lcdc > 1) {
                        /* If there is more than one lcdc device, we disable
                           the layer which attached to this device */
@@ -3223,6 +3196,7 @@ int rk_fb_switch_screen(struct rk_screen *screen, int enable, int lcdc_id)
        } else {
                if (dev_drv->screen1)
                        dev_drv->cur_screen = dev_drv->screen1;
+
                memcpy(dev_drv->cur_screen, screen, sizeof(struct rk_screen));
                dev_drv->cur_screen->xsize = dev_drv->cur_screen->mode.xres;
                dev_drv->cur_screen->ysize = dev_drv->cur_screen->mode.yres;
@@ -3264,11 +3238,16 @@ int rk_fb_switch_screen(struct rk_screen *screen, int enable, int lcdc_id)
                dev_drv->uboot_logo = 0;
        }
        hdmi_switch_complete = 1;
-       if (rk_fb->disp_mode == ONE_DUAL) {
-               if (dev_drv->ops->set_screen_scaler)
+       if ((rk_fb->disp_mode == ONE_DUAL) || (rk_fb->disp_mode == NO_DUAL)) {
+               if ((dev_drv->ops->set_screen_scaler) &&
+                   (rk_fb->disp_policy != DISPLAY_POLICY_BOX))
                        dev_drv->ops->set_screen_scaler(dev_drv, dev_drv->screen0, 1);
                if (dev_drv->ops->dsp_black)
                        dev_drv->ops->dsp_black(dev_drv, 0);
+               if ((dev_drv->ops->backlight_close) &&
+                   (rk_fb->disp_policy != DISPLAY_POLICY_BOX) &&
+                   (rk_fb->disp_mode == ONE_DUAL))
+                       dev_drv->ops->backlight_close(dev_drv, 0);
        }
        return 0;
 }
@@ -3525,7 +3504,7 @@ static int init_lcdc_device_driver(struct rk_fb *rk_fb,
        dev_drv->screen0 = screen;
        dev_drv->cur_screen = screen;
        /* devie use one lcdc + rk61x scaler for dual display */
-       if (rk_fb->disp_mode == ONE_DUAL) {
+       if ((rk_fb->disp_mode == ONE_DUAL) || (rk_fb->disp_mode == NO_DUAL)) {
                struct rk_screen *screen1 =
                                devm_kzalloc(dev_drv->dev,
                                             sizeof(struct rk_screen),
@@ -3766,8 +3745,9 @@ int rk_fb_register(struct rk_lcdc_driver *dev_drv,
                        vaddr = vmap(pages, nr_pages, VM_MAP,
                                        pgprot_writecombine(PAGE_KERNEL));
                        if (!vaddr) {
-                               pr_err("failed to vmap phy addr %x\n",
-                                       uboot_logo_base + uboot_logo_offset);
+                               pr_err("failed to vmap phy addr 0x%lx\n",
+                                      (long)(uboot_logo_base +
+                                      uboot_logo_offset));
                                return -1;
                        }
 
@@ -3801,7 +3781,7 @@ int rk_fb_register(struct rk_lcdc_driver *dev_drv,
 
                        return 0;
                } else if (dev_drv->uboot_logo && uboot_logo_base) {
-                       phys_addr_t start = uboot_logo_base;
+                       u32 start = uboot_logo_base;
                        int logo_len, i=0;
                        unsigned int nr_pages;
                        struct page **pages;
@@ -3828,8 +3808,8 @@ int rk_fb_register(struct rk_lcdc_driver *dev_drv,
                        vaddr = vmap(pages, nr_pages, VM_MAP,
                                        pgprot_writecombine(PAGE_KERNEL));
                        if (!vaddr) {
-                               pr_err("failed to vmap phy addr %x\n",
-                                       uboot_logo_base);
+                               pr_err("failed to vmap phy addr 0x%llx\n",
+                                      uboot_logo_base);
                                return -1;
                        }
 
@@ -3849,6 +3829,12 @@ int rk_fb_register(struct rk_lcdc_driver *dev_drv,
                                freed_index = 0;
                        }
                        return 0;
+               } else {
+                       if (dev_drv->iommu_enabled) {
+                               if (dev_drv->ops->mmu_en)
+                                       dev_drv->ops->mmu_en(dev_drv);
+                               freed_index = 0;
+                       }
                }
 #if defined(CONFIG_LOGO)
                main_fbi->fbops->fb_set_par(main_fbi);