diff options
author | Danny Nold <dannynold@freescale.com> | 2010-08-31 10:46:32 -0500 |
---|---|---|
committer | Danny Nold <dannynold@freescale.com> | 2010-09-02 15:25:14 -0500 |
commit | 01d9f8cf736de396e6a9149f17fff9b3836d0f46 (patch) | |
tree | 75c29a557ea45ab4d985e42731e7c2f67af7a3e6 | |
parent | bd1061757bd39ef69793cc726f6ad53f1ab72020 (diff) |
ENGR00126939 - EPDC fb: Screen shows garbage under certain update conditions.
When update X coordinate is an odd number and the update region width
is a multiple of 8, the screen shows garbage due to a bug in how the
driver handles this corner case. The fix is to identify and handle
this case in the driver.
Signed-off-by: Danny Nold <dannynold@freescale.com>
-rw-r--r-- | drivers/video/mxc/mxc_epdc_fb.c | 31 |
1 files changed, 22 insertions, 9 deletions
diff --git a/drivers/video/mxc/mxc_epdc_fb.c b/drivers/video/mxc/mxc_epdc_fb.c index 548f77514cdd..b4168e0d0caa 100644 --- a/drivers/video/mxc/mxc_epdc_fb.c +++ b/drivers/video/mxc/mxc_epdc_fb.c @@ -193,7 +193,8 @@ void __iomem *epdc_base; static int mxc_epdc_fb_blank(int blank, struct fb_info *info); static int mxc_epdc_fb_init_hw(struct fb_info *info); static int pxp_process_update(struct mxc_epdc_fb_data *fb_data, - struct mxcfb_rect *update_region); + struct mxcfb_rect *update_region, + int x_start_offs); static int pxp_complete_update(struct mxc_epdc_fb_data *fb_data, u32 *hist_stat); static void draw_mode0(struct mxc_epdc_fb_data *fb_data); @@ -1279,7 +1280,7 @@ static int mxc_epdc_fb_send_update(struct mxcfb_update_data *upd_data, u32 offset_from_8, bytes_per_pixel; u32 post_rotation_xcoord, post_rotation_ycoord, width_pxp_blocks; u32 pxp_input_offs, pxp_output_offs, pxp_output_shift; - int adj_left, adj_top; + int x_start_offs = 0; u32 hist_stat = 0; int temp_index; bool wait_for_power = false; @@ -1408,11 +1409,21 @@ static int mxc_epdc_fb_send_update(struct mxcfb_update_data *upd_data, pxp_upd_region.left = 0; } + /* + * We want PxP processing region to start at the first pixel + * that we have to process in each row, but PxP alignment + * restricts the input mem address to be 32-bit aligned + * + * We work around this by using x_start_offs to offset + * to offset from our starting pixel location to the + * first pixel that is in the relevant update region + * for each row. + */ + x_start_offs = pxp_upd_region.left & 0x7; + /* Update region to meet 8x8 pixel requirement */ - adj_left = pxp_upd_region.left & 0x7; - adj_top = pxp_upd_region.top & 0x7; - pxp_upd_region.width = ALIGN(src_upd_region->width + adj_left, 8); - pxp_upd_region.height = ALIGN(src_upd_region->height + adj_top, 8); + pxp_upd_region.width = ALIGN(src_upd_region->width, 8); + pxp_upd_region.height = ALIGN(src_upd_region->height, 8); pxp_upd_region.top &= ~0x7; pxp_upd_region.left &= ~0x7; @@ -1471,7 +1482,8 @@ static int mxc_epdc_fb_send_update(struct mxcfb_update_data *upd_data, mutex_lock(&fb_data->pxp_mutex); /* This is a blocking call, so upon return PxP tx should be done */ - ret = pxp_process_update(fb_data, &pxp_upd_region); + ret = pxp_process_update(fb_data, &pxp_upd_region, + x_start_offs); if (ret) { dev_err(fb_data->dev, "Unable to submit PxP update task.\n"); mutex_unlock(&fb_data->pxp_mutex); @@ -3003,7 +3015,8 @@ static int pxp_chan_init(struct mxc_epdc_fb_data *fb_data) * Note: This is a blocking call, so upon return the PxP tx should be complete. */ static int pxp_process_update(struct mxc_epdc_fb_data *fb_data, - struct mxcfb_rect *update_region) + struct mxcfb_rect *update_region, + int x_start_offs) { dma_cookie_t cookie; struct scatterlist *sg = fb_data->sg; @@ -3064,7 +3077,7 @@ static int pxp_process_update(struct mxc_epdc_fb_data *fb_data, * probe() and should not need to be changed. */ proc_data->srect.top = update_region->top; - proc_data->srect.left = update_region->left; + proc_data->srect.left = update_region->left + x_start_offs; proc_data->srect.width = update_region->width; proc_data->srect.height = update_region->height; |