diff options
-rw-r--r-- | drivers/media/video/ivtv/ivtv-driver.h | 26 | ||||
-rw-r--r-- | drivers/media/video/ivtv/ivtv-fileops.c | 11 | ||||
-rw-r--r-- | drivers/media/video/ivtv/ivtv-irq.c | 10 | ||||
-rw-r--r-- | drivers/media/video/ivtv/ivtv-vbi.c | 239 | ||||
-rw-r--r-- | drivers/media/video/ivtv/ivtv-vbi.h | 4 | ||||
-rw-r--r-- | drivers/media/video/saa7127.c | 10 |
6 files changed, 113 insertions, 187 deletions
diff --git a/drivers/media/video/ivtv/ivtv-driver.h b/drivers/media/video/ivtv/ivtv-driver.h index 41f753c125da..748ef66bd945 100644 --- a/drivers/media/video/ivtv/ivtv-driver.h +++ b/drivers/media/video/ivtv/ivtv-driver.h | |||
@@ -489,6 +489,15 @@ struct yuv_playback_info | |||
489 | #define IVTV_VBI_FRAMES 32 | 489 | #define IVTV_VBI_FRAMES 32 |
490 | 490 | ||
491 | /* VBI data */ | 491 | /* VBI data */ |
492 | struct vbi_cc { | ||
493 | u8 odd[2]; /* two-byte payload of odd field */ | ||
494 | u8 even[2]; /* two-byte payload of even field */; | ||
495 | }; | ||
496 | |||
497 | struct vbi_vps { | ||
498 | u8 data[5]; /* five-byte VPS payload */ | ||
499 | }; | ||
500 | |||
492 | struct vbi_info { | 501 | struct vbi_info { |
493 | /* VBI general fixed card data */ | 502 | /* VBI general fixed card data */ |
494 | u32 raw_decoder_line_size; /* raw VBI line size from digitizer */ | 503 | u32 raw_decoder_line_size; /* raw VBI line size from digitizer */ |
@@ -502,15 +511,14 @@ struct vbi_info { | |||
502 | u32 enc_start, enc_size; | 511 | u32 enc_start, enc_size; |
503 | int fpi; | 512 | int fpi; |
504 | u32 frame; | 513 | u32 frame; |
505 | u8 cc_data_odd[256]; | 514 | struct vbi_cc cc_payload[256]; /* Sliced VBI CC payload array. It is an array to |
506 | u8 cc_data_even[256]; | 515 | prevent dropping CC data if they couldn't be |
507 | int cc_pos; | 516 | processed fast enough. */ |
508 | u8 cc_no_update; | 517 | int cc_payload_idx; /* Index in cc_payload */ |
509 | u8 vps[5]; | 518 | u8 cc_missing_cnt; /* Counts number of frames without CC for passthrough mode */ |
510 | u8 vps_found; | 519 | int wss_payload; /* Sliced VBI WSS payload */ |
511 | int wss; | 520 | u8 wss_missing_cnt; /* Counts number of frames without WSS for passthrough mode */ |
512 | u8 wss_found; | 521 | struct vbi_vps vps_payload; /* Sliced VBI VPS payload */ |
513 | u8 wss_no_update; | ||
514 | struct v4l2_format in; | 522 | struct v4l2_format in; |
515 | /* convenience pointer to sliced struct in vbi_in union */ | 523 | /* convenience pointer to sliced struct in vbi_in union */ |
516 | struct v4l2_sliced_vbi_format *sliced_in; | 524 | struct v4l2_sliced_vbi_format *sliced_in; |
diff --git a/drivers/media/video/ivtv/ivtv-fileops.c b/drivers/media/video/ivtv/ivtv-fileops.c index 5b5d6666fa16..da50fa4a72a5 100644 --- a/drivers/media/video/ivtv/ivtv-fileops.c +++ b/drivers/media/video/ivtv/ivtv-fileops.c | |||
@@ -563,8 +563,11 @@ ssize_t ivtv_v4l2_write(struct file *filp, const char __user *user_buf, size_t c | |||
563 | 563 | ||
564 | /* This stream does not need to start any decoding */ | 564 | /* This stream does not need to start any decoding */ |
565 | if (s->type == IVTV_DEC_STREAM_TYPE_VOUT) { | 565 | if (s->type == IVTV_DEC_STREAM_TYPE_VOUT) { |
566 | int elems = count / sizeof(struct v4l2_sliced_vbi_data); | ||
567 | |||
566 | set_bit(IVTV_F_S_APPL_IO, &s->s_flags); | 568 | set_bit(IVTV_F_S_APPL_IO, &s->s_flags); |
567 | return ivtv_write_vbi(itv, user_buf, count); | 569 | ivtv_write_vbi(itv, (const struct v4l2_sliced_vbi_data *)user_buf, elems); |
570 | return elems * sizeof(struct v4l2_sliced_vbi_data); | ||
568 | } | 571 | } |
569 | 572 | ||
570 | mode = s->type == IVTV_DEC_STREAM_TYPE_MPG ? OUT_MPG : OUT_YUV; | 573 | mode = s->type == IVTV_DEC_STREAM_TYPE_MPG ? OUT_MPG : OUT_YUV; |
@@ -828,10 +831,10 @@ int ivtv_v4l2_close(struct inode *inode, struct file *filp) | |||
828 | ivtv_stop_decoding(id, VIDEO_CMD_STOP_TO_BLACK | VIDEO_CMD_STOP_IMMEDIATELY, 0); | 831 | ivtv_stop_decoding(id, VIDEO_CMD_STOP_TO_BLACK | VIDEO_CMD_STOP_IMMEDIATELY, 0); |
829 | 832 | ||
830 | /* If all output streams are closed, and if the user doesn't have | 833 | /* If all output streams are closed, and if the user doesn't have |
831 | IVTV_DEC_STREAM_TYPE_VOUT open, then disable VBI on TV-out. */ | 834 | IVTV_DEC_STREAM_TYPE_VOUT open, then disable CC on TV-out. */ |
832 | if (itv->output_mode == OUT_NONE && !test_bit(IVTV_F_S_APPL_IO, &s_vout->s_flags)) { | 835 | if (itv->output_mode == OUT_NONE && !test_bit(IVTV_F_S_APPL_IO, &s_vout->s_flags)) { |
833 | /* disable VBI on TV-out */ | 836 | /* disable CC on TV-out */ |
834 | ivtv_disable_vbi(itv); | 837 | ivtv_disable_cc(itv); |
835 | } | 838 | } |
836 | } else { | 839 | } else { |
837 | ivtv_stop_capture(id, 0); | 840 | ivtv_stop_capture(id, 0); |
diff --git a/drivers/media/video/ivtv/ivtv-irq.c b/drivers/media/video/ivtv/ivtv-irq.c index 66d0da22389f..bf7d99c6ffaf 100644 --- a/drivers/media/video/ivtv/ivtv-irq.c +++ b/drivers/media/video/ivtv/ivtv-irq.c | |||
@@ -786,7 +786,10 @@ static void ivtv_irq_vsync(struct ivtv *itv) | |||
786 | wake_up(&s->waitq); | 786 | wake_up(&s->waitq); |
787 | 787 | ||
788 | /* Send VBI to saa7127 */ | 788 | /* Send VBI to saa7127 */ |
789 | if (frame) { | 789 | if (frame && (itv->output_mode == OUT_PASSTHROUGH || |
790 | test_bit(IVTV_F_I_UPDATE_WSS, &itv->i_flags) || | ||
791 | test_bit(IVTV_F_I_UPDATE_VPS, &itv->i_flags) || | ||
792 | test_bit(IVTV_F_I_UPDATE_CC, &itv->i_flags))) { | ||
790 | set_bit(IVTV_F_I_WORK_HANDLER_VBI, &itv->i_flags); | 793 | set_bit(IVTV_F_I_WORK_HANDLER_VBI, &itv->i_flags); |
791 | set_bit(IVTV_F_I_HAVE_WORK, &itv->i_flags); | 794 | set_bit(IVTV_F_I_HAVE_WORK, &itv->i_flags); |
792 | } | 795 | } |
@@ -809,7 +812,7 @@ static void ivtv_irq_vsync(struct ivtv *itv) | |||
809 | } | 812 | } |
810 | } | 813 | } |
811 | 814 | ||
812 | #define IVTV_IRQ_DMA (IVTV_IRQ_DMA_READ | IVTV_IRQ_ENC_DMA_COMPLETE | IVTV_IRQ_DMA_ERR | IVTV_IRQ_ENC_START_CAP | IVTV_IRQ_ENC_VBI_CAP | IVTV_IRQ_DEC_DATA_REQ) | 815 | #define IVTV_IRQ_DMA (IVTV_IRQ_DMA_READ | IVTV_IRQ_ENC_DMA_COMPLETE | IVTV_IRQ_DMA_ERR | IVTV_IRQ_ENC_START_CAP | IVTV_IRQ_ENC_VBI_CAP | IVTV_IRQ_DEC_DATA_REQ | IVTV_IRQ_DEC_VBI_RE_INSERT) |
813 | 816 | ||
814 | irqreturn_t ivtv_irq_handler(int irq, void *dev_id) | 817 | irqreturn_t ivtv_irq_handler(int irq, void *dev_id) |
815 | { | 818 | { |
@@ -942,8 +945,9 @@ irqreturn_t ivtv_irq_handler(int irq, void *dev_id) | |||
942 | } | 945 | } |
943 | } | 946 | } |
944 | 947 | ||
945 | if (test_and_clear_bit(IVTV_F_I_HAVE_WORK, &itv->i_flags)) | 948 | if (test_and_clear_bit(IVTV_F_I_HAVE_WORK, &itv->i_flags)) { |
946 | queue_work(itv->irq_work_queues, &itv->irq_work_queue); | 949 | queue_work(itv->irq_work_queues, &itv->irq_work_queue); |
950 | } | ||
947 | 951 | ||
948 | spin_unlock(&itv->dma_reg_lock); | 952 | spin_unlock(&itv->dma_reg_lock); |
949 | 953 | ||
diff --git a/drivers/media/video/ivtv/ivtv-vbi.c b/drivers/media/video/ivtv/ivtv-vbi.c index 5d8a40f3d2b6..c151bcf5519a 100644 --- a/drivers/media/video/ivtv/ivtv-vbi.c +++ b/drivers/media/video/ivtv/ivtv-vbi.c | |||
@@ -23,8 +23,7 @@ | |||
23 | #include "ivtv-queue.h" | 23 | #include "ivtv-queue.h" |
24 | #include "ivtv-vbi.h" | 24 | #include "ivtv-vbi.h" |
25 | 25 | ||
26 | static void ivtv_set_vps(struct ivtv *itv, int enabled, u8 vps1, u8 vps2, u8 vps3, | 26 | static void ivtv_set_vps(struct ivtv *itv, int enabled) |
27 | u8 vps4, u8 vps5) | ||
28 | { | 27 | { |
29 | struct v4l2_sliced_vbi_data data; | 28 | struct v4l2_sliced_vbi_data data; |
30 | 29 | ||
@@ -33,15 +32,15 @@ static void ivtv_set_vps(struct ivtv *itv, int enabled, u8 vps1, u8 vps2, u8 vps | |||
33 | data.id = V4L2_SLICED_VPS; | 32 | data.id = V4L2_SLICED_VPS; |
34 | data.field = 0; | 33 | data.field = 0; |
35 | data.line = enabled ? 16 : 0; | 34 | data.line = enabled ? 16 : 0; |
36 | data.data[4] = vps1; | 35 | data.data[2] = itv->vbi.vps_payload.data[0]; |
37 | data.data[10] = vps2; | 36 | data.data[8] = itv->vbi.vps_payload.data[1]; |
38 | data.data[11] = vps3; | 37 | data.data[9] = itv->vbi.vps_payload.data[2]; |
39 | data.data[12] = vps4; | 38 | data.data[10] = itv->vbi.vps_payload.data[3]; |
40 | data.data[13] = vps5; | 39 | data.data[11] = itv->vbi.vps_payload.data[4]; |
41 | ivtv_saa7127(itv, VIDIOC_INT_S_VBI_DATA, &data); | 40 | ivtv_saa7127(itv, VIDIOC_INT_S_VBI_DATA, &data); |
42 | } | 41 | } |
43 | 42 | ||
44 | static void ivtv_set_cc(struct ivtv *itv, int mode, u8 cc1, u8 cc2, u8 cc3, u8 cc4) | 43 | static void ivtv_set_cc(struct ivtv *itv, int mode, const struct vbi_cc *cc) |
45 | { | 44 | { |
46 | struct v4l2_sliced_vbi_data data; | 45 | struct v4l2_sliced_vbi_data data; |
47 | 46 | ||
@@ -50,13 +49,13 @@ static void ivtv_set_cc(struct ivtv *itv, int mode, u8 cc1, u8 cc2, u8 cc3, u8 c | |||
50 | data.id = V4L2_SLICED_CAPTION_525; | 49 | data.id = V4L2_SLICED_CAPTION_525; |
51 | data.field = 0; | 50 | data.field = 0; |
52 | data.line = (mode & 1) ? 21 : 0; | 51 | data.line = (mode & 1) ? 21 : 0; |
53 | data.data[0] = cc1; | 52 | data.data[0] = cc->odd[0]; |
54 | data.data[1] = cc2; | 53 | data.data[1] = cc->odd[1]; |
55 | ivtv_saa7127(itv, VIDIOC_INT_S_VBI_DATA, &data); | 54 | ivtv_saa7127(itv, VIDIOC_INT_S_VBI_DATA, &data); |
56 | data.field = 1; | 55 | data.field = 1; |
57 | data.line = (mode & 2) ? 21 : 0; | 56 | data.line = (mode & 2) ? 21 : 0; |
58 | data.data[0] = cc3; | 57 | data.data[0] = cc->even[0]; |
59 | data.data[1] = cc4; | 58 | data.data[1] = cc->even[1]; |
60 | ivtv_saa7127(itv, VIDIOC_INT_S_VBI_DATA, &data); | 59 | ivtv_saa7127(itv, VIDIOC_INT_S_VBI_DATA, &data); |
61 | } | 60 | } |
62 | 61 | ||
@@ -92,62 +91,50 @@ static int odd_parity(u8 c) | |||
92 | return c & 1; | 91 | return c & 1; |
93 | } | 92 | } |
94 | 93 | ||
95 | static void passthrough_vbi_data(struct ivtv *itv, int cnt) | 94 | void ivtv_write_vbi(struct ivtv *itv, const struct v4l2_sliced_vbi_data *sliced, size_t cnt) |
96 | { | 95 | { |
97 | int wss = 0; | 96 | struct vbi_info *vi = &itv->vbi; |
98 | u8 cc[4] = { 0x80, 0x80, 0x80, 0x80 }; | 97 | struct vbi_cc cc = { .odd = { 0x80, 0x80 }, .even = { 0x80, 0x80 } }; |
99 | u8 vps[13]; | ||
100 | int found_cc = 0; | 98 | int found_cc = 0; |
101 | int found_wss = 0; | 99 | size_t i; |
102 | int found_vps = 0; | ||
103 | int cc_pos = itv->vbi.cc_pos; | ||
104 | int i; | ||
105 | 100 | ||
106 | for (i = 0; i < cnt; i++) { | 101 | for (i = 0; i < cnt; i++) { |
107 | struct v4l2_sliced_vbi_data *d = itv->vbi.sliced_dec_data + i; | 102 | const struct v4l2_sliced_vbi_data *d = sliced + i; |
108 | 103 | ||
109 | if (d->id == V4L2_SLICED_CAPTION_525 && d->line == 21) { | 104 | if (d->id == V4L2_SLICED_CAPTION_525 && d->line == 21) { |
110 | found_cc = 1; | ||
111 | if (d->field) { | 105 | if (d->field) { |
112 | cc[2] = d->data[0]; | 106 | cc.even[0] = d->data[0]; |
113 | cc[3] = d->data[1]; | 107 | cc.even[1] = d->data[1]; |
114 | } else { | 108 | } else { |
115 | cc[0] = d->data[0]; | 109 | cc.odd[0] = d->data[0]; |
116 | cc[1] = d->data[1]; | 110 | cc.odd[1] = d->data[1]; |
117 | } | 111 | } |
112 | found_cc = 1; | ||
118 | } | 113 | } |
119 | else if (d->id == V4L2_SLICED_VPS && d->line == 16 && d->field == 0) { | 114 | else if (d->id == V4L2_SLICED_VPS && d->line == 16 && d->field == 0) { |
120 | memcpy(vps, d->data, sizeof(vps)); | 115 | struct vbi_vps vps; |
121 | found_vps = 1; | 116 | |
117 | vps.data[0] = d->data[2]; | ||
118 | vps.data[1] = d->data[8]; | ||
119 | vps.data[2] = d->data[9]; | ||
120 | vps.data[3] = d->data[10]; | ||
121 | vps.data[4] = d->data[11]; | ||
122 | if (memcmp(&vps, &vi->vps_payload, sizeof(vps))) { | ||
123 | vi->vps_payload = vps; | ||
124 | set_bit(IVTV_F_I_UPDATE_VPS, &itv->i_flags); | ||
125 | } | ||
122 | } | 126 | } |
123 | else if (d->id == V4L2_SLICED_WSS_625 && d->line == 23 && d->field == 0) { | 127 | else if (d->id == V4L2_SLICED_WSS_625 && d->line == 23 && d->field == 0) { |
124 | wss = d->data[0] | d->data[1] << 8; | 128 | int wss = d->data[0] | d->data[1] << 8; |
125 | found_wss = 1; | ||
126 | } | ||
127 | } | ||
128 | 129 | ||
129 | if (itv->vbi.wss_found != found_wss || itv->vbi.wss != wss) { | 130 | if (vi->wss_payload != wss) { |
130 | itv->vbi.wss = wss; | 131 | vi->wss_payload = wss; |
131 | itv->vbi.wss_found = found_wss; | 132 | set_bit(IVTV_F_I_UPDATE_WSS, &itv->i_flags); |
132 | set_bit(IVTV_F_I_UPDATE_WSS, &itv->i_flags); | 133 | } |
133 | } | 134 | } |
134 | |||
135 | if (found_vps || itv->vbi.vps_found) { | ||
136 | itv->vbi.vps[0] = vps[2]; | ||
137 | itv->vbi.vps[1] = vps[8]; | ||
138 | itv->vbi.vps[2] = vps[9]; | ||
139 | itv->vbi.vps[3] = vps[10]; | ||
140 | itv->vbi.vps[4] = vps[11]; | ||
141 | itv->vbi.vps_found = found_vps; | ||
142 | set_bit(IVTV_F_I_UPDATE_VPS, &itv->i_flags); | ||
143 | } | 135 | } |
144 | 136 | if (found_cc && vi->cc_payload_idx < sizeof(vi->cc_payload)) { | |
145 | if (found_cc && cc_pos < sizeof(itv->vbi.cc_data_even)) { | 137 | vi->cc_payload[vi->cc_payload_idx++] = cc; |
146 | itv->vbi.cc_data_odd[cc_pos] = cc[0]; | ||
147 | itv->vbi.cc_data_odd[cc_pos + 1] = cc[1]; | ||
148 | itv->vbi.cc_data_even[cc_pos] = cc[2]; | ||
149 | itv->vbi.cc_data_even[cc_pos + 1] = cc[3]; | ||
150 | itv->vbi.cc_pos = cc_pos + 2; | ||
151 | set_bit(IVTV_F_I_UPDATE_CC, &itv->i_flags); | 138 | set_bit(IVTV_F_I_UPDATE_CC, &itv->i_flags); |
152 | } | 139 | } |
153 | } | 140 | } |
@@ -271,69 +258,6 @@ static int ivtv_convert_ivtv_vbi(struct ivtv *itv, u8 *p) | |||
271 | return line * sizeof(itv->vbi.sliced_dec_data[0]); | 258 | return line * sizeof(itv->vbi.sliced_dec_data[0]); |
272 | } | 259 | } |
273 | 260 | ||
274 | ssize_t ivtv_write_vbi(struct ivtv *itv, const char __user *ubuf, size_t count) | ||
275 | { | ||
276 | /* Should be a __user pointer, but sparse doesn't parse this bit correctly. */ | ||
277 | const struct v4l2_sliced_vbi_data *p = (const struct v4l2_sliced_vbi_data *)ubuf; | ||
278 | u8 cc[4] = { 0x80, 0x80, 0x80, 0x80 }; | ||
279 | int found_cc = 0; | ||
280 | int cc_pos = itv->vbi.cc_pos; | ||
281 | |||
282 | while (count >= sizeof(struct v4l2_sliced_vbi_data)) { | ||
283 | switch (p->id) { | ||
284 | case V4L2_SLICED_CAPTION_525: | ||
285 | if (p->line == 21) { | ||
286 | found_cc = 1; | ||
287 | if (p->field) { | ||
288 | cc[2] = p->data[0]; | ||
289 | cc[3] = p->data[1]; | ||
290 | } else { | ||
291 | cc[0] = p->data[0]; | ||
292 | cc[1] = p->data[1]; | ||
293 | } | ||
294 | } | ||
295 | break; | ||
296 | |||
297 | case V4L2_SLICED_VPS: | ||
298 | if (p->line == 16 && p->field == 0) { | ||
299 | itv->vbi.vps[0] = p->data[2]; | ||
300 | itv->vbi.vps[1] = p->data[8]; | ||
301 | itv->vbi.vps[2] = p->data[9]; | ||
302 | itv->vbi.vps[3] = p->data[10]; | ||
303 | itv->vbi.vps[4] = p->data[11]; | ||
304 | itv->vbi.vps_found = 1; | ||
305 | set_bit(IVTV_F_I_UPDATE_VPS, &itv->i_flags); | ||
306 | } | ||
307 | break; | ||
308 | |||
309 | case V4L2_SLICED_WSS_625: | ||
310 | if (p->line == 23 && p->field == 0) { | ||
311 | /* No lock needed for WSS */ | ||
312 | itv->vbi.wss = p->data[0] | (p->data[1] << 8); | ||
313 | itv->vbi.wss_found = 1; | ||
314 | set_bit(IVTV_F_I_UPDATE_WSS, &itv->i_flags); | ||
315 | } | ||
316 | break; | ||
317 | |||
318 | default: | ||
319 | break; | ||
320 | } | ||
321 | count -= sizeof(*p); | ||
322 | p++; | ||
323 | } | ||
324 | |||
325 | if (found_cc && cc_pos < sizeof(itv->vbi.cc_data_even)) { | ||
326 | itv->vbi.cc_data_odd[cc_pos] = cc[0]; | ||
327 | itv->vbi.cc_data_odd[cc_pos + 1] = cc[1]; | ||
328 | itv->vbi.cc_data_even[cc_pos] = cc[2]; | ||
329 | itv->vbi.cc_data_even[cc_pos + 1] = cc[3]; | ||
330 | itv->vbi.cc_pos = cc_pos + 2; | ||
331 | set_bit(IVTV_F_I_UPDATE_CC, &itv->i_flags); | ||
332 | } | ||
333 | |||
334 | return (const char __user *)p - ubuf; | ||
335 | } | ||
336 | |||
337 | /* Compress raw VBI format, removes leading SAV codes and surplus space after the | 261 | /* Compress raw VBI format, removes leading SAV codes and surplus space after the |
338 | field. | 262 | field. |
339 | Returns new compressed size. */ | 263 | Returns new compressed size. */ |
@@ -482,108 +406,95 @@ void ivtv_process_vbi_data(struct ivtv *itv, struct ivtv_buffer *buf, | |||
482 | memcpy(buf->buf, itv->vbi.sliced_dec_data, cnt); | 406 | memcpy(buf->buf, itv->vbi.sliced_dec_data, cnt); |
483 | buf->bytesused = cnt; | 407 | buf->bytesused = cnt; |
484 | 408 | ||
485 | passthrough_vbi_data(itv, cnt / sizeof(itv->vbi.sliced_dec_data[0])); | 409 | ivtv_write_vbi(itv, itv->vbi.sliced_dec_data, |
410 | cnt / sizeof(itv->vbi.sliced_dec_data[0])); | ||
486 | return; | 411 | return; |
487 | } | 412 | } |
488 | } | 413 | } |
489 | 414 | ||
490 | void ivtv_disable_vbi(struct ivtv *itv) | 415 | void ivtv_disable_cc(struct ivtv *itv) |
491 | { | 416 | { |
492 | clear_bit(IVTV_F_I_UPDATE_WSS, &itv->i_flags); | 417 | struct vbi_cc cc = { .odd = { 0x80, 0x80 }, .even = { 0x80, 0x80 } }; |
493 | clear_bit(IVTV_F_I_UPDATE_VPS, &itv->i_flags); | 418 | |
494 | clear_bit(IVTV_F_I_UPDATE_CC, &itv->i_flags); | 419 | clear_bit(IVTV_F_I_UPDATE_CC, &itv->i_flags); |
495 | ivtv_set_wss(itv, 0, 0); | 420 | ivtv_set_cc(itv, 0, &cc); |
496 | ivtv_set_cc(itv, 0, 0, 0, 0, 0); | 421 | itv->vbi.cc_payload_idx = 0; |
497 | ivtv_set_vps(itv, 0, 0, 0, 0, 0, 0); | ||
498 | itv->vbi.vps_found = itv->vbi.wss_found = 0; | ||
499 | itv->vbi.wss = 0; | ||
500 | itv->vbi.cc_pos = 0; | ||
501 | } | 422 | } |
502 | 423 | ||
503 | 424 | ||
504 | void ivtv_vbi_work_handler(struct ivtv *itv) | 425 | void ivtv_vbi_work_handler(struct ivtv *itv) |
505 | { | 426 | { |
427 | struct vbi_info *vi = &itv->vbi; | ||
506 | struct v4l2_sliced_vbi_data data; | 428 | struct v4l2_sliced_vbi_data data; |
429 | struct vbi_cc cc = { .odd = { 0x80, 0x80 }, .even = { 0x80, 0x80 } }; | ||
507 | 430 | ||
508 | /* Lock */ | 431 | /* Lock */ |
509 | if (itv->output_mode == OUT_PASSTHROUGH) { | 432 | if (itv->output_mode == OUT_PASSTHROUGH) { |
510 | /* Note: currently only the saa7115 is used in a PVR350, | ||
511 | so these commands are for now saa7115 specific. */ | ||
512 | if (itv->is_50hz) { | 433 | if (itv->is_50hz) { |
513 | data.id = V4L2_SLICED_WSS_625; | 434 | data.id = V4L2_SLICED_WSS_625; |
514 | data.field = 0; | 435 | data.field = 0; |
515 | 436 | ||
516 | if (itv->video_dec_func(itv, VIDIOC_INT_G_VBI_DATA, &data) == 0) { | 437 | if (itv->video_dec_func(itv, VIDIOC_INT_G_VBI_DATA, &data) == 0) { |
517 | ivtv_set_wss(itv, 1, data.data[0] & 0xf); | 438 | ivtv_set_wss(itv, 1, data.data[0] & 0xf); |
518 | itv->vbi.wss_no_update = 0; | 439 | vi->wss_missing_cnt = 0; |
519 | } else if (itv->vbi.wss_no_update == 4) { | 440 | } else if (vi->wss_missing_cnt == 4) { |
520 | ivtv_set_wss(itv, 1, 0x8); /* 4x3 full format */ | 441 | ivtv_set_wss(itv, 1, 0x8); /* 4x3 full format */ |
521 | } else { | 442 | } else { |
522 | itv->vbi.wss_no_update++; | 443 | vi->wss_missing_cnt++; |
523 | } | 444 | } |
524 | } | 445 | } |
525 | else { | 446 | else { |
526 | u8 c1 = 0, c2 = 0, c3 = 0, c4 = 0; | ||
527 | int mode = 0; | 447 | int mode = 0; |
528 | 448 | ||
529 | data.id = V4L2_SLICED_CAPTION_525; | 449 | data.id = V4L2_SLICED_CAPTION_525; |
530 | data.field = 0; | 450 | data.field = 0; |
531 | if (itv->video_dec_func(itv, VIDIOC_INT_G_VBI_DATA, &data) == 0) { | 451 | if (itv->video_dec_func(itv, VIDIOC_INT_G_VBI_DATA, &data) == 0) { |
532 | mode |= 1; | 452 | mode |= 1; |
533 | c1 = data.data[0]; | 453 | cc.odd[0] = data.data[0]; |
534 | c2 = data.data[1]; | 454 | cc.odd[1] = data.data[1]; |
535 | } | 455 | } |
536 | data.field = 1; | 456 | data.field = 1; |
537 | if (itv->video_dec_func(itv, VIDIOC_INT_G_VBI_DATA, &data) == 0) { | 457 | if (itv->video_dec_func(itv, VIDIOC_INT_G_VBI_DATA, &data) == 0) { |
538 | mode |= 2; | 458 | mode |= 2; |
539 | c3 = data.data[0]; | 459 | cc.even[0] = data.data[0]; |
540 | c4 = data.data[1]; | 460 | cc.even[1] = data.data[1]; |
541 | } | 461 | } |
542 | if (mode) { | 462 | if (mode) { |
543 | itv->vbi.cc_no_update = 0; | 463 | vi->cc_missing_cnt = 0; |
544 | ivtv_set_cc(itv, mode, c1, c2, c3, c4); | 464 | ivtv_set_cc(itv, mode, &cc); |
545 | } else if (itv->vbi.cc_no_update == 4) { | 465 | } else if (vi->cc_missing_cnt == 4) { |
546 | ivtv_set_cc(itv, 0, 0, 0, 0, 0); | 466 | ivtv_set_cc(itv, 0, &cc); |
547 | } else { | 467 | } else { |
548 | itv->vbi.cc_no_update++; | 468 | vi->cc_missing_cnt++; |
549 | } | 469 | } |
550 | } | 470 | } |
551 | return; | 471 | return; |
552 | } | 472 | } |
553 | 473 | ||
554 | if (test_and_clear_bit(IVTV_F_I_UPDATE_WSS, &itv->i_flags)) { | 474 | if (test_and_clear_bit(IVTV_F_I_UPDATE_WSS, &itv->i_flags)) { |
555 | /* Lock */ | 475 | ivtv_set_wss(itv, 1, vi->wss_payload & 0xf); |
556 | ivtv_set_wss(itv, itv->vbi.wss_found, itv->vbi.wss & 0xf); | ||
557 | } | 476 | } |
558 | 477 | ||
559 | if (test_and_clear_bit(IVTV_F_I_UPDATE_CC, &itv->i_flags)) { | 478 | if (test_bit(IVTV_F_I_UPDATE_CC, &itv->i_flags)) { |
560 | if (itv->vbi.cc_pos == 0) { | 479 | if (vi->cc_payload_idx == 0) { |
561 | ivtv_set_cc(itv, 3, 0x80, 0x80, 0x80, 0x80); | 480 | clear_bit(IVTV_F_I_UPDATE_CC, &itv->i_flags); |
481 | ivtv_set_cc(itv, 3, &cc); | ||
562 | } | 482 | } |
563 | while (itv->vbi.cc_pos) { | 483 | while (vi->cc_payload_idx) { |
564 | u8 cc_odd0 = itv->vbi.cc_data_odd[0]; | 484 | cc = vi->cc_payload[0]; |
565 | u8 cc_odd1 = itv->vbi.cc_data_odd[1]; | 485 | |
566 | u8 cc_even0 = itv->vbi.cc_data_even[0]; | 486 | memcpy(vi->cc_payload, vi->cc_payload + 1, |
567 | u8 cc_even1 = itv->vbi.cc_data_even[1]; | 487 | sizeof(vi->cc_payload) - sizeof(vi->cc_payload[0])); |
568 | 488 | vi->cc_payload_idx--; | |
569 | memcpy(itv->vbi.cc_data_odd, itv->vbi.cc_data_odd + 2, sizeof(itv->vbi.cc_data_odd) - 2); | 489 | if (vi->cc_payload_idx && cc.odd[0] == 0x80 && cc.odd[1] == 0x80) |
570 | memcpy(itv->vbi.cc_data_even, itv->vbi.cc_data_even + 2, sizeof(itv->vbi.cc_data_even) - 2); | ||
571 | itv->vbi.cc_pos -= 2; | ||
572 | if (itv->vbi.cc_pos && cc_odd0 == 0x80 && cc_odd1 == 0x80) | ||
573 | continue; | 490 | continue; |
574 | 491 | ||
575 | /* Send to Saa7127 */ | 492 | ivtv_set_cc(itv, 3, &cc); |
576 | ivtv_set_cc(itv, 3, cc_odd0, cc_odd1, cc_even0, cc_even1); | ||
577 | if (itv->vbi.cc_pos == 0) | ||
578 | set_bit(IVTV_F_I_UPDATE_CC, &itv->i_flags); | ||
579 | break; | 493 | break; |
580 | } | 494 | } |
581 | } | 495 | } |
582 | 496 | ||
583 | if (test_and_clear_bit(IVTV_F_I_UPDATE_VPS, &itv->i_flags)) { | 497 | if (test_and_clear_bit(IVTV_F_I_UPDATE_VPS, &itv->i_flags)) { |
584 | /* Lock */ | 498 | ivtv_set_vps(itv, 1); |
585 | ivtv_set_vps(itv, itv->vbi.vps_found, | ||
586 | itv->vbi.vps[0], itv->vbi.vps[1], | ||
587 | itv->vbi.vps[2], itv->vbi.vps[3], itv->vbi.vps[4]); | ||
588 | } | 499 | } |
589 | } | 500 | } |
diff --git a/drivers/media/video/ivtv/ivtv-vbi.h b/drivers/media/video/ivtv/ivtv-vbi.h index d5740493a690..970567b9194d 100644 --- a/drivers/media/video/ivtv/ivtv-vbi.h +++ b/drivers/media/video/ivtv/ivtv-vbi.h | |||
@@ -20,11 +20,11 @@ | |||
20 | #ifndef IVTV_VBI_H | 20 | #ifndef IVTV_VBI_H |
21 | #define IVTV_VBI_H | 21 | #define IVTV_VBI_H |
22 | 22 | ||
23 | ssize_t ivtv_write_vbi(struct ivtv *itv, const char __user *ubuf, size_t count); | 23 | void ivtv_write_vbi(struct ivtv *itv, const struct v4l2_sliced_vbi_data *sliced, size_t count); |
24 | void ivtv_process_vbi_data(struct ivtv *itv, struct ivtv_buffer *buf, | 24 | void ivtv_process_vbi_data(struct ivtv *itv, struct ivtv_buffer *buf, |
25 | u64 pts_stamp, int streamtype); | 25 | u64 pts_stamp, int streamtype); |
26 | int ivtv_used_line(struct ivtv *itv, int line, int field); | 26 | int ivtv_used_line(struct ivtv *itv, int line, int field); |
27 | void ivtv_disable_vbi(struct ivtv *itv); | 27 | void ivtv_disable_cc(struct ivtv *itv); |
28 | void ivtv_set_vbi(unsigned long arg); | 28 | void ivtv_set_vbi(unsigned long arg); |
29 | void ivtv_vbi_work_handler(struct ivtv *itv); | 29 | void ivtv_vbi_work_handler(struct ivtv *itv); |
30 | 30 | ||
diff --git a/drivers/media/video/saa7127.c b/drivers/media/video/saa7127.c index 9f986930490f..e35ef321ec71 100644 --- a/drivers/media/video/saa7127.c +++ b/drivers/media/video/saa7127.c | |||
@@ -332,11 +332,11 @@ static int saa7127_set_vps(struct i2c_client *client, struct v4l2_sliced_vbi_dat | |||
332 | if (!enable) | 332 | if (!enable) |
333 | return 0; | 333 | return 0; |
334 | 334 | ||
335 | state->vps_data[0] = data->data[4]; | 335 | state->vps_data[0] = data->data[2]; |
336 | state->vps_data[1] = data->data[10]; | 336 | state->vps_data[1] = data->data[8]; |
337 | state->vps_data[2] = data->data[11]; | 337 | state->vps_data[2] = data->data[9]; |
338 | state->vps_data[3] = data->data[12]; | 338 | state->vps_data[3] = data->data[10]; |
339 | state->vps_data[4] = data->data[13]; | 339 | state->vps_data[4] = data->data[11]; |
340 | v4l_dbg(1, debug, client, "Set VPS data %02x %02x %02x %02x %02x\n", | 340 | v4l_dbg(1, debug, client, "Set VPS data %02x %02x %02x %02x %02x\n", |
341 | state->vps_data[0], state->vps_data[1], | 341 | state->vps_data[0], state->vps_data[1], |
342 | state->vps_data[2], state->vps_data[3], | 342 | state->vps_data[2], state->vps_data[3], |