Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/sound/soc/qcom/qdsp6/q6afe-dai.c
26444 views
1
// SPDX-License-Identifier: GPL-2.0
2
// Copyright (c) 2011-2017, The Linux Foundation. All rights reserved.
3
// Copyright (c) 2018, Linaro Limited
4
5
#include <dt-bindings/sound/qcom,q6afe.h>
6
#include <linux/err.h>
7
#include <linux/init.h>
8
#include <linux/module.h>
9
#include <linux/device.h>
10
#include <linux/platform_device.h>
11
#include <linux/slab.h>
12
#include <sound/pcm.h>
13
#include <sound/soc.h>
14
#include <sound/pcm_params.h>
15
#include "q6dsp-lpass-ports.h"
16
#include "q6dsp-common.h"
17
#include "q6afe.h"
18
19
20
struct q6afe_dai_priv_data {
21
uint32_t sd_line_mask;
22
uint32_t sync_mode;
23
uint32_t sync_src;
24
uint32_t data_out_enable;
25
uint32_t invert_sync;
26
uint32_t data_delay;
27
uint32_t data_align;
28
};
29
30
struct q6afe_dai_data {
31
struct q6afe_port *port[AFE_PORT_MAX];
32
struct q6afe_port_config port_config[AFE_PORT_MAX];
33
bool is_port_started[AFE_PORT_MAX];
34
struct q6afe_dai_priv_data priv[AFE_PORT_MAX];
35
};
36
37
static int q6slim_hw_params(struct snd_pcm_substream *substream,
38
struct snd_pcm_hw_params *params,
39
struct snd_soc_dai *dai)
40
{
41
42
struct q6afe_dai_data *dai_data = dev_get_drvdata(dai->dev);
43
struct q6afe_slim_cfg *slim = &dai_data->port_config[dai->id].slim;
44
45
slim->sample_rate = params_rate(params);
46
47
switch (params_format(params)) {
48
case SNDRV_PCM_FORMAT_S16_LE:
49
case SNDRV_PCM_FORMAT_SPECIAL:
50
slim->bit_width = 16;
51
break;
52
case SNDRV_PCM_FORMAT_S24_LE:
53
slim->bit_width = 24;
54
break;
55
case SNDRV_PCM_FORMAT_S32_LE:
56
slim->bit_width = 32;
57
break;
58
default:
59
pr_err("%s: format %d\n",
60
__func__, params_format(params));
61
return -EINVAL;
62
}
63
64
return 0;
65
}
66
67
static int q6hdmi_hw_params(struct snd_pcm_substream *substream,
68
struct snd_pcm_hw_params *params,
69
struct snd_soc_dai *dai)
70
{
71
struct q6afe_dai_data *dai_data = dev_get_drvdata(dai->dev);
72
int channels = params_channels(params);
73
struct q6afe_hdmi_cfg *hdmi = &dai_data->port_config[dai->id].hdmi;
74
int ret;
75
76
hdmi->sample_rate = params_rate(params);
77
switch (params_format(params)) {
78
case SNDRV_PCM_FORMAT_S16_LE:
79
hdmi->bit_width = 16;
80
break;
81
case SNDRV_PCM_FORMAT_S24_LE:
82
hdmi->bit_width = 24;
83
break;
84
}
85
86
ret = q6dsp_get_channel_allocation(channels);
87
if (ret < 0)
88
return ret;
89
90
hdmi->channel_allocation = (u16) ret;
91
92
return 0;
93
}
94
95
static int q6afe_usb_hw_params(struct snd_pcm_substream *substream,
96
struct snd_pcm_hw_params *params,
97
struct snd_soc_dai *dai)
98
{
99
struct q6afe_dai_data *dai_data = dev_get_drvdata(dai->dev);
100
int channels = params_channels(params);
101
int rate = params_rate(params);
102
struct q6afe_usb_cfg *usb = &dai_data->port_config[dai->id].usb_audio;
103
104
usb->sample_rate = rate;
105
usb->num_channels = channels;
106
107
switch (params_format(params)) {
108
case SNDRV_PCM_FORMAT_U16_LE:
109
case SNDRV_PCM_FORMAT_S16_LE:
110
usb->bit_width = 16;
111
break;
112
case SNDRV_PCM_FORMAT_S24_LE:
113
case SNDRV_PCM_FORMAT_S24_3LE:
114
usb->bit_width = 24;
115
break;
116
case SNDRV_PCM_FORMAT_S32_LE:
117
usb->bit_width = 32;
118
break;
119
default:
120
dev_err(dai->dev, "%s: invalid format %d\n",
121
__func__, params_format(params));
122
return -EINVAL;
123
}
124
125
return 0;
126
}
127
128
static int q6i2s_hw_params(struct snd_pcm_substream *substream,
129
struct snd_pcm_hw_params *params,
130
struct snd_soc_dai *dai)
131
{
132
struct q6afe_dai_data *dai_data = dev_get_drvdata(dai->dev);
133
struct q6afe_i2s_cfg *i2s = &dai_data->port_config[dai->id].i2s_cfg;
134
135
i2s->sample_rate = params_rate(params);
136
i2s->bit_width = params_width(params);
137
i2s->num_channels = params_channels(params);
138
i2s->sd_line_mask = dai_data->priv[dai->id].sd_line_mask;
139
140
return 0;
141
}
142
143
static int q6i2s_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
144
{
145
struct q6afe_dai_data *dai_data = dev_get_drvdata(dai->dev);
146
struct q6afe_i2s_cfg *i2s = &dai_data->port_config[dai->id].i2s_cfg;
147
148
i2s->fmt = fmt;
149
150
return 0;
151
}
152
153
static int q6tdm_set_tdm_slot(struct snd_soc_dai *dai,
154
unsigned int tx_mask,
155
unsigned int rx_mask,
156
int slots, int slot_width)
157
{
158
159
struct q6afe_dai_data *dai_data = dev_get_drvdata(dai->dev);
160
struct q6afe_tdm_cfg *tdm = &dai_data->port_config[dai->id].tdm;
161
unsigned int cap_mask;
162
int rc = 0;
163
164
/* HW only supports 16 and 32 bit slot width configuration */
165
if ((slot_width != 16) && (slot_width != 32)) {
166
dev_err(dai->dev, "%s: invalid slot_width %d\n",
167
__func__, slot_width);
168
return -EINVAL;
169
}
170
171
/* HW supports 1-32 slots configuration. Typical: 1, 2, 4, 8, 16, 32 */
172
switch (slots) {
173
case 2:
174
cap_mask = 0x03;
175
break;
176
case 4:
177
cap_mask = 0x0F;
178
break;
179
case 8:
180
cap_mask = 0xFF;
181
break;
182
case 16:
183
cap_mask = 0xFFFF;
184
break;
185
default:
186
dev_err(dai->dev, "%s: invalid slots %d\n",
187
__func__, slots);
188
return -EINVAL;
189
}
190
191
switch (dai->id) {
192
case PRIMARY_TDM_RX_0 ... QUINARY_TDM_TX_7:
193
tdm->nslots_per_frame = slots;
194
tdm->slot_width = slot_width;
195
/* TDM RX dais ids are even and tx are odd */
196
tdm->slot_mask = ((dai->id & 0x1) ? tx_mask : rx_mask) & cap_mask;
197
break;
198
default:
199
dev_err(dai->dev, "%s: invalid dai id 0x%x\n",
200
__func__, dai->id);
201
return -EINVAL;
202
}
203
204
return rc;
205
}
206
207
static int q6tdm_set_channel_map(struct snd_soc_dai *dai,
208
unsigned int tx_num, const unsigned int *tx_slot,
209
unsigned int rx_num, const unsigned int *rx_slot)
210
{
211
212
struct q6afe_dai_data *dai_data = dev_get_drvdata(dai->dev);
213
struct q6afe_tdm_cfg *tdm = &dai_data->port_config[dai->id].tdm;
214
int rc = 0;
215
int i = 0;
216
217
switch (dai->id) {
218
case PRIMARY_TDM_RX_0 ... QUINARY_TDM_TX_7:
219
if (dai->id & 0x1) {
220
if (!tx_slot) {
221
dev_err(dai->dev, "tx slot not found\n");
222
return -EINVAL;
223
}
224
if (tx_num > AFE_PORT_MAX_AUDIO_CHAN_CNT) {
225
dev_err(dai->dev, "invalid tx num %d\n",
226
tx_num);
227
return -EINVAL;
228
}
229
230
for (i = 0; i < tx_num; i++)
231
tdm->ch_mapping[i] = tx_slot[i];
232
233
for (i = tx_num; i < AFE_PORT_MAX_AUDIO_CHAN_CNT; i++)
234
tdm->ch_mapping[i] = Q6AFE_CMAP_INVALID;
235
236
tdm->num_channels = tx_num;
237
} else {
238
/* rx */
239
if (!rx_slot) {
240
dev_err(dai->dev, "rx slot not found\n");
241
return -EINVAL;
242
}
243
if (rx_num > AFE_PORT_MAX_AUDIO_CHAN_CNT) {
244
dev_err(dai->dev, "invalid rx num %d\n",
245
rx_num);
246
return -EINVAL;
247
}
248
249
for (i = 0; i < rx_num; i++)
250
tdm->ch_mapping[i] = rx_slot[i];
251
252
for (i = rx_num; i < AFE_PORT_MAX_AUDIO_CHAN_CNT; i++)
253
tdm->ch_mapping[i] = Q6AFE_CMAP_INVALID;
254
255
tdm->num_channels = rx_num;
256
}
257
258
break;
259
default:
260
dev_err(dai->dev, "%s: invalid dai id 0x%x\n",
261
__func__, dai->id);
262
return -EINVAL;
263
}
264
265
return rc;
266
}
267
268
static int q6tdm_hw_params(struct snd_pcm_substream *substream,
269
struct snd_pcm_hw_params *params,
270
struct snd_soc_dai *dai)
271
{
272
struct q6afe_dai_data *dai_data = dev_get_drvdata(dai->dev);
273
struct q6afe_tdm_cfg *tdm = &dai_data->port_config[dai->id].tdm;
274
275
tdm->bit_width = params_width(params);
276
tdm->sample_rate = params_rate(params);
277
tdm->num_channels = params_channels(params);
278
tdm->data_align_type = dai_data->priv[dai->id].data_align;
279
tdm->sync_src = dai_data->priv[dai->id].sync_src;
280
tdm->sync_mode = dai_data->priv[dai->id].sync_mode;
281
282
return 0;
283
}
284
285
static int q6dma_set_channel_map(struct snd_soc_dai *dai,
286
unsigned int tx_num,
287
const unsigned int *tx_ch_mask,
288
unsigned int rx_num,
289
const unsigned int *rx_ch_mask)
290
{
291
292
struct q6afe_dai_data *dai_data = dev_get_drvdata(dai->dev);
293
struct q6afe_cdc_dma_cfg *cfg = &dai_data->port_config[dai->id].dma_cfg;
294
int ch_mask;
295
int rc = 0;
296
297
switch (dai->id) {
298
case WSA_CODEC_DMA_TX_0:
299
case WSA_CODEC_DMA_TX_1:
300
case WSA_CODEC_DMA_TX_2:
301
case VA_CODEC_DMA_TX_0:
302
case VA_CODEC_DMA_TX_1:
303
case VA_CODEC_DMA_TX_2:
304
case TX_CODEC_DMA_TX_0:
305
case TX_CODEC_DMA_TX_1:
306
case TX_CODEC_DMA_TX_2:
307
case TX_CODEC_DMA_TX_3:
308
case TX_CODEC_DMA_TX_4:
309
case TX_CODEC_DMA_TX_5:
310
if (!tx_ch_mask) {
311
dev_err(dai->dev, "tx slot not found\n");
312
return -EINVAL;
313
}
314
315
if (tx_num > AFE_PORT_MAX_AUDIO_CHAN_CNT) {
316
dev_err(dai->dev, "invalid tx num %d\n",
317
tx_num);
318
return -EINVAL;
319
}
320
ch_mask = *tx_ch_mask;
321
322
break;
323
case WSA_CODEC_DMA_RX_0:
324
case WSA_CODEC_DMA_RX_1:
325
case RX_CODEC_DMA_RX_0:
326
case RX_CODEC_DMA_RX_1:
327
case RX_CODEC_DMA_RX_2:
328
case RX_CODEC_DMA_RX_3:
329
case RX_CODEC_DMA_RX_4:
330
case RX_CODEC_DMA_RX_5:
331
case RX_CODEC_DMA_RX_6:
332
case RX_CODEC_DMA_RX_7:
333
/* rx */
334
if (!rx_ch_mask) {
335
dev_err(dai->dev, "rx slot not found\n");
336
return -EINVAL;
337
}
338
if (rx_num > AFE_PORT_MAX_AUDIO_CHAN_CNT) {
339
dev_err(dai->dev, "invalid rx num %d\n",
340
rx_num);
341
return -EINVAL;
342
}
343
ch_mask = *rx_ch_mask;
344
345
break;
346
default:
347
dev_err(dai->dev, "%s: invalid dai id 0x%x\n",
348
__func__, dai->id);
349
return -EINVAL;
350
}
351
352
cfg->active_channels_mask = ch_mask;
353
354
return rc;
355
}
356
357
static int q6dma_hw_params(struct snd_pcm_substream *substream,
358
struct snd_pcm_hw_params *params,
359
struct snd_soc_dai *dai)
360
{
361
struct q6afe_dai_data *dai_data = dev_get_drvdata(dai->dev);
362
struct q6afe_cdc_dma_cfg *cfg = &dai_data->port_config[dai->id].dma_cfg;
363
364
cfg->bit_width = params_width(params);
365
cfg->sample_rate = params_rate(params);
366
cfg->num_channels = params_channels(params);
367
368
return 0;
369
}
370
static void q6afe_dai_shutdown(struct snd_pcm_substream *substream,
371
struct snd_soc_dai *dai)
372
{
373
struct q6afe_dai_data *dai_data = dev_get_drvdata(dai->dev);
374
int rc;
375
376
if (!dai_data->is_port_started[dai->id])
377
return;
378
379
rc = q6afe_port_stop(dai_data->port[dai->id]);
380
if (rc < 0)
381
dev_err(dai->dev, "fail to close AFE port (%d)\n", rc);
382
383
dai_data->is_port_started[dai->id] = false;
384
385
}
386
387
static int q6afe_dai_prepare(struct snd_pcm_substream *substream,
388
struct snd_soc_dai *dai)
389
{
390
struct q6afe_dai_data *dai_data = dev_get_drvdata(dai->dev);
391
int rc;
392
393
if (dai_data->is_port_started[dai->id]) {
394
/* stop the port and restart with new port config */
395
rc = q6afe_port_stop(dai_data->port[dai->id]);
396
if (rc < 0) {
397
dev_err(dai->dev, "fail to close AFE port (%d)\n", rc);
398
return rc;
399
}
400
}
401
402
switch (dai->id) {
403
case HDMI_RX:
404
case DISPLAY_PORT_RX:
405
q6afe_hdmi_port_prepare(dai_data->port[dai->id],
406
&dai_data->port_config[dai->id].hdmi);
407
break;
408
case SLIMBUS_0_RX ... SLIMBUS_6_TX:
409
q6afe_slim_port_prepare(dai_data->port[dai->id],
410
&dai_data->port_config[dai->id].slim);
411
break;
412
case QUINARY_MI2S_RX ... QUINARY_MI2S_TX:
413
case PRIMARY_MI2S_RX ... QUATERNARY_MI2S_TX:
414
rc = q6afe_i2s_port_prepare(dai_data->port[dai->id],
415
&dai_data->port_config[dai->id].i2s_cfg);
416
if (rc < 0) {
417
dev_err(dai->dev, "fail to prepare AFE port %x\n",
418
dai->id);
419
return rc;
420
}
421
break;
422
case PRIMARY_TDM_RX_0 ... QUINARY_TDM_TX_7:
423
q6afe_tdm_port_prepare(dai_data->port[dai->id],
424
&dai_data->port_config[dai->id].tdm);
425
break;
426
case WSA_CODEC_DMA_RX_0 ... RX_CODEC_DMA_RX_7:
427
q6afe_cdc_dma_port_prepare(dai_data->port[dai->id],
428
&dai_data->port_config[dai->id].dma_cfg);
429
break;
430
case USB_RX:
431
q6afe_usb_port_prepare(dai_data->port[dai->id],
432
&dai_data->port_config[dai->id].usb_audio);
433
break;
434
default:
435
return -EINVAL;
436
}
437
438
rc = q6afe_port_start(dai_data->port[dai->id]);
439
if (rc < 0) {
440
dev_err(dai->dev, "fail to start AFE port %x\n", dai->id);
441
return rc;
442
}
443
dai_data->is_port_started[dai->id] = true;
444
445
return 0;
446
}
447
448
static int q6slim_set_channel_map(struct snd_soc_dai *dai,
449
unsigned int tx_num,
450
const unsigned int *tx_slot,
451
unsigned int rx_num,
452
const unsigned int *rx_slot)
453
{
454
struct q6afe_dai_data *dai_data = dev_get_drvdata(dai->dev);
455
struct q6afe_port_config *pcfg = &dai_data->port_config[dai->id];
456
int i;
457
458
if (dai->id & 0x1) {
459
/* TX */
460
if (!tx_slot) {
461
pr_err("%s: tx slot not found\n", __func__);
462
return -EINVAL;
463
}
464
465
for (i = 0; i < tx_num; i++)
466
pcfg->slim.ch_mapping[i] = tx_slot[i];
467
468
pcfg->slim.num_channels = tx_num;
469
470
471
} else {
472
if (!rx_slot) {
473
pr_err("%s: rx slot not found\n", __func__);
474
return -EINVAL;
475
}
476
477
for (i = 0; i < rx_num; i++)
478
pcfg->slim.ch_mapping[i] = rx_slot[i];
479
480
pcfg->slim.num_channels = rx_num;
481
482
}
483
484
return 0;
485
}
486
487
static int q6afe_mi2s_set_sysclk(struct snd_soc_dai *dai,
488
int clk_id, unsigned int freq, int dir)
489
{
490
struct q6afe_dai_data *dai_data = dev_get_drvdata(dai->dev);
491
struct q6afe_port *port = dai_data->port[dai->id];
492
493
switch (clk_id) {
494
case LPAIF_DIG_CLK:
495
return q6afe_port_set_sysclk(port, clk_id, 0, 5, freq, dir);
496
case LPAIF_BIT_CLK:
497
case LPAIF_OSR_CLK:
498
return q6afe_port_set_sysclk(port, clk_id,
499
Q6AFE_LPASS_CLK_SRC_INTERNAL,
500
Q6AFE_LPASS_CLK_ROOT_DEFAULT,
501
freq, dir);
502
case Q6AFE_LPASS_CLK_ID_PRI_MI2S_IBIT ... Q6AFE_LPASS_CLK_ID_QUI_MI2S_OSR:
503
case Q6AFE_LPASS_CLK_ID_MCLK_1 ... Q6AFE_LPASS_CLK_ID_INT_MCLK_1:
504
case Q6AFE_LPASS_CLK_ID_WSA_CORE_MCLK ... Q6AFE_LPASS_CLK_ID_VA_CORE_2X_MCLK:
505
return q6afe_port_set_sysclk(port, clk_id,
506
Q6AFE_LPASS_CLK_ATTRIBUTE_COUPLE_NO,
507
Q6AFE_LPASS_CLK_ROOT_DEFAULT,
508
freq, dir);
509
case Q6AFE_LPASS_CLK_ID_PRI_TDM_IBIT ... Q6AFE_LPASS_CLK_ID_QUIN_TDM_EBIT:
510
return q6afe_port_set_sysclk(port, clk_id,
511
Q6AFE_LPASS_CLK_ATTRIBUTE_INVERT_COUPLE_NO,
512
Q6AFE_LPASS_CLK_ROOT_DEFAULT,
513
freq, dir);
514
}
515
516
return 0;
517
}
518
519
static const struct snd_soc_dapm_route q6afe_dapm_routes[] = {
520
{"HDMI Playback", NULL, "HDMI_RX"},
521
{"DISPLAY_PORT_RX_0 Playback", NULL, "DISPLAY_PORT_RX"},
522
{"Slimbus Playback", NULL, "SLIMBUS_0_RX"},
523
{"Slimbus1 Playback", NULL, "SLIMBUS_1_RX"},
524
{"Slimbus2 Playback", NULL, "SLIMBUS_2_RX"},
525
{"Slimbus3 Playback", NULL, "SLIMBUS_3_RX"},
526
{"Slimbus4 Playback", NULL, "SLIMBUS_4_RX"},
527
{"Slimbus5 Playback", NULL, "SLIMBUS_5_RX"},
528
{"Slimbus6 Playback", NULL, "SLIMBUS_6_RX"},
529
530
{"SLIMBUS_0_TX", NULL, "Slimbus Capture"},
531
{"SLIMBUS_1_TX", NULL, "Slimbus1 Capture"},
532
{"SLIMBUS_2_TX", NULL, "Slimbus2 Capture"},
533
{"SLIMBUS_3_TX", NULL, "Slimbus3 Capture"},
534
{"SLIMBUS_4_TX", NULL, "Slimbus4 Capture"},
535
{"SLIMBUS_5_TX", NULL, "Slimbus5 Capture"},
536
{"SLIMBUS_6_TX", NULL, "Slimbus6 Capture"},
537
538
{"Primary MI2S Playback", NULL, "PRI_MI2S_RX"},
539
{"Secondary MI2S Playback", NULL, "SEC_MI2S_RX"},
540
{"Tertiary MI2S Playback", NULL, "TERT_MI2S_RX"},
541
{"Quaternary MI2S Playback", NULL, "QUAT_MI2S_RX"},
542
{"Quinary MI2S Playback", NULL, "QUIN_MI2S_RX"},
543
544
{"Primary TDM0 Playback", NULL, "PRIMARY_TDM_RX_0"},
545
{"Primary TDM1 Playback", NULL, "PRIMARY_TDM_RX_1"},
546
{"Primary TDM2 Playback", NULL, "PRIMARY_TDM_RX_2"},
547
{"Primary TDM3 Playback", NULL, "PRIMARY_TDM_RX_3"},
548
{"Primary TDM4 Playback", NULL, "PRIMARY_TDM_RX_4"},
549
{"Primary TDM5 Playback", NULL, "PRIMARY_TDM_RX_5"},
550
{"Primary TDM6 Playback", NULL, "PRIMARY_TDM_RX_6"},
551
{"Primary TDM7 Playback", NULL, "PRIMARY_TDM_RX_7"},
552
553
{"Secondary TDM0 Playback", NULL, "SEC_TDM_RX_0"},
554
{"Secondary TDM1 Playback", NULL, "SEC_TDM_RX_1"},
555
{"Secondary TDM2 Playback", NULL, "SEC_TDM_RX_2"},
556
{"Secondary TDM3 Playback", NULL, "SEC_TDM_RX_3"},
557
{"Secondary TDM4 Playback", NULL, "SEC_TDM_RX_4"},
558
{"Secondary TDM5 Playback", NULL, "SEC_TDM_RX_5"},
559
{"Secondary TDM6 Playback", NULL, "SEC_TDM_RX_6"},
560
{"Secondary TDM7 Playback", NULL, "SEC_TDM_RX_7"},
561
562
{"Tertiary TDM0 Playback", NULL, "TERT_TDM_RX_0"},
563
{"Tertiary TDM1 Playback", NULL, "TERT_TDM_RX_1"},
564
{"Tertiary TDM2 Playback", NULL, "TERT_TDM_RX_2"},
565
{"Tertiary TDM3 Playback", NULL, "TERT_TDM_RX_3"},
566
{"Tertiary TDM4 Playback", NULL, "TERT_TDM_RX_4"},
567
{"Tertiary TDM5 Playback", NULL, "TERT_TDM_RX_5"},
568
{"Tertiary TDM6 Playback", NULL, "TERT_TDM_RX_6"},
569
{"Tertiary TDM7 Playback", NULL, "TERT_TDM_RX_7"},
570
571
{"Quaternary TDM0 Playback", NULL, "QUAT_TDM_RX_0"},
572
{"Quaternary TDM1 Playback", NULL, "QUAT_TDM_RX_1"},
573
{"Quaternary TDM2 Playback", NULL, "QUAT_TDM_RX_2"},
574
{"Quaternary TDM3 Playback", NULL, "QUAT_TDM_RX_3"},
575
{"Quaternary TDM4 Playback", NULL, "QUAT_TDM_RX_4"},
576
{"Quaternary TDM5 Playback", NULL, "QUAT_TDM_RX_5"},
577
{"Quaternary TDM6 Playback", NULL, "QUAT_TDM_RX_6"},
578
{"Quaternary TDM7 Playback", NULL, "QUAT_TDM_RX_7"},
579
580
{"Quinary TDM0 Playback", NULL, "QUIN_TDM_RX_0"},
581
{"Quinary TDM1 Playback", NULL, "QUIN_TDM_RX_1"},
582
{"Quinary TDM2 Playback", NULL, "QUIN_TDM_RX_2"},
583
{"Quinary TDM3 Playback", NULL, "QUIN_TDM_RX_3"},
584
{"Quinary TDM4 Playback", NULL, "QUIN_TDM_RX_4"},
585
{"Quinary TDM5 Playback", NULL, "QUIN_TDM_RX_5"},
586
{"Quinary TDM6 Playback", NULL, "QUIN_TDM_RX_6"},
587
{"Quinary TDM7 Playback", NULL, "QUIN_TDM_RX_7"},
588
589
{"PRIMARY_TDM_TX_0", NULL, "Primary TDM0 Capture"},
590
{"PRIMARY_TDM_TX_1", NULL, "Primary TDM1 Capture"},
591
{"PRIMARY_TDM_TX_2", NULL, "Primary TDM2 Capture"},
592
{"PRIMARY_TDM_TX_3", NULL, "Primary TDM3 Capture"},
593
{"PRIMARY_TDM_TX_4", NULL, "Primary TDM4 Capture"},
594
{"PRIMARY_TDM_TX_5", NULL, "Primary TDM5 Capture"},
595
{"PRIMARY_TDM_TX_6", NULL, "Primary TDM6 Capture"},
596
{"PRIMARY_TDM_TX_7", NULL, "Primary TDM7 Capture"},
597
598
{"SEC_TDM_TX_0", NULL, "Secondary TDM0 Capture"},
599
{"SEC_TDM_TX_1", NULL, "Secondary TDM1 Capture"},
600
{"SEC_TDM_TX_2", NULL, "Secondary TDM2 Capture"},
601
{"SEC_TDM_TX_3", NULL, "Secondary TDM3 Capture"},
602
{"SEC_TDM_TX_4", NULL, "Secondary TDM4 Capture"},
603
{"SEC_TDM_TX_5", NULL, "Secondary TDM5 Capture"},
604
{"SEC_TDM_TX_6", NULL, "Secondary TDM6 Capture"},
605
{"SEC_TDM_TX_7", NULL, "Secondary TDM7 Capture"},
606
607
{"TERT_TDM_TX_0", NULL, "Tertiary TDM0 Capture"},
608
{"TERT_TDM_TX_1", NULL, "Tertiary TDM1 Capture"},
609
{"TERT_TDM_TX_2", NULL, "Tertiary TDM2 Capture"},
610
{"TERT_TDM_TX_3", NULL, "Tertiary TDM3 Capture"},
611
{"TERT_TDM_TX_4", NULL, "Tertiary TDM4 Capture"},
612
{"TERT_TDM_TX_5", NULL, "Tertiary TDM5 Capture"},
613
{"TERT_TDM_TX_6", NULL, "Tertiary TDM6 Capture"},
614
{"TERT_TDM_TX_7", NULL, "Tertiary TDM7 Capture"},
615
616
{"QUAT_TDM_TX_0", NULL, "Quaternary TDM0 Capture"},
617
{"QUAT_TDM_TX_1", NULL, "Quaternary TDM1 Capture"},
618
{"QUAT_TDM_TX_2", NULL, "Quaternary TDM2 Capture"},
619
{"QUAT_TDM_TX_3", NULL, "Quaternary TDM3 Capture"},
620
{"QUAT_TDM_TX_4", NULL, "Quaternary TDM4 Capture"},
621
{"QUAT_TDM_TX_5", NULL, "Quaternary TDM5 Capture"},
622
{"QUAT_TDM_TX_6", NULL, "Quaternary TDM6 Capture"},
623
{"QUAT_TDM_TX_7", NULL, "Quaternary TDM7 Capture"},
624
625
{"QUIN_TDM_TX_0", NULL, "Quinary TDM0 Capture"},
626
{"QUIN_TDM_TX_1", NULL, "Quinary TDM1 Capture"},
627
{"QUIN_TDM_TX_2", NULL, "Quinary TDM2 Capture"},
628
{"QUIN_TDM_TX_3", NULL, "Quinary TDM3 Capture"},
629
{"QUIN_TDM_TX_4", NULL, "Quinary TDM4 Capture"},
630
{"QUIN_TDM_TX_5", NULL, "Quinary TDM5 Capture"},
631
{"QUIN_TDM_TX_6", NULL, "Quinary TDM6 Capture"},
632
{"QUIN_TDM_TX_7", NULL, "Quinary TDM7 Capture"},
633
634
{"TERT_MI2S_TX", NULL, "Tertiary MI2S Capture"},
635
{"PRI_MI2S_TX", NULL, "Primary MI2S Capture"},
636
{"SEC_MI2S_TX", NULL, "Secondary MI2S Capture"},
637
{"QUAT_MI2S_TX", NULL, "Quaternary MI2S Capture"},
638
{"QUIN_MI2S_TX", NULL, "Quinary MI2S Capture"},
639
640
{"WSA_CODEC_DMA_RX_0 Playback", NULL, "WSA_CODEC_DMA_RX_0"},
641
{"WSA_CODEC_DMA_TX_0", NULL, "WSA_CODEC_DMA_TX_0 Capture"},
642
{"WSA_CODEC_DMA_RX_1 Playback", NULL, "WSA_CODEC_DMA_RX_1"},
643
{"WSA_CODEC_DMA_TX_1", NULL, "WSA_CODEC_DMA_TX_1 Capture"},
644
{"WSA_CODEC_DMA_TX_2", NULL, "WSA_CODEC_DMA_TX_2 Capture"},
645
{"VA_CODEC_DMA_TX_0", NULL, "VA_CODEC_DMA_TX_0 Capture"},
646
{"VA_CODEC_DMA_TX_1", NULL, "VA_CODEC_DMA_TX_1 Capture"},
647
{"VA_CODEC_DMA_TX_2", NULL, "VA_CODEC_DMA_TX_2 Capture"},
648
{"RX_CODEC_DMA_RX_0 Playback", NULL, "RX_CODEC_DMA_RX_0"},
649
{"TX_CODEC_DMA_TX_0", NULL, "TX_CODEC_DMA_TX_0 Capture"},
650
{"RX_CODEC_DMA_RX_1 Playback", NULL, "RX_CODEC_DMA_RX_1"},
651
{"TX_CODEC_DMA_TX_1", NULL, "TX_CODEC_DMA_TX_1 Capture"},
652
{"RX_CODEC_DMA_RX_2 Playback", NULL, "RX_CODEC_DMA_RX_2"},
653
{"TX_CODEC_DMA_TX_2", NULL, "TX_CODEC_DMA_TX_2 Capture"},
654
{"RX_CODEC_DMA_RX_3 Playback", NULL, "RX_CODEC_DMA_RX_3"},
655
{"TX_CODEC_DMA_TX_3", NULL, "TX_CODEC_DMA_TX_3 Capture"},
656
{"RX_CODEC_DMA_RX_4 Playback", NULL, "RX_CODEC_DMA_RX_4"},
657
{"TX_CODEC_DMA_TX_4", NULL, "TX_CODEC_DMA_TX_4 Capture"},
658
{"RX_CODEC_DMA_RX_5 Playback", NULL, "RX_CODEC_DMA_RX_5"},
659
{"TX_CODEC_DMA_TX_5", NULL, "TX_CODEC_DMA_TX_5 Capture"},
660
{"RX_CODEC_DMA_RX_6 Playback", NULL, "RX_CODEC_DMA_RX_6"},
661
{"RX_CODEC_DMA_RX_7 Playback", NULL, "RX_CODEC_DMA_RX_7"},
662
663
/* USB playback AFE port receives data for playback, hence use the RX port */
664
{"USB Playback", NULL, "USB_RX"},
665
};
666
667
static int msm_dai_q6_dai_probe(struct snd_soc_dai *dai)
668
{
669
struct q6afe_dai_data *dai_data = dev_get_drvdata(dai->dev);
670
struct q6afe_port *port;
671
672
port = q6afe_port_get_from_id(dai->dev, dai->id);
673
if (IS_ERR(port)) {
674
dev_err(dai->dev, "Unable to get afe port\n");
675
return -EINVAL;
676
}
677
dai_data->port[dai->id] = port;
678
679
return 0;
680
}
681
682
static int msm_dai_q6_dai_remove(struct snd_soc_dai *dai)
683
{
684
struct q6afe_dai_data *dai_data = dev_get_drvdata(dai->dev);
685
686
q6afe_port_put(dai_data->port[dai->id]);
687
dai_data->port[dai->id] = NULL;
688
689
return 0;
690
}
691
692
static const struct snd_soc_dai_ops q6afe_usb_ops = {
693
.probe = msm_dai_q6_dai_probe,
694
.prepare = q6afe_dai_prepare,
695
.hw_params = q6afe_usb_hw_params,
696
/*
697
* Shutdown callback required to stop the USB AFE port, which is enabled
698
* by the prepare() stage. This stops the audio traffic on the USB AFE
699
* port on the Q6DSP.
700
*/
701
.shutdown = q6afe_dai_shutdown,
702
/*
703
* Startup callback not needed, as AFE port start command passes the PCM
704
* parameters within the AFE command, which is provided by the PCM core
705
* during the prepare() stage.
706
*/
707
};
708
709
static const struct snd_soc_dai_ops q6hdmi_ops = {
710
.probe = msm_dai_q6_dai_probe,
711
.remove = msm_dai_q6_dai_remove,
712
.prepare = q6afe_dai_prepare,
713
.hw_params = q6hdmi_hw_params,
714
.shutdown = q6afe_dai_shutdown,
715
};
716
717
static const struct snd_soc_dai_ops q6i2s_ops = {
718
.probe = msm_dai_q6_dai_probe,
719
.remove = msm_dai_q6_dai_remove,
720
.prepare = q6afe_dai_prepare,
721
.hw_params = q6i2s_hw_params,
722
.set_fmt = q6i2s_set_fmt,
723
.shutdown = q6afe_dai_shutdown,
724
.set_sysclk = q6afe_mi2s_set_sysclk,
725
};
726
727
static const struct snd_soc_dai_ops q6slim_ops = {
728
.probe = msm_dai_q6_dai_probe,
729
.remove = msm_dai_q6_dai_remove,
730
.prepare = q6afe_dai_prepare,
731
.hw_params = q6slim_hw_params,
732
.shutdown = q6afe_dai_shutdown,
733
.set_channel_map = q6slim_set_channel_map,
734
};
735
736
static const struct snd_soc_dai_ops q6tdm_ops = {
737
.probe = msm_dai_q6_dai_probe,
738
.remove = msm_dai_q6_dai_remove,
739
.prepare = q6afe_dai_prepare,
740
.shutdown = q6afe_dai_shutdown,
741
.set_sysclk = q6afe_mi2s_set_sysclk,
742
.set_tdm_slot = q6tdm_set_tdm_slot,
743
.set_channel_map = q6tdm_set_channel_map,
744
.hw_params = q6tdm_hw_params,
745
};
746
747
static const struct snd_soc_dai_ops q6dma_ops = {
748
.probe = msm_dai_q6_dai_probe,
749
.remove = msm_dai_q6_dai_remove,
750
.prepare = q6afe_dai_prepare,
751
.shutdown = q6afe_dai_shutdown,
752
.set_sysclk = q6afe_mi2s_set_sysclk,
753
.set_channel_map = q6dma_set_channel_map,
754
.hw_params = q6dma_hw_params,
755
};
756
757
static const struct snd_soc_dapm_widget q6afe_dai_widgets[] = {
758
SND_SOC_DAPM_AIF_IN("HDMI_RX", NULL, 0, SND_SOC_NOPM, 0, 0),
759
SND_SOC_DAPM_AIF_IN("SLIMBUS_0_RX", NULL, 0, SND_SOC_NOPM, 0, 0),
760
SND_SOC_DAPM_AIF_IN("SLIMBUS_1_RX", NULL, 0, SND_SOC_NOPM, 0, 0),
761
SND_SOC_DAPM_AIF_IN("SLIMBUS_2_RX", NULL, 0, SND_SOC_NOPM, 0, 0),
762
SND_SOC_DAPM_AIF_IN("SLIMBUS_3_RX", NULL, 0, SND_SOC_NOPM, 0, 0),
763
SND_SOC_DAPM_AIF_IN("SLIMBUS_4_RX", NULL, 0, SND_SOC_NOPM, 0, 0),
764
SND_SOC_DAPM_AIF_IN("SLIMBUS_5_RX", NULL, 0, SND_SOC_NOPM, 0, 0),
765
SND_SOC_DAPM_AIF_IN("SLIMBUS_6_RX", NULL, 0, SND_SOC_NOPM, 0, 0),
766
SND_SOC_DAPM_AIF_OUT("SLIMBUS_0_TX", NULL, 0, SND_SOC_NOPM, 0, 0),
767
SND_SOC_DAPM_AIF_OUT("SLIMBUS_1_TX", NULL, 0, SND_SOC_NOPM, 0, 0),
768
SND_SOC_DAPM_AIF_OUT("SLIMBUS_2_TX", NULL, 0, SND_SOC_NOPM, 0, 0),
769
SND_SOC_DAPM_AIF_OUT("SLIMBUS_3_TX", NULL, 0, SND_SOC_NOPM, 0, 0),
770
SND_SOC_DAPM_AIF_OUT("SLIMBUS_4_TX", NULL, 0, SND_SOC_NOPM, 0, 0),
771
SND_SOC_DAPM_AIF_OUT("SLIMBUS_5_TX", NULL, 0, SND_SOC_NOPM, 0, 0),
772
SND_SOC_DAPM_AIF_OUT("SLIMBUS_6_TX", NULL, 0, SND_SOC_NOPM, 0, 0),
773
SND_SOC_DAPM_AIF_IN("QUIN_MI2S_RX", NULL,
774
0, SND_SOC_NOPM, 0, 0),
775
SND_SOC_DAPM_AIF_OUT("QUIN_MI2S_TX", NULL,
776
0, SND_SOC_NOPM, 0, 0),
777
SND_SOC_DAPM_AIF_IN("QUAT_MI2S_RX", NULL,
778
0, SND_SOC_NOPM, 0, 0),
779
SND_SOC_DAPM_AIF_OUT("QUAT_MI2S_TX", NULL,
780
0, SND_SOC_NOPM, 0, 0),
781
SND_SOC_DAPM_AIF_IN("TERT_MI2S_RX", NULL,
782
0, SND_SOC_NOPM, 0, 0),
783
SND_SOC_DAPM_AIF_OUT("TERT_MI2S_TX", NULL,
784
0, SND_SOC_NOPM, 0, 0),
785
SND_SOC_DAPM_AIF_IN("SEC_MI2S_RX", NULL,
786
0, SND_SOC_NOPM, 0, 0),
787
SND_SOC_DAPM_AIF_OUT("SEC_MI2S_TX", NULL,
788
0, SND_SOC_NOPM, 0, 0),
789
SND_SOC_DAPM_AIF_IN("SEC_MI2S_RX_SD1",
790
"Secondary MI2S Playback SD1",
791
0, SND_SOC_NOPM, 0, 0),
792
SND_SOC_DAPM_AIF_IN("PRI_MI2S_RX", NULL,
793
0, SND_SOC_NOPM, 0, 0),
794
SND_SOC_DAPM_AIF_OUT("PRI_MI2S_TX", NULL,
795
0, SND_SOC_NOPM, 0, 0),
796
797
SND_SOC_DAPM_AIF_IN("PRIMARY_TDM_RX_0", NULL,
798
0, SND_SOC_NOPM, 0, 0),
799
SND_SOC_DAPM_AIF_IN("PRIMARY_TDM_RX_1", NULL,
800
0, SND_SOC_NOPM, 0, 0),
801
SND_SOC_DAPM_AIF_IN("PRIMARY_TDM_RX_2", NULL,
802
0, SND_SOC_NOPM, 0, 0),
803
SND_SOC_DAPM_AIF_IN("PRIMARY_TDM_RX_3", NULL,
804
0, SND_SOC_NOPM, 0, 0),
805
SND_SOC_DAPM_AIF_IN("PRIMARY_TDM_RX_4", NULL,
806
0, SND_SOC_NOPM, 0, 0),
807
SND_SOC_DAPM_AIF_IN("PRIMARY_TDM_RX_5", NULL,
808
0, SND_SOC_NOPM, 0, 0),
809
SND_SOC_DAPM_AIF_IN("PRIMARY_TDM_RX_6", NULL,
810
0, SND_SOC_NOPM, 0, 0),
811
SND_SOC_DAPM_AIF_IN("PRIMARY_TDM_RX_7", NULL,
812
0, SND_SOC_NOPM, 0, 0),
813
SND_SOC_DAPM_AIF_OUT("PRIMARY_TDM_TX_0", NULL,
814
0, SND_SOC_NOPM, 0, 0),
815
SND_SOC_DAPM_AIF_OUT("PRIMARY_TDM_TX_1", NULL,
816
0, SND_SOC_NOPM, 0, 0),
817
SND_SOC_DAPM_AIF_OUT("PRIMARY_TDM_TX_2", NULL,
818
0, SND_SOC_NOPM, 0, 0),
819
SND_SOC_DAPM_AIF_OUT("PRIMARY_TDM_TX_3", NULL,
820
0, SND_SOC_NOPM, 0, 0),
821
SND_SOC_DAPM_AIF_OUT("PRIMARY_TDM_TX_4", NULL,
822
0, SND_SOC_NOPM, 0, 0),
823
SND_SOC_DAPM_AIF_OUT("PRIMARY_TDM_TX_5", NULL,
824
0, SND_SOC_NOPM, 0, 0),
825
SND_SOC_DAPM_AIF_OUT("PRIMARY_TDM_TX_6", NULL,
826
0, SND_SOC_NOPM, 0, 0),
827
SND_SOC_DAPM_AIF_OUT("PRIMARY_TDM_TX_7", NULL,
828
0, SND_SOC_NOPM, 0, 0),
829
830
SND_SOC_DAPM_AIF_IN("SEC_TDM_RX_0", NULL,
831
0, SND_SOC_NOPM, 0, 0),
832
SND_SOC_DAPM_AIF_IN("SEC_TDM_RX_1", NULL,
833
0, SND_SOC_NOPM, 0, 0),
834
SND_SOC_DAPM_AIF_IN("SEC_TDM_RX_2", NULL,
835
0, SND_SOC_NOPM, 0, 0),
836
SND_SOC_DAPM_AIF_IN("SEC_TDM_RX_3", NULL,
837
0, SND_SOC_NOPM, 0, 0),
838
SND_SOC_DAPM_AIF_IN("SEC_TDM_RX_4", NULL,
839
0, SND_SOC_NOPM, 0, 0),
840
SND_SOC_DAPM_AIF_IN("SEC_TDM_RX_5", NULL,
841
0, SND_SOC_NOPM, 0, 0),
842
SND_SOC_DAPM_AIF_IN("SEC_TDM_RX_6", NULL,
843
0, SND_SOC_NOPM, 0, 0),
844
SND_SOC_DAPM_AIF_IN("SEC_TDM_RX_7", NULL,
845
0, SND_SOC_NOPM, 0, 0),
846
SND_SOC_DAPM_AIF_OUT("SEC_TDM_TX_0", NULL,
847
0, SND_SOC_NOPM, 0, 0),
848
SND_SOC_DAPM_AIF_OUT("SEC_TDM_TX_1", NULL,
849
0, SND_SOC_NOPM, 0, 0),
850
SND_SOC_DAPM_AIF_OUT("SEC_TDM_TX_2", NULL,
851
0, SND_SOC_NOPM, 0, 0),
852
SND_SOC_DAPM_AIF_OUT("SEC_TDM_TX_3", NULL,
853
0, SND_SOC_NOPM, 0, 0),
854
SND_SOC_DAPM_AIF_OUT("SEC_TDM_TX_4", NULL,
855
0, SND_SOC_NOPM, 0, 0),
856
SND_SOC_DAPM_AIF_OUT("SEC_TDM_TX_5", NULL,
857
0, SND_SOC_NOPM, 0, 0),
858
SND_SOC_DAPM_AIF_OUT("SEC_TDM_TX_6", NULL,
859
0, SND_SOC_NOPM, 0, 0),
860
SND_SOC_DAPM_AIF_OUT("SEC_TDM_TX_7", NULL,
861
0, SND_SOC_NOPM, 0, 0),
862
863
SND_SOC_DAPM_AIF_IN("TERT_TDM_RX_0", NULL,
864
0, SND_SOC_NOPM, 0, 0),
865
SND_SOC_DAPM_AIF_IN("TERT_TDM_RX_1", NULL,
866
0, SND_SOC_NOPM, 0, 0),
867
SND_SOC_DAPM_AIF_IN("TERT_TDM_RX_2", NULL,
868
0, SND_SOC_NOPM, 0, 0),
869
SND_SOC_DAPM_AIF_IN("TERT_TDM_RX_3", NULL,
870
0, SND_SOC_NOPM, 0, 0),
871
SND_SOC_DAPM_AIF_IN("TERT_TDM_RX_4", NULL,
872
0, SND_SOC_NOPM, 0, 0),
873
SND_SOC_DAPM_AIF_IN("TERT_TDM_RX_5", NULL,
874
0, SND_SOC_NOPM, 0, 0),
875
SND_SOC_DAPM_AIF_IN("TERT_TDM_RX_6", NULL,
876
0, SND_SOC_NOPM, 0, 0),
877
SND_SOC_DAPM_AIF_IN("TERT_TDM_RX_7", NULL,
878
0, SND_SOC_NOPM, 0, 0),
879
SND_SOC_DAPM_AIF_OUT("TERT_TDM_TX_0", NULL,
880
0, SND_SOC_NOPM, 0, 0),
881
SND_SOC_DAPM_AIF_OUT("TERT_TDM_TX_1", NULL,
882
0, SND_SOC_NOPM, 0, 0),
883
SND_SOC_DAPM_AIF_OUT("TERT_TDM_TX_2", NULL,
884
0, SND_SOC_NOPM, 0, 0),
885
SND_SOC_DAPM_AIF_OUT("TERT_TDM_TX_3", NULL,
886
0, SND_SOC_NOPM, 0, 0),
887
SND_SOC_DAPM_AIF_OUT("TERT_TDM_TX_4", NULL,
888
0, SND_SOC_NOPM, 0, 0),
889
SND_SOC_DAPM_AIF_OUT("TERT_TDM_TX_5", NULL,
890
0, SND_SOC_NOPM, 0, 0),
891
SND_SOC_DAPM_AIF_OUT("TERT_TDM_TX_6", NULL,
892
0, SND_SOC_NOPM, 0, 0),
893
SND_SOC_DAPM_AIF_OUT("TERT_TDM_TX_7", NULL,
894
0, SND_SOC_NOPM, 0, 0),
895
896
SND_SOC_DAPM_AIF_IN("QUAT_TDM_RX_0", NULL,
897
0, SND_SOC_NOPM, 0, 0),
898
SND_SOC_DAPM_AIF_IN("QUAT_TDM_RX_1", NULL,
899
0, SND_SOC_NOPM, 0, 0),
900
SND_SOC_DAPM_AIF_IN("QUAT_TDM_RX_2", NULL,
901
0, SND_SOC_NOPM, 0, 0),
902
SND_SOC_DAPM_AIF_IN("QUAT_TDM_RX_3", NULL,
903
0, SND_SOC_NOPM, 0, 0),
904
SND_SOC_DAPM_AIF_IN("QUAT_TDM_RX_4", NULL,
905
0, SND_SOC_NOPM, 0, 0),
906
SND_SOC_DAPM_AIF_IN("QUAT_TDM_RX_5", NULL,
907
0, SND_SOC_NOPM, 0, 0),
908
SND_SOC_DAPM_AIF_IN("QUAT_TDM_RX_6", NULL,
909
0, SND_SOC_NOPM, 0, 0),
910
SND_SOC_DAPM_AIF_IN("QUAT_TDM_RX_7", NULL,
911
0, SND_SOC_NOPM, 0, 0),
912
SND_SOC_DAPM_AIF_OUT("QUAT_TDM_TX_0", NULL,
913
0, SND_SOC_NOPM, 0, 0),
914
SND_SOC_DAPM_AIF_OUT("QUAT_TDM_TX_1", NULL,
915
0, SND_SOC_NOPM, 0, 0),
916
SND_SOC_DAPM_AIF_OUT("QUAT_TDM_TX_2", NULL,
917
0, SND_SOC_NOPM, 0, 0),
918
SND_SOC_DAPM_AIF_OUT("QUAT_TDM_TX_3", NULL,
919
0, SND_SOC_NOPM, 0, 0),
920
SND_SOC_DAPM_AIF_OUT("QUAT_TDM_TX_4", NULL,
921
0, SND_SOC_NOPM, 0, 0),
922
SND_SOC_DAPM_AIF_OUT("QUAT_TDM_TX_5", NULL,
923
0, SND_SOC_NOPM, 0, 0),
924
SND_SOC_DAPM_AIF_OUT("QUAT_TDM_TX_6", NULL,
925
0, SND_SOC_NOPM, 0, 0),
926
SND_SOC_DAPM_AIF_OUT("QUAT_TDM_TX_7", NULL,
927
0, SND_SOC_NOPM, 0, 0),
928
929
SND_SOC_DAPM_AIF_IN("QUIN_TDM_RX_0", NULL,
930
0, SND_SOC_NOPM, 0, 0),
931
SND_SOC_DAPM_AIF_IN("QUIN_TDM_RX_1", NULL,
932
0, SND_SOC_NOPM, 0, 0),
933
SND_SOC_DAPM_AIF_IN("QUIN_TDM_RX_2", NULL,
934
0, SND_SOC_NOPM, 0, 0),
935
SND_SOC_DAPM_AIF_IN("QUIN_TDM_RX_3", NULL,
936
0, SND_SOC_NOPM, 0, 0),
937
SND_SOC_DAPM_AIF_IN("QUIN_TDM_RX_4", NULL,
938
0, SND_SOC_NOPM, 0, 0),
939
SND_SOC_DAPM_AIF_IN("QUIN_TDM_RX_5", NULL,
940
0, SND_SOC_NOPM, 0, 0),
941
SND_SOC_DAPM_AIF_IN("QUIN_TDM_RX_6", NULL,
942
0, SND_SOC_NOPM, 0, 0),
943
SND_SOC_DAPM_AIF_IN("QUIN_TDM_RX_7", NULL,
944
0, SND_SOC_NOPM, 0, 0),
945
SND_SOC_DAPM_AIF_OUT("QUIN_TDM_TX_0", NULL,
946
0, SND_SOC_NOPM, 0, 0),
947
SND_SOC_DAPM_AIF_OUT("QUIN_TDM_TX_1", NULL,
948
0, SND_SOC_NOPM, 0, 0),
949
SND_SOC_DAPM_AIF_OUT("QUIN_TDM_TX_2", NULL,
950
0, SND_SOC_NOPM, 0, 0),
951
SND_SOC_DAPM_AIF_OUT("QUIN_TDM_TX_3", NULL,
952
0, SND_SOC_NOPM, 0, 0),
953
SND_SOC_DAPM_AIF_OUT("QUIN_TDM_TX_4", NULL,
954
0, SND_SOC_NOPM, 0, 0),
955
SND_SOC_DAPM_AIF_OUT("QUIN_TDM_TX_5", NULL,
956
0, SND_SOC_NOPM, 0, 0),
957
SND_SOC_DAPM_AIF_OUT("QUIN_TDM_TX_6", NULL,
958
0, SND_SOC_NOPM, 0, 0),
959
SND_SOC_DAPM_AIF_OUT("QUIN_TDM_TX_7", NULL,
960
0, SND_SOC_NOPM, 0, 0),
961
SND_SOC_DAPM_AIF_OUT("DISPLAY_PORT_RX", "NULL", 0, SND_SOC_NOPM, 0, 0),
962
963
SND_SOC_DAPM_AIF_IN("WSA_CODEC_DMA_RX_0", "NULL",
964
0, SND_SOC_NOPM, 0, 0),
965
SND_SOC_DAPM_AIF_OUT("WSA_CODEC_DMA_TX_0", "NULL",
966
0, SND_SOC_NOPM, 0, 0),
967
SND_SOC_DAPM_AIF_IN("WSA_CODEC_DMA_RX_1", "NULL",
968
0, SND_SOC_NOPM, 0, 0),
969
SND_SOC_DAPM_AIF_OUT("WSA_CODEC_DMA_TX_1", "NULL",
970
0, SND_SOC_NOPM, 0, 0),
971
SND_SOC_DAPM_AIF_OUT("WSA_CODEC_DMA_TX_2", "NULL",
972
0, SND_SOC_NOPM, 0, 0),
973
SND_SOC_DAPM_AIF_OUT("VA_CODEC_DMA_TX_0", "NULL",
974
0, SND_SOC_NOPM, 0, 0),
975
SND_SOC_DAPM_AIF_OUT("VA_CODEC_DMA_TX_1", "NULL",
976
0, SND_SOC_NOPM, 0, 0),
977
SND_SOC_DAPM_AIF_OUT("VA_CODEC_DMA_TX_2", "NULL",
978
0, SND_SOC_NOPM, 0, 0),
979
SND_SOC_DAPM_AIF_IN("RX_CODEC_DMA_RX_0", "NULL",
980
0, SND_SOC_NOPM, 0, 0),
981
SND_SOC_DAPM_AIF_OUT("TX_CODEC_DMA_TX_0", "NULL",
982
0, SND_SOC_NOPM, 0, 0),
983
SND_SOC_DAPM_AIF_IN("RX_CODEC_DMA_RX_1", "NULL",
984
0, SND_SOC_NOPM, 0, 0),
985
SND_SOC_DAPM_AIF_OUT("TX_CODEC_DMA_TX_1", "NULL",
986
0, SND_SOC_NOPM, 0, 0),
987
SND_SOC_DAPM_AIF_IN("RX_CODEC_DMA_RX_2", "NULL",
988
0, SND_SOC_NOPM, 0, 0),
989
SND_SOC_DAPM_AIF_OUT("TX_CODEC_DMA_TX_2", "NULL",
990
0, SND_SOC_NOPM, 0, 0),
991
SND_SOC_DAPM_AIF_IN("RX_CODEC_DMA_RX_3", "NULL",
992
0, SND_SOC_NOPM, 0, 0),
993
SND_SOC_DAPM_AIF_OUT("TX_CODEC_DMA_TX_3", "NULL",
994
0, SND_SOC_NOPM, 0, 0),
995
SND_SOC_DAPM_AIF_IN("RX_CODEC_DMA_RX_4", "NULL",
996
0, SND_SOC_NOPM, 0, 0),
997
SND_SOC_DAPM_AIF_OUT("TX_CODEC_DMA_TX_4", "NULL",
998
0, SND_SOC_NOPM, 0, 0),
999
SND_SOC_DAPM_AIF_IN("RX_CODEC_DMA_RX_5", "NULL",
1000
0, SND_SOC_NOPM, 0, 0),
1001
SND_SOC_DAPM_AIF_OUT("TX_CODEC_DMA_TX_5", "NULL",
1002
0, SND_SOC_NOPM, 0, 0),
1003
SND_SOC_DAPM_AIF_IN("RX_CODEC_DMA_RX_6", "NULL",
1004
0, SND_SOC_NOPM, 0, 0),
1005
SND_SOC_DAPM_AIF_IN("RX_CODEC_DMA_RX_7", "NULL",
1006
0, SND_SOC_NOPM, 0, 0),
1007
1008
SND_SOC_DAPM_AIF_IN("USB_RX", NULL, 0, SND_SOC_NOPM, 0, 0),
1009
};
1010
1011
static const struct snd_soc_component_driver q6afe_dai_component = {
1012
.name = "q6afe-dai-component",
1013
.dapm_widgets = q6afe_dai_widgets,
1014
.num_dapm_widgets = ARRAY_SIZE(q6afe_dai_widgets),
1015
.dapm_routes = q6afe_dapm_routes,
1016
.num_dapm_routes = ARRAY_SIZE(q6afe_dapm_routes),
1017
.of_xlate_dai_name = q6dsp_audio_ports_of_xlate_dai_name,
1018
1019
};
1020
1021
static void of_q6afe_parse_dai_data(struct device *dev,
1022
struct q6afe_dai_data *data)
1023
{
1024
struct device_node *node;
1025
int ret;
1026
1027
for_each_child_of_node(dev->of_node, node) {
1028
unsigned int lines[Q6AFE_MAX_MI2S_LINES];
1029
struct q6afe_dai_priv_data *priv;
1030
int id, i, num_lines;
1031
1032
ret = of_property_read_u32(node, "reg", &id);
1033
if (ret || id < 0 || id >= AFE_PORT_MAX) {
1034
dev_err(dev, "valid dai id not found:%d\n", ret);
1035
continue;
1036
}
1037
1038
switch (id) {
1039
/* MI2S specific properties */
1040
case QUINARY_MI2S_RX ... QUINARY_MI2S_TX:
1041
case PRIMARY_MI2S_RX ... QUATERNARY_MI2S_TX:
1042
priv = &data->priv[id];
1043
ret = of_property_read_variable_u32_array(node,
1044
"qcom,sd-lines",
1045
lines, 0,
1046
Q6AFE_MAX_MI2S_LINES);
1047
if (ret < 0)
1048
num_lines = 0;
1049
else
1050
num_lines = ret;
1051
1052
priv->sd_line_mask = 0;
1053
1054
for (i = 0; i < num_lines; i++)
1055
priv->sd_line_mask |= BIT(lines[i]);
1056
1057
break;
1058
case PRIMARY_TDM_RX_0 ... QUINARY_TDM_TX_7:
1059
priv = &data->priv[id];
1060
ret = of_property_read_u32(node, "qcom,tdm-sync-mode",
1061
&priv->sync_mode);
1062
if (ret) {
1063
dev_err(dev, "No Sync mode from DT\n");
1064
break;
1065
}
1066
ret = of_property_read_u32(node, "qcom,tdm-sync-src",
1067
&priv->sync_src);
1068
if (ret) {
1069
dev_err(dev, "No Sync Src from DT\n");
1070
break;
1071
}
1072
ret = of_property_read_u32(node, "qcom,tdm-data-out",
1073
&priv->data_out_enable);
1074
if (ret) {
1075
dev_err(dev, "No Data out enable from DT\n");
1076
break;
1077
}
1078
ret = of_property_read_u32(node, "qcom,tdm-invert-sync",
1079
&priv->invert_sync);
1080
if (ret) {
1081
dev_err(dev, "No Invert sync from DT\n");
1082
break;
1083
}
1084
ret = of_property_read_u32(node, "qcom,tdm-data-delay",
1085
&priv->data_delay);
1086
if (ret) {
1087
dev_err(dev, "No Data Delay from DT\n");
1088
break;
1089
}
1090
ret = of_property_read_u32(node, "qcom,tdm-data-align",
1091
&priv->data_align);
1092
if (ret) {
1093
dev_err(dev, "No Data align from DT\n");
1094
break;
1095
}
1096
break;
1097
default:
1098
break;
1099
}
1100
}
1101
}
1102
1103
static int q6afe_dai_dev_probe(struct platform_device *pdev)
1104
{
1105
struct q6dsp_audio_port_dai_driver_config cfg;
1106
struct snd_soc_dai_driver *dais;
1107
struct q6afe_dai_data *dai_data;
1108
struct device *dev = &pdev->dev;
1109
int num_dais;
1110
1111
dai_data = devm_kzalloc(dev, sizeof(*dai_data), GFP_KERNEL);
1112
if (!dai_data)
1113
return -ENOMEM;
1114
1115
dev_set_drvdata(dev, dai_data);
1116
of_q6afe_parse_dai_data(dev, dai_data);
1117
1118
cfg.q6hdmi_ops = &q6hdmi_ops;
1119
cfg.q6slim_ops = &q6slim_ops;
1120
cfg.q6i2s_ops = &q6i2s_ops;
1121
cfg.q6tdm_ops = &q6tdm_ops;
1122
cfg.q6dma_ops = &q6dma_ops;
1123
cfg.q6usb_ops = &q6afe_usb_ops;
1124
dais = q6dsp_audio_ports_set_config(dev, &cfg, &num_dais);
1125
1126
return devm_snd_soc_register_component(dev, &q6afe_dai_component, dais, num_dais);
1127
}
1128
1129
#ifdef CONFIG_OF
1130
static const struct of_device_id q6afe_dai_device_id[] = {
1131
{ .compatible = "qcom,q6afe-dais" },
1132
{},
1133
};
1134
MODULE_DEVICE_TABLE(of, q6afe_dai_device_id);
1135
#endif
1136
1137
static struct platform_driver q6afe_dai_platform_driver = {
1138
.driver = {
1139
.name = "q6afe-dai",
1140
.of_match_table = of_match_ptr(q6afe_dai_device_id),
1141
},
1142
.probe = q6afe_dai_dev_probe,
1143
};
1144
module_platform_driver(q6afe_dai_platform_driver);
1145
1146
MODULE_DESCRIPTION("Q6 Audio Frontend dai driver");
1147
MODULE_LICENSE("GPL v2");
1148
1149