aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/video')
-rw-r--r--drivers/video/pvr2fb.c2
-rw-r--r--drivers/video/sh_mobile_lcdcfb.c88
2 files changed, 63 insertions, 27 deletions
diff --git a/drivers/video/pvr2fb.c b/drivers/video/pvr2fb.c
index 53f8f1100e81..f9975100d56d 100644
--- a/drivers/video/pvr2fb.c
+++ b/drivers/video/pvr2fb.c
@@ -831,7 +831,7 @@ static int __devinit pvr2fb_common_init(void)
831 printk(KERN_NOTICE "fb%d: registering with SQ API\n", fb_info->node); 831 printk(KERN_NOTICE "fb%d: registering with SQ API\n", fb_info->node);
832 832
833 pvr2fb_map = sq_remap(fb_info->fix.smem_start, fb_info->fix.smem_len, 833 pvr2fb_map = sq_remap(fb_info->fix.smem_start, fb_info->fix.smem_len,
834 fb_info->fix.id, pgprot_val(PAGE_SHARED)); 834 fb_info->fix.id, PAGE_SHARED);
835 835
836 printk(KERN_NOTICE "fb%d: Mapped video memory to SQ addr 0x%lx\n", 836 printk(KERN_NOTICE "fb%d: Mapped video memory to SQ addr 0x%lx\n",
837 fb_info->node, pvr2fb_map); 837 fb_info->node, pvr2fb_map);
diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c
index a69830d26f7f..8d7653e56df5 100644
--- a/drivers/video/sh_mobile_lcdcfb.c
+++ b/drivers/video/sh_mobile_lcdcfb.c
@@ -19,6 +19,7 @@
19#include <linux/dma-mapping.h> 19#include <linux/dma-mapping.h>
20#include <linux/interrupt.h> 20#include <linux/interrupt.h>
21#include <linux/vmalloc.h> 21#include <linux/vmalloc.h>
22#include <linux/ioctl.h>
22#include <video/sh_mobile_lcdc.h> 23#include <video/sh_mobile_lcdc.h>
23#include <asm/atomic.h> 24#include <asm/atomic.h>
24 25
@@ -106,6 +107,7 @@ static unsigned long lcdc_offs_sublcd[NR_CH_REGS] = {
106#define LDRCNTR_SRC 0x00010000 107#define LDRCNTR_SRC 0x00010000
107#define LDRCNTR_MRS 0x00000002 108#define LDRCNTR_MRS 0x00000002
108#define LDRCNTR_MRC 0x00000001 109#define LDRCNTR_MRC 0x00000001
110#define LDSR_MRS 0x00000100
109 111
110struct sh_mobile_lcdc_priv; 112struct sh_mobile_lcdc_priv;
111struct sh_mobile_lcdc_chan { 113struct sh_mobile_lcdc_chan {
@@ -122,8 +124,8 @@ struct sh_mobile_lcdc_chan {
122 struct scatterlist *sglist; 124 struct scatterlist *sglist;
123 unsigned long frame_end; 125 unsigned long frame_end;
124 unsigned long pan_offset; 126 unsigned long pan_offset;
125 unsigned long new_pan_offset;
126 wait_queue_head_t frame_end_wait; 127 wait_queue_head_t frame_end_wait;
128 struct completion vsync_completion;
127}; 129};
128 130
129struct sh_mobile_lcdc_priv { 131struct sh_mobile_lcdc_priv {
@@ -366,19 +368,8 @@ static irqreturn_t sh_mobile_lcdc_irq(int irq, void *data)
366 } 368 }
367 369
368 /* VSYNC End */ 370 /* VSYNC End */
369 if (ldintr & LDINTR_VES) { 371 if (ldintr & LDINTR_VES)
370 unsigned long ldrcntr = lcdc_read(priv, _LDRCNTR); 372 complete(&ch->vsync_completion);
371 /* Set the source address for the next refresh */
372 lcdc_write_chan_mirror(ch, LDSA1R, ch->dma_handle +
373 ch->new_pan_offset);
374 if (lcdc_chan_is_sublcd(ch))
375 lcdc_write(ch->lcdc, _LDRCNTR,
376 ldrcntr ^ LDRCNTR_SRS);
377 else
378 lcdc_write(ch->lcdc, _LDRCNTR,
379 ldrcntr ^ LDRCNTR_MRS);
380 ch->pan_offset = ch->new_pan_offset;
381 }
382 } 373 }
383 374
384 return IRQ_HANDLED; 375 return IRQ_HANDLED;
@@ -767,25 +758,69 @@ static int sh_mobile_fb_pan_display(struct fb_var_screeninfo *var,
767 struct fb_info *info) 758 struct fb_info *info)
768{ 759{
769 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));
770 767
771 if (info->var.xoffset == var->xoffset && 768 if (new_pan_offset == ch->pan_offset)
772 info->var.yoffset == var->yoffset)
773 return 0; /* No change, do nothing */ 769 return 0; /* No change, do nothing */
774 770
775 ch->new_pan_offset = (var->yoffset * info->fix.line_length) + 771 ldrcntr = lcdc_read(priv, _LDRCNTR);
776 (var->xoffset * (info->var.bits_per_pixel / 8));
777 772
778 if (ch->new_pan_offset != ch->pan_offset) { 773 /* Set the source address for the next refresh */
779 unsigned long ldintr; 774 lcdc_write_chan_mirror(ch, LDSA1R, ch->dma_handle + new_pan_offset);
780 ldintr = lcdc_read(ch->lcdc, _LDINTR); 775 if (lcdc_chan_is_sublcd(ch))
781 ldintr |= LDINTR_VEE; 776 lcdc_write(ch->lcdc, _LDRCNTR, ldrcntr ^ LDRCNTR_SRS);
782 lcdc_write(ch->lcdc, _LDINTR, ldintr); 777 else
783 sh_mobile_lcdc_deferred_io_touch(info); 778 lcdc_write(ch->lcdc, _LDRCNTR, ldrcntr ^ LDRCNTR_MRS);
784 } 779
780 ch->pan_offset = new_pan_offset;
781
782 sh_mobile_lcdc_deferred_io_touch(info);
783
784 return 0;
785}
786
787static int sh_mobile_wait_for_vsync(struct fb_info *info)
788{
789 struct sh_mobile_lcdc_chan *ch = info->par;
790 unsigned long ldintr;
791 int ret;
792
793 /* Enable VSync End interrupt */
794 ldintr = lcdc_read(ch->lcdc, _LDINTR);
795 ldintr |= LDINTR_VEE;
796 lcdc_write(ch->lcdc, _LDINTR, ldintr);
797
798 ret = wait_for_completion_interruptible_timeout(&ch->vsync_completion,
799 msecs_to_jiffies(100));
800 if (!ret)
801 return -ETIMEDOUT;
785 802
786 return 0; 803 return 0;
787} 804}
788 805
806static int sh_mobile_ioctl(struct fb_info *info, unsigned int cmd,
807 unsigned long arg)
808{
809 int retval;
810
811 switch (cmd) {
812 case FBIO_WAITFORVSYNC:
813 retval = sh_mobile_wait_for_vsync(info);
814 break;
815
816 default:
817 retval = -ENOIOCTLCMD;
818 break;
819 }
820 return retval;
821}
822
823
789static struct fb_ops sh_mobile_lcdc_ops = { 824static struct fb_ops sh_mobile_lcdc_ops = {
790 .owner = THIS_MODULE, 825 .owner = THIS_MODULE,
791 .fb_setcolreg = sh_mobile_lcdc_setcolreg, 826 .fb_setcolreg = sh_mobile_lcdc_setcolreg,
@@ -795,6 +830,7 @@ static struct fb_ops sh_mobile_lcdc_ops = {
795 .fb_copyarea = sh_mobile_lcdc_copyarea, 830 .fb_copyarea = sh_mobile_lcdc_copyarea,
796 .fb_imageblit = sh_mobile_lcdc_imageblit, 831 .fb_imageblit = sh_mobile_lcdc_imageblit,
797 .fb_pan_display = sh_mobile_fb_pan_display, 832 .fb_pan_display = sh_mobile_fb_pan_display,
833 .fb_ioctl = sh_mobile_ioctl,
798}; 834};
799 835
800static int sh_mobile_lcdc_set_bpp(struct fb_var_screeninfo *var, int bpp) 836static int sh_mobile_lcdc_set_bpp(struct fb_var_screeninfo *var, int bpp)
@@ -962,8 +998,8 @@ static int __init sh_mobile_lcdc_probe(struct platform_device *pdev)
962 goto err1; 998 goto err1;
963 } 999 }
964 init_waitqueue_head(&priv->ch[i].frame_end_wait); 1000 init_waitqueue_head(&priv->ch[i].frame_end_wait);
1001 init_completion(&priv->ch[i].vsync_completion);
965 priv->ch[j].pan_offset = 0; 1002 priv->ch[j].pan_offset = 0;
966 priv->ch[j].new_pan_offset = 0;
967 1003
968 switch (pdata->ch[i].chan) { 1004 switch (pdata->ch[i].chan) {
969 case LCDC_CHAN_MAINLCD: 1005 case LCDC_CHAN_MAINLCD: