diff options
author | Danny Nold <dannynold@freescale.com> | 2011-02-04 14:03:54 -0600 |
---|---|---|
committer | Danny Nold <dannynold@freescale.com> | 2011-02-08 08:56:02 -0600 |
commit | 0b3f782cfaad8eaac459a2d2a91834700e845761 (patch) | |
tree | 9592e931025852670053681ff61e9d0e6a27a111 /drivers | |
parent | 1fcf0b4b0c6e9576b0d23bfb1609b394dd9ae0d0 (diff) |
ENGR00138821 - EPDC fb: Panning may cause missed collision
- When update is processed, we check against latest
panning offset and drop the update if they don't match. This
ensures that we always update using the most current
buffer location.
Signed-off-by: Danny Nold <dannynold@freescale.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/video/mxc/mxc_epdc_fb.c | 43 |
1 files changed, 39 insertions, 4 deletions
diff --git a/drivers/video/mxc/mxc_epdc_fb.c b/drivers/video/mxc/mxc_epdc_fb.c index 9589812f89d1..a26e1bc98bb7 100644 --- a/drivers/video/mxc/mxc_epdc_fb.c +++ b/drivers/video/mxc/mxc_epdc_fb.c @@ -1047,6 +1047,7 @@ static int mxc_epdc_fb_set_par(struct fb_info *info) int i; int ret; unsigned long flags; + __u32 xoffset_old, yoffset_old; /* * Can't change the FB parameters until current updates have completed. @@ -1055,7 +1056,15 @@ static int mxc_epdc_fb_set_par(struct fb_info *info) mxc_epdc_fb_flush_updates(fb_data); spin_lock_irqsave(&fb_data->queue_lock, flags); + /* + * Set all screeninfo except for xoffset/yoffset + * Subsequent call to pan_display will handle those. + */ + xoffset_old = fb_data->epdc_fb_var.xoffset; + yoffset_old = fb_data->epdc_fb_var.yoffset; fb_data->epdc_fb_var = *screeninfo; + fb_data->epdc_fb_var.xoffset = xoffset_old; + fb_data->epdc_fb_var.yoffset = yoffset_old; spin_unlock_irqrestore(&fb_data->queue_lock, flags); mutex_lock(&fb_data->pxp_mutex); @@ -1824,6 +1833,18 @@ static void epdc_submit_work_func(struct work_struct *work) continue; dev_dbg(fb_data->dev, "A collision update is ready to go!\n"); + + /* If update uses an out-of-date pan offset, we delete it */ + if (next_update->fb_offset != fb_data->fb_offset) { + dev_dbg(fb_data->dev, + "Dropping update (old pan offset)\n"); + list_del_init(&next_update->list); + /* Add to free buffer list */ + list_add_tail(&next_update->list, + &fb_data->upd_buf_free_list->list); + continue; + } + /* * We have a collision cleared, so select it for resubmission. * If an update is already selected, attempt to merge. @@ -1861,6 +1882,20 @@ static void epdc_submit_work_func(struct work_struct *work) dev_dbg(fb_data->dev, "Found a pending update!\n"); + /* + * Delete update if it is based on + * an out-of-date pan offset. + */ + if (next_update->fb_offset != fb_data->fb_offset) { + dev_dbg(fb_data->dev, + "Dropping update (old pan offset)\n"); + list_del_init(&next_update->list); + /* Add to free buffer list */ + list_add_tail(&next_update->list, + &fb_data->upd_buf_free_list->list); + continue; + } + if (!upd_data_list) { upd_data_list = next_update; list_del_init(&next_update->list); @@ -2430,8 +2465,8 @@ static int mxc_epdc_fb_pan_display(struct fb_var_screeninfo *var, u_int y_bottom; unsigned long flags; - dev_dbg(info->device, "%s: var->xoffset %d, info->var.xoffset %d\n", - __func__, var->xoffset, info->var.xoffset); + dev_dbg(info->device, "%s: var->yoffset %d, info->var.yoffset %d\n", + __func__, var->yoffset, info->var.yoffset); /* check if var is valid; also, xpan is not supported */ if (!var || (var->xoffset != info->var.xoffset) || (var->yoffset + var->yres > var->yres_virtual)) { @@ -2443,8 +2478,6 @@ static int mxc_epdc_fb_pan_display(struct fb_var_screeninfo *var, (fb_data->epdc_fb_var.yoffset == var->yoffset)) return 0; /* No change, do nothing */ - spin_lock_irqsave(&fb_data->queue_lock, flags); - y_bottom = var->yoffset; if (!(var->vmode & FB_VMODE_YWRAP)) @@ -2455,6 +2488,8 @@ static int mxc_epdc_fb_pan_display(struct fb_var_screeninfo *var, return -EINVAL; } + spin_lock_irqsave(&fb_data->queue_lock, flags); + fb_data->fb_offset = (var->yoffset * var->xres_virtual + var->xoffset) * (var->bits_per_pixel) / 8; |