return snd_dmaengine_pcm_pointer(substream);
}
+static struct dma_chan *mca_request_dma_channel(struct mca_cluster *cl, unsigned int stream)
+{
+ bool is_tx = (stream == SNDRV_PCM_STREAM_PLAYBACK);
+#ifndef USE_RXB_FOR_CAPTURE
+ char *name = devm_kasprintf(cl->host->dev, GFP_KERNEL,
+ is_tx ? "tx%da" : "rx%da", cl->no);
+#else
+ char *name = devm_kasprintf(cl->host->dev, GFP_KERNEL,
+ is_tx ? "tx%da" : "rx%db", cl->no);
+#endif
+ return of_dma_request_slave_channel(cl->host->dev->of_node, name);
+
+}
+
+static void mca_pcm_free(struct snd_soc_component *component,
+ struct snd_pcm *pcm)
+{
+ struct snd_soc_pcm_runtime *rtd = snd_pcm_chip(pcm);
+ struct mca_cluster *cl = mca_dai_to_cluster(asoc_rtd_to_cpu(rtd, 0));
+ unsigned int i;
+
+ if (rtd->dai_link->no_pcm)
+ return;
+
+ for_each_pcm_streams(i) {
+ struct snd_pcm_substream *substream =
+ rtd->pcm->streams[i].substream;
+
+ if (!substream || !cl->dma_chans[i])
+ continue;
+
+ dma_release_channel(cl->dma_chans[i]);
+ cl->dma_chans[i] = NULL;
+ }
+}
+
+
static int mca_pcm_new(struct snd_soc_component *component,
struct snd_soc_pcm_runtime *rtd)
{
for_each_pcm_streams(i) {
struct snd_pcm_substream *substream =
rtd->pcm->streams[i].substream;
- struct dma_chan *chan = cl->dma_chans[i];
+ struct dma_chan *chan;
if (!substream)
continue;
- if (!chan) {
- dev_err(component->dev, "missing DMA channel for stream %d on SERDES %d\n",
- i, cl->no);
+ chan = mca_request_dma_channel(cl, i);
+
+ if (IS_ERR_OR_NULL(chan)) {
+ dev_err(component->dev, "unable to obtain DMA channel (stream %d cluster %d): %pe\n",
+ i, cl->no, chan);
+ mca_pcm_free(component, rtd->pcm);
return -EINVAL;
}
+ cl->dma_chans[i] = chan;
snd_pcm_set_managed_buffer(substream, SNDRV_DMA_TYPE_DEV_IRAM,
chan->device->dev, 512 * 1024 * 6,
SIZE_MAX);
.trigger = mca_trigger,
.pointer = mca_pointer,
.pcm_construct = mca_pcm_new,
+ .pcm_destruct = mca_pcm_free,
};
static void apple_mca_release(struct mca_data *mca)
struct snd_soc_dai_driver *fe =
&dai_drivers[mca->nclusters + i];
struct snd_soc_dai_driver *be = &dai_drivers[i];
- int stream;
cl->host = mca;
cl->no = i;
goto err_release;
}
- for_each_pcm_streams(stream) {
- struct dma_chan *chan;
- bool is_tx = (stream == SNDRV_PCM_STREAM_PLAYBACK);
-#ifndef USE_RXB_FOR_CAPTURE
- char *name = devm_kasprintf(&pdev->dev, GFP_KERNEL,
- is_tx ? "tx%da" : "rx%da",
- i);
-#else
- char *name = devm_kasprintf(&pdev->dev, GFP_KERNEL,
- is_tx ? "tx%da" : "rx%db",
- i);
-#endif
-
- chan = of_dma_request_slave_channel(pdev->dev.of_node,
- name);
- if (IS_ERR(chan)) {
- if (PTR_ERR(chan) != -EPROBE_DEFER)
- dev_err(&pdev->dev,
- "no %s DMA channel: %ld\n",
- name, PTR_ERR(chan));
-
- ret = PTR_ERR(chan);
- goto err_release;
- }
-
- cl->dma_chans[stream] = chan;
- }
-
fe->id = i;
fe->name =
devm_kasprintf(&pdev->dev, GFP_KERNEL, "mca-pcm-%d", i);