This source file includes following definitions.
- ivtv_set_vps
- ivtv_set_cc
- ivtv_set_wss
- odd_parity
- ivtv_write_vbi_line
- ivtv_write_vbi_cc_lines
- ivtv_write_vbi
- ivtv_write_vbi_from_user
- copy_vbi_data
- ivtv_convert_ivtv_vbi
- compress_raw_buf
- compress_sliced_buf
- ivtv_process_vbi_data
- ivtv_disable_cc
- ivtv_vbi_work_handler
1
2
3
4
5
6
7
8 #include "ivtv-driver.h"
9 #include "ivtv-i2c.h"
10 #include "ivtv-ioctl.h"
11 #include "ivtv-queue.h"
12 #include "ivtv-cards.h"
13 #include "ivtv-vbi.h"
14
15 static void ivtv_set_vps(struct ivtv *itv, int enabled)
16 {
17 struct v4l2_sliced_vbi_data data;
18
19 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
20 return;
21 data.id = V4L2_SLICED_VPS;
22 data.field = 0;
23 data.line = enabled ? 16 : 0;
24 data.data[2] = itv->vbi.vps_payload.data[0];
25 data.data[8] = itv->vbi.vps_payload.data[1];
26 data.data[9] = itv->vbi.vps_payload.data[2];
27 data.data[10] = itv->vbi.vps_payload.data[3];
28 data.data[11] = itv->vbi.vps_payload.data[4];
29 ivtv_call_hw(itv, IVTV_HW_SAA7127, vbi, s_vbi_data, &data);
30 }
31
32 static void ivtv_set_cc(struct ivtv *itv, int mode, const struct vbi_cc *cc)
33 {
34 struct v4l2_sliced_vbi_data data;
35
36 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
37 return;
38 data.id = V4L2_SLICED_CAPTION_525;
39 data.field = 0;
40 data.line = (mode & 1) ? 21 : 0;
41 data.data[0] = cc->odd[0];
42 data.data[1] = cc->odd[1];
43 ivtv_call_hw(itv, IVTV_HW_SAA7127, vbi, s_vbi_data, &data);
44 data.field = 1;
45 data.line = (mode & 2) ? 21 : 0;
46 data.data[0] = cc->even[0];
47 data.data[1] = cc->even[1];
48 ivtv_call_hw(itv, IVTV_HW_SAA7127, vbi, s_vbi_data, &data);
49 }
50
51 static void ivtv_set_wss(struct ivtv *itv, int enabled, int mode)
52 {
53 struct v4l2_sliced_vbi_data data;
54
55 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
56 return;
57
58
59
60
61
62 if ((itv->std_out & V4L2_STD_625_50) && !enabled) {
63 enabled = 1;
64 mode = 0x08;
65 }
66 data.id = V4L2_SLICED_WSS_625;
67 data.field = 0;
68 data.line = enabled ? 23 : 0;
69 data.data[0] = mode & 0xff;
70 data.data[1] = (mode >> 8) & 0xff;
71 ivtv_call_hw(itv, IVTV_HW_SAA7127, vbi, s_vbi_data, &data);
72 }
73
74 static int odd_parity(u8 c)
75 {
76 c ^= (c >> 4);
77 c ^= (c >> 2);
78 c ^= (c >> 1);
79
80 return c & 1;
81 }
82
83 static void ivtv_write_vbi_line(struct ivtv *itv,
84 const struct v4l2_sliced_vbi_data *d,
85 struct vbi_cc *cc, int *found_cc)
86 {
87 struct vbi_info *vi = &itv->vbi;
88
89 if (d->id == V4L2_SLICED_CAPTION_525 && d->line == 21) {
90 if (d->field) {
91 cc->even[0] = d->data[0];
92 cc->even[1] = d->data[1];
93 } else {
94 cc->odd[0] = d->data[0];
95 cc->odd[1] = d->data[1];
96 }
97 *found_cc = 1;
98 } else if (d->id == V4L2_SLICED_VPS && d->line == 16 && d->field == 0) {
99 struct vbi_vps vps;
100
101 vps.data[0] = d->data[2];
102 vps.data[1] = d->data[8];
103 vps.data[2] = d->data[9];
104 vps.data[3] = d->data[10];
105 vps.data[4] = d->data[11];
106 if (memcmp(&vps, &vi->vps_payload, sizeof(vps))) {
107 vi->vps_payload = vps;
108 set_bit(IVTV_F_I_UPDATE_VPS, &itv->i_flags);
109 }
110 } else if (d->id == V4L2_SLICED_WSS_625 &&
111 d->line == 23 && d->field == 0) {
112 int wss = d->data[0] | d->data[1] << 8;
113
114 if (vi->wss_payload != wss) {
115 vi->wss_payload = wss;
116 set_bit(IVTV_F_I_UPDATE_WSS, &itv->i_flags);
117 }
118 }
119 }
120
121 static void ivtv_write_vbi_cc_lines(struct ivtv *itv, const struct vbi_cc *cc)
122 {
123 struct vbi_info *vi = &itv->vbi;
124
125 if (vi->cc_payload_idx < ARRAY_SIZE(vi->cc_payload)) {
126 memcpy(&vi->cc_payload[vi->cc_payload_idx], cc,
127 sizeof(struct vbi_cc));
128 vi->cc_payload_idx++;
129 set_bit(IVTV_F_I_UPDATE_CC, &itv->i_flags);
130 }
131 }
132
133 static void ivtv_write_vbi(struct ivtv *itv,
134 const struct v4l2_sliced_vbi_data *sliced,
135 size_t cnt)
136 {
137 struct vbi_cc cc = { .odd = { 0x80, 0x80 }, .even = { 0x80, 0x80 } };
138 int found_cc = 0;
139 size_t i;
140
141 for (i = 0; i < cnt; i++)
142 ivtv_write_vbi_line(itv, sliced + i, &cc, &found_cc);
143
144 if (found_cc)
145 ivtv_write_vbi_cc_lines(itv, &cc);
146 }
147
148 ssize_t
149 ivtv_write_vbi_from_user(struct ivtv *itv,
150 const struct v4l2_sliced_vbi_data __user *sliced,
151 size_t cnt)
152 {
153 struct vbi_cc cc = { .odd = { 0x80, 0x80 }, .even = { 0x80, 0x80 } };
154 int found_cc = 0;
155 size_t i;
156 struct v4l2_sliced_vbi_data d;
157 ssize_t ret = cnt * sizeof(struct v4l2_sliced_vbi_data);
158
159 for (i = 0; i < cnt; i++) {
160 if (copy_from_user(&d, sliced + i,
161 sizeof(struct v4l2_sliced_vbi_data))) {
162 ret = -EFAULT;
163 break;
164 }
165 ivtv_write_vbi_line(itv, &d, &cc, &found_cc);
166 }
167
168 if (found_cc)
169 ivtv_write_vbi_cc_lines(itv, &cc);
170
171 return ret;
172 }
173
174 static void copy_vbi_data(struct ivtv *itv, int lines, u32 pts_stamp)
175 {
176 int line = 0;
177 int i;
178 u32 linemask[2] = { 0, 0 };
179 unsigned short size;
180 static const u8 mpeg_hdr_data[] = {
181 0x00, 0x00, 0x01, 0xba, 0x44, 0x00, 0x0c, 0x66,
182 0x24, 0x01, 0x01, 0xd1, 0xd3, 0xfa, 0xff, 0xff,
183 0x00, 0x00, 0x01, 0xbd, 0x00, 0x1a, 0x84, 0x80,
184 0x07, 0x21, 0x00, 0x5d, 0x63, 0xa7, 0xff, 0xff
185 };
186 const int sd = sizeof(mpeg_hdr_data);
187 int idx = itv->vbi.frame % IVTV_VBI_FRAMES;
188 u8 *dst = &itv->vbi.sliced_mpeg_data[idx][0];
189
190 for (i = 0; i < lines; i++) {
191 int f, l;
192
193 if (itv->vbi.sliced_data[i].id == 0)
194 continue;
195
196 l = itv->vbi.sliced_data[i].line - 6;
197 f = itv->vbi.sliced_data[i].field;
198 if (f)
199 l += 18;
200 if (l < 32)
201 linemask[0] |= (1 << l);
202 else
203 linemask[1] |= (1 << (l - 32));
204 dst[sd + 12 + line * 43] =
205 ivtv_service2vbi(itv->vbi.sliced_data[i].id);
206 memcpy(dst + sd + 12 + line * 43 + 1, itv->vbi.sliced_data[i].data, 42);
207 line++;
208 }
209 memcpy(dst, mpeg_hdr_data, sizeof(mpeg_hdr_data));
210 if (line == 36) {
211
212
213
214 memcpy(dst + sd, "ITV0", 4);
215 memmove(dst + sd + 4, dst + sd + 12, line * 43);
216 size = 4 + ((43 * line + 3) & ~3);
217 } else {
218 memcpy(dst + sd, "itv0", 4);
219 cpu_to_le32s(&linemask[0]);
220 cpu_to_le32s(&linemask[1]);
221 memcpy(dst + sd + 4, &linemask[0], 8);
222 size = 12 + ((43 * line + 3) & ~3);
223 }
224 dst[4+16] = (size + 10) >> 8;
225 dst[5+16] = (size + 10) & 0xff;
226 dst[9+16] = 0x21 | ((pts_stamp >> 29) & 0x6);
227 dst[10+16] = (pts_stamp >> 22) & 0xff;
228 dst[11+16] = 1 | ((pts_stamp >> 14) & 0xff);
229 dst[12+16] = (pts_stamp >> 7) & 0xff;
230 dst[13+16] = 1 | ((pts_stamp & 0x7f) << 1);
231 itv->vbi.sliced_mpeg_size[idx] = sd + size;
232 }
233
234 static int ivtv_convert_ivtv_vbi(struct ivtv *itv, u8 *p)
235 {
236 u32 linemask[2];
237 int i, l, id2;
238 int line = 0;
239
240 if (!memcmp(p, "itv0", 4)) {
241 memcpy(linemask, p + 4, 8);
242 p += 12;
243 } else if (!memcmp(p, "ITV0", 4)) {
244 linemask[0] = 0xffffffff;
245 linemask[1] = 0xf;
246 p += 4;
247 } else {
248
249 linemask[0] = linemask[1] = 0;
250 }
251 for (i = 0; i < 36; i++) {
252 int err = 0;
253
254 if (i < 32 && !(linemask[0] & (1 << i)))
255 continue;
256 if (i >= 32 && !(linemask[1] & (1 << (i - 32))))
257 continue;
258 id2 = *p & 0xf;
259 switch (id2) {
260 case IVTV_SLICED_TYPE_TELETEXT_B:
261 id2 = V4L2_SLICED_TELETEXT_B;
262 break;
263 case IVTV_SLICED_TYPE_CAPTION_525:
264 id2 = V4L2_SLICED_CAPTION_525;
265 err = !odd_parity(p[1]) || !odd_parity(p[2]);
266 break;
267 case IVTV_SLICED_TYPE_VPS:
268 id2 = V4L2_SLICED_VPS;
269 break;
270 case IVTV_SLICED_TYPE_WSS_625:
271 id2 = V4L2_SLICED_WSS_625;
272 break;
273 default:
274 id2 = 0;
275 break;
276 }
277 if (err == 0) {
278 l = (i < 18) ? i + 6 : i - 18 + 6;
279 itv->vbi.sliced_dec_data[line].line = l;
280 itv->vbi.sliced_dec_data[line].field = i >= 18;
281 itv->vbi.sliced_dec_data[line].id = id2;
282 memcpy(itv->vbi.sliced_dec_data[line].data, p + 1, 42);
283 line++;
284 }
285 p += 43;
286 }
287 while (line < 36) {
288 itv->vbi.sliced_dec_data[line].id = 0;
289 itv->vbi.sliced_dec_data[line].line = 0;
290 itv->vbi.sliced_dec_data[line].field = 0;
291 line++;
292 }
293 return line * sizeof(itv->vbi.sliced_dec_data[0]);
294 }
295
296
297
298
299 static u32 compress_raw_buf(struct ivtv *itv, u8 *buf, u32 size)
300 {
301 u32 line_size = itv->vbi.raw_decoder_line_size;
302 u32 lines = itv->vbi.count;
303 u8 sav1 = itv->vbi.raw_decoder_sav_odd_field;
304 u8 sav2 = itv->vbi.raw_decoder_sav_even_field;
305 u8 *q = buf;
306 u8 *p;
307 int i;
308
309 for (i = 0; i < lines; i++) {
310 p = buf + i * line_size;
311
312
313 if (p[0] != 0xff || p[1] || p[2] || (p[3] != sav1 && p[3] != sav2)) {
314 break;
315 }
316 memcpy(q, p + 4, line_size - 4);
317 q += line_size - 4;
318 }
319 return lines * (line_size - 4);
320 }
321
322
323
324
325 static u32 compress_sliced_buf(struct ivtv *itv, u32 line, u8 *buf, u32 size, u8 sav)
326 {
327 u32 line_size = itv->vbi.sliced_decoder_line_size;
328 struct v4l2_decode_vbi_line vbi;
329 int i;
330 unsigned lines = 0;
331
332
333 for (i = 0; i < size; i++, buf++) {
334 if (buf[0] == 0xff && !buf[1] && !buf[2] && buf[3] == sav)
335 break;
336 }
337
338 size -= i;
339 if (size < line_size) {
340 return line;
341 }
342 for (i = 0; i < size / line_size; i++) {
343 u8 *p = buf + i * line_size;
344
345
346 if (p[0] != 0xff || p[1] || p[2] || p[3] != sav) {
347 continue;
348 }
349 vbi.p = p + 4;
350 v4l2_subdev_call(itv->sd_video, vbi, decode_vbi_line, &vbi);
351 if (vbi.type && !(lines & (1 << vbi.line))) {
352 lines |= 1 << vbi.line;
353 itv->vbi.sliced_data[line].id = vbi.type;
354 itv->vbi.sliced_data[line].field = vbi.is_second_field;
355 itv->vbi.sliced_data[line].line = vbi.line;
356 memcpy(itv->vbi.sliced_data[line].data, vbi.p, 42);
357 line++;
358 }
359 }
360 return line;
361 }
362
363 void ivtv_process_vbi_data(struct ivtv *itv, struct ivtv_buffer *buf,
364 u64 pts_stamp, int streamtype)
365 {
366 u8 *p = (u8 *) buf->buf;
367 u32 size = buf->bytesused;
368 int y;
369
370
371 if (streamtype == IVTV_ENC_STREAM_TYPE_VBI && ivtv_raw_vbi(itv)) {
372 u8 type;
373
374 ivtv_buf_swap(buf);
375
376 type = p[3];
377
378 size = buf->bytesused = compress_raw_buf(itv, p, size);
379
380
381 if (type == itv->vbi.raw_decoder_sav_even_field) {
382
383
384 p += size - 4;
385 memcpy(p, &itv->vbi.frame, 4);
386 itv->vbi.frame++;
387 }
388 return;
389 }
390
391
392 if (streamtype == IVTV_ENC_STREAM_TYPE_VBI) {
393 int lines;
394
395 ivtv_buf_swap(buf);
396
397
398 lines = compress_sliced_buf(itv, 0, p, size / 2,
399 itv->vbi.sliced_decoder_sav_odd_field);
400
401
402
403 lines = compress_sliced_buf(itv, lines, p + size / 2 - 32, size / 2 + 32,
404 itv->vbi.sliced_decoder_sav_even_field);
405
406 if (lines == 0) {
407 itv->vbi.sliced_data[0].id = 0;
408 itv->vbi.sliced_data[0].line = 0;
409 itv->vbi.sliced_data[0].field = 0;
410 lines = 1;
411 }
412 buf->bytesused = size = lines * sizeof(itv->vbi.sliced_data[0]);
413 memcpy(p, &itv->vbi.sliced_data[0], size);
414
415 if (itv->vbi.insert_mpeg) {
416 copy_vbi_data(itv, lines, pts_stamp);
417 }
418 itv->vbi.frame++;
419 return;
420 }
421
422
423 if (streamtype == IVTV_DEC_STREAM_TYPE_VBI) {
424
425
426
427
428
429
430
431 int offset = size & 3;
432 int cnt;
433
434 if (offset) {
435 p += 4 - offset;
436 }
437
438 for (y = 0; y < size; y += 4) {
439 swab32s((u32 *)(p + y));
440 }
441
442 cnt = ivtv_convert_ivtv_vbi(itv, p + offset);
443 memcpy(buf->buf, itv->vbi.sliced_dec_data, cnt);
444 buf->bytesused = cnt;
445
446 ivtv_write_vbi(itv, itv->vbi.sliced_dec_data,
447 cnt / sizeof(itv->vbi.sliced_dec_data[0]));
448 return;
449 }
450 }
451
452 void ivtv_disable_cc(struct ivtv *itv)
453 {
454 struct vbi_cc cc = { .odd = { 0x80, 0x80 }, .even = { 0x80, 0x80 } };
455
456 clear_bit(IVTV_F_I_UPDATE_CC, &itv->i_flags);
457 ivtv_set_cc(itv, 0, &cc);
458 itv->vbi.cc_payload_idx = 0;
459 }
460
461
462 void ivtv_vbi_work_handler(struct ivtv *itv)
463 {
464 struct vbi_info *vi = &itv->vbi;
465 struct v4l2_sliced_vbi_data data;
466 struct vbi_cc cc = { .odd = { 0x80, 0x80 }, .even = { 0x80, 0x80 } };
467
468
469 if (itv->output_mode == OUT_PASSTHROUGH) {
470 if (itv->is_50hz) {
471 data.id = V4L2_SLICED_WSS_625;
472 data.field = 0;
473
474 if (v4l2_subdev_call(itv->sd_video, vbi, g_vbi_data, &data) == 0) {
475 ivtv_set_wss(itv, 1, data.data[0] & 0xf);
476 vi->wss_missing_cnt = 0;
477 } else if (vi->wss_missing_cnt == 4) {
478 ivtv_set_wss(itv, 1, 0x8);
479 } else {
480 vi->wss_missing_cnt++;
481 }
482 }
483 else {
484 int mode = 0;
485
486 data.id = V4L2_SLICED_CAPTION_525;
487 data.field = 0;
488 if (v4l2_subdev_call(itv->sd_video, vbi, g_vbi_data, &data) == 0) {
489 mode |= 1;
490 cc.odd[0] = data.data[0];
491 cc.odd[1] = data.data[1];
492 }
493 data.field = 1;
494 if (v4l2_subdev_call(itv->sd_video, vbi, g_vbi_data, &data) == 0) {
495 mode |= 2;
496 cc.even[0] = data.data[0];
497 cc.even[1] = data.data[1];
498 }
499 if (mode) {
500 vi->cc_missing_cnt = 0;
501 ivtv_set_cc(itv, mode, &cc);
502 } else if (vi->cc_missing_cnt == 4) {
503 ivtv_set_cc(itv, 0, &cc);
504 } else {
505 vi->cc_missing_cnt++;
506 }
507 }
508 return;
509 }
510
511 if (test_and_clear_bit(IVTV_F_I_UPDATE_WSS, &itv->i_flags)) {
512 ivtv_set_wss(itv, 1, vi->wss_payload & 0xf);
513 }
514
515 if (test_bit(IVTV_F_I_UPDATE_CC, &itv->i_flags)) {
516 if (vi->cc_payload_idx == 0) {
517 clear_bit(IVTV_F_I_UPDATE_CC, &itv->i_flags);
518 ivtv_set_cc(itv, 3, &cc);
519 }
520 while (vi->cc_payload_idx) {
521 cc = vi->cc_payload[0];
522
523 memmove(vi->cc_payload, vi->cc_payload + 1,
524 sizeof(vi->cc_payload) - sizeof(vi->cc_payload[0]));
525 vi->cc_payload_idx--;
526 if (vi->cc_payload_idx && cc.odd[0] == 0x80 && cc.odd[1] == 0x80)
527 continue;
528
529 ivtv_set_cc(itv, 3, &cc);
530 break;
531 }
532 }
533
534 if (test_and_clear_bit(IVTV_F_I_UPDATE_VPS, &itv->i_flags)) {
535 ivtv_set_vps(itv, 1);
536 }
537 }