aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/ivtv/ivtv-yuv.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/ivtv/ivtv-yuv.c')
-rw-r--r--drivers/media/video/ivtv/ivtv-yuv.c55
1 files changed, 47 insertions, 8 deletions
diff --git a/drivers/media/video/ivtv/ivtv-yuv.c b/drivers/media/video/ivtv/ivtv-yuv.c
index bcea09542e5a..e2288f224ab6 100644
--- a/drivers/media/video/ivtv/ivtv-yuv.c
+++ b/drivers/media/video/ivtv/ivtv-yuv.c
@@ -19,11 +19,16 @@
19 */ 19 */
20 20
21#include "ivtv-driver.h" 21#include "ivtv-driver.h"
22#include "ivtv-queue.h"
23#include "ivtv-udma.h" 22#include "ivtv-udma.h"
24#include "ivtv-irq.h"
25#include "ivtv-yuv.h" 23#include "ivtv-yuv.h"
26 24
25const u32 yuv_offset[4] = {
26 IVTV_YUV_BUFFER_OFFSET,
27 IVTV_YUV_BUFFER_OFFSET_1,
28 IVTV_YUV_BUFFER_OFFSET_2,
29 IVTV_YUV_BUFFER_OFFSET_3
30};
31
27static int ivtv_yuv_prep_user_dma(struct ivtv *itv, struct ivtv_user_dma *dma, 32static int ivtv_yuv_prep_user_dma(struct ivtv *itv, struct ivtv_user_dma *dma,
28 struct ivtv_dma_frame *args) 33 struct ivtv_dma_frame *args)
29{ 34{
@@ -37,7 +42,7 @@ static int ivtv_yuv_prep_user_dma(struct ivtv *itv, struct ivtv_user_dma *dma,
37 int y_decode_height, uv_decode_height, y_size; 42 int y_decode_height, uv_decode_height, y_size;
38 int frame = atomic_read(&itv->yuv_info.next_fill_frame); 43 int frame = atomic_read(&itv->yuv_info.next_fill_frame);
39 44
40 y_buffer_offset = IVTV_DEC_MEM_START + yuv_offset[frame]; 45 y_buffer_offset = IVTV_DECODER_OFFSET + yuv_offset[frame];
41 uv_buffer_offset = y_buffer_offset + IVTV_YUV_BUFFER_UV_OFFSET; 46 uv_buffer_offset = y_buffer_offset + IVTV_YUV_BUFFER_UV_OFFSET;
42 47
43 y_decode_height = uv_decode_height = args->src.height + args->src.top; 48 y_decode_height = uv_decode_height = args->src.height + args->src.top;
@@ -83,7 +88,14 @@ static int ivtv_yuv_prep_user_dma(struct ivtv *itv, struct ivtv_user_dma *dma,
83 } 88 }
84 89
85 /* Fill & map SG List */ 90 /* Fill & map SG List */
86 ivtv_udma_fill_sg_list (dma, &uv_dma, ivtv_udma_fill_sg_list (dma, &y_dma, 0)); 91 if (ivtv_udma_fill_sg_list (dma, &uv_dma, ivtv_udma_fill_sg_list (dma, &y_dma, 0)) < 0) {
92 IVTV_DEBUG_WARN("could not allocate bounce buffers for highmem userspace buffers\n");
93 for (i = 0; i < dma->page_count; i++) {
94 put_page(dma->map[i]);
95 }
96 dma->page_count = 0;
97 return -ENOMEM;
98 }
87 dma->SG_length = pci_map_sg(itv->dev, dma->SGlist, dma->page_count, PCI_DMA_TODEVICE); 99 dma->SG_length = pci_map_sg(itv->dev, dma->SGlist, dma->page_count, PCI_DMA_TODEVICE);
88 100
89 /* Fill SG Array with new values */ 101 /* Fill SG Array with new values */
@@ -94,7 +106,7 @@ static int ivtv_yuv_prep_user_dma(struct ivtv *itv, struct ivtv_user_dma *dma,
94 if (itv->yuv_info.blanking_dmaptr) { 106 if (itv->yuv_info.blanking_dmaptr) {
95 dma->SGarray[dma->SG_length].size = cpu_to_le32(720*16); 107 dma->SGarray[dma->SG_length].size = cpu_to_le32(720*16);
96 dma->SGarray[dma->SG_length].src = cpu_to_le32(itv->yuv_info.blanking_dmaptr); 108 dma->SGarray[dma->SG_length].src = cpu_to_le32(itv->yuv_info.blanking_dmaptr);
97 dma->SGarray[dma->SG_length].dst = cpu_to_le32(IVTV_DEC_MEM_START + yuv_offset[frame]); 109 dma->SGarray[dma->SG_length].dst = cpu_to_le32(IVTV_DECODER_OFFSET + yuv_offset[frame]);
98 dma->SG_length++; 110 dma->SG_length++;
99 } 111 }
100 } 112 }
@@ -612,7 +624,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; 624 itv->yuv_info.v_filter_2 = v_filter_2;
613 } 625 }
614 626
615 itv->yuv_info.frame_interlaced_last = itv->yuv_info.frame_interlaced;
616} 627}
617 628
618/* Modify the supplied coordinate information to fit the visible osd area */ 629/* Modify the supplied coordinate information to fit the visible osd area */
@@ -799,6 +810,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) || 810 (itv->yuv_info.old_frame_info.src_y != window->src_y) ||
800 (itv->yuv_info.old_frame_info.pan_y != window->pan_y) || 811 (itv->yuv_info.old_frame_info.pan_y != window->pan_y) ||
801 (itv->yuv_info.old_frame_info.vis_h != window->vis_h) || 812 (itv->yuv_info.old_frame_info.vis_h != window->vis_h) ||
813 (itv->yuv_info.old_frame_info.lace_mode != window->lace_mode) ||
802 (itv->yuv_info.old_frame_info.interlaced_y != window->interlaced_y) || 814 (itv->yuv_info.old_frame_info.interlaced_y != window->interlaced_y) ||
803 (itv->yuv_info.old_frame_info.interlaced_uv != window->interlaced_uv)) { 815 (itv->yuv_info.old_frame_info.interlaced_uv != window->interlaced_uv)) {
804 yuv_update |= IVTV_YUV_UPDATE_VERTICAL; 816 yuv_update |= IVTV_YUV_UPDATE_VERTICAL;
@@ -898,8 +910,21 @@ static void ivtv_yuv_init (struct ivtv *itv)
898 itv->yuv_info.decode_height = 480; 910 itv->yuv_info.decode_height = 480;
899 911
900 /* If no visible size set, assume full size */ 912 /* If no visible size set, assume full size */
901 if (!itv->yuv_info.osd_vis_w) itv->yuv_info.osd_vis_w = 720 - itv->yuv_info.osd_x_offset; 913 if (!itv->yuv_info.osd_vis_w)
902 if (!itv->yuv_info.osd_vis_h) itv->yuv_info.osd_vis_h = itv->yuv_info.decode_height - itv->yuv_info.osd_y_offset; 914 itv->yuv_info.osd_vis_w = 720 - itv->yuv_info.osd_x_offset;
915
916 if (!itv->yuv_info.osd_vis_h) {
917 itv->yuv_info.osd_vis_h = itv->yuv_info.decode_height - itv->yuv_info.osd_y_offset;
918 } else {
919 /* If output video standard has changed, requested height may
920 not be legal */
921 if (itv->yuv_info.osd_vis_h + itv->yuv_info.osd_y_offset > itv->yuv_info.decode_height) {
922 IVTV_DEBUG_WARN("Clipping yuv output - fb size (%d) exceeds video standard limit (%d)\n",
923 itv->yuv_info.osd_vis_h + itv->yuv_info.osd_y_offset,
924 itv->yuv_info.decode_height);
925 itv->yuv_info.osd_vis_h = itv->yuv_info.decode_height - itv->yuv_info.osd_y_offset;
926 }
927 }
903 928
904 /* We need a buffer for blanking when Y plane is offset - non-fatal if we can't get one */ 929 /* We need a buffer for blanking when Y plane is offset - non-fatal if we can't get one */
905 itv->yuv_info.blanking_ptr = kzalloc(720*16,GFP_KERNEL); 930 itv->yuv_info.blanking_ptr = kzalloc(720*16,GFP_KERNEL);
@@ -927,6 +952,7 @@ int ivtv_yuv_prep_frame(struct ivtv *itv, struct ivtv_dma_frame *args)
927 int rc = 0; 952 int rc = 0;
928 int got_sig = 0; 953 int got_sig = 0;
929 int frame, next_fill_frame, last_fill_frame; 954 int frame, next_fill_frame, last_fill_frame;
955 int register_update = 0;
930 956
931 IVTV_DEBUG_INFO("yuv_prep_frame\n"); 957 IVTV_DEBUG_INFO("yuv_prep_frame\n");
932 958
@@ -940,6 +966,7 @@ int ivtv_yuv_prep_frame(struct ivtv *itv, struct ivtv_dma_frame *args)
940 /* Buffers are full - Overwrite the last frame */ 966 /* Buffers are full - Overwrite the last frame */
941 next_fill_frame = frame; 967 next_fill_frame = frame;
942 frame = (frame - 1) & 3; 968 frame = (frame - 1) & 3;
969 register_update = itv->yuv_info.new_frame_info[frame].update;
943 } 970 }
944 971
945 /* Take a snapshot of the yuv coordinate information */ 972 /* Take a snapshot of the yuv coordinate information */
@@ -955,6 +982,9 @@ int ivtv_yuv_prep_frame(struct ivtv *itv, struct ivtv_dma_frame *args)
955 itv->yuv_info.new_frame_info[frame].tru_w = args->src_width; 982 itv->yuv_info.new_frame_info[frame].tru_w = args->src_width;
956 itv->yuv_info.new_frame_info[frame].tru_h = args->src_height; 983 itv->yuv_info.new_frame_info[frame].tru_h = args->src_height;
957 984
985 /* Snapshot field order */
986 itv->yuv_info.sync_field[frame] = itv->yuv_info.lace_sync_field;
987
958 /* Are we going to offset the Y plane */ 988 /* Are we going to offset the Y plane */
959 if (args->src.height + args->src.top < 512-16) 989 if (args->src.height + args->src.top < 512-16)
960 itv->yuv_info.new_frame_info[frame].offset_y = 1; 990 itv->yuv_info.new_frame_info[frame].offset_y = 1;
@@ -970,6 +1000,7 @@ int ivtv_yuv_prep_frame(struct ivtv *itv, struct ivtv_dma_frame *args)
970 itv->yuv_info.new_frame_info[frame].update = 0; 1000 itv->yuv_info.new_frame_info[frame].update = 0;
971 itv->yuv_info.new_frame_info[frame].interlaced_y = 0; 1001 itv->yuv_info.new_frame_info[frame].interlaced_y = 0;
972 itv->yuv_info.new_frame_info[frame].interlaced_uv = 0; 1002 itv->yuv_info.new_frame_info[frame].interlaced_uv = 0;
1003 itv->yuv_info.new_frame_info[frame].lace_mode = itv->yuv_info.lace_mode;
973 1004
974 if (memcmp (&itv->yuv_info.old_frame_info_args, &itv->yuv_info.new_frame_info[frame], 1005 if (memcmp (&itv->yuv_info.old_frame_info_args, &itv->yuv_info.new_frame_info[frame],
975 sizeof (itv->yuv_info.new_frame_info[frame]))) { 1006 sizeof (itv->yuv_info.new_frame_info[frame]))) {
@@ -978,6 +1009,14 @@ int ivtv_yuv_prep_frame(struct ivtv *itv, struct ivtv_dma_frame *args)
978/* IVTV_DEBUG_YUV ("Requesting register update for frame %d\n",frame); */ 1009/* IVTV_DEBUG_YUV ("Requesting register update for frame %d\n",frame); */
979 } 1010 }
980 1011
1012 itv->yuv_info.new_frame_info[frame].update |= register_update;
1013
1014 /* Should this frame be delayed ? */
1015 if (itv->yuv_info.sync_field[frame] != itv->yuv_info.sync_field[(frame - 1) & 3])
1016 itv->yuv_info.field_delay[frame] = 1;
1017 else
1018 itv->yuv_info.field_delay[frame] = 0;
1019
981 /* DMA the frame */ 1020 /* DMA the frame */
982 mutex_lock(&itv->udma.lock); 1021 mutex_lock(&itv->udma.lock);
983 1022