blob: 23b31670bf1dbc9143028ac2b68b78a1fb6844a1 [file] [log] [blame]
Hans Verkuil1c1e45d2008-04-28 20:24:33 -03001/*
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
Andy Walls302df972009-01-31 00:33:02 -030027/*
Andy Wallsc1994082009-02-05 22:37:49 -030028 * 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.
Andy Walls302df972009-01-31 00:33:02 -030030 * 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)
Andy Wallsc1994082009-02-05 22:37:49 -030038 * 2 byte Internal DID: VBI-line-# 0x80
39 * NN data bytes
Andy Walls302df972009-01-31 00:33:02 -030040 * 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];
Andy Wallsc1994082009-02-05 22:37:49 -030068 u8 payload[1]; /* data_count of payload */
Andy Walls302df972009-01-31 00:33:02 -030069 /* u8 checksum; */
70 /* u8 fill[]; Variable number of fill bytes */
71};
72
Hans Verkuil1c1e45d2008-04-28 20:24:33 -030073static 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
Hans Verkuil41c129a2009-03-30 06:43:13 -0300132int cx18_av_vbi_g_fmt(struct cx18 *cx, struct v4l2_format *fmt)
Hans Verkuil1c1e45d2008-04-28 20:24:33 -0300133{
134 struct cx18_av_state *state = &cx->av_state;
Hans Verkuil1c1e45d2008-04-28 20:24:33 -0300135 struct v4l2_sliced_vbi_format *svbi;
Hans Verkuil41c129a2009-03-30 06:43:13 -0300136 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;
Hans Verkuil1c1e45d2008-04-28 20:24:33 -0300145
Hans Verkuil41c129a2009-03-30 06:43:13 -0300146 if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE)
147 return -EINVAL;
148 svbi = &fmt->fmt.sliced;
149 memset(svbi, 0, sizeof(*svbi));
150 /* we're done if raw VBI is active */
151 if ((cx18_av_read(cx, 0x404) & 0x10) == 0)
152 return 0;
Hans Verkuil1c1e45d2008-04-28 20:24:33 -0300153
Hans Verkuil41c129a2009-03-30 06:43:13 -0300154 if (is_pal) {
155 for (i = 7; i <= 23; i++) {
156 u8 v = cx18_av_read(cx, 0x424 + i - 7);
Hans Verkuil1c1e45d2008-04-28 20:24:33 -0300157
Hans Verkuil41c129a2009-03-30 06:43:13 -0300158 svbi->service_lines[0][i] = lcr2vbi[v >> 4];
159 svbi->service_lines[1][i] = lcr2vbi[v & 0xf];
160 svbi->service_set |= svbi->service_lines[0][i] |
161 svbi->service_lines[1][i];
Hans Verkuil1c1e45d2008-04-28 20:24:33 -0300162 }
Hans Verkuil41c129a2009-03-30 06:43:13 -0300163 } else {
164 for (i = 10; i <= 21; i++) {
165 u8 v = cx18_av_read(cx, 0x424 + i - 10);
166
167 svbi->service_lines[0][i] = lcr2vbi[v >> 4];
168 svbi->service_lines[1][i] = lcr2vbi[v & 0xf];
169 svbi->service_set |= svbi->service_lines[0][i] |
170 svbi->service_lines[1][i];
171 }
Hans Verkuil1c1e45d2008-04-28 20:24:33 -0300172 }
Hans Verkuil41c129a2009-03-30 06:43:13 -0300173 return 0;
174}
Hans Verkuil1c1e45d2008-04-28 20:24:33 -0300175
Hans Verkuil41c129a2009-03-30 06:43:13 -0300176int cx18_av_vbi_s_fmt(struct cx18 *cx, struct v4l2_format *fmt)
177{
178 struct cx18_av_state *state = &cx->av_state;
179 struct v4l2_sliced_vbi_format *svbi;
180 int is_pal = !(state->std & V4L2_STD_525_60);
181 int i, x;
182 u8 lcr[24];
Hans Verkuil1c1e45d2008-04-28 20:24:33 -0300183
Hans Verkuil41c129a2009-03-30 06:43:13 -0300184 if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE &&
185 fmt->type != V4L2_BUF_TYPE_VBI_CAPTURE)
186 return -EINVAL;
187 svbi = &fmt->fmt.sliced;
188 if (fmt->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
189 /* raw VBI */
190 memset(svbi, 0, sizeof(*svbi));
Hans Verkuil1c1e45d2008-04-28 20:24:33 -0300191
Hans Verkuil03b52c32008-07-17 12:33:08 -0300192 /* Setup standard */
193 cx18_av_std_setup(cx);
Hans Verkuil1c1e45d2008-04-28 20:24:33 -0300194
Hans Verkuil41c129a2009-03-30 06:43:13 -0300195 /* VBI Offset */
Andy Walls812b1f92009-02-08 22:40:04 -0300196 cx18_av_write(cx, 0x47f, state->slicer_line_delay);
Hans Verkuil41c129a2009-03-30 06:43:13 -0300197 cx18_av_write(cx, 0x404, 0x2e);
198 return 0;
199 }
Hans Verkuil1c1e45d2008-04-28 20:24:33 -0300200
Hans Verkuil41c129a2009-03-30 06:43:13 -0300201 for (x = 0; x <= 23; x++)
202 lcr[x] = 0x00;
Hans Verkuil1c1e45d2008-04-28 20:24:33 -0300203
Hans Verkuil41c129a2009-03-30 06:43:13 -0300204 /* Setup standard */
205 cx18_av_std_setup(cx);
Hans Verkuil1c1e45d2008-04-28 20:24:33 -0300206
Hans Verkuil41c129a2009-03-30 06:43:13 -0300207 /* Sliced VBI */
208 cx18_av_write(cx, 0x404, 0x32); /* Ancillary data */
209 cx18_av_write(cx, 0x406, 0x13);
210 cx18_av_write(cx, 0x47f, state->slicer_line_delay);
211
212 /* Force impossible lines to 0 */
213 if (is_pal) {
214 for (i = 0; i <= 6; i++)
215 svbi->service_lines[0][i] =
216 svbi->service_lines[1][i] = 0;
217 } else {
218 for (i = 0; i <= 9; i++)
219 svbi->service_lines[0][i] =
220 svbi->service_lines[1][i] = 0;
221
222 for (i = 22; i <= 23; i++)
223 svbi->service_lines[0][i] =
224 svbi->service_lines[1][i] = 0;
225 }
226
227 /* Build register values for requested service lines */
228 for (i = 7; i <= 23; i++) {
229 for (x = 0; x <= 1; x++) {
230 switch (svbi->service_lines[1-x][i]) {
231 case V4L2_SLICED_TELETEXT_B:
232 lcr[i] |= 1 << (4 * x);
233 break;
234 case V4L2_SLICED_WSS_625:
235 lcr[i] |= 4 << (4 * x);
236 break;
237 case V4L2_SLICED_CAPTION_525:
238 lcr[i] |= 6 << (4 * x);
239 break;
240 case V4L2_SLICED_VPS:
241 lcr[i] |= 9 << (4 * x);
242 break;
Hans Verkuil1c1e45d2008-04-28 20:24:33 -0300243 }
244 }
Hans Verkuil1c1e45d2008-04-28 20:24:33 -0300245 }
246
Hans Verkuil41c129a2009-03-30 06:43:13 -0300247 if (is_pal) {
248 for (x = 1, i = 0x424; i <= 0x434; i++, x++)
249 cx18_av_write(cx, i, lcr[6 + x]);
250 } else {
251 for (x = 1, i = 0x424; i <= 0x430; i++, x++)
252 cx18_av_write(cx, i, lcr[9 + x]);
253 for (i = 0x431; i <= 0x434; i++)
254 cx18_av_write(cx, i, 0);
255 }
Hans Verkuil1c1e45d2008-04-28 20:24:33 -0300256
Hans Verkuil41c129a2009-03-30 06:43:13 -0300257 cx18_av_write(cx, 0x43c, 0x16);
258 /* FIXME - should match vblank set in cx18_av_std_setup() */
259 cx18_av_write(cx, 0x474, is_pal ? 0x2a : 26);
260 return 0;
261}
Hans Verkuil1c1e45d2008-04-28 20:24:33 -0300262
Hans Verkuil41c129a2009-03-30 06:43:13 -0300263int cx18_av_decode_vbi_line(struct v4l2_subdev *sd,
264 struct v4l2_decode_vbi_line *vbi)
265{
266 struct cx18 *cx = v4l2_get_subdevdata(sd);
267 struct cx18_av_state *state = &cx->av_state;
268 struct vbi_anc_data *anc = (struct vbi_anc_data *)vbi->p;
269 u8 *p;
270 int did, sdid, l, err = 0;
Hans Verkuil1c1e45d2008-04-28 20:24:33 -0300271
Hans Verkuil41c129a2009-03-30 06:43:13 -0300272 /*
273 * Check for the ancillary data header for sliced VBI
274 */
275 if (anc->preamble[0] ||
276 anc->preamble[1] != 0xff || anc->preamble[2] != 0xff ||
277 (anc->did != sliced_vbi_did[0] &&
278 anc->did != sliced_vbi_did[1])) {
279 vbi->line = vbi->type = 0;
280 return 0;
281 }
282
283 did = anc->did;
284 sdid = anc->sdid & 0xf;
285 l = anc->idid[0] & 0x3f;
286 l += state->slicer_line_offset;
287 p = anc->payload;
288
289 /* Decode the SDID set by the slicer */
290 switch (sdid) {
291 case 1:
292 sdid = V4L2_SLICED_TELETEXT_B;
293 break;
294 case 4:
295 sdid = V4L2_SLICED_WSS_625;
296 break;
297 case 6:
298 sdid = V4L2_SLICED_CAPTION_525;
299 err = !odd_parity(p[0]) || !odd_parity(p[1]);
300 break;
301 case 9:
302 sdid = V4L2_SLICED_VPS;
303 if (decode_vps(p, p) != 0)
Hans Verkuil1c1e45d2008-04-28 20:24:33 -0300304 err = 1;
Hans Verkuil41c129a2009-03-30 06:43:13 -0300305 break;
306 default:
307 sdid = 0;
308 err = 1;
Hans Verkuil1c1e45d2008-04-28 20:24:33 -0300309 break;
310 }
Hans Verkuil1c1e45d2008-04-28 20:24:33 -0300311
Hans Verkuil41c129a2009-03-30 06:43:13 -0300312 vbi->type = err ? 0 : sdid;
313 vbi->line = err ? 0 : l;
314 vbi->is_second_field = err ? 0 : (did == sliced_vbi_did[1]);
315 vbi->p = p;
Hans Verkuil1c1e45d2008-04-28 20:24:33 -0300316 return 0;
317}