1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * ALSA SoC using the QUICC Multichannel Controller (QMC)
4 *
5 * Copyright 2022 CS GROUP France
6 *
7 * Author: Herve Codina <herve.codina@bootlin.com>
8 */
9
10 #include <linux/dma-mapping.h>
11 #include <linux/module.h>
12 #include <linux/of.h>
13 #include <linux/of_platform.h>
14 #include <linux/platform_device.h>
15 #include <linux/slab.h>
16 #include <soc/fsl/qe/qmc.h>
17 #include <sound/pcm_params.h>
18 #include <sound/soc.h>
19
20 struct qmc_dai {
21 char *name;
22 int id;
23 struct device *dev;
24 unsigned int nb_tx_ts;
25 unsigned int nb_rx_ts;
26
27 unsigned int nb_chans_avail;
28 unsigned int nb_chans_used_tx;
29 unsigned int nb_chans_used_rx;
30 struct qmc_chan **qmc_chans;
31 };
32
33 struct qmc_audio {
34 struct device *dev;
35 unsigned int num_dais;
36 struct qmc_dai *dais;
37 struct snd_soc_dai_driver *dai_drivers;
38 };
39
40 struct qmc_dai_prtd {
41 struct qmc_dai *qmc_dai;
42
43 snd_pcm_uframes_t buffer_ended;
44 snd_pcm_uframes_t buffer_size;
45 snd_pcm_uframes_t period_size;
46
47 dma_addr_t ch_dma_addr_start;
48 dma_addr_t ch_dma_addr_current;
49 dma_addr_t ch_dma_addr_end;
50 size_t ch_dma_size;
51 size_t ch_dma_offset;
52
53 unsigned int channels;
54 struct snd_pcm_substream *substream;
55 };
56
qmc_audio_pcm_construct(struct snd_soc_component * component,struct snd_soc_pcm_runtime * rtd)57 static int qmc_audio_pcm_construct(struct snd_soc_component *component,
58 struct snd_soc_pcm_runtime *rtd)
59 {
60 struct snd_card *card = rtd->card->snd_card;
61 int ret;
62
63 ret = dma_coerce_mask_and_coherent(card->dev, DMA_BIT_MASK(32));
64 if (ret)
65 return ret;
66
67 snd_pcm_set_managed_buffer_all(rtd->pcm, SNDRV_DMA_TYPE_DEV, card->dev,
68 64 * 1024, 64 * 1024);
69 return 0;
70 }
71
qmc_audio_access_is_interleaved(snd_pcm_access_t access)72 static bool qmc_audio_access_is_interleaved(snd_pcm_access_t access)
73 {
74 switch (access) {
75 case SNDRV_PCM_ACCESS_MMAP_INTERLEAVED:
76 case SNDRV_PCM_ACCESS_RW_INTERLEAVED:
77 return true;
78 default:
79 break;
80 }
81 return false;
82 }
83
qmc_audio_pcm_hw_params(struct snd_soc_component * component,struct snd_pcm_substream * substream,struct snd_pcm_hw_params * params)84 static int qmc_audio_pcm_hw_params(struct snd_soc_component *component,
85 struct snd_pcm_substream *substream,
86 struct snd_pcm_hw_params *params)
87 {
88 struct snd_pcm_runtime *runtime = substream->runtime;
89 struct qmc_dai_prtd *prtd = substream->runtime->private_data;
90
91 /*
92 * In interleaved mode, the driver uses one QMC channel for all audio
93 * channels whereas in non-interleaved mode, it uses one QMC channel per
94 * audio channel.
95 */
96 prtd->channels = qmc_audio_access_is_interleaved(params_access(params)) ?
97 1 : params_channels(params);
98
99 prtd->substream = substream;
100
101 prtd->buffer_ended = 0;
102 prtd->buffer_size = params_buffer_size(params);
103 prtd->period_size = params_period_size(params);
104
105 prtd->ch_dma_addr_start = runtime->dma_addr;
106 prtd->ch_dma_offset = params_buffer_bytes(params) / prtd->channels;
107 prtd->ch_dma_addr_end = runtime->dma_addr + prtd->ch_dma_offset;
108 prtd->ch_dma_addr_current = prtd->ch_dma_addr_start;
109 prtd->ch_dma_size = params_period_bytes(params) / prtd->channels;
110
111 return 0;
112 }
113
114 static void qmc_audio_pcm_write_complete(void *context);
115
qmc_audio_pcm_write_submit(struct qmc_dai_prtd * prtd)116 static int qmc_audio_pcm_write_submit(struct qmc_dai_prtd *prtd)
117 {
118 unsigned int i;
119 int ret;
120
121 for (i = 0; i < prtd->channels; i++) {
122 ret = qmc_chan_write_submit(prtd->qmc_dai->qmc_chans[i],
123 prtd->ch_dma_addr_current + i * prtd->ch_dma_offset,
124 prtd->ch_dma_size,
125 i == prtd->channels - 1 ? qmc_audio_pcm_write_complete :
126 NULL, prtd);
127 if (ret) {
128 dev_err(prtd->qmc_dai->dev, "write_submit %u failed %d\n",
129 i, ret);
130 return ret;
131 }
132 }
133
134 return 0;
135 }
136
qmc_audio_pcm_write_complete(void * context)137 static void qmc_audio_pcm_write_complete(void *context)
138 {
139 struct qmc_dai_prtd *prtd = context;
140
141 prtd->buffer_ended += prtd->period_size;
142 if (prtd->buffer_ended >= prtd->buffer_size)
143 prtd->buffer_ended = 0;
144
145 prtd->ch_dma_addr_current += prtd->ch_dma_size;
146 if (prtd->ch_dma_addr_current >= prtd->ch_dma_addr_end)
147 prtd->ch_dma_addr_current = prtd->ch_dma_addr_start;
148
149 qmc_audio_pcm_write_submit(prtd);
150
151 snd_pcm_period_elapsed(prtd->substream);
152 }
153
154 static void qmc_audio_pcm_read_complete(void *context, size_t length, unsigned int flags);
155
qmc_audio_pcm_read_submit(struct qmc_dai_prtd * prtd)156 static int qmc_audio_pcm_read_submit(struct qmc_dai_prtd *prtd)
157 {
158 unsigned int i;
159 int ret;
160
161 for (i = 0; i < prtd->channels; i++) {
162 ret = qmc_chan_read_submit(prtd->qmc_dai->qmc_chans[i],
163 prtd->ch_dma_addr_current + i * prtd->ch_dma_offset,
164 prtd->ch_dma_size,
165 i == prtd->channels - 1 ? qmc_audio_pcm_read_complete :
166 NULL, prtd);
167 if (ret) {
168 dev_err(prtd->qmc_dai->dev, "read_submit %u failed %d\n",
169 i, ret);
170 return ret;
171 }
172 }
173
174 return 0;
175 }
176
qmc_audio_pcm_read_complete(void * context,size_t length,unsigned int flags)177 static void qmc_audio_pcm_read_complete(void *context, size_t length, unsigned int flags)
178 {
179 struct qmc_dai_prtd *prtd = context;
180
181 if (length != prtd->ch_dma_size) {
182 dev_err(prtd->qmc_dai->dev, "read complete length = %zu, exp %zu\n",
183 length, prtd->ch_dma_size);
184 }
185
186 prtd->buffer_ended += prtd->period_size;
187 if (prtd->buffer_ended >= prtd->buffer_size)
188 prtd->buffer_ended = 0;
189
190 prtd->ch_dma_addr_current += prtd->ch_dma_size;
191 if (prtd->ch_dma_addr_current >= prtd->ch_dma_addr_end)
192 prtd->ch_dma_addr_current = prtd->ch_dma_addr_start;
193
194 qmc_audio_pcm_read_submit(prtd);
195
196 snd_pcm_period_elapsed(prtd->substream);
197 }
198
qmc_audio_pcm_trigger(struct snd_soc_component * component,struct snd_pcm_substream * substream,int cmd)199 static int qmc_audio_pcm_trigger(struct snd_soc_component *component,
200 struct snd_pcm_substream *substream, int cmd)
201 {
202 struct qmc_dai_prtd *prtd = substream->runtime->private_data;
203 int ret;
204
205 if (!prtd->qmc_dai) {
206 dev_err(component->dev, "qmc_dai is not set\n");
207 return -EINVAL;
208 }
209
210 switch (cmd) {
211 case SNDRV_PCM_TRIGGER_START:
212 prtd->buffer_ended = 0;
213 prtd->ch_dma_addr_current = prtd->ch_dma_addr_start;
214
215 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
216 /* Submit first chunk ... */
217 ret = qmc_audio_pcm_write_submit(prtd);
218 if (ret)
219 return ret;
220
221 /* ... prepare next one ... */
222 prtd->ch_dma_addr_current += prtd->ch_dma_size;
223 if (prtd->ch_dma_addr_current >= prtd->ch_dma_addr_end)
224 prtd->ch_dma_addr_current = prtd->ch_dma_addr_start;
225
226 /* ... and send it */
227 ret = qmc_audio_pcm_write_submit(prtd);
228 if (ret)
229 return ret;
230 } else {
231 /* Submit first chunk ... */
232 ret = qmc_audio_pcm_read_submit(prtd);
233 if (ret)
234 return ret;
235
236 /* ... prepare next one ... */
237 prtd->ch_dma_addr_current += prtd->ch_dma_size;
238 if (prtd->ch_dma_addr_current >= prtd->ch_dma_addr_end)
239 prtd->ch_dma_addr_current = prtd->ch_dma_addr_start;
240
241 /* ... and send it */
242 ret = qmc_audio_pcm_read_submit(prtd);
243 if (ret)
244 return ret;
245 }
246 break;
247
248 case SNDRV_PCM_TRIGGER_RESUME:
249 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
250 break;
251
252 case SNDRV_PCM_TRIGGER_STOP:
253 case SNDRV_PCM_TRIGGER_SUSPEND:
254 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
255 break;
256
257 default:
258 return -EINVAL;
259 }
260
261 return 0;
262 }
263
qmc_audio_pcm_pointer(struct snd_soc_component * component,struct snd_pcm_substream * substream)264 static snd_pcm_uframes_t qmc_audio_pcm_pointer(struct snd_soc_component *component,
265 struct snd_pcm_substream *substream)
266 {
267 struct qmc_dai_prtd *prtd = substream->runtime->private_data;
268
269 return prtd->buffer_ended;
270 }
271
qmc_audio_of_xlate_dai_name(struct snd_soc_component * component,const struct of_phandle_args * args,const char ** dai_name)272 static int qmc_audio_of_xlate_dai_name(struct snd_soc_component *component,
273 const struct of_phandle_args *args,
274 const char **dai_name)
275 {
276 struct qmc_audio *qmc_audio = dev_get_drvdata(component->dev);
277 struct snd_soc_dai_driver *dai_driver;
278 int id = args->args[0];
279 int i;
280
281 for (i = 0; i < qmc_audio->num_dais; i++) {
282 dai_driver = qmc_audio->dai_drivers + i;
283 if (dai_driver->id == id) {
284 *dai_name = dai_driver->name;
285 return 0;
286 }
287 }
288
289 return -EINVAL;
290 }
291
292 static const struct snd_pcm_hardware qmc_audio_pcm_hardware = {
293 .info = SNDRV_PCM_INFO_MMAP |
294 SNDRV_PCM_INFO_MMAP_VALID |
295 SNDRV_PCM_INFO_INTERLEAVED |
296 SNDRV_PCM_INFO_NONINTERLEAVED |
297 SNDRV_PCM_INFO_PAUSE,
298 .period_bytes_min = 32,
299 .period_bytes_max = 64 * 1024,
300 .periods_min = 2,
301 .periods_max = 2 * 1024,
302 .buffer_bytes_max = 64 * 1024,
303 };
304
qmc_audio_pcm_open(struct snd_soc_component * component,struct snd_pcm_substream * substream)305 static int qmc_audio_pcm_open(struct snd_soc_component *component,
306 struct snd_pcm_substream *substream)
307 {
308 struct snd_pcm_runtime *runtime = substream->runtime;
309 struct qmc_dai_prtd *prtd;
310 int ret;
311
312 snd_soc_set_runtime_hwparams(substream, &qmc_audio_pcm_hardware);
313
314 /* ensure that buffer size is a multiple of period size */
315 ret = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
316 if (ret < 0)
317 return ret;
318
319 prtd = kzalloc_obj(*prtd);
320 if (!prtd)
321 return -ENOMEM;
322
323 runtime->private_data = prtd;
324
325 return 0;
326 }
327
qmc_audio_pcm_close(struct snd_soc_component * component,struct snd_pcm_substream * substream)328 static int qmc_audio_pcm_close(struct snd_soc_component *component,
329 struct snd_pcm_substream *substream)
330 {
331 struct qmc_dai_prtd *prtd = substream->runtime->private_data;
332
333 kfree(prtd);
334 return 0;
335 }
336
337 static const struct snd_soc_component_driver qmc_audio_soc_platform = {
338 .open = qmc_audio_pcm_open,
339 .close = qmc_audio_pcm_close,
340 .hw_params = qmc_audio_pcm_hw_params,
341 .trigger = qmc_audio_pcm_trigger,
342 .pointer = qmc_audio_pcm_pointer,
343 .pcm_construct = qmc_audio_pcm_construct,
344 .of_xlate_dai_name = qmc_audio_of_xlate_dai_name,
345 };
346
qmc_dai_get_index(struct snd_soc_dai * dai)347 static unsigned int qmc_dai_get_index(struct snd_soc_dai *dai)
348 {
349 struct qmc_audio *qmc_audio = snd_soc_dai_get_drvdata(dai);
350
351 return dai->driver - qmc_audio->dai_drivers;
352 }
353
qmc_dai_get_data(struct snd_soc_dai * dai)354 static struct qmc_dai *qmc_dai_get_data(struct snd_soc_dai *dai)
355 {
356 struct qmc_audio *qmc_audio = snd_soc_dai_get_drvdata(dai);
357 unsigned int index;
358
359 index = qmc_dai_get_index(dai);
360 if (index > qmc_audio->num_dais)
361 return NULL;
362
363 return qmc_audio->dais + index;
364 }
365
366 /*
367 * The constraints for format/channel is to match with the number of 8bit
368 * time-slots available.
369 */
qmc_dai_hw_rule_channels_by_format(struct qmc_dai * qmc_dai,struct snd_pcm_hw_params * params,unsigned int nb_ts)370 static int qmc_dai_hw_rule_channels_by_format(struct qmc_dai *qmc_dai,
371 struct snd_pcm_hw_params *params,
372 unsigned int nb_ts)
373 {
374 struct snd_interval *c = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
375 snd_pcm_format_t format = params_format(params);
376 struct snd_interval ch = {0};
377
378 switch (snd_pcm_format_physical_width(format)) {
379 case 8:
380 ch.max = nb_ts;
381 break;
382 case 16:
383 ch.max = nb_ts / 2;
384 break;
385 case 32:
386 ch.max = nb_ts / 4;
387 break;
388 case 64:
389 ch.max = nb_ts / 8;
390 break;
391 default:
392 dev_err(qmc_dai->dev, "format physical width %u not supported\n",
393 snd_pcm_format_physical_width(format));
394 return -EINVAL;
395 }
396
397 ch.min = ch.max ? 1 : 0;
398
399 return snd_interval_refine(c, &ch);
400 }
401
qmc_dai_hw_rule_playback_channels_by_format(struct snd_pcm_hw_params * params,struct snd_pcm_hw_rule * rule)402 static int qmc_dai_hw_rule_playback_channels_by_format(struct snd_pcm_hw_params *params,
403 struct snd_pcm_hw_rule *rule)
404 {
405 struct qmc_dai *qmc_dai = rule->private;
406
407 return qmc_dai_hw_rule_channels_by_format(qmc_dai, params, qmc_dai->nb_tx_ts);
408 }
409
qmc_dai_hw_rule_capture_channels_by_format(struct snd_pcm_hw_params * params,struct snd_pcm_hw_rule * rule)410 static int qmc_dai_hw_rule_capture_channels_by_format(struct snd_pcm_hw_params *params,
411 struct snd_pcm_hw_rule *rule)
412 {
413 struct qmc_dai *qmc_dai = rule->private;
414
415 return qmc_dai_hw_rule_channels_by_format(qmc_dai, params, qmc_dai->nb_rx_ts);
416 }
417
qmc_dai_hw_rule_format_by_channels(struct qmc_dai * qmc_dai,struct snd_pcm_hw_params * params,unsigned int nb_ts)418 static int qmc_dai_hw_rule_format_by_channels(struct qmc_dai *qmc_dai,
419 struct snd_pcm_hw_params *params,
420 unsigned int nb_ts)
421 {
422 struct snd_mask *f_old = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
423 unsigned int channels = params_channels(params);
424 unsigned int slot_width;
425 snd_pcm_format_t format;
426 struct snd_mask f_new;
427
428 if (!channels || channels > nb_ts) {
429 dev_err(qmc_dai->dev, "channels %u not supported\n",
430 nb_ts);
431 return -EINVAL;
432 }
433
434 slot_width = (nb_ts / channels) * 8;
435
436 snd_mask_none(&f_new);
437 pcm_for_each_format(format) {
438 if (snd_mask_test_format(f_old, format)) {
439 if (snd_pcm_format_physical_width(format) <= slot_width)
440 snd_mask_set_format(&f_new, format);
441 }
442 }
443
444 return snd_mask_refine(f_old, &f_new);
445 }
446
qmc_dai_hw_rule_playback_format_by_channels(struct snd_pcm_hw_params * params,struct snd_pcm_hw_rule * rule)447 static int qmc_dai_hw_rule_playback_format_by_channels(struct snd_pcm_hw_params *params,
448 struct snd_pcm_hw_rule *rule)
449 {
450 struct qmc_dai *qmc_dai = rule->private;
451
452 return qmc_dai_hw_rule_format_by_channels(qmc_dai, params, qmc_dai->nb_tx_ts);
453 }
454
qmc_dai_hw_rule_capture_format_by_channels(struct snd_pcm_hw_params * params,struct snd_pcm_hw_rule * rule)455 static int qmc_dai_hw_rule_capture_format_by_channels(struct snd_pcm_hw_params *params,
456 struct snd_pcm_hw_rule *rule)
457 {
458 struct qmc_dai *qmc_dai = rule->private;
459
460 return qmc_dai_hw_rule_format_by_channels(qmc_dai, params, qmc_dai->nb_rx_ts);
461 }
462
qmc_dai_constraints_interleaved(struct snd_pcm_substream * substream,struct qmc_dai * qmc_dai)463 static int qmc_dai_constraints_interleaved(struct snd_pcm_substream *substream,
464 struct qmc_dai *qmc_dai)
465 {
466 snd_pcm_hw_rule_func_t hw_rule_channels_by_format;
467 snd_pcm_hw_rule_func_t hw_rule_format_by_channels;
468 unsigned int frame_bits;
469 u64 access;
470 int ret;
471
472 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
473 hw_rule_channels_by_format = qmc_dai_hw_rule_capture_channels_by_format;
474 hw_rule_format_by_channels = qmc_dai_hw_rule_capture_format_by_channels;
475 frame_bits = qmc_dai->nb_rx_ts * 8;
476 } else {
477 hw_rule_channels_by_format = qmc_dai_hw_rule_playback_channels_by_format;
478 hw_rule_format_by_channels = qmc_dai_hw_rule_playback_format_by_channels;
479 frame_bits = qmc_dai->nb_tx_ts * 8;
480 }
481
482 ret = snd_pcm_hw_rule_add(substream->runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
483 hw_rule_channels_by_format, qmc_dai,
484 SNDRV_PCM_HW_PARAM_FORMAT, -1);
485 if (ret) {
486 dev_err(qmc_dai->dev, "Failed to add channels rule (%d)\n", ret);
487 return ret;
488 }
489
490 ret = snd_pcm_hw_rule_add(substream->runtime, 0, SNDRV_PCM_HW_PARAM_FORMAT,
491 hw_rule_format_by_channels, qmc_dai,
492 SNDRV_PCM_HW_PARAM_CHANNELS, -1);
493 if (ret) {
494 dev_err(qmc_dai->dev, "Failed to add format rule (%d)\n", ret);
495 return ret;
496 }
497
498 ret = snd_pcm_hw_constraint_single(substream->runtime,
499 SNDRV_PCM_HW_PARAM_FRAME_BITS,
500 frame_bits);
501 if (ret < 0) {
502 dev_err(qmc_dai->dev, "Failed to add frame_bits constraint (%d)\n", ret);
503 return ret;
504 }
505
506 access = 1ULL << (__force int)SNDRV_PCM_ACCESS_MMAP_INTERLEAVED |
507 1ULL << (__force int)SNDRV_PCM_ACCESS_RW_INTERLEAVED;
508 ret = snd_pcm_hw_constraint_mask64(substream->runtime, SNDRV_PCM_HW_PARAM_ACCESS,
509 access);
510 if (ret) {
511 dev_err(qmc_dai->dev, "Failed to add hw_param_access constraint (%d)\n", ret);
512 return ret;
513 }
514
515 return 0;
516 }
517
qmc_dai_constraints_noninterleaved(struct snd_pcm_substream * substream,struct qmc_dai * qmc_dai)518 static int qmc_dai_constraints_noninterleaved(struct snd_pcm_substream *substream,
519 struct qmc_dai *qmc_dai)
520 {
521 unsigned int frame_bits;
522 u64 access;
523 int ret;
524
525 frame_bits = (substream->stream == SNDRV_PCM_STREAM_CAPTURE) ?
526 qmc_dai->nb_rx_ts * 8 : qmc_dai->nb_tx_ts * 8;
527 ret = snd_pcm_hw_constraint_single(substream->runtime,
528 SNDRV_PCM_HW_PARAM_FRAME_BITS,
529 frame_bits);
530 if (ret < 0) {
531 dev_err(qmc_dai->dev, "Failed to add frame_bits constraint (%d)\n", ret);
532 return ret;
533 }
534
535 access = 1ULL << (__force int)SNDRV_PCM_ACCESS_MMAP_NONINTERLEAVED |
536 1ULL << (__force int)SNDRV_PCM_ACCESS_RW_NONINTERLEAVED;
537 ret = snd_pcm_hw_constraint_mask64(substream->runtime, SNDRV_PCM_HW_PARAM_ACCESS,
538 access);
539 if (ret) {
540 dev_err(qmc_dai->dev, "Failed to add hw_param_access constraint (%d)\n", ret);
541 return ret;
542 }
543
544 return 0;
545 }
546
qmc_dai_startup(struct snd_pcm_substream * substream,struct snd_soc_dai * dai)547 static int qmc_dai_startup(struct snd_pcm_substream *substream,
548 struct snd_soc_dai *dai)
549 {
550 struct qmc_dai_prtd *prtd = substream->runtime->private_data;
551 struct qmc_dai *qmc_dai;
552
553 qmc_dai = qmc_dai_get_data(dai);
554 if (!qmc_dai) {
555 dev_err(dai->dev, "Invalid dai\n");
556 return -EINVAL;
557 }
558
559 prtd->qmc_dai = qmc_dai;
560
561 return qmc_dai->nb_chans_avail > 1 ?
562 qmc_dai_constraints_noninterleaved(substream, qmc_dai) :
563 qmc_dai_constraints_interleaved(substream, qmc_dai);
564 }
565
qmc_dai_hw_params(struct snd_pcm_substream * substream,struct snd_pcm_hw_params * params,struct snd_soc_dai * dai)566 static int qmc_dai_hw_params(struct snd_pcm_substream *substream,
567 struct snd_pcm_hw_params *params,
568 struct snd_soc_dai *dai)
569 {
570 struct qmc_chan_param chan_param = {0};
571 unsigned int nb_chans_used;
572 struct qmc_dai *qmc_dai;
573 unsigned int i;
574 int ret;
575
576 qmc_dai = qmc_dai_get_data(dai);
577 if (!qmc_dai) {
578 dev_err(dai->dev, "Invalid dai\n");
579 return -EINVAL;
580 }
581
582 /*
583 * In interleaved mode, the driver uses one QMC channel for all audio
584 * channels whereas in non-interleaved mode, it uses one QMC channel per
585 * audio channel.
586 */
587 nb_chans_used = qmc_audio_access_is_interleaved(params_access(params)) ?
588 1 : params_channels(params);
589
590 if (nb_chans_used > qmc_dai->nb_chans_avail) {
591 dev_err(dai->dev, "Not enough qmc_chans. Need %u, avail %u\n",
592 nb_chans_used, qmc_dai->nb_chans_avail);
593 return -EINVAL;
594 }
595
596 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
597 chan_param.mode = QMC_TRANSPARENT;
598 chan_param.transp.max_rx_buf_size = params_period_bytes(params) / nb_chans_used;
599 for (i = 0; i < nb_chans_used; i++) {
600 ret = qmc_chan_set_param(qmc_dai->qmc_chans[i], &chan_param);
601 if (ret) {
602 dev_err(dai->dev, "qmc_chans[%u], set param failed %d\n",
603 i, ret);
604 return ret;
605 }
606 }
607 qmc_dai->nb_chans_used_rx = nb_chans_used;
608 } else {
609 qmc_dai->nb_chans_used_tx = nb_chans_used;
610 }
611
612 return 0;
613 }
614
qmc_dai_trigger(struct snd_pcm_substream * substream,int cmd,struct snd_soc_dai * dai)615 static int qmc_dai_trigger(struct snd_pcm_substream *substream, int cmd,
616 struct snd_soc_dai *dai)
617 {
618 unsigned int nb_chans_used;
619 struct qmc_dai *qmc_dai;
620 unsigned int i;
621 int direction;
622 int ret = 0;
623 int ret_tmp;
624
625 qmc_dai = qmc_dai_get_data(dai);
626 if (!qmc_dai) {
627 dev_err(dai->dev, "Invalid dai\n");
628 return -EINVAL;
629 }
630
631 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
632 direction = QMC_CHAN_WRITE;
633 nb_chans_used = qmc_dai->nb_chans_used_tx;
634 } else {
635 direction = QMC_CHAN_READ;
636 nb_chans_used = qmc_dai->nb_chans_used_rx;
637 }
638
639 switch (cmd) {
640 case SNDRV_PCM_TRIGGER_START:
641 case SNDRV_PCM_TRIGGER_RESUME:
642 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
643 for (i = 0; i < nb_chans_used; i++) {
644 ret = qmc_chan_start(qmc_dai->qmc_chans[i], direction);
645 if (ret)
646 goto err_stop;
647 }
648 break;
649
650 case SNDRV_PCM_TRIGGER_STOP:
651 /* Stop and reset all QMC channels and return the first error encountered */
652 for (i = 0; i < nb_chans_used; i++) {
653 ret_tmp = qmc_chan_stop(qmc_dai->qmc_chans[i], direction);
654 if (!ret)
655 ret = ret_tmp;
656 if (ret_tmp)
657 continue;
658
659 ret_tmp = qmc_chan_reset(qmc_dai->qmc_chans[i], direction);
660 if (!ret)
661 ret = ret_tmp;
662 }
663 if (ret)
664 return ret;
665 break;
666
667 case SNDRV_PCM_TRIGGER_SUSPEND:
668 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
669 /* Stop all QMC channels and return the first error encountered */
670 for (i = 0; i < nb_chans_used; i++) {
671 ret_tmp = qmc_chan_stop(qmc_dai->qmc_chans[i], direction);
672 if (!ret)
673 ret = ret_tmp;
674 }
675 if (ret)
676 return ret;
677 break;
678
679 default:
680 return -EINVAL;
681 }
682
683 return 0;
684
685 err_stop:
686 while (i--) {
687 qmc_chan_stop(qmc_dai->qmc_chans[i], direction);
688 qmc_chan_reset(qmc_dai->qmc_chans[i], direction);
689 }
690 return ret;
691 }
692
693 static const struct snd_soc_dai_ops qmc_dai_ops = {
694 .startup = qmc_dai_startup,
695 .trigger = qmc_dai_trigger,
696 .hw_params = qmc_dai_hw_params,
697 };
698
qmc_audio_formats(u8 nb_ts,bool is_noninterleaved)699 static u64 qmc_audio_formats(u8 nb_ts, bool is_noninterleaved)
700 {
701 unsigned int format_width;
702 unsigned int chan_width;
703 snd_pcm_format_t format;
704 u64 formats_mask;
705
706 if (!nb_ts)
707 return 0;
708
709 formats_mask = 0;
710 chan_width = nb_ts * 8;
711 pcm_for_each_format(format) {
712 /*
713 * Support format other than little-endian (ie big-endian or
714 * without endianness such as 8bit formats)
715 */
716 if (snd_pcm_format_little_endian(format) == 1)
717 continue;
718
719 /* Support physical width multiple of 8bit */
720 format_width = snd_pcm_format_physical_width(format);
721 if (format_width == 0 || format_width % 8)
722 continue;
723
724 /*
725 * And support physical width that can fit N times in the
726 * channel
727 */
728 if (format_width > chan_width || chan_width % format_width)
729 continue;
730
731 /*
732 * In non interleaved mode, we can only support formats that
733 * can fit only 1 time in the channel
734 */
735 if (is_noninterleaved && format_width != chan_width)
736 continue;
737
738 formats_mask |= pcm_format_to_bits(format);
739 }
740 return formats_mask;
741 }
742
qmc_audio_dai_parse(struct qmc_audio * qmc_audio,struct device_node * np,struct qmc_dai * qmc_dai,struct snd_soc_dai_driver * qmc_soc_dai_driver)743 static int qmc_audio_dai_parse(struct qmc_audio *qmc_audio, struct device_node *np,
744 struct qmc_dai *qmc_dai,
745 struct snd_soc_dai_driver *qmc_soc_dai_driver)
746 {
747 struct qmc_chan_ts_info ts_info;
748 struct qmc_chan_info info;
749 unsigned long rx_fs_rate;
750 unsigned long tx_fs_rate;
751 int prev_last_rx_ts = 0;
752 int prev_last_tx_ts = 0;
753 unsigned int nb_tx_ts;
754 unsigned int nb_rx_ts;
755 unsigned int i;
756 int last_rx_ts;
757 int last_tx_ts;
758 int count;
759 u32 val;
760 int ret;
761
762 qmc_dai->dev = qmc_audio->dev;
763
764 ret = of_property_read_u32(np, "reg", &val);
765 if (ret) {
766 dev_err(qmc_audio->dev, "%pOF: failed to read reg\n", np);
767 return ret;
768 }
769 qmc_dai->id = val;
770
771 qmc_dai->name = devm_kasprintf(qmc_audio->dev, GFP_KERNEL, "%s.%d",
772 np->parent->name, qmc_dai->id);
773 if (!qmc_dai->name)
774 return -ENOMEM;
775
776 count = qmc_chan_count_phandles(np, "fsl,qmc-chan");
777 if (count < 0)
778 return dev_err_probe(qmc_audio->dev, count,
779 "dai %d get number of QMC channel failed\n", qmc_dai->id);
780 if (!count)
781 return dev_err_probe(qmc_audio->dev, -EINVAL,
782 "dai %d no QMC channel defined\n", qmc_dai->id);
783
784 qmc_dai->qmc_chans = devm_kcalloc(qmc_audio->dev, count, sizeof(*qmc_dai->qmc_chans),
785 GFP_KERNEL);
786 if (!qmc_dai->qmc_chans)
787 return -ENOMEM;
788
789 for (i = 0; i < count; i++) {
790 qmc_dai->qmc_chans[i] = devm_qmc_chan_get_byphandles_index(qmc_audio->dev, np,
791 "fsl,qmc-chan", i);
792 if (IS_ERR(qmc_dai->qmc_chans[i])) {
793 return dev_err_probe(qmc_audio->dev, PTR_ERR(qmc_dai->qmc_chans[i]),
794 "dai %d get QMC channel %d failed\n", qmc_dai->id, i);
795 }
796
797 ret = qmc_chan_get_info(qmc_dai->qmc_chans[i], &info);
798 if (ret) {
799 dev_err(qmc_audio->dev, "dai %d get QMC %d channel info failed %d\n",
800 qmc_dai->id, i, ret);
801 return ret;
802 }
803
804 if (info.mode != QMC_TRANSPARENT) {
805 dev_err(qmc_audio->dev, "dai %d QMC chan %d mode %d is not QMC_TRANSPARENT\n",
806 qmc_dai->id, i, info.mode);
807 return -EINVAL;
808 }
809
810 /*
811 * All channels must have the same number of Tx slots and the
812 * same numbers of Rx slots.
813 */
814 if (i == 0) {
815 nb_tx_ts = info.nb_tx_ts;
816 nb_rx_ts = info.nb_rx_ts;
817 tx_fs_rate = info.tx_fs_rate;
818 rx_fs_rate = info.rx_fs_rate;
819 } else {
820 if (nb_tx_ts != info.nb_tx_ts) {
821 dev_err(qmc_audio->dev, "dai %d QMC chan %d inconsistent number of Tx timeslots (%u instead of %u)\n",
822 qmc_dai->id, i, info.nb_tx_ts, nb_tx_ts);
823 return -EINVAL;
824 }
825 if (nb_rx_ts != info.nb_rx_ts) {
826 dev_err(qmc_audio->dev, "dai %d QMC chan %d inconsistent number of Rx timeslots (%u instead of %u)\n",
827 qmc_dai->id, i, info.nb_rx_ts, nb_rx_ts);
828 return -EINVAL;
829 }
830 if (tx_fs_rate != info.tx_fs_rate) {
831 dev_err(qmc_audio->dev, "dai %d QMC chan %d inconsistent Tx frame sample rate (%lu instead of %lu)\n",
832 qmc_dai->id, i, info.tx_fs_rate, tx_fs_rate);
833 return -EINVAL;
834 }
835 if (rx_fs_rate != info.rx_fs_rate) {
836 dev_err(qmc_audio->dev, "dai %d QMC chan %d inconsistent Rx frame sample rate (%lu instead of %lu)\n",
837 qmc_dai->id, i, info.rx_fs_rate, rx_fs_rate);
838 return -EINVAL;
839 }
840 }
841
842 ret = qmc_chan_get_ts_info(qmc_dai->qmc_chans[i], &ts_info);
843 if (ret) {
844 dev_err(qmc_audio->dev, "dai %d get QMC %d channel TS info failed %d\n",
845 qmc_dai->id, i, ret);
846 return ret;
847 }
848
849 last_rx_ts = fls64(ts_info.rx_ts_mask);
850 last_tx_ts = fls64(ts_info.tx_ts_mask);
851
852 if (prev_last_rx_ts > last_rx_ts) {
853 dev_err(qmc_audio->dev, "dai %d QMC chan %d unordered channels (RX timeslot %d before %d)\n",
854 qmc_dai->id, i, prev_last_rx_ts, last_rx_ts);
855 return -EINVAL;
856 }
857 if (prev_last_tx_ts > last_tx_ts) {
858 dev_err(qmc_audio->dev, "dai %d QMC chan %d unordered channels (TX timeslot %d before %d)\n",
859 qmc_dai->id, i, prev_last_tx_ts, last_tx_ts);
860 return -EINVAL;
861 }
862
863 prev_last_rx_ts = last_rx_ts;
864 prev_last_tx_ts = last_tx_ts;
865 }
866
867 qmc_dai->nb_chans_avail = count;
868 qmc_dai->nb_tx_ts = nb_tx_ts * count;
869 qmc_dai->nb_rx_ts = nb_rx_ts * count;
870
871 qmc_soc_dai_driver->id = qmc_dai->id;
872 qmc_soc_dai_driver->name = qmc_dai->name;
873
874 qmc_soc_dai_driver->playback.channels_min = 0;
875 qmc_soc_dai_driver->playback.channels_max = 0;
876 if (nb_tx_ts) {
877 qmc_soc_dai_driver->playback.channels_min = 1;
878 qmc_soc_dai_driver->playback.channels_max = count > 1 ? count : nb_tx_ts;
879 }
880 qmc_soc_dai_driver->playback.formats = qmc_audio_formats(nb_tx_ts,
881 count > 1);
882
883 qmc_soc_dai_driver->capture.channels_min = 0;
884 qmc_soc_dai_driver->capture.channels_max = 0;
885 if (nb_rx_ts) {
886 qmc_soc_dai_driver->capture.channels_min = 1;
887 qmc_soc_dai_driver->capture.channels_max = count > 1 ? count : nb_rx_ts;
888 }
889 qmc_soc_dai_driver->capture.formats = qmc_audio_formats(nb_rx_ts,
890 count > 1);
891
892 qmc_soc_dai_driver->playback.rates = snd_pcm_rate_to_rate_bit(tx_fs_rate);
893 qmc_soc_dai_driver->playback.rate_min = tx_fs_rate;
894 qmc_soc_dai_driver->playback.rate_max = tx_fs_rate;
895 qmc_soc_dai_driver->capture.rates = snd_pcm_rate_to_rate_bit(rx_fs_rate);
896 qmc_soc_dai_driver->capture.rate_min = rx_fs_rate;
897 qmc_soc_dai_driver->capture.rate_max = rx_fs_rate;
898
899 qmc_soc_dai_driver->ops = &qmc_dai_ops;
900
901 return 0;
902 }
903
qmc_audio_probe(struct platform_device * pdev)904 static int qmc_audio_probe(struct platform_device *pdev)
905 {
906 struct device_node *np = pdev->dev.of_node;
907 struct qmc_audio *qmc_audio;
908 struct device_node *child;
909 unsigned int i;
910 int ret;
911
912 qmc_audio = devm_kzalloc(&pdev->dev, sizeof(*qmc_audio), GFP_KERNEL);
913 if (!qmc_audio)
914 return -ENOMEM;
915
916 qmc_audio->dev = &pdev->dev;
917
918 qmc_audio->num_dais = of_get_available_child_count(np);
919 if (qmc_audio->num_dais) {
920 qmc_audio->dais = devm_kcalloc(&pdev->dev, qmc_audio->num_dais,
921 sizeof(*qmc_audio->dais),
922 GFP_KERNEL);
923 if (!qmc_audio->dais)
924 return -ENOMEM;
925
926 qmc_audio->dai_drivers = devm_kcalloc(&pdev->dev, qmc_audio->num_dais,
927 sizeof(*qmc_audio->dai_drivers),
928 GFP_KERNEL);
929 if (!qmc_audio->dai_drivers)
930 return -ENOMEM;
931 }
932
933 i = 0;
934 for_each_available_child_of_node(np, child) {
935 ret = qmc_audio_dai_parse(qmc_audio, child,
936 qmc_audio->dais + i,
937 qmc_audio->dai_drivers + i);
938 if (ret) {
939 of_node_put(child);
940 return ret;
941 }
942 i++;
943 }
944
945 platform_set_drvdata(pdev, qmc_audio);
946
947 ret = devm_snd_soc_register_component(qmc_audio->dev,
948 &qmc_audio_soc_platform,
949 qmc_audio->dai_drivers,
950 qmc_audio->num_dais);
951 if (ret)
952 return ret;
953
954 return 0;
955 }
956
957 static const struct of_device_id qmc_audio_id_table[] = {
958 { .compatible = "fsl,qmc-audio" },
959 {} /* sentinel */
960 };
961 MODULE_DEVICE_TABLE(of, qmc_audio_id_table);
962
963 static struct platform_driver qmc_audio_driver = {
964 .driver = {
965 .name = "fsl-qmc-audio",
966 .of_match_table = of_match_ptr(qmc_audio_id_table),
967 },
968 .probe = qmc_audio_probe,
969 };
970 module_platform_driver(qmc_audio_driver);
971
972 MODULE_AUTHOR("Herve Codina <herve.codina@bootlin.com>");
973 MODULE_DESCRIPTION("CPM/QE QMC audio driver");
974 MODULE_LICENSE("GPL");
975