blob: ad1278cee11e64685e4800ebeaea0047e5c6b15d [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>
Asish Bhattacharyab86c3472012-02-15 08:31:52 +053023#include <sound/pcm.h>
24#include <sound/jack.h>
25#include <asm/mach-types.h>
26#include <mach/socinfo.h>
27#include "msm-pcm-routing.h"
28#include "../codecs/wcd9304.h"
29
30/* 8930 machine driver */
31
Asish Bhattacharyab86c3472012-02-15 08:31:52 +053032#define MSM8930_SPK_ON 1
33#define MSM8930_SPK_OFF 0
34
Asish Bhattacharyab86c3472012-02-15 08:31:52 +053035#define BTSCO_RATE_8KHZ 8000
36#define BTSCO_RATE_16KHZ 16000
37
Asish Bhattacharyac71827a2012-03-05 10:11:45 -080038#define SPK_AMP_POS 0x1
39#define SPK_AMP_NEG 0x2
Bhalchandra Gajare98a28cd2012-05-16 12:00:20 -070040#define SPKR_BOOST_GPIO 15
Bhalchandra Gajare97676792012-05-22 17:41:45 -070041#define DEFAULT_PMIC_SPK_GAIN 0x0D
Asish Bhattacharyab86c3472012-02-15 08:31:52 +053042#define SITAR_EXT_CLK_RATE 12288000
43
Bhalchandra Gajare7708ee32012-05-24 17:37:37 -070044#define SITAR_MBHC_DEF_BUTTONS 8
Asish Bhattacharyab86c3472012-02-15 08:31:52 +053045#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;
Bhalchandra Gajare97676792012-05-22 17:41:45 -070050static int msm8930_pmic_spk_gain = DEFAULT_PMIC_SPK_GAIN;
Asish Bhattacharyab86c3472012-02-15 08:31:52 +053051
Asish Bhattacharyac71827a2012-03-05 10:11:45 -080052static int msm8930_ext_spk_pamp;
Asish Bhattacharyab86c3472012-02-15 08:31:52 +053053static int msm8930_btsco_rate = BTSCO_RATE_8KHZ;
54static int msm8930_btsco_ch = 1;
55
56static struct clk *codec_clk;
57static int clk_users;
58
59static int msm8930_headset_gpios_configured;
60
61static struct snd_soc_jack hs_jack;
62static struct snd_soc_jack button_jack;
Bhalchandra Gajare466aafe2012-05-02 17:55:26 -070063
64static int msm8930_enable_codec_ext_clk(
65 struct snd_soc_codec *codec, int enable,
66 bool dapm);
67
68static struct sitar_mbhc_config mbhc_cfg = {
69 .headset_jack = &hs_jack,
70 .button_jack = &button_jack,
71 .read_fw_bin = false,
72 .calibration = NULL,
73 .micbias = SITAR_MICBIAS2,
74 .mclk_cb_fn = msm8930_enable_codec_ext_clk,
75 .mclk_rate = SITAR_EXT_CLK_RATE,
76 .gpio = 0,
77 .gpio_irq = 0,
78 .gpio_level_insert = 1,
79};
80
Asish Bhattacharyab86c3472012-02-15 08:31:52 +053081
82static void msm8930_ext_control(struct snd_soc_codec *codec)
83{
84 struct snd_soc_dapm_context *dapm = &codec->dapm;
85
86 pr_debug("%s: msm8930_spk_control = %d", __func__, msm8930_spk_control);
87 if (msm8930_spk_control == MSM8930_SPK_ON) {
88 snd_soc_dapm_enable_pin(dapm, "Ext Spk Left Pos");
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -080089 snd_soc_dapm_enable_pin(dapm, "Ext Spk left Neg");
Asish Bhattacharyab86c3472012-02-15 08:31:52 +053090 } else {
91 snd_soc_dapm_disable_pin(dapm, "Ext Spk Left Pos");
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -080092 snd_soc_dapm_disable_pin(dapm, "Ext Spk Left Neg");
Asish Bhattacharyab86c3472012-02-15 08:31:52 +053093 }
94
95 snd_soc_dapm_sync(dapm);
96}
97
98static int msm8930_get_spk(struct snd_kcontrol *kcontrol,
99 struct snd_ctl_elem_value *ucontrol)
100{
101 pr_debug("%s: msm8930_spk_control = %d", __func__, msm8930_spk_control);
102 ucontrol->value.integer.value[0] = msm8930_spk_control;
103 return 0;
104}
105static int msm8930_set_spk(struct snd_kcontrol *kcontrol,
106 struct snd_ctl_elem_value *ucontrol)
107{
108 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
109
110 pr_debug("%s()\n", __func__);
111 if (msm8930_spk_control == ucontrol->value.integer.value[0])
112 return 0;
113
114 msm8930_spk_control = ucontrol->value.integer.value[0];
115 msm8930_ext_control(codec);
116 return 1;
117}
118
Asish Bhattacharyac71827a2012-03-05 10:11:45 -0800119static void msm8960_ext_spk_power_amp_on(u32 spk)
120{
Bhalchandra Gajare98a28cd2012-05-16 12:00:20 -0700121 int ret = 0;
122
Asish Bhattacharyac71827a2012-03-05 10:11:45 -0800123 if (spk & (SPK_AMP_POS | SPK_AMP_NEG)) {
124 if ((msm8930_ext_spk_pamp & SPK_AMP_POS) &&
125 (msm8930_ext_spk_pamp & SPK_AMP_NEG)) {
126
127 pr_debug("%s() External Bottom Speaker Ampl already "
128 "turned on. spk = 0x%08x\n", __func__, spk);
129 return;
130 }
131
132 msm8930_ext_spk_pamp |= spk;
133
134 if ((msm8930_ext_spk_pamp & SPK_AMP_POS) &&
135 (msm8930_ext_spk_pamp & SPK_AMP_NEG)) {
136
Bhalchandra Gajare98a28cd2012-05-16 12:00:20 -0700137 if (machine_is_msm8930_mtp()
138 || machine_is_msm8930_fluid()) {
139 pr_debug("%s: Configure Speaker Boost GPIO %u",
140 __func__, SPKR_BOOST_GPIO);
141 ret = gpio_request(SPKR_BOOST_GPIO,
142 "SPKR_BOOST_EN");
143 if (ret) {
144 pr_err("%s: Failed to configure speaker boost "
145 "gpio %u\n", __func__, SPKR_BOOST_GPIO);
146 return;
147 }
148
149 pr_debug("%s: Enable Speaker boost gpio %u\n",
150 __func__, SPKR_BOOST_GPIO);
151 gpio_direction_output(SPKR_BOOST_GPIO, 1);
152 }
153
Asish Bhattacharyac71827a2012-03-05 10:11:45 -0800154 pm8xxx_spk_enable(MSM8930_SPK_ON);
155 pr_debug("%s: slepping 4 ms after turning on external "
156 " Left Speaker Ampl\n", __func__);
157 usleep_range(4000, 4000);
158 }
159
160 } else {
161
162 pr_err("%s: ERROR : Invalid External Speaker Ampl. spk = 0x%08x\n",
163 __func__, spk);
164 return;
165 }
166}
167
168static void msm8960_ext_spk_power_amp_off(u32 spk)
169{
170 if (spk & (SPK_AMP_POS | SPK_AMP_NEG)) {
171 if (!msm8930_ext_spk_pamp)
172 return;
Bhalchandra Gajare98a28cd2012-05-16 12:00:20 -0700173 if (machine_is_msm8930_mtp()
174 || machine_is_msm8930_fluid()) {
175 pr_debug("%s: Free speaker boost gpio %u\n",
176 __func__, SPKR_BOOST_GPIO);
177 gpio_direction_output(SPKR_BOOST_GPIO, 0);
178 gpio_free(SPKR_BOOST_GPIO);
179 }
Asish Bhattacharyac71827a2012-03-05 10:11:45 -0800180
181 pm8xxx_spk_enable(MSM8930_SPK_OFF);
182 msm8930_ext_spk_pamp = 0;
183 pr_debug("%s: slepping 4 ms after turning on external "
184 " Left Speaker Ampl\n", __func__);
185 usleep_range(4000, 4000);
186
187 } else {
188
189 pr_err("%s: ERROR : Invalid External Speaker Ampl. spk = 0x%08x\n",
190 __func__, spk);
191 return;
192 }
193}
194
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530195static int msm8930_spkramp_event(struct snd_soc_dapm_widget *w,
196 struct snd_kcontrol *k, int event)
197{
198 pr_debug("%s() %x\n", __func__, SND_SOC_DAPM_EVENT_ON(event));
Asish Bhattacharyac71827a2012-03-05 10:11:45 -0800199 if (SND_SOC_DAPM_EVENT_ON(event)) {
200 if (!strncmp(w->name, "Ext Spk Left Pos", 17))
201 msm8960_ext_spk_power_amp_on(SPK_AMP_POS);
202 else if (!strncmp(w->name, "Ext Spk Left Neg", 17))
203 msm8960_ext_spk_power_amp_on(SPK_AMP_NEG);
204 else {
205 pr_err("%s() Invalid Speaker Widget = %s\n",
206 __func__, w->name);
207 return -EINVAL;
208 }
209 } else {
210 if (!strncmp(w->name, "Ext Spk Left Pos", 17))
211 msm8960_ext_spk_power_amp_off(SPK_AMP_POS);
212 else if (!strncmp(w->name, "Ext Spk Left Neg", 17))
213 msm8960_ext_spk_power_amp_off(SPK_AMP_NEG);
214 else {
215 pr_err("%s() Invalid Speaker Widget = %s\n",
216 __func__, w->name);
217 return -EINVAL;
218 }
219 }
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530220 return 0;
221}
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800222
Bhalchandra Gajare466aafe2012-05-02 17:55:26 -0700223static int msm8930_enable_codec_ext_clk(
224 struct snd_soc_codec *codec, int enable,
225 bool dapm)
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530226{
227 pr_debug("%s: enable = %d\n", __func__, enable);
228 if (enable) {
229 clk_users++;
230 pr_debug("%s: clk_users = %d\n", __func__, clk_users);
231 if (clk_users != 1)
232 return 0;
233
234 if (codec_clk) {
235 clk_set_rate(codec_clk, SITAR_EXT_CLK_RATE);
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800236 clk_prepare_enable(codec_clk);
Bhalchandra Gajare466aafe2012-05-02 17:55:26 -0700237 sitar_mclk_enable(codec, 1, dapm);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530238 } else {
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800239 pr_err("%s: Error setting Sitar MCLK\n", __func__);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530240 clk_users--;
241 return -EINVAL;
242 }
243 } else {
244 pr_debug("%s: clk_users = %d\n", __func__, clk_users);
245 if (clk_users == 0)
246 return 0;
247 clk_users--;
248 if (!clk_users) {
249 pr_debug("%s: disabling MCLK. clk_users = %d\n",
250 __func__, clk_users);
Bhalchandra Gajare466aafe2012-05-02 17:55:26 -0700251 sitar_mclk_enable(codec, 0, dapm);
Bhalchandra Gajare2776af12012-04-27 16:59:39 -0700252 clk_disable_unprepare(codec_clk);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530253 }
254 }
255 return 0;
256}
257
258static int msm8930_mclk_event(struct snd_soc_dapm_widget *w,
259 struct snd_kcontrol *kcontrol, int event)
260{
261 pr_debug("%s: event = %d\n", __func__, event);
262
263 switch (event) {
264 case SND_SOC_DAPM_PRE_PMU:
Bhalchandra Gajare466aafe2012-05-02 17:55:26 -0700265 return msm8930_enable_codec_ext_clk(w->codec, 1, true);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530266 case SND_SOC_DAPM_POST_PMD:
Bhalchandra Gajare466aafe2012-05-02 17:55:26 -0700267 return msm8930_enable_codec_ext_clk(w->codec, 0, true);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530268 }
269 return 0;
270}
271
272static const struct snd_soc_dapm_widget msm8930_dapm_widgets[] = {
273
274 SND_SOC_DAPM_SUPPLY("MCLK", SND_SOC_NOPM, 0, 0,
275 msm8930_mclk_event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
276
277 SND_SOC_DAPM_SPK("Ext Spk Left Pos", msm8930_spkramp_event),
Asish Bhattacharyac71827a2012-03-05 10:11:45 -0800278 SND_SOC_DAPM_SPK("Ext Spk Left Neg", msm8930_spkramp_event),
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530279
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530280 SND_SOC_DAPM_MIC("Headset Mic", NULL),
281 SND_SOC_DAPM_MIC("Digital Mic1", NULL),
282 SND_SOC_DAPM_MIC("ANCRight Headset Mic", NULL),
283 SND_SOC_DAPM_MIC("ANCLeft Headset Mic", NULL),
284
285 SND_SOC_DAPM_MIC("Digital Mic1", NULL),
286 SND_SOC_DAPM_MIC("Digital Mic2", NULL),
287 SND_SOC_DAPM_MIC("Digital Mic3", NULL),
288 SND_SOC_DAPM_MIC("Digital Mic4", NULL),
289
290};
291
292static const struct snd_soc_dapm_route common_audio_map[] = {
293
294 {"RX_BIAS", NULL, "MCLK"},
295 {"LDO_H", NULL, "MCLK"},
296
297 {"MIC BIAS1 Internal1", NULL, "MCLK"},
298 {"MIC BIAS2 Internal1", NULL, "MCLK"},
299
300 /* Speaker path */
301 {"Ext Spk Left Pos", NULL, "LINEOUT1"},
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800302 {"Ext Spk Left Neg", NULL, "LINEOUT2"},
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530303
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800304 /* Headset Mic */
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530305 {"AMIC2", NULL, "MIC BIAS2 Internal1"},
306 {"MIC BIAS2 Internal1", NULL, "Headset Mic"},
307
308 /* Microphone path */
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800309 {"AMIC1", NULL, "MIC BIAS2 Internal1"},
310 {"MIC BIAS2 Internal1", NULL, "ANCLeft Headset Mic"},
311
312 {"AMIC3", NULL, "MIC BIAS2 Internal1"},
313 {"MIC BIAS2 Internal1", NULL, "ANCRight Headset Mic"},
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530314
315 {"HEADPHONE", NULL, "LDO_H"},
316
317 /**
318 * The digital Mic routes are setup considering
319 * fluid as default device.
320 */
321
322 /**
Bhalchandra Gajaree6a30f72012-05-23 19:46:21 -0700323 * Digital Mic1. Front Bottom left Mic on Fluid and MTP.
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530324 * Digital Mic GM5 on CDP mainboard.
Bhalchandra Gajaree6a30f72012-05-23 19:46:21 -0700325 * Conncted to DMIC1 Input on Sitar codec.
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530326 */
327 {"DMIC1", NULL, "MIC BIAS1 External"},
328 {"MIC BIAS1 External", NULL, "Digital Mic1"},
329
330 /**
Bhalchandra Gajaree6a30f72012-05-23 19:46:21 -0700331 * Digital Mic2. Back top MIC on Fluid.
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530332 * Digital Mic GM6 on CDP mainboard.
Bhalchandra Gajaree6a30f72012-05-23 19:46:21 -0700333 * Conncted to DMIC2 Input on Sitar codec.
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530334 */
335 {"DMIC2", NULL, "MIC BIAS1 External"},
336 {"MIC BIAS1 External", NULL, "Digital Mic2"},
337 /**
338 * Digital Mic3. Back Bottom Digital Mic on Fluid.
339 * Digital Mic GM1 on CDP mainboard.
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800340 * Conncted to DMIC4 Input on Sitar codec.
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530341 */
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800342 {"DMIC3", NULL, "MIC BIAS1 External"},
343 {"MIC BIAS1 External", NULL, "Digital Mic3"},
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530344
345 /**
346 * Digital Mic4. Back top Digital Mic on Fluid.
347 * Digital Mic GM2 on CDP mainboard.
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800348 * Conncted to DMIC3 Input on Sitar codec.
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530349 */
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800350 {"DMIC4", NULL, "MIC BIAS1 External"},
351 {"MIC BIAS1 External", NULL, "Digital Mic4"},
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530352
353
354};
355
356static const char *spk_function[] = {"Off", "On"};
357static const char *slim0_rx_ch_text[] = {"One", "Two"};
358static const char *slim0_tx_ch_text[] = {"One", "Two", "Three", "Four"};
359
360static const struct soc_enum msm8930_enum[] = {
361 SOC_ENUM_SINGLE_EXT(2, spk_function),
362 SOC_ENUM_SINGLE_EXT(2, slim0_rx_ch_text),
363 SOC_ENUM_SINGLE_EXT(4, slim0_tx_ch_text),
364};
365
366static const char *btsco_rate_text[] = {"8000", "16000"};
367static const struct soc_enum msm8930_btsco_enum[] = {
368 SOC_ENUM_SINGLE_EXT(2, btsco_rate_text),
369};
370
371static int msm8930_slim_0_rx_ch_get(struct snd_kcontrol *kcontrol,
372 struct snd_ctl_elem_value *ucontrol)
373{
374 pr_debug("%s: msm8930_slim_0_rx_ch = %d\n", __func__,
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800375 msm8930_slim_0_rx_ch);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530376 ucontrol->value.integer.value[0] = msm8930_slim_0_rx_ch - 1;
377 return 0;
378}
379
380static int msm8930_slim_0_rx_ch_put(struct snd_kcontrol *kcontrol,
381 struct snd_ctl_elem_value *ucontrol)
382{
383 msm8930_slim_0_rx_ch = ucontrol->value.integer.value[0] + 1;
384
385 pr_debug("%s: msm8930_slim_0_rx_ch = %d\n", __func__,
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800386 msm8930_slim_0_rx_ch);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530387 return 1;
388}
389
390static int msm8930_slim_0_tx_ch_get(struct snd_kcontrol *kcontrol,
391 struct snd_ctl_elem_value *ucontrol)
392{
393 pr_debug("%s: msm8930_slim_0_tx_ch = %d\n", __func__,
394 msm8930_slim_0_tx_ch);
395 ucontrol->value.integer.value[0] = msm8930_slim_0_tx_ch - 1;
396 return 0;
397}
398
399static int msm8930_slim_0_tx_ch_put(struct snd_kcontrol *kcontrol,
400 struct snd_ctl_elem_value *ucontrol)
401{
402 msm8930_slim_0_tx_ch = ucontrol->value.integer.value[0] + 1;
403
404 pr_debug("%s: msm8930_slim_0_tx_ch = %d\n", __func__,
405 msm8930_slim_0_tx_ch);
406 return 1;
407}
408
409static int msm8930_btsco_rate_get(struct snd_kcontrol *kcontrol,
410 struct snd_ctl_elem_value *ucontrol)
411{
412 pr_debug("%s: msm8930_btsco_rate = %d", __func__, msm8930_btsco_rate);
413 ucontrol->value.integer.value[0] = msm8930_btsco_rate;
414 return 0;
415}
416
417static int msm8930_btsco_rate_put(struct snd_kcontrol *kcontrol,
418 struct snd_ctl_elem_value *ucontrol)
419{
420 switch (ucontrol->value.integer.value[0]) {
421 case 0:
422 msm8930_btsco_rate = BTSCO_RATE_8KHZ;
423 break;
424 case 1:
425 msm8930_btsco_rate = BTSCO_RATE_16KHZ;
426 break;
427 default:
428 msm8930_btsco_rate = BTSCO_RATE_8KHZ;
429 break;
430 }
431 pr_debug("%s: msm8930_btsco_rate = %d\n", __func__, msm8930_btsco_rate);
432 return 0;
433}
434
Bhalchandra Gajare97676792012-05-22 17:41:45 -0700435static const char *pmic_spk_gain_text[] = {
436 "NEG_6_DB", "NEG_4_DB", "NEG_2_DB", "ZERO_DB", "POS_2_DB", "POS_4_DB",
437 "POS_6_DB", "POS_8_DB", "POS_10_DB", "POS_12_DB", "POS_14_DB",
438 "POS_16_DB", "POS_18_DB", "POS_20_DB", "POS_22_DB", "POS_24_DB"
439};
440
441static const struct soc_enum msm8960_pmic_spk_gain_enum[] = {
442 SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(pmic_spk_gain_text),
443 pmic_spk_gain_text),
444};
445
446static int msm8930_pmic_gain_get(struct snd_kcontrol *kcontrol,
447 struct snd_ctl_elem_value *ucontrol)
448{
449 pr_debug("%s: msm8930_pmic_spk_gain = %d\n", __func__,
450 msm8930_pmic_spk_gain);
451 ucontrol->value.integer.value[0] = msm8930_pmic_spk_gain;
452 return 0;
453}
454
455static int msm8930_pmic_gain_put(struct snd_kcontrol *kcontrol,
456 struct snd_ctl_elem_value *ucontrol)
457{
458 int ret = 0;
459 msm8930_pmic_spk_gain = ucontrol->value.integer.value[0];
460 ret = pm8xxx_spk_gain(msm8930_pmic_spk_gain);
461 pr_debug("%s: msm8930_pmic_spk_gain = %d"
462 " ucontrol->value.integer.value[0] = %d\n", __func__,
463 msm8930_pmic_spk_gain,
464 (int) ucontrol->value.integer.value[0]);
465 return ret;
466}
467
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530468static const struct snd_kcontrol_new sitar_msm8930_controls[] = {
469 SOC_ENUM_EXT("Speaker Function", msm8930_enum[0], msm8930_get_spk,
470 msm8930_set_spk),
471 SOC_ENUM_EXT("SLIM_0_RX Channels", msm8930_enum[1],
472 msm8930_slim_0_rx_ch_get, msm8930_slim_0_rx_ch_put),
473 SOC_ENUM_EXT("SLIM_0_TX Channels", msm8930_enum[2],
474 msm8930_slim_0_tx_ch_get, msm8930_slim_0_tx_ch_put),
Bhalchandra Gajare97676792012-05-22 17:41:45 -0700475 SOC_ENUM_EXT("PMIC SPK Gain", msm8960_pmic_spk_gain_enum[0],
476 msm8930_pmic_gain_get, msm8930_pmic_gain_put),
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530477 SOC_ENUM_EXT("Internal BTSCO SampleRate", msm8930_btsco_enum[0],
478 msm8930_btsco_rate_get, msm8930_btsco_rate_put),
479};
480
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800481static void *def_sitar_mbhc_cal(void)
482{
483 void *sitar_cal;
484 struct sitar_mbhc_btn_detect_cfg *btn_cfg;
485 u16 *btn_low, *btn_high;
486 u8 *n_ready, *n_cic, *gain;
487
488 sitar_cal = kzalloc(SITAR_MBHC_CAL_SIZE(SITAR_MBHC_DEF_BUTTONS,
489 SITAR_MBHC_DEF_RLOADS),
490 GFP_KERNEL);
491 if (!sitar_cal) {
492 pr_err("%s: out of memory\n", __func__);
493 return NULL;
494 }
495
496#define S(X, Y) ((SITAR_MBHC_CAL_GENERAL_PTR(sitar_cal)->X) = (Y))
497 S(t_ldoh, 100);
498 S(t_bg_fast_settle, 100);
499 S(t_shutdown_plug_rem, 255);
500 S(mbhc_nsa, 4);
501 S(mbhc_navg, 4);
502#undef S
503#define S(X, Y) ((SITAR_MBHC_CAL_PLUG_DET_PTR(sitar_cal)->X) = (Y))
504 S(mic_current, SITAR_PID_MIC_5_UA);
505 S(hph_current, SITAR_PID_MIC_5_UA);
506 S(t_mic_pid, 100);
507 S(t_ins_complete, 250);
508 S(t_ins_retry, 200);
509#undef S
510#define S(X, Y) ((SITAR_MBHC_CAL_PLUG_TYPE_PTR(sitar_cal)->X) = (Y))
511 S(v_no_mic, 30);
512 S(v_hs_max, 1550);
513#undef S
514#define S(X, Y) ((SITAR_MBHC_CAL_BTN_DET_PTR(sitar_cal)->X) = (Y))
515 S(c[0], 62);
516 S(c[1], 124);
517 S(nc, 1);
518 S(n_meas, 3);
519 S(mbhc_nsc, 11);
520 S(n_btn_meas, 1);
521 S(n_btn_con, 2);
522 S(num_btn, SITAR_MBHC_DEF_BUTTONS);
523 S(v_btn_press_delta_sta, 100);
524 S(v_btn_press_delta_cic, 50);
525#undef S
526 btn_cfg = SITAR_MBHC_CAL_BTN_DET_PTR(sitar_cal);
527 btn_low = sitar_mbhc_cal_btn_det_mp(btn_cfg, SITAR_BTN_DET_V_BTN_LOW);
528 btn_high = sitar_mbhc_cal_btn_det_mp(btn_cfg, SITAR_BTN_DET_V_BTN_HIGH);
529 btn_low[0] = -50;
530 btn_high[0] = 10;
531 btn_low[1] = 11;
532 btn_high[1] = 38;
533 btn_low[2] = 39;
534 btn_high[2] = 64;
535 btn_low[3] = 65;
536 btn_high[3] = 91;
537 btn_low[4] = 92;
538 btn_high[4] = 115;
539 btn_low[5] = 116;
540 btn_high[5] = 141;
541 btn_low[6] = 142;
542 btn_high[6] = 163;
543 btn_low[7] = 164;
544 btn_high[7] = 250;
545 n_ready = sitar_mbhc_cal_btn_det_mp(btn_cfg, SITAR_BTN_DET_N_READY);
546 n_ready[0] = 48;
547 n_ready[1] = 38;
548 n_cic = sitar_mbhc_cal_btn_det_mp(btn_cfg, SITAR_BTN_DET_N_CIC);
549 n_cic[0] = 60;
550 n_cic[1] = 47;
551 gain = sitar_mbhc_cal_btn_det_mp(btn_cfg, SITAR_BTN_DET_GAIN);
552 gain[0] = 11;
553 gain[1] = 9;
554
555 return sitar_cal;
556}
557
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530558static int msm8930_hw_params(struct snd_pcm_substream *substream,
559 struct snd_pcm_hw_params *params)
560{
561 struct snd_soc_pcm_runtime *rtd = substream->private_data;
562 struct snd_soc_dai *codec_dai = rtd->codec_dai;
563 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
564 int ret = 0;
565 unsigned int rx_ch[SLIM_MAX_RX_PORTS], tx_ch[SLIM_MAX_TX_PORTS];
566 unsigned int rx_ch_cnt = 0, tx_ch_cnt = 0;
567
568 pr_debug("%s: ch=%d\n", __func__,
569 msm8930_slim_0_rx_ch);
570 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
571 ret = snd_soc_dai_get_channel_map(codec_dai,
572 &tx_ch_cnt, tx_ch, &rx_ch_cnt , rx_ch);
573 if (ret < 0) {
574 pr_err("%s: failed to get codec chan map\n", __func__);
575 goto end;
576 }
577
578 ret = snd_soc_dai_set_channel_map(cpu_dai, 0, 0,
579 msm8930_slim_0_rx_ch, rx_ch);
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, 0, 0,
585 msm8930_slim_0_rx_ch, rx_ch);
586 if (ret < 0) {
587 pr_err("%s: failed to set codec channel map\n",
588 __func__);
589 goto end;
590 }
591 } else {
592 ret = snd_soc_dai_get_channel_map(codec_dai,
593 &tx_ch_cnt, tx_ch, &rx_ch_cnt , rx_ch);
594 if (ret < 0) {
595 pr_err("%s: failed to get codec chan map\n", __func__);
596 goto end;
597 }
598 ret = snd_soc_dai_set_channel_map(cpu_dai,
599 msm8930_slim_0_tx_ch, tx_ch, 0 , 0);
600 if (ret < 0) {
601 pr_err("%s: failed to set cpu chan map\n", __func__);
602 goto end;
603 }
604 ret = snd_soc_dai_set_channel_map(codec_dai,
605 msm8930_slim_0_tx_ch, tx_ch, 0, 0);
606 if (ret < 0) {
607 pr_err("%s: failed to set codec channel map\n",
608 __func__);
609 goto end;
610 }
611
612 }
613end:
614 return ret;
615}
616
617static int msm8930_audrx_init(struct snd_soc_pcm_runtime *rtd)
618{
619 int err;
620 struct snd_soc_codec *codec = rtd->codec;
621 struct snd_soc_dapm_context *dapm = &codec->dapm;
622 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
623
624 pr_debug("%s()\n", __func__);
625
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530626 snd_soc_dapm_new_controls(dapm, msm8930_dapm_widgets,
627 ARRAY_SIZE(msm8930_dapm_widgets));
628
629 snd_soc_dapm_add_routes(dapm, common_audio_map,
630 ARRAY_SIZE(common_audio_map));
631
632 snd_soc_dapm_enable_pin(dapm, "Ext Spk Left Pos");
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800633 snd_soc_dapm_enable_pin(dapm, "Ext Spk Left Neg");
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530634
635 snd_soc_dapm_sync(dapm);
636
637 err = snd_soc_jack_new(codec, "Headset Jack",
638 (SND_JACK_HEADSET | SND_JACK_OC_HPHL | SND_JACK_OC_HPHR),
639 &hs_jack);
640 if (err) {
641 pr_err("failed to create new jack\n");
642 return err;
643 }
644
645 err = snd_soc_jack_new(codec, "Button Jack",
Bhalchandra Gajare7708ee32012-05-24 17:37:37 -0700646 SITAR_JACK_BUTTON_MASK, &button_jack);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530647 if (err) {
648 pr_err("failed to create new jack\n");
649 return err;
650 }
651 codec_clk = clk_get(cpu_dai->dev, "osr_clk");
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800652
Bhalchandra Gajare466aafe2012-05-02 17:55:26 -0700653 mbhc_cfg.gpio = 37;
654 mbhc_cfg.gpio_irq = gpio_to_irq(mbhc_cfg.gpio);
655 sitar_hs_detect(codec, &mbhc_cfg);
656
Bhalchandra Gajare97676792012-05-22 17:41:45 -0700657 /* Initialize default PMIC speaker gain */
658 pm8xxx_spk_gain(DEFAULT_PMIC_SPK_GAIN);
659
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530660 return 0;
661}
662
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530663static int msm8930_slim_0_rx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
664 struct snd_pcm_hw_params *params)
665{
666 struct snd_interval *rate = hw_param_interval(params,
667 SNDRV_PCM_HW_PARAM_RATE);
668
669 struct snd_interval *channels = hw_param_interval(params,
670 SNDRV_PCM_HW_PARAM_CHANNELS);
671
672 pr_debug("%s()\n", __func__);
673 rate->min = rate->max = 48000;
674 channels->min = channels->max = msm8930_slim_0_rx_ch;
675
676 return 0;
677}
678
679static int msm8930_slim_0_tx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
680 struct snd_pcm_hw_params *params)
681{
682 struct snd_interval *rate = hw_param_interval(params,
683 SNDRV_PCM_HW_PARAM_RATE);
684
685 struct snd_interval *channels = hw_param_interval(params,
686 SNDRV_PCM_HW_PARAM_CHANNELS);
687
688 pr_debug("%s()\n", __func__);
689 rate->min = rate->max = 48000;
690 channels->min = channels->max = msm8930_slim_0_tx_ch;
691
692 return 0;
693}
694
695static int msm8930_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
696 struct snd_pcm_hw_params *params)
697{
698 struct snd_interval *rate = hw_param_interval(params,
699 SNDRV_PCM_HW_PARAM_RATE);
700
701 pr_debug("%s()\n", __func__);
702 rate->min = rate->max = 48000;
703
704 return 0;
705}
706
707static int msm8930_hdmi_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
708 struct snd_pcm_hw_params *params)
709{
710 struct snd_interval *rate = hw_param_interval(params,
711 SNDRV_PCM_HW_PARAM_RATE);
712
713 struct snd_interval *channels = hw_param_interval(params,
714 SNDRV_PCM_HW_PARAM_CHANNELS);
715
716 rate->min = rate->max = 48000;
717 channels->min = channels->max = 2;
718
719 return 0;
720}
721
722static int msm8930_btsco_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
723 struct snd_pcm_hw_params *params)
724{
725 struct snd_interval *rate = hw_param_interval(params,
726 SNDRV_PCM_HW_PARAM_RATE);
727
728 struct snd_interval *channels = hw_param_interval(params,
729 SNDRV_PCM_HW_PARAM_CHANNELS);
730
731 rate->min = rate->max = msm8930_btsco_rate;
732 channels->min = channels->max = msm8930_btsco_ch;
733
734 return 0;
735}
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530736
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530737static int msm8930_startup(struct snd_pcm_substream *substream)
738{
739 pr_debug("%s(): substream = %s stream = %d\n", __func__,
740 substream->name, substream->stream);
741 return 0;
742}
743
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530744static void msm8930_shutdown(struct snd_pcm_substream *substream)
745{
746 pr_debug("%s(): substream = %s stream = %d\n", __func__,
747 substream->name, substream->stream);
748}
749
750static struct snd_soc_ops msm8930_be_ops = {
751 .startup = msm8930_startup,
752 .hw_params = msm8930_hw_params,
753 .shutdown = msm8930_shutdown,
754};
755
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530756/* Digital audio interface glue - connects codec <---> CPU */
757static struct snd_soc_dai_link msm8930_dai[] = {
758 /* FrontEnd DAI Links */
759 {
760 .name = "MSM8930 Media1",
761 .stream_name = "MultiMedia1",
762 .cpu_dai_name = "MultiMedia1",
763 .platform_name = "msm-pcm-dsp",
764 .dynamic = 1,
Steve Mucklef132c6c2012-06-06 18:30:57 -0700765 .codec_dai_name = "snd-soc-dummy-dai",
766 .codec_name = "snd-soc-dummy",
767 .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
768 .ignore_suspend = 1,
769 .ignore_pmdown_time = 1, /* this dainlink has playback support */
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530770 .be_id = MSM_FRONTEND_DAI_MULTIMEDIA1
771 },
772 {
773 .name = "MSM8930 Media2",
774 .stream_name = "MultiMedia2",
775 .cpu_dai_name = "MultiMedia2",
776 .platform_name = "msm-pcm-dsp",
777 .dynamic = 1,
Steve Mucklef132c6c2012-06-06 18:30:57 -0700778 .codec_dai_name = "snd-soc-dummy-dai",
779 .codec_name = "snd-soc-dummy",
780 .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
781 .ignore_suspend = 1,
782 .ignore_pmdown_time = 1, /* this dainlink has playback support */
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530783 .be_id = MSM_FRONTEND_DAI_MULTIMEDIA2,
784 },
785 {
786 .name = "Circuit-Switch Voice",
787 .stream_name = "CS-Voice",
788 .cpu_dai_name = "CS-VOICE",
789 .platform_name = "msm-pcm-voice",
790 .dynamic = 1,
Steve Mucklef132c6c2012-06-06 18:30:57 -0700791 .codec_dai_name = "snd-soc-dummy-dai",
792 .codec_name = "snd-soc-dummy",
793 .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530794 .be_id = MSM_FRONTEND_DAI_CS_VOICE,
795 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
796 .ignore_suspend = 1,
Steve Mucklef132c6c2012-06-06 18:30:57 -0700797 .ignore_pmdown_time = 1, /* this dainlink has playback support */
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530798 },
799 {
800 .name = "MSM VoIP",
801 .stream_name = "VoIP",
802 .cpu_dai_name = "VoIP",
803 .platform_name = "msm-voip-dsp",
804 .dynamic = 1,
Steve Mucklef132c6c2012-06-06 18:30:57 -0700805 .codec_dai_name = "snd-soc-dummy-dai",
806 .codec_name = "snd-soc-dummy",
807 .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
808 .ignore_suspend = 1,
809 .ignore_pmdown_time = 1, /* this dainlink has playback support */
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530810 .be_id = MSM_FRONTEND_DAI_VOIP,
811 },
812 {
813 .name = "MSM8930 LPA",
814 .stream_name = "LPA",
815 .cpu_dai_name = "MultiMedia3",
816 .platform_name = "msm-pcm-lpa",
817 .dynamic = 1,
Steve Mucklef132c6c2012-06-06 18:30:57 -0700818 .codec_dai_name = "snd-soc-dummy-dai",
819 .codec_name = "snd-soc-dummy",
820 .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
821 .ignore_suspend = 1,
822 .ignore_pmdown_time = 1, /* this dainlink has playback support */
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530823 .be_id = MSM_FRONTEND_DAI_MULTIMEDIA3,
824 },
825 /* Hostless PMC purpose */
826 {
827 .name = "SLIMBUS_0 Hostless",
828 .stream_name = "SLIMBUS_0 Hostless",
829 .cpu_dai_name = "SLIMBUS0_HOSTLESS",
830 .platform_name = "msm-pcm-hostless",
831 .dynamic = 1,
Steve Mucklef132c6c2012-06-06 18:30:57 -0700832 .codec_dai_name = "snd-soc-dummy-dai",
833 .codec_name = "snd-soc-dummy",
834 .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530835 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
836 .ignore_suspend = 1,
Steve Mucklef132c6c2012-06-06 18:30:57 -0700837 .ignore_pmdown_time = 1, /* this dainlink has playback support */
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530838 /* .be_id = do not care */
839 },
840 {
841 .name = "INT_FM Hostless",
842 .stream_name = "INT_FM Hostless",
843 .cpu_dai_name = "INT_FM_HOSTLESS",
844 .platform_name = "msm-pcm-hostless",
845 .dynamic = 1,
Steve Mucklef132c6c2012-06-06 18:30:57 -0700846 .codec_dai_name = "snd-soc-dummy-dai",
847 .codec_name = "snd-soc-dummy",
848 .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530849 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
850 .ignore_suspend = 1,
Steve Mucklef132c6c2012-06-06 18:30:57 -0700851 .ignore_pmdown_time = 1, /* this dainlink has playback support */
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530852 /* .be_id = do not care */
853 },
854 {
855 .name = "MSM AFE-PCM RX",
856 .stream_name = "AFE-PROXY RX",
857 .cpu_dai_name = "msm-dai-q6.241",
858 .codec_name = "msm-stub-codec.1",
859 .codec_dai_name = "msm-stub-rx",
860 .platform_name = "msm-pcm-afe",
861 .ignore_suspend = 1,
Steve Mucklef132c6c2012-06-06 18:30:57 -0700862 .ignore_pmdown_time = 1, /* this dainlink has playback support */
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530863 },
864 {
865 .name = "MSM AFE-PCM TX",
866 .stream_name = "AFE-PROXY TX",
867 .cpu_dai_name = "msm-dai-q6.240",
868 .codec_name = "msm-stub-codec.1",
869 .codec_dai_name = "msm-stub-tx",
870 .platform_name = "msm-pcm-afe",
871 .ignore_suspend = 1,
872 },
873 {
874 .name = "MSM8930 Compr",
875 .stream_name = "COMPR",
876 .cpu_dai_name = "MultiMedia4",
877 .platform_name = "msm-compr-dsp",
878 .dynamic = 1,
Steve Mucklef132c6c2012-06-06 18:30:57 -0700879 .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
880 .codec_dai_name = "snd-soc-dummy-dai",
881 .codec_name = "snd-soc-dummy",
882 .ignore_suspend = 1,
883 .ignore_pmdown_time = 1, /* this dainlink has playback support */
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530884 .be_id = MSM_FRONTEND_DAI_MULTIMEDIA4,
885 },
886 {
887 .name = "AUXPCM Hostless",
888 .stream_name = "AUXPCM Hostless",
889 .cpu_dai_name = "AUXPCM_HOSTLESS",
890 .platform_name = "msm-pcm-hostless",
891 .dynamic = 1,
Steve Mucklef132c6c2012-06-06 18:30:57 -0700892 .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530893 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
894 .ignore_suspend = 1,
Steve Mucklef132c6c2012-06-06 18:30:57 -0700895 .ignore_pmdown_time = 1, /* this dainlink has playback support */
896 .codec_dai_name = "snd-soc-dummy-dai",
897 .codec_name = "snd-soc-dummy",
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530898 },
899 /* HDMI Hostless */
900 {
901 .name = "HDMI_RX_HOSTLESS",
902 .stream_name = "HDMI_RX_HOSTLESS",
903 .cpu_dai_name = "HDMI_HOSTLESS",
904 .platform_name = "msm-pcm-hostless",
905 .dynamic = 1,
Steve Mucklef132c6c2012-06-06 18:30:57 -0700906 .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530907 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530908 .ignore_suspend = 1,
Steve Mucklef132c6c2012-06-06 18:30:57 -0700909 .ignore_pmdown_time = 1, /* this dainlink has playback support */
910 .codec_dai_name = "snd-soc-dummy-dai",
911 .codec_name = "snd-soc-dummy",
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530912 },
913 /* Backend DAI Links */
914 {
915 .name = LPASS_BE_SLIMBUS_0_RX,
916 .stream_name = "Slimbus Playback",
917 .cpu_dai_name = "msm-dai-q6.16384",
918 .platform_name = "msm-pcm-routing",
919 .codec_name = "sitar_codec",
920 .codec_dai_name = "sitar_rx1",
921 .no_pcm = 1,
922 .be_id = MSM_BACKEND_DAI_SLIMBUS_0_RX,
923 .init = &msm8930_audrx_init,
924 .be_hw_params_fixup = msm8930_slim_0_rx_be_hw_params_fixup,
925 .ops = &msm8930_be_ops,
Steve Mucklef132c6c2012-06-06 18:30:57 -0700926 .ignore_pmdown_time = 1, /* this dainlink has playback support */
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530927 },
928 {
929 .name = LPASS_BE_SLIMBUS_0_TX,
930 .stream_name = "Slimbus Capture",
931 .cpu_dai_name = "msm-dai-q6.16385",
932 .platform_name = "msm-pcm-routing",
933 .codec_name = "sitar_codec",
934 .codec_dai_name = "sitar_tx1",
935 .no_pcm = 1,
936 .be_id = MSM_BACKEND_DAI_SLIMBUS_0_TX,
937 .be_hw_params_fixup = msm8930_slim_0_tx_be_hw_params_fixup,
938 .ops = &msm8930_be_ops,
939 },
940 /* Backend BT/FM DAI Links */
941 {
942 .name = LPASS_BE_INT_BT_SCO_RX,
943 .stream_name = "Internal BT-SCO Playback",
944 .cpu_dai_name = "msm-dai-q6.12288",
945 .platform_name = "msm-pcm-routing",
946 .codec_name = "msm-stub-codec.1",
947 .codec_dai_name = "msm-stub-rx",
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530948 .no_pcm = 1,
949 .be_id = MSM_BACKEND_DAI_INT_BT_SCO_RX,
950 .be_hw_params_fixup = msm8930_btsco_be_hw_params_fixup,
Steve Mucklef132c6c2012-06-06 18:30:57 -0700951 .ignore_pmdown_time = 1, /* this dainlink has playback support */
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530952 },
953 {
954 .name = LPASS_BE_INT_BT_SCO_TX,
955 .stream_name = "Internal BT-SCO Capture",
956 .cpu_dai_name = "msm-dai-q6.12289",
957 .platform_name = "msm-pcm-routing",
958 .codec_name = "msm-stub-codec.1",
959 .codec_dai_name = "msm-stub-tx",
960 .no_pcm = 1,
961 .be_id = MSM_BACKEND_DAI_INT_BT_SCO_TX,
962 .be_hw_params_fixup = msm8930_btsco_be_hw_params_fixup,
963 },
964 {
965 .name = LPASS_BE_INT_FM_RX,
966 .stream_name = "Internal FM Playback",
967 .cpu_dai_name = "msm-dai-q6.12292",
968 .platform_name = "msm-pcm-routing",
969 .codec_name = "msm-stub-codec.1",
970 .codec_dai_name = "msm-stub-rx",
971 .no_pcm = 1,
972 .be_id = MSM_BACKEND_DAI_INT_FM_RX,
973 .be_hw_params_fixup = msm8930_be_hw_params_fixup,
Steve Mucklef132c6c2012-06-06 18:30:57 -0700974 .ignore_pmdown_time = 1, /* this dainlink has playback support */
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530975 },
976 {
977 .name = LPASS_BE_INT_FM_TX,
978 .stream_name = "Internal FM Capture",
979 .cpu_dai_name = "msm-dai-q6.12293",
980 .platform_name = "msm-pcm-routing",
981 .codec_name = "msm-stub-codec.1",
982 .codec_dai_name = "msm-stub-tx",
983 .no_pcm = 1,
984 .be_id = MSM_BACKEND_DAI_INT_FM_TX,
985 .be_hw_params_fixup = msm8930_be_hw_params_fixup,
986 },
987 /* HDMI BACK END DAI Link */
988 {
989 .name = LPASS_BE_HDMI,
990 .stream_name = "HDMI Playback",
991 .cpu_dai_name = "msm-dai-q6-hdmi.8",
992 .platform_name = "msm-pcm-routing",
993 .codec_name = "msm-stub-codec.1",
994 .codec_dai_name = "msm-stub-rx",
995 .no_pcm = 1,
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530996 .be_id = MSM_BACKEND_DAI_HDMI_RX,
997 .be_hw_params_fixup = msm8930_hdmi_be_hw_params_fixup,
Steve Mucklef132c6c2012-06-06 18:30:57 -0700998 .ignore_pmdown_time = 1, /* this dainlink has playback support */
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530999 },
1000 /* Backend AFE DAI Links */
1001 {
1002 .name = LPASS_BE_AFE_PCM_RX,
1003 .stream_name = "AFE Playback",
1004 .cpu_dai_name = "msm-dai-q6.224",
1005 .platform_name = "msm-pcm-routing",
1006 .codec_name = "msm-stub-codec.1",
1007 .codec_dai_name = "msm-stub-rx",
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301008 .no_pcm = 1,
1009 .be_id = MSM_BACKEND_DAI_AFE_PCM_RX,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001010 .ignore_pmdown_time = 1, /* this dainlink has playback support */
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301011 },
1012 {
1013 .name = LPASS_BE_AFE_PCM_TX,
1014 .stream_name = "AFE Capture",
1015 .cpu_dai_name = "msm-dai-q6.225",
1016 .platform_name = "msm-pcm-routing",
1017 .codec_name = "msm-stub-codec.1",
1018 .codec_dai_name = "msm-stub-tx",
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301019 .no_pcm = 1,
1020 .be_id = MSM_BACKEND_DAI_AFE_PCM_TX,
1021 },
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301022 /* Incall Music BACK END DAI Link */
1023 {
1024 .name = LPASS_BE_VOICE_PLAYBACK_TX,
1025 .stream_name = "Voice Farend Playback",
1026 .cpu_dai_name = "msm-dai-q6.32773",
1027 .platform_name = "msm-pcm-routing",
1028 .codec_name = "msm-stub-codec.1",
1029 .codec_dai_name = "msm-stub-rx",
1030 .no_pcm = 1,
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301031 .be_id = MSM_BACKEND_DAI_VOICE_PLAYBACK_TX,
1032 .be_hw_params_fixup = msm8930_be_hw_params_fixup,
1033 },
1034 /* Incall Record Uplink BACK END DAI Link */
1035 {
1036 .name = LPASS_BE_INCALL_RECORD_TX,
1037 .stream_name = "Voice Uplink Capture",
1038 .cpu_dai_name = "msm-dai-q6.32772",
1039 .platform_name = "msm-pcm-routing",
1040 .codec_name = "msm-stub-codec.1",
1041 .codec_dai_name = "msm-stub-tx",
1042 .no_pcm = 1,
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301043 .be_id = MSM_BACKEND_DAI_INCALL_RECORD_TX,
1044 .be_hw_params_fixup = msm8930_be_hw_params_fixup,
1045 },
1046 /* Incall Record Downlink BACK END DAI Link */
1047 {
1048 .name = LPASS_BE_INCALL_RECORD_RX,
1049 .stream_name = "Voice Downlink Capture",
1050 .cpu_dai_name = "msm-dai-q6.32771",
1051 .platform_name = "msm-pcm-routing",
1052 .codec_name = "msm-stub-codec.1",
1053 .codec_dai_name = "msm-stub-tx",
1054 .no_pcm = 1,
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301055 .be_id = MSM_BACKEND_DAI_INCALL_RECORD_RX,
1056 .be_hw_params_fixup = msm8930_be_hw_params_fixup,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001057 .ignore_pmdown_time = 1, /* this dainlink has playback support */
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301058 },
1059};
1060
1061struct snd_soc_card snd_soc_card_msm8930 = {
1062 .name = "msm8930-sitar-snd-card",
1063 .dai_link = msm8930_dai,
1064 .num_links = ARRAY_SIZE(msm8930_dai),
Steve Mucklef132c6c2012-06-06 18:30:57 -07001065 .controls = sitar_msm8930_controls,
1066 .num_controls = ARRAY_SIZE(sitar_msm8930_controls),
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301067};
1068
1069static struct platform_device *msm8930_snd_device;
1070
1071static int msm8930_configure_headset_mic_gpios(void)
1072{
1073 int ret;
1074 ret = gpio_request(80, "US_EURO_SWITCH");
1075 if (ret) {
1076 pr_err("%s: Failed to request gpio 80\n", __func__);
1077 return ret;
1078 }
1079 ret = gpio_direction_output(80, 0);
1080 if (ret) {
1081 pr_err("%s: Unable to set direction\n", __func__);
1082 gpio_free(80);
1083 }
1084 msm8930_headset_gpios_configured = 0;
1085 return 0;
1086}
1087static void msm8930_free_headset_mic_gpios(void)
1088{
1089 if (msm8930_headset_gpios_configured)
1090 gpio_free(80);
1091}
1092
1093static int __init msm8930_audio_init(void)
1094{
1095 int ret;
1096
1097 if (!cpu_is_msm8930()) {
1098 pr_err("%s: Not the right machine type\n", __func__);
1099 return -ENODEV ;
1100 }
Bhalchandra Gajare466aafe2012-05-02 17:55:26 -07001101 mbhc_cfg.calibration = def_sitar_mbhc_cal();
1102 if (!mbhc_cfg.calibration) {
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -08001103 pr_err("Calibration data allocation failed\n");
1104 return -ENOMEM;
1105 }
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301106
1107 msm8930_snd_device = platform_device_alloc("soc-audio", 0);
1108 if (!msm8930_snd_device) {
1109 pr_err("Platform device allocation failed\n");
Bhalchandra Gajare466aafe2012-05-02 17:55:26 -07001110 kfree(mbhc_cfg.calibration);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301111 return -ENOMEM;
1112 }
1113
1114 platform_set_drvdata(msm8930_snd_device, &snd_soc_card_msm8930);
1115 ret = platform_device_add(msm8930_snd_device);
1116 if (ret) {
1117 platform_device_put(msm8930_snd_device);
Bhalchandra Gajare466aafe2012-05-02 17:55:26 -07001118 kfree(mbhc_cfg.calibration);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301119 return ret;
1120 }
1121
1122 if (msm8930_configure_headset_mic_gpios()) {
1123 pr_err("%s Fail to configure headset mic gpios\n", __func__);
1124 msm8930_headset_gpios_configured = 0;
1125 } else
1126 msm8930_headset_gpios_configured = 1;
1127
1128 return ret;
1129
1130}
1131module_init(msm8930_audio_init);
1132
1133static void __exit msm8930_audio_exit(void)
1134{
1135 if (!cpu_is_msm8930()) {
1136 pr_err("%s: Not the right machine type\n", __func__);
1137 return ;
1138 }
1139 msm8930_free_headset_mic_gpios();
1140 platform_device_unregister(msm8930_snd_device);
Bhalchandra Gajare466aafe2012-05-02 17:55:26 -07001141 kfree(mbhc_cfg.calibration);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301142}
1143module_exit(msm8930_audio_exit);
1144
1145MODULE_DESCRIPTION("ALSA SoC MSM8930");
1146MODULE_LICENSE("GPL v2");