From 531c66a8fe7a84a4bc8fc6880ce523892a7fa6b4 Mon Sep 17 00:00:00 2001 From: Venkata Narendra Kumar Gutta Date: Thu, 31 Mar 2016 15:57:13 +0530 Subject: [PATCH] ASoC: msm: qdsp6v2: Fix mute in WFD playback during ADSP SSR Mute observed in WFD playback during ADSP SSR. This is due to playback session isn't being restarted post SSR. Fix this by listening to reset events and propagate the appropriate error back to userspace in case of SSR. CRs-Fixed: 986757 Change-Id: I4c2fdf70e518310157d81d527afff4436dd42140 Signed-off-by: Venkata Narendra Kumar Gutta --- sound/soc/msm/qdsp6v2/msm-pcm-afe-v2.c | 34 +++++++++++++++++++++++++- sound/soc/msm/qdsp6v2/msm-pcm-afe-v2.h | 3 ++- sound/soc/msm/qdsp6v2/q6afe.c | 15 ++++++++++++ 3 files changed, 50 insertions(+), 2 deletions(-) diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-afe-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-afe-v2.c index 8ebc2a1660e6..6144619ca39a 100644 --- a/sound/soc/msm/qdsp6v2/msm-pcm-afe-v2.c +++ b/sound/soc/msm/qdsp6v2/msm-pcm-afe-v2.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -241,6 +241,12 @@ static void pcm_afe_process_tx_pkt(uint32_t opcode, } break; } + case RESET_EVENTS: + prtd->pcm_irq_pos += snd_pcm_lib_period_bytes + (prtd->substream); + prtd->reset_event = true; + snd_pcm_period_elapsed(prtd->substream); + break; default: break; } @@ -342,6 +348,16 @@ static void pcm_afe_process_rx_pkt(uint32_t opcode, } break; } + case RESET_EVENTS: + prtd->pcm_irq_pos += snd_pcm_lib_period_bytes + (prtd->substream); + prtd->reset_event = true; + if (!prtd->mmap_flag) { + atomic_set(&prtd->rec_bytes_avail, 1); + wake_up(&prtd->read_wait); + } + snd_pcm_period_elapsed(prtd->substream); + break; default: break; } @@ -470,6 +486,7 @@ static int msm_afe_open(struct snd_pcm_substream *substream) } } + prtd->reset_event = false; return 0; } @@ -590,8 +607,17 @@ static int msm_afe_copy(struct snd_pcm_substream *substream, int channel, snd_pcm_uframes_t hwoff, void __user *buf, snd_pcm_uframes_t frames) { + struct snd_pcm_runtime *runtime = substream->runtime; + struct pcm_afe_info *prtd = runtime->private_data; + int ret = 0; + if (prtd->reset_event) { + pr_debug("%s: reset events received from ADSP, return error\n", + __func__); + return -ENETRESET; + } + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ret = msm_afe_playback_copy(substream, channel, hwoff, buf, frames); @@ -804,6 +830,12 @@ static snd_pcm_uframes_t msm_afe_pointer(struct snd_pcm_substream *substream) if (prtd->pcm_irq_pos >= snd_pcm_lib_buffer_bytes(substream)) prtd->pcm_irq_pos = 0; + if (prtd->reset_event) { + pr_debug("%s: reset events received from ADSP, return XRUN\n", + __func__); + return SNDRV_PCM_POS_XRUN; + } + pr_debug("pcm_irq_pos = %d\n", prtd->pcm_irq_pos); return bytes_to_frames(runtime, (prtd->pcm_irq_pos)); } diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-afe-v2.h b/sound/soc/msm/qdsp6v2/msm-pcm-afe-v2.h index d2aed4c6e2ab..84a4c3c6c275 100644 --- a/sound/soc/msm/qdsp6v2/msm-pcm-afe-v2.h +++ b/sound/soc/msm/qdsp6v2/msm-pcm-afe-v2.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2012,2015 The Linux Foundation. All rights reserved. +/* Copyright (c) 2012,2015-2016 The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -33,6 +33,7 @@ struct pcm_afe_info { struct afe_audio_client *audio_client; wait_queue_head_t read_wait; atomic_t rec_bytes_avail; + bool reset_event; }; diff --git a/sound/soc/msm/qdsp6v2/q6afe.c b/sound/soc/msm/qdsp6v2/q6afe.c index 7a1e61e29381..803c913b04b1 100644 --- a/sound/soc/msm/qdsp6v2/q6afe.c +++ b/sound/soc/msm/qdsp6v2/q6afe.c @@ -284,6 +284,21 @@ static int32_t afe_callback(struct apr_client_data *data, void *priv) pr_debug("%s: task_name = %s pid = %d\n", __func__, this_afe.task->comm, this_afe.task->pid); + + /* + * Pass reset events to proxy driver, if cb is registered + */ + if (this_afe.tx_cb) { + this_afe.tx_cb(data->opcode, data->token, + data->payload, + this_afe.tx_private_data); + } + if (this_afe.rx_cb) { + this_afe.rx_cb(data->opcode, data->token, + data->payload, + this_afe.rx_private_data); + } + return 0; } afe_callback_debug_print(data);