[Sound-open-firmware] [PATCH] ssp: cleanup ssp status

Keyon Jie yang.jie at linux.intel.com
Mon Oct 24 04:44:44 CEST 2016


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 <yang.jie at linux.intel.com>
---
 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 d4a8d89..b7d27d1 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;
 }
 
-- 
2.5.0



More information about the Sound-open-firmware mailing list