GNU Linux-libre 6.9.1-gnu
[releases.git] / sound / soc / fsl / fsl_qmc_audio.c
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         struct qmc_chan *qmc_chan;
25         unsigned int nb_tx_ts;
26         unsigned int nb_rx_ts;
27 };
28
29 struct qmc_audio {
30         struct device *dev;
31         unsigned int num_dais;
32         struct qmc_dai *dais;
33         struct snd_soc_dai_driver *dai_drivers;
34 };
35
36 struct qmc_dai_prtd {
37         struct qmc_dai *qmc_dai;
38         dma_addr_t dma_buffer_start;
39         dma_addr_t period_ptr_submitted;
40         dma_addr_t period_ptr_ended;
41         dma_addr_t dma_buffer_end;
42         size_t period_size;
43         struct snd_pcm_substream *substream;
44 };
45
46 static int qmc_audio_pcm_construct(struct snd_soc_component *component,
47                                    struct snd_soc_pcm_runtime *rtd)
48 {
49         struct snd_card *card = rtd->card->snd_card;
50         int ret;
51
52         ret = dma_coerce_mask_and_coherent(card->dev, DMA_BIT_MASK(32));
53         if (ret)
54                 return ret;
55
56         snd_pcm_set_managed_buffer_all(rtd->pcm, SNDRV_DMA_TYPE_DEV, card->dev,
57                                        64*1024, 64*1024);
58         return 0;
59 }
60
61 static int qmc_audio_pcm_hw_params(struct snd_soc_component *component,
62                                    struct snd_pcm_substream *substream,
63                                    struct snd_pcm_hw_params *params)
64 {
65         struct snd_pcm_runtime *runtime = substream->runtime;
66         struct qmc_dai_prtd *prtd = substream->runtime->private_data;
67
68         prtd->dma_buffer_start = runtime->dma_addr;
69         prtd->dma_buffer_end = runtime->dma_addr + params_buffer_bytes(params);
70         prtd->period_size = params_period_bytes(params);
71         prtd->period_ptr_submitted = prtd->dma_buffer_start;
72         prtd->period_ptr_ended = prtd->dma_buffer_start;
73         prtd->substream = substream;
74
75         return 0;
76 }
77
78 static void qmc_audio_pcm_write_complete(void *context)
79 {
80         struct qmc_dai_prtd *prtd = context;
81         int ret;
82
83         prtd->period_ptr_ended += prtd->period_size;
84         if (prtd->period_ptr_ended >= prtd->dma_buffer_end)
85                 prtd->period_ptr_ended = prtd->dma_buffer_start;
86
87         prtd->period_ptr_submitted += prtd->period_size;
88         if (prtd->period_ptr_submitted >= prtd->dma_buffer_end)
89                 prtd->period_ptr_submitted = prtd->dma_buffer_start;
90
91         ret = qmc_chan_write_submit(prtd->qmc_dai->qmc_chan,
92                 prtd->period_ptr_submitted, prtd->period_size,
93                 qmc_audio_pcm_write_complete, prtd);
94         if (ret) {
95                 dev_err(prtd->qmc_dai->dev, "write_submit failed %d\n",
96                         ret);
97         }
98
99         snd_pcm_period_elapsed(prtd->substream);
100 }
101
102 static void qmc_audio_pcm_read_complete(void *context, size_t length, unsigned int flags)
103 {
104         struct qmc_dai_prtd *prtd = context;
105         int ret;
106
107         if (length != prtd->period_size) {
108                 dev_err(prtd->qmc_dai->dev, "read complete length = %zu, exp %zu\n",
109                         length, prtd->period_size);
110         }
111
112         prtd->period_ptr_ended += prtd->period_size;
113         if (prtd->period_ptr_ended >= prtd->dma_buffer_end)
114                 prtd->period_ptr_ended = prtd->dma_buffer_start;
115
116         prtd->period_ptr_submitted += prtd->period_size;
117         if (prtd->period_ptr_submitted >= prtd->dma_buffer_end)
118                 prtd->period_ptr_submitted = prtd->dma_buffer_start;
119
120         ret = qmc_chan_read_submit(prtd->qmc_dai->qmc_chan,
121                 prtd->period_ptr_submitted, prtd->period_size,
122                 qmc_audio_pcm_read_complete, prtd);
123         if (ret) {
124                 dev_err(prtd->qmc_dai->dev, "read_submit failed %d\n",
125                         ret);
126         }
127
128         snd_pcm_period_elapsed(prtd->substream);
129 }
130
131 static int qmc_audio_pcm_trigger(struct snd_soc_component *component,
132                                  struct snd_pcm_substream *substream, int cmd)
133 {
134         struct qmc_dai_prtd *prtd = substream->runtime->private_data;
135         int ret;
136
137         if (!prtd->qmc_dai) {
138                 dev_err(component->dev, "qmc_dai is not set\n");
139                 return -EINVAL;
140         }
141
142         switch (cmd) {
143         case SNDRV_PCM_TRIGGER_START:
144                 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
145                         /* Submit first chunk ... */
146                         ret = qmc_chan_write_submit(prtd->qmc_dai->qmc_chan,
147                                 prtd->period_ptr_submitted, prtd->period_size,
148                                 qmc_audio_pcm_write_complete, prtd);
149                         if (ret) {
150                                 dev_err(component->dev, "write_submit failed %d\n",
151                                         ret);
152                                 return ret;
153                         }
154
155                         /* ... prepare next one ... */
156                         prtd->period_ptr_submitted += prtd->period_size;
157                         if (prtd->period_ptr_submitted >= prtd->dma_buffer_end)
158                                 prtd->period_ptr_submitted = prtd->dma_buffer_start;
159
160                         /* ... and send it */
161                         ret = qmc_chan_write_submit(prtd->qmc_dai->qmc_chan,
162                                 prtd->period_ptr_submitted, prtd->period_size,
163                                 qmc_audio_pcm_write_complete, prtd);
164                         if (ret) {
165                                 dev_err(component->dev, "write_submit failed %d\n",
166                                         ret);
167                                 return ret;
168                         }
169                 } else {
170                         /* Submit first chunk ... */
171                         ret = qmc_chan_read_submit(prtd->qmc_dai->qmc_chan,
172                                 prtd->period_ptr_submitted, prtd->period_size,
173                                 qmc_audio_pcm_read_complete, prtd);
174                         if (ret) {
175                                 dev_err(component->dev, "read_submit failed %d\n",
176                                         ret);
177                                 return ret;
178                         }
179
180                         /* ... prepare next one ... */
181                         prtd->period_ptr_submitted += prtd->period_size;
182                         if (prtd->period_ptr_submitted >= prtd->dma_buffer_end)
183                                 prtd->period_ptr_submitted = prtd->dma_buffer_start;
184
185                         /* ... and send it */
186                         ret = qmc_chan_read_submit(prtd->qmc_dai->qmc_chan,
187                                 prtd->period_ptr_submitted, prtd->period_size,
188                                 qmc_audio_pcm_read_complete, prtd);
189                         if (ret) {
190                                 dev_err(component->dev, "write_submit failed %d\n",
191                                         ret);
192                                 return ret;
193                         }
194                 }
195                 break;
196
197         case SNDRV_PCM_TRIGGER_RESUME:
198         case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
199                 break;
200
201         case SNDRV_PCM_TRIGGER_STOP:
202         case SNDRV_PCM_TRIGGER_SUSPEND:
203         case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
204                 break;
205
206         default:
207                 return -EINVAL;
208         }
209
210         return 0;
211 }
212
213 static snd_pcm_uframes_t qmc_audio_pcm_pointer(struct snd_soc_component *component,
214                                                struct snd_pcm_substream *substream)
215 {
216         struct qmc_dai_prtd *prtd = substream->runtime->private_data;
217
218         return bytes_to_frames(substream->runtime,
219                                prtd->period_ptr_ended - prtd->dma_buffer_start);
220 }
221
222 static int qmc_audio_of_xlate_dai_name(struct snd_soc_component *component,
223                                         const struct of_phandle_args *args,
224                                         const char **dai_name)
225 {
226         struct qmc_audio *qmc_audio = dev_get_drvdata(component->dev);
227         struct snd_soc_dai_driver *dai_driver;
228         int id = args->args[0];
229         int i;
230
231         for (i = 0; i  < qmc_audio->num_dais; i++) {
232                 dai_driver = qmc_audio->dai_drivers + i;
233                 if (dai_driver->id == id) {
234                         *dai_name = dai_driver->name;
235                         return 0;
236                 }
237         }
238
239         return -EINVAL;
240 }
241
242 static const struct snd_pcm_hardware qmc_audio_pcm_hardware = {
243         .info                   = SNDRV_PCM_INFO_MMAP |
244                                   SNDRV_PCM_INFO_MMAP_VALID |
245                                   SNDRV_PCM_INFO_INTERLEAVED |
246                                   SNDRV_PCM_INFO_PAUSE,
247         .period_bytes_min       = 32,
248         .period_bytes_max       = 64*1024,
249         .periods_min            = 2,
250         .periods_max            = 2*1024,
251         .buffer_bytes_max       = 64*1024,
252 };
253
254 static int qmc_audio_pcm_open(struct snd_soc_component *component,
255                               struct snd_pcm_substream *substream)
256 {
257         struct snd_pcm_runtime *runtime = substream->runtime;
258         struct qmc_dai_prtd *prtd;
259         int ret;
260
261         snd_soc_set_runtime_hwparams(substream, &qmc_audio_pcm_hardware);
262
263         /* ensure that buffer size is a multiple of period size */
264         ret = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
265         if (ret < 0)
266                 return ret;
267
268         prtd = kzalloc(sizeof(*prtd), GFP_KERNEL);
269         if (prtd == NULL)
270                 return -ENOMEM;
271
272         runtime->private_data = prtd;
273
274         return 0;
275 }
276
277 static int qmc_audio_pcm_close(struct snd_soc_component *component,
278                                struct snd_pcm_substream *substream)
279 {
280         struct qmc_dai_prtd *prtd = substream->runtime->private_data;
281
282         kfree(prtd);
283         return 0;
284 }
285
286 static const struct snd_soc_component_driver qmc_audio_soc_platform = {
287         .open                   = qmc_audio_pcm_open,
288         .close                  = qmc_audio_pcm_close,
289         .hw_params              = qmc_audio_pcm_hw_params,
290         .trigger                = qmc_audio_pcm_trigger,
291         .pointer                = qmc_audio_pcm_pointer,
292         .pcm_construct          = qmc_audio_pcm_construct,
293         .of_xlate_dai_name      = qmc_audio_of_xlate_dai_name,
294 };
295
296 static unsigned int qmc_dai_get_index(struct snd_soc_dai *dai)
297 {
298         struct qmc_audio *qmc_audio = snd_soc_dai_get_drvdata(dai);
299
300         return dai->driver - qmc_audio->dai_drivers;
301 }
302
303 static struct qmc_dai *qmc_dai_get_data(struct snd_soc_dai *dai)
304 {
305         struct qmc_audio *qmc_audio = snd_soc_dai_get_drvdata(dai);
306         unsigned int index;
307
308         index = qmc_dai_get_index(dai);
309         if (index > qmc_audio->num_dais)
310                 return NULL;
311
312         return qmc_audio->dais + index;
313 }
314
315 /*
316  * The constraints for format/channel is to match with the number of 8bit
317  * time-slots available.
318  */
319 static int qmc_dai_hw_rule_channels_by_format(struct qmc_dai *qmc_dai,
320                                               struct snd_pcm_hw_params *params,
321                                               unsigned int nb_ts)
322 {
323         struct snd_interval *c = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
324         snd_pcm_format_t format = params_format(params);
325         struct snd_interval ch = {0};
326
327         switch (snd_pcm_format_physical_width(format)) {
328         case 8:
329                 ch.max = nb_ts;
330                 break;
331         case 16:
332                 ch.max = nb_ts/2;
333                 break;
334         case 32:
335                 ch.max = nb_ts/4;
336                 break;
337         case 64:
338                 ch.max = nb_ts/8;
339                 break;
340         default:
341                 dev_err(qmc_dai->dev, "format physical width %u not supported\n",
342                         snd_pcm_format_physical_width(format));
343                 return -EINVAL;
344         }
345
346         ch.min = ch.max ? 1 : 0;
347
348         return snd_interval_refine(c, &ch);
349 }
350
351 static int qmc_dai_hw_rule_playback_channels_by_format(struct snd_pcm_hw_params *params,
352                                                        struct snd_pcm_hw_rule *rule)
353 {
354         struct qmc_dai *qmc_dai = rule->private;
355
356         return qmc_dai_hw_rule_channels_by_format(qmc_dai, params, qmc_dai->nb_tx_ts);
357 }
358
359 static int qmc_dai_hw_rule_capture_channels_by_format(
360                         struct snd_pcm_hw_params *params,
361                         struct snd_pcm_hw_rule *rule)
362 {
363         struct qmc_dai *qmc_dai = rule->private;
364
365         return qmc_dai_hw_rule_channels_by_format(qmc_dai, params, qmc_dai->nb_rx_ts);
366 }
367
368 static int qmc_dai_hw_rule_format_by_channels(struct qmc_dai *qmc_dai,
369                                               struct snd_pcm_hw_params *params,
370                                               unsigned int nb_ts)
371 {
372         struct snd_mask *f_old = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
373         unsigned int channels = params_channels(params);
374         unsigned int slot_width;
375         snd_pcm_format_t format;
376         struct snd_mask f_new;
377
378         if (!channels || channels > nb_ts) {
379                 dev_err(qmc_dai->dev, "channels %u not supported\n",
380                         nb_ts);
381                 return -EINVAL;
382         }
383
384         slot_width = (nb_ts / channels) * 8;
385
386         snd_mask_none(&f_new);
387         pcm_for_each_format(format) {
388                 if (snd_mask_test_format(f_old, format)) {
389                         if (snd_pcm_format_physical_width(format) <= slot_width)
390                                 snd_mask_set_format(&f_new, format);
391                 }
392         }
393
394         return snd_mask_refine(f_old, &f_new);
395 }
396
397 static int qmc_dai_hw_rule_playback_format_by_channels(
398                         struct snd_pcm_hw_params *params,
399                         struct snd_pcm_hw_rule *rule)
400 {
401         struct qmc_dai *qmc_dai = rule->private;
402
403         return qmc_dai_hw_rule_format_by_channels(qmc_dai, params, qmc_dai->nb_tx_ts);
404 }
405
406 static int qmc_dai_hw_rule_capture_format_by_channels(
407                         struct snd_pcm_hw_params *params,
408                         struct snd_pcm_hw_rule *rule)
409 {
410         struct qmc_dai *qmc_dai = rule->private;
411
412         return qmc_dai_hw_rule_format_by_channels(qmc_dai, params, qmc_dai->nb_rx_ts);
413 }
414
415 static int qmc_dai_startup(struct snd_pcm_substream *substream,
416                              struct snd_soc_dai *dai)
417 {
418         struct qmc_dai_prtd *prtd = substream->runtime->private_data;
419         snd_pcm_hw_rule_func_t hw_rule_channels_by_format;
420         snd_pcm_hw_rule_func_t hw_rule_format_by_channels;
421         struct qmc_dai *qmc_dai;
422         unsigned int frame_bits;
423         int ret;
424
425         qmc_dai = qmc_dai_get_data(dai);
426         if (!qmc_dai) {
427                 dev_err(dai->dev, "Invalid dai\n");
428                 return -EINVAL;
429         }
430
431         prtd->qmc_dai = qmc_dai;
432
433         if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
434                 hw_rule_channels_by_format = qmc_dai_hw_rule_capture_channels_by_format;
435                 hw_rule_format_by_channels = qmc_dai_hw_rule_capture_format_by_channels;
436                 frame_bits = qmc_dai->nb_rx_ts * 8;
437         } else {
438                 hw_rule_channels_by_format = qmc_dai_hw_rule_playback_channels_by_format;
439                 hw_rule_format_by_channels = qmc_dai_hw_rule_playback_format_by_channels;
440                 frame_bits = qmc_dai->nb_tx_ts * 8;
441         }
442
443         ret = snd_pcm_hw_rule_add(substream->runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
444                                   hw_rule_channels_by_format, qmc_dai,
445                                   SNDRV_PCM_HW_PARAM_FORMAT, -1);
446         if (ret) {
447                 dev_err(dai->dev, "Failed to add channels rule (%d)\n", ret);
448                 return ret;
449         }
450
451         ret = snd_pcm_hw_rule_add(substream->runtime, 0,  SNDRV_PCM_HW_PARAM_FORMAT,
452                                   hw_rule_format_by_channels, qmc_dai,
453                                   SNDRV_PCM_HW_PARAM_CHANNELS, -1);
454         if (ret) {
455                 dev_err(dai->dev, "Failed to add format rule (%d)\n", ret);
456                 return ret;
457         }
458
459         ret = snd_pcm_hw_constraint_single(substream->runtime,
460                                            SNDRV_PCM_HW_PARAM_FRAME_BITS,
461                                            frame_bits);
462         if (ret < 0) {
463                 dev_err(dai->dev, "Failed to add frame_bits constraint (%d)\n", ret);
464                 return ret;
465         }
466
467         return 0;
468 }
469
470 static int qmc_dai_hw_params(struct snd_pcm_substream *substream,
471                              struct snd_pcm_hw_params *params,
472                              struct snd_soc_dai *dai)
473 {
474         struct qmc_chan_param chan_param = {0};
475         struct qmc_dai *qmc_dai;
476         int ret;
477
478         qmc_dai = qmc_dai_get_data(dai);
479         if (!qmc_dai) {
480                 dev_err(dai->dev, "Invalid dai\n");
481                 return -EINVAL;
482         }
483
484         if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
485                 chan_param.mode = QMC_TRANSPARENT;
486                 chan_param.transp.max_rx_buf_size = params_period_bytes(params);
487                 ret = qmc_chan_set_param(qmc_dai->qmc_chan, &chan_param);
488                 if (ret) {
489                         dev_err(dai->dev, "set param failed %d\n",
490                                 ret);
491                         return ret;
492                 }
493         }
494
495         return 0;
496 }
497
498 static int qmc_dai_trigger(struct snd_pcm_substream *substream, int cmd,
499                            struct snd_soc_dai *dai)
500 {
501         struct qmc_dai *qmc_dai;
502         int direction;
503         int ret;
504
505         qmc_dai = qmc_dai_get_data(dai);
506         if (!qmc_dai) {
507                 dev_err(dai->dev, "Invalid dai\n");
508                 return -EINVAL;
509         }
510
511         direction = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
512                     QMC_CHAN_WRITE : QMC_CHAN_READ;
513
514         switch (cmd) {
515         case SNDRV_PCM_TRIGGER_START:
516         case SNDRV_PCM_TRIGGER_RESUME:
517         case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
518                 ret = qmc_chan_start(qmc_dai->qmc_chan, direction);
519                 if (ret)
520                         return ret;
521                 break;
522
523         case SNDRV_PCM_TRIGGER_STOP:
524                 ret = qmc_chan_stop(qmc_dai->qmc_chan, direction);
525                 if (ret)
526                         return ret;
527                 ret = qmc_chan_reset(qmc_dai->qmc_chan, direction);
528                 if (ret)
529                         return ret;
530                 break;
531
532         case SNDRV_PCM_TRIGGER_SUSPEND:
533         case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
534                 ret = qmc_chan_stop(qmc_dai->qmc_chan, direction);
535                 if (ret)
536                         return ret;
537                 break;
538
539         default:
540                 return -EINVAL;
541         }
542
543         return 0;
544 }
545
546 static const struct snd_soc_dai_ops qmc_dai_ops = {
547         .startup        = qmc_dai_startup,
548         .trigger        = qmc_dai_trigger,
549         .hw_params      = qmc_dai_hw_params,
550 };
551
552 static u64 qmc_audio_formats(u8 nb_ts)
553 {
554         unsigned int format_width;
555         unsigned int chan_width;
556         snd_pcm_format_t format;
557         u64 formats_mask;
558
559         if (!nb_ts)
560                 return 0;
561
562         formats_mask = 0;
563         chan_width = nb_ts * 8;
564         pcm_for_each_format(format) {
565                 /*
566                  * Support format other than little-endian (ie big-endian or
567                  * without endianness such as 8bit formats)
568                  */
569                 if (snd_pcm_format_little_endian(format) == 1)
570                         continue;
571
572                 /* Support physical width multiple of 8bit */
573                 format_width = snd_pcm_format_physical_width(format);
574                 if (format_width == 0 || format_width % 8)
575                         continue;
576
577                 /*
578                  * And support physical width that can fit N times in the
579                  * channel
580                  */
581                 if (format_width > chan_width || chan_width % format_width)
582                         continue;
583
584                 formats_mask |= pcm_format_to_bits(format);
585         }
586         return formats_mask;
587 }
588
589 static int qmc_audio_dai_parse(struct qmc_audio *qmc_audio, struct device_node *np,
590         struct qmc_dai *qmc_dai, struct snd_soc_dai_driver *qmc_soc_dai_driver)
591 {
592         struct qmc_chan_info info;
593         u32 val;
594         int ret;
595
596         qmc_dai->dev = qmc_audio->dev;
597
598         ret = of_property_read_u32(np, "reg", &val);
599         if (ret) {
600                 dev_err(qmc_audio->dev, "%pOF: failed to read reg\n", np);
601                 return ret;
602         }
603         qmc_dai->id = val;
604
605         qmc_dai->name = devm_kasprintf(qmc_audio->dev, GFP_KERNEL, "%s.%d",
606                                        np->parent->name, qmc_dai->id);
607
608         qmc_dai->qmc_chan = devm_qmc_chan_get_byphandle(qmc_audio->dev, np,
609                                                         "fsl,qmc-chan");
610         if (IS_ERR(qmc_dai->qmc_chan)) {
611                 ret = PTR_ERR(qmc_dai->qmc_chan);
612                 return dev_err_probe(qmc_audio->dev, ret,
613                                      "dai %d get QMC channel failed\n", qmc_dai->id);
614         }
615
616         qmc_soc_dai_driver->id = qmc_dai->id;
617         qmc_soc_dai_driver->name = qmc_dai->name;
618
619         ret = qmc_chan_get_info(qmc_dai->qmc_chan, &info);
620         if (ret) {
621                 dev_err(qmc_audio->dev, "dai %d get QMC channel info failed %d\n",
622                         qmc_dai->id, ret);
623                 return ret;
624         }
625         dev_info(qmc_audio->dev, "dai %d QMC channel mode %d, nb_tx_ts %u, nb_rx_ts %u\n",
626                  qmc_dai->id, info.mode, info.nb_tx_ts, info.nb_rx_ts);
627
628         if (info.mode != QMC_TRANSPARENT) {
629                 dev_err(qmc_audio->dev, "dai %d QMC chan mode %d is not QMC_TRANSPARENT\n",
630                         qmc_dai->id, info.mode);
631                 return -EINVAL;
632         }
633         qmc_dai->nb_tx_ts = info.nb_tx_ts;
634         qmc_dai->nb_rx_ts = info.nb_rx_ts;
635
636         qmc_soc_dai_driver->playback.channels_min = 0;
637         qmc_soc_dai_driver->playback.channels_max = 0;
638         if (qmc_dai->nb_tx_ts) {
639                 qmc_soc_dai_driver->playback.channels_min = 1;
640                 qmc_soc_dai_driver->playback.channels_max = qmc_dai->nb_tx_ts;
641         }
642         qmc_soc_dai_driver->playback.formats = qmc_audio_formats(qmc_dai->nb_tx_ts);
643
644         qmc_soc_dai_driver->capture.channels_min = 0;
645         qmc_soc_dai_driver->capture.channels_max = 0;
646         if (qmc_dai->nb_rx_ts) {
647                 qmc_soc_dai_driver->capture.channels_min = 1;
648                 qmc_soc_dai_driver->capture.channels_max = qmc_dai->nb_rx_ts;
649         }
650         qmc_soc_dai_driver->capture.formats = qmc_audio_formats(qmc_dai->nb_rx_ts);
651
652         qmc_soc_dai_driver->playback.rates = snd_pcm_rate_to_rate_bit(info.tx_fs_rate);
653         qmc_soc_dai_driver->playback.rate_min = info.tx_fs_rate;
654         qmc_soc_dai_driver->playback.rate_max = info.tx_fs_rate;
655         qmc_soc_dai_driver->capture.rates = snd_pcm_rate_to_rate_bit(info.rx_fs_rate);
656         qmc_soc_dai_driver->capture.rate_min = info.rx_fs_rate;
657         qmc_soc_dai_driver->capture.rate_max = info.rx_fs_rate;
658
659         qmc_soc_dai_driver->ops = &qmc_dai_ops;
660
661         return 0;
662 }
663
664 static int qmc_audio_probe(struct platform_device *pdev)
665 {
666         struct device_node *np = pdev->dev.of_node;
667         struct qmc_audio *qmc_audio;
668         struct device_node *child;
669         unsigned int i;
670         int ret;
671
672         qmc_audio = devm_kzalloc(&pdev->dev, sizeof(*qmc_audio), GFP_KERNEL);
673         if (!qmc_audio)
674                 return -ENOMEM;
675
676         qmc_audio->dev = &pdev->dev;
677
678         qmc_audio->num_dais = of_get_available_child_count(np);
679         if (qmc_audio->num_dais) {
680                 qmc_audio->dais = devm_kcalloc(&pdev->dev, qmc_audio->num_dais,
681                                                sizeof(*qmc_audio->dais),
682                                                GFP_KERNEL);
683                 if (!qmc_audio->dais)
684                         return -ENOMEM;
685
686                 qmc_audio->dai_drivers = devm_kcalloc(&pdev->dev, qmc_audio->num_dais,
687                                                       sizeof(*qmc_audio->dai_drivers),
688                                                       GFP_KERNEL);
689                 if (!qmc_audio->dai_drivers)
690                         return -ENOMEM;
691         }
692
693         i = 0;
694         for_each_available_child_of_node(np, child) {
695                 ret = qmc_audio_dai_parse(qmc_audio, child,
696                                           qmc_audio->dais + i,
697                                           qmc_audio->dai_drivers + i);
698                 if (ret) {
699                         of_node_put(child);
700                         return ret;
701                 }
702                 i++;
703         }
704
705
706         platform_set_drvdata(pdev, qmc_audio);
707
708         ret = devm_snd_soc_register_component(qmc_audio->dev,
709                                               &qmc_audio_soc_platform,
710                                               qmc_audio->dai_drivers,
711                                               qmc_audio->num_dais);
712         if (ret)
713                 return ret;
714
715         return 0;
716 }
717
718 static const struct of_device_id qmc_audio_id_table[] = {
719         { .compatible = "fsl,qmc-audio" },
720         {} /* sentinel */
721 };
722 MODULE_DEVICE_TABLE(of, qmc_audio_id_table);
723
724 static struct platform_driver qmc_audio_driver = {
725         .driver = {
726                 .name = "fsl-qmc-audio",
727                 .of_match_table = of_match_ptr(qmc_audio_id_table),
728         },
729         .probe = qmc_audio_probe,
730 };
731 module_platform_driver(qmc_audio_driver);
732
733 MODULE_AUTHOR("Herve Codina <herve.codina@bootlin.com>");
734 MODULE_DESCRIPTION("CPM/QE QMC audio driver");
735 MODULE_LICENSE("GPL");