blob: 472fcae7cf953ebd4f00123d6a9d94b073342bd8 [file] [log] [blame]
Kiran Kandi3426e512011-09-13 22:50:10 -07001/* Copyright (c) 2011-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
Kiran Kandi3426e512011-09-13 22:50:10 -0700822static const struct soc_enum sb_tx9_mux_enum =
823 SOC_ENUM_SINGLE(TABLA_A_CDC_CONN_TX_SB_B9_CTL, 0, 18,
824 sb_tx7_to_tx10_mux_text);
825
826static const struct soc_enum sb_tx10_mux_enum =
827 SOC_ENUM_SINGLE(TABLA_A_CDC_CONN_TX_SB_B10_CTL, 0, 18,
828 sb_tx7_to_tx10_mux_text);
829
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700830static const struct soc_enum sb_tx1_mux_enum =
831 SOC_ENUM_SINGLE(TABLA_A_CDC_CONN_TX_SB_B1_CTL, 0, 9, sb_tx1_mux_text);
832
833static const struct soc_enum dec1_mux_enum =
834 SOC_ENUM_SINGLE(TABLA_A_CDC_CONN_TX_B1_CTL, 0, 3, dec1_mux_text);
835
Bhalchandra Gajare0d77e1b2011-07-08 10:54:14 -0700836static const struct soc_enum dec2_mux_enum =
837 SOC_ENUM_SINGLE(TABLA_A_CDC_CONN_TX_B1_CTL, 2, 3, dec2_mux_text);
838
Bhalchandra Gajarecc6ffa02011-07-14 18:35:41 -0700839static const struct soc_enum dec3_mux_enum =
840 SOC_ENUM_SINGLE(TABLA_A_CDC_CONN_TX_B1_CTL, 4, 3, dec3_mux_text);
841
842static const struct soc_enum dec4_mux_enum =
843 SOC_ENUM_SINGLE(TABLA_A_CDC_CONN_TX_B1_CTL, 6, 3, dec4_mux_text);
844
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700845static const struct soc_enum dec5_mux_enum =
846 SOC_ENUM_SINGLE(TABLA_A_CDC_CONN_TX_B2_CTL, 0, 3, dec5_mux_text);
847
848static const struct soc_enum dec6_mux_enum =
849 SOC_ENUM_SINGLE(TABLA_A_CDC_CONN_TX_B2_CTL, 2, 3, dec6_mux_text);
850
851static const struct soc_enum dec7_mux_enum =
852 SOC_ENUM_SINGLE(TABLA_A_CDC_CONN_TX_B2_CTL, 4, 7, dec7_mux_text);
853
Bhalchandra Gajare0d77e1b2011-07-08 10:54:14 -0700854static const struct soc_enum dec8_mux_enum =
855 SOC_ENUM_SINGLE(TABLA_A_CDC_CONN_TX_B3_CTL, 0, 7, dec8_mux_text);
856
Bhalchandra Gajarecc6ffa02011-07-14 18:35:41 -0700857static const struct soc_enum dec9_mux_enum =
858 SOC_ENUM_SINGLE(TABLA_A_CDC_CONN_TX_B3_CTL, 3, 8, dec9_mux_text);
859
860static const struct soc_enum dec10_mux_enum =
861 SOC_ENUM_SINGLE(TABLA_A_CDC_CONN_TX_B4_CTL, 0, 8, dec10_mux_text);
862
Bradley Rubin229c6a52011-07-12 16:18:48 -0700863static const struct soc_enum anc1_mux_enum =
864 SOC_ENUM_SINGLE(TABLA_A_CDC_CONN_ANC_B1_CTL, 0, 16, anc_mux_text);
865
866static const struct soc_enum anc2_mux_enum =
867 SOC_ENUM_SINGLE(TABLA_A_CDC_CONN_ANC_B1_CTL, 4, 16, anc_mux_text);
868
869static const struct soc_enum anc1_fb_mux_enum =
870 SOC_ENUM_SINGLE(TABLA_A_CDC_CONN_ANC_B2_CTL, 0, 3, anc1_fb_mux_text);
871
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700872static const struct soc_enum iir1_inp1_mux_enum =
873 SOC_ENUM_SINGLE(TABLA_A_CDC_CONN_EQ1_B1_CTL, 0, 18, iir1_inp1_text);
874
875static const struct snd_kcontrol_new rx_mix1_inp1_mux =
876 SOC_DAPM_ENUM("RX1 MIX1 INP1 Mux", rx_mix1_inp1_chain_enum);
877
Bradley Rubin229c6a52011-07-12 16:18:48 -0700878static const struct snd_kcontrol_new rx_mix1_inp2_mux =
879 SOC_DAPM_ENUM("RX1 MIX1 INP2 Mux", rx_mix1_inp2_chain_enum);
880
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700881static const struct snd_kcontrol_new rx2_mix1_inp1_mux =
882 SOC_DAPM_ENUM("RX2 MIX1 INP1 Mux", rx2_mix1_inp1_chain_enum);
883
Bradley Rubin229c6a52011-07-12 16:18:48 -0700884static const struct snd_kcontrol_new rx2_mix1_inp2_mux =
885 SOC_DAPM_ENUM("RX2 MIX1 INP2 Mux", rx2_mix1_inp2_chain_enum);
886
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700887static const struct snd_kcontrol_new rx3_mix1_inp1_mux =
888 SOC_DAPM_ENUM("RX3 MIX1 INP1 Mux", rx3_mix1_inp1_chain_enum);
889
Bradley Rubin74a9b4a2011-06-13 15:03:43 -0700890static const struct snd_kcontrol_new rx3_mix1_inp2_mux =
891 SOC_DAPM_ENUM("RX3 MIX1 INP2 Mux", rx3_mix1_inp2_chain_enum);
892
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700893static const struct snd_kcontrol_new rx4_mix1_inp1_mux =
894 SOC_DAPM_ENUM("RX4 MIX1 INP1 Mux", rx4_mix1_inp1_chain_enum);
895
Bradley Rubin74a9b4a2011-06-13 15:03:43 -0700896static const struct snd_kcontrol_new rx4_mix1_inp2_mux =
897 SOC_DAPM_ENUM("RX4 MIX1 INP2 Mux", rx4_mix1_inp2_chain_enum);
898
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700899static const struct snd_kcontrol_new rx5_mix1_inp1_mux =
900 SOC_DAPM_ENUM("RX5 MIX1 INP1 Mux", rx5_mix1_inp1_chain_enum);
901
Bradley Rubin74a9b4a2011-06-13 15:03:43 -0700902static const struct snd_kcontrol_new rx5_mix1_inp2_mux =
903 SOC_DAPM_ENUM("RX5 MIX1 INP2 Mux", rx5_mix1_inp2_chain_enum);
904
905static const struct snd_kcontrol_new rx6_mix1_inp1_mux =
906 SOC_DAPM_ENUM("RX6 MIX1 INP1 Mux", rx6_mix1_inp1_chain_enum);
907
908static const struct snd_kcontrol_new rx6_mix1_inp2_mux =
909 SOC_DAPM_ENUM("RX6 MIX1 INP2 Mux", rx6_mix1_inp2_chain_enum);
910
Bhalchandra Gajare0a8ad172011-08-12 13:32:22 -0700911static const struct snd_kcontrol_new rx7_mix1_inp1_mux =
912 SOC_DAPM_ENUM("RX7 MIX1 INP1 Mux", rx7_mix1_inp1_chain_enum);
913
914static const struct snd_kcontrol_new rx7_mix1_inp2_mux =
915 SOC_DAPM_ENUM("RX7 MIX1 INP2 Mux", rx7_mix1_inp2_chain_enum);
916
Kiran Kandi8b3a8302011-09-27 16:13:28 -0700917static const struct snd_kcontrol_new rx4_dsm_mux =
918 SOC_DAPM_ENUM("RX4 DSM MUX Mux", rx4_dsm_enum);
919
920static const struct snd_kcontrol_new rx6_dsm_mux =
921 SOC_DAPM_ENUM("RX6 DSM MUX Mux", rx6_dsm_enum);
922
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700923static const struct snd_kcontrol_new sb_tx5_mux =
924 SOC_DAPM_ENUM("SLIM TX5 MUX Mux", sb_tx5_mux_enum);
925
926static const struct snd_kcontrol_new sb_tx6_mux =
927 SOC_DAPM_ENUM("SLIM TX6 MUX Mux", sb_tx6_mux_enum);
928
929static const struct snd_kcontrol_new sb_tx7_mux =
930 SOC_DAPM_ENUM("SLIM TX7 MUX Mux", sb_tx7_mux_enum);
931
932static const struct snd_kcontrol_new sb_tx8_mux =
933 SOC_DAPM_ENUM("SLIM TX8 MUX Mux", sb_tx8_mux_enum);
934
Kiran Kandi3426e512011-09-13 22:50:10 -0700935static const struct snd_kcontrol_new sb_tx9_mux =
936 SOC_DAPM_ENUM("SLIM TX9 MUX Mux", sb_tx9_mux_enum);
937
938static const struct snd_kcontrol_new sb_tx10_mux =
939 SOC_DAPM_ENUM("SLIM TX10 MUX Mux", sb_tx10_mux_enum);
940
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700941static const struct snd_kcontrol_new sb_tx1_mux =
942 SOC_DAPM_ENUM("SLIM TX1 MUX Mux", sb_tx1_mux_enum);
943
944static const struct snd_kcontrol_new dec1_mux =
945 SOC_DAPM_ENUM("DEC1 MUX Mux", dec1_mux_enum);
946
Bhalchandra Gajare0d77e1b2011-07-08 10:54:14 -0700947static const struct snd_kcontrol_new dec2_mux =
948 SOC_DAPM_ENUM("DEC2 MUX Mux", dec2_mux_enum);
949
Bhalchandra Gajarecc6ffa02011-07-14 18:35:41 -0700950static const struct snd_kcontrol_new dec3_mux =
951 SOC_DAPM_ENUM("DEC3 MUX Mux", dec3_mux_enum);
952
953static const struct snd_kcontrol_new dec4_mux =
954 SOC_DAPM_ENUM("DEC4 MUX Mux", dec4_mux_enum);
955
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700956static const struct snd_kcontrol_new dec5_mux =
957 SOC_DAPM_ENUM("DEC5 MUX Mux", dec5_mux_enum);
958
959static const struct snd_kcontrol_new dec6_mux =
960 SOC_DAPM_ENUM("DEC6 MUX Mux", dec6_mux_enum);
961
962static const struct snd_kcontrol_new dec7_mux =
963 SOC_DAPM_ENUM("DEC7 MUX Mux", dec7_mux_enum);
964
Bradley Rubin229c6a52011-07-12 16:18:48 -0700965static const struct snd_kcontrol_new anc1_mux =
966 SOC_DAPM_ENUM("ANC1 MUX Mux", anc1_mux_enum);
Bhalchandra Gajare0d77e1b2011-07-08 10:54:14 -0700967static const struct snd_kcontrol_new dec8_mux =
968 SOC_DAPM_ENUM("DEC8 MUX Mux", dec8_mux_enum);
969
Bhalchandra Gajarecc6ffa02011-07-14 18:35:41 -0700970static const struct snd_kcontrol_new dec9_mux =
971 SOC_DAPM_ENUM("DEC9 MUX Mux", dec9_mux_enum);
972
973static const struct snd_kcontrol_new dec10_mux =
974 SOC_DAPM_ENUM("DEC10 MUX Mux", dec10_mux_enum);
975
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700976static const struct snd_kcontrol_new iir1_inp1_mux =
977 SOC_DAPM_ENUM("IIR1 INP1 Mux", iir1_inp1_mux_enum);
978
Bradley Rubin229c6a52011-07-12 16:18:48 -0700979static const struct snd_kcontrol_new anc2_mux =
980 SOC_DAPM_ENUM("ANC2 MUX Mux", anc2_mux_enum);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700981
Bradley Rubin229c6a52011-07-12 16:18:48 -0700982static const struct snd_kcontrol_new anc1_fb_mux =
983 SOC_DAPM_ENUM("ANC1 FB MUX Mux", anc1_fb_mux_enum);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700984
Bradley Rubin229c6a52011-07-12 16:18:48 -0700985static const struct snd_kcontrol_new dac1_switch[] = {
986 SOC_DAPM_SINGLE("Switch", TABLA_A_RX_EAR_EN, 5, 1, 0)
987};
988static const struct snd_kcontrol_new hphl_switch[] = {
989 SOC_DAPM_SINGLE("Switch", TABLA_A_RX_HPH_L_DAC_CTL, 6, 1, 0)
990};
Kiran Kandi8b3a8302011-09-27 16:13:28 -0700991
992static const struct snd_kcontrol_new lineout3_ground_switch =
993 SOC_DAPM_SINGLE("Switch", TABLA_A_RX_LINE_3_DAC_CTL, 6, 1, 0);
994
995static const struct snd_kcontrol_new lineout4_ground_switch =
996 SOC_DAPM_SINGLE("Switch", TABLA_A_RX_LINE_4_DAC_CTL, 6, 1, 0);
Bradley Rubin74a9b4a2011-06-13 15:03:43 -0700997
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700998static void tabla_codec_enable_adc_block(struct snd_soc_codec *codec,
999 int enable)
1000{
1001 struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
1002
1003 pr_debug("%s %d\n", __func__, enable);
1004
1005 if (enable) {
1006 tabla->adc_count++;
1007 snd_soc_update_bits(codec, TABLA_A_TX_COM_BIAS, 0xE0, 0xE0);
1008 snd_soc_update_bits(codec, TABLA_A_CDC_CLK_OTHR_CTL, 0x2, 0x2);
1009 } else {
1010 tabla->adc_count--;
1011 if (!tabla->adc_count) {
1012 snd_soc_update_bits(codec, TABLA_A_CDC_CLK_OTHR_CTL,
1013 0x2, 0x0);
1014 if (!tabla->mbhc_polling_active)
1015 snd_soc_update_bits(codec, TABLA_A_TX_COM_BIAS,
1016 0xE0, 0x0);
1017 }
1018 }
1019}
1020
1021static int tabla_codec_enable_adc(struct snd_soc_dapm_widget *w,
1022 struct snd_kcontrol *kcontrol, int event)
1023{
1024 struct snd_soc_codec *codec = w->codec;
1025 u16 adc_reg;
Kiran Kandi9a2c62a82011-12-07 13:13:26 -08001026 u8 init_bit_shift;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001027
1028 pr_debug("%s %d\n", __func__, event);
1029
1030 if (w->reg == TABLA_A_TX_1_2_EN)
1031 adc_reg = TABLA_A_TX_1_2_TEST_CTL;
1032 else if (w->reg == TABLA_A_TX_3_4_EN)
1033 adc_reg = TABLA_A_TX_3_4_TEST_CTL;
1034 else if (w->reg == TABLA_A_TX_5_6_EN)
1035 adc_reg = TABLA_A_TX_5_6_TEST_CTL;
1036 else {
1037 pr_err("%s: Error, invalid adc register\n", __func__);
1038 return -EINVAL;
1039 }
1040
Kiran Kandi9a2c62a82011-12-07 13:13:26 -08001041 if (w->shift == 3)
1042 init_bit_shift = 6;
1043 else if (w->shift == 7)
1044 init_bit_shift = 7;
1045 else {
1046 pr_err("%s: Error, invalid init bit postion adc register\n",
1047 __func__);
1048 return -EINVAL;
1049 }
1050
1051
1052
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001053 switch (event) {
1054 case SND_SOC_DAPM_PRE_PMU:
1055 tabla_codec_enable_adc_block(codec, 1);
Kiran Kandi9a2c62a82011-12-07 13:13:26 -08001056 snd_soc_update_bits(codec, adc_reg, 1 << init_bit_shift,
1057 1 << init_bit_shift);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001058 break;
1059 case SND_SOC_DAPM_POST_PMU:
Kiran Kandi9a2c62a82011-12-07 13:13:26 -08001060
1061 snd_soc_update_bits(codec, adc_reg, 1 << init_bit_shift, 0x00);
1062
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001063 break;
1064 case SND_SOC_DAPM_POST_PMD:
1065 tabla_codec_enable_adc_block(codec, 0);
1066 break;
1067 }
1068 return 0;
1069}
1070
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001071static int tabla_codec_enable_lineout(struct snd_soc_dapm_widget *w,
1072 struct snd_kcontrol *kcontrol, int event)
1073{
1074 struct snd_soc_codec *codec = w->codec;
1075 u16 lineout_gain_reg;
1076
Kiran Kandidb0a4b02011-08-23 09:32:09 -07001077 pr_debug("%s %d %s\n", __func__, event, w->name);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001078
1079 switch (w->shift) {
1080 case 0:
1081 lineout_gain_reg = TABLA_A_RX_LINE_1_GAIN;
1082 break;
1083 case 1:
1084 lineout_gain_reg = TABLA_A_RX_LINE_2_GAIN;
1085 break;
1086 case 2:
1087 lineout_gain_reg = TABLA_A_RX_LINE_3_GAIN;
1088 break;
1089 case 3:
1090 lineout_gain_reg = TABLA_A_RX_LINE_4_GAIN;
1091 break;
1092 case 4:
1093 lineout_gain_reg = TABLA_A_RX_LINE_5_GAIN;
1094 break;
1095 default:
1096 pr_err("%s: Error, incorrect lineout register value\n",
1097 __func__);
1098 return -EINVAL;
1099 }
1100
1101 switch (event) {
1102 case SND_SOC_DAPM_PRE_PMU:
1103 snd_soc_update_bits(codec, lineout_gain_reg, 0x40, 0x40);
1104 break;
1105 case SND_SOC_DAPM_POST_PMU:
Krishnankutty Kolathappilly31169f42011-11-17 10:33:11 -08001106 pr_debug("%s: sleeping 16 ms after %s PA turn on\n",
Kiran Kandidb0a4b02011-08-23 09:32:09 -07001107 __func__, w->name);
Krishnankutty Kolathappilly31169f42011-11-17 10:33:11 -08001108 usleep_range(16000, 16000);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001109 break;
1110 case SND_SOC_DAPM_POST_PMD:
1111 snd_soc_update_bits(codec, lineout_gain_reg, 0x40, 0x00);
1112 break;
1113 }
1114 return 0;
1115}
1116
Kiran Kandicf45f6a2011-07-17 21:10:19 -07001117
1118static int tabla_codec_enable_dmic(struct snd_soc_dapm_widget *w,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001119 struct snd_kcontrol *kcontrol, int event)
1120{
1121 struct snd_soc_codec *codec = w->codec;
Kiran Kandicf45f6a2011-07-17 21:10:19 -07001122 u16 tx_mux_ctl_reg, tx_dmic_ctl_reg;
1123 u8 dmic_clk_sel, dmic_clk_en;
Bhalchandra Gajare7cf018e2011-08-11 18:58:32 -07001124 unsigned int dmic;
1125 int ret;
Kiran Kandicf45f6a2011-07-17 21:10:19 -07001126
Bhalchandra Gajare7cf018e2011-08-11 18:58:32 -07001127 ret = kstrtouint(strpbrk(w->name, "123456"), 10, &dmic);
1128 if (ret < 0) {
1129 pr_err("%s: Invalid DMIC line on the codec\n", __func__);
Kiran Kandicf45f6a2011-07-17 21:10:19 -07001130 return -EINVAL;
1131 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001132
Bhalchandra Gajare7cf018e2011-08-11 18:58:32 -07001133 switch (dmic) {
1134 case 1:
1135 case 2:
1136 dmic_clk_sel = 0x02;
1137 dmic_clk_en = 0x01;
1138 break;
1139
1140 case 3:
1141 case 4:
1142 dmic_clk_sel = 0x08;
1143 dmic_clk_en = 0x04;
1144 break;
1145
1146 case 5:
1147 case 6:
1148 dmic_clk_sel = 0x20;
1149 dmic_clk_en = 0x10;
1150 break;
1151
1152 default:
1153 pr_err("%s: Invalid DMIC Selection\n", __func__);
1154 return -EINVAL;
1155 }
1156
1157 tx_mux_ctl_reg = TABLA_A_CDC_TX1_MUX_CTL + 8 * (dmic - 1);
1158 tx_dmic_ctl_reg = TABLA_A_CDC_TX1_DMIC_CTL + 8 * (dmic - 1);
1159
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001160 pr_debug("%s %d\n", __func__, event);
Kiran Kandicf45f6a2011-07-17 21:10:19 -07001161
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001162 switch (event) {
1163 case SND_SOC_DAPM_PRE_PMU:
Kiran Kandicf45f6a2011-07-17 21:10:19 -07001164 snd_soc_update_bits(codec, tx_mux_ctl_reg, 0x1, 0x1);
1165
1166 snd_soc_update_bits(codec, TABLA_A_CDC_CLK_DMIC_CTL,
1167 dmic_clk_sel, dmic_clk_sel);
1168
1169 snd_soc_update_bits(codec, tx_dmic_ctl_reg, 0x1, 0x1);
1170
1171 snd_soc_update_bits(codec, TABLA_A_CDC_CLK_DMIC_CTL,
1172 dmic_clk_en, dmic_clk_en);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001173 break;
1174 case SND_SOC_DAPM_POST_PMD:
Kiran Kandicf45f6a2011-07-17 21:10:19 -07001175 snd_soc_update_bits(codec, TABLA_A_CDC_CLK_DMIC_CTL,
1176 dmic_clk_en, 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001177 break;
1178 }
1179 return 0;
1180}
1181
Bradley Rubin229c6a52011-07-12 16:18:48 -07001182static int tabla_codec_enable_anc(struct snd_soc_dapm_widget *w,
1183 struct snd_kcontrol *kcontrol, int event)
1184{
1185 struct snd_soc_codec *codec = w->codec;
1186 const char *filename;
1187 const struct firmware *fw;
1188 int i;
1189 int ret;
Bradley Rubina7096d02011-08-03 18:29:02 -07001190 int num_anc_slots;
1191 struct anc_header *anc_head;
Bradley Rubin229c6a52011-07-12 16:18:48 -07001192 struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
Bradley Rubina7096d02011-08-03 18:29:02 -07001193 u32 anc_writes_size = 0;
1194 int anc_size_remaining;
1195 u32 *anc_ptr;
Bradley Rubin229c6a52011-07-12 16:18:48 -07001196 u16 reg;
1197 u8 mask, val, old_val;
1198
1199 pr_debug("%s %d\n", __func__, event);
1200 switch (event) {
1201 case SND_SOC_DAPM_PRE_PMU:
1202
Bradley Rubin4283a4c2011-07-29 16:18:54 -07001203 filename = "wcd9310/wcd9310_anc.bin";
Bradley Rubin229c6a52011-07-12 16:18:48 -07001204
1205 ret = request_firmware(&fw, filename, codec->dev);
1206 if (ret != 0) {
1207 dev_err(codec->dev, "Failed to acquire ANC data: %d\n",
1208 ret);
1209 return -ENODEV;
1210 }
1211
Bradley Rubina7096d02011-08-03 18:29:02 -07001212 if (fw->size < sizeof(struct anc_header)) {
Bradley Rubin229c6a52011-07-12 16:18:48 -07001213 dev_err(codec->dev, "Not enough data\n");
1214 release_firmware(fw);
1215 return -ENOMEM;
1216 }
1217
1218 /* First number is the number of register writes */
Bradley Rubina7096d02011-08-03 18:29:02 -07001219 anc_head = (struct anc_header *)(fw->data);
1220 anc_ptr = (u32 *)((u32)fw->data + sizeof(struct anc_header));
1221 anc_size_remaining = fw->size - sizeof(struct anc_header);
1222 num_anc_slots = anc_head->num_anc_slots;
Bradley Rubin229c6a52011-07-12 16:18:48 -07001223
Bradley Rubina7096d02011-08-03 18:29:02 -07001224 if (tabla->anc_slot >= num_anc_slots) {
1225 dev_err(codec->dev, "Invalid ANC slot selected\n");
1226 release_firmware(fw);
1227 return -EINVAL;
1228 }
1229
1230 for (i = 0; i < num_anc_slots; i++) {
1231
1232 if (anc_size_remaining < TABLA_PACKED_REG_SIZE) {
1233 dev_err(codec->dev, "Invalid register format\n");
1234 release_firmware(fw);
1235 return -EINVAL;
1236 }
1237 anc_writes_size = (u32)(*anc_ptr);
1238 anc_size_remaining -= sizeof(u32);
1239 anc_ptr += 1;
1240
1241 if (anc_writes_size * TABLA_PACKED_REG_SIZE
1242 > anc_size_remaining) {
1243 dev_err(codec->dev, "Invalid register format\n");
1244 release_firmware(fw);
1245 return -ENOMEM;
1246 }
1247
1248 if (tabla->anc_slot == i)
1249 break;
1250
1251 anc_size_remaining -= (anc_writes_size *
1252 TABLA_PACKED_REG_SIZE);
Bradley Rubin939ff3f2011-08-26 17:19:34 -07001253 anc_ptr += anc_writes_size;
Bradley Rubina7096d02011-08-03 18:29:02 -07001254 }
1255 if (i == num_anc_slots) {
1256 dev_err(codec->dev, "Selected ANC slot not present\n");
Bradley Rubin229c6a52011-07-12 16:18:48 -07001257 release_firmware(fw);
1258 return -ENOMEM;
1259 }
1260
Bradley Rubina7096d02011-08-03 18:29:02 -07001261 for (i = 0; i < anc_writes_size; i++) {
1262 TABLA_CODEC_UNPACK_ENTRY(anc_ptr[i], reg,
Bradley Rubin229c6a52011-07-12 16:18:48 -07001263 mask, val);
1264 old_val = snd_soc_read(codec, reg);
Bradley Rubin4283a4c2011-07-29 16:18:54 -07001265 snd_soc_write(codec, reg, (old_val & ~mask) |
1266 (val & mask));
Bradley Rubin229c6a52011-07-12 16:18:48 -07001267 }
1268 release_firmware(fw);
Bradley Rubin229c6a52011-07-12 16:18:48 -07001269
1270 break;
1271 case SND_SOC_DAPM_POST_PMD:
1272 snd_soc_write(codec, TABLA_A_CDC_CLK_ANC_RESET_CTL, 0xFF);
1273 snd_soc_write(codec, TABLA_A_CDC_CLK_ANC_CLK_EN_CTL, 0);
1274 break;
1275 }
1276 return 0;
1277}
1278
1279
Bradley Rubincb3950a2011-08-18 13:07:26 -07001280static void tabla_codec_disable_button_presses(struct snd_soc_codec *codec)
1281{
1282 snd_soc_write(codec, TABLA_A_CDC_MBHC_VOLT_B4_CTL, 0x80);
1283 snd_soc_write(codec, TABLA_A_CDC_MBHC_VOLT_B3_CTL, 0x00);
1284}
1285
Bradley Rubin4d09cf42011-08-17 17:59:16 -07001286static void tabla_codec_start_hs_polling(struct snd_soc_codec *codec)
1287{
Bradley Rubincb3950a2011-08-18 13:07:26 -07001288 struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
1289
Bradley Rubin4d09cf42011-08-17 17:59:16 -07001290 snd_soc_write(codec, TABLA_A_MBHC_SCALING_MUX_1, 0x84);
Bradley Rubin4d09cf42011-08-17 17:59:16 -07001291 tabla_enable_irq(codec->control_data, TABLA_IRQ_MBHC_REMOVAL);
Bradley Rubincb3950a2011-08-18 13:07:26 -07001292 if (!tabla->no_mic_headset_override) {
1293 tabla_enable_irq(codec->control_data, TABLA_IRQ_MBHC_POTENTIAL);
1294 tabla_enable_irq(codec->control_data, TABLA_IRQ_MBHC_RELEASE);
1295 } else {
1296 tabla_codec_disable_button_presses(codec);
1297 }
Bradley Rubin4d09cf42011-08-17 17:59:16 -07001298 snd_soc_write(codec, TABLA_A_CDC_MBHC_EN_CTL, 0x1);
1299 snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_CLK_CTL, 0x8, 0x0);
1300 snd_soc_write(codec, TABLA_A_CDC_MBHC_EN_CTL, 0x1);
1301}
1302
1303static void tabla_codec_pause_hs_polling(struct snd_soc_codec *codec)
1304{
Bradley Rubincb3950a2011-08-18 13:07:26 -07001305 struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
1306
Bradley Rubin4d09cf42011-08-17 17:59:16 -07001307 snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_CLK_CTL, 0x8, 0x8);
1308 tabla_disable_irq(codec->control_data, TABLA_IRQ_MBHC_REMOVAL);
Bradley Rubincb3950a2011-08-18 13:07:26 -07001309 if (!tabla->no_mic_headset_override) {
1310 tabla_disable_irq(codec->control_data,
1311 TABLA_IRQ_MBHC_POTENTIAL);
1312 tabla_disable_irq(codec->control_data, TABLA_IRQ_MBHC_RELEASE);
1313 }
Bradley Rubin4d09cf42011-08-17 17:59:16 -07001314}
1315
Bhalchandra Gajare19d9c132011-11-18 14:57:08 -08001316static void tabla_codec_switch_cfilt_mode(struct snd_soc_codec *codec,
1317 int mode)
1318{
1319 struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
1320 u8 reg_mode_val, cur_mode_val;
1321 bool mbhc_was_polling = false;
1322
1323 if (mode)
1324 reg_mode_val = TABLA_CFILT_FAST_MODE;
1325 else
1326 reg_mode_val = TABLA_CFILT_SLOW_MODE;
1327
1328 cur_mode_val = snd_soc_read(codec,
1329 tabla->mbhc_bias_regs.cfilt_ctl) & 0x40;
1330
1331 if (cur_mode_val != reg_mode_val) {
1332 if (tabla->mbhc_polling_active) {
1333 tabla_codec_pause_hs_polling(codec);
1334 mbhc_was_polling = true;
1335 }
1336 snd_soc_update_bits(codec,
1337 tabla->mbhc_bias_regs.cfilt_ctl, 0x40, reg_mode_val);
1338 if (mbhc_was_polling)
1339 tabla_codec_start_hs_polling(codec);
1340 pr_debug("%s: CFILT mode change (%x to %x)\n", __func__,
1341 cur_mode_val, reg_mode_val);
1342 } else {
1343 pr_debug("%s: CFILT Value is already %x\n",
1344 __func__, cur_mode_val);
1345 }
1346}
1347
1348static void tabla_codec_update_cfilt_usage(struct snd_soc_codec *codec,
1349 u8 cfilt_sel, int inc)
1350{
1351 struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
1352 u32 *cfilt_cnt_ptr = NULL;
1353 u16 micb_cfilt_reg;
1354
1355 switch (cfilt_sel) {
1356 case TABLA_CFILT1_SEL:
1357 cfilt_cnt_ptr = &tabla->cfilt1_cnt;
1358 micb_cfilt_reg = TABLA_A_MICB_CFILT_1_CTL;
1359 break;
1360 case TABLA_CFILT2_SEL:
1361 cfilt_cnt_ptr = &tabla->cfilt2_cnt;
1362 micb_cfilt_reg = TABLA_A_MICB_CFILT_2_CTL;
1363 break;
1364 case TABLA_CFILT3_SEL:
1365 cfilt_cnt_ptr = &tabla->cfilt3_cnt;
1366 micb_cfilt_reg = TABLA_A_MICB_CFILT_3_CTL;
1367 break;
1368 default:
1369 return; /* should not happen */
1370 }
1371
1372 if (inc) {
1373 if (!(*cfilt_cnt_ptr)++) {
1374 /* Switch CFILT to slow mode if MBHC CFILT being used */
1375 if (cfilt_sel == tabla->mbhc_bias_regs.cfilt_sel)
1376 tabla_codec_switch_cfilt_mode(codec, 0);
1377
1378 snd_soc_update_bits(codec, micb_cfilt_reg, 0x80, 0x80);
1379 }
1380 } else {
1381 /* check if count not zero, decrement
1382 * then check if zero, go ahead disable cfilter
1383 */
1384 if ((*cfilt_cnt_ptr) && !--(*cfilt_cnt_ptr)) {
1385 snd_soc_update_bits(codec, micb_cfilt_reg, 0x80, 0);
1386
1387 /* Switch CFILT to fast mode if MBHC CFILT being used */
1388 if (cfilt_sel == tabla->mbhc_bias_regs.cfilt_sel)
1389 tabla_codec_switch_cfilt_mode(codec, 1);
1390 }
1391 }
1392}
1393
Bhalchandra Gajared9ebb6c2011-10-03 19:54:41 -07001394static int tabla_find_k_value(unsigned int ldoh_v, unsigned int cfilt_mv)
1395{
1396 int rc = -EINVAL;
1397 unsigned min_mv, max_mv;
1398
1399 switch (ldoh_v) {
1400 case TABLA_LDOH_1P95_V:
1401 min_mv = 160;
1402 max_mv = 1800;
1403 break;
1404 case TABLA_LDOH_2P35_V:
1405 min_mv = 200;
1406 max_mv = 2200;
1407 break;
1408 case TABLA_LDOH_2P75_V:
1409 min_mv = 240;
1410 max_mv = 2600;
1411 break;
1412 case TABLA_LDOH_2P85_V:
1413 min_mv = 250;
1414 max_mv = 2700;
1415 break;
1416 default:
1417 goto done;
1418 }
1419
1420 if (cfilt_mv < min_mv || cfilt_mv > max_mv)
1421 goto done;
1422
1423 for (rc = 4; rc <= 44; rc++) {
1424 min_mv = max_mv * (rc) / 44;
1425 if (min_mv >= cfilt_mv) {
1426 rc -= 4;
1427 break;
1428 }
1429 }
1430done:
1431 return rc;
1432}
1433
1434static bool tabla_is_hph_pa_on(struct snd_soc_codec *codec)
1435{
1436 u8 hph_reg_val = 0;
1437 hph_reg_val = snd_soc_read(codec, TABLA_A_RX_HPH_CNP_EN);
1438
1439 return (hph_reg_val & 0x30) ? true : false;
1440}
1441
Joonwoo Parka9444452011-12-08 18:48:27 -08001442static bool tabla_is_hph_dac_on(struct snd_soc_codec *codec, int left)
1443{
1444 u8 hph_reg_val = 0;
1445 if (left)
1446 hph_reg_val = snd_soc_read(codec,
1447 TABLA_A_RX_HPH_L_DAC_CTL);
1448 else
1449 hph_reg_val = snd_soc_read(codec,
1450 TABLA_A_RX_HPH_R_DAC_CTL);
1451
1452 return (hph_reg_val & 0xC0) ? true : false;
1453}
1454
Bhalchandra Gajared9ebb6c2011-10-03 19:54:41 -07001455static void tabla_codec_switch_micbias(struct snd_soc_codec *codec,
1456 int vddio_switch)
1457{
1458 struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
1459 int cfilt_k_val;
Bhalchandra Gajarec1e19c42011-11-18 11:22:56 -08001460 bool mbhc_was_polling = false;
Bhalchandra Gajared9ebb6c2011-10-03 19:54:41 -07001461
1462 switch (vddio_switch) {
1463 case 1:
1464 if (tabla->mbhc_polling_active) {
Bhalchandra Gajarec1e19c42011-11-18 11:22:56 -08001465
1466 tabla_codec_pause_hs_polling(codec);
Joonwoo Park0976d012011-12-22 11:48:18 -08001467 /* VDDIO switch enabled */
Bhalchandra Gajared9ebb6c2011-10-03 19:54:41 -07001468 tabla->cfilt_k_value = snd_soc_read(codec,
1469 tabla->mbhc_bias_regs.cfilt_val);
1470 cfilt_k_val = tabla_find_k_value(
1471 tabla->pdata->micbias.ldoh_v, 1800);
1472 snd_soc_update_bits(codec,
1473 tabla->mbhc_bias_regs.cfilt_val,
1474 0xFC, (cfilt_k_val << 2));
1475
1476 snd_soc_update_bits(codec,
1477 tabla->mbhc_bias_regs.mbhc_reg, 0x80, 0x80);
1478 snd_soc_update_bits(codec,
1479 tabla->mbhc_bias_regs.mbhc_reg, 0x10, 0x00);
Bhalchandra Gajarec1e19c42011-11-18 11:22:56 -08001480 tabla_codec_start_hs_polling(codec);
Bhalchandra Gajared9ebb6c2011-10-03 19:54:41 -07001481
1482 tabla->mbhc_micbias_switched = true;
Joonwoo Park0976d012011-12-22 11:48:18 -08001483 pr_debug("%s: VDDIO switch enabled\n", __func__);
Bhalchandra Gajared9ebb6c2011-10-03 19:54:41 -07001484 }
1485 break;
1486
1487 case 0:
1488 if (tabla->mbhc_micbias_switched) {
Bhalchandra Gajarec1e19c42011-11-18 11:22:56 -08001489 if (tabla->mbhc_polling_active) {
1490 tabla_codec_pause_hs_polling(codec);
1491 mbhc_was_polling = true;
1492 }
Joonwoo Park0976d012011-12-22 11:48:18 -08001493 /* VDDIO switch disabled */
Bhalchandra Gajared9ebb6c2011-10-03 19:54:41 -07001494 if (tabla->cfilt_k_value != 0)
1495 snd_soc_update_bits(codec,
1496 tabla->mbhc_bias_regs.cfilt_val, 0XFC,
1497 tabla->cfilt_k_value);
1498 snd_soc_update_bits(codec,
1499 tabla->mbhc_bias_regs.mbhc_reg, 0x80, 0x00);
1500 snd_soc_update_bits(codec,
1501 tabla->mbhc_bias_regs.mbhc_reg, 0x10, 0x00);
1502
Bhalchandra Gajarec1e19c42011-11-18 11:22:56 -08001503 if (mbhc_was_polling)
1504 tabla_codec_start_hs_polling(codec);
1505
Bhalchandra Gajared9ebb6c2011-10-03 19:54:41 -07001506 tabla->mbhc_micbias_switched = false;
Joonwoo Park0976d012011-12-22 11:48:18 -08001507 pr_debug("%s: VDDIO switch disabled\n", __func__);
Bhalchandra Gajared9ebb6c2011-10-03 19:54:41 -07001508 }
1509 break;
1510 }
1511}
1512
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001513static int tabla_codec_enable_micbias(struct snd_soc_dapm_widget *w,
1514 struct snd_kcontrol *kcontrol, int event)
1515{
1516 struct snd_soc_codec *codec = w->codec;
Patrick Lai3043fba2011-08-01 14:15:57 -07001517 struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
1518 u16 micb_int_reg;
Bradley Rubin4d09cf42011-08-17 17:59:16 -07001519 int micb_line;
Bhalchandra Gajarecc6ffa02011-07-14 18:35:41 -07001520 u8 cfilt_sel_val = 0;
Bradley Rubin229c6a52011-07-12 16:18:48 -07001521 char *internal1_text = "Internal1";
1522 char *internal2_text = "Internal2";
1523 char *internal3_text = "Internal3";
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001524
1525 pr_debug("%s %d\n", __func__, event);
1526 switch (w->reg) {
1527 case TABLA_A_MICB_1_CTL:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001528 micb_int_reg = TABLA_A_MICB_1_INT_RBIAS;
Patrick Lai3043fba2011-08-01 14:15:57 -07001529 cfilt_sel_val = tabla->pdata->micbias.bias1_cfilt_sel;
Bradley Rubin4d09cf42011-08-17 17:59:16 -07001530 micb_line = TABLA_MICBIAS1;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001531 break;
1532 case TABLA_A_MICB_2_CTL:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001533 micb_int_reg = TABLA_A_MICB_2_INT_RBIAS;
Patrick Lai3043fba2011-08-01 14:15:57 -07001534 cfilt_sel_val = tabla->pdata->micbias.bias2_cfilt_sel;
Bradley Rubin4d09cf42011-08-17 17:59:16 -07001535 micb_line = TABLA_MICBIAS2;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001536 break;
1537 case TABLA_A_MICB_3_CTL:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001538 micb_int_reg = TABLA_A_MICB_3_INT_RBIAS;
Patrick Lai3043fba2011-08-01 14:15:57 -07001539 cfilt_sel_val = tabla->pdata->micbias.bias3_cfilt_sel;
Bradley Rubin4d09cf42011-08-17 17:59:16 -07001540 micb_line = TABLA_MICBIAS3;
Bhalchandra Gajarecc6ffa02011-07-14 18:35:41 -07001541 break;
1542 case TABLA_A_MICB_4_CTL:
Bhalchandra Gajarecc6ffa02011-07-14 18:35:41 -07001543 micb_int_reg = TABLA_A_MICB_4_INT_RBIAS;
Patrick Lai3043fba2011-08-01 14:15:57 -07001544 cfilt_sel_val = tabla->pdata->micbias.bias4_cfilt_sel;
Bradley Rubin4d09cf42011-08-17 17:59:16 -07001545 micb_line = TABLA_MICBIAS4;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001546 break;
1547 default:
1548 pr_err("%s: Error, invalid micbias register\n", __func__);
1549 return -EINVAL;
1550 }
1551
1552 switch (event) {
1553 case SND_SOC_DAPM_PRE_PMU:
Bhalchandra Gajared9ebb6c2011-10-03 19:54:41 -07001554 /* Decide whether to switch the micbias for MBHC */
1555 if ((w->reg == tabla->mbhc_bias_regs.ctl_reg)
1556 && tabla->mbhc_micbias_switched)
1557 tabla_codec_switch_micbias(codec, 0);
1558
Bhalchandra Gajarecc6ffa02011-07-14 18:35:41 -07001559 snd_soc_update_bits(codec, w->reg, 0x0E, 0x0A);
Patrick Lai3043fba2011-08-01 14:15:57 -07001560 tabla_codec_update_cfilt_usage(codec, cfilt_sel_val, 1);
Bradley Rubin229c6a52011-07-12 16:18:48 -07001561
1562 if (strnstr(w->name, internal1_text, 30))
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001563 snd_soc_update_bits(codec, micb_int_reg, 0xE0, 0xE0);
Bradley Rubin229c6a52011-07-12 16:18:48 -07001564 else if (strnstr(w->name, internal2_text, 30))
1565 snd_soc_update_bits(codec, micb_int_reg, 0x1C, 0x1C);
1566 else if (strnstr(w->name, internal3_text, 30))
1567 snd_soc_update_bits(codec, micb_int_reg, 0x3, 0x3);
1568
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001569 break;
Bradley Rubin4d09cf42011-08-17 17:59:16 -07001570 case SND_SOC_DAPM_POST_PMU:
1571 if (tabla->mbhc_polling_active &&
Joonwoo Park0976d012011-12-22 11:48:18 -08001572 tabla->micbias == micb_line) {
Bradley Rubin4d09cf42011-08-17 17:59:16 -07001573 tabla_codec_pause_hs_polling(codec);
1574 tabla_codec_start_hs_polling(codec);
1575 }
1576 break;
Bhalchandra Gajared9ebb6c2011-10-03 19:54:41 -07001577
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001578 case SND_SOC_DAPM_POST_PMD:
Bhalchandra Gajared9ebb6c2011-10-03 19:54:41 -07001579
1580 if ((w->reg == tabla->mbhc_bias_regs.ctl_reg)
1581 && tabla_is_hph_pa_on(codec))
1582 tabla_codec_switch_micbias(codec, 1);
1583
Bradley Rubin229c6a52011-07-12 16:18:48 -07001584 if (strnstr(w->name, internal1_text, 30))
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001585 snd_soc_update_bits(codec, micb_int_reg, 0x80, 0x00);
Bradley Rubin229c6a52011-07-12 16:18:48 -07001586 else if (strnstr(w->name, internal2_text, 30))
1587 snd_soc_update_bits(codec, micb_int_reg, 0x10, 0x00);
1588 else if (strnstr(w->name, internal3_text, 30))
1589 snd_soc_update_bits(codec, micb_int_reg, 0x2, 0x0);
1590
Patrick Lai3043fba2011-08-01 14:15:57 -07001591 tabla_codec_update_cfilt_usage(codec, cfilt_sel_val, 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001592 break;
1593 }
1594
1595 return 0;
1596}
1597
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001598static int tabla_codec_enable_dec(struct snd_soc_dapm_widget *w,
1599 struct snd_kcontrol *kcontrol, int event)
1600{
1601 struct snd_soc_codec *codec = w->codec;
1602 u16 dec_reset_reg;
1603
1604 pr_debug("%s %d\n", __func__, event);
1605
1606 if (w->reg == TABLA_A_CDC_CLK_TX_CLK_EN_B1_CTL)
1607 dec_reset_reg = TABLA_A_CDC_CLK_TX_RESET_B1_CTL;
1608 else if (w->reg == TABLA_A_CDC_CLK_TX_CLK_EN_B2_CTL)
1609 dec_reset_reg = TABLA_A_CDC_CLK_TX_RESET_B2_CTL;
1610 else {
1611 pr_err("%s: Error, incorrect dec\n", __func__);
1612 return -EINVAL;
1613 }
1614
1615 switch (event) {
1616 case SND_SOC_DAPM_PRE_PMU:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001617 snd_soc_update_bits(codec, dec_reset_reg, 1 << w->shift,
1618 1 << w->shift);
1619 snd_soc_update_bits(codec, dec_reset_reg, 1 << w->shift, 0x0);
1620 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001621 }
1622 return 0;
1623}
1624
Bradley Rubin74a9b4a2011-06-13 15:03:43 -07001625static int tabla_codec_reset_interpolator(struct snd_soc_dapm_widget *w,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001626 struct snd_kcontrol *kcontrol, int event)
1627{
1628 struct snd_soc_codec *codec = w->codec;
1629
Kiran Kandi8b3a8302011-09-27 16:13:28 -07001630 pr_debug("%s %d %s\n", __func__, event, w->name);
1631
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001632 switch (event) {
1633 case SND_SOC_DAPM_PRE_PMU:
Bradley Rubin74a9b4a2011-06-13 15:03:43 -07001634 snd_soc_update_bits(codec, TABLA_A_CDC_CLK_RX_RESET_CTL,
1635 1 << w->shift, 1 << w->shift);
1636 snd_soc_update_bits(codec, TABLA_A_CDC_CLK_RX_RESET_CTL,
1637 1 << w->shift, 0x0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001638 break;
1639 }
1640 return 0;
1641}
1642
Bradley Rubin229c6a52011-07-12 16:18:48 -07001643static int tabla_codec_enable_ldo_h(struct snd_soc_dapm_widget *w,
1644 struct snd_kcontrol *kcontrol, int event)
1645{
1646 switch (event) {
1647 case SND_SOC_DAPM_POST_PMU:
1648 case SND_SOC_DAPM_POST_PMD:
1649 usleep_range(1000, 1000);
1650 break;
1651 }
1652 return 0;
1653}
1654
Kiran Kandi6fae8bf2011-08-15 10:36:42 -07001655
1656static void tabla_enable_rx_bias(struct snd_soc_codec *codec, u32 enable)
1657{
1658 struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
1659
1660 if (enable) {
1661 tabla->rx_bias_count++;
1662 if (tabla->rx_bias_count == 1)
1663 snd_soc_update_bits(codec, TABLA_A_RX_COM_BIAS,
1664 0x80, 0x80);
1665 } else {
1666 tabla->rx_bias_count--;
1667 if (!tabla->rx_bias_count)
1668 snd_soc_update_bits(codec, TABLA_A_RX_COM_BIAS,
1669 0x80, 0x00);
1670 }
1671}
1672
1673static int tabla_codec_enable_rx_bias(struct snd_soc_dapm_widget *w,
1674 struct snd_kcontrol *kcontrol, int event)
1675{
1676 struct snd_soc_codec *codec = w->codec;
1677
1678 pr_debug("%s %d\n", __func__, event);
1679
1680 switch (event) {
1681 case SND_SOC_DAPM_PRE_PMU:
1682 tabla_enable_rx_bias(codec, 1);
1683 break;
1684 case SND_SOC_DAPM_POST_PMD:
1685 tabla_enable_rx_bias(codec, 0);
1686 break;
1687 }
1688 return 0;
1689}
Kiran Kandi8b3a8302011-09-27 16:13:28 -07001690static int tabla_hphr_dac_event(struct snd_soc_dapm_widget *w,
1691 struct snd_kcontrol *kcontrol, int event)
1692{
1693 struct snd_soc_codec *codec = w->codec;
1694
1695 pr_debug("%s %s %d\n", __func__, w->name, event);
1696
1697 switch (event) {
1698 case SND_SOC_DAPM_PRE_PMU:
1699 snd_soc_update_bits(codec, w->reg, 0x40, 0x40);
1700 break;
1701 case SND_SOC_DAPM_POST_PMD:
1702 snd_soc_update_bits(codec, w->reg, 0x40, 0x00);
1703 break;
1704 }
1705 return 0;
1706}
Kiran Kandi6fae8bf2011-08-15 10:36:42 -07001707
Joonwoo Park8b1f0982011-12-08 17:12:45 -08001708static void tabla_snd_soc_jack_report(struct tabla_priv *tabla,
1709 struct snd_soc_jack *jack, int status,
1710 int mask)
1711{
1712 /* XXX: wake_lock_timeout()? */
1713 snd_soc_jack_report(jack, status, mask);
1714}
1715
Patrick Lai49efeac2011-11-03 11:01:12 -07001716static void hphocp_off_report(struct tabla_priv *tabla,
1717 u32 jack_status, int irq)
1718{
1719 struct snd_soc_codec *codec;
1720
1721 if (tabla) {
1722 pr_info("%s: clear ocp status %x\n", __func__, jack_status);
1723 codec = tabla->codec;
1724 tabla->hph_status &= ~jack_status;
1725 if (tabla->headset_jack)
Joonwoo Park8b1f0982011-12-08 17:12:45 -08001726 tabla_snd_soc_jack_report(tabla, tabla->headset_jack,
1727 tabla->hph_status,
1728 TABLA_JACK_MASK);
Joonwoo Park0976d012011-12-22 11:48:18 -08001729 snd_soc_update_bits(codec, TABLA_A_RX_HPH_OCP_CTL, 0x10, 0x00);
1730 snd_soc_update_bits(codec, TABLA_A_RX_HPH_OCP_CTL, 0x10, 0x10);
Patrick Laic7cae882011-11-18 11:52:49 -08001731 /* reset retry counter as PA is turned off signifying
1732 * start of new OCP detection session
1733 */
1734 if (TABLA_IRQ_HPH_PA_OCPL_FAULT)
1735 tabla->hphlocp_cnt = 0;
1736 else
1737 tabla->hphrocp_cnt = 0;
Patrick Lai49efeac2011-11-03 11:01:12 -07001738 tabla_enable_irq(codec->control_data, irq);
1739 } else {
1740 pr_err("%s: Bad tabla private data\n", __func__);
1741 }
1742}
1743
1744static void hphlocp_off_report(struct work_struct *work)
1745{
1746 struct tabla_priv *tabla = container_of(work, struct tabla_priv,
1747 hphlocp_work);
1748 hphocp_off_report(tabla, SND_JACK_OC_HPHL, TABLA_IRQ_HPH_PA_OCPL_FAULT);
1749}
1750
1751static void hphrocp_off_report(struct work_struct *work)
1752{
1753 struct tabla_priv *tabla = container_of(work, struct tabla_priv,
1754 hphrocp_work);
1755 hphocp_off_report(tabla, SND_JACK_OC_HPHR, TABLA_IRQ_HPH_PA_OCPR_FAULT);
1756}
1757
Kiran Kandibf0b1ff2011-09-15 13:55:21 -07001758static int tabla_hph_pa_event(struct snd_soc_dapm_widget *w,
1759 struct snd_kcontrol *kcontrol, int event)
1760{
Bhalchandra Gajared9ebb6c2011-10-03 19:54:41 -07001761 struct snd_soc_codec *codec = w->codec;
1762 struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
1763 u8 mbhc_micb_ctl_val;
Kiran Kandibf0b1ff2011-09-15 13:55:21 -07001764 pr_debug("%s: event = %d\n", __func__, event);
1765
1766 switch (event) {
Bhalchandra Gajared9ebb6c2011-10-03 19:54:41 -07001767 case SND_SOC_DAPM_PRE_PMU:
1768 mbhc_micb_ctl_val = snd_soc_read(codec,
1769 tabla->mbhc_bias_regs.ctl_reg);
1770
1771 if (!(mbhc_micb_ctl_val & 0x80)
1772 && !tabla->mbhc_micbias_switched)
1773 tabla_codec_switch_micbias(codec, 1);
1774
1775 break;
1776
Kiran Kandibf0b1ff2011-09-15 13:55:21 -07001777 case SND_SOC_DAPM_POST_PMD:
Patrick Lai49efeac2011-11-03 11:01:12 -07001778 /* schedule work is required because at the time HPH PA DAPM
1779 * event callback is called by DAPM framework, CODEC dapm mutex
1780 * would have been locked while snd_soc_jack_report also
1781 * attempts to acquire same lock.
1782 */
Joonwoo Parka9444452011-12-08 18:48:27 -08001783 if (w->shift == 5) {
1784 clear_bit(TABLA_HPHL_PA_OFF_ACK,
1785 &tabla->hph_pa_dac_state);
1786 clear_bit(TABLA_HPHL_DAC_OFF_ACK,
1787 &tabla->hph_pa_dac_state);
1788 if (tabla->hph_status & SND_JACK_OC_HPHL)
1789 schedule_work(&tabla->hphlocp_work);
1790 } else if (w->shift == 4) {
1791 clear_bit(TABLA_HPHR_PA_OFF_ACK,
1792 &tabla->hph_pa_dac_state);
1793 clear_bit(TABLA_HPHR_DAC_OFF_ACK,
1794 &tabla->hph_pa_dac_state);
1795 if (tabla->hph_status & SND_JACK_OC_HPHR)
1796 schedule_work(&tabla->hphrocp_work);
1797 }
1798
Bhalchandra Gajared9ebb6c2011-10-03 19:54:41 -07001799 if (tabla->mbhc_micbias_switched)
1800 tabla_codec_switch_micbias(codec, 0);
1801
Kiran Kandibf0b1ff2011-09-15 13:55:21 -07001802 pr_debug("%s: sleep 10 ms after %s PA disable.\n", __func__,
1803 w->name);
1804 usleep_range(10000, 10000);
1805
1806 break;
1807 }
1808 return 0;
1809}
1810
Bhalchandra Gajare02d90cd2011-09-30 16:14:00 -07001811static void tabla_get_mbhc_micbias_regs(struct snd_soc_codec *codec,
1812 struct mbhc_micbias_regs *micbias_regs)
1813{
1814 struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
Bhalchandra Gajare02d90cd2011-09-30 16:14:00 -07001815 unsigned int cfilt;
1816
Joonwoo Park0976d012011-12-22 11:48:18 -08001817 switch (tabla->micbias) {
Bhalchandra Gajare02d90cd2011-09-30 16:14:00 -07001818 case TABLA_MICBIAS1:
1819 cfilt = tabla->pdata->micbias.bias1_cfilt_sel;
1820 micbias_regs->mbhc_reg = TABLA_A_MICB_1_MBHC;
1821 micbias_regs->int_rbias = TABLA_A_MICB_1_INT_RBIAS;
1822 micbias_regs->ctl_reg = TABLA_A_MICB_1_CTL;
1823 break;
1824 case TABLA_MICBIAS2:
1825 cfilt = tabla->pdata->micbias.bias2_cfilt_sel;
1826 micbias_regs->mbhc_reg = TABLA_A_MICB_2_MBHC;
1827 micbias_regs->int_rbias = TABLA_A_MICB_2_INT_RBIAS;
1828 micbias_regs->ctl_reg = TABLA_A_MICB_2_CTL;
1829 break;
1830 case TABLA_MICBIAS3:
1831 cfilt = tabla->pdata->micbias.bias3_cfilt_sel;
1832 micbias_regs->mbhc_reg = TABLA_A_MICB_3_MBHC;
1833 micbias_regs->int_rbias = TABLA_A_MICB_3_INT_RBIAS;
1834 micbias_regs->ctl_reg = TABLA_A_MICB_3_CTL;
1835 break;
1836 case TABLA_MICBIAS4:
1837 cfilt = tabla->pdata->micbias.bias4_cfilt_sel;
1838 micbias_regs->mbhc_reg = TABLA_A_MICB_4_MBHC;
1839 micbias_regs->int_rbias = TABLA_A_MICB_4_INT_RBIAS;
1840 micbias_regs->ctl_reg = TABLA_A_MICB_4_CTL;
1841 break;
1842 default:
1843 /* Should never reach here */
1844 pr_err("%s: Invalid MIC BIAS for MBHC\n", __func__);
Jordan Crouse239d8412011-11-23 11:47:02 -07001845 return;
Bhalchandra Gajare02d90cd2011-09-30 16:14:00 -07001846 }
1847
Bhalchandra Gajare19d9c132011-11-18 14:57:08 -08001848 micbias_regs->cfilt_sel = cfilt;
1849
Bhalchandra Gajare02d90cd2011-09-30 16:14:00 -07001850 switch (cfilt) {
1851 case TABLA_CFILT1_SEL:
1852 micbias_regs->cfilt_val = TABLA_A_MICB_CFILT_1_VAL;
1853 micbias_regs->cfilt_ctl = TABLA_A_MICB_CFILT_1_CTL;
Joonwoo Park0976d012011-12-22 11:48:18 -08001854 tabla->mbhc_data.micb_mv = tabla->pdata->micbias.cfilt1_mv;
Bhalchandra Gajare02d90cd2011-09-30 16:14:00 -07001855 break;
1856 case TABLA_CFILT2_SEL:
1857 micbias_regs->cfilt_val = TABLA_A_MICB_CFILT_2_VAL;
1858 micbias_regs->cfilt_ctl = TABLA_A_MICB_CFILT_2_CTL;
Joonwoo Park0976d012011-12-22 11:48:18 -08001859 tabla->mbhc_data.micb_mv = tabla->pdata->micbias.cfilt2_mv;
Bhalchandra Gajare02d90cd2011-09-30 16:14:00 -07001860 break;
1861 case TABLA_CFILT3_SEL:
1862 micbias_regs->cfilt_val = TABLA_A_MICB_CFILT_3_VAL;
1863 micbias_regs->cfilt_ctl = TABLA_A_MICB_CFILT_3_CTL;
Joonwoo Park0976d012011-12-22 11:48:18 -08001864 tabla->mbhc_data.micb_mv = tabla->pdata->micbias.cfilt3_mv;
Bhalchandra Gajare02d90cd2011-09-30 16:14:00 -07001865 break;
1866 }
1867}
Santosh Mardie15e2302011-11-15 10:39:23 +05301868static const struct snd_soc_dapm_widget tabla_dapm_i2s_widgets[] = {
1869 SND_SOC_DAPM_SUPPLY("RX_I2S_CLK", TABLA_A_CDC_CLK_RX_I2S_CTL,
1870 4, 0, NULL, 0),
1871 SND_SOC_DAPM_SUPPLY("TX_I2S_CLK", TABLA_A_CDC_CLK_TX_I2S_CTL, 4,
1872 0, NULL, 0),
1873};
Bhalchandra Gajare02d90cd2011-09-30 16:14:00 -07001874
Kiran Kandi8b3a8302011-09-27 16:13:28 -07001875static int tabla_lineout_dac_event(struct snd_soc_dapm_widget *w,
1876 struct snd_kcontrol *kcontrol, int event)
1877{
1878 struct snd_soc_codec *codec = w->codec;
1879
1880 pr_debug("%s %s %d\n", __func__, w->name, event);
1881
1882 switch (event) {
1883 case SND_SOC_DAPM_PRE_PMU:
1884 snd_soc_update_bits(codec, w->reg, 0x40, 0x40);
1885 break;
1886
1887 case SND_SOC_DAPM_POST_PMD:
1888 snd_soc_update_bits(codec, w->reg, 0x40, 0x00);
1889 break;
1890 }
1891 return 0;
1892}
1893
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001894static const struct snd_soc_dapm_widget tabla_dapm_widgets[] = {
1895 /*RX stuff */
1896 SND_SOC_DAPM_OUTPUT("EAR"),
1897
Kiran Kandid2d86b52011-09-09 17:44:28 -07001898 SND_SOC_DAPM_PGA("EAR PA", TABLA_A_RX_EAR_EN, 4, 0, NULL, 0),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001899
Bradley Rubin229c6a52011-07-12 16:18:48 -07001900 SND_SOC_DAPM_MIXER("DAC1", TABLA_A_RX_EAR_EN, 6, 0, dac1_switch,
1901 ARRAY_SIZE(dac1_switch)),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001902
Bradley Rubin229c6a52011-07-12 16:18:48 -07001903 SND_SOC_DAPM_AIF_IN("SLIM RX1", "AIF1 Playback", 0, SND_SOC_NOPM, 0, 0),
1904 SND_SOC_DAPM_AIF_IN("SLIM RX2", "AIF1 Playback", 0, SND_SOC_NOPM, 0, 0),
Santosh Mardie15e2302011-11-15 10:39:23 +05301905 SND_SOC_DAPM_AIF_IN("SLIM RX3", "AIF1 Playback", 0, SND_SOC_NOPM, 0, 0),
1906 SND_SOC_DAPM_AIF_IN("SLIM RX4", "AIF1 Playback", 0, SND_SOC_NOPM, 0, 0),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001907
1908 /* Headphone */
1909 SND_SOC_DAPM_OUTPUT("HEADPHONE"),
Kiran Kandibf0b1ff2011-09-15 13:55:21 -07001910 SND_SOC_DAPM_PGA_E("HPHL", TABLA_A_RX_HPH_CNP_EN, 5, 0, NULL, 0,
Bhalchandra Gajared9ebb6c2011-10-03 19:54:41 -07001911 tabla_hph_pa_event, SND_SOC_DAPM_PRE_PMU |
1912 SND_SOC_DAPM_POST_PMD),
Bradley Rubin229c6a52011-07-12 16:18:48 -07001913 SND_SOC_DAPM_MIXER("HPHL DAC", TABLA_A_RX_HPH_L_DAC_CTL, 7, 0,
1914 hphl_switch, ARRAY_SIZE(hphl_switch)),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001915
Kiran Kandibf0b1ff2011-09-15 13:55:21 -07001916 SND_SOC_DAPM_PGA_E("HPHR", TABLA_A_RX_HPH_CNP_EN, 4, 0, NULL, 0,
Bhalchandra Gajared9ebb6c2011-10-03 19:54:41 -07001917 tabla_hph_pa_event, SND_SOC_DAPM_PRE_PMU |
1918 SND_SOC_DAPM_POST_PMD),
Kiran Kandi8b3a8302011-09-27 16:13:28 -07001919
1920 SND_SOC_DAPM_DAC_E("HPHR DAC", NULL, TABLA_A_RX_HPH_R_DAC_CTL, 7, 0,
1921 tabla_hphr_dac_event,
1922 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001923
1924 /* Speaker */
Kiran Kandidb0a4b02011-08-23 09:32:09 -07001925 SND_SOC_DAPM_OUTPUT("LINEOUT1"),
1926 SND_SOC_DAPM_OUTPUT("LINEOUT2"),
1927 SND_SOC_DAPM_OUTPUT("LINEOUT3"),
1928 SND_SOC_DAPM_OUTPUT("LINEOUT4"),
1929 SND_SOC_DAPM_OUTPUT("LINEOUT5"),
Bradley Rubin74a9b4a2011-06-13 15:03:43 -07001930
Kiran Kandidb0a4b02011-08-23 09:32:09 -07001931 SND_SOC_DAPM_PGA_E("LINEOUT1 PA", TABLA_A_RX_LINE_CNP_EN, 0, 0, NULL,
1932 0, tabla_codec_enable_lineout, SND_SOC_DAPM_PRE_PMU |
1933 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
1934 SND_SOC_DAPM_PGA_E("LINEOUT2 PA", TABLA_A_RX_LINE_CNP_EN, 1, 0, NULL,
1935 0, tabla_codec_enable_lineout, SND_SOC_DAPM_PRE_PMU |
1936 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
1937 SND_SOC_DAPM_PGA_E("LINEOUT3 PA", TABLA_A_RX_LINE_CNP_EN, 2, 0, NULL,
1938 0, tabla_codec_enable_lineout, SND_SOC_DAPM_PRE_PMU |
1939 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
1940 SND_SOC_DAPM_PGA_E("LINEOUT4 PA", TABLA_A_RX_LINE_CNP_EN, 3, 0, NULL,
1941 0, tabla_codec_enable_lineout, SND_SOC_DAPM_PRE_PMU |
1942 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
1943 SND_SOC_DAPM_PGA_E("LINEOUT5 PA", TABLA_A_RX_LINE_CNP_EN, 4, 0, NULL, 0,
Bhalchandra Gajare0a8ad172011-08-12 13:32:22 -07001944 tabla_codec_enable_lineout, SND_SOC_DAPM_PRE_PMU |
1945 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
Bradley Rubin74a9b4a2011-06-13 15:03:43 -07001946
Kiran Kandi8b3a8302011-09-27 16:13:28 -07001947 SND_SOC_DAPM_DAC_E("LINEOUT1 DAC", NULL, TABLA_A_RX_LINE_1_DAC_CTL, 7, 0
1948 , tabla_lineout_dac_event,
1949 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
1950 SND_SOC_DAPM_DAC_E("LINEOUT2 DAC", NULL, TABLA_A_RX_LINE_2_DAC_CTL, 7, 0
1951 , tabla_lineout_dac_event,
1952 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
1953 SND_SOC_DAPM_DAC_E("LINEOUT3 DAC", NULL, TABLA_A_RX_LINE_3_DAC_CTL, 7, 0
1954 , tabla_lineout_dac_event,
1955 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
1956 SND_SOC_DAPM_SWITCH("LINEOUT3 DAC GROUND", SND_SOC_NOPM, 0, 0,
1957 &lineout3_ground_switch),
1958 SND_SOC_DAPM_DAC_E("LINEOUT4 DAC", NULL, TABLA_A_RX_LINE_4_DAC_CTL, 7, 0
1959 , tabla_lineout_dac_event,
1960 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
1961 SND_SOC_DAPM_SWITCH("LINEOUT4 DAC GROUND", SND_SOC_NOPM, 0, 0,
1962 &lineout4_ground_switch),
1963 SND_SOC_DAPM_DAC_E("LINEOUT5 DAC", NULL, TABLA_A_RX_LINE_5_DAC_CTL, 7, 0
1964 , tabla_lineout_dac_event,
1965 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
Bradley Rubin74a9b4a2011-06-13 15:03:43 -07001966
Bradley Rubin229c6a52011-07-12 16:18:48 -07001967 SND_SOC_DAPM_MIXER_E("RX1 MIX1", TABLA_A_CDC_CLK_RX_B1_CTL, 0, 0, NULL,
1968 0, tabla_codec_reset_interpolator, SND_SOC_DAPM_PRE_PMU),
1969 SND_SOC_DAPM_MIXER_E("RX2 MIX1", TABLA_A_CDC_CLK_RX_B1_CTL, 1, 0, NULL,
1970 0, tabla_codec_reset_interpolator, SND_SOC_DAPM_PRE_PMU),
1971 SND_SOC_DAPM_MIXER_E("RX3 MIX1", TABLA_A_CDC_CLK_RX_B1_CTL, 2, 0, NULL,
1972 0, tabla_codec_reset_interpolator, SND_SOC_DAPM_PRE_PMU),
1973 SND_SOC_DAPM_MIXER_E("RX4 MIX1", TABLA_A_CDC_CLK_RX_B1_CTL, 3, 0, NULL,
1974 0, tabla_codec_reset_interpolator, SND_SOC_DAPM_PRE_PMU),
1975 SND_SOC_DAPM_MIXER_E("RX5 MIX1", TABLA_A_CDC_CLK_RX_B1_CTL, 4, 0, NULL,
1976 0, tabla_codec_reset_interpolator, SND_SOC_DAPM_PRE_PMU),
1977 SND_SOC_DAPM_MIXER_E("RX6 MIX1", TABLA_A_CDC_CLK_RX_B1_CTL, 5, 0, NULL,
1978 0, tabla_codec_reset_interpolator, SND_SOC_DAPM_PRE_PMU),
Bhalchandra Gajare0a8ad172011-08-12 13:32:22 -07001979 SND_SOC_DAPM_MIXER_E("RX7 MIX1", TABLA_A_CDC_CLK_RX_B1_CTL, 6, 0, NULL,
1980 0, tabla_codec_reset_interpolator, SND_SOC_DAPM_PRE_PMU),
Bradley Rubin74a9b4a2011-06-13 15:03:43 -07001981
Kiran Kandi8b3a8302011-09-27 16:13:28 -07001982
1983 SND_SOC_DAPM_MUX_E("RX4 DSM MUX", TABLA_A_CDC_CLK_RX_B1_CTL, 3, 0,
1984 &rx4_dsm_mux, tabla_codec_reset_interpolator,
1985 SND_SOC_DAPM_PRE_PMU),
1986
1987 SND_SOC_DAPM_MUX_E("RX6 DSM MUX", TABLA_A_CDC_CLK_RX_B1_CTL, 5, 0,
1988 &rx6_dsm_mux, tabla_codec_reset_interpolator,
1989 SND_SOC_DAPM_PRE_PMU),
1990
Bradley Rubin229c6a52011-07-12 16:18:48 -07001991 SND_SOC_DAPM_MIXER("RX1 CHAIN", TABLA_A_CDC_RX1_B6_CTL, 5, 0, NULL, 0),
1992 SND_SOC_DAPM_MIXER("RX2 CHAIN", TABLA_A_CDC_RX2_B6_CTL, 5, 0, NULL, 0),
1993
1994 SND_SOC_DAPM_MUX("RX1 MIX1 INP1", SND_SOC_NOPM, 0, 0,
1995 &rx_mix1_inp1_mux),
1996 SND_SOC_DAPM_MUX("RX1 MIX1 INP2", SND_SOC_NOPM, 0, 0,
1997 &rx_mix1_inp2_mux),
1998 SND_SOC_DAPM_MUX("RX2 MIX1 INP1", SND_SOC_NOPM, 0, 0,
1999 &rx2_mix1_inp1_mux),
2000 SND_SOC_DAPM_MUX("RX2 MIX1 INP2", SND_SOC_NOPM, 0, 0,
2001 &rx2_mix1_inp2_mux),
Bradley Rubin74a9b4a2011-06-13 15:03:43 -07002002 SND_SOC_DAPM_MUX("RX3 MIX1 INP1", SND_SOC_NOPM, 0, 0,
2003 &rx3_mix1_inp1_mux),
2004 SND_SOC_DAPM_MUX("RX3 MIX1 INP2", SND_SOC_NOPM, 0, 0,
2005 &rx3_mix1_inp2_mux),
2006 SND_SOC_DAPM_MUX("RX4 MIX1 INP1", SND_SOC_NOPM, 0, 0,
2007 &rx4_mix1_inp1_mux),
2008 SND_SOC_DAPM_MUX("RX4 MIX1 INP2", SND_SOC_NOPM, 0, 0,
2009 &rx4_mix1_inp2_mux),
2010 SND_SOC_DAPM_MUX("RX5 MIX1 INP1", SND_SOC_NOPM, 0, 0,
2011 &rx5_mix1_inp1_mux),
2012 SND_SOC_DAPM_MUX("RX5 MIX1 INP2", SND_SOC_NOPM, 0, 0,
2013 &rx5_mix1_inp2_mux),
2014 SND_SOC_DAPM_MUX("RX6 MIX1 INP1", SND_SOC_NOPM, 0, 0,
2015 &rx6_mix1_inp1_mux),
2016 SND_SOC_DAPM_MUX("RX6 MIX1 INP2", SND_SOC_NOPM, 0, 0,
2017 &rx6_mix1_inp2_mux),
Bhalchandra Gajare0a8ad172011-08-12 13:32:22 -07002018 SND_SOC_DAPM_MUX("RX7 MIX1 INP1", SND_SOC_NOPM, 0, 0,
2019 &rx7_mix1_inp1_mux),
2020 SND_SOC_DAPM_MUX("RX7 MIX1 INP2", SND_SOC_NOPM, 0, 0,
2021 &rx7_mix1_inp2_mux),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002022
Bradley Rubin229c6a52011-07-12 16:18:48 -07002023 SND_SOC_DAPM_SUPPLY("CP", TABLA_A_CP_EN, 0, 0,
2024 tabla_codec_enable_charge_pump, SND_SOC_DAPM_POST_PMU |
2025 SND_SOC_DAPM_PRE_PMD),
2026
Kiran Kandi6fae8bf2011-08-15 10:36:42 -07002027 SND_SOC_DAPM_SUPPLY("RX_BIAS", SND_SOC_NOPM, 0, 0,
2028 tabla_codec_enable_rx_bias, SND_SOC_DAPM_PRE_PMU |
2029 SND_SOC_DAPM_POST_PMD),
2030
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002031 /* TX */
Bradley Rubin229c6a52011-07-12 16:18:48 -07002032
Bradley Rubine1d08622011-07-20 18:01:35 -07002033 SND_SOC_DAPM_SUPPLY("CDC_CONN", TABLA_A_CDC_CLK_OTHR_CTL, 2, 0, NULL,
2034 0),
2035
Bradley Rubin229c6a52011-07-12 16:18:48 -07002036 SND_SOC_DAPM_SUPPLY("LDO_H", TABLA_A_LDO_H_MODE_1, 7, 0,
2037 tabla_codec_enable_ldo_h, SND_SOC_DAPM_POST_PMU),
2038
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002039 SND_SOC_DAPM_INPUT("AMIC1"),
2040 SND_SOC_DAPM_MICBIAS_E("MIC BIAS1 External", TABLA_A_MICB_1_CTL, 7, 0,
2041 tabla_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
Bradley Rubin4d09cf42011-08-17 17:59:16 -07002042 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
Bradley Rubin229c6a52011-07-12 16:18:48 -07002043 SND_SOC_DAPM_MICBIAS_E("MIC BIAS1 Internal1", TABLA_A_MICB_1_CTL, 7, 0,
2044 tabla_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
Bradley Rubin4d09cf42011-08-17 17:59:16 -07002045 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
Bradley Rubin229c6a52011-07-12 16:18:48 -07002046 SND_SOC_DAPM_MICBIAS_E("MIC BIAS1 Internal2", TABLA_A_MICB_1_CTL, 7, 0,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002047 tabla_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
Bradley Rubin4d09cf42011-08-17 17:59:16 -07002048 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002049 SND_SOC_DAPM_ADC_E("ADC1", NULL, TABLA_A_TX_1_2_EN, 7, 0,
2050 tabla_codec_enable_adc, SND_SOC_DAPM_PRE_PMU |
2051 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
2052
Bhalchandra Gajarecc6ffa02011-07-14 18:35:41 -07002053 SND_SOC_DAPM_INPUT("AMIC3"),
2054 SND_SOC_DAPM_ADC_E("ADC3", NULL, TABLA_A_TX_3_4_EN, 7, 0,
2055 tabla_codec_enable_adc, SND_SOC_DAPM_PRE_PMU |
2056 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
2057
2058 SND_SOC_DAPM_INPUT("AMIC4"),
2059 SND_SOC_DAPM_ADC_E("ADC4", NULL, TABLA_A_TX_3_4_EN, 3, 0,
2060 tabla_codec_enable_adc, SND_SOC_DAPM_PRE_PMU |
2061 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
2062
2063 SND_SOC_DAPM_MICBIAS_E("MIC BIAS4 External", TABLA_A_MICB_4_CTL, 7, 0,
2064 tabla_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
Bradley Rubin4d09cf42011-08-17 17:59:16 -07002065 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
Bhalchandra Gajarecc6ffa02011-07-14 18:35:41 -07002066
Bhalchandra Gajare0d77e1b2011-07-08 10:54:14 -07002067 SND_SOC_DAPM_INPUT("AMIC5"),
2068 SND_SOC_DAPM_ADC_E("ADC5", NULL, TABLA_A_TX_5_6_EN, 7, 0,
2069 tabla_codec_enable_adc, SND_SOC_DAPM_POST_PMU),
2070
2071 SND_SOC_DAPM_INPUT("AMIC6"),
2072 SND_SOC_DAPM_ADC_E("ADC6", NULL, TABLA_A_TX_5_6_EN, 3, 0,
2073 tabla_codec_enable_adc, SND_SOC_DAPM_POST_PMU),
2074
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002075 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 -07002076 &dec1_mux, tabla_codec_enable_dec, SND_SOC_DAPM_PRE_PMU),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002077
Bhalchandra Gajare0d77e1b2011-07-08 10:54:14 -07002078 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 -07002079 &dec2_mux, tabla_codec_enable_dec, SND_SOC_DAPM_PRE_PMU),
Bhalchandra Gajare0d77e1b2011-07-08 10:54:14 -07002080
Bhalchandra Gajarecc6ffa02011-07-14 18:35:41 -07002081 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 -07002082 &dec3_mux, tabla_codec_enable_dec, SND_SOC_DAPM_PRE_PMU),
Bhalchandra Gajarecc6ffa02011-07-14 18:35:41 -07002083
2084 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 -07002085 &dec4_mux, tabla_codec_enable_dec, SND_SOC_DAPM_PRE_PMU),
Bhalchandra Gajarecc6ffa02011-07-14 18:35:41 -07002086
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002087 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 -07002088 &dec5_mux, tabla_codec_enable_dec, SND_SOC_DAPM_PRE_PMU),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002089
2090 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 -07002091 &dec6_mux, tabla_codec_enable_dec, SND_SOC_DAPM_PRE_PMU),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002092
2093 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 -07002094 &dec7_mux, tabla_codec_enable_dec, SND_SOC_DAPM_PRE_PMU),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002095
Bhalchandra Gajare0d77e1b2011-07-08 10:54:14 -07002096 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 -07002097 &dec8_mux, tabla_codec_enable_dec, SND_SOC_DAPM_PRE_PMU),
Bhalchandra Gajare0d77e1b2011-07-08 10:54:14 -07002098
Bhalchandra Gajarecc6ffa02011-07-14 18:35:41 -07002099 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 -07002100 &dec9_mux, tabla_codec_enable_dec, SND_SOC_DAPM_PRE_PMU),
Bhalchandra Gajarecc6ffa02011-07-14 18:35:41 -07002101
2102 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 -07002103 &dec10_mux, tabla_codec_enable_dec, SND_SOC_DAPM_PRE_PMU),
Bhalchandra Gajarecc6ffa02011-07-14 18:35:41 -07002104
Bradley Rubin229c6a52011-07-12 16:18:48 -07002105 SND_SOC_DAPM_MUX("ANC1 MUX", SND_SOC_NOPM, 0, 0, &anc1_mux),
2106 SND_SOC_DAPM_MUX("ANC2 MUX", SND_SOC_NOPM, 0, 0, &anc2_mux),
2107
2108 SND_SOC_DAPM_MIXER_E("ANC", SND_SOC_NOPM, 0, 0, NULL, 0,
2109 tabla_codec_enable_anc, SND_SOC_DAPM_PRE_PMU |
2110 SND_SOC_DAPM_POST_PMD),
2111
2112 SND_SOC_DAPM_MUX("ANC1 FB MUX", SND_SOC_NOPM, 0, 0, &anc1_fb_mux),
2113
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002114 SND_SOC_DAPM_INPUT("AMIC2"),
2115 SND_SOC_DAPM_MICBIAS_E("MIC BIAS2 External", TABLA_A_MICB_2_CTL, 7, 0,
2116 tabla_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
Bradley Rubin4d09cf42011-08-17 17:59:16 -07002117 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
Bradley Rubin229c6a52011-07-12 16:18:48 -07002118 SND_SOC_DAPM_MICBIAS_E("MIC BIAS2 Internal1", TABLA_A_MICB_2_CTL, 7, 0,
2119 tabla_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
Bradley Rubin4d09cf42011-08-17 17:59:16 -07002120 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
Bradley Rubin229c6a52011-07-12 16:18:48 -07002121 SND_SOC_DAPM_MICBIAS_E("MIC BIAS2 Internal2", TABLA_A_MICB_2_CTL, 7, 0,
2122 tabla_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
Bradley Rubin4d09cf42011-08-17 17:59:16 -07002123 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
Bradley Rubin229c6a52011-07-12 16:18:48 -07002124 SND_SOC_DAPM_MICBIAS_E("MIC BIAS2 Internal3", TABLA_A_MICB_2_CTL, 7, 0,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002125 tabla_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
Bradley Rubin4d09cf42011-08-17 17:59:16 -07002126 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002127 SND_SOC_DAPM_MICBIAS_E("MIC BIAS3 External", TABLA_A_MICB_3_CTL, 7, 0,
2128 tabla_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
Bradley Rubin4d09cf42011-08-17 17:59:16 -07002129 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
Bradley Rubin229c6a52011-07-12 16:18:48 -07002130 SND_SOC_DAPM_MICBIAS_E("MIC BIAS3 Internal1", TABLA_A_MICB_3_CTL, 7, 0,
2131 tabla_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
Bradley Rubin4d09cf42011-08-17 17:59:16 -07002132 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
Bradley Rubin229c6a52011-07-12 16:18:48 -07002133 SND_SOC_DAPM_MICBIAS_E("MIC BIAS3 Internal2", TABLA_A_MICB_3_CTL, 7, 0,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002134 tabla_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
Bradley Rubin4d09cf42011-08-17 17:59:16 -07002135 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002136 SND_SOC_DAPM_ADC_E("ADC2", NULL, TABLA_A_TX_1_2_EN, 3, 0,
2137 tabla_codec_enable_adc, SND_SOC_DAPM_PRE_PMU |
2138 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
2139
2140 SND_SOC_DAPM_MUX("SLIM TX1 MUX", SND_SOC_NOPM, 0, 0, &sb_tx1_mux),
2141 SND_SOC_DAPM_AIF_OUT("SLIM TX1", "AIF1 Capture", NULL, SND_SOC_NOPM,
2142 0, 0),
2143
2144 SND_SOC_DAPM_MUX("SLIM TX5 MUX", SND_SOC_NOPM, 0, 0, &sb_tx5_mux),
2145 SND_SOC_DAPM_AIF_OUT("SLIM TX5", "AIF1 Capture", NULL, SND_SOC_NOPM,
2146 4, 0),
2147
2148 SND_SOC_DAPM_MUX("SLIM TX6 MUX", SND_SOC_NOPM, 0, 0, &sb_tx6_mux),
2149 SND_SOC_DAPM_AIF_OUT("SLIM TX6", "AIF1 Capture", NULL, SND_SOC_NOPM,
2150 5, 0),
2151
2152 SND_SOC_DAPM_MUX("SLIM TX7 MUX", SND_SOC_NOPM, 0, 0, &sb_tx7_mux),
2153 SND_SOC_DAPM_AIF_OUT("SLIM TX7", "AIF1 Capture", NULL, SND_SOC_NOPM,
2154 0, 0),
2155
2156 SND_SOC_DAPM_MUX("SLIM TX8 MUX", SND_SOC_NOPM, 0, 0, &sb_tx8_mux),
2157 SND_SOC_DAPM_AIF_OUT("SLIM TX8", "AIF1 Capture", NULL, SND_SOC_NOPM,
2158 0, 0),
2159
Kiran Kandi3426e512011-09-13 22:50:10 -07002160 SND_SOC_DAPM_MUX("SLIM TX9 MUX", SND_SOC_NOPM, 0, 0, &sb_tx9_mux),
2161 SND_SOC_DAPM_AIF_OUT("SLIM TX9", "AIF1 Capture", NULL, SND_SOC_NOPM,
2162 0, 0),
2163
2164 SND_SOC_DAPM_MUX("SLIM TX10 MUX", SND_SOC_NOPM, 0, 0, &sb_tx10_mux),
2165 SND_SOC_DAPM_AIF_OUT("SLIM TX10", "AIF1 Capture", NULL, SND_SOC_NOPM,
2166 0, 0),
2167
Kiran Kandicf45f6a2011-07-17 21:10:19 -07002168 /* Digital Mic Inputs */
Bhalchandra Gajare7cf018e2011-08-11 18:58:32 -07002169 SND_SOC_DAPM_ADC_E("DMIC1", NULL, SND_SOC_NOPM, 0, 0,
2170 tabla_codec_enable_dmic, SND_SOC_DAPM_PRE_PMU |
2171 SND_SOC_DAPM_POST_PMD),
2172
2173 SND_SOC_DAPM_ADC_E("DMIC2", NULL, SND_SOC_NOPM, 0, 0,
2174 tabla_codec_enable_dmic, SND_SOC_DAPM_PRE_PMU |
2175 SND_SOC_DAPM_POST_PMD),
2176
2177 SND_SOC_DAPM_ADC_E("DMIC3", NULL, SND_SOC_NOPM, 0, 0,
2178 tabla_codec_enable_dmic, SND_SOC_DAPM_PRE_PMU |
2179 SND_SOC_DAPM_POST_PMD),
2180
2181 SND_SOC_DAPM_ADC_E("DMIC4", NULL, SND_SOC_NOPM, 0, 0,
2182 tabla_codec_enable_dmic, SND_SOC_DAPM_PRE_PMU |
2183 SND_SOC_DAPM_POST_PMD),
2184
2185 SND_SOC_DAPM_ADC_E("DMIC5", NULL, SND_SOC_NOPM, 0, 0,
2186 tabla_codec_enable_dmic, SND_SOC_DAPM_PRE_PMU |
2187 SND_SOC_DAPM_POST_PMD),
2188
2189 SND_SOC_DAPM_ADC_E("DMIC6", NULL, SND_SOC_NOPM, 0, 0,
2190 tabla_codec_enable_dmic, SND_SOC_DAPM_PRE_PMU |
2191 SND_SOC_DAPM_POST_PMD),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002192
2193 /* Sidetone */
2194 SND_SOC_DAPM_MUX("IIR1 INP1 MUX", SND_SOC_NOPM, 0, 0, &iir1_inp1_mux),
2195 SND_SOC_DAPM_PGA("IIR1", TABLA_A_CDC_CLK_SD_CTL, 0, 0, NULL, 0),
2196};
2197
Santosh Mardie15e2302011-11-15 10:39:23 +05302198static const struct snd_soc_dapm_route audio_i2s_map[] = {
2199 {"RX_I2S_CLK", NULL, "CDC_CONN"},
2200 {"SLIM RX1", NULL, "RX_I2S_CLK"},
2201 {"SLIM RX2", NULL, "RX_I2S_CLK"},
2202 {"SLIM RX3", NULL, "RX_I2S_CLK"},
2203 {"SLIM RX4", NULL, "RX_I2S_CLK"},
2204
2205 {"SLIM TX7", NULL, "TX_I2S_CLK"},
2206 {"SLIM TX8", NULL, "TX_I2S_CLK"},
2207 {"SLIM TX9", NULL, "TX_I2S_CLK"},
2208 {"SLIM TX10", NULL, "TX_I2S_CLK"},
2209};
2210
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002211static const struct snd_soc_dapm_route audio_map[] = {
2212 /* SLIMBUS Connections */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002213
2214 {"SLIM TX1", NULL, "SLIM TX1 MUX"},
2215 {"SLIM TX1 MUX", "DEC1", "DEC1 MUX"},
2216
2217 {"SLIM TX5", NULL, "SLIM TX5 MUX"},
2218 {"SLIM TX5 MUX", "DEC5", "DEC5 MUX"},
2219
2220 {"SLIM TX6", NULL, "SLIM TX6 MUX"},
2221 {"SLIM TX6 MUX", "DEC6", "DEC6 MUX"},
2222
2223 {"SLIM TX7", NULL, "SLIM TX7 MUX"},
2224 {"SLIM TX7 MUX", "DEC1", "DEC1 MUX"},
Bhalchandra Gajare0d77e1b2011-07-08 10:54:14 -07002225 {"SLIM TX7 MUX", "DEC2", "DEC2 MUX"},
Bhalchandra Gajarecc6ffa02011-07-14 18:35:41 -07002226 {"SLIM TX7 MUX", "DEC3", "DEC3 MUX"},
2227 {"SLIM TX7 MUX", "DEC4", "DEC4 MUX"},
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002228 {"SLIM TX7 MUX", "DEC5", "DEC5 MUX"},
2229 {"SLIM TX7 MUX", "DEC6", "DEC6 MUX"},
Bhalchandra Gajare0d77e1b2011-07-08 10:54:14 -07002230 {"SLIM TX7 MUX", "DEC7", "DEC7 MUX"},
2231 {"SLIM TX7 MUX", "DEC8", "DEC8 MUX"},
Bhalchandra Gajarecc6ffa02011-07-14 18:35:41 -07002232 {"SLIM TX7 MUX", "DEC9", "DEC9 MUX"},
2233 {"SLIM TX7 MUX", "DEC10", "DEC10 MUX"},
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002234
2235 {"SLIM TX8", NULL, "SLIM TX8 MUX"},
Kiran Kandicf45f6a2011-07-17 21:10:19 -07002236 {"SLIM TX8 MUX", "DEC1", "DEC1 MUX"},
2237 {"SLIM TX8 MUX", "DEC2", "DEC2 MUX"},
2238 {"SLIM TX8 MUX", "DEC3", "DEC3 MUX"},
Bhalchandra Gajare9ec83cd2011-09-23 17:25:07 -07002239 {"SLIM TX8 MUX", "DEC4", "DEC4 MUX"},
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002240 {"SLIM TX8 MUX", "DEC5", "DEC5 MUX"},
2241 {"SLIM TX8 MUX", "DEC6", "DEC6 MUX"},
2242
Kiran Kandi3426e512011-09-13 22:50:10 -07002243 {"SLIM TX9", NULL, "SLIM TX9 MUX"},
2244 {"SLIM TX9 MUX", "DEC1", "DEC1 MUX"},
2245 {"SLIM TX9 MUX", "DEC2", "DEC2 MUX"},
2246 {"SLIM TX9 MUX", "DEC3", "DEC3 MUX"},
2247 {"SLIM TX9 MUX", "DEC4", "DEC4 MUX"},
2248 {"SLIM TX9 MUX", "DEC5", "DEC5 MUX"},
2249 {"SLIM TX9 MUX", "DEC6", "DEC6 MUX"},
2250 {"SLIM TX9 MUX", "DEC7", "DEC7 MUX"},
2251 {"SLIM TX9 MUX", "DEC8", "DEC8 MUX"},
2252 {"SLIM TX9 MUX", "DEC9", "DEC9 MUX"},
2253 {"SLIM TX9 MUX", "DEC10", "DEC10 MUX"},
2254
2255 {"SLIM TX10", NULL, "SLIM TX10 MUX"},
2256 {"SLIM TX10 MUX", "DEC1", "DEC1 MUX"},
2257 {"SLIM TX10 MUX", "DEC2", "DEC2 MUX"},
2258 {"SLIM TX10 MUX", "DEC3", "DEC3 MUX"},
2259 {"SLIM TX10 MUX", "DEC4", "DEC4 MUX"},
2260 {"SLIM TX10 MUX", "DEC5", "DEC5 MUX"},
2261 {"SLIM TX10 MUX", "DEC6", "DEC6 MUX"},
2262 {"SLIM TX10 MUX", "DEC7", "DEC7 MUX"},
2263 {"SLIM TX10 MUX", "DEC8", "DEC8 MUX"},
2264 {"SLIM TX10 MUX", "DEC9", "DEC9 MUX"},
2265 {"SLIM TX10 MUX", "DEC10", "DEC10 MUX"},
2266
2267
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002268 /* Earpiece (RX MIX1) */
2269 {"EAR", NULL, "EAR PA"},
Kiran Kandiac034ac2011-07-29 16:39:08 -07002270 {"EAR PA", NULL, "DAC1"},
Bradley Rubin229c6a52011-07-12 16:18:48 -07002271 {"DAC1", NULL, "CP"},
2272
2273 {"ANC1 FB MUX", "EAR_HPH_L", "RX1 MIX1"},
2274 {"ANC1 FB MUX", "EAR_LINE_1", "RX2 MIX1"},
2275 {"ANC", NULL, "ANC1 FB MUX"},
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002276
2277 /* Headset (RX MIX1 and RX MIX2) */
2278 {"HEADPHONE", NULL, "HPHL"},
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002279 {"HEADPHONE", NULL, "HPHR"},
Bradley Rubin229c6a52011-07-12 16:18:48 -07002280
2281 {"HPHL", NULL, "HPHL DAC"},
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002282 {"HPHR", NULL, "HPHR DAC"},
Bradley Rubin229c6a52011-07-12 16:18:48 -07002283
2284 {"HPHL DAC", NULL, "CP"},
2285 {"HPHR DAC", NULL, "CP"},
2286
2287 {"ANC", NULL, "ANC1 MUX"},
2288 {"ANC", NULL, "ANC2 MUX"},
2289 {"ANC1 MUX", "ADC1", "ADC1"},
2290 {"ANC1 MUX", "ADC2", "ADC2"},
2291 {"ANC1 MUX", "ADC3", "ADC3"},
2292 {"ANC1 MUX", "ADC4", "ADC4"},
2293 {"ANC2 MUX", "ADC1", "ADC1"},
2294 {"ANC2 MUX", "ADC2", "ADC2"},
2295 {"ANC2 MUX", "ADC3", "ADC3"},
2296 {"ANC2 MUX", "ADC4", "ADC4"},
2297
Bradley Rubine1d08622011-07-20 18:01:35 -07002298 {"ANC", NULL, "CDC_CONN"},
2299
Bradley Rubin229c6a52011-07-12 16:18:48 -07002300 {"DAC1", "Switch", "RX1 CHAIN"},
2301 {"HPHL DAC", "Switch", "RX1 CHAIN"},
Kiran Kandi8b3a8302011-09-27 16:13:28 -07002302 {"HPHR DAC", NULL, "RX2 CHAIN"},
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002303
Kiran Kandidb0a4b02011-08-23 09:32:09 -07002304 {"LINEOUT1", NULL, "LINEOUT1 PA"},
2305 {"LINEOUT2", NULL, "LINEOUT2 PA"},
2306 {"LINEOUT3", NULL, "LINEOUT3 PA"},
2307 {"LINEOUT4", NULL, "LINEOUT4 PA"},
2308 {"LINEOUT5", NULL, "LINEOUT5 PA"},
Bradley Rubin74a9b4a2011-06-13 15:03:43 -07002309
Kiran Kandidb0a4b02011-08-23 09:32:09 -07002310 {"LINEOUT1 PA", NULL, "LINEOUT1 DAC"},
2311 {"LINEOUT2 PA", NULL, "LINEOUT2 DAC"},
2312 {"LINEOUT3 PA", NULL, "LINEOUT3 DAC"},
2313 {"LINEOUT4 PA", NULL, "LINEOUT4 DAC"},
2314 {"LINEOUT5 PA", NULL, "LINEOUT5 DAC"},
Bradley Rubin74a9b4a2011-06-13 15:03:43 -07002315
Kiran Kandi8b3a8302011-09-27 16:13:28 -07002316 {"LINEOUT1 DAC", NULL, "RX3 MIX1"},
2317 {"LINEOUT5 DAC", NULL, "RX7 MIX1"},
2318
Bradley Rubin229c6a52011-07-12 16:18:48 -07002319 {"RX1 CHAIN", NULL, "RX1 MIX1"},
2320 {"RX2 CHAIN", NULL, "RX2 MIX1"},
2321 {"RX1 CHAIN", NULL, "ANC"},
2322 {"RX2 CHAIN", NULL, "ANC"},
Bradley Rubin74a9b4a2011-06-13 15:03:43 -07002323
Kiran Kandi6fae8bf2011-08-15 10:36:42 -07002324 {"CP", NULL, "RX_BIAS"},
2325 {"LINEOUT1 DAC", NULL, "RX_BIAS"},
2326 {"LINEOUT2 DAC", NULL, "RX_BIAS"},
2327 {"LINEOUT3 DAC", NULL, "RX_BIAS"},
2328 {"LINEOUT4 DAC", NULL, "RX_BIAS"},
Kiran Kandi8b3a8302011-09-27 16:13:28 -07002329 {"LINEOUT5 DAC", NULL, "RX_BIAS"},
Kiran Kandi6fae8bf2011-08-15 10:36:42 -07002330
Bradley Rubin229c6a52011-07-12 16:18:48 -07002331 {"RX1 MIX1", NULL, "RX1 MIX1 INP1"},
2332 {"RX1 MIX1", NULL, "RX1 MIX1 INP2"},
2333 {"RX2 MIX1", NULL, "RX2 MIX1 INP1"},
2334 {"RX2 MIX1", NULL, "RX2 MIX1 INP2"},
Bradley Rubin74a9b4a2011-06-13 15:03:43 -07002335 {"RX3 MIX1", NULL, "RX3 MIX1 INP1"},
2336 {"RX3 MIX1", NULL, "RX3 MIX1 INP2"},
2337 {"RX4 MIX1", NULL, "RX4 MIX1 INP1"},
2338 {"RX4 MIX1", NULL, "RX4 MIX1 INP2"},
2339 {"RX5 MIX1", NULL, "RX5 MIX1 INP1"},
2340 {"RX5 MIX1", NULL, "RX5 MIX1 INP2"},
2341 {"RX6 MIX1", NULL, "RX6 MIX1 INP1"},
2342 {"RX6 MIX1", NULL, "RX6 MIX1 INP2"},
Bhalchandra Gajare0a8ad172011-08-12 13:32:22 -07002343 {"RX7 MIX1", NULL, "RX7 MIX1 INP1"},
2344 {"RX7 MIX1", NULL, "RX7 MIX1 INP2"},
Bradley Rubin74a9b4a2011-06-13 15:03:43 -07002345
Bradley Rubin229c6a52011-07-12 16:18:48 -07002346 {"RX1 MIX1 INP1", "RX1", "SLIM RX1"},
2347 {"RX1 MIX1 INP1", "RX2", "SLIM RX2"},
Santosh Mardie15e2302011-11-15 10:39:23 +05302348 {"RX1 MIX1 INP1", "RX3", "SLIM RX3"},
2349 {"RX1 MIX1 INP1", "RX4", "SLIM RX4"},
Bradley Rubin229c6a52011-07-12 16:18:48 -07002350 {"RX1 MIX1 INP1", "IIR1", "IIR1"},
2351 {"RX1 MIX1 INP2", "RX1", "SLIM RX1"},
2352 {"RX1 MIX1 INP2", "RX2", "SLIM RX2"},
Santosh Mardie15e2302011-11-15 10:39:23 +05302353 {"RX1 MIX1 INP2", "RX3", "SLIM RX3"},
2354 {"RX1 MIX1 INP2", "RX4", "SLIM RX4"},
Bradley Rubin229c6a52011-07-12 16:18:48 -07002355 {"RX1 MIX1 INP2", "IIR1", "IIR1"},
2356 {"RX2 MIX1 INP1", "RX1", "SLIM RX1"},
2357 {"RX2 MIX1 INP1", "RX2", "SLIM RX2"},
Santosh Mardie15e2302011-11-15 10:39:23 +05302358 {"RX2 MIX1 INP1", "RX3", "SLIM RX3"},
2359 {"RX2 MIX1 INP1", "RX4", "SLIM RX4"},
Patrick Lai16261e82011-09-30 13:25:52 -07002360 {"RX2 MIX1 INP1", "IIR1", "IIR1"},
Bradley Rubin229c6a52011-07-12 16:18:48 -07002361 {"RX2 MIX1 INP2", "RX1", "SLIM RX1"},
2362 {"RX2 MIX1 INP2", "RX2", "SLIM RX2"},
Santosh Mardie15e2302011-11-15 10:39:23 +05302363 {"RX2 MIX1 INP2", "RX3", "SLIM RX3"},
2364 {"RX2 MIX1 INP2", "RX4", "SLIM RX4"},
Patrick Lai16261e82011-09-30 13:25:52 -07002365 {"RX2 MIX1 INP2", "IIR1", "IIR1"},
Bradley Rubin229c6a52011-07-12 16:18:48 -07002366 {"RX3 MIX1 INP1", "RX1", "SLIM RX1"},
2367 {"RX3 MIX1 INP1", "RX2", "SLIM RX2"},
Santosh Mardie15e2302011-11-15 10:39:23 +05302368 {"RX3 MIX1 INP1", "RX3", "SLIM RX3"},
2369 {"RX3 MIX1 INP1", "RX4", "SLIM RX4"},
Patrick Lai16261e82011-09-30 13:25:52 -07002370 {"RX3 MIX1 INP1", "IIR1", "IIR1"},
Bradley Rubin229c6a52011-07-12 16:18:48 -07002371 {"RX3 MIX1 INP2", "RX1", "SLIM RX1"},
2372 {"RX3 MIX1 INP2", "RX2", "SLIM RX2"},
Santosh Mardie15e2302011-11-15 10:39:23 +05302373 {"RX3 MIX1 INP2", "RX3", "SLIM RX3"},
2374 {"RX3 MIX1 INP2", "RX4", "SLIM RX4"},
Patrick Lai16261e82011-09-30 13:25:52 -07002375 {"RX3 MIX1 INP2", "IIR1", "IIR1"},
Bradley Rubin229c6a52011-07-12 16:18:48 -07002376 {"RX4 MIX1 INP1", "RX1", "SLIM RX1"},
2377 {"RX4 MIX1 INP1", "RX2", "SLIM RX2"},
Santosh Mardie15e2302011-11-15 10:39:23 +05302378 {"RX4 MIX1 INP1", "RX3", "SLIM RX3"},
2379 {"RX4 MIX1 INP1", "RX4", "SLIM RX4"},
Patrick Lai16261e82011-09-30 13:25:52 -07002380 {"RX4 MIX1 INP1", "IIR1", "IIR1"},
Bradley Rubin229c6a52011-07-12 16:18:48 -07002381 {"RX4 MIX1 INP2", "RX1", "SLIM RX1"},
2382 {"RX4 MIX1 INP2", "RX2", "SLIM RX2"},
Santosh Mardie15e2302011-11-15 10:39:23 +05302383 {"RX4 MIX1 INP2", "RX3", "SLIM RX3"},
2384 {"RX4 MIX1 INP2", "RX4", "SLIM RX4"},
Patrick Lai16261e82011-09-30 13:25:52 -07002385 {"RX4 MIX1 INP2", "IIR1", "IIR1"},
Bradley Rubin229c6a52011-07-12 16:18:48 -07002386 {"RX5 MIX1 INP1", "RX1", "SLIM RX1"},
2387 {"RX5 MIX1 INP1", "RX2", "SLIM RX2"},
Santosh Mardie15e2302011-11-15 10:39:23 +05302388 {"RX5 MIX1 INP1", "RX3", "SLIM RX3"},
2389 {"RX5 MIX1 INP1", "RX4", "SLIM RX4"},
Patrick Lai16261e82011-09-30 13:25:52 -07002390 {"RX5 MIX1 INP1", "IIR1", "IIR1"},
Bradley Rubin229c6a52011-07-12 16:18:48 -07002391 {"RX5 MIX1 INP2", "RX1", "SLIM RX1"},
2392 {"RX5 MIX1 INP2", "RX2", "SLIM RX2"},
Santosh Mardie15e2302011-11-15 10:39:23 +05302393 {"RX5 MIX1 INP2", "RX3", "SLIM RX3"},
2394 {"RX5 MIX1 INP2", "RX4", "SLIM RX4"},
Patrick Lai16261e82011-09-30 13:25:52 -07002395 {"RX5 MIX1 INP2", "IIR1", "IIR1"},
Bradley Rubin229c6a52011-07-12 16:18:48 -07002396 {"RX6 MIX1 INP1", "RX1", "SLIM RX1"},
2397 {"RX6 MIX1 INP1", "RX2", "SLIM RX2"},
Santosh Mardie15e2302011-11-15 10:39:23 +05302398 {"RX6 MIX1 INP1", "RX3", "SLIM RX3"},
2399 {"RX6 MIX1 INP1", "RX4", "SLIM RX4"},
Patrick Lai16261e82011-09-30 13:25:52 -07002400 {"RX6 MIX1 INP1", "IIR1", "IIR1"},
Bradley Rubin229c6a52011-07-12 16:18:48 -07002401 {"RX6 MIX1 INP2", "RX1", "SLIM RX1"},
2402 {"RX6 MIX1 INP2", "RX2", "SLIM RX2"},
Santosh Mardie15e2302011-11-15 10:39:23 +05302403 {"RX6 MIX1 INP2", "RX3", "SLIM RX3"},
2404 {"RX6 MIX1 INP2", "RX4", "SLIM RX4"},
Patrick Lai16261e82011-09-30 13:25:52 -07002405 {"RX6 MIX1 INP2", "IIR1", "IIR1"},
Bhalchandra Gajare0a8ad172011-08-12 13:32:22 -07002406 {"RX7 MIX1 INP1", "RX1", "SLIM RX1"},
2407 {"RX7 MIX1 INP1", "RX2", "SLIM RX2"},
Santosh Mardie15e2302011-11-15 10:39:23 +05302408 {"RX7 MIX1 INP1", "RX3", "SLIM RX3"},
2409 {"RX7 MIX1 INP1", "RX4", "SLIM RX4"},
Patrick Lai16261e82011-09-30 13:25:52 -07002410 {"RX7 MIX1 INP1", "IIR1", "IIR1"},
Bhalchandra Gajare0a8ad172011-08-12 13:32:22 -07002411 {"RX7 MIX1 INP2", "RX1", "SLIM RX1"},
2412 {"RX7 MIX1 INP2", "RX2", "SLIM RX2"},
Santosh Mardie15e2302011-11-15 10:39:23 +05302413 {"RX7 MIX1 INP2", "RX3", "SLIM RX3"},
2414 {"RX7 MIX1 INP2", "RX4", "SLIM RX4"},
Patrick Lai16261e82011-09-30 13:25:52 -07002415 {"RX7 MIX1 INP2", "IIR1", "IIR1"},
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002416
Bhalchandra Gajarecc6ffa02011-07-14 18:35:41 -07002417 /* Decimator Inputs */
Bhalchandra Gajarecc6ffa02011-07-14 18:35:41 -07002418 {"DEC1 MUX", "DMIC1", "DMIC1"},
Kiran Kandicf45f6a2011-07-17 21:10:19 -07002419 {"DEC1 MUX", "ADC6", "ADC6"},
Bradley Rubine1d08622011-07-20 18:01:35 -07002420 {"DEC1 MUX", NULL, "CDC_CONN"},
Kiran Kandicf45f6a2011-07-17 21:10:19 -07002421 {"DEC2 MUX", "DMIC2", "DMIC2"},
Bhalchandra Gajarecc6ffa02011-07-14 18:35:41 -07002422 {"DEC2 MUX", "ADC5", "ADC5"},
Bradley Rubine1d08622011-07-20 18:01:35 -07002423 {"DEC2 MUX", NULL, "CDC_CONN"},
Kiran Kandicf45f6a2011-07-17 21:10:19 -07002424 {"DEC3 MUX", "DMIC3", "DMIC3"},
Bhalchandra Gajarecc6ffa02011-07-14 18:35:41 -07002425 {"DEC3 MUX", "ADC4", "ADC4"},
Bradley Rubine1d08622011-07-20 18:01:35 -07002426 {"DEC3 MUX", NULL, "CDC_CONN"},
Bhalchandra Gajare7cf018e2011-08-11 18:58:32 -07002427 {"DEC4 MUX", "DMIC4", "DMIC4"},
Bhalchandra Gajarecc6ffa02011-07-14 18:35:41 -07002428 {"DEC4 MUX", "ADC3", "ADC3"},
Bradley Rubine1d08622011-07-20 18:01:35 -07002429 {"DEC4 MUX", NULL, "CDC_CONN"},
Bhalchandra Gajare7cf018e2011-08-11 18:58:32 -07002430 {"DEC5 MUX", "DMIC5", "DMIC5"},
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002431 {"DEC5 MUX", "ADC2", "ADC2"},
Bradley Rubine1d08622011-07-20 18:01:35 -07002432 {"DEC5 MUX", NULL, "CDC_CONN"},
Bhalchandra Gajare7cf018e2011-08-11 18:58:32 -07002433 {"DEC6 MUX", "DMIC6", "DMIC6"},
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002434 {"DEC6 MUX", "ADC1", "ADC1"},
Bradley Rubine1d08622011-07-20 18:01:35 -07002435 {"DEC6 MUX", NULL, "CDC_CONN"},
Bhalchandra Gajarecc6ffa02011-07-14 18:35:41 -07002436 {"DEC7 MUX", "DMIC1", "DMIC1"},
Kiran Kandicf45f6a2011-07-17 21:10:19 -07002437 {"DEC7 MUX", "ADC6", "ADC6"},
Bradley Rubine1d08622011-07-20 18:01:35 -07002438 {"DEC7 MUX", NULL, "CDC_CONN"},
Bhalchandra Gajarecc6ffa02011-07-14 18:35:41 -07002439 {"DEC8 MUX", "ADC5", "ADC5"},
Bradley Rubine1d08622011-07-20 18:01:35 -07002440 {"DEC8 MUX", NULL, "CDC_CONN"},
Bhalchandra Gajarecc6ffa02011-07-14 18:35:41 -07002441 {"DEC9 MUX", "ADC3", "ADC3"},
Bradley Rubine1d08622011-07-20 18:01:35 -07002442 {"DEC9 MUX", NULL, "CDC_CONN"},
Bhalchandra Gajarecc6ffa02011-07-14 18:35:41 -07002443 {"DEC10 MUX", "ADC4", "ADC4"},
Bradley Rubine1d08622011-07-20 18:01:35 -07002444 {"DEC10 MUX", NULL, "CDC_CONN"},
Bhalchandra Gajarecc6ffa02011-07-14 18:35:41 -07002445
2446 /* ADC Connections */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002447 {"ADC1", NULL, "AMIC1"},
2448 {"ADC2", NULL, "AMIC2"},
Bhalchandra Gajarecc6ffa02011-07-14 18:35:41 -07002449 {"ADC3", NULL, "AMIC3"},
2450 {"ADC4", NULL, "AMIC4"},
2451 {"ADC5", NULL, "AMIC5"},
2452 {"ADC6", NULL, "AMIC6"},
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002453
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002454 {"IIR1", NULL, "IIR1 INP1 MUX"},
Patrick Lai16261e82011-09-30 13:25:52 -07002455 {"IIR1 INP1 MUX", "DEC1", "DEC1 MUX"},
2456 {"IIR1 INP1 MUX", "DEC2", "DEC2 MUX"},
2457 {"IIR1 INP1 MUX", "DEC3", "DEC3 MUX"},
2458 {"IIR1 INP1 MUX", "DEC4", "DEC4 MUX"},
2459 {"IIR1 INP1 MUX", "DEC5", "DEC5 MUX"},
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002460 {"IIR1 INP1 MUX", "DEC6", "DEC6 MUX"},
Patrick Lai16261e82011-09-30 13:25:52 -07002461 {"IIR1 INP1 MUX", "DEC7", "DEC7 MUX"},
2462 {"IIR1 INP1 MUX", "DEC8", "DEC8 MUX"},
2463 {"IIR1 INP1 MUX", "DEC9", "DEC9 MUX"},
2464 {"IIR1 INP1 MUX", "DEC10", "DEC10 MUX"},
Bradley Rubin229c6a52011-07-12 16:18:48 -07002465
2466 {"MIC BIAS1 Internal1", NULL, "LDO_H"},
2467 {"MIC BIAS1 Internal2", NULL, "LDO_H"},
2468 {"MIC BIAS1 External", NULL, "LDO_H"},
2469 {"MIC BIAS2 Internal1", NULL, "LDO_H"},
2470 {"MIC BIAS2 Internal2", NULL, "LDO_H"},
2471 {"MIC BIAS2 Internal3", NULL, "LDO_H"},
2472 {"MIC BIAS2 External", NULL, "LDO_H"},
2473 {"MIC BIAS3 Internal1", NULL, "LDO_H"},
2474 {"MIC BIAS3 Internal2", NULL, "LDO_H"},
2475 {"MIC BIAS3 External", NULL, "LDO_H"},
2476 {"MIC BIAS4 External", NULL, "LDO_H"},
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002477};
2478
Kiran Kandi8b3a8302011-09-27 16:13:28 -07002479static const struct snd_soc_dapm_route tabla_1_x_lineout_2_to_4_map[] = {
2480
2481 {"RX4 DSM MUX", "DSM_INV", "RX3 MIX1"},
2482 {"RX4 DSM MUX", "CIC_OUT", "RX4 MIX1"},
2483
2484 {"LINEOUT2 DAC", NULL, "RX4 DSM MUX"},
2485
2486 {"LINEOUT3 DAC", NULL, "RX5 MIX1"},
2487 {"LINEOUT3 DAC GROUND", "Switch", "RX3 MIX1"},
2488 {"LINEOUT3 DAC", NULL, "LINEOUT3 DAC GROUND"},
2489
2490 {"RX6 DSM MUX", "DSM_INV", "RX5 MIX1"},
2491 {"RX6 DSM MUX", "CIC_OUT", "RX6 MIX1"},
2492
2493 {"LINEOUT4 DAC", NULL, "RX6 DSM MUX"},
2494 {"LINEOUT4 DAC GROUND", "Switch", "RX4 DSM MUX"},
2495 {"LINEOUT4 DAC", NULL, "LINEOUT4 DAC GROUND"},
2496};
2497
Kiran Kandi7a9fd902011-11-14 13:51:45 -08002498
2499static const struct snd_soc_dapm_route tabla_2_x_lineout_2_to_4_map[] = {
2500
2501 {"RX4 DSM MUX", "DSM_INV", "RX3 MIX1"},
2502 {"RX4 DSM MUX", "CIC_OUT", "RX4 MIX1"},
2503
2504 {"LINEOUT3 DAC", NULL, "RX4 DSM MUX"},
2505
2506 {"LINEOUT2 DAC", NULL, "RX5 MIX1"},
2507
2508 {"RX6 DSM MUX", "DSM_INV", "RX5 MIX1"},
2509 {"RX6 DSM MUX", "CIC_OUT", "RX6 MIX1"},
2510
2511 {"LINEOUT4 DAC", NULL, "RX6 DSM MUX"},
2512};
2513
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002514static int tabla_readable(struct snd_soc_codec *ssc, unsigned int reg)
2515{
2516 return tabla_reg_readable[reg];
2517}
2518
2519static int tabla_volatile(struct snd_soc_codec *ssc, unsigned int reg)
2520{
2521 /* Registers lower than 0x100 are top level registers which can be
2522 * written by the Tabla core driver.
2523 */
2524
2525 if ((reg >= TABLA_A_CDC_MBHC_EN_CTL) || (reg < 0x100))
2526 return 1;
2527
Ben Romberger1f045a72011-11-04 10:14:57 -07002528 /* IIR Coeff registers are not cacheable */
2529 if ((reg >= TABLA_A_CDC_IIR1_COEF_B1_CTL) &&
2530 (reg <= TABLA_A_CDC_IIR2_COEF_B5_CTL))
2531 return 1;
2532
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002533 return 0;
2534}
2535
2536#define TABLA_FORMATS (SNDRV_PCM_FMTBIT_S16_LE)
2537static int tabla_write(struct snd_soc_codec *codec, unsigned int reg,
2538 unsigned int value)
2539{
2540 int ret;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002541
2542 BUG_ON(reg > TABLA_MAX_REGISTER);
2543
2544 if (!tabla_volatile(codec, reg)) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002545 ret = snd_soc_cache_write(codec, reg, value);
2546 if (ret != 0)
2547 dev_err(codec->dev, "Cache write to %x failed: %d\n",
2548 reg, ret);
2549 }
2550
2551 return tabla_reg_write(codec->control_data, reg, value);
2552}
2553static unsigned int tabla_read(struct snd_soc_codec *codec,
2554 unsigned int reg)
2555{
2556 unsigned int val;
2557 int ret;
2558
2559 BUG_ON(reg > TABLA_MAX_REGISTER);
2560
2561 if (!tabla_volatile(codec, reg) && tabla_readable(codec, reg) &&
2562 reg < codec->driver->reg_cache_size) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002563 ret = snd_soc_cache_read(codec, reg, &val);
2564 if (ret >= 0) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002565 return val;
2566 } else
2567 dev_err(codec->dev, "Cache read from %x failed: %d\n",
2568 reg, ret);
2569 }
2570
2571 val = tabla_reg_read(codec->control_data, reg);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002572 return val;
2573}
2574
2575static void tabla_codec_enable_audio_mode_bandgap(struct snd_soc_codec *codec)
2576{
2577 snd_soc_write(codec, TABLA_A_BIAS_REF_CTL, 0x1C);
2578 snd_soc_update_bits(codec, TABLA_A_BIAS_CENTRAL_BG_CTL, 0x80,
2579 0x80);
2580 snd_soc_update_bits(codec, TABLA_A_BIAS_CENTRAL_BG_CTL, 0x04,
2581 0x04);
2582 snd_soc_update_bits(codec, TABLA_A_BIAS_CENTRAL_BG_CTL, 0x01,
2583 0x01);
2584 usleep_range(1000, 1000);
2585 snd_soc_update_bits(codec, TABLA_A_BIAS_CENTRAL_BG_CTL, 0x80,
2586 0x00);
2587}
2588
2589static void tabla_codec_enable_bandgap(struct snd_soc_codec *codec,
2590 enum tabla_bandgap_type choice)
2591{
2592 struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
2593
2594 /* TODO lock resources accessed by audio streams and threaded
2595 * interrupt handlers
2596 */
2597
2598 pr_debug("%s, choice is %d, current is %d\n", __func__, choice,
2599 tabla->bandgap_type);
2600
2601 if (tabla->bandgap_type == choice)
2602 return;
2603
2604 if ((tabla->bandgap_type == TABLA_BANDGAP_OFF) &&
2605 (choice == TABLA_BANDGAP_AUDIO_MODE)) {
2606 tabla_codec_enable_audio_mode_bandgap(codec);
2607 } else if ((tabla->bandgap_type == TABLA_BANDGAP_AUDIO_MODE) &&
2608 (choice == TABLA_BANDGAP_MBHC_MODE)) {
2609 snd_soc_update_bits(codec, TABLA_A_BIAS_CENTRAL_BG_CTL, 0x2,
2610 0x2);
2611 snd_soc_update_bits(codec, TABLA_A_BIAS_CENTRAL_BG_CTL, 0x80,
2612 0x80);
2613 snd_soc_update_bits(codec, TABLA_A_BIAS_CENTRAL_BG_CTL, 0x4,
2614 0x4);
2615 usleep_range(1000, 1000);
2616 snd_soc_update_bits(codec, TABLA_A_BIAS_CENTRAL_BG_CTL, 0x80,
2617 0x00);
2618 } else if ((tabla->bandgap_type == TABLA_BANDGAP_MBHC_MODE) &&
2619 (choice == TABLA_BANDGAP_AUDIO_MODE)) {
2620 snd_soc_write(codec, TABLA_A_BIAS_CENTRAL_BG_CTL, 0x00);
2621 usleep_range(100, 100);
2622 tabla_codec_enable_audio_mode_bandgap(codec);
2623 } else if (choice == TABLA_BANDGAP_OFF) {
2624 snd_soc_write(codec, TABLA_A_BIAS_CENTRAL_BG_CTL, 0x00);
2625 } else {
2626 pr_err("%s: Error, Invalid bandgap settings\n", __func__);
2627 }
2628 tabla->bandgap_type = choice;
2629}
2630
2631static int tabla_codec_enable_config_mode(struct snd_soc_codec *codec,
2632 int enable)
2633{
2634 struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
2635
2636 if (enable) {
2637 snd_soc_update_bits(codec, TABLA_A_CONFIG_MODE_FREQ, 0x10, 0);
2638 snd_soc_write(codec, TABLA_A_BIAS_CONFIG_MODE_BG_CTL, 0x17);
2639 usleep_range(5, 5);
2640 snd_soc_update_bits(codec, TABLA_A_CONFIG_MODE_FREQ, 0x80,
2641 0x80);
2642 snd_soc_update_bits(codec, TABLA_A_CONFIG_MODE_TEST, 0x80,
2643 0x80);
2644 usleep_range(10, 10);
2645 snd_soc_update_bits(codec, TABLA_A_CONFIG_MODE_TEST, 0x80, 0);
2646 usleep_range(20, 20);
2647 snd_soc_update_bits(codec, TABLA_A_CLK_BUFF_EN1, 0x08, 0x08);
2648 } else {
2649 snd_soc_update_bits(codec, TABLA_A_BIAS_CONFIG_MODE_BG_CTL, 0x1,
2650 0);
2651 snd_soc_update_bits(codec, TABLA_A_CONFIG_MODE_FREQ, 0x80, 0);
2652 }
2653 tabla->config_mode_active = enable ? true : false;
2654
2655 return 0;
2656}
2657
2658static int tabla_codec_enable_clock_block(struct snd_soc_codec *codec,
2659 int config_mode)
2660{
2661 struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
2662
2663 pr_debug("%s\n", __func__);
2664
2665 if (config_mode) {
2666 tabla_codec_enable_config_mode(codec, 1);
2667 snd_soc_write(codec, TABLA_A_CLK_BUFF_EN2, 0x00);
2668 snd_soc_write(codec, TABLA_A_CLK_BUFF_EN2, 0x02);
2669 snd_soc_write(codec, TABLA_A_CLK_BUFF_EN1, 0x0D);
2670 usleep_range(1000, 1000);
2671 } else
2672 snd_soc_update_bits(codec, TABLA_A_CLK_BUFF_EN1, 0x08, 0x00);
2673
2674 if (!config_mode && tabla->mbhc_polling_active) {
2675 snd_soc_write(codec, TABLA_A_CLK_BUFF_EN2, 0x02);
2676 tabla_codec_enable_config_mode(codec, 0);
2677
2678 }
2679
2680 snd_soc_update_bits(codec, TABLA_A_CLK_BUFF_EN1, 0x05, 0x05);
2681 snd_soc_update_bits(codec, TABLA_A_CLK_BUFF_EN2, 0x02, 0x00);
2682 snd_soc_update_bits(codec, TABLA_A_CLK_BUFF_EN2, 0x04, 0x04);
2683 snd_soc_update_bits(codec, TABLA_A_CDC_CLK_MCLK_CTL, 0x01, 0x01);
2684 usleep_range(50, 50);
2685 tabla->clock_active = true;
2686 return 0;
2687}
2688static void tabla_codec_disable_clock_block(struct snd_soc_codec *codec)
2689{
2690 struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
2691 pr_debug("%s\n", __func__);
2692 snd_soc_update_bits(codec, TABLA_A_CLK_BUFF_EN2, 0x04, 0x00);
2693 ndelay(160);
2694 snd_soc_update_bits(codec, TABLA_A_CLK_BUFF_EN2, 0x02, 0x02);
2695 snd_soc_update_bits(codec, TABLA_A_CLK_BUFF_EN1, 0x05, 0x00);
2696 tabla->clock_active = false;
2697}
2698
Bradley Rubincb1e2732011-06-23 16:49:20 -07002699static void tabla_codec_calibrate_hs_polling(struct snd_soc_codec *codec)
2700{
Joonwoo Park0976d012011-12-22 11:48:18 -08002701 u8 *n_cic;
2702 struct tabla_mbhc_btn_detect_cfg *btn_det;
2703 struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
Bradley Rubincb1e2732011-06-23 16:49:20 -07002704
Joonwoo Park0976d012011-12-22 11:48:18 -08002705 btn_det = TABLA_MBHC_CAL_BTN_DET_PTR(tabla->calibration);
Bradley Rubincb1e2732011-06-23 16:49:20 -07002706
Joonwoo Park0976d012011-12-22 11:48:18 -08002707 snd_soc_write(codec, TABLA_A_CDC_MBHC_VOLT_B1_CTL,
2708 tabla->mbhc_data.v_ins_hu & 0xFF);
2709 snd_soc_write(codec, TABLA_A_CDC_MBHC_VOLT_B2_CTL,
2710 (tabla->mbhc_data.v_ins_hu >> 8) & 0xFF);
Bradley Rubincb1e2732011-06-23 16:49:20 -07002711
Joonwoo Park0976d012011-12-22 11:48:18 -08002712 snd_soc_write(codec, TABLA_A_CDC_MBHC_VOLT_B3_CTL,
2713 tabla->mbhc_data.v_b1_hu & 0xFF);
2714 snd_soc_write(codec, TABLA_A_CDC_MBHC_VOLT_B4_CTL,
2715 (tabla->mbhc_data.v_b1_hu >> 8) & 0xFF);
2716
2717 snd_soc_write(codec, TABLA_A_CDC_MBHC_VOLT_B5_CTL,
2718 tabla->mbhc_data.v_b1_h & 0xFF);
2719 snd_soc_write(codec, TABLA_A_CDC_MBHC_VOLT_B6_CTL,
2720 (tabla->mbhc_data.v_b1_h >> 8) & 0xFF);
2721
2722 snd_soc_write(codec, TABLA_A_CDC_MBHC_VOLT_B9_CTL,
2723 tabla->mbhc_data.v_brh & 0xFF);
2724 snd_soc_write(codec, TABLA_A_CDC_MBHC_VOLT_B10_CTL,
2725 (tabla->mbhc_data.v_brh >> 8) & 0xFF);
2726
2727 snd_soc_write(codec, TABLA_A_CDC_MBHC_VOLT_B11_CTL,
2728 tabla->mbhc_data.v_brl & 0xFF);
2729 snd_soc_write(codec, TABLA_A_CDC_MBHC_VOLT_B12_CTL,
2730 (tabla->mbhc_data.v_brl >> 8) & 0xFF);
2731
2732 snd_soc_write(codec, TABLA_A_CDC_MBHC_TIMER_B1_CTL,
2733 tabla->mbhc_data.nready);
2734 snd_soc_write(codec, TABLA_A_CDC_MBHC_TIMER_B2_CTL,
2735 tabla->mbhc_data.npoll);
2736 snd_soc_write(codec, TABLA_A_CDC_MBHC_TIMER_B3_CTL,
2737 tabla->mbhc_data.nbounce_wait);
2738
2739 n_cic = tabla_mbhc_cal_btn_det_mp(btn_det, TABLA_BTN_DET_N_CIC);
2740 snd_soc_write(codec, TABLA_A_CDC_MBHC_TIMER_B6_CTL, n_cic[0]);
Bradley Rubincb1e2732011-06-23 16:49:20 -07002741}
2742
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002743static int tabla_startup(struct snd_pcm_substream *substream,
2744 struct snd_soc_dai *dai)
2745{
Kiran Kandi6fae8bf2011-08-15 10:36:42 -07002746 pr_debug("%s(): substream = %s stream = %d\n" , __func__,
2747 substream->name, substream->stream);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002748
Kiran Kandi6fae8bf2011-08-15 10:36:42 -07002749 return 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002750}
2751
2752static void tabla_shutdown(struct snd_pcm_substream *substream,
2753 struct snd_soc_dai *dai)
2754{
Kiran Kandi6fae8bf2011-08-15 10:36:42 -07002755 pr_debug("%s(): substream = %s stream = %d\n" , __func__,
2756 substream->name, substream->stream);
2757}
2758
2759int tabla_mclk_enable(struct snd_soc_codec *codec, int mclk_enable)
2760{
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002761 struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
2762
Kiran Kandi6fae8bf2011-08-15 10:36:42 -07002763 pr_debug("%s() mclk_enable = %u\n", __func__, mclk_enable);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002764
Kiran Kandi6fae8bf2011-08-15 10:36:42 -07002765 if (mclk_enable) {
2766 tabla->mclk_enabled = true;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002767
Kiran Kandi6fae8bf2011-08-15 10:36:42 -07002768 if (tabla->mbhc_polling_active && (tabla->mclk_enabled)) {
Bradley Rubincb1e2732011-06-23 16:49:20 -07002769 tabla_codec_pause_hs_polling(codec);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002770 tabla_codec_enable_bandgap(codec,
Kiran Kandi6fae8bf2011-08-15 10:36:42 -07002771 TABLA_BANDGAP_AUDIO_MODE);
2772 tabla_codec_enable_clock_block(codec, 0);
Bradley Rubincb1e2732011-06-23 16:49:20 -07002773 tabla_codec_calibrate_hs_polling(codec);
2774 tabla_codec_start_hs_polling(codec);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002775 }
Kiran Kandi6fae8bf2011-08-15 10:36:42 -07002776 } else {
2777
2778 if (!tabla->mclk_enabled) {
2779 pr_err("Error, MCLK already diabled\n");
2780 return -EINVAL;
2781 }
2782 tabla->mclk_enabled = false;
2783
2784 if (tabla->mbhc_polling_active) {
2785 if (!tabla->mclk_enabled) {
2786 tabla_codec_pause_hs_polling(codec);
2787 tabla_codec_enable_bandgap(codec,
2788 TABLA_BANDGAP_MBHC_MODE);
2789 tabla_enable_rx_bias(codec, 1);
2790 tabla_codec_enable_clock_block(codec, 1);
2791 tabla_codec_calibrate_hs_polling(codec);
2792 tabla_codec_start_hs_polling(codec);
2793 }
2794 snd_soc_update_bits(codec, TABLA_A_CLK_BUFF_EN1,
2795 0x05, 0x01);
2796 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002797 }
Kiran Kandi6fae8bf2011-08-15 10:36:42 -07002798 return 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002799}
2800
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002801static int tabla_set_dai_sysclk(struct snd_soc_dai *dai,
2802 int clk_id, unsigned int freq, int dir)
2803{
2804 pr_debug("%s\n", __func__);
2805 return 0;
2806}
2807
2808static int tabla_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
2809{
Santosh Mardie15e2302011-11-15 10:39:23 +05302810 u8 val = 0;
2811 struct tabla_priv *tabla = snd_soc_codec_get_drvdata(dai->codec);
2812
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002813 pr_debug("%s\n", __func__);
Santosh Mardie15e2302011-11-15 10:39:23 +05302814 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
2815 case SND_SOC_DAIFMT_CBS_CFS:
2816 /* CPU is master */
2817 if (tabla->intf_type == TABLA_INTERFACE_TYPE_I2C) {
2818 if (dai->id == TABLA_TX_DAI_ID)
2819 snd_soc_update_bits(dai->codec,
2820 TABLA_A_CDC_CLK_TX_I2S_CTL,
2821 TABLA_I2S_MASTER_MODE_MASK, 0);
2822 else if (dai->id == TABLA_RX_DAI_ID)
2823 snd_soc_update_bits(dai->codec,
2824 TABLA_A_CDC_CLK_RX_I2S_CTL,
2825 TABLA_I2S_MASTER_MODE_MASK, 0);
2826 }
2827 break;
2828 case SND_SOC_DAIFMT_CBM_CFM:
2829 /* CPU is slave */
2830 if (tabla->intf_type == TABLA_INTERFACE_TYPE_I2C) {
2831 val = TABLA_I2S_MASTER_MODE_MASK;
2832 if (dai->id == TABLA_TX_DAI_ID)
2833 snd_soc_update_bits(dai->codec,
2834 TABLA_A_CDC_CLK_TX_I2S_CTL, val, val);
2835 else if (dai->id == TABLA_RX_DAI_ID)
2836 snd_soc_update_bits(dai->codec,
2837 TABLA_A_CDC_CLK_RX_I2S_CTL, val, val);
2838 }
2839 break;
2840 default:
2841 return -EINVAL;
2842 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002843 return 0;
2844}
2845
2846static int tabla_hw_params(struct snd_pcm_substream *substream,
2847 struct snd_pcm_hw_params *params,
2848 struct snd_soc_dai *dai)
2849{
Bhalchandra Gajare9a901fd2011-08-01 10:07:15 -07002850 struct snd_soc_codec *codec = dai->codec;
Santosh Mardie15e2302011-11-15 10:39:23 +05302851 struct tabla_priv *tabla = snd_soc_codec_get_drvdata(dai->codec);
Bhalchandra Gajare038bf3a2011-09-02 15:32:30 -07002852 u8 path, shift;
2853 u16 tx_fs_reg, rx_fs_reg;
Bhalchandra Gajare9a901fd2011-08-01 10:07:15 -07002854 u8 tx_fs_rate, rx_fs_rate, rx_state, tx_state;
2855
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002856 pr_debug("%s: DAI-ID %x\n", __func__, dai->id);
Bhalchandra Gajare9a901fd2011-08-01 10:07:15 -07002857
2858 switch (params_rate(params)) {
2859 case 8000:
2860 tx_fs_rate = 0x00;
2861 rx_fs_rate = 0x00;
2862 break;
2863 case 16000:
2864 tx_fs_rate = 0x01;
2865 rx_fs_rate = 0x20;
2866 break;
2867 case 32000:
2868 tx_fs_rate = 0x02;
2869 rx_fs_rate = 0x40;
2870 break;
2871 case 48000:
2872 tx_fs_rate = 0x03;
2873 rx_fs_rate = 0x60;
2874 break;
2875 default:
2876 pr_err("%s: Invalid sampling rate %d\n", __func__,
2877 params_rate(params));
2878 return -EINVAL;
2879 }
2880
2881
2882 /**
2883 * If current dai is a tx dai, set sample rate to
2884 * all the txfe paths that are currently not active
2885 */
2886 if (dai->id == TABLA_TX_DAI_ID) {
2887
2888 tx_state = snd_soc_read(codec,
2889 TABLA_A_CDC_CLK_TX_CLK_EN_B1_CTL);
2890
2891 for (path = 1, shift = 0;
2892 path <= NUM_DECIMATORS; path++, shift++) {
2893
2894 if (path == BITS_PER_REG + 1) {
2895 shift = 0;
2896 tx_state = snd_soc_read(codec,
2897 TABLA_A_CDC_CLK_TX_CLK_EN_B2_CTL);
2898 }
2899
2900 if (!(tx_state & (1 << shift))) {
2901 tx_fs_reg = TABLA_A_CDC_TX1_CLK_FS_CTL
2902 + (BITS_PER_REG*(path-1));
2903 snd_soc_update_bits(codec, tx_fs_reg,
2904 0x03, tx_fs_rate);
2905 }
2906 }
Santosh Mardie15e2302011-11-15 10:39:23 +05302907 if (tabla->intf_type == TABLA_INTERFACE_TYPE_I2C) {
2908 switch (params_format(params)) {
2909 case SNDRV_PCM_FORMAT_S16_LE:
2910 snd_soc_update_bits(codec,
2911 TABLA_A_CDC_CLK_TX_I2S_CTL,
2912 0x20, 0x20);
2913 break;
2914 case SNDRV_PCM_FORMAT_S32_LE:
2915 snd_soc_update_bits(codec,
2916 TABLA_A_CDC_CLK_TX_I2S_CTL,
2917 0x20, 0x00);
2918 break;
2919 default:
2920 pr_err("invalid format\n");
2921 break;
2922 }
2923 snd_soc_update_bits(codec, TABLA_A_CDC_CLK_TX_I2S_CTL,
2924 0x03, tx_fs_rate);
2925 }
Bhalchandra Gajare9a901fd2011-08-01 10:07:15 -07002926 }
2927
2928 /**
2929 * TODO: Need to handle case where same RX chain takes 2 or more inputs
2930 * with varying sample rates
2931 */
2932
2933 /**
2934 * If current dai is a rx dai, set sample rate to
2935 * all the rx paths that are currently not active
2936 */
2937 if (dai->id == TABLA_RX_DAI_ID) {
2938
2939 rx_state = snd_soc_read(codec,
2940 TABLA_A_CDC_CLK_RX_B1_CTL);
2941
2942 for (path = 1, shift = 0;
2943 path <= NUM_INTERPOLATORS; path++, shift++) {
2944
2945 if (!(rx_state & (1 << shift))) {
2946 rx_fs_reg = TABLA_A_CDC_RX1_B5_CTL
2947 + (BITS_PER_REG*(path-1));
2948 snd_soc_update_bits(codec, rx_fs_reg,
2949 0xE0, rx_fs_rate);
2950 }
2951 }
Santosh Mardie15e2302011-11-15 10:39:23 +05302952 if (tabla->intf_type == TABLA_INTERFACE_TYPE_I2C) {
2953 switch (params_format(params)) {
2954 case SNDRV_PCM_FORMAT_S16_LE:
2955 snd_soc_update_bits(codec,
2956 TABLA_A_CDC_CLK_RX_I2S_CTL,
2957 0x20, 0x20);
2958 break;
2959 case SNDRV_PCM_FORMAT_S32_LE:
2960 snd_soc_update_bits(codec,
2961 TABLA_A_CDC_CLK_RX_I2S_CTL,
2962 0x20, 0x00);
2963 break;
2964 default:
2965 pr_err("invalid format\n");
2966 break;
2967 }
2968 snd_soc_update_bits(codec, TABLA_A_CDC_CLK_RX_I2S_CTL,
2969 0x03, (rx_fs_rate >> 0x05));
2970 }
Bhalchandra Gajare9a901fd2011-08-01 10:07:15 -07002971 }
2972
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002973 return 0;
2974}
2975
2976static struct snd_soc_dai_ops tabla_dai_ops = {
2977 .startup = tabla_startup,
2978 .shutdown = tabla_shutdown,
2979 .hw_params = tabla_hw_params,
2980 .set_sysclk = tabla_set_dai_sysclk,
2981 .set_fmt = tabla_set_dai_fmt,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002982};
2983
2984static struct snd_soc_dai_driver tabla_dai[] = {
2985 {
2986 .name = "tabla_rx1",
2987 .id = 1,
2988 .playback = {
2989 .stream_name = "AIF1 Playback",
Bhalchandra Gajare9a901fd2011-08-01 10:07:15 -07002990 .rates = WCD9310_RATES,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002991 .formats = TABLA_FORMATS,
2992 .rate_max = 48000,
2993 .rate_min = 8000,
2994 .channels_min = 1,
Kiran Kandi3426e512011-09-13 22:50:10 -07002995 .channels_max = 4,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002996 },
2997 .ops = &tabla_dai_ops,
2998 },
2999 {
3000 .name = "tabla_tx1",
3001 .id = 2,
3002 .capture = {
3003 .stream_name = "AIF1 Capture",
Bhalchandra Gajare9a901fd2011-08-01 10:07:15 -07003004 .rates = WCD9310_RATES,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003005 .formats = TABLA_FORMATS,
3006 .rate_max = 48000,
3007 .rate_min = 8000,
3008 .channels_min = 1,
3009 .channels_max = 2,
3010 },
3011 .ops = &tabla_dai_ops,
3012 },
3013};
Santosh Mardie15e2302011-11-15 10:39:23 +05303014
3015static struct snd_soc_dai_driver tabla_i2s_dai[] = {
3016 {
3017 .name = "tabla_i2s_rx1",
3018 .id = 1,
3019 .playback = {
3020 .stream_name = "AIF1 Playback",
3021 .rates = WCD9310_RATES,
3022 .formats = TABLA_FORMATS,
3023 .rate_max = 48000,
3024 .rate_min = 8000,
3025 .channels_min = 1,
3026 .channels_max = 4,
3027 },
3028 .ops = &tabla_dai_ops,
3029 },
3030 {
3031 .name = "tabla_i2s_tx1",
3032 .id = 2,
3033 .capture = {
3034 .stream_name = "AIF1 Capture",
3035 .rates = WCD9310_RATES,
3036 .formats = TABLA_FORMATS,
3037 .rate_max = 48000,
3038 .rate_min = 8000,
3039 .channels_min = 1,
3040 .channels_max = 4,
3041 },
3042 .ops = &tabla_dai_ops,
3043 },
3044};
Bradley Rubin89ffd0a2011-07-21 16:04:06 -07003045static short tabla_codec_read_sta_result(struct snd_soc_codec *codec)
Bradley Rubincb1e2732011-06-23 16:49:20 -07003046{
3047 u8 bias_msb, bias_lsb;
3048 short bias_value;
3049
Bradley Rubin89ffd0a2011-07-21 16:04:06 -07003050 bias_msb = snd_soc_read(codec, TABLA_A_CDC_MBHC_B3_STATUS);
3051 bias_lsb = snd_soc_read(codec, TABLA_A_CDC_MBHC_B2_STATUS);
3052 bias_value = (bias_msb << 8) | bias_lsb;
3053 return bias_value;
3054}
3055
3056static short tabla_codec_read_dce_result(struct snd_soc_codec *codec)
3057{
3058 u8 bias_msb, bias_lsb;
3059 short bias_value;
3060
3061 bias_msb = snd_soc_read(codec, TABLA_A_CDC_MBHC_B5_STATUS);
3062 bias_lsb = snd_soc_read(codec, TABLA_A_CDC_MBHC_B4_STATUS);
3063 bias_value = (bias_msb << 8) | bias_lsb;
3064 return bias_value;
3065}
3066
Joonwoo Park0976d012011-12-22 11:48:18 -08003067static short tabla_codec_sta_dce(struct snd_soc_codec *codec, int dce)
Bradley Rubin89ffd0a2011-07-21 16:04:06 -07003068{
Joonwoo Park0976d012011-12-22 11:48:18 -08003069 struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
Bradley Rubin89ffd0a2011-07-21 16:04:06 -07003070 short bias_value;
3071
Joonwoo Park925914c2012-01-05 13:35:18 -08003072 /* Turn on the override */
3073 snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_B1_CTL, 0x4, 0x4);
Bradley Rubincb1e2732011-06-23 16:49:20 -07003074 if (dce) {
Bradley Rubin89ffd0a2011-07-21 16:04:06 -07003075 snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_CLK_CTL, 0x8, 0x8);
3076 snd_soc_write(codec, TABLA_A_CDC_MBHC_EN_CTL, 0x4);
3077 snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_CLK_CTL, 0x8, 0x0);
3078 snd_soc_write(codec, TABLA_A_CDC_MBHC_EN_CTL, 0x4);
Joonwoo Park0976d012011-12-22 11:48:18 -08003079 usleep_range(tabla->mbhc_data.t_dce,
3080 tabla->mbhc_data.t_dce);
Bradley Rubin89ffd0a2011-07-21 16:04:06 -07003081 bias_value = tabla_codec_read_dce_result(codec);
Bradley Rubincb1e2732011-06-23 16:49:20 -07003082 } else {
Bradley Rubin89ffd0a2011-07-21 16:04:06 -07003083 snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_CLK_CTL, 0x8, 0x8);
Bradley Rubincb1e2732011-06-23 16:49:20 -07003084 snd_soc_write(codec, TABLA_A_CDC_MBHC_EN_CTL, 0x2);
3085 snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_CLK_CTL, 0x8, 0x0);
Bradley Rubin89ffd0a2011-07-21 16:04:06 -07003086 usleep_range(50, 50);
Joonwoo Park0976d012011-12-22 11:48:18 -08003087 snd_soc_write(codec, TABLA_A_CDC_MBHC_EN_CTL, 0x2);
3088 usleep_range(tabla->mbhc_data.t_sta,
3089 tabla->mbhc_data.t_sta);
Bradley Rubin89ffd0a2011-07-21 16:04:06 -07003090 bias_value = tabla_codec_read_sta_result(codec);
3091 snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_CLK_CTL, 0x8, 0x8);
3092 snd_soc_write(codec, TABLA_A_CDC_MBHC_EN_CTL, 0x0);
Bradley Rubincb1e2732011-06-23 16:49:20 -07003093 }
Joonwoo Park925914c2012-01-05 13:35:18 -08003094 /* Turn off the override after measuring mic voltage */
3095 snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_B1_CTL, 0x04, 0x00);
Bradley Rubincb1e2732011-06-23 16:49:20 -07003096
Joonwoo Park0976d012011-12-22 11:48:18 -08003097 pr_debug("read microphone bias value %04x\n", bias_value);
Bradley Rubincb1e2732011-06-23 16:49:20 -07003098 return bias_value;
3099}
3100
Bhalchandra Gajare343cbb02011-09-07 18:58:19 -07003101static short tabla_codec_setup_hs_polling(struct snd_soc_codec *codec)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003102{
3103 struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
Bhalchandra Gajare343cbb02011-09-07 18:58:19 -07003104 short bias_value;
Bhalchandra Gajare19d9c132011-11-18 14:57:08 -08003105 u8 cfilt_mode;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003106
Joonwoo Park0976d012011-12-22 11:48:18 -08003107 if (!tabla->calibration) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003108 pr_err("Error, no tabla calibration\n");
Bradley Rubincb1e2732011-06-23 16:49:20 -07003109 return -ENODEV;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003110 }
3111
3112 tabla->mbhc_polling_active = true;
3113
Kiran Kandi6fae8bf2011-08-15 10:36:42 -07003114 if (!tabla->mclk_enabled) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003115 tabla_codec_enable_bandgap(codec, TABLA_BANDGAP_MBHC_MODE);
Kiran Kandi6fae8bf2011-08-15 10:36:42 -07003116 tabla_enable_rx_bias(codec, 1);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003117 tabla_codec_enable_clock_block(codec, 1);
3118 }
3119
3120 snd_soc_update_bits(codec, TABLA_A_CLK_BUFF_EN1, 0x05, 0x01);
3121
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003122 snd_soc_update_bits(codec, TABLA_A_TX_COM_BIAS, 0xE0, 0xE0);
3123
Bhalchandra Gajare19d9c132011-11-18 14:57:08 -08003124 /* Make sure CFILT is in fast mode, save current mode */
Joonwoo Parkf4267c22012-01-10 13:25:24 -08003125 cfilt_mode = snd_soc_read(codec, tabla->mbhc_bias_regs.cfilt_ctl);
3126 snd_soc_update_bits(codec, tabla->mbhc_bias_regs.cfilt_ctl, 0x70, 0x00);
Patrick Lai3043fba2011-08-01 14:15:57 -07003127
Joonwoo Parkf4267c22012-01-10 13:25:24 -08003128 snd_soc_update_bits(codec, tabla->mbhc_bias_regs.ctl_reg, 0x1F, 0x16);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003129
3130 snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_CLK_CTL, 0x2, 0x2);
Bradley Rubincb1e2732011-06-23 16:49:20 -07003131 snd_soc_write(codec, TABLA_A_MBHC_SCALING_MUX_1, 0x84);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003132
3133 snd_soc_update_bits(codec, TABLA_A_TX_7_MBHC_EN, 0x80, 0x80);
3134 snd_soc_update_bits(codec, TABLA_A_TX_7_MBHC_EN, 0x1F, 0x1C);
3135 snd_soc_update_bits(codec, TABLA_A_TX_7_MBHC_TEST_CTL, 0x40, 0x40);
3136
3137 snd_soc_update_bits(codec, TABLA_A_TX_7_MBHC_EN, 0x80, 0x00);
Bradley Rubincb1e2732011-06-23 16:49:20 -07003138 snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_CLK_CTL, 0x8, 0x8);
3139 snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_CLK_CTL, 0x8, 0x00);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003140
Joonwoo Park925914c2012-01-05 13:35:18 -08003141 snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_B1_CTL, 0x2, 0x2);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003142 snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_CLK_CTL, 0x8, 0x8);
3143
Bradley Rubincb1e2732011-06-23 16:49:20 -07003144 tabla_codec_calibrate_hs_polling(codec);
3145
Joonwoo Park0976d012011-12-22 11:48:18 -08003146 bias_value = tabla_codec_sta_dce(codec, 0);
3147 snd_soc_update_bits(codec, tabla->mbhc_bias_regs.cfilt_ctl, 0x40,
3148 cfilt_mode);
Bradley Rubin89ffd0a2011-07-21 16:04:06 -07003149 snd_soc_update_bits(codec, TABLA_A_MBHC_HPH, 0x13, 0x00);
Bradley Rubincb1e2732011-06-23 16:49:20 -07003150
Bhalchandra Gajare343cbb02011-09-07 18:58:19 -07003151 return bias_value;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003152}
3153
3154static int tabla_codec_enable_hs_detect(struct snd_soc_codec *codec,
3155 int insertion)
3156{
3157 struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003158 int central_bias_enabled = 0;
Joonwoo Park0976d012011-12-22 11:48:18 -08003159 const struct tabla_mbhc_general_cfg *generic =
3160 TABLA_MBHC_CAL_GENERAL_PTR(tabla->calibration);
3161 const struct tabla_mbhc_plug_detect_cfg *plug_det =
3162 TABLA_MBHC_CAL_PLUG_DET_PTR(tabla->calibration);
Bhalchandra Gajare5ea376d2011-11-30 14:21:20 -08003163 u8 wg_time;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003164
Joonwoo Park0976d012011-12-22 11:48:18 -08003165 if (!tabla->calibration) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003166 pr_err("Error, no tabla calibration\n");
3167 return -EINVAL;
3168 }
3169
3170 snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_INT_CTL, 0x1, 0);
3171
Bhalchandra Gajare7fc72332011-10-13 19:01:55 -07003172 if (insertion) {
3173 /* Make sure mic bias and Mic line schmitt trigger
3174 * are turned OFF
3175 */
3176 snd_soc_update_bits(codec, tabla->mbhc_bias_regs.ctl_reg,
3177 0x81, 0x01);
3178 snd_soc_update_bits(codec, tabla->mbhc_bias_regs.mbhc_reg,
3179 0x90, 0x00);
Bhalchandra Gajare5ea376d2011-11-30 14:21:20 -08003180 wg_time = snd_soc_read(codec, TABLA_A_RX_HPH_CNP_WG_TIME) ;
3181 wg_time += 1;
Bhalchandra Gajare7fc72332011-10-13 19:01:55 -07003182
3183 /* Enable HPH Schmitt Trigger */
Bhalchandra Gajare5ea376d2011-11-30 14:21:20 -08003184 snd_soc_update_bits(codec, TABLA_A_MBHC_HPH, 0x11, 0x11);
Bhalchandra Gajare7fc72332011-10-13 19:01:55 -07003185 snd_soc_update_bits(codec, TABLA_A_MBHC_HPH, 0x0C,
Joonwoo Park0976d012011-12-22 11:48:18 -08003186 plug_det->hph_current << 2);
Bhalchandra Gajare7fc72332011-10-13 19:01:55 -07003187
Bhalchandra Gajare5ea376d2011-11-30 14:21:20 -08003188 /* Turn off HPH PAs and DAC's during insertion detection to
3189 * avoid false insertion interrupts
Bhalchandra Gajare7fc72332011-10-13 19:01:55 -07003190 */
3191 if (tabla->mbhc_micbias_switched)
3192 tabla_codec_switch_micbias(codec, 0);
3193 snd_soc_update_bits(codec, TABLA_A_RX_HPH_CNP_EN, 0x30, 0x00);
Bhalchandra Gajare5ea376d2011-11-30 14:21:20 -08003194 snd_soc_update_bits(codec, TABLA_A_RX_HPH_L_DAC_CTL,
Joonwoo Park0976d012011-12-22 11:48:18 -08003195 0xC0, 0x00);
Bhalchandra Gajare5ea376d2011-11-30 14:21:20 -08003196 snd_soc_update_bits(codec, TABLA_A_RX_HPH_R_DAC_CTL,
Joonwoo Park0976d012011-12-22 11:48:18 -08003197 0xC0, 0x00);
Bhalchandra Gajare5ea376d2011-11-30 14:21:20 -08003198 usleep_range(wg_time * 1000, wg_time * 1000);
Bhalchandra Gajare7fc72332011-10-13 19:01:55 -07003199
3200 /* setup for insetion detection */
Bhalchandra Gajare5ea376d2011-11-30 14:21:20 -08003201 snd_soc_update_bits(codec, TABLA_A_MBHC_HPH, 0x02, 0x02);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003202 snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_INT_CTL, 0x2, 0);
Bhalchandra Gajare7fc72332011-10-13 19:01:55 -07003203 } else {
3204 /* Make sure the HPH schmitt trigger is OFF */
3205 snd_soc_update_bits(codec, TABLA_A_MBHC_HPH, 0x12, 0x00);
3206
3207 /* enable the mic line schmitt trigger */
3208 snd_soc_update_bits(codec, tabla->mbhc_bias_regs.mbhc_reg, 0x60,
Joonwoo Park0976d012011-12-22 11:48:18 -08003209 plug_det->mic_current << 5);
Bhalchandra Gajare7fc72332011-10-13 19:01:55 -07003210 snd_soc_update_bits(codec, tabla->mbhc_bias_regs.mbhc_reg,
3211 0x80, 0x80);
Joonwoo Park0976d012011-12-22 11:48:18 -08003212 usleep_range(plug_det->t_mic_pid, plug_det->t_mic_pid);
Bhalchandra Gajare7fc72332011-10-13 19:01:55 -07003213 snd_soc_update_bits(codec, tabla->mbhc_bias_regs.mbhc_reg,
3214 0x10, 0x10);
3215
3216 /* Setup for low power removal detection */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003217 snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_INT_CTL, 0x2, 0x2);
Bhalchandra Gajare7fc72332011-10-13 19:01:55 -07003218 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003219
3220 if (snd_soc_read(codec, TABLA_A_CDC_MBHC_B1_CTL) & 0x4) {
3221 if (!(tabla->clock_active)) {
3222 tabla_codec_enable_config_mode(codec, 1);
3223 snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_B1_CTL,
Bradley Rubincb1e2732011-06-23 16:49:20 -07003224 0x06, 0);
Joonwoo Park0976d012011-12-22 11:48:18 -08003225 usleep_range(generic->t_shutdown_plug_rem,
3226 generic->t_shutdown_plug_rem);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003227 tabla_codec_enable_config_mode(codec, 0);
3228 } else
3229 snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_B1_CTL,
Bradley Rubincb1e2732011-06-23 16:49:20 -07003230 0x06, 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003231 }
3232
Bhalchandra Gajare02d90cd2011-09-30 16:14:00 -07003233 snd_soc_update_bits(codec, tabla->mbhc_bias_regs.int_rbias, 0x80, 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003234
3235 /* If central bandgap disabled */
3236 if (!(snd_soc_read(codec, TABLA_A_PIN_CTL_OE1) & 1)) {
3237 snd_soc_update_bits(codec, TABLA_A_PIN_CTL_OE1, 0x3, 0x3);
Joonwoo Park0976d012011-12-22 11:48:18 -08003238 usleep_range(generic->t_bg_fast_settle,
3239 generic->t_bg_fast_settle);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003240 central_bias_enabled = 1;
3241 }
3242
3243 /* If LDO_H disabled */
3244 if (snd_soc_read(codec, TABLA_A_PIN_CTL_OE0) & 0x80) {
3245 snd_soc_update_bits(codec, TABLA_A_PIN_CTL_OE0, 0x10, 0);
3246 snd_soc_update_bits(codec, TABLA_A_PIN_CTL_OE0, 0x80, 0x80);
Joonwoo Park0976d012011-12-22 11:48:18 -08003247 usleep_range(generic->t_ldoh, generic->t_ldoh);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003248 snd_soc_update_bits(codec, TABLA_A_PIN_CTL_OE0, 0x80, 0);
3249
3250 if (central_bias_enabled)
3251 snd_soc_update_bits(codec, TABLA_A_PIN_CTL_OE1, 0x1, 0);
3252 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003253
Joonwoo Park0976d012011-12-22 11:48:18 -08003254 snd_soc_update_bits(codec, TABLA_A_MICB_4_MBHC, 0x3, tabla->micbias);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003255
3256 tabla_enable_irq(codec->control_data, TABLA_IRQ_MBHC_INSERTION);
3257 snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_INT_CTL, 0x1, 0x1);
3258 return 0;
3259}
3260
Joonwoo Park8b1f0982011-12-08 17:12:45 -08003261static void tabla_lock_sleep(struct tabla_priv *tabla)
3262{
3263 int ret;
3264 while (!(ret = wait_event_timeout(tabla->pm_wq,
3265 atomic_inc_not_zero(&tabla->pm_cnt),
3266 2 * HZ))) {
3267 pr_err("%s: didn't wake up for 2000ms (%d), pm_cnt %d\n",
3268 __func__, ret, atomic_read(&tabla->pm_cnt));
3269 WARN_ON_ONCE(1);
3270 }
3271}
3272
3273static void tabla_unlock_sleep(struct tabla_priv *tabla)
3274{
3275 atomic_dec(&tabla->pm_cnt);
3276 wake_up(&tabla->pm_wq);
3277}
3278
Joonwoo Park0976d012011-12-22 11:48:18 -08003279static u16 tabla_codec_v_sta_dce(struct snd_soc_codec *codec, bool dce,
3280 s16 vin_mv)
3281{
3282 short diff, zero;
3283 struct tabla_priv *tabla;
3284 u32 mb_mv, in;
3285
3286 tabla = snd_soc_codec_get_drvdata(codec);
3287 mb_mv = tabla->mbhc_data.micb_mv;
3288
3289 if (mb_mv == 0) {
3290 pr_err("%s: Mic Bias voltage is set to zero\n", __func__);
3291 return -EINVAL;
3292 }
3293
3294 if (dce) {
3295 diff = tabla->mbhc_data.dce_mb - tabla->mbhc_data.dce_z;
3296 zero = tabla->mbhc_data.dce_z;
3297 } else {
3298 diff = tabla->mbhc_data.sta_mb - tabla->mbhc_data.sta_z;
3299 zero = tabla->mbhc_data.sta_z;
3300 }
3301 in = (u32) diff * vin_mv;
3302
3303 return (u16) (in / mb_mv) + zero;
3304}
3305
3306static s32 tabla_codec_sta_dce_v(struct snd_soc_codec *codec, s8 dce,
3307 u16 bias_value)
3308{
3309 struct tabla_priv *tabla;
3310 s32 mv;
3311
3312 tabla = snd_soc_codec_get_drvdata(codec);
3313
3314 if (dce) {
3315 mv = ((s32)bias_value - (s32)tabla->mbhc_data.dce_z) *
3316 (s32)tabla->mbhc_data.micb_mv /
3317 (s32)(tabla->mbhc_data.dce_mb - tabla->mbhc_data.dce_z);
3318 } else {
3319 mv = ((s32)bias_value - (s32)tabla->mbhc_data.sta_z) *
3320 (s32)tabla->mbhc_data.micb_mv /
3321 (s32)(tabla->mbhc_data.sta_mb - tabla->mbhc_data.sta_z);
3322 }
3323
3324 return mv;
3325}
3326
Bhalchandra Gajare0a792b12011-09-06 16:36:58 -07003327static void btn0_lpress_fn(struct work_struct *work)
3328{
3329 struct delayed_work *delayed_work;
3330 struct tabla_priv *tabla;
Joonwoo Park0976d012011-12-22 11:48:18 -08003331 short bias_value;
3332 int dce_mv, sta_mv;
Bhalchandra Gajare0a792b12011-09-06 16:36:58 -07003333
3334 pr_debug("%s:\n", __func__);
3335
3336 delayed_work = to_delayed_work(work);
3337 tabla = container_of(delayed_work, struct tabla_priv, btn0_dwork);
3338
3339 if (tabla) {
3340 if (tabla->button_jack) {
Joonwoo Park0976d012011-12-22 11:48:18 -08003341 bias_value = tabla_codec_read_sta_result(tabla->codec);
3342 sta_mv = tabla_codec_sta_dce_v(tabla->codec, 0,
3343 bias_value);
3344 bias_value = tabla_codec_read_dce_result(tabla->codec);
3345 dce_mv = tabla_codec_sta_dce_v(tabla->codec, 1,
3346 bias_value);
3347 pr_debug("%s: Reporting long button press event"
3348 " STA: %d, DCE: %d\n", __func__,
3349 sta_mv, dce_mv);
Joonwoo Park8b1f0982011-12-08 17:12:45 -08003350 tabla_snd_soc_jack_report(tabla, tabla->button_jack,
3351 SND_JACK_BTN_0,
3352 SND_JACK_BTN_0);
Bhalchandra Gajare0a792b12011-09-06 16:36:58 -07003353 }
3354 } else {
3355 pr_err("%s: Bad tabla private data\n", __func__);
3356 }
3357
Joonwoo Park8b1f0982011-12-08 17:12:45 -08003358 tabla_unlock_sleep(tabla);
Bhalchandra Gajare0a792b12011-09-06 16:36:58 -07003359}
Bhalchandra Gajared9ebb6c2011-10-03 19:54:41 -07003360
Joonwoo Park0976d012011-12-22 11:48:18 -08003361void tabla_mbhc_cal(struct snd_soc_codec *codec)
3362{
3363 struct tabla_priv *tabla;
3364 struct tabla_mbhc_btn_detect_cfg *btn_det;
3365 u8 cfilt_mode, bg_mode;
3366 u8 ncic, nmeas, navg;
3367 u32 mclk_rate;
3368 u32 dce_wait, sta_wait;
3369 u8 *n_cic;
3370
3371 tabla = snd_soc_codec_get_drvdata(codec);
3372
3373 /* First compute the DCE / STA wait times
3374 * depending on tunable parameters.
3375 * The value is computed in microseconds
3376 */
3377 btn_det = TABLA_MBHC_CAL_BTN_DET_PTR(tabla->calibration);
3378 n_cic = tabla_mbhc_cal_btn_det_mp(btn_det, TABLA_BTN_DET_N_CIC);
3379 ncic = n_cic[0];
3380 nmeas = TABLA_MBHC_CAL_BTN_DET_PTR(tabla->calibration)->n_meas;
3381 navg = TABLA_MBHC_CAL_GENERAL_PTR(tabla->calibration)->mbhc_navg;
3382 mclk_rate = tabla->mclk_freq;
3383 dce_wait = (1000 * 512 * ncic * nmeas) / (mclk_rate / 1000);
3384 if (tabla->mclk_freq == TABLA_MCLK_RATE_12288KHZ)
3385 dce_wait = dce_wait + 10000;
3386 else if (tabla->mclk_freq == TABLA_MCLK_RATE_9600KHZ)
3387 dce_wait = dce_wait + 9810;
3388 else
3389 WARN(1, "Unsupported mclk freq %d\n", tabla->mclk_freq);
3390
3391 sta_wait = (1000 * 128 * navg) / (mclk_rate / 1000);
3392
3393 /* Add 10 microseconds to handle error margin */
3394 dce_wait = dce_wait + 10;
3395 sta_wait = sta_wait + 10;
3396
3397 tabla->mbhc_data.t_dce = dce_wait;
3398 tabla->mbhc_data.t_sta = sta_wait;
3399
3400 /* LDOH and CFILT are already configured during pdata handling.
3401 * Only need to make sure CFILT and bandgap are in Fast mode.
3402 * Need to restore defaults once calculation is done.
3403 */
3404 cfilt_mode = snd_soc_read(codec, tabla->mbhc_bias_regs.cfilt_ctl);
3405 snd_soc_update_bits(codec, tabla->mbhc_bias_regs.cfilt_ctl, 0x40, 0x00);
3406 bg_mode = snd_soc_update_bits(codec, TABLA_A_BIAS_CENTRAL_BG_CTL, 0x02,
3407 0x02);
3408
3409 /* Micbias, CFILT, LDOH, MBHC MUX mode settings
3410 * to perform ADC calibration
3411 */
3412 snd_soc_update_bits(codec, tabla->mbhc_bias_regs.ctl_reg, 0x60,
3413 tabla->micbias << 5);
3414 snd_soc_update_bits(codec, tabla->mbhc_bias_regs.ctl_reg, 0x01, 0x00);
3415 snd_soc_update_bits(codec, TABLA_A_LDO_H_MODE_1, 0x60, 0x60);
3416 snd_soc_write(codec, TABLA_A_TX_7_MBHC_TEST_CTL, 0x78);
3417 snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_B1_CTL, 0x04, 0x04);
3418
3419 /* DCE measurement for 0 volts */
3420 snd_soc_write(codec, TABLA_A_CDC_MBHC_CLK_CTL, 0x0A);
3421 snd_soc_write(codec, TABLA_A_CDC_MBHC_EN_CTL, 0x04);
3422 snd_soc_write(codec, TABLA_A_CDC_MBHC_CLK_CTL, 0x02);
3423 snd_soc_write(codec, TABLA_A_CDC_MBHC_EN_CTL, 0x04);
3424 snd_soc_write(codec, TABLA_A_MBHC_SCALING_MUX_1, 0x81);
3425 usleep_range(100, 100);
3426 snd_soc_write(codec, TABLA_A_CDC_MBHC_EN_CTL, 0x04);
3427 usleep_range(tabla->mbhc_data.t_dce, tabla->mbhc_data.t_dce);
3428 tabla->mbhc_data.dce_z = tabla_codec_read_dce_result(codec);
3429
3430 /* DCE measurment for MB voltage */
3431 snd_soc_write(codec, TABLA_A_CDC_MBHC_CLK_CTL, 0x0A);
3432 snd_soc_write(codec, TABLA_A_CDC_MBHC_CLK_CTL, 0x02);
3433 snd_soc_write(codec, TABLA_A_MBHC_SCALING_MUX_1, 0x82);
3434 usleep_range(100, 100);
3435 snd_soc_write(codec, TABLA_A_CDC_MBHC_EN_CTL, 0x04);
3436 usleep_range(tabla->mbhc_data.t_dce, tabla->mbhc_data.t_dce);
3437 tabla->mbhc_data.dce_mb = tabla_codec_read_dce_result(codec);
3438
3439 /* Sta measuremnt for 0 volts */
3440 snd_soc_write(codec, TABLA_A_CDC_MBHC_CLK_CTL, 0x0A);
3441 snd_soc_write(codec, TABLA_A_CDC_MBHC_EN_CTL, 0x02);
3442 snd_soc_write(codec, TABLA_A_CDC_MBHC_CLK_CTL, 0x02);
3443 snd_soc_write(codec, TABLA_A_CDC_MBHC_EN_CTL, 0x02);
3444 snd_soc_write(codec, TABLA_A_MBHC_SCALING_MUX_1, 0x81);
3445 usleep_range(100, 100);
3446 snd_soc_write(codec, TABLA_A_CDC_MBHC_EN_CTL, 0x02);
3447 usleep_range(tabla->mbhc_data.t_sta, tabla->mbhc_data.t_sta);
3448 tabla->mbhc_data.sta_z = tabla_codec_read_sta_result(codec);
3449
3450 /* STA Measurement for MB Voltage */
3451 snd_soc_write(codec, TABLA_A_MBHC_SCALING_MUX_1, 0x82);
3452 usleep_range(100, 100);
3453 snd_soc_write(codec, TABLA_A_CDC_MBHC_EN_CTL, 0x02);
3454 usleep_range(tabla->mbhc_data.t_sta, tabla->mbhc_data.t_sta);
3455 tabla->mbhc_data.sta_mb = tabla_codec_read_sta_result(codec);
3456
3457 /* Restore default settings. */
3458 snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_B1_CTL, 0x04, 0x00);
3459 snd_soc_update_bits(codec, tabla->mbhc_bias_regs.cfilt_ctl, 0x40,
3460 cfilt_mode);
3461 snd_soc_update_bits(codec, TABLA_A_BIAS_CENTRAL_BG_CTL, 0x02, bg_mode);
3462
3463 snd_soc_write(codec, TABLA_A_MBHC_SCALING_MUX_1, 0x84);
3464 usleep_range(100, 100);
3465}
3466
3467void *tabla_mbhc_cal_btn_det_mp(const struct tabla_mbhc_btn_detect_cfg* btn_det,
3468 const enum tabla_mbhc_btn_det_mem mem)
3469{
3470 void *ret = &btn_det->_v_btn_low;
3471
3472 switch (mem) {
3473 case TABLA_BTN_DET_GAIN:
3474 ret += sizeof(btn_det->_n_cic);
3475 case TABLA_BTN_DET_N_CIC:
3476 ret += sizeof(btn_det->_n_ready);
3477 case TABLA_BTN_DET_V_N_READY:
3478 ret += sizeof(btn_det->_v_btn_high[0]) * btn_det->num_btn;
3479 case TABLA_BTN_DET_V_BTN_HIGH:
3480 ret += sizeof(btn_det->_v_btn_low[0]) * btn_det->num_btn;
3481 case TABLA_BTN_DET_V_BTN_LOW:
3482 /* do nothing */
3483 break;
3484 default:
3485 ret = NULL;
3486 }
3487
3488 return ret;
3489}
3490
3491static void tabla_mbhc_calc_thres(struct snd_soc_codec *codec)
3492{
3493 struct tabla_priv *tabla;
3494 s16 btn_mv = 0, btn_delta_mv;
3495 struct tabla_mbhc_btn_detect_cfg *btn_det;
3496 struct tabla_mbhc_plug_type_cfg *plug_type;
3497 u16 *btn_high;
3498 int i;
3499
3500 tabla = snd_soc_codec_get_drvdata(codec);
3501 btn_det = TABLA_MBHC_CAL_BTN_DET_PTR(tabla->calibration);
3502 plug_type = TABLA_MBHC_CAL_PLUG_TYPE_PTR(tabla->calibration);
3503
3504 if (tabla->mclk_freq == TABLA_MCLK_RATE_12288KHZ) {
3505 tabla->mbhc_data.nready = 3;
3506 tabla->mbhc_data.npoll = 9;
3507 tabla->mbhc_data.nbounce_wait = 30;
3508 } else if (tabla->mclk_freq == TABLA_MCLK_RATE_9600KHZ) {
3509 tabla->mbhc_data.nready = 2;
3510 tabla->mbhc_data.npoll = 7;
3511 tabla->mbhc_data.nbounce_wait = 23;
3512 }
3513
3514 tabla->mbhc_data.v_ins_hu =
3515 tabla_codec_v_sta_dce(codec, STA, plug_type->v_hs_max);
3516 tabla->mbhc_data.v_ins_h =
3517 tabla_codec_v_sta_dce(codec, DCE, plug_type->v_hs_max);
3518
3519 btn_high = tabla_mbhc_cal_btn_det_mp(btn_det, TABLA_BTN_DET_V_BTN_HIGH);
3520 for (i = 0; i < btn_det->num_btn; i++)
3521 btn_mv = btn_high[i] > btn_mv ? btn_high[i] : btn_mv;
3522
3523 tabla->mbhc_data.v_b1_h = tabla_codec_v_sta_dce(codec, DCE, btn_mv);
3524 btn_delta_mv = btn_mv + btn_det->v_btn_press_delta_sta;
3525
3526 tabla->mbhc_data.v_b1_hu =
3527 tabla_codec_v_sta_dce(codec, STA, btn_delta_mv);
3528
3529 btn_delta_mv = btn_mv + btn_det->v_btn_press_delta_cic;
3530
3531 tabla->mbhc_data.v_b1_huc =
3532 tabla_codec_v_sta_dce(codec, DCE, btn_delta_mv);
3533
3534 tabla->mbhc_data.v_brh = tabla->mbhc_data.v_b1_h;
3535 tabla->mbhc_data.v_brl = 0xFA55;
3536
3537 tabla->mbhc_data.v_no_mic =
3538 tabla_codec_v_sta_dce(codec, STA, plug_type->v_no_mic);
3539}
3540
3541void tabla_mbhc_init(struct snd_soc_codec *codec)
3542{
3543 struct tabla_priv *tabla;
3544 struct tabla_mbhc_general_cfg *generic;
3545 struct tabla_mbhc_btn_detect_cfg *btn_det;
3546 int n;
3547 u8 tabla_ver;
3548 u8 *n_cic, *gain;
3549
3550 tabla = snd_soc_codec_get_drvdata(codec);
3551 generic = TABLA_MBHC_CAL_GENERAL_PTR(tabla->calibration);
3552 btn_det = TABLA_MBHC_CAL_BTN_DET_PTR(tabla->calibration);
3553
3554 tabla_ver = snd_soc_read(codec, TABLA_A_CHIP_VERSION);
3555 tabla_ver &= 0x1F;
3556
3557 for (n = 0; n < 8; n++) {
3558 if ((tabla_ver != TABLA_VERSION_1_0 &&
3559 tabla_ver != TABLA_VERSION_1_1) || n != 7) {
3560 snd_soc_update_bits(codec,
3561 TABLA_A_CDC_MBHC_FEATURE_B1_CFG,
3562 0x07, n);
3563 snd_soc_write(codec, TABLA_A_CDC_MBHC_FEATURE_B2_CFG,
3564 btn_det->c[n]);
3565 }
3566 }
3567 snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_B2_CTL, 0x07,
3568 btn_det->nc);
3569
3570 n_cic = tabla_mbhc_cal_btn_det_mp(btn_det, TABLA_BTN_DET_N_CIC);
3571 snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_TIMER_B6_CTL, 0xFF,
3572 n_cic[0]);
3573
3574 gain = tabla_mbhc_cal_btn_det_mp(btn_det, TABLA_BTN_DET_GAIN);
3575 snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_B2_CTL, 0x78, gain[0] << 3);
3576
3577 snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_TIMER_B4_CTL, 0x70,
3578 generic->mbhc_nsa << 4);
3579
3580 snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_TIMER_B4_CTL, 0x0F,
3581 btn_det->n_meas);
3582
3583 snd_soc_write(codec, TABLA_A_CDC_MBHC_TIMER_B5_CTL, generic->mbhc_navg);
3584
3585 snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_B1_CTL, 0x80, 0x80);
3586
3587 snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_B1_CTL, 0x78,
3588 btn_det->mbhc_nsc << 3);
3589
3590 snd_soc_update_bits(codec, TABLA_A_MICB_4_MBHC, 0x03, TABLA_MICBIAS2);
3591
3592 snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_B1_CTL, 0x02, 0x02);
3593}
3594
Bradley Rubincb1e2732011-06-23 16:49:20 -07003595int tabla_hs_detect(struct snd_soc_codec *codec,
Joonwoo Park0976d012011-12-22 11:48:18 -08003596 struct snd_soc_jack *headset_jack,
3597 struct snd_soc_jack *button_jack,
3598 void *calibration, enum tabla_micbias_num micbias,
3599 int (*mclk_cb_fn) (struct snd_soc_codec*, int),
3600 int read_fw_bin, u32 mclk_rate)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003601{
3602 struct tabla_priv *tabla;
Patrick Lai49efeac2011-11-03 11:01:12 -07003603 int rc;
3604
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003605 if (!codec || !calibration) {
3606 pr_err("Error: no codec or calibration\n");
3607 return -EINVAL;
3608 }
3609 tabla = snd_soc_codec_get_drvdata(codec);
Bradley Rubincb1e2732011-06-23 16:49:20 -07003610 tabla->headset_jack = headset_jack;
3611 tabla->button_jack = button_jack;
Joonwoo Park0976d012011-12-22 11:48:18 -08003612 tabla->micbias = micbias;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003613 tabla->calibration = calibration;
Joonwoo Park0976d012011-12-22 11:48:18 -08003614 tabla->mclk_cb = mclk_cb_fn;
3615 tabla->mclk_freq = mclk_rate;
Bhalchandra Gajare02d90cd2011-09-30 16:14:00 -07003616 tabla_get_mbhc_micbias_regs(codec, &tabla->mbhc_bias_regs);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003617
Bhalchandra Gajare19d9c132011-11-18 14:57:08 -08003618 /* Put CFILT in fast mode by default */
3619 snd_soc_update_bits(codec, tabla->mbhc_bias_regs.cfilt_ctl,
3620 0x40, TABLA_CFILT_FAST_MODE);
3621
Bhalchandra Gajare0a792b12011-09-06 16:36:58 -07003622 INIT_DELAYED_WORK(&tabla->btn0_dwork, btn0_lpress_fn);
Patrick Lai49efeac2011-11-03 11:01:12 -07003623 INIT_WORK(&tabla->hphlocp_work, hphlocp_off_report);
3624 INIT_WORK(&tabla->hphrocp_work, hphrocp_off_report);
Joonwoo Park0976d012011-12-22 11:48:18 -08003625
3626 if (!read_fw_bin) {
3627 tabla->mclk_cb(codec, 1);
3628 tabla_mbhc_init(codec);
3629 tabla_mbhc_cal(codec);
3630 tabla_mbhc_calc_thres(codec);
3631 tabla->mclk_cb(codec, 0);
3632 tabla_codec_calibrate_hs_polling(codec);
3633 rc = tabla_codec_enable_hs_detect(codec, 1);
3634 } else {
3635 pr_err("%s: MBHC firmware read not supported\n", __func__);
3636 rc = -EINVAL;
3637 }
Patrick Lai49efeac2011-11-03 11:01:12 -07003638
3639 if (!IS_ERR_VALUE(rc)) {
3640 snd_soc_update_bits(codec, TABLA_A_RX_HPH_OCP_CTL, 0x10,
3641 0x10);
3642 tabla_enable_irq(codec->control_data,
3643 TABLA_IRQ_HPH_PA_OCPL_FAULT);
3644 tabla_enable_irq(codec->control_data,
3645 TABLA_IRQ_HPH_PA_OCPR_FAULT);
3646 }
3647
3648 return rc;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003649}
3650EXPORT_SYMBOL_GPL(tabla_hs_detect);
3651
Bradley Rubincb1e2732011-06-23 16:49:20 -07003652static irqreturn_t tabla_dce_handler(int irq, void *data)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003653{
3654 struct tabla_priv *priv = data;
3655 struct snd_soc_codec *codec = priv->codec;
Bhalchandra Gajare0a792b12011-09-06 16:36:58 -07003656 short bias_value;
Bradley Rubincb1e2732011-06-23 16:49:20 -07003657
3658 tabla_disable_irq(codec->control_data, TABLA_IRQ_MBHC_REMOVAL);
3659 tabla_disable_irq(codec->control_data, TABLA_IRQ_MBHC_POTENTIAL);
Joonwoo Park8b1f0982011-12-08 17:12:45 -08003660 tabla_lock_sleep(priv);
Bradley Rubincb1e2732011-06-23 16:49:20 -07003661
Bradley Rubin89ffd0a2011-07-21 16:04:06 -07003662 bias_value = tabla_codec_read_dce_result(codec);
Joonwoo Park0976d012011-12-22 11:48:18 -08003663 pr_debug("%s: button press interrupt, DCE: %d,%d\n",
3664 __func__, bias_value,
3665 tabla_codec_sta_dce_v(codec, 1, bias_value));
Bradley Rubin89ffd0a2011-07-21 16:04:06 -07003666
Bhalchandra Gajare30cf4842011-10-17 18:12:52 -07003667 bias_value = tabla_codec_read_sta_result(codec);
Joonwoo Park0976d012011-12-22 11:48:18 -08003668 pr_debug("%s: button press interrupt, STA: %d,%d\n",
3669 __func__, bias_value,
3670 tabla_codec_sta_dce_v(codec, 0, bias_value));
Bhalchandra Gajare0a792b12011-09-06 16:36:58 -07003671 /*
3672 * TODO: If button pressed is not button 0,
3673 * report the button press event immediately.
3674 */
3675 priv->buttons_pressed |= SND_JACK_BTN_0;
Bradley Rubincb1e2732011-06-23 16:49:20 -07003676
Bradley Rubin688c66a2011-08-16 12:25:13 -07003677 msleep(100);
Bradley Rubincb1e2732011-06-23 16:49:20 -07003678
Joonwoo Park8b1f0982011-12-08 17:12:45 -08003679 if (schedule_delayed_work(&priv->btn0_dwork,
3680 msecs_to_jiffies(400)) == 0) {
3681 WARN(1, "Button pressed twice without release event\n");
3682 tabla_unlock_sleep(priv);
3683 }
Bhalchandra Gajare0a792b12011-09-06 16:36:58 -07003684
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003685 return IRQ_HANDLED;
3686}
3687
Bradley Rubincb1e2732011-06-23 16:49:20 -07003688static irqreturn_t tabla_release_handler(int irq, void *data)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003689{
3690 struct tabla_priv *priv = data;
3691 struct snd_soc_codec *codec = priv->codec;
Joonwoo Park0976d012011-12-22 11:48:18 -08003692 int ret, mb_v;
Bhalchandra Gajare0a792b12011-09-06 16:36:58 -07003693
Bradley Rubin4d09cf42011-08-17 17:59:16 -07003694 pr_debug("%s\n", __func__);
3695 tabla_disable_irq(codec->control_data, TABLA_IRQ_MBHC_RELEASE);
Joonwoo Park8b1f0982011-12-08 17:12:45 -08003696 tabla_lock_sleep(priv);
Bhalchandra Gajare0a792b12011-09-06 16:36:58 -07003697
Bradley Rubincb1e2732011-06-23 16:49:20 -07003698 if (priv->buttons_pressed & SND_JACK_BTN_0) {
Bhalchandra Gajare0a792b12011-09-06 16:36:58 -07003699 ret = cancel_delayed_work(&priv->btn0_dwork);
3700
3701 if (ret == 0) {
Bhalchandra Gajare0a792b12011-09-06 16:36:58 -07003702 pr_debug("%s: Reporting long button release event\n",
3703 __func__);
Joonwoo Park0976d012011-12-22 11:48:18 -08003704 if (priv->button_jack)
Joonwoo Park8b1f0982011-12-08 17:12:45 -08003705 tabla_snd_soc_jack_report(priv,
3706 priv->button_jack, 0,
3707 SND_JACK_BTN_0);
Bhalchandra Gajare0a792b12011-09-06 16:36:58 -07003708 } else {
Joonwoo Park8b1f0982011-12-08 17:12:45 -08003709 /* if scheduled btn0_dwork is canceled from here,
3710 * we have to unlock from here instead btn0_work */
3711 tabla_unlock_sleep(priv);
Joonwoo Park0976d012011-12-22 11:48:18 -08003712 mb_v = tabla_codec_sta_dce(codec, 0);
3713 pr_debug("%s: Mic Voltage on release STA: %d,%d\n",
3714 __func__, mb_v,
3715 tabla_codec_sta_dce_v(codec, 0, mb_v));
Bhalchandra Gajare0a792b12011-09-06 16:36:58 -07003716
Joonwoo Park0976d012011-12-22 11:48:18 -08003717 if (mb_v < -2000 || mb_v > -670)
Bhalchandra Gajare0a792b12011-09-06 16:36:58 -07003718 pr_debug("%s: Fake buttton press interrupt\n",
3719 __func__);
Joonwoo Park0976d012011-12-22 11:48:18 -08003720 else if (priv->button_jack) {
3721 pr_debug("%s:reporting short button "
3722 "press and release\n", __func__);
3723 tabla_snd_soc_jack_report(priv,
3724 priv->button_jack,
3725 SND_JACK_BTN_0,
3726 SND_JACK_BTN_0);
3727 tabla_snd_soc_jack_report(priv,
3728 priv->button_jack,
3729 0, SND_JACK_BTN_0);
Bhalchandra Gajare0a792b12011-09-06 16:36:58 -07003730 }
3731 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003732
Bradley Rubincb1e2732011-06-23 16:49:20 -07003733 priv->buttons_pressed &= ~SND_JACK_BTN_0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003734 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003735
Bradley Rubin688c66a2011-08-16 12:25:13 -07003736 tabla_codec_start_hs_polling(codec);
Joonwoo Park8b1f0982011-12-08 17:12:45 -08003737 tabla_unlock_sleep(priv);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003738 return IRQ_HANDLED;
3739}
3740
Bradley Rubincb1e2732011-06-23 16:49:20 -07003741static void tabla_codec_shutdown_hs_removal_detect(struct snd_soc_codec *codec)
3742{
3743 struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
Joonwoo Park0976d012011-12-22 11:48:18 -08003744 const struct tabla_mbhc_general_cfg *generic =
3745 TABLA_MBHC_CAL_GENERAL_PTR(tabla->calibration);
Bradley Rubincb1e2732011-06-23 16:49:20 -07003746
Kiran Kandi6fae8bf2011-08-15 10:36:42 -07003747 if (!tabla->mclk_enabled && !tabla->mbhc_polling_active)
Bradley Rubincb1e2732011-06-23 16:49:20 -07003748 tabla_codec_enable_config_mode(codec, 1);
3749
3750 snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_CLK_CTL, 0x2, 0x2);
3751 snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_B1_CTL, 0x6, 0x0);
Bradley Rubincb1e2732011-06-23 16:49:20 -07003752
Joonwoo Park0976d012011-12-22 11:48:18 -08003753 snd_soc_update_bits(codec, tabla->mbhc_bias_regs.mbhc_reg, 0x80, 0x00);
3754
3755 usleep_range(generic->t_shutdown_plug_rem,
3756 generic->t_shutdown_plug_rem);
Bradley Rubincb1e2732011-06-23 16:49:20 -07003757
3758 snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_CLK_CTL, 0xA, 0x8);
Kiran Kandi6fae8bf2011-08-15 10:36:42 -07003759 if (!tabla->mclk_enabled && !tabla->mbhc_polling_active)
Bradley Rubincb1e2732011-06-23 16:49:20 -07003760 tabla_codec_enable_config_mode(codec, 0);
3761
3762 snd_soc_write(codec, TABLA_A_MBHC_SCALING_MUX_1, 0x00);
3763}
3764
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003765static void tabla_codec_shutdown_hs_polling(struct snd_soc_codec *codec)
3766{
3767 struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
Bradley Rubincb1e2732011-06-23 16:49:20 -07003768
3769 tabla_codec_shutdown_hs_removal_detect(codec);
3770
Kiran Kandi6fae8bf2011-08-15 10:36:42 -07003771 if (!tabla->mclk_enabled) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003772 snd_soc_update_bits(codec, TABLA_A_TX_COM_BIAS, 0xE0, 0x00);
3773 tabla_codec_enable_bandgap(codec, TABLA_BANDGAP_AUDIO_MODE);
3774 tabla_codec_enable_clock_block(codec, 0);
3775 }
3776
3777 tabla->mbhc_polling_active = false;
3778}
3779
Patrick Lai49efeac2011-11-03 11:01:12 -07003780static irqreturn_t tabla_hphl_ocp_irq(int irq, void *data)
3781{
3782 struct tabla_priv *tabla = data;
3783 struct snd_soc_codec *codec;
3784
3785 pr_info("%s: received HPHL OCP irq\n", __func__);
3786
3787 if (tabla) {
3788 codec = tabla->codec;
Patrick Laic7cae882011-11-18 11:52:49 -08003789 if (tabla->hphlocp_cnt++ < TABLA_OCP_ATTEMPT) {
3790 pr_info("%s: retry\n", __func__);
3791 snd_soc_update_bits(codec, TABLA_A_RX_HPH_OCP_CTL, 0x10,
3792 0x00);
3793 snd_soc_update_bits(codec, TABLA_A_RX_HPH_OCP_CTL, 0x10,
3794 0x10);
3795 } else {
3796 tabla_disable_irq(codec->control_data,
3797 TABLA_IRQ_HPH_PA_OCPL_FAULT);
3798 tabla->hphlocp_cnt = 0;
3799 tabla->hph_status |= SND_JACK_OC_HPHL;
3800 if (tabla->headset_jack)
3801 tabla_snd_soc_jack_report(tabla,
3802 tabla->headset_jack,
3803 tabla->hph_status,
3804 TABLA_JACK_MASK);
Patrick Lai49efeac2011-11-03 11:01:12 -07003805 }
3806 } else {
3807 pr_err("%s: Bad tabla private data\n", __func__);
3808 }
3809
3810 return IRQ_HANDLED;
3811}
3812
3813static irqreturn_t tabla_hphr_ocp_irq(int irq, void *data)
3814{
3815 struct tabla_priv *tabla = data;
3816 struct snd_soc_codec *codec;
3817
3818 pr_info("%s: received HPHR OCP irq\n", __func__);
3819
3820 if (tabla) {
3821 codec = tabla->codec;
Patrick Laic7cae882011-11-18 11:52:49 -08003822 if (tabla->hphrocp_cnt++ < TABLA_OCP_ATTEMPT) {
3823 pr_info("%s: retry\n", __func__);
3824 snd_soc_update_bits(codec, TABLA_A_RX_HPH_OCP_CTL, 0x10,
3825 0x00);
3826 snd_soc_update_bits(codec, TABLA_A_RX_HPH_OCP_CTL, 0x10,
3827 0x10);
3828 } else {
3829 tabla_disable_irq(codec->control_data,
3830 TABLA_IRQ_HPH_PA_OCPR_FAULT);
3831 tabla->hphrocp_cnt = 0;
3832 tabla->hph_status |= SND_JACK_OC_HPHR;
3833 if (tabla->headset_jack)
3834 tabla_snd_soc_jack_report(tabla,
3835 tabla->headset_jack,
3836 tabla->hph_status,
3837 TABLA_JACK_MASK);
Patrick Lai49efeac2011-11-03 11:01:12 -07003838 }
3839 } else {
3840 pr_err("%s: Bad tabla private data\n", __func__);
3841 }
3842
3843 return IRQ_HANDLED;
3844}
3845
Joonwoo Parka9444452011-12-08 18:48:27 -08003846static void tabla_sync_hph_state(struct tabla_priv *tabla)
3847{
3848 if (test_and_clear_bit(TABLA_HPHR_PA_OFF_ACK,
3849 &tabla->hph_pa_dac_state)) {
3850 pr_debug("%s: HPHR clear flag and enable PA\n", __func__);
3851 snd_soc_update_bits(tabla->codec, TABLA_A_RX_HPH_CNP_EN, 0x10,
3852 1 << 4);
3853 }
3854 if (test_and_clear_bit(TABLA_HPHL_PA_OFF_ACK,
3855 &tabla->hph_pa_dac_state)) {
3856 pr_debug("%s: HPHL clear flag and enable PA\n", __func__);
3857 snd_soc_update_bits(tabla->codec, TABLA_A_RX_HPH_CNP_EN, 0x20,
3858 1 << 5);
3859 }
3860
3861 if (test_and_clear_bit(TABLA_HPHR_DAC_OFF_ACK,
3862 &tabla->hph_pa_dac_state)) {
3863 pr_debug("%s: HPHR clear flag and enable DAC\n", __func__);
3864 snd_soc_update_bits(tabla->codec, TABLA_A_RX_HPH_R_DAC_CTL,
3865 0xC0, 0xC0);
3866 }
3867 if (test_and_clear_bit(TABLA_HPHL_DAC_OFF_ACK,
3868 &tabla->hph_pa_dac_state)) {
3869 pr_debug("%s: HPHL clear flag and enable DAC\n", __func__);
3870 snd_soc_update_bits(tabla->codec, TABLA_A_RX_HPH_L_DAC_CTL,
3871 0xC0, 0xC0);
3872 }
3873}
3874
Bradley Rubincb1e2732011-06-23 16:49:20 -07003875static irqreturn_t tabla_hs_insert_irq(int irq, void *data)
3876{
3877 struct tabla_priv *priv = data;
3878 struct snd_soc_codec *codec = priv->codec;
Joonwoo Park0976d012011-12-22 11:48:18 -08003879 const struct tabla_mbhc_plug_detect_cfg *plug_det =
3880 TABLA_MBHC_CAL_PLUG_DET_PTR(priv->calibration);
Bradley Rubin355611a2011-08-24 14:01:18 -07003881 int ldo_h_on, micb_cfilt_on;
Joonwoo Park0976d012011-12-22 11:48:18 -08003882 short mb_v;
Bhalchandra Gajare7fc72332011-10-13 19:01:55 -07003883 u8 is_removal;
Joonwoo Park0976d012011-12-22 11:48:18 -08003884 int mic_mv;
Bhalchandra Gajare343cbb02011-09-07 18:58:19 -07003885
Joonwoo Parkf4267c22012-01-10 13:25:24 -08003886 pr_debug("%s: enter\n", __func__);
Bradley Rubincb1e2732011-06-23 16:49:20 -07003887 tabla_disable_irq(codec->control_data, TABLA_IRQ_MBHC_INSERTION);
Joonwoo Park8b1f0982011-12-08 17:12:45 -08003888 tabla_lock_sleep(priv);
3889
Bhalchandra Gajare7fc72332011-10-13 19:01:55 -07003890 is_removal = snd_soc_read(codec, TABLA_A_CDC_MBHC_INT_CTL) & 0x02;
3891 snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_INT_CTL, 0x03, 0x00);
3892
3893 /* Turn off both HPH and MIC line schmitt triggers */
Joonwoo Park0976d012011-12-22 11:48:18 -08003894 snd_soc_update_bits(codec, priv->mbhc_bias_regs.mbhc_reg, 0x90, 0x00);
Bhalchandra Gajare7fc72332011-10-13 19:01:55 -07003895 snd_soc_update_bits(codec, TABLA_A_MBHC_HPH, 0x13, 0x00);
Bradley Rubincb1e2732011-06-23 16:49:20 -07003896
Joonwoo Parkf4267c22012-01-10 13:25:24 -08003897 if (priv->mbhc_fake_ins_start &&
3898 time_after(jiffies, priv->mbhc_fake_ins_start +
3899 msecs_to_jiffies(TABLA_FAKE_INS_THRESHOLD_MS))) {
Bhalchandra Gajare9494fa262011-11-10 19:25:59 -08003900 pr_debug("%s: fake context interrupt, reset insertion\n",
Joonwoo Parkf4267c22012-01-10 13:25:24 -08003901 __func__);
3902 priv->mbhc_fake_ins_start = 0;
Bhalchandra Gajare9494fa262011-11-10 19:25:59 -08003903 tabla_codec_shutdown_hs_polling(codec);
3904 tabla_codec_enable_hs_detect(codec, 1);
3905 return IRQ_HANDLED;
3906 }
3907
Bradley Rubin355611a2011-08-24 14:01:18 -07003908 ldo_h_on = snd_soc_read(codec, TABLA_A_LDO_H_MODE_1) & 0x80;
Joonwoo Park0976d012011-12-22 11:48:18 -08003909 micb_cfilt_on = snd_soc_read(codec, priv->mbhc_bias_regs.cfilt_ctl)
3910 & 0x80;
Bradley Rubin355611a2011-08-24 14:01:18 -07003911
3912 if (!ldo_h_on)
3913 snd_soc_update_bits(codec, TABLA_A_LDO_H_MODE_1, 0x80, 0x80);
3914 if (!micb_cfilt_on)
Bhalchandra Gajare02d90cd2011-09-30 16:14:00 -07003915 snd_soc_update_bits(codec, priv->mbhc_bias_regs.cfilt_ctl,
Joonwoo Park0976d012011-12-22 11:48:18 -08003916 0x80, 0x80);
3917 if (plug_det->t_ins_complete > 20)
3918 msleep(plug_det->t_ins_complete);
3919 else
3920 usleep_range(plug_det->t_ins_complete * 1000,
3921 plug_det->t_ins_complete * 1000);
Bradley Rubincb1e2732011-06-23 16:49:20 -07003922
Bhalchandra Gajare7fc72332011-10-13 19:01:55 -07003923 if (!ldo_h_on)
3924 snd_soc_update_bits(codec, TABLA_A_LDO_H_MODE_1, 0x80, 0x0);
3925 if (!micb_cfilt_on)
3926 snd_soc_update_bits(codec, priv->mbhc_bias_regs.cfilt_ctl,
Joonwoo Park0976d012011-12-22 11:48:18 -08003927 0x80, 0x0);
Bhalchandra Gajare7fc72332011-10-13 19:01:55 -07003928
3929 if (is_removal) {
Bhalchandra Gajared9ebb6c2011-10-03 19:54:41 -07003930 /*
3931 * If headphone is removed while playback is in progress,
3932 * it is possible that micbias will be switched to VDDIO.
3933 */
3934 if (priv->mbhc_micbias_switched)
3935 tabla_codec_switch_micbias(codec, 0);
Patrick Lai72aa4da2011-12-08 12:38:18 -08003936 priv->hph_status &= ~SND_JACK_HEADPHONE;
Joonwoo Parka9444452011-12-08 18:48:27 -08003937
3938 /* If headphone PA is on, check if userspace receives
3939 * removal event to sync-up PA's state */
3940 if (tabla_is_hph_pa_on(codec)) {
3941 set_bit(TABLA_HPHL_PA_OFF_ACK, &priv->hph_pa_dac_state);
3942 set_bit(TABLA_HPHR_PA_OFF_ACK, &priv->hph_pa_dac_state);
3943 }
3944
3945 if (tabla_is_hph_dac_on(codec, 1))
3946 set_bit(TABLA_HPHL_DAC_OFF_ACK,
3947 &priv->hph_pa_dac_state);
3948 if (tabla_is_hph_dac_on(codec, 0))
3949 set_bit(TABLA_HPHR_DAC_OFF_ACK,
3950 &priv->hph_pa_dac_state);
3951
Bradley Rubincb1e2732011-06-23 16:49:20 -07003952 if (priv->headset_jack) {
3953 pr_debug("%s: Reporting removal\n", __func__);
Joonwoo Park8b1f0982011-12-08 17:12:45 -08003954 tabla_snd_soc_jack_report(priv, priv->headset_jack,
3955 priv->hph_status,
3956 TABLA_JACK_MASK);
Bradley Rubincb1e2732011-06-23 16:49:20 -07003957 }
3958 tabla_codec_shutdown_hs_removal_detect(codec);
3959 tabla_codec_enable_hs_detect(codec, 1);
Joonwoo Park8b1f0982011-12-08 17:12:45 -08003960 tabla_unlock_sleep(priv);
Bradley Rubincb1e2732011-06-23 16:49:20 -07003961 return IRQ_HANDLED;
3962 }
3963
Joonwoo Park0976d012011-12-22 11:48:18 -08003964 mb_v = tabla_codec_setup_hs_polling(codec);
3965 mic_mv = tabla_codec_sta_dce_v(codec, 0, mb_v);
Bradley Rubin355611a2011-08-24 14:01:18 -07003966
Joonwoo Park0976d012011-12-22 11:48:18 -08003967 if (mb_v > (short) priv->mbhc_data.v_ins_hu) {
Joonwoo Parkf4267c22012-01-10 13:25:24 -08003968 pr_debug("%s: Fake insertion interrupt since %dmsec ago, "
3969 "STA : %d,%d\n", __func__,
3970 (priv->mbhc_fake_ins_start ?
3971 jiffies_to_msecs(jiffies -
3972 priv->mbhc_fake_ins_start) :
3973 0),
3974 mb_v, mic_mv);
3975 if (time_after(jiffies,
3976 priv->mbhc_fake_ins_start +
3977 msecs_to_jiffies(TABLA_FAKE_INS_THRESHOLD_MS))) {
3978 /* Disable HPH trigger and enable MIC line trigger */
3979 snd_soc_update_bits(codec, TABLA_A_MBHC_HPH, 0x12,
3980 0x00);
3981 snd_soc_update_bits(codec,
3982 priv->mbhc_bias_regs.mbhc_reg, 0x60,
3983 plug_det->mic_current << 5);
3984 snd_soc_update_bits(codec,
3985 priv->mbhc_bias_regs.mbhc_reg,
3986 0x80, 0x80);
3987 usleep_range(plug_det->t_mic_pid, plug_det->t_mic_pid);
3988 snd_soc_update_bits(codec,
3989 priv->mbhc_bias_regs.mbhc_reg,
3990 0x10, 0x10);
3991 } else {
3992 if (priv->mbhc_fake_ins_start == 0)
3993 priv->mbhc_fake_ins_start = jiffies;
3994 /* Setup normal insert detection
3995 * Enable HPH Schmitt Trigger
3996 */
3997 snd_soc_update_bits(codec, TABLA_A_MBHC_HPH,
3998 0x13 | 0x0C,
3999 0x13 | plug_det->hph_current << 2);
4000 }
Bhalchandra Gajare9494fa262011-11-10 19:25:59 -08004001 /* Setup for insertion detection */
4002 snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_INT_CTL, 0x2, 0);
Bhalchandra Gajare9494fa262011-11-10 19:25:59 -08004003 tabla_enable_irq(codec->control_data, TABLA_IRQ_MBHC_INSERTION);
4004 snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_INT_CTL, 0x1, 0x1);
4005
Joonwoo Park0976d012011-12-22 11:48:18 -08004006 } else if (mb_v < (short) priv->mbhc_data.v_no_mic) {
4007 pr_debug("%s: Headphone Detected, mb_v: %d,%d\n",
4008 __func__, mb_v, mic_mv);
Joonwoo Parkf4267c22012-01-10 13:25:24 -08004009 priv->mbhc_fake_ins_start = 0;
Patrick Lai49efeac2011-11-03 11:01:12 -07004010 priv->hph_status |= SND_JACK_HEADPHONE;
Bradley Rubincb1e2732011-06-23 16:49:20 -07004011 if (priv->headset_jack) {
4012 pr_debug("%s: Reporting insertion %d\n", __func__,
Joonwoo Park0976d012011-12-22 11:48:18 -08004013 SND_JACK_HEADPHONE);
Joonwoo Park8b1f0982011-12-08 17:12:45 -08004014 tabla_snd_soc_jack_report(priv, priv->headset_jack,
4015 priv->hph_status,
4016 TABLA_JACK_MASK);
Bradley Rubincb1e2732011-06-23 16:49:20 -07004017 }
4018 tabla_codec_shutdown_hs_polling(codec);
4019 tabla_codec_enable_hs_detect(codec, 0);
Joonwoo Parka9444452011-12-08 18:48:27 -08004020 tabla_sync_hph_state(priv);
Bhalchandra Gajare343cbb02011-09-07 18:58:19 -07004021 } else {
Joonwoo Park0976d012011-12-22 11:48:18 -08004022 pr_debug("%s: Headset detected, mb_v: %d,%d\n",
4023 __func__, mb_v, mic_mv);
Joonwoo Parkf4267c22012-01-10 13:25:24 -08004024 priv->mbhc_fake_ins_start = 0;
Patrick Lai49efeac2011-11-03 11:01:12 -07004025 priv->hph_status |= SND_JACK_HEADSET;
Bradley Rubincb1e2732011-06-23 16:49:20 -07004026 if (priv->headset_jack) {
4027 pr_debug("%s: Reporting insertion %d\n", __func__,
Joonwoo Park0976d012011-12-22 11:48:18 -08004028 SND_JACK_HEADSET);
Joonwoo Park8b1f0982011-12-08 17:12:45 -08004029 tabla_snd_soc_jack_report(priv, priv->headset_jack,
4030 priv->hph_status,
4031 TABLA_JACK_MASK);
Bradley Rubincb1e2732011-06-23 16:49:20 -07004032 }
Joonwoo Parkf4267c22012-01-10 13:25:24 -08004033 /* avoid false button press detect */
4034 msleep(50);
Bradley Rubincb1e2732011-06-23 16:49:20 -07004035 tabla_codec_start_hs_polling(codec);
Joonwoo Parka9444452011-12-08 18:48:27 -08004036 tabla_sync_hph_state(priv);
Bradley Rubincb1e2732011-06-23 16:49:20 -07004037 }
4038
Joonwoo Park8b1f0982011-12-08 17:12:45 -08004039 tabla_unlock_sleep(priv);
Bradley Rubincb1e2732011-06-23 16:49:20 -07004040 return IRQ_HANDLED;
4041}
4042
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004043static irqreturn_t tabla_hs_remove_irq(int irq, void *data)
4044{
4045 struct tabla_priv *priv = data;
4046 struct snd_soc_codec *codec = priv->codec;
Joonwoo Park0976d012011-12-22 11:48:18 -08004047 const struct tabla_mbhc_general_cfg *generic =
4048 TABLA_MBHC_CAL_GENERAL_PTR(priv->calibration);
Bradley Rubin89ffd0a2011-07-21 16:04:06 -07004049 short bias_value;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004050
4051 tabla_disable_irq(codec->control_data, TABLA_IRQ_MBHC_REMOVAL);
4052 tabla_disable_irq(codec->control_data, TABLA_IRQ_MBHC_POTENTIAL);
Bradley Rubin4d09cf42011-08-17 17:59:16 -07004053 tabla_disable_irq(codec->control_data, TABLA_IRQ_MBHC_RELEASE);
Joonwoo Park8b1f0982011-12-08 17:12:45 -08004054 tabla_lock_sleep(priv);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004055
Joonwoo Park0976d012011-12-22 11:48:18 -08004056 usleep_range(generic->t_shutdown_plug_rem,
4057 generic->t_shutdown_plug_rem);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004058
Joonwoo Park0976d012011-12-22 11:48:18 -08004059 bias_value = tabla_codec_sta_dce(codec, 1);
4060 pr_debug("removal interrupt, DCE: %d,%d\n",
4061 bias_value, tabla_codec_sta_dce_v(codec, 1, bias_value));
Bradley Rubin89ffd0a2011-07-21 16:04:06 -07004062
Joonwoo Park0976d012011-12-22 11:48:18 -08004063 if (bias_value < (short) priv->mbhc_data.v_ins_h) {
Bradley Rubin89ffd0a2011-07-21 16:04:06 -07004064 pr_debug("False alarm, headset not actually removed\n");
4065 tabla_codec_start_hs_polling(codec);
4066 } else {
Bhalchandra Gajared9ebb6c2011-10-03 19:54:41 -07004067 /*
4068 * If this removal is not false, first check the micbias
4069 * switch status and switch it to LDOH if it is already
4070 * switched to VDDIO.
4071 */
4072 if (priv->mbhc_micbias_switched)
4073 tabla_codec_switch_micbias(codec, 0);
Patrick Lai49efeac2011-11-03 11:01:12 -07004074 priv->hph_status &= ~SND_JACK_HEADSET;
Bradley Rubin89ffd0a2011-07-21 16:04:06 -07004075 if (priv->headset_jack) {
4076 pr_debug("%s: Reporting removal\n", __func__);
Joonwoo Park8b1f0982011-12-08 17:12:45 -08004077 tabla_snd_soc_jack_report(priv, priv->headset_jack, 0,
4078 TABLA_JACK_MASK);
Bradley Rubin89ffd0a2011-07-21 16:04:06 -07004079 }
4080 tabla_codec_shutdown_hs_polling(codec);
4081
4082 tabla_codec_enable_hs_detect(codec, 1);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004083 }
Joonwoo Park8b1f0982011-12-08 17:12:45 -08004084
4085 tabla_unlock_sleep(priv);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004086 return IRQ_HANDLED;
4087}
4088
4089static unsigned long slimbus_value;
4090
4091static irqreturn_t tabla_slimbus_irq(int irq, void *data)
4092{
4093 struct tabla_priv *priv = data;
4094 struct snd_soc_codec *codec = priv->codec;
4095 int i, j;
4096 u8 val;
4097
Joonwoo Park8b1f0982011-12-08 17:12:45 -08004098 tabla_lock_sleep(priv);
4099
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004100 for (i = 0; i < TABLA_SLIM_NUM_PORT_REG; i++) {
4101 slimbus_value = tabla_interface_reg_read(codec->control_data,
4102 TABLA_SLIM_PGD_PORT_INT_STATUS0 + i);
4103 for_each_set_bit(j, &slimbus_value, BITS_PER_BYTE) {
4104 val = tabla_interface_reg_read(codec->control_data,
4105 TABLA_SLIM_PGD_PORT_INT_SOURCE0 + i*8 + j);
4106 if (val & 0x1)
4107 pr_err_ratelimited("overflow error on port %x,"
4108 " value %x\n", i*8 + j, val);
4109 if (val & 0x2)
4110 pr_err_ratelimited("underflow error on port %x,"
4111 " value %x\n", i*8 + j, val);
4112 }
4113 tabla_interface_reg_write(codec->control_data,
4114 TABLA_SLIM_PGD_PORT_INT_CLR0 + i, 0xFF);
4115 }
4116
Joonwoo Park8b1f0982011-12-08 17:12:45 -08004117 tabla_unlock_sleep(priv);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004118 return IRQ_HANDLED;
4119}
4120
Patrick Lai3043fba2011-08-01 14:15:57 -07004121
4122static int tabla_handle_pdata(struct tabla_priv *tabla)
4123{
4124 struct snd_soc_codec *codec = tabla->codec;
4125 struct tabla_pdata *pdata = tabla->pdata;
4126 int k1, k2, k3, rc = 0;
Santosh Mardi22920282011-10-26 02:38:40 +05304127 u8 leg_mode = pdata->amic_settings.legacy_mode;
4128 u8 txfe_bypass = pdata->amic_settings.txfe_enable;
4129 u8 txfe_buff = pdata->amic_settings.txfe_buff;
4130 u8 flag = pdata->amic_settings.use_pdata;
4131 u8 i = 0, j = 0;
4132 u8 val_txfe = 0, value = 0;
Patrick Lai3043fba2011-08-01 14:15:57 -07004133
4134 if (!pdata) {
4135 rc = -ENODEV;
4136 goto done;
4137 }
4138
4139 /* Make sure settings are correct */
4140 if ((pdata->micbias.ldoh_v > TABLA_LDOH_2P85_V) ||
4141 (pdata->micbias.bias1_cfilt_sel > TABLA_CFILT3_SEL) ||
4142 (pdata->micbias.bias2_cfilt_sel > TABLA_CFILT3_SEL) ||
4143 (pdata->micbias.bias3_cfilt_sel > TABLA_CFILT3_SEL) ||
4144 (pdata->micbias.bias4_cfilt_sel > TABLA_CFILT3_SEL)) {
4145 rc = -EINVAL;
4146 goto done;
4147 }
4148
4149 /* figure out k value */
4150 k1 = tabla_find_k_value(pdata->micbias.ldoh_v,
4151 pdata->micbias.cfilt1_mv);
4152 k2 = tabla_find_k_value(pdata->micbias.ldoh_v,
4153 pdata->micbias.cfilt2_mv);
4154 k3 = tabla_find_k_value(pdata->micbias.ldoh_v,
4155 pdata->micbias.cfilt3_mv);
4156
4157 if (IS_ERR_VALUE(k1) || IS_ERR_VALUE(k2) || IS_ERR_VALUE(k3)) {
4158 rc = -EINVAL;
4159 goto done;
4160 }
4161
4162 /* Set voltage level and always use LDO */
4163 snd_soc_update_bits(codec, TABLA_A_LDO_H_MODE_1, 0x0C,
4164 (pdata->micbias.ldoh_v << 2));
4165
4166 snd_soc_update_bits(codec, TABLA_A_MICB_CFILT_1_VAL, 0xFC,
4167 (k1 << 2));
4168 snd_soc_update_bits(codec, TABLA_A_MICB_CFILT_2_VAL, 0xFC,
4169 (k2 << 2));
4170 snd_soc_update_bits(codec, TABLA_A_MICB_CFILT_3_VAL, 0xFC,
4171 (k3 << 2));
4172
4173 snd_soc_update_bits(codec, TABLA_A_MICB_1_CTL, 0x60,
4174 (pdata->micbias.bias1_cfilt_sel << 5));
4175 snd_soc_update_bits(codec, TABLA_A_MICB_2_CTL, 0x60,
4176 (pdata->micbias.bias2_cfilt_sel << 5));
4177 snd_soc_update_bits(codec, TABLA_A_MICB_3_CTL, 0x60,
4178 (pdata->micbias.bias3_cfilt_sel << 5));
4179 snd_soc_update_bits(codec, TABLA_A_MICB_4_CTL, 0x60,
4180 (pdata->micbias.bias4_cfilt_sel << 5));
4181
Santosh Mardi22920282011-10-26 02:38:40 +05304182 for (i = 0; i < 6; j++, i += 2) {
4183 if (flag & (0x01 << i)) {
4184 value = (leg_mode & (0x01 << i)) ? 0x10 : 0x00;
4185 val_txfe = (txfe_bypass & (0x01 << i)) ? 0x20 : 0x00;
4186 val_txfe = val_txfe |
4187 ((txfe_buff & (0x01 << i)) ? 0x10 : 0x00);
4188 snd_soc_update_bits(codec, TABLA_A_TX_1_2_EN + j * 10,
4189 0x10, value);
4190 snd_soc_update_bits(codec,
4191 TABLA_A_TX_1_2_TEST_EN + j * 10,
4192 0x30, val_txfe);
4193 }
4194 if (flag & (0x01 << (i + 1))) {
4195 value = (leg_mode & (0x01 << (i + 1))) ? 0x01 : 0x00;
4196 val_txfe = (txfe_bypass &
4197 (0x01 << (i + 1))) ? 0x02 : 0x00;
4198 val_txfe |= (txfe_buff &
4199 (0x01 << (i + 1))) ? 0x01 : 0x00;
4200 snd_soc_update_bits(codec, TABLA_A_TX_1_2_EN + j * 10,
4201 0x01, value);
4202 snd_soc_update_bits(codec,
4203 TABLA_A_TX_1_2_TEST_EN + j * 10,
4204 0x03, val_txfe);
4205 }
4206 }
4207 if (flag & 0x40) {
4208 value = (leg_mode & 0x40) ? 0x10 : 0x00;
4209 value = value | ((txfe_bypass & 0x40) ? 0x02 : 0x00);
4210 value = value | ((txfe_buff & 0x40) ? 0x01 : 0x00);
4211 snd_soc_update_bits(codec, TABLA_A_TX_7_MBHC_EN,
4212 0x13, value);
4213 }
Patrick Lai49efeac2011-11-03 11:01:12 -07004214
4215 if (pdata->ocp.use_pdata) {
4216 /* not defined in CODEC specification */
4217 if (pdata->ocp.hph_ocp_limit == 1 ||
4218 pdata->ocp.hph_ocp_limit == 5) {
4219 rc = -EINVAL;
4220 goto done;
4221 }
4222 snd_soc_update_bits(codec, TABLA_A_RX_COM_OCP_CTL,
4223 0x0F, pdata->ocp.num_attempts);
4224 snd_soc_write(codec, TABLA_A_RX_COM_OCP_COUNT,
4225 ((pdata->ocp.run_time << 4) | pdata->ocp.wait_time));
4226 snd_soc_update_bits(codec, TABLA_A_RX_HPH_OCP_CTL,
4227 0xE0, (pdata->ocp.hph_ocp_limit << 5));
4228 }
Patrick Lai3043fba2011-08-01 14:15:57 -07004229done:
4230 return rc;
4231}
4232
Kiran Kandi1f6fd722011-08-11 10:36:11 -07004233static const struct tabla_reg_mask_val tabla_1_1_reg_defaults[] = {
4234
4235 /* Tabla 1.1 MICBIAS changes */
4236 TABLA_REG_VAL(TABLA_A_MICB_1_INT_RBIAS, 0x24),
4237 TABLA_REG_VAL(TABLA_A_MICB_2_INT_RBIAS, 0x24),
4238 TABLA_REG_VAL(TABLA_A_MICB_3_INT_RBIAS, 0x24),
4239 TABLA_REG_VAL(TABLA_A_MICB_4_INT_RBIAS, 0x24),
4240
4241 /* Tabla 1.1 HPH changes */
4242 TABLA_REG_VAL(TABLA_A_RX_HPH_BIAS_PA, 0x57),
4243 TABLA_REG_VAL(TABLA_A_RX_HPH_BIAS_LDO, 0x56),
4244
4245 /* Tabla 1.1 EAR PA changes */
4246 TABLA_REG_VAL(TABLA_A_RX_EAR_BIAS_PA, 0xA6),
4247 TABLA_REG_VAL(TABLA_A_RX_EAR_GAIN, 0x02),
4248 TABLA_REG_VAL(TABLA_A_RX_EAR_VCM, 0x03),
4249
4250 /* Tabla 1.1 Lineout_5 Changes */
4251 TABLA_REG_VAL(TABLA_A_RX_LINE_5_GAIN, 0x10),
4252
4253 /* Tabla 1.1 RX Changes */
4254 TABLA_REG_VAL(TABLA_A_CDC_RX1_B5_CTL, 0x78),
4255 TABLA_REG_VAL(TABLA_A_CDC_RX2_B5_CTL, 0x78),
4256 TABLA_REG_VAL(TABLA_A_CDC_RX3_B5_CTL, 0x78),
4257 TABLA_REG_VAL(TABLA_A_CDC_RX4_B5_CTL, 0x78),
4258 TABLA_REG_VAL(TABLA_A_CDC_RX5_B5_CTL, 0x78),
4259 TABLA_REG_VAL(TABLA_A_CDC_RX6_B5_CTL, 0x78),
4260 TABLA_REG_VAL(TABLA_A_CDC_RX7_B5_CTL, 0x78),
4261
4262 /* Tabla 1.1 RX1 and RX2 Changes */
4263 TABLA_REG_VAL(TABLA_A_CDC_RX1_B6_CTL, 0xA0),
4264 TABLA_REG_VAL(TABLA_A_CDC_RX2_B6_CTL, 0xA0),
4265
4266 /* Tabla 1.1 RX3 to RX7 Changes */
4267 TABLA_REG_VAL(TABLA_A_CDC_RX3_B6_CTL, 0x80),
4268 TABLA_REG_VAL(TABLA_A_CDC_RX4_B6_CTL, 0x80),
4269 TABLA_REG_VAL(TABLA_A_CDC_RX5_B6_CTL, 0x80),
4270 TABLA_REG_VAL(TABLA_A_CDC_RX6_B6_CTL, 0x80),
4271 TABLA_REG_VAL(TABLA_A_CDC_RX7_B6_CTL, 0x80),
4272
4273 /* Tabla 1.1 CLASSG Changes */
4274 TABLA_REG_VAL(TABLA_A_CDC_CLSG_FREQ_THRESH_B3_CTL, 0x1B),
4275};
4276
4277static const struct tabla_reg_mask_val tabla_2_0_reg_defaults[] = {
4278
4279 /* Tabla 2.0 MICBIAS changes */
4280 TABLA_REG_VAL(TABLA_A_MICB_2_MBHC, 0x02),
4281};
4282
4283static void tabla_update_reg_defaults(struct snd_soc_codec *codec)
4284{
4285 u32 i;
4286
4287 for (i = 0; i < ARRAY_SIZE(tabla_1_1_reg_defaults); i++)
4288 snd_soc_write(codec, tabla_1_1_reg_defaults[i].reg,
4289 tabla_1_1_reg_defaults[i].val);
4290
4291 for (i = 0; i < ARRAY_SIZE(tabla_2_0_reg_defaults); i++)
4292 snd_soc_write(codec, tabla_2_0_reg_defaults[i].reg,
4293 tabla_2_0_reg_defaults[i].val);
4294}
4295
4296static const struct tabla_reg_mask_val tabla_codec_reg_init_val[] = {
Patrick Laic7cae882011-11-18 11:52:49 -08004297 /* Initialize current threshold to 350MA
4298 * number of wait and run cycles to 4096
4299 */
Patrick Lai49efeac2011-11-03 11:01:12 -07004300 {TABLA_A_RX_HPH_OCP_CTL, 0xE0, 0x60},
Patrick Laic7cae882011-11-18 11:52:49 -08004301 {TABLA_A_RX_COM_OCP_COUNT, 0xFF, 0xFF},
Kiran Kandi1f6fd722011-08-11 10:36:11 -07004302
Santosh Mardi32171012011-10-28 23:32:06 +05304303 {TABLA_A_QFUSE_CTL, 0xFF, 0x03},
4304
Kiran Kandi1f6fd722011-08-11 10:36:11 -07004305 /* Initialize gain registers to use register gain */
4306 {TABLA_A_RX_HPH_L_GAIN, 0x10, 0x10},
4307 {TABLA_A_RX_HPH_R_GAIN, 0x10, 0x10},
4308 {TABLA_A_RX_LINE_1_GAIN, 0x10, 0x10},
4309 {TABLA_A_RX_LINE_2_GAIN, 0x10, 0x10},
4310 {TABLA_A_RX_LINE_3_GAIN, 0x10, 0x10},
4311 {TABLA_A_RX_LINE_4_GAIN, 0x10, 0x10},
4312
4313 /* Initialize mic biases to differential mode */
4314 {TABLA_A_MICB_1_INT_RBIAS, 0x24, 0x24},
4315 {TABLA_A_MICB_2_INT_RBIAS, 0x24, 0x24},
4316 {TABLA_A_MICB_3_INT_RBIAS, 0x24, 0x24},
4317 {TABLA_A_MICB_4_INT_RBIAS, 0x24, 0x24},
4318
4319 {TABLA_A_CDC_CONN_CLSG_CTL, 0x3C, 0x14},
4320
4321 /* Use 16 bit sample size for TX1 to TX6 */
4322 {TABLA_A_CDC_CONN_TX_SB_B1_CTL, 0x30, 0x20},
4323 {TABLA_A_CDC_CONN_TX_SB_B2_CTL, 0x30, 0x20},
4324 {TABLA_A_CDC_CONN_TX_SB_B3_CTL, 0x30, 0x20},
4325 {TABLA_A_CDC_CONN_TX_SB_B4_CTL, 0x30, 0x20},
4326 {TABLA_A_CDC_CONN_TX_SB_B5_CTL, 0x30, 0x20},
4327 {TABLA_A_CDC_CONN_TX_SB_B6_CTL, 0x30, 0x20},
4328
4329 /* Use 16 bit sample size for TX7 to TX10 */
4330 {TABLA_A_CDC_CONN_TX_SB_B7_CTL, 0x60, 0x40},
4331 {TABLA_A_CDC_CONN_TX_SB_B8_CTL, 0x60, 0x40},
4332 {TABLA_A_CDC_CONN_TX_SB_B9_CTL, 0x60, 0x40},
4333 {TABLA_A_CDC_CONN_TX_SB_B10_CTL, 0x60, 0x40},
4334
4335 /* Use 16 bit sample size for RX */
4336 {TABLA_A_CDC_CONN_RX_SB_B1_CTL, 0xFF, 0xAA},
4337 {TABLA_A_CDC_CONN_RX_SB_B2_CTL, 0xFF, 0xAA},
4338
4339 /*enable HPF filter for TX paths */
4340 {TABLA_A_CDC_TX1_MUX_CTL, 0x8, 0x0},
4341 {TABLA_A_CDC_TX2_MUX_CTL, 0x8, 0x0},
4342 {TABLA_A_CDC_TX3_MUX_CTL, 0x8, 0x0},
4343 {TABLA_A_CDC_TX4_MUX_CTL, 0x8, 0x0},
4344 {TABLA_A_CDC_TX5_MUX_CTL, 0x8, 0x0},
4345 {TABLA_A_CDC_TX6_MUX_CTL, 0x8, 0x0},
4346 {TABLA_A_CDC_TX7_MUX_CTL, 0x8, 0x0},
4347 {TABLA_A_CDC_TX8_MUX_CTL, 0x8, 0x0},
4348 {TABLA_A_CDC_TX9_MUX_CTL, 0x8, 0x0},
4349 {TABLA_A_CDC_TX10_MUX_CTL, 0x8, 0x0},
4350};
4351
4352static void tabla_codec_init_reg(struct snd_soc_codec *codec)
4353{
4354 u32 i;
4355
4356 for (i = 0; i < ARRAY_SIZE(tabla_codec_reg_init_val); i++)
4357 snd_soc_update_bits(codec, tabla_codec_reg_init_val[i].reg,
4358 tabla_codec_reg_init_val[i].mask,
4359 tabla_codec_reg_init_val[i].val);
4360}
4361
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004362static int tabla_codec_probe(struct snd_soc_codec *codec)
4363{
4364 struct tabla *control;
4365 struct tabla_priv *tabla;
4366 struct snd_soc_dapm_context *dapm = &codec->dapm;
4367 int ret = 0;
4368 int i;
Kiran Kandi8b3a8302011-09-27 16:13:28 -07004369 u8 tabla_version;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004370
4371 codec->control_data = dev_get_drvdata(codec->dev->parent);
4372 control = codec->control_data;
4373
4374 tabla = kzalloc(sizeof(struct tabla_priv), GFP_KERNEL);
4375 if (!tabla) {
4376 dev_err(codec->dev, "Failed to allocate private data\n");
4377 return -ENOMEM;
4378 }
4379
Bhalchandra Gajare02d90cd2011-09-30 16:14:00 -07004380 /* Make sure mbhc micbias register addresses are zeroed out */
4381 memset(&tabla->mbhc_bias_regs, 0,
4382 sizeof(struct mbhc_micbias_regs));
Bhalchandra Gajared9ebb6c2011-10-03 19:54:41 -07004383 tabla->cfilt_k_value = 0;
4384 tabla->mbhc_micbias_switched = false;
Bhalchandra Gajare02d90cd2011-09-30 16:14:00 -07004385
Joonwoo Park0976d012011-12-22 11:48:18 -08004386 /* Make sure mbhc intenal calibration data is zeroed out */
4387 memset(&tabla->mbhc_data, 0,
4388 sizeof(struct mbhc_internal_cal_data));
4389 tabla->mbhc_data.t_dce = DEFAULT_DCE_WAIT;
4390 tabla->mbhc_data.t_sta = DEFAULT_STA_WAIT;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004391 snd_soc_codec_set_drvdata(codec, tabla);
4392
Kiran Kandi6fae8bf2011-08-15 10:36:42 -07004393 tabla->mclk_enabled = false;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004394 tabla->bandgap_type = TABLA_BANDGAP_OFF;
4395 tabla->clock_active = false;
4396 tabla->config_mode_active = false;
4397 tabla->mbhc_polling_active = false;
Joonwoo Parkf4267c22012-01-10 13:25:24 -08004398 tabla->mbhc_fake_ins_start = 0;
Bradley Rubincb3950a2011-08-18 13:07:26 -07004399 tabla->no_mic_headset_override = false;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004400 tabla->codec = codec;
Patrick Lai3043fba2011-08-01 14:15:57 -07004401 tabla->pdata = dev_get_platdata(codec->dev->parent);
Santosh Mardie15e2302011-11-15 10:39:23 +05304402 tabla->intf_type = tabla_get_intf_type();
Joonwoo Park8b1f0982011-12-08 17:12:45 -08004403 atomic_set(&tabla->pm_cnt, 1);
4404 init_waitqueue_head(&tabla->pm_wq);
Patrick Lai3043fba2011-08-01 14:15:57 -07004405
Santosh Mardi22920282011-10-26 02:38:40 +05304406 tabla_update_reg_defaults(codec);
4407 tabla_codec_init_reg(codec);
Patrick Lai3043fba2011-08-01 14:15:57 -07004408
Santosh Mardi22920282011-10-26 02:38:40 +05304409 ret = tabla_handle_pdata(tabla);
Patrick Lai3043fba2011-08-01 14:15:57 -07004410 if (IS_ERR_VALUE(ret)) {
4411 pr_err("%s: bad pdata\n", __func__);
4412 goto err_pdata;
4413 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004414
4415 /* TODO only enable bandgap when necessary in order to save power */
4416 tabla_codec_enable_bandgap(codec, TABLA_BANDGAP_AUDIO_MODE);
4417 tabla_codec_enable_clock_block(codec, 0);
4418
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004419 snd_soc_add_controls(codec, tabla_snd_controls,
4420 ARRAY_SIZE(tabla_snd_controls));
4421 snd_soc_dapm_new_controls(dapm, tabla_dapm_widgets,
4422 ARRAY_SIZE(tabla_dapm_widgets));
Santosh Mardie15e2302011-11-15 10:39:23 +05304423 if (tabla->intf_type == TABLA_INTERFACE_TYPE_I2C) {
4424 snd_soc_dapm_new_controls(dapm, tabla_dapm_i2s_widgets,
4425 ARRAY_SIZE(tabla_dapm_i2s_widgets));
4426 snd_soc_dapm_add_routes(dapm, audio_i2s_map,
4427 ARRAY_SIZE(audio_i2s_map));
4428 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004429 snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
Kiran Kandi8b3a8302011-09-27 16:13:28 -07004430
4431 tabla_version = snd_soc_read(codec, TABLA_A_CHIP_VERSION);
Joonwoo Park0976d012011-12-22 11:48:18 -08004432 pr_info("%s : Tabla version reg 0x%2x\n", __func__,
4433 (u32)tabla_version);
Kiran Kandi8b3a8302011-09-27 16:13:28 -07004434
4435 tabla_version &= 0x1F;
4436 pr_info("%s : Tabla version %u\n", __func__, (u32)tabla_version);
4437
Kiran Kandi7a9fd902011-11-14 13:51:45 -08004438 if ((tabla_version == TABLA_VERSION_1_0) ||
4439 (tabla_version == TABLA_VERSION_1_1)) {
4440 snd_soc_dapm_add_routes(dapm, tabla_1_x_lineout_2_to_4_map,
Kiran Kandi8b3a8302011-09-27 16:13:28 -07004441 ARRAY_SIZE(tabla_1_x_lineout_2_to_4_map));
4442
Kiran Kandi7a9fd902011-11-14 13:51:45 -08004443 } else if (tabla_version == TABLA_VERSION_2_0) {
4444 snd_soc_dapm_add_routes(dapm, tabla_2_x_lineout_2_to_4_map,
4445 ARRAY_SIZE(tabla_2_x_lineout_2_to_4_map));
4446 } else {
4447 pr_err("%s : ERROR. Unsupported Tabla version 0x%2x\n",
4448 __func__, (u32)tabla_version);
4449 goto err_pdata;
4450 }
4451
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004452 snd_soc_dapm_sync(dapm);
4453
4454 ret = tabla_request_irq(codec->control_data, TABLA_IRQ_MBHC_INSERTION,
4455 tabla_hs_insert_irq, "Headset insert detect", tabla);
4456 if (ret) {
4457 pr_err("%s: Failed to request irq %d\n", __func__,
4458 TABLA_IRQ_MBHC_INSERTION);
4459 goto err_insert_irq;
4460 }
4461 tabla_disable_irq(codec->control_data, TABLA_IRQ_MBHC_INSERTION);
4462
4463 ret = tabla_request_irq(codec->control_data, TABLA_IRQ_MBHC_REMOVAL,
4464 tabla_hs_remove_irq, "Headset remove detect", tabla);
4465 if (ret) {
4466 pr_err("%s: Failed to request irq %d\n", __func__,
4467 TABLA_IRQ_MBHC_REMOVAL);
4468 goto err_remove_irq;
4469 }
4470 tabla_disable_irq(codec->control_data, TABLA_IRQ_MBHC_REMOVAL);
4471
4472 ret = tabla_request_irq(codec->control_data, TABLA_IRQ_MBHC_POTENTIAL,
Bradley Rubincb1e2732011-06-23 16:49:20 -07004473 tabla_dce_handler, "DC Estimation detect", tabla);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004474 if (ret) {
4475 pr_err("%s: Failed to request irq %d\n", __func__,
4476 TABLA_IRQ_MBHC_POTENTIAL);
4477 goto err_potential_irq;
4478 }
4479 tabla_disable_irq(codec->control_data, TABLA_IRQ_MBHC_POTENTIAL);
4480
Bradley Rubincb1e2732011-06-23 16:49:20 -07004481 ret = tabla_request_irq(codec->control_data, TABLA_IRQ_MBHC_RELEASE,
4482 tabla_release_handler, "Button Release detect", tabla);
4483 if (ret) {
4484 pr_err("%s: Failed to request irq %d\n", __func__,
4485 TABLA_IRQ_MBHC_RELEASE);
4486 goto err_release_irq;
4487 }
Bradley Rubin4d09cf42011-08-17 17:59:16 -07004488 tabla_disable_irq(codec->control_data, TABLA_IRQ_MBHC_RELEASE);
Bradley Rubincb1e2732011-06-23 16:49:20 -07004489
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004490 ret = tabla_request_irq(codec->control_data, TABLA_IRQ_SLIMBUS,
4491 tabla_slimbus_irq, "SLIMBUS Slave", tabla);
4492 if (ret) {
4493 pr_err("%s: Failed to request irq %d\n", __func__,
4494 TABLA_IRQ_SLIMBUS);
4495 goto err_slimbus_irq;
4496 }
4497
4498 for (i = 0; i < TABLA_SLIM_NUM_PORT_REG; i++)
4499 tabla_interface_reg_write(codec->control_data,
4500 TABLA_SLIM_PGD_PORT_INT_EN0 + i, 0xFF);
4501
Patrick Lai49efeac2011-11-03 11:01:12 -07004502 ret = tabla_request_irq(codec->control_data,
4503 TABLA_IRQ_HPH_PA_OCPL_FAULT, tabla_hphl_ocp_irq,
4504 "HPH_L OCP detect", tabla);
4505 if (ret) {
4506 pr_err("%s: Failed to request irq %d\n", __func__,
4507 TABLA_IRQ_HPH_PA_OCPL_FAULT);
4508 goto err_hphl_ocp_irq;
4509 }
Patrick Lai92032be2011-12-19 14:14:25 -08004510 tabla_disable_irq(codec->control_data, TABLA_IRQ_HPH_PA_OCPL_FAULT);
Patrick Lai49efeac2011-11-03 11:01:12 -07004511
4512 ret = tabla_request_irq(codec->control_data,
4513 TABLA_IRQ_HPH_PA_OCPR_FAULT, tabla_hphr_ocp_irq,
4514 "HPH_R OCP detect", tabla);
4515 if (ret) {
4516 pr_err("%s: Failed to request irq %d\n", __func__,
4517 TABLA_IRQ_HPH_PA_OCPR_FAULT);
4518 goto err_hphr_ocp_irq;
4519 }
Patrick Lai92032be2011-12-19 14:14:25 -08004520 tabla_disable_irq(codec->control_data, TABLA_IRQ_HPH_PA_OCPR_FAULT);
Patrick Lai49efeac2011-11-03 11:01:12 -07004521
Bradley Rubincb3950a2011-08-18 13:07:26 -07004522#ifdef CONFIG_DEBUG_FS
4523 debug_tabla_priv = tabla;
4524#endif
4525
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004526 return ret;
4527
Patrick Lai49efeac2011-11-03 11:01:12 -07004528err_hphr_ocp_irq:
4529 tabla_free_irq(codec->control_data, TABLA_IRQ_HPH_PA_OCPL_FAULT, tabla);
4530err_hphl_ocp_irq:
4531 tabla_free_irq(codec->control_data, TABLA_IRQ_SLIMBUS, tabla);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004532err_slimbus_irq:
Bradley Rubincb1e2732011-06-23 16:49:20 -07004533 tabla_free_irq(codec->control_data, TABLA_IRQ_MBHC_RELEASE, tabla);
4534err_release_irq:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004535 tabla_free_irq(codec->control_data, TABLA_IRQ_MBHC_POTENTIAL, tabla);
4536err_potential_irq:
4537 tabla_free_irq(codec->control_data, TABLA_IRQ_MBHC_REMOVAL, tabla);
4538err_remove_irq:
4539 tabla_free_irq(codec->control_data, TABLA_IRQ_MBHC_INSERTION, tabla);
4540err_insert_irq:
Patrick Lai3043fba2011-08-01 14:15:57 -07004541err_pdata:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004542 kfree(tabla);
4543 return ret;
4544}
4545static int tabla_codec_remove(struct snd_soc_codec *codec)
4546{
4547 struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
4548 tabla_free_irq(codec->control_data, TABLA_IRQ_SLIMBUS, tabla);
Bradley Rubincb1e2732011-06-23 16:49:20 -07004549 tabla_free_irq(codec->control_data, TABLA_IRQ_MBHC_RELEASE, tabla);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004550 tabla_free_irq(codec->control_data, TABLA_IRQ_MBHC_POTENTIAL, tabla);
4551 tabla_free_irq(codec->control_data, TABLA_IRQ_MBHC_REMOVAL, tabla);
4552 tabla_free_irq(codec->control_data, TABLA_IRQ_MBHC_INSERTION, tabla);
4553 tabla_codec_disable_clock_block(codec);
4554 tabla_codec_enable_bandgap(codec, TABLA_BANDGAP_OFF);
4555 kfree(tabla);
4556 return 0;
4557}
4558static struct snd_soc_codec_driver soc_codec_dev_tabla = {
4559 .probe = tabla_codec_probe,
4560 .remove = tabla_codec_remove,
4561 .read = tabla_read,
4562 .write = tabla_write,
4563
4564 .readable_register = tabla_readable,
4565 .volatile_register = tabla_volatile,
4566
4567 .reg_cache_size = TABLA_CACHE_SIZE,
4568 .reg_cache_default = tabla_reg_defaults,
4569 .reg_word_size = 1,
4570};
Bradley Rubincb3950a2011-08-18 13:07:26 -07004571
4572#ifdef CONFIG_DEBUG_FS
4573static struct dentry *debugfs_poke;
4574
4575static int codec_debug_open(struct inode *inode, struct file *file)
4576{
4577 file->private_data = inode->i_private;
4578 return 0;
4579}
4580
4581static ssize_t codec_debug_write(struct file *filp,
4582 const char __user *ubuf, size_t cnt, loff_t *ppos)
4583{
4584 char lbuf[32];
4585 char *buf;
4586 int rc;
4587
4588 if (cnt > sizeof(lbuf) - 1)
4589 return -EINVAL;
4590
4591 rc = copy_from_user(lbuf, ubuf, cnt);
4592 if (rc)
4593 return -EFAULT;
4594
4595 lbuf[cnt] = '\0';
4596 buf = (char *)lbuf;
4597 debug_tabla_priv->no_mic_headset_override = (*strsep(&buf, " ") == '0')
4598 ? false : true;
4599
4600 return rc;
4601}
4602
4603static const struct file_operations codec_debug_ops = {
4604 .open = codec_debug_open,
4605 .write = codec_debug_write,
4606};
4607#endif
4608
Joonwoo Park8b1f0982011-12-08 17:12:45 -08004609#ifdef CONFIG_PM
4610static int tabla_suspend(struct device *dev)
4611{
4612 int ret = 0, cnt;
4613 struct platform_device *pdev = to_platform_device(dev);
4614 struct tabla_priv *tabla = platform_get_drvdata(pdev);
4615
4616 cnt = atomic_read(&tabla->pm_cnt);
4617 if (cnt > 0) {
4618 if (wait_event_timeout(tabla->pm_wq,
4619 (atomic_cmpxchg(&tabla->pm_cnt, 1, 0)
4620 == 1), 5 * HZ)) {
4621 dev_dbg(dev, "system suspend pm_cnt %d\n",
4622 atomic_read(&tabla->pm_cnt));
4623 } else {
4624 dev_err(dev, "%s timed out pm_cnt = %d\n",
4625 __func__, atomic_read(&tabla->pm_cnt));
4626 WARN_ON_ONCE(1);
4627 ret = -EBUSY;
4628 }
4629 } else if (cnt == 0)
4630 dev_warn(dev, "system is already in suspend, pm_cnt %d\n",
4631 atomic_read(&tabla->pm_cnt));
4632 else {
4633 WARN(1, "unexpected pm_cnt %d\n", cnt);
4634 ret = -EFAULT;
4635 }
4636
4637 return ret;
4638}
4639
4640static int tabla_resume(struct device *dev)
4641{
4642 int ret = 0, cnt;
4643 struct platform_device *pdev = to_platform_device(dev);
4644 struct tabla_priv *tabla = platform_get_drvdata(pdev);
4645
4646 cnt = atomic_cmpxchg(&tabla->pm_cnt, 0, 1);
4647 if (cnt == 0) {
4648 dev_dbg(dev, "system resume, pm_cnt %d\n",
4649 atomic_read(&tabla->pm_cnt));
4650 wake_up_all(&tabla->pm_wq);
4651 } else if (cnt > 0)
4652 dev_warn(dev, "system is already awake, pm_cnt %d\n", cnt);
4653 else {
4654 WARN(1, "unexpected pm_cnt %d\n", cnt);
4655 ret = -EFAULT;
4656 }
4657
4658 return ret;
4659}
4660
4661static const struct dev_pm_ops tabla_pm_ops = {
4662 .suspend = tabla_suspend,
4663 .resume = tabla_resume,
4664};
4665#endif
4666
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004667static int __devinit tabla_probe(struct platform_device *pdev)
4668{
Santosh Mardie15e2302011-11-15 10:39:23 +05304669 int ret = 0;
Bradley Rubincb3950a2011-08-18 13:07:26 -07004670#ifdef CONFIG_DEBUG_FS
4671 debugfs_poke = debugfs_create_file("TRRS",
4672 S_IFREG | S_IRUGO, NULL, (void *) "TRRS", &codec_debug_ops);
4673
4674#endif
Santosh Mardie15e2302011-11-15 10:39:23 +05304675 if (tabla_get_intf_type() == TABLA_INTERFACE_TYPE_SLIMBUS)
4676 ret = snd_soc_register_codec(&pdev->dev, &soc_codec_dev_tabla,
4677 tabla_dai, ARRAY_SIZE(tabla_dai));
4678 else if (tabla_get_intf_type() == TABLA_INTERFACE_TYPE_I2C)
4679 ret = snd_soc_register_codec(&pdev->dev, &soc_codec_dev_tabla,
4680 tabla_i2s_dai, ARRAY_SIZE(tabla_i2s_dai));
4681 return ret;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004682}
4683static int __devexit tabla_remove(struct platform_device *pdev)
4684{
4685 snd_soc_unregister_codec(&pdev->dev);
Bradley Rubincb3950a2011-08-18 13:07:26 -07004686
4687#ifdef CONFIG_DEBUG_FS
4688 debugfs_remove(debugfs_poke);
4689#endif
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004690 return 0;
4691}
4692static struct platform_driver tabla_codec_driver = {
4693 .probe = tabla_probe,
4694 .remove = tabla_remove,
4695 .driver = {
4696 .name = "tabla_codec",
4697 .owner = THIS_MODULE,
Joonwoo Park8b1f0982011-12-08 17:12:45 -08004698#ifdef CONFIG_PM
4699 .pm = &tabla_pm_ops,
4700#endif
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004701 },
4702};
4703
4704static int __init tabla_codec_init(void)
4705{
4706 return platform_driver_register(&tabla_codec_driver);
4707}
4708
4709static void __exit tabla_codec_exit(void)
4710{
4711 platform_driver_unregister(&tabla_codec_driver);
4712}
4713
4714module_init(tabla_codec_init);
4715module_exit(tabla_codec_exit);
4716
4717MODULE_DESCRIPTION("Tabla codec driver");
4718MODULE_VERSION("1.0");
4719MODULE_LICENSE("GPL v2");