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->service_lines, 0, sizeof(svbi->service_lines));
147	svbi->service_set = 0;
148
149	/* we're done if raw VBI is active */
150	if ((cx18_av_read(cx, 0x404) & 0x10) == 0)
151		return 0;
152
153	if (is_pal) {
154		for (i = 7; i <= 23; i++) {
155			u8 v = cx18_av_read(cx, 0x424 + i - 7);
156
157			svbi->service_lines[0][i] = lcr2vbi[v >> 4];
158			svbi->service_lines[1][i] = lcr2vbi[v & 0xf];
159			svbi->service_set |= svbi->service_lines[0][i] |
160				svbi->service_lines[1][i];
161		}
162	} else {
163		for (i = 10; i <= 21; i++) {
164			u8 v = cx18_av_read(cx, 0x424 + i - 10);
165
166			svbi->service_lines[0][i] = lcr2vbi[v >> 4];
167			svbi->service_lines[1][i] = lcr2vbi[v & 0xf];
168			svbi->service_set |= svbi->service_lines[0][i] |
169				svbi->service_lines[1][i];
170		}
171	}
172	return 0;
173}
174
175int cx18_av_s_raw_fmt(struct v4l2_subdev *sd, struct v4l2_vbi_format *fmt)
176{
177	struct cx18 *cx = v4l2_get_subdevdata(sd);
178	struct cx18_av_state *state = &cx->av_state;
179
180	/* Setup standard */
181	cx18_av_std_setup(cx);
182
183	/* VBI Offset */
184	cx18_av_write(cx, 0x47f, state->slicer_line_delay);
185	cx18_av_write(cx, 0x404, 0x2e);
186	return 0;
187}
188
189int cx18_av_s_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *svbi)
190{
191	struct cx18 *cx = v4l2_get_subdevdata(sd);
192	struct cx18_av_state *state = &cx->av_state;
193	int is_pal = !(state->std & V4L2_STD_525_60);
194	int i, x;
195	u8 lcr[24];
196
197	for (x = 0; x <= 23; x++)
198		lcr[x] = 0x00;
199
200	/* Setup standard */
201	cx18_av_std_setup(cx);
202
203	/* Sliced VBI */
204	cx18_av_write(cx, 0x404, 0x32);	/* Ancillary data */
205	cx18_av_write(cx, 0x406, 0x13);
206	cx18_av_write(cx, 0x47f, state->slicer_line_delay);
207
208	/* Force impossible lines to 0 */
209	if (is_pal) {
210		for (i = 0; i <= 6; i++)
211			svbi->service_lines[0][i] =
212				svbi->service_lines[1][i] = 0;
213	} else {
214		for (i = 0; i <= 9; i++)
215			svbi->service_lines[0][i] =
216				svbi->service_lines[1][i] = 0;
217
218		for (i = 22; i <= 23; i++)
219			svbi->service_lines[0][i] =
220				svbi->service_lines[1][i] = 0;
221	}
222
223	/* Build register values for requested service lines */
224	for (i = 7; i <= 23; i++) {
225		for (x = 0; x <= 1; x++) {
226			switch (svbi->service_lines[1-x][i]) {
227			case V4L2_SLICED_TELETEXT_B:
228				lcr[i] |= 1 << (4 * x);
229				break;
230			case V4L2_SLICED_WSS_625:
231				lcr[i] |= 4 << (4 * x);
232				break;
233			case V4L2_SLICED_CAPTION_525:
234				lcr[i] |= 6 << (4 * x);
235				break;
236			case V4L2_SLICED_VPS:
237				lcr[i] |= 9 << (4 * x);
238				break;
239			}
240		}
241	}
242
243	if (is_pal) {
244		for (x = 1, i = 0x424; i <= 0x434; i++, x++)
245			cx18_av_write(cx, i, lcr[6 + x]);
246	} else {
247		for (x = 1, i = 0x424; i <= 0x430; i++, x++)
248			cx18_av_write(cx, i, lcr[9 + x]);
249		for (i = 0x431; i <= 0x434; i++)
250			cx18_av_write(cx, i, 0);
251	}
252
253	cx18_av_write(cx, 0x43c, 0x16);
254	/* Should match vblank set in cx18_av_std_setup() */
255	cx18_av_write(cx, 0x474, is_pal ? 38 : 26);
256	return 0;
257}
258
259int cx18_av_decode_vbi_line(struct v4l2_subdev *sd,
260				   struct v4l2_decode_vbi_line *vbi)
261{
262	struct cx18 *cx = v4l2_get_subdevdata(sd);
263	struct cx18_av_state *state = &cx->av_state;
264	struct vbi_anc_data *anc = (struct vbi_anc_data *)vbi->p;
265	u8 *p;
266	int did, sdid, l, err = 0;
267
268	/*
269	 * Check for the ancillary data header for sliced VBI
270	 */
271	if (anc->preamble[0] ||
272			anc->preamble[1] != 0xff || anc->preamble[2] != 0xff ||
273			(anc->did != sliced_vbi_did[0] &&
274			 anc->did != sliced_vbi_did[1])) {
275		vbi->line = vbi->type = 0;
276		return 0;
277	}
278
279	did = anc->did;
280	sdid = anc->sdid & 0xf;
281	l = anc->idid[0] & 0x3f;
282	l += state->slicer_line_offset;
283	p = anc->payload;
284
285	/* Decode the SDID set by the slicer */
286	switch (sdid) {
287	case 1:
288		sdid = V4L2_SLICED_TELETEXT_B;
289		break;
290	case 4:
291		sdid = V4L2_SLICED_WSS_625;
292		break;
293	case 6:
294		sdid = V4L2_SLICED_CAPTION_525;
295		err = !odd_parity(p[0]) || !odd_parity(p[1]);
296		break;
297	case 9:
298		sdid = V4L2_SLICED_VPS;
299		if (decode_vps(p, p) != 0)
300			err = 1;
301		break;
302	default:
303		sdid = 0;
304		err = 1;
305		break;
306	}
307
308	vbi->type = err ? 0 : sdid;
309	vbi->line = err ? 0 : l;
310	vbi->is_second_field = err ? 0 : (did == sliced_vbi_did[1]);
311	vbi->p = p;
312	return 0;
313}
314