Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/sound/soc/fsl/fsl_qmc_audio.c
29267 views
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 <[email protected]>
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
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
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
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
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
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
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
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
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
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
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
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(sizeof(*prtd), GFP_KERNEL);
320
if (!prtd)
321
return -ENOMEM;
322
323
runtime->private_data = prtd;
324
325
return 0;
326
}
327
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
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
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
*/
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
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
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
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
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
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
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
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
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
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
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
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
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
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 <[email protected]>");
973
MODULE_DESCRIPTION("CPM/QE QMC audio driver");
974
MODULE_LICENSE("GPL");
975
976