Commit 6e931375 authored by Mike Isely's avatar Mike Isely Committed by Mauro Carvalho Chehab

V4L/DVB: pvrusb2: Enforce a 300msec stabilization interval during stream strart

Martin Dauskardt <martin.dauskardt@gmx.de> has determined that the
encoder has a much better chance of starting cleanly if we
deliberately hold off starting it util the video digitizer has had a
chance to run for at least 300msec first.  These changes implement an
enforced 300msec wait in the state machine that orchestrates streaming
start / stop.
Signed-off-by: default avatarMike Isely <isely@pobox.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent 7cae112e
...@@ -233,8 +233,9 @@ struct pvr2_hdw { ...@@ -233,8 +233,9 @@ struct pvr2_hdw {
int state_encoder_waitok; /* Encoder pre-wait done */ int state_encoder_waitok; /* Encoder pre-wait done */
int state_encoder_runok; /* Encoder has run for >= .25 sec */ int state_encoder_runok; /* Encoder has run for >= .25 sec */
int state_decoder_run; /* Decoder is running */ int state_decoder_run; /* Decoder is running */
int state_decoder_ready; /* Decoder is stabilized & streamable */
int state_usbstream_run; /* FX2 is streaming */ int state_usbstream_run; /* FX2 is streaming */
int state_decoder_quiescent; /* Decoder idle for > 50msec */ int state_decoder_quiescent; /* Decoder idle for minimal interval */
int state_pipeline_config; /* Pipeline is configured */ int state_pipeline_config; /* Pipeline is configured */
int state_pipeline_req; /* Somebody wants to stream */ int state_pipeline_req; /* Somebody wants to stream */
int state_pipeline_pause; /* Pipeline must be paused */ int state_pipeline_pause; /* Pipeline must be paused */
...@@ -255,9 +256,16 @@ struct pvr2_hdw { ...@@ -255,9 +256,16 @@ struct pvr2_hdw {
void (*state_func)(void *); void (*state_func)(void *);
void *state_data; void *state_data;
/* Timer for measuring decoder settling time */ /* Timer for measuring required decoder settling time before we're
allowed to fire it up again. */
struct timer_list quiescent_timer; struct timer_list quiescent_timer;
/* Timer for measuring decoder stabilization time, which is the
amount of time we need to let the decoder run before we can
trust its output (otherwise the encoder might see garbage and
then fail to start correctly). */
struct timer_list decoder_stabilization_timer;
/* Timer for measuring encoder pre-wait time */ /* Timer for measuring encoder pre-wait time */
struct timer_list encoder_wait_timer; struct timer_list encoder_wait_timer;
......
...@@ -48,6 +48,10 @@ ...@@ -48,6 +48,10 @@
before we are allowed to start it running. */ before we are allowed to start it running. */
#define TIME_MSEC_DECODER_WAIT 50 #define TIME_MSEC_DECODER_WAIT 50
/* This defines a minimum interval that the decoder must be allowed to run
before we can safely begin using its streaming output. */
#define TIME_MSEC_DECODER_STABILIZATION_WAIT 300
/* This defines a minimum interval that the encoder must remain quiet /* This defines a minimum interval that the encoder must remain quiet
before we are allowed to configure it. I had this originally set to before we are allowed to configure it. I had this originally set to
50msec, but Martin Dauskardt <martin.dauskardt@gmx.de> reports that 50msec, but Martin Dauskardt <martin.dauskardt@gmx.de> reports that
...@@ -334,6 +338,7 @@ static int pvr2_hdw_get_eeprom_addr(struct pvr2_hdw *hdw); ...@@ -334,6 +338,7 @@ static int pvr2_hdw_get_eeprom_addr(struct pvr2_hdw *hdw);
static void pvr2_hdw_internal_find_stdenum(struct pvr2_hdw *hdw); 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_internal_set_std_avail(struct pvr2_hdw *hdw);
static void pvr2_hdw_quiescent_timeout(unsigned long); static void pvr2_hdw_quiescent_timeout(unsigned long);
static void pvr2_hdw_decoder_stabilization_timeout(unsigned long);
static void pvr2_hdw_encoder_wait_timeout(unsigned long); static void pvr2_hdw_encoder_wait_timeout(unsigned long);
static void pvr2_hdw_encoder_run_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_issue_simple_cmd(struct pvr2_hdw *,u32);
...@@ -2462,6 +2467,11 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf, ...@@ -2462,6 +2467,11 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf,
hdw->quiescent_timer.data = (unsigned long)hdw; hdw->quiescent_timer.data = (unsigned long)hdw;
hdw->quiescent_timer.function = pvr2_hdw_quiescent_timeout; hdw->quiescent_timer.function = pvr2_hdw_quiescent_timeout;
init_timer(&hdw->decoder_stabilization_timer);
hdw->decoder_stabilization_timer.data = (unsigned long)hdw;
hdw->decoder_stabilization_timer.function =
pvr2_hdw_decoder_stabilization_timeout;
init_timer(&hdw->encoder_wait_timer); init_timer(&hdw->encoder_wait_timer);
hdw->encoder_wait_timer.data = (unsigned long)hdw; hdw->encoder_wait_timer.data = (unsigned long)hdw;
hdw->encoder_wait_timer.function = pvr2_hdw_encoder_wait_timeout; hdw->encoder_wait_timer.function = pvr2_hdw_encoder_wait_timeout;
...@@ -2675,6 +2685,7 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf, ...@@ -2675,6 +2685,7 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf,
fail: fail:
if (hdw) { if (hdw) {
del_timer_sync(&hdw->quiescent_timer); del_timer_sync(&hdw->quiescent_timer);
del_timer_sync(&hdw->decoder_stabilization_timer);
del_timer_sync(&hdw->encoder_run_timer); del_timer_sync(&hdw->encoder_run_timer);
del_timer_sync(&hdw->encoder_wait_timer); del_timer_sync(&hdw->encoder_wait_timer);
if (hdw->workqueue) { if (hdw->workqueue) {
...@@ -2742,6 +2753,7 @@ void pvr2_hdw_destroy(struct pvr2_hdw *hdw) ...@@ -2742,6 +2753,7 @@ void pvr2_hdw_destroy(struct pvr2_hdw *hdw)
hdw->workqueue = NULL; hdw->workqueue = NULL;
} }
del_timer_sync(&hdw->quiescent_timer); del_timer_sync(&hdw->quiescent_timer);
del_timer_sync(&hdw->decoder_stabilization_timer);
del_timer_sync(&hdw->encoder_run_timer); del_timer_sync(&hdw->encoder_run_timer);
del_timer_sync(&hdw->encoder_wait_timer); del_timer_sync(&hdw->encoder_wait_timer);
if (hdw->fw_buffer) { if (hdw->fw_buffer) {
...@@ -4453,7 +4465,7 @@ static int state_check_enable_encoder_run(struct pvr2_hdw *hdw) ...@@ -4453,7 +4465,7 @@ static int state_check_enable_encoder_run(struct pvr2_hdw *hdw)
switch (hdw->pathway_state) { switch (hdw->pathway_state) {
case PVR2_PATHWAY_ANALOG: case PVR2_PATHWAY_ANALOG:
if (hdw->state_decoder_run) { if (hdw->state_decoder_run && hdw->state_decoder_ready) {
/* In analog mode, if the decoder is running, then /* In analog mode, if the decoder is running, then
run the encoder. */ run the encoder. */
return !0; return !0;
...@@ -4520,6 +4532,17 @@ static void pvr2_hdw_quiescent_timeout(unsigned long data) ...@@ -4520,6 +4532,17 @@ static void pvr2_hdw_quiescent_timeout(unsigned long data)
} }
/* Timeout function for decoder stabilization timer. */
static void pvr2_hdw_decoder_stabilization_timeout(unsigned long data)
{
struct pvr2_hdw *hdw = (struct pvr2_hdw *)data;
hdw->state_decoder_ready = !0;
trace_stbit("state_decoder_ready", hdw->state_decoder_ready);
hdw->state_stale = !0;
queue_work(hdw->workqueue, &hdw->workpoll);
}
/* Timeout function for encoder wait timer. */ /* Timeout function for encoder wait timer. */
static void pvr2_hdw_encoder_wait_timeout(unsigned long data) static void pvr2_hdw_encoder_wait_timeout(unsigned long data)
{ {
...@@ -4558,8 +4581,13 @@ static int state_eval_decoder_run(struct pvr2_hdw *hdw) ...@@ -4558,8 +4581,13 @@ static int state_eval_decoder_run(struct pvr2_hdw *hdw)
} }
hdw->state_decoder_quiescent = 0; hdw->state_decoder_quiescent = 0;
hdw->state_decoder_run = 0; hdw->state_decoder_run = 0;
/* paranoia - solve race if timer just completed */ /* paranoia - solve race if timer(s) just completed */
del_timer_sync(&hdw->quiescent_timer); del_timer_sync(&hdw->quiescent_timer);
/* Kill the stabilization timer, in case we're killing the
encoder before the previous stabilization interval has
been properly timed. */
del_timer_sync(&hdw->decoder_stabilization_timer);
hdw->state_decoder_ready = 0;
} else { } else {
if (!hdw->state_decoder_quiescent) { if (!hdw->state_decoder_quiescent) {
if (!timer_pending(&hdw->quiescent_timer)) { if (!timer_pending(&hdw->quiescent_timer)) {
...@@ -4597,10 +4625,16 @@ static int state_eval_decoder_run(struct pvr2_hdw *hdw) ...@@ -4597,10 +4625,16 @@ static int state_eval_decoder_run(struct pvr2_hdw *hdw)
if (hdw->flag_decoder_missed) return 0; if (hdw->flag_decoder_missed) return 0;
if (pvr2_decoder_enable(hdw,!0) < 0) return 0; if (pvr2_decoder_enable(hdw,!0) < 0) return 0;
hdw->state_decoder_quiescent = 0; hdw->state_decoder_quiescent = 0;
hdw->state_decoder_ready = 0;
hdw->state_decoder_run = !0; hdw->state_decoder_run = !0;
hdw->decoder_stabilization_timer.expires =
jiffies +
(HZ * TIME_MSEC_DECODER_STABILIZATION_WAIT / 1000);
add_timer(&hdw->decoder_stabilization_timer);
} }
trace_stbit("state_decoder_quiescent",hdw->state_decoder_quiescent); trace_stbit("state_decoder_quiescent",hdw->state_decoder_quiescent);
trace_stbit("state_decoder_run",hdw->state_decoder_run); trace_stbit("state_decoder_run",hdw->state_decoder_run);
trace_stbit("state_decoder_ready", hdw->state_decoder_ready);
return !0; return !0;
} }
...@@ -4798,7 +4832,8 @@ static unsigned int pvr2_hdw_report_unlocked(struct pvr2_hdw *hdw,int which, ...@@ -4798,7 +4832,8 @@ static unsigned int pvr2_hdw_report_unlocked(struct pvr2_hdw *hdw,int which,
buf,acnt, buf,acnt,
"worker:%s%s%s%s%s%s%s", "worker:%s%s%s%s%s%s%s",
(hdw->state_decoder_run ? (hdw->state_decoder_run ?
" <decode:run>" : (hdw->state_decoder_ready ?
"<decode:run>" : " <decode:start>") :
(hdw->state_decoder_quiescent ? (hdw->state_decoder_quiescent ?
"" : " <decode:stop>")), "" : " <decode:stop>")),
(hdw->state_decoder_quiescent ? (hdw->state_decoder_quiescent ?
......
...@@ -306,6 +306,7 @@ struct pvr2_hdw_debug_info { ...@@ -306,6 +306,7 @@ struct pvr2_hdw_debug_info {
int state_encoder_ok; int state_encoder_ok;
int state_encoder_run; int state_encoder_run;
int state_decoder_run; int state_decoder_run;
int state_decoder_ready;
int state_usbstream_run; int state_usbstream_run;
int state_decoder_quiescent; int state_decoder_quiescent;
int state_pipeline_config; int state_pipeline_config;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment