aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video
diff options
context:
space:
mode:
authorAndy Walls <awalls@radix.net>2009-02-08 20:40:04 -0500
committerMauro Carvalho Chehab <mchehab@redhat.com>2009-03-30 11:42:39 -0400
commit812b1f9d54a5f75066f8a5c92166a979c48c98c6 (patch)
treed04cdfdd80d0e2df825dbd22a6130434867233f0 /drivers/media/video
parent466df46484aced005fa41706f87e18eaa86918ad (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.c44
-rw-r--r--drivers/media/video/cx18/cx18-av-core.h19
-rw-r--r--drivers/media/video/cx18/cx18-av-vbi.c10
-rw-r--r--drivers/media/video/cx18/cx18-driver.c4
-rw-r--r--drivers/media/video/cx18/cx18-streams.c19
-rw-r--r--drivers/media/video/cx18/cx18-vbi.c19
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
639static int cx18_setup_pci(struct cx18 *cx, struct pci_dev *pci_dev, 641static 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 */