blob: b31ed65acd8725117034c321e0c11a2e669be441 [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
Bhalchandra Gajare98a28cd2012-05-16 12:00:20 -070041#define SPKR_BOOST_GPIO 15
Asish Bhattacharyab86c3472012-02-15 08:31:52 +053042#define SITAR_EXT_CLK_RATE 12288000
43
44#define SITAR_MBHC_DEF_BUTTONS 3
45#define SITAR_MBHC_DEF_RLOADS 5
46
47static int msm8930_spk_control;
48static int msm8930_slim_0_rx_ch = 1;
49static int msm8930_slim_0_tx_ch = 1;
50
Asish Bhattacharyac71827a2012-03-05 10:11:45 -080051static int msm8930_ext_spk_pamp;
Asish Bhattacharyab86c3472012-02-15 08:31:52 +053052static int msm8930_btsco_rate = BTSCO_RATE_8KHZ;
53static int msm8930_btsco_ch = 1;
54
55static struct clk *codec_clk;
56static int clk_users;
57
58static int msm8930_headset_gpios_configured;
59
60static struct snd_soc_jack hs_jack;
61static struct snd_soc_jack button_jack;
Bhalchandra Gajare466aafe2012-05-02 17:55:26 -070062
63static int msm8930_enable_codec_ext_clk(
64 struct snd_soc_codec *codec, int enable,
65 bool dapm);
66
67static struct sitar_mbhc_config mbhc_cfg = {
68 .headset_jack = &hs_jack,
69 .button_jack = &button_jack,
70 .read_fw_bin = false,
71 .calibration = NULL,
72 .micbias = SITAR_MICBIAS2,
73 .mclk_cb_fn = msm8930_enable_codec_ext_clk,
74 .mclk_rate = SITAR_EXT_CLK_RATE,
75 .gpio = 0,
76 .gpio_irq = 0,
77 .gpio_level_insert = 1,
78};
79
Asish Bhattacharyab86c3472012-02-15 08:31:52 +053080
81static void msm8930_ext_control(struct snd_soc_codec *codec)
82{
83 struct snd_soc_dapm_context *dapm = &codec->dapm;
84
85 pr_debug("%s: msm8930_spk_control = %d", __func__, msm8930_spk_control);
86 if (msm8930_spk_control == MSM8930_SPK_ON) {
87 snd_soc_dapm_enable_pin(dapm, "Ext Spk Left Pos");
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -080088 snd_soc_dapm_enable_pin(dapm, "Ext Spk left Neg");
Asish Bhattacharyab86c3472012-02-15 08:31:52 +053089 } else {
90 snd_soc_dapm_disable_pin(dapm, "Ext Spk Left Pos");
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -080091 snd_soc_dapm_disable_pin(dapm, "Ext Spk Left Neg");
Asish Bhattacharyab86c3472012-02-15 08:31:52 +053092 }
93
94 snd_soc_dapm_sync(dapm);
95}
96
97static int msm8930_get_spk(struct snd_kcontrol *kcontrol,
98 struct snd_ctl_elem_value *ucontrol)
99{
100 pr_debug("%s: msm8930_spk_control = %d", __func__, msm8930_spk_control);
101 ucontrol->value.integer.value[0] = msm8930_spk_control;
102 return 0;
103}
104static int msm8930_set_spk(struct snd_kcontrol *kcontrol,
105 struct snd_ctl_elem_value *ucontrol)
106{
107 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
108
109 pr_debug("%s()\n", __func__);
110 if (msm8930_spk_control == ucontrol->value.integer.value[0])
111 return 0;
112
113 msm8930_spk_control = ucontrol->value.integer.value[0];
114 msm8930_ext_control(codec);
115 return 1;
116}
117
Asish Bhattacharyac71827a2012-03-05 10:11:45 -0800118static void msm8960_ext_spk_power_amp_on(u32 spk)
119{
Bhalchandra Gajare98a28cd2012-05-16 12:00:20 -0700120 int ret = 0;
121
Asish Bhattacharyac71827a2012-03-05 10:11:45 -0800122 if (spk & (SPK_AMP_POS | SPK_AMP_NEG)) {
123 if ((msm8930_ext_spk_pamp & SPK_AMP_POS) &&
124 (msm8930_ext_spk_pamp & SPK_AMP_NEG)) {
125
126 pr_debug("%s() External Bottom Speaker Ampl already "
127 "turned on. spk = 0x%08x\n", __func__, spk);
128 return;
129 }
130
131 msm8930_ext_spk_pamp |= spk;
132
133 if ((msm8930_ext_spk_pamp & SPK_AMP_POS) &&
134 (msm8930_ext_spk_pamp & SPK_AMP_NEG)) {
135
Bhalchandra Gajare98a28cd2012-05-16 12:00:20 -0700136 if (machine_is_msm8930_mtp()
137 || machine_is_msm8930_fluid()) {
138 pr_debug("%s: Configure Speaker Boost GPIO %u",
139 __func__, SPKR_BOOST_GPIO);
140 ret = gpio_request(SPKR_BOOST_GPIO,
141 "SPKR_BOOST_EN");
142 if (ret) {
143 pr_err("%s: Failed to configure speaker boost "
144 "gpio %u\n", __func__, SPKR_BOOST_GPIO);
145 return;
146 }
147
148 pr_debug("%s: Enable Speaker boost gpio %u\n",
149 __func__, SPKR_BOOST_GPIO);
150 gpio_direction_output(SPKR_BOOST_GPIO, 1);
151 }
152
Asish Bhattacharyac71827a2012-03-05 10:11:45 -0800153 pm8xxx_spk_enable(MSM8930_SPK_ON);
154 pr_debug("%s: slepping 4 ms after turning on external "
155 " Left Speaker Ampl\n", __func__);
156 usleep_range(4000, 4000);
157 }
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
167static void msm8960_ext_spk_power_amp_off(u32 spk)
168{
169 if (spk & (SPK_AMP_POS | SPK_AMP_NEG)) {
170 if (!msm8930_ext_spk_pamp)
171 return;
Bhalchandra Gajare98a28cd2012-05-16 12:00:20 -0700172 if (machine_is_msm8930_mtp()
173 || machine_is_msm8930_fluid()) {
174 pr_debug("%s: Free speaker boost gpio %u\n",
175 __func__, SPKR_BOOST_GPIO);
176 gpio_direction_output(SPKR_BOOST_GPIO, 0);
177 gpio_free(SPKR_BOOST_GPIO);
178 }
Asish Bhattacharyac71827a2012-03-05 10:11:45 -0800179
180 pm8xxx_spk_enable(MSM8930_SPK_OFF);
181 msm8930_ext_spk_pamp = 0;
182 pr_debug("%s: slepping 4 ms after turning on external "
183 " Left Speaker Ampl\n", __func__);
184 usleep_range(4000, 4000);
185
186 } else {
187
188 pr_err("%s: ERROR : Invalid External Speaker Ampl. spk = 0x%08x\n",
189 __func__, spk);
190 return;
191 }
192}
193
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530194static int msm8930_spkramp_event(struct snd_soc_dapm_widget *w,
195 struct snd_kcontrol *k, int event)
196{
197 pr_debug("%s() %x\n", __func__, SND_SOC_DAPM_EVENT_ON(event));
Asish Bhattacharyac71827a2012-03-05 10:11:45 -0800198 if (SND_SOC_DAPM_EVENT_ON(event)) {
199 if (!strncmp(w->name, "Ext Spk Left Pos", 17))
200 msm8960_ext_spk_power_amp_on(SPK_AMP_POS);
201 else if (!strncmp(w->name, "Ext Spk Left Neg", 17))
202 msm8960_ext_spk_power_amp_on(SPK_AMP_NEG);
203 else {
204 pr_err("%s() Invalid Speaker Widget = %s\n",
205 __func__, w->name);
206 return -EINVAL;
207 }
208 } else {
209 if (!strncmp(w->name, "Ext Spk Left Pos", 17))
210 msm8960_ext_spk_power_amp_off(SPK_AMP_POS);
211 else if (!strncmp(w->name, "Ext Spk Left Neg", 17))
212 msm8960_ext_spk_power_amp_off(SPK_AMP_NEG);
213 else {
214 pr_err("%s() Invalid Speaker Widget = %s\n",
215 __func__, w->name);
216 return -EINVAL;
217 }
218 }
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530219 return 0;
220}
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800221
Bhalchandra Gajare466aafe2012-05-02 17:55:26 -0700222static int msm8930_enable_codec_ext_clk(
223 struct snd_soc_codec *codec, int enable,
224 bool dapm)
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530225{
226 pr_debug("%s: enable = %d\n", __func__, enable);
227 if (enable) {
228 clk_users++;
229 pr_debug("%s: clk_users = %d\n", __func__, clk_users);
230 if (clk_users != 1)
231 return 0;
232
233 if (codec_clk) {
234 clk_set_rate(codec_clk, SITAR_EXT_CLK_RATE);
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800235 clk_prepare_enable(codec_clk);
Bhalchandra Gajare466aafe2012-05-02 17:55:26 -0700236 sitar_mclk_enable(codec, 1, dapm);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530237 } else {
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800238 pr_err("%s: Error setting Sitar MCLK\n", __func__);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530239 clk_users--;
240 return -EINVAL;
241 }
242 } else {
243 pr_debug("%s: clk_users = %d\n", __func__, clk_users);
244 if (clk_users == 0)
245 return 0;
246 clk_users--;
247 if (!clk_users) {
248 pr_debug("%s: disabling MCLK. clk_users = %d\n",
249 __func__, clk_users);
Bhalchandra Gajare466aafe2012-05-02 17:55:26 -0700250 sitar_mclk_enable(codec, 0, dapm);
Bhalchandra Gajare2776af12012-04-27 16:59:39 -0700251 clk_disable_unprepare(codec_clk);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530252 }
253 }
254 return 0;
255}
256
257static int msm8930_mclk_event(struct snd_soc_dapm_widget *w,
258 struct snd_kcontrol *kcontrol, int event)
259{
260 pr_debug("%s: event = %d\n", __func__, event);
261
262 switch (event) {
263 case SND_SOC_DAPM_PRE_PMU:
Bhalchandra Gajare466aafe2012-05-02 17:55:26 -0700264 return msm8930_enable_codec_ext_clk(w->codec, 1, true);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530265 case SND_SOC_DAPM_POST_PMD:
Bhalchandra Gajare466aafe2012-05-02 17:55:26 -0700266 return msm8930_enable_codec_ext_clk(w->codec, 0, true);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530267 }
268 return 0;
269}
270
271static const struct snd_soc_dapm_widget msm8930_dapm_widgets[] = {
272
273 SND_SOC_DAPM_SUPPLY("MCLK", SND_SOC_NOPM, 0, 0,
274 msm8930_mclk_event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
275
276 SND_SOC_DAPM_SPK("Ext Spk Left Pos", msm8930_spkramp_event),
Asish Bhattacharyac71827a2012-03-05 10:11:45 -0800277 SND_SOC_DAPM_SPK("Ext Spk Left Neg", msm8930_spkramp_event),
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530278
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530279 SND_SOC_DAPM_MIC("Headset Mic", NULL),
280 SND_SOC_DAPM_MIC("Digital Mic1", NULL),
281 SND_SOC_DAPM_MIC("ANCRight Headset Mic", NULL),
282 SND_SOC_DAPM_MIC("ANCLeft Headset Mic", NULL),
283
284 SND_SOC_DAPM_MIC("Digital Mic1", NULL),
285 SND_SOC_DAPM_MIC("Digital Mic2", NULL),
286 SND_SOC_DAPM_MIC("Digital Mic3", NULL),
287 SND_SOC_DAPM_MIC("Digital Mic4", NULL),
288
289};
290
291static const struct snd_soc_dapm_route common_audio_map[] = {
292
293 {"RX_BIAS", NULL, "MCLK"},
294 {"LDO_H", NULL, "MCLK"},
295
296 {"MIC BIAS1 Internal1", NULL, "MCLK"},
297 {"MIC BIAS2 Internal1", NULL, "MCLK"},
298
299 /* Speaker path */
300 {"Ext Spk Left Pos", NULL, "LINEOUT1"},
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800301 {"Ext Spk Left Neg", NULL, "LINEOUT2"},
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530302
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800303 /* Headset Mic */
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530304 {"AMIC2", NULL, "MIC BIAS2 Internal1"},
305 {"MIC BIAS2 Internal1", NULL, "Headset Mic"},
306
307 /* Microphone path */
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800308 {"AMIC1", NULL, "MIC BIAS2 Internal1"},
309 {"MIC BIAS2 Internal1", NULL, "ANCLeft Headset Mic"},
310
311 {"AMIC3", NULL, "MIC BIAS2 Internal1"},
312 {"MIC BIAS2 Internal1", NULL, "ANCRight Headset Mic"},
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530313
314 {"HEADPHONE", NULL, "LDO_H"},
315
316 /**
317 * The digital Mic routes are setup considering
318 * fluid as default device.
319 */
320
321 /**
322 * Digital Mic1. Front Bottom left Digital Mic on Fluid and MTP.
323 * Digital Mic GM5 on CDP mainboard.
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800324 * Conncted to DMIC2 Input on Sitar codec.
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530325 */
326 {"DMIC1", NULL, "MIC BIAS1 External"},
327 {"MIC BIAS1 External", NULL, "Digital Mic1"},
328
329 /**
330 * Digital Mic2. Front Bottom right Digital Mic on Fluid and MTP.
331 * Digital Mic GM6 on CDP mainboard.
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800332 * Conncted to DMIC1 Input on Sitar codec.
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530333 */
334 {"DMIC2", NULL, "MIC BIAS1 External"},
335 {"MIC BIAS1 External", NULL, "Digital Mic2"},
336 /**
337 * Digital Mic3. Back Bottom Digital Mic on Fluid.
338 * Digital Mic GM1 on CDP mainboard.
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800339 * Conncted to DMIC4 Input on Sitar codec.
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530340 */
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800341 {"DMIC3", NULL, "MIC BIAS1 External"},
342 {"MIC BIAS1 External", NULL, "Digital Mic3"},
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530343
344 /**
345 * Digital Mic4. Back top Digital Mic on Fluid.
346 * Digital Mic GM2 on CDP mainboard.
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800347 * Conncted to DMIC3 Input on Sitar codec.
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530348 */
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800349 {"DMIC4", NULL, "MIC BIAS1 External"},
350 {"MIC BIAS1 External", NULL, "Digital Mic4"},
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530351
352
353};
354
355static const char *spk_function[] = {"Off", "On"};
356static const char *slim0_rx_ch_text[] = {"One", "Two"};
357static const char *slim0_tx_ch_text[] = {"One", "Two", "Three", "Four"};
358
359static const struct soc_enum msm8930_enum[] = {
360 SOC_ENUM_SINGLE_EXT(2, spk_function),
361 SOC_ENUM_SINGLE_EXT(2, slim0_rx_ch_text),
362 SOC_ENUM_SINGLE_EXT(4, slim0_tx_ch_text),
363};
364
365static const char *btsco_rate_text[] = {"8000", "16000"};
366static const struct soc_enum msm8930_btsco_enum[] = {
367 SOC_ENUM_SINGLE_EXT(2, btsco_rate_text),
368};
369
370static int msm8930_slim_0_rx_ch_get(struct snd_kcontrol *kcontrol,
371 struct snd_ctl_elem_value *ucontrol)
372{
373 pr_debug("%s: msm8930_slim_0_rx_ch = %d\n", __func__,
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800374 msm8930_slim_0_rx_ch);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530375 ucontrol->value.integer.value[0] = msm8930_slim_0_rx_ch - 1;
376 return 0;
377}
378
379static int msm8930_slim_0_rx_ch_put(struct snd_kcontrol *kcontrol,
380 struct snd_ctl_elem_value *ucontrol)
381{
382 msm8930_slim_0_rx_ch = ucontrol->value.integer.value[0] + 1;
383
384 pr_debug("%s: msm8930_slim_0_rx_ch = %d\n", __func__,
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800385 msm8930_slim_0_rx_ch);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530386 return 1;
387}
388
389static int msm8930_slim_0_tx_ch_get(struct snd_kcontrol *kcontrol,
390 struct snd_ctl_elem_value *ucontrol)
391{
392 pr_debug("%s: msm8930_slim_0_tx_ch = %d\n", __func__,
393 msm8930_slim_0_tx_ch);
394 ucontrol->value.integer.value[0] = msm8930_slim_0_tx_ch - 1;
395 return 0;
396}
397
398static int msm8930_slim_0_tx_ch_put(struct snd_kcontrol *kcontrol,
399 struct snd_ctl_elem_value *ucontrol)
400{
401 msm8930_slim_0_tx_ch = ucontrol->value.integer.value[0] + 1;
402
403 pr_debug("%s: msm8930_slim_0_tx_ch = %d\n", __func__,
404 msm8930_slim_0_tx_ch);
405 return 1;
406}
407
408static int msm8930_btsco_rate_get(struct snd_kcontrol *kcontrol,
409 struct snd_ctl_elem_value *ucontrol)
410{
411 pr_debug("%s: msm8930_btsco_rate = %d", __func__, msm8930_btsco_rate);
412 ucontrol->value.integer.value[0] = msm8930_btsco_rate;
413 return 0;
414}
415
416static int msm8930_btsco_rate_put(struct snd_kcontrol *kcontrol,
417 struct snd_ctl_elem_value *ucontrol)
418{
419 switch (ucontrol->value.integer.value[0]) {
420 case 0:
421 msm8930_btsco_rate = BTSCO_RATE_8KHZ;
422 break;
423 case 1:
424 msm8930_btsco_rate = BTSCO_RATE_16KHZ;
425 break;
426 default:
427 msm8930_btsco_rate = BTSCO_RATE_8KHZ;
428 break;
429 }
430 pr_debug("%s: msm8930_btsco_rate = %d\n", __func__, msm8930_btsco_rate);
431 return 0;
432}
433
434static const struct snd_kcontrol_new sitar_msm8930_controls[] = {
435 SOC_ENUM_EXT("Speaker Function", msm8930_enum[0], msm8930_get_spk,
436 msm8930_set_spk),
437 SOC_ENUM_EXT("SLIM_0_RX Channels", msm8930_enum[1],
438 msm8930_slim_0_rx_ch_get, msm8930_slim_0_rx_ch_put),
439 SOC_ENUM_EXT("SLIM_0_TX Channels", msm8930_enum[2],
440 msm8930_slim_0_tx_ch_get, msm8930_slim_0_tx_ch_put),
441};
442
443static const struct snd_kcontrol_new int_btsco_rate_mixer_controls[] = {
444 SOC_ENUM_EXT("Internal BTSCO SampleRate", msm8930_btsco_enum[0],
445 msm8930_btsco_rate_get, msm8930_btsco_rate_put),
446};
447
448static int msm8930_btsco_init(struct snd_soc_pcm_runtime *rtd)
449{
450 int err = 0;
451 struct snd_soc_platform *platform = rtd->platform;
452
453 err = snd_soc_add_platform_controls(platform,
454 int_btsco_rate_mixer_controls,
455 ARRAY_SIZE(int_btsco_rate_mixer_controls));
456 if (err < 0)
457 return err;
458 return 0;
459}
460
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800461static void *def_sitar_mbhc_cal(void)
462{
463 void *sitar_cal;
464 struct sitar_mbhc_btn_detect_cfg *btn_cfg;
465 u16 *btn_low, *btn_high;
466 u8 *n_ready, *n_cic, *gain;
467
468 sitar_cal = kzalloc(SITAR_MBHC_CAL_SIZE(SITAR_MBHC_DEF_BUTTONS,
469 SITAR_MBHC_DEF_RLOADS),
470 GFP_KERNEL);
471 if (!sitar_cal) {
472 pr_err("%s: out of memory\n", __func__);
473 return NULL;
474 }
475
476#define S(X, Y) ((SITAR_MBHC_CAL_GENERAL_PTR(sitar_cal)->X) = (Y))
477 S(t_ldoh, 100);
478 S(t_bg_fast_settle, 100);
479 S(t_shutdown_plug_rem, 255);
480 S(mbhc_nsa, 4);
481 S(mbhc_navg, 4);
482#undef S
483#define S(X, Y) ((SITAR_MBHC_CAL_PLUG_DET_PTR(sitar_cal)->X) = (Y))
484 S(mic_current, SITAR_PID_MIC_5_UA);
485 S(hph_current, SITAR_PID_MIC_5_UA);
486 S(t_mic_pid, 100);
487 S(t_ins_complete, 250);
488 S(t_ins_retry, 200);
489#undef S
490#define S(X, Y) ((SITAR_MBHC_CAL_PLUG_TYPE_PTR(sitar_cal)->X) = (Y))
491 S(v_no_mic, 30);
492 S(v_hs_max, 1550);
493#undef S
494#define S(X, Y) ((SITAR_MBHC_CAL_BTN_DET_PTR(sitar_cal)->X) = (Y))
495 S(c[0], 62);
496 S(c[1], 124);
497 S(nc, 1);
498 S(n_meas, 3);
499 S(mbhc_nsc, 11);
500 S(n_btn_meas, 1);
501 S(n_btn_con, 2);
502 S(num_btn, SITAR_MBHC_DEF_BUTTONS);
503 S(v_btn_press_delta_sta, 100);
504 S(v_btn_press_delta_cic, 50);
505#undef S
506 btn_cfg = SITAR_MBHC_CAL_BTN_DET_PTR(sitar_cal);
507 btn_low = sitar_mbhc_cal_btn_det_mp(btn_cfg, SITAR_BTN_DET_V_BTN_LOW);
508 btn_high = sitar_mbhc_cal_btn_det_mp(btn_cfg, SITAR_BTN_DET_V_BTN_HIGH);
509 btn_low[0] = -50;
510 btn_high[0] = 10;
511 btn_low[1] = 11;
512 btn_high[1] = 38;
513 btn_low[2] = 39;
514 btn_high[2] = 64;
515 btn_low[3] = 65;
516 btn_high[3] = 91;
517 btn_low[4] = 92;
518 btn_high[4] = 115;
519 btn_low[5] = 116;
520 btn_high[5] = 141;
521 btn_low[6] = 142;
522 btn_high[6] = 163;
523 btn_low[7] = 164;
524 btn_high[7] = 250;
525 n_ready = sitar_mbhc_cal_btn_det_mp(btn_cfg, SITAR_BTN_DET_N_READY);
526 n_ready[0] = 48;
527 n_ready[1] = 38;
528 n_cic = sitar_mbhc_cal_btn_det_mp(btn_cfg, SITAR_BTN_DET_N_CIC);
529 n_cic[0] = 60;
530 n_cic[1] = 47;
531 gain = sitar_mbhc_cal_btn_det_mp(btn_cfg, SITAR_BTN_DET_GAIN);
532 gain[0] = 11;
533 gain[1] = 9;
534
535 return sitar_cal;
536}
537
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530538static int msm8930_hw_params(struct snd_pcm_substream *substream,
539 struct snd_pcm_hw_params *params)
540{
541 struct snd_soc_pcm_runtime *rtd = substream->private_data;
542 struct snd_soc_dai *codec_dai = rtd->codec_dai;
543 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
544 int ret = 0;
545 unsigned int rx_ch[SLIM_MAX_RX_PORTS], tx_ch[SLIM_MAX_TX_PORTS];
546 unsigned int rx_ch_cnt = 0, tx_ch_cnt = 0;
547
548 pr_debug("%s: ch=%d\n", __func__,
549 msm8930_slim_0_rx_ch);
550 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
551 ret = snd_soc_dai_get_channel_map(codec_dai,
552 &tx_ch_cnt, tx_ch, &rx_ch_cnt , rx_ch);
553 if (ret < 0) {
554 pr_err("%s: failed to get codec chan map\n", __func__);
555 goto end;
556 }
557
558 ret = snd_soc_dai_set_channel_map(cpu_dai, 0, 0,
559 msm8930_slim_0_rx_ch, rx_ch);
560 if (ret < 0) {
561 pr_err("%s: failed to set cpu chan map\n", __func__);
562 goto end;
563 }
564 ret = snd_soc_dai_set_channel_map(codec_dai, 0, 0,
565 msm8930_slim_0_rx_ch, rx_ch);
566 if (ret < 0) {
567 pr_err("%s: failed to set codec channel map\n",
568 __func__);
569 goto end;
570 }
571 } else {
572 ret = snd_soc_dai_get_channel_map(codec_dai,
573 &tx_ch_cnt, tx_ch, &rx_ch_cnt , rx_ch);
574 if (ret < 0) {
575 pr_err("%s: failed to get codec chan map\n", __func__);
576 goto end;
577 }
578 ret = snd_soc_dai_set_channel_map(cpu_dai,
579 msm8930_slim_0_tx_ch, tx_ch, 0 , 0);
580 if (ret < 0) {
581 pr_err("%s: failed to set cpu chan map\n", __func__);
582 goto end;
583 }
584 ret = snd_soc_dai_set_channel_map(codec_dai,
585 msm8930_slim_0_tx_ch, tx_ch, 0, 0);
586 if (ret < 0) {
587 pr_err("%s: failed to set codec channel map\n",
588 __func__);
589 goto end;
590 }
591
592 }
593end:
594 return ret;
595}
596
597static int msm8930_audrx_init(struct snd_soc_pcm_runtime *rtd)
598{
599 int err;
600 struct snd_soc_codec *codec = rtd->codec;
601 struct snd_soc_dapm_context *dapm = &codec->dapm;
602 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
603
604 pr_debug("%s()\n", __func__);
605
606
607 rtd->pmdown_time = 0;
608
609 err = snd_soc_add_controls(codec, sitar_msm8930_controls,
610 ARRAY_SIZE(sitar_msm8930_controls));
611 if (err < 0)
612 return err;
613
614 snd_soc_dapm_new_controls(dapm, msm8930_dapm_widgets,
615 ARRAY_SIZE(msm8930_dapm_widgets));
616
617 snd_soc_dapm_add_routes(dapm, common_audio_map,
618 ARRAY_SIZE(common_audio_map));
619
620 snd_soc_dapm_enable_pin(dapm, "Ext Spk Left Pos");
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800621 snd_soc_dapm_enable_pin(dapm, "Ext Spk Left Neg");
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530622
623 snd_soc_dapm_sync(dapm);
624
625 err = snd_soc_jack_new(codec, "Headset Jack",
626 (SND_JACK_HEADSET | SND_JACK_OC_HPHL | SND_JACK_OC_HPHR),
627 &hs_jack);
628 if (err) {
629 pr_err("failed to create new jack\n");
630 return err;
631 }
632
633 err = snd_soc_jack_new(codec, "Button Jack",
634 SND_JACK_BTN_0, &button_jack);
635 if (err) {
636 pr_err("failed to create new jack\n");
637 return err;
638 }
639 codec_clk = clk_get(cpu_dai->dev, "osr_clk");
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800640
Bhalchandra Gajare466aafe2012-05-02 17:55:26 -0700641 mbhc_cfg.gpio = 37;
642 mbhc_cfg.gpio_irq = gpio_to_irq(mbhc_cfg.gpio);
643 sitar_hs_detect(codec, &mbhc_cfg);
644
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530645 return 0;
646}
647
648static struct snd_soc_dsp_link lpa_fe_media = {
649 .playback = true,
650 .trigger = {
651 SND_SOC_DSP_TRIGGER_POST,
652 SND_SOC_DSP_TRIGGER_POST
653 },
654};
655
656static struct snd_soc_dsp_link fe_media = {
657 .playback = true,
658 .capture = true,
659 .trigger = {
660 SND_SOC_DSP_TRIGGER_POST,
661 SND_SOC_DSP_TRIGGER_POST
662 },
663};
664
665static struct snd_soc_dsp_link slimbus0_hl_media = {
666 .playback = true,
667 .capture = true,
668 .trigger = {
669 SND_SOC_DSP_TRIGGER_POST,
670 SND_SOC_DSP_TRIGGER_POST
671 },
672};
673
674static struct snd_soc_dsp_link int_fm_hl_media = {
675 .playback = true,
676 .capture = true,
677 .trigger = {
678 SND_SOC_DSP_TRIGGER_POST,
679 SND_SOC_DSP_TRIGGER_POST
680 },
681};
682
683/* bi-directional media definition for hostless PCM device */
684static struct snd_soc_dsp_link bidir_hl_media = {
685 .playback = true,
686 .capture = true,
687 .trigger = {
688 SND_SOC_DSP_TRIGGER_POST,
689 SND_SOC_DSP_TRIGGER_POST
690 },
691};
692
693static struct snd_soc_dsp_link hdmi_rx_hl = {
694 .playback = true,
695 .trigger = {
696 SND_SOC_DSP_TRIGGER_POST,
697 SND_SOC_DSP_TRIGGER_POST
698 },
699};
700
701static int msm8930_slim_0_rx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
702 struct snd_pcm_hw_params *params)
703{
704 struct snd_interval *rate = hw_param_interval(params,
705 SNDRV_PCM_HW_PARAM_RATE);
706
707 struct snd_interval *channels = hw_param_interval(params,
708 SNDRV_PCM_HW_PARAM_CHANNELS);
709
710 pr_debug("%s()\n", __func__);
711 rate->min = rate->max = 48000;
712 channels->min = channels->max = msm8930_slim_0_rx_ch;
713
714 return 0;
715}
716
717static int msm8930_slim_0_tx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
718 struct snd_pcm_hw_params *params)
719{
720 struct snd_interval *rate = hw_param_interval(params,
721 SNDRV_PCM_HW_PARAM_RATE);
722
723 struct snd_interval *channels = hw_param_interval(params,
724 SNDRV_PCM_HW_PARAM_CHANNELS);
725
726 pr_debug("%s()\n", __func__);
727 rate->min = rate->max = 48000;
728 channels->min = channels->max = msm8930_slim_0_tx_ch;
729
730 return 0;
731}
732
733static int msm8930_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 pr_debug("%s()\n", __func__);
740 rate->min = rate->max = 48000;
741
742 return 0;
743}
744
745static int msm8930_hdmi_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
746 struct snd_pcm_hw_params *params)
747{
748 struct snd_interval *rate = hw_param_interval(params,
749 SNDRV_PCM_HW_PARAM_RATE);
750
751 struct snd_interval *channels = hw_param_interval(params,
752 SNDRV_PCM_HW_PARAM_CHANNELS);
753
754 rate->min = rate->max = 48000;
755 channels->min = channels->max = 2;
756
757 return 0;
758}
759
760static int msm8930_btsco_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
761 struct snd_pcm_hw_params *params)
762{
763 struct snd_interval *rate = hw_param_interval(params,
764 SNDRV_PCM_HW_PARAM_RATE);
765
766 struct snd_interval *channels = hw_param_interval(params,
767 SNDRV_PCM_HW_PARAM_CHANNELS);
768
769 rate->min = rate->max = msm8930_btsco_rate;
770 channels->min = channels->max = msm8930_btsco_ch;
771
772 return 0;
773}
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530774
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530775static int msm8930_startup(struct snd_pcm_substream *substream)
776{
777 pr_debug("%s(): substream = %s stream = %d\n", __func__,
778 substream->name, substream->stream);
779 return 0;
780}
781
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530782static void msm8930_shutdown(struct snd_pcm_substream *substream)
783{
784 pr_debug("%s(): substream = %s stream = %d\n", __func__,
785 substream->name, substream->stream);
786}
787
788static struct snd_soc_ops msm8930_be_ops = {
789 .startup = msm8930_startup,
790 .hw_params = msm8930_hw_params,
791 .shutdown = msm8930_shutdown,
792};
793
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530794/* Digital audio interface glue - connects codec <---> CPU */
795static struct snd_soc_dai_link msm8930_dai[] = {
796 /* FrontEnd DAI Links */
797 {
798 .name = "MSM8930 Media1",
799 .stream_name = "MultiMedia1",
800 .cpu_dai_name = "MultiMedia1",
801 .platform_name = "msm-pcm-dsp",
802 .dynamic = 1,
803 .dsp_link = &fe_media,
804 .be_id = MSM_FRONTEND_DAI_MULTIMEDIA1
805 },
806 {
807 .name = "MSM8930 Media2",
808 .stream_name = "MultiMedia2",
809 .cpu_dai_name = "MultiMedia2",
810 .platform_name = "msm-pcm-dsp",
811 .dynamic = 1,
812 .dsp_link = &fe_media,
813 .be_id = MSM_FRONTEND_DAI_MULTIMEDIA2,
814 },
815 {
816 .name = "Circuit-Switch Voice",
817 .stream_name = "CS-Voice",
818 .cpu_dai_name = "CS-VOICE",
819 .platform_name = "msm-pcm-voice",
820 .dynamic = 1,
821 .dsp_link = &fe_media,
822 .be_id = MSM_FRONTEND_DAI_CS_VOICE,
823 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
824 .ignore_suspend = 1,
825 },
826 {
827 .name = "MSM VoIP",
828 .stream_name = "VoIP",
829 .cpu_dai_name = "VoIP",
830 .platform_name = "msm-voip-dsp",
831 .dynamic = 1,
832 .dsp_link = &fe_media,
833 .be_id = MSM_FRONTEND_DAI_VOIP,
834 },
835 {
836 .name = "MSM8930 LPA",
837 .stream_name = "LPA",
838 .cpu_dai_name = "MultiMedia3",
839 .platform_name = "msm-pcm-lpa",
840 .dynamic = 1,
841 .dsp_link = &lpa_fe_media,
842 .be_id = MSM_FRONTEND_DAI_MULTIMEDIA3,
843 },
844 /* Hostless PMC purpose */
845 {
846 .name = "SLIMBUS_0 Hostless",
847 .stream_name = "SLIMBUS_0 Hostless",
848 .cpu_dai_name = "SLIMBUS0_HOSTLESS",
849 .platform_name = "msm-pcm-hostless",
850 .dynamic = 1,
851 .dsp_link = &slimbus0_hl_media,
852 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
853 .ignore_suspend = 1,
854 /* .be_id = do not care */
855 },
856 {
857 .name = "INT_FM Hostless",
858 .stream_name = "INT_FM Hostless",
859 .cpu_dai_name = "INT_FM_HOSTLESS",
860 .platform_name = "msm-pcm-hostless",
861 .dynamic = 1,
862 .dsp_link = &int_fm_hl_media,
863 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
864 .ignore_suspend = 1,
865 /* .be_id = do not care */
866 },
867 {
868 .name = "MSM AFE-PCM RX",
869 .stream_name = "AFE-PROXY RX",
870 .cpu_dai_name = "msm-dai-q6.241",
871 .codec_name = "msm-stub-codec.1",
872 .codec_dai_name = "msm-stub-rx",
873 .platform_name = "msm-pcm-afe",
874 .ignore_suspend = 1,
875 },
876 {
877 .name = "MSM AFE-PCM TX",
878 .stream_name = "AFE-PROXY TX",
879 .cpu_dai_name = "msm-dai-q6.240",
880 .codec_name = "msm-stub-codec.1",
881 .codec_dai_name = "msm-stub-tx",
882 .platform_name = "msm-pcm-afe",
883 .ignore_suspend = 1,
884 },
885 {
886 .name = "MSM8930 Compr",
887 .stream_name = "COMPR",
888 .cpu_dai_name = "MultiMedia4",
889 .platform_name = "msm-compr-dsp",
890 .dynamic = 1,
891 .dsp_link = &lpa_fe_media,
892 .be_id = MSM_FRONTEND_DAI_MULTIMEDIA4,
893 },
894 {
895 .name = "AUXPCM Hostless",
896 .stream_name = "AUXPCM Hostless",
897 .cpu_dai_name = "AUXPCM_HOSTLESS",
898 .platform_name = "msm-pcm-hostless",
899 .dynamic = 1,
900 .dsp_link = &bidir_hl_media,
901 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
902 .ignore_suspend = 1,
903 },
904 /* HDMI Hostless */
905 {
906 .name = "HDMI_RX_HOSTLESS",
907 .stream_name = "HDMI_RX_HOSTLESS",
908 .cpu_dai_name = "HDMI_HOSTLESS",
909 .platform_name = "msm-pcm-hostless",
910 .dynamic = 1,
911 .dsp_link = &hdmi_rx_hl,
912 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
913 .no_codec = 1,
914 .ignore_suspend = 1,
915 },
916 /* Backend DAI Links */
917 {
918 .name = LPASS_BE_SLIMBUS_0_RX,
919 .stream_name = "Slimbus Playback",
920 .cpu_dai_name = "msm-dai-q6.16384",
921 .platform_name = "msm-pcm-routing",
922 .codec_name = "sitar_codec",
923 .codec_dai_name = "sitar_rx1",
924 .no_pcm = 1,
925 .be_id = MSM_BACKEND_DAI_SLIMBUS_0_RX,
926 .init = &msm8930_audrx_init,
927 .be_hw_params_fixup = msm8930_slim_0_rx_be_hw_params_fixup,
928 .ops = &msm8930_be_ops,
929 },
930 {
931 .name = LPASS_BE_SLIMBUS_0_TX,
932 .stream_name = "Slimbus Capture",
933 .cpu_dai_name = "msm-dai-q6.16385",
934 .platform_name = "msm-pcm-routing",
935 .codec_name = "sitar_codec",
936 .codec_dai_name = "sitar_tx1",
937 .no_pcm = 1,
938 .be_id = MSM_BACKEND_DAI_SLIMBUS_0_TX,
939 .be_hw_params_fixup = msm8930_slim_0_tx_be_hw_params_fixup,
940 .ops = &msm8930_be_ops,
941 },
942 /* Backend BT/FM DAI Links */
943 {
944 .name = LPASS_BE_INT_BT_SCO_RX,
945 .stream_name = "Internal BT-SCO Playback",
946 .cpu_dai_name = "msm-dai-q6.12288",
947 .platform_name = "msm-pcm-routing",
948 .codec_name = "msm-stub-codec.1",
949 .codec_dai_name = "msm-stub-rx",
950 .init = &msm8930_btsco_init,
951 .no_pcm = 1,
952 .be_id = MSM_BACKEND_DAI_INT_BT_SCO_RX,
953 .be_hw_params_fixup = msm8930_btsco_be_hw_params_fixup,
954 },
955 {
956 .name = LPASS_BE_INT_BT_SCO_TX,
957 .stream_name = "Internal BT-SCO Capture",
958 .cpu_dai_name = "msm-dai-q6.12289",
959 .platform_name = "msm-pcm-routing",
960 .codec_name = "msm-stub-codec.1",
961 .codec_dai_name = "msm-stub-tx",
962 .no_pcm = 1,
963 .be_id = MSM_BACKEND_DAI_INT_BT_SCO_TX,
964 .be_hw_params_fixup = msm8930_btsco_be_hw_params_fixup,
965 },
966 {
967 .name = LPASS_BE_INT_FM_RX,
968 .stream_name = "Internal FM Playback",
969 .cpu_dai_name = "msm-dai-q6.12292",
970 .platform_name = "msm-pcm-routing",
971 .codec_name = "msm-stub-codec.1",
972 .codec_dai_name = "msm-stub-rx",
973 .no_pcm = 1,
974 .be_id = MSM_BACKEND_DAI_INT_FM_RX,
975 .be_hw_params_fixup = msm8930_be_hw_params_fixup,
976 },
977 {
978 .name = LPASS_BE_INT_FM_TX,
979 .stream_name = "Internal FM Capture",
980 .cpu_dai_name = "msm-dai-q6.12293",
981 .platform_name = "msm-pcm-routing",
982 .codec_name = "msm-stub-codec.1",
983 .codec_dai_name = "msm-stub-tx",
984 .no_pcm = 1,
985 .be_id = MSM_BACKEND_DAI_INT_FM_TX,
986 .be_hw_params_fixup = msm8930_be_hw_params_fixup,
987 },
988 /* HDMI BACK END DAI Link */
989 {
990 .name = LPASS_BE_HDMI,
991 .stream_name = "HDMI Playback",
992 .cpu_dai_name = "msm-dai-q6-hdmi.8",
993 .platform_name = "msm-pcm-routing",
994 .codec_name = "msm-stub-codec.1",
995 .codec_dai_name = "msm-stub-rx",
996 .no_pcm = 1,
997 .no_codec = 1,
998 .be_id = MSM_BACKEND_DAI_HDMI_RX,
999 .be_hw_params_fixup = msm8930_hdmi_be_hw_params_fixup,
1000 },
1001 /* Backend AFE DAI Links */
1002 {
1003 .name = LPASS_BE_AFE_PCM_RX,
1004 .stream_name = "AFE Playback",
1005 .cpu_dai_name = "msm-dai-q6.224",
1006 .platform_name = "msm-pcm-routing",
1007 .codec_name = "msm-stub-codec.1",
1008 .codec_dai_name = "msm-stub-rx",
1009 .no_codec = 1,
1010 .no_pcm = 1,
1011 .be_id = MSM_BACKEND_DAI_AFE_PCM_RX,
1012 },
1013 {
1014 .name = LPASS_BE_AFE_PCM_TX,
1015 .stream_name = "AFE Capture",
1016 .cpu_dai_name = "msm-dai-q6.225",
1017 .platform_name = "msm-pcm-routing",
1018 .codec_name = "msm-stub-codec.1",
1019 .codec_dai_name = "msm-stub-tx",
1020 .no_codec = 1,
1021 .no_pcm = 1,
1022 .be_id = MSM_BACKEND_DAI_AFE_PCM_TX,
1023 },
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301024 /* Incall Music BACK END DAI Link */
1025 {
1026 .name = LPASS_BE_VOICE_PLAYBACK_TX,
1027 .stream_name = "Voice Farend Playback",
1028 .cpu_dai_name = "msm-dai-q6.32773",
1029 .platform_name = "msm-pcm-routing",
1030 .codec_name = "msm-stub-codec.1",
1031 .codec_dai_name = "msm-stub-rx",
1032 .no_pcm = 1,
1033 .no_codec = 1,
1034 .be_id = MSM_BACKEND_DAI_VOICE_PLAYBACK_TX,
1035 .be_hw_params_fixup = msm8930_be_hw_params_fixup,
1036 },
1037 /* Incall Record Uplink BACK END DAI Link */
1038 {
1039 .name = LPASS_BE_INCALL_RECORD_TX,
1040 .stream_name = "Voice Uplink Capture",
1041 .cpu_dai_name = "msm-dai-q6.32772",
1042 .platform_name = "msm-pcm-routing",
1043 .codec_name = "msm-stub-codec.1",
1044 .codec_dai_name = "msm-stub-tx",
1045 .no_pcm = 1,
1046 .no_codec = 1,
1047 .be_id = MSM_BACKEND_DAI_INCALL_RECORD_TX,
1048 .be_hw_params_fixup = msm8930_be_hw_params_fixup,
1049 },
1050 /* Incall Record Downlink BACK END DAI Link */
1051 {
1052 .name = LPASS_BE_INCALL_RECORD_RX,
1053 .stream_name = "Voice Downlink Capture",
1054 .cpu_dai_name = "msm-dai-q6.32771",
1055 .platform_name = "msm-pcm-routing",
1056 .codec_name = "msm-stub-codec.1",
1057 .codec_dai_name = "msm-stub-tx",
1058 .no_pcm = 1,
1059 .no_codec = 1,
1060 .be_id = MSM_BACKEND_DAI_INCALL_RECORD_RX,
1061 .be_hw_params_fixup = msm8930_be_hw_params_fixup,
1062 },
1063};
1064
1065struct snd_soc_card snd_soc_card_msm8930 = {
1066 .name = "msm8930-sitar-snd-card",
1067 .dai_link = msm8930_dai,
1068 .num_links = ARRAY_SIZE(msm8930_dai),
1069};
1070
1071static struct platform_device *msm8930_snd_device;
1072
1073static int msm8930_configure_headset_mic_gpios(void)
1074{
1075 int ret;
1076 ret = gpio_request(80, "US_EURO_SWITCH");
1077 if (ret) {
1078 pr_err("%s: Failed to request gpio 80\n", __func__);
1079 return ret;
1080 }
1081 ret = gpio_direction_output(80, 0);
1082 if (ret) {
1083 pr_err("%s: Unable to set direction\n", __func__);
1084 gpio_free(80);
1085 }
1086 msm8930_headset_gpios_configured = 0;
1087 return 0;
1088}
1089static void msm8930_free_headset_mic_gpios(void)
1090{
1091 if (msm8930_headset_gpios_configured)
1092 gpio_free(80);
1093}
1094
1095static int __init msm8930_audio_init(void)
1096{
1097 int ret;
1098
1099 if (!cpu_is_msm8930()) {
1100 pr_err("%s: Not the right machine type\n", __func__);
1101 return -ENODEV ;
1102 }
Bhalchandra Gajare466aafe2012-05-02 17:55:26 -07001103 mbhc_cfg.calibration = def_sitar_mbhc_cal();
1104 if (!mbhc_cfg.calibration) {
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -08001105 pr_err("Calibration data allocation failed\n");
1106 return -ENOMEM;
1107 }
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301108
1109 msm8930_snd_device = platform_device_alloc("soc-audio", 0);
1110 if (!msm8930_snd_device) {
1111 pr_err("Platform device allocation failed\n");
Bhalchandra Gajare466aafe2012-05-02 17:55:26 -07001112 kfree(mbhc_cfg.calibration);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301113 return -ENOMEM;
1114 }
1115
1116 platform_set_drvdata(msm8930_snd_device, &snd_soc_card_msm8930);
1117 ret = platform_device_add(msm8930_snd_device);
1118 if (ret) {
1119 platform_device_put(msm8930_snd_device);
Bhalchandra Gajare466aafe2012-05-02 17:55:26 -07001120 kfree(mbhc_cfg.calibration);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301121 return ret;
1122 }
1123
1124 if (msm8930_configure_headset_mic_gpios()) {
1125 pr_err("%s Fail to configure headset mic gpios\n", __func__);
1126 msm8930_headset_gpios_configured = 0;
1127 } else
1128 msm8930_headset_gpios_configured = 1;
1129
1130 return ret;
1131
1132}
1133module_init(msm8930_audio_init);
1134
1135static void __exit msm8930_audio_exit(void)
1136{
1137 if (!cpu_is_msm8930()) {
1138 pr_err("%s: Not the right machine type\n", __func__);
1139 return ;
1140 }
1141 msm8930_free_headset_mic_gpios();
1142 platform_device_unregister(msm8930_snd_device);
Bhalchandra Gajare466aafe2012-05-02 17:55:26 -07001143 kfree(mbhc_cfg.calibration);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301144}
1145module_exit(msm8930_audio_exit);
1146
1147MODULE_DESCRIPTION("ALSA SoC MSM8930");
1148MODULE_LICENSE("GPL v2");