blob: 063fe6bdf0a16717430a912c950719ed8f743342 [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
Bhalchandra Gajare97676792012-05-22 17:41:45 -070042#define DEFAULT_PMIC_SPK_GAIN 0x0D
Asish Bhattacharyab86c3472012-02-15 08:31:52 +053043#define SITAR_EXT_CLK_RATE 12288000
44
Bhalchandra Gajare7708ee32012-05-24 17:37:37 -070045#define SITAR_MBHC_DEF_BUTTONS 8
Asish Bhattacharyab86c3472012-02-15 08:31:52 +053046#define SITAR_MBHC_DEF_RLOADS 5
47
Bhalchandra Gajare2e0893e2012-05-24 00:39:47 -070048#define GPIO_AUX_PCM_DOUT 63
49#define GPIO_AUX_PCM_DIN 64
50#define GPIO_AUX_PCM_SYNC 65
51#define GPIO_AUX_PCM_CLK 66
52
Asish Bhattacharyab86c3472012-02-15 08:31:52 +053053static int msm8930_spk_control;
54static int msm8930_slim_0_rx_ch = 1;
55static int msm8930_slim_0_tx_ch = 1;
Bhalchandra Gajare97676792012-05-22 17:41:45 -070056static int msm8930_pmic_spk_gain = DEFAULT_PMIC_SPK_GAIN;
Asish Bhattacharyab86c3472012-02-15 08:31:52 +053057
Asish Bhattacharyac71827a2012-03-05 10:11:45 -080058static int msm8930_ext_spk_pamp;
Asish Bhattacharyab86c3472012-02-15 08:31:52 +053059static int msm8930_btsco_rate = BTSCO_RATE_8KHZ;
60static int msm8930_btsco_ch = 1;
61
62static struct clk *codec_clk;
63static int clk_users;
64
65static int msm8930_headset_gpios_configured;
66
67static struct snd_soc_jack hs_jack;
68static struct snd_soc_jack button_jack;
Bhalchandra Gajare466aafe2012-05-02 17:55:26 -070069
70static int msm8930_enable_codec_ext_clk(
71 struct snd_soc_codec *codec, int enable,
72 bool dapm);
73
74static struct sitar_mbhc_config mbhc_cfg = {
75 .headset_jack = &hs_jack,
76 .button_jack = &button_jack,
77 .read_fw_bin = false,
78 .calibration = NULL,
79 .micbias = SITAR_MICBIAS2,
80 .mclk_cb_fn = msm8930_enable_codec_ext_clk,
81 .mclk_rate = SITAR_EXT_CLK_RATE,
82 .gpio = 0,
83 .gpio_irq = 0,
84 .gpio_level_insert = 1,
85};
86
Asish Bhattacharyab86c3472012-02-15 08:31:52 +053087
88static void msm8930_ext_control(struct snd_soc_codec *codec)
89{
90 struct snd_soc_dapm_context *dapm = &codec->dapm;
91
92 pr_debug("%s: msm8930_spk_control = %d", __func__, msm8930_spk_control);
93 if (msm8930_spk_control == MSM8930_SPK_ON) {
94 snd_soc_dapm_enable_pin(dapm, "Ext Spk Left Pos");
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -080095 snd_soc_dapm_enable_pin(dapm, "Ext Spk left Neg");
Asish Bhattacharyab86c3472012-02-15 08:31:52 +053096 } else {
97 snd_soc_dapm_disable_pin(dapm, "Ext Spk Left Pos");
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -080098 snd_soc_dapm_disable_pin(dapm, "Ext Spk Left Neg");
Asish Bhattacharyab86c3472012-02-15 08:31:52 +053099 }
100
101 snd_soc_dapm_sync(dapm);
102}
103
104static int msm8930_get_spk(struct snd_kcontrol *kcontrol,
105 struct snd_ctl_elem_value *ucontrol)
106{
107 pr_debug("%s: msm8930_spk_control = %d", __func__, msm8930_spk_control);
108 ucontrol->value.integer.value[0] = msm8930_spk_control;
109 return 0;
110}
111static int msm8930_set_spk(struct snd_kcontrol *kcontrol,
112 struct snd_ctl_elem_value *ucontrol)
113{
114 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
115
116 pr_debug("%s()\n", __func__);
117 if (msm8930_spk_control == ucontrol->value.integer.value[0])
118 return 0;
119
120 msm8930_spk_control = ucontrol->value.integer.value[0];
121 msm8930_ext_control(codec);
122 return 1;
123}
124
Asish Bhattacharyac71827a2012-03-05 10:11:45 -0800125static void msm8960_ext_spk_power_amp_on(u32 spk)
126{
Bhalchandra Gajare98a28cd2012-05-16 12:00:20 -0700127 int ret = 0;
128
Asish Bhattacharyac71827a2012-03-05 10:11:45 -0800129 if (spk & (SPK_AMP_POS | SPK_AMP_NEG)) {
130 if ((msm8930_ext_spk_pamp & SPK_AMP_POS) &&
131 (msm8930_ext_spk_pamp & SPK_AMP_NEG)) {
132
133 pr_debug("%s() External Bottom Speaker Ampl already "
134 "turned on. spk = 0x%08x\n", __func__, spk);
135 return;
136 }
137
138 msm8930_ext_spk_pamp |= spk;
139
140 if ((msm8930_ext_spk_pamp & SPK_AMP_POS) &&
141 (msm8930_ext_spk_pamp & SPK_AMP_NEG)) {
142
Bhalchandra Gajare98a28cd2012-05-16 12:00:20 -0700143 if (machine_is_msm8930_mtp()
144 || machine_is_msm8930_fluid()) {
145 pr_debug("%s: Configure Speaker Boost GPIO %u",
146 __func__, SPKR_BOOST_GPIO);
147 ret = gpio_request(SPKR_BOOST_GPIO,
148 "SPKR_BOOST_EN");
149 if (ret) {
150 pr_err("%s: Failed to configure speaker boost "
151 "gpio %u\n", __func__, SPKR_BOOST_GPIO);
152 return;
153 }
154
155 pr_debug("%s: Enable Speaker boost gpio %u\n",
156 __func__, SPKR_BOOST_GPIO);
157 gpio_direction_output(SPKR_BOOST_GPIO, 1);
158 }
159
Asish Bhattacharyac71827a2012-03-05 10:11:45 -0800160 pm8xxx_spk_enable(MSM8930_SPK_ON);
161 pr_debug("%s: slepping 4 ms after turning on external "
162 " Left Speaker Ampl\n", __func__);
163 usleep_range(4000, 4000);
164 }
165
166 } else {
167
168 pr_err("%s: ERROR : Invalid External Speaker Ampl. spk = 0x%08x\n",
169 __func__, spk);
170 return;
171 }
172}
173
174static void msm8960_ext_spk_power_amp_off(u32 spk)
175{
176 if (spk & (SPK_AMP_POS | SPK_AMP_NEG)) {
177 if (!msm8930_ext_spk_pamp)
178 return;
Bhalchandra Gajare98a28cd2012-05-16 12:00:20 -0700179 if (machine_is_msm8930_mtp()
180 || machine_is_msm8930_fluid()) {
181 pr_debug("%s: Free speaker boost gpio %u\n",
182 __func__, SPKR_BOOST_GPIO);
183 gpio_direction_output(SPKR_BOOST_GPIO, 0);
184 gpio_free(SPKR_BOOST_GPIO);
185 }
Asish Bhattacharyac71827a2012-03-05 10:11:45 -0800186
187 pm8xxx_spk_enable(MSM8930_SPK_OFF);
188 msm8930_ext_spk_pamp = 0;
189 pr_debug("%s: slepping 4 ms after turning on external "
190 " Left Speaker Ampl\n", __func__);
191 usleep_range(4000, 4000);
192
193 } else {
194
195 pr_err("%s: ERROR : Invalid External Speaker Ampl. spk = 0x%08x\n",
196 __func__, spk);
197 return;
198 }
199}
200
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530201static int msm8930_spkramp_event(struct snd_soc_dapm_widget *w,
202 struct snd_kcontrol *k, int event)
203{
204 pr_debug("%s() %x\n", __func__, SND_SOC_DAPM_EVENT_ON(event));
Asish Bhattacharyac71827a2012-03-05 10:11:45 -0800205 if (SND_SOC_DAPM_EVENT_ON(event)) {
206 if (!strncmp(w->name, "Ext Spk Left Pos", 17))
207 msm8960_ext_spk_power_amp_on(SPK_AMP_POS);
208 else if (!strncmp(w->name, "Ext Spk Left Neg", 17))
209 msm8960_ext_spk_power_amp_on(SPK_AMP_NEG);
210 else {
211 pr_err("%s() Invalid Speaker Widget = %s\n",
212 __func__, w->name);
213 return -EINVAL;
214 }
215 } else {
216 if (!strncmp(w->name, "Ext Spk Left Pos", 17))
217 msm8960_ext_spk_power_amp_off(SPK_AMP_POS);
218 else if (!strncmp(w->name, "Ext Spk Left Neg", 17))
219 msm8960_ext_spk_power_amp_off(SPK_AMP_NEG);
220 else {
221 pr_err("%s() Invalid Speaker Widget = %s\n",
222 __func__, w->name);
223 return -EINVAL;
224 }
225 }
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530226 return 0;
227}
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800228
Bhalchandra Gajare466aafe2012-05-02 17:55:26 -0700229static int msm8930_enable_codec_ext_clk(
230 struct snd_soc_codec *codec, int enable,
231 bool dapm)
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530232{
233 pr_debug("%s: enable = %d\n", __func__, enable);
234 if (enable) {
235 clk_users++;
236 pr_debug("%s: clk_users = %d\n", __func__, clk_users);
237 if (clk_users != 1)
238 return 0;
239
240 if (codec_clk) {
241 clk_set_rate(codec_clk, SITAR_EXT_CLK_RATE);
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800242 clk_prepare_enable(codec_clk);
Bhalchandra Gajare466aafe2012-05-02 17:55:26 -0700243 sitar_mclk_enable(codec, 1, dapm);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530244 } else {
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800245 pr_err("%s: Error setting Sitar MCLK\n", __func__);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530246 clk_users--;
247 return -EINVAL;
248 }
249 } else {
250 pr_debug("%s: clk_users = %d\n", __func__, clk_users);
251 if (clk_users == 0)
252 return 0;
253 clk_users--;
254 if (!clk_users) {
255 pr_debug("%s: disabling MCLK. clk_users = %d\n",
256 __func__, clk_users);
Bhalchandra Gajare466aafe2012-05-02 17:55:26 -0700257 sitar_mclk_enable(codec, 0, dapm);
Bhalchandra Gajare2776af12012-04-27 16:59:39 -0700258 clk_disable_unprepare(codec_clk);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530259 }
260 }
261 return 0;
262}
263
264static int msm8930_mclk_event(struct snd_soc_dapm_widget *w,
265 struct snd_kcontrol *kcontrol, int event)
266{
267 pr_debug("%s: event = %d\n", __func__, event);
268
269 switch (event) {
270 case SND_SOC_DAPM_PRE_PMU:
Bhalchandra Gajare466aafe2012-05-02 17:55:26 -0700271 return msm8930_enable_codec_ext_clk(w->codec, 1, true);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530272 case SND_SOC_DAPM_POST_PMD:
Bhalchandra Gajare466aafe2012-05-02 17:55:26 -0700273 return msm8930_enable_codec_ext_clk(w->codec, 0, true);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530274 }
275 return 0;
276}
277
278static const struct snd_soc_dapm_widget msm8930_dapm_widgets[] = {
279
280 SND_SOC_DAPM_SUPPLY("MCLK", SND_SOC_NOPM, 0, 0,
281 msm8930_mclk_event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
282
283 SND_SOC_DAPM_SPK("Ext Spk Left Pos", msm8930_spkramp_event),
Asish Bhattacharyac71827a2012-03-05 10:11:45 -0800284 SND_SOC_DAPM_SPK("Ext Spk Left Neg", msm8930_spkramp_event),
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530285
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530286 SND_SOC_DAPM_MIC("Headset Mic", NULL),
287 SND_SOC_DAPM_MIC("Digital Mic1", NULL),
288 SND_SOC_DAPM_MIC("ANCRight Headset Mic", NULL),
289 SND_SOC_DAPM_MIC("ANCLeft Headset Mic", NULL),
290
291 SND_SOC_DAPM_MIC("Digital Mic1", NULL),
292 SND_SOC_DAPM_MIC("Digital Mic2", NULL),
293 SND_SOC_DAPM_MIC("Digital Mic3", NULL),
294 SND_SOC_DAPM_MIC("Digital Mic4", NULL),
295
296};
297
298static const struct snd_soc_dapm_route common_audio_map[] = {
299
300 {"RX_BIAS", NULL, "MCLK"},
301 {"LDO_H", NULL, "MCLK"},
302
303 {"MIC BIAS1 Internal1", NULL, "MCLK"},
304 {"MIC BIAS2 Internal1", NULL, "MCLK"},
305
306 /* Speaker path */
307 {"Ext Spk Left Pos", NULL, "LINEOUT1"},
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800308 {"Ext Spk Left Neg", NULL, "LINEOUT2"},
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530309
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800310 /* Headset Mic */
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530311 {"AMIC2", NULL, "MIC BIAS2 Internal1"},
312 {"MIC BIAS2 Internal1", NULL, "Headset Mic"},
313
314 /* Microphone path */
Bhalchandra Gajare18314d52012-06-06 19:03:01 -0700315 {"AMIC1", NULL, "MIC BIAS2 External"},
316 {"MIC BIAS2 External", NULL, "ANCLeft Headset Mic"},
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800317
Bhalchandra Gajare18314d52012-06-06 19:03:01 -0700318 {"AMIC3", NULL, "MIC BIAS2 External"},
319 {"MIC BIAS2 External", NULL, "ANCRight Headset Mic"},
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530320
321 {"HEADPHONE", NULL, "LDO_H"},
322
323 /**
324 * The digital Mic routes are setup considering
325 * fluid as default device.
326 */
327
328 /**
Bhalchandra Gajaree6a30f72012-05-23 19:46:21 -0700329 * Digital Mic1. Front Bottom left Mic on Fluid and MTP.
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530330 * Digital Mic GM5 on CDP mainboard.
Bhalchandra Gajaree6a30f72012-05-23 19:46:21 -0700331 * Conncted to DMIC1 Input on Sitar codec.
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530332 */
333 {"DMIC1", NULL, "MIC BIAS1 External"},
334 {"MIC BIAS1 External", NULL, "Digital Mic1"},
335
336 /**
Bhalchandra Gajaree6a30f72012-05-23 19:46:21 -0700337 * Digital Mic2. Back top MIC on Fluid.
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530338 * Digital Mic GM6 on CDP mainboard.
Bhalchandra Gajaree6a30f72012-05-23 19:46:21 -0700339 * Conncted to DMIC2 Input on Sitar codec.
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530340 */
341 {"DMIC2", NULL, "MIC BIAS1 External"},
342 {"MIC BIAS1 External", NULL, "Digital Mic2"},
343 /**
344 * Digital Mic3. Back Bottom Digital Mic on Fluid.
345 * Digital Mic GM1 on CDP mainboard.
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800346 * Conncted to DMIC4 Input on Sitar codec.
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530347 */
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800348 {"DMIC3", NULL, "MIC BIAS1 External"},
349 {"MIC BIAS1 External", NULL, "Digital Mic3"},
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530350
351 /**
352 * Digital Mic4. Back top Digital Mic on Fluid.
353 * Digital Mic GM2 on CDP mainboard.
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800354 * Conncted to DMIC3 Input on Sitar codec.
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530355 */
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800356 {"DMIC4", NULL, "MIC BIAS1 External"},
357 {"MIC BIAS1 External", NULL, "Digital Mic4"},
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530358
359
360};
361
362static const char *spk_function[] = {"Off", "On"};
363static const char *slim0_rx_ch_text[] = {"One", "Two"};
364static const char *slim0_tx_ch_text[] = {"One", "Two", "Three", "Four"};
365
366static const struct soc_enum msm8930_enum[] = {
367 SOC_ENUM_SINGLE_EXT(2, spk_function),
368 SOC_ENUM_SINGLE_EXT(2, slim0_rx_ch_text),
369 SOC_ENUM_SINGLE_EXT(4, slim0_tx_ch_text),
370};
371
372static const char *btsco_rate_text[] = {"8000", "16000"};
373static const struct soc_enum msm8930_btsco_enum[] = {
374 SOC_ENUM_SINGLE_EXT(2, btsco_rate_text),
375};
376
377static int msm8930_slim_0_rx_ch_get(struct snd_kcontrol *kcontrol,
378 struct snd_ctl_elem_value *ucontrol)
379{
380 pr_debug("%s: msm8930_slim_0_rx_ch = %d\n", __func__,
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800381 msm8930_slim_0_rx_ch);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530382 ucontrol->value.integer.value[0] = msm8930_slim_0_rx_ch - 1;
383 return 0;
384}
385
386static int msm8930_slim_0_rx_ch_put(struct snd_kcontrol *kcontrol,
387 struct snd_ctl_elem_value *ucontrol)
388{
389 msm8930_slim_0_rx_ch = ucontrol->value.integer.value[0] + 1;
390
391 pr_debug("%s: msm8930_slim_0_rx_ch = %d\n", __func__,
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800392 msm8930_slim_0_rx_ch);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530393 return 1;
394}
395
396static int msm8930_slim_0_tx_ch_get(struct snd_kcontrol *kcontrol,
397 struct snd_ctl_elem_value *ucontrol)
398{
399 pr_debug("%s: msm8930_slim_0_tx_ch = %d\n", __func__,
400 msm8930_slim_0_tx_ch);
401 ucontrol->value.integer.value[0] = msm8930_slim_0_tx_ch - 1;
402 return 0;
403}
404
405static int msm8930_slim_0_tx_ch_put(struct snd_kcontrol *kcontrol,
406 struct snd_ctl_elem_value *ucontrol)
407{
408 msm8930_slim_0_tx_ch = ucontrol->value.integer.value[0] + 1;
409
410 pr_debug("%s: msm8930_slim_0_tx_ch = %d\n", __func__,
411 msm8930_slim_0_tx_ch);
412 return 1;
413}
414
415static int msm8930_btsco_rate_get(struct snd_kcontrol *kcontrol,
416 struct snd_ctl_elem_value *ucontrol)
417{
418 pr_debug("%s: msm8930_btsco_rate = %d", __func__, msm8930_btsco_rate);
419 ucontrol->value.integer.value[0] = msm8930_btsco_rate;
420 return 0;
421}
422
423static int msm8930_btsco_rate_put(struct snd_kcontrol *kcontrol,
424 struct snd_ctl_elem_value *ucontrol)
425{
426 switch (ucontrol->value.integer.value[0]) {
427 case 0:
428 msm8930_btsco_rate = BTSCO_RATE_8KHZ;
429 break;
430 case 1:
431 msm8930_btsco_rate = BTSCO_RATE_16KHZ;
432 break;
433 default:
434 msm8930_btsco_rate = BTSCO_RATE_8KHZ;
435 break;
436 }
437 pr_debug("%s: msm8930_btsco_rate = %d\n", __func__, msm8930_btsco_rate);
438 return 0;
439}
440
Bhalchandra Gajare97676792012-05-22 17:41:45 -0700441static const char *pmic_spk_gain_text[] = {
442 "NEG_6_DB", "NEG_4_DB", "NEG_2_DB", "ZERO_DB", "POS_2_DB", "POS_4_DB",
443 "POS_6_DB", "POS_8_DB", "POS_10_DB", "POS_12_DB", "POS_14_DB",
444 "POS_16_DB", "POS_18_DB", "POS_20_DB", "POS_22_DB", "POS_24_DB"
445};
446
447static const struct soc_enum msm8960_pmic_spk_gain_enum[] = {
448 SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(pmic_spk_gain_text),
449 pmic_spk_gain_text),
450};
451
452static int msm8930_pmic_gain_get(struct snd_kcontrol *kcontrol,
453 struct snd_ctl_elem_value *ucontrol)
454{
455 pr_debug("%s: msm8930_pmic_spk_gain = %d\n", __func__,
456 msm8930_pmic_spk_gain);
457 ucontrol->value.integer.value[0] = msm8930_pmic_spk_gain;
458 return 0;
459}
460
461static int msm8930_pmic_gain_put(struct snd_kcontrol *kcontrol,
462 struct snd_ctl_elem_value *ucontrol)
463{
464 int ret = 0;
465 msm8930_pmic_spk_gain = ucontrol->value.integer.value[0];
466 ret = pm8xxx_spk_gain(msm8930_pmic_spk_gain);
467 pr_debug("%s: msm8930_pmic_spk_gain = %d"
468 " ucontrol->value.integer.value[0] = %d\n", __func__,
469 msm8930_pmic_spk_gain,
470 (int) ucontrol->value.integer.value[0]);
471 return ret;
472}
473
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530474static const struct snd_kcontrol_new sitar_msm8930_controls[] = {
475 SOC_ENUM_EXT("Speaker Function", msm8930_enum[0], msm8930_get_spk,
476 msm8930_set_spk),
477 SOC_ENUM_EXT("SLIM_0_RX Channels", msm8930_enum[1],
478 msm8930_slim_0_rx_ch_get, msm8930_slim_0_rx_ch_put),
479 SOC_ENUM_EXT("SLIM_0_TX Channels", msm8930_enum[2],
480 msm8930_slim_0_tx_ch_get, msm8930_slim_0_tx_ch_put),
Bhalchandra Gajare97676792012-05-22 17:41:45 -0700481 SOC_ENUM_EXT("PMIC SPK Gain", msm8960_pmic_spk_gain_enum[0],
482 msm8930_pmic_gain_get, msm8930_pmic_gain_put),
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530483};
484
485static const struct snd_kcontrol_new int_btsco_rate_mixer_controls[] = {
486 SOC_ENUM_EXT("Internal BTSCO SampleRate", msm8930_btsco_enum[0],
487 msm8930_btsco_rate_get, msm8930_btsco_rate_put),
488};
489
490static int msm8930_btsco_init(struct snd_soc_pcm_runtime *rtd)
491{
492 int err = 0;
493 struct snd_soc_platform *platform = rtd->platform;
494
495 err = snd_soc_add_platform_controls(platform,
496 int_btsco_rate_mixer_controls,
497 ARRAY_SIZE(int_btsco_rate_mixer_controls));
498 if (err < 0)
499 return err;
500 return 0;
501}
502
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800503static void *def_sitar_mbhc_cal(void)
504{
505 void *sitar_cal;
506 struct sitar_mbhc_btn_detect_cfg *btn_cfg;
507 u16 *btn_low, *btn_high;
508 u8 *n_ready, *n_cic, *gain;
509
510 sitar_cal = kzalloc(SITAR_MBHC_CAL_SIZE(SITAR_MBHC_DEF_BUTTONS,
511 SITAR_MBHC_DEF_RLOADS),
512 GFP_KERNEL);
513 if (!sitar_cal) {
514 pr_err("%s: out of memory\n", __func__);
515 return NULL;
516 }
517
518#define S(X, Y) ((SITAR_MBHC_CAL_GENERAL_PTR(sitar_cal)->X) = (Y))
519 S(t_ldoh, 100);
520 S(t_bg_fast_settle, 100);
521 S(t_shutdown_plug_rem, 255);
522 S(mbhc_nsa, 4);
523 S(mbhc_navg, 4);
524#undef S
525#define S(X, Y) ((SITAR_MBHC_CAL_PLUG_DET_PTR(sitar_cal)->X) = (Y))
526 S(mic_current, SITAR_PID_MIC_5_UA);
527 S(hph_current, SITAR_PID_MIC_5_UA);
528 S(t_mic_pid, 100);
529 S(t_ins_complete, 250);
530 S(t_ins_retry, 200);
531#undef S
532#define S(X, Y) ((SITAR_MBHC_CAL_PLUG_TYPE_PTR(sitar_cal)->X) = (Y))
533 S(v_no_mic, 30);
Bhalchandra Gajare18314d52012-06-06 19:03:01 -0700534 S(v_hs_max, 1650);
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800535#undef S
536#define S(X, Y) ((SITAR_MBHC_CAL_BTN_DET_PTR(sitar_cal)->X) = (Y))
537 S(c[0], 62);
538 S(c[1], 124);
539 S(nc, 1);
540 S(n_meas, 3);
541 S(mbhc_nsc, 11);
542 S(n_btn_meas, 1);
543 S(n_btn_con, 2);
544 S(num_btn, SITAR_MBHC_DEF_BUTTONS);
545 S(v_btn_press_delta_sta, 100);
546 S(v_btn_press_delta_cic, 50);
547#undef S
548 btn_cfg = SITAR_MBHC_CAL_BTN_DET_PTR(sitar_cal);
549 btn_low = sitar_mbhc_cal_btn_det_mp(btn_cfg, SITAR_BTN_DET_V_BTN_LOW);
550 btn_high = sitar_mbhc_cal_btn_det_mp(btn_cfg, SITAR_BTN_DET_V_BTN_HIGH);
551 btn_low[0] = -50;
552 btn_high[0] = 10;
553 btn_low[1] = 11;
554 btn_high[1] = 38;
555 btn_low[2] = 39;
556 btn_high[2] = 64;
557 btn_low[3] = 65;
558 btn_high[3] = 91;
559 btn_low[4] = 92;
560 btn_high[4] = 115;
561 btn_low[5] = 116;
562 btn_high[5] = 141;
563 btn_low[6] = 142;
564 btn_high[6] = 163;
565 btn_low[7] = 164;
566 btn_high[7] = 250;
567 n_ready = sitar_mbhc_cal_btn_det_mp(btn_cfg, SITAR_BTN_DET_N_READY);
568 n_ready[0] = 48;
569 n_ready[1] = 38;
570 n_cic = sitar_mbhc_cal_btn_det_mp(btn_cfg, SITAR_BTN_DET_N_CIC);
571 n_cic[0] = 60;
572 n_cic[1] = 47;
573 gain = sitar_mbhc_cal_btn_det_mp(btn_cfg, SITAR_BTN_DET_GAIN);
574 gain[0] = 11;
575 gain[1] = 9;
576
577 return sitar_cal;
578}
579
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530580static int msm8930_hw_params(struct snd_pcm_substream *substream,
581 struct snd_pcm_hw_params *params)
582{
583 struct snd_soc_pcm_runtime *rtd = substream->private_data;
584 struct snd_soc_dai *codec_dai = rtd->codec_dai;
585 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
586 int ret = 0;
587 unsigned int rx_ch[SLIM_MAX_RX_PORTS], tx_ch[SLIM_MAX_TX_PORTS];
588 unsigned int rx_ch_cnt = 0, tx_ch_cnt = 0;
589
590 pr_debug("%s: ch=%d\n", __func__,
591 msm8930_slim_0_rx_ch);
592 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
593 ret = snd_soc_dai_get_channel_map(codec_dai,
594 &tx_ch_cnt, tx_ch, &rx_ch_cnt , rx_ch);
595 if (ret < 0) {
596 pr_err("%s: failed to get codec chan map\n", __func__);
597 goto end;
598 }
599
600 ret = snd_soc_dai_set_channel_map(cpu_dai, 0, 0,
601 msm8930_slim_0_rx_ch, rx_ch);
602 if (ret < 0) {
603 pr_err("%s: failed to set cpu chan map\n", __func__);
604 goto end;
605 }
606 ret = snd_soc_dai_set_channel_map(codec_dai, 0, 0,
607 msm8930_slim_0_rx_ch, rx_ch);
608 if (ret < 0) {
609 pr_err("%s: failed to set codec channel map\n",
610 __func__);
611 goto end;
612 }
613 } else {
614 ret = snd_soc_dai_get_channel_map(codec_dai,
615 &tx_ch_cnt, tx_ch, &rx_ch_cnt , rx_ch);
616 if (ret < 0) {
617 pr_err("%s: failed to get codec chan map\n", __func__);
618 goto end;
619 }
620 ret = snd_soc_dai_set_channel_map(cpu_dai,
621 msm8930_slim_0_tx_ch, tx_ch, 0 , 0);
622 if (ret < 0) {
623 pr_err("%s: failed to set cpu chan map\n", __func__);
624 goto end;
625 }
626 ret = snd_soc_dai_set_channel_map(codec_dai,
627 msm8930_slim_0_tx_ch, tx_ch, 0, 0);
628 if (ret < 0) {
629 pr_err("%s: failed to set codec channel map\n",
630 __func__);
631 goto end;
632 }
633
634 }
635end:
636 return ret;
637}
638
639static int msm8930_audrx_init(struct snd_soc_pcm_runtime *rtd)
640{
641 int err;
642 struct snd_soc_codec *codec = rtd->codec;
643 struct snd_soc_dapm_context *dapm = &codec->dapm;
644 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
645
646 pr_debug("%s()\n", __func__);
647
648
649 rtd->pmdown_time = 0;
650
651 err = snd_soc_add_controls(codec, sitar_msm8930_controls,
652 ARRAY_SIZE(sitar_msm8930_controls));
653 if (err < 0)
654 return err;
655
656 snd_soc_dapm_new_controls(dapm, msm8930_dapm_widgets,
657 ARRAY_SIZE(msm8930_dapm_widgets));
658
659 snd_soc_dapm_add_routes(dapm, common_audio_map,
660 ARRAY_SIZE(common_audio_map));
661
662 snd_soc_dapm_enable_pin(dapm, "Ext Spk Left Pos");
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800663 snd_soc_dapm_enable_pin(dapm, "Ext Spk Left Neg");
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530664
665 snd_soc_dapm_sync(dapm);
666
667 err = snd_soc_jack_new(codec, "Headset Jack",
668 (SND_JACK_HEADSET | SND_JACK_OC_HPHL | SND_JACK_OC_HPHR),
669 &hs_jack);
670 if (err) {
671 pr_err("failed to create new jack\n");
672 return err;
673 }
674
675 err = snd_soc_jack_new(codec, "Button Jack",
Bhalchandra Gajare7708ee32012-05-24 17:37:37 -0700676 SITAR_JACK_BUTTON_MASK, &button_jack);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530677 if (err) {
678 pr_err("failed to create new jack\n");
679 return err;
680 }
681 codec_clk = clk_get(cpu_dai->dev, "osr_clk");
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800682
Bhalchandra Gajare466aafe2012-05-02 17:55:26 -0700683 mbhc_cfg.gpio = 37;
684 mbhc_cfg.gpio_irq = gpio_to_irq(mbhc_cfg.gpio);
685 sitar_hs_detect(codec, &mbhc_cfg);
686
Bhalchandra Gajare97676792012-05-22 17:41:45 -0700687 /* Initialize default PMIC speaker gain */
688 pm8xxx_spk_gain(DEFAULT_PMIC_SPK_GAIN);
689
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530690 return 0;
691}
692
693static struct snd_soc_dsp_link lpa_fe_media = {
694 .playback = true,
695 .trigger = {
696 SND_SOC_DSP_TRIGGER_POST,
697 SND_SOC_DSP_TRIGGER_POST
698 },
699};
700
701static struct snd_soc_dsp_link fe_media = {
702 .playback = true,
703 .capture = true,
704 .trigger = {
705 SND_SOC_DSP_TRIGGER_POST,
706 SND_SOC_DSP_TRIGGER_POST
707 },
708};
709
710static struct snd_soc_dsp_link slimbus0_hl_media = {
711 .playback = true,
712 .capture = true,
713 .trigger = {
714 SND_SOC_DSP_TRIGGER_POST,
715 SND_SOC_DSP_TRIGGER_POST
716 },
717};
718
719static struct snd_soc_dsp_link int_fm_hl_media = {
720 .playback = true,
721 .capture = true,
722 .trigger = {
723 SND_SOC_DSP_TRIGGER_POST,
724 SND_SOC_DSP_TRIGGER_POST
725 },
726};
727
728/* bi-directional media definition for hostless PCM device */
729static struct snd_soc_dsp_link bidir_hl_media = {
730 .playback = true,
731 .capture = true,
732 .trigger = {
733 SND_SOC_DSP_TRIGGER_POST,
734 SND_SOC_DSP_TRIGGER_POST
735 },
736};
737
738static struct snd_soc_dsp_link hdmi_rx_hl = {
739 .playback = true,
740 .trigger = {
741 SND_SOC_DSP_TRIGGER_POST,
742 SND_SOC_DSP_TRIGGER_POST
743 },
744};
745
746static int msm8930_slim_0_rx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
747 struct snd_pcm_hw_params *params)
748{
749 struct snd_interval *rate = hw_param_interval(params,
750 SNDRV_PCM_HW_PARAM_RATE);
751
752 struct snd_interval *channels = hw_param_interval(params,
753 SNDRV_PCM_HW_PARAM_CHANNELS);
754
755 pr_debug("%s()\n", __func__);
756 rate->min = rate->max = 48000;
757 channels->min = channels->max = msm8930_slim_0_rx_ch;
758
759 return 0;
760}
761
762static int msm8930_slim_0_tx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
763 struct snd_pcm_hw_params *params)
764{
765 struct snd_interval *rate = hw_param_interval(params,
766 SNDRV_PCM_HW_PARAM_RATE);
767
768 struct snd_interval *channels = hw_param_interval(params,
769 SNDRV_PCM_HW_PARAM_CHANNELS);
770
771 pr_debug("%s()\n", __func__);
772 rate->min = rate->max = 48000;
773 channels->min = channels->max = msm8930_slim_0_tx_ch;
774
775 return 0;
776}
777
778static int msm8930_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
779 struct snd_pcm_hw_params *params)
780{
781 struct snd_interval *rate = hw_param_interval(params,
782 SNDRV_PCM_HW_PARAM_RATE);
783
784 pr_debug("%s()\n", __func__);
785 rate->min = rate->max = 48000;
786
787 return 0;
788}
789
790static int msm8930_hdmi_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
791 struct snd_pcm_hw_params *params)
792{
793 struct snd_interval *rate = hw_param_interval(params,
794 SNDRV_PCM_HW_PARAM_RATE);
795
796 struct snd_interval *channels = hw_param_interval(params,
797 SNDRV_PCM_HW_PARAM_CHANNELS);
798
799 rate->min = rate->max = 48000;
800 channels->min = channels->max = 2;
801
802 return 0;
803}
804
805static int msm8930_btsco_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
806 struct snd_pcm_hw_params *params)
807{
808 struct snd_interval *rate = hw_param_interval(params,
809 SNDRV_PCM_HW_PARAM_RATE);
810
811 struct snd_interval *channels = hw_param_interval(params,
812 SNDRV_PCM_HW_PARAM_CHANNELS);
813
814 rate->min = rate->max = msm8930_btsco_rate;
815 channels->min = channels->max = msm8930_btsco_ch;
816
817 return 0;
818}
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530819
Bhalchandra Gajare2e0893e2012-05-24 00:39:47 -0700820static int msm8930_auxpcm_be_params_fixup(struct snd_soc_pcm_runtime *rtd,
821 struct snd_pcm_hw_params *params)
822{
823 struct snd_interval *rate = hw_param_interval(params,
824 SNDRV_PCM_HW_PARAM_RATE);
825
826 struct snd_interval *channels = hw_param_interval(params,
827 SNDRV_PCM_HW_PARAM_CHANNELS);
828
829 /* PCM only supports mono output with 8khz sample rate */
830 rate->min = rate->max = 8000;
831 channels->min = channels->max = 1;
832
833 return 0;
834}
835
836static int msm8930_aux_pcm_get_gpios(void)
837{
838 int ret = 0;
839
840 pr_debug("%s\n", __func__);
841
842 ret = gpio_request(GPIO_AUX_PCM_DOUT, "AUX PCM DOUT");
843 if (ret < 0) {
844 pr_err("%s: Failed to request gpio(%d): AUX PCM DOUT",
845 __func__, GPIO_AUX_PCM_DOUT);
846
847 goto fail_dout;
848 }
849
850 ret = gpio_request(GPIO_AUX_PCM_DIN, "AUX PCM DIN");
851 if (ret < 0) {
852 pr_err("%s: Failed to request gpio(%d): AUX PCM DIN",
853 __func__, GPIO_AUX_PCM_DIN);
854 goto fail_din;
855 }
856
857 ret = gpio_request(GPIO_AUX_PCM_SYNC, "AUX PCM SYNC");
858 if (ret < 0) {
859 pr_err("%s: Failed to request gpio(%d): AUX PCM SYNC",
860 __func__, GPIO_AUX_PCM_SYNC);
861 goto fail_sync;
862 }
863
864 ret = gpio_request(GPIO_AUX_PCM_CLK, "AUX PCM CLK");
865 if (ret < 0) {
866 pr_err("%s: Failed to request gpio(%d): AUX PCM CLK",
867 __func__, GPIO_AUX_PCM_CLK);
868 goto fail_clk;
869 }
870
871 return 0;
872
873fail_clk:
874 gpio_free(GPIO_AUX_PCM_SYNC);
875fail_sync:
876 gpio_free(GPIO_AUX_PCM_DIN);
877fail_din:
878 gpio_free(GPIO_AUX_PCM_DOUT);
879fail_dout:
880
881 return ret;
882}
883
884static int msm8930_aux_pcm_free_gpios(void)
885{
886 gpio_free(GPIO_AUX_PCM_DIN);
887 gpio_free(GPIO_AUX_PCM_DOUT);
888 gpio_free(GPIO_AUX_PCM_SYNC);
889 gpio_free(GPIO_AUX_PCM_CLK);
890
891 return 0;
892}
893
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530894static int msm8930_startup(struct snd_pcm_substream *substream)
895{
896 pr_debug("%s(): substream = %s stream = %d\n", __func__,
897 substream->name, substream->stream);
898 return 0;
899}
900
Bhalchandra Gajare2e0893e2012-05-24 00:39:47 -0700901static int msm8930_auxpcm_startup(struct snd_pcm_substream *substream)
902{
903 int ret = 0;
904
905 pr_debug("%s(): substream = %s\n", __func__, substream->name);
906 ret = msm8930_aux_pcm_get_gpios();
907 if (ret < 0) {
908 pr_err("%s: Aux PCM GPIO request failed\n", __func__);
909 return -EINVAL;
910 }
911 return 0;
912
913}
914
915static void msm8930_auxpcm_shutdown(struct snd_pcm_substream *substream)
916{
917 pr_debug("%s(): substream = %s\n", __func__, substream->name);
918 msm8930_aux_pcm_free_gpios();
919}
920
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530921static void msm8930_shutdown(struct snd_pcm_substream *substream)
922{
923 pr_debug("%s(): substream = %s stream = %d\n", __func__,
924 substream->name, substream->stream);
925}
926
927static struct snd_soc_ops msm8930_be_ops = {
928 .startup = msm8930_startup,
929 .hw_params = msm8930_hw_params,
930 .shutdown = msm8930_shutdown,
931};
932
Bhalchandra Gajare2e0893e2012-05-24 00:39:47 -0700933static struct snd_soc_ops msm8930_auxpcm_be_ops = {
934 .startup = msm8930_auxpcm_startup,
935 .shutdown = msm8930_auxpcm_shutdown,
936};
937
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530938/* Digital audio interface glue - connects codec <---> CPU */
939static struct snd_soc_dai_link msm8930_dai[] = {
940 /* FrontEnd DAI Links */
941 {
942 .name = "MSM8930 Media1",
943 .stream_name = "MultiMedia1",
944 .cpu_dai_name = "MultiMedia1",
945 .platform_name = "msm-pcm-dsp",
946 .dynamic = 1,
947 .dsp_link = &fe_media,
948 .be_id = MSM_FRONTEND_DAI_MULTIMEDIA1
949 },
950 {
951 .name = "MSM8930 Media2",
952 .stream_name = "MultiMedia2",
953 .cpu_dai_name = "MultiMedia2",
954 .platform_name = "msm-pcm-dsp",
955 .dynamic = 1,
956 .dsp_link = &fe_media,
957 .be_id = MSM_FRONTEND_DAI_MULTIMEDIA2,
958 },
959 {
960 .name = "Circuit-Switch Voice",
961 .stream_name = "CS-Voice",
962 .cpu_dai_name = "CS-VOICE",
963 .platform_name = "msm-pcm-voice",
964 .dynamic = 1,
965 .dsp_link = &fe_media,
966 .be_id = MSM_FRONTEND_DAI_CS_VOICE,
967 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
968 .ignore_suspend = 1,
969 },
970 {
971 .name = "MSM VoIP",
972 .stream_name = "VoIP",
973 .cpu_dai_name = "VoIP",
974 .platform_name = "msm-voip-dsp",
975 .dynamic = 1,
976 .dsp_link = &fe_media,
977 .be_id = MSM_FRONTEND_DAI_VOIP,
978 },
979 {
980 .name = "MSM8930 LPA",
981 .stream_name = "LPA",
982 .cpu_dai_name = "MultiMedia3",
983 .platform_name = "msm-pcm-lpa",
984 .dynamic = 1,
985 .dsp_link = &lpa_fe_media,
986 .be_id = MSM_FRONTEND_DAI_MULTIMEDIA3,
987 },
988 /* Hostless PMC purpose */
989 {
990 .name = "SLIMBUS_0 Hostless",
991 .stream_name = "SLIMBUS_0 Hostless",
992 .cpu_dai_name = "SLIMBUS0_HOSTLESS",
993 .platform_name = "msm-pcm-hostless",
994 .dynamic = 1,
995 .dsp_link = &slimbus0_hl_media,
996 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
997 .ignore_suspend = 1,
998 /* .be_id = do not care */
999 },
1000 {
1001 .name = "INT_FM Hostless",
1002 .stream_name = "INT_FM Hostless",
1003 .cpu_dai_name = "INT_FM_HOSTLESS",
1004 .platform_name = "msm-pcm-hostless",
1005 .dynamic = 1,
1006 .dsp_link = &int_fm_hl_media,
1007 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
1008 .ignore_suspend = 1,
1009 /* .be_id = do not care */
1010 },
1011 {
1012 .name = "MSM AFE-PCM RX",
1013 .stream_name = "AFE-PROXY RX",
1014 .cpu_dai_name = "msm-dai-q6.241",
1015 .codec_name = "msm-stub-codec.1",
1016 .codec_dai_name = "msm-stub-rx",
1017 .platform_name = "msm-pcm-afe",
1018 .ignore_suspend = 1,
1019 },
1020 {
1021 .name = "MSM AFE-PCM TX",
1022 .stream_name = "AFE-PROXY TX",
1023 .cpu_dai_name = "msm-dai-q6.240",
1024 .codec_name = "msm-stub-codec.1",
1025 .codec_dai_name = "msm-stub-tx",
1026 .platform_name = "msm-pcm-afe",
1027 .ignore_suspend = 1,
1028 },
1029 {
1030 .name = "MSM8930 Compr",
1031 .stream_name = "COMPR",
1032 .cpu_dai_name = "MultiMedia4",
1033 .platform_name = "msm-compr-dsp",
1034 .dynamic = 1,
1035 .dsp_link = &lpa_fe_media,
1036 .be_id = MSM_FRONTEND_DAI_MULTIMEDIA4,
1037 },
1038 {
1039 .name = "AUXPCM Hostless",
1040 .stream_name = "AUXPCM Hostless",
1041 .cpu_dai_name = "AUXPCM_HOSTLESS",
1042 .platform_name = "msm-pcm-hostless",
1043 .dynamic = 1,
1044 .dsp_link = &bidir_hl_media,
1045 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
1046 .ignore_suspend = 1,
1047 },
1048 /* HDMI Hostless */
1049 {
1050 .name = "HDMI_RX_HOSTLESS",
1051 .stream_name = "HDMI_RX_HOSTLESS",
1052 .cpu_dai_name = "HDMI_HOSTLESS",
1053 .platform_name = "msm-pcm-hostless",
1054 .dynamic = 1,
1055 .dsp_link = &hdmi_rx_hl,
1056 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
1057 .no_codec = 1,
1058 .ignore_suspend = 1,
1059 },
1060 /* Backend DAI Links */
1061 {
1062 .name = LPASS_BE_SLIMBUS_0_RX,
1063 .stream_name = "Slimbus Playback",
1064 .cpu_dai_name = "msm-dai-q6.16384",
1065 .platform_name = "msm-pcm-routing",
1066 .codec_name = "sitar_codec",
1067 .codec_dai_name = "sitar_rx1",
1068 .no_pcm = 1,
1069 .be_id = MSM_BACKEND_DAI_SLIMBUS_0_RX,
1070 .init = &msm8930_audrx_init,
1071 .be_hw_params_fixup = msm8930_slim_0_rx_be_hw_params_fixup,
1072 .ops = &msm8930_be_ops,
1073 },
1074 {
1075 .name = LPASS_BE_SLIMBUS_0_TX,
1076 .stream_name = "Slimbus Capture",
1077 .cpu_dai_name = "msm-dai-q6.16385",
1078 .platform_name = "msm-pcm-routing",
1079 .codec_name = "sitar_codec",
1080 .codec_dai_name = "sitar_tx1",
1081 .no_pcm = 1,
1082 .be_id = MSM_BACKEND_DAI_SLIMBUS_0_TX,
1083 .be_hw_params_fixup = msm8930_slim_0_tx_be_hw_params_fixup,
1084 .ops = &msm8930_be_ops,
1085 },
1086 /* Backend BT/FM DAI Links */
1087 {
1088 .name = LPASS_BE_INT_BT_SCO_RX,
1089 .stream_name = "Internal BT-SCO Playback",
1090 .cpu_dai_name = "msm-dai-q6.12288",
1091 .platform_name = "msm-pcm-routing",
1092 .codec_name = "msm-stub-codec.1",
1093 .codec_dai_name = "msm-stub-rx",
1094 .init = &msm8930_btsco_init,
1095 .no_pcm = 1,
1096 .be_id = MSM_BACKEND_DAI_INT_BT_SCO_RX,
1097 .be_hw_params_fixup = msm8930_btsco_be_hw_params_fixup,
1098 },
1099 {
1100 .name = LPASS_BE_INT_BT_SCO_TX,
1101 .stream_name = "Internal BT-SCO Capture",
1102 .cpu_dai_name = "msm-dai-q6.12289",
1103 .platform_name = "msm-pcm-routing",
1104 .codec_name = "msm-stub-codec.1",
1105 .codec_dai_name = "msm-stub-tx",
1106 .no_pcm = 1,
1107 .be_id = MSM_BACKEND_DAI_INT_BT_SCO_TX,
1108 .be_hw_params_fixup = msm8930_btsco_be_hw_params_fixup,
1109 },
1110 {
1111 .name = LPASS_BE_INT_FM_RX,
1112 .stream_name = "Internal FM Playback",
1113 .cpu_dai_name = "msm-dai-q6.12292",
1114 .platform_name = "msm-pcm-routing",
1115 .codec_name = "msm-stub-codec.1",
1116 .codec_dai_name = "msm-stub-rx",
1117 .no_pcm = 1,
1118 .be_id = MSM_BACKEND_DAI_INT_FM_RX,
1119 .be_hw_params_fixup = msm8930_be_hw_params_fixup,
1120 },
1121 {
1122 .name = LPASS_BE_INT_FM_TX,
1123 .stream_name = "Internal FM Capture",
1124 .cpu_dai_name = "msm-dai-q6.12293",
1125 .platform_name = "msm-pcm-routing",
1126 .codec_name = "msm-stub-codec.1",
1127 .codec_dai_name = "msm-stub-tx",
1128 .no_pcm = 1,
1129 .be_id = MSM_BACKEND_DAI_INT_FM_TX,
1130 .be_hw_params_fixup = msm8930_be_hw_params_fixup,
1131 },
1132 /* HDMI BACK END DAI Link */
1133 {
1134 .name = LPASS_BE_HDMI,
1135 .stream_name = "HDMI Playback",
1136 .cpu_dai_name = "msm-dai-q6-hdmi.8",
1137 .platform_name = "msm-pcm-routing",
1138 .codec_name = "msm-stub-codec.1",
1139 .codec_dai_name = "msm-stub-rx",
1140 .no_pcm = 1,
1141 .no_codec = 1,
1142 .be_id = MSM_BACKEND_DAI_HDMI_RX,
1143 .be_hw_params_fixup = msm8930_hdmi_be_hw_params_fixup,
1144 },
1145 /* Backend AFE DAI Links */
1146 {
1147 .name = LPASS_BE_AFE_PCM_RX,
1148 .stream_name = "AFE Playback",
1149 .cpu_dai_name = "msm-dai-q6.224",
1150 .platform_name = "msm-pcm-routing",
1151 .codec_name = "msm-stub-codec.1",
1152 .codec_dai_name = "msm-stub-rx",
1153 .no_codec = 1,
1154 .no_pcm = 1,
1155 .be_id = MSM_BACKEND_DAI_AFE_PCM_RX,
1156 },
1157 {
1158 .name = LPASS_BE_AFE_PCM_TX,
1159 .stream_name = "AFE Capture",
1160 .cpu_dai_name = "msm-dai-q6.225",
1161 .platform_name = "msm-pcm-routing",
1162 .codec_name = "msm-stub-codec.1",
1163 .codec_dai_name = "msm-stub-tx",
1164 .no_codec = 1,
1165 .no_pcm = 1,
1166 .be_id = MSM_BACKEND_DAI_AFE_PCM_TX,
1167 },
Bhalchandra Gajare2e0893e2012-05-24 00:39:47 -07001168 /* AUX PCM Backend DAI Links */
1169 {
1170 .name = LPASS_BE_AUXPCM_RX,
1171 .stream_name = "AUX PCM Playback",
1172 .cpu_dai_name = "msm-dai-q6.2",
1173 .platform_name = "msm-pcm-routing",
1174 .codec_name = "msm-stub-codec.1",
1175 .codec_dai_name = "msm-stub-rx",
1176 .no_pcm = 1,
1177 .be_id = MSM_BACKEND_DAI_AUXPCM_RX,
1178 .be_hw_params_fixup = msm8930_auxpcm_be_params_fixup,
1179 .ops = &msm8930_auxpcm_be_ops,
1180 },
1181 {
1182 .name = LPASS_BE_AUXPCM_TX,
1183 .stream_name = "AUX PCM Capture",
1184 .cpu_dai_name = "msm-dai-q6.3",
1185 .platform_name = "msm-pcm-routing",
1186 .codec_name = "msm-stub-codec.1",
1187 .codec_dai_name = "msm-stub-tx",
1188 .no_pcm = 1,
1189 .be_id = MSM_BACKEND_DAI_AUXPCM_TX,
1190 .be_hw_params_fixup = msm8930_auxpcm_be_params_fixup,
1191 },
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301192 /* Incall Music BACK END DAI Link */
1193 {
1194 .name = LPASS_BE_VOICE_PLAYBACK_TX,
1195 .stream_name = "Voice Farend Playback",
1196 .cpu_dai_name = "msm-dai-q6.32773",
1197 .platform_name = "msm-pcm-routing",
1198 .codec_name = "msm-stub-codec.1",
1199 .codec_dai_name = "msm-stub-rx",
1200 .no_pcm = 1,
1201 .no_codec = 1,
1202 .be_id = MSM_BACKEND_DAI_VOICE_PLAYBACK_TX,
1203 .be_hw_params_fixup = msm8930_be_hw_params_fixup,
1204 },
1205 /* Incall Record Uplink BACK END DAI Link */
1206 {
1207 .name = LPASS_BE_INCALL_RECORD_TX,
1208 .stream_name = "Voice Uplink Capture",
1209 .cpu_dai_name = "msm-dai-q6.32772",
1210 .platform_name = "msm-pcm-routing",
1211 .codec_name = "msm-stub-codec.1",
1212 .codec_dai_name = "msm-stub-tx",
1213 .no_pcm = 1,
1214 .no_codec = 1,
1215 .be_id = MSM_BACKEND_DAI_INCALL_RECORD_TX,
1216 .be_hw_params_fixup = msm8930_be_hw_params_fixup,
1217 },
1218 /* Incall Record Downlink BACK END DAI Link */
1219 {
1220 .name = LPASS_BE_INCALL_RECORD_RX,
1221 .stream_name = "Voice Downlink Capture",
1222 .cpu_dai_name = "msm-dai-q6.32771",
1223 .platform_name = "msm-pcm-routing",
1224 .codec_name = "msm-stub-codec.1",
1225 .codec_dai_name = "msm-stub-tx",
1226 .no_pcm = 1,
1227 .no_codec = 1,
1228 .be_id = MSM_BACKEND_DAI_INCALL_RECORD_RX,
1229 .be_hw_params_fixup = msm8930_be_hw_params_fixup,
1230 },
1231};
1232
1233struct snd_soc_card snd_soc_card_msm8930 = {
1234 .name = "msm8930-sitar-snd-card",
1235 .dai_link = msm8930_dai,
1236 .num_links = ARRAY_SIZE(msm8930_dai),
1237};
1238
1239static struct platform_device *msm8930_snd_device;
1240
1241static int msm8930_configure_headset_mic_gpios(void)
1242{
1243 int ret;
1244 ret = gpio_request(80, "US_EURO_SWITCH");
1245 if (ret) {
1246 pr_err("%s: Failed to request gpio 80\n", __func__);
1247 return ret;
1248 }
1249 ret = gpio_direction_output(80, 0);
1250 if (ret) {
1251 pr_err("%s: Unable to set direction\n", __func__);
1252 gpio_free(80);
1253 }
1254 msm8930_headset_gpios_configured = 0;
1255 return 0;
1256}
1257static void msm8930_free_headset_mic_gpios(void)
1258{
1259 if (msm8930_headset_gpios_configured)
1260 gpio_free(80);
1261}
1262
1263static int __init msm8930_audio_init(void)
1264{
1265 int ret;
1266
1267 if (!cpu_is_msm8930()) {
1268 pr_err("%s: Not the right machine type\n", __func__);
1269 return -ENODEV ;
1270 }
Bhalchandra Gajare466aafe2012-05-02 17:55:26 -07001271 mbhc_cfg.calibration = def_sitar_mbhc_cal();
1272 if (!mbhc_cfg.calibration) {
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -08001273 pr_err("Calibration data allocation failed\n");
1274 return -ENOMEM;
1275 }
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301276
1277 msm8930_snd_device = platform_device_alloc("soc-audio", 0);
1278 if (!msm8930_snd_device) {
1279 pr_err("Platform device allocation failed\n");
Bhalchandra Gajare466aafe2012-05-02 17:55:26 -07001280 kfree(mbhc_cfg.calibration);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301281 return -ENOMEM;
1282 }
1283
1284 platform_set_drvdata(msm8930_snd_device, &snd_soc_card_msm8930);
1285 ret = platform_device_add(msm8930_snd_device);
1286 if (ret) {
1287 platform_device_put(msm8930_snd_device);
Bhalchandra Gajare466aafe2012-05-02 17:55:26 -07001288 kfree(mbhc_cfg.calibration);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301289 return ret;
1290 }
1291
1292 if (msm8930_configure_headset_mic_gpios()) {
1293 pr_err("%s Fail to configure headset mic gpios\n", __func__);
1294 msm8930_headset_gpios_configured = 0;
1295 } else
1296 msm8930_headset_gpios_configured = 1;
1297
1298 return ret;
1299
1300}
1301module_init(msm8930_audio_init);
1302
1303static void __exit msm8930_audio_exit(void)
1304{
1305 if (!cpu_is_msm8930()) {
1306 pr_err("%s: Not the right machine type\n", __func__);
1307 return ;
1308 }
1309 msm8930_free_headset_mic_gpios();
1310 platform_device_unregister(msm8930_snd_device);
Bhalchandra Gajare466aafe2012-05-02 17:55:26 -07001311 kfree(mbhc_cfg.calibration);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301312}
1313module_exit(msm8930_audio_exit);
1314
1315MODULE_DESCRIPTION("ALSA SoC MSM8930");
1316MODULE_LICENSE("GPL v2");