aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video
diff options
context:
space:
mode:
authorHans Verkuil <hverkuil@xs4all.nl>2007-08-25 13:11:23 -0400
committerMauro Carvalho Chehab <mchehab@infradead.org>2007-10-09 21:07:14 -0400
commit2f3a98931f51be6093df7c6cc2633bf238778b7d (patch)
treef25f00c9f0a46c9c4885a24445dc795a2151fc97 /drivers/media/video
parent26e9d599561e9a964bd4d7c2be0029db8aaff852 (diff)
V4L/DVB (6116): ivtv: VBI cleanups and fixes
Besides some VBI cleanups this patch also fixes a subtle problem with the VBI re-insertion stream where the PIO work handler wasn't called quickly enough, resulting in occasional corrupt data. Furthermore the CC output didn't disable CC correctly and at the right time, causing duplicates to be sent. An saa7127 fix for VPS output was also added: the wrong data was sent. Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl> Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Diffstat (limited to 'drivers/media/video')
-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],