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  */
58 static const u8 sliced_vbi_did[2] = { 0x91, 0x55 };
59 
60 struct 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 
73 static 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 
82 static 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 
132 int 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 
175 int 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 
189 int 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 
259 int 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