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