blob: 27699839b80dabe75eca90a53af96f4fac0ec0e4 [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 Verkuil1c1e45d2008-04-28 20:24:33 -0300132int cx18_av_vbi(struct cx18 *cx, unsigned int cmd, void *arg)
133{
134 struct cx18_av_state *state = &cx->av_state;
135 struct v4l2_format *fmt;
136 struct v4l2_sliced_vbi_format *svbi;
137
138 switch (cmd) {
139 case VIDIOC_G_FMT:
140 {
141 static u16 lcr2vbi[] = {
142 0, V4L2_SLICED_TELETEXT_B, 0, /* 1 */
143 0, V4L2_SLICED_WSS_625, 0, /* 4 */
144 V4L2_SLICED_CAPTION_525, /* 6 */
Andy Wallscb95a402009-02-28 23:06:08 -0300145 0, 0, V4L2_SLICED_VPS, 0, 0, /* 9 */
Hans Verkuil1c1e45d2008-04-28 20:24:33 -0300146 0, 0, 0, 0
147 };
148 int is_pal = !(state->std & V4L2_STD_525_60);
149 int i;
150
151 fmt = arg;
152 if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE)
153 return -EINVAL;
154 svbi = &fmt->fmt.sliced;
155 memset(svbi, 0, sizeof(*svbi));
156 /* we're done if raw VBI is active */
157 if ((cx18_av_read(cx, 0x404) & 0x10) == 0)
158 break;
159
160 if (is_pal) {
161 for (i = 7; i <= 23; i++) {
162 u8 v = cx18_av_read(cx, 0x424 + i - 7);
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 } else {
170 for (i = 10; i <= 21; i++) {
171 u8 v = cx18_av_read(cx, 0x424 + i - 10);
172
173 svbi->service_lines[0][i] = lcr2vbi[v >> 4];
174 svbi->service_lines[1][i] = lcr2vbi[v & 0xf];
175 svbi->service_set |= svbi->service_lines[0][i] |
176 svbi->service_lines[1][i];
177 }
178 }
179 break;
180 }
181
182 case VIDIOC_S_FMT:
183 {
184 int is_pal = !(state->std & V4L2_STD_525_60);
Hans Verkuil1c1e45d2008-04-28 20:24:33 -0300185 int i, x;
186 u8 lcr[24];
187
188 fmt = arg;
Andy Wallsdd073432008-12-12 16:24:04 -0300189 if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE &&
190 fmt->type != V4L2_BUF_TYPE_VBI_CAPTURE)
Hans Verkuil1c1e45d2008-04-28 20:24:33 -0300191 return -EINVAL;
192 svbi = &fmt->fmt.sliced;
Andy Wallsdd073432008-12-12 16:24:04 -0300193 if (fmt->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
Hans Verkuil1c1e45d2008-04-28 20:24:33 -0300194 /* raw VBI */
195 memset(svbi, 0, sizeof(*svbi));
196
Hans Verkuil03b52c32008-07-17 12:33:08 -0300197 /* Setup standard */
198 cx18_av_std_setup(cx);
Hans Verkuil1c1e45d2008-04-28 20:24:33 -0300199
200 /* VBI Offset */
Andy Walls812b1f92009-02-08 22:40:04 -0300201 cx18_av_write(cx, 0x47f, state->slicer_line_delay);
Hans Verkuil1c1e45d2008-04-28 20:24:33 -0300202 cx18_av_write(cx, 0x404, 0x2e);
203 break;
204 }
205
206 for (x = 0; x <= 23; x++)
207 lcr[x] = 0x00;
208
Hans Verkuil03b52c32008-07-17 12:33:08 -0300209 /* Setup standard */
210 cx18_av_std_setup(cx);
Hans Verkuil1c1e45d2008-04-28 20:24:33 -0300211
212 /* Sliced VBI */
213 cx18_av_write(cx, 0x404, 0x32); /* Ancillary data */
214 cx18_av_write(cx, 0x406, 0x13);
Andy Walls812b1f92009-02-08 22:40:04 -0300215 cx18_av_write(cx, 0x47f, state->slicer_line_delay);
Hans Verkuil1c1e45d2008-04-28 20:24:33 -0300216
Andy Wallsc1994082009-02-05 22:37:49 -0300217 /* Force impossible lines to 0 */
Hans Verkuil1c1e45d2008-04-28 20:24:33 -0300218 if (is_pal) {
219 for (i = 0; i <= 6; i++)
220 svbi->service_lines[0][i] =
221 svbi->service_lines[1][i] = 0;
222 } else {
223 for (i = 0; i <= 9; i++)
224 svbi->service_lines[0][i] =
225 svbi->service_lines[1][i] = 0;
226
227 for (i = 22; i <= 23; i++)
228 svbi->service_lines[0][i] =
229 svbi->service_lines[1][i] = 0;
230 }
231
Andy Wallsc1994082009-02-05 22:37:49 -0300232 /* Build register values for requested service lines */
Hans Verkuil1c1e45d2008-04-28 20:24:33 -0300233 for (i = 7; i <= 23; i++) {
234 for (x = 0; x <= 1; x++) {
235 switch (svbi->service_lines[1-x][i]) {
236 case V4L2_SLICED_TELETEXT_B:
237 lcr[i] |= 1 << (4 * x);
238 break;
239 case V4L2_SLICED_WSS_625:
240 lcr[i] |= 4 << (4 * x);
241 break;
242 case V4L2_SLICED_CAPTION_525:
243 lcr[i] |= 6 << (4 * x);
244 break;
245 case V4L2_SLICED_VPS:
Andy Wallscb95a402009-02-28 23:06:08 -0300246 lcr[i] |= 9 << (4 * x);
Hans Verkuil1c1e45d2008-04-28 20:24:33 -0300247 break;
248 }
249 }
250 }
251
252 if (is_pal) {
253 for (x = 1, i = 0x424; i <= 0x434; i++, x++)
254 cx18_av_write(cx, i, lcr[6 + x]);
255 } else {
256 for (x = 1, i = 0x424; i <= 0x430; i++, x++)
257 cx18_av_write(cx, i, lcr[9 + x]);
258 for (i = 0x431; i <= 0x434; i++)
259 cx18_av_write(cx, i, 0);
260 }
261
262 cx18_av_write(cx, 0x43c, 0x16);
Andy Walls812b1f92009-02-08 22:40:04 -0300263 /* FIXME - should match vblank set in cx18_av_std_setup() */
264 cx18_av_write(cx, 0x474, is_pal ? 0x2a : 26);
Hans Verkuil1c1e45d2008-04-28 20:24:33 -0300265 break;
266 }
267
268 case VIDIOC_INT_DECODE_VBI_LINE:
269 {
270 struct v4l2_decode_vbi_line *vbi = arg;
Andy Walls302df972009-01-31 00:33:02 -0300271 u8 *p;
272 struct vbi_anc_data *anc = (struct vbi_anc_data *) vbi->p;
273 int did, sdid, l, err = 0;
Hans Verkuil1c1e45d2008-04-28 20:24:33 -0300274
Andy Walls302df972009-01-31 00:33:02 -0300275 /*
276 * Check for the ancillary data header for sliced VBI
277 */
278 if (anc->preamble[0] ||
279 anc->preamble[1] != 0xff || anc->preamble[2] != 0xff ||
280 (anc->did != sliced_vbi_did[0] &&
281 anc->did != sliced_vbi_did[1])) {
Hans Verkuil1c1e45d2008-04-28 20:24:33 -0300282 vbi->line = vbi->type = 0;
283 break;
284 }
285
Andy Walls302df972009-01-31 00:33:02 -0300286 did = anc->did;
287 sdid = anc->sdid & 0xf;
288 l = anc->idid[0] & 0x3f;
Andy Walls812b1f92009-02-08 22:40:04 -0300289 l += state->slicer_line_offset;
Andy Walls302df972009-01-31 00:33:02 -0300290 p = anc->payload;
Hans Verkuil1c1e45d2008-04-28 20:24:33 -0300291
Andy Walls302df972009-01-31 00:33:02 -0300292 /* Decode the SDID set by the slicer */
293 switch (sdid) {
Hans Verkuil1c1e45d2008-04-28 20:24:33 -0300294 case 1:
Andy Walls302df972009-01-31 00:33:02 -0300295 sdid = V4L2_SLICED_TELETEXT_B;
Hans Verkuil1c1e45d2008-04-28 20:24:33 -0300296 break;
297 case 4:
Andy Walls302df972009-01-31 00:33:02 -0300298 sdid = V4L2_SLICED_WSS_625;
Hans Verkuil1c1e45d2008-04-28 20:24:33 -0300299 break;
300 case 6:
Andy Walls302df972009-01-31 00:33:02 -0300301 sdid = V4L2_SLICED_CAPTION_525;
Hans Verkuil1c1e45d2008-04-28 20:24:33 -0300302 err = !odd_parity(p[0]) || !odd_parity(p[1]);
303 break;
Andy Wallscb95a402009-02-28 23:06:08 -0300304 case 9:
Andy Walls302df972009-01-31 00:33:02 -0300305 sdid = V4L2_SLICED_VPS;
Hans Verkuil1c1e45d2008-04-28 20:24:33 -0300306 if (decode_vps(p, p) != 0)
307 err = 1;
308 break;
309 default:
Andy Walls302df972009-01-31 00:33:02 -0300310 sdid = 0;
Hans Verkuil1c1e45d2008-04-28 20:24:33 -0300311 err = 1;
312 break;
313 }
314
Andy Walls302df972009-01-31 00:33:02 -0300315 vbi->type = err ? 0 : sdid;
Hans Verkuil1c1e45d2008-04-28 20:24:33 -0300316 vbi->line = err ? 0 : l;
Andy Walls302df972009-01-31 00:33:02 -0300317 vbi->is_second_field = err ? 0 : (did == sliced_vbi_did[1]);
Hans Verkuil1c1e45d2008-04-28 20:24:33 -0300318 vbi->p = p;
319 break;
320 }
321 }
322
323 return 0;
324}