diff options
author | Mike Isely <isely@pobox.com> | 2006-06-25 19:05:01 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@infradead.org> | 2006-06-26 23:17:32 -0400 |
commit | b30d244176846de3480ae17097a5f7831ec6aaf6 (patch) | |
tree | fba5650757a84032802b87635b7fe41d77c8e3cd /drivers/media/video/pvrusb2/pvrusb2-encoder.c | |
parent | 1d9f8461f1a870571f9403a312c26deec3305be5 (diff) |
V4L/DVB (4244): Implement use of cx2341x module in pvrusb2 driver
Signed-off-by: Mike Isely <isely@pobox.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Diffstat (limited to 'drivers/media/video/pvrusb2/pvrusb2-encoder.c')
-rw-r--r-- | drivers/media/video/pvrusb2/pvrusb2-encoder.c | 228 |
1 files changed, 48 insertions, 180 deletions
diff --git a/drivers/media/video/pvrusb2/pvrusb2-encoder.c b/drivers/media/video/pvrusb2/pvrusb2-encoder.c index 47c8e0203ce7..d944081072e6 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-encoder.c +++ b/drivers/media/video/pvrusb2/pvrusb2-encoder.c | |||
@@ -27,34 +27,6 @@ | |||
27 | #include "pvrusb2-hdw-internal.h" | 27 | #include "pvrusb2-hdw-internal.h" |
28 | #include "pvrusb2-debug.h" | 28 | #include "pvrusb2-debug.h" |
29 | 29 | ||
30 | static u32 pvr_tbl_emphasis [] = { | ||
31 | [PVR2_CVAL_AUDIOEMPHASIS_NONE] = 0x0 << 12, | ||
32 | [PVR2_CVAL_AUDIOEMPHASIS_50_15] = 0x1 << 12, | ||
33 | [PVR2_CVAL_AUDIOEMPHASIS_CCITT] = 0x3 << 12, | ||
34 | }; | ||
35 | |||
36 | static u32 pvr_tbl_srate[] = { | ||
37 | [PVR2_CVAL_SRATE_48] = 0x01, | ||
38 | [PVR2_CVAL_SRATE_44_1] = 0x00, | ||
39 | }; | ||
40 | |||
41 | static u32 pvr_tbl_audiobitrate[] = { | ||
42 | [PVR2_CVAL_AUDIOBITRATE_384] = 0xe << 4, | ||
43 | [PVR2_CVAL_AUDIOBITRATE_320] = 0xd << 4, | ||
44 | [PVR2_CVAL_AUDIOBITRATE_256] = 0xc << 4, | ||
45 | [PVR2_CVAL_AUDIOBITRATE_224] = 0xb << 4, | ||
46 | [PVR2_CVAL_AUDIOBITRATE_192] = 0xa << 4, | ||
47 | [PVR2_CVAL_AUDIOBITRATE_160] = 0x9 << 4, | ||
48 | [PVR2_CVAL_AUDIOBITRATE_128] = 0x8 << 4, | ||
49 | [PVR2_CVAL_AUDIOBITRATE_112] = 0x7 << 4, | ||
50 | [PVR2_CVAL_AUDIOBITRATE_96] = 0x6 << 4, | ||
51 | [PVR2_CVAL_AUDIOBITRATE_80] = 0x5 << 4, | ||
52 | [PVR2_CVAL_AUDIOBITRATE_64] = 0x4 << 4, | ||
53 | [PVR2_CVAL_AUDIOBITRATE_56] = 0x3 << 4, | ||
54 | [PVR2_CVAL_AUDIOBITRATE_48] = 0x2 << 4, | ||
55 | [PVR2_CVAL_AUDIOBITRATE_32] = 0x1 << 4, | ||
56 | [PVR2_CVAL_AUDIOBITRATE_VBR] = 0x0 << 4, | ||
57 | }; | ||
58 | 30 | ||
59 | 31 | ||
60 | /* Firmware mailbox flags - definitions found from ivtv */ | 32 | /* Firmware mailbox flags - definitions found from ivtv */ |
@@ -316,171 +288,67 @@ static int pvr2_encoder_vcmd(struct pvr2_hdw *hdw, int cmd, | |||
316 | return pvr2_encoder_cmd(hdw,cmd,args,0,data); | 288 | return pvr2_encoder_cmd(hdw,cmd,args,0,data); |
317 | } | 289 | } |
318 | 290 | ||
319 | |||
320 | int pvr2_encoder_configure(struct pvr2_hdw *hdw) | 291 | int pvr2_encoder_configure(struct pvr2_hdw *hdw) |
321 | { | 292 | { |
322 | int ret = 0, audio, i; | 293 | int ret; |
323 | v4l2_std_id vd_std = hdw->std_mask_cur; | 294 | pvr2_trace(PVR2_TRACE_ENCODER,"pvr2_encoder_configure" |
324 | int height = hdw->res_ver_val; | 295 | " (cx2341x module)"); |
325 | int width = hdw->res_hor_val; | 296 | hdw->enc_ctl_state.port = CX2341X_PORT_STREAMING; |
326 | int height_full = !hdw->interlace_val; | 297 | hdw->enc_ctl_state.width = hdw->res_hor_val; |
327 | 298 | hdw->enc_ctl_state.height = hdw->res_ver_val; | |
328 | int is_30fps, is_ntsc; | 299 | hdw->enc_ctl_state.is_50hz = ((hdw->std_mask_cur & |
329 | 300 | (V4L2_STD_NTSC|V4L2_STD_PAL_M)) ? | |
330 | if (vd_std & V4L2_STD_NTSC) { | 301 | 0 : 1); |
331 | is_ntsc=1; | ||
332 | is_30fps=1; | ||
333 | } else if (vd_std & V4L2_STD_PAL_M) { | ||
334 | is_ntsc=0; | ||
335 | is_30fps=1; | ||
336 | } else { | ||
337 | is_ntsc=0; | ||
338 | is_30fps=0; | ||
339 | } | ||
340 | 302 | ||
341 | pvr2_trace(PVR2_TRACE_ENCODER,"pvr2_encoder_configure (native)"); | 303 | ret = 0; |
342 | 304 | ||
343 | /* set stream output port. Some notes here: The ivtv-derived | 305 | if (!ret) ret = pvr2_encoder_vcmd( |
344 | encoder documentation says that this command only gets a | 306 | hdw,CX2341X_ENC_SET_NUM_VSYNC_LINES, 2, |
345 | single argument. However the Windows driver for the model | 307 | 0xf0, 0xf0); |
346 | 29xxx series hardware has been sending 0x01 as a second | ||
347 | argument, while the Windows driver for the model 24xxx | ||
348 | series hardware has been sending 0x02 as a second argument. | ||
349 | Confusing matters further are the observations that 0x01 | ||
350 | for that second argument simply won't work on the 24xxx | ||
351 | hardware, while 0x02 will work on the 29xxx - except that | ||
352 | when we use 0x02 then xawtv breaks due to a loss of | ||
353 | synchronization with the mpeg packet headers. While xawtv | ||
354 | should be fixed to let it resync better (I did try to | ||
355 | contact Gerd about this but he has not answered), it has | ||
356 | also been determined that sending 0x00 as this mystery | ||
357 | second argument seems to work on both hardware models AND | ||
358 | xawtv works again. So we're going to send 0x00. */ | ||
359 | ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_SET_OUTPUT_PORT, 2, | ||
360 | 0x01, 0x00); | ||
361 | |||
362 | /* set the Program Index Information. We want I,P,B frames (max 400) */ | ||
363 | ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_SET_PGM_INDEX_INFO, 2, | ||
364 | 0x07, 0x0190); | ||
365 | |||
366 | /* NOTE : windows driver sends these */ | ||
367 | /* Mike Isely <isely@pobox.com> 7-Mar-2006 The windows driver | ||
368 | sends the following commands but if we do the same then | ||
369 | many apps are no longer able to read the video stream. | ||
370 | Leaving these out seems to do no harm at all, so they're | ||
371 | commented out for that reason. */ | ||
372 | #ifdef notdef | ||
373 | ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_MISC,4, 5,0,0,0); | ||
374 | ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_MISC,4, 3,1,0,0); | ||
375 | ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_MISC,4, 8,0,0,0); | ||
376 | ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_MISC,4, 4,1,0,0); | ||
377 | ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_MISC,4, 0,3,0,0); | ||
378 | ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_MISC,4,15,0,0,0); | ||
379 | #endif | ||
380 | |||
381 | /* Strange compared to ivtv data. */ | ||
382 | ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_SET_NUM_VSYNC_LINES, 2, | ||
383 | 0xf0, 0xf0); | ||
384 | 308 | ||
385 | /* setup firmware to notify us about some events (don't know why...) */ | 309 | /* setup firmware to notify us about some events (don't know why...) */ |
386 | ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_SET_EVENT_NOTIFICATION, 4, | 310 | if (!ret) ret = pvr2_encoder_vcmd( |
387 | 0, 0, 0x10000000, 0xffffffff); | 311 | hdw,CX2341X_ENC_SET_EVENT_NOTIFICATION, 4, |
312 | 0, 0, 0x10000000, 0xffffffff); | ||
313 | |||
314 | if (!ret) ret = pvr2_encoder_vcmd( | ||
315 | hdw,CX2341X_ENC_SET_VBI_LINE, 5, | ||
316 | 0xffffffff,0,0,0,0); | ||
317 | |||
318 | if (ret) { | ||
319 | pvr2_trace(PVR2_TRACE_ERROR_LEGS, | ||
320 | "Failed to configure cx32416"); | ||
321 | return ret; | ||
322 | } | ||
388 | 323 | ||
389 | /* set fps to 25 or 30 (1 or 0)*/ | 324 | ret = cx2341x_update(hdw,pvr2_encoder_cmd, |
390 | ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_SET_FRAME_RATE, 1, | 325 | (hdw->enc_cur_valid ? &hdw->enc_cur_state : 0), |
391 | is_30fps ? 0 : 1); | 326 | &hdw->enc_ctl_state); |
327 | if (ret) { | ||
328 | pvr2_trace(PVR2_TRACE_ERROR_LEGS, | ||
329 | "Error from cx2341x module code=%d",ret); | ||
330 | return ret; | ||
331 | } | ||
392 | 332 | ||
393 | /* set encoding resolution */ | 333 | ret = 0; |
394 | ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_SET_FRAME_SIZE, 2, | ||
395 | (height_full ? height : (height / 2)), | ||
396 | width); | ||
397 | /* set encoding aspect ratio to 4:3 */ | ||
398 | ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_SET_ASPECT_RATIO, 1, | ||
399 | 0x02); | ||
400 | 334 | ||
401 | /* VBI */ | 335 | if (!ret) ret = pvr2_encoder_vcmd( |
336 | hdw, CX2341X_ENC_INITIALIZE_INPUT, 0); | ||
402 | 337 | ||
403 | if (hdw->config == pvr2_config_vbi) { | 338 | if (ret) { |
404 | int lines = 2 * (is_30fps ? 12 : 18); | 339 | pvr2_trace(PVR2_TRACE_ERROR_LEGS, |
405 | int size = (4*((lines*1443+3)/4)) / lines; | 340 | "Failed to initialize cx32416 video input"); |
406 | ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_SET_VBI_CONFIG, 7, | 341 | return ret; |
407 | 0xbd05, 1, 4, | ||
408 | 0x25256262, 0x387f7f7f, | ||
409 | lines , size); | ||
410 | // 0x25256262, 0x13135454, lines , size); | ||
411 | /* select vbi lines */ | ||
412 | #define line_used(l) (is_30fps ? (l >= 10 && l <= 21) : (l >= 6 && l <= 23)) | ||
413 | for (i = 2 ; i <= 24 ; i++){ | ||
414 | ret |= pvr2_encoder_vcmd( | ||
415 | hdw,CX2341X_ENC_SET_VBI_LINE, 5, | ||
416 | i-1,line_used(i), 0, 0, 0); | ||
417 | ret |= pvr2_encoder_vcmd( | ||
418 | hdw,CX2341X_ENC_SET_VBI_LINE, 5, | ||
419 | (i-1) | (1 << 31), | ||
420 | line_used(i), 0, 0, 0); | ||
421 | } | ||
422 | } else { | ||
423 | ret |= pvr2_encoder_vcmd( | ||
424 | hdw,CX2341X_ENC_SET_VBI_LINE, 5, | ||
425 | 0xffffffff,0,0,0,0); | ||
426 | } | ||
427 | |||
428 | /* set stream type, depending on resolution. */ | ||
429 | ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_SET_STREAM_TYPE, 1, | ||
430 | height_full ? 0x0a : 0x0b); | ||
431 | /* set video bitrate */ | ||
432 | ret |= pvr2_encoder_vcmd( | ||
433 | hdw, CX2341X_ENC_SET_BIT_RATE, 3, | ||
434 | (hdw->vbr_val ? 1 : 0), | ||
435 | hdw->videobitrate_val, | ||
436 | hdw->videopeak_val / 400); | ||
437 | /* setup GOP structure (GOP size = 0f or 0c, 3-1 = 2 B-frames) */ | ||
438 | ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_SET_GOP_PROPERTIES, 2, | ||
439 | is_30fps ? 0x0f : 0x0c, 0x03); | ||
440 | |||
441 | /* enable 3:2 pulldown */ | ||
442 | ret |= pvr2_encoder_vcmd(hdw,CX2341X_ENC_SET_3_2_PULLDOWN,1,0); | ||
443 | |||
444 | /* set GOP open/close property (open) */ | ||
445 | ret |= pvr2_encoder_vcmd(hdw,CX2341X_ENC_SET_GOP_CLOSURE,1,0); | ||
446 | |||
447 | /* set audio stream properties 0x40b9? 0100 0000 1011 1001 */ | ||
448 | audio = (pvr_tbl_audiobitrate[hdw->audiobitrate_val] | | ||
449 | pvr_tbl_srate[hdw->srate_val] | | ||
450 | hdw->audiolayer_val << 2 | | ||
451 | (hdw->audiocrc_val ? 1 << 14 : 0) | | ||
452 | pvr_tbl_emphasis[hdw->audioemphasis_val]); | ||
453 | |||
454 | ret |= pvr2_encoder_vcmd(hdw,CX2341X_ENC_SET_AUDIO_PROPERTIES,1, | ||
455 | audio); | ||
456 | |||
457 | /* set dynamic noise reduction filter to manual, Horiz/Vert */ | ||
458 | ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_SET_DNR_FILTER_MODE, 2, | ||
459 | 0, 0x03); | ||
460 | |||
461 | /* dynamic noise reduction filter param */ | ||
462 | ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_SET_DNR_FILTER_PROPS, 2 | ||
463 | , 0, 0); | ||
464 | |||
465 | /* dynamic noise reduction median filter */ | ||
466 | ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_SET_CORING_LEVELS, 4, | ||
467 | 0, 0xff, 0, 0xff); | ||
468 | |||
469 | /* spacial prefiler parameter */ | ||
470 | ret |= pvr2_encoder_vcmd(hdw, | ||
471 | CX2341X_ENC_SET_SPATIAL_FILTER_TYPE, 2, | ||
472 | 0x01, 0x01); | ||
473 | |||
474 | /* initialize video input */ | ||
475 | ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_INITIALIZE_INPUT, 0); | ||
476 | |||
477 | if (!ret) { | ||
478 | hdw->subsys_enabled_mask |= (1<<PVR2_SUBSYS_B_ENC_CFG); | ||
479 | } | 342 | } |
480 | 343 | ||
481 | return ret; | 344 | hdw->subsys_enabled_mask |= (1<<PVR2_SUBSYS_B_ENC_CFG); |
345 | memcpy(&hdw->enc_cur_state,&hdw->enc_ctl_state, | ||
346 | sizeof(struct cx2341x_mpeg_params)); | ||
347 | hdw->enc_cur_valid = !0; | ||
348 | return 0; | ||
482 | } | 349 | } |
483 | 350 | ||
351 | |||
484 | int pvr2_encoder_start(struct pvr2_hdw *hdw) | 352 | int pvr2_encoder_start(struct pvr2_hdw *hdw) |
485 | { | 353 | { |
486 | int status; | 354 | int status; |