From bd84ac72c1cabfdf31008fc84dbd8ea3ecb6f1d5 Mon Sep 17 00:00:00 2001 From: Santosh Mardi Date: Tue, 9 Oct 2012 10:32:42 +0530 Subject: [PATCH] ANDROID: GKI: ASoC: core: Update ALSA core to issue restart in underrun. When compressed and pcm session is started the buffer pull will Be from the DSP, in mmap mode for the scenario Hardware pointer Is same as application pointer implies application has not filled the Buffer to be send to DSP, and platform driver has to break and restart The de queue process when the application has sufficient buffers. When hardware pointer is same as application pointer it is an under run Scenario where the ALSA framework has to trigger the under run and in HAL The session has to re-prepare and re-triggered. based on the stop Threshold, but in our system the stop threshold is INT_MAX which Indicates that under run is not triggered in practical cases. We have a brodcast usecase in which the mentioned under run case Is hit mulitple times, and every time re-prepare and re-trigger will be Expensive Update the ASoC core framework to restart de queue process stopped By platform Driver when the under run is hit, based on the available Buffer and render flag, so the System will recover from the hang state. To restart de queue process the ASoC core will be calling the restart Callback registered by platform driver and this callback will be running in Atomic context. Test: build Bug: 151372815 Change-Id: Ic9ea05a0dc6246346e9913493232882e2f5447d1 Signed-off-by: Santosh Mardi Signed-off-by: Meng Wang (cherry picked from commit ddbe60b879175f7260a910e77fc8e9e9369de84f) Signed-off-by: Hridya Valsaraju --- include/sound/pcm.h | 6 ++++++ sound/core/pcm_native.c | 11 +++++++++++ 2 files changed, 17 insertions(+) diff --git a/include/sound/pcm.h b/include/sound/pcm.h index 4a6a631b5a7f..ead7dea4bc2b 100644 --- a/include/sound/pcm.h +++ b/include/sound/pcm.h @@ -123,6 +123,11 @@ struct snd_pcm_ops { #define SNDRV_PCM_POS_XRUN ((snd_pcm_uframes_t)-1) +#define SNDRV_DMA_MODE (0) +#define SNDRV_NON_DMA_MODE (1 << 0) +#define SNDRV_RENDER_STOPPED (1 << 1) +#define SNDRV_RENDER_RUNNING (1 << 2) + /* If you change this don't forget to change rates[] table in pcm_native.c */ #define SNDRV_PCM_RATE_5512 (1<<0) /* 5512Hz */ #define SNDRV_PCM_RATE_8000 (1<<1) /* 8000Hz */ @@ -390,6 +395,7 @@ struct snd_pcm_runtime { unsigned int rate_num; unsigned int rate_den; unsigned int no_period_wakeup: 1; + unsigned int render_flag; /* -- SW params -- */ int tstamp_mode; /* mmap timestamp is updated */ diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index c049f639061f..47725555fe34 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c @@ -2728,6 +2728,7 @@ static int snd_pcm_sync_ptr(struct snd_pcm_substream *substream, volatile struct snd_pcm_mmap_status *status; volatile struct snd_pcm_mmap_control *control; int err; + snd_pcm_uframes_t hw_avail; memset(&sync_ptr, 0, sizeof(sync_ptr)); if (get_user(sync_ptr.flags, (unsigned __user *)&(_sync_ptr->flags))) @@ -2756,6 +2757,16 @@ static int snd_pcm_sync_ptr(struct snd_pcm_substream *substream, control->avail_min = sync_ptr.c.control.avail_min; else sync_ptr.c.control.avail_min = control->avail_min; + + if (runtime->render_flag & SNDRV_NON_DMA_MODE) { + hw_avail = snd_pcm_playback_hw_avail(runtime); + if ((hw_avail >= runtime->start_threshold) + && (runtime->render_flag & + SNDRV_RENDER_STOPPED)) { + if (substream->ops->restart) + substream->ops->restart(substream); + } + } sync_ptr.s.status.state = status->state; sync_ptr.s.status.hw_ptr = status->hw_ptr; sync_ptr.s.status.tstamp = status->tstamp;