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

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

Version: ~ [ linux-5.7-rc7 ] ~ [ linux-5.6.14 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.42 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.124 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.181 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.224 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.224 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.140 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.84 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ 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.5 ] ~ [ 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 <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 "q6afe.h"
 15 
 16 #define Q6AFE_TDM_PB_DAI(pre, num, did) {                               \
 17                 .playback = {                                           \
 18                         .stream_name = pre" TDM"#num" Playback",        \
 19                         .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |\
 20                                 SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 |\
 21                                 SNDRV_PCM_RATE_176400,                  \
 22                         .formats = SNDRV_PCM_FMTBIT_S16_LE |            \
 23                                    SNDRV_PCM_FMTBIT_S24_LE |            \
 24                                    SNDRV_PCM_FMTBIT_S32_LE,             \
 25                         .channels_min = 1,                              \
 26                         .channels_max = 8,                              \
 27                         .rate_min = 8000,                               \
 28                         .rate_max = 176400,                             \
 29                 },                                                      \
 30                 .name = #did,                                           \
 31                 .ops = &q6tdm_ops,                                      \
 32                 .id = did,                                              \
 33                 .probe = msm_dai_q6_dai_probe,                          \
 34                 .remove = msm_dai_q6_dai_remove,                        \
 35         }
 36 
 37 #define Q6AFE_TDM_CAP_DAI(pre, num, did) {                              \
 38                 .capture = {                                            \
 39                         .stream_name = pre" TDM"#num" Capture",         \
 40                         .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |\
 41                                 SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 |\
 42                                 SNDRV_PCM_RATE_176400,                  \
 43                         .formats = SNDRV_PCM_FMTBIT_S16_LE |            \
 44                                    SNDRV_PCM_FMTBIT_S24_LE |            \
 45                                    SNDRV_PCM_FMTBIT_S32_LE,             \
 46                         .channels_min = 1,                              \
 47                         .channels_max = 8,                              \
 48                         .rate_min = 8000,                               \
 49                         .rate_max = 176400,                             \
 50                 },                                                      \
 51                 .name = #did,                                           \
 52                 .ops = &q6tdm_ops,                                      \
 53                 .id = did,                                              \
 54                 .probe = msm_dai_q6_dai_probe,                          \
 55                 .remove = msm_dai_q6_dai_remove,                        \
 56         }
 57 
 58 struct q6afe_dai_priv_data {
 59         uint32_t sd_line_mask;
 60         uint32_t sync_mode;
 61         uint32_t sync_src;
 62         uint32_t data_out_enable;
 63         uint32_t invert_sync;
 64         uint32_t data_delay;
 65         uint32_t data_align;
 66 };
 67 
 68 struct q6afe_dai_data {
 69         struct q6afe_port *port[AFE_PORT_MAX];
 70         struct q6afe_port_config port_config[AFE_PORT_MAX];
 71         bool is_port_started[AFE_PORT_MAX];
 72         struct q6afe_dai_priv_data priv[AFE_PORT_MAX];
 73 };
 74 
 75 static int q6slim_hw_params(struct snd_pcm_substream *substream,
 76                             struct snd_pcm_hw_params *params,
 77                             struct snd_soc_dai *dai)
 78 {
 79 
 80         struct q6afe_dai_data *dai_data = dev_get_drvdata(dai->dev);
 81         struct q6afe_slim_cfg *slim = &dai_data->port_config[dai->id].slim;
 82 
 83         slim->sample_rate = params_rate(params);
 84 
 85         switch (params_format(params)) {
 86         case SNDRV_PCM_FORMAT_S16_LE:
 87         case SNDRV_PCM_FORMAT_SPECIAL:
 88                 slim->bit_width = 16;
 89                 break;
 90         case SNDRV_PCM_FORMAT_S24_LE:
 91                 slim->bit_width = 24;
 92                 break;
 93         case SNDRV_PCM_FORMAT_S32_LE:
 94                 slim->bit_width = 32;
 95                 break;
 96         default:
 97                 pr_err("%s: format %d\n",
 98                         __func__, params_format(params));
 99                 return -EINVAL;
100         }
101 
102         return 0;
103 }
104 
105 static int q6hdmi_hw_params(struct snd_pcm_substream *substream,
106                                 struct snd_pcm_hw_params *params,
107                                 struct snd_soc_dai *dai)
108 {
109         struct q6afe_dai_data *dai_data = dev_get_drvdata(dai->dev);
110         int channels = params_channels(params);
111         struct q6afe_hdmi_cfg *hdmi = &dai_data->port_config[dai->id].hdmi;
112 
113         hdmi->sample_rate = params_rate(params);
114         switch (params_format(params)) {
115         case SNDRV_PCM_FORMAT_S16_LE:
116                 hdmi->bit_width = 16;
117                 break;
118         case SNDRV_PCM_FORMAT_S24_LE:
119                 hdmi->bit_width = 24;
120                 break;
121         }
122 
123         /* HDMI spec CEA-861-E: Table 28 Audio InfoFrame Data Byte 4 */
124         switch (channels) {
125         case 2:
126                 hdmi->channel_allocation = 0;
127                 break;
128         case 3:
129                 hdmi->channel_allocation = 0x02;
130                 break;
131         case 4:
132                 hdmi->channel_allocation = 0x06;
133                 break;
134         case 5:
135                 hdmi->channel_allocation = 0x0A;
136                 break;
137         case 6:
138                 hdmi->channel_allocation = 0x0B;
139                 break;
140         case 7:
141                 hdmi->channel_allocation = 0x12;
142                 break;
143         case 8:
144                 hdmi->channel_allocation = 0x13;
145                 break;
146         default:
147                 dev_err(dai->dev, "invalid Channels = %u\n", channels);
148                 return -EINVAL;
149         }
150 
151         return 0;
152 }
153 
154 static int q6i2s_hw_params(struct snd_pcm_substream *substream,
155                            struct snd_pcm_hw_params *params,
156                            struct snd_soc_dai *dai)
157 {
158         struct q6afe_dai_data *dai_data = dev_get_drvdata(dai->dev);
159         struct q6afe_i2s_cfg *i2s = &dai_data->port_config[dai->id].i2s_cfg;
160 
161         i2s->sample_rate = params_rate(params);
162         i2s->bit_width = params_width(params);
163         i2s->num_channels = params_channels(params);
164         i2s->sd_line_mask = dai_data->priv[dai->id].sd_line_mask;
165 
166         return 0;
167 }
168 
169 static int q6i2s_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
170 {
171         struct q6afe_dai_data *dai_data = dev_get_drvdata(dai->dev);
172         struct q6afe_i2s_cfg *i2s = &dai_data->port_config[dai->id].i2s_cfg;
173 
174         i2s->fmt = fmt;
175 
176         return 0;
177 }
178 
179 static int q6tdm_set_tdm_slot(struct snd_soc_dai *dai,
180                                 unsigned int tx_mask,
181                                 unsigned int rx_mask,
182                                 int slots, int slot_width)
183 {
184 
185         struct q6afe_dai_data *dai_data = dev_get_drvdata(dai->dev);
186         struct q6afe_tdm_cfg *tdm = &dai_data->port_config[dai->id].tdm;
187         unsigned int cap_mask;
188         int rc = 0;
189 
190         /* HW only supports 16 and 32 bit slot width configuration */
191         if ((slot_width != 16) && (slot_width != 32)) {
192                 dev_err(dai->dev, "%s: invalid slot_width %d\n",
193                         __func__, slot_width);
194                 return -EINVAL;
195         }
196 
197         /* HW supports 1-32 slots configuration. Typical: 1, 2, 4, 8, 16, 32 */
198         switch (slots) {
199         case 2:
200                 cap_mask = 0x03;
201                 break;
202         case 4:
203                 cap_mask = 0x0F;
204                 break;
205         case 8:
206                 cap_mask = 0xFF;
207                 break;
208         case 16:
209                 cap_mask = 0xFFFF;
210                 break;
211         default:
212                 dev_err(dai->dev, "%s: invalid slots %d\n",
213                         __func__, slots);
214                 return -EINVAL;
215         }
216 
217         switch (dai->id) {
218         case PRIMARY_TDM_RX_0 ... QUINARY_TDM_TX_7:
219                 tdm->nslots_per_frame = slots;
220                 tdm->slot_width = slot_width;
221                 /* TDM RX dais ids are even and tx are odd */
222                 tdm->slot_mask = (dai->id & 0x1 ? tx_mask : rx_mask) & cap_mask;
223                 break;
224         default:
225                 dev_err(dai->dev, "%s: invalid dai id 0x%x\n",
226                         __func__, dai->id);
227                 return -EINVAL;
228         }
229 
230         return rc;
231 }
232 
233 static int q6tdm_set_channel_map(struct snd_soc_dai *dai,
234                                 unsigned int tx_num, unsigned int *tx_slot,
235                                 unsigned int rx_num, unsigned int *rx_slot)
236 {
237 
238         struct q6afe_dai_data *dai_data = dev_get_drvdata(dai->dev);
239         struct q6afe_tdm_cfg *tdm = &dai_data->port_config[dai->id].tdm;
240         int rc = 0;
241         int i = 0;
242 
243         switch (dai->id) {
244         case PRIMARY_TDM_RX_0 ... QUINARY_TDM_TX_7:
245                 if (dai->id & 0x1) {
246                         if (!tx_slot) {
247                                 dev_err(dai->dev, "tx slot not found\n");
248                                 return -EINVAL;
249                         }
250                         if (tx_num > AFE_PORT_MAX_AUDIO_CHAN_CNT) {
251                                 dev_err(dai->dev, "invalid tx num %d\n",
252                                         tx_num);
253                                 return -EINVAL;
254                         }
255 
256                         for (i = 0; i < tx_num; i++)
257                                 tdm->ch_mapping[i] = tx_slot[i];
258 
259                         for (i = tx_num; i < AFE_PORT_MAX_AUDIO_CHAN_CNT; i++)
260                                 tdm->ch_mapping[i] = Q6AFE_CMAP_INVALID;
261 
262                         tdm->num_channels = tx_num;
263                 } else {
264                         /* rx */
265                         if (!rx_slot) {
266                                 dev_err(dai->dev, "rx slot not found\n");
267                                 return -EINVAL;
268                         }
269                         if (rx_num > AFE_PORT_MAX_AUDIO_CHAN_CNT) {
270                                 dev_err(dai->dev, "invalid rx num %d\n",
271                                         rx_num);
272                                 return -EINVAL;
273                         }
274 
275                         for (i = 0; i < rx_num; i++)
276                                 tdm->ch_mapping[i] = rx_slot[i];
277 
278                         for (i = rx_num; i < AFE_PORT_MAX_AUDIO_CHAN_CNT; i++)
279                                 tdm->ch_mapping[i] = Q6AFE_CMAP_INVALID;
280 
281                         tdm->num_channels = rx_num;
282                 }
283 
284                 break;
285         default:
286                 dev_err(dai->dev, "%s: invalid dai id 0x%x\n",
287                         __func__, dai->id);
288                 return -EINVAL;
289         }
290 
291         return rc;
292 }
293 
294 static int q6tdm_hw_params(struct snd_pcm_substream *substream,
295                            struct snd_pcm_hw_params *params,
296                            struct snd_soc_dai *dai)
297 {
298         struct q6afe_dai_data *dai_data = dev_get_drvdata(dai->dev);
299         struct q6afe_tdm_cfg *tdm = &dai_data->port_config[dai->id].tdm;
300 
301         tdm->bit_width = params_width(params);
302         tdm->sample_rate = params_rate(params);
303         tdm->num_channels = params_channels(params);
304         tdm->data_align_type = dai_data->priv[dai->id].data_align;
305         tdm->sync_src = dai_data->priv[dai->id].sync_src;
306         tdm->sync_mode = dai_data->priv[dai->id].sync_mode;
307 
308         return 0;
309 }
310 static void q6afe_dai_shutdown(struct snd_pcm_substream *substream,
311                                 struct snd_soc_dai *dai)
312 {
313         struct q6afe_dai_data *dai_data = dev_get_drvdata(dai->dev);
314         int rc;
315 
316         if (!dai_data->is_port_started[dai->id])
317                 return;
318 
319         rc = q6afe_port_stop(dai_data->port[dai->id]);
320         if (rc < 0)
321                 dev_err(dai->dev, "fail to close AFE port (%d)\n", rc);
322 
323         dai_data->is_port_started[dai->id] = false;
324 
325 }
326 
327 static int q6afe_dai_prepare(struct snd_pcm_substream *substream,
328                 struct snd_soc_dai *dai)
329 {
330         struct q6afe_dai_data *dai_data = dev_get_drvdata(dai->dev);
331         int rc;
332 
333         if (dai_data->is_port_started[dai->id]) {
334                 /* stop the port and restart with new port config */
335                 rc = q6afe_port_stop(dai_data->port[dai->id]);
336                 if (rc < 0) {
337                         dev_err(dai->dev, "fail to close AFE port (%d)\n", rc);
338                         return rc;
339                 }
340         }
341 
342         switch (dai->id) {
343         case HDMI_RX:
344                 q6afe_hdmi_port_prepare(dai_data->port[dai->id],
345                                         &dai_data->port_config[dai->id].hdmi);
346                 break;
347         case SLIMBUS_0_RX ... SLIMBUS_6_TX:
348                 q6afe_slim_port_prepare(dai_data->port[dai->id],
349                                         &dai_data->port_config[dai->id].slim);
350                 break;
351         case PRIMARY_MI2S_RX ... QUATERNARY_MI2S_TX:
352                 rc = q6afe_i2s_port_prepare(dai_data->port[dai->id],
353                                &dai_data->port_config[dai->id].i2s_cfg);
354                 if (rc < 0) {
355                         dev_err(dai->dev, "fail to prepare AFE port %x\n",
356                                 dai->id);
357                         return rc;
358                 }
359                 break;
360         case PRIMARY_TDM_RX_0 ... QUINARY_TDM_TX_7:
361                 q6afe_tdm_port_prepare(dai_data->port[dai->id],
362                                         &dai_data->port_config[dai->id].tdm);
363                 break;
364         default:
365                 return -EINVAL;
366         }
367 
368         rc = q6afe_port_start(dai_data->port[dai->id]);
369         if (rc < 0) {
370                 dev_err(dai->dev, "fail to start AFE port %x\n", dai->id);
371                 return rc;
372         }
373         dai_data->is_port_started[dai->id] = true;
374 
375         return 0;
376 }
377 
378 static int q6slim_set_channel_map(struct snd_soc_dai *dai,
379                                 unsigned int tx_num, unsigned int *tx_slot,
380                                 unsigned int rx_num, unsigned int *rx_slot)
381 {
382         struct q6afe_dai_data *dai_data = dev_get_drvdata(dai->dev);
383         struct q6afe_port_config *pcfg = &dai_data->port_config[dai->id];
384         int i;
385 
386         if (dai->id & 0x1) {
387                 /* TX */
388                 if (!tx_slot) {
389                         pr_err("%s: tx slot not found\n", __func__);
390                         return -EINVAL;
391                 }
392 
393                 for (i = 0; i < tx_num; i++)
394                         pcfg->slim.ch_mapping[i] = tx_slot[i];
395 
396                 pcfg->slim.num_channels = tx_num;
397 
398 
399         } else {
400                 if (!rx_slot) {
401                         pr_err("%s: rx slot not found\n", __func__);
402                         return -EINVAL;
403                 }
404 
405                 for (i = 0; i < rx_num; i++)
406                         pcfg->slim.ch_mapping[i] =   rx_slot[i];
407 
408                 pcfg->slim.num_channels = rx_num;
409 
410         }
411 
412         return 0;
413 }
414 
415 static int q6afe_mi2s_set_sysclk(struct snd_soc_dai *dai,
416                 int clk_id, unsigned int freq, int dir)
417 {
418         struct q6afe_dai_data *dai_data = dev_get_drvdata(dai->dev);
419         struct q6afe_port *port = dai_data->port[dai->id];
420 
421         switch (clk_id) {
422         case LPAIF_DIG_CLK:
423                 return q6afe_port_set_sysclk(port, clk_id, 0, 5, freq, dir);
424         case LPAIF_BIT_CLK:
425         case LPAIF_OSR_CLK:
426                 return q6afe_port_set_sysclk(port, clk_id,
427                                              Q6AFE_LPASS_CLK_SRC_INTERNAL,
428                                              Q6AFE_LPASS_CLK_ROOT_DEFAULT,
429                                              freq, dir);
430         case Q6AFE_LPASS_CLK_ID_PRI_MI2S_IBIT ... Q6AFE_LPASS_CLK_ID_QUI_MI2S_OSR:
431         case Q6AFE_LPASS_CLK_ID_MCLK_1 ... Q6AFE_LPASS_CLK_ID_INT_MCLK_1:
432                 return q6afe_port_set_sysclk(port, clk_id,
433                                              Q6AFE_LPASS_CLK_ATTRIBUTE_COUPLE_NO,
434                                              Q6AFE_LPASS_CLK_ROOT_DEFAULT,
435                                              freq, dir);
436         case Q6AFE_LPASS_CLK_ID_PRI_TDM_IBIT ... Q6AFE_LPASS_CLK_ID_QUIN_TDM_EBIT:
437                 return q6afe_port_set_sysclk(port, clk_id,
438                                              Q6AFE_LPASS_CLK_ATTRIBUTE_INVERT_COUPLE_NO,
439                                              Q6AFE_LPASS_CLK_ROOT_DEFAULT,
440                                              freq, dir);
441         }
442 
443         return 0;
444 }
445 
446 static const struct snd_soc_dapm_route q6afe_dapm_routes[] = {
447         {"HDMI Playback", NULL, "HDMI_RX"},
448         {"Slimbus1 Playback", NULL, "SLIMBUS_1_RX"},
449         {"Slimbus2 Playback", NULL, "SLIMBUS_2_RX"},
450         {"Slimbus3 Playback", NULL, "SLIMBUS_3_RX"},
451         {"Slimbus4 Playback", NULL, "SLIMBUS_4_RX"},
452         {"Slimbus5 Playback", NULL, "SLIMBUS_5_RX"},
453         {"Slimbus6 Playback", NULL, "SLIMBUS_6_RX"},
454 
455         {"SLIMBUS_0_TX", NULL, "Slimbus Capture"},
456         {"SLIMBUS_1_TX", NULL, "Slimbus1 Capture"},
457         {"SLIMBUS_2_TX", NULL, "Slimbus2 Capture"},
458         {"SLIMBUS_3_TX", NULL, "Slimbus3 Capture"},
459         {"SLIMBUS_4_TX", NULL, "Slimbus4 Capture"},
460         {"SLIMBUS_5_TX", NULL, "Slimbus5 Capture"},
461         {"SLIMBUS_6_TX", NULL, "Slimbus6 Capture"},
462 
463         {"Primary MI2S Playback", NULL, "PRI_MI2S_RX"},
464         {"Secondary MI2S Playback", NULL, "SEC_MI2S_RX"},
465         {"Tertiary MI2S Playback", NULL, "TERT_MI2S_RX"},
466         {"Quaternary MI2S Playback", NULL, "QUAT_MI2S_RX"},
467 
468         {"Primary TDM0 Playback", NULL, "PRIMARY_TDM_RX_0"},
469         {"Primary TDM1 Playback", NULL, "PRIMARY_TDM_RX_1"},
470         {"Primary TDM2 Playback", NULL, "PRIMARY_TDM_RX_2"},
471         {"Primary TDM3 Playback", NULL, "PRIMARY_TDM_RX_3"},
472         {"Primary TDM4 Playback", NULL, "PRIMARY_TDM_RX_4"},
473         {"Primary TDM5 Playback", NULL, "PRIMARY_TDM_RX_5"},
474         {"Primary TDM6 Playback", NULL, "PRIMARY_TDM_RX_6"},
475         {"Primary TDM7 Playback", NULL, "PRIMARY_TDM_RX_7"},
476 
477         {"Secondary TDM0 Playback", NULL, "SEC_TDM_RX_0"},
478         {"Secondary TDM1 Playback", NULL, "SEC_TDM_RX_1"},
479         {"Secondary TDM2 Playback", NULL, "SEC_TDM_RX_2"},
480         {"Secondary TDM3 Playback", NULL, "SEC_TDM_RX_3"},
481         {"Secondary TDM4 Playback", NULL, "SEC_TDM_RX_4"},
482         {"Secondary TDM5 Playback", NULL, "SEC_TDM_RX_5"},
483         {"Secondary TDM6 Playback", NULL, "SEC_TDM_RX_6"},
484         {"Secondary TDM7 Playback", NULL, "SEC_TDM_RX_7"},
485 
486         {"Tertiary TDM0 Playback", NULL, "TERT_TDM_RX_0"},
487         {"Tertiary TDM1 Playback", NULL, "TERT_TDM_RX_1"},
488         {"Tertiary TDM2 Playback", NULL, "TERT_TDM_RX_2"},
489         {"Tertiary TDM3 Playback", NULL, "TERT_TDM_RX_3"},
490         {"Tertiary TDM4 Playback", NULL, "TERT_TDM_RX_4"},
491         {"Tertiary TDM5 Playback", NULL, "TERT_TDM_RX_5"},
492         {"Tertiary TDM6 Playback", NULL, "TERT_TDM_RX_6"},
493         {"Tertiary TDM7 Playback", NULL, "TERT_TDM_RX_7"},
494 
495         {"Quaternary TDM0 Playback", NULL, "QUAT_TDM_RX_0"},
496         {"Quaternary TDM1 Playback", NULL, "QUAT_TDM_RX_1"},
497         {"Quaternary TDM2 Playback", NULL, "QUAT_TDM_RX_2"},
498         {"Quaternary TDM3 Playback", NULL, "QUAT_TDM_RX_3"},
499         {"Quaternary TDM4 Playback", NULL, "QUAT_TDM_RX_4"},
500         {"Quaternary TDM5 Playback", NULL, "QUAT_TDM_RX_5"},
501         {"Quaternary TDM6 Playback", NULL, "QUAT_TDM_RX_6"},
502         {"Quaternary TDM7 Playback", NULL, "QUAT_TDM_RX_7"},
503 
504         {"Quinary TDM0 Playback", NULL, "QUIN_TDM_RX_0"},
505         {"Quinary TDM1 Playback", NULL, "QUIN_TDM_RX_1"},
506         {"Quinary TDM2 Playback", NULL, "QUIN_TDM_RX_2"},
507         {"Quinary TDM3 Playback", NULL, "QUIN_TDM_RX_3"},
508         {"Quinary TDM4 Playback", NULL, "QUIN_TDM_RX_4"},
509         {"Quinary TDM5 Playback", NULL, "QUIN_TDM_RX_5"},
510         {"Quinary TDM6 Playback", NULL, "QUIN_TDM_RX_6"},
511         {"Quinary TDM7 Playback", NULL, "QUIN_TDM_RX_7"},
512 
513         {"PRIMARY_TDM_TX_0", NULL, "Primary TDM0 Capture"},
514         {"PRIMARY_TDM_TX_1", NULL, "Primary TDM1 Capture"},
515         {"PRIMARY_TDM_TX_2", NULL, "Primary TDM2 Capture"},
516         {"PRIMARY_TDM_TX_3", NULL, "Primary TDM3 Capture"},
517         {"PRIMARY_TDM_TX_4", NULL, "Primary TDM4 Capture"},
518         {"PRIMARY_TDM_TX_5", NULL, "Primary TDM5 Capture"},
519         {"PRIMARY_TDM_TX_6", NULL, "Primary TDM6 Capture"},
520         {"PRIMARY_TDM_TX_7", NULL, "Primary TDM7 Capture"},
521 
522         {"SEC_TDM_TX_0", NULL, "Secondary TDM0 Capture"},
523         {"SEC_TDM_TX_1", NULL, "Secondary TDM1 Capture"},
524         {"SEC_TDM_TX_2", NULL, "Secondary TDM2 Capture"},
525         {"SEC_TDM_TX_3", NULL, "Secondary TDM3 Capture"},
526         {"SEC_TDM_TX_4", NULL, "Secondary TDM4 Capture"},
527         {"SEC_TDM_TX_5", NULL, "Secondary TDM5 Capture"},
528         {"SEC_TDM_TX_6", NULL, "Secondary TDM6 Capture"},
529         {"SEC_TDM_TX_7", NULL, "Secondary TDM7 Capture"},
530 
531         {"TERT_TDM_TX_0", NULL, "Tertiary TDM0 Capture"},
532         {"TERT_TDM_TX_1", NULL, "Tertiary TDM1 Capture"},
533         {"TERT_TDM_TX_2", NULL, "Tertiary TDM2 Capture"},
534         {"TERT_TDM_TX_3", NULL, "Tertiary TDM3 Capture"},
535         {"TERT_TDM_TX_4", NULL, "Tertiary TDM4 Capture"},
536         {"TERT_TDM_TX_5", NULL, "Tertiary TDM5 Capture"},
537         {"TERT_TDM_TX_6", NULL, "Tertiary TDM6 Capture"},
538         {"TERT_TDM_TX_7", NULL, "Tertiary TDM7 Capture"},
539 
540         {"QUAT_TDM_TX_0", NULL, "Quaternary TDM0 Capture"},
541         {"QUAT_TDM_TX_1", NULL, "Quaternary TDM1 Capture"},
542         {"QUAT_TDM_TX_2", NULL, "Quaternary TDM2 Capture"},
543         {"QUAT_TDM_TX_3", NULL, "Quaternary TDM3 Capture"},
544         {"QUAT_TDM_TX_4", NULL, "Quaternary TDM4 Capture"},
545         {"QUAT_TDM_TX_5", NULL, "Quaternary TDM5 Capture"},
546         {"QUAT_TDM_TX_6", NULL, "Quaternary TDM6 Capture"},
547         {"QUAT_TDM_TX_7", NULL, "Quaternary TDM7 Capture"},
548 
549         {"QUIN_TDM_TX_0", NULL, "Quinary TDM0 Capture"},
550         {"QUIN_TDM_TX_1", NULL, "Quinary TDM1 Capture"},
551         {"QUIN_TDM_TX_2", NULL, "Quinary TDM2 Capture"},
552         {"QUIN_TDM_TX_3", NULL, "Quinary TDM3 Capture"},
553         {"QUIN_TDM_TX_4", NULL, "Quinary TDM4 Capture"},
554         {"QUIN_TDM_TX_5", NULL, "Quinary TDM5 Capture"},
555         {"QUIN_TDM_TX_6", NULL, "Quinary TDM6 Capture"},
556         {"QUIN_TDM_TX_7", NULL, "Quinary TDM7 Capture"},
557 
558         {"TERT_MI2S_TX", NULL, "Tertiary MI2S Capture"},
559         {"PRI_MI2S_TX", NULL, "Primary MI2S Capture"},
560         {"SEC_MI2S_TX", NULL, "Secondary MI2S Capture"},
561         {"QUAT_MI2S_TX", NULL, "Quaternary MI2S Capture"},
562 };
563 
564 static struct snd_soc_dai_ops q6hdmi_ops = {
565         .prepare        = q6afe_dai_prepare,
566         .hw_params      = q6hdmi_hw_params,
567         .shutdown       = q6afe_dai_shutdown,
568 };
569 
570 static struct snd_soc_dai_ops q6i2s_ops = {
571         .prepare        = q6afe_dai_prepare,
572         .hw_params      = q6i2s_hw_params,
573         .set_fmt        = q6i2s_set_fmt,
574         .shutdown       = q6afe_dai_shutdown,
575         .set_sysclk     = q6afe_mi2s_set_sysclk,
576 };
577 
578 static struct snd_soc_dai_ops q6slim_ops = {
579         .prepare        = q6afe_dai_prepare,
580         .hw_params      = q6slim_hw_params,
581         .shutdown       = q6afe_dai_shutdown,
582         .set_channel_map = q6slim_set_channel_map,
583 };
584 
585 static struct snd_soc_dai_ops q6tdm_ops = {
586         .prepare        = q6afe_dai_prepare,
587         .shutdown       = q6afe_dai_shutdown,
588         .set_sysclk     = q6afe_mi2s_set_sysclk,
589         .set_tdm_slot     = q6tdm_set_tdm_slot,
590         .set_channel_map  = q6tdm_set_channel_map,
591         .hw_params        = q6tdm_hw_params,
592 };
593 
594 static int msm_dai_q6_dai_probe(struct snd_soc_dai *dai)
595 {
596         struct q6afe_dai_data *dai_data = dev_get_drvdata(dai->dev);
597         struct q6afe_port *port;
598 
599         port = q6afe_port_get_from_id(dai->dev, dai->id);
600         if (IS_ERR(port)) {
601                 dev_err(dai->dev, "Unable to get afe port\n");
602                 return -EINVAL;
603         }
604         dai_data->port[dai->id] = port;
605 
606         return 0;
607 }
608 
609 static int msm_dai_q6_dai_remove(struct snd_soc_dai *dai)
610 {
611         struct q6afe_dai_data *dai_data = dev_get_drvdata(dai->dev);
612 
613         q6afe_port_put(dai_data->port[dai->id]);
614         dai_data->port[dai->id] = NULL;
615 
616         return 0;
617 }
618 
619 static struct snd_soc_dai_driver q6afe_dais[] = {
620         {
621                 .playback = {
622                         .stream_name = "HDMI Playback",
623                         .rates = SNDRV_PCM_RATE_48000 |
624                                  SNDRV_PCM_RATE_96000 |
625                                  SNDRV_PCM_RATE_192000,
626                         .formats = SNDRV_PCM_FMTBIT_S16_LE |
627                                    SNDRV_PCM_FMTBIT_S24_LE,
628                         .channels_min = 2,
629                         .channels_max = 8,
630                         .rate_max =     192000,
631                         .rate_min =     48000,
632                 },
633                 .ops = &q6hdmi_ops,
634                 .id = HDMI_RX,
635                 .name = "HDMI",
636                 .probe = msm_dai_q6_dai_probe,
637                 .remove = msm_dai_q6_dai_remove,
638         }, {
639                 .name = "SLIMBUS_0_RX",
640                 .ops = &q6slim_ops,
641                 .id = SLIMBUS_0_RX,
642                 .probe = msm_dai_q6_dai_probe,
643                 .remove = msm_dai_q6_dai_remove,
644                 .playback = {
645                         .stream_name = "Slimbus Playback",
646                         .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
647                                  SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_96000 |
648                                  SNDRV_PCM_RATE_192000,
649                         .formats = SNDRV_PCM_FMTBIT_S16_LE |
650                                    SNDRV_PCM_FMTBIT_S24_LE,
651                         .channels_min = 1,
652                         .channels_max = 8,
653                         .rate_min = 8000,
654                         .rate_max = 192000,
655                 },
656         }, {
657                 .name = "SLIMBUS_0_TX",
658                 .ops = &q6slim_ops,
659                 .id = SLIMBUS_0_TX,
660                 .probe = msm_dai_q6_dai_probe,
661                 .remove = msm_dai_q6_dai_remove,
662                 .capture = {
663                         .stream_name = "Slimbus Capture",
664                         .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
665                                  SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_96000 |
666                                  SNDRV_PCM_RATE_192000,
667                         .formats = SNDRV_PCM_FMTBIT_S16_LE |
668                                    SNDRV_PCM_FMTBIT_S24_LE,
669                         .channels_min = 1,
670                         .channels_max = 8,
671                         .rate_min = 8000,
672                         .rate_max = 192000,
673                 },
674         }, {
675                 .playback = {
676                         .stream_name = "Slimbus1 Playback",
677                         .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |
678                                  SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 |
679                                  SNDRV_PCM_RATE_192000,
680                         .formats = SNDRV_PCM_FMTBIT_S16_LE |
681                                    SNDRV_PCM_FMTBIT_S24_LE,
682                         .channels_min = 1,
683                         .channels_max = 2,
684                         .rate_min = 8000,
685                         .rate_max = 192000,
686                 },
687                 .name = "SLIMBUS_1_RX",
688                 .ops = &q6slim_ops,
689                 .id = SLIMBUS_1_RX,
690                 .probe = msm_dai_q6_dai_probe,
691                 .remove = msm_dai_q6_dai_remove,
692         }, {
693                 .name = "SLIMBUS_1_TX",
694                 .ops = &q6slim_ops,
695                 .id = SLIMBUS_1_TX,
696                 .probe = msm_dai_q6_dai_probe,
697                 .remove = msm_dai_q6_dai_remove,
698                 .capture = {
699                         .stream_name = "Slimbus1 Capture",
700                         .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
701                                  SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_96000 |
702                                  SNDRV_PCM_RATE_192000,
703                         .formats = SNDRV_PCM_FMTBIT_S16_LE |
704                                    SNDRV_PCM_FMTBIT_S24_LE,
705                         .channels_min = 1,
706                         .channels_max = 8,
707                         .rate_min = 8000,
708                         .rate_max = 192000,
709                 },
710         }, {
711                 .playback = {
712                         .stream_name = "Slimbus2 Playback",
713                         .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
714                                  SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_96000 |
715                                  SNDRV_PCM_RATE_192000,
716                         .formats = SNDRV_PCM_FMTBIT_S16_LE |
717                                    SNDRV_PCM_FMTBIT_S24_LE,
718                         .channels_min = 1,
719                         .channels_max = 8,
720                         .rate_min = 8000,
721                         .rate_max = 192000,
722                 },
723                 .name = "SLIMBUS_2_RX",
724                 .ops = &q6slim_ops,
725                 .id = SLIMBUS_2_RX,
726                 .probe = msm_dai_q6_dai_probe,
727                 .remove = msm_dai_q6_dai_remove,
728 
729         }, {
730                 .name = "SLIMBUS_2_TX",
731                 .ops = &q6slim_ops,
732                 .id = SLIMBUS_2_TX,
733                 .probe = msm_dai_q6_dai_probe,
734                 .remove = msm_dai_q6_dai_remove,
735                 .capture = {
736                         .stream_name = "Slimbus2 Capture",
737                         .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
738                                  SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_96000 |
739                                  SNDRV_PCM_RATE_192000,
740                         .formats = SNDRV_PCM_FMTBIT_S16_LE |
741                                    SNDRV_PCM_FMTBIT_S24_LE,
742                         .channels_min = 1,
743                         .channels_max = 8,
744                         .rate_min = 8000,
745                         .rate_max = 192000,
746                 },
747         }, {
748                 .playback = {
749                         .stream_name = "Slimbus3 Playback",
750                         .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |
751                                  SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 |
752                                  SNDRV_PCM_RATE_192000,
753                         .formats = SNDRV_PCM_FMTBIT_S16_LE |
754                                    SNDRV_PCM_FMTBIT_S24_LE,
755                         .channels_min = 1,
756                         .channels_max = 2,
757                         .rate_min = 8000,
758                         .rate_max = 192000,
759                 },
760                 .name = "SLIMBUS_3_RX",
761                 .ops = &q6slim_ops,
762                 .id = SLIMBUS_3_RX,
763                 .probe = msm_dai_q6_dai_probe,
764                 .remove = msm_dai_q6_dai_remove,
765 
766         }, {
767                 .name = "SLIMBUS_3_TX",
768                 .ops = &q6slim_ops,
769                 .id = SLIMBUS_3_TX,
770                 .probe = msm_dai_q6_dai_probe,
771                 .remove = msm_dai_q6_dai_remove,
772                 .capture = {
773                         .stream_name = "Slimbus3 Capture",
774                         .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
775                                  SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_96000 |
776                                  SNDRV_PCM_RATE_192000,
777                         .formats = SNDRV_PCM_FMTBIT_S16_LE |
778                                    SNDRV_PCM_FMTBIT_S24_LE,
779                         .channels_min = 1,
780                         .channels_max = 8,
781                         .rate_min = 8000,
782                         .rate_max = 192000,
783                 },
784         }, {
785                 .playback = {
786                         .stream_name = "Slimbus4 Playback",
787                         .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |
788                                  SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 |
789                                  SNDRV_PCM_RATE_192000,
790                         .formats = SNDRV_PCM_FMTBIT_S16_LE |
791                                    SNDRV_PCM_FMTBIT_S24_LE,
792                         .channels_min = 1,
793                         .channels_max = 2,
794                         .rate_min = 8000,
795                         .rate_max = 192000,
796                 },
797                 .name = "SLIMBUS_4_RX",
798                 .ops = &q6slim_ops,
799                 .id = SLIMBUS_4_RX,
800                 .probe = msm_dai_q6_dai_probe,
801                 .remove = msm_dai_q6_dai_remove,
802 
803         }, {
804                 .name = "SLIMBUS_4_TX",
805                 .ops = &q6slim_ops,
806                 .id = SLIMBUS_4_TX,
807                 .probe = msm_dai_q6_dai_probe,
808                 .remove = msm_dai_q6_dai_remove,
809                 .capture = {
810                         .stream_name = "Slimbus4 Capture",
811                         .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
812                                  SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_96000 |
813                                  SNDRV_PCM_RATE_192000,
814                         .formats = SNDRV_PCM_FMTBIT_S16_LE |
815                                    SNDRV_PCM_FMTBIT_S24_LE,
816                         .channels_min = 1,
817                         .channels_max = 8,
818                         .rate_min = 8000,
819                         .rate_max = 192000,
820                 },
821         }, {
822                 .playback = {
823                         .stream_name = "Slimbus5 Playback",
824                         .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |
825                                  SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 |
826                                  SNDRV_PCM_RATE_192000,
827                         .formats = SNDRV_PCM_FMTBIT_S16_LE |
828                                    SNDRV_PCM_FMTBIT_S24_LE,
829                         .channels_min = 1,
830                         .channels_max = 2,
831                         .rate_min = 8000,
832                         .rate_max = 192000,
833                 },
834                 .name = "SLIMBUS_5_RX",
835                 .ops = &q6slim_ops,
836                 .id = SLIMBUS_5_RX,
837                 .probe = msm_dai_q6_dai_probe,
838                 .remove = msm_dai_q6_dai_remove,
839 
840         }, {
841                 .name = "SLIMBUS_5_TX",
842                 .ops = &q6slim_ops,
843                 .id = SLIMBUS_5_TX,
844                 .probe = msm_dai_q6_dai_probe,
845                 .remove = msm_dai_q6_dai_remove,
846                 .capture = {
847                         .stream_name = "Slimbus5 Capture",
848                         .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
849                                  SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_96000 |
850                                  SNDRV_PCM_RATE_192000,
851                         .formats = SNDRV_PCM_FMTBIT_S16_LE |
852                                    SNDRV_PCM_FMTBIT_S24_LE,
853                         .channels_min = 1,
854                         .channels_max = 8,
855                         .rate_min = 8000,
856                         .rate_max = 192000,
857                 },
858         }, {
859                 .playback = {
860                         .stream_name = "Slimbus6 Playback",
861                         .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |
862                                  SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 |
863                                  SNDRV_PCM_RATE_192000,
864                         .formats = SNDRV_PCM_FMTBIT_S16_LE |
865                                    SNDRV_PCM_FMTBIT_S24_LE,
866                         .channels_min = 1,
867                         .channels_max = 2,
868                         .rate_min = 8000,
869                         .rate_max = 192000,
870                 },
871                 .ops = &q6slim_ops,
872                 .name = "SLIMBUS_6_RX",
873                 .id = SLIMBUS_6_RX,
874                 .probe = msm_dai_q6_dai_probe,
875                 .remove = msm_dai_q6_dai_remove,
876 
877         }, {
878                 .name = "SLIMBUS_6_TX",
879                 .ops = &q6slim_ops,
880                 .id = SLIMBUS_6_TX,
881                 .probe = msm_dai_q6_dai_probe,
882                 .remove = msm_dai_q6_dai_remove,
883                 .capture = {
884                         .stream_name = "Slimbus6 Capture",
885                         .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
886                                  SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_96000 |
887                                  SNDRV_PCM_RATE_192000,
888                         .formats = SNDRV_PCM_FMTBIT_S16_LE |
889                                    SNDRV_PCM_FMTBIT_S24_LE,
890                         .channels_min = 1,
891                         .channels_max = 8,
892                         .rate_min = 8000,
893                         .rate_max = 192000,
894                 },
895         }, {
896                 .playback = {
897                         .stream_name = "Primary MI2S Playback",
898                         .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
899                                  SNDRV_PCM_RATE_16000,
900                         .formats = SNDRV_PCM_FMTBIT_S16_LE |
901                                    SNDRV_PCM_FMTBIT_S24_LE,
902                         .rate_min =     8000,
903                         .rate_max =     48000,
904                 },
905                 .id = PRIMARY_MI2S_RX,
906                 .name = "PRI_MI2S_RX",
907                 .ops = &q6i2s_ops,
908                 .probe = msm_dai_q6_dai_probe,
909                 .remove = msm_dai_q6_dai_remove,
910         }, {
911                 .capture = {
912                         .stream_name = "Primary MI2S Capture",
913                         .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
914                                  SNDRV_PCM_RATE_16000,
915                         .formats = SNDRV_PCM_FMTBIT_S16_LE |
916                                    SNDRV_PCM_FMTBIT_S24_LE,
917                         .rate_min =     8000,
918                         .rate_max =     48000,
919                 },
920                 .id = PRIMARY_MI2S_TX,
921                 .name = "PRI_MI2S_TX",
922                 .ops = &q6i2s_ops,
923                 .probe = msm_dai_q6_dai_probe,
924                 .remove = msm_dai_q6_dai_remove,
925         }, {
926                 .playback = {
927                         .stream_name = "Secondary MI2S Playback",
928                         .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
929                                  SNDRV_PCM_RATE_16000,
930                         .formats = SNDRV_PCM_FMTBIT_S16_LE,
931                         .rate_min =     8000,
932                         .rate_max =     48000,
933                 },
934                 .name = "SEC_MI2S_RX",
935                 .id = SECONDARY_MI2S_RX,
936                 .ops = &q6i2s_ops,
937                 .probe = msm_dai_q6_dai_probe,
938                 .remove = msm_dai_q6_dai_remove,
939         }, {
940                 .capture = {
941                         .stream_name = "Secondary MI2S Capture",
942                         .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
943                                  SNDRV_PCM_RATE_16000,
944                         .formats = SNDRV_PCM_FMTBIT_S16_LE |
945                                    SNDRV_PCM_FMTBIT_S24_LE,
946                         .rate_min =     8000,
947                         .rate_max =     48000,
948                 },
949                 .id = SECONDARY_MI2S_TX,
950                 .name = "SEC_MI2S_TX",
951                 .ops = &q6i2s_ops,
952                 .probe = msm_dai_q6_dai_probe,
953                 .remove = msm_dai_q6_dai_remove,
954         }, {
955                 .playback = {
956                         .stream_name = "Tertiary MI2S Playback",
957                         .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
958                                  SNDRV_PCM_RATE_16000,
959                         .formats = SNDRV_PCM_FMTBIT_S16_LE,
960                         .rate_min =     8000,
961                         .rate_max =     48000,
962                 },
963                 .name = "TERT_MI2S_RX",
964                 .id = TERTIARY_MI2S_RX,
965                 .ops = &q6i2s_ops,
966                 .probe = msm_dai_q6_dai_probe,
967                 .remove = msm_dai_q6_dai_remove,
968         }, {
969                 .capture = {
970                         .stream_name = "Tertiary MI2S Capture",
971                         .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
972                                  SNDRV_PCM_RATE_16000,
973                         .formats = SNDRV_PCM_FMTBIT_S16_LE |
974                                    SNDRV_PCM_FMTBIT_S24_LE,
975                         .rate_min =     8000,
976                         .rate_max =     48000,
977                 },
978                 .id = TERTIARY_MI2S_TX,
979                 .name = "TERT_MI2S_TX",
980                 .ops = &q6i2s_ops,
981                 .probe = msm_dai_q6_dai_probe,
982                 .remove = msm_dai_q6_dai_remove,
983         }, {
984                 .playback = {
985                         .stream_name = "Quaternary MI2S Playback",
986                         .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
987                                  SNDRV_PCM_RATE_16000,
988                         .formats = SNDRV_PCM_FMTBIT_S16_LE,
989                         .rate_min =     8000,
990                         .rate_max =     48000,
991                 },
992                 .name = "QUAT_MI2S_RX",
993                 .id = QUATERNARY_MI2S_RX,
994                 .ops = &q6i2s_ops,
995                 .probe = msm_dai_q6_dai_probe,
996                 .remove = msm_dai_q6_dai_remove,
997         }, {
998                 .capture = {
999                         .stream_name = "Quaternary MI2S Capture",
1000                         .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
1001                                  SNDRV_PCM_RATE_16000,
1002                         .formats = SNDRV_PCM_FMTBIT_S16_LE |
1003                                    SNDRV_PCM_FMTBIT_S24_LE,
1004                         .rate_min =     8000,
1005                         .rate_max =     48000,
1006                 },
1007                 .id = QUATERNARY_MI2S_TX,
1008                 .name = "QUAT_MI2S_TX",
1009                 .ops = &q6i2s_ops,
1010                 .probe = msm_dai_q6_dai_probe,
1011                 .remove = msm_dai_q6_dai_remove,
1012         },
1013         Q6AFE_TDM_PB_DAI("Primary", 0, PRIMARY_TDM_RX_0),
1014         Q6AFE_TDM_PB_DAI("Primary", 1, PRIMARY_TDM_RX_1),
1015         Q6AFE_TDM_PB_DAI("Primary", 2, PRIMARY_TDM_RX_2),
1016         Q6AFE_TDM_PB_DAI("Primary", 3, PRIMARY_TDM_RX_3),
1017         Q6AFE_TDM_PB_DAI("Primary", 4, PRIMARY_TDM_RX_4),
1018         Q6AFE_TDM_PB_DAI("Primary", 5, PRIMARY_TDM_RX_5),
1019         Q6AFE_TDM_PB_DAI("Primary", 6, PRIMARY_TDM_RX_6),
1020         Q6AFE_TDM_PB_DAI("Primary", 7, PRIMARY_TDM_RX_7),
1021         Q6AFE_TDM_CAP_DAI("Primary", 0, PRIMARY_TDM_TX_0),
1022         Q6AFE_TDM_CAP_DAI("Primary", 1, PRIMARY_TDM_TX_1),
1023         Q6AFE_TDM_CAP_DAI("Primary", 2, PRIMARY_TDM_TX_2),
1024         Q6AFE_TDM_CAP_DAI("Primary", 3, PRIMARY_TDM_TX_3),
1025         Q6AFE_TDM_CAP_DAI("Primary", 4, PRIMARY_TDM_TX_4),
1026         Q6AFE_TDM_CAP_DAI("Primary", 5, PRIMARY_TDM_TX_5),
1027         Q6AFE_TDM_CAP_DAI("Primary", 6, PRIMARY_TDM_TX_6),
1028         Q6AFE_TDM_CAP_DAI("Primary", 7, PRIMARY_TDM_TX_7),
1029         Q6AFE_TDM_PB_DAI("Secondary", 0, SECONDARY_TDM_RX_0),
1030         Q6AFE_TDM_PB_DAI("Secondary", 1, SECONDARY_TDM_RX_1),
1031         Q6AFE_TDM_PB_DAI("Secondary", 2, SECONDARY_TDM_RX_2),
1032         Q6AFE_TDM_PB_DAI("Secondary", 3, SECONDARY_TDM_RX_3),
1033         Q6AFE_TDM_PB_DAI("Secondary", 4, SECONDARY_TDM_RX_4),
1034         Q6AFE_TDM_PB_DAI("Secondary", 5, SECONDARY_TDM_RX_5),
1035         Q6AFE_TDM_PB_DAI("Secondary", 6, SECONDARY_TDM_RX_6),
1036         Q6AFE_TDM_PB_DAI("Secondary", 7, SECONDARY_TDM_RX_7),
1037         Q6AFE_TDM_CAP_DAI("Secondary", 0, SECONDARY_TDM_TX_0),
1038         Q6AFE_TDM_CAP_DAI("Secondary", 1, SECONDARY_TDM_TX_1),
1039         Q6AFE_TDM_CAP_DAI("Secondary", 2, SECONDARY_TDM_TX_2),
1040         Q6AFE_TDM_CAP_DAI("Secondary", 3, SECONDARY_TDM_TX_3),
1041         Q6AFE_TDM_CAP_DAI("Secondary", 4, SECONDARY_TDM_TX_4),
1042         Q6AFE_TDM_CAP_DAI("Secondary", 5, SECONDARY_TDM_TX_5),
1043         Q6AFE_TDM_CAP_DAI("Secondary", 6, SECONDARY_TDM_TX_6),
1044         Q6AFE_TDM_CAP_DAI("Secondary", 7, SECONDARY_TDM_TX_7),
1045         Q6AFE_TDM_PB_DAI("Tertiary", 0, TERTIARY_TDM_RX_0),
1046         Q6AFE_TDM_PB_DAI("Tertiary", 1, TERTIARY_TDM_RX_1),
1047         Q6AFE_TDM_PB_DAI("Tertiary", 2, TERTIARY_TDM_RX_2),
1048         Q6AFE_TDM_PB_DAI("Tertiary", 3, TERTIARY_TDM_RX_3),
1049         Q6AFE_TDM_PB_DAI("Tertiary", 4, TERTIARY_TDM_RX_4),
1050         Q6AFE_TDM_PB_DAI("Tertiary", 5, TERTIARY_TDM_RX_5),
1051         Q6AFE_TDM_PB_DAI("Tertiary", 6, TERTIARY_TDM_RX_6),
1052         Q6AFE_TDM_PB_DAI("Tertiary", 7, TERTIARY_TDM_RX_7),
1053         Q6AFE_TDM_CAP_DAI("Tertiary", 0, TERTIARY_TDM_TX_0),
1054         Q6AFE_TDM_CAP_DAI("Tertiary", 1, TERTIARY_TDM_TX_1),
1055         Q6AFE_TDM_CAP_DAI("Tertiary", 2, TERTIARY_TDM_TX_2),
1056         Q6AFE_TDM_CAP_DAI("Tertiary", 3, TERTIARY_TDM_TX_3),
1057         Q6AFE_TDM_CAP_DAI("Tertiary", 4, TERTIARY_TDM_TX_4),
1058         Q6AFE_TDM_CAP_DAI("Tertiary", 5, TERTIARY_TDM_TX_5),
1059         Q6AFE_TDM_CAP_DAI("Tertiary", 6, TERTIARY_TDM_TX_6),
1060         Q6AFE_TDM_CAP_DAI("Tertiary", 7, TERTIARY_TDM_TX_7),
1061         Q6AFE_TDM_PB_DAI("Quaternary", 0, QUATERNARY_TDM_RX_0),
1062         Q6AFE_TDM_PB_DAI("Quaternary", 1, QUATERNARY_TDM_RX_1),
1063         Q6AFE_TDM_PB_DAI("Quaternary", 2, QUATERNARY_TDM_RX_2),
1064         Q6AFE_TDM_PB_DAI("Quaternary", 3, QUATERNARY_TDM_RX_3),
1065         Q6AFE_TDM_PB_DAI("Quaternary", 4, QUATERNARY_TDM_RX_4),
1066         Q6AFE_TDM_PB_DAI("Quaternary", 5, QUATERNARY_TDM_RX_5),
1067         Q6AFE_TDM_PB_DAI("Quaternary", 6, QUATERNARY_TDM_RX_6),
1068         Q6AFE_TDM_PB_DAI("Quaternary", 7, QUATERNARY_TDM_RX_7),
1069         Q6AFE_TDM_CAP_DAI("Quaternary", 0, QUATERNARY_TDM_TX_0),
1070         Q6AFE_TDM_CAP_DAI("Quaternary", 1, QUATERNARY_TDM_TX_1),
1071         Q6AFE_TDM_CAP_DAI("Quaternary", 2, QUATERNARY_TDM_TX_2),
1072         Q6AFE_TDM_CAP_DAI("Quaternary", 3, QUATERNARY_TDM_TX_3),
1073         Q6AFE_TDM_CAP_DAI("Quaternary", 4, QUATERNARY_TDM_TX_4),
1074         Q6AFE_TDM_CAP_DAI("Quaternary", 5, QUATERNARY_TDM_TX_5),
1075         Q6AFE_TDM_CAP_DAI("Quaternary", 6, QUATERNARY_TDM_TX_6),
1076         Q6AFE_TDM_CAP_DAI("Quaternary", 7, QUATERNARY_TDM_TX_7),
1077         Q6AFE_TDM_PB_DAI("Quinary", 0, QUINARY_TDM_RX_0),
1078         Q6AFE_TDM_PB_DAI("Quinary", 1, QUINARY_TDM_RX_1),
1079         Q6AFE_TDM_PB_DAI("Quinary", 2, QUINARY_TDM_RX_2),
1080         Q6AFE_TDM_PB_DAI("Quinary", 3, QUINARY_TDM_RX_3),
1081         Q6AFE_TDM_PB_DAI("Quinary", 4, QUINARY_TDM_RX_4),
1082         Q6AFE_TDM_PB_DAI("Quinary", 5, QUINARY_TDM_RX_5),
1083         Q6AFE_TDM_PB_DAI("Quinary", 6, QUINARY_TDM_RX_6),
1084         Q6AFE_TDM_PB_DAI("Quinary", 7, QUINARY_TDM_RX_7),
1085         Q6AFE_TDM_CAP_DAI("Quinary", 0, QUINARY_TDM_TX_0),
1086         Q6AFE_TDM_CAP_DAI("Quinary", 1, QUINARY_TDM_TX_1),
1087         Q6AFE_TDM_CAP_DAI("Quinary", 2, QUINARY_TDM_TX_2),
1088         Q6AFE_TDM_CAP_DAI("Quinary", 3, QUINARY_TDM_TX_3),
1089         Q6AFE_TDM_CAP_DAI("Quinary", 4, QUINARY_TDM_TX_4),
1090         Q6AFE_TDM_CAP_DAI("Quinary", 5, QUINARY_TDM_TX_5),
1091         Q6AFE_TDM_CAP_DAI("Quinary", 6, QUINARY_TDM_TX_6),
1092         Q6AFE_TDM_CAP_DAI("Quinary", 7, QUINARY_TDM_TX_7),
1093 };
1094 
1095 static int q6afe_of_xlate_dai_name(struct snd_soc_component *component,
1096                                    struct of_phandle_args *args,
1097                                    const char **dai_name)
1098 {
1099         int id = args->args[0];
1100         int ret = -EINVAL;
1101         int i;
1102 
1103         for (i = 0; i  < ARRAY_SIZE(q6afe_dais); i++) {
1104                 if (q6afe_dais[i].id == id) {
1105                         *dai_name = q6afe_dais[i].name;
1106                         ret = 0;
1107                         break;
1108                 }
1109         }
1110 
1111         return ret;
1112 }
1113 
1114 static const struct snd_soc_dapm_widget q6afe_dai_widgets[] = {
1115         SND_SOC_DAPM_AIF_IN("HDMI_RX", NULL, 0, 0, 0, 0),
1116         SND_SOC_DAPM_AIF_IN("SLIMBUS_0_RX", NULL, 0, 0, 0, 0),
1117         SND_SOC_DAPM_AIF_IN("SLIMBUS_1_RX", NULL, 0, 0, 0, 0),
1118         SND_SOC_DAPM_AIF_IN("SLIMBUS_2_RX", NULL, 0, 0, 0, 0),
1119         SND_SOC_DAPM_AIF_IN("SLIMBUS_3_RX", NULL, 0, 0, 0, 0),
1120         SND_SOC_DAPM_AIF_IN("SLIMBUS_4_RX", NULL, 0, 0, 0, 0),
1121         SND_SOC_DAPM_AIF_IN("SLIMBUS_5_RX", NULL, 0, 0, 0, 0),
1122         SND_SOC_DAPM_AIF_IN("SLIMBUS_6_RX", NULL, 0, 0, 0, 0),
1123         SND_SOC_DAPM_AIF_OUT("SLIMBUS_0_TX", NULL, 0, 0, 0, 0),
1124         SND_SOC_DAPM_AIF_OUT("SLIMBUS_1_TX", NULL, 0, 0, 0, 0),
1125         SND_SOC_DAPM_AIF_OUT("SLIMBUS_2_TX", NULL, 0, 0, 0, 0),
1126         SND_SOC_DAPM_AIF_OUT("SLIMBUS_3_TX", NULL, 0, 0, 0, 0),
1127         SND_SOC_DAPM_AIF_OUT("SLIMBUS_4_TX", NULL, 0, 0, 0, 0),
1128         SND_SOC_DAPM_AIF_OUT("SLIMBUS_5_TX", NULL, 0, 0, 0, 0),
1129         SND_SOC_DAPM_AIF_OUT("SLIMBUS_6_TX", NULL, 0, 0, 0, 0),
1130         SND_SOC_DAPM_AIF_IN("QUAT_MI2S_RX", NULL,
1131                                                 0, 0, 0, 0),
1132         SND_SOC_DAPM_AIF_OUT("QUAT_MI2S_TX", NULL,
1133                                                 0, 0, 0, 0),
1134         SND_SOC_DAPM_AIF_IN("TERT_MI2S_RX", NULL,
1135                                                 0, 0, 0, 0),
1136         SND_SOC_DAPM_AIF_OUT("TERT_MI2S_TX", NULL,
1137                                                 0, 0, 0, 0),
1138         SND_SOC_DAPM_AIF_IN("SEC_MI2S_RX", NULL,
1139                              0, 0, 0, 0),
1140         SND_SOC_DAPM_AIF_OUT("SEC_MI2S_TX", NULL,
1141                                                 0, 0, 0, 0),
1142         SND_SOC_DAPM_AIF_IN("SEC_MI2S_RX_SD1",
1143                         "Secondary MI2S Playback SD1",
1144                         0, 0, 0, 0),
1145         SND_SOC_DAPM_AIF_IN("PRI_MI2S_RX", NULL,
1146                              0, 0, 0, 0),
1147         SND_SOC_DAPM_AIF_OUT("PRI_MI2S_TX", NULL,
1148                                                 0, 0, 0, 0),
1149 
1150         SND_SOC_DAPM_AIF_IN("PRIMARY_TDM_RX_0", NULL,
1151                              0, 0, 0, 0),
1152         SND_SOC_DAPM_AIF_IN("PRIMARY_TDM_RX_1", NULL,
1153                              0, 0, 0, 0),
1154         SND_SOC_DAPM_AIF_IN("PRIMARY_TDM_RX_2", NULL,
1155                              0, 0, 0, 0),
1156         SND_SOC_DAPM_AIF_IN("PRIMARY_TDM_RX_3", NULL,
1157                              0, 0, 0, 0),
1158         SND_SOC_DAPM_AIF_IN("PRIMARY_TDM_RX_4", NULL,
1159                              0, 0, 0, 0),
1160         SND_SOC_DAPM_AIF_IN("PRIMARY_TDM_RX_5", NULL,
1161                              0, 0, 0, 0),
1162         SND_SOC_DAPM_AIF_IN("PRIMARY_TDM_RX_6", NULL,
1163                              0, 0, 0, 0),
1164         SND_SOC_DAPM_AIF_IN("PRIMARY_TDM_RX_7", NULL,
1165                              0, 0, 0, 0),
1166         SND_SOC_DAPM_AIF_OUT("PRIMARY_TDM_TX_0", NULL,
1167                                                 0, 0, 0, 0),
1168         SND_SOC_DAPM_AIF_OUT("PRIMARY_TDM_TX_1", NULL,
1169                                                 0, 0, 0, 0),
1170         SND_SOC_DAPM_AIF_OUT("PRIMARY_TDM_TX_2", NULL,
1171                                                 0, 0, 0, 0),
1172         SND_SOC_DAPM_AIF_OUT("PRIMARY_TDM_TX_3", NULL,
1173                                                 0, 0, 0, 0),
1174         SND_SOC_DAPM_AIF_OUT("PRIMARY_TDM_TX_4", NULL,
1175                                                 0, 0, 0, 0),
1176         SND_SOC_DAPM_AIF_OUT("PRIMARY_TDM_TX_5", NULL,
1177                                                 0, 0, 0, 0),
1178         SND_SOC_DAPM_AIF_OUT("PRIMARY_TDM_TX_6", NULL,
1179                                                 0, 0, 0, 0),
1180         SND_SOC_DAPM_AIF_OUT("PRIMARY_TDM_TX_7", NULL,
1181                                                 0, 0, 0, 0),
1182 
1183         SND_SOC_DAPM_AIF_IN("SEC_TDM_RX_0", NULL,
1184                              0, 0, 0, 0),
1185         SND_SOC_DAPM_AIF_IN("SEC_TDM_RX_1", NULL,
1186                              0, 0, 0, 0),
1187         SND_SOC_DAPM_AIF_IN("SEC_TDM_RX_2", NULL,
1188                              0, 0, 0, 0),
1189         SND_SOC_DAPM_AIF_IN("SEC_TDM_RX_3", NULL,
1190                              0, 0, 0, 0),
1191         SND_SOC_DAPM_AIF_IN("SEC_TDM_RX_4", NULL,
1192                              0, 0, 0, 0),
1193         SND_SOC_DAPM_AIF_IN("SEC_TDM_RX_5", NULL,
1194                              0, 0, 0, 0),
1195         SND_SOC_DAPM_AIF_IN("SEC_TDM_RX_6", NULL,
1196                              0, 0, 0, 0),
1197         SND_SOC_DAPM_AIF_IN("SEC_TDM_RX_7", NULL,
1198                              0, 0, 0, 0),
1199         SND_SOC_DAPM_AIF_OUT("SEC_TDM_TX_0", NULL,
1200                                                 0, 0, 0, 0),
1201         SND_SOC_DAPM_AIF_OUT("SEC_TDM_TX_1", NULL,
1202                                                 0, 0, 0, 0),
1203         SND_SOC_DAPM_AIF_OUT("SEC_TDM_TX_2", NULL,
1204                                                 0, 0, 0, 0),
1205         SND_SOC_DAPM_AIF_OUT("SEC_TDM_TX_3", NULL,
1206                                                 0, 0, 0, 0),
1207         SND_SOC_DAPM_AIF_OUT("SEC_TDM_TX_4", NULL,
1208                                                 0, 0, 0, 0),
1209         SND_SOC_DAPM_AIF_OUT("SEC_TDM_TX_5", NULL,
1210                                                 0, 0, 0, 0),
1211         SND_SOC_DAPM_AIF_OUT("SEC_TDM_TX_6", NULL,
1212                                                 0, 0, 0, 0),
1213         SND_SOC_DAPM_AIF_OUT("SEC_TDM_TX_7", NULL,
1214                                                 0, 0, 0, 0),
1215 
1216         SND_SOC_DAPM_AIF_IN("TERT_TDM_RX_0", NULL,
1217                              0, 0, 0, 0),
1218         SND_SOC_DAPM_AIF_IN("TERT_TDM_RX_1", NULL,
1219                              0, 0, 0, 0),
1220         SND_SOC_DAPM_AIF_IN("TERT_TDM_RX_2", NULL,
1221                              0, 0, 0, 0),
1222         SND_SOC_DAPM_AIF_IN("TERT_TDM_RX_3", NULL,
1223                              0, 0, 0, 0),
1224         SND_SOC_DAPM_AIF_IN("TERT_TDM_RX_4", NULL,
1225                              0, 0, 0, 0),
1226         SND_SOC_DAPM_AIF_IN("TERT_TDM_RX_5", NULL,
1227                              0, 0, 0, 0),
1228         SND_SOC_DAPM_AIF_IN("TERT_TDM_RX_6", NULL,
1229                              0, 0, 0, 0),
1230         SND_SOC_DAPM_AIF_IN("TERT_TDM_RX_7", NULL,
1231                              0, 0, 0, 0),
1232         SND_SOC_DAPM_AIF_OUT("TERT_TDM_TX_0", NULL,
1233                                                 0, 0, 0, 0),
1234         SND_SOC_DAPM_AIF_OUT("TERT_TDM_TX_1", NULL,
1235                                                 0, 0, 0, 0),
1236         SND_SOC_DAPM_AIF_OUT("TERT_TDM_TX_2", NULL,
1237                                                 0, 0, 0, 0),
1238         SND_SOC_DAPM_AIF_OUT("TERT_TDM_TX_3", NULL,
1239                                                 0, 0, 0, 0),
1240         SND_SOC_DAPM_AIF_OUT("TERT_TDM_TX_4", NULL,
1241                                                 0, 0, 0, 0),
1242         SND_SOC_DAPM_AIF_OUT("TERT_TDM_TX_5", NULL,
1243                                                 0, 0, 0, 0),
1244         SND_SOC_DAPM_AIF_OUT("TERT_TDM_TX_6", NULL,
1245                                                 0, 0, 0, 0),
1246         SND_SOC_DAPM_AIF_OUT("TERT_TDM_TX_7", NULL,
1247                                                 0, 0, 0, 0),
1248 
1249         SND_SOC_DAPM_AIF_IN("QUAT_TDM_RX_0", NULL,
1250                              0, 0, 0, 0),
1251         SND_SOC_DAPM_AIF_IN("QUAT_TDM_RX_1", NULL,
1252                              0, 0, 0, 0),
1253         SND_SOC_DAPM_AIF_IN("QUAT_TDM_RX_2", NULL,
1254                              0, 0, 0, 0),
1255         SND_SOC_DAPM_AIF_IN("QUAT_TDM_RX_3", NULL,
1256                              0, 0, 0, 0),
1257         SND_SOC_DAPM_AIF_IN("QUAT_TDM_RX_4", NULL,
1258                              0, 0, 0, 0),
1259         SND_SOC_DAPM_AIF_IN("QUAT_TDM_RX_5", NULL,
1260                              0, 0, 0, 0),
1261         SND_SOC_DAPM_AIF_IN("QUAT_TDM_RX_6", NULL,
1262                              0, 0, 0, 0),
1263         SND_SOC_DAPM_AIF_IN("QUAT_TDM_RX_7", NULL,
1264                              0, 0, 0, 0),
1265         SND_SOC_DAPM_AIF_OUT("QUAT_TDM_TX_0", NULL,
1266                                                 0, 0, 0, 0),
1267         SND_SOC_DAPM_AIF_OUT("QUAT_TDM_TX_1", NULL,
1268                                                 0, 0, 0, 0),
1269         SND_SOC_DAPM_AIF_OUT("QUAT_TDM_TX_2", NULL,
1270                                                 0, 0, 0, 0),
1271         SND_SOC_DAPM_AIF_OUT("QUAT_TDM_TX_3", NULL,
1272                                                 0, 0, 0, 0),
1273         SND_SOC_DAPM_AIF_OUT("QUAT_TDM_TX_4", NULL,
1274                                                 0, 0, 0, 0),
1275         SND_SOC_DAPM_AIF_OUT("QUAT_TDM_TX_5", NULL,
1276                                                 0, 0, 0, 0),
1277         SND_SOC_DAPM_AIF_OUT("QUAT_TDM_TX_6", NULL,
1278                                                 0, 0, 0, 0),
1279         SND_SOC_DAPM_AIF_OUT("QUAT_TDM_TX_7", NULL,
1280                                                 0, 0, 0, 0),
1281 
1282         SND_SOC_DAPM_AIF_IN("QUIN_TDM_RX_0", NULL,
1283                              0, 0, 0, 0),
1284         SND_SOC_DAPM_AIF_IN("QUIN_TDM_RX_1", NULL,
1285                              0, 0, 0, 0),
1286         SND_SOC_DAPM_AIF_IN("QUIN_TDM_RX_2", NULL,
1287                              0, 0, 0, 0),
1288         SND_SOC_DAPM_AIF_IN("QUIN_TDM_RX_3", NULL,
1289                              0, 0, 0, 0),
1290         SND_SOC_DAPM_AIF_IN("QUIN_TDM_RX_4", NULL,
1291                              0, 0, 0, 0),
1292         SND_SOC_DAPM_AIF_IN("QUIN_TDM_RX_5", NULL,
1293                              0, 0, 0, 0),
1294         SND_SOC_DAPM_AIF_IN("QUIN_TDM_RX_6", NULL,
1295                              0, 0, 0, 0),
1296         SND_SOC_DAPM_AIF_IN("QUIN_TDM_RX_7", NULL,
1297                              0, 0, 0, 0),
1298         SND_SOC_DAPM_AIF_OUT("QUIN_TDM_TX_0", NULL,
1299                                                 0, 0, 0, 0),
1300         SND_SOC_DAPM_AIF_OUT("QUIN_TDM_TX_1", NULL,
1301                                                 0, 0, 0, 0),
1302         SND_SOC_DAPM_AIF_OUT("QUIN_TDM_TX_2", NULL,
1303                                                 0, 0, 0, 0),
1304         SND_SOC_DAPM_AIF_OUT("QUIN_TDM_TX_3", NULL,
1305                                                 0, 0, 0, 0),
1306         SND_SOC_DAPM_AIF_OUT("QUIN_TDM_TX_4", NULL,
1307                                                 0, 0, 0, 0),
1308         SND_SOC_DAPM_AIF_OUT("QUIN_TDM_TX_5", NULL,
1309                                                 0, 0, 0, 0),
1310         SND_SOC_DAPM_AIF_OUT("QUIN_TDM_TX_6", NULL,
1311                                                 0, 0, 0, 0),
1312         SND_SOC_DAPM_AIF_OUT("QUIN_TDM_TX_7", NULL,
1313                                                 0, 0, 0, 0),
1314 };
1315 
1316 static const struct snd_soc_component_driver q6afe_dai_component = {
1317         .name           = "q6afe-dai-component",
1318         .dapm_widgets = q6afe_dai_widgets,
1319         .num_dapm_widgets = ARRAY_SIZE(q6afe_dai_widgets),
1320         .dapm_routes = q6afe_dapm_routes,
1321         .num_dapm_routes = ARRAY_SIZE(q6afe_dapm_routes),
1322         .of_xlate_dai_name = q6afe_of_xlate_dai_name,
1323 
1324 };
1325 
1326 static void of_q6afe_parse_dai_data(struct device *dev,
1327                                     struct q6afe_dai_data *data)
1328 {
1329         struct device_node *node;
1330         int ret;
1331 
1332         for_each_child_of_node(dev->of_node, node) {
1333                 unsigned int lines[Q6AFE_MAX_MI2S_LINES];
1334                 struct q6afe_dai_priv_data *priv;
1335                 int id, i, num_lines;
1336 
1337                 ret = of_property_read_u32(node, "reg", &id);
1338                 if (ret || id < 0 || id >= AFE_PORT_MAX) {
1339                         dev_err(dev, "valid dai id not found:%d\n", ret);
1340                         continue;
1341                 }
1342 
1343                 switch (id) {
1344                 /* MI2S specific properties */
1345                 case PRIMARY_MI2S_RX ... QUATERNARY_MI2S_TX:
1346                         priv = &data->priv[id];
1347                         ret = of_property_read_variable_u32_array(node,
1348                                                         "qcom,sd-lines",
1349                                                         lines, 0,
1350                                                         Q6AFE_MAX_MI2S_LINES);
1351                         if (ret < 0)
1352                                 num_lines = 0;
1353                         else
1354                                 num_lines = ret;
1355 
1356                         priv->sd_line_mask = 0;
1357 
1358                         for (i = 0; i < num_lines; i++)
1359                                 priv->sd_line_mask |= BIT(lines[i]);
1360 
1361                         break;
1362                 case PRIMARY_TDM_RX_0 ... QUINARY_TDM_TX_7:
1363                         priv = &data->priv[id];
1364                         ret = of_property_read_u32(node, "qcom,tdm-sync-mode",
1365                                                    &priv->sync_mode);
1366                         if (ret) {
1367                                 dev_err(dev, "No Sync mode from DT\n");
1368                                 break;
1369                         }
1370                         ret = of_property_read_u32(node, "qcom,tdm-sync-src",
1371                                                    &priv->sync_src);
1372                         if (ret) {
1373                                 dev_err(dev, "No Sync Src from DT\n");
1374                                 break;
1375                         }
1376                         ret = of_property_read_u32(node, "qcom,tdm-data-out",
1377                                                    &priv->data_out_enable);
1378                         if (ret) {
1379                                 dev_err(dev, "No Data out enable from DT\n");
1380                                 break;
1381                         }
1382                         ret = of_property_read_u32(node, "qcom,tdm-invert-sync",
1383                                                    &priv->invert_sync);
1384                         if (ret) {
1385                                 dev_err(dev, "No Invert sync from DT\n");
1386                                 break;
1387                         }
1388                         ret = of_property_read_u32(node, "qcom,tdm-data-delay",
1389                                                    &priv->data_delay);
1390                         if (ret) {
1391                                 dev_err(dev, "No Data Delay from DT\n");
1392                                 break;
1393                         }
1394                         ret = of_property_read_u32(node, "qcom,tdm-data-align",
1395                                                    &priv->data_align);
1396                         if (ret) {
1397                                 dev_err(dev, "No Data align from DT\n");
1398                                 break;
1399                         }
1400                         break;
1401                 default:
1402                         break;
1403                 }
1404         }
1405 }
1406 
1407 static int q6afe_dai_dev_probe(struct platform_device *pdev)
1408 {
1409         struct q6afe_dai_data *dai_data;
1410         struct device *dev = &pdev->dev;
1411 
1412         dai_data = devm_kzalloc(dev, sizeof(*dai_data), GFP_KERNEL);
1413         if (!dai_data)
1414                 return -ENOMEM;
1415 
1416         dev_set_drvdata(dev, dai_data);
1417 
1418         of_q6afe_parse_dai_data(dev, dai_data);
1419 
1420         return devm_snd_soc_register_component(dev, &q6afe_dai_component,
1421                                           q6afe_dais, ARRAY_SIZE(q6afe_dais));
1422 }
1423 
1424 static const struct of_device_id q6afe_dai_device_id[] = {
1425         { .compatible = "qcom,q6afe-dais" },
1426         {},
1427 };
1428 MODULE_DEVICE_TABLE(of, q6afe_dai_device_id);
1429 
1430 static struct platform_driver q6afe_dai_platform_driver = {
1431         .driver = {
1432                 .name = "q6afe-dai",
1433                 .of_match_table = of_match_ptr(q6afe_dai_device_id),
1434         },
1435         .probe = q6afe_dai_dev_probe,
1436 };
1437 module_platform_driver(q6afe_dai_platform_driver);
1438 
1439 MODULE_DESCRIPTION("Q6 Audio Fronend dai driver");
1440 MODULE_LICENSE("GPL v2");
1441 

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

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | 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.

osdn.jp