aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/ivtv/ivtv-irq.c
diff options
context:
space:
mode:
authorIan Armstrong <ian@iarmst.demon.co.uk>2007-08-03 09:01:39 -0400
committerMauro Carvalho Chehab <mchehab@infradead.org>2007-10-09 21:04:29 -0400
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)
698 698
699 if (0) IVTV_DEBUG_IRQ("DEC VSYNC\n"); 699 if (0) IVTV_DEBUG_IRQ("DEC VSYNC\n");
700 700
701 if (((frame ^ itv->yuv_info.lace_sync_field) == 0 && ((itv->lastVsyncFrame & 1) ^ itv->yuv_info.lace_sync_field)) || 701 if (((frame ^ itv->yuv_info.sync_field[last_dma_frame]) == 0 &&
702 ((itv->lastVsyncFrame & 1) ^ itv->yuv_info.sync_field[last_dma_frame])) ||
702 (frame != (itv->lastVsyncFrame & 1) && !itv->yuv_info.frame_interlaced)) { 703 (frame != (itv->lastVsyncFrame & 1) && !itv->yuv_info.frame_interlaced)) {
703 int next_dma_frame = last_dma_frame; 704 int next_dma_frame = last_dma_frame;
704 705
705 if (next_dma_frame >= 0 && next_dma_frame != atomic_read(&itv->yuv_info.next_fill_frame)) { 706 if (!(itv->yuv_info.frame_interlaced && itv->yuv_info.field_delay[next_dma_frame] && itv->yuv_info.fields_lapsed < 1)) {
706 write_reg(yuv_offset[next_dma_frame] >> 4, 0x82c); 707 if (next_dma_frame >= 0 && next_dma_frame != atomic_read(&itv->yuv_info.next_fill_frame)) {
707 write_reg((yuv_offset[next_dma_frame] + IVTV_YUV_BUFFER_UV_OFFSET) >> 4, 0x830); 708 write_reg(yuv_offset[next_dma_frame] >> 4, 0x82c);
708 write_reg(yuv_offset[next_dma_frame] >> 4, 0x834); 709 write_reg((yuv_offset[next_dma_frame] + IVTV_YUV_BUFFER_UV_OFFSET) >> 4, 0x830);
709 write_reg((yuv_offset[next_dma_frame] + IVTV_YUV_BUFFER_UV_OFFSET) >> 4, 0x838); 710 write_reg(yuv_offset[next_dma_frame] >> 4, 0x834);
710 next_dma_frame = (next_dma_frame + 1) & 0x3; 711 write_reg((yuv_offset[next_dma_frame] + IVTV_YUV_BUFFER_UV_OFFSET) >> 4, 0x838);
711 atomic_set(&itv->yuv_info.next_dma_frame, next_dma_frame); 712 next_dma_frame = (next_dma_frame + 1) & 0x3;
713 atomic_set(&itv->yuv_info.next_dma_frame, next_dma_frame);
714 itv->yuv_info.fields_lapsed = -1;
715 }
712 } 716 }
713 } 717 }
714 if (frame != (itv->lastVsyncFrame & 1)) { 718 if (frame != (itv->lastVsyncFrame & 1)) {
@@ -749,6 +753,8 @@ static void ivtv_irq_vsync(struct ivtv *itv)
749 set_bit(IVTV_F_I_HAVE_WORK, &itv->i_flags); 753 set_bit(IVTV_F_I_HAVE_WORK, &itv->i_flags);
750 } 754 }
751 } 755 }
756
757 itv->yuv_info.fields_lapsed ++;
752 } 758 }
753} 759}
754 760