blob: f155c443d9b38783e8481118436c9612b4b2137d [file] [log] [blame]
Manjunatha Madana80e8ffa2018-12-17 14:13:08 +05301/* Copyright (c) 2015-2019, 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/regulator/consumer.h>
21#include <linux/workqueue.h>
22#include <linux/input.h>
23#include <sound/core.h>
24#include <sound/soc.h>
25#include <sound/soc-dapm.h>
26#include <sound/pcm.h>
27#include <sound/jack.h>
28#include <dsp/q6afe-v2.h>
29#include <dsp/q6core.h>
30#include <soc/qcom/socinfo.h>
31#include "msm-pcm-routing-v2.h"
32#include "codecs/msm-cdc-pinctrl.h"
33#include "codecs/sdm660_cdc/msm-digital-cdc.h"
34//#include "codecs/sdm660_cdc/msm-analog-cdc.h"
35#include "codecs/wcd-mbhc-v2.h"
36#include "msm8952.h"
37
38#define DRV_NAME "msm8909-asoc-wcd"
39
40enum btsco_rates {
41 RATE_8KHZ_ID,
42 RATE_16KHZ_ID,
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 msm8909_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 mi2s_rx_bit_format = SNDRV_PCM_FORMAT_S16_LE;
59static int mi2s_rx_bits_per_sample = 16;
60static int mi2s_rx_sample_rate = SAMPLING_RATE_48KHZ;
61static int mi2s_tx_bit_format = SNDRV_PCM_FORMAT_S16_LE;
62static int mi2s_tx_bits_per_sample = 16;
63static int mi2s_tx_sample_rate = SAMPLING_RATE_48KHZ;
64
65static atomic_t quat_mi2s_clk_ref;
66static atomic_t quin_mi2s_clk_ref;
67static atomic_t auxpcm_mi2s_clk_ref;
68
69static struct snd_info_entry *codec_root;
70
71static int msm_enable_dig_cdc_clk(struct snd_soc_codec *codec, int enable,
72 bool dapm);
73static int msm_mclk_event(struct snd_soc_dapm_widget *w,
74 struct snd_kcontrol *kcontrol, int event);
75
76static struct afe_clk_cfg mi2s_rx_clk_v1 = {
77 AFE_API_VERSION_I2S_CONFIG,
78 Q6AFE_LPASS_IBIT_CLK_1_P536_MHZ,
79 Q6AFE_LPASS_OSR_CLK_12_P288_MHZ,
80 Q6AFE_LPASS_CLK_SRC_INTERNAL,
81 Q6AFE_LPASS_CLK_ROOT_DEFAULT,
82 Q6AFE_LPASS_MODE_CLK1_VALID,
83 0,
84};
85
86static struct afe_clk_cfg mi2s_tx_clk_v1 = {
87 AFE_API_VERSION_I2S_CONFIG,
88 Q6AFE_LPASS_IBIT_CLK_1_P536_MHZ,
89 Q6AFE_LPASS_OSR_CLK_12_P288_MHZ,
90 Q6AFE_LPASS_CLK_SRC_INTERNAL,
91 Q6AFE_LPASS_CLK_ROOT_DEFAULT,
92 Q6AFE_LPASS_MODE_CLK1_VALID,
93 0,
94};
95
96static struct afe_clk_set mi2s_tx_clk = {
97 AFE_API_VERSION_I2S_CONFIG,
98 Q6AFE_LPASS_CLK_ID_TER_MI2S_IBIT,
99 Q6AFE_LPASS_IBIT_CLK_1_P536_MHZ,
100 Q6AFE_LPASS_CLK_ATTRIBUTE_COUPLE_NO,
101 Q6AFE_LPASS_CLK_ROOT_DEFAULT,
102 0,
103};
104
105static struct afe_clk_set mi2s_rx_clk = {
106 AFE_API_VERSION_I2S_CONFIG,
107 Q6AFE_LPASS_CLK_ID_PRI_MI2S_IBIT,
108 Q6AFE_LPASS_IBIT_CLK_1_P536_MHZ,
109 Q6AFE_LPASS_CLK_ATTRIBUTE_COUPLE_NO,
110 Q6AFE_LPASS_CLK_ROOT_DEFAULT,
111 0,
112};
113
114static char const *bit_format_text[] = {"S16_LE", "S24_LE", "S24_3LE",
115 "S32_LE"};
116static const char *const mi2s_ch_text[] = {"One", "Two"};
117static const char *const btsco_rate_text[] = {"BTSCO_RATE_8KHZ",
118 "BTSCO_RATE_16KHZ"};
119static const char *const proxy_rx_ch_text[] = {"One", "Two", "Three", "Four",
120 "Five", "Six", "Seven", "Eight"};
121static char const *mi2s_rx_sample_rate_text[] = {"KHZ_48",
122 "KHZ_96", "KHZ_192"};
123
124static inline int param_is_mask(int p)
125{
126 return (p >= SNDRV_PCM_HW_PARAM_FIRST_MASK) &&
127 (p <= SNDRV_PCM_HW_PARAM_LAST_MASK);
128}
129
130static inline struct snd_mask *param_to_mask(struct snd_pcm_hw_params *p, int n)
131{
132 return &(p->masks[n - SNDRV_PCM_HW_PARAM_FIRST_MASK]);
133}
134
135static void param_set_mask(struct snd_pcm_hw_params *p, int n, unsigned int bit)
136{
137 if (bit >= SNDRV_MASK_MAX)
138 return;
139 if (param_is_mask(n)) {
140 struct snd_mask *m = param_to_mask(p, n);
141
142 m->bits[0] = 0;
143 m->bits[1] = 0;
144 m->bits[bit >> 5] |= (1 << (bit & 31));
145 }
146}
147
148static int msm8909_dmic_event(struct snd_soc_dapm_widget *w,
149 struct snd_kcontrol *kcontrol, int event)
150{
151 struct msm_asoc_mach_data *pdata = NULL;
152 int ret = 0;
153 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
154
155 pdata = snd_soc_card_get_drvdata(codec->component.card);
156 pr_debug("%s: event = %d\n", __func__, event);
157 switch (event) {
158 case SND_SOC_DAPM_PRE_PMU:
159 ret = msm_cdc_pinctrl_select_active_state(pdata->dmic_gpio_p);
160 if (ret) {
161 pr_err("%s: gpio set cannot be activated: %sd\n",
162 __func__, "dmic_gpio");
163 break;
164 }
165 break;
166 case SND_SOC_DAPM_POST_PMD:
167 ret = msm_cdc_pinctrl_select_sleep_state(pdata->dmic_gpio_p);
168 if (ret < 0) {
169 pr_err("%s: gpio set cannot be de-activated %sd\n",
170 __func__, "dmic_gpio");
171 return ret;
172 }
173 break;
174 default:
175 return -EINVAL;
176 }
177 return 0;
178}
179
180static const struct snd_soc_dapm_widget msm8909_dapm_widgets[] = {
181 SND_SOC_DAPM_SUPPLY_S("MCLK", -1, SND_SOC_NOPM, 0, 0,
182 msm_mclk_event, SND_SOC_DAPM_POST_PMD),
183 SND_SOC_DAPM_MIC("Digital Mic1", msm8909_dmic_event),
184 SND_SOC_DAPM_MIC("Digital Mic2", msm8909_dmic_event),
185};
186
187static int msm_proxy_rx_ch_get(struct snd_kcontrol *kcontrol,
188 struct snd_ctl_elem_value *ucontrol)
189{
190 pr_debug("%s: msm_proxy_rx_ch = %d\n", __func__,
191 msm_proxy_rx_ch);
192 ucontrol->value.integer.value[0] = msm_proxy_rx_ch - 1;
193 return 0;
194}
195
196static int msm_proxy_rx_ch_put(struct snd_kcontrol *kcontrol,
197 struct snd_ctl_elem_value *ucontrol)
198{
199 msm_proxy_rx_ch = ucontrol->value.integer.value[0] + 1;
200 pr_debug("%s: msm_proxy_rx_ch = %d\n", __func__,
201 msm_proxy_rx_ch);
202 return 0;
203}
204
205static int msm_auxpcm_be_params_fixup(struct snd_soc_pcm_runtime *rtd,
206 struct snd_pcm_hw_params *params)
207{
208 struct snd_interval *rate =
209 hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
210
211 struct snd_interval *channels =
212 hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
213
214 rate->min = rate->max = msm8909_auxpcm_rate;
215 channels->min = channels->max = 1;
216
217 return 0;
218}
219
220static int msm_mi2s_rx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
221 struct snd_pcm_hw_params *params)
222{
223 struct snd_interval *rate = hw_param_interval(params,
224 SNDRV_PCM_HW_PARAM_RATE);
225
226 struct snd_interval *channels = hw_param_interval(params,
227 SNDRV_PCM_HW_PARAM_CHANNELS);
228
229 pr_debug("%s: Num of channels = %d Sample rate = %d\n", __func__,
230 msm_pri_mi2s_rx_ch, mi2s_rx_sample_rate);
231 rate->min = rate->max = mi2s_rx_sample_rate;
232 channels->min = channels->max = msm_pri_mi2s_rx_ch;
233
234 return 0;
235}
236
237static int msm_tx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
238 struct snd_pcm_hw_params *params)
239{
240 struct snd_interval *rate = hw_param_interval(params,
241 SNDRV_PCM_HW_PARAM_RATE);
242 struct snd_interval *channels = hw_param_interval(params,
243 SNDRV_PCM_HW_PARAM_CHANNELS);
244
245 pr_debug("%s(), channel:%d\n", __func__, msm_ter_mi2s_tx_ch);
246 param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
247 mi2s_tx_bit_format);
248 rate->min = rate->max = 48000;
249 channels->min = channels->max = msm_ter_mi2s_tx_ch;
250
251 return 0;
252}
253
254static int msm_senary_tx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
255 struct snd_pcm_hw_params *params)
256{
257 struct snd_interval *rate = hw_param_interval(params,
258 SNDRV_PCM_HW_PARAM_RATE);
259 struct snd_interval *channels = hw_param_interval(params,
260 SNDRV_PCM_HW_PARAM_CHANNELS);
261
262 rate->min = rate->max = 48000;
263 channels->min = channels->max = 2;
264
265 return 0;
266}
267
268
269static int msm_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
270 struct snd_pcm_hw_params *params)
271{
272 struct snd_interval *rate = hw_param_interval(params,
273 SNDRV_PCM_HW_PARAM_RATE);
274
275 struct snd_interval *channels = hw_param_interval(params,
276 SNDRV_PCM_HW_PARAM_CHANNELS);
277
278 pr_debug("%s()\n", __func__);
279 rate->min = rate->max = 48000;
280 channels->min = channels->max = 2;
281
282 return 0;
283}
284
285static int msm_btsco_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
286 struct snd_pcm_hw_params *params)
287{
288 struct snd_interval *rate = hw_param_interval(params,
289 SNDRV_PCM_HW_PARAM_RATE);
290
291 struct snd_interval *channels = hw_param_interval(params,
292 SNDRV_PCM_HW_PARAM_CHANNELS);
293
294 rate->min = rate->max = msm_btsco_rate;
295 channels->min = channels->max = msm_btsco_ch;
296
297 return 0;
298}
299
300static int msm_proxy_rx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
301 struct snd_pcm_hw_params *params)
302{
303 struct snd_interval *rate = hw_param_interval(params,
304 SNDRV_PCM_HW_PARAM_RATE);
305
306 struct snd_interval *channels = hw_param_interval(params,
307 SNDRV_PCM_HW_PARAM_CHANNELS);
308
309 pr_debug("%s: msm_proxy_rx_ch =%d\n", __func__, msm_proxy_rx_ch);
310
311 if (channels->max < 2)
312 channels->min = channels->max = 2;
313 channels->min = channels->max = msm_proxy_rx_ch;
314 rate->min = rate->max = 48000;
315 return 0;
316}
317
318static int msm_proxy_tx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
319 struct snd_pcm_hw_params *params)
320{
321 struct snd_interval *rate = hw_param_interval(params,
322 SNDRV_PCM_HW_PARAM_RATE);
323
324 rate->min = rate->max = 48000;
325 return 0;
326}
327
328static int msm_mi2s_snd_hw_params(struct snd_pcm_substream *substream,
329 struct snd_pcm_hw_params *params)
330{
331 pr_debug("%s(): substream = %s stream = %d\n", __func__,
332 substream->name, substream->stream);
333 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
334 param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
335 mi2s_rx_bit_format);
336 else
337 param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
338 mi2s_tx_bit_format);
339 return 0;
340}
341
342static int msm8909_get_clk_id(int port_id)
343{
344 switch (port_id) {
345 case AFE_PORT_ID_PRIMARY_MI2S_RX:
346 return Q6AFE_LPASS_CLK_ID_PRI_MI2S_IBIT;
347 case AFE_PORT_ID_SECONDARY_MI2S_RX:
348 return Q6AFE_LPASS_CLK_ID_SEC_MI2S_IBIT;
349 case AFE_PORT_ID_TERTIARY_MI2S_TX:
350 return Q6AFE_LPASS_CLK_ID_TER_MI2S_IBIT;
351 case AFE_PORT_ID_QUATERNARY_MI2S_RX:
352 case AFE_PORT_ID_QUATERNARY_MI2S_TX:
353 return Q6AFE_LPASS_CLK_ID_QUAD_MI2S_IBIT;
354 case AFE_PORT_ID_QUINARY_MI2S_RX:
355 case AFE_PORT_ID_QUINARY_MI2S_TX:
356 return Q6AFE_LPASS_CLK_ID_QUI_MI2S_IBIT;
357 case AFE_PORT_ID_SENARY_MI2S_TX:
358 return Q6AFE_LPASS_CLK_ID_SEN_MI2S_IBIT;
359 default:
360 pr_err("%s: invalid port_id: 0x%x\n", __func__, port_id);
361 return -EINVAL;
362 }
363}
364
365static int msm8909_get_port_id(int be_id)
366{
367 switch (be_id) {
368 case MSM_BACKEND_DAI_PRI_MI2S_RX:
369 return AFE_PORT_ID_PRIMARY_MI2S_RX;
370 case MSM_BACKEND_DAI_SECONDARY_MI2S_RX:
371 return AFE_PORT_ID_SECONDARY_MI2S_RX;
372 case MSM_BACKEND_DAI_TERTIARY_MI2S_TX:
373 return AFE_PORT_ID_TERTIARY_MI2S_TX;
374 case MSM_BACKEND_DAI_QUATERNARY_MI2S_RX:
375 return AFE_PORT_ID_QUATERNARY_MI2S_RX;
376 case MSM_BACKEND_DAI_QUATERNARY_MI2S_TX:
377 return AFE_PORT_ID_QUATERNARY_MI2S_TX;
378 case MSM_BACKEND_DAI_QUINARY_MI2S_RX:
379 return AFE_PORT_ID_QUINARY_MI2S_RX;
380 case MSM_BACKEND_DAI_QUINARY_MI2S_TX:
381 return AFE_PORT_ID_QUINARY_MI2S_TX;
382 case MSM_BACKEND_DAI_SENARY_MI2S_TX:
383 return AFE_PORT_ID_SENARY_MI2S_TX;
384 default:
385 pr_err("%s: Invalid be_id: %d\n", __func__, be_id);
386 return -EINVAL;
387 }
388}
389
390static bool is_mi2s_rx_port(int port_id)
391{
392 bool ret = false;
393
394 switch (port_id) {
395 case AFE_PORT_ID_PRIMARY_MI2S_RX:
396 case AFE_PORT_ID_SECONDARY_MI2S_RX:
397 case AFE_PORT_ID_QUATERNARY_MI2S_RX:
398 case AFE_PORT_ID_QUINARY_MI2S_RX:
399 ret = true;
400 break;
401 default:
402 break;
403 }
404 return ret;
405}
406
407static uint32_t get_mi2s_clk_val(int port_id)
408{
409 uint32_t clk_val = 0;
410
411 /*
412 * Derive clock value based on sample rate, bits per sample and
413 * channel count is used as 2
414 */
415 if (is_mi2s_rx_port(port_id))
416 clk_val = (mi2s_rx_sample_rate * mi2s_rx_bits_per_sample * 2);
417 else
418 clk_val = (mi2s_tx_sample_rate * mi2s_tx_bits_per_sample * 2);
419
420 pr_debug("%s: MI2S bit clock value: 0x%0x\n", __func__, clk_val);
421 return clk_val;
422}
423
424static int msm_mi2s_sclk_ctl(struct snd_pcm_substream *substream, bool enable)
425{
426 int ret = 0;
427 struct snd_soc_pcm_runtime *rtd = substream->private_data;
428 struct snd_soc_card *card = rtd->card;
429 struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
430 int port_id = 0;
431
432 port_id = msm8909_get_port_id(rtd->dai_link->id);
433 if (port_id < 0) {
434 pr_err("%s: Invalid port_id\n", __func__);
435 return -EINVAL;
436 }
437 if (enable) {
438 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
439 if (pdata->afe_clk_ver == AFE_CLK_VERSION_V1) {
440 mi2s_rx_clk_v1.clk_val1 =
441 get_mi2s_clk_val(port_id);
442 ret = afe_set_lpass_clock(port_id,
443 &mi2s_rx_clk_v1);
444 } else {
445 mi2s_rx_clk.enable = enable;
446 mi2s_rx_clk.clk_id =
447 msm8909_get_clk_id(port_id);
448 mi2s_rx_clk.clk_freq_in_hz =
449 get_mi2s_clk_val(port_id);
450 ret = afe_set_lpass_clock_v2(port_id,
451 &mi2s_rx_clk);
452 }
453 } else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
454 if (pdata->afe_clk_ver == AFE_CLK_VERSION_V1) {
455 mi2s_tx_clk_v1.clk_val1 =
456 get_mi2s_clk_val(port_id);
457 ret = afe_set_lpass_clock(port_id,
458 &mi2s_tx_clk_v1);
459 } else {
460 mi2s_tx_clk.enable = enable;
461 mi2s_tx_clk.clk_id =
462 msm8909_get_clk_id(port_id);
463 mi2s_tx_clk.clk_freq_in_hz =
464 get_mi2s_clk_val(port_id);
465 ret = afe_set_lpass_clock_v2(port_id,
466 &mi2s_tx_clk);
467 }
468 } else {
469 pr_err("%s:Not valid substream.\n", __func__);
470 }
471
472 if (ret < 0)
473 pr_err("%s:afe_set_lpass_clock_v2 failed\n", __func__);
474 } else {
475 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
476 if (pdata->afe_clk_ver == AFE_CLK_VERSION_V1) {
477 mi2s_rx_clk_v1.clk_val1 =
478 Q6AFE_LPASS_IBIT_CLK_DISABLE;
479 ret = afe_set_lpass_clock(port_id,
480 &mi2s_rx_clk_v1);
481 } else {
482 mi2s_rx_clk.enable = enable;
483 mi2s_rx_clk.clk_id =
484 msm8909_get_clk_id(port_id);
485 ret = afe_set_lpass_clock_v2(port_id,
486 &mi2s_rx_clk);
487 }
488 } else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
489 if (pdata->afe_clk_ver == AFE_CLK_VERSION_V1) {
490 mi2s_tx_clk_v1.clk_val1 =
491 Q6AFE_LPASS_IBIT_CLK_DISABLE;
492 ret = afe_set_lpass_clock(port_id,
493 &mi2s_tx_clk_v1);
494 } else {
495 mi2s_tx_clk.enable = enable;
496 mi2s_tx_clk.clk_id =
497 msm8909_get_clk_id(port_id);
498 ret = afe_set_lpass_clock_v2(port_id,
499 &mi2s_tx_clk);
500 }
501 } else {
502 pr_err("%s:Not valid substream.\n", __func__);
503 }
504
505 if (ret < 0)
506 pr_err("%s:afe_set_lpass_clock_v2 failed\n", __func__);
507 }
508 return ret;
509}
510
511static int msm_enable_dig_cdc_clk(struct snd_soc_codec *codec,
512 int enable, bool dapm)
513{
514 int ret = 0;
515 struct msm_asoc_mach_data *pdata = NULL;
516
517 pdata = snd_soc_card_get_drvdata(codec->component.card);
518 pr_debug("%s: enable %d mclk ref counter %d\n",
519 __func__, enable,
520 atomic_read(&pdata->int_mclk0_rsc_ref));
521 if (enable) {
522 if (!atomic_read(&pdata->int_mclk0_rsc_ref)) {
523 cancel_delayed_work_sync(
524 &pdata->disable_int_mclk0_work);
525 mutex_lock(&pdata->cdc_int_mclk0_mutex);
526 if (atomic_read(&pdata->int_mclk0_enabled) == false) {
527 pdata->digital_cdc_core_clk.enable = 1;
528 ret = afe_set_lpass_clock_v2(
529 AFE_PORT_ID_PRIMARY_MI2S_RX,
530 &pdata->digital_cdc_core_clk);
531 if (ret < 0) {
532 pr_err("%s: failed to enable CCLK\n",
533 __func__);
534 mutex_unlock(
535 &pdata->cdc_int_mclk0_mutex);
536 return ret;
537 }
538 pr_debug("enabled digital codec core clk\n");
539 atomic_set(&pdata->int_mclk0_enabled, true);
540 } else
541 pr_debug("digital codec core clk is already enabled\n");
542 mutex_unlock(&pdata->cdc_int_mclk0_mutex);
543 }
544 atomic_inc(&pdata->int_mclk0_rsc_ref);
545 } else {
546 cancel_delayed_work_sync(&pdata->disable_int_mclk0_work);
547 mutex_lock(&pdata->cdc_int_mclk0_mutex);
548 if (atomic_read(&pdata->int_mclk0_enabled) == true) {
549 pdata->digital_cdc_core_clk.clk_freq_in_hz =
550 DEFAULT_MCLK_RATE;
551 pdata->digital_cdc_core_clk.enable = 0;
552 ret = afe_set_lpass_clock_v2(
553 AFE_PORT_ID_PRIMARY_MI2S_RX,
554 &pdata->digital_cdc_core_clk);
555 if (ret < 0)
556 pr_err("%s: failed to disable CCLK\n",
557 __func__);
558 atomic_set(&pdata->int_mclk0_enabled, false);
559 atomic_set(&pdata->int_mclk0_rsc_ref, 0);
560 }
561 mutex_unlock(&pdata->cdc_int_mclk0_mutex);
562 }
563 return ret;
564}
565
566static int msm_btsco_rate_get(struct snd_kcontrol *kcontrol,
567 struct snd_ctl_elem_value *ucontrol)
568{
569 pr_debug("%s: msm_btsco_rate = %d", __func__, msm_btsco_rate);
570 ucontrol->value.integer.value[0] = msm_btsco_rate;
571 return 0;
572}
573
574static int msm_btsco_rate_put(struct snd_kcontrol *kcontrol,
575 struct snd_ctl_elem_value *ucontrol)
576{
577 switch (ucontrol->value.integer.value[0]) {
578 case RATE_8KHZ_ID:
579 msm_btsco_rate = BTSCO_RATE_8KHZ;
580 break;
581 case RATE_16KHZ_ID:
582 msm_btsco_rate = BTSCO_RATE_16KHZ;
583 break;
584 default:
585 msm_btsco_rate = BTSCO_RATE_8KHZ;
586 break;
587 }
588
589 pr_debug("%s: msm_btsco_rate = %d\n", __func__, msm_btsco_rate);
590 return 0;
591}
592
593static int mi2s_rx_bit_format_get(struct snd_kcontrol *kcontrol,
594 struct snd_ctl_elem_value *ucontrol)
595{
596
597 switch (mi2s_rx_bit_format) {
598 case SNDRV_PCM_FORMAT_S24_3LE:
599 ucontrol->value.integer.value[0] = 2;
600 break;
601
602 case SNDRV_PCM_FORMAT_S24_LE:
603 ucontrol->value.integer.value[0] = 1;
604 break;
605
606 case SNDRV_PCM_FORMAT_S16_LE:
607 default:
608 ucontrol->value.integer.value[0] = 0;
609 break;
610 }
611
612 pr_debug("%s: mi2s_rx_bit_format = %d, ucontrol value = %ld\n",
613 __func__, mi2s_rx_bit_format,
614 ucontrol->value.integer.value[0]);
615
616 return 0;
617}
618
619static int mi2s_rx_bit_format_put(struct snd_kcontrol *kcontrol,
620 struct snd_ctl_elem_value *ucontrol)
621{
622 switch (ucontrol->value.integer.value[0]) {
623 case 2:
624 mi2s_rx_bit_format = SNDRV_PCM_FORMAT_S24_3LE;
625 mi2s_rx_bits_per_sample = 32;
626 break;
627 case 1:
628 mi2s_rx_bit_format = SNDRV_PCM_FORMAT_S24_LE;
629 mi2s_rx_bits_per_sample = 32;
630 break;
631 case 0:
632 default:
633 mi2s_rx_bit_format = SNDRV_PCM_FORMAT_S16_LE;
634 mi2s_rx_bits_per_sample = 16;
635 break;
636 }
637 return 0;
638}
639
640static int mi2s_tx_bit_format_put(struct snd_kcontrol *kcontrol,
641 struct snd_ctl_elem_value *ucontrol)
642{
643 switch (ucontrol->value.integer.value[0]) {
644 case 3:
645 mi2s_tx_bit_format = SNDRV_PCM_FORMAT_S32_LE;
646 mi2s_tx_bits_per_sample = 32;
647 break;
648 case 2:
649 mi2s_tx_bit_format = SNDRV_PCM_FORMAT_S24_3LE;
650 mi2s_tx_bits_per_sample = 32;
651 break;
652 case 1:
653 mi2s_tx_bit_format = SNDRV_PCM_FORMAT_S24_LE;
654 mi2s_tx_bits_per_sample = 32;
655 break;
656 case 0:
657 default:
658 mi2s_tx_bit_format = SNDRV_PCM_FORMAT_S16_LE;
659 mi2s_tx_bits_per_sample = 16;
660 break;
661 }
662 return 0;
663}
664
665static int mi2s_tx_bit_format_get(struct snd_kcontrol *kcontrol,
666 struct snd_ctl_elem_value *ucontrol)
667{
668
669 switch (mi2s_tx_bit_format) {
670 case SNDRV_PCM_FORMAT_S32_LE:
671 ucontrol->value.integer.value[0] = 3;
672 break;
673
674 case SNDRV_PCM_FORMAT_S24_3LE:
675 ucontrol->value.integer.value[0] = 2;
676 break;
677
678 case SNDRV_PCM_FORMAT_S24_LE:
679 ucontrol->value.integer.value[0] = 1;
680 break;
681
682 case SNDRV_PCM_FORMAT_S16_LE:
683 default:
684 ucontrol->value.integer.value[0] = 0;
685 break;
686 }
687
688 pr_debug("%s: mi2s_tx_bit_format = %d, ucontrol value = %ld\n",
689 __func__, mi2s_tx_bit_format,
690 ucontrol->value.integer.value[0]);
691
692 return 0;
693}
694
695static int msm_pri_mi2s_rx_ch_get(struct snd_kcontrol *kcontrol,
696 struct snd_ctl_elem_value *ucontrol)
697{
698 pr_debug("%s: msm_pri_mi2s_rx_ch = %d\n", __func__,
699 msm_pri_mi2s_rx_ch);
700 ucontrol->value.integer.value[0] = msm_pri_mi2s_rx_ch - 1;
701 return 0;
702}
703
704static int msm_pri_mi2s_rx_ch_put(struct snd_kcontrol *kcontrol,
705 struct snd_ctl_elem_value *ucontrol)
706{
707 msm_pri_mi2s_rx_ch = ucontrol->value.integer.value[0] + 1;
708
709 pr_debug("%s: msm_pri_mi2s_rx_ch = %d\n", __func__, msm_pri_mi2s_rx_ch);
710 return 1;
711}
712
713static int mi2s_rx_sample_rate_get(struct snd_kcontrol *kcontrol,
714 struct snd_ctl_elem_value *ucontrol)
715{
716 int sample_rate_val = 0;
717
718 switch (mi2s_rx_sample_rate) {
719 case SAMPLING_RATE_96KHZ:
720 sample_rate_val = 1;
721 break;
722 case SAMPLING_RATE_192KHZ:
723 sample_rate_val = 2;
724 break;
725 case SAMPLING_RATE_48KHZ:
726 default:
727 sample_rate_val = 0;
728 break;
729 }
730
731 ucontrol->value.integer.value[0] = sample_rate_val;
732 pr_debug("%s: sample_rate_val = %d\n", __func__,
733 sample_rate_val);
734
735 return 0;
736}
737
738static int mi2s_rx_sample_rate_put(struct snd_kcontrol *kcontrol,
739 struct snd_ctl_elem_value *ucontrol)
740{
741 switch (ucontrol->value.integer.value[0]) {
742 case 1:
743 mi2s_rx_sample_rate = SAMPLING_RATE_96KHZ;
744 break;
745 case 2:
746 mi2s_rx_sample_rate = SAMPLING_RATE_192KHZ;
747 break;
748 case 0:
749 default:
750 mi2s_rx_sample_rate = SAMPLING_RATE_48KHZ;
751 break;
752 }
753 pr_debug("%s: mi2s_rx_sample_rate = %d\n", __func__,
754 mi2s_rx_sample_rate);
755 return 0;
756}
757
758static int msm_ter_mi2s_tx_ch_get(struct snd_kcontrol *kcontrol,
759 struct snd_ctl_elem_value *ucontrol)
760{
761 pr_debug("%s: msm_ter_mi2s_tx_ch = %d\n", __func__,
762 msm_ter_mi2s_tx_ch);
763 ucontrol->value.integer.value[0] = msm_ter_mi2s_tx_ch - 1;
764 return 0;
765}
766
767static int msm_ter_mi2s_tx_ch_put(struct snd_kcontrol *kcontrol,
768 struct snd_ctl_elem_value *ucontrol)
769{
770 msm_ter_mi2s_tx_ch = ucontrol->value.integer.value[0] + 1;
771
772 pr_debug("%s: msm_ter_mi2s_tx_ch = %d\n", __func__, msm_ter_mi2s_tx_ch);
773 return 1;
774}
775
776static const struct soc_enum msm_snd_enum[] = {
777 SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(bit_format_text),
778 bit_format_text),
779 SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(mi2s_ch_text),
780 mi2s_ch_text),
781 SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(btsco_rate_text),
782 btsco_rate_text),
783 SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(proxy_rx_ch_text),
784 proxy_rx_ch_text),
785 SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(mi2s_rx_sample_rate_text),
786 mi2s_rx_sample_rate_text),
787};
788
789static const struct snd_kcontrol_new msm_snd_controls[] = {
790 SOC_ENUM_EXT("MI2S_RX Format", msm_snd_enum[0],
791 mi2s_rx_bit_format_get, mi2s_rx_bit_format_put),
792 SOC_ENUM_EXT("MI2S_TX Format", msm_snd_enum[0],
793 mi2s_tx_bit_format_get, mi2s_tx_bit_format_put),
794 SOC_ENUM_EXT("MI2S_TX Channels", msm_snd_enum[1],
795 msm_ter_mi2s_tx_ch_get, msm_ter_mi2s_tx_ch_put),
796 SOC_ENUM_EXT("MI2S_RX Channels", msm_snd_enum[1],
797 msm_pri_mi2s_rx_ch_get, msm_pri_mi2s_rx_ch_put),
798 SOC_ENUM_EXT("Internal BTSCO SampleRate", msm_snd_enum[2],
799 msm_btsco_rate_get, msm_btsco_rate_put),
800 SOC_ENUM_EXT("PROXY_RX Channels", msm_snd_enum[3],
801 msm_proxy_rx_ch_get, msm_proxy_rx_ch_put),
802 SOC_ENUM_EXT("MI2S_RX SampleRate", msm_snd_enum[4],
803 mi2s_rx_sample_rate_get, mi2s_rx_sample_rate_put),
804};
805
806static int msm_mclk_event(struct snd_soc_dapm_widget *w,
807 struct snd_kcontrol *kcontrol, int event)
808{
809 struct msm_asoc_mach_data *pdata = NULL;
810 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
811
812 pdata = snd_soc_card_get_drvdata(codec->component.card);
813 pr_debug("%s: event = %d\n", __func__, event);
814 switch (event) {
815 case SND_SOC_DAPM_POST_PMD:
816 pr_debug("%s: mclk_res_ref = %d\n",
817 __func__, atomic_read(&pdata->int_mclk0_rsc_ref));
818 if (atomic_read(&pdata->int_mclk0_rsc_ref) == 0) {
819 pr_debug("%s: disabling MCLK\n", __func__);
820 /* disable the codec mclk config*/
821 msm_digcdc_mclk_enable(codec, 0, true);
822 msm_enable_dig_cdc_clk(codec, 0, true);
823 }
824 break;
825 default:
826 pr_err("%s: invalid DAPM event %d\n", __func__, event);
827 return -EINVAL;
828 }
829 return 0;
830}
831
832static int msm_mi2s_snd_startup(struct snd_pcm_substream *substream)
833{
834 struct snd_soc_pcm_runtime *rtd = substream->private_data;
835 struct snd_soc_card *card = rtd->card;
836 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
837 struct snd_soc_codec *codec = rtd->codec;
838 struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
839 int ret = 0, val = 0;
840
841 pr_debug("%s(): substream = %s stream = %d\n", __func__,
842 substream->name, substream->stream);
843
844 if (!q6core_is_adsp_ready()) {
845 pr_err("%s(): adsp not ready\n", __func__);
846 return -EINVAL;
847 }
848
849 /*
850 * configure the slave select to
851 * invalid state for internal codec
852 */
853 if (pdata->vaddr_gpio_mux_spkr_ctl) {
854 val = ioread32(pdata->vaddr_gpio_mux_spkr_ctl);
855 val = val | 0x00010000;
856 iowrite32(val, pdata->vaddr_gpio_mux_spkr_ctl);
857 }
858
859 if (pdata->vaddr_gpio_mux_mic_ctl) {
860 val = ioread32(pdata->vaddr_gpio_mux_mic_ctl);
861 val = val | 0x00200000;
862 iowrite32(val, pdata->vaddr_gpio_mux_mic_ctl);
863 }
864
865 ret = msm_mi2s_sclk_ctl(substream, true);
866 if (ret < 0) {
867 pr_err("%s: failed to enable sclk %d\n",
868 __func__, ret);
869 return ret;
870 }
871 ret = msm_enable_dig_cdc_clk(codec, 1, true);
872 if (ret < 0) {
873 pr_err("failed to enable mclk\n");
874 return ret;
875 }
876 /* Enable the codec mclk config */
877 msm_digcdc_mclk_enable(codec, 1, true);
878 ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_CBS_CFS);
879 if (ret < 0)
880 pr_err("%s: set fmt cpu dai failed; ret=%d\n", __func__, ret);
881
882 return ret;
883}
884
885static void msm_mi2s_snd_shutdown(struct snd_pcm_substream *substream)
886{
887 int ret;
888 struct snd_soc_pcm_runtime *rtd = substream->private_data;
889 struct snd_soc_card *card = rtd->card;
890 struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
891
892 pr_debug("%s(): substream = %s stream = %d\n", __func__,
893 substream->name, substream->stream);
894
895 ret = msm_mi2s_sclk_ctl(substream, false);
896 if (ret < 0)
897 pr_err("%s:clock disable failed; ret=%d\n", __func__,
898 ret);
899 if (atomic_read(&pdata->int_mclk0_rsc_ref) > 0) {
900 atomic_dec(&pdata->int_mclk0_rsc_ref);
901 pr_debug("%s: decrementing mclk_res_ref %d\n", __func__,
902 atomic_read(&pdata->int_mclk0_rsc_ref));
903 }
904}
905
906static int msm_prim_auxpcm_startup(struct snd_pcm_substream *substream)
907{
908 struct snd_soc_pcm_runtime *rtd = substream->private_data;
909 struct snd_soc_codec *codec = rtd->codec;
910 struct snd_soc_card *card = rtd->card;
911 struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
912 int ret = 0, val = 0;
913
914 pr_debug("%s(): substream = %s\n",
915 __func__, substream->name);
916
917 if (!q6core_is_adsp_ready()) {
918 pr_err("%s(): adsp not ready\n", __func__);
919 return -EINVAL;
920 }
921
922 /* mux config to route the AUX MI2S */
923 if (pdata->vaddr_gpio_mux_mic_ctl) {
924 val = ioread32(pdata->vaddr_gpio_mux_mic_ctl);
925 val = val | 0x2;
926 iowrite32(val, pdata->vaddr_gpio_mux_mic_ctl);
927 }
928 if (pdata->vaddr_gpio_mux_pcm_ctl) {
929 val = ioread32(pdata->vaddr_gpio_mux_pcm_ctl);
930 val = val | 0x1;
931 iowrite32(val, pdata->vaddr_gpio_mux_pcm_ctl);
932 }
933 msm_enable_dig_cdc_clk(codec, 1, true);
934 atomic_inc(&auxpcm_mi2s_clk_ref);
935
936 /* enable the gpio's used for the external AUXPCM interface */
937 if (pdata->mi2s_gpio_p[QUAT_MI2S]) {
938 ret = msm_cdc_pinctrl_select_active_state(
939 pdata->mi2s_gpio_p[QUAT_MI2S]);
940 if (ret < 0)
941 pr_err("%s(): configure gpios failed = %s\n",
942 __func__, "quat_i2s");
943 }
944 return ret;
945}
946
947static void msm_prim_auxpcm_shutdown(struct snd_pcm_substream *substream)
948{
949 int ret = 0;
950 struct snd_soc_pcm_runtime *rtd = substream->private_data;
951 struct snd_soc_card *card = rtd->card;
952 struct snd_soc_codec *codec = rtd->codec;
953 struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
954
955 pr_debug("%s(): substream = %s\n",
956 __func__, substream->name);
957 if (atomic_read(&pdata->int_mclk0_rsc_ref) > 0) {
958 atomic_dec(&pdata->int_mclk0_rsc_ref);
959 pr_debug("%s: decrementing mclk_res_ref %d\n",
960 __func__, atomic_read(&pdata->int_mclk0_rsc_ref));
961 }
962 if (atomic_read(&auxpcm_mi2s_clk_ref) > 0)
963 atomic_dec(&auxpcm_mi2s_clk_ref);
964 if ((atomic_read(&auxpcm_mi2s_clk_ref) == 0) &&
965 (atomic_read(&pdata->int_mclk0_rsc_ref) == 0)) {
966 msm_enable_dig_cdc_clk(codec, 0, true);
967 }
968 if (pdata->mi2s_gpio_p[QUAT_MI2S]) {
969 ret = msm_cdc_pinctrl_select_sleep_state(
970 pdata->mi2s_gpio_p[QUAT_MI2S]);
971 if (ret < 0)
972 pr_err("%s(): configure gpios failed = %s\n",
973 __func__, "quat_i2s");
974 }
975}
976
977static int msm_sec_mi2s_snd_startup(struct snd_pcm_substream *substream)
978{
979 struct snd_soc_pcm_runtime *rtd = substream->private_data;
980 struct snd_soc_card *card = rtd->card;
981 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
982 struct msm_asoc_mach_data *pdata =
983 snd_soc_card_get_drvdata(card);
984 int ret = 0, val = 0;
985
986 pr_debug("%s(): substream = %s stream = %d\n", __func__,
987 substream->name, substream->stream);
988
989 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
990 pr_info("%s: Secondary Mi2s does not support capture\n",
991 __func__);
992 return 0;
993 }
994
995 if (!q6core_is_adsp_ready()) {
996 pr_err("%s(): adsp not ready\n", __func__);
997 return -EINVAL;
998 }
999
1000 if ((pdata->ext_pa & SEC_MI2S_ID) == SEC_MI2S_ID) {
1001 if (pdata->vaddr_gpio_mux_spkr_ctl) {
1002 val = ioread32(pdata->vaddr_gpio_mux_spkr_ctl);
1003 val = val | 0x0004835c;
1004 iowrite32(val, pdata->vaddr_gpio_mux_spkr_ctl);
1005 }
1006 ret = msm_mi2s_sclk_ctl(substream, true);
1007 if (ret < 0) {
1008 pr_err("failed to enable sclk\n");
1009 return ret;
1010 }
1011 pr_debug("%s(): SEC I2S gpios turned on = %s\n", __func__,
1012 "sec_i2s");
1013 if (pdata->mi2s_gpio_p[SEC_MI2S]) {
1014 ret = msm_cdc_pinctrl_select_active_state(
1015 pdata->mi2s_gpio_p[SEC_MI2S]);
1016 if (ret < 0) {
1017 pr_err("%s: gpio set cannot be activated %sd",
1018 __func__, "sec_i2s");
1019 goto err;
1020 }
1021 }
1022 } else {
1023 pr_err("%s: error codec type\n", __func__);
1024 }
1025 ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_CBS_CFS);
1026 if (ret < 0) {
1027 pr_err("%s: set fmt cpu dai failed\n", __func__);
1028 if (pdata->mi2s_gpio_p[SEC_MI2S]) {
1029 ret = msm_cdc_pinctrl_select_sleep_state(
1030 pdata->mi2s_gpio_p[SEC_MI2S]);
1031 if (ret < 0) {
1032 pr_err("%s: gpio de-activate error %s",
1033 __func__, "sec_i2s");
1034 goto err;
1035 }
1036 }
1037 }
1038 return ret;
1039err:
1040 ret = msm_mi2s_sclk_ctl(substream, false);
1041 if (ret < 0)
1042 pr_err("failed to disable sclk\n");
1043 return ret;
1044}
1045
1046static void msm_sec_mi2s_snd_shutdown(struct snd_pcm_substream *substream)
1047{
1048 int ret = 0;
1049 struct snd_soc_pcm_runtime *rtd = substream->private_data;
1050 struct snd_soc_card *card = rtd->card;
1051 struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
1052
1053 pr_debug("%s(): substream = %s stream = %d\n", __func__,
1054 substream->name, substream->stream);
1055 if ((pdata->ext_pa & SEC_MI2S_ID) == SEC_MI2S_ID) {
1056 if (pdata->mi2s_gpio_p[SEC_MI2S]) {
1057 ret = msm_cdc_pinctrl_select_sleep_state(
1058 pdata->mi2s_gpio_p[SEC_MI2S]);
1059 if (ret < 0) {
1060 pr_err("%s: gpio set cannot be de-activated: %sd",
1061 __func__, "sec_i2s");
1062 return;
1063 }
1064 }
1065 ret = msm_mi2s_sclk_ctl(substream, false);
1066 if (ret < 0)
1067 pr_err("%s:clock disable failed\n", __func__);
1068 }
1069}
1070
1071static int msm_quat_mi2s_snd_startup(struct snd_pcm_substream *substream)
1072{
1073 struct snd_soc_pcm_runtime *rtd = substream->private_data;
1074 struct snd_soc_card *card = rtd->card;
1075 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
1076 struct msm_asoc_mach_data *pdata =
1077 snd_soc_card_get_drvdata(card);
1078 int ret = 0, val = 0;
1079
1080 pr_debug("%s(): substream = %s stream = %d\n", __func__,
1081 substream->name, substream->stream);
1082
1083 if (!q6core_is_adsp_ready()) {
1084 pr_err("%s(): adsp not ready\n", __func__);
1085 return -EINVAL;
1086 }
1087
1088 if (pdata->vaddr_gpio_mux_mic_ctl) {
1089 val = ioread32(pdata->vaddr_gpio_mux_mic_ctl);
1090 val = val | 0x02020002;
1091 iowrite32(val, pdata->vaddr_gpio_mux_mic_ctl);
1092 }
1093 ret = msm_mi2s_sclk_ctl(substream, true);
1094 if (ret < 0) {
1095 pr_err("failed to enable sclk\n");
1096 return ret;
1097 }
1098 if (pdata->mi2s_gpio_p[QUAT_MI2S]) {
1099 ret = msm_cdc_pinctrl_select_active_state(
1100 pdata->mi2s_gpio_p[QUAT_MI2S]);
1101 if (ret < 0) {
1102 pr_err("failed to enable codec gpios\n");
1103 goto err;
1104 }
1105 }
1106 if (atomic_inc_return(&quat_mi2s_clk_ref) == 1) {
1107 ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_CBS_CFS);
1108 if (ret < 0)
1109 pr_err("%s: set fmt cpu dai failed\n", __func__);
1110 }
1111 return ret;
1112err:
1113 ret = msm_mi2s_sclk_ctl(substream, false);
1114 if (ret < 0)
1115 pr_err("failed to disable sclk\n");
1116 return ret;
1117}
1118
1119static void msm_quat_mi2s_snd_shutdown(struct snd_pcm_substream *substream)
1120{
1121 struct snd_soc_pcm_runtime *rtd = substream->private_data;
1122 struct snd_soc_card *card = rtd->card;
1123 struct msm_asoc_mach_data *pdata =
1124 snd_soc_card_get_drvdata(card);
1125 int ret = 0;
1126
1127 pr_debug("%s(): substream = %s stream = %d\n", __func__,
1128 substream->name, substream->stream);
1129 ret = msm_mi2s_sclk_ctl(substream, false);
1130 if (ret < 0)
1131 pr_err("%s:clock disable failed\n", __func__);
1132 if (atomic_read(&quat_mi2s_clk_ref) > 0)
1133 atomic_dec(&quat_mi2s_clk_ref);
1134 if (pdata->mi2s_gpio_p[QUAT_MI2S]) {
1135 ret = msm_cdc_pinctrl_select_sleep_state(
1136 pdata->mi2s_gpio_p[QUAT_MI2S]);
1137 if (ret < 0) {
1138 pr_err("%s: gpio set cannot be de-activated %sd",
1139 __func__, "quat_i2s");
1140 return;
1141 }
1142 }
1143}
1144
1145static int msm_quin_mi2s_snd_startup(struct snd_pcm_substream *substream)
1146{
1147 struct snd_soc_pcm_runtime *rtd = substream->private_data;
1148 struct snd_soc_card *card = rtd->card;
1149 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
1150 struct msm_asoc_mach_data *pdata =
1151 snd_soc_card_get_drvdata(card);
1152 int ret = 0, val = 0;
1153
1154 pr_debug("%s(): substream = %s stream = %d\n", __func__,
1155 substream->name, substream->stream);
1156
1157 if (!q6core_is_adsp_ready()) {
1158 pr_err("%s(): adsp not ready\n", __func__);
1159 return -EINVAL;
1160 }
1161
1162 if (pdata->vaddr_gpio_mux_quin_ctl) {
1163 val = ioread32(pdata->vaddr_gpio_mux_quin_ctl);
1164 val = val | 0x00000001;
1165 iowrite32(val, pdata->vaddr_gpio_mux_quin_ctl);
1166 } else {
1167 return -EINVAL;
1168 }
1169 ret = msm_mi2s_sclk_ctl(substream, true);
1170 if (ret < 0) {
1171 pr_err("failed to enable sclk\n");
1172 return ret;
1173 }
1174 if (pdata->mi2s_gpio_p[QUIN_MI2S]) {
1175 ret = msm_cdc_pinctrl_select_active_state(
1176 pdata->mi2s_gpio_p[QUIN_MI2S]);
1177 if (ret < 0) {
1178 pr_err("failed to enable codec gpios\n");
1179 goto err;
1180 }
1181 }
1182 if (atomic_inc_return(&quin_mi2s_clk_ref) == 1) {
1183 ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_CBS_CFS);
1184 if (ret < 0)
1185 pr_err("%s: set fmt cpu dai failed\n", __func__);
1186 }
1187 return ret;
1188err:
1189 ret = msm_mi2s_sclk_ctl(substream, false);
1190 if (ret < 0)
1191 pr_err("failed to disable sclk\n");
1192 return ret;
1193}
1194
1195static void msm_quin_mi2s_snd_shutdown(struct snd_pcm_substream *substream)
1196{
1197 struct snd_soc_pcm_runtime *rtd = substream->private_data;
1198 struct snd_soc_card *card = rtd->card;
1199 struct msm_asoc_mach_data *pdata =
1200 snd_soc_card_get_drvdata(card);
1201 int ret = 0;
1202
1203 pr_debug("%s(): substream = %s stream = %d\n", __func__,
1204 substream->name, substream->stream);
1205 ret = msm_mi2s_sclk_ctl(substream, false);
1206 if (ret < 0)
1207 pr_err("%s:clock disable failed\n", __func__);
1208 if (atomic_read(&quin_mi2s_clk_ref) > 0)
1209 atomic_dec(&quin_mi2s_clk_ref);
1210 if (pdata->mi2s_gpio_p[QUIN_MI2S]) {
1211 ret = msm_cdc_pinctrl_select_sleep_state(
1212 pdata->mi2s_gpio_p[QUIN_MI2S]);
1213 if (ret < 0) {
1214 pr_err("%s: gpio set cannot be de-activated %sd",
1215 __func__, "quin_i2s");
1216 return;
1217 }
1218 }
1219}
1220
1221static int msm_audrx_init(struct snd_soc_pcm_runtime *rtd)
1222{
1223 struct snd_soc_codec *codec = rtd->codec;
1224 struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
1225 struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(rtd->card);
1226 struct snd_card *card;
1227
1228 snd_soc_add_codec_controls(codec, msm_snd_controls,
1229 ARRAY_SIZE(msm_snd_controls));
1230
1231 snd_soc_dapm_new_controls(dapm, msm8909_dapm_widgets,
1232 ARRAY_SIZE(msm8909_dapm_widgets));
1233
1234 snd_soc_dapm_ignore_suspend(dapm, "Digital Mic1");
1235 snd_soc_dapm_ignore_suspend(dapm, "Digital Mic2");
1236
1237 snd_soc_dapm_ignore_suspend(dapm, "DMIC1");
1238 snd_soc_dapm_ignore_suspend(dapm, "DMIC2");
1239
1240 snd_soc_dapm_sync(dapm);
1241
1242 card = rtd->card->snd_card;
1243 if (!codec_root) {
1244 codec_root = snd_info_create_subdir(card->module, "codecs",
1245 card->proc_root);
1246 if (codec_root)
1247 msm_dig_codec_info_create_codec_entry(codec_root,
1248 codec);
1249 else
1250 pr_debug("%s: Cannot create codecs module entry\n",
1251 __func__);
1252 }
1253 pdata->codec_root = codec_root;
1254 msm_dig_codec_info_create_codec_entry(codec_root, codec);
1255 return 0;
1256}
1257
1258static struct snd_soc_ops msm8909_quat_mi2s_be_ops = {
1259 .startup = msm_quat_mi2s_snd_startup,
1260 .hw_params = msm_mi2s_snd_hw_params,
1261 .shutdown = msm_quat_mi2s_snd_shutdown,
1262};
1263
1264static struct snd_soc_ops msm8909_quin_mi2s_be_ops = {
1265 .startup = msm_quin_mi2s_snd_startup,
1266 .hw_params = msm_mi2s_snd_hw_params,
1267 .shutdown = msm_quin_mi2s_snd_shutdown,
1268};
1269
1270static struct snd_soc_ops msm8909_sec_mi2s_be_ops = {
1271 .startup = msm_sec_mi2s_snd_startup,
1272 .hw_params = msm_mi2s_snd_hw_params,
1273 .shutdown = msm_sec_mi2s_snd_shutdown,
1274};
1275
1276static struct snd_soc_ops msm8909_mi2s_be_ops = {
1277 .startup = msm_mi2s_snd_startup,
1278 .hw_params = msm_mi2s_snd_hw_params,
1279 .shutdown = msm_mi2s_snd_shutdown,
1280};
1281
1282static struct snd_soc_ops msm_pri_auxpcm_be_ops = {
1283 .startup = msm_prim_auxpcm_startup,
1284 .shutdown = msm_prim_auxpcm_shutdown,
1285};
1286
1287/* Digital audio interface glue - connects codec <---> CPU */
1288static struct snd_soc_dai_link msm8909_dai[] = {
1289 /* FrontEnd DAI Links */
1290 {/* hw:x,0 */
1291 .name = "MSM8909 Media1",
1292 .stream_name = "MultiMedia1",
1293 .cpu_dai_name = "MultiMedia1",
1294 .platform_name = "msm-pcm-dsp.0",
1295 .dynamic = 1,
1296 .async_ops = ASYNC_DPCM_SND_SOC_PREPARE,
1297 .dpcm_playback = 1,
1298 .dpcm_capture = 1,
1299 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
1300 SND_SOC_DPCM_TRIGGER_POST},
1301 .codec_dai_name = "snd-soc-dummy-dai",
1302 .codec_name = "snd-soc-dummy",
1303 .ignore_suspend = 1,
1304 /* this dainlink has playback support */
1305 .ignore_pmdown_time = 1,
1306 .id = MSM_FRONTEND_DAI_MULTIMEDIA1
1307 },
1308 {/* hw:x,1 */
1309 .name = "MSM8909 Media2",
1310 .stream_name = "MultiMedia2",
1311 .cpu_dai_name = "MultiMedia2",
1312 .platform_name = "msm-pcm-dsp.0",
1313 .dynamic = 1,
1314 .dpcm_playback = 1,
1315 .dpcm_capture = 1,
1316 .codec_dai_name = "snd-soc-dummy-dai",
1317 .codec_name = "snd-soc-dummy",
1318 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
1319 SND_SOC_DPCM_TRIGGER_POST},
1320 .ignore_suspend = 1,
1321 /* this dainlink has playback support */
1322 .ignore_pmdown_time = 1,
1323 .id = MSM_FRONTEND_DAI_MULTIMEDIA2,
1324 },
1325 {/* hw:x,2 */
1326 .name = "Circuit-Switch Voice",
1327 .stream_name = "CS-Voice",
1328 .cpu_dai_name = "VoiceMMode1",
1329 .platform_name = "msm-pcm-voice",
1330 .dynamic = 1,
1331 .dpcm_playback = 1,
1332 .dpcm_capture = 1,
1333 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
1334 SND_SOC_DPCM_TRIGGER_POST},
1335 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
1336 .ignore_suspend = 1,
1337 /* this dainlink has playback support */
1338 .ignore_pmdown_time = 1,
1339 .id = MSM_FRONTEND_DAI_CS_VOICE,
1340 .codec_dai_name = "snd-soc-dummy-dai",
1341 .codec_name = "snd-soc-dummy",
1342 },
1343 {/* hw:x,3 */
1344 .name = "MSM VoIP",
1345 .stream_name = "VoIP",
1346 .cpu_dai_name = "VoIP",
1347 .platform_name = "msm-voip-dsp",
1348 .dynamic = 1,
1349 .dpcm_playback = 1,
1350 .dpcm_capture = 1,
1351 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
1352 SND_SOC_DPCM_TRIGGER_POST},
1353 .codec_dai_name = "snd-soc-dummy-dai",
1354 .codec_name = "snd-soc-dummy",
1355 .ignore_suspend = 1,
1356 /* this dainlink has playback support */
1357 .ignore_pmdown_time = 1,
1358 .id = MSM_FRONTEND_DAI_VOIP,
1359 },
1360 {/* hw:x,4 */
1361 .name = "MSM8X16 ULL",
1362 .stream_name = "ULL",
1363 .cpu_dai_name = "MultiMedia3",
1364 .platform_name = "msm-pcm-dsp.2",
1365 .dynamic = 1,
1366 .async_ops = ASYNC_DPCM_SND_SOC_PREPARE,
1367 .dpcm_playback = 1,
1368 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
1369 SND_SOC_DPCM_TRIGGER_POST},
1370 .codec_dai_name = "snd-soc-dummy-dai",
1371 .codec_name = "snd-soc-dummy",
1372 .ignore_suspend = 1,
1373 /* this dainlink has playback support */
1374 .ignore_pmdown_time = 1,
1375 .id = MSM_FRONTEND_DAI_MULTIMEDIA3,
1376 },
1377 /* Hostless PCM purpose */
1378 {/* hw:x,5 */
1379 .name = "Primary MI2S_RX Hostless",
1380 .stream_name = "Primary MI2S_RX Hostless",
1381 .cpu_dai_name = "PRI_MI2S_RX_HOSTLESS",
1382 .platform_name = "msm-pcm-hostless",
1383 .dynamic = 1,
1384 .dpcm_playback = 1,
1385 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
1386 SND_SOC_DPCM_TRIGGER_POST},
1387 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
1388 .ignore_suspend = 1,
1389 /* this dailink has playback support */
1390 .ignore_pmdown_time = 1,
1391 /* This dainlink has MI2S support */
1392 .codec_dai_name = "snd-soc-dummy-dai",
1393 .codec_name = "snd-soc-dummy",
1394 },
1395 {/* hw:x,6 */
1396 .name = "INT_FM Hostless",
1397 .stream_name = "INT_FM Hostless",
1398 .cpu_dai_name = "INT_FM_HOSTLESS",
1399 .platform_name = "msm-pcm-hostless",
1400 .dynamic = 1,
1401 .dpcm_capture = 1,
1402 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
1403 SND_SOC_DPCM_TRIGGER_POST},
1404 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
1405 .ignore_suspend = 1,
1406 /* this dainlink has playback support */
1407 .ignore_pmdown_time = 1,
1408 .codec_dai_name = "snd-soc-dummy-dai",
1409 .codec_name = "snd-soc-dummy",
1410 },
1411 {/* hw:x,7 */
1412 .name = "MSM AFE-PCM RX",
1413 .stream_name = "AFE-PROXY RX",
1414 .cpu_dai_name = "msm-dai-q6-dev.241",
1415 .codec_name = "msm-stub-codec.1",
1416 .codec_dai_name = "msm-stub-rx",
1417 .platform_name = "msm-pcm-afe",
1418 .ignore_suspend = 1,
1419 /* this dainlink has playback support */
1420 .ignore_pmdown_time = 1,
1421 },
1422 {/* hw:x,8 */
1423 .name = "MSM AFE-PCM TX",
1424 .stream_name = "AFE-PROXY TX",
1425 .cpu_dai_name = "msm-dai-q6-dev.240",
1426 .codec_name = "msm-stub-codec.1",
1427 .codec_dai_name = "msm-stub-tx",
1428 .platform_name = "msm-pcm-afe",
1429 .ignore_suspend = 1,
1430 },
1431 {/* hw:x,9 */
1432 .name = "MSM8909 Compress1",
1433 .stream_name = "Compress1",
1434 .cpu_dai_name = "MultiMedia4",
1435 .platform_name = "msm-compress-dsp",
1436 .dynamic = 1,
1437 .async_ops = ASYNC_DPCM_SND_SOC_HW_PARAMS,
1438 .dpcm_playback = 1,
1439 .dpcm_capture = 1,
1440 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
1441 SND_SOC_DPCM_TRIGGER_POST},
1442 .codec_dai_name = "snd-soc-dummy-dai",
1443 .codec_name = "snd-soc-dummy",
1444 .ignore_suspend = 1,
1445 .ignore_pmdown_time = 1,
1446 /* this dainlink has playback support */
1447 .id = MSM_FRONTEND_DAI_MULTIMEDIA4,
1448 },
1449 {/* hw:x,10 */
1450 .name = "AUXPCM Hostless",
1451 .stream_name = "AUXPCM Hostless",
1452 .cpu_dai_name = "AUXPCM_HOSTLESS",
1453 .platform_name = "msm-pcm-hostless",
1454 .dynamic = 1,
1455 .dpcm_playback = 1,
1456 .dpcm_capture = 1,
1457 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
1458 SND_SOC_DPCM_TRIGGER_POST},
1459 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
1460 .ignore_suspend = 1,
1461 /* this dainlink has playback support */
1462 .ignore_pmdown_time = 1,
1463 .codec_dai_name = "snd-soc-dummy-dai",
1464 .codec_name = "snd-soc-dummy",
1465 },
1466 {/* hw:x,11 */
1467 .name = "Tertiary MI2S_TX Hostless",
1468 .stream_name = "Tertiary MI2S_TX Hostless",
1469 .cpu_dai_name = "TERT_MI2S_TX_HOSTLESS",
1470 .platform_name = "msm-pcm-hostless",
1471 .dynamic = 1,
1472 .dpcm_capture = 1,
1473 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
1474 SND_SOC_DPCM_TRIGGER_POST},
1475 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
1476 .ignore_suspend = 1,
1477 .ignore_pmdown_time = 1, /* dai link has playback support */
1478 .codec_dai_name = "snd-soc-dummy-dai",
1479 .codec_name = "snd-soc-dummy",
1480 },
1481 {/* hw:x,12 */
1482 .name = "MSM8x16 LowLatency",
1483 .stream_name = "MultiMedia5",
1484 .cpu_dai_name = "MultiMedia5",
1485 .platform_name = "msm-pcm-dsp.1",
1486 .dynamic = 1,
1487 .dpcm_playback = 1,
1488 .dpcm_capture = 1,
1489 .async_ops = ASYNC_DPCM_SND_SOC_PREPARE |
1490 ASYNC_DPCM_SND_SOC_HW_PARAMS,
1491 .codec_dai_name = "snd-soc-dummy-dai",
1492 .codec_name = "snd-soc-dummy",
1493 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
1494 SND_SOC_DPCM_TRIGGER_POST},
1495 .ignore_suspend = 1,
1496 /* this dainlink has playback support */
1497 .ignore_pmdown_time = 1,
1498 .id = MSM_FRONTEND_DAI_MULTIMEDIA5,
1499 },
1500 {/* hw:x,13 */
1501 .name = "Voice2",
1502 .stream_name = "Voice2",
1503 .cpu_dai_name = "VoiceMMode1",
1504 .platform_name = "msm-pcm-voice",
1505 .dynamic = 1,
1506 .dpcm_playback = 1,
1507 .dpcm_capture = 1,
1508 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
1509 SND_SOC_DPCM_TRIGGER_POST},
1510 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
1511 .ignore_suspend = 1,
1512 /* this dainlink has playback support */
1513 .ignore_pmdown_time = 1,
1514 .codec_dai_name = "snd-soc-dummy-dai",
1515 .codec_name = "snd-soc-dummy",
1516 .id = MSM_FRONTEND_DAI_VOICE2,
1517 },
1518 {/* hw:x,14 */
1519 .name = "MSM8x16 Media9",
1520 .stream_name = "MultiMedia9",
1521 .cpu_dai_name = "MultiMedia9",
1522 .platform_name = "msm-pcm-dsp.0",
1523 .dynamic = 1,
1524 .dpcm_playback = 1,
1525 .dpcm_capture = 1,
1526 .codec_dai_name = "snd-soc-dummy-dai",
1527 .codec_name = "snd-soc-dummy",
1528 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
1529 SND_SOC_DPCM_TRIGGER_POST},
1530 .ignore_suspend = 1,
1531 /* This dailink has playback support */
1532 .ignore_pmdown_time = 1,
1533 .id = MSM_FRONTEND_DAI_MULTIMEDIA9,
1534 },
1535 { /* hw:x,15 */
1536 .name = "VoLTE",
1537 .stream_name = "VoLTE",
1538 .cpu_dai_name = "VoiceMMode1",
1539 .platform_name = "msm-pcm-voice",
1540 .dynamic = 1,
1541 .dpcm_playback = 1,
1542 .dpcm_capture = 1,
1543 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
1544 SND_SOC_DPCM_TRIGGER_POST},
1545 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
1546 .ignore_suspend = 1,
1547 /* this dainlink has playback support */
1548 .ignore_pmdown_time = 1,
1549 .codec_dai_name = "snd-soc-dummy-dai",
1550 .codec_name = "snd-soc-dummy",
1551 .id = MSM_FRONTEND_DAI_VOLTE,
1552 },
1553 { /* hw:x,16 */
1554 .name = "VoWLAN",
1555 .stream_name = "VoWLAN",
1556 .cpu_dai_name = "VoiceMMode1",
1557 .platform_name = "msm-pcm-voice",
1558 .dynamic = 1,
1559 .dpcm_playback = 1,
1560 .dpcm_capture = 1,
1561 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
1562 SND_SOC_DPCM_TRIGGER_POST},
1563 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
1564 .ignore_suspend = 1,
1565 .ignore_pmdown_time = 1,
1566 .codec_dai_name = "snd-soc-dummy-dai",
1567 .codec_name = "snd-soc-dummy",
1568 .id = MSM_FRONTEND_DAI_VOWLAN,
1569 },
1570 {/* hw:x,17 */
1571 .name = "INT_HFP_BT Hostless",
1572 .stream_name = "INT_HFP_BT Hostless",
1573 .cpu_dai_name = "INT_HFP_BT_HOSTLESS",
1574 .platform_name = "msm-pcm-hostless",
1575 .dynamic = 1,
1576 .dpcm_playback = 1,
1577 .dpcm_capture = 1,
1578 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
1579 SND_SOC_DPCM_TRIGGER_POST},
1580 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
1581 .ignore_suspend = 1,
1582 /* this dai link has playback support */
1583 .ignore_pmdown_time = 1,
1584 .codec_dai_name = "snd-soc-dummy-dai",
1585 .codec_name = "snd-soc-dummy",
1586 },
1587 {/* hw:x,18 */
1588 .name = "MSM8916 HFP",
1589 .stream_name = "MultiMedia6",
1590 .cpu_dai_name = "MultiMedia6",
1591 .platform_name = "msm-pcm-loopback",
1592 .dynamic = 1,
1593 .dpcm_playback = 1,
1594 .dpcm_capture = 1,
1595 .codec_dai_name = "snd-soc-dummy-dai",
1596 .codec_name = "snd-soc-dummy",
1597 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
1598 SND_SOC_DPCM_TRIGGER_POST},
1599 .ignore_suspend = 1,
1600 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
1601 /* this dai link has playback support */
1602 .ignore_pmdown_time = 1,
1603 .id = MSM_FRONTEND_DAI_MULTIMEDIA6,
1604 },
1605 /* LSM FE */
1606 {/* hw:x,19 */
1607 .name = "Listen 1 Audio Service",
1608 .stream_name = "Listen 1 Audio Service",
1609 .cpu_dai_name = "LSM1",
1610 .platform_name = "msm-lsm-client",
1611 .dynamic = 1,
1612 .dpcm_capture = 1,
1613 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
1614 SND_SOC_DPCM_TRIGGER_POST },
1615 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
1616 .ignore_suspend = 1,
1617 .ignore_pmdown_time = 1,
1618 .codec_dai_name = "snd-soc-dummy-dai",
1619 .codec_name = "snd-soc-dummy",
1620 .id = MSM_FRONTEND_DAI_LSM1,
1621 },
1622 {/* hw:x,20 */
1623 .name = "Listen 2 Audio Service",
1624 .stream_name = "Listen 2 Audio Service",
1625 .cpu_dai_name = "LSM2",
1626 .platform_name = "msm-lsm-client",
1627 .dynamic = 1,
1628 .dpcm_capture = 1,
1629 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
1630 SND_SOC_DPCM_TRIGGER_POST },
1631 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
1632 .ignore_suspend = 1,
1633 .ignore_pmdown_time = 1,
1634 .codec_dai_name = "snd-soc-dummy-dai",
1635 .codec_name = "snd-soc-dummy",
1636 .id = MSM_FRONTEND_DAI_LSM2,
1637 },
1638 {/* hw:x,21 */
1639 .name = "Listen 3 Audio Service",
1640 .stream_name = "Listen 3 Audio Service",
1641 .cpu_dai_name = "LSM3",
1642 .platform_name = "msm-lsm-client",
1643 .dynamic = 1,
1644 .dpcm_capture = 1,
1645 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
1646 SND_SOC_DPCM_TRIGGER_POST },
1647 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
1648 .ignore_suspend = 1,
1649 .ignore_pmdown_time = 1,
1650 .codec_dai_name = "snd-soc-dummy-dai",
1651 .codec_name = "snd-soc-dummy",
1652 .id = MSM_FRONTEND_DAI_LSM3,
1653 },
1654 {/* hw:x,22 */
1655 .name = "Listen 4 Audio Service",
1656 .stream_name = "Listen 4 Audio Service",
1657 .cpu_dai_name = "LSM4",
1658 .platform_name = "msm-lsm-client",
1659 .dynamic = 1,
1660 .dpcm_capture = 1,
1661 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
1662 SND_SOC_DPCM_TRIGGER_POST },
1663 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
1664 .ignore_suspend = 1,
1665 .ignore_pmdown_time = 1,
1666 .codec_dai_name = "snd-soc-dummy-dai",
1667 .codec_name = "snd-soc-dummy",
1668 .id = MSM_FRONTEND_DAI_LSM4,
1669 },
1670 {/* hw:x,23 */
1671 .name = "Listen 5 Audio Service",
1672 .stream_name = "Listen 5 Audio Service",
1673 .cpu_dai_name = "LSM5",
1674 .platform_name = "msm-lsm-client",
1675 .dynamic = 1,
1676 .dpcm_capture = 1,
1677 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
1678 SND_SOC_DPCM_TRIGGER_POST },
1679 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
1680 .ignore_suspend = 1,
1681 .ignore_pmdown_time = 1,
1682 .codec_dai_name = "snd-soc-dummy-dai",
1683 .codec_name = "snd-soc-dummy",
1684 .id = MSM_FRONTEND_DAI_LSM5,
1685 },
1686 { /* hw:x,24 */
1687 .name = "MSM8X16 Compress2",
1688 .stream_name = "Compress2",
1689 .cpu_dai_name = "MultiMedia7",
1690 .platform_name = "msm-compress-dsp",
1691 .dynamic = 1,
1692 .dpcm_playback = 1,
1693 .codec_dai_name = "snd-soc-dummy-dai",
1694 .codec_name = "snd-soc-dummy",
1695 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
1696 SND_SOC_DPCM_TRIGGER_POST},
1697 .ignore_suspend = 1,
1698 /* this dainlink has playback support */
1699 .ignore_pmdown_time = 1,
1700 .id = MSM_FRONTEND_DAI_MULTIMEDIA7,
1701 },
1702 { /* hw:x,25 */
1703 .name = "QUAT_MI2S Hostless",
1704 .stream_name = "QUAT_MI2S Hostless",
1705 .cpu_dai_name = "QUAT_MI2S_RX_HOSTLESS",
1706 .platform_name = "msm-pcm-hostless",
1707 .dynamic = 1,
1708 .dpcm_playback = 1,
1709 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
1710 SND_SOC_DPCM_TRIGGER_POST},
1711 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
1712 .ignore_suspend = 1,
1713 /* this dainlink has playback support */
1714 .ignore_pmdown_time = 1,
1715 .codec_dai_name = "snd-soc-dummy-dai",
1716 .codec_name = "snd-soc-dummy",
1717 },
1718 {/* hw:x,26 */
1719 .name = LPASS_BE_SENARY_MI2S_TX,
1720 .stream_name = "Senary_mi2s Capture",
1721 .cpu_dai_name = "msm-dai-q6-mi2s.6",
1722 .platform_name = "msm-pcm-hostless",
1723 .codec_name = "snd-soc-dummy",
1724 .codec_dai_name = "snd-soc-dummy-dai",
1725 .id = MSM_BACKEND_DAI_SENARY_MI2S_TX,
1726 .be_hw_params_fixup = msm_senary_tx_be_hw_params_fixup,
1727 .ops = &msm8909_mi2s_be_ops,
1728 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
1729 .ignore_suspend = 1,
1730 .dpcm_capture = 1,
1731 .ignore_pmdown_time = 1,
1732 },
1733 {/* hw:x,27 */
1734 .name = "MSM8X16 Compress3",
1735 .stream_name = "Compress3",
1736 .cpu_dai_name = "MultiMedia10",
1737 .platform_name = "msm-pcm-dsp.1",
1738 .dynamic = 1,
1739 .dpcm_playback = 1,
1740 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
1741 SND_SOC_DPCM_TRIGGER_POST},
1742 .codec_dai_name = "snd-soc-dummy-dai",
1743 .codec_name = "snd-soc-dummy",
1744 .ignore_suspend = 1,
1745 .ignore_pmdown_time = 1,
1746 /* this dai link has playback support */
1747 .id = MSM_FRONTEND_DAI_MULTIMEDIA10,
1748 },
1749 {/* hw:x,28 */
1750 .name = "MSM8X16 Compress4",
1751 .stream_name = "Compress4",
1752 .cpu_dai_name = "MultiMedia11",
1753 .platform_name = "msm-compress-dsp",
1754 .dynamic = 1,
1755 .dpcm_playback = 1,
1756 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
1757 SND_SOC_DPCM_TRIGGER_POST},
1758 .codec_dai_name = "snd-soc-dummy-dai",
1759 .codec_name = "snd-soc-dummy",
1760 .ignore_suspend = 1,
1761 .ignore_pmdown_time = 1,
1762 /* this dai link has playback support */
1763 .id = MSM_FRONTEND_DAI_MULTIMEDIA11,
1764 },
1765 {/* hw:x,29 */
1766 .name = "MSM8X16 Compress5",
1767 .stream_name = "Compress5",
1768 .cpu_dai_name = "MultiMedia12",
1769 .platform_name = "msm-compress-dsp",
1770 .dynamic = 1,
1771 .dpcm_playback = 1,
1772 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
1773 SND_SOC_DPCM_TRIGGER_POST},
1774 .codec_dai_name = "snd-soc-dummy-dai",
1775 .codec_name = "snd-soc-dummy",
1776 .ignore_suspend = 1,
1777 .ignore_pmdown_time = 1,
1778 /* this dai link has playback support */
1779 .id = MSM_FRONTEND_DAI_MULTIMEDIA12,
1780 },
1781 {/* hw:x,30 */
1782 .name = "MSM8X16 Compress6",
1783 .stream_name = "Compress6",
1784 .cpu_dai_name = "MultiMedia13",
1785 .platform_name = "msm-compress-dsp",
1786 .dynamic = 1,
1787 .dpcm_playback = 1,
1788 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
1789 SND_SOC_DPCM_TRIGGER_POST},
1790 .codec_dai_name = "snd-soc-dummy-dai",
1791 .codec_name = "snd-soc-dummy",
1792 .ignore_suspend = 1,
1793 .ignore_pmdown_time = 1,
1794 /* this dai link has playback support */
1795 .id = MSM_FRONTEND_DAI_MULTIMEDIA13,
1796 },
1797 {/* hw:x,31 */
1798 .name = "MSM8X16 Compress7",
1799 .stream_name = "Compress7",
1800 .cpu_dai_name = "MultiMedia14",
1801 .platform_name = "msm-compress-dsp",
1802 .dynamic = 1,
1803 .dpcm_playback = 1,
1804 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
1805 SND_SOC_DPCM_TRIGGER_POST},
1806 .codec_dai_name = "snd-soc-dummy-dai",
1807 .codec_name = "snd-soc-dummy",
1808 .ignore_suspend = 1,
1809 .ignore_pmdown_time = 1,
1810 /* this dai link has playback support */
1811 .id = MSM_FRONTEND_DAI_MULTIMEDIA14,
1812 },
1813 {/* hw:x,32 */
1814 .name = "MSM8X16 Compress8",
1815 .stream_name = "Compress8",
1816 .cpu_dai_name = "MultiMedia15",
1817 .platform_name = "msm-compress-dsp",
1818 .dynamic = 1,
1819 .dpcm_playback = 1,
1820 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
1821 SND_SOC_DPCM_TRIGGER_POST},
1822 .codec_dai_name = "snd-soc-dummy-dai",
1823 .codec_name = "snd-soc-dummy",
1824 .ignore_suspend = 1,
1825 .ignore_pmdown_time = 1,
1826 /* this dai link has playback support */
1827 .id = MSM_FRONTEND_DAI_MULTIMEDIA15,
1828 },
1829 {/* hw:x,34 */
1830 .name = "VoiceMMode1",
1831 .stream_name = "VoiceMMode1",
1832 .cpu_dai_name = "VoiceMMode1",
1833 .platform_name = "msm-pcm-voice",
1834 .dynamic = 1,
1835 .dpcm_playback = 1,
1836 .dpcm_capture = 1,
1837 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
1838 SND_SOC_DPCM_TRIGGER_POST},
1839 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
1840 .ignore_suspend = 1,
1841 .ignore_pmdown_time = 1,
1842 .codec_dai_name = "snd-soc-dummy-dai",
1843 .codec_name = "snd-soc-dummy",
1844 .id = MSM_FRONTEND_DAI_VOICEMMODE1,
1845 },
1846 {/* hw:x,35 */
1847 .name = "VoiceMMode2",
1848 .stream_name = "VoiceMMode2",
1849 .cpu_dai_name = "VoiceMMode2",
1850 .platform_name = "msm-pcm-voice",
1851 .dynamic = 1,
1852 .dpcm_playback = 1,
1853 .dpcm_capture = 1,
1854 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
1855 SND_SOC_DPCM_TRIGGER_POST},
1856 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
1857 .ignore_suspend = 1,
1858 .ignore_pmdown_time = 1,
1859 .codec_dai_name = "snd-soc-dummy-dai",
1860 .codec_name = "snd-soc-dummy",
1861 .id = MSM_FRONTEND_DAI_VOICEMMODE2,
1862 },
1863 {/* hw:x,36 */
1864 .name = "MSM8916 HFP Loopback2",
1865 .stream_name = "MultiMedia8",
1866 .cpu_dai_name = "MultiMedia8",
1867 .platform_name = "msm-pcm-loopback",
1868 .dynamic = 1,
1869 .dpcm_playback = 1,
1870 .dpcm_capture = 1,
1871 .codec_dai_name = "snd-soc-dummy-dai",
1872 .codec_name = "snd-soc-dummy",
1873 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
1874 SND_SOC_DPCM_TRIGGER_POST},
1875 .ignore_suspend = 1,
1876 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
1877 /* this dai link has playback support */
1878 .ignore_pmdown_time = 1,
1879 .id = MSM_FRONTEND_DAI_MULTIMEDIA8,
1880 },
1881 {/* hw:x,37 */
1882 .name = "QCHAT",
1883 .stream_name = "QCHAT",
1884 .cpu_dai_name = "QCHAT",
1885 .platform_name = "msm-pcm-voice",
1886 .dynamic = 1,
1887 .dpcm_playback = 1,
1888 .dpcm_capture = 1,
1889 .codec_dai_name = "snd-soc-dummy-dai",
1890 .codec_name = "snd-soc-dummy",
1891 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
1892 SND_SOC_DPCM_TRIGGER_POST},
1893 .ignore_suspend = 1,
1894 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
1895 /* this dai link has playback support */
1896 .ignore_pmdown_time = 1,
1897 .id = MSM_FRONTEND_DAI_QCHAT,
1898 },
1899 {/* hw:x,38 */
1900 .name = "MSM8X16 Compress10",
1901 .stream_name = "Compress10",
1902 .cpu_dai_name = "MultiMedia17",
1903 .platform_name = "msm-compress-dsp",
1904 .dynamic = 1,
1905 .dpcm_capture = 1,
1906 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
1907 SND_SOC_DPCM_TRIGGER_POST},
1908 .codec_dai_name = "snd-soc-dummy-dai",
1909 .codec_name = "snd-soc-dummy",
1910 .ignore_suspend = 1,
1911 .ignore_pmdown_time = 1,
1912 .id = MSM_FRONTEND_DAI_MULTIMEDIA17,
1913 },
1914 {/* hw:x,39 */
1915 .name = "MSM8X16 Compress11",
1916 .stream_name = "Compress11",
1917 .cpu_dai_name = "MultiMedia18",
1918 .platform_name = "msm-compress-dsp",
1919 .dynamic = 1,
1920 .dpcm_capture = 1,
1921 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
1922 SND_SOC_DPCM_TRIGGER_POST},
1923 .codec_dai_name = "snd-soc-dummy-dai",
1924 .codec_name = "snd-soc-dummy",
1925 .ignore_suspend = 1,
1926 .ignore_pmdown_time = 1,
1927 .id = MSM_FRONTEND_DAI_MULTIMEDIA18,
1928 },
1929 {/* hw:x,40 */
1930 .name = "MSM8X16 Compress12",
1931 .stream_name = "Compress12",
1932 .cpu_dai_name = "MultiMedia19",
1933 .platform_name = "msm-compress-dsp",
1934 .dynamic = 1,
1935 .dpcm_capture = 1,
1936 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
1937 SND_SOC_DPCM_TRIGGER_POST},
1938 .codec_dai_name = "snd-soc-dummy-dai",
1939 .codec_name = "snd-soc-dummy",
1940 .ignore_suspend = 1,
1941 .ignore_pmdown_time = 1,
1942 .id = MSM_FRONTEND_DAI_MULTIMEDIA19,
1943 },
1944 {/* hw:x,41 */
1945 .name = "MSM8X16 Compress13",
1946 .stream_name = "Compress13",
1947 .cpu_dai_name = "MultiMedia28",
1948 .platform_name = "msm-compress-dsp",
1949 .dynamic = 1,
1950 .dpcm_capture = 1,
1951 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
1952 SND_SOC_DPCM_TRIGGER_POST},
1953 .codec_dai_name = "snd-soc-dummy-dai",
1954 .codec_name = "snd-soc-dummy",
1955 .ignore_suspend = 1,
1956 .ignore_pmdown_time = 1,
1957 .id = MSM_FRONTEND_DAI_MULTIMEDIA28,
1958 },
1959 {/* hw:x,42 */
1960 .name = "MSM8X16 Compress14",
1961 .stream_name = "Compress14",
1962 .cpu_dai_name = "MultiMedia29",
1963 .platform_name = "msm-compress-dsp",
1964 .dynamic = 1,
1965 .dpcm_capture = 1,
1966 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
1967 SND_SOC_DPCM_TRIGGER_POST},
1968 .codec_dai_name = "snd-soc-dummy-dai",
1969 .codec_name = "snd-soc-dummy",
1970 .ignore_suspend = 1,
1971 .ignore_pmdown_time = 1,
1972 .id = MSM_FRONTEND_DAI_MULTIMEDIA29,
1973 },
1974 /* Backend I2S DAI Links */
1975 {
1976 .name = LPASS_BE_PRI_MI2S_RX,
1977 .stream_name = "Primary MI2S Playback",
1978 .cpu_dai_name = "msm-dai-q6-mi2s.0",
1979 .platform_name = "msm-pcm-routing",
1980 .codec_name = "snd-soc-dummy",
1981 .codec_dai_name = "snd-soc-dummy-dai",
1982 .no_pcm = 1,
1983 .dpcm_playback = 1,
1984 .async_ops = ASYNC_DPCM_SND_SOC_PREPARE |
1985 ASYNC_DPCM_SND_SOC_HW_PARAMS,
1986 .id = MSM_BACKEND_DAI_PRI_MI2S_RX,
1987 .be_hw_params_fixup = msm_mi2s_rx_be_hw_params_fixup,
1988 .ops = &msm8909_mi2s_be_ops,
1989 .ignore_suspend = 1,
1990 },
1991 {
1992 .name = LPASS_BE_SEC_MI2S_RX,
1993 .stream_name = "Secondary MI2S Playback",
1994 .cpu_dai_name = "msm-dai-q6-mi2s.1",
1995 .platform_name = "msm-pcm-routing",
1996 .codec_name = "msm-stub-codec.1",
1997 .codec_dai_name = "msm-stub-rx",
1998 .no_pcm = 1,
1999 .dpcm_playback = 1,
2000 .id = MSM_BACKEND_DAI_SECONDARY_MI2S_RX,
2001 .be_hw_params_fixup = msm_mi2s_rx_be_hw_params_fixup,
2002 .ops = &msm8909_sec_mi2s_be_ops,
2003 .ignore_suspend = 1,
2004 },
2005 {
2006 .name = LPASS_BE_TERT_MI2S_TX,
2007 .stream_name = "Tertiary MI2S Capture",
2008 .cpu_dai_name = "msm-dai-q6-mi2s.2",
2009 .platform_name = "msm-pcm-routing",
2010 .codec_name = "msm-dig-codec",
2011 .codec_dai_name = "msm_dig_cdc_dai_tx1",
2012 .no_pcm = 1,
2013 .dpcm_capture = 1,
2014 .async_ops = ASYNC_DPCM_SND_SOC_PREPARE |
2015 ASYNC_DPCM_SND_SOC_HW_PARAMS,
2016 .id = MSM_BACKEND_DAI_TERTIARY_MI2S_TX,
2017 .init = &msm_audrx_init,
2018 .be_hw_params_fixup = msm_tx_be_hw_params_fixup,
2019 .ops = &msm8909_mi2s_be_ops,
2020 .ignore_suspend = 1,
2021 },
2022 {
2023 .name = LPASS_BE_QUAT_MI2S_RX,
2024 .stream_name = "Quaternary MI2S Playback",
2025 .cpu_dai_name = "msm-dai-q6-mi2s.3",
2026 .platform_name = "msm-pcm-routing",
2027 .codec_dai_name = "snd-soc-dummy-dai",
2028 .codec_name = "snd-soc-dummy",
2029 .no_pcm = 1,
2030 .dpcm_playback = 1,
2031 .id = MSM_BACKEND_DAI_QUATERNARY_MI2S_RX,
2032 .be_hw_params_fixup = msm_mi2s_rx_be_hw_params_fixup,
2033 .ops = &msm8909_quat_mi2s_be_ops,
2034 .ignore_pmdown_time = 1, /* dai link has playback support */
2035 .ignore_suspend = 1,
2036 },
2037 {
2038 .name = LPASS_BE_QUAT_MI2S_TX,
2039 .stream_name = "Quaternary MI2S Capture",
2040 .cpu_dai_name = "msm-dai-q6-mi2s.3",
2041 .platform_name = "msm-pcm-routing",
2042 .codec_dai_name = "snd-soc-dummy-dai",
2043 .codec_name = "snd-soc-dummy",
2044 .no_pcm = 1,
2045 .dpcm_capture = 1,
2046 .id = MSM_BACKEND_DAI_QUATERNARY_MI2S_TX,
2047 .be_hw_params_fixup = msm_be_hw_params_fixup,
2048 .ops = &msm8909_quat_mi2s_be_ops,
2049 .ignore_suspend = 1,
2050 },
2051 /* Primary AUX PCM Backend DAI Links */
2052 {
2053 .name = LPASS_BE_AUXPCM_RX,
2054 .stream_name = "AUX PCM Playback",
2055 .cpu_dai_name = "msm-dai-q6-auxpcm.1",
2056 .platform_name = "msm-pcm-routing",
2057 .codec_name = "msm-stub-codec.1",
2058 .codec_dai_name = "msm-stub-rx",
2059 .no_pcm = 1,
2060 .dpcm_playback = 1,
2061 .id = MSM_BACKEND_DAI_AUXPCM_RX,
2062 .be_hw_params_fixup = msm_auxpcm_be_params_fixup,
2063 .ops = &msm_pri_auxpcm_be_ops,
2064 .ignore_pmdown_time = 1,
2065 .ignore_suspend = 1,
2066 },
2067 {
2068 .name = LPASS_BE_AUXPCM_TX,
2069 .stream_name = "AUX PCM Capture",
2070 .cpu_dai_name = "msm-dai-q6-auxpcm.1",
2071 .platform_name = "msm-pcm-routing",
2072 .codec_name = "msm-stub-codec.1",
2073 .codec_dai_name = "msm-stub-tx",
2074 .no_pcm = 1,
2075 .dpcm_capture = 1,
2076 .id = MSM_BACKEND_DAI_AUXPCM_TX,
2077 .be_hw_params_fixup = msm_auxpcm_be_params_fixup,
2078 .ops = &msm_pri_auxpcm_be_ops,
2079 .ignore_suspend = 1,
2080 },
2081 {
2082 .name = LPASS_BE_INT_BT_SCO_RX,
2083 .stream_name = "Internal BT-SCO Playback",
2084 .cpu_dai_name = "msm-dai-q6-dev.12288",
2085 .platform_name = "msm-pcm-routing",
2086 .codec_name = "msm-stub-codec.1",
2087 .codec_dai_name = "msm-stub-rx",
2088 .no_pcm = 1,
2089 .dpcm_playback = 1,
2090 .id = MSM_BACKEND_DAI_INT_BT_SCO_RX,
2091 .be_hw_params_fixup = msm_btsco_be_hw_params_fixup,
2092 /* this dainlink has playback support */
2093 .ignore_pmdown_time = 1,
2094 .ignore_suspend = 1,
2095 },
2096 {
2097 .name = LPASS_BE_INT_BT_SCO_TX,
2098 .stream_name = "Internal BT-SCO Capture",
2099 .cpu_dai_name = "msm-dai-q6-dev.12289",
2100 .platform_name = "msm-pcm-routing",
2101 .codec_name = "msm-stub-codec.1",
2102 .codec_dai_name = "msm-stub-tx",
2103 .no_pcm = 1,
2104 .dpcm_capture = 1,
2105 .id = MSM_BACKEND_DAI_INT_BT_SCO_TX,
2106 .be_hw_params_fixup = msm_btsco_be_hw_params_fixup,
2107 .ignore_suspend = 1,
2108 },
2109 {
2110 .name = LPASS_BE_INT_FM_RX,
2111 .stream_name = "Internal FM Playback",
2112 .cpu_dai_name = "msm-dai-q6-dev.12292",
2113 .platform_name = "msm-pcm-routing",
2114 .codec_name = "msm-stub-codec.1",
2115 .codec_dai_name = "msm-stub-rx",
2116 .no_pcm = 1,
2117 .dpcm_playback = 1,
2118 .id = MSM_BACKEND_DAI_INT_FM_RX,
2119 .be_hw_params_fixup = msm_be_hw_params_fixup,
2120 /* this dainlink has playback support */
2121 .ignore_pmdown_time = 1,
2122 .ignore_suspend = 1,
2123 },
2124 {
2125 .name = LPASS_BE_INT_FM_TX,
2126 .stream_name = "Internal FM Capture",
2127 .cpu_dai_name = "msm-dai-q6-dev.12293",
2128 .platform_name = "msm-pcm-routing",
2129 .codec_name = "msm-stub-codec.1",
2130 .codec_dai_name = "msm-stub-tx",
2131 .no_pcm = 1,
2132 .dpcm_capture = 1,
2133 .id = MSM_BACKEND_DAI_INT_FM_TX,
2134 .be_hw_params_fixup = msm_be_hw_params_fixup,
2135 .ignore_suspend = 1,
2136 },
2137 {
2138 .name = LPASS_BE_AFE_PCM_RX,
2139 .stream_name = "AFE Playback",
2140 .cpu_dai_name = "msm-dai-q6-dev.224",
2141 .platform_name = "msm-pcm-routing",
2142 .codec_name = "msm-stub-codec.1",
2143 .codec_dai_name = "msm-stub-rx",
2144 .no_pcm = 1,
2145 .dpcm_playback = 1,
2146 .id = MSM_BACKEND_DAI_AFE_PCM_RX,
2147 .be_hw_params_fixup = msm_proxy_rx_be_hw_params_fixup,
2148 /* this dainlink has playback support */
2149 .ignore_pmdown_time = 1,
2150 .ignore_suspend = 1,
2151 },
2152 {
2153 .name = LPASS_BE_AFE_PCM_TX,
2154 .stream_name = "AFE Capture",
2155 .cpu_dai_name = "msm-dai-q6-dev.225",
2156 .platform_name = "msm-pcm-routing",
2157 .codec_name = "msm-stub-codec.1",
2158 .codec_dai_name = "msm-stub-tx",
2159 .no_pcm = 1,
2160 .dpcm_capture = 1,
2161 .id = MSM_BACKEND_DAI_AFE_PCM_TX,
2162 .be_hw_params_fixup = msm_proxy_tx_be_hw_params_fixup,
2163 .ignore_suspend = 1,
2164 },
2165 /* Incall Record Uplink BACK END DAI Link */
2166 {
2167 .name = LPASS_BE_INCALL_RECORD_TX,
2168 .stream_name = "Voice Uplink Capture",
2169 .cpu_dai_name = "msm-dai-q6-dev.32772",
2170 .platform_name = "msm-pcm-routing",
2171 .codec_name = "msm-stub-codec.1",
2172 .codec_dai_name = "msm-stub-tx",
2173 .no_pcm = 1,
2174 .dpcm_capture = 1,
2175 .id = MSM_BACKEND_DAI_INCALL_RECORD_TX,
2176 .be_hw_params_fixup = msm_be_hw_params_fixup,
2177 .ignore_suspend = 1,
2178 },
2179 /* Incall Record Downlink BACK END DAI Link */
2180 {
2181 .name = LPASS_BE_INCALL_RECORD_RX,
2182 .stream_name = "Voice Downlink Capture",
2183 .cpu_dai_name = "msm-dai-q6-dev.32771",
2184 .platform_name = "msm-pcm-routing",
2185 .codec_name = "msm-stub-codec.1",
2186 .codec_dai_name = "msm-stub-tx",
2187 .no_pcm = 1,
2188 .dpcm_capture = 1,
2189 .id = MSM_BACKEND_DAI_INCALL_RECORD_RX,
2190 .be_hw_params_fixup = msm_be_hw_params_fixup,
2191 .ignore_suspend = 1,
2192 },
2193 /* Incall Music BACK END DAI Link */
2194 {
2195 .name = LPASS_BE_VOICE_PLAYBACK_TX,
2196 .stream_name = "Voice Farend Playback",
2197 .cpu_dai_name = "msm-dai-q6-dev.32773",
2198 .platform_name = "msm-pcm-routing",
2199 .codec_name = "msm-stub-codec.1",
2200 .codec_dai_name = "msm-stub-rx",
2201 .no_pcm = 1,
2202 .dpcm_playback = 1,
2203 .id = MSM_BACKEND_DAI_VOICE_PLAYBACK_TX,
2204 .be_hw_params_fixup = msm_be_hw_params_fixup,
2205 .ignore_suspend = 1,
2206 },
2207 /* Incall Music 2 BACK END DAI Link */
2208 {
2209 .name = LPASS_BE_VOICE2_PLAYBACK_TX,
2210 .stream_name = "Voice2 Farend Playback",
2211 .cpu_dai_name = "msm-dai-q6-dev.32770",
2212 .platform_name = "msm-pcm-routing",
2213 .codec_name = "msm-stub-codec.1",
2214 .codec_dai_name = "msm-stub-rx",
2215 .no_pcm = 1,
2216 .dpcm_playback = 1,
2217 .id = MSM_BACKEND_DAI_VOICE2_PLAYBACK_TX,
2218 .be_hw_params_fixup = msm_be_hw_params_fixup,
2219 .ignore_suspend = 1,
2220 },
2221 {
2222 .name = LPASS_BE_QUIN_MI2S_TX,
2223 .stream_name = "Quinary MI2S Capture",
2224 .cpu_dai_name = "msm-dai-q6-mi2s.4",
2225 .platform_name = "msm-pcm-routing",
2226 .codec_dai_name = "snd-soc-dummy-dai",
2227 .codec_name = "snd-soc-dummy",
2228 .no_pcm = 1,
2229 .dpcm_capture = 1,
2230 .id = MSM_BACKEND_DAI_QUINARY_MI2S_TX,
2231 .be_hw_params_fixup = msm_be_hw_params_fixup,
2232 .ops = &msm8909_quin_mi2s_be_ops,
2233 .ignore_suspend = 1,
2234 },
2235};
2236static struct snd_soc_dai_link msm8909_hdmi_dba_dai_link[] = {
2237 {
2238 .name = LPASS_BE_QUIN_MI2S_RX,
2239 .stream_name = "Quinary MI2S Playback",
2240 .cpu_dai_name = "msm-dai-q6-mi2s.4",
2241 .platform_name = "msm-pcm-routing",
2242 .codec_dai_name = "msm_hdmi_dba_codec_rx_dai",
2243 .codec_name = "msm-hdmi-dba-codec-rx",
2244 .no_pcm = 1,
2245 .dpcm_playback = 1,
2246 .id = MSM_BACKEND_DAI_QUINARY_MI2S_RX,
2247 .be_hw_params_fixup = msm_mi2s_rx_be_hw_params_fixup,
2248 .ops = &msm8909_quin_mi2s_be_ops,
2249 .ignore_pmdown_time = 1, /* dai link has playback support */
2250 .ignore_suspend = 1,
2251 },
2252};
2253
2254static struct snd_soc_dai_link msm8909_quin_dai_link[] = {
2255 {
2256 .name = LPASS_BE_QUIN_MI2S_RX,
2257 .stream_name = "Quinary MI2S Playback",
2258 .cpu_dai_name = "msm-dai-q6-mi2s.4",
2259 .platform_name = "msm-pcm-routing",
2260 .codec_dai_name = "snd-soc-dummy-dai",
2261 .codec_name = "snd-soc-dummy",
2262 .no_pcm = 1,
2263 .dpcm_playback = 1,
2264 .id = MSM_BACKEND_DAI_QUINARY_MI2S_RX,
2265 .be_hw_params_fixup = msm_mi2s_rx_be_hw_params_fixup,
2266 .ops = &msm8909_quin_mi2s_be_ops,
2267 .ignore_pmdown_time = 1, /* dai link has playback support */
2268 .ignore_suspend = 1,
2269 },
2270};
2271
2272static struct snd_soc_dai_link msm8909_split_a2dp_dai_link[] = {
2273 {
2274 .name = LPASS_BE_INT_BT_A2DP_RX,
2275 .stream_name = "Internal BT-A2DP Playback",
2276 .cpu_dai_name = "msm-dai-q6-dev.12290",
2277 .platform_name = "msm-pcm-routing",
2278 .codec_dai_name = "msm-stub-rx",
2279 .codec_name = "msm-stub-codec.1",
2280 .no_pcm = 1,
2281 .dpcm_playback = 1,
2282 .id = MSM_BACKEND_DAI_INT_BT_A2DP_RX,
2283 .be_hw_params_fixup = msm_be_hw_params_fixup,
2284 .ignore_pmdown_time = 1, /* dai link has playback support */
2285 .ignore_suspend = 1,
2286 },
2287};
2288
2289static struct snd_soc_dai_link msm8909_dai_links[
2290 ARRAY_SIZE(msm8909_dai) +
2291 ARRAY_SIZE(msm8909_hdmi_dba_dai_link) +
2292 ARRAY_SIZE(msm8909_split_a2dp_dai_link)];
2293
2294static struct snd_soc_card bear_card = {
2295 /* snd_soc_card_msm8909 */
2296 .name = "msm8909-snd-card",
2297 .dai_link = msm8909_dai,
2298 .num_links = ARRAY_SIZE(msm8909_dai),
2299};
2300
2301static void msm_disable_mclk(struct work_struct *work)
2302{
2303 struct msm_asoc_mach_data *pdata = NULL;
2304 struct delayed_work *dwork;
2305 int ret = 0;
2306
2307 dwork = to_delayed_work(work);
2308 pdata = container_of(dwork, struct msm_asoc_mach_data,
2309 disable_int_mclk0_work);
2310 mutex_lock(&pdata->cdc_int_mclk0_mutex);
2311 pr_debug("%s: int_mclk0_enabled %d int_mclk0_rsc_ref %d\n", __func__,
2312 atomic_read(&pdata->int_mclk0_enabled),
2313 atomic_read(&pdata->int_mclk0_rsc_ref));
2314
2315 if (atomic_read(&pdata->int_mclk0_enabled) == true
2316 && atomic_read(&pdata->int_mclk0_rsc_ref) == 0) {
2317 pr_debug("Disable the mclk\n");
2318 pdata->digital_cdc_core_clk.enable = 0;
2319 pdata->digital_cdc_core_clk.clk_freq_in_hz =
2320 DEFAULT_MCLK_RATE;
2321 ret = afe_set_lpass_clock_v2(
2322 AFE_PORT_ID_PRIMARY_MI2S_RX,
2323 &pdata->digital_cdc_core_clk);
2324 if (ret < 0)
2325 pr_err("%s failed to disable the CCLK\n", __func__);
2326 atomic_set(&pdata->int_mclk0_enabled, false);
2327 }
2328 mutex_unlock(&pdata->cdc_int_mclk0_mutex);
2329}
2330
2331static int msm8909_populate_dai_link_component_of_node(
2332 struct snd_soc_card *card)
2333{
2334 int i, index, ret = 0;
2335 struct device *cdev = card->dev;
2336 struct snd_soc_dai_link *dai_link = card->dai_link;
2337 struct device_node *phandle;
2338
2339 if (!cdev) {
2340 pr_err("%s: Sound card device memory NULL\n", __func__);
2341 return -ENODEV;
2342 }
2343
2344 for (i = 0; i < card->num_links; i++) {
2345 if (dai_link[i].platform_of_node && dai_link[i].cpu_of_node)
2346 continue;
2347
2348 /* populate platform_of_node for snd card dai links */
2349 if (dai_link[i].platform_name &&
2350 !dai_link[i].platform_of_node) {
2351 index = of_property_match_string(cdev->of_node,
2352 "asoc-platform-names",
2353 dai_link[i].platform_name);
2354 if (index < 0) {
2355 pr_err("%s: No match found for platform name: %s\n",
2356 __func__, dai_link[i].platform_name);
2357 ret = index;
2358 goto cpu_dai;
2359 }
2360 pr_debug("%s: match found for platform name: %s\n",
2361 __func__, dai_link[i].platform_name);
2362 phandle = of_parse_phandle(cdev->of_node,
2363 "asoc-platform",
2364 index);
2365 if (!phandle) {
2366 pr_err("%s: retrieving phandle for platform %s, index %d failed\n",
2367 __func__, dai_link[i].platform_name,
2368 index);
2369 ret = -ENODEV;
2370 goto err;
2371 }
2372 dai_link[i].platform_of_node = phandle;
2373 dai_link[i].platform_name = NULL;
2374 }
2375cpu_dai:
2376 /* populate cpu_of_node for snd card dai links */
2377 if (dai_link[i].cpu_dai_name && !dai_link[i].cpu_of_node) {
2378 index = of_property_match_string(cdev->of_node,
2379 "asoc-cpu-names",
2380 dai_link[i].cpu_dai_name);
2381 if (index < 0)
2382 goto codec_dai;
2383 phandle = of_parse_phandle(cdev->of_node, "asoc-cpu",
2384 index);
2385 if (!phandle) {
2386 pr_err("%s: retrieving phandle for cpu dai %s failed\n",
2387 __func__, dai_link[i].cpu_dai_name);
2388 ret = -ENODEV;
2389 goto err;
2390 }
2391 dai_link[i].cpu_of_node = phandle;
2392 dai_link[i].cpu_dai_name = NULL;
2393 }
2394codec_dai:
2395 /* populate codec_of_node for snd card dai links */
2396 if (dai_link[i].codec_name && !dai_link[i].codec_of_node) {
2397 index = of_property_match_string(cdev->of_node,
2398 "asoc-codec-names",
2399 dai_link[i].codec_name);
2400 if (index < 0)
2401 continue;
2402 phandle = of_parse_phandle(cdev->of_node, "asoc-codec",
2403 index);
2404 if (!phandle) {
2405 pr_err("%s: retrieving phandle for codec dai %s failed\n",
2406 __func__, dai_link[i].codec_name);
2407 ret = -ENODEV;
2408 goto err;
2409 }
2410 dai_link[i].codec_of_node = phandle;
2411 dai_link[i].codec_name = NULL;
2412 }
2413 }
2414err:
2415 return ret;
2416}
2417
2418static struct snd_soc_card *msm8909_populate_sndcard_dailinks(
2419 struct device *dev)
2420{
2421 struct snd_soc_card *card = &bear_card;
2422 struct snd_soc_dai_link *dailink;
2423 int len1;
2424
2425 card->name = dev_name(dev);
2426 len1 = ARRAY_SIZE(msm8909_dai);
2427 memcpy(msm8909_dai_links, msm8909_dai, sizeof(msm8909_dai));
2428 dailink = msm8909_dai_links;
2429 if (of_property_read_bool(dev->of_node,
2430 "qcom,hdmi-dba-codec-rx")) {
2431 dev_dbg(dev, "%s(): hdmi audio support present\n",
2432 __func__);
2433 memcpy(dailink + len1, msm8909_hdmi_dba_dai_link,
2434 sizeof(msm8909_hdmi_dba_dai_link));
2435 len1 += ARRAY_SIZE(msm8909_hdmi_dba_dai_link);
2436 } else {
2437 dev_dbg(dev, "%s(): No hdmi dba present, add quin dai\n",
2438 __func__);
2439 memcpy(dailink + len1, msm8909_quin_dai_link,
2440 sizeof(msm8909_quin_dai_link));
2441 len1 += ARRAY_SIZE(msm8909_quin_dai_link);
2442 }
2443 if (of_property_read_bool(dev->of_node,
2444 "qcom,split-a2dp")) {
2445 dev_dbg(dev, "%s(): split a2dp support present\n",
2446 __func__);
2447 memcpy(dailink + len1, msm8909_split_a2dp_dai_link,
2448 sizeof(msm8909_split_a2dp_dai_link));
2449 len1 += ARRAY_SIZE(msm8909_split_a2dp_dai_link);
2450 }
2451 card->dai_link = dailink;
2452 card->num_links = len1;
2453 return card;
2454}
2455
2456static int msm8909_asoc_machine_probe(struct platform_device *pdev)
2457{
2458 struct snd_soc_card *card;
2459 struct msm_asoc_mach_data *pdata = NULL;
2460 const char *mclk = "qcom,msm-mclk-freq";
2461 const char *ext_pa = "qcom,msm-ext-pa";
2462 const char *ext_pa_str = NULL;
2463 int num_strings;
2464 int ret, id, i, val;
2465 struct resource *muxsel;
2466
2467 pdata = devm_kzalloc(&pdev->dev,
2468 sizeof(struct msm_asoc_mach_data), GFP_KERNEL);
2469 if (!pdata)
2470 return -ENOMEM;
2471
2472 muxsel = platform_get_resource_byname(pdev, IORESOURCE_MEM,
2473 "csr_gp_io_mux_mic_ctl");
2474 if (!muxsel) {
2475 dev_err(&pdev->dev, "MUX addr invalid for MI2S\n");
2476 ret = -ENODEV;
2477 goto err1;
2478 }
2479 pdata->vaddr_gpio_mux_mic_ctl =
2480 ioremap(muxsel->start, resource_size(muxsel));
2481 if (pdata->vaddr_gpio_mux_mic_ctl == NULL) {
2482 pr_err("%s ioremap failure for muxsel virt addr\n",
2483 __func__);
2484 ret = -ENOMEM;
2485 goto err1;
2486 }
2487
2488 muxsel = platform_get_resource_byname(pdev, IORESOURCE_MEM,
2489 "csr_gp_io_mux_spkr_ctl");
2490 if (!muxsel) {
2491 dev_err(&pdev->dev, "MUX addr invalid for MI2S\n");
2492 ret = -ENODEV;
2493 goto err;
2494 }
2495 pdata->vaddr_gpio_mux_spkr_ctl =
2496 ioremap(muxsel->start, resource_size(muxsel));
2497 if (pdata->vaddr_gpio_mux_spkr_ctl == NULL) {
2498 pr_err("%s ioremap failure for muxsel virt addr\n",
2499 __func__);
2500 ret = -ENOMEM;
2501 goto err;
2502 }
2503
2504 muxsel = platform_get_resource_byname(pdev, IORESOURCE_MEM,
2505 "csr_gp_io_lpaif_pri_pcm_pri_mode_muxsel");
2506 if (!muxsel) {
2507 dev_err(&pdev->dev, "MUX addr invalid for MI2S\n");
2508 ret = -ENODEV;
2509 goto err;
2510 }
2511 pdata->vaddr_gpio_mux_pcm_ctl =
2512 ioremap(muxsel->start, resource_size(muxsel));
2513 if (pdata->vaddr_gpio_mux_pcm_ctl == NULL) {
2514 pr_err("%s ioremap failure for muxsel virt addr\n",
2515 __func__);
2516 ret = -ENOMEM;
2517 goto err;
2518 }
2519
2520 muxsel = platform_get_resource_byname(pdev, IORESOURCE_MEM,
2521 "csr_gp_io_mux_quin_ctl");
2522 if (!muxsel) {
2523 dev_dbg(&pdev->dev, "MUX addr invalid for MI2S\n");
2524 goto parse_mclk_freq;
2525 }
2526 pdata->vaddr_gpio_mux_quin_ctl =
2527 ioremap(muxsel->start, resource_size(muxsel));
2528 if (pdata->vaddr_gpio_mux_quin_ctl == NULL) {
2529 pr_err("%s ioremap failure for muxsel virt addr\n",
2530 __func__);
2531 ret = -ENOMEM;
2532 goto err;
2533 }
2534parse_mclk_freq:
2535 ret = of_property_read_u32(pdev->dev.of_node, mclk, &id);
2536 if (ret) {
2537 dev_err(&pdev->dev,
2538 "%s: missing %s in dt node\n", __func__, mclk);
2539 id = DEFAULT_MCLK_RATE;
2540 }
2541 pdata->mclk_freq = id;
2542 card = msm8909_populate_sndcard_dailinks(&pdev->dev);
2543 dev_info(&pdev->dev, "default codec configured\n");
2544 num_strings = of_property_count_strings(pdev->dev.of_node,
2545 ext_pa);
2546 if (num_strings < 0) {
2547 dev_err(&pdev->dev,
2548 "%s: missing %s in dt node or length is incorrect\n",
2549 __func__, ext_pa);
2550 goto err;
2551 }
2552 for (i = 0; i < num_strings; i++) {
2553 ret = of_property_read_string_index(pdev->dev.of_node,
2554 ext_pa, i, &ext_pa_str);
2555 if (ret) {
2556 dev_err(&pdev->dev, "%s:of read string %s i %d error %d\n",
2557 __func__, ext_pa, i, ret);
2558 goto err;
2559 }
2560 if (!strcmp(ext_pa_str, "primary"))
2561 pdata->ext_pa = (pdata->ext_pa | PRI_MI2S_ID);
2562 else if (!strcmp(ext_pa_str, "secondary"))
2563 pdata->ext_pa = (pdata->ext_pa | SEC_MI2S_ID);
2564 else if (!strcmp(ext_pa_str, "tertiary"))
2565 pdata->ext_pa = (pdata->ext_pa | TER_MI2S_ID);
2566 else if (!strcmp(ext_pa_str, "quaternary"))
2567 pdata->ext_pa = (pdata->ext_pa | QUAT_MI2S_ID);
2568 else if (!strcmp(ext_pa_str, "quinary"))
2569 pdata->ext_pa = (pdata->ext_pa | QUIN_MI2S_ID);
2570 }
2571 pr_debug("%s: ext_pa = %d\n", __func__, pdata->ext_pa);
2572
2573 pdata->mi2s_gpio_p[QUAT_MI2S] = of_parse_phandle(pdev->dev.of_node,
2574 "qcom,quat-mi2s-gpios", 0);
2575 pdata->dmic_gpio_p = of_parse_phandle(pdev->dev.of_node,
2576 "qcom,cdc-dmic-gpios", 0);
2577
2578 ret = of_property_read_u32(pdev->dev.of_node,
2579 "qcom,msm-afe-clk-ver", &val);
2580 if (ret)
2581 pdata->afe_clk_ver = AFE_CLK_VERSION_V2;
2582 else
2583 pdata->afe_clk_ver = val;
2584 /* initialize the mclk */
2585 pdata->digital_cdc_clk.i2s_cfg_minor_version =
2586 AFE_API_VERSION_I2S_CONFIG;
2587 pdata->digital_cdc_clk.clk_val = pdata->mclk_freq;
2588 pdata->digital_cdc_clk.clk_root = 5;
2589 pdata->digital_cdc_clk.reserved = 0;
2590 /* initialize the digital codec core clk */
2591 pdata->digital_cdc_core_clk.clk_set_minor_version =
2592 AFE_API_VERSION_I2S_CONFIG;
2593 pdata->digital_cdc_core_clk.clk_id =
2594 Q6AFE_LPASS_CLK_ID_INTERNAL_DIGITAL_CODEC_CORE;
2595 pdata->digital_cdc_core_clk.clk_freq_in_hz =
2596 pdata->mclk_freq;
2597 pdata->digital_cdc_core_clk.clk_attri =
2598 Q6AFE_LPASS_CLK_ATTRIBUTE_COUPLE_NO;
2599 pdata->digital_cdc_core_clk.clk_root =
2600 Q6AFE_LPASS_CLK_ROOT_DEFAULT;
2601 pdata->digital_cdc_core_clk.enable = 1;
2602
2603 /* Initialize loopback mode to false */
2604 pdata->lb_mode = false;
2605
2606 card->dev = &pdev->dev;
2607 platform_set_drvdata(pdev, card);
2608 snd_soc_card_set_drvdata(card, pdata);
2609 ret = snd_soc_of_parse_card_name(card, "qcom,model");
2610 if (ret)
2611 goto err;
2612
2613 /* initialize timer */
2614 INIT_DELAYED_WORK(&pdata->disable_int_mclk0_work, msm_disable_mclk);
2615 mutex_init(&pdata->cdc_int_mclk0_mutex);
2616 atomic_set(&pdata->int_mclk0_rsc_ref, 0);
2617 if (card->aux_dev) {
2618 mutex_init(&pdata->wsa_mclk_mutex);
2619 atomic_set(&pdata->wsa_int_mclk0_rsc_ref, 0);
2620 }
2621 atomic_set(&pdata->int_mclk0_enabled, false);
2622 atomic_set(&quat_mi2s_clk_ref, 0);
2623 atomic_set(&quin_mi2s_clk_ref, 0);
2624 atomic_set(&auxpcm_mi2s_clk_ref, 0);
2625
2626 ret = snd_soc_of_parse_audio_routing(card,
2627 "qcom,audio-routing");
2628 if (ret)
2629 goto err;
2630
2631 ret = msm8909_populate_dai_link_component_of_node(card);
2632 if (ret) {
2633 ret = -EPROBE_DEFER;
2634 goto err;
2635 }
2636
2637 ret = devm_snd_soc_register_card(&pdev->dev, card);
2638 if (ret) {
2639 dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n",
2640 ret);
2641 goto err;
2642 }
2643 return 0;
2644err:
2645 if (pdata->vaddr_gpio_mux_spkr_ctl)
2646 iounmap(pdata->vaddr_gpio_mux_spkr_ctl);
2647 if (pdata->vaddr_gpio_mux_mic_ctl)
2648 iounmap(pdata->vaddr_gpio_mux_mic_ctl);
2649 if (pdata->vaddr_gpio_mux_pcm_ctl)
2650 iounmap(pdata->vaddr_gpio_mux_pcm_ctl);
2651 if (pdata->vaddr_gpio_mux_quin_ctl)
2652 iounmap(pdata->vaddr_gpio_mux_quin_ctl);
2653err1:
2654 devm_kfree(&pdev->dev, pdata);
2655 return ret;
2656}
2657
2658static int msm8909_asoc_machine_remove(struct platform_device *pdev)
2659{
2660 struct snd_soc_card *card = platform_get_drvdata(pdev);
2661 struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
2662
2663 if (pdata->vaddr_gpio_mux_spkr_ctl)
2664 iounmap(pdata->vaddr_gpio_mux_spkr_ctl);
2665 if (pdata->vaddr_gpio_mux_mic_ctl)
2666 iounmap(pdata->vaddr_gpio_mux_mic_ctl);
2667 if (pdata->vaddr_gpio_mux_pcm_ctl)
2668 iounmap(pdata->vaddr_gpio_mux_pcm_ctl);
2669 if (pdata->vaddr_gpio_mux_quin_ctl)
2670 iounmap(pdata->vaddr_gpio_mux_quin_ctl);
2671 snd_soc_unregister_card(card);
2672 mutex_destroy(&pdata->cdc_int_mclk0_mutex);
2673 return 0;
2674}
2675
2676static const struct of_device_id msm8909_asoc_machine_of_match[] = {
2677 { .compatible = "qcom,msm8909-audio-codec", },
2678 {},
2679};
2680
2681static struct platform_driver msm8909_asoc_machine_driver = {
2682 .driver = {
2683 .name = DRV_NAME,
2684 .owner = THIS_MODULE,
2685 .pm = &snd_soc_pm_ops,
2686 .of_match_table = msm8909_asoc_machine_of_match,
2687 },
2688 .probe = msm8909_asoc_machine_probe,
2689 .remove = msm8909_asoc_machine_remove,
2690};
2691
2692static int __init msm8909_machine_init(void)
2693{
2694 return platform_driver_register(&msm8909_asoc_machine_driver);
2695}
2696late_initcall(msm8909_machine_init);
2697
2698static void __exit msm8909_machine_exit(void)
2699{
2700 return platform_driver_unregister(&msm8909_asoc_machine_driver);
2701}
2702module_exit(msm8909_machine_exit);
2703
2704MODULE_DESCRIPTION("ALSA SoC msm");
2705MODULE_LICENSE("GPL v2");
2706MODULE_ALIAS("platform:" DRV_NAME);
2707MODULE_DEVICE_TABLE(of, msm8909_asoc_machine_of_match);