WIP FPC-III support
[linux/fpc-iii.git] / drivers / media / pci / ivtv / ivtv-vbi.c
blob80478b026d752fed3c9aac9bb4633111fa10f889
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>
6 */
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"
15 static void ivtv_set_vps(struct ivtv *itv, int enabled)
17 struct v4l2_sliced_vbi_data data;
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);
32 static void ivtv_set_cc(struct ivtv *itv, int mode, const struct vbi_cc *cc)
34 struct v4l2_sliced_vbi_data data;
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);
51 static void ivtv_set_wss(struct ivtv *itv, int enabled, int mode)
53 struct v4l2_sliced_vbi_data data;
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 */
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);
74 static int odd_parity(u8 c)
76 c ^= (c >> 4);
77 c ^= (c >> 2);
78 c ^= (c >> 1);
80 return c & 1;
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)
87 struct vbi_info *vi = &itv->vbi;
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];
97 *found_cc = 1;
98 } else if (d->id == V4L2_SLICED_VPS && d->line == 16 && d->field == 0) {
99 struct vbi_vps vps;
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);
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;
114 if (vi->wss_payload != wss) {
115 vi->wss_payload = wss;
116 set_bit(IVTV_F_I_UPDATE_WSS, &itv->i_flags);
121 static void ivtv_write_vbi_cc_lines(struct ivtv *itv, const struct vbi_cc *cc)
123 struct vbi_info *vi = &itv->vbi;
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);
133 static void ivtv_write_vbi(struct ivtv *itv,
134 const struct v4l2_sliced_vbi_data *sliced,
135 size_t cnt)
137 struct vbi_cc cc = { .odd = { 0x80, 0x80 }, .even = { 0x80, 0x80 } };
138 int found_cc = 0;
139 size_t i;
141 for (i = 0; i < cnt; i++)
142 ivtv_write_vbi_line(itv, sliced + i, &cc, &found_cc);
144 if (found_cc)
145 ivtv_write_vbi_cc_lines(itv, &cc);
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)
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);
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;
165 ivtv_write_vbi_line(itv, &d, &cc, &found_cc);
168 if (found_cc)
169 ivtv_write_vbi_cc_lines(itv, &cc);
171 return ret;
174 static void copy_vbi_data(struct ivtv *itv, int lines, u32 pts_stamp)
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
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];
190 for (i = 0; i < lines; i++) {
191 int f, l;
193 if (itv->vbi.sliced_data[i].id == 0)
194 continue;
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++;
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);
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;
234 static int ivtv_convert_ivtv_vbi(struct ivtv *itv, u8 *p)
236 u32 linemask[2];
237 int i, l, id2;
238 int line = 0;
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 /* unknown VBI data, convert to empty VBI frame */
249 linemask[0] = linemask[1] = 0;
251 for (i = 0; i < 36; i++) {
252 int err = 0;
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;
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++;
285 p += 43;
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++;
293 return line * sizeof(itv->vbi.sliced_dec_data[0]);
296 /* Compress raw VBI format, removes leading SAV codes and surplus space after the
297 field.
298 Returns new compressed size. */
299 static u32 compress_raw_buf(struct ivtv *itv, u8 *buf, u32 size)
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;
309 for (i = 0; i < lines; i++) {
310 p = buf + i * line_size;
312 /* Look for SAV code */
313 if (p[0] != 0xff || p[1] || p[2] || (p[3] != sav1 && p[3] != sav2)) {
314 break;
316 memcpy(q, p + 4, line_size - 4);
317 q += line_size - 4;
319 return lines * (line_size - 4);
323 /* Compressed VBI format, all found sliced blocks put next to one another
324 Returns new compressed size */
325 static u32 compress_sliced_buf(struct ivtv *itv, u32 line, u8 *buf, u32 size, u8 sav)
327 u32 line_size = itv->vbi.sliced_decoder_line_size;
328 struct v4l2_decode_vbi_line vbi = {};
329 int i;
330 unsigned lines = 0;
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;
338 size -= i;
339 if (size < line_size) {
340 return line;
342 for (i = 0; i < size / line_size; i++) {
343 u8 *p = buf + i * line_size;
345 /* Look for SAV code */
346 if (p[0] != 0xff || p[1] || p[2] || p[3] != sav) {
347 continue;
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++;
360 return line;
363 void ivtv_process_vbi_data(struct ivtv *itv, struct ivtv_buffer *buf,
364 u64 pts_stamp, int streamtype)
366 u8 *p = (u8 *) buf->buf;
367 u32 size = buf->bytesused;
368 int y;
370 /* Raw VBI data */
371 if (streamtype == IVTV_ENC_STREAM_TYPE_VBI && ivtv_raw_vbi(itv)) {
372 u8 type;
374 ivtv_buf_swap(buf);
376 type = p[3];
378 size = buf->bytesused = compress_raw_buf(itv, p, size);
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++;
388 return;
391 /* Sliced VBI data with data insertion */
392 if (streamtype == IVTV_ENC_STREAM_TYPE_VBI) {
393 int lines;
395 ivtv_buf_swap(buf);
397 /* first field */
398 lines = compress_sliced_buf(itv, 0, p, size / 2,
399 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, lines, p + size / 2 - 32, size / 2 + 32,
404 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;
412 buf->bytesused = size = lines * sizeof(itv->vbi.sliced_data[0]);
413 memcpy(p, &itv->vbi.sliced_data[0], size);
415 if (itv->vbi.insert_mpeg) {
416 copy_vbi_data(itv, lines, pts_stamp);
418 itv->vbi.frame++;
419 return;
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;
434 if (offset) {
435 p += 4 - offset;
437 /* Swap Buffer */
438 for (y = 0; y < size; y += 4) {
439 swab32s((u32 *)(p + y));
442 cnt = ivtv_convert_ivtv_vbi(itv, p + offset);
443 memcpy(buf->buf, itv->vbi.sliced_dec_data, cnt);
444 buf->bytesused = cnt;
446 ivtv_write_vbi(itv, itv->vbi.sliced_dec_data,
447 cnt / sizeof(itv->vbi.sliced_dec_data[0]));
448 return;
452 void ivtv_disable_cc(struct ivtv *itv)
454 struct vbi_cc cc = { .odd = { 0x80, 0x80 }, .even = { 0x80, 0x80 } };
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;
462 void ivtv_vbi_work_handler(struct ivtv *itv)
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 } };
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;
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); /* 4x3 full format */
479 } else {
480 vi->wss_missing_cnt++;
483 else {
484 int mode = 0;
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];
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];
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++;
508 return;
511 if (test_and_clear_bit(IVTV_F_I_UPDATE_WSS, &itv->i_flags)) {
512 ivtv_set_wss(itv, 1, vi->wss_payload & 0xf);
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);
520 while (vi->cc_payload_idx) {
521 cc = vi->cc_payload[0];
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;
529 ivtv_set_cc(itv, 3, &cc);
530 break;
534 if (test_and_clear_bit(IVTV_F_I_UPDATE_VPS, &itv->i_flags)) {
535 ivtv_set_vps(itv, 1);