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 
odd_parity(u8 c)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 
decode_vps(u8 * dst,u8 * p)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 
cx18_av_g_sliced_fmt(struct v4l2_subdev * sd,struct v4l2_sliced_vbi_format * svbi)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, 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 
cx18_av_s_raw_fmt(struct v4l2_subdev * sd,struct v4l2_vbi_format * fmt)173 int 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 
cx18_av_s_sliced_fmt(struct v4l2_subdev * sd,struct v4l2_sliced_vbi_format * svbi)187 int 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 
cx18_av_decode_vbi_line(struct v4l2_subdev * sd,struct v4l2_decode_vbi_line * vbi)257 int 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