summaryrefslogtreecommitdiff
path: root/drivers/media/video/ivtv/ivtv-irq.c
diff options
context:
space:
mode:
authorIan Armstrong <ian@iarmst.demon.co.uk>2007-08-03 10:01:39 -0300
committerMauro Carvalho Chehab <mchehab@infradead.org>2007-10-09 22:04:29 -0300
commitbfd7beacff2b5c811badb587a74c3dfbf7f98721 (patch)
tree47628dfa13bc221e2a5466934830ca54a6f46bc0 /drivers/media/video/ivtv/ivtv-irq.c
parent943e8910db31e36d945f2bf7d4c273ca5fa01f6e (diff)
V4L/DVB (5973): ivtv: attach yuv field order to each frame
In the current driver, the field order is global. As soon as it's changed it takes immediate effect. This is a problem when the video changes order mid stream. Although it mostly works okay, the video may judder / flicker. This patch attaches the field order to the frame, so that any buffered frames will not be displayed until the correct field. In the event that the field order is changed mid stream, the driver will ensure that the previous frame is displayed for a minimum of 3 fields. These are the two original fields the frame should have occupied, plus the one extra since the new frame still has to wait for the correct field. Signed-off-by: Ian Armstrong <ian@iarmst.demon.co.uk> Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl> Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Diffstat (limited to 'drivers/media/video/ivtv/ivtv-irq.c')
-rw-r--r--drivers/media/video/ivtv/ivtv-irq.c22
1 files changed, 14 insertions, 8 deletions
diff --git a/drivers/media/video/ivtv/ivtv-irq.c b/drivers/media/video/ivtv/ivtv-irq.c
index fcd6e7f5f121..88c6f4ff5c6d 100644
--- a/drivers/media/video/ivtv/ivtv-irq.c
+++ b/drivers/media/video/ivtv/ivtv-irq.c
@@ -698,17 +698,21 @@ static void ivtv_irq_vsync(struct ivtv *itv)
if (0) IVTV_DEBUG_IRQ("DEC VSYNC\n");
- if (((frame ^ itv->yuv_info.lace_sync_field) == 0 && ((itv->lastVsyncFrame & 1) ^ itv->yuv_info.lace_sync_field)) ||
+ if (((frame ^ itv->yuv_info.sync_field[last_dma_frame]) == 0 &&
+ ((itv->lastVsyncFrame & 1) ^ itv->yuv_info.sync_field[last_dma_frame])) ||
(frame != (itv->lastVsyncFrame & 1) && !itv->yuv_info.frame_interlaced)) {
int next_dma_frame = last_dma_frame;
- if (next_dma_frame >= 0 && next_dma_frame != atomic_read(&itv->yuv_info.next_fill_frame)) {
- write_reg(yuv_offset[next_dma_frame] >> 4, 0x82c);
- write_reg((yuv_offset[next_dma_frame] + IVTV_YUV_BUFFER_UV_OFFSET) >> 4, 0x830);
- write_reg(yuv_offset[next_dma_frame] >> 4, 0x834);
- write_reg((yuv_offset[next_dma_frame] + IVTV_YUV_BUFFER_UV_OFFSET) >> 4, 0x838);
- next_dma_frame = (next_dma_frame + 1) & 0x3;
- atomic_set(&itv->yuv_info.next_dma_frame, next_dma_frame);
+ if (!(itv->yuv_info.frame_interlaced && itv->yuv_info.field_delay[next_dma_frame] && itv->yuv_info.fields_lapsed < 1)) {
+ if (next_dma_frame >= 0 && next_dma_frame != atomic_read(&itv->yuv_info.next_fill_frame)) {
+ write_reg(yuv_offset[next_dma_frame] >> 4, 0x82c);
+ write_reg((yuv_offset[next_dma_frame] + IVTV_YUV_BUFFER_UV_OFFSET) >> 4, 0x830);
+ write_reg(yuv_offset[next_dma_frame] >> 4, 0x834);
+ write_reg((yuv_offset[next_dma_frame] + IVTV_YUV_BUFFER_UV_OFFSET) >> 4, 0x838);
+ next_dma_frame = (next_dma_frame + 1) & 0x3;
+ atomic_set(&itv->yuv_info.next_dma_frame, next_dma_frame);
+ itv->yuv_info.fields_lapsed = -1;
+ }
}
}
if (frame != (itv->lastVsyncFrame & 1)) {
@@ -749,6 +753,8 @@ static void ivtv_irq_vsync(struct ivtv *itv)
set_bit(IVTV_F_I_HAVE_WORK, &itv->i_flags);
}
}
+
+ itv->yuv_info.fields_lapsed ++;
}
}