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 <vgutta@codeaurora.org>
This commit is contained in:
Venkata Narendra Kumar Gutta 2016-03-31 15:57:13 +05:30 committed by Jeevan Shriram
parent d886b34289
commit 531c66a8fe
3 changed files with 50 additions and 2 deletions

View file

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

View file

@ -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;
};

View file

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