static int pcm_in_release(struct inode *inode, struct file *file) { int rc = 0; struct pcm *pcm = file->private_data; pr_info("[AUD][%s:%s] release session id[%d]\n", __MM_FILE__, __func__, pcm->ac->session); mutex_lock(&pcm->lock); /* remove this session from topology list */ auddev_cfg_tx_copp_topology(pcm->ac->session, DEFAULT_COPP_TOPOLOGY); rc = pcm_in_disable(pcm); hrtimer_cancel(&pcm->hrt); rc = afe_cmd_memory_unmap(pcm->dma_addr); if (rc < 0) pr_err("AFE memory unmap failed\n"); rc = afe_unregister_get_events(RT_PROXY_DAI_001_TX); if (rc < 0) pr_err("AFE unregister for events failed\n"); afe_close(RT_PROXY_DAI_001_TX); pr_debug("release all buffer\n"); q6asm_audio_client_buf_free_contiguous(OUT, pcm->ac); msm_clear_session_id(pcm->ac->session); q6asm_audio_client_free(pcm->ac); mutex_unlock(&pcm->lock); mutex_destroy(&pcm->lock); mutex_destroy(&pcm->read_lock); kfree(pcm); return rc; }
static int msm_compr_playback_close(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; struct snd_soc_pcm_runtime *soc_prtd = substream->private_data; struct compr_audio *compr = runtime->private_data; struct msm_audio *prtd = &compr->prtd; int dir = 0; int rc = 0; pr_debug("[AUD] %s +++\n", __func__); /* If routing is still enabled, we need to issue EOS to the DSP To issue EOS to dsp, we need to be run state otherwise EOS is not honored. */ if (msm_routing_check_backend_enabled(soc_prtd->dai_link->be_id)) { rc = q6asm_run(prtd->audio_client,0,0,0); atomic_set(&prtd->pending_buffer, 0); prtd->cmd_ack = 0; q6asm_cmd_nowait(prtd->audio_client, CMD_EOS); pr_debug("%s ++\n", __func__); rc = wait_event_timeout(the_locks.eos_wait, prtd->cmd_ack, 3 * HZ); pr_debug("%s --\n", __func__); if (rc <= 0) pr_err("EOS cmd timeout\n"); prtd->pcm_irq_pos = 0; } dir = IN; atomic_set(&prtd->pending_buffer, 0); q6asm_cmd(prtd->audio_client, CMD_CLOSE); q6asm_audio_client_buf_free_contiguous(dir, prtd->audio_client); msm_pcm_routing_dereg_phy_stream(soc_prtd->dai_link->be_id, SNDRV_PCM_STREAM_PLAYBACK); q6asm_audio_client_free(prtd->audio_client); kfree(prtd); pr_debug("[AUD] %s ---\n", __func__); return 0; }
static int msm_compr_playback_close(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; struct snd_soc_pcm_runtime *soc_prtd = substream->private_data; struct compr_audio *compr = runtime->private_data; struct msm_audio *prtd = &compr->prtd; int dir = 0; pr_debug("%s\n", __func__); dir = IN; atomic_set(&prtd->pending_buffer, 0); q6asm_cmd(prtd->audio_client, CMD_CLOSE); q6asm_audio_client_buf_free_contiguous(dir, prtd->audio_client); msm_pcm_routing_dereg_phy_stream(soc_prtd->dai_link->be_id, SNDRV_PCM_STREAM_PLAYBACK); q6asm_audio_client_free(prtd->audio_client); kfree(prtd); return 0; }
static int msm_afe_close(struct snd_pcm_substream *substream) { int rc = 0; struct snd_dma_buffer *dma_buf; struct snd_pcm_runtime *runtime; struct pcm_afe_info *prtd; struct snd_soc_pcm_runtime *rtd = NULL; struct snd_soc_dai *dai = NULL; int dir = IN; int ret = 0; pr_debug("%s\n", __func__); if (substream == NULL) { pr_err("substream is NULL\n"); return -EINVAL; } rtd = substream->private_data; dai = rtd->cpu_dai; runtime = substream->runtime; prtd = runtime->private_data; mutex_lock(&prtd->lock); if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { dir = IN; ret = afe_unregister_get_events(dai->id); if (ret < 0) pr_err("AFE unregister for events failed\n"); } else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { dir = OUT; ret = afe_unregister_get_events(dai->id); if (ret < 0) pr_err("AFE unregister for events failed\n"); } hrtimer_cancel(&prtd->hrt); rc = afe_cmd_memory_unmap(runtime->dma_addr); if (rc < 0) pr_err("AFE memory unmap failed\n"); pr_debug("release all buffer\n"); dma_buf = &substream->dma_buffer; if (dma_buf == NULL) { pr_debug("dma_buf is NULL\n"); goto done; } if (dma_buf->area) { dma_buf->area = NULL; } q6asm_audio_client_buf_free_contiguous(dir, prtd->audio_client); done: pr_debug("%s: dai->id =%x\n", __func__, dai->id); q6asm_audio_client_free(prtd->audio_client); mutex_unlock(&prtd->lock); prtd->prepared--; kfree(prtd); return 0; }
static int msm_compr_free(struct snd_compr_stream *cstream) { struct snd_compr_runtime *runtime = cstream->runtime; struct msm_compr_audio *prtd = runtime->private_data; struct snd_soc_pcm_runtime *soc_prtd = cstream->private_data; struct msm_compr_pdata *pdata = snd_soc_platform_get_drvdata(soc_prtd->platform); struct audio_client *ac = prtd->audio_client; int dir = IN, ret = 0, stream_id; unsigned long flags; pr_debug("%s\n", __func__); pdata->cstream[soc_prtd->dai_link->be_id] = NULL; if (cstream->direction == SND_COMPRESS_PLAYBACK) { if (atomic_read(&pdata->audio_ocmem_req) > 1) atomic_dec(&pdata->audio_ocmem_req); else if (atomic_cmpxchg(&pdata->audio_ocmem_req, 1, 0)) audio_ocmem_process_req(AUDIO, false); msm_pcm_routing_dereg_phy_stream(soc_prtd->dai_link->be_id, SNDRV_PCM_STREAM_PLAYBACK); } pr_debug("%s: ocmem_req: %d\n", __func__, atomic_read(&pdata->audio_ocmem_req)); if (atomic_read(&prtd->eos)) { ret = wait_event_timeout(prtd->eos_wait, prtd->cmd_ack, 5 * HZ); if (!ret) pr_err("%s: CMD_EOS failed\n", __func__); } if (atomic_read(&prtd->close)) { prtd->cmd_ack = 0; atomic_set(&prtd->wait_on_close, 1); ret = wait_event_timeout(prtd->close_wait, prtd->cmd_ack, 5 * HZ); if (!ret) pr_err("%s: CMD_CLOSE failed\n", __func__); } spin_lock_irqsave(&prtd->lock, flags); stream_id = ac->stream_id; if (prtd->gapless_state.stream_opened[stream_id^1]) { spin_unlock_irqrestore(&prtd->lock, flags); q6asm_stream_cmd(ac, CMD_CLOSE, stream_id^1); spin_lock_irqsave(&prtd->lock, flags); } if (prtd->gapless_state.stream_opened[stream_id]) { spin_unlock_irqrestore(&prtd->lock, flags); q6asm_stream_cmd(ac, CMD_CLOSE, stream_id); spin_lock_irqsave(&prtd->lock, flags); } spin_unlock_irqrestore(&prtd->lock, flags); /* client buf alloc was with stream id 0, so free with the same */ ac->stream_id = 0; q6asm_audio_client_buf_free_contiguous(dir, ac); q6asm_audio_client_free(ac); kfree(pdata->audio_effects[soc_prtd->dai_link->be_id]); kfree(prtd); return 0; }