diff options
author | Mike Isely <isely@pobox.com> | 2007-11-25 23:48:52 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@infradead.org> | 2008-01-25 16:03:01 -0500 |
commit | 681c739944018d80dbcf7f19997eba97676c7116 (patch) | |
tree | 4c2f3ab63bfd852fba0ec87f69fe76e52fa4aa48 /drivers/media/video/pvrusb2/pvrusb2-encoder.c | |
parent | 493977f016f2ff52fdca38d031c7211b4da658fd (diff) |
V4L/DVB (6691): pvrusb2: Rework pipeline state control
This is a new implementation for video pipeline control within the
pvrusb2 driver. Actual start/stop of the pipeline is moved to the
driver's kernel thread. Pipeline stages are controlled autonomously
based on surrounding pipeline or application control state. Kernel
thread management is also cleaned up and moved into the internal
control structure of the driver, solving a set up / tear down race
along the way. Better failure recovery is implemented with this new
control strategy. Also with this change comes better control of the
cx23416 encoder, building on additional information learned about the
peculiarities of controlling this part (this information was the
original trigger for this rework). With this change, overall encoder
stability should be considerably improved. Yes, this is a large
change for this driver, but due to the nature of the feature being
worked on, the changes are fairly pervasive and would be difficult to
break into smaller pieces with any semblence of step-wise stability.
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 | 54 |
1 files changed, 29 insertions, 25 deletions
diff --git a/drivers/media/video/pvrusb2/pvrusb2-encoder.c b/drivers/media/video/pvrusb2/pvrusb2-encoder.c index 205087a3e136..5ca548cc7e7f 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-encoder.c +++ b/drivers/media/video/pvrusb2/pvrusb2-encoder.c | |||
@@ -209,7 +209,7 @@ static int pvr2_encoder_cmd(void *ctxt, | |||
209 | 209 | ||
210 | LOCK_TAKE(hdw->ctl_lock); do { | 210 | LOCK_TAKE(hdw->ctl_lock); do { |
211 | 211 | ||
212 | if (!hdw->flag_encoder_ok) { | 212 | if (!hdw->state_encoder_ok) { |
213 | ret = -EIO; | 213 | ret = -EIO; |
214 | break; | 214 | break; |
215 | } | 215 | } |
@@ -278,7 +278,11 @@ static int pvr2_encoder_cmd(void *ctxt, | |||
278 | ret = -EBUSY; | 278 | ret = -EBUSY; |
279 | } | 279 | } |
280 | if (ret) { | 280 | if (ret) { |
281 | hdw->flag_encoder_ok = 0; | 281 | hdw->state_encoder_ok = 0; |
282 | pvr2_trace(PVR2_TRACE_STBITS, | ||
283 | "State bit %s <-- %s", | ||
284 | "state_encoder_ok", | ||
285 | (hdw->state_encoder_ok ? "true" : "false")); | ||
282 | pvr2_trace( | 286 | pvr2_trace( |
283 | PVR2_TRACE_ERROR_LEGS, | 287 | PVR2_TRACE_ERROR_LEGS, |
284 | "Giving up on command." | 288 | "Giving up on command." |
@@ -394,6 +398,24 @@ static int pvr2_encoder_prep_config(struct pvr2_hdw *hdw) | |||
394 | return ret; | 398 | return ret; |
395 | } | 399 | } |
396 | 400 | ||
401 | int pvr2_encoder_adjust(struct pvr2_hdw *hdw) | ||
402 | { | ||
403 | int ret; | ||
404 | ret = cx2341x_update(hdw,pvr2_encoder_cmd, | ||
405 | (hdw->enc_cur_valid ? &hdw->enc_cur_state : NULL), | ||
406 | &hdw->enc_ctl_state); | ||
407 | if (ret) { | ||
408 | pvr2_trace(PVR2_TRACE_ERROR_LEGS, | ||
409 | "Error from cx2341x module code=%d",ret); | ||
410 | } else { | ||
411 | memcpy(&hdw->enc_cur_state,&hdw->enc_ctl_state, | ||
412 | sizeof(struct cx2341x_mpeg_params)); | ||
413 | hdw->enc_cur_valid = !0; | ||
414 | } | ||
415 | return ret; | ||
416 | } | ||
417 | |||
418 | |||
397 | int pvr2_encoder_configure(struct pvr2_hdw *hdw) | 419 | int pvr2_encoder_configure(struct pvr2_hdw *hdw) |
398 | { | 420 | { |
399 | int ret; | 421 | int ret; |
@@ -436,18 +458,10 @@ int pvr2_encoder_configure(struct pvr2_hdw *hdw) | |||
436 | return ret; | 458 | return ret; |
437 | } | 459 | } |
438 | 460 | ||
439 | ret = cx2341x_update(hdw,pvr2_encoder_cmd, | 461 | ret = pvr2_encoder_adjust(hdw); |
440 | (hdw->enc_cur_valid ? &hdw->enc_cur_state : NULL), | 462 | if (ret) return ret; |
441 | &hdw->enc_ctl_state); | ||
442 | if (ret) { | ||
443 | pvr2_trace(PVR2_TRACE_ERROR_LEGS, | ||
444 | "Error from cx2341x module code=%d",ret); | ||
445 | return ret; | ||
446 | } | ||
447 | |||
448 | ret = 0; | ||
449 | 463 | ||
450 | if (!ret) ret = pvr2_encoder_vcmd( | 464 | ret = pvr2_encoder_vcmd( |
451 | hdw, CX2341X_ENC_INITIALIZE_INPUT, 0); | 465 | hdw, CX2341X_ENC_INITIALIZE_INPUT, 0); |
452 | 466 | ||
453 | if (ret) { | 467 | if (ret) { |
@@ -456,10 +470,6 @@ int pvr2_encoder_configure(struct pvr2_hdw *hdw) | |||
456 | return ret; | 470 | return ret; |
457 | } | 471 | } |
458 | 472 | ||
459 | hdw->subsys_enabled_mask |= (1<<PVR2_SUBSYS_B_ENC_CFG); | ||
460 | memcpy(&hdw->enc_cur_state,&hdw->enc_ctl_state, | ||
461 | sizeof(struct cx2341x_mpeg_params)); | ||
462 | hdw->enc_cur_valid = !0; | ||
463 | return 0; | 473 | return 0; |
464 | } | 474 | } |
465 | 475 | ||
@@ -478,7 +488,7 @@ int pvr2_encoder_start(struct pvr2_hdw *hdw) | |||
478 | pvr2_encoder_vcmd(hdw,CX2341X_ENC_MUTE_VIDEO,1, | 488 | pvr2_encoder_vcmd(hdw,CX2341X_ENC_MUTE_VIDEO,1, |
479 | hdw->input_val == PVR2_CVAL_INPUT_RADIO ? 1 : 0); | 489 | hdw->input_val == PVR2_CVAL_INPUT_RADIO ? 1 : 0); |
480 | 490 | ||
481 | switch (hdw->config) { | 491 | switch (hdw->active_stream_type) { |
482 | case pvr2_config_vbi: | 492 | case pvr2_config_vbi: |
483 | status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_START_CAPTURE,2, | 493 | status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_START_CAPTURE,2, |
484 | 0x01,0x14); | 494 | 0x01,0x14); |
@@ -492,9 +502,6 @@ int pvr2_encoder_start(struct pvr2_hdw *hdw) | |||
492 | 0,0x13); | 502 | 0,0x13); |
493 | break; | 503 | break; |
494 | } | 504 | } |
495 | if (!status) { | ||
496 | hdw->subsys_enabled_mask |= (1<<PVR2_SUBSYS_B_ENC_RUN); | ||
497 | } | ||
498 | return status; | 505 | return status; |
499 | } | 506 | } |
500 | 507 | ||
@@ -505,7 +512,7 @@ int pvr2_encoder_stop(struct pvr2_hdw *hdw) | |||
505 | /* mask all interrupts */ | 512 | /* mask all interrupts */ |
506 | pvr2_write_register(hdw, 0x0048, 0xffffffff); | 513 | pvr2_write_register(hdw, 0x0048, 0xffffffff); |
507 | 514 | ||
508 | switch (hdw->config) { | 515 | switch (hdw->active_stream_type) { |
509 | case pvr2_config_vbi: | 516 | case pvr2_config_vbi: |
510 | status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_STOP_CAPTURE,3, | 517 | status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_STOP_CAPTURE,3, |
511 | 0x01,0x01,0x14); | 518 | 0x01,0x01,0x14); |
@@ -526,9 +533,6 @@ int pvr2_encoder_stop(struct pvr2_hdw *hdw) | |||
526 | pvr2_hdw_gpio_chg_dir(hdw,0xffffffff,0x00000401); | 533 | pvr2_hdw_gpio_chg_dir(hdw,0xffffffff,0x00000401); |
527 | pvr2_hdw_gpio_chg_out(hdw,0xffffffff,0x00000000); | 534 | pvr2_hdw_gpio_chg_out(hdw,0xffffffff,0x00000000); |
528 | 535 | ||
529 | if (!status) { | ||
530 | hdw->subsys_enabled_mask &= ~(1<<PVR2_SUBSYS_B_ENC_RUN); | ||
531 | } | ||
532 | return status; | 536 | return status; |
533 | } | 537 | } |
534 | 538 | ||