blob: 246982841fece5ac75df67c9beb08604d56f3eba [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 Verkuil15859272010-03-14 10:49:48 -0300132int cx18_av_g_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *svbi)
Hans Verkuil1c1e45d2008-04-28 20:24:33 -0300133{
Hans Verkuil15859272010-03-14 10:49:48 -0300134 struct cx18 *cx = v4l2_get_subdevdata(sd);
Hans Verkuil1c1e45d2008-04-28 20:24:33 -0300135 struct cx18_av_state *state = &cx->av_state;
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 Verkuil30634e82012-09-05 10:38:10 -0300146 memset(svbi->service_lines, 0, sizeof(svbi->service_lines));
147 svbi->service_set = 0;
148
Hans Verkuil41c129a2009-03-30 06:43:13 -0300149 /* we're done if raw VBI is active */
150 if ((cx18_av_read(cx, 0x404) & 0x10) == 0)
151 return 0;
Hans Verkuil1c1e45d2008-04-28 20:24:33 -0300152
Hans Verkuil41c129a2009-03-30 06:43:13 -0300153 if (is_pal) {
154 for (i = 7; i <= 23; i++) {
155 u8 v = cx18_av_read(cx, 0x424 + i - 7);
Hans Verkuil1c1e45d2008-04-28 20:24:33 -0300156
Hans Verkuil41c129a2009-03-30 06:43:13 -0300157 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];
Hans Verkuil1c1e45d2008-04-28 20:24:33 -0300161 }
Hans Verkuil41c129a2009-03-30 06:43:13 -0300162 } 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 }
Hans Verkuil1c1e45d2008-04-28 20:24:33 -0300171 }
Hans Verkuil41c129a2009-03-30 06:43:13 -0300172 return 0;
173}
Hans Verkuil1c1e45d2008-04-28 20:24:33 -0300174
Hans Verkuil15859272010-03-14 10:49:48 -0300175int cx18_av_s_raw_fmt(struct v4l2_subdev *sd, struct v4l2_vbi_format *fmt)
Hans Verkuil41c129a2009-03-30 06:43:13 -0300176{
Hans Verkuil15859272010-03-14 10:49:48 -0300177 struct cx18 *cx = v4l2_get_subdevdata(sd);
Hans Verkuil41c129a2009-03-30 06:43:13 -0300178 struct cx18_av_state *state = &cx->av_state;
Hans Verkuil15859272010-03-14 10:49:48 -0300179
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;
Hans Verkuil41c129a2009-03-30 06:43:13 -0300193 int is_pal = !(state->std & V4L2_STD_525_60);
194 int i, x;
195 u8 lcr[24];
Hans Verkuil1c1e45d2008-04-28 20:24:33 -0300196
Hans Verkuil41c129a2009-03-30 06:43:13 -0300197 for (x = 0; x <= 23; x++)
198 lcr[x] = 0x00;
Hans Verkuil1c1e45d2008-04-28 20:24:33 -0300199
Hans Verkuil41c129a2009-03-30 06:43:13 -0300200 /* Setup standard */
201 cx18_av_std_setup(cx);
Hans Verkuil1c1e45d2008-04-28 20:24:33 -0300202
Hans Verkuil41c129a2009-03-30 06:43:13 -0300203 /* 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;
Hans Verkuil1c1e45d2008-04-28 20:24:33 -0300239 }
240 }
Hans Verkuil1c1e45d2008-04-28 20:24:33 -0300241 }
242
Hans Verkuil41c129a2009-03-30 06:43:13 -0300243 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 }
Hans Verkuil1c1e45d2008-04-28 20:24:33 -0300252
Hans Verkuil41c129a2009-03-30 06:43:13 -0300253 cx18_av_write(cx, 0x43c, 0x16);
Andy Walls5ab74052009-05-10 22:14:29 -0300254 /* Should match vblank set in cx18_av_std_setup() */
Andy Walls929a3ad2009-05-16 21:06:57 -0300255 cx18_av_write(cx, 0x474, is_pal ? 38 : 26);
Hans Verkuil41c129a2009-03-30 06:43:13 -0300256 return 0;
257}
Hans Verkuil1c1e45d2008-04-28 20:24:33 -0300258
Hans Verkuil41c129a2009-03-30 06:43:13 -0300259int 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;
Hans Verkuil1c1e45d2008-04-28 20:24:33 -0300267
Hans Verkuil41c129a2009-03-30 06:43:13 -0300268 /*
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)
Hans Verkuil1c1e45d2008-04-28 20:24:33 -0300300 err = 1;
Hans Verkuil41c129a2009-03-30 06:43:13 -0300301 break;
302 default:
303 sdid = 0;
304 err = 1;
Hans Verkuil1c1e45d2008-04-28 20:24:33 -0300305 break;
306 }
Hans Verkuil1c1e45d2008-04-28 20:24:33 -0300307
Hans Verkuil41c129a2009-03-30 06:43:13 -0300308 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;
Hans Verkuil1c1e45d2008-04-28 20:24:33 -0300312 return 0;
313}