aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Chen <b02280@freescale.com>2011-12-14 14:02:16 +0800
committerEric Miao <eric.miao@linaro.org>2012-01-11 21:39:30 +0800
commitb80aa11ee88cc4a3a9764eb6312f011da15c566b (patch)
tree5fb49e505a95c5b1d95ed4447e08d6c381f988d2
parente9c4ab4d44dca63faafba62054896ef196623095 (diff)
downloadlinux-linaro-b80aa11ee88cc4a3a9764eb6312f011da15c566b.tar.gz
ENGR00170168-1 ipuv3 fb: add non FB_VMODE_YWRAP support
when use pan display, the case could be: 1. a small window wrap in a big frame buffer 2. a frame switch in a serial buffers the ipuv3 fb driver used to support case 1, and for case 2, if the fb format is interleaved, there is no problem, but for non-interleaved format (like I420), there will be a display bug. Signed-off-by: Jason Chen <b02280@freescale.com>
-rw-r--r--drivers/video/mxc/mxc_ipuv3_fb.c63
1 files changed, 49 insertions, 14 deletions
diff --git a/drivers/video/mxc/mxc_ipuv3_fb.c b/drivers/video/mxc/mxc_ipuv3_fb.c
index 70b7be1df0b..9ccafc2d95b 100644
--- a/drivers/video/mxc/mxc_ipuv3_fb.c
+++ b/drivers/video/mxc/mxc_ipuv3_fb.c
@@ -247,6 +247,7 @@ static int _setup_disp_channel2(struct fb_info *fbi)
struct mxcfb_info *mxc_fbi = (struct mxcfb_info *)fbi->par;
int fb_stride;
unsigned long base;
+ unsigned int fr_xoff, fr_yoff, fr_w, fr_h;
switch (bpp_to_pixfmt(fbi)) {
case IPU_PIX_FMT_YUV420P2:
@@ -261,16 +262,28 @@ static int _setup_disp_channel2(struct fb_info *fbi)
fb_stride = fbi->fix.line_length;
}
+ base = fbi->fix.smem_start;
+ fr_xoff = fbi->var.xoffset;
+ fr_w = fbi->var.xres_virtual;
+ if (!(fbi->var.vmode & FB_VMODE_YWRAP)) {
+ dev_dbg(fbi->device, "Y wrap disabled\n");
+ fr_yoff = fbi->var.yoffset % fbi->var.yres;
+ fr_h = fbi->var.yres;
+ base += fbi->fix.line_length * fbi->var.yres *
+ (fbi->var.yoffset / fbi->var.yres);
+ } else {
+ dev_dbg(fbi->device, "Y wrap enabled\n");
+ fr_yoff = fbi->var.yoffset;
+ fr_h = fbi->var.yres_virtual;
+ }
+ base += fr_yoff * fb_stride + fr_xoff;
+
mxc_fbi->cur_ipu_buf = 2;
sema_init(&mxc_fbi->flip_sem, 1);
if (mxc_fbi->alpha_chan_en) {
mxc_fbi->cur_ipu_alpha_buf = 1;
sema_init(&mxc_fbi->alpha_flip_sem, 1);
}
- fbi->var.xoffset = 0;
-
- base = (fbi->var.yoffset * fb_stride + fbi->var.xoffset);
- base += fbi->fix.smem_start;
retval = ipu_init_channel_buffer(mxc_fbi->ipu,
mxc_fbi->ipu_ch, IPU_INPUT_BUFFER,
@@ -288,6 +301,17 @@ static int _setup_disp_channel2(struct fb_info *fbi)
"ipu_init_channel_buffer error %d\n", retval);
}
+ /* update u/v offset */
+ ipu_update_channel_offset(mxc_fbi->ipu, mxc_fbi->ipu_ch,
+ IPU_INPUT_BUFFER,
+ bpp_to_pixfmt(fbi),
+ fr_w,
+ fr_h,
+ fr_w,
+ 0, 0,
+ fr_yoff,
+ fr_xoff);
+
if (mxc_fbi->alpha_chan_en) {
retval = ipu_init_channel_buffer(mxc_fbi->ipu,
mxc_fbi->ipu_ch,
@@ -1224,6 +1248,7 @@ mxcfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
struct mxcfb_info *mxc_fbi = (struct mxcfb_info *)info->par,
*mxc_graphic_fbi = NULL;
u_int y_bottom;
+ unsigned int fr_xoff, fr_yoff, fr_w, fr_h;
unsigned long base, active_alpha_phy_addr = 0;
bool loc_alpha_en = false;
int fb_stride;
@@ -1250,9 +1275,6 @@ mxcfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
y_bottom = var->yoffset;
- if (!(var->vmode & FB_VMODE_YWRAP))
- y_bottom += var->yres;
-
if (y_bottom > info->var.yres_virtual)
return -EINVAL;
@@ -1269,8 +1291,21 @@ mxcfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
fb_stride = info->fix.line_length;
}
- base = (var->yoffset * fb_stride + var->xoffset);
- base += info->fix.smem_start;
+ base = info->fix.smem_start;
+ fr_xoff = var->xoffset;
+ fr_w = info->var.xres_virtual;
+ if (!(var->vmode & FB_VMODE_YWRAP)) {
+ dev_dbg(info->device, "Y wrap disabled\n");
+ fr_yoff = var->yoffset % info->var.yres;
+ fr_h = info->var.yres;
+ base += info->fix.line_length * info->var.yres *
+ (var->yoffset / info->var.yres);
+ } else {
+ dev_dbg(info->device, "Y wrap enabled\n");
+ fr_yoff = var->yoffset;
+ fr_h = info->var.yres_virtual;
+ }
+ base += fr_yoff * fb_stride + fr_xoff;
/* Check if DP local alpha is enabled and find the graphic fb */
if (mxc_fbi->ipu_ch == MEM_BG_SYNC || mxc_fbi->ipu_ch == MEM_FG_SYNC) {
@@ -1326,12 +1361,12 @@ mxcfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
ipu_update_channel_offset(mxc_fbi->ipu, mxc_fbi->ipu_ch,
IPU_INPUT_BUFFER,
bpp_to_pixfmt(info),
- info->var.xres_virtual,
- info->var.yres_virtual,
- info->var.xres_virtual,
+ fr_w,
+ fr_h,
+ fr_w,
0, 0,
- var->yoffset,
- var->xoffset);
+ fr_yoff,
+ fr_xoff);
ipu_select_buffer(mxc_fbi->ipu, mxc_fbi->ipu_ch, IPU_INPUT_BUFFER,
mxc_fbi->cur_ipu_buf);