@@ -19,6 +19,7 @@
#include <linux/dma-mapping.h>
#include <linux/interrupt.h>
#include <linux/vmalloc.h>
+#include <linux/ioctl.h>
#include <video/sh_mobile_lcdc.h>
#include <asm/atomic.h>
@@ -40,6 +41,10 @@
#define _LDDWAR 0x900
#define _LDDRAR 0x904
+#ifndef FBIO_WAITFORVSYNC
+#define FBIO_WAITFORVSYNC _IOW('F', 0x20, __u32)
+#endif
+
/* shared registers and their order for context save/restore */
static int lcdc_shared_regs[] = {
_LDDCKR,
@@ -106,6 +111,7 @@
#define LDRCNTR_SRC 0x00010000
#define LDRCNTR_MRS 0x00000002
#define LDRCNTR_MRC 0x00000001
+#define LDSR_MRS 0x00000100
struct sh_mobile_lcdc_priv;
struct sh_mobile_lcdc_chan {
@@ -124,6 +130,8 @@
unsigned long pan_offset;
unsigned long new_pan_offset;
wait_queue_head_t frame_end_wait;
+ unsigned long seen_vsync;
+ wait_queue_head_t wait_vsync;
};
struct sh_mobile_lcdc_priv {
@@ -367,17 +375,22 @@
/* VSYNC End */
if (ldintr & LDINTR_VES) {
- unsigned long ldrcntr = lcdc_read(priv, _LDRCNTR);
- /* Set the source address for the next refresh */
- lcdc_write_chan_mirror(ch, LDSA1R, ch->dma_handle +
- ch->new_pan_offset);
- if (lcdc_chan_is_sublcd(ch))
- lcdc_write(ch->lcdc, _LDRCNTR,
- ldrcntr ^ LDRCNTR_SRS);
- else
- lcdc_write(ch->lcdc, _LDRCNTR,
- ldrcntr ^ LDRCNTR_MRS);
- ch->pan_offset = ch->new_pan_offset;
+ if (ch->pan_offset != ch->new_pan_offset) {
+ unsigned long ldrcntr = lcdc_read(priv,
_LDRCNTR);
+ /* Set the source address for the next
refresh */
+ lcdc_write_chan_mirror(ch, LDSA1R,
ch->dma_handle +
+
ch->new_pan_offset);
+ if (lcdc_chan_is_sublcd(ch))
+ lcdc_write(ch->lcdc, _LDRCNTR,
+ ldrcntr ^ LDRCNTR_SRS);
+ else
+ lcdc_write(ch->lcdc, _LDRCNTR,
+ ldrcntr ^ LDRCNTR_MRS);
+ ch->pan_offset = ch->new_pan_offset;
+ }
+
+ ch->seen_vsync = 1;