aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/ivtv
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
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')
-rw-r--r--drivers/media/video/ivtv/ivtv-driver.h7
-rw-r--r--drivers/media/video/ivtv/ivtv-irq.c22
-rw-r--r--drivers/media/video/ivtv/ivtv-yuv.c12
3 files changed, 31 insertions, 10 deletions
diff --git a/drivers/media/video/ivtv/ivtv-driver.h b/drivers/media/video/ivtv/ivtv-driver.h
index 6e53a1f04f7e..6c7c9a57a1ab 100644
--- a/drivers/media/video/ivtv/ivtv-driver.h
+++ b/drivers/media/video/ivtv/ivtv-driver.h
@@ -531,6 +531,7 @@ struct yuv_frame_info
531 u32 tru_w; 531 u32 tru_w;
532 u32 tru_h; 532 u32 tru_h;
533 u32 offset_y; 533 u32 offset_y;
534 int lace_mode;
534}; 535};
535 536
536#define IVTV_YUV_MODE_INTERLACED 0x00 537#define IVTV_YUV_MODE_INTERLACED 0x00
@@ -603,7 +604,6 @@ struct yuv_playback_info
603 int decode_height; 604 int decode_height;
604 605
605 int frame_interlaced; 606 int frame_interlaced;
606 int frame_interlaced_last;
607 607
608 int lace_mode; 608 int lace_mode;
609 int lace_threshold; 609 int lace_threshold;
@@ -614,6 +614,11 @@ struct yuv_playback_info
614 614
615 u32 yuv_forced_update; 615 u32 yuv_forced_update;
616 int update_frame; 616 int update_frame;
617
618 int sync_field[4]; /* Field to sync on */
619 int field_delay[4]; /* Flag to extend duration of previous frame */
620 u8 fields_lapsed; /* Counter used when delaying a frame */
621
617 struct yuv_frame_info new_frame_info[4]; 622 struct yuv_frame_info new_frame_info[4];
618 struct yuv_frame_info old_frame_info; 623 struct yuv_frame_info old_frame_info;
619 struct yuv_frame_info old_frame_info_args; 624 struct yuv_frame_info old_frame_info_args;
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
diff --git a/drivers/media/video/ivtv/ivtv-yuv.c b/drivers/media/video/ivtv/ivtv-yuv.c
index 5c94d3282c82..fa8c76f3d359 100644
--- a/drivers/media/video/ivtv/ivtv-yuv.c
+++ b/drivers/media/video/ivtv/ivtv-yuv.c
@@ -612,7 +612,6 @@ static void ivtv_yuv_handle_vertical(struct ivtv *itv, struct yuv_frame_info *wi
612 itv->yuv_info.v_filter_2 = v_filter_2; 612 itv->yuv_info.v_filter_2 = v_filter_2;
613 } 613 }
614 614
615 itv->yuv_info.frame_interlaced_last = itv->yuv_info.frame_interlaced;
616} 615}
617 616
618/* Modify the supplied coordinate information to fit the visible osd area */ 617/* Modify the supplied coordinate information to fit the visible osd area */
@@ -799,6 +798,7 @@ static u32 ivtv_yuv_window_setup (struct ivtv *itv, struct yuv_frame_info *windo
799 (itv->yuv_info.old_frame_info.src_y != window->src_y) || 798 (itv->yuv_info.old_frame_info.src_y != window->src_y) ||
800 (itv->yuv_info.old_frame_info.pan_y != window->pan_y) || 799 (itv->yuv_info.old_frame_info.pan_y != window->pan_y) ||
801 (itv->yuv_info.old_frame_info.vis_h != window->vis_h) || 800 (itv->yuv_info.old_frame_info.vis_h != window->vis_h) ||
801 (itv->yuv_info.old_frame_info.lace_mode != window->lace_mode) ||
802 (itv->yuv_info.old_frame_info.interlaced_y != window->interlaced_y) || 802 (itv->yuv_info.old_frame_info.interlaced_y != window->interlaced_y) ||
803 (itv->yuv_info.old_frame_info.interlaced_uv != window->interlaced_uv)) { 803 (itv->yuv_info.old_frame_info.interlaced_uv != window->interlaced_uv)) {
804 yuv_update |= IVTV_YUV_UPDATE_VERTICAL; 804 yuv_update |= IVTV_YUV_UPDATE_VERTICAL;
@@ -970,6 +970,9 @@ int ivtv_yuv_prep_frame(struct ivtv *itv, struct ivtv_dma_frame *args)
970 itv->yuv_info.new_frame_info[frame].tru_w = args->src_width; 970 itv->yuv_info.new_frame_info[frame].tru_w = args->src_width;
971 itv->yuv_info.new_frame_info[frame].tru_h = args->src_height; 971 itv->yuv_info.new_frame_info[frame].tru_h = args->src_height;
972 972
973 /* Snapshot field order */
974 itv->yuv_info.sync_field[frame] = itv->yuv_info.lace_sync_field;
975
973 /* Are we going to offset the Y plane */ 976 /* Are we going to offset the Y plane */
974 if (args->src.height + args->src.top < 512-16) 977 if (args->src.height + args->src.top < 512-16)
975 itv->yuv_info.new_frame_info[frame].offset_y = 1; 978 itv->yuv_info.new_frame_info[frame].offset_y = 1;
@@ -985,6 +988,7 @@ int ivtv_yuv_prep_frame(struct ivtv *itv, struct ivtv_dma_frame *args)
985 itv->yuv_info.new_frame_info[frame].update = 0; 988 itv->yuv_info.new_frame_info[frame].update = 0;
986 itv->yuv_info.new_frame_info[frame].interlaced_y = 0; 989 itv->yuv_info.new_frame_info[frame].interlaced_y = 0;
987 itv->yuv_info.new_frame_info[frame].interlaced_uv = 0; 990 itv->yuv_info.new_frame_info[frame].interlaced_uv = 0;
991 itv->yuv_info.new_frame_info[frame].lace_mode = itv->yuv_info.lace_mode;
988 992
989 if (memcmp (&itv->yuv_info.old_frame_info_args, &itv->yuv_info.new_frame_info[frame], 993 if (memcmp (&itv->yuv_info.old_frame_info_args, &itv->yuv_info.new_frame_info[frame],
990 sizeof (itv->yuv_info.new_frame_info[frame]))) { 994 sizeof (itv->yuv_info.new_frame_info[frame]))) {
@@ -995,6 +999,12 @@ int ivtv_yuv_prep_frame(struct ivtv *itv, struct ivtv_dma_frame *args)
995 999
996 itv->yuv_info.new_frame_info[frame].update |= register_update; 1000 itv->yuv_info.new_frame_info[frame].update |= register_update;
997 1001
1002 /* Should this frame be delayed ? */
1003 if (itv->yuv_info.sync_field[frame] != itv->yuv_info.sync_field[(frame - 1) & 3])
1004 itv->yuv_info.field_delay[frame] = 1;
1005 else
1006 itv->yuv_info.field_delay[frame] = 0;
1007
998 /* DMA the frame */ 1008 /* DMA the frame */
999 mutex_lock(&itv->udma.lock); 1009 mutex_lock(&itv->udma.lock);
1000 1010