~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/sound/soc/qcom/qdsp6/q6afe-dai.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

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

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php