diff options
author | Andy Walls <awalls@radix.net> | 2009-01-30 22:33:02 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2009-03-30 11:42:38 -0400 |
commit | 302df9702192a68578916ef922c33370cbba350d (patch) | |
tree | eab3173a4b82ec26c89b82c50e9bfb0fe2477953 /drivers | |
parent | 4325dff220918c2ced82d16c3475d9a5afb1cab3 (diff) |
V4L/DVB (10439): cx18: Clean-up and enable sliced VBI handling
Removed legacy ivtv state variables, added comments, and cleaned
up sliced VBI related code. Enabled sliced VBI.
Signed-off-by: Andy Walls <awalls@radix.net>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/media/video/cx18/cx18-av-core.c | 11 | ||||
-rw-r--r-- | drivers/media/video/cx18/cx18-av-vbi.c | 92 | ||||
-rw-r--r-- | drivers/media/video/cx18/cx18-cards.c | 8 | ||||
-rw-r--r-- | drivers/media/video/cx18/cx18-cards.h | 3 | ||||
-rw-r--r-- | drivers/media/video/cx18/cx18-controls.c | 4 | ||||
-rw-r--r-- | drivers/media/video/cx18/cx18-driver.c | 49 | ||||
-rw-r--r-- | drivers/media/video/cx18/cx18-driver.h | 142 | ||||
-rw-r--r-- | drivers/media/video/cx18/cx18-fileops.c | 54 | ||||
-rw-r--r-- | drivers/media/video/cx18/cx18-ioctl.c | 77 | ||||
-rw-r--r-- | drivers/media/video/cx18/cx18-streams.c | 45 | ||||
-rw-r--r-- | drivers/media/video/cx18/cx18-vbi.c | 58 |
11 files changed, 383 insertions, 160 deletions
diff --git a/drivers/media/video/cx18/cx18-av-core.c b/drivers/media/video/cx18/cx18-av-core.c index 091f0cac0633..1d197649446e 100644 --- a/drivers/media/video/cx18/cx18-av-core.c +++ b/drivers/media/video/cx18/cx18-av-core.c | |||
@@ -169,9 +169,14 @@ static void cx18_av_initialize(struct cx18 *cx) | |||
169 | /* Set VGA_TRACK_RANGE to 0x20 */ | 169 | /* Set VGA_TRACK_RANGE to 0x20 */ |
170 | cx18_av_and_or4(cx, CXADEC_DFE_CTRL2, 0xFFFF00FF, 0x00002000); | 170 | cx18_av_and_or4(cx, CXADEC_DFE_CTRL2, 0xFFFF00FF, 0x00002000); |
171 | 171 | ||
172 | /* Enable VBI capture */ | 172 | /* |
173 | cx18_av_write4(cx, CXADEC_OUT_CTRL1, 0x4010253F); | 173 | * Initial VBI setup |
174 | /* cx18_av_write4(cx, CXADEC_OUT_CTRL1, 0x4010253E); */ | 174 | * VIP-1.1, 10 bit mode, enable Raw, disable sliced, |
175 | * don't clamp raw samples when codes are in use, 4 byte user D-words, | ||
176 | * programmed IDID, RP code V bit transition on VBLANK, data during | ||
177 | * blanking intervals | ||
178 | */ | ||
179 | cx18_av_write4(cx, CXADEC_OUT_CTRL1, 0x4010252e); | ||
175 | 180 | ||
176 | /* Set the video input. | 181 | /* Set the video input. |
177 | The setting in MODE_CTRL gets lost when we do the above setup */ | 182 | The setting in MODE_CTRL gets lost when we do the above setup */ |
diff --git a/drivers/media/video/cx18/cx18-av-vbi.c b/drivers/media/video/cx18/cx18-av-vbi.c index 1527ea4f6b06..72325d774a60 100644 --- a/drivers/media/video/cx18/cx18-av-vbi.c +++ b/drivers/media/video/cx18/cx18-av-vbi.c | |||
@@ -24,6 +24,52 @@ | |||
24 | 24 | ||
25 | #include "cx18-driver.h" | 25 | #include "cx18-driver.h" |
26 | 26 | ||
27 | /* | ||
28 | * For sliced VBI output, we set up to use VIP-1.1, 10-bit mode, | ||
29 | * NN counts 4 bytes Dwords, an IDID of 0x00 0x80 or one with the VBI line #. | ||
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: 0x00 0x80 (programmed value) | ||
39 | * 4*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]; /* 4*data_count of payload */ | ||
69 | /* u8 checksum; */ | ||
70 | /* u8 fill[]; Variable number of fill bytes */ | ||
71 | }; | ||
72 | |||
27 | static int odd_parity(u8 c) | 73 | static int odd_parity(u8 c) |
28 | { | 74 | { |
29 | c ^= (c >> 4); | 75 | c ^= (c >> 4); |
@@ -96,7 +142,7 @@ int cx18_av_vbi(struct cx18 *cx, unsigned int cmd, void *arg) | |||
96 | 0, V4L2_SLICED_TELETEXT_B, 0, /* 1 */ | 142 | 0, V4L2_SLICED_TELETEXT_B, 0, /* 1 */ |
97 | 0, V4L2_SLICED_WSS_625, 0, /* 4 */ | 143 | 0, V4L2_SLICED_WSS_625, 0, /* 4 */ |
98 | V4L2_SLICED_CAPTION_525, /* 6 */ | 144 | V4L2_SLICED_CAPTION_525, /* 6 */ |
99 | 0, 0, V4L2_SLICED_VPS, 0, 0, /* 9 */ | 145 | V4L2_SLICED_VPS, 0, 0, 0, 0, /* 7 - unlike cx25840 */ |
100 | 0, 0, 0, 0 | 146 | 0, 0, 0, 0 |
101 | }; | 147 | }; |
102 | int is_pal = !(state->std & V4L2_STD_525_60); | 148 | int is_pal = !(state->std & V4L2_STD_525_60); |
@@ -220,47 +266,53 @@ int cx18_av_vbi(struct cx18 *cx, unsigned int cmd, void *arg) | |||
220 | case VIDIOC_INT_DECODE_VBI_LINE: | 266 | case VIDIOC_INT_DECODE_VBI_LINE: |
221 | { | 267 | { |
222 | struct v4l2_decode_vbi_line *vbi = arg; | 268 | struct v4l2_decode_vbi_line *vbi = arg; |
223 | u8 *p = vbi->p; | 269 | u8 *p; |
224 | int id1, id2, l, err = 0; | 270 | struct vbi_anc_data *anc = (struct vbi_anc_data *) vbi->p; |
225 | 271 | int did, sdid, l, err = 0; | |
226 | if (p[0] || p[1] != 0xff || p[2] != 0xff || | 272 | |
227 | (p[3] != 0x55 && p[3] != 0x91)) { | 273 | /* |
274 | * Check for the ancillary data header for sliced VBI | ||
275 | */ | ||
276 | if (anc->preamble[0] || | ||
277 | anc->preamble[1] != 0xff || anc->preamble[2] != 0xff || | ||
278 | (anc->did != sliced_vbi_did[0] && | ||
279 | anc->did != sliced_vbi_did[1])) { | ||
228 | vbi->line = vbi->type = 0; | 280 | vbi->line = vbi->type = 0; |
229 | break; | 281 | break; |
230 | } | 282 | } |
231 | 283 | ||
232 | p += 4; | 284 | did = anc->did; |
233 | id1 = p[-1]; | 285 | sdid = anc->sdid & 0xf; |
234 | id2 = p[0] & 0xf; | 286 | l = anc->idid[0] & 0x3f; |
235 | l = p[2] & 0x3f; | ||
236 | l += state->vbi_line_offset; | 287 | l += state->vbi_line_offset; |
237 | p += 4; | 288 | p = anc->payload; |
238 | 289 | ||
239 | switch (id2) { | 290 | /* Decode the SDID set by the slicer */ |
291 | switch (sdid) { | ||
240 | case 1: | 292 | case 1: |
241 | id2 = V4L2_SLICED_TELETEXT_B; | 293 | sdid = V4L2_SLICED_TELETEXT_B; |
242 | break; | 294 | break; |
243 | case 4: | 295 | case 4: |
244 | id2 = V4L2_SLICED_WSS_625; | 296 | sdid = V4L2_SLICED_WSS_625; |
245 | break; | 297 | break; |
246 | case 6: | 298 | case 6: |
247 | id2 = V4L2_SLICED_CAPTION_525; | 299 | sdid = V4L2_SLICED_CAPTION_525; |
248 | err = !odd_parity(p[0]) || !odd_parity(p[1]); | 300 | err = !odd_parity(p[0]) || !odd_parity(p[1]); |
249 | break; | 301 | break; |
250 | case 9: | 302 | case 7: /* Differs from cx25840 */ |
251 | id2 = V4L2_SLICED_VPS; | 303 | sdid = V4L2_SLICED_VPS; |
252 | if (decode_vps(p, p) != 0) | 304 | if (decode_vps(p, p) != 0) |
253 | err = 1; | 305 | err = 1; |
254 | break; | 306 | break; |
255 | default: | 307 | default: |
256 | id2 = 0; | 308 | sdid = 0; |
257 | err = 1; | 309 | err = 1; |
258 | break; | 310 | break; |
259 | } | 311 | } |
260 | 312 | ||
261 | vbi->type = err ? 0 : id2; | 313 | vbi->type = err ? 0 : sdid; |
262 | vbi->line = err ? 0 : l; | 314 | vbi->line = err ? 0 : l; |
263 | vbi->is_second_field = err ? 0 : (id1 == 0x55); | 315 | vbi->is_second_field = err ? 0 : (did == sliced_vbi_did[1]); |
264 | vbi->p = p; | 316 | vbi->p = p; |
265 | break; | 317 | break; |
266 | } | 318 | } |
diff --git a/drivers/media/video/cx18/cx18-cards.c b/drivers/media/video/cx18/cx18-cards.c index a0d4d2e49d1b..6e2105ac2bc4 100644 --- a/drivers/media/video/cx18/cx18-cards.c +++ b/drivers/media/video/cx18/cx18-cards.c | |||
@@ -51,7 +51,7 @@ static struct cx18_card_tuner_i2c cx18_i2c_std = { | |||
51 | static const struct cx18_card cx18_card_hvr1600_esmt = { | 51 | static const struct cx18_card cx18_card_hvr1600_esmt = { |
52 | .type = CX18_CARD_HVR_1600_ESMT, | 52 | .type = CX18_CARD_HVR_1600_ESMT, |
53 | .name = "Hauppauge HVR-1600", | 53 | .name = "Hauppauge HVR-1600", |
54 | .comment = "Raw VBI supported; Sliced VBI is not yet supported\n", | 54 | .comment = "Simultaneous Digital and Analog TV capture supported\n", |
55 | .v4l2_capabilities = CX18_CAP_ENCODER, | 55 | .v4l2_capabilities = CX18_CAP_ENCODER, |
56 | .hw_audio_ctrl = CX18_HW_CX23418, | 56 | .hw_audio_ctrl = CX18_HW_CX23418, |
57 | .hw_muxer = CX18_HW_CS5345, | 57 | .hw_muxer = CX18_HW_CS5345, |
@@ -97,7 +97,7 @@ static const struct cx18_card cx18_card_hvr1600_esmt = { | |||
97 | static const struct cx18_card cx18_card_hvr1600_samsung = { | 97 | static const struct cx18_card cx18_card_hvr1600_samsung = { |
98 | .type = CX18_CARD_HVR_1600_SAMSUNG, | 98 | .type = CX18_CARD_HVR_1600_SAMSUNG, |
99 | .name = "Hauppauge HVR-1600 (Preproduction)", | 99 | .name = "Hauppauge HVR-1600 (Preproduction)", |
100 | .comment = "Raw VBI supported; Sliced VBI is not yet supported\n", | 100 | .comment = "Simultaneous Digital and Analog TV capture supported\n", |
101 | .v4l2_capabilities = CX18_CAP_ENCODER, | 101 | .v4l2_capabilities = CX18_CAP_ENCODER, |
102 | .hw_audio_ctrl = CX18_HW_CX23418, | 102 | .hw_audio_ctrl = CX18_HW_CX23418, |
103 | .hw_muxer = CX18_HW_CS5345, | 103 | .hw_muxer = CX18_HW_CS5345, |
@@ -152,7 +152,7 @@ static const struct cx18_card_pci_info cx18_pci_h900[] = { | |||
152 | static const struct cx18_card cx18_card_h900 = { | 152 | static const struct cx18_card cx18_card_h900 = { |
153 | .type = CX18_CARD_COMPRO_H900, | 153 | .type = CX18_CARD_COMPRO_H900, |
154 | .name = "Compro VideoMate H900", | 154 | .name = "Compro VideoMate H900", |
155 | .comment = "Raw VBI supported; Sliced VBI is not yet supported\n", | 155 | .comment = "Analog TV capture supported\n", |
156 | .v4l2_capabilities = CX18_CAP_ENCODER, | 156 | .v4l2_capabilities = CX18_CAP_ENCODER, |
157 | .hw_audio_ctrl = CX18_HW_CX23418, | 157 | .hw_audio_ctrl = CX18_HW_CX23418, |
158 | .hw_all = CX18_HW_TUNER, | 158 | .hw_all = CX18_HW_TUNER, |
@@ -249,7 +249,7 @@ static const struct cx18_card_pci_info cx18_pci_cnxt_raptor_pal[] = { | |||
249 | static const struct cx18_card cx18_card_cnxt_raptor_pal = { | 249 | static const struct cx18_card cx18_card_cnxt_raptor_pal = { |
250 | .type = CX18_CARD_CNXT_RAPTOR_PAL, | 250 | .type = CX18_CARD_CNXT_RAPTOR_PAL, |
251 | .name = "Conexant Raptor PAL/SECAM", | 251 | .name = "Conexant Raptor PAL/SECAM", |
252 | .comment = "Raw VBI supported; Sliced VBI is not yet supported\n", | 252 | .comment = "Analog TV capture supported\n", |
253 | .v4l2_capabilities = CX18_CAP_ENCODER, | 253 | .v4l2_capabilities = CX18_CAP_ENCODER, |
254 | .hw_audio_ctrl = CX18_HW_CX23418, | 254 | .hw_audio_ctrl = CX18_HW_CX23418, |
255 | .hw_muxer = CX18_HW_GPIO, | 255 | .hw_muxer = CX18_HW_GPIO, |
diff --git a/drivers/media/video/cx18/cx18-cards.h b/drivers/media/video/cx18/cx18-cards.h index 6fa7bcb42dde..f8ee29f102d4 100644 --- a/drivers/media/video/cx18/cx18-cards.h +++ b/drivers/media/video/cx18/cx18-cards.h | |||
@@ -49,8 +49,7 @@ | |||
49 | /* V4L2 capability aliases */ | 49 | /* V4L2 capability aliases */ |
50 | #define CX18_CAP_ENCODER (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_TUNER | \ | 50 | #define CX18_CAP_ENCODER (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_TUNER | \ |
51 | V4L2_CAP_AUDIO | V4L2_CAP_READWRITE | \ | 51 | V4L2_CAP_AUDIO | V4L2_CAP_READWRITE | \ |
52 | V4L2_CAP_VBI_CAPTURE) | 52 | V4L2_CAP_VBI_CAPTURE | V4L2_CAP_SLICED_VBI_CAPTURE) |
53 | /* | V4L2_CAP_SLICED_VBI_CAPTURE) not yet */ | ||
54 | 53 | ||
55 | struct cx18_card_video_input { | 54 | struct cx18_card_video_input { |
56 | u8 video_type; /* video input type */ | 55 | u8 video_type; /* video input type */ |
diff --git a/drivers/media/video/cx18/cx18-controls.c b/drivers/media/video/cx18/cx18-controls.c index 17edf305d649..6af4d5c190e1 100644 --- a/drivers/media/video/cx18/cx18-controls.c +++ b/drivers/media/video/cx18/cx18-controls.c | |||
@@ -178,8 +178,8 @@ static int cx18_setup_vbi_fmt(struct cx18 *cx, enum v4l2_mpeg_stream_vbi_fmt fmt | |||
178 | int i; | 178 | int i; |
179 | 179 | ||
180 | for (i = 0; i < CX18_VBI_FRAMES; i++) { | 180 | for (i = 0; i < CX18_VBI_FRAMES; i++) { |
181 | /* Yuck, hardcoded. Needs to be a define */ | 181 | cx->vbi.sliced_mpeg_data[i] = |
182 | cx->vbi.sliced_mpeg_data[i] = kmalloc(2049, GFP_KERNEL); | 182 | kmalloc(CX18_SLICED_MPEG_DATA_BUFSZ, GFP_KERNEL); |
183 | if (cx->vbi.sliced_mpeg_data[i] == NULL) { | 183 | if (cx->vbi.sliced_mpeg_data[i] == NULL) { |
184 | while (--i >= 0) { | 184 | while (--i >= 0) { |
185 | kfree(cx->vbi.sliced_mpeg_data[i]); | 185 | kfree(cx->vbi.sliced_mpeg_data[i]); |
diff --git a/drivers/media/video/cx18/cx18-driver.c b/drivers/media/video/cx18/cx18-driver.c index 062f1910e8dd..842ce636e45c 100644 --- a/drivers/media/video/cx18/cx18-driver.c +++ b/drivers/media/video/cx18/cx18-driver.c | |||
@@ -586,7 +586,8 @@ static int __devinit cx18_init_struct1(struct cx18 *cx) | |||
586 | (cx->params.video_temporal_filter_mode << 1) | | 586 | (cx->params.video_temporal_filter_mode << 1) | |
587 | (cx->params.video_median_filter_type << 2); | 587 | (cx->params.video_median_filter_type << 2); |
588 | cx->params.port = CX2341X_PORT_MEMORY; | 588 | cx->params.port = CX2341X_PORT_MEMORY; |
589 | cx->params.capabilities = CX2341X_CAP_HAS_TS | CX2341X_CAP_HAS_AC3; | 589 | cx->params.capabilities = |
590 | CX2341X_CAP_HAS_TS | CX2341X_CAP_HAS_AC3 | CX2341X_CAP_HAS_SLICED_VBI; | ||
590 | init_waitqueue_head(&cx->cap_w); | 591 | init_waitqueue_head(&cx->cap_w); |
591 | init_waitqueue_head(&cx->mb_apu_waitq); | 592 | init_waitqueue_head(&cx->mb_apu_waitq); |
592 | init_waitqueue_head(&cx->mb_cpu_waitq); | 593 | init_waitqueue_head(&cx->mb_cpu_waitq); |
@@ -596,49 +597,6 @@ static int __devinit cx18_init_struct1(struct cx18 *cx) | |||
596 | cx->vbi.in.type = V4L2_BUF_TYPE_VBI_CAPTURE; | 597 | cx->vbi.in.type = V4L2_BUF_TYPE_VBI_CAPTURE; |
597 | cx->vbi.sliced_in = &cx->vbi.in.fmt.sliced; | 598 | cx->vbi.sliced_in = &cx->vbi.in.fmt.sliced; |
598 | 599 | ||
599 | /* | ||
600 | * The VBI line sizes depend on the pixel clock and the horiz rate | ||
601 | * | ||
602 | * (1/Fh)*(2*Fp) = Samples/line | ||
603 | * = 4 bytes EAV + Anc data in hblank + 4 bytes SAV + active samples | ||
604 | * | ||
605 | * Sliced VBI is sent as ancillary data during horizontal blanking | ||
606 | * Raw VBI is sent as active video samples during vertcal blanking | ||
607 | * | ||
608 | * We use a BT.656 pxiel clock of 13.5 MHz and a BT.656 active line | ||
609 | * length of 720 pixels @ 4:2:2 sampling. Thus... | ||
610 | * | ||
611 | * For systems that use a 15.734 kHz horizontal rate, such as | ||
612 | * NTSC-M, PAL-M, PAL-60, and other 60 Hz/525 line systems, we have: | ||
613 | * | ||
614 | * (1/15.734 kHz) * 2 * 13.5 MHz = 1716 samples/line = | ||
615 | * 4 bytes SAV + 268 bytes anc data + 4 bytes SAV + 1440 active samples | ||
616 | * | ||
617 | * For systems that use a 15.625 kHz horizontal rate, such as | ||
618 | * PAL-B/G/H, PAL-I, SECAM-L and other 50 Hz/625 line systems, we have: | ||
619 | * | ||
620 | * (1/15.625 kHz) * 2 * 13.5 MHz = 1728 samples/line = | ||
621 | * 4 bytes SAV + 280 bytes anc data + 4 bytes SAV + 1440 active samples | ||
622 | * | ||
623 | */ | ||
624 | |||
625 | /* FIXME: init these based on tuner std & modify when std changes */ | ||
626 | /* CX18-AV-Core number of VBI samples output per horizontal line */ | ||
627 | cx->vbi.raw_decoder_line_size = 1444; /* 4 byte SAV + 2 * 720 */ | ||
628 | cx->vbi.sliced_decoder_line_size = 272; /* 60 Hz: 268+4, 50 Hz: 280+4 */ | ||
629 | |||
630 | /* CX18-AV-Core VBI samples/line possibly rounded up */ | ||
631 | cx->vbi.raw_size = 1444; /* Real max size is 1444 */ | ||
632 | cx->vbi.sliced_size = 284; /* Real max size is 284 */ | ||
633 | |||
634 | /* | ||
635 | * CX18-AV-Core SAV/EAV RP codes in VIP 1.x mode | ||
636 | * Task Field VerticalBlank HorizontalBlank 0 0 0 0 | ||
637 | */ | ||
638 | cx->vbi.raw_decoder_sav_odd_field = 0x20; /* V */ | ||
639 | cx->vbi.raw_decoder_sav_even_field = 0x60; /* FV */ | ||
640 | cx->vbi.sliced_decoder_sav_odd_field = 0xB0; /* T VH - actually EAV */ | ||
641 | cx->vbi.sliced_decoder_sav_even_field = 0xF0; /* TFVH - actually EAV */ | ||
642 | return 0; | 600 | return 0; |
643 | } | 601 | } |
644 | 602 | ||
@@ -671,7 +629,6 @@ static void __devinit cx18_init_struct2(struct cx18 *cx) | |||
671 | cx->av_state.aud_input = CX18_AV_AUDIO8; | 629 | cx->av_state.aud_input = CX18_AV_AUDIO8; |
672 | cx->av_state.audclk_freq = 48000; | 630 | cx->av_state.audclk_freq = 48000; |
673 | cx->av_state.audmode = V4L2_TUNER_MODE_LANG1; | 631 | cx->av_state.audmode = V4L2_TUNER_MODE_LANG1; |
674 | /* FIXME - 8 is NTSC value, investigate */ | ||
675 | cx->av_state.vbi_line_offset = 8; | 632 | cx->av_state.vbi_line_offset = 8; |
676 | } | 633 | } |
677 | 634 | ||
@@ -936,7 +893,7 @@ static int __devinit cx18_probe(struct pci_dev *pci_dev, | |||
936 | * suboptimal, as the CVBS and SVideo inputs could use a different std | 893 | * suboptimal, as the CVBS and SVideo inputs could use a different std |
937 | * and the buffer could end up being too small in that case. | 894 | * and the buffer could end up being too small in that case. |
938 | */ | 895 | */ |
939 | vbi_buf_size = cx->vbi.raw_size * (cx->is_60hz ? 24 : 36) / 2; | 896 | vbi_buf_size = vbi_active_samples * (cx->is_60hz ? 24 : 36) / 2; |
940 | cx->stream_buf_size[CX18_ENC_STREAM_TYPE_VBI] = vbi_buf_size; | 897 | cx->stream_buf_size[CX18_ENC_STREAM_TYPE_VBI] = vbi_buf_size; |
941 | 898 | ||
942 | if (cx->stream_buffers[CX18_ENC_STREAM_TYPE_VBI] < 0) | 899 | if (cx->stream_buffers[CX18_ENC_STREAM_TYPE_VBI] < 0) |
diff --git a/drivers/media/video/cx18/cx18-driver.h b/drivers/media/video/cx18/cx18-driver.h index d95c6ace2b96..a41d9c4178f0 100644 --- a/drivers/media/video/cx18/cx18-driver.h +++ b/drivers/media/video/cx18/cx18-driver.h | |||
@@ -319,59 +319,121 @@ struct cx18_open_id { | |||
319 | /* forward declaration of struct defined in cx18-cards.h */ | 319 | /* forward declaration of struct defined in cx18-cards.h */ |
320 | struct cx18_card; | 320 | struct cx18_card; |
321 | 321 | ||
322 | /* | ||
323 | * A note about "sliced" VBI data as implemented in this driver: | ||
324 | * | ||
325 | * Currently we collect the sliced VBI in the form of Ancillary Data | ||
326 | * packets, inserted by the AV core decoder/digitizer/slicer in the | ||
327 | * horizontal blanking region of the VBI lines, in "raw" mode as far as | ||
328 | * the Encoder is concerned. We don't ever tell the Encoder itself | ||
329 | * to provide sliced VBI. (AV Core: sliced mode - Encoder: raw mode) | ||
330 | * | ||
331 | * We then process the ancillary data ourselves to send the sliced data | ||
332 | * to the user application directly or build up MPEG-2 private stream 1 | ||
333 | * packets to splice into (only!) MPEG-2 PS streams for the user app. | ||
334 | * | ||
335 | * (That's how ivtv essentially does it.) | ||
336 | * | ||
337 | * The Encoder should be able to extract certain sliced VBI data for | ||
338 | * us and provide it in a separate stream or splice it into any type of | ||
339 | * MPEG PS or TS stream, but this isn't implemented yet. | ||
340 | */ | ||
341 | |||
342 | /* | ||
343 | * Number of "raw" VBI samples per horizontal line we tell the Encoder to | ||
344 | * grab from the decoder/digitizer/slicer output for raw or sliced VBI. | ||
345 | * It depends on the pixel clock and the horiz rate: | ||
346 | * | ||
347 | * (1/Fh)*(2*Fp) = Samples/line | ||
348 | * = 4 bytes EAV + Anc data in hblank + 4 bytes SAV + active samples | ||
349 | * | ||
350 | * Sliced VBI data is sent as ancillary data during horizontal blanking | ||
351 | * Raw VBI is sent as active video samples during vertcal blanking | ||
352 | * | ||
353 | * We use a BT.656 pxiel clock of 13.5 MHz and a BT.656 active line | ||
354 | * length of 720 pixels @ 4:2:2 sampling. Thus... | ||
355 | * | ||
356 | * For systems that use a 15.734 kHz horizontal rate, such as | ||
357 | * NTSC-M, PAL-M, PAL-60, and other 60 Hz/525 line systems, we have: | ||
358 | * | ||
359 | * (1/15.734 kHz) * 2 * 13.5 MHz = 1716 samples/line = | ||
360 | * 4 bytes SAV + 268 bytes anc data + 4 bytes SAV + 1440 active samples | ||
361 | * | ||
362 | * For systems that use a 15.625 kHz horizontal rate, such as | ||
363 | * PAL-B/G/H, PAL-I, SECAM-L and other 50 Hz/625 line systems, we have: | ||
364 | * | ||
365 | * (1/15.625 kHz) * 2 * 13.5 MHz = 1728 samples/line = | ||
366 | * 4 bytes SAV + 280 bytes anc data + 4 bytes SAV + 1440 active samples | ||
367 | */ | ||
368 | static const u32 vbi_active_samples = 1444; /* 4 byte SAV + 720 Y + 720 U/V */ | ||
369 | static const u32 vbi_hblank_samples_60Hz = 272; /* 4 byte EAV + 268 anc/fill */ | ||
370 | static const u32 vbi_hblank_samples_50Hz = 284; /* 4 byte EAV + 280 anc/fill */ | ||
322 | 371 | ||
323 | #define CX18_VBI_FRAMES 32 | 372 | #define CX18_VBI_FRAMES 32 |
324 | 373 | ||
325 | /* VBI data */ | ||
326 | struct vbi_info { | 374 | struct vbi_info { |
327 | u32 enc_size; | 375 | /* Current state of v4l2 VBI settings for this device */ |
328 | u32 frame; | ||
329 | u8 cc_data_odd[256]; | ||
330 | u8 cc_data_even[256]; | ||
331 | int cc_pos; | ||
332 | u8 cc_no_update; | ||
333 | u8 vps[5]; | ||
334 | u8 vps_found; | ||
335 | int wss; | ||
336 | u8 wss_found; | ||
337 | u8 wss_no_update; | ||
338 | u32 raw_decoder_line_size; | ||
339 | u8 raw_decoder_sav_odd_field; | ||
340 | u8 raw_decoder_sav_even_field; | ||
341 | u32 sliced_decoder_line_size; | ||
342 | u8 sliced_decoder_sav_odd_field; | ||
343 | u8 sliced_decoder_sav_even_field; | ||
344 | struct v4l2_format in; | 376 | struct v4l2_format in; |
345 | /* convenience pointer to sliced struct in vbi_in union */ | 377 | struct v4l2_sliced_vbi_format *sliced_in; /* pointer to in.fmt.sliced */ |
346 | struct v4l2_sliced_vbi_format *sliced_in; | 378 | u32 count; /* Count of VBI data lines: 60 Hz: 12 or 50 Hz: 18 */ |
347 | u32 service_set_in; | 379 | u32 start[2]; /* First VBI data line per field: 10 & 273 or 6 & 318 */ |
348 | int insert_mpeg; | ||
349 | 380 | ||
350 | /* Buffer for the maximum of 2 * 18 * packet_size sliced VBI lines. | 381 | u32 frame; /* Count of VBI buffers/frames received from Encoder */ |
351 | One for /dev/vbi0 and one for /dev/vbi8 */ | ||
352 | struct v4l2_sliced_vbi_data sliced_data[36]; | ||
353 | 382 | ||
354 | /* Buffer for VBI data inserted into MPEG stream. | 383 | /* |
355 | The first byte is a dummy byte that's never used. | 384 | * Vars for creation and insertion of MPEG Private Stream 1 packets |
356 | The next 16 bytes contain the MPEG header for the VBI data, | 385 | * of sliced VBI data into an MPEG PS |
357 | the remainder is the actual VBI data. | 386 | */ |
358 | The max size accepted by the MPEG VBI reinsertion turns out | ||
359 | to be 1552 bytes, which happens to be 4 + (1 + 42) * (2 * 18) bytes, | ||
360 | where 4 is a four byte header, 42 is the max sliced VBI payload, 1 is | ||
361 | a single line header byte and 2 * 18 is the number of VBI lines per frame. | ||
362 | 387 | ||
363 | However, it seems that the data must be 1K aligned, so we have to | 388 | /* Boolean: create and insert Private Stream 1 packets into the PS */ |
364 | pad the data until the 1 or 2 K boundary. | 389 | int insert_mpeg; |
390 | |||
391 | /* | ||
392 | * Buffer for the maximum of 2 * 18 * packet_size sliced VBI lines. | ||
393 | * Used in cx18-vbi.c only for collecting sliced data, and as a source | ||
394 | * during conversion of sliced VBI data into MPEG Priv Stream 1 packets. | ||
395 | * We don't need to save state here, but the array may have been a bit | ||
396 | * too big (2304 bytes) to alloc from the stack. | ||
397 | */ | ||
398 | struct v4l2_sliced_vbi_data sliced_data[36]; | ||
365 | 399 | ||
366 | This pointer array will allocate 2049 bytes to store each VBI frame. */ | 400 | /* |
401 | * A ring buffer of driver-generated MPEG-2 PS | ||
402 | * Program Pack/Private Stream 1 packets for sliced VBI data insertion | ||
403 | * into the MPEG PS stream. | ||
404 | * | ||
405 | * In each sliced_mpeg_data[] buffer is: | ||
406 | * 16 byte MPEG-2 PS Program Pack Header | ||
407 | * 16 byte MPEG-2 Private Stream 1 PES Header | ||
408 | * 4 byte magic number: "itv0" or "ITV0" | ||
409 | * 4 byte first field line mask, if "itv0" | ||
410 | * 4 byte second field line mask, if "itv0" | ||
411 | * 36 lines, if "ITV0"; or <36 lines, if "itv0"; of sliced VBI data | ||
412 | * | ||
413 | * Each line in the payload is | ||
414 | * 1 byte line header derived from the SDID (WSS, CC, VPS, etc.) | ||
415 | * 42 bytes of line data | ||
416 | * | ||
417 | * That's a maximum 1552 bytes of payload in the Private Stream 1 packet | ||
418 | * which is the payload size a PVR-350 (CX23415) MPEG decoder will | ||
419 | * accept for VBI data. So, including the headers, it's a maximum 1584 | ||
420 | * bytes total. | ||
421 | */ | ||
422 | #define CX18_SLICED_MPEG_DATA_MAXSZ 1584 | ||
423 | /* copy_vbi_buf() needs 8 temp bytes on the end for the worst case */ | ||
424 | #define CX18_SLICED_MPEG_DATA_BUFSZ (CX18_SLICED_MPEG_DATA_MAXSZ+8) | ||
367 | u8 *sliced_mpeg_data[CX18_VBI_FRAMES]; | 425 | u8 *sliced_mpeg_data[CX18_VBI_FRAMES]; |
368 | u32 sliced_mpeg_size[CX18_VBI_FRAMES]; | 426 | u32 sliced_mpeg_size[CX18_VBI_FRAMES]; |
369 | struct cx18_buffer sliced_mpeg_buf; | 427 | |
428 | /* Count of Program Pack/Program Stream 1 packets inserted into PS */ | ||
370 | u32 inserted_frame; | 429 | u32 inserted_frame; |
371 | 430 | ||
372 | u32 start[2], count; | 431 | /* |
373 | u32 raw_size; | 432 | * A dummy driver stream transfer buffer with a copy of the next |
374 | u32 sliced_size; | 433 | * sliced_mpeg_data[] buffer for output to userland apps. |
434 | * Only used in cx18-fileops.c, but its state needs to persist at times. | ||
435 | */ | ||
436 | struct cx18_buffer sliced_mpeg_buf; | ||
375 | }; | 437 | }; |
376 | 438 | ||
377 | /* Per cx23418, per I2C bus private algo callback data */ | 439 | /* Per cx23418, per I2C bus private algo callback data */ |
diff --git a/drivers/media/video/cx18/cx18-fileops.c b/drivers/media/video/cx18/cx18-fileops.c index 23006f7d9159..0b1dbc67e1ab 100644 --- a/drivers/media/video/cx18/cx18-fileops.c +++ b/drivers/media/video/cx18/cx18-fileops.c | |||
@@ -176,6 +176,8 @@ static struct cx18_buffer *cx18_get_buffer(struct cx18_stream *s, int non_block, | |||
176 | *err = 0; | 176 | *err = 0; |
177 | while (1) { | 177 | while (1) { |
178 | if (s->type == CX18_ENC_STREAM_TYPE_MPG) { | 178 | if (s->type == CX18_ENC_STREAM_TYPE_MPG) { |
179 | /* Process pending program info updates and pending | ||
180 | VBI data */ | ||
179 | 181 | ||
180 | if (time_after(jiffies, cx->dualwatch_jiffies + msecs_to_jiffies(1000))) { | 182 | if (time_after(jiffies, cx->dualwatch_jiffies + msecs_to_jiffies(1000))) { |
181 | cx->dualwatch_jiffies = jiffies; | 183 | cx->dualwatch_jiffies = jiffies; |
@@ -260,6 +262,20 @@ static size_t cx18_copy_buf_to_user(struct cx18_stream *s, | |||
260 | len = ucount; | 262 | len = ucount; |
261 | if (cx->vbi.insert_mpeg && s->type == CX18_ENC_STREAM_TYPE_MPG && | 263 | if (cx->vbi.insert_mpeg && s->type == CX18_ENC_STREAM_TYPE_MPG && |
262 | !cx18_raw_vbi(cx) && buf != &cx->vbi.sliced_mpeg_buf) { | 264 | !cx18_raw_vbi(cx) && buf != &cx->vbi.sliced_mpeg_buf) { |
265 | /* | ||
266 | * Try to find a good splice point in the PS, just before | ||
267 | * an MPEG-2 Program Pack start code, and provide only | ||
268 | * up to that point to the user, so it's easy to insert VBI data | ||
269 | * the next time around. | ||
270 | */ | ||
271 | /* FIXME - This only works for an MPEG-2 PS, not a TS */ | ||
272 | /* | ||
273 | * An MPEG-2 Program Stream (PS) is a series of | ||
274 | * MPEG-2 Program Packs terminated by an | ||
275 | * MPEG Program End Code after the last Program Pack. | ||
276 | * A Program Pack may hold a PS System Header packet and any | ||
277 | * number of Program Elementary Stream (PES) Packets | ||
278 | */ | ||
263 | const char *start = buf->buf + buf->readpos; | 279 | const char *start = buf->buf + buf->readpos; |
264 | const char *p = start + 1; | 280 | const char *p = start + 1; |
265 | const u8 *q; | 281 | const u8 *q; |
@@ -267,38 +283,54 @@ static size_t cx18_copy_buf_to_user(struct cx18_stream *s, | |||
267 | int stuffing, i; | 283 | int stuffing, i; |
268 | 284 | ||
269 | while (start + len > p) { | 285 | while (start + len > p) { |
286 | /* Scan for a 0 to find a potential MPEG-2 start code */ | ||
270 | q = memchr(p, 0, start + len - p); | 287 | q = memchr(p, 0, start + len - p); |
271 | if (q == NULL) | 288 | if (q == NULL) |
272 | break; | 289 | break; |
273 | p = q + 1; | 290 | p = q + 1; |
291 | /* | ||
292 | * Keep looking if not a | ||
293 | * MPEG-2 Pack header start code: 0x00 0x00 0x01 0xba | ||
294 | * or MPEG-2 video PES start code: 0x00 0x00 0x01 0xe0 | ||
295 | */ | ||
274 | if ((char *)q + 15 >= buf->buf + buf->bytesused || | 296 | if ((char *)q + 15 >= buf->buf + buf->bytesused || |
275 | q[1] != 0 || q[2] != 1 || q[3] != ch) | 297 | q[1] != 0 || q[2] != 1 || q[3] != ch) |
276 | continue; | 298 | continue; |
299 | |||
300 | /* If expecting the primary video PES */ | ||
277 | if (!cx->search_pack_header) { | 301 | if (!cx->search_pack_header) { |
302 | /* Continue if it couldn't be a PES packet */ | ||
278 | if ((q[6] & 0xc0) != 0x80) | 303 | if ((q[6] & 0xc0) != 0x80) |
279 | continue; | 304 | continue; |
280 | if (((q[7] & 0xc0) == 0x80 && | 305 | /* Check if a PTS or PTS & DTS follow */ |
281 | (q[9] & 0xf0) == 0x20) || | 306 | if (((q[7] & 0xc0) == 0x80 && /* PTS only */ |
282 | ((q[7] & 0xc0) == 0xc0 && | 307 | (q[9] & 0xf0) == 0x20) || /* PTS only */ |
283 | (q[9] & 0xf0) == 0x30)) { | 308 | ((q[7] & 0xc0) == 0xc0 && /* PTS & DTS */ |
284 | ch = 0xba; | 309 | (q[9] & 0xf0) == 0x30)) { /* DTS follows */ |
310 | /* Assume we found the video PES hdr */ | ||
311 | ch = 0xba; /* next want a Program Pack*/ | ||
285 | cx->search_pack_header = 1; | 312 | cx->search_pack_header = 1; |
286 | p = q + 9; | 313 | p = q + 9; /* Skip this video PES hdr */ |
287 | } | 314 | } |
288 | continue; | 315 | continue; |
289 | } | 316 | } |
317 | |||
318 | /* We may have found a Program Pack start code */ | ||
319 | |||
320 | /* Get the count of stuffing bytes & verify them */ | ||
290 | stuffing = q[13] & 7; | 321 | stuffing = q[13] & 7; |
291 | /* all stuffing bytes must be 0xff */ | 322 | /* all stuffing bytes must be 0xff */ |
292 | for (i = 0; i < stuffing; i++) | 323 | for (i = 0; i < stuffing; i++) |
293 | if (q[14 + i] != 0xff) | 324 | if (q[14 + i] != 0xff) |
294 | break; | 325 | break; |
295 | if (i == stuffing && | 326 | if (i == stuffing && /* right number of stuffing bytes*/ |
296 | (q[4] & 0xc4) == 0x44 && | 327 | (q[4] & 0xc4) == 0x44 && /* marker check */ |
297 | (q[12] & 3) == 3 && | 328 | (q[12] & 3) == 3 && /* marker check */ |
298 | q[14 + stuffing] == 0 && | 329 | q[14 + stuffing] == 0 && /* PES Pack or Sys Hdr */ |
299 | q[15 + stuffing] == 0 && | 330 | q[15 + stuffing] == 0 && |
300 | q[16 + stuffing] == 1) { | 331 | q[16 + stuffing] == 1) { |
301 | cx->search_pack_header = 0; | 332 | /* We declare we actually found a Program Pack*/ |
333 | cx->search_pack_header = 0; /* expect vid PES */ | ||
302 | len = (char *)q - start; | 334 | len = (char *)q - start; |
303 | cx18_setup_sliced_vbi_buf(cx); | 335 | cx18_setup_sliced_vbi_buf(cx); |
304 | break; | 336 | break; |
diff --git a/drivers/media/video/cx18/cx18-ioctl.c b/drivers/media/video/cx18/cx18-ioctl.c index 20467fce5251..1adb97220920 100644 --- a/drivers/media/video/cx18/cx18-ioctl.c +++ b/drivers/media/video/cx18/cx18-ioctl.c | |||
@@ -102,6 +102,19 @@ void cx18_expand_service_set(struct v4l2_sliced_vbi_format *fmt, int is_pal) | |||
102 | } | 102 | } |
103 | } | 103 | } |
104 | 104 | ||
105 | static int check_service_set(struct v4l2_sliced_vbi_format *fmt, int is_pal) | ||
106 | { | ||
107 | int f, l; | ||
108 | u16 set = 0; | ||
109 | |||
110 | for (f = 0; f < 2; f++) { | ||
111 | for (l = 0; l < 24; l++) { | ||
112 | fmt->service_lines[f][l] = select_service_from_set(f, l, fmt->service_lines[f][l], is_pal); | ||
113 | set |= fmt->service_lines[f][l]; | ||
114 | } | ||
115 | } | ||
116 | return set != 0; | ||
117 | } | ||
105 | 118 | ||
106 | u16 cx18_get_service_set(struct v4l2_sliced_vbi_format *fmt) | 119 | u16 cx18_get_service_set(struct v4l2_sliced_vbi_format *fmt) |
107 | { | 120 | { |
@@ -150,7 +163,7 @@ static int cx18_g_fmt_vbi_cap(struct file *file, void *fh, | |||
150 | 163 | ||
151 | vbifmt->sampling_rate = 27000000; | 164 | vbifmt->sampling_rate = 27000000; |
152 | vbifmt->offset = 248; | 165 | vbifmt->offset = 248; |
153 | vbifmt->samples_per_line = cx->vbi.raw_decoder_line_size - 4; | 166 | vbifmt->samples_per_line = vbi_active_samples - 4; |
154 | vbifmt->sample_format = V4L2_PIX_FMT_GREY; | 167 | vbifmt->sample_format = V4L2_PIX_FMT_GREY; |
155 | vbifmt->start[0] = cx->vbi.start[0]; | 168 | vbifmt->start[0] = cx->vbi.start[0]; |
156 | vbifmt->start[1] = cx->vbi.start[1]; | 169 | vbifmt->start[1] = cx->vbi.start[1]; |
@@ -164,7 +177,17 @@ static int cx18_g_fmt_vbi_cap(struct file *file, void *fh, | |||
164 | static int cx18_g_fmt_sliced_vbi_cap(struct file *file, void *fh, | 177 | static int cx18_g_fmt_sliced_vbi_cap(struct file *file, void *fh, |
165 | struct v4l2_format *fmt) | 178 | struct v4l2_format *fmt) |
166 | { | 179 | { |
167 | return -EINVAL; | 180 | struct cx18 *cx = ((struct cx18_open_id *)fh)->cx; |
181 | struct v4l2_sliced_vbi_format *vbifmt = &fmt->fmt.sliced; | ||
182 | |||
183 | vbifmt->reserved[0] = 0; | ||
184 | vbifmt->reserved[1] = 0; | ||
185 | vbifmt->io_size = sizeof(struct v4l2_sliced_vbi_data) * 36; | ||
186 | memset(vbifmt->service_lines, 0, sizeof(vbifmt->service_lines)); | ||
187 | |||
188 | cx18_av_cmd(cx, VIDIOC_G_FMT, fmt); | ||
189 | vbifmt->service_set = cx18_get_service_set(vbifmt); | ||
190 | return 0; | ||
168 | } | 191 | } |
169 | 192 | ||
170 | static int cx18_try_fmt_vid_cap(struct file *file, void *fh, | 193 | static int cx18_try_fmt_vid_cap(struct file *file, void *fh, |
@@ -194,7 +217,18 @@ static int cx18_try_fmt_vbi_cap(struct file *file, void *fh, | |||
194 | static int cx18_try_fmt_sliced_vbi_cap(struct file *file, void *fh, | 217 | static int cx18_try_fmt_sliced_vbi_cap(struct file *file, void *fh, |
195 | struct v4l2_format *fmt) | 218 | struct v4l2_format *fmt) |
196 | { | 219 | { |
197 | return -EINVAL; | 220 | struct cx18 *cx = ((struct cx18_open_id *)fh)->cx; |
221 | struct v4l2_sliced_vbi_format *vbifmt = &fmt->fmt.sliced; | ||
222 | |||
223 | vbifmt->io_size = sizeof(struct v4l2_sliced_vbi_data) * 36; | ||
224 | vbifmt->reserved[0] = 0; | ||
225 | vbifmt->reserved[1] = 0; | ||
226 | |||
227 | if (vbifmt->service_set) | ||
228 | cx18_expand_service_set(vbifmt, cx->is_50hz); | ||
229 | check_service_set(vbifmt, cx->is_50hz); | ||
230 | vbifmt->service_set = cx18_get_service_set(vbifmt); | ||
231 | return 0; | ||
198 | } | 232 | } |
199 | 233 | ||
200 | static int cx18_s_fmt_vid_cap(struct file *file, void *fh, | 234 | static int cx18_s_fmt_vid_cap(struct file *file, void *fh, |
@@ -250,7 +284,28 @@ static int cx18_s_fmt_vbi_cap(struct file *file, void *fh, | |||
250 | static int cx18_s_fmt_sliced_vbi_cap(struct file *file, void *fh, | 284 | static int cx18_s_fmt_sliced_vbi_cap(struct file *file, void *fh, |
251 | struct v4l2_format *fmt) | 285 | struct v4l2_format *fmt) |
252 | { | 286 | { |
253 | return -EINVAL; | 287 | struct cx18_open_id *id = fh; |
288 | struct cx18 *cx = id->cx; | ||
289 | int ret; | ||
290 | struct v4l2_sliced_vbi_format *vbifmt = &fmt->fmt.sliced; | ||
291 | |||
292 | ret = v4l2_prio_check(&cx->prio, &id->prio); | ||
293 | if (ret) | ||
294 | return ret; | ||
295 | |||
296 | ret = cx18_try_fmt_sliced_vbi_cap(file, fh, fmt); | ||
297 | if (ret) | ||
298 | return ret; | ||
299 | |||
300 | if (check_service_set(vbifmt, cx->is_50hz) == 0) | ||
301 | return -EINVAL; | ||
302 | |||
303 | if (cx18_raw_vbi(cx) && atomic_read(&cx->ana_capturing) > 0) | ||
304 | return -EBUSY; | ||
305 | cx->vbi.in.type = V4L2_BUF_TYPE_SLICED_VBI_CAPTURE; | ||
306 | cx18_av_cmd(cx, VIDIOC_S_FMT, fmt); | ||
307 | memcpy(cx->vbi.sliced_in, vbifmt, sizeof(*cx->vbi.sliced_in)); | ||
308 | return 0; | ||
254 | } | 309 | } |
255 | 310 | ||
256 | static int cx18_g_chip_ident(struct file *file, void *fh, | 311 | static int cx18_g_chip_ident(struct file *file, void *fh, |
@@ -548,7 +603,6 @@ int cx18_s_std(struct file *file, void *fh, v4l2_std_id *std) | |||
548 | cx->vbi.count = cx->is_50hz ? 18 : 12; | 603 | cx->vbi.count = cx->is_50hz ? 18 : 12; |
549 | cx->vbi.start[0] = cx->is_50hz ? 6 : 10; | 604 | cx->vbi.start[0] = cx->is_50hz ? 6 : 10; |
550 | cx->vbi.start[1] = cx->is_50hz ? 318 : 273; | 605 | cx->vbi.start[1] = cx->is_50hz ? 318 : 273; |
551 | cx->vbi.sliced_decoder_line_size = cx->is_60hz ? 272 : 284; | ||
552 | CX18_DEBUG_INFO("Switching standard to %llx.\n", | 606 | CX18_DEBUG_INFO("Switching standard to %llx.\n", |
553 | (unsigned long long) cx->std); | 607 | (unsigned long long) cx->std); |
554 | 608 | ||
@@ -599,6 +653,19 @@ static int cx18_g_tuner(struct file *file, void *fh, struct v4l2_tuner *vt) | |||
599 | static int cx18_g_sliced_vbi_cap(struct file *file, void *fh, | 653 | static int cx18_g_sliced_vbi_cap(struct file *file, void *fh, |
600 | struct v4l2_sliced_vbi_cap *cap) | 654 | struct v4l2_sliced_vbi_cap *cap) |
601 | { | 655 | { |
656 | struct cx18 *cx = ((struct cx18_open_id *)fh)->cx; | ||
657 | int set = cx->is_50hz ? V4L2_SLICED_VBI_625 : V4L2_SLICED_VBI_525; | ||
658 | int f, l; | ||
659 | |||
660 | if (cap->type == V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) { | ||
661 | for (f = 0; f < 2; f++) { | ||
662 | for (l = 0; l < 24; l++) { | ||
663 | if (valid_service_line(f, l, cx->is_50hz)) | ||
664 | cap->service_lines[f][l] = set; | ||
665 | } | ||
666 | } | ||
667 | return 0; | ||
668 | } | ||
602 | return -EINVAL; | 669 | return -EINVAL; |
603 | } | 670 | } |
604 | 671 | ||
diff --git a/drivers/media/video/cx18/cx18-streams.c b/drivers/media/video/cx18/cx18-streams.c index abc3fe605f00..a89f7f840d95 100644 --- a/drivers/media/video/cx18/cx18-streams.c +++ b/drivers/media/video/cx18/cx18-streams.c | |||
@@ -349,10 +349,6 @@ static void cx18_vbi_setup(struct cx18_stream *s) | |||
349 | /* setup VBI registers */ | 349 | /* setup VBI registers */ |
350 | cx18_av_cmd(cx, VIDIOC_S_FMT, &cx->vbi.in); | 350 | cx18_av_cmd(cx, VIDIOC_S_FMT, &cx->vbi.in); |
351 | 351 | ||
352 | /* determine number of lines and total number of VBI bytes. | ||
353 | A raw line takes 1444 bytes: 4 byte SAV code + 2 * 720 | ||
354 | A sliced line takes 51 bytes: 4 byte frame header, 4 byte internal | ||
355 | header, 42 data bytes + checksum (to be confirmed) */ | ||
356 | if (raw) { | 352 | if (raw) { |
357 | lines = cx->vbi.count * 2; | 353 | lines = cx->vbi.count * 2; |
358 | } else { | 354 | } else { |
@@ -361,24 +357,53 @@ static void cx18_vbi_setup(struct cx18_stream *s) | |||
361 | lines += 2; | 357 | lines += 2; |
362 | } | 358 | } |
363 | 359 | ||
364 | cx->vbi.enc_size = lines * | ||
365 | (raw ? cx->vbi.raw_size : cx->vbi.sliced_size); | ||
366 | |||
367 | data[0] = s->handle; | 360 | data[0] = s->handle; |
368 | /* Lines per field */ | 361 | /* Lines per field */ |
369 | data[1] = (lines / 2) | ((lines / 2) << 16); | 362 | data[1] = (lines / 2) | ((lines / 2) << 16); |
370 | /* bytes per line */ | 363 | /* bytes per line */ |
371 | data[2] = (raw ? cx->vbi.raw_decoder_line_size | 364 | data[2] = (raw ? vbi_active_samples |
372 | : cx->vbi.sliced_decoder_line_size); | 365 | : (cx->is_60hz ? vbi_hblank_samples_60Hz |
366 | : vbi_hblank_samples_50Hz)); | ||
373 | /* Every X number of frames a VBI interrupt arrives | 367 | /* Every X number of frames a VBI interrupt arrives |
374 | (frames as in 25 or 30 fps) */ | 368 | (frames as in 25 or 30 fps) */ |
375 | data[3] = 1; | 369 | data[3] = 1; |
376 | /* Setup VBI for the cx25840 digitizer */ | 370 | /* |
371 | * Set the SAV/EAV RP codes to look for as start/stop points | ||
372 | * when in VIP-1.1 mode | ||
373 | */ | ||
377 | if (raw) { | 374 | if (raw) { |
375 | /* | ||
376 | * Start codes for beginning of "active" line in vertical blank | ||
377 | * 0x20 ( VerticalBlank ) | ||
378 | * 0x60 ( EvenField VerticalBlank ) | ||
379 | */ | ||
378 | data[4] = 0x20602060; | 380 | data[4] = 0x20602060; |
381 | /* | ||
382 | * End codes for end of "active" raw lines and regular lines | ||
383 | * 0x30 ( VerticalBlank HorizontalBlank) | ||
384 | * 0x70 ( EvenField VerticalBlank HorizontalBlank) | ||
385 | * 0x90 (Task HorizontalBlank) | ||
386 | * 0xd0 (Task EvenField HorizontalBlank) | ||
387 | */ | ||
379 | data[5] = 0x307090d0; | 388 | data[5] = 0x307090d0; |
380 | } else { | 389 | } else { |
390 | /* | ||
391 | * End codes for active video, we want data in the hblank region | ||
392 | * 0xb0 (Task 0 VerticalBlank HorizontalBlank) | ||
393 | * 0xf0 (Task EvenField VerticalBlank HorizontalBlank) | ||
394 | * | ||
395 | * Since the V bit is only allowed to toggle in the EAV RP code, | ||
396 | * just before the first active region line, these two | ||
397 | * are problematic and we have to ignore them: | ||
398 | * 0x90 (Task HorizontalBlank) | ||
399 | * 0xd0 (Task EvenField HorizontalBlank) | ||
400 | */ | ||
381 | data[4] = 0xB0F0B0F0; | 401 | data[4] = 0xB0F0B0F0; |
402 | /* | ||
403 | * Start codes for beginning of active line in vertical blank | ||
404 | * 0xa0 (Task VerticalBlank ) | ||
405 | * 0xe0 (Task EvenField VerticalBlank ) | ||
406 | */ | ||
382 | data[5] = 0xA0E0A0E0; | 407 | data[5] = 0xA0E0A0E0; |
383 | } | 408 | } |
384 | 409 | ||
diff --git a/drivers/media/video/cx18/cx18-vbi.c b/drivers/media/video/cx18/cx18-vbi.c index fb595bd548e8..38d26c42e4cb 100644 --- a/drivers/media/video/cx18/cx18-vbi.c +++ b/drivers/media/video/cx18/cx18-vbi.c | |||
@@ -27,6 +27,16 @@ | |||
27 | #include "cx18-queue.h" | 27 | #include "cx18-queue.h" |
28 | #include "cx18-av-core.h" | 28 | #include "cx18-av-core.h" |
29 | 29 | ||
30 | /* | ||
31 | * Raster Reference/Protection (RP) bytes, used in Start/End Active | ||
32 | * Video codes emitted from the digitzer in VIP 1.x mode, that flag the start | ||
33 | * of VBI sample or VBI ancilliary data regions in the digitial ratser line. | ||
34 | * | ||
35 | * Task FieldEven VerticalBlank HorizontalBlank 0 0 0 0 | ||
36 | */ | ||
37 | static const u8 raw_vbi_sav_rp[2] = { 0x20, 0x60 }; /* __V_, _FV_ */ | ||
38 | static const u8 sliced_vbi_eav_rp[2] = { 0xb0, 0xf0 }; /* T_VH, TFVH */ | ||
39 | |||
30 | static void copy_vbi_data(struct cx18 *cx, int lines, u32 pts_stamp) | 40 | static void copy_vbi_data(struct cx18 *cx, int lines, u32 pts_stamp) |
31 | { | 41 | { |
32 | int line = 0; | 42 | int line = 0; |
@@ -34,10 +44,17 @@ static void copy_vbi_data(struct cx18 *cx, int lines, u32 pts_stamp) | |||
34 | u32 linemask[2] = { 0, 0 }; | 44 | u32 linemask[2] = { 0, 0 }; |
35 | unsigned short size; | 45 | unsigned short size; |
36 | static const u8 mpeg_hdr_data[] = { | 46 | static const u8 mpeg_hdr_data[] = { |
37 | 0x00, 0x00, 0x01, 0xba, 0x44, 0x00, 0x0c, 0x66, | 47 | /* MPEG-2 Program Pack */ |
38 | 0x24, 0x01, 0x01, 0xd1, 0xd3, 0xfa, 0xff, 0xff, | 48 | 0x00, 0x00, 0x01, 0xba, /* Prog Pack start code */ |
39 | 0x00, 0x00, 0x01, 0xbd, 0x00, 0x1a, 0x84, 0x80, | 49 | 0x44, 0x00, 0x0c, 0x66, 0x24, 0x01, /* SCR, SCR Ext, markers */ |
40 | 0x07, 0x21, 0x00, 0x5d, 0x63, 0xa7, 0xff, 0xff | 50 | 0x01, 0xd1, 0xd3, /* Mux Rate, markers */ |
51 | 0xfa, 0xff, 0xff, /* Res, Suff cnt, Stuff */ | ||
52 | /* MPEG-2 Private Stream 1 PES Packet */ | ||
53 | 0x00, 0x00, 0x01, 0xbd, /* Priv Stream 1 start */ | ||
54 | 0x00, 0x1a, /* length */ | ||
55 | 0x84, 0x80, 0x07, /* flags, hdr data len */ | ||
56 | 0x21, 0x00, 0x5d, 0x63, 0xa7, /* PTS, markers */ | ||
57 | 0xff, 0xff /* stuffing */ | ||
41 | }; | 58 | }; |
42 | const int sd = sizeof(mpeg_hdr_data); /* start of vbi data */ | 59 | const int sd = sizeof(mpeg_hdr_data); /* start of vbi data */ |
43 | int idx = cx->vbi.frame % CX18_VBI_FRAMES; | 60 | int idx = cx->vbi.frame % CX18_VBI_FRAMES; |
@@ -71,7 +88,7 @@ static void copy_vbi_data(struct cx18 *cx, int lines, u32 pts_stamp) | |||
71 | memcpy(dst + sd + 4, dst + sd + 12, line * 43); | 88 | memcpy(dst + sd + 4, dst + sd + 12, line * 43); |
72 | size = 4 + ((43 * line + 3) & ~3); | 89 | size = 4 + ((43 * line + 3) & ~3); |
73 | } else { | 90 | } else { |
74 | memcpy(dst + sd, "cx0", 4); | 91 | memcpy(dst + sd, "itv0", 4); |
75 | memcpy(dst + sd + 4, &linemask[0], 8); | 92 | memcpy(dst + sd + 4, &linemask[0], 8); |
76 | size = 12 + ((43 * line + 3) & ~3); | 93 | size = 12 + ((43 * line + 3) & ~3); |
77 | } | 94 | } |
@@ -90,10 +107,10 @@ static void copy_vbi_data(struct cx18 *cx, int lines, u32 pts_stamp) | |||
90 | Returns new compressed size. */ | 107 | Returns new compressed size. */ |
91 | static u32 compress_raw_buf(struct cx18 *cx, u8 *buf, u32 size) | 108 | static u32 compress_raw_buf(struct cx18 *cx, u8 *buf, u32 size) |
92 | { | 109 | { |
93 | u32 line_size = cx->vbi.raw_decoder_line_size; | 110 | u32 line_size = vbi_active_samples; |
94 | u32 lines = cx->vbi.count; | 111 | u32 lines = cx->vbi.count; |
95 | u8 sav1 = cx->vbi.raw_decoder_sav_odd_field; | 112 | u8 sav1 = raw_vbi_sav_rp[0]; |
96 | u8 sav2 = cx->vbi.raw_decoder_sav_even_field; | 113 | u8 sav2 = raw_vbi_sav_rp[1]; |
97 | u8 *q = buf; | 114 | u8 *q = buf; |
98 | u8 *p; | 115 | u8 *p; |
99 | int i; | 116 | int i; |
@@ -115,15 +132,16 @@ static u32 compress_raw_buf(struct cx18 *cx, u8 *buf, u32 size) | |||
115 | /* Compressed VBI format, all found sliced blocks put next to one another | 132 | /* Compressed VBI format, all found sliced blocks put next to one another |
116 | Returns new compressed size */ | 133 | Returns new compressed size */ |
117 | static u32 compress_sliced_buf(struct cx18 *cx, u32 line, u8 *buf, | 134 | static u32 compress_sliced_buf(struct cx18 *cx, u32 line, u8 *buf, |
118 | u32 size, u8 sav) | 135 | u32 size, u8 eav) |
119 | { | 136 | { |
120 | u32 line_size = cx->vbi.sliced_decoder_line_size; | ||
121 | struct v4l2_decode_vbi_line vbi; | 137 | struct v4l2_decode_vbi_line vbi; |
122 | int i; | 138 | int i; |
139 | u32 line_size = cx->is_60hz ? vbi_hblank_samples_60Hz | ||
140 | : vbi_hblank_samples_50Hz; | ||
123 | 141 | ||
124 | /* find the first valid line */ | 142 | /* find the first valid line */ |
125 | for (i = 0; i < size; i++, buf++) { | 143 | for (i = 0; i < size; i++, buf++) { |
126 | if (buf[0] == 0xff && !buf[1] && !buf[2] && buf[3] == sav) | 144 | if (buf[0] == 0xff && !buf[1] && !buf[2] && buf[3] == eav) |
127 | break; | 145 | break; |
128 | } | 146 | } |
129 | 147 | ||
@@ -133,8 +151,8 @@ static u32 compress_sliced_buf(struct cx18 *cx, u32 line, u8 *buf, | |||
133 | for (i = 0; i < size / line_size; i++) { | 151 | for (i = 0; i < size / line_size; i++) { |
134 | u8 *p = buf + i * line_size; | 152 | u8 *p = buf + i * line_size; |
135 | 153 | ||
136 | /* Look for SAV code */ | 154 | /* Look for EAV code */ |
137 | if (p[0] != 0xff || p[1] || p[2] || p[3] != sav) | 155 | if (p[0] != 0xff || p[1] || p[2] || p[3] != eav) |
138 | continue; | 156 | continue; |
139 | vbi.p = p + 4; | 157 | vbi.p = p + 4; |
140 | cx18_av_cmd(cx, VIDIOC_INT_DECODE_VBI_LINE, &vbi); | 158 | cx18_av_cmd(cx, VIDIOC_INT_DECODE_VBI_LINE, &vbi); |
@@ -159,6 +177,12 @@ void cx18_process_vbi_data(struct cx18 *cx, struct cx18_buffer *buf, | |||
159 | if (streamtype != CX18_ENC_STREAM_TYPE_VBI) | 177 | if (streamtype != CX18_ENC_STREAM_TYPE_VBI) |
160 | return; | 178 | return; |
161 | 179 | ||
180 | /* | ||
181 | * Note the CX23418 provides a 12 byte header, in it's raw VBI | ||
182 | * buffers to us, that we currently throw away: | ||
183 | * 0x3fffffff [4 bytes of something] [4 byte timestamp] | ||
184 | */ | ||
185 | |||
162 | /* Raw VBI data */ | 186 | /* Raw VBI data */ |
163 | if (cx18_raw_vbi(cx)) { | 187 | if (cx18_raw_vbi(cx)) { |
164 | u8 type; | 188 | u8 type; |
@@ -173,7 +197,7 @@ void cx18_process_vbi_data(struct cx18 *cx, struct cx18_buffer *buf, | |||
173 | size = buf->bytesused = compress_raw_buf(cx, p, size); | 197 | size = buf->bytesused = compress_raw_buf(cx, p, size); |
174 | 198 | ||
175 | /* second field of the frame? */ | 199 | /* second field of the frame? */ |
176 | if (type == cx->vbi.raw_decoder_sav_even_field) { | 200 | if (type == raw_vbi_sav_rp[1]) { |
177 | /* Dirty hack needed for backwards | 201 | /* Dirty hack needed for backwards |
178 | compatibility of old VBI software. */ | 202 | compatibility of old VBI software. */ |
179 | p += size - 4; | 203 | p += size - 4; |
@@ -187,14 +211,14 @@ void cx18_process_vbi_data(struct cx18 *cx, struct cx18_buffer *buf, | |||
187 | cx18_buf_swap(buf); | 211 | cx18_buf_swap(buf); |
188 | 212 | ||
189 | /* first field */ | 213 | /* first field */ |
190 | lines = compress_sliced_buf(cx, 0, p, size / 2, | 214 | /* compress_sliced_buf() will skip the 12 bytes of header */ |
191 | cx->vbi.sliced_decoder_sav_odd_field); | 215 | lines = compress_sliced_buf(cx, 0, p, size / 2, sliced_vbi_eav_rp[0]); |
192 | /* second field */ | 216 | /* second field */ |
193 | /* experimentation shows that the second half does not always | 217 | /* experimentation shows that the second half does not always |
194 | begin at the exact address. So start a bit earlier | 218 | begin at the exact address. So start a bit earlier |
195 | (hence 32). */ | 219 | (hence 32). */ |
196 | lines = compress_sliced_buf(cx, lines, p + size / 2 - 32, | 220 | lines = compress_sliced_buf(cx, lines, p + size / 2 - 32, |
197 | size / 2 + 32, cx->vbi.sliced_decoder_sav_even_field); | 221 | size / 2 + 32, sliced_vbi_eav_rp[1]); |
198 | /* always return at least one empty line */ | 222 | /* always return at least one empty line */ |
199 | if (lines == 0) { | 223 | if (lines == 0) { |
200 | cx->vbi.sliced_data[0].id = 0; | 224 | cx->vbi.sliced_data[0].id = 0; |