xref: /OK3568_Linux_fs/kernel/sound/soc/rockchip/rockchip_dlp.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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