aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/pvrusb2/pvrusb2-encoder.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/pvrusb2/pvrusb2-encoder.c')
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-encoder.c228
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
30static 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
36static u32 pvr_tbl_srate[] = {
37 [PVR2_CVAL_SRATE_48] = 0x01,
38 [PVR2_CVAL_SRATE_44_1] = 0x00,
39};
40
41static 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
320int pvr2_encoder_configure(struct pvr2_hdw *hdw) 291int 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
484int pvr2_encoder_start(struct pvr2_hdw *hdw) 352int pvr2_encoder_start(struct pvr2_hdw *hdw)
485{ 353{
486 int status; 354 int status;