aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/ivtv/ivtv-yuv.c
diff options
context:
space:
mode:
authorIan Armstrong <ian@iarmst.demon.co.uk>2007-10-20 13:52:55 -0400
committerMauro Carvalho Chehab <mchehab@infradead.org>2008-01-25 16:03:10 -0500
commita3e5f5e2dfb50bebca24329e5377d804c6e3eb1b (patch)
tree6a900057b715633c5b7951568253f35de2e0a24f /drivers/media/video/ivtv/ivtv-yuv.c
parentc240ad00af78228726e6301ad6ffc54d3adce2a0 (diff)
V4L/DVB (6713): ivtv: ivtv_yuv_prep_frame breakup and yuv hardware buffer changes
ivtv_yuv_prep_frame is split in smaller code blocks. Modified yuv buffer handling on the PVR350 itself. We now cycle through all 8 hardware buffers. With this patch in place, driver behaviour should remain unchanged from the existing release. 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/ivtv-yuv.c')
-rw-r--r--drivers/media/video/ivtv/ivtv-yuv.c149
1 files changed, 91 insertions, 58 deletions
diff --git a/drivers/media/video/ivtv/ivtv-yuv.c b/drivers/media/video/ivtv/ivtv-yuv.c
index 9091c4837bbc..15e9bd2486d0 100644
--- a/drivers/media/video/ivtv/ivtv-yuv.c
+++ b/drivers/media/video/ivtv/ivtv-yuv.c
@@ -22,11 +22,16 @@
22#include "ivtv-udma.h" 22#include "ivtv-udma.h"
23#include "ivtv-yuv.h" 23#include "ivtv-yuv.h"
24 24
25const u32 yuv_offset[4] = { 25/* YUV buffer offsets */
26 IVTV_YUV_BUFFER_OFFSET, 26const u32 yuv_offset[IVTV_YUV_BUFFERS] = {
27 IVTV_YUV_BUFFER_OFFSET_1, 27 0x001a8600,
28 IVTV_YUV_BUFFER_OFFSET_2, 28 0x00240400,
29 IVTV_YUV_BUFFER_OFFSET_3 29 0x002d8200,
30 0x00370000,
31 0x00029000,
32 0x000C0E00,
33 0x006B0400,
34 0x00748200
30}; 35};
31 36
32static int ivtv_yuv_prep_user_dma(struct ivtv *itv, struct ivtv_user_dma *dma, 37static int ivtv_yuv_prep_user_dma(struct ivtv *itv, struct ivtv_user_dma *dma,
@@ -37,10 +42,9 @@ static int ivtv_yuv_prep_user_dma(struct ivtv *itv, struct ivtv_user_dma *dma,
37 42
38 int i; 43 int i;
39 int y_pages, uv_pages; 44 int y_pages, uv_pages;
40 45 u8 frame = itv->yuv_info.draw_frame;
41 unsigned long y_buffer_offset, uv_buffer_offset; 46 unsigned long y_buffer_offset, uv_buffer_offset;
42 int y_decode_height, uv_decode_height, y_size; 47 int y_decode_height, uv_decode_height, y_size;
43 int frame = atomic_read(&itv->yuv_info.next_fill_frame);
44 48
45 y_buffer_offset = IVTV_DECODER_OFFSET + yuv_offset[frame]; 49 y_buffer_offset = IVTV_DECODER_OFFSET + yuv_offset[frame];
46 uv_buffer_offset = y_buffer_offset + IVTV_YUV_BUFFER_UV_OFFSET; 50 uv_buffer_offset = y_buffer_offset + IVTV_YUV_BUFFER_UV_OFFSET;
@@ -954,76 +958,105 @@ static void ivtv_yuv_init (struct ivtv *itv)
954 atomic_set(&yi->next_dma_frame, 0); 958 atomic_set(&yi->next_dma_frame, 0);
955} 959}
956 960
957int ivtv_yuv_prep_frame(struct ivtv *itv, struct ivtv_dma_frame *args) 961/* Get next available yuv buffer on PVR350 */
962void ivtv_yuv_next_free(struct ivtv *itv)
958{ 963{
959 DEFINE_WAIT(wait); 964 int draw, display;
960 int rc = 0; 965 struct yuv_playback_info *yi = &itv->yuv_info;
961 int got_sig = 0;
962 int frame, next_fill_frame, last_fill_frame;
963 int register_update = 0;
964 966
965 IVTV_DEBUG_INFO("yuv_prep_frame\n"); 967 if (atomic_read(&yi->next_dma_frame) == -1)
968 ivtv_yuv_init(itv);
966 969
967 if (atomic_read(&itv->yuv_info.next_dma_frame) == -1) ivtv_yuv_init(itv); 970 draw = atomic_read(&yi->next_fill_frame);
971 display = atomic_read(&yi->next_dma_frame);
968 972
969 frame = atomic_read(&itv->yuv_info.next_fill_frame); 973 if (display > draw)
970 next_fill_frame = (frame + 1) & 0x3; 974 display -= IVTV_YUV_BUFFERS;
971 last_fill_frame = (atomic_read(&itv->yuv_info.next_dma_frame)+1) & 0x3;
972 975
973 if (next_fill_frame != last_fill_frame && last_fill_frame != frame) { 976 if (draw - display >= yi->max_frames_buffered)
974 /* Buffers are full - Overwrite the last frame */ 977 draw = (u8)(draw - 1) % IVTV_YUV_BUFFERS;
975 next_fill_frame = frame; 978 else
976 frame = (frame - 1) & 3; 979 yi->new_frame_info[draw].update = 0;
977 register_update = itv->yuv_info.new_frame_info[frame].update; 980
978 } 981 yi->draw_frame = draw;
982}
983
984/* Set up frame according to ivtv_dma_frame parameters */
985void ivtv_yuv_setup_frame(struct ivtv *itv, struct ivtv_dma_frame *args)
986{
987 struct yuv_playback_info *yi = &itv->yuv_info;
988 u8 frame = yi->draw_frame;
989
990 /* Preserve old update flag in case we're overwriting a queued frame */
991 int register_update = yi->new_frame_info[frame].update;
979 992
980 /* Take a snapshot of the yuv coordinate information */ 993 /* Take a snapshot of the yuv coordinate information */
981 itv->yuv_info.new_frame_info[frame].src_x = args->src.left; 994 yi->new_frame_info[frame].src_x = args->src.left;
982 itv->yuv_info.new_frame_info[frame].src_y = args->src.top; 995 yi->new_frame_info[frame].src_y = args->src.top;
983 itv->yuv_info.new_frame_info[frame].src_w = args->src.width; 996 yi->new_frame_info[frame].src_w = args->src.width;
984 itv->yuv_info.new_frame_info[frame].src_h = args->src.height; 997 yi->new_frame_info[frame].src_h = args->src.height;
985 itv->yuv_info.new_frame_info[frame].dst_x = args->dst.left; 998 yi->new_frame_info[frame].dst_x = args->dst.left;
986 itv->yuv_info.new_frame_info[frame].dst_y = args->dst.top; 999 yi->new_frame_info[frame].dst_y = args->dst.top;
987 itv->yuv_info.new_frame_info[frame].dst_w = args->dst.width; 1000 yi->new_frame_info[frame].dst_w = args->dst.width;
988 itv->yuv_info.new_frame_info[frame].dst_h = args->dst.height; 1001 yi->new_frame_info[frame].dst_h = args->dst.height;
989 itv->yuv_info.new_frame_info[frame].tru_x = args->dst.left; 1002 yi->new_frame_info[frame].tru_x = args->dst.left;
990 itv->yuv_info.new_frame_info[frame].tru_w = args->src_width; 1003 yi->new_frame_info[frame].tru_w = args->src_width;
991 itv->yuv_info.new_frame_info[frame].tru_h = args->src_height; 1004 yi->new_frame_info[frame].tru_h = args->src_height;
992 1005
993 /* Snapshot field order */ 1006 /* Snapshot field order */
994 itv->yuv_info.sync_field[frame] = itv->yuv_info.lace_sync_field; 1007 yi->sync_field[frame] = yi->lace_sync_field;
995 1008
996 /* Are we going to offset the Y plane */ 1009 /* Are we going to offset the Y plane */
997 if (args->src.height + args->src.top < 512-16) 1010 if (args->src.height + args->src.top < 512-16)
998 itv->yuv_info.new_frame_info[frame].offset_y = 1; 1011 yi->new_frame_info[frame].offset_y = 1;
999 else 1012 else
1000 itv->yuv_info.new_frame_info[frame].offset_y = 0; 1013 yi->new_frame_info[frame].offset_y = 0;
1001 1014
1002 /* Snapshot the osd pan info */ 1015 /* Snapshot the osd pan info */
1003 itv->yuv_info.new_frame_info[frame].pan_x = itv->yuv_info.osd_x_pan; 1016 yi->new_frame_info[frame].pan_x = yi->osd_x_pan;
1004 itv->yuv_info.new_frame_info[frame].pan_y = itv->yuv_info.osd_y_pan; 1017 yi->new_frame_info[frame].pan_y = yi->osd_y_pan;
1005 itv->yuv_info.new_frame_info[frame].vis_w = itv->yuv_info.osd_vis_w; 1018 yi->new_frame_info[frame].vis_w = yi->osd_vis_w;
1006 itv->yuv_info.new_frame_info[frame].vis_h = itv->yuv_info.osd_vis_h; 1019 yi->new_frame_info[frame].vis_h = yi->osd_vis_h;
1007 1020
1008 itv->yuv_info.new_frame_info[frame].update = 0; 1021 yi->new_frame_info[frame].update = 0;
1009 itv->yuv_info.new_frame_info[frame].interlaced_y = 0; 1022 yi->new_frame_info[frame].interlaced_y = 0;
1010 itv->yuv_info.new_frame_info[frame].interlaced_uv = 0; 1023 yi->new_frame_info[frame].interlaced_uv = 0;
1011 itv->yuv_info.new_frame_info[frame].lace_mode = itv->yuv_info.lace_mode; 1024 yi->new_frame_info[frame].lace_mode = yi->lace_mode;
1012 1025
1013 if (memcmp (&itv->yuv_info.old_frame_info_args, &itv->yuv_info.new_frame_info[frame], 1026 if (memcmp(&yi->old_frame_info_args, &yi->new_frame_info[frame],
1014 sizeof (itv->yuv_info.new_frame_info[frame]))) { 1027 sizeof(yi->new_frame_info[frame]))) {
1015 memcpy(&itv->yuv_info.old_frame_info_args, &itv->yuv_info.new_frame_info[frame], sizeof (itv->yuv_info.old_frame_info_args)); 1028 yi->old_frame_info_args = yi->new_frame_info[frame];
1016 itv->yuv_info.new_frame_info[frame].update = 1; 1029 yi->new_frame_info[frame].update = 1;
1017/* IVTV_DEBUG_YUV ("Requesting register update for frame %d\n",frame); */ 1030/* IVTV_DEBUG_YUV ("Requesting register update for frame %d\n",frame); */
1018 } 1031 }
1019 1032
1020 itv->yuv_info.new_frame_info[frame].update |= register_update; 1033 yi->new_frame_info[frame].update |= register_update;
1021 1034
1022 /* Should this frame be delayed ? */ 1035 /* Should this frame be delayed ? */
1023 if (itv->yuv_info.sync_field[frame] != itv->yuv_info.sync_field[(frame - 1) & 3]) 1036 if (yi->sync_field[frame] !=
1024 itv->yuv_info.field_delay[frame] = 1; 1037 yi->sync_field[(frame - 1) % IVTV_YUV_BUFFERS])
1038 yi->field_delay[frame] = 1;
1025 else 1039 else
1026 itv->yuv_info.field_delay[frame] = 0; 1040 yi->field_delay[frame] = 0;
1041}
1042
1043/* Frame is complete & ready for display */
1044void ivtv_yuv_frame_complete(struct ivtv *itv)
1045{
1046 atomic_set(&itv->yuv_info.next_fill_frame,
1047 (itv->yuv_info.draw_frame + 1) % IVTV_YUV_BUFFERS);
1048}
1049
1050int ivtv_yuv_prep_frame(struct ivtv *itv, struct ivtv_dma_frame *args)
1051{
1052 DEFINE_WAIT(wait);
1053 int rc = 0;
1054 int got_sig = 0;
1055
1056 IVTV_DEBUG_INFO("yuv_prep_frame\n");
1057
1058 ivtv_yuv_next_free(itv);
1059 ivtv_yuv_setup_frame(itv, args);
1027 1060
1028 /* DMA the frame */ 1061 /* DMA the frame */
1029 mutex_lock(&itv->udma.lock); 1062 mutex_lock(&itv->udma.lock);
@@ -1057,7 +1090,7 @@ int ivtv_yuv_prep_frame(struct ivtv *itv, struct ivtv_dma_frame *args)
1057 return -EINTR; 1090 return -EINTR;
1058 } 1091 }
1059 1092
1060 atomic_set(&itv->yuv_info.next_fill_frame, next_fill_frame); 1093 ivtv_yuv_frame_complete(itv);
1061 1094
1062 mutex_unlock(&itv->udma.lock); 1095 mutex_unlock(&itv->udma.lock);
1063 return rc; 1096 return rc;