blob: 3f7e399217814fab944aad7fe52d09ca27d593bf [file] [log] [blame]
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 */
12
13#include <linux/clk.h>
14#include <linux/delay.h>
15#include <linux/gpio.h>
Asish Bhattacharyac71827a2012-03-05 10:11:45 -080016#include <linux/mfd/pm8xxx/spk.h>
Asish Bhattacharyab86c3472012-02-15 08:31:52 +053017#include <linux/platform_device.h>
18#include <linux/gpio.h>
Asish Bhattacharyab86c3472012-02-15 08:31:52 +053019#include <linux/slab.h>
20#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>
26#include <asm/mach-types.h>
27#include <mach/socinfo.h>
28#include "msm-pcm-routing.h"
29#include "../codecs/wcd9304.h"
30
31/* 8930 machine driver */
32
Asish Bhattacharyab86c3472012-02-15 08:31:52 +053033#define MSM8930_SPK_ON 1
34#define MSM8930_SPK_OFF 0
35
Asish Bhattacharyab86c3472012-02-15 08:31:52 +053036#define BTSCO_RATE_8KHZ 8000
37#define BTSCO_RATE_16KHZ 16000
38
Asish Bhattacharyac71827a2012-03-05 10:11:45 -080039#define SPK_AMP_POS 0x1
40#define SPK_AMP_NEG 0x2
Asish Bhattacharyab86c3472012-02-15 08:31:52 +053041#define SITAR_EXT_CLK_RATE 12288000
42
43#define SITAR_MBHC_DEF_BUTTONS 3
44#define SITAR_MBHC_DEF_RLOADS 5
45
46static int msm8930_spk_control;
47static int msm8930_slim_0_rx_ch = 1;
48static int msm8930_slim_0_tx_ch = 1;
49
Asish Bhattacharyac71827a2012-03-05 10:11:45 -080050static int msm8930_ext_spk_pamp;
Asish Bhattacharyab86c3472012-02-15 08:31:52 +053051static int msm8930_btsco_rate = BTSCO_RATE_8KHZ;
52static int msm8930_btsco_ch = 1;
53
54static struct clk *codec_clk;
55static int clk_users;
56
57static int msm8930_headset_gpios_configured;
58
59static struct snd_soc_jack hs_jack;
60static struct snd_soc_jack button_jack;
Bhalchandra Gajare466aafe2012-05-02 17:55:26 -070061
62static int msm8930_enable_codec_ext_clk(
63 struct snd_soc_codec *codec, int enable,
64 bool dapm);
65
66static struct sitar_mbhc_config mbhc_cfg = {
67 .headset_jack = &hs_jack,
68 .button_jack = &button_jack,
69 .read_fw_bin = false,
70 .calibration = NULL,
71 .micbias = SITAR_MICBIAS2,
72 .mclk_cb_fn = msm8930_enable_codec_ext_clk,
73 .mclk_rate = SITAR_EXT_CLK_RATE,
74 .gpio = 0,
75 .gpio_irq = 0,
76 .gpio_level_insert = 1,
77};
78
Asish Bhattacharyab86c3472012-02-15 08:31:52 +053079
80static void msm8930_ext_control(struct snd_soc_codec *codec)
81{
82 struct snd_soc_dapm_context *dapm = &codec->dapm;
83
84 pr_debug("%s: msm8930_spk_control = %d", __func__, msm8930_spk_control);
85 if (msm8930_spk_control == MSM8930_SPK_ON) {
86 snd_soc_dapm_enable_pin(dapm, "Ext Spk Left Pos");
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -080087 snd_soc_dapm_enable_pin(dapm, "Ext Spk left Neg");
Asish Bhattacharyab86c3472012-02-15 08:31:52 +053088 } else {
89 snd_soc_dapm_disable_pin(dapm, "Ext Spk Left Pos");
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -080090 snd_soc_dapm_disable_pin(dapm, "Ext Spk Left Neg");
Asish Bhattacharyab86c3472012-02-15 08:31:52 +053091 }
92
93 snd_soc_dapm_sync(dapm);
94}
95
96static int msm8930_get_spk(struct snd_kcontrol *kcontrol,
97 struct snd_ctl_elem_value *ucontrol)
98{
99 pr_debug("%s: msm8930_spk_control = %d", __func__, msm8930_spk_control);
100 ucontrol->value.integer.value[0] = msm8930_spk_control;
101 return 0;
102}
103static int msm8930_set_spk(struct snd_kcontrol *kcontrol,
104 struct snd_ctl_elem_value *ucontrol)
105{
106 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
107
108 pr_debug("%s()\n", __func__);
109 if (msm8930_spk_control == ucontrol->value.integer.value[0])
110 return 0;
111
112 msm8930_spk_control = ucontrol->value.integer.value[0];
113 msm8930_ext_control(codec);
114 return 1;
115}
116
Asish Bhattacharyac71827a2012-03-05 10:11:45 -0800117static void msm8960_ext_spk_power_amp_on(u32 spk)
118{
119 if (spk & (SPK_AMP_POS | SPK_AMP_NEG)) {
120 if ((msm8930_ext_spk_pamp & SPK_AMP_POS) &&
121 (msm8930_ext_spk_pamp & SPK_AMP_NEG)) {
122
123 pr_debug("%s() External Bottom Speaker Ampl already "
124 "turned on. spk = 0x%08x\n", __func__, spk);
125 return;
126 }
127
128 msm8930_ext_spk_pamp |= spk;
129
130 if ((msm8930_ext_spk_pamp & SPK_AMP_POS) &&
131 (msm8930_ext_spk_pamp & SPK_AMP_NEG)) {
132
133 pm8xxx_spk_enable(MSM8930_SPK_ON);
134 pr_debug("%s: slepping 4 ms after turning on external "
135 " Left Speaker Ampl\n", __func__);
136 usleep_range(4000, 4000);
137 }
138
139 } else {
140
141 pr_err("%s: ERROR : Invalid External Speaker Ampl. spk = 0x%08x\n",
142 __func__, spk);
143 return;
144 }
145}
146
147static void msm8960_ext_spk_power_amp_off(u32 spk)
148{
149 if (spk & (SPK_AMP_POS | SPK_AMP_NEG)) {
150 if (!msm8930_ext_spk_pamp)
151 return;
152
153 pm8xxx_spk_enable(MSM8930_SPK_OFF);
154 msm8930_ext_spk_pamp = 0;
155 pr_debug("%s: slepping 4 ms after turning on external "
156 " Left Speaker Ampl\n", __func__);
157 usleep_range(4000, 4000);
158
159 } else {
160
161 pr_err("%s: ERROR : Invalid External Speaker Ampl. spk = 0x%08x\n",
162 __func__, spk);
163 return;
164 }
165}
166
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530167static int msm8930_spkramp_event(struct snd_soc_dapm_widget *w,
168 struct snd_kcontrol *k, int event)
169{
170 pr_debug("%s() %x\n", __func__, SND_SOC_DAPM_EVENT_ON(event));
Asish Bhattacharyac71827a2012-03-05 10:11:45 -0800171 if (SND_SOC_DAPM_EVENT_ON(event)) {
172 if (!strncmp(w->name, "Ext Spk Left Pos", 17))
173 msm8960_ext_spk_power_amp_on(SPK_AMP_POS);
174 else if (!strncmp(w->name, "Ext Spk Left Neg", 17))
175 msm8960_ext_spk_power_amp_on(SPK_AMP_NEG);
176 else {
177 pr_err("%s() Invalid Speaker Widget = %s\n",
178 __func__, w->name);
179 return -EINVAL;
180 }
181 } else {
182 if (!strncmp(w->name, "Ext Spk Left Pos", 17))
183 msm8960_ext_spk_power_amp_off(SPK_AMP_POS);
184 else if (!strncmp(w->name, "Ext Spk Left Neg", 17))
185 msm8960_ext_spk_power_amp_off(SPK_AMP_NEG);
186 else {
187 pr_err("%s() Invalid Speaker Widget = %s\n",
188 __func__, w->name);
189 return -EINVAL;
190 }
191 }
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530192 return 0;
193}
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800194
Bhalchandra Gajare466aafe2012-05-02 17:55:26 -0700195static int msm8930_enable_codec_ext_clk(
196 struct snd_soc_codec *codec, int enable,
197 bool dapm)
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530198{
199 pr_debug("%s: enable = %d\n", __func__, enable);
200 if (enable) {
201 clk_users++;
202 pr_debug("%s: clk_users = %d\n", __func__, clk_users);
203 if (clk_users != 1)
204 return 0;
205
206 if (codec_clk) {
207 clk_set_rate(codec_clk, SITAR_EXT_CLK_RATE);
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800208 clk_prepare_enable(codec_clk);
Bhalchandra Gajare466aafe2012-05-02 17:55:26 -0700209 sitar_mclk_enable(codec, 1, dapm);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530210 } else {
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800211 pr_err("%s: Error setting Sitar MCLK\n", __func__);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530212 clk_users--;
213 return -EINVAL;
214 }
215 } else {
216 pr_debug("%s: clk_users = %d\n", __func__, clk_users);
217 if (clk_users == 0)
218 return 0;
219 clk_users--;
220 if (!clk_users) {
221 pr_debug("%s: disabling MCLK. clk_users = %d\n",
222 __func__, clk_users);
Bhalchandra Gajare466aafe2012-05-02 17:55:26 -0700223 sitar_mclk_enable(codec, 0, dapm);
Bhalchandra Gajare2776af12012-04-27 16:59:39 -0700224 clk_disable_unprepare(codec_clk);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530225 }
226 }
227 return 0;
228}
229
230static int msm8930_mclk_event(struct snd_soc_dapm_widget *w,
231 struct snd_kcontrol *kcontrol, int event)
232{
233 pr_debug("%s: event = %d\n", __func__, event);
234
235 switch (event) {
236 case SND_SOC_DAPM_PRE_PMU:
Bhalchandra Gajare466aafe2012-05-02 17:55:26 -0700237 return msm8930_enable_codec_ext_clk(w->codec, 1, true);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530238 case SND_SOC_DAPM_POST_PMD:
Bhalchandra Gajare466aafe2012-05-02 17:55:26 -0700239 return msm8930_enable_codec_ext_clk(w->codec, 0, true);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530240 }
241 return 0;
242}
243
244static const struct snd_soc_dapm_widget msm8930_dapm_widgets[] = {
245
246 SND_SOC_DAPM_SUPPLY("MCLK", SND_SOC_NOPM, 0, 0,
247 msm8930_mclk_event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
248
249 SND_SOC_DAPM_SPK("Ext Spk Left Pos", msm8930_spkramp_event),
Asish Bhattacharyac71827a2012-03-05 10:11:45 -0800250 SND_SOC_DAPM_SPK("Ext Spk Left Neg", msm8930_spkramp_event),
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530251
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530252 SND_SOC_DAPM_MIC("Headset Mic", NULL),
253 SND_SOC_DAPM_MIC("Digital Mic1", NULL),
254 SND_SOC_DAPM_MIC("ANCRight Headset Mic", NULL),
255 SND_SOC_DAPM_MIC("ANCLeft Headset Mic", NULL),
256
257 SND_SOC_DAPM_MIC("Digital Mic1", NULL),
258 SND_SOC_DAPM_MIC("Digital Mic2", NULL),
259 SND_SOC_DAPM_MIC("Digital Mic3", NULL),
260 SND_SOC_DAPM_MIC("Digital Mic4", NULL),
261
262};
263
264static const struct snd_soc_dapm_route common_audio_map[] = {
265
266 {"RX_BIAS", NULL, "MCLK"},
267 {"LDO_H", NULL, "MCLK"},
268
269 {"MIC BIAS1 Internal1", NULL, "MCLK"},
270 {"MIC BIAS2 Internal1", NULL, "MCLK"},
271
272 /* Speaker path */
273 {"Ext Spk Left Pos", NULL, "LINEOUT1"},
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800274 {"Ext Spk Left Neg", NULL, "LINEOUT2"},
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530275
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800276 /* Headset Mic */
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530277 {"AMIC2", NULL, "MIC BIAS2 Internal1"},
278 {"MIC BIAS2 Internal1", NULL, "Headset Mic"},
279
280 /* Microphone path */
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800281 {"AMIC1", NULL, "MIC BIAS2 Internal1"},
282 {"MIC BIAS2 Internal1", NULL, "ANCLeft Headset Mic"},
283
284 {"AMIC3", NULL, "MIC BIAS2 Internal1"},
285 {"MIC BIAS2 Internal1", NULL, "ANCRight Headset Mic"},
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530286
287 {"HEADPHONE", NULL, "LDO_H"},
288
289 /**
290 * The digital Mic routes are setup considering
291 * fluid as default device.
292 */
293
294 /**
295 * Digital Mic1. Front Bottom left Digital Mic on Fluid and MTP.
296 * Digital Mic GM5 on CDP mainboard.
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800297 * Conncted to DMIC2 Input on Sitar codec.
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530298 */
299 {"DMIC1", NULL, "MIC BIAS1 External"},
300 {"MIC BIAS1 External", NULL, "Digital Mic1"},
301
302 /**
303 * Digital Mic2. Front Bottom right Digital Mic on Fluid and MTP.
304 * Digital Mic GM6 on CDP mainboard.
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800305 * Conncted to DMIC1 Input on Sitar codec.
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530306 */
307 {"DMIC2", NULL, "MIC BIAS1 External"},
308 {"MIC BIAS1 External", NULL, "Digital Mic2"},
309 /**
310 * Digital Mic3. Back Bottom Digital Mic on Fluid.
311 * Digital Mic GM1 on CDP mainboard.
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800312 * Conncted to DMIC4 Input on Sitar codec.
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530313 */
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800314 {"DMIC3", NULL, "MIC BIAS1 External"},
315 {"MIC BIAS1 External", NULL, "Digital Mic3"},
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530316
317 /**
318 * Digital Mic4. Back top Digital Mic on Fluid.
319 * Digital Mic GM2 on CDP mainboard.
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800320 * Conncted to DMIC3 Input on Sitar codec.
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530321 */
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800322 {"DMIC4", NULL, "MIC BIAS1 External"},
323 {"MIC BIAS1 External", NULL, "Digital Mic4"},
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530324
325
326};
327
328static const char *spk_function[] = {"Off", "On"};
329static const char *slim0_rx_ch_text[] = {"One", "Two"};
330static const char *slim0_tx_ch_text[] = {"One", "Two", "Three", "Four"};
331
332static const struct soc_enum msm8930_enum[] = {
333 SOC_ENUM_SINGLE_EXT(2, spk_function),
334 SOC_ENUM_SINGLE_EXT(2, slim0_rx_ch_text),
335 SOC_ENUM_SINGLE_EXT(4, slim0_tx_ch_text),
336};
337
338static const char *btsco_rate_text[] = {"8000", "16000"};
339static const struct soc_enum msm8930_btsco_enum[] = {
340 SOC_ENUM_SINGLE_EXT(2, btsco_rate_text),
341};
342
343static int msm8930_slim_0_rx_ch_get(struct snd_kcontrol *kcontrol,
344 struct snd_ctl_elem_value *ucontrol)
345{
346 pr_debug("%s: msm8930_slim_0_rx_ch = %d\n", __func__,
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800347 msm8930_slim_0_rx_ch);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530348 ucontrol->value.integer.value[0] = msm8930_slim_0_rx_ch - 1;
349 return 0;
350}
351
352static int msm8930_slim_0_rx_ch_put(struct snd_kcontrol *kcontrol,
353 struct snd_ctl_elem_value *ucontrol)
354{
355 msm8930_slim_0_rx_ch = ucontrol->value.integer.value[0] + 1;
356
357 pr_debug("%s: msm8930_slim_0_rx_ch = %d\n", __func__,
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800358 msm8930_slim_0_rx_ch);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530359 return 1;
360}
361
362static int msm8930_slim_0_tx_ch_get(struct snd_kcontrol *kcontrol,
363 struct snd_ctl_elem_value *ucontrol)
364{
365 pr_debug("%s: msm8930_slim_0_tx_ch = %d\n", __func__,
366 msm8930_slim_0_tx_ch);
367 ucontrol->value.integer.value[0] = msm8930_slim_0_tx_ch - 1;
368 return 0;
369}
370
371static int msm8930_slim_0_tx_ch_put(struct snd_kcontrol *kcontrol,
372 struct snd_ctl_elem_value *ucontrol)
373{
374 msm8930_slim_0_tx_ch = ucontrol->value.integer.value[0] + 1;
375
376 pr_debug("%s: msm8930_slim_0_tx_ch = %d\n", __func__,
377 msm8930_slim_0_tx_ch);
378 return 1;
379}
380
381static int msm8930_btsco_rate_get(struct snd_kcontrol *kcontrol,
382 struct snd_ctl_elem_value *ucontrol)
383{
384 pr_debug("%s: msm8930_btsco_rate = %d", __func__, msm8930_btsco_rate);
385 ucontrol->value.integer.value[0] = msm8930_btsco_rate;
386 return 0;
387}
388
389static int msm8930_btsco_rate_put(struct snd_kcontrol *kcontrol,
390 struct snd_ctl_elem_value *ucontrol)
391{
392 switch (ucontrol->value.integer.value[0]) {
393 case 0:
394 msm8930_btsco_rate = BTSCO_RATE_8KHZ;
395 break;
396 case 1:
397 msm8930_btsco_rate = BTSCO_RATE_16KHZ;
398 break;
399 default:
400 msm8930_btsco_rate = BTSCO_RATE_8KHZ;
401 break;
402 }
403 pr_debug("%s: msm8930_btsco_rate = %d\n", __func__, msm8930_btsco_rate);
404 return 0;
405}
406
407static const struct snd_kcontrol_new sitar_msm8930_controls[] = {
408 SOC_ENUM_EXT("Speaker Function", msm8930_enum[0], msm8930_get_spk,
409 msm8930_set_spk),
410 SOC_ENUM_EXT("SLIM_0_RX Channels", msm8930_enum[1],
411 msm8930_slim_0_rx_ch_get, msm8930_slim_0_rx_ch_put),
412 SOC_ENUM_EXT("SLIM_0_TX Channels", msm8930_enum[2],
413 msm8930_slim_0_tx_ch_get, msm8930_slim_0_tx_ch_put),
414};
415
416static const struct snd_kcontrol_new int_btsco_rate_mixer_controls[] = {
417 SOC_ENUM_EXT("Internal BTSCO SampleRate", msm8930_btsco_enum[0],
418 msm8930_btsco_rate_get, msm8930_btsco_rate_put),
419};
420
421static int msm8930_btsco_init(struct snd_soc_pcm_runtime *rtd)
422{
423 int err = 0;
424 struct snd_soc_platform *platform = rtd->platform;
425
426 err = snd_soc_add_platform_controls(platform,
427 int_btsco_rate_mixer_controls,
428 ARRAY_SIZE(int_btsco_rate_mixer_controls));
429 if (err < 0)
430 return err;
431 return 0;
432}
433
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800434static void *def_sitar_mbhc_cal(void)
435{
436 void *sitar_cal;
437 struct sitar_mbhc_btn_detect_cfg *btn_cfg;
438 u16 *btn_low, *btn_high;
439 u8 *n_ready, *n_cic, *gain;
440
441 sitar_cal = kzalloc(SITAR_MBHC_CAL_SIZE(SITAR_MBHC_DEF_BUTTONS,
442 SITAR_MBHC_DEF_RLOADS),
443 GFP_KERNEL);
444 if (!sitar_cal) {
445 pr_err("%s: out of memory\n", __func__);
446 return NULL;
447 }
448
449#define S(X, Y) ((SITAR_MBHC_CAL_GENERAL_PTR(sitar_cal)->X) = (Y))
450 S(t_ldoh, 100);
451 S(t_bg_fast_settle, 100);
452 S(t_shutdown_plug_rem, 255);
453 S(mbhc_nsa, 4);
454 S(mbhc_navg, 4);
455#undef S
456#define S(X, Y) ((SITAR_MBHC_CAL_PLUG_DET_PTR(sitar_cal)->X) = (Y))
457 S(mic_current, SITAR_PID_MIC_5_UA);
458 S(hph_current, SITAR_PID_MIC_5_UA);
459 S(t_mic_pid, 100);
460 S(t_ins_complete, 250);
461 S(t_ins_retry, 200);
462#undef S
463#define S(X, Y) ((SITAR_MBHC_CAL_PLUG_TYPE_PTR(sitar_cal)->X) = (Y))
464 S(v_no_mic, 30);
465 S(v_hs_max, 1550);
466#undef S
467#define S(X, Y) ((SITAR_MBHC_CAL_BTN_DET_PTR(sitar_cal)->X) = (Y))
468 S(c[0], 62);
469 S(c[1], 124);
470 S(nc, 1);
471 S(n_meas, 3);
472 S(mbhc_nsc, 11);
473 S(n_btn_meas, 1);
474 S(n_btn_con, 2);
475 S(num_btn, SITAR_MBHC_DEF_BUTTONS);
476 S(v_btn_press_delta_sta, 100);
477 S(v_btn_press_delta_cic, 50);
478#undef S
479 btn_cfg = SITAR_MBHC_CAL_BTN_DET_PTR(sitar_cal);
480 btn_low = sitar_mbhc_cal_btn_det_mp(btn_cfg, SITAR_BTN_DET_V_BTN_LOW);
481 btn_high = sitar_mbhc_cal_btn_det_mp(btn_cfg, SITAR_BTN_DET_V_BTN_HIGH);
482 btn_low[0] = -50;
483 btn_high[0] = 10;
484 btn_low[1] = 11;
485 btn_high[1] = 38;
486 btn_low[2] = 39;
487 btn_high[2] = 64;
488 btn_low[3] = 65;
489 btn_high[3] = 91;
490 btn_low[4] = 92;
491 btn_high[4] = 115;
492 btn_low[5] = 116;
493 btn_high[5] = 141;
494 btn_low[6] = 142;
495 btn_high[6] = 163;
496 btn_low[7] = 164;
497 btn_high[7] = 250;
498 n_ready = sitar_mbhc_cal_btn_det_mp(btn_cfg, SITAR_BTN_DET_N_READY);
499 n_ready[0] = 48;
500 n_ready[1] = 38;
501 n_cic = sitar_mbhc_cal_btn_det_mp(btn_cfg, SITAR_BTN_DET_N_CIC);
502 n_cic[0] = 60;
503 n_cic[1] = 47;
504 gain = sitar_mbhc_cal_btn_det_mp(btn_cfg, SITAR_BTN_DET_GAIN);
505 gain[0] = 11;
506 gain[1] = 9;
507
508 return sitar_cal;
509}
510
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530511static int msm8930_hw_params(struct snd_pcm_substream *substream,
512 struct snd_pcm_hw_params *params)
513{
514 struct snd_soc_pcm_runtime *rtd = substream->private_data;
515 struct snd_soc_dai *codec_dai = rtd->codec_dai;
516 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
517 int ret = 0;
518 unsigned int rx_ch[SLIM_MAX_RX_PORTS], tx_ch[SLIM_MAX_TX_PORTS];
519 unsigned int rx_ch_cnt = 0, tx_ch_cnt = 0;
520
521 pr_debug("%s: ch=%d\n", __func__,
522 msm8930_slim_0_rx_ch);
523 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
524 ret = snd_soc_dai_get_channel_map(codec_dai,
525 &tx_ch_cnt, tx_ch, &rx_ch_cnt , rx_ch);
526 if (ret < 0) {
527 pr_err("%s: failed to get codec chan map\n", __func__);
528 goto end;
529 }
530
531 ret = snd_soc_dai_set_channel_map(cpu_dai, 0, 0,
532 msm8930_slim_0_rx_ch, rx_ch);
533 if (ret < 0) {
534 pr_err("%s: failed to set cpu chan map\n", __func__);
535 goto end;
536 }
537 ret = snd_soc_dai_set_channel_map(codec_dai, 0, 0,
538 msm8930_slim_0_rx_ch, rx_ch);
539 if (ret < 0) {
540 pr_err("%s: failed to set codec channel map\n",
541 __func__);
542 goto end;
543 }
544 } else {
545 ret = snd_soc_dai_get_channel_map(codec_dai,
546 &tx_ch_cnt, tx_ch, &rx_ch_cnt , rx_ch);
547 if (ret < 0) {
548 pr_err("%s: failed to get codec chan map\n", __func__);
549 goto end;
550 }
551 ret = snd_soc_dai_set_channel_map(cpu_dai,
552 msm8930_slim_0_tx_ch, tx_ch, 0 , 0);
553 if (ret < 0) {
554 pr_err("%s: failed to set cpu chan map\n", __func__);
555 goto end;
556 }
557 ret = snd_soc_dai_set_channel_map(codec_dai,
558 msm8930_slim_0_tx_ch, tx_ch, 0, 0);
559 if (ret < 0) {
560 pr_err("%s: failed to set codec channel map\n",
561 __func__);
562 goto end;
563 }
564
565 }
566end:
567 return ret;
568}
569
570static int msm8930_audrx_init(struct snd_soc_pcm_runtime *rtd)
571{
572 int err;
573 struct snd_soc_codec *codec = rtd->codec;
574 struct snd_soc_dapm_context *dapm = &codec->dapm;
575 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
576
577 pr_debug("%s()\n", __func__);
578
579
580 rtd->pmdown_time = 0;
581
582 err = snd_soc_add_controls(codec, sitar_msm8930_controls,
583 ARRAY_SIZE(sitar_msm8930_controls));
584 if (err < 0)
585 return err;
586
587 snd_soc_dapm_new_controls(dapm, msm8930_dapm_widgets,
588 ARRAY_SIZE(msm8930_dapm_widgets));
589
590 snd_soc_dapm_add_routes(dapm, common_audio_map,
591 ARRAY_SIZE(common_audio_map));
592
593 snd_soc_dapm_enable_pin(dapm, "Ext Spk Left Pos");
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800594 snd_soc_dapm_enable_pin(dapm, "Ext Spk Left Neg");
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530595
596 snd_soc_dapm_sync(dapm);
597
598 err = snd_soc_jack_new(codec, "Headset Jack",
599 (SND_JACK_HEADSET | SND_JACK_OC_HPHL | SND_JACK_OC_HPHR),
600 &hs_jack);
601 if (err) {
602 pr_err("failed to create new jack\n");
603 return err;
604 }
605
606 err = snd_soc_jack_new(codec, "Button Jack",
607 SND_JACK_BTN_0, &button_jack);
608 if (err) {
609 pr_err("failed to create new jack\n");
610 return err;
611 }
612 codec_clk = clk_get(cpu_dai->dev, "osr_clk");
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800613
Bhalchandra Gajare466aafe2012-05-02 17:55:26 -0700614 mbhc_cfg.gpio = 37;
615 mbhc_cfg.gpio_irq = gpio_to_irq(mbhc_cfg.gpio);
616 sitar_hs_detect(codec, &mbhc_cfg);
617
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530618 return 0;
619}
620
621static struct snd_soc_dsp_link lpa_fe_media = {
622 .playback = true,
623 .trigger = {
624 SND_SOC_DSP_TRIGGER_POST,
625 SND_SOC_DSP_TRIGGER_POST
626 },
627};
628
629static struct snd_soc_dsp_link fe_media = {
630 .playback = true,
631 .capture = true,
632 .trigger = {
633 SND_SOC_DSP_TRIGGER_POST,
634 SND_SOC_DSP_TRIGGER_POST
635 },
636};
637
638static struct snd_soc_dsp_link slimbus0_hl_media = {
639 .playback = true,
640 .capture = true,
641 .trigger = {
642 SND_SOC_DSP_TRIGGER_POST,
643 SND_SOC_DSP_TRIGGER_POST
644 },
645};
646
647static struct snd_soc_dsp_link int_fm_hl_media = {
648 .playback = true,
649 .capture = true,
650 .trigger = {
651 SND_SOC_DSP_TRIGGER_POST,
652 SND_SOC_DSP_TRIGGER_POST
653 },
654};
655
656/* bi-directional media definition for hostless PCM device */
657static struct snd_soc_dsp_link bidir_hl_media = {
658 .playback = true,
659 .capture = true,
660 .trigger = {
661 SND_SOC_DSP_TRIGGER_POST,
662 SND_SOC_DSP_TRIGGER_POST
663 },
664};
665
666static struct snd_soc_dsp_link hdmi_rx_hl = {
667 .playback = true,
668 .trigger = {
669 SND_SOC_DSP_TRIGGER_POST,
670 SND_SOC_DSP_TRIGGER_POST
671 },
672};
673
674static int msm8930_slim_0_rx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
675 struct snd_pcm_hw_params *params)
676{
677 struct snd_interval *rate = hw_param_interval(params,
678 SNDRV_PCM_HW_PARAM_RATE);
679
680 struct snd_interval *channels = hw_param_interval(params,
681 SNDRV_PCM_HW_PARAM_CHANNELS);
682
683 pr_debug("%s()\n", __func__);
684 rate->min = rate->max = 48000;
685 channels->min = channels->max = msm8930_slim_0_rx_ch;
686
687 return 0;
688}
689
690static int msm8930_slim_0_tx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
691 struct snd_pcm_hw_params *params)
692{
693 struct snd_interval *rate = hw_param_interval(params,
694 SNDRV_PCM_HW_PARAM_RATE);
695
696 struct snd_interval *channels = hw_param_interval(params,
697 SNDRV_PCM_HW_PARAM_CHANNELS);
698
699 pr_debug("%s()\n", __func__);
700 rate->min = rate->max = 48000;
701 channels->min = channels->max = msm8930_slim_0_tx_ch;
702
703 return 0;
704}
705
706static int msm8930_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
707 struct snd_pcm_hw_params *params)
708{
709 struct snd_interval *rate = hw_param_interval(params,
710 SNDRV_PCM_HW_PARAM_RATE);
711
712 pr_debug("%s()\n", __func__);
713 rate->min = rate->max = 48000;
714
715 return 0;
716}
717
718static int msm8930_hdmi_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
719 struct snd_pcm_hw_params *params)
720{
721 struct snd_interval *rate = hw_param_interval(params,
722 SNDRV_PCM_HW_PARAM_RATE);
723
724 struct snd_interval *channels = hw_param_interval(params,
725 SNDRV_PCM_HW_PARAM_CHANNELS);
726
727 rate->min = rate->max = 48000;
728 channels->min = channels->max = 2;
729
730 return 0;
731}
732
733static int msm8930_btsco_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
734 struct snd_pcm_hw_params *params)
735{
736 struct snd_interval *rate = hw_param_interval(params,
737 SNDRV_PCM_HW_PARAM_RATE);
738
739 struct snd_interval *channels = hw_param_interval(params,
740 SNDRV_PCM_HW_PARAM_CHANNELS);
741
742 rate->min = rate->max = msm8930_btsco_rate;
743 channels->min = channels->max = msm8930_btsco_ch;
744
745 return 0;
746}
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530747
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530748static int msm8930_startup(struct snd_pcm_substream *substream)
749{
750 pr_debug("%s(): substream = %s stream = %d\n", __func__,
751 substream->name, substream->stream);
752 return 0;
753}
754
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530755static void msm8930_shutdown(struct snd_pcm_substream *substream)
756{
757 pr_debug("%s(): substream = %s stream = %d\n", __func__,
758 substream->name, substream->stream);
759}
760
761static struct snd_soc_ops msm8930_be_ops = {
762 .startup = msm8930_startup,
763 .hw_params = msm8930_hw_params,
764 .shutdown = msm8930_shutdown,
765};
766
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530767/* Digital audio interface glue - connects codec <---> CPU */
768static struct snd_soc_dai_link msm8930_dai[] = {
769 /* FrontEnd DAI Links */
770 {
771 .name = "MSM8930 Media1",
772 .stream_name = "MultiMedia1",
773 .cpu_dai_name = "MultiMedia1",
774 .platform_name = "msm-pcm-dsp",
775 .dynamic = 1,
776 .dsp_link = &fe_media,
777 .be_id = MSM_FRONTEND_DAI_MULTIMEDIA1
778 },
779 {
780 .name = "MSM8930 Media2",
781 .stream_name = "MultiMedia2",
782 .cpu_dai_name = "MultiMedia2",
783 .platform_name = "msm-pcm-dsp",
784 .dynamic = 1,
785 .dsp_link = &fe_media,
786 .be_id = MSM_FRONTEND_DAI_MULTIMEDIA2,
787 },
788 {
789 .name = "Circuit-Switch Voice",
790 .stream_name = "CS-Voice",
791 .cpu_dai_name = "CS-VOICE",
792 .platform_name = "msm-pcm-voice",
793 .dynamic = 1,
794 .dsp_link = &fe_media,
795 .be_id = MSM_FRONTEND_DAI_CS_VOICE,
796 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
797 .ignore_suspend = 1,
798 },
799 {
800 .name = "MSM VoIP",
801 .stream_name = "VoIP",
802 .cpu_dai_name = "VoIP",
803 .platform_name = "msm-voip-dsp",
804 .dynamic = 1,
805 .dsp_link = &fe_media,
806 .be_id = MSM_FRONTEND_DAI_VOIP,
807 },
808 {
809 .name = "MSM8930 LPA",
810 .stream_name = "LPA",
811 .cpu_dai_name = "MultiMedia3",
812 .platform_name = "msm-pcm-lpa",
813 .dynamic = 1,
814 .dsp_link = &lpa_fe_media,
815 .be_id = MSM_FRONTEND_DAI_MULTIMEDIA3,
816 },
817 /* Hostless PMC purpose */
818 {
819 .name = "SLIMBUS_0 Hostless",
820 .stream_name = "SLIMBUS_0 Hostless",
821 .cpu_dai_name = "SLIMBUS0_HOSTLESS",
822 .platform_name = "msm-pcm-hostless",
823 .dynamic = 1,
824 .dsp_link = &slimbus0_hl_media,
825 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
826 .ignore_suspend = 1,
827 /* .be_id = do not care */
828 },
829 {
830 .name = "INT_FM Hostless",
831 .stream_name = "INT_FM Hostless",
832 .cpu_dai_name = "INT_FM_HOSTLESS",
833 .platform_name = "msm-pcm-hostless",
834 .dynamic = 1,
835 .dsp_link = &int_fm_hl_media,
836 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
837 .ignore_suspend = 1,
838 /* .be_id = do not care */
839 },
840 {
841 .name = "MSM AFE-PCM RX",
842 .stream_name = "AFE-PROXY RX",
843 .cpu_dai_name = "msm-dai-q6.241",
844 .codec_name = "msm-stub-codec.1",
845 .codec_dai_name = "msm-stub-rx",
846 .platform_name = "msm-pcm-afe",
847 .ignore_suspend = 1,
848 },
849 {
850 .name = "MSM AFE-PCM TX",
851 .stream_name = "AFE-PROXY TX",
852 .cpu_dai_name = "msm-dai-q6.240",
853 .codec_name = "msm-stub-codec.1",
854 .codec_dai_name = "msm-stub-tx",
855 .platform_name = "msm-pcm-afe",
856 .ignore_suspend = 1,
857 },
858 {
859 .name = "MSM8930 Compr",
860 .stream_name = "COMPR",
861 .cpu_dai_name = "MultiMedia4",
862 .platform_name = "msm-compr-dsp",
863 .dynamic = 1,
864 .dsp_link = &lpa_fe_media,
865 .be_id = MSM_FRONTEND_DAI_MULTIMEDIA4,
866 },
867 {
868 .name = "AUXPCM Hostless",
869 .stream_name = "AUXPCM Hostless",
870 .cpu_dai_name = "AUXPCM_HOSTLESS",
871 .platform_name = "msm-pcm-hostless",
872 .dynamic = 1,
873 .dsp_link = &bidir_hl_media,
874 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
875 .ignore_suspend = 1,
876 },
877 /* HDMI Hostless */
878 {
879 .name = "HDMI_RX_HOSTLESS",
880 .stream_name = "HDMI_RX_HOSTLESS",
881 .cpu_dai_name = "HDMI_HOSTLESS",
882 .platform_name = "msm-pcm-hostless",
883 .dynamic = 1,
884 .dsp_link = &hdmi_rx_hl,
885 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
886 .no_codec = 1,
887 .ignore_suspend = 1,
888 },
889 /* Backend DAI Links */
890 {
891 .name = LPASS_BE_SLIMBUS_0_RX,
892 .stream_name = "Slimbus Playback",
893 .cpu_dai_name = "msm-dai-q6.16384",
894 .platform_name = "msm-pcm-routing",
895 .codec_name = "sitar_codec",
896 .codec_dai_name = "sitar_rx1",
897 .no_pcm = 1,
898 .be_id = MSM_BACKEND_DAI_SLIMBUS_0_RX,
899 .init = &msm8930_audrx_init,
900 .be_hw_params_fixup = msm8930_slim_0_rx_be_hw_params_fixup,
901 .ops = &msm8930_be_ops,
902 },
903 {
904 .name = LPASS_BE_SLIMBUS_0_TX,
905 .stream_name = "Slimbus Capture",
906 .cpu_dai_name = "msm-dai-q6.16385",
907 .platform_name = "msm-pcm-routing",
908 .codec_name = "sitar_codec",
909 .codec_dai_name = "sitar_tx1",
910 .no_pcm = 1,
911 .be_id = MSM_BACKEND_DAI_SLIMBUS_0_TX,
912 .be_hw_params_fixup = msm8930_slim_0_tx_be_hw_params_fixup,
913 .ops = &msm8930_be_ops,
914 },
915 /* Backend BT/FM DAI Links */
916 {
917 .name = LPASS_BE_INT_BT_SCO_RX,
918 .stream_name = "Internal BT-SCO Playback",
919 .cpu_dai_name = "msm-dai-q6.12288",
920 .platform_name = "msm-pcm-routing",
921 .codec_name = "msm-stub-codec.1",
922 .codec_dai_name = "msm-stub-rx",
923 .init = &msm8930_btsco_init,
924 .no_pcm = 1,
925 .be_id = MSM_BACKEND_DAI_INT_BT_SCO_RX,
926 .be_hw_params_fixup = msm8930_btsco_be_hw_params_fixup,
927 },
928 {
929 .name = LPASS_BE_INT_BT_SCO_TX,
930 .stream_name = "Internal BT-SCO Capture",
931 .cpu_dai_name = "msm-dai-q6.12289",
932 .platform_name = "msm-pcm-routing",
933 .codec_name = "msm-stub-codec.1",
934 .codec_dai_name = "msm-stub-tx",
935 .no_pcm = 1,
936 .be_id = MSM_BACKEND_DAI_INT_BT_SCO_TX,
937 .be_hw_params_fixup = msm8930_btsco_be_hw_params_fixup,
938 },
939 {
940 .name = LPASS_BE_INT_FM_RX,
941 .stream_name = "Internal FM Playback",
942 .cpu_dai_name = "msm-dai-q6.12292",
943 .platform_name = "msm-pcm-routing",
944 .codec_name = "msm-stub-codec.1",
945 .codec_dai_name = "msm-stub-rx",
946 .no_pcm = 1,
947 .be_id = MSM_BACKEND_DAI_INT_FM_RX,
948 .be_hw_params_fixup = msm8930_be_hw_params_fixup,
949 },
950 {
951 .name = LPASS_BE_INT_FM_TX,
952 .stream_name = "Internal FM Capture",
953 .cpu_dai_name = "msm-dai-q6.12293",
954 .platform_name = "msm-pcm-routing",
955 .codec_name = "msm-stub-codec.1",
956 .codec_dai_name = "msm-stub-tx",
957 .no_pcm = 1,
958 .be_id = MSM_BACKEND_DAI_INT_FM_TX,
959 .be_hw_params_fixup = msm8930_be_hw_params_fixup,
960 },
961 /* HDMI BACK END DAI Link */
962 {
963 .name = LPASS_BE_HDMI,
964 .stream_name = "HDMI Playback",
965 .cpu_dai_name = "msm-dai-q6-hdmi.8",
966 .platform_name = "msm-pcm-routing",
967 .codec_name = "msm-stub-codec.1",
968 .codec_dai_name = "msm-stub-rx",
969 .no_pcm = 1,
970 .no_codec = 1,
971 .be_id = MSM_BACKEND_DAI_HDMI_RX,
972 .be_hw_params_fixup = msm8930_hdmi_be_hw_params_fixup,
973 },
974 /* Backend AFE DAI Links */
975 {
976 .name = LPASS_BE_AFE_PCM_RX,
977 .stream_name = "AFE Playback",
978 .cpu_dai_name = "msm-dai-q6.224",
979 .platform_name = "msm-pcm-routing",
980 .codec_name = "msm-stub-codec.1",
981 .codec_dai_name = "msm-stub-rx",
982 .no_codec = 1,
983 .no_pcm = 1,
984 .be_id = MSM_BACKEND_DAI_AFE_PCM_RX,
985 },
986 {
987 .name = LPASS_BE_AFE_PCM_TX,
988 .stream_name = "AFE Capture",
989 .cpu_dai_name = "msm-dai-q6.225",
990 .platform_name = "msm-pcm-routing",
991 .codec_name = "msm-stub-codec.1",
992 .codec_dai_name = "msm-stub-tx",
993 .no_codec = 1,
994 .no_pcm = 1,
995 .be_id = MSM_BACKEND_DAI_AFE_PCM_TX,
996 },
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530997 /* Incall Music BACK END DAI Link */
998 {
999 .name = LPASS_BE_VOICE_PLAYBACK_TX,
1000 .stream_name = "Voice Farend Playback",
1001 .cpu_dai_name = "msm-dai-q6.32773",
1002 .platform_name = "msm-pcm-routing",
1003 .codec_name = "msm-stub-codec.1",
1004 .codec_dai_name = "msm-stub-rx",
1005 .no_pcm = 1,
1006 .no_codec = 1,
1007 .be_id = MSM_BACKEND_DAI_VOICE_PLAYBACK_TX,
1008 .be_hw_params_fixup = msm8930_be_hw_params_fixup,
1009 },
1010 /* Incall Record Uplink BACK END DAI Link */
1011 {
1012 .name = LPASS_BE_INCALL_RECORD_TX,
1013 .stream_name = "Voice Uplink Capture",
1014 .cpu_dai_name = "msm-dai-q6.32772",
1015 .platform_name = "msm-pcm-routing",
1016 .codec_name = "msm-stub-codec.1",
1017 .codec_dai_name = "msm-stub-tx",
1018 .no_pcm = 1,
1019 .no_codec = 1,
1020 .be_id = MSM_BACKEND_DAI_INCALL_RECORD_TX,
1021 .be_hw_params_fixup = msm8930_be_hw_params_fixup,
1022 },
1023 /* Incall Record Downlink BACK END DAI Link */
1024 {
1025 .name = LPASS_BE_INCALL_RECORD_RX,
1026 .stream_name = "Voice Downlink Capture",
1027 .cpu_dai_name = "msm-dai-q6.32771",
1028 .platform_name = "msm-pcm-routing",
1029 .codec_name = "msm-stub-codec.1",
1030 .codec_dai_name = "msm-stub-tx",
1031 .no_pcm = 1,
1032 .no_codec = 1,
1033 .be_id = MSM_BACKEND_DAI_INCALL_RECORD_RX,
1034 .be_hw_params_fixup = msm8930_be_hw_params_fixup,
1035 },
1036};
1037
1038struct snd_soc_card snd_soc_card_msm8930 = {
1039 .name = "msm8930-sitar-snd-card",
1040 .dai_link = msm8930_dai,
1041 .num_links = ARRAY_SIZE(msm8930_dai),
1042};
1043
1044static struct platform_device *msm8930_snd_device;
1045
1046static int msm8930_configure_headset_mic_gpios(void)
1047{
1048 int ret;
1049 ret = gpio_request(80, "US_EURO_SWITCH");
1050 if (ret) {
1051 pr_err("%s: Failed to request gpio 80\n", __func__);
1052 return ret;
1053 }
1054 ret = gpio_direction_output(80, 0);
1055 if (ret) {
1056 pr_err("%s: Unable to set direction\n", __func__);
1057 gpio_free(80);
1058 }
1059 msm8930_headset_gpios_configured = 0;
1060 return 0;
1061}
1062static void msm8930_free_headset_mic_gpios(void)
1063{
1064 if (msm8930_headset_gpios_configured)
1065 gpio_free(80);
1066}
1067
1068static int __init msm8930_audio_init(void)
1069{
1070 int ret;
1071
1072 if (!cpu_is_msm8930()) {
1073 pr_err("%s: Not the right machine type\n", __func__);
1074 return -ENODEV ;
1075 }
Bhalchandra Gajare466aafe2012-05-02 17:55:26 -07001076 mbhc_cfg.calibration = def_sitar_mbhc_cal();
1077 if (!mbhc_cfg.calibration) {
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -08001078 pr_err("Calibration data allocation failed\n");
1079 return -ENOMEM;
1080 }
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301081
1082 msm8930_snd_device = platform_device_alloc("soc-audio", 0);
1083 if (!msm8930_snd_device) {
1084 pr_err("Platform device allocation failed\n");
Bhalchandra Gajare466aafe2012-05-02 17:55:26 -07001085 kfree(mbhc_cfg.calibration);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301086 return -ENOMEM;
1087 }
1088
1089 platform_set_drvdata(msm8930_snd_device, &snd_soc_card_msm8930);
1090 ret = platform_device_add(msm8930_snd_device);
1091 if (ret) {
1092 platform_device_put(msm8930_snd_device);
Bhalchandra Gajare466aafe2012-05-02 17:55:26 -07001093 kfree(mbhc_cfg.calibration);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301094 return ret;
1095 }
1096
1097 if (msm8930_configure_headset_mic_gpios()) {
1098 pr_err("%s Fail to configure headset mic gpios\n", __func__);
1099 msm8930_headset_gpios_configured = 0;
1100 } else
1101 msm8930_headset_gpios_configured = 1;
1102
1103 return ret;
1104
1105}
1106module_init(msm8930_audio_init);
1107
1108static void __exit msm8930_audio_exit(void)
1109{
1110 if (!cpu_is_msm8930()) {
1111 pr_err("%s: Not the right machine type\n", __func__);
1112 return ;
1113 }
1114 msm8930_free_headset_mic_gpios();
1115 platform_device_unregister(msm8930_snd_device);
Bhalchandra Gajare466aafe2012-05-02 17:55:26 -07001116 kfree(mbhc_cfg.calibration);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301117}
1118module_exit(msm8930_audio_exit);
1119
1120MODULE_DESCRIPTION("ALSA SoC MSM8930");
1121MODULE_LICENSE("GPL v2");