aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/ivtv
diff options
context:
space:
mode:
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