ASoC: msm: qdsp6v2: handle VoIP call recovery during SSR
Add support for VoIP call auto recovery during Sub System Restart(SSR)
Change-Id: Ie8dce8f575ba3af5560c523a00e8520aef1c68c3
Signed-off-by: Venkata Narendra Kumar Gutta <vgutta@codeaurora.org>
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-voip-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-voip-v2.c
index 6b32064..4fe2459 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-voip-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-voip-v2.c
@@ -144,6 +144,7 @@
spinlock_t dsp_lock;
spinlock_t dsp_ul_lock;
+ bool voip_reset;
uint32_t mode;
uint32_t rate_type;
uint32_t rate;
@@ -317,6 +318,34 @@
/* sample rate supported */
static unsigned int supported_sample_rates[] = {8000, 16000};
+static void voip_ssr_cb_fn(uint32_t opcode, void *private_data)
+{
+
+ /* Notify ASoC to send next playback/Capture to unblock write/read */
+ struct voip_drv_info *prtd = private_data;
+
+ if (opcode == 0xFFFFFFFF) {
+
+ prtd->voip_reset = true;
+ pr_debug("%s: Notify ASoC to send next playback/Capture\n",
+ __func__);
+
+ prtd->pcm_playback_irq_pos += prtd->pcm_count;
+ if (prtd->state == VOIP_STARTED)
+ snd_pcm_period_elapsed(prtd->playback_substream);
+ wake_up(&prtd->out_wait);
+
+ prtd->pcm_capture_irq_pos += prtd->pcm_capture_count;
+ if (prtd->state == VOIP_STARTED)
+ snd_pcm_period_elapsed(prtd->capture_substream);
+ wake_up(&prtd->in_wait);
+
+ } else {
+ pr_err("%s: Invalid opcode during reset : %d\n",
+ __func__, opcode);
+ }
+}
+
/* capture path */
static void voip_process_ul_pkt(uint8_t *voc_pkt,
uint32_t pkt_len,
@@ -754,10 +783,20 @@
int count = frames_to_bytes(runtime, frames);
pr_debug("%s: count = %d, frames=%d\n", __func__, count, (int)frames);
+ if (prtd->voip_reset) {
+ pr_debug("%s: RESET event happened during VoIP\n", __func__);
+ return -ENETRESET;
+ }
+
ret = wait_event_interruptible_timeout(prtd->in_wait,
(!list_empty(&prtd->free_in_queue) ||
prtd->state == VOIP_STOPPED),
1 * HZ);
+ if (prtd->voip_reset) {
+ pr_debug("%s: RESET event happened during VoIP\n", __func__);
+ return -ENETRESET;
+ }
+
if (ret > 0) {
if (count <= VOIP_MAX_VOC_PKT_SIZE) {
spin_lock_irqsave(&prtd->dsp_lock, dsp_flags);
@@ -807,11 +846,21 @@
pr_debug("%s: count = %d\n", __func__, count);
+ if (prtd->voip_reset) {
+ pr_debug("%s: RESET event happened during VoIP\n", __func__);
+ return -ENETRESET;
+ }
+
ret = wait_event_interruptible_timeout(prtd->out_wait,
(!list_empty(&prtd->out_queue) ||
prtd->state == VOIP_STOPPED),
1 * HZ);
+ if (prtd->voip_reset) {
+ pr_debug("%s: RESET event happened during VoIP\n", __func__);
+ return -ENETRESET;
+ }
+
if (ret > 0) {
if (count <= VOIP_MAX_VOC_PKT_SIZE) {
@@ -842,7 +891,6 @@
list_add_tail(&buf_node->list,
&prtd->free_out_queue);
spin_unlock_irqrestore(&prtd->dsp_ul_lock, dsp_flags);
-
} else {
pr_err("%s: Read count %d > VOIP_MAX_VOC_PKT_SIZE\n",
__func__, count);
@@ -902,10 +950,11 @@
if (!prtd->playback_instance && !prtd->capture_instance) {
if (prtd->state == VOIP_STARTED) {
+ prtd->voip_reset = false;
prtd->state = VOIP_STOPPED;
voc_end_voice_call(
voc_get_session_id(VOIP_SESSION_NAME));
- voc_register_mvs_cb(NULL, NULL, prtd);
+ voc_register_mvs_cb(NULL, NULL, NULL, prtd);
}
/* release all buffer */
/* release in_queue and free_in_queue */
@@ -1131,8 +1180,10 @@
goto done;
}
+ /* Initialaizing cb variables */
voc_register_mvs_cb(voip_process_ul_pkt,
- voip_process_dl_pkt, prtd);
+ voip_process_dl_pkt,
+ voip_ssr_cb_fn, prtd);
ret = voc_start_voice_call(
voc_get_session_id(VOIP_SESSION_NAME));
diff --git a/sound/soc/msm/qdsp6v2/q6voice.c b/sound/soc/msm/qdsp6v2/q6voice.c
index 475a0eb..b165664 100644
--- a/sound/soc/msm/qdsp6v2/q6voice.c
+++ b/sound/soc/msm/qdsp6v2/q6voice.c
@@ -5206,10 +5206,12 @@
void voc_register_mvs_cb(ul_cb_fn ul_cb,
dl_cb_fn dl_cb,
+ voip_ssr_cb ssr_cb,
void *private_data)
{
common.mvs_info.ul_cb = ul_cb;
common.mvs_info.dl_cb = dl_cb;
+ common.mvs_info.ssr_cb = ssr_cb;
common.mvs_info.private_data = private_data;
}
@@ -5260,6 +5262,14 @@
} else {
pr_debug("%s: Reset event received in Voice service\n",
__func__);
+
+ if (common.mvs_info.ssr_cb) {
+ pr_debug("%s: Informing reset event to VoIP\n",
+ __func__);
+ common.mvs_info.ssr_cb(data->opcode,
+ common.mvs_info.private_data);
+ }
+
apr_reset(c->apr_q6_mvm);
c->apr_q6_mvm = NULL;
diff --git a/sound/soc/msm/qdsp6v2/q6voice.h b/sound/soc/msm/qdsp6v2/q6voice.h
index c6f3482..58cdfc3 100644
--- a/sound/soc/msm/qdsp6v2/q6voice.h
+++ b/sound/soc/msm/qdsp6v2/q6voice.h
@@ -1226,6 +1226,9 @@
char *session,
void *private_data);
+typedef void (*voip_ssr_cb) (uint32_t opcode,
+ void *private_data);
+
struct mvs_driver_info {
uint32_t media_type;
uint32_t rate;
@@ -1233,6 +1236,7 @@
uint32_t dtx_mode;
ul_cb_fn ul_cb;
dl_cb_fn dl_cb;
+ voip_ssr_cb ssr_cb;
void *private_data;
uint32_t evrc_min_rate;
uint32_t evrc_max_rate;
@@ -1365,6 +1369,7 @@
void voc_register_mvs_cb(ul_cb_fn ul_cb,
dl_cb_fn dl_cb,
+ voip_ssr_cb ssr_cb,
void *private_data);
void voc_register_dtmf_rx_detection_cb(dtmf_rx_det_cb_fn dtmf_rx_ul_cb,