blob: 374e875495b6d19945fcce306fe6dbb73328a0a8 [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
Bhalchandra Gajare2e0893e2012-05-24 00:39:47 -070047#define GPIO_AUX_PCM_DOUT 63
48#define GPIO_AUX_PCM_DIN 64
49#define GPIO_AUX_PCM_SYNC 65
50#define GPIO_AUX_PCM_CLK 66
51
Asish Bhattacharyab86c3472012-02-15 08:31:52 +053052static int msm8930_spk_control;
53static int msm8930_slim_0_rx_ch = 1;
54static int msm8930_slim_0_tx_ch = 1;
Bhalchandra Gajare97676792012-05-22 17:41:45 -070055static int msm8930_pmic_spk_gain = DEFAULT_PMIC_SPK_GAIN;
Asish Bhattacharyab86c3472012-02-15 08:31:52 +053056
Asish Bhattacharyac71827a2012-03-05 10:11:45 -080057static int msm8930_ext_spk_pamp;
Asish Bhattacharyab86c3472012-02-15 08:31:52 +053058static int msm8930_btsco_rate = BTSCO_RATE_8KHZ;
59static int msm8930_btsco_ch = 1;
60
61static struct clk *codec_clk;
62static int clk_users;
63
64static int msm8930_headset_gpios_configured;
65
66static struct snd_soc_jack hs_jack;
67static struct snd_soc_jack button_jack;
Bhalchandra Gajare466aafe2012-05-02 17:55:26 -070068
69static int msm8930_enable_codec_ext_clk(
70 struct snd_soc_codec *codec, int enable,
71 bool dapm);
72
73static struct sitar_mbhc_config mbhc_cfg = {
74 .headset_jack = &hs_jack,
75 .button_jack = &button_jack,
76 .read_fw_bin = false,
77 .calibration = NULL,
78 .micbias = SITAR_MICBIAS2,
79 .mclk_cb_fn = msm8930_enable_codec_ext_clk,
80 .mclk_rate = SITAR_EXT_CLK_RATE,
81 .gpio = 0,
82 .gpio_irq = 0,
83 .gpio_level_insert = 1,
84};
85
Asish Bhattacharyab86c3472012-02-15 08:31:52 +053086
87static void msm8930_ext_control(struct snd_soc_codec *codec)
88{
89 struct snd_soc_dapm_context *dapm = &codec->dapm;
90
91 pr_debug("%s: msm8930_spk_control = %d", __func__, msm8930_spk_control);
92 if (msm8930_spk_control == MSM8930_SPK_ON) {
93 snd_soc_dapm_enable_pin(dapm, "Ext Spk Left Pos");
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -080094 snd_soc_dapm_enable_pin(dapm, "Ext Spk left Neg");
Asish Bhattacharyab86c3472012-02-15 08:31:52 +053095 } else {
96 snd_soc_dapm_disable_pin(dapm, "Ext Spk Left Pos");
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -080097 snd_soc_dapm_disable_pin(dapm, "Ext Spk Left Neg");
Asish Bhattacharyab86c3472012-02-15 08:31:52 +053098 }
99
100 snd_soc_dapm_sync(dapm);
101}
102
103static int msm8930_get_spk(struct snd_kcontrol *kcontrol,
104 struct snd_ctl_elem_value *ucontrol)
105{
106 pr_debug("%s: msm8930_spk_control = %d", __func__, msm8930_spk_control);
107 ucontrol->value.integer.value[0] = msm8930_spk_control;
108 return 0;
109}
110static int msm8930_set_spk(struct snd_kcontrol *kcontrol,
111 struct snd_ctl_elem_value *ucontrol)
112{
113 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
114
115 pr_debug("%s()\n", __func__);
116 if (msm8930_spk_control == ucontrol->value.integer.value[0])
117 return 0;
118
119 msm8930_spk_control = ucontrol->value.integer.value[0];
120 msm8930_ext_control(codec);
121 return 1;
122}
123
Asish Bhattacharyac71827a2012-03-05 10:11:45 -0800124static void msm8960_ext_spk_power_amp_on(u32 spk)
125{
Bhalchandra Gajare98a28cd2012-05-16 12:00:20 -0700126 int ret = 0;
127
Asish Bhattacharyac71827a2012-03-05 10:11:45 -0800128 if (spk & (SPK_AMP_POS | SPK_AMP_NEG)) {
129 if ((msm8930_ext_spk_pamp & SPK_AMP_POS) &&
130 (msm8930_ext_spk_pamp & SPK_AMP_NEG)) {
131
132 pr_debug("%s() External Bottom Speaker Ampl already "
133 "turned on. spk = 0x%08x\n", __func__, spk);
134 return;
135 }
136
137 msm8930_ext_spk_pamp |= spk;
138
139 if ((msm8930_ext_spk_pamp & SPK_AMP_POS) &&
140 (msm8930_ext_spk_pamp & SPK_AMP_NEG)) {
141
Bhalchandra Gajare98a28cd2012-05-16 12:00:20 -0700142 if (machine_is_msm8930_mtp()
143 || machine_is_msm8930_fluid()) {
144 pr_debug("%s: Configure Speaker Boost GPIO %u",
145 __func__, SPKR_BOOST_GPIO);
146 ret = gpio_request(SPKR_BOOST_GPIO,
147 "SPKR_BOOST_EN");
148 if (ret) {
149 pr_err("%s: Failed to configure speaker boost "
150 "gpio %u\n", __func__, SPKR_BOOST_GPIO);
151 return;
152 }
153
154 pr_debug("%s: Enable Speaker boost gpio %u\n",
155 __func__, SPKR_BOOST_GPIO);
156 gpio_direction_output(SPKR_BOOST_GPIO, 1);
157 }
158
Asish Bhattacharyac71827a2012-03-05 10:11:45 -0800159 pm8xxx_spk_enable(MSM8930_SPK_ON);
160 pr_debug("%s: slepping 4 ms after turning on external "
161 " Left Speaker Ampl\n", __func__);
162 usleep_range(4000, 4000);
163 }
164
165 } else {
166
167 pr_err("%s: ERROR : Invalid External Speaker Ampl. spk = 0x%08x\n",
168 __func__, spk);
169 return;
170 }
171}
172
173static void msm8960_ext_spk_power_amp_off(u32 spk)
174{
175 if (spk & (SPK_AMP_POS | SPK_AMP_NEG)) {
176 if (!msm8930_ext_spk_pamp)
177 return;
Bhalchandra Gajare98a28cd2012-05-16 12:00:20 -0700178 if (machine_is_msm8930_mtp()
179 || machine_is_msm8930_fluid()) {
180 pr_debug("%s: Free speaker boost gpio %u\n",
181 __func__, SPKR_BOOST_GPIO);
182 gpio_direction_output(SPKR_BOOST_GPIO, 0);
183 gpio_free(SPKR_BOOST_GPIO);
184 }
Asish Bhattacharyac71827a2012-03-05 10:11:45 -0800185
186 pm8xxx_spk_enable(MSM8930_SPK_OFF);
187 msm8930_ext_spk_pamp = 0;
188 pr_debug("%s: slepping 4 ms after turning on external "
189 " Left Speaker Ampl\n", __func__);
190 usleep_range(4000, 4000);
191
192 } else {
193
194 pr_err("%s: ERROR : Invalid External Speaker Ampl. spk = 0x%08x\n",
195 __func__, spk);
196 return;
197 }
198}
199
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530200static int msm8930_spkramp_event(struct snd_soc_dapm_widget *w,
201 struct snd_kcontrol *k, int event)
202{
203 pr_debug("%s() %x\n", __func__, SND_SOC_DAPM_EVENT_ON(event));
Asish Bhattacharyac71827a2012-03-05 10:11:45 -0800204 if (SND_SOC_DAPM_EVENT_ON(event)) {
205 if (!strncmp(w->name, "Ext Spk Left Pos", 17))
206 msm8960_ext_spk_power_amp_on(SPK_AMP_POS);
207 else if (!strncmp(w->name, "Ext Spk Left Neg", 17))
208 msm8960_ext_spk_power_amp_on(SPK_AMP_NEG);
209 else {
210 pr_err("%s() Invalid Speaker Widget = %s\n",
211 __func__, w->name);
212 return -EINVAL;
213 }
214 } else {
215 if (!strncmp(w->name, "Ext Spk Left Pos", 17))
216 msm8960_ext_spk_power_amp_off(SPK_AMP_POS);
217 else if (!strncmp(w->name, "Ext Spk Left Neg", 17))
218 msm8960_ext_spk_power_amp_off(SPK_AMP_NEG);
219 else {
220 pr_err("%s() Invalid Speaker Widget = %s\n",
221 __func__, w->name);
222 return -EINVAL;
223 }
224 }
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530225 return 0;
226}
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800227
Bhalchandra Gajare466aafe2012-05-02 17:55:26 -0700228static int msm8930_enable_codec_ext_clk(
229 struct snd_soc_codec *codec, int enable,
230 bool dapm)
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530231{
232 pr_debug("%s: enable = %d\n", __func__, enable);
233 if (enable) {
234 clk_users++;
235 pr_debug("%s: clk_users = %d\n", __func__, clk_users);
236 if (clk_users != 1)
237 return 0;
238
239 if (codec_clk) {
240 clk_set_rate(codec_clk, SITAR_EXT_CLK_RATE);
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800241 clk_prepare_enable(codec_clk);
Bhalchandra Gajare466aafe2012-05-02 17:55:26 -0700242 sitar_mclk_enable(codec, 1, dapm);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530243 } else {
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800244 pr_err("%s: Error setting Sitar MCLK\n", __func__);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530245 clk_users--;
246 return -EINVAL;
247 }
248 } else {
249 pr_debug("%s: clk_users = %d\n", __func__, clk_users);
250 if (clk_users == 0)
251 return 0;
252 clk_users--;
253 if (!clk_users) {
254 pr_debug("%s: disabling MCLK. clk_users = %d\n",
255 __func__, clk_users);
Bhalchandra Gajare466aafe2012-05-02 17:55:26 -0700256 sitar_mclk_enable(codec, 0, dapm);
Bhalchandra Gajare2776af12012-04-27 16:59:39 -0700257 clk_disable_unprepare(codec_clk);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530258 }
259 }
260 return 0;
261}
262
263static int msm8930_mclk_event(struct snd_soc_dapm_widget *w,
264 struct snd_kcontrol *kcontrol, int event)
265{
266 pr_debug("%s: event = %d\n", __func__, event);
267
268 switch (event) {
269 case SND_SOC_DAPM_PRE_PMU:
Bhalchandra Gajare466aafe2012-05-02 17:55:26 -0700270 return msm8930_enable_codec_ext_clk(w->codec, 1, true);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530271 case SND_SOC_DAPM_POST_PMD:
Bhalchandra Gajare466aafe2012-05-02 17:55:26 -0700272 return msm8930_enable_codec_ext_clk(w->codec, 0, true);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530273 }
274 return 0;
275}
276
277static const struct snd_soc_dapm_widget msm8930_dapm_widgets[] = {
278
279 SND_SOC_DAPM_SUPPLY("MCLK", SND_SOC_NOPM, 0, 0,
280 msm8930_mclk_event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
281
282 SND_SOC_DAPM_SPK("Ext Spk Left Pos", msm8930_spkramp_event),
Asish Bhattacharyac71827a2012-03-05 10:11:45 -0800283 SND_SOC_DAPM_SPK("Ext Spk Left Neg", msm8930_spkramp_event),
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530284
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530285 SND_SOC_DAPM_MIC("Headset Mic", NULL),
286 SND_SOC_DAPM_MIC("Digital Mic1", NULL),
287 SND_SOC_DAPM_MIC("ANCRight Headset Mic", NULL),
288 SND_SOC_DAPM_MIC("ANCLeft Headset Mic", NULL),
289
290 SND_SOC_DAPM_MIC("Digital Mic1", NULL),
291 SND_SOC_DAPM_MIC("Digital Mic2", NULL),
292 SND_SOC_DAPM_MIC("Digital Mic3", NULL),
293 SND_SOC_DAPM_MIC("Digital Mic4", NULL),
294
295};
296
297static const struct snd_soc_dapm_route common_audio_map[] = {
298
299 {"RX_BIAS", NULL, "MCLK"},
300 {"LDO_H", NULL, "MCLK"},
301
302 {"MIC BIAS1 Internal1", NULL, "MCLK"},
303 {"MIC BIAS2 Internal1", NULL, "MCLK"},
304
305 /* Speaker path */
306 {"Ext Spk Left Pos", NULL, "LINEOUT1"},
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800307 {"Ext Spk Left Neg", NULL, "LINEOUT2"},
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530308
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800309 /* Headset Mic */
Bhalchandra Gajare553fb9e2012-06-26 14:48:54 -0700310 {"AMIC2", NULL, "MIC BIAS2 External"},
311 {"MIC BIAS2 External", NULL, "Headset Mic"},
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530312
313 /* Microphone path */
Bhalchandra Gajare18314d52012-06-06 19:03:01 -0700314 {"AMIC1", NULL, "MIC BIAS2 External"},
315 {"MIC BIAS2 External", NULL, "ANCLeft Headset Mic"},
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800316
Bhalchandra Gajare18314d52012-06-06 19:03:01 -0700317 {"AMIC3", NULL, "MIC BIAS2 External"},
318 {"MIC BIAS2 External", NULL, "ANCRight Headset Mic"},
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530319
320 {"HEADPHONE", NULL, "LDO_H"},
321
322 /**
323 * The digital Mic routes are setup considering
324 * fluid as default device.
325 */
326
327 /**
Bhalchandra Gajaree6a30f72012-05-23 19:46:21 -0700328 * Digital Mic1. Front Bottom left Mic on Fluid and MTP.
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530329 * Digital Mic GM5 on CDP mainboard.
Bhalchandra Gajaree6a30f72012-05-23 19:46:21 -0700330 * Conncted to DMIC1 Input on Sitar codec.
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530331 */
332 {"DMIC1", NULL, "MIC BIAS1 External"},
333 {"MIC BIAS1 External", NULL, "Digital Mic1"},
334
335 /**
Bhalchandra Gajaree6a30f72012-05-23 19:46:21 -0700336 * Digital Mic2. Back top MIC on Fluid.
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530337 * Digital Mic GM6 on CDP mainboard.
Bhalchandra Gajaree6a30f72012-05-23 19:46:21 -0700338 * Conncted to DMIC2 Input on Sitar codec.
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530339 */
340 {"DMIC2", NULL, "MIC BIAS1 External"},
341 {"MIC BIAS1 External", NULL, "Digital Mic2"},
342 /**
343 * Digital Mic3. Back Bottom Digital Mic on Fluid.
344 * Digital Mic GM1 on CDP mainboard.
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800345 * Conncted to DMIC4 Input on Sitar codec.
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530346 */
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800347 {"DMIC3", NULL, "MIC BIAS1 External"},
348 {"MIC BIAS1 External", NULL, "Digital Mic3"},
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530349
350 /**
351 * Digital Mic4. Back top Digital Mic on Fluid.
352 * Digital Mic GM2 on CDP mainboard.
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800353 * Conncted to DMIC3 Input on Sitar codec.
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530354 */
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800355 {"DMIC4", NULL, "MIC BIAS1 External"},
356 {"MIC BIAS1 External", NULL, "Digital Mic4"},
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530357
358
359};
360
361static const char *spk_function[] = {"Off", "On"};
362static const char *slim0_rx_ch_text[] = {"One", "Two"};
363static const char *slim0_tx_ch_text[] = {"One", "Two", "Three", "Four"};
364
365static const struct soc_enum msm8930_enum[] = {
366 SOC_ENUM_SINGLE_EXT(2, spk_function),
367 SOC_ENUM_SINGLE_EXT(2, slim0_rx_ch_text),
368 SOC_ENUM_SINGLE_EXT(4, slim0_tx_ch_text),
369};
370
371static const char *btsco_rate_text[] = {"8000", "16000"};
372static const struct soc_enum msm8930_btsco_enum[] = {
373 SOC_ENUM_SINGLE_EXT(2, btsco_rate_text),
374};
375
376static int msm8930_slim_0_rx_ch_get(struct snd_kcontrol *kcontrol,
377 struct snd_ctl_elem_value *ucontrol)
378{
379 pr_debug("%s: msm8930_slim_0_rx_ch = %d\n", __func__,
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800380 msm8930_slim_0_rx_ch);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530381 ucontrol->value.integer.value[0] = msm8930_slim_0_rx_ch - 1;
382 return 0;
383}
384
385static int msm8930_slim_0_rx_ch_put(struct snd_kcontrol *kcontrol,
386 struct snd_ctl_elem_value *ucontrol)
387{
388 msm8930_slim_0_rx_ch = ucontrol->value.integer.value[0] + 1;
389
390 pr_debug("%s: msm8930_slim_0_rx_ch = %d\n", __func__,
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800391 msm8930_slim_0_rx_ch);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530392 return 1;
393}
394
395static int msm8930_slim_0_tx_ch_get(struct snd_kcontrol *kcontrol,
396 struct snd_ctl_elem_value *ucontrol)
397{
398 pr_debug("%s: msm8930_slim_0_tx_ch = %d\n", __func__,
399 msm8930_slim_0_tx_ch);
400 ucontrol->value.integer.value[0] = msm8930_slim_0_tx_ch - 1;
401 return 0;
402}
403
404static int msm8930_slim_0_tx_ch_put(struct snd_kcontrol *kcontrol,
405 struct snd_ctl_elem_value *ucontrol)
406{
407 msm8930_slim_0_tx_ch = ucontrol->value.integer.value[0] + 1;
408
409 pr_debug("%s: msm8930_slim_0_tx_ch = %d\n", __func__,
410 msm8930_slim_0_tx_ch);
411 return 1;
412}
413
414static int msm8930_btsco_rate_get(struct snd_kcontrol *kcontrol,
415 struct snd_ctl_elem_value *ucontrol)
416{
417 pr_debug("%s: msm8930_btsco_rate = %d", __func__, msm8930_btsco_rate);
418 ucontrol->value.integer.value[0] = msm8930_btsco_rate;
419 return 0;
420}
421
422static int msm8930_btsco_rate_put(struct snd_kcontrol *kcontrol,
423 struct snd_ctl_elem_value *ucontrol)
424{
425 switch (ucontrol->value.integer.value[0]) {
426 case 0:
427 msm8930_btsco_rate = BTSCO_RATE_8KHZ;
428 break;
429 case 1:
430 msm8930_btsco_rate = BTSCO_RATE_16KHZ;
431 break;
432 default:
433 msm8930_btsco_rate = BTSCO_RATE_8KHZ;
434 break;
435 }
436 pr_debug("%s: msm8930_btsco_rate = %d\n", __func__, msm8930_btsco_rate);
437 return 0;
438}
439
Bhalchandra Gajare97676792012-05-22 17:41:45 -0700440static const char *pmic_spk_gain_text[] = {
441 "NEG_6_DB", "NEG_4_DB", "NEG_2_DB", "ZERO_DB", "POS_2_DB", "POS_4_DB",
442 "POS_6_DB", "POS_8_DB", "POS_10_DB", "POS_12_DB", "POS_14_DB",
443 "POS_16_DB", "POS_18_DB", "POS_20_DB", "POS_22_DB", "POS_24_DB"
444};
445
446static const struct soc_enum msm8960_pmic_spk_gain_enum[] = {
447 SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(pmic_spk_gain_text),
448 pmic_spk_gain_text),
449};
450
451static int msm8930_pmic_gain_get(struct snd_kcontrol *kcontrol,
452 struct snd_ctl_elem_value *ucontrol)
453{
454 pr_debug("%s: msm8930_pmic_spk_gain = %d\n", __func__,
455 msm8930_pmic_spk_gain);
456 ucontrol->value.integer.value[0] = msm8930_pmic_spk_gain;
457 return 0;
458}
459
460static int msm8930_pmic_gain_put(struct snd_kcontrol *kcontrol,
461 struct snd_ctl_elem_value *ucontrol)
462{
463 int ret = 0;
464 msm8930_pmic_spk_gain = ucontrol->value.integer.value[0];
465 ret = pm8xxx_spk_gain(msm8930_pmic_spk_gain);
466 pr_debug("%s: msm8930_pmic_spk_gain = %d"
467 " ucontrol->value.integer.value[0] = %d\n", __func__,
468 msm8930_pmic_spk_gain,
469 (int) ucontrol->value.integer.value[0]);
470 return ret;
471}
472
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530473static const struct snd_kcontrol_new sitar_msm8930_controls[] = {
474 SOC_ENUM_EXT("Speaker Function", msm8930_enum[0], msm8930_get_spk,
475 msm8930_set_spk),
476 SOC_ENUM_EXT("SLIM_0_RX Channels", msm8930_enum[1],
477 msm8930_slim_0_rx_ch_get, msm8930_slim_0_rx_ch_put),
478 SOC_ENUM_EXT("SLIM_0_TX Channels", msm8930_enum[2],
479 msm8930_slim_0_tx_ch_get, msm8930_slim_0_tx_ch_put),
Bhalchandra Gajare97676792012-05-22 17:41:45 -0700480 SOC_ENUM_EXT("PMIC SPK Gain", msm8960_pmic_spk_gain_enum[0],
481 msm8930_pmic_gain_get, msm8930_pmic_gain_put),
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530482 SOC_ENUM_EXT("Internal BTSCO SampleRate", msm8930_btsco_enum[0],
483 msm8930_btsco_rate_get, msm8930_btsco_rate_put),
484};
485
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800486static void *def_sitar_mbhc_cal(void)
487{
488 void *sitar_cal;
489 struct sitar_mbhc_btn_detect_cfg *btn_cfg;
490 u16 *btn_low, *btn_high;
491 u8 *n_ready, *n_cic, *gain;
492
493 sitar_cal = kzalloc(SITAR_MBHC_CAL_SIZE(SITAR_MBHC_DEF_BUTTONS,
494 SITAR_MBHC_DEF_RLOADS),
495 GFP_KERNEL);
496 if (!sitar_cal) {
497 pr_err("%s: out of memory\n", __func__);
498 return NULL;
499 }
500
501#define S(X, Y) ((SITAR_MBHC_CAL_GENERAL_PTR(sitar_cal)->X) = (Y))
502 S(t_ldoh, 100);
503 S(t_bg_fast_settle, 100);
504 S(t_shutdown_plug_rem, 255);
505 S(mbhc_nsa, 4);
506 S(mbhc_navg, 4);
507#undef S
508#define S(X, Y) ((SITAR_MBHC_CAL_PLUG_DET_PTR(sitar_cal)->X) = (Y))
509 S(mic_current, SITAR_PID_MIC_5_UA);
510 S(hph_current, SITAR_PID_MIC_5_UA);
511 S(t_mic_pid, 100);
512 S(t_ins_complete, 250);
513 S(t_ins_retry, 200);
514#undef S
515#define S(X, Y) ((SITAR_MBHC_CAL_PLUG_TYPE_PTR(sitar_cal)->X) = (Y))
516 S(v_no_mic, 30);
Bhalchandra Gajare18314d52012-06-06 19:03:01 -0700517 S(v_hs_max, 1650);
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800518#undef S
519#define S(X, Y) ((SITAR_MBHC_CAL_BTN_DET_PTR(sitar_cal)->X) = (Y))
520 S(c[0], 62);
521 S(c[1], 124);
522 S(nc, 1);
523 S(n_meas, 3);
524 S(mbhc_nsc, 11);
525 S(n_btn_meas, 1);
526 S(n_btn_con, 2);
527 S(num_btn, SITAR_MBHC_DEF_BUTTONS);
528 S(v_btn_press_delta_sta, 100);
529 S(v_btn_press_delta_cic, 50);
530#undef S
531 btn_cfg = SITAR_MBHC_CAL_BTN_DET_PTR(sitar_cal);
532 btn_low = sitar_mbhc_cal_btn_det_mp(btn_cfg, SITAR_BTN_DET_V_BTN_LOW);
533 btn_high = sitar_mbhc_cal_btn_det_mp(btn_cfg, SITAR_BTN_DET_V_BTN_HIGH);
534 btn_low[0] = -50;
535 btn_high[0] = 10;
536 btn_low[1] = 11;
537 btn_high[1] = 38;
538 btn_low[2] = 39;
539 btn_high[2] = 64;
540 btn_low[3] = 65;
541 btn_high[3] = 91;
542 btn_low[4] = 92;
543 btn_high[4] = 115;
544 btn_low[5] = 116;
545 btn_high[5] = 141;
546 btn_low[6] = 142;
547 btn_high[6] = 163;
548 btn_low[7] = 164;
549 btn_high[7] = 250;
550 n_ready = sitar_mbhc_cal_btn_det_mp(btn_cfg, SITAR_BTN_DET_N_READY);
551 n_ready[0] = 48;
552 n_ready[1] = 38;
553 n_cic = sitar_mbhc_cal_btn_det_mp(btn_cfg, SITAR_BTN_DET_N_CIC);
554 n_cic[0] = 60;
555 n_cic[1] = 47;
556 gain = sitar_mbhc_cal_btn_det_mp(btn_cfg, SITAR_BTN_DET_GAIN);
557 gain[0] = 11;
558 gain[1] = 9;
559
560 return sitar_cal;
561}
562
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530563static int msm8930_hw_params(struct snd_pcm_substream *substream,
564 struct snd_pcm_hw_params *params)
565{
566 struct snd_soc_pcm_runtime *rtd = substream->private_data;
567 struct snd_soc_dai *codec_dai = rtd->codec_dai;
568 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
569 int ret = 0;
570 unsigned int rx_ch[SLIM_MAX_RX_PORTS], tx_ch[SLIM_MAX_TX_PORTS];
571 unsigned int rx_ch_cnt = 0, tx_ch_cnt = 0;
572
573 pr_debug("%s: ch=%d\n", __func__,
574 msm8930_slim_0_rx_ch);
575 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
576 ret = snd_soc_dai_get_channel_map(codec_dai,
577 &tx_ch_cnt, tx_ch, &rx_ch_cnt , rx_ch);
578 if (ret < 0) {
579 pr_err("%s: failed to get codec chan map\n", __func__);
580 goto end;
581 }
582
583 ret = snd_soc_dai_set_channel_map(cpu_dai, 0, 0,
584 msm8930_slim_0_rx_ch, rx_ch);
585 if (ret < 0) {
586 pr_err("%s: failed to set cpu chan map\n", __func__);
587 goto end;
588 }
589 ret = snd_soc_dai_set_channel_map(codec_dai, 0, 0,
590 msm8930_slim_0_rx_ch, rx_ch);
591 if (ret < 0) {
592 pr_err("%s: failed to set codec channel map\n",
593 __func__);
594 goto end;
595 }
596 } else {
597 ret = snd_soc_dai_get_channel_map(codec_dai,
598 &tx_ch_cnt, tx_ch, &rx_ch_cnt , rx_ch);
599 if (ret < 0) {
600 pr_err("%s: failed to get codec chan map\n", __func__);
601 goto end;
602 }
603 ret = snd_soc_dai_set_channel_map(cpu_dai,
604 msm8930_slim_0_tx_ch, tx_ch, 0 , 0);
605 if (ret < 0) {
606 pr_err("%s: failed to set cpu chan map\n", __func__);
607 goto end;
608 }
609 ret = snd_soc_dai_set_channel_map(codec_dai,
610 msm8930_slim_0_tx_ch, tx_ch, 0, 0);
611 if (ret < 0) {
612 pr_err("%s: failed to set codec channel map\n",
613 __func__);
614 goto end;
615 }
616
617 }
618end:
619 return ret;
620}
621
622static int msm8930_audrx_init(struct snd_soc_pcm_runtime *rtd)
623{
624 int err;
625 struct snd_soc_codec *codec = rtd->codec;
626 struct snd_soc_dapm_context *dapm = &codec->dapm;
627 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
628
629 pr_debug("%s()\n", __func__);
630
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530631 snd_soc_dapm_new_controls(dapm, msm8930_dapm_widgets,
632 ARRAY_SIZE(msm8930_dapm_widgets));
633
634 snd_soc_dapm_add_routes(dapm, common_audio_map,
635 ARRAY_SIZE(common_audio_map));
636
637 snd_soc_dapm_enable_pin(dapm, "Ext Spk Left Pos");
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800638 snd_soc_dapm_enable_pin(dapm, "Ext Spk Left Neg");
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530639
640 snd_soc_dapm_sync(dapm);
641
642 err = snd_soc_jack_new(codec, "Headset Jack",
643 (SND_JACK_HEADSET | SND_JACK_OC_HPHL | SND_JACK_OC_HPHR),
644 &hs_jack);
645 if (err) {
646 pr_err("failed to create new jack\n");
647 return err;
648 }
649
650 err = snd_soc_jack_new(codec, "Button Jack",
Bhalchandra Gajare7708ee32012-05-24 17:37:37 -0700651 SITAR_JACK_BUTTON_MASK, &button_jack);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530652 if (err) {
653 pr_err("failed to create new jack\n");
654 return err;
655 }
656 codec_clk = clk_get(cpu_dai->dev, "osr_clk");
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800657
Bhalchandra Gajare466aafe2012-05-02 17:55:26 -0700658 mbhc_cfg.gpio = 37;
659 mbhc_cfg.gpio_irq = gpio_to_irq(mbhc_cfg.gpio);
660 sitar_hs_detect(codec, &mbhc_cfg);
661
Bhalchandra Gajare97676792012-05-22 17:41:45 -0700662 /* Initialize default PMIC speaker gain */
663 pm8xxx_spk_gain(DEFAULT_PMIC_SPK_GAIN);
664
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530665 return 0;
666}
667
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530668static int msm8930_slim_0_rx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
669 struct snd_pcm_hw_params *params)
670{
671 struct snd_interval *rate = hw_param_interval(params,
672 SNDRV_PCM_HW_PARAM_RATE);
673
674 struct snd_interval *channels = hw_param_interval(params,
675 SNDRV_PCM_HW_PARAM_CHANNELS);
676
677 pr_debug("%s()\n", __func__);
678 rate->min = rate->max = 48000;
679 channels->min = channels->max = msm8930_slim_0_rx_ch;
680
681 return 0;
682}
683
684static int msm8930_slim_0_tx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
685 struct snd_pcm_hw_params *params)
686{
687 struct snd_interval *rate = hw_param_interval(params,
688 SNDRV_PCM_HW_PARAM_RATE);
689
690 struct snd_interval *channels = hw_param_interval(params,
691 SNDRV_PCM_HW_PARAM_CHANNELS);
692
693 pr_debug("%s()\n", __func__);
694 rate->min = rate->max = 48000;
695 channels->min = channels->max = msm8930_slim_0_tx_ch;
696
697 return 0;
698}
699
700static int msm8930_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
701 struct snd_pcm_hw_params *params)
702{
703 struct snd_interval *rate = hw_param_interval(params,
704 SNDRV_PCM_HW_PARAM_RATE);
705
706 pr_debug("%s()\n", __func__);
707 rate->min = rate->max = 48000;
708
709 return 0;
710}
711
712static int msm8930_hdmi_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
713 struct snd_pcm_hw_params *params)
714{
715 struct snd_interval *rate = hw_param_interval(params,
716 SNDRV_PCM_HW_PARAM_RATE);
717
718 struct snd_interval *channels = hw_param_interval(params,
719 SNDRV_PCM_HW_PARAM_CHANNELS);
720
721 rate->min = rate->max = 48000;
722 channels->min = channels->max = 2;
723
724 return 0;
725}
726
727static int msm8930_btsco_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
728 struct snd_pcm_hw_params *params)
729{
730 struct snd_interval *rate = hw_param_interval(params,
731 SNDRV_PCM_HW_PARAM_RATE);
732
733 struct snd_interval *channels = hw_param_interval(params,
734 SNDRV_PCM_HW_PARAM_CHANNELS);
735
736 rate->min = rate->max = msm8930_btsco_rate;
737 channels->min = channels->max = msm8930_btsco_ch;
738
739 return 0;
740}
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530741
Bhalchandra Gajare2e0893e2012-05-24 00:39:47 -0700742static int msm8930_auxpcm_be_params_fixup(struct snd_soc_pcm_runtime *rtd,
743 struct snd_pcm_hw_params *params)
744{
745 struct snd_interval *rate = hw_param_interval(params,
746 SNDRV_PCM_HW_PARAM_RATE);
747
748 struct snd_interval *channels = hw_param_interval(params,
749 SNDRV_PCM_HW_PARAM_CHANNELS);
750
751 /* PCM only supports mono output with 8khz sample rate */
752 rate->min = rate->max = 8000;
753 channels->min = channels->max = 1;
754
755 return 0;
756}
757
758static int msm8930_aux_pcm_get_gpios(void)
759{
760 int ret = 0;
761
762 pr_debug("%s\n", __func__);
763
764 ret = gpio_request(GPIO_AUX_PCM_DOUT, "AUX PCM DOUT");
765 if (ret < 0) {
766 pr_err("%s: Failed to request gpio(%d): AUX PCM DOUT",
767 __func__, GPIO_AUX_PCM_DOUT);
768
769 goto fail_dout;
770 }
771
772 ret = gpio_request(GPIO_AUX_PCM_DIN, "AUX PCM DIN");
773 if (ret < 0) {
774 pr_err("%s: Failed to request gpio(%d): AUX PCM DIN",
775 __func__, GPIO_AUX_PCM_DIN);
776 goto fail_din;
777 }
778
779 ret = gpio_request(GPIO_AUX_PCM_SYNC, "AUX PCM SYNC");
780 if (ret < 0) {
781 pr_err("%s: Failed to request gpio(%d): AUX PCM SYNC",
782 __func__, GPIO_AUX_PCM_SYNC);
783 goto fail_sync;
784 }
785
786 ret = gpio_request(GPIO_AUX_PCM_CLK, "AUX PCM CLK");
787 if (ret < 0) {
788 pr_err("%s: Failed to request gpio(%d): AUX PCM CLK",
789 __func__, GPIO_AUX_PCM_CLK);
790 goto fail_clk;
791 }
792
793 return 0;
794
795fail_clk:
796 gpio_free(GPIO_AUX_PCM_SYNC);
797fail_sync:
798 gpio_free(GPIO_AUX_PCM_DIN);
799fail_din:
800 gpio_free(GPIO_AUX_PCM_DOUT);
801fail_dout:
802
803 return ret;
804}
805
806static int msm8930_aux_pcm_free_gpios(void)
807{
808 gpio_free(GPIO_AUX_PCM_DIN);
809 gpio_free(GPIO_AUX_PCM_DOUT);
810 gpio_free(GPIO_AUX_PCM_SYNC);
811 gpio_free(GPIO_AUX_PCM_CLK);
812
813 return 0;
814}
815
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530816static int msm8930_startup(struct snd_pcm_substream *substream)
817{
818 pr_debug("%s(): substream = %s stream = %d\n", __func__,
819 substream->name, substream->stream);
820 return 0;
821}
822
Bhalchandra Gajare2e0893e2012-05-24 00:39:47 -0700823static int msm8930_auxpcm_startup(struct snd_pcm_substream *substream)
824{
825 int ret = 0;
826
827 pr_debug("%s(): substream = %s\n", __func__, substream->name);
828 ret = msm8930_aux_pcm_get_gpios();
829 if (ret < 0) {
830 pr_err("%s: Aux PCM GPIO request failed\n", __func__);
831 return -EINVAL;
832 }
833 return 0;
834
835}
836
837static void msm8930_auxpcm_shutdown(struct snd_pcm_substream *substream)
838{
839 pr_debug("%s(): substream = %s\n", __func__, substream->name);
840 msm8930_aux_pcm_free_gpios();
841}
842
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530843static void msm8930_shutdown(struct snd_pcm_substream *substream)
844{
845 pr_debug("%s(): substream = %s stream = %d\n", __func__,
846 substream->name, substream->stream);
847}
848
849static struct snd_soc_ops msm8930_be_ops = {
850 .startup = msm8930_startup,
851 .hw_params = msm8930_hw_params,
852 .shutdown = msm8930_shutdown,
853};
854
Bhalchandra Gajare2e0893e2012-05-24 00:39:47 -0700855static struct snd_soc_ops msm8930_auxpcm_be_ops = {
856 .startup = msm8930_auxpcm_startup,
857 .shutdown = msm8930_auxpcm_shutdown,
858};
859
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530860/* Digital audio interface glue - connects codec <---> CPU */
861static struct snd_soc_dai_link msm8930_dai[] = {
862 /* FrontEnd DAI Links */
863 {
864 .name = "MSM8930 Media1",
865 .stream_name = "MultiMedia1",
866 .cpu_dai_name = "MultiMedia1",
867 .platform_name = "msm-pcm-dsp",
868 .dynamic = 1,
Steve Mucklef132c6c2012-06-06 18:30:57 -0700869 .codec_dai_name = "snd-soc-dummy-dai",
870 .codec_name = "snd-soc-dummy",
871 .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
872 .ignore_suspend = 1,
873 .ignore_pmdown_time = 1, /* this dainlink has playback support */
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530874 .be_id = MSM_FRONTEND_DAI_MULTIMEDIA1
875 },
876 {
877 .name = "MSM8930 Media2",
878 .stream_name = "MultiMedia2",
879 .cpu_dai_name = "MultiMedia2",
Asish Bhattacharyae2601ae2012-07-18 21:13:21 +0530880 .platform_name = "msm-multi-ch-pcm-dsp",
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530881 .dynamic = 1,
Steve Mucklef132c6c2012-06-06 18:30:57 -0700882 .codec_dai_name = "snd-soc-dummy-dai",
883 .codec_name = "snd-soc-dummy",
884 .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
885 .ignore_suspend = 1,
886 .ignore_pmdown_time = 1, /* this dainlink has playback support */
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530887 .be_id = MSM_FRONTEND_DAI_MULTIMEDIA2,
888 },
889 {
890 .name = "Circuit-Switch Voice",
891 .stream_name = "CS-Voice",
892 .cpu_dai_name = "CS-VOICE",
893 .platform_name = "msm-pcm-voice",
894 .dynamic = 1,
Steve Mucklef132c6c2012-06-06 18:30:57 -0700895 .codec_dai_name = "snd-soc-dummy-dai",
896 .codec_name = "snd-soc-dummy",
897 .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530898 .be_id = MSM_FRONTEND_DAI_CS_VOICE,
899 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
900 .ignore_suspend = 1,
Steve Mucklef132c6c2012-06-06 18:30:57 -0700901 .ignore_pmdown_time = 1, /* this dainlink has playback support */
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530902 },
903 {
904 .name = "MSM VoIP",
905 .stream_name = "VoIP",
906 .cpu_dai_name = "VoIP",
907 .platform_name = "msm-voip-dsp",
908 .dynamic = 1,
Steve Mucklef132c6c2012-06-06 18:30:57 -0700909 .codec_dai_name = "snd-soc-dummy-dai",
910 .codec_name = "snd-soc-dummy",
911 .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
912 .ignore_suspend = 1,
913 .ignore_pmdown_time = 1, /* this dainlink has playback support */
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530914 .be_id = MSM_FRONTEND_DAI_VOIP,
915 },
916 {
917 .name = "MSM8930 LPA",
918 .stream_name = "LPA",
919 .cpu_dai_name = "MultiMedia3",
920 .platform_name = "msm-pcm-lpa",
921 .dynamic = 1,
Steve Mucklef132c6c2012-06-06 18:30:57 -0700922 .codec_dai_name = "snd-soc-dummy-dai",
923 .codec_name = "snd-soc-dummy",
924 .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
925 .ignore_suspend = 1,
926 .ignore_pmdown_time = 1, /* this dainlink has playback support */
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530927 .be_id = MSM_FRONTEND_DAI_MULTIMEDIA3,
928 },
929 /* Hostless PMC purpose */
930 {
931 .name = "SLIMBUS_0 Hostless",
932 .stream_name = "SLIMBUS_0 Hostless",
933 .cpu_dai_name = "SLIMBUS0_HOSTLESS",
934 .platform_name = "msm-pcm-hostless",
935 .dynamic = 1,
Steve Mucklef132c6c2012-06-06 18:30:57 -0700936 .codec_dai_name = "snd-soc-dummy-dai",
937 .codec_name = "snd-soc-dummy",
938 .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530939 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
940 .ignore_suspend = 1,
Steve Mucklef132c6c2012-06-06 18:30:57 -0700941 .ignore_pmdown_time = 1, /* this dainlink has playback support */
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530942 /* .be_id = do not care */
943 },
944 {
945 .name = "INT_FM Hostless",
946 .stream_name = "INT_FM Hostless",
947 .cpu_dai_name = "INT_FM_HOSTLESS",
948 .platform_name = "msm-pcm-hostless",
949 .dynamic = 1,
Steve Mucklef132c6c2012-06-06 18:30:57 -0700950 .codec_dai_name = "snd-soc-dummy-dai",
951 .codec_name = "snd-soc-dummy",
952 .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530953 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
954 .ignore_suspend = 1,
Steve Mucklef132c6c2012-06-06 18:30:57 -0700955 .ignore_pmdown_time = 1, /* this dainlink has playback support */
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530956 /* .be_id = do not care */
957 },
958 {
959 .name = "MSM AFE-PCM RX",
960 .stream_name = "AFE-PROXY RX",
961 .cpu_dai_name = "msm-dai-q6.241",
962 .codec_name = "msm-stub-codec.1",
963 .codec_dai_name = "msm-stub-rx",
964 .platform_name = "msm-pcm-afe",
965 .ignore_suspend = 1,
Steve Mucklef132c6c2012-06-06 18:30:57 -0700966 .ignore_pmdown_time = 1, /* this dainlink has playback support */
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530967 },
968 {
969 .name = "MSM AFE-PCM TX",
970 .stream_name = "AFE-PROXY TX",
971 .cpu_dai_name = "msm-dai-q6.240",
972 .codec_name = "msm-stub-codec.1",
973 .codec_dai_name = "msm-stub-tx",
974 .platform_name = "msm-pcm-afe",
975 .ignore_suspend = 1,
976 },
977 {
978 .name = "MSM8930 Compr",
979 .stream_name = "COMPR",
980 .cpu_dai_name = "MultiMedia4",
981 .platform_name = "msm-compr-dsp",
982 .dynamic = 1,
Steve Mucklef132c6c2012-06-06 18:30:57 -0700983 .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
984 .codec_dai_name = "snd-soc-dummy-dai",
985 .codec_name = "snd-soc-dummy",
986 .ignore_suspend = 1,
987 .ignore_pmdown_time = 1, /* this dainlink has playback support */
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530988 .be_id = MSM_FRONTEND_DAI_MULTIMEDIA4,
989 },
990 {
991 .name = "AUXPCM Hostless",
992 .stream_name = "AUXPCM Hostless",
993 .cpu_dai_name = "AUXPCM_HOSTLESS",
994 .platform_name = "msm-pcm-hostless",
995 .dynamic = 1,
Steve Mucklef132c6c2012-06-06 18:30:57 -0700996 .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530997 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
998 .ignore_suspend = 1,
Steve Mucklef132c6c2012-06-06 18:30:57 -0700999 .ignore_pmdown_time = 1, /* this dainlink has playback support */
1000 .codec_dai_name = "snd-soc-dummy-dai",
1001 .codec_name = "snd-soc-dummy",
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301002 },
1003 /* HDMI Hostless */
1004 {
1005 .name = "HDMI_RX_HOSTLESS",
1006 .stream_name = "HDMI_RX_HOSTLESS",
1007 .cpu_dai_name = "HDMI_HOSTLESS",
1008 .platform_name = "msm-pcm-hostless",
1009 .dynamic = 1,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001010 .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301011 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301012 .ignore_suspend = 1,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001013 .ignore_pmdown_time = 1, /* this dainlink has playback support */
1014 .codec_dai_name = "snd-soc-dummy-dai",
1015 .codec_name = "snd-soc-dummy",
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301016 },
1017 /* Backend DAI Links */
1018 {
1019 .name = LPASS_BE_SLIMBUS_0_RX,
1020 .stream_name = "Slimbus Playback",
1021 .cpu_dai_name = "msm-dai-q6.16384",
1022 .platform_name = "msm-pcm-routing",
1023 .codec_name = "sitar_codec",
1024 .codec_dai_name = "sitar_rx1",
1025 .no_pcm = 1,
1026 .be_id = MSM_BACKEND_DAI_SLIMBUS_0_RX,
1027 .init = &msm8930_audrx_init,
1028 .be_hw_params_fixup = msm8930_slim_0_rx_be_hw_params_fixup,
1029 .ops = &msm8930_be_ops,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001030 .ignore_pmdown_time = 1, /* this dainlink has playback support */
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301031 },
1032 {
1033 .name = LPASS_BE_SLIMBUS_0_TX,
1034 .stream_name = "Slimbus Capture",
1035 .cpu_dai_name = "msm-dai-q6.16385",
1036 .platform_name = "msm-pcm-routing",
1037 .codec_name = "sitar_codec",
1038 .codec_dai_name = "sitar_tx1",
1039 .no_pcm = 1,
1040 .be_id = MSM_BACKEND_DAI_SLIMBUS_0_TX,
1041 .be_hw_params_fixup = msm8930_slim_0_tx_be_hw_params_fixup,
1042 .ops = &msm8930_be_ops,
1043 },
1044 /* Backend BT/FM DAI Links */
1045 {
1046 .name = LPASS_BE_INT_BT_SCO_RX,
1047 .stream_name = "Internal BT-SCO Playback",
1048 .cpu_dai_name = "msm-dai-q6.12288",
1049 .platform_name = "msm-pcm-routing",
1050 .codec_name = "msm-stub-codec.1",
1051 .codec_dai_name = "msm-stub-rx",
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301052 .no_pcm = 1,
1053 .be_id = MSM_BACKEND_DAI_INT_BT_SCO_RX,
1054 .be_hw_params_fixup = msm8930_btsco_be_hw_params_fixup,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001055 .ignore_pmdown_time = 1, /* this dainlink has playback support */
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301056 },
1057 {
1058 .name = LPASS_BE_INT_BT_SCO_TX,
1059 .stream_name = "Internal BT-SCO Capture",
1060 .cpu_dai_name = "msm-dai-q6.12289",
1061 .platform_name = "msm-pcm-routing",
1062 .codec_name = "msm-stub-codec.1",
1063 .codec_dai_name = "msm-stub-tx",
1064 .no_pcm = 1,
1065 .be_id = MSM_BACKEND_DAI_INT_BT_SCO_TX,
1066 .be_hw_params_fixup = msm8930_btsco_be_hw_params_fixup,
1067 },
1068 {
1069 .name = LPASS_BE_INT_FM_RX,
1070 .stream_name = "Internal FM Playback",
1071 .cpu_dai_name = "msm-dai-q6.12292",
1072 .platform_name = "msm-pcm-routing",
1073 .codec_name = "msm-stub-codec.1",
1074 .codec_dai_name = "msm-stub-rx",
1075 .no_pcm = 1,
1076 .be_id = MSM_BACKEND_DAI_INT_FM_RX,
1077 .be_hw_params_fixup = msm8930_be_hw_params_fixup,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001078 .ignore_pmdown_time = 1, /* this dainlink has playback support */
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301079 },
1080 {
1081 .name = LPASS_BE_INT_FM_TX,
1082 .stream_name = "Internal FM Capture",
1083 .cpu_dai_name = "msm-dai-q6.12293",
1084 .platform_name = "msm-pcm-routing",
1085 .codec_name = "msm-stub-codec.1",
1086 .codec_dai_name = "msm-stub-tx",
1087 .no_pcm = 1,
1088 .be_id = MSM_BACKEND_DAI_INT_FM_TX,
1089 .be_hw_params_fixup = msm8930_be_hw_params_fixup,
1090 },
1091 /* HDMI BACK END DAI Link */
1092 {
1093 .name = LPASS_BE_HDMI,
1094 .stream_name = "HDMI Playback",
1095 .cpu_dai_name = "msm-dai-q6-hdmi.8",
1096 .platform_name = "msm-pcm-routing",
1097 .codec_name = "msm-stub-codec.1",
1098 .codec_dai_name = "msm-stub-rx",
1099 .no_pcm = 1,
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301100 .be_id = MSM_BACKEND_DAI_HDMI_RX,
1101 .be_hw_params_fixup = msm8930_hdmi_be_hw_params_fixup,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001102 .ignore_pmdown_time = 1, /* this dainlink has playback support */
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301103 },
1104 /* Backend AFE DAI Links */
1105 {
1106 .name = LPASS_BE_AFE_PCM_RX,
1107 .stream_name = "AFE Playback",
1108 .cpu_dai_name = "msm-dai-q6.224",
1109 .platform_name = "msm-pcm-routing",
1110 .codec_name = "msm-stub-codec.1",
1111 .codec_dai_name = "msm-stub-rx",
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301112 .no_pcm = 1,
1113 .be_id = MSM_BACKEND_DAI_AFE_PCM_RX,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001114 .ignore_pmdown_time = 1, /* this dainlink has playback support */
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301115 },
1116 {
1117 .name = LPASS_BE_AFE_PCM_TX,
1118 .stream_name = "AFE Capture",
1119 .cpu_dai_name = "msm-dai-q6.225",
1120 .platform_name = "msm-pcm-routing",
1121 .codec_name = "msm-stub-codec.1",
1122 .codec_dai_name = "msm-stub-tx",
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301123 .no_pcm = 1,
1124 .be_id = MSM_BACKEND_DAI_AFE_PCM_TX,
1125 },
Bhalchandra Gajare2e0893e2012-05-24 00:39:47 -07001126 /* AUX PCM Backend DAI Links */
1127 {
1128 .name = LPASS_BE_AUXPCM_RX,
1129 .stream_name = "AUX PCM Playback",
1130 .cpu_dai_name = "msm-dai-q6.2",
1131 .platform_name = "msm-pcm-routing",
1132 .codec_name = "msm-stub-codec.1",
1133 .codec_dai_name = "msm-stub-rx",
1134 .no_pcm = 1,
1135 .be_id = MSM_BACKEND_DAI_AUXPCM_RX,
1136 .be_hw_params_fixup = msm8930_auxpcm_be_params_fixup,
1137 .ops = &msm8930_auxpcm_be_ops,
1138 },
1139 {
1140 .name = LPASS_BE_AUXPCM_TX,
1141 .stream_name = "AUX PCM Capture",
1142 .cpu_dai_name = "msm-dai-q6.3",
1143 .platform_name = "msm-pcm-routing",
1144 .codec_name = "msm-stub-codec.1",
1145 .codec_dai_name = "msm-stub-tx",
1146 .no_pcm = 1,
1147 .be_id = MSM_BACKEND_DAI_AUXPCM_TX,
1148 .be_hw_params_fixup = msm8930_auxpcm_be_params_fixup,
1149 },
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301150 /* Incall Music BACK END DAI Link */
1151 {
1152 .name = LPASS_BE_VOICE_PLAYBACK_TX,
1153 .stream_name = "Voice Farend Playback",
1154 .cpu_dai_name = "msm-dai-q6.32773",
1155 .platform_name = "msm-pcm-routing",
1156 .codec_name = "msm-stub-codec.1",
1157 .codec_dai_name = "msm-stub-rx",
1158 .no_pcm = 1,
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301159 .be_id = MSM_BACKEND_DAI_VOICE_PLAYBACK_TX,
1160 .be_hw_params_fixup = msm8930_be_hw_params_fixup,
1161 },
1162 /* Incall Record Uplink BACK END DAI Link */
1163 {
1164 .name = LPASS_BE_INCALL_RECORD_TX,
1165 .stream_name = "Voice Uplink Capture",
1166 .cpu_dai_name = "msm-dai-q6.32772",
1167 .platform_name = "msm-pcm-routing",
1168 .codec_name = "msm-stub-codec.1",
1169 .codec_dai_name = "msm-stub-tx",
1170 .no_pcm = 1,
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301171 .be_id = MSM_BACKEND_DAI_INCALL_RECORD_TX,
1172 .be_hw_params_fixup = msm8930_be_hw_params_fixup,
1173 },
1174 /* Incall Record Downlink BACK END DAI Link */
1175 {
1176 .name = LPASS_BE_INCALL_RECORD_RX,
1177 .stream_name = "Voice Downlink Capture",
1178 .cpu_dai_name = "msm-dai-q6.32771",
1179 .platform_name = "msm-pcm-routing",
1180 .codec_name = "msm-stub-codec.1",
1181 .codec_dai_name = "msm-stub-tx",
1182 .no_pcm = 1,
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301183 .be_id = MSM_BACKEND_DAI_INCALL_RECORD_RX,
1184 .be_hw_params_fixup = msm8930_be_hw_params_fixup,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001185 .ignore_pmdown_time = 1, /* this dainlink has playback support */
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301186 },
1187};
1188
1189struct snd_soc_card snd_soc_card_msm8930 = {
1190 .name = "msm8930-sitar-snd-card",
1191 .dai_link = msm8930_dai,
1192 .num_links = ARRAY_SIZE(msm8930_dai),
Steve Mucklef132c6c2012-06-06 18:30:57 -07001193 .controls = sitar_msm8930_controls,
1194 .num_controls = ARRAY_SIZE(sitar_msm8930_controls),
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301195};
1196
1197static struct platform_device *msm8930_snd_device;
1198
1199static int msm8930_configure_headset_mic_gpios(void)
1200{
1201 int ret;
1202 ret = gpio_request(80, "US_EURO_SWITCH");
1203 if (ret) {
1204 pr_err("%s: Failed to request gpio 80\n", __func__);
1205 return ret;
1206 }
1207 ret = gpio_direction_output(80, 0);
1208 if (ret) {
1209 pr_err("%s: Unable to set direction\n", __func__);
1210 gpio_free(80);
1211 }
1212 msm8930_headset_gpios_configured = 0;
1213 return 0;
1214}
1215static void msm8930_free_headset_mic_gpios(void)
1216{
1217 if (msm8930_headset_gpios_configured)
1218 gpio_free(80);
1219}
1220
1221static int __init msm8930_audio_init(void)
1222{
1223 int ret;
1224
Stepan Moskovchenko0df9bb22012-07-06 18:19:15 -07001225 if (!cpu_is_msm8930() && !cpu_is_msm8930aa() && !cpu_is_msm8627()) {
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301226 pr_err("%s: Not the right machine type\n", __func__);
1227 return -ENODEV ;
1228 }
Bhalchandra Gajare466aafe2012-05-02 17:55:26 -07001229 mbhc_cfg.calibration = def_sitar_mbhc_cal();
1230 if (!mbhc_cfg.calibration) {
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -08001231 pr_err("Calibration data allocation failed\n");
1232 return -ENOMEM;
1233 }
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301234
1235 msm8930_snd_device = platform_device_alloc("soc-audio", 0);
1236 if (!msm8930_snd_device) {
1237 pr_err("Platform device allocation failed\n");
Bhalchandra Gajare466aafe2012-05-02 17:55:26 -07001238 kfree(mbhc_cfg.calibration);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301239 return -ENOMEM;
1240 }
1241
1242 platform_set_drvdata(msm8930_snd_device, &snd_soc_card_msm8930);
1243 ret = platform_device_add(msm8930_snd_device);
1244 if (ret) {
1245 platform_device_put(msm8930_snd_device);
Bhalchandra Gajare466aafe2012-05-02 17:55:26 -07001246 kfree(mbhc_cfg.calibration);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301247 return ret;
1248 }
1249
1250 if (msm8930_configure_headset_mic_gpios()) {
1251 pr_err("%s Fail to configure headset mic gpios\n", __func__);
1252 msm8930_headset_gpios_configured = 0;
1253 } else
1254 msm8930_headset_gpios_configured = 1;
1255
1256 return ret;
1257
1258}
1259module_init(msm8930_audio_init);
1260
1261static void __exit msm8930_audio_exit(void)
1262{
Stepan Moskovchenko0df9bb22012-07-06 18:19:15 -07001263 if (!cpu_is_msm8930() && !cpu_is_msm8930aa() && !cpu_is_msm8627()) {
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301264 pr_err("%s: Not the right machine type\n", __func__);
1265 return ;
1266 }
1267 msm8930_free_headset_mic_gpios();
1268 platform_device_unregister(msm8930_snd_device);
Bhalchandra Gajare466aafe2012-05-02 17:55:26 -07001269 kfree(mbhc_cfg.calibration);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301270}
1271module_exit(msm8930_audio_exit);
1272
1273MODULE_DESCRIPTION("ALSA SoC MSM8930");
1274MODULE_LICENSE("GPL v2");