blob: 293db806d9362b688f000ed90ed3475c0b85ae09 [file] [log] [blame]
Hans Verkuil1a0adaf2007-04-27 12:31:25 -03001/*
2 Vertical Blank Interval support functions
3 Copyright (C) 2004-2007 Hans Verkuil <hverkuil@xs4all.nl>
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19
20#include "ivtv-driver.h"
Hans Verkuil33c0fca2007-08-23 06:32:46 -030021#include "ivtv-i2c.h"
Hans Verkuil1a0adaf2007-04-27 12:31:25 -030022#include "ivtv-ioctl.h"
23#include "ivtv-queue.h"
Hans Verkuil67ec09f2008-11-29 19:38:23 -030024#include "ivtv-cards.h"
Hans Verkuil33c0fca2007-08-23 06:32:46 -030025#include "ivtv-vbi.h"
26
Hans Verkuil2f3a9892007-08-25 14:11:23 -030027static void ivtv_set_vps(struct ivtv *itv, int enabled)
Hans Verkuil33c0fca2007-08-23 06:32:46 -030028{
29 struct v4l2_sliced_vbi_data data;
30
31 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
32 return;
33 data.id = V4L2_SLICED_VPS;
34 data.field = 0;
35 data.line = enabled ? 16 : 0;
Hans Verkuil2f3a9892007-08-25 14:11:23 -030036 data.data[2] = itv->vbi.vps_payload.data[0];
37 data.data[8] = itv->vbi.vps_payload.data[1];
38 data.data[9] = itv->vbi.vps_payload.data[2];
39 data.data[10] = itv->vbi.vps_payload.data[3];
40 data.data[11] = itv->vbi.vps_payload.data[4];
Hans Verkuil32cd5272010-03-14 09:57:30 -030041 ivtv_call_hw(itv, IVTV_HW_SAA7127, vbi, s_vbi_data, &data);
Hans Verkuil33c0fca2007-08-23 06:32:46 -030042}
43
Hans Verkuil2f3a9892007-08-25 14:11:23 -030044static void ivtv_set_cc(struct ivtv *itv, int mode, const struct vbi_cc *cc)
Hans Verkuil33c0fca2007-08-23 06:32:46 -030045{
46 struct v4l2_sliced_vbi_data data;
47
48 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
49 return;
50 data.id = V4L2_SLICED_CAPTION_525;
51 data.field = 0;
52 data.line = (mode & 1) ? 21 : 0;
Hans Verkuil2f3a9892007-08-25 14:11:23 -030053 data.data[0] = cc->odd[0];
54 data.data[1] = cc->odd[1];
Hans Verkuil32cd5272010-03-14 09:57:30 -030055 ivtv_call_hw(itv, IVTV_HW_SAA7127, vbi, s_vbi_data, &data);
Hans Verkuil33c0fca2007-08-23 06:32:46 -030056 data.field = 1;
57 data.line = (mode & 2) ? 21 : 0;
Hans Verkuil2f3a9892007-08-25 14:11:23 -030058 data.data[0] = cc->even[0];
59 data.data[1] = cc->even[1];
Hans Verkuil32cd5272010-03-14 09:57:30 -030060 ivtv_call_hw(itv, IVTV_HW_SAA7127, vbi, s_vbi_data, &data);
Hans Verkuil33c0fca2007-08-23 06:32:46 -030061}
62
63static void ivtv_set_wss(struct ivtv *itv, int enabled, int mode)
64{
65 struct v4l2_sliced_vbi_data data;
66
67 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
68 return;
69 /* When using a 50 Hz system, always turn on the
70 wide screen signal with 4x3 ratio as the default.
71 Turning this signal on and off can confuse certain
72 TVs. As far as I can tell there is no reason not to
73 transmit this signal. */
Ian Armstrongc5874c92011-05-29 21:33:17 -030074 if ((itv->std_out & V4L2_STD_625_50) && !enabled) {
Hans Verkuil33c0fca2007-08-23 06:32:46 -030075 enabled = 1;
76 mode = 0x08; /* 4x3 full format */
77 }
78 data.id = V4L2_SLICED_WSS_625;
79 data.field = 0;
80 data.line = enabled ? 23 : 0;
81 data.data[0] = mode & 0xff;
82 data.data[1] = (mode >> 8) & 0xff;
Hans Verkuil32cd5272010-03-14 09:57:30 -030083 ivtv_call_hw(itv, IVTV_HW_SAA7127, vbi, s_vbi_data, &data);
Hans Verkuil33c0fca2007-08-23 06:32:46 -030084}
Hans Verkuil1a0adaf2007-04-27 12:31:25 -030085
86static int odd_parity(u8 c)
87{
88 c ^= (c >> 4);
89 c ^= (c >> 2);
90 c ^= (c >> 1);
91
92 return c & 1;
93}
94
Andy Wallsb0c45682010-12-18 10:48:17 -030095static void ivtv_write_vbi_line(struct ivtv *itv,
96 const struct v4l2_sliced_vbi_data *d,
97 struct vbi_cc *cc, int *found_cc)
Hans Verkuil1a0adaf2007-04-27 12:31:25 -030098{
Hans Verkuil2f3a9892007-08-25 14:11:23 -030099 struct vbi_info *vi = &itv->vbi;
Andy Wallsb0c45682010-12-18 10:48:17 -0300100
101 if (d->id == V4L2_SLICED_CAPTION_525 && d->line == 21) {
102 if (d->field) {
103 cc->even[0] = d->data[0];
104 cc->even[1] = d->data[1];
105 } else {
106 cc->odd[0] = d->data[0];
107 cc->odd[1] = d->data[1];
108 }
109 *found_cc = 1;
110 } else if (d->id == V4L2_SLICED_VPS && d->line == 16 && d->field == 0) {
111 struct vbi_vps vps;
112
113 vps.data[0] = d->data[2];
114 vps.data[1] = d->data[8];
115 vps.data[2] = d->data[9];
116 vps.data[3] = d->data[10];
117 vps.data[4] = d->data[11];
118 if (memcmp(&vps, &vi->vps_payload, sizeof(vps))) {
119 vi->vps_payload = vps;
120 set_bit(IVTV_F_I_UPDATE_VPS, &itv->i_flags);
121 }
122 } else if (d->id == V4L2_SLICED_WSS_625 &&
123 d->line == 23 && d->field == 0) {
124 int wss = d->data[0] | d->data[1] << 8;
125
126 if (vi->wss_payload != wss) {
127 vi->wss_payload = wss;
128 set_bit(IVTV_F_I_UPDATE_WSS, &itv->i_flags);
129 }
130 }
131}
132
133static void ivtv_write_vbi_cc_lines(struct ivtv *itv, const struct vbi_cc *cc)
134{
135 struct vbi_info *vi = &itv->vbi;
136
137 if (vi->cc_payload_idx < ARRAY_SIZE(vi->cc_payload)) {
138 memcpy(&vi->cc_payload[vi->cc_payload_idx], cc,
139 sizeof(struct vbi_cc));
140 vi->cc_payload_idx++;
141 set_bit(IVTV_F_I_UPDATE_CC, &itv->i_flags);
142 }
143}
144
145static void ivtv_write_vbi(struct ivtv *itv,
146 const struct v4l2_sliced_vbi_data *sliced,
147 size_t cnt)
148{
Hans Verkuil2f3a9892007-08-25 14:11:23 -0300149 struct vbi_cc cc = { .odd = { 0x80, 0x80 }, .even = { 0x80, 0x80 } };
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300150 int found_cc = 0;
Hans Verkuil2f3a9892007-08-25 14:11:23 -0300151 size_t i;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300152
Andy Wallsb0c45682010-12-18 10:48:17 -0300153 for (i = 0; i < cnt; i++)
154 ivtv_write_vbi_line(itv, sliced + i, &cc, &found_cc);
155
156 if (found_cc)
157 ivtv_write_vbi_cc_lines(itv, &cc);
158}
159
Andy Wallsddda4242010-12-19 21:59:56 -0300160ssize_t
161ivtv_write_vbi_from_user(struct ivtv *itv,
162 const struct v4l2_sliced_vbi_data __user *sliced,
163 size_t cnt)
Andy Wallsb0c45682010-12-18 10:48:17 -0300164{
165 struct vbi_cc cc = { .odd = { 0x80, 0x80 }, .even = { 0x80, 0x80 } };
166 int found_cc = 0;
167 size_t i;
168 struct v4l2_sliced_vbi_data d;
Andy Wallsddda4242010-12-19 21:59:56 -0300169 ssize_t ret = cnt * sizeof(struct v4l2_sliced_vbi_data);
Andy Wallsb0c45682010-12-18 10:48:17 -0300170
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300171 for (i = 0; i < cnt; i++) {
Andy Wallsb0c45682010-12-18 10:48:17 -0300172 if (copy_from_user(&d, sliced + i,
Andy Wallsddda4242010-12-19 21:59:56 -0300173 sizeof(struct v4l2_sliced_vbi_data))) {
174 ret = -EFAULT;
Andy Wallsb0c45682010-12-18 10:48:17 -0300175 break;
Andy Wallsddda4242010-12-19 21:59:56 -0300176 }
Andy Walls0d44b122011-02-08 22:39:28 -0300177 ivtv_write_vbi_line(itv, &d, &cc, &found_cc);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300178 }
Andy Wallsb0c45682010-12-18 10:48:17 -0300179
180 if (found_cc)
181 ivtv_write_vbi_cc_lines(itv, &cc);
Andy Wallsddda4242010-12-19 21:59:56 -0300182
183 return ret;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300184}
185
186static void copy_vbi_data(struct ivtv *itv, int lines, u32 pts_stamp)
187{
188 int line = 0;
189 int i;
190 u32 linemask[2] = { 0, 0 };
191 unsigned short size;
192 static const u8 mpeg_hdr_data[] = {
193 0x00, 0x00, 0x01, 0xba, 0x44, 0x00, 0x0c, 0x66,
194 0x24, 0x01, 0x01, 0xd1, 0xd3, 0xfa, 0xff, 0xff,
195 0x00, 0x00, 0x01, 0xbd, 0x00, 0x1a, 0x84, 0x80,
196 0x07, 0x21, 0x00, 0x5d, 0x63, 0xa7, 0xff, 0xff
197 };
198 const int sd = sizeof(mpeg_hdr_data); /* start of vbi data */
199 int idx = itv->vbi.frame % IVTV_VBI_FRAMES;
200 u8 *dst = &itv->vbi.sliced_mpeg_data[idx][0];
201
202 for (i = 0; i < lines; i++) {
203 int f, l;
204
205 if (itv->vbi.sliced_data[i].id == 0)
206 continue;
207
208 l = itv->vbi.sliced_data[i].line - 6;
209 f = itv->vbi.sliced_data[i].field;
210 if (f)
211 l += 18;
212 if (l < 32)
213 linemask[0] |= (1 << l);
214 else
215 linemask[1] |= (1 << (l - 32));
Hans Verkuilfeb5bce2008-05-01 09:22:13 -0300216 dst[sd + 12 + line * 43] =
217 ivtv_service2vbi(itv->vbi.sliced_data[i].id);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300218 memcpy(dst + sd + 12 + line * 43 + 1, itv->vbi.sliced_data[i].data, 42);
219 line++;
220 }
221 memcpy(dst, mpeg_hdr_data, sizeof(mpeg_hdr_data));
222 if (line == 36) {
223 /* All lines are used, so there is no space for the linemask
224 (the max size of the VBI data is 36 * 43 + 4 bytes).
225 So in this case we use the magic number 'ITV0'. */
226 memcpy(dst + sd, "ITV0", 4);
227 memcpy(dst + sd + 4, dst + sd + 12, line * 43);
228 size = 4 + ((43 * line + 3) & ~3);
229 } else {
230 memcpy(dst + sd, "itv0", 4);
Andy Walls6e1a63722009-03-14 20:03:26 -0300231 cpu_to_le32s(&linemask[0]);
232 cpu_to_le32s(&linemask[1]);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300233 memcpy(dst + sd + 4, &linemask[0], 8);
234 size = 12 + ((43 * line + 3) & ~3);
235 }
236 dst[4+16] = (size + 10) >> 8;
237 dst[5+16] = (size + 10) & 0xff;
238 dst[9+16] = 0x21 | ((pts_stamp >> 29) & 0x6);
239 dst[10+16] = (pts_stamp >> 22) & 0xff;
240 dst[11+16] = 1 | ((pts_stamp >> 14) & 0xff);
241 dst[12+16] = (pts_stamp >> 7) & 0xff;
242 dst[13+16] = 1 | ((pts_stamp & 0x7f) << 1);
243 itv->vbi.sliced_mpeg_size[idx] = sd + size;
244}
245
246static int ivtv_convert_ivtv_vbi(struct ivtv *itv, u8 *p)
247{
248 u32 linemask[2];
249 int i, l, id2;
250 int line = 0;
251
252 if (!memcmp(p, "itv0", 4)) {
253 memcpy(linemask, p + 4, 8);
254 p += 12;
255 } else if (!memcmp(p, "ITV0", 4)) {
256 linemask[0] = 0xffffffff;
257 linemask[1] = 0xf;
258 p += 4;
259 } else {
Hans Verkuil51a99c02007-08-18 15:16:00 -0300260 /* unknown VBI data, convert to empty VBI frame */
261 linemask[0] = linemask[1] = 0;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300262 }
263 for (i = 0; i < 36; i++) {
264 int err = 0;
265
266 if (i < 32 && !(linemask[0] & (1 << i)))
267 continue;
268 if (i >= 32 && !(linemask[1] & (1 << (i - 32))))
269 continue;
270 id2 = *p & 0xf;
271 switch (id2) {
272 case IVTV_SLICED_TYPE_TELETEXT_B:
273 id2 = V4L2_SLICED_TELETEXT_B;
274 break;
275 case IVTV_SLICED_TYPE_CAPTION_525:
276 id2 = V4L2_SLICED_CAPTION_525;
277 err = !odd_parity(p[1]) || !odd_parity(p[2]);
278 break;
279 case IVTV_SLICED_TYPE_VPS:
280 id2 = V4L2_SLICED_VPS;
281 break;
282 case IVTV_SLICED_TYPE_WSS_625:
283 id2 = V4L2_SLICED_WSS_625;
284 break;
285 default:
286 id2 = 0;
287 break;
288 }
289 if (err == 0) {
290 l = (i < 18) ? i + 6 : i - 18 + 6;
291 itv->vbi.sliced_dec_data[line].line = l;
292 itv->vbi.sliced_dec_data[line].field = i >= 18;
293 itv->vbi.sliced_dec_data[line].id = id2;
294 memcpy(itv->vbi.sliced_dec_data[line].data, p + 1, 42);
295 line++;
296 }
297 p += 43;
298 }
299 while (line < 36) {
300 itv->vbi.sliced_dec_data[line].id = 0;
301 itv->vbi.sliced_dec_data[line].line = 0;
302 itv->vbi.sliced_dec_data[line].field = 0;
303 line++;
304 }
305 return line * sizeof(itv->vbi.sliced_dec_data[0]);
306}
307
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300308/* Compress raw VBI format, removes leading SAV codes and surplus space after the
309 field.
310 Returns new compressed size. */
311static u32 compress_raw_buf(struct ivtv *itv, u8 *buf, u32 size)
312{
313 u32 line_size = itv->vbi.raw_decoder_line_size;
314 u32 lines = itv->vbi.count;
315 u8 sav1 = itv->vbi.raw_decoder_sav_odd_field;
316 u8 sav2 = itv->vbi.raw_decoder_sav_even_field;
317 u8 *q = buf;
318 u8 *p;
319 int i;
320
321 for (i = 0; i < lines; i++) {
322 p = buf + i * line_size;
323
324 /* Look for SAV code */
325 if (p[0] != 0xff || p[1] || p[2] || (p[3] != sav1 && p[3] != sav2)) {
326 break;
327 }
328 memcpy(q, p + 4, line_size - 4);
329 q += line_size - 4;
330 }
331 return lines * (line_size - 4);
332}
333
334
335/* Compressed VBI format, all found sliced blocks put next to one another
336 Returns new compressed size */
337static u32 compress_sliced_buf(struct ivtv *itv, u32 line, u8 *buf, u32 size, u8 sav)
338{
339 u32 line_size = itv->vbi.sliced_decoder_line_size;
340 struct v4l2_decode_vbi_line vbi;
341 int i;
Hans Verkuild526afe2008-09-03 16:47:14 -0300342 unsigned lines = 0;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300343
344 /* find the first valid line */
345 for (i = 0; i < size; i++, buf++) {
346 if (buf[0] == 0xff && !buf[1] && !buf[2] && buf[3] == sav)
347 break;
348 }
349
350 size -= i;
351 if (size < line_size) {
352 return line;
353 }
354 for (i = 0; i < size / line_size; i++) {
355 u8 *p = buf + i * line_size;
356
357 /* Look for SAV code */
358 if (p[0] != 0xff || p[1] || p[2] || p[3] != sav) {
359 continue;
360 }
361 vbi.p = p + 4;
Hans Verkuil32cd5272010-03-14 09:57:30 -0300362 v4l2_subdev_call(itv->sd_video, vbi, decode_vbi_line, &vbi);
Hans Verkuild526afe2008-09-03 16:47:14 -0300363 if (vbi.type && !(lines & (1 << vbi.line))) {
364 lines |= 1 << vbi.line;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300365 itv->vbi.sliced_data[line].id = vbi.type;
366 itv->vbi.sliced_data[line].field = vbi.is_second_field;
367 itv->vbi.sliced_data[line].line = vbi.line;
368 memcpy(itv->vbi.sliced_data[line].data, vbi.p, 42);
369 line++;
370 }
371 }
372 return line;
373}
374
375void ivtv_process_vbi_data(struct ivtv *itv, struct ivtv_buffer *buf,
376 u64 pts_stamp, int streamtype)
377{
378 u8 *p = (u8 *) buf->buf;
379 u32 size = buf->bytesused;
380 int y;
381
382 /* Raw VBI data */
Hans Verkuila8b86432008-10-04 08:05:30 -0300383 if (streamtype == IVTV_ENC_STREAM_TYPE_VBI && ivtv_raw_vbi(itv)) {
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300384 u8 type;
385
386 ivtv_buf_swap(buf);
387
388 type = p[3];
389
390 size = buf->bytesused = compress_raw_buf(itv, p, size);
391
392 /* second field of the frame? */
393 if (type == itv->vbi.raw_decoder_sav_even_field) {
394 /* Dirty hack needed for backwards
395 compatibility of old VBI software. */
396 p += size - 4;
397 memcpy(p, &itv->vbi.frame, 4);
398 itv->vbi.frame++;
399 }
400 return;
401 }
402
403 /* Sliced VBI data with data insertion */
404 if (streamtype == IVTV_ENC_STREAM_TYPE_VBI) {
405 int lines;
406
407 ivtv_buf_swap(buf);
408
409 /* first field */
410 lines = compress_sliced_buf(itv, 0, p, size / 2,
411 itv->vbi.sliced_decoder_sav_odd_field);
412 /* second field */
413 /* experimentation shows that the second half does not always begin
414 at the exact address. So start a bit earlier (hence 32). */
415 lines = compress_sliced_buf(itv, lines, p + size / 2 - 32, size / 2 + 32,
416 itv->vbi.sliced_decoder_sav_even_field);
417 /* always return at least one empty line */
418 if (lines == 0) {
419 itv->vbi.sliced_data[0].id = 0;
420 itv->vbi.sliced_data[0].line = 0;
421 itv->vbi.sliced_data[0].field = 0;
422 lines = 1;
423 }
424 buf->bytesused = size = lines * sizeof(itv->vbi.sliced_data[0]);
425 memcpy(p, &itv->vbi.sliced_data[0], size);
426
427 if (itv->vbi.insert_mpeg) {
428 copy_vbi_data(itv, lines, pts_stamp);
429 }
430 itv->vbi.frame++;
431 return;
432 }
433
434 /* Sliced VBI re-inserted from an MPEG stream */
435 if (streamtype == IVTV_DEC_STREAM_TYPE_VBI) {
436 /* If the size is not 4-byte aligned, then the starting address
437 for the swapping is also shifted. After swapping the data the
438 real start address of the VBI data is exactly 4 bytes after the
439 original start. It's a bit fiddly but it works like a charm.
440 Non-4-byte alignment happens when an lseek is done on the input
441 mpeg file to a non-4-byte aligned position. So on arrival here
442 the VBI data is also non-4-byte aligned. */
443 int offset = size & 3;
444 int cnt;
445
446 if (offset) {
447 p += 4 - offset;
448 }
449 /* Swap Buffer */
450 for (y = 0; y < size; y += 4) {
451 swab32s((u32 *)(p + y));
452 }
453
454 cnt = ivtv_convert_ivtv_vbi(itv, p + offset);
455 memcpy(buf->buf, itv->vbi.sliced_dec_data, cnt);
456 buf->bytesused = cnt;
457
Hans Verkuil2f3a9892007-08-25 14:11:23 -0300458 ivtv_write_vbi(itv, itv->vbi.sliced_dec_data,
459 cnt / sizeof(itv->vbi.sliced_dec_data[0]));
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300460 return;
461 }
462}
463
Hans Verkuil2f3a9892007-08-25 14:11:23 -0300464void ivtv_disable_cc(struct ivtv *itv)
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300465{
Hans Verkuil2f3a9892007-08-25 14:11:23 -0300466 struct vbi_cc cc = { .odd = { 0x80, 0x80 }, .even = { 0x80, 0x80 } };
467
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300468 clear_bit(IVTV_F_I_UPDATE_CC, &itv->i_flags);
Hans Verkuil2f3a9892007-08-25 14:11:23 -0300469 ivtv_set_cc(itv, 0, &cc);
470 itv->vbi.cc_payload_idx = 0;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300471}
472
Hans Verkuil1e13f9e2007-03-10 06:52:02 -0300473
Hans Verkuildc02d502007-05-19 14:07:16 -0300474void ivtv_vbi_work_handler(struct ivtv *itv)
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300475{
Hans Verkuil2f3a9892007-08-25 14:11:23 -0300476 struct vbi_info *vi = &itv->vbi;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300477 struct v4l2_sliced_vbi_data data;
Hans Verkuil2f3a9892007-08-25 14:11:23 -0300478 struct vbi_cc cc = { .odd = { 0x80, 0x80 }, .even = { 0x80, 0x80 } };
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300479
480 /* Lock */
481 if (itv->output_mode == OUT_PASSTHROUGH) {
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300482 if (itv->is_50hz) {
483 data.id = V4L2_SLICED_WSS_625;
484 data.field = 0;
485
Hans Verkuil32cd5272010-03-14 09:57:30 -0300486 if (v4l2_subdev_call(itv->sd_video, vbi, g_vbi_data, &data) == 0) {
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300487 ivtv_set_wss(itv, 1, data.data[0] & 0xf);
Hans Verkuil2f3a9892007-08-25 14:11:23 -0300488 vi->wss_missing_cnt = 0;
489 } else if (vi->wss_missing_cnt == 4) {
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300490 ivtv_set_wss(itv, 1, 0x8); /* 4x3 full format */
491 } else {
Hans Verkuil2f3a9892007-08-25 14:11:23 -0300492 vi->wss_missing_cnt++;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300493 }
494 }
495 else {
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300496 int mode = 0;
497
498 data.id = V4L2_SLICED_CAPTION_525;
499 data.field = 0;
Hans Verkuil32cd5272010-03-14 09:57:30 -0300500 if (v4l2_subdev_call(itv->sd_video, vbi, g_vbi_data, &data) == 0) {
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300501 mode |= 1;
Hans Verkuil2f3a9892007-08-25 14:11:23 -0300502 cc.odd[0] = data.data[0];
503 cc.odd[1] = data.data[1];
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300504 }
505 data.field = 1;
Hans Verkuil32cd5272010-03-14 09:57:30 -0300506 if (v4l2_subdev_call(itv->sd_video, vbi, g_vbi_data, &data) == 0) {
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300507 mode |= 2;
Hans Verkuil2f3a9892007-08-25 14:11:23 -0300508 cc.even[0] = data.data[0];
509 cc.even[1] = data.data[1];
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300510 }
511 if (mode) {
Hans Verkuil2f3a9892007-08-25 14:11:23 -0300512 vi->cc_missing_cnt = 0;
513 ivtv_set_cc(itv, mode, &cc);
514 } else if (vi->cc_missing_cnt == 4) {
515 ivtv_set_cc(itv, 0, &cc);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300516 } else {
Hans Verkuil2f3a9892007-08-25 14:11:23 -0300517 vi->cc_missing_cnt++;
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300518 }
519 }
520 return;
521 }
522
523 if (test_and_clear_bit(IVTV_F_I_UPDATE_WSS, &itv->i_flags)) {
Hans Verkuil2f3a9892007-08-25 14:11:23 -0300524 ivtv_set_wss(itv, 1, vi->wss_payload & 0xf);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300525 }
526
Hans Verkuil2f3a9892007-08-25 14:11:23 -0300527 if (test_bit(IVTV_F_I_UPDATE_CC, &itv->i_flags)) {
528 if (vi->cc_payload_idx == 0) {
529 clear_bit(IVTV_F_I_UPDATE_CC, &itv->i_flags);
530 ivtv_set_cc(itv, 3, &cc);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300531 }
Hans Verkuil2f3a9892007-08-25 14:11:23 -0300532 while (vi->cc_payload_idx) {
533 cc = vi->cc_payload[0];
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300534
Hans Verkuil2f3a9892007-08-25 14:11:23 -0300535 memcpy(vi->cc_payload, vi->cc_payload + 1,
536 sizeof(vi->cc_payload) - sizeof(vi->cc_payload[0]));
537 vi->cc_payload_idx--;
538 if (vi->cc_payload_idx && cc.odd[0] == 0x80 && cc.odd[1] == 0x80)
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300539 continue;
540
Hans Verkuil2f3a9892007-08-25 14:11:23 -0300541 ivtv_set_cc(itv, 3, &cc);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300542 break;
543 }
544 }
545
546 if (test_and_clear_bit(IVTV_F_I_UPDATE_VPS, &itv->i_flags)) {
Hans Verkuil2f3a9892007-08-25 14:11:23 -0300547 ivtv_set_vps(itv, 1);
Hans Verkuil1a0adaf2007-04-27 12:31:25 -0300548 }
549}