diff options
author | Andy Walls <awalls@radix.net> | 2009-02-08 20:40:04 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2009-03-30 11:42:39 -0400 |
commit | 812b1f9d54a5f75066f8a5c92166a979c48c98c6 (patch) | |
tree | d04cdfdd80d0e2df825dbd22a6130434867233f0 /drivers/media/video | |
parent | 466df46484aced005fa41706f87e18eaa86918ad (diff) |
V4L/DVB (10446): cx18: Finally get sliced VBI working - for 525 line 60 Hz systems at least
Sliced VBI, in the manner that ivtv implements it as a separate data stream,
now works for 525 line 60 Hz systems like NTSC-M. It may work for 625 line
50 Hz systems, but I have more engineering work to do, to verify it is operating
properly. Sliced data insertion into the MPEG PS should be working, but is
untested.
Signed-off-by: Andy Walls <awalls@radix.net>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video')
-rw-r--r-- | drivers/media/video/cx18/cx18-av-core.c | 44 | ||||
-rw-r--r-- | drivers/media/video/cx18/cx18-av-core.h | 19 | ||||
-rw-r--r-- | drivers/media/video/cx18/cx18-av-vbi.c | 10 | ||||
-rw-r--r-- | drivers/media/video/cx18/cx18-driver.c | 4 | ||||
-rw-r--r-- | drivers/media/video/cx18/cx18-streams.c | 19 | ||||
-rw-r--r-- | drivers/media/video/cx18/cx18-vbi.c | 19 |
6 files changed, 88 insertions, 27 deletions
diff --git a/drivers/media/video/cx18/cx18-av-core.c b/drivers/media/video/cx18/cx18-av-core.c index 1d197649446e..a3bd2c95f582 100644 --- a/drivers/media/video/cx18/cx18-av-core.c +++ b/drivers/media/video/cx18/cx18-av-core.c | |||
@@ -172,11 +172,11 @@ static void cx18_av_initialize(struct cx18 *cx) | |||
172 | /* | 172 | /* |
173 | * Initial VBI setup | 173 | * Initial VBI setup |
174 | * VIP-1.1, 10 bit mode, enable Raw, disable sliced, | 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, | 175 | * don't clamp raw samples when codes are in use, 1 byte user D-words, |
176 | * programmed IDID, RP code V bit transition on VBLANK, data during | 176 | * IDID0 has line #, RP code V bit transition on VBLANK, data during |
177 | * blanking intervals | 177 | * blanking intervals |
178 | */ | 178 | */ |
179 | cx18_av_write4(cx, CXADEC_OUT_CTRL1, 0x4010252e); | 179 | cx18_av_write4(cx, CXADEC_OUT_CTRL1, 0x4013252e); |
180 | 180 | ||
181 | /* Set the video input. | 181 | /* Set the video input. |
182 | 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 */ |
@@ -218,6 +218,7 @@ void cx18_av_std_setup(struct cx18 *cx) | |||
218 | cx18_av_write(cx, 0x49f, 0x14); | 218 | cx18_av_write(cx, 0x49f, 0x14); |
219 | 219 | ||
220 | if (std & V4L2_STD_625_50) { | 220 | if (std & V4L2_STD_625_50) { |
221 | /* FIXME - revisit these for Sliced VBI */ | ||
221 | hblank = 132; | 222 | hblank = 132; |
222 | hactive = 720; | 223 | hactive = 720; |
223 | burst = 93; | 224 | burst = 93; |
@@ -241,13 +242,34 @@ void cx18_av_std_setup(struct cx18 *cx) | |||
241 | sc = 672351; | 242 | sc = 672351; |
242 | } | 243 | } |
243 | } else { | 244 | } else { |
245 | /* | ||
246 | * The following relationships of half line counts should hold: | ||
247 | * 525 = vsync + vactive + vblank656 | ||
248 | * 12 = vblank656 - vblank | ||
249 | * | ||
250 | * vsync: always 6 half-lines of vsync pulses | ||
251 | * vactive: half lines of active video | ||
252 | * vblank656: half lines, after line 3, of blanked video | ||
253 | * vblank: half lines, after line 9, of blanked video | ||
254 | * | ||
255 | * vblank656 starts counting from the falling edge of the first | ||
256 | * vsync pulse (start of line 4) | ||
257 | * vblank starts counting from the after the 6 vsync pulses and | ||
258 | * 6 equalization pulses (start of line 10) | ||
259 | * | ||
260 | * For 525 line systems the driver will extract VBI information | ||
261 | * from lines 10 through 21. To avoid the EAV RP code from | ||
262 | * toggling at the start of hblank at line 22, where sliced VBI | ||
263 | * data from line 21 is stuffed, also treat line 22 as blanked. | ||
264 | */ | ||
265 | vblank656 = 38; /* lines 4 through 22 */ | ||
266 | vblank = 26; /* lines 10 through 22 */ | ||
267 | vactive = 481; /* lines 23 through 262.5 */ | ||
268 | |||
244 | hactive = 720; | 269 | hactive = 720; |
245 | hblank = 122; | 270 | hblank = 122; |
246 | vactive = 487; | ||
247 | luma_lpf = 1; | 271 | luma_lpf = 1; |
248 | uv_lpf = 1; | 272 | uv_lpf = 1; |
249 | vblank = 26; | ||
250 | vblank656 = 26; | ||
251 | 273 | ||
252 | src_decimation = 0x21f; | 274 | src_decimation = 0x21f; |
253 | if (std == V4L2_STD_PAL_60) { | 275 | if (std == V4L2_STD_PAL_60) { |
@@ -330,14 +352,14 @@ void cx18_av_std_setup(struct cx18 *cx) | |||
330 | cx18_av_write(cx, 0x47d, 0xff & sc >> 8); | 352 | cx18_av_write(cx, 0x47d, 0xff & sc >> 8); |
331 | cx18_av_write(cx, 0x47e, 0xff & sc >> 16); | 353 | cx18_av_write(cx, 0x47e, 0xff & sc >> 16); |
332 | 354 | ||
333 | /* Sets VBI parameters */ | ||
334 | if (std & V4L2_STD_625_50) { | 355 | if (std & V4L2_STD_625_50) { |
335 | cx18_av_write(cx, 0x47f, 0x01); | 356 | state->slicer_line_delay = 1; |
336 | state->vbi_line_offset = 5; | 357 | state->slicer_line_offset = (6 + state->slicer_line_delay - 2); |
337 | } else { | 358 | } else { |
338 | cx18_av_write(cx, 0x47f, 0x00); | 359 | state->slicer_line_delay = 0; |
339 | state->vbi_line_offset = 8; | 360 | state->slicer_line_offset = (10 + state->slicer_line_delay - 2); |
340 | } | 361 | } |
362 | cx18_av_write(cx, 0x47f, state->slicer_line_delay); | ||
341 | } | 363 | } |
342 | 364 | ||
343 | /* ----------------------------------------------------------------------- */ | 365 | /* ----------------------------------------------------------------------- */ |
diff --git a/drivers/media/video/cx18/cx18-av-core.h b/drivers/media/video/cx18/cx18-av-core.h index cf68a6039091..d83760cae540 100644 --- a/drivers/media/video/cx18/cx18-av-core.h +++ b/drivers/media/video/cx18/cx18-av-core.h | |||
@@ -79,11 +79,28 @@ struct cx18_av_state { | |||
79 | enum cx18_av_audio_input aud_input; | 79 | enum cx18_av_audio_input aud_input; |
80 | u32 audclk_freq; | 80 | u32 audclk_freq; |
81 | int audmode; | 81 | int audmode; |
82 | int vbi_line_offset; | ||
83 | int default_volume; | 82 | int default_volume; |
84 | u32 id; | 83 | u32 id; |
85 | u32 rev; | 84 | u32 rev; |
86 | int is_initialized; | 85 | int is_initialized; |
86 | |||
87 | /* | ||
88 | * The VBI slicer starts operating and counting lines, begining at | ||
89 | * slicer line count of 1, at D lines after the deassertion of VRESET | ||
90 | * This staring field line, S, is 6 or 10 for 625 or 525 line systems. | ||
91 | * Sliced ancillary data captured on VBI slicer line M is sent at the | ||
92 | * beginning of the next VBI slicer line, VBI slicer line count N = M+1. | ||
93 | * Thus when the VBI slicer reports a VBI slicer line number with | ||
94 | * ancillary data, the IDID0 byte indicates VBI slicer line N. | ||
95 | * The actual field line that the captured data comes from is | ||
96 | * L = M+(S+D-1) = N-1+(S+D-1) = N + (S+D-2). | ||
97 | * | ||
98 | * D is the slicer_line_delay value programmed into register 0x47f. | ||
99 | * (S+D-2) is the slicer_line_offset used to convert slicer reported | ||
100 | * line counts to actual field lines. | ||
101 | */ | ||
102 | int slicer_line_delay; | ||
103 | int slicer_line_offset; | ||
87 | }; | 104 | }; |
88 | 105 | ||
89 | 106 | ||
diff --git a/drivers/media/video/cx18/cx18-av-vbi.c b/drivers/media/video/cx18/cx18-av-vbi.c index b5763372a316..43267d1afb92 100644 --- a/drivers/media/video/cx18/cx18-av-vbi.c +++ b/drivers/media/video/cx18/cx18-av-vbi.c | |||
@@ -182,7 +182,6 @@ int cx18_av_vbi(struct cx18 *cx, unsigned int cmd, void *arg) | |||
182 | case VIDIOC_S_FMT: | 182 | case VIDIOC_S_FMT: |
183 | { | 183 | { |
184 | int is_pal = !(state->std & V4L2_STD_525_60); | 184 | int is_pal = !(state->std & V4L2_STD_525_60); |
185 | int vbi_offset = is_pal ? 1 : 0; | ||
186 | int i, x; | 185 | int i, x; |
187 | u8 lcr[24]; | 186 | u8 lcr[24]; |
188 | 187 | ||
@@ -199,7 +198,7 @@ int cx18_av_vbi(struct cx18 *cx, unsigned int cmd, void *arg) | |||
199 | cx18_av_std_setup(cx); | 198 | cx18_av_std_setup(cx); |
200 | 199 | ||
201 | /* VBI Offset */ | 200 | /* VBI Offset */ |
202 | cx18_av_write(cx, 0x47f, vbi_offset); | 201 | cx18_av_write(cx, 0x47f, state->slicer_line_delay); |
203 | cx18_av_write(cx, 0x404, 0x2e); | 202 | cx18_av_write(cx, 0x404, 0x2e); |
204 | break; | 203 | break; |
205 | } | 204 | } |
@@ -213,7 +212,7 @@ int cx18_av_vbi(struct cx18 *cx, unsigned int cmd, void *arg) | |||
213 | /* Sliced VBI */ | 212 | /* Sliced VBI */ |
214 | cx18_av_write(cx, 0x404, 0x32); /* Ancillary data */ | 213 | cx18_av_write(cx, 0x404, 0x32); /* Ancillary data */ |
215 | cx18_av_write(cx, 0x406, 0x13); | 214 | cx18_av_write(cx, 0x406, 0x13); |
216 | cx18_av_write(cx, 0x47f, vbi_offset); | 215 | cx18_av_write(cx, 0x47f, state->slicer_line_delay); |
217 | 216 | ||
218 | /* Force impossible lines to 0 */ | 217 | /* Force impossible lines to 0 */ |
219 | if (is_pal) { | 218 | if (is_pal) { |
@@ -261,7 +260,8 @@ int cx18_av_vbi(struct cx18 *cx, unsigned int cmd, void *arg) | |||
261 | } | 260 | } |
262 | 261 | ||
263 | cx18_av_write(cx, 0x43c, 0x16); | 262 | cx18_av_write(cx, 0x43c, 0x16); |
264 | cx18_av_write(cx, 0x474, is_pal ? 0x2a : 0x22); | 263 | /* FIXME - should match vblank set in cx18_av_std_setup() */ |
264 | cx18_av_write(cx, 0x474, is_pal ? 0x2a : 26); | ||
265 | break; | 265 | break; |
266 | } | 266 | } |
267 | 267 | ||
@@ -286,7 +286,7 @@ int cx18_av_vbi(struct cx18 *cx, unsigned int cmd, void *arg) | |||
286 | did = anc->did; | 286 | did = anc->did; |
287 | sdid = anc->sdid & 0xf; | 287 | sdid = anc->sdid & 0xf; |
288 | l = anc->idid[0] & 0x3f; | 288 | l = anc->idid[0] & 0x3f; |
289 | l += state->vbi_line_offset; | 289 | l += state->slicer_line_offset; |
290 | p = anc->payload; | 290 | p = anc->payload; |
291 | 291 | ||
292 | /* Decode the SDID set by the slicer */ | 292 | /* Decode the SDID set by the slicer */ |
diff --git a/drivers/media/video/cx18/cx18-driver.c b/drivers/media/video/cx18/cx18-driver.c index 3cf8ddb633b4..2a45bbc757e8 100644 --- a/drivers/media/video/cx18/cx18-driver.c +++ b/drivers/media/video/cx18/cx18-driver.c | |||
@@ -633,7 +633,9 @@ static void __devinit cx18_init_struct2(struct cx18 *cx) | |||
633 | cx->av_state.aud_input = CX18_AV_AUDIO8; | 633 | cx->av_state.aud_input = CX18_AV_AUDIO8; |
634 | cx->av_state.audclk_freq = 48000; | 634 | cx->av_state.audclk_freq = 48000; |
635 | cx->av_state.audmode = V4L2_TUNER_MODE_LANG1; | 635 | cx->av_state.audmode = V4L2_TUNER_MODE_LANG1; |
636 | cx->av_state.vbi_line_offset = 8; | 636 | cx->av_state.slicer_line_delay = 0; |
637 | cx->av_state.slicer_line_offset = | ||
638 | (10 + cx->av_state.slicer_line_delay - 2); | ||
637 | } | 639 | } |
638 | 640 | ||
639 | static int cx18_setup_pci(struct cx18 *cx, struct pci_dev *pci_dev, | 641 | static int cx18_setup_pci(struct cx18 *cx, struct pci_dev *pci_dev, |
diff --git a/drivers/media/video/cx18/cx18-streams.c b/drivers/media/video/cx18/cx18-streams.c index a8dcc0f171d1..778aa0c0f9b5 100644 --- a/drivers/media/video/cx18/cx18-streams.c +++ b/drivers/media/video/cx18/cx18-streams.c | |||
@@ -360,9 +360,16 @@ static void cx18_vbi_setup(struct cx18_stream *s) | |||
360 | if (raw) { | 360 | if (raw) { |
361 | lines = cx->vbi.count * 2; | 361 | lines = cx->vbi.count * 2; |
362 | } else { | 362 | } else { |
363 | lines = cx->is_60hz ? 24 : 38; | 363 | /* |
364 | if (cx->is_60hz) | 364 | * For 525/60 systems, according to the VIP 2 & BT.656 std: |
365 | lines += 2; | 365 | * The EAV RP code's Field bit toggles on line 4, a few lines |
366 | * after the Vertcal Blank bit has already toggled. | ||
367 | * Tell the encoder to capture 21-4+1=18 lines per field, | ||
368 | * since we want lines 10 through 21. | ||
369 | * | ||
370 | * FIXME - revisit for 625/50 systems | ||
371 | */ | ||
372 | lines = cx->is_60hz ? (21 - 4 + 1) * 2 : 38; | ||
366 | } | 373 | } |
367 | 374 | ||
368 | data[0] = s->handle; | 375 | data[0] = s->handle; |
@@ -402,9 +409,13 @@ static void cx18_vbi_setup(struct cx18_stream *s) | |||
402 | * | 409 | * |
403 | * Since the V bit is only allowed to toggle in the EAV RP code, | 410 | * Since the V bit is only allowed to toggle in the EAV RP code, |
404 | * just before the first active region line, these two | 411 | * just before the first active region line, these two |
405 | * are problematic and we have to ignore them: | 412 | * are problematic: |
406 | * 0x90 (Task HorizontalBlank) | 413 | * 0x90 (Task HorizontalBlank) |
407 | * 0xd0 (Task EvenField HorizontalBlank) | 414 | * 0xd0 (Task EvenField HorizontalBlank) |
415 | * | ||
416 | * We have set the digitzer to consider the first active line | ||
417 | * as part of VerticalBlank as well so we don't have to look for | ||
418 | * these problem codes nor lose the last line of sliced data. | ||
408 | */ | 419 | */ |
409 | data[4] = 0xB0F0B0F0; | 420 | data[4] = 0xB0F0B0F0; |
410 | /* | 421 | /* |
diff --git a/drivers/media/video/cx18/cx18-vbi.c b/drivers/media/video/cx18/cx18-vbi.c index 52082d4a179e..8e6f4d4aff9a 100644 --- a/drivers/media/video/cx18/cx18-vbi.c +++ b/drivers/media/video/cx18/cx18-vbi.c | |||
@@ -221,13 +221,22 @@ void cx18_process_vbi_data(struct cx18 *cx, struct cx18_buffer *buf, | |||
221 | 221 | ||
222 | pts = (be32_to_cpu(q[0] == 0x3fffffff)) ? be32_to_cpu(q[2]) : 0; | 222 | pts = (be32_to_cpu(q[0] == 0x3fffffff)) ? be32_to_cpu(q[2]) : 0; |
223 | 223 | ||
224 | /* | ||
225 | * For calls to compress_sliced_buf(), ensure there are an integral | ||
226 | * number of lines by shifting the real data up over the 12 bytes header | ||
227 | * that got stuffed in. | ||
228 | * FIXME - there's a smarter way to do this with pointers, but for some | ||
229 | * reason I can't get it to work correctly right now. | ||
230 | */ | ||
231 | memcpy(p, &buf->buf[12], size-12); | ||
232 | |||
224 | /* first field */ | 233 | /* first field */ |
225 | /* compress_sliced_buf() will skip the 12 bytes of header */ | ||
226 | lines = compress_sliced_buf(cx, 0, p, size / 2, sliced_vbi_eav_rp[0]); | 234 | lines = compress_sliced_buf(cx, 0, p, size / 2, sliced_vbi_eav_rp[0]); |
227 | /* second field */ | 235 | /* |
228 | /* experimentation shows that the second half does not always | 236 | * second field |
229 | begin at the exact address. So start a bit earlier | 237 | * In case the second half does not always begin at the exact address, |
230 | (hence 32). */ | 238 | * start a bit earlier (hence 32). |
239 | */ | ||
231 | lines = compress_sliced_buf(cx, lines, p + size / 2 - 32, | 240 | lines = compress_sliced_buf(cx, lines, p + size / 2 - 32, |
232 | size / 2 + 32, sliced_vbi_eav_rp[1]); | 241 | size / 2 + 32, sliced_vbi_eav_rp[1]); |
233 | /* always return at least one empty line */ | 242 | /* always return at least one empty line */ |