aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/sh_mobile_lcdcfb.c
diff options
context:
space:
mode:
authorPhil Edworthy <Phil.Edworthy@renesas.com>2010-02-11 05:24:25 -0500
committerPaul Mundt <lethal@linux-sh.org>2010-02-15 23:30:29 -0500
commit92e1f9a7ed613b36f3aaf8b04a79e2fd4fa37ec1 (patch)
tree3e1ac9265c8b7044b99d8473deb25dff577994ec /drivers/video/sh_mobile_lcdcfb.c
parent40331b21f5fdb746e80fc609ef60ef71b5cd47d9 (diff)
video: sh_mobile_lcdcfb: Fix panning.
Fixed SH-Mobile panning. Previously the address of the frame to be displayed was updated in the VSync end interrupt. This meant there was a minimum of 1 frame bewteen calling FBIOPAN_DISPLAY ioctl and the pan occuring. This meant that apps were not able to use the FBIO_WAITFORVSYNC ioctl to wait for the pan to complete. This patch moves the write to LDSA1R mirror reg into the pan ioctl. Tested on MS7724 board against 2.6.33-rc7 Signed-off-by: Phil Edworthy <phil.edworthy@renesas.com> Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Diffstat (limited to 'drivers/video/sh_mobile_lcdcfb.c')
-rw-r--r--drivers/video/sh_mobile_lcdcfb.c46
1 files changed, 18 insertions, 28 deletions
diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c
index 37aeced2dc18..8d7653e56df5 100644
--- a/drivers/video/sh_mobile_lcdcfb.c
+++ b/drivers/video/sh_mobile_lcdcfb.c
@@ -124,7 +124,6 @@ struct sh_mobile_lcdc_chan {
124 struct scatterlist *sglist; 124 struct scatterlist *sglist;
125 unsigned long frame_end; 125 unsigned long frame_end;
126 unsigned long pan_offset; 126 unsigned long pan_offset;
127 unsigned long new_pan_offset;
128 wait_queue_head_t frame_end_wait; 127 wait_queue_head_t frame_end_wait;
129 struct completion vsync_completion; 128 struct completion vsync_completion;
130}; 129};
@@ -369,21 +368,6 @@ static irqreturn_t sh_mobile_lcdc_irq(int irq, void *data)
369 } 368 }
370 369
371 /* VSYNC End */ 370 /* VSYNC End */
372 if ((ldintr & LDINTR_VES) &&
373 (ch->pan_offset != ch->new_pan_offset)) {
374 unsigned long ldrcntr = lcdc_read(priv, _LDRCNTR);
375 /* Set the source address for the next refresh */
376 lcdc_write_chan_mirror(ch, LDSA1R, ch->dma_handle +
377 ch->new_pan_offset);
378 if (lcdc_chan_is_sublcd(ch))
379 lcdc_write(ch->lcdc, _LDRCNTR,
380 ldrcntr ^ LDRCNTR_SRS);
381 else
382 lcdc_write(ch->lcdc, _LDRCNTR,
383 ldrcntr ^ LDRCNTR_MRS);
384 ch->pan_offset = ch->new_pan_offset;
385 }
386
387 if (ldintr & LDINTR_VES) 371 if (ldintr & LDINTR_VES)
388 complete(&ch->vsync_completion); 372 complete(&ch->vsync_completion);
389 } 373 }
@@ -774,21 +758,28 @@ static int sh_mobile_fb_pan_display(struct fb_var_screeninfo *var,
774 struct fb_info *info) 758 struct fb_info *info)
775{ 759{
776 struct sh_mobile_lcdc_chan *ch = info->par; 760 struct sh_mobile_lcdc_chan *ch = info->par;
761 struct sh_mobile_lcdc_priv *priv = ch->lcdc;
762 unsigned long ldrcntr;
763 unsigned long new_pan_offset;
764
765 new_pan_offset = (var->yoffset * info->fix.line_length) +
766 (var->xoffset * (info->var.bits_per_pixel / 8));
777 767
778 if (info->var.xoffset == var->xoffset && 768 if (new_pan_offset == ch->pan_offset)
779 info->var.yoffset == var->yoffset)
780 return 0; /* No change, do nothing */ 769 return 0; /* No change, do nothing */
781 770
782 ch->new_pan_offset = (var->yoffset * info->fix.line_length) + 771 ldrcntr = lcdc_read(priv, _LDRCNTR);
783 (var->xoffset * (info->var.bits_per_pixel / 8));
784 772
785 if (ch->new_pan_offset != ch->pan_offset) { 773 /* Set the source address for the next refresh */
786 unsigned long ldintr; 774 lcdc_write_chan_mirror(ch, LDSA1R, ch->dma_handle + new_pan_offset);
787 ldintr = lcdc_read(ch->lcdc, _LDINTR); 775 if (lcdc_chan_is_sublcd(ch))
788 ldintr |= LDINTR_VEE; 776 lcdc_write(ch->lcdc, _LDRCNTR, ldrcntr ^ LDRCNTR_SRS);
789 lcdc_write(ch->lcdc, _LDINTR, ldintr); 777 else
790 sh_mobile_lcdc_deferred_io_touch(info); 778 lcdc_write(ch->lcdc, _LDRCNTR, ldrcntr ^ LDRCNTR_MRS);
791 } 779
780 ch->pan_offset = new_pan_offset;
781
782 sh_mobile_lcdc_deferred_io_touch(info);
792 783
793 return 0; 784 return 0;
794} 785}
@@ -1009,7 +1000,6 @@ static int __init sh_mobile_lcdc_probe(struct platform_device *pdev)
1009 init_waitqueue_head(&priv->ch[i].frame_end_wait); 1000 init_waitqueue_head(&priv->ch[i].frame_end_wait);
1010 init_completion(&priv->ch[i].vsync_completion); 1001 init_completion(&priv->ch[i].vsync_completion);
1011 priv->ch[j].pan_offset = 0; 1002 priv->ch[j].pan_offset = 0;
1012 priv->ch[j].new_pan_offset = 0;
1013 1003
1014 switch (pdata->ch[i].chan) { 1004 switch (pdata->ch[i].chan) {
1015 case LCDC_CHAN_MAINLCD: 1005 case LCDC_CHAN_MAINLCD: