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