1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * Rockchip DLP (Digital Loopback) Driver
4 *
5 * Copyright (c) 2022 Rockchip Electronics Co. Ltd.
6 * Author: Sugar Zhang <sugar.zhang@rock-chips.com>
7 *
8 */
9
10 #include <linux/kref.h>
11 #include <linux/module.h>
12 #include <linux/init.h>
13 #include <linux/dmaengine.h>
14 #include <linux/slab.h>
15 #include <sound/pcm.h>
16 #include <sound/pcm_params.h>
17 #include <sound/soc.h>
18 #include <linux/dma-mapping.h>
19 #include <linux/of.h>
20
21 #include <sound/dmaengine_pcm.h>
22 #include "rockchip_dlp.h"
23
24 #ifdef DLP_DBG
25 #define dlp_info(args...) pr_info(args)
26 #else
27 #define dlp_info(args...) no_printk(args)
28 #endif
29
30 #define SND_DMAENGINE_DLP_DRV_NAME "snd_dmaengine_dlp"
31 #define PBUF_CNT 2
32
33 static unsigned int prealloc_buffer_size_kbytes = 512;
34 module_param(prealloc_buffer_size_kbytes, uint, 0444);
35 MODULE_PARM_DESC(prealloc_buffer_size_kbytes, "Preallocate DMA buffer size (KB).");
36
37 /* MUST: dlp_text should be match to enum dlp_mode */
38 static const char *const dlp_text[] = {
39 "Disabled",
40 "2CH: 1 Loopback + 1 Mic",
41 "2CH: 1 Mic + 1 Loopback",
42 "2CH: 1 Mic + 1 Loopback-mixed",
43 "2CH: 2 Loopbacks",
44 "4CH: 2 Mics + 2 Loopbacks",
45 "4CH: 2 Mics + 1 Loopback-mixed",
46 "4CH: 4 Loopbacks",
47 "6CH: 4 Mics + 2 Loopbacks",
48 "6CH: 4 Mics + 1 Loopback-mixed",
49 "6CH: 6 Loopbacks",
50 "8CH: 6 Mics + 2 Loopbacks",
51 "8CH: 6 Mics + 1 Loopback-mixed",
52 "8CH: 8 Loopbacks",
53 "10CH: 8 Mics + 2 Loopbacks",
54 "10CH: 8 Mics + 1 Loopback-mixed",
55 "16CH: 8 Mics + 8 Loopbacks",
56 };
57
58 enum dlp_mode {
59 DLP_MODE_DISABLED,
60 DLP_MODE_2CH_1LP_1MIC, /* replace cap-ch-0 with play-ch-0 */
61 DLP_MODE_2CH_1MIC_1LP, /* replace cap-ch-1 with play-ch-1 */
62 DLP_MODE_2CH_1MIC_1LP_MIX, /* replace cap-ch-1 with play-ch-all-mix */
63 DLP_MODE_2CH_2LP, /* replace cap-ch-0~1 with play-ch-0~1 */
64 DLP_MODE_4CH_2MIC_2LP, /* replace cap-ch-2~3 with play-ch-0~1 */
65 DLP_MODE_4CH_2MIC_1LP_MIX, /* replace cap-ch-3 with play-ch-all-mix */
66 DLP_MODE_4CH_4LP, /* replace cap-ch-0~3 with play-ch-0~3 */
67 DLP_MODE_6CH_4MIC_2LP, /* replace cap-ch-4~5 with play-ch-0~1 */
68 DLP_MODE_6CH_4MIC_1LP_MIX, /* replace cap-ch-4 with play-ch-all-mix */
69 DLP_MODE_6CH_6LP, /* replace cap-ch-0~5 with play-ch-0~5 */
70 DLP_MODE_8CH_6MIC_2LP, /* replace cap-ch-6~7 with play-ch-0~1 */
71 DLP_MODE_8CH_6MIC_1LP_MIX, /* replace cap-ch-6 with play-ch-all-mix */
72 DLP_MODE_8CH_8LP, /* replace cap-ch-0~7 with play-ch-0~7 */
73 DLP_MODE_10CH_8MIC_2LP, /* replace cap-ch-8~9 with play-ch-0~1 */
74 DLP_MODE_10CH_8MIC_1LP_MIX, /* replace cap-ch-8 with play-ch-all-mix */
75 DLP_MODE_16CH_8MIC_8LP, /* replace cap-ch-8~f with play-ch-8~f */
76 };
77
78 struct dmaengine_dlp_runtime_data;
79 struct dmaengine_dlp {
80 struct device *dev;
81 struct dma_chan *chan[SNDRV_PCM_STREAM_LAST + 1];
82 const struct snd_dlp_config *config;
83 struct snd_soc_component component;
84 struct list_head ref_list;
85 enum dlp_mode mode;
86 struct dmaengine_dlp_runtime_data *pref;
87 spinlock_t lock;
88 spinlock_t pref_lock;
89 };
90
91 struct dmaengine_dlp_runtime_data {
92 struct dmaengine_dlp *parent;
93 struct dmaengine_dlp_runtime_data *ref;
94 struct dma_chan *dma_chan;
95 struct kref refcount;
96 struct list_head node;
97 dma_cookie_t cookie;
98
99 char *buf;
100 snd_pcm_uframes_t buf_sz;
101 snd_pcm_uframes_t period_sz;
102 snd_pcm_uframes_t hw_ptr;
103 snd_pcm_sframes_t hw_ptr_delta; /* play-ptr - cap-ptr */
104 unsigned long period_elapsed;
105 unsigned int frame_bytes;
106 unsigned int channels;
107 unsigned int buf_ofs;
108 int stream;
109 };
110
dlp_activate(struct dmaengine_dlp * dlp)111 static inline void dlp_activate(struct dmaengine_dlp *dlp)
112 {
113 spin_lock(&dlp->lock);
114 dlp->component.active++;
115 spin_unlock(&dlp->lock);
116 }
117
dlp_deactivate(struct dmaengine_dlp * dlp)118 static inline void dlp_deactivate(struct dmaengine_dlp *dlp)
119 {
120 spin_lock(&dlp->lock);
121 dlp->component.active--;
122 spin_unlock(&dlp->lock);
123 }
124
dlp_mode_channels_match(struct dmaengine_dlp * dlp,int ch,int * expected)125 static inline bool dlp_mode_channels_match(struct dmaengine_dlp *dlp,
126 int ch, int *expected)
127 {
128 *expected = 0;
129
130 switch (dlp->mode) {
131 case DLP_MODE_DISABLED:
132 return true;
133 case DLP_MODE_2CH_1LP_1MIC:
134 case DLP_MODE_2CH_1MIC_1LP:
135 case DLP_MODE_2CH_1MIC_1LP_MIX:
136 case DLP_MODE_2CH_2LP:
137 *expected = 2;
138 return (ch == 2);
139 case DLP_MODE_4CH_2MIC_2LP:
140 case DLP_MODE_4CH_2MIC_1LP_MIX:
141 case DLP_MODE_4CH_4LP:
142 *expected = 4;
143 return (ch == 4);
144 case DLP_MODE_6CH_4MIC_2LP:
145 case DLP_MODE_6CH_4MIC_1LP_MIX:
146 case DLP_MODE_6CH_6LP:
147 *expected = 6;
148 return (ch == 6);
149 case DLP_MODE_8CH_6MIC_2LP:
150 case DLP_MODE_8CH_6MIC_1LP_MIX:
151 case DLP_MODE_8CH_8LP:
152 *expected = 8;
153 return (ch == 8);
154 case DLP_MODE_10CH_8MIC_2LP:
155 case DLP_MODE_10CH_8MIC_1LP_MIX:
156 *expected = 10;
157 return (ch == 10);
158 case DLP_MODE_16CH_8MIC_8LP:
159 *expected = 16;
160 return (ch == 16);
161 default:
162 return false;
163 }
164 }
165
dlp_channels_to_bytes(struct dmaengine_dlp_runtime_data * prtd,int channels)166 static inline ssize_t dlp_channels_to_bytes(struct dmaengine_dlp_runtime_data *prtd,
167 int channels)
168 {
169 return (prtd->frame_bytes / prtd->channels) * channels;
170 }
171
dlp_frames_to_bytes(struct dmaengine_dlp_runtime_data * prtd,snd_pcm_sframes_t size)172 static inline ssize_t dlp_frames_to_bytes(struct dmaengine_dlp_runtime_data *prtd,
173 snd_pcm_sframes_t size)
174 {
175 return size * prtd->frame_bytes;
176 }
177
dlp_bytes_to_frames(struct dmaengine_dlp_runtime_data * prtd,ssize_t size)178 static inline snd_pcm_sframes_t dlp_bytes_to_frames(struct dmaengine_dlp_runtime_data *prtd,
179 ssize_t size)
180 {
181 return size / prtd->frame_bytes;
182 }
183
soc_component_to_dlp(struct snd_soc_component * p)184 static inline struct dmaengine_dlp *soc_component_to_dlp(struct snd_soc_component *p)
185 {
186 return container_of(p, struct dmaengine_dlp, component);
187 }
188
substream_to_prtd(const struct snd_pcm_substream * substream)189 static inline struct dmaengine_dlp_runtime_data *substream_to_prtd(
190 const struct snd_pcm_substream *substream)
191 {
192 if (!substream->runtime)
193 return NULL;
194
195 return substream->runtime->private_data;
196 }
197
snd_dmaengine_dlp_get_chan(struct snd_pcm_substream * substream)198 static struct dma_chan *snd_dmaengine_dlp_get_chan(struct snd_pcm_substream *substream)
199 {
200 struct dmaengine_dlp_runtime_data *prtd = substream_to_prtd(substream);
201
202 return prtd->dma_chan;
203 }
204
dmaengine_dma_dev(struct dmaengine_dlp * dlp,struct snd_pcm_substream * substream)205 static struct device *dmaengine_dma_dev(struct dmaengine_dlp *dlp,
206 struct snd_pcm_substream *substream)
207 {
208 if (!dlp->chan[substream->stream])
209 return NULL;
210
211 return dlp->chan[substream->stream]->device->dev;
212 }
213
dlp_get_offset_size(struct dmaengine_dlp_runtime_data * prtd,enum dlp_mode mode,int * ofs,int * size,bool * mix)214 static int dlp_get_offset_size(struct dmaengine_dlp_runtime_data *prtd,
215 enum dlp_mode mode, int *ofs, int *size, bool *mix)
216 {
217 bool is_playback = prtd->stream == SNDRV_PCM_STREAM_PLAYBACK;
218 int ret = 0;
219
220 switch (mode) {
221 case DLP_MODE_2CH_1LP_1MIC:
222 *ofs = 0;
223 *size = dlp_channels_to_bytes(prtd, 1);
224 break;
225 case DLP_MODE_2CH_1MIC_1LP:
226 *ofs = dlp_channels_to_bytes(prtd, 1);
227 *size = dlp_channels_to_bytes(prtd, 1);
228 break;
229 case DLP_MODE_2CH_1MIC_1LP_MIX:
230 if (is_playback) {
231 *ofs = 0;
232 *size = dlp_frames_to_bytes(prtd, 1);
233 if (mix)
234 *mix = true;
235 } else {
236 *ofs = dlp_channels_to_bytes(prtd, 1);
237 *size = dlp_channels_to_bytes(prtd, 1);
238 }
239 break;
240 case DLP_MODE_2CH_2LP:
241 *ofs = 0;
242 *size = dlp_channels_to_bytes(prtd, 2);
243 break;
244 case DLP_MODE_4CH_2MIC_2LP:
245 if (is_playback) {
246 *ofs = 0;
247 *size = dlp_channels_to_bytes(prtd, 2);
248 } else {
249 *ofs = dlp_channels_to_bytes(prtd, 2);
250 *size = dlp_channels_to_bytes(prtd, 2);
251 }
252 break;
253 case DLP_MODE_4CH_2MIC_1LP_MIX:
254 if (is_playback) {
255 *ofs = 0;
256 *size = dlp_frames_to_bytes(prtd, 1);
257 if (mix)
258 *mix = true;
259 } else {
260 *ofs = dlp_channels_to_bytes(prtd, 2);
261 *size = dlp_channels_to_bytes(prtd, 1);
262 }
263 break;
264 case DLP_MODE_4CH_4LP:
265 *ofs = 0;
266 *size = dlp_channels_to_bytes(prtd, 4);
267 break;
268 case DLP_MODE_6CH_4MIC_2LP:
269 if (is_playback) {
270 *ofs = 0;
271 *size = dlp_channels_to_bytes(prtd, 2);
272 } else {
273 *ofs = dlp_channels_to_bytes(prtd, 4);
274 *size = dlp_channels_to_bytes(prtd, 2);
275 }
276 break;
277 case DLP_MODE_6CH_4MIC_1LP_MIX:
278 if (is_playback) {
279 *ofs = 0;
280 *size = dlp_frames_to_bytes(prtd, 1);
281 if (mix)
282 *mix = true;
283 } else {
284 *ofs = dlp_channels_to_bytes(prtd, 4);
285 *size = dlp_channels_to_bytes(prtd, 1);
286 }
287 break;
288 case DLP_MODE_6CH_6LP:
289 *ofs = 0;
290 *size = dlp_channels_to_bytes(prtd, 6);
291 break;
292 case DLP_MODE_8CH_6MIC_2LP:
293 if (is_playback) {
294 *ofs = 0;
295 *size = dlp_channels_to_bytes(prtd, 2);
296 } else {
297 *ofs = dlp_channels_to_bytes(prtd, 6);
298 *size = dlp_channels_to_bytes(prtd, 2);
299 }
300 break;
301 case DLP_MODE_8CH_6MIC_1LP_MIX:
302 if (is_playback) {
303 *ofs = 0;
304 *size = dlp_frames_to_bytes(prtd, 1);
305 if (mix)
306 *mix = true;
307 } else {
308 *ofs = dlp_channels_to_bytes(prtd, 6);
309 *size = dlp_channels_to_bytes(prtd, 1);
310 }
311 break;
312 case DLP_MODE_8CH_8LP:
313 *ofs = 0;
314 *size = dlp_channels_to_bytes(prtd, 8);
315 break;
316 case DLP_MODE_10CH_8MIC_2LP:
317 if (is_playback) {
318 *ofs = 0;
319 *size = dlp_channels_to_bytes(prtd, 2);
320 } else {
321 *ofs = dlp_channels_to_bytes(prtd, 8);
322 *size = dlp_channels_to_bytes(prtd, 2);
323 }
324 break;
325 case DLP_MODE_10CH_8MIC_1LP_MIX:
326 if (is_playback) {
327 *ofs = 0;
328 *size = dlp_frames_to_bytes(prtd, 1);
329 if (mix)
330 *mix = true;
331 } else {
332 *ofs = dlp_channels_to_bytes(prtd, 8);
333 *size = dlp_channels_to_bytes(prtd, 1);
334 }
335 break;
336 case DLP_MODE_16CH_8MIC_8LP:
337 if (is_playback) {
338 *ofs = 0;
339 *size = dlp_channels_to_bytes(prtd, 8);
340 } else {
341 *ofs = dlp_channels_to_bytes(prtd, 8);
342 *size = dlp_channels_to_bytes(prtd, 8);
343 }
344 break;
345 default:
346 *ofs = 0;
347 *size = 0;
348 if (mix)
349 *mix = false;
350 ret = -EINVAL;
351 }
352
353 return ret;
354 }
355
dlp_mix_frame_buffer(struct dmaengine_dlp_runtime_data * prtd,void * buf)356 static int dlp_mix_frame_buffer(struct dmaengine_dlp_runtime_data *prtd, void *buf)
357 {
358 int sample_bytes = dlp_channels_to_bytes(prtd, 1);
359 int16_t *p16 = (int16_t *)buf, v16 = 0;
360 int32_t *p32 = (int32_t *)buf, v32 = 0;
361 int i = 0;
362
363 switch (sample_bytes) {
364 case 2:
365 for (i = 0; i < prtd->channels; i++)
366 v16 += (p16[i] / prtd->channels);
367 p16[0] = v16;
368 break;
369 case 4:
370 for (i = 0; i < prtd->channels; i++)
371 v32 += (p32[i] / prtd->channels);
372 p32[0] = v32;
373 break;
374 default:
375 return -EINVAL;
376 }
377
378 return 0;
379 }
380
dmaengine_dlp_hw_params(struct snd_soc_component * component,struct snd_pcm_substream * substream,struct snd_pcm_hw_params * params)381 static int dmaengine_dlp_hw_params(struct snd_soc_component *component,
382 struct snd_pcm_substream *substream,
383 struct snd_pcm_hw_params *params)
384 {
385 struct dmaengine_dlp *dlp = soc_component_to_dlp(component);
386 struct dmaengine_dlp_runtime_data *prtd = substream_to_prtd(substream);
387 struct dma_chan *chan = snd_dmaengine_dlp_get_chan(substream);
388 struct dma_slave_config slave_config;
389 bool is_playback = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
390 int ch_req = params_channels(params), ch_exp = 0;
391 int ret;
392
393 /* mode should match to channels */
394 if (!is_playback && !dlp_mode_channels_match(dlp, ch_req, &ch_exp)) {
395 dev_err(dlp->dev,
396 "capture %d ch, expected: %d ch for loopback mode-%d\n",
397 ch_req, ch_exp, dlp->mode);
398 return -EINVAL;
399 }
400
401 memset(&slave_config, 0, sizeof(slave_config));
402
403 ret = snd_dmaengine_pcm_prepare_slave_config(substream, params, &slave_config);
404 if (ret)
405 return ret;
406
407 ret = dmaengine_slave_config(chan, &slave_config);
408 if (ret)
409 return ret;
410
411 prtd->frame_bytes = snd_pcm_format_size(params_format(params),
412 params_channels(params));
413 prtd->period_sz = params_period_size(params);
414 prtd->buf_sz = params_buffer_size(params);
415 prtd->channels = params_channels(params);
416
417 if (is_playback)
418 prtd->buf_sz *= PBUF_CNT;
419
420 return 0;
421 }
422
423 static int
dmaengine_pcm_set_runtime_hwparams(struct snd_soc_component * component,struct snd_pcm_substream * substream)424 dmaengine_pcm_set_runtime_hwparams(struct snd_soc_component *component,
425 struct snd_pcm_substream *substream)
426 {
427 struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
428 struct dmaengine_dlp *dlp = soc_component_to_dlp(component);
429 struct device *dma_dev = dmaengine_dma_dev(dlp, substream);
430 struct dma_chan *chan = dlp->chan[substream->stream];
431 struct snd_dmaengine_dai_dma_data *dma_data;
432 struct snd_pcm_hardware hw;
433
434 if (rtd->num_cpus > 1) {
435 dev_err(rtd->dev,
436 "%s doesn't support Multi CPU yet\n", __func__);
437 return -EINVAL;
438 }
439
440 dma_data = snd_soc_dai_get_dma_data(asoc_rtd_to_cpu(rtd, 0), substream);
441
442 memset(&hw, 0, sizeof(hw));
443 hw.info = SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID |
444 SNDRV_PCM_INFO_INTERLEAVED;
445 hw.periods_min = 2;
446 hw.periods_max = UINT_MAX;
447 hw.period_bytes_min = 256;
448 hw.period_bytes_max = dma_get_max_seg_size(dma_dev);
449 hw.buffer_bytes_max = SIZE_MAX;
450 hw.fifo_size = dma_data->fifo_size;
451
452 /**
453 * FIXME: Remove the return value check to align with the code
454 * before adding snd_dmaengine_pcm_refine_runtime_hwparams
455 * function.
456 */
457 snd_dmaengine_pcm_refine_runtime_hwparams(substream,
458 dma_data,
459 &hw,
460 chan);
461
462 return snd_soc_set_runtime_hwparams(substream, &hw);
463 }
464
dmaengine_dlp_open(struct snd_soc_component * component,struct snd_pcm_substream * substream)465 static int dmaengine_dlp_open(struct snd_soc_component *component,
466 struct snd_pcm_substream *substream)
467 {
468 struct dmaengine_dlp *dlp = soc_component_to_dlp(component);
469 struct dma_chan *chan = dlp->chan[substream->stream];
470 struct dmaengine_dlp_runtime_data *prtd;
471 int ret;
472
473 if (!chan)
474 return -ENXIO;
475
476 ret = dmaengine_pcm_set_runtime_hwparams(component, substream);
477 if (ret)
478 return ret;
479
480 ret = snd_pcm_hw_constraint_integer(substream->runtime,
481 SNDRV_PCM_HW_PARAM_PERIODS);
482 if (ret < 0)
483 return ret;
484
485 prtd = kzalloc(sizeof(*prtd), GFP_KERNEL);
486 if (!prtd)
487 return -ENOMEM;
488
489 dlp_info("PRTD-CREATE: 0x%px (%s)\n",
490 prtd, substream->stream ? "C" : "P");
491
492 kref_init(&prtd->refcount);
493 prtd->parent = dlp;
494 prtd->stream = substream->stream;
495 prtd->dma_chan = chan;
496
497 substream->runtime->private_data = prtd;
498
499 dlp_activate(dlp);
500
501 return 0;
502 }
503
dmaengine_free_prtd(struct kref * ref)504 static void dmaengine_free_prtd(struct kref *ref)
505 {
506 struct dmaengine_dlp_runtime_data *prtd =
507 container_of(ref, struct dmaengine_dlp_runtime_data, refcount);
508
509 dlp_info("PRTD-FREE: 0x%px\n", prtd);
510
511 kfree(prtd->buf);
512 kfree(prtd);
513 }
514
free_ref_list(struct snd_soc_component * component)515 static void free_ref_list(struct snd_soc_component *component)
516 {
517 struct dmaengine_dlp *dlp = soc_component_to_dlp(component);
518 struct dmaengine_dlp_runtime_data *prtd, *_pt;
519
520 spin_lock(&dlp->lock);
521 list_for_each_entry_safe(prtd, _pt, &dlp->ref_list, node) {
522 list_del(&prtd->node);
523 kref_put(&prtd->refcount, dmaengine_free_prtd);
524 }
525 spin_unlock(&dlp->lock);
526 }
527
dmaengine_dlp_close(struct snd_soc_component * component,struct snd_pcm_substream * substream)528 static int dmaengine_dlp_close(struct snd_soc_component *component,
529 struct snd_pcm_substream *substream)
530 {
531 struct dmaengine_dlp *dlp = soc_component_to_dlp(component);
532 struct dmaengine_dlp_runtime_data *prtd = substream_to_prtd(substream);
533
534 dmaengine_synchronize(prtd->dma_chan);
535
536 /*
537 * kref put should be after hw_ptr updated when stop,
538 * ops->trigger: SNDRV_PCM_TRIGGER_STOP -> ops->close
539 * obviously, it is!
540 */
541 kref_put(&prtd->refcount, dmaengine_free_prtd);
542
543 dlp_deactivate(dlp);
544
545 return 0;
546 }
547
dmaengine_dlp_pointer(struct snd_soc_component * component,struct snd_pcm_substream * substream)548 static snd_pcm_uframes_t dmaengine_dlp_pointer(
549 struct snd_soc_component *component,
550 struct snd_pcm_substream *substream)
551 {
552 struct dmaengine_dlp_runtime_data *prtd = substream_to_prtd(substream);
553 struct dma_tx_state state;
554 unsigned int buf_size;
555 unsigned int pos = 0;
556
557 dmaengine_tx_status(prtd->dma_chan, prtd->cookie, &state);
558 buf_size = snd_pcm_lib_buffer_bytes(substream);
559 if (state.residue > 0 && state.residue <= buf_size)
560 pos = buf_size - state.residue;
561
562 return dlp_bytes_to_frames(prtd, pos);
563 }
564
dmaengine_dlp_dma_complete(void * arg)565 static void dmaengine_dlp_dma_complete(void *arg)
566 {
567 struct snd_pcm_substream *substream = arg;
568 struct dmaengine_dlp_runtime_data *prtd = substream_to_prtd(substream);
569 struct dmaengine_dlp *dlp = prtd->parent;
570
571 if (!substream->runtime)
572 return;
573
574 spin_lock(&dlp->lock);
575 prtd->period_elapsed++;
576 prtd->hw_ptr = prtd->period_elapsed * prtd->period_sz;
577 spin_unlock(&dlp->lock);
578 snd_pcm_period_elapsed(substream);
579 }
580
dmaengine_dlp_prepare_and_submit(struct snd_pcm_substream * substream)581 static int dmaengine_dlp_prepare_and_submit(struct snd_pcm_substream *substream)
582 {
583 struct dmaengine_dlp_runtime_data *prtd = substream_to_prtd(substream);
584 struct dma_chan *chan = prtd->dma_chan;
585 struct dma_async_tx_descriptor *desc;
586 enum dma_transfer_direction direction;
587 unsigned long flags = DMA_CTRL_ACK;
588
589 direction = snd_pcm_substream_to_dma_direction(substream);
590
591 if (!substream->runtime->no_period_wakeup)
592 flags |= DMA_PREP_INTERRUPT;
593
594 desc = dmaengine_prep_dma_cyclic(chan,
595 substream->runtime->dma_addr,
596 snd_pcm_lib_buffer_bytes(substream),
597 snd_pcm_lib_period_bytes(substream), direction, flags);
598
599 if (!desc)
600 return -ENOMEM;
601
602 desc->callback = dmaengine_dlp_dma_complete;
603 desc->callback_param = substream;
604 prtd->cookie = dmaengine_submit(desc);
605
606 return 0;
607 }
608
dmaengine_dlp_setup(struct snd_soc_component * component,struct snd_pcm_substream * substream)609 static int dmaengine_dlp_setup(struct snd_soc_component *component,
610 struct snd_pcm_substream *substream)
611 {
612 struct dmaengine_dlp *dlp = soc_component_to_dlp(component);
613 int bstream = SNDRV_PCM_STREAM_LAST - substream->stream;
614 struct snd_pcm_str *bro = &substream->pcm->streams[bstream];
615 struct snd_pcm_substream *bsubstream = bro->substream;
616 struct dmaengine_dlp_runtime_data *prtd = substream_to_prtd(substream);
617 struct dmaengine_dlp_runtime_data *brtd = substream_to_prtd(bsubstream);
618 struct dmaengine_dlp_runtime_data *pref = dlp->pref;
619 bool is_playback = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
620 snd_pcm_uframes_t a = 0, b = 0, fifo_a = 0, fifo_b = 0;
621 snd_pcm_sframes_t delta = 0;
622
623 if (dlp->mode == DLP_MODE_DISABLED)
624 return -EINVAL;
625
626 fifo_a = dlp->config->get_fifo_count(dlp->dev, substream->stream);
627 a = dmaengine_dlp_pointer(component, substream);
628
629 if (bsubstream->runtime && snd_pcm_running(bsubstream)) {
630 fifo_b = dlp->config->get_fifo_count(dlp->dev, bstream);
631 b = dmaengine_dlp_pointer(component, bsubstream);
632
633 spin_lock(&dlp->lock);
634 if (!pref) {
635 spin_unlock(&dlp->lock);
636 return -EINVAL;
637 }
638
639 a = (prtd->period_elapsed * prtd->period_sz) + (a % prtd->period_sz);
640 b = (brtd->period_elapsed * brtd->period_sz) + (b % brtd->period_sz);
641
642 fifo_a = dlp_bytes_to_frames(prtd, fifo_a * 4);
643 fifo_b = dlp_bytes_to_frames(brtd, fifo_b * 4);
644
645 delta = is_playback ? (a - fifo_a) - (b + fifo_b) : (b - fifo_b) - (a + fifo_a);
646
647 pref->hw_ptr_delta = delta;
648 kref_get(&pref->refcount);
649 /* push valid playback into ref list */
650 list_add_tail(&pref->node, &dlp->ref_list);
651
652 spin_unlock(&dlp->lock);
653 }
654
655 if (is_playback)
656 dlp_info("START-P: DMA-P: %lu, DMA-C: %lu, FIFO-P: %lu, FIFO-C: %lu, DELTA: %ld\n",
657 a, b, fifo_a, fifo_b, delta);
658 else
659 dlp_info("START-C: DMA-P: %lu, DMA-C: %lu, FIFO-P: %lu, FIFO-C: %lu, DELTA: %ld\n",
660 b, a, fifo_b, fifo_a, delta);
661
662 return 0;
663 }
664
dmaengine_dlp_release(struct snd_soc_component * component,struct snd_pcm_substream * substream)665 static void dmaengine_dlp_release(struct snd_soc_component *component,
666 struct snd_pcm_substream *substream)
667 {
668 struct dmaengine_dlp *dlp = soc_component_to_dlp(component);
669 struct dmaengine_dlp_runtime_data *prtd = substream_to_prtd(substream);
670 struct dmaengine_dlp_runtime_data *pref = dlp->pref;
671 struct snd_pcm_runtime *runtime = substream->runtime;
672 snd_pcm_uframes_t appl_ptr, hw_ptr;
673
674 if (dlp->mode == DLP_MODE_DISABLED)
675 return;
676
677 /* any data in FIFOs will be gone ,so don't care */
678 appl_ptr = READ_ONCE(runtime->control->appl_ptr);
679 hw_ptr = dmaengine_dlp_pointer(component, substream);
680 spin_lock(&dlp->lock);
681 hw_ptr = (prtd->period_elapsed * prtd->period_sz) + (hw_ptr % prtd->period_sz);
682 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
683 pref->hw_ptr = min(hw_ptr, appl_ptr);
684 prtd->period_elapsed = 0;
685 prtd->hw_ptr = 0;
686 spin_unlock(&dlp->lock);
687
688 /*
689 * playback:
690 *
691 * snd_pcm_drop: hw_ptr will be smaller than appl_ptr
692 * snd_pcm_drain, hw_ptr will be equal to appl_ptr
693 *
694 * anyway, we should use the smaller one, obviously, it's hw_ptr.
695 */
696 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
697 spin_lock(&dlp->pref_lock);
698 kref_put(&pref->refcount, dmaengine_free_prtd);
699 dlp->pref = NULL;
700 spin_unlock(&dlp->pref_lock);
701 dlp_info("STOP-P: applptr: %lu, hwptr: %lu\n", appl_ptr, hw_ptr);
702 } else {
703 /* free residue playback ref list for capture when stop */
704 free_ref_list(component);
705 dlp_info("STOP-C: applptr: %lu, hwptr: %lu\n", appl_ptr, hw_ptr);
706 }
707 }
708
dmaengine_dlp_trigger(struct snd_soc_component * component,struct snd_pcm_substream * substream,int cmd)709 static int dmaengine_dlp_trigger(struct snd_soc_component *component,
710 struct snd_pcm_substream *substream, int cmd)
711 {
712 struct dmaengine_dlp_runtime_data *prtd = substream_to_prtd(substream);
713 struct snd_pcm_runtime *runtime = substream->runtime;
714 int ret;
715
716 switch (cmd) {
717 case SNDRV_PCM_TRIGGER_START:
718 ret = dmaengine_dlp_prepare_and_submit(substream);
719 if (ret)
720 return ret;
721 dma_async_issue_pending(prtd->dma_chan);
722 dmaengine_dlp_setup(component, substream);
723 break;
724 case SNDRV_PCM_TRIGGER_RESUME:
725 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
726 dmaengine_resume(prtd->dma_chan);
727 break;
728 case SNDRV_PCM_TRIGGER_SUSPEND:
729 if (runtime->info & SNDRV_PCM_INFO_PAUSE) {
730 dmaengine_pause(prtd->dma_chan);
731 } else {
732 dmaengine_dlp_release(component, substream);
733 dmaengine_terminate_async(prtd->dma_chan);
734 }
735 break;
736 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
737 dmaengine_pause(prtd->dma_chan);
738 break;
739 case SNDRV_PCM_TRIGGER_STOP:
740 dmaengine_dlp_release(component, substream);
741 dmaengine_terminate_async(prtd->dma_chan);
742 break;
743 default:
744 return -EINVAL;
745 }
746
747 return 0;
748 }
749
dmaengine_dlp_new(struct snd_soc_component * component,struct snd_soc_pcm_runtime * rtd)750 static int dmaengine_dlp_new(struct snd_soc_component *component,
751 struct snd_soc_pcm_runtime *rtd)
752 {
753 struct dmaengine_dlp *dlp = soc_component_to_dlp(component);
754 struct snd_pcm_substream *substream;
755 size_t prealloc_buffer_size;
756 size_t max_buffer_size;
757 unsigned int i;
758
759 prealloc_buffer_size = prealloc_buffer_size_kbytes * 1024;
760 max_buffer_size = SIZE_MAX;
761
762 for_each_pcm_streams(i) {
763 substream = rtd->pcm->streams[i].substream;
764 if (!substream)
765 continue;
766
767 if (!dlp->chan[i]) {
768 dev_err(component->dev,
769 "Missing dma channel for stream: %d\n", i);
770 return -EINVAL;
771 }
772
773 snd_pcm_set_managed_buffer(substream,
774 SNDRV_DMA_TYPE_DEV_IRAM,
775 dmaengine_dma_dev(dlp, substream),
776 prealloc_buffer_size,
777 max_buffer_size);
778
779 if (rtd->pcm->streams[i].pcm->name[0] == '\0') {
780 strscpy_pad(rtd->pcm->streams[i].pcm->name,
781 rtd->pcm->streams[i].pcm->id,
782 sizeof(rtd->pcm->streams[i].pcm->name));
783 }
784 }
785
786 return 0;
787 }
788
get_ref(struct snd_soc_component * component)789 static struct dmaengine_dlp_runtime_data *get_ref(struct snd_soc_component *component)
790 {
791 struct dmaengine_dlp *dlp = soc_component_to_dlp(component);
792 struct dmaengine_dlp_runtime_data *pref = NULL;
793
794 spin_lock(&dlp->lock);
795 if (!list_empty(&dlp->ref_list)) {
796 pref = list_first_entry(&dlp->ref_list, struct dmaengine_dlp_runtime_data, node);
797 list_del(&pref->node);
798 }
799 spin_unlock(&dlp->lock);
800
801 return pref;
802 }
803
process_capture(struct snd_soc_component * component,struct snd_pcm_substream * substream,unsigned long hwoff,void __user * buf,unsigned long bytes)804 static int process_capture(struct snd_soc_component *component,
805 struct snd_pcm_substream *substream,
806 unsigned long hwoff,
807 void __user *buf, unsigned long bytes)
808 {
809 struct dmaengine_dlp *dlp = soc_component_to_dlp(component);
810 struct snd_pcm_runtime *runtime = substream->runtime;
811 struct dmaengine_dlp_runtime_data *prtd = substream_to_prtd(substream);
812 struct dmaengine_dlp_runtime_data *pref = NULL;
813 void *dma_ptr = runtime->dma_area + hwoff;
814 snd_pcm_sframes_t frames = dlp_bytes_to_frames(prtd, bytes);
815 snd_pcm_sframes_t frames_consumed = 0, frames_residue = 0, frames_tmp = 0;
816 snd_pcm_sframes_t ofs = 0;
817 snd_pcm_uframes_t appl_ptr;
818 char *cbuf = prtd->buf, *pbuf = NULL;
819 int ofs_cap, ofs_play, size_cap, size_play;
820 int i = 0, j = 0, ret = 0;
821 bool free_ref = false, mix = false;
822
823 appl_ptr = READ_ONCE(runtime->control->appl_ptr);
824
825 memcpy(cbuf, dma_ptr, bytes);
826 #ifdef DLP_DBG
827 /* DBG: mark STUB in ch-REC for trace each read */
828 memset(cbuf, 0x22, dlp_channels_to_bytes(prtd, 1));
829 #endif
830 ret = dlp_get_offset_size(prtd, dlp->mode, &ofs_cap, &size_cap, NULL);
831 if (ret) {
832 dlp_info("fail to get dlp cap offset\n");
833 return -EINVAL;
834 }
835
836 /* clear channel-LP_CHN */
837 for (i = 0; i < frames; i++) {
838 cbuf = prtd->buf + dlp_frames_to_bytes(prtd, i) + ofs_cap;
839 memset(cbuf, 0x0, size_cap);
840 }
841
842 start:
843 if (!prtd->ref)
844 prtd->ref = get_ref(component);
845 pref = prtd->ref;
846
847 /* do nothing if play stop */
848 if (!pref)
849 return 0;
850
851 ret = dlp_get_offset_size(pref, dlp->mode, &ofs_play, &size_play, &mix);
852 if (ret) {
853 dlp_info("fail to get dlp play offset\n");
854 return 0;
855 }
856
857 ofs = appl_ptr + pref->hw_ptr_delta;
858
859 /*
860 * if playback stop, kref_put ref, and we can check this to
861 * know if playback stopped, then free prtd->ref if data consumed.
862 *
863 */
864 if (kref_read(&pref->refcount) == 1) {
865 if (ofs >= pref->hw_ptr) {
866 kref_put(&pref->refcount, dmaengine_free_prtd);
867 prtd->ref = NULL;
868 return 0;
869 } else if ((ofs + frames) > pref->hw_ptr) {
870 dlp_info("applptr: %8lu, ofs': %7ld, refhwptr: %lu, frames: %lu (*)\n",
871 appl_ptr, ofs, pref->hw_ptr, frames);
872 /*
873 * should ignore the data that after play stop
874 * and care about if the next ref start in the
875 * same window
876 */
877 frames_tmp = pref->hw_ptr - ofs;
878 frames_residue = frames - frames_tmp;
879 frames = frames_tmp;
880 free_ref = true;
881 }
882 }
883
884 /*
885 * should ignore the data that before play start:
886 *
887 * frames:
888 * +---------------------------------------------+
889 * | ofs<0 | ofs>0 |
890 * +---------------------------------------------+
891 *
892 */
893 if ((ofs + frames) <= 0)
894 return 0;
895
896 /* skip if ofs < 0 and fixup ofs */
897 j = 0;
898 if (ofs < 0) {
899 dlp_info("applptr: %8lu, ofs: %8ld, frames: %lu (*)\n",
900 appl_ptr, ofs, frames);
901 j = -ofs;
902 frames += ofs;
903 ofs = 0;
904 }
905
906 ofs %= pref->buf_sz;
907
908 dlp_info("applptr: %8lu, ofs: %8ld, frames: %lu\n", appl_ptr, ofs, frames);
909
910 for (i = 0; i < frames; i++, j++) {
911 cbuf = prtd->buf + dlp_frames_to_bytes(prtd, j + frames_consumed) + ofs_cap;
912 pbuf = pref->buf + dlp_frames_to_bytes(pref, ((i + ofs) % pref->buf_sz)) + ofs_play;
913 if (mix)
914 dlp_mix_frame_buffer(pref, pbuf);
915 memcpy(cbuf, pbuf, size_cap);
916 }
917
918 appl_ptr += frames;
919 frames_consumed += frames;
920
921 if (free_ref) {
922 kref_put(&pref->refcount, dmaengine_free_prtd);
923 prtd->ref = NULL;
924 free_ref = false;
925 if (frames_residue) {
926 frames = frames_residue;
927 frames_residue = 0;
928 goto start;
929 }
930 }
931
932 return 0;
933 }
934
process_playback(struct snd_soc_component * component,struct snd_pcm_substream * substream,unsigned long hwoff,void __user * buf,unsigned long bytes)935 static int process_playback(struct snd_soc_component *component,
936 struct snd_pcm_substream *substream,
937 unsigned long hwoff,
938 void __user *buf, unsigned long bytes)
939 {
940 struct dmaengine_dlp *dlp = soc_component_to_dlp(component);
941 struct dmaengine_dlp_runtime_data *pref;
942 char *pbuf;
943 int ret = 0;
944
945 spin_lock(&dlp->pref_lock);
946 pref = dlp->pref;
947 if (!pref) {
948 ret = -EFAULT;
949 goto err_unlock;
950 }
951
952 pbuf = pref->buf + pref->buf_ofs;
953
954 if (copy_from_user(pbuf, buf, bytes)) {
955 ret = -EFAULT;
956 goto err_unlock;
957 }
958
959 pref->buf_ofs += bytes;
960 pref->buf_ofs %= dlp_frames_to_bytes(pref, pref->buf_sz);
961
962 err_unlock:
963 spin_unlock(&dlp->pref_lock);
964
965 return ret;
966 }
967
dmaengine_dlp_process(struct snd_soc_component * component,struct snd_pcm_substream * substream,unsigned long hwoff,void __user * buf,unsigned long bytes)968 static int dmaengine_dlp_process(struct snd_soc_component *component,
969 struct snd_pcm_substream *substream,
970 unsigned long hwoff,
971 void __user *buf, unsigned long bytes)
972 {
973 struct dmaengine_dlp *dlp = soc_component_to_dlp(component);
974 int ret = 0;
975
976 if (dlp->mode == DLP_MODE_DISABLED)
977 return -EINVAL;
978
979 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
980 ret = process_playback(component, substream, hwoff, buf, bytes);
981 else
982 ret = process_capture(component, substream, hwoff, buf, bytes);
983
984 return ret;
985 }
986
dmaengine_dlp_copy_user(struct snd_soc_component * component,struct snd_pcm_substream * substream,int channel,unsigned long hwoff,void __user * buf,unsigned long bytes)987 static int dmaengine_dlp_copy_user(struct snd_soc_component *component,
988 struct snd_pcm_substream *substream,
989 int channel, unsigned long hwoff,
990 void __user *buf, unsigned long bytes)
991 {
992 struct dmaengine_dlp_runtime_data *prtd = substream_to_prtd(substream);
993 struct snd_pcm_runtime *runtime = substream->runtime;
994 bool is_playback = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
995 void *dma_ptr = runtime->dma_area + hwoff +
996 channel * (runtime->dma_bytes / runtime->channels);
997 int ret;
998
999 if (is_playback)
1000 if (copy_from_user(dma_ptr, buf, bytes))
1001 return -EFAULT;
1002
1003 ret = dmaengine_dlp_process(component, substream, hwoff, buf, bytes);
1004 if (!ret)
1005 dma_ptr = prtd->buf;
1006
1007 if (!is_playback)
1008 if (copy_to_user(buf, dma_ptr, bytes))
1009 return -EFAULT;
1010
1011 return 0;
1012 }
1013
1014 static SOC_ENUM_SINGLE_EXT_DECL(dlp_mode, dlp_text);
1015
dmaengine_dlp_mode_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)1016 static int dmaengine_dlp_mode_get(struct snd_kcontrol *kcontrol,
1017 struct snd_ctl_elem_value *ucontrol)
1018 {
1019 struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
1020 struct dmaengine_dlp *dlp = soc_component_to_dlp(component);
1021
1022 ucontrol->value.enumerated.item[0] = dlp->mode;
1023
1024 return 0;
1025 }
1026
dmaengine_dlp_mode_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)1027 static int dmaengine_dlp_mode_put(struct snd_kcontrol *kcontrol,
1028 struct snd_ctl_elem_value *ucontrol)
1029 {
1030 struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
1031 struct dmaengine_dlp *dlp = soc_component_to_dlp(component);
1032 unsigned int mode = ucontrol->value.enumerated.item[0];
1033
1034 /* MUST: do not update mode while stream is running */
1035 if (snd_soc_component_active(component))
1036 return -EPERM;
1037
1038 if (mode == dlp->mode)
1039 return 0;
1040
1041 dlp->mode = mode;
1042
1043 return 1;
1044 }
1045
1046 static const struct snd_kcontrol_new dmaengine_dlp_controls[] = {
1047 SOC_ENUM_EXT("Software Digital Loopback Mode", dlp_mode,
1048 dmaengine_dlp_mode_get,
1049 dmaengine_dlp_mode_put),
1050 };
1051
dmaengine_dlp_prepare(struct snd_soc_component * component,struct snd_pcm_substream * substream)1052 static int dmaengine_dlp_prepare(struct snd_soc_component *component,
1053 struct snd_pcm_substream *substream)
1054 {
1055 struct dmaengine_dlp *dlp = soc_component_to_dlp(component);
1056 struct dmaengine_dlp_runtime_data *prtd = substream_to_prtd(substream);
1057 struct dmaengine_dlp_runtime_data *pref = NULL;
1058 int buf_bytes = dlp_frames_to_bytes(prtd, prtd->buf_sz);
1059
1060 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
1061 pref = kmemdup(prtd, sizeof(*prtd), GFP_KERNEL);
1062 if (!pref)
1063 return -ENOMEM;
1064
1065 kref_init(&pref->refcount);
1066 pref->buf_ofs = 0;
1067 pref->buf = kzalloc(buf_bytes, GFP_KERNEL);
1068 if (!pref->buf) {
1069 kfree(pref);
1070 return -ENOMEM;
1071 }
1072
1073 spin_lock(&dlp->pref_lock);
1074 dlp->pref = pref;
1075 spin_unlock(&dlp->pref_lock);
1076 dlp_info("PREF-CREATE: 0x%px\n", pref);
1077 } else {
1078 prtd->buf = kzalloc(buf_bytes, GFP_KERNEL);
1079 if (!prtd->buf)
1080 return -ENOMEM;
1081 }
1082
1083 return 0;
1084 }
1085 static const struct snd_soc_component_driver dmaengine_dlp_component = {
1086 .name = SND_DMAENGINE_DLP_DRV_NAME,
1087 .probe_order = SND_SOC_COMP_ORDER_LATE,
1088 .open = dmaengine_dlp_open,
1089 .close = dmaengine_dlp_close,
1090 .hw_params = dmaengine_dlp_hw_params,
1091 .prepare = dmaengine_dlp_prepare,
1092 .trigger = dmaengine_dlp_trigger,
1093 .pointer = dmaengine_dlp_pointer,
1094 .copy_user = dmaengine_dlp_copy_user,
1095 .pcm_construct = dmaengine_dlp_new,
1096 .controls = dmaengine_dlp_controls,
1097 .num_controls = ARRAY_SIZE(dmaengine_dlp_controls),
1098 };
1099
1100 static const char * const dmaengine_pcm_dma_channel_names[] = {
1101 [SNDRV_PCM_STREAM_PLAYBACK] = "tx",
1102 [SNDRV_PCM_STREAM_CAPTURE] = "rx",
1103 };
1104
dmaengine_pcm_request_chan_of(struct dmaengine_dlp * dlp,struct device * dev,const struct snd_dmaengine_pcm_config * config)1105 static int dmaengine_pcm_request_chan_of(struct dmaengine_dlp *dlp,
1106 struct device *dev, const struct snd_dmaengine_pcm_config *config)
1107 {
1108 unsigned int i;
1109 const char *name;
1110 struct dma_chan *chan;
1111
1112 for_each_pcm_streams(i) {
1113 name = dmaengine_pcm_dma_channel_names[i];
1114 chan = dma_request_chan(dev, name);
1115 if (IS_ERR(chan)) {
1116 /*
1117 * Only report probe deferral errors, channels
1118 * might not be present for devices that
1119 * support only TX or only RX.
1120 */
1121 if (PTR_ERR(chan) == -EPROBE_DEFER)
1122 return -EPROBE_DEFER;
1123 dlp->chan[i] = NULL;
1124 } else {
1125 dlp->chan[i] = chan;
1126 }
1127 }
1128
1129 return 0;
1130 }
1131
dmaengine_pcm_release_chan(struct dmaengine_dlp * dlp)1132 static void dmaengine_pcm_release_chan(struct dmaengine_dlp *dlp)
1133 {
1134 unsigned int i;
1135
1136 for_each_pcm_streams(i) {
1137 if (!dlp->chan[i])
1138 continue;
1139 dma_release_channel(dlp->chan[i]);
1140 }
1141 }
1142
1143 /**
1144 * snd_dmaengine_dlp_register - Register a dmaengine based DLP device
1145 * @dev: The parent device for the DLP device
1146 * @config: Platform specific DLP configuration
1147 */
snd_dmaengine_dlp_register(struct device * dev,const struct snd_dlp_config * config)1148 static int snd_dmaengine_dlp_register(struct device *dev,
1149 const struct snd_dlp_config *config)
1150 {
1151 const struct snd_soc_component_driver *driver;
1152 struct dmaengine_dlp *dlp;
1153 int ret;
1154
1155 dlp = kzalloc(sizeof(*dlp), GFP_KERNEL);
1156 if (!dlp)
1157 return -ENOMEM;
1158
1159 dlp->dev = dev;
1160 dlp->config = config;
1161
1162 INIT_LIST_HEAD(&dlp->ref_list);
1163 spin_lock_init(&dlp->lock);
1164 spin_lock_init(&dlp->pref_lock);
1165
1166 #ifdef CONFIG_DEBUG_FS
1167 dlp->component.debugfs_prefix = "dma";
1168 #endif
1169 ret = dmaengine_pcm_request_chan_of(dlp, dev, NULL);
1170 if (ret)
1171 goto err_free_dma;
1172
1173 driver = &dmaengine_dlp_component;
1174
1175 ret = snd_soc_component_initialize(&dlp->component, driver, dev);
1176 if (ret)
1177 goto err_free_dma;
1178
1179 ret = snd_soc_add_component(&dlp->component, NULL, 0);
1180 if (ret)
1181 goto err_free_dma;
1182
1183 return 0;
1184
1185 err_free_dma:
1186 dmaengine_pcm_release_chan(dlp);
1187 kfree(dlp);
1188 return ret;
1189 }
1190
1191 /**
1192 * snd_dmaengine_dlp_unregister - Removes a dmaengine based DLP device
1193 * @dev: Parent device the DLP was register with
1194 *
1195 * Removes a dmaengine based DLP device previously registered with
1196 * snd_dmaengine_dlp_register.
1197 */
snd_dmaengine_dlp_unregister(struct device * dev)1198 static void snd_dmaengine_dlp_unregister(struct device *dev)
1199 {
1200 struct snd_soc_component *component;
1201 struct dmaengine_dlp *dlp;
1202
1203 component = snd_soc_lookup_component(dev, SND_DMAENGINE_DLP_DRV_NAME);
1204 if (!component)
1205 return;
1206
1207 dlp = soc_component_to_dlp(component);
1208
1209 snd_soc_unregister_component_by_driver(dev, component->driver);
1210 dmaengine_pcm_release_chan(dlp);
1211 kfree(dlp);
1212 }
1213
devm_dmaengine_dlp_release(struct device * dev,void * res)1214 static void devm_dmaengine_dlp_release(struct device *dev, void *res)
1215 {
1216 snd_dmaengine_dlp_unregister(*(struct device **)res);
1217 }
1218
1219 /**
1220 * devm_snd_dmaengine_dlp_register - resource managed dmaengine DLP registration
1221 * @dev: The parent device for the DLP device
1222 * @config: Platform specific DLP configuration
1223 *
1224 * Register a dmaengine based DLP device with automatic unregistration when the
1225 * device is unregistered.
1226 */
devm_snd_dmaengine_dlp_register(struct device * dev,const struct snd_dlp_config * config)1227 int devm_snd_dmaengine_dlp_register(struct device *dev,
1228 const struct snd_dlp_config *config)
1229 {
1230 struct device **ptr;
1231 int ret;
1232
1233 ptr = devres_alloc(devm_dmaengine_dlp_release, sizeof(*ptr), GFP_KERNEL);
1234 if (!ptr)
1235 return -ENOMEM;
1236
1237 ret = snd_dmaengine_dlp_register(dev, config);
1238 if (ret == 0) {
1239 *ptr = dev;
1240 devres_add(dev, ptr);
1241 } else {
1242 devres_free(ptr);
1243 }
1244
1245 return ret;
1246 }
1247 EXPORT_SYMBOL_GPL(devm_snd_dmaengine_dlp_register);
1248
1249 MODULE_LICENSE("GPL");
1250