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>
This commit is contained in:
Venkata Narendra Kumar Gutta 2014-06-25 20:31:52 +05:30
parent 168f6aa1df
commit 5a799cb840
3 changed files with 69 additions and 3 deletions

View file

@ -144,6 +144,7 @@ struct voip_drv_info {
spinlock_t dsp_lock;
spinlock_t dsp_ul_lock;
bool voip_reset;
uint32_t mode;
uint32_t rate_type;
uint32_t rate;
@ -318,6 +319,34 @@ static int msm_pcm_voip_probe(struct snd_soc_platform *platform)
/* 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,
@ -756,10 +785,20 @@ static int msm_pcm_playback_copy(struct snd_pcm_substream *substream, int a,
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);
@ -809,11 +848,21 @@ static int msm_pcm_capture_copy(struct snd_pcm_substream *substream,
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) {
@ -844,7 +893,6 @@ static int msm_pcm_capture_copy(struct snd_pcm_substream *substream,
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);
@ -904,10 +952,11 @@ static int msm_pcm_close(struct snd_pcm_substream *substream)
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 */
@ -1134,8 +1183,10 @@ static int msm_pcm_prepare(struct snd_pcm_substream *substream)
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));

View file

@ -5418,10 +5418,12 @@ exit:
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;
}
@ -5472,6 +5474,14 @@ static int32_t qdsp_mvm_callback(struct apr_client_data *data, void *priv)
} 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;

View file

@ -1348,6 +1348,9 @@ typedef void (*dtmf_rx_det_cb_fn)(uint8_t *pkt,
char *session,
void *private_data);
typedef void (*voip_ssr_cb) (uint32_t opcode,
void *private_data);
typedef void (*hostpcm_cb_fn)(uint8_t *data,
char *session,
void *private_data);
@ -1359,6 +1362,7 @@ struct mvs_driver_info {
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;
@ -1508,6 +1512,7 @@ struct voice_session_itr {
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,