]> git.proxmox.com Git - mirror_ubuntu-hirsute-kernel.git/blob - drivers/media/pci/cx18/cx18-av-vbi.c
Merge branch 'pm-cpufreq'
[mirror_ubuntu-hirsute-kernel.git] / drivers / media / pci / cx18 / cx18-av-vbi.c
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
19
20 #include "cx18-driver.h"
21
22 /*
23 * For sliced VBI output, we set up to use VIP-1.1, 8-bit mode,
24 * NN counts 1 byte Dwords, an IDID with the VBI line # in it.
25 * Thus, according to the VIP-2 Spec, our VBI ancillary data lines
26 * (should!) look like:
27 * 4 byte EAV code: 0xff 0x00 0x00 0xRP
28 * unknown number of possible idle bytes
29 * 3 byte Anc data preamble: 0x00 0xff 0xff
30 * 1 byte data identifier: ne010iii (parity bits, 010, DID bits)
31 * 1 byte secondary data id: nessssss (parity bits, SDID bits)
32 * 1 byte data word count: necccccc (parity bits, NN Dword count)
33 * 2 byte Internal DID: VBI-line-# 0x80
34 * NN data bytes
35 * 1 byte checksum
36 * Fill bytes needed to fil out to 4*NN bytes of payload
37 *
38 * The RP codes for EAVs when in VIP-1.1 mode, not in raw mode, &
39 * in the vertical blanking interval are:
40 * 0xb0 (Task 0 VerticalBlank HorizontalBlank 0 0 0 0)
41 * 0xf0 (Task EvenField VerticalBlank HorizontalBlank 0 0 0 0)
42 *
43 * Since the V bit is only allowed to toggle in the EAV RP code, just
44 * before the first active region line and for active lines, they are:
45 * 0x90 (Task 0 0 HorizontalBlank 0 0 0 0)
46 * 0xd0 (Task EvenField 0 HorizontalBlank 0 0 0 0)
47 *
48 * The user application DID bytes we care about are:
49 * 0x91 (1 0 010 0 !ActiveLine AncDataPresent)
50 * 0x55 (0 1 010 2ndField !ActiveLine AncDataPresent)
51 *
52 */
53 static const u8 sliced_vbi_did[2] = { 0x91, 0x55 };
54
55 struct vbi_anc_data {
56 /* u8 eav[4]; */
57 /* u8 idle[]; Variable number of idle bytes */
58 u8 preamble[3];
59 u8 did;
60 u8 sdid;
61 u8 data_count;
62 u8 idid[2];
63 u8 payload[1]; /* data_count of payload */
64 /* u8 checksum; */
65 /* u8 fill[]; Variable number of fill bytes */
66 };
67
68 static int odd_parity(u8 c)
69 {
70 c ^= (c >> 4);
71 c ^= (c >> 2);
72 c ^= (c >> 1);
73
74 return c & 1;
75 }
76
77 static int decode_vps(u8 *dst, u8 *p)
78 {
79 static const u8 biphase_tbl[] = {
80 0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4,
81 0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0,
82 0xd2, 0x5a, 0x52, 0xd2, 0x96, 0x1e, 0x16, 0x96,
83 0x92, 0x1a, 0x12, 0x92, 0xd2, 0x5a, 0x52, 0xd2,
84 0xd0, 0x58, 0x50, 0xd0, 0x94, 0x1c, 0x14, 0x94,
85 0x90, 0x18, 0x10, 0x90, 0xd0, 0x58, 0x50, 0xd0,
86 0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4,
87 0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0,
88 0xe1, 0x69, 0x61, 0xe1, 0xa5, 0x2d, 0x25, 0xa5,
89 0xa1, 0x29, 0x21, 0xa1, 0xe1, 0x69, 0x61, 0xe1,
90 0xc3, 0x4b, 0x43, 0xc3, 0x87, 0x0f, 0x07, 0x87,
91 0x83, 0x0b, 0x03, 0x83, 0xc3, 0x4b, 0x43, 0xc3,
92 0xc1, 0x49, 0x41, 0xc1, 0x85, 0x0d, 0x05, 0x85,
93 0x81, 0x09, 0x01, 0x81, 0xc1, 0x49, 0x41, 0xc1,
94 0xe1, 0x69, 0x61, 0xe1, 0xa5, 0x2d, 0x25, 0xa5,
95 0xa1, 0x29, 0x21, 0xa1, 0xe1, 0x69, 0x61, 0xe1,
96 0xe0, 0x68, 0x60, 0xe0, 0xa4, 0x2c, 0x24, 0xa4,
97 0xa0, 0x28, 0x20, 0xa0, 0xe0, 0x68, 0x60, 0xe0,
98 0xc2, 0x4a, 0x42, 0xc2, 0x86, 0x0e, 0x06, 0x86,
99 0x82, 0x0a, 0x02, 0x82, 0xc2, 0x4a, 0x42, 0xc2,
100 0xc0, 0x48, 0x40, 0xc0, 0x84, 0x0c, 0x04, 0x84,
101 0x80, 0x08, 0x00, 0x80, 0xc0, 0x48, 0x40, 0xc0,
102 0xe0, 0x68, 0x60, 0xe0, 0xa4, 0x2c, 0x24, 0xa4,
103 0xa0, 0x28, 0x20, 0xa0, 0xe0, 0x68, 0x60, 0xe0,
104 0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4,
105 0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0,
106 0xd2, 0x5a, 0x52, 0xd2, 0x96, 0x1e, 0x16, 0x96,
107 0x92, 0x1a, 0x12, 0x92, 0xd2, 0x5a, 0x52, 0xd2,
108 0xd0, 0x58, 0x50, 0xd0, 0x94, 0x1c, 0x14, 0x94,
109 0x90, 0x18, 0x10, 0x90, 0xd0, 0x58, 0x50, 0xd0,
110 0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4,
111 0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0,
112 };
113
114 u8 c, err = 0;
115 int i;
116
117 for (i = 0; i < 2 * 13; i += 2) {
118 err |= biphase_tbl[p[i]] | biphase_tbl[p[i + 1]];
119 c = (biphase_tbl[p[i + 1]] & 0xf) |
120 ((biphase_tbl[p[i]] & 0xf) << 4);
121 dst[i / 2] = c;
122 }
123
124 return err & 0xf0;
125 }
126
127 int cx18_av_g_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *svbi)
128 {
129 struct cx18 *cx = v4l2_get_subdevdata(sd);
130 struct cx18_av_state *state = &cx->av_state;
131 static const u16 lcr2vbi[] = {
132 0, V4L2_SLICED_TELETEXT_B, 0, /* 1 */
133 0, V4L2_SLICED_WSS_625, 0, /* 4 */
134 V4L2_SLICED_CAPTION_525, /* 6 */
135 0, 0, V4L2_SLICED_VPS, 0, 0, /* 9 */
136 0, 0, 0, 0
137 };
138 int is_pal = !(state->std & V4L2_STD_525_60);
139 int i;
140
141 memset(svbi->service_lines, 0, sizeof(svbi->service_lines));
142 svbi->service_set = 0;
143
144 /* we're done if raw VBI is active */
145 if ((cx18_av_read(cx, 0x404) & 0x10) == 0)
146 return 0;
147
148 if (is_pal) {
149 for (i = 7; i <= 23; i++) {
150 u8 v = cx18_av_read(cx, 0x424 + i - 7);
151
152 svbi->service_lines[0][i] = lcr2vbi[v >> 4];
153 svbi->service_lines[1][i] = lcr2vbi[v & 0xf];
154 svbi->service_set |= svbi->service_lines[0][i] |
155 svbi->service_lines[1][i];
156 }
157 } else {
158 for (i = 10; i <= 21; i++) {
159 u8 v = cx18_av_read(cx, 0x424 + i - 10);
160
161 svbi->service_lines[0][i] = lcr2vbi[v >> 4];
162 svbi->service_lines[1][i] = lcr2vbi[v & 0xf];
163 svbi->service_set |= svbi->service_lines[0][i] |
164 svbi->service_lines[1][i];
165 }
166 }
167 return 0;
168 }
169
170 int cx18_av_s_raw_fmt(struct v4l2_subdev *sd, struct v4l2_vbi_format *fmt)
171 {
172 struct cx18 *cx = v4l2_get_subdevdata(sd);
173 struct cx18_av_state *state = &cx->av_state;
174
175 /* Setup standard */
176 cx18_av_std_setup(cx);
177
178 /* VBI Offset */
179 cx18_av_write(cx, 0x47f, state->slicer_line_delay);
180 cx18_av_write(cx, 0x404, 0x2e);
181 return 0;
182 }
183
184 int cx18_av_s_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *svbi)
185 {
186 struct cx18 *cx = v4l2_get_subdevdata(sd);
187 struct cx18_av_state *state = &cx->av_state;
188 int is_pal = !(state->std & V4L2_STD_525_60);
189 int i, x;
190 u8 lcr[24];
191
192 for (x = 0; x <= 23; x++)
193 lcr[x] = 0x00;
194
195 /* Setup standard */
196 cx18_av_std_setup(cx);
197
198 /* Sliced VBI */
199 cx18_av_write(cx, 0x404, 0x32); /* Ancillary data */
200 cx18_av_write(cx, 0x406, 0x13);
201 cx18_av_write(cx, 0x47f, state->slicer_line_delay);
202
203 /* Force impossible lines to 0 */
204 if (is_pal) {
205 for (i = 0; i <= 6; i++)
206 svbi->service_lines[0][i] =
207 svbi->service_lines[1][i] = 0;
208 } else {
209 for (i = 0; i <= 9; i++)
210 svbi->service_lines[0][i] =
211 svbi->service_lines[1][i] = 0;
212
213 for (i = 22; i <= 23; i++)
214 svbi->service_lines[0][i] =
215 svbi->service_lines[1][i] = 0;
216 }
217
218 /* Build register values for requested service lines */
219 for (i = 7; i <= 23; i++) {
220 for (x = 0; x <= 1; x++) {
221 switch (svbi->service_lines[1-x][i]) {
222 case V4L2_SLICED_TELETEXT_B:
223 lcr[i] |= 1 << (4 * x);
224 break;
225 case V4L2_SLICED_WSS_625:
226 lcr[i] |= 4 << (4 * x);
227 break;
228 case V4L2_SLICED_CAPTION_525:
229 lcr[i] |= 6 << (4 * x);
230 break;
231 case V4L2_SLICED_VPS:
232 lcr[i] |= 9 << (4 * x);
233 break;
234 }
235 }
236 }
237
238 if (is_pal) {
239 for (x = 1, i = 0x424; i <= 0x434; i++, x++)
240 cx18_av_write(cx, i, lcr[6 + x]);
241 } else {
242 for (x = 1, i = 0x424; i <= 0x430; i++, x++)
243 cx18_av_write(cx, i, lcr[9 + x]);
244 for (i = 0x431; i <= 0x434; i++)
245 cx18_av_write(cx, i, 0);
246 }
247
248 cx18_av_write(cx, 0x43c, 0x16);
249 /* Should match vblank set in cx18_av_std_setup() */
250 cx18_av_write(cx, 0x474, is_pal ? 38 : 26);
251 return 0;
252 }
253
254 int cx18_av_decode_vbi_line(struct v4l2_subdev *sd,
255 struct v4l2_decode_vbi_line *vbi)
256 {
257 struct cx18 *cx = v4l2_get_subdevdata(sd);
258 struct cx18_av_state *state = &cx->av_state;
259 struct vbi_anc_data *anc = (struct vbi_anc_data *)vbi->p;
260 u8 *p;
261 int did, sdid, l, err = 0;
262
263 /*
264 * Check for the ancillary data header for sliced VBI
265 */
266 if (anc->preamble[0] ||
267 anc->preamble[1] != 0xff || anc->preamble[2] != 0xff ||
268 (anc->did != sliced_vbi_did[0] &&
269 anc->did != sliced_vbi_did[1])) {
270 vbi->line = vbi->type = 0;
271 return 0;
272 }
273
274 did = anc->did;
275 sdid = anc->sdid & 0xf;
276 l = anc->idid[0] & 0x3f;
277 l += state->slicer_line_offset;
278 p = anc->payload;
279
280 /* Decode the SDID set by the slicer */
281 switch (sdid) {
282 case 1:
283 sdid = V4L2_SLICED_TELETEXT_B;
284 break;
285 case 4:
286 sdid = V4L2_SLICED_WSS_625;
287 break;
288 case 6:
289 sdid = V4L2_SLICED_CAPTION_525;
290 err = !odd_parity(p[0]) || !odd_parity(p[1]);
291 break;
292 case 9:
293 sdid = V4L2_SLICED_VPS;
294 if (decode_vps(p, p) != 0)
295 err = 1;
296 break;
297 default:
298 sdid = 0;
299 err = 1;
300 break;
301 }
302
303 vbi->type = err ? 0 : sdid;
304 vbi->line = err ? 0 : l;
305 vbi->is_second_field = err ? 0 : (did == sliced_vbi_did[1]);
306 vbi->p = p;
307 return 0;
308 }