static int davinci_pcm_close(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; struct davinci_runtime_data *prtd = runtime->private_data; if (prtd->ram_channel >= 0) edma_stop(prtd->ram_channel); if (prtd->asp_channel >= 0) edma_stop(prtd->asp_channel); if (prtd->asp_link[0] >= 0) edma_unlink(prtd->asp_link[0]); if (prtd->asp_link[1] >= 0) edma_unlink(prtd->asp_link[1]); if (prtd->ram_link >= 0) edma_unlink(prtd->ram_link); if (prtd->asp_link[0] >= 0) edma_free_slot(prtd->asp_link[0]); if (prtd->asp_link[1] >= 0) edma_free_slot(prtd->asp_link[1]); if (prtd->asp_channel >= 0) edma_free_channel(prtd->asp_channel); if (prtd->ram_link >= 0) edma_free_slot(prtd->ram_link); if (prtd->ram_link2 >= 0) edma_free_slot(prtd->ram_link2); if (prtd->ram_channel >= 0) edma_free_channel(prtd->ram_channel); kfree(prtd); return 0; }
/* release_channel() must be called with the edma_mutex held */ static void release_channel(int chan) { int localChan; int i; /* * The non-LSP_210 EDMA interface returns a "magic" value that represents * the controller number and channel number muxed together in one UInt32. * This module doesn't yet support a controller other than 0, however, this * function needs to accommodate being called with a controller > 0 since * it's called to release a channel on a controller > 0 when the * REQUESTDMA ioctl() receives a controller > 0 that it can't handle and * needs to clean up after itself. */ /* * In order to not be dependent on the LSP #defines, we need to * translate our EDMA interface's #defines to the LSP ones. */ #if defined(LSP_210) localChan = chan; if (chan >= EDMA_QDMA0 && chan <= EDMA_QDMA7) { __D(" release_channel: translating QDMA channel %d to LSP namespace ...\n", chan); localChan = EDMA_QDMA_CHANNEL_0 + (chan - EDMA_QDMA0); } for (i = 0; i < channels[localChan].nParam; i++) { __D(" release_channel: freeing channel %d...\n", localChan + i); davinci_free_dma(localChan + i); } INIT_LIST_HEAD(&channels[localChan].users); channels[localChan].nParam = 0; channels[localChan].isParam = 0; #else /* defined(LSP_210) */ localChan = EDMA_CHAN_SLOT(chan); if (localChan >= EDMA_QDMA0 && localChan <= EDMA_QDMA7) { __E(" release_channel: QDMA is not supported: chan %d\n", chan); return; } for (i = 0; i < channels[localChan].nParam; i++) { if (channels[localChan].isParam) { __D(" release_channel: calling edma_free_slot(%d)...\n", chan + i); edma_free_slot(chan + i); } else { __D(" release_channel: calling edma_free_channel(%d)...\n", chan + i); edma_clean_channel(chan + i); edma_free_channel(chan + i); } } if (EDMA_CTLR(chan) == 0) { INIT_LIST_HEAD(&channels[localChan].users); channels[localChan].nParam = 0; channels[localChan].isParam = 0; } #endif /* defined(LSP_210) */ }