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
q6slim_hw_params(struct snd_pcm_substream * substream,struct snd_pcm_hw_params * params,struct snd_soc_dai * dai)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
q6hdmi_hw_params(struct snd_pcm_substream * substream,struct snd_pcm_hw_params * params,struct snd_soc_dai * dai)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
q6afe_usb_hw_params(struct snd_pcm_substream * substream,struct snd_pcm_hw_params * params,struct snd_soc_dai * dai)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
q6i2s_hw_params(struct snd_pcm_substream * substream,struct snd_pcm_hw_params * params,struct snd_soc_dai * dai)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
q6i2s_set_fmt(struct snd_soc_dai * dai,unsigned int fmt)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
q6tdm_set_tdm_slot(struct snd_soc_dai * dai,unsigned int tx_mask,unsigned int rx_mask,int slots,int slot_width)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
q6tdm_set_channel_map(struct snd_soc_dai * dai,unsigned int tx_num,const unsigned int * tx_slot,unsigned int rx_num,const unsigned int * rx_slot)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
q6tdm_hw_params(struct snd_pcm_substream * substream,struct snd_pcm_hw_params * params,struct snd_soc_dai * dai)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
q6dma_set_channel_map(struct snd_soc_dai * dai,unsigned int tx_num,const unsigned int * tx_ch_mask,unsigned int rx_num,const unsigned int * rx_ch_mask)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
q6dma_hw_params(struct snd_pcm_substream * substream,struct snd_pcm_hw_params * params,struct snd_soc_dai * dai)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 }
q6afe_dai_shutdown(struct snd_pcm_substream * substream,struct snd_soc_dai * dai)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
q6afe_dai_prepare(struct snd_pcm_substream * substream,struct snd_soc_dai * dai)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
q6slim_set_channel_map(struct snd_soc_dai * dai,unsigned int tx_num,const unsigned int * tx_slot,unsigned int rx_num,const unsigned int * rx_slot)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
q6afe_mi2s_set_sysclk(struct snd_soc_dai * dai,int clk_id,unsigned int freq,int dir)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
msm_dai_q6_dai_probe(struct snd_soc_dai * dai)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
msm_dai_q6_dai_remove(struct snd_soc_dai * dai)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
of_q6afe_parse_dai_data(struct device * dev,struct q6afe_dai_data * data)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
q6afe_dai_dev_probe(struct platform_device * pdev)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