From 7d7ddd15954aa71c40a5e4f7c0e651a63ce42c0a Mon Sep 17 00:00:00 2001 From: Zhang Jiejing Date: Fri, 25 May 2012 17:03:02 +0800 Subject: [PATCH] ENGR00210915 fb: mxc_elcdfb: fix screen flash when use fb_set_var 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 Signed-off-by: Liu Ying --- drivers/video/mxc/mxc_elcdif_fb.c | 32 +++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/drivers/video/mxc/mxc_elcdif_fb.c b/drivers/video/mxc/mxc_elcdif_fb.c index 2c96eecc111f..50c23e4c9348 100644 --- a/drivers/video/mxc/mxc_elcdif_fb.c +++ b/drivers/video/mxc/mxc_elcdif_fb.c @@ -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); -- 2.39.5