blob: 8f0fa32a33dd55cb9b0050b5813e27623324b3c5 [file] [log] [blame]
Joonwoo Park0976d012011-12-22 11:48:18 -08001/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002 *
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>
Kiran Kandidb0a4b02011-08-23 09:32:09 -070014#include <linux/delay.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070015#include <linux/gpio.h>
16#include <linux/mfd/pm8xxx/pm8921.h>
17#include <linux/platform_device.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070018#include <linux/mfd/pm8xxx/pm8921.h>
Joonwoo Park0976d012011-12-22 11:48:18 -080019#include <linux/slab.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070020#include <sound/core.h>
21#include <sound/soc.h>
22#include <sound/soc-dapm.h>
23#include <sound/soc-dsp.h>
24#include <sound/pcm.h>
25#include <sound/jack.h>
Bradley Rubin229c6a52011-07-12 16:18:48 -070026#include <asm/mach-types.h>
Bharath Ramachandramurthyb8e797f2011-11-30 12:08:42 -080027#include <mach/socinfo.h>
Joonwoo Parkd7cf2e92012-03-19 19:38:23 -070028#include <linux/mfd/wcd9xxx/core.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070029#include "msm-pcm-routing.h"
Bhalchandra Gajare0b9d4d52011-10-21 16:17:47 -070030#include "../codecs/wcd9310.h"
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070031
32/* 8960 machine driver */
33
34#define PM8921_GPIO_BASE NR_GPIO_IRQS
Joonwoo Parkd7cf2e92012-03-19 19:38:23 -070035#define PM8921_IRQ_BASE (NR_MSM_IRQS + NR_GPIO_IRQS)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070036#define PM8921_GPIO_PM_TO_SYS(pm_gpio) (pm_gpio - 1 + PM8921_GPIO_BASE)
37
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070038#define MSM8960_SPK_ON 1
39#define MSM8960_SPK_OFF 0
40
41#define msm8960_SLIM_0_RX_MAX_CHANNELS 2
42#define msm8960_SLIM_0_TX_MAX_CHANNELS 4
43
Kuirong Wang054e1832012-05-11 15:43:30 -070044#define SAMPLE_RATE_8KHZ 8000
45#define SAMPLE_RATE_16KHZ 16000
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070046
Kiran Kandi462acea2011-08-31 23:53:14 -070047#define BOTTOM_SPK_AMP_POS 0x1
48#define BOTTOM_SPK_AMP_NEG 0x2
49#define TOP_SPK_AMP_POS 0x4
50#define TOP_SPK_AMP_NEG 0x8
51
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -070052#define GPIO_AUX_PCM_DOUT 63
53#define GPIO_AUX_PCM_DIN 64
54#define GPIO_AUX_PCM_SYNC 65
55#define GPIO_AUX_PCM_CLK 66
56
Joonwoo Park0976d012011-12-22 11:48:18 -080057#define TABLA_EXT_CLK_RATE 12288000
58
Joonwoo Park6b9b03f2012-01-23 18:48:54 -080059#define TABLA_MBHC_DEF_BUTTONS 8
Joonwoo Park0976d012011-12-22 11:48:18 -080060#define TABLA_MBHC_DEF_RLOADS 5
61
Joonwoo Parkd7cf2e92012-03-19 19:38:23 -070062#define JACK_DETECT_GPIO 38
63#define JACK_DETECT_INT PM8921_GPIO_IRQ(PM8921_IRQ_BASE, JACK_DETECT_GPIO)
Joonwoo Park2cc13f02012-05-09 12:44:25 -070064#define JACK_US_EURO_SEL_GPIO 35
Joonwoo Parkd7cf2e92012-03-19 19:38:23 -070065
Harmandeep Singh0dd82412011-11-11 09:46:17 -080066static u32 top_spk_pamp_gpio = PM8921_GPIO_PM_TO_SYS(18);
67static u32 bottom_spk_pamp_gpio = PM8921_GPIO_PM_TO_SYS(19);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070068static int msm8960_spk_control;
Kiran Kandi462acea2011-08-31 23:53:14 -070069static int msm8960_ext_bottom_spk_pamp;
70static int msm8960_ext_top_spk_pamp;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070071static int msm8960_slim_0_rx_ch = 1;
72static int msm8960_slim_0_tx_ch = 1;
73
Kuirong Wang054e1832012-05-11 15:43:30 -070074static int msm8960_btsco_rate = SAMPLE_RATE_8KHZ;
Jayasena Sangaraboina47c08242011-08-10 11:30:57 -070075static int msm8960_btsco_ch = 1;
76
Kuirong Wang054e1832012-05-11 15:43:30 -070077static int msm8960_auxpcm_rate = SAMPLE_RATE_8KHZ;
78
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070079static struct clk *codec_clk;
80static int clk_users;
81
82static int msm8960_headset_gpios_configured;
83
84static struct snd_soc_jack hs_jack;
Bradley Rubincb1e2732011-06-23 16:49:20 -070085static struct snd_soc_jack button_jack;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070086
Joonwoo Park9115ade2012-04-18 13:14:10 -070087static bool hs_detect_use_gpio;
88module_param(hs_detect_use_gpio, bool, 0444);
89MODULE_PARM_DESC(hs_detect_use_gpio, "Use GPIO for headset detection");
90
91static bool hs_detect_use_firmware;
92module_param(hs_detect_use_firmware, bool, 0444);
93MODULE_PARM_DESC(hs_detect_use_firmware, "Use firmware for headset detection");
94
Joonwoo Parkd7cf2e92012-03-19 19:38:23 -070095static int msm8960_enable_codec_ext_clk(struct snd_soc_codec *codec, int enable,
96 bool dapm);
Joonwoo Park2cc13f02012-05-09 12:44:25 -070097static bool msm8960_swap_gnd_mic(struct snd_soc_codec *codec);
Joonwoo Parkd7cf2e92012-03-19 19:38:23 -070098
99static struct tabla_mbhc_config mbhc_cfg = {
100 .headset_jack = &hs_jack,
101 .button_jack = &button_jack,
102 .read_fw_bin = false,
103 .calibration = NULL,
104 .micbias = TABLA_MICBIAS2,
105 .mclk_cb_fn = msm8960_enable_codec_ext_clk,
106 .mclk_rate = TABLA_EXT_CLK_RATE,
107 .gpio = 0,
108 .gpio_irq = 0,
109 .gpio_level_insert = 1,
Joonwoo Park2cc13f02012-05-09 12:44:25 -0700110 .swap_gnd_mic = NULL,
Joonwoo Parkd7cf2e92012-03-19 19:38:23 -0700111};
Joonwoo Park0976d012011-12-22 11:48:18 -0800112
Joonwoo Park2cc13f02012-05-09 12:44:25 -0700113static u32 us_euro_sel_gpio = PM8921_GPIO_PM_TO_SYS(JACK_US_EURO_SEL_GPIO);
114
Joonwoo Park28f49c82012-03-16 12:29:21 -0700115static struct mutex cdc_mclk_mutex;
116
Kiran Kandi462acea2011-08-31 23:53:14 -0700117static void msm8960_enable_ext_spk_amp_gpio(u32 spk_amp_gpio)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700118{
119 int ret = 0;
120
121 struct pm_gpio param = {
122 .direction = PM_GPIO_DIR_OUT,
123 .output_buffer = PM_GPIO_OUT_BUF_CMOS,
124 .output_value = 1,
125 .pull = PM_GPIO_PULL_NO,
126 .vin_sel = PM_GPIO_VIN_S4,
127 .out_strength = PM_GPIO_STRENGTH_MED,
Kiran Kandi462acea2011-08-31 23:53:14 -0700128 .
129 function = PM_GPIO_FUNC_NORMAL,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700130 };
131
Harmandeep Singh0dd82412011-11-11 09:46:17 -0800132 if (spk_amp_gpio == bottom_spk_pamp_gpio) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700133
Harmandeep Singh0dd82412011-11-11 09:46:17 -0800134 ret = gpio_request(bottom_spk_pamp_gpio, "BOTTOM_SPK_AMP");
Kiran Kandi462acea2011-08-31 23:53:14 -0700135 if (ret) {
136 pr_err("%s: Error requesting BOTTOM SPK AMP GPIO %u\n",
Harmandeep Singh0dd82412011-11-11 09:46:17 -0800137 __func__, bottom_spk_pamp_gpio);
Kiran Kandi462acea2011-08-31 23:53:14 -0700138 return;
139 }
Harmandeep Singh0dd82412011-11-11 09:46:17 -0800140 ret = pm8xxx_gpio_config(bottom_spk_pamp_gpio, &param);
Kiran Kandi462acea2011-08-31 23:53:14 -0700141 if (ret)
142 pr_err("%s: Failed to configure Bottom Spk Ampl"
Harmandeep Singh0dd82412011-11-11 09:46:17 -0800143 " gpio %u\n", __func__, bottom_spk_pamp_gpio);
Kiran Kandi462acea2011-08-31 23:53:14 -0700144 else {
145 pr_debug("%s: enable Bottom spkr amp gpio\n", __func__);
Harmandeep Singh0dd82412011-11-11 09:46:17 -0800146 gpio_direction_output(bottom_spk_pamp_gpio, 1);
Kiran Kandi462acea2011-08-31 23:53:14 -0700147 }
148
Harmandeep Singh0dd82412011-11-11 09:46:17 -0800149 } else if (spk_amp_gpio == top_spk_pamp_gpio) {
Kiran Kandi462acea2011-08-31 23:53:14 -0700150
Harmandeep Singh0dd82412011-11-11 09:46:17 -0800151 ret = gpio_request(top_spk_pamp_gpio, "TOP_SPK_AMP");
Kiran Kandidb0a4b02011-08-23 09:32:09 -0700152 if (ret) {
153 pr_err("%s: Error requesting GPIO %d\n", __func__,
Harmandeep Singh0dd82412011-11-11 09:46:17 -0800154 top_spk_pamp_gpio);
Kiran Kandidb0a4b02011-08-23 09:32:09 -0700155 return;
156 }
Harmandeep Singh0dd82412011-11-11 09:46:17 -0800157 ret = pm8xxx_gpio_config(top_spk_pamp_gpio, &param);
Kiran Kandidb0a4b02011-08-23 09:32:09 -0700158 if (ret)
Kiran Kandi462acea2011-08-31 23:53:14 -0700159 pr_err("%s: Failed to configure Top Spk Ampl"
Harmandeep Singh0dd82412011-11-11 09:46:17 -0800160 " gpio %u\n", __func__, top_spk_pamp_gpio);
Kiran Kandidb0a4b02011-08-23 09:32:09 -0700161 else {
Kiran Kandi462acea2011-08-31 23:53:14 -0700162 pr_debug("%s: enable Top spkr amp gpio\n", __func__);
Harmandeep Singh0dd82412011-11-11 09:46:17 -0800163 gpio_direction_output(top_spk_pamp_gpio, 1);
Kiran Kandidb0a4b02011-08-23 09:32:09 -0700164 }
Kiran Kandidb0a4b02011-08-23 09:32:09 -0700165 } else {
Kiran Kandi462acea2011-08-31 23:53:14 -0700166 pr_err("%s: ERROR : Invalid External Speaker Ampl GPIO."
167 " gpio = %u\n", __func__, spk_amp_gpio);
168 return;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700169 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700170}
Kiran Kandidb0a4b02011-08-23 09:32:09 -0700171
Kiran Kandi462acea2011-08-31 23:53:14 -0700172static void msm8960_ext_spk_power_amp_on(u32 spk)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700173{
Kiran Kandi462acea2011-08-31 23:53:14 -0700174 if (spk & (BOTTOM_SPK_AMP_POS | BOTTOM_SPK_AMP_NEG)) {
175
176 if ((msm8960_ext_bottom_spk_pamp & BOTTOM_SPK_AMP_POS) &&
177 (msm8960_ext_bottom_spk_pamp & BOTTOM_SPK_AMP_NEG)) {
178
179 pr_debug("%s() External Bottom Speaker Ampl already "
180 "turned on. spk = 0x%08x\n", __func__, spk);
Kiran Kandidb0a4b02011-08-23 09:32:09 -0700181 return;
Kiran Kandi462acea2011-08-31 23:53:14 -0700182 }
183
184 msm8960_ext_bottom_spk_pamp |= spk;
185
186 if ((msm8960_ext_bottom_spk_pamp & BOTTOM_SPK_AMP_POS) &&
187 (msm8960_ext_bottom_spk_pamp & BOTTOM_SPK_AMP_NEG)) {
188
Harmandeep Singh0dd82412011-11-11 09:46:17 -0800189 msm8960_enable_ext_spk_amp_gpio(bottom_spk_pamp_gpio);
Kiran Kandi462acea2011-08-31 23:53:14 -0700190 pr_debug("%s: slepping 4 ms after turning on external "
191 " Bottom Speaker Ampl\n", __func__);
192 usleep_range(4000, 4000);
193 }
194
195 } else if (spk & (TOP_SPK_AMP_POS | TOP_SPK_AMP_NEG)) {
196
197 if ((msm8960_ext_top_spk_pamp & TOP_SPK_AMP_POS) &&
198 (msm8960_ext_top_spk_pamp & TOP_SPK_AMP_NEG)) {
199
200 pr_debug("%s() External Top Speaker Ampl already"
201 "turned on. spk = 0x%08x\n", __func__, spk);
Kiran Kandidb0a4b02011-08-23 09:32:09 -0700202 return;
Kiran Kandi462acea2011-08-31 23:53:14 -0700203 }
204
205 msm8960_ext_top_spk_pamp |= spk;
206
207 if ((msm8960_ext_top_spk_pamp & TOP_SPK_AMP_POS) &&
208 (msm8960_ext_top_spk_pamp & TOP_SPK_AMP_NEG)) {
209
Harmandeep Singh0dd82412011-11-11 09:46:17 -0800210 msm8960_enable_ext_spk_amp_gpio(top_spk_pamp_gpio);
Kiran Kandi462acea2011-08-31 23:53:14 -0700211 pr_debug("%s: sleeping 4 ms after turning on "
212 " external Top Speaker Ampl\n", __func__);
213 usleep_range(4000, 4000);
214 }
215 } else {
216
217 pr_err("%s: ERROR : Invalid External Speaker Ampl. spk = 0x%08x\n",
218 __func__, spk);
219 return;
Kiran Kandidb0a4b02011-08-23 09:32:09 -0700220 }
Kiran Kandi462acea2011-08-31 23:53:14 -0700221}
222
223static void msm8960_ext_spk_power_amp_off(u32 spk)
224{
225 if (spk & (BOTTOM_SPK_AMP_POS | BOTTOM_SPK_AMP_NEG)) {
226
227 if (!msm8960_ext_bottom_spk_pamp)
228 return;
229
Harmandeep Singh0dd82412011-11-11 09:46:17 -0800230 gpio_direction_output(bottom_spk_pamp_gpio, 0);
231 gpio_free(bottom_spk_pamp_gpio);
Kiran Kandi462acea2011-08-31 23:53:14 -0700232 msm8960_ext_bottom_spk_pamp = 0;
233
234 pr_debug("%s: sleeping 4 ms after turning off external Bottom"
235 " Speaker Ampl\n", __func__);
236
237 usleep_range(4000, 4000);
238
239 } else if (spk & (TOP_SPK_AMP_POS | TOP_SPK_AMP_NEG)) {
240
241 if (!msm8960_ext_top_spk_pamp)
242 return;
243
Harmandeep Singh0dd82412011-11-11 09:46:17 -0800244 gpio_direction_output(top_spk_pamp_gpio, 0);
245 gpio_free(top_spk_pamp_gpio);
Kiran Kandi462acea2011-08-31 23:53:14 -0700246 msm8960_ext_top_spk_pamp = 0;
247
248 pr_debug("%s: sleeping 4 ms after turning off external Top"
249 " Spkaker Ampl\n", __func__);
250
251 usleep_range(4000, 4000);
252 } else {
253
254 pr_err("%s: ERROR : Invalid Ext Spk Ampl. spk = 0x%08x\n",
255 __func__, spk);
256 return;
257 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700258}
Kiran Kandidb0a4b02011-08-23 09:32:09 -0700259
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700260static void msm8960_ext_control(struct snd_soc_codec *codec)
261{
262 struct snd_soc_dapm_context *dapm = &codec->dapm;
263
Jayasena Sangaraboina247d36e2012-04-17 10:16:18 -0700264 mutex_lock(&dapm->codec->mutex);
265
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700266 pr_debug("%s: msm8960_spk_control = %d", __func__, msm8960_spk_control);
Peter Lohmannb8203ef2011-10-07 15:05:28 -0700267 if (msm8960_spk_control == MSM8960_SPK_ON) {
268 snd_soc_dapm_enable_pin(dapm, "Ext Spk Bottom Pos");
269 snd_soc_dapm_enable_pin(dapm, "Ext Spk Bottom Neg");
270 snd_soc_dapm_enable_pin(dapm, "Ext Spk Top Pos");
271 snd_soc_dapm_enable_pin(dapm, "Ext Spk Top Neg");
272 } else {
273 snd_soc_dapm_disable_pin(dapm, "Ext Spk Bottom Pos");
274 snd_soc_dapm_disable_pin(dapm, "Ext Spk Bottom Neg");
275 snd_soc_dapm_disable_pin(dapm, "Ext Spk Top Pos");
276 snd_soc_dapm_disable_pin(dapm, "Ext Spk Top Neg");
277 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700278
279 snd_soc_dapm_sync(dapm);
Jayasena Sangaraboina247d36e2012-04-17 10:16:18 -0700280 mutex_unlock(&dapm->codec->mutex);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700281}
282
283static int msm8960_get_spk(struct snd_kcontrol *kcontrol,
284 struct snd_ctl_elem_value *ucontrol)
285{
286 pr_debug("%s: msm8960_spk_control = %d", __func__, msm8960_spk_control);
287 ucontrol->value.integer.value[0] = msm8960_spk_control;
288 return 0;
289}
290static int msm8960_set_spk(struct snd_kcontrol *kcontrol,
291 struct snd_ctl_elem_value *ucontrol)
292{
293 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
294
295 pr_debug("%s()\n", __func__);
296 if (msm8960_spk_control == ucontrol->value.integer.value[0])
297 return 0;
298
299 msm8960_spk_control = ucontrol->value.integer.value[0];
300 msm8960_ext_control(codec);
301 return 1;
302}
303static int msm8960_spkramp_event(struct snd_soc_dapm_widget *w,
304 struct snd_kcontrol *k, int event)
305{
306 pr_debug("%s() %x\n", __func__, SND_SOC_DAPM_EVENT_ON(event));
Kiran Kandidb0a4b02011-08-23 09:32:09 -0700307
308 if (SND_SOC_DAPM_EVENT_ON(event)) {
Kiran Kandi462acea2011-08-31 23:53:14 -0700309 if (!strncmp(w->name, "Ext Spk Bottom Pos", 18))
310 msm8960_ext_spk_power_amp_on(BOTTOM_SPK_AMP_POS);
311 else if (!strncmp(w->name, "Ext Spk Bottom Neg", 18))
312 msm8960_ext_spk_power_amp_on(BOTTOM_SPK_AMP_NEG);
313 else if (!strncmp(w->name, "Ext Spk Top Pos", 15))
314 msm8960_ext_spk_power_amp_on(TOP_SPK_AMP_POS);
315 else if (!strncmp(w->name, "Ext Spk Top Neg", 15))
316 msm8960_ext_spk_power_amp_on(TOP_SPK_AMP_NEG);
317 else {
318 pr_err("%s() Invalid Speaker Widget = %s\n",
319 __func__, w->name);
320 return -EINVAL;
321 }
322
Kiran Kandidb0a4b02011-08-23 09:32:09 -0700323 } else {
Kiran Kandi462acea2011-08-31 23:53:14 -0700324 if (!strncmp(w->name, "Ext Spk Bottom Pos", 18))
325 msm8960_ext_spk_power_amp_off(BOTTOM_SPK_AMP_POS);
326 else if (!strncmp(w->name, "Ext Spk Bottom Neg", 18))
327 msm8960_ext_spk_power_amp_off(BOTTOM_SPK_AMP_NEG);
328 else if (!strncmp(w->name, "Ext Spk Top Pos", 15))
329 msm8960_ext_spk_power_amp_off(TOP_SPK_AMP_POS);
330 else if (!strncmp(w->name, "Ext Spk Top Neg", 15))
331 msm8960_ext_spk_power_amp_off(TOP_SPK_AMP_NEG);
332 else {
333 pr_err("%s() Invalid Speaker Widget = %s\n",
334 __func__, w->name);
335 return -EINVAL;
336 }
Kiran Kandidb0a4b02011-08-23 09:32:09 -0700337 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700338 return 0;
339}
Joonwoo Parkd7cf2e92012-03-19 19:38:23 -0700340
341static int msm8960_enable_codec_ext_clk(struct snd_soc_codec *codec, int enable,
342 bool dapm)
Joonwoo Park0976d012011-12-22 11:48:18 -0800343{
Joonwoo Park28f49c82012-03-16 12:29:21 -0700344 int r = 0;
Joonwoo Park0976d012011-12-22 11:48:18 -0800345 pr_debug("%s: enable = %d\n", __func__, enable);
Joonwoo Park28f49c82012-03-16 12:29:21 -0700346
347 mutex_lock(&cdc_mclk_mutex);
Joonwoo Park0976d012011-12-22 11:48:18 -0800348 if (enable) {
349 clk_users++;
350 pr_debug("%s: clk_users = %d\n", __func__, clk_users);
Joonwoo Park28f49c82012-03-16 12:29:21 -0700351 if (clk_users == 1) {
352 if (codec_clk) {
353 clk_set_rate(codec_clk, TABLA_EXT_CLK_RATE);
Asish Bhattacharya4776d962012-04-25 12:08:09 +0530354 clk_prepare_enable(codec_clk);
Joonwoo Park28f49c82012-03-16 12:29:21 -0700355 tabla_mclk_enable(codec, 1, dapm);
356 } else {
357 pr_err("%s: Error setting Tabla MCLK\n",
358 __func__);
359 clk_users--;
360 r = -EINVAL;
361 }
Joonwoo Park0976d012011-12-22 11:48:18 -0800362 }
363 } else {
Joonwoo Park28f49c82012-03-16 12:29:21 -0700364 if (clk_users > 0) {
365 clk_users--;
366 pr_debug("%s: clk_users = %d\n", __func__, clk_users);
367 if (clk_users == 0) {
368 pr_debug("%s: disabling MCLK. clk_users = %d\n",
Joonwoo Park0976d012011-12-22 11:48:18 -0800369 __func__, clk_users);
Joonwoo Park28f49c82012-03-16 12:29:21 -0700370 tabla_mclk_enable(codec, 0, dapm);
Asish Bhattacharya4776d962012-04-25 12:08:09 +0530371 clk_disable_unprepare(codec_clk);
Joonwoo Park28f49c82012-03-16 12:29:21 -0700372 }
373 } else {
374 pr_err("%s: Error releasing Tabla MCLK\n", __func__);
375 r = -EINVAL;
Joonwoo Park0976d012011-12-22 11:48:18 -0800376 }
377 }
Joonwoo Park28f49c82012-03-16 12:29:21 -0700378 mutex_unlock(&cdc_mclk_mutex);
379 return r;
Joonwoo Park0976d012011-12-22 11:48:18 -0800380}
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700381
Joonwoo Park2cc13f02012-05-09 12:44:25 -0700382static bool msm8960_swap_gnd_mic(struct snd_soc_codec *codec)
383{
384 int value = gpio_get_value_cansleep(us_euro_sel_gpio);
385 pr_debug("%s: US EURO select switch %d to %d\n", __func__, value,
386 !value);
387 gpio_set_value_cansleep(us_euro_sel_gpio, !value);
388 return true;
389}
390
Kiran Kandi6fae8bf2011-08-15 10:36:42 -0700391static int msm8960_mclk_event(struct snd_soc_dapm_widget *w,
392 struct snd_kcontrol *kcontrol, int event)
393{
394 pr_debug("%s: event = %d\n", __func__, event);
395
396 switch (event) {
397 case SND_SOC_DAPM_PRE_PMU:
Joonwoo Parkd7cf2e92012-03-19 19:38:23 -0700398 return msm8960_enable_codec_ext_clk(w->codec, 1, true);
Kiran Kandi6fae8bf2011-08-15 10:36:42 -0700399 case SND_SOC_DAPM_POST_PMD:
Joonwoo Parkd7cf2e92012-03-19 19:38:23 -0700400 return msm8960_enable_codec_ext_clk(w->codec, 0, true);
Kiran Kandi6fae8bf2011-08-15 10:36:42 -0700401 }
402 return 0;
403}
404
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700405static const struct snd_soc_dapm_widget msm8960_dapm_widgets[] = {
Kiran Kandi3a30bda2011-08-15 10:36:42 -0700406
Kiran Kandi6fae8bf2011-08-15 10:36:42 -0700407 SND_SOC_DAPM_SUPPLY("MCLK", SND_SOC_NOPM, 0, 0,
408 msm8960_mclk_event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
409
Kiran Kandi462acea2011-08-31 23:53:14 -0700410 SND_SOC_DAPM_SPK("Ext Spk Bottom Pos", msm8960_spkramp_event),
411 SND_SOC_DAPM_SPK("Ext Spk Bottom Neg", msm8960_spkramp_event),
412
413 SND_SOC_DAPM_SPK("Ext Spk Top Pos", msm8960_spkramp_event),
414 SND_SOC_DAPM_SPK("Ext Spk Top Neg", msm8960_spkramp_event),
Kiran Kandi3a30bda2011-08-15 10:36:42 -0700415
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700416 SND_SOC_DAPM_MIC("Handset Mic", NULL),
417 SND_SOC_DAPM_MIC("Headset Mic", NULL),
418 SND_SOC_DAPM_MIC("Digital Mic1", NULL),
Bhalchandra Gajarecc6ffa02011-07-14 18:35:41 -0700419 SND_SOC_DAPM_MIC("ANCRight Headset Mic", NULL),
420 SND_SOC_DAPM_MIC("ANCLeft Headset Mic", NULL),
Kiran Kandia21d6bc2011-07-17 21:19:59 -0700421
Kiran Kandia21d6bc2011-07-17 21:19:59 -0700422 SND_SOC_DAPM_MIC("Digital Mic1", NULL),
Kiran Kandia21d6bc2011-07-17 21:19:59 -0700423 SND_SOC_DAPM_MIC("Digital Mic2", NULL),
Bhalchandra Gajarea0101ba2011-08-11 20:05:56 -0700424 SND_SOC_DAPM_MIC("Digital Mic3", NULL),
Kiran Kandia21d6bc2011-07-17 21:19:59 -0700425 SND_SOC_DAPM_MIC("Digital Mic4", NULL),
Bhalchandra Gajarea0101ba2011-08-11 20:05:56 -0700426 SND_SOC_DAPM_MIC("Digital Mic5", NULL),
427 SND_SOC_DAPM_MIC("Digital Mic6", NULL),
428
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700429};
430
Bradley Rubin229c6a52011-07-12 16:18:48 -0700431static const struct snd_soc_dapm_route common_audio_map[] = {
Kiran Kandidb0a4b02011-08-23 09:32:09 -0700432
Kiran Kandi6fae8bf2011-08-15 10:36:42 -0700433 {"RX_BIAS", NULL, "MCLK"},
434 {"LDO_H", NULL, "MCLK"},
435
436 /* Speaker path */
Kiran Kandi462acea2011-08-31 23:53:14 -0700437 {"Ext Spk Bottom Pos", NULL, "LINEOUT1"},
438 {"Ext Spk Bottom Neg", NULL, "LINEOUT3"},
Kiran Kandidb0a4b02011-08-23 09:32:09 -0700439
Kiran Kandi462acea2011-08-31 23:53:14 -0700440 {"Ext Spk Top Pos", NULL, "LINEOUT2"},
441 {"Ext Spk Top Neg", NULL, "LINEOUT4"},
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700442
443 /* Microphone path */
Bradley Rubin229c6a52011-07-12 16:18:48 -0700444 {"AMIC1", NULL, "MIC BIAS1 Internal1"},
445 {"MIC BIAS1 Internal1", NULL, "Handset Mic"},
Bhalchandra Gajarecc6ffa02011-07-14 18:35:41 -0700446
447 {"AMIC2", NULL, "MIC BIAS2 External"},
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700448 {"MIC BIAS2 External", NULL, "Headset Mic"},
Bhalchandra Gajarecc6ffa02011-07-14 18:35:41 -0700449
Patrick Laie519dd62011-09-28 12:37:11 -0700450 /**
451 * AMIC3 and AMIC4 inputs are connected to ANC microphones
452 * These mics are biased differently on CDP and FLUID
453 * routing entries below are based on bias arrangement
454 * on FLUID.
455 */
456 {"AMIC3", NULL, "MIC BIAS3 Internal1"},
457 {"MIC BIAS3 Internal1", NULL, "ANCRight Headset Mic"},
458
459 {"AMIC4", NULL, "MIC BIAS1 Internal2"},
460 {"MIC BIAS1 Internal2", NULL, "ANCLeft Headset Mic"},
461
Kiran Kandie9bf86a2011-07-21 16:50:41 -0700462 {"HEADPHONE", NULL, "LDO_H"},
463
Kiran Kandia21d6bc2011-07-17 21:19:59 -0700464 /**
Bhalchandra Gajarea0101ba2011-08-11 20:05:56 -0700465 * The digital Mic routes are setup considering
466 * fluid as default device.
467 */
468
469 /**
Kiran Kandia21d6bc2011-07-17 21:19:59 -0700470 * Digital Mic1. Front Bottom left Digital Mic on Fluid and MTP.
Bhalchandra Gajarea0101ba2011-08-11 20:05:56 -0700471 * Digital Mic GM5 on CDP mainboard.
Kiran Kandia21d6bc2011-07-17 21:19:59 -0700472 * Conncted to DMIC2 Input on Tabla codec.
473 */
474 {"DMIC2", NULL, "MIC BIAS1 External"},
Bhalchandra Gajarecc6ffa02011-07-14 18:35:41 -0700475 {"MIC BIAS1 External", NULL, "Digital Mic1"},
Kiran Kandia21d6bc2011-07-17 21:19:59 -0700476
477 /**
478 * Digital Mic2. Front Bottom right Digital Mic on Fluid and MTP.
Bhalchandra Gajarea0101ba2011-08-11 20:05:56 -0700479 * Digital Mic GM6 on CDP mainboard.
Kiran Kandia21d6bc2011-07-17 21:19:59 -0700480 * Conncted to DMIC1 Input on Tabla codec.
481 */
482 {"DMIC1", NULL, "MIC BIAS1 External"},
483 {"MIC BIAS1 External", NULL, "Digital Mic2"},
484
485 /**
Bhalchandra Gajarea0101ba2011-08-11 20:05:56 -0700486 * Digital Mic3. Back Bottom Digital Mic on Fluid.
487 * Digital Mic GM1 on CDP mainboard.
488 * Conncted to DMIC4 Input on Tabla codec.
489 */
490 {"DMIC4", NULL, "MIC BIAS3 External"},
491 {"MIC BIAS3 External", NULL, "Digital Mic3"},
492
493 /**
Kiran Kandia21d6bc2011-07-17 21:19:59 -0700494 * Digital Mic4. Back top Digital Mic on Fluid.
Bhalchandra Gajarea0101ba2011-08-11 20:05:56 -0700495 * Digital Mic GM2 on CDP mainboard.
Kiran Kandia21d6bc2011-07-17 21:19:59 -0700496 * Conncted to DMIC3 Input on Tabla codec.
497 */
498 {"DMIC3", NULL, "MIC BIAS3 External"},
499 {"MIC BIAS3 External", NULL, "Digital Mic4"},
Bhalchandra Gajarea0101ba2011-08-11 20:05:56 -0700500
501 /**
502 * Digital Mic5. Front top Digital Mic on Fluid.
503 * Digital Mic GM3 on CDP mainboard.
504 * Conncted to DMIC5 Input on Tabla codec.
505 */
506 {"DMIC5", NULL, "MIC BIAS4 External"},
507 {"MIC BIAS4 External", NULL, "Digital Mic5"},
508
Patrick Laicb7802b2011-10-04 12:39:18 -0700509 /* Tabla digital Mic6 - back bottom digital Mic on Liquid and
510 * bottom mic on CDP. FLUID/MTP do not have dmic6 installed.
Bhalchandra Gajarea0101ba2011-08-11 20:05:56 -0700511 */
512 {"DMIC6", NULL, "MIC BIAS4 External"},
513 {"MIC BIAS4 External", NULL, "Digital Mic6"},
Bradley Rubin229c6a52011-07-12 16:18:48 -0700514};
515
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700516static const char *spk_function[] = {"Off", "On"};
Patrick Lai9f4b4292011-07-16 22:11:09 -0700517static const char *slim0_rx_ch_text[] = {"One", "Two"};
518static const char *slim0_tx_ch_text[] = {"One", "Two", "Three", "Four"};
519
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700520static const struct soc_enum msm8960_enum[] = {
521 SOC_ENUM_SINGLE_EXT(2, spk_function),
Patrick Lai9f4b4292011-07-16 22:11:09 -0700522 SOC_ENUM_SINGLE_EXT(2, slim0_rx_ch_text),
523 SOC_ENUM_SINGLE_EXT(4, slim0_tx_ch_text),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700524};
525
Jayasena Sangaraboina47c08242011-08-10 11:30:57 -0700526static const char *btsco_rate_text[] = {"8000", "16000"};
527static const struct soc_enum msm8960_btsco_enum[] = {
528 SOC_ENUM_SINGLE_EXT(2, btsco_rate_text),
529};
530
Kuirong Wang054e1832012-05-11 15:43:30 -0700531static const char *auxpcm_rate_text[] = {"rate_8000", "rate_16000"};
532static const struct soc_enum msm8960_auxpcm_enum[] = {
533 SOC_ENUM_SINGLE_EXT(2, auxpcm_rate_text),
534};
535
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700536static int msm8960_slim_0_rx_ch_get(struct snd_kcontrol *kcontrol,
537 struct snd_ctl_elem_value *ucontrol)
538{
Patrick Lai9f4b4292011-07-16 22:11:09 -0700539 pr_debug("%s: msm8960_slim_0_rx_ch = %d\n", __func__,
Joonwoo Park0976d012011-12-22 11:48:18 -0800540 msm8960_slim_0_rx_ch);
Patrick Lai9f4b4292011-07-16 22:11:09 -0700541 ucontrol->value.integer.value[0] = msm8960_slim_0_rx_ch - 1;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700542 return 0;
543}
544
545static int msm8960_slim_0_rx_ch_put(struct snd_kcontrol *kcontrol,
546 struct snd_ctl_elem_value *ucontrol)
547{
Patrick Lai9f4b4292011-07-16 22:11:09 -0700548 msm8960_slim_0_rx_ch = ucontrol->value.integer.value[0] + 1;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700549
Patrick Lai9f4b4292011-07-16 22:11:09 -0700550 pr_debug("%s: msm8960_slim_0_rx_ch = %d\n", __func__,
Joonwoo Park0976d012011-12-22 11:48:18 -0800551 msm8960_slim_0_rx_ch);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700552 return 1;
553}
554
555static int msm8960_slim_0_tx_ch_get(struct snd_kcontrol *kcontrol,
556 struct snd_ctl_elem_value *ucontrol)
557{
Patrick Lai9f4b4292011-07-16 22:11:09 -0700558 pr_debug("%s: msm8960_slim_0_tx_ch = %d\n", __func__,
Joonwoo Park0976d012011-12-22 11:48:18 -0800559 msm8960_slim_0_tx_ch);
Patrick Lai9f4b4292011-07-16 22:11:09 -0700560 ucontrol->value.integer.value[0] = msm8960_slim_0_tx_ch - 1;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700561 return 0;
562}
563
564static int msm8960_slim_0_tx_ch_put(struct snd_kcontrol *kcontrol,
565 struct snd_ctl_elem_value *ucontrol)
566{
Patrick Lai9f4b4292011-07-16 22:11:09 -0700567 msm8960_slim_0_tx_ch = ucontrol->value.integer.value[0] + 1;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700568
569 pr_debug("%s: msm8960_slim_0_tx_ch = %d\n", __func__,
Joonwoo Park0976d012011-12-22 11:48:18 -0800570 msm8960_slim_0_tx_ch);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700571 return 1;
572}
573
Jayasena Sangaraboina47c08242011-08-10 11:30:57 -0700574static int msm8960_btsco_rate_get(struct snd_kcontrol *kcontrol,
575 struct snd_ctl_elem_value *ucontrol)
576{
Joonwoo Park0976d012011-12-22 11:48:18 -0800577 pr_debug("%s: msm8960_btsco_rate = %d", __func__, msm8960_btsco_rate);
Jayasena Sangaraboina47c08242011-08-10 11:30:57 -0700578 ucontrol->value.integer.value[0] = msm8960_btsco_rate;
579 return 0;
580}
581
582static int msm8960_btsco_rate_put(struct snd_kcontrol *kcontrol,
583 struct snd_ctl_elem_value *ucontrol)
584{
585 switch (ucontrol->value.integer.value[0]) {
586 case 0:
Kuirong Wang054e1832012-05-11 15:43:30 -0700587 msm8960_btsco_rate = SAMPLE_RATE_8KHZ;
Jayasena Sangaraboina47c08242011-08-10 11:30:57 -0700588 break;
589 case 1:
Kuirong Wang054e1832012-05-11 15:43:30 -0700590 msm8960_btsco_rate = SAMPLE_RATE_16KHZ;
Jayasena Sangaraboina47c08242011-08-10 11:30:57 -0700591 break;
592 default:
Kuirong Wang054e1832012-05-11 15:43:30 -0700593 msm8960_btsco_rate = SAMPLE_RATE_8KHZ;
Jayasena Sangaraboina47c08242011-08-10 11:30:57 -0700594 break;
595 }
Joonwoo Park0976d012011-12-22 11:48:18 -0800596 pr_debug("%s: msm8960_btsco_rate = %d\n", __func__, msm8960_btsco_rate);
Jayasena Sangaraboina47c08242011-08-10 11:30:57 -0700597 return 0;
598}
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700599
Kuirong Wang054e1832012-05-11 15:43:30 -0700600static int msm8960_auxpcm_rate_get(struct snd_kcontrol *kcontrol,
601 struct snd_ctl_elem_value *ucontrol)
602{
603 pr_debug("%s: msm8960_auxpcm_rate = %d", __func__,
604 msm8960_auxpcm_rate);
605 ucontrol->value.integer.value[0] = msm8960_auxpcm_rate;
606 return 0;
607}
608
609static int msm8960_auxpcm_rate_put(struct snd_kcontrol *kcontrol,
610 struct snd_ctl_elem_value *ucontrol)
611{
612 switch (ucontrol->value.integer.value[0]) {
613 case 0:
614 msm8960_auxpcm_rate = SAMPLE_RATE_8KHZ;
615 break;
616 case 1:
617 msm8960_auxpcm_rate = SAMPLE_RATE_16KHZ;
618 break;
619 default:
620 msm8960_auxpcm_rate = SAMPLE_RATE_8KHZ;
621 break;
622 }
623 pr_debug("%s: msm8960_auxpcm_rate = %d"
624 "ucontrol->value.integer.value[0] = %d\n", __func__,
625 msm8960_auxpcm_rate,
626 (int)ucontrol->value.integer.value[0]);
627 return 0;
628}
629
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700630static const struct snd_kcontrol_new tabla_msm8960_controls[] = {
631 SOC_ENUM_EXT("Speaker Function", msm8960_enum[0], msm8960_get_spk,
632 msm8960_set_spk),
Patrick Lai9f4b4292011-07-16 22:11:09 -0700633 SOC_ENUM_EXT("SLIM_0_RX Channels", msm8960_enum[1],
634 msm8960_slim_0_rx_ch_get, msm8960_slim_0_rx_ch_put),
635 SOC_ENUM_EXT("SLIM_0_TX Channels", msm8960_enum[2],
636 msm8960_slim_0_tx_ch_get, msm8960_slim_0_tx_ch_put),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700637};
638
Jayasena Sangaraboina47c08242011-08-10 11:30:57 -0700639static const struct snd_kcontrol_new int_btsco_rate_mixer_controls[] = {
640 SOC_ENUM_EXT("Internal BTSCO SampleRate", msm8960_btsco_enum[0],
641 msm8960_btsco_rate_get, msm8960_btsco_rate_put),
642};
643
Kuirong Wang054e1832012-05-11 15:43:30 -0700644static const struct snd_kcontrol_new auxpcm_rate_mixer_controls[] = {
645 SOC_ENUM_EXT("AUX PCM SampleRate", msm8960_auxpcm_enum[0],
646 msm8960_auxpcm_rate_get, msm8960_auxpcm_rate_put),
647};
648
Jayasena Sangaraboina47c08242011-08-10 11:30:57 -0700649static int msm8960_btsco_init(struct snd_soc_pcm_runtime *rtd)
650{
651 int err = 0;
652 struct snd_soc_platform *platform = rtd->platform;
653
654 err = snd_soc_add_platform_controls(platform,
655 int_btsco_rate_mixer_controls,
656 ARRAY_SIZE(int_btsco_rate_mixer_controls));
657 if (err < 0)
658 return err;
659 return 0;
660}
661
Kuirong Wang054e1832012-05-11 15:43:30 -0700662static int msm8960_auxpcm_init(struct snd_soc_pcm_runtime *rtd)
663{
664 int err = 0;
665 struct snd_soc_platform *platform = rtd->platform;
666
667 err = snd_soc_add_platform_controls(platform,
668 auxpcm_rate_mixer_controls,
669 ARRAY_SIZE(auxpcm_rate_mixer_controls));
670 if (err < 0)
671 return err;
672 return 0;
673}
674
Joonwoo Park0976d012011-12-22 11:48:18 -0800675static void *def_tabla_mbhc_cal(void)
676{
677 void *tabla_cal;
678 struct tabla_mbhc_btn_detect_cfg *btn_cfg;
679 u16 *btn_low, *btn_high;
Joonwoo Parkc0672392012-01-11 11:03:14 -0800680 u8 *n_ready, *n_cic, *gain;
Joonwoo Park0976d012011-12-22 11:48:18 -0800681
682 tabla_cal = kzalloc(TABLA_MBHC_CAL_SIZE(TABLA_MBHC_DEF_BUTTONS,
683 TABLA_MBHC_DEF_RLOADS),
684 GFP_KERNEL);
685 if (!tabla_cal) {
686 pr_err("%s: out of memory\n", __func__);
687 return NULL;
688 }
689
690#define S(X, Y) ((TABLA_MBHC_CAL_GENERAL_PTR(tabla_cal)->X) = (Y))
691 S(t_ldoh, 100);
692 S(t_bg_fast_settle, 100);
693 S(t_shutdown_plug_rem, 255);
694 S(mbhc_nsa, 4);
695 S(mbhc_navg, 4);
696#undef S
697#define S(X, Y) ((TABLA_MBHC_CAL_PLUG_DET_PTR(tabla_cal)->X) = (Y))
698 S(mic_current, TABLA_PID_MIC_5_UA);
699 S(hph_current, TABLA_PID_MIC_5_UA);
700 S(t_mic_pid, 100);
Joonwoo Parkf4267c22012-01-10 13:25:24 -0800701 S(t_ins_complete, 250);
Joonwoo Park0976d012011-12-22 11:48:18 -0800702 S(t_ins_retry, 200);
703#undef S
704#define S(X, Y) ((TABLA_MBHC_CAL_PLUG_TYPE_PTR(tabla_cal)->X) = (Y))
705 S(v_no_mic, 30);
Joonwoo Parkcf473b42012-03-29 19:48:16 -0700706 S(v_hs_max, 2400);
Joonwoo Park0976d012011-12-22 11:48:18 -0800707#undef S
708#define S(X, Y) ((TABLA_MBHC_CAL_BTN_DET_PTR(tabla_cal)->X) = (Y))
Joonwoo Park6b9b03f2012-01-23 18:48:54 -0800709 S(c[0], 62);
710 S(c[1], 124);
711 S(nc, 1);
712 S(n_meas, 3);
Joonwoo Park0976d012011-12-22 11:48:18 -0800713 S(mbhc_nsc, 11);
Joonwoo Park6b9b03f2012-01-23 18:48:54 -0800714 S(n_btn_meas, 1);
715 S(n_btn_con, 2);
Joonwoo Park0976d012011-12-22 11:48:18 -0800716 S(num_btn, TABLA_MBHC_DEF_BUTTONS);
717 S(v_btn_press_delta_sta, 100);
718 S(v_btn_press_delta_cic, 50);
719#undef S
720 btn_cfg = TABLA_MBHC_CAL_BTN_DET_PTR(tabla_cal);
721 btn_low = tabla_mbhc_cal_btn_det_mp(btn_cfg, TABLA_BTN_DET_V_BTN_LOW);
722 btn_high = tabla_mbhc_cal_btn_det_mp(btn_cfg, TABLA_BTN_DET_V_BTN_HIGH);
Joonwoo Park6b9b03f2012-01-23 18:48:54 -0800723 btn_low[0] = -50;
Joonwoo Parkfee17432012-04-16 16:33:55 -0700724 btn_high[0] = 20;
725 btn_low[1] = 21;
726 btn_high[1] = 62;
727 btn_low[2] = 63;
728 btn_high[2] = 104;
729 btn_low[3] = 105;
730 btn_high[3] = 143;
731 btn_low[4] = 144;
732 btn_high[4] = 181;
733 btn_low[5] = 182;
734 btn_high[5] = 218;
735 btn_low[6] = 219;
736 btn_high[6] = 254;
737 btn_low[7] = 255;
738 btn_high[7] = 330;
Joonwoo Parkc0672392012-01-11 11:03:14 -0800739 n_ready = tabla_mbhc_cal_btn_det_mp(btn_cfg, TABLA_BTN_DET_N_READY);
Joonwoo Parkcf473b42012-03-29 19:48:16 -0700740 n_ready[0] = 80;
741 n_ready[1] = 68;
Joonwoo Park0976d012011-12-22 11:48:18 -0800742 n_cic = tabla_mbhc_cal_btn_det_mp(btn_cfg, TABLA_BTN_DET_N_CIC);
Joonwoo Park6b9b03f2012-01-23 18:48:54 -0800743 n_cic[0] = 60;
744 n_cic[1] = 47;
Joonwoo Park0976d012011-12-22 11:48:18 -0800745 gain = tabla_mbhc_cal_btn_det_mp(btn_cfg, TABLA_BTN_DET_GAIN);
746 gain[0] = 11;
747 gain[1] = 9;
748
749 return tabla_cal;
750}
751
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800752static int msm8960_hw_params(struct snd_pcm_substream *substream,
753 struct snd_pcm_hw_params *params)
754{
755 struct snd_soc_pcm_runtime *rtd = substream->private_data;
756 struct snd_soc_dai *codec_dai = rtd->codec_dai;
757 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
758 int ret = 0;
759 unsigned int rx_ch[SLIM_MAX_RX_PORTS], tx_ch[SLIM_MAX_TX_PORTS];
760 unsigned int rx_ch_cnt = 0, tx_ch_cnt = 0;
Kiran Kandi1e6371d2012-03-29 11:48:57 -0700761 unsigned int user_set_tx_ch = 0;
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800762
Kiran Kandi1e6371d2012-03-29 11:48:57 -0700763
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800764 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
Kiran Kandi1e6371d2012-03-29 11:48:57 -0700765
766 pr_debug("%s: rx_0_ch=%d\n", __func__, msm8960_slim_0_rx_ch);
767
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800768 ret = snd_soc_dai_get_channel_map(codec_dai,
769 &tx_ch_cnt, tx_ch, &rx_ch_cnt , rx_ch);
770 if (ret < 0) {
771 pr_err("%s: failed to get codec chan map\n", __func__);
772 goto end;
773 }
774
775 ret = snd_soc_dai_set_channel_map(cpu_dai, 0, 0,
776 msm8960_slim_0_rx_ch, rx_ch);
777 if (ret < 0) {
778 pr_err("%s: failed to set cpu chan map\n", __func__);
779 goto end;
780 }
781 ret = snd_soc_dai_set_channel_map(codec_dai, 0, 0,
782 msm8960_slim_0_rx_ch, rx_ch);
783 if (ret < 0) {
784 pr_err("%s: failed to set codec channel map\n",
785 __func__);
786 goto end;
787 }
788 } else {
Kiran Kandi1e6371d2012-03-29 11:48:57 -0700789
790 if (codec_dai->id == 2)
791 user_set_tx_ch = msm8960_slim_0_tx_ch;
792 else if (codec_dai->id == 4)
793 user_set_tx_ch = params_channels(params);
794
795 pr_debug("%s: %s_tx_dai_id_%d_ch=%d\n", __func__,
796 codec_dai->name, codec_dai->id, user_set_tx_ch);
797
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800798 ret = snd_soc_dai_get_channel_map(codec_dai,
799 &tx_ch_cnt, tx_ch, &rx_ch_cnt , rx_ch);
800 if (ret < 0) {
801 pr_err("%s: failed to get codec chan map\n", __func__);
802 goto end;
803 }
804 ret = snd_soc_dai_set_channel_map(cpu_dai,
Kiran Kandi1e6371d2012-03-29 11:48:57 -0700805 user_set_tx_ch, tx_ch, 0 , 0);
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800806 if (ret < 0) {
807 pr_err("%s: failed to set cpu chan map\n", __func__);
808 goto end;
809 }
810 ret = snd_soc_dai_set_channel_map(codec_dai,
Kiran Kandi1e6371d2012-03-29 11:48:57 -0700811 user_set_tx_ch, tx_ch, 0, 0);
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800812 if (ret < 0) {
813 pr_err("%s: failed to set codec channel map\n",
814 __func__);
815 goto end;
816 }
817
818
819 }
820end:
821 return ret;
822}
823
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700824static int msm8960_audrx_init(struct snd_soc_pcm_runtime *rtd)
825{
826 int err;
827 struct snd_soc_codec *codec = rtd->codec;
828 struct snd_soc_dapm_context *dapm = &codec->dapm;
Kuirong Wanga9c3acc2012-02-09 17:00:45 -0800829 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
Joonwoo Parkd7cf2e92012-03-19 19:38:23 -0700830 struct pm_gpio jack_gpio_cfg = {
831 .direction = PM_GPIO_DIR_IN,
832 .pull = PM_GPIO_PULL_UP_1P5,
833 .function = PM_GPIO_FUNC_NORMAL,
834 .vin_sel = 2,
835 .inv_int_pol = 0,
836 };
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700837
Kuirong Wanga9c3acc2012-02-09 17:00:45 -0800838 pr_debug("%s(), dev_name%s\n", __func__, dev_name(cpu_dai->dev));
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700839
Harmandeep Singh0dd82412011-11-11 09:46:17 -0800840 if (machine_is_msm8960_liquid()) {
841 top_spk_pamp_gpio = (PM8921_GPIO_PM_TO_SYS(19));
842 bottom_spk_pamp_gpio = (PM8921_GPIO_PM_TO_SYS(18));
843 }
844
Kiran Kandi28ef14e2011-09-16 15:45:47 -0700845 rtd->pmdown_time = 0;
846
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700847 err = snd_soc_add_controls(codec, tabla_msm8960_controls,
848 ARRAY_SIZE(tabla_msm8960_controls));
849 if (err < 0)
850 return err;
851
852 snd_soc_dapm_new_controls(dapm, msm8960_dapm_widgets,
853 ARRAY_SIZE(msm8960_dapm_widgets));
854
Bradley Rubin229c6a52011-07-12 16:18:48 -0700855 snd_soc_dapm_add_routes(dapm, common_audio_map,
856 ARRAY_SIZE(common_audio_map));
857
Peter Lohmannb8203ef2011-10-07 15:05:28 -0700858 snd_soc_dapm_enable_pin(dapm, "Ext Spk Bottom Pos");
859 snd_soc_dapm_enable_pin(dapm, "Ext Spk Bottom Neg");
860 snd_soc_dapm_enable_pin(dapm, "Ext Spk Top Pos");
861 snd_soc_dapm_enable_pin(dapm, "Ext Spk Top Neg");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700862
863 snd_soc_dapm_sync(dapm);
864
865 err = snd_soc_jack_new(codec, "Headset Jack",
Joonwoo Park6b9b03f2012-01-23 18:48:54 -0800866 (SND_JACK_HEADSET | SND_JACK_OC_HPHL |
Joonwoo Park2cc13f02012-05-09 12:44:25 -0700867 SND_JACK_OC_HPHR | SND_JACK_UNSUPPORTED),
Joonwoo Park6b9b03f2012-01-23 18:48:54 -0800868 &hs_jack);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700869 if (err) {
870 pr_err("failed to create new jack\n");
871 return err;
872 }
Bradley Rubincb1e2732011-06-23 16:49:20 -0700873
874 err = snd_soc_jack_new(codec, "Button Jack",
Joonwoo Park6b9b03f2012-01-23 18:48:54 -0800875 TABLA_JACK_BUTTON_MASK, &button_jack);
Bradley Rubincb1e2732011-06-23 16:49:20 -0700876 if (err) {
877 pr_err("failed to create new jack\n");
878 return err;
879 }
880
Kuirong Wanga9c3acc2012-02-09 17:00:45 -0800881 codec_clk = clk_get(cpu_dai->dev, "osr_clk");
882
Joonwoo Park2cc13f02012-05-09 12:44:25 -0700883 if (machine_is_msm8960_cdp())
884 mbhc_cfg.swap_gnd_mic = msm8960_swap_gnd_mic;
885
Joonwoo Park9115ade2012-04-18 13:14:10 -0700886 if (hs_detect_use_gpio) {
Joonwoo Parkd7cf2e92012-03-19 19:38:23 -0700887 mbhc_cfg.gpio = PM8921_GPIO_PM_TO_SYS(JACK_DETECT_GPIO);
888 mbhc_cfg.gpio_irq = JACK_DETECT_INT;
889 }
890
891 if (mbhc_cfg.gpio) {
892 err = pm8xxx_gpio_config(mbhc_cfg.gpio, &jack_gpio_cfg);
893 if (err) {
Joonwoo Park2cc13f02012-05-09 12:44:25 -0700894 pr_err("%s: pm8xxx_gpio_config JACK_DETECT failed %d\n",
895 __func__, err);
Joonwoo Parkd7cf2e92012-03-19 19:38:23 -0700896 return err;
897 }
898 }
Joonwoo Park9115ade2012-04-18 13:14:10 -0700899
900 mbhc_cfg.read_fw_bin = hs_detect_use_firmware;
901
Joonwoo Parkd7cf2e92012-03-19 19:38:23 -0700902 err = tabla_hs_detect(codec, &mbhc_cfg);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700903
Joonwoo Park03324832012-03-19 19:36:16 -0700904 return err;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700905}
906
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700907static struct snd_soc_dsp_link lpa_fe_media = {
Patrick Lai5b3fdfc2011-09-01 11:04:56 -0700908 .playback = true,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700909 .trigger = {
910 SND_SOC_DSP_TRIGGER_POST,
911 SND_SOC_DSP_TRIGGER_POST
912 },
913};
914
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700915static struct snd_soc_dsp_link fe_media = {
Patrick Lai5b3fdfc2011-09-01 11:04:56 -0700916 .playback = true,
917 .capture = true,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700918 .trigger = {
919 SND_SOC_DSP_TRIGGER_POST,
920 SND_SOC_DSP_TRIGGER_POST
921 },
922};
923
Patrick Lai9b56e1d2012-01-22 22:14:15 -0800924/* bi-directional media definition for hostless PCM device */
925static struct snd_soc_dsp_link bidir_hl_media = {
Patrick Lai5b3fdfc2011-09-01 11:04:56 -0700926 .playback = true,
927 .capture = true,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700928 .trigger = {
929 SND_SOC_DSP_TRIGGER_POST,
930 SND_SOC_DSP_TRIGGER_POST
931 },
932};
933
Alex Wongb3d06a02012-01-12 10:00:41 -0800934static struct snd_soc_dsp_link hdmi_rx_hl = {
935 .playback = true,
936 .trigger = {
937 SND_SOC_DSP_TRIGGER_POST,
938 SND_SOC_DSP_TRIGGER_POST
939 },
940};
941
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700942static int msm8960_slim_0_rx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
943 struct snd_pcm_hw_params *params)
944{
945 struct snd_interval *rate = hw_param_interval(params,
946 SNDRV_PCM_HW_PARAM_RATE);
947
948 struct snd_interval *channels = hw_param_interval(params,
949 SNDRV_PCM_HW_PARAM_CHANNELS);
950
951 pr_debug("%s()\n", __func__);
952 rate->min = rate->max = 48000;
953 channels->min = channels->max = msm8960_slim_0_rx_ch;
954
955 return 0;
956}
957
958static int msm8960_slim_0_tx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
959 struct snd_pcm_hw_params *params)
960{
961 struct snd_interval *rate = hw_param_interval(params,
962 SNDRV_PCM_HW_PARAM_RATE);
963
964 struct snd_interval *channels = hw_param_interval(params,
965 SNDRV_PCM_HW_PARAM_CHANNELS);
966
967 pr_debug("%s()\n", __func__);
968 rate->min = rate->max = 48000;
969 channels->min = channels->max = msm8960_slim_0_tx_ch;
970
971 return 0;
972}
973
974static int msm8960_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
975 struct snd_pcm_hw_params *params)
976{
977 struct snd_interval *rate = hw_param_interval(params,
978 SNDRV_PCM_HW_PARAM_RATE);
979
980 pr_debug("%s()\n", __func__);
981 rate->min = rate->max = 48000;
982
983 return 0;
984}
985
Helen Zeng73f7fc62011-11-18 16:29:59 -0800986static int msm8960_hdmi_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
987 struct snd_pcm_hw_params *params)
988{
989 struct snd_interval *rate = hw_param_interval(params,
990 SNDRV_PCM_HW_PARAM_RATE);
991
992 struct snd_interval *channels = hw_param_interval(params,
993 SNDRV_PCM_HW_PARAM_CHANNELS);
994
Kiran Kandi5e809b02012-01-31 00:24:33 -0800995 pr_debug("%s channels->min %u channels->max %u ()\n", __func__,
996 channels->min, channels->max);
997
Helen Zeng73f7fc62011-11-18 16:29:59 -0800998 rate->min = rate->max = 48000;
Helen Zeng73f7fc62011-11-18 16:29:59 -0800999
1000 return 0;
1001}
1002
Jayasena Sangaraboina47c08242011-08-10 11:30:57 -07001003static int msm8960_btsco_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
1004 struct snd_pcm_hw_params *params)
1005{
1006 struct snd_interval *rate = hw_param_interval(params,
1007 SNDRV_PCM_HW_PARAM_RATE);
1008
1009 struct snd_interval *channels = hw_param_interval(params,
1010 SNDRV_PCM_HW_PARAM_CHANNELS);
1011
1012 rate->min = rate->max = msm8960_btsco_rate;
1013 channels->min = channels->max = msm8960_btsco_ch;
1014
1015 return 0;
1016}
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -07001017static int msm8960_auxpcm_be_params_fixup(struct snd_soc_pcm_runtime *rtd,
1018 struct snd_pcm_hw_params *params)
1019{
1020 struct snd_interval *rate = hw_param_interval(params,
1021 SNDRV_PCM_HW_PARAM_RATE);
Jayasena Sangaraboina47c08242011-08-10 11:30:57 -07001022
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -07001023 struct snd_interval *channels = hw_param_interval(params,
1024 SNDRV_PCM_HW_PARAM_CHANNELS);
1025
Kuirong Wang054e1832012-05-11 15:43:30 -07001026 rate->min = rate->max = msm8960_auxpcm_rate;
1027 /* PCM only supports mono output */
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -07001028 channels->min = channels->max = 1;
1029
1030 return 0;
1031}
1032static int msm8960_aux_pcm_get_gpios(void)
1033{
1034 int ret = 0;
1035
1036 pr_debug("%s\n", __func__);
1037
1038 ret = gpio_request(GPIO_AUX_PCM_DOUT, "AUX PCM DOUT");
1039 if (ret < 0) {
1040 pr_err("%s: Failed to request gpio(%d): AUX PCM DOUT",
1041 __func__, GPIO_AUX_PCM_DOUT);
1042 goto fail_dout;
1043 }
1044
1045 ret = gpio_request(GPIO_AUX_PCM_DIN, "AUX PCM DIN");
1046 if (ret < 0) {
1047 pr_err("%s: Failed to request gpio(%d): AUX PCM DIN",
1048 __func__, GPIO_AUX_PCM_DIN);
1049 goto fail_din;
1050 }
1051
1052 ret = gpio_request(GPIO_AUX_PCM_SYNC, "AUX PCM SYNC");
1053 if (ret < 0) {
1054 pr_err("%s: Failed to request gpio(%d): AUX PCM SYNC",
1055 __func__, GPIO_AUX_PCM_SYNC);
1056 goto fail_sync;
1057 }
1058 ret = gpio_request(GPIO_AUX_PCM_CLK, "AUX PCM CLK");
1059 if (ret < 0) {
1060 pr_err("%s: Failed to request gpio(%d): AUX PCM CLK",
1061 __func__, GPIO_AUX_PCM_CLK);
1062 goto fail_clk;
1063 }
1064
1065 return 0;
1066
1067fail_clk:
1068 gpio_free(GPIO_AUX_PCM_SYNC);
1069fail_sync:
1070 gpio_free(GPIO_AUX_PCM_DIN);
1071fail_din:
1072 gpio_free(GPIO_AUX_PCM_DOUT);
1073fail_dout:
1074
1075 return ret;
1076}
1077
1078static int msm8960_aux_pcm_free_gpios(void)
1079{
1080 gpio_free(GPIO_AUX_PCM_DIN);
1081 gpio_free(GPIO_AUX_PCM_DOUT);
1082 gpio_free(GPIO_AUX_PCM_SYNC);
1083 gpio_free(GPIO_AUX_PCM_CLK);
1084
1085 return 0;
1086}
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001087static int msm8960_startup(struct snd_pcm_substream *substream)
1088{
Kiran Kandi6fae8bf2011-08-15 10:36:42 -07001089 pr_debug("%s(): substream = %s stream = %d\n", __func__,
1090 substream->name, substream->stream);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001091 return 0;
1092}
1093
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -07001094static int msm8960_auxpcm_startup(struct snd_pcm_substream *substream)
1095{
1096 int ret = 0;
1097
1098 pr_debug("%s(): substream = %s\n", __func__, substream->name);
1099 ret = msm8960_aux_pcm_get_gpios();
1100 if (ret < 0) {
1101 pr_err("%s: Aux PCM GPIO request failed\n", __func__);
1102 return -EINVAL;
1103 }
1104 return 0;
1105}
1106
1107static void msm8960_auxpcm_shutdown(struct snd_pcm_substream *substream)
1108{
1109
1110 pr_debug("%s(): substream = %s\n", __func__, substream->name);
1111 msm8960_aux_pcm_free_gpios();
1112}
1113
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001114static void msm8960_shutdown(struct snd_pcm_substream *substream)
1115{
Kiran Kandi6fae8bf2011-08-15 10:36:42 -07001116 pr_debug("%s(): substream = %s stream = %d\n", __func__,
1117 substream->name, substream->stream);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001118}
1119
1120static struct snd_soc_ops msm8960_be_ops = {
1121 .startup = msm8960_startup,
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -08001122 .hw_params = msm8960_hw_params,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001123 .shutdown = msm8960_shutdown,
1124};
1125
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -07001126static struct snd_soc_ops msm8960_auxpcm_be_ops = {
1127 .startup = msm8960_auxpcm_startup,
1128 .shutdown = msm8960_auxpcm_shutdown,
1129};
1130
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001131/* Digital audio interface glue - connects codec <---> CPU */
Kuirong Wangb25838e2012-01-16 23:37:23 -08001132static struct snd_soc_dai_link msm8960_dai_common[] = {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001133 /* FrontEnd DAI Links */
1134 {
1135 .name = "MSM8960 Media1",
1136 .stream_name = "MultiMedia1",
1137 .cpu_dai_name = "MultiMedia1",
1138 .platform_name = "msm-pcm-dsp",
1139 .dynamic = 1,
1140 .dsp_link = &fe_media,
1141 .be_id = MSM_FRONTEND_DAI_MULTIMEDIA1
1142 },
1143 {
1144 .name = "MSM8960 Media2",
1145 .stream_name = "MultiMedia2",
1146 .cpu_dai_name = "MultiMedia2",
Kiran Kandi5e809b02012-01-31 00:24:33 -08001147 .platform_name = "msm-multi-ch-pcm-dsp",
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001148 .dynamic = 1,
1149 .dsp_link = &fe_media,
1150 .be_id = MSM_FRONTEND_DAI_MULTIMEDIA2,
1151 },
1152 {
1153 .name = "Circuit-Switch Voice",
1154 .stream_name = "CS-Voice",
1155 .cpu_dai_name = "CS-VOICE",
1156 .platform_name = "msm-pcm-voice",
1157 .dynamic = 1,
1158 .dsp_link = &fe_media,
1159 .be_id = MSM_FRONTEND_DAI_CS_VOICE,
1160 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
Alex Wongb9367922011-09-21 23:09:43 -07001161 .ignore_suspend = 1,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001162 },
1163 {
1164 .name = "MSM VoIP",
1165 .stream_name = "VoIP",
1166 .cpu_dai_name = "VoIP",
1167 .platform_name = "msm-voip-dsp",
1168 .dynamic = 1,
1169 .dsp_link = &fe_media,
1170 .be_id = MSM_FRONTEND_DAI_VOIP,
1171 },
1172 {
1173 .name = "MSM8960 LPA",
1174 .stream_name = "LPA",
1175 .cpu_dai_name = "MultiMedia3",
1176 .platform_name = "msm-pcm-lpa",
1177 .dynamic = 1,
1178 .dsp_link = &lpa_fe_media,
1179 .be_id = MSM_FRONTEND_DAI_MULTIMEDIA3,
1180 },
1181 /* Hostless PMC purpose */
1182 {
1183 .name = "SLIMBUS_0 Hostless",
1184 .stream_name = "SLIMBUS_0 Hostless",
1185 .cpu_dai_name = "SLIMBUS0_HOSTLESS",
1186 .platform_name = "msm-pcm-hostless",
1187 .dynamic = 1,
Patrick Lai9b56e1d2012-01-22 22:14:15 -08001188 .dsp_link = &bidir_hl_media,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001189 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
Alex Wongb9367922011-09-21 23:09:43 -07001190 .ignore_suspend = 1,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001191 /* .be_id = do not care */
1192 },
1193 {
1194 .name = "INT_FM Hostless",
1195 .stream_name = "INT_FM Hostless",
1196 .cpu_dai_name = "INT_FM_HOSTLESS",
1197 .platform_name = "msm-pcm-hostless",
1198 .dynamic = 1,
Patrick Lai9b56e1d2012-01-22 22:14:15 -08001199 .dsp_link = &bidir_hl_media,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001200 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
Alex Wongb9367922011-09-21 23:09:43 -07001201 .ignore_suspend = 1,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001202 /* .be_id = do not care */
1203 },
Laxminath Kasam32657ec2011-08-01 19:26:57 +05301204 {
1205 .name = "MSM AFE-PCM RX",
1206 .stream_name = "AFE-PROXY RX",
1207 .cpu_dai_name = "msm-dai-q6.241",
1208 .codec_name = "msm-stub-codec.1",
1209 .codec_dai_name = "msm-stub-rx",
1210 .platform_name = "msm-pcm-afe",
Alex Wongb9367922011-09-21 23:09:43 -07001211 .ignore_suspend = 1,
Laxminath Kasam32657ec2011-08-01 19:26:57 +05301212 },
1213 {
1214 .name = "MSM AFE-PCM TX",
1215 .stream_name = "AFE-PROXY TX",
1216 .cpu_dai_name = "msm-dai-q6.240",
1217 .codec_name = "msm-stub-codec.1",
1218 .codec_dai_name = "msm-stub-tx",
1219 .platform_name = "msm-pcm-afe",
Alex Wongb9367922011-09-21 23:09:43 -07001220 .ignore_suspend = 1,
Laxminath Kasam32657ec2011-08-01 19:26:57 +05301221 },
Asish Bhattacharya09f9e0a2011-11-11 13:22:47 +05301222 {
1223 .name = "MSM8960 Compr",
1224 .stream_name = "COMPR",
1225 .cpu_dai_name = "MultiMedia4",
1226 .platform_name = "msm-compr-dsp",
1227 .dynamic = 1,
1228 .dsp_link = &lpa_fe_media,
1229 .be_id = MSM_FRONTEND_DAI_MULTIMEDIA4,
1230 },
Patrick Lai9b56e1d2012-01-22 22:14:15 -08001231 {
1232 .name = "AUXPCM Hostless",
1233 .stream_name = "AUXPCM Hostless",
1234 .cpu_dai_name = "AUXPCM_HOSTLESS",
1235 .platform_name = "msm-pcm-hostless",
1236 .dynamic = 1,
1237 .dsp_link = &bidir_hl_media,
1238 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
1239 .ignore_suspend = 1,
1240 },
Alex Wongb3d06a02012-01-12 10:00:41 -08001241 /* HDMI Hostless */
1242 {
1243 .name = "HDMI_RX_HOSTLESS",
1244 .stream_name = "HDMI_RX_HOSTLESS",
1245 .cpu_dai_name = "HDMI_HOSTLESS",
1246 .platform_name = "msm-pcm-hostless",
1247 .dynamic = 1,
1248 .dsp_link = &hdmi_rx_hl,
1249 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
1250 .no_codec = 1,
1251 .ignore_suspend = 1,
1252 },
Venkat Sudhir1c79c3b2012-04-09 23:42:28 -07001253 {
1254 .name = "VoLTE",
1255 .stream_name = "VoLTE",
1256 .cpu_dai_name = "VoLTE",
1257 .platform_name = "msm-pcm-voice",
1258 .dynamic = 1,
1259 .dsp_link = &fe_media,
1260 .be_id = MSM_FRONTEND_DAI_VOLTE,
1261 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
1262 .ignore_suspend = 1,
1263 },
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001264 /* Backend BT/FM DAI Links */
1265 {
1266 .name = LPASS_BE_INT_BT_SCO_RX,
1267 .stream_name = "Internal BT-SCO Playback",
1268 .cpu_dai_name = "msm-dai-q6.12288",
1269 .platform_name = "msm-pcm-routing",
1270 .codec_name = "msm-stub-codec.1",
1271 .codec_dai_name = "msm-stub-rx",
Jayasena Sangaraboina47c08242011-08-10 11:30:57 -07001272 .init = &msm8960_btsco_init,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001273 .no_pcm = 1,
1274 .be_id = MSM_BACKEND_DAI_INT_BT_SCO_RX,
Jayasena Sangaraboina47c08242011-08-10 11:30:57 -07001275 .be_hw_params_fixup = msm8960_btsco_be_hw_params_fixup,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001276 },
1277 {
1278 .name = LPASS_BE_INT_BT_SCO_TX,
1279 .stream_name = "Internal BT-SCO Capture",
1280 .cpu_dai_name = "msm-dai-q6.12289",
1281 .platform_name = "msm-pcm-routing",
1282 .codec_name = "msm-stub-codec.1",
1283 .codec_dai_name = "msm-stub-tx",
1284 .no_pcm = 1,
1285 .be_id = MSM_BACKEND_DAI_INT_BT_SCO_TX,
Jayasena Sangaraboina47c08242011-08-10 11:30:57 -07001286 .be_hw_params_fixup = msm8960_btsco_be_hw_params_fixup,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001287 },
1288 {
1289 .name = LPASS_BE_INT_FM_RX,
1290 .stream_name = "Internal FM Playback",
1291 .cpu_dai_name = "msm-dai-q6.12292",
1292 .platform_name = "msm-pcm-routing",
1293 .codec_name = "msm-stub-codec.1",
1294 .codec_dai_name = "msm-stub-rx",
1295 .no_pcm = 1,
1296 .be_id = MSM_BACKEND_DAI_INT_FM_RX,
1297 .be_hw_params_fixup = msm8960_be_hw_params_fixup,
1298 },
1299 {
1300 .name = LPASS_BE_INT_FM_TX,
1301 .stream_name = "Internal FM Capture",
1302 .cpu_dai_name = "msm-dai-q6.12293",
1303 .platform_name = "msm-pcm-routing",
1304 .codec_name = "msm-stub-codec.1",
1305 .codec_dai_name = "msm-stub-tx",
1306 .no_pcm = 1,
1307 .be_id = MSM_BACKEND_DAI_INT_FM_TX,
1308 .be_hw_params_fixup = msm8960_be_hw_params_fixup,
1309 },
1310 /* HDMI BACK END DAI Link */
1311 {
1312 .name = LPASS_BE_HDMI,
1313 .stream_name = "HDMI Playback",
Kiran Kandi5e809b02012-01-31 00:24:33 -08001314 .cpu_dai_name = "msm-dai-q6-hdmi.8",
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001315 .platform_name = "msm-pcm-routing",
1316 .codec_name = "msm-stub-codec.1",
1317 .codec_dai_name = "msm-stub-rx",
1318 .no_pcm = 1,
1319 .no_codec = 1,
1320 .be_id = MSM_BACKEND_DAI_HDMI_RX,
Helen Zeng73f7fc62011-11-18 16:29:59 -08001321 .be_hw_params_fixup = msm8960_hdmi_be_hw_params_fixup,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001322 },
Laxminath Kasam32657ec2011-08-01 19:26:57 +05301323 /* Backend AFE DAI Links */
1324 {
1325 .name = LPASS_BE_AFE_PCM_RX,
1326 .stream_name = "AFE Playback",
1327 .cpu_dai_name = "msm-dai-q6.224",
1328 .platform_name = "msm-pcm-routing",
1329 .codec_name = "msm-stub-codec.1",
1330 .codec_dai_name = "msm-stub-rx",
1331 .no_codec = 1,
1332 .no_pcm = 1,
1333 .be_id = MSM_BACKEND_DAI_AFE_PCM_RX,
1334 },
1335 {
1336 .name = LPASS_BE_AFE_PCM_TX,
1337 .stream_name = "AFE Capture",
1338 .cpu_dai_name = "msm-dai-q6.225",
1339 .platform_name = "msm-pcm-routing",
1340 .codec_name = "msm-stub-codec.1",
1341 .codec_dai_name = "msm-stub-tx",
1342 .no_codec = 1,
1343 .no_pcm = 1,
1344 .be_id = MSM_BACKEND_DAI_AFE_PCM_TX,
1345 },
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -07001346 /* AUX PCM Backend DAI Links */
1347 {
1348 .name = LPASS_BE_AUXPCM_RX,
1349 .stream_name = "AUX PCM Playback",
1350 .cpu_dai_name = "msm-dai-q6.2",
1351 .platform_name = "msm-pcm-routing",
1352 .codec_name = "msm-stub-codec.1",
1353 .codec_dai_name = "msm-stub-rx",
Kuirong Wang054e1832012-05-11 15:43:30 -07001354 .init = &msm8960_auxpcm_init,
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -07001355 .no_pcm = 1,
1356 .be_id = MSM_BACKEND_DAI_AUXPCM_RX,
1357 .be_hw_params_fixup = msm8960_auxpcm_be_params_fixup,
1358 .ops = &msm8960_auxpcm_be_ops,
1359 },
1360 {
1361 .name = LPASS_BE_AUXPCM_TX,
1362 .stream_name = "AUX PCM Capture",
1363 .cpu_dai_name = "msm-dai-q6.3",
1364 .platform_name = "msm-pcm-routing",
1365 .codec_name = "msm-stub-codec.1",
1366 .codec_dai_name = "msm-stub-tx",
1367 .no_pcm = 1,
1368 .be_id = MSM_BACKEND_DAI_AUXPCM_TX,
1369 .be_hw_params_fixup = msm8960_auxpcm_be_params_fixup,
1370 },
Helen Zeng0705a5f2011-10-14 15:29:52 -07001371 /* Incall Music BACK END DAI Link */
1372 {
1373 .name = LPASS_BE_VOICE_PLAYBACK_TX,
1374 .stream_name = "Voice Farend Playback",
1375 .cpu_dai_name = "msm-dai-q6.32773",
1376 .platform_name = "msm-pcm-routing",
1377 .codec_name = "msm-stub-codec.1",
1378 .codec_dai_name = "msm-stub-rx",
1379 .no_pcm = 1,
1380 .no_codec = 1,
1381 .be_id = MSM_BACKEND_DAI_VOICE_PLAYBACK_TX,
1382 .be_hw_params_fixup = msm8960_be_hw_params_fixup,
1383 },
Helen Zenge3d716a2011-10-14 16:32:16 -07001384 /* Incall Record Uplink BACK END DAI Link */
1385 {
1386 .name = LPASS_BE_INCALL_RECORD_TX,
1387 .stream_name = "Voice Uplink Capture",
1388 .cpu_dai_name = "msm-dai-q6.32772",
1389 .platform_name = "msm-pcm-routing",
1390 .codec_name = "msm-stub-codec.1",
1391 .codec_dai_name = "msm-stub-tx",
1392 .no_pcm = 1,
1393 .no_codec = 1,
1394 .be_id = MSM_BACKEND_DAI_INCALL_RECORD_TX,
1395 .be_hw_params_fixup = msm8960_be_hw_params_fixup,
1396 },
1397 /* Incall Record Downlink BACK END DAI Link */
1398 {
1399 .name = LPASS_BE_INCALL_RECORD_RX,
1400 .stream_name = "Voice Downlink Capture",
1401 .cpu_dai_name = "msm-dai-q6.32771",
1402 .platform_name = "msm-pcm-routing",
1403 .codec_name = "msm-stub-codec.1",
1404 .codec_dai_name = "msm-stub-tx",
1405 .no_pcm = 1,
1406 .no_codec = 1,
1407 .be_id = MSM_BACKEND_DAI_INCALL_RECORD_RX,
1408 .be_hw_params_fixup = msm8960_be_hw_params_fixup,
1409 },
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001410};
1411
Kuirong Wangb25838e2012-01-16 23:37:23 -08001412static struct snd_soc_dai_link msm8960_dai_delta_tabla1x[] = {
1413 /* Backend DAI Links */
1414 {
1415 .name = LPASS_BE_SLIMBUS_0_RX,
1416 .stream_name = "Slimbus Playback",
1417 .cpu_dai_name = "msm-dai-q6.16384",
1418 .platform_name = "msm-pcm-routing",
1419 .codec_name = "tabla1x_codec",
1420 .codec_dai_name = "tabla_rx1",
1421 .no_pcm = 1,
1422 .be_id = MSM_BACKEND_DAI_SLIMBUS_0_RX,
1423 .init = &msm8960_audrx_init,
1424 .be_hw_params_fixup = msm8960_slim_0_rx_be_hw_params_fixup,
1425 .ops = &msm8960_be_ops,
1426 },
1427 {
1428 .name = LPASS_BE_SLIMBUS_0_TX,
1429 .stream_name = "Slimbus Capture",
1430 .cpu_dai_name = "msm-dai-q6.16385",
1431 .platform_name = "msm-pcm-routing",
1432 .codec_name = "tabla1x_codec",
1433 .codec_dai_name = "tabla_tx1",
1434 .no_pcm = 1,
1435 .be_id = MSM_BACKEND_DAI_SLIMBUS_0_TX,
1436 .be_hw_params_fixup = msm8960_slim_0_tx_be_hw_params_fixup,
1437 .ops = &msm8960_be_ops,
1438 },
Kiran Kandi1e6371d2012-03-29 11:48:57 -07001439 {
1440 .name = "SLIMBUS_2 Hostless",
1441 .stream_name = "SLIMBUS_2 Hostless",
1442 .cpu_dai_name = "msm-dai-q6.16389",
1443 .platform_name = "msm-pcm-hostless",
1444 .codec_name = "tabla1x_codec",
1445 .codec_dai_name = "tabla_tx2",
Swaminathan Sathappan630c5a42012-05-10 17:33:01 -07001446 .ignore_suspend = 1,
Kiran Kandi1e6371d2012-03-29 11:48:57 -07001447 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
1448 .ops = &msm8960_be_ops,
1449 },
Kuirong Wangb25838e2012-01-16 23:37:23 -08001450};
1451
1452
1453static struct snd_soc_dai_link msm8960_dai_delta_tabla2x[] = {
1454 /* Backend DAI Links */
1455 {
1456 .name = LPASS_BE_SLIMBUS_0_RX,
1457 .stream_name = "Slimbus Playback",
1458 .cpu_dai_name = "msm-dai-q6.16384",
1459 .platform_name = "msm-pcm-routing",
1460 .codec_name = "tabla_codec",
1461 .codec_dai_name = "tabla_rx1",
1462 .no_pcm = 1,
1463 .be_id = MSM_BACKEND_DAI_SLIMBUS_0_RX,
1464 .init = &msm8960_audrx_init,
1465 .be_hw_params_fixup = msm8960_slim_0_rx_be_hw_params_fixup,
1466 .ops = &msm8960_be_ops,
1467 },
1468 {
1469 .name = LPASS_BE_SLIMBUS_0_TX,
1470 .stream_name = "Slimbus Capture",
1471 .cpu_dai_name = "msm-dai-q6.16385",
1472 .platform_name = "msm-pcm-routing",
1473 .codec_name = "tabla_codec",
1474 .codec_dai_name = "tabla_tx1",
1475 .no_pcm = 1,
1476 .be_id = MSM_BACKEND_DAI_SLIMBUS_0_TX,
1477 .be_hw_params_fixup = msm8960_slim_0_tx_be_hw_params_fixup,
1478 .ops = &msm8960_be_ops,
1479 },
Kiran Kandi1e6371d2012-03-29 11:48:57 -07001480 {
1481 .name = "SLIMBUS_2 Hostless",
1482 .stream_name = "SLIMBUS_2 Hostless",
1483 .cpu_dai_name = "msm-dai-q6.16389",
1484 .platform_name = "msm-pcm-hostless",
1485 .codec_name = "tabla_codec",
1486 .codec_dai_name = "tabla_tx2",
Swaminathan Sathappan630c5a42012-05-10 17:33:01 -07001487 .ignore_suspend = 1,
Kiran Kandi1e6371d2012-03-29 11:48:57 -07001488 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
1489 .ops = &msm8960_be_ops,
1490 },
Kuirong Wangb25838e2012-01-16 23:37:23 -08001491};
1492
1493static struct snd_soc_dai_link msm8960_tabla1x_dai[
1494 ARRAY_SIZE(msm8960_dai_common) +
1495 ARRAY_SIZE(msm8960_dai_delta_tabla1x)];
1496
1497
1498static struct snd_soc_dai_link msm8960_dai[
1499 ARRAY_SIZE(msm8960_dai_common) +
1500 ARRAY_SIZE(msm8960_dai_delta_tabla2x)];
1501
1502static struct snd_soc_card snd_soc_tabla1x_card_msm8960 = {
1503 .name = "msm8960-tabla1x-snd-card",
1504 .dai_link = msm8960_tabla1x_dai,
1505 .num_links = ARRAY_SIZE(msm8960_tabla1x_dai),
1506};
1507
1508static struct snd_soc_card snd_soc_card_msm8960 = {
1509 .name = "msm8960-snd-card",
1510 .dai_link = msm8960_dai,
1511 .num_links = ARRAY_SIZE(msm8960_dai),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001512};
1513
1514static struct platform_device *msm8960_snd_device;
Kuirong Wangb25838e2012-01-16 23:37:23 -08001515static struct platform_device *msm8960_snd_tabla1x_device;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001516
1517static int msm8960_configure_headset_mic_gpios(void)
1518{
1519 int ret;
1520 struct pm_gpio param = {
1521 .direction = PM_GPIO_DIR_OUT,
1522 .output_buffer = PM_GPIO_OUT_BUF_CMOS,
1523 .output_value = 1,
1524 .pull = PM_GPIO_PULL_NO,
1525 .vin_sel = PM_GPIO_VIN_S4,
1526 .out_strength = PM_GPIO_STRENGTH_MED,
1527 .function = PM_GPIO_FUNC_NORMAL,
1528 };
1529
1530 ret = gpio_request(PM8921_GPIO_PM_TO_SYS(23), "AV_SWITCH");
1531 if (ret) {
1532 pr_err("%s: Failed to request gpio %d\n", __func__,
1533 PM8921_GPIO_PM_TO_SYS(23));
1534 return ret;
1535 }
1536
1537 ret = pm8xxx_gpio_config(PM8921_GPIO_PM_TO_SYS(23), &param);
1538 if (ret)
1539 pr_err("%s: Failed to configure gpio %d\n", __func__,
1540 PM8921_GPIO_PM_TO_SYS(23));
1541 else
1542 gpio_direction_output(PM8921_GPIO_PM_TO_SYS(23), 0);
1543
Joonwoo Park2cc13f02012-05-09 12:44:25 -07001544 ret = gpio_request(us_euro_sel_gpio, "US_EURO_SWITCH");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001545 if (ret) {
1546 pr_err("%s: Failed to request gpio %d\n", __func__,
Joonwoo Park2cc13f02012-05-09 12:44:25 -07001547 us_euro_sel_gpio);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001548 gpio_free(PM8921_GPIO_PM_TO_SYS(23));
1549 return ret;
1550 }
Joonwoo Park2cc13f02012-05-09 12:44:25 -07001551 ret = pm8xxx_gpio_config(us_euro_sel_gpio, &param);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001552 if (ret)
1553 pr_err("%s: Failed to configure gpio %d\n", __func__,
Joonwoo Park2cc13f02012-05-09 12:44:25 -07001554 us_euro_sel_gpio);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001555 else
Joonwoo Park2cc13f02012-05-09 12:44:25 -07001556 gpio_direction_output(us_euro_sel_gpio, 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001557
1558 return 0;
1559}
1560static void msm8960_free_headset_mic_gpios(void)
1561{
1562 if (msm8960_headset_gpios_configured) {
1563 gpio_free(PM8921_GPIO_PM_TO_SYS(23));
Joonwoo Park2cc13f02012-05-09 12:44:25 -07001564 gpio_free(us_euro_sel_gpio);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001565 }
1566}
1567
1568static int __init msm8960_audio_init(void)
1569{
1570 int ret;
1571
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301572 if (!cpu_is_msm8960()) {
Bharath Ramachandramurthyb8e797f2011-11-30 12:08:42 -08001573 pr_err("%s: Not the right machine type\n", __func__);
1574 return -ENODEV ;
1575 }
Joonwoo Park0976d012011-12-22 11:48:18 -08001576
Joonwoo Parkd7cf2e92012-03-19 19:38:23 -07001577 mbhc_cfg.calibration = def_tabla_mbhc_cal();
1578 if (!mbhc_cfg.calibration) {
Joonwoo Park0976d012011-12-22 11:48:18 -08001579 pr_err("Calibration data allocation failed\n");
1580 return -ENOMEM;
1581 }
1582
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001583 msm8960_snd_device = platform_device_alloc("soc-audio", 0);
1584 if (!msm8960_snd_device) {
1585 pr_err("Platform device allocation failed\n");
Joonwoo Parkd7cf2e92012-03-19 19:38:23 -07001586 kfree(mbhc_cfg.calibration);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001587 return -ENOMEM;
1588 }
1589
Kuirong Wangb25838e2012-01-16 23:37:23 -08001590 memcpy(msm8960_dai, msm8960_dai_common, sizeof(msm8960_dai_common));
1591 memcpy(msm8960_dai + ARRAY_SIZE(msm8960_dai_common),
1592 msm8960_dai_delta_tabla2x, sizeof(msm8960_dai_delta_tabla2x));
1593
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001594 platform_set_drvdata(msm8960_snd_device, &snd_soc_card_msm8960);
1595 ret = platform_device_add(msm8960_snd_device);
1596 if (ret) {
1597 platform_device_put(msm8960_snd_device);
Joonwoo Parkd7cf2e92012-03-19 19:38:23 -07001598 kfree(mbhc_cfg.calibration);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001599 return ret;
1600 }
1601
Kuirong Wangb25838e2012-01-16 23:37:23 -08001602 msm8960_snd_tabla1x_device = platform_device_alloc("soc-audio", 1);
1603 if (!msm8960_snd_tabla1x_device) {
1604 pr_err("Platform device allocation failed\n");
Joonwoo Parkd7cf2e92012-03-19 19:38:23 -07001605 kfree(mbhc_cfg.calibration);
Kuirong Wangb25838e2012-01-16 23:37:23 -08001606 return -ENOMEM;
1607 }
1608
1609 memcpy(msm8960_tabla1x_dai, msm8960_dai_common,
1610 sizeof(msm8960_dai_common));
1611 memcpy(msm8960_tabla1x_dai + ARRAY_SIZE(msm8960_dai_common),
1612 msm8960_dai_delta_tabla1x, sizeof(msm8960_dai_delta_tabla1x));
1613
1614 platform_set_drvdata(msm8960_snd_tabla1x_device,
1615 &snd_soc_tabla1x_card_msm8960);
1616 ret = platform_device_add(msm8960_snd_tabla1x_device);
1617 if (ret) {
1618 platform_device_put(msm8960_snd_tabla1x_device);
Joonwoo Parkd7cf2e92012-03-19 19:38:23 -07001619 kfree(mbhc_cfg.calibration);
Kuirong Wangb25838e2012-01-16 23:37:23 -08001620 return ret;
1621 }
1622
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001623 if (msm8960_configure_headset_mic_gpios()) {
1624 pr_err("%s Fail to configure headset mic gpios\n", __func__);
1625 msm8960_headset_gpios_configured = 0;
1626 } else
1627 msm8960_headset_gpios_configured = 1;
1628
Joonwoo Park28f49c82012-03-16 12:29:21 -07001629 mutex_init(&cdc_mclk_mutex);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001630 return ret;
1631
1632}
1633module_init(msm8960_audio_init);
1634
1635static void __exit msm8960_audio_exit(void)
1636{
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301637 if (!cpu_is_msm8960()) {
Bharath Ramachandramurthyb8e797f2011-11-30 12:08:42 -08001638 pr_err("%s: Not the right machine type\n", __func__);
1639 return ;
1640 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001641 msm8960_free_headset_mic_gpios();
1642 platform_device_unregister(msm8960_snd_device);
Kuirong Wangb25838e2012-01-16 23:37:23 -08001643 platform_device_unregister(msm8960_snd_tabla1x_device);
Joonwoo Parkd7cf2e92012-03-19 19:38:23 -07001644 kfree(mbhc_cfg.calibration);
Joonwoo Park28f49c82012-03-16 12:29:21 -07001645 mutex_destroy(&cdc_mclk_mutex);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001646}
1647module_exit(msm8960_audio_exit);
1648
1649MODULE_DESCRIPTION("ALSA SoC MSM8960");
1650MODULE_LICENSE("GPL v2");