aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/media/video/ivtv/ivtv-driver.c1
-rw-r--r--drivers/media/video/ivtv/ivtv-driver.h11
-rw-r--r--drivers/media/video/ivtv/ivtv-irq.c31
-rw-r--r--drivers/media/video/ivtv/ivtv-yuv.c149
-rw-r--r--drivers/media/video/ivtv/ivtv-yuv.h7
5 files changed, 117 insertions, 82 deletions
diff --git a/drivers/media/video/ivtv/ivtv-driver.c b/drivers/media/video/ivtv/ivtv-driver.c
index 48db22cc1bd8..e3020f456641 100644
--- a/drivers/media/video/ivtv/ivtv-driver.c
+++ b/drivers/media/video/ivtv/ivtv-driver.c
@@ -697,6 +697,7 @@ static int __devinit ivtv_init_struct1(struct ivtv *itv)
697 atomic_set(&itv->yuv_info.next_dma_frame, -1); 697 atomic_set(&itv->yuv_info.next_dma_frame, -1);
698 itv->yuv_info.lace_mode = ivtv_yuv_mode; 698 itv->yuv_info.lace_mode = ivtv_yuv_mode;
699 itv->yuv_info.lace_threshold = ivtv_yuv_threshold; 699 itv->yuv_info.lace_threshold = ivtv_yuv_threshold;
700 itv->yuv_info.max_frames_buffered = 3;
700 return 0; 701 return 0;
701} 702}
702 703
diff --git a/drivers/media/video/ivtv/ivtv-driver.h b/drivers/media/video/ivtv/ivtv-driver.h
index b6dd2360e610..12ff9382718d 100644
--- a/drivers/media/video/ivtv/ivtv-driver.h
+++ b/drivers/media/video/ivtv/ivtv-driver.h
@@ -403,6 +403,8 @@ struct yuv_frame_info
403#define IVTV_YUV_SYNC_ODD 0x04 403#define IVTV_YUV_SYNC_ODD 0x04
404#define IVTV_YUV_SYNC_MASK 0x04 404#define IVTV_YUV_SYNC_MASK 0x04
405 405
406#define IVTV_YUV_BUFFERS 8
407
406struct yuv_playback_info 408struct yuv_playback_info
407{ 409{
408 u32 reg_2834; 410 u32 reg_2834;
@@ -475,11 +477,11 @@ struct yuv_playback_info
475 u32 yuv_forced_update; 477 u32 yuv_forced_update;
476 int update_frame; 478 int update_frame;
477 479
478 int sync_field[4]; /* Field to sync on */ 480 int sync_field[IVTV_YUV_BUFFERS]; /* Field to sync on */
479 int field_delay[4]; /* Flag to extend duration of previous frame */ 481 int field_delay[IVTV_YUV_BUFFERS]; /* Flag to extend duration of previous frame */
480 u8 fields_lapsed; /* Counter used when delaying a frame */ 482 u8 fields_lapsed; /* Counter used when delaying a frame */
481 483
482 struct yuv_frame_info new_frame_info[4]; 484 struct yuv_frame_info new_frame_info[IVTV_YUV_BUFFERS];
483 struct yuv_frame_info old_frame_info; 485 struct yuv_frame_info old_frame_info;
484 struct yuv_frame_info old_frame_info_args; 486 struct yuv_frame_info old_frame_info_args;
485 487
@@ -487,6 +489,9 @@ struct yuv_playback_info
487 dma_addr_t blanking_dmaptr; 489 dma_addr_t blanking_dmaptr;
488 490
489 int stream_size; 491 int stream_size;
492
493 u8 draw_frame; /* PVR350 buffer to draw into */
494 u8 max_frames_buffered; /* Maximum number of frames to buffer */
490}; 495};
491 496
492#define IVTV_VBI_FRAMES 32 497#define IVTV_VBI_FRAMES 32
diff --git a/drivers/media/video/ivtv/ivtv-irq.c b/drivers/media/video/ivtv/ivtv-irq.c
index bcf1c85991af..fc8eac09584c 100644
--- a/drivers/media/video/ivtv/ivtv-irq.c
+++ b/drivers/media/video/ivtv/ivtv-irq.c
@@ -744,24 +744,25 @@ static void ivtv_irq_vsync(struct ivtv *itv)
744 * one vsync per frame. 744 * one vsync per frame.
745 */ 745 */
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 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);
748 749
749 if (0) IVTV_DEBUG_IRQ("DEC VSYNC\n"); 750 if (0) IVTV_DEBUG_IRQ("DEC VSYNC\n");
750 751
751 if (((frame ^ itv->yuv_info.sync_field[last_dma_frame]) == 0 && 752 if (((frame ^ yi->sync_field[last_dma_frame]) == 0 &&
752 ((itv->last_vsync_field & 1) ^ itv->yuv_info.sync_field[last_dma_frame])) || 753 ((itv->last_vsync_field & 1) ^ yi->sync_field[last_dma_frame])) ||
753 (frame != (itv->last_vsync_field & 1) && !itv->yuv_info.frame_interlaced)) { 754 (frame != (itv->last_vsync_field & 1) && !yi->frame_interlaced)) {
754 int next_dma_frame = last_dma_frame; 755 int next_dma_frame = last_dma_frame;
755 756
756 if (!(itv->yuv_info.frame_interlaced && itv->yuv_info.field_delay[next_dma_frame] && itv->yuv_info.fields_lapsed < 1)) { 757 if (!(yi->frame_interlaced && yi->field_delay[next_dma_frame] && yi->fields_lapsed < 1)) {
757 if (next_dma_frame >= 0 && next_dma_frame != atomic_read(&itv->yuv_info.next_fill_frame)) { 758 if (next_dma_frame >= 0 && next_dma_frame != atomic_read(&yi->next_fill_frame)) {
758 write_reg(yuv_offset[next_dma_frame] >> 4, 0x82c); 759 write_reg(yuv_offset[next_dma_frame] >> 4, 0x82c);
759 write_reg((yuv_offset[next_dma_frame] + IVTV_YUV_BUFFER_UV_OFFSET) >> 4, 0x830); 760 write_reg((yuv_offset[next_dma_frame] + IVTV_YUV_BUFFER_UV_OFFSET) >> 4, 0x830);
760 write_reg(yuv_offset[next_dma_frame] >> 4, 0x834); 761 write_reg(yuv_offset[next_dma_frame] >> 4, 0x834);
761 write_reg((yuv_offset[next_dma_frame] + IVTV_YUV_BUFFER_UV_OFFSET) >> 4, 0x838); 762 write_reg((yuv_offset[next_dma_frame] + IVTV_YUV_BUFFER_UV_OFFSET) >> 4, 0x838);
762 next_dma_frame = (next_dma_frame + 1) & 0x3; 763 next_dma_frame = (next_dma_frame + 1) % IVTV_YUV_BUFFERS;
763 atomic_set(&itv->yuv_info.next_dma_frame, next_dma_frame); 764 atomic_set(&yi->next_dma_frame, next_dma_frame);
764 itv->yuv_info.fields_lapsed = -1; 765 yi->fields_lapsed = -1;
765 } 766 }
766 } 767 }
767 } 768 }
@@ -794,20 +795,20 @@ static void ivtv_irq_vsync(struct ivtv *itv)
794 } 795 }
795 796
796 /* Check if we need to update the yuv registers */ 797 /* Check if we need to update the yuv registers */
797 if ((itv->yuv_info.yuv_forced_update || itv->yuv_info.new_frame_info[last_dma_frame].update) && last_dma_frame != -1) { 798 if ((yi->yuv_forced_update || yi->new_frame_info[last_dma_frame].update) && last_dma_frame != -1) {
798 if (!itv->yuv_info.new_frame_info[last_dma_frame].update) 799 if (!yi->new_frame_info[last_dma_frame].update)
799 last_dma_frame = (last_dma_frame - 1) & 3; 800 last_dma_frame = (last_dma_frame - 1) & 3;
800 801
801 if (itv->yuv_info.new_frame_info[last_dma_frame].src_w) { 802 if (yi->new_frame_info[last_dma_frame].src_w) {
802 itv->yuv_info.update_frame = last_dma_frame; 803 yi->update_frame = last_dma_frame;
803 itv->yuv_info.new_frame_info[last_dma_frame].update = 0; 804 yi->new_frame_info[last_dma_frame].update = 0;
804 itv->yuv_info.yuv_forced_update = 0; 805 yi->yuv_forced_update = 0;
805 set_bit(IVTV_F_I_WORK_HANDLER_YUV, &itv->i_flags); 806 set_bit(IVTV_F_I_WORK_HANDLER_YUV, &itv->i_flags);
806 set_bit(IVTV_F_I_HAVE_WORK, &itv->i_flags); 807 set_bit(IVTV_F_I_HAVE_WORK, &itv->i_flags);
807 } 808 }
808 } 809 }
809 810
810 itv->yuv_info.fields_lapsed ++; 811 yi->fields_lapsed++;
811 } 812 }
812} 813}
813 814
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;
diff --git a/drivers/media/video/ivtv/ivtv-yuv.h b/drivers/media/video/ivtv/ivtv-yuv.h
index 3b966f0a204a..3b290927d367 100644
--- a/drivers/media/video/ivtv/ivtv-yuv.h
+++ b/drivers/media/video/ivtv/ivtv-yuv.h
@@ -21,11 +21,6 @@
21#ifndef IVTV_YUV_H 21#ifndef IVTV_YUV_H
22#define IVTV_YUV_H 22#define IVTV_YUV_H
23 23
24/* Buffers on hardware offsets */
25#define IVTV_YUV_BUFFER_OFFSET 0x001a8600 /* First YUV Buffer */
26#define IVTV_YUV_BUFFER_OFFSET_1 0x00240400 /* Second YUV Buffer */
27#define IVTV_YUV_BUFFER_OFFSET_2 0x002d8200 /* Third YUV Buffer */
28#define IVTV_YUV_BUFFER_OFFSET_3 0x00370000 /* Fourth YUV Buffer */
29#define IVTV_YUV_BUFFER_UV_OFFSET 0x65400 /* Offset to UV Buffer */ 24#define IVTV_YUV_BUFFER_UV_OFFSET 0x65400 /* Offset to UV Buffer */
30 25
31/* Offset to filter table in firmware */ 26/* Offset to filter table in firmware */
@@ -36,7 +31,7 @@
36#define IVTV_YUV_UPDATE_VERTICAL 0x02 31#define IVTV_YUV_UPDATE_VERTICAL 0x02
37#define IVTV_YUV_UPDATE_INVALID 0x04 32#define IVTV_YUV_UPDATE_INVALID 0x04
38 33
39extern const u32 yuv_offset[4]; 34extern const u32 yuv_offset[IVTV_YUV_BUFFERS];
40 35
41int ivtv_yuv_filter_check(struct ivtv *itv); 36int ivtv_yuv_filter_check(struct ivtv *itv);
42int ivtv_yuv_prep_frame(struct ivtv *itv, struct ivtv_dma_frame *args); 37int ivtv_yuv_prep_frame(struct ivtv *itv, struct ivtv_dma_frame *args);