blob: deef8ac60974bb74b1af913e3ef173190e47801b [file] [log] [blame]
Kiran Kandi9a2c62a82011-12-07 13:13:26 -08001/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002 *
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#include <linux/module.h>
13#include <linux/init.h>
Bradley Rubin229c6a52011-07-12 16:18:48 -070014#include <linux/firmware.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070015#include <linux/slab.h>
16#include <linux/platform_device.h>
Santosh Mardie15e2302011-11-15 10:39:23 +053017#include <linux/device.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070018#include <linux/printk.h>
19#include <linux/ratelimit.h>
Bradley Rubincb3950a2011-08-18 13:07:26 -070020#include <linux/debugfs.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070021#include <linux/mfd/wcd9310/core.h>
22#include <linux/mfd/wcd9310/registers.h>
Patrick Lai3043fba2011-08-01 14:15:57 -070023#include <linux/mfd/wcd9310/pdata.h>
Santosh Mardie15e2302011-11-15 10:39:23 +053024#include <sound/pcm.h>
25#include <sound/pcm_params.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070026#include <sound/jack.h>
27#include <sound/soc.h>
28#include <sound/soc-dapm.h>
29#include <sound/tlv.h>
30#include <linux/bitops.h>
31#include <linux/delay.h>
32#include "wcd9310.h"
33
Bhalchandra Gajare9a901fd2011-08-01 10:07:15 -070034#define WCD9310_RATES (SNDRV_PCM_RATE_8000|SNDRV_PCM_RATE_16000|\
35 SNDRV_PCM_RATE_32000|SNDRV_PCM_RATE_48000)
36
37#define NUM_DECIMATORS 10
38#define NUM_INTERPOLATORS 7
39#define BITS_PER_REG 8
40#define TABLA_RX_DAI_ID 1
41#define TABLA_TX_DAI_ID 2
Bhalchandra Gajare19d9c132011-11-18 14:57:08 -080042#define TABLA_CFILT_FAST_MODE 0x00
43#define TABLA_CFILT_SLOW_MODE 0x40
Bhalchandra Gajare9a901fd2011-08-01 10:07:15 -070044
Patrick Lai49efeac2011-11-03 11:01:12 -070045#define TABLA_JACK_MASK (SND_JACK_HEADSET | SND_JACK_OC_HPHL | SND_JACK_OC_HPHR)
46
Santosh Mardie15e2302011-11-15 10:39:23 +053047#define TABLA_I2S_MASTER_MODE_MASK 0x08
48
Patrick Laic7cae882011-11-18 11:52:49 -080049#define TABLA_OCP_ATTEMPT 1
50
Joonwoo Park0976d012011-12-22 11:48:18 -080051#define TABLA_MCLK_RATE_12288KHZ 12288000
52#define TABLA_MCLK_RATE_9600KHZ 9600000
53
Joonwoo Parkf4267c22012-01-10 13:25:24 -080054#define TABLA_FAKE_INS_THRESHOLD_MS 2500
55
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070056static const DECLARE_TLV_DB_SCALE(digital_gain, 0, 1, 0);
57static const DECLARE_TLV_DB_SCALE(line_gain, 0, 7, 1);
58static const DECLARE_TLV_DB_SCALE(analog_gain, 0, 25, 1);
59
60enum tabla_bandgap_type {
61 TABLA_BANDGAP_OFF = 0,
62 TABLA_BANDGAP_AUDIO_MODE,
63 TABLA_BANDGAP_MBHC_MODE,
64};
65
Bhalchandra Gajare02d90cd2011-09-30 16:14:00 -070066struct mbhc_micbias_regs {
67 u16 cfilt_val;
68 u16 cfilt_ctl;
69 u16 mbhc_reg;
70 u16 int_rbias;
71 u16 ctl_reg;
Bhalchandra Gajare19d9c132011-11-18 14:57:08 -080072 u8 cfilt_sel;
Bhalchandra Gajare02d90cd2011-09-30 16:14:00 -070073};
74
Ben Romberger1f045a72011-11-04 10:14:57 -070075/* Codec supports 2 IIR filters */
76enum {
77 IIR1 = 0,
78 IIR2,
79 IIR_MAX,
80};
81/* Codec supports 5 bands */
82enum {
83 BAND1 = 0,
84 BAND2,
85 BAND3,
86 BAND4,
87 BAND5,
88 BAND_MAX,
89};
90
Joonwoo Parka9444452011-12-08 18:48:27 -080091/* Flags to track of PA and DAC state.
92 * PA and DAC should be tracked separately as AUXPGA loopback requires
93 * only PA to be turned on without DAC being on. */
94enum tabla_priv_ack_flags {
95 TABLA_HPHL_PA_OFF_ACK = 0,
96 TABLA_HPHR_PA_OFF_ACK,
97 TABLA_HPHL_DAC_OFF_ACK,
98 TABLA_HPHR_DAC_OFF_ACK
99};
100
Joonwoo Park0976d012011-12-22 11:48:18 -0800101/* Data used by MBHC */
102struct mbhc_internal_cal_data {
103 u16 dce_z;
104 u16 dce_mb;
105 u16 sta_z;
106 u16 sta_mb;
107 u32 t_dce;
108 u32 t_sta;
109 u32 micb_mv;
110 u16 v_ins_hu;
111 u16 v_ins_h;
112 u16 v_b1_hu;
113 u16 v_b1_h;
114 u16 v_b1_huc;
115 u16 v_brh;
116 u16 v_brl;
117 u16 v_no_mic;
118 u8 nready;
119 u8 npoll;
120 u8 nbounce_wait;
121};
122
Bradley Rubin229c6a52011-07-12 16:18:48 -0700123struct tabla_priv {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700124 struct snd_soc_codec *codec;
Joonwoo Park0976d012011-12-22 11:48:18 -0800125 u32 mclk_freq;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700126 u32 adc_count;
Patrick Lai3043fba2011-08-01 14:15:57 -0700127 u32 cfilt1_cnt;
128 u32 cfilt2_cnt;
129 u32 cfilt3_cnt;
Kiran Kandi6fae8bf2011-08-15 10:36:42 -0700130 u32 rx_bias_count;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700131 enum tabla_bandgap_type bandgap_type;
Kiran Kandi6fae8bf2011-08-15 10:36:42 -0700132 bool mclk_enabled;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700133 bool clock_active;
134 bool config_mode_active;
135 bool mbhc_polling_active;
Joonwoo Parkf4267c22012-01-10 13:25:24 -0800136 unsigned long mbhc_fake_ins_start;
Bradley Rubincb1e2732011-06-23 16:49:20 -0700137 int buttons_pressed;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700138
Joonwoo Park0976d012011-12-22 11:48:18 -0800139 enum tabla_micbias_num micbias;
140 /* void* calibration contains:
141 * struct tabla_mbhc_general_cfg generic;
142 * struct tabla_mbhc_plug_detect_cfg plug_det;
143 * struct tabla_mbhc_plug_type_cfg plug_type;
144 * struct tabla_mbhc_btn_detect_cfg btn_det;
145 * struct tabla_mbhc_imped_detect_cfg imped_det;
146 * Note: various size depends on btn_det->num_btn
147 */
148 void *calibration;
149 struct mbhc_internal_cal_data mbhc_data;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700150
Bradley Rubincb1e2732011-06-23 16:49:20 -0700151 struct snd_soc_jack *headset_jack;
152 struct snd_soc_jack *button_jack;
Bradley Rubin229c6a52011-07-12 16:18:48 -0700153
Patrick Lai3043fba2011-08-01 14:15:57 -0700154 struct tabla_pdata *pdata;
Bradley Rubina7096d02011-08-03 18:29:02 -0700155 u32 anc_slot;
Bradley Rubincb3950a2011-08-18 13:07:26 -0700156
157 bool no_mic_headset_override;
Bhalchandra Gajare0a792b12011-09-06 16:36:58 -0700158 /* Delayed work to report long button press */
159 struct delayed_work btn0_dwork;
Bhalchandra Gajare02d90cd2011-09-30 16:14:00 -0700160
161 struct mbhc_micbias_regs mbhc_bias_regs;
Bhalchandra Gajared9ebb6c2011-10-03 19:54:41 -0700162 u8 cfilt_k_value;
163 bool mbhc_micbias_switched;
Patrick Lai49efeac2011-11-03 11:01:12 -0700164
Joonwoo Parka9444452011-12-08 18:48:27 -0800165 /* track PA/DAC state */
166 unsigned long hph_pa_dac_state;
167
Santosh Mardie15e2302011-11-15 10:39:23 +0530168 /*track tabla interface type*/
169 u8 intf_type;
170
Patrick Lai49efeac2011-11-03 11:01:12 -0700171 u32 hph_status; /* track headhpone status */
172 /* define separate work for left and right headphone OCP to avoid
173 * additional checking on which OCP event to report so no locking
174 * to ensure synchronization is required
175 */
176 struct work_struct hphlocp_work; /* reporting left hph ocp off */
177 struct work_struct hphrocp_work; /* reporting right hph ocp off */
Joonwoo Park8b1f0982011-12-08 17:12:45 -0800178
179 /* pm_cnt holds number of sleep lock holders + 1
180 * so if pm_cnt is 1 system is sleep-able. */
181 atomic_t pm_cnt;
182 wait_queue_head_t pm_wq;
Patrick Laic7cae882011-11-18 11:52:49 -0800183
184 u8 hphlocp_cnt; /* headphone left ocp retry */
185 u8 hphrocp_cnt; /* headphone right ocp retry */
Joonwoo Park0976d012011-12-22 11:48:18 -0800186
187 /* Callback function to enable MCLK */
188 int (*mclk_cb) (struct snd_soc_codec*, int);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700189};
190
Bradley Rubincb3950a2011-08-18 13:07:26 -0700191#ifdef CONFIG_DEBUG_FS
192struct tabla_priv *debug_tabla_priv;
193#endif
194
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700195static int tabla_codec_enable_charge_pump(struct snd_soc_dapm_widget *w,
196 struct snd_kcontrol *kcontrol, int event)
197{
198 struct snd_soc_codec *codec = w->codec;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700199
200 pr_debug("%s %d\n", __func__, event);
201 switch (event) {
202 case SND_SOC_DAPM_POST_PMU:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700203 snd_soc_update_bits(codec, TABLA_A_CDC_CLK_OTHR_CTL, 0x01,
204 0x01);
205 snd_soc_update_bits(codec, TABLA_A_CDC_CLSG_CTL, 0x08, 0x08);
206 usleep_range(200, 200);
207 snd_soc_update_bits(codec, TABLA_A_CP_STATIC, 0x10, 0x00);
208 break;
209 case SND_SOC_DAPM_PRE_PMD:
210 snd_soc_update_bits(codec, TABLA_A_CDC_CLK_OTHR_RESET_CTL, 0x10,
211 0x10);
212 usleep_range(20, 20);
213 snd_soc_update_bits(codec, TABLA_A_CP_STATIC, 0x08, 0x08);
214 snd_soc_update_bits(codec, TABLA_A_CP_STATIC, 0x10, 0x10);
215 snd_soc_update_bits(codec, TABLA_A_CDC_CLSG_CTL, 0x08, 0x00);
216 snd_soc_update_bits(codec, TABLA_A_CDC_CLK_OTHR_CTL, 0x01,
217 0x00);
218 snd_soc_update_bits(codec, TABLA_A_CP_STATIC, 0x08, 0x00);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700219 break;
220 }
221 return 0;
222}
223
Bradley Rubina7096d02011-08-03 18:29:02 -0700224static int tabla_get_anc_slot(struct snd_kcontrol *kcontrol,
225 struct snd_ctl_elem_value *ucontrol)
226{
227 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
228 struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
229 ucontrol->value.integer.value[0] = tabla->anc_slot;
230 return 0;
231}
232
233static int tabla_put_anc_slot(struct snd_kcontrol *kcontrol,
234 struct snd_ctl_elem_value *ucontrol)
235{
236 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
237 struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
238 tabla->anc_slot = ucontrol->value.integer.value[0];
239 return 0;
240}
241
Kiran Kandid2d86b52011-09-09 17:44:28 -0700242static int tabla_pa_gain_get(struct snd_kcontrol *kcontrol,
243 struct snd_ctl_elem_value *ucontrol)
244{
245 u8 ear_pa_gain;
246 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
247
248 ear_pa_gain = snd_soc_read(codec, TABLA_A_RX_EAR_GAIN);
249
250 ear_pa_gain = ear_pa_gain >> 5;
251
252 if (ear_pa_gain == 0x00) {
253 ucontrol->value.integer.value[0] = 0;
254 } else if (ear_pa_gain == 0x04) {
255 ucontrol->value.integer.value[0] = 1;
256 } else {
257 pr_err("%s: ERROR: Unsupported Ear Gain = 0x%x\n",
258 __func__, ear_pa_gain);
259 return -EINVAL;
260 }
261
262 pr_debug("%s: ear_pa_gain = 0x%x\n", __func__, ear_pa_gain);
263
264 return 0;
265}
266
267static int tabla_pa_gain_put(struct snd_kcontrol *kcontrol,
268 struct snd_ctl_elem_value *ucontrol)
269{
270 u8 ear_pa_gain;
271 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
272
273 pr_debug("%s: ucontrol->value.integer.value[0] = %ld\n", __func__,
274 ucontrol->value.integer.value[0]);
275
276 switch (ucontrol->value.integer.value[0]) {
277 case 0:
278 ear_pa_gain = 0x00;
279 break;
280 case 1:
281 ear_pa_gain = 0x80;
282 break;
283 default:
284 return -EINVAL;
285 }
286
287 snd_soc_update_bits(codec, TABLA_A_RX_EAR_GAIN, 0xE0, ear_pa_gain);
288 return 0;
289}
290
Ben Romberger1f045a72011-11-04 10:14:57 -0700291static int tabla_get_iir_enable_audio_mixer(
292 struct snd_kcontrol *kcontrol,
293 struct snd_ctl_elem_value *ucontrol)
294{
295 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
296 int iir_idx = ((struct soc_multi_mixer_control *)
297 kcontrol->private_value)->reg;
298 int band_idx = ((struct soc_multi_mixer_control *)
299 kcontrol->private_value)->shift;
300
301 ucontrol->value.integer.value[0] =
302 snd_soc_read(codec, (TABLA_A_CDC_IIR1_CTL + 16 * iir_idx)) &
303 (1 << band_idx);
304
305 pr_debug("%s: IIR #%d band #%d enable %d\n", __func__,
306 iir_idx, band_idx,
307 (uint32_t)ucontrol->value.integer.value[0]);
308 return 0;
309}
310
311static int tabla_put_iir_enable_audio_mixer(
312 struct snd_kcontrol *kcontrol,
313 struct snd_ctl_elem_value *ucontrol)
314{
315 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
316 int iir_idx = ((struct soc_multi_mixer_control *)
317 kcontrol->private_value)->reg;
318 int band_idx = ((struct soc_multi_mixer_control *)
319 kcontrol->private_value)->shift;
320 int value = ucontrol->value.integer.value[0];
321
322 /* Mask first 5 bits, 6-8 are reserved */
323 snd_soc_update_bits(codec, (TABLA_A_CDC_IIR1_CTL + 16 * iir_idx),
324 (1 << band_idx), (value << band_idx));
325
326 pr_debug("%s: IIR #%d band #%d enable %d\n", __func__,
327 iir_idx, band_idx, value);
328 return 0;
329}
330static uint32_t get_iir_band_coeff(struct snd_soc_codec *codec,
331 int iir_idx, int band_idx,
332 int coeff_idx)
333{
334 /* Address does not automatically update if reading */
335 snd_soc_update_bits(codec,
336 (TABLA_A_CDC_IIR1_COEF_B1_CTL + 16 * iir_idx),
337 0x1F, band_idx * BAND_MAX + coeff_idx);
338
339 /* Mask bits top 2 bits since they are reserved */
340 return ((snd_soc_read(codec,
341 (TABLA_A_CDC_IIR1_COEF_B2_CTL + 16 * iir_idx)) << 24) |
342 (snd_soc_read(codec,
343 (TABLA_A_CDC_IIR1_COEF_B3_CTL + 16 * iir_idx)) << 16) |
344 (snd_soc_read(codec,
345 (TABLA_A_CDC_IIR1_COEF_B4_CTL + 16 * iir_idx)) << 8) |
346 (snd_soc_read(codec,
347 (TABLA_A_CDC_IIR1_COEF_B5_CTL + 16 * iir_idx)))) &
348 0x3FFFFFFF;
349}
350
351static int tabla_get_iir_band_audio_mixer(
352 struct snd_kcontrol *kcontrol,
353 struct snd_ctl_elem_value *ucontrol)
354{
355 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
356 int iir_idx = ((struct soc_multi_mixer_control *)
357 kcontrol->private_value)->reg;
358 int band_idx = ((struct soc_multi_mixer_control *)
359 kcontrol->private_value)->shift;
360
361 ucontrol->value.integer.value[0] =
362 get_iir_band_coeff(codec, iir_idx, band_idx, 0);
363 ucontrol->value.integer.value[1] =
364 get_iir_band_coeff(codec, iir_idx, band_idx, 1);
365 ucontrol->value.integer.value[2] =
366 get_iir_band_coeff(codec, iir_idx, band_idx, 2);
367 ucontrol->value.integer.value[3] =
368 get_iir_band_coeff(codec, iir_idx, band_idx, 3);
369 ucontrol->value.integer.value[4] =
370 get_iir_band_coeff(codec, iir_idx, band_idx, 4);
371
372 pr_debug("%s: IIR #%d band #%d b0 = 0x%x\n"
373 "%s: IIR #%d band #%d b1 = 0x%x\n"
374 "%s: IIR #%d band #%d b2 = 0x%x\n"
375 "%s: IIR #%d band #%d a1 = 0x%x\n"
376 "%s: IIR #%d band #%d a2 = 0x%x\n",
377 __func__, iir_idx, band_idx,
378 (uint32_t)ucontrol->value.integer.value[0],
379 __func__, iir_idx, band_idx,
380 (uint32_t)ucontrol->value.integer.value[1],
381 __func__, iir_idx, band_idx,
382 (uint32_t)ucontrol->value.integer.value[2],
383 __func__, iir_idx, band_idx,
384 (uint32_t)ucontrol->value.integer.value[3],
385 __func__, iir_idx, band_idx,
386 (uint32_t)ucontrol->value.integer.value[4]);
387 return 0;
388}
389
390static void set_iir_band_coeff(struct snd_soc_codec *codec,
391 int iir_idx, int band_idx,
392 int coeff_idx, uint32_t value)
393{
394 /* Mask top 3 bits, 6-8 are reserved */
395 /* Update address manually each time */
396 snd_soc_update_bits(codec,
397 (TABLA_A_CDC_IIR1_COEF_B1_CTL + 16 * iir_idx),
398 0x1F, band_idx * BAND_MAX + coeff_idx);
399
400 /* Mask top 2 bits, 7-8 are reserved */
401 snd_soc_update_bits(codec,
402 (TABLA_A_CDC_IIR1_COEF_B2_CTL + 16 * iir_idx),
403 0x3F, (value >> 24) & 0x3F);
404
405 /* Isolate 8bits at a time */
406 snd_soc_update_bits(codec,
407 (TABLA_A_CDC_IIR1_COEF_B3_CTL + 16 * iir_idx),
408 0xFF, (value >> 16) & 0xFF);
409
410 snd_soc_update_bits(codec,
411 (TABLA_A_CDC_IIR1_COEF_B4_CTL + 16 * iir_idx),
412 0xFF, (value >> 8) & 0xFF);
413
414 snd_soc_update_bits(codec,
415 (TABLA_A_CDC_IIR1_COEF_B5_CTL + 16 * iir_idx),
416 0xFF, value & 0xFF);
417}
418
419static int tabla_put_iir_band_audio_mixer(
420 struct snd_kcontrol *kcontrol,
421 struct snd_ctl_elem_value *ucontrol)
422{
423 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
424 int iir_idx = ((struct soc_multi_mixer_control *)
425 kcontrol->private_value)->reg;
426 int band_idx = ((struct soc_multi_mixer_control *)
427 kcontrol->private_value)->shift;
428
429 set_iir_band_coeff(codec, iir_idx, band_idx, 0,
430 ucontrol->value.integer.value[0]);
431 set_iir_band_coeff(codec, iir_idx, band_idx, 1,
432 ucontrol->value.integer.value[1]);
433 set_iir_band_coeff(codec, iir_idx, band_idx, 2,
434 ucontrol->value.integer.value[2]);
435 set_iir_band_coeff(codec, iir_idx, band_idx, 3,
436 ucontrol->value.integer.value[3]);
437 set_iir_band_coeff(codec, iir_idx, band_idx, 4,
438 ucontrol->value.integer.value[4]);
439
440 pr_debug("%s: IIR #%d band #%d b0 = 0x%x\n"
441 "%s: IIR #%d band #%d b1 = 0x%x\n"
442 "%s: IIR #%d band #%d b2 = 0x%x\n"
443 "%s: IIR #%d band #%d a1 = 0x%x\n"
444 "%s: IIR #%d band #%d a2 = 0x%x\n",
445 __func__, iir_idx, band_idx,
446 get_iir_band_coeff(codec, iir_idx, band_idx, 0),
447 __func__, iir_idx, band_idx,
448 get_iir_band_coeff(codec, iir_idx, band_idx, 1),
449 __func__, iir_idx, band_idx,
450 get_iir_band_coeff(codec, iir_idx, band_idx, 2),
451 __func__, iir_idx, band_idx,
452 get_iir_band_coeff(codec, iir_idx, band_idx, 3),
453 __func__, iir_idx, band_idx,
454 get_iir_band_coeff(codec, iir_idx, band_idx, 4));
455 return 0;
456}
457
Kiran Kandid2d86b52011-09-09 17:44:28 -0700458static const char *tabla_ear_pa_gain_text[] = {"POS_6_DB", "POS_2_DB"};
459static const struct soc_enum tabla_ear_pa_gain_enum[] = {
460 SOC_ENUM_SINGLE_EXT(2, tabla_ear_pa_gain_text),
461};
462
Santosh Mardi024010f2011-10-18 06:27:21 +0530463/*cut of frequency for high pass filter*/
464static const char *cf_text[] = {
465 "MIN_3DB_4Hz", "MIN_3DB_75Hz", "MIN_3DB_150Hz"
466};
467
468static const struct soc_enum cf_dec1_enum =
469 SOC_ENUM_SINGLE(TABLA_A_CDC_TX1_MUX_CTL, 4, 3, cf_text);
470
471static const struct soc_enum cf_dec2_enum =
472 SOC_ENUM_SINGLE(TABLA_A_CDC_TX2_MUX_CTL, 4, 3, cf_text);
473
474static const struct soc_enum cf_dec3_enum =
475 SOC_ENUM_SINGLE(TABLA_A_CDC_TX3_MUX_CTL, 4, 3, cf_text);
476
477static const struct soc_enum cf_dec4_enum =
478 SOC_ENUM_SINGLE(TABLA_A_CDC_TX4_MUX_CTL, 4, 3, cf_text);
479
480static const struct soc_enum cf_dec5_enum =
481 SOC_ENUM_SINGLE(TABLA_A_CDC_TX5_MUX_CTL, 4, 3, cf_text);
482
483static const struct soc_enum cf_dec6_enum =
484 SOC_ENUM_SINGLE(TABLA_A_CDC_TX6_MUX_CTL, 4, 3, cf_text);
485
486static const struct soc_enum cf_dec7_enum =
487 SOC_ENUM_SINGLE(TABLA_A_CDC_TX7_MUX_CTL, 4, 3, cf_text);
488
489static const struct soc_enum cf_dec8_enum =
490 SOC_ENUM_SINGLE(TABLA_A_CDC_TX8_MUX_CTL, 4, 3, cf_text);
491
492static const struct soc_enum cf_dec9_enum =
493 SOC_ENUM_SINGLE(TABLA_A_CDC_TX9_MUX_CTL, 4, 3, cf_text);
494
495static const struct soc_enum cf_dec10_enum =
496 SOC_ENUM_SINGLE(TABLA_A_CDC_TX10_MUX_CTL, 4, 3, cf_text);
497
498static const struct soc_enum cf_rxmix1_enum =
499 SOC_ENUM_SINGLE(TABLA_A_CDC_RX1_B4_CTL, 1, 3, cf_text);
500
501static const struct soc_enum cf_rxmix2_enum =
502 SOC_ENUM_SINGLE(TABLA_A_CDC_RX2_B4_CTL, 1, 3, cf_text);
503
504static const struct soc_enum cf_rxmix3_enum =
505 SOC_ENUM_SINGLE(TABLA_A_CDC_RX3_B4_CTL, 1, 3, cf_text);
506
507static const struct soc_enum cf_rxmix4_enum =
508 SOC_ENUM_SINGLE(TABLA_A_CDC_RX4_B4_CTL, 1, 3, cf_text);
509
510static const struct soc_enum cf_rxmix5_enum =
511 SOC_ENUM_SINGLE(TABLA_A_CDC_RX5_B4_CTL, 1, 3, cf_text)
512;
513static const struct soc_enum cf_rxmix6_enum =
514 SOC_ENUM_SINGLE(TABLA_A_CDC_RX6_B4_CTL, 1, 3, cf_text);
515
516static const struct soc_enum cf_rxmix7_enum =
517 SOC_ENUM_SINGLE(TABLA_A_CDC_RX7_B4_CTL, 1, 3, cf_text);
518
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700519static const struct snd_kcontrol_new tabla_snd_controls[] = {
Kiran Kandid2d86b52011-09-09 17:44:28 -0700520
521 SOC_ENUM_EXT("EAR PA Gain", tabla_ear_pa_gain_enum[0],
522 tabla_pa_gain_get, tabla_pa_gain_put),
523
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700524 SOC_SINGLE_TLV("LINEOUT1 Volume", TABLA_A_RX_LINE_1_GAIN, 0, 12, 1,
525 line_gain),
Bradley Rubin74a9b4a2011-06-13 15:03:43 -0700526 SOC_SINGLE_TLV("LINEOUT2 Volume", TABLA_A_RX_LINE_2_GAIN, 0, 12, 1,
527 line_gain),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700528 SOC_SINGLE_TLV("LINEOUT3 Volume", TABLA_A_RX_LINE_3_GAIN, 0, 12, 1,
529 line_gain),
Bradley Rubin74a9b4a2011-06-13 15:03:43 -0700530 SOC_SINGLE_TLV("LINEOUT4 Volume", TABLA_A_RX_LINE_4_GAIN, 0, 12, 1,
531 line_gain),
Bhalchandra Gajare0a8ad172011-08-12 13:32:22 -0700532 SOC_SINGLE_TLV("LINEOUT5 Volume", TABLA_A_RX_LINE_5_GAIN, 0, 12, 1,
533 line_gain),
Bradley Rubin74a9b4a2011-06-13 15:03:43 -0700534
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700535 SOC_SINGLE_TLV("HPHL Volume", TABLA_A_RX_HPH_L_GAIN, 0, 12, 1,
536 line_gain),
537 SOC_SINGLE_TLV("HPHR Volume", TABLA_A_RX_HPH_R_GAIN, 0, 12, 1,
538 line_gain),
539
Bradley Rubin410383f2011-07-22 13:44:23 -0700540 SOC_SINGLE_S8_TLV("RX1 Digital Volume", TABLA_A_CDC_RX1_VOL_CTL_B2_CTL,
541 -84, 40, digital_gain),
542 SOC_SINGLE_S8_TLV("RX2 Digital Volume", TABLA_A_CDC_RX2_VOL_CTL_B2_CTL,
543 -84, 40, digital_gain),
544 SOC_SINGLE_S8_TLV("RX3 Digital Volume", TABLA_A_CDC_RX3_VOL_CTL_B2_CTL,
545 -84, 40, digital_gain),
546 SOC_SINGLE_S8_TLV("RX4 Digital Volume", TABLA_A_CDC_RX4_VOL_CTL_B2_CTL,
547 -84, 40, digital_gain),
548 SOC_SINGLE_S8_TLV("RX5 Digital Volume", TABLA_A_CDC_RX5_VOL_CTL_B2_CTL,
549 -84, 40, digital_gain),
550 SOC_SINGLE_S8_TLV("RX6 Digital Volume", TABLA_A_CDC_RX6_VOL_CTL_B2_CTL,
551 -84, 40, digital_gain),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700552
Bradley Rubin410383f2011-07-22 13:44:23 -0700553 SOC_SINGLE_S8_TLV("DEC1 Volume", TABLA_A_CDC_TX1_VOL_CTL_GAIN, -84, 40,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700554 digital_gain),
Bradley Rubin410383f2011-07-22 13:44:23 -0700555 SOC_SINGLE_S8_TLV("DEC2 Volume", TABLA_A_CDC_TX2_VOL_CTL_GAIN, -84, 40,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700556 digital_gain),
Bradley Rubin410383f2011-07-22 13:44:23 -0700557 SOC_SINGLE_S8_TLV("DEC3 Volume", TABLA_A_CDC_TX3_VOL_CTL_GAIN, -84, 40,
558 digital_gain),
559 SOC_SINGLE_S8_TLV("DEC4 Volume", TABLA_A_CDC_TX4_VOL_CTL_GAIN, -84, 40,
560 digital_gain),
561 SOC_SINGLE_S8_TLV("DEC5 Volume", TABLA_A_CDC_TX5_VOL_CTL_GAIN, -84, 40,
562 digital_gain),
563 SOC_SINGLE_S8_TLV("DEC6 Volume", TABLA_A_CDC_TX6_VOL_CTL_GAIN, -84, 40,
564 digital_gain),
565 SOC_SINGLE_S8_TLV("DEC7 Volume", TABLA_A_CDC_TX7_VOL_CTL_GAIN, -84, 40,
566 digital_gain),
567 SOC_SINGLE_S8_TLV("DEC8 Volume", TABLA_A_CDC_TX8_VOL_CTL_GAIN, -84, 40,
568 digital_gain),
569 SOC_SINGLE_S8_TLV("DEC9 Volume", TABLA_A_CDC_TX9_VOL_CTL_GAIN, -84, 40,
570 digital_gain),
571 SOC_SINGLE_S8_TLV("DEC10 Volume", TABLA_A_CDC_TX10_VOL_CTL_GAIN, -84,
572 40, digital_gain),
Patrick Lai29006372011-09-28 17:57:42 -0700573 SOC_SINGLE_S8_TLV("IIR1 INP1 Volume", TABLA_A_CDC_IIR1_GAIN_B1_CTL, -84,
574 40, digital_gain),
575 SOC_SINGLE_S8_TLV("IIR1 INP2 Volume", TABLA_A_CDC_IIR1_GAIN_B2_CTL, -84,
576 40, digital_gain),
577 SOC_SINGLE_S8_TLV("IIR1 INP3 Volume", TABLA_A_CDC_IIR1_GAIN_B3_CTL, -84,
578 40, digital_gain),
579 SOC_SINGLE_S8_TLV("IIR1 INP4 Volume", TABLA_A_CDC_IIR1_GAIN_B4_CTL, -84,
580 40, digital_gain),
Bhalchandra Gajare0d77e1b2011-07-08 10:54:14 -0700581 SOC_SINGLE_TLV("ADC1 Volume", TABLA_A_TX_1_2_EN, 5, 3, 0, analog_gain),
582 SOC_SINGLE_TLV("ADC2 Volume", TABLA_A_TX_1_2_EN, 1, 3, 0, analog_gain),
Bhalchandra Gajarecc6ffa02011-07-14 18:35:41 -0700583 SOC_SINGLE_TLV("ADC3 Volume", TABLA_A_TX_3_4_EN, 5, 3, 0, analog_gain),
584 SOC_SINGLE_TLV("ADC4 Volume", TABLA_A_TX_3_4_EN, 1, 3, 0, analog_gain),
Bhalchandra Gajare0d77e1b2011-07-08 10:54:14 -0700585 SOC_SINGLE_TLV("ADC5 Volume", TABLA_A_TX_5_6_EN, 5, 3, 0, analog_gain),
586 SOC_SINGLE_TLV("ADC6 Volume", TABLA_A_TX_5_6_EN, 1, 3, 0, analog_gain),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700587
588 SOC_SINGLE("MICBIAS1 CAPLESS Switch", TABLA_A_MICB_1_CTL, 4, 1, 1),
Santosh Mardi680b41e2011-11-22 16:51:16 -0800589 SOC_SINGLE("MICBIAS2 CAPLESS Switch", TABLA_A_MICB_2_CTL, 4, 1, 1),
Bhalchandra Gajarecc6ffa02011-07-14 18:35:41 -0700590 SOC_SINGLE("MICBIAS3 CAPLESS Switch", TABLA_A_MICB_3_CTL, 4, 1, 1),
591 SOC_SINGLE("MICBIAS4 CAPLESS Switch", TABLA_A_MICB_4_CTL, 4, 1, 1),
Bradley Rubina7096d02011-08-03 18:29:02 -0700592
593 SOC_SINGLE_EXT("ANC Slot", SND_SOC_NOPM, 0, 0, 100, tabla_get_anc_slot,
594 tabla_put_anc_slot),
Santosh Mardi024010f2011-10-18 06:27:21 +0530595 SOC_ENUM("TX1 HPF cut off", cf_dec1_enum),
596 SOC_ENUM("TX2 HPF cut off", cf_dec2_enum),
597 SOC_ENUM("TX3 HPF cut off", cf_dec3_enum),
598 SOC_ENUM("TX4 HPF cut off", cf_dec4_enum),
599 SOC_ENUM("TX5 HPF cut off", cf_dec5_enum),
600 SOC_ENUM("TX6 HPF cut off", cf_dec6_enum),
601 SOC_ENUM("TX7 HPF cut off", cf_dec7_enum),
602 SOC_ENUM("TX8 HPF cut off", cf_dec8_enum),
603 SOC_ENUM("TX9 HPF cut off", cf_dec9_enum),
604 SOC_ENUM("TX10 HPF cut off", cf_dec10_enum),
605
606 SOC_SINGLE("TX1 HPF Switch", TABLA_A_CDC_TX1_MUX_CTL, 3, 1, 0),
607 SOC_SINGLE("TX2 HPF Switch", TABLA_A_CDC_TX2_MUX_CTL, 3, 1, 0),
608 SOC_SINGLE("TX3 HPF Switch", TABLA_A_CDC_TX3_MUX_CTL, 3, 1, 0),
609 SOC_SINGLE("TX4 HPF Switch", TABLA_A_CDC_TX4_MUX_CTL, 3, 1, 0),
610 SOC_SINGLE("TX5 HPF Switch", TABLA_A_CDC_TX5_MUX_CTL, 3, 1, 0),
611 SOC_SINGLE("TX6 HPF Switch", TABLA_A_CDC_TX6_MUX_CTL, 3, 1, 0),
612 SOC_SINGLE("TX7 HPF Switch", TABLA_A_CDC_TX7_MUX_CTL, 3, 1, 0),
613 SOC_SINGLE("TX8 HPF Switch", TABLA_A_CDC_TX8_MUX_CTL, 3, 1, 0),
614 SOC_SINGLE("TX9 HPF Switch", TABLA_A_CDC_TX9_MUX_CTL, 3, 1, 0),
615 SOC_SINGLE("TX10 HPF Switch", TABLA_A_CDC_TX10_MUX_CTL, 3, 1, 0),
616
617 SOC_SINGLE("RX1 HPF Switch", TABLA_A_CDC_RX1_B5_CTL, 2, 1, 0),
618 SOC_SINGLE("RX2 HPF Switch", TABLA_A_CDC_RX2_B5_CTL, 2, 1, 0),
619 SOC_SINGLE("RX3 HPF Switch", TABLA_A_CDC_RX3_B5_CTL, 2, 1, 0),
620 SOC_SINGLE("RX4 HPF Switch", TABLA_A_CDC_RX4_B5_CTL, 2, 1, 0),
621 SOC_SINGLE("RX5 HPF Switch", TABLA_A_CDC_RX5_B5_CTL, 2, 1, 0),
622 SOC_SINGLE("RX6 HPF Switch", TABLA_A_CDC_RX6_B5_CTL, 2, 1, 0),
623 SOC_SINGLE("RX7 HPF Switch", TABLA_A_CDC_RX7_B5_CTL, 2, 1, 0),
624
625 SOC_ENUM("RX1 HPF cut off", cf_rxmix1_enum),
626 SOC_ENUM("RX2 HPF cut off", cf_rxmix2_enum),
627 SOC_ENUM("RX3 HPF cut off", cf_rxmix3_enum),
628 SOC_ENUM("RX4 HPF cut off", cf_rxmix4_enum),
629 SOC_ENUM("RX5 HPF cut off", cf_rxmix5_enum),
630 SOC_ENUM("RX6 HPF cut off", cf_rxmix6_enum),
631 SOC_ENUM("RX7 HPF cut off", cf_rxmix7_enum),
Ben Romberger1f045a72011-11-04 10:14:57 -0700632
633 SOC_SINGLE_EXT("IIR1 Enable Band1", IIR1, BAND1, 1, 0,
634 tabla_get_iir_enable_audio_mixer, tabla_put_iir_enable_audio_mixer),
635 SOC_SINGLE_EXT("IIR1 Enable Band2", IIR1, BAND2, 1, 0,
636 tabla_get_iir_enable_audio_mixer, tabla_put_iir_enable_audio_mixer),
637 SOC_SINGLE_EXT("IIR1 Enable Band3", IIR1, BAND3, 1, 0,
638 tabla_get_iir_enable_audio_mixer, tabla_put_iir_enable_audio_mixer),
639 SOC_SINGLE_EXT("IIR1 Enable Band4", IIR1, BAND4, 1, 0,
640 tabla_get_iir_enable_audio_mixer, tabla_put_iir_enable_audio_mixer),
641 SOC_SINGLE_EXT("IIR1 Enable Band5", IIR1, BAND5, 1, 0,
642 tabla_get_iir_enable_audio_mixer, tabla_put_iir_enable_audio_mixer),
643 SOC_SINGLE_EXT("IIR2 Enable Band1", IIR2, BAND1, 1, 0,
644 tabla_get_iir_enable_audio_mixer, tabla_put_iir_enable_audio_mixer),
645 SOC_SINGLE_EXT("IIR2 Enable Band2", IIR2, BAND2, 1, 0,
646 tabla_get_iir_enable_audio_mixer, tabla_put_iir_enable_audio_mixer),
647 SOC_SINGLE_EXT("IIR2 Enable Band3", IIR2, BAND3, 1, 0,
648 tabla_get_iir_enable_audio_mixer, tabla_put_iir_enable_audio_mixer),
649 SOC_SINGLE_EXT("IIR2 Enable Band4", IIR2, BAND4, 1, 0,
650 tabla_get_iir_enable_audio_mixer, tabla_put_iir_enable_audio_mixer),
651 SOC_SINGLE_EXT("IIR2 Enable Band5", IIR2, BAND5, 1, 0,
652 tabla_get_iir_enable_audio_mixer, tabla_put_iir_enable_audio_mixer),
653
654 SOC_SINGLE_MULTI_EXT("IIR1 Band1", IIR1, BAND1, 255, 0, 5,
655 tabla_get_iir_band_audio_mixer, tabla_put_iir_band_audio_mixer),
656 SOC_SINGLE_MULTI_EXT("IIR1 Band2", IIR1, BAND2, 255, 0, 5,
657 tabla_get_iir_band_audio_mixer, tabla_put_iir_band_audio_mixer),
658 SOC_SINGLE_MULTI_EXT("IIR1 Band3", IIR1, BAND3, 255, 0, 5,
659 tabla_get_iir_band_audio_mixer, tabla_put_iir_band_audio_mixer),
660 SOC_SINGLE_MULTI_EXT("IIR1 Band4", IIR1, BAND4, 255, 0, 5,
661 tabla_get_iir_band_audio_mixer, tabla_put_iir_band_audio_mixer),
662 SOC_SINGLE_MULTI_EXT("IIR1 Band5", IIR1, BAND5, 255, 0, 5,
663 tabla_get_iir_band_audio_mixer, tabla_put_iir_band_audio_mixer),
664 SOC_SINGLE_MULTI_EXT("IIR2 Band1", IIR2, BAND1, 255, 0, 5,
665 tabla_get_iir_band_audio_mixer, tabla_put_iir_band_audio_mixer),
666 SOC_SINGLE_MULTI_EXT("IIR2 Band2", IIR2, BAND2, 255, 0, 5,
667 tabla_get_iir_band_audio_mixer, tabla_put_iir_band_audio_mixer),
668 SOC_SINGLE_MULTI_EXT("IIR2 Band3", IIR2, BAND3, 255, 0, 5,
669 tabla_get_iir_band_audio_mixer, tabla_put_iir_band_audio_mixer),
670 SOC_SINGLE_MULTI_EXT("IIR2 Band4", IIR2, BAND4, 255, 0, 5,
671 tabla_get_iir_band_audio_mixer, tabla_put_iir_band_audio_mixer),
672 SOC_SINGLE_MULTI_EXT("IIR2 Band5", IIR2, BAND5, 255, 0, 5,
673 tabla_get_iir_band_audio_mixer, tabla_put_iir_band_audio_mixer),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700674};
675
676static const char *rx_mix1_text[] = {
677 "ZERO", "SRC1", "SRC2", "IIR1", "IIR2", "RX1", "RX2", "RX3", "RX4",
678 "RX5", "RX6", "RX7"
679};
680
Kiran Kandi8b3a8302011-09-27 16:13:28 -0700681static const char *rx_dsm_text[] = {
682 "CIC_OUT", "DSM_INV"
683};
684
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700685static const char *sb_tx1_mux_text[] = {
686 "ZERO", "RMIX1", "RMIX2", "RMIX3", "RMIX4", "RMIX5", "RMIX6", "RMIX7",
687 "DEC1"
688};
689
690static const char *sb_tx5_mux_text[] = {
691 "ZERO", "RMIX1", "RMIX2", "RMIX3", "RMIX4", "RMIX5", "RMIX6", "RMIX7",
692 "DEC5"
693};
694
695static const char *sb_tx6_mux_text[] = {
696 "ZERO", "RMIX1", "RMIX2", "RMIX3", "RMIX4", "RMIX5", "RMIX6", "RMIX7",
697 "DEC6"
698};
699
700static const char const *sb_tx7_to_tx10_mux_text[] = {
701 "ZERO", "RMIX1", "RMIX2", "RMIX3", "RMIX4", "RMIX5", "RMIX6", "RMIX7",
702 "DEC1", "DEC2", "DEC3", "DEC4", "DEC5", "DEC6", "DEC7", "DEC8",
703 "DEC9", "DEC10"
704};
705
706static const char *dec1_mux_text[] = {
707 "ZERO", "DMIC1", "ADC6",
708};
709
Bhalchandra Gajare0d77e1b2011-07-08 10:54:14 -0700710static const char *dec2_mux_text[] = {
711 "ZERO", "DMIC2", "ADC5",
712};
713
Bhalchandra Gajarecc6ffa02011-07-14 18:35:41 -0700714static const char *dec3_mux_text[] = {
715 "ZERO", "DMIC3", "ADC4",
716};
717
718static const char *dec4_mux_text[] = {
719 "ZERO", "DMIC4", "ADC3",
720};
721
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700722static const char *dec5_mux_text[] = {
723 "ZERO", "DMIC5", "ADC2",
724};
725
726static const char *dec6_mux_text[] = {
727 "ZERO", "DMIC6", "ADC1",
728};
729
730static const char const *dec7_mux_text[] = {
731 "ZERO", "DMIC1", "DMIC6", "ADC1", "ADC6", "ANC1_FB", "ANC2_FB",
732};
733
Bhalchandra Gajare0d77e1b2011-07-08 10:54:14 -0700734static const char *dec8_mux_text[] = {
735 "ZERO", "DMIC2", "DMIC5", "ADC2", "ADC5",
736};
737
Bhalchandra Gajarecc6ffa02011-07-14 18:35:41 -0700738static const char *dec9_mux_text[] = {
739 "ZERO", "DMIC4", "DMIC5", "ADC2", "ADC3", "ADCMB", "ANC1_FB", "ANC2_FB",
740};
741
742static const char *dec10_mux_text[] = {
743 "ZERO", "DMIC3", "DMIC6", "ADC1", "ADC4", "ADCMB", "ANC1_FB", "ANC2_FB",
744};
745
Bradley Rubin229c6a52011-07-12 16:18:48 -0700746static const char const *anc_mux_text[] = {
747 "ZERO", "ADC1", "ADC2", "ADC3", "ADC4", "ADC5", "ADC6", "ADC_MB",
748 "RSVD_1", "DMIC1", "DMIC2", "DMIC3", "DMIC4", "DMIC5", "DMIC6"
749};
750
751static const char const *anc1_fb_mux_text[] = {
752 "ZERO", "EAR_HPH_L", "EAR_LINE_1",
753};
754
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700755static const char *iir1_inp1_text[] = {
756 "ZERO", "DEC1", "DEC2", "DEC3", "DEC4", "DEC5", "DEC6", "DEC7", "DEC8",
757 "DEC9", "DEC10", "RX1", "RX2", "RX3", "RX4", "RX5", "RX6", "RX7"
758};
759
760static const struct soc_enum rx_mix1_inp1_chain_enum =
761 SOC_ENUM_SINGLE(TABLA_A_CDC_CONN_RX1_B1_CTL, 0, 12, rx_mix1_text);
762
Bradley Rubin229c6a52011-07-12 16:18:48 -0700763static const struct soc_enum rx_mix1_inp2_chain_enum =
764 SOC_ENUM_SINGLE(TABLA_A_CDC_CONN_RX1_B1_CTL, 4, 12, rx_mix1_text);
765
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700766static const struct soc_enum rx2_mix1_inp1_chain_enum =
767 SOC_ENUM_SINGLE(TABLA_A_CDC_CONN_RX2_B1_CTL, 0, 12, rx_mix1_text);
768
Bradley Rubin229c6a52011-07-12 16:18:48 -0700769static const struct soc_enum rx2_mix1_inp2_chain_enum =
770 SOC_ENUM_SINGLE(TABLA_A_CDC_CONN_RX2_B1_CTL, 4, 12, rx_mix1_text);
771
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700772static const struct soc_enum rx3_mix1_inp1_chain_enum =
773 SOC_ENUM_SINGLE(TABLA_A_CDC_CONN_RX3_B1_CTL, 0, 12, rx_mix1_text);
774
Bradley Rubin74a9b4a2011-06-13 15:03:43 -0700775static const struct soc_enum rx3_mix1_inp2_chain_enum =
776 SOC_ENUM_SINGLE(TABLA_A_CDC_CONN_RX3_B1_CTL, 4, 12, rx_mix1_text);
777
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700778static const struct soc_enum rx4_mix1_inp1_chain_enum =
779 SOC_ENUM_SINGLE(TABLA_A_CDC_CONN_RX4_B1_CTL, 0, 12, rx_mix1_text);
780
Bradley Rubin74a9b4a2011-06-13 15:03:43 -0700781static const struct soc_enum rx4_mix1_inp2_chain_enum =
782 SOC_ENUM_SINGLE(TABLA_A_CDC_CONN_RX4_B1_CTL, 4, 12, rx_mix1_text);
783
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700784static const struct soc_enum rx5_mix1_inp1_chain_enum =
785 SOC_ENUM_SINGLE(TABLA_A_CDC_CONN_RX5_B1_CTL, 0, 12, rx_mix1_text);
786
Bradley Rubin74a9b4a2011-06-13 15:03:43 -0700787static const struct soc_enum rx5_mix1_inp2_chain_enum =
788 SOC_ENUM_SINGLE(TABLA_A_CDC_CONN_RX5_B1_CTL, 4, 12, rx_mix1_text);
789
790static const struct soc_enum rx6_mix1_inp1_chain_enum =
791 SOC_ENUM_SINGLE(TABLA_A_CDC_CONN_RX6_B1_CTL, 0, 12, rx_mix1_text);
792
793static const struct soc_enum rx6_mix1_inp2_chain_enum =
794 SOC_ENUM_SINGLE(TABLA_A_CDC_CONN_RX6_B1_CTL, 4, 12, rx_mix1_text);
795
Bhalchandra Gajare0a8ad172011-08-12 13:32:22 -0700796static const struct soc_enum rx7_mix1_inp1_chain_enum =
797 SOC_ENUM_SINGLE(TABLA_A_CDC_CONN_RX7_B1_CTL, 0, 12, rx_mix1_text);
798
799static const struct soc_enum rx7_mix1_inp2_chain_enum =
800 SOC_ENUM_SINGLE(TABLA_A_CDC_CONN_RX7_B1_CTL, 4, 12, rx_mix1_text);
801
Kiran Kandi8b3a8302011-09-27 16:13:28 -0700802static const struct soc_enum rx4_dsm_enum =
803 SOC_ENUM_SINGLE(TABLA_A_CDC_RX4_B6_CTL, 4, 2, rx_dsm_text);
804
805static const struct soc_enum rx6_dsm_enum =
806 SOC_ENUM_SINGLE(TABLA_A_CDC_RX6_B6_CTL, 4, 2, rx_dsm_text);
807
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700808static const struct soc_enum sb_tx5_mux_enum =
809 SOC_ENUM_SINGLE(TABLA_A_CDC_CONN_TX_SB_B5_CTL, 0, 9, sb_tx5_mux_text);
810
811static const struct soc_enum sb_tx6_mux_enum =
812 SOC_ENUM_SINGLE(TABLA_A_CDC_CONN_TX_SB_B6_CTL, 0, 9, sb_tx6_mux_text);
813
814static const struct soc_enum sb_tx7_mux_enum =
815 SOC_ENUM_SINGLE(TABLA_A_CDC_CONN_TX_SB_B7_CTL, 0, 18,
816 sb_tx7_to_tx10_mux_text);
817
818static const struct soc_enum sb_tx8_mux_enum =
819 SOC_ENUM_SINGLE(TABLA_A_CDC_CONN_TX_SB_B8_CTL, 0, 18,
820 sb_tx7_to_tx10_mux_text);
821
822static const struct soc_enum sb_tx1_mux_enum =
823 SOC_ENUM_SINGLE(TABLA_A_CDC_CONN_TX_SB_B1_CTL, 0, 9, sb_tx1_mux_text);
824
825static const struct soc_enum dec1_mux_enum =
826 SOC_ENUM_SINGLE(TABLA_A_CDC_CONN_TX_B1_CTL, 0, 3, dec1_mux_text);
827
Bhalchandra Gajare0d77e1b2011-07-08 10:54:14 -0700828static const struct soc_enum dec2_mux_enum =
829 SOC_ENUM_SINGLE(TABLA_A_CDC_CONN_TX_B1_CTL, 2, 3, dec2_mux_text);
830
Bhalchandra Gajarecc6ffa02011-07-14 18:35:41 -0700831static const struct soc_enum dec3_mux_enum =
832 SOC_ENUM_SINGLE(TABLA_A_CDC_CONN_TX_B1_CTL, 4, 3, dec3_mux_text);
833
834static const struct soc_enum dec4_mux_enum =
835 SOC_ENUM_SINGLE(TABLA_A_CDC_CONN_TX_B1_CTL, 6, 3, dec4_mux_text);
836
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700837static const struct soc_enum dec5_mux_enum =
838 SOC_ENUM_SINGLE(TABLA_A_CDC_CONN_TX_B2_CTL, 0, 3, dec5_mux_text);
839
840static const struct soc_enum dec6_mux_enum =
841 SOC_ENUM_SINGLE(TABLA_A_CDC_CONN_TX_B2_CTL, 2, 3, dec6_mux_text);
842
843static const struct soc_enum dec7_mux_enum =
844 SOC_ENUM_SINGLE(TABLA_A_CDC_CONN_TX_B2_CTL, 4, 7, dec7_mux_text);
845
Bhalchandra Gajare0d77e1b2011-07-08 10:54:14 -0700846static const struct soc_enum dec8_mux_enum =
847 SOC_ENUM_SINGLE(TABLA_A_CDC_CONN_TX_B3_CTL, 0, 7, dec8_mux_text);
848
Bhalchandra Gajarecc6ffa02011-07-14 18:35:41 -0700849static const struct soc_enum dec9_mux_enum =
850 SOC_ENUM_SINGLE(TABLA_A_CDC_CONN_TX_B3_CTL, 3, 8, dec9_mux_text);
851
852static const struct soc_enum dec10_mux_enum =
853 SOC_ENUM_SINGLE(TABLA_A_CDC_CONN_TX_B4_CTL, 0, 8, dec10_mux_text);
854
Bradley Rubin229c6a52011-07-12 16:18:48 -0700855static const struct soc_enum anc1_mux_enum =
856 SOC_ENUM_SINGLE(TABLA_A_CDC_CONN_ANC_B1_CTL, 0, 16, anc_mux_text);
857
858static const struct soc_enum anc2_mux_enum =
859 SOC_ENUM_SINGLE(TABLA_A_CDC_CONN_ANC_B1_CTL, 4, 16, anc_mux_text);
860
861static const struct soc_enum anc1_fb_mux_enum =
862 SOC_ENUM_SINGLE(TABLA_A_CDC_CONN_ANC_B2_CTL, 0, 3, anc1_fb_mux_text);
863
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700864static const struct soc_enum iir1_inp1_mux_enum =
865 SOC_ENUM_SINGLE(TABLA_A_CDC_CONN_EQ1_B1_CTL, 0, 18, iir1_inp1_text);
866
867static const struct snd_kcontrol_new rx_mix1_inp1_mux =
868 SOC_DAPM_ENUM("RX1 MIX1 INP1 Mux", rx_mix1_inp1_chain_enum);
869
Bradley Rubin229c6a52011-07-12 16:18:48 -0700870static const struct snd_kcontrol_new rx_mix1_inp2_mux =
871 SOC_DAPM_ENUM("RX1 MIX1 INP2 Mux", rx_mix1_inp2_chain_enum);
872
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700873static const struct snd_kcontrol_new rx2_mix1_inp1_mux =
874 SOC_DAPM_ENUM("RX2 MIX1 INP1 Mux", rx2_mix1_inp1_chain_enum);
875
Bradley Rubin229c6a52011-07-12 16:18:48 -0700876static const struct snd_kcontrol_new rx2_mix1_inp2_mux =
877 SOC_DAPM_ENUM("RX2 MIX1 INP2 Mux", rx2_mix1_inp2_chain_enum);
878
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700879static const struct snd_kcontrol_new rx3_mix1_inp1_mux =
880 SOC_DAPM_ENUM("RX3 MIX1 INP1 Mux", rx3_mix1_inp1_chain_enum);
881
Bradley Rubin74a9b4a2011-06-13 15:03:43 -0700882static const struct snd_kcontrol_new rx3_mix1_inp2_mux =
883 SOC_DAPM_ENUM("RX3 MIX1 INP2 Mux", rx3_mix1_inp2_chain_enum);
884
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700885static const struct snd_kcontrol_new rx4_mix1_inp1_mux =
886 SOC_DAPM_ENUM("RX4 MIX1 INP1 Mux", rx4_mix1_inp1_chain_enum);
887
Bradley Rubin74a9b4a2011-06-13 15:03:43 -0700888static const struct snd_kcontrol_new rx4_mix1_inp2_mux =
889 SOC_DAPM_ENUM("RX4 MIX1 INP2 Mux", rx4_mix1_inp2_chain_enum);
890
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700891static const struct snd_kcontrol_new rx5_mix1_inp1_mux =
892 SOC_DAPM_ENUM("RX5 MIX1 INP1 Mux", rx5_mix1_inp1_chain_enum);
893
Bradley Rubin74a9b4a2011-06-13 15:03:43 -0700894static const struct snd_kcontrol_new rx5_mix1_inp2_mux =
895 SOC_DAPM_ENUM("RX5 MIX1 INP2 Mux", rx5_mix1_inp2_chain_enum);
896
897static const struct snd_kcontrol_new rx6_mix1_inp1_mux =
898 SOC_DAPM_ENUM("RX6 MIX1 INP1 Mux", rx6_mix1_inp1_chain_enum);
899
900static const struct snd_kcontrol_new rx6_mix1_inp2_mux =
901 SOC_DAPM_ENUM("RX6 MIX1 INP2 Mux", rx6_mix1_inp2_chain_enum);
902
Bhalchandra Gajare0a8ad172011-08-12 13:32:22 -0700903static const struct snd_kcontrol_new rx7_mix1_inp1_mux =
904 SOC_DAPM_ENUM("RX7 MIX1 INP1 Mux", rx7_mix1_inp1_chain_enum);
905
906static const struct snd_kcontrol_new rx7_mix1_inp2_mux =
907 SOC_DAPM_ENUM("RX7 MIX1 INP2 Mux", rx7_mix1_inp2_chain_enum);
908
Kiran Kandi8b3a8302011-09-27 16:13:28 -0700909static const struct snd_kcontrol_new rx4_dsm_mux =
910 SOC_DAPM_ENUM("RX4 DSM MUX Mux", rx4_dsm_enum);
911
912static const struct snd_kcontrol_new rx6_dsm_mux =
913 SOC_DAPM_ENUM("RX6 DSM MUX Mux", rx6_dsm_enum);
914
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700915static const struct snd_kcontrol_new sb_tx5_mux =
916 SOC_DAPM_ENUM("SLIM TX5 MUX Mux", sb_tx5_mux_enum);
917
918static const struct snd_kcontrol_new sb_tx6_mux =
919 SOC_DAPM_ENUM("SLIM TX6 MUX Mux", sb_tx6_mux_enum);
920
921static const struct snd_kcontrol_new sb_tx7_mux =
922 SOC_DAPM_ENUM("SLIM TX7 MUX Mux", sb_tx7_mux_enum);
923
924static const struct snd_kcontrol_new sb_tx8_mux =
925 SOC_DAPM_ENUM("SLIM TX8 MUX Mux", sb_tx8_mux_enum);
926
927static const struct snd_kcontrol_new sb_tx1_mux =
928 SOC_DAPM_ENUM("SLIM TX1 MUX Mux", sb_tx1_mux_enum);
929
930static const struct snd_kcontrol_new dec1_mux =
931 SOC_DAPM_ENUM("DEC1 MUX Mux", dec1_mux_enum);
932
Bhalchandra Gajare0d77e1b2011-07-08 10:54:14 -0700933static const struct snd_kcontrol_new dec2_mux =
934 SOC_DAPM_ENUM("DEC2 MUX Mux", dec2_mux_enum);
935
Bhalchandra Gajarecc6ffa02011-07-14 18:35:41 -0700936static const struct snd_kcontrol_new dec3_mux =
937 SOC_DAPM_ENUM("DEC3 MUX Mux", dec3_mux_enum);
938
939static const struct snd_kcontrol_new dec4_mux =
940 SOC_DAPM_ENUM("DEC4 MUX Mux", dec4_mux_enum);
941
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700942static const struct snd_kcontrol_new dec5_mux =
943 SOC_DAPM_ENUM("DEC5 MUX Mux", dec5_mux_enum);
944
945static const struct snd_kcontrol_new dec6_mux =
946 SOC_DAPM_ENUM("DEC6 MUX Mux", dec6_mux_enum);
947
948static const struct snd_kcontrol_new dec7_mux =
949 SOC_DAPM_ENUM("DEC7 MUX Mux", dec7_mux_enum);
950
Bradley Rubin229c6a52011-07-12 16:18:48 -0700951static const struct snd_kcontrol_new anc1_mux =
952 SOC_DAPM_ENUM("ANC1 MUX Mux", anc1_mux_enum);
Bhalchandra Gajare0d77e1b2011-07-08 10:54:14 -0700953static const struct snd_kcontrol_new dec8_mux =
954 SOC_DAPM_ENUM("DEC8 MUX Mux", dec8_mux_enum);
955
Bhalchandra Gajarecc6ffa02011-07-14 18:35:41 -0700956static const struct snd_kcontrol_new dec9_mux =
957 SOC_DAPM_ENUM("DEC9 MUX Mux", dec9_mux_enum);
958
959static const struct snd_kcontrol_new dec10_mux =
960 SOC_DAPM_ENUM("DEC10 MUX Mux", dec10_mux_enum);
961
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700962static const struct snd_kcontrol_new iir1_inp1_mux =
963 SOC_DAPM_ENUM("IIR1 INP1 Mux", iir1_inp1_mux_enum);
964
Bradley Rubin229c6a52011-07-12 16:18:48 -0700965static const struct snd_kcontrol_new anc2_mux =
966 SOC_DAPM_ENUM("ANC2 MUX Mux", anc2_mux_enum);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700967
Bradley Rubin229c6a52011-07-12 16:18:48 -0700968static const struct snd_kcontrol_new anc1_fb_mux =
969 SOC_DAPM_ENUM("ANC1 FB MUX Mux", anc1_fb_mux_enum);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700970
Bradley Rubin229c6a52011-07-12 16:18:48 -0700971static const struct snd_kcontrol_new dac1_switch[] = {
972 SOC_DAPM_SINGLE("Switch", TABLA_A_RX_EAR_EN, 5, 1, 0)
973};
974static const struct snd_kcontrol_new hphl_switch[] = {
975 SOC_DAPM_SINGLE("Switch", TABLA_A_RX_HPH_L_DAC_CTL, 6, 1, 0)
976};
Kiran Kandi8b3a8302011-09-27 16:13:28 -0700977
978static const struct snd_kcontrol_new lineout3_ground_switch =
979 SOC_DAPM_SINGLE("Switch", TABLA_A_RX_LINE_3_DAC_CTL, 6, 1, 0);
980
981static const struct snd_kcontrol_new lineout4_ground_switch =
982 SOC_DAPM_SINGLE("Switch", TABLA_A_RX_LINE_4_DAC_CTL, 6, 1, 0);
Bradley Rubin74a9b4a2011-06-13 15:03:43 -0700983
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700984static void tabla_codec_enable_adc_block(struct snd_soc_codec *codec,
985 int enable)
986{
987 struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
988
989 pr_debug("%s %d\n", __func__, enable);
990
991 if (enable) {
992 tabla->adc_count++;
993 snd_soc_update_bits(codec, TABLA_A_TX_COM_BIAS, 0xE0, 0xE0);
994 snd_soc_update_bits(codec, TABLA_A_CDC_CLK_OTHR_CTL, 0x2, 0x2);
995 } else {
996 tabla->adc_count--;
997 if (!tabla->adc_count) {
998 snd_soc_update_bits(codec, TABLA_A_CDC_CLK_OTHR_CTL,
999 0x2, 0x0);
1000 if (!tabla->mbhc_polling_active)
1001 snd_soc_update_bits(codec, TABLA_A_TX_COM_BIAS,
1002 0xE0, 0x0);
1003 }
1004 }
1005}
1006
1007static int tabla_codec_enable_adc(struct snd_soc_dapm_widget *w,
1008 struct snd_kcontrol *kcontrol, int event)
1009{
1010 struct snd_soc_codec *codec = w->codec;
1011 u16 adc_reg;
Kiran Kandi9a2c62a82011-12-07 13:13:26 -08001012 u8 init_bit_shift;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001013
1014 pr_debug("%s %d\n", __func__, event);
1015
1016 if (w->reg == TABLA_A_TX_1_2_EN)
1017 adc_reg = TABLA_A_TX_1_2_TEST_CTL;
1018 else if (w->reg == TABLA_A_TX_3_4_EN)
1019 adc_reg = TABLA_A_TX_3_4_TEST_CTL;
1020 else if (w->reg == TABLA_A_TX_5_6_EN)
1021 adc_reg = TABLA_A_TX_5_6_TEST_CTL;
1022 else {
1023 pr_err("%s: Error, invalid adc register\n", __func__);
1024 return -EINVAL;
1025 }
1026
Kiran Kandi9a2c62a82011-12-07 13:13:26 -08001027 if (w->shift == 3)
1028 init_bit_shift = 6;
1029 else if (w->shift == 7)
1030 init_bit_shift = 7;
1031 else {
1032 pr_err("%s: Error, invalid init bit postion adc register\n",
1033 __func__);
1034 return -EINVAL;
1035 }
1036
1037
1038
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001039 switch (event) {
1040 case SND_SOC_DAPM_PRE_PMU:
1041 tabla_codec_enable_adc_block(codec, 1);
Kiran Kandi9a2c62a82011-12-07 13:13:26 -08001042 snd_soc_update_bits(codec, adc_reg, 1 << init_bit_shift,
1043 1 << init_bit_shift);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001044 break;
1045 case SND_SOC_DAPM_POST_PMU:
Kiran Kandi9a2c62a82011-12-07 13:13:26 -08001046
1047 snd_soc_update_bits(codec, adc_reg, 1 << init_bit_shift, 0x00);
1048
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001049 break;
1050 case SND_SOC_DAPM_POST_PMD:
1051 tabla_codec_enable_adc_block(codec, 0);
1052 break;
1053 }
1054 return 0;
1055}
1056
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001057static int tabla_codec_enable_lineout(struct snd_soc_dapm_widget *w,
1058 struct snd_kcontrol *kcontrol, int event)
1059{
1060 struct snd_soc_codec *codec = w->codec;
1061 u16 lineout_gain_reg;
1062
Kiran Kandidb0a4b02011-08-23 09:32:09 -07001063 pr_debug("%s %d %s\n", __func__, event, w->name);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001064
1065 switch (w->shift) {
1066 case 0:
1067 lineout_gain_reg = TABLA_A_RX_LINE_1_GAIN;
1068 break;
1069 case 1:
1070 lineout_gain_reg = TABLA_A_RX_LINE_2_GAIN;
1071 break;
1072 case 2:
1073 lineout_gain_reg = TABLA_A_RX_LINE_3_GAIN;
1074 break;
1075 case 3:
1076 lineout_gain_reg = TABLA_A_RX_LINE_4_GAIN;
1077 break;
1078 case 4:
1079 lineout_gain_reg = TABLA_A_RX_LINE_5_GAIN;
1080 break;
1081 default:
1082 pr_err("%s: Error, incorrect lineout register value\n",
1083 __func__);
1084 return -EINVAL;
1085 }
1086
1087 switch (event) {
1088 case SND_SOC_DAPM_PRE_PMU:
1089 snd_soc_update_bits(codec, lineout_gain_reg, 0x40, 0x40);
1090 break;
1091 case SND_SOC_DAPM_POST_PMU:
Krishnankutty Kolathappilly31169f42011-11-17 10:33:11 -08001092 pr_debug("%s: sleeping 16 ms after %s PA turn on\n",
Kiran Kandidb0a4b02011-08-23 09:32:09 -07001093 __func__, w->name);
Krishnankutty Kolathappilly31169f42011-11-17 10:33:11 -08001094 usleep_range(16000, 16000);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001095 break;
1096 case SND_SOC_DAPM_POST_PMD:
1097 snd_soc_update_bits(codec, lineout_gain_reg, 0x40, 0x00);
1098 break;
1099 }
1100 return 0;
1101}
1102
Kiran Kandicf45f6a2011-07-17 21:10:19 -07001103
1104static int tabla_codec_enable_dmic(struct snd_soc_dapm_widget *w,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001105 struct snd_kcontrol *kcontrol, int event)
1106{
1107 struct snd_soc_codec *codec = w->codec;
Kiran Kandicf45f6a2011-07-17 21:10:19 -07001108 u16 tx_mux_ctl_reg, tx_dmic_ctl_reg;
1109 u8 dmic_clk_sel, dmic_clk_en;
Bhalchandra Gajare7cf018e2011-08-11 18:58:32 -07001110 unsigned int dmic;
1111 int ret;
Kiran Kandicf45f6a2011-07-17 21:10:19 -07001112
Bhalchandra Gajare7cf018e2011-08-11 18:58:32 -07001113 ret = kstrtouint(strpbrk(w->name, "123456"), 10, &dmic);
1114 if (ret < 0) {
1115 pr_err("%s: Invalid DMIC line on the codec\n", __func__);
Kiran Kandicf45f6a2011-07-17 21:10:19 -07001116 return -EINVAL;
1117 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001118
Bhalchandra Gajare7cf018e2011-08-11 18:58:32 -07001119 switch (dmic) {
1120 case 1:
1121 case 2:
1122 dmic_clk_sel = 0x02;
1123 dmic_clk_en = 0x01;
1124 break;
1125
1126 case 3:
1127 case 4:
1128 dmic_clk_sel = 0x08;
1129 dmic_clk_en = 0x04;
1130 break;
1131
1132 case 5:
1133 case 6:
1134 dmic_clk_sel = 0x20;
1135 dmic_clk_en = 0x10;
1136 break;
1137
1138 default:
1139 pr_err("%s: Invalid DMIC Selection\n", __func__);
1140 return -EINVAL;
1141 }
1142
1143 tx_mux_ctl_reg = TABLA_A_CDC_TX1_MUX_CTL + 8 * (dmic - 1);
1144 tx_dmic_ctl_reg = TABLA_A_CDC_TX1_DMIC_CTL + 8 * (dmic - 1);
1145
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001146 pr_debug("%s %d\n", __func__, event);
Kiran Kandicf45f6a2011-07-17 21:10:19 -07001147
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001148 switch (event) {
1149 case SND_SOC_DAPM_PRE_PMU:
Kiran Kandicf45f6a2011-07-17 21:10:19 -07001150 snd_soc_update_bits(codec, tx_mux_ctl_reg, 0x1, 0x1);
1151
1152 snd_soc_update_bits(codec, TABLA_A_CDC_CLK_DMIC_CTL,
1153 dmic_clk_sel, dmic_clk_sel);
1154
1155 snd_soc_update_bits(codec, tx_dmic_ctl_reg, 0x1, 0x1);
1156
1157 snd_soc_update_bits(codec, TABLA_A_CDC_CLK_DMIC_CTL,
1158 dmic_clk_en, dmic_clk_en);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001159 break;
1160 case SND_SOC_DAPM_POST_PMD:
Kiran Kandicf45f6a2011-07-17 21:10:19 -07001161 snd_soc_update_bits(codec, TABLA_A_CDC_CLK_DMIC_CTL,
1162 dmic_clk_en, 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001163 break;
1164 }
1165 return 0;
1166}
1167
Bradley Rubin229c6a52011-07-12 16:18:48 -07001168static int tabla_codec_enable_anc(struct snd_soc_dapm_widget *w,
1169 struct snd_kcontrol *kcontrol, int event)
1170{
1171 struct snd_soc_codec *codec = w->codec;
1172 const char *filename;
1173 const struct firmware *fw;
1174 int i;
1175 int ret;
Bradley Rubina7096d02011-08-03 18:29:02 -07001176 int num_anc_slots;
1177 struct anc_header *anc_head;
Bradley Rubin229c6a52011-07-12 16:18:48 -07001178 struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
Bradley Rubina7096d02011-08-03 18:29:02 -07001179 u32 anc_writes_size = 0;
1180 int anc_size_remaining;
1181 u32 *anc_ptr;
Bradley Rubin229c6a52011-07-12 16:18:48 -07001182 u16 reg;
1183 u8 mask, val, old_val;
1184
1185 pr_debug("%s %d\n", __func__, event);
1186 switch (event) {
1187 case SND_SOC_DAPM_PRE_PMU:
1188
Bradley Rubin4283a4c2011-07-29 16:18:54 -07001189 filename = "wcd9310/wcd9310_anc.bin";
Bradley Rubin229c6a52011-07-12 16:18:48 -07001190
1191 ret = request_firmware(&fw, filename, codec->dev);
1192 if (ret != 0) {
1193 dev_err(codec->dev, "Failed to acquire ANC data: %d\n",
1194 ret);
1195 return -ENODEV;
1196 }
1197
Bradley Rubina7096d02011-08-03 18:29:02 -07001198 if (fw->size < sizeof(struct anc_header)) {
Bradley Rubin229c6a52011-07-12 16:18:48 -07001199 dev_err(codec->dev, "Not enough data\n");
1200 release_firmware(fw);
1201 return -ENOMEM;
1202 }
1203
1204 /* First number is the number of register writes */
Bradley Rubina7096d02011-08-03 18:29:02 -07001205 anc_head = (struct anc_header *)(fw->data);
1206 anc_ptr = (u32 *)((u32)fw->data + sizeof(struct anc_header));
1207 anc_size_remaining = fw->size - sizeof(struct anc_header);
1208 num_anc_slots = anc_head->num_anc_slots;
Bradley Rubin229c6a52011-07-12 16:18:48 -07001209
Bradley Rubina7096d02011-08-03 18:29:02 -07001210 if (tabla->anc_slot >= num_anc_slots) {
1211 dev_err(codec->dev, "Invalid ANC slot selected\n");
1212 release_firmware(fw);
1213 return -EINVAL;
1214 }
1215
1216 for (i = 0; i < num_anc_slots; i++) {
1217
1218 if (anc_size_remaining < TABLA_PACKED_REG_SIZE) {
1219 dev_err(codec->dev, "Invalid register format\n");
1220 release_firmware(fw);
1221 return -EINVAL;
1222 }
1223 anc_writes_size = (u32)(*anc_ptr);
1224 anc_size_remaining -= sizeof(u32);
1225 anc_ptr += 1;
1226
1227 if (anc_writes_size * TABLA_PACKED_REG_SIZE
1228 > anc_size_remaining) {
1229 dev_err(codec->dev, "Invalid register format\n");
1230 release_firmware(fw);
1231 return -ENOMEM;
1232 }
1233
1234 if (tabla->anc_slot == i)
1235 break;
1236
1237 anc_size_remaining -= (anc_writes_size *
1238 TABLA_PACKED_REG_SIZE);
Bradley Rubin939ff3f2011-08-26 17:19:34 -07001239 anc_ptr += anc_writes_size;
Bradley Rubina7096d02011-08-03 18:29:02 -07001240 }
1241 if (i == num_anc_slots) {
1242 dev_err(codec->dev, "Selected ANC slot not present\n");
Bradley Rubin229c6a52011-07-12 16:18:48 -07001243 release_firmware(fw);
1244 return -ENOMEM;
1245 }
1246
Bradley Rubina7096d02011-08-03 18:29:02 -07001247 for (i = 0; i < anc_writes_size; i++) {
1248 TABLA_CODEC_UNPACK_ENTRY(anc_ptr[i], reg,
Bradley Rubin229c6a52011-07-12 16:18:48 -07001249 mask, val);
1250 old_val = snd_soc_read(codec, reg);
Bradley Rubin4283a4c2011-07-29 16:18:54 -07001251 snd_soc_write(codec, reg, (old_val & ~mask) |
1252 (val & mask));
Bradley Rubin229c6a52011-07-12 16:18:48 -07001253 }
1254 release_firmware(fw);
Bradley Rubin229c6a52011-07-12 16:18:48 -07001255
1256 break;
1257 case SND_SOC_DAPM_POST_PMD:
1258 snd_soc_write(codec, TABLA_A_CDC_CLK_ANC_RESET_CTL, 0xFF);
1259 snd_soc_write(codec, TABLA_A_CDC_CLK_ANC_CLK_EN_CTL, 0);
1260 break;
1261 }
1262 return 0;
1263}
1264
1265
Bradley Rubincb3950a2011-08-18 13:07:26 -07001266static void tabla_codec_disable_button_presses(struct snd_soc_codec *codec)
1267{
1268 snd_soc_write(codec, TABLA_A_CDC_MBHC_VOLT_B4_CTL, 0x80);
1269 snd_soc_write(codec, TABLA_A_CDC_MBHC_VOLT_B3_CTL, 0x00);
1270}
1271
Bradley Rubin4d09cf42011-08-17 17:59:16 -07001272static void tabla_codec_start_hs_polling(struct snd_soc_codec *codec)
1273{
Bradley Rubincb3950a2011-08-18 13:07:26 -07001274 struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
1275
Bradley Rubin4d09cf42011-08-17 17:59:16 -07001276 snd_soc_write(codec, TABLA_A_MBHC_SCALING_MUX_1, 0x84);
Bradley Rubin4d09cf42011-08-17 17:59:16 -07001277 tabla_enable_irq(codec->control_data, TABLA_IRQ_MBHC_REMOVAL);
Bradley Rubincb3950a2011-08-18 13:07:26 -07001278 if (!tabla->no_mic_headset_override) {
1279 tabla_enable_irq(codec->control_data, TABLA_IRQ_MBHC_POTENTIAL);
1280 tabla_enable_irq(codec->control_data, TABLA_IRQ_MBHC_RELEASE);
1281 } else {
1282 tabla_codec_disable_button_presses(codec);
1283 }
Bradley Rubin4d09cf42011-08-17 17:59:16 -07001284 snd_soc_write(codec, TABLA_A_CDC_MBHC_EN_CTL, 0x1);
1285 snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_CLK_CTL, 0x8, 0x0);
1286 snd_soc_write(codec, TABLA_A_CDC_MBHC_EN_CTL, 0x1);
1287}
1288
1289static void tabla_codec_pause_hs_polling(struct snd_soc_codec *codec)
1290{
Bradley Rubincb3950a2011-08-18 13:07:26 -07001291 struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
1292
Bradley Rubin4d09cf42011-08-17 17:59:16 -07001293 snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_CLK_CTL, 0x8, 0x8);
1294 tabla_disable_irq(codec->control_data, TABLA_IRQ_MBHC_REMOVAL);
Bradley Rubincb3950a2011-08-18 13:07:26 -07001295 if (!tabla->no_mic_headset_override) {
1296 tabla_disable_irq(codec->control_data,
1297 TABLA_IRQ_MBHC_POTENTIAL);
1298 tabla_disable_irq(codec->control_data, TABLA_IRQ_MBHC_RELEASE);
1299 }
Bradley Rubin4d09cf42011-08-17 17:59:16 -07001300}
1301
Bhalchandra Gajare19d9c132011-11-18 14:57:08 -08001302static void tabla_codec_switch_cfilt_mode(struct snd_soc_codec *codec,
1303 int mode)
1304{
1305 struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
1306 u8 reg_mode_val, cur_mode_val;
1307 bool mbhc_was_polling = false;
1308
1309 if (mode)
1310 reg_mode_val = TABLA_CFILT_FAST_MODE;
1311 else
1312 reg_mode_val = TABLA_CFILT_SLOW_MODE;
1313
1314 cur_mode_val = snd_soc_read(codec,
1315 tabla->mbhc_bias_regs.cfilt_ctl) & 0x40;
1316
1317 if (cur_mode_val != reg_mode_val) {
1318 if (tabla->mbhc_polling_active) {
1319 tabla_codec_pause_hs_polling(codec);
1320 mbhc_was_polling = true;
1321 }
1322 snd_soc_update_bits(codec,
1323 tabla->mbhc_bias_regs.cfilt_ctl, 0x40, reg_mode_val);
1324 if (mbhc_was_polling)
1325 tabla_codec_start_hs_polling(codec);
1326 pr_debug("%s: CFILT mode change (%x to %x)\n", __func__,
1327 cur_mode_val, reg_mode_val);
1328 } else {
1329 pr_debug("%s: CFILT Value is already %x\n",
1330 __func__, cur_mode_val);
1331 }
1332}
1333
1334static void tabla_codec_update_cfilt_usage(struct snd_soc_codec *codec,
1335 u8 cfilt_sel, int inc)
1336{
1337 struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
1338 u32 *cfilt_cnt_ptr = NULL;
1339 u16 micb_cfilt_reg;
1340
1341 switch (cfilt_sel) {
1342 case TABLA_CFILT1_SEL:
1343 cfilt_cnt_ptr = &tabla->cfilt1_cnt;
1344 micb_cfilt_reg = TABLA_A_MICB_CFILT_1_CTL;
1345 break;
1346 case TABLA_CFILT2_SEL:
1347 cfilt_cnt_ptr = &tabla->cfilt2_cnt;
1348 micb_cfilt_reg = TABLA_A_MICB_CFILT_2_CTL;
1349 break;
1350 case TABLA_CFILT3_SEL:
1351 cfilt_cnt_ptr = &tabla->cfilt3_cnt;
1352 micb_cfilt_reg = TABLA_A_MICB_CFILT_3_CTL;
1353 break;
1354 default:
1355 return; /* should not happen */
1356 }
1357
1358 if (inc) {
1359 if (!(*cfilt_cnt_ptr)++) {
1360 /* Switch CFILT to slow mode if MBHC CFILT being used */
1361 if (cfilt_sel == tabla->mbhc_bias_regs.cfilt_sel)
1362 tabla_codec_switch_cfilt_mode(codec, 0);
1363
1364 snd_soc_update_bits(codec, micb_cfilt_reg, 0x80, 0x80);
1365 }
1366 } else {
1367 /* check if count not zero, decrement
1368 * then check if zero, go ahead disable cfilter
1369 */
1370 if ((*cfilt_cnt_ptr) && !--(*cfilt_cnt_ptr)) {
1371 snd_soc_update_bits(codec, micb_cfilt_reg, 0x80, 0);
1372
1373 /* Switch CFILT to fast mode if MBHC CFILT being used */
1374 if (cfilt_sel == tabla->mbhc_bias_regs.cfilt_sel)
1375 tabla_codec_switch_cfilt_mode(codec, 1);
1376 }
1377 }
1378}
1379
Bhalchandra Gajared9ebb6c2011-10-03 19:54:41 -07001380static int tabla_find_k_value(unsigned int ldoh_v, unsigned int cfilt_mv)
1381{
1382 int rc = -EINVAL;
1383 unsigned min_mv, max_mv;
1384
1385 switch (ldoh_v) {
1386 case TABLA_LDOH_1P95_V:
1387 min_mv = 160;
1388 max_mv = 1800;
1389 break;
1390 case TABLA_LDOH_2P35_V:
1391 min_mv = 200;
1392 max_mv = 2200;
1393 break;
1394 case TABLA_LDOH_2P75_V:
1395 min_mv = 240;
1396 max_mv = 2600;
1397 break;
1398 case TABLA_LDOH_2P85_V:
1399 min_mv = 250;
1400 max_mv = 2700;
1401 break;
1402 default:
1403 goto done;
1404 }
1405
1406 if (cfilt_mv < min_mv || cfilt_mv > max_mv)
1407 goto done;
1408
1409 for (rc = 4; rc <= 44; rc++) {
1410 min_mv = max_mv * (rc) / 44;
1411 if (min_mv >= cfilt_mv) {
1412 rc -= 4;
1413 break;
1414 }
1415 }
1416done:
1417 return rc;
1418}
1419
1420static bool tabla_is_hph_pa_on(struct snd_soc_codec *codec)
1421{
1422 u8 hph_reg_val = 0;
1423 hph_reg_val = snd_soc_read(codec, TABLA_A_RX_HPH_CNP_EN);
1424
1425 return (hph_reg_val & 0x30) ? true : false;
1426}
1427
Joonwoo Parka9444452011-12-08 18:48:27 -08001428static bool tabla_is_hph_dac_on(struct snd_soc_codec *codec, int left)
1429{
1430 u8 hph_reg_val = 0;
1431 if (left)
1432 hph_reg_val = snd_soc_read(codec,
1433 TABLA_A_RX_HPH_L_DAC_CTL);
1434 else
1435 hph_reg_val = snd_soc_read(codec,
1436 TABLA_A_RX_HPH_R_DAC_CTL);
1437
1438 return (hph_reg_val & 0xC0) ? true : false;
1439}
1440
Bhalchandra Gajared9ebb6c2011-10-03 19:54:41 -07001441static void tabla_codec_switch_micbias(struct snd_soc_codec *codec,
1442 int vddio_switch)
1443{
1444 struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
1445 int cfilt_k_val;
Bhalchandra Gajarec1e19c42011-11-18 11:22:56 -08001446 bool mbhc_was_polling = false;
Bhalchandra Gajared9ebb6c2011-10-03 19:54:41 -07001447
1448 switch (vddio_switch) {
1449 case 1:
1450 if (tabla->mbhc_polling_active) {
Bhalchandra Gajarec1e19c42011-11-18 11:22:56 -08001451
1452 tabla_codec_pause_hs_polling(codec);
Joonwoo Park0976d012011-12-22 11:48:18 -08001453 /* VDDIO switch enabled */
Bhalchandra Gajared9ebb6c2011-10-03 19:54:41 -07001454 tabla->cfilt_k_value = snd_soc_read(codec,
1455 tabla->mbhc_bias_regs.cfilt_val);
1456 cfilt_k_val = tabla_find_k_value(
1457 tabla->pdata->micbias.ldoh_v, 1800);
1458 snd_soc_update_bits(codec,
1459 tabla->mbhc_bias_regs.cfilt_val,
1460 0xFC, (cfilt_k_val << 2));
1461
1462 snd_soc_update_bits(codec,
1463 tabla->mbhc_bias_regs.mbhc_reg, 0x80, 0x80);
1464 snd_soc_update_bits(codec,
1465 tabla->mbhc_bias_regs.mbhc_reg, 0x10, 0x00);
Bhalchandra Gajarec1e19c42011-11-18 11:22:56 -08001466 tabla_codec_start_hs_polling(codec);
Bhalchandra Gajared9ebb6c2011-10-03 19:54:41 -07001467
1468 tabla->mbhc_micbias_switched = true;
Joonwoo Park0976d012011-12-22 11:48:18 -08001469 pr_debug("%s: VDDIO switch enabled\n", __func__);
Bhalchandra Gajared9ebb6c2011-10-03 19:54:41 -07001470 }
1471 break;
1472
1473 case 0:
1474 if (tabla->mbhc_micbias_switched) {
Bhalchandra Gajarec1e19c42011-11-18 11:22:56 -08001475 if (tabla->mbhc_polling_active) {
1476 tabla_codec_pause_hs_polling(codec);
1477 mbhc_was_polling = true;
1478 }
Joonwoo Park0976d012011-12-22 11:48:18 -08001479 /* VDDIO switch disabled */
Bhalchandra Gajared9ebb6c2011-10-03 19:54:41 -07001480 if (tabla->cfilt_k_value != 0)
1481 snd_soc_update_bits(codec,
1482 tabla->mbhc_bias_regs.cfilt_val, 0XFC,
1483 tabla->cfilt_k_value);
1484 snd_soc_update_bits(codec,
1485 tabla->mbhc_bias_regs.mbhc_reg, 0x80, 0x00);
1486 snd_soc_update_bits(codec,
1487 tabla->mbhc_bias_regs.mbhc_reg, 0x10, 0x00);
1488
Bhalchandra Gajarec1e19c42011-11-18 11:22:56 -08001489 if (mbhc_was_polling)
1490 tabla_codec_start_hs_polling(codec);
1491
Bhalchandra Gajared9ebb6c2011-10-03 19:54:41 -07001492 tabla->mbhc_micbias_switched = false;
Joonwoo Park0976d012011-12-22 11:48:18 -08001493 pr_debug("%s: VDDIO switch disabled\n", __func__);
Bhalchandra Gajared9ebb6c2011-10-03 19:54:41 -07001494 }
1495 break;
1496 }
1497}
1498
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001499static int tabla_codec_enable_micbias(struct snd_soc_dapm_widget *w,
1500 struct snd_kcontrol *kcontrol, int event)
1501{
1502 struct snd_soc_codec *codec = w->codec;
Patrick Lai3043fba2011-08-01 14:15:57 -07001503 struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
1504 u16 micb_int_reg;
Bradley Rubin4d09cf42011-08-17 17:59:16 -07001505 int micb_line;
Bhalchandra Gajarecc6ffa02011-07-14 18:35:41 -07001506 u8 cfilt_sel_val = 0;
Bradley Rubin229c6a52011-07-12 16:18:48 -07001507 char *internal1_text = "Internal1";
1508 char *internal2_text = "Internal2";
1509 char *internal3_text = "Internal3";
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001510
1511 pr_debug("%s %d\n", __func__, event);
1512 switch (w->reg) {
1513 case TABLA_A_MICB_1_CTL:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001514 micb_int_reg = TABLA_A_MICB_1_INT_RBIAS;
Patrick Lai3043fba2011-08-01 14:15:57 -07001515 cfilt_sel_val = tabla->pdata->micbias.bias1_cfilt_sel;
Bradley Rubin4d09cf42011-08-17 17:59:16 -07001516 micb_line = TABLA_MICBIAS1;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001517 break;
1518 case TABLA_A_MICB_2_CTL:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001519 micb_int_reg = TABLA_A_MICB_2_INT_RBIAS;
Patrick Lai3043fba2011-08-01 14:15:57 -07001520 cfilt_sel_val = tabla->pdata->micbias.bias2_cfilt_sel;
Bradley Rubin4d09cf42011-08-17 17:59:16 -07001521 micb_line = TABLA_MICBIAS2;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001522 break;
1523 case TABLA_A_MICB_3_CTL:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001524 micb_int_reg = TABLA_A_MICB_3_INT_RBIAS;
Patrick Lai3043fba2011-08-01 14:15:57 -07001525 cfilt_sel_val = tabla->pdata->micbias.bias3_cfilt_sel;
Bradley Rubin4d09cf42011-08-17 17:59:16 -07001526 micb_line = TABLA_MICBIAS3;
Bhalchandra Gajarecc6ffa02011-07-14 18:35:41 -07001527 break;
1528 case TABLA_A_MICB_4_CTL:
Bhalchandra Gajarecc6ffa02011-07-14 18:35:41 -07001529 micb_int_reg = TABLA_A_MICB_4_INT_RBIAS;
Patrick Lai3043fba2011-08-01 14:15:57 -07001530 cfilt_sel_val = tabla->pdata->micbias.bias4_cfilt_sel;
Bradley Rubin4d09cf42011-08-17 17:59:16 -07001531 micb_line = TABLA_MICBIAS4;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001532 break;
1533 default:
1534 pr_err("%s: Error, invalid micbias register\n", __func__);
1535 return -EINVAL;
1536 }
1537
1538 switch (event) {
1539 case SND_SOC_DAPM_PRE_PMU:
Bhalchandra Gajared9ebb6c2011-10-03 19:54:41 -07001540 /* Decide whether to switch the micbias for MBHC */
1541 if ((w->reg == tabla->mbhc_bias_regs.ctl_reg)
1542 && tabla->mbhc_micbias_switched)
1543 tabla_codec_switch_micbias(codec, 0);
1544
Bhalchandra Gajarecc6ffa02011-07-14 18:35:41 -07001545 snd_soc_update_bits(codec, w->reg, 0x0E, 0x0A);
Patrick Lai3043fba2011-08-01 14:15:57 -07001546 tabla_codec_update_cfilt_usage(codec, cfilt_sel_val, 1);
Bradley Rubin229c6a52011-07-12 16:18:48 -07001547
1548 if (strnstr(w->name, internal1_text, 30))
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001549 snd_soc_update_bits(codec, micb_int_reg, 0xE0, 0xE0);
Bradley Rubin229c6a52011-07-12 16:18:48 -07001550 else if (strnstr(w->name, internal2_text, 30))
1551 snd_soc_update_bits(codec, micb_int_reg, 0x1C, 0x1C);
1552 else if (strnstr(w->name, internal3_text, 30))
1553 snd_soc_update_bits(codec, micb_int_reg, 0x3, 0x3);
1554
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001555 break;
Bradley Rubin4d09cf42011-08-17 17:59:16 -07001556 case SND_SOC_DAPM_POST_PMU:
1557 if (tabla->mbhc_polling_active &&
Joonwoo Park0976d012011-12-22 11:48:18 -08001558 tabla->micbias == micb_line) {
Bradley Rubin4d09cf42011-08-17 17:59:16 -07001559 tabla_codec_pause_hs_polling(codec);
1560 tabla_codec_start_hs_polling(codec);
1561 }
1562 break;
Bhalchandra Gajared9ebb6c2011-10-03 19:54:41 -07001563
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001564 case SND_SOC_DAPM_POST_PMD:
Bhalchandra Gajared9ebb6c2011-10-03 19:54:41 -07001565
1566 if ((w->reg == tabla->mbhc_bias_regs.ctl_reg)
1567 && tabla_is_hph_pa_on(codec))
1568 tabla_codec_switch_micbias(codec, 1);
1569
Bradley Rubin229c6a52011-07-12 16:18:48 -07001570 if (strnstr(w->name, internal1_text, 30))
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001571 snd_soc_update_bits(codec, micb_int_reg, 0x80, 0x00);
Bradley Rubin229c6a52011-07-12 16:18:48 -07001572 else if (strnstr(w->name, internal2_text, 30))
1573 snd_soc_update_bits(codec, micb_int_reg, 0x10, 0x00);
1574 else if (strnstr(w->name, internal3_text, 30))
1575 snd_soc_update_bits(codec, micb_int_reg, 0x2, 0x0);
1576
Patrick Lai3043fba2011-08-01 14:15:57 -07001577 tabla_codec_update_cfilt_usage(codec, cfilt_sel_val, 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001578 break;
1579 }
1580
1581 return 0;
1582}
1583
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001584static int tabla_codec_enable_dec(struct snd_soc_dapm_widget *w,
1585 struct snd_kcontrol *kcontrol, int event)
1586{
1587 struct snd_soc_codec *codec = w->codec;
1588 u16 dec_reset_reg;
1589
1590 pr_debug("%s %d\n", __func__, event);
1591
1592 if (w->reg == TABLA_A_CDC_CLK_TX_CLK_EN_B1_CTL)
1593 dec_reset_reg = TABLA_A_CDC_CLK_TX_RESET_B1_CTL;
1594 else if (w->reg == TABLA_A_CDC_CLK_TX_CLK_EN_B2_CTL)
1595 dec_reset_reg = TABLA_A_CDC_CLK_TX_RESET_B2_CTL;
1596 else {
1597 pr_err("%s: Error, incorrect dec\n", __func__);
1598 return -EINVAL;
1599 }
1600
1601 switch (event) {
1602 case SND_SOC_DAPM_PRE_PMU:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001603 snd_soc_update_bits(codec, dec_reset_reg, 1 << w->shift,
1604 1 << w->shift);
1605 snd_soc_update_bits(codec, dec_reset_reg, 1 << w->shift, 0x0);
1606 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001607 }
1608 return 0;
1609}
1610
Bradley Rubin74a9b4a2011-06-13 15:03:43 -07001611static int tabla_codec_reset_interpolator(struct snd_soc_dapm_widget *w,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001612 struct snd_kcontrol *kcontrol, int event)
1613{
1614 struct snd_soc_codec *codec = w->codec;
1615
Kiran Kandi8b3a8302011-09-27 16:13:28 -07001616 pr_debug("%s %d %s\n", __func__, event, w->name);
1617
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001618 switch (event) {
1619 case SND_SOC_DAPM_PRE_PMU:
Bradley Rubin74a9b4a2011-06-13 15:03:43 -07001620 snd_soc_update_bits(codec, TABLA_A_CDC_CLK_RX_RESET_CTL,
1621 1 << w->shift, 1 << w->shift);
1622 snd_soc_update_bits(codec, TABLA_A_CDC_CLK_RX_RESET_CTL,
1623 1 << w->shift, 0x0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001624 break;
1625 }
1626 return 0;
1627}
1628
Bradley Rubin229c6a52011-07-12 16:18:48 -07001629static int tabla_codec_enable_ldo_h(struct snd_soc_dapm_widget *w,
1630 struct snd_kcontrol *kcontrol, int event)
1631{
1632 switch (event) {
1633 case SND_SOC_DAPM_POST_PMU:
1634 case SND_SOC_DAPM_POST_PMD:
1635 usleep_range(1000, 1000);
1636 break;
1637 }
1638 return 0;
1639}
1640
Kiran Kandi6fae8bf2011-08-15 10:36:42 -07001641
1642static void tabla_enable_rx_bias(struct snd_soc_codec *codec, u32 enable)
1643{
1644 struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
1645
1646 if (enable) {
1647 tabla->rx_bias_count++;
1648 if (tabla->rx_bias_count == 1)
1649 snd_soc_update_bits(codec, TABLA_A_RX_COM_BIAS,
1650 0x80, 0x80);
1651 } else {
1652 tabla->rx_bias_count--;
1653 if (!tabla->rx_bias_count)
1654 snd_soc_update_bits(codec, TABLA_A_RX_COM_BIAS,
1655 0x80, 0x00);
1656 }
1657}
1658
1659static int tabla_codec_enable_rx_bias(struct snd_soc_dapm_widget *w,
1660 struct snd_kcontrol *kcontrol, int event)
1661{
1662 struct snd_soc_codec *codec = w->codec;
1663
1664 pr_debug("%s %d\n", __func__, event);
1665
1666 switch (event) {
1667 case SND_SOC_DAPM_PRE_PMU:
1668 tabla_enable_rx_bias(codec, 1);
1669 break;
1670 case SND_SOC_DAPM_POST_PMD:
1671 tabla_enable_rx_bias(codec, 0);
1672 break;
1673 }
1674 return 0;
1675}
Kiran Kandi8b3a8302011-09-27 16:13:28 -07001676static int tabla_hphr_dac_event(struct snd_soc_dapm_widget *w,
1677 struct snd_kcontrol *kcontrol, int event)
1678{
1679 struct snd_soc_codec *codec = w->codec;
1680
1681 pr_debug("%s %s %d\n", __func__, w->name, event);
1682
1683 switch (event) {
1684 case SND_SOC_DAPM_PRE_PMU:
1685 snd_soc_update_bits(codec, w->reg, 0x40, 0x40);
1686 break;
1687 case SND_SOC_DAPM_POST_PMD:
1688 snd_soc_update_bits(codec, w->reg, 0x40, 0x00);
1689 break;
1690 }
1691 return 0;
1692}
Kiran Kandi6fae8bf2011-08-15 10:36:42 -07001693
Joonwoo Park8b1f0982011-12-08 17:12:45 -08001694static void tabla_snd_soc_jack_report(struct tabla_priv *tabla,
1695 struct snd_soc_jack *jack, int status,
1696 int mask)
1697{
1698 /* XXX: wake_lock_timeout()? */
1699 snd_soc_jack_report(jack, status, mask);
1700}
1701
Patrick Lai49efeac2011-11-03 11:01:12 -07001702static void hphocp_off_report(struct tabla_priv *tabla,
1703 u32 jack_status, int irq)
1704{
1705 struct snd_soc_codec *codec;
1706
1707 if (tabla) {
1708 pr_info("%s: clear ocp status %x\n", __func__, jack_status);
1709 codec = tabla->codec;
1710 tabla->hph_status &= ~jack_status;
1711 if (tabla->headset_jack)
Joonwoo Park8b1f0982011-12-08 17:12:45 -08001712 tabla_snd_soc_jack_report(tabla, tabla->headset_jack,
1713 tabla->hph_status,
1714 TABLA_JACK_MASK);
Joonwoo Park0976d012011-12-22 11:48:18 -08001715 snd_soc_update_bits(codec, TABLA_A_RX_HPH_OCP_CTL, 0x10, 0x00);
1716 snd_soc_update_bits(codec, TABLA_A_RX_HPH_OCP_CTL, 0x10, 0x10);
Patrick Laic7cae882011-11-18 11:52:49 -08001717 /* reset retry counter as PA is turned off signifying
1718 * start of new OCP detection session
1719 */
1720 if (TABLA_IRQ_HPH_PA_OCPL_FAULT)
1721 tabla->hphlocp_cnt = 0;
1722 else
1723 tabla->hphrocp_cnt = 0;
Patrick Lai49efeac2011-11-03 11:01:12 -07001724 tabla_enable_irq(codec->control_data, irq);
1725 } else {
1726 pr_err("%s: Bad tabla private data\n", __func__);
1727 }
1728}
1729
1730static void hphlocp_off_report(struct work_struct *work)
1731{
1732 struct tabla_priv *tabla = container_of(work, struct tabla_priv,
1733 hphlocp_work);
1734 hphocp_off_report(tabla, SND_JACK_OC_HPHL, TABLA_IRQ_HPH_PA_OCPL_FAULT);
1735}
1736
1737static void hphrocp_off_report(struct work_struct *work)
1738{
1739 struct tabla_priv *tabla = container_of(work, struct tabla_priv,
1740 hphrocp_work);
1741 hphocp_off_report(tabla, SND_JACK_OC_HPHR, TABLA_IRQ_HPH_PA_OCPR_FAULT);
1742}
1743
Kiran Kandibf0b1ff2011-09-15 13:55:21 -07001744static int tabla_hph_pa_event(struct snd_soc_dapm_widget *w,
1745 struct snd_kcontrol *kcontrol, int event)
1746{
Bhalchandra Gajared9ebb6c2011-10-03 19:54:41 -07001747 struct snd_soc_codec *codec = w->codec;
1748 struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
1749 u8 mbhc_micb_ctl_val;
Kiran Kandibf0b1ff2011-09-15 13:55:21 -07001750 pr_debug("%s: event = %d\n", __func__, event);
1751
1752 switch (event) {
Bhalchandra Gajared9ebb6c2011-10-03 19:54:41 -07001753 case SND_SOC_DAPM_PRE_PMU:
1754 mbhc_micb_ctl_val = snd_soc_read(codec,
1755 tabla->mbhc_bias_regs.ctl_reg);
1756
1757 if (!(mbhc_micb_ctl_val & 0x80)
1758 && !tabla->mbhc_micbias_switched)
1759 tabla_codec_switch_micbias(codec, 1);
1760
1761 break;
1762
Kiran Kandibf0b1ff2011-09-15 13:55:21 -07001763 case SND_SOC_DAPM_POST_PMD:
Patrick Lai49efeac2011-11-03 11:01:12 -07001764 /* schedule work is required because at the time HPH PA DAPM
1765 * event callback is called by DAPM framework, CODEC dapm mutex
1766 * would have been locked while snd_soc_jack_report also
1767 * attempts to acquire same lock.
1768 */
Joonwoo Parka9444452011-12-08 18:48:27 -08001769 if (w->shift == 5) {
1770 clear_bit(TABLA_HPHL_PA_OFF_ACK,
1771 &tabla->hph_pa_dac_state);
1772 clear_bit(TABLA_HPHL_DAC_OFF_ACK,
1773 &tabla->hph_pa_dac_state);
1774 if (tabla->hph_status & SND_JACK_OC_HPHL)
1775 schedule_work(&tabla->hphlocp_work);
1776 } else if (w->shift == 4) {
1777 clear_bit(TABLA_HPHR_PA_OFF_ACK,
1778 &tabla->hph_pa_dac_state);
1779 clear_bit(TABLA_HPHR_DAC_OFF_ACK,
1780 &tabla->hph_pa_dac_state);
1781 if (tabla->hph_status & SND_JACK_OC_HPHR)
1782 schedule_work(&tabla->hphrocp_work);
1783 }
1784
Bhalchandra Gajared9ebb6c2011-10-03 19:54:41 -07001785 if (tabla->mbhc_micbias_switched)
1786 tabla_codec_switch_micbias(codec, 0);
1787
Kiran Kandibf0b1ff2011-09-15 13:55:21 -07001788 pr_debug("%s: sleep 10 ms after %s PA disable.\n", __func__,
1789 w->name);
1790 usleep_range(10000, 10000);
1791
1792 break;
1793 }
1794 return 0;
1795}
1796
Bhalchandra Gajare02d90cd2011-09-30 16:14:00 -07001797static void tabla_get_mbhc_micbias_regs(struct snd_soc_codec *codec,
1798 struct mbhc_micbias_regs *micbias_regs)
1799{
1800 struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
Bhalchandra Gajare02d90cd2011-09-30 16:14:00 -07001801 unsigned int cfilt;
1802
Joonwoo Park0976d012011-12-22 11:48:18 -08001803 switch (tabla->micbias) {
Bhalchandra Gajare02d90cd2011-09-30 16:14:00 -07001804 case TABLA_MICBIAS1:
1805 cfilt = tabla->pdata->micbias.bias1_cfilt_sel;
1806 micbias_regs->mbhc_reg = TABLA_A_MICB_1_MBHC;
1807 micbias_regs->int_rbias = TABLA_A_MICB_1_INT_RBIAS;
1808 micbias_regs->ctl_reg = TABLA_A_MICB_1_CTL;
1809 break;
1810 case TABLA_MICBIAS2:
1811 cfilt = tabla->pdata->micbias.bias2_cfilt_sel;
1812 micbias_regs->mbhc_reg = TABLA_A_MICB_2_MBHC;
1813 micbias_regs->int_rbias = TABLA_A_MICB_2_INT_RBIAS;
1814 micbias_regs->ctl_reg = TABLA_A_MICB_2_CTL;
1815 break;
1816 case TABLA_MICBIAS3:
1817 cfilt = tabla->pdata->micbias.bias3_cfilt_sel;
1818 micbias_regs->mbhc_reg = TABLA_A_MICB_3_MBHC;
1819 micbias_regs->int_rbias = TABLA_A_MICB_3_INT_RBIAS;
1820 micbias_regs->ctl_reg = TABLA_A_MICB_3_CTL;
1821 break;
1822 case TABLA_MICBIAS4:
1823 cfilt = tabla->pdata->micbias.bias4_cfilt_sel;
1824 micbias_regs->mbhc_reg = TABLA_A_MICB_4_MBHC;
1825 micbias_regs->int_rbias = TABLA_A_MICB_4_INT_RBIAS;
1826 micbias_regs->ctl_reg = TABLA_A_MICB_4_CTL;
1827 break;
1828 default:
1829 /* Should never reach here */
1830 pr_err("%s: Invalid MIC BIAS for MBHC\n", __func__);
Jordan Crouse239d8412011-11-23 11:47:02 -07001831 return;
Bhalchandra Gajare02d90cd2011-09-30 16:14:00 -07001832 }
1833
Bhalchandra Gajare19d9c132011-11-18 14:57:08 -08001834 micbias_regs->cfilt_sel = cfilt;
1835
Bhalchandra Gajare02d90cd2011-09-30 16:14:00 -07001836 switch (cfilt) {
1837 case TABLA_CFILT1_SEL:
1838 micbias_regs->cfilt_val = TABLA_A_MICB_CFILT_1_VAL;
1839 micbias_regs->cfilt_ctl = TABLA_A_MICB_CFILT_1_CTL;
Joonwoo Park0976d012011-12-22 11:48:18 -08001840 tabla->mbhc_data.micb_mv = tabla->pdata->micbias.cfilt1_mv;
Bhalchandra Gajare02d90cd2011-09-30 16:14:00 -07001841 break;
1842 case TABLA_CFILT2_SEL:
1843 micbias_regs->cfilt_val = TABLA_A_MICB_CFILT_2_VAL;
1844 micbias_regs->cfilt_ctl = TABLA_A_MICB_CFILT_2_CTL;
Joonwoo Park0976d012011-12-22 11:48:18 -08001845 tabla->mbhc_data.micb_mv = tabla->pdata->micbias.cfilt2_mv;
Bhalchandra Gajare02d90cd2011-09-30 16:14:00 -07001846 break;
1847 case TABLA_CFILT3_SEL:
1848 micbias_regs->cfilt_val = TABLA_A_MICB_CFILT_3_VAL;
1849 micbias_regs->cfilt_ctl = TABLA_A_MICB_CFILT_3_CTL;
Joonwoo Park0976d012011-12-22 11:48:18 -08001850 tabla->mbhc_data.micb_mv = tabla->pdata->micbias.cfilt3_mv;
Bhalchandra Gajare02d90cd2011-09-30 16:14:00 -07001851 break;
1852 }
1853}
Santosh Mardie15e2302011-11-15 10:39:23 +05301854static const struct snd_soc_dapm_widget tabla_dapm_i2s_widgets[] = {
1855 SND_SOC_DAPM_SUPPLY("RX_I2S_CLK", TABLA_A_CDC_CLK_RX_I2S_CTL,
1856 4, 0, NULL, 0),
1857 SND_SOC_DAPM_SUPPLY("TX_I2S_CLK", TABLA_A_CDC_CLK_TX_I2S_CTL, 4,
1858 0, NULL, 0),
1859};
Bhalchandra Gajare02d90cd2011-09-30 16:14:00 -07001860
Kiran Kandi8b3a8302011-09-27 16:13:28 -07001861static int tabla_lineout_dac_event(struct snd_soc_dapm_widget *w,
1862 struct snd_kcontrol *kcontrol, int event)
1863{
1864 struct snd_soc_codec *codec = w->codec;
1865
1866 pr_debug("%s %s %d\n", __func__, w->name, event);
1867
1868 switch (event) {
1869 case SND_SOC_DAPM_PRE_PMU:
1870 snd_soc_update_bits(codec, w->reg, 0x40, 0x40);
1871 break;
1872
1873 case SND_SOC_DAPM_POST_PMD:
1874 snd_soc_update_bits(codec, w->reg, 0x40, 0x00);
1875 break;
1876 }
1877 return 0;
1878}
1879
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001880static const struct snd_soc_dapm_widget tabla_dapm_widgets[] = {
1881 /*RX stuff */
1882 SND_SOC_DAPM_OUTPUT("EAR"),
1883
Kiran Kandid2d86b52011-09-09 17:44:28 -07001884 SND_SOC_DAPM_PGA("EAR PA", TABLA_A_RX_EAR_EN, 4, 0, NULL, 0),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001885
Bradley Rubin229c6a52011-07-12 16:18:48 -07001886 SND_SOC_DAPM_MIXER("DAC1", TABLA_A_RX_EAR_EN, 6, 0, dac1_switch,
1887 ARRAY_SIZE(dac1_switch)),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001888
Bradley Rubin229c6a52011-07-12 16:18:48 -07001889 SND_SOC_DAPM_AIF_IN("SLIM RX1", "AIF1 Playback", 0, SND_SOC_NOPM, 0, 0),
1890 SND_SOC_DAPM_AIF_IN("SLIM RX2", "AIF1 Playback", 0, SND_SOC_NOPM, 0, 0),
Santosh Mardie15e2302011-11-15 10:39:23 +05301891 SND_SOC_DAPM_AIF_IN("SLIM RX3", "AIF1 Playback", 0, SND_SOC_NOPM, 0, 0),
1892 SND_SOC_DAPM_AIF_IN("SLIM RX4", "AIF1 Playback", 0, SND_SOC_NOPM, 0, 0),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001893
1894 /* Headphone */
1895 SND_SOC_DAPM_OUTPUT("HEADPHONE"),
Kiran Kandibf0b1ff2011-09-15 13:55:21 -07001896 SND_SOC_DAPM_PGA_E("HPHL", TABLA_A_RX_HPH_CNP_EN, 5, 0, NULL, 0,
Bhalchandra Gajared9ebb6c2011-10-03 19:54:41 -07001897 tabla_hph_pa_event, SND_SOC_DAPM_PRE_PMU |
1898 SND_SOC_DAPM_POST_PMD),
Bradley Rubin229c6a52011-07-12 16:18:48 -07001899 SND_SOC_DAPM_MIXER("HPHL DAC", TABLA_A_RX_HPH_L_DAC_CTL, 7, 0,
1900 hphl_switch, ARRAY_SIZE(hphl_switch)),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001901
Kiran Kandibf0b1ff2011-09-15 13:55:21 -07001902 SND_SOC_DAPM_PGA_E("HPHR", TABLA_A_RX_HPH_CNP_EN, 4, 0, NULL, 0,
Bhalchandra Gajared9ebb6c2011-10-03 19:54:41 -07001903 tabla_hph_pa_event, SND_SOC_DAPM_PRE_PMU |
1904 SND_SOC_DAPM_POST_PMD),
Kiran Kandi8b3a8302011-09-27 16:13:28 -07001905
1906 SND_SOC_DAPM_DAC_E("HPHR DAC", NULL, TABLA_A_RX_HPH_R_DAC_CTL, 7, 0,
1907 tabla_hphr_dac_event,
1908 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001909
1910 /* Speaker */
Kiran Kandidb0a4b02011-08-23 09:32:09 -07001911 SND_SOC_DAPM_OUTPUT("LINEOUT1"),
1912 SND_SOC_DAPM_OUTPUT("LINEOUT2"),
1913 SND_SOC_DAPM_OUTPUT("LINEOUT3"),
1914 SND_SOC_DAPM_OUTPUT("LINEOUT4"),
1915 SND_SOC_DAPM_OUTPUT("LINEOUT5"),
Bradley Rubin74a9b4a2011-06-13 15:03:43 -07001916
Kiran Kandidb0a4b02011-08-23 09:32:09 -07001917 SND_SOC_DAPM_PGA_E("LINEOUT1 PA", TABLA_A_RX_LINE_CNP_EN, 0, 0, NULL,
1918 0, tabla_codec_enable_lineout, SND_SOC_DAPM_PRE_PMU |
1919 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
1920 SND_SOC_DAPM_PGA_E("LINEOUT2 PA", TABLA_A_RX_LINE_CNP_EN, 1, 0, NULL,
1921 0, tabla_codec_enable_lineout, SND_SOC_DAPM_PRE_PMU |
1922 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
1923 SND_SOC_DAPM_PGA_E("LINEOUT3 PA", TABLA_A_RX_LINE_CNP_EN, 2, 0, NULL,
1924 0, tabla_codec_enable_lineout, SND_SOC_DAPM_PRE_PMU |
1925 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
1926 SND_SOC_DAPM_PGA_E("LINEOUT4 PA", TABLA_A_RX_LINE_CNP_EN, 3, 0, NULL,
1927 0, tabla_codec_enable_lineout, SND_SOC_DAPM_PRE_PMU |
1928 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
1929 SND_SOC_DAPM_PGA_E("LINEOUT5 PA", TABLA_A_RX_LINE_CNP_EN, 4, 0, NULL, 0,
Bhalchandra Gajare0a8ad172011-08-12 13:32:22 -07001930 tabla_codec_enable_lineout, SND_SOC_DAPM_PRE_PMU |
1931 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
Bradley Rubin74a9b4a2011-06-13 15:03:43 -07001932
Kiran Kandi8b3a8302011-09-27 16:13:28 -07001933 SND_SOC_DAPM_DAC_E("LINEOUT1 DAC", NULL, TABLA_A_RX_LINE_1_DAC_CTL, 7, 0
1934 , tabla_lineout_dac_event,
1935 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
1936 SND_SOC_DAPM_DAC_E("LINEOUT2 DAC", NULL, TABLA_A_RX_LINE_2_DAC_CTL, 7, 0
1937 , tabla_lineout_dac_event,
1938 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
1939 SND_SOC_DAPM_DAC_E("LINEOUT3 DAC", NULL, TABLA_A_RX_LINE_3_DAC_CTL, 7, 0
1940 , tabla_lineout_dac_event,
1941 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
1942 SND_SOC_DAPM_SWITCH("LINEOUT3 DAC GROUND", SND_SOC_NOPM, 0, 0,
1943 &lineout3_ground_switch),
1944 SND_SOC_DAPM_DAC_E("LINEOUT4 DAC", NULL, TABLA_A_RX_LINE_4_DAC_CTL, 7, 0
1945 , tabla_lineout_dac_event,
1946 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
1947 SND_SOC_DAPM_SWITCH("LINEOUT4 DAC GROUND", SND_SOC_NOPM, 0, 0,
1948 &lineout4_ground_switch),
1949 SND_SOC_DAPM_DAC_E("LINEOUT5 DAC", NULL, TABLA_A_RX_LINE_5_DAC_CTL, 7, 0
1950 , tabla_lineout_dac_event,
1951 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
Bradley Rubin74a9b4a2011-06-13 15:03:43 -07001952
Bradley Rubin229c6a52011-07-12 16:18:48 -07001953 SND_SOC_DAPM_MIXER_E("RX1 MIX1", TABLA_A_CDC_CLK_RX_B1_CTL, 0, 0, NULL,
1954 0, tabla_codec_reset_interpolator, SND_SOC_DAPM_PRE_PMU),
1955 SND_SOC_DAPM_MIXER_E("RX2 MIX1", TABLA_A_CDC_CLK_RX_B1_CTL, 1, 0, NULL,
1956 0, tabla_codec_reset_interpolator, SND_SOC_DAPM_PRE_PMU),
1957 SND_SOC_DAPM_MIXER_E("RX3 MIX1", TABLA_A_CDC_CLK_RX_B1_CTL, 2, 0, NULL,
1958 0, tabla_codec_reset_interpolator, SND_SOC_DAPM_PRE_PMU),
1959 SND_SOC_DAPM_MIXER_E("RX4 MIX1", TABLA_A_CDC_CLK_RX_B1_CTL, 3, 0, NULL,
1960 0, tabla_codec_reset_interpolator, SND_SOC_DAPM_PRE_PMU),
1961 SND_SOC_DAPM_MIXER_E("RX5 MIX1", TABLA_A_CDC_CLK_RX_B1_CTL, 4, 0, NULL,
1962 0, tabla_codec_reset_interpolator, SND_SOC_DAPM_PRE_PMU),
1963 SND_SOC_DAPM_MIXER_E("RX6 MIX1", TABLA_A_CDC_CLK_RX_B1_CTL, 5, 0, NULL,
1964 0, tabla_codec_reset_interpolator, SND_SOC_DAPM_PRE_PMU),
Bhalchandra Gajare0a8ad172011-08-12 13:32:22 -07001965 SND_SOC_DAPM_MIXER_E("RX7 MIX1", TABLA_A_CDC_CLK_RX_B1_CTL, 6, 0, NULL,
1966 0, tabla_codec_reset_interpolator, SND_SOC_DAPM_PRE_PMU),
Bradley Rubin74a9b4a2011-06-13 15:03:43 -07001967
Kiran Kandi8b3a8302011-09-27 16:13:28 -07001968
1969 SND_SOC_DAPM_MUX_E("RX4 DSM MUX", TABLA_A_CDC_CLK_RX_B1_CTL, 3, 0,
1970 &rx4_dsm_mux, tabla_codec_reset_interpolator,
1971 SND_SOC_DAPM_PRE_PMU),
1972
1973 SND_SOC_DAPM_MUX_E("RX6 DSM MUX", TABLA_A_CDC_CLK_RX_B1_CTL, 5, 0,
1974 &rx6_dsm_mux, tabla_codec_reset_interpolator,
1975 SND_SOC_DAPM_PRE_PMU),
1976
Bradley Rubin229c6a52011-07-12 16:18:48 -07001977 SND_SOC_DAPM_MIXER("RX1 CHAIN", TABLA_A_CDC_RX1_B6_CTL, 5, 0, NULL, 0),
1978 SND_SOC_DAPM_MIXER("RX2 CHAIN", TABLA_A_CDC_RX2_B6_CTL, 5, 0, NULL, 0),
1979
1980 SND_SOC_DAPM_MUX("RX1 MIX1 INP1", SND_SOC_NOPM, 0, 0,
1981 &rx_mix1_inp1_mux),
1982 SND_SOC_DAPM_MUX("RX1 MIX1 INP2", SND_SOC_NOPM, 0, 0,
1983 &rx_mix1_inp2_mux),
1984 SND_SOC_DAPM_MUX("RX2 MIX1 INP1", SND_SOC_NOPM, 0, 0,
1985 &rx2_mix1_inp1_mux),
1986 SND_SOC_DAPM_MUX("RX2 MIX1 INP2", SND_SOC_NOPM, 0, 0,
1987 &rx2_mix1_inp2_mux),
Bradley Rubin74a9b4a2011-06-13 15:03:43 -07001988 SND_SOC_DAPM_MUX("RX3 MIX1 INP1", SND_SOC_NOPM, 0, 0,
1989 &rx3_mix1_inp1_mux),
1990 SND_SOC_DAPM_MUX("RX3 MIX1 INP2", SND_SOC_NOPM, 0, 0,
1991 &rx3_mix1_inp2_mux),
1992 SND_SOC_DAPM_MUX("RX4 MIX1 INP1", SND_SOC_NOPM, 0, 0,
1993 &rx4_mix1_inp1_mux),
1994 SND_SOC_DAPM_MUX("RX4 MIX1 INP2", SND_SOC_NOPM, 0, 0,
1995 &rx4_mix1_inp2_mux),
1996 SND_SOC_DAPM_MUX("RX5 MIX1 INP1", SND_SOC_NOPM, 0, 0,
1997 &rx5_mix1_inp1_mux),
1998 SND_SOC_DAPM_MUX("RX5 MIX1 INP2", SND_SOC_NOPM, 0, 0,
1999 &rx5_mix1_inp2_mux),
2000 SND_SOC_DAPM_MUX("RX6 MIX1 INP1", SND_SOC_NOPM, 0, 0,
2001 &rx6_mix1_inp1_mux),
2002 SND_SOC_DAPM_MUX("RX6 MIX1 INP2", SND_SOC_NOPM, 0, 0,
2003 &rx6_mix1_inp2_mux),
Bhalchandra Gajare0a8ad172011-08-12 13:32:22 -07002004 SND_SOC_DAPM_MUX("RX7 MIX1 INP1", SND_SOC_NOPM, 0, 0,
2005 &rx7_mix1_inp1_mux),
2006 SND_SOC_DAPM_MUX("RX7 MIX1 INP2", SND_SOC_NOPM, 0, 0,
2007 &rx7_mix1_inp2_mux),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002008
Bradley Rubin229c6a52011-07-12 16:18:48 -07002009 SND_SOC_DAPM_SUPPLY("CP", TABLA_A_CP_EN, 0, 0,
2010 tabla_codec_enable_charge_pump, SND_SOC_DAPM_POST_PMU |
2011 SND_SOC_DAPM_PRE_PMD),
2012
Kiran Kandi6fae8bf2011-08-15 10:36:42 -07002013 SND_SOC_DAPM_SUPPLY("RX_BIAS", SND_SOC_NOPM, 0, 0,
2014 tabla_codec_enable_rx_bias, SND_SOC_DAPM_PRE_PMU |
2015 SND_SOC_DAPM_POST_PMD),
2016
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002017 /* TX */
Bradley Rubin229c6a52011-07-12 16:18:48 -07002018
Bradley Rubine1d08622011-07-20 18:01:35 -07002019 SND_SOC_DAPM_SUPPLY("CDC_CONN", TABLA_A_CDC_CLK_OTHR_CTL, 2, 0, NULL,
2020 0),
2021
Bradley Rubin229c6a52011-07-12 16:18:48 -07002022 SND_SOC_DAPM_SUPPLY("LDO_H", TABLA_A_LDO_H_MODE_1, 7, 0,
2023 tabla_codec_enable_ldo_h, SND_SOC_DAPM_POST_PMU),
2024
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002025 SND_SOC_DAPM_INPUT("AMIC1"),
2026 SND_SOC_DAPM_MICBIAS_E("MIC BIAS1 External", TABLA_A_MICB_1_CTL, 7, 0,
2027 tabla_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
Bradley Rubin4d09cf42011-08-17 17:59:16 -07002028 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
Bradley Rubin229c6a52011-07-12 16:18:48 -07002029 SND_SOC_DAPM_MICBIAS_E("MIC BIAS1 Internal1", TABLA_A_MICB_1_CTL, 7, 0,
2030 tabla_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
Bradley Rubin4d09cf42011-08-17 17:59:16 -07002031 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
Bradley Rubin229c6a52011-07-12 16:18:48 -07002032 SND_SOC_DAPM_MICBIAS_E("MIC BIAS1 Internal2", TABLA_A_MICB_1_CTL, 7, 0,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002033 tabla_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
Bradley Rubin4d09cf42011-08-17 17:59:16 -07002034 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002035 SND_SOC_DAPM_ADC_E("ADC1", NULL, TABLA_A_TX_1_2_EN, 7, 0,
2036 tabla_codec_enable_adc, SND_SOC_DAPM_PRE_PMU |
2037 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
2038
Bhalchandra Gajarecc6ffa02011-07-14 18:35:41 -07002039 SND_SOC_DAPM_INPUT("AMIC3"),
2040 SND_SOC_DAPM_ADC_E("ADC3", NULL, TABLA_A_TX_3_4_EN, 7, 0,
2041 tabla_codec_enable_adc, SND_SOC_DAPM_PRE_PMU |
2042 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
2043
2044 SND_SOC_DAPM_INPUT("AMIC4"),
2045 SND_SOC_DAPM_ADC_E("ADC4", NULL, TABLA_A_TX_3_4_EN, 3, 0,
2046 tabla_codec_enable_adc, SND_SOC_DAPM_PRE_PMU |
2047 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
2048
2049 SND_SOC_DAPM_MICBIAS_E("MIC BIAS4 External", TABLA_A_MICB_4_CTL, 7, 0,
2050 tabla_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
Bradley Rubin4d09cf42011-08-17 17:59:16 -07002051 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
Bhalchandra Gajarecc6ffa02011-07-14 18:35:41 -07002052
Bhalchandra Gajare0d77e1b2011-07-08 10:54:14 -07002053 SND_SOC_DAPM_INPUT("AMIC5"),
2054 SND_SOC_DAPM_ADC_E("ADC5", NULL, TABLA_A_TX_5_6_EN, 7, 0,
2055 tabla_codec_enable_adc, SND_SOC_DAPM_POST_PMU),
2056
2057 SND_SOC_DAPM_INPUT("AMIC6"),
2058 SND_SOC_DAPM_ADC_E("ADC6", NULL, TABLA_A_TX_5_6_EN, 3, 0,
2059 tabla_codec_enable_adc, SND_SOC_DAPM_POST_PMU),
2060
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002061 SND_SOC_DAPM_MUX_E("DEC1 MUX", TABLA_A_CDC_CLK_TX_CLK_EN_B1_CTL, 0, 0,
Bradley Rubine1d08622011-07-20 18:01:35 -07002062 &dec1_mux, tabla_codec_enable_dec, SND_SOC_DAPM_PRE_PMU),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002063
Bhalchandra Gajare0d77e1b2011-07-08 10:54:14 -07002064 SND_SOC_DAPM_MUX_E("DEC2 MUX", TABLA_A_CDC_CLK_TX_CLK_EN_B1_CTL, 1, 0,
Bradley Rubine1d08622011-07-20 18:01:35 -07002065 &dec2_mux, tabla_codec_enable_dec, SND_SOC_DAPM_PRE_PMU),
Bhalchandra Gajare0d77e1b2011-07-08 10:54:14 -07002066
Bhalchandra Gajarecc6ffa02011-07-14 18:35:41 -07002067 SND_SOC_DAPM_MUX_E("DEC3 MUX", TABLA_A_CDC_CLK_TX_CLK_EN_B1_CTL, 2, 0,
Bradley Rubine1d08622011-07-20 18:01:35 -07002068 &dec3_mux, tabla_codec_enable_dec, SND_SOC_DAPM_PRE_PMU),
Bhalchandra Gajarecc6ffa02011-07-14 18:35:41 -07002069
2070 SND_SOC_DAPM_MUX_E("DEC4 MUX", TABLA_A_CDC_CLK_TX_CLK_EN_B1_CTL, 3, 0,
Bradley Rubine1d08622011-07-20 18:01:35 -07002071 &dec4_mux, tabla_codec_enable_dec, SND_SOC_DAPM_PRE_PMU),
Bhalchandra Gajarecc6ffa02011-07-14 18:35:41 -07002072
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002073 SND_SOC_DAPM_MUX_E("DEC5 MUX", TABLA_A_CDC_CLK_TX_CLK_EN_B1_CTL, 4, 0,
Bradley Rubine1d08622011-07-20 18:01:35 -07002074 &dec5_mux, tabla_codec_enable_dec, SND_SOC_DAPM_PRE_PMU),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002075
2076 SND_SOC_DAPM_MUX_E("DEC6 MUX", TABLA_A_CDC_CLK_TX_CLK_EN_B1_CTL, 5, 0,
Bradley Rubine1d08622011-07-20 18:01:35 -07002077 &dec6_mux, tabla_codec_enable_dec, SND_SOC_DAPM_PRE_PMU),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002078
2079 SND_SOC_DAPM_MUX_E("DEC7 MUX", TABLA_A_CDC_CLK_TX_CLK_EN_B1_CTL, 6, 0,
Bradley Rubine1d08622011-07-20 18:01:35 -07002080 &dec7_mux, tabla_codec_enable_dec, SND_SOC_DAPM_PRE_PMU),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002081
Bhalchandra Gajare0d77e1b2011-07-08 10:54:14 -07002082 SND_SOC_DAPM_MUX_E("DEC8 MUX", TABLA_A_CDC_CLK_TX_CLK_EN_B1_CTL, 7, 0,
Bradley Rubine1d08622011-07-20 18:01:35 -07002083 &dec8_mux, tabla_codec_enable_dec, SND_SOC_DAPM_PRE_PMU),
Bhalchandra Gajare0d77e1b2011-07-08 10:54:14 -07002084
Bhalchandra Gajarecc6ffa02011-07-14 18:35:41 -07002085 SND_SOC_DAPM_MUX_E("DEC9 MUX", TABLA_A_CDC_CLK_TX_CLK_EN_B2_CTL, 0, 0,
Bradley Rubine1d08622011-07-20 18:01:35 -07002086 &dec9_mux, tabla_codec_enable_dec, SND_SOC_DAPM_PRE_PMU),
Bhalchandra Gajarecc6ffa02011-07-14 18:35:41 -07002087
2088 SND_SOC_DAPM_MUX_E("DEC10 MUX", TABLA_A_CDC_CLK_TX_CLK_EN_B2_CTL, 1, 0,
Bradley Rubine1d08622011-07-20 18:01:35 -07002089 &dec10_mux, tabla_codec_enable_dec, SND_SOC_DAPM_PRE_PMU),
Bhalchandra Gajarecc6ffa02011-07-14 18:35:41 -07002090
Bradley Rubin229c6a52011-07-12 16:18:48 -07002091 SND_SOC_DAPM_MUX("ANC1 MUX", SND_SOC_NOPM, 0, 0, &anc1_mux),
2092 SND_SOC_DAPM_MUX("ANC2 MUX", SND_SOC_NOPM, 0, 0, &anc2_mux),
2093
2094 SND_SOC_DAPM_MIXER_E("ANC", SND_SOC_NOPM, 0, 0, NULL, 0,
2095 tabla_codec_enable_anc, SND_SOC_DAPM_PRE_PMU |
2096 SND_SOC_DAPM_POST_PMD),
2097
2098 SND_SOC_DAPM_MUX("ANC1 FB MUX", SND_SOC_NOPM, 0, 0, &anc1_fb_mux),
2099
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002100 SND_SOC_DAPM_INPUT("AMIC2"),
2101 SND_SOC_DAPM_MICBIAS_E("MIC BIAS2 External", TABLA_A_MICB_2_CTL, 7, 0,
2102 tabla_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
Bradley Rubin4d09cf42011-08-17 17:59:16 -07002103 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
Bradley Rubin229c6a52011-07-12 16:18:48 -07002104 SND_SOC_DAPM_MICBIAS_E("MIC BIAS2 Internal1", TABLA_A_MICB_2_CTL, 7, 0,
2105 tabla_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
Bradley Rubin4d09cf42011-08-17 17:59:16 -07002106 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
Bradley Rubin229c6a52011-07-12 16:18:48 -07002107 SND_SOC_DAPM_MICBIAS_E("MIC BIAS2 Internal2", TABLA_A_MICB_2_CTL, 7, 0,
2108 tabla_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
Bradley Rubin4d09cf42011-08-17 17:59:16 -07002109 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
Bradley Rubin229c6a52011-07-12 16:18:48 -07002110 SND_SOC_DAPM_MICBIAS_E("MIC BIAS2 Internal3", TABLA_A_MICB_2_CTL, 7, 0,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002111 tabla_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
Bradley Rubin4d09cf42011-08-17 17:59:16 -07002112 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002113 SND_SOC_DAPM_MICBIAS_E("MIC BIAS3 External", TABLA_A_MICB_3_CTL, 7, 0,
2114 tabla_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
Bradley Rubin4d09cf42011-08-17 17:59:16 -07002115 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
Bradley Rubin229c6a52011-07-12 16:18:48 -07002116 SND_SOC_DAPM_MICBIAS_E("MIC BIAS3 Internal1", TABLA_A_MICB_3_CTL, 7, 0,
2117 tabla_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
Bradley Rubin4d09cf42011-08-17 17:59:16 -07002118 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
Bradley Rubin229c6a52011-07-12 16:18:48 -07002119 SND_SOC_DAPM_MICBIAS_E("MIC BIAS3 Internal2", TABLA_A_MICB_3_CTL, 7, 0,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002120 tabla_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
Bradley Rubin4d09cf42011-08-17 17:59:16 -07002121 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002122 SND_SOC_DAPM_ADC_E("ADC2", NULL, TABLA_A_TX_1_2_EN, 3, 0,
2123 tabla_codec_enable_adc, SND_SOC_DAPM_PRE_PMU |
2124 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
2125
2126 SND_SOC_DAPM_MUX("SLIM TX1 MUX", SND_SOC_NOPM, 0, 0, &sb_tx1_mux),
2127 SND_SOC_DAPM_AIF_OUT("SLIM TX1", "AIF1 Capture", NULL, SND_SOC_NOPM,
2128 0, 0),
2129
2130 SND_SOC_DAPM_MUX("SLIM TX5 MUX", SND_SOC_NOPM, 0, 0, &sb_tx5_mux),
2131 SND_SOC_DAPM_AIF_OUT("SLIM TX5", "AIF1 Capture", NULL, SND_SOC_NOPM,
2132 4, 0),
2133
2134 SND_SOC_DAPM_MUX("SLIM TX6 MUX", SND_SOC_NOPM, 0, 0, &sb_tx6_mux),
2135 SND_SOC_DAPM_AIF_OUT("SLIM TX6", "AIF1 Capture", NULL, SND_SOC_NOPM,
2136 5, 0),
2137
2138 SND_SOC_DAPM_MUX("SLIM TX7 MUX", SND_SOC_NOPM, 0, 0, &sb_tx7_mux),
2139 SND_SOC_DAPM_AIF_OUT("SLIM TX7", "AIF1 Capture", NULL, SND_SOC_NOPM,
2140 0, 0),
2141
2142 SND_SOC_DAPM_MUX("SLIM TX8 MUX", SND_SOC_NOPM, 0, 0, &sb_tx8_mux),
2143 SND_SOC_DAPM_AIF_OUT("SLIM TX8", "AIF1 Capture", NULL, SND_SOC_NOPM,
2144 0, 0),
2145
Kiran Kandicf45f6a2011-07-17 21:10:19 -07002146 /* Digital Mic Inputs */
Bhalchandra Gajare7cf018e2011-08-11 18:58:32 -07002147 SND_SOC_DAPM_ADC_E("DMIC1", NULL, SND_SOC_NOPM, 0, 0,
2148 tabla_codec_enable_dmic, SND_SOC_DAPM_PRE_PMU |
2149 SND_SOC_DAPM_POST_PMD),
2150
2151 SND_SOC_DAPM_ADC_E("DMIC2", NULL, SND_SOC_NOPM, 0, 0,
2152 tabla_codec_enable_dmic, SND_SOC_DAPM_PRE_PMU |
2153 SND_SOC_DAPM_POST_PMD),
2154
2155 SND_SOC_DAPM_ADC_E("DMIC3", NULL, SND_SOC_NOPM, 0, 0,
2156 tabla_codec_enable_dmic, SND_SOC_DAPM_PRE_PMU |
2157 SND_SOC_DAPM_POST_PMD),
2158
2159 SND_SOC_DAPM_ADC_E("DMIC4", NULL, SND_SOC_NOPM, 0, 0,
2160 tabla_codec_enable_dmic, SND_SOC_DAPM_PRE_PMU |
2161 SND_SOC_DAPM_POST_PMD),
2162
2163 SND_SOC_DAPM_ADC_E("DMIC5", NULL, SND_SOC_NOPM, 0, 0,
2164 tabla_codec_enable_dmic, SND_SOC_DAPM_PRE_PMU |
2165 SND_SOC_DAPM_POST_PMD),
2166
2167 SND_SOC_DAPM_ADC_E("DMIC6", NULL, SND_SOC_NOPM, 0, 0,
2168 tabla_codec_enable_dmic, SND_SOC_DAPM_PRE_PMU |
2169 SND_SOC_DAPM_POST_PMD),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002170
2171 /* Sidetone */
2172 SND_SOC_DAPM_MUX("IIR1 INP1 MUX", SND_SOC_NOPM, 0, 0, &iir1_inp1_mux),
2173 SND_SOC_DAPM_PGA("IIR1", TABLA_A_CDC_CLK_SD_CTL, 0, 0, NULL, 0),
2174};
2175
Santosh Mardie15e2302011-11-15 10:39:23 +05302176static const struct snd_soc_dapm_route audio_i2s_map[] = {
2177 {"RX_I2S_CLK", NULL, "CDC_CONN"},
2178 {"SLIM RX1", NULL, "RX_I2S_CLK"},
2179 {"SLIM RX2", NULL, "RX_I2S_CLK"},
2180 {"SLIM RX3", NULL, "RX_I2S_CLK"},
2181 {"SLIM RX4", NULL, "RX_I2S_CLK"},
2182
2183 {"SLIM TX7", NULL, "TX_I2S_CLK"},
2184 {"SLIM TX8", NULL, "TX_I2S_CLK"},
2185 {"SLIM TX9", NULL, "TX_I2S_CLK"},
2186 {"SLIM TX10", NULL, "TX_I2S_CLK"},
2187};
2188
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002189static const struct snd_soc_dapm_route audio_map[] = {
2190 /* SLIMBUS Connections */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002191
2192 {"SLIM TX1", NULL, "SLIM TX1 MUX"},
2193 {"SLIM TX1 MUX", "DEC1", "DEC1 MUX"},
2194
2195 {"SLIM TX5", NULL, "SLIM TX5 MUX"},
2196 {"SLIM TX5 MUX", "DEC5", "DEC5 MUX"},
2197
2198 {"SLIM TX6", NULL, "SLIM TX6 MUX"},
2199 {"SLIM TX6 MUX", "DEC6", "DEC6 MUX"},
2200
2201 {"SLIM TX7", NULL, "SLIM TX7 MUX"},
2202 {"SLIM TX7 MUX", "DEC1", "DEC1 MUX"},
Bhalchandra Gajare0d77e1b2011-07-08 10:54:14 -07002203 {"SLIM TX7 MUX", "DEC2", "DEC2 MUX"},
Bhalchandra Gajarecc6ffa02011-07-14 18:35:41 -07002204 {"SLIM TX7 MUX", "DEC3", "DEC3 MUX"},
2205 {"SLIM TX7 MUX", "DEC4", "DEC4 MUX"},
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002206 {"SLIM TX7 MUX", "DEC5", "DEC5 MUX"},
2207 {"SLIM TX7 MUX", "DEC6", "DEC6 MUX"},
Bhalchandra Gajare0d77e1b2011-07-08 10:54:14 -07002208 {"SLIM TX7 MUX", "DEC7", "DEC7 MUX"},
2209 {"SLIM TX7 MUX", "DEC8", "DEC8 MUX"},
Bhalchandra Gajarecc6ffa02011-07-14 18:35:41 -07002210 {"SLIM TX7 MUX", "DEC9", "DEC9 MUX"},
2211 {"SLIM TX7 MUX", "DEC10", "DEC10 MUX"},
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002212
2213 {"SLIM TX8", NULL, "SLIM TX8 MUX"},
Kiran Kandicf45f6a2011-07-17 21:10:19 -07002214 {"SLIM TX8 MUX", "DEC1", "DEC1 MUX"},
2215 {"SLIM TX8 MUX", "DEC2", "DEC2 MUX"},
2216 {"SLIM TX8 MUX", "DEC3", "DEC3 MUX"},
Bhalchandra Gajare9ec83cd2011-09-23 17:25:07 -07002217 {"SLIM TX8 MUX", "DEC4", "DEC4 MUX"},
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002218 {"SLIM TX8 MUX", "DEC5", "DEC5 MUX"},
2219 {"SLIM TX8 MUX", "DEC6", "DEC6 MUX"},
2220
2221 /* Earpiece (RX MIX1) */
2222 {"EAR", NULL, "EAR PA"},
Kiran Kandiac034ac2011-07-29 16:39:08 -07002223 {"EAR PA", NULL, "DAC1"},
Bradley Rubin229c6a52011-07-12 16:18:48 -07002224 {"DAC1", NULL, "CP"},
2225
2226 {"ANC1 FB MUX", "EAR_HPH_L", "RX1 MIX1"},
2227 {"ANC1 FB MUX", "EAR_LINE_1", "RX2 MIX1"},
2228 {"ANC", NULL, "ANC1 FB MUX"},
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002229
2230 /* Headset (RX MIX1 and RX MIX2) */
2231 {"HEADPHONE", NULL, "HPHL"},
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002232 {"HEADPHONE", NULL, "HPHR"},
Bradley Rubin229c6a52011-07-12 16:18:48 -07002233
2234 {"HPHL", NULL, "HPHL DAC"},
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002235 {"HPHR", NULL, "HPHR DAC"},
Bradley Rubin229c6a52011-07-12 16:18:48 -07002236
2237 {"HPHL DAC", NULL, "CP"},
2238 {"HPHR DAC", NULL, "CP"},
2239
2240 {"ANC", NULL, "ANC1 MUX"},
2241 {"ANC", NULL, "ANC2 MUX"},
2242 {"ANC1 MUX", "ADC1", "ADC1"},
2243 {"ANC1 MUX", "ADC2", "ADC2"},
2244 {"ANC1 MUX", "ADC3", "ADC3"},
2245 {"ANC1 MUX", "ADC4", "ADC4"},
2246 {"ANC2 MUX", "ADC1", "ADC1"},
2247 {"ANC2 MUX", "ADC2", "ADC2"},
2248 {"ANC2 MUX", "ADC3", "ADC3"},
2249 {"ANC2 MUX", "ADC4", "ADC4"},
2250
Bradley Rubine1d08622011-07-20 18:01:35 -07002251 {"ANC", NULL, "CDC_CONN"},
2252
Bradley Rubin229c6a52011-07-12 16:18:48 -07002253 {"DAC1", "Switch", "RX1 CHAIN"},
2254 {"HPHL DAC", "Switch", "RX1 CHAIN"},
Kiran Kandi8b3a8302011-09-27 16:13:28 -07002255 {"HPHR DAC", NULL, "RX2 CHAIN"},
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002256
Kiran Kandidb0a4b02011-08-23 09:32:09 -07002257 {"LINEOUT1", NULL, "LINEOUT1 PA"},
2258 {"LINEOUT2", NULL, "LINEOUT2 PA"},
2259 {"LINEOUT3", NULL, "LINEOUT3 PA"},
2260 {"LINEOUT4", NULL, "LINEOUT4 PA"},
2261 {"LINEOUT5", NULL, "LINEOUT5 PA"},
Bradley Rubin74a9b4a2011-06-13 15:03:43 -07002262
Kiran Kandidb0a4b02011-08-23 09:32:09 -07002263 {"LINEOUT1 PA", NULL, "LINEOUT1 DAC"},
2264 {"LINEOUT2 PA", NULL, "LINEOUT2 DAC"},
2265 {"LINEOUT3 PA", NULL, "LINEOUT3 DAC"},
2266 {"LINEOUT4 PA", NULL, "LINEOUT4 DAC"},
2267 {"LINEOUT5 PA", NULL, "LINEOUT5 DAC"},
Bradley Rubin74a9b4a2011-06-13 15:03:43 -07002268
Kiran Kandi8b3a8302011-09-27 16:13:28 -07002269 {"LINEOUT1 DAC", NULL, "RX3 MIX1"},
2270 {"LINEOUT5 DAC", NULL, "RX7 MIX1"},
2271
Bradley Rubin229c6a52011-07-12 16:18:48 -07002272 {"RX1 CHAIN", NULL, "RX1 MIX1"},
2273 {"RX2 CHAIN", NULL, "RX2 MIX1"},
2274 {"RX1 CHAIN", NULL, "ANC"},
2275 {"RX2 CHAIN", NULL, "ANC"},
Bradley Rubin74a9b4a2011-06-13 15:03:43 -07002276
Kiran Kandi6fae8bf2011-08-15 10:36:42 -07002277 {"CP", NULL, "RX_BIAS"},
2278 {"LINEOUT1 DAC", NULL, "RX_BIAS"},
2279 {"LINEOUT2 DAC", NULL, "RX_BIAS"},
2280 {"LINEOUT3 DAC", NULL, "RX_BIAS"},
2281 {"LINEOUT4 DAC", NULL, "RX_BIAS"},
Kiran Kandi8b3a8302011-09-27 16:13:28 -07002282 {"LINEOUT5 DAC", NULL, "RX_BIAS"},
Kiran Kandi6fae8bf2011-08-15 10:36:42 -07002283
Bradley Rubin229c6a52011-07-12 16:18:48 -07002284 {"RX1 MIX1", NULL, "RX1 MIX1 INP1"},
2285 {"RX1 MIX1", NULL, "RX1 MIX1 INP2"},
2286 {"RX2 MIX1", NULL, "RX2 MIX1 INP1"},
2287 {"RX2 MIX1", NULL, "RX2 MIX1 INP2"},
Bradley Rubin74a9b4a2011-06-13 15:03:43 -07002288 {"RX3 MIX1", NULL, "RX3 MIX1 INP1"},
2289 {"RX3 MIX1", NULL, "RX3 MIX1 INP2"},
2290 {"RX4 MIX1", NULL, "RX4 MIX1 INP1"},
2291 {"RX4 MIX1", NULL, "RX4 MIX1 INP2"},
2292 {"RX5 MIX1", NULL, "RX5 MIX1 INP1"},
2293 {"RX5 MIX1", NULL, "RX5 MIX1 INP2"},
2294 {"RX6 MIX1", NULL, "RX6 MIX1 INP1"},
2295 {"RX6 MIX1", NULL, "RX6 MIX1 INP2"},
Bhalchandra Gajare0a8ad172011-08-12 13:32:22 -07002296 {"RX7 MIX1", NULL, "RX7 MIX1 INP1"},
2297 {"RX7 MIX1", NULL, "RX7 MIX1 INP2"},
Bradley Rubin74a9b4a2011-06-13 15:03:43 -07002298
Bradley Rubin229c6a52011-07-12 16:18:48 -07002299 {"RX1 MIX1 INP1", "RX1", "SLIM RX1"},
2300 {"RX1 MIX1 INP1", "RX2", "SLIM RX2"},
Santosh Mardie15e2302011-11-15 10:39:23 +05302301 {"RX1 MIX1 INP1", "RX3", "SLIM RX3"},
2302 {"RX1 MIX1 INP1", "RX4", "SLIM RX4"},
Bradley Rubin229c6a52011-07-12 16:18:48 -07002303 {"RX1 MIX1 INP1", "IIR1", "IIR1"},
2304 {"RX1 MIX1 INP2", "RX1", "SLIM RX1"},
2305 {"RX1 MIX1 INP2", "RX2", "SLIM RX2"},
Santosh Mardie15e2302011-11-15 10:39:23 +05302306 {"RX1 MIX1 INP2", "RX3", "SLIM RX3"},
2307 {"RX1 MIX1 INP2", "RX4", "SLIM RX4"},
Bradley Rubin229c6a52011-07-12 16:18:48 -07002308 {"RX1 MIX1 INP2", "IIR1", "IIR1"},
2309 {"RX2 MIX1 INP1", "RX1", "SLIM RX1"},
2310 {"RX2 MIX1 INP1", "RX2", "SLIM RX2"},
Santosh Mardie15e2302011-11-15 10:39:23 +05302311 {"RX2 MIX1 INP1", "RX3", "SLIM RX3"},
2312 {"RX2 MIX1 INP1", "RX4", "SLIM RX4"},
Patrick Lai16261e82011-09-30 13:25:52 -07002313 {"RX2 MIX1 INP1", "IIR1", "IIR1"},
Bradley Rubin229c6a52011-07-12 16:18:48 -07002314 {"RX2 MIX1 INP2", "RX1", "SLIM RX1"},
2315 {"RX2 MIX1 INP2", "RX2", "SLIM RX2"},
Santosh Mardie15e2302011-11-15 10:39:23 +05302316 {"RX2 MIX1 INP2", "RX3", "SLIM RX3"},
2317 {"RX2 MIX1 INP2", "RX4", "SLIM RX4"},
Patrick Lai16261e82011-09-30 13:25:52 -07002318 {"RX2 MIX1 INP2", "IIR1", "IIR1"},
Bradley Rubin229c6a52011-07-12 16:18:48 -07002319 {"RX3 MIX1 INP1", "RX1", "SLIM RX1"},
2320 {"RX3 MIX1 INP1", "RX2", "SLIM RX2"},
Santosh Mardie15e2302011-11-15 10:39:23 +05302321 {"RX3 MIX1 INP1", "RX3", "SLIM RX3"},
2322 {"RX3 MIX1 INP1", "RX4", "SLIM RX4"},
Patrick Lai16261e82011-09-30 13:25:52 -07002323 {"RX3 MIX1 INP1", "IIR1", "IIR1"},
Bradley Rubin229c6a52011-07-12 16:18:48 -07002324 {"RX3 MIX1 INP2", "RX1", "SLIM RX1"},
2325 {"RX3 MIX1 INP2", "RX2", "SLIM RX2"},
Santosh Mardie15e2302011-11-15 10:39:23 +05302326 {"RX3 MIX1 INP2", "RX3", "SLIM RX3"},
2327 {"RX3 MIX1 INP2", "RX4", "SLIM RX4"},
Patrick Lai16261e82011-09-30 13:25:52 -07002328 {"RX3 MIX1 INP2", "IIR1", "IIR1"},
Bradley Rubin229c6a52011-07-12 16:18:48 -07002329 {"RX4 MIX1 INP1", "RX1", "SLIM RX1"},
2330 {"RX4 MIX1 INP1", "RX2", "SLIM RX2"},
Santosh Mardie15e2302011-11-15 10:39:23 +05302331 {"RX4 MIX1 INP1", "RX3", "SLIM RX3"},
2332 {"RX4 MIX1 INP1", "RX4", "SLIM RX4"},
Patrick Lai16261e82011-09-30 13:25:52 -07002333 {"RX4 MIX1 INP1", "IIR1", "IIR1"},
Bradley Rubin229c6a52011-07-12 16:18:48 -07002334 {"RX4 MIX1 INP2", "RX1", "SLIM RX1"},
2335 {"RX4 MIX1 INP2", "RX2", "SLIM RX2"},
Santosh Mardie15e2302011-11-15 10:39:23 +05302336 {"RX4 MIX1 INP2", "RX3", "SLIM RX3"},
2337 {"RX4 MIX1 INP2", "RX4", "SLIM RX4"},
Patrick Lai16261e82011-09-30 13:25:52 -07002338 {"RX4 MIX1 INP2", "IIR1", "IIR1"},
Bradley Rubin229c6a52011-07-12 16:18:48 -07002339 {"RX5 MIX1 INP1", "RX1", "SLIM RX1"},
2340 {"RX5 MIX1 INP1", "RX2", "SLIM RX2"},
Santosh Mardie15e2302011-11-15 10:39:23 +05302341 {"RX5 MIX1 INP1", "RX3", "SLIM RX3"},
2342 {"RX5 MIX1 INP1", "RX4", "SLIM RX4"},
Patrick Lai16261e82011-09-30 13:25:52 -07002343 {"RX5 MIX1 INP1", "IIR1", "IIR1"},
Bradley Rubin229c6a52011-07-12 16:18:48 -07002344 {"RX5 MIX1 INP2", "RX1", "SLIM RX1"},
2345 {"RX5 MIX1 INP2", "RX2", "SLIM RX2"},
Santosh Mardie15e2302011-11-15 10:39:23 +05302346 {"RX5 MIX1 INP2", "RX3", "SLIM RX3"},
2347 {"RX5 MIX1 INP2", "RX4", "SLIM RX4"},
Patrick Lai16261e82011-09-30 13:25:52 -07002348 {"RX5 MIX1 INP2", "IIR1", "IIR1"},
Bradley Rubin229c6a52011-07-12 16:18:48 -07002349 {"RX6 MIX1 INP1", "RX1", "SLIM RX1"},
2350 {"RX6 MIX1 INP1", "RX2", "SLIM RX2"},
Santosh Mardie15e2302011-11-15 10:39:23 +05302351 {"RX6 MIX1 INP1", "RX3", "SLIM RX3"},
2352 {"RX6 MIX1 INP1", "RX4", "SLIM RX4"},
Patrick Lai16261e82011-09-30 13:25:52 -07002353 {"RX6 MIX1 INP1", "IIR1", "IIR1"},
Bradley Rubin229c6a52011-07-12 16:18:48 -07002354 {"RX6 MIX1 INP2", "RX1", "SLIM RX1"},
2355 {"RX6 MIX1 INP2", "RX2", "SLIM RX2"},
Santosh Mardie15e2302011-11-15 10:39:23 +05302356 {"RX6 MIX1 INP2", "RX3", "SLIM RX3"},
2357 {"RX6 MIX1 INP2", "RX4", "SLIM RX4"},
Patrick Lai16261e82011-09-30 13:25:52 -07002358 {"RX6 MIX1 INP2", "IIR1", "IIR1"},
Bhalchandra Gajare0a8ad172011-08-12 13:32:22 -07002359 {"RX7 MIX1 INP1", "RX1", "SLIM RX1"},
2360 {"RX7 MIX1 INP1", "RX2", "SLIM RX2"},
Santosh Mardie15e2302011-11-15 10:39:23 +05302361 {"RX7 MIX1 INP1", "RX3", "SLIM RX3"},
2362 {"RX7 MIX1 INP1", "RX4", "SLIM RX4"},
Patrick Lai16261e82011-09-30 13:25:52 -07002363 {"RX7 MIX1 INP1", "IIR1", "IIR1"},
Bhalchandra Gajare0a8ad172011-08-12 13:32:22 -07002364 {"RX7 MIX1 INP2", "RX1", "SLIM RX1"},
2365 {"RX7 MIX1 INP2", "RX2", "SLIM RX2"},
Santosh Mardie15e2302011-11-15 10:39:23 +05302366 {"RX7 MIX1 INP2", "RX3", "SLIM RX3"},
2367 {"RX7 MIX1 INP2", "RX4", "SLIM RX4"},
Patrick Lai16261e82011-09-30 13:25:52 -07002368 {"RX7 MIX1 INP2", "IIR1", "IIR1"},
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002369
Bhalchandra Gajarecc6ffa02011-07-14 18:35:41 -07002370 /* Decimator Inputs */
Bhalchandra Gajarecc6ffa02011-07-14 18:35:41 -07002371 {"DEC1 MUX", "DMIC1", "DMIC1"},
Kiran Kandicf45f6a2011-07-17 21:10:19 -07002372 {"DEC1 MUX", "ADC6", "ADC6"},
Bradley Rubine1d08622011-07-20 18:01:35 -07002373 {"DEC1 MUX", NULL, "CDC_CONN"},
Kiran Kandicf45f6a2011-07-17 21:10:19 -07002374 {"DEC2 MUX", "DMIC2", "DMIC2"},
Bhalchandra Gajarecc6ffa02011-07-14 18:35:41 -07002375 {"DEC2 MUX", "ADC5", "ADC5"},
Bradley Rubine1d08622011-07-20 18:01:35 -07002376 {"DEC2 MUX", NULL, "CDC_CONN"},
Kiran Kandicf45f6a2011-07-17 21:10:19 -07002377 {"DEC3 MUX", "DMIC3", "DMIC3"},
Bhalchandra Gajarecc6ffa02011-07-14 18:35:41 -07002378 {"DEC3 MUX", "ADC4", "ADC4"},
Bradley Rubine1d08622011-07-20 18:01:35 -07002379 {"DEC3 MUX", NULL, "CDC_CONN"},
Bhalchandra Gajare7cf018e2011-08-11 18:58:32 -07002380 {"DEC4 MUX", "DMIC4", "DMIC4"},
Bhalchandra Gajarecc6ffa02011-07-14 18:35:41 -07002381 {"DEC4 MUX", "ADC3", "ADC3"},
Bradley Rubine1d08622011-07-20 18:01:35 -07002382 {"DEC4 MUX", NULL, "CDC_CONN"},
Bhalchandra Gajare7cf018e2011-08-11 18:58:32 -07002383 {"DEC5 MUX", "DMIC5", "DMIC5"},
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002384 {"DEC5 MUX", "ADC2", "ADC2"},
Bradley Rubine1d08622011-07-20 18:01:35 -07002385 {"DEC5 MUX", NULL, "CDC_CONN"},
Bhalchandra Gajare7cf018e2011-08-11 18:58:32 -07002386 {"DEC6 MUX", "DMIC6", "DMIC6"},
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002387 {"DEC6 MUX", "ADC1", "ADC1"},
Bradley Rubine1d08622011-07-20 18:01:35 -07002388 {"DEC6 MUX", NULL, "CDC_CONN"},
Bhalchandra Gajarecc6ffa02011-07-14 18:35:41 -07002389 {"DEC7 MUX", "DMIC1", "DMIC1"},
Kiran Kandicf45f6a2011-07-17 21:10:19 -07002390 {"DEC7 MUX", "ADC6", "ADC6"},
Bradley Rubine1d08622011-07-20 18:01:35 -07002391 {"DEC7 MUX", NULL, "CDC_CONN"},
Bhalchandra Gajarecc6ffa02011-07-14 18:35:41 -07002392 {"DEC8 MUX", "ADC5", "ADC5"},
Bradley Rubine1d08622011-07-20 18:01:35 -07002393 {"DEC8 MUX", NULL, "CDC_CONN"},
Bhalchandra Gajarecc6ffa02011-07-14 18:35:41 -07002394 {"DEC9 MUX", "ADC3", "ADC3"},
Bradley Rubine1d08622011-07-20 18:01:35 -07002395 {"DEC9 MUX", NULL, "CDC_CONN"},
Bhalchandra Gajarecc6ffa02011-07-14 18:35:41 -07002396 {"DEC10 MUX", "ADC4", "ADC4"},
Bradley Rubine1d08622011-07-20 18:01:35 -07002397 {"DEC10 MUX", NULL, "CDC_CONN"},
Bhalchandra Gajarecc6ffa02011-07-14 18:35:41 -07002398
2399 /* ADC Connections */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002400 {"ADC1", NULL, "AMIC1"},
2401 {"ADC2", NULL, "AMIC2"},
Bhalchandra Gajarecc6ffa02011-07-14 18:35:41 -07002402 {"ADC3", NULL, "AMIC3"},
2403 {"ADC4", NULL, "AMIC4"},
2404 {"ADC5", NULL, "AMIC5"},
2405 {"ADC6", NULL, "AMIC6"},
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002406
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002407 {"IIR1", NULL, "IIR1 INP1 MUX"},
Patrick Lai16261e82011-09-30 13:25:52 -07002408 {"IIR1 INP1 MUX", "DEC1", "DEC1 MUX"},
2409 {"IIR1 INP1 MUX", "DEC2", "DEC2 MUX"},
2410 {"IIR1 INP1 MUX", "DEC3", "DEC3 MUX"},
2411 {"IIR1 INP1 MUX", "DEC4", "DEC4 MUX"},
2412 {"IIR1 INP1 MUX", "DEC5", "DEC5 MUX"},
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002413 {"IIR1 INP1 MUX", "DEC6", "DEC6 MUX"},
Patrick Lai16261e82011-09-30 13:25:52 -07002414 {"IIR1 INP1 MUX", "DEC7", "DEC7 MUX"},
2415 {"IIR1 INP1 MUX", "DEC8", "DEC8 MUX"},
2416 {"IIR1 INP1 MUX", "DEC9", "DEC9 MUX"},
2417 {"IIR1 INP1 MUX", "DEC10", "DEC10 MUX"},
Bradley Rubin229c6a52011-07-12 16:18:48 -07002418
2419 {"MIC BIAS1 Internal1", NULL, "LDO_H"},
2420 {"MIC BIAS1 Internal2", NULL, "LDO_H"},
2421 {"MIC BIAS1 External", NULL, "LDO_H"},
2422 {"MIC BIAS2 Internal1", NULL, "LDO_H"},
2423 {"MIC BIAS2 Internal2", NULL, "LDO_H"},
2424 {"MIC BIAS2 Internal3", NULL, "LDO_H"},
2425 {"MIC BIAS2 External", NULL, "LDO_H"},
2426 {"MIC BIAS3 Internal1", NULL, "LDO_H"},
2427 {"MIC BIAS3 Internal2", NULL, "LDO_H"},
2428 {"MIC BIAS3 External", NULL, "LDO_H"},
2429 {"MIC BIAS4 External", NULL, "LDO_H"},
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002430};
2431
Kiran Kandi8b3a8302011-09-27 16:13:28 -07002432static const struct snd_soc_dapm_route tabla_1_x_lineout_2_to_4_map[] = {
2433
2434 {"RX4 DSM MUX", "DSM_INV", "RX3 MIX1"},
2435 {"RX4 DSM MUX", "CIC_OUT", "RX4 MIX1"},
2436
2437 {"LINEOUT2 DAC", NULL, "RX4 DSM MUX"},
2438
2439 {"LINEOUT3 DAC", NULL, "RX5 MIX1"},
2440 {"LINEOUT3 DAC GROUND", "Switch", "RX3 MIX1"},
2441 {"LINEOUT3 DAC", NULL, "LINEOUT3 DAC GROUND"},
2442
2443 {"RX6 DSM MUX", "DSM_INV", "RX5 MIX1"},
2444 {"RX6 DSM MUX", "CIC_OUT", "RX6 MIX1"},
2445
2446 {"LINEOUT4 DAC", NULL, "RX6 DSM MUX"},
2447 {"LINEOUT4 DAC GROUND", "Switch", "RX4 DSM MUX"},
2448 {"LINEOUT4 DAC", NULL, "LINEOUT4 DAC GROUND"},
2449};
2450
Kiran Kandi7a9fd902011-11-14 13:51:45 -08002451
2452static const struct snd_soc_dapm_route tabla_2_x_lineout_2_to_4_map[] = {
2453
2454 {"RX4 DSM MUX", "DSM_INV", "RX3 MIX1"},
2455 {"RX4 DSM MUX", "CIC_OUT", "RX4 MIX1"},
2456
2457 {"LINEOUT3 DAC", NULL, "RX4 DSM MUX"},
2458
2459 {"LINEOUT2 DAC", NULL, "RX5 MIX1"},
2460
2461 {"RX6 DSM MUX", "DSM_INV", "RX5 MIX1"},
2462 {"RX6 DSM MUX", "CIC_OUT", "RX6 MIX1"},
2463
2464 {"LINEOUT4 DAC", NULL, "RX6 DSM MUX"},
2465};
2466
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002467static int tabla_readable(struct snd_soc_codec *ssc, unsigned int reg)
2468{
2469 return tabla_reg_readable[reg];
2470}
2471
2472static int tabla_volatile(struct snd_soc_codec *ssc, unsigned int reg)
2473{
2474 /* Registers lower than 0x100 are top level registers which can be
2475 * written by the Tabla core driver.
2476 */
2477
2478 if ((reg >= TABLA_A_CDC_MBHC_EN_CTL) || (reg < 0x100))
2479 return 1;
2480
Ben Romberger1f045a72011-11-04 10:14:57 -07002481 /* IIR Coeff registers are not cacheable */
2482 if ((reg >= TABLA_A_CDC_IIR1_COEF_B1_CTL) &&
2483 (reg <= TABLA_A_CDC_IIR2_COEF_B5_CTL))
2484 return 1;
2485
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002486 return 0;
2487}
2488
2489#define TABLA_FORMATS (SNDRV_PCM_FMTBIT_S16_LE)
2490static int tabla_write(struct snd_soc_codec *codec, unsigned int reg,
2491 unsigned int value)
2492{
2493 int ret;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002494
2495 BUG_ON(reg > TABLA_MAX_REGISTER);
2496
2497 if (!tabla_volatile(codec, reg)) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002498 ret = snd_soc_cache_write(codec, reg, value);
2499 if (ret != 0)
2500 dev_err(codec->dev, "Cache write to %x failed: %d\n",
2501 reg, ret);
2502 }
2503
2504 return tabla_reg_write(codec->control_data, reg, value);
2505}
2506static unsigned int tabla_read(struct snd_soc_codec *codec,
2507 unsigned int reg)
2508{
2509 unsigned int val;
2510 int ret;
2511
2512 BUG_ON(reg > TABLA_MAX_REGISTER);
2513
2514 if (!tabla_volatile(codec, reg) && tabla_readable(codec, reg) &&
2515 reg < codec->driver->reg_cache_size) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002516 ret = snd_soc_cache_read(codec, reg, &val);
2517 if (ret >= 0) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002518 return val;
2519 } else
2520 dev_err(codec->dev, "Cache read from %x failed: %d\n",
2521 reg, ret);
2522 }
2523
2524 val = tabla_reg_read(codec->control_data, reg);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002525 return val;
2526}
2527
2528static void tabla_codec_enable_audio_mode_bandgap(struct snd_soc_codec *codec)
2529{
2530 snd_soc_write(codec, TABLA_A_BIAS_REF_CTL, 0x1C);
2531 snd_soc_update_bits(codec, TABLA_A_BIAS_CENTRAL_BG_CTL, 0x80,
2532 0x80);
2533 snd_soc_update_bits(codec, TABLA_A_BIAS_CENTRAL_BG_CTL, 0x04,
2534 0x04);
2535 snd_soc_update_bits(codec, TABLA_A_BIAS_CENTRAL_BG_CTL, 0x01,
2536 0x01);
2537 usleep_range(1000, 1000);
2538 snd_soc_update_bits(codec, TABLA_A_BIAS_CENTRAL_BG_CTL, 0x80,
2539 0x00);
2540}
2541
2542static void tabla_codec_enable_bandgap(struct snd_soc_codec *codec,
2543 enum tabla_bandgap_type choice)
2544{
2545 struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
2546
2547 /* TODO lock resources accessed by audio streams and threaded
2548 * interrupt handlers
2549 */
2550
2551 pr_debug("%s, choice is %d, current is %d\n", __func__, choice,
2552 tabla->bandgap_type);
2553
2554 if (tabla->bandgap_type == choice)
2555 return;
2556
2557 if ((tabla->bandgap_type == TABLA_BANDGAP_OFF) &&
2558 (choice == TABLA_BANDGAP_AUDIO_MODE)) {
2559 tabla_codec_enable_audio_mode_bandgap(codec);
2560 } else if ((tabla->bandgap_type == TABLA_BANDGAP_AUDIO_MODE) &&
2561 (choice == TABLA_BANDGAP_MBHC_MODE)) {
2562 snd_soc_update_bits(codec, TABLA_A_BIAS_CENTRAL_BG_CTL, 0x2,
2563 0x2);
2564 snd_soc_update_bits(codec, TABLA_A_BIAS_CENTRAL_BG_CTL, 0x80,
2565 0x80);
2566 snd_soc_update_bits(codec, TABLA_A_BIAS_CENTRAL_BG_CTL, 0x4,
2567 0x4);
2568 usleep_range(1000, 1000);
2569 snd_soc_update_bits(codec, TABLA_A_BIAS_CENTRAL_BG_CTL, 0x80,
2570 0x00);
2571 } else if ((tabla->bandgap_type == TABLA_BANDGAP_MBHC_MODE) &&
2572 (choice == TABLA_BANDGAP_AUDIO_MODE)) {
2573 snd_soc_write(codec, TABLA_A_BIAS_CENTRAL_BG_CTL, 0x00);
2574 usleep_range(100, 100);
2575 tabla_codec_enable_audio_mode_bandgap(codec);
2576 } else if (choice == TABLA_BANDGAP_OFF) {
2577 snd_soc_write(codec, TABLA_A_BIAS_CENTRAL_BG_CTL, 0x00);
2578 } else {
2579 pr_err("%s: Error, Invalid bandgap settings\n", __func__);
2580 }
2581 tabla->bandgap_type = choice;
2582}
2583
2584static int tabla_codec_enable_config_mode(struct snd_soc_codec *codec,
2585 int enable)
2586{
2587 struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
2588
2589 if (enable) {
2590 snd_soc_update_bits(codec, TABLA_A_CONFIG_MODE_FREQ, 0x10, 0);
2591 snd_soc_write(codec, TABLA_A_BIAS_CONFIG_MODE_BG_CTL, 0x17);
2592 usleep_range(5, 5);
2593 snd_soc_update_bits(codec, TABLA_A_CONFIG_MODE_FREQ, 0x80,
2594 0x80);
2595 snd_soc_update_bits(codec, TABLA_A_CONFIG_MODE_TEST, 0x80,
2596 0x80);
2597 usleep_range(10, 10);
2598 snd_soc_update_bits(codec, TABLA_A_CONFIG_MODE_TEST, 0x80, 0);
2599 usleep_range(20, 20);
2600 snd_soc_update_bits(codec, TABLA_A_CLK_BUFF_EN1, 0x08, 0x08);
2601 } else {
2602 snd_soc_update_bits(codec, TABLA_A_BIAS_CONFIG_MODE_BG_CTL, 0x1,
2603 0);
2604 snd_soc_update_bits(codec, TABLA_A_CONFIG_MODE_FREQ, 0x80, 0);
2605 }
2606 tabla->config_mode_active = enable ? true : false;
2607
2608 return 0;
2609}
2610
2611static int tabla_codec_enable_clock_block(struct snd_soc_codec *codec,
2612 int config_mode)
2613{
2614 struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
2615
2616 pr_debug("%s\n", __func__);
2617
2618 if (config_mode) {
2619 tabla_codec_enable_config_mode(codec, 1);
2620 snd_soc_write(codec, TABLA_A_CLK_BUFF_EN2, 0x00);
2621 snd_soc_write(codec, TABLA_A_CLK_BUFF_EN2, 0x02);
2622 snd_soc_write(codec, TABLA_A_CLK_BUFF_EN1, 0x0D);
2623 usleep_range(1000, 1000);
2624 } else
2625 snd_soc_update_bits(codec, TABLA_A_CLK_BUFF_EN1, 0x08, 0x00);
2626
2627 if (!config_mode && tabla->mbhc_polling_active) {
2628 snd_soc_write(codec, TABLA_A_CLK_BUFF_EN2, 0x02);
2629 tabla_codec_enable_config_mode(codec, 0);
2630
2631 }
2632
2633 snd_soc_update_bits(codec, TABLA_A_CLK_BUFF_EN1, 0x05, 0x05);
2634 snd_soc_update_bits(codec, TABLA_A_CLK_BUFF_EN2, 0x02, 0x00);
2635 snd_soc_update_bits(codec, TABLA_A_CLK_BUFF_EN2, 0x04, 0x04);
2636 snd_soc_update_bits(codec, TABLA_A_CDC_CLK_MCLK_CTL, 0x01, 0x01);
2637 usleep_range(50, 50);
2638 tabla->clock_active = true;
2639 return 0;
2640}
2641static void tabla_codec_disable_clock_block(struct snd_soc_codec *codec)
2642{
2643 struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
2644 pr_debug("%s\n", __func__);
2645 snd_soc_update_bits(codec, TABLA_A_CLK_BUFF_EN2, 0x04, 0x00);
2646 ndelay(160);
2647 snd_soc_update_bits(codec, TABLA_A_CLK_BUFF_EN2, 0x02, 0x02);
2648 snd_soc_update_bits(codec, TABLA_A_CLK_BUFF_EN1, 0x05, 0x00);
2649 tabla->clock_active = false;
2650}
2651
Bradley Rubincb1e2732011-06-23 16:49:20 -07002652static void tabla_codec_calibrate_hs_polling(struct snd_soc_codec *codec)
2653{
Joonwoo Park0976d012011-12-22 11:48:18 -08002654 u8 *n_cic;
2655 struct tabla_mbhc_btn_detect_cfg *btn_det;
2656 struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
Bradley Rubincb1e2732011-06-23 16:49:20 -07002657
Joonwoo Park0976d012011-12-22 11:48:18 -08002658 btn_det = TABLA_MBHC_CAL_BTN_DET_PTR(tabla->calibration);
Bradley Rubincb1e2732011-06-23 16:49:20 -07002659
Joonwoo Park0976d012011-12-22 11:48:18 -08002660 snd_soc_write(codec, TABLA_A_CDC_MBHC_VOLT_B1_CTL,
2661 tabla->mbhc_data.v_ins_hu & 0xFF);
2662 snd_soc_write(codec, TABLA_A_CDC_MBHC_VOLT_B2_CTL,
2663 (tabla->mbhc_data.v_ins_hu >> 8) & 0xFF);
Bradley Rubincb1e2732011-06-23 16:49:20 -07002664
Joonwoo Park0976d012011-12-22 11:48:18 -08002665 snd_soc_write(codec, TABLA_A_CDC_MBHC_VOLT_B3_CTL,
2666 tabla->mbhc_data.v_b1_hu & 0xFF);
2667 snd_soc_write(codec, TABLA_A_CDC_MBHC_VOLT_B4_CTL,
2668 (tabla->mbhc_data.v_b1_hu >> 8) & 0xFF);
2669
2670 snd_soc_write(codec, TABLA_A_CDC_MBHC_VOLT_B5_CTL,
2671 tabla->mbhc_data.v_b1_h & 0xFF);
2672 snd_soc_write(codec, TABLA_A_CDC_MBHC_VOLT_B6_CTL,
2673 (tabla->mbhc_data.v_b1_h >> 8) & 0xFF);
2674
2675 snd_soc_write(codec, TABLA_A_CDC_MBHC_VOLT_B9_CTL,
2676 tabla->mbhc_data.v_brh & 0xFF);
2677 snd_soc_write(codec, TABLA_A_CDC_MBHC_VOLT_B10_CTL,
2678 (tabla->mbhc_data.v_brh >> 8) & 0xFF);
2679
2680 snd_soc_write(codec, TABLA_A_CDC_MBHC_VOLT_B11_CTL,
2681 tabla->mbhc_data.v_brl & 0xFF);
2682 snd_soc_write(codec, TABLA_A_CDC_MBHC_VOLT_B12_CTL,
2683 (tabla->mbhc_data.v_brl >> 8) & 0xFF);
2684
2685 snd_soc_write(codec, TABLA_A_CDC_MBHC_TIMER_B1_CTL,
2686 tabla->mbhc_data.nready);
2687 snd_soc_write(codec, TABLA_A_CDC_MBHC_TIMER_B2_CTL,
2688 tabla->mbhc_data.npoll);
2689 snd_soc_write(codec, TABLA_A_CDC_MBHC_TIMER_B3_CTL,
2690 tabla->mbhc_data.nbounce_wait);
2691
2692 n_cic = tabla_mbhc_cal_btn_det_mp(btn_det, TABLA_BTN_DET_N_CIC);
2693 snd_soc_write(codec, TABLA_A_CDC_MBHC_TIMER_B6_CTL, n_cic[0]);
Bradley Rubincb1e2732011-06-23 16:49:20 -07002694}
2695
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002696static int tabla_startup(struct snd_pcm_substream *substream,
2697 struct snd_soc_dai *dai)
2698{
Kiran Kandi6fae8bf2011-08-15 10:36:42 -07002699 pr_debug("%s(): substream = %s stream = %d\n" , __func__,
2700 substream->name, substream->stream);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002701
Kiran Kandi6fae8bf2011-08-15 10:36:42 -07002702 return 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002703}
2704
2705static void tabla_shutdown(struct snd_pcm_substream *substream,
2706 struct snd_soc_dai *dai)
2707{
Kiran Kandi6fae8bf2011-08-15 10:36:42 -07002708 pr_debug("%s(): substream = %s stream = %d\n" , __func__,
2709 substream->name, substream->stream);
2710}
2711
2712int tabla_mclk_enable(struct snd_soc_codec *codec, int mclk_enable)
2713{
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002714 struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
2715
Kiran Kandi6fae8bf2011-08-15 10:36:42 -07002716 pr_debug("%s() mclk_enable = %u\n", __func__, mclk_enable);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002717
Kiran Kandi6fae8bf2011-08-15 10:36:42 -07002718 if (mclk_enable) {
2719 tabla->mclk_enabled = true;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002720
Kiran Kandi6fae8bf2011-08-15 10:36:42 -07002721 if (tabla->mbhc_polling_active && (tabla->mclk_enabled)) {
Bradley Rubincb1e2732011-06-23 16:49:20 -07002722 tabla_codec_pause_hs_polling(codec);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002723 tabla_codec_enable_bandgap(codec,
Kiran Kandi6fae8bf2011-08-15 10:36:42 -07002724 TABLA_BANDGAP_AUDIO_MODE);
2725 tabla_codec_enable_clock_block(codec, 0);
Bradley Rubincb1e2732011-06-23 16:49:20 -07002726 tabla_codec_calibrate_hs_polling(codec);
2727 tabla_codec_start_hs_polling(codec);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002728 }
Kiran Kandi6fae8bf2011-08-15 10:36:42 -07002729 } else {
2730
2731 if (!tabla->mclk_enabled) {
2732 pr_err("Error, MCLK already diabled\n");
2733 return -EINVAL;
2734 }
2735 tabla->mclk_enabled = false;
2736
2737 if (tabla->mbhc_polling_active) {
2738 if (!tabla->mclk_enabled) {
2739 tabla_codec_pause_hs_polling(codec);
2740 tabla_codec_enable_bandgap(codec,
2741 TABLA_BANDGAP_MBHC_MODE);
2742 tabla_enable_rx_bias(codec, 1);
2743 tabla_codec_enable_clock_block(codec, 1);
2744 tabla_codec_calibrate_hs_polling(codec);
2745 tabla_codec_start_hs_polling(codec);
2746 }
2747 snd_soc_update_bits(codec, TABLA_A_CLK_BUFF_EN1,
2748 0x05, 0x01);
2749 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002750 }
Kiran Kandi6fae8bf2011-08-15 10:36:42 -07002751 return 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002752}
2753
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002754static int tabla_set_dai_sysclk(struct snd_soc_dai *dai,
2755 int clk_id, unsigned int freq, int dir)
2756{
2757 pr_debug("%s\n", __func__);
2758 return 0;
2759}
2760
2761static int tabla_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
2762{
Santosh Mardie15e2302011-11-15 10:39:23 +05302763 u8 val = 0;
2764 struct tabla_priv *tabla = snd_soc_codec_get_drvdata(dai->codec);
2765
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002766 pr_debug("%s\n", __func__);
Santosh Mardie15e2302011-11-15 10:39:23 +05302767 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
2768 case SND_SOC_DAIFMT_CBS_CFS:
2769 /* CPU is master */
2770 if (tabla->intf_type == TABLA_INTERFACE_TYPE_I2C) {
2771 if (dai->id == TABLA_TX_DAI_ID)
2772 snd_soc_update_bits(dai->codec,
2773 TABLA_A_CDC_CLK_TX_I2S_CTL,
2774 TABLA_I2S_MASTER_MODE_MASK, 0);
2775 else if (dai->id == TABLA_RX_DAI_ID)
2776 snd_soc_update_bits(dai->codec,
2777 TABLA_A_CDC_CLK_RX_I2S_CTL,
2778 TABLA_I2S_MASTER_MODE_MASK, 0);
2779 }
2780 break;
2781 case SND_SOC_DAIFMT_CBM_CFM:
2782 /* CPU is slave */
2783 if (tabla->intf_type == TABLA_INTERFACE_TYPE_I2C) {
2784 val = TABLA_I2S_MASTER_MODE_MASK;
2785 if (dai->id == TABLA_TX_DAI_ID)
2786 snd_soc_update_bits(dai->codec,
2787 TABLA_A_CDC_CLK_TX_I2S_CTL, val, val);
2788 else if (dai->id == TABLA_RX_DAI_ID)
2789 snd_soc_update_bits(dai->codec,
2790 TABLA_A_CDC_CLK_RX_I2S_CTL, val, val);
2791 }
2792 break;
2793 default:
2794 return -EINVAL;
2795 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002796 return 0;
2797}
2798
2799static int tabla_hw_params(struct snd_pcm_substream *substream,
2800 struct snd_pcm_hw_params *params,
2801 struct snd_soc_dai *dai)
2802{
Bhalchandra Gajare9a901fd2011-08-01 10:07:15 -07002803 struct snd_soc_codec *codec = dai->codec;
Santosh Mardie15e2302011-11-15 10:39:23 +05302804 struct tabla_priv *tabla = snd_soc_codec_get_drvdata(dai->codec);
Bhalchandra Gajare038bf3a2011-09-02 15:32:30 -07002805 u8 path, shift;
2806 u16 tx_fs_reg, rx_fs_reg;
Bhalchandra Gajare9a901fd2011-08-01 10:07:15 -07002807 u8 tx_fs_rate, rx_fs_rate, rx_state, tx_state;
2808
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002809 pr_debug("%s: DAI-ID %x\n", __func__, dai->id);
Bhalchandra Gajare9a901fd2011-08-01 10:07:15 -07002810
2811 switch (params_rate(params)) {
2812 case 8000:
2813 tx_fs_rate = 0x00;
2814 rx_fs_rate = 0x00;
2815 break;
2816 case 16000:
2817 tx_fs_rate = 0x01;
2818 rx_fs_rate = 0x20;
2819 break;
2820 case 32000:
2821 tx_fs_rate = 0x02;
2822 rx_fs_rate = 0x40;
2823 break;
2824 case 48000:
2825 tx_fs_rate = 0x03;
2826 rx_fs_rate = 0x60;
2827 break;
2828 default:
2829 pr_err("%s: Invalid sampling rate %d\n", __func__,
2830 params_rate(params));
2831 return -EINVAL;
2832 }
2833
2834
2835 /**
2836 * If current dai is a tx dai, set sample rate to
2837 * all the txfe paths that are currently not active
2838 */
2839 if (dai->id == TABLA_TX_DAI_ID) {
2840
2841 tx_state = snd_soc_read(codec,
2842 TABLA_A_CDC_CLK_TX_CLK_EN_B1_CTL);
2843
2844 for (path = 1, shift = 0;
2845 path <= NUM_DECIMATORS; path++, shift++) {
2846
2847 if (path == BITS_PER_REG + 1) {
2848 shift = 0;
2849 tx_state = snd_soc_read(codec,
2850 TABLA_A_CDC_CLK_TX_CLK_EN_B2_CTL);
2851 }
2852
2853 if (!(tx_state & (1 << shift))) {
2854 tx_fs_reg = TABLA_A_CDC_TX1_CLK_FS_CTL
2855 + (BITS_PER_REG*(path-1));
2856 snd_soc_update_bits(codec, tx_fs_reg,
2857 0x03, tx_fs_rate);
2858 }
2859 }
Santosh Mardie15e2302011-11-15 10:39:23 +05302860 if (tabla->intf_type == TABLA_INTERFACE_TYPE_I2C) {
2861 switch (params_format(params)) {
2862 case SNDRV_PCM_FORMAT_S16_LE:
2863 snd_soc_update_bits(codec,
2864 TABLA_A_CDC_CLK_TX_I2S_CTL,
2865 0x20, 0x20);
2866 break;
2867 case SNDRV_PCM_FORMAT_S32_LE:
2868 snd_soc_update_bits(codec,
2869 TABLA_A_CDC_CLK_TX_I2S_CTL,
2870 0x20, 0x00);
2871 break;
2872 default:
2873 pr_err("invalid format\n");
2874 break;
2875 }
2876 snd_soc_update_bits(codec, TABLA_A_CDC_CLK_TX_I2S_CTL,
2877 0x03, tx_fs_rate);
2878 }
Bhalchandra Gajare9a901fd2011-08-01 10:07:15 -07002879 }
2880
2881 /**
2882 * TODO: Need to handle case where same RX chain takes 2 or more inputs
2883 * with varying sample rates
2884 */
2885
2886 /**
2887 * If current dai is a rx dai, set sample rate to
2888 * all the rx paths that are currently not active
2889 */
2890 if (dai->id == TABLA_RX_DAI_ID) {
2891
2892 rx_state = snd_soc_read(codec,
2893 TABLA_A_CDC_CLK_RX_B1_CTL);
2894
2895 for (path = 1, shift = 0;
2896 path <= NUM_INTERPOLATORS; path++, shift++) {
2897
2898 if (!(rx_state & (1 << shift))) {
2899 rx_fs_reg = TABLA_A_CDC_RX1_B5_CTL
2900 + (BITS_PER_REG*(path-1));
2901 snd_soc_update_bits(codec, rx_fs_reg,
2902 0xE0, rx_fs_rate);
2903 }
2904 }
Santosh Mardie15e2302011-11-15 10:39:23 +05302905 if (tabla->intf_type == TABLA_INTERFACE_TYPE_I2C) {
2906 switch (params_format(params)) {
2907 case SNDRV_PCM_FORMAT_S16_LE:
2908 snd_soc_update_bits(codec,
2909 TABLA_A_CDC_CLK_RX_I2S_CTL,
2910 0x20, 0x20);
2911 break;
2912 case SNDRV_PCM_FORMAT_S32_LE:
2913 snd_soc_update_bits(codec,
2914 TABLA_A_CDC_CLK_RX_I2S_CTL,
2915 0x20, 0x00);
2916 break;
2917 default:
2918 pr_err("invalid format\n");
2919 break;
2920 }
2921 snd_soc_update_bits(codec, TABLA_A_CDC_CLK_RX_I2S_CTL,
2922 0x03, (rx_fs_rate >> 0x05));
2923 }
Bhalchandra Gajare9a901fd2011-08-01 10:07:15 -07002924 }
2925
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002926 return 0;
2927}
2928
2929static struct snd_soc_dai_ops tabla_dai_ops = {
2930 .startup = tabla_startup,
2931 .shutdown = tabla_shutdown,
2932 .hw_params = tabla_hw_params,
2933 .set_sysclk = tabla_set_dai_sysclk,
2934 .set_fmt = tabla_set_dai_fmt,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002935};
2936
2937static struct snd_soc_dai_driver tabla_dai[] = {
2938 {
2939 .name = "tabla_rx1",
2940 .id = 1,
2941 .playback = {
2942 .stream_name = "AIF1 Playback",
Bhalchandra Gajare9a901fd2011-08-01 10:07:15 -07002943 .rates = WCD9310_RATES,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002944 .formats = TABLA_FORMATS,
2945 .rate_max = 48000,
2946 .rate_min = 8000,
2947 .channels_min = 1,
2948 .channels_max = 2,
2949 },
2950 .ops = &tabla_dai_ops,
2951 },
2952 {
2953 .name = "tabla_tx1",
2954 .id = 2,
2955 .capture = {
2956 .stream_name = "AIF1 Capture",
Bhalchandra Gajare9a901fd2011-08-01 10:07:15 -07002957 .rates = WCD9310_RATES,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002958 .formats = TABLA_FORMATS,
2959 .rate_max = 48000,
2960 .rate_min = 8000,
2961 .channels_min = 1,
2962 .channels_max = 2,
2963 },
2964 .ops = &tabla_dai_ops,
2965 },
2966};
Santosh Mardie15e2302011-11-15 10:39:23 +05302967
2968static struct snd_soc_dai_driver tabla_i2s_dai[] = {
2969 {
2970 .name = "tabla_i2s_rx1",
2971 .id = 1,
2972 .playback = {
2973 .stream_name = "AIF1 Playback",
2974 .rates = WCD9310_RATES,
2975 .formats = TABLA_FORMATS,
2976 .rate_max = 48000,
2977 .rate_min = 8000,
2978 .channels_min = 1,
2979 .channels_max = 4,
2980 },
2981 .ops = &tabla_dai_ops,
2982 },
2983 {
2984 .name = "tabla_i2s_tx1",
2985 .id = 2,
2986 .capture = {
2987 .stream_name = "AIF1 Capture",
2988 .rates = WCD9310_RATES,
2989 .formats = TABLA_FORMATS,
2990 .rate_max = 48000,
2991 .rate_min = 8000,
2992 .channels_min = 1,
2993 .channels_max = 4,
2994 },
2995 .ops = &tabla_dai_ops,
2996 },
2997};
Bradley Rubin89ffd0a2011-07-21 16:04:06 -07002998static short tabla_codec_read_sta_result(struct snd_soc_codec *codec)
Bradley Rubincb1e2732011-06-23 16:49:20 -07002999{
3000 u8 bias_msb, bias_lsb;
3001 short bias_value;
3002
Bradley Rubin89ffd0a2011-07-21 16:04:06 -07003003 bias_msb = snd_soc_read(codec, TABLA_A_CDC_MBHC_B3_STATUS);
3004 bias_lsb = snd_soc_read(codec, TABLA_A_CDC_MBHC_B2_STATUS);
3005 bias_value = (bias_msb << 8) | bias_lsb;
3006 return bias_value;
3007}
3008
3009static short tabla_codec_read_dce_result(struct snd_soc_codec *codec)
3010{
3011 u8 bias_msb, bias_lsb;
3012 short bias_value;
3013
3014 bias_msb = snd_soc_read(codec, TABLA_A_CDC_MBHC_B5_STATUS);
3015 bias_lsb = snd_soc_read(codec, TABLA_A_CDC_MBHC_B4_STATUS);
3016 bias_value = (bias_msb << 8) | bias_lsb;
3017 return bias_value;
3018}
3019
Joonwoo Park0976d012011-12-22 11:48:18 -08003020static short tabla_codec_sta_dce(struct snd_soc_codec *codec, int dce)
Bradley Rubin89ffd0a2011-07-21 16:04:06 -07003021{
Joonwoo Park0976d012011-12-22 11:48:18 -08003022 struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
Bradley Rubin89ffd0a2011-07-21 16:04:06 -07003023 short bias_value;
3024
Joonwoo Park925914c2012-01-05 13:35:18 -08003025 /* Turn on the override */
3026 snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_B1_CTL, 0x4, 0x4);
Bradley Rubincb1e2732011-06-23 16:49:20 -07003027 if (dce) {
Bradley Rubin89ffd0a2011-07-21 16:04:06 -07003028 snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_CLK_CTL, 0x8, 0x8);
3029 snd_soc_write(codec, TABLA_A_CDC_MBHC_EN_CTL, 0x4);
3030 snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_CLK_CTL, 0x8, 0x0);
3031 snd_soc_write(codec, TABLA_A_CDC_MBHC_EN_CTL, 0x4);
Joonwoo Park0976d012011-12-22 11:48:18 -08003032 usleep_range(tabla->mbhc_data.t_dce,
3033 tabla->mbhc_data.t_dce);
Bradley Rubin89ffd0a2011-07-21 16:04:06 -07003034 bias_value = tabla_codec_read_dce_result(codec);
Bradley Rubincb1e2732011-06-23 16:49:20 -07003035 } else {
Bradley Rubin89ffd0a2011-07-21 16:04:06 -07003036 snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_CLK_CTL, 0x8, 0x8);
Bradley Rubincb1e2732011-06-23 16:49:20 -07003037 snd_soc_write(codec, TABLA_A_CDC_MBHC_EN_CTL, 0x2);
3038 snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_CLK_CTL, 0x8, 0x0);
Bradley Rubin89ffd0a2011-07-21 16:04:06 -07003039 usleep_range(50, 50);
Joonwoo Park0976d012011-12-22 11:48:18 -08003040 snd_soc_write(codec, TABLA_A_CDC_MBHC_EN_CTL, 0x2);
3041 usleep_range(tabla->mbhc_data.t_sta,
3042 tabla->mbhc_data.t_sta);
Bradley Rubin89ffd0a2011-07-21 16:04:06 -07003043 bias_value = tabla_codec_read_sta_result(codec);
3044 snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_CLK_CTL, 0x8, 0x8);
3045 snd_soc_write(codec, TABLA_A_CDC_MBHC_EN_CTL, 0x0);
Bradley Rubincb1e2732011-06-23 16:49:20 -07003046 }
Joonwoo Park925914c2012-01-05 13:35:18 -08003047 /* Turn off the override after measuring mic voltage */
3048 snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_B1_CTL, 0x04, 0x00);
Bradley Rubincb1e2732011-06-23 16:49:20 -07003049
Joonwoo Park0976d012011-12-22 11:48:18 -08003050 pr_debug("read microphone bias value %04x\n", bias_value);
Bradley Rubincb1e2732011-06-23 16:49:20 -07003051 return bias_value;
3052}
3053
Bhalchandra Gajare343cbb02011-09-07 18:58:19 -07003054static short tabla_codec_setup_hs_polling(struct snd_soc_codec *codec)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003055{
3056 struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
Bhalchandra Gajare343cbb02011-09-07 18:58:19 -07003057 short bias_value;
Bhalchandra Gajare19d9c132011-11-18 14:57:08 -08003058 u8 cfilt_mode;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003059
Joonwoo Park0976d012011-12-22 11:48:18 -08003060 if (!tabla->calibration) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003061 pr_err("Error, no tabla calibration\n");
Bradley Rubincb1e2732011-06-23 16:49:20 -07003062 return -ENODEV;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003063 }
3064
3065 tabla->mbhc_polling_active = true;
3066
Kiran Kandi6fae8bf2011-08-15 10:36:42 -07003067 if (!tabla->mclk_enabled) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003068 tabla_codec_enable_bandgap(codec, TABLA_BANDGAP_MBHC_MODE);
Kiran Kandi6fae8bf2011-08-15 10:36:42 -07003069 tabla_enable_rx_bias(codec, 1);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003070 tabla_codec_enable_clock_block(codec, 1);
3071 }
3072
3073 snd_soc_update_bits(codec, TABLA_A_CLK_BUFF_EN1, 0x05, 0x01);
3074
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003075 snd_soc_update_bits(codec, TABLA_A_TX_COM_BIAS, 0xE0, 0xE0);
3076
Bhalchandra Gajare19d9c132011-11-18 14:57:08 -08003077 /* Make sure CFILT is in fast mode, save current mode */
Joonwoo Parkf4267c22012-01-10 13:25:24 -08003078 cfilt_mode = snd_soc_read(codec, tabla->mbhc_bias_regs.cfilt_ctl);
3079 snd_soc_update_bits(codec, tabla->mbhc_bias_regs.cfilt_ctl, 0x70, 0x00);
Patrick Lai3043fba2011-08-01 14:15:57 -07003080
Joonwoo Parkf4267c22012-01-10 13:25:24 -08003081 snd_soc_update_bits(codec, tabla->mbhc_bias_regs.ctl_reg, 0x1F, 0x16);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003082
3083 snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_CLK_CTL, 0x2, 0x2);
Bradley Rubincb1e2732011-06-23 16:49:20 -07003084 snd_soc_write(codec, TABLA_A_MBHC_SCALING_MUX_1, 0x84);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003085
3086 snd_soc_update_bits(codec, TABLA_A_TX_7_MBHC_EN, 0x80, 0x80);
3087 snd_soc_update_bits(codec, TABLA_A_TX_7_MBHC_EN, 0x1F, 0x1C);
3088 snd_soc_update_bits(codec, TABLA_A_TX_7_MBHC_TEST_CTL, 0x40, 0x40);
3089
3090 snd_soc_update_bits(codec, TABLA_A_TX_7_MBHC_EN, 0x80, 0x00);
Bradley Rubincb1e2732011-06-23 16:49:20 -07003091 snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_CLK_CTL, 0x8, 0x8);
3092 snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_CLK_CTL, 0x8, 0x00);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003093
Joonwoo Park925914c2012-01-05 13:35:18 -08003094 snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_B1_CTL, 0x2, 0x2);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003095 snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_CLK_CTL, 0x8, 0x8);
3096
Bradley Rubincb1e2732011-06-23 16:49:20 -07003097 tabla_codec_calibrate_hs_polling(codec);
3098
Joonwoo Park0976d012011-12-22 11:48:18 -08003099 bias_value = tabla_codec_sta_dce(codec, 0);
3100 snd_soc_update_bits(codec, tabla->mbhc_bias_regs.cfilt_ctl, 0x40,
3101 cfilt_mode);
Bradley Rubin89ffd0a2011-07-21 16:04:06 -07003102 snd_soc_update_bits(codec, TABLA_A_MBHC_HPH, 0x13, 0x00);
Bradley Rubincb1e2732011-06-23 16:49:20 -07003103
Bhalchandra Gajare343cbb02011-09-07 18:58:19 -07003104 return bias_value;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003105}
3106
3107static int tabla_codec_enable_hs_detect(struct snd_soc_codec *codec,
3108 int insertion)
3109{
3110 struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003111 int central_bias_enabled = 0;
Joonwoo Park0976d012011-12-22 11:48:18 -08003112 const struct tabla_mbhc_general_cfg *generic =
3113 TABLA_MBHC_CAL_GENERAL_PTR(tabla->calibration);
3114 const struct tabla_mbhc_plug_detect_cfg *plug_det =
3115 TABLA_MBHC_CAL_PLUG_DET_PTR(tabla->calibration);
Bhalchandra Gajare5ea376d2011-11-30 14:21:20 -08003116 u8 wg_time;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003117
Joonwoo Park0976d012011-12-22 11:48:18 -08003118 if (!tabla->calibration) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003119 pr_err("Error, no tabla calibration\n");
3120 return -EINVAL;
3121 }
3122
3123 snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_INT_CTL, 0x1, 0);
3124
Bhalchandra Gajare7fc72332011-10-13 19:01:55 -07003125 if (insertion) {
3126 /* Make sure mic bias and Mic line schmitt trigger
3127 * are turned OFF
3128 */
3129 snd_soc_update_bits(codec, tabla->mbhc_bias_regs.ctl_reg,
3130 0x81, 0x01);
3131 snd_soc_update_bits(codec, tabla->mbhc_bias_regs.mbhc_reg,
3132 0x90, 0x00);
Bhalchandra Gajare5ea376d2011-11-30 14:21:20 -08003133 wg_time = snd_soc_read(codec, TABLA_A_RX_HPH_CNP_WG_TIME) ;
3134 wg_time += 1;
Bhalchandra Gajare7fc72332011-10-13 19:01:55 -07003135
3136 /* Enable HPH Schmitt Trigger */
Bhalchandra Gajare5ea376d2011-11-30 14:21:20 -08003137 snd_soc_update_bits(codec, TABLA_A_MBHC_HPH, 0x11, 0x11);
Bhalchandra Gajare7fc72332011-10-13 19:01:55 -07003138 snd_soc_update_bits(codec, TABLA_A_MBHC_HPH, 0x0C,
Joonwoo Park0976d012011-12-22 11:48:18 -08003139 plug_det->hph_current << 2);
Bhalchandra Gajare7fc72332011-10-13 19:01:55 -07003140
Bhalchandra Gajare5ea376d2011-11-30 14:21:20 -08003141 /* Turn off HPH PAs and DAC's during insertion detection to
3142 * avoid false insertion interrupts
Bhalchandra Gajare7fc72332011-10-13 19:01:55 -07003143 */
3144 if (tabla->mbhc_micbias_switched)
3145 tabla_codec_switch_micbias(codec, 0);
3146 snd_soc_update_bits(codec, TABLA_A_RX_HPH_CNP_EN, 0x30, 0x00);
Bhalchandra Gajare5ea376d2011-11-30 14:21:20 -08003147 snd_soc_update_bits(codec, TABLA_A_RX_HPH_L_DAC_CTL,
Joonwoo Park0976d012011-12-22 11:48:18 -08003148 0xC0, 0x00);
Bhalchandra Gajare5ea376d2011-11-30 14:21:20 -08003149 snd_soc_update_bits(codec, TABLA_A_RX_HPH_R_DAC_CTL,
Joonwoo Park0976d012011-12-22 11:48:18 -08003150 0xC0, 0x00);
Bhalchandra Gajare5ea376d2011-11-30 14:21:20 -08003151 usleep_range(wg_time * 1000, wg_time * 1000);
Bhalchandra Gajare7fc72332011-10-13 19:01:55 -07003152
3153 /* setup for insetion detection */
Bhalchandra Gajare5ea376d2011-11-30 14:21:20 -08003154 snd_soc_update_bits(codec, TABLA_A_MBHC_HPH, 0x02, 0x02);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003155 snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_INT_CTL, 0x2, 0);
Bhalchandra Gajare7fc72332011-10-13 19:01:55 -07003156 } else {
3157 /* Make sure the HPH schmitt trigger is OFF */
3158 snd_soc_update_bits(codec, TABLA_A_MBHC_HPH, 0x12, 0x00);
3159
3160 /* enable the mic line schmitt trigger */
3161 snd_soc_update_bits(codec, tabla->mbhc_bias_regs.mbhc_reg, 0x60,
Joonwoo Park0976d012011-12-22 11:48:18 -08003162 plug_det->mic_current << 5);
Bhalchandra Gajare7fc72332011-10-13 19:01:55 -07003163 snd_soc_update_bits(codec, tabla->mbhc_bias_regs.mbhc_reg,
3164 0x80, 0x80);
Joonwoo Park0976d012011-12-22 11:48:18 -08003165 usleep_range(plug_det->t_mic_pid, plug_det->t_mic_pid);
Bhalchandra Gajare7fc72332011-10-13 19:01:55 -07003166 snd_soc_update_bits(codec, tabla->mbhc_bias_regs.mbhc_reg,
3167 0x10, 0x10);
3168
3169 /* Setup for low power removal detection */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003170 snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_INT_CTL, 0x2, 0x2);
Bhalchandra Gajare7fc72332011-10-13 19:01:55 -07003171 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003172
3173 if (snd_soc_read(codec, TABLA_A_CDC_MBHC_B1_CTL) & 0x4) {
3174 if (!(tabla->clock_active)) {
3175 tabla_codec_enable_config_mode(codec, 1);
3176 snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_B1_CTL,
Bradley Rubincb1e2732011-06-23 16:49:20 -07003177 0x06, 0);
Joonwoo Park0976d012011-12-22 11:48:18 -08003178 usleep_range(generic->t_shutdown_plug_rem,
3179 generic->t_shutdown_plug_rem);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003180 tabla_codec_enable_config_mode(codec, 0);
3181 } else
3182 snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_B1_CTL,
Bradley Rubincb1e2732011-06-23 16:49:20 -07003183 0x06, 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003184 }
3185
Bhalchandra Gajare02d90cd2011-09-30 16:14:00 -07003186 snd_soc_update_bits(codec, tabla->mbhc_bias_regs.int_rbias, 0x80, 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003187
3188 /* If central bandgap disabled */
3189 if (!(snd_soc_read(codec, TABLA_A_PIN_CTL_OE1) & 1)) {
3190 snd_soc_update_bits(codec, TABLA_A_PIN_CTL_OE1, 0x3, 0x3);
Joonwoo Park0976d012011-12-22 11:48:18 -08003191 usleep_range(generic->t_bg_fast_settle,
3192 generic->t_bg_fast_settle);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003193 central_bias_enabled = 1;
3194 }
3195
3196 /* If LDO_H disabled */
3197 if (snd_soc_read(codec, TABLA_A_PIN_CTL_OE0) & 0x80) {
3198 snd_soc_update_bits(codec, TABLA_A_PIN_CTL_OE0, 0x10, 0);
3199 snd_soc_update_bits(codec, TABLA_A_PIN_CTL_OE0, 0x80, 0x80);
Joonwoo Park0976d012011-12-22 11:48:18 -08003200 usleep_range(generic->t_ldoh, generic->t_ldoh);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003201 snd_soc_update_bits(codec, TABLA_A_PIN_CTL_OE0, 0x80, 0);
3202
3203 if (central_bias_enabled)
3204 snd_soc_update_bits(codec, TABLA_A_PIN_CTL_OE1, 0x1, 0);
3205 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003206
Joonwoo Park0976d012011-12-22 11:48:18 -08003207 snd_soc_update_bits(codec, TABLA_A_MICB_4_MBHC, 0x3, tabla->micbias);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003208
3209 tabla_enable_irq(codec->control_data, TABLA_IRQ_MBHC_INSERTION);
3210 snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_INT_CTL, 0x1, 0x1);
3211 return 0;
3212}
3213
Joonwoo Park8b1f0982011-12-08 17:12:45 -08003214static void tabla_lock_sleep(struct tabla_priv *tabla)
3215{
3216 int ret;
3217 while (!(ret = wait_event_timeout(tabla->pm_wq,
3218 atomic_inc_not_zero(&tabla->pm_cnt),
3219 2 * HZ))) {
3220 pr_err("%s: didn't wake up for 2000ms (%d), pm_cnt %d\n",
3221 __func__, ret, atomic_read(&tabla->pm_cnt));
3222 WARN_ON_ONCE(1);
3223 }
3224}
3225
3226static void tabla_unlock_sleep(struct tabla_priv *tabla)
3227{
3228 atomic_dec(&tabla->pm_cnt);
3229 wake_up(&tabla->pm_wq);
3230}
3231
Joonwoo Park0976d012011-12-22 11:48:18 -08003232static u16 tabla_codec_v_sta_dce(struct snd_soc_codec *codec, bool dce,
3233 s16 vin_mv)
3234{
3235 short diff, zero;
3236 struct tabla_priv *tabla;
3237 u32 mb_mv, in;
3238
3239 tabla = snd_soc_codec_get_drvdata(codec);
3240 mb_mv = tabla->mbhc_data.micb_mv;
3241
3242 if (mb_mv == 0) {
3243 pr_err("%s: Mic Bias voltage is set to zero\n", __func__);
3244 return -EINVAL;
3245 }
3246
3247 if (dce) {
3248 diff = tabla->mbhc_data.dce_mb - tabla->mbhc_data.dce_z;
3249 zero = tabla->mbhc_data.dce_z;
3250 } else {
3251 diff = tabla->mbhc_data.sta_mb - tabla->mbhc_data.sta_z;
3252 zero = tabla->mbhc_data.sta_z;
3253 }
3254 in = (u32) diff * vin_mv;
3255
3256 return (u16) (in / mb_mv) + zero;
3257}
3258
3259static s32 tabla_codec_sta_dce_v(struct snd_soc_codec *codec, s8 dce,
3260 u16 bias_value)
3261{
3262 struct tabla_priv *tabla;
3263 s32 mv;
3264
3265 tabla = snd_soc_codec_get_drvdata(codec);
3266
3267 if (dce) {
3268 mv = ((s32)bias_value - (s32)tabla->mbhc_data.dce_z) *
3269 (s32)tabla->mbhc_data.micb_mv /
3270 (s32)(tabla->mbhc_data.dce_mb - tabla->mbhc_data.dce_z);
3271 } else {
3272 mv = ((s32)bias_value - (s32)tabla->mbhc_data.sta_z) *
3273 (s32)tabla->mbhc_data.micb_mv /
3274 (s32)(tabla->mbhc_data.sta_mb - tabla->mbhc_data.sta_z);
3275 }
3276
3277 return mv;
3278}
3279
Bhalchandra Gajare0a792b12011-09-06 16:36:58 -07003280static void btn0_lpress_fn(struct work_struct *work)
3281{
3282 struct delayed_work *delayed_work;
3283 struct tabla_priv *tabla;
Joonwoo Park0976d012011-12-22 11:48:18 -08003284 short bias_value;
3285 int dce_mv, sta_mv;
Bhalchandra Gajare0a792b12011-09-06 16:36:58 -07003286
3287 pr_debug("%s:\n", __func__);
3288
3289 delayed_work = to_delayed_work(work);
3290 tabla = container_of(delayed_work, struct tabla_priv, btn0_dwork);
3291
3292 if (tabla) {
3293 if (tabla->button_jack) {
Joonwoo Park0976d012011-12-22 11:48:18 -08003294 bias_value = tabla_codec_read_sta_result(tabla->codec);
3295 sta_mv = tabla_codec_sta_dce_v(tabla->codec, 0,
3296 bias_value);
3297 bias_value = tabla_codec_read_dce_result(tabla->codec);
3298 dce_mv = tabla_codec_sta_dce_v(tabla->codec, 1,
3299 bias_value);
3300 pr_debug("%s: Reporting long button press event"
3301 " STA: %d, DCE: %d\n", __func__,
3302 sta_mv, dce_mv);
Joonwoo Park8b1f0982011-12-08 17:12:45 -08003303 tabla_snd_soc_jack_report(tabla, tabla->button_jack,
3304 SND_JACK_BTN_0,
3305 SND_JACK_BTN_0);
Bhalchandra Gajare0a792b12011-09-06 16:36:58 -07003306 }
3307 } else {
3308 pr_err("%s: Bad tabla private data\n", __func__);
3309 }
3310
Joonwoo Park8b1f0982011-12-08 17:12:45 -08003311 tabla_unlock_sleep(tabla);
Bhalchandra Gajare0a792b12011-09-06 16:36:58 -07003312}
Bhalchandra Gajared9ebb6c2011-10-03 19:54:41 -07003313
Joonwoo Park0976d012011-12-22 11:48:18 -08003314void tabla_mbhc_cal(struct snd_soc_codec *codec)
3315{
3316 struct tabla_priv *tabla;
3317 struct tabla_mbhc_btn_detect_cfg *btn_det;
3318 u8 cfilt_mode, bg_mode;
3319 u8 ncic, nmeas, navg;
3320 u32 mclk_rate;
3321 u32 dce_wait, sta_wait;
3322 u8 *n_cic;
3323
3324 tabla = snd_soc_codec_get_drvdata(codec);
3325
3326 /* First compute the DCE / STA wait times
3327 * depending on tunable parameters.
3328 * The value is computed in microseconds
3329 */
3330 btn_det = TABLA_MBHC_CAL_BTN_DET_PTR(tabla->calibration);
3331 n_cic = tabla_mbhc_cal_btn_det_mp(btn_det, TABLA_BTN_DET_N_CIC);
3332 ncic = n_cic[0];
3333 nmeas = TABLA_MBHC_CAL_BTN_DET_PTR(tabla->calibration)->n_meas;
3334 navg = TABLA_MBHC_CAL_GENERAL_PTR(tabla->calibration)->mbhc_navg;
3335 mclk_rate = tabla->mclk_freq;
3336 dce_wait = (1000 * 512 * ncic * nmeas) / (mclk_rate / 1000);
3337 if (tabla->mclk_freq == TABLA_MCLK_RATE_12288KHZ)
3338 dce_wait = dce_wait + 10000;
3339 else if (tabla->mclk_freq == TABLA_MCLK_RATE_9600KHZ)
3340 dce_wait = dce_wait + 9810;
3341 else
3342 WARN(1, "Unsupported mclk freq %d\n", tabla->mclk_freq);
3343
3344 sta_wait = (1000 * 128 * navg) / (mclk_rate / 1000);
3345
3346 /* Add 10 microseconds to handle error margin */
3347 dce_wait = dce_wait + 10;
3348 sta_wait = sta_wait + 10;
3349
3350 tabla->mbhc_data.t_dce = dce_wait;
3351 tabla->mbhc_data.t_sta = sta_wait;
3352
3353 /* LDOH and CFILT are already configured during pdata handling.
3354 * Only need to make sure CFILT and bandgap are in Fast mode.
3355 * Need to restore defaults once calculation is done.
3356 */
3357 cfilt_mode = snd_soc_read(codec, tabla->mbhc_bias_regs.cfilt_ctl);
3358 snd_soc_update_bits(codec, tabla->mbhc_bias_regs.cfilt_ctl, 0x40, 0x00);
3359 bg_mode = snd_soc_update_bits(codec, TABLA_A_BIAS_CENTRAL_BG_CTL, 0x02,
3360 0x02);
3361
3362 /* Micbias, CFILT, LDOH, MBHC MUX mode settings
3363 * to perform ADC calibration
3364 */
3365 snd_soc_update_bits(codec, tabla->mbhc_bias_regs.ctl_reg, 0x60,
3366 tabla->micbias << 5);
3367 snd_soc_update_bits(codec, tabla->mbhc_bias_regs.ctl_reg, 0x01, 0x00);
3368 snd_soc_update_bits(codec, TABLA_A_LDO_H_MODE_1, 0x60, 0x60);
3369 snd_soc_write(codec, TABLA_A_TX_7_MBHC_TEST_CTL, 0x78);
3370 snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_B1_CTL, 0x04, 0x04);
3371
3372 /* DCE measurement for 0 volts */
3373 snd_soc_write(codec, TABLA_A_CDC_MBHC_CLK_CTL, 0x0A);
3374 snd_soc_write(codec, TABLA_A_CDC_MBHC_EN_CTL, 0x04);
3375 snd_soc_write(codec, TABLA_A_CDC_MBHC_CLK_CTL, 0x02);
3376 snd_soc_write(codec, TABLA_A_CDC_MBHC_EN_CTL, 0x04);
3377 snd_soc_write(codec, TABLA_A_MBHC_SCALING_MUX_1, 0x81);
3378 usleep_range(100, 100);
3379 snd_soc_write(codec, TABLA_A_CDC_MBHC_EN_CTL, 0x04);
3380 usleep_range(tabla->mbhc_data.t_dce, tabla->mbhc_data.t_dce);
3381 tabla->mbhc_data.dce_z = tabla_codec_read_dce_result(codec);
3382
3383 /* DCE measurment for MB voltage */
3384 snd_soc_write(codec, TABLA_A_CDC_MBHC_CLK_CTL, 0x0A);
3385 snd_soc_write(codec, TABLA_A_CDC_MBHC_CLK_CTL, 0x02);
3386 snd_soc_write(codec, TABLA_A_MBHC_SCALING_MUX_1, 0x82);
3387 usleep_range(100, 100);
3388 snd_soc_write(codec, TABLA_A_CDC_MBHC_EN_CTL, 0x04);
3389 usleep_range(tabla->mbhc_data.t_dce, tabla->mbhc_data.t_dce);
3390 tabla->mbhc_data.dce_mb = tabla_codec_read_dce_result(codec);
3391
3392 /* Sta measuremnt for 0 volts */
3393 snd_soc_write(codec, TABLA_A_CDC_MBHC_CLK_CTL, 0x0A);
3394 snd_soc_write(codec, TABLA_A_CDC_MBHC_EN_CTL, 0x02);
3395 snd_soc_write(codec, TABLA_A_CDC_MBHC_CLK_CTL, 0x02);
3396 snd_soc_write(codec, TABLA_A_CDC_MBHC_EN_CTL, 0x02);
3397 snd_soc_write(codec, TABLA_A_MBHC_SCALING_MUX_1, 0x81);
3398 usleep_range(100, 100);
3399 snd_soc_write(codec, TABLA_A_CDC_MBHC_EN_CTL, 0x02);
3400 usleep_range(tabla->mbhc_data.t_sta, tabla->mbhc_data.t_sta);
3401 tabla->mbhc_data.sta_z = tabla_codec_read_sta_result(codec);
3402
3403 /* STA Measurement for MB Voltage */
3404 snd_soc_write(codec, TABLA_A_MBHC_SCALING_MUX_1, 0x82);
3405 usleep_range(100, 100);
3406 snd_soc_write(codec, TABLA_A_CDC_MBHC_EN_CTL, 0x02);
3407 usleep_range(tabla->mbhc_data.t_sta, tabla->mbhc_data.t_sta);
3408 tabla->mbhc_data.sta_mb = tabla_codec_read_sta_result(codec);
3409
3410 /* Restore default settings. */
3411 snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_B1_CTL, 0x04, 0x00);
3412 snd_soc_update_bits(codec, tabla->mbhc_bias_regs.cfilt_ctl, 0x40,
3413 cfilt_mode);
3414 snd_soc_update_bits(codec, TABLA_A_BIAS_CENTRAL_BG_CTL, 0x02, bg_mode);
3415
3416 snd_soc_write(codec, TABLA_A_MBHC_SCALING_MUX_1, 0x84);
3417 usleep_range(100, 100);
3418}
3419
3420void *tabla_mbhc_cal_btn_det_mp(const struct tabla_mbhc_btn_detect_cfg* btn_det,
3421 const enum tabla_mbhc_btn_det_mem mem)
3422{
3423 void *ret = &btn_det->_v_btn_low;
3424
3425 switch (mem) {
3426 case TABLA_BTN_DET_GAIN:
3427 ret += sizeof(btn_det->_n_cic);
3428 case TABLA_BTN_DET_N_CIC:
3429 ret += sizeof(btn_det->_n_ready);
3430 case TABLA_BTN_DET_V_N_READY:
3431 ret += sizeof(btn_det->_v_btn_high[0]) * btn_det->num_btn;
3432 case TABLA_BTN_DET_V_BTN_HIGH:
3433 ret += sizeof(btn_det->_v_btn_low[0]) * btn_det->num_btn;
3434 case TABLA_BTN_DET_V_BTN_LOW:
3435 /* do nothing */
3436 break;
3437 default:
3438 ret = NULL;
3439 }
3440
3441 return ret;
3442}
3443
3444static void tabla_mbhc_calc_thres(struct snd_soc_codec *codec)
3445{
3446 struct tabla_priv *tabla;
3447 s16 btn_mv = 0, btn_delta_mv;
3448 struct tabla_mbhc_btn_detect_cfg *btn_det;
3449 struct tabla_mbhc_plug_type_cfg *plug_type;
3450 u16 *btn_high;
3451 int i;
3452
3453 tabla = snd_soc_codec_get_drvdata(codec);
3454 btn_det = TABLA_MBHC_CAL_BTN_DET_PTR(tabla->calibration);
3455 plug_type = TABLA_MBHC_CAL_PLUG_TYPE_PTR(tabla->calibration);
3456
3457 if (tabla->mclk_freq == TABLA_MCLK_RATE_12288KHZ) {
3458 tabla->mbhc_data.nready = 3;
3459 tabla->mbhc_data.npoll = 9;
3460 tabla->mbhc_data.nbounce_wait = 30;
3461 } else if (tabla->mclk_freq == TABLA_MCLK_RATE_9600KHZ) {
3462 tabla->mbhc_data.nready = 2;
3463 tabla->mbhc_data.npoll = 7;
3464 tabla->mbhc_data.nbounce_wait = 23;
3465 }
3466
3467 tabla->mbhc_data.v_ins_hu =
3468 tabla_codec_v_sta_dce(codec, STA, plug_type->v_hs_max);
3469 tabla->mbhc_data.v_ins_h =
3470 tabla_codec_v_sta_dce(codec, DCE, plug_type->v_hs_max);
3471
3472 btn_high = tabla_mbhc_cal_btn_det_mp(btn_det, TABLA_BTN_DET_V_BTN_HIGH);
3473 for (i = 0; i < btn_det->num_btn; i++)
3474 btn_mv = btn_high[i] > btn_mv ? btn_high[i] : btn_mv;
3475
3476 tabla->mbhc_data.v_b1_h = tabla_codec_v_sta_dce(codec, DCE, btn_mv);
3477 btn_delta_mv = btn_mv + btn_det->v_btn_press_delta_sta;
3478
3479 tabla->mbhc_data.v_b1_hu =
3480 tabla_codec_v_sta_dce(codec, STA, btn_delta_mv);
3481
3482 btn_delta_mv = btn_mv + btn_det->v_btn_press_delta_cic;
3483
3484 tabla->mbhc_data.v_b1_huc =
3485 tabla_codec_v_sta_dce(codec, DCE, btn_delta_mv);
3486
3487 tabla->mbhc_data.v_brh = tabla->mbhc_data.v_b1_h;
3488 tabla->mbhc_data.v_brl = 0xFA55;
3489
3490 tabla->mbhc_data.v_no_mic =
3491 tabla_codec_v_sta_dce(codec, STA, plug_type->v_no_mic);
3492}
3493
3494void tabla_mbhc_init(struct snd_soc_codec *codec)
3495{
3496 struct tabla_priv *tabla;
3497 struct tabla_mbhc_general_cfg *generic;
3498 struct tabla_mbhc_btn_detect_cfg *btn_det;
3499 int n;
3500 u8 tabla_ver;
3501 u8 *n_cic, *gain;
3502
3503 tabla = snd_soc_codec_get_drvdata(codec);
3504 generic = TABLA_MBHC_CAL_GENERAL_PTR(tabla->calibration);
3505 btn_det = TABLA_MBHC_CAL_BTN_DET_PTR(tabla->calibration);
3506
3507 tabla_ver = snd_soc_read(codec, TABLA_A_CHIP_VERSION);
3508 tabla_ver &= 0x1F;
3509
3510 for (n = 0; n < 8; n++) {
3511 if ((tabla_ver != TABLA_VERSION_1_0 &&
3512 tabla_ver != TABLA_VERSION_1_1) || n != 7) {
3513 snd_soc_update_bits(codec,
3514 TABLA_A_CDC_MBHC_FEATURE_B1_CFG,
3515 0x07, n);
3516 snd_soc_write(codec, TABLA_A_CDC_MBHC_FEATURE_B2_CFG,
3517 btn_det->c[n]);
3518 }
3519 }
3520 snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_B2_CTL, 0x07,
3521 btn_det->nc);
3522
3523 n_cic = tabla_mbhc_cal_btn_det_mp(btn_det, TABLA_BTN_DET_N_CIC);
3524 snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_TIMER_B6_CTL, 0xFF,
3525 n_cic[0]);
3526
3527 gain = tabla_mbhc_cal_btn_det_mp(btn_det, TABLA_BTN_DET_GAIN);
3528 snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_B2_CTL, 0x78, gain[0] << 3);
3529
3530 snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_TIMER_B4_CTL, 0x70,
3531 generic->mbhc_nsa << 4);
3532
3533 snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_TIMER_B4_CTL, 0x0F,
3534 btn_det->n_meas);
3535
3536 snd_soc_write(codec, TABLA_A_CDC_MBHC_TIMER_B5_CTL, generic->mbhc_navg);
3537
3538 snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_B1_CTL, 0x80, 0x80);
3539
3540 snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_B1_CTL, 0x78,
3541 btn_det->mbhc_nsc << 3);
3542
3543 snd_soc_update_bits(codec, TABLA_A_MICB_4_MBHC, 0x03, TABLA_MICBIAS2);
3544
3545 snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_B1_CTL, 0x02, 0x02);
3546}
3547
Bradley Rubincb1e2732011-06-23 16:49:20 -07003548int tabla_hs_detect(struct snd_soc_codec *codec,
Joonwoo Park0976d012011-12-22 11:48:18 -08003549 struct snd_soc_jack *headset_jack,
3550 struct snd_soc_jack *button_jack,
3551 void *calibration, enum tabla_micbias_num micbias,
3552 int (*mclk_cb_fn) (struct snd_soc_codec*, int),
3553 int read_fw_bin, u32 mclk_rate)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003554{
3555 struct tabla_priv *tabla;
Patrick Lai49efeac2011-11-03 11:01:12 -07003556 int rc;
3557
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003558 if (!codec || !calibration) {
3559 pr_err("Error: no codec or calibration\n");
3560 return -EINVAL;
3561 }
3562 tabla = snd_soc_codec_get_drvdata(codec);
Bradley Rubincb1e2732011-06-23 16:49:20 -07003563 tabla->headset_jack = headset_jack;
3564 tabla->button_jack = button_jack;
Joonwoo Park0976d012011-12-22 11:48:18 -08003565 tabla->micbias = micbias;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003566 tabla->calibration = calibration;
Joonwoo Park0976d012011-12-22 11:48:18 -08003567 tabla->mclk_cb = mclk_cb_fn;
3568 tabla->mclk_freq = mclk_rate;
Bhalchandra Gajare02d90cd2011-09-30 16:14:00 -07003569 tabla_get_mbhc_micbias_regs(codec, &tabla->mbhc_bias_regs);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003570
Bhalchandra Gajare19d9c132011-11-18 14:57:08 -08003571 /* Put CFILT in fast mode by default */
3572 snd_soc_update_bits(codec, tabla->mbhc_bias_regs.cfilt_ctl,
3573 0x40, TABLA_CFILT_FAST_MODE);
3574
Bhalchandra Gajare0a792b12011-09-06 16:36:58 -07003575 INIT_DELAYED_WORK(&tabla->btn0_dwork, btn0_lpress_fn);
Patrick Lai49efeac2011-11-03 11:01:12 -07003576 INIT_WORK(&tabla->hphlocp_work, hphlocp_off_report);
3577 INIT_WORK(&tabla->hphrocp_work, hphrocp_off_report);
Joonwoo Park0976d012011-12-22 11:48:18 -08003578
3579 if (!read_fw_bin) {
3580 tabla->mclk_cb(codec, 1);
3581 tabla_mbhc_init(codec);
3582 tabla_mbhc_cal(codec);
3583 tabla_mbhc_calc_thres(codec);
3584 tabla->mclk_cb(codec, 0);
3585 tabla_codec_calibrate_hs_polling(codec);
3586 rc = tabla_codec_enable_hs_detect(codec, 1);
3587 } else {
3588 pr_err("%s: MBHC firmware read not supported\n", __func__);
3589 rc = -EINVAL;
3590 }
Patrick Lai49efeac2011-11-03 11:01:12 -07003591
3592 if (!IS_ERR_VALUE(rc)) {
3593 snd_soc_update_bits(codec, TABLA_A_RX_HPH_OCP_CTL, 0x10,
3594 0x10);
3595 tabla_enable_irq(codec->control_data,
3596 TABLA_IRQ_HPH_PA_OCPL_FAULT);
3597 tabla_enable_irq(codec->control_data,
3598 TABLA_IRQ_HPH_PA_OCPR_FAULT);
3599 }
3600
3601 return rc;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003602}
3603EXPORT_SYMBOL_GPL(tabla_hs_detect);
3604
Bradley Rubincb1e2732011-06-23 16:49:20 -07003605static irqreturn_t tabla_dce_handler(int irq, void *data)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003606{
3607 struct tabla_priv *priv = data;
3608 struct snd_soc_codec *codec = priv->codec;
Bhalchandra Gajare0a792b12011-09-06 16:36:58 -07003609 short bias_value;
Bradley Rubincb1e2732011-06-23 16:49:20 -07003610
3611 tabla_disable_irq(codec->control_data, TABLA_IRQ_MBHC_REMOVAL);
3612 tabla_disable_irq(codec->control_data, TABLA_IRQ_MBHC_POTENTIAL);
Joonwoo Park8b1f0982011-12-08 17:12:45 -08003613 tabla_lock_sleep(priv);
Bradley Rubincb1e2732011-06-23 16:49:20 -07003614
Bradley Rubin89ffd0a2011-07-21 16:04:06 -07003615 bias_value = tabla_codec_read_dce_result(codec);
Joonwoo Park0976d012011-12-22 11:48:18 -08003616 pr_debug("%s: button press interrupt, DCE: %d,%d\n",
3617 __func__, bias_value,
3618 tabla_codec_sta_dce_v(codec, 1, bias_value));
Bradley Rubin89ffd0a2011-07-21 16:04:06 -07003619
Bhalchandra Gajare30cf4842011-10-17 18:12:52 -07003620 bias_value = tabla_codec_read_sta_result(codec);
Joonwoo Park0976d012011-12-22 11:48:18 -08003621 pr_debug("%s: button press interrupt, STA: %d,%d\n",
3622 __func__, bias_value,
3623 tabla_codec_sta_dce_v(codec, 0, bias_value));
Bhalchandra Gajare0a792b12011-09-06 16:36:58 -07003624 /*
3625 * TODO: If button pressed is not button 0,
3626 * report the button press event immediately.
3627 */
3628 priv->buttons_pressed |= SND_JACK_BTN_0;
Bradley Rubincb1e2732011-06-23 16:49:20 -07003629
Bradley Rubin688c66a2011-08-16 12:25:13 -07003630 msleep(100);
Bradley Rubincb1e2732011-06-23 16:49:20 -07003631
Joonwoo Park8b1f0982011-12-08 17:12:45 -08003632 if (schedule_delayed_work(&priv->btn0_dwork,
3633 msecs_to_jiffies(400)) == 0) {
3634 WARN(1, "Button pressed twice without release event\n");
3635 tabla_unlock_sleep(priv);
3636 }
Bhalchandra Gajare0a792b12011-09-06 16:36:58 -07003637
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003638 return IRQ_HANDLED;
3639}
3640
Bradley Rubincb1e2732011-06-23 16:49:20 -07003641static irqreturn_t tabla_release_handler(int irq, void *data)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003642{
3643 struct tabla_priv *priv = data;
3644 struct snd_soc_codec *codec = priv->codec;
Joonwoo Park0976d012011-12-22 11:48:18 -08003645 int ret, mb_v;
Bhalchandra Gajare0a792b12011-09-06 16:36:58 -07003646
Bradley Rubin4d09cf42011-08-17 17:59:16 -07003647 pr_debug("%s\n", __func__);
3648 tabla_disable_irq(codec->control_data, TABLA_IRQ_MBHC_RELEASE);
Joonwoo Park8b1f0982011-12-08 17:12:45 -08003649 tabla_lock_sleep(priv);
Bhalchandra Gajare0a792b12011-09-06 16:36:58 -07003650
Bradley Rubincb1e2732011-06-23 16:49:20 -07003651 if (priv->buttons_pressed & SND_JACK_BTN_0) {
Bhalchandra Gajare0a792b12011-09-06 16:36:58 -07003652 ret = cancel_delayed_work(&priv->btn0_dwork);
3653
3654 if (ret == 0) {
Bhalchandra Gajare0a792b12011-09-06 16:36:58 -07003655 pr_debug("%s: Reporting long button release event\n",
3656 __func__);
Joonwoo Park0976d012011-12-22 11:48:18 -08003657 if (priv->button_jack)
Joonwoo Park8b1f0982011-12-08 17:12:45 -08003658 tabla_snd_soc_jack_report(priv,
3659 priv->button_jack, 0,
3660 SND_JACK_BTN_0);
Bhalchandra Gajare0a792b12011-09-06 16:36:58 -07003661 } else {
Joonwoo Park8b1f0982011-12-08 17:12:45 -08003662 /* if scheduled btn0_dwork is canceled from here,
3663 * we have to unlock from here instead btn0_work */
3664 tabla_unlock_sleep(priv);
Joonwoo Park0976d012011-12-22 11:48:18 -08003665 mb_v = tabla_codec_sta_dce(codec, 0);
3666 pr_debug("%s: Mic Voltage on release STA: %d,%d\n",
3667 __func__, mb_v,
3668 tabla_codec_sta_dce_v(codec, 0, mb_v));
Bhalchandra Gajare0a792b12011-09-06 16:36:58 -07003669
Joonwoo Park0976d012011-12-22 11:48:18 -08003670 if (mb_v < -2000 || mb_v > -670)
Bhalchandra Gajare0a792b12011-09-06 16:36:58 -07003671 pr_debug("%s: Fake buttton press interrupt\n",
3672 __func__);
Joonwoo Park0976d012011-12-22 11:48:18 -08003673 else if (priv->button_jack) {
3674 pr_debug("%s:reporting short button "
3675 "press and release\n", __func__);
3676 tabla_snd_soc_jack_report(priv,
3677 priv->button_jack,
3678 SND_JACK_BTN_0,
3679 SND_JACK_BTN_0);
3680 tabla_snd_soc_jack_report(priv,
3681 priv->button_jack,
3682 0, SND_JACK_BTN_0);
Bhalchandra Gajare0a792b12011-09-06 16:36:58 -07003683 }
3684 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003685
Bradley Rubincb1e2732011-06-23 16:49:20 -07003686 priv->buttons_pressed &= ~SND_JACK_BTN_0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003687 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003688
Bradley Rubin688c66a2011-08-16 12:25:13 -07003689 tabla_codec_start_hs_polling(codec);
Joonwoo Park8b1f0982011-12-08 17:12:45 -08003690 tabla_unlock_sleep(priv);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003691 return IRQ_HANDLED;
3692}
3693
Bradley Rubincb1e2732011-06-23 16:49:20 -07003694static void tabla_codec_shutdown_hs_removal_detect(struct snd_soc_codec *codec)
3695{
3696 struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
Joonwoo Park0976d012011-12-22 11:48:18 -08003697 const struct tabla_mbhc_general_cfg *generic =
3698 TABLA_MBHC_CAL_GENERAL_PTR(tabla->calibration);
Bradley Rubincb1e2732011-06-23 16:49:20 -07003699
Kiran Kandi6fae8bf2011-08-15 10:36:42 -07003700 if (!tabla->mclk_enabled && !tabla->mbhc_polling_active)
Bradley Rubincb1e2732011-06-23 16:49:20 -07003701 tabla_codec_enable_config_mode(codec, 1);
3702
3703 snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_CLK_CTL, 0x2, 0x2);
3704 snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_B1_CTL, 0x6, 0x0);
Bradley Rubincb1e2732011-06-23 16:49:20 -07003705
Joonwoo Park0976d012011-12-22 11:48:18 -08003706 snd_soc_update_bits(codec, tabla->mbhc_bias_regs.mbhc_reg, 0x80, 0x00);
3707
3708 usleep_range(generic->t_shutdown_plug_rem,
3709 generic->t_shutdown_plug_rem);
Bradley Rubincb1e2732011-06-23 16:49:20 -07003710
3711 snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_CLK_CTL, 0xA, 0x8);
Kiran Kandi6fae8bf2011-08-15 10:36:42 -07003712 if (!tabla->mclk_enabled && !tabla->mbhc_polling_active)
Bradley Rubincb1e2732011-06-23 16:49:20 -07003713 tabla_codec_enable_config_mode(codec, 0);
3714
3715 snd_soc_write(codec, TABLA_A_MBHC_SCALING_MUX_1, 0x00);
3716}
3717
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003718static void tabla_codec_shutdown_hs_polling(struct snd_soc_codec *codec)
3719{
3720 struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
Bradley Rubincb1e2732011-06-23 16:49:20 -07003721
3722 tabla_codec_shutdown_hs_removal_detect(codec);
3723
Kiran Kandi6fae8bf2011-08-15 10:36:42 -07003724 if (!tabla->mclk_enabled) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003725 snd_soc_update_bits(codec, TABLA_A_TX_COM_BIAS, 0xE0, 0x00);
3726 tabla_codec_enable_bandgap(codec, TABLA_BANDGAP_AUDIO_MODE);
3727 tabla_codec_enable_clock_block(codec, 0);
3728 }
3729
3730 tabla->mbhc_polling_active = false;
3731}
3732
Patrick Lai49efeac2011-11-03 11:01:12 -07003733static irqreturn_t tabla_hphl_ocp_irq(int irq, void *data)
3734{
3735 struct tabla_priv *tabla = data;
3736 struct snd_soc_codec *codec;
3737
3738 pr_info("%s: received HPHL OCP irq\n", __func__);
3739
3740 if (tabla) {
3741 codec = tabla->codec;
Patrick Laic7cae882011-11-18 11:52:49 -08003742 if (tabla->hphlocp_cnt++ < TABLA_OCP_ATTEMPT) {
3743 pr_info("%s: retry\n", __func__);
3744 snd_soc_update_bits(codec, TABLA_A_RX_HPH_OCP_CTL, 0x10,
3745 0x00);
3746 snd_soc_update_bits(codec, TABLA_A_RX_HPH_OCP_CTL, 0x10,
3747 0x10);
3748 } else {
3749 tabla_disable_irq(codec->control_data,
3750 TABLA_IRQ_HPH_PA_OCPL_FAULT);
3751 tabla->hphlocp_cnt = 0;
3752 tabla->hph_status |= SND_JACK_OC_HPHL;
3753 if (tabla->headset_jack)
3754 tabla_snd_soc_jack_report(tabla,
3755 tabla->headset_jack,
3756 tabla->hph_status,
3757 TABLA_JACK_MASK);
Patrick Lai49efeac2011-11-03 11:01:12 -07003758 }
3759 } else {
3760 pr_err("%s: Bad tabla private data\n", __func__);
3761 }
3762
3763 return IRQ_HANDLED;
3764}
3765
3766static irqreturn_t tabla_hphr_ocp_irq(int irq, void *data)
3767{
3768 struct tabla_priv *tabla = data;
3769 struct snd_soc_codec *codec;
3770
3771 pr_info("%s: received HPHR OCP irq\n", __func__);
3772
3773 if (tabla) {
3774 codec = tabla->codec;
Patrick Laic7cae882011-11-18 11:52:49 -08003775 if (tabla->hphrocp_cnt++ < TABLA_OCP_ATTEMPT) {
3776 pr_info("%s: retry\n", __func__);
3777 snd_soc_update_bits(codec, TABLA_A_RX_HPH_OCP_CTL, 0x10,
3778 0x00);
3779 snd_soc_update_bits(codec, TABLA_A_RX_HPH_OCP_CTL, 0x10,
3780 0x10);
3781 } else {
3782 tabla_disable_irq(codec->control_data,
3783 TABLA_IRQ_HPH_PA_OCPR_FAULT);
3784 tabla->hphrocp_cnt = 0;
3785 tabla->hph_status |= SND_JACK_OC_HPHR;
3786 if (tabla->headset_jack)
3787 tabla_snd_soc_jack_report(tabla,
3788 tabla->headset_jack,
3789 tabla->hph_status,
3790 TABLA_JACK_MASK);
Patrick Lai49efeac2011-11-03 11:01:12 -07003791 }
3792 } else {
3793 pr_err("%s: Bad tabla private data\n", __func__);
3794 }
3795
3796 return IRQ_HANDLED;
3797}
3798
Joonwoo Parka9444452011-12-08 18:48:27 -08003799static void tabla_sync_hph_state(struct tabla_priv *tabla)
3800{
3801 if (test_and_clear_bit(TABLA_HPHR_PA_OFF_ACK,
3802 &tabla->hph_pa_dac_state)) {
3803 pr_debug("%s: HPHR clear flag and enable PA\n", __func__);
3804 snd_soc_update_bits(tabla->codec, TABLA_A_RX_HPH_CNP_EN, 0x10,
3805 1 << 4);
3806 }
3807 if (test_and_clear_bit(TABLA_HPHL_PA_OFF_ACK,
3808 &tabla->hph_pa_dac_state)) {
3809 pr_debug("%s: HPHL clear flag and enable PA\n", __func__);
3810 snd_soc_update_bits(tabla->codec, TABLA_A_RX_HPH_CNP_EN, 0x20,
3811 1 << 5);
3812 }
3813
3814 if (test_and_clear_bit(TABLA_HPHR_DAC_OFF_ACK,
3815 &tabla->hph_pa_dac_state)) {
3816 pr_debug("%s: HPHR clear flag and enable DAC\n", __func__);
3817 snd_soc_update_bits(tabla->codec, TABLA_A_RX_HPH_R_DAC_CTL,
3818 0xC0, 0xC0);
3819 }
3820 if (test_and_clear_bit(TABLA_HPHL_DAC_OFF_ACK,
3821 &tabla->hph_pa_dac_state)) {
3822 pr_debug("%s: HPHL clear flag and enable DAC\n", __func__);
3823 snd_soc_update_bits(tabla->codec, TABLA_A_RX_HPH_L_DAC_CTL,
3824 0xC0, 0xC0);
3825 }
3826}
3827
Bradley Rubincb1e2732011-06-23 16:49:20 -07003828static irqreturn_t tabla_hs_insert_irq(int irq, void *data)
3829{
3830 struct tabla_priv *priv = data;
3831 struct snd_soc_codec *codec = priv->codec;
Joonwoo Park0976d012011-12-22 11:48:18 -08003832 const struct tabla_mbhc_plug_detect_cfg *plug_det =
3833 TABLA_MBHC_CAL_PLUG_DET_PTR(priv->calibration);
Bradley Rubin355611a2011-08-24 14:01:18 -07003834 int ldo_h_on, micb_cfilt_on;
Joonwoo Park0976d012011-12-22 11:48:18 -08003835 short mb_v;
Bhalchandra Gajare7fc72332011-10-13 19:01:55 -07003836 u8 is_removal;
Joonwoo Park0976d012011-12-22 11:48:18 -08003837 int mic_mv;
Bhalchandra Gajare343cbb02011-09-07 18:58:19 -07003838
Joonwoo Parkf4267c22012-01-10 13:25:24 -08003839 pr_debug("%s: enter\n", __func__);
Bradley Rubincb1e2732011-06-23 16:49:20 -07003840 tabla_disable_irq(codec->control_data, TABLA_IRQ_MBHC_INSERTION);
Joonwoo Park8b1f0982011-12-08 17:12:45 -08003841 tabla_lock_sleep(priv);
3842
Bhalchandra Gajare7fc72332011-10-13 19:01:55 -07003843 is_removal = snd_soc_read(codec, TABLA_A_CDC_MBHC_INT_CTL) & 0x02;
3844 snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_INT_CTL, 0x03, 0x00);
3845
3846 /* Turn off both HPH and MIC line schmitt triggers */
Joonwoo Park0976d012011-12-22 11:48:18 -08003847 snd_soc_update_bits(codec, priv->mbhc_bias_regs.mbhc_reg, 0x90, 0x00);
Bhalchandra Gajare7fc72332011-10-13 19:01:55 -07003848 snd_soc_update_bits(codec, TABLA_A_MBHC_HPH, 0x13, 0x00);
Bradley Rubincb1e2732011-06-23 16:49:20 -07003849
Joonwoo Parkf4267c22012-01-10 13:25:24 -08003850 if (priv->mbhc_fake_ins_start &&
3851 time_after(jiffies, priv->mbhc_fake_ins_start +
3852 msecs_to_jiffies(TABLA_FAKE_INS_THRESHOLD_MS))) {
Bhalchandra Gajare9494fa262011-11-10 19:25:59 -08003853 pr_debug("%s: fake context interrupt, reset insertion\n",
Joonwoo Parkf4267c22012-01-10 13:25:24 -08003854 __func__);
3855 priv->mbhc_fake_ins_start = 0;
Bhalchandra Gajare9494fa262011-11-10 19:25:59 -08003856 tabla_codec_shutdown_hs_polling(codec);
3857 tabla_codec_enable_hs_detect(codec, 1);
3858 return IRQ_HANDLED;
3859 }
3860
Bradley Rubin355611a2011-08-24 14:01:18 -07003861 ldo_h_on = snd_soc_read(codec, TABLA_A_LDO_H_MODE_1) & 0x80;
Joonwoo Park0976d012011-12-22 11:48:18 -08003862 micb_cfilt_on = snd_soc_read(codec, priv->mbhc_bias_regs.cfilt_ctl)
3863 & 0x80;
Bradley Rubin355611a2011-08-24 14:01:18 -07003864
3865 if (!ldo_h_on)
3866 snd_soc_update_bits(codec, TABLA_A_LDO_H_MODE_1, 0x80, 0x80);
3867 if (!micb_cfilt_on)
Bhalchandra Gajare02d90cd2011-09-30 16:14:00 -07003868 snd_soc_update_bits(codec, priv->mbhc_bias_regs.cfilt_ctl,
Joonwoo Park0976d012011-12-22 11:48:18 -08003869 0x80, 0x80);
3870 if (plug_det->t_ins_complete > 20)
3871 msleep(plug_det->t_ins_complete);
3872 else
3873 usleep_range(plug_det->t_ins_complete * 1000,
3874 plug_det->t_ins_complete * 1000);
Bradley Rubincb1e2732011-06-23 16:49:20 -07003875
Bhalchandra Gajare7fc72332011-10-13 19:01:55 -07003876 if (!ldo_h_on)
3877 snd_soc_update_bits(codec, TABLA_A_LDO_H_MODE_1, 0x80, 0x0);
3878 if (!micb_cfilt_on)
3879 snd_soc_update_bits(codec, priv->mbhc_bias_regs.cfilt_ctl,
Joonwoo Park0976d012011-12-22 11:48:18 -08003880 0x80, 0x0);
Bhalchandra Gajare7fc72332011-10-13 19:01:55 -07003881
3882 if (is_removal) {
Bhalchandra Gajared9ebb6c2011-10-03 19:54:41 -07003883 /*
3884 * If headphone is removed while playback is in progress,
3885 * it is possible that micbias will be switched to VDDIO.
3886 */
3887 if (priv->mbhc_micbias_switched)
3888 tabla_codec_switch_micbias(codec, 0);
Patrick Lai72aa4da2011-12-08 12:38:18 -08003889 priv->hph_status &= ~SND_JACK_HEADPHONE;
Joonwoo Parka9444452011-12-08 18:48:27 -08003890
3891 /* If headphone PA is on, check if userspace receives
3892 * removal event to sync-up PA's state */
3893 if (tabla_is_hph_pa_on(codec)) {
3894 set_bit(TABLA_HPHL_PA_OFF_ACK, &priv->hph_pa_dac_state);
3895 set_bit(TABLA_HPHR_PA_OFF_ACK, &priv->hph_pa_dac_state);
3896 }
3897
3898 if (tabla_is_hph_dac_on(codec, 1))
3899 set_bit(TABLA_HPHL_DAC_OFF_ACK,
3900 &priv->hph_pa_dac_state);
3901 if (tabla_is_hph_dac_on(codec, 0))
3902 set_bit(TABLA_HPHR_DAC_OFF_ACK,
3903 &priv->hph_pa_dac_state);
3904
Bradley Rubincb1e2732011-06-23 16:49:20 -07003905 if (priv->headset_jack) {
3906 pr_debug("%s: Reporting removal\n", __func__);
Joonwoo Park8b1f0982011-12-08 17:12:45 -08003907 tabla_snd_soc_jack_report(priv, priv->headset_jack,
3908 priv->hph_status,
3909 TABLA_JACK_MASK);
Bradley Rubincb1e2732011-06-23 16:49:20 -07003910 }
3911 tabla_codec_shutdown_hs_removal_detect(codec);
3912 tabla_codec_enable_hs_detect(codec, 1);
Joonwoo Park8b1f0982011-12-08 17:12:45 -08003913 tabla_unlock_sleep(priv);
Bradley Rubincb1e2732011-06-23 16:49:20 -07003914 return IRQ_HANDLED;
3915 }
3916
Joonwoo Park0976d012011-12-22 11:48:18 -08003917 mb_v = tabla_codec_setup_hs_polling(codec);
3918 mic_mv = tabla_codec_sta_dce_v(codec, 0, mb_v);
Bradley Rubin355611a2011-08-24 14:01:18 -07003919
Joonwoo Park0976d012011-12-22 11:48:18 -08003920 if (mb_v > (short) priv->mbhc_data.v_ins_hu) {
Joonwoo Parkf4267c22012-01-10 13:25:24 -08003921 pr_debug("%s: Fake insertion interrupt since %dmsec ago, "
3922 "STA : %d,%d\n", __func__,
3923 (priv->mbhc_fake_ins_start ?
3924 jiffies_to_msecs(jiffies -
3925 priv->mbhc_fake_ins_start) :
3926 0),
3927 mb_v, mic_mv);
3928 if (time_after(jiffies,
3929 priv->mbhc_fake_ins_start +
3930 msecs_to_jiffies(TABLA_FAKE_INS_THRESHOLD_MS))) {
3931 /* Disable HPH trigger and enable MIC line trigger */
3932 snd_soc_update_bits(codec, TABLA_A_MBHC_HPH, 0x12,
3933 0x00);
3934 snd_soc_update_bits(codec,
3935 priv->mbhc_bias_regs.mbhc_reg, 0x60,
3936 plug_det->mic_current << 5);
3937 snd_soc_update_bits(codec,
3938 priv->mbhc_bias_regs.mbhc_reg,
3939 0x80, 0x80);
3940 usleep_range(plug_det->t_mic_pid, plug_det->t_mic_pid);
3941 snd_soc_update_bits(codec,
3942 priv->mbhc_bias_regs.mbhc_reg,
3943 0x10, 0x10);
3944 } else {
3945 if (priv->mbhc_fake_ins_start == 0)
3946 priv->mbhc_fake_ins_start = jiffies;
3947 /* Setup normal insert detection
3948 * Enable HPH Schmitt Trigger
3949 */
3950 snd_soc_update_bits(codec, TABLA_A_MBHC_HPH,
3951 0x13 | 0x0C,
3952 0x13 | plug_det->hph_current << 2);
3953 }
Bhalchandra Gajare9494fa262011-11-10 19:25:59 -08003954 /* Setup for insertion detection */
3955 snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_INT_CTL, 0x2, 0);
Bhalchandra Gajare9494fa262011-11-10 19:25:59 -08003956 tabla_enable_irq(codec->control_data, TABLA_IRQ_MBHC_INSERTION);
3957 snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_INT_CTL, 0x1, 0x1);
3958
Joonwoo Park0976d012011-12-22 11:48:18 -08003959 } else if (mb_v < (short) priv->mbhc_data.v_no_mic) {
3960 pr_debug("%s: Headphone Detected, mb_v: %d,%d\n",
3961 __func__, mb_v, mic_mv);
Joonwoo Parkf4267c22012-01-10 13:25:24 -08003962 priv->mbhc_fake_ins_start = 0;
Patrick Lai49efeac2011-11-03 11:01:12 -07003963 priv->hph_status |= SND_JACK_HEADPHONE;
Bradley Rubincb1e2732011-06-23 16:49:20 -07003964 if (priv->headset_jack) {
3965 pr_debug("%s: Reporting insertion %d\n", __func__,
Joonwoo Park0976d012011-12-22 11:48:18 -08003966 SND_JACK_HEADPHONE);
Joonwoo Park8b1f0982011-12-08 17:12:45 -08003967 tabla_snd_soc_jack_report(priv, priv->headset_jack,
3968 priv->hph_status,
3969 TABLA_JACK_MASK);
Bradley Rubincb1e2732011-06-23 16:49:20 -07003970 }
3971 tabla_codec_shutdown_hs_polling(codec);
3972 tabla_codec_enable_hs_detect(codec, 0);
Joonwoo Parka9444452011-12-08 18:48:27 -08003973 tabla_sync_hph_state(priv);
Bhalchandra Gajare343cbb02011-09-07 18:58:19 -07003974 } else {
Joonwoo Park0976d012011-12-22 11:48:18 -08003975 pr_debug("%s: Headset detected, mb_v: %d,%d\n",
3976 __func__, mb_v, mic_mv);
Joonwoo Parkf4267c22012-01-10 13:25:24 -08003977 priv->mbhc_fake_ins_start = 0;
Patrick Lai49efeac2011-11-03 11:01:12 -07003978 priv->hph_status |= SND_JACK_HEADSET;
Bradley Rubincb1e2732011-06-23 16:49:20 -07003979 if (priv->headset_jack) {
3980 pr_debug("%s: Reporting insertion %d\n", __func__,
Joonwoo Park0976d012011-12-22 11:48:18 -08003981 SND_JACK_HEADSET);
Joonwoo Park8b1f0982011-12-08 17:12:45 -08003982 tabla_snd_soc_jack_report(priv, priv->headset_jack,
3983 priv->hph_status,
3984 TABLA_JACK_MASK);
Bradley Rubincb1e2732011-06-23 16:49:20 -07003985 }
Joonwoo Parkf4267c22012-01-10 13:25:24 -08003986 /* avoid false button press detect */
3987 msleep(50);
Bradley Rubincb1e2732011-06-23 16:49:20 -07003988 tabla_codec_start_hs_polling(codec);
Joonwoo Parka9444452011-12-08 18:48:27 -08003989 tabla_sync_hph_state(priv);
Bradley Rubincb1e2732011-06-23 16:49:20 -07003990 }
3991
Joonwoo Park8b1f0982011-12-08 17:12:45 -08003992 tabla_unlock_sleep(priv);
Bradley Rubincb1e2732011-06-23 16:49:20 -07003993 return IRQ_HANDLED;
3994}
3995
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003996static irqreturn_t tabla_hs_remove_irq(int irq, void *data)
3997{
3998 struct tabla_priv *priv = data;
3999 struct snd_soc_codec *codec = priv->codec;
Joonwoo Park0976d012011-12-22 11:48:18 -08004000 const struct tabla_mbhc_general_cfg *generic =
4001 TABLA_MBHC_CAL_GENERAL_PTR(priv->calibration);
Bradley Rubin89ffd0a2011-07-21 16:04:06 -07004002 short bias_value;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004003
4004 tabla_disable_irq(codec->control_data, TABLA_IRQ_MBHC_REMOVAL);
4005 tabla_disable_irq(codec->control_data, TABLA_IRQ_MBHC_POTENTIAL);
Bradley Rubin4d09cf42011-08-17 17:59:16 -07004006 tabla_disable_irq(codec->control_data, TABLA_IRQ_MBHC_RELEASE);
Joonwoo Park8b1f0982011-12-08 17:12:45 -08004007 tabla_lock_sleep(priv);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004008
Joonwoo Park0976d012011-12-22 11:48:18 -08004009 usleep_range(generic->t_shutdown_plug_rem,
4010 generic->t_shutdown_plug_rem);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004011
Joonwoo Park0976d012011-12-22 11:48:18 -08004012 bias_value = tabla_codec_sta_dce(codec, 1);
4013 pr_debug("removal interrupt, DCE: %d,%d\n",
4014 bias_value, tabla_codec_sta_dce_v(codec, 1, bias_value));
Bradley Rubin89ffd0a2011-07-21 16:04:06 -07004015
Joonwoo Park0976d012011-12-22 11:48:18 -08004016 if (bias_value < (short) priv->mbhc_data.v_ins_h) {
Bradley Rubin89ffd0a2011-07-21 16:04:06 -07004017 pr_debug("False alarm, headset not actually removed\n");
4018 tabla_codec_start_hs_polling(codec);
4019 } else {
Bhalchandra Gajared9ebb6c2011-10-03 19:54:41 -07004020 /*
4021 * If this removal is not false, first check the micbias
4022 * switch status and switch it to LDOH if it is already
4023 * switched to VDDIO.
4024 */
4025 if (priv->mbhc_micbias_switched)
4026 tabla_codec_switch_micbias(codec, 0);
Patrick Lai49efeac2011-11-03 11:01:12 -07004027 priv->hph_status &= ~SND_JACK_HEADSET;
Bradley Rubin89ffd0a2011-07-21 16:04:06 -07004028 if (priv->headset_jack) {
4029 pr_debug("%s: Reporting removal\n", __func__);
Joonwoo Park8b1f0982011-12-08 17:12:45 -08004030 tabla_snd_soc_jack_report(priv, priv->headset_jack, 0,
4031 TABLA_JACK_MASK);
Bradley Rubin89ffd0a2011-07-21 16:04:06 -07004032 }
4033 tabla_codec_shutdown_hs_polling(codec);
4034
4035 tabla_codec_enable_hs_detect(codec, 1);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004036 }
Joonwoo Park8b1f0982011-12-08 17:12:45 -08004037
4038 tabla_unlock_sleep(priv);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004039 return IRQ_HANDLED;
4040}
4041
4042static unsigned long slimbus_value;
4043
4044static irqreturn_t tabla_slimbus_irq(int irq, void *data)
4045{
4046 struct tabla_priv *priv = data;
4047 struct snd_soc_codec *codec = priv->codec;
4048 int i, j;
4049 u8 val;
4050
Joonwoo Park8b1f0982011-12-08 17:12:45 -08004051 tabla_lock_sleep(priv);
4052
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004053 for (i = 0; i < TABLA_SLIM_NUM_PORT_REG; i++) {
4054 slimbus_value = tabla_interface_reg_read(codec->control_data,
4055 TABLA_SLIM_PGD_PORT_INT_STATUS0 + i);
4056 for_each_set_bit(j, &slimbus_value, BITS_PER_BYTE) {
4057 val = tabla_interface_reg_read(codec->control_data,
4058 TABLA_SLIM_PGD_PORT_INT_SOURCE0 + i*8 + j);
4059 if (val & 0x1)
4060 pr_err_ratelimited("overflow error on port %x,"
4061 " value %x\n", i*8 + j, val);
4062 if (val & 0x2)
4063 pr_err_ratelimited("underflow error on port %x,"
4064 " value %x\n", i*8 + j, val);
4065 }
4066 tabla_interface_reg_write(codec->control_data,
4067 TABLA_SLIM_PGD_PORT_INT_CLR0 + i, 0xFF);
4068 }
4069
Joonwoo Park8b1f0982011-12-08 17:12:45 -08004070 tabla_unlock_sleep(priv);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004071 return IRQ_HANDLED;
4072}
4073
Patrick Lai3043fba2011-08-01 14:15:57 -07004074
4075static int tabla_handle_pdata(struct tabla_priv *tabla)
4076{
4077 struct snd_soc_codec *codec = tabla->codec;
4078 struct tabla_pdata *pdata = tabla->pdata;
4079 int k1, k2, k3, rc = 0;
Santosh Mardi22920282011-10-26 02:38:40 +05304080 u8 leg_mode = pdata->amic_settings.legacy_mode;
4081 u8 txfe_bypass = pdata->amic_settings.txfe_enable;
4082 u8 txfe_buff = pdata->amic_settings.txfe_buff;
4083 u8 flag = pdata->amic_settings.use_pdata;
4084 u8 i = 0, j = 0;
4085 u8 val_txfe = 0, value = 0;
Patrick Lai3043fba2011-08-01 14:15:57 -07004086
4087 if (!pdata) {
4088 rc = -ENODEV;
4089 goto done;
4090 }
4091
4092 /* Make sure settings are correct */
4093 if ((pdata->micbias.ldoh_v > TABLA_LDOH_2P85_V) ||
4094 (pdata->micbias.bias1_cfilt_sel > TABLA_CFILT3_SEL) ||
4095 (pdata->micbias.bias2_cfilt_sel > TABLA_CFILT3_SEL) ||
4096 (pdata->micbias.bias3_cfilt_sel > TABLA_CFILT3_SEL) ||
4097 (pdata->micbias.bias4_cfilt_sel > TABLA_CFILT3_SEL)) {
4098 rc = -EINVAL;
4099 goto done;
4100 }
4101
4102 /* figure out k value */
4103 k1 = tabla_find_k_value(pdata->micbias.ldoh_v,
4104 pdata->micbias.cfilt1_mv);
4105 k2 = tabla_find_k_value(pdata->micbias.ldoh_v,
4106 pdata->micbias.cfilt2_mv);
4107 k3 = tabla_find_k_value(pdata->micbias.ldoh_v,
4108 pdata->micbias.cfilt3_mv);
4109
4110 if (IS_ERR_VALUE(k1) || IS_ERR_VALUE(k2) || IS_ERR_VALUE(k3)) {
4111 rc = -EINVAL;
4112 goto done;
4113 }
4114
4115 /* Set voltage level and always use LDO */
4116 snd_soc_update_bits(codec, TABLA_A_LDO_H_MODE_1, 0x0C,
4117 (pdata->micbias.ldoh_v << 2));
4118
4119 snd_soc_update_bits(codec, TABLA_A_MICB_CFILT_1_VAL, 0xFC,
4120 (k1 << 2));
4121 snd_soc_update_bits(codec, TABLA_A_MICB_CFILT_2_VAL, 0xFC,
4122 (k2 << 2));
4123 snd_soc_update_bits(codec, TABLA_A_MICB_CFILT_3_VAL, 0xFC,
4124 (k3 << 2));
4125
4126 snd_soc_update_bits(codec, TABLA_A_MICB_1_CTL, 0x60,
4127 (pdata->micbias.bias1_cfilt_sel << 5));
4128 snd_soc_update_bits(codec, TABLA_A_MICB_2_CTL, 0x60,
4129 (pdata->micbias.bias2_cfilt_sel << 5));
4130 snd_soc_update_bits(codec, TABLA_A_MICB_3_CTL, 0x60,
4131 (pdata->micbias.bias3_cfilt_sel << 5));
4132 snd_soc_update_bits(codec, TABLA_A_MICB_4_CTL, 0x60,
4133 (pdata->micbias.bias4_cfilt_sel << 5));
4134
Santosh Mardi22920282011-10-26 02:38:40 +05304135 for (i = 0; i < 6; j++, i += 2) {
4136 if (flag & (0x01 << i)) {
4137 value = (leg_mode & (0x01 << i)) ? 0x10 : 0x00;
4138 val_txfe = (txfe_bypass & (0x01 << i)) ? 0x20 : 0x00;
4139 val_txfe = val_txfe |
4140 ((txfe_buff & (0x01 << i)) ? 0x10 : 0x00);
4141 snd_soc_update_bits(codec, TABLA_A_TX_1_2_EN + j * 10,
4142 0x10, value);
4143 snd_soc_update_bits(codec,
4144 TABLA_A_TX_1_2_TEST_EN + j * 10,
4145 0x30, val_txfe);
4146 }
4147 if (flag & (0x01 << (i + 1))) {
4148 value = (leg_mode & (0x01 << (i + 1))) ? 0x01 : 0x00;
4149 val_txfe = (txfe_bypass &
4150 (0x01 << (i + 1))) ? 0x02 : 0x00;
4151 val_txfe |= (txfe_buff &
4152 (0x01 << (i + 1))) ? 0x01 : 0x00;
4153 snd_soc_update_bits(codec, TABLA_A_TX_1_2_EN + j * 10,
4154 0x01, value);
4155 snd_soc_update_bits(codec,
4156 TABLA_A_TX_1_2_TEST_EN + j * 10,
4157 0x03, val_txfe);
4158 }
4159 }
4160 if (flag & 0x40) {
4161 value = (leg_mode & 0x40) ? 0x10 : 0x00;
4162 value = value | ((txfe_bypass & 0x40) ? 0x02 : 0x00);
4163 value = value | ((txfe_buff & 0x40) ? 0x01 : 0x00);
4164 snd_soc_update_bits(codec, TABLA_A_TX_7_MBHC_EN,
4165 0x13, value);
4166 }
Patrick Lai49efeac2011-11-03 11:01:12 -07004167
4168 if (pdata->ocp.use_pdata) {
4169 /* not defined in CODEC specification */
4170 if (pdata->ocp.hph_ocp_limit == 1 ||
4171 pdata->ocp.hph_ocp_limit == 5) {
4172 rc = -EINVAL;
4173 goto done;
4174 }
4175 snd_soc_update_bits(codec, TABLA_A_RX_COM_OCP_CTL,
4176 0x0F, pdata->ocp.num_attempts);
4177 snd_soc_write(codec, TABLA_A_RX_COM_OCP_COUNT,
4178 ((pdata->ocp.run_time << 4) | pdata->ocp.wait_time));
4179 snd_soc_update_bits(codec, TABLA_A_RX_HPH_OCP_CTL,
4180 0xE0, (pdata->ocp.hph_ocp_limit << 5));
4181 }
Patrick Lai3043fba2011-08-01 14:15:57 -07004182done:
4183 return rc;
4184}
4185
Kiran Kandi1f6fd722011-08-11 10:36:11 -07004186static const struct tabla_reg_mask_val tabla_1_1_reg_defaults[] = {
4187
4188 /* Tabla 1.1 MICBIAS changes */
4189 TABLA_REG_VAL(TABLA_A_MICB_1_INT_RBIAS, 0x24),
4190 TABLA_REG_VAL(TABLA_A_MICB_2_INT_RBIAS, 0x24),
4191 TABLA_REG_VAL(TABLA_A_MICB_3_INT_RBIAS, 0x24),
4192 TABLA_REG_VAL(TABLA_A_MICB_4_INT_RBIAS, 0x24),
4193
4194 /* Tabla 1.1 HPH changes */
4195 TABLA_REG_VAL(TABLA_A_RX_HPH_BIAS_PA, 0x57),
4196 TABLA_REG_VAL(TABLA_A_RX_HPH_BIAS_LDO, 0x56),
4197
4198 /* Tabla 1.1 EAR PA changes */
4199 TABLA_REG_VAL(TABLA_A_RX_EAR_BIAS_PA, 0xA6),
4200 TABLA_REG_VAL(TABLA_A_RX_EAR_GAIN, 0x02),
4201 TABLA_REG_VAL(TABLA_A_RX_EAR_VCM, 0x03),
4202
4203 /* Tabla 1.1 Lineout_5 Changes */
4204 TABLA_REG_VAL(TABLA_A_RX_LINE_5_GAIN, 0x10),
4205
4206 /* Tabla 1.1 RX Changes */
4207 TABLA_REG_VAL(TABLA_A_CDC_RX1_B5_CTL, 0x78),
4208 TABLA_REG_VAL(TABLA_A_CDC_RX2_B5_CTL, 0x78),
4209 TABLA_REG_VAL(TABLA_A_CDC_RX3_B5_CTL, 0x78),
4210 TABLA_REG_VAL(TABLA_A_CDC_RX4_B5_CTL, 0x78),
4211 TABLA_REG_VAL(TABLA_A_CDC_RX5_B5_CTL, 0x78),
4212 TABLA_REG_VAL(TABLA_A_CDC_RX6_B5_CTL, 0x78),
4213 TABLA_REG_VAL(TABLA_A_CDC_RX7_B5_CTL, 0x78),
4214
4215 /* Tabla 1.1 RX1 and RX2 Changes */
4216 TABLA_REG_VAL(TABLA_A_CDC_RX1_B6_CTL, 0xA0),
4217 TABLA_REG_VAL(TABLA_A_CDC_RX2_B6_CTL, 0xA0),
4218
4219 /* Tabla 1.1 RX3 to RX7 Changes */
4220 TABLA_REG_VAL(TABLA_A_CDC_RX3_B6_CTL, 0x80),
4221 TABLA_REG_VAL(TABLA_A_CDC_RX4_B6_CTL, 0x80),
4222 TABLA_REG_VAL(TABLA_A_CDC_RX5_B6_CTL, 0x80),
4223 TABLA_REG_VAL(TABLA_A_CDC_RX6_B6_CTL, 0x80),
4224 TABLA_REG_VAL(TABLA_A_CDC_RX7_B6_CTL, 0x80),
4225
4226 /* Tabla 1.1 CLASSG Changes */
4227 TABLA_REG_VAL(TABLA_A_CDC_CLSG_FREQ_THRESH_B3_CTL, 0x1B),
4228};
4229
4230static const struct tabla_reg_mask_val tabla_2_0_reg_defaults[] = {
4231
4232 /* Tabla 2.0 MICBIAS changes */
4233 TABLA_REG_VAL(TABLA_A_MICB_2_MBHC, 0x02),
4234};
4235
4236static void tabla_update_reg_defaults(struct snd_soc_codec *codec)
4237{
4238 u32 i;
4239
4240 for (i = 0; i < ARRAY_SIZE(tabla_1_1_reg_defaults); i++)
4241 snd_soc_write(codec, tabla_1_1_reg_defaults[i].reg,
4242 tabla_1_1_reg_defaults[i].val);
4243
4244 for (i = 0; i < ARRAY_SIZE(tabla_2_0_reg_defaults); i++)
4245 snd_soc_write(codec, tabla_2_0_reg_defaults[i].reg,
4246 tabla_2_0_reg_defaults[i].val);
4247}
4248
4249static const struct tabla_reg_mask_val tabla_codec_reg_init_val[] = {
Patrick Laic7cae882011-11-18 11:52:49 -08004250 /* Initialize current threshold to 350MA
4251 * number of wait and run cycles to 4096
4252 */
Patrick Lai49efeac2011-11-03 11:01:12 -07004253 {TABLA_A_RX_HPH_OCP_CTL, 0xE0, 0x60},
Patrick Laic7cae882011-11-18 11:52:49 -08004254 {TABLA_A_RX_COM_OCP_COUNT, 0xFF, 0xFF},
Kiran Kandi1f6fd722011-08-11 10:36:11 -07004255
Santosh Mardi32171012011-10-28 23:32:06 +05304256 {TABLA_A_QFUSE_CTL, 0xFF, 0x03},
4257
Kiran Kandi1f6fd722011-08-11 10:36:11 -07004258 /* Initialize gain registers to use register gain */
4259 {TABLA_A_RX_HPH_L_GAIN, 0x10, 0x10},
4260 {TABLA_A_RX_HPH_R_GAIN, 0x10, 0x10},
4261 {TABLA_A_RX_LINE_1_GAIN, 0x10, 0x10},
4262 {TABLA_A_RX_LINE_2_GAIN, 0x10, 0x10},
4263 {TABLA_A_RX_LINE_3_GAIN, 0x10, 0x10},
4264 {TABLA_A_RX_LINE_4_GAIN, 0x10, 0x10},
4265
4266 /* Initialize mic biases to differential mode */
4267 {TABLA_A_MICB_1_INT_RBIAS, 0x24, 0x24},
4268 {TABLA_A_MICB_2_INT_RBIAS, 0x24, 0x24},
4269 {TABLA_A_MICB_3_INT_RBIAS, 0x24, 0x24},
4270 {TABLA_A_MICB_4_INT_RBIAS, 0x24, 0x24},
4271
4272 {TABLA_A_CDC_CONN_CLSG_CTL, 0x3C, 0x14},
4273
4274 /* Use 16 bit sample size for TX1 to TX6 */
4275 {TABLA_A_CDC_CONN_TX_SB_B1_CTL, 0x30, 0x20},
4276 {TABLA_A_CDC_CONN_TX_SB_B2_CTL, 0x30, 0x20},
4277 {TABLA_A_CDC_CONN_TX_SB_B3_CTL, 0x30, 0x20},
4278 {TABLA_A_CDC_CONN_TX_SB_B4_CTL, 0x30, 0x20},
4279 {TABLA_A_CDC_CONN_TX_SB_B5_CTL, 0x30, 0x20},
4280 {TABLA_A_CDC_CONN_TX_SB_B6_CTL, 0x30, 0x20},
4281
4282 /* Use 16 bit sample size for TX7 to TX10 */
4283 {TABLA_A_CDC_CONN_TX_SB_B7_CTL, 0x60, 0x40},
4284 {TABLA_A_CDC_CONN_TX_SB_B8_CTL, 0x60, 0x40},
4285 {TABLA_A_CDC_CONN_TX_SB_B9_CTL, 0x60, 0x40},
4286 {TABLA_A_CDC_CONN_TX_SB_B10_CTL, 0x60, 0x40},
4287
4288 /* Use 16 bit sample size for RX */
4289 {TABLA_A_CDC_CONN_RX_SB_B1_CTL, 0xFF, 0xAA},
4290 {TABLA_A_CDC_CONN_RX_SB_B2_CTL, 0xFF, 0xAA},
4291
4292 /*enable HPF filter for TX paths */
4293 {TABLA_A_CDC_TX1_MUX_CTL, 0x8, 0x0},
4294 {TABLA_A_CDC_TX2_MUX_CTL, 0x8, 0x0},
4295 {TABLA_A_CDC_TX3_MUX_CTL, 0x8, 0x0},
4296 {TABLA_A_CDC_TX4_MUX_CTL, 0x8, 0x0},
4297 {TABLA_A_CDC_TX5_MUX_CTL, 0x8, 0x0},
4298 {TABLA_A_CDC_TX6_MUX_CTL, 0x8, 0x0},
4299 {TABLA_A_CDC_TX7_MUX_CTL, 0x8, 0x0},
4300 {TABLA_A_CDC_TX8_MUX_CTL, 0x8, 0x0},
4301 {TABLA_A_CDC_TX9_MUX_CTL, 0x8, 0x0},
4302 {TABLA_A_CDC_TX10_MUX_CTL, 0x8, 0x0},
4303};
4304
4305static void tabla_codec_init_reg(struct snd_soc_codec *codec)
4306{
4307 u32 i;
4308
4309 for (i = 0; i < ARRAY_SIZE(tabla_codec_reg_init_val); i++)
4310 snd_soc_update_bits(codec, tabla_codec_reg_init_val[i].reg,
4311 tabla_codec_reg_init_val[i].mask,
4312 tabla_codec_reg_init_val[i].val);
4313}
4314
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004315static int tabla_codec_probe(struct snd_soc_codec *codec)
4316{
4317 struct tabla *control;
4318 struct tabla_priv *tabla;
4319 struct snd_soc_dapm_context *dapm = &codec->dapm;
4320 int ret = 0;
4321 int i;
Kiran Kandi8b3a8302011-09-27 16:13:28 -07004322 u8 tabla_version;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004323
4324 codec->control_data = dev_get_drvdata(codec->dev->parent);
4325 control = codec->control_data;
4326
4327 tabla = kzalloc(sizeof(struct tabla_priv), GFP_KERNEL);
4328 if (!tabla) {
4329 dev_err(codec->dev, "Failed to allocate private data\n");
4330 return -ENOMEM;
4331 }
4332
Bhalchandra Gajare02d90cd2011-09-30 16:14:00 -07004333 /* Make sure mbhc micbias register addresses are zeroed out */
4334 memset(&tabla->mbhc_bias_regs, 0,
4335 sizeof(struct mbhc_micbias_regs));
Bhalchandra Gajared9ebb6c2011-10-03 19:54:41 -07004336 tabla->cfilt_k_value = 0;
4337 tabla->mbhc_micbias_switched = false;
Bhalchandra Gajare02d90cd2011-09-30 16:14:00 -07004338
Joonwoo Park0976d012011-12-22 11:48:18 -08004339 /* Make sure mbhc intenal calibration data is zeroed out */
4340 memset(&tabla->mbhc_data, 0,
4341 sizeof(struct mbhc_internal_cal_data));
4342 tabla->mbhc_data.t_dce = DEFAULT_DCE_WAIT;
4343 tabla->mbhc_data.t_sta = DEFAULT_STA_WAIT;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004344 snd_soc_codec_set_drvdata(codec, tabla);
4345
Kiran Kandi6fae8bf2011-08-15 10:36:42 -07004346 tabla->mclk_enabled = false;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004347 tabla->bandgap_type = TABLA_BANDGAP_OFF;
4348 tabla->clock_active = false;
4349 tabla->config_mode_active = false;
4350 tabla->mbhc_polling_active = false;
Joonwoo Parkf4267c22012-01-10 13:25:24 -08004351 tabla->mbhc_fake_ins_start = 0;
Bradley Rubincb3950a2011-08-18 13:07:26 -07004352 tabla->no_mic_headset_override = false;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004353 tabla->codec = codec;
Patrick Lai3043fba2011-08-01 14:15:57 -07004354 tabla->pdata = dev_get_platdata(codec->dev->parent);
Santosh Mardie15e2302011-11-15 10:39:23 +05304355 tabla->intf_type = tabla_get_intf_type();
Joonwoo Park8b1f0982011-12-08 17:12:45 -08004356 atomic_set(&tabla->pm_cnt, 1);
4357 init_waitqueue_head(&tabla->pm_wq);
Patrick Lai3043fba2011-08-01 14:15:57 -07004358
Santosh Mardi22920282011-10-26 02:38:40 +05304359 tabla_update_reg_defaults(codec);
4360 tabla_codec_init_reg(codec);
Patrick Lai3043fba2011-08-01 14:15:57 -07004361
Santosh Mardi22920282011-10-26 02:38:40 +05304362 ret = tabla_handle_pdata(tabla);
Patrick Lai3043fba2011-08-01 14:15:57 -07004363 if (IS_ERR_VALUE(ret)) {
4364 pr_err("%s: bad pdata\n", __func__);
4365 goto err_pdata;
4366 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004367
4368 /* TODO only enable bandgap when necessary in order to save power */
4369 tabla_codec_enable_bandgap(codec, TABLA_BANDGAP_AUDIO_MODE);
4370 tabla_codec_enable_clock_block(codec, 0);
4371
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004372 snd_soc_add_controls(codec, tabla_snd_controls,
4373 ARRAY_SIZE(tabla_snd_controls));
4374 snd_soc_dapm_new_controls(dapm, tabla_dapm_widgets,
4375 ARRAY_SIZE(tabla_dapm_widgets));
Santosh Mardie15e2302011-11-15 10:39:23 +05304376 if (tabla->intf_type == TABLA_INTERFACE_TYPE_I2C) {
4377 snd_soc_dapm_new_controls(dapm, tabla_dapm_i2s_widgets,
4378 ARRAY_SIZE(tabla_dapm_i2s_widgets));
4379 snd_soc_dapm_add_routes(dapm, audio_i2s_map,
4380 ARRAY_SIZE(audio_i2s_map));
4381 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004382 snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
Kiran Kandi8b3a8302011-09-27 16:13:28 -07004383
4384 tabla_version = snd_soc_read(codec, TABLA_A_CHIP_VERSION);
Joonwoo Park0976d012011-12-22 11:48:18 -08004385 pr_info("%s : Tabla version reg 0x%2x\n", __func__,
4386 (u32)tabla_version);
Kiran Kandi8b3a8302011-09-27 16:13:28 -07004387
4388 tabla_version &= 0x1F;
4389 pr_info("%s : Tabla version %u\n", __func__, (u32)tabla_version);
4390
Kiran Kandi7a9fd902011-11-14 13:51:45 -08004391 if ((tabla_version == TABLA_VERSION_1_0) ||
4392 (tabla_version == TABLA_VERSION_1_1)) {
4393 snd_soc_dapm_add_routes(dapm, tabla_1_x_lineout_2_to_4_map,
Kiran Kandi8b3a8302011-09-27 16:13:28 -07004394 ARRAY_SIZE(tabla_1_x_lineout_2_to_4_map));
4395
Kiran Kandi7a9fd902011-11-14 13:51:45 -08004396 } else if (tabla_version == TABLA_VERSION_2_0) {
4397 snd_soc_dapm_add_routes(dapm, tabla_2_x_lineout_2_to_4_map,
4398 ARRAY_SIZE(tabla_2_x_lineout_2_to_4_map));
4399 } else {
4400 pr_err("%s : ERROR. Unsupported Tabla version 0x%2x\n",
4401 __func__, (u32)tabla_version);
4402 goto err_pdata;
4403 }
4404
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004405 snd_soc_dapm_sync(dapm);
4406
4407 ret = tabla_request_irq(codec->control_data, TABLA_IRQ_MBHC_INSERTION,
4408 tabla_hs_insert_irq, "Headset insert detect", tabla);
4409 if (ret) {
4410 pr_err("%s: Failed to request irq %d\n", __func__,
4411 TABLA_IRQ_MBHC_INSERTION);
4412 goto err_insert_irq;
4413 }
4414 tabla_disable_irq(codec->control_data, TABLA_IRQ_MBHC_INSERTION);
4415
4416 ret = tabla_request_irq(codec->control_data, TABLA_IRQ_MBHC_REMOVAL,
4417 tabla_hs_remove_irq, "Headset remove detect", tabla);
4418 if (ret) {
4419 pr_err("%s: Failed to request irq %d\n", __func__,
4420 TABLA_IRQ_MBHC_REMOVAL);
4421 goto err_remove_irq;
4422 }
4423 tabla_disable_irq(codec->control_data, TABLA_IRQ_MBHC_REMOVAL);
4424
4425 ret = tabla_request_irq(codec->control_data, TABLA_IRQ_MBHC_POTENTIAL,
Bradley Rubincb1e2732011-06-23 16:49:20 -07004426 tabla_dce_handler, "DC Estimation detect", tabla);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004427 if (ret) {
4428 pr_err("%s: Failed to request irq %d\n", __func__,
4429 TABLA_IRQ_MBHC_POTENTIAL);
4430 goto err_potential_irq;
4431 }
4432 tabla_disable_irq(codec->control_data, TABLA_IRQ_MBHC_POTENTIAL);
4433
Bradley Rubincb1e2732011-06-23 16:49:20 -07004434 ret = tabla_request_irq(codec->control_data, TABLA_IRQ_MBHC_RELEASE,
4435 tabla_release_handler, "Button Release detect", tabla);
4436 if (ret) {
4437 pr_err("%s: Failed to request irq %d\n", __func__,
4438 TABLA_IRQ_MBHC_RELEASE);
4439 goto err_release_irq;
4440 }
Bradley Rubin4d09cf42011-08-17 17:59:16 -07004441 tabla_disable_irq(codec->control_data, TABLA_IRQ_MBHC_RELEASE);
Bradley Rubincb1e2732011-06-23 16:49:20 -07004442
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004443 ret = tabla_request_irq(codec->control_data, TABLA_IRQ_SLIMBUS,
4444 tabla_slimbus_irq, "SLIMBUS Slave", tabla);
4445 if (ret) {
4446 pr_err("%s: Failed to request irq %d\n", __func__,
4447 TABLA_IRQ_SLIMBUS);
4448 goto err_slimbus_irq;
4449 }
4450
4451 for (i = 0; i < TABLA_SLIM_NUM_PORT_REG; i++)
4452 tabla_interface_reg_write(codec->control_data,
4453 TABLA_SLIM_PGD_PORT_INT_EN0 + i, 0xFF);
4454
Patrick Lai49efeac2011-11-03 11:01:12 -07004455 ret = tabla_request_irq(codec->control_data,
4456 TABLA_IRQ_HPH_PA_OCPL_FAULT, tabla_hphl_ocp_irq,
4457 "HPH_L OCP detect", tabla);
4458 if (ret) {
4459 pr_err("%s: Failed to request irq %d\n", __func__,
4460 TABLA_IRQ_HPH_PA_OCPL_FAULT);
4461 goto err_hphl_ocp_irq;
4462 }
Patrick Lai92032be2011-12-19 14:14:25 -08004463 tabla_disable_irq(codec->control_data, TABLA_IRQ_HPH_PA_OCPL_FAULT);
Patrick Lai49efeac2011-11-03 11:01:12 -07004464
4465 ret = tabla_request_irq(codec->control_data,
4466 TABLA_IRQ_HPH_PA_OCPR_FAULT, tabla_hphr_ocp_irq,
4467 "HPH_R OCP detect", tabla);
4468 if (ret) {
4469 pr_err("%s: Failed to request irq %d\n", __func__,
4470 TABLA_IRQ_HPH_PA_OCPR_FAULT);
4471 goto err_hphr_ocp_irq;
4472 }
Patrick Lai92032be2011-12-19 14:14:25 -08004473 tabla_disable_irq(codec->control_data, TABLA_IRQ_HPH_PA_OCPR_FAULT);
Patrick Lai49efeac2011-11-03 11:01:12 -07004474
Bradley Rubincb3950a2011-08-18 13:07:26 -07004475#ifdef CONFIG_DEBUG_FS
4476 debug_tabla_priv = tabla;
4477#endif
4478
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004479 return ret;
4480
Patrick Lai49efeac2011-11-03 11:01:12 -07004481err_hphr_ocp_irq:
4482 tabla_free_irq(codec->control_data, TABLA_IRQ_HPH_PA_OCPL_FAULT, tabla);
4483err_hphl_ocp_irq:
4484 tabla_free_irq(codec->control_data, TABLA_IRQ_SLIMBUS, tabla);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004485err_slimbus_irq:
Bradley Rubincb1e2732011-06-23 16:49:20 -07004486 tabla_free_irq(codec->control_data, TABLA_IRQ_MBHC_RELEASE, tabla);
4487err_release_irq:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004488 tabla_free_irq(codec->control_data, TABLA_IRQ_MBHC_POTENTIAL, tabla);
4489err_potential_irq:
4490 tabla_free_irq(codec->control_data, TABLA_IRQ_MBHC_REMOVAL, tabla);
4491err_remove_irq:
4492 tabla_free_irq(codec->control_data, TABLA_IRQ_MBHC_INSERTION, tabla);
4493err_insert_irq:
Patrick Lai3043fba2011-08-01 14:15:57 -07004494err_pdata:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004495 kfree(tabla);
4496 return ret;
4497}
4498static int tabla_codec_remove(struct snd_soc_codec *codec)
4499{
4500 struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
4501 tabla_free_irq(codec->control_data, TABLA_IRQ_SLIMBUS, tabla);
Bradley Rubincb1e2732011-06-23 16:49:20 -07004502 tabla_free_irq(codec->control_data, TABLA_IRQ_MBHC_RELEASE, tabla);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004503 tabla_free_irq(codec->control_data, TABLA_IRQ_MBHC_POTENTIAL, tabla);
4504 tabla_free_irq(codec->control_data, TABLA_IRQ_MBHC_REMOVAL, tabla);
4505 tabla_free_irq(codec->control_data, TABLA_IRQ_MBHC_INSERTION, tabla);
4506 tabla_codec_disable_clock_block(codec);
4507 tabla_codec_enable_bandgap(codec, TABLA_BANDGAP_OFF);
4508 kfree(tabla);
4509 return 0;
4510}
4511static struct snd_soc_codec_driver soc_codec_dev_tabla = {
4512 .probe = tabla_codec_probe,
4513 .remove = tabla_codec_remove,
4514 .read = tabla_read,
4515 .write = tabla_write,
4516
4517 .readable_register = tabla_readable,
4518 .volatile_register = tabla_volatile,
4519
4520 .reg_cache_size = TABLA_CACHE_SIZE,
4521 .reg_cache_default = tabla_reg_defaults,
4522 .reg_word_size = 1,
4523};
Bradley Rubincb3950a2011-08-18 13:07:26 -07004524
4525#ifdef CONFIG_DEBUG_FS
4526static struct dentry *debugfs_poke;
4527
4528static int codec_debug_open(struct inode *inode, struct file *file)
4529{
4530 file->private_data = inode->i_private;
4531 return 0;
4532}
4533
4534static ssize_t codec_debug_write(struct file *filp,
4535 const char __user *ubuf, size_t cnt, loff_t *ppos)
4536{
4537 char lbuf[32];
4538 char *buf;
4539 int rc;
4540
4541 if (cnt > sizeof(lbuf) - 1)
4542 return -EINVAL;
4543
4544 rc = copy_from_user(lbuf, ubuf, cnt);
4545 if (rc)
4546 return -EFAULT;
4547
4548 lbuf[cnt] = '\0';
4549 buf = (char *)lbuf;
4550 debug_tabla_priv->no_mic_headset_override = (*strsep(&buf, " ") == '0')
4551 ? false : true;
4552
4553 return rc;
4554}
4555
4556static const struct file_operations codec_debug_ops = {
4557 .open = codec_debug_open,
4558 .write = codec_debug_write,
4559};
4560#endif
4561
Joonwoo Park8b1f0982011-12-08 17:12:45 -08004562#ifdef CONFIG_PM
4563static int tabla_suspend(struct device *dev)
4564{
4565 int ret = 0, cnt;
4566 struct platform_device *pdev = to_platform_device(dev);
4567 struct tabla_priv *tabla = platform_get_drvdata(pdev);
4568
4569 cnt = atomic_read(&tabla->pm_cnt);
4570 if (cnt > 0) {
4571 if (wait_event_timeout(tabla->pm_wq,
4572 (atomic_cmpxchg(&tabla->pm_cnt, 1, 0)
4573 == 1), 5 * HZ)) {
4574 dev_dbg(dev, "system suspend pm_cnt %d\n",
4575 atomic_read(&tabla->pm_cnt));
4576 } else {
4577 dev_err(dev, "%s timed out pm_cnt = %d\n",
4578 __func__, atomic_read(&tabla->pm_cnt));
4579 WARN_ON_ONCE(1);
4580 ret = -EBUSY;
4581 }
4582 } else if (cnt == 0)
4583 dev_warn(dev, "system is already in suspend, pm_cnt %d\n",
4584 atomic_read(&tabla->pm_cnt));
4585 else {
4586 WARN(1, "unexpected pm_cnt %d\n", cnt);
4587 ret = -EFAULT;
4588 }
4589
4590 return ret;
4591}
4592
4593static int tabla_resume(struct device *dev)
4594{
4595 int ret = 0, cnt;
4596 struct platform_device *pdev = to_platform_device(dev);
4597 struct tabla_priv *tabla = platform_get_drvdata(pdev);
4598
4599 cnt = atomic_cmpxchg(&tabla->pm_cnt, 0, 1);
4600 if (cnt == 0) {
4601 dev_dbg(dev, "system resume, pm_cnt %d\n",
4602 atomic_read(&tabla->pm_cnt));
4603 wake_up_all(&tabla->pm_wq);
4604 } else if (cnt > 0)
4605 dev_warn(dev, "system is already awake, pm_cnt %d\n", cnt);
4606 else {
4607 WARN(1, "unexpected pm_cnt %d\n", cnt);
4608 ret = -EFAULT;
4609 }
4610
4611 return ret;
4612}
4613
4614static const struct dev_pm_ops tabla_pm_ops = {
4615 .suspend = tabla_suspend,
4616 .resume = tabla_resume,
4617};
4618#endif
4619
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004620static int __devinit tabla_probe(struct platform_device *pdev)
4621{
Santosh Mardie15e2302011-11-15 10:39:23 +05304622 int ret = 0;
Bradley Rubincb3950a2011-08-18 13:07:26 -07004623#ifdef CONFIG_DEBUG_FS
4624 debugfs_poke = debugfs_create_file("TRRS",
4625 S_IFREG | S_IRUGO, NULL, (void *) "TRRS", &codec_debug_ops);
4626
4627#endif
Santosh Mardie15e2302011-11-15 10:39:23 +05304628 if (tabla_get_intf_type() == TABLA_INTERFACE_TYPE_SLIMBUS)
4629 ret = snd_soc_register_codec(&pdev->dev, &soc_codec_dev_tabla,
4630 tabla_dai, ARRAY_SIZE(tabla_dai));
4631 else if (tabla_get_intf_type() == TABLA_INTERFACE_TYPE_I2C)
4632 ret = snd_soc_register_codec(&pdev->dev, &soc_codec_dev_tabla,
4633 tabla_i2s_dai, ARRAY_SIZE(tabla_i2s_dai));
4634 return ret;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004635}
4636static int __devexit tabla_remove(struct platform_device *pdev)
4637{
4638 snd_soc_unregister_codec(&pdev->dev);
Bradley Rubincb3950a2011-08-18 13:07:26 -07004639
4640#ifdef CONFIG_DEBUG_FS
4641 debugfs_remove(debugfs_poke);
4642#endif
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004643 return 0;
4644}
4645static struct platform_driver tabla_codec_driver = {
4646 .probe = tabla_probe,
4647 .remove = tabla_remove,
4648 .driver = {
4649 .name = "tabla_codec",
4650 .owner = THIS_MODULE,
Joonwoo Park8b1f0982011-12-08 17:12:45 -08004651#ifdef CONFIG_PM
4652 .pm = &tabla_pm_ops,
4653#endif
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004654 },
4655};
4656
4657static int __init tabla_codec_init(void)
4658{
4659 return platform_driver_register(&tabla_codec_driver);
4660}
4661
4662static void __exit tabla_codec_exit(void)
4663{
4664 platform_driver_unregister(&tabla_codec_driver);
4665}
4666
4667module_init(tabla_codec_init);
4668module_exit(tabla_codec_exit);
4669
4670MODULE_DESCRIPTION("Tabla codec driver");
4671MODULE_VERSION("1.0");
4672MODULE_LICENSE("GPL v2");