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