Skip to content

Commit

Permalink
V4L/DVB (7710): pvrusb2: Implement critical digital streaming quirk f…
Browse files Browse the repository at this point in the history
…or onair devices

Implement timed measurement of encoder operation for the first time it
is run.  This allows the driver to note when the encoder has been run
successfully for at least 1/4 second.  On top of that implement
various bits to ensure that the encoder has been run once before
digital streaming for OnAir devices.  This is done via several core
state machine tweaks.

Signed-off-by: Mike Isely <isely@pobox.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
  • Loading branch information
Mike Isely authored and Mauro Carvalho Chehab committed Apr 24, 2008
1 parent 72998b7 commit d913d63
Show file tree
Hide file tree
Showing 3 changed files with 156 additions and 7 deletions.
9 changes: 9 additions & 0 deletions drivers/media/video/pvrusb2/pvrusb2-encoder.c
Original file line number Diff line number Diff line change
Expand Up @@ -278,11 +278,20 @@ static int pvr2_encoder_cmd(void *ctxt,
ret = -EBUSY;
}
if (ret) {
del_timer_sync(&hdw->encoder_run_timer);
hdw->state_encoder_ok = 0;
pvr2_trace(PVR2_TRACE_STBITS,
"State bit %s <-- %s",
"state_encoder_ok",
(hdw->state_encoder_ok ? "true" : "false"));
if (hdw->state_encoder_runok) {
hdw->state_encoder_runok = 0;
pvr2_trace(PVR2_TRACE_STBITS,
"State bit %s <-- %s",
"state_encoder_runok",
(hdw->state_encoder_runok ?
"true" : "false"));
}
pvr2_trace(
PVR2_TRACE_ERROR_LEGS,
"Giving up on command."
Expand Down
4 changes: 4 additions & 0 deletions drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,7 @@ struct pvr2_hdw {
int state_encoder_run; /* Encoder is running */
int state_encoder_config; /* Encoder is configured */
int state_encoder_waitok; /* Encoder pre-wait done */
int state_encoder_runok; /* Encoder has run for >= .25 sec */
int state_decoder_run; /* Decoder is running */
int state_usbstream_run; /* FX2 is streaming */
int state_decoder_quiescent; /* Decoder idle for > 50msec */
Expand Down Expand Up @@ -267,6 +268,9 @@ struct pvr2_hdw {
/* Timer for measuring encoder pre-wait time */
struct timer_list encoder_wait_timer;

/* Timer for measuring encoder minimum run time */
struct timer_list encoder_run_timer;

/* Place to block while waiting for state changes */
wait_queue_head_t state_wait_data;

Expand Down
150 changes: 143 additions & 7 deletions drivers/media/video/pvrusb2/pvrusb2-hdw.c
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,7 @@ static void pvr2_hdw_internal_find_stdenum(struct pvr2_hdw *hdw);
static void pvr2_hdw_internal_set_std_avail(struct pvr2_hdw *hdw);
static void pvr2_hdw_quiescent_timeout(unsigned long);
static void pvr2_hdw_encoder_wait_timeout(unsigned long);
static void pvr2_hdw_encoder_run_timeout(unsigned long);
static int pvr2_issue_simple_cmd(struct pvr2_hdw *,u32);
static int pvr2_send_request_ex(struct pvr2_hdw *hdw,
unsigned int timeout,int probe_fl,
Expand Down Expand Up @@ -1236,6 +1237,14 @@ int pvr2_upload_firmware2(struct pvr2_hdw *hdw)
time we configure the encoder, then we'll fully configure it. */
hdw->enc_cur_valid = 0;

/* Encoder is about to be reset so note that as far as we're
concerned now, the encoder has never been run. */
del_timer_sync(&hdw->encoder_run_timer);
if (hdw->state_encoder_runok) {
hdw->state_encoder_runok = 0;
trace_stbit("state_encoder_runok",hdw->state_encoder_runok);
}

/* First prepare firmware loading */
ret |= pvr2_write_register(hdw, 0x0048, 0xffffffff); /*interrupt mask*/
ret |= pvr2_hdw_gpio_chg_dir(hdw,0xffffffff,0x00000088); /*gpio dir*/
Expand Down Expand Up @@ -1882,6 +1891,10 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf,
hdw->encoder_wait_timer.data = (unsigned long)hdw;
hdw->encoder_wait_timer.function = pvr2_hdw_encoder_wait_timeout;

init_timer(&hdw->encoder_run_timer);
hdw->encoder_run_timer.data = (unsigned long)hdw;
hdw->encoder_run_timer.function = pvr2_hdw_encoder_run_timeout;

hdw->master_state = PVR2_STATE_DEAD;

init_waitqueue_head(&hdw->state_wait_data);
Expand Down Expand Up @@ -2082,6 +2095,7 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf,
fail:
if (hdw) {
del_timer_sync(&hdw->quiescent_timer);
del_timer_sync(&hdw->encoder_run_timer);
del_timer_sync(&hdw->encoder_wait_timer);
if (hdw->workqueue) {
flush_workqueue(hdw->workqueue);
Expand Down Expand Up @@ -2144,6 +2158,7 @@ void pvr2_hdw_destroy(struct pvr2_hdw *hdw)
hdw->workqueue = NULL;
}
del_timer_sync(&hdw->quiescent_timer);
del_timer_sync(&hdw->encoder_run_timer);
del_timer_sync(&hdw->encoder_wait_timer);
if (hdw->fw_buffer) {
kfree(hdw->fw_buffer);
Expand Down Expand Up @@ -3584,23 +3599,116 @@ static int state_eval_encoder_config(struct pvr2_hdw *hdw)
}


/* Return true if the encoder should not be running. */
static int state_check_disable_encoder_run(struct pvr2_hdw *hdw)
{
if (!hdw->state_encoder_ok) {
/* Encoder isn't healthy at the moment, so stop it. */
return !0;
}
if (!hdw->state_pathway_ok) {
/* Mode is not understood at the moment (i.e. it wants to
change), so encoder must be stopped. */
return !0;
}

switch (hdw->pathway_state) {
case PVR2_PATHWAY_ANALOG:
if (!hdw->state_decoder_run) {
/* We're in analog mode and the decoder is not
running; thus the encoder should be stopped as
well. */
return !0;
}
break;
case PVR2_PATHWAY_DIGITAL:
if (hdw->state_encoder_runok) {
/* This is a funny case. We're in digital mode so
really the encoder should be stopped. However
if it really is running, only kill it after
runok has been set. This gives a chance for the
onair quirk to function (encoder must run
briefly first, at least once, before onair
digital streaming can work). */
return !0;
}
break;
default:
/* Unknown mode; so encoder should be stopped. */
return !0;
}

/* If we get here, we haven't found a reason to stop the
encoder. */
return 0;
}


/* Return true if the encoder should be running. */
static int state_check_enable_encoder_run(struct pvr2_hdw *hdw)
{
if (!hdw->state_encoder_ok) {
/* Don't run the encoder if it isn't healthy... */
return 0;
}
if (!hdw->state_pathway_ok) {
/* Don't run the encoder if we don't (yet) know what mode
we need to be in... */
return 0;
}

switch (hdw->pathway_state) {
case PVR2_PATHWAY_ANALOG:
if (hdw->state_decoder_run) {
/* In analog mode, if the decoder is running, then
run the encoder. */
return !0;
}
break;
case PVR2_PATHWAY_DIGITAL:
if ((hdw->hdw_desc->digital_control_scheme ==
PVR2_DIGITAL_SCHEME_ONAIR) &&
!hdw->state_encoder_runok) {
/* This is a quirk. OnAir hardware won't stream
digital until the encoder has been run at least
once, for a minimal period of time (empiricially
measured to be 1/4 second). So if we're on
OnAir hardware and the encoder has never been
run at all, then start the encoder. Normal
state machine logic in the driver will
automatically handle the remaining bits. */
return !0;
}
break;
default:
/* For completeness (unknown mode; encoder won't run ever) */
break;
}
/* If we get here, then we haven't found any reason to run the
encoder, so don't run it. */
return 0;
}


/* Evaluate whether or not state_encoder_run can change */
static int state_eval_encoder_run(struct pvr2_hdw *hdw)
{
if (hdw->state_encoder_run) {
if (!state_check_disable_encoder_run(hdw)) return 0;
if (hdw->state_encoder_ok) {
if (hdw->state_decoder_run &&
hdw->state_pathway_ok) return 0;
del_timer_sync(&hdw->encoder_run_timer);
if (pvr2_encoder_stop(hdw) < 0) return !0;
}
hdw->state_encoder_run = 0;
} else {
if (!hdw->state_encoder_ok) return 0;
if (!hdw->state_decoder_run) return 0;
if (!hdw->state_pathway_ok) return 0;
if (hdw->pathway_state != PVR2_PATHWAY_ANALOG) return 0;
if (!state_check_enable_encoder_run(hdw)) return 0;
if (pvr2_encoder_start(hdw) < 0) return !0;
hdw->state_encoder_run = !0;
if (!hdw->state_encoder_runok) {
hdw->encoder_run_timer.expires =
jiffies + (HZ*250/1000);
add_timer(&hdw->encoder_run_timer);
}
}
trace_stbit("state_encoder_run",hdw->state_encoder_run);
return !0;
Expand Down Expand Up @@ -3629,6 +3737,19 @@ static void pvr2_hdw_encoder_wait_timeout(unsigned long data)
}


/* Timeout function for encoder run timer. */
static void pvr2_hdw_encoder_run_timeout(unsigned long data)
{
struct pvr2_hdw *hdw = (struct pvr2_hdw *)data;
if (!hdw->state_encoder_runok) {
hdw->state_encoder_runok = !0;
trace_stbit("state_encoder_runok",hdw->state_encoder_runok);
hdw->state_stale = !0;
queue_work(hdw->workqueue,&hdw->workpoll);
}
}


/* Evaluate whether or not state_decoder_run can change */
static int state_eval_decoder_run(struct pvr2_hdw *hdw)
{
Expand Down Expand Up @@ -3718,6 +3839,16 @@ static int state_eval_usbstream_run(struct pvr2_hdw *hdw)
} else if ((hdw->pathway_state == PVR2_PATHWAY_DIGITAL) &&
(hdw->hdw_desc->flag_digital_requires_cx23416)) {
if (!hdw->state_encoder_ok) return 0;
if (hdw->state_encoder_run) return 0;
if (hdw->hdw_desc->digital_control_scheme ==
PVR2_DIGITAL_SCHEME_ONAIR) {
/* OnAir digital receivers won't stream
unless the analog encoder has run first.
Why? I have no idea. But don't even
try until we know the analog side is
known to have run. */
if (!hdw->state_encoder_runok) return 0;
}
}
if (pvr2_hdw_cmd_usbstream(hdw,!0) < 0) return 0;
hdw->state_usbstream_run = !0;
Expand Down Expand Up @@ -3861,7 +3992,12 @@ static unsigned int pvr2_hdw_report_unlocked(struct pvr2_hdw *hdw,int which,
(hdw->state_encoder_ok ?
"" : " <encode:init>"),
(hdw->state_encoder_run ?
" <encode:run>" : " <encode:stop>"),
(hdw->state_encoder_runok ?
" <encode:run>" :
" <encode:firstrun>") :
(hdw->state_encoder_runok ?
" <encode:stop>" :
" <encode:virgin>")),
(hdw->state_encoder_config ?
" <encode:configok>" :
(hdw->state_encoder_waitok ?
Expand Down

0 comments on commit d913d63

Please sign in to comment.