diff options
Diffstat (limited to 'drivers/media/video/ivtv/ivtv-yuv.c')
-rw-r--r-- | drivers/media/video/ivtv/ivtv-yuv.c | 382 |
1 files changed, 185 insertions, 197 deletions
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 */ |
634 | static u32 ivtv_yuv_window_setup (struct ivtv *itv, struct yuv_frame_info *window) | 633 | static 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 */ |
827 | void ivtv_yuv_work_handler (struct ivtv *itv) | 776 | void 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 | ||
862 | static void ivtv_yuv_init (struct ivtv *itv) | 810 | static 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 */ |