1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 Vertical Blank Interval support functions
4 Copyright (C) 2004-2007 Hans Verkuil <hverkuil@xs4all.nl>
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
15static 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
32static 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
51static 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 /* When using a 50 Hz system, always turn on the
58 wide screen signal with 4x3 ratio as the default.
59 Turning this signal on and off can confuse certain
60 TVs. As far as I can tell there is no reason not to
61 transmit this signal. */
62 if ((itv->std_out & V4L2_STD_625_50) && !enabled) {
63 enabled = 1;
64 mode = 0x08; /* 4x3 full format */
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
74static 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
83static 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(p: &vps, q: &vi->vps_payload, size: sizeof(vps))) {
107 vi->vps_payload = vps;
108 set_bit(IVTV_F_I_UPDATE_VPS, addr: &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, addr: &itv->i_flags);
117 }
118 }
119}
120
121static 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, addr: &itv->i_flags);
130 }
131}
132
133static 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, d: sliced + i, cc: &cc, found_cc: &found_cc);
143
144 if (found_cc)
145 ivtv_write_vbi_cc_lines(itv, cc: &cc);
146}
147
148ssize_t
149ivtv_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(to: &d, from: sliced + i,
161 n: sizeof(struct v4l2_sliced_vbi_data))) {
162 ret = -EFAULT;
163 break;
164 }
165 ivtv_write_vbi_line(itv, d: &d, cc: &cc, found_cc: &found_cc);
166 }
167
168 if (found_cc)
169 ivtv_write_vbi_cc_lines(itv, cc: &cc);
170
171 return ret;
172}
173
174static 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); /* start of vbi 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(type: 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 /* All lines are used, so there is no space for the linemask
212 (the max size of the VBI data is 36 * 43 + 4 bytes).
213 So in this case we use the magic number 'ITV0'. */
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
234static 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, q: "itv0", size: 4)) {
241 memcpy(linemask, p + 4, 8);
242 p += 12;
243 } else if (!memcmp(p, q: "ITV0", size: 4)) {
244 linemask[0] = 0xffffffff;
245 linemask[1] = 0xf;
246 p += 4;
247 } else {
248 /* unknown VBI data, convert to empty VBI frame */
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(c: p[1]) || !odd_parity(c: 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/* Compress raw VBI format, removes leading SAV codes and surplus space after the
297 field.
298 Returns new compressed size. */
299static 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 /* Look for SAV code */
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/* Compressed VBI format, all found sliced blocks put next to one another
324 Returns new compressed size */
325static 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 /* find the first valid line */
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 /* Look for SAV code */
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
363void 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 /* Raw VBI data */
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, buf: p, size);
379
380 /* second field of the frame? */
381 if (type == itv->vbi.raw_decoder_sav_even_field) {
382 /* Dirty hack needed for backwards
383 compatibility of old VBI software. */
384 p += size - 4;
385 memcpy(p, &itv->vbi.frame, 4);
386 itv->vbi.frame++;
387 }
388 return;
389 }
390
391 /* Sliced VBI data with data insertion */
392 if (streamtype == IVTV_ENC_STREAM_TYPE_VBI) {
393 int lines;
394
395 ivtv_buf_swap(buf);
396
397 /* first field */
398 lines = compress_sliced_buf(itv, line: 0, buf: p, size: size / 2,
399 sav: itv->vbi.sliced_decoder_sav_odd_field);
400 /* second field */
401 /* experimentation shows that the second half does not always begin
402 at the exact address. So start a bit earlier (hence 32). */
403 lines = compress_sliced_buf(itv, line: lines, buf: p + size / 2 - 32, size: size / 2 + 32,
404 sav: itv->vbi.sliced_decoder_sav_even_field);
405 /* always return at least one empty line */
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 /* Sliced VBI re-inserted from an MPEG stream */
423 if (streamtype == IVTV_DEC_STREAM_TYPE_VBI) {
424 /* If the size is not 4-byte aligned, then the starting address
425 for the swapping is also shifted. After swapping the data the
426 real start address of the VBI data is exactly 4 bytes after the
427 original start. It's a bit fiddly but it works like a charm.
428 Non-4-byte alignment happens when an lseek is done on the input
429 mpeg file to a non-4-byte aligned position. So on arrival here
430 the VBI data is also non-4-byte aligned. */
431 int offset = size & 3;
432 int cnt;
433
434 if (offset) {
435 p += 4 - offset;
436 }
437 /* Swap Buffer */
438 for (y = 0; y < size; y += 4) {
439 swab32s(p: (u32 *)(p + y));
440 }
441
442 cnt = ivtv_convert_ivtv_vbi(itv, p: p + offset);
443 memcpy(buf->buf, itv->vbi.sliced_dec_data, cnt);
444 buf->bytesused = cnt;
445
446 ivtv_write_vbi(itv, sliced: itv->vbi.sliced_dec_data,
447 cnt: cnt / sizeof(itv->vbi.sliced_dec_data[0]));
448 return;
449 }
450}
451
452void 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, addr: &itv->i_flags);
457 ivtv_set_cc(itv, mode: 0, cc: &cc);
458 itv->vbi.cc_payload_idx = 0;
459}
460
461
462void 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 /* Lock */
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, enabled: 1, mode: data.data[0] & 0xf);
476 vi->wss_missing_cnt = 0;
477 } else if (vi->wss_missing_cnt == 4) {
478 ivtv_set_wss(itv, enabled: 1, mode: 0x8); /* 4x3 full format */
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: &cc);
502 } else if (vi->cc_missing_cnt == 4) {
503 ivtv_set_cc(itv, mode: 0, cc: &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, addr: &itv->i_flags)) {
512 ivtv_set_wss(itv, enabled: 1, mode: 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, addr: &itv->i_flags);
518 ivtv_set_cc(itv, mode: 3, cc: &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, mode: 3, cc: &cc);
530 break;
531 }
532 }
533
534 if (test_and_clear_bit(IVTV_F_I_UPDATE_VPS, addr: &itv->i_flags)) {
535 ivtv_set_vps(itv, enabled: 1);
536 }
537}
538

source code of linux/drivers/media/pci/ivtv/ivtv-vbi.c