From 677fc76612e385bc07b9e93bf6aa3e5e5e6e8f58 Mon Sep 17 00:00:00 2001 From: Keyon Jie Date: Mon, 24 Oct 2016 10:44:44 +0800 Subject: [PATCH] ssp: cleanup ssp status We are using 6 states, 2 of them are substates: init, idle, running, paused, draining(sub state when transferring from running to idle) pausing(substate when transferring from running to paused). Don't response new command when in substates, only stay in substates for limited timeout. e.g. 2ms for draing and 1ms for pausing. Signed-off-by: Keyon Jie --- src/drivers/ssp.c | 48 ++++++++++++++++++++++++++++++++--------------- 1 file changed, 33 insertions(+), 15 deletions(-) diff --git a/src/drivers/ssp.c b/src/drivers/ssp.c index d4a8d8961..b7d27d1ea 100644 --- a/src/drivers/ssp.c +++ b/src/drivers/ssp.c @@ -113,8 +113,8 @@ /* SSP port status */ #define SSP_STATE_INIT 0 -#define SSP_STATE_RUNNING 1 -#define SSP_STATE_IDLE 2 +#define SSP_STATE_IDLE 1 +#define SSP_STATE_RUNNING 2 #define SSP_STATE_DRAINING 3 #define SSP_STATE_PAUSING 4 #define SSP_STATE_PAUSED 5 @@ -182,16 +182,10 @@ static inline int ssp_set_config(struct dai *dai, struct dai_config *dai_config) spin_lock(&ssp->lock); - /* is playback already running */ - if (ssp->state[DAI_DIR_PLAYBACK] == SSP_STATE_RUNNING || - ssp->state[DAI_DIR_PLAYBACK] == SSP_STATE_DRAINING) { - trace_ssp_error("wsP"); - goto out; - } - - /* is capture already running */ - if (ssp->state[DAI_DIR_CAPTURE] == SSP_STATE_RUNNING) { - trace_ssp_error("wsC"); + /* is playback/capture already running */ + if (ssp->state[DAI_DIR_PLAYBACK] > SSP_STATE_IDLE || + ssp->state[DAI_DIR_CAPTURE] > SSP_STATE_IDLE) { + trace_ssp_error("wsS"); goto out; } @@ -301,6 +295,9 @@ static inline int ssp_set_config(struct dai *dai, struct dai_config *dai_config) ssp_write(dai, SSPSP, sspsp); ssp_write(dai, SFIFOTT, sfifott); + ssp->state[DAI_DIR_PLAYBACK] = SSP_STATE_IDLE; + ssp->state[DAI_DIR_CAPTURE] = SSP_STATE_IDLE; + out: spin_unlock(&ssp->lock); @@ -415,17 +412,29 @@ static int ssp_trigger(struct dai *dai, int cmd, int direction) switch (cmd) { case DAI_TRIGGER_START: +/* let's only wait until draining finished(timout) before another start */ +#if 0 /* cancel any scheduled work */ if (ssp->state[direction] == SSP_STATE_DRAINING) work_cancel_default(&ssp->work); - ssp_start(dai, direction); +#endif + if (ssp->state[direction] == SSP_STATE_IDLE) + ssp_start(dai, direction); break; case DAI_TRIGGER_PAUSE_RELEASE: +/* let's only wait until pausing finished(timout) before next release */ +#if 0 if (ssp->state[direction] == SSP_STATE_PAUSING) work_cancel_default(&ssp->work); - ssp_start(dai, direction); +#endif + if (ssp->state[direction] == SSP_STATE_PAUSED) + ssp_start(dai, direction); break; case DAI_TRIGGER_PAUSE_PUSH: + if (ssp->state[direction] != SSP_STATE_RUNNING) { + trace_ssp_error("wsP"); + return 0; + } if (direction == STREAM_DIRECTION_PLAYBACK) { ssp->state[STREAM_DIRECTION_PLAYBACK] = SSP_STATE_PAUSING; @@ -434,7 +443,13 @@ static int ssp_trigger(struct dai *dai, int cmd, int direction) ssp_pause(dai, direction); break; case DAI_TRIGGER_STOP: - if (direction == STREAM_DIRECTION_PLAYBACK) { + if (ssp->state[direction] != SSP_STATE_RUNNING && + ssp->state[direction] != SSP_STATE_PAUSED) { + trace_ssp_error("wsO"); + return 0; + } + if (direction == STREAM_DIRECTION_PLAYBACK && + ssp->state[direction] == SSP_STATE_RUNNING) { ssp->state[STREAM_DIRECTION_PLAYBACK] = SSP_STATE_DRAINING; work_schedule_default(&ssp->work, 2000); @@ -467,6 +482,9 @@ static int ssp_probe(struct dai *dai) work_init(&ssp->work, ssp_drain_work, dai, WORK_ASYNC); spinlock_init(&ssp->lock); + ssp->state[DAI_DIR_PLAYBACK] = SSP_STATE_INIT; + ssp->state[DAI_DIR_CAPTURE] = SSP_STATE_INIT; + return 0; }