blob: da19ca56229efc9e7df042fdc28fbcfe3a2fabc4 [file] [log] [blame]
Helen Zeng47ca0072013-03-06 10:37:52 -08001/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05302 *
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>
Laxminath Kasam852c7812013-03-07 20:03:37 +053027#include <linux/mfd/pm8xxx/pm8038.h>
Asish Bhattacharyab86c3472012-02-15 08:31:52 +053028#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 Gajareb28275f2012-08-13 12:32:12 -070042#define LEFT_SPKR_AMPL_GPIO 15
Bhalchandra Gajare97676792012-05-22 17:41:45 -070043#define DEFAULT_PMIC_SPK_GAIN 0x0D
Asish Bhattacharyab86c3472012-02-15 08:31:52 +053044#define SITAR_EXT_CLK_RATE 12288000
45
Bhalchandra Gajare7708ee32012-05-24 17:37:37 -070046#define SITAR_MBHC_DEF_BUTTONS 8
Asish Bhattacharyab86c3472012-02-15 08:31:52 +053047#define SITAR_MBHC_DEF_RLOADS 5
48
Bhalchandra Gajare2e0893e2012-05-24 00:39:47 -070049#define GPIO_AUX_PCM_DOUT 63
50#define GPIO_AUX_PCM_DIN 64
51#define GPIO_AUX_PCM_SYNC 65
52#define GPIO_AUX_PCM_CLK 66
53
Laxminath Kasam82433012013-03-20 23:41:37 +053054#define GPIO_HS_US_EURO_SEL_GPIO 80
55#define GPIO_HS_US_EURO_SEL_GPIO_SGLTE 66
56
57#define GPIO_HS_DET 37
58#define GPIO_HS_DET_SGLTE 50
Laxminath Kasam852c7812013-03-07 20:03:37 +053059
60#define PM8038_GPIO_BASE NR_GPIO_IRQS
61#define PM8038_GPIO_PM_TO_SYS(pm_gpio) (pm_gpio - 1 + PM8038_GPIO_BASE)
Laxminath Kasam82433012013-03-20 23:41:37 +053062#define MSM8930_JACK_TYPES (SND_JACK_HEADSET | SND_JACK_OC_HPHL | \
63 SND_JACK_OC_HPHR | SND_JACK_UNSUPPORTED)
Laxminath Kasam852c7812013-03-07 20:03:37 +053064
Asish Bhattacharyab86c3472012-02-15 08:31:52 +053065static int msm8930_spk_control;
66static int msm8930_slim_0_rx_ch = 1;
67static int msm8930_slim_0_tx_ch = 1;
Bhalchandra Gajare97676792012-05-22 17:41:45 -070068static int msm8930_pmic_spk_gain = DEFAULT_PMIC_SPK_GAIN;
Laxminath Kasam82433012013-03-20 23:41:37 +053069static int us_euro_gpio;
Asish Bhattacharyab86c3472012-02-15 08:31:52 +053070
Asish Bhattacharyac71827a2012-03-05 10:11:45 -080071static int msm8930_ext_spk_pamp;
Asish Bhattacharyab86c3472012-02-15 08:31:52 +053072static int msm8930_btsco_rate = BTSCO_RATE_8KHZ;
73static int msm8930_btsco_ch = 1;
Vicky Sehrawat53f5c2e2012-11-05 17:54:13 -080074static int hdmi_rate_variable;
Subhash Chandra Bose Naripeddya3a99232013-01-11 14:05:21 -080075static int msm_hdmi_rx_ch = 2;
Asish Bhattacharyab86c3472012-02-15 08:31:52 +053076static struct clk *codec_clk;
77static int clk_users;
78
Laxminath Kasam82433012013-03-20 23:41:37 +053079static int msm8930_useuro_gpio_requested;
Laxminath Kasam3a8d49e2013-03-29 12:34:41 +053080static struct mutex cdc_mclk_mutex;
Asish Bhattacharyab86c3472012-02-15 08:31:52 +053081
82static struct snd_soc_jack hs_jack;
83static struct snd_soc_jack button_jack;
Kuirong Wang892c9ad2012-09-20 11:43:17 -070084static atomic_t auxpcm_rsc_ref;
Bhalchandra Gajare466aafe2012-05-02 17:55:26 -070085
86static int msm8930_enable_codec_ext_clk(
87 struct snd_soc_codec *codec, int enable,
88 bool dapm);
Laxminath Kasam82433012013-03-20 23:41:37 +053089static bool msm8930_swap_gnd_mic(struct snd_soc_codec *codec);
Bhalchandra Gajare466aafe2012-05-02 17:55:26 -070090
Laxminath Kasam852c7812013-03-07 20:03:37 +053091static u32 spkr_boost_enable_gpio = PM8038_GPIO_PM_TO_SYS(0x1);
92
93struct pm_gpio SPKR_ON = {
94 .direction = PM_GPIO_DIR_OUT,
95 .output_buffer = PM_GPIO_OUT_BUF_CMOS,
96 .output_value = 1,
97 .pull = PM_GPIO_PULL_NO,
98 .vin_sel = PM_GPIO_VIN_S4,
99 .out_strength = PM_GPIO_STRENGTH_MED,
100 .function = PM_GPIO_FUNC_NORMAL,
101};
102struct pm_gpio SPKR_OFF = {
103 .direction = PM_GPIO_DIR_OUT,
104 .output_buffer = PM_GPIO_OUT_BUF_CMOS,
105 .output_value = 0,
106 .pull = PM_GPIO_PULL_NO,
107 .vin_sel = PM_GPIO_VIN_S4,
108 .out_strength = PM_GPIO_STRENGTH_MED,
109 .function = PM_GPIO_FUNC_NORMAL,
110};
111
Bhalchandra Gajare466aafe2012-05-02 17:55:26 -0700112static struct sitar_mbhc_config mbhc_cfg = {
113 .headset_jack = &hs_jack,
114 .button_jack = &button_jack,
115 .read_fw_bin = false,
116 .calibration = NULL,
117 .micbias = SITAR_MICBIAS2,
118 .mclk_cb_fn = msm8930_enable_codec_ext_clk,
119 .mclk_rate = SITAR_EXT_CLK_RATE,
120 .gpio = 0,
121 .gpio_irq = 0,
122 .gpio_level_insert = 1,
Laxminath Kasam82433012013-03-20 23:41:37 +0530123 .swap_gnd_mic = NULL,
Bhalchandra Gajare466aafe2012-05-02 17:55:26 -0700124};
125
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530126static void msm8930_ext_control(struct snd_soc_codec *codec)
127{
128 struct snd_soc_dapm_context *dapm = &codec->dapm;
129
130 pr_debug("%s: msm8930_spk_control = %d", __func__, msm8930_spk_control);
131 if (msm8930_spk_control == MSM8930_SPK_ON) {
132 snd_soc_dapm_enable_pin(dapm, "Ext Spk Left Pos");
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800133 snd_soc_dapm_enable_pin(dapm, "Ext Spk left Neg");
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530134 } else {
135 snd_soc_dapm_disable_pin(dapm, "Ext Spk Left Pos");
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800136 snd_soc_dapm_disable_pin(dapm, "Ext Spk Left Neg");
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530137 }
138
139 snd_soc_dapm_sync(dapm);
140}
141
142static int msm8930_get_spk(struct snd_kcontrol *kcontrol,
143 struct snd_ctl_elem_value *ucontrol)
144{
145 pr_debug("%s: msm8930_spk_control = %d", __func__, msm8930_spk_control);
146 ucontrol->value.integer.value[0] = msm8930_spk_control;
147 return 0;
148}
149static int msm8930_set_spk(struct snd_kcontrol *kcontrol,
150 struct snd_ctl_elem_value *ucontrol)
151{
152 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
153
154 pr_debug("%s()\n", __func__);
155 if (msm8930_spk_control == ucontrol->value.integer.value[0])
156 return 0;
157
158 msm8930_spk_control = ucontrol->value.integer.value[0];
159 msm8930_ext_control(codec);
160 return 1;
161}
162
Bhalchandra Gajareb28275f2012-08-13 12:32:12 -0700163static int msm8930_cfg_spkr_gpio(int gpio,
164 int enable, const char *gpio_label)
165{
166 int ret = 0;
167
168 pr_debug("%s: Configure %s GPIO %u",
169 __func__, gpio_label, gpio);
170 ret = gpio_request(gpio, gpio_label);
171 if (ret)
172 return ret;
173
174 pr_debug("%s: Enable %s gpio %u\n",
175 __func__, gpio_label, gpio);
176 gpio_direction_output(gpio, enable);
177
178 return ret;
179}
180
Asish Bhattacharyac71827a2012-03-05 10:11:45 -0800181static void msm8960_ext_spk_power_amp_on(u32 spk)
182{
Bhalchandra Gajare98a28cd2012-05-16 12:00:20 -0700183 int ret = 0;
184
Asish Bhattacharyac71827a2012-03-05 10:11:45 -0800185 if (spk & (SPK_AMP_POS | SPK_AMP_NEG)) {
186 if ((msm8930_ext_spk_pamp & SPK_AMP_POS) &&
187 (msm8930_ext_spk_pamp & SPK_AMP_NEG)) {
188
189 pr_debug("%s() External Bottom Speaker Ampl already "
190 "turned on. spk = 0x%08x\n", __func__, spk);
191 return;
192 }
193
194 msm8930_ext_spk_pamp |= spk;
195
196 if ((msm8930_ext_spk_pamp & SPK_AMP_POS) &&
197 (msm8930_ext_spk_pamp & SPK_AMP_NEG)) {
198
Bhalchandra Gajareb28275f2012-08-13 12:32:12 -0700199 if (socinfo_get_pmic_model() == PMIC_MODEL_PM8917) {
200 ret = msm8930_cfg_spkr_gpio(
201 LEFT_SPKR_AMPL_GPIO,
202 1, "LEFT_SPKR_AMPL");
Bhalchandra Gajare98a28cd2012-05-16 12:00:20 -0700203 if (ret) {
Bhalchandra Gajareb28275f2012-08-13 12:32:12 -0700204 pr_err("%s: Failed to config ampl gpio %u\n",
205 __func__, LEFT_SPKR_AMPL_GPIO);
Bhalchandra Gajare98a28cd2012-05-16 12:00:20 -0700206 return;
207 }
Bhalchandra Gajareb28275f2012-08-13 12:32:12 -0700208 } else {
Bhalchandra Gajare98a28cd2012-05-16 12:00:20 -0700209
Bhalchandra Gajareb28275f2012-08-13 12:32:12 -0700210 if (machine_is_msm8930_mtp()
211 || machine_is_msm8930_fluid()) {
212 ret = msm8930_cfg_spkr_gpio(
213 SPKR_BOOST_GPIO, 1, "SPKR_BOOST");
214 if (ret) {
215 pr_err("%s: Failure: spkr boost gpio %u\n",
216 __func__, SPKR_BOOST_GPIO);
217 return;
218 }
Laxminath Kasam852c7812013-03-07 20:03:37 +0530219 } else if (socinfo_get_platform_subtype() ==
220 PLATFORM_SUBTYPE_SGLTE) {
221 ret = pm8xxx_gpio_config(
222 spkr_boost_enable_gpio,
223 &SPKR_ON);
224 if (ret) {
225 pr_err("%s: Failure: spkr" \
226 "boost gpio ON %u\n",
227 __func__, spkr_boost_enable_gpio);
228 return;
229 } else {
230 pr_debug("%s:Config PMIC8038" \
231 "gpio for speaker ON successfully\n",
232 __func__);
233 }
Bhalchandra Gajareb28275f2012-08-13 12:32:12 -0700234 }
235 pm8xxx_spk_enable(MSM8930_SPK_ON);
Bhalchandra Gajare98a28cd2012-05-16 12:00:20 -0700236 }
237
Asish Bhattacharyac71827a2012-03-05 10:11:45 -0800238 pr_debug("%s: slepping 4 ms after turning on external "
239 " Left Speaker Ampl\n", __func__);
240 usleep_range(4000, 4000);
241 }
242
243 } else {
244
245 pr_err("%s: ERROR : Invalid External Speaker Ampl. spk = 0x%08x\n",
246 __func__, spk);
247 return;
248 }
249}
250
251static void msm8960_ext_spk_power_amp_off(u32 spk)
252{
Laxminath Kasam852c7812013-03-07 20:03:37 +0530253 int ret = 0;
Asish Bhattacharyac71827a2012-03-05 10:11:45 -0800254 if (spk & (SPK_AMP_POS | SPK_AMP_NEG)) {
255 if (!msm8930_ext_spk_pamp)
256 return;
Bhalchandra Gajareb28275f2012-08-13 12:32:12 -0700257
258 if (socinfo_get_pmic_model() == PMIC_MODEL_PM8917) {
259 gpio_free(LEFT_SPKR_AMPL_GPIO);
260 msm8930_ext_spk_pamp = 0;
261 return;
262 }
263
Bhalchandra Gajare98a28cd2012-05-16 12:00:20 -0700264 if (machine_is_msm8930_mtp()
265 || machine_is_msm8930_fluid()) {
266 pr_debug("%s: Free speaker boost gpio %u\n",
267 __func__, SPKR_BOOST_GPIO);
268 gpio_direction_output(SPKR_BOOST_GPIO, 0);
269 gpio_free(SPKR_BOOST_GPIO);
Laxminath Kasam852c7812013-03-07 20:03:37 +0530270 } else if (socinfo_get_platform_subtype() ==
271 PLATFORM_SUBTYPE_SGLTE) {
272 ret = pm8xxx_gpio_config(spkr_boost_enable_gpio,
273 &SPKR_OFF);
274 if (ret) {
275 pr_err("%s: Failure: spkr boost gpio OFF %u\n",
276 __func__, spkr_boost_enable_gpio);
277 return;
278 } else {
279 pr_debug("%s:Config PMIC8038 gpio for speaker" \
280 " OFF successfully\n", __func__);
281 }
Bhalchandra Gajare98a28cd2012-05-16 12:00:20 -0700282 }
Asish Bhattacharyac71827a2012-03-05 10:11:45 -0800283
284 pm8xxx_spk_enable(MSM8930_SPK_OFF);
285 msm8930_ext_spk_pamp = 0;
286 pr_debug("%s: slepping 4 ms after turning on external "
287 " Left Speaker Ampl\n", __func__);
288 usleep_range(4000, 4000);
289
290 } else {
291
292 pr_err("%s: ERROR : Invalid External Speaker Ampl. spk = 0x%08x\n",
293 __func__, spk);
294 return;
295 }
296}
297
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530298static int msm8930_spkramp_event(struct snd_soc_dapm_widget *w,
299 struct snd_kcontrol *k, int event)
300{
301 pr_debug("%s() %x\n", __func__, SND_SOC_DAPM_EVENT_ON(event));
Asish Bhattacharyac71827a2012-03-05 10:11:45 -0800302 if (SND_SOC_DAPM_EVENT_ON(event)) {
303 if (!strncmp(w->name, "Ext Spk Left Pos", 17))
304 msm8960_ext_spk_power_amp_on(SPK_AMP_POS);
305 else if (!strncmp(w->name, "Ext Spk Left Neg", 17))
306 msm8960_ext_spk_power_amp_on(SPK_AMP_NEG);
307 else {
308 pr_err("%s() Invalid Speaker Widget = %s\n",
309 __func__, w->name);
310 return -EINVAL;
311 }
312 } else {
313 if (!strncmp(w->name, "Ext Spk Left Pos", 17))
314 msm8960_ext_spk_power_amp_off(SPK_AMP_POS);
315 else if (!strncmp(w->name, "Ext Spk Left Neg", 17))
316 msm8960_ext_spk_power_amp_off(SPK_AMP_NEG);
317 else {
318 pr_err("%s() Invalid Speaker Widget = %s\n",
319 __func__, w->name);
320 return -EINVAL;
321 }
322 }
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530323 return 0;
324}
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800325
Bhalchandra Gajare466aafe2012-05-02 17:55:26 -0700326static int msm8930_enable_codec_ext_clk(
327 struct snd_soc_codec *codec, int enable,
328 bool dapm)
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530329{
Laxminath Kasam3a8d49e2013-03-29 12:34:41 +0530330 int r = 0;
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530331 pr_debug("%s: enable = %d\n", __func__, enable);
Laxminath Kasam3a8d49e2013-03-29 12:34:41 +0530332
333 mutex_lock(&cdc_mclk_mutex);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530334 if (enable) {
335 clk_users++;
336 pr_debug("%s: clk_users = %d\n", __func__, clk_users);
Laxminath Kasam3a8d49e2013-03-29 12:34:41 +0530337 if (clk_users == 1) {
338 if (codec_clk) {
339 clk_set_rate(codec_clk, SITAR_EXT_CLK_RATE);
340 clk_prepare_enable(codec_clk);
341 sitar_mclk_enable(codec, 1, dapm);
342 } else {
343 pr_err("%s: Error setting Sitar MCLK\n",
344 __func__);
345 clk_users--;
346 r = -EINVAL;
347 }
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530348 }
349 } else {
Laxminath Kasam3a8d49e2013-03-29 12:34:41 +0530350 if (clk_users > 0) {
351 clk_users--;
352 pr_debug("%s: clk_users = %d\n", __func__, clk_users);
353 if (clk_users == 0) {
354 pr_debug("%s: disabling MCLK. clk_users = %d\n",
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530355 __func__, clk_users);
Laxminath Kasam3a8d49e2013-03-29 12:34:41 +0530356 sitar_mclk_enable(codec, 0, dapm);
357 clk_disable_unprepare(codec_clk);
358 }
359 } else {
360 pr_err("%s: Error releasing Sitar MCLK\n", __func__);
361 r = -EINVAL;
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530362 }
363 }
Laxminath Kasam3a8d49e2013-03-29 12:34:41 +0530364 mutex_unlock(&cdc_mclk_mutex);
365 return r;
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530366}
367
Laxminath Kasam82433012013-03-20 23:41:37 +0530368static bool msm8930_swap_gnd_mic(struct snd_soc_codec *codec)
369{
370 int value = 0;
371
372 value = gpio_get_value_cansleep(us_euro_gpio);
373 pr_debug("%s: US EURO select switch %d to %d\n", __func__, value,
374 !value);
375 gpio_set_value_cansleep(us_euro_gpio, !value);
376 return true;
377}
378
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530379static int msm8930_mclk_event(struct snd_soc_dapm_widget *w,
380 struct snd_kcontrol *kcontrol, int event)
381{
382 pr_debug("%s: event = %d\n", __func__, event);
383
384 switch (event) {
385 case SND_SOC_DAPM_PRE_PMU:
Bhalchandra Gajare466aafe2012-05-02 17:55:26 -0700386 return msm8930_enable_codec_ext_clk(w->codec, 1, true);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530387 case SND_SOC_DAPM_POST_PMD:
Bhalchandra Gajare466aafe2012-05-02 17:55:26 -0700388 return msm8930_enable_codec_ext_clk(w->codec, 0, true);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530389 }
390 return 0;
391}
392
393static const struct snd_soc_dapm_widget msm8930_dapm_widgets[] = {
394
395 SND_SOC_DAPM_SUPPLY("MCLK", SND_SOC_NOPM, 0, 0,
396 msm8930_mclk_event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
397
398 SND_SOC_DAPM_SPK("Ext Spk Left Pos", msm8930_spkramp_event),
Asish Bhattacharyac71827a2012-03-05 10:11:45 -0800399 SND_SOC_DAPM_SPK("Ext Spk Left Neg", msm8930_spkramp_event),
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530400
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530401 SND_SOC_DAPM_MIC("Headset Mic", NULL),
402 SND_SOC_DAPM_MIC("Digital Mic1", NULL),
403 SND_SOC_DAPM_MIC("ANCRight Headset Mic", NULL),
404 SND_SOC_DAPM_MIC("ANCLeft Headset Mic", NULL),
405
406 SND_SOC_DAPM_MIC("Digital Mic1", NULL),
407 SND_SOC_DAPM_MIC("Digital Mic2", NULL),
408 SND_SOC_DAPM_MIC("Digital Mic3", NULL),
409 SND_SOC_DAPM_MIC("Digital Mic4", NULL),
410
411};
412
413static const struct snd_soc_dapm_route common_audio_map[] = {
414
415 {"RX_BIAS", NULL, "MCLK"},
416 {"LDO_H", NULL, "MCLK"},
417
418 {"MIC BIAS1 Internal1", NULL, "MCLK"},
419 {"MIC BIAS2 Internal1", NULL, "MCLK"},
420
421 /* Speaker path */
422 {"Ext Spk Left Pos", NULL, "LINEOUT1"},
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800423 {"Ext Spk Left Neg", NULL, "LINEOUT2"},
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530424
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800425 /* Headset Mic */
Bhalchandra Gajare553fb9e2012-06-26 14:48:54 -0700426 {"AMIC2", NULL, "MIC BIAS2 External"},
427 {"MIC BIAS2 External", NULL, "Headset Mic"},
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530428
429 /* Microphone path */
Bhalchandra Gajare18314d52012-06-06 19:03:01 -0700430 {"AMIC1", NULL, "MIC BIAS2 External"},
431 {"MIC BIAS2 External", NULL, "ANCLeft Headset Mic"},
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800432
Bhalchandra Gajare18314d52012-06-06 19:03:01 -0700433 {"AMIC3", NULL, "MIC BIAS2 External"},
434 {"MIC BIAS2 External", NULL, "ANCRight Headset Mic"},
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530435
436 {"HEADPHONE", NULL, "LDO_H"},
437
438 /**
439 * The digital Mic routes are setup considering
440 * fluid as default device.
441 */
442
443 /**
Bhalchandra Gajaree6a30f72012-05-23 19:46:21 -0700444 * Digital Mic1. Front Bottom left Mic on Fluid and MTP.
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530445 * Digital Mic GM5 on CDP mainboard.
Bhalchandra Gajaree6a30f72012-05-23 19:46:21 -0700446 * Conncted to DMIC1 Input on Sitar codec.
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530447 */
448 {"DMIC1", NULL, "MIC BIAS1 External"},
449 {"MIC BIAS1 External", NULL, "Digital Mic1"},
450
451 /**
Bhalchandra Gajaree6a30f72012-05-23 19:46:21 -0700452 * Digital Mic2. Back top MIC on Fluid.
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530453 * Digital Mic GM6 on CDP mainboard.
Bhalchandra Gajaree6a30f72012-05-23 19:46:21 -0700454 * Conncted to DMIC2 Input on Sitar codec.
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530455 */
456 {"DMIC2", NULL, "MIC BIAS1 External"},
457 {"MIC BIAS1 External", NULL, "Digital Mic2"},
458 /**
459 * Digital Mic3. Back Bottom Digital Mic on Fluid.
460 * Digital Mic GM1 on CDP mainboard.
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800461 * Conncted to DMIC4 Input on Sitar codec.
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530462 */
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800463 {"DMIC3", NULL, "MIC BIAS1 External"},
464 {"MIC BIAS1 External", NULL, "Digital Mic3"},
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530465
466 /**
467 * Digital Mic4. Back top Digital Mic on Fluid.
468 * Digital Mic GM2 on CDP mainboard.
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800469 * Conncted to DMIC3 Input on Sitar codec.
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530470 */
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800471 {"DMIC4", NULL, "MIC BIAS1 External"},
472 {"MIC BIAS1 External", NULL, "Digital Mic4"},
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530473
474
475};
476
Laxminath Kasam852c7812013-03-07 20:03:37 +0530477static const struct snd_soc_dapm_route common_audio_map_sglte[] = {
478
479 {"RX_BIAS", NULL, "MCLK"},
480 {"LDO_H", NULL, "MCLK"},
481
482 {"MIC BIAS1 Internal1", NULL, "MCLK"},
483 {"MIC BIAS2 Internal1", NULL, "MCLK"},
484
485 /* Speaker path */
486 {"Ext Spk Left Pos", NULL, "LINEOUT1"},
487 {"Ext Spk Left Neg", NULL, "LINEOUT2"},
488
489 /* Headset Mic */
490 {"AMIC2", NULL, "MIC BIAS2 External"},
491 {"MIC BIAS2 External", NULL, "Headset Mic"},
492
493 /* Microphone path */
494 {"AMIC1", NULL, "MIC BIAS1 External"},
495 {"MIC BIAS1 External", NULL, "ANCLeft Headset Mic"},
496
497 {"AMIC3", NULL, "MIC BIAS1 External"},
498 {"MIC BIAS1 External", NULL, "ANCRight Headset Mic"},
499
500 {"HEADPHONE", NULL, "LDO_H"},
501};
502
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530503static const char *spk_function[] = {"Off", "On"};
504static const char *slim0_rx_ch_text[] = {"One", "Two"};
505static const char *slim0_tx_ch_text[] = {"One", "Two", "Three", "Four"};
Subhash Chandra Bose Naripeddya3a99232013-01-11 14:05:21 -0800506static char const *hdmi_rx_ch_text[] = {"Two", "Three", "Four", "Five",
507 "Six", "Seven", "Eight"};
Vicky Sehrawat53f5c2e2012-11-05 17:54:13 -0800508static const char * const hdmi_rate[] = {"Default", "Variable"};
509
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530510static const struct soc_enum msm8930_enum[] = {
511 SOC_ENUM_SINGLE_EXT(2, spk_function),
512 SOC_ENUM_SINGLE_EXT(2, slim0_rx_ch_text),
513 SOC_ENUM_SINGLE_EXT(4, slim0_tx_ch_text),
Vicky Sehrawat53f5c2e2012-11-05 17:54:13 -0800514 SOC_ENUM_SINGLE_EXT(2, hdmi_rate),
Subhash Chandra Bose Naripeddya3a99232013-01-11 14:05:21 -0800515 SOC_ENUM_SINGLE_EXT(7, hdmi_rx_ch_text),
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530516};
517
518static const char *btsco_rate_text[] = {"8000", "16000"};
519static const struct soc_enum msm8930_btsco_enum[] = {
520 SOC_ENUM_SINGLE_EXT(2, btsco_rate_text),
521};
522
523static int msm8930_slim_0_rx_ch_get(struct snd_kcontrol *kcontrol,
524 struct snd_ctl_elem_value *ucontrol)
525{
526 pr_debug("%s: msm8930_slim_0_rx_ch = %d\n", __func__,
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800527 msm8930_slim_0_rx_ch);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530528 ucontrol->value.integer.value[0] = msm8930_slim_0_rx_ch - 1;
529 return 0;
530}
531
532static int msm8930_slim_0_rx_ch_put(struct snd_kcontrol *kcontrol,
533 struct snd_ctl_elem_value *ucontrol)
534{
535 msm8930_slim_0_rx_ch = ucontrol->value.integer.value[0] + 1;
536
537 pr_debug("%s: msm8930_slim_0_rx_ch = %d\n", __func__,
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800538 msm8930_slim_0_rx_ch);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530539 return 1;
540}
541
542static int msm8930_slim_0_tx_ch_get(struct snd_kcontrol *kcontrol,
543 struct snd_ctl_elem_value *ucontrol)
544{
545 pr_debug("%s: msm8930_slim_0_tx_ch = %d\n", __func__,
546 msm8930_slim_0_tx_ch);
547 ucontrol->value.integer.value[0] = msm8930_slim_0_tx_ch - 1;
548 return 0;
549}
550
551static int msm8930_slim_0_tx_ch_put(struct snd_kcontrol *kcontrol,
552 struct snd_ctl_elem_value *ucontrol)
553{
554 msm8930_slim_0_tx_ch = ucontrol->value.integer.value[0] + 1;
555
556 pr_debug("%s: msm8930_slim_0_tx_ch = %d\n", __func__,
557 msm8930_slim_0_tx_ch);
558 return 1;
559}
560
561static int msm8930_btsco_rate_get(struct snd_kcontrol *kcontrol,
562 struct snd_ctl_elem_value *ucontrol)
563{
564 pr_debug("%s: msm8930_btsco_rate = %d", __func__, msm8930_btsco_rate);
565 ucontrol->value.integer.value[0] = msm8930_btsco_rate;
566 return 0;
567}
568
569static int msm8930_btsco_rate_put(struct snd_kcontrol *kcontrol,
570 struct snd_ctl_elem_value *ucontrol)
571{
Kuirong Wangfd8e0b32012-05-30 19:45:04 -0700572
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530573 switch (ucontrol->value.integer.value[0]) {
Kuirong Wangfd8e0b32012-05-30 19:45:04 -0700574 case 8000:
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530575 msm8930_btsco_rate = BTSCO_RATE_8KHZ;
576 break;
Kuirong Wangfd8e0b32012-05-30 19:45:04 -0700577 case 16000:
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530578 msm8930_btsco_rate = BTSCO_RATE_16KHZ;
579 break;
580 default:
581 msm8930_btsco_rate = BTSCO_RATE_8KHZ;
582 break;
583 }
584 pr_debug("%s: msm8930_btsco_rate = %d\n", __func__, msm8930_btsco_rate);
585 return 0;
586}
587
Bhalchandra Gajare97676792012-05-22 17:41:45 -0700588static const char *pmic_spk_gain_text[] = {
589 "NEG_6_DB", "NEG_4_DB", "NEG_2_DB", "ZERO_DB", "POS_2_DB", "POS_4_DB",
590 "POS_6_DB", "POS_8_DB", "POS_10_DB", "POS_12_DB", "POS_14_DB",
591 "POS_16_DB", "POS_18_DB", "POS_20_DB", "POS_22_DB", "POS_24_DB"
592};
593
594static const struct soc_enum msm8960_pmic_spk_gain_enum[] = {
595 SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(pmic_spk_gain_text),
596 pmic_spk_gain_text),
597};
598
599static int msm8930_pmic_gain_get(struct snd_kcontrol *kcontrol,
600 struct snd_ctl_elem_value *ucontrol)
601{
602 pr_debug("%s: msm8930_pmic_spk_gain = %d\n", __func__,
603 msm8930_pmic_spk_gain);
604 ucontrol->value.integer.value[0] = msm8930_pmic_spk_gain;
605 return 0;
606}
607
608static int msm8930_pmic_gain_put(struct snd_kcontrol *kcontrol,
609 struct snd_ctl_elem_value *ucontrol)
610{
611 int ret = 0;
612 msm8930_pmic_spk_gain = ucontrol->value.integer.value[0];
Bhalchandra Gajareb28275f2012-08-13 12:32:12 -0700613 if (socinfo_get_pmic_model() != PMIC_MODEL_PM8917)
614 ret = pm8xxx_spk_gain(msm8930_pmic_spk_gain);
Bhalchandra Gajare97676792012-05-22 17:41:45 -0700615 pr_debug("%s: msm8930_pmic_spk_gain = %d"
616 " ucontrol->value.integer.value[0] = %d\n", __func__,
617 msm8930_pmic_spk_gain,
618 (int) ucontrol->value.integer.value[0]);
619 return ret;
620}
621
Subhash Chandra Bose Naripeddya3a99232013-01-11 14:05:21 -0800622static int msm_hdmi_rx_ch_get(struct snd_kcontrol *kcontrol,
623 struct snd_ctl_elem_value *ucontrol)
624{
625 pr_debug("%s: msm_hdmi_rx_ch = %d\n", __func__,
626 msm_hdmi_rx_ch);
627 ucontrol->value.integer.value[0] = msm_hdmi_rx_ch - 2;
628 return 0;
629}
630
631static int msm_hdmi_rx_ch_put(struct snd_kcontrol *kcontrol,
632 struct snd_ctl_elem_value *ucontrol)
633{
634 msm_hdmi_rx_ch = ucontrol->value.integer.value[0] + 2;
635
636 pr_debug("%s: msm_hdmi_rx_ch = %d\n", __func__,
637 msm_hdmi_rx_ch);
638 return 1;
639}
640
Vicky Sehrawat53f5c2e2012-11-05 17:54:13 -0800641static int msm8930_hdmi_rate_put(struct snd_kcontrol *kcontrol,
642 struct snd_ctl_elem_value *ucontrol)
643{
644 hdmi_rate_variable = ucontrol->value.integer.value[0];
645 pr_debug("%s: hdmi_rate_variable = %d\n", __func__, hdmi_rate_variable);
646 return 0;
647}
648
649static int msm8930_hdmi_rate_get(struct snd_kcontrol *kcontrol,
650 struct snd_ctl_elem_value *ucontrol)
651{
652 ucontrol->value.integer.value[0] = hdmi_rate_variable;
653 return 0;
654}
655
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530656static const struct snd_kcontrol_new sitar_msm8930_controls[] = {
657 SOC_ENUM_EXT("Speaker Function", msm8930_enum[0], msm8930_get_spk,
658 msm8930_set_spk),
659 SOC_ENUM_EXT("SLIM_0_RX Channels", msm8930_enum[1],
660 msm8930_slim_0_rx_ch_get, msm8930_slim_0_rx_ch_put),
661 SOC_ENUM_EXT("SLIM_0_TX Channels", msm8930_enum[2],
662 msm8930_slim_0_tx_ch_get, msm8930_slim_0_tx_ch_put),
Bhalchandra Gajare97676792012-05-22 17:41:45 -0700663 SOC_ENUM_EXT("PMIC SPK Gain", msm8960_pmic_spk_gain_enum[0],
664 msm8930_pmic_gain_get, msm8930_pmic_gain_put),
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530665 SOC_ENUM_EXT("Internal BTSCO SampleRate", msm8930_btsco_enum[0],
666 msm8930_btsco_rate_get, msm8930_btsco_rate_put),
Vicky Sehrawat53f5c2e2012-11-05 17:54:13 -0800667 SOC_ENUM_EXT("HDMI RX Rate", msm8930_enum[3],
668 msm8930_hdmi_rate_get,
669 msm8930_hdmi_rate_put),
Subhash Chandra Bose Naripeddya3a99232013-01-11 14:05:21 -0800670 SOC_ENUM_EXT("HDMI_RX Channels", msm8930_enum[4],
671 msm_hdmi_rx_ch_get, msm_hdmi_rx_ch_put),
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530672};
673
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800674static void *def_sitar_mbhc_cal(void)
675{
676 void *sitar_cal;
677 struct sitar_mbhc_btn_detect_cfg *btn_cfg;
678 u16 *btn_low, *btn_high;
679 u8 *n_ready, *n_cic, *gain;
680
681 sitar_cal = kzalloc(SITAR_MBHC_CAL_SIZE(SITAR_MBHC_DEF_BUTTONS,
682 SITAR_MBHC_DEF_RLOADS),
683 GFP_KERNEL);
684 if (!sitar_cal) {
685 pr_err("%s: out of memory\n", __func__);
686 return NULL;
687 }
688
689#define S(X, Y) ((SITAR_MBHC_CAL_GENERAL_PTR(sitar_cal)->X) = (Y))
690 S(t_ldoh, 100);
691 S(t_bg_fast_settle, 100);
692 S(t_shutdown_plug_rem, 255);
693 S(mbhc_nsa, 4);
694 S(mbhc_navg, 4);
695#undef S
696#define S(X, Y) ((SITAR_MBHC_CAL_PLUG_DET_PTR(sitar_cal)->X) = (Y))
697 S(mic_current, SITAR_PID_MIC_5_UA);
698 S(hph_current, SITAR_PID_MIC_5_UA);
699 S(t_mic_pid, 100);
700 S(t_ins_complete, 250);
701 S(t_ins_retry, 200);
702#undef S
703#define S(X, Y) ((SITAR_MBHC_CAL_PLUG_TYPE_PTR(sitar_cal)->X) = (Y))
704 S(v_no_mic, 30);
Bhalchandra Gajare18314d52012-06-06 19:03:01 -0700705 S(v_hs_max, 1650);
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800706#undef S
707#define S(X, Y) ((SITAR_MBHC_CAL_BTN_DET_PTR(sitar_cal)->X) = (Y))
708 S(c[0], 62);
709 S(c[1], 124);
710 S(nc, 1);
711 S(n_meas, 3);
712 S(mbhc_nsc, 11);
713 S(n_btn_meas, 1);
714 S(n_btn_con, 2);
715 S(num_btn, SITAR_MBHC_DEF_BUTTONS);
716 S(v_btn_press_delta_sta, 100);
717 S(v_btn_press_delta_cic, 50);
718#undef S
719 btn_cfg = SITAR_MBHC_CAL_BTN_DET_PTR(sitar_cal);
720 btn_low = sitar_mbhc_cal_btn_det_mp(btn_cfg, SITAR_BTN_DET_V_BTN_LOW);
721 btn_high = sitar_mbhc_cal_btn_det_mp(btn_cfg, SITAR_BTN_DET_V_BTN_HIGH);
722 btn_low[0] = -50;
723 btn_high[0] = 10;
724 btn_low[1] = 11;
725 btn_high[1] = 38;
726 btn_low[2] = 39;
727 btn_high[2] = 64;
728 btn_low[3] = 65;
729 btn_high[3] = 91;
730 btn_low[4] = 92;
731 btn_high[4] = 115;
732 btn_low[5] = 116;
733 btn_high[5] = 141;
734 btn_low[6] = 142;
735 btn_high[6] = 163;
736 btn_low[7] = 164;
737 btn_high[7] = 250;
738 n_ready = sitar_mbhc_cal_btn_det_mp(btn_cfg, SITAR_BTN_DET_N_READY);
739 n_ready[0] = 48;
740 n_ready[1] = 38;
741 n_cic = sitar_mbhc_cal_btn_det_mp(btn_cfg, SITAR_BTN_DET_N_CIC);
742 n_cic[0] = 60;
743 n_cic[1] = 47;
744 gain = sitar_mbhc_cal_btn_det_mp(btn_cfg, SITAR_BTN_DET_GAIN);
745 gain[0] = 11;
746 gain[1] = 9;
747
748 return sitar_cal;
749}
750
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530751static int msm8930_hw_params(struct snd_pcm_substream *substream,
752 struct snd_pcm_hw_params *params)
753{
754 struct snd_soc_pcm_runtime *rtd = substream->private_data;
755 struct snd_soc_dai *codec_dai = rtd->codec_dai;
756 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
757 int ret = 0;
758 unsigned int rx_ch[SLIM_MAX_RX_PORTS], tx_ch[SLIM_MAX_TX_PORTS];
759 unsigned int rx_ch_cnt = 0, tx_ch_cnt = 0;
760
761 pr_debug("%s: ch=%d\n", __func__,
762 msm8930_slim_0_rx_ch);
763 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
764 ret = snd_soc_dai_get_channel_map(codec_dai,
765 &tx_ch_cnt, tx_ch, &rx_ch_cnt , rx_ch);
766 if (ret < 0) {
767 pr_err("%s: failed to get codec chan map\n", __func__);
768 goto end;
769 }
770
771 ret = snd_soc_dai_set_channel_map(cpu_dai, 0, 0,
772 msm8930_slim_0_rx_ch, rx_ch);
773 if (ret < 0) {
774 pr_err("%s: failed to set cpu chan map\n", __func__);
775 goto end;
776 }
777 ret = snd_soc_dai_set_channel_map(codec_dai, 0, 0,
778 msm8930_slim_0_rx_ch, rx_ch);
779 if (ret < 0) {
780 pr_err("%s: failed to set codec channel map\n",
781 __func__);
782 goto end;
783 }
784 } else {
785 ret = snd_soc_dai_get_channel_map(codec_dai,
786 &tx_ch_cnt, tx_ch, &rx_ch_cnt , rx_ch);
787 if (ret < 0) {
788 pr_err("%s: failed to get codec chan map\n", __func__);
789 goto end;
790 }
791 ret = snd_soc_dai_set_channel_map(cpu_dai,
792 msm8930_slim_0_tx_ch, tx_ch, 0 , 0);
793 if (ret < 0) {
794 pr_err("%s: failed to set cpu chan map\n", __func__);
795 goto end;
796 }
797 ret = snd_soc_dai_set_channel_map(codec_dai,
798 msm8930_slim_0_tx_ch, tx_ch, 0, 0);
799 if (ret < 0) {
800 pr_err("%s: failed to set codec channel map\n",
801 __func__);
802 goto end;
803 }
804
805 }
806end:
807 return ret;
808}
809
810static int msm8930_audrx_init(struct snd_soc_pcm_runtime *rtd)
811{
812 int err;
813 struct snd_soc_codec *codec = rtd->codec;
814 struct snd_soc_dapm_context *dapm = &codec->dapm;
815 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
816
817 pr_debug("%s()\n", __func__);
818
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530819 snd_soc_dapm_new_controls(dapm, msm8930_dapm_widgets,
820 ARRAY_SIZE(msm8930_dapm_widgets));
821
Laxminath Kasam852c7812013-03-07 20:03:37 +0530822 if (socinfo_get_platform_subtype() == PLATFORM_SUBTYPE_SGLTE)
823 snd_soc_dapm_add_routes(dapm, common_audio_map_sglte,
824 ARRAY_SIZE(common_audio_map_sglte));
825 else
826 snd_soc_dapm_add_routes(dapm, common_audio_map,
827 ARRAY_SIZE(common_audio_map));
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530828
829 snd_soc_dapm_enable_pin(dapm, "Ext Spk Left Pos");
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800830 snd_soc_dapm_enable_pin(dapm, "Ext Spk Left Neg");
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530831
832 snd_soc_dapm_sync(dapm);
833
834 err = snd_soc_jack_new(codec, "Headset Jack",
Laxminath Kasam82433012013-03-20 23:41:37 +0530835 MSM8930_JACK_TYPES,
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530836 &hs_jack);
837 if (err) {
838 pr_err("failed to create new jack\n");
839 return err;
840 }
841
842 err = snd_soc_jack_new(codec, "Button Jack",
Bhalchandra Gajare7708ee32012-05-24 17:37:37 -0700843 SITAR_JACK_BUTTON_MASK, &button_jack);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530844 if (err) {
845 pr_err("failed to create new jack\n");
846 return err;
847 }
848 codec_clk = clk_get(cpu_dai->dev, "osr_clk");
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800849
Laxminath Kasam82433012013-03-20 23:41:37 +0530850 /*
851 * Switch is present only in 8930 CDP and SGLTE
852 */
853 if (socinfo_get_platform_subtype() == PLATFORM_SUBTYPE_SGLTE ||
854 machine_is_msm8930_cdp())
855 mbhc_cfg.swap_gnd_mic = msm8930_swap_gnd_mic;
856
Laxminath Kasamc8082aa2013-03-15 21:08:20 +0530857 if (socinfo_get_platform_subtype() == PLATFORM_SUBTYPE_SGLTE) {
Laxminath Kasam82433012013-03-20 23:41:37 +0530858 mbhc_cfg.gpio = GPIO_HS_DET_SGLTE;
Laxminath Kasamc8082aa2013-03-15 21:08:20 +0530859 mbhc_cfg.gpio_level_insert = 0;
Laxminath Kasam82433012013-03-20 23:41:37 +0530860 } else
861 mbhc_cfg.gpio = GPIO_HS_DET;
862
863 /*
864 * GPIO for headset detect is present in all devices
865 * MTP/Fluid/CDP/SGLTE
866 */
867 err = gpio_request(mbhc_cfg.gpio, "HEADSET_DETECT");
868 if (err) {
869 pr_err("%s: Failed to request gpio %d\n",
870 __func__, mbhc_cfg.gpio);
871 return err;
Laxminath Kasamc8082aa2013-03-15 21:08:20 +0530872 }
Laxminath Kasam852c7812013-03-07 20:03:37 +0530873
Bhalchandra Gajare466aafe2012-05-02 17:55:26 -0700874 mbhc_cfg.gpio_irq = gpio_to_irq(mbhc_cfg.gpio);
875 sitar_hs_detect(codec, &mbhc_cfg);
876
Bhalchandra Gajareb28275f2012-08-13 12:32:12 -0700877 if (socinfo_get_pmic_model() != PMIC_MODEL_PM8917) {
878 /* Initialize default PMIC speaker gain */
879 pm8xxx_spk_gain(DEFAULT_PMIC_SPK_GAIN);
880 }
Bhalchandra Gajare97676792012-05-22 17:41:45 -0700881
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530882 return 0;
883}
884
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530885static int msm8930_slim_0_rx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
886 struct snd_pcm_hw_params *params)
887{
888 struct snd_interval *rate = hw_param_interval(params,
889 SNDRV_PCM_HW_PARAM_RATE);
890
891 struct snd_interval *channels = hw_param_interval(params,
892 SNDRV_PCM_HW_PARAM_CHANNELS);
893
894 pr_debug("%s()\n", __func__);
895 rate->min = rate->max = 48000;
896 channels->min = channels->max = msm8930_slim_0_rx_ch;
897
898 return 0;
899}
900
901static int msm8930_slim_0_tx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
902 struct snd_pcm_hw_params *params)
903{
904 struct snd_interval *rate = hw_param_interval(params,
905 SNDRV_PCM_HW_PARAM_RATE);
906
907 struct snd_interval *channels = hw_param_interval(params,
908 SNDRV_PCM_HW_PARAM_CHANNELS);
909
910 pr_debug("%s()\n", __func__);
911 rate->min = rate->max = 48000;
912 channels->min = channels->max = msm8930_slim_0_tx_ch;
913
914 return 0;
915}
916
917static int msm8930_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
918 struct snd_pcm_hw_params *params)
919{
920 struct snd_interval *rate = hw_param_interval(params,
921 SNDRV_PCM_HW_PARAM_RATE);
922
923 pr_debug("%s()\n", __func__);
924 rate->min = rate->max = 48000;
925
926 return 0;
927}
928
929static int msm8930_hdmi_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
930 struct snd_pcm_hw_params *params)
931{
932 struct snd_interval *rate = hw_param_interval(params,
933 SNDRV_PCM_HW_PARAM_RATE);
934
935 struct snd_interval *channels = hw_param_interval(params,
936 SNDRV_PCM_HW_PARAM_CHANNELS);
937
Vicky Sehrawat53f5c2e2012-11-05 17:54:13 -0800938 if (!hdmi_rate_variable)
939 rate->min = rate->max = 48000;
Subhash Chandra Bose Naripeddya3a99232013-01-11 14:05:21 -0800940 channels->min = channels->max = msm_hdmi_rx_ch;
941 if (channels->max < 2)
942 channels->min = channels->max = 2;
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530943
944 return 0;
945}
946
947static int msm8930_btsco_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
948 struct snd_pcm_hw_params *params)
949{
950 struct snd_interval *rate = hw_param_interval(params,
951 SNDRV_PCM_HW_PARAM_RATE);
952
953 struct snd_interval *channels = hw_param_interval(params,
954 SNDRV_PCM_HW_PARAM_CHANNELS);
955
956 rate->min = rate->max = msm8930_btsco_rate;
957 channels->min = channels->max = msm8930_btsco_ch;
958
959 return 0;
960}
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530961
Bhalchandra Gajare2e0893e2012-05-24 00:39:47 -0700962static int msm8930_auxpcm_be_params_fixup(struct snd_soc_pcm_runtime *rtd,
963 struct snd_pcm_hw_params *params)
964{
965 struct snd_interval *rate = hw_param_interval(params,
966 SNDRV_PCM_HW_PARAM_RATE);
967
968 struct snd_interval *channels = hw_param_interval(params,
969 SNDRV_PCM_HW_PARAM_CHANNELS);
970
971 /* PCM only supports mono output with 8khz sample rate */
972 rate->min = rate->max = 8000;
973 channels->min = channels->max = 1;
974
975 return 0;
976}
977
Jayasena Sangaraboina6b4de782012-10-23 16:52:01 -0700978static int msm8930_proxy_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
979 struct snd_pcm_hw_params *params)
980{
981 struct snd_interval *rate = hw_param_interval(params,
982 SNDRV_PCM_HW_PARAM_RATE);
983
984 pr_debug("%s()\n", __func__);
985 rate->min = rate->max = 48000;
986
987 return 0;
988}
989
Bhalchandra Gajare2e0893e2012-05-24 00:39:47 -0700990static int msm8930_aux_pcm_get_gpios(void)
991{
992 int ret = 0;
993
994 pr_debug("%s\n", __func__);
995
996 ret = gpio_request(GPIO_AUX_PCM_DOUT, "AUX PCM DOUT");
997 if (ret < 0) {
998 pr_err("%s: Failed to request gpio(%d): AUX PCM DOUT",
999 __func__, GPIO_AUX_PCM_DOUT);
1000
1001 goto fail_dout;
1002 }
1003
1004 ret = gpio_request(GPIO_AUX_PCM_DIN, "AUX PCM DIN");
1005 if (ret < 0) {
1006 pr_err("%s: Failed to request gpio(%d): AUX PCM DIN",
1007 __func__, GPIO_AUX_PCM_DIN);
1008 goto fail_din;
1009 }
1010
1011 ret = gpio_request(GPIO_AUX_PCM_SYNC, "AUX PCM SYNC");
1012 if (ret < 0) {
1013 pr_err("%s: Failed to request gpio(%d): AUX PCM SYNC",
1014 __func__, GPIO_AUX_PCM_SYNC);
1015 goto fail_sync;
1016 }
1017
1018 ret = gpio_request(GPIO_AUX_PCM_CLK, "AUX PCM CLK");
1019 if (ret < 0) {
1020 pr_err("%s: Failed to request gpio(%d): AUX PCM CLK",
1021 __func__, GPIO_AUX_PCM_CLK);
1022 goto fail_clk;
1023 }
1024
1025 return 0;
1026
1027fail_clk:
1028 gpio_free(GPIO_AUX_PCM_SYNC);
1029fail_sync:
1030 gpio_free(GPIO_AUX_PCM_DIN);
1031fail_din:
1032 gpio_free(GPIO_AUX_PCM_DOUT);
1033fail_dout:
1034
1035 return ret;
1036}
1037
1038static int msm8930_aux_pcm_free_gpios(void)
1039{
1040 gpio_free(GPIO_AUX_PCM_DIN);
1041 gpio_free(GPIO_AUX_PCM_DOUT);
1042 gpio_free(GPIO_AUX_PCM_SYNC);
1043 gpio_free(GPIO_AUX_PCM_CLK);
1044
1045 return 0;
1046}
1047
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301048static int msm8930_startup(struct snd_pcm_substream *substream)
1049{
1050 pr_debug("%s(): substream = %s stream = %d\n", __func__,
1051 substream->name, substream->stream);
1052 return 0;
1053}
1054
Bhalchandra Gajare2e0893e2012-05-24 00:39:47 -07001055static int msm8930_auxpcm_startup(struct snd_pcm_substream *substream)
1056{
1057 int ret = 0;
1058
Kuirong Wang892c9ad2012-09-20 11:43:17 -07001059 pr_debug("%s(): substream = %s, auxpcm_rsc_ref counter = %d\n",
1060 __func__, substream->name, atomic_read(&auxpcm_rsc_ref));
1061 if (atomic_inc_return(&auxpcm_rsc_ref) == 1)
1062 ret = msm8930_aux_pcm_get_gpios();
Bhalchandra Gajare2e0893e2012-05-24 00:39:47 -07001063 if (ret < 0) {
1064 pr_err("%s: Aux PCM GPIO request failed\n", __func__);
1065 return -EINVAL;
1066 }
1067 return 0;
1068
1069}
1070
1071static void msm8930_auxpcm_shutdown(struct snd_pcm_substream *substream)
1072{
Kuirong Wang892c9ad2012-09-20 11:43:17 -07001073 pr_debug("%s(): substream = %s, auxpcm_rsc_ref counter = %d\n",
1074 __func__, substream->name, atomic_read(&auxpcm_rsc_ref));
1075 if (atomic_dec_return(&auxpcm_rsc_ref) == 0)
1076 msm8930_aux_pcm_free_gpios();
Bhalchandra Gajare2e0893e2012-05-24 00:39:47 -07001077}
1078
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301079static void msm8930_shutdown(struct snd_pcm_substream *substream)
1080{
1081 pr_debug("%s(): substream = %s stream = %d\n", __func__,
1082 substream->name, substream->stream);
1083}
1084
1085static struct snd_soc_ops msm8930_be_ops = {
1086 .startup = msm8930_startup,
1087 .hw_params = msm8930_hw_params,
1088 .shutdown = msm8930_shutdown,
1089};
1090
Bhalchandra Gajare2e0893e2012-05-24 00:39:47 -07001091static struct snd_soc_ops msm8930_auxpcm_be_ops = {
1092 .startup = msm8930_auxpcm_startup,
1093 .shutdown = msm8930_auxpcm_shutdown,
1094};
1095
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301096/* Digital audio interface glue - connects codec <---> CPU */
1097static struct snd_soc_dai_link msm8930_dai[] = {
1098 /* FrontEnd DAI Links */
1099 {
1100 .name = "MSM8930 Media1",
1101 .stream_name = "MultiMedia1",
1102 .cpu_dai_name = "MultiMedia1",
1103 .platform_name = "msm-pcm-dsp",
1104 .dynamic = 1,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001105 .codec_dai_name = "snd-soc-dummy-dai",
1106 .codec_name = "snd-soc-dummy",
1107 .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
1108 .ignore_suspend = 1,
1109 .ignore_pmdown_time = 1, /* this dainlink has playback support */
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301110 .be_id = MSM_FRONTEND_DAI_MULTIMEDIA1
1111 },
1112 {
1113 .name = "MSM8930 Media2",
1114 .stream_name = "MultiMedia2",
1115 .cpu_dai_name = "MultiMedia2",
Asish Bhattacharyae2601ae2012-07-18 21:13:21 +05301116 .platform_name = "msm-multi-ch-pcm-dsp",
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301117 .dynamic = 1,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001118 .codec_dai_name = "snd-soc-dummy-dai",
1119 .codec_name = "snd-soc-dummy",
1120 .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
1121 .ignore_suspend = 1,
1122 .ignore_pmdown_time = 1, /* this dainlink has playback support */
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301123 .be_id = MSM_FRONTEND_DAI_MULTIMEDIA2,
1124 },
1125 {
1126 .name = "Circuit-Switch Voice",
1127 .stream_name = "CS-Voice",
1128 .cpu_dai_name = "CS-VOICE",
1129 .platform_name = "msm-pcm-voice",
1130 .dynamic = 1,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001131 .codec_dai_name = "snd-soc-dummy-dai",
1132 .codec_name = "snd-soc-dummy",
1133 .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301134 .be_id = MSM_FRONTEND_DAI_CS_VOICE,
1135 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
1136 .ignore_suspend = 1,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001137 .ignore_pmdown_time = 1, /* this dainlink has playback support */
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301138 },
1139 {
1140 .name = "MSM VoIP",
1141 .stream_name = "VoIP",
1142 .cpu_dai_name = "VoIP",
1143 .platform_name = "msm-voip-dsp",
1144 .dynamic = 1,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001145 .codec_dai_name = "snd-soc-dummy-dai",
1146 .codec_name = "snd-soc-dummy",
1147 .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
1148 .ignore_suspend = 1,
1149 .ignore_pmdown_time = 1, /* this dainlink has playback support */
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301150 .be_id = MSM_FRONTEND_DAI_VOIP,
1151 },
1152 {
1153 .name = "MSM8930 LPA",
1154 .stream_name = "LPA",
1155 .cpu_dai_name = "MultiMedia3",
1156 .platform_name = "msm-pcm-lpa",
1157 .dynamic = 1,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001158 .codec_dai_name = "snd-soc-dummy-dai",
1159 .codec_name = "snd-soc-dummy",
1160 .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
1161 .ignore_suspend = 1,
1162 .ignore_pmdown_time = 1, /* this dainlink has playback support */
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301163 .be_id = MSM_FRONTEND_DAI_MULTIMEDIA3,
1164 },
1165 /* Hostless PMC purpose */
1166 {
1167 .name = "SLIMBUS_0 Hostless",
1168 .stream_name = "SLIMBUS_0 Hostless",
1169 .cpu_dai_name = "SLIMBUS0_HOSTLESS",
1170 .platform_name = "msm-pcm-hostless",
1171 .dynamic = 1,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001172 .codec_dai_name = "snd-soc-dummy-dai",
1173 .codec_name = "snd-soc-dummy",
1174 .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301175 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
1176 .ignore_suspend = 1,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001177 .ignore_pmdown_time = 1, /* this dainlink has playback support */
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301178 /* .be_id = do not care */
1179 },
1180 {
1181 .name = "INT_FM Hostless",
1182 .stream_name = "INT_FM Hostless",
1183 .cpu_dai_name = "INT_FM_HOSTLESS",
1184 .platform_name = "msm-pcm-hostless",
1185 .dynamic = 1,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001186 .codec_dai_name = "snd-soc-dummy-dai",
1187 .codec_name = "snd-soc-dummy",
1188 .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301189 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
1190 .ignore_suspend = 1,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001191 .ignore_pmdown_time = 1, /* this dainlink has playback support */
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301192 /* .be_id = do not care */
1193 },
1194 {
1195 .name = "MSM AFE-PCM RX",
1196 .stream_name = "AFE-PROXY RX",
1197 .cpu_dai_name = "msm-dai-q6.241",
1198 .codec_name = "msm-stub-codec.1",
1199 .codec_dai_name = "msm-stub-rx",
1200 .platform_name = "msm-pcm-afe",
1201 .ignore_suspend = 1,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001202 .ignore_pmdown_time = 1, /* this dainlink has playback support */
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301203 },
1204 {
1205 .name = "MSM AFE-PCM TX",
1206 .stream_name = "AFE-PROXY TX",
1207 .cpu_dai_name = "msm-dai-q6.240",
1208 .codec_name = "msm-stub-codec.1",
1209 .codec_dai_name = "msm-stub-tx",
1210 .platform_name = "msm-pcm-afe",
1211 .ignore_suspend = 1,
1212 },
1213 {
1214 .name = "MSM8930 Compr",
1215 .stream_name = "COMPR",
1216 .cpu_dai_name = "MultiMedia4",
1217 .platform_name = "msm-compr-dsp",
1218 .dynamic = 1,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001219 .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
1220 .codec_dai_name = "snd-soc-dummy-dai",
1221 .codec_name = "snd-soc-dummy",
1222 .ignore_suspend = 1,
1223 .ignore_pmdown_time = 1, /* this dainlink has playback support */
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301224 .be_id = MSM_FRONTEND_DAI_MULTIMEDIA4,
1225 },
1226 {
1227 .name = "AUXPCM Hostless",
1228 .stream_name = "AUXPCM Hostless",
1229 .cpu_dai_name = "AUXPCM_HOSTLESS",
1230 .platform_name = "msm-pcm-hostless",
1231 .dynamic = 1,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001232 .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301233 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
1234 .ignore_suspend = 1,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001235 .ignore_pmdown_time = 1, /* this dainlink has playback support */
1236 .codec_dai_name = "snd-soc-dummy-dai",
1237 .codec_name = "snd-soc-dummy",
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301238 },
1239 /* HDMI Hostless */
1240 {
1241 .name = "HDMI_RX_HOSTLESS",
1242 .stream_name = "HDMI_RX_HOSTLESS",
1243 .cpu_dai_name = "HDMI_HOSTLESS",
1244 .platform_name = "msm-pcm-hostless",
1245 .dynamic = 1,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001246 .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301247 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301248 .ignore_suspend = 1,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001249 .ignore_pmdown_time = 1, /* this dainlink has playback support */
1250 .codec_dai_name = "snd-soc-dummy-dai",
1251 .codec_name = "snd-soc-dummy",
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301252 },
Jayasena Sangaraboina99bf09c2012-07-17 12:03:08 -07001253 {
1254 .name = "VoLTE",
1255 .stream_name = "VoLTE",
1256 .cpu_dai_name = "VoLTE",
1257 .platform_name = "msm-pcm-voice",
1258 .dynamic = 1,
1259 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
1260 SND_SOC_DPCM_TRIGGER_POST},
1261 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
1262 .ignore_suspend = 1,
1263 /* this dainlink has playback support */
1264 .ignore_pmdown_time = 1,
1265 .codec_dai_name = "snd-soc-dummy-dai",
1266 .codec_name = "snd-soc-dummy",
1267 .be_id = MSM_FRONTEND_DAI_VOLTE,
1268 },
1269 {
Helen Zeng47ca0072013-03-06 10:37:52 -08001270 .name = "Voice2",
1271 .stream_name = "Voice2",
1272 .cpu_dai_name = "Voice2",
Jayasena Sangaraboina99bf09c2012-07-17 12:03:08 -07001273 .platform_name = "msm-pcm-voice",
1274 .dynamic = 1,
1275 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
1276 SND_SOC_DPCM_TRIGGER_POST},
1277 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
1278 .ignore_suspend = 1,
1279 /* this dainlink has playback support */
1280 .ignore_pmdown_time = 1,
1281 .codec_dai_name = "snd-soc-dummy-dai",
1282 .codec_name = "snd-soc-dummy",
Helen Zeng47ca0072013-03-06 10:37:52 -08001283 .be_id = MSM_FRONTEND_DAI_VOICE2,
Jayasena Sangaraboina99bf09c2012-07-17 12:03:08 -07001284 },
1285 {
1286 .name = "MSM8960 LowLatency",
1287 .stream_name = "MultiMedia5",
1288 .cpu_dai_name = "MultiMedia5",
1289 .platform_name = "msm-lowlatency-pcm-dsp",
1290 .dynamic = 1,
1291 .codec_dai_name = "snd-soc-dummy-dai",
1292 .codec_name = "snd-soc-dummy",
1293 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
1294 SND_SOC_DPCM_TRIGGER_POST},
1295 .ignore_suspend = 1,
1296 /* this dainlink has playback support */
1297 .ignore_pmdown_time = 1,
1298 .be_id = MSM_FRONTEND_DAI_MULTIMEDIA5,
1299 },
Damir Didjusto54807c82013-04-23 13:48:24 -07001300 {
1301 .name = "MSM8960 FM",
1302 .stream_name = "MultiMedia6",
1303 .cpu_dai_name = "MultiMedia6",
1304 .platform_name = "msm-pcm-loopback",
1305 .dynamic = 1,
1306 .codec_dai_name = "snd-soc-dummy-dai",
1307 .codec_name = "snd-soc-dummy",
1308 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
1309 SND_SOC_DPCM_TRIGGER_POST},
1310 .ignore_suspend = 1,
1311 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
1312 /* this dainlink has playback support */
1313 .ignore_pmdown_time = 1,
1314 .be_id = MSM_FRONTEND_DAI_MULTIMEDIA6,
1315 },
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301316 /* Backend DAI Links */
1317 {
1318 .name = LPASS_BE_SLIMBUS_0_RX,
1319 .stream_name = "Slimbus Playback",
1320 .cpu_dai_name = "msm-dai-q6.16384",
1321 .platform_name = "msm-pcm-routing",
1322 .codec_name = "sitar_codec",
1323 .codec_dai_name = "sitar_rx1",
1324 .no_pcm = 1,
1325 .be_id = MSM_BACKEND_DAI_SLIMBUS_0_RX,
1326 .init = &msm8930_audrx_init,
1327 .be_hw_params_fixup = msm8930_slim_0_rx_be_hw_params_fixup,
1328 .ops = &msm8930_be_ops,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001329 .ignore_pmdown_time = 1, /* this dainlink has playback support */
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301330 },
1331 {
1332 .name = LPASS_BE_SLIMBUS_0_TX,
1333 .stream_name = "Slimbus Capture",
1334 .cpu_dai_name = "msm-dai-q6.16385",
1335 .platform_name = "msm-pcm-routing",
1336 .codec_name = "sitar_codec",
1337 .codec_dai_name = "sitar_tx1",
1338 .no_pcm = 1,
1339 .be_id = MSM_BACKEND_DAI_SLIMBUS_0_TX,
1340 .be_hw_params_fixup = msm8930_slim_0_tx_be_hw_params_fixup,
1341 .ops = &msm8930_be_ops,
1342 },
1343 /* Backend BT/FM DAI Links */
1344 {
1345 .name = LPASS_BE_INT_BT_SCO_RX,
1346 .stream_name = "Internal BT-SCO Playback",
1347 .cpu_dai_name = "msm-dai-q6.12288",
1348 .platform_name = "msm-pcm-routing",
1349 .codec_name = "msm-stub-codec.1",
1350 .codec_dai_name = "msm-stub-rx",
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301351 .no_pcm = 1,
1352 .be_id = MSM_BACKEND_DAI_INT_BT_SCO_RX,
1353 .be_hw_params_fixup = msm8930_btsco_be_hw_params_fixup,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001354 .ignore_pmdown_time = 1, /* this dainlink has playback support */
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301355 },
1356 {
1357 .name = LPASS_BE_INT_BT_SCO_TX,
1358 .stream_name = "Internal BT-SCO Capture",
1359 .cpu_dai_name = "msm-dai-q6.12289",
1360 .platform_name = "msm-pcm-routing",
1361 .codec_name = "msm-stub-codec.1",
1362 .codec_dai_name = "msm-stub-tx",
1363 .no_pcm = 1,
1364 .be_id = MSM_BACKEND_DAI_INT_BT_SCO_TX,
1365 .be_hw_params_fixup = msm8930_btsco_be_hw_params_fixup,
1366 },
1367 {
1368 .name = LPASS_BE_INT_FM_RX,
1369 .stream_name = "Internal FM Playback",
1370 .cpu_dai_name = "msm-dai-q6.12292",
1371 .platform_name = "msm-pcm-routing",
1372 .codec_name = "msm-stub-codec.1",
1373 .codec_dai_name = "msm-stub-rx",
1374 .no_pcm = 1,
1375 .be_id = MSM_BACKEND_DAI_INT_FM_RX,
1376 .be_hw_params_fixup = msm8930_be_hw_params_fixup,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001377 .ignore_pmdown_time = 1, /* this dainlink has playback support */
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301378 },
1379 {
1380 .name = LPASS_BE_INT_FM_TX,
1381 .stream_name = "Internal FM Capture",
1382 .cpu_dai_name = "msm-dai-q6.12293",
1383 .platform_name = "msm-pcm-routing",
1384 .codec_name = "msm-stub-codec.1",
1385 .codec_dai_name = "msm-stub-tx",
1386 .no_pcm = 1,
1387 .be_id = MSM_BACKEND_DAI_INT_FM_TX,
1388 .be_hw_params_fixup = msm8930_be_hw_params_fixup,
1389 },
1390 /* HDMI BACK END DAI Link */
1391 {
1392 .name = LPASS_BE_HDMI,
1393 .stream_name = "HDMI Playback",
1394 .cpu_dai_name = "msm-dai-q6-hdmi.8",
1395 .platform_name = "msm-pcm-routing",
1396 .codec_name = "msm-stub-codec.1",
1397 .codec_dai_name = "msm-stub-rx",
1398 .no_pcm = 1,
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301399 .be_id = MSM_BACKEND_DAI_HDMI_RX,
1400 .be_hw_params_fixup = msm8930_hdmi_be_hw_params_fixup,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001401 .ignore_pmdown_time = 1, /* this dainlink has playback support */
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301402 },
1403 /* Backend AFE DAI Links */
1404 {
1405 .name = LPASS_BE_AFE_PCM_RX,
1406 .stream_name = "AFE Playback",
1407 .cpu_dai_name = "msm-dai-q6.224",
1408 .platform_name = "msm-pcm-routing",
1409 .codec_name = "msm-stub-codec.1",
1410 .codec_dai_name = "msm-stub-rx",
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301411 .no_pcm = 1,
1412 .be_id = MSM_BACKEND_DAI_AFE_PCM_RX,
Jayasena Sangaraboina6b4de782012-10-23 16:52:01 -07001413 .be_hw_params_fixup = msm8930_proxy_be_hw_params_fixup,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001414 .ignore_pmdown_time = 1, /* this dainlink has playback support */
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301415 },
1416 {
1417 .name = LPASS_BE_AFE_PCM_TX,
1418 .stream_name = "AFE Capture",
1419 .cpu_dai_name = "msm-dai-q6.225",
1420 .platform_name = "msm-pcm-routing",
1421 .codec_name = "msm-stub-codec.1",
1422 .codec_dai_name = "msm-stub-tx",
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301423 .no_pcm = 1,
1424 .be_id = MSM_BACKEND_DAI_AFE_PCM_TX,
Jayasena Sangaraboina6b4de782012-10-23 16:52:01 -07001425 .be_hw_params_fixup = msm8930_proxy_be_hw_params_fixup,
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301426 },
Bhalchandra Gajare2e0893e2012-05-24 00:39:47 -07001427 /* AUX PCM Backend DAI Links */
1428 {
1429 .name = LPASS_BE_AUXPCM_RX,
1430 .stream_name = "AUX PCM Playback",
1431 .cpu_dai_name = "msm-dai-q6.2",
1432 .platform_name = "msm-pcm-routing",
1433 .codec_name = "msm-stub-codec.1",
1434 .codec_dai_name = "msm-stub-rx",
1435 .no_pcm = 1,
1436 .be_id = MSM_BACKEND_DAI_AUXPCM_RX,
1437 .be_hw_params_fixup = msm8930_auxpcm_be_params_fixup,
1438 .ops = &msm8930_auxpcm_be_ops,
1439 },
1440 {
1441 .name = LPASS_BE_AUXPCM_TX,
1442 .stream_name = "AUX PCM Capture",
1443 .cpu_dai_name = "msm-dai-q6.3",
1444 .platform_name = "msm-pcm-routing",
1445 .codec_name = "msm-stub-codec.1",
1446 .codec_dai_name = "msm-stub-tx",
1447 .no_pcm = 1,
1448 .be_id = MSM_BACKEND_DAI_AUXPCM_TX,
1449 .be_hw_params_fixup = msm8930_auxpcm_be_params_fixup,
Kuirong Wang892c9ad2012-09-20 11:43:17 -07001450 .ops = &msm8930_auxpcm_be_ops,
Bhalchandra Gajare2e0893e2012-05-24 00:39:47 -07001451 },
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301452 /* Incall Music BACK END DAI Link */
1453 {
1454 .name = LPASS_BE_VOICE_PLAYBACK_TX,
1455 .stream_name = "Voice Farend Playback",
1456 .cpu_dai_name = "msm-dai-q6.32773",
1457 .platform_name = "msm-pcm-routing",
1458 .codec_name = "msm-stub-codec.1",
1459 .codec_dai_name = "msm-stub-rx",
1460 .no_pcm = 1,
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301461 .be_id = MSM_BACKEND_DAI_VOICE_PLAYBACK_TX,
1462 .be_hw_params_fixup = msm8930_be_hw_params_fixup,
1463 },
1464 /* Incall Record Uplink BACK END DAI Link */
1465 {
1466 .name = LPASS_BE_INCALL_RECORD_TX,
1467 .stream_name = "Voice Uplink Capture",
1468 .cpu_dai_name = "msm-dai-q6.32772",
1469 .platform_name = "msm-pcm-routing",
1470 .codec_name = "msm-stub-codec.1",
1471 .codec_dai_name = "msm-stub-tx",
1472 .no_pcm = 1,
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301473 .be_id = MSM_BACKEND_DAI_INCALL_RECORD_TX,
1474 .be_hw_params_fixup = msm8930_be_hw_params_fixup,
1475 },
1476 /* Incall Record Downlink BACK END DAI Link */
1477 {
1478 .name = LPASS_BE_INCALL_RECORD_RX,
1479 .stream_name = "Voice Downlink Capture",
1480 .cpu_dai_name = "msm-dai-q6.32771",
1481 .platform_name = "msm-pcm-routing",
1482 .codec_name = "msm-stub-codec.1",
1483 .codec_dai_name = "msm-stub-tx",
1484 .no_pcm = 1,
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301485 .be_id = MSM_BACKEND_DAI_INCALL_RECORD_RX,
1486 .be_hw_params_fixup = msm8930_be_hw_params_fixup,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001487 .ignore_pmdown_time = 1, /* this dainlink has playback support */
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301488 },
1489};
1490
1491struct snd_soc_card snd_soc_card_msm8930 = {
1492 .name = "msm8930-sitar-snd-card",
1493 .dai_link = msm8930_dai,
1494 .num_links = ARRAY_SIZE(msm8930_dai),
Steve Mucklef132c6c2012-06-06 18:30:57 -07001495 .controls = sitar_msm8930_controls,
1496 .num_controls = ARRAY_SIZE(sitar_msm8930_controls),
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301497};
1498
1499static struct platform_device *msm8930_snd_device;
1500
1501static int msm8930_configure_headset_mic_gpios(void)
1502{
1503 int ret;
Laxminath Kasam852c7812013-03-07 20:03:37 +05301504
Laxminath Kasam82433012013-03-20 23:41:37 +05301505 if (!us_euro_gpio)
1506 return 0;
1507
1508 ret = gpio_request(us_euro_gpio, "US_EURO_SWITCH");
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301509 if (ret) {
Laxminath Kasam82433012013-03-20 23:41:37 +05301510 pr_err("%s: Failed to request gpio %d\n", __func__,
1511 us_euro_gpio);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301512 return ret;
1513 }
Laxminath Kasam82433012013-03-20 23:41:37 +05301514 ret = gpio_direction_output(us_euro_gpio, 0);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301515 if (ret) {
1516 pr_err("%s: Unable to set direction\n", __func__);
Laxminath Kasam82433012013-03-20 23:41:37 +05301517 gpio_free(us_euro_gpio);
1518 return ret;
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301519 }
Laxminath Kasam82433012013-03-20 23:41:37 +05301520 msm8930_useuro_gpio_requested = 1;
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301521 return 0;
1522}
1523static void msm8930_free_headset_mic_gpios(void)
1524{
Laxminath Kasam82433012013-03-20 23:41:37 +05301525 if (msm8930_useuro_gpio_requested) {
1526 gpio_free(us_euro_gpio);
1527 msm8930_useuro_gpio_requested = 0;
1528 }
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301529}
1530
1531static int __init msm8930_audio_init(void)
1532{
1533 int ret;
1534
Stepan Moskovchenkoc6a603a2012-09-21 20:32:17 -07001535 if (!soc_class_is_msm8930()) {
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301536 pr_err("%s: Not the right machine type\n", __func__);
1537 return -ENODEV ;
1538 }
Bhalchandra Gajare466aafe2012-05-02 17:55:26 -07001539 mbhc_cfg.calibration = def_sitar_mbhc_cal();
1540 if (!mbhc_cfg.calibration) {
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -08001541 pr_err("Calibration data allocation failed\n");
1542 return -ENOMEM;
1543 }
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301544
1545 msm8930_snd_device = platform_device_alloc("soc-audio", 0);
1546 if (!msm8930_snd_device) {
1547 pr_err("Platform device allocation failed\n");
Bhalchandra Gajare466aafe2012-05-02 17:55:26 -07001548 kfree(mbhc_cfg.calibration);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301549 return -ENOMEM;
1550 }
1551
1552 platform_set_drvdata(msm8930_snd_device, &snd_soc_card_msm8930);
1553 ret = platform_device_add(msm8930_snd_device);
1554 if (ret) {
1555 platform_device_put(msm8930_snd_device);
Bhalchandra Gajare466aafe2012-05-02 17:55:26 -07001556 kfree(mbhc_cfg.calibration);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301557 return ret;
1558 }
1559
Laxminath Kasam82433012013-03-20 23:41:37 +05301560 if (socinfo_get_platform_subtype() == PLATFORM_SUBTYPE_SGLTE)
1561 us_euro_gpio = GPIO_HS_US_EURO_SEL_GPIO_SGLTE;
1562 else
1563 us_euro_gpio = GPIO_HS_US_EURO_SEL_GPIO;
1564
1565 if (msm8930_configure_headset_mic_gpios())
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301566 pr_err("%s Fail to configure headset mic gpios\n", __func__);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301567
Kuirong Wang892c9ad2012-09-20 11:43:17 -07001568 atomic_set(&auxpcm_rsc_ref, 0);
Laxminath Kasam3a8d49e2013-03-29 12:34:41 +05301569 mutex_init(&cdc_mclk_mutex);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301570 return ret;
1571
1572}
1573module_init(msm8930_audio_init);
1574
1575static void __exit msm8930_audio_exit(void)
1576{
Stepan Moskovchenkoc6a603a2012-09-21 20:32:17 -07001577 if (!soc_class_is_msm8930()) {
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301578 pr_err("%s: Not the right machine type\n", __func__);
1579 return ;
1580 }
1581 msm8930_free_headset_mic_gpios();
1582 platform_device_unregister(msm8930_snd_device);
Bhalchandra Gajare466aafe2012-05-02 17:55:26 -07001583 kfree(mbhc_cfg.calibration);
Laxminath Kasam3a8d49e2013-03-29 12:34:41 +05301584 mutex_destroy(&cdc_mclk_mutex);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301585}
1586module_exit(msm8930_audio_exit);
1587
1588MODULE_DESCRIPTION("ALSA SoC MSM8930");
1589MODULE_LICENSE("GPL v2");