aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/media/video/ivtv/ivtv-driver.h26
-rw-r--r--drivers/media/video/ivtv/ivtv-fileops.c11
-rw-r--r--drivers/media/video/ivtv/ivtv-irq.c10
-rw-r--r--drivers/media/video/ivtv/ivtv-vbi.c239
-rw-r--r--drivers/media/video/ivtv/ivtv-vbi.h4
-rw-r--r--drivers/media/video/saa7127.c10
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 */
492struct vbi_cc {
493 u8 odd[2]; /* two-byte payload of odd field */
494 u8 even[2]; /* two-byte payload of even field */;
495};
496
497struct vbi_vps {
498 u8 data[5]; /* five-byte VPS payload */
499};
500
492struct vbi_info { 501struct 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
814irqreturn_t ivtv_irq_handler(int irq, void *dev_id) 817irqreturn_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
26static void ivtv_set_vps(struct ivtv *itv, int enabled, u8 vps1, u8 vps2, u8 vps3, 26static 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
44static void ivtv_set_cc(struct ivtv *itv, int mode, u8 cc1, u8 cc2, u8 cc3, u8 cc4) 43static 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
95static void passthrough_vbi_data(struct ivtv *itv, int cnt) 94void 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
274ssize_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
490void ivtv_disable_vbi(struct ivtv *itv) 415void 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
504void ivtv_vbi_work_handler(struct ivtv *itv) 425void 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
23ssize_t ivtv_write_vbi(struct ivtv *itv, const char __user *ubuf, size_t count); 23void ivtv_write_vbi(struct ivtv *itv, const struct v4l2_sliced_vbi_data *sliced, size_t count);
24void ivtv_process_vbi_data(struct ivtv *itv, struct ivtv_buffer *buf, 24void ivtv_process_vbi_data(struct ivtv *itv, struct ivtv_buffer *buf,
25 u64 pts_stamp, int streamtype); 25 u64 pts_stamp, int streamtype);
26int ivtv_used_line(struct ivtv *itv, int line, int field); 26int ivtv_used_line(struct ivtv *itv, int line, int field);
27void ivtv_disable_vbi(struct ivtv *itv); 27void ivtv_disable_cc(struct ivtv *itv);
28void ivtv_set_vbi(unsigned long arg); 28void ivtv_set_vbi(unsigned long arg);
29void ivtv_vbi_work_handler(struct ivtv *itv); 29void 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],