diff options
Diffstat (limited to 'drivers/media/video/ivtv')
-rw-r--r-- | drivers/media/video/ivtv/ivtv-driver.h | 7 | ||||
-rw-r--r-- | drivers/media/video/ivtv/ivtv-irq.c | 22 | ||||
-rw-r--r-- | drivers/media/video/ivtv/ivtv-yuv.c | 12 |
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 | ||