Skip to content

Commit 22897e5

Browse files
claudiubezneabroonie
authored andcommitted
ASoC: renesas: rz-ssi: Use proper dma_buffer_pos after resume
When the driver supports DMA, it enqueues four DMA descriptors per substream before the substream is started. New descriptors are enqueued in the DMA completion callback, and each time a new descriptor is queued, the dma_buffer_pos is incremented. During suspend, the DMA transactions are terminated. There might be cases where the four extra enqueued DMA descriptors are not completed and are instead canceled on suspend. However, the cancel operation does not take into account that the dma_buffer_pos was already incremented. Previously, the suspend code reinitialized dma_buffer_pos to zero, but this is not always correct. To avoid losing any audio periods during suspend/resume and to prevent clip sound, save the completed DMA buffer position in the DMA callback and reinitialize dma_buffer_pos on resume. Cc: stable@vger.kernel.org Fixes: 1fc778f ("ASoC: renesas: rz-ssi: Add suspend to RAM support") Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com> Link: https://patch.msgid.link/20251029141134.2556926-3-claudiu.beznea.uj@bp.renesas.com Signed-off-by: Mark Brown <broonie@kernel.org>
1 parent 45f5c9e commit 22897e5

File tree

1 file changed

+12
-13
lines changed

1 file changed

+12
-13
lines changed

sound/soc/renesas/rz-ssi.c

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ struct rz_ssi_stream {
8585
struct snd_pcm_substream *substream;
8686
int fifo_sample_size; /* sample capacity of SSI FIFO */
8787
int dma_buffer_pos; /* The address for the next DMA descriptor */
88+
int completed_dma_buf_pos; /* The address of the last completed DMA descriptor. */
8889
int period_counter; /* for keeping track of periods transferred */
8990
int sample_width;
9091
int buffer_pos; /* current frame position in the buffer */
@@ -215,6 +216,7 @@ static void rz_ssi_stream_init(struct rz_ssi_stream *strm,
215216
rz_ssi_set_substream(strm, substream);
216217
strm->sample_width = samples_to_bytes(runtime, 1);
217218
strm->dma_buffer_pos = 0;
219+
strm->completed_dma_buf_pos = 0;
218220
strm->period_counter = 0;
219221
strm->buffer_pos = 0;
220222

@@ -437,6 +439,10 @@ static void rz_ssi_pointer_update(struct rz_ssi_stream *strm, int frames)
437439
snd_pcm_period_elapsed(strm->substream);
438440
strm->period_counter = current_period;
439441
}
442+
443+
strm->completed_dma_buf_pos += runtime->period_size;
444+
if (strm->completed_dma_buf_pos >= runtime->buffer_size)
445+
strm->completed_dma_buf_pos = 0;
440446
}
441447

442448
static int rz_ssi_pio_recv(struct rz_ssi_priv *ssi, struct rz_ssi_stream *strm)
@@ -778,10 +784,14 @@ static int rz_ssi_dma_request(struct rz_ssi_priv *ssi, struct device *dev)
778784
return -ENODEV;
779785
}
780786

781-
static int rz_ssi_trigger_resume(struct rz_ssi_priv *ssi)
787+
static int rz_ssi_trigger_resume(struct rz_ssi_priv *ssi, struct rz_ssi_stream *strm)
782788
{
789+
struct snd_pcm_substream *substream = strm->substream;
790+
struct snd_pcm_runtime *runtime = substream->runtime;
783791
int ret;
784792

793+
strm->dma_buffer_pos = strm->completed_dma_buf_pos + runtime->period_size;
794+
785795
if (rz_ssi_is_stream_running(&ssi->playback) ||
786796
rz_ssi_is_stream_running(&ssi->capture))
787797
return 0;
@@ -794,16 +804,6 @@ static int rz_ssi_trigger_resume(struct rz_ssi_priv *ssi)
794804
ssi->hw_params_cache.channels);
795805
}
796806

797-
static void rz_ssi_streams_suspend(struct rz_ssi_priv *ssi)
798-
{
799-
if (rz_ssi_is_stream_running(&ssi->playback) ||
800-
rz_ssi_is_stream_running(&ssi->capture))
801-
return;
802-
803-
ssi->playback.dma_buffer_pos = 0;
804-
ssi->capture.dma_buffer_pos = 0;
805-
}
806-
807807
static int rz_ssi_dai_trigger(struct snd_pcm_substream *substream, int cmd,
808808
struct snd_soc_dai *dai)
809809
{
@@ -813,7 +813,7 @@ static int rz_ssi_dai_trigger(struct snd_pcm_substream *substream, int cmd,
813813

814814
switch (cmd) {
815815
case SNDRV_PCM_TRIGGER_RESUME:
816-
ret = rz_ssi_trigger_resume(ssi);
816+
ret = rz_ssi_trigger_resume(ssi, strm);
817817
if (ret)
818818
return ret;
819819

@@ -852,7 +852,6 @@ static int rz_ssi_dai_trigger(struct snd_pcm_substream *substream, int cmd,
852852

853853
case SNDRV_PCM_TRIGGER_SUSPEND:
854854
rz_ssi_stop(ssi, strm);
855-
rz_ssi_streams_suspend(ssi);
856855
break;
857856

858857
case SNDRV_PCM_TRIGGER_STOP:

0 commit comments

Comments
 (0)