aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/ivtv
diff options
context:
space:
mode:
authorIan Armstrong <ian@iarmst.demon.co.uk>2007-10-22 13:24:26 -0400
committerMauro Carvalho Chehab <mchehab@infradead.org>2008-01-25 16:03:10 -0500
commit3b5c1c8e71eb8fe2297a5884db59108e3c8b44c5 (patch)
tree39161a925790139e733137c5114e4419d3e45983 /drivers/media/video/ivtv
parent406c8b0ff0891ace87440bcb298a91c1927f9ae5 (diff)
V4L/DVB (6716): ivtv: yuv interlace mode change
Interlace mode selection code moved into the frame setup phase, so it's now run before the frame is loaded into a hardware buffer. Given that it can affect how a new frame is displayed, it was a bit stupid running it after the frame was already visible. A few stray interlace related variables which were linked to individual frames have now been moved into the yuv_frame_info struct. This means that all variables linked to a specific frame are in the same place & not scattered. Minor code reformatting in areas touched by the above changes. 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.c19
-rw-r--r--drivers/media/video/ivtv/ivtv-yuv.c382
3 files changed, 199 insertions, 209 deletions
diff --git a/drivers/media/video/ivtv/ivtv-driver.h b/drivers/media/video/ivtv/ivtv-driver.h
index 12ff9382718d..0e4ad29821e0 100644
--- a/drivers/media/video/ivtv/ivtv-driver.h
+++ b/drivers/media/video/ivtv/ivtv-driver.h
@@ -392,6 +392,9 @@ struct yuv_frame_info
392 u32 tru_h; 392 u32 tru_h;
393 u32 offset_y; 393 u32 offset_y;
394 s32 lace_mode; 394 s32 lace_mode;
395 u32 sync_field;
396 u32 delay;
397 u32 interlaced;
395}; 398};
396 399
397#define IVTV_YUV_MODE_INTERLACED 0x00 400#define IVTV_YUV_MODE_INTERLACED 0x00
@@ -465,8 +468,6 @@ struct yuv_playback_info
465 468
466 int decode_height; 469 int decode_height;
467 470
468 int frame_interlaced;
469
470 int lace_mode; 471 int lace_mode;
471 int lace_threshold; 472 int lace_threshold;
472 int lace_sync_field; 473 int lace_sync_field;
@@ -477,8 +478,6 @@ struct yuv_playback_info
477 u32 yuv_forced_update; 478 u32 yuv_forced_update;
478 int update_frame; 479 int update_frame;
479 480
480 int sync_field[IVTV_YUV_BUFFERS]; /* Field to sync on */
481 int field_delay[IVTV_YUV_BUFFERS]; /* Flag to extend duration of previous frame */
482 u8 fields_lapsed; /* Counter used when delaying a frame */ 481 u8 fields_lapsed; /* Counter used when delaying a frame */
483 482
484 struct yuv_frame_info new_frame_info[IVTV_YUV_BUFFERS]; 483 struct yuv_frame_info new_frame_info[IVTV_YUV_BUFFERS];
diff --git a/drivers/media/video/ivtv/ivtv-irq.c b/drivers/media/video/ivtv/ivtv-irq.c
index 8c00d8f6d4d9..dd0dd8d126de 100644
--- a/drivers/media/video/ivtv/ivtv-irq.c
+++ b/drivers/media/video/ivtv/ivtv-irq.c
@@ -746,15 +746,16 @@ static void ivtv_irq_vsync(struct ivtv *itv)
746 unsigned int frame = read_reg(0x28c0) & 1; 746 unsigned int frame = read_reg(0x28c0) & 1;
747 struct yuv_playback_info *yi = &itv->yuv_info; 747 struct yuv_playback_info *yi = &itv->yuv_info;
748 int last_dma_frame = atomic_read(&itv->yuv_info.next_dma_frame); 748 int last_dma_frame = atomic_read(&itv->yuv_info.next_dma_frame);
749 struct yuv_frame_info *f = &yi->new_frame_info[last_dma_frame];
749 750
750 if (0) IVTV_DEBUG_IRQ("DEC VSYNC\n"); 751 if (0) IVTV_DEBUG_IRQ("DEC VSYNC\n");
751 752
752 if (((frame ^ yi->sync_field[last_dma_frame]) == 0 && 753 if (((frame ^ f->sync_field) == 0 &&
753 ((itv->last_vsync_field & 1) ^ yi->sync_field[last_dma_frame])) || 754 ((itv->last_vsync_field & 1) ^ f->sync_field)) ||
754 (frame != (itv->last_vsync_field & 1) && !yi->frame_interlaced)) { 755 (frame != (itv->last_vsync_field & 1) && !f->interlaced)) {
755 int next_dma_frame = last_dma_frame; 756 int next_dma_frame = last_dma_frame;
756 757
757 if (!(yi->frame_interlaced && yi->field_delay[next_dma_frame] && yi->fields_lapsed < 1)) { 758 if (!(f->interlaced && f->delay && yi->fields_lapsed < 1)) {
758 if (next_dma_frame >= 0 && next_dma_frame != atomic_read(&yi->next_fill_frame)) { 759 if (next_dma_frame >= 0 && next_dma_frame != atomic_read(&yi->next_fill_frame)) {
759 write_reg(yuv_offset[next_dma_frame] >> 4, 0x82c); 760 write_reg(yuv_offset[next_dma_frame] >> 4, 0x82c);
760 write_reg((yuv_offset[next_dma_frame] + IVTV_YUV_BUFFER_UV_OFFSET) >> 4, 0x830); 761 write_reg((yuv_offset[next_dma_frame] + IVTV_YUV_BUFFER_UV_OFFSET) >> 4, 0x830);
@@ -795,13 +796,15 @@ static void ivtv_irq_vsync(struct ivtv *itv)
795 } 796 }
796 797
797 /* Check if we need to update the yuv registers */ 798 /* Check if we need to update the yuv registers */
798 if ((yi->yuv_forced_update || yi->new_frame_info[last_dma_frame].update) && last_dma_frame != -1) { 799 if ((yi->yuv_forced_update || f->update) && last_dma_frame != -1) {
799 if (!yi->new_frame_info[last_dma_frame].update) 800 if (!f->update) {
800 last_dma_frame = (u8)(last_dma_frame - 1) % IVTV_YUV_BUFFERS; 801 last_dma_frame = (u8)(last_dma_frame - 1) % IVTV_YUV_BUFFERS;
802 f = &yi->new_frame_info[last_dma_frame];
803 }
801 804
802 if (yi->new_frame_info[last_dma_frame].src_w) { 805 if (f->src_w) {
803 yi->update_frame = last_dma_frame; 806 yi->update_frame = last_dma_frame;
804 yi->new_frame_info[last_dma_frame].update = 0; 807 f->update = 0;
805 yi->yuv_forced_update = 0; 808 yi->yuv_forced_update = 0;
806 set_bit(IVTV_F_I_WORK_HANDLER_YUV, &itv->i_flags); 809 set_bit(IVTV_F_I_WORK_HANDLER_YUV, &itv->i_flags);
807 set_bit(IVTV_F_I_HAVE_WORK, &itv->i_flags); 810 set_bit(IVTV_F_I_HAVE_WORK, &itv->i_flags);
diff --git a/drivers/media/video/ivtv/ivtv-yuv.c b/drivers/media/video/ivtv/ivtv-yuv.c
index a23108fae4fd..cd42db9b5a15 100644
--- a/drivers/media/video/ivtv/ivtv-yuv.c
+++ b/drivers/media/video/ivtv/ivtv-yuv.c
@@ -39,19 +39,20 @@ static int ivtv_yuv_prep_user_dma(struct ivtv *itv, struct ivtv_user_dma *dma,
39{ 39{
40 struct ivtv_dma_page_info y_dma; 40 struct ivtv_dma_page_info y_dma;
41 struct ivtv_dma_page_info uv_dma; 41 struct ivtv_dma_page_info uv_dma;
42 42 struct yuv_playback_info *yi = &itv->yuv_info;
43 u8 frame = yi->draw_frame;
44 struct yuv_frame_info *f = &yi->new_frame_info[frame];
43 int i; 45 int i;
44 int y_pages, uv_pages; 46 int y_pages, uv_pages;
45 u8 frame = itv->yuv_info.draw_frame;
46 unsigned long y_buffer_offset, uv_buffer_offset; 47 unsigned long y_buffer_offset, uv_buffer_offset;
47 int y_decode_height, uv_decode_height, y_size; 48 int y_decode_height, uv_decode_height, y_size;
48 49
49 y_buffer_offset = IVTV_DECODER_OFFSET + yuv_offset[frame]; 50 y_buffer_offset = IVTV_DECODER_OFFSET + yuv_offset[frame];
50 uv_buffer_offset = y_buffer_offset + IVTV_YUV_BUFFER_UV_OFFSET; 51 uv_buffer_offset = y_buffer_offset + IVTV_YUV_BUFFER_UV_OFFSET;
51 52
52 y_decode_height = uv_decode_height = args->src.height + args->src.top; 53 y_decode_height = uv_decode_height = f->src_h + f->src_x;
53 54
54 if (y_decode_height < 512-16) 55 if (f->offset_y)
55 y_buffer_offset += 720 * 16; 56 y_buffer_offset += 720 * 16;
56 57
57 if (y_decode_height & 15) 58 if (y_decode_height & 15)
@@ -106,13 +107,11 @@ static int ivtv_yuv_prep_user_dma(struct ivtv *itv, struct ivtv_user_dma *dma,
106 ivtv_udma_fill_sg_array (dma, y_buffer_offset, uv_buffer_offset, y_size); 107 ivtv_udma_fill_sg_array (dma, y_buffer_offset, uv_buffer_offset, y_size);
107 108
108 /* If we've offset the y plane, ensure top area is blanked */ 109 /* If we've offset the y plane, ensure top area is blanked */
109 if (args->src.height + args->src.top < 512-16) { 110 if (f->offset_y && itv->yuv_info.blanking_dmaptr) {
110 if (itv->yuv_info.blanking_dmaptr) { 111 dma->SGarray[dma->SG_length].size = cpu_to_le32(720*16);
111 dma->SGarray[dma->SG_length].size = cpu_to_le32(720*16); 112 dma->SGarray[dma->SG_length].src = cpu_to_le32(itv->yuv_info.blanking_dmaptr);
112 dma->SGarray[dma->SG_length].src = cpu_to_le32(itv->yuv_info.blanking_dmaptr); 113 dma->SGarray[dma->SG_length].dst = cpu_to_le32(IVTV_DECODER_OFFSET + yuv_offset[frame]);
113 dma->SGarray[dma->SG_length].dst = cpu_to_le32(IVTV_DECODER_OFFSET + yuv_offset[frame]); 114 dma->SG_length++;
114 dma->SG_length++;
115 }
116 } 115 }
117 116
118 /* Tag SG Array with Interrupt Bit */ 117 /* Tag SG Array with Interrupt Bit */
@@ -387,7 +386,7 @@ static void ivtv_yuv_handle_vertical(struct ivtv *itv, struct yuv_frame_info *wi
387 } 386 }
388 387
389 /* What is the source video being treated as... */ 388 /* What is the source video being treated as... */
390 if (itv->yuv_info.frame_interlaced) { 389 if (window->interlaced) {
391 IVTV_DEBUG_WARN("Source video: Interlaced\n"); 390 IVTV_DEBUG_WARN("Source video: Interlaced\n");
392 } 391 }
393 else { 392 else {
@@ -631,192 +630,142 @@ static void ivtv_yuv_handle_vertical(struct ivtv *itv, struct yuv_frame_info *wi
631} 630}
632 631
633/* Modify the supplied coordinate information to fit the visible osd area */ 632/* Modify the supplied coordinate information to fit the visible osd area */
634static u32 ivtv_yuv_window_setup (struct ivtv *itv, struct yuv_frame_info *window) 633static u32 ivtv_yuv_window_setup(struct ivtv *itv, struct yuv_frame_info *f)
635{ 634{
636 int osd_crop, lace_threshold; 635 struct yuv_frame_info *of = &itv->yuv_info.old_frame_info;
636 int osd_crop;
637 u32 osd_scale; 637 u32 osd_scale;
638 u32 yuv_update = 0; 638 u32 yuv_update = 0;
639 639
640 lace_threshold = itv->yuv_info.lace_threshold;
641 if (lace_threshold < 0)
642 lace_threshold = itv->yuv_info.decode_height - 1;
643
644 /* Work out the lace settings */
645 switch (itv->yuv_info.lace_mode) {
646 case IVTV_YUV_MODE_PROGRESSIVE: /* Progressive mode */
647 itv->yuv_info.frame_interlaced = 0;
648 if (window->tru_h < 512 || (window->tru_h > 576 && window->tru_h < 1021))
649 window->interlaced_y = 0;
650 else
651 window->interlaced_y = 1;
652
653 if (window->tru_h < 1021 && (window->dst_h >= window->src_h /2))
654 window->interlaced_uv = 0;
655 else
656 window->interlaced_uv = 1;
657 break;
658
659 case IVTV_YUV_MODE_AUTO:
660 if (window->tru_h <= lace_threshold || window->tru_h > 576 || window->tru_w > 720){
661 itv->yuv_info.frame_interlaced = 0;
662 if ((window->tru_h < 512) ||
663 (window->tru_h > 576 && window->tru_h < 1021) ||
664 (window->tru_w > 720 && window->tru_h < 1021))
665 window->interlaced_y = 0;
666 else
667 window->interlaced_y = 1;
668
669 if (window->tru_h < 1021 && (window->dst_h >= window->src_h /2))
670 window->interlaced_uv = 0;
671 else
672 window->interlaced_uv = 1;
673 }
674 else {
675 itv->yuv_info.frame_interlaced = 1;
676 window->interlaced_y = 1;
677 window->interlaced_uv = 1;
678 }
679 break;
680
681 case IVTV_YUV_MODE_INTERLACED: /* Interlace mode */
682 default:
683 itv->yuv_info.frame_interlaced = 1;
684 window->interlaced_y = 1;
685 window->interlaced_uv = 1;
686 break;
687 }
688
689 /* Sorry, but no negative coords for src */ 640 /* Sorry, but no negative coords for src */
690 if (window->src_x < 0) window->src_x = 0; 641 if (f->src_x < 0)
691 if (window->src_y < 0) window->src_y = 0; 642 f->src_x = 0;
643 if (f->src_y < 0)
644 f->src_y = 0;
692 645
693 /* Can only reduce width down to 1/4 original size */ 646 /* Can only reduce width down to 1/4 original size */
694 if ((osd_crop = window->src_w - ( 4 * window->dst_w )) > 0) { 647 if ((osd_crop = f->src_w - 4 * f->dst_w) > 0) {
695 window->src_x += osd_crop / 2; 648 f->src_x += osd_crop / 2;
696 window->src_w = (window->src_w - osd_crop) & ~3; 649 f->src_w = (f->src_w - osd_crop) & ~3;
697 window->dst_w = window->src_w / 4; 650 f->dst_w = f->src_w / 4;
698 window->dst_w += window->dst_w & 1; 651 f->dst_w += f->dst_w & 1;
699 } 652 }
700 653
701 /* Can only reduce height down to 1/4 original size */ 654 /* Can only reduce height down to 1/4 original size */
702 if (window->src_h / window->dst_h >= 2) { 655 if (f->src_h / f->dst_h >= 2) {
703 /* Overflow may be because we're running progressive, so force mode switch */ 656 /* Overflow may be because we're running progressive,
704 window->interlaced_y = 1; 657 so force mode switch */
658 f->interlaced_y = 1;
705 /* Make sure we're still within limits for interlace */ 659 /* Make sure we're still within limits for interlace */
706 if ((osd_crop = window->src_h - ( 4 * window->dst_h )) > 0) { 660 if ((osd_crop = f->src_h - 4 * f->dst_h) > 0) {
707 /* If we reach here we'll have to force the height. */ 661 /* If we reach here we'll have to force the height. */
708 window->src_y += osd_crop / 2; 662 f->src_y += osd_crop / 2;
709 window->src_h = (window->src_h - osd_crop) & ~3; 663 f->src_h = (f->src_h - osd_crop) & ~3;
710 window->dst_h = window->src_h / 4; 664 f->dst_h = f->src_h / 4;
711 window->dst_h += window->dst_h & 1; 665 f->dst_h += f->dst_h & 1;
712 } 666 }
713 } 667 }
714 668
715 /* If there's nothing to safe to display, we may as well stop now */ 669 /* If there's nothing to safe to display, we may as well stop now */
716 if ((int)window->dst_w <= 2 || (int)window->dst_h <= 2 || (int)window->src_w <= 2 || (int)window->src_h <= 2) { 670 if ((int)f->dst_w <= 2 || (int)f->dst_h <= 2 ||
671 (int)f->src_w <= 2 || (int)f->src_h <= 2) {
717 return IVTV_YUV_UPDATE_INVALID; 672 return IVTV_YUV_UPDATE_INVALID;
718 } 673 }
719 674
720 /* Ensure video remains inside OSD area */ 675 /* Ensure video remains inside OSD area */
721 osd_scale = (window->src_h << 16) / window->dst_h; 676 osd_scale = (f->src_h << 16) / f->dst_h;
722 677
723 if ((osd_crop = window->pan_y - window->dst_y) > 0) { 678 if ((osd_crop = f->pan_y - f->dst_y) > 0) {
724 /* Falls off the upper edge - crop */ 679 /* Falls off the upper edge - crop */
725 window->src_y += (osd_scale * osd_crop) >> 16; 680 f->src_y += (osd_scale * osd_crop) >> 16;
726 window->src_h -= (osd_scale * osd_crop) >> 16; 681 f->src_h -= (osd_scale * osd_crop) >> 16;
727 window->dst_h -= osd_crop; 682 f->dst_h -= osd_crop;
728 window->dst_y = 0; 683 f->dst_y = 0;
729 } 684 } else {
730 else { 685 f->dst_y -= f->pan_y;
731 window->dst_y -= window->pan_y;
732 } 686 }
733 687
734 if ((osd_crop = window->dst_h + window->dst_y - window->vis_h) > 0) { 688 if ((osd_crop = f->dst_h + f->dst_y - f->vis_h) > 0) {
735 /* Falls off the lower edge - crop */ 689 /* Falls off the lower edge - crop */
736 window->dst_h -= osd_crop; 690 f->dst_h -= osd_crop;
737 window->src_h -= (osd_scale * osd_crop) >> 16; 691 f->src_h -= (osd_scale * osd_crop) >> 16;
738 } 692 }
739 693
740 osd_scale = (window->src_w << 16) / window->dst_w; 694 osd_scale = (f->src_w << 16) / f->dst_w;
741 695
742 if ((osd_crop = window->pan_x - window->dst_x) > 0) { 696 if ((osd_crop = f->pan_x - f->dst_x) > 0) {
743 /* Fall off the left edge - crop */ 697 /* Fall off the left edge - crop */
744 window->src_x += (osd_scale * osd_crop) >> 16; 698 f->src_x += (osd_scale * osd_crop) >> 16;
745 window->src_w -= (osd_scale * osd_crop) >> 16; 699 f->src_w -= (osd_scale * osd_crop) >> 16;
746 window->dst_w -= osd_crop; 700 f->dst_w -= osd_crop;
747 window->dst_x = 0; 701 f->dst_x = 0;
748 } 702 } else {
749 else { 703 f->dst_x -= f->pan_x;
750 window->dst_x -= window->pan_x;
751 } 704 }
752 705
753 if ((osd_crop = window->dst_w + window->dst_x - window->vis_w) > 0) { 706 if ((osd_crop = f->dst_w + f->dst_x - f->vis_w) > 0) {
754 /* Falls off the right edge - crop */ 707 /* Falls off the right edge - crop */
755 window->dst_w -= osd_crop; 708 f->dst_w -= osd_crop;
756 window->src_w -= (osd_scale * osd_crop) >> 16; 709 f->src_w -= (osd_scale * osd_crop) >> 16;
757 } 710 }
758 711
759 /* The OSD can be moved. Track to it */ 712 /* The OSD can be moved. Track to it */
760 window->dst_x += itv->yuv_info.osd_x_offset; 713 f->dst_x += itv->yuv_info.osd_x_offset;
761 window->dst_y += itv->yuv_info.osd_y_offset; 714 f->dst_y += itv->yuv_info.osd_y_offset;
762 715
763 /* Width & height for both src & dst must be even. 716 /* Width & height for both src & dst must be even.
764 Same for coordinates. */ 717 Same for coordinates. */
765 window->dst_w &= ~1; 718 f->dst_w &= ~1;
766 window->dst_x &= ~1; 719 f->dst_x &= ~1;
767 720
768 window->src_w += window->src_x & 1; 721 f->src_w += f->src_x & 1;
769 window->src_x &= ~1; 722 f->src_x &= ~1;
770 723
771 window->src_w &= ~1; 724 f->src_w &= ~1;
772 window->dst_w &= ~1; 725 f->dst_w &= ~1;
773 726
774 window->dst_h &= ~1; 727 f->dst_h &= ~1;
775 window->dst_y &= ~1; 728 f->dst_y &= ~1;
776 729
777 window->src_h += window->src_y & 1; 730 f->src_h += f->src_y & 1;
778 window->src_y &= ~1; 731 f->src_y &= ~1;
779 732
780 window->src_h &= ~1; 733 f->src_h &= ~1;
781 window->dst_h &= ~1; 734 f->dst_h &= ~1;
782 735
783 /* Due to rounding, we may have reduced the output size to <1/4 of the source 736 /* Due to rounding, we may have reduced the output size to <1/4 of
784 Check again, but this time just resize. Don't change source coordinates */ 737 the source. Check again, but this time just resize. Don't change
785 if (window->dst_w < window->src_w / 4) { 738 source coordinates */
786 window->src_w &= ~3; 739 if (f->dst_w < f->src_w / 4) {
787 window->dst_w = window->src_w / 4; 740 f->src_w &= ~3;
788 window->dst_w += window->dst_w & 1; 741 f->dst_w = f->src_w / 4;
742 f->dst_w += f->dst_w & 1;
789 } 743 }
790 if (window->dst_h < window->src_h / 4) { 744 if (f->dst_h < f->src_h / 4) {
791 window->src_h &= ~3; 745 f->src_h &= ~3;
792 window->dst_h = window->src_h / 4; 746 f->dst_h = f->src_h / 4;
793 window->dst_h += window->dst_h & 1; 747 f->dst_h += f->dst_h & 1;
794 } 748 }
795 749
796 /* Check again. If there's nothing to safe to display, stop now */ 750 /* Check again. If there's nothing to safe to display, stop now */
797 if ((int)window->dst_w <= 2 || (int)window->dst_h <= 2 || (int)window->src_w <= 2 || (int)window->src_h <= 2) { 751 if ((int)f->dst_w <= 2 || (int)f->dst_h <= 2 ||
752 (int)f->src_w <= 2 || (int)f->src_h <= 2) {
798 return IVTV_YUV_UPDATE_INVALID; 753 return IVTV_YUV_UPDATE_INVALID;
799 } 754 }
800 755
801 /* Both x offset & width are linked, so they have to be done together */ 756 /* Both x offset & width are linked, so they have to be done together */
802 if ((itv->yuv_info.old_frame_info.dst_w != window->dst_w) || 757 if ((of->dst_w != f->dst_w) || (of->src_w != f->src_w) ||
803 (itv->yuv_info.old_frame_info.src_w != window->src_w) || 758 (of->dst_x != f->dst_x) || (of->src_x != f->src_x) ||
804 (itv->yuv_info.old_frame_info.dst_x != window->dst_x) || 759 (of->pan_x != f->pan_x) || (of->vis_w != f->vis_w)) {
805 (itv->yuv_info.old_frame_info.src_x != window->src_x) ||
806 (itv->yuv_info.old_frame_info.pan_x != window->pan_x) ||
807 (itv->yuv_info.old_frame_info.vis_w != window->vis_w)) {
808 yuv_update |= IVTV_YUV_UPDATE_HORIZONTAL; 760 yuv_update |= IVTV_YUV_UPDATE_HORIZONTAL;
809 } 761 }
810 762
811 if ((itv->yuv_info.old_frame_info.src_h != window->src_h) || 763 if ((of->src_h != f->src_h) || (of->dst_h != f->dst_h) ||
812 (itv->yuv_info.old_frame_info.dst_h != window->dst_h) || 764 (of->dst_y != f->dst_y) || (of->src_y != f->src_y) ||
813 (itv->yuv_info.old_frame_info.dst_y != window->dst_y) || 765 (of->pan_y != f->pan_y) || (of->vis_h != f->vis_h) ||
814 (itv->yuv_info.old_frame_info.src_y != window->src_y) || 766 (of->lace_mode != f->lace_mode) ||
815 (itv->yuv_info.old_frame_info.pan_y != window->pan_y) || 767 (of->interlaced_y != f->interlaced_y) ||
816 (itv->yuv_info.old_frame_info.vis_h != window->vis_h) || 768 (of->interlaced_uv != f->interlaced_uv)) {
817 (itv->yuv_info.old_frame_info.lace_mode != window->lace_mode) ||
818 (itv->yuv_info.old_frame_info.interlaced_y != window->interlaced_y) ||
819 (itv->yuv_info.old_frame_info.interlaced_uv != window->interlaced_uv)) {
820 yuv_update |= IVTV_YUV_UPDATE_VERTICAL; 769 yuv_update |= IVTV_YUV_UPDATE_VERTICAL;
821 } 770 }
822 771
@@ -826,22 +775,22 @@ static u32 ivtv_yuv_window_setup (struct ivtv *itv, struct yuv_frame_info *windo
826/* Update the scaling register to the requested value */ 775/* Update the scaling register to the requested value */
827void ivtv_yuv_work_handler (struct ivtv *itv) 776void ivtv_yuv_work_handler (struct ivtv *itv)
828{ 777{
829 struct yuv_frame_info window; 778 struct yuv_playback_info *yi = &itv->yuv_info;
779 struct yuv_frame_info f;
780 int frame = yi->update_frame;
830 u32 yuv_update; 781 u32 yuv_update;
831 782
832 int frame = itv->yuv_info.update_frame;
833
834/* IVTV_DEBUG_YUV("Update yuv registers for frame %d\n",frame); */ 783/* IVTV_DEBUG_YUV("Update yuv registers for frame %d\n",frame); */
835 memcpy(&window, &itv->yuv_info.new_frame_info[frame], sizeof (window)); 784 f = yi->new_frame_info[frame];
836 785
837 /* Update the osd pan info */ 786 /* Update the osd pan info */
838 window.pan_x = itv->yuv_info.osd_x_pan; 787 f.pan_x = itv->yuv_info.osd_x_pan;
839 window.pan_y = itv->yuv_info.osd_y_pan; 788 f.pan_y = itv->yuv_info.osd_y_pan;
840 window.vis_w = itv->yuv_info.osd_vis_w; 789 f.vis_w = itv->yuv_info.osd_vis_w;
841 window.vis_h = itv->yuv_info.osd_vis_h; 790 f.vis_h = itv->yuv_info.osd_vis_h;
842 791
843 /* Calculate the display window coordinates. Exit if nothing left */ 792 /* Calculate the display window coordinates. Exit if nothing left */
844 if (!(yuv_update = ivtv_yuv_window_setup (itv, &window))) 793 if (!(yuv_update = ivtv_yuv_window_setup (itv, &f)))
845 return; 794 return;
846 795
847 if (yuv_update & IVTV_YUV_UPDATE_INVALID) { 796 if (yuv_update & IVTV_YUV_UPDATE_INVALID) {
@@ -850,13 +799,12 @@ void ivtv_yuv_work_handler (struct ivtv *itv)
850 write_reg(0x00108080, 0x2898); 799 write_reg(0x00108080, 0x2898);
851 800
852 if (yuv_update & IVTV_YUV_UPDATE_HORIZONTAL) 801 if (yuv_update & IVTV_YUV_UPDATE_HORIZONTAL)
853 ivtv_yuv_handle_horizontal(itv, &window); 802 ivtv_yuv_handle_horizontal(itv, &f);
854 803
855 if (yuv_update & IVTV_YUV_UPDATE_VERTICAL) 804 if (yuv_update & IVTV_YUV_UPDATE_VERTICAL)
856 ivtv_yuv_handle_vertical(itv, &window); 805 ivtv_yuv_handle_vertical(itv, &f);
857 } 806 }
858 807 yi->old_frame_info = f;
859 memcpy(&itv->yuv_info.old_frame_info, &window, sizeof (itv->yuv_info.old_frame_info));
860} 808}
861 809
862static void ivtv_yuv_init (struct ivtv *itv) 810static void ivtv_yuv_init (struct ivtv *itv)
@@ -986,58 +934,98 @@ void ivtv_yuv_setup_frame(struct ivtv *itv, struct ivtv_dma_frame *args)
986{ 934{
987 struct yuv_playback_info *yi = &itv->yuv_info; 935 struct yuv_playback_info *yi = &itv->yuv_info;
988 u8 frame = yi->draw_frame; 936 u8 frame = yi->draw_frame;
937 u8 last_frame = (u8)(frame - 1) % IVTV_YUV_BUFFERS;
938 struct yuv_frame_info *nf = &yi->new_frame_info[frame];
939 struct yuv_frame_info *of = &yi->new_frame_info[last_frame];
940 int lace_threshold = yi->lace_threshold;
989 941
990 /* Preserve old update flag in case we're overwriting a queued frame */ 942 /* Preserve old update flag in case we're overwriting a queued frame */
991 int register_update = yi->new_frame_info[frame].update; 943 int update = nf->update;
992 944
993 /* Take a snapshot of the yuv coordinate information */ 945 /* Take a snapshot of the yuv coordinate information */
994 yi->new_frame_info[frame].src_x = args->src.left; 946 nf->src_x = args->src.left;
995 yi->new_frame_info[frame].src_y = args->src.top; 947 nf->src_y = args->src.top;
996 yi->new_frame_info[frame].src_w = args->src.width; 948 nf->src_w = args->src.width;
997 yi->new_frame_info[frame].src_h = args->src.height; 949 nf->src_h = args->src.height;
998 yi->new_frame_info[frame].dst_x = args->dst.left; 950 nf->dst_x = args->dst.left;
999 yi->new_frame_info[frame].dst_y = args->dst.top; 951 nf->dst_y = args->dst.top;
1000 yi->new_frame_info[frame].dst_w = args->dst.width; 952 nf->dst_w = args->dst.width;
1001 yi->new_frame_info[frame].dst_h = args->dst.height; 953 nf->dst_h = args->dst.height;
1002 yi->new_frame_info[frame].tru_x = args->dst.left; 954 nf->tru_x = args->dst.left;
1003 yi->new_frame_info[frame].tru_w = args->src_width; 955 nf->tru_w = args->src_width;
1004 yi->new_frame_info[frame].tru_h = args->src_height; 956 nf->tru_h = args->src_height;
1005
1006 /* Snapshot field order */
1007 yi->sync_field[frame] = yi->lace_sync_field;
1008 957
1009 /* Are we going to offset the Y plane */ 958 /* Are we going to offset the Y plane */
1010 if (args->src.height + args->src.top < 512-16) 959 nf->offset_y = (nf->tru_h + nf->src_x < 512 - 16) ? 1 : 0;
1011 yi->new_frame_info[frame].offset_y = 1;
1012 else
1013 yi->new_frame_info[frame].offset_y = 0;
1014 960
1015 /* Snapshot the osd pan info */ 961 /* Snapshot the osd pan info */
1016 yi->new_frame_info[frame].pan_x = yi->osd_x_pan; 962 nf->pan_x = yi->osd_x_pan;
1017 yi->new_frame_info[frame].pan_y = yi->osd_y_pan; 963 nf->pan_y = yi->osd_y_pan;
1018 yi->new_frame_info[frame].vis_w = yi->osd_vis_w; 964 nf->vis_w = yi->osd_vis_w;
1019 yi->new_frame_info[frame].vis_h = yi->osd_vis_h; 965 nf->vis_h = yi->osd_vis_h;
1020 966
1021 yi->new_frame_info[frame].update = 0; 967 nf->update = 0;
1022 yi->new_frame_info[frame].interlaced_y = 0; 968 nf->interlaced_y = 0;
1023 yi->new_frame_info[frame].interlaced_uv = 0; 969 nf->interlaced_uv = 0;
1024 yi->new_frame_info[frame].lace_mode = yi->lace_mode & IVTV_YUV_MODE_MASK; 970 nf->delay = 0;
1025 971 nf->sync_field = 0;
1026 if (memcmp(&yi->old_frame_info_args, &yi->new_frame_info[frame], 972 nf->lace_mode = yi->lace_mode & IVTV_YUV_MODE_MASK;
1027 sizeof(yi->new_frame_info[frame]))) { 973
1028 yi->old_frame_info_args = yi->new_frame_info[frame]; 974 if (lace_threshold < 0)
1029 yi->new_frame_info[frame].update = 1; 975 lace_threshold = yi->decode_height - 1;
1030/* IVTV_DEBUG_YUV ("Requesting register update for frame %d\n",frame); */ 976
977 /* Work out the lace settings */
978 switch (nf->lace_mode) {
979 case IVTV_YUV_MODE_PROGRESSIVE: /* Progressive mode */
980 nf->interlaced = 0;
981 if (nf->tru_h < 512 || (nf->tru_h > 576 && nf->tru_h < 1021))
982 nf->interlaced_y = 0;
983 else
984 nf->interlaced_y = 1;
985
986 if (nf->tru_h < 1021 && (nf->dst_h >= nf->src_h / 2))
987 nf->interlaced_uv = 0;
988 else
989 nf->interlaced_uv = 1;
990 break;
991
992 case IVTV_YUV_MODE_AUTO:
993 if (nf->tru_h <= lace_threshold || nf->tru_h > 576 || nf->tru_w > 720) {
994 nf->interlaced = 0;
995 if ((nf->tru_h < 512) ||
996 (nf->tru_h > 576 && nf->tru_h < 1021) ||
997 (nf->tru_w > 720 && nf->tru_h < 1021))
998 nf->interlaced_y = 0;
999 else
1000 nf->interlaced_y = 1;
1001 if (nf->tru_h < 1021 && (nf->dst_h >= nf->src_h / 2))
1002 nf->interlaced_uv = 0;
1003 else
1004 nf->interlaced_uv = 1;
1005 } else {
1006 nf->interlaced = 1;
1007 nf->interlaced_y = 1;
1008 nf->interlaced_uv = 1;
1009 }
1010 break;
1011
1012 case IVTV_YUV_MODE_INTERLACED: /* Interlace mode */
1013 default:
1014 nf->interlaced = 1;
1015 nf->interlaced_y = 1;
1016 nf->interlaced_uv = 1;
1017 break;
1031 } 1018 }
1032 1019
1033 yi->new_frame_info[frame].update |= register_update; 1020 if (memcmp(&yi->old_frame_info_args, nf, sizeof(*nf))) {
1021 yi->old_frame_info_args = *nf;
1022 nf->update = 1;
1023/* IVTV_DEBUG_YUV ("Requesting register update for frame %d\n",frame); */
1024 }
1034 1025
1035 /* Should this frame be delayed ? */ 1026 nf->update |= update;
1036 if (yi->sync_field[frame] != 1027 nf->sync_field = yi->lace_sync_field;
1037 yi->sync_field[(frame - 1) % IVTV_YUV_BUFFERS]) 1028 nf->delay = nf->sync_field != of->sync_field;
1038 yi->field_delay[frame] = 1;
1039 else
1040 yi->field_delay[frame] = 0;
1041} 1029}
1042 1030
1043/* Frame is complete & ready for display */ 1031/* Frame is complete & ready for display */