PageRenderTime 45ms CodeModel.GetById 18ms app.highlight 24ms RepoModel.GetById 0ms app.codeStats 0ms

/drivers/media/video/ivtv/ivtv-vbi.c

https://bitbucket.org/ndreys/linux-sunxi
C | 549 lines | 431 code | 63 blank | 55 comment | 125 complexity | a24fb09ef242385784b8a0521521f9f4 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.0, AGPL-1.0
  1/*
  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"
 21#include "ivtv-i2c.h"
 22#include "ivtv-ioctl.h"
 23#include "ivtv-queue.h"
 24#include "ivtv-cards.h"
 25#include "ivtv-vbi.h"
 26
 27static void ivtv_set_vps(struct ivtv *itv, int enabled)
 28{
 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;
 36	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];
 41	ivtv_call_hw(itv, IVTV_HW_SAA7127, vbi, s_vbi_data, &data);
 42}
 43
 44static void ivtv_set_cc(struct ivtv *itv, int mode, const struct vbi_cc *cc)
 45{
 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;
 53	data.data[0] = cc->odd[0];
 54	data.data[1] = cc->odd[1];
 55	ivtv_call_hw(itv, IVTV_HW_SAA7127, vbi, s_vbi_data, &data);
 56	data.field = 1;
 57	data.line = (mode & 2) ? 21 : 0;
 58	data.data[0] = cc->even[0];
 59	data.data[1] = cc->even[1];
 60	ivtv_call_hw(itv, IVTV_HW_SAA7127, vbi, s_vbi_data, &data);
 61}
 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. */
 74	if ((itv->std_out & V4L2_STD_625_50) && !enabled) {
 75		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;
 83	ivtv_call_hw(itv, IVTV_HW_SAA7127, vbi, s_vbi_data, &data);
 84}
 85
 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
 95static void ivtv_write_vbi_line(struct ivtv *itv,
 96				const struct v4l2_sliced_vbi_data *d,
 97				struct vbi_cc *cc, int *found_cc)
 98{
 99	struct vbi_info *vi = &itv->vbi;
100
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{
149	struct vbi_cc cc = { .odd = { 0x80, 0x80 }, .even = { 0x80, 0x80 } };
150	int found_cc = 0;
151	size_t i;
152
153	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
160ssize_t
161ivtv_write_vbi_from_user(struct ivtv *itv,
162			 const struct v4l2_sliced_vbi_data __user *sliced,
163			 size_t cnt)
164{
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;
169	ssize_t ret = cnt * sizeof(struct v4l2_sliced_vbi_data);
170
171	for (i = 0; i < cnt; i++) {
172		if (copy_from_user(&d, sliced + i,
173				   sizeof(struct v4l2_sliced_vbi_data))) {
174			ret = -EFAULT;
175			break;
176		}
177		ivtv_write_vbi_line(itv, &d, &cc, &found_cc);
178	}
179
180	if (found_cc)
181		ivtv_write_vbi_cc_lines(itv, &cc);
182
183	return ret;
184}
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));
216		dst[sd + 12 + line * 43] =
217			ivtv_service2vbi(itv->vbi.sliced_data[i].id);
218		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);
231		cpu_to_le32s(&linemask[0]);
232		cpu_to_le32s(&linemask[1]);
233		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 {
260		/* unknown VBI data, convert to empty VBI frame */
261		linemask[0] = linemask[1] = 0;
262	}
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
308/* 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;
342	unsigned lines = 0;
343
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;
362		v4l2_subdev_call(itv->sd_video, vbi, decode_vbi_line, &vbi);
363		if (vbi.type && !(lines & (1 << vbi.line))) {
364			lines |= 1 << vbi.line;
365			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 */
383	if (streamtype == IVTV_ENC_STREAM_TYPE_VBI && ivtv_raw_vbi(itv)) {
384		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
458		ivtv_write_vbi(itv, itv->vbi.sliced_dec_data,
459			       cnt / sizeof(itv->vbi.sliced_dec_data[0]));
460		return;
461	}
462}
463
464void ivtv_disable_cc(struct ivtv *itv)
465{
466	struct vbi_cc cc = { .odd = { 0x80, 0x80 }, .even = { 0x80, 0x80 } };
467
468	clear_bit(IVTV_F_I_UPDATE_CC, &itv->i_flags);
469	ivtv_set_cc(itv, 0, &cc);
470	itv->vbi.cc_payload_idx = 0;
471}
472
473
474void ivtv_vbi_work_handler(struct ivtv *itv)
475{
476	struct vbi_info *vi = &itv->vbi;
477	struct v4l2_sliced_vbi_data data;
478	struct vbi_cc cc = { .odd = { 0x80, 0x80 }, .even = { 0x80, 0x80 } };
479
480	/* Lock */
481	if (itv->output_mode == OUT_PASSTHROUGH) {
482		if (itv->is_50hz) {
483			data.id = V4L2_SLICED_WSS_625;
484			data.field = 0;
485
486			if (v4l2_subdev_call(itv->sd_video, vbi, g_vbi_data, &data) == 0) {
487				ivtv_set_wss(itv, 1, data.data[0] & 0xf);
488				vi->wss_missing_cnt = 0;
489			} else if (vi->wss_missing_cnt == 4) {
490				ivtv_set_wss(itv, 1, 0x8);  /* 4x3 full format */
491			} else {
492				vi->wss_missing_cnt++;
493			}
494		}
495		else {
496			int mode = 0;
497
498			data.id = V4L2_SLICED_CAPTION_525;
499			data.field = 0;
500			if (v4l2_subdev_call(itv->sd_video, vbi, g_vbi_data, &data) == 0) {
501				mode |= 1;
502				cc.odd[0] = data.data[0];
503				cc.odd[1] = data.data[1];
504			}
505			data.field = 1;
506			if (v4l2_subdev_call(itv->sd_video, vbi, g_vbi_data, &data) == 0) {
507				mode |= 2;
508				cc.even[0] = data.data[0];
509				cc.even[1] = data.data[1];
510			}
511			if (mode) {
512				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);
516			} else {
517				vi->cc_missing_cnt++;
518			}
519		}
520		return;
521	}
522
523	if (test_and_clear_bit(IVTV_F_I_UPDATE_WSS, &itv->i_flags)) {
524		ivtv_set_wss(itv, 1, vi->wss_payload & 0xf);
525	}
526
527	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);
531		}
532		while (vi->cc_payload_idx) {
533			cc = vi->cc_payload[0];
534
535			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)
539				continue;
540
541			ivtv_set_cc(itv, 3, &cc);
542			break;
543		}
544	}
545
546	if (test_and_clear_bit(IVTV_F_I_UPDATE_VPS, &itv->i_flags)) {
547		ivtv_set_vps(itv, 1);
548	}
549}