diff options
author | Ian Armstrong <ian@iarmst.demon.co.uk> | 2007-10-20 13:52:55 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@infradead.org> | 2008-01-25 16:03:10 -0500 |
commit | a3e5f5e2dfb50bebca24329e5377d804c6e3eb1b (patch) | |
tree | 6a900057b715633c5b7951568253f35de2e0a24f /drivers/media/video/ivtv/ivtv-yuv.c | |
parent | c240ad00af78228726e6301ad6ffc54d3adce2a0 (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.c | 149 |
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 | ||
25 | const u32 yuv_offset[4] = { | 25 | /* YUV buffer offsets */ |
26 | IVTV_YUV_BUFFER_OFFSET, | 26 | const 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 | ||
32 | static int ivtv_yuv_prep_user_dma(struct ivtv *itv, struct ivtv_user_dma *dma, | 37 | static 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 | ||
957 | int ivtv_yuv_prep_frame(struct ivtv *itv, struct ivtv_dma_frame *args) | 961 | /* Get next available yuv buffer on PVR350 */ |
962 | void 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 */ | ||
985 | void 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 */ | ||
1044 | void 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 | |||
1050 | int 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; |