Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/drivers/media/video/cx18/cx18-av-vbi.c
17900 views
1
/*
2
* cx18 ADEC VBI functions
3
*
4
* Derived from cx25840-vbi.c
5
*
6
* Copyright (C) 2007 Hans Verkuil <[email protected]>
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
27
/*
28
* 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.
30
* 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)
38
* 2 byte Internal DID: VBI-line-# 0x80
39
* NN data bytes
40
* 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
*/
58
static const u8 sliced_vbi_did[2] = { 0x91, 0x55 };
59
60
struct 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];
68
u8 payload[1]; /* data_count of payload */
69
/* u8 checksum; */
70
/* u8 fill[]; Variable number of fill bytes */
71
};
72
73
static 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
82
static 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
132
int 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, /* 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;
145
146
memset(svbi, 0, sizeof(*svbi));
147
/* we're done if raw VBI is active */
148
if ((cx18_av_read(cx, 0x404) & 0x10) == 0)
149
return 0;
150
151
if (is_pal) {
152
for (i = 7; i <= 23; i++) {
153
u8 v = cx18_av_read(cx, 0x424 + i - 7);
154
155
svbi->service_lines[0][i] = lcr2vbi[v >> 4];
156
svbi->service_lines[1][i] = lcr2vbi[v & 0xf];
157
svbi->service_set |= svbi->service_lines[0][i] |
158
svbi->service_lines[1][i];
159
}
160
} else {
161
for (i = 10; i <= 21; i++) {
162
u8 v = cx18_av_read(cx, 0x424 + i - 10);
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
}
170
return 0;
171
}
172
173
int cx18_av_s_raw_fmt(struct v4l2_subdev *sd, struct v4l2_vbi_format *fmt)
174
{
175
struct cx18 *cx = v4l2_get_subdevdata(sd);
176
struct cx18_av_state *state = &cx->av_state;
177
178
/* Setup standard */
179
cx18_av_std_setup(cx);
180
181
/* VBI Offset */
182
cx18_av_write(cx, 0x47f, state->slicer_line_delay);
183
cx18_av_write(cx, 0x404, 0x2e);
184
return 0;
185
}
186
187
int cx18_av_s_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *svbi)
188
{
189
struct cx18 *cx = v4l2_get_subdevdata(sd);
190
struct cx18_av_state *state = &cx->av_state;
191
int is_pal = !(state->std & V4L2_STD_525_60);
192
int i, x;
193
u8 lcr[24];
194
195
for (x = 0; x <= 23; x++)
196
lcr[x] = 0x00;
197
198
/* Setup standard */
199
cx18_av_std_setup(cx);
200
201
/* Sliced VBI */
202
cx18_av_write(cx, 0x404, 0x32); /* Ancillary data */
203
cx18_av_write(cx, 0x406, 0x13);
204
cx18_av_write(cx, 0x47f, state->slicer_line_delay);
205
206
/* Force impossible lines to 0 */
207
if (is_pal) {
208
for (i = 0; i <= 6; i++)
209
svbi->service_lines[0][i] =
210
svbi->service_lines[1][i] = 0;
211
} else {
212
for (i = 0; i <= 9; i++)
213
svbi->service_lines[0][i] =
214
svbi->service_lines[1][i] = 0;
215
216
for (i = 22; i <= 23; i++)
217
svbi->service_lines[0][i] =
218
svbi->service_lines[1][i] = 0;
219
}
220
221
/* Build register values for requested service lines */
222
for (i = 7; i <= 23; i++) {
223
for (x = 0; x <= 1; x++) {
224
switch (svbi->service_lines[1-x][i]) {
225
case V4L2_SLICED_TELETEXT_B:
226
lcr[i] |= 1 << (4 * x);
227
break;
228
case V4L2_SLICED_WSS_625:
229
lcr[i] |= 4 << (4 * x);
230
break;
231
case V4L2_SLICED_CAPTION_525:
232
lcr[i] |= 6 << (4 * x);
233
break;
234
case V4L2_SLICED_VPS:
235
lcr[i] |= 9 << (4 * x);
236
break;
237
}
238
}
239
}
240
241
if (is_pal) {
242
for (x = 1, i = 0x424; i <= 0x434; i++, x++)
243
cx18_av_write(cx, i, lcr[6 + x]);
244
} else {
245
for (x = 1, i = 0x424; i <= 0x430; i++, x++)
246
cx18_av_write(cx, i, lcr[9 + x]);
247
for (i = 0x431; i <= 0x434; i++)
248
cx18_av_write(cx, i, 0);
249
}
250
251
cx18_av_write(cx, 0x43c, 0x16);
252
/* Should match vblank set in cx18_av_std_setup() */
253
cx18_av_write(cx, 0x474, is_pal ? 38 : 26);
254
return 0;
255
}
256
257
int cx18_av_decode_vbi_line(struct v4l2_subdev *sd,
258
struct v4l2_decode_vbi_line *vbi)
259
{
260
struct cx18 *cx = v4l2_get_subdevdata(sd);
261
struct cx18_av_state *state = &cx->av_state;
262
struct vbi_anc_data *anc = (struct vbi_anc_data *)vbi->p;
263
u8 *p;
264
int did, sdid, l, err = 0;
265
266
/*
267
* Check for the ancillary data header for sliced VBI
268
*/
269
if (anc->preamble[0] ||
270
anc->preamble[1] != 0xff || anc->preamble[2] != 0xff ||
271
(anc->did != sliced_vbi_did[0] &&
272
anc->did != sliced_vbi_did[1])) {
273
vbi->line = vbi->type = 0;
274
return 0;
275
}
276
277
did = anc->did;
278
sdid = anc->sdid & 0xf;
279
l = anc->idid[0] & 0x3f;
280
l += state->slicer_line_offset;
281
p = anc->payload;
282
283
/* Decode the SDID set by the slicer */
284
switch (sdid) {
285
case 1:
286
sdid = V4L2_SLICED_TELETEXT_B;
287
break;
288
case 4:
289
sdid = V4L2_SLICED_WSS_625;
290
break;
291
case 6:
292
sdid = V4L2_SLICED_CAPTION_525;
293
err = !odd_parity(p[0]) || !odd_parity(p[1]);
294
break;
295
case 9:
296
sdid = V4L2_SLICED_VPS;
297
if (decode_vps(p, p) != 0)
298
err = 1;
299
break;
300
default:
301
sdid = 0;
302
err = 1;
303
break;
304
}
305
306
vbi->type = err ? 0 : sdid;
307
vbi->line = err ? 0 : l;
308
vbi->is_second_field = err ? 0 : (did == sliced_vbi_did[1]);
309
vbi->p = p;
310
return 0;
311
}
312
313