2 * cx18 ADEC VBI functions
4 * Derived from cx25840-vbi.c
6 * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
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.
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.
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
25 #include "cx18-driver.h"
27 static int odd_parity(u8 c
)
36 static int decode_vps(u8
*dst
, u8
*p
)
38 static const u8 biphase_tbl
[] = {
39 0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4,
40 0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0,
41 0xd2, 0x5a, 0x52, 0xd2, 0x96, 0x1e, 0x16, 0x96,
42 0x92, 0x1a, 0x12, 0x92, 0xd2, 0x5a, 0x52, 0xd2,
43 0xd0, 0x58, 0x50, 0xd0, 0x94, 0x1c, 0x14, 0x94,
44 0x90, 0x18, 0x10, 0x90, 0xd0, 0x58, 0x50, 0xd0,
45 0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4,
46 0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0,
47 0xe1, 0x69, 0x61, 0xe1, 0xa5, 0x2d, 0x25, 0xa5,
48 0xa1, 0x29, 0x21, 0xa1, 0xe1, 0x69, 0x61, 0xe1,
49 0xc3, 0x4b, 0x43, 0xc3, 0x87, 0x0f, 0x07, 0x87,
50 0x83, 0x0b, 0x03, 0x83, 0xc3, 0x4b, 0x43, 0xc3,
51 0xc1, 0x49, 0x41, 0xc1, 0x85, 0x0d, 0x05, 0x85,
52 0x81, 0x09, 0x01, 0x81, 0xc1, 0x49, 0x41, 0xc1,
53 0xe1, 0x69, 0x61, 0xe1, 0xa5, 0x2d, 0x25, 0xa5,
54 0xa1, 0x29, 0x21, 0xa1, 0xe1, 0x69, 0x61, 0xe1,
55 0xe0, 0x68, 0x60, 0xe0, 0xa4, 0x2c, 0x24, 0xa4,
56 0xa0, 0x28, 0x20, 0xa0, 0xe0, 0x68, 0x60, 0xe0,
57 0xc2, 0x4a, 0x42, 0xc2, 0x86, 0x0e, 0x06, 0x86,
58 0x82, 0x0a, 0x02, 0x82, 0xc2, 0x4a, 0x42, 0xc2,
59 0xc0, 0x48, 0x40, 0xc0, 0x84, 0x0c, 0x04, 0x84,
60 0x80, 0x08, 0x00, 0x80, 0xc0, 0x48, 0x40, 0xc0,
61 0xe0, 0x68, 0x60, 0xe0, 0xa4, 0x2c, 0x24, 0xa4,
62 0xa0, 0x28, 0x20, 0xa0, 0xe0, 0x68, 0x60, 0xe0,
63 0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4,
64 0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0,
65 0xd2, 0x5a, 0x52, 0xd2, 0x96, 0x1e, 0x16, 0x96,
66 0x92, 0x1a, 0x12, 0x92, 0xd2, 0x5a, 0x52, 0xd2,
67 0xd0, 0x58, 0x50, 0xd0, 0x94, 0x1c, 0x14, 0x94,
68 0x90, 0x18, 0x10, 0x90, 0xd0, 0x58, 0x50, 0xd0,
69 0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4,
70 0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0,
76 for (i
= 0; i
< 2 * 13; i
+= 2) {
77 err
|= biphase_tbl
[p
[i
]] | biphase_tbl
[p
[i
+ 1]];
78 c
= (biphase_tbl
[p
[i
+ 1]] & 0xf) |
79 ((biphase_tbl
[p
[i
]] & 0xf) << 4);
86 void cx18_av_vbi_setup(struct cx18
*cx
)
88 struct cx18_av_state
*state
= &cx
->av_state
;
89 v4l2_std_id std
= state
->std
;
90 int hblank
, hactive
, burst
, vblank
, vactive
, sc
;
91 int vblank656
, src_decimation
;
92 int luma_lpf
, uv_lpf
, comb
;
93 u32 pll_int
, pll_frac
, pll_post
;
95 /* datasheet startup, step 8d */
96 if (std
& ~V4L2_STD_NTSC
)
97 cx18_av_write(cx
, 0x49f, 0x11);
99 cx18_av_write(cx
, 0x49f, 0x14);
101 if (std
& V4L2_STD_625_50
) {
108 src_decimation
= 0x21f;
111 if (std
& V4L2_STD_SECAM
) {
115 } else if (std
== V4L2_STD_PAL_Nc
) {
131 src_decimation
= 0x21f;
132 if (std
== V4L2_STD_PAL_60
) {
139 } else if (std
== V4L2_STD_PAL_M
) {
155 /* DEBUG: Displays configured PLL frequency */
156 pll_int
= cx18_av_read(cx
, 0x108);
157 pll_frac
= cx18_av_read4(cx
, 0x10c) & 0x1ffffff;
158 pll_post
= cx18_av_read(cx
, 0x109);
159 CX18_DEBUG_INFO("PLL regs = int: %u, frac: %u, post: %u\n",
160 pll_int
, pll_frac
, pll_post
);
164 int pll
= 28636363L * ((((u64
)pll_int
) << 25) + pll_frac
);
168 CX18_DEBUG_INFO("PLL = %d.%06d MHz\n",
169 pll
/ 1000000, pll
% 1000000);
170 CX18_DEBUG_INFO("PLL/8 = %d.%06d MHz\n",
171 pll
/ 8000000, (pll
/ 8) % 1000000);
173 fin
= ((u64
)src_decimation
* pll
) >> 12;
174 CX18_DEBUG_INFO("ADC Sampling freq = %d.%06d MHz\n",
175 fin
/ 1000000, fin
% 1000000);
177 fsc
= (((u64
)sc
) * pll
) >> 24L;
178 CX18_DEBUG_INFO("Chroma sub-carrier freq = %d.%06d MHz\n",
179 fsc
/ 1000000, fsc
% 1000000);
181 CX18_DEBUG_INFO("hblank %i, hactive %i, "
182 "vblank %i , vactive %i, vblank656 %i, src_dec %i,"
183 "burst 0x%02x, luma_lpf %i, uv_lpf %i, comb 0x%02x,"
185 hblank
, hactive
, vblank
, vactive
, vblank656
,
186 src_decimation
, burst
, luma_lpf
, uv_lpf
, comb
, sc
);
189 /* Sets horizontal blanking delay and active lines */
190 cx18_av_write(cx
, 0x470, hblank
);
191 cx18_av_write(cx
, 0x471, 0xff & (((hblank
>> 8) & 0x3) |
193 cx18_av_write(cx
, 0x472, hactive
>> 4);
195 /* Sets burst gate delay */
196 cx18_av_write(cx
, 0x473, burst
);
198 /* Sets vertical blanking delay and active duration */
199 cx18_av_write(cx
, 0x474, vblank
);
200 cx18_av_write(cx
, 0x475, 0xff & (((vblank
>> 8) & 0x3) |
202 cx18_av_write(cx
, 0x476, vactive
>> 4);
203 cx18_av_write(cx
, 0x477, vblank656
);
205 /* Sets src decimation rate */
206 cx18_av_write(cx
, 0x478, 0xff & src_decimation
);
207 cx18_av_write(cx
, 0x479, 0xff & (src_decimation
>> 8));
209 /* Sets Luma and UV Low pass filters */
210 cx18_av_write(cx
, 0x47a, luma_lpf
<< 6 | ((uv_lpf
<< 4) & 0x30));
212 /* Enables comb filters */
213 cx18_av_write(cx
, 0x47b, comb
);
216 cx18_av_write(cx
, 0x47c, sc
);
217 cx18_av_write(cx
, 0x47d, 0xff & sc
>> 8);
218 cx18_av_write(cx
, 0x47e, 0xff & sc
>> 16);
220 /* Sets VBI parameters */
221 if (std
& V4L2_STD_625_50
) {
222 cx18_av_write(cx
, 0x47f, 0x01);
223 state
->vbi_line_offset
= 5;
225 cx18_av_write(cx
, 0x47f, 0x00);
226 state
->vbi_line_offset
= 8;
230 int cx18_av_vbi(struct cx18
*cx
, unsigned int cmd
, void *arg
)
232 struct cx18_av_state
*state
= &cx
->av_state
;
233 struct v4l2_format
*fmt
;
234 struct v4l2_sliced_vbi_format
*svbi
;
239 static u16 lcr2vbi
[] = {
240 0, V4L2_SLICED_TELETEXT_B
, 0, /* 1 */
241 0, V4L2_SLICED_WSS_625
, 0, /* 4 */
242 V4L2_SLICED_CAPTION_525
, /* 6 */
243 0, 0, V4L2_SLICED_VPS
, 0, 0, /* 9 */
246 int is_pal
= !(state
->std
& V4L2_STD_525_60
);
250 if (fmt
->type
!= V4L2_BUF_TYPE_SLICED_VBI_CAPTURE
)
252 svbi
= &fmt
->fmt
.sliced
;
253 memset(svbi
, 0, sizeof(*svbi
));
254 /* we're done if raw VBI is active */
255 if ((cx18_av_read(cx
, 0x404) & 0x10) == 0)
259 for (i
= 7; i
<= 23; i
++) {
260 u8 v
= cx18_av_read(cx
, 0x424 + i
- 7);
262 svbi
->service_lines
[0][i
] = lcr2vbi
[v
>> 4];
263 svbi
->service_lines
[1][i
] = lcr2vbi
[v
& 0xf];
264 svbi
->service_set
|= svbi
->service_lines
[0][i
] |
265 svbi
->service_lines
[1][i
];
268 for (i
= 10; i
<= 21; i
++) {
269 u8 v
= cx18_av_read(cx
, 0x424 + i
- 10);
271 svbi
->service_lines
[0][i
] = lcr2vbi
[v
>> 4];
272 svbi
->service_lines
[1][i
] = lcr2vbi
[v
& 0xf];
273 svbi
->service_set
|= svbi
->service_lines
[0][i
] |
274 svbi
->service_lines
[1][i
];
282 int is_pal
= !(state
->std
& V4L2_STD_525_60
);
283 int vbi_offset
= is_pal
? 1 : 0;
288 if (fmt
->type
!= V4L2_BUF_TYPE_SLICED_VBI_CAPTURE
)
290 svbi
= &fmt
->fmt
.sliced
;
291 if (svbi
->service_set
== 0) {
293 memset(svbi
, 0, sizeof(*svbi
));
296 cx18_av_vbi_setup(cx
);
299 cx18_av_write(cx
, 0x47f, vbi_offset
);
300 cx18_av_write(cx
, 0x404, 0x2e);
304 for (x
= 0; x
<= 23; x
++)
308 cx18_av_vbi_setup(cx
);
311 cx18_av_write(cx
, 0x404, 0x32); /* Ancillary data */
312 cx18_av_write(cx
, 0x406, 0x13);
313 cx18_av_write(cx
, 0x47f, vbi_offset
);
316 for (i
= 0; i
<= 6; i
++)
317 svbi
->service_lines
[0][i
] =
318 svbi
->service_lines
[1][i
] = 0;
320 for (i
= 0; i
<= 9; i
++)
321 svbi
->service_lines
[0][i
] =
322 svbi
->service_lines
[1][i
] = 0;
324 for (i
= 22; i
<= 23; i
++)
325 svbi
->service_lines
[0][i
] =
326 svbi
->service_lines
[1][i
] = 0;
329 for (i
= 7; i
<= 23; i
++) {
330 for (x
= 0; x
<= 1; x
++) {
331 switch (svbi
->service_lines
[1-x
][i
]) {
332 case V4L2_SLICED_TELETEXT_B
:
333 lcr
[i
] |= 1 << (4 * x
);
335 case V4L2_SLICED_WSS_625
:
336 lcr
[i
] |= 4 << (4 * x
);
338 case V4L2_SLICED_CAPTION_525
:
339 lcr
[i
] |= 6 << (4 * x
);
341 case V4L2_SLICED_VPS
:
342 lcr
[i
] |= 9 << (4 * x
);
349 for (x
= 1, i
= 0x424; i
<= 0x434; i
++, x
++)
350 cx18_av_write(cx
, i
, lcr
[6 + x
]);
352 for (x
= 1, i
= 0x424; i
<= 0x430; i
++, x
++)
353 cx18_av_write(cx
, i
, lcr
[9 + x
]);
354 for (i
= 0x431; i
<= 0x434; i
++)
355 cx18_av_write(cx
, i
, 0);
358 cx18_av_write(cx
, 0x43c, 0x16);
359 cx18_av_write(cx
, 0x474, is_pal
? 0x2a : 0x22);
363 case VIDIOC_INT_DECODE_VBI_LINE
:
365 struct v4l2_decode_vbi_line
*vbi
= arg
;
367 int id1
, id2
, l
, err
= 0;
369 if (p
[0] || p
[1] != 0xff || p
[2] != 0xff ||
370 (p
[3] != 0x55 && p
[3] != 0x91)) {
371 vbi
->line
= vbi
->type
= 0;
379 l
+= state
->vbi_line_offset
;
384 id2
= V4L2_SLICED_TELETEXT_B
;
387 id2
= V4L2_SLICED_WSS_625
;
390 id2
= V4L2_SLICED_CAPTION_525
;
391 err
= !odd_parity(p
[0]) || !odd_parity(p
[1]);
394 id2
= V4L2_SLICED_VPS
;
395 if (decode_vps(p
, p
) != 0)
404 vbi
->type
= err
? 0 : id2
;
405 vbi
->line
= err
? 0 : l
;
406 vbi
->is_second_field
= err
? 0 : (id1
== 0x55);