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);