Linux 6.13
[linux.git] / sound / soc / fsl / fsl_qmc_audio.c
blobe257b8adafe09543bf467c60e406397c2ae0767c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * ALSA SoC using the QUICC Multichannel Controller (QMC)
5 * Copyright 2022 CS GROUP France
7 * Author: Herve Codina <herve.codina@bootlin.com>
8 */
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>
20 struct qmc_dai_chan {
21 struct qmc_dai_prtd *prtd_tx;
22 struct qmc_dai_prtd *prtd_rx;
23 struct qmc_chan *qmc_chan;
26 struct qmc_dai {
27 char *name;
28 int id;
29 struct device *dev;
30 unsigned int nb_tx_ts;
31 unsigned int nb_rx_ts;
33 unsigned int nb_chans_avail;
34 unsigned int nb_chans_used_tx;
35 unsigned int nb_chans_used_rx;
36 struct qmc_dai_chan *chans;
39 struct qmc_audio {
40 struct device *dev;
41 unsigned int num_dais;
42 struct qmc_dai *dais;
43 struct snd_soc_dai_driver *dai_drivers;
46 struct qmc_dai_prtd {
47 struct qmc_dai *qmc_dai;
49 snd_pcm_uframes_t buffer_ended;
50 snd_pcm_uframes_t buffer_size;
51 snd_pcm_uframes_t period_size;
53 dma_addr_t ch_dma_addr_start;
54 dma_addr_t ch_dma_addr_current;
55 dma_addr_t ch_dma_addr_end;
56 size_t ch_dma_size;
57 size_t ch_dma_offset;
59 unsigned int channels;
60 DECLARE_BITMAP(chans_pending, 64);
61 struct snd_pcm_substream *substream;
64 static int qmc_audio_pcm_construct(struct snd_soc_component *component,
65 struct snd_soc_pcm_runtime *rtd)
67 struct snd_card *card = rtd->card->snd_card;
68 int ret;
70 ret = dma_coerce_mask_and_coherent(card->dev, DMA_BIT_MASK(32));
71 if (ret)
72 return ret;
74 snd_pcm_set_managed_buffer_all(rtd->pcm, SNDRV_DMA_TYPE_DEV, card->dev,
75 64 * 1024, 64 * 1024);
76 return 0;
79 static bool qmc_audio_access_is_interleaved(snd_pcm_access_t access)
81 switch (access) {
82 case SNDRV_PCM_ACCESS_MMAP_INTERLEAVED:
83 case SNDRV_PCM_ACCESS_RW_INTERLEAVED:
84 return true;
85 default:
86 break;
88 return false;
91 static int qmc_audio_pcm_hw_params(struct snd_soc_component *component,
92 struct snd_pcm_substream *substream,
93 struct snd_pcm_hw_params *params)
95 struct snd_pcm_runtime *runtime = substream->runtime;
96 struct qmc_dai_prtd *prtd = substream->runtime->private_data;
99 * In interleaved mode, the driver uses one QMC channel for all audio
100 * channels whereas in non-interleaved mode, it uses one QMC channel per
101 * audio channel.
103 prtd->channels = qmc_audio_access_is_interleaved(params_access(params)) ?
104 1 : params_channels(params);
106 prtd->substream = substream;
108 prtd->buffer_ended = 0;
109 prtd->buffer_size = params_buffer_size(params);
110 prtd->period_size = params_period_size(params);
112 prtd->ch_dma_addr_start = runtime->dma_addr;
113 prtd->ch_dma_offset = params_buffer_bytes(params) / prtd->channels;
114 prtd->ch_dma_addr_end = runtime->dma_addr + prtd->ch_dma_offset;
115 prtd->ch_dma_addr_current = prtd->ch_dma_addr_start;
116 prtd->ch_dma_size = params_period_bytes(params) / prtd->channels;
118 return 0;
121 static void qmc_audio_pcm_write_complete(void *context);
123 static int qmc_audio_pcm_write_submit(struct qmc_dai_prtd *prtd)
125 unsigned int i;
126 int ret;
128 for (i = 0; i < prtd->channels; i++) {
129 bitmap_set(prtd->chans_pending, i, 1);
131 ret = qmc_chan_write_submit(prtd->qmc_dai->chans[i].qmc_chan,
132 prtd->ch_dma_addr_current + i * prtd->ch_dma_offset,
133 prtd->ch_dma_size,
134 qmc_audio_pcm_write_complete,
135 &prtd->qmc_dai->chans[i]);
136 if (ret) {
137 dev_err(prtd->qmc_dai->dev, "write_submit %u failed %d\n",
138 i, ret);
139 bitmap_clear(prtd->chans_pending, i, 1);
140 return ret;
144 return 0;
147 static void qmc_audio_pcm_write_complete(void *context)
149 struct qmc_dai_chan *chan = context;
150 struct qmc_dai_prtd *prtd;
152 prtd = chan->prtd_tx;
154 /* Mark the current channel as completed */
155 bitmap_clear(prtd->chans_pending, chan - prtd->qmc_dai->chans, 1);
158 * All QMC channels involved must have completed their transfer before
159 * submitting a new one.
161 if (!bitmap_empty(prtd->chans_pending, 64))
162 return;
164 prtd->buffer_ended += prtd->period_size;
165 if (prtd->buffer_ended >= prtd->buffer_size)
166 prtd->buffer_ended = 0;
168 prtd->ch_dma_addr_current += prtd->ch_dma_size;
169 if (prtd->ch_dma_addr_current >= prtd->ch_dma_addr_end)
170 prtd->ch_dma_addr_current = prtd->ch_dma_addr_start;
172 qmc_audio_pcm_write_submit(prtd);
174 snd_pcm_period_elapsed(prtd->substream);
177 static void qmc_audio_pcm_read_complete(void *context, size_t length, unsigned int flags);
179 static int qmc_audio_pcm_read_submit(struct qmc_dai_prtd *prtd)
181 unsigned int i;
182 int ret;
184 for (i = 0; i < prtd->channels; i++) {
185 bitmap_set(prtd->chans_pending, i, 1);
187 ret = qmc_chan_read_submit(prtd->qmc_dai->chans[i].qmc_chan,
188 prtd->ch_dma_addr_current + i * prtd->ch_dma_offset,
189 prtd->ch_dma_size,
190 qmc_audio_pcm_read_complete,
191 &prtd->qmc_dai->chans[i]);
192 if (ret) {
193 dev_err(prtd->qmc_dai->dev, "read_submit %u failed %d\n",
194 i, ret);
195 bitmap_clear(prtd->chans_pending, i, 1);
196 return ret;
200 return 0;
203 static void qmc_audio_pcm_read_complete(void *context, size_t length, unsigned int flags)
205 struct qmc_dai_chan *chan = context;
206 struct qmc_dai_prtd *prtd;
208 prtd = chan->prtd_rx;
210 /* Mark the current channel as completed */
211 bitmap_clear(prtd->chans_pending, chan - prtd->qmc_dai->chans, 1);
213 if (length != prtd->ch_dma_size) {
214 dev_err(prtd->qmc_dai->dev, "read complete length = %zu, exp %zu\n",
215 length, prtd->ch_dma_size);
219 * All QMC channels involved must have completed their transfer before
220 * submitting a new one.
222 if (!bitmap_empty(prtd->chans_pending, 64))
223 return;
225 prtd->buffer_ended += prtd->period_size;
226 if (prtd->buffer_ended >= prtd->buffer_size)
227 prtd->buffer_ended = 0;
229 prtd->ch_dma_addr_current += prtd->ch_dma_size;
230 if (prtd->ch_dma_addr_current >= prtd->ch_dma_addr_end)
231 prtd->ch_dma_addr_current = prtd->ch_dma_addr_start;
233 qmc_audio_pcm_read_submit(prtd);
235 snd_pcm_period_elapsed(prtd->substream);
238 static int qmc_audio_pcm_trigger(struct snd_soc_component *component,
239 struct snd_pcm_substream *substream, int cmd)
241 struct qmc_dai_prtd *prtd = substream->runtime->private_data;
242 unsigned int i;
243 int ret;
245 if (!prtd->qmc_dai) {
246 dev_err(component->dev, "qmc_dai is not set\n");
247 return -EINVAL;
250 switch (cmd) {
251 case SNDRV_PCM_TRIGGER_START:
252 bitmap_zero(prtd->chans_pending, 64);
253 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
254 for (i = 0; i < prtd->channels; i++)
255 prtd->qmc_dai->chans[i].prtd_tx = prtd;
257 /* Submit first chunk ... */
258 ret = qmc_audio_pcm_write_submit(prtd);
259 if (ret)
260 return ret;
262 /* ... prepare next one ... */
263 prtd->ch_dma_addr_current += prtd->ch_dma_size;
264 if (prtd->ch_dma_addr_current >= prtd->ch_dma_addr_end)
265 prtd->ch_dma_addr_current = prtd->ch_dma_addr_start;
267 /* ... and send it */
268 ret = qmc_audio_pcm_write_submit(prtd);
269 if (ret)
270 return ret;
271 } else {
272 for (i = 0; i < prtd->channels; i++)
273 prtd->qmc_dai->chans[i].prtd_rx = prtd;
275 /* Submit first chunk ... */
276 ret = qmc_audio_pcm_read_submit(prtd);
277 if (ret)
278 return ret;
280 /* ... prepare next one ... */
281 prtd->ch_dma_addr_current += prtd->ch_dma_size;
282 if (prtd->ch_dma_addr_current >= prtd->ch_dma_addr_end)
283 prtd->ch_dma_addr_current = prtd->ch_dma_addr_start;
285 /* ... and send it */
286 ret = qmc_audio_pcm_read_submit(prtd);
287 if (ret)
288 return ret;
290 break;
292 case SNDRV_PCM_TRIGGER_RESUME:
293 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
294 break;
296 case SNDRV_PCM_TRIGGER_STOP:
297 case SNDRV_PCM_TRIGGER_SUSPEND:
298 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
299 break;
301 default:
302 return -EINVAL;
305 return 0;
308 static snd_pcm_uframes_t qmc_audio_pcm_pointer(struct snd_soc_component *component,
309 struct snd_pcm_substream *substream)
311 struct qmc_dai_prtd *prtd = substream->runtime->private_data;
313 return prtd->buffer_ended;
316 static int qmc_audio_of_xlate_dai_name(struct snd_soc_component *component,
317 const struct of_phandle_args *args,
318 const char **dai_name)
320 struct qmc_audio *qmc_audio = dev_get_drvdata(component->dev);
321 struct snd_soc_dai_driver *dai_driver;
322 int id = args->args[0];
323 int i;
325 for (i = 0; i < qmc_audio->num_dais; i++) {
326 dai_driver = qmc_audio->dai_drivers + i;
327 if (dai_driver->id == id) {
328 *dai_name = dai_driver->name;
329 return 0;
333 return -EINVAL;
336 static const struct snd_pcm_hardware qmc_audio_pcm_hardware = {
337 .info = SNDRV_PCM_INFO_MMAP |
338 SNDRV_PCM_INFO_MMAP_VALID |
339 SNDRV_PCM_INFO_INTERLEAVED |
340 SNDRV_PCM_INFO_NONINTERLEAVED |
341 SNDRV_PCM_INFO_PAUSE,
342 .period_bytes_min = 32,
343 .period_bytes_max = 64 * 1024,
344 .periods_min = 2,
345 .periods_max = 2 * 1024,
346 .buffer_bytes_max = 64 * 1024,
349 static int qmc_audio_pcm_open(struct snd_soc_component *component,
350 struct snd_pcm_substream *substream)
352 struct snd_pcm_runtime *runtime = substream->runtime;
353 struct qmc_dai_prtd *prtd;
354 int ret;
356 snd_soc_set_runtime_hwparams(substream, &qmc_audio_pcm_hardware);
358 /* ensure that buffer size is a multiple of period size */
359 ret = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
360 if (ret < 0)
361 return ret;
363 prtd = kzalloc(sizeof(*prtd), GFP_KERNEL);
364 if (!prtd)
365 return -ENOMEM;
367 runtime->private_data = prtd;
369 return 0;
372 static int qmc_audio_pcm_close(struct snd_soc_component *component,
373 struct snd_pcm_substream *substream)
375 struct qmc_dai_prtd *prtd = substream->runtime->private_data;
377 kfree(prtd);
378 return 0;
381 static const struct snd_soc_component_driver qmc_audio_soc_platform = {
382 .open = qmc_audio_pcm_open,
383 .close = qmc_audio_pcm_close,
384 .hw_params = qmc_audio_pcm_hw_params,
385 .trigger = qmc_audio_pcm_trigger,
386 .pointer = qmc_audio_pcm_pointer,
387 .pcm_construct = qmc_audio_pcm_construct,
388 .of_xlate_dai_name = qmc_audio_of_xlate_dai_name,
391 static unsigned int qmc_dai_get_index(struct snd_soc_dai *dai)
393 struct qmc_audio *qmc_audio = snd_soc_dai_get_drvdata(dai);
395 return dai->driver - qmc_audio->dai_drivers;
398 static struct qmc_dai *qmc_dai_get_data(struct snd_soc_dai *dai)
400 struct qmc_audio *qmc_audio = snd_soc_dai_get_drvdata(dai);
401 unsigned int index;
403 index = qmc_dai_get_index(dai);
404 if (index > qmc_audio->num_dais)
405 return NULL;
407 return qmc_audio->dais + index;
411 * The constraints for format/channel is to match with the number of 8bit
412 * time-slots available.
414 static int qmc_dai_hw_rule_channels_by_format(struct qmc_dai *qmc_dai,
415 struct snd_pcm_hw_params *params,
416 unsigned int nb_ts)
418 struct snd_interval *c = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
419 snd_pcm_format_t format = params_format(params);
420 struct snd_interval ch = {0};
422 switch (snd_pcm_format_physical_width(format)) {
423 case 8:
424 ch.max = nb_ts;
425 break;
426 case 16:
427 ch.max = nb_ts / 2;
428 break;
429 case 32:
430 ch.max = nb_ts / 4;
431 break;
432 case 64:
433 ch.max = nb_ts / 8;
434 break;
435 default:
436 dev_err(qmc_dai->dev, "format physical width %u not supported\n",
437 snd_pcm_format_physical_width(format));
438 return -EINVAL;
441 ch.min = ch.max ? 1 : 0;
443 return snd_interval_refine(c, &ch);
446 static int qmc_dai_hw_rule_playback_channels_by_format(struct snd_pcm_hw_params *params,
447 struct snd_pcm_hw_rule *rule)
449 struct qmc_dai *qmc_dai = rule->private;
451 return qmc_dai_hw_rule_channels_by_format(qmc_dai, params, qmc_dai->nb_tx_ts);
454 static int qmc_dai_hw_rule_capture_channels_by_format(struct snd_pcm_hw_params *params,
455 struct snd_pcm_hw_rule *rule)
457 struct qmc_dai *qmc_dai = rule->private;
459 return qmc_dai_hw_rule_channels_by_format(qmc_dai, params, qmc_dai->nb_rx_ts);
462 static int qmc_dai_hw_rule_format_by_channels(struct qmc_dai *qmc_dai,
463 struct snd_pcm_hw_params *params,
464 unsigned int nb_ts)
466 struct snd_mask *f_old = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
467 unsigned int channels = params_channels(params);
468 unsigned int slot_width;
469 snd_pcm_format_t format;
470 struct snd_mask f_new;
472 if (!channels || channels > nb_ts) {
473 dev_err(qmc_dai->dev, "channels %u not supported\n",
474 nb_ts);
475 return -EINVAL;
478 slot_width = (nb_ts / channels) * 8;
480 snd_mask_none(&f_new);
481 pcm_for_each_format(format) {
482 if (snd_mask_test_format(f_old, format)) {
483 if (snd_pcm_format_physical_width(format) <= slot_width)
484 snd_mask_set_format(&f_new, format);
488 return snd_mask_refine(f_old, &f_new);
491 static int qmc_dai_hw_rule_playback_format_by_channels(struct snd_pcm_hw_params *params,
492 struct snd_pcm_hw_rule *rule)
494 struct qmc_dai *qmc_dai = rule->private;
496 return qmc_dai_hw_rule_format_by_channels(qmc_dai, params, qmc_dai->nb_tx_ts);
499 static int qmc_dai_hw_rule_capture_format_by_channels(struct snd_pcm_hw_params *params,
500 struct snd_pcm_hw_rule *rule)
502 struct qmc_dai *qmc_dai = rule->private;
504 return qmc_dai_hw_rule_format_by_channels(qmc_dai, params, qmc_dai->nb_rx_ts);
507 static int qmc_dai_constraints_interleaved(struct snd_pcm_substream *substream,
508 struct qmc_dai *qmc_dai)
510 snd_pcm_hw_rule_func_t hw_rule_channels_by_format;
511 snd_pcm_hw_rule_func_t hw_rule_format_by_channels;
512 unsigned int frame_bits;
513 u64 access;
514 int ret;
516 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
517 hw_rule_channels_by_format = qmc_dai_hw_rule_capture_channels_by_format;
518 hw_rule_format_by_channels = qmc_dai_hw_rule_capture_format_by_channels;
519 frame_bits = qmc_dai->nb_rx_ts * 8;
520 } else {
521 hw_rule_channels_by_format = qmc_dai_hw_rule_playback_channels_by_format;
522 hw_rule_format_by_channels = qmc_dai_hw_rule_playback_format_by_channels;
523 frame_bits = qmc_dai->nb_tx_ts * 8;
526 ret = snd_pcm_hw_rule_add(substream->runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
527 hw_rule_channels_by_format, qmc_dai,
528 SNDRV_PCM_HW_PARAM_FORMAT, -1);
529 if (ret) {
530 dev_err(qmc_dai->dev, "Failed to add channels rule (%d)\n", ret);
531 return ret;
534 ret = snd_pcm_hw_rule_add(substream->runtime, 0, SNDRV_PCM_HW_PARAM_FORMAT,
535 hw_rule_format_by_channels, qmc_dai,
536 SNDRV_PCM_HW_PARAM_CHANNELS, -1);
537 if (ret) {
538 dev_err(qmc_dai->dev, "Failed to add format rule (%d)\n", ret);
539 return ret;
542 ret = snd_pcm_hw_constraint_single(substream->runtime,
543 SNDRV_PCM_HW_PARAM_FRAME_BITS,
544 frame_bits);
545 if (ret < 0) {
546 dev_err(qmc_dai->dev, "Failed to add frame_bits constraint (%d)\n", ret);
547 return ret;
550 access = 1ULL << (__force int)SNDRV_PCM_ACCESS_MMAP_INTERLEAVED |
551 1ULL << (__force int)SNDRV_PCM_ACCESS_RW_INTERLEAVED;
552 ret = snd_pcm_hw_constraint_mask64(substream->runtime, SNDRV_PCM_HW_PARAM_ACCESS,
553 access);
554 if (ret) {
555 dev_err(qmc_dai->dev, "Failed to add hw_param_access constraint (%d)\n", ret);
556 return ret;
559 return 0;
562 static int qmc_dai_constraints_noninterleaved(struct snd_pcm_substream *substream,
563 struct qmc_dai *qmc_dai)
565 unsigned int frame_bits;
566 u64 access;
567 int ret;
569 frame_bits = (substream->stream == SNDRV_PCM_STREAM_CAPTURE) ?
570 qmc_dai->nb_rx_ts * 8 : qmc_dai->nb_tx_ts * 8;
571 ret = snd_pcm_hw_constraint_single(substream->runtime,
572 SNDRV_PCM_HW_PARAM_FRAME_BITS,
573 frame_bits);
574 if (ret < 0) {
575 dev_err(qmc_dai->dev, "Failed to add frame_bits constraint (%d)\n", ret);
576 return ret;
579 access = 1ULL << (__force int)SNDRV_PCM_ACCESS_MMAP_NONINTERLEAVED |
580 1ULL << (__force int)SNDRV_PCM_ACCESS_RW_NONINTERLEAVED;
581 ret = snd_pcm_hw_constraint_mask64(substream->runtime, SNDRV_PCM_HW_PARAM_ACCESS,
582 access);
583 if (ret) {
584 dev_err(qmc_dai->dev, "Failed to add hw_param_access constraint (%d)\n", ret);
585 return ret;
588 return 0;
591 static int qmc_dai_startup(struct snd_pcm_substream *substream,
592 struct snd_soc_dai *dai)
594 struct qmc_dai_prtd *prtd = substream->runtime->private_data;
595 struct qmc_dai *qmc_dai;
597 qmc_dai = qmc_dai_get_data(dai);
598 if (!qmc_dai) {
599 dev_err(dai->dev, "Invalid dai\n");
600 return -EINVAL;
603 prtd->qmc_dai = qmc_dai;
605 return qmc_dai->nb_chans_avail > 1 ?
606 qmc_dai_constraints_noninterleaved(substream, qmc_dai) :
607 qmc_dai_constraints_interleaved(substream, qmc_dai);
610 static int qmc_dai_hw_params(struct snd_pcm_substream *substream,
611 struct snd_pcm_hw_params *params,
612 struct snd_soc_dai *dai)
614 struct qmc_chan_param chan_param = {0};
615 unsigned int nb_chans_used;
616 struct qmc_dai *qmc_dai;
617 unsigned int i;
618 int ret;
620 qmc_dai = qmc_dai_get_data(dai);
621 if (!qmc_dai) {
622 dev_err(dai->dev, "Invalid dai\n");
623 return -EINVAL;
627 * In interleaved mode, the driver uses one QMC channel for all audio
628 * channels whereas in non-interleaved mode, it uses one QMC channel per
629 * audio channel.
631 nb_chans_used = qmc_audio_access_is_interleaved(params_access(params)) ?
632 1 : params_channels(params);
634 if (nb_chans_used > qmc_dai->nb_chans_avail) {
635 dev_err(dai->dev, "Not enough qmc_chans. Need %u, avail %u\n",
636 nb_chans_used, qmc_dai->nb_chans_avail);
637 return -EINVAL;
640 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
641 chan_param.mode = QMC_TRANSPARENT;
642 chan_param.transp.max_rx_buf_size = params_period_bytes(params) / nb_chans_used;
643 for (i = 0; i < nb_chans_used; i++) {
644 ret = qmc_chan_set_param(qmc_dai->chans[i].qmc_chan, &chan_param);
645 if (ret) {
646 dev_err(dai->dev, "chans[%u], set param failed %d\n",
647 i, ret);
648 return ret;
651 qmc_dai->nb_chans_used_rx = nb_chans_used;
652 } else {
653 qmc_dai->nb_chans_used_tx = nb_chans_used;
656 return 0;
659 static int qmc_dai_trigger(struct snd_pcm_substream *substream, int cmd,
660 struct snd_soc_dai *dai)
662 unsigned int nb_chans_used;
663 struct qmc_dai *qmc_dai;
664 unsigned int i;
665 int direction;
666 int ret = 0;
667 int ret_tmp;
669 qmc_dai = qmc_dai_get_data(dai);
670 if (!qmc_dai) {
671 dev_err(dai->dev, "Invalid dai\n");
672 return -EINVAL;
675 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
676 direction = QMC_CHAN_WRITE;
677 nb_chans_used = qmc_dai->nb_chans_used_tx;
678 } else {
679 direction = QMC_CHAN_READ;
680 nb_chans_used = qmc_dai->nb_chans_used_rx;
683 switch (cmd) {
684 case SNDRV_PCM_TRIGGER_START:
685 case SNDRV_PCM_TRIGGER_RESUME:
686 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
687 for (i = 0; i < nb_chans_used; i++) {
688 ret = qmc_chan_start(qmc_dai->chans[i].qmc_chan, direction);
689 if (ret)
690 goto err_stop;
692 break;
694 case SNDRV_PCM_TRIGGER_STOP:
695 /* Stop and reset all QMC channels and return the first error encountered */
696 for (i = 0; i < nb_chans_used; i++) {
697 ret_tmp = qmc_chan_stop(qmc_dai->chans[i].qmc_chan, direction);
698 if (!ret)
699 ret = ret_tmp;
700 if (ret_tmp)
701 continue;
703 ret_tmp = qmc_chan_reset(qmc_dai->chans[i].qmc_chan, direction);
704 if (!ret)
705 ret = ret_tmp;
707 if (ret)
708 return ret;
709 break;
711 case SNDRV_PCM_TRIGGER_SUSPEND:
712 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
713 /* Stop all QMC channels and return the first error encountered */
714 for (i = 0; i < nb_chans_used; i++) {
715 ret_tmp = qmc_chan_stop(qmc_dai->chans[i].qmc_chan, direction);
716 if (!ret)
717 ret = ret_tmp;
719 if (ret)
720 return ret;
721 break;
723 default:
724 return -EINVAL;
727 return 0;
729 err_stop:
730 while (i--) {
731 qmc_chan_stop(qmc_dai->chans[i].qmc_chan, direction);
732 qmc_chan_reset(qmc_dai->chans[i].qmc_chan, direction);
734 return ret;
737 static const struct snd_soc_dai_ops qmc_dai_ops = {
738 .startup = qmc_dai_startup,
739 .trigger = qmc_dai_trigger,
740 .hw_params = qmc_dai_hw_params,
743 static u64 qmc_audio_formats(u8 nb_ts, bool is_noninterleaved)
745 unsigned int format_width;
746 unsigned int chan_width;
747 snd_pcm_format_t format;
748 u64 formats_mask;
750 if (!nb_ts)
751 return 0;
753 formats_mask = 0;
754 chan_width = nb_ts * 8;
755 pcm_for_each_format(format) {
757 * Support format other than little-endian (ie big-endian or
758 * without endianness such as 8bit formats)
760 if (snd_pcm_format_little_endian(format) == 1)
761 continue;
763 /* Support physical width multiple of 8bit */
764 format_width = snd_pcm_format_physical_width(format);
765 if (format_width == 0 || format_width % 8)
766 continue;
769 * And support physical width that can fit N times in the
770 * channel
772 if (format_width > chan_width || chan_width % format_width)
773 continue;
776 * In non interleaved mode, we can only support formats that
777 * can fit only 1 time in the channel
779 if (is_noninterleaved && format_width != chan_width)
780 continue;
782 formats_mask |= pcm_format_to_bits(format);
784 return formats_mask;
787 static int qmc_audio_dai_parse(struct qmc_audio *qmc_audio, struct device_node *np,
788 struct qmc_dai *qmc_dai,
789 struct snd_soc_dai_driver *qmc_soc_dai_driver)
791 struct qmc_chan_info info;
792 unsigned long rx_fs_rate;
793 unsigned long tx_fs_rate;
794 unsigned int nb_tx_ts;
795 unsigned int nb_rx_ts;
796 unsigned int i;
797 int count;
798 u32 val;
799 int ret;
801 qmc_dai->dev = qmc_audio->dev;
803 ret = of_property_read_u32(np, "reg", &val);
804 if (ret) {
805 dev_err(qmc_audio->dev, "%pOF: failed to read reg\n", np);
806 return ret;
808 qmc_dai->id = val;
810 qmc_dai->name = devm_kasprintf(qmc_audio->dev, GFP_KERNEL, "%s.%d",
811 np->parent->name, qmc_dai->id);
812 if (!qmc_dai->name)
813 return -ENOMEM;
815 count = qmc_chan_count_phandles(np, "fsl,qmc-chan");
816 if (count < 0)
817 return dev_err_probe(qmc_audio->dev, count,
818 "dai %d get number of QMC channel failed\n", qmc_dai->id);
819 if (!count)
820 return dev_err_probe(qmc_audio->dev, -EINVAL,
821 "dai %d no QMC channel defined\n", qmc_dai->id);
823 qmc_dai->chans = devm_kcalloc(qmc_audio->dev, count, sizeof(*qmc_dai->chans), GFP_KERNEL);
824 if (!qmc_dai->chans)
825 return -ENOMEM;
827 for (i = 0; i < count; i++) {
828 qmc_dai->chans[i].qmc_chan = devm_qmc_chan_get_byphandles_index(qmc_audio->dev, np,
829 "fsl,qmc-chan", i);
830 if (IS_ERR(qmc_dai->chans[i].qmc_chan)) {
831 return dev_err_probe(qmc_audio->dev, PTR_ERR(qmc_dai->chans[i].qmc_chan),
832 "dai %d get QMC channel %d failed\n", qmc_dai->id, i);
835 ret = qmc_chan_get_info(qmc_dai->chans[i].qmc_chan, &info);
836 if (ret) {
837 dev_err(qmc_audio->dev, "dai %d get QMC %d channel info failed %d\n",
838 qmc_dai->id, i, ret);
839 return ret;
842 if (info.mode != QMC_TRANSPARENT) {
843 dev_err(qmc_audio->dev, "dai %d QMC chan %d mode %d is not QMC_TRANSPARENT\n",
844 qmc_dai->id, i, info.mode);
845 return -EINVAL;
849 * All channels must have the same number of Tx slots and the
850 * same numbers of Rx slots.
852 if (i == 0) {
853 nb_tx_ts = info.nb_tx_ts;
854 nb_rx_ts = info.nb_rx_ts;
855 tx_fs_rate = info.tx_fs_rate;
856 rx_fs_rate = info.rx_fs_rate;
857 } else {
858 if (nb_tx_ts != info.nb_tx_ts) {
859 dev_err(qmc_audio->dev, "dai %d QMC chan %d inconsistent number of Tx timeslots (%u instead of %u)\n",
860 qmc_dai->id, i, info.nb_tx_ts, nb_tx_ts);
861 return -EINVAL;
863 if (nb_rx_ts != info.nb_rx_ts) {
864 dev_err(qmc_audio->dev, "dai %d QMC chan %d inconsistent number of Rx timeslots (%u instead of %u)\n",
865 qmc_dai->id, i, info.nb_rx_ts, nb_rx_ts);
866 return -EINVAL;
868 if (tx_fs_rate != info.tx_fs_rate) {
869 dev_err(qmc_audio->dev, "dai %d QMC chan %d inconsistent Tx frame sample rate (%lu instead of %lu)\n",
870 qmc_dai->id, i, info.tx_fs_rate, tx_fs_rate);
871 return -EINVAL;
873 if (rx_fs_rate != info.rx_fs_rate) {
874 dev_err(qmc_audio->dev, "dai %d QMC chan %d inconsistent Rx frame sample rate (%lu instead of %lu)\n",
875 qmc_dai->id, i, info.rx_fs_rate, rx_fs_rate);
876 return -EINVAL;
881 qmc_dai->nb_chans_avail = count;
882 qmc_dai->nb_tx_ts = nb_tx_ts * count;
883 qmc_dai->nb_rx_ts = nb_rx_ts * count;
885 qmc_soc_dai_driver->id = qmc_dai->id;
886 qmc_soc_dai_driver->name = qmc_dai->name;
888 qmc_soc_dai_driver->playback.channels_min = 0;
889 qmc_soc_dai_driver->playback.channels_max = 0;
890 if (nb_tx_ts) {
891 qmc_soc_dai_driver->playback.channels_min = 1;
892 qmc_soc_dai_driver->playback.channels_max = count > 1 ? count : nb_tx_ts;
894 qmc_soc_dai_driver->playback.formats = qmc_audio_formats(nb_tx_ts,
895 count > 1 ? true : false);
897 qmc_soc_dai_driver->capture.channels_min = 0;
898 qmc_soc_dai_driver->capture.channels_max = 0;
899 if (nb_rx_ts) {
900 qmc_soc_dai_driver->capture.channels_min = 1;
901 qmc_soc_dai_driver->capture.channels_max = count > 1 ? count : nb_rx_ts;
903 qmc_soc_dai_driver->capture.formats = qmc_audio_formats(nb_rx_ts,
904 count > 1 ? true : false);
906 qmc_soc_dai_driver->playback.rates = snd_pcm_rate_to_rate_bit(tx_fs_rate);
907 qmc_soc_dai_driver->playback.rate_min = tx_fs_rate;
908 qmc_soc_dai_driver->playback.rate_max = tx_fs_rate;
909 qmc_soc_dai_driver->capture.rates = snd_pcm_rate_to_rate_bit(rx_fs_rate);
910 qmc_soc_dai_driver->capture.rate_min = rx_fs_rate;
911 qmc_soc_dai_driver->capture.rate_max = rx_fs_rate;
913 qmc_soc_dai_driver->ops = &qmc_dai_ops;
915 return 0;
918 static int qmc_audio_probe(struct platform_device *pdev)
920 struct device_node *np = pdev->dev.of_node;
921 struct qmc_audio *qmc_audio;
922 struct device_node *child;
923 unsigned int i;
924 int ret;
926 qmc_audio = devm_kzalloc(&pdev->dev, sizeof(*qmc_audio), GFP_KERNEL);
927 if (!qmc_audio)
928 return -ENOMEM;
930 qmc_audio->dev = &pdev->dev;
932 qmc_audio->num_dais = of_get_available_child_count(np);
933 if (qmc_audio->num_dais) {
934 qmc_audio->dais = devm_kcalloc(&pdev->dev, qmc_audio->num_dais,
935 sizeof(*qmc_audio->dais),
936 GFP_KERNEL);
937 if (!qmc_audio->dais)
938 return -ENOMEM;
940 qmc_audio->dai_drivers = devm_kcalloc(&pdev->dev, qmc_audio->num_dais,
941 sizeof(*qmc_audio->dai_drivers),
942 GFP_KERNEL);
943 if (!qmc_audio->dai_drivers)
944 return -ENOMEM;
947 i = 0;
948 for_each_available_child_of_node(np, child) {
949 ret = qmc_audio_dai_parse(qmc_audio, child,
950 qmc_audio->dais + i,
951 qmc_audio->dai_drivers + i);
952 if (ret) {
953 of_node_put(child);
954 return ret;
956 i++;
959 platform_set_drvdata(pdev, qmc_audio);
961 ret = devm_snd_soc_register_component(qmc_audio->dev,
962 &qmc_audio_soc_platform,
963 qmc_audio->dai_drivers,
964 qmc_audio->num_dais);
965 if (ret)
966 return ret;
968 return 0;
971 static const struct of_device_id qmc_audio_id_table[] = {
972 { .compatible = "fsl,qmc-audio" },
973 {} /* sentinel */
975 MODULE_DEVICE_TABLE(of, qmc_audio_id_table);
977 static struct platform_driver qmc_audio_driver = {
978 .driver = {
979 .name = "fsl-qmc-audio",
980 .of_match_table = of_match_ptr(qmc_audio_id_table),
982 .probe = qmc_audio_probe,
984 module_platform_driver(qmc_audio_driver);
986 MODULE_AUTHOR("Herve Codina <herve.codina@bootlin.com>");
987 MODULE_DESCRIPTION("CPM/QE QMC audio driver");
988 MODULE_LICENSE("GPL");