hc
2023-12-08 01573e231f18eb2d99162747186f59511f56b64d
kernel/sound/soc/fsl/fsl_asrc_dma.c
....@@ -12,17 +12,15 @@
1212 #include <sound/dmaengine_pcm.h>
1313 #include <sound/pcm_params.h>
1414
15
-#include "fsl_asrc.h"
15
+#include "fsl_asrc_common.h"
1616
1717 #define FSL_ASRC_DMABUF_SIZE (256 * 1024)
1818
19
-static const struct snd_pcm_hardware snd_imx_hardware = {
19
+static struct snd_pcm_hardware snd_imx_hardware = {
2020 .info = SNDRV_PCM_INFO_INTERLEAVED |
2121 SNDRV_PCM_INFO_BLOCK_TRANSFER |
2222 SNDRV_PCM_INFO_MMAP |
23
- SNDRV_PCM_INFO_MMAP_VALID |
24
- SNDRV_PCM_INFO_PAUSE |
25
- SNDRV_PCM_INFO_RESUME,
23
+ SNDRV_PCM_INFO_MMAP_VALID,
2624 .buffer_bytes_max = FSL_ASRC_DMABUF_SIZE,
2725 .period_bytes_min = 128,
2826 .period_bytes_max = 65535, /* Limited by SDMA engine */
....@@ -54,13 +52,12 @@
5452 snd_pcm_period_elapsed(substream);
5553 }
5654
57
-static int fsl_asrc_dma_prepare_and_submit(struct snd_pcm_substream *substream)
55
+static int fsl_asrc_dma_prepare_and_submit(struct snd_pcm_substream *substream,
56
+ struct snd_soc_component *component)
5857 {
5958 u8 dir = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? OUT : IN;
60
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
6159 struct snd_pcm_runtime *runtime = substream->runtime;
6260 struct fsl_asrc_pair *pair = runtime->private_data;
63
- struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, DRV_NAME);
6461 struct device *dev = component->dev;
6562 unsigned long flags = DMA_CTRL_ACK;
6663
....@@ -97,7 +94,8 @@
9794 return 0;
9895 }
9996
100
-static int fsl_asrc_dma_trigger(struct snd_pcm_substream *substream, int cmd)
97
+static int fsl_asrc_dma_trigger(struct snd_soc_component *component,
98
+ struct snd_pcm_substream *substream, int cmd)
10199 {
102100 struct snd_pcm_runtime *runtime = substream->runtime;
103101 struct fsl_asrc_pair *pair = runtime->private_data;
....@@ -107,7 +105,7 @@
107105 case SNDRV_PCM_TRIGGER_START:
108106 case SNDRV_PCM_TRIGGER_RESUME:
109107 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
110
- ret = fsl_asrc_dma_prepare_and_submit(substream);
108
+ ret = fsl_asrc_dma_prepare_and_submit(substream, component);
111109 if (ret)
112110 return ret;
113111 dma_async_issue_pending(pair->dma_chan[IN]);
....@@ -126,35 +124,36 @@
126124 return 0;
127125 }
128126
129
-static int fsl_asrc_dma_hw_params(struct snd_pcm_substream *substream,
127
+static int fsl_asrc_dma_hw_params(struct snd_soc_component *component,
128
+ struct snd_pcm_substream *substream,
130129 struct snd_pcm_hw_params *params)
131130 {
132131 enum dma_slave_buswidth buswidth = DMA_SLAVE_BUSWIDTH_2_BYTES;
133
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
132
+ struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
134133 bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
135134 struct snd_dmaengine_dai_dma_data *dma_params_fe = NULL;
136135 struct snd_dmaengine_dai_dma_data *dma_params_be = NULL;
137
- struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, DRV_NAME);
138136 struct snd_pcm_runtime *runtime = substream->runtime;
139137 struct fsl_asrc_pair *pair = runtime->private_data;
140
- struct fsl_asrc *asrc_priv = pair->asrc_priv;
138
+ struct dma_chan *tmp_chan = NULL, *be_chan = NULL;
139
+ struct snd_soc_component *component_be = NULL;
140
+ struct fsl_asrc *asrc = pair->asrc;
141141 struct dma_slave_config config_fe, config_be;
142142 enum asrc_pair_index index = pair->index;
143143 struct device *dev = component->dev;
144144 int stream = substream->stream;
145145 struct imx_dma_data *tmp_data;
146146 struct snd_soc_dpcm *dpcm;
147
- struct dma_chan *tmp_chan;
148147 struct device *dev_be;
149148 u8 dir = tx ? OUT : IN;
150149 dma_cap_mask_t mask;
151
- int ret;
150
+ int ret, width;
152151
153152 /* Fetch the Back-End dma_data from DPCM */
154
- list_for_each_entry(dpcm, &rtd->dpcm[stream].be_clients, list_be) {
153
+ for_each_dpcm_be(rtd, stream, dpcm) {
155154 struct snd_soc_pcm_runtime *be = dpcm->be;
156155 struct snd_pcm_substream *substream_be;
157
- struct snd_soc_dai *dai = be->cpu_dai;
156
+ struct snd_soc_dai *dai = asoc_rtd_to_cpu(be, 0);
158157
159158 if (dpcm->fe != rtd)
160159 continue;
....@@ -171,11 +170,11 @@
171170 }
172171
173172 /* Override dma_data of the Front-End and config its dmaengine */
174
- dma_params_fe = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
175
- dma_params_fe->addr = asrc_priv->paddr + REG_ASRDx(!dir, index);
173
+ dma_params_fe = snd_soc_dai_get_dma_data(asoc_rtd_to_cpu(rtd, 0), substream);
174
+ dma_params_fe->addr = asrc->paddr + asrc->get_fifo_addr(!dir, index);
176175 dma_params_fe->maxburst = dma_params_be->maxburst;
177176
178
- pair->dma_chan[!dir] = fsl_asrc_get_dma_channel(pair, !dir);
177
+ pair->dma_chan[!dir] = asrc->get_dma_channel(pair, !dir);
179178 if (!pair->dma_chan[!dir]) {
180179 dev_err(dev, "failed to request DMA channel\n");
181180 return -EINVAL;
....@@ -199,30 +198,66 @@
199198 dma_cap_set(DMA_SLAVE, mask);
200199 dma_cap_set(DMA_CYCLIC, mask);
201200
202
- /* Get DMA request of Back-End */
203
- tmp_chan = dma_request_slave_channel(dev_be, tx ? "tx" : "rx");
204
- tmp_data = tmp_chan->private;
205
- pair->dma_data.dma_request = tmp_data->dma_request;
206
- dma_release_channel(tmp_chan);
201
+ /*
202
+ * The Back-End device might have already requested a DMA channel,
203
+ * so try to reuse it first, and then request a new one upon NULL.
204
+ */
205
+ component_be = snd_soc_lookup_component_nolocked(dev_be, SND_DMAENGINE_PCM_DRV_NAME);
206
+ if (component_be) {
207
+ be_chan = soc_component_to_pcm(component_be)->chan[substream->stream];
208
+ tmp_chan = be_chan;
209
+ }
210
+ if (!tmp_chan)
211
+ tmp_chan = dma_request_slave_channel(dev_be, tx ? "tx" : "rx");
207212
208
- /* Get DMA request of Front-End */
209
- tmp_chan = fsl_asrc_get_dma_channel(pair, dir);
210
- tmp_data = tmp_chan->private;
211
- pair->dma_data.dma_request2 = tmp_data->dma_request;
212
- pair->dma_data.peripheral_type = tmp_data->peripheral_type;
213
- pair->dma_data.priority = tmp_data->priority;
214
- dma_release_channel(tmp_chan);
213
+ /*
214
+ * An EDMA DEV_TO_DEV channel is fixed and bound with DMA event of each
215
+ * peripheral, unlike SDMA channel that is allocated dynamically. So no
216
+ * need to configure dma_request and dma_request2, but get dma_chan of
217
+ * Back-End device directly via dma_request_slave_channel.
218
+ */
219
+ if (!asrc->use_edma) {
220
+ /* Get DMA request of Back-End */
221
+ tmp_data = tmp_chan->private;
222
+ pair->dma_data.dma_request = tmp_data->dma_request;
223
+ if (!be_chan)
224
+ dma_release_channel(tmp_chan);
215225
216
- pair->dma_chan[dir] = dma_request_channel(mask, filter, &pair->dma_data);
226
+ /* Get DMA request of Front-End */
227
+ tmp_chan = asrc->get_dma_channel(pair, dir);
228
+ tmp_data = tmp_chan->private;
229
+ pair->dma_data.dma_request2 = tmp_data->dma_request;
230
+ pair->dma_data.peripheral_type = tmp_data->peripheral_type;
231
+ pair->dma_data.priority = tmp_data->priority;
232
+ dma_release_channel(tmp_chan);
233
+
234
+ pair->dma_chan[dir] =
235
+ dma_request_channel(mask, filter, &pair->dma_data);
236
+ pair->req_dma_chan = true;
237
+ } else {
238
+ pair->dma_chan[dir] = tmp_chan;
239
+ /* Do not flag to release if we are reusing the Back-End one */
240
+ pair->req_dma_chan = !be_chan;
241
+ }
242
+
217243 if (!pair->dma_chan[dir]) {
218244 dev_err(dev, "failed to request DMA channel for Back-End\n");
219245 return -EINVAL;
220246 }
221247
222
- if (asrc_priv->asrc_width == 16)
248
+ width = snd_pcm_format_physical_width(asrc->asrc_format);
249
+ if (width < 8 || width > 64)
250
+ return -EINVAL;
251
+ else if (width == 8)
252
+ buswidth = DMA_SLAVE_BUSWIDTH_1_BYTE;
253
+ else if (width == 16)
223254 buswidth = DMA_SLAVE_BUSWIDTH_2_BYTES;
224
- else
255
+ else if (width == 24)
256
+ buswidth = DMA_SLAVE_BUSWIDTH_3_BYTES;
257
+ else if (width <= 32)
225258 buswidth = DMA_SLAVE_BUSWIDTH_4_BYTES;
259
+ else
260
+ buswidth = DMA_SLAVE_BUSWIDTH_8_BYTES;
226261
227262 config_be.direction = DMA_DEV_TO_DEV;
228263 config_be.src_addr_width = buswidth;
....@@ -231,17 +266,18 @@
231266 config_be.dst_maxburst = dma_params_be->maxburst;
232267
233268 if (tx) {
234
- config_be.src_addr = asrc_priv->paddr + REG_ASRDO(index);
269
+ config_be.src_addr = asrc->paddr + asrc->get_fifo_addr(OUT, index);
235270 config_be.dst_addr = dma_params_be->addr;
236271 } else {
237
- config_be.dst_addr = asrc_priv->paddr + REG_ASRDI(index);
272
+ config_be.dst_addr = asrc->paddr + asrc->get_fifo_addr(IN, index);
238273 config_be.src_addr = dma_params_be->addr;
239274 }
240275
241276 ret = dmaengine_slave_config(pair->dma_chan[dir], &config_be);
242277 if (ret) {
243278 dev_err(dev, "failed to config DMA channel for Back-End\n");
244
- dma_release_channel(pair->dma_chan[dir]);
279
+ if (pair->req_dma_chan)
280
+ dma_release_channel(pair->dma_chan[dir]);
245281 return ret;
246282 }
247283
....@@ -250,69 +286,129 @@
250286 return 0;
251287 }
252288
253
-static int fsl_asrc_dma_hw_free(struct snd_pcm_substream *substream)
289
+static int fsl_asrc_dma_hw_free(struct snd_soc_component *component,
290
+ struct snd_pcm_substream *substream)
254291 {
292
+ bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
255293 struct snd_pcm_runtime *runtime = substream->runtime;
256294 struct fsl_asrc_pair *pair = runtime->private_data;
295
+ u8 dir = tx ? OUT : IN;
257296
258297 snd_pcm_set_runtime_buffer(substream, NULL);
259298
260
- if (pair->dma_chan[IN])
261
- dma_release_channel(pair->dma_chan[IN]);
299
+ if (pair->dma_chan[!dir])
300
+ dma_release_channel(pair->dma_chan[!dir]);
262301
263
- if (pair->dma_chan[OUT])
264
- dma_release_channel(pair->dma_chan[OUT]);
302
+ /* release dev_to_dev chan if we aren't reusing the Back-End one */
303
+ if (pair->dma_chan[dir] && pair->req_dma_chan)
304
+ dma_release_channel(pair->dma_chan[dir]);
265305
266
- pair->dma_chan[IN] = NULL;
267
- pair->dma_chan[OUT] = NULL;
306
+ pair->dma_chan[!dir] = NULL;
307
+ pair->dma_chan[dir] = NULL;
268308
269309 return 0;
270310 }
271311
272
-static int fsl_asrc_dma_startup(struct snd_pcm_substream *substream)
312
+static int fsl_asrc_dma_startup(struct snd_soc_component *component,
313
+ struct snd_pcm_substream *substream)
273314 {
274
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
315
+ bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
316
+ struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
275317 struct snd_pcm_runtime *runtime = substream->runtime;
276
- struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, DRV_NAME);
318
+ struct snd_dmaengine_dai_dma_data *dma_data;
277319 struct device *dev = component->dev;
278
- struct fsl_asrc *asrc_priv = dev_get_drvdata(dev);
320
+ struct fsl_asrc *asrc = dev_get_drvdata(dev);
279321 struct fsl_asrc_pair *pair;
322
+ struct dma_chan *tmp_chan = NULL;
323
+ u8 dir = tx ? OUT : IN;
324
+ bool release_pair = true;
325
+ int ret = 0;
280326
281
- pair = kzalloc(sizeof(struct fsl_asrc_pair), GFP_KERNEL);
327
+ ret = snd_pcm_hw_constraint_integer(substream->runtime,
328
+ SNDRV_PCM_HW_PARAM_PERIODS);
329
+ if (ret < 0) {
330
+ dev_err(dev, "failed to set pcm hw params periods\n");
331
+ return ret;
332
+ }
333
+
334
+ pair = kzalloc(sizeof(*pair) + asrc->pair_priv_size, GFP_KERNEL);
282335 if (!pair)
283336 return -ENOMEM;
284337
285
- pair->asrc_priv = asrc_priv;
338
+ pair->asrc = asrc;
339
+ pair->private = (void *)pair + sizeof(struct fsl_asrc_pair);
286340
287341 runtime->private_data = pair;
288342
289
- snd_pcm_hw_constraint_integer(substream->runtime,
290
- SNDRV_PCM_HW_PARAM_PERIODS);
343
+ /* Request a dummy pair, which will be released later.
344
+ * Request pair function needs channel num as input, for this
345
+ * dummy pair, we just request "1" channel temporarily.
346
+ */
347
+ ret = asrc->request_pair(1, pair);
348
+ if (ret < 0) {
349
+ dev_err(dev, "failed to request asrc pair\n");
350
+ goto req_pair_err;
351
+ }
352
+
353
+ /* Request a dummy dma channel, which will be released later. */
354
+ tmp_chan = asrc->get_dma_channel(pair, dir);
355
+ if (!tmp_chan) {
356
+ dev_err(dev, "failed to get dma channel\n");
357
+ ret = -EINVAL;
358
+ goto dma_chan_err;
359
+ }
360
+
361
+ dma_data = snd_soc_dai_get_dma_data(asoc_rtd_to_cpu(rtd, 0), substream);
362
+
363
+ /* Refine the snd_imx_hardware according to caps of DMA. */
364
+ ret = snd_dmaengine_pcm_refine_runtime_hwparams(substream,
365
+ dma_data,
366
+ &snd_imx_hardware,
367
+ tmp_chan);
368
+ if (ret < 0) {
369
+ dev_err(dev, "failed to refine runtime hwparams\n");
370
+ goto out;
371
+ }
372
+
373
+ release_pair = false;
291374 snd_soc_set_runtime_hwparams(substream, &snd_imx_hardware);
292375
293
- return 0;
376
+out:
377
+ dma_release_channel(tmp_chan);
378
+
379
+dma_chan_err:
380
+ asrc->release_pair(pair);
381
+
382
+req_pair_err:
383
+ if (release_pair)
384
+ kfree(pair);
385
+
386
+ return ret;
294387 }
295388
296
-static int fsl_asrc_dma_shutdown(struct snd_pcm_substream *substream)
389
+static int fsl_asrc_dma_shutdown(struct snd_soc_component *component,
390
+ struct snd_pcm_substream *substream)
297391 {
298392 struct snd_pcm_runtime *runtime = substream->runtime;
299393 struct fsl_asrc_pair *pair = runtime->private_data;
300
- struct fsl_asrc *asrc_priv;
394
+ struct fsl_asrc *asrc;
301395
302396 if (!pair)
303397 return 0;
304398
305
- asrc_priv = pair->asrc_priv;
399
+ asrc = pair->asrc;
306400
307
- if (asrc_priv->pair[pair->index] == pair)
308
- asrc_priv->pair[pair->index] = NULL;
401
+ if (asrc->pair[pair->index] == pair)
402
+ asrc->pair[pair->index] = NULL;
309403
310404 kfree(pair);
311405
312406 return 0;
313407 }
314408
315
-static snd_pcm_uframes_t fsl_asrc_dma_pcm_pointer(struct snd_pcm_substream *substream)
409
+static snd_pcm_uframes_t
410
+fsl_asrc_dma_pcm_pointer(struct snd_soc_component *component,
411
+ struct snd_pcm_substream *substream)
316412 {
317413 struct snd_pcm_runtime *runtime = substream->runtime;
318414 struct fsl_asrc_pair *pair = runtime->private_data;
....@@ -320,17 +416,8 @@
320416 return bytes_to_frames(substream->runtime, pair->pos);
321417 }
322418
323
-static const struct snd_pcm_ops fsl_asrc_dma_pcm_ops = {
324
- .ioctl = snd_pcm_lib_ioctl,
325
- .hw_params = fsl_asrc_dma_hw_params,
326
- .hw_free = fsl_asrc_dma_hw_free,
327
- .trigger = fsl_asrc_dma_trigger,
328
- .open = fsl_asrc_dma_startup,
329
- .close = fsl_asrc_dma_shutdown,
330
- .pointer = fsl_asrc_dma_pcm_pointer,
331
-};
332
-
333
-static int fsl_asrc_dma_pcm_new(struct snd_soc_pcm_runtime *rtd)
419
+static int fsl_asrc_dma_pcm_new(struct snd_soc_component *component,
420
+ struct snd_soc_pcm_runtime *rtd)
334421 {
335422 struct snd_card *card = rtd->card->snd_card;
336423 struct snd_pcm_substream *substream;
....@@ -343,7 +430,7 @@
343430 return ret;
344431 }
345432
346
- for (i = SNDRV_PCM_STREAM_PLAYBACK; i <= SNDRV_PCM_STREAM_LAST; i++) {
433
+ for_each_pcm_streams(i) {
347434 substream = pcm->streams[i].substream;
348435 if (!substream)
349436 continue;
....@@ -365,12 +452,13 @@
365452 return ret;
366453 }
367454
368
-static void fsl_asrc_dma_pcm_free(struct snd_pcm *pcm)
455
+static void fsl_asrc_dma_pcm_free(struct snd_soc_component *component,
456
+ struct snd_pcm *pcm)
369457 {
370458 struct snd_pcm_substream *substream;
371459 int i;
372460
373
- for (i = SNDRV_PCM_STREAM_PLAYBACK; i <= SNDRV_PCM_STREAM_LAST; i++) {
461
+ for_each_pcm_streams(i) {
374462 substream = pcm->streams[i].substream;
375463 if (!substream)
376464 continue;
....@@ -383,8 +471,13 @@
383471
384472 struct snd_soc_component_driver fsl_asrc_component = {
385473 .name = DRV_NAME,
386
- .ops = &fsl_asrc_dma_pcm_ops,
387
- .pcm_new = fsl_asrc_dma_pcm_new,
388
- .pcm_free = fsl_asrc_dma_pcm_free,
474
+ .hw_params = fsl_asrc_dma_hw_params,
475
+ .hw_free = fsl_asrc_dma_hw_free,
476
+ .trigger = fsl_asrc_dma_trigger,
477
+ .open = fsl_asrc_dma_startup,
478
+ .close = fsl_asrc_dma_shutdown,
479
+ .pointer = fsl_asrc_dma_pcm_pointer,
480
+ .pcm_construct = fsl_asrc_dma_pcm_new,
481
+ .pcm_destruct = fsl_asrc_dma_pcm_free,
389482 };
390483 EXPORT_SYMBOL_GPL(fsl_asrc_component);