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