blob: fcafd27a4e89ffc8f3846e3ce7ba9061ea354c9f [file] [log] [blame]
Manjunatha Madana58ebedb2020-02-19 17:39:05 +05301/* Copyright (c) 2015-2016, 2018, 2020, The Linux Foundation.
2 * All rights reserved.
Soumya Managoli84c975c2018-02-23 13:00:54 +05303 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 and
6 * only version 2 as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 */
13
14#include <linux/clk.h>
15#include <linux/delay.h>
16#include <linux/gpio.h>
17#include <linux/of_gpio.h>
18#include <linux/platform_device.h>
19#include <linux/io.h>
20#include <linux/module.h>
21#include <linux/workqueue.h>
22#include <linux/input.h>
23#include <sound/core.h>
24#include <sound/soc.h>
25#include <sound/soc-dapm.h>
26#include <sound/pcm.h>
27#include <sound/jack.h>
28#include <dsp/q6afe-v2.h>
29#include <dsp/q6core.h>
30#include <soc/qcom/socinfo.h>
31#include "msm-pcm-routing-v2.h"
32#include "codecs/msm-cdc-pinctrl.h"
33#include "msm8952.h"
34
35#define DRV_NAME "msm8952-asoc-wcd"
36
37#define MSM_INT_DIGITAL_CODEC "msm-dig-codec"
38#define PMIC_INT_ANALOG_CODEC "analog-codec"
39
40enum btsco_rates {
41 RATE_8KHZ_ID,
42 RATE_16KHZ_ID,
43};
44
45/* dummy definition of deprecated FE DAI's*/
46enum {
47 MSM_FRONTEND_DAI_CS_VOICE = 39,
48 MSM_FRONTEND_DAI_VOICE2,
49 MSM_FRONTEND_DAI_VOLTE,
50 MSM_FRONTEND_DAI_VOWLAN,
51};
52
53static int msm8952_auxpcm_rate = 8000;
54static int msm_btsco_rate = BTSCO_RATE_8KHZ;
55static int msm_btsco_ch = 1;
56static int msm_ter_mi2s_tx_ch = 1;
57static int msm_pri_mi2s_rx_ch = 1;
58static int msm_proxy_rx_ch = 2;
59static int msm_vi_feed_tx_ch = 2;
60static int mi2s_rx_bit_format = SNDRV_PCM_FORMAT_S16_LE;
61static int mi2s_rx_bits_per_sample = 16;
62static int mi2s_rx_sample_rate = SAMPLING_RATE_48KHZ;
63
64static atomic_t quat_mi2s_clk_ref;
65static atomic_t quin_mi2s_clk_ref;
66static atomic_t auxpcm_mi2s_clk_ref;
67static struct snd_info_entry *codec_root;
68
69static int msm8952_enable_dig_cdc_clk(struct snd_soc_codec *codec, int enable,
70 bool dapm);
71static bool msm8952_swap_gnd_mic(struct snd_soc_codec *codec, bool active);
72static int msm8952_mclk_event(struct snd_soc_dapm_widget *w,
73 struct snd_kcontrol *kcontrol, int event);
74static int msm8952_wsa_switch_event(struct snd_soc_dapm_widget *w,
75 struct snd_kcontrol *kcontrol, int event);
76
77/*
78 * Android L spec
79 * Need to report LINEIN
80 * if R/L channel impedance is larger than 5K ohm
81 */
82static struct wcd_mbhc_config mbhc_cfg = {
83 .read_fw_bin = false,
84 .calibration = NULL,
85 .detect_extn_cable = true,
86 .mono_stero_detection = false,
87 .swap_gnd_mic = NULL,
88 .hs_ext_micbias = false,
89 .key_code[0] = KEY_MEDIA,
90 .key_code[1] = KEY_VOICECOMMAND,
91 .key_code[2] = KEY_VOLUMEUP,
92 .key_code[3] = KEY_VOLUMEDOWN,
93 .key_code[4] = 0,
94 .key_code[5] = 0,
95 .key_code[6] = 0,
96 .key_code[7] = 0,
97 .linein_th = 5000,
98 .moisture_en = false,
99 .mbhc_micbias = 0,
100 .anc_micbias = 0,
101 .enable_anc_mic_detect = false,
102};
103
104static struct afe_clk_set mi2s_tx_clk = {
105 AFE_API_VERSION_I2S_CONFIG,
106 Q6AFE_LPASS_CLK_ID_TER_MI2S_IBIT,
107 Q6AFE_LPASS_IBIT_CLK_1_P536_MHZ,
108 Q6AFE_LPASS_CLK_ATTRIBUTE_COUPLE_NO,
109 Q6AFE_LPASS_CLK_ROOT_DEFAULT,
110 0,
111};
112
113static struct afe_clk_set mi2s_rx_clk = {
114 AFE_API_VERSION_I2S_CONFIG,
115 Q6AFE_LPASS_CLK_ID_PRI_MI2S_IBIT,
116 Q6AFE_LPASS_IBIT_CLK_1_P536_MHZ,
117 Q6AFE_LPASS_CLK_ATTRIBUTE_COUPLE_NO,
118 Q6AFE_LPASS_CLK_ROOT_DEFAULT,
119 0,
120};
121
122static struct afe_clk_set wsa_ana_clk = {
123 AFE_API_VERSION_I2S_CONFIG,
124 Q6AFE_LPASS_CLK_ID_MCLK_1,
125 Q6AFE_LPASS_OSR_CLK_9_P600_MHZ,
126 Q6AFE_LPASS_CLK_ATTRIBUTE_COUPLE_NO,
127 Q6AFE_LPASS_CLK_ROOT_DEFAULT,
128 0,
129};
130
131static char const *rx_bit_format_text[] = {"S16_LE", "S24_LE", "S24_3LE"};
132static const char *const mi2s_ch_text[] = {"One", "Two"};
133static const char *const loopback_mclk_text[] = {"DISABLE", "ENABLE"};
134static const char *const btsco_rate_text[] = {"BTSCO_RATE_8KHZ",
135 "BTSCO_RATE_16KHZ"};
136static const char *const proxy_rx_ch_text[] = {"One", "Two", "Three", "Four",
137 "Five", "Six", "Seven", "Eight"};
138static const char *const vi_feed_ch_text[] = {"One", "Two"};
139static char const *mi2s_rx_sample_rate_text[] = {"KHZ_48",
140 "KHZ_96", "KHZ_192"};
141
142static inline int param_is_mask(int p)
143{
144 return (p >= SNDRV_PCM_HW_PARAM_FIRST_MASK) &&
145 (p <= SNDRV_PCM_HW_PARAM_LAST_MASK);
146}
147
148static inline struct snd_mask *param_to_mask(struct snd_pcm_hw_params *p, int n)
149{
150 return &(p->masks[n - SNDRV_PCM_HW_PARAM_FIRST_MASK]);
151}
152
153static void param_set_mask(struct snd_pcm_hw_params *p, int n,
154 unsigned int bit)
155{
156 if (bit >= SNDRV_MASK_MAX)
157 return;
158 if (param_is_mask(n)) {
159 struct snd_mask *m = param_to_mask(p, n);
160
161 m->bits[0] = 0;
162 m->bits[1] = 0;
163 m->bits[bit >> 5] |= (1 << (bit & 31));
164 }
165}
166
167static int msm8952_mclk_event(struct snd_soc_dapm_widget *w,
168 struct snd_kcontrol *kcontrol, int event)
169{
170 struct msm_asoc_mach_data *pdata = NULL;
171 int ret = 0;
172 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
173
174 pdata = snd_soc_card_get_drvdata(codec->component.card);
175 pr_debug("%s: event = %d\n", __func__, event);
176 switch (event) {
177 case SND_SOC_DAPM_PRE_PMU:
178 if (pdata->mi2s_gpio_p[PRIM_MI2S]) {
179 ret = msm_cdc_pinctrl_select_active_state(
180 pdata->mi2s_gpio_p[PRIM_MI2S]);
181 if (ret) {
182 pr_err("%s: failed to enable pri gpios: %d\n",
183 __func__, ret);
184 break;
185 }
186 }
187 msm8952_enable_dig_cdc_clk(codec, 1, true);
188 msm_anlg_cdc_mclk_enable(codec, 1, true);
189 break;
190 case SND_SOC_DAPM_POST_PMD:
191 pr_debug("%s: mclk_res_ref = %d\n",
192 __func__, atomic_read(&pdata->int_mclk0_rsc_ref));
193 if (pdata->mi2s_gpio_p[PRIM_MI2S]) {
194 ret = msm_cdc_pinctrl_select_sleep_state(
195 pdata->mi2s_gpio_p[PRIM_MI2S]);
196 if (ret < 0) {
197 pr_err("%s: gpio set cannot be de-activated %s",
198 __func__, "pri_i2s");
199 return ret;
200 }
201 }
202 pr_debug("%s: disabling MCLK\n", __func__);
203 /* disable the codec mclk config*/
204 msm_anlg_cdc_mclk_enable(codec, 0, true);
205 msm8952_enable_dig_cdc_clk(codec, 0, true);
206 break;
207 default:
208 pr_err("%s: invalid DAPM event %d\n", __func__, event);
209 return -EINVAL;
210 }
211 return 0;
212}
213
214static int msm8952_wsa_switch_event(struct snd_soc_dapm_widget *w,
215 struct snd_kcontrol *kcontrol, int event)
216{
217 int ret = 0;
218 struct msm_asoc_mach_data *pdata = NULL;
219 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
220 struct on_demand_supply *supply;
221
222 pdata = snd_soc_card_get_drvdata(codec->component.card);
223 supply = &pdata->wsa_switch_supply;
224 if (!supply->supply) {
225 dev_err(codec->component.card->dev, "%s: no wsa switch supply",
226 __func__);
227 return ret;
228 }
229
230 switch (event) {
231 case SND_SOC_DAPM_PRE_PMU:
232 if (atomic_inc_return(&supply->ref) == 1)
233 ret = regulator_enable(supply->supply);
234 if (ret)
235 dev_err(codec->component.card->dev,
236 "%s: Failed to enable wsa switch supply\n",
237 __func__);
238 break;
239 case SND_SOC_DAPM_POST_PMD:
240 if (atomic_read(&supply->ref) == 0) {
241 dev_dbg(codec->component.card->dev,
242 "%s: wsa switch supply has been disabled.\n",
243 __func__);
244 return ret;
245 }
Sachin Mohan Gadag1afa1bb2018-03-20 20:23:44 +0530246 if (atomic_dec_return(&supply->ref) == 0) {
Soumya Managoli84c975c2018-02-23 13:00:54 +0530247 ret = regulator_disable(supply->supply);
248 if (ret)
249 dev_err(codec->component.card->dev,
250 "%s: Failed to disable wsa switch supply\n",
251 __func__);
Sachin Mohan Gadag1afa1bb2018-03-20 20:23:44 +0530252 }
Soumya Managoli84c975c2018-02-23 13:00:54 +0530253 break;
254 default:
255 break;
256 }
257
258 return ret;
259}
260
261static const struct snd_soc_dapm_widget msm8952_dapm_widgets[] = {
262
263 SND_SOC_DAPM_SUPPLY_S("MCLK", -1, SND_SOC_NOPM, 0, 0,
264 msm8952_mclk_event,
265 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
266 SND_SOC_DAPM_MIC("Handset Mic", NULL),
267 SND_SOC_DAPM_MIC("Headset Mic", NULL),
268 SND_SOC_DAPM_MIC("Secondary Mic", NULL),
269 SND_SOC_DAPM_MIC("Digital Mic1", NULL),
270 SND_SOC_DAPM_MIC("Digital Mic2", NULL),
271 SND_SOC_DAPM_SUPPLY("VDD_WSA_SWITCH", SND_SOC_NOPM, 0, 0,
272 msm8952_wsa_switch_event,
273 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
274};
275
276static int config_hph_compander_gpio(bool enable,
277 struct snd_soc_codec *codec)
278{
279 int ret = 0;
280 struct snd_soc_card *card = codec->component.card;
281 struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
282
283 pr_debug("%s: %s HPH Compander\n", __func__,
284 enable ? "Enable" : "Disable");
285
286 if (pdata->comp_gpio_p) {
287 if (enable) {
288 ret = msm_cdc_pinctrl_select_active_state(
289 pdata->comp_gpio_p);
290 if (ret) {
291 pr_err("%s: gpio set cannot be activated %s\n",
292 __func__, "comp_gpio");
293 goto done;
294 }
295 } else {
296 ret = msm_cdc_pinctrl_select_sleep_state(
297 pdata->comp_gpio_p);
298 if (ret) {
299 pr_err("%s: gpio set cannot be de-activated %s\n",
300 __func__, "comp_gpio");
301 goto done;
302 }
303 }
304 }
305
306done:
307 return ret;
308}
309
310int is_ext_spk_gpio_support(struct platform_device *pdev,
311 struct msm_asoc_mach_data *pdata)
312{
313 const char *spk_ext_pa = "qcom,msm-spk-ext-pa";
314
315 pr_debug("%s:Enter\n", __func__);
316
317 pdata->spk_ext_pa_gpio = of_get_named_gpio(pdev->dev.of_node,
318 spk_ext_pa, 0);
319
320 if (pdata->spk_ext_pa_gpio < 0) {
321 dev_err(&pdev->dev,
322 "%s: missing %s in dt node\n", __func__, spk_ext_pa);
323 } else {
324 if (!gpio_is_valid(pdata->spk_ext_pa_gpio)) {
325 pr_err("%s: Invalid external speaker gpio: %d",
326 __func__, pdata->spk_ext_pa_gpio);
327 return -EINVAL;
328 }
329 }
330 return 0;
331}
332
333static int enable_spk_ext_pa(struct snd_soc_codec *codec, int enable)
334{
335 struct snd_soc_card *card = codec->component.card;
336 struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
337 int ret;
338
339 if (!gpio_is_valid(pdata->spk_ext_pa_gpio)) {
340 pr_err("%s: Invalid gpio: %d\n", __func__,
341 pdata->spk_ext_pa_gpio);
342 return false;
343 }
344
345 pr_debug("%s: %s external speaker PA\n", __func__,
346 enable ? "Enable" : "Disable");
347
348 if (enable) {
349 ret = msm_cdc_pinctrl_select_active_state(
350 pdata->spk_ext_pa_gpio_p);
351 if (ret) {
352 pr_err("%s: gpio set cannot be de-activated %s\n",
353 __func__, "ext_spk_gpio");
354 return ret;
355 }
356 gpio_set_value_cansleep(pdata->spk_ext_pa_gpio, enable);
357 } else {
358 gpio_set_value_cansleep(pdata->spk_ext_pa_gpio, enable);
359 ret = msm_cdc_pinctrl_select_sleep_state(
360 pdata->spk_ext_pa_gpio_p);
361 if (ret) {
362 pr_err("%s: gpio set cannot be de-activated %s\n",
363 __func__, "ext_spk_gpio");
364 return ret;
365 }
366 }
367 return 0;
368}
369
370static bool msm8952_swap_gnd_mic(struct snd_soc_codec *codec, bool active)
371{
372 struct snd_soc_card *card = codec->component.card;
373 struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
374 int value = 0, ret = 0;
375
376 pr_debug("%s: configure gpios for US_EU\n", __func__);
377
378 if (!gpio_is_valid(pdata->us_euro_gpio)) {
379 pr_err("%s: Invalid gpio: %d", __func__, pdata->us_euro_gpio);
380 return false;
381 }
382 value = gpio_get_value_cansleep(pdata->us_euro_gpio);
383 if (pdata->us_euro_gpio_p) {
384 ret = msm_cdc_pinctrl_select_active_state(
385 pdata->us_euro_gpio_p);
386 if (ret < 0) {
387 pr_err("%s: gpio set cannot be activated %sd",
388 __func__, "us_eu_gpio");
389 return false;
390 }
391 }
392 gpio_set_value_cansleep(pdata->us_euro_gpio, !value);
393 if (pdata->us_euro_gpio_p) {
394 ret = msm_cdc_pinctrl_select_sleep_state(
395 pdata->us_euro_gpio_p);
396 if (ret < 0) {
397 pr_err("%s: gpio set cannot be de-activated %sd",
398 __func__, "us_eu_gpio");
399 return false;
400 }
401 }
402 pr_debug("%s: swap select switch %d to %d\n", __func__, value, !value);
403 return true;
404}
405
406/* Validate whether US EU switch is present or not */
407int is_us_eu_switch_gpio_support(struct platform_device *pdev,
408 struct msm_asoc_mach_data *pdata)
409{
410 /* check if US-EU GPIO is supported */
411 pdata->us_euro_gpio = of_get_named_gpio(pdev->dev.of_node,
412 "qcom,cdc-us-euro-gpios", 0);
413 if (pdata->us_euro_gpio < 0) {
414 dev_err(&pdev->dev,
415 "property %s in node %s not found %d\n",
416 "qcom,cdc-us-euro-gpios", pdev->dev.of_node->full_name,
417 pdata->us_euro_gpio);
418 } else {
419 if (!gpio_is_valid(pdata->us_euro_gpio)) {
420 pr_err("%s: Invalid gpio: %d", __func__,
421 pdata->us_euro_gpio);
422 return -EINVAL;
423 }
424 pdata->us_euro_gpio_p = of_parse_phandle(pdev->dev.of_node,
425 "qcom,cdc-us-eu-gpios", 0);
426 mbhc_cfg.swap_gnd_mic = msm8952_swap_gnd_mic;
427 }
428 return 0;
429}
430
431static int msm_proxy_rx_ch_get(struct snd_kcontrol *kcontrol,
432 struct snd_ctl_elem_value *ucontrol)
433{
434 pr_debug("%s: msm_proxy_rx_ch = %d\n", __func__,
435 msm_proxy_rx_ch);
436 ucontrol->value.integer.value[0] = msm_proxy_rx_ch - 1;
437 return 0;
438}
439
440static int msm_proxy_rx_ch_put(struct snd_kcontrol *kcontrol,
441 struct snd_ctl_elem_value *ucontrol)
442{
443 msm_proxy_rx_ch = ucontrol->value.integer.value[0] + 1;
444 pr_debug("%s: msm_proxy_rx_ch = %d\n", __func__,
445 msm_proxy_rx_ch);
446 return 0;
447}
448
449static int msm_auxpcm_be_params_fixup(struct snd_soc_pcm_runtime *rtd,
450 struct snd_pcm_hw_params *params)
451{
452 struct snd_interval *rate =
453 hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
454
455 struct snd_interval *channels =
456 hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
457
458 rate->min = rate->max = msm8952_auxpcm_rate;
459 channels->min = channels->max = 1;
460
461 return 0;
462}
463
464static int msm_mi2s_rx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
465 struct snd_pcm_hw_params *params)
466{
467 struct snd_interval *rate = hw_param_interval(params,
468 SNDRV_PCM_HW_PARAM_RATE);
469
470 struct snd_interval *channels = hw_param_interval(params,
471 SNDRV_PCM_HW_PARAM_CHANNELS);
472
473 pr_debug("%s: Num of channels = %d Sample rate = %d\n", __func__,
474 msm_pri_mi2s_rx_ch, mi2s_rx_sample_rate);
475 rate->min = rate->max = mi2s_rx_sample_rate;
476 channels->min = channels->max = msm_pri_mi2s_rx_ch;
477
478 return 0;
479}
480
481static int msm_tx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
482 struct snd_pcm_hw_params *params)
483{
484 struct snd_interval *rate = hw_param_interval(params,
485 SNDRV_PCM_HW_PARAM_RATE);
486 struct snd_interval *channels = hw_param_interval(params,
487 SNDRV_PCM_HW_PARAM_CHANNELS);
488
489 pr_debug("%s(), channel:%d\n", __func__, msm_ter_mi2s_tx_ch);
490 param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
491 SNDRV_PCM_FORMAT_S16_LE);
492 rate->min = rate->max = 48000;
493 channels->min = channels->max = msm_ter_mi2s_tx_ch;
494
495 return 0;
496}
497
498static int msm_senary_tx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
499 struct snd_pcm_hw_params *params)
500{
501 struct snd_interval *rate = hw_param_interval(params,
502 SNDRV_PCM_HW_PARAM_RATE);
503 struct snd_interval *channels = hw_param_interval(params,
504 SNDRV_PCM_HW_PARAM_CHANNELS);
505
506 rate->min = rate->max = 48000;
507 channels->min = channels->max = 2;
508
509 return 0;
510}
511
512static int msm_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
513 struct snd_pcm_hw_params *params)
514{
515 struct snd_interval *rate = hw_param_interval(params,
516 SNDRV_PCM_HW_PARAM_RATE);
517
518 struct snd_interval *channels = hw_param_interval(params,
519 SNDRV_PCM_HW_PARAM_CHANNELS);
520
521 pr_debug("%s()\n", __func__);
522 rate->min = rate->max = 48000;
523 channels->min = channels->max = 2;
524
525 return 0;
526}
527
528static int msm_btsco_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
529 struct snd_pcm_hw_params *params)
530{
531 struct snd_interval *rate = hw_param_interval(params,
532 SNDRV_PCM_HW_PARAM_RATE);
533
534 struct snd_interval *channels = hw_param_interval(params,
535 SNDRV_PCM_HW_PARAM_CHANNELS);
536
537 rate->min = rate->max = msm_btsco_rate;
538 channels->min = channels->max = msm_btsco_ch;
539
540 return 0;
541}
542
543static int msm_proxy_rx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
544 struct snd_pcm_hw_params *params)
545{
546 struct snd_interval *rate = hw_param_interval(params,
547 SNDRV_PCM_HW_PARAM_RATE);
548
549 struct snd_interval *channels = hw_param_interval(params,
550 SNDRV_PCM_HW_PARAM_CHANNELS);
551
552 pr_debug("%s: msm_proxy_rx_ch =%d\n", __func__, msm_proxy_rx_ch);
553
554 if (channels->max < 2)
555 channels->min = channels->max = 2;
556 channels->min = channels->max = msm_proxy_rx_ch;
557 rate->min = rate->max = 48000;
558 return 0;
559}
560
561static int msm_proxy_tx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
562 struct snd_pcm_hw_params *params)
563{
564 struct snd_interval *rate = hw_param_interval(params,
565 SNDRV_PCM_HW_PARAM_RATE);
566
567 rate->min = rate->max = 48000;
568 return 0;
569}
570
571static int msm_mi2s_snd_hw_params(struct snd_pcm_substream *substream,
572 struct snd_pcm_hw_params *params)
573{
574 pr_debug("%s(): substream = %s stream = %d\n", __func__,
575 substream->name, substream->stream);
576 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
577 param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
578 mi2s_rx_bit_format);
579 else
580 param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
581 SNDRV_PCM_FORMAT_S16_LE);
582 return 0;
583}
584static int msm8952_get_clk_id(int port_id)
585{
586 switch (port_id) {
587 case AFE_PORT_ID_PRIMARY_MI2S_RX:
588 return Q6AFE_LPASS_CLK_ID_PRI_MI2S_IBIT;
589 case AFE_PORT_ID_SECONDARY_MI2S_RX:
590 return Q6AFE_LPASS_CLK_ID_SEC_MI2S_IBIT;
591 case AFE_PORT_ID_TERTIARY_MI2S_TX:
592 return Q6AFE_LPASS_CLK_ID_TER_MI2S_IBIT;
593 case AFE_PORT_ID_QUATERNARY_MI2S_RX:
594 case AFE_PORT_ID_QUATERNARY_MI2S_TX:
595 return Q6AFE_LPASS_CLK_ID_QUAD_MI2S_IBIT;
596 case AFE_PORT_ID_QUINARY_MI2S_RX:
597 case AFE_PORT_ID_QUINARY_MI2S_TX:
598 return Q6AFE_LPASS_CLK_ID_QUI_MI2S_IBIT;
599 case AFE_PORT_ID_SENARY_MI2S_TX:
600 return Q6AFE_LPASS_CLK_ID_SEN_MI2S_IBIT;
601 default:
602 pr_err("%s: invalid port_id: 0x%x\n", __func__, port_id);
603 return -EINVAL;
604 }
605}
606
607static int msm8952_get_port_id(int be_id)
608{
609 switch (be_id) {
610 case MSM_BACKEND_DAI_PRI_MI2S_RX:
611 return AFE_PORT_ID_PRIMARY_MI2S_RX;
612 case MSM_BACKEND_DAI_SECONDARY_MI2S_RX:
613 return AFE_PORT_ID_SECONDARY_MI2S_RX;
614 case MSM_BACKEND_DAI_TERTIARY_MI2S_TX:
615 return AFE_PORT_ID_TERTIARY_MI2S_TX;
616 case MSM_BACKEND_DAI_QUATERNARY_MI2S_RX:
617 return AFE_PORT_ID_QUATERNARY_MI2S_RX;
618 case MSM_BACKEND_DAI_QUATERNARY_MI2S_TX:
619 return AFE_PORT_ID_QUATERNARY_MI2S_TX;
620 case MSM_BACKEND_DAI_QUINARY_MI2S_RX:
621 return AFE_PORT_ID_QUINARY_MI2S_RX;
622 case MSM_BACKEND_DAI_QUINARY_MI2S_TX:
623 return AFE_PORT_ID_QUINARY_MI2S_TX;
624 case MSM_BACKEND_DAI_SENARY_MI2S_TX:
625 return AFE_PORT_ID_SENARY_MI2S_TX;
626 default:
627 pr_err("%s: Invalid.id: %d\n", __func__, be_id);
628 return -EINVAL;
629 }
630}
631
632static bool is_mi2s_rx_port(int port_id)
633{
634 bool ret = false;
635
636 switch (port_id) {
637 case AFE_PORT_ID_PRIMARY_MI2S_RX:
638 case AFE_PORT_ID_SECONDARY_MI2S_RX:
639 case AFE_PORT_ID_QUATERNARY_MI2S_RX:
640 case AFE_PORT_ID_QUINARY_MI2S_RX:
641 ret = true;
642 break;
643 default:
644 break;
645 }
646 return ret;
647}
648
649static uint32_t get_mi2s_rx_clk_val(int port_id)
650{
651 uint32_t clk_val = 0;
652
653 /*
654 * Derive clock value based on sample rate, bits per sample and
655 * channel count is used as 2
656 */
657 if (is_mi2s_rx_port(port_id))
658 clk_val = (mi2s_rx_sample_rate * mi2s_rx_bits_per_sample * 2);
659
660 pr_debug("%s: MI2S Rx bit clock value: 0x%0x\n", __func__, clk_val);
661 return clk_val;
662}
663
664static int msm_mi2s_sclk_ctl(struct snd_pcm_substream *substream, bool enable)
665{
666 int ret = 0;
667 struct snd_soc_pcm_runtime *rtd = substream->private_data;
668 int port_id = 0;
669
670 port_id = msm8952_get_port_id(rtd->dai_link->id);
671 if (port_id < 0) {
672 pr_err("%s: Invalid port_id\n", __func__);
673 return -EINVAL;
674 }
675 if (enable) {
676 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
677 mi2s_rx_clk.enable = enable;
678 mi2s_rx_clk.clk_id =
679 msm8952_get_clk_id(port_id);
680 mi2s_rx_clk.clk_freq_in_hz =
681 get_mi2s_rx_clk_val(port_id);
682 ret = afe_set_lpass_clock_v2(port_id,
683 &mi2s_rx_clk);
684 } else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
685 mi2s_tx_clk.enable = enable;
686 mi2s_tx_clk.clk_id =
687 msm8952_get_clk_id(port_id);
688 mi2s_tx_clk.clk_freq_in_hz =
689 Q6AFE_LPASS_IBIT_CLK_1_P536_MHZ;
690 ret = afe_set_lpass_clock_v2(port_id,
691 &mi2s_tx_clk);
692 } else {
693 pr_err("%s:Not valid substream.\n", __func__);
694 }
695
696 if (ret < 0)
697 pr_err("%s:afe_set_lpass_clock_v2 failed\n", __func__);
698 } else {
699 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
700 mi2s_rx_clk.enable = enable;
701 mi2s_rx_clk.clk_id =
702 msm8952_get_clk_id(port_id);
703 ret = afe_set_lpass_clock_v2(port_id,
704 &mi2s_rx_clk);
705 } else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
706 mi2s_tx_clk.enable = enable;
707 mi2s_tx_clk.clk_id =
708 msm8952_get_clk_id(port_id);
709 ret = afe_set_lpass_clock_v2(port_id,
710 &mi2s_tx_clk);
711 } else {
712 pr_err("%s:Not valid substream.\n", __func__);
713 }
714
715 if (ret < 0)
716 pr_err("%s:afe_set_lpass_clock_v2 failed\n", __func__);
717 }
718 return ret;
719}
720
721static int msm8952_enable_dig_cdc_clk(struct snd_soc_codec *codec,
722 int enable, bool dapm)
723{
724 int ret = 0;
725 struct msm_asoc_mach_data *pdata = NULL;
726
727 pdata = snd_soc_card_get_drvdata(codec->component.card);
728 pr_debug("%s: enable %d mclk ref counter %d\n",
729 __func__, enable,
730 atomic_read(&pdata->int_mclk0_rsc_ref));
731 if (enable) {
732 if (!atomic_read(&pdata->int_mclk0_rsc_ref)) {
733 cancel_delayed_work_sync(
734 &pdata->disable_int_mclk0_work);
735 mutex_lock(&pdata->cdc_int_mclk0_mutex);
736 if (atomic_read(&pdata->int_mclk0_enabled) == false) {
737 pdata->digital_cdc_core_clk.enable = 1;
738 ret = afe_set_lpass_clock_v2(
739 AFE_PORT_ID_PRIMARY_MI2S_RX,
740 &pdata->digital_cdc_core_clk);
741 if (ret < 0) {
742 pr_err("%s: failed to enable CCLK\n",
743 __func__);
744 mutex_unlock(
745 &pdata->cdc_int_mclk0_mutex);
746 return ret;
747 }
748 pr_debug("enabled digital codec core clk\n");
749 atomic_set(&pdata->int_mclk0_enabled, true);
750 }
751 mutex_unlock(&pdata->cdc_int_mclk0_mutex);
752 }
753 atomic_inc(&pdata->int_mclk0_rsc_ref);
754 } else {
755 cancel_delayed_work_sync(&pdata->disable_int_mclk0_work);
756 mutex_lock(&pdata->cdc_int_mclk0_mutex);
757 if (atomic_read(&pdata->int_mclk0_enabled) == true) {
758 pdata->digital_cdc_core_clk.clk_freq_in_hz =
759 DEFAULT_MCLK_RATE;
760 pdata->digital_cdc_core_clk.enable = 0;
761 ret = afe_set_lpass_clock_v2(
762 AFE_PORT_ID_PRIMARY_MI2S_RX,
763 &pdata->digital_cdc_core_clk);
764 if (ret < 0)
765 pr_err("%s: failed to disable CCLK\n",
766 __func__);
767 atomic_set(&pdata->int_mclk0_enabled, false);
768 atomic_set(&pdata->int_mclk0_rsc_ref, 0);
769 }
770 mutex_unlock(&pdata->cdc_int_mclk0_mutex);
771 }
772 return ret;
773}
774
775static int msm_btsco_rate_get(struct snd_kcontrol *kcontrol,
776 struct snd_ctl_elem_value *ucontrol)
777{
778 pr_debug("%s: msm_btsco_rate = %d", __func__, msm_btsco_rate);
779 ucontrol->value.integer.value[0] = msm_btsco_rate;
780 return 0;
781}
782
783static int msm_btsco_rate_put(struct snd_kcontrol *kcontrol,
784 struct snd_ctl_elem_value *ucontrol)
785{
786 switch (ucontrol->value.integer.value[0]) {
787 case RATE_8KHZ_ID:
788 msm_btsco_rate = BTSCO_RATE_8KHZ;
789 break;
790 case RATE_16KHZ_ID:
791 msm_btsco_rate = BTSCO_RATE_16KHZ;
792 break;
793 default:
794 msm_btsco_rate = BTSCO_RATE_8KHZ;
795 break;
796 }
797
798 pr_debug("%s: msm_btsco_rate = %d\n", __func__, msm_btsco_rate);
799 return 0;
800}
801
802static int mi2s_rx_bit_format_get(struct snd_kcontrol *kcontrol,
803 struct snd_ctl_elem_value *ucontrol)
804{
805
806 switch (mi2s_rx_bit_format) {
807 case SNDRV_PCM_FORMAT_S24_3LE:
808 ucontrol->value.integer.value[0] = 2;
809 break;
810
811 case SNDRV_PCM_FORMAT_S24_LE:
812 ucontrol->value.integer.value[0] = 1;
813 break;
814
815 case SNDRV_PCM_FORMAT_S16_LE:
816 default:
817 ucontrol->value.integer.value[0] = 0;
818 break;
819 }
820
821 pr_debug("%s: mi2s_rx_bit_format = %d, ucontrol value = %ld\n",
822 __func__, mi2s_rx_bit_format,
823 ucontrol->value.integer.value[0]);
824
825 return 0;
826}
827
828static int mi2s_rx_bit_format_put(struct snd_kcontrol *kcontrol,
829 struct snd_ctl_elem_value *ucontrol)
830{
831 switch (ucontrol->value.integer.value[0]) {
832 case 2:
833 mi2s_rx_bit_format = SNDRV_PCM_FORMAT_S24_3LE;
834 mi2s_rx_bits_per_sample = 32;
835 break;
836 case 1:
837 mi2s_rx_bit_format = SNDRV_PCM_FORMAT_S24_LE;
838 mi2s_rx_bits_per_sample = 32;
839 break;
840 case 0:
841 default:
842 mi2s_rx_bit_format = SNDRV_PCM_FORMAT_S16_LE;
843 mi2s_rx_bits_per_sample = 16;
844 break;
845 }
846 return 0;
847}
848
849static int loopback_mclk_get(struct snd_kcontrol *kcontrol,
850 struct snd_ctl_elem_value *ucontrol)
851{
852 pr_debug("%s\n", __func__);
853 return 0;
854}
855
856static int loopback_mclk_put(struct snd_kcontrol *kcontrol,
857 struct snd_ctl_elem_value *ucontrol)
858{
859 int ret = -EINVAL;
860 struct msm_asoc_mach_data *pdata = NULL;
861 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
862
863 pdata = snd_soc_card_get_drvdata(codec->component.card);
864 pr_debug("%s: int_mclk0_rsc_ref %d enable %ld\n",
865 __func__, atomic_read(&pdata->int_mclk0_rsc_ref),
866 ucontrol->value.integer.value[0]);
867 switch (ucontrol->value.integer.value[0]) {
868 case 1:
869 if (pdata->mi2s_gpio_p[PRIM_MI2S]) {
870 ret = msm_cdc_pinctrl_select_active_state(
871 pdata->mi2s_gpio_p[PRIM_MI2S]);
872 if (ret) {
873 pr_err("%s: failed to enable pri gpios: %d\n",
874 __func__, ret);
875 break;
876 }
877 }
878 mutex_lock(&pdata->cdc_int_mclk0_mutex);
879 if ((!atomic_read(&pdata->int_mclk0_rsc_ref)) &&
880 (!atomic_read(&pdata->int_mclk0_enabled))) {
881 pdata->digital_cdc_core_clk.enable = 1;
882 ret = afe_set_lpass_clock_v2(
883 AFE_PORT_ID_PRIMARY_MI2S_RX,
884 &pdata->digital_cdc_core_clk);
885 if (ret < 0) {
886 pr_err("%s: failed to enable the MCLK: %d\n",
887 __func__, ret);
888 mutex_unlock(&pdata->cdc_int_mclk0_mutex);
889 if (pdata->mi2s_gpio_p[PRIM_MI2S]) {
890 ret =
891 msm_cdc_pinctrl_select_sleep_state(
892 pdata->mi2s_gpio_p[PRIM_MI2S]);
893 if (ret)
894 pr_err("%s disable gpio fail\n",
895 __func__);
896 }
897 break;
898 }
899 atomic_set(&pdata->int_mclk0_enabled, true);
900 }
901 mutex_unlock(&pdata->cdc_int_mclk0_mutex);
902 atomic_inc(&pdata->int_mclk0_rsc_ref);
903 msm_anlg_cdc_mclk_enable(codec, 1, true);
904 break;
905 case 0:
906 if (atomic_read(&pdata->int_mclk0_rsc_ref) <= 0)
907 break;
908 msm_anlg_cdc_mclk_enable(codec, 0, true);
909 mutex_lock(&pdata->cdc_int_mclk0_mutex);
910 if ((!atomic_dec_return(&pdata->int_mclk0_rsc_ref)) &&
911 (atomic_read(&pdata->int_mclk0_enabled))) {
912 pdata->digital_cdc_core_clk.enable = 0;
913 ret = afe_set_lpass_clock_v2(
914 AFE_PORT_ID_PRIMARY_MI2S_RX,
915 &pdata->digital_cdc_core_clk);
916 if (ret < 0) {
917 pr_err("%s: failed to disable the CCLK: %d\n",
918 __func__, ret);
919 mutex_unlock(&pdata->cdc_int_mclk0_mutex);
920 break;
921 }
922 atomic_set(&pdata->int_mclk0_enabled, false);
923 }
924 mutex_unlock(&pdata->cdc_int_mclk0_mutex);
925 if (pdata->mi2s_gpio_p[PRIM_MI2S]) {
926 ret = msm_cdc_pinctrl_select_sleep_state(
927 pdata->mi2s_gpio_p[PRIM_MI2S]);
928 if (ret)
929 pr_err("%s: failed to disable pri gpios: %d\n",
930 __func__, ret);
931 }
932 break;
933 default:
934 pr_err("%s: Unexpected input value\n", __func__);
935 break;
936 }
937 return ret;
938}
939
940static int msm_pri_mi2s_rx_ch_get(struct snd_kcontrol *kcontrol,
941 struct snd_ctl_elem_value *ucontrol)
942{
943 pr_debug("%s: msm_pri_mi2s_rx_ch = %d\n", __func__,
944 msm_pri_mi2s_rx_ch);
945 ucontrol->value.integer.value[0] = msm_pri_mi2s_rx_ch - 1;
946 return 0;
947}
948
949static int msm_pri_mi2s_rx_ch_put(struct snd_kcontrol *kcontrol,
950 struct snd_ctl_elem_value *ucontrol)
951{
952 msm_pri_mi2s_rx_ch = ucontrol->value.integer.value[0] + 1;
953
954 pr_debug("%s: msm_pri_mi2s_rx_ch = %d\n", __func__, msm_pri_mi2s_rx_ch);
955 return 1;
956}
957
958static int mi2s_rx_sample_rate_get(struct snd_kcontrol *kcontrol,
959 struct snd_ctl_elem_value *ucontrol)
960{
961 int sample_rate_val = 0;
962
963 switch (mi2s_rx_sample_rate) {
964 case SAMPLING_RATE_96KHZ:
965 sample_rate_val = 1;
966 break;
967 case SAMPLING_RATE_192KHZ:
968 sample_rate_val = 2;
969 break;
970 case SAMPLING_RATE_48KHZ:
971 default:
972 sample_rate_val = 0;
973 break;
974 }
975
976 ucontrol->value.integer.value[0] = sample_rate_val;
977 pr_debug("%s: sample_rate_val = %d\n", __func__,
978 sample_rate_val);
979
980 return 0;
981}
982
983static int mi2s_rx_sample_rate_put(struct snd_kcontrol *kcontrol,
984 struct snd_ctl_elem_value *ucontrol)
985{
986 switch (ucontrol->value.integer.value[0]) {
987 case 1:
988 mi2s_rx_sample_rate = SAMPLING_RATE_96KHZ;
989 break;
990 case 2:
991 mi2s_rx_sample_rate = SAMPLING_RATE_192KHZ;
992 break;
993 case 0:
994 default:
995 mi2s_rx_sample_rate = SAMPLING_RATE_48KHZ;
996 break;
997 }
998 pr_debug("%s: mi2s_rx_sample_rate = %d\n", __func__,
999 mi2s_rx_sample_rate);
1000 return 0;
1001}
1002
1003static int msm_ter_mi2s_tx_ch_get(struct snd_kcontrol *kcontrol,
1004 struct snd_ctl_elem_value *ucontrol)
1005{
1006 pr_debug("%s: msm_ter_mi2s_tx_ch = %d\n", __func__,
1007 msm_ter_mi2s_tx_ch);
1008 ucontrol->value.integer.value[0] = msm_ter_mi2s_tx_ch - 1;
1009 return 0;
1010}
1011
1012static int msm_ter_mi2s_tx_ch_put(struct snd_kcontrol *kcontrol,
1013 struct snd_ctl_elem_value *ucontrol)
1014{
1015 msm_ter_mi2s_tx_ch = ucontrol->value.integer.value[0] + 1;
1016
1017 pr_debug("%s: msm_ter_mi2s_tx_ch = %d\n", __func__, msm_ter_mi2s_tx_ch);
1018 return 1;
1019}
1020
1021static int msm_vi_feed_tx_ch_get(struct snd_kcontrol *kcontrol,
1022 struct snd_ctl_elem_value *ucontrol)
1023{
1024 ucontrol->value.integer.value[0] = (msm_vi_feed_tx_ch/2 - 1);
1025 pr_debug("%s: msm_vi_feed_tx_ch = %ld\n", __func__,
1026 ucontrol->value.integer.value[0]);
1027 return 0;
1028}
1029
1030static int msm_vi_feed_tx_ch_put(struct snd_kcontrol *kcontrol,
1031 struct snd_ctl_elem_value *ucontrol)
1032{
1033 msm_vi_feed_tx_ch =
1034 roundup_pow_of_two(ucontrol->value.integer.value[0] + 2);
1035
1036 pr_debug("%s: msm_vi_feed_tx_ch = %d\n", __func__, msm_vi_feed_tx_ch);
1037 return 1;
1038}
1039
1040static const struct soc_enum msm_snd_enum[] = {
1041 SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(rx_bit_format_text),
1042 rx_bit_format_text),
1043 SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(mi2s_ch_text),
1044 mi2s_ch_text),
1045 SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(loopback_mclk_text),
1046 loopback_mclk_text),
1047 SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(btsco_rate_text),
1048 btsco_rate_text),
1049 SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(proxy_rx_ch_text),
1050 proxy_rx_ch_text),
1051 SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(vi_feed_ch_text),
1052 vi_feed_ch_text),
1053 SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(mi2s_rx_sample_rate_text),
1054 mi2s_rx_sample_rate_text),
1055};
1056
1057static const struct snd_kcontrol_new msm_snd_controls[] = {
1058 SOC_ENUM_EXT("MI2S_RX Format", msm_snd_enum[0],
1059 mi2s_rx_bit_format_get, mi2s_rx_bit_format_put),
1060 SOC_ENUM_EXT("MI2S_TX Channels", msm_snd_enum[1],
1061 msm_ter_mi2s_tx_ch_get, msm_ter_mi2s_tx_ch_put),
1062 SOC_ENUM_EXT("MI2S_RX Channels", msm_snd_enum[1],
1063 msm_pri_mi2s_rx_ch_get, msm_pri_mi2s_rx_ch_put),
1064 SOC_ENUM_EXT("Loopback MCLK", msm_snd_enum[2],
1065 loopback_mclk_get, loopback_mclk_put),
1066 SOC_ENUM_EXT("Internal BTSCO SampleRate", msm_snd_enum[3],
1067 msm_btsco_rate_get, msm_btsco_rate_put),
1068 SOC_ENUM_EXT("PROXY_RX Channels", msm_snd_enum[4],
1069 msm_proxy_rx_ch_get, msm_proxy_rx_ch_put),
1070 SOC_ENUM_EXT("VI_FEED_TX Channels", msm_snd_enum[5],
1071 msm_vi_feed_tx_ch_get, msm_vi_feed_tx_ch_put),
1072 SOC_ENUM_EXT("MI2S_RX SampleRate", msm_snd_enum[6],
1073 mi2s_rx_sample_rate_get, mi2s_rx_sample_rate_put),
1074};
1075
1076static int msm8952_enable_wsa_mclk(struct snd_soc_card *card, bool enable)
1077{
1078 int ret = 0;
1079 struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
1080
1081 mutex_lock(&pdata->wsa_mclk_mutex);
1082 if (enable) {
1083 if (!atomic_read(&pdata->wsa_int_mclk0_rsc_ref)) {
1084 wsa_ana_clk.enable = enable;
1085 ret = afe_set_lpass_clock_v2(
1086 AFE_PORT_ID_PRIMARY_MI2S_RX,
1087 &wsa_ana_clk);
1088 if (ret < 0) {
1089 pr_err("%s: failed to enable mclk %d\n",
1090 __func__, ret);
1091 goto done;
1092 }
1093 }
1094 atomic_inc(&pdata->wsa_int_mclk0_rsc_ref);
1095 } else {
1096 if (!atomic_read(&pdata->wsa_int_mclk0_rsc_ref))
1097 goto done;
1098 if (!atomic_dec_return(&pdata->wsa_int_mclk0_rsc_ref)) {
1099 wsa_ana_clk.enable = enable;
1100 ret = afe_set_lpass_clock_v2(
1101 AFE_PORT_ID_PRIMARY_MI2S_RX,
1102 &wsa_ana_clk);
1103 if (ret < 0) {
1104 pr_err("%s: failed to disable mclk %d\n",
1105 __func__, ret);
1106 goto done;
1107 }
1108 }
1109 }
1110
1111done:
1112 mutex_unlock(&pdata->wsa_mclk_mutex);
1113 return ret;
1114}
1115
1116static int msm_mi2s_snd_startup(struct snd_pcm_substream *substream)
1117{
1118 struct snd_soc_pcm_runtime *rtd = substream->private_data;
1119 struct snd_soc_card *card = rtd->card;
1120 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
1121 struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
1122 int ret = 0, val = 0;
1123
1124 pr_debug("%s(): substream = %s stream = %d\n", __func__,
1125 substream->name, substream->stream);
1126
1127 if (!q6core_is_adsp_ready()) {
1128 pr_err("%s(): adsp not ready\n", __func__);
1129 return -EINVAL;
1130 }
1131
1132 /*
1133 * configure the slave select to
1134 * invalid state for internal codec
1135 */
1136 if (pdata->vaddr_gpio_mux_spkr_ctl) {
1137 val = ioread32(pdata->vaddr_gpio_mux_spkr_ctl);
1138 val = val | 0x00010000;
1139 iowrite32(val, pdata->vaddr_gpio_mux_spkr_ctl);
1140 }
1141
1142 if (pdata->vaddr_gpio_mux_mic_ctl) {
1143 val = ioread32(pdata->vaddr_gpio_mux_mic_ctl);
1144 val = val | 0x00200000;
1145 iowrite32(val, pdata->vaddr_gpio_mux_mic_ctl);
1146 }
1147
1148 ret = msm_mi2s_sclk_ctl(substream, true);
1149 if (ret < 0) {
1150 pr_err("%s: failed to enable sclk %d\n",
1151 __func__, ret);
1152 return ret;
1153 }
1154 if (card->aux_dev && substream->stream ==
1155 SNDRV_PCM_STREAM_PLAYBACK) {
1156 ret = msm8952_enable_wsa_mclk(card, true);
1157 if (ret < 0) {
1158 pr_err("%s: failed to enable mclk for wsa %d\n",
1159 __func__, ret);
1160 return ret;
1161 }
1162 }
1163 ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_CBS_CFS);
1164 if (ret < 0)
1165 pr_err("%s: set fmt cpu dai failed; ret=%d\n", __func__, ret);
1166
1167 return ret;
1168}
1169
1170static void msm_mi2s_snd_shutdown(struct snd_pcm_substream *substream)
1171{
1172 int ret;
1173 struct snd_soc_pcm_runtime *rtd = substream->private_data;
1174 struct snd_soc_card *card = rtd->card;
1175
1176 pr_debug("%s(): substream = %s stream = %d\n", __func__,
1177 substream->name, substream->stream);
1178
1179 ret = msm_mi2s_sclk_ctl(substream, false);
1180 if (ret < 0)
1181 pr_err("%s:clock disable failed; ret=%d\n", __func__,
1182 ret);
1183 if (card->aux_dev && substream->stream ==
1184 SNDRV_PCM_STREAM_PLAYBACK) {
1185 ret = msm8952_enable_wsa_mclk(card, false);
1186 if (ret < 0) {
1187 pr_err("%s: failed to disable mclk for wsa %d\n",
1188 __func__, ret);
1189 }
1190 }
1191}
1192
1193static int msm_prim_auxpcm_startup(struct snd_pcm_substream *substream)
1194{
1195 struct snd_soc_pcm_runtime *rtd = substream->private_data;
1196 struct snd_soc_codec *dig_cdc = rtd->codec_dais[DIG_CDC]->codec;
1197 struct snd_soc_card *card = rtd->card;
1198 struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
1199 int ret = 0, val = 0;
1200
1201 pr_debug("%s(): substream = %s\n",
1202 __func__, substream->name);
1203
1204 if (!q6core_is_adsp_ready()) {
1205 pr_err("%s(): adsp not ready\n", __func__);
1206 return -EINVAL;
1207 }
1208
1209 /* mux config to route the AUX MI2S */
1210 if (pdata->vaddr_gpio_mux_mic_ctl) {
1211 val = ioread32(pdata->vaddr_gpio_mux_mic_ctl);
1212 val = val | 0x2;
1213 iowrite32(val, pdata->vaddr_gpio_mux_mic_ctl);
1214 }
1215 if (pdata->vaddr_gpio_mux_pcm_ctl) {
1216 val = ioread32(pdata->vaddr_gpio_mux_pcm_ctl);
1217 val = val | 0x1;
1218 iowrite32(val, pdata->vaddr_gpio_mux_pcm_ctl);
1219 }
1220 msm8952_enable_dig_cdc_clk(dig_cdc, 1, true);
1221 atomic_inc(&auxpcm_mi2s_clk_ref);
1222
1223 /* enable the gpio's used for the external AUXPCM interface */
1224 if (pdata->mi2s_gpio_p[QUAT_MI2S]) {
1225 ret = msm_cdc_pinctrl_select_active_state(
1226 pdata->mi2s_gpio_p[QUAT_MI2S]);
1227 if (ret < 0)
1228 pr_err("%s(): configure gpios failed = %s\n",
1229 __func__, "quat_i2s");
1230 }
1231 return ret;
1232}
1233
1234static void msm_prim_auxpcm_shutdown(struct snd_pcm_substream *substream)
1235{
1236 int ret;
1237 struct snd_soc_pcm_runtime *rtd = substream->private_data;
1238 struct snd_soc_card *card = rtd->card;
1239 struct snd_soc_codec *dig_cdc = rtd->codec_dais[DIG_CDC]->codec;
1240 struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
1241
1242 pr_debug("%s(): substream = %s\n",
1243 __func__, substream->name);
1244 if (atomic_read(&pdata->int_mclk0_rsc_ref) > 0) {
1245 atomic_dec(&pdata->int_mclk0_rsc_ref);
1246 pr_debug("%s: decrementing mclk_res_ref %d\n",
1247 __func__, atomic_read(&pdata->int_mclk0_rsc_ref));
1248 }
1249 if (atomic_read(&auxpcm_mi2s_clk_ref) > 0)
1250 atomic_dec(&auxpcm_mi2s_clk_ref);
1251 if ((atomic_read(&auxpcm_mi2s_clk_ref) == 0) &&
1252 (atomic_read(&pdata->int_mclk0_rsc_ref) == 0)) {
1253 msm8952_enable_dig_cdc_clk(dig_cdc, 0, true);
1254 }
1255 if (pdata->mi2s_gpio_p[QUAT_MI2S]) {
1256 ret = msm_cdc_pinctrl_select_sleep_state(
1257 pdata->mi2s_gpio_p[QUAT_MI2S]);
1258 if (ret < 0)
1259 pr_err("%s(): configure gpios failed = %s\n",
1260 __func__, "quat_i2s");
1261 }
1262}
1263
1264static int msm_sec_mi2s_snd_startup(struct snd_pcm_substream *substream)
1265{
1266 struct snd_soc_pcm_runtime *rtd = substream->private_data;
1267 struct snd_soc_card *card = rtd->card;
1268 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
1269 struct msm_asoc_mach_data *pdata =
1270 snd_soc_card_get_drvdata(card);
1271 int ret = 0, val = 0;
1272
1273 pr_debug("%s(): substream = %s stream = %d\n", __func__,
1274 substream->name, substream->stream);
1275
1276 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
1277 pr_info("%s: Secondary Mi2s does not support capture\n",
1278 __func__);
1279 return 0;
1280 }
1281
1282 if (!q6core_is_adsp_ready()) {
1283 pr_err("%s(): adsp not ready\n", __func__);
1284 return -EINVAL;
1285 }
1286
1287 if ((pdata->ext_pa & SEC_MI2S_ID) == SEC_MI2S_ID) {
1288 if (pdata->vaddr_gpio_mux_spkr_ctl) {
1289 val = ioread32(pdata->vaddr_gpio_mux_spkr_ctl);
1290 val = val | 0x0004835c;
1291 iowrite32(val, pdata->vaddr_gpio_mux_spkr_ctl);
1292 }
1293 ret = msm_mi2s_sclk_ctl(substream, true);
1294 if (ret < 0) {
1295 pr_err("failed to enable sclk\n");
1296 return ret;
1297 }
1298 pr_debug("%s(): SEC I2S gpios turned on = %s\n", __func__,
1299 "sec_i2s");
1300 if (pdata->mi2s_gpio_p[SEC_MI2S]) {
1301 ret = msm_cdc_pinctrl_select_active_state(
1302 pdata->mi2s_gpio_p[SEC_MI2S]);
1303 if (ret < 0) {
1304 pr_err("%s: gpio set cannot be activated %sd",
1305 __func__, "sec_i2s");
1306 goto err;
1307 }
1308 }
1309 } else {
1310 pr_err("%s: error codec type\n", __func__);
1311 }
1312 ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_CBS_CFS);
1313 if (ret < 0) {
1314 pr_err("%s: set fmt cpu dai failed\n", __func__);
1315 if (pdata->mi2s_gpio_p[SEC_MI2S]) {
1316 ret = msm_cdc_pinctrl_select_sleep_state(
1317 pdata->mi2s_gpio_p[SEC_MI2S]);
1318 if (ret < 0) {
1319 pr_err("%s: gpio de-activate error %s",
1320 __func__, "sec_i2s");
1321 goto err;
1322 }
1323 }
1324 }
1325 return ret;
1326err:
1327 ret = msm_mi2s_sclk_ctl(substream, false);
1328 if (ret < 0)
1329 pr_err("failed to disable sclk\n");
1330 return ret;
1331}
1332
1333static void msm_sec_mi2s_snd_shutdown(struct snd_pcm_substream *substream)
1334{
1335 int ret;
1336 struct snd_soc_pcm_runtime *rtd = substream->private_data;
1337 struct snd_soc_card *card = rtd->card;
1338 struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
1339
1340 pr_debug("%s(): substream = %s stream = %d\n", __func__,
1341 substream->name, substream->stream);
1342 if ((pdata->ext_pa & SEC_MI2S_ID) == SEC_MI2S_ID) {
1343 if (pdata->mi2s_gpio_p[SEC_MI2S]) {
1344 ret = msm_cdc_pinctrl_select_sleep_state(
1345 pdata->mi2s_gpio_p[SEC_MI2S]);
1346 if (ret < 0) {
1347 pr_err("%s: gpio set cannot be de-activated: %sd",
1348 __func__, "sec_i2s");
1349 return;
1350 }
1351 }
1352 ret = msm_mi2s_sclk_ctl(substream, false);
1353 if (ret < 0)
1354 pr_err("%s:clock disable failed\n", __func__);
1355 }
1356}
1357
1358static int msm_quat_mi2s_snd_startup(struct snd_pcm_substream *substream)
1359{
1360 struct snd_soc_pcm_runtime *rtd = substream->private_data;
1361 struct snd_soc_card *card = rtd->card;
1362 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
1363 struct msm_asoc_mach_data *pdata =
1364 snd_soc_card_get_drvdata(card);
1365 int ret = 0, val = 0;
1366
1367 pr_debug("%s(): substream = %s stream = %d\n", __func__,
1368 substream->name, substream->stream);
1369
1370 if (!q6core_is_adsp_ready()) {
1371 pr_err("%s(): adsp not ready\n", __func__);
1372 return -EINVAL;
1373 }
1374
1375 if (pdata->vaddr_gpio_mux_mic_ctl) {
1376 val = ioread32(pdata->vaddr_gpio_mux_mic_ctl);
1377 val = val | 0x02020002;
1378 iowrite32(val, pdata->vaddr_gpio_mux_mic_ctl);
1379 }
1380 ret = msm_mi2s_sclk_ctl(substream, true);
1381 if (ret < 0) {
1382 pr_err("failed to enable sclk\n");
1383 return ret;
1384 }
1385 if (pdata->mi2s_gpio_p[QUAT_MI2S]) {
1386 ret = msm_cdc_pinctrl_select_active_state(
1387 pdata->mi2s_gpio_p[QUAT_MI2S]);
1388 if (ret < 0) {
1389 pr_err("failed to enable codec gpios\n");
1390 goto err;
1391 }
1392 }
1393 if (atomic_inc_return(&quat_mi2s_clk_ref) == 1) {
1394 ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_CBS_CFS);
1395 if (ret < 0)
1396 pr_err("%s: set fmt cpu dai failed\n", __func__);
1397 }
1398 return ret;
1399err:
1400 ret = msm_mi2s_sclk_ctl(substream, false);
1401 if (ret < 0)
1402 pr_err("failed to disable sclk\n");
1403 return ret;
1404}
1405
1406static void msm_quat_mi2s_snd_shutdown(struct snd_pcm_substream *substream)
1407{
1408 struct snd_soc_pcm_runtime *rtd = substream->private_data;
1409 struct snd_soc_card *card = rtd->card;
1410 struct msm_asoc_mach_data *pdata =
1411 snd_soc_card_get_drvdata(card);
1412 int ret = 0;
1413
1414 pr_debug("%s(): substream = %s stream = %d\n", __func__,
1415 substream->name, substream->stream);
1416 ret = msm_mi2s_sclk_ctl(substream, false);
1417 if (ret < 0)
1418 pr_err("%s:clock disable failed\n", __func__);
1419 if (atomic_read(&quat_mi2s_clk_ref) > 0)
1420 atomic_dec(&quat_mi2s_clk_ref);
1421 if (pdata->mi2s_gpio_p[QUAT_MI2S]) {
1422 ret = msm_cdc_pinctrl_select_sleep_state(
1423 pdata->mi2s_gpio_p[QUAT_MI2S]);
1424 if (ret < 0) {
1425 pr_err("%s: gpio set cannot be de-activated %sd",
1426 __func__, "quat_i2s");
1427 return;
1428 }
1429 }
1430}
1431
1432static int msm_quin_mi2s_snd_startup(struct snd_pcm_substream *substream)
1433{
1434 struct snd_soc_pcm_runtime *rtd = substream->private_data;
1435 struct snd_soc_card *card = rtd->card;
1436 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
1437 struct msm_asoc_mach_data *pdata =
1438 snd_soc_card_get_drvdata(card);
1439 int ret = 0, val = 0;
1440
1441 pr_debug("%s(): substream = %s stream = %d\n", __func__,
1442 substream->name, substream->stream);
1443
1444 if (!q6core_is_adsp_ready()) {
1445 pr_err("%s(): adsp not ready\n", __func__);
1446 return -EINVAL;
1447 }
1448
1449 if (pdata->vaddr_gpio_mux_quin_ctl) {
1450 val = ioread32(pdata->vaddr_gpio_mux_quin_ctl);
1451 val = val | 0x00000001;
1452 iowrite32(val, pdata->vaddr_gpio_mux_quin_ctl);
1453 } else {
1454 return -EINVAL;
1455 }
1456 ret = msm_mi2s_sclk_ctl(substream, true);
1457 if (ret < 0) {
1458 pr_err("failed to enable sclk\n");
1459 return ret;
1460 }
1461 if (pdata->mi2s_gpio_p[QUIN_MI2S]) {
1462 ret = msm_cdc_pinctrl_select_active_state(
1463 pdata->mi2s_gpio_p[QUIN_MI2S]);
1464 if (ret < 0) {
1465 pr_err("failed to enable codec gpios\n");
1466 goto err;
1467 }
1468 }
1469 if (atomic_inc_return(&quin_mi2s_clk_ref) == 1) {
1470 ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_CBS_CFS);
1471 if (ret < 0)
1472 pr_err("%s: set fmt cpu dai failed\n", __func__);
1473 }
1474 return ret;
1475err:
1476 ret = msm_mi2s_sclk_ctl(substream, false);
1477 if (ret < 0)
1478 pr_err("failed to disable sclk\n");
1479 return ret;
1480}
1481
1482static void msm_quin_mi2s_snd_shutdown(struct snd_pcm_substream *substream)
1483{
1484 struct snd_soc_pcm_runtime *rtd = substream->private_data;
1485 struct snd_soc_card *card = rtd->card;
1486 struct msm_asoc_mach_data *pdata =
1487 snd_soc_card_get_drvdata(card);
1488 int ret = 0;
1489
1490 pr_debug("%s(): substream = %s stream = %d\n", __func__,
1491 substream->name, substream->stream);
1492 ret = msm_mi2s_sclk_ctl(substream, false);
1493 if (ret < 0)
1494 pr_err("%s:clock disable failed\n", __func__);
1495 if (atomic_read(&quin_mi2s_clk_ref) > 0)
1496 atomic_dec(&quin_mi2s_clk_ref);
1497 if (pdata->mi2s_gpio_p[QUIN_MI2S]) {
1498 ret = msm_cdc_pinctrl_select_sleep_state(
1499 pdata->mi2s_gpio_p[QUIN_MI2S]);
1500 if (ret < 0) {
1501 pr_err("%s: gpio set cannot be de-activated %sd",
1502 __func__, "quin_i2s");
1503 return;
1504 }
1505 }
1506}
1507
1508static void *def_msm8952_wcd_mbhc_cal(void)
1509{
1510 void *msm8952_wcd_cal;
1511 struct wcd_mbhc_btn_detect_cfg *btn_cfg;
1512 u16 *btn_low, *btn_high;
1513
1514 msm8952_wcd_cal = kzalloc(WCD_MBHC_CAL_SIZE(WCD_MBHC_DEF_BUTTONS,
1515 WCD_MBHC_DEF_RLOADS), GFP_KERNEL);
1516 if (!msm8952_wcd_cal)
1517 return NULL;
1518
1519#define S(X, Y) ((WCD_MBHC_CAL_PLUG_TYPE_PTR(msm8952_wcd_cal)->X) = (Y))
1520 S(v_hs_max, 1500);
1521#undef S
1522#define S(X, Y) ((WCD_MBHC_CAL_BTN_DET_PTR(msm8952_wcd_cal)->X) = (Y))
1523 S(num_btn, WCD_MBHC_DEF_BUTTONS);
1524#undef S
1525
1526
1527 btn_cfg = WCD_MBHC_CAL_BTN_DET_PTR(msm8952_wcd_cal);
1528 btn_low = btn_cfg->_v_btn_low;
1529 btn_high = ((void *)&btn_cfg->_v_btn_low) +
1530 (sizeof(btn_cfg->_v_btn_low[0]) * btn_cfg->num_btn);
1531
1532 /*
1533 * In SW we are maintaining two sets of threshold register
1534 * one for current source and another for Micbias.
1535 * all btn_low corresponds to threshold for current source
1536 * all bt_high corresponds to threshold for Micbias
1537 * Below thresholds are based on following resistances
1538 * 0-70 == Button 0
1539 * 110-180 == Button 1
1540 * 210-290 == Button 2
1541 * 360-680 == Button 3
1542 */
1543 btn_low[0] = 75;
1544 btn_high[0] = 75;
1545 btn_low[1] = 150;
1546 btn_high[1] = 150;
1547 btn_low[2] = 225;
1548 btn_high[2] = 225;
1549 btn_low[3] = 450;
1550 btn_high[3] = 450;
1551 btn_low[4] = 500;
1552 btn_high[4] = 500;
1553
1554 return msm8952_wcd_cal;
1555}
1556
1557static int msm_audrx_init(struct snd_soc_pcm_runtime *rtd)
1558{
1559 struct snd_soc_codec *dig_cdc = rtd->codec_dais[DIG_CDC]->codec;
1560 struct snd_soc_codec *ana_cdc = rtd->codec_dais[ANA_CDC]->codec;
1561 struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(ana_cdc);
1562 struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(rtd->card);
1563 struct snd_card *card;
1564 int ret = -ENOMEM;
1565
1566 snd_soc_add_codec_controls(ana_cdc, msm_snd_controls,
1567 ARRAY_SIZE(msm_snd_controls));
1568 snd_soc_dapm_new_controls(dapm, msm8952_dapm_widgets,
1569 ARRAY_SIZE(msm8952_dapm_widgets));
1570
1571 snd_soc_dapm_ignore_suspend(dapm, "Handset Mic");
1572 snd_soc_dapm_ignore_suspend(dapm, "Headset Mic");
1573 snd_soc_dapm_ignore_suspend(dapm, "Secondary Mic");
1574 snd_soc_dapm_ignore_suspend(dapm, "Digital Mic1");
1575 snd_soc_dapm_ignore_suspend(dapm, "Digital Mic2");
1576
1577 snd_soc_dapm_ignore_suspend(dapm, "EAR");
1578 snd_soc_dapm_ignore_suspend(dapm, "HEADPHONE");
1579 snd_soc_dapm_ignore_suspend(dapm, "SPK_OUT");
1580 snd_soc_dapm_ignore_suspend(dapm, "AMIC1");
1581 snd_soc_dapm_ignore_suspend(dapm, "AMIC2");
1582 snd_soc_dapm_ignore_suspend(dapm, "AMIC3");
1583 snd_soc_dapm_ignore_suspend(dapm, "DMIC1");
1584 snd_soc_dapm_ignore_suspend(dapm, "DMIC2");
1585 snd_soc_dapm_ignore_suspend(dapm, "WSA_SPK OUT");
1586 snd_soc_dapm_ignore_suspend(dapm, "LINEOUT");
1587
1588 snd_soc_dapm_sync(dapm);
1589
1590 msm_anlg_cdc_spk_ext_pa_cb(enable_spk_ext_pa, ana_cdc);
1591 msm_dig_cdc_hph_comp_cb(config_hph_compander_gpio, dig_cdc);
1592
1593 mbhc_cfg.calibration = def_msm8952_wcd_mbhc_cal();
1594 if (mbhc_cfg.calibration) {
1595 ret = msm_anlg_cdc_hs_detect(ana_cdc, &mbhc_cfg);
1596 if (ret) {
1597 kfree(mbhc_cfg.calibration);
1598 return ret;
1599 }
1600 }
1601 card = rtd->card->snd_card;
1602 if (!codec_root)
1603 codec_root = snd_info_create_subdir(card->module, "codecs",
1604 card->proc_root);
1605 if (!codec_root) {
1606 pr_debug("%s: Cannot create codecs module entry\n", __func__);
1607 goto done;
1608 }
1609 pdata->codec_root = codec_root;
1610 msm_dig_codec_info_create_codec_entry(codec_root, dig_cdc);
1611 msm_anlg_codec_info_create_codec_entry(codec_root, ana_cdc);
1612done:
1613 return 0;
1614}
1615
1616static struct snd_soc_ops msm8952_quat_mi2s_be_ops = {
1617 .startup = msm_quat_mi2s_snd_startup,
1618 .hw_params = msm_mi2s_snd_hw_params,
1619 .shutdown = msm_quat_mi2s_snd_shutdown,
1620};
1621
1622static struct snd_soc_ops msm8952_quin_mi2s_be_ops = {
1623 .startup = msm_quin_mi2s_snd_startup,
1624 .hw_params = msm_mi2s_snd_hw_params,
1625 .shutdown = msm_quin_mi2s_snd_shutdown,
1626};
1627
1628static struct snd_soc_ops msm8952_sec_mi2s_be_ops = {
1629 .startup = msm_sec_mi2s_snd_startup,
1630 .hw_params = msm_mi2s_snd_hw_params,
1631 .shutdown = msm_sec_mi2s_snd_shutdown,
1632};
1633
1634static struct snd_soc_ops msm8952_mi2s_be_ops = {
1635 .startup = msm_mi2s_snd_startup,
1636 .hw_params = msm_mi2s_snd_hw_params,
1637 .shutdown = msm_mi2s_snd_shutdown,
1638};
1639
1640static struct snd_soc_ops msm_pri_auxpcm_be_ops = {
1641 .startup = msm_prim_auxpcm_startup,
1642 .shutdown = msm_prim_auxpcm_shutdown,
1643};
1644
1645struct snd_soc_dai_link_component dlc_rx1[] = {
1646 {
1647 .of_node = NULL,
1648 .dai_name = "msm_dig_cdc_dai_rx1",
1649 },
1650 {
1651 .of_node = NULL,
1652 .dai_name = "msm_anlg_cdc_i2s_rx1",
1653 },
1654};
1655
1656struct snd_soc_dai_link_component dlc_tx1[] = {
1657 {
1658 .of_node = NULL,
1659 .dai_name = "msm_dig_cdc_dai_tx1",
1660 },
1661 {
1662 .of_node = NULL,
1663 .dai_name = "msm_anlg_cdc_i2s_tx1",
1664 },
1665};
1666
1667struct snd_soc_dai_link_component dlc_vifeed[] = {
1668 {
1669 .of_node = NULL,
1670 .dai_name = "msm_dig_cdc_dai_vifeed",
1671 },
1672 {
1673 .of_node = NULL,
1674 .dai_name = "msm_anlg_vifeedback",
1675 },
1676};
1677
1678/* Digital audio interface glue - connects codec <---> CPU */
1679static struct snd_soc_dai_link msm8952_dai[] = {
1680 /* FrontEnd DAI Links */
1681 {/* hw:x,0 */
1682 .name = "MSM8952 Media1",
1683 .stream_name = "MultiMedia1",
1684 .cpu_dai_name = "MultiMedia1",
1685 .platform_name = "msm-pcm-dsp.0",
1686 .dynamic = 1,
1687 .async_ops = ASYNC_DPCM_SND_SOC_PREPARE,
1688 .dpcm_playback = 1,
1689 .dpcm_capture = 1,
1690 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
1691 SND_SOC_DPCM_TRIGGER_POST},
1692 .codec_dai_name = "snd-soc-dummy-dai",
1693 .codec_name = "snd-soc-dummy",
1694 .ignore_suspend = 1,
1695 /* this dainlink has playback support */
1696 .ignore_pmdown_time = 1,
1697 .id = MSM_FRONTEND_DAI_MULTIMEDIA1
1698 },
1699 {/* hw:x,1 */
1700 .name = "MSM8952 Media2",
1701 .stream_name = "MultiMedia2",
1702 .cpu_dai_name = "MultiMedia2",
1703 .platform_name = "msm-pcm-dsp.0",
1704 .dynamic = 1,
1705 .dpcm_playback = 1,
1706 .dpcm_capture = 1,
1707 .codec_dai_name = "snd-soc-dummy-dai",
1708 .codec_name = "snd-soc-dummy",
1709 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
1710 SND_SOC_DPCM_TRIGGER_POST},
1711 .ignore_suspend = 1,
1712 /* this dainlink has playback support */
1713 .ignore_pmdown_time = 1,
1714 .id = MSM_FRONTEND_DAI_MULTIMEDIA2,
1715 },
1716 {/* hw:x,2 */
1717 .name = "Circuit-Switch Voice",
1718 .stream_name = "CS-Voice",
1719 .cpu_dai_name = "VoiceMMode1",
1720 .platform_name = "msm-pcm-voice",
1721 .dynamic = 1,
1722 .dpcm_playback = 1,
1723 .dpcm_capture = 1,
1724 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
1725 SND_SOC_DPCM_TRIGGER_POST},
1726 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
1727 .ignore_suspend = 1,
1728 /* this dainlink has playback support */
1729 .ignore_pmdown_time = 1,
1730 .id = MSM_FRONTEND_DAI_CS_VOICE,
1731 .codec_dai_name = "snd-soc-dummy-dai",
1732 .codec_name = "snd-soc-dummy",
1733 },
1734 {/* hw:x,3 */
1735 .name = "MSM VoIP",
1736 .stream_name = "VoIP",
1737 .cpu_dai_name = "VoIP",
1738 .platform_name = "msm-voip-dsp",
1739 .dynamic = 1,
1740 .dpcm_playback = 1,
1741 .dpcm_capture = 1,
1742 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
1743 SND_SOC_DPCM_TRIGGER_POST},
1744 .codec_dai_name = "snd-soc-dummy-dai",
1745 .codec_name = "snd-soc-dummy",
1746 .ignore_suspend = 1,
1747 /* this dainlink has playback support */
1748 .ignore_pmdown_time = 1,
1749 .id = MSM_FRONTEND_DAI_VOIP,
1750 },
1751 {/* hw:x,4 */
1752 .name = "MSM8X16 ULL",
1753 .stream_name = "ULL",
1754 .cpu_dai_name = "MultiMedia3",
1755 .platform_name = "msm-pcm-dsp.2",
1756 .dynamic = 1,
1757 .async_ops = ASYNC_DPCM_SND_SOC_PREPARE,
1758 .dpcm_playback = 1,
1759 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
1760 SND_SOC_DPCM_TRIGGER_POST},
1761 .codec_dai_name = "snd-soc-dummy-dai",
1762 .codec_name = "snd-soc-dummy",
1763 .ignore_suspend = 1,
1764 /* this dainlink has playback support */
1765 .ignore_pmdown_time = 1,
1766 .id = MSM_FRONTEND_DAI_MULTIMEDIA3,
1767 },
1768 /* Hostless PCM purpose */
1769 {/* hw:x,5 */
1770 .name = "Primary MI2S_RX Hostless",
1771 .stream_name = "Primary MI2S_RX Hostless",
1772 .cpu_dai_name = "PRI_MI2S_RX_HOSTLESS",
1773 .platform_name = "msm-pcm-hostless",
1774 .dynamic = 1,
1775 .dpcm_playback = 1,
1776 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
1777 SND_SOC_DPCM_TRIGGER_POST},
1778 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
1779 .ignore_suspend = 1,
1780 /* this dailink has playback support */
1781 .ignore_pmdown_time = 1,
1782 /* This dainlink has MI2S support */
1783 .codec_dai_name = "snd-soc-dummy-dai",
1784 .codec_name = "snd-soc-dummy",
1785 },
1786 {/* hw:x,6 */
1787 .name = "INT_FM Hostless",
1788 .stream_name = "INT_FM Hostless",
1789 .cpu_dai_name = "INT_FM_HOSTLESS",
1790 .platform_name = "msm-pcm-hostless",
1791 .dynamic = 1,
1792 .dpcm_capture = 1,
1793 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
1794 SND_SOC_DPCM_TRIGGER_POST},
1795 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
1796 .ignore_suspend = 1,
1797 /* this dainlink has playback support */
1798 .ignore_pmdown_time = 1,
1799 .codec_dai_name = "snd-soc-dummy-dai",
1800 .codec_name = "snd-soc-dummy",
1801 },
1802 {/* hw:x,7 */
1803 .name = "MSM AFE-PCM RX",
1804 .stream_name = "AFE-PROXY RX",
1805 .cpu_dai_name = "msm-dai-q6-dev.241",
1806 .codec_name = "msm-stub-codec.1",
1807 .codec_dai_name = "msm-stub-rx",
1808 .platform_name = "msm-pcm-afe",
1809 .ignore_suspend = 1,
1810 /* this dainlink has playback support */
1811 .ignore_pmdown_time = 1,
1812 },
1813 {/* hw:x,8 */
1814 .name = "MSM AFE-PCM TX",
1815 .stream_name = "AFE-PROXY TX",
1816 .cpu_dai_name = "msm-dai-q6-dev.240",
1817 .codec_name = "msm-stub-codec.1",
1818 .codec_dai_name = "msm-stub-tx",
1819 .platform_name = "msm-pcm-afe",
1820 .ignore_suspend = 1,
1821 },
1822 {/* hw:x,9 */
1823 .name = "MSM8952 Compress1",
1824 .stream_name = "Compress1",
1825 .cpu_dai_name = "MultiMedia4",
1826 .platform_name = "msm-compress-dsp",
1827 .dynamic = 1,
1828 .async_ops = ASYNC_DPCM_SND_SOC_HW_PARAMS,
1829 .dpcm_playback = 1,
1830 .dpcm_capture = 1,
1831 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
1832 SND_SOC_DPCM_TRIGGER_POST},
1833 .codec_dai_name = "snd-soc-dummy-dai",
1834 .codec_name = "snd-soc-dummy",
1835 .ignore_suspend = 1,
1836 .ignore_pmdown_time = 1,
1837 /* this dainlink has playback support */
1838 .id = MSM_FRONTEND_DAI_MULTIMEDIA4,
1839 },
1840 {/* hw:x,10 */
1841 .name = "AUXPCM Hostless",
1842 .stream_name = "AUXPCM Hostless",
1843 .cpu_dai_name = "AUXPCM_HOSTLESS",
1844 .platform_name = "msm-pcm-hostless",
1845 .dynamic = 1,
1846 .dpcm_playback = 1,
1847 .dpcm_capture = 1,
1848 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
1849 SND_SOC_DPCM_TRIGGER_POST},
1850 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
1851 .ignore_suspend = 1,
1852 /* this dainlink has playback support */
1853 .ignore_pmdown_time = 1,
1854 .codec_dai_name = "snd-soc-dummy-dai",
1855 .codec_name = "snd-soc-dummy",
1856 },
1857 {/* hw:x,11 */
1858 .name = "Tertiary MI2S_TX Hostless",
1859 .stream_name = "Tertiary MI2S_TX Hostless",
1860 .cpu_dai_name = "TERT_MI2S_TX_HOSTLESS",
1861 .platform_name = "msm-pcm-hostless",
1862 .dynamic = 1,
1863 .dpcm_capture = 1,
1864 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
1865 SND_SOC_DPCM_TRIGGER_POST},
1866 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
1867 .ignore_suspend = 1,
1868 .ignore_pmdown_time = 1, /* dai link has playback support */
1869 .codec_dai_name = "snd-soc-dummy-dai",
1870 .codec_name = "snd-soc-dummy",
1871 },
1872 {/* hw:x,12 */
1873 .name = "MSM8x16 LowLatency",
1874 .stream_name = "MultiMedia5",
1875 .cpu_dai_name = "MultiMedia5",
1876 .platform_name = "msm-pcm-dsp.1",
1877 .dynamic = 1,
1878 .dpcm_playback = 1,
1879 .dpcm_capture = 1,
1880 .async_ops = ASYNC_DPCM_SND_SOC_PREPARE |
1881 ASYNC_DPCM_SND_SOC_HW_PARAMS,
1882 .codec_dai_name = "snd-soc-dummy-dai",
1883 .codec_name = "snd-soc-dummy",
1884 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
1885 SND_SOC_DPCM_TRIGGER_POST},
1886 .ignore_suspend = 1,
1887 /* this dainlink has playback support */
1888 .ignore_pmdown_time = 1,
1889 .id = MSM_FRONTEND_DAI_MULTIMEDIA5,
1890 },
1891 {/* hw:x,13 */
1892 .name = "Voice2",
1893 .stream_name = "Voice2",
1894 .cpu_dai_name = "VoiceMMode1",
1895 .platform_name = "msm-pcm-voice",
1896 .dynamic = 1,
1897 .dpcm_playback = 1,
1898 .dpcm_capture = 1,
1899 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
1900 SND_SOC_DPCM_TRIGGER_POST},
1901 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
1902 .ignore_suspend = 1,
1903 /* this dainlink has playback support */
1904 .ignore_pmdown_time = 1,
1905 .codec_dai_name = "snd-soc-dummy-dai",
1906 .codec_name = "snd-soc-dummy",
1907 .id = MSM_FRONTEND_DAI_VOICE2,
1908 },
1909 {/* hw:x,14 */
1910 .name = "MSM8x16 Media9",
1911 .stream_name = "MultiMedia9",
1912 .cpu_dai_name = "MultiMedia9",
1913 .platform_name = "msm-pcm-dsp.0",
1914 .dynamic = 1,
1915 .dpcm_playback = 1,
1916 .dpcm_capture = 1,
1917 .codec_dai_name = "snd-soc-dummy-dai",
1918 .codec_name = "snd-soc-dummy",
1919 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
1920 SND_SOC_DPCM_TRIGGER_POST},
1921 .ignore_suspend = 1,
1922 /* This dailink has playback support */
1923 .ignore_pmdown_time = 1,
1924 .id = MSM_FRONTEND_DAI_MULTIMEDIA9,
1925 },
1926 { /* hw:x,15 */
1927 .name = "VoLTE",
1928 .stream_name = "VoLTE",
1929 .cpu_dai_name = "VoiceMMode1",
1930 .platform_name = "msm-pcm-voice",
1931 .dynamic = 1,
1932 .dpcm_playback = 1,
1933 .dpcm_capture = 1,
1934 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
1935 SND_SOC_DPCM_TRIGGER_POST},
1936 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
1937 .ignore_suspend = 1,
1938 /* this dainlink has playback support */
1939 .ignore_pmdown_time = 1,
1940 .codec_dai_name = "snd-soc-dummy-dai",
1941 .codec_name = "snd-soc-dummy",
1942 .id = MSM_FRONTEND_DAI_VOLTE,
1943 },
1944 { /* hw:x,16 */
1945 .name = "VoWLAN",
1946 .stream_name = "VoWLAN",
1947 .cpu_dai_name = "VoiceMMode1",
1948 .platform_name = "msm-pcm-voice",
1949 .dynamic = 1,
1950 .dpcm_playback = 1,
1951 .dpcm_capture = 1,
1952 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
1953 SND_SOC_DPCM_TRIGGER_POST},
1954 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
1955 .ignore_suspend = 1,
1956 .ignore_pmdown_time = 1,
1957 .codec_dai_name = "snd-soc-dummy-dai",
1958 .codec_name = "snd-soc-dummy",
1959 .id = MSM_FRONTEND_DAI_VOWLAN,
1960 },
1961 {/* hw:x,17 */
1962 .name = "INT_HFP_BT Hostless",
1963 .stream_name = "INT_HFP_BT Hostless",
1964 .cpu_dai_name = "INT_HFP_BT_HOSTLESS",
1965 .platform_name = "msm-pcm-hostless",
1966 .dynamic = 1,
1967 .dpcm_playback = 1,
1968 .dpcm_capture = 1,
1969 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
1970 SND_SOC_DPCM_TRIGGER_POST},
1971 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
1972 .ignore_suspend = 1,
1973 /* this dai link has playback support */
1974 .ignore_pmdown_time = 1,
1975 .codec_dai_name = "snd-soc-dummy-dai",
1976 .codec_name = "snd-soc-dummy",
1977 },
1978 {/* hw:x,18 */
1979 .name = "MSM8916 HFP",
1980 .stream_name = "MultiMedia6",
1981 .cpu_dai_name = "MultiMedia6",
1982 .platform_name = "msm-pcm-loopback",
1983 .dynamic = 1,
1984 .dpcm_playback = 1,
1985 .dpcm_capture = 1,
1986 .codec_dai_name = "snd-soc-dummy-dai",
1987 .codec_name = "snd-soc-dummy",
1988 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
1989 SND_SOC_DPCM_TRIGGER_POST},
1990 .ignore_suspend = 1,
1991 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
1992 /* this dai link has playback support */
1993 .ignore_pmdown_time = 1,
1994 .id = MSM_FRONTEND_DAI_MULTIMEDIA6,
1995 },
1996 /* LSM FE */
1997 {/* hw:x,19 */
1998 .name = "Listen 1 Audio Service",
1999 .stream_name = "Listen 1 Audio Service",
2000 .cpu_dai_name = "LSM1",
2001 .platform_name = "msm-lsm-client",
2002 .dynamic = 1,
2003 .dpcm_capture = 1,
2004 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
2005 SND_SOC_DPCM_TRIGGER_POST },
2006 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
2007 .ignore_suspend = 1,
2008 .ignore_pmdown_time = 1,
2009 .codec_dai_name = "snd-soc-dummy-dai",
2010 .codec_name = "snd-soc-dummy",
2011 .id = MSM_FRONTEND_DAI_LSM1,
2012 },
2013 {/* hw:x,20 */
2014 .name = "Listen 2 Audio Service",
2015 .stream_name = "Listen 2 Audio Service",
2016 .cpu_dai_name = "LSM2",
2017 .platform_name = "msm-lsm-client",
2018 .dynamic = 1,
2019 .dpcm_capture = 1,
2020 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
2021 SND_SOC_DPCM_TRIGGER_POST },
2022 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
2023 .ignore_suspend = 1,
2024 .ignore_pmdown_time = 1,
2025 .codec_dai_name = "snd-soc-dummy-dai",
2026 .codec_name = "snd-soc-dummy",
2027 .id = MSM_FRONTEND_DAI_LSM2,
2028 },
2029 {/* hw:x,21 */
2030 .name = "Listen 3 Audio Service",
2031 .stream_name = "Listen 3 Audio Service",
2032 .cpu_dai_name = "LSM3",
2033 .platform_name = "msm-lsm-client",
2034 .dynamic = 1,
2035 .dpcm_capture = 1,
2036 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
2037 SND_SOC_DPCM_TRIGGER_POST },
2038 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
2039 .ignore_suspend = 1,
2040 .ignore_pmdown_time = 1,
2041 .codec_dai_name = "snd-soc-dummy-dai",
2042 .codec_name = "snd-soc-dummy",
2043 .id = MSM_FRONTEND_DAI_LSM3,
2044 },
2045 {/* hw:x,22 */
2046 .name = "Listen 4 Audio Service",
2047 .stream_name = "Listen 4 Audio Service",
2048 .cpu_dai_name = "LSM4",
2049 .platform_name = "msm-lsm-client",
2050 .dynamic = 1,
2051 .dpcm_capture = 1,
2052 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
2053 SND_SOC_DPCM_TRIGGER_POST },
2054 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
2055 .ignore_suspend = 1,
2056 .ignore_pmdown_time = 1,
2057 .codec_dai_name = "snd-soc-dummy-dai",
2058 .codec_name = "snd-soc-dummy",
2059 .id = MSM_FRONTEND_DAI_LSM4,
2060 },
2061 {/* hw:x,23 */
2062 .name = "Listen 5 Audio Service",
2063 .stream_name = "Listen 5 Audio Service",
2064 .cpu_dai_name = "LSM5",
2065 .platform_name = "msm-lsm-client",
2066 .dynamic = 1,
2067 .dpcm_capture = 1,
2068 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
2069 SND_SOC_DPCM_TRIGGER_POST },
2070 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
2071 .ignore_suspend = 1,
2072 .ignore_pmdown_time = 1,
2073 .codec_dai_name = "snd-soc-dummy-dai",
2074 .codec_name = "snd-soc-dummy",
2075 .id = MSM_FRONTEND_DAI_LSM5,
2076 },
2077 { /* hw:x,24 */
2078 .name = "MSM8X16 Compress2",
2079 .stream_name = "Compress2",
2080 .cpu_dai_name = "MultiMedia7",
2081 .platform_name = "msm-compress-dsp",
2082 .dynamic = 1,
2083 .dpcm_playback = 1,
2084 .codec_dai_name = "snd-soc-dummy-dai",
2085 .codec_name = "snd-soc-dummy",
2086 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
2087 SND_SOC_DPCM_TRIGGER_POST},
2088 .ignore_suspend = 1,
2089 /* this dainlink has playback support */
2090 .ignore_pmdown_time = 1,
2091 .id = MSM_FRONTEND_DAI_MULTIMEDIA7,
2092 },
2093 { /* hw:x,25 */
2094 .name = "QUAT_MI2S Hostless",
2095 .stream_name = "QUAT_MI2S Hostless",
2096 .cpu_dai_name = "QUAT_MI2S_RX_HOSTLESS",
2097 .platform_name = "msm-pcm-hostless",
2098 .dynamic = 1,
2099 .dpcm_playback = 1,
2100 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
2101 SND_SOC_DPCM_TRIGGER_POST},
2102 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
2103 .ignore_suspend = 1,
2104 /* this dainlink has playback support */
2105 .ignore_pmdown_time = 1,
2106 .codec_dai_name = "snd-soc-dummy-dai",
2107 .codec_name = "snd-soc-dummy",
2108 },
2109 {/* hw:x,26 */
2110 .name = LPASS_BE_SENARY_MI2S_TX,
2111 .stream_name = "Senary_mi2s Capture",
2112 .cpu_dai_name = "msm-dai-q6-mi2s.6",
2113 .platform_name = "msm-pcm-hostless",
2114 .codecs = dlc_vifeed,
2115 .num_codecs = CODECS_MAX,
2116 .id = MSM_BACKEND_DAI_SENARY_MI2S_TX,
2117 .be_hw_params_fixup = msm_senary_tx_be_hw_params_fixup,
2118 .ops = &msm8952_mi2s_be_ops,
2119 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
2120 .ignore_suspend = 1,
2121 .dpcm_capture = 1,
2122 .ignore_pmdown_time = 1,
2123 },
2124 {/* hw:x,27 */
2125 .name = "MSM8X16 Compress3",
2126 .stream_name = "Compress3",
2127 .cpu_dai_name = "MultiMedia10",
2128 .platform_name = "msm-pcm-dsp.1",
2129 .dynamic = 1,
2130 .dpcm_playback = 1,
2131 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
2132 SND_SOC_DPCM_TRIGGER_POST},
2133 .codec_dai_name = "snd-soc-dummy-dai",
2134 .codec_name = "snd-soc-dummy",
2135 .ignore_suspend = 1,
2136 .ignore_pmdown_time = 1,
2137 /* this dai link has playback support */
2138 .id = MSM_FRONTEND_DAI_MULTIMEDIA10,
2139 },
2140 {/* hw:x,28 */
2141 .name = "MSM8X16 Compress4",
2142 .stream_name = "Compress4",
2143 .cpu_dai_name = "MultiMedia11",
2144 .platform_name = "msm-compress-dsp",
2145 .dynamic = 1,
2146 .dpcm_playback = 1,
2147 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
2148 SND_SOC_DPCM_TRIGGER_POST},
2149 .codec_dai_name = "snd-soc-dummy-dai",
2150 .codec_name = "snd-soc-dummy",
2151 .ignore_suspend = 1,
2152 .ignore_pmdown_time = 1,
2153 /* this dai link has playback support */
2154 .id = MSM_FRONTEND_DAI_MULTIMEDIA11,
2155 },
2156 {/* hw:x,29 */
2157 .name = "MSM8X16 Compress5",
2158 .stream_name = "Compress5",
2159 .cpu_dai_name = "MultiMedia12",
2160 .platform_name = "msm-compress-dsp",
2161 .dynamic = 1,
2162 .dpcm_playback = 1,
2163 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
2164 SND_SOC_DPCM_TRIGGER_POST},
2165 .codec_dai_name = "snd-soc-dummy-dai",
2166 .codec_name = "snd-soc-dummy",
2167 .ignore_suspend = 1,
2168 .ignore_pmdown_time = 1,
2169 /* this dai link has playback support */
2170 .id = MSM_FRONTEND_DAI_MULTIMEDIA12,
2171 },
2172 {/* hw:x,30 */
2173 .name = "MSM8X16 Compress6",
2174 .stream_name = "Compress6",
2175 .cpu_dai_name = "MultiMedia13",
2176 .platform_name = "msm-compress-dsp",
2177 .dynamic = 1,
2178 .dpcm_playback = 1,
2179 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
2180 SND_SOC_DPCM_TRIGGER_POST},
2181 .codec_dai_name = "snd-soc-dummy-dai",
2182 .codec_name = "snd-soc-dummy",
2183 .ignore_suspend = 1,
2184 .ignore_pmdown_time = 1,
2185 /* this dai link has playback support */
2186 .id = MSM_FRONTEND_DAI_MULTIMEDIA13,
2187 },
2188 {/* hw:x,31 */
2189 .name = "MSM8X16 Compress7",
2190 .stream_name = "Compress7",
2191 .cpu_dai_name = "MultiMedia14",
2192 .platform_name = "msm-compress-dsp",
2193 .dynamic = 1,
2194 .dpcm_playback = 1,
2195 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
2196 SND_SOC_DPCM_TRIGGER_POST},
2197 .codec_dai_name = "snd-soc-dummy-dai",
2198 .codec_name = "snd-soc-dummy",
2199 .ignore_suspend = 1,
2200 .ignore_pmdown_time = 1,
2201 /* this dai link has playback support */
2202 .id = MSM_FRONTEND_DAI_MULTIMEDIA14,
2203 },
2204 {/* hw:x,32 */
2205 .name = "MSM8X16 Compress8",
2206 .stream_name = "Compress8",
2207 .cpu_dai_name = "MultiMedia15",
2208 .platform_name = "msm-compress-dsp",
2209 .dynamic = 1,
2210 .dpcm_playback = 1,
2211 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
2212 SND_SOC_DPCM_TRIGGER_POST},
2213 .codec_dai_name = "snd-soc-dummy-dai",
2214 .codec_name = "snd-soc-dummy",
2215 .ignore_suspend = 1,
2216 .ignore_pmdown_time = 1,
2217 /* this dai link has playback support */
2218 .id = MSM_FRONTEND_DAI_MULTIMEDIA15,
2219 },
2220 { /*hw:x,33 */
2221 .name = "MSM8X16 Compress9",
2222 .stream_name = "Compress9",
2223 .cpu_dai_name = "MultiMedia16",
2224 .platform_name = "msm-pcm-dsp-noirq",
2225 .dynamic = 1,
2226 .dpcm_playback = 1,
2227 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
2228 SND_SOC_DPCM_TRIGGER_POST},
2229 .codec_dai_name = "snd-soc-dummy-dai",
2230 .codec_name = "snd-soc-dummy",
2231 .ignore_suspend = 1,
2232 .ignore_pmdown_time = 1,
2233 /*this dai link has playback support */
2234 .id = MSM_FRONTEND_DAI_MULTIMEDIA16,
2235 },
2236 {/* hw:x,34 */
2237 .name = "VoiceMMode1",
2238 .stream_name = "VoiceMMode1",
2239 .cpu_dai_name = "VoiceMMode1",
2240 .platform_name = "msm-pcm-voice",
2241 .dynamic = 1,
2242 .dpcm_playback = 1,
2243 .dpcm_capture = 1,
2244 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
2245 SND_SOC_DPCM_TRIGGER_POST},
2246 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
2247 .ignore_suspend = 1,
2248 .ignore_pmdown_time = 1,
2249 .codec_dai_name = "snd-soc-dummy-dai",
2250 .codec_name = "snd-soc-dummy",
2251 .id = MSM_FRONTEND_DAI_VOICEMMODE1,
2252 },
2253 {/* hw:x,35 */
2254 .name = "VoiceMMode2",
2255 .stream_name = "VoiceMMode2",
2256 .cpu_dai_name = "VoiceMMode2",
2257 .platform_name = "msm-pcm-voice",
2258 .dynamic = 1,
2259 .dpcm_playback = 1,
2260 .dpcm_capture = 1,
2261 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
2262 SND_SOC_DPCM_TRIGGER_POST},
2263 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
2264 .ignore_suspend = 1,
2265 .ignore_pmdown_time = 1,
2266 .codec_dai_name = "snd-soc-dummy-dai",
2267 .codec_name = "snd-soc-dummy",
2268 .id = MSM_FRONTEND_DAI_VOICEMMODE2,
2269 },
2270 {/* hw:x,36 */
2271 .name = "MSM8916 HFP Loopback2",
2272 .stream_name = "MultiMedia8",
2273 .cpu_dai_name = "MultiMedia8",
2274 .platform_name = "msm-pcm-loopback",
2275 .dynamic = 1,
2276 .dpcm_playback = 1,
2277 .dpcm_capture = 1,
2278 .codec_dai_name = "snd-soc-dummy-dai",
2279 .codec_name = "snd-soc-dummy",
2280 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
2281 SND_SOC_DPCM_TRIGGER_POST},
2282 .ignore_suspend = 1,
2283 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
2284 /* this dai link has playback support */
2285 .ignore_pmdown_time = 1,
2286 .id = MSM_FRONTEND_DAI_MULTIMEDIA8,
2287 },
2288 {/* hw:x,37 */
2289 .name = "QCHAT",
2290 .stream_name = "QCHAT",
2291 .cpu_dai_name = "QCHAT",
2292 .platform_name = "msm-pcm-voice",
2293 .dynamic = 1,
2294 .dpcm_playback = 1,
2295 .dpcm_capture = 1,
2296 .codec_dai_name = "snd-soc-dummy-dai",
2297 .codec_name = "snd-soc-dummy",
2298 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
2299 SND_SOC_DPCM_TRIGGER_POST},
2300 .ignore_suspend = 1,
2301 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
2302 /* this dai link has playback support */
2303 .ignore_pmdown_time = 1,
2304 .id = MSM_FRONTEND_DAI_QCHAT,
2305 },
2306 {/* hw:x,38 */
2307 .name = "MSM8X16 Compress10",
2308 .stream_name = "Compress10",
2309 .cpu_dai_name = "MultiMedia17",
2310 .platform_name = "msm-compress-dsp",
2311 .dynamic = 1,
2312 .dpcm_capture = 1,
2313 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
2314 SND_SOC_DPCM_TRIGGER_POST},
2315 .codec_dai_name = "snd-soc-dummy-dai",
2316 .codec_name = "snd-soc-dummy",
2317 .ignore_suspend = 1,
2318 .ignore_pmdown_time = 1,
2319 .id = MSM_FRONTEND_DAI_MULTIMEDIA17,
2320 },
2321 {/* hw:x,39 */
2322 .name = "MSM8X16 Compress11",
2323 .stream_name = "Compress11",
2324 .cpu_dai_name = "MultiMedia18",
2325 .platform_name = "msm-compress-dsp",
2326 .dynamic = 1,
2327 .dpcm_capture = 1,
2328 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
2329 SND_SOC_DPCM_TRIGGER_POST},
2330 .codec_dai_name = "snd-soc-dummy-dai",
2331 .codec_name = "snd-soc-dummy",
2332 .ignore_suspend = 1,
2333 .ignore_pmdown_time = 1,
2334 .id = MSM_FRONTEND_DAI_MULTIMEDIA18,
2335 },
2336 {/* hw:x,40 */
2337 .name = "MSM8X16 Compress12",
2338 .stream_name = "Compress12",
2339 .cpu_dai_name = "MultiMedia19",
2340 .platform_name = "msm-compress-dsp",
2341 .dynamic = 1,
2342 .dpcm_capture = 1,
2343 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
2344 SND_SOC_DPCM_TRIGGER_POST},
2345 .codec_dai_name = "snd-soc-dummy-dai",
2346 .codec_name = "snd-soc-dummy",
2347 .ignore_suspend = 1,
2348 .ignore_pmdown_time = 1,
2349 .id = MSM_FRONTEND_DAI_MULTIMEDIA19,
2350 },
Ramjee Singh29973d72020-03-06 09:21:43 +05302351 {/* hw:x,41 */
2352 .name = "MSM8x16 Haptic Audio",
2353 .stream_name = "MultiMedia30",
2354 .cpu_dai_name = "MultiMedia30",
2355 .platform_name = "msm-pcm-dsp.1",
2356 .dynamic = 1,
2357 .dpcm_playback = 1,
2358 .async_ops = ASYNC_DPCM_SND_SOC_PREPARE |
2359 ASYNC_DPCM_SND_SOC_HW_PARAMS,
2360 .codec_dai_name = "snd-soc-dummy-dai",
2361 .codec_name = "snd-soc-dummy",
2362 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
2363 SND_SOC_DPCM_TRIGGER_POST},
2364 .ignore_suspend = 1,
2365 /* this dainlink has playback support */
2366 .ignore_pmdown_time = 1,
2367 .id = MSM_FRONTEND_DAI_MULTIMEDIA30,
2368 },
Soumya Managoli84c975c2018-02-23 13:00:54 +05302369 /* Backend I2S DAI Links */
2370 {
2371 .name = LPASS_BE_PRI_MI2S_RX,
2372 .stream_name = "Primary MI2S Playback",
2373 .cpu_dai_name = "msm-dai-q6-mi2s.0",
2374 .platform_name = "msm-pcm-routing",
2375 .codecs = dlc_rx1,
2376 .num_codecs = CODECS_MAX,
2377 .no_pcm = 1,
2378 .dpcm_playback = 1,
2379 .async_ops = ASYNC_DPCM_SND_SOC_PREPARE |
2380 ASYNC_DPCM_SND_SOC_HW_PARAMS,
2381 .id = MSM_BACKEND_DAI_PRI_MI2S_RX,
2382 .init = &msm_audrx_init,
2383 .be_hw_params_fixup = msm_mi2s_rx_be_hw_params_fixup,
2384 .ops = &msm8952_mi2s_be_ops,
2385 .ignore_suspend = 1,
2386 },
2387 {
2388 .name = LPASS_BE_SEC_MI2S_RX,
2389 .stream_name = "Secondary MI2S Playback",
2390 .cpu_dai_name = "msm-dai-q6-mi2s.1",
2391 .platform_name = "msm-pcm-routing",
2392 .codec_name = "msm-stub-codec.1",
2393 .codec_dai_name = "msm-stub-rx",
2394 .no_pcm = 1,
2395 .dpcm_playback = 1,
2396 .id = MSM_BACKEND_DAI_SECONDARY_MI2S_RX,
2397 .be_hw_params_fixup = msm_mi2s_rx_be_hw_params_fixup,
2398 .ops = &msm8952_sec_mi2s_be_ops,
2399 .ignore_suspend = 1,
2400 },
2401 {
2402 .name = LPASS_BE_TERT_MI2S_TX,
2403 .stream_name = "Tertiary MI2S Capture",
2404 .cpu_dai_name = "msm-dai-q6-mi2s.2",
2405 .platform_name = "msm-pcm-routing",
2406 .codecs = dlc_tx1,
2407 .num_codecs = CODECS_MAX,
2408 .no_pcm = 1,
2409 .dpcm_capture = 1,
2410 .async_ops = ASYNC_DPCM_SND_SOC_PREPARE |
2411 ASYNC_DPCM_SND_SOC_HW_PARAMS,
2412 .id = MSM_BACKEND_DAI_TERTIARY_MI2S_TX,
2413 .be_hw_params_fixup = msm_tx_be_hw_params_fixup,
2414 .ops = &msm8952_mi2s_be_ops,
2415 .ignore_suspend = 1,
2416 },
2417 {
2418 .name = LPASS_BE_QUAT_MI2S_RX,
2419 .stream_name = "Quaternary MI2S Playback",
2420 .cpu_dai_name = "msm-dai-q6-mi2s.3",
2421 .platform_name = "msm-pcm-routing",
2422 .codec_dai_name = "snd-soc-dummy-dai",
2423 .codec_name = "snd-soc-dummy",
2424 .no_pcm = 1,
2425 .dpcm_playback = 1,
2426 .id = MSM_BACKEND_DAI_QUATERNARY_MI2S_RX,
2427 .be_hw_params_fixup = msm_mi2s_rx_be_hw_params_fixup,
2428 .ops = &msm8952_quat_mi2s_be_ops,
2429 .ignore_pmdown_time = 1, /* dai link has playback support */
2430 .ignore_suspend = 1,
2431 },
2432 {
2433 .name = LPASS_BE_QUAT_MI2S_TX,
2434 .stream_name = "Quaternary MI2S Capture",
2435 .cpu_dai_name = "msm-dai-q6-mi2s.3",
2436 .platform_name = "msm-pcm-routing",
2437 .codec_dai_name = "snd-soc-dummy-dai",
2438 .codec_name = "snd-soc-dummy",
2439 .no_pcm = 1,
2440 .dpcm_capture = 1,
2441 .id = MSM_BACKEND_DAI_QUATERNARY_MI2S_TX,
2442 .be_hw_params_fixup = msm_be_hw_params_fixup,
2443 .ops = &msm8952_quat_mi2s_be_ops,
2444 .ignore_suspend = 1,
2445 },
2446 /* Primary AUX PCM Backend DAI Links */
2447 {
2448 .name = LPASS_BE_AUXPCM_RX,
2449 .stream_name = "AUX PCM Playback",
2450 .cpu_dai_name = "msm-dai-q6-auxpcm.1",
2451 .platform_name = "msm-pcm-routing",
2452 .codec_name = "msm-stub-codec.1",
2453 .codec_dai_name = "msm-stub-rx",
2454 .no_pcm = 1,
2455 .dpcm_playback = 1,
2456 .id = MSM_BACKEND_DAI_AUXPCM_RX,
2457 .be_hw_params_fixup = msm_auxpcm_be_params_fixup,
2458 .ops = &msm_pri_auxpcm_be_ops,
2459 .ignore_pmdown_time = 1,
2460 .ignore_suspend = 1,
2461 },
2462 {
2463 .name = LPASS_BE_AUXPCM_TX,
2464 .stream_name = "AUX PCM Capture",
2465 .cpu_dai_name = "msm-dai-q6-auxpcm.1",
2466 .platform_name = "msm-pcm-routing",
2467 .codec_name = "msm-stub-codec.1",
2468 .codec_dai_name = "msm-stub-tx",
2469 .no_pcm = 1,
2470 .dpcm_capture = 1,
2471 .id = MSM_BACKEND_DAI_AUXPCM_TX,
2472 .be_hw_params_fixup = msm_auxpcm_be_params_fixup,
2473 .ops = &msm_pri_auxpcm_be_ops,
2474 .ignore_suspend = 1,
2475 },
2476 {
2477 .name = LPASS_BE_INT_BT_SCO_RX,
2478 .stream_name = "Internal BT-SCO Playback",
2479 .cpu_dai_name = "msm-dai-q6-dev.12288",
2480 .platform_name = "msm-pcm-routing",
2481 .codec_name = "msm-stub-codec.1",
2482 .codec_dai_name = "msm-stub-rx",
2483 .no_pcm = 1,
2484 .dpcm_playback = 1,
2485 .id = MSM_BACKEND_DAI_INT_BT_SCO_RX,
2486 .be_hw_params_fixup = msm_btsco_be_hw_params_fixup,
2487 /* this dainlink has playback support */
2488 .ignore_pmdown_time = 1,
2489 .ignore_suspend = 1,
2490 },
2491 {
2492 .name = LPASS_BE_INT_BT_SCO_TX,
2493 .stream_name = "Internal BT-SCO Capture",
2494 .cpu_dai_name = "msm-dai-q6-dev.12289",
2495 .platform_name = "msm-pcm-routing",
2496 .codec_name = "msm-stub-codec.1",
2497 .codec_dai_name = "msm-stub-tx",
2498 .no_pcm = 1,
2499 .dpcm_capture = 1,
2500 .id = MSM_BACKEND_DAI_INT_BT_SCO_TX,
2501 .be_hw_params_fixup = msm_btsco_be_hw_params_fixup,
2502 .ignore_suspend = 1,
2503 },
2504 {
2505 .name = LPASS_BE_INT_FM_RX,
2506 .stream_name = "Internal FM Playback",
2507 .cpu_dai_name = "msm-dai-q6-dev.12292",
2508 .platform_name = "msm-pcm-routing",
2509 .codec_name = "msm-stub-codec.1",
2510 .codec_dai_name = "msm-stub-rx",
2511 .no_pcm = 1,
2512 .dpcm_playback = 1,
2513 .id = MSM_BACKEND_DAI_INT_FM_RX,
2514 .be_hw_params_fixup = msm_be_hw_params_fixup,
2515 /* this dainlink has playback support */
2516 .ignore_pmdown_time = 1,
2517 .ignore_suspend = 1,
2518 },
2519 {
2520 .name = LPASS_BE_INT_FM_TX,
2521 .stream_name = "Internal FM Capture",
2522 .cpu_dai_name = "msm-dai-q6-dev.12293",
2523 .platform_name = "msm-pcm-routing",
2524 .codec_name = "msm-stub-codec.1",
2525 .codec_dai_name = "msm-stub-tx",
2526 .no_pcm = 1,
2527 .dpcm_capture = 1,
2528 .id = MSM_BACKEND_DAI_INT_FM_TX,
2529 .be_hw_params_fixup = msm_be_hw_params_fixup,
2530 .ignore_suspend = 1,
2531 },
2532 {
2533 .name = LPASS_BE_AFE_PCM_RX,
2534 .stream_name = "AFE Playback",
2535 .cpu_dai_name = "msm-dai-q6-dev.224",
2536 .platform_name = "msm-pcm-routing",
2537 .codec_name = "msm-stub-codec.1",
2538 .codec_dai_name = "msm-stub-rx",
2539 .no_pcm = 1,
2540 .dpcm_playback = 1,
2541 .id = MSM_BACKEND_DAI_AFE_PCM_RX,
2542 .be_hw_params_fixup = msm_proxy_rx_be_hw_params_fixup,
2543 /* this dainlink has playback support */
2544 .ignore_pmdown_time = 1,
2545 .ignore_suspend = 1,
2546 },
2547 {
2548 .name = LPASS_BE_AFE_PCM_TX,
2549 .stream_name = "AFE Capture",
2550 .cpu_dai_name = "msm-dai-q6-dev.225",
2551 .platform_name = "msm-pcm-routing",
2552 .codec_name = "msm-stub-codec.1",
2553 .codec_dai_name = "msm-stub-tx",
2554 .no_pcm = 1,
2555 .dpcm_capture = 1,
2556 .id = MSM_BACKEND_DAI_AFE_PCM_TX,
2557 .be_hw_params_fixup = msm_proxy_tx_be_hw_params_fixup,
2558 .ignore_suspend = 1,
2559 },
2560 /* Incall Record Uplink BACK END DAI Link */
2561 {
2562 .name = LPASS_BE_INCALL_RECORD_TX,
2563 .stream_name = "Voice Uplink Capture",
2564 .cpu_dai_name = "msm-dai-q6-dev.32772",
2565 .platform_name = "msm-pcm-routing",
2566 .codec_name = "msm-stub-codec.1",
2567 .codec_dai_name = "msm-stub-tx",
2568 .no_pcm = 1,
2569 .dpcm_capture = 1,
2570 .id = MSM_BACKEND_DAI_INCALL_RECORD_TX,
2571 .be_hw_params_fixup = msm_be_hw_params_fixup,
2572 .ignore_suspend = 1,
2573 },
2574 /* Incall Record Downlink BACK END DAI Link */
2575 {
2576 .name = LPASS_BE_INCALL_RECORD_RX,
2577 .stream_name = "Voice Downlink Capture",
2578 .cpu_dai_name = "msm-dai-q6-dev.32771",
2579 .platform_name = "msm-pcm-routing",
2580 .codec_name = "msm-stub-codec.1",
2581 .codec_dai_name = "msm-stub-tx",
2582 .no_pcm = 1,
2583 .dpcm_capture = 1,
2584 .id = MSM_BACKEND_DAI_INCALL_RECORD_RX,
2585 .be_hw_params_fixup = msm_be_hw_params_fixup,
2586 .ignore_suspend = 1,
2587 },
2588 /* Incall Music BACK END DAI Link */
2589 {
2590 .name = LPASS_BE_VOICE_PLAYBACK_TX,
2591 .stream_name = "Voice Farend Playback",
2592 .cpu_dai_name = "msm-dai-q6-dev.32773",
2593 .platform_name = "msm-pcm-routing",
2594 .codec_name = "msm-stub-codec.1",
2595 .codec_dai_name = "msm-stub-rx",
2596 .no_pcm = 1,
2597 .dpcm_playback = 1,
2598 .id = MSM_BACKEND_DAI_VOICE_PLAYBACK_TX,
2599 .be_hw_params_fixup = msm_be_hw_params_fixup,
2600 .ignore_suspend = 1,
2601 },
2602 /* Incall Music 2 BACK END DAI Link */
2603 {
2604 .name = LPASS_BE_VOICE2_PLAYBACK_TX,
2605 .stream_name = "Voice2 Farend Playback",
2606 .cpu_dai_name = "msm-dai-q6-dev.32770",
2607 .platform_name = "msm-pcm-routing",
2608 .codec_name = "msm-stub-codec.1",
2609 .codec_dai_name = "msm-stub-rx",
2610 .no_pcm = 1,
2611 .dpcm_playback = 1,
2612 .id = MSM_BACKEND_DAI_VOICE2_PLAYBACK_TX,
2613 .be_hw_params_fixup = msm_be_hw_params_fixup,
2614 .ignore_suspend = 1,
2615 },
2616
2617 {
2618 .name = LPASS_BE_QUIN_MI2S_TX,
2619 .stream_name = "Quinary MI2S Capture",
2620 .cpu_dai_name = "msm-dai-q6-mi2s.4",
2621 .platform_name = "msm-pcm-routing",
2622 .codec_dai_name = "snd-soc-dummy-dai",
2623 .codec_name = "snd-soc-dummy",
2624 .no_pcm = 1,
2625 .dpcm_capture = 1,
2626 .id = MSM_BACKEND_DAI_QUINARY_MI2S_TX,
2627 .be_hw_params_fixup = msm_be_hw_params_fixup,
2628 .ops = &msm8952_quin_mi2s_be_ops,
2629 .ignore_suspend = 1,
2630 },
2631};
2632static struct snd_soc_dai_link msm8952_hdmi_dba_dai_link[] = {
2633 {
2634 .name = LPASS_BE_QUIN_MI2S_RX,
2635 .stream_name = "Quinary MI2S Playback",
2636 .cpu_dai_name = "msm-dai-q6-mi2s.4",
2637 .platform_name = "msm-pcm-routing",
2638 .codec_dai_name = "msm_hdmi_audio_codec_rx_dai",
2639 .codec_name = "msm-ext-disp-audio-codec-rx",
2640 .no_pcm = 1,
2641 .dpcm_playback = 1,
2642 .id = MSM_BACKEND_DAI_QUINARY_MI2S_RX,
2643 .be_hw_params_fixup = msm_mi2s_rx_be_hw_params_fixup,
2644 .ops = &msm8952_quin_mi2s_be_ops,
2645 .ignore_pmdown_time = 1, /* dai link has playback support */
2646 .ignore_suspend = 1,
2647 },
2648};
2649static struct snd_soc_dai_link msm8952_quin_dai_link[] = {
2650 {
2651 .name = LPASS_BE_QUIN_MI2S_RX,
2652 .stream_name = "Quinary MI2S Playback",
2653 .cpu_dai_name = "msm-dai-q6-mi2s.4",
2654 .platform_name = "msm-pcm-routing",
2655 .codec_dai_name = "snd-soc-dummy-dai",
2656 .codec_name = "snd-soc-dummy",
2657 .no_pcm = 1,
2658 .dpcm_playback = 1,
2659 .id = MSM_BACKEND_DAI_QUINARY_MI2S_RX,
2660 .be_hw_params_fixup = msm_mi2s_rx_be_hw_params_fixup,
2661 .ops = &msm8952_quin_mi2s_be_ops,
2662 .ignore_pmdown_time = 1, /* dai link has playback support */
2663 .ignore_suspend = 1,
2664 },
2665};
2666
2667static struct snd_soc_dai_link msm8952_split_a2dp_dai_link[] = {
2668 {
2669 .name = LPASS_BE_INT_BT_A2DP_RX,
2670 .stream_name = "Internal BT-A2DP Playback",
2671 .cpu_dai_name = "msm-dai-q6-dev.12290",
2672 .platform_name = "msm-pcm-routing",
2673 .codec_dai_name = "msm-stub-rx",
2674 .codec_name = "msm-stub-codec.1",
2675 .no_pcm = 1,
2676 .dpcm_playback = 1,
2677 .id = MSM_BACKEND_DAI_INT_BT_A2DP_RX,
2678 .be_hw_params_fixup = msm_be_hw_params_fixup,
2679 .ignore_pmdown_time = 1, /* dai link has playback support */
2680 .ignore_suspend = 1,
2681 },
2682};
2683
2684static struct snd_soc_dai_link msm8952_dai_links[
2685ARRAY_SIZE(msm8952_dai) +
2686ARRAY_SIZE(msm8952_hdmi_dba_dai_link) +
2687ARRAY_SIZE(msm8952_split_a2dp_dai_link)];
2688
2689static int msm8952_wsa881x_init(struct snd_soc_component *component)
2690{
2691 return 0;
2692}
2693
2694static struct snd_soc_aux_dev msm8952_aux_dev[] = {
2695 {
2696 .name = "wsa881x.0",
2697 .codec_name = NULL,
2698 .init = msm8952_wsa881x_init,
2699 },
2700 {
2701 .name = "wsa881x.0",
2702 .codec_name = NULL,
2703 .init = msm8952_wsa881x_init,
2704 },
2705};
2706
2707static struct snd_soc_codec_conf msm8952_codec_conf[] = {
2708 {
2709 .dev_name = NULL,
2710 .name_prefix = NULL,
2711 },
2712 {
2713 .dev_name = NULL,
2714 .name_prefix = NULL,
2715 },
2716};
2717static struct snd_soc_card bear_card = {
2718 /* snd_soc_card_msm8952 */
2719 .name = "msm8952-snd-card",
2720 .dai_link = msm8952_dai,
2721 .num_links = ARRAY_SIZE(msm8952_dai),
2722};
2723
2724void msm8952_disable_mclk(struct work_struct *work)
2725{
2726 struct msm_asoc_mach_data *pdata = NULL;
2727 struct delayed_work *dwork;
2728 int ret = 0;
2729
2730 dwork = to_delayed_work(work);
2731 pdata = container_of(dwork, struct msm_asoc_mach_data,
2732 disable_int_mclk0_work);
2733 mutex_lock(&pdata->cdc_int_mclk0_mutex);
2734 pr_debug("%s: int_mclk0_enabled %d int_mclk0_rsc_ref %d\n", __func__,
2735 atomic_read(&pdata->int_mclk0_enabled),
2736 atomic_read(&pdata->int_mclk0_rsc_ref));
2737
2738 if (atomic_read(&pdata->int_mclk0_enabled) == true
2739 && atomic_read(&pdata->int_mclk0_rsc_ref) == 0) {
2740 pr_debug("Disable the mclk\n");
2741 pdata->digital_cdc_core_clk.enable = 0;
2742 pdata->digital_cdc_core_clk.clk_freq_in_hz =
2743 DEFAULT_MCLK_RATE;
2744 ret = afe_set_lpass_clock_v2(
2745 AFE_PORT_ID_PRIMARY_MI2S_RX,
2746 &pdata->digital_cdc_core_clk);
2747 if (ret < 0)
2748 pr_err("%s failed to disable the CCLK\n", __func__);
2749 atomic_set(&pdata->int_mclk0_enabled, false);
2750 }
2751 mutex_unlock(&pdata->cdc_int_mclk0_mutex);
2752}
2753
2754static void msm8952_dt_parse_cap_info(struct platform_device *pdev,
2755 struct msm_asoc_mach_data *pdata)
2756{
2757 const char *ext1_cap = "qcom,msm-micbias1-ext-cap";
2758 const char *ext2_cap = "qcom,msm-micbias2-ext-cap";
2759
2760 pdata->micbias1_cap_mode =
2761 (of_property_read_bool(pdev->dev.of_node, ext1_cap) ?
2762 MICBIAS_EXT_BYP_CAP : MICBIAS_NO_EXT_BYP_CAP);
2763
2764 pdata->micbias2_cap_mode =
2765 (of_property_read_bool(pdev->dev.of_node, ext2_cap) ?
2766 MICBIAS_EXT_BYP_CAP : MICBIAS_NO_EXT_BYP_CAP);
2767}
2768
2769static int msm8952_populate_dai_link_component_of_node(
2770 struct snd_soc_card *card)
2771{
2772 int i, index, ret = 0;
2773 struct device *cdev = card->dev;
2774 struct snd_soc_dai_link *dai_link = card->dai_link;
2775 struct device_node *phandle;
2776
2777 if (!cdev) {
2778 pr_err("%s: Sound card device memory NULL\n", __func__);
2779 return -ENODEV;
2780 }
2781
2782 for (i = 0; i < card->num_links; i++) {
2783 if (dai_link[i].platform_of_node && dai_link[i].cpu_of_node)
2784 continue;
2785
2786 /* populate platform_of_node for snd card dai links */
2787 if (dai_link[i].platform_name &&
2788 !dai_link[i].platform_of_node) {
2789 index = of_property_match_string(cdev->of_node,
2790 "asoc-platform-names",
2791 dai_link[i].platform_name);
2792 if (index < 0) {
2793 pr_err("%s: No match found for platform name: %s\n",
2794 __func__, dai_link[i].platform_name);
2795 ret = index;
2796 goto cpu_dai;
2797 }
2798 phandle = of_parse_phandle(cdev->of_node,
2799 "asoc-platform",
2800 index);
2801 if (!phandle) {
2802 pr_err("%s: retrieving phandle for platform %s, index %d failed\n",
2803 __func__, dai_link[i].platform_name,
2804 index);
2805 ret = -ENODEV;
2806 goto err;
2807 }
2808 dai_link[i].platform_of_node = phandle;
2809 dai_link[i].platform_name = NULL;
2810 }
2811cpu_dai:
2812 /* populate cpu_of_node for snd card dai links */
2813 if (dai_link[i].cpu_dai_name && !dai_link[i].cpu_of_node) {
2814 index = of_property_match_string(cdev->of_node,
2815 "asoc-cpu-names",
2816 dai_link[i].cpu_dai_name);
2817 if (index < 0)
2818 goto codec_dai;
2819 phandle = of_parse_phandle(cdev->of_node, "asoc-cpu",
2820 index);
2821 if (!phandle) {
2822 pr_err("%s: retrieving phandle for cpu dai %s failed\n",
2823 __func__, dai_link[i].cpu_dai_name);
2824 ret = -ENODEV;
2825 goto err;
2826 }
2827 dai_link[i].cpu_of_node = phandle;
2828 dai_link[i].cpu_dai_name = NULL;
2829 }
2830codec_dai:
2831 /* populate codec_of_node for snd card dai links */
2832 if (dai_link[i].codec_name && !dai_link[i].codec_of_node) {
2833 index = of_property_match_string(cdev->of_node,
2834 "asoc-codec-names",
2835 dai_link[i].codec_name);
2836 if (index < 0)
2837 continue;
2838 phandle = of_parse_phandle(cdev->of_node, "asoc-codec",
2839 index);
2840 if (!phandle) {
2841 pr_err("%s: retrieving phandle for codec dai %s failed\n",
2842 __func__, dai_link[i].codec_name);
2843 ret = -ENODEV;
2844 goto err;
2845 }
2846 dai_link[i].codec_of_node = phandle;
2847 dai_link[i].codec_name = NULL;
2848 }
2849 if ((dai_link[i].id == MSM_BACKEND_DAI_PRI_MI2S_RX) ||
2850 (dai_link[i].id == MSM_BACKEND_DAI_TERTIARY_MI2S_TX) ||
2851 (dai_link[i].id == MSM_BACKEND_DAI_SENARY_MI2S_TX)) {
2852 index = of_property_match_string(
2853 cdev->of_node,
2854 "asoc-codec-names",
2855 MSM_INT_DIGITAL_CODEC);
2856
2857 phandle = of_parse_phandle(
2858 cdev->of_node,
2859 "asoc-codec", index);
2860 dai_link[i].codecs[DIG_CDC].of_node = phandle;
2861
2862 index = of_property_match_string(
2863 cdev->of_node,
2864 "asoc-codec-names",
2865 PMIC_INT_ANALOG_CODEC);
2866
2867 phandle = of_parse_phandle(
2868 cdev->of_node,
2869 "asoc-codec", index);
2870 dai_link[i].codecs[ANA_CDC].of_node = phandle;
2871 }
2872 }
2873err:
2874 return ret;
2875}
2876
2877int msm8952_init_wsa_switch_supply(struct platform_device *pdev,
2878 struct msm_asoc_mach_data *pdata)
2879{
2880 const char *switch_supply_str = "msm-vdd-wsa-switch";
2881 char prop_name[MSM_DT_MAX_PROP_SIZE];
2882 struct device_node *regnode = NULL;
2883 struct device *dev = &pdev->dev;
2884 u32 prop_val;
2885 int ret = 0;
2886
2887 snprintf(prop_name, MSM_DT_MAX_PROP_SIZE, "%s-supply",
2888 switch_supply_str);
2889 regnode = of_parse_phandle(dev->of_node, prop_name, 0);
2890 if (!regnode) {
2891 dev_err(dev, "Looking up %s property in node %s failed\n",
2892 prop_name, dev->of_node->full_name);
2893 return -ENODEV;
2894 }
2895
2896 pdata->wsa_switch_supply.supply = devm_regulator_get(dev,
2897 switch_supply_str);
2898 if (IS_ERR(pdata->wsa_switch_supply.supply)) {
2899 ret = PTR_ERR(pdata->wsa_switch_supply.supply);
2900 dev_err(dev, "Failed to get wsa switch supply: err = %d\n",
2901 ret);
2902 return ret;
2903 }
2904
2905 snprintf(prop_name, MSM_DT_MAX_PROP_SIZE,
2906 "qcom,%s-voltage", switch_supply_str);
2907 ret = of_property_read_u32(dev->of_node, prop_name,
2908 &prop_val);
2909 if (ret) {
2910 dev_err(dev, "Looking up %s property in node %s failed",
2911 prop_name, dev->of_node->full_name);
2912 return -EFAULT;
2913 }
2914 ret = regulator_set_voltage(pdata->wsa_switch_supply.supply,
2915 prop_val, prop_val);
2916 if (ret) {
2917 dev_err(dev, "Setting voltage failed for %s err = %d\n",
2918 switch_supply_str, ret);
2919 pdata->wsa_switch_supply.supply = NULL;
2920 return ret;
2921 }
2922 ret = regulator_set_load(pdata->wsa_switch_supply.supply,
2923 prop_val);
2924 if (ret < 0) {
2925 dev_err(dev, "Setting voltage failed for %s err = %d\n",
2926 switch_supply_str, ret);
2927 pdata->wsa_switch_supply.supply = NULL;
2928 return ret;
2929 }
2930
2931 snprintf(prop_name, MSM_DT_MAX_PROP_SIZE,
2932 "qcom,%s-current", switch_supply_str);
2933 ret = of_property_read_u32(dev->of_node, prop_name,
2934 &prop_val);
2935 if (ret) {
2936 dev_err(dev, "Looking up %s property in node %s failed",
2937 prop_name, dev->of_node->full_name);
2938 return -EFAULT;
2939 }
2940 atomic_set(&pdata->wsa_switch_supply.ref, 0);
2941 return ret;
2942}
2943
2944static struct snd_soc_card *msm8952_populate_sndcard_dailinks(
2945 struct device *dev)
2946{
2947 struct snd_soc_card *card = &bear_card;
2948 struct snd_soc_dai_link *dailink;
2949 int len1;
2950
2951 card->name = dev_name(dev);
2952 len1 = ARRAY_SIZE(msm8952_dai);
2953 memcpy(msm8952_dai_links, msm8952_dai, sizeof(msm8952_dai));
2954 dailink = msm8952_dai_links;
2955 if (of_property_read_bool(dev->of_node,
2956 "qcom,hdmi-dba-codec-rx")) {
2957 dev_dbg(dev, "%s(): hdmi audio support present\n",
2958 __func__);
2959 memcpy(dailink + len1, msm8952_hdmi_dba_dai_link,
2960 sizeof(msm8952_hdmi_dba_dai_link));
2961 len1 += ARRAY_SIZE(msm8952_hdmi_dba_dai_link);
2962 } else {
2963 dev_dbg(dev, "%s(): No hdmi dba present, add quin dai\n",
2964 __func__);
2965 memcpy(dailink + len1, msm8952_quin_dai_link,
2966 sizeof(msm8952_quin_dai_link));
2967 len1 += ARRAY_SIZE(msm8952_quin_dai_link);
2968 }
2969 if (of_property_read_bool(dev->of_node,
2970 "qcom,split-a2dp")) {
2971 dev_dbg(dev, "%s(): split a2dp support present\n",
2972 __func__);
2973 memcpy(dailink + len1, msm8952_split_a2dp_dai_link,
2974 sizeof(msm8952_split_a2dp_dai_link));
2975 len1 += ARRAY_SIZE(msm8952_split_a2dp_dai_link);
2976 }
2977 card->dai_link = dailink;
2978 card->num_links = len1;
2979 return card;
2980}
2981
2982static int msm8952_asoc_machine_probe(struct platform_device *pdev)
2983{
2984 struct snd_soc_card *card;
2985 struct msm_asoc_mach_data *pdata = NULL;
2986 const char *hs_micbias_type = "qcom,msm-hs-micbias-type";
2987 const char *ext_pa = "qcom,msm-ext-pa";
2988 const char *mclk = "qcom,msm-mclk-freq";
2989 const char *wsa = "asoc-wsa-codec-names";
Soumya Managoli84c975c2018-02-23 13:00:54 +05302990 const char *type = NULL;
2991 const char *ext_pa_str = NULL;
Soumya Managoli84c975c2018-02-23 13:00:54 +05302992 const char *spk_ext_pa = "qcom,msm-spk-ext-pa";
2993 int num_strings;
2994 int id, i, val;
2995 int ret = 0;
2996 struct resource *muxsel;
Manjunatha Madana58ebedb2020-02-19 17:39:05 +05302997#if IS_ENABLED(CONFIG_SND_SOC_WSA881X_ANALOG)
2998 const char *wsa_prefix = "asoc-wsa-codec-prefixes";
2999 const char *wsa_str = NULL;
3000 const char *wsa_prefix_str = NULL;
Soumya Managoli84c975c2018-02-23 13:00:54 +05303001 char *temp_str = NULL;
Manjunatha Madana58ebedb2020-02-19 17:39:05 +05303002#endif
Soumya Managoli84c975c2018-02-23 13:00:54 +05303003
3004 pdata = devm_kzalloc(&pdev->dev,
3005 sizeof(struct msm_asoc_mach_data),
3006 GFP_KERNEL);
3007 if (!pdata)
3008 return -ENOMEM;
3009
3010 muxsel = platform_get_resource_byname(pdev, IORESOURCE_MEM,
3011 "csr_gp_io_mux_mic_ctl");
3012 if (!muxsel) {
3013 dev_err(&pdev->dev, "MUX addr invalid for MI2S\n");
3014 ret = -ENODEV;
3015 goto err1;
3016 }
3017 pdata->vaddr_gpio_mux_mic_ctl =
3018 ioremap(muxsel->start, resource_size(muxsel));
3019 if (pdata->vaddr_gpio_mux_mic_ctl == NULL) {
3020 pr_err("%s ioremap failure for muxsel virt addr\n",
3021 __func__);
3022 ret = -ENOMEM;
3023 goto err1;
3024 }
3025
3026 muxsel = platform_get_resource_byname(pdev, IORESOURCE_MEM,
3027 "csr_gp_io_mux_spkr_ctl");
3028 if (!muxsel) {
3029 dev_err(&pdev->dev, "MUX addr invalid for MI2S\n");
3030 ret = -ENODEV;
3031 goto err;
3032 }
3033 pdata->vaddr_gpio_mux_spkr_ctl =
3034 ioremap(muxsel->start, resource_size(muxsel));
3035 if (pdata->vaddr_gpio_mux_spkr_ctl == NULL) {
3036 pr_err("%s ioremap failure for muxsel virt addr\n",
3037 __func__);
3038 ret = -ENOMEM;
3039 goto err;
3040 }
3041
3042 muxsel = platform_get_resource_byname(pdev, IORESOURCE_MEM,
3043 "csr_gp_io_lpaif_pri_pcm_pri_mode_muxsel");
3044 if (!muxsel) {
3045 dev_err(&pdev->dev, "MUX addr invalid for MI2S\n");
3046 ret = -ENODEV;
3047 goto err;
3048 }
3049 pdata->vaddr_gpio_mux_pcm_ctl =
3050 ioremap(muxsel->start, resource_size(muxsel));
3051 if (pdata->vaddr_gpio_mux_pcm_ctl == NULL) {
3052 pr_err("%s ioremap failure for muxsel virt addr\n",
3053 __func__);
3054 ret = -ENOMEM;
3055 goto err;
3056 }
3057
3058 muxsel = platform_get_resource_byname(pdev, IORESOURCE_MEM,
3059 "csr_gp_io_mux_quin_ctl");
3060 if (!muxsel) {
3061 dev_dbg(&pdev->dev, "MUX addr invalid for MI2S\n");
3062 goto parse_mclk_freq;
3063 }
3064 pdata->vaddr_gpio_mux_quin_ctl =
3065 ioremap(muxsel->start, resource_size(muxsel));
3066 if (pdata->vaddr_gpio_mux_quin_ctl == NULL) {
3067 pr_err("%s ioremap failure for muxsel virt addr\n",
3068 __func__);
3069 ret = -ENOMEM;
3070 goto err;
3071 }
3072parse_mclk_freq:
3073 ret = of_property_read_u32(pdev->dev.of_node, mclk, &id);
3074 if (ret) {
3075 dev_err(&pdev->dev,
3076 "%s: missing %s in dt node\n", __func__, mclk);
3077 id = DEFAULT_MCLK_RATE;
3078 }
3079 pdata->mclk_freq = id;
3080
3081 /*reading the gpio configurations from dtsi file*/
3082 num_strings = of_property_count_strings(pdev->dev.of_node,
3083 wsa);
Manjunatha Madana58ebedb2020-02-19 17:39:05 +05303084#if IS_ENABLED(CONFIG_SND_SOC_WSA881X_ANALOG)
Soumya Managoli84c975c2018-02-23 13:00:54 +05303085 if (num_strings > 0) {
3086 if (wsa881x_get_probing_count() < 2) {
3087 ret = -EPROBE_DEFER;
3088 goto err;
3089 } else if (wsa881x_get_presence_count() == num_strings) {
3090 bear_card.aux_dev = msm8952_aux_dev;
3091 bear_card.num_aux_devs = num_strings;
3092 bear_card.codec_conf = msm8952_codec_conf;
3093 bear_card.num_configs = num_strings;
3094
3095 for (i = 0; i < num_strings; i++) {
3096 ret = of_property_read_string_index(
3097 pdev->dev.of_node, wsa,
3098 i, &wsa_str);
3099 if (ret) {
3100 dev_err(&pdev->dev,
3101 "%s:of read string %s i %d error %d\n",
3102 __func__, wsa, i, ret);
3103 goto err;
3104 }
3105 temp_str = kstrdup(wsa_str, GFP_KERNEL);
3106 if (!temp_str) {
3107 ret = -ENOMEM;
3108 goto err;
3109 }
3110 msm8952_aux_dev[i].codec_name = temp_str;
3111 temp_str = NULL;
3112
3113 temp_str = kstrdup(wsa_str, GFP_KERNEL);
3114 if (!temp_str) {
3115 ret = -ENOMEM;
3116 goto err;
3117 }
3118 msm8952_codec_conf[i].dev_name = temp_str;
3119 temp_str = NULL;
3120
3121 ret = of_property_read_string_index(
3122 pdev->dev.of_node, wsa_prefix,
3123 i, &wsa_prefix_str);
3124 if (ret) {
3125 dev_err(&pdev->dev,
3126 "%s:of read string %s i %d error %d\n",
3127 __func__, wsa_prefix, i, ret);
3128 goto err;
3129 }
3130 temp_str = kstrdup(wsa_prefix_str, GFP_KERNEL);
3131 if (!temp_str) {
3132 ret = -ENOMEM;
3133 goto err;
3134 }
3135 msm8952_codec_conf[i].name_prefix = temp_str;
3136 temp_str = NULL;
3137 }
3138
3139 ret = msm8952_init_wsa_switch_supply(pdev, pdata);
3140 if (ret < 0) {
3141 pr_err("%s: failed to init wsa_switch vdd supply %d\n",
3142 __func__, ret);
3143 goto err;
3144 }
3145 wsa881x_set_mclk_callback(msm8952_enable_wsa_mclk);
3146 /* update the internal speaker boost usage */
3147 msm_anlg_cdc_update_int_spk_boost(false);
3148 }
3149 }
Manjunatha Madana58ebedb2020-02-19 17:39:05 +05303150#endif
Soumya Managoli84c975c2018-02-23 13:00:54 +05303151
3152 card = msm8952_populate_sndcard_dailinks(&pdev->dev);
3153 dev_dbg(&pdev->dev, "default codec configured\n");
3154 num_strings = of_property_count_strings(pdev->dev.of_node,
3155 ext_pa);
3156 if (num_strings < 0) {
3157 dev_err(&pdev->dev,
3158 "%s: missing %s in dt node or length is incorrect\n",
3159 __func__, ext_pa);
3160 goto err;
3161 }
3162 for (i = 0; i < num_strings; i++) {
3163 ret = of_property_read_string_index(pdev->dev.of_node,
3164 ext_pa, i, &ext_pa_str);
3165 if (ret) {
3166 dev_err(&pdev->dev, "%s:of read string %s i %d error %d\n",
3167 __func__, ext_pa, i, ret);
3168 goto err;
3169 }
3170 dev_err(&pdev->dev, "%s:of read string %s i %d ret %d\n",
3171 __func__, ext_pa, i, ret);
3172 if (!strcmp(ext_pa_str, "primary"))
3173 pdata->ext_pa = (pdata->ext_pa | PRI_MI2S_ID);
3174 else if (!strcmp(ext_pa_str, "secondary"))
3175 pdata->ext_pa = (pdata->ext_pa | SEC_MI2S_ID);
3176 else if (!strcmp(ext_pa_str, "tertiary"))
3177 pdata->ext_pa = (pdata->ext_pa | TER_MI2S_ID);
3178 else if (!strcmp(ext_pa_str, "quaternary"))
3179 pdata->ext_pa = (pdata->ext_pa | QUAT_MI2S_ID);
3180 else if (!strcmp(ext_pa_str, "quinary"))
3181 pdata->ext_pa = (pdata->ext_pa | QUIN_MI2S_ID);
3182 }
3183 pr_debug("%s: ext_pa = %d\n", __func__, pdata->ext_pa);
3184 pdata->spk_ext_pa_gpio = of_get_named_gpio(pdev->dev.of_node,
3185 spk_ext_pa, 0);
3186 if (pdata->spk_ext_pa_gpio < 0) {
3187 dev_err(&pdev->dev, "%s: missing %s in dt node\n",
3188 __func__, spk_ext_pa);
3189 }
3190
3191 pdata->spk_ext_pa_gpio_p = of_parse_phandle(pdev->dev.of_node,
3192 spk_ext_pa, 0);
3193
3194 ret = is_us_eu_switch_gpio_support(pdev, pdata);
3195 if (ret < 0) {
3196 pr_err("%s: failed to is_us_eu_switch_gpio_support %d\n",
3197 __func__, ret);
3198 goto err;
3199 }
3200
3201 ret = is_ext_spk_gpio_support(pdev, pdata);
3202 if (ret < 0)
3203 pr_err("%s: doesn't support external speaker pa\n",
3204 __func__);
3205
3206 pdata->comp_gpio_p = of_parse_phandle(pdev->dev.of_node,
3207 "qcom,cdc-comp-gpios", 0);
3208
3209 pdata->mi2s_gpio_p[PRIM_MI2S] = of_parse_phandle(pdev->dev.of_node,
3210 "qcom,pri-mi2s-gpios", 0);
3211 pdata->mi2s_gpio_p[SEC_MI2S] = of_parse_phandle(pdev->dev.of_node,
3212 "qcom,sec-mi2s-gpios", 0);
3213 pdata->mi2s_gpio_p[TERT_MI2S] = of_parse_phandle(pdev->dev.of_node,
3214 "qcom,tert-mi2s-gpios", 0);
3215 pdata->mi2s_gpio_p[QUAT_MI2S] = of_parse_phandle(pdev->dev.of_node,
3216 "qcom,quat-mi2s-gpios", 0);
3217 pdata->mi2s_gpio_p[QUIN_MI2S] = of_parse_phandle(pdev->dev.of_node,
3218 "qcom,quin-mi2s-gpios", 0);
3219
3220 ret = of_property_read_string(pdev->dev.of_node,
3221 hs_micbias_type, &type);
3222 if (ret) {
3223 dev_err(&pdev->dev, "%s: missing %s in dt node\n",
3224 __func__, hs_micbias_type);
3225 goto err;
3226 }
3227 if (!strcmp(type, "external")) {
3228 dev_err(&pdev->dev, "Headset is using external micbias\n");
3229 mbhc_cfg.hs_ext_micbias = true;
3230 } else {
3231 dev_err(&pdev->dev, "Headset is using internal micbias\n");
3232 mbhc_cfg.hs_ext_micbias = false;
3233 }
3234
3235 ret = of_property_read_u32(pdev->dev.of_node,
3236 "qcom,msm-afe-clk-ver", &val);
3237 if (ret)
3238 pdata->afe_clk_ver = AFE_CLK_VERSION_V2;
3239 else
3240 pdata->afe_clk_ver = val;
3241 /* initialize the mclk */
3242 pdata->digital_cdc_clk.i2s_cfg_minor_version =
3243 AFE_API_VERSION_I2S_CONFIG;
3244 pdata->digital_cdc_clk.clk_val = pdata->mclk_freq;
3245 pdata->digital_cdc_clk.clk_root = 5;
3246 pdata->digital_cdc_clk.reserved = 0;
3247 /* initialize the digital codec core clk */
3248 pdata->digital_cdc_core_clk.clk_set_minor_version =
3249 AFE_API_VERSION_I2S_CONFIG;
3250 pdata->digital_cdc_core_clk.clk_id =
3251 Q6AFE_LPASS_CLK_ID_INTERNAL_DIGITAL_CODEC_CORE;
3252 pdata->digital_cdc_core_clk.clk_freq_in_hz =
3253 pdata->mclk_freq;
3254 pdata->digital_cdc_core_clk.clk_attri =
3255 Q6AFE_LPASS_CLK_ATTRIBUTE_COUPLE_NO;
3256 pdata->digital_cdc_core_clk.clk_root =
3257 Q6AFE_LPASS_CLK_ROOT_DEFAULT;
3258 pdata->digital_cdc_core_clk.enable = 1;
3259
3260 /* Initialize loopback mode to false */
3261 pdata->lb_mode = false;
3262 msm8952_dt_parse_cap_info(pdev, pdata);
3263
3264 card->dev = &pdev->dev;
3265 platform_set_drvdata(pdev, card);
3266 snd_soc_card_set_drvdata(card, pdata);
3267 ret = snd_soc_of_parse_card_name(card, "qcom,model");
3268 if (ret)
3269 goto err;
3270 /* initialize timer */
3271 INIT_DELAYED_WORK(&pdata->disable_int_mclk0_work, msm8952_disable_mclk);
3272 mutex_init(&pdata->cdc_int_mclk0_mutex);
3273 atomic_set(&pdata->int_mclk0_rsc_ref, 0);
3274 if (card->aux_dev) {
3275 mutex_init(&pdata->wsa_mclk_mutex);
3276 atomic_set(&pdata->wsa_int_mclk0_rsc_ref, 0);
3277 }
3278 atomic_set(&pdata->int_mclk0_enabled, false);
3279 atomic_set(&quat_mi2s_clk_ref, 0);
3280 atomic_set(&quin_mi2s_clk_ref, 0);
3281 atomic_set(&auxpcm_mi2s_clk_ref, 0);
3282
3283 ret = snd_soc_of_parse_audio_routing(card,
3284 "qcom,audio-routing");
3285 if (ret)
3286 goto err;
3287
3288 ret = msm8952_populate_dai_link_component_of_node(card);
3289 if (ret) {
3290 ret = -EPROBE_DEFER;
3291 goto err;
3292 }
3293
3294 ret = devm_snd_soc_register_card(&pdev->dev, card);
3295 if (ret) {
3296 dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n",
3297 ret);
3298 goto err;
3299 }
3300
3301 return 0;
3302err:
3303 if (pdata->vaddr_gpio_mux_spkr_ctl)
3304 iounmap(pdata->vaddr_gpio_mux_spkr_ctl);
3305 if (pdata->vaddr_gpio_mux_mic_ctl)
3306 iounmap(pdata->vaddr_gpio_mux_mic_ctl);
3307 if (pdata->vaddr_gpio_mux_pcm_ctl)
3308 iounmap(pdata->vaddr_gpio_mux_pcm_ctl);
3309 if (pdata->vaddr_gpio_mux_quin_ctl)
3310 iounmap(pdata->vaddr_gpio_mux_quin_ctl);
3311 if (bear_card.num_aux_devs > 0) {
3312 for (i = 0; i < bear_card.num_aux_devs; i++) {
3313 kfree(msm8952_aux_dev[i].codec_name);
3314 kfree(msm8952_codec_conf[i].dev_name);
3315 kfree(msm8952_codec_conf[i].name_prefix);
3316 }
3317 }
3318err1:
3319 devm_kfree(&pdev->dev, pdata);
3320 return ret;
3321}
3322
3323static int msm8952_asoc_machine_remove(struct platform_device *pdev)
3324{
3325 int i;
3326 struct snd_soc_card *card = platform_get_drvdata(pdev);
3327 struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
3328
3329 if (pdata->vaddr_gpio_mux_spkr_ctl)
3330 iounmap(pdata->vaddr_gpio_mux_spkr_ctl);
3331 if (pdata->vaddr_gpio_mux_mic_ctl)
3332 iounmap(pdata->vaddr_gpio_mux_mic_ctl);
3333 if (pdata->vaddr_gpio_mux_pcm_ctl)
3334 iounmap(pdata->vaddr_gpio_mux_pcm_ctl);
3335 if (pdata->vaddr_gpio_mux_quin_ctl)
3336 iounmap(pdata->vaddr_gpio_mux_quin_ctl);
3337 if (bear_card.num_aux_devs > 0) {
3338 for (i = 0; i < bear_card.num_aux_devs; i++) {
3339 kfree(msm8952_aux_dev[i].codec_name);
3340 kfree(msm8952_codec_conf[i].dev_name);
3341 kfree(msm8952_codec_conf[i].name_prefix);
3342 }
3343 mutex_destroy(&pdata->wsa_mclk_mutex);
3344 }
3345 snd_soc_unregister_card(card);
3346 mutex_destroy(&pdata->cdc_int_mclk0_mutex);
3347 return 0;
3348}
3349
3350static const struct of_device_id msm8952_asoc_machine_of_match[] = {
3351 { .compatible = "qcom,msm8952-audio-codec", },
3352 {},
3353};
3354
3355static struct platform_driver msm8952_asoc_machine_driver = {
3356 .driver = {
3357 .name = DRV_NAME,
3358 .owner = THIS_MODULE,
3359 .pm = &snd_soc_pm_ops,
3360 .of_match_table = msm8952_asoc_machine_of_match,
3361 },
3362 .probe = msm8952_asoc_machine_probe,
3363 .remove = msm8952_asoc_machine_remove,
3364};
3365
3366static int __init msm8952_machine_init(void)
3367{
3368 return platform_driver_register(&msm8952_asoc_machine_driver);
3369}
3370module_init(msm8952_machine_init);
3371
3372static void __exit msm8952_machine_exit(void)
3373{
3374 return platform_driver_unregister(&msm8952_asoc_machine_driver);
3375}
3376module_exit(msm8952_machine_exit);
3377
3378MODULE_DESCRIPTION("ALSA SoC msm");
3379MODULE_LICENSE("GPL v2");
3380MODULE_ALIAS("platform:" DRV_NAME);
3381MODULE_DEVICE_TABLE(of, msm8952_asoc_machine_of_match);