blob: 18b871619e3727fbc9a5860313b556940a93334f [file] [log] [blame]
Duy Truonge833aca2013-02-12 13:35:08 -08001/* Copyright (c) 2012, 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>
27#include "msm-pcm-routing.h"
28#include "../codecs/wcd9304.h"
29
30/* 8930 machine driver */
31
Asish Bhattacharyab86c3472012-02-15 08:31:52 +053032#define MSM8930_SPK_ON 1
33#define MSM8930_SPK_OFF 0
34
Asish Bhattacharyab86c3472012-02-15 08:31:52 +053035#define BTSCO_RATE_8KHZ 8000
36#define BTSCO_RATE_16KHZ 16000
37
Asish Bhattacharyac71827a2012-03-05 10:11:45 -080038#define SPK_AMP_POS 0x1
39#define SPK_AMP_NEG 0x2
Bhalchandra Gajare98a28cd2012-05-16 12:00:20 -070040#define SPKR_BOOST_GPIO 15
Bhalchandra Gajareb28275f2012-08-13 12:32:12 -070041#define LEFT_SPKR_AMPL_GPIO 15
Bhalchandra Gajare97676792012-05-22 17:41:45 -070042#define DEFAULT_PMIC_SPK_GAIN 0x0D
Asish Bhattacharyab86c3472012-02-15 08:31:52 +053043#define SITAR_EXT_CLK_RATE 12288000
44
Bhalchandra Gajare7708ee32012-05-24 17:37:37 -070045#define SITAR_MBHC_DEF_BUTTONS 8
Asish Bhattacharyab86c3472012-02-15 08:31:52 +053046#define SITAR_MBHC_DEF_RLOADS 5
47
Bhalchandra Gajare2e0893e2012-05-24 00:39:47 -070048#define GPIO_AUX_PCM_DOUT 63
49#define GPIO_AUX_PCM_DIN 64
50#define GPIO_AUX_PCM_SYNC 65
51#define GPIO_AUX_PCM_CLK 66
52
Asish Bhattacharyab86c3472012-02-15 08:31:52 +053053static int msm8930_spk_control;
54static int msm8930_slim_0_rx_ch = 1;
55static int msm8930_slim_0_tx_ch = 1;
Bhalchandra Gajare97676792012-05-22 17:41:45 -070056static int msm8930_pmic_spk_gain = DEFAULT_PMIC_SPK_GAIN;
Asish Bhattacharyab86c3472012-02-15 08:31:52 +053057
Asish Bhattacharyac71827a2012-03-05 10:11:45 -080058static int msm8930_ext_spk_pamp;
Asish Bhattacharyab86c3472012-02-15 08:31:52 +053059static int msm8930_btsco_rate = BTSCO_RATE_8KHZ;
60static int msm8930_btsco_ch = 1;
Vicky Sehrawat53f5c2e2012-11-05 17:54:13 -080061static int hdmi_rate_variable;
Subhash Chandra Bose Naripeddya3a99232013-01-11 14:05:21 -080062static int msm_hdmi_rx_ch = 2;
Asish Bhattacharyab86c3472012-02-15 08:31:52 +053063static struct clk *codec_clk;
64static int clk_users;
65
66static int msm8930_headset_gpios_configured;
67
68static struct snd_soc_jack hs_jack;
69static struct snd_soc_jack button_jack;
Kuirong Wang892c9ad2012-09-20 11:43:17 -070070static atomic_t auxpcm_rsc_ref;
Bhalchandra Gajare466aafe2012-05-02 17:55:26 -070071
72static int msm8930_enable_codec_ext_clk(
73 struct snd_soc_codec *codec, int enable,
74 bool dapm);
75
76static struct sitar_mbhc_config mbhc_cfg = {
77 .headset_jack = &hs_jack,
78 .button_jack = &button_jack,
79 .read_fw_bin = false,
80 .calibration = NULL,
81 .micbias = SITAR_MICBIAS2,
82 .mclk_cb_fn = msm8930_enable_codec_ext_clk,
83 .mclk_rate = SITAR_EXT_CLK_RATE,
84 .gpio = 0,
85 .gpio_irq = 0,
86 .gpio_level_insert = 1,
87};
88
Asish Bhattacharyab86c3472012-02-15 08:31:52 +053089
90static void msm8930_ext_control(struct snd_soc_codec *codec)
91{
92 struct snd_soc_dapm_context *dapm = &codec->dapm;
93
94 pr_debug("%s: msm8930_spk_control = %d", __func__, msm8930_spk_control);
95 if (msm8930_spk_control == MSM8930_SPK_ON) {
96 snd_soc_dapm_enable_pin(dapm, "Ext Spk Left Pos");
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -080097 snd_soc_dapm_enable_pin(dapm, "Ext Spk left Neg");
Asish Bhattacharyab86c3472012-02-15 08:31:52 +053098 } else {
99 snd_soc_dapm_disable_pin(dapm, "Ext Spk Left Pos");
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800100 snd_soc_dapm_disable_pin(dapm, "Ext Spk Left Neg");
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530101 }
102
103 snd_soc_dapm_sync(dapm);
104}
105
106static int msm8930_get_spk(struct snd_kcontrol *kcontrol,
107 struct snd_ctl_elem_value *ucontrol)
108{
109 pr_debug("%s: msm8930_spk_control = %d", __func__, msm8930_spk_control);
110 ucontrol->value.integer.value[0] = msm8930_spk_control;
111 return 0;
112}
113static int msm8930_set_spk(struct snd_kcontrol *kcontrol,
114 struct snd_ctl_elem_value *ucontrol)
115{
116 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
117
118 pr_debug("%s()\n", __func__);
119 if (msm8930_spk_control == ucontrol->value.integer.value[0])
120 return 0;
121
122 msm8930_spk_control = ucontrol->value.integer.value[0];
123 msm8930_ext_control(codec);
124 return 1;
125}
126
Bhalchandra Gajareb28275f2012-08-13 12:32:12 -0700127static int msm8930_cfg_spkr_gpio(int gpio,
128 int enable, const char *gpio_label)
129{
130 int ret = 0;
131
132 pr_debug("%s: Configure %s GPIO %u",
133 __func__, gpio_label, gpio);
134 ret = gpio_request(gpio, gpio_label);
135 if (ret)
136 return ret;
137
138 pr_debug("%s: Enable %s gpio %u\n",
139 __func__, gpio_label, gpio);
140 gpio_direction_output(gpio, enable);
141
142 return ret;
143}
144
Asish Bhattacharyac71827a2012-03-05 10:11:45 -0800145static void msm8960_ext_spk_power_amp_on(u32 spk)
146{
Bhalchandra Gajare98a28cd2012-05-16 12:00:20 -0700147 int ret = 0;
148
Asish Bhattacharyac71827a2012-03-05 10:11:45 -0800149 if (spk & (SPK_AMP_POS | SPK_AMP_NEG)) {
150 if ((msm8930_ext_spk_pamp & SPK_AMP_POS) &&
151 (msm8930_ext_spk_pamp & SPK_AMP_NEG)) {
152
153 pr_debug("%s() External Bottom Speaker Ampl already "
154 "turned on. spk = 0x%08x\n", __func__, spk);
155 return;
156 }
157
158 msm8930_ext_spk_pamp |= spk;
159
160 if ((msm8930_ext_spk_pamp & SPK_AMP_POS) &&
161 (msm8930_ext_spk_pamp & SPK_AMP_NEG)) {
162
Bhalchandra Gajareb28275f2012-08-13 12:32:12 -0700163 if (socinfo_get_pmic_model() == PMIC_MODEL_PM8917) {
164 ret = msm8930_cfg_spkr_gpio(
165 LEFT_SPKR_AMPL_GPIO,
166 1, "LEFT_SPKR_AMPL");
Bhalchandra Gajare98a28cd2012-05-16 12:00:20 -0700167 if (ret) {
Bhalchandra Gajareb28275f2012-08-13 12:32:12 -0700168 pr_err("%s: Failed to config ampl gpio %u\n",
169 __func__, LEFT_SPKR_AMPL_GPIO);
Bhalchandra Gajare98a28cd2012-05-16 12:00:20 -0700170 return;
171 }
Bhalchandra Gajareb28275f2012-08-13 12:32:12 -0700172 } else {
Bhalchandra Gajare98a28cd2012-05-16 12:00:20 -0700173
Bhalchandra Gajareb28275f2012-08-13 12:32:12 -0700174 if (machine_is_msm8930_mtp()
175 || machine_is_msm8930_fluid()) {
176 ret = msm8930_cfg_spkr_gpio(
177 SPKR_BOOST_GPIO, 1, "SPKR_BOOST");
178 if (ret) {
179 pr_err("%s: Failure: spkr boost gpio %u\n",
180 __func__, SPKR_BOOST_GPIO);
181 return;
182 }
183 }
184 pm8xxx_spk_enable(MSM8930_SPK_ON);
Bhalchandra Gajare98a28cd2012-05-16 12:00:20 -0700185 }
186
Asish Bhattacharyac71827a2012-03-05 10:11:45 -0800187 pr_debug("%s: slepping 4 ms after turning on external "
188 " Left Speaker Ampl\n", __func__);
189 usleep_range(4000, 4000);
190 }
191
192 } else {
193
194 pr_err("%s: ERROR : Invalid External Speaker Ampl. spk = 0x%08x\n",
195 __func__, spk);
196 return;
197 }
198}
199
200static void msm8960_ext_spk_power_amp_off(u32 spk)
201{
202 if (spk & (SPK_AMP_POS | SPK_AMP_NEG)) {
203 if (!msm8930_ext_spk_pamp)
204 return;
Bhalchandra Gajareb28275f2012-08-13 12:32:12 -0700205
206 if (socinfo_get_pmic_model() == PMIC_MODEL_PM8917) {
207 gpio_free(LEFT_SPKR_AMPL_GPIO);
208 msm8930_ext_spk_pamp = 0;
209 return;
210 }
211
Bhalchandra Gajare98a28cd2012-05-16 12:00:20 -0700212 if (machine_is_msm8930_mtp()
213 || machine_is_msm8930_fluid()) {
214 pr_debug("%s: Free speaker boost gpio %u\n",
215 __func__, SPKR_BOOST_GPIO);
216 gpio_direction_output(SPKR_BOOST_GPIO, 0);
217 gpio_free(SPKR_BOOST_GPIO);
218 }
Asish Bhattacharyac71827a2012-03-05 10:11:45 -0800219
220 pm8xxx_spk_enable(MSM8930_SPK_OFF);
221 msm8930_ext_spk_pamp = 0;
222 pr_debug("%s: slepping 4 ms after turning on external "
223 " Left Speaker Ampl\n", __func__);
224 usleep_range(4000, 4000);
225
226 } else {
227
228 pr_err("%s: ERROR : Invalid External Speaker Ampl. spk = 0x%08x\n",
229 __func__, spk);
230 return;
231 }
232}
233
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530234static int msm8930_spkramp_event(struct snd_soc_dapm_widget *w,
235 struct snd_kcontrol *k, int event)
236{
237 pr_debug("%s() %x\n", __func__, SND_SOC_DAPM_EVENT_ON(event));
Asish Bhattacharyac71827a2012-03-05 10:11:45 -0800238 if (SND_SOC_DAPM_EVENT_ON(event)) {
239 if (!strncmp(w->name, "Ext Spk Left Pos", 17))
240 msm8960_ext_spk_power_amp_on(SPK_AMP_POS);
241 else if (!strncmp(w->name, "Ext Spk Left Neg", 17))
242 msm8960_ext_spk_power_amp_on(SPK_AMP_NEG);
243 else {
244 pr_err("%s() Invalid Speaker Widget = %s\n",
245 __func__, w->name);
246 return -EINVAL;
247 }
248 } else {
249 if (!strncmp(w->name, "Ext Spk Left Pos", 17))
250 msm8960_ext_spk_power_amp_off(SPK_AMP_POS);
251 else if (!strncmp(w->name, "Ext Spk Left Neg", 17))
252 msm8960_ext_spk_power_amp_off(SPK_AMP_NEG);
253 else {
254 pr_err("%s() Invalid Speaker Widget = %s\n",
255 __func__, w->name);
256 return -EINVAL;
257 }
258 }
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530259 return 0;
260}
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800261
Bhalchandra Gajare466aafe2012-05-02 17:55:26 -0700262static int msm8930_enable_codec_ext_clk(
263 struct snd_soc_codec *codec, int enable,
264 bool dapm)
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530265{
266 pr_debug("%s: enable = %d\n", __func__, enable);
267 if (enable) {
268 clk_users++;
269 pr_debug("%s: clk_users = %d\n", __func__, clk_users);
270 if (clk_users != 1)
271 return 0;
272
273 if (codec_clk) {
274 clk_set_rate(codec_clk, SITAR_EXT_CLK_RATE);
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800275 clk_prepare_enable(codec_clk);
Bhalchandra Gajare466aafe2012-05-02 17:55:26 -0700276 sitar_mclk_enable(codec, 1, dapm);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530277 } else {
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800278 pr_err("%s: Error setting Sitar MCLK\n", __func__);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530279 clk_users--;
280 return -EINVAL;
281 }
282 } else {
283 pr_debug("%s: clk_users = %d\n", __func__, clk_users);
284 if (clk_users == 0)
285 return 0;
286 clk_users--;
287 if (!clk_users) {
288 pr_debug("%s: disabling MCLK. clk_users = %d\n",
289 __func__, clk_users);
Bhalchandra Gajare466aafe2012-05-02 17:55:26 -0700290 sitar_mclk_enable(codec, 0, dapm);
Bhalchandra Gajare2776af12012-04-27 16:59:39 -0700291 clk_disable_unprepare(codec_clk);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530292 }
293 }
294 return 0;
295}
296
297static int msm8930_mclk_event(struct snd_soc_dapm_widget *w,
298 struct snd_kcontrol *kcontrol, int event)
299{
300 pr_debug("%s: event = %d\n", __func__, event);
301
302 switch (event) {
303 case SND_SOC_DAPM_PRE_PMU:
Bhalchandra Gajare466aafe2012-05-02 17:55:26 -0700304 return msm8930_enable_codec_ext_clk(w->codec, 1, true);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530305 case SND_SOC_DAPM_POST_PMD:
Bhalchandra Gajare466aafe2012-05-02 17:55:26 -0700306 return msm8930_enable_codec_ext_clk(w->codec, 0, true);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530307 }
308 return 0;
309}
310
311static const struct snd_soc_dapm_widget msm8930_dapm_widgets[] = {
312
313 SND_SOC_DAPM_SUPPLY("MCLK", SND_SOC_NOPM, 0, 0,
314 msm8930_mclk_event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
315
316 SND_SOC_DAPM_SPK("Ext Spk Left Pos", msm8930_spkramp_event),
Asish Bhattacharyac71827a2012-03-05 10:11:45 -0800317 SND_SOC_DAPM_SPK("Ext Spk Left Neg", msm8930_spkramp_event),
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530318
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530319 SND_SOC_DAPM_MIC("Headset Mic", NULL),
320 SND_SOC_DAPM_MIC("Digital Mic1", NULL),
321 SND_SOC_DAPM_MIC("ANCRight Headset Mic", NULL),
322 SND_SOC_DAPM_MIC("ANCLeft Headset Mic", NULL),
323
324 SND_SOC_DAPM_MIC("Digital Mic1", NULL),
325 SND_SOC_DAPM_MIC("Digital Mic2", NULL),
326 SND_SOC_DAPM_MIC("Digital Mic3", NULL),
327 SND_SOC_DAPM_MIC("Digital Mic4", NULL),
328
329};
330
331static const struct snd_soc_dapm_route common_audio_map[] = {
332
333 {"RX_BIAS", NULL, "MCLK"},
334 {"LDO_H", NULL, "MCLK"},
335
336 {"MIC BIAS1 Internal1", NULL, "MCLK"},
337 {"MIC BIAS2 Internal1", NULL, "MCLK"},
338
339 /* Speaker path */
340 {"Ext Spk Left Pos", NULL, "LINEOUT1"},
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800341 {"Ext Spk Left Neg", NULL, "LINEOUT2"},
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530342
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800343 /* Headset Mic */
Bhalchandra Gajare553fb9e2012-06-26 14:48:54 -0700344 {"AMIC2", NULL, "MIC BIAS2 External"},
345 {"MIC BIAS2 External", NULL, "Headset Mic"},
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530346
347 /* Microphone path */
Bhalchandra Gajare18314d52012-06-06 19:03:01 -0700348 {"AMIC1", NULL, "MIC BIAS2 External"},
349 {"MIC BIAS2 External", NULL, "ANCLeft Headset Mic"},
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800350
Bhalchandra Gajare18314d52012-06-06 19:03:01 -0700351 {"AMIC3", NULL, "MIC BIAS2 External"},
352 {"MIC BIAS2 External", NULL, "ANCRight Headset Mic"},
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530353
354 {"HEADPHONE", NULL, "LDO_H"},
355
356 /**
357 * The digital Mic routes are setup considering
358 * fluid as default device.
359 */
360
361 /**
Bhalchandra Gajaree6a30f72012-05-23 19:46:21 -0700362 * Digital Mic1. Front Bottom left Mic on Fluid and MTP.
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530363 * Digital Mic GM5 on CDP mainboard.
Bhalchandra Gajaree6a30f72012-05-23 19:46:21 -0700364 * Conncted to DMIC1 Input on Sitar codec.
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530365 */
366 {"DMIC1", NULL, "MIC BIAS1 External"},
367 {"MIC BIAS1 External", NULL, "Digital Mic1"},
368
369 /**
Bhalchandra Gajaree6a30f72012-05-23 19:46:21 -0700370 * Digital Mic2. Back top MIC on Fluid.
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530371 * Digital Mic GM6 on CDP mainboard.
Bhalchandra Gajaree6a30f72012-05-23 19:46:21 -0700372 * Conncted to DMIC2 Input on Sitar codec.
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530373 */
374 {"DMIC2", NULL, "MIC BIAS1 External"},
375 {"MIC BIAS1 External", NULL, "Digital Mic2"},
376 /**
377 * Digital Mic3. Back Bottom Digital Mic on Fluid.
378 * Digital Mic GM1 on CDP mainboard.
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800379 * Conncted to DMIC4 Input on Sitar codec.
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530380 */
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800381 {"DMIC3", NULL, "MIC BIAS1 External"},
382 {"MIC BIAS1 External", NULL, "Digital Mic3"},
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530383
384 /**
385 * Digital Mic4. Back top Digital Mic on Fluid.
386 * Digital Mic GM2 on CDP mainboard.
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800387 * Conncted to DMIC3 Input on Sitar codec.
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530388 */
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800389 {"DMIC4", NULL, "MIC BIAS1 External"},
390 {"MIC BIAS1 External", NULL, "Digital Mic4"},
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530391
392
393};
394
395static const char *spk_function[] = {"Off", "On"};
396static const char *slim0_rx_ch_text[] = {"One", "Two"};
397static const char *slim0_tx_ch_text[] = {"One", "Two", "Three", "Four"};
Subhash Chandra Bose Naripeddya3a99232013-01-11 14:05:21 -0800398static char const *hdmi_rx_ch_text[] = {"Two", "Three", "Four", "Five",
399 "Six", "Seven", "Eight"};
Vicky Sehrawat53f5c2e2012-11-05 17:54:13 -0800400static const char * const hdmi_rate[] = {"Default", "Variable"};
401
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530402static const struct soc_enum msm8930_enum[] = {
403 SOC_ENUM_SINGLE_EXT(2, spk_function),
404 SOC_ENUM_SINGLE_EXT(2, slim0_rx_ch_text),
405 SOC_ENUM_SINGLE_EXT(4, slim0_tx_ch_text),
Vicky Sehrawat53f5c2e2012-11-05 17:54:13 -0800406 SOC_ENUM_SINGLE_EXT(2, hdmi_rate),
Subhash Chandra Bose Naripeddya3a99232013-01-11 14:05:21 -0800407 SOC_ENUM_SINGLE_EXT(7, hdmi_rx_ch_text),
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530408};
409
410static const char *btsco_rate_text[] = {"8000", "16000"};
411static const struct soc_enum msm8930_btsco_enum[] = {
412 SOC_ENUM_SINGLE_EXT(2, btsco_rate_text),
413};
414
415static int msm8930_slim_0_rx_ch_get(struct snd_kcontrol *kcontrol,
416 struct snd_ctl_elem_value *ucontrol)
417{
418 pr_debug("%s: msm8930_slim_0_rx_ch = %d\n", __func__,
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800419 msm8930_slim_0_rx_ch);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530420 ucontrol->value.integer.value[0] = msm8930_slim_0_rx_ch - 1;
421 return 0;
422}
423
424static int msm8930_slim_0_rx_ch_put(struct snd_kcontrol *kcontrol,
425 struct snd_ctl_elem_value *ucontrol)
426{
427 msm8930_slim_0_rx_ch = ucontrol->value.integer.value[0] + 1;
428
429 pr_debug("%s: msm8930_slim_0_rx_ch = %d\n", __func__,
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800430 msm8930_slim_0_rx_ch);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530431 return 1;
432}
433
434static int msm8930_slim_0_tx_ch_get(struct snd_kcontrol *kcontrol,
435 struct snd_ctl_elem_value *ucontrol)
436{
437 pr_debug("%s: msm8930_slim_0_tx_ch = %d\n", __func__,
438 msm8930_slim_0_tx_ch);
439 ucontrol->value.integer.value[0] = msm8930_slim_0_tx_ch - 1;
440 return 0;
441}
442
443static int msm8930_slim_0_tx_ch_put(struct snd_kcontrol *kcontrol,
444 struct snd_ctl_elem_value *ucontrol)
445{
446 msm8930_slim_0_tx_ch = ucontrol->value.integer.value[0] + 1;
447
448 pr_debug("%s: msm8930_slim_0_tx_ch = %d\n", __func__,
449 msm8930_slim_0_tx_ch);
450 return 1;
451}
452
453static int msm8930_btsco_rate_get(struct snd_kcontrol *kcontrol,
454 struct snd_ctl_elem_value *ucontrol)
455{
456 pr_debug("%s: msm8930_btsco_rate = %d", __func__, msm8930_btsco_rate);
457 ucontrol->value.integer.value[0] = msm8930_btsco_rate;
458 return 0;
459}
460
461static int msm8930_btsco_rate_put(struct snd_kcontrol *kcontrol,
462 struct snd_ctl_elem_value *ucontrol)
463{
Kuirong Wangfd8e0b32012-05-30 19:45:04 -0700464
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530465 switch (ucontrol->value.integer.value[0]) {
Kuirong Wangfd8e0b32012-05-30 19:45:04 -0700466 case 8000:
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530467 msm8930_btsco_rate = BTSCO_RATE_8KHZ;
468 break;
Kuirong Wangfd8e0b32012-05-30 19:45:04 -0700469 case 16000:
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530470 msm8930_btsco_rate = BTSCO_RATE_16KHZ;
471 break;
472 default:
473 msm8930_btsco_rate = BTSCO_RATE_8KHZ;
474 break;
475 }
476 pr_debug("%s: msm8930_btsco_rate = %d\n", __func__, msm8930_btsco_rate);
477 return 0;
478}
479
Bhalchandra Gajare97676792012-05-22 17:41:45 -0700480static const char *pmic_spk_gain_text[] = {
481 "NEG_6_DB", "NEG_4_DB", "NEG_2_DB", "ZERO_DB", "POS_2_DB", "POS_4_DB",
482 "POS_6_DB", "POS_8_DB", "POS_10_DB", "POS_12_DB", "POS_14_DB",
483 "POS_16_DB", "POS_18_DB", "POS_20_DB", "POS_22_DB", "POS_24_DB"
484};
485
486static const struct soc_enum msm8960_pmic_spk_gain_enum[] = {
487 SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(pmic_spk_gain_text),
488 pmic_spk_gain_text),
489};
490
491static int msm8930_pmic_gain_get(struct snd_kcontrol *kcontrol,
492 struct snd_ctl_elem_value *ucontrol)
493{
494 pr_debug("%s: msm8930_pmic_spk_gain = %d\n", __func__,
495 msm8930_pmic_spk_gain);
496 ucontrol->value.integer.value[0] = msm8930_pmic_spk_gain;
497 return 0;
498}
499
500static int msm8930_pmic_gain_put(struct snd_kcontrol *kcontrol,
501 struct snd_ctl_elem_value *ucontrol)
502{
503 int ret = 0;
504 msm8930_pmic_spk_gain = ucontrol->value.integer.value[0];
Bhalchandra Gajareb28275f2012-08-13 12:32:12 -0700505 if (socinfo_get_pmic_model() != PMIC_MODEL_PM8917)
506 ret = pm8xxx_spk_gain(msm8930_pmic_spk_gain);
Bhalchandra Gajare97676792012-05-22 17:41:45 -0700507 pr_debug("%s: msm8930_pmic_spk_gain = %d"
508 " ucontrol->value.integer.value[0] = %d\n", __func__,
509 msm8930_pmic_spk_gain,
510 (int) ucontrol->value.integer.value[0]);
511 return ret;
512}
513
Subhash Chandra Bose Naripeddya3a99232013-01-11 14:05:21 -0800514static int msm_hdmi_rx_ch_get(struct snd_kcontrol *kcontrol,
515 struct snd_ctl_elem_value *ucontrol)
516{
517 pr_debug("%s: msm_hdmi_rx_ch = %d\n", __func__,
518 msm_hdmi_rx_ch);
519 ucontrol->value.integer.value[0] = msm_hdmi_rx_ch - 2;
520 return 0;
521}
522
523static int msm_hdmi_rx_ch_put(struct snd_kcontrol *kcontrol,
524 struct snd_ctl_elem_value *ucontrol)
525{
526 msm_hdmi_rx_ch = ucontrol->value.integer.value[0] + 2;
527
528 pr_debug("%s: msm_hdmi_rx_ch = %d\n", __func__,
529 msm_hdmi_rx_ch);
530 return 1;
531}
532
Vicky Sehrawat53f5c2e2012-11-05 17:54:13 -0800533static int msm8930_hdmi_rate_put(struct snd_kcontrol *kcontrol,
534 struct snd_ctl_elem_value *ucontrol)
535{
536 hdmi_rate_variable = ucontrol->value.integer.value[0];
537 pr_debug("%s: hdmi_rate_variable = %d\n", __func__, hdmi_rate_variable);
538 return 0;
539}
540
541static int msm8930_hdmi_rate_get(struct snd_kcontrol *kcontrol,
542 struct snd_ctl_elem_value *ucontrol)
543{
544 ucontrol->value.integer.value[0] = hdmi_rate_variable;
545 return 0;
546}
547
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530548static const struct snd_kcontrol_new sitar_msm8930_controls[] = {
549 SOC_ENUM_EXT("Speaker Function", msm8930_enum[0], msm8930_get_spk,
550 msm8930_set_spk),
551 SOC_ENUM_EXT("SLIM_0_RX Channels", msm8930_enum[1],
552 msm8930_slim_0_rx_ch_get, msm8930_slim_0_rx_ch_put),
553 SOC_ENUM_EXT("SLIM_0_TX Channels", msm8930_enum[2],
554 msm8930_slim_0_tx_ch_get, msm8930_slim_0_tx_ch_put),
Bhalchandra Gajare97676792012-05-22 17:41:45 -0700555 SOC_ENUM_EXT("PMIC SPK Gain", msm8960_pmic_spk_gain_enum[0],
556 msm8930_pmic_gain_get, msm8930_pmic_gain_put),
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530557 SOC_ENUM_EXT("Internal BTSCO SampleRate", msm8930_btsco_enum[0],
558 msm8930_btsco_rate_get, msm8930_btsco_rate_put),
Vicky Sehrawat53f5c2e2012-11-05 17:54:13 -0800559 SOC_ENUM_EXT("HDMI RX Rate", msm8930_enum[3],
560 msm8930_hdmi_rate_get,
561 msm8930_hdmi_rate_put),
Subhash Chandra Bose Naripeddya3a99232013-01-11 14:05:21 -0800562 SOC_ENUM_EXT("HDMI_RX Channels", msm8930_enum[4],
563 msm_hdmi_rx_ch_get, msm_hdmi_rx_ch_put),
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530564};
565
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800566static void *def_sitar_mbhc_cal(void)
567{
568 void *sitar_cal;
569 struct sitar_mbhc_btn_detect_cfg *btn_cfg;
570 u16 *btn_low, *btn_high;
571 u8 *n_ready, *n_cic, *gain;
572
573 sitar_cal = kzalloc(SITAR_MBHC_CAL_SIZE(SITAR_MBHC_DEF_BUTTONS,
574 SITAR_MBHC_DEF_RLOADS),
575 GFP_KERNEL);
576 if (!sitar_cal) {
577 pr_err("%s: out of memory\n", __func__);
578 return NULL;
579 }
580
581#define S(X, Y) ((SITAR_MBHC_CAL_GENERAL_PTR(sitar_cal)->X) = (Y))
582 S(t_ldoh, 100);
583 S(t_bg_fast_settle, 100);
584 S(t_shutdown_plug_rem, 255);
585 S(mbhc_nsa, 4);
586 S(mbhc_navg, 4);
587#undef S
588#define S(X, Y) ((SITAR_MBHC_CAL_PLUG_DET_PTR(sitar_cal)->X) = (Y))
589 S(mic_current, SITAR_PID_MIC_5_UA);
590 S(hph_current, SITAR_PID_MIC_5_UA);
591 S(t_mic_pid, 100);
592 S(t_ins_complete, 250);
593 S(t_ins_retry, 200);
594#undef S
595#define S(X, Y) ((SITAR_MBHC_CAL_PLUG_TYPE_PTR(sitar_cal)->X) = (Y))
596 S(v_no_mic, 30);
Bhalchandra Gajare18314d52012-06-06 19:03:01 -0700597 S(v_hs_max, 1650);
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800598#undef S
599#define S(X, Y) ((SITAR_MBHC_CAL_BTN_DET_PTR(sitar_cal)->X) = (Y))
600 S(c[0], 62);
601 S(c[1], 124);
602 S(nc, 1);
603 S(n_meas, 3);
604 S(mbhc_nsc, 11);
605 S(n_btn_meas, 1);
606 S(n_btn_con, 2);
607 S(num_btn, SITAR_MBHC_DEF_BUTTONS);
608 S(v_btn_press_delta_sta, 100);
609 S(v_btn_press_delta_cic, 50);
610#undef S
611 btn_cfg = SITAR_MBHC_CAL_BTN_DET_PTR(sitar_cal);
612 btn_low = sitar_mbhc_cal_btn_det_mp(btn_cfg, SITAR_BTN_DET_V_BTN_LOW);
613 btn_high = sitar_mbhc_cal_btn_det_mp(btn_cfg, SITAR_BTN_DET_V_BTN_HIGH);
614 btn_low[0] = -50;
615 btn_high[0] = 10;
616 btn_low[1] = 11;
617 btn_high[1] = 38;
618 btn_low[2] = 39;
619 btn_high[2] = 64;
620 btn_low[3] = 65;
621 btn_high[3] = 91;
622 btn_low[4] = 92;
623 btn_high[4] = 115;
624 btn_low[5] = 116;
625 btn_high[5] = 141;
626 btn_low[6] = 142;
627 btn_high[6] = 163;
628 btn_low[7] = 164;
629 btn_high[7] = 250;
630 n_ready = sitar_mbhc_cal_btn_det_mp(btn_cfg, SITAR_BTN_DET_N_READY);
631 n_ready[0] = 48;
632 n_ready[1] = 38;
633 n_cic = sitar_mbhc_cal_btn_det_mp(btn_cfg, SITAR_BTN_DET_N_CIC);
634 n_cic[0] = 60;
635 n_cic[1] = 47;
636 gain = sitar_mbhc_cal_btn_det_mp(btn_cfg, SITAR_BTN_DET_GAIN);
637 gain[0] = 11;
638 gain[1] = 9;
639
640 return sitar_cal;
641}
642
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530643static int msm8930_hw_params(struct snd_pcm_substream *substream,
644 struct snd_pcm_hw_params *params)
645{
646 struct snd_soc_pcm_runtime *rtd = substream->private_data;
647 struct snd_soc_dai *codec_dai = rtd->codec_dai;
648 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
649 int ret = 0;
650 unsigned int rx_ch[SLIM_MAX_RX_PORTS], tx_ch[SLIM_MAX_TX_PORTS];
651 unsigned int rx_ch_cnt = 0, tx_ch_cnt = 0;
652
653 pr_debug("%s: ch=%d\n", __func__,
654 msm8930_slim_0_rx_ch);
655 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
656 ret = snd_soc_dai_get_channel_map(codec_dai,
657 &tx_ch_cnt, tx_ch, &rx_ch_cnt , rx_ch);
658 if (ret < 0) {
659 pr_err("%s: failed to get codec chan map\n", __func__);
660 goto end;
661 }
662
663 ret = snd_soc_dai_set_channel_map(cpu_dai, 0, 0,
664 msm8930_slim_0_rx_ch, rx_ch);
665 if (ret < 0) {
666 pr_err("%s: failed to set cpu chan map\n", __func__);
667 goto end;
668 }
669 ret = snd_soc_dai_set_channel_map(codec_dai, 0, 0,
670 msm8930_slim_0_rx_ch, rx_ch);
671 if (ret < 0) {
672 pr_err("%s: failed to set codec channel map\n",
673 __func__);
674 goto end;
675 }
676 } else {
677 ret = snd_soc_dai_get_channel_map(codec_dai,
678 &tx_ch_cnt, tx_ch, &rx_ch_cnt , rx_ch);
679 if (ret < 0) {
680 pr_err("%s: failed to get codec chan map\n", __func__);
681 goto end;
682 }
683 ret = snd_soc_dai_set_channel_map(cpu_dai,
684 msm8930_slim_0_tx_ch, tx_ch, 0 , 0);
685 if (ret < 0) {
686 pr_err("%s: failed to set cpu chan map\n", __func__);
687 goto end;
688 }
689 ret = snd_soc_dai_set_channel_map(codec_dai,
690 msm8930_slim_0_tx_ch, tx_ch, 0, 0);
691 if (ret < 0) {
692 pr_err("%s: failed to set codec channel map\n",
693 __func__);
694 goto end;
695 }
696
697 }
698end:
699 return ret;
700}
701
702static int msm8930_audrx_init(struct snd_soc_pcm_runtime *rtd)
703{
704 int err;
705 struct snd_soc_codec *codec = rtd->codec;
706 struct snd_soc_dapm_context *dapm = &codec->dapm;
707 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
708
709 pr_debug("%s()\n", __func__);
710
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530711 snd_soc_dapm_new_controls(dapm, msm8930_dapm_widgets,
712 ARRAY_SIZE(msm8930_dapm_widgets));
713
714 snd_soc_dapm_add_routes(dapm, common_audio_map,
715 ARRAY_SIZE(common_audio_map));
716
717 snd_soc_dapm_enable_pin(dapm, "Ext Spk Left Pos");
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800718 snd_soc_dapm_enable_pin(dapm, "Ext Spk Left Neg");
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530719
720 snd_soc_dapm_sync(dapm);
721
722 err = snd_soc_jack_new(codec, "Headset Jack",
723 (SND_JACK_HEADSET | SND_JACK_OC_HPHL | SND_JACK_OC_HPHR),
724 &hs_jack);
725 if (err) {
726 pr_err("failed to create new jack\n");
727 return err;
728 }
729
730 err = snd_soc_jack_new(codec, "Button Jack",
Bhalchandra Gajare7708ee32012-05-24 17:37:37 -0700731 SITAR_JACK_BUTTON_MASK, &button_jack);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530732 if (err) {
733 pr_err("failed to create new jack\n");
734 return err;
735 }
736 codec_clk = clk_get(cpu_dai->dev, "osr_clk");
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800737
Bhalchandra Gajare466aafe2012-05-02 17:55:26 -0700738 mbhc_cfg.gpio = 37;
739 mbhc_cfg.gpio_irq = gpio_to_irq(mbhc_cfg.gpio);
740 sitar_hs_detect(codec, &mbhc_cfg);
741
Bhalchandra Gajareb28275f2012-08-13 12:32:12 -0700742 if (socinfo_get_pmic_model() != PMIC_MODEL_PM8917) {
743 /* Initialize default PMIC speaker gain */
744 pm8xxx_spk_gain(DEFAULT_PMIC_SPK_GAIN);
745 }
Bhalchandra Gajare97676792012-05-22 17:41:45 -0700746
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530747 return 0;
748}
749
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530750static int msm8930_slim_0_rx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
751 struct snd_pcm_hw_params *params)
752{
753 struct snd_interval *rate = hw_param_interval(params,
754 SNDRV_PCM_HW_PARAM_RATE);
755
756 struct snd_interval *channels = hw_param_interval(params,
757 SNDRV_PCM_HW_PARAM_CHANNELS);
758
759 pr_debug("%s()\n", __func__);
760 rate->min = rate->max = 48000;
761 channels->min = channels->max = msm8930_slim_0_rx_ch;
762
763 return 0;
764}
765
766static int msm8930_slim_0_tx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
767 struct snd_pcm_hw_params *params)
768{
769 struct snd_interval *rate = hw_param_interval(params,
770 SNDRV_PCM_HW_PARAM_RATE);
771
772 struct snd_interval *channels = hw_param_interval(params,
773 SNDRV_PCM_HW_PARAM_CHANNELS);
774
775 pr_debug("%s()\n", __func__);
776 rate->min = rate->max = 48000;
777 channels->min = channels->max = msm8930_slim_0_tx_ch;
778
779 return 0;
780}
781
782static int msm8930_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
783 struct snd_pcm_hw_params *params)
784{
785 struct snd_interval *rate = hw_param_interval(params,
786 SNDRV_PCM_HW_PARAM_RATE);
787
788 pr_debug("%s()\n", __func__);
789 rate->min = rate->max = 48000;
790
791 return 0;
792}
793
794static int msm8930_hdmi_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
795 struct snd_pcm_hw_params *params)
796{
797 struct snd_interval *rate = hw_param_interval(params,
798 SNDRV_PCM_HW_PARAM_RATE);
799
800 struct snd_interval *channels = hw_param_interval(params,
801 SNDRV_PCM_HW_PARAM_CHANNELS);
802
Vicky Sehrawat53f5c2e2012-11-05 17:54:13 -0800803 if (!hdmi_rate_variable)
804 rate->min = rate->max = 48000;
Subhash Chandra Bose Naripeddya3a99232013-01-11 14:05:21 -0800805 channels->min = channels->max = msm_hdmi_rx_ch;
806 if (channels->max < 2)
807 channels->min = channels->max = 2;
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530808
809 return 0;
810}
811
812static int msm8930_btsco_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
813 struct snd_pcm_hw_params *params)
814{
815 struct snd_interval *rate = hw_param_interval(params,
816 SNDRV_PCM_HW_PARAM_RATE);
817
818 struct snd_interval *channels = hw_param_interval(params,
819 SNDRV_PCM_HW_PARAM_CHANNELS);
820
821 rate->min = rate->max = msm8930_btsco_rate;
822 channels->min = channels->max = msm8930_btsco_ch;
823
824 return 0;
825}
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530826
Bhalchandra Gajare2e0893e2012-05-24 00:39:47 -0700827static int msm8930_auxpcm_be_params_fixup(struct snd_soc_pcm_runtime *rtd,
828 struct snd_pcm_hw_params *params)
829{
830 struct snd_interval *rate = hw_param_interval(params,
831 SNDRV_PCM_HW_PARAM_RATE);
832
833 struct snd_interval *channels = hw_param_interval(params,
834 SNDRV_PCM_HW_PARAM_CHANNELS);
835
836 /* PCM only supports mono output with 8khz sample rate */
837 rate->min = rate->max = 8000;
838 channels->min = channels->max = 1;
839
840 return 0;
841}
842
Jayasena Sangaraboina6b4de782012-10-23 16:52:01 -0700843static int msm8930_proxy_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
844 struct snd_pcm_hw_params *params)
845{
846 struct snd_interval *rate = hw_param_interval(params,
847 SNDRV_PCM_HW_PARAM_RATE);
848
849 pr_debug("%s()\n", __func__);
850 rate->min = rate->max = 48000;
851
852 return 0;
853}
854
Bhalchandra Gajare2e0893e2012-05-24 00:39:47 -0700855static int msm8930_aux_pcm_get_gpios(void)
856{
857 int ret = 0;
858
859 pr_debug("%s\n", __func__);
860
861 ret = gpio_request(GPIO_AUX_PCM_DOUT, "AUX PCM DOUT");
862 if (ret < 0) {
863 pr_err("%s: Failed to request gpio(%d): AUX PCM DOUT",
864 __func__, GPIO_AUX_PCM_DOUT);
865
866 goto fail_dout;
867 }
868
869 ret = gpio_request(GPIO_AUX_PCM_DIN, "AUX PCM DIN");
870 if (ret < 0) {
871 pr_err("%s: Failed to request gpio(%d): AUX PCM DIN",
872 __func__, GPIO_AUX_PCM_DIN);
873 goto fail_din;
874 }
875
876 ret = gpio_request(GPIO_AUX_PCM_SYNC, "AUX PCM SYNC");
877 if (ret < 0) {
878 pr_err("%s: Failed to request gpio(%d): AUX PCM SYNC",
879 __func__, GPIO_AUX_PCM_SYNC);
880 goto fail_sync;
881 }
882
883 ret = gpio_request(GPIO_AUX_PCM_CLK, "AUX PCM CLK");
884 if (ret < 0) {
885 pr_err("%s: Failed to request gpio(%d): AUX PCM CLK",
886 __func__, GPIO_AUX_PCM_CLK);
887 goto fail_clk;
888 }
889
890 return 0;
891
892fail_clk:
893 gpio_free(GPIO_AUX_PCM_SYNC);
894fail_sync:
895 gpio_free(GPIO_AUX_PCM_DIN);
896fail_din:
897 gpio_free(GPIO_AUX_PCM_DOUT);
898fail_dout:
899
900 return ret;
901}
902
903static int msm8930_aux_pcm_free_gpios(void)
904{
905 gpio_free(GPIO_AUX_PCM_DIN);
906 gpio_free(GPIO_AUX_PCM_DOUT);
907 gpio_free(GPIO_AUX_PCM_SYNC);
908 gpio_free(GPIO_AUX_PCM_CLK);
909
910 return 0;
911}
912
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530913static int msm8930_startup(struct snd_pcm_substream *substream)
914{
915 pr_debug("%s(): substream = %s stream = %d\n", __func__,
916 substream->name, substream->stream);
917 return 0;
918}
919
Bhalchandra Gajare2e0893e2012-05-24 00:39:47 -0700920static int msm8930_auxpcm_startup(struct snd_pcm_substream *substream)
921{
922 int ret = 0;
923
Kuirong Wang892c9ad2012-09-20 11:43:17 -0700924 pr_debug("%s(): substream = %s, auxpcm_rsc_ref counter = %d\n",
925 __func__, substream->name, atomic_read(&auxpcm_rsc_ref));
926 if (atomic_inc_return(&auxpcm_rsc_ref) == 1)
927 ret = msm8930_aux_pcm_get_gpios();
Bhalchandra Gajare2e0893e2012-05-24 00:39:47 -0700928 if (ret < 0) {
929 pr_err("%s: Aux PCM GPIO request failed\n", __func__);
930 return -EINVAL;
931 }
932 return 0;
933
934}
935
936static void msm8930_auxpcm_shutdown(struct snd_pcm_substream *substream)
937{
Kuirong Wang892c9ad2012-09-20 11:43:17 -0700938 pr_debug("%s(): substream = %s, auxpcm_rsc_ref counter = %d\n",
939 __func__, substream->name, atomic_read(&auxpcm_rsc_ref));
940 if (atomic_dec_return(&auxpcm_rsc_ref) == 0)
941 msm8930_aux_pcm_free_gpios();
Bhalchandra Gajare2e0893e2012-05-24 00:39:47 -0700942}
943
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530944static void msm8930_shutdown(struct snd_pcm_substream *substream)
945{
946 pr_debug("%s(): substream = %s stream = %d\n", __func__,
947 substream->name, substream->stream);
948}
949
950static struct snd_soc_ops msm8930_be_ops = {
951 .startup = msm8930_startup,
952 .hw_params = msm8930_hw_params,
953 .shutdown = msm8930_shutdown,
954};
955
Bhalchandra Gajare2e0893e2012-05-24 00:39:47 -0700956static struct snd_soc_ops msm8930_auxpcm_be_ops = {
957 .startup = msm8930_auxpcm_startup,
958 .shutdown = msm8930_auxpcm_shutdown,
959};
960
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530961/* Digital audio interface glue - connects codec <---> CPU */
962static struct snd_soc_dai_link msm8930_dai[] = {
963 /* FrontEnd DAI Links */
964 {
965 .name = "MSM8930 Media1",
966 .stream_name = "MultiMedia1",
967 .cpu_dai_name = "MultiMedia1",
968 .platform_name = "msm-pcm-dsp",
969 .dynamic = 1,
Steve Mucklef132c6c2012-06-06 18:30:57 -0700970 .codec_dai_name = "snd-soc-dummy-dai",
971 .codec_name = "snd-soc-dummy",
972 .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
973 .ignore_suspend = 1,
974 .ignore_pmdown_time = 1, /* this dainlink has playback support */
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530975 .be_id = MSM_FRONTEND_DAI_MULTIMEDIA1
976 },
977 {
978 .name = "MSM8930 Media2",
979 .stream_name = "MultiMedia2",
980 .cpu_dai_name = "MultiMedia2",
Asish Bhattacharyae2601ae2012-07-18 21:13:21 +0530981 .platform_name = "msm-multi-ch-pcm-dsp",
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530982 .dynamic = 1,
Steve Mucklef132c6c2012-06-06 18:30:57 -0700983 .codec_dai_name = "snd-soc-dummy-dai",
984 .codec_name = "snd-soc-dummy",
985 .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
986 .ignore_suspend = 1,
987 .ignore_pmdown_time = 1, /* this dainlink has playback support */
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530988 .be_id = MSM_FRONTEND_DAI_MULTIMEDIA2,
989 },
990 {
991 .name = "Circuit-Switch Voice",
992 .stream_name = "CS-Voice",
993 .cpu_dai_name = "CS-VOICE",
994 .platform_name = "msm-pcm-voice",
995 .dynamic = 1,
Steve Mucklef132c6c2012-06-06 18:30:57 -0700996 .codec_dai_name = "snd-soc-dummy-dai",
997 .codec_name = "snd-soc-dummy",
998 .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530999 .be_id = MSM_FRONTEND_DAI_CS_VOICE,
1000 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
1001 .ignore_suspend = 1,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001002 .ignore_pmdown_time = 1, /* this dainlink has playback support */
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301003 },
1004 {
1005 .name = "MSM VoIP",
1006 .stream_name = "VoIP",
1007 .cpu_dai_name = "VoIP",
1008 .platform_name = "msm-voip-dsp",
1009 .dynamic = 1,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001010 .codec_dai_name = "snd-soc-dummy-dai",
1011 .codec_name = "snd-soc-dummy",
1012 .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
1013 .ignore_suspend = 1,
1014 .ignore_pmdown_time = 1, /* this dainlink has playback support */
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301015 .be_id = MSM_FRONTEND_DAI_VOIP,
1016 },
1017 {
1018 .name = "MSM8930 LPA",
1019 .stream_name = "LPA",
1020 .cpu_dai_name = "MultiMedia3",
1021 .platform_name = "msm-pcm-lpa",
1022 .dynamic = 1,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001023 .codec_dai_name = "snd-soc-dummy-dai",
1024 .codec_name = "snd-soc-dummy",
1025 .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
1026 .ignore_suspend = 1,
1027 .ignore_pmdown_time = 1, /* this dainlink has playback support */
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301028 .be_id = MSM_FRONTEND_DAI_MULTIMEDIA3,
1029 },
1030 /* Hostless PMC purpose */
1031 {
1032 .name = "SLIMBUS_0 Hostless",
1033 .stream_name = "SLIMBUS_0 Hostless",
1034 .cpu_dai_name = "SLIMBUS0_HOSTLESS",
1035 .platform_name = "msm-pcm-hostless",
1036 .dynamic = 1,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001037 .codec_dai_name = "snd-soc-dummy-dai",
1038 .codec_name = "snd-soc-dummy",
1039 .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301040 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
1041 .ignore_suspend = 1,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001042 .ignore_pmdown_time = 1, /* this dainlink has playback support */
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301043 /* .be_id = do not care */
1044 },
1045 {
1046 .name = "INT_FM Hostless",
1047 .stream_name = "INT_FM Hostless",
1048 .cpu_dai_name = "INT_FM_HOSTLESS",
1049 .platform_name = "msm-pcm-hostless",
1050 .dynamic = 1,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001051 .codec_dai_name = "snd-soc-dummy-dai",
1052 .codec_name = "snd-soc-dummy",
1053 .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301054 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
1055 .ignore_suspend = 1,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001056 .ignore_pmdown_time = 1, /* this dainlink has playback support */
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301057 /* .be_id = do not care */
1058 },
1059 {
1060 .name = "MSM AFE-PCM RX",
1061 .stream_name = "AFE-PROXY RX",
1062 .cpu_dai_name = "msm-dai-q6.241",
1063 .codec_name = "msm-stub-codec.1",
1064 .codec_dai_name = "msm-stub-rx",
1065 .platform_name = "msm-pcm-afe",
1066 .ignore_suspend = 1,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001067 .ignore_pmdown_time = 1, /* this dainlink has playback support */
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301068 },
1069 {
1070 .name = "MSM AFE-PCM TX",
1071 .stream_name = "AFE-PROXY TX",
1072 .cpu_dai_name = "msm-dai-q6.240",
1073 .codec_name = "msm-stub-codec.1",
1074 .codec_dai_name = "msm-stub-tx",
1075 .platform_name = "msm-pcm-afe",
1076 .ignore_suspend = 1,
1077 },
1078 {
1079 .name = "MSM8930 Compr",
1080 .stream_name = "COMPR",
1081 .cpu_dai_name = "MultiMedia4",
1082 .platform_name = "msm-compr-dsp",
1083 .dynamic = 1,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001084 .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
1085 .codec_dai_name = "snd-soc-dummy-dai",
1086 .codec_name = "snd-soc-dummy",
1087 .ignore_suspend = 1,
1088 .ignore_pmdown_time = 1, /* this dainlink has playback support */
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301089 .be_id = MSM_FRONTEND_DAI_MULTIMEDIA4,
1090 },
1091 {
1092 .name = "AUXPCM Hostless",
1093 .stream_name = "AUXPCM Hostless",
1094 .cpu_dai_name = "AUXPCM_HOSTLESS",
1095 .platform_name = "msm-pcm-hostless",
1096 .dynamic = 1,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001097 .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301098 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
1099 .ignore_suspend = 1,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001100 .ignore_pmdown_time = 1, /* this dainlink has playback support */
1101 .codec_dai_name = "snd-soc-dummy-dai",
1102 .codec_name = "snd-soc-dummy",
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301103 },
1104 /* HDMI Hostless */
1105 {
1106 .name = "HDMI_RX_HOSTLESS",
1107 .stream_name = "HDMI_RX_HOSTLESS",
1108 .cpu_dai_name = "HDMI_HOSTLESS",
1109 .platform_name = "msm-pcm-hostless",
1110 .dynamic = 1,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001111 .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301112 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301113 .ignore_suspend = 1,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001114 .ignore_pmdown_time = 1, /* this dainlink has playback support */
1115 .codec_dai_name = "snd-soc-dummy-dai",
1116 .codec_name = "snd-soc-dummy",
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301117 },
Jayasena Sangaraboina99bf09c2012-07-17 12:03:08 -07001118 {
1119 .name = "VoLTE",
1120 .stream_name = "VoLTE",
1121 .cpu_dai_name = "VoLTE",
1122 .platform_name = "msm-pcm-voice",
1123 .dynamic = 1,
1124 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
1125 SND_SOC_DPCM_TRIGGER_POST},
1126 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
1127 .ignore_suspend = 1,
1128 /* this dainlink has playback support */
1129 .ignore_pmdown_time = 1,
1130 .codec_dai_name = "snd-soc-dummy-dai",
1131 .codec_name = "snd-soc-dummy",
1132 .be_id = MSM_FRONTEND_DAI_VOLTE,
1133 },
1134 {
1135 .name = "SGLTE",
1136 .stream_name = "SGLTE",
1137 .cpu_dai_name = "SGLTE",
1138 .platform_name = "msm-pcm-voice",
1139 .dynamic = 1,
1140 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
1141 SND_SOC_DPCM_TRIGGER_POST},
1142 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
1143 .ignore_suspend = 1,
1144 /* this dainlink has playback support */
1145 .ignore_pmdown_time = 1,
1146 .codec_dai_name = "snd-soc-dummy-dai",
1147 .codec_name = "snd-soc-dummy",
1148 .be_id = MSM_FRONTEND_DAI_SGLTE,
1149 },
1150 {
1151 .name = "MSM8960 LowLatency",
1152 .stream_name = "MultiMedia5",
1153 .cpu_dai_name = "MultiMedia5",
1154 .platform_name = "msm-lowlatency-pcm-dsp",
1155 .dynamic = 1,
1156 .codec_dai_name = "snd-soc-dummy-dai",
1157 .codec_name = "snd-soc-dummy",
1158 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
1159 SND_SOC_DPCM_TRIGGER_POST},
1160 .ignore_suspend = 1,
1161 /* this dainlink has playback support */
1162 .ignore_pmdown_time = 1,
1163 .be_id = MSM_FRONTEND_DAI_MULTIMEDIA5,
1164 },
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301165 /* Backend DAI Links */
1166 {
1167 .name = LPASS_BE_SLIMBUS_0_RX,
1168 .stream_name = "Slimbus Playback",
1169 .cpu_dai_name = "msm-dai-q6.16384",
1170 .platform_name = "msm-pcm-routing",
1171 .codec_name = "sitar_codec",
1172 .codec_dai_name = "sitar_rx1",
1173 .no_pcm = 1,
1174 .be_id = MSM_BACKEND_DAI_SLIMBUS_0_RX,
1175 .init = &msm8930_audrx_init,
1176 .be_hw_params_fixup = msm8930_slim_0_rx_be_hw_params_fixup,
1177 .ops = &msm8930_be_ops,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001178 .ignore_pmdown_time = 1, /* this dainlink has playback support */
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301179 },
1180 {
1181 .name = LPASS_BE_SLIMBUS_0_TX,
1182 .stream_name = "Slimbus Capture",
1183 .cpu_dai_name = "msm-dai-q6.16385",
1184 .platform_name = "msm-pcm-routing",
1185 .codec_name = "sitar_codec",
1186 .codec_dai_name = "sitar_tx1",
1187 .no_pcm = 1,
1188 .be_id = MSM_BACKEND_DAI_SLIMBUS_0_TX,
1189 .be_hw_params_fixup = msm8930_slim_0_tx_be_hw_params_fixup,
1190 .ops = &msm8930_be_ops,
1191 },
1192 /* Backend BT/FM DAI Links */
1193 {
1194 .name = LPASS_BE_INT_BT_SCO_RX,
1195 .stream_name = "Internal BT-SCO Playback",
1196 .cpu_dai_name = "msm-dai-q6.12288",
1197 .platform_name = "msm-pcm-routing",
1198 .codec_name = "msm-stub-codec.1",
1199 .codec_dai_name = "msm-stub-rx",
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301200 .no_pcm = 1,
1201 .be_id = MSM_BACKEND_DAI_INT_BT_SCO_RX,
1202 .be_hw_params_fixup = msm8930_btsco_be_hw_params_fixup,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001203 .ignore_pmdown_time = 1, /* this dainlink has playback support */
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301204 },
1205 {
1206 .name = LPASS_BE_INT_BT_SCO_TX,
1207 .stream_name = "Internal BT-SCO Capture",
1208 .cpu_dai_name = "msm-dai-q6.12289",
1209 .platform_name = "msm-pcm-routing",
1210 .codec_name = "msm-stub-codec.1",
1211 .codec_dai_name = "msm-stub-tx",
1212 .no_pcm = 1,
1213 .be_id = MSM_BACKEND_DAI_INT_BT_SCO_TX,
1214 .be_hw_params_fixup = msm8930_btsco_be_hw_params_fixup,
1215 },
1216 {
1217 .name = LPASS_BE_INT_FM_RX,
1218 .stream_name = "Internal FM Playback",
1219 .cpu_dai_name = "msm-dai-q6.12292",
1220 .platform_name = "msm-pcm-routing",
1221 .codec_name = "msm-stub-codec.1",
1222 .codec_dai_name = "msm-stub-rx",
1223 .no_pcm = 1,
1224 .be_id = MSM_BACKEND_DAI_INT_FM_RX,
1225 .be_hw_params_fixup = msm8930_be_hw_params_fixup,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001226 .ignore_pmdown_time = 1, /* this dainlink has playback support */
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301227 },
1228 {
1229 .name = LPASS_BE_INT_FM_TX,
1230 .stream_name = "Internal FM Capture",
1231 .cpu_dai_name = "msm-dai-q6.12293",
1232 .platform_name = "msm-pcm-routing",
1233 .codec_name = "msm-stub-codec.1",
1234 .codec_dai_name = "msm-stub-tx",
1235 .no_pcm = 1,
1236 .be_id = MSM_BACKEND_DAI_INT_FM_TX,
1237 .be_hw_params_fixup = msm8930_be_hw_params_fixup,
1238 },
1239 /* HDMI BACK END DAI Link */
1240 {
1241 .name = LPASS_BE_HDMI,
1242 .stream_name = "HDMI Playback",
1243 .cpu_dai_name = "msm-dai-q6-hdmi.8",
1244 .platform_name = "msm-pcm-routing",
1245 .codec_name = "msm-stub-codec.1",
1246 .codec_dai_name = "msm-stub-rx",
1247 .no_pcm = 1,
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301248 .be_id = MSM_BACKEND_DAI_HDMI_RX,
1249 .be_hw_params_fixup = msm8930_hdmi_be_hw_params_fixup,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001250 .ignore_pmdown_time = 1, /* this dainlink has playback support */
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301251 },
1252 /* Backend AFE DAI Links */
1253 {
1254 .name = LPASS_BE_AFE_PCM_RX,
1255 .stream_name = "AFE Playback",
1256 .cpu_dai_name = "msm-dai-q6.224",
1257 .platform_name = "msm-pcm-routing",
1258 .codec_name = "msm-stub-codec.1",
1259 .codec_dai_name = "msm-stub-rx",
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301260 .no_pcm = 1,
1261 .be_id = MSM_BACKEND_DAI_AFE_PCM_RX,
Jayasena Sangaraboina6b4de782012-10-23 16:52:01 -07001262 .be_hw_params_fixup = msm8930_proxy_be_hw_params_fixup,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001263 .ignore_pmdown_time = 1, /* this dainlink has playback support */
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301264 },
1265 {
1266 .name = LPASS_BE_AFE_PCM_TX,
1267 .stream_name = "AFE Capture",
1268 .cpu_dai_name = "msm-dai-q6.225",
1269 .platform_name = "msm-pcm-routing",
1270 .codec_name = "msm-stub-codec.1",
1271 .codec_dai_name = "msm-stub-tx",
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301272 .no_pcm = 1,
1273 .be_id = MSM_BACKEND_DAI_AFE_PCM_TX,
Jayasena Sangaraboina6b4de782012-10-23 16:52:01 -07001274 .be_hw_params_fixup = msm8930_proxy_be_hw_params_fixup,
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301275 },
Bhalchandra Gajare2e0893e2012-05-24 00:39:47 -07001276 /* AUX PCM Backend DAI Links */
1277 {
1278 .name = LPASS_BE_AUXPCM_RX,
1279 .stream_name = "AUX PCM Playback",
1280 .cpu_dai_name = "msm-dai-q6.2",
1281 .platform_name = "msm-pcm-routing",
1282 .codec_name = "msm-stub-codec.1",
1283 .codec_dai_name = "msm-stub-rx",
1284 .no_pcm = 1,
1285 .be_id = MSM_BACKEND_DAI_AUXPCM_RX,
1286 .be_hw_params_fixup = msm8930_auxpcm_be_params_fixup,
1287 .ops = &msm8930_auxpcm_be_ops,
1288 },
1289 {
1290 .name = LPASS_BE_AUXPCM_TX,
1291 .stream_name = "AUX PCM Capture",
1292 .cpu_dai_name = "msm-dai-q6.3",
1293 .platform_name = "msm-pcm-routing",
1294 .codec_name = "msm-stub-codec.1",
1295 .codec_dai_name = "msm-stub-tx",
1296 .no_pcm = 1,
1297 .be_id = MSM_BACKEND_DAI_AUXPCM_TX,
1298 .be_hw_params_fixup = msm8930_auxpcm_be_params_fixup,
Kuirong Wang892c9ad2012-09-20 11:43:17 -07001299 .ops = &msm8930_auxpcm_be_ops,
Bhalchandra Gajare2e0893e2012-05-24 00:39:47 -07001300 },
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301301 /* Incall Music BACK END DAI Link */
1302 {
1303 .name = LPASS_BE_VOICE_PLAYBACK_TX,
1304 .stream_name = "Voice Farend Playback",
1305 .cpu_dai_name = "msm-dai-q6.32773",
1306 .platform_name = "msm-pcm-routing",
1307 .codec_name = "msm-stub-codec.1",
1308 .codec_dai_name = "msm-stub-rx",
1309 .no_pcm = 1,
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301310 .be_id = MSM_BACKEND_DAI_VOICE_PLAYBACK_TX,
1311 .be_hw_params_fixup = msm8930_be_hw_params_fixup,
1312 },
1313 /* Incall Record Uplink BACK END DAI Link */
1314 {
1315 .name = LPASS_BE_INCALL_RECORD_TX,
1316 .stream_name = "Voice Uplink Capture",
1317 .cpu_dai_name = "msm-dai-q6.32772",
1318 .platform_name = "msm-pcm-routing",
1319 .codec_name = "msm-stub-codec.1",
1320 .codec_dai_name = "msm-stub-tx",
1321 .no_pcm = 1,
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301322 .be_id = MSM_BACKEND_DAI_INCALL_RECORD_TX,
1323 .be_hw_params_fixup = msm8930_be_hw_params_fixup,
1324 },
1325 /* Incall Record Downlink BACK END DAI Link */
1326 {
1327 .name = LPASS_BE_INCALL_RECORD_RX,
1328 .stream_name = "Voice Downlink Capture",
1329 .cpu_dai_name = "msm-dai-q6.32771",
1330 .platform_name = "msm-pcm-routing",
1331 .codec_name = "msm-stub-codec.1",
1332 .codec_dai_name = "msm-stub-tx",
1333 .no_pcm = 1,
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301334 .be_id = MSM_BACKEND_DAI_INCALL_RECORD_RX,
1335 .be_hw_params_fixup = msm8930_be_hw_params_fixup,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001336 .ignore_pmdown_time = 1, /* this dainlink has playback support */
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301337 },
1338};
1339
1340struct snd_soc_card snd_soc_card_msm8930 = {
1341 .name = "msm8930-sitar-snd-card",
1342 .dai_link = msm8930_dai,
1343 .num_links = ARRAY_SIZE(msm8930_dai),
Steve Mucklef132c6c2012-06-06 18:30:57 -07001344 .controls = sitar_msm8930_controls,
1345 .num_controls = ARRAY_SIZE(sitar_msm8930_controls),
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301346};
1347
1348static struct platform_device *msm8930_snd_device;
1349
1350static int msm8930_configure_headset_mic_gpios(void)
1351{
1352 int ret;
1353 ret = gpio_request(80, "US_EURO_SWITCH");
1354 if (ret) {
1355 pr_err("%s: Failed to request gpio 80\n", __func__);
1356 return ret;
1357 }
1358 ret = gpio_direction_output(80, 0);
1359 if (ret) {
1360 pr_err("%s: Unable to set direction\n", __func__);
1361 gpio_free(80);
1362 }
1363 msm8930_headset_gpios_configured = 0;
1364 return 0;
1365}
1366static void msm8930_free_headset_mic_gpios(void)
1367{
1368 if (msm8930_headset_gpios_configured)
1369 gpio_free(80);
1370}
1371
1372static int __init msm8930_audio_init(void)
1373{
1374 int ret;
1375
Stepan Moskovchenkoc6a603a2012-09-21 20:32:17 -07001376 if (!soc_class_is_msm8930()) {
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301377 pr_err("%s: Not the right machine type\n", __func__);
1378 return -ENODEV ;
1379 }
Bhalchandra Gajare466aafe2012-05-02 17:55:26 -07001380 mbhc_cfg.calibration = def_sitar_mbhc_cal();
1381 if (!mbhc_cfg.calibration) {
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -08001382 pr_err("Calibration data allocation failed\n");
1383 return -ENOMEM;
1384 }
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301385
1386 msm8930_snd_device = platform_device_alloc("soc-audio", 0);
1387 if (!msm8930_snd_device) {
1388 pr_err("Platform device allocation failed\n");
Bhalchandra Gajare466aafe2012-05-02 17:55:26 -07001389 kfree(mbhc_cfg.calibration);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301390 return -ENOMEM;
1391 }
1392
1393 platform_set_drvdata(msm8930_snd_device, &snd_soc_card_msm8930);
1394 ret = platform_device_add(msm8930_snd_device);
1395 if (ret) {
1396 platform_device_put(msm8930_snd_device);
Bhalchandra Gajare466aafe2012-05-02 17:55:26 -07001397 kfree(mbhc_cfg.calibration);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301398 return ret;
1399 }
1400
1401 if (msm8930_configure_headset_mic_gpios()) {
1402 pr_err("%s Fail to configure headset mic gpios\n", __func__);
1403 msm8930_headset_gpios_configured = 0;
1404 } else
1405 msm8930_headset_gpios_configured = 1;
1406
Kuirong Wang892c9ad2012-09-20 11:43:17 -07001407 atomic_set(&auxpcm_rsc_ref, 0);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301408 return ret;
1409
1410}
1411module_init(msm8930_audio_init);
1412
1413static void __exit msm8930_audio_exit(void)
1414{
Stepan Moskovchenkoc6a603a2012-09-21 20:32:17 -07001415 if (!soc_class_is_msm8930()) {
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301416 pr_err("%s: Not the right machine type\n", __func__);
1417 return ;
1418 }
1419 msm8930_free_headset_mic_gpios();
1420 platform_device_unregister(msm8930_snd_device);
Bhalchandra Gajare466aafe2012-05-02 17:55:26 -07001421 kfree(mbhc_cfg.calibration);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301422}
1423module_exit(msm8930_audio_exit);
1424
1425MODULE_DESCRIPTION("ALSA SoC MSM8930");
1426MODULE_LICENSE("GPL v2");