]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
ENGR00210915 fb: mxc_elcdfb: fix screen flash when use fb_set_var
authorZhang Jiejing <jiejing.zhang@freescale.com>
Fri, 25 May 2012 09:03:02 +0000 (17:03 +0800)
committerLothar Waßmann <LW@KARO-electronics.de>
Fri, 24 May 2013 06:34:44 +0000 (08:34 +0200)
fb_set_var() is used by android default display,
we found the screen will flash using android default
display support, found the root case was we init the
hardware (blank and unblank) the screen.

because fb_set_var() will call fb_set_par() every time,
we needs check only set the hardware register when needed,
then the android default image without any modify can works.

Also a build warnning fix.

Signed-off-by: Zhang Jiejing <jiejing.zhang@freescale.com>
Signed-off-by: Liu Ying <Ying.Liu@freescale.com>
drivers/video/mxc/mxc_elcdif_fb.c

index 2c96eecc111fb44b215e041001542adc5ad7e7d9..50c23e4c934857bb1c247f3fefac2a5eec9cb360 100644 (file)
@@ -75,6 +75,7 @@ struct mxc_elcdif_fb_data {
        struct completion vsync_complete;
        struct completion frame_done_complete;
        struct semaphore flip_sem;
+       struct fb_var_screeninfo var;
        u32 pseudo_palette[16];
 };
 
@@ -775,6 +776,24 @@ static int mxc_elcdif_fb_setcolreg(u_int regno, u_int red, u_int green,
        return ret;
 }
 
+/**
+   This function compare the fb parameter see whether it was different
+   parameter for hardware, if it was different parameter, the hardware
+   will reinitialize. All will compared except x/y offset.
+ */
+static int mxc_fb_par_equal(struct fb_info *fbi, struct mxc_elcdif_fb_data *data)
+{
+       /* Here we set the xoffset, yoffset to zero, and compare two
+        * var see have different or not. */
+       struct fb_var_screeninfo oldvar = data->var;
+       struct fb_var_screeninfo newvar = fbi->var;
+
+       oldvar.xoffset = newvar.xoffset = 0;
+       oldvar.yoffset = newvar.yoffset = 0;
+
+       return memcmp(&oldvar, &newvar, sizeof(struct fb_var_screeninfo));
+}
+
 /*
  * This routine actually sets the video mode. It's in here where we
  * the hardware state info->par and fix which can be affected by the
@@ -789,6 +808,10 @@ static int mxc_elcdif_fb_set_par(struct fb_info *fbi)
 
        dev_dbg(fbi->device, "Reconfiguring framebuffer\n");
 
+       /* If parameter no change, don't reconfigure. */
+       if (mxc_fb_par_equal(fbi, data))
+           return 0;
+
        sema_init(&data->flip_sem, 1);
 
        /* release prev panel */
@@ -826,7 +849,7 @@ static int mxc_elcdif_fb_set_par(struct fb_info *fbi)
        mxc_init_elcdif();
        mxc_elcdif_init_panel();
 
-       dev_dbg(fbi->device, "pixclock = %lu Hz\n",
+       dev_dbg(fbi->device, "pixclock = %u Hz\n",
                (u32) (PICOS2KHZ(fbi->var.pixclock) * 1000UL));
 
        memset(&sig_cfg, 0, sizeof(sig_cfg));
@@ -860,6 +883,8 @@ static int mxc_elcdif_fb_set_par(struct fb_info *fbi)
 
        fbi->mode = (struct fb_videomode *)fb_match_mode(&fbi->var,
                                                         &fbi->modelist);
+       data->var = fbi->var;
+
        return 0;
 }
 
@@ -1119,7 +1144,10 @@ static int mxc_elcdif_fb_pan_display(struct fb_var_screeninfo *var,
        base = (var->bits_per_pixel) * base / 8;
        base += info->fix.smem_start;
 
-       down(&data->flip_sem);
+       if (down_timeout(&data->flip_sem, HZ / 2)) {
+               dev_err(info->device, "timeout when waiting for flip irq\n");
+               return -ETIMEDOUT;
+       }
 
        __raw_writel(base, elcdif_base + HW_ELCDIF_NEXT_BUF);