blob: 5dfd326574061239ab324f5f1dd5ccd60a53b013 [file] [log] [blame]
Bhalchandra Gajare120bd402013-03-06 15:30:19 -08001/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
Bhalchandra Gajare5baa95b2012-12-18 15:42:48 -08002 *
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/slab.h>
19#include <linux/mfd/pm8xxx/pm8921.h>
20#include <sound/core.h>
21#include <sound/soc.h>
22#include <sound/soc-dapm.h>
23#include <sound/pcm.h>
24#include <sound/jack.h>
25#include <asm/mach-types.h>
26#include <mach/socinfo.h>
27#include <qdsp6v2/msm-pcm-routing-v2.h>
28#include "../codecs/wcd9306.h"
Banajit Goswami25715c52013-05-10 11:45:47 -070029#include <linux/io.h>
Bhalchandra Gajare5baa95b2012-12-18 15:42:48 -080030
31#define DRV_NAME "msm8226-asoc-tapan"
32
33#define MSM_SLIM_0_RX_MAX_CHANNELS 2
34#define MSM_SLIM_0_TX_MAX_CHANNELS 4
35
36#define BTSCO_RATE_8KHZ 8000
37#define BTSCO_RATE_16KHZ 16000
38
Bhalchandra Gajare5baa95b2012-12-18 15:42:48 -080039#define WCD9XXX_MBHC_DEF_BUTTONS 8
40#define WCD9XXX_MBHC_DEF_RLOADS 5
41#define TAPAN_EXT_CLK_RATE 9600000
42
Banajit Goswami25715c52013-05-10 11:45:47 -070043#define NUM_OF_AUXPCM_GPIOS 4
44
45static int msm8226_auxpcm_rate = 8000;
46static atomic_t auxpcm_rsc_ref;
47static const char *const auxpcm_rate_text[] = {"rate_8000", "rate_16000"};
48static const struct soc_enum msm8226_auxpcm_enum[] = {
49 SOC_ENUM_SINGLE_EXT(2, auxpcm_rate_text),
50};
51
52#define LPAIF_OFFSET 0xFE000000
53#define LPAIF_PRI_MODE_MUXSEL (LPAIF_OFFSET + 0x2B000)
54#define LPAIF_SEC_MODE_MUXSEL (LPAIF_OFFSET + 0x2C000)
55#define LPAIF_TER_MODE_MUXSEL (LPAIF_OFFSET + 0x2D000)
56#define LPAIF_QUAD_MODE_MUXSEL (LPAIF_OFFSET + 0x2E000)
57
58#define I2S_PCM_SEL 1
59#define I2S_PCM_SEL_OFFSET 1
60
Bhalchandra Gajare5baa95b2012-12-18 15:42:48 -080061void *def_tapan_mbhc_cal(void);
62static int msm_snd_enable_codec_ext_clk(struct snd_soc_codec *codec, int enable,
63 bool dapm);
64
65static struct wcd9xxx_mbhc_config mbhc_cfg = {
66 .read_fw_bin = false,
67 .calibration = NULL,
68 .micbias = MBHC_MICBIAS2,
69 .mclk_cb_fn = msm_snd_enable_codec_ext_clk,
70 .mclk_rate = TAPAN_EXT_CLK_RATE,
71 .gpio = 0,
72 .gpio_irq = 0,
Simmi Pateriya432cbcf2013-04-04 02:17:26 +053073 .gpio_level_insert = 0,
Bhalchandra Gajare5baa95b2012-12-18 15:42:48 -080074 .detect_extn_cable = true,
Phani Kumar Uppalapati9784bbb2013-06-13 17:49:07 -070075 .micbias_enable_flags = 1 << MBHC_MICBIAS_ENABLE_THRESHOLD_HEADSET,
Bhalchandra Gajare5baa95b2012-12-18 15:42:48 -080076 .insert_detect = true,
77 .swap_gnd_mic = NULL,
78};
79
Banajit Goswami25715c52013-05-10 11:45:47 -070080struct msm_auxpcm_gpio {
81 unsigned gpio_no;
82 const char *gpio_name;
83};
84
85struct msm_auxpcm_ctrl {
86 struct msm_auxpcm_gpio *pin_data;
87 u32 cnt;
88};
89
Bhalchandra Gajare5baa95b2012-12-18 15:42:48 -080090struct msm8226_asoc_mach_data {
91 int mclk_gpio;
92 u32 mclk_freq;
Banajit Goswami25715c52013-05-10 11:45:47 -070093 struct msm_auxpcm_ctrl *auxpcm_ctrl;
Bhalchandra Gajare6ce3b712013-04-23 17:30:40 -070094 u32 us_euro_gpio;
Bhalchandra Gajare5baa95b2012-12-18 15:42:48 -080095};
96
Banajit Goswami25715c52013-05-10 11:45:47 -070097#define GPIO_NAME_INDEX 0
98#define DT_PARSE_INDEX 1
99
100static char *msm_auxpcm_gpio_name[][2] = {
101 {"PRIM_AUXPCM_CLK", "qcom,prim-auxpcm-gpio-clk"},
102 {"PRIM_AUXPCM_SYNC", "qcom,prim-auxpcm-gpio-sync"},
103 {"PRIM_AUXPCM_DIN", "qcom,prim-auxpcm-gpio-din"},
104 {"PRIM_AUXPCM_DOUT", "qcom,prim-auxpcm-gpio-dout"},
105};
106
107void *lpaif_pri_muxsel_virt_addr;
108
Bhalchandra Gajare5baa95b2012-12-18 15:42:48 -0800109/* Shared channel numbers for Slimbus ports that connect APQ to MDM. */
110enum {
111 SLIM_1_RX_1 = 145, /* BT-SCO and USB TX */
112 SLIM_1_TX_1 = 146, /* BT-SCO and USB RX */
113 SLIM_2_RX_1 = 147, /* HDMI RX */
114 SLIM_3_RX_1 = 148, /* In-call recording RX */
115 SLIM_3_RX_2 = 149, /* In-call recording RX */
116 SLIM_4_TX_1 = 150, /* In-call musid delivery TX */
117};
118
119static int msm_slim_0_rx_ch = 1;
120static int msm_slim_0_tx_ch = 1;
121
122static int msm_btsco_rate = BTSCO_RATE_8KHZ;
123static int msm_btsco_ch = 1;
124
125static struct mutex cdc_mclk_mutex;
Bhalchandra Gajared5a4ba72013-03-11 16:15:13 -0700126static struct clk *codec_clk;
Bhalchandra Gajare5baa95b2012-12-18 15:42:48 -0800127static int clk_users;
Bhalchandra Gajare0eca29d2013-03-14 17:54:53 -0700128static int vdd_spkr_gpio = -1;
Krishnankutty Kolathappilly80bf6d42013-06-06 17:54:40 -0700129static int msm_proxy_rx_ch = 2;
Bhalchandra Gajare5baa95b2012-12-18 15:42:48 -0800130
131static int msm_snd_enable_codec_ext_clk(struct snd_soc_codec *codec, int enable,
132 bool dapm)
133{
134 int ret = 0;
135 pr_debug("%s: enable = %d clk_users = %d\n",
136 __func__, enable, clk_users);
137
138 mutex_lock(&cdc_mclk_mutex);
139 if (enable) {
Bhalchandra Gajared5a4ba72013-03-11 16:15:13 -0700140 if (!codec_clk) {
141 dev_err(codec->dev, "%s: did not get Taiko MCLK\n",
142 __func__);
143 ret = -EINVAL;
144 goto exit;
145 }
Bhalchandra Gajare5baa95b2012-12-18 15:42:48 -0800146
147 clk_users++;
148 if (clk_users != 1)
149 goto exit;
Bhalchandra Gajared5a4ba72013-03-11 16:15:13 -0700150 if (codec_clk) {
Bhalchandra Gajared5a4ba72013-03-11 16:15:13 -0700151 clk_prepare_enable(codec_clk);
152 tapan_mclk_enable(codec, 1, dapm);
153 } else {
154 pr_err("%s: Error setting Tapan MCLK\n", __func__);
155 clk_users--;
156 ret = -EINVAL;
157 goto exit;
158 }
Bhalchandra Gajare5baa95b2012-12-18 15:42:48 -0800159 } else {
160 if (clk_users > 0) {
161 clk_users--;
162 if (clk_users == 0) {
163 tapan_mclk_enable(codec, 0, dapm);
Bhalchandra Gajared5a4ba72013-03-11 16:15:13 -0700164 clk_disable_unprepare(codec_clk);
Bhalchandra Gajare5baa95b2012-12-18 15:42:48 -0800165 }
166 } else {
Bhalchandra Gajared5a4ba72013-03-11 16:15:13 -0700167 pr_err("%s: Error releasing Tapan MCLK\n", __func__);
Bhalchandra Gajare5baa95b2012-12-18 15:42:48 -0800168 ret = -EINVAL;
169 goto exit;
170 }
171 }
172exit:
173 mutex_unlock(&cdc_mclk_mutex);
174 return ret;
175}
176
177static int msm8226_mclk_event(struct snd_soc_dapm_widget *w,
178 struct snd_kcontrol *kcontrol, int event)
179{
180 pr_debug("%s: event = %d\n", __func__, event);
181
182 switch (event) {
183 case SND_SOC_DAPM_PRE_PMU:
184 return msm_snd_enable_codec_ext_clk(w->codec, 1, true);
185 case SND_SOC_DAPM_POST_PMD:
186 return msm_snd_enable_codec_ext_clk(w->codec, 0, true);
187 }
188
189 return 0;
190}
191
Bhalchandra Gajare0eca29d2013-03-14 17:54:53 -0700192static int msm8226_vdd_spkr_event(struct snd_soc_dapm_widget *w,
193 struct snd_kcontrol *kcontrol, int event)
194{
195 pr_debug("%s: event = %d\n", __func__, event);
196
197 switch (event) {
198 case SND_SOC_DAPM_PRE_PMU:
199 if (vdd_spkr_gpio >= 0) {
200 gpio_direction_output(vdd_spkr_gpio, 1);
201 pr_debug("%s: Enabled 5V external supply for speaker\n",
202 __func__);
203 }
204 break;
205 case SND_SOC_DAPM_POST_PMD:
206 if (vdd_spkr_gpio >= 0) {
207 gpio_direction_output(vdd_spkr_gpio, 0);
208 pr_debug("%s: Disabled 5V external supply for speaker\n",
209 __func__);
210 }
211 break;
212 }
213 return 0;
214}
215
Bhalchandra Gajare5baa95b2012-12-18 15:42:48 -0800216static const struct snd_soc_dapm_widget msm8226_dapm_widgets[] = {
217
218 SND_SOC_DAPM_SUPPLY("MCLK", SND_SOC_NOPM, 0, 0,
219 msm8226_mclk_event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
220
221 SND_SOC_DAPM_MIC("Handset Mic", NULL),
222 SND_SOC_DAPM_MIC("Headset Mic", NULL),
223 SND_SOC_DAPM_MIC("ANCRight Headset Mic", NULL),
224 SND_SOC_DAPM_MIC("ANCLeft Headset Mic", NULL),
225
226 SND_SOC_DAPM_MIC("Digital Mic1", NULL),
227 SND_SOC_DAPM_MIC("Digital Mic2", NULL),
228 SND_SOC_DAPM_MIC("Digital Mic3", NULL),
229 SND_SOC_DAPM_MIC("Digital Mic4", NULL),
230 SND_SOC_DAPM_MIC("Digital Mic5", NULL),
231 SND_SOC_DAPM_MIC("Digital Mic6", NULL),
Bhalchandra Gajare0eca29d2013-03-14 17:54:53 -0700232
233 SND_SOC_DAPM_SUPPLY("EXT_VDD_SPKR", SND_SOC_NOPM, 0, 0,
234 msm8226_vdd_spkr_event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
Bhalchandra Gajare5baa95b2012-12-18 15:42:48 -0800235};
236
237static const char *const slim0_rx_ch_text[] = {"One", "Two"};
238static const char *const slim0_tx_ch_text[] = {"One", "Two", "Three", "Four"};
Krishnankutty Kolathappilly80bf6d42013-06-06 17:54:40 -0700239static const char *const proxy_rx_ch_text[] = {"One", "Two", "Three", "Four",
240 "Five", "Six", "Seven", "Eight"};
Bhalchandra Gajare5baa95b2012-12-18 15:42:48 -0800241
242static const struct soc_enum msm_enum[] = {
243 SOC_ENUM_SINGLE_EXT(2, slim0_rx_ch_text),
244 SOC_ENUM_SINGLE_EXT(4, slim0_tx_ch_text),
245};
246
247static const char *const btsco_rate_text[] = {"8000", "16000"};
248static const struct soc_enum msm_btsco_enum[] = {
249 SOC_ENUM_SINGLE_EXT(2, btsco_rate_text),
250};
251
252static int msm_slim_0_rx_ch_get(struct snd_kcontrol *kcontrol,
253 struct snd_ctl_elem_value *ucontrol)
254{
255 pr_debug("%s: msm_slim_0_rx_ch = %d\n", __func__,
256 msm_slim_0_rx_ch);
257 ucontrol->value.integer.value[0] = msm_slim_0_rx_ch - 1;
258 return 0;
259}
260
261static int msm_slim_0_rx_ch_put(struct snd_kcontrol *kcontrol,
262 struct snd_ctl_elem_value *ucontrol)
263{
264 msm_slim_0_rx_ch = ucontrol->value.integer.value[0] + 1;
265
266 pr_debug("%s: msm_slim_0_rx_ch = %d\n", __func__,
267 msm_slim_0_rx_ch);
268 return 1;
269}
270
271static int msm_slim_0_tx_ch_get(struct snd_kcontrol *kcontrol,
272 struct snd_ctl_elem_value *ucontrol)
273{
274 pr_debug("%s: msm_slim_0_tx_ch = %d\n", __func__,
275 msm_slim_0_tx_ch);
276 ucontrol->value.integer.value[0] = msm_slim_0_tx_ch - 1;
277 return 0;
278}
279
280static int msm_slim_0_tx_ch_put(struct snd_kcontrol *kcontrol,
281 struct snd_ctl_elem_value *ucontrol)
282{
283 msm_slim_0_tx_ch = ucontrol->value.integer.value[0] + 1;
284
285 pr_debug("%s: msm_slim_0_tx_ch = %d\n", __func__, msm_slim_0_tx_ch);
286 return 1;
287}
288
289static int msm_btsco_rate_get(struct snd_kcontrol *kcontrol,
290 struct snd_ctl_elem_value *ucontrol)
291{
292 pr_debug("%s: msm_btsco_rate = %d", __func__, msm_btsco_rate);
293 ucontrol->value.integer.value[0] = msm_btsco_rate;
294 return 0;
295}
296
297static int msm_btsco_rate_put(struct snd_kcontrol *kcontrol,
298 struct snd_ctl_elem_value *ucontrol)
299{
300 switch (ucontrol->value.integer.value[0]) {
Vicky Sehrawate6525c22013-04-25 14:21:42 -0700301 case 8000:
Bhalchandra Gajare5baa95b2012-12-18 15:42:48 -0800302 msm_btsco_rate = BTSCO_RATE_8KHZ;
303 break;
Vicky Sehrawate6525c22013-04-25 14:21:42 -0700304 case 16000:
Bhalchandra Gajare5baa95b2012-12-18 15:42:48 -0800305 msm_btsco_rate = BTSCO_RATE_16KHZ;
306 break;
307 default:
308 msm_btsco_rate = BTSCO_RATE_8KHZ;
309 break;
310 }
311
312 pr_debug("%s: msm_btsco_rate = %d\n", __func__, msm_btsco_rate);
313 return 0;
314}
315
Bhalchandra Gajare5baa95b2012-12-18 15:42:48 -0800316static int msm_btsco_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
317 struct snd_pcm_hw_params *params)
318{
319 struct snd_interval *rate = hw_param_interval(params,
320 SNDRV_PCM_HW_PARAM_RATE);
321
322 struct snd_interval *channels = hw_param_interval(params,
323 SNDRV_PCM_HW_PARAM_CHANNELS);
324
325 rate->min = rate->max = msm_btsco_rate;
326 channels->min = channels->max = msm_btsco_ch;
327
328 return 0;
329}
330
Banajit Goswami25715c52013-05-10 11:45:47 -0700331static int msm8226_auxpcm_rate_get(struct snd_kcontrol *kcontrol,
332 struct snd_ctl_elem_value *ucontrol)
333{
334 ucontrol->value.integer.value[0] = msm8226_auxpcm_rate;
335 return 0;
336}
337
338static int msm8226_auxpcm_rate_put(struct snd_kcontrol *kcontrol,
339 struct snd_ctl_elem_value *ucontrol)
340{
341 switch (ucontrol->value.integer.value[0]) {
342 case 0:
343 msm8226_auxpcm_rate = 8000;
344 break;
345 case 1:
346 msm8226_auxpcm_rate = 16000;
347 break;
348 default:
349 msm8226_auxpcm_rate = 8000;
350 break;
351 }
352 return 0;
353}
354
Krishnankutty Kolathappilly80bf6d42013-06-06 17:54:40 -0700355static int msm_proxy_rx_ch_get(struct snd_kcontrol *kcontrol,
356 struct snd_ctl_elem_value *ucontrol)
357{
358 pr_debug("%s: msm_proxy_rx_ch = %d\n", __func__,
359 msm_proxy_rx_ch);
360 ucontrol->value.integer.value[0] = msm_proxy_rx_ch - 1;
361 return 0;
362}
363
364static int msm_proxy_rx_ch_put(struct snd_kcontrol *kcontrol,
365 struct snd_ctl_elem_value *ucontrol)
366{
367 msm_proxy_rx_ch = ucontrol->value.integer.value[0] + 1;
368 pr_debug("%s: msm_proxy_rx_ch = %d\n", __func__,
369 msm_proxy_rx_ch);
370 return 1;
371}
Banajit Goswami25715c52013-05-10 11:45:47 -0700372static int msm_auxpcm_be_params_fixup(struct snd_soc_pcm_runtime *rtd,
373 struct snd_pcm_hw_params *params)
374{
375 struct snd_interval *rate =
376 hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
377
378 struct snd_interval *channels =
379 hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
380
381 rate->min = rate->max = msm8226_auxpcm_rate;
382 channels->min = channels->max = 1;
383
384 return 0;
385}
386
Krishnankutty Kolathappilly80bf6d42013-06-06 17:54:40 -0700387static int msm_proxy_rx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
388 struct snd_pcm_hw_params *params)
Bhalchandra Gajare5baa95b2012-12-18 15:42:48 -0800389{
390 struct snd_interval *rate = hw_param_interval(params,
Krishnankutty Kolathappilly80bf6d42013-06-06 17:54:40 -0700391 SNDRV_PCM_HW_PARAM_RATE);
Bhalchandra Gajare5baa95b2012-12-18 15:42:48 -0800392
Krishnankutty Kolathappilly80bf6d42013-06-06 17:54:40 -0700393 struct snd_interval *channels = hw_param_interval(params,
394 SNDRV_PCM_HW_PARAM_CHANNELS);
395
396 pr_debug("%s: msm_proxy_rx_ch =%d\n", __func__, msm_proxy_rx_ch);
397
398 if (channels->max < 2)
399 channels->min = channels->max = 2;
400 channels->min = channels->max = msm_proxy_rx_ch;
Bhalchandra Gajare5baa95b2012-12-18 15:42:48 -0800401 rate->min = rate->max = 48000;
Krishnankutty Kolathappilly80bf6d42013-06-06 17:54:40 -0700402 return 0;
403}
Bhalchandra Gajare5baa95b2012-12-18 15:42:48 -0800404
Krishnankutty Kolathappilly80bf6d42013-06-06 17:54:40 -0700405static int msm_proxy_tx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
406 struct snd_pcm_hw_params *params)
407{
408 struct snd_interval *rate = hw_param_interval(params,
409 SNDRV_PCM_HW_PARAM_RATE);
410
411 rate->min = rate->max = 48000;
Bhalchandra Gajare5baa95b2012-12-18 15:42:48 -0800412 return 0;
413}
414
Banajit Goswami25715c52013-05-10 11:45:47 -0700415static int msm_aux_pcm_get_gpios(struct msm_auxpcm_ctrl *auxpcm_ctrl)
416{
417 struct msm_auxpcm_gpio *pin_data = NULL;
418 int ret = 0;
419 int i;
420 int j;
421
422 pin_data = auxpcm_ctrl->pin_data;
423 if (!pin_data) {
424 pr_err("%s: Invalid control data for AUXPCM\n", __func__);
425 ret = -EINVAL;
426 goto err;
427 }
428 for (i = 0; i < auxpcm_ctrl->cnt; i++, pin_data++) {
429 ret = gpio_request(pin_data->gpio_no,
430 pin_data->gpio_name);
431 pr_debug("%s: gpio = %d, gpio name = %s\n"
432 "ret = %d\n", __func__,
433 pin_data->gpio_no,
434 pin_data->gpio_name,
435 ret);
436 if (ret) {
437 pr_err("%s: Failed to request gpio %d\n",
438 __func__, pin_data->gpio_no);
439 /* Release all GPIOs on failure */
440 if (i > 0) {
441 for (j = i; j >= 0; j--)
442 gpio_free(pin_data->gpio_no);
443 }
444 goto err;
445 }
446 }
447err:
448 return ret;
449}
450
451static int msm_aux_pcm_free_gpios(struct msm_auxpcm_ctrl *auxpcm_ctrl)
452{
453 struct msm_auxpcm_gpio *pin_data = NULL;
454 int i;
455 int ret = 0;
456
457 if (auxpcm_ctrl == NULL || auxpcm_ctrl->pin_data == NULL) {
458 pr_err("%s: Invalid control data for AUXPCM\n", __func__);
459 ret = -EINVAL;
460 goto err;
461 }
462
463 pin_data = auxpcm_ctrl->pin_data;
464 for (i = 0; i < auxpcm_ctrl->cnt; i++, pin_data++) {
465 gpio_free(pin_data->gpio_no);
466 pr_debug("%s: gpio = %d, gpio_name = %s\n",
467 __func__, pin_data->gpio_no,
468 pin_data->gpio_name);
469 }
470err:
471 return ret;
472}
473
474static int msm_auxpcm_startup(struct snd_pcm_substream *substream)
475{
476 struct snd_soc_pcm_runtime *rtd = substream->private_data;
477 struct snd_soc_card *card = rtd->card;
478 struct msm8226_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
479 struct msm_auxpcm_ctrl *auxpcm_ctrl = NULL;
480 int ret = 0;
481
482 pr_debug("%s(): substream = %s, auxpcm_rsc_ref counter = %d\n",
483 __func__, substream->name, atomic_read(&auxpcm_rsc_ref));
484
485 auxpcm_ctrl = pdata->auxpcm_ctrl;
486
487 if (auxpcm_ctrl == NULL || auxpcm_ctrl->pin_data == NULL ||
488 lpaif_pri_muxsel_virt_addr == NULL) {
489 pr_err("%s: Invalid control data for AUXPCM\n", __func__);
490 ret = -EINVAL;
491 goto err;
492 }
493 if (atomic_inc_return(&auxpcm_rsc_ref) == 1) {
494 iowrite32(I2S_PCM_SEL << I2S_PCM_SEL_OFFSET,
495 lpaif_pri_muxsel_virt_addr);
496 ret = msm_aux_pcm_get_gpios(auxpcm_ctrl);
497 }
498 if (ret < 0) {
499 pr_err("%s: Aux PCM GPIO request failed\n", __func__);
500 return -EINVAL;
501 }
502err:
503 return ret;
504}
505
506static void msm_auxpcm_shutdown(struct snd_pcm_substream *substream)
507{
508 struct snd_soc_pcm_runtime *rtd = substream->private_data;
509 struct snd_soc_card *card = rtd->card;
510 struct msm8226_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
511 struct msm_auxpcm_ctrl *auxpcm_ctrl = NULL;
512
513 pr_debug("%s(): substream = %s, auxpcm_rsc_ref counter = %d\n",
514 __func__, substream->name, atomic_read(&auxpcm_rsc_ref));
515
516 auxpcm_ctrl = pdata->auxpcm_ctrl;
517
518 if (atomic_dec_return(&auxpcm_rsc_ref) == 0)
519 msm_aux_pcm_free_gpios(auxpcm_ctrl);
520}
521
522static struct snd_soc_ops msm_auxpcm_be_ops = {
523 .startup = msm_auxpcm_startup,
524 .shutdown = msm_auxpcm_shutdown,
525};
526
Bhalchandra Gajare5baa95b2012-12-18 15:42:48 -0800527static int msm_slim_0_rx_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 =
534 hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
535
536 pr_debug("%s()\n", __func__);
537 rate->min = rate->max = 48000;
538 channels->min = channels->max = msm_slim_0_rx_ch;
539
540 return 0;
541}
542
543static int msm_slim_0_tx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
544 struct snd_pcm_hw_params *params)
545{
546 struct snd_interval *rate = hw_param_interval(params,
547 SNDRV_PCM_HW_PARAM_RATE);
548
549 struct snd_interval *channels = hw_param_interval(params,
550 SNDRV_PCM_HW_PARAM_CHANNELS);
551
552 pr_debug("%s()\n", __func__);
553 rate->min = rate->max = 48000;
554 channels->min = channels->max = msm_slim_0_tx_ch;
555
556 return 0;
557}
558
559static int msm_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
560 struct snd_pcm_hw_params *params)
561{
562 struct snd_interval *rate = hw_param_interval(params,
563 SNDRV_PCM_HW_PARAM_RATE);
564
565 pr_debug("%s()\n", __func__);
566 rate->min = rate->max = 48000;
567
568 return 0;
569}
570
571static const struct soc_enum msm_snd_enum[] = {
572 SOC_ENUM_SINGLE_EXT(2, slim0_rx_ch_text),
573 SOC_ENUM_SINGLE_EXT(4, slim0_tx_ch_text),
Krishnankutty Kolathappilly80bf6d42013-06-06 17:54:40 -0700574 SOC_ENUM_SINGLE_EXT(8, proxy_rx_ch_text),
Bhalchandra Gajare5baa95b2012-12-18 15:42:48 -0800575};
576
577static const struct snd_kcontrol_new msm_snd_controls[] = {
Bhalchandra Gajareda9d2dc2013-03-06 16:06:57 -0800578 SOC_ENUM_EXT("SLIM_0_RX Channels", msm_snd_enum[0],
Bhalchandra Gajare5baa95b2012-12-18 15:42:48 -0800579 msm_slim_0_rx_ch_get, msm_slim_0_rx_ch_put),
Bhalchandra Gajareda9d2dc2013-03-06 16:06:57 -0800580 SOC_ENUM_EXT("SLIM_0_TX Channels", msm_snd_enum[1],
Bhalchandra Gajare5baa95b2012-12-18 15:42:48 -0800581 msm_slim_0_tx_ch_get, msm_slim_0_tx_ch_put),
Banajit Goswami25715c52013-05-10 11:45:47 -0700582 SOC_ENUM_EXT("AUX PCM SampleRate", msm8226_auxpcm_enum[0],
583 msm8226_auxpcm_rate_get, msm8226_auxpcm_rate_put),
Vicky Sehrawate6525c22013-04-25 14:21:42 -0700584 SOC_ENUM_EXT("Internal BTSCO SampleRate", msm_btsco_enum[0],
585 msm_btsco_rate_get, msm_btsco_rate_put),
Krishnankutty Kolathappilly80bf6d42013-06-06 17:54:40 -0700586 SOC_ENUM_EXT("PROXY_RX Channels", msm_snd_enum[2],
587 msm_proxy_rx_ch_get, msm_proxy_rx_ch_put),
Bhalchandra Gajare5baa95b2012-12-18 15:42:48 -0800588};
589
590static int msm_audrx_init(struct snd_soc_pcm_runtime *rtd)
591{
592 int err;
593 struct snd_soc_codec *codec = rtd->codec;
594 struct snd_soc_dapm_context *dapm = &codec->dapm;
595 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
596 struct snd_soc_dai *codec_dai = rtd->codec_dai;
597
598 /*
599 * Tapan SLIMBUS configuration
600 * RX1, RX2, RX3, RX4, RX5, RX6, RX7, RX8, RX9, RX10, RX11, RX12, RX13
601 * TX1, TX2, TX3, TX4, TX5, TX6, TX7, TX8, TX9, TX10, TX11, TX12, TX13
602 * TX14, TX15, TX16
603 */
604 unsigned int rx_ch[TAPAN_RX_MAX] = {144, 145, 146, 147, 148};
605 unsigned int tx_ch[TAPAN_TX_MAX] = {128, 129, 130, 131, 132};
606
607
608 pr_debug("%s(), dev_name%s\n", __func__, dev_name(cpu_dai->dev));
609
610 rtd->pmdown_time = 0;
611
612 err = snd_soc_add_codec_controls(codec, msm_snd_controls,
613 ARRAY_SIZE(msm_snd_controls));
614 if (err < 0)
615 return err;
616
617 snd_soc_dapm_new_controls(dapm, msm8226_dapm_widgets,
618 ARRAY_SIZE(msm8226_dapm_widgets));
619
620 snd_soc_dapm_sync(dapm);
621
Bhalchandra Gajared5a4ba72013-03-11 16:15:13 -0700622 codec_clk = clk_get(cpu_dai->dev, "osr_clk");
623 if (codec_clk < 0)
624 pr_err("%s() Failed to get clock for %s\n",
625 __func__, dev_name(cpu_dai->dev));
626
Bhalchandra Gajare5baa95b2012-12-18 15:42:48 -0800627 snd_soc_dai_set_channel_map(codec_dai, ARRAY_SIZE(tx_ch),
628 tx_ch, ARRAY_SIZE(rx_ch), rx_ch);
629
630 /* start mbhc */
631 mbhc_cfg.calibration = def_tapan_mbhc_cal();
Simmi Pateriya432cbcf2013-04-04 02:17:26 +0530632 if (mbhc_cfg.calibration)
633 err = tapan_hs_detect(codec, &mbhc_cfg);
Bhalchandra Gajare5baa95b2012-12-18 15:42:48 -0800634 else
635 err = -ENOMEM;
636
637 return err;
638}
639
640static int msm_snd_startup(struct snd_pcm_substream *substream)
641{
642 pr_debug("%s(): substream = %s stream = %d\n", __func__,
643 substream->name, substream->stream);
644 return 0;
645}
646
647void *def_tapan_mbhc_cal(void)
648{
649 void *tapan_cal;
650 struct wcd9xxx_mbhc_btn_detect_cfg *btn_cfg;
651 u16 *btn_low, *btn_high;
652 u8 *n_ready, *n_cic, *gain;
653
654 tapan_cal = kzalloc(WCD9XXX_MBHC_CAL_SIZE(WCD9XXX_MBHC_DEF_BUTTONS,
655 WCD9XXX_MBHC_DEF_RLOADS),
656 GFP_KERNEL);
657 if (!tapan_cal) {
658 pr_err("%s: out of memory\n", __func__);
659 return NULL;
660 }
661
662#define S(X, Y) ((WCD9XXX_MBHC_CAL_GENERAL_PTR(tapan_cal)->X) = (Y))
663 S(t_ldoh, 100);
664 S(t_bg_fast_settle, 100);
665 S(t_shutdown_plug_rem, 255);
Simmi Pateriya432cbcf2013-04-04 02:17:26 +0530666 S(mbhc_nsa, 2);
667 S(mbhc_navg, 128);
Bhalchandra Gajare5baa95b2012-12-18 15:42:48 -0800668#undef S
669#define S(X, Y) ((WCD9XXX_MBHC_CAL_PLUG_DET_PTR(tapan_cal)->X) = (Y))
670 S(mic_current, TAPAN_PID_MIC_5_UA);
671 S(hph_current, TAPAN_PID_MIC_5_UA);
672 S(t_mic_pid, 100);
673 S(t_ins_complete, 250);
674 S(t_ins_retry, 200);
675#undef S
676#define S(X, Y) ((WCD9XXX_MBHC_CAL_PLUG_TYPE_PTR(tapan_cal)->X) = (Y))
677 S(v_no_mic, 30);
Phani Kumar Uppalapatia2aa7312013-05-21 23:09:13 -0700678 S(v_hs_max, 2450);
Bhalchandra Gajare5baa95b2012-12-18 15:42:48 -0800679#undef S
680#define S(X, Y) ((WCD9XXX_MBHC_CAL_BTN_DET_PTR(tapan_cal)->X) = (Y))
681 S(c[0], 62);
682 S(c[1], 124);
683 S(nc, 1);
Simmi Pateriya432cbcf2013-04-04 02:17:26 +0530684 S(n_meas, 5);
Bhalchandra Gajare5baa95b2012-12-18 15:42:48 -0800685 S(mbhc_nsc, 11);
686 S(n_btn_meas, 1);
687 S(n_btn_con, 2);
688 S(num_btn, WCD9XXX_MBHC_DEF_BUTTONS);
689 S(v_btn_press_delta_sta, 100);
690 S(v_btn_press_delta_cic, 50);
691#undef S
692 btn_cfg = WCD9XXX_MBHC_CAL_BTN_DET_PTR(tapan_cal);
693 btn_low = wcd9xxx_mbhc_cal_btn_det_mp(btn_cfg, MBHC_BTN_DET_V_BTN_LOW);
694 btn_high = wcd9xxx_mbhc_cal_btn_det_mp(btn_cfg,
695 MBHC_BTN_DET_V_BTN_HIGH);
696 btn_low[0] = -50;
697 btn_high[0] = 10;
698 btn_low[1] = 11;
699 btn_high[1] = 52;
700 btn_low[2] = 53;
701 btn_high[2] = 94;
702 btn_low[3] = 95;
703 btn_high[3] = 133;
704 btn_low[4] = 134;
705 btn_high[4] = 171;
706 btn_low[5] = 172;
707 btn_high[5] = 208;
708 btn_low[6] = 209;
709 btn_high[6] = 244;
710 btn_low[7] = 245;
711 btn_high[7] = 330;
712 n_ready = wcd9xxx_mbhc_cal_btn_det_mp(btn_cfg, MBHC_BTN_DET_N_READY);
713 n_ready[0] = 80;
Simmi Pateriya432cbcf2013-04-04 02:17:26 +0530714 n_ready[1] = 12;
Bhalchandra Gajare5baa95b2012-12-18 15:42:48 -0800715 n_cic = wcd9xxx_mbhc_cal_btn_det_mp(btn_cfg, MBHC_BTN_DET_N_CIC);
716 n_cic[0] = 60;
717 n_cic[1] = 47;
718 gain = wcd9xxx_mbhc_cal_btn_det_mp(btn_cfg, MBHC_BTN_DET_GAIN);
719 gain[0] = 11;
Simmi Pateriya432cbcf2013-04-04 02:17:26 +0530720 gain[1] = 14;
Bhalchandra Gajare5baa95b2012-12-18 15:42:48 -0800721
722 return tapan_cal;
723}
724
725static int msm_snd_hw_params(struct snd_pcm_substream *substream,
726 struct snd_pcm_hw_params *params)
727{
728 struct snd_soc_pcm_runtime *rtd = substream->private_data;
729 struct snd_soc_dai *codec_dai = rtd->codec_dai;
730 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
731 int ret = 0;
732 unsigned int rx_ch[SLIM_MAX_RX_PORTS], tx_ch[SLIM_MAX_TX_PORTS];
733 unsigned int rx_ch_cnt = 0, tx_ch_cnt = 0;
734 unsigned int user_set_tx_ch = 0;
735
736 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
737 pr_debug("%s: rx_0_ch=%d\n", __func__, msm_slim_0_rx_ch);
738 ret = snd_soc_dai_get_channel_map(codec_dai,
739 &tx_ch_cnt, tx_ch, &rx_ch_cnt , rx_ch);
740 if (ret < 0) {
741 pr_err("%s: failed to get codec chan map\n", __func__);
742 goto end;
743 }
744
745 ret = snd_soc_dai_set_channel_map(cpu_dai, 0, 0,
746 msm_slim_0_rx_ch, rx_ch);
747 if (ret < 0) {
748 pr_err("%s: failed to set cpu chan map\n", __func__);
749 goto end;
750 }
751 } else {
752
753 pr_debug("%s: %s_tx_dai_id_%d_ch=%d\n", __func__,
754 codec_dai->name, codec_dai->id, user_set_tx_ch);
755
756 ret = snd_soc_dai_get_channel_map(codec_dai,
757 &tx_ch_cnt, tx_ch, &rx_ch_cnt , rx_ch);
758 if (ret < 0) {
759 pr_err("%s: failed to get codec chan map\n", __func__);
760 goto end;
761 }
762 /* For tabla_tx1 case */
763 if (codec_dai->id == 1)
764 user_set_tx_ch = msm_slim_0_tx_ch;
765 /* For tabla_tx2 case */
766 else if (codec_dai->id == 3)
767 user_set_tx_ch = params_channels(params);
768 else
769 user_set_tx_ch = tx_ch_cnt;
770
771 pr_debug("%s: msm_slim_0_tx_ch(%d)user_set_tx_ch(%d)tx_ch_cnt(%d)\n",
772 __func__, msm_slim_0_tx_ch, user_set_tx_ch, tx_ch_cnt);
773
774 ret = snd_soc_dai_set_channel_map(cpu_dai,
775 user_set_tx_ch, tx_ch, 0 , 0);
776 if (ret < 0) {
777 pr_err("%s: failed to set cpu chan map\n", __func__);
778 goto end;
779 }
780 }
781end:
782 return ret;
783}
784
785static void msm_snd_shutdown(struct snd_pcm_substream *substream)
786{
787 pr_debug("%s(): substream = %s stream = %d\n", __func__,
788 substream->name, substream->stream);
789}
790
791static struct snd_soc_ops msm8226_be_ops = {
792 .startup = msm_snd_startup,
793 .hw_params = msm_snd_hw_params,
794 .shutdown = msm_snd_shutdown,
795};
796
797/* Digital audio interface glue - connects codec <---> CPU */
798static struct snd_soc_dai_link msm8226_dai[] = {
799 /* FrontEnd DAI Links */
800 {
801 .name = "MSM8226 Media1",
802 .stream_name = "MultiMedia1",
803 .cpu_dai_name = "MultiMedia1",
Bhalchandra Gajareda9d2dc2013-03-06 16:06:57 -0800804 .platform_name = "msm-pcm-dsp.0",
Bhalchandra Gajare5baa95b2012-12-18 15:42:48 -0800805 .dynamic = 1,
806 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
807 SND_SOC_DPCM_TRIGGER_POST},
808 .codec_dai_name = "snd-soc-dummy-dai",
809 .codec_name = "snd-soc-dummy",
810 .ignore_suspend = 1,
811 /* This dainlink has playback support */
812 .ignore_pmdown_time = 1,
813 .be_id = MSM_FRONTEND_DAI_MULTIMEDIA1
814 },
815 {
816 .name = "MSM8226 Media2",
817 .stream_name = "MultiMedia2",
818 .cpu_dai_name = "MultiMedia2",
Bhalchandra Gajareda9d2dc2013-03-06 16:06:57 -0800819 .platform_name = "msm-pcm-dsp.0",
Bhalchandra Gajare5baa95b2012-12-18 15:42:48 -0800820 .dynamic = 1,
821 .codec_dai_name = "snd-soc-dummy-dai",
822 .codec_name = "snd-soc-dummy",
823 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
824 SND_SOC_DPCM_TRIGGER_POST},
825 .ignore_suspend = 1,
826 /* This dainlink has playback support */
827 .ignore_pmdown_time = 1,
828 .be_id = MSM_FRONTEND_DAI_MULTIMEDIA2,
829 },
830 {
831 .name = "Circuit-Switch Voice",
832 .stream_name = "CS-Voice",
833 .cpu_dai_name = "CS-VOICE",
834 .platform_name = "msm-pcm-voice",
835 .dynamic = 1,
836 .codec_dai_name = "snd-soc-dummy-dai",
837 .codec_name = "snd-soc-dummy",
838 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
839 SND_SOC_DPCM_TRIGGER_POST},
840 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
841 .ignore_suspend = 1,
842 /* this dainlink has playback support */
843 .ignore_pmdown_time = 1,
844 .be_id = MSM_FRONTEND_DAI_CS_VOICE,
845 },
846 {
847 .name = "MSM VoIP",
848 .stream_name = "VoIP",
849 .cpu_dai_name = "VoIP",
850 .platform_name = "msm-voip-dsp",
851 .dynamic = 1,
852 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
853 SND_SOC_DPCM_TRIGGER_POST},
854 .codec_dai_name = "snd-soc-dummy-dai",
855 .codec_name = "snd-soc-dummy",
856 .ignore_suspend = 1,
857 /* this dainlink has playback support */
858 .ignore_pmdown_time = 1,
859 .be_id = MSM_FRONTEND_DAI_VOIP,
860 },
861 {
862 .name = "MSM8226 LPA",
863 .stream_name = "LPA",
864 .cpu_dai_name = "MultiMedia3",
865 .platform_name = "msm-pcm-lpa",
866 .dynamic = 1,
867 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
868 SND_SOC_DPCM_TRIGGER_POST},
869 .codec_dai_name = "snd-soc-dummy-dai",
870 .codec_name = "snd-soc-dummy",
871 .ignore_suspend = 1,
872 /* this dainlink has playback support */
873 .ignore_pmdown_time = 1,
874 .be_id = MSM_FRONTEND_DAI_MULTIMEDIA3,
875 },
876 /* Hostless PCM purpose */
877 {
878 .name = "SLIMBUS_0 Hostless",
879 .stream_name = "SLIMBUS_0 Hostless",
880 .cpu_dai_name = "SLIMBUS0_HOSTLESS",
881 .platform_name = "msm-pcm-hostless",
882 .dynamic = 1,
883 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
884 SND_SOC_DPCM_TRIGGER_POST},
885 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
886 .ignore_suspend = 1,
887 .ignore_pmdown_time = 1, /* dai link has playback support */
888 .codec_dai_name = "snd-soc-dummy-dai",
889 .codec_name = "snd-soc-dummy",
890 },
891 {
892 .name = "INT_FM Hostless",
893 .stream_name = "INT_FM Hostless",
894 .cpu_dai_name = "INT_FM_HOSTLESS",
895 .platform_name = "msm-pcm-hostless",
896 .dynamic = 1,
897 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
898 SND_SOC_DPCM_TRIGGER_POST},
899 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
900 .ignore_suspend = 1,
901 /* this dainlink has playback support */
902 .ignore_pmdown_time = 1,
903 .codec_dai_name = "snd-soc-dummy-dai",
904 .codec_name = "snd-soc-dummy",
905 },
906 {
907 .name = "MSM AFE-PCM RX",
908 .stream_name = "AFE-PROXY RX",
909 .cpu_dai_name = "msm-dai-q6-dev.241",
910 .codec_name = "msm-stub-codec.1",
911 .codec_dai_name = "msm-stub-rx",
912 .platform_name = "msm-pcm-afe",
913 .ignore_suspend = 1,
914 /* this dainlink has playback support */
915 .ignore_pmdown_time = 1,
916 },
917 {
918 .name = "MSM AFE-PCM TX",
919 .stream_name = "AFE-PROXY TX",
920 .cpu_dai_name = "msm-dai-q6-dev.240",
921 .codec_name = "msm-stub-codec.1",
922 .codec_dai_name = "msm-stub-tx",
923 .platform_name = "msm-pcm-afe",
924 .ignore_suspend = 1,
925 },
926 {
927 .name = "MSM8226 Compr",
928 .stream_name = "COMPR",
929 .cpu_dai_name = "MultiMedia4",
930 .platform_name = "msm-compr-dsp",
931 .dynamic = 1,
932 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
933 SND_SOC_DPCM_TRIGGER_POST},
934 .codec_dai_name = "snd-soc-dummy-dai",
935 .codec_name = "snd-soc-dummy",
936 .ignore_suspend = 1,
937 .ignore_pmdown_time = 1,
938 /* this dainlink has playback support */
939 .be_id = MSM_FRONTEND_DAI_MULTIMEDIA4,
940 },
941 {
942 .name = "AUXPCM Hostless",
943 .stream_name = "AUXPCM Hostless",
944 .cpu_dai_name = "AUXPCM_HOSTLESS",
945 .platform_name = "msm-pcm-hostless",
946 .dynamic = 1,
947 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
948 SND_SOC_DPCM_TRIGGER_POST},
949 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
950 .ignore_suspend = 1,
951 /* this dainlink has playback support */
952 .ignore_pmdown_time = 1,
953 .codec_dai_name = "snd-soc-dummy-dai",
954 .codec_name = "snd-soc-dummy",
955 },
956 {
957 .name = "SLIMBUS_1 Hostless",
958 .stream_name = "SLIMBUS_1 Hostless",
959 .cpu_dai_name = "SLIMBUS1_HOSTLESS",
960 .platform_name = "msm-pcm-hostless",
961 .dynamic = 1,
962 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
963 SND_SOC_DPCM_TRIGGER_POST},
964 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
965 .ignore_suspend = 1,
966 .ignore_pmdown_time = 1, /* dai link has playback support */
967 .codec_dai_name = "snd-soc-dummy-dai",
968 .codec_name = "snd-soc-dummy",
969 },
970 {
971 .name = "SLIMBUS_3 Hostless",
972 .stream_name = "SLIMBUS_3 Hostless",
973 .cpu_dai_name = "SLIMBUS3_HOSTLESS",
974 .platform_name = "msm-pcm-hostless",
975 .dynamic = 1,
976 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
977 SND_SOC_DPCM_TRIGGER_POST},
978 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
979 .ignore_suspend = 1,
980 .ignore_pmdown_time = 1, /* dai link has playback support */
981 .codec_dai_name = "snd-soc-dummy-dai",
982 .codec_name = "snd-soc-dummy",
983 },
984 {
985 .name = "SLIMBUS_4 Hostless",
986 .stream_name = "SLIMBUS_4 Hostless",
987 .cpu_dai_name = "SLIMBUS4_HOSTLESS",
988 .platform_name = "msm-pcm-hostless",
989 .dynamic = 1,
990 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
991 SND_SOC_DPCM_TRIGGER_POST},
992 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
993 .ignore_suspend = 1,
994 .ignore_pmdown_time = 1, /* dai link has playback support */
995 .codec_dai_name = "snd-soc-dummy-dai",
996 .codec_name = "snd-soc-dummy",
997 },
Bhalchandra Gajareda9d2dc2013-03-06 16:06:57 -0800998 {
Helen Zeng13d4aff2013-03-21 18:52:56 -0700999 .name = "Voice2",
1000 .stream_name = "Voice2",
1001 .cpu_dai_name = "Voice2",
Bhalchandra Gajareda9d2dc2013-03-06 16:06:57 -08001002 .platform_name = "msm-pcm-voice",
1003 .dynamic = 1,
1004 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
Helen Zeng13d4aff2013-03-21 18:52:56 -07001005 SND_SOC_DPCM_TRIGGER_POST},
Bhalchandra Gajareda9d2dc2013-03-06 16:06:57 -08001006 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
1007 .ignore_suspend = 1,
1008 /* this dainlink has playback support */
1009 .ignore_pmdown_time = 1,
1010 .codec_dai_name = "snd-soc-dummy-dai",
1011 .codec_name = "snd-soc-dummy",
Bhalchandra Gajareda9d2dc2013-03-06 16:06:57 -08001012 },
Bhalchandra Gajaredcf6a162013-03-11 18:39:39 -07001013 {
1014 .name = "MSM8226 LowLatency",
1015 .stream_name = "MultiMedia5",
1016 .cpu_dai_name = "MultiMedia5",
1017 .platform_name = "msm-pcm-dsp.1",
1018 .dynamic = 1,
1019 .codec_dai_name = "snd-soc-dummy-dai",
1020 .codec_name = "snd-soc-dummy",
1021 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
1022 SND_SOC_DPCM_TRIGGER_POST},
1023 .ignore_suspend = 1,
1024 /* this dainlink has playback support */
1025 .ignore_pmdown_time = 1,
1026 .be_id = MSM_FRONTEND_DAI_MULTIMEDIA5,
1027 },
Bhalchandra Gajare5baa95b2012-12-18 15:42:48 -08001028 /* Backend BT/FM DAI Links */
1029 {
1030 .name = LPASS_BE_INT_BT_SCO_RX,
1031 .stream_name = "Internal BT-SCO Playback",
1032 .cpu_dai_name = "msm-dai-q6-dev.12288",
1033 .platform_name = "msm-pcm-routing",
1034 .codec_name = "msm-stub-codec.1",
1035 .codec_dai_name = "msm-stub-rx",
1036 .no_pcm = 1,
1037 .be_id = MSM_BACKEND_DAI_INT_BT_SCO_RX,
1038 .be_hw_params_fixup = msm_btsco_be_hw_params_fixup,
1039 /* this dainlink has playback support */
1040 .ignore_pmdown_time = 1,
Bhalchandra Gajareda9d2dc2013-03-06 16:06:57 -08001041 .ignore_suspend = 1,
Bhalchandra Gajare5baa95b2012-12-18 15:42:48 -08001042 },
1043 {
1044 .name = LPASS_BE_INT_BT_SCO_TX,
1045 .stream_name = "Internal BT-SCO Capture",
1046 .cpu_dai_name = "msm-dai-q6-dev.12289",
1047 .platform_name = "msm-pcm-routing",
1048 .codec_name = "msm-stub-codec.1",
1049 .codec_dai_name = "msm-stub-tx",
1050 .no_pcm = 1,
1051 .be_id = MSM_BACKEND_DAI_INT_BT_SCO_TX,
1052 .be_hw_params_fixup = msm_btsco_be_hw_params_fixup,
Bhalchandra Gajareda9d2dc2013-03-06 16:06:57 -08001053 .ignore_suspend = 1,
Bhalchandra Gajare5baa95b2012-12-18 15:42:48 -08001054 },
1055 {
1056 .name = LPASS_BE_INT_FM_RX,
1057 .stream_name = "Internal FM Playback",
1058 .cpu_dai_name = "msm-dai-q6-dev.12292",
1059 .platform_name = "msm-pcm-routing",
1060 .codec_name = "msm-stub-codec.1",
1061 .codec_dai_name = "msm-stub-rx",
1062 .no_pcm = 1,
1063 .be_id = MSM_BACKEND_DAI_INT_FM_RX,
1064 .be_hw_params_fixup = msm_be_hw_params_fixup,
1065 /* this dainlink has playback support */
1066 .ignore_pmdown_time = 1,
Bhalchandra Gajareda9d2dc2013-03-06 16:06:57 -08001067 .ignore_suspend = 1,
Bhalchandra Gajare5baa95b2012-12-18 15:42:48 -08001068 },
1069 {
1070 .name = LPASS_BE_INT_FM_TX,
1071 .stream_name = "Internal FM Capture",
1072 .cpu_dai_name = "msm-dai-q6-dev.12293",
1073 .platform_name = "msm-pcm-routing",
1074 .codec_name = "msm-stub-codec.1",
1075 .codec_dai_name = "msm-stub-tx",
1076 .no_pcm = 1,
1077 .be_id = MSM_BACKEND_DAI_INT_FM_TX,
1078 .be_hw_params_fixup = msm_be_hw_params_fixup,
Bhalchandra Gajareda9d2dc2013-03-06 16:06:57 -08001079 .ignore_suspend = 1,
Bhalchandra Gajare5baa95b2012-12-18 15:42:48 -08001080 },
1081 /* Backend AFE DAI Links */
1082 {
1083 .name = LPASS_BE_AFE_PCM_RX,
1084 .stream_name = "AFE Playback",
1085 .cpu_dai_name = "msm-dai-q6-dev.224",
1086 .platform_name = "msm-pcm-routing",
1087 .codec_name = "msm-stub-codec.1",
1088 .codec_dai_name = "msm-stub-rx",
1089 .no_pcm = 1,
1090 .be_id = MSM_BACKEND_DAI_AFE_PCM_RX,
Krishnankutty Kolathappilly80bf6d42013-06-06 17:54:40 -07001091 .be_hw_params_fixup = msm_proxy_rx_be_hw_params_fixup,
Bhalchandra Gajare5baa95b2012-12-18 15:42:48 -08001092 /* this dainlink has playback support */
1093 .ignore_pmdown_time = 1,
Bhalchandra Gajareda9d2dc2013-03-06 16:06:57 -08001094 .ignore_suspend = 1,
Bhalchandra Gajare5baa95b2012-12-18 15:42:48 -08001095 },
1096 {
1097 .name = LPASS_BE_AFE_PCM_TX,
1098 .stream_name = "AFE Capture",
1099 .cpu_dai_name = "msm-dai-q6-dev.225",
1100 .platform_name = "msm-pcm-routing",
1101 .codec_name = "msm-stub-codec.1",
1102 .codec_dai_name = "msm-stub-tx",
1103 .no_pcm = 1,
1104 .be_id = MSM_BACKEND_DAI_AFE_PCM_TX,
Krishnankutty Kolathappilly80bf6d42013-06-06 17:54:40 -07001105 .be_hw_params_fixup = msm_proxy_tx_be_hw_params_fixup,
Bhalchandra Gajareda9d2dc2013-03-06 16:06:57 -08001106 .ignore_suspend = 1,
Bhalchandra Gajare5baa95b2012-12-18 15:42:48 -08001107 },
1108 /* HDMI Hostless */
1109 {
1110 .name = "HDMI_RX_HOSTLESS",
1111 .stream_name = "HDMI_RX_HOSTLESS",
1112 .cpu_dai_name = "HDMI_HOSTLESS",
1113 .platform_name = "msm-pcm-hostless",
1114 .dynamic = 1,
1115 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
1116 SND_SOC_DPCM_TRIGGER_POST},
1117 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
1118 .ignore_suspend = 1,
1119 .ignore_pmdown_time = 1,
1120 .codec_dai_name = "snd-soc-dummy-dai",
1121 .codec_name = "snd-soc-dummy",
1122 },
Banajit Goswami25715c52013-05-10 11:45:47 -07001123 /* AUX PCM Backend DAI Links */
1124 {
1125 .name = LPASS_BE_AUXPCM_RX,
1126 .stream_name = "AUX PCM Playback",
1127 .cpu_dai_name = "msm-dai-q6.4106",
1128 .platform_name = "msm-pcm-routing",
1129 .codec_name = "msm-stub-codec.1",
1130 .codec_dai_name = "msm-stub-rx",
1131 .no_pcm = 1,
1132 .be_id = MSM_BACKEND_DAI_AUXPCM_RX,
1133 .be_hw_params_fixup = msm_auxpcm_be_params_fixup,
1134 .ops = &msm_auxpcm_be_ops,
1135 .ignore_pmdown_time = 1,
1136 .ignore_suspend = 1
1137 /* this dainlink has playback support */
1138 },
1139 {
1140 .name = LPASS_BE_AUXPCM_TX,
1141 .stream_name = "AUX PCM Capture",
1142 .cpu_dai_name = "msm-dai-q6.4107",
1143 .platform_name = "msm-pcm-routing",
1144 .codec_name = "msm-stub-codec.1",
1145 .codec_dai_name = "msm-stub-tx",
1146 .no_pcm = 1,
1147 .be_id = MSM_BACKEND_DAI_AUXPCM_TX,
1148 .be_hw_params_fixup = msm_auxpcm_be_params_fixup,
1149 .ops = &msm_auxpcm_be_ops,
1150 .ignore_suspend = 1
1151 },
Bhalchandra Gajare5baa95b2012-12-18 15:42:48 -08001152 /* Backend DAI Links */
1153 {
1154 .name = LPASS_BE_SLIMBUS_0_RX,
1155 .stream_name = "Slimbus Playback",
1156 .cpu_dai_name = "msm-dai-q6-dev.16384",
1157 .platform_name = "msm-pcm-routing",
1158 .codec_name = "tapan_codec",
1159 .codec_dai_name = "tapan_rx1",
1160 .no_pcm = 1,
1161 .be_id = MSM_BACKEND_DAI_SLIMBUS_0_RX,
1162 .init = &msm_audrx_init,
1163 .be_hw_params_fixup = msm_slim_0_rx_be_hw_params_fixup,
1164 .ops = &msm8226_be_ops,
1165 .ignore_pmdown_time = 1, /* dai link has playback support */
Bhalchandra Gajareda9d2dc2013-03-06 16:06:57 -08001166 .ignore_suspend = 1,
Bhalchandra Gajare5baa95b2012-12-18 15:42:48 -08001167 },
1168 {
1169 .name = LPASS_BE_SLIMBUS_0_TX,
1170 .stream_name = "Slimbus Capture",
1171 .cpu_dai_name = "msm-dai-q6-dev.16385",
1172 .platform_name = "msm-pcm-routing",
1173 .codec_name = "tapan_codec",
1174 .codec_dai_name = "tapan_tx1",
1175 .no_pcm = 1,
1176 .be_id = MSM_BACKEND_DAI_SLIMBUS_0_TX,
1177 .be_hw_params_fixup = msm_slim_0_tx_be_hw_params_fixup,
1178 .ops = &msm8226_be_ops,
Bhalchandra Gajareda9d2dc2013-03-06 16:06:57 -08001179 .ignore_suspend = 1,
Bhalchandra Gajare5baa95b2012-12-18 15:42:48 -08001180 },
1181 {
1182 .name = LPASS_BE_SLIMBUS_1_RX,
1183 .stream_name = "Slimbus1 Playback",
1184 .cpu_dai_name = "msm-dai-q6-dev.16386",
1185 .platform_name = "msm-pcm-routing",
1186 .codec_name = "tapan_codec",
1187 .codec_dai_name = "tapan_rx1",
1188 .no_pcm = 1,
1189 .be_id = MSM_BACKEND_DAI_SLIMBUS_1_RX,
1190 .be_hw_params_fixup = msm_slim_0_rx_be_hw_params_fixup,
1191 .ops = &msm8226_be_ops,
1192 /* dai link has playback support */
1193 .ignore_pmdown_time = 1,
Bhalchandra Gajareda9d2dc2013-03-06 16:06:57 -08001194 .ignore_suspend = 1,
Bhalchandra Gajare5baa95b2012-12-18 15:42:48 -08001195 },
1196 {
1197 .name = LPASS_BE_SLIMBUS_1_TX,
1198 .stream_name = "Slimbus1 Capture",
1199 .cpu_dai_name = "msm-dai-q6-dev.16387",
1200 .platform_name = "msm-pcm-routing",
1201 .codec_name = "tapan_codec",
1202 .codec_dai_name = "tapan_tx1",
1203 .no_pcm = 1,
1204 .be_id = MSM_BACKEND_DAI_SLIMBUS_1_TX,
1205 .be_hw_params_fixup = msm_slim_0_tx_be_hw_params_fixup,
1206 .ops = &msm8226_be_ops,
Bhalchandra Gajareda9d2dc2013-03-06 16:06:57 -08001207 .ignore_suspend = 1,
Bhalchandra Gajare5baa95b2012-12-18 15:42:48 -08001208 },
1209 {
1210 .name = LPASS_BE_SLIMBUS_3_RX,
1211 .stream_name = "Slimbus3 Playback",
1212 .cpu_dai_name = "msm-dai-q6-dev.16390",
1213 .platform_name = "msm-pcm-routing",
1214 .codec_name = "tapan_codec",
1215 .codec_dai_name = "tapan_rx1",
1216 .no_pcm = 1,
1217 .be_id = MSM_BACKEND_DAI_SLIMBUS_3_RX,
1218 .be_hw_params_fixup = msm_slim_0_rx_be_hw_params_fixup,
1219 .ops = &msm8226_be_ops,
1220 /* dai link has playback support */
1221 .ignore_pmdown_time = 1,
Bhalchandra Gajareda9d2dc2013-03-06 16:06:57 -08001222 .ignore_suspend = 1,
Bhalchandra Gajare5baa95b2012-12-18 15:42:48 -08001223 },
1224 {
1225 .name = LPASS_BE_SLIMBUS_3_TX,
1226 .stream_name = "Slimbus3 Capture",
1227 .cpu_dai_name = "msm-dai-q6-dev.16391",
1228 .platform_name = "msm-pcm-routing",
1229 .codec_name = "tapan_codec",
1230 .codec_dai_name = "tapan_tx1",
1231 .no_pcm = 1,
1232 .be_id = MSM_BACKEND_DAI_SLIMBUS_3_TX,
1233 .be_hw_params_fixup = msm_slim_0_tx_be_hw_params_fixup,
1234 .ops = &msm8226_be_ops,
Bhalchandra Gajareda9d2dc2013-03-06 16:06:57 -08001235 .ignore_suspend = 1,
Bhalchandra Gajare5baa95b2012-12-18 15:42:48 -08001236 },
1237 {
1238 .name = LPASS_BE_SLIMBUS_4_RX,
1239 .stream_name = "Slimbus4 Playback",
1240 .cpu_dai_name = "msm-dai-q6-dev.16392",
1241 .platform_name = "msm-pcm-routing",
1242 .codec_name = "tapan_codec",
1243 .codec_dai_name = "tapan_rx1",
1244 .no_pcm = 1,
1245 .be_id = MSM_BACKEND_DAI_SLIMBUS_4_RX,
1246 .be_hw_params_fixup = msm_slim_0_rx_be_hw_params_fixup,
1247 .ops = &msm8226_be_ops,
1248 /* dai link has playback support */
1249 .ignore_pmdown_time = 1,
Bhalchandra Gajareda9d2dc2013-03-06 16:06:57 -08001250 .ignore_suspend = 1,
Bhalchandra Gajare5baa95b2012-12-18 15:42:48 -08001251 },
1252 {
1253 .name = LPASS_BE_SLIMBUS_4_TX,
1254 .stream_name = "Slimbus4 Capture",
1255 .cpu_dai_name = "msm-dai-q6-dev.16393",
1256 .platform_name = "msm-pcm-routing",
1257 .codec_name = "tapan_codec",
1258 .codec_dai_name = "tapan_tx1",
1259 .no_pcm = 1,
1260 .be_id = MSM_BACKEND_DAI_SLIMBUS_4_TX,
1261 .be_hw_params_fixup = msm_slim_0_tx_be_hw_params_fixup,
1262 .ops = &msm8226_be_ops,
Bhalchandra Gajareda9d2dc2013-03-06 16:06:57 -08001263 .ignore_suspend = 1,
Bhalchandra Gajare5baa95b2012-12-18 15:42:48 -08001264 },
Vicky Sehrawatbedb5e02013-03-12 16:47:22 -07001265 /* Incall Record Uplink BACK END DAI Link */
1266 {
1267 .name = LPASS_BE_INCALL_RECORD_TX,
1268 .stream_name = "Voice Uplink Capture",
1269 .cpu_dai_name = "msm-dai-q6-dev.32772",
1270 .platform_name = "msm-pcm-routing",
1271 .codec_name = "msm-stub-codec.1",
1272 .codec_dai_name = "msm-stub-tx",
1273 .no_pcm = 1,
1274 .be_id = MSM_BACKEND_DAI_INCALL_RECORD_TX,
1275 .be_hw_params_fixup = msm_be_hw_params_fixup,
1276 .ignore_suspend = 1,
1277 },
1278 /* Incall Record Downlink BACK END DAI Link */
1279 {
1280 .name = LPASS_BE_INCALL_RECORD_RX,
1281 .stream_name = "Voice Downlink Capture",
1282 .cpu_dai_name = "msm-dai-q6-dev.32771",
1283 .platform_name = "msm-pcm-routing",
1284 .codec_name = "msm-stub-codec.1",
1285 .codec_dai_name = "msm-stub-tx",
1286 .no_pcm = 1,
1287 .be_id = MSM_BACKEND_DAI_INCALL_RECORD_RX,
1288 .be_hw_params_fixup = msm_be_hw_params_fixup,
1289 .ignore_suspend = 1,
1290 },
1291 /* Incall Music BACK END DAI Link */
1292 {
1293 .name = LPASS_BE_VOICE_PLAYBACK_TX,
1294 .stream_name = "Voice Farend Playback",
1295 .cpu_dai_name = "msm-dai-q6-dev.32773",
1296 .platform_name = "msm-pcm-routing",
1297 .codec_name = "msm-stub-codec.1",
1298 .codec_dai_name = "msm-stub-rx",
1299 .no_pcm = 1,
1300 .be_id = MSM_BACKEND_DAI_VOICE_PLAYBACK_TX,
1301 .be_hw_params_fixup = msm_be_hw_params_fixup,
1302 .ignore_suspend = 1,
1303 },
Bhalchandra Gajare5baa95b2012-12-18 15:42:48 -08001304};
1305
1306struct snd_soc_card snd_soc_card_msm8226 = {
1307 .name = "msm8226-tapan-snd-card",
1308 .dai_link = msm8226_dai,
1309 .num_links = ARRAY_SIZE(msm8226_dai),
1310};
1311
Banajit Goswami25715c52013-05-10 11:45:47 -07001312static int msm8226_dtparse_auxpcm(struct platform_device *pdev,
1313 struct msm_auxpcm_ctrl **auxpcm_ctrl,
1314 char *msm_auxpcm_gpio_name[][2])
1315{
1316 int ret = 0;
1317 int i = 0;
1318 struct msm_auxpcm_gpio *pin_data = NULL;
1319 struct msm_auxpcm_ctrl *ctrl;
1320 unsigned int gpio_no[NUM_OF_AUXPCM_GPIOS];
1321 enum of_gpio_flags flags = OF_GPIO_ACTIVE_LOW;
1322 int auxpcm_cnt = 0;
1323
1324 pin_data = devm_kzalloc(&pdev->dev, (ARRAY_SIZE(gpio_no) *
1325 sizeof(struct msm_auxpcm_gpio)),
1326 GFP_KERNEL);
1327 if (!pin_data) {
1328 dev_err(&pdev->dev, "No memory for gpio\n");
1329 ret = -ENOMEM;
1330 goto err;
1331 }
1332
1333 for (i = 0; i < ARRAY_SIZE(gpio_no); i++) {
1334 gpio_no[i] = of_get_named_gpio_flags(pdev->dev.of_node,
1335 msm_auxpcm_gpio_name[i][DT_PARSE_INDEX],
1336 0, &flags);
1337
1338 if (gpio_no[i] > 0) {
1339 pin_data[i].gpio_name =
1340 msm_auxpcm_gpio_name[auxpcm_cnt][GPIO_NAME_INDEX];
1341 pin_data[i].gpio_no = gpio_no[i];
1342 dev_dbg(&pdev->dev, "%s:GPIO gpio[%s] =\n"
1343 "0x%x\n", __func__,
1344 pin_data[i].gpio_name,
1345 pin_data[i].gpio_no);
1346 auxpcm_cnt++;
1347 } else {
1348 dev_err(&pdev->dev, "%s:Invalid AUXPCM GPIO[%s]= %x\n",
1349 __func__,
1350 msm_auxpcm_gpio_name[i][GPIO_NAME_INDEX],
1351 gpio_no[i]);
1352 ret = -ENODEV;
1353 goto err;
1354 }
1355 }
1356
1357 ctrl = devm_kzalloc(&pdev->dev,
1358 sizeof(struct msm_auxpcm_ctrl), GFP_KERNEL);
1359 if (!ctrl) {
1360 dev_err(&pdev->dev, "No memory for gpio\n");
1361 ret = -ENOMEM;
1362 goto err;
1363 }
1364
1365 ctrl->pin_data = pin_data;
1366 ctrl->cnt = auxpcm_cnt;
1367 *auxpcm_ctrl = ctrl;
1368 return ret;
1369
1370err:
1371 if (pin_data)
1372 devm_kfree(&pdev->dev, pin_data);
1373 return ret;
1374}
1375
Bhalchandra Gajare5baa95b2012-12-18 15:42:48 -08001376static int msm8226_prepare_codec_mclk(struct snd_soc_card *card)
1377{
Bhalchandra Gajared5a4ba72013-03-11 16:15:13 -07001378 struct msm8226_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
1379 int ret;
1380 if (pdata->mclk_gpio) {
1381 ret = gpio_request(pdata->mclk_gpio, "TAPAN_CODEC_PMIC_MCLK");
1382 if (ret) {
1383 dev_err(card->dev,
1384 "%s: Failed to request taiko mclk gpio %d\n",
1385 __func__, pdata->mclk_gpio);
1386 return ret;
1387 }
1388 }
Bhalchandra Gajare5baa95b2012-12-18 15:42:48 -08001389 return 0;
1390}
1391
Bhalchandra Gajare6ce3b712013-04-23 17:30:40 -07001392static bool msm8226_swap_gnd_mic(struct snd_soc_codec *codec)
1393{
1394 struct snd_soc_card *card = codec->card;
1395 struct msm8226_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
1396 int value = gpio_get_value_cansleep(pdata->us_euro_gpio);
1397
1398 pr_debug("%s: swap select switch %d to %d\n", __func__, value, !value);
1399 gpio_direction_output(pdata->us_euro_gpio, !value);
1400
1401 return true;
1402}
1403
1404static int msm8226_setup_hs_jack(struct platform_device *pdev,
1405 struct msm8226_asoc_mach_data *pdata)
1406{
1407 int rc;
1408
1409 pdata->us_euro_gpio = of_get_named_gpio(pdev->dev.of_node,
1410 "qcom,cdc-us-euro-gpios", 0);
1411 if (pdata->us_euro_gpio < 0) {
1412 dev_info(&pdev->dev,
1413 "property %s in node %s not found %d\n",
1414 "qcom,cdc-us-euro-gpios", pdev->dev.of_node->full_name,
1415 pdata->us_euro_gpio);
1416 } else {
1417 rc = gpio_request(pdata->us_euro_gpio,
1418 "TAPAN_CODEC_US_EURO_GPIO");
1419 if (rc) {
1420 dev_err(&pdev->dev,
1421 "%s: Failed to request tapan us-euro gpio %d\n",
1422 __func__, pdata->us_euro_gpio);
1423 } else {
1424 mbhc_cfg.swap_gnd_mic = msm8226_swap_gnd_mic;
1425 }
1426 }
1427 return 0;
1428}
1429
Bhalchandra Gajare5baa95b2012-12-18 15:42:48 -08001430static __devinit int msm8226_asoc_machine_probe(struct platform_device *pdev)
1431{
1432 struct snd_soc_card *card = &snd_soc_card_msm8226;
1433 struct msm8226_asoc_mach_data *pdata;
1434 int ret;
Banajit Goswami25715c52013-05-10 11:45:47 -07001435 const char *auxpcm_pri_gpio_set = NULL;
Bhalchandra Gajare5baa95b2012-12-18 15:42:48 -08001436
1437 if (!pdev->dev.of_node) {
1438 dev_err(&pdev->dev, "No platform supplied from device tree\n");
1439 return -EINVAL;
1440 }
1441
1442 pdata = devm_kzalloc(&pdev->dev,
1443 sizeof(struct msm8226_asoc_mach_data), GFP_KERNEL);
1444 if (!pdata) {
1445 dev_err(&pdev->dev, "Can't allocate msm8226_asoc_mach_data\n");
1446 ret = -ENOMEM;
1447 goto err;
1448 }
1449
Banajit Goswami25715c52013-05-10 11:45:47 -07001450 /* Parse AUXPCM info from DT */
1451 ret = msm8226_dtparse_auxpcm(pdev, &pdata->auxpcm_ctrl,
1452 msm_auxpcm_gpio_name);
1453 if (ret) {
1454 dev_err(&pdev->dev,
1455 "%s: Auxpcm pin data parse failed\n", __func__);
1456 goto err;
1457 }
1458
Bhalchandra Gajare5baa95b2012-12-18 15:42:48 -08001459 card->dev = &pdev->dev;
1460 platform_set_drvdata(pdev, card);
1461 snd_soc_card_set_drvdata(card, pdata);
1462
1463 ret = snd_soc_of_parse_card_name(card, "qcom,model");
1464 if (ret)
1465 goto err;
1466
1467 ret = snd_soc_of_parse_audio_routing(card,
1468 "qcom,audio-routing");
1469 if (ret)
1470 goto err;
1471
1472 ret = of_property_read_u32(pdev->dev.of_node,
1473 "qcom,tapan-mclk-clk-freq", &pdata->mclk_freq);
1474 if (ret) {
1475 dev_err(&pdev->dev, "Looking up %s property in node %s failed",
1476 "qcom,tapan-mclk-clk-freq",
1477 pdev->dev.of_node->full_name);
1478 goto err;
1479 }
1480
1481 if (pdata->mclk_freq != 9600000) {
1482 dev_err(&pdev->dev, "unsupported tapan mclk freq %u\n",
1483 pdata->mclk_freq);
1484 ret = -EINVAL;
1485 goto err;
1486 }
1487
Bhalchandra Gajared5a4ba72013-03-11 16:15:13 -07001488 pdata->mclk_gpio = of_get_named_gpio(pdev->dev.of_node,
1489 "qcom,cdc-mclk-gpios", 0);
1490 if (pdata->mclk_gpio < 0) {
1491 dev_err(&pdev->dev,
1492 "Looking up %s property in node %s failed %d\n",
1493 "qcom, cdc-mclk-gpios", pdev->dev.of_node->full_name,
1494 pdata->mclk_gpio);
1495 ret = -ENODEV;
1496 goto err;
1497 }
Bhalchandra Gajare5baa95b2012-12-18 15:42:48 -08001498
Bhalchandra Gajare0eca29d2013-03-14 17:54:53 -07001499 vdd_spkr_gpio = of_get_named_gpio(pdev->dev.of_node,
1500 "qcom,cdc-vdd-spkr-gpios", 0);
1501 if (vdd_spkr_gpio < 0) {
1502 dev_err(&pdev->dev,
1503 "Looking up %s property in node %s failed %d\n",
1504 "qcom, cdc-vdd-spkr-gpios",
1505 pdev->dev.of_node->full_name, vdd_spkr_gpio);
1506 } else {
1507 ret = gpio_request(vdd_spkr_gpio, "TAPAN_CODEC_VDD_SPKR");
1508 if (ret) {
1509 /* GPIO to enable EXT VDD exists, but failed request */
1510 dev_err(card->dev,
1511 "%s: Failed to request tapan vdd spkr gpio %d\n",
1512 __func__, vdd_spkr_gpio);
1513 goto err;
1514 }
1515 }
1516
Phani Kumar Uppalapatief087572013-05-03 11:19:33 -07001517 mbhc_cfg.gpio_level_insert = of_property_read_bool(pdev->dev.of_node,
1518 "qcom,headset-jack-type-NO");
Bhalchandra Gajare6ce3b712013-04-23 17:30:40 -07001519 msm8226_setup_hs_jack(pdev, pdata);
Phani Kumar Uppalapatief087572013-05-03 11:19:33 -07001520
Bhalchandra Gajare5baa95b2012-12-18 15:42:48 -08001521 ret = msm8226_prepare_codec_mclk(card);
1522 if (ret)
Bhalchandra Gajare0eca29d2013-03-14 17:54:53 -07001523 goto err_vdd_spkr;
Bhalchandra Gajare5baa95b2012-12-18 15:42:48 -08001524
1525 ret = snd_soc_register_card(card);
1526 if (ret) {
1527 dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n",
1528 ret);
Bhalchandra Gajare0eca29d2013-03-14 17:54:53 -07001529 goto err_vdd_spkr;
Bhalchandra Gajare5baa95b2012-12-18 15:42:48 -08001530 }
1531 mutex_init(&cdc_mclk_mutex);
1532
Banajit Goswami25715c52013-05-10 11:45:47 -07001533 ret = of_property_read_string(pdev->dev.of_node,
1534 "qcom,prim-auxpcm-gpio-set", &auxpcm_pri_gpio_set);
1535 if (ret) {
1536 dev_err(&pdev->dev, "Looking up %s property in node %s failed",
1537 "qcom,prim-auxpcm-gpio-set",
1538 pdev->dev.of_node->full_name);
1539 goto err_vdd_spkr;
1540 }
1541 if (!strcmp(auxpcm_pri_gpio_set, "prim-gpio-prim")) {
1542 lpaif_pri_muxsel_virt_addr = ioremap(LPAIF_PRI_MODE_MUXSEL, 4);
1543 } else if (!strcmp(auxpcm_pri_gpio_set, "prim-gpio-tert")) {
1544 lpaif_pri_muxsel_virt_addr = ioremap(LPAIF_TER_MODE_MUXSEL, 4);
1545 } else {
1546 dev_err(&pdev->dev, "Invalid value %s for AUXPCM GPIO set\n",
1547 auxpcm_pri_gpio_set);
1548 ret = -EINVAL;
1549 goto err_vdd_spkr;
1550 }
1551 if (lpaif_pri_muxsel_virt_addr == NULL) {
1552 pr_err("%s Pri muxsel virt addr is null\n", __func__);
1553 ret = -EINVAL;
1554 goto err_vdd_spkr;
1555 }
1556
Bhalchandra Gajare5baa95b2012-12-18 15:42:48 -08001557 return 0;
Bhalchandra Gajare0eca29d2013-03-14 17:54:53 -07001558
1559err_vdd_spkr:
1560 if (vdd_spkr_gpio >= 0) {
1561 gpio_free(vdd_spkr_gpio);
1562 vdd_spkr_gpio = -1;
1563 }
1564
Bhalchandra Gajare5baa95b2012-12-18 15:42:48 -08001565err:
Bhalchandra Gajared5a4ba72013-03-11 16:15:13 -07001566 if (pdata->mclk_gpio > 0) {
1567 dev_dbg(&pdev->dev, "%s free gpio %d\n",
1568 __func__, pdata->mclk_gpio);
1569 gpio_free(pdata->mclk_gpio);
1570 pdata->mclk_gpio = 0;
1571 }
Bhalchandra Gajare5baa95b2012-12-18 15:42:48 -08001572 devm_kfree(&pdev->dev, pdata);
1573 return ret;
1574}
1575
1576static int __devexit msm8226_asoc_machine_remove(struct platform_device *pdev)
1577{
1578 struct snd_soc_card *card = platform_get_drvdata(pdev);
Bhalchandra Gajared5a4ba72013-03-11 16:15:13 -07001579 struct msm8226_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
Bhalchandra Gajare5baa95b2012-12-18 15:42:48 -08001580
Bhalchandra Gajared5a4ba72013-03-11 16:15:13 -07001581 gpio_free(pdata->mclk_gpio);
Bhalchandra Gajare0eca29d2013-03-14 17:54:53 -07001582 gpio_free(vdd_spkr_gpio);
Bhalchandra Gajare6ce3b712013-04-23 17:30:40 -07001583 if (pdata->us_euro_gpio > 0)
1584 gpio_free(pdata->us_euro_gpio);
1585
Bhalchandra Gajare0eca29d2013-03-14 17:54:53 -07001586 vdd_spkr_gpio = -1;
Bhalchandra Gajare5baa95b2012-12-18 15:42:48 -08001587 snd_soc_unregister_card(card);
1588
1589 return 0;
1590}
1591
1592static const struct of_device_id msm8226_asoc_machine_of_match[] = {
1593 { .compatible = "qcom,msm8226-audio-tapan", },
1594 {},
1595};
1596
1597static struct platform_driver msm8226_asoc_machine_driver = {
1598 .driver = {
1599 .name = DRV_NAME,
1600 .owner = THIS_MODULE,
1601 .pm = &snd_soc_pm_ops,
1602 .of_match_table = msm8226_asoc_machine_of_match,
1603 },
1604 .probe = msm8226_asoc_machine_probe,
1605 .remove = __devexit_p(msm8226_asoc_machine_remove),
1606};
1607module_platform_driver(msm8226_asoc_machine_driver);
1608
1609MODULE_DESCRIPTION("ALSA SoC msm");
1610MODULE_LICENSE("GPL v2");
1611MODULE_ALIAS("platform:" DRV_NAME);
1612MODULE_DEVICE_TABLE(of, msm8226_asoc_machine_of_match);