1 // SPDX-License-Identifier: GPL-2.0
2 // Copyright (c) 2011-2017, The Linux Foundation. All rights reserved.
3 // Copyright (c) 2018, Linaro Limited
6 #include <linux/init.h>
7 #include <linux/module.h>
8 #include <linux/device.h>
9 #include <linux/platform_device.h>
10 #include <linux/slab.h>
11 #include <sound/pcm.h>
12 #include <sound/soc.h>
13 #include <sound/pcm_params.h>
16 #define Q6AFE_TDM_PB_DAI(pre, num, did) { \
18 .stream_name = pre" TDM"#num" Playback", \
19 .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |\
20 SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 |\
21 SNDRV_PCM_RATE_176400, \
22 .formats = SNDRV_PCM_FMTBIT_S16_LE | \
23 SNDRV_PCM_FMTBIT_S24_LE | \
24 SNDRV_PCM_FMTBIT_S32_LE, \
33 .probe = msm_dai_q6_dai_probe, \
34 .remove = msm_dai_q6_dai_remove, \
37 #define Q6AFE_TDM_CAP_DAI(pre, num, did) { \
39 .stream_name = pre" TDM"#num" Capture", \
40 .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |\
41 SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 |\
42 SNDRV_PCM_RATE_176400, \
43 .formats = SNDRV_PCM_FMTBIT_S16_LE | \
44 SNDRV_PCM_FMTBIT_S24_LE | \
45 SNDRV_PCM_FMTBIT_S32_LE, \
54 .probe = msm_dai_q6_dai_probe, \
55 .remove = msm_dai_q6_dai_remove, \
58 struct q6afe_dai_priv_data
{
59 uint32_t sd_line_mask
;
62 uint32_t data_out_enable
;
68 struct q6afe_dai_data
{
69 struct q6afe_port
*port
[AFE_PORT_MAX
];
70 struct q6afe_port_config port_config
[AFE_PORT_MAX
];
71 bool is_port_started
[AFE_PORT_MAX
];
72 struct q6afe_dai_priv_data priv
[AFE_PORT_MAX
];
75 static int q6slim_hw_params(struct snd_pcm_substream
*substream
,
76 struct snd_pcm_hw_params
*params
,
77 struct snd_soc_dai
*dai
)
80 struct q6afe_dai_data
*dai_data
= dev_get_drvdata(dai
->dev
);
81 struct q6afe_slim_cfg
*slim
= &dai_data
->port_config
[dai
->id
].slim
;
83 slim
->sample_rate
= params_rate(params
);
85 switch (params_format(params
)) {
86 case SNDRV_PCM_FORMAT_S16_LE
:
87 case SNDRV_PCM_FORMAT_SPECIAL
:
90 case SNDRV_PCM_FORMAT_S24_LE
:
93 case SNDRV_PCM_FORMAT_S32_LE
:
97 pr_err("%s: format %d\n",
98 __func__
, params_format(params
));
105 static int q6hdmi_hw_params(struct snd_pcm_substream
*substream
,
106 struct snd_pcm_hw_params
*params
,
107 struct snd_soc_dai
*dai
)
109 struct q6afe_dai_data
*dai_data
= dev_get_drvdata(dai
->dev
);
110 int channels
= params_channels(params
);
111 struct q6afe_hdmi_cfg
*hdmi
= &dai_data
->port_config
[dai
->id
].hdmi
;
113 hdmi
->sample_rate
= params_rate(params
);
114 switch (params_format(params
)) {
115 case SNDRV_PCM_FORMAT_S16_LE
:
116 hdmi
->bit_width
= 16;
118 case SNDRV_PCM_FORMAT_S24_LE
:
119 hdmi
->bit_width
= 24;
123 /* HDMI spec CEA-861-E: Table 28 Audio InfoFrame Data Byte 4 */
126 hdmi
->channel_allocation
= 0;
129 hdmi
->channel_allocation
= 0x02;
132 hdmi
->channel_allocation
= 0x06;
135 hdmi
->channel_allocation
= 0x0A;
138 hdmi
->channel_allocation
= 0x0B;
141 hdmi
->channel_allocation
= 0x12;
144 hdmi
->channel_allocation
= 0x13;
147 dev_err(dai
->dev
, "invalid Channels = %u\n", channels
);
154 static int q6i2s_hw_params(struct snd_pcm_substream
*substream
,
155 struct snd_pcm_hw_params
*params
,
156 struct snd_soc_dai
*dai
)
158 struct q6afe_dai_data
*dai_data
= dev_get_drvdata(dai
->dev
);
159 struct q6afe_i2s_cfg
*i2s
= &dai_data
->port_config
[dai
->id
].i2s_cfg
;
161 i2s
->sample_rate
= params_rate(params
);
162 i2s
->bit_width
= params_width(params
);
163 i2s
->num_channels
= params_channels(params
);
164 i2s
->sd_line_mask
= dai_data
->priv
[dai
->id
].sd_line_mask
;
169 static int q6i2s_set_fmt(struct snd_soc_dai
*dai
, unsigned int fmt
)
171 struct q6afe_dai_data
*dai_data
= dev_get_drvdata(dai
->dev
);
172 struct q6afe_i2s_cfg
*i2s
= &dai_data
->port_config
[dai
->id
].i2s_cfg
;
179 static int q6tdm_set_tdm_slot(struct snd_soc_dai
*dai
,
180 unsigned int tx_mask
,
181 unsigned int rx_mask
,
182 int slots
, int slot_width
)
185 struct q6afe_dai_data
*dai_data
= dev_get_drvdata(dai
->dev
);
186 struct q6afe_tdm_cfg
*tdm
= &dai_data
->port_config
[dai
->id
].tdm
;
187 unsigned int cap_mask
;
190 /* HW only supports 16 and 32 bit slot width configuration */
191 if ((slot_width
!= 16) && (slot_width
!= 32)) {
192 dev_err(dai
->dev
, "%s: invalid slot_width %d\n",
193 __func__
, slot_width
);
197 /* HW supports 1-32 slots configuration. Typical: 1, 2, 4, 8, 16, 32 */
212 dev_err(dai
->dev
, "%s: invalid slots %d\n",
218 case PRIMARY_TDM_RX_0
... QUINARY_TDM_TX_7
:
219 tdm
->nslots_per_frame
= slots
;
220 tdm
->slot_width
= slot_width
;
221 /* TDM RX dais ids are even and tx are odd */
222 tdm
->slot_mask
= (dai
->id
& 0x1 ? tx_mask
: rx_mask
) & cap_mask
;
225 dev_err(dai
->dev
, "%s: invalid dai id 0x%x\n",
233 static int q6tdm_set_channel_map(struct snd_soc_dai
*dai
,
234 unsigned int tx_num
, unsigned int *tx_slot
,
235 unsigned int rx_num
, unsigned int *rx_slot
)
238 struct q6afe_dai_data
*dai_data
= dev_get_drvdata(dai
->dev
);
239 struct q6afe_tdm_cfg
*tdm
= &dai_data
->port_config
[dai
->id
].tdm
;
244 case PRIMARY_TDM_RX_0
... QUINARY_TDM_TX_7
:
247 dev_err(dai
->dev
, "tx slot not found\n");
250 if (tx_num
> AFE_PORT_MAX_AUDIO_CHAN_CNT
) {
251 dev_err(dai
->dev
, "invalid tx num %d\n",
256 for (i
= 0; i
< tx_num
; i
++)
257 tdm
->ch_mapping
[i
] = tx_slot
[i
];
259 for (i
= tx_num
; i
< AFE_PORT_MAX_AUDIO_CHAN_CNT
; i
++)
260 tdm
->ch_mapping
[i
] = Q6AFE_CMAP_INVALID
;
262 tdm
->num_channels
= tx_num
;
266 dev_err(dai
->dev
, "rx slot not found\n");
269 if (rx_num
> AFE_PORT_MAX_AUDIO_CHAN_CNT
) {
270 dev_err(dai
->dev
, "invalid rx num %d\n",
275 for (i
= 0; i
< rx_num
; i
++)
276 tdm
->ch_mapping
[i
] = rx_slot
[i
];
278 for (i
= rx_num
; i
< AFE_PORT_MAX_AUDIO_CHAN_CNT
; i
++)
279 tdm
->ch_mapping
[i
] = Q6AFE_CMAP_INVALID
;
281 tdm
->num_channels
= rx_num
;
286 dev_err(dai
->dev
, "%s: invalid dai id 0x%x\n",
294 static int q6tdm_hw_params(struct snd_pcm_substream
*substream
,
295 struct snd_pcm_hw_params
*params
,
296 struct snd_soc_dai
*dai
)
298 struct q6afe_dai_data
*dai_data
= dev_get_drvdata(dai
->dev
);
299 struct q6afe_tdm_cfg
*tdm
= &dai_data
->port_config
[dai
->id
].tdm
;
301 tdm
->bit_width
= params_width(params
);
302 tdm
->sample_rate
= params_rate(params
);
303 tdm
->num_channels
= params_channels(params
);
304 tdm
->data_align_type
= dai_data
->priv
[dai
->id
].data_align
;
305 tdm
->sync_src
= dai_data
->priv
[dai
->id
].sync_src
;
306 tdm
->sync_mode
= dai_data
->priv
[dai
->id
].sync_mode
;
310 static void q6afe_dai_shutdown(struct snd_pcm_substream
*substream
,
311 struct snd_soc_dai
*dai
)
313 struct q6afe_dai_data
*dai_data
= dev_get_drvdata(dai
->dev
);
316 if (!dai_data
->is_port_started
[dai
->id
])
319 rc
= q6afe_port_stop(dai_data
->port
[dai
->id
]);
321 dev_err(dai
->dev
, "fail to close AFE port (%d)\n", rc
);
323 dai_data
->is_port_started
[dai
->id
] = false;
327 static int q6afe_dai_prepare(struct snd_pcm_substream
*substream
,
328 struct snd_soc_dai
*dai
)
330 struct q6afe_dai_data
*dai_data
= dev_get_drvdata(dai
->dev
);
333 if (dai_data
->is_port_started
[dai
->id
]) {
334 /* stop the port and restart with new port config */
335 rc
= q6afe_port_stop(dai_data
->port
[dai
->id
]);
337 dev_err(dai
->dev
, "fail to close AFE port (%d)\n", rc
);
344 q6afe_hdmi_port_prepare(dai_data
->port
[dai
->id
],
345 &dai_data
->port_config
[dai
->id
].hdmi
);
347 case SLIMBUS_0_RX
... SLIMBUS_6_TX
:
348 q6afe_slim_port_prepare(dai_data
->port
[dai
->id
],
349 &dai_data
->port_config
[dai
->id
].slim
);
351 case PRIMARY_MI2S_RX
... QUATERNARY_MI2S_TX
:
352 rc
= q6afe_i2s_port_prepare(dai_data
->port
[dai
->id
],
353 &dai_data
->port_config
[dai
->id
].i2s_cfg
);
355 dev_err(dai
->dev
, "fail to prepare AFE port %x\n",
360 case PRIMARY_TDM_RX_0
... QUINARY_TDM_TX_7
:
361 q6afe_tdm_port_prepare(dai_data
->port
[dai
->id
],
362 &dai_data
->port_config
[dai
->id
].tdm
);
368 rc
= q6afe_port_start(dai_data
->port
[dai
->id
]);
370 dev_err(dai
->dev
, "fail to start AFE port %x\n", dai
->id
);
373 dai_data
->is_port_started
[dai
->id
] = true;
378 static int q6slim_set_channel_map(struct snd_soc_dai
*dai
,
379 unsigned int tx_num
, unsigned int *tx_slot
,
380 unsigned int rx_num
, unsigned int *rx_slot
)
382 struct q6afe_dai_data
*dai_data
= dev_get_drvdata(dai
->dev
);
383 struct q6afe_port_config
*pcfg
= &dai_data
->port_config
[dai
->id
];
389 pr_err("%s: tx slot not found\n", __func__
);
393 for (i
= 0; i
< tx_num
; i
++)
394 pcfg
->slim
.ch_mapping
[i
] = tx_slot
[i
];
396 pcfg
->slim
.num_channels
= tx_num
;
401 pr_err("%s: rx slot not found\n", __func__
);
405 for (i
= 0; i
< rx_num
; i
++)
406 pcfg
->slim
.ch_mapping
[i
] = rx_slot
[i
];
408 pcfg
->slim
.num_channels
= rx_num
;
415 static int q6afe_mi2s_set_sysclk(struct snd_soc_dai
*dai
,
416 int clk_id
, unsigned int freq
, int dir
)
418 struct q6afe_dai_data
*dai_data
= dev_get_drvdata(dai
->dev
);
419 struct q6afe_port
*port
= dai_data
->port
[dai
->id
];
423 return q6afe_port_set_sysclk(port
, clk_id
, 0, 5, freq
, dir
);
426 return q6afe_port_set_sysclk(port
, clk_id
,
427 Q6AFE_LPASS_CLK_SRC_INTERNAL
,
428 Q6AFE_LPASS_CLK_ROOT_DEFAULT
,
430 case Q6AFE_LPASS_CLK_ID_PRI_MI2S_IBIT
... Q6AFE_LPASS_CLK_ID_QUI_MI2S_OSR
:
431 case Q6AFE_LPASS_CLK_ID_MCLK_1
... Q6AFE_LPASS_CLK_ID_INT_MCLK_1
:
432 return q6afe_port_set_sysclk(port
, clk_id
,
433 Q6AFE_LPASS_CLK_ATTRIBUTE_COUPLE_NO
,
434 Q6AFE_LPASS_CLK_ROOT_DEFAULT
,
436 case Q6AFE_LPASS_CLK_ID_PRI_TDM_IBIT
... Q6AFE_LPASS_CLK_ID_QUIN_TDM_EBIT
:
437 return q6afe_port_set_sysclk(port
, clk_id
,
438 Q6AFE_LPASS_CLK_ATTRIBUTE_INVERT_COUPLE_NO
,
439 Q6AFE_LPASS_CLK_ROOT_DEFAULT
,
446 static const struct snd_soc_dapm_route q6afe_dapm_routes
[] = {
447 {"HDMI Playback", NULL
, "HDMI_RX"},
448 {"Slimbus1 Playback", NULL
, "SLIMBUS_1_RX"},
449 {"Slimbus2 Playback", NULL
, "SLIMBUS_2_RX"},
450 {"Slimbus3 Playback", NULL
, "SLIMBUS_3_RX"},
451 {"Slimbus4 Playback", NULL
, "SLIMBUS_4_RX"},
452 {"Slimbus5 Playback", NULL
, "SLIMBUS_5_RX"},
453 {"Slimbus6 Playback", NULL
, "SLIMBUS_6_RX"},
455 {"SLIMBUS_0_TX", NULL
, "Slimbus Capture"},
456 {"SLIMBUS_1_TX", NULL
, "Slimbus1 Capture"},
457 {"SLIMBUS_2_TX", NULL
, "Slimbus2 Capture"},
458 {"SLIMBUS_3_TX", NULL
, "Slimbus3 Capture"},
459 {"SLIMBUS_4_TX", NULL
, "Slimbus4 Capture"},
460 {"SLIMBUS_5_TX", NULL
, "Slimbus5 Capture"},
461 {"SLIMBUS_6_TX", NULL
, "Slimbus6 Capture"},
463 {"Primary MI2S Playback", NULL
, "PRI_MI2S_RX"},
464 {"Secondary MI2S Playback", NULL
, "SEC_MI2S_RX"},
465 {"Tertiary MI2S Playback", NULL
, "TERT_MI2S_RX"},
466 {"Quaternary MI2S Playback", NULL
, "QUAT_MI2S_RX"},
468 {"Primary TDM0 Playback", NULL
, "PRIMARY_TDM_RX_0"},
469 {"Primary TDM1 Playback", NULL
, "PRIMARY_TDM_RX_1"},
470 {"Primary TDM2 Playback", NULL
, "PRIMARY_TDM_RX_2"},
471 {"Primary TDM3 Playback", NULL
, "PRIMARY_TDM_RX_3"},
472 {"Primary TDM4 Playback", NULL
, "PRIMARY_TDM_RX_4"},
473 {"Primary TDM5 Playback", NULL
, "PRIMARY_TDM_RX_5"},
474 {"Primary TDM6 Playback", NULL
, "PRIMARY_TDM_RX_6"},
475 {"Primary TDM7 Playback", NULL
, "PRIMARY_TDM_RX_7"},
477 {"Secondary TDM0 Playback", NULL
, "SEC_TDM_RX_0"},
478 {"Secondary TDM1 Playback", NULL
, "SEC_TDM_RX_1"},
479 {"Secondary TDM2 Playback", NULL
, "SEC_TDM_RX_2"},
480 {"Secondary TDM3 Playback", NULL
, "SEC_TDM_RX_3"},
481 {"Secondary TDM4 Playback", NULL
, "SEC_TDM_RX_4"},
482 {"Secondary TDM5 Playback", NULL
, "SEC_TDM_RX_5"},
483 {"Secondary TDM6 Playback", NULL
, "SEC_TDM_RX_6"},
484 {"Secondary TDM7 Playback", NULL
, "SEC_TDM_RX_7"},
486 {"Tertiary TDM0 Playback", NULL
, "TERT_TDM_RX_0"},
487 {"Tertiary TDM1 Playback", NULL
, "TERT_TDM_RX_1"},
488 {"Tertiary TDM2 Playback", NULL
, "TERT_TDM_RX_2"},
489 {"Tertiary TDM3 Playback", NULL
, "TERT_TDM_RX_3"},
490 {"Tertiary TDM4 Playback", NULL
, "TERT_TDM_RX_4"},
491 {"Tertiary TDM5 Playback", NULL
, "TERT_TDM_RX_5"},
492 {"Tertiary TDM6 Playback", NULL
, "TERT_TDM_RX_6"},
493 {"Tertiary TDM7 Playback", NULL
, "TERT_TDM_RX_7"},
495 {"Quaternary TDM0 Playback", NULL
, "QUAT_TDM_RX_0"},
496 {"Quaternary TDM1 Playback", NULL
, "QUAT_TDM_RX_1"},
497 {"Quaternary TDM2 Playback", NULL
, "QUAT_TDM_RX_2"},
498 {"Quaternary TDM3 Playback", NULL
, "QUAT_TDM_RX_3"},
499 {"Quaternary TDM4 Playback", NULL
, "QUAT_TDM_RX_4"},
500 {"Quaternary TDM5 Playback", NULL
, "QUAT_TDM_RX_5"},
501 {"Quaternary TDM6 Playback", NULL
, "QUAT_TDM_RX_6"},
502 {"Quaternary TDM7 Playback", NULL
, "QUAT_TDM_RX_7"},
504 {"Quinary TDM0 Playback", NULL
, "QUIN_TDM_RX_0"},
505 {"Quinary TDM1 Playback", NULL
, "QUIN_TDM_RX_1"},
506 {"Quinary TDM2 Playback", NULL
, "QUIN_TDM_RX_2"},
507 {"Quinary TDM3 Playback", NULL
, "QUIN_TDM_RX_3"},
508 {"Quinary TDM4 Playback", NULL
, "QUIN_TDM_RX_4"},
509 {"Quinary TDM5 Playback", NULL
, "QUIN_TDM_RX_5"},
510 {"Quinary TDM6 Playback", NULL
, "QUIN_TDM_RX_6"},
511 {"Quinary TDM7 Playback", NULL
, "QUIN_TDM_RX_7"},
513 {"PRIMARY_TDM_TX_0", NULL
, "Primary TDM0 Capture"},
514 {"PRIMARY_TDM_TX_1", NULL
, "Primary TDM1 Capture"},
515 {"PRIMARY_TDM_TX_2", NULL
, "Primary TDM2 Capture"},
516 {"PRIMARY_TDM_TX_3", NULL
, "Primary TDM3 Capture"},
517 {"PRIMARY_TDM_TX_4", NULL
, "Primary TDM4 Capture"},
518 {"PRIMARY_TDM_TX_5", NULL
, "Primary TDM5 Capture"},
519 {"PRIMARY_TDM_TX_6", NULL
, "Primary TDM6 Capture"},
520 {"PRIMARY_TDM_TX_7", NULL
, "Primary TDM7 Capture"},
522 {"SEC_TDM_TX_0", NULL
, "Secondary TDM0 Capture"},
523 {"SEC_TDM_TX_1", NULL
, "Secondary TDM1 Capture"},
524 {"SEC_TDM_TX_2", NULL
, "Secondary TDM2 Capture"},
525 {"SEC_TDM_TX_3", NULL
, "Secondary TDM3 Capture"},
526 {"SEC_TDM_TX_4", NULL
, "Secondary TDM4 Capture"},
527 {"SEC_TDM_TX_5", NULL
, "Secondary TDM5 Capture"},
528 {"SEC_TDM_TX_6", NULL
, "Secondary TDM6 Capture"},
529 {"SEC_TDM_TX_7", NULL
, "Secondary TDM7 Capture"},
531 {"TERT_TDM_TX_0", NULL
, "Tertiary TDM0 Capture"},
532 {"TERT_TDM_TX_1", NULL
, "Tertiary TDM1 Capture"},
533 {"TERT_TDM_TX_2", NULL
, "Tertiary TDM2 Capture"},
534 {"TERT_TDM_TX_3", NULL
, "Tertiary TDM3 Capture"},
535 {"TERT_TDM_TX_4", NULL
, "Tertiary TDM4 Capture"},
536 {"TERT_TDM_TX_5", NULL
, "Tertiary TDM5 Capture"},
537 {"TERT_TDM_TX_6", NULL
, "Tertiary TDM6 Capture"},
538 {"TERT_TDM_TX_7", NULL
, "Tertiary TDM7 Capture"},
540 {"QUAT_TDM_TX_0", NULL
, "Quaternary TDM0 Capture"},
541 {"QUAT_TDM_TX_1", NULL
, "Quaternary TDM1 Capture"},
542 {"QUAT_TDM_TX_2", NULL
, "Quaternary TDM2 Capture"},
543 {"QUAT_TDM_TX_3", NULL
, "Quaternary TDM3 Capture"},
544 {"QUAT_TDM_TX_4", NULL
, "Quaternary TDM4 Capture"},
545 {"QUAT_TDM_TX_5", NULL
, "Quaternary TDM5 Capture"},
546 {"QUAT_TDM_TX_6", NULL
, "Quaternary TDM6 Capture"},
547 {"QUAT_TDM_TX_7", NULL
, "Quaternary TDM7 Capture"},
549 {"QUIN_TDM_TX_0", NULL
, "Quinary TDM0 Capture"},
550 {"QUIN_TDM_TX_1", NULL
, "Quinary TDM1 Capture"},
551 {"QUIN_TDM_TX_2", NULL
, "Quinary TDM2 Capture"},
552 {"QUIN_TDM_TX_3", NULL
, "Quinary TDM3 Capture"},
553 {"QUIN_TDM_TX_4", NULL
, "Quinary TDM4 Capture"},
554 {"QUIN_TDM_TX_5", NULL
, "Quinary TDM5 Capture"},
555 {"QUIN_TDM_TX_6", NULL
, "Quinary TDM6 Capture"},
556 {"QUIN_TDM_TX_7", NULL
, "Quinary TDM7 Capture"},
558 {"TERT_MI2S_TX", NULL
, "Tertiary MI2S Capture"},
559 {"PRI_MI2S_TX", NULL
, "Primary MI2S Capture"},
560 {"SEC_MI2S_TX", NULL
, "Secondary MI2S Capture"},
561 {"QUAT_MI2S_TX", NULL
, "Quaternary MI2S Capture"},
564 static struct snd_soc_dai_ops q6hdmi_ops
= {
565 .prepare
= q6afe_dai_prepare
,
566 .hw_params
= q6hdmi_hw_params
,
567 .shutdown
= q6afe_dai_shutdown
,
570 static struct snd_soc_dai_ops q6i2s_ops
= {
571 .prepare
= q6afe_dai_prepare
,
572 .hw_params
= q6i2s_hw_params
,
573 .set_fmt
= q6i2s_set_fmt
,
574 .shutdown
= q6afe_dai_shutdown
,
575 .set_sysclk
= q6afe_mi2s_set_sysclk
,
578 static struct snd_soc_dai_ops q6slim_ops
= {
579 .prepare
= q6afe_dai_prepare
,
580 .hw_params
= q6slim_hw_params
,
581 .shutdown
= q6afe_dai_shutdown
,
582 .set_channel_map
= q6slim_set_channel_map
,
585 static struct snd_soc_dai_ops q6tdm_ops
= {
586 .prepare
= q6afe_dai_prepare
,
587 .shutdown
= q6afe_dai_shutdown
,
588 .set_sysclk
= q6afe_mi2s_set_sysclk
,
589 .set_tdm_slot
= q6tdm_set_tdm_slot
,
590 .set_channel_map
= q6tdm_set_channel_map
,
591 .hw_params
= q6tdm_hw_params
,
594 static int msm_dai_q6_dai_probe(struct snd_soc_dai
*dai
)
596 struct q6afe_dai_data
*dai_data
= dev_get_drvdata(dai
->dev
);
597 struct q6afe_port
*port
;
599 port
= q6afe_port_get_from_id(dai
->dev
, dai
->id
);
601 dev_err(dai
->dev
, "Unable to get afe port\n");
604 dai_data
->port
[dai
->id
] = port
;
609 static int msm_dai_q6_dai_remove(struct snd_soc_dai
*dai
)
611 struct q6afe_dai_data
*dai_data
= dev_get_drvdata(dai
->dev
);
613 q6afe_port_put(dai_data
->port
[dai
->id
]);
614 dai_data
->port
[dai
->id
] = NULL
;
619 static struct snd_soc_dai_driver q6afe_dais
[] = {
622 .stream_name
= "HDMI Playback",
623 .rates
= SNDRV_PCM_RATE_48000
|
624 SNDRV_PCM_RATE_96000
|
625 SNDRV_PCM_RATE_192000
,
626 .formats
= SNDRV_PCM_FMTBIT_S16_LE
|
627 SNDRV_PCM_FMTBIT_S24_LE
,
636 .probe
= msm_dai_q6_dai_probe
,
637 .remove
= msm_dai_q6_dai_remove
,
639 .name
= "SLIMBUS_0_RX",
642 .probe
= msm_dai_q6_dai_probe
,
643 .remove
= msm_dai_q6_dai_remove
,
645 .stream_name
= "Slimbus Playback",
646 .rates
= SNDRV_PCM_RATE_48000
| SNDRV_PCM_RATE_8000
|
647 SNDRV_PCM_RATE_16000
| SNDRV_PCM_RATE_96000
|
648 SNDRV_PCM_RATE_192000
,
649 .formats
= SNDRV_PCM_FMTBIT_S16_LE
|
650 SNDRV_PCM_FMTBIT_S24_LE
,
657 .name
= "SLIMBUS_0_TX",
660 .probe
= msm_dai_q6_dai_probe
,
661 .remove
= msm_dai_q6_dai_remove
,
663 .stream_name
= "Slimbus Capture",
664 .rates
= SNDRV_PCM_RATE_48000
| SNDRV_PCM_RATE_8000
|
665 SNDRV_PCM_RATE_16000
| SNDRV_PCM_RATE_96000
|
666 SNDRV_PCM_RATE_192000
,
667 .formats
= SNDRV_PCM_FMTBIT_S16_LE
|
668 SNDRV_PCM_FMTBIT_S24_LE
,
676 .stream_name
= "Slimbus1 Playback",
677 .rates
= SNDRV_PCM_RATE_8000
| SNDRV_PCM_RATE_16000
|
678 SNDRV_PCM_RATE_48000
| SNDRV_PCM_RATE_96000
|
679 SNDRV_PCM_RATE_192000
,
680 .formats
= SNDRV_PCM_FMTBIT_S16_LE
|
681 SNDRV_PCM_FMTBIT_S24_LE
,
687 .name
= "SLIMBUS_1_RX",
690 .probe
= msm_dai_q6_dai_probe
,
691 .remove
= msm_dai_q6_dai_remove
,
693 .name
= "SLIMBUS_1_TX",
696 .probe
= msm_dai_q6_dai_probe
,
697 .remove
= msm_dai_q6_dai_remove
,
699 .stream_name
= "Slimbus1 Capture",
700 .rates
= SNDRV_PCM_RATE_48000
| SNDRV_PCM_RATE_8000
|
701 SNDRV_PCM_RATE_16000
| SNDRV_PCM_RATE_96000
|
702 SNDRV_PCM_RATE_192000
,
703 .formats
= SNDRV_PCM_FMTBIT_S16_LE
|
704 SNDRV_PCM_FMTBIT_S24_LE
,
712 .stream_name
= "Slimbus2 Playback",
713 .rates
= SNDRV_PCM_RATE_48000
| SNDRV_PCM_RATE_8000
|
714 SNDRV_PCM_RATE_16000
| SNDRV_PCM_RATE_96000
|
715 SNDRV_PCM_RATE_192000
,
716 .formats
= SNDRV_PCM_FMTBIT_S16_LE
|
717 SNDRV_PCM_FMTBIT_S24_LE
,
723 .name
= "SLIMBUS_2_RX",
726 .probe
= msm_dai_q6_dai_probe
,
727 .remove
= msm_dai_q6_dai_remove
,
730 .name
= "SLIMBUS_2_TX",
733 .probe
= msm_dai_q6_dai_probe
,
734 .remove
= msm_dai_q6_dai_remove
,
736 .stream_name
= "Slimbus2 Capture",
737 .rates
= SNDRV_PCM_RATE_48000
| SNDRV_PCM_RATE_8000
|
738 SNDRV_PCM_RATE_16000
| SNDRV_PCM_RATE_96000
|
739 SNDRV_PCM_RATE_192000
,
740 .formats
= SNDRV_PCM_FMTBIT_S16_LE
|
741 SNDRV_PCM_FMTBIT_S24_LE
,
749 .stream_name
= "Slimbus3 Playback",
750 .rates
= SNDRV_PCM_RATE_8000
| SNDRV_PCM_RATE_16000
|
751 SNDRV_PCM_RATE_48000
| SNDRV_PCM_RATE_96000
|
752 SNDRV_PCM_RATE_192000
,
753 .formats
= SNDRV_PCM_FMTBIT_S16_LE
|
754 SNDRV_PCM_FMTBIT_S24_LE
,
760 .name
= "SLIMBUS_3_RX",
763 .probe
= msm_dai_q6_dai_probe
,
764 .remove
= msm_dai_q6_dai_remove
,
767 .name
= "SLIMBUS_3_TX",
770 .probe
= msm_dai_q6_dai_probe
,
771 .remove
= msm_dai_q6_dai_remove
,
773 .stream_name
= "Slimbus3 Capture",
774 .rates
= SNDRV_PCM_RATE_48000
| SNDRV_PCM_RATE_8000
|
775 SNDRV_PCM_RATE_16000
| SNDRV_PCM_RATE_96000
|
776 SNDRV_PCM_RATE_192000
,
777 .formats
= SNDRV_PCM_FMTBIT_S16_LE
|
778 SNDRV_PCM_FMTBIT_S24_LE
,
786 .stream_name
= "Slimbus4 Playback",
787 .rates
= SNDRV_PCM_RATE_8000
| SNDRV_PCM_RATE_16000
|
788 SNDRV_PCM_RATE_48000
| SNDRV_PCM_RATE_96000
|
789 SNDRV_PCM_RATE_192000
,
790 .formats
= SNDRV_PCM_FMTBIT_S16_LE
|
791 SNDRV_PCM_FMTBIT_S24_LE
,
797 .name
= "SLIMBUS_4_RX",
800 .probe
= msm_dai_q6_dai_probe
,
801 .remove
= msm_dai_q6_dai_remove
,
804 .name
= "SLIMBUS_4_TX",
807 .probe
= msm_dai_q6_dai_probe
,
808 .remove
= msm_dai_q6_dai_remove
,
810 .stream_name
= "Slimbus4 Capture",
811 .rates
= SNDRV_PCM_RATE_48000
| SNDRV_PCM_RATE_8000
|
812 SNDRV_PCM_RATE_16000
| SNDRV_PCM_RATE_96000
|
813 SNDRV_PCM_RATE_192000
,
814 .formats
= SNDRV_PCM_FMTBIT_S16_LE
|
815 SNDRV_PCM_FMTBIT_S24_LE
,
823 .stream_name
= "Slimbus5 Playback",
824 .rates
= SNDRV_PCM_RATE_8000
| SNDRV_PCM_RATE_16000
|
825 SNDRV_PCM_RATE_48000
| SNDRV_PCM_RATE_96000
|
826 SNDRV_PCM_RATE_192000
,
827 .formats
= SNDRV_PCM_FMTBIT_S16_LE
|
828 SNDRV_PCM_FMTBIT_S24_LE
,
834 .name
= "SLIMBUS_5_RX",
837 .probe
= msm_dai_q6_dai_probe
,
838 .remove
= msm_dai_q6_dai_remove
,
841 .name
= "SLIMBUS_5_TX",
844 .probe
= msm_dai_q6_dai_probe
,
845 .remove
= msm_dai_q6_dai_remove
,
847 .stream_name
= "Slimbus5 Capture",
848 .rates
= SNDRV_PCM_RATE_48000
| SNDRV_PCM_RATE_8000
|
849 SNDRV_PCM_RATE_16000
| SNDRV_PCM_RATE_96000
|
850 SNDRV_PCM_RATE_192000
,
851 .formats
= SNDRV_PCM_FMTBIT_S16_LE
|
852 SNDRV_PCM_FMTBIT_S24_LE
,
860 .stream_name
= "Slimbus6 Playback",
861 .rates
= SNDRV_PCM_RATE_8000
| SNDRV_PCM_RATE_16000
|
862 SNDRV_PCM_RATE_48000
| SNDRV_PCM_RATE_96000
|
863 SNDRV_PCM_RATE_192000
,
864 .formats
= SNDRV_PCM_FMTBIT_S16_LE
|
865 SNDRV_PCM_FMTBIT_S24_LE
,
872 .name
= "SLIMBUS_6_RX",
874 .probe
= msm_dai_q6_dai_probe
,
875 .remove
= msm_dai_q6_dai_remove
,
878 .name
= "SLIMBUS_6_TX",
881 .probe
= msm_dai_q6_dai_probe
,
882 .remove
= msm_dai_q6_dai_remove
,
884 .stream_name
= "Slimbus6 Capture",
885 .rates
= SNDRV_PCM_RATE_48000
| SNDRV_PCM_RATE_8000
|
886 SNDRV_PCM_RATE_16000
| SNDRV_PCM_RATE_96000
|
887 SNDRV_PCM_RATE_192000
,
888 .formats
= SNDRV_PCM_FMTBIT_S16_LE
|
889 SNDRV_PCM_FMTBIT_S24_LE
,
897 .stream_name
= "Primary MI2S Playback",
898 .rates
= SNDRV_PCM_RATE_48000
| SNDRV_PCM_RATE_8000
|
899 SNDRV_PCM_RATE_16000
,
900 .formats
= SNDRV_PCM_FMTBIT_S16_LE
|
901 SNDRV_PCM_FMTBIT_S24_LE
,
905 .id
= PRIMARY_MI2S_RX
,
906 .name
= "PRI_MI2S_RX",
908 .probe
= msm_dai_q6_dai_probe
,
909 .remove
= msm_dai_q6_dai_remove
,
912 .stream_name
= "Primary MI2S Capture",
913 .rates
= SNDRV_PCM_RATE_48000
| SNDRV_PCM_RATE_8000
|
914 SNDRV_PCM_RATE_16000
,
915 .formats
= SNDRV_PCM_FMTBIT_S16_LE
|
916 SNDRV_PCM_FMTBIT_S24_LE
,
920 .id
= PRIMARY_MI2S_TX
,
921 .name
= "PRI_MI2S_TX",
923 .probe
= msm_dai_q6_dai_probe
,
924 .remove
= msm_dai_q6_dai_remove
,
927 .stream_name
= "Secondary MI2S Playback",
928 .rates
= SNDRV_PCM_RATE_48000
| SNDRV_PCM_RATE_8000
|
929 SNDRV_PCM_RATE_16000
,
930 .formats
= SNDRV_PCM_FMTBIT_S16_LE
,
934 .name
= "SEC_MI2S_RX",
935 .id
= SECONDARY_MI2S_RX
,
937 .probe
= msm_dai_q6_dai_probe
,
938 .remove
= msm_dai_q6_dai_remove
,
941 .stream_name
= "Secondary MI2S Capture",
942 .rates
= SNDRV_PCM_RATE_48000
| SNDRV_PCM_RATE_8000
|
943 SNDRV_PCM_RATE_16000
,
944 .formats
= SNDRV_PCM_FMTBIT_S16_LE
|
945 SNDRV_PCM_FMTBIT_S24_LE
,
949 .id
= SECONDARY_MI2S_TX
,
950 .name
= "SEC_MI2S_TX",
952 .probe
= msm_dai_q6_dai_probe
,
953 .remove
= msm_dai_q6_dai_remove
,
956 .stream_name
= "Tertiary MI2S Playback",
957 .rates
= SNDRV_PCM_RATE_48000
| SNDRV_PCM_RATE_8000
|
958 SNDRV_PCM_RATE_16000
,
959 .formats
= SNDRV_PCM_FMTBIT_S16_LE
,
963 .name
= "TERT_MI2S_RX",
964 .id
= TERTIARY_MI2S_RX
,
966 .probe
= msm_dai_q6_dai_probe
,
967 .remove
= msm_dai_q6_dai_remove
,
970 .stream_name
= "Tertiary MI2S Capture",
971 .rates
= SNDRV_PCM_RATE_48000
| SNDRV_PCM_RATE_8000
|
972 SNDRV_PCM_RATE_16000
,
973 .formats
= SNDRV_PCM_FMTBIT_S16_LE
|
974 SNDRV_PCM_FMTBIT_S24_LE
,
978 .id
= TERTIARY_MI2S_TX
,
979 .name
= "TERT_MI2S_TX",
981 .probe
= msm_dai_q6_dai_probe
,
982 .remove
= msm_dai_q6_dai_remove
,
985 .stream_name
= "Quaternary MI2S Playback",
986 .rates
= SNDRV_PCM_RATE_48000
| SNDRV_PCM_RATE_8000
|
987 SNDRV_PCM_RATE_16000
,
988 .formats
= SNDRV_PCM_FMTBIT_S16_LE
,
992 .name
= "QUAT_MI2S_RX",
993 .id
= QUATERNARY_MI2S_RX
,
995 .probe
= msm_dai_q6_dai_probe
,
996 .remove
= msm_dai_q6_dai_remove
,
999 .stream_name
= "Quaternary MI2S Capture",
1000 .rates
= SNDRV_PCM_RATE_48000
| SNDRV_PCM_RATE_8000
|
1001 SNDRV_PCM_RATE_16000
,
1002 .formats
= SNDRV_PCM_FMTBIT_S16_LE
|
1003 SNDRV_PCM_FMTBIT_S24_LE
,
1007 .id
= QUATERNARY_MI2S_TX
,
1008 .name
= "QUAT_MI2S_TX",
1010 .probe
= msm_dai_q6_dai_probe
,
1011 .remove
= msm_dai_q6_dai_remove
,
1013 Q6AFE_TDM_PB_DAI("Primary", 0, PRIMARY_TDM_RX_0
),
1014 Q6AFE_TDM_PB_DAI("Primary", 1, PRIMARY_TDM_RX_1
),
1015 Q6AFE_TDM_PB_DAI("Primary", 2, PRIMARY_TDM_RX_2
),
1016 Q6AFE_TDM_PB_DAI("Primary", 3, PRIMARY_TDM_RX_3
),
1017 Q6AFE_TDM_PB_DAI("Primary", 4, PRIMARY_TDM_RX_4
),
1018 Q6AFE_TDM_PB_DAI("Primary", 5, PRIMARY_TDM_RX_5
),
1019 Q6AFE_TDM_PB_DAI("Primary", 6, PRIMARY_TDM_RX_6
),
1020 Q6AFE_TDM_PB_DAI("Primary", 7, PRIMARY_TDM_RX_7
),
1021 Q6AFE_TDM_CAP_DAI("Primary", 0, PRIMARY_TDM_TX_0
),
1022 Q6AFE_TDM_CAP_DAI("Primary", 1, PRIMARY_TDM_TX_1
),
1023 Q6AFE_TDM_CAP_DAI("Primary", 2, PRIMARY_TDM_TX_2
),
1024 Q6AFE_TDM_CAP_DAI("Primary", 3, PRIMARY_TDM_TX_3
),
1025 Q6AFE_TDM_CAP_DAI("Primary", 4, PRIMARY_TDM_TX_4
),
1026 Q6AFE_TDM_CAP_DAI("Primary", 5, PRIMARY_TDM_TX_5
),
1027 Q6AFE_TDM_CAP_DAI("Primary", 6, PRIMARY_TDM_TX_6
),
1028 Q6AFE_TDM_CAP_DAI("Primary", 7, PRIMARY_TDM_TX_7
),
1029 Q6AFE_TDM_PB_DAI("Secondary", 0, SECONDARY_TDM_RX_0
),
1030 Q6AFE_TDM_PB_DAI("Secondary", 1, SECONDARY_TDM_RX_1
),
1031 Q6AFE_TDM_PB_DAI("Secondary", 2, SECONDARY_TDM_RX_2
),
1032 Q6AFE_TDM_PB_DAI("Secondary", 3, SECONDARY_TDM_RX_3
),
1033 Q6AFE_TDM_PB_DAI("Secondary", 4, SECONDARY_TDM_RX_4
),
1034 Q6AFE_TDM_PB_DAI("Secondary", 5, SECONDARY_TDM_RX_5
),
1035 Q6AFE_TDM_PB_DAI("Secondary", 6, SECONDARY_TDM_RX_6
),
1036 Q6AFE_TDM_PB_DAI("Secondary", 7, SECONDARY_TDM_RX_7
),
1037 Q6AFE_TDM_CAP_DAI("Secondary", 0, SECONDARY_TDM_TX_0
),
1038 Q6AFE_TDM_CAP_DAI("Secondary", 1, SECONDARY_TDM_TX_1
),
1039 Q6AFE_TDM_CAP_DAI("Secondary", 2, SECONDARY_TDM_TX_2
),
1040 Q6AFE_TDM_CAP_DAI("Secondary", 3, SECONDARY_TDM_TX_3
),
1041 Q6AFE_TDM_CAP_DAI("Secondary", 4, SECONDARY_TDM_TX_4
),
1042 Q6AFE_TDM_CAP_DAI("Secondary", 5, SECONDARY_TDM_TX_5
),
1043 Q6AFE_TDM_CAP_DAI("Secondary", 6, SECONDARY_TDM_TX_6
),
1044 Q6AFE_TDM_CAP_DAI("Secondary", 7, SECONDARY_TDM_TX_7
),
1045 Q6AFE_TDM_PB_DAI("Tertiary", 0, TERTIARY_TDM_RX_0
),
1046 Q6AFE_TDM_PB_DAI("Tertiary", 1, TERTIARY_TDM_RX_1
),
1047 Q6AFE_TDM_PB_DAI("Tertiary", 2, TERTIARY_TDM_RX_2
),
1048 Q6AFE_TDM_PB_DAI("Tertiary", 3, TERTIARY_TDM_RX_3
),
1049 Q6AFE_TDM_PB_DAI("Tertiary", 4, TERTIARY_TDM_RX_4
),
1050 Q6AFE_TDM_PB_DAI("Tertiary", 5, TERTIARY_TDM_RX_5
),
1051 Q6AFE_TDM_PB_DAI("Tertiary", 6, TERTIARY_TDM_RX_6
),
1052 Q6AFE_TDM_PB_DAI("Tertiary", 7, TERTIARY_TDM_RX_7
),
1053 Q6AFE_TDM_CAP_DAI("Tertiary", 0, TERTIARY_TDM_TX_0
),
1054 Q6AFE_TDM_CAP_DAI("Tertiary", 1, TERTIARY_TDM_TX_1
),
1055 Q6AFE_TDM_CAP_DAI("Tertiary", 2, TERTIARY_TDM_TX_2
),
1056 Q6AFE_TDM_CAP_DAI("Tertiary", 3, TERTIARY_TDM_TX_3
),
1057 Q6AFE_TDM_CAP_DAI("Tertiary", 4, TERTIARY_TDM_TX_4
),
1058 Q6AFE_TDM_CAP_DAI("Tertiary", 5, TERTIARY_TDM_TX_5
),
1059 Q6AFE_TDM_CAP_DAI("Tertiary", 6, TERTIARY_TDM_TX_6
),
1060 Q6AFE_TDM_CAP_DAI("Tertiary", 7, TERTIARY_TDM_TX_7
),
1061 Q6AFE_TDM_PB_DAI("Quaternary", 0, QUATERNARY_TDM_RX_0
),
1062 Q6AFE_TDM_PB_DAI("Quaternary", 1, QUATERNARY_TDM_RX_1
),
1063 Q6AFE_TDM_PB_DAI("Quaternary", 2, QUATERNARY_TDM_RX_2
),
1064 Q6AFE_TDM_PB_DAI("Quaternary", 3, QUATERNARY_TDM_RX_3
),
1065 Q6AFE_TDM_PB_DAI("Quaternary", 4, QUATERNARY_TDM_RX_4
),
1066 Q6AFE_TDM_PB_DAI("Quaternary", 5, QUATERNARY_TDM_RX_5
),
1067 Q6AFE_TDM_PB_DAI("Quaternary", 6, QUATERNARY_TDM_RX_6
),
1068 Q6AFE_TDM_PB_DAI("Quaternary", 7, QUATERNARY_TDM_RX_7
),
1069 Q6AFE_TDM_CAP_DAI("Quaternary", 0, QUATERNARY_TDM_TX_0
),
1070 Q6AFE_TDM_CAP_DAI("Quaternary", 1, QUATERNARY_TDM_TX_1
),
1071 Q6AFE_TDM_CAP_DAI("Quaternary", 2, QUATERNARY_TDM_TX_2
),
1072 Q6AFE_TDM_CAP_DAI("Quaternary", 3, QUATERNARY_TDM_TX_3
),
1073 Q6AFE_TDM_CAP_DAI("Quaternary", 4, QUATERNARY_TDM_TX_4
),
1074 Q6AFE_TDM_CAP_DAI("Quaternary", 5, QUATERNARY_TDM_TX_5
),
1075 Q6AFE_TDM_CAP_DAI("Quaternary", 6, QUATERNARY_TDM_TX_6
),
1076 Q6AFE_TDM_CAP_DAI("Quaternary", 7, QUATERNARY_TDM_TX_7
),
1077 Q6AFE_TDM_PB_DAI("Quinary", 0, QUINARY_TDM_RX_0
),
1078 Q6AFE_TDM_PB_DAI("Quinary", 1, QUINARY_TDM_RX_1
),
1079 Q6AFE_TDM_PB_DAI("Quinary", 2, QUINARY_TDM_RX_2
),
1080 Q6AFE_TDM_PB_DAI("Quinary", 3, QUINARY_TDM_RX_3
),
1081 Q6AFE_TDM_PB_DAI("Quinary", 4, QUINARY_TDM_RX_4
),
1082 Q6AFE_TDM_PB_DAI("Quinary", 5, QUINARY_TDM_RX_5
),
1083 Q6AFE_TDM_PB_DAI("Quinary", 6, QUINARY_TDM_RX_6
),
1084 Q6AFE_TDM_PB_DAI("Quinary", 7, QUINARY_TDM_RX_7
),
1085 Q6AFE_TDM_CAP_DAI("Quinary", 0, QUINARY_TDM_TX_0
),
1086 Q6AFE_TDM_CAP_DAI("Quinary", 1, QUINARY_TDM_TX_1
),
1087 Q6AFE_TDM_CAP_DAI("Quinary", 2, QUINARY_TDM_TX_2
),
1088 Q6AFE_TDM_CAP_DAI("Quinary", 3, QUINARY_TDM_TX_3
),
1089 Q6AFE_TDM_CAP_DAI("Quinary", 4, QUINARY_TDM_TX_4
),
1090 Q6AFE_TDM_CAP_DAI("Quinary", 5, QUINARY_TDM_TX_5
),
1091 Q6AFE_TDM_CAP_DAI("Quinary", 6, QUINARY_TDM_TX_6
),
1092 Q6AFE_TDM_CAP_DAI("Quinary", 7, QUINARY_TDM_TX_7
),
1095 static int q6afe_of_xlate_dai_name(struct snd_soc_component
*component
,
1096 struct of_phandle_args
*args
,
1097 const char **dai_name
)
1099 int id
= args
->args
[0];
1103 for (i
= 0; i
< ARRAY_SIZE(q6afe_dais
); i
++) {
1104 if (q6afe_dais
[i
].id
== id
) {
1105 *dai_name
= q6afe_dais
[i
].name
;
1114 static const struct snd_soc_dapm_widget q6afe_dai_widgets
[] = {
1115 SND_SOC_DAPM_AIF_OUT("HDMI_RX", "HDMI Playback", 0, 0, 0, 0),
1116 SND_SOC_DAPM_AIF_OUT("SLIMBUS_0_RX", "Slimbus Playback", 0, 0, 0, 0),
1117 SND_SOC_DAPM_AIF_OUT("SLIMBUS_1_RX", "Slimbus1 Playback", 0, 0, 0, 0),
1118 SND_SOC_DAPM_AIF_OUT("SLIMBUS_2_RX", "Slimbus2 Playback", 0, 0, 0, 0),
1119 SND_SOC_DAPM_AIF_OUT("SLIMBUS_3_RX", "Slimbus3 Playback", 0, 0, 0, 0),
1120 SND_SOC_DAPM_AIF_OUT("SLIMBUS_4_RX", "Slimbus4 Playback", 0, 0, 0, 0),
1121 SND_SOC_DAPM_AIF_OUT("SLIMBUS_5_RX", "Slimbus5 Playback", 0, 0, 0, 0),
1122 SND_SOC_DAPM_AIF_OUT("SLIMBUS_6_RX", "Slimbus6 Playback", 0, 0, 0, 0),
1123 SND_SOC_DAPM_AIF_IN("SLIMBUS_0_TX", "Slimbus Capture", 0, 0, 0, 0),
1124 SND_SOC_DAPM_AIF_IN("SLIMBUS_1_TX", "Slimbus1 Capture", 0, 0, 0, 0),
1125 SND_SOC_DAPM_AIF_IN("SLIMBUS_2_TX", "Slimbus2 Capture", 0, 0, 0, 0),
1126 SND_SOC_DAPM_AIF_IN("SLIMBUS_3_TX", "Slimbus3 Capture", 0, 0, 0, 0),
1127 SND_SOC_DAPM_AIF_IN("SLIMBUS_4_TX", "Slimbus4 Capture", 0, 0, 0, 0),
1128 SND_SOC_DAPM_AIF_IN("SLIMBUS_5_TX", "Slimbus5 Capture", 0, 0, 0, 0),
1129 SND_SOC_DAPM_AIF_IN("SLIMBUS_6_TX", "Slimbus6 Capture", 0, 0, 0, 0),
1130 SND_SOC_DAPM_AIF_OUT("QUAT_MI2S_RX", "Quaternary MI2S Playback",
1132 SND_SOC_DAPM_AIF_IN("QUAT_MI2S_TX", "Quaternary MI2S Capture",
1134 SND_SOC_DAPM_AIF_OUT("TERT_MI2S_RX", "Tertiary MI2S Playback",
1136 SND_SOC_DAPM_AIF_IN("TERT_MI2S_TX", "Tertiary MI2S Capture",
1138 SND_SOC_DAPM_AIF_OUT("SEC_MI2S_RX", "Secondary MI2S Playback",
1140 SND_SOC_DAPM_AIF_IN("SEC_MI2S_TX", "Secondary MI2S Capture",
1142 SND_SOC_DAPM_AIF_OUT("SEC_MI2S_RX_SD1",
1143 "Secondary MI2S Playback SD1",
1145 SND_SOC_DAPM_AIF_OUT("PRI_MI2S_RX", "Primary MI2S Playback",
1147 SND_SOC_DAPM_AIF_IN("PRI_MI2S_TX", "Primary MI2S Capture",
1150 SND_SOC_DAPM_AIF_OUT("PRIMARY_TDM_RX_0", "Primary TDM0 Playback",
1152 SND_SOC_DAPM_AIF_OUT("PRIMARY_TDM_RX_1", "Primary TDM1 Playback",
1154 SND_SOC_DAPM_AIF_OUT("PRIMARY_TDM_RX_2", "Primary TDM2 Playback",
1156 SND_SOC_DAPM_AIF_OUT("PRIMARY_TDM_RX_3", "Primary TDM3 Playback",
1158 SND_SOC_DAPM_AIF_OUT("PRIMARY_TDM_RX_4", "Primary TDM4 Playback",
1160 SND_SOC_DAPM_AIF_OUT("PRIMARY_TDM_RX_5", "Primary TDM5 Playback",
1162 SND_SOC_DAPM_AIF_OUT("PRIMARY_TDM_RX_6", "Primary TDM6 Playback",
1164 SND_SOC_DAPM_AIF_OUT("PRIMARY_TDM_RX_7", "Primary TDM7 Playback",
1166 SND_SOC_DAPM_AIF_IN("PRIMARY_TDM_TX_0", "Primary TDM0 Capture",
1168 SND_SOC_DAPM_AIF_IN("PRIMARY_TDM_TX_1", "Primary TDM1 Capture",
1170 SND_SOC_DAPM_AIF_IN("PRIMARY_TDM_TX_2", "Primary TDM2 Capture",
1172 SND_SOC_DAPM_AIF_IN("PRIMARY_TDM_TX_3", "Primary TDM3 Capture",
1174 SND_SOC_DAPM_AIF_IN("PRIMARY_TDM_TX_4", "Primary TDM4 Capture",
1176 SND_SOC_DAPM_AIF_IN("PRIMARY_TDM_TX_5", "Primary TDM5 Capture",
1178 SND_SOC_DAPM_AIF_IN("PRIMARY_TDM_TX_6", "Primary TDM6 Capture",
1180 SND_SOC_DAPM_AIF_IN("PRIMARY_TDM_TX_7", "Primary TDM7 Capture",
1183 SND_SOC_DAPM_AIF_OUT("SEC_TDM_RX_0", "Secondary TDM0 Playback",
1185 SND_SOC_DAPM_AIF_OUT("SEC_TDM_RX_1", "Secondary TDM1 Playback",
1187 SND_SOC_DAPM_AIF_OUT("SEC_TDM_RX_2", "Secondary TDM2 Playback",
1189 SND_SOC_DAPM_AIF_OUT("SEC_TDM_RX_3", "Secondary TDM3 Playback",
1191 SND_SOC_DAPM_AIF_OUT("SEC_TDM_RX_4", "Secondary TDM4 Playback",
1193 SND_SOC_DAPM_AIF_OUT("SEC_TDM_RX_5", "Secondary TDM5 Playback",
1195 SND_SOC_DAPM_AIF_OUT("SEC_TDM_RX_6", "Secondary TDM6 Playback",
1197 SND_SOC_DAPM_AIF_OUT("SEC_TDM_RX_7", "Secondary TDM7 Playback",
1199 SND_SOC_DAPM_AIF_IN("SEC_TDM_TX_0", "Secondary TDM0 Capture",
1201 SND_SOC_DAPM_AIF_IN("SEC_TDM_TX_1", "Secondary TDM1 Capture",
1203 SND_SOC_DAPM_AIF_IN("SEC_TDM_TX_2", "Secondary TDM2 Capture",
1205 SND_SOC_DAPM_AIF_IN("SEC_TDM_TX_3", "Secondary TDM3 Capture",
1207 SND_SOC_DAPM_AIF_IN("SEC_TDM_TX_4", "Secondary TDM4 Capture",
1209 SND_SOC_DAPM_AIF_IN("SEC_TDM_TX_5", "Secondary TDM5 Capture",
1211 SND_SOC_DAPM_AIF_IN("SEC_TDM_TX_6", "Secondary TDM6 Capture",
1213 SND_SOC_DAPM_AIF_IN("SEC_TDM_TX_7", "Secondary TDM7 Capture",
1216 SND_SOC_DAPM_AIF_OUT("TERT_TDM_RX_0", "Tertiary TDM0 Playback",
1218 SND_SOC_DAPM_AIF_OUT("TERT_TDM_RX_1", "Tertiary TDM1 Playback",
1220 SND_SOC_DAPM_AIF_OUT("TERT_TDM_RX_2", "Tertiary TDM2 Playback",
1222 SND_SOC_DAPM_AIF_OUT("TERT_TDM_RX_3", "Tertiary TDM3 Playback",
1224 SND_SOC_DAPM_AIF_OUT("TERT_TDM_RX_4", "Tertiary TDM4 Playback",
1226 SND_SOC_DAPM_AIF_OUT("TERT_TDM_RX_5", "Tertiary TDM5 Playback",
1228 SND_SOC_DAPM_AIF_OUT("TERT_TDM_RX_6", "Tertiary TDM6 Playback",
1230 SND_SOC_DAPM_AIF_OUT("TERT_TDM_RX_7", "Tertiary TDM7 Playback",
1232 SND_SOC_DAPM_AIF_IN("TERT_TDM_TX_0", "Tertiary TDM0 Capture",
1234 SND_SOC_DAPM_AIF_IN("TERT_TDM_TX_1", "Tertiary TDM1 Capture",
1236 SND_SOC_DAPM_AIF_IN("TERT_TDM_TX_2", "Tertiary TDM2 Capture",
1238 SND_SOC_DAPM_AIF_IN("TERT_TDM_TX_3", "Tertiary TDM3 Capture",
1240 SND_SOC_DAPM_AIF_IN("TERT_TDM_TX_4", "Tertiary TDM4 Capture",
1242 SND_SOC_DAPM_AIF_IN("TERT_TDM_TX_5", "Tertiary TDM5 Capture",
1244 SND_SOC_DAPM_AIF_IN("TERT_TDM_TX_6", "Tertiary TDM6 Capture",
1246 SND_SOC_DAPM_AIF_IN("TERT_TDM_TX_7", "Tertiary TDM7 Capture",
1249 SND_SOC_DAPM_AIF_OUT("QUAT_TDM_RX_0", "Quaternary TDM0 Playback",
1251 SND_SOC_DAPM_AIF_OUT("QUAT_TDM_RX_1", "Quaternary TDM1 Playback",
1253 SND_SOC_DAPM_AIF_OUT("QUAT_TDM_RX_2", "Quaternary TDM2 Playback",
1255 SND_SOC_DAPM_AIF_OUT("QUAT_TDM_RX_3", "Quaternary TDM3 Playback",
1257 SND_SOC_DAPM_AIF_OUT("QUAT_TDM_RX_4", "Quaternary TDM4 Playback",
1259 SND_SOC_DAPM_AIF_OUT("QUAT_TDM_RX_5", "Quaternary TDM5 Playback",
1261 SND_SOC_DAPM_AIF_OUT("QUAT_TDM_RX_6", "Quaternary TDM6 Playback",
1263 SND_SOC_DAPM_AIF_OUT("QUAT_TDM_RX_7", "Quaternary TDM7 Playback",
1265 SND_SOC_DAPM_AIF_IN("QUAT_TDM_TX_0", "Quaternary TDM0 Capture",
1267 SND_SOC_DAPM_AIF_IN("QUAT_TDM_TX_1", "Quaternary TDM1 Capture",
1269 SND_SOC_DAPM_AIF_IN("QUAT_TDM_TX_2", "Quaternary TDM2 Capture",
1271 SND_SOC_DAPM_AIF_IN("QUAT_TDM_TX_3", "Quaternary TDM3 Capture",
1273 SND_SOC_DAPM_AIF_IN("QUAT_TDM_TX_4", "Quaternary TDM4 Capture",
1275 SND_SOC_DAPM_AIF_IN("QUAT_TDM_TX_5", "Quaternary TDM5 Capture",
1277 SND_SOC_DAPM_AIF_IN("QUAT_TDM_TX_6", "Quaternary TDM6 Capture",
1279 SND_SOC_DAPM_AIF_IN("QUAT_TDM_TX_7", "Quaternary TDM7 Capture",
1282 SND_SOC_DAPM_AIF_OUT("QUIN_TDM_RX_0", "Quinary TDM0 Playback",
1284 SND_SOC_DAPM_AIF_OUT("QUIN_TDM_RX_1", "Quinary TDM1 Playback",
1286 SND_SOC_DAPM_AIF_OUT("QUIN_TDM_RX_2", "Quinary TDM2 Playback",
1288 SND_SOC_DAPM_AIF_OUT("QUIN_TDM_RX_3", "Quinary TDM3 Playback",
1290 SND_SOC_DAPM_AIF_OUT("QUIN_TDM_RX_4", "Quinary TDM4 Playback",
1292 SND_SOC_DAPM_AIF_OUT("QUIN_TDM_RX_5", "Quinary TDM5 Playback",
1294 SND_SOC_DAPM_AIF_OUT("QUIN_TDM_RX_6", "Quinary TDM6 Playback",
1296 SND_SOC_DAPM_AIF_OUT("QUIN_TDM_RX_7", "Quinary TDM7 Playback",
1298 SND_SOC_DAPM_AIF_IN("QUIN_TDM_TX_0", "Quinary TDM0 Capture",
1300 SND_SOC_DAPM_AIF_IN("QUIN_TDM_TX_1", "Quinary TDM1 Capture",
1302 SND_SOC_DAPM_AIF_IN("QUIN_TDM_TX_2", "Quinary TDM2 Capture",
1304 SND_SOC_DAPM_AIF_IN("QUIN_TDM_TX_3", "Quinary TDM3 Capture",
1306 SND_SOC_DAPM_AIF_IN("QUIN_TDM_TX_4", "Quinary TDM4 Capture",
1308 SND_SOC_DAPM_AIF_IN("QUIN_TDM_TX_5", "Quinary TDM5 Capture",
1310 SND_SOC_DAPM_AIF_IN("QUIN_TDM_TX_6", "Quinary TDM6 Capture",
1312 SND_SOC_DAPM_AIF_IN("QUIN_TDM_TX_7", "Quinary TDM7 Capture",
1316 static const struct snd_soc_component_driver q6afe_dai_component
= {
1317 .name
= "q6afe-dai-component",
1318 .dapm_widgets
= q6afe_dai_widgets
,
1319 .num_dapm_widgets
= ARRAY_SIZE(q6afe_dai_widgets
),
1320 .dapm_routes
= q6afe_dapm_routes
,
1321 .num_dapm_routes
= ARRAY_SIZE(q6afe_dapm_routes
),
1322 .of_xlate_dai_name
= q6afe_of_xlate_dai_name
,
1326 static void of_q6afe_parse_dai_data(struct device
*dev
,
1327 struct q6afe_dai_data
*data
)
1329 struct device_node
*node
;
1332 for_each_child_of_node(dev
->of_node
, node
) {
1333 unsigned int lines
[Q6AFE_MAX_MI2S_LINES
];
1334 struct q6afe_dai_priv_data
*priv
;
1335 int id
, i
, num_lines
;
1337 ret
= of_property_read_u32(node
, "reg", &id
);
1338 if (ret
|| id
< 0 || id
>= AFE_PORT_MAX
) {
1339 dev_err(dev
, "valid dai id not found:%d\n", ret
);
1344 /* MI2S specific properties */
1345 case PRIMARY_MI2S_RX
... QUATERNARY_MI2S_TX
:
1346 priv
= &data
->priv
[id
];
1347 ret
= of_property_read_variable_u32_array(node
,
1350 Q6AFE_MAX_MI2S_LINES
);
1356 priv
->sd_line_mask
= 0;
1358 for (i
= 0; i
< num_lines
; i
++)
1359 priv
->sd_line_mask
|= BIT(lines
[i
]);
1362 case PRIMARY_TDM_RX_0
... QUINARY_TDM_TX_7
:
1363 priv
= &data
->priv
[id
];
1364 ret
= of_property_read_u32(node
, "qcom,tdm-sync-mode",
1367 dev_err(dev
, "No Sync mode from DT\n");
1370 ret
= of_property_read_u32(node
, "qcom,tdm-sync-src",
1373 dev_err(dev
, "No Sync Src from DT\n");
1376 ret
= of_property_read_u32(node
, "qcom,tdm-data-out",
1377 &priv
->data_out_enable
);
1379 dev_err(dev
, "No Data out enable from DT\n");
1382 ret
= of_property_read_u32(node
, "qcom,tdm-invert-sync",
1383 &priv
->invert_sync
);
1385 dev_err(dev
, "No Invert sync from DT\n");
1388 ret
= of_property_read_u32(node
, "qcom,tdm-data-delay",
1391 dev_err(dev
, "No Data Delay from DT\n");
1394 ret
= of_property_read_u32(node
, "qcom,tdm-data-align",
1397 dev_err(dev
, "No Data align from DT\n");
1407 static int q6afe_dai_dev_probe(struct platform_device
*pdev
)
1409 struct q6afe_dai_data
*dai_data
;
1410 struct device
*dev
= &pdev
->dev
;
1412 dai_data
= devm_kzalloc(dev
, sizeof(*dai_data
), GFP_KERNEL
);
1416 dev_set_drvdata(dev
, dai_data
);
1418 of_q6afe_parse_dai_data(dev
, dai_data
);
1420 return devm_snd_soc_register_component(dev
, &q6afe_dai_component
,
1421 q6afe_dais
, ARRAY_SIZE(q6afe_dais
));
1424 static const struct of_device_id q6afe_dai_device_id
[] = {
1425 { .compatible
= "qcom,q6afe-dais" },
1428 MODULE_DEVICE_TABLE(of
, q6afe_dai_device_id
);
1430 static struct platform_driver q6afe_dai_platform_driver
= {
1432 .name
= "q6afe-dai",
1433 .of_match_table
= of_match_ptr(q6afe_dai_device_id
),
1435 .probe
= q6afe_dai_dev_probe
,
1437 module_platform_driver(q6afe_dai_platform_driver
);
1439 MODULE_DESCRIPTION("Q6 Audio Fronend dai driver");
1440 MODULE_LICENSE("GPL v2");