• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-R7000-V1.0.7.12_1.2.5/components/opensource/linux/linux-2.6.36/drivers/media/video/cx18/
1/*
2 *  cx18 ADEC VBI functions
3 *
4 *  Derived from cx25840-vbi.c
5 *
6 *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
7 *
8 *  This program is free software; you can redistribute it and/or
9 *  modify it under the terms of the GNU General Public License
10 *  as published by the Free Software Foundation; either version 2
11 *  of the License, or (at your option) any later version.
12 *
13 *  This program is distributed in the hope that it will be useful,
14 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 *  GNU General Public License for more details.
17 *
18 *  You should have received a copy of the GNU General Public License
19 *  along with this program; if not, write to the Free Software
20 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21 *  02110-1301, USA.
22 */
23
24
25#include "cx18-driver.h"
26
27/*
28 * For sliced VBI output, we set up to use VIP-1.1, 8-bit mode,
29 * NN counts 1 byte Dwords, an IDID with the VBI line # in it.
30 * Thus, according to the VIP-2 Spec, our VBI ancillary data lines
31 * (should!) look like:
32 *	4 byte EAV code:          0xff 0x00 0x00 0xRP
33 *	unknown number of possible idle bytes
34 *	3 byte Anc data preamble: 0x00 0xff 0xff
35 *	1 byte data identifier:   ne010iii (parity bits, 010, DID bits)
36 *	1 byte secondary data id: nessssss (parity bits, SDID bits)
37 *	1 byte data word count:   necccccc (parity bits, NN Dword count)
38 *	2 byte Internal DID:	  VBI-line-# 0x80
39 *	NN data bytes
40 *	1 byte checksum
41 *	Fill bytes needed to fil out to 4*NN bytes of payload
42 *
43 * The RP codes for EAVs when in VIP-1.1 mode, not in raw mode, &
44 * in the vertical blanking interval are:
45 *	0xb0 (Task         0 VerticalBlank HorizontalBlank 0 0 0 0)
46 *	0xf0 (Task EvenField VerticalBlank HorizontalBlank 0 0 0 0)
47 *
48 * Since the V bit is only allowed to toggle in the EAV RP code, just
49 * before the first active region line and for active lines, they are:
50 *	0x90 (Task         0 0 HorizontalBlank 0 0 0 0)
51 *	0xd0 (Task EvenField 0 HorizontalBlank 0 0 0 0)
52 *
53 * The user application DID bytes we care about are:
54 *	0x91 (1 0 010        0 !ActiveLine AncDataPresent)
55 *	0x55 (0 1 010 2ndField !ActiveLine AncDataPresent)
56 *
57 */
58static const u8 sliced_vbi_did[2] = { 0x91, 0x55 };
59
60struct vbi_anc_data {
61	/* u8 eav[4]; */
62	/* u8 idle[]; Variable number of idle bytes */
63	u8 preamble[3];
64	u8 did;
65	u8 sdid;
66	u8 data_count;
67	u8 idid[2];
68	u8 payload[1]; /* data_count of payload */
69	/* u8 checksum; */
70	/* u8 fill[]; Variable number of fill bytes */
71};
72
73static int odd_parity(u8 c)
74{
75	c ^= (c >> 4);
76	c ^= (c >> 2);
77	c ^= (c >> 1);
78
79	return c & 1;
80}
81
82static int decode_vps(u8 *dst, u8 *p)
83{
84	static const u8 biphase_tbl[] = {
85		0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4,
86		0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0,
87		0xd2, 0x5a, 0x52, 0xd2, 0x96, 0x1e, 0x16, 0x96,
88		0x92, 0x1a, 0x12, 0x92, 0xd2, 0x5a, 0x52, 0xd2,
89		0xd0, 0x58, 0x50, 0xd0, 0x94, 0x1c, 0x14, 0x94,
90		0x90, 0x18, 0x10, 0x90, 0xd0, 0x58, 0x50, 0xd0,
91		0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4,
92		0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0,
93		0xe1, 0x69, 0x61, 0xe1, 0xa5, 0x2d, 0x25, 0xa5,
94		0xa1, 0x29, 0x21, 0xa1, 0xe1, 0x69, 0x61, 0xe1,
95		0xc3, 0x4b, 0x43, 0xc3, 0x87, 0x0f, 0x07, 0x87,
96		0x83, 0x0b, 0x03, 0x83, 0xc3, 0x4b, 0x43, 0xc3,
97		0xc1, 0x49, 0x41, 0xc1, 0x85, 0x0d, 0x05, 0x85,
98		0x81, 0x09, 0x01, 0x81, 0xc1, 0x49, 0x41, 0xc1,
99		0xe1, 0x69, 0x61, 0xe1, 0xa5, 0x2d, 0x25, 0xa5,
100		0xa1, 0x29, 0x21, 0xa1, 0xe1, 0x69, 0x61, 0xe1,
101		0xe0, 0x68, 0x60, 0xe0, 0xa4, 0x2c, 0x24, 0xa4,
102		0xa0, 0x28, 0x20, 0xa0, 0xe0, 0x68, 0x60, 0xe0,
103		0xc2, 0x4a, 0x42, 0xc2, 0x86, 0x0e, 0x06, 0x86,
104		0x82, 0x0a, 0x02, 0x82, 0xc2, 0x4a, 0x42, 0xc2,
105		0xc0, 0x48, 0x40, 0xc0, 0x84, 0x0c, 0x04, 0x84,
106		0x80, 0x08, 0x00, 0x80, 0xc0, 0x48, 0x40, 0xc0,
107		0xe0, 0x68, 0x60, 0xe0, 0xa4, 0x2c, 0x24, 0xa4,
108		0xa0, 0x28, 0x20, 0xa0, 0xe0, 0x68, 0x60, 0xe0,
109		0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4,
110		0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0,
111		0xd2, 0x5a, 0x52, 0xd2, 0x96, 0x1e, 0x16, 0x96,
112		0x92, 0x1a, 0x12, 0x92, 0xd2, 0x5a, 0x52, 0xd2,
113		0xd0, 0x58, 0x50, 0xd0, 0x94, 0x1c, 0x14, 0x94,
114		0x90, 0x18, 0x10, 0x90, 0xd0, 0x58, 0x50, 0xd0,
115		0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4,
116		0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0,
117	};
118
119	u8 c, err = 0;
120	int i;
121
122	for (i = 0; i < 2 * 13; i += 2) {
123		err |= biphase_tbl[p[i]] | biphase_tbl[p[i + 1]];
124		c = (biphase_tbl[p[i + 1]] & 0xf) |
125		    ((biphase_tbl[p[i]] & 0xf) << 4);
126		dst[i / 2] = c;
127	}
128
129	return err & 0xf0;
130}
131
132int cx18_av_g_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *svbi)
133{
134	struct cx18 *cx = v4l2_get_subdevdata(sd);
135	struct cx18_av_state *state = &cx->av_state;
136	static const u16 lcr2vbi[] = {
137		0, V4L2_SLICED_TELETEXT_B, 0,	/* 1 */
138		0, V4L2_SLICED_WSS_625, 0,	/* 4 */
139		V4L2_SLICED_CAPTION_525,	/* 6 */
140		0, 0, V4L2_SLICED_VPS, 0, 0,	/* 9 */
141		0, 0, 0, 0
142	};
143	int is_pal = !(state->std & V4L2_STD_525_60);
144	int i;
145
146	memset(svbi, 0, sizeof(*svbi));
147	/* we're done if raw VBI is active */
148	if ((cx18_av_read(cx, 0x404) & 0x10) == 0)
149		return 0;
150
151	if (is_pal) {
152		for (i = 7; i <= 23; i++) {
153			u8 v = cx18_av_read(cx, 0x424 + i - 7);
154
155			svbi->service_lines[0][i] = lcr2vbi[v >> 4];
156			svbi->service_lines[1][i] = lcr2vbi[v & 0xf];
157			svbi->service_set |= svbi->service_lines[0][i] |
158				svbi->service_lines[1][i];
159		}
160	} else {
161		for (i = 10; i <= 21; i++) {
162			u8 v = cx18_av_read(cx, 0x424 + i - 10);
163
164			svbi->service_lines[0][i] = lcr2vbi[v >> 4];
165			svbi->service_lines[1][i] = lcr2vbi[v & 0xf];
166			svbi->service_set |= svbi->service_lines[0][i] |
167				svbi->service_lines[1][i];
168		}
169	}
170	return 0;
171}
172
173int cx18_av_s_raw_fmt(struct v4l2_subdev *sd, struct v4l2_vbi_format *fmt)
174{
175	struct cx18 *cx = v4l2_get_subdevdata(sd);
176	struct cx18_av_state *state = &cx->av_state;
177
178	/* Setup standard */
179	cx18_av_std_setup(cx);
180
181	/* VBI Offset */
182	cx18_av_write(cx, 0x47f, state->slicer_line_delay);
183	cx18_av_write(cx, 0x404, 0x2e);
184	return 0;
185}
186
187int cx18_av_s_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *svbi)
188{
189	struct cx18 *cx = v4l2_get_subdevdata(sd);
190	struct cx18_av_state *state = &cx->av_state;
191	int is_pal = !(state->std & V4L2_STD_525_60);
192	int i, x;
193	u8 lcr[24];
194
195	for (x = 0; x <= 23; x++)
196		lcr[x] = 0x00;
197
198	/* Setup standard */
199	cx18_av_std_setup(cx);
200
201	/* Sliced VBI */
202	cx18_av_write(cx, 0x404, 0x32);	/* Ancillary data */
203	cx18_av_write(cx, 0x406, 0x13);
204	cx18_av_write(cx, 0x47f, state->slicer_line_delay);
205
206	/* Force impossible lines to 0 */
207	if (is_pal) {
208		for (i = 0; i <= 6; i++)
209			svbi->service_lines[0][i] =
210				svbi->service_lines[1][i] = 0;
211	} else {
212		for (i = 0; i <= 9; i++)
213			svbi->service_lines[0][i] =
214				svbi->service_lines[1][i] = 0;
215
216		for (i = 22; i <= 23; i++)
217			svbi->service_lines[0][i] =
218				svbi->service_lines[1][i] = 0;
219	}
220
221	/* Build register values for requested service lines */
222	for (i = 7; i <= 23; i++) {
223		for (x = 0; x <= 1; x++) {
224			switch (svbi->service_lines[1-x][i]) {
225			case V4L2_SLICED_TELETEXT_B:
226				lcr[i] |= 1 << (4 * x);
227				break;
228			case V4L2_SLICED_WSS_625:
229				lcr[i] |= 4 << (4 * x);
230				break;
231			case V4L2_SLICED_CAPTION_525:
232				lcr[i] |= 6 << (4 * x);
233				break;
234			case V4L2_SLICED_VPS:
235				lcr[i] |= 9 << (4 * x);
236				break;
237			}
238		}
239	}
240
241	if (is_pal) {
242		for (x = 1, i = 0x424; i <= 0x434; i++, x++)
243			cx18_av_write(cx, i, lcr[6 + x]);
244	} else {
245		for (x = 1, i = 0x424; i <= 0x430; i++, x++)
246			cx18_av_write(cx, i, lcr[9 + x]);
247		for (i = 0x431; i <= 0x434; i++)
248			cx18_av_write(cx, i, 0);
249	}
250
251	cx18_av_write(cx, 0x43c, 0x16);
252	/* Should match vblank set in cx18_av_std_setup() */
253	cx18_av_write(cx, 0x474, is_pal ? 38 : 26);
254	return 0;
255}
256
257int cx18_av_decode_vbi_line(struct v4l2_subdev *sd,
258				   struct v4l2_decode_vbi_line *vbi)
259{
260	struct cx18 *cx = v4l2_get_subdevdata(sd);
261	struct cx18_av_state *state = &cx->av_state;
262	struct vbi_anc_data *anc = (struct vbi_anc_data *)vbi->p;
263	u8 *p;
264	int did, sdid, l, err = 0;
265
266	/*
267	 * Check for the ancillary data header for sliced VBI
268	 */
269	if (anc->preamble[0] ||
270			anc->preamble[1] != 0xff || anc->preamble[2] != 0xff ||
271			(anc->did != sliced_vbi_did[0] &&
272			 anc->did != sliced_vbi_did[1])) {
273		vbi->line = vbi->type = 0;
274		return 0;
275	}
276
277	did = anc->did;
278	sdid = anc->sdid & 0xf;
279	l = anc->idid[0] & 0x3f;
280	l += state->slicer_line_offset;
281	p = anc->payload;
282
283	/* Decode the SDID set by the slicer */
284	switch (sdid) {
285	case 1:
286		sdid = V4L2_SLICED_TELETEXT_B;
287		break;
288	case 4:
289		sdid = V4L2_SLICED_WSS_625;
290		break;
291	case 6:
292		sdid = V4L2_SLICED_CAPTION_525;
293		err = !odd_parity(p[0]) || !odd_parity(p[1]);
294		break;
295	case 9:
296		sdid = V4L2_SLICED_VPS;
297		if (decode_vps(p, p) != 0)
298			err = 1;
299		break;
300	default:
301		sdid = 0;
302		err = 1;
303		break;
304	}
305
306	vbi->type = err ? 0 : sdid;
307	vbi->line = err ? 0 : l;
308	vbi->is_second_field = err ? 0 : (did == sliced_vbi_did[1]);
309	vbi->p = p;
310	return 0;
311}
312