diff --git a/sound/soc/sof/Kconfig b/sound/soc/sof/Kconfig index 627b3c2c5edabe..eac00bcc5277b7 100644 --- a/sound/soc/sof/Kconfig +++ b/sound/soc/sof/Kconfig @@ -99,12 +99,15 @@ config SND_SOC_SOF_FORCE_NOCODEC_MODE Say Y if you need this force nocodec mode option If unsure select "N". -config SND_SOC_SOF_DEBUG_XRUN_STOP - bool "SOF stop on XRUN" +config SND_SOC_SOF_DEBUG_XRUN_REPORT + bool "SOF report FW XRUN to ALSA " help - This option forces PCMs to stop on any XRUN event. This is useful to - preserve any trace data ond pipeline status prior to the XRUN. - Say Y if you are debugging SOF FW pipeline XRUNs. + This option report Firmware XRUN event to ALSA, and ALSA framework + will trigger PCM stop->prepare->start later on it. + If we don't report this XRUN event, ALSA will still observe XRUN + later when .pointer() callback has no update for some time, usually + that may lead to later and lower frequecy ALSA XRUN response. + Say Y if you are debugging SOF FW pipeline XRUNs handling. If unsure select "N". config SND_SOC_SOF_DEBUG_VERBOSE_IPC diff --git a/sound/soc/sof/ipc.c b/sound/soc/sof/ipc.c index 1dc4f9881efef8..81f3f4cadee602 100644 --- a/sound/soc/sof/ipc.c +++ b/sound/soc/sof/ipc.c @@ -556,10 +556,9 @@ static void ipc_xrun(struct snd_sof_dev *sdev, u32 msg_id) dev_dbg(sdev->dev, "posn XRUN: host %llx comp %d size %d\n", posn.host_posn, posn.xrun_comp_id, posn.xrun_size); -#if defined(CONFIG_SND_SOC_SOF_DEBUG_XRUN_STOP) - /* stop PCM on XRUN - used for pipeline debug */ +#if defined(CONFIG_SND_SOC_SOF_DEBUG_XRUN_REPORT) + /* save XRUN info and send to ALSA in .pointer later */ memcpy(&spcm->stream[direction].posn, &posn, sizeof(posn)); - snd_pcm_stop_xrun(spcm->stream[direction].substream); #endif } diff --git a/sound/soc/sof/pcm.c b/sound/soc/sof/pcm.c index d62bb052c62788..caaac31b5ee75d 100644 --- a/sound/soc/sof/pcm.c +++ b/sound/soc/sof/pcm.c @@ -338,6 +338,13 @@ static snd_pcm_uframes_t sof_pcm_pointer(struct snd_pcm_substream *substream) if (rtd->dai_link->no_pcm) return 0; + /* return Xrun to ALSA for further handling */ + if (spcm->stream[substream->stream].posn.xrun_size) { + /* only report once for each XRUN IPC */ + spcm->stream[substream->stream].posn.xrun_size = 0; + return SNDRV_PCM_POS_XRUN; + } + /* if have dsp ops pointer callback, use that directly */ if (sdev->ops->pcm_pointer) return sdev->ops->pcm_pointer(sdev, substream);