blob: 798f2c790a3d0c892070c4e9eea457c1261d919d [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;
Asish Bhattacharyab86c3472012-02-15 08:31:52 +053080
81static struct snd_soc_jack hs_jack;
82static struct snd_soc_jack button_jack;
Kuirong Wang892c9ad2012-09-20 11:43:17 -070083static atomic_t auxpcm_rsc_ref;
Bhalchandra Gajare466aafe2012-05-02 17:55:26 -070084
85static int msm8930_enable_codec_ext_clk(
86 struct snd_soc_codec *codec, int enable,
87 bool dapm);
Laxminath Kasam82433012013-03-20 23:41:37 +053088static bool msm8930_swap_gnd_mic(struct snd_soc_codec *codec);
Bhalchandra Gajare466aafe2012-05-02 17:55:26 -070089
Laxminath Kasam852c7812013-03-07 20:03:37 +053090static u32 spkr_boost_enable_gpio = PM8038_GPIO_PM_TO_SYS(0x1);
91
92struct pm_gpio SPKR_ON = {
93 .direction = PM_GPIO_DIR_OUT,
94 .output_buffer = PM_GPIO_OUT_BUF_CMOS,
95 .output_value = 1,
96 .pull = PM_GPIO_PULL_NO,
97 .vin_sel = PM_GPIO_VIN_S4,
98 .out_strength = PM_GPIO_STRENGTH_MED,
99 .function = PM_GPIO_FUNC_NORMAL,
100};
101struct pm_gpio SPKR_OFF = {
102 .direction = PM_GPIO_DIR_OUT,
103 .output_buffer = PM_GPIO_OUT_BUF_CMOS,
104 .output_value = 0,
105 .pull = PM_GPIO_PULL_NO,
106 .vin_sel = PM_GPIO_VIN_S4,
107 .out_strength = PM_GPIO_STRENGTH_MED,
108 .function = PM_GPIO_FUNC_NORMAL,
109};
110
Bhalchandra Gajare466aafe2012-05-02 17:55:26 -0700111static struct sitar_mbhc_config mbhc_cfg = {
112 .headset_jack = &hs_jack,
113 .button_jack = &button_jack,
114 .read_fw_bin = false,
115 .calibration = NULL,
116 .micbias = SITAR_MICBIAS2,
117 .mclk_cb_fn = msm8930_enable_codec_ext_clk,
118 .mclk_rate = SITAR_EXT_CLK_RATE,
119 .gpio = 0,
120 .gpio_irq = 0,
121 .gpio_level_insert = 1,
Laxminath Kasam82433012013-03-20 23:41:37 +0530122 .swap_gnd_mic = NULL,
Bhalchandra Gajare466aafe2012-05-02 17:55:26 -0700123};
124
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530125static void msm8930_ext_control(struct snd_soc_codec *codec)
126{
127 struct snd_soc_dapm_context *dapm = &codec->dapm;
128
129 pr_debug("%s: msm8930_spk_control = %d", __func__, msm8930_spk_control);
130 if (msm8930_spk_control == MSM8930_SPK_ON) {
131 snd_soc_dapm_enable_pin(dapm, "Ext Spk Left Pos");
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800132 snd_soc_dapm_enable_pin(dapm, "Ext Spk left Neg");
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530133 } else {
134 snd_soc_dapm_disable_pin(dapm, "Ext Spk Left Pos");
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800135 snd_soc_dapm_disable_pin(dapm, "Ext Spk Left Neg");
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530136 }
137
138 snd_soc_dapm_sync(dapm);
139}
140
141static int msm8930_get_spk(struct snd_kcontrol *kcontrol,
142 struct snd_ctl_elem_value *ucontrol)
143{
144 pr_debug("%s: msm8930_spk_control = %d", __func__, msm8930_spk_control);
145 ucontrol->value.integer.value[0] = msm8930_spk_control;
146 return 0;
147}
148static int msm8930_set_spk(struct snd_kcontrol *kcontrol,
149 struct snd_ctl_elem_value *ucontrol)
150{
151 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
152
153 pr_debug("%s()\n", __func__);
154 if (msm8930_spk_control == ucontrol->value.integer.value[0])
155 return 0;
156
157 msm8930_spk_control = ucontrol->value.integer.value[0];
158 msm8930_ext_control(codec);
159 return 1;
160}
161
Bhalchandra Gajareb28275f2012-08-13 12:32:12 -0700162static int msm8930_cfg_spkr_gpio(int gpio,
163 int enable, const char *gpio_label)
164{
165 int ret = 0;
166
167 pr_debug("%s: Configure %s GPIO %u",
168 __func__, gpio_label, gpio);
169 ret = gpio_request(gpio, gpio_label);
170 if (ret)
171 return ret;
172
173 pr_debug("%s: Enable %s gpio %u\n",
174 __func__, gpio_label, gpio);
175 gpio_direction_output(gpio, enable);
176
177 return ret;
178}
179
Asish Bhattacharyac71827a2012-03-05 10:11:45 -0800180static void msm8960_ext_spk_power_amp_on(u32 spk)
181{
Bhalchandra Gajare98a28cd2012-05-16 12:00:20 -0700182 int ret = 0;
183
Asish Bhattacharyac71827a2012-03-05 10:11:45 -0800184 if (spk & (SPK_AMP_POS | SPK_AMP_NEG)) {
185 if ((msm8930_ext_spk_pamp & SPK_AMP_POS) &&
186 (msm8930_ext_spk_pamp & SPK_AMP_NEG)) {
187
188 pr_debug("%s() External Bottom Speaker Ampl already "
189 "turned on. spk = 0x%08x\n", __func__, spk);
190 return;
191 }
192
193 msm8930_ext_spk_pamp |= spk;
194
195 if ((msm8930_ext_spk_pamp & SPK_AMP_POS) &&
196 (msm8930_ext_spk_pamp & SPK_AMP_NEG)) {
197
Bhalchandra Gajareb28275f2012-08-13 12:32:12 -0700198 if (socinfo_get_pmic_model() == PMIC_MODEL_PM8917) {
199 ret = msm8930_cfg_spkr_gpio(
200 LEFT_SPKR_AMPL_GPIO,
201 1, "LEFT_SPKR_AMPL");
Bhalchandra Gajare98a28cd2012-05-16 12:00:20 -0700202 if (ret) {
Bhalchandra Gajareb28275f2012-08-13 12:32:12 -0700203 pr_err("%s: Failed to config ampl gpio %u\n",
204 __func__, LEFT_SPKR_AMPL_GPIO);
Bhalchandra Gajare98a28cd2012-05-16 12:00:20 -0700205 return;
206 }
Bhalchandra Gajareb28275f2012-08-13 12:32:12 -0700207 } else {
Bhalchandra Gajare98a28cd2012-05-16 12:00:20 -0700208
Bhalchandra Gajareb28275f2012-08-13 12:32:12 -0700209 if (machine_is_msm8930_mtp()
210 || machine_is_msm8930_fluid()) {
211 ret = msm8930_cfg_spkr_gpio(
212 SPKR_BOOST_GPIO, 1, "SPKR_BOOST");
213 if (ret) {
214 pr_err("%s: Failure: spkr boost gpio %u\n",
215 __func__, SPKR_BOOST_GPIO);
216 return;
217 }
Laxminath Kasam852c7812013-03-07 20:03:37 +0530218 } else if (socinfo_get_platform_subtype() ==
219 PLATFORM_SUBTYPE_SGLTE) {
220 ret = pm8xxx_gpio_config(
221 spkr_boost_enable_gpio,
222 &SPKR_ON);
223 if (ret) {
224 pr_err("%s: Failure: spkr" \
225 "boost gpio ON %u\n",
226 __func__, spkr_boost_enable_gpio);
227 return;
228 } else {
229 pr_debug("%s:Config PMIC8038" \
230 "gpio for speaker ON successfully\n",
231 __func__);
232 }
Bhalchandra Gajareb28275f2012-08-13 12:32:12 -0700233 }
234 pm8xxx_spk_enable(MSM8930_SPK_ON);
Bhalchandra Gajare98a28cd2012-05-16 12:00:20 -0700235 }
236
Asish Bhattacharyac71827a2012-03-05 10:11:45 -0800237 pr_debug("%s: slepping 4 ms after turning on external "
238 " Left Speaker Ampl\n", __func__);
239 usleep_range(4000, 4000);
240 }
241
242 } else {
243
244 pr_err("%s: ERROR : Invalid External Speaker Ampl. spk = 0x%08x\n",
245 __func__, spk);
246 return;
247 }
248}
249
250static void msm8960_ext_spk_power_amp_off(u32 spk)
251{
Laxminath Kasam852c7812013-03-07 20:03:37 +0530252 int ret = 0;
Asish Bhattacharyac71827a2012-03-05 10:11:45 -0800253 if (spk & (SPK_AMP_POS | SPK_AMP_NEG)) {
254 if (!msm8930_ext_spk_pamp)
255 return;
Bhalchandra Gajareb28275f2012-08-13 12:32:12 -0700256
257 if (socinfo_get_pmic_model() == PMIC_MODEL_PM8917) {
258 gpio_free(LEFT_SPKR_AMPL_GPIO);
259 msm8930_ext_spk_pamp = 0;
260 return;
261 }
262
Bhalchandra Gajare98a28cd2012-05-16 12:00:20 -0700263 if (machine_is_msm8930_mtp()
264 || machine_is_msm8930_fluid()) {
265 pr_debug("%s: Free speaker boost gpio %u\n",
266 __func__, SPKR_BOOST_GPIO);
267 gpio_direction_output(SPKR_BOOST_GPIO, 0);
268 gpio_free(SPKR_BOOST_GPIO);
Laxminath Kasam852c7812013-03-07 20:03:37 +0530269 } else if (socinfo_get_platform_subtype() ==
270 PLATFORM_SUBTYPE_SGLTE) {
271 ret = pm8xxx_gpio_config(spkr_boost_enable_gpio,
272 &SPKR_OFF);
273 if (ret) {
274 pr_err("%s: Failure: spkr boost gpio OFF %u\n",
275 __func__, spkr_boost_enable_gpio);
276 return;
277 } else {
278 pr_debug("%s:Config PMIC8038 gpio for speaker" \
279 " OFF successfully\n", __func__);
280 }
Bhalchandra Gajare98a28cd2012-05-16 12:00:20 -0700281 }
Asish Bhattacharyac71827a2012-03-05 10:11:45 -0800282
283 pm8xxx_spk_enable(MSM8930_SPK_OFF);
284 msm8930_ext_spk_pamp = 0;
285 pr_debug("%s: slepping 4 ms after turning on external "
286 " Left Speaker Ampl\n", __func__);
287 usleep_range(4000, 4000);
288
289 } else {
290
291 pr_err("%s: ERROR : Invalid External Speaker Ampl. spk = 0x%08x\n",
292 __func__, spk);
293 return;
294 }
295}
296
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530297static int msm8930_spkramp_event(struct snd_soc_dapm_widget *w,
298 struct snd_kcontrol *k, int event)
299{
300 pr_debug("%s() %x\n", __func__, SND_SOC_DAPM_EVENT_ON(event));
Asish Bhattacharyac71827a2012-03-05 10:11:45 -0800301 if (SND_SOC_DAPM_EVENT_ON(event)) {
302 if (!strncmp(w->name, "Ext Spk Left Pos", 17))
303 msm8960_ext_spk_power_amp_on(SPK_AMP_POS);
304 else if (!strncmp(w->name, "Ext Spk Left Neg", 17))
305 msm8960_ext_spk_power_amp_on(SPK_AMP_NEG);
306 else {
307 pr_err("%s() Invalid Speaker Widget = %s\n",
308 __func__, w->name);
309 return -EINVAL;
310 }
311 } else {
312 if (!strncmp(w->name, "Ext Spk Left Pos", 17))
313 msm8960_ext_spk_power_amp_off(SPK_AMP_POS);
314 else if (!strncmp(w->name, "Ext Spk Left Neg", 17))
315 msm8960_ext_spk_power_amp_off(SPK_AMP_NEG);
316 else {
317 pr_err("%s() Invalid Speaker Widget = %s\n",
318 __func__, w->name);
319 return -EINVAL;
320 }
321 }
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530322 return 0;
323}
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800324
Bhalchandra Gajare466aafe2012-05-02 17:55:26 -0700325static int msm8930_enable_codec_ext_clk(
326 struct snd_soc_codec *codec, int enable,
327 bool dapm)
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530328{
329 pr_debug("%s: enable = %d\n", __func__, enable);
330 if (enable) {
331 clk_users++;
332 pr_debug("%s: clk_users = %d\n", __func__, clk_users);
333 if (clk_users != 1)
334 return 0;
335
336 if (codec_clk) {
337 clk_set_rate(codec_clk, SITAR_EXT_CLK_RATE);
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800338 clk_prepare_enable(codec_clk);
Bhalchandra Gajare466aafe2012-05-02 17:55:26 -0700339 sitar_mclk_enable(codec, 1, dapm);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530340 } else {
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800341 pr_err("%s: Error setting Sitar MCLK\n", __func__);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530342 clk_users--;
343 return -EINVAL;
344 }
345 } else {
346 pr_debug("%s: clk_users = %d\n", __func__, clk_users);
347 if (clk_users == 0)
348 return 0;
349 clk_users--;
350 if (!clk_users) {
351 pr_debug("%s: disabling MCLK. clk_users = %d\n",
352 __func__, clk_users);
Bhalchandra Gajare466aafe2012-05-02 17:55:26 -0700353 sitar_mclk_enable(codec, 0, dapm);
Bhalchandra Gajare2776af12012-04-27 16:59:39 -0700354 clk_disable_unprepare(codec_clk);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530355 }
356 }
357 return 0;
358}
359
Laxminath Kasam82433012013-03-20 23:41:37 +0530360static bool msm8930_swap_gnd_mic(struct snd_soc_codec *codec)
361{
362 int value = 0;
363
364 value = gpio_get_value_cansleep(us_euro_gpio);
365 pr_debug("%s: US EURO select switch %d to %d\n", __func__, value,
366 !value);
367 gpio_set_value_cansleep(us_euro_gpio, !value);
368 return true;
369}
370
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530371static int msm8930_mclk_event(struct snd_soc_dapm_widget *w,
372 struct snd_kcontrol *kcontrol, int event)
373{
374 pr_debug("%s: event = %d\n", __func__, event);
375
376 switch (event) {
377 case SND_SOC_DAPM_PRE_PMU:
Bhalchandra Gajare466aafe2012-05-02 17:55:26 -0700378 return msm8930_enable_codec_ext_clk(w->codec, 1, true);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530379 case SND_SOC_DAPM_POST_PMD:
Bhalchandra Gajare466aafe2012-05-02 17:55:26 -0700380 return msm8930_enable_codec_ext_clk(w->codec, 0, true);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530381 }
382 return 0;
383}
384
385static const struct snd_soc_dapm_widget msm8930_dapm_widgets[] = {
386
387 SND_SOC_DAPM_SUPPLY("MCLK", SND_SOC_NOPM, 0, 0,
388 msm8930_mclk_event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
389
390 SND_SOC_DAPM_SPK("Ext Spk Left Pos", msm8930_spkramp_event),
Asish Bhattacharyac71827a2012-03-05 10:11:45 -0800391 SND_SOC_DAPM_SPK("Ext Spk Left Neg", msm8930_spkramp_event),
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530392
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530393 SND_SOC_DAPM_MIC("Headset Mic", NULL),
394 SND_SOC_DAPM_MIC("Digital Mic1", NULL),
395 SND_SOC_DAPM_MIC("ANCRight Headset Mic", NULL),
396 SND_SOC_DAPM_MIC("ANCLeft Headset Mic", NULL),
397
398 SND_SOC_DAPM_MIC("Digital Mic1", NULL),
399 SND_SOC_DAPM_MIC("Digital Mic2", NULL),
400 SND_SOC_DAPM_MIC("Digital Mic3", NULL),
401 SND_SOC_DAPM_MIC("Digital Mic4", NULL),
402
403};
404
405static const struct snd_soc_dapm_route common_audio_map[] = {
406
407 {"RX_BIAS", NULL, "MCLK"},
408 {"LDO_H", NULL, "MCLK"},
409
410 {"MIC BIAS1 Internal1", NULL, "MCLK"},
411 {"MIC BIAS2 Internal1", NULL, "MCLK"},
412
413 /* Speaker path */
414 {"Ext Spk Left Pos", NULL, "LINEOUT1"},
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800415 {"Ext Spk Left Neg", NULL, "LINEOUT2"},
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530416
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800417 /* Headset Mic */
Bhalchandra Gajare553fb9e2012-06-26 14:48:54 -0700418 {"AMIC2", NULL, "MIC BIAS2 External"},
419 {"MIC BIAS2 External", NULL, "Headset Mic"},
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530420
421 /* Microphone path */
Bhalchandra Gajare18314d52012-06-06 19:03:01 -0700422 {"AMIC1", NULL, "MIC BIAS2 External"},
423 {"MIC BIAS2 External", NULL, "ANCLeft Headset Mic"},
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800424
Bhalchandra Gajare18314d52012-06-06 19:03:01 -0700425 {"AMIC3", NULL, "MIC BIAS2 External"},
426 {"MIC BIAS2 External", NULL, "ANCRight Headset Mic"},
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530427
428 {"HEADPHONE", NULL, "LDO_H"},
429
430 /**
431 * The digital Mic routes are setup considering
432 * fluid as default device.
433 */
434
435 /**
Bhalchandra Gajaree6a30f72012-05-23 19:46:21 -0700436 * Digital Mic1. Front Bottom left Mic on Fluid and MTP.
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530437 * Digital Mic GM5 on CDP mainboard.
Bhalchandra Gajaree6a30f72012-05-23 19:46:21 -0700438 * Conncted to DMIC1 Input on Sitar codec.
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530439 */
440 {"DMIC1", NULL, "MIC BIAS1 External"},
441 {"MIC BIAS1 External", NULL, "Digital Mic1"},
442
443 /**
Bhalchandra Gajaree6a30f72012-05-23 19:46:21 -0700444 * Digital Mic2. Back top MIC on Fluid.
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530445 * Digital Mic GM6 on CDP mainboard.
Bhalchandra Gajaree6a30f72012-05-23 19:46:21 -0700446 * Conncted to DMIC2 Input on Sitar codec.
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530447 */
448 {"DMIC2", NULL, "MIC BIAS1 External"},
449 {"MIC BIAS1 External", NULL, "Digital Mic2"},
450 /**
451 * Digital Mic3. Back Bottom Digital Mic on Fluid.
452 * Digital Mic GM1 on CDP mainboard.
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800453 * Conncted to DMIC4 Input on Sitar codec.
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530454 */
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800455 {"DMIC3", NULL, "MIC BIAS1 External"},
456 {"MIC BIAS1 External", NULL, "Digital Mic3"},
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530457
458 /**
459 * Digital Mic4. Back top Digital Mic on Fluid.
460 * Digital Mic GM2 on CDP mainboard.
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800461 * Conncted to DMIC3 Input on Sitar codec.
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530462 */
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800463 {"DMIC4", NULL, "MIC BIAS1 External"},
464 {"MIC BIAS1 External", NULL, "Digital Mic4"},
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530465
466
467};
468
Laxminath Kasam852c7812013-03-07 20:03:37 +0530469static const struct snd_soc_dapm_route common_audio_map_sglte[] = {
470
471 {"RX_BIAS", NULL, "MCLK"},
472 {"LDO_H", NULL, "MCLK"},
473
474 {"MIC BIAS1 Internal1", NULL, "MCLK"},
475 {"MIC BIAS2 Internal1", NULL, "MCLK"},
476
477 /* Speaker path */
478 {"Ext Spk Left Pos", NULL, "LINEOUT1"},
479 {"Ext Spk Left Neg", NULL, "LINEOUT2"},
480
481 /* Headset Mic */
482 {"AMIC2", NULL, "MIC BIAS2 External"},
483 {"MIC BIAS2 External", NULL, "Headset Mic"},
484
485 /* Microphone path */
486 {"AMIC1", NULL, "MIC BIAS1 External"},
487 {"MIC BIAS1 External", NULL, "ANCLeft Headset Mic"},
488
489 {"AMIC3", NULL, "MIC BIAS1 External"},
490 {"MIC BIAS1 External", NULL, "ANCRight Headset Mic"},
491
492 {"HEADPHONE", NULL, "LDO_H"},
493};
494
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530495static const char *spk_function[] = {"Off", "On"};
496static const char *slim0_rx_ch_text[] = {"One", "Two"};
497static const char *slim0_tx_ch_text[] = {"One", "Two", "Three", "Four"};
Subhash Chandra Bose Naripeddya3a99232013-01-11 14:05:21 -0800498static char const *hdmi_rx_ch_text[] = {"Two", "Three", "Four", "Five",
499 "Six", "Seven", "Eight"};
Vicky Sehrawat53f5c2e2012-11-05 17:54:13 -0800500static const char * const hdmi_rate[] = {"Default", "Variable"};
501
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530502static const struct soc_enum msm8930_enum[] = {
503 SOC_ENUM_SINGLE_EXT(2, spk_function),
504 SOC_ENUM_SINGLE_EXT(2, slim0_rx_ch_text),
505 SOC_ENUM_SINGLE_EXT(4, slim0_tx_ch_text),
Vicky Sehrawat53f5c2e2012-11-05 17:54:13 -0800506 SOC_ENUM_SINGLE_EXT(2, hdmi_rate),
Subhash Chandra Bose Naripeddya3a99232013-01-11 14:05:21 -0800507 SOC_ENUM_SINGLE_EXT(7, hdmi_rx_ch_text),
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530508};
509
510static const char *btsco_rate_text[] = {"8000", "16000"};
511static const struct soc_enum msm8930_btsco_enum[] = {
512 SOC_ENUM_SINGLE_EXT(2, btsco_rate_text),
513};
514
515static int msm8930_slim_0_rx_ch_get(struct snd_kcontrol *kcontrol,
516 struct snd_ctl_elem_value *ucontrol)
517{
518 pr_debug("%s: msm8930_slim_0_rx_ch = %d\n", __func__,
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800519 msm8930_slim_0_rx_ch);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530520 ucontrol->value.integer.value[0] = msm8930_slim_0_rx_ch - 1;
521 return 0;
522}
523
524static int msm8930_slim_0_rx_ch_put(struct snd_kcontrol *kcontrol,
525 struct snd_ctl_elem_value *ucontrol)
526{
527 msm8930_slim_0_rx_ch = ucontrol->value.integer.value[0] + 1;
528
529 pr_debug("%s: msm8930_slim_0_rx_ch = %d\n", __func__,
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800530 msm8930_slim_0_rx_ch);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530531 return 1;
532}
533
534static int msm8930_slim_0_tx_ch_get(struct snd_kcontrol *kcontrol,
535 struct snd_ctl_elem_value *ucontrol)
536{
537 pr_debug("%s: msm8930_slim_0_tx_ch = %d\n", __func__,
538 msm8930_slim_0_tx_ch);
539 ucontrol->value.integer.value[0] = msm8930_slim_0_tx_ch - 1;
540 return 0;
541}
542
543static int msm8930_slim_0_tx_ch_put(struct snd_kcontrol *kcontrol,
544 struct snd_ctl_elem_value *ucontrol)
545{
546 msm8930_slim_0_tx_ch = ucontrol->value.integer.value[0] + 1;
547
548 pr_debug("%s: msm8930_slim_0_tx_ch = %d\n", __func__,
549 msm8930_slim_0_tx_ch);
550 return 1;
551}
552
553static int msm8930_btsco_rate_get(struct snd_kcontrol *kcontrol,
554 struct snd_ctl_elem_value *ucontrol)
555{
556 pr_debug("%s: msm8930_btsco_rate = %d", __func__, msm8930_btsco_rate);
557 ucontrol->value.integer.value[0] = msm8930_btsco_rate;
558 return 0;
559}
560
561static int msm8930_btsco_rate_put(struct snd_kcontrol *kcontrol,
562 struct snd_ctl_elem_value *ucontrol)
563{
Kuirong Wangfd8e0b32012-05-30 19:45:04 -0700564
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530565 switch (ucontrol->value.integer.value[0]) {
Kuirong Wangfd8e0b32012-05-30 19:45:04 -0700566 case 8000:
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530567 msm8930_btsco_rate = BTSCO_RATE_8KHZ;
568 break;
Kuirong Wangfd8e0b32012-05-30 19:45:04 -0700569 case 16000:
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530570 msm8930_btsco_rate = BTSCO_RATE_16KHZ;
571 break;
572 default:
573 msm8930_btsco_rate = BTSCO_RATE_8KHZ;
574 break;
575 }
576 pr_debug("%s: msm8930_btsco_rate = %d\n", __func__, msm8930_btsco_rate);
577 return 0;
578}
579
Bhalchandra Gajare97676792012-05-22 17:41:45 -0700580static const char *pmic_spk_gain_text[] = {
581 "NEG_6_DB", "NEG_4_DB", "NEG_2_DB", "ZERO_DB", "POS_2_DB", "POS_4_DB",
582 "POS_6_DB", "POS_8_DB", "POS_10_DB", "POS_12_DB", "POS_14_DB",
583 "POS_16_DB", "POS_18_DB", "POS_20_DB", "POS_22_DB", "POS_24_DB"
584};
585
586static const struct soc_enum msm8960_pmic_spk_gain_enum[] = {
587 SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(pmic_spk_gain_text),
588 pmic_spk_gain_text),
589};
590
591static int msm8930_pmic_gain_get(struct snd_kcontrol *kcontrol,
592 struct snd_ctl_elem_value *ucontrol)
593{
594 pr_debug("%s: msm8930_pmic_spk_gain = %d\n", __func__,
595 msm8930_pmic_spk_gain);
596 ucontrol->value.integer.value[0] = msm8930_pmic_spk_gain;
597 return 0;
598}
599
600static int msm8930_pmic_gain_put(struct snd_kcontrol *kcontrol,
601 struct snd_ctl_elem_value *ucontrol)
602{
603 int ret = 0;
604 msm8930_pmic_spk_gain = ucontrol->value.integer.value[0];
Bhalchandra Gajareb28275f2012-08-13 12:32:12 -0700605 if (socinfo_get_pmic_model() != PMIC_MODEL_PM8917)
606 ret = pm8xxx_spk_gain(msm8930_pmic_spk_gain);
Bhalchandra Gajare97676792012-05-22 17:41:45 -0700607 pr_debug("%s: msm8930_pmic_spk_gain = %d"
608 " ucontrol->value.integer.value[0] = %d\n", __func__,
609 msm8930_pmic_spk_gain,
610 (int) ucontrol->value.integer.value[0]);
611 return ret;
612}
613
Subhash Chandra Bose Naripeddya3a99232013-01-11 14:05:21 -0800614static int msm_hdmi_rx_ch_get(struct snd_kcontrol *kcontrol,
615 struct snd_ctl_elem_value *ucontrol)
616{
617 pr_debug("%s: msm_hdmi_rx_ch = %d\n", __func__,
618 msm_hdmi_rx_ch);
619 ucontrol->value.integer.value[0] = msm_hdmi_rx_ch - 2;
620 return 0;
621}
622
623static int msm_hdmi_rx_ch_put(struct snd_kcontrol *kcontrol,
624 struct snd_ctl_elem_value *ucontrol)
625{
626 msm_hdmi_rx_ch = ucontrol->value.integer.value[0] + 2;
627
628 pr_debug("%s: msm_hdmi_rx_ch = %d\n", __func__,
629 msm_hdmi_rx_ch);
630 return 1;
631}
632
Vicky Sehrawat53f5c2e2012-11-05 17:54:13 -0800633static int msm8930_hdmi_rate_put(struct snd_kcontrol *kcontrol,
634 struct snd_ctl_elem_value *ucontrol)
635{
636 hdmi_rate_variable = ucontrol->value.integer.value[0];
637 pr_debug("%s: hdmi_rate_variable = %d\n", __func__, hdmi_rate_variable);
638 return 0;
639}
640
641static int msm8930_hdmi_rate_get(struct snd_kcontrol *kcontrol,
642 struct snd_ctl_elem_value *ucontrol)
643{
644 ucontrol->value.integer.value[0] = hdmi_rate_variable;
645 return 0;
646}
647
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530648static const struct snd_kcontrol_new sitar_msm8930_controls[] = {
649 SOC_ENUM_EXT("Speaker Function", msm8930_enum[0], msm8930_get_spk,
650 msm8930_set_spk),
651 SOC_ENUM_EXT("SLIM_0_RX Channels", msm8930_enum[1],
652 msm8930_slim_0_rx_ch_get, msm8930_slim_0_rx_ch_put),
653 SOC_ENUM_EXT("SLIM_0_TX Channels", msm8930_enum[2],
654 msm8930_slim_0_tx_ch_get, msm8930_slim_0_tx_ch_put),
Bhalchandra Gajare97676792012-05-22 17:41:45 -0700655 SOC_ENUM_EXT("PMIC SPK Gain", msm8960_pmic_spk_gain_enum[0],
656 msm8930_pmic_gain_get, msm8930_pmic_gain_put),
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530657 SOC_ENUM_EXT("Internal BTSCO SampleRate", msm8930_btsco_enum[0],
658 msm8930_btsco_rate_get, msm8930_btsco_rate_put),
Vicky Sehrawat53f5c2e2012-11-05 17:54:13 -0800659 SOC_ENUM_EXT("HDMI RX Rate", msm8930_enum[3],
660 msm8930_hdmi_rate_get,
661 msm8930_hdmi_rate_put),
Subhash Chandra Bose Naripeddya3a99232013-01-11 14:05:21 -0800662 SOC_ENUM_EXT("HDMI_RX Channels", msm8930_enum[4],
663 msm_hdmi_rx_ch_get, msm_hdmi_rx_ch_put),
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530664};
665
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800666static void *def_sitar_mbhc_cal(void)
667{
668 void *sitar_cal;
669 struct sitar_mbhc_btn_detect_cfg *btn_cfg;
670 u16 *btn_low, *btn_high;
671 u8 *n_ready, *n_cic, *gain;
672
673 sitar_cal = kzalloc(SITAR_MBHC_CAL_SIZE(SITAR_MBHC_DEF_BUTTONS,
674 SITAR_MBHC_DEF_RLOADS),
675 GFP_KERNEL);
676 if (!sitar_cal) {
677 pr_err("%s: out of memory\n", __func__);
678 return NULL;
679 }
680
681#define S(X, Y) ((SITAR_MBHC_CAL_GENERAL_PTR(sitar_cal)->X) = (Y))
682 S(t_ldoh, 100);
683 S(t_bg_fast_settle, 100);
684 S(t_shutdown_plug_rem, 255);
685 S(mbhc_nsa, 4);
686 S(mbhc_navg, 4);
687#undef S
688#define S(X, Y) ((SITAR_MBHC_CAL_PLUG_DET_PTR(sitar_cal)->X) = (Y))
689 S(mic_current, SITAR_PID_MIC_5_UA);
690 S(hph_current, SITAR_PID_MIC_5_UA);
691 S(t_mic_pid, 100);
692 S(t_ins_complete, 250);
693 S(t_ins_retry, 200);
694#undef S
695#define S(X, Y) ((SITAR_MBHC_CAL_PLUG_TYPE_PTR(sitar_cal)->X) = (Y))
696 S(v_no_mic, 30);
Bhalchandra Gajare18314d52012-06-06 19:03:01 -0700697 S(v_hs_max, 1650);
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800698#undef S
699#define S(X, Y) ((SITAR_MBHC_CAL_BTN_DET_PTR(sitar_cal)->X) = (Y))
700 S(c[0], 62);
701 S(c[1], 124);
702 S(nc, 1);
703 S(n_meas, 3);
704 S(mbhc_nsc, 11);
705 S(n_btn_meas, 1);
706 S(n_btn_con, 2);
707 S(num_btn, SITAR_MBHC_DEF_BUTTONS);
708 S(v_btn_press_delta_sta, 100);
709 S(v_btn_press_delta_cic, 50);
710#undef S
711 btn_cfg = SITAR_MBHC_CAL_BTN_DET_PTR(sitar_cal);
712 btn_low = sitar_mbhc_cal_btn_det_mp(btn_cfg, SITAR_BTN_DET_V_BTN_LOW);
713 btn_high = sitar_mbhc_cal_btn_det_mp(btn_cfg, SITAR_BTN_DET_V_BTN_HIGH);
714 btn_low[0] = -50;
715 btn_high[0] = 10;
716 btn_low[1] = 11;
717 btn_high[1] = 38;
718 btn_low[2] = 39;
719 btn_high[2] = 64;
720 btn_low[3] = 65;
721 btn_high[3] = 91;
722 btn_low[4] = 92;
723 btn_high[4] = 115;
724 btn_low[5] = 116;
725 btn_high[5] = 141;
726 btn_low[6] = 142;
727 btn_high[6] = 163;
728 btn_low[7] = 164;
729 btn_high[7] = 250;
730 n_ready = sitar_mbhc_cal_btn_det_mp(btn_cfg, SITAR_BTN_DET_N_READY);
731 n_ready[0] = 48;
732 n_ready[1] = 38;
733 n_cic = sitar_mbhc_cal_btn_det_mp(btn_cfg, SITAR_BTN_DET_N_CIC);
734 n_cic[0] = 60;
735 n_cic[1] = 47;
736 gain = sitar_mbhc_cal_btn_det_mp(btn_cfg, SITAR_BTN_DET_GAIN);
737 gain[0] = 11;
738 gain[1] = 9;
739
740 return sitar_cal;
741}
742
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530743static int msm8930_hw_params(struct snd_pcm_substream *substream,
744 struct snd_pcm_hw_params *params)
745{
746 struct snd_soc_pcm_runtime *rtd = substream->private_data;
747 struct snd_soc_dai *codec_dai = rtd->codec_dai;
748 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
749 int ret = 0;
750 unsigned int rx_ch[SLIM_MAX_RX_PORTS], tx_ch[SLIM_MAX_TX_PORTS];
751 unsigned int rx_ch_cnt = 0, tx_ch_cnt = 0;
752
753 pr_debug("%s: ch=%d\n", __func__,
754 msm8930_slim_0_rx_ch);
755 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
756 ret = snd_soc_dai_get_channel_map(codec_dai,
757 &tx_ch_cnt, tx_ch, &rx_ch_cnt , rx_ch);
758 if (ret < 0) {
759 pr_err("%s: failed to get codec chan map\n", __func__);
760 goto end;
761 }
762
763 ret = snd_soc_dai_set_channel_map(cpu_dai, 0, 0,
764 msm8930_slim_0_rx_ch, rx_ch);
765 if (ret < 0) {
766 pr_err("%s: failed to set cpu chan map\n", __func__);
767 goto end;
768 }
769 ret = snd_soc_dai_set_channel_map(codec_dai, 0, 0,
770 msm8930_slim_0_rx_ch, rx_ch);
771 if (ret < 0) {
772 pr_err("%s: failed to set codec channel map\n",
773 __func__);
774 goto end;
775 }
776 } else {
777 ret = snd_soc_dai_get_channel_map(codec_dai,
778 &tx_ch_cnt, tx_ch, &rx_ch_cnt , rx_ch);
779 if (ret < 0) {
780 pr_err("%s: failed to get codec chan map\n", __func__);
781 goto end;
782 }
783 ret = snd_soc_dai_set_channel_map(cpu_dai,
784 msm8930_slim_0_tx_ch, tx_ch, 0 , 0);
785 if (ret < 0) {
786 pr_err("%s: failed to set cpu chan map\n", __func__);
787 goto end;
788 }
789 ret = snd_soc_dai_set_channel_map(codec_dai,
790 msm8930_slim_0_tx_ch, tx_ch, 0, 0);
791 if (ret < 0) {
792 pr_err("%s: failed to set codec channel map\n",
793 __func__);
794 goto end;
795 }
796
797 }
798end:
799 return ret;
800}
801
802static int msm8930_audrx_init(struct snd_soc_pcm_runtime *rtd)
803{
804 int err;
805 struct snd_soc_codec *codec = rtd->codec;
806 struct snd_soc_dapm_context *dapm = &codec->dapm;
807 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
808
809 pr_debug("%s()\n", __func__);
810
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530811 snd_soc_dapm_new_controls(dapm, msm8930_dapm_widgets,
812 ARRAY_SIZE(msm8930_dapm_widgets));
813
Laxminath Kasam852c7812013-03-07 20:03:37 +0530814 if (socinfo_get_platform_subtype() == PLATFORM_SUBTYPE_SGLTE)
815 snd_soc_dapm_add_routes(dapm, common_audio_map_sglte,
816 ARRAY_SIZE(common_audio_map_sglte));
817 else
818 snd_soc_dapm_add_routes(dapm, common_audio_map,
819 ARRAY_SIZE(common_audio_map));
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530820
821 snd_soc_dapm_enable_pin(dapm, "Ext Spk Left Pos");
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800822 snd_soc_dapm_enable_pin(dapm, "Ext Spk Left Neg");
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530823
824 snd_soc_dapm_sync(dapm);
825
826 err = snd_soc_jack_new(codec, "Headset Jack",
Laxminath Kasam82433012013-03-20 23:41:37 +0530827 MSM8930_JACK_TYPES,
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530828 &hs_jack);
829 if (err) {
830 pr_err("failed to create new jack\n");
831 return err;
832 }
833
834 err = snd_soc_jack_new(codec, "Button Jack",
Bhalchandra Gajare7708ee32012-05-24 17:37:37 -0700835 SITAR_JACK_BUTTON_MASK, &button_jack);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530836 if (err) {
837 pr_err("failed to create new jack\n");
838 return err;
839 }
840 codec_clk = clk_get(cpu_dai->dev, "osr_clk");
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800841
Laxminath Kasam82433012013-03-20 23:41:37 +0530842 /*
843 * Switch is present only in 8930 CDP and SGLTE
844 */
845 if (socinfo_get_platform_subtype() == PLATFORM_SUBTYPE_SGLTE ||
846 machine_is_msm8930_cdp())
847 mbhc_cfg.swap_gnd_mic = msm8930_swap_gnd_mic;
848
Laxminath Kasamc8082aa2013-03-15 21:08:20 +0530849 if (socinfo_get_platform_subtype() == PLATFORM_SUBTYPE_SGLTE) {
Laxminath Kasam82433012013-03-20 23:41:37 +0530850 mbhc_cfg.gpio = GPIO_HS_DET_SGLTE;
Laxminath Kasamc8082aa2013-03-15 21:08:20 +0530851 mbhc_cfg.gpio_level_insert = 0;
Laxminath Kasam82433012013-03-20 23:41:37 +0530852 } else
853 mbhc_cfg.gpio = GPIO_HS_DET;
854
855 /*
856 * GPIO for headset detect is present in all devices
857 * MTP/Fluid/CDP/SGLTE
858 */
859 err = gpio_request(mbhc_cfg.gpio, "HEADSET_DETECT");
860 if (err) {
861 pr_err("%s: Failed to request gpio %d\n",
862 __func__, mbhc_cfg.gpio);
863 return err;
Laxminath Kasamc8082aa2013-03-15 21:08:20 +0530864 }
Laxminath Kasam852c7812013-03-07 20:03:37 +0530865
Bhalchandra Gajare466aafe2012-05-02 17:55:26 -0700866 mbhc_cfg.gpio_irq = gpio_to_irq(mbhc_cfg.gpio);
867 sitar_hs_detect(codec, &mbhc_cfg);
868
Bhalchandra Gajareb28275f2012-08-13 12:32:12 -0700869 if (socinfo_get_pmic_model() != PMIC_MODEL_PM8917) {
870 /* Initialize default PMIC speaker gain */
871 pm8xxx_spk_gain(DEFAULT_PMIC_SPK_GAIN);
872 }
Bhalchandra Gajare97676792012-05-22 17:41:45 -0700873
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530874 return 0;
875}
876
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530877static int msm8930_slim_0_rx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
878 struct snd_pcm_hw_params *params)
879{
880 struct snd_interval *rate = hw_param_interval(params,
881 SNDRV_PCM_HW_PARAM_RATE);
882
883 struct snd_interval *channels = hw_param_interval(params,
884 SNDRV_PCM_HW_PARAM_CHANNELS);
885
886 pr_debug("%s()\n", __func__);
887 rate->min = rate->max = 48000;
888 channels->min = channels->max = msm8930_slim_0_rx_ch;
889
890 return 0;
891}
892
893static int msm8930_slim_0_tx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
894 struct snd_pcm_hw_params *params)
895{
896 struct snd_interval *rate = hw_param_interval(params,
897 SNDRV_PCM_HW_PARAM_RATE);
898
899 struct snd_interval *channels = hw_param_interval(params,
900 SNDRV_PCM_HW_PARAM_CHANNELS);
901
902 pr_debug("%s()\n", __func__);
903 rate->min = rate->max = 48000;
904 channels->min = channels->max = msm8930_slim_0_tx_ch;
905
906 return 0;
907}
908
909static int msm8930_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
910 struct snd_pcm_hw_params *params)
911{
912 struct snd_interval *rate = hw_param_interval(params,
913 SNDRV_PCM_HW_PARAM_RATE);
914
915 pr_debug("%s()\n", __func__);
916 rate->min = rate->max = 48000;
917
918 return 0;
919}
920
921static int msm8930_hdmi_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
922 struct snd_pcm_hw_params *params)
923{
924 struct snd_interval *rate = hw_param_interval(params,
925 SNDRV_PCM_HW_PARAM_RATE);
926
927 struct snd_interval *channels = hw_param_interval(params,
928 SNDRV_PCM_HW_PARAM_CHANNELS);
929
Vicky Sehrawat53f5c2e2012-11-05 17:54:13 -0800930 if (!hdmi_rate_variable)
931 rate->min = rate->max = 48000;
Subhash Chandra Bose Naripeddya3a99232013-01-11 14:05:21 -0800932 channels->min = channels->max = msm_hdmi_rx_ch;
933 if (channels->max < 2)
934 channels->min = channels->max = 2;
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530935
936 return 0;
937}
938
939static int msm8930_btsco_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
940 struct snd_pcm_hw_params *params)
941{
942 struct snd_interval *rate = hw_param_interval(params,
943 SNDRV_PCM_HW_PARAM_RATE);
944
945 struct snd_interval *channels = hw_param_interval(params,
946 SNDRV_PCM_HW_PARAM_CHANNELS);
947
948 rate->min = rate->max = msm8930_btsco_rate;
949 channels->min = channels->max = msm8930_btsco_ch;
950
951 return 0;
952}
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530953
Bhalchandra Gajare2e0893e2012-05-24 00:39:47 -0700954static int msm8930_auxpcm_be_params_fixup(struct snd_soc_pcm_runtime *rtd,
955 struct snd_pcm_hw_params *params)
956{
957 struct snd_interval *rate = hw_param_interval(params,
958 SNDRV_PCM_HW_PARAM_RATE);
959
960 struct snd_interval *channels = hw_param_interval(params,
961 SNDRV_PCM_HW_PARAM_CHANNELS);
962
963 /* PCM only supports mono output with 8khz sample rate */
964 rate->min = rate->max = 8000;
965 channels->min = channels->max = 1;
966
967 return 0;
968}
969
Jayasena Sangaraboina6b4de782012-10-23 16:52:01 -0700970static int msm8930_proxy_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
971 struct snd_pcm_hw_params *params)
972{
973 struct snd_interval *rate = hw_param_interval(params,
974 SNDRV_PCM_HW_PARAM_RATE);
975
976 pr_debug("%s()\n", __func__);
977 rate->min = rate->max = 48000;
978
979 return 0;
980}
981
Bhalchandra Gajare2e0893e2012-05-24 00:39:47 -0700982static int msm8930_aux_pcm_get_gpios(void)
983{
984 int ret = 0;
985
986 pr_debug("%s\n", __func__);
987
988 ret = gpio_request(GPIO_AUX_PCM_DOUT, "AUX PCM DOUT");
989 if (ret < 0) {
990 pr_err("%s: Failed to request gpio(%d): AUX PCM DOUT",
991 __func__, GPIO_AUX_PCM_DOUT);
992
993 goto fail_dout;
994 }
995
996 ret = gpio_request(GPIO_AUX_PCM_DIN, "AUX PCM DIN");
997 if (ret < 0) {
998 pr_err("%s: Failed to request gpio(%d): AUX PCM DIN",
999 __func__, GPIO_AUX_PCM_DIN);
1000 goto fail_din;
1001 }
1002
1003 ret = gpio_request(GPIO_AUX_PCM_SYNC, "AUX PCM SYNC");
1004 if (ret < 0) {
1005 pr_err("%s: Failed to request gpio(%d): AUX PCM SYNC",
1006 __func__, GPIO_AUX_PCM_SYNC);
1007 goto fail_sync;
1008 }
1009
1010 ret = gpio_request(GPIO_AUX_PCM_CLK, "AUX PCM CLK");
1011 if (ret < 0) {
1012 pr_err("%s: Failed to request gpio(%d): AUX PCM CLK",
1013 __func__, GPIO_AUX_PCM_CLK);
1014 goto fail_clk;
1015 }
1016
1017 return 0;
1018
1019fail_clk:
1020 gpio_free(GPIO_AUX_PCM_SYNC);
1021fail_sync:
1022 gpio_free(GPIO_AUX_PCM_DIN);
1023fail_din:
1024 gpio_free(GPIO_AUX_PCM_DOUT);
1025fail_dout:
1026
1027 return ret;
1028}
1029
1030static int msm8930_aux_pcm_free_gpios(void)
1031{
1032 gpio_free(GPIO_AUX_PCM_DIN);
1033 gpio_free(GPIO_AUX_PCM_DOUT);
1034 gpio_free(GPIO_AUX_PCM_SYNC);
1035 gpio_free(GPIO_AUX_PCM_CLK);
1036
1037 return 0;
1038}
1039
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301040static int msm8930_startup(struct snd_pcm_substream *substream)
1041{
1042 pr_debug("%s(): substream = %s stream = %d\n", __func__,
1043 substream->name, substream->stream);
1044 return 0;
1045}
1046
Bhalchandra Gajare2e0893e2012-05-24 00:39:47 -07001047static int msm8930_auxpcm_startup(struct snd_pcm_substream *substream)
1048{
1049 int ret = 0;
1050
Kuirong Wang892c9ad2012-09-20 11:43:17 -07001051 pr_debug("%s(): substream = %s, auxpcm_rsc_ref counter = %d\n",
1052 __func__, substream->name, atomic_read(&auxpcm_rsc_ref));
1053 if (atomic_inc_return(&auxpcm_rsc_ref) == 1)
1054 ret = msm8930_aux_pcm_get_gpios();
Bhalchandra Gajare2e0893e2012-05-24 00:39:47 -07001055 if (ret < 0) {
1056 pr_err("%s: Aux PCM GPIO request failed\n", __func__);
1057 return -EINVAL;
1058 }
1059 return 0;
1060
1061}
1062
1063static void msm8930_auxpcm_shutdown(struct snd_pcm_substream *substream)
1064{
Kuirong Wang892c9ad2012-09-20 11:43:17 -07001065 pr_debug("%s(): substream = %s, auxpcm_rsc_ref counter = %d\n",
1066 __func__, substream->name, atomic_read(&auxpcm_rsc_ref));
1067 if (atomic_dec_return(&auxpcm_rsc_ref) == 0)
1068 msm8930_aux_pcm_free_gpios();
Bhalchandra Gajare2e0893e2012-05-24 00:39:47 -07001069}
1070
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301071static void msm8930_shutdown(struct snd_pcm_substream *substream)
1072{
1073 pr_debug("%s(): substream = %s stream = %d\n", __func__,
1074 substream->name, substream->stream);
1075}
1076
1077static struct snd_soc_ops msm8930_be_ops = {
1078 .startup = msm8930_startup,
1079 .hw_params = msm8930_hw_params,
1080 .shutdown = msm8930_shutdown,
1081};
1082
Bhalchandra Gajare2e0893e2012-05-24 00:39:47 -07001083static struct snd_soc_ops msm8930_auxpcm_be_ops = {
1084 .startup = msm8930_auxpcm_startup,
1085 .shutdown = msm8930_auxpcm_shutdown,
1086};
1087
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301088/* Digital audio interface glue - connects codec <---> CPU */
1089static struct snd_soc_dai_link msm8930_dai[] = {
1090 /* FrontEnd DAI Links */
1091 {
1092 .name = "MSM8930 Media1",
1093 .stream_name = "MultiMedia1",
1094 .cpu_dai_name = "MultiMedia1",
1095 .platform_name = "msm-pcm-dsp",
1096 .dynamic = 1,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001097 .codec_dai_name = "snd-soc-dummy-dai",
1098 .codec_name = "snd-soc-dummy",
1099 .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
1100 .ignore_suspend = 1,
1101 .ignore_pmdown_time = 1, /* this dainlink has playback support */
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301102 .be_id = MSM_FRONTEND_DAI_MULTIMEDIA1
1103 },
1104 {
1105 .name = "MSM8930 Media2",
1106 .stream_name = "MultiMedia2",
1107 .cpu_dai_name = "MultiMedia2",
Asish Bhattacharyae2601ae2012-07-18 21:13:21 +05301108 .platform_name = "msm-multi-ch-pcm-dsp",
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301109 .dynamic = 1,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001110 .codec_dai_name = "snd-soc-dummy-dai",
1111 .codec_name = "snd-soc-dummy",
1112 .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
1113 .ignore_suspend = 1,
1114 .ignore_pmdown_time = 1, /* this dainlink has playback support */
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301115 .be_id = MSM_FRONTEND_DAI_MULTIMEDIA2,
1116 },
1117 {
1118 .name = "Circuit-Switch Voice",
1119 .stream_name = "CS-Voice",
1120 .cpu_dai_name = "CS-VOICE",
1121 .platform_name = "msm-pcm-voice",
1122 .dynamic = 1,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001123 .codec_dai_name = "snd-soc-dummy-dai",
1124 .codec_name = "snd-soc-dummy",
1125 .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301126 .be_id = MSM_FRONTEND_DAI_CS_VOICE,
1127 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
1128 .ignore_suspend = 1,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001129 .ignore_pmdown_time = 1, /* this dainlink has playback support */
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301130 },
1131 {
1132 .name = "MSM VoIP",
1133 .stream_name = "VoIP",
1134 .cpu_dai_name = "VoIP",
1135 .platform_name = "msm-voip-dsp",
1136 .dynamic = 1,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001137 .codec_dai_name = "snd-soc-dummy-dai",
1138 .codec_name = "snd-soc-dummy",
1139 .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
1140 .ignore_suspend = 1,
1141 .ignore_pmdown_time = 1, /* this dainlink has playback support */
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301142 .be_id = MSM_FRONTEND_DAI_VOIP,
1143 },
1144 {
1145 .name = "MSM8930 LPA",
1146 .stream_name = "LPA",
1147 .cpu_dai_name = "MultiMedia3",
1148 .platform_name = "msm-pcm-lpa",
1149 .dynamic = 1,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001150 .codec_dai_name = "snd-soc-dummy-dai",
1151 .codec_name = "snd-soc-dummy",
1152 .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
1153 .ignore_suspend = 1,
1154 .ignore_pmdown_time = 1, /* this dainlink has playback support */
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301155 .be_id = MSM_FRONTEND_DAI_MULTIMEDIA3,
1156 },
1157 /* Hostless PMC purpose */
1158 {
1159 .name = "SLIMBUS_0 Hostless",
1160 .stream_name = "SLIMBUS_0 Hostless",
1161 .cpu_dai_name = "SLIMBUS0_HOSTLESS",
1162 .platform_name = "msm-pcm-hostless",
1163 .dynamic = 1,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001164 .codec_dai_name = "snd-soc-dummy-dai",
1165 .codec_name = "snd-soc-dummy",
1166 .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301167 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
1168 .ignore_suspend = 1,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001169 .ignore_pmdown_time = 1, /* this dainlink has playback support */
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301170 /* .be_id = do not care */
1171 },
1172 {
1173 .name = "INT_FM Hostless",
1174 .stream_name = "INT_FM Hostless",
1175 .cpu_dai_name = "INT_FM_HOSTLESS",
1176 .platform_name = "msm-pcm-hostless",
1177 .dynamic = 1,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001178 .codec_dai_name = "snd-soc-dummy-dai",
1179 .codec_name = "snd-soc-dummy",
1180 .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301181 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
1182 .ignore_suspend = 1,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001183 .ignore_pmdown_time = 1, /* this dainlink has playback support */
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301184 /* .be_id = do not care */
1185 },
1186 {
1187 .name = "MSM AFE-PCM RX",
1188 .stream_name = "AFE-PROXY RX",
1189 .cpu_dai_name = "msm-dai-q6.241",
1190 .codec_name = "msm-stub-codec.1",
1191 .codec_dai_name = "msm-stub-rx",
1192 .platform_name = "msm-pcm-afe",
1193 .ignore_suspend = 1,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001194 .ignore_pmdown_time = 1, /* this dainlink has playback support */
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301195 },
1196 {
1197 .name = "MSM AFE-PCM TX",
1198 .stream_name = "AFE-PROXY TX",
1199 .cpu_dai_name = "msm-dai-q6.240",
1200 .codec_name = "msm-stub-codec.1",
1201 .codec_dai_name = "msm-stub-tx",
1202 .platform_name = "msm-pcm-afe",
1203 .ignore_suspend = 1,
1204 },
1205 {
1206 .name = "MSM8930 Compr",
1207 .stream_name = "COMPR",
1208 .cpu_dai_name = "MultiMedia4",
1209 .platform_name = "msm-compr-dsp",
1210 .dynamic = 1,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001211 .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
1212 .codec_dai_name = "snd-soc-dummy-dai",
1213 .codec_name = "snd-soc-dummy",
1214 .ignore_suspend = 1,
1215 .ignore_pmdown_time = 1, /* this dainlink has playback support */
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301216 .be_id = MSM_FRONTEND_DAI_MULTIMEDIA4,
1217 },
1218 {
1219 .name = "AUXPCM Hostless",
1220 .stream_name = "AUXPCM Hostless",
1221 .cpu_dai_name = "AUXPCM_HOSTLESS",
1222 .platform_name = "msm-pcm-hostless",
1223 .dynamic = 1,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001224 .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301225 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
1226 .ignore_suspend = 1,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001227 .ignore_pmdown_time = 1, /* this dainlink has playback support */
1228 .codec_dai_name = "snd-soc-dummy-dai",
1229 .codec_name = "snd-soc-dummy",
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301230 },
1231 /* HDMI Hostless */
1232 {
1233 .name = "HDMI_RX_HOSTLESS",
1234 .stream_name = "HDMI_RX_HOSTLESS",
1235 .cpu_dai_name = "HDMI_HOSTLESS",
1236 .platform_name = "msm-pcm-hostless",
1237 .dynamic = 1,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001238 .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301239 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301240 .ignore_suspend = 1,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001241 .ignore_pmdown_time = 1, /* this dainlink has playback support */
1242 .codec_dai_name = "snd-soc-dummy-dai",
1243 .codec_name = "snd-soc-dummy",
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301244 },
Jayasena Sangaraboina99bf09c2012-07-17 12:03:08 -07001245 {
1246 .name = "VoLTE",
1247 .stream_name = "VoLTE",
1248 .cpu_dai_name = "VoLTE",
1249 .platform_name = "msm-pcm-voice",
1250 .dynamic = 1,
1251 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
1252 SND_SOC_DPCM_TRIGGER_POST},
1253 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
1254 .ignore_suspend = 1,
1255 /* this dainlink has playback support */
1256 .ignore_pmdown_time = 1,
1257 .codec_dai_name = "snd-soc-dummy-dai",
1258 .codec_name = "snd-soc-dummy",
1259 .be_id = MSM_FRONTEND_DAI_VOLTE,
1260 },
1261 {
Helen Zeng47ca0072013-03-06 10:37:52 -08001262 .name = "Voice2",
1263 .stream_name = "Voice2",
1264 .cpu_dai_name = "Voice2",
Jayasena Sangaraboina99bf09c2012-07-17 12:03:08 -07001265 .platform_name = "msm-pcm-voice",
1266 .dynamic = 1,
1267 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
1268 SND_SOC_DPCM_TRIGGER_POST},
1269 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
1270 .ignore_suspend = 1,
1271 /* this dainlink has playback support */
1272 .ignore_pmdown_time = 1,
1273 .codec_dai_name = "snd-soc-dummy-dai",
1274 .codec_name = "snd-soc-dummy",
Helen Zeng47ca0072013-03-06 10:37:52 -08001275 .be_id = MSM_FRONTEND_DAI_VOICE2,
Jayasena Sangaraboina99bf09c2012-07-17 12:03:08 -07001276 },
1277 {
1278 .name = "MSM8960 LowLatency",
1279 .stream_name = "MultiMedia5",
1280 .cpu_dai_name = "MultiMedia5",
1281 .platform_name = "msm-lowlatency-pcm-dsp",
1282 .dynamic = 1,
1283 .codec_dai_name = "snd-soc-dummy-dai",
1284 .codec_name = "snd-soc-dummy",
1285 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
1286 SND_SOC_DPCM_TRIGGER_POST},
1287 .ignore_suspend = 1,
1288 /* this dainlink has playback support */
1289 .ignore_pmdown_time = 1,
1290 .be_id = MSM_FRONTEND_DAI_MULTIMEDIA5,
1291 },
Damir Didjusto54807c82013-04-23 13:48:24 -07001292 {
1293 .name = "MSM8960 FM",
1294 .stream_name = "MultiMedia6",
1295 .cpu_dai_name = "MultiMedia6",
1296 .platform_name = "msm-pcm-loopback",
1297 .dynamic = 1,
1298 .codec_dai_name = "snd-soc-dummy-dai",
1299 .codec_name = "snd-soc-dummy",
1300 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
1301 SND_SOC_DPCM_TRIGGER_POST},
1302 .ignore_suspend = 1,
1303 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
1304 /* this dainlink has playback support */
1305 .ignore_pmdown_time = 1,
1306 .be_id = MSM_FRONTEND_DAI_MULTIMEDIA6,
1307 },
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301308 /* Backend DAI Links */
1309 {
1310 .name = LPASS_BE_SLIMBUS_0_RX,
1311 .stream_name = "Slimbus Playback",
1312 .cpu_dai_name = "msm-dai-q6.16384",
1313 .platform_name = "msm-pcm-routing",
1314 .codec_name = "sitar_codec",
1315 .codec_dai_name = "sitar_rx1",
1316 .no_pcm = 1,
1317 .be_id = MSM_BACKEND_DAI_SLIMBUS_0_RX,
1318 .init = &msm8930_audrx_init,
1319 .be_hw_params_fixup = msm8930_slim_0_rx_be_hw_params_fixup,
1320 .ops = &msm8930_be_ops,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001321 .ignore_pmdown_time = 1, /* this dainlink has playback support */
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301322 },
1323 {
1324 .name = LPASS_BE_SLIMBUS_0_TX,
1325 .stream_name = "Slimbus Capture",
1326 .cpu_dai_name = "msm-dai-q6.16385",
1327 .platform_name = "msm-pcm-routing",
1328 .codec_name = "sitar_codec",
1329 .codec_dai_name = "sitar_tx1",
1330 .no_pcm = 1,
1331 .be_id = MSM_BACKEND_DAI_SLIMBUS_0_TX,
1332 .be_hw_params_fixup = msm8930_slim_0_tx_be_hw_params_fixup,
1333 .ops = &msm8930_be_ops,
1334 },
1335 /* Backend BT/FM DAI Links */
1336 {
1337 .name = LPASS_BE_INT_BT_SCO_RX,
1338 .stream_name = "Internal BT-SCO Playback",
1339 .cpu_dai_name = "msm-dai-q6.12288",
1340 .platform_name = "msm-pcm-routing",
1341 .codec_name = "msm-stub-codec.1",
1342 .codec_dai_name = "msm-stub-rx",
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301343 .no_pcm = 1,
1344 .be_id = MSM_BACKEND_DAI_INT_BT_SCO_RX,
1345 .be_hw_params_fixup = msm8930_btsco_be_hw_params_fixup,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001346 .ignore_pmdown_time = 1, /* this dainlink has playback support */
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301347 },
1348 {
1349 .name = LPASS_BE_INT_BT_SCO_TX,
1350 .stream_name = "Internal BT-SCO Capture",
1351 .cpu_dai_name = "msm-dai-q6.12289",
1352 .platform_name = "msm-pcm-routing",
1353 .codec_name = "msm-stub-codec.1",
1354 .codec_dai_name = "msm-stub-tx",
1355 .no_pcm = 1,
1356 .be_id = MSM_BACKEND_DAI_INT_BT_SCO_TX,
1357 .be_hw_params_fixup = msm8930_btsco_be_hw_params_fixup,
1358 },
1359 {
1360 .name = LPASS_BE_INT_FM_RX,
1361 .stream_name = "Internal FM Playback",
1362 .cpu_dai_name = "msm-dai-q6.12292",
1363 .platform_name = "msm-pcm-routing",
1364 .codec_name = "msm-stub-codec.1",
1365 .codec_dai_name = "msm-stub-rx",
1366 .no_pcm = 1,
1367 .be_id = MSM_BACKEND_DAI_INT_FM_RX,
1368 .be_hw_params_fixup = msm8930_be_hw_params_fixup,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001369 .ignore_pmdown_time = 1, /* this dainlink has playback support */
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301370 },
1371 {
1372 .name = LPASS_BE_INT_FM_TX,
1373 .stream_name = "Internal FM Capture",
1374 .cpu_dai_name = "msm-dai-q6.12293",
1375 .platform_name = "msm-pcm-routing",
1376 .codec_name = "msm-stub-codec.1",
1377 .codec_dai_name = "msm-stub-tx",
1378 .no_pcm = 1,
1379 .be_id = MSM_BACKEND_DAI_INT_FM_TX,
1380 .be_hw_params_fixup = msm8930_be_hw_params_fixup,
1381 },
1382 /* HDMI BACK END DAI Link */
1383 {
1384 .name = LPASS_BE_HDMI,
1385 .stream_name = "HDMI Playback",
1386 .cpu_dai_name = "msm-dai-q6-hdmi.8",
1387 .platform_name = "msm-pcm-routing",
1388 .codec_name = "msm-stub-codec.1",
1389 .codec_dai_name = "msm-stub-rx",
1390 .no_pcm = 1,
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301391 .be_id = MSM_BACKEND_DAI_HDMI_RX,
1392 .be_hw_params_fixup = msm8930_hdmi_be_hw_params_fixup,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001393 .ignore_pmdown_time = 1, /* this dainlink has playback support */
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301394 },
1395 /* Backend AFE DAI Links */
1396 {
1397 .name = LPASS_BE_AFE_PCM_RX,
1398 .stream_name = "AFE Playback",
1399 .cpu_dai_name = "msm-dai-q6.224",
1400 .platform_name = "msm-pcm-routing",
1401 .codec_name = "msm-stub-codec.1",
1402 .codec_dai_name = "msm-stub-rx",
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301403 .no_pcm = 1,
1404 .be_id = MSM_BACKEND_DAI_AFE_PCM_RX,
Jayasena Sangaraboina6b4de782012-10-23 16:52:01 -07001405 .be_hw_params_fixup = msm8930_proxy_be_hw_params_fixup,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001406 .ignore_pmdown_time = 1, /* this dainlink has playback support */
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301407 },
1408 {
1409 .name = LPASS_BE_AFE_PCM_TX,
1410 .stream_name = "AFE Capture",
1411 .cpu_dai_name = "msm-dai-q6.225",
1412 .platform_name = "msm-pcm-routing",
1413 .codec_name = "msm-stub-codec.1",
1414 .codec_dai_name = "msm-stub-tx",
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301415 .no_pcm = 1,
1416 .be_id = MSM_BACKEND_DAI_AFE_PCM_TX,
Jayasena Sangaraboina6b4de782012-10-23 16:52:01 -07001417 .be_hw_params_fixup = msm8930_proxy_be_hw_params_fixup,
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301418 },
Bhalchandra Gajare2e0893e2012-05-24 00:39:47 -07001419 /* AUX PCM Backend DAI Links */
1420 {
1421 .name = LPASS_BE_AUXPCM_RX,
1422 .stream_name = "AUX PCM Playback",
1423 .cpu_dai_name = "msm-dai-q6.2",
1424 .platform_name = "msm-pcm-routing",
1425 .codec_name = "msm-stub-codec.1",
1426 .codec_dai_name = "msm-stub-rx",
1427 .no_pcm = 1,
1428 .be_id = MSM_BACKEND_DAI_AUXPCM_RX,
1429 .be_hw_params_fixup = msm8930_auxpcm_be_params_fixup,
1430 .ops = &msm8930_auxpcm_be_ops,
1431 },
1432 {
1433 .name = LPASS_BE_AUXPCM_TX,
1434 .stream_name = "AUX PCM Capture",
1435 .cpu_dai_name = "msm-dai-q6.3",
1436 .platform_name = "msm-pcm-routing",
1437 .codec_name = "msm-stub-codec.1",
1438 .codec_dai_name = "msm-stub-tx",
1439 .no_pcm = 1,
1440 .be_id = MSM_BACKEND_DAI_AUXPCM_TX,
1441 .be_hw_params_fixup = msm8930_auxpcm_be_params_fixup,
Kuirong Wang892c9ad2012-09-20 11:43:17 -07001442 .ops = &msm8930_auxpcm_be_ops,
Bhalchandra Gajare2e0893e2012-05-24 00:39:47 -07001443 },
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301444 /* Incall Music BACK END DAI Link */
1445 {
1446 .name = LPASS_BE_VOICE_PLAYBACK_TX,
1447 .stream_name = "Voice Farend Playback",
1448 .cpu_dai_name = "msm-dai-q6.32773",
1449 .platform_name = "msm-pcm-routing",
1450 .codec_name = "msm-stub-codec.1",
1451 .codec_dai_name = "msm-stub-rx",
1452 .no_pcm = 1,
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301453 .be_id = MSM_BACKEND_DAI_VOICE_PLAYBACK_TX,
1454 .be_hw_params_fixup = msm8930_be_hw_params_fixup,
1455 },
1456 /* Incall Record Uplink BACK END DAI Link */
1457 {
1458 .name = LPASS_BE_INCALL_RECORD_TX,
1459 .stream_name = "Voice Uplink Capture",
1460 .cpu_dai_name = "msm-dai-q6.32772",
1461 .platform_name = "msm-pcm-routing",
1462 .codec_name = "msm-stub-codec.1",
1463 .codec_dai_name = "msm-stub-tx",
1464 .no_pcm = 1,
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301465 .be_id = MSM_BACKEND_DAI_INCALL_RECORD_TX,
1466 .be_hw_params_fixup = msm8930_be_hw_params_fixup,
1467 },
1468 /* Incall Record Downlink BACK END DAI Link */
1469 {
1470 .name = LPASS_BE_INCALL_RECORD_RX,
1471 .stream_name = "Voice Downlink Capture",
1472 .cpu_dai_name = "msm-dai-q6.32771",
1473 .platform_name = "msm-pcm-routing",
1474 .codec_name = "msm-stub-codec.1",
1475 .codec_dai_name = "msm-stub-tx",
1476 .no_pcm = 1,
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301477 .be_id = MSM_BACKEND_DAI_INCALL_RECORD_RX,
1478 .be_hw_params_fixup = msm8930_be_hw_params_fixup,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001479 .ignore_pmdown_time = 1, /* this dainlink has playback support */
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301480 },
1481};
1482
1483struct snd_soc_card snd_soc_card_msm8930 = {
1484 .name = "msm8930-sitar-snd-card",
1485 .dai_link = msm8930_dai,
1486 .num_links = ARRAY_SIZE(msm8930_dai),
Steve Mucklef132c6c2012-06-06 18:30:57 -07001487 .controls = sitar_msm8930_controls,
1488 .num_controls = ARRAY_SIZE(sitar_msm8930_controls),
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301489};
1490
1491static struct platform_device *msm8930_snd_device;
1492
1493static int msm8930_configure_headset_mic_gpios(void)
1494{
1495 int ret;
Laxminath Kasam852c7812013-03-07 20:03:37 +05301496
Laxminath Kasam82433012013-03-20 23:41:37 +05301497 if (!us_euro_gpio)
1498 return 0;
1499
1500 ret = gpio_request(us_euro_gpio, "US_EURO_SWITCH");
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301501 if (ret) {
Laxminath Kasam82433012013-03-20 23:41:37 +05301502 pr_err("%s: Failed to request gpio %d\n", __func__,
1503 us_euro_gpio);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301504 return ret;
1505 }
Laxminath Kasam82433012013-03-20 23:41:37 +05301506 ret = gpio_direction_output(us_euro_gpio, 0);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301507 if (ret) {
1508 pr_err("%s: Unable to set direction\n", __func__);
Laxminath Kasam82433012013-03-20 23:41:37 +05301509 gpio_free(us_euro_gpio);
1510 return ret;
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301511 }
Laxminath Kasam82433012013-03-20 23:41:37 +05301512 msm8930_useuro_gpio_requested = 1;
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301513 return 0;
1514}
1515static void msm8930_free_headset_mic_gpios(void)
1516{
Laxminath Kasam82433012013-03-20 23:41:37 +05301517 if (msm8930_useuro_gpio_requested) {
1518 gpio_free(us_euro_gpio);
1519 msm8930_useuro_gpio_requested = 0;
1520 }
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301521}
1522
1523static int __init msm8930_audio_init(void)
1524{
1525 int ret;
1526
Stepan Moskovchenkoc6a603a2012-09-21 20:32:17 -07001527 if (!soc_class_is_msm8930()) {
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301528 pr_err("%s: Not the right machine type\n", __func__);
1529 return -ENODEV ;
1530 }
Bhalchandra Gajare466aafe2012-05-02 17:55:26 -07001531 mbhc_cfg.calibration = def_sitar_mbhc_cal();
1532 if (!mbhc_cfg.calibration) {
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -08001533 pr_err("Calibration data allocation failed\n");
1534 return -ENOMEM;
1535 }
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301536
1537 msm8930_snd_device = platform_device_alloc("soc-audio", 0);
1538 if (!msm8930_snd_device) {
1539 pr_err("Platform device allocation failed\n");
Bhalchandra Gajare466aafe2012-05-02 17:55:26 -07001540 kfree(mbhc_cfg.calibration);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301541 return -ENOMEM;
1542 }
1543
1544 platform_set_drvdata(msm8930_snd_device, &snd_soc_card_msm8930);
1545 ret = platform_device_add(msm8930_snd_device);
1546 if (ret) {
1547 platform_device_put(msm8930_snd_device);
Bhalchandra Gajare466aafe2012-05-02 17:55:26 -07001548 kfree(mbhc_cfg.calibration);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301549 return ret;
1550 }
1551
Laxminath Kasam82433012013-03-20 23:41:37 +05301552 if (socinfo_get_platform_subtype() == PLATFORM_SUBTYPE_SGLTE)
1553 us_euro_gpio = GPIO_HS_US_EURO_SEL_GPIO_SGLTE;
1554 else
1555 us_euro_gpio = GPIO_HS_US_EURO_SEL_GPIO;
1556
1557 if (msm8930_configure_headset_mic_gpios())
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301558 pr_err("%s Fail to configure headset mic gpios\n", __func__);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301559
Kuirong Wang892c9ad2012-09-20 11:43:17 -07001560 atomic_set(&auxpcm_rsc_ref, 0);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301561 return ret;
1562
1563}
1564module_init(msm8930_audio_init);
1565
1566static void __exit msm8930_audio_exit(void)
1567{
Stepan Moskovchenkoc6a603a2012-09-21 20:32:17 -07001568 if (!soc_class_is_msm8930()) {
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301569 pr_err("%s: Not the right machine type\n", __func__);
1570 return ;
1571 }
1572 msm8930_free_headset_mic_gpios();
1573 platform_device_unregister(msm8930_snd_device);
Bhalchandra Gajare466aafe2012-05-02 17:55:26 -07001574 kfree(mbhc_cfg.calibration);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301575}
1576module_exit(msm8930_audio_exit);
1577
1578MODULE_DESCRIPTION("ALSA SoC MSM8930");
1579MODULE_LICENSE("GPL v2");