mirror of https://github.com/thesofproject/sof.git
ssp: Keep SSP connected with DMA in pause state
When there is not enough time to wait for FIFO empty and we care about data continuity - like in pause state - then SSP should be kept connected with DMA in pause state. Stop function has been updated to take action also on channels in COMP_STATE_PAUSED state. After receiving COMP_TRIGGER_STOP, component state should be set to COMP_STATE_PREPARE, what is consistent with sof-docs. Introduced changes have positive impact on glitches after pause/resume sequence. Signed-off-by: Karol Trzcinski <karolx.trzcinski@linux.intel.com>
This commit is contained in:
parent
93cf630d9d
commit
6cd8acc16a
|
@ -626,7 +626,7 @@ static int dai_comp_trigger(struct comp_dev *dev, int cmd)
|
|||
case COMP_TRIGGER_STOP:
|
||||
comp_info(dev, "dai_comp_trigger(), PAUSE/STOP");
|
||||
ret = dma_stop(dd->chan);
|
||||
dai_trigger(dd->dai, COMP_TRIGGER_STOP, dev->direction);
|
||||
dai_trigger(dd->dai, cmd, dev->direction);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
|
|
@ -543,33 +543,43 @@ static void ssp_stop(struct dai *dai, int direction)
|
|||
|
||||
/* stop Rx if neeed */
|
||||
if (direction == DAI_DIR_CAPTURE &&
|
||||
ssp->state[SOF_IPC_STREAM_CAPTURE] == COMP_STATE_ACTIVE) {
|
||||
ssp->state[SOF_IPC_STREAM_CAPTURE] != COMP_STATE_PREPARE) {
|
||||
ssp_update_bits(dai, SSCR1, SSCR1_RSRE, 0);
|
||||
ssp_empty_rx_fifo(dai);
|
||||
ssp->state[SOF_IPC_STREAM_CAPTURE] = COMP_STATE_PAUSED;
|
||||
ssp->state[SOF_IPC_STREAM_CAPTURE] = COMP_STATE_PREPARE;
|
||||
dai_info(dai, "ssp_stop(), RX stop");
|
||||
}
|
||||
|
||||
/* stop Tx if needed */
|
||||
if (direction == DAI_DIR_PLAYBACK &&
|
||||
ssp->state[SOF_IPC_STREAM_PLAYBACK] == COMP_STATE_ACTIVE) {
|
||||
ssp->state[SOF_IPC_STREAM_PLAYBACK] != COMP_STATE_PREPARE) {
|
||||
ssp_update_bits(dai, SSCR1, SSCR1_TSRE, 0);
|
||||
ssp->state[SOF_IPC_STREAM_PLAYBACK] = COMP_STATE_PAUSED;
|
||||
ssp->state[SOF_IPC_STREAM_PLAYBACK] = COMP_STATE_PREPARE;
|
||||
dai_info(dai, "ssp_stop(), TX stop");
|
||||
}
|
||||
|
||||
/* disable SSP port if no users */
|
||||
if (ssp->state[SOF_IPC_STREAM_CAPTURE] != COMP_STATE_ACTIVE &&
|
||||
ssp->state[SOF_IPC_STREAM_PLAYBACK] != COMP_STATE_ACTIVE) {
|
||||
if (ssp->state[SOF_IPC_STREAM_CAPTURE] == COMP_STATE_PREPARE &&
|
||||
ssp->state[SOF_IPC_STREAM_PLAYBACK] == COMP_STATE_PREPARE) {
|
||||
ssp_update_bits(dai, SSCR0, SSCR0_SSE, 0);
|
||||
ssp->state[SOF_IPC_STREAM_CAPTURE] = COMP_STATE_PREPARE;
|
||||
ssp->state[SOF_IPC_STREAM_PLAYBACK] = COMP_STATE_PREPARE;
|
||||
dai_info(dai, "ssp_stop(), SSP port disabled");
|
||||
}
|
||||
|
||||
spin_unlock(&dai->lock);
|
||||
}
|
||||
|
||||
static void ssp_pause(struct dai *dai, int direction)
|
||||
{
|
||||
struct ssp_pdata *ssp = dai_get_drvdata(dai);
|
||||
|
||||
if (direction == SOF_IPC_STREAM_CAPTURE)
|
||||
dai_info(dai, "ssp_pause(), RX");
|
||||
else
|
||||
dai_info(dai, "ssp_pause(), TX");
|
||||
|
||||
ssp->state[direction] = COMP_STATE_PAUSED;
|
||||
}
|
||||
|
||||
static int ssp_trigger(struct dai *dai, int cmd, int direction)
|
||||
{
|
||||
struct ssp_pdata *ssp = dai_get_drvdata(dai);
|
||||
|
@ -588,9 +598,11 @@ static int ssp_trigger(struct dai *dai, int cmd, int direction)
|
|||
ssp_start(dai, direction);
|
||||
break;
|
||||
case COMP_TRIGGER_STOP:
|
||||
case COMP_TRIGGER_PAUSE:
|
||||
ssp_stop(dai, direction);
|
||||
break;
|
||||
case COMP_TRIGGER_PAUSE:
|
||||
ssp_pause(dai, direction);
|
||||
break;
|
||||
case COMP_TRIGGER_RESUME:
|
||||
ssp_context_restore(dai);
|
||||
break;
|
||||
|
|
|
@ -700,36 +700,46 @@ static void ssp_stop(struct dai *dai, int direction)
|
|||
|
||||
/* stop Rx if neeed */
|
||||
if (direction == DAI_DIR_CAPTURE &&
|
||||
ssp->state[SOF_IPC_STREAM_CAPTURE] == COMP_STATE_ACTIVE) {
|
||||
ssp->state[SOF_IPC_STREAM_CAPTURE] != COMP_STATE_PREPARE) {
|
||||
ssp_update_bits(dai, SSCR1, SSCR1_RSRE, 0);
|
||||
ssp_update_bits(dai, SSRSA, SSRSA_RXEN, 0);
|
||||
ssp_empty_rx_fifo(dai);
|
||||
ssp->state[SOF_IPC_STREAM_CAPTURE] = COMP_STATE_PAUSED;
|
||||
ssp->state[SOF_IPC_STREAM_CAPTURE] = COMP_STATE_PREPARE;
|
||||
dai_info(dai, "ssp_stop(), RX stop");
|
||||
}
|
||||
|
||||
/* stop Tx if needed */
|
||||
if (direction == DAI_DIR_PLAYBACK &&
|
||||
ssp->state[SOF_IPC_STREAM_PLAYBACK] == COMP_STATE_ACTIVE) {
|
||||
ssp->state[SOF_IPC_STREAM_PLAYBACK] != COMP_STATE_PREPARE) {
|
||||
ssp_empty_tx_fifo(dai);
|
||||
ssp_update_bits(dai, SSCR1, SSCR1_TSRE, 0);
|
||||
ssp_update_bits(dai, SSTSA, SSTSA_TXEN, 0);
|
||||
ssp->state[SOF_IPC_STREAM_PLAYBACK] = COMP_STATE_PAUSED;
|
||||
ssp->state[SOF_IPC_STREAM_PLAYBACK] = COMP_STATE_PREPARE;
|
||||
dai_info(dai, "ssp_stop(), TX stop");
|
||||
}
|
||||
|
||||
/* disable SSP port if no users */
|
||||
if (ssp->state[SOF_IPC_STREAM_CAPTURE] != COMP_STATE_ACTIVE &&
|
||||
ssp->state[SOF_IPC_STREAM_PLAYBACK] != COMP_STATE_ACTIVE) {
|
||||
if (ssp->state[SOF_IPC_STREAM_CAPTURE] == COMP_STATE_PREPARE &&
|
||||
ssp->state[SOF_IPC_STREAM_PLAYBACK] == COMP_STATE_PREPARE) {
|
||||
ssp_update_bits(dai, SSCR0, SSCR0_SSE, 0);
|
||||
ssp->state[SOF_IPC_STREAM_CAPTURE] = COMP_STATE_PREPARE;
|
||||
ssp->state[SOF_IPC_STREAM_PLAYBACK] = COMP_STATE_PREPARE;
|
||||
dai_info(dai, "ssp_stop(), SSP port disabled");
|
||||
}
|
||||
|
||||
spin_unlock(&dai->lock);
|
||||
}
|
||||
|
||||
static void ssp_pause(struct dai *dai, int direction)
|
||||
{
|
||||
struct ssp_pdata *ssp = dai_get_drvdata(dai);
|
||||
|
||||
if (direction == SOF_IPC_STREAM_CAPTURE)
|
||||
dai_info(dai, "ssp_pause(), RX");
|
||||
else
|
||||
dai_info(dai, "ssp_pause(), TX");
|
||||
|
||||
ssp->state[direction] = COMP_STATE_PAUSED;
|
||||
}
|
||||
|
||||
static int ssp_trigger(struct dai *dai, int cmd, int direction)
|
||||
{
|
||||
struct ssp_pdata *ssp = dai_get_drvdata(dai);
|
||||
|
@ -748,9 +758,11 @@ static int ssp_trigger(struct dai *dai, int cmd, int direction)
|
|||
ssp_start(dai, direction);
|
||||
break;
|
||||
case COMP_TRIGGER_STOP:
|
||||
case COMP_TRIGGER_PAUSE:
|
||||
ssp_stop(dai, direction);
|
||||
break;
|
||||
case COMP_TRIGGER_PAUSE:
|
||||
ssp_pause(dai, direction);
|
||||
break;
|
||||
case COMP_TRIGGER_RESUME:
|
||||
ssp_context_restore(dai);
|
||||
break;
|
||||
|
|
|
@ -459,34 +459,44 @@ static void ssp_stop(struct dai *dai, int direction)
|
|||
|
||||
/* stop Rx if neeed */
|
||||
if (direction == DAI_DIR_CAPTURE &&
|
||||
ssp->state[SOF_IPC_STREAM_CAPTURE] == COMP_STATE_ACTIVE) {
|
||||
ssp->state[SOF_IPC_STREAM_CAPTURE] != COMP_STATE_PREPARE) {
|
||||
ssp_update_bits(dai, SSCR1, SSCR1_RSRE, 0);
|
||||
ssp_update_bits(dai, SSCR0, SSCR0_RIM, SSCR0_RIM);
|
||||
ssp->state[SOF_IPC_STREAM_CAPTURE] = COMP_STATE_PAUSED;
|
||||
ssp->state[SOF_IPC_STREAM_CAPTURE] = COMP_STATE_PREPARE;
|
||||
dai_info(dai, "ssp_stop(), RX stop");
|
||||
}
|
||||
|
||||
/* stop Tx if needed */
|
||||
if (direction == DAI_DIR_PLAYBACK &&
|
||||
ssp->state[SOF_IPC_STREAM_PLAYBACK] == COMP_STATE_ACTIVE) {
|
||||
ssp->state[SOF_IPC_STREAM_PLAYBACK] != COMP_STATE_PREPARE) {
|
||||
ssp_update_bits(dai, SSCR1, SSCR1_TSRE, 0);
|
||||
ssp_update_bits(dai, SSCR0, SSCR0_TIM, SSCR0_TIM);
|
||||
ssp->state[SOF_IPC_STREAM_PLAYBACK] = COMP_STATE_PAUSED;
|
||||
ssp->state[SOF_IPC_STREAM_PLAYBACK] = COMP_STATE_PREPARE;
|
||||
dai_info(dai, "ssp_stop(), TX stop");
|
||||
}
|
||||
|
||||
/* disable SSP port if no users */
|
||||
if (ssp->state[SOF_IPC_STREAM_CAPTURE] != COMP_STATE_ACTIVE &&
|
||||
ssp->state[SOF_IPC_STREAM_PLAYBACK] != COMP_STATE_ACTIVE) {
|
||||
if (ssp->state[SOF_IPC_STREAM_CAPTURE] == COMP_STATE_PREPARE &&
|
||||
ssp->state[SOF_IPC_STREAM_PLAYBACK] == COMP_STATE_PREPARE) {
|
||||
ssp_update_bits(dai, SSCR0, SSCR0_SSE, 0);
|
||||
ssp->state[SOF_IPC_STREAM_CAPTURE] = COMP_STATE_PREPARE;
|
||||
ssp->state[SOF_IPC_STREAM_PLAYBACK] = COMP_STATE_PREPARE;
|
||||
dai_info(dai, "ssp_stop(), SSP port disabled");
|
||||
}
|
||||
|
||||
spin_unlock(&dai->lock);
|
||||
}
|
||||
|
||||
static void ssp_pause(struct dai *dai, int direction)
|
||||
{
|
||||
struct ssp_pdata *ssp = dai_get_drvdata(dai);
|
||||
|
||||
if (direction == SOF_IPC_STREAM_CAPTURE)
|
||||
dai_info(dai, "ssp_pause(), RX");
|
||||
else
|
||||
dai_info(dai, "ssp_pause(), TX");
|
||||
|
||||
ssp->state[direction] = COMP_STATE_PAUSED;
|
||||
}
|
||||
|
||||
static int ssp_trigger(struct dai *dai, int cmd, int direction)
|
||||
{
|
||||
struct ssp_pdata *ssp = dai_get_drvdata(dai);
|
||||
|
@ -505,9 +515,11 @@ static int ssp_trigger(struct dai *dai, int cmd, int direction)
|
|||
ssp_start(dai, direction);
|
||||
break;
|
||||
case COMP_TRIGGER_STOP:
|
||||
case COMP_TRIGGER_PAUSE:
|
||||
ssp_stop(dai, direction);
|
||||
break;
|
||||
case COMP_TRIGGER_PAUSE:
|
||||
ssp_pause(dai, direction);
|
||||
break;
|
||||
case COMP_TRIGGER_RESUME:
|
||||
ssp_context_restore(dai);
|
||||
break;
|
||||
|
|
Loading…
Reference in New Issue