1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25#include "cx18-driver.h"
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58static const u8 sliced_vbi_did[2] = { 0x91, 0x55 };
59
60struct vbi_anc_data {
61
62
63 u8 preamble[3];
64 u8 did;
65 u8 sdid;
66 u8 data_count;
67 u8 idid[2];
68 u8 payload[1];
69
70
71};
72
73static 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
132int 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,
138 0, V4L2_SLICED_WSS_625, 0,
139 V4L2_SLICED_CAPTION_525,
140 0, 0, V4L2_SLICED_VPS, 0, 0,
141 0, 0, 0, 0
142 };
143 int is_pal = !(state->std & V4L2_STD_525_60);
144 int i;
145
146 memset(svbi->service_lines, 0, sizeof(svbi->service_lines));
147 svbi->service_set = 0;
148
149
150 if ((cx18_av_read(cx, 0x404) & 0x10) == 0)
151 return 0;
152
153 if (is_pal) {
154 for (i = 7; i <= 23; i++) {
155 u8 v = cx18_av_read(cx, 0x424 + i - 7);
156
157 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];
161 }
162 } 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 }
171 }
172 return 0;
173}
174
175int cx18_av_s_raw_fmt(struct v4l2_subdev *sd, struct v4l2_vbi_format *fmt)
176{
177 struct cx18 *cx = v4l2_get_subdevdata(sd);
178 struct cx18_av_state *state = &cx->av_state;
179
180
181 cx18_av_std_setup(cx);
182
183
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;
193 int is_pal = !(state->std & V4L2_STD_525_60);
194 int i, x;
195 u8 lcr[24];
196
197 for (x = 0; x <= 23; x++)
198 lcr[x] = 0x00;
199
200
201 cx18_av_std_setup(cx);
202
203
204 cx18_av_write(cx, 0x404, 0x32);
205 cx18_av_write(cx, 0x406, 0x13);
206 cx18_av_write(cx, 0x47f, state->slicer_line_delay);
207
208
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
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;
239 }
240 }
241 }
242
243 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 }
252
253 cx18_av_write(cx, 0x43c, 0x16);
254
255 cx18_av_write(cx, 0x474, is_pal ? 38 : 26);
256 return 0;
257}
258
259int 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;
267
268
269
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
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)
300 err = 1;
301 break;
302 default:
303 sdid = 0;
304 err = 1;
305 break;
306 }
307
308 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;
312 return 0;
313}
314