blob: 7ba43c03550dad7189a29cfa9f3d37a044faf0b9 [file] [log] [blame]
Ravishankar Sarawadi839fcf32012-11-14 12:13:00 -08001/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
Kiran Kandic3b24402012-06-11 00:05:59 -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>
14#include <linux/firmware.h>
15#include <linux/slab.h>
16#include <linux/platform_device.h>
17#include <linux/device.h>
18#include <linux/printk.h>
19#include <linux/ratelimit.h>
20#include <linux/debugfs.h>
Joonwoo Park9bbb4d12012-11-09 19:58:11 -080021#include <linux/wait.h>
22#include <linux/bitops.h>
Kiran Kandic3b24402012-06-11 00:05:59 -070023#include <linux/mfd/wcd9xxx/core.h>
24#include <linux/mfd/wcd9xxx/wcd9xxx_registers.h>
25#include <linux/mfd/wcd9xxx/wcd9320_registers.h>
26#include <linux/mfd/wcd9xxx/pdata.h>
Joonwoo Park448a8fc2013-04-10 15:25:58 -070027#include <linux/regulator/consumer.h>
Kiran Kandic3b24402012-06-11 00:05:59 -070028#include <sound/pcm.h>
29#include <sound/pcm_params.h>
30#include <sound/soc.h>
31#include <sound/soc-dapm.h>
32#include <sound/tlv.h>
33#include <linux/bitops.h>
34#include <linux/delay.h>
35#include <linux/pm_runtime.h>
36#include <linux/kernel.h>
37#include <linux/gpio.h>
38#include "wcd9320.h"
Joonwoo Parka8890262012-10-15 12:04:27 -070039#include "wcd9xxx-resmgr.h"
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -080040#include "wcd9xxx-common.h"
Kiran Kandic3b24402012-06-11 00:05:59 -070041
Joonwoo Park1d05bb92013-03-07 16:55:06 -080042#define TAIKO_MAD_SLIMBUS_TX_PORT 12
43#define TAIKO_MAD_AUDIO_FIRMWARE_PATH "wcd9320/wcd9320_mad_audio.bin"
44
Bhalchandra Gajare9581aed2013-03-29 17:06:10 -070045#define TAIKO_HPH_PA_SETTLE_COMP_ON 3000
Bhalchandra Gajareef7810e2013-03-29 16:50:37 -070046#define TAIKO_HPH_PA_SETTLE_COMP_OFF 13000
47
Joonwoo Park125cd4e2012-12-11 15:16:11 -080048static atomic_t kp_taiko_priv;
49static int spkr_drv_wrnd_param_set(const char *val,
50 const struct kernel_param *kp);
51static int spkr_drv_wrnd = 1;
52
53static struct kernel_param_ops spkr_drv_wrnd_param_ops = {
54 .set = spkr_drv_wrnd_param_set,
55 .get = param_get_int,
56};
Joonwoo Park1d05bb92013-03-07 16:55:06 -080057
58static struct afe_param_slimbus_slave_port_cfg taiko_slimbus_slave_port_cfg = {
59 .minor_version = 1,
60 .slimbus_dev_id = AFE_SLIMBUS_DEVICE_1,
61 .slave_dev_pgd_la = 0,
62 .slave_dev_intfdev_la = 0,
63 .bit_width = 16,
64 .data_format = 0,
65 .num_channels = 1
66};
67
68enum {
69 RESERVED = 0,
70 AANC_LPF_FF_FB = 1,
71 AANC_LPF_COEFF_MSB,
72 AANC_LPF_COEFF_LSB,
73 HW_MAD_AUDIO_ENABLE,
74 HW_MAD_ULTR_ENABLE,
75 HW_MAD_BEACON_ENABLE,
76 HW_MAD_AUDIO_SLEEP_TIME,
77 HW_MAD_ULTR_SLEEP_TIME,
78 HW_MAD_BEACON_SLEEP_TIME,
79 HW_MAD_TX_AUDIO_SWITCH_OFF,
80 HW_MAD_TX_ULTR_SWITCH_OFF,
81 HW_MAD_TX_BEACON_SWITCH_OFF,
82 MAD_AUDIO_INT_DEST_SELECT_REG,
83 MAD_ULT_INT_DEST_SELECT_REG,
84 MAD_BEACON_INT_DEST_SELECT_REG,
85 MAD_CLIP_INT_DEST_SELECT_REG,
86 MAD_VBAT_INT_DEST_SELECT_REG,
87 MAD_AUDIO_INT_MASK_REG,
88 MAD_ULT_INT_MASK_REG,
89 MAD_BEACON_INT_MASK_REG,
90 MAD_CLIP_INT_MASK_REG,
91 MAD_VBAT_INT_MASK_REG,
92 MAD_AUDIO_INT_STATUS_REG,
93 MAD_ULT_INT_STATUS_REG,
94 MAD_BEACON_INT_STATUS_REG,
95 MAD_CLIP_INT_STATUS_REG,
96 MAD_VBAT_INT_STATUS_REG,
97 MAD_AUDIO_INT_CLEAR_REG,
98 MAD_ULT_INT_CLEAR_REG,
99 MAD_BEACON_INT_CLEAR_REG,
100 MAD_CLIP_INT_CLEAR_REG,
101 MAD_VBAT_INT_CLEAR_REG,
102 SB_PGD_PORT_TX_WATERMARK_n,
103 SB_PGD_PORT_TX_ENABLE_n,
104 SB_PGD_PORT_RX_WATERMARK_n,
105 SB_PGD_PORT_RX_ENABLE_n,
Damir Didjustodcfdff82013-03-21 23:26:41 -0700106 SB_PGD_TX_PORTn_MULTI_CHNL_0,
107 SB_PGD_TX_PORTn_MULTI_CHNL_1,
108 SB_PGD_RX_PORTn_MULTI_CHNL_0,
109 SB_PGD_RX_PORTn_MULTI_CHNL_1,
110 AANC_FF_GAIN_ADAPTIVE,
111 AANC_FFGAIN_ADAPTIVE_EN,
112 AANC_GAIN_CONTROL,
Joonwoo Park1d05bb92013-03-07 16:55:06 -0800113 MAX_CFG_REGISTERS,
114};
115
Damir Didjustodcfdff82013-03-21 23:26:41 -0700116static struct afe_param_cdc_reg_cfg audio_reg_cfg[] = {
Joonwoo Park1d05bb92013-03-07 16:55:06 -0800117 {
118 1,
119 (TAIKO_REGISTER_START_OFFSET + TAIKO_A_CDC_MAD_MAIN_CTL_1),
120 HW_MAD_AUDIO_ENABLE, 0x1, 8, 0
121 },
122 {
123 1,
124 (TAIKO_REGISTER_START_OFFSET + TAIKO_A_CDC_MAD_AUDIO_CTL_3),
125 HW_MAD_AUDIO_SLEEP_TIME, 0xF, 8, 0
126 },
127 {
128 1,
129 (TAIKO_REGISTER_START_OFFSET + TAIKO_A_CDC_MAD_AUDIO_CTL_4),
130 HW_MAD_TX_AUDIO_SWITCH_OFF, 0x1, 8, 0
131 },
132 {
133 1,
134 (TAIKO_REGISTER_START_OFFSET + TAIKO_A_INTR_DESTN3),
135 MAD_AUDIO_INT_DEST_SELECT_REG, 0x1, 8, 0
136 },
137 {
138 1,
139 (TAIKO_REGISTER_START_OFFSET + TAIKO_A_INTR_MASK3),
140 MAD_AUDIO_INT_MASK_REG, 0x1, 8, 0
141 },
142 {
143 1,
144 (TAIKO_REGISTER_START_OFFSET + TAIKO_A_INTR_STATUS3),
145 MAD_AUDIO_INT_STATUS_REG, 0x1, 8, 0
146 },
147 {
148 1,
149 (TAIKO_REGISTER_START_OFFSET + TAIKO_A_INTR_CLEAR3),
150 MAD_AUDIO_INT_CLEAR_REG, 0x1, 8, 0
151 },
152 {
153 1,
154 (TAIKO_REGISTER_START_OFFSET + TAIKO_SB_PGD_PORT_TX_BASE),
155 SB_PGD_PORT_TX_WATERMARK_n, 0x1E, 8, 0x1
156 },
157 {
158 1,
159 (TAIKO_REGISTER_START_OFFSET + TAIKO_SB_PGD_PORT_TX_BASE),
160 SB_PGD_PORT_TX_ENABLE_n, 0x1, 8, 0x1
161 },
162 {
163 1,
164 (TAIKO_REGISTER_START_OFFSET + TAIKO_SB_PGD_PORT_RX_BASE),
165 SB_PGD_PORT_RX_WATERMARK_n, 0x1E, 8, 0x1
166 },
167 {
168 1,
169 (TAIKO_REGISTER_START_OFFSET + TAIKO_SB_PGD_PORT_RX_BASE),
170 SB_PGD_PORT_RX_ENABLE_n, 0x1, 8, 0x1
Damir Didjustodcfdff82013-03-21 23:26:41 -0700171 },
172 { 1,
173 (TAIKO_REGISTER_START_OFFSET + TAIKO_A_CDC_ANC1_IIR_B1_CTL),
174 AANC_FF_GAIN_ADAPTIVE, 0x4, 8, 0
175 },
176 { 1,
177 (TAIKO_REGISTER_START_OFFSET + TAIKO_A_CDC_ANC1_IIR_B1_CTL),
178 AANC_FFGAIN_ADAPTIVE_EN, 0x8, 8, 0
179 },
180 {
181 1,
182 (TAIKO_REGISTER_START_OFFSET + TAIKO_A_CDC_ANC1_GAIN_CTL),
183 AANC_GAIN_CONTROL, 0xFF, 8, 0
184 },
Joonwoo Park1d05bb92013-03-07 16:55:06 -0800185};
186
Damir Didjustodcfdff82013-03-21 23:26:41 -0700187static struct afe_param_cdc_reg_cfg_data taiko_audio_reg_cfg = {
188 .num_registers = ARRAY_SIZE(audio_reg_cfg),
189 .reg_data = audio_reg_cfg,
190};
191
192static struct afe_param_id_cdc_aanc_version taiko_cdc_aanc_version = {
193 .cdc_aanc_minor_version = AFE_API_VERSION_CDC_AANC_VERSION,
194 .aanc_hw_version = AANC_HW_BLOCK_VERSION_2,
Joonwoo Park1d05bb92013-03-07 16:55:06 -0800195};
196
Joonwoo Park125cd4e2012-12-11 15:16:11 -0800197module_param_cb(spkr_drv_wrnd, &spkr_drv_wrnd_param_ops, &spkr_drv_wrnd, 0644);
198MODULE_PARM_DESC(spkr_drv_wrnd,
199 "Run software workaround to avoid leakage on the speaker drive");
200
Kiran Kandic3b24402012-06-11 00:05:59 -0700201#define WCD9320_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |\
202 SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 |\
203 SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000)
204
Kiran Kandic3b24402012-06-11 00:05:59 -0700205#define NUM_DECIMATORS 10
206#define NUM_INTERPOLATORS 7
207#define BITS_PER_REG 8
Kuirong Wang906ac472012-07-09 12:54:44 -0700208#define TAIKO_TX_PORT_NUMBER 16
Kiran Kandic3b24402012-06-11 00:05:59 -0700209
Kiran Kandic3b24402012-06-11 00:05:59 -0700210#define TAIKO_I2S_MASTER_MODE_MASK 0x08
Damir Didjusto1a353ce2013-04-02 11:45:47 -0700211
212#define TAIKO_DMIC_SAMPLE_RATE_DIV_2 0x0
213#define TAIKO_DMIC_SAMPLE_RATE_DIV_3 0x1
214#define TAIKO_DMIC_SAMPLE_RATE_DIV_4 0x2
215
216#define TAIKO_DMIC_B1_CTL_DIV_2 0x00
217#define TAIKO_DMIC_B1_CTL_DIV_3 0x22
218#define TAIKO_DMIC_B1_CTL_DIV_4 0x44
219
220#define TAIKO_DMIC_B2_CTL_DIV_2 0x00
221#define TAIKO_DMIC_B2_CTL_DIV_3 0x02
222#define TAIKO_DMIC_B2_CTL_DIV_4 0x04
223
224#define TAIKO_ANC_DMIC_X2_ON 0x1
225#define TAIKO_ANC_DMIC_X2_OFF 0x0
Joonwoo Park9bbb4d12012-11-09 19:58:11 -0800226
227#define TAIKO_SLIM_CLOSE_TIMEOUT 1000
228#define TAIKO_SLIM_IRQ_OVERFLOW (1 << 0)
229#define TAIKO_SLIM_IRQ_UNDERFLOW (1 << 1)
230#define TAIKO_SLIM_IRQ_PORT_CLOSED (1 << 2)
Venkat Sudhira50a3762012-11-26 12:12:15 -0800231#define TAIKO_MCLK_CLK_12P288MHZ 12288000
232#define TAIKO_MCLK_CLK_9P6HZ 9600000
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -0800233
Bhalchandra Gajare5b40c532013-02-19 13:36:47 -0800234#define TAIKO_FORMATS_S16_S24_LE (SNDRV_PCM_FMTBIT_S16_LE | \
235 SNDRV_PCM_FORMAT_S24_LE)
236
237#define TAIKO_FORMATS (SNDRV_PCM_FMTBIT_S16_LE)
238
Kuirong Wang906ac472012-07-09 12:54:44 -0700239enum {
240 AIF1_PB = 0,
241 AIF1_CAP,
242 AIF2_PB,
243 AIF2_CAP,
244 AIF3_PB,
245 AIF3_CAP,
Gopikrishnaiah Anandana2627572013-02-26 13:30:50 -0500246 AIF4_VIFEED,
Joonwoo Park1d05bb92013-03-07 16:55:06 -0800247 AIF4_MAD_TX,
Kuirong Wang906ac472012-07-09 12:54:44 -0700248 NUM_CODEC_DAIS,
Kiran Kandic3b24402012-06-11 00:05:59 -0700249};
250
Kuirong Wang906ac472012-07-09 12:54:44 -0700251enum {
252 RX_MIX1_INP_SEL_ZERO = 0,
253 RX_MIX1_INP_SEL_SRC1,
254 RX_MIX1_INP_SEL_SRC2,
255 RX_MIX1_INP_SEL_IIR1,
256 RX_MIX1_INP_SEL_IIR2,
257 RX_MIX1_INP_SEL_RX1,
258 RX_MIX1_INP_SEL_RX2,
259 RX_MIX1_INP_SEL_RX3,
260 RX_MIX1_INP_SEL_RX4,
261 RX_MIX1_INP_SEL_RX5,
262 RX_MIX1_INP_SEL_RX6,
263 RX_MIX1_INP_SEL_RX7,
264 RX_MIX1_INP_SEL_AUXRX,
265};
266
267#define TAIKO_COMP_DIGITAL_GAIN_OFFSET 3
268
Kiran Kandic3b24402012-06-11 00:05:59 -0700269static const DECLARE_TLV_DB_SCALE(digital_gain, 0, 1, 0);
270static const DECLARE_TLV_DB_SCALE(line_gain, 0, 7, 1);
271static const DECLARE_TLV_DB_SCALE(analog_gain, 0, 25, 1);
272static struct snd_soc_dai_driver taiko_dai[];
273static const DECLARE_TLV_DB_SCALE(aux_pga_gain, 0, 2, 0);
274
Kiran Kandic3b24402012-06-11 00:05:59 -0700275/* Codec supports 2 IIR filters */
276enum {
277 IIR1 = 0,
278 IIR2,
279 IIR_MAX,
280};
281/* Codec supports 5 bands */
282enum {
283 BAND1 = 0,
284 BAND2,
285 BAND3,
286 BAND4,
287 BAND5,
288 BAND_MAX,
289};
290
291enum {
Joonwoo Parkc7731432012-10-17 12:41:44 -0700292 COMPANDER_0,
293 COMPANDER_1,
Kiran Kandic3b24402012-06-11 00:05:59 -0700294 COMPANDER_2,
295 COMPANDER_MAX,
296};
297
298enum {
299 COMPANDER_FS_8KHZ = 0,
300 COMPANDER_FS_16KHZ,
301 COMPANDER_FS_32KHZ,
302 COMPANDER_FS_48KHZ,
303 COMPANDER_FS_96KHZ,
304 COMPANDER_FS_192KHZ,
305 COMPANDER_FS_MAX,
306};
307
Kiran Kandic3b24402012-06-11 00:05:59 -0700308struct comp_sample_dependent_params {
309 u32 peak_det_timeout;
310 u32 rms_meter_div_fact;
311 u32 rms_meter_resamp_fact;
312};
313
Kiran Kandic3b24402012-06-11 00:05:59 -0700314struct hpf_work {
315 struct taiko_priv *taiko;
316 u32 decimator;
317 u8 tx_hpf_cut_of_freq;
318 struct delayed_work dwork;
319};
320
321static struct hpf_work tx_hpf_work[NUM_DECIMATORS];
322
Kuirong Wang906ac472012-07-09 12:54:44 -0700323static const struct wcd9xxx_ch taiko_rx_chs[TAIKO_RX_MAX] = {
324 WCD9XXX_CH(16, 0),
325 WCD9XXX_CH(17, 1),
326 WCD9XXX_CH(18, 2),
327 WCD9XXX_CH(19, 3),
328 WCD9XXX_CH(20, 4),
329 WCD9XXX_CH(21, 5),
330 WCD9XXX_CH(22, 6),
331 WCD9XXX_CH(23, 7),
332 WCD9XXX_CH(24, 8),
333 WCD9XXX_CH(25, 9),
334 WCD9XXX_CH(26, 10),
335 WCD9XXX_CH(27, 11),
336 WCD9XXX_CH(28, 12),
337};
338
339static const struct wcd9xxx_ch taiko_tx_chs[TAIKO_TX_MAX] = {
340 WCD9XXX_CH(0, 0),
341 WCD9XXX_CH(1, 1),
342 WCD9XXX_CH(2, 2),
343 WCD9XXX_CH(3, 3),
344 WCD9XXX_CH(4, 4),
345 WCD9XXX_CH(5, 5),
346 WCD9XXX_CH(6, 6),
347 WCD9XXX_CH(7, 7),
348 WCD9XXX_CH(8, 8),
349 WCD9XXX_CH(9, 9),
350 WCD9XXX_CH(10, 10),
351 WCD9XXX_CH(11, 11),
352 WCD9XXX_CH(12, 12),
353 WCD9XXX_CH(13, 13),
354 WCD9XXX_CH(14, 14),
355 WCD9XXX_CH(15, 15),
356};
357
358static const u32 vport_check_table[NUM_CODEC_DAIS] = {
359 0, /* AIF1_PB */
360 (1 << AIF2_CAP) | (1 << AIF3_CAP), /* AIF1_CAP */
361 0, /* AIF2_PB */
362 (1 << AIF1_CAP) | (1 << AIF3_CAP), /* AIF2_CAP */
363 0, /* AIF2_PB */
364 (1 << AIF1_CAP) | (1 << AIF2_CAP), /* AIF2_CAP */
365};
366
Venkat Sudhir96dd28c2012-12-04 17:00:19 -0800367static const u32 vport_i2s_check_table[NUM_CODEC_DAIS] = {
368 0, /* AIF1_PB */
369 0, /* AIF1_CAP */
Venkat Sudhir994193b2012-12-17 17:30:51 -0800370 0, /* AIF2_PB */
371 0, /* AIF2_CAP */
Venkat Sudhir96dd28c2012-12-04 17:00:19 -0800372};
373
Kiran Kandic3b24402012-06-11 00:05:59 -0700374struct taiko_priv {
375 struct snd_soc_codec *codec;
Kiran Kandic3b24402012-06-11 00:05:59 -0700376 u32 adc_count;
Kiran Kandic3b24402012-06-11 00:05:59 -0700377 u32 rx_bias_count;
378 s32 dmic_1_2_clk_cnt;
379 s32 dmic_3_4_clk_cnt;
380 s32 dmic_5_6_clk_cnt;
381
Kiran Kandic3b24402012-06-11 00:05:59 -0700382 u32 anc_slot;
Damir Didjusto2cb06bd2013-01-30 23:14:55 -0800383 bool anc_func;
Kiran Kandic3b24402012-06-11 00:05:59 -0700384
Kiran Kandic3b24402012-06-11 00:05:59 -0700385 /*track taiko interface type*/
386 u8 intf_type;
387
Kiran Kandic3b24402012-06-11 00:05:59 -0700388 /* num of slim ports required */
Kuirong Wang906ac472012-07-09 12:54:44 -0700389 struct wcd9xxx_codec_dai_data dai[NUM_CODEC_DAIS];
Kiran Kandic3b24402012-06-11 00:05:59 -0700390
391 /*compander*/
392 int comp_enabled[COMPANDER_MAX];
393 u32 comp_fs[COMPANDER_MAX];
394
395 /* Maintain the status of AUX PGA */
396 int aux_pga_cnt;
397 u8 aux_l_gain;
398 u8 aux_r_gain;
399
Joonwoo Park125cd4e2012-12-11 15:16:11 -0800400 bool spkr_pa_widget_on;
Joonwoo Park448a8fc2013-04-10 15:25:58 -0700401 struct regulator *spkdrv_reg;
Joonwoo Park125cd4e2012-12-11 15:16:11 -0800402
Joonwoo Park1d05bb92013-03-07 16:55:06 -0800403 struct afe_param_cdc_slimbus_slave_cfg slimbus_slave_cfg;
404
Joonwoo Parka8890262012-10-15 12:04:27 -0700405 /* resmgr module */
406 struct wcd9xxx_resmgr resmgr;
407 /* mbhc module */
408 struct wcd9xxx_mbhc mbhc;
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -0800409
410 /* class h specific data */
411 struct wcd9xxx_clsh_cdc_data clsh_d;
Kiran Kandic3b24402012-06-11 00:05:59 -0700412};
413
Kiran Kandic3b24402012-06-11 00:05:59 -0700414static const u32 comp_shift[] = {
Joonwoo Parkc7731432012-10-17 12:41:44 -0700415 4, /* Compander 0's clock source is on interpolator 7 */
Kiran Kandic3b24402012-06-11 00:05:59 -0700416 0,
417 2,
418};
419
420static const int comp_rx_path[] = {
421 COMPANDER_1,
422 COMPANDER_1,
423 COMPANDER_2,
424 COMPANDER_2,
425 COMPANDER_2,
426 COMPANDER_2,
Joonwoo Parkc7731432012-10-17 12:41:44 -0700427 COMPANDER_0,
Kiran Kandic3b24402012-06-11 00:05:59 -0700428 COMPANDER_MAX,
429};
430
431static const struct comp_sample_dependent_params comp_samp_params[] = {
432 {
Joonwoo Parkc7731432012-10-17 12:41:44 -0700433 /* 8 Khz */
Bhalchandra Gajareed090e62013-03-29 16:11:49 -0700434 .peak_det_timeout = 0x06,
Joonwoo Parkc7731432012-10-17 12:41:44 -0700435 .rms_meter_div_fact = 0x09,
436 .rms_meter_resamp_fact = 0x06,
Kiran Kandic3b24402012-06-11 00:05:59 -0700437 },
438 {
Joonwoo Parkc7731432012-10-17 12:41:44 -0700439 /* 16 Khz */
Bhalchandra Gajareed090e62013-03-29 16:11:49 -0700440 .peak_det_timeout = 0x07,
Joonwoo Parkc7731432012-10-17 12:41:44 -0700441 .rms_meter_div_fact = 0x0A,
442 .rms_meter_resamp_fact = 0x0C,
443 },
444 {
445 /* 32 Khz */
Bhalchandra Gajareed090e62013-03-29 16:11:49 -0700446 .peak_det_timeout = 0x08,
Joonwoo Parkc7731432012-10-17 12:41:44 -0700447 .rms_meter_div_fact = 0x0B,
448 .rms_meter_resamp_fact = 0x1E,
449 },
450 {
451 /* 48 Khz */
Bhalchandra Gajareed090e62013-03-29 16:11:49 -0700452 .peak_det_timeout = 0x09,
Joonwoo Parkc7731432012-10-17 12:41:44 -0700453 .rms_meter_div_fact = 0x0B,
Kiran Kandic3b24402012-06-11 00:05:59 -0700454 .rms_meter_resamp_fact = 0x28,
455 },
Kiran Kandic3b24402012-06-11 00:05:59 -0700456 {
Joonwoo Parkc7731432012-10-17 12:41:44 -0700457 /* 96 Khz */
Bhalchandra Gajareed090e62013-03-29 16:11:49 -0700458 .peak_det_timeout = 0x0A,
Joonwoo Parkc7731432012-10-17 12:41:44 -0700459 .rms_meter_div_fact = 0x0C,
460 .rms_meter_resamp_fact = 0x50,
Kiran Kandic3b24402012-06-11 00:05:59 -0700461 },
Kiran Kandic3b24402012-06-11 00:05:59 -0700462 {
Joonwoo Parkc7731432012-10-17 12:41:44 -0700463 /* 192 Khz */
Bhalchandra Gajareed090e62013-03-29 16:11:49 -0700464 .peak_det_timeout = 0x0B,
465 .rms_meter_div_fact = 0xC,
466 .rms_meter_resamp_fact = 0x50,
Kiran Kandic3b24402012-06-11 00:05:59 -0700467 },
468};
469
470static unsigned short rx_digital_gain_reg[] = {
471 TAIKO_A_CDC_RX1_VOL_CTL_B2_CTL,
472 TAIKO_A_CDC_RX2_VOL_CTL_B2_CTL,
473 TAIKO_A_CDC_RX3_VOL_CTL_B2_CTL,
474 TAIKO_A_CDC_RX4_VOL_CTL_B2_CTL,
475 TAIKO_A_CDC_RX5_VOL_CTL_B2_CTL,
476 TAIKO_A_CDC_RX6_VOL_CTL_B2_CTL,
477 TAIKO_A_CDC_RX7_VOL_CTL_B2_CTL,
478};
479
480
481static unsigned short tx_digital_gain_reg[] = {
482 TAIKO_A_CDC_TX1_VOL_CTL_GAIN,
483 TAIKO_A_CDC_TX2_VOL_CTL_GAIN,
484 TAIKO_A_CDC_TX3_VOL_CTL_GAIN,
485 TAIKO_A_CDC_TX4_VOL_CTL_GAIN,
486 TAIKO_A_CDC_TX5_VOL_CTL_GAIN,
487 TAIKO_A_CDC_TX6_VOL_CTL_GAIN,
488 TAIKO_A_CDC_TX7_VOL_CTL_GAIN,
489 TAIKO_A_CDC_TX8_VOL_CTL_GAIN,
490 TAIKO_A_CDC_TX9_VOL_CTL_GAIN,
491 TAIKO_A_CDC_TX10_VOL_CTL_GAIN,
492};
493
Joonwoo Park125cd4e2012-12-11 15:16:11 -0800494static int spkr_drv_wrnd_param_set(const char *val,
495 const struct kernel_param *kp)
496{
497 struct snd_soc_codec *codec;
498 int ret, old;
499 struct taiko_priv *priv;
500
501 priv = (struct taiko_priv *)atomic_read(&kp_taiko_priv);
502 if (!priv) {
503 pr_debug("%s: codec isn't yet registered\n", __func__);
504 return 0;
505 }
506
507 WCD9XXX_BCL_LOCK(&priv->resmgr);
508 old = spkr_drv_wrnd;
509 ret = param_set_int(val, kp);
510 if (ret) {
511 WCD9XXX_BCL_UNLOCK(&priv->resmgr);
512 return ret;
513 }
514
515 pr_debug("%s: spkr_drv_wrnd %d -> %d\n", __func__, old, spkr_drv_wrnd);
516 codec = priv->codec;
517 if (old == 0 && spkr_drv_wrnd == 1) {
518 wcd9xxx_resmgr_get_bandgap(&priv->resmgr,
519 WCD9XXX_BANDGAP_AUDIO_MODE);
520 snd_soc_update_bits(codec, TAIKO_A_SPKR_DRV_EN, 0x80, 0x80);
521 } else if (old == 1 && spkr_drv_wrnd == 0) {
522 wcd9xxx_resmgr_put_bandgap(&priv->resmgr,
523 WCD9XXX_BANDGAP_AUDIO_MODE);
524 if (!priv->spkr_pa_widget_on)
525 snd_soc_update_bits(codec, TAIKO_A_SPKR_DRV_EN, 0x80,
526 0x00);
527 }
528
529 WCD9XXX_BCL_UNLOCK(&priv->resmgr);
530 return 0;
531}
532
Kiran Kandic3b24402012-06-11 00:05:59 -0700533static int taiko_get_anc_slot(struct snd_kcontrol *kcontrol,
534 struct snd_ctl_elem_value *ucontrol)
535{
536 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
537 struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
538 ucontrol->value.integer.value[0] = taiko->anc_slot;
539 return 0;
540}
541
542static int taiko_put_anc_slot(struct snd_kcontrol *kcontrol,
543 struct snd_ctl_elem_value *ucontrol)
544{
545 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
546 struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
547 taiko->anc_slot = ucontrol->value.integer.value[0];
548 return 0;
549}
550
Damir Didjusto2cb06bd2013-01-30 23:14:55 -0800551static int taiko_get_anc_func(struct snd_kcontrol *kcontrol,
552 struct snd_ctl_elem_value *ucontrol)
553{
554 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
555 struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
556
557 ucontrol->value.integer.value[0] = (taiko->anc_func == true ? 1 : 0);
558 return 0;
559}
560
561static int taiko_put_anc_func(struct snd_kcontrol *kcontrol,
562 struct snd_ctl_elem_value *ucontrol)
563{
564 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
565 struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
566 struct snd_soc_dapm_context *dapm = &codec->dapm;
567
568 mutex_lock(&dapm->codec->mutex);
569 taiko->anc_func = (!ucontrol->value.integer.value[0] ? false : true);
570
571 dev_dbg(codec->dev, "%s: anc_func %x", __func__, taiko->anc_func);
572
573 if (taiko->anc_func == true) {
574 snd_soc_dapm_enable_pin(dapm, "ANC HPHR");
575 snd_soc_dapm_enable_pin(dapm, "ANC HPHL");
576 snd_soc_dapm_enable_pin(dapm, "ANC HEADPHONE");
577 snd_soc_dapm_enable_pin(dapm, "ANC EAR PA");
578 snd_soc_dapm_enable_pin(dapm, "ANC EAR");
579 snd_soc_dapm_disable_pin(dapm, "HPHR");
580 snd_soc_dapm_disable_pin(dapm, "HPHL");
581 snd_soc_dapm_disable_pin(dapm, "HEADPHONE");
582 snd_soc_dapm_disable_pin(dapm, "EAR PA");
583 snd_soc_dapm_disable_pin(dapm, "EAR");
584 } else {
585 snd_soc_dapm_disable_pin(dapm, "ANC HPHR");
586 snd_soc_dapm_disable_pin(dapm, "ANC HPHL");
587 snd_soc_dapm_disable_pin(dapm, "ANC HEADPHONE");
588 snd_soc_dapm_disable_pin(dapm, "ANC EAR PA");
589 snd_soc_dapm_disable_pin(dapm, "ANC EAR");
590 snd_soc_dapm_enable_pin(dapm, "HPHR");
591 snd_soc_dapm_enable_pin(dapm, "HPHL");
592 snd_soc_dapm_enable_pin(dapm, "HEADPHONE");
593 snd_soc_dapm_enable_pin(dapm, "EAR PA");
594 snd_soc_dapm_enable_pin(dapm, "EAR");
595 }
596 snd_soc_dapm_sync(dapm);
597 mutex_unlock(&dapm->codec->mutex);
598 return 0;
599}
600
Kiran Kandic3b24402012-06-11 00:05:59 -0700601static int taiko_get_iir_enable_audio_mixer(
602 struct snd_kcontrol *kcontrol,
603 struct snd_ctl_elem_value *ucontrol)
604{
605 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
606 int iir_idx = ((struct soc_multi_mixer_control *)
607 kcontrol->private_value)->reg;
608 int band_idx = ((struct soc_multi_mixer_control *)
609 kcontrol->private_value)->shift;
610
611 ucontrol->value.integer.value[0] =
Ben Romberger205e14d2013-02-06 12:31:53 -0800612 (snd_soc_read(codec, (TAIKO_A_CDC_IIR1_CTL + 16 * iir_idx)) &
613 (1 << band_idx)) != 0;
Kiran Kandic3b24402012-06-11 00:05:59 -0700614
615 pr_debug("%s: IIR #%d band #%d enable %d\n", __func__,
616 iir_idx, band_idx,
617 (uint32_t)ucontrol->value.integer.value[0]);
618 return 0;
619}
620
621static int taiko_put_iir_enable_audio_mixer(
622 struct snd_kcontrol *kcontrol,
623 struct snd_ctl_elem_value *ucontrol)
624{
625 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
626 int iir_idx = ((struct soc_multi_mixer_control *)
627 kcontrol->private_value)->reg;
628 int band_idx = ((struct soc_multi_mixer_control *)
629 kcontrol->private_value)->shift;
630 int value = ucontrol->value.integer.value[0];
631
632 /* Mask first 5 bits, 6-8 are reserved */
633 snd_soc_update_bits(codec, (TAIKO_A_CDC_IIR1_CTL + 16 * iir_idx),
634 (1 << band_idx), (value << band_idx));
635
636 pr_debug("%s: IIR #%d band #%d enable %d\n", __func__,
Ben Romberger205e14d2013-02-06 12:31:53 -0800637 iir_idx, band_idx,
638 ((snd_soc_read(codec, (TAIKO_A_CDC_IIR1_CTL + 16 * iir_idx)) &
639 (1 << band_idx)) != 0));
Kiran Kandic3b24402012-06-11 00:05:59 -0700640 return 0;
641}
642static uint32_t get_iir_band_coeff(struct snd_soc_codec *codec,
643 int iir_idx, int band_idx,
644 int coeff_idx)
645{
Ben Romberger205e14d2013-02-06 12:31:53 -0800646 uint32_t value = 0;
647
Kiran Kandic3b24402012-06-11 00:05:59 -0700648 /* Address does not automatically update if reading */
649 snd_soc_write(codec,
650 (TAIKO_A_CDC_IIR1_COEF_B1_CTL + 16 * iir_idx),
Ben Romberger205e14d2013-02-06 12:31:53 -0800651 ((band_idx * BAND_MAX + coeff_idx)
652 * sizeof(uint32_t)) & 0x7F);
653
654 value |= snd_soc_read(codec,
655 (TAIKO_A_CDC_IIR1_COEF_B2_CTL + 16 * iir_idx));
656
657 snd_soc_write(codec,
658 (TAIKO_A_CDC_IIR1_COEF_B1_CTL + 16 * iir_idx),
659 ((band_idx * BAND_MAX + coeff_idx)
660 * sizeof(uint32_t) + 1) & 0x7F);
661
662 value |= (snd_soc_read(codec,
663 (TAIKO_A_CDC_IIR1_COEF_B2_CTL + 16 * iir_idx)) << 8);
664
665 snd_soc_write(codec,
666 (TAIKO_A_CDC_IIR1_COEF_B1_CTL + 16 * iir_idx),
667 ((band_idx * BAND_MAX + coeff_idx)
668 * sizeof(uint32_t) + 2) & 0x7F);
669
670 value |= (snd_soc_read(codec,
671 (TAIKO_A_CDC_IIR1_COEF_B2_CTL + 16 * iir_idx)) << 16);
672
673 snd_soc_write(codec,
674 (TAIKO_A_CDC_IIR1_COEF_B1_CTL + 16 * iir_idx),
675 ((band_idx * BAND_MAX + coeff_idx)
676 * sizeof(uint32_t) + 3) & 0x7F);
Kiran Kandic3b24402012-06-11 00:05:59 -0700677
678 /* Mask bits top 2 bits since they are reserved */
Ben Romberger205e14d2013-02-06 12:31:53 -0800679 value |= ((snd_soc_read(codec,
680 (TAIKO_A_CDC_IIR1_COEF_B2_CTL + 16 * iir_idx)) & 0x3F) << 24);
681
682 return value;
Kiran Kandic3b24402012-06-11 00:05:59 -0700683}
684
685static int taiko_get_iir_band_audio_mixer(
686 struct snd_kcontrol *kcontrol,
687 struct snd_ctl_elem_value *ucontrol)
688{
689 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
690 int iir_idx = ((struct soc_multi_mixer_control *)
691 kcontrol->private_value)->reg;
692 int band_idx = ((struct soc_multi_mixer_control *)
693 kcontrol->private_value)->shift;
694
695 ucontrol->value.integer.value[0] =
696 get_iir_band_coeff(codec, iir_idx, band_idx, 0);
697 ucontrol->value.integer.value[1] =
698 get_iir_band_coeff(codec, iir_idx, band_idx, 1);
699 ucontrol->value.integer.value[2] =
700 get_iir_band_coeff(codec, iir_idx, band_idx, 2);
701 ucontrol->value.integer.value[3] =
702 get_iir_band_coeff(codec, iir_idx, band_idx, 3);
703 ucontrol->value.integer.value[4] =
704 get_iir_band_coeff(codec, iir_idx, band_idx, 4);
705
706 pr_debug("%s: IIR #%d band #%d b0 = 0x%x\n"
707 "%s: IIR #%d band #%d b1 = 0x%x\n"
708 "%s: IIR #%d band #%d b2 = 0x%x\n"
709 "%s: IIR #%d band #%d a1 = 0x%x\n"
710 "%s: IIR #%d band #%d a2 = 0x%x\n",
711 __func__, iir_idx, band_idx,
712 (uint32_t)ucontrol->value.integer.value[0],
713 __func__, iir_idx, band_idx,
714 (uint32_t)ucontrol->value.integer.value[1],
715 __func__, iir_idx, band_idx,
716 (uint32_t)ucontrol->value.integer.value[2],
717 __func__, iir_idx, band_idx,
718 (uint32_t)ucontrol->value.integer.value[3],
719 __func__, iir_idx, band_idx,
720 (uint32_t)ucontrol->value.integer.value[4]);
721 return 0;
722}
723
724static void set_iir_band_coeff(struct snd_soc_codec *codec,
725 int iir_idx, int band_idx,
Ben Romberger205e14d2013-02-06 12:31:53 -0800726 uint32_t value)
Kiran Kandic3b24402012-06-11 00:05:59 -0700727{
Kiran Kandic3b24402012-06-11 00:05:59 -0700728 snd_soc_write(codec,
Ben Romberger205e14d2013-02-06 12:31:53 -0800729 (TAIKO_A_CDC_IIR1_COEF_B2_CTL + 16 * iir_idx),
730 (value & 0xFF));
731
732 snd_soc_write(codec,
733 (TAIKO_A_CDC_IIR1_COEF_B2_CTL + 16 * iir_idx),
734 (value >> 8) & 0xFF);
735
736 snd_soc_write(codec,
737 (TAIKO_A_CDC_IIR1_COEF_B2_CTL + 16 * iir_idx),
738 (value >> 16) & 0xFF);
Kiran Kandic3b24402012-06-11 00:05:59 -0700739
740 /* Mask top 2 bits, 7-8 are reserved */
741 snd_soc_write(codec,
742 (TAIKO_A_CDC_IIR1_COEF_B2_CTL + 16 * iir_idx),
743 (value >> 24) & 0x3F);
Kiran Kandic3b24402012-06-11 00:05:59 -0700744}
745
746static int taiko_put_iir_band_audio_mixer(
747 struct snd_kcontrol *kcontrol,
748 struct snd_ctl_elem_value *ucontrol)
749{
750 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
751 int iir_idx = ((struct soc_multi_mixer_control *)
752 kcontrol->private_value)->reg;
753 int band_idx = ((struct soc_multi_mixer_control *)
754 kcontrol->private_value)->shift;
755
Ben Romberger205e14d2013-02-06 12:31:53 -0800756 /* Mask top bit it is reserved */
757 /* Updates addr automatically for each B2 write */
758 snd_soc_write(codec,
759 (TAIKO_A_CDC_IIR1_COEF_B1_CTL + 16 * iir_idx),
760 (band_idx * BAND_MAX * sizeof(uint32_t)) & 0x7F);
761
762 set_iir_band_coeff(codec, iir_idx, band_idx,
Kiran Kandic3b24402012-06-11 00:05:59 -0700763 ucontrol->value.integer.value[0]);
Ben Romberger205e14d2013-02-06 12:31:53 -0800764 set_iir_band_coeff(codec, iir_idx, band_idx,
Kiran Kandic3b24402012-06-11 00:05:59 -0700765 ucontrol->value.integer.value[1]);
Ben Romberger205e14d2013-02-06 12:31:53 -0800766 set_iir_band_coeff(codec, iir_idx, band_idx,
Kiran Kandic3b24402012-06-11 00:05:59 -0700767 ucontrol->value.integer.value[2]);
Ben Romberger205e14d2013-02-06 12:31:53 -0800768 set_iir_band_coeff(codec, iir_idx, band_idx,
Kiran Kandic3b24402012-06-11 00:05:59 -0700769 ucontrol->value.integer.value[3]);
Ben Romberger205e14d2013-02-06 12:31:53 -0800770 set_iir_band_coeff(codec, iir_idx, band_idx,
Kiran Kandic3b24402012-06-11 00:05:59 -0700771 ucontrol->value.integer.value[4]);
772
773 pr_debug("%s: IIR #%d band #%d b0 = 0x%x\n"
774 "%s: IIR #%d band #%d b1 = 0x%x\n"
775 "%s: IIR #%d band #%d b2 = 0x%x\n"
776 "%s: IIR #%d band #%d a1 = 0x%x\n"
777 "%s: IIR #%d band #%d a2 = 0x%x\n",
778 __func__, iir_idx, band_idx,
779 get_iir_band_coeff(codec, iir_idx, band_idx, 0),
780 __func__, iir_idx, band_idx,
781 get_iir_band_coeff(codec, iir_idx, band_idx, 1),
782 __func__, iir_idx, band_idx,
783 get_iir_band_coeff(codec, iir_idx, band_idx, 2),
784 __func__, iir_idx, band_idx,
785 get_iir_band_coeff(codec, iir_idx, band_idx, 3),
786 __func__, iir_idx, band_idx,
787 get_iir_band_coeff(codec, iir_idx, band_idx, 4));
788 return 0;
789}
790
Kiran Kandic3b24402012-06-11 00:05:59 -0700791static int taiko_get_compander(struct snd_kcontrol *kcontrol,
Joonwoo Parkc7731432012-10-17 12:41:44 -0700792 struct snd_ctl_elem_value *ucontrol)
Kiran Kandic3b24402012-06-11 00:05:59 -0700793{
794
795 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
796 int comp = ((struct soc_multi_mixer_control *)
Joonwoo Parkc7731432012-10-17 12:41:44 -0700797 kcontrol->private_value)->shift;
Kiran Kandic3b24402012-06-11 00:05:59 -0700798 struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
799
800 ucontrol->value.integer.value[0] = taiko->comp_enabled[comp];
Kiran Kandic3b24402012-06-11 00:05:59 -0700801 return 0;
802}
803
804static int taiko_set_compander(struct snd_kcontrol *kcontrol,
Joonwoo Parkc7731432012-10-17 12:41:44 -0700805 struct snd_ctl_elem_value *ucontrol)
Kiran Kandic3b24402012-06-11 00:05:59 -0700806{
807 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
808 struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
809 int comp = ((struct soc_multi_mixer_control *)
Joonwoo Parkc7731432012-10-17 12:41:44 -0700810 kcontrol->private_value)->shift;
Kiran Kandic3b24402012-06-11 00:05:59 -0700811 int value = ucontrol->value.integer.value[0];
812
Joonwoo Parkc7731432012-10-17 12:41:44 -0700813 pr_debug("%s: Compander %d enable current %d, new %d\n",
814 __func__, comp, taiko->comp_enabled[comp], value);
Kiran Kandic3b24402012-06-11 00:05:59 -0700815 taiko->comp_enabled[comp] = value;
Bhalchandra Gajareef7810e2013-03-29 16:50:37 -0700816
817 if (comp == COMPANDER_1 &&
818 taiko->comp_enabled[comp] == 1) {
819 /* Wavegen to 5 msec */
820 snd_soc_write(codec, TAIKO_A_RX_HPH_CNP_WG_CTL, 0xDA);
821 snd_soc_write(codec, TAIKO_A_RX_HPH_CNP_WG_TIME, 0x15);
822 snd_soc_write(codec, TAIKO_A_RX_HPH_BIAS_WG_OCP, 0x2A);
823
824 /* Enable Chopper */
825 snd_soc_update_bits(codec,
826 TAIKO_A_RX_HPH_CHOP_CTL, 0x80, 0x80);
Bhalchandra Gajare9581aed2013-03-29 17:06:10 -0700827
828 snd_soc_write(codec, TAIKO_A_NCP_DTEST, 0x20);
Bhalchandra Gajareef7810e2013-03-29 16:50:37 -0700829 pr_debug("%s: Enabled Chopper and set wavegen to 5 msec\n",
830 __func__);
831 } else if (comp == COMPANDER_1 &&
832 taiko->comp_enabled[comp] == 0) {
833 /* Wavegen to 20 msec */
834 snd_soc_write(codec, TAIKO_A_RX_HPH_CNP_WG_CTL, 0xDB);
835 snd_soc_write(codec, TAIKO_A_RX_HPH_CNP_WG_TIME, 0x58);
836 snd_soc_write(codec, TAIKO_A_RX_HPH_BIAS_WG_OCP, 0x1A);
837
838 /* Disable CHOPPER block */
839 snd_soc_update_bits(codec,
840 TAIKO_A_RX_HPH_CHOP_CTL, 0x80, 0x00);
Bhalchandra Gajare9581aed2013-03-29 17:06:10 -0700841
842 snd_soc_write(codec, TAIKO_A_NCP_DTEST, 0x10);
Bhalchandra Gajareef7810e2013-03-29 16:50:37 -0700843 pr_debug("%s: Disabled Chopper and set wavegen to 20 msec\n",
844 __func__);
845 }
Kiran Kandic3b24402012-06-11 00:05:59 -0700846 return 0;
847}
848
Joonwoo Parkc7731432012-10-17 12:41:44 -0700849static int taiko_config_gain_compander(struct snd_soc_codec *codec,
850 int comp, bool enable)
851{
852 int ret = 0;
853
854 switch (comp) {
855 case COMPANDER_0:
856 snd_soc_update_bits(codec, TAIKO_A_SPKR_DRV_GAIN,
857 1 << 2, !enable << 2);
858 break;
859 case COMPANDER_1:
860 snd_soc_update_bits(codec, TAIKO_A_RX_HPH_L_GAIN,
861 1 << 5, !enable << 5);
862 snd_soc_update_bits(codec, TAIKO_A_RX_HPH_R_GAIN,
863 1 << 5, !enable << 5);
864 break;
865 case COMPANDER_2:
866 snd_soc_update_bits(codec, TAIKO_A_RX_LINE_1_GAIN,
867 1 << 5, !enable << 5);
868 snd_soc_update_bits(codec, TAIKO_A_RX_LINE_3_GAIN,
869 1 << 5, !enable << 5);
870 snd_soc_update_bits(codec, TAIKO_A_RX_LINE_2_GAIN,
871 1 << 5, !enable << 5);
872 snd_soc_update_bits(codec, TAIKO_A_RX_LINE_4_GAIN,
873 1 << 5, !enable << 5);
874 break;
875 default:
876 WARN_ON(1);
877 ret = -EINVAL;
878 }
879
880 return ret;
881}
882
883static void taiko_discharge_comp(struct snd_soc_codec *codec, int comp)
884{
Bhalchandra Gajareed090e62013-03-29 16:11:49 -0700885 /* Level meter DIV Factor to 5*/
Joonwoo Parkc7731432012-10-17 12:41:44 -0700886 snd_soc_update_bits(codec, TAIKO_A_CDC_COMP0_B2_CTL + (comp * 8), 0xF0,
Bhalchandra Gajareed090e62013-03-29 16:11:49 -0700887 0x05 << 4);
888 /* RMS meter Sampling to 0x01 */
889 snd_soc_write(codec, TAIKO_A_CDC_COMP0_B3_CTL + (comp * 8), 0x01);
890
891 /* Worst case timeout for compander CnP sleep timeout */
892 usleep_range(3000, 3000);
893}
894
895static enum wcd9xxx_buck_volt taiko_codec_get_buck_mv(
896 struct snd_soc_codec *codec)
897{
898 int buck_volt = WCD9XXX_CDC_BUCK_UNSUPPORTED;
899 struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
900 struct wcd9xxx_pdata *pdata = taiko->resmgr.pdata;
901 int i;
902
903 for (i = 0; i < ARRAY_SIZE(pdata->regulator); i++) {
904 if (!strncmp(pdata->regulator[i].name,
905 WCD9XXX_SUPPLY_BUCK_NAME,
906 sizeof(WCD9XXX_SUPPLY_BUCK_NAME))) {
907 if ((pdata->regulator[i].min_uV ==
908 WCD9XXX_CDC_BUCK_MV_1P8) ||
909 (pdata->regulator[i].min_uV ==
910 WCD9XXX_CDC_BUCK_MV_2P15))
911 buck_volt = pdata->regulator[i].min_uV;
912 break;
913 }
914 }
915 return buck_volt;
Joonwoo Parkc7731432012-10-17 12:41:44 -0700916}
Kiran Kandic3b24402012-06-11 00:05:59 -0700917
918static int taiko_config_compander(struct snd_soc_dapm_widget *w,
Joonwoo Parkc7731432012-10-17 12:41:44 -0700919 struct snd_kcontrol *kcontrol, int event)
Kiran Kandic3b24402012-06-11 00:05:59 -0700920{
Bhalchandra Gajareed090e62013-03-29 16:11:49 -0700921 int mask, enable_mask;
Kiran Kandic3b24402012-06-11 00:05:59 -0700922 struct snd_soc_codec *codec = w->codec;
923 struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
Joonwoo Parkc7731432012-10-17 12:41:44 -0700924 const int comp = w->shift;
925 const u32 rate = taiko->comp_fs[comp];
926 const struct comp_sample_dependent_params *comp_params =
927 &comp_samp_params[rate];
Bhalchandra Gajareed090e62013-03-29 16:11:49 -0700928 enum wcd9xxx_buck_volt buck_mv;
Kiran Kandic3b24402012-06-11 00:05:59 -0700929
Joonwoo Parkc7731432012-10-17 12:41:44 -0700930 pr_debug("%s: %s event %d compander %d, enabled %d", __func__,
931 w->name, event, comp, taiko->comp_enabled[comp]);
932
933 if (!taiko->comp_enabled[comp])
934 return 0;
935
936 /* Compander 0 has single channel */
937 mask = (comp == COMPANDER_0 ? 0x01 : 0x03);
Bhalchandra Gajareed090e62013-03-29 16:11:49 -0700938 enable_mask = (comp == COMPANDER_0 ? 0x02 : 0x03);
939 buck_mv = taiko_codec_get_buck_mv(codec);
Kiran Kandid2b46332012-10-05 12:04:00 -0700940
Kiran Kandic3b24402012-06-11 00:05:59 -0700941 switch (event) {
942 case SND_SOC_DAPM_PRE_PMU:
Bhalchandra Gajareed090e62013-03-29 16:11:49 -0700943 /* Set compander Sample rate */
944 snd_soc_update_bits(codec,
945 TAIKO_A_CDC_COMP0_FS_CFG + (comp * 8),
946 0x07, rate);
947 /* Set the static gain offset */
948 if (comp == COMPANDER_1
949 && buck_mv == WCD9XXX_CDC_BUCK_MV_2P15) {
950 snd_soc_update_bits(codec,
951 TAIKO_A_CDC_COMP0_B4_CTL + (comp * 8),
952 0x80, 0x80);
953 } else {
954 snd_soc_update_bits(codec,
955 TAIKO_A_CDC_COMP0_B4_CTL + (comp * 8),
956 0x80, 0x00);
957 }
958 /* Enable RX interpolation path compander clocks */
Joonwoo Parkc7731432012-10-17 12:41:44 -0700959 snd_soc_update_bits(codec, TAIKO_A_CDC_CLK_RX_B2_CTL,
960 mask << comp_shift[comp],
961 mask << comp_shift[comp]);
Joonwoo Parkc7731432012-10-17 12:41:44 -0700962 /* Toggle compander reset bits */
963 snd_soc_update_bits(codec, TAIKO_A_CDC_CLK_OTHR_RESET_B2_CTL,
964 mask << comp_shift[comp],
965 mask << comp_shift[comp]);
966 snd_soc_update_bits(codec, TAIKO_A_CDC_CLK_OTHR_RESET_B2_CTL,
967 mask << comp_shift[comp], 0);
Bhalchandra Gajareed090e62013-03-29 16:11:49 -0700968
969 /* Set gain source to compander */
970 taiko_config_gain_compander(codec, comp, true);
971
972 /* Compander enable */
973 snd_soc_update_bits(codec, TAIKO_A_CDC_COMP0_B1_CTL +
974 (comp * 8), enable_mask, enable_mask);
975
976 taiko_discharge_comp(codec, comp);
977
Joonwoo Parkc7731432012-10-17 12:41:44 -0700978 /* Set sample rate dependent paramater */
Joonwoo Parkc7731432012-10-17 12:41:44 -0700979 snd_soc_write(codec, TAIKO_A_CDC_COMP0_B3_CTL + (comp * 8),
980 comp_params->rms_meter_resamp_fact);
981 snd_soc_update_bits(codec,
982 TAIKO_A_CDC_COMP0_B2_CTL + (comp * 8),
Joonwoo Parkc7731432012-10-17 12:41:44 -0700983 0xF0, comp_params->rms_meter_div_fact << 4);
Bhalchandra Gajareed090e62013-03-29 16:11:49 -0700984 snd_soc_update_bits(codec,
985 TAIKO_A_CDC_COMP0_B2_CTL + (comp * 8),
986 0x0F, comp_params->peak_det_timeout);
Kiran Kandic3b24402012-06-11 00:05:59 -0700987 break;
988 case SND_SOC_DAPM_PRE_PMD:
Joonwoo Parkc7731432012-10-17 12:41:44 -0700989 /* Disable compander */
990 snd_soc_update_bits(codec,
991 TAIKO_A_CDC_COMP0_B1_CTL + (comp * 8),
Bhalchandra Gajareed090e62013-03-29 16:11:49 -0700992 enable_mask, 0x00);
993
994 /* Toggle compander reset bits */
995 snd_soc_update_bits(codec, TAIKO_A_CDC_CLK_OTHR_RESET_B2_CTL,
996 mask << comp_shift[comp],
997 mask << comp_shift[comp]);
998 snd_soc_update_bits(codec, TAIKO_A_CDC_CLK_OTHR_RESET_B2_CTL,
999 mask << comp_shift[comp], 0);
1000
Joonwoo Parkc7731432012-10-17 12:41:44 -07001001 /* Turn off the clock for compander in pair */
1002 snd_soc_update_bits(codec, TAIKO_A_CDC_CLK_RX_B2_CTL,
1003 mask << comp_shift[comp], 0);
Bhalchandra Gajareed090e62013-03-29 16:11:49 -07001004
Joonwoo Parkc7731432012-10-17 12:41:44 -07001005 /* Set gain source to register */
1006 taiko_config_gain_compander(codec, comp, false);
Kiran Kandic3b24402012-06-11 00:05:59 -07001007 break;
1008 }
1009 return 0;
1010}
1011
Kiran Kandiec0db5c2013-03-08 16:03:58 -08001012
Kiran Kandic3b24402012-06-11 00:05:59 -07001013
Damir Didjusto2cb06bd2013-01-30 23:14:55 -08001014static const char *const taiko_anc_func_text[] = {"OFF", "ON"};
1015static const struct soc_enum taiko_anc_func_enum =
1016 SOC_ENUM_SINGLE_EXT(2, taiko_anc_func_text);
1017
1018static const char *const tabla_ear_pa_gain_text[] = {"POS_6_DB", "POS_2_DB"};
1019static const struct soc_enum tabla_ear_pa_gain_enum[] = {
1020 SOC_ENUM_SINGLE_EXT(2, tabla_ear_pa_gain_text),
1021};
1022
Kiran Kandic3b24402012-06-11 00:05:59 -07001023/*cut of frequency for high pass filter*/
1024static const char * const cf_text[] = {
1025 "MIN_3DB_4Hz", "MIN_3DB_75Hz", "MIN_3DB_150Hz"
1026};
1027
1028static const struct soc_enum cf_dec1_enum =
1029 SOC_ENUM_SINGLE(TAIKO_A_CDC_TX1_MUX_CTL, 4, 3, cf_text);
1030
1031static const struct soc_enum cf_dec2_enum =
1032 SOC_ENUM_SINGLE(TAIKO_A_CDC_TX2_MUX_CTL, 4, 3, cf_text);
1033
1034static const struct soc_enum cf_dec3_enum =
1035 SOC_ENUM_SINGLE(TAIKO_A_CDC_TX3_MUX_CTL, 4, 3, cf_text);
1036
1037static const struct soc_enum cf_dec4_enum =
1038 SOC_ENUM_SINGLE(TAIKO_A_CDC_TX4_MUX_CTL, 4, 3, cf_text);
1039
1040static const struct soc_enum cf_dec5_enum =
1041 SOC_ENUM_SINGLE(TAIKO_A_CDC_TX5_MUX_CTL, 4, 3, cf_text);
1042
1043static const struct soc_enum cf_dec6_enum =
1044 SOC_ENUM_SINGLE(TAIKO_A_CDC_TX6_MUX_CTL, 4, 3, cf_text);
1045
1046static const struct soc_enum cf_dec7_enum =
1047 SOC_ENUM_SINGLE(TAIKO_A_CDC_TX7_MUX_CTL, 4, 3, cf_text);
1048
1049static const struct soc_enum cf_dec8_enum =
1050 SOC_ENUM_SINGLE(TAIKO_A_CDC_TX8_MUX_CTL, 4, 3, cf_text);
1051
1052static const struct soc_enum cf_dec9_enum =
1053 SOC_ENUM_SINGLE(TAIKO_A_CDC_TX9_MUX_CTL, 4, 3, cf_text);
1054
1055static const struct soc_enum cf_dec10_enum =
1056 SOC_ENUM_SINGLE(TAIKO_A_CDC_TX10_MUX_CTL, 4, 3, cf_text);
1057
1058static const struct soc_enum cf_rxmix1_enum =
Joonwoo Park2000a982013-03-01 14:50:31 -08001059 SOC_ENUM_SINGLE(TAIKO_A_CDC_RX1_B4_CTL, 0, 3, cf_text);
Kiran Kandic3b24402012-06-11 00:05:59 -07001060
1061static const struct soc_enum cf_rxmix2_enum =
Joonwoo Park2000a982013-03-01 14:50:31 -08001062 SOC_ENUM_SINGLE(TAIKO_A_CDC_RX2_B4_CTL, 0, 3, cf_text);
Kiran Kandic3b24402012-06-11 00:05:59 -07001063
1064static const struct soc_enum cf_rxmix3_enum =
Joonwoo Park2000a982013-03-01 14:50:31 -08001065 SOC_ENUM_SINGLE(TAIKO_A_CDC_RX3_B4_CTL, 0, 3, cf_text);
Kiran Kandic3b24402012-06-11 00:05:59 -07001066
1067static const struct soc_enum cf_rxmix4_enum =
Joonwoo Park2000a982013-03-01 14:50:31 -08001068 SOC_ENUM_SINGLE(TAIKO_A_CDC_RX4_B4_CTL, 0, 3, cf_text);
Kiran Kandic3b24402012-06-11 00:05:59 -07001069
1070static const struct soc_enum cf_rxmix5_enum =
Joonwoo Park2000a982013-03-01 14:50:31 -08001071 SOC_ENUM_SINGLE(TAIKO_A_CDC_RX5_B4_CTL, 0, 3, cf_text)
Kiran Kandic3b24402012-06-11 00:05:59 -07001072;
1073static const struct soc_enum cf_rxmix6_enum =
Joonwoo Park2000a982013-03-01 14:50:31 -08001074 SOC_ENUM_SINGLE(TAIKO_A_CDC_RX6_B4_CTL, 0, 3, cf_text);
Kiran Kandic3b24402012-06-11 00:05:59 -07001075
1076static const struct soc_enum cf_rxmix7_enum =
Joonwoo Park2000a982013-03-01 14:50:31 -08001077 SOC_ENUM_SINGLE(TAIKO_A_CDC_RX7_B4_CTL, 0, 3, cf_text);
Kiran Kandic3b24402012-06-11 00:05:59 -07001078
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08001079static const char * const class_h_dsm_text[] = {
1080 "ZERO", "DSM_HPHL_RX1", "DSM_SPKR_RX7"
1081};
1082
1083static const struct soc_enum class_h_dsm_enum =
1084 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_CLSH_CTL, 4, 3, class_h_dsm_text);
1085
1086static const struct snd_kcontrol_new class_h_dsm_mux =
1087 SOC_DAPM_ENUM("CLASS_H_DSM MUX Mux", class_h_dsm_enum);
1088
1089
Kiran Kandic3b24402012-06-11 00:05:59 -07001090static const struct snd_kcontrol_new taiko_snd_controls[] = {
1091
Kiran Kandic3b24402012-06-11 00:05:59 -07001092 SOC_SINGLE_S8_TLV("RX1 Digital Volume", TAIKO_A_CDC_RX1_VOL_CTL_B2_CTL,
1093 -84, 40, digital_gain),
1094 SOC_SINGLE_S8_TLV("RX2 Digital Volume", TAIKO_A_CDC_RX2_VOL_CTL_B2_CTL,
1095 -84, 40, digital_gain),
1096 SOC_SINGLE_S8_TLV("RX3 Digital Volume", TAIKO_A_CDC_RX3_VOL_CTL_B2_CTL,
1097 -84, 40, digital_gain),
1098 SOC_SINGLE_S8_TLV("RX4 Digital Volume", TAIKO_A_CDC_RX4_VOL_CTL_B2_CTL,
1099 -84, 40, digital_gain),
1100 SOC_SINGLE_S8_TLV("RX5 Digital Volume", TAIKO_A_CDC_RX5_VOL_CTL_B2_CTL,
1101 -84, 40, digital_gain),
1102 SOC_SINGLE_S8_TLV("RX6 Digital Volume", TAIKO_A_CDC_RX6_VOL_CTL_B2_CTL,
1103 -84, 40, digital_gain),
1104 SOC_SINGLE_S8_TLV("RX7 Digital Volume", TAIKO_A_CDC_RX7_VOL_CTL_B2_CTL,
1105 -84, 40, digital_gain),
1106
1107 SOC_SINGLE_S8_TLV("DEC1 Volume", TAIKO_A_CDC_TX1_VOL_CTL_GAIN, -84, 40,
1108 digital_gain),
1109 SOC_SINGLE_S8_TLV("DEC2 Volume", TAIKO_A_CDC_TX2_VOL_CTL_GAIN, -84, 40,
1110 digital_gain),
1111 SOC_SINGLE_S8_TLV("DEC3 Volume", TAIKO_A_CDC_TX3_VOL_CTL_GAIN, -84, 40,
1112 digital_gain),
1113 SOC_SINGLE_S8_TLV("DEC4 Volume", TAIKO_A_CDC_TX4_VOL_CTL_GAIN, -84, 40,
1114 digital_gain),
1115 SOC_SINGLE_S8_TLV("DEC5 Volume", TAIKO_A_CDC_TX5_VOL_CTL_GAIN, -84, 40,
1116 digital_gain),
1117 SOC_SINGLE_S8_TLV("DEC6 Volume", TAIKO_A_CDC_TX6_VOL_CTL_GAIN, -84, 40,
1118 digital_gain),
1119 SOC_SINGLE_S8_TLV("DEC7 Volume", TAIKO_A_CDC_TX7_VOL_CTL_GAIN, -84, 40,
1120 digital_gain),
1121 SOC_SINGLE_S8_TLV("DEC8 Volume", TAIKO_A_CDC_TX8_VOL_CTL_GAIN, -84, 40,
1122 digital_gain),
1123 SOC_SINGLE_S8_TLV("DEC9 Volume", TAIKO_A_CDC_TX9_VOL_CTL_GAIN, -84, 40,
1124 digital_gain),
1125 SOC_SINGLE_S8_TLV("DEC10 Volume", TAIKO_A_CDC_TX10_VOL_CTL_GAIN, -84,
1126 40, digital_gain),
Kiran Kandiec0db5c2013-03-08 16:03:58 -08001127
Kiran Kandic3b24402012-06-11 00:05:59 -07001128 SOC_SINGLE_S8_TLV("IIR1 INP1 Volume", TAIKO_A_CDC_IIR1_GAIN_B1_CTL, -84,
1129 40, digital_gain),
1130 SOC_SINGLE_S8_TLV("IIR1 INP2 Volume", TAIKO_A_CDC_IIR1_GAIN_B2_CTL, -84,
1131 40, digital_gain),
1132 SOC_SINGLE_S8_TLV("IIR1 INP3 Volume", TAIKO_A_CDC_IIR1_GAIN_B3_CTL, -84,
1133 40, digital_gain),
1134 SOC_SINGLE_S8_TLV("IIR1 INP4 Volume", TAIKO_A_CDC_IIR1_GAIN_B4_CTL, -84,
1135 40, digital_gain),
Fred Oh456fcb52013-02-28 19:08:15 -08001136 SOC_SINGLE_S8_TLV("IIR2 INP1 Volume", TAIKO_A_CDC_IIR2_GAIN_B1_CTL, -84,
1137 40, digital_gain),
1138 SOC_SINGLE_S8_TLV("IIR2 INP2 Volume", TAIKO_A_CDC_IIR2_GAIN_B2_CTL, -84,
1139 40, digital_gain),
1140 SOC_SINGLE_S8_TLV("IIR2 INP3 Volume", TAIKO_A_CDC_IIR2_GAIN_B3_CTL, -84,
1141 40, digital_gain),
1142 SOC_SINGLE_S8_TLV("IIR2 INP4 Volume", TAIKO_A_CDC_IIR2_GAIN_B4_CTL, -84,
1143 40, digital_gain),
Kiran Kandic3b24402012-06-11 00:05:59 -07001144
Damir Didjusto2cb06bd2013-01-30 23:14:55 -08001145 SOC_SINGLE_EXT("ANC Slot", SND_SOC_NOPM, 0, 100, 0, taiko_get_anc_slot,
Kiran Kandic3b24402012-06-11 00:05:59 -07001146 taiko_put_anc_slot),
Damir Didjusto2cb06bd2013-01-30 23:14:55 -08001147 SOC_ENUM_EXT("ANC Function", taiko_anc_func_enum, taiko_get_anc_func,
1148 taiko_put_anc_func),
Kiran Kandiec0db5c2013-03-08 16:03:58 -08001149
Kiran Kandic3b24402012-06-11 00:05:59 -07001150 SOC_ENUM("TX1 HPF cut off", cf_dec1_enum),
1151 SOC_ENUM("TX2 HPF cut off", cf_dec2_enum),
1152 SOC_ENUM("TX3 HPF cut off", cf_dec3_enum),
1153 SOC_ENUM("TX4 HPF cut off", cf_dec4_enum),
1154 SOC_ENUM("TX5 HPF cut off", cf_dec5_enum),
1155 SOC_ENUM("TX6 HPF cut off", cf_dec6_enum),
1156 SOC_ENUM("TX7 HPF cut off", cf_dec7_enum),
1157 SOC_ENUM("TX8 HPF cut off", cf_dec8_enum),
1158 SOC_ENUM("TX9 HPF cut off", cf_dec9_enum),
1159 SOC_ENUM("TX10 HPF cut off", cf_dec10_enum),
1160
1161 SOC_SINGLE("TX1 HPF Switch", TAIKO_A_CDC_TX1_MUX_CTL, 3, 1, 0),
1162 SOC_SINGLE("TX2 HPF Switch", TAIKO_A_CDC_TX2_MUX_CTL, 3, 1, 0),
1163 SOC_SINGLE("TX3 HPF Switch", TAIKO_A_CDC_TX3_MUX_CTL, 3, 1, 0),
1164 SOC_SINGLE("TX4 HPF Switch", TAIKO_A_CDC_TX4_MUX_CTL, 3, 1, 0),
1165 SOC_SINGLE("TX5 HPF Switch", TAIKO_A_CDC_TX5_MUX_CTL, 3, 1, 0),
1166 SOC_SINGLE("TX6 HPF Switch", TAIKO_A_CDC_TX6_MUX_CTL, 3, 1, 0),
1167 SOC_SINGLE("TX7 HPF Switch", TAIKO_A_CDC_TX7_MUX_CTL, 3, 1, 0),
1168 SOC_SINGLE("TX8 HPF Switch", TAIKO_A_CDC_TX8_MUX_CTL, 3, 1, 0),
1169 SOC_SINGLE("TX9 HPF Switch", TAIKO_A_CDC_TX9_MUX_CTL, 3, 1, 0),
1170 SOC_SINGLE("TX10 HPF Switch", TAIKO_A_CDC_TX10_MUX_CTL, 3, 1, 0),
1171
1172 SOC_SINGLE("RX1 HPF Switch", TAIKO_A_CDC_RX1_B5_CTL, 2, 1, 0),
1173 SOC_SINGLE("RX2 HPF Switch", TAIKO_A_CDC_RX2_B5_CTL, 2, 1, 0),
1174 SOC_SINGLE("RX3 HPF Switch", TAIKO_A_CDC_RX3_B5_CTL, 2, 1, 0),
1175 SOC_SINGLE("RX4 HPF Switch", TAIKO_A_CDC_RX4_B5_CTL, 2, 1, 0),
1176 SOC_SINGLE("RX5 HPF Switch", TAIKO_A_CDC_RX5_B5_CTL, 2, 1, 0),
1177 SOC_SINGLE("RX6 HPF Switch", TAIKO_A_CDC_RX6_B5_CTL, 2, 1, 0),
1178 SOC_SINGLE("RX7 HPF Switch", TAIKO_A_CDC_RX7_B5_CTL, 2, 1, 0),
1179
1180 SOC_ENUM("RX1 HPF cut off", cf_rxmix1_enum),
1181 SOC_ENUM("RX2 HPF cut off", cf_rxmix2_enum),
1182 SOC_ENUM("RX3 HPF cut off", cf_rxmix3_enum),
1183 SOC_ENUM("RX4 HPF cut off", cf_rxmix4_enum),
1184 SOC_ENUM("RX5 HPF cut off", cf_rxmix5_enum),
1185 SOC_ENUM("RX6 HPF cut off", cf_rxmix6_enum),
1186 SOC_ENUM("RX7 HPF cut off", cf_rxmix7_enum),
1187
1188 SOC_SINGLE_EXT("IIR1 Enable Band1", IIR1, BAND1, 1, 0,
1189 taiko_get_iir_enable_audio_mixer, taiko_put_iir_enable_audio_mixer),
1190 SOC_SINGLE_EXT("IIR1 Enable Band2", IIR1, BAND2, 1, 0,
1191 taiko_get_iir_enable_audio_mixer, taiko_put_iir_enable_audio_mixer),
1192 SOC_SINGLE_EXT("IIR1 Enable Band3", IIR1, BAND3, 1, 0,
1193 taiko_get_iir_enable_audio_mixer, taiko_put_iir_enable_audio_mixer),
1194 SOC_SINGLE_EXT("IIR1 Enable Band4", IIR1, BAND4, 1, 0,
1195 taiko_get_iir_enable_audio_mixer, taiko_put_iir_enable_audio_mixer),
1196 SOC_SINGLE_EXT("IIR1 Enable Band5", IIR1, BAND5, 1, 0,
1197 taiko_get_iir_enable_audio_mixer, taiko_put_iir_enable_audio_mixer),
1198 SOC_SINGLE_EXT("IIR2 Enable Band1", IIR2, BAND1, 1, 0,
1199 taiko_get_iir_enable_audio_mixer, taiko_put_iir_enable_audio_mixer),
1200 SOC_SINGLE_EXT("IIR2 Enable Band2", IIR2, BAND2, 1, 0,
1201 taiko_get_iir_enable_audio_mixer, taiko_put_iir_enable_audio_mixer),
1202 SOC_SINGLE_EXT("IIR2 Enable Band3", IIR2, BAND3, 1, 0,
1203 taiko_get_iir_enable_audio_mixer, taiko_put_iir_enable_audio_mixer),
1204 SOC_SINGLE_EXT("IIR2 Enable Band4", IIR2, BAND4, 1, 0,
1205 taiko_get_iir_enable_audio_mixer, taiko_put_iir_enable_audio_mixer),
1206 SOC_SINGLE_EXT("IIR2 Enable Band5", IIR2, BAND5, 1, 0,
1207 taiko_get_iir_enable_audio_mixer, taiko_put_iir_enable_audio_mixer),
1208
1209 SOC_SINGLE_MULTI_EXT("IIR1 Band1", IIR1, BAND1, 255, 0, 5,
1210 taiko_get_iir_band_audio_mixer, taiko_put_iir_band_audio_mixer),
1211 SOC_SINGLE_MULTI_EXT("IIR1 Band2", IIR1, BAND2, 255, 0, 5,
1212 taiko_get_iir_band_audio_mixer, taiko_put_iir_band_audio_mixer),
1213 SOC_SINGLE_MULTI_EXT("IIR1 Band3", IIR1, BAND3, 255, 0, 5,
1214 taiko_get_iir_band_audio_mixer, taiko_put_iir_band_audio_mixer),
1215 SOC_SINGLE_MULTI_EXT("IIR1 Band4", IIR1, BAND4, 255, 0, 5,
1216 taiko_get_iir_band_audio_mixer, taiko_put_iir_band_audio_mixer),
1217 SOC_SINGLE_MULTI_EXT("IIR1 Band5", IIR1, BAND5, 255, 0, 5,
1218 taiko_get_iir_band_audio_mixer, taiko_put_iir_band_audio_mixer),
1219 SOC_SINGLE_MULTI_EXT("IIR2 Band1", IIR2, BAND1, 255, 0, 5,
1220 taiko_get_iir_band_audio_mixer, taiko_put_iir_band_audio_mixer),
1221 SOC_SINGLE_MULTI_EXT("IIR2 Band2", IIR2, BAND2, 255, 0, 5,
1222 taiko_get_iir_band_audio_mixer, taiko_put_iir_band_audio_mixer),
1223 SOC_SINGLE_MULTI_EXT("IIR2 Band3", IIR2, BAND3, 255, 0, 5,
1224 taiko_get_iir_band_audio_mixer, taiko_put_iir_band_audio_mixer),
1225 SOC_SINGLE_MULTI_EXT("IIR2 Band4", IIR2, BAND4, 255, 0, 5,
1226 taiko_get_iir_band_audio_mixer, taiko_put_iir_band_audio_mixer),
1227 SOC_SINGLE_MULTI_EXT("IIR2 Band5", IIR2, BAND5, 255, 0, 5,
1228 taiko_get_iir_band_audio_mixer, taiko_put_iir_band_audio_mixer),
1229
Joonwoo Parkc7731432012-10-17 12:41:44 -07001230 SOC_SINGLE_EXT("COMP0 Switch", SND_SOC_NOPM, COMPANDER_0, 1, 0,
1231 taiko_get_compander, taiko_set_compander),
1232 SOC_SINGLE_EXT("COMP1 Switch", SND_SOC_NOPM, COMPANDER_1, 1, 0,
1233 taiko_get_compander, taiko_set_compander),
1234 SOC_SINGLE_EXT("COMP2 Switch", SND_SOC_NOPM, COMPANDER_2, 1, 0,
1235 taiko_get_compander, taiko_set_compander),
Kiran Kandic3b24402012-06-11 00:05:59 -07001236
1237};
1238
Kiran Kandiec0db5c2013-03-08 16:03:58 -08001239static int taiko_pa_gain_get(struct snd_kcontrol *kcontrol,
1240 struct snd_ctl_elem_value *ucontrol)
1241{
1242 u8 ear_pa_gain;
1243 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
1244
1245 ear_pa_gain = snd_soc_read(codec, TAIKO_A_RX_EAR_GAIN);
1246
1247 ear_pa_gain = ear_pa_gain >> 5;
1248
1249 ucontrol->value.integer.value[0] = ear_pa_gain;
1250
1251 pr_debug("%s: ear_pa_gain = 0x%x\n", __func__, ear_pa_gain);
1252
1253 return 0;
1254}
1255
1256static int taiko_pa_gain_put(struct snd_kcontrol *kcontrol,
1257 struct snd_ctl_elem_value *ucontrol)
1258{
1259 u8 ear_pa_gain;
1260 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
1261
1262 pr_debug("%s: ucontrol->value.integer.value[0] = %ld\n", __func__,
1263 ucontrol->value.integer.value[0]);
1264
1265 ear_pa_gain = ucontrol->value.integer.value[0] << 5;
1266
1267 snd_soc_update_bits(codec, TAIKO_A_RX_EAR_GAIN, 0xE0, ear_pa_gain);
1268 return 0;
1269}
1270
1271static const char * const taiko_1_x_ear_pa_gain_text[] = {
1272 "POS_6_DB", "UNDEFINED_1", "UNDEFINED_2", "UNDEFINED_3", "POS_2_DB",
1273 "NEG_2P5_DB", "UNDEFINED_4", "NEG_12_DB"
1274};
1275
1276static const struct soc_enum taiko_1_x_ear_pa_gain_enum =
1277 SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(taiko_1_x_ear_pa_gain_text),
1278 taiko_1_x_ear_pa_gain_text);
1279
1280static const struct snd_kcontrol_new taiko_1_x_analog_gain_controls[] = {
1281
1282 SOC_ENUM_EXT("EAR PA Gain", taiko_1_x_ear_pa_gain_enum,
1283 taiko_pa_gain_get, taiko_pa_gain_put),
1284
1285 SOC_SINGLE_TLV("HPHL Volume", TAIKO_A_RX_HPH_L_GAIN, 0, 20, 1,
1286 line_gain),
1287 SOC_SINGLE_TLV("HPHR Volume", TAIKO_A_RX_HPH_R_GAIN, 0, 20, 1,
1288 line_gain),
1289
1290 SOC_SINGLE_TLV("LINEOUT1 Volume", TAIKO_A_RX_LINE_1_GAIN, 0, 20, 1,
1291 line_gain),
1292 SOC_SINGLE_TLV("LINEOUT2 Volume", TAIKO_A_RX_LINE_2_GAIN, 0, 20, 1,
1293 line_gain),
1294 SOC_SINGLE_TLV("LINEOUT3 Volume", TAIKO_A_RX_LINE_3_GAIN, 0, 20, 1,
1295 line_gain),
1296 SOC_SINGLE_TLV("LINEOUT4 Volume", TAIKO_A_RX_LINE_4_GAIN, 0, 20, 1,
1297 line_gain),
1298
1299 SOC_SINGLE_TLV("SPK DRV Volume", TAIKO_A_SPKR_DRV_GAIN, 3, 7, 1,
1300 line_gain),
1301
1302 SOC_SINGLE_TLV("ADC1 Volume", TAIKO_A_TX_1_2_EN, 5, 3, 0, analog_gain),
1303 SOC_SINGLE_TLV("ADC2 Volume", TAIKO_A_TX_1_2_EN, 1, 3, 0, analog_gain),
1304 SOC_SINGLE_TLV("ADC3 Volume", TAIKO_A_TX_3_4_EN, 5, 3, 0, analog_gain),
1305 SOC_SINGLE_TLV("ADC4 Volume", TAIKO_A_TX_3_4_EN, 1, 3, 0, analog_gain),
1306 SOC_SINGLE_TLV("ADC5 Volume", TAIKO_A_TX_5_6_EN, 5, 3, 0, analog_gain),
1307 SOC_SINGLE_TLV("ADC6 Volume", TAIKO_A_TX_5_6_EN, 1, 3, 0, analog_gain),
1308};
1309
1310static const char * const taiko_2_x_ear_pa_gain_text[] = {
1311 "POS_6_DB", "POS_4P5_DB", "POS_3_DB", "POS_1P5_DB",
1312 "POS_0_DB", "NEG_2P5_DB", "UNDEFINED", "NEG_12_DB"
1313};
1314
1315static const struct soc_enum taiko_2_x_ear_pa_gain_enum =
1316 SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(taiko_2_x_ear_pa_gain_text),
1317 taiko_2_x_ear_pa_gain_text);
1318
1319static const struct snd_kcontrol_new taiko_2_x_analog_gain_controls[] = {
1320
1321 SOC_ENUM_EXT("EAR PA Gain", taiko_2_x_ear_pa_gain_enum,
1322 taiko_pa_gain_get, taiko_pa_gain_put),
1323
1324 SOC_SINGLE_TLV("HPHL Volume", TAIKO_A_RX_HPH_L_GAIN, 0, 20, 1,
1325 line_gain),
1326 SOC_SINGLE_TLV("HPHR Volume", TAIKO_A_RX_HPH_R_GAIN, 0, 20, 1,
1327 line_gain),
1328
1329 SOC_SINGLE_TLV("LINEOUT1 Volume", TAIKO_A_RX_LINE_1_GAIN, 0, 20, 1,
1330 line_gain),
1331 SOC_SINGLE_TLV("LINEOUT2 Volume", TAIKO_A_RX_LINE_2_GAIN, 0, 20, 1,
1332 line_gain),
1333 SOC_SINGLE_TLV("LINEOUT3 Volume", TAIKO_A_RX_LINE_3_GAIN, 0, 20, 1,
1334 line_gain),
1335 SOC_SINGLE_TLV("LINEOUT4 Volume", TAIKO_A_RX_LINE_4_GAIN, 0, 20, 1,
1336 line_gain),
1337
1338 SOC_SINGLE_TLV("SPK DRV Volume", TAIKO_A_SPKR_DRV_GAIN, 3, 8, 1,
1339 line_gain),
1340
1341 SOC_SINGLE_TLV("ADC1 Volume", TAIKO_A_CDC_TX_1_GAIN, 2, 19, 0,
1342 analog_gain),
1343 SOC_SINGLE_TLV("ADC2 Volume", TAIKO_A_CDC_TX_2_GAIN, 2, 19, 0,
1344 analog_gain),
1345 SOC_SINGLE_TLV("ADC3 Volume", TAIKO_A_CDC_TX_3_GAIN, 2, 19, 0,
1346 analog_gain),
1347 SOC_SINGLE_TLV("ADC4 Volume", TAIKO_A_CDC_TX_4_GAIN, 2, 19, 0,
1348 analog_gain),
1349 SOC_SINGLE_TLV("ADC5 Volume", TAIKO_A_CDC_TX_5_GAIN, 2, 19, 0,
1350 analog_gain),
1351 SOC_SINGLE_TLV("ADC6 Volume", TAIKO_A_CDC_TX_6_GAIN, 2, 19, 0,
1352 analog_gain),
1353};
1354
Kiran Kandic3b24402012-06-11 00:05:59 -07001355static const char * const rx_mix1_text[] = {
1356 "ZERO", "SRC1", "SRC2", "IIR1", "IIR2", "RX1", "RX2", "RX3", "RX4",
1357 "RX5", "RX6", "RX7"
1358};
1359
1360static const char * const rx_mix2_text[] = {
1361 "ZERO", "SRC1", "SRC2", "IIR1", "IIR2"
1362};
1363
Tanya Finkeldaaa6d12012-10-25 11:22:48 +02001364static const char * const rx_rdac5_text[] = {
1365 "DEM4", "DEM3_INV"
Kiran Kandic3b24402012-06-11 00:05:59 -07001366};
1367
Tanya Finkeldaaa6d12012-10-25 11:22:48 +02001368static const char * const rx_rdac7_text[] = {
1369 "DEM6", "DEM5_INV"
1370};
1371
1372
Kiran Kandic3b24402012-06-11 00:05:59 -07001373static const char * const sb_tx1_mux_text[] = {
1374 "ZERO", "RMIX1", "RMIX2", "RMIX3", "RMIX4", "RMIX5", "RMIX6", "RMIX7",
1375 "DEC1"
1376};
1377
1378static const char * const sb_tx2_mux_text[] = {
1379 "ZERO", "RMIX1", "RMIX2", "RMIX3", "RMIX4", "RMIX5", "RMIX6", "RMIX7",
1380 "DEC2"
1381};
1382
1383static const char * const sb_tx3_mux_text[] = {
1384 "ZERO", "RMIX1", "RMIX2", "RMIX3", "RMIX4", "RMIX5", "RMIX6", "RMIX7",
1385 "DEC3"
1386};
1387
1388static const char * const sb_tx4_mux_text[] = {
1389 "ZERO", "RMIX1", "RMIX2", "RMIX3", "RMIX4", "RMIX5", "RMIX6", "RMIX7",
1390 "DEC4"
1391};
1392
1393static const char * const sb_tx5_mux_text[] = {
1394 "ZERO", "RMIX1", "RMIX2", "RMIX3", "RMIX4", "RMIX5", "RMIX6", "RMIX7",
1395 "DEC5"
1396};
1397
1398static const char * const sb_tx6_mux_text[] = {
1399 "ZERO", "RMIX1", "RMIX2", "RMIX3", "RMIX4", "RMIX5", "RMIX6", "RMIX7",
1400 "DEC6"
1401};
1402
1403static const char * const sb_tx7_to_tx10_mux_text[] = {
1404 "ZERO", "RMIX1", "RMIX2", "RMIX3", "RMIX4", "RMIX5", "RMIX6", "RMIX7",
1405 "DEC1", "DEC2", "DEC3", "DEC4", "DEC5", "DEC6", "DEC7", "DEC8",
1406 "DEC9", "DEC10"
1407};
1408
1409static const char * const dec1_mux_text[] = {
1410 "ZERO", "DMIC1", "ADC6",
1411};
1412
1413static const char * const dec2_mux_text[] = {
1414 "ZERO", "DMIC2", "ADC5",
1415};
1416
1417static const char * const dec3_mux_text[] = {
1418 "ZERO", "DMIC3", "ADC4",
1419};
1420
1421static const char * const dec4_mux_text[] = {
1422 "ZERO", "DMIC4", "ADC3",
1423};
1424
1425static const char * const dec5_mux_text[] = {
1426 "ZERO", "DMIC5", "ADC2",
1427};
1428
1429static const char * const dec6_mux_text[] = {
1430 "ZERO", "DMIC6", "ADC1",
1431};
1432
1433static const char * const dec7_mux_text[] = {
1434 "ZERO", "DMIC1", "DMIC6", "ADC1", "ADC6", "ANC1_FB", "ANC2_FB",
1435};
1436
1437static const char * const dec8_mux_text[] = {
1438 "ZERO", "DMIC2", "DMIC5", "ADC2", "ADC5",
1439};
1440
1441static const char * const dec9_mux_text[] = {
1442 "ZERO", "DMIC4", "DMIC5", "ADC2", "ADC3", "ADCMB", "ANC1_FB", "ANC2_FB",
1443};
1444
1445static const char * const dec10_mux_text[] = {
1446 "ZERO", "DMIC3", "DMIC6", "ADC1", "ADC4", "ADCMB", "ANC1_FB", "ANC2_FB",
1447};
1448
1449static const char * const anc_mux_text[] = {
1450 "ZERO", "ADC1", "ADC2", "ADC3", "ADC4", "ADC5", "ADC6", "ADC_MB",
1451 "RSVD_1", "DMIC1", "DMIC2", "DMIC3", "DMIC4", "DMIC5", "DMIC6"
1452};
1453
1454static const char * const anc1_fb_mux_text[] = {
1455 "ZERO", "EAR_HPH_L", "EAR_LINE_1",
1456};
1457
Fred Oh456fcb52013-02-28 19:08:15 -08001458static const char * const iir_inp1_text[] = {
Kiran Kandic3b24402012-06-11 00:05:59 -07001459 "ZERO", "DEC1", "DEC2", "DEC3", "DEC4", "DEC5", "DEC6", "DEC7", "DEC8",
1460 "DEC9", "DEC10", "RX1", "RX2", "RX3", "RX4", "RX5", "RX6", "RX7"
1461};
1462
1463static const struct soc_enum rx_mix1_inp1_chain_enum =
1464 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_RX1_B1_CTL, 0, 12, rx_mix1_text);
1465
1466static const struct soc_enum rx_mix1_inp2_chain_enum =
1467 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_RX1_B1_CTL, 4, 12, rx_mix1_text);
1468
1469static const struct soc_enum rx_mix1_inp3_chain_enum =
1470 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_RX1_B2_CTL, 0, 12, rx_mix1_text);
1471
1472static const struct soc_enum rx2_mix1_inp1_chain_enum =
1473 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_RX2_B1_CTL, 0, 12, rx_mix1_text);
1474
1475static const struct soc_enum rx2_mix1_inp2_chain_enum =
1476 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_RX2_B1_CTL, 4, 12, rx_mix1_text);
1477
1478static const struct soc_enum rx3_mix1_inp1_chain_enum =
1479 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_RX3_B1_CTL, 0, 12, rx_mix1_text);
1480
1481static const struct soc_enum rx3_mix1_inp2_chain_enum =
1482 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_RX3_B1_CTL, 4, 12, rx_mix1_text);
1483
1484static const struct soc_enum rx4_mix1_inp1_chain_enum =
1485 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_RX4_B1_CTL, 0, 12, rx_mix1_text);
1486
1487static const struct soc_enum rx4_mix1_inp2_chain_enum =
1488 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_RX4_B1_CTL, 4, 12, rx_mix1_text);
1489
1490static const struct soc_enum rx5_mix1_inp1_chain_enum =
1491 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_RX5_B1_CTL, 0, 12, rx_mix1_text);
1492
1493static const struct soc_enum rx5_mix1_inp2_chain_enum =
1494 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_RX5_B1_CTL, 4, 12, rx_mix1_text);
1495
1496static const struct soc_enum rx6_mix1_inp1_chain_enum =
1497 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_RX6_B1_CTL, 0, 12, rx_mix1_text);
1498
1499static const struct soc_enum rx6_mix1_inp2_chain_enum =
1500 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_RX6_B1_CTL, 4, 12, rx_mix1_text);
1501
1502static const struct soc_enum rx7_mix1_inp1_chain_enum =
1503 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_RX7_B1_CTL, 0, 12, rx_mix1_text);
1504
1505static const struct soc_enum rx7_mix1_inp2_chain_enum =
1506 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_RX7_B1_CTL, 4, 12, rx_mix1_text);
1507
1508static const struct soc_enum rx1_mix2_inp1_chain_enum =
1509 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_RX1_B3_CTL, 0, 5, rx_mix2_text);
1510
1511static const struct soc_enum rx1_mix2_inp2_chain_enum =
1512 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_RX1_B3_CTL, 3, 5, rx_mix2_text);
1513
1514static const struct soc_enum rx2_mix2_inp1_chain_enum =
1515 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_RX2_B3_CTL, 0, 5, rx_mix2_text);
1516
1517static const struct soc_enum rx2_mix2_inp2_chain_enum =
1518 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_RX2_B3_CTL, 3, 5, rx_mix2_text);
1519
1520static const struct soc_enum rx7_mix2_inp1_chain_enum =
1521 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_RX7_B3_CTL, 0, 5, rx_mix2_text);
1522
1523static const struct soc_enum rx7_mix2_inp2_chain_enum =
1524 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_RX7_B3_CTL, 3, 5, rx_mix2_text);
1525
Tanya Finkeldaaa6d12012-10-25 11:22:48 +02001526static const struct soc_enum rx_rdac5_enum =
1527 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_MISC, 2, 2, rx_rdac5_text);
Kiran Kandic3b24402012-06-11 00:05:59 -07001528
Tanya Finkeldaaa6d12012-10-25 11:22:48 +02001529static const struct soc_enum rx_rdac7_enum =
1530 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_MISC, 1, 2, rx_rdac7_text);
Kiran Kandic3b24402012-06-11 00:05:59 -07001531
1532static const struct soc_enum sb_tx1_mux_enum =
1533 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_TX_SB_B1_CTL, 0, 9, sb_tx1_mux_text);
1534
1535static const struct soc_enum sb_tx2_mux_enum =
1536 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_TX_SB_B2_CTL, 0, 9, sb_tx2_mux_text);
1537
1538static const struct soc_enum sb_tx3_mux_enum =
1539 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_TX_SB_B3_CTL, 0, 9, sb_tx3_mux_text);
1540
1541static const struct soc_enum sb_tx4_mux_enum =
1542 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_TX_SB_B4_CTL, 0, 9, sb_tx4_mux_text);
1543
1544static const struct soc_enum sb_tx5_mux_enum =
1545 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_TX_SB_B5_CTL, 0, 9, sb_tx5_mux_text);
1546
1547static const struct soc_enum sb_tx6_mux_enum =
1548 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_TX_SB_B6_CTL, 0, 9, sb_tx6_mux_text);
1549
1550static const struct soc_enum sb_tx7_mux_enum =
1551 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_TX_SB_B7_CTL, 0, 18,
1552 sb_tx7_to_tx10_mux_text);
1553
1554static const struct soc_enum sb_tx8_mux_enum =
1555 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_TX_SB_B8_CTL, 0, 18,
1556 sb_tx7_to_tx10_mux_text);
1557
1558static const struct soc_enum sb_tx9_mux_enum =
1559 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_TX_SB_B9_CTL, 0, 18,
1560 sb_tx7_to_tx10_mux_text);
1561
1562static const struct soc_enum sb_tx10_mux_enum =
1563 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_TX_SB_B10_CTL, 0, 18,
1564 sb_tx7_to_tx10_mux_text);
1565
1566static const struct soc_enum dec1_mux_enum =
1567 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_TX_B1_CTL, 0, 3, dec1_mux_text);
1568
1569static const struct soc_enum dec2_mux_enum =
1570 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_TX_B1_CTL, 2, 3, dec2_mux_text);
1571
1572static const struct soc_enum dec3_mux_enum =
1573 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_TX_B1_CTL, 4, 3, dec3_mux_text);
1574
1575static const struct soc_enum dec4_mux_enum =
1576 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_TX_B1_CTL, 6, 3, dec4_mux_text);
1577
1578static const struct soc_enum dec5_mux_enum =
1579 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_TX_B2_CTL, 0, 3, dec5_mux_text);
1580
1581static const struct soc_enum dec6_mux_enum =
1582 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_TX_B2_CTL, 2, 3, dec6_mux_text);
1583
1584static const struct soc_enum dec7_mux_enum =
1585 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_TX_B2_CTL, 4, 7, dec7_mux_text);
1586
1587static const struct soc_enum dec8_mux_enum =
1588 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_TX_B3_CTL, 0, 7, dec8_mux_text);
1589
1590static const struct soc_enum dec9_mux_enum =
1591 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_TX_B3_CTL, 3, 8, dec9_mux_text);
1592
1593static const struct soc_enum dec10_mux_enum =
1594 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_TX_B4_CTL, 0, 8, dec10_mux_text);
1595
1596static const struct soc_enum anc1_mux_enum =
1597 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_ANC_B1_CTL, 0, 16, anc_mux_text);
1598
1599static const struct soc_enum anc2_mux_enum =
1600 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_ANC_B1_CTL, 4, 16, anc_mux_text);
1601
1602static const struct soc_enum anc1_fb_mux_enum =
1603 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_ANC_B2_CTL, 0, 3, anc1_fb_mux_text);
1604
1605static const struct soc_enum iir1_inp1_mux_enum =
Fred Oh456fcb52013-02-28 19:08:15 -08001606 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_EQ1_B1_CTL, 0, 18, iir_inp1_text);
1607
1608static const struct soc_enum iir2_inp1_mux_enum =
1609 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_EQ2_B1_CTL, 0, 18, iir_inp1_text);
Kiran Kandic3b24402012-06-11 00:05:59 -07001610
1611static const struct snd_kcontrol_new rx_mix1_inp1_mux =
1612 SOC_DAPM_ENUM("RX1 MIX1 INP1 Mux", rx_mix1_inp1_chain_enum);
1613
1614static const struct snd_kcontrol_new rx_mix1_inp2_mux =
1615 SOC_DAPM_ENUM("RX1 MIX1 INP2 Mux", rx_mix1_inp2_chain_enum);
1616
1617static const struct snd_kcontrol_new rx_mix1_inp3_mux =
1618 SOC_DAPM_ENUM("RX1 MIX1 INP3 Mux", rx_mix1_inp3_chain_enum);
1619
1620static const struct snd_kcontrol_new rx2_mix1_inp1_mux =
1621 SOC_DAPM_ENUM("RX2 MIX1 INP1 Mux", rx2_mix1_inp1_chain_enum);
1622
1623static const struct snd_kcontrol_new rx2_mix1_inp2_mux =
1624 SOC_DAPM_ENUM("RX2 MIX1 INP2 Mux", rx2_mix1_inp2_chain_enum);
1625
1626static const struct snd_kcontrol_new rx3_mix1_inp1_mux =
1627 SOC_DAPM_ENUM("RX3 MIX1 INP1 Mux", rx3_mix1_inp1_chain_enum);
1628
1629static const struct snd_kcontrol_new rx3_mix1_inp2_mux =
1630 SOC_DAPM_ENUM("RX3 MIX1 INP2 Mux", rx3_mix1_inp2_chain_enum);
1631
1632static const struct snd_kcontrol_new rx4_mix1_inp1_mux =
1633 SOC_DAPM_ENUM("RX4 MIX1 INP1 Mux", rx4_mix1_inp1_chain_enum);
1634
1635static const struct snd_kcontrol_new rx4_mix1_inp2_mux =
1636 SOC_DAPM_ENUM("RX4 MIX1 INP2 Mux", rx4_mix1_inp2_chain_enum);
1637
1638static const struct snd_kcontrol_new rx5_mix1_inp1_mux =
1639 SOC_DAPM_ENUM("RX5 MIX1 INP1 Mux", rx5_mix1_inp1_chain_enum);
1640
1641static const struct snd_kcontrol_new rx5_mix1_inp2_mux =
1642 SOC_DAPM_ENUM("RX5 MIX1 INP2 Mux", rx5_mix1_inp2_chain_enum);
1643
1644static const struct snd_kcontrol_new rx6_mix1_inp1_mux =
1645 SOC_DAPM_ENUM("RX6 MIX1 INP1 Mux", rx6_mix1_inp1_chain_enum);
1646
1647static const struct snd_kcontrol_new rx6_mix1_inp2_mux =
1648 SOC_DAPM_ENUM("RX6 MIX1 INP2 Mux", rx6_mix1_inp2_chain_enum);
1649
1650static const struct snd_kcontrol_new rx7_mix1_inp1_mux =
1651 SOC_DAPM_ENUM("RX7 MIX1 INP1 Mux", rx7_mix1_inp1_chain_enum);
1652
1653static const struct snd_kcontrol_new rx7_mix1_inp2_mux =
1654 SOC_DAPM_ENUM("RX7 MIX1 INP2 Mux", rx7_mix1_inp2_chain_enum);
1655
1656static const struct snd_kcontrol_new rx1_mix2_inp1_mux =
1657 SOC_DAPM_ENUM("RX1 MIX2 INP1 Mux", rx1_mix2_inp1_chain_enum);
1658
1659static const struct snd_kcontrol_new rx1_mix2_inp2_mux =
1660 SOC_DAPM_ENUM("RX1 MIX2 INP2 Mux", rx1_mix2_inp2_chain_enum);
1661
1662static const struct snd_kcontrol_new rx2_mix2_inp1_mux =
1663 SOC_DAPM_ENUM("RX2 MIX2 INP1 Mux", rx2_mix2_inp1_chain_enum);
1664
1665static const struct snd_kcontrol_new rx2_mix2_inp2_mux =
1666 SOC_DAPM_ENUM("RX2 MIX2 INP2 Mux", rx2_mix2_inp2_chain_enum);
1667
1668static const struct snd_kcontrol_new rx7_mix2_inp1_mux =
1669 SOC_DAPM_ENUM("RX7 MIX2 INP1 Mux", rx7_mix2_inp1_chain_enum);
1670
1671static const struct snd_kcontrol_new rx7_mix2_inp2_mux =
1672 SOC_DAPM_ENUM("RX7 MIX2 INP2 Mux", rx7_mix2_inp2_chain_enum);
1673
Tanya Finkeldaaa6d12012-10-25 11:22:48 +02001674static const struct snd_kcontrol_new rx_dac5_mux =
1675 SOC_DAPM_ENUM("RDAC5 MUX Mux", rx_rdac5_enum);
Kiran Kandic3b24402012-06-11 00:05:59 -07001676
Tanya Finkeldaaa6d12012-10-25 11:22:48 +02001677static const struct snd_kcontrol_new rx_dac7_mux =
1678 SOC_DAPM_ENUM("RDAC7 MUX Mux", rx_rdac7_enum);
Kiran Kandic3b24402012-06-11 00:05:59 -07001679
1680static const struct snd_kcontrol_new sb_tx1_mux =
1681 SOC_DAPM_ENUM("SLIM TX1 MUX Mux", sb_tx1_mux_enum);
1682
1683static const struct snd_kcontrol_new sb_tx2_mux =
1684 SOC_DAPM_ENUM("SLIM TX2 MUX Mux", sb_tx2_mux_enum);
1685
1686static const struct snd_kcontrol_new sb_tx3_mux =
1687 SOC_DAPM_ENUM("SLIM TX3 MUX Mux", sb_tx3_mux_enum);
1688
1689static const struct snd_kcontrol_new sb_tx4_mux =
1690 SOC_DAPM_ENUM("SLIM TX4 MUX Mux", sb_tx4_mux_enum);
1691
1692static const struct snd_kcontrol_new sb_tx5_mux =
1693 SOC_DAPM_ENUM("SLIM TX5 MUX Mux", sb_tx5_mux_enum);
1694
1695static const struct snd_kcontrol_new sb_tx6_mux =
1696 SOC_DAPM_ENUM("SLIM TX6 MUX Mux", sb_tx6_mux_enum);
1697
1698static const struct snd_kcontrol_new sb_tx7_mux =
1699 SOC_DAPM_ENUM("SLIM TX7 MUX Mux", sb_tx7_mux_enum);
1700
1701static const struct snd_kcontrol_new sb_tx8_mux =
1702 SOC_DAPM_ENUM("SLIM TX8 MUX Mux", sb_tx8_mux_enum);
1703
1704static const struct snd_kcontrol_new sb_tx9_mux =
1705 SOC_DAPM_ENUM("SLIM TX9 MUX Mux", sb_tx9_mux_enum);
1706
1707static const struct snd_kcontrol_new sb_tx10_mux =
1708 SOC_DAPM_ENUM("SLIM TX10 MUX Mux", sb_tx10_mux_enum);
1709
1710
1711static int wcd9320_put_dec_enum(struct snd_kcontrol *kcontrol,
1712 struct snd_ctl_elem_value *ucontrol)
1713{
1714 struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol);
1715 struct snd_soc_dapm_widget *w = wlist->widgets[0];
1716 struct snd_soc_codec *codec = w->codec;
1717 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
1718 unsigned int dec_mux, decimator;
1719 char *dec_name = NULL;
1720 char *widget_name = NULL;
1721 char *temp;
1722 u16 tx_mux_ctl_reg;
1723 u8 adc_dmic_sel = 0x0;
1724 int ret = 0;
1725
1726 if (ucontrol->value.enumerated.item[0] > e->max - 1)
1727 return -EINVAL;
1728
1729 dec_mux = ucontrol->value.enumerated.item[0];
1730
1731 widget_name = kstrndup(w->name, 15, GFP_KERNEL);
1732 if (!widget_name)
1733 return -ENOMEM;
1734 temp = widget_name;
1735
1736 dec_name = strsep(&widget_name, " ");
1737 widget_name = temp;
1738 if (!dec_name) {
1739 pr_err("%s: Invalid decimator = %s\n", __func__, w->name);
1740 ret = -EINVAL;
1741 goto out;
1742 }
1743
1744 ret = kstrtouint(strpbrk(dec_name, "123456789"), 10, &decimator);
1745 if (ret < 0) {
1746 pr_err("%s: Invalid decimator = %s\n", __func__, dec_name);
1747 ret = -EINVAL;
1748 goto out;
1749 }
1750
1751 dev_dbg(w->dapm->dev, "%s(): widget = %s decimator = %u dec_mux = %u\n"
1752 , __func__, w->name, decimator, dec_mux);
1753
1754
1755 switch (decimator) {
1756 case 1:
1757 case 2:
1758 case 3:
1759 case 4:
1760 case 5:
1761 case 6:
1762 if (dec_mux == 1)
1763 adc_dmic_sel = 0x1;
1764 else
1765 adc_dmic_sel = 0x0;
1766 break;
1767 case 7:
1768 case 8:
1769 case 9:
1770 case 10:
1771 if ((dec_mux == 1) || (dec_mux == 2))
1772 adc_dmic_sel = 0x1;
1773 else
1774 adc_dmic_sel = 0x0;
1775 break;
1776 default:
1777 pr_err("%s: Invalid Decimator = %u\n", __func__, decimator);
1778 ret = -EINVAL;
1779 goto out;
1780 }
1781
1782 tx_mux_ctl_reg = TAIKO_A_CDC_TX1_MUX_CTL + 8 * (decimator - 1);
1783
1784 snd_soc_update_bits(codec, tx_mux_ctl_reg, 0x1, adc_dmic_sel);
1785
1786 ret = snd_soc_dapm_put_enum_double(kcontrol, ucontrol);
1787
1788out:
1789 kfree(widget_name);
1790 return ret;
1791}
1792
1793#define WCD9320_DEC_ENUM(xname, xenum) \
1794{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
1795 .info = snd_soc_info_enum_double, \
1796 .get = snd_soc_dapm_get_enum_double, \
1797 .put = wcd9320_put_dec_enum, \
1798 .private_value = (unsigned long)&xenum }
1799
1800static const struct snd_kcontrol_new dec1_mux =
1801 WCD9320_DEC_ENUM("DEC1 MUX Mux", dec1_mux_enum);
1802
1803static const struct snd_kcontrol_new dec2_mux =
1804 WCD9320_DEC_ENUM("DEC2 MUX Mux", dec2_mux_enum);
1805
1806static const struct snd_kcontrol_new dec3_mux =
1807 WCD9320_DEC_ENUM("DEC3 MUX Mux", dec3_mux_enum);
1808
1809static const struct snd_kcontrol_new dec4_mux =
1810 WCD9320_DEC_ENUM("DEC4 MUX Mux", dec4_mux_enum);
1811
1812static const struct snd_kcontrol_new dec5_mux =
1813 WCD9320_DEC_ENUM("DEC5 MUX Mux", dec5_mux_enum);
1814
1815static const struct snd_kcontrol_new dec6_mux =
1816 WCD9320_DEC_ENUM("DEC6 MUX Mux", dec6_mux_enum);
1817
1818static const struct snd_kcontrol_new dec7_mux =
1819 WCD9320_DEC_ENUM("DEC7 MUX Mux", dec7_mux_enum);
1820
1821static const struct snd_kcontrol_new dec8_mux =
1822 WCD9320_DEC_ENUM("DEC8 MUX Mux", dec8_mux_enum);
1823
1824static const struct snd_kcontrol_new dec9_mux =
1825 WCD9320_DEC_ENUM("DEC9 MUX Mux", dec9_mux_enum);
1826
1827static const struct snd_kcontrol_new dec10_mux =
1828 WCD9320_DEC_ENUM("DEC10 MUX Mux", dec10_mux_enum);
1829
1830static const struct snd_kcontrol_new iir1_inp1_mux =
1831 SOC_DAPM_ENUM("IIR1 INP1 Mux", iir1_inp1_mux_enum);
1832
Fred Oh456fcb52013-02-28 19:08:15 -08001833static const struct snd_kcontrol_new iir2_inp1_mux =
1834 SOC_DAPM_ENUM("IIR2 INP1 Mux", iir2_inp1_mux_enum);
1835
Kiran Kandic3b24402012-06-11 00:05:59 -07001836static const struct snd_kcontrol_new anc1_mux =
1837 SOC_DAPM_ENUM("ANC1 MUX Mux", anc1_mux_enum);
1838
1839static const struct snd_kcontrol_new anc2_mux =
1840 SOC_DAPM_ENUM("ANC2 MUX Mux", anc2_mux_enum);
1841
1842static const struct snd_kcontrol_new anc1_fb_mux =
1843 SOC_DAPM_ENUM("ANC1 FB MUX Mux", anc1_fb_mux_enum);
1844
1845static const struct snd_kcontrol_new dac1_switch[] = {
1846 SOC_DAPM_SINGLE("Switch", TAIKO_A_RX_EAR_EN, 5, 1, 0)
1847};
1848static const struct snd_kcontrol_new hphl_switch[] = {
1849 SOC_DAPM_SINGLE("Switch", TAIKO_A_RX_HPH_L_DAC_CTL, 6, 1, 0)
1850};
1851
1852static const struct snd_kcontrol_new hphl_pa_mix[] = {
1853 SOC_DAPM_SINGLE("AUX_PGA_L Switch", TAIKO_A_RX_PA_AUX_IN_CONN,
1854 7, 1, 0),
1855};
1856
1857static const struct snd_kcontrol_new hphr_pa_mix[] = {
1858 SOC_DAPM_SINGLE("AUX_PGA_R Switch", TAIKO_A_RX_PA_AUX_IN_CONN,
1859 6, 1, 0),
1860};
1861
1862static const struct snd_kcontrol_new ear_pa_mix[] = {
1863 SOC_DAPM_SINGLE("AUX_PGA_L Switch", TAIKO_A_RX_PA_AUX_IN_CONN,
1864 5, 1, 0),
1865};
1866static const struct snd_kcontrol_new lineout1_pa_mix[] = {
1867 SOC_DAPM_SINGLE("AUX_PGA_L Switch", TAIKO_A_RX_PA_AUX_IN_CONN,
1868 4, 1, 0),
1869};
1870
1871static const struct snd_kcontrol_new lineout2_pa_mix[] = {
1872 SOC_DAPM_SINGLE("AUX_PGA_R Switch", TAIKO_A_RX_PA_AUX_IN_CONN,
1873 3, 1, 0),
1874};
1875
1876static const struct snd_kcontrol_new lineout3_pa_mix[] = {
1877 SOC_DAPM_SINGLE("AUX_PGA_L Switch", TAIKO_A_RX_PA_AUX_IN_CONN,
1878 2, 1, 0),
1879};
1880
1881static const struct snd_kcontrol_new lineout4_pa_mix[] = {
1882 SOC_DAPM_SINGLE("AUX_PGA_R Switch", TAIKO_A_RX_PA_AUX_IN_CONN,
1883 1, 1, 0),
1884};
1885
1886static const struct snd_kcontrol_new lineout3_ground_switch =
1887 SOC_DAPM_SINGLE("Switch", TAIKO_A_RX_LINE_3_DAC_CTL, 6, 1, 0);
1888
1889static const struct snd_kcontrol_new lineout4_ground_switch =
1890 SOC_DAPM_SINGLE("Switch", TAIKO_A_RX_LINE_4_DAC_CTL, 6, 1, 0);
1891
Joonwoo Park9ead0e92013-03-18 11:33:33 -07001892static const struct snd_kcontrol_new aif4_mad_switch =
1893 SOC_DAPM_SINGLE("Switch", TAIKO_A_CDC_CLK_OTHR_CTL, 4, 1, 0);
1894
Kuirong Wang906ac472012-07-09 12:54:44 -07001895/* virtual port entries */
1896static int slim_tx_mixer_get(struct snd_kcontrol *kcontrol,
1897 struct snd_ctl_elem_value *ucontrol)
1898{
1899 struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol);
1900 struct snd_soc_dapm_widget *widget = wlist->widgets[0];
1901
1902 ucontrol->value.integer.value[0] = widget->value;
1903 return 0;
1904}
1905
1906static int slim_tx_mixer_put(struct snd_kcontrol *kcontrol,
1907 struct snd_ctl_elem_value *ucontrol)
1908{
1909 struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol);
1910 struct snd_soc_dapm_widget *widget = wlist->widgets[0];
1911 struct snd_soc_codec *codec = widget->codec;
1912 struct taiko_priv *taiko_p = snd_soc_codec_get_drvdata(codec);
1913 struct wcd9xxx *core = dev_get_drvdata(codec->dev->parent);
1914 struct soc_multi_mixer_control *mixer =
1915 ((struct soc_multi_mixer_control *)kcontrol->private_value);
1916 u32 dai_id = widget->shift;
1917 u32 port_id = mixer->shift;
1918 u32 enable = ucontrol->value.integer.value[0];
Venkat Sudhir96dd28c2012-12-04 17:00:19 -08001919 u32 vtable = vport_check_table[dai_id];
Kuirong Wang906ac472012-07-09 12:54:44 -07001920
1921
1922 pr_debug("%s: wname %s cname %s value %u shift %d item %ld\n", __func__,
1923 widget->name, ucontrol->id.name, widget->value, widget->shift,
1924 ucontrol->value.integer.value[0]);
1925
1926 mutex_lock(&codec->mutex);
1927
1928 if (taiko_p->intf_type != WCD9XXX_INTERFACE_TYPE_SLIMBUS) {
1929 if (dai_id != AIF1_CAP) {
1930 dev_err(codec->dev, "%s: invalid AIF for I2C mode\n",
1931 __func__);
1932 mutex_unlock(&codec->mutex);
1933 return -EINVAL;
1934 }
1935 }
Venkat Sudhira41630a2012-10-27 00:57:31 -07001936 switch (dai_id) {
1937 case AIF1_CAP:
1938 case AIF2_CAP:
1939 case AIF3_CAP:
1940 /* only add to the list if value not set
1941 */
1942 if (enable && !(widget->value & 1 << port_id)) {
Venkat Sudhir96dd28c2012-12-04 17:00:19 -08001943
1944 if (taiko_p->intf_type ==
1945 WCD9XXX_INTERFACE_TYPE_SLIMBUS)
1946 vtable = vport_check_table[dai_id];
1947 if (taiko_p->intf_type ==
1948 WCD9XXX_INTERFACE_TYPE_I2C)
1949 vtable = vport_i2s_check_table[dai_id];
1950
Venkat Sudhira41630a2012-10-27 00:57:31 -07001951 if (wcd9xxx_tx_vport_validation(
Venkat Sudhir96dd28c2012-12-04 17:00:19 -08001952 vtable,
Kuirong Wangdcc392e2012-10-19 00:33:38 -07001953 port_id,
1954 taiko_p->dai)) {
Venkat Sudhira41630a2012-10-27 00:57:31 -07001955 pr_debug("%s: TX%u is used by other\n"
1956 "virtual port\n",
1957 __func__, port_id + 1);
1958 mutex_unlock(&codec->mutex);
1959 return -EINVAL;
1960 }
1961 widget->value |= 1 << port_id;
1962 list_add_tail(&core->tx_chs[port_id].list,
Kuirong Wang906ac472012-07-09 12:54:44 -07001963 &taiko_p->dai[dai_id].wcd9xxx_ch_list
Venkat Sudhira41630a2012-10-27 00:57:31 -07001964 );
1965 } else if (!enable && (widget->value & 1 << port_id)) {
1966 widget->value &= ~(1 << port_id);
1967 list_del_init(&core->tx_chs[port_id].list);
1968 } else {
1969 if (enable)
1970 pr_debug("%s: TX%u port is used by\n"
1971 "this virtual port\n",
1972 __func__, port_id + 1);
1973 else
1974 pr_debug("%s: TX%u port is not used by\n"
1975 "this virtual port\n",
1976 __func__, port_id + 1);
1977 /* avoid update power function */
1978 mutex_unlock(&codec->mutex);
1979 return 0;
1980 }
1981 break;
1982 default:
1983 pr_err("Unknown AIF %d\n", dai_id);
Kuirong Wang906ac472012-07-09 12:54:44 -07001984 mutex_unlock(&codec->mutex);
Venkat Sudhira41630a2012-10-27 00:57:31 -07001985 return -EINVAL;
Kuirong Wang906ac472012-07-09 12:54:44 -07001986 }
Kuirong Wang906ac472012-07-09 12:54:44 -07001987 pr_debug("%s: name %s sname %s updated value %u shift %d\n", __func__,
1988 widget->name, widget->sname, widget->value, widget->shift);
1989
1990 snd_soc_dapm_mixer_update_power(widget, kcontrol, enable);
1991
1992 mutex_unlock(&codec->mutex);
1993 return 0;
1994}
1995
1996static int slim_rx_mux_get(struct snd_kcontrol *kcontrol,
1997 struct snd_ctl_elem_value *ucontrol)
1998{
1999 struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol);
2000 struct snd_soc_dapm_widget *widget = wlist->widgets[0];
2001
2002 ucontrol->value.enumerated.item[0] = widget->value;
2003 return 0;
2004}
2005
2006static const char *const slim_rx_mux_text[] = {
2007 "ZERO", "AIF1_PB", "AIF2_PB", "AIF3_PB"
2008};
2009
2010static int slim_rx_mux_put(struct snd_kcontrol *kcontrol,
2011 struct snd_ctl_elem_value *ucontrol)
2012{
2013 struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol);
2014 struct snd_soc_dapm_widget *widget = wlist->widgets[0];
2015 struct snd_soc_codec *codec = widget->codec;
2016 struct taiko_priv *taiko_p = snd_soc_codec_get_drvdata(codec);
2017 struct wcd9xxx *core = dev_get_drvdata(codec->dev->parent);
2018 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
2019 u32 port_id = widget->shift;
2020
2021 pr_debug("%s: wname %s cname %s value %u shift %d item %ld\n", __func__,
2022 widget->name, ucontrol->id.name, widget->value, widget->shift,
2023 ucontrol->value.integer.value[0]);
2024
2025 widget->value = ucontrol->value.enumerated.item[0];
2026
2027 mutex_lock(&codec->mutex);
2028
2029 if (taiko_p->intf_type != WCD9XXX_INTERFACE_TYPE_SLIMBUS) {
Venkat Sudhir994193b2012-12-17 17:30:51 -08002030 if (widget->value > 2) {
Kuirong Wang906ac472012-07-09 12:54:44 -07002031 dev_err(codec->dev, "%s: invalid AIF for I2C mode\n",
2032 __func__);
Kuirong Wangdcc392e2012-10-19 00:33:38 -07002033 goto err;
Kuirong Wang906ac472012-07-09 12:54:44 -07002034 }
2035 }
2036 /* value need to match the Virtual port and AIF number
2037 */
2038 switch (widget->value) {
2039 case 0:
2040 list_del_init(&core->rx_chs[port_id].list);
2041 break;
2042 case 1:
Kuirong Wangdcc392e2012-10-19 00:33:38 -07002043 if (wcd9xxx_rx_vport_validation(port_id + core->num_tx_port,
2044 &taiko_p->dai[AIF1_PB].wcd9xxx_ch_list))
2045 goto pr_err;
Kuirong Wang906ac472012-07-09 12:54:44 -07002046 list_add_tail(&core->rx_chs[port_id].list,
2047 &taiko_p->dai[AIF1_PB].wcd9xxx_ch_list);
2048 break;
2049 case 2:
Kuirong Wangdcc392e2012-10-19 00:33:38 -07002050 if (wcd9xxx_rx_vport_validation(port_id + core->num_tx_port,
Gopikrishnaiah Anandana8aec1f2013-01-23 14:26:27 -05002051 &taiko_p->dai[AIF2_PB].wcd9xxx_ch_list))
Kuirong Wangdcc392e2012-10-19 00:33:38 -07002052 goto pr_err;
Kuirong Wang906ac472012-07-09 12:54:44 -07002053 list_add_tail(&core->rx_chs[port_id].list,
2054 &taiko_p->dai[AIF2_PB].wcd9xxx_ch_list);
2055 break;
2056 case 3:
Kuirong Wangdcc392e2012-10-19 00:33:38 -07002057 if (wcd9xxx_rx_vport_validation(port_id + core->num_tx_port,
Gopikrishnaiah Anandana8aec1f2013-01-23 14:26:27 -05002058 &taiko_p->dai[AIF3_PB].wcd9xxx_ch_list))
Kuirong Wangdcc392e2012-10-19 00:33:38 -07002059 goto pr_err;
Kuirong Wang906ac472012-07-09 12:54:44 -07002060 list_add_tail(&core->rx_chs[port_id].list,
2061 &taiko_p->dai[AIF3_PB].wcd9xxx_ch_list);
2062 break;
2063 default:
2064 pr_err("Unknown AIF %d\n", widget->value);
Kuirong Wangdcc392e2012-10-19 00:33:38 -07002065 goto err;
Kuirong Wang906ac472012-07-09 12:54:44 -07002066 }
2067
2068 snd_soc_dapm_mux_update_power(widget, kcontrol, 1, widget->value, e);
2069
2070 mutex_unlock(&codec->mutex);
2071 return 0;
Kuirong Wangdcc392e2012-10-19 00:33:38 -07002072pr_err:
2073 pr_err("%s: RX%u is used by current requesting AIF_PB itself\n",
2074 __func__, port_id + 1);
2075err:
2076 mutex_unlock(&codec->mutex);
2077 return -EINVAL;
Kuirong Wang906ac472012-07-09 12:54:44 -07002078}
2079
2080static const struct soc_enum slim_rx_mux_enum =
2081 SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(slim_rx_mux_text), slim_rx_mux_text);
2082
2083static const struct snd_kcontrol_new slim_rx_mux[TAIKO_RX_MAX] = {
2084 SOC_DAPM_ENUM_EXT("SLIM RX1 Mux", slim_rx_mux_enum,
2085 slim_rx_mux_get, slim_rx_mux_put),
2086 SOC_DAPM_ENUM_EXT("SLIM RX2 Mux", slim_rx_mux_enum,
2087 slim_rx_mux_get, slim_rx_mux_put),
2088 SOC_DAPM_ENUM_EXT("SLIM RX3 Mux", slim_rx_mux_enum,
2089 slim_rx_mux_get, slim_rx_mux_put),
2090 SOC_DAPM_ENUM_EXT("SLIM RX4 Mux", slim_rx_mux_enum,
2091 slim_rx_mux_get, slim_rx_mux_put),
2092 SOC_DAPM_ENUM_EXT("SLIM RX5 Mux", slim_rx_mux_enum,
2093 slim_rx_mux_get, slim_rx_mux_put),
2094 SOC_DAPM_ENUM_EXT("SLIM RX6 Mux", slim_rx_mux_enum,
2095 slim_rx_mux_get, slim_rx_mux_put),
2096 SOC_DAPM_ENUM_EXT("SLIM RX7 Mux", slim_rx_mux_enum,
2097 slim_rx_mux_get, slim_rx_mux_put),
2098};
2099
2100static const struct snd_kcontrol_new aif_cap_mixer[] = {
2101 SOC_SINGLE_EXT("SLIM TX1", SND_SOC_NOPM, TAIKO_TX1, 1, 0,
2102 slim_tx_mixer_get, slim_tx_mixer_put),
2103 SOC_SINGLE_EXT("SLIM TX2", SND_SOC_NOPM, TAIKO_TX2, 1, 0,
2104 slim_tx_mixer_get, slim_tx_mixer_put),
2105 SOC_SINGLE_EXT("SLIM TX3", SND_SOC_NOPM, TAIKO_TX3, 1, 0,
2106 slim_tx_mixer_get, slim_tx_mixer_put),
2107 SOC_SINGLE_EXT("SLIM TX4", SND_SOC_NOPM, TAIKO_TX4, 1, 0,
2108 slim_tx_mixer_get, slim_tx_mixer_put),
2109 SOC_SINGLE_EXT("SLIM TX5", SND_SOC_NOPM, TAIKO_TX5, 1, 0,
2110 slim_tx_mixer_get, slim_tx_mixer_put),
2111 SOC_SINGLE_EXT("SLIM TX6", SND_SOC_NOPM, TAIKO_TX6, 1, 0,
2112 slim_tx_mixer_get, slim_tx_mixer_put),
2113 SOC_SINGLE_EXT("SLIM TX7", SND_SOC_NOPM, TAIKO_TX7, 1, 0,
2114 slim_tx_mixer_get, slim_tx_mixer_put),
2115 SOC_SINGLE_EXT("SLIM TX8", SND_SOC_NOPM, TAIKO_TX8, 1, 0,
2116 slim_tx_mixer_get, slim_tx_mixer_put),
2117 SOC_SINGLE_EXT("SLIM TX9", SND_SOC_NOPM, TAIKO_TX9, 1, 0,
2118 slim_tx_mixer_get, slim_tx_mixer_put),
2119 SOC_SINGLE_EXT("SLIM TX10", SND_SOC_NOPM, TAIKO_TX10, 1, 0,
2120 slim_tx_mixer_get, slim_tx_mixer_put),
2121};
2122
Kiran Kandic3b24402012-06-11 00:05:59 -07002123static void taiko_codec_enable_adc_block(struct snd_soc_codec *codec,
2124 int enable)
2125{
2126 struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
2127
2128 pr_debug("%s %d\n", __func__, enable);
2129
2130 if (enable) {
2131 taiko->adc_count++;
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08002132 snd_soc_update_bits(codec, WCD9XXX_A_CDC_CLK_OTHR_CTL,
2133 0x2, 0x2);
Kiran Kandic3b24402012-06-11 00:05:59 -07002134 } else {
2135 taiko->adc_count--;
2136 if (!taiko->adc_count)
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08002137 snd_soc_update_bits(codec, WCD9XXX_A_CDC_CLK_OTHR_CTL,
Kiran Kandic3b24402012-06-11 00:05:59 -07002138 0x2, 0x0);
2139 }
2140}
2141
2142static int taiko_codec_enable_adc(struct snd_soc_dapm_widget *w,
2143 struct snd_kcontrol *kcontrol, int event)
2144{
2145 struct snd_soc_codec *codec = w->codec;
2146 u16 adc_reg;
2147 u8 init_bit_shift;
Joonwoo Park2a9170a2013-03-04 17:05:57 -08002148 struct wcd9xxx *core = dev_get_drvdata(codec->dev->parent);
Kiran Kandic3b24402012-06-11 00:05:59 -07002149
2150 pr_debug("%s %d\n", __func__, event);
2151
Joonwoo Park2a9170a2013-03-04 17:05:57 -08002152 if (TAIKO_IS_1_0(core->version)) {
2153 if (w->reg == TAIKO_A_TX_1_2_EN) {
2154 adc_reg = TAIKO_A_TX_1_2_TEST_CTL;
2155 } else if (w->reg == TAIKO_A_TX_3_4_EN) {
2156 adc_reg = TAIKO_A_TX_3_4_TEST_CTL;
2157 } else if (w->reg == TAIKO_A_TX_5_6_EN) {
2158 adc_reg = TAIKO_A_TX_5_6_TEST_CTL;
2159 } else {
2160 pr_err("%s: Error, invalid adc register\n", __func__);
2161 return -EINVAL;
2162 }
Kiran Kandic3b24402012-06-11 00:05:59 -07002163
Joonwoo Park2a9170a2013-03-04 17:05:57 -08002164 if (w->shift == 3) {
2165 init_bit_shift = 6;
2166 } else if (w->shift == 7) {
2167 init_bit_shift = 7;
2168 } else {
2169 pr_err("%s: Error, invalid init bit postion adc register\n",
2170 __func__);
2171 return -EINVAL;
2172 }
2173 } else {
2174 switch (w->reg) {
2175 case TAIKO_A_CDC_TX_1_GAIN:
2176 adc_reg = TAIKO_A_TX_1_2_TEST_CTL;
2177 init_bit_shift = 7;
2178 break;
2179 case TAIKO_A_CDC_TX_2_GAIN:
2180 adc_reg = TAIKO_A_TX_1_2_TEST_CTL;
2181 init_bit_shift = 6;
2182 break;
2183 case TAIKO_A_CDC_TX_3_GAIN:
2184 adc_reg = TAIKO_A_TX_3_4_TEST_CTL;
2185 init_bit_shift = 7;
2186 break;
2187 case TAIKO_A_CDC_TX_4_GAIN:
2188 adc_reg = TAIKO_A_TX_3_4_TEST_CTL;
2189 init_bit_shift = 6;
2190 break;
2191 case TAIKO_A_CDC_TX_5_GAIN:
2192 adc_reg = TAIKO_A_TX_5_6_TEST_CTL;
2193 init_bit_shift = 7;
2194 break;
2195 case TAIKO_A_CDC_TX_6_GAIN:
2196 adc_reg = TAIKO_A_TX_5_6_TEST_CTL;
2197 init_bit_shift = 6;
2198 break;
2199 default:
2200 pr_err("%s: Error, invalid adc register\n", __func__);
2201 return -EINVAL;
2202 }
Kiran Kandic3b24402012-06-11 00:05:59 -07002203 }
2204
2205 switch (event) {
2206 case SND_SOC_DAPM_PRE_PMU:
2207 taiko_codec_enable_adc_block(codec, 1);
2208 snd_soc_update_bits(codec, adc_reg, 1 << init_bit_shift,
2209 1 << init_bit_shift);
2210 break;
2211 case SND_SOC_DAPM_POST_PMU:
Kiran Kandic3b24402012-06-11 00:05:59 -07002212 snd_soc_update_bits(codec, adc_reg, 1 << init_bit_shift, 0x00);
Kiran Kandic3b24402012-06-11 00:05:59 -07002213 break;
2214 case SND_SOC_DAPM_POST_PMD:
2215 taiko_codec_enable_adc_block(codec, 0);
2216 break;
2217 }
2218 return 0;
2219}
2220
Kiran Kandic3b24402012-06-11 00:05:59 -07002221static int taiko_codec_enable_aux_pga(struct snd_soc_dapm_widget *w,
2222 struct snd_kcontrol *kcontrol, int event)
2223{
2224 struct snd_soc_codec *codec = w->codec;
2225 struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
2226
2227 pr_debug("%s: %d\n", __func__, event);
2228
2229 switch (event) {
2230 case SND_SOC_DAPM_PRE_PMU:
Joonwoo Parka8890262012-10-15 12:04:27 -07002231 WCD9XXX_BCL_LOCK(&taiko->resmgr);
2232 wcd9xxx_resmgr_get_bandgap(&taiko->resmgr,
2233 WCD9XXX_BANDGAP_AUDIO_MODE);
2234 /* AUX PGA requires RCO or MCLK */
2235 wcd9xxx_resmgr_get_clk_block(&taiko->resmgr, WCD9XXX_CLK_RCO);
2236 wcd9xxx_resmgr_enable_rx_bias(&taiko->resmgr, 1);
2237 WCD9XXX_BCL_UNLOCK(&taiko->resmgr);
Kiran Kandic3b24402012-06-11 00:05:59 -07002238 break;
2239
2240 case SND_SOC_DAPM_POST_PMD:
Joonwoo Parka8890262012-10-15 12:04:27 -07002241 WCD9XXX_BCL_LOCK(&taiko->resmgr);
2242 wcd9xxx_resmgr_enable_rx_bias(&taiko->resmgr, 0);
2243 wcd9xxx_resmgr_put_bandgap(&taiko->resmgr,
2244 WCD9XXX_BANDGAP_AUDIO_MODE);
2245 wcd9xxx_resmgr_put_clk_block(&taiko->resmgr, WCD9XXX_CLK_RCO);
2246 WCD9XXX_BCL_UNLOCK(&taiko->resmgr);
Kiran Kandic3b24402012-06-11 00:05:59 -07002247 break;
2248 }
2249 return 0;
2250}
2251
2252static int taiko_codec_enable_lineout(struct snd_soc_dapm_widget *w,
2253 struct snd_kcontrol *kcontrol, int event)
2254{
2255 struct snd_soc_codec *codec = w->codec;
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08002256 struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
Kiran Kandic3b24402012-06-11 00:05:59 -07002257 u16 lineout_gain_reg;
2258
2259 pr_debug("%s %d %s\n", __func__, event, w->name);
2260
2261 switch (w->shift) {
2262 case 0:
2263 lineout_gain_reg = TAIKO_A_RX_LINE_1_GAIN;
2264 break;
2265 case 1:
2266 lineout_gain_reg = TAIKO_A_RX_LINE_2_GAIN;
2267 break;
2268 case 2:
2269 lineout_gain_reg = TAIKO_A_RX_LINE_3_GAIN;
2270 break;
2271 case 3:
2272 lineout_gain_reg = TAIKO_A_RX_LINE_4_GAIN;
2273 break;
2274 default:
2275 pr_err("%s: Error, incorrect lineout register value\n",
2276 __func__);
2277 return -EINVAL;
2278 }
2279
2280 switch (event) {
2281 case SND_SOC_DAPM_PRE_PMU:
2282 snd_soc_update_bits(codec, lineout_gain_reg, 0x40, 0x40);
2283 break;
2284 case SND_SOC_DAPM_POST_PMU:
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08002285 wcd9xxx_clsh_fsm(codec, &taiko->clsh_d,
2286 WCD9XXX_CLSH_STATE_LO,
2287 WCD9XXX_CLSH_REQ_ENABLE,
2288 WCD9XXX_CLSH_EVENT_POST_PA);
2289 pr_debug("%s: sleeping 3 ms after %s PA turn on\n",
Kiran Kandic3b24402012-06-11 00:05:59 -07002290 __func__, w->name);
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08002291 usleep_range(3000, 3000);
Kiran Kandic3b24402012-06-11 00:05:59 -07002292 break;
2293 case SND_SOC_DAPM_POST_PMD:
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08002294 wcd9xxx_clsh_fsm(codec, &taiko->clsh_d,
2295 WCD9XXX_CLSH_STATE_LO,
2296 WCD9XXX_CLSH_REQ_DISABLE,
2297 WCD9XXX_CLSH_EVENT_POST_PA);
Kiran Kandic3b24402012-06-11 00:05:59 -07002298 snd_soc_update_bits(codec, lineout_gain_reg, 0x40, 0x00);
2299 break;
2300 }
2301 return 0;
2302}
2303
Joonwoo Park7680b9f2012-07-13 11:36:48 -07002304static int taiko_codec_enable_spk_pa(struct snd_soc_dapm_widget *w,
2305 struct snd_kcontrol *kcontrol, int event)
2306{
Joonwoo Park125cd4e2012-12-11 15:16:11 -08002307 struct snd_soc_codec *codec = w->codec;
2308 struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
2309
2310 pr_debug("%s: %d %s\n", __func__, event, w->name);
2311 WCD9XXX_BCL_LOCK(&taiko->resmgr);
2312 switch (event) {
2313 case SND_SOC_DAPM_PRE_PMU:
2314 taiko->spkr_pa_widget_on = true;
2315 snd_soc_update_bits(codec, TAIKO_A_SPKR_DRV_EN, 0x80, 0x80);
2316 break;
2317 case SND_SOC_DAPM_POST_PMD:
2318 taiko->spkr_pa_widget_on = false;
2319 snd_soc_update_bits(codec, TAIKO_A_SPKR_DRV_EN, 0x80, 0x00);
2320 break;
2321 }
2322 WCD9XXX_BCL_UNLOCK(&taiko->resmgr);
Joonwoo Park7680b9f2012-07-13 11:36:48 -07002323 return 0;
2324}
Kiran Kandic3b24402012-06-11 00:05:59 -07002325
2326static int taiko_codec_enable_dmic(struct snd_soc_dapm_widget *w,
2327 struct snd_kcontrol *kcontrol, int event)
2328{
2329 struct snd_soc_codec *codec = w->codec;
2330 struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
2331 u8 dmic_clk_en;
2332 u16 dmic_clk_reg;
2333 s32 *dmic_clk_cnt;
2334 unsigned int dmic;
2335 int ret;
2336
2337 ret = kstrtouint(strpbrk(w->name, "123456"), 10, &dmic);
2338 if (ret < 0) {
2339 pr_err("%s: Invalid DMIC line on the codec\n", __func__);
2340 return -EINVAL;
2341 }
2342
2343 switch (dmic) {
2344 case 1:
2345 case 2:
2346 dmic_clk_en = 0x01;
2347 dmic_clk_cnt = &(taiko->dmic_1_2_clk_cnt);
2348 dmic_clk_reg = TAIKO_A_CDC_CLK_DMIC_B1_CTL;
2349 pr_debug("%s() event %d DMIC%d dmic_1_2_clk_cnt %d\n",
2350 __func__, event, dmic, *dmic_clk_cnt);
2351
2352 break;
2353
2354 case 3:
2355 case 4:
2356 dmic_clk_en = 0x10;
2357 dmic_clk_cnt = &(taiko->dmic_3_4_clk_cnt);
2358 dmic_clk_reg = TAIKO_A_CDC_CLK_DMIC_B1_CTL;
2359
2360 pr_debug("%s() event %d DMIC%d dmic_3_4_clk_cnt %d\n",
2361 __func__, event, dmic, *dmic_clk_cnt);
2362 break;
2363
2364 case 5:
2365 case 6:
2366 dmic_clk_en = 0x01;
2367 dmic_clk_cnt = &(taiko->dmic_5_6_clk_cnt);
2368 dmic_clk_reg = TAIKO_A_CDC_CLK_DMIC_B2_CTL;
2369
2370 pr_debug("%s() event %d DMIC%d dmic_5_6_clk_cnt %d\n",
2371 __func__, event, dmic, *dmic_clk_cnt);
2372
2373 break;
2374
2375 default:
2376 pr_err("%s: Invalid DMIC Selection\n", __func__);
2377 return -EINVAL;
2378 }
2379
2380 switch (event) {
2381 case SND_SOC_DAPM_PRE_PMU:
2382
2383 (*dmic_clk_cnt)++;
2384 if (*dmic_clk_cnt == 1)
2385 snd_soc_update_bits(codec, dmic_clk_reg,
2386 dmic_clk_en, dmic_clk_en);
2387
2388 break;
2389 case SND_SOC_DAPM_POST_PMD:
2390
2391 (*dmic_clk_cnt)--;
2392 if (*dmic_clk_cnt == 0)
2393 snd_soc_update_bits(codec, dmic_clk_reg,
2394 dmic_clk_en, 0);
2395 break;
2396 }
2397 return 0;
2398}
2399
Joonwoo Park1d05bb92013-03-07 16:55:06 -08002400static int taiko_codec_config_mad(struct snd_soc_codec *codec)
2401{
2402 int ret;
2403 const struct firmware *fw;
2404 struct mad_audio_cal *mad_cal;
2405 const char *filename = TAIKO_MAD_AUDIO_FIRMWARE_PATH;
2406
2407 pr_debug("%s: enter\n", __func__);
2408 ret = request_firmware(&fw, filename, codec->dev);
2409 if (ret != 0) {
2410 pr_err("Failed to acquire MAD firwmare data %s: %d\n", filename,
2411 ret);
2412 return -ENODEV;
2413 }
2414
2415 if (fw->size < sizeof(struct mad_audio_cal)) {
2416 pr_err("%s: incorrect firmware size %u\n", __func__, fw->size);
2417 release_firmware(fw);
2418 return -ENOMEM;
2419 }
2420
2421 mad_cal = (struct mad_audio_cal *)(fw->data);
2422 if (!mad_cal) {
2423 pr_err("%s: Invalid calibration data\n", __func__);
2424 release_firmware(fw);
2425 return -EINVAL;
2426 }
2427
2428 snd_soc_update_bits(codec, TAIKO_A_CDC_CONN_MAD,
2429 0x0F, mad_cal->microphone_info.input_microphone);
2430 snd_soc_write(codec, TAIKO_A_CDC_MAD_MAIN_CTL_2,
2431 mad_cal->microphone_info.cycle_time);
2432 snd_soc_update_bits(codec, TAIKO_A_CDC_MAD_MAIN_CTL_1, 0xFF << 3,
2433 ((uint16_t)mad_cal->microphone_info.settle_time)
2434 << 3);
2435
2436 /* Audio */
2437 snd_soc_write(codec, TAIKO_A_CDC_MAD_AUDIO_CTL_8,
2438 mad_cal->audio_info.rms_omit_samples);
2439 snd_soc_update_bits(codec, TAIKO_A_CDC_MAD_AUDIO_CTL_1,
2440 0x07 << 4, mad_cal->audio_info.rms_comp_time << 4);
2441 snd_soc_update_bits(codec, TAIKO_A_CDC_MAD_AUDIO_CTL_2, 0x03 << 2,
2442 mad_cal->audio_info.detection_mechanism << 2);
2443 snd_soc_write(codec, TAIKO_A_CDC_MAD_AUDIO_CTL_7,
2444 mad_cal->audio_info.rms_diff_threshold & 0x3F);
2445 snd_soc_write(codec, TAIKO_A_CDC_MAD_AUDIO_CTL_5,
2446 mad_cal->audio_info.rms_threshold_lsb);
2447 snd_soc_write(codec, TAIKO_A_CDC_MAD_AUDIO_CTL_6,
2448 mad_cal->audio_info.rms_threshold_msb);
2449
2450
2451 /* Beacon */
2452 snd_soc_write(codec, TAIKO_A_CDC_MAD_BEACON_CTL_8,
2453 mad_cal->beacon_info.rms_omit_samples);
2454 snd_soc_update_bits(codec, TAIKO_A_CDC_MAD_BEACON_CTL_1,
2455 0x07 << 4, mad_cal->beacon_info.rms_comp_time);
2456 snd_soc_update_bits(codec, TAIKO_A_CDC_MAD_BEACON_CTL_2, 0x03 << 2,
2457 mad_cal->beacon_info.detection_mechanism << 2);
2458 snd_soc_write(codec, TAIKO_A_CDC_MAD_BEACON_CTL_7,
2459 mad_cal->beacon_info.rms_diff_threshold & 0x1F);
2460 snd_soc_write(codec, TAIKO_A_CDC_MAD_BEACON_CTL_5,
2461 mad_cal->beacon_info.rms_threshold_lsb);
2462 snd_soc_write(codec, TAIKO_A_CDC_MAD_BEACON_CTL_6,
2463 mad_cal->beacon_info.rms_threshold_msb);
2464
2465 /* Ultrasound */
2466 snd_soc_update_bits(codec, TAIKO_A_CDC_MAD_BEACON_CTL_1,
2467 0x07 << 4, mad_cal->beacon_info.rms_comp_time);
2468 snd_soc_update_bits(codec, TAIKO_A_CDC_MAD_ULTR_CTL_2, 0x03 << 2,
2469 mad_cal->ultrasound_info.detection_mechanism);
2470 snd_soc_write(codec, TAIKO_A_CDC_MAD_ULTR_CTL_7,
2471 mad_cal->ultrasound_info.rms_diff_threshold & 0x1F);
2472 snd_soc_write(codec, TAIKO_A_CDC_MAD_ULTR_CTL_5,
2473 mad_cal->ultrasound_info.rms_threshold_lsb);
2474 snd_soc_write(codec, TAIKO_A_CDC_MAD_ULTR_CTL_6,
2475 mad_cal->ultrasound_info.rms_threshold_msb);
2476
2477 release_firmware(fw);
2478 pr_debug("%s: leave ret %d\n", __func__, ret);
2479
2480 return ret;
2481}
2482
2483static int taiko_codec_enable_mad(struct snd_soc_dapm_widget *w,
2484 struct snd_kcontrol *kcontrol, int event)
2485{
2486 struct snd_soc_codec *codec = w->codec;
2487 int ret = 0;
2488
2489 pr_debug("%s %d\n", __func__, event);
2490 switch (event) {
2491 case SND_SOC_DAPM_PRE_PMU:
2492 ret = taiko_codec_config_mad(codec);
2493 if (ret) {
2494 pr_err("%s: Failed to config MAD\n", __func__);
2495 break;
2496 }
2497 break;
2498 }
2499 return ret;
2500}
2501
Kiran Kandic3b24402012-06-11 00:05:59 -07002502static int taiko_codec_enable_micbias(struct snd_soc_dapm_widget *w,
2503 struct snd_kcontrol *kcontrol, int event)
2504{
2505 struct snd_soc_codec *codec = w->codec;
2506 struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
Joonwoo Park3699ca32013-02-08 12:06:15 -08002507 u16 micb_int_reg = 0, micb_ctl_reg = 0;
Kiran Kandic3b24402012-06-11 00:05:59 -07002508 u8 cfilt_sel_val = 0;
2509 char *internal1_text = "Internal1";
2510 char *internal2_text = "Internal2";
2511 char *internal3_text = "Internal3";
Joonwoo Parka8890262012-10-15 12:04:27 -07002512 enum wcd9xxx_notify_event e_post_off, e_pre_on, e_post_on;
Kiran Kandic3b24402012-06-11 00:05:59 -07002513
Joonwoo Park3699ca32013-02-08 12:06:15 -08002514 pr_debug("%s: w->name %s event %d\n", __func__, w->name, event);
2515 if (strnstr(w->name, "MIC BIAS1", sizeof("MIC BIAS1"))) {
2516 micb_ctl_reg = TAIKO_A_MICB_1_CTL;
Kiran Kandic3b24402012-06-11 00:05:59 -07002517 micb_int_reg = TAIKO_A_MICB_1_INT_RBIAS;
Joonwoo Parka8890262012-10-15 12:04:27 -07002518 cfilt_sel_val = taiko->resmgr.pdata->micbias.bias1_cfilt_sel;
2519 e_pre_on = WCD9XXX_EVENT_PRE_MICBIAS_1_ON;
2520 e_post_on = WCD9XXX_EVENT_POST_MICBIAS_1_ON;
2521 e_post_off = WCD9XXX_EVENT_POST_MICBIAS_1_OFF;
Joonwoo Park3699ca32013-02-08 12:06:15 -08002522 } else if (strnstr(w->name, "MIC BIAS2", sizeof("MIC BIAS2"))) {
2523 micb_ctl_reg = TAIKO_A_MICB_2_CTL;
Kiran Kandic3b24402012-06-11 00:05:59 -07002524 micb_int_reg = TAIKO_A_MICB_2_INT_RBIAS;
Joonwoo Parka8890262012-10-15 12:04:27 -07002525 cfilt_sel_val = taiko->resmgr.pdata->micbias.bias2_cfilt_sel;
2526 e_pre_on = WCD9XXX_EVENT_PRE_MICBIAS_2_ON;
2527 e_post_on = WCD9XXX_EVENT_POST_MICBIAS_2_ON;
2528 e_post_off = WCD9XXX_EVENT_POST_MICBIAS_2_OFF;
Joonwoo Park3699ca32013-02-08 12:06:15 -08002529 } else if (strnstr(w->name, "MIC BIAS3", sizeof("MIC BIAS3"))) {
Damir Didjusto6e4f9d22013-03-07 10:10:57 -08002530 micb_ctl_reg = TAIKO_A_MICB_3_CTL;
Kiran Kandic3b24402012-06-11 00:05:59 -07002531 micb_int_reg = TAIKO_A_MICB_3_INT_RBIAS;
Joonwoo Parka8890262012-10-15 12:04:27 -07002532 cfilt_sel_val = taiko->resmgr.pdata->micbias.bias3_cfilt_sel;
2533 e_pre_on = WCD9XXX_EVENT_PRE_MICBIAS_3_ON;
2534 e_post_on = WCD9XXX_EVENT_POST_MICBIAS_3_ON;
2535 e_post_off = WCD9XXX_EVENT_POST_MICBIAS_3_OFF;
Joonwoo Park3699ca32013-02-08 12:06:15 -08002536 } else if (strnstr(w->name, "MIC BIAS4", sizeof("MIC BIAS4"))) {
Damir Didjusto6e4f9d22013-03-07 10:10:57 -08002537 micb_ctl_reg = TAIKO_A_MICB_4_CTL;
Joonwoo Parka8890262012-10-15 12:04:27 -07002538 micb_int_reg = taiko->resmgr.reg_addr->micb_4_int_rbias;
2539 cfilt_sel_val = taiko->resmgr.pdata->micbias.bias4_cfilt_sel;
2540 e_pre_on = WCD9XXX_EVENT_PRE_MICBIAS_4_ON;
2541 e_post_on = WCD9XXX_EVENT_POST_MICBIAS_4_ON;
2542 e_post_off = WCD9XXX_EVENT_POST_MICBIAS_4_OFF;
Joonwoo Park3699ca32013-02-08 12:06:15 -08002543 } else {
2544 pr_err("%s: Error, invalid micbias %s\n", __func__, w->name);
Kiran Kandic3b24402012-06-11 00:05:59 -07002545 return -EINVAL;
2546 }
2547
2548 switch (event) {
2549 case SND_SOC_DAPM_PRE_PMU:
Joonwoo Parka8890262012-10-15 12:04:27 -07002550 /* Let MBHC module know so micbias switch to be off */
2551 wcd9xxx_resmgr_notifier_call(&taiko->resmgr, e_pre_on);
Kiran Kandic3b24402012-06-11 00:05:59 -07002552
Joonwoo Parka8890262012-10-15 12:04:27 -07002553 /* Get cfilt */
2554 wcd9xxx_resmgr_cfilt_get(&taiko->resmgr, cfilt_sel_val);
Kiran Kandic3b24402012-06-11 00:05:59 -07002555
2556 if (strnstr(w->name, internal1_text, 30))
2557 snd_soc_update_bits(codec, micb_int_reg, 0xE0, 0xE0);
2558 else if (strnstr(w->name, internal2_text, 30))
2559 snd_soc_update_bits(codec, micb_int_reg, 0x1C, 0x1C);
2560 else if (strnstr(w->name, internal3_text, 30))
2561 snd_soc_update_bits(codec, micb_int_reg, 0x3, 0x3);
2562
Joonwoo Park3edb9892013-03-05 17:44:54 -08002563 if (micb_ctl_reg == TAIKO_A_MICB_2_CTL)
Joonwoo Park3699ca32013-02-08 12:06:15 -08002564 wcd9xxx_resmgr_add_cond_update_bits(&taiko->resmgr,
2565 WCD9XXX_COND_HPH_MIC,
2566 micb_ctl_reg, w->shift,
2567 false);
Joonwoo Park3edb9892013-03-05 17:44:54 -08002568 else
Joonwoo Park3699ca32013-02-08 12:06:15 -08002569 snd_soc_update_bits(codec, micb_ctl_reg, 1 << w->shift,
2570 1 << w->shift);
Kiran Kandic3b24402012-06-11 00:05:59 -07002571 break;
2572 case SND_SOC_DAPM_POST_PMU:
Kiran Kandic3b24402012-06-11 00:05:59 -07002573 usleep_range(20000, 20000);
Joonwoo Parka8890262012-10-15 12:04:27 -07002574 /* Let MBHC module know so micbias is on */
2575 wcd9xxx_resmgr_notifier_call(&taiko->resmgr, e_post_on);
Kiran Kandic3b24402012-06-11 00:05:59 -07002576 break;
Kiran Kandic3b24402012-06-11 00:05:59 -07002577 case SND_SOC_DAPM_POST_PMD:
Joonwoo Park3edb9892013-03-05 17:44:54 -08002578 if (micb_ctl_reg == TAIKO_A_MICB_2_CTL)
Joonwoo Park3699ca32013-02-08 12:06:15 -08002579 wcd9xxx_resmgr_rm_cond_update_bits(&taiko->resmgr,
2580 WCD9XXX_COND_HPH_MIC,
2581 micb_ctl_reg, 7, false);
Joonwoo Park3edb9892013-03-05 17:44:54 -08002582 else
Joonwoo Park3699ca32013-02-08 12:06:15 -08002583 snd_soc_update_bits(codec, micb_ctl_reg, 1 << w->shift,
2584 0);
2585
Joonwoo Parka8890262012-10-15 12:04:27 -07002586 /* Let MBHC module know so micbias switch to be off */
2587 wcd9xxx_resmgr_notifier_call(&taiko->resmgr, e_post_off);
Kiran Kandic3b24402012-06-11 00:05:59 -07002588
2589 if (strnstr(w->name, internal1_text, 30))
2590 snd_soc_update_bits(codec, micb_int_reg, 0x80, 0x00);
2591 else if (strnstr(w->name, internal2_text, 30))
2592 snd_soc_update_bits(codec, micb_int_reg, 0x10, 0x00);
2593 else if (strnstr(w->name, internal3_text, 30))
2594 snd_soc_update_bits(codec, micb_int_reg, 0x2, 0x0);
2595
Joonwoo Parka8890262012-10-15 12:04:27 -07002596 /* Put cfilt */
2597 wcd9xxx_resmgr_cfilt_put(&taiko->resmgr, cfilt_sel_val);
Kiran Kandic3b24402012-06-11 00:05:59 -07002598 break;
2599 }
2600
2601 return 0;
2602}
2603
2604
2605static void tx_hpf_corner_freq_callback(struct work_struct *work)
2606{
2607 struct delayed_work *hpf_delayed_work;
2608 struct hpf_work *hpf_work;
2609 struct taiko_priv *taiko;
2610 struct snd_soc_codec *codec;
2611 u16 tx_mux_ctl_reg;
2612 u8 hpf_cut_of_freq;
2613
2614 hpf_delayed_work = to_delayed_work(work);
2615 hpf_work = container_of(hpf_delayed_work, struct hpf_work, dwork);
2616 taiko = hpf_work->taiko;
2617 codec = hpf_work->taiko->codec;
2618 hpf_cut_of_freq = hpf_work->tx_hpf_cut_of_freq;
2619
2620 tx_mux_ctl_reg = TAIKO_A_CDC_TX1_MUX_CTL +
2621 (hpf_work->decimator - 1) * 8;
2622
2623 pr_debug("%s(): decimator %u hpf_cut_of_freq 0x%x\n", __func__,
2624 hpf_work->decimator, (unsigned int)hpf_cut_of_freq);
2625
2626 snd_soc_update_bits(codec, tx_mux_ctl_reg, 0x30, hpf_cut_of_freq << 4);
2627}
2628
2629#define TX_MUX_CTL_CUT_OFF_FREQ_MASK 0x30
2630#define CF_MIN_3DB_4HZ 0x0
2631#define CF_MIN_3DB_75HZ 0x1
2632#define CF_MIN_3DB_150HZ 0x2
2633
2634static int taiko_codec_enable_dec(struct snd_soc_dapm_widget *w,
2635 struct snd_kcontrol *kcontrol, int event)
2636{
2637 struct snd_soc_codec *codec = w->codec;
2638 unsigned int decimator;
2639 char *dec_name = NULL;
2640 char *widget_name = NULL;
2641 char *temp;
2642 int ret = 0;
2643 u16 dec_reset_reg, tx_vol_ctl_reg, tx_mux_ctl_reg;
2644 u8 dec_hpf_cut_of_freq;
2645 int offset;
2646
2647
2648 pr_debug("%s %d\n", __func__, event);
2649
2650 widget_name = kstrndup(w->name, 15, GFP_KERNEL);
2651 if (!widget_name)
2652 return -ENOMEM;
2653 temp = widget_name;
2654
2655 dec_name = strsep(&widget_name, " ");
2656 widget_name = temp;
2657 if (!dec_name) {
2658 pr_err("%s: Invalid decimator = %s\n", __func__, w->name);
2659 ret = -EINVAL;
2660 goto out;
2661 }
2662
2663 ret = kstrtouint(strpbrk(dec_name, "123456789"), 10, &decimator);
2664 if (ret < 0) {
2665 pr_err("%s: Invalid decimator = %s\n", __func__, dec_name);
2666 ret = -EINVAL;
2667 goto out;
2668 }
2669
2670 pr_debug("%s(): widget = %s dec_name = %s decimator = %u\n", __func__,
2671 w->name, dec_name, decimator);
2672
2673 if (w->reg == TAIKO_A_CDC_CLK_TX_CLK_EN_B1_CTL) {
2674 dec_reset_reg = TAIKO_A_CDC_CLK_TX_RESET_B1_CTL;
2675 offset = 0;
2676 } else if (w->reg == TAIKO_A_CDC_CLK_TX_CLK_EN_B2_CTL) {
2677 dec_reset_reg = TAIKO_A_CDC_CLK_TX_RESET_B2_CTL;
2678 offset = 8;
2679 } else {
2680 pr_err("%s: Error, incorrect dec\n", __func__);
2681 return -EINVAL;
2682 }
2683
2684 tx_vol_ctl_reg = TAIKO_A_CDC_TX1_VOL_CTL_CFG + 8 * (decimator - 1);
2685 tx_mux_ctl_reg = TAIKO_A_CDC_TX1_MUX_CTL + 8 * (decimator - 1);
2686
2687 switch (event) {
2688 case SND_SOC_DAPM_PRE_PMU:
2689
2690 /* Enableable TX digital mute */
2691 snd_soc_update_bits(codec, tx_vol_ctl_reg, 0x01, 0x01);
2692
2693 snd_soc_update_bits(codec, dec_reset_reg, 1 << w->shift,
2694 1 << w->shift);
2695 snd_soc_update_bits(codec, dec_reset_reg, 1 << w->shift, 0x0);
2696
2697 dec_hpf_cut_of_freq = snd_soc_read(codec, tx_mux_ctl_reg);
2698
2699 dec_hpf_cut_of_freq = (dec_hpf_cut_of_freq & 0x30) >> 4;
2700
2701 tx_hpf_work[decimator - 1].tx_hpf_cut_of_freq =
2702 dec_hpf_cut_of_freq;
2703
2704 if ((dec_hpf_cut_of_freq != CF_MIN_3DB_150HZ)) {
2705
2706 /* set cut of freq to CF_MIN_3DB_150HZ (0x1); */
2707 snd_soc_update_bits(codec, tx_mux_ctl_reg, 0x30,
2708 CF_MIN_3DB_150HZ << 4);
2709 }
2710
2711 /* enable HPF */
2712 snd_soc_update_bits(codec, tx_mux_ctl_reg , 0x08, 0x00);
2713
2714 break;
2715
2716 case SND_SOC_DAPM_POST_PMU:
2717
2718 /* Disable TX digital mute */
2719 snd_soc_update_bits(codec, tx_vol_ctl_reg, 0x01, 0x00);
2720
2721 if (tx_hpf_work[decimator - 1].tx_hpf_cut_of_freq !=
2722 CF_MIN_3DB_150HZ) {
2723
2724 schedule_delayed_work(&tx_hpf_work[decimator - 1].dwork,
2725 msecs_to_jiffies(300));
2726 }
2727 /* apply the digital gain after the decimator is enabled*/
Damir Didjustoed406e22012-11-16 15:44:57 -08002728 if ((w->shift + offset) < ARRAY_SIZE(tx_digital_gain_reg))
Kiran Kandic3b24402012-06-11 00:05:59 -07002729 snd_soc_write(codec,
2730 tx_digital_gain_reg[w->shift + offset],
2731 snd_soc_read(codec,
2732 tx_digital_gain_reg[w->shift + offset])
2733 );
2734
2735 break;
2736
2737 case SND_SOC_DAPM_PRE_PMD:
2738
2739 snd_soc_update_bits(codec, tx_vol_ctl_reg, 0x01, 0x01);
2740 cancel_delayed_work_sync(&tx_hpf_work[decimator - 1].dwork);
2741 break;
2742
2743 case SND_SOC_DAPM_POST_PMD:
2744
2745 snd_soc_update_bits(codec, tx_mux_ctl_reg, 0x08, 0x08);
2746 snd_soc_update_bits(codec, tx_mux_ctl_reg, 0x30,
2747 (tx_hpf_work[decimator - 1].tx_hpf_cut_of_freq) << 4);
2748
2749 break;
2750 }
2751out:
2752 kfree(widget_name);
2753 return ret;
2754}
2755
Joonwoo Park125cd4e2012-12-11 15:16:11 -08002756static int taiko_codec_enable_vdd_spkr(struct snd_soc_dapm_widget *w,
2757 struct snd_kcontrol *kcontrol, int event)
2758{
2759 int ret = 0;
2760 struct snd_soc_codec *codec = w->codec;
2761 struct wcd9xxx *core = dev_get_drvdata(codec->dev->parent);
Joonwoo Park448a8fc2013-04-10 15:25:58 -07002762 struct taiko_priv *priv = snd_soc_codec_get_drvdata(codec);
Joonwoo Park125cd4e2012-12-11 15:16:11 -08002763
2764 pr_debug("%s: %d %s\n", __func__, event, w->name);
Joonwoo Park448a8fc2013-04-10 15:25:58 -07002765
2766 WARN_ONCE(!priv->spkdrv_reg, "SPKDRV supply %s isn't defined\n",
2767 WCD9XXX_VDD_SPKDRV_NAME);
Joonwoo Park125cd4e2012-12-11 15:16:11 -08002768 switch (event) {
2769 case SND_SOC_DAPM_PRE_PMU:
Joonwoo Park448a8fc2013-04-10 15:25:58 -07002770 if (priv->spkdrv_reg) {
2771 ret = regulator_enable(priv->spkdrv_reg);
2772 if (ret)
2773 pr_err("%s: Failed to enable spkdrv_reg %s\n",
2774 __func__, WCD9XXX_VDD_SPKDRV_NAME);
2775 }
Joonwoo Park125cd4e2012-12-11 15:16:11 -08002776 if (spkr_drv_wrnd > 0) {
2777 WARN_ON(!(snd_soc_read(codec, TAIKO_A_SPKR_DRV_EN) &
2778 0x80));
2779 snd_soc_update_bits(codec, TAIKO_A_SPKR_DRV_EN, 0x80,
2780 0x00);
2781 }
2782 if (TAIKO_IS_1_0(core->version))
2783 snd_soc_update_bits(codec, TAIKO_A_SPKR_DRV_DBG_PWRSTG,
2784 0x24, 0x00);
2785 break;
2786 case SND_SOC_DAPM_POST_PMD:
2787 if (TAIKO_IS_1_0(core->version))
2788 snd_soc_update_bits(codec, TAIKO_A_SPKR_DRV_DBG_PWRSTG,
2789 0x24, 0x24);
2790 if (spkr_drv_wrnd > 0) {
2791 WARN_ON(!!(snd_soc_read(codec, TAIKO_A_SPKR_DRV_EN) &
2792 0x80));
2793 snd_soc_update_bits(codec, TAIKO_A_SPKR_DRV_EN, 0x80,
2794 0x80);
2795 }
Joonwoo Park448a8fc2013-04-10 15:25:58 -07002796 if (priv->spkdrv_reg) {
2797 ret = regulator_disable(priv->spkdrv_reg);
2798 if (ret)
2799 pr_err("%s: Failed to disable spkdrv_reg %s\n",
2800 __func__, WCD9XXX_VDD_SPKDRV_NAME);
2801 }
Joonwoo Park125cd4e2012-12-11 15:16:11 -08002802 break;
2803 }
2804
2805 return ret;
2806}
2807
Kiran Kandi7b7d2ff2012-09-14 14:52:14 -07002808static int taiko_codec_enable_interpolator(struct snd_soc_dapm_widget *w,
Kiran Kandic3b24402012-06-11 00:05:59 -07002809 struct snd_kcontrol *kcontrol, int event)
2810{
2811 struct snd_soc_codec *codec = w->codec;
2812
2813 pr_debug("%s %d %s\n", __func__, event, w->name);
2814
2815 switch (event) {
2816 case SND_SOC_DAPM_PRE_PMU:
2817 snd_soc_update_bits(codec, TAIKO_A_CDC_CLK_RX_RESET_CTL,
2818 1 << w->shift, 1 << w->shift);
2819 snd_soc_update_bits(codec, TAIKO_A_CDC_CLK_RX_RESET_CTL,
2820 1 << w->shift, 0x0);
2821 break;
2822 case SND_SOC_DAPM_POST_PMU:
2823 /* apply the digital gain after the interpolator is enabled*/
2824 if ((w->shift) < ARRAY_SIZE(rx_digital_gain_reg))
2825 snd_soc_write(codec,
2826 rx_digital_gain_reg[w->shift],
2827 snd_soc_read(codec,
2828 rx_digital_gain_reg[w->shift])
2829 );
2830 break;
2831 }
2832 return 0;
2833}
2834
2835static int taiko_codec_enable_ldo_h(struct snd_soc_dapm_widget *w,
2836 struct snd_kcontrol *kcontrol, int event)
2837{
2838 switch (event) {
2839 case SND_SOC_DAPM_POST_PMU:
2840 case SND_SOC_DAPM_POST_PMD:
2841 usleep_range(1000, 1000);
2842 break;
2843 }
2844 return 0;
2845}
2846
2847static int taiko_codec_enable_rx_bias(struct snd_soc_dapm_widget *w,
2848 struct snd_kcontrol *kcontrol, int event)
2849{
2850 struct snd_soc_codec *codec = w->codec;
Joonwoo Parka8890262012-10-15 12:04:27 -07002851 struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
Kiran Kandic3b24402012-06-11 00:05:59 -07002852
2853 pr_debug("%s %d\n", __func__, event);
2854
2855 switch (event) {
2856 case SND_SOC_DAPM_PRE_PMU:
Joonwoo Parka8890262012-10-15 12:04:27 -07002857 wcd9xxx_resmgr_enable_rx_bias(&taiko->resmgr, 1);
Kiran Kandic3b24402012-06-11 00:05:59 -07002858 break;
2859 case SND_SOC_DAPM_POST_PMD:
Joonwoo Parka8890262012-10-15 12:04:27 -07002860 wcd9xxx_resmgr_enable_rx_bias(&taiko->resmgr, 0);
Kiran Kandic3b24402012-06-11 00:05:59 -07002861 break;
2862 }
2863 return 0;
2864}
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08002865
2866static int taiko_hphl_dac_event(struct snd_soc_dapm_widget *w,
Kiran Kandic3b24402012-06-11 00:05:59 -07002867 struct snd_kcontrol *kcontrol, int event)
2868{
2869 struct snd_soc_codec *codec = w->codec;
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08002870 struct taiko_priv *taiko_p = snd_soc_codec_get_drvdata(codec);
Kiran Kandic3b24402012-06-11 00:05:59 -07002871
2872 pr_debug("%s %s %d\n", __func__, w->name, event);
2873
2874 switch (event) {
2875 case SND_SOC_DAPM_PRE_PMU:
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08002876 snd_soc_update_bits(codec, TAIKO_A_CDC_CLK_RDAC_CLK_EN_CTL,
2877 0x02, 0x02);
2878 wcd9xxx_clsh_fsm(codec, &taiko_p->clsh_d,
2879 WCD9XXX_CLSH_STATE_HPHL,
2880 WCD9XXX_CLSH_REQ_ENABLE,
2881 WCD9XXX_CLSH_EVENT_PRE_DAC);
Kiran Kandic3b24402012-06-11 00:05:59 -07002882 break;
2883 case SND_SOC_DAPM_POST_PMD:
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08002884 snd_soc_update_bits(codec, TAIKO_A_CDC_CLK_RDAC_CLK_EN_CTL,
2885 0x02, 0x00);
2886 }
2887 return 0;
2888}
2889
2890static int taiko_hphr_dac_event(struct snd_soc_dapm_widget *w,
2891 struct snd_kcontrol *kcontrol, int event)
2892{
2893 struct snd_soc_codec *codec = w->codec;
2894 struct taiko_priv *taiko_p = snd_soc_codec_get_drvdata(codec);
2895
2896 pr_debug("%s %s %d\n", __func__, w->name, event);
2897
2898 switch (event) {
2899 case SND_SOC_DAPM_PRE_PMU:
2900 snd_soc_update_bits(codec, TAIKO_A_CDC_CLK_RDAC_CLK_EN_CTL,
2901 0x04, 0x04);
2902 snd_soc_update_bits(codec, w->reg, 0x40, 0x40);
2903 wcd9xxx_clsh_fsm(codec, &taiko_p->clsh_d,
2904 WCD9XXX_CLSH_STATE_HPHR,
2905 WCD9XXX_CLSH_REQ_ENABLE,
2906 WCD9XXX_CLSH_EVENT_PRE_DAC);
2907 break;
2908 case SND_SOC_DAPM_POST_PMD:
2909 snd_soc_update_bits(codec, TAIKO_A_CDC_CLK_RDAC_CLK_EN_CTL,
2910 0x04, 0x00);
Kiran Kandic3b24402012-06-11 00:05:59 -07002911 snd_soc_update_bits(codec, w->reg, 0x40, 0x00);
2912 break;
2913 }
2914 return 0;
2915}
2916
Damir Didjusto2cb06bd2013-01-30 23:14:55 -08002917static int taiko_codec_enable_anc(struct snd_soc_dapm_widget *w,
2918 struct snd_kcontrol *kcontrol, int event)
2919{
2920 struct snd_soc_codec *codec = w->codec;
2921 const char *filename;
2922 const struct firmware *fw;
2923 int i;
2924 int ret;
2925 int num_anc_slots;
Simmi Pateriyadf675e92013-04-05 01:15:54 +05302926 struct wcd9xxx_anc_header *anc_head;
Damir Didjusto2cb06bd2013-01-30 23:14:55 -08002927 struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
2928 u32 anc_writes_size = 0;
2929 int anc_size_remaining;
2930 u32 *anc_ptr;
2931 u16 reg;
2932 u8 mask, val, old_val;
2933
2934
2935 if (taiko->anc_func == 0)
2936 return 0;
2937
2938 switch (event) {
2939 case SND_SOC_DAPM_PRE_PMU:
2940 filename = "wcd9320/wcd9320_anc.bin";
2941
2942 ret = request_firmware(&fw, filename, codec->dev);
2943 if (ret != 0) {
2944 dev_err(codec->dev, "Failed to acquire ANC data: %d\n",
2945 ret);
2946 return -ENODEV;
2947 }
2948
Simmi Pateriyadf675e92013-04-05 01:15:54 +05302949 if (fw->size < sizeof(struct wcd9xxx_anc_header)) {
Damir Didjusto2cb06bd2013-01-30 23:14:55 -08002950 dev_err(codec->dev, "Not enough data\n");
2951 release_firmware(fw);
2952 return -ENOMEM;
2953 }
2954
2955 /* First number is the number of register writes */
Simmi Pateriyadf675e92013-04-05 01:15:54 +05302956 anc_head = (struct wcd9xxx_anc_header *)(fw->data);
2957 anc_ptr = (u32 *)((u32)fw->data +
2958 sizeof(struct wcd9xxx_anc_header));
2959 anc_size_remaining = fw->size -
2960 sizeof(struct wcd9xxx_anc_header);
Damir Didjusto2cb06bd2013-01-30 23:14:55 -08002961 num_anc_slots = anc_head->num_anc_slots;
2962
2963 if (taiko->anc_slot >= num_anc_slots) {
2964 dev_err(codec->dev, "Invalid ANC slot selected\n");
2965 release_firmware(fw);
2966 return -EINVAL;
2967 }
2968 for (i = 0; i < num_anc_slots; i++) {
2969 if (anc_size_remaining < TAIKO_PACKED_REG_SIZE) {
2970 dev_err(codec->dev, "Invalid register format\n");
2971 release_firmware(fw);
2972 return -EINVAL;
2973 }
2974 anc_writes_size = (u32)(*anc_ptr);
2975 anc_size_remaining -= sizeof(u32);
2976 anc_ptr += 1;
2977
2978 if (anc_writes_size * TAIKO_PACKED_REG_SIZE
2979 > anc_size_remaining) {
2980 dev_err(codec->dev, "Invalid register format\n");
2981 release_firmware(fw);
2982 return -ENOMEM;
2983 }
2984
2985 if (taiko->anc_slot == i)
2986 break;
2987
2988 anc_size_remaining -= (anc_writes_size *
2989 TAIKO_PACKED_REG_SIZE);
2990 anc_ptr += anc_writes_size;
2991 }
2992 if (i == num_anc_slots) {
2993 dev_err(codec->dev, "Selected ANC slot not present\n");
2994 release_firmware(fw);
2995 return -ENOMEM;
2996 }
2997 for (i = 0; i < anc_writes_size; i++) {
2998 TAIKO_CODEC_UNPACK_ENTRY(anc_ptr[i], reg,
2999 mask, val);
3000 old_val = snd_soc_read(codec, reg);
3001 snd_soc_write(codec, reg, (old_val & ~mask) |
3002 (val & mask));
3003 }
3004 release_firmware(fw);
3005 break;
3006 case SND_SOC_DAPM_POST_PMD:
3007 msleep(40);
3008 snd_soc_update_bits(codec, TAIKO_A_CDC_ANC1_B1_CTL, 0x01, 0x00);
3009 snd_soc_update_bits(codec, TAIKO_A_CDC_ANC2_B1_CTL, 0x02, 0x00);
3010 msleep(20);
3011 snd_soc_write(codec, TAIKO_A_CDC_CLK_ANC_RESET_CTL, 0x0F);
3012 snd_soc_write(codec, TAIKO_A_CDC_CLK_ANC_CLK_EN_CTL, 0);
3013 snd_soc_write(codec, TAIKO_A_CDC_CLK_ANC_RESET_CTL, 0xFF);
3014 break;
3015 }
3016 return 0;
3017}
3018
Kiran Kandic3b24402012-06-11 00:05:59 -07003019static int taiko_hph_pa_event(struct snd_soc_dapm_widget *w,
Joonwoo Parka8890262012-10-15 12:04:27 -07003020 struct snd_kcontrol *kcontrol, int event)
Kiran Kandic3b24402012-06-11 00:05:59 -07003021{
3022 struct snd_soc_codec *codec = w->codec;
3023 struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
Joonwoo Parka8890262012-10-15 12:04:27 -07003024 enum wcd9xxx_notify_event e_pre_on, e_post_off;
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08003025 u8 req_clsh_state;
Bhalchandra Gajareef7810e2013-03-29 16:50:37 -07003026 u32 pa_settle_time = TAIKO_HPH_PA_SETTLE_COMP_OFF;
Joonwoo Parka8890262012-10-15 12:04:27 -07003027
Kiran Kandi4c56c592012-07-25 11:04:55 -07003028 pr_debug("%s: %s event = %d\n", __func__, w->name, event);
Joonwoo Parka8890262012-10-15 12:04:27 -07003029 if (w->shift == 5) {
Joonwoo Parka8890262012-10-15 12:04:27 -07003030 e_pre_on = WCD9XXX_EVENT_PRE_HPHL_PA_ON;
3031 e_post_off = WCD9XXX_EVENT_POST_HPHL_PA_OFF;
Patrick Lai453cd742013-03-02 16:51:27 -08003032 req_clsh_state = WCD9XXX_CLSH_STATE_HPHL;
3033 } else if (w->shift == 4) {
3034 e_pre_on = WCD9XXX_EVENT_PRE_HPHR_PA_ON;
3035 e_post_off = WCD9XXX_EVENT_POST_HPHR_PA_OFF;
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08003036 req_clsh_state = WCD9XXX_CLSH_STATE_HPHR;
Joonwoo Parka8890262012-10-15 12:04:27 -07003037 } else {
3038 pr_err("%s: Invalid w->shift %d\n", __func__, w->shift);
3039 return -EINVAL;
3040 }
Kiran Kandic3b24402012-06-11 00:05:59 -07003041
Bhalchandra Gajareef7810e2013-03-29 16:50:37 -07003042 if (taiko->comp_enabled[COMPANDER_1])
3043 pa_settle_time = TAIKO_HPH_PA_SETTLE_COMP_ON;
3044
Kiran Kandic3b24402012-06-11 00:05:59 -07003045 switch (event) {
3046 case SND_SOC_DAPM_PRE_PMU:
Joonwoo Parka8890262012-10-15 12:04:27 -07003047 /* Let MBHC module know PA is turning on */
3048 wcd9xxx_resmgr_notifier_call(&taiko->resmgr, e_pre_on);
Kiran Kandic3b24402012-06-11 00:05:59 -07003049 break;
3050
Kiran Kandi4c56c592012-07-25 11:04:55 -07003051 case SND_SOC_DAPM_POST_PMU:
Bhalchandra Gajareef7810e2013-03-29 16:50:37 -07003052 usleep_range(pa_settle_time, pa_settle_time + 1000);
3053 pr_debug("%s: sleep %d us after %s PA enable\n", __func__,
3054 pa_settle_time, w->name);
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08003055 wcd9xxx_clsh_fsm(codec, &taiko->clsh_d,
3056 req_clsh_state,
3057 WCD9XXX_CLSH_REQ_ENABLE,
3058 WCD9XXX_CLSH_EVENT_POST_PA);
Kiran Kandi4c56c592012-07-25 11:04:55 -07003059
Kiran Kandi4c56c592012-07-25 11:04:55 -07003060 break;
3061
Kiran Kandic3b24402012-06-11 00:05:59 -07003062 case SND_SOC_DAPM_POST_PMD:
Bhalchandra Gajareef7810e2013-03-29 16:50:37 -07003063 usleep_range(pa_settle_time, pa_settle_time + 1000);
3064 pr_debug("%s: sleep %d us after %s PA disable\n", __func__,
3065 pa_settle_time, w->name);
3066
Joonwoo Parka8890262012-10-15 12:04:27 -07003067 /* Let MBHC module know PA turned off */
3068 wcd9xxx_resmgr_notifier_call(&taiko->resmgr, e_post_off);
3069
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08003070 wcd9xxx_clsh_fsm(codec, &taiko->clsh_d,
3071 req_clsh_state,
3072 WCD9XXX_CLSH_REQ_DISABLE,
3073 WCD9XXX_CLSH_EVENT_POST_PA);
3074
Kiran Kandic3b24402012-06-11 00:05:59 -07003075 break;
3076 }
3077 return 0;
3078}
3079
Damir Didjusto2cb06bd2013-01-30 23:14:55 -08003080static int taiko_codec_enable_anc_hph(struct snd_soc_dapm_widget *w,
3081 struct snd_kcontrol *kcontrol, int event)
3082{
3083 struct snd_soc_codec *codec = w->codec;
3084 int ret = 0;
3085
3086 switch (event) {
3087 case SND_SOC_DAPM_PRE_PMU:
3088 ret = taiko_hph_pa_event(w, kcontrol, event);
3089 if (w->shift == 4) {
3090 ret |= taiko_codec_enable_anc(w, kcontrol, event);
3091 msleep(50);
3092 }
3093 break;
3094 case SND_SOC_DAPM_POST_PMU:
3095 if (w->shift == 4) {
3096 snd_soc_update_bits(codec,
3097 TAIKO_A_RX_HPH_CNP_EN, 0x30, 0x30);
3098 msleep(30);
3099 }
3100 ret = taiko_hph_pa_event(w, kcontrol, event);
3101 break;
3102 case SND_SOC_DAPM_PRE_PMD:
3103 if (w->shift == 5) {
3104 snd_soc_update_bits(codec,
3105 TAIKO_A_RX_HPH_CNP_EN, 0x30, 0x00);
3106 msleep(40);
3107 }
3108 if (w->shift == 5) {
3109 snd_soc_update_bits(codec,
3110 TAIKO_A_TX_7_MBHC_EN, 0x80, 00);
3111 ret |= taiko_codec_enable_anc(w, kcontrol, event);
3112 }
3113 case SND_SOC_DAPM_POST_PMD:
3114 ret = taiko_hph_pa_event(w, kcontrol, event);
3115 break;
3116 }
3117 return ret;
3118}
3119
Kiran Kandic3b24402012-06-11 00:05:59 -07003120static const struct snd_soc_dapm_widget taiko_dapm_i2s_widgets[] = {
3121 SND_SOC_DAPM_SUPPLY("RX_I2S_CLK", TAIKO_A_CDC_CLK_RX_I2S_CTL,
3122 4, 0, NULL, 0),
3123 SND_SOC_DAPM_SUPPLY("TX_I2S_CLK", TAIKO_A_CDC_CLK_TX_I2S_CTL, 4,
3124 0, NULL, 0),
3125};
3126
3127static int taiko_lineout_dac_event(struct snd_soc_dapm_widget *w,
3128 struct snd_kcontrol *kcontrol, int event)
3129{
3130 struct snd_soc_codec *codec = w->codec;
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08003131 struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
Kiran Kandic3b24402012-06-11 00:05:59 -07003132
3133 pr_debug("%s %s %d\n", __func__, w->name, event);
3134
3135 switch (event) {
3136 case SND_SOC_DAPM_PRE_PMU:
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08003137 wcd9xxx_clsh_fsm(codec, &taiko->clsh_d,
3138 WCD9XXX_CLSH_STATE_LO,
3139 WCD9XXX_CLSH_REQ_ENABLE,
3140 WCD9XXX_CLSH_EVENT_PRE_DAC);
Kiran Kandic3b24402012-06-11 00:05:59 -07003141 snd_soc_update_bits(codec, w->reg, 0x40, 0x40);
3142 break;
3143
3144 case SND_SOC_DAPM_POST_PMD:
3145 snd_soc_update_bits(codec, w->reg, 0x40, 0x00);
3146 break;
3147 }
3148 return 0;
3149}
3150
Joonwoo Park7680b9f2012-07-13 11:36:48 -07003151static int taiko_spk_dac_event(struct snd_soc_dapm_widget *w,
3152 struct snd_kcontrol *kcontrol, int event)
3153{
3154 pr_debug("%s %s %d\n", __func__, w->name, event);
3155 return 0;
3156}
3157
Kiran Kandic3b24402012-06-11 00:05:59 -07003158static const struct snd_soc_dapm_route audio_i2s_map[] = {
Kiran Kandic3b24402012-06-11 00:05:59 -07003159 {"SLIM RX1", NULL, "RX_I2S_CLK"},
3160 {"SLIM RX2", NULL, "RX_I2S_CLK"},
3161 {"SLIM RX3", NULL, "RX_I2S_CLK"},
3162 {"SLIM RX4", NULL, "RX_I2S_CLK"},
3163
Venkat Sudhira41630a2012-10-27 00:57:31 -07003164 {"SLIM TX7 MUX", NULL, "TX_I2S_CLK"},
3165 {"SLIM TX8 MUX", NULL, "TX_I2S_CLK"},
3166 {"SLIM TX9 MUX", NULL, "TX_I2S_CLK"},
3167 {"SLIM TX10 MUX", NULL, "TX_I2S_CLK"},
Kiran Kandic3b24402012-06-11 00:05:59 -07003168};
3169
Joonwoo Park559a5bf2013-02-15 14:46:36 -08003170static const struct snd_soc_dapm_route audio_i2s_map_1_0[] = {
3171 {"RX_I2S_CLK", NULL, "CDC_CONN"},
3172};
3173
3174static const struct snd_soc_dapm_route audio_i2s_map_2_0[] = {
3175 {"RX_I2S_CLK", NULL, "CDC_I2S_RX_CONN"},
3176};
3177
Kiran Kandic3b24402012-06-11 00:05:59 -07003178static const struct snd_soc_dapm_route audio_map[] = {
3179 /* SLIMBUS Connections */
Kuirong Wang906ac472012-07-09 12:54:44 -07003180 {"AIF1 CAP", NULL, "AIF1_CAP Mixer"},
3181 {"AIF2 CAP", NULL, "AIF2_CAP Mixer"},
3182 {"AIF3 CAP", NULL, "AIF3_CAP Mixer"},
Gopikrishnaiah Anandana2627572013-02-26 13:30:50 -05003183 {"AIF4 VI", NULL, "SPK_OUT"},
Kiran Kandic3b24402012-06-11 00:05:59 -07003184
Joonwoo Park1d05bb92013-03-07 16:55:06 -08003185 /* MAD */
3186 {"AIF4 MAD", NULL, "CDC_CONN"},
Joonwoo Park9ead0e92013-03-18 11:33:33 -07003187 {"MADONOFF", "Switch", "MADINPUT"},
3188 {"AIF4 MAD", NULL, "MADONOFF"},
Joonwoo Park1d05bb92013-03-07 16:55:06 -08003189
Kuirong Wang906ac472012-07-09 12:54:44 -07003190 /* SLIM_MIXER("AIF1_CAP Mixer"),*/
3191 {"AIF1_CAP Mixer", "SLIM TX1", "SLIM TX1 MUX"},
3192 {"AIF1_CAP Mixer", "SLIM TX2", "SLIM TX2 MUX"},
3193 {"AIF1_CAP Mixer", "SLIM TX3", "SLIM TX3 MUX"},
3194 {"AIF1_CAP Mixer", "SLIM TX4", "SLIM TX4 MUX"},
3195 {"AIF1_CAP Mixer", "SLIM TX5", "SLIM TX5 MUX"},
3196 {"AIF1_CAP Mixer", "SLIM TX6", "SLIM TX6 MUX"},
3197 {"AIF1_CAP Mixer", "SLIM TX7", "SLIM TX7 MUX"},
3198 {"AIF1_CAP Mixer", "SLIM TX8", "SLIM TX8 MUX"},
3199 {"AIF1_CAP Mixer", "SLIM TX9", "SLIM TX9 MUX"},
3200 {"AIF1_CAP Mixer", "SLIM TX10", "SLIM TX10 MUX"},
3201 /* SLIM_MIXER("AIF2_CAP Mixer"),*/
3202 {"AIF2_CAP Mixer", "SLIM TX1", "SLIM TX1 MUX"},
3203 {"AIF2_CAP Mixer", "SLIM TX2", "SLIM TX2 MUX"},
3204 {"AIF2_CAP Mixer", "SLIM TX3", "SLIM TX3 MUX"},
3205 {"AIF2_CAP Mixer", "SLIM TX4", "SLIM TX4 MUX"},
3206 {"AIF2_CAP Mixer", "SLIM TX5", "SLIM TX5 MUX"},
3207 {"AIF2_CAP Mixer", "SLIM TX6", "SLIM TX6 MUX"},
3208 {"AIF2_CAP Mixer", "SLIM TX7", "SLIM TX7 MUX"},
3209 {"AIF2_CAP Mixer", "SLIM TX8", "SLIM TX8 MUX"},
3210 {"AIF2_CAP Mixer", "SLIM TX9", "SLIM TX9 MUX"},
3211 {"AIF2_CAP Mixer", "SLIM TX10", "SLIM TX10 MUX"},
3212 /* SLIM_MIXER("AIF3_CAP Mixer"),*/
3213 {"AIF3_CAP Mixer", "SLIM TX1", "SLIM TX1 MUX"},
3214 {"AIF3_CAP Mixer", "SLIM TX2", "SLIM TX2 MUX"},
3215 {"AIF3_CAP Mixer", "SLIM TX3", "SLIM TX3 MUX"},
3216 {"AIF3_CAP Mixer", "SLIM TX4", "SLIM TX4 MUX"},
3217 {"AIF3_CAP Mixer", "SLIM TX5", "SLIM TX5 MUX"},
3218 {"AIF3_CAP Mixer", "SLIM TX6", "SLIM TX6 MUX"},
3219 {"AIF3_CAP Mixer", "SLIM TX7", "SLIM TX7 MUX"},
3220 {"AIF3_CAP Mixer", "SLIM TX8", "SLIM TX8 MUX"},
3221 {"AIF3_CAP Mixer", "SLIM TX9", "SLIM TX9 MUX"},
3222 {"AIF3_CAP Mixer", "SLIM TX10", "SLIM TX10 MUX"},
3223
Kiran Kandic3b24402012-06-11 00:05:59 -07003224 {"SLIM TX1 MUX", "DEC1", "DEC1 MUX"},
3225
Kiran Kandic3b24402012-06-11 00:05:59 -07003226 {"SLIM TX2 MUX", "DEC2", "DEC2 MUX"},
3227
Kiran Kandic3b24402012-06-11 00:05:59 -07003228 {"SLIM TX3 MUX", "DEC3", "DEC3 MUX"},
3229 {"SLIM TX3 MUX", "RMIX1", "RX1 MIX1"},
3230 {"SLIM TX3 MUX", "RMIX2", "RX2 MIX1"},
3231 {"SLIM TX3 MUX", "RMIX3", "RX3 MIX1"},
3232 {"SLIM TX3 MUX", "RMIX4", "RX4 MIX1"},
3233 {"SLIM TX3 MUX", "RMIX5", "RX5 MIX1"},
3234 {"SLIM TX3 MUX", "RMIX6", "RX6 MIX1"},
3235 {"SLIM TX3 MUX", "RMIX7", "RX7 MIX1"},
3236
Kiran Kandic3b24402012-06-11 00:05:59 -07003237 {"SLIM TX4 MUX", "DEC4", "DEC4 MUX"},
3238
Kiran Kandic3b24402012-06-11 00:05:59 -07003239 {"SLIM TX5 MUX", "DEC5", "DEC5 MUX"},
3240 {"SLIM TX5 MUX", "RMIX1", "RX1 MIX1"},
3241 {"SLIM TX5 MUX", "RMIX2", "RX2 MIX1"},
3242 {"SLIM TX5 MUX", "RMIX3", "RX3 MIX1"},
3243 {"SLIM TX5 MUX", "RMIX4", "RX4 MIX1"},
3244 {"SLIM TX5 MUX", "RMIX5", "RX5 MIX1"},
3245 {"SLIM TX5 MUX", "RMIX6", "RX6 MIX1"},
3246 {"SLIM TX5 MUX", "RMIX7", "RX7 MIX1"},
3247
Kiran Kandic3b24402012-06-11 00:05:59 -07003248 {"SLIM TX6 MUX", "DEC6", "DEC6 MUX"},
3249
Kiran Kandic3b24402012-06-11 00:05:59 -07003250 {"SLIM TX7 MUX", "DEC1", "DEC1 MUX"},
3251 {"SLIM TX7 MUX", "DEC2", "DEC2 MUX"},
3252 {"SLIM TX7 MUX", "DEC3", "DEC3 MUX"},
3253 {"SLIM TX7 MUX", "DEC4", "DEC4 MUX"},
3254 {"SLIM TX7 MUX", "DEC5", "DEC5 MUX"},
3255 {"SLIM TX7 MUX", "DEC6", "DEC6 MUX"},
3256 {"SLIM TX7 MUX", "DEC7", "DEC7 MUX"},
3257 {"SLIM TX7 MUX", "DEC8", "DEC8 MUX"},
3258 {"SLIM TX7 MUX", "DEC9", "DEC9 MUX"},
3259 {"SLIM TX7 MUX", "DEC10", "DEC10 MUX"},
3260 {"SLIM TX7 MUX", "RMIX1", "RX1 MIX1"},
3261 {"SLIM TX7 MUX", "RMIX2", "RX2 MIX1"},
3262 {"SLIM TX7 MUX", "RMIX3", "RX3 MIX1"},
3263 {"SLIM TX7 MUX", "RMIX4", "RX4 MIX1"},
3264 {"SLIM TX7 MUX", "RMIX5", "RX5 MIX1"},
3265 {"SLIM TX7 MUX", "RMIX6", "RX6 MIX1"},
3266 {"SLIM TX7 MUX", "RMIX7", "RX7 MIX1"},
3267
Kiran Kandic3b24402012-06-11 00:05:59 -07003268 {"SLIM TX8 MUX", "DEC1", "DEC1 MUX"},
3269 {"SLIM TX8 MUX", "DEC2", "DEC2 MUX"},
3270 {"SLIM TX8 MUX", "DEC3", "DEC3 MUX"},
3271 {"SLIM TX8 MUX", "DEC4", "DEC4 MUX"},
3272 {"SLIM TX8 MUX", "DEC5", "DEC5 MUX"},
3273 {"SLIM TX8 MUX", "DEC6", "DEC6 MUX"},
3274 {"SLIM TX8 MUX", "DEC7", "DEC7 MUX"},
3275 {"SLIM TX8 MUX", "DEC8", "DEC8 MUX"},
3276 {"SLIM TX8 MUX", "DEC9", "DEC9 MUX"},
3277 {"SLIM TX8 MUX", "DEC10", "DEC10 MUX"},
3278
Kiran Kandic3b24402012-06-11 00:05:59 -07003279 {"SLIM TX9 MUX", "DEC1", "DEC1 MUX"},
3280 {"SLIM TX9 MUX", "DEC2", "DEC2 MUX"},
3281 {"SLIM TX9 MUX", "DEC3", "DEC3 MUX"},
3282 {"SLIM TX9 MUX", "DEC4", "DEC4 MUX"},
3283 {"SLIM TX9 MUX", "DEC5", "DEC5 MUX"},
3284 {"SLIM TX9 MUX", "DEC6", "DEC6 MUX"},
3285 {"SLIM TX9 MUX", "DEC7", "DEC7 MUX"},
3286 {"SLIM TX9 MUX", "DEC8", "DEC8 MUX"},
3287 {"SLIM TX9 MUX", "DEC9", "DEC9 MUX"},
3288 {"SLIM TX9 MUX", "DEC10", "DEC10 MUX"},
3289
Kiran Kandic3b24402012-06-11 00:05:59 -07003290 {"SLIM TX10 MUX", "DEC1", "DEC1 MUX"},
3291 {"SLIM TX10 MUX", "DEC2", "DEC2 MUX"},
3292 {"SLIM TX10 MUX", "DEC3", "DEC3 MUX"},
3293 {"SLIM TX10 MUX", "DEC4", "DEC4 MUX"},
3294 {"SLIM TX10 MUX", "DEC5", "DEC5 MUX"},
3295 {"SLIM TX10 MUX", "DEC6", "DEC6 MUX"},
3296 {"SLIM TX10 MUX", "DEC7", "DEC7 MUX"},
3297 {"SLIM TX10 MUX", "DEC8", "DEC8 MUX"},
3298 {"SLIM TX10 MUX", "DEC9", "DEC9 MUX"},
3299 {"SLIM TX10 MUX", "DEC10", "DEC10 MUX"},
3300
3301 /* Earpiece (RX MIX1) */
3302 {"EAR", NULL, "EAR PA"},
3303 {"EAR PA", NULL, "EAR_PA_MIXER"},
3304 {"EAR_PA_MIXER", NULL, "DAC1"},
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08003305 {"DAC1", NULL, "RX_BIAS"},
Kiran Kandic3b24402012-06-11 00:05:59 -07003306
Damir Didjusto2cb06bd2013-01-30 23:14:55 -08003307 {"ANC EAR", NULL, "ANC EAR PA"},
3308 {"ANC EAR PA", NULL, "EAR_PA_MIXER"},
Kiran Kandic3b24402012-06-11 00:05:59 -07003309 {"ANC1 FB MUX", "EAR_HPH_L", "RX1 MIX2"},
3310 {"ANC1 FB MUX", "EAR_LINE_1", "RX2 MIX2"},
Kiran Kandic3b24402012-06-11 00:05:59 -07003311
3312 /* Headset (RX MIX1 and RX MIX2) */
3313 {"HEADPHONE", NULL, "HPHL"},
3314 {"HEADPHONE", NULL, "HPHR"},
3315
3316 {"HPHL", NULL, "HPHL_PA_MIXER"},
3317 {"HPHL_PA_MIXER", NULL, "HPHL DAC"},
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08003318 {"HPHL DAC", NULL, "RX_BIAS"},
Kiran Kandic3b24402012-06-11 00:05:59 -07003319
3320 {"HPHR", NULL, "HPHR_PA_MIXER"},
3321 {"HPHR_PA_MIXER", NULL, "HPHR DAC"},
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08003322 {"HPHR DAC", NULL, "RX_BIAS"},
Kiran Kandic3b24402012-06-11 00:05:59 -07003323
Damir Didjusto2cb06bd2013-01-30 23:14:55 -08003324 {"ANC HEADPHONE", NULL, "ANC HPHL"},
3325 {"ANC HEADPHONE", NULL, "ANC HPHR"},
3326
3327 {"ANC HPHL", NULL, "HPHL_PA_MIXER"},
3328 {"ANC HPHR", NULL, "HPHR_PA_MIXER"},
3329
Kiran Kandic3b24402012-06-11 00:05:59 -07003330 {"ANC1 MUX", "ADC1", "ADC1"},
3331 {"ANC1 MUX", "ADC2", "ADC2"},
3332 {"ANC1 MUX", "ADC3", "ADC3"},
3333 {"ANC1 MUX", "ADC4", "ADC4"},
Damir Didjusto2cb06bd2013-01-30 23:14:55 -08003334 {"ANC1 MUX", "DMIC1", "DMIC1"},
3335 {"ANC1 MUX", "DMIC2", "DMIC2"},
3336 {"ANC1 MUX", "DMIC3", "DMIC3"},
3337 {"ANC1 MUX", "DMIC4", "DMIC4"},
3338 {"ANC1 MUX", "DMIC5", "DMIC5"},
3339 {"ANC1 MUX", "DMIC6", "DMIC6"},
Kiran Kandic3b24402012-06-11 00:05:59 -07003340 {"ANC2 MUX", "ADC1", "ADC1"},
3341 {"ANC2 MUX", "ADC2", "ADC2"},
3342 {"ANC2 MUX", "ADC3", "ADC3"},
3343 {"ANC2 MUX", "ADC4", "ADC4"},
3344
Damir Didjusto2cb06bd2013-01-30 23:14:55 -08003345 {"ANC HPHR", NULL, "CDC_CONN"},
Kiran Kandic3b24402012-06-11 00:05:59 -07003346
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08003347 {"DAC1", "Switch", "CLASS_H_DSM MUX"},
3348 {"HPHL DAC", "Switch", "CLASS_H_DSM MUX"},
Kiran Kandic3b24402012-06-11 00:05:59 -07003349 {"HPHR DAC", NULL, "RX2 CHAIN"},
3350
3351 {"LINEOUT1", NULL, "LINEOUT1 PA"},
3352 {"LINEOUT2", NULL, "LINEOUT2 PA"},
3353 {"LINEOUT3", NULL, "LINEOUT3 PA"},
3354 {"LINEOUT4", NULL, "LINEOUT4 PA"},
Joonwoo Park7680b9f2012-07-13 11:36:48 -07003355 {"SPK_OUT", NULL, "SPK PA"},
Kiran Kandic3b24402012-06-11 00:05:59 -07003356
3357 {"LINEOUT1 PA", NULL, "LINEOUT1_PA_MIXER"},
3358 {"LINEOUT1_PA_MIXER", NULL, "LINEOUT1 DAC"},
Tanya Finkelfe634462012-10-23 22:12:07 +02003359
Kiran Kandic3b24402012-06-11 00:05:59 -07003360 {"LINEOUT2 PA", NULL, "LINEOUT2_PA_MIXER"},
3361 {"LINEOUT2_PA_MIXER", NULL, "LINEOUT2 DAC"},
Tanya Finkelfe634462012-10-23 22:12:07 +02003362
Kiran Kandic3b24402012-06-11 00:05:59 -07003363 {"LINEOUT3 PA", NULL, "LINEOUT3_PA_MIXER"},
3364 {"LINEOUT3_PA_MIXER", NULL, "LINEOUT3 DAC"},
Tanya Finkelfe634462012-10-23 22:12:07 +02003365
Kiran Kandic3b24402012-06-11 00:05:59 -07003366 {"LINEOUT4 PA", NULL, "LINEOUT4_PA_MIXER"},
3367 {"LINEOUT4_PA_MIXER", NULL, "LINEOUT4 DAC"},
3368
3369 {"LINEOUT1 DAC", NULL, "RX3 MIX1"},
3370
Tanya Finkeldaaa6d12012-10-25 11:22:48 +02003371 {"RDAC5 MUX", "DEM3_INV", "RX3 MIX1"},
3372 {"RDAC5 MUX", "DEM4", "RX4 MIX1"},
3373
3374 {"LINEOUT3 DAC", NULL, "RDAC5 MUX"},
Kiran Kandic3b24402012-06-11 00:05:59 -07003375
3376 {"LINEOUT2 DAC", NULL, "RX5 MIX1"},
3377
Tanya Finkeldaaa6d12012-10-25 11:22:48 +02003378 {"RDAC7 MUX", "DEM5_INV", "RX5 MIX1"},
3379 {"RDAC7 MUX", "DEM6", "RX6 MIX1"},
3380
3381 {"LINEOUT4 DAC", NULL, "RDAC7 MUX"},
Kiran Kandic3b24402012-06-11 00:05:59 -07003382
Joonwoo Park7680b9f2012-07-13 11:36:48 -07003383 {"SPK PA", NULL, "SPK DAC"},
Kiran Kandid2b46332012-10-05 12:04:00 -07003384 {"SPK DAC", NULL, "RX7 MIX2"},
Joonwoo Park125cd4e2012-12-11 15:16:11 -08003385 {"SPK DAC", NULL, "VDD_SPKDRV"},
Joonwoo Park7680b9f2012-07-13 11:36:48 -07003386
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08003387 {"CLASS_H_DSM MUX", "DSM_HPHL_RX1", "RX1 CHAIN"},
3388
Kiran Kandic3b24402012-06-11 00:05:59 -07003389 {"RX1 CHAIN", NULL, "RX1 MIX2"},
3390 {"RX2 CHAIN", NULL, "RX2 MIX2"},
Damir Didjusto2cb06bd2013-01-30 23:14:55 -08003391 {"RX1 MIX2", NULL, "ANC1 MUX"},
3392 {"RX2 MIX2", NULL, "ANC2 MUX"},
Kiran Kandic3b24402012-06-11 00:05:59 -07003393
Kiran Kandic3b24402012-06-11 00:05:59 -07003394 {"LINEOUT1 DAC", NULL, "RX_BIAS"},
3395 {"LINEOUT2 DAC", NULL, "RX_BIAS"},
3396 {"LINEOUT3 DAC", NULL, "RX_BIAS"},
3397 {"LINEOUT4 DAC", NULL, "RX_BIAS"},
Joonwoo Park7680b9f2012-07-13 11:36:48 -07003398 {"SPK DAC", NULL, "RX_BIAS"},
Kiran Kandic3b24402012-06-11 00:05:59 -07003399
Joonwoo Parkc7731432012-10-17 12:41:44 -07003400 {"RX7 MIX1", NULL, "COMP0_CLK"},
Kiran Kandic3b24402012-06-11 00:05:59 -07003401 {"RX1 MIX1", NULL, "COMP1_CLK"},
3402 {"RX2 MIX1", NULL, "COMP1_CLK"},
3403 {"RX3 MIX1", NULL, "COMP2_CLK"},
3404 {"RX5 MIX1", NULL, "COMP2_CLK"},
3405
Kiran Kandic3b24402012-06-11 00:05:59 -07003406 {"RX1 MIX1", NULL, "RX1 MIX1 INP1"},
3407 {"RX1 MIX1", NULL, "RX1 MIX1 INP2"},
3408 {"RX1 MIX1", NULL, "RX1 MIX1 INP3"},
3409 {"RX2 MIX1", NULL, "RX2 MIX1 INP1"},
3410 {"RX2 MIX1", NULL, "RX2 MIX1 INP2"},
3411 {"RX3 MIX1", NULL, "RX3 MIX1 INP1"},
3412 {"RX3 MIX1", NULL, "RX3 MIX1 INP2"},
3413 {"RX4 MIX1", NULL, "RX4 MIX1 INP1"},
3414 {"RX4 MIX1", NULL, "RX4 MIX1 INP2"},
3415 {"RX5 MIX1", NULL, "RX5 MIX1 INP1"},
3416 {"RX5 MIX1", NULL, "RX5 MIX1 INP2"},
3417 {"RX6 MIX1", NULL, "RX6 MIX1 INP1"},
3418 {"RX6 MIX1", NULL, "RX6 MIX1 INP2"},
3419 {"RX7 MIX1", NULL, "RX7 MIX1 INP1"},
3420 {"RX7 MIX1", NULL, "RX7 MIX1 INP2"},
3421 {"RX1 MIX2", NULL, "RX1 MIX1"},
3422 {"RX1 MIX2", NULL, "RX1 MIX2 INP1"},
3423 {"RX1 MIX2", NULL, "RX1 MIX2 INP2"},
3424 {"RX2 MIX2", NULL, "RX2 MIX1"},
3425 {"RX2 MIX2", NULL, "RX2 MIX2 INP1"},
3426 {"RX2 MIX2", NULL, "RX2 MIX2 INP2"},
3427 {"RX7 MIX2", NULL, "RX7 MIX1"},
3428 {"RX7 MIX2", NULL, "RX7 MIX2 INP1"},
3429 {"RX7 MIX2", NULL, "RX7 MIX2 INP2"},
3430
Kuirong Wang906ac472012-07-09 12:54:44 -07003431 /* SLIM_MUX("AIF1_PB", "AIF1 PB"),*/
3432 {"SLIM RX1 MUX", "AIF1_PB", "AIF1 PB"},
3433 {"SLIM RX2 MUX", "AIF1_PB", "AIF1 PB"},
3434 {"SLIM RX3 MUX", "AIF1_PB", "AIF1 PB"},
3435 {"SLIM RX4 MUX", "AIF1_PB", "AIF1 PB"},
3436 {"SLIM RX5 MUX", "AIF1_PB", "AIF1 PB"},
3437 {"SLIM RX6 MUX", "AIF1_PB", "AIF1 PB"},
3438 {"SLIM RX7 MUX", "AIF1_PB", "AIF1 PB"},
3439 /* SLIM_MUX("AIF2_PB", "AIF2 PB"),*/
3440 {"SLIM RX1 MUX", "AIF2_PB", "AIF2 PB"},
3441 {"SLIM RX2 MUX", "AIF2_PB", "AIF2 PB"},
3442 {"SLIM RX3 MUX", "AIF2_PB", "AIF2 PB"},
3443 {"SLIM RX4 MUX", "AIF2_PB", "AIF2 PB"},
3444 {"SLIM RX5 MUX", "AIF2_PB", "AIF2 PB"},
3445 {"SLIM RX6 MUX", "AIF2_PB", "AIF2 PB"},
3446 {"SLIM RX7 MUX", "AIF2_PB", "AIF2 PB"},
3447 /* SLIM_MUX("AIF3_PB", "AIF3 PB"),*/
3448 {"SLIM RX1 MUX", "AIF3_PB", "AIF3 PB"},
3449 {"SLIM RX2 MUX", "AIF3_PB", "AIF3 PB"},
3450 {"SLIM RX3 MUX", "AIF3_PB", "AIF3 PB"},
3451 {"SLIM RX4 MUX", "AIF3_PB", "AIF3 PB"},
3452 {"SLIM RX5 MUX", "AIF3_PB", "AIF3 PB"},
3453 {"SLIM RX6 MUX", "AIF3_PB", "AIF3 PB"},
3454 {"SLIM RX7 MUX", "AIF3_PB", "AIF3 PB"},
3455
3456 {"SLIM RX1", NULL, "SLIM RX1 MUX"},
3457 {"SLIM RX2", NULL, "SLIM RX2 MUX"},
3458 {"SLIM RX3", NULL, "SLIM RX3 MUX"},
3459 {"SLIM RX4", NULL, "SLIM RX4 MUX"},
3460 {"SLIM RX5", NULL, "SLIM RX5 MUX"},
3461 {"SLIM RX6", NULL, "SLIM RX6 MUX"},
3462 {"SLIM RX7", NULL, "SLIM RX7 MUX"},
3463
Kiran Kandic3b24402012-06-11 00:05:59 -07003464 {"RX1 MIX1 INP1", "RX1", "SLIM RX1"},
3465 {"RX1 MIX1 INP1", "RX2", "SLIM RX2"},
3466 {"RX1 MIX1 INP1", "RX3", "SLIM RX3"},
3467 {"RX1 MIX1 INP1", "RX4", "SLIM RX4"},
3468 {"RX1 MIX1 INP1", "RX5", "SLIM RX5"},
3469 {"RX1 MIX1 INP1", "RX6", "SLIM RX6"},
3470 {"RX1 MIX1 INP1", "RX7", "SLIM RX7"},
3471 {"RX1 MIX1 INP1", "IIR1", "IIR1"},
Fred Oh456fcb52013-02-28 19:08:15 -08003472 {"RX1 MIX1 INP1", "IIR2", "IIR2"},
Kiran Kandic3b24402012-06-11 00:05:59 -07003473 {"RX1 MIX1 INP2", "RX1", "SLIM RX1"},
3474 {"RX1 MIX1 INP2", "RX2", "SLIM RX2"},
3475 {"RX1 MIX1 INP2", "RX3", "SLIM RX3"},
3476 {"RX1 MIX1 INP2", "RX4", "SLIM RX4"},
3477 {"RX1 MIX1 INP2", "RX5", "SLIM RX5"},
3478 {"RX1 MIX1 INP2", "RX6", "SLIM RX6"},
3479 {"RX1 MIX1 INP2", "RX7", "SLIM RX7"},
3480 {"RX1 MIX1 INP2", "IIR1", "IIR1"},
Fred Oh456fcb52013-02-28 19:08:15 -08003481 {"RX1 MIX1 INP2", "IIR2", "IIR2"},
Kiran Kandic3b24402012-06-11 00:05:59 -07003482 {"RX1 MIX1 INP3", "RX1", "SLIM RX1"},
3483 {"RX1 MIX1 INP3", "RX2", "SLIM RX2"},
3484 {"RX1 MIX1 INP3", "RX3", "SLIM RX3"},
3485 {"RX1 MIX1 INP3", "RX4", "SLIM RX4"},
3486 {"RX1 MIX1 INP3", "RX5", "SLIM RX5"},
3487 {"RX1 MIX1 INP3", "RX6", "SLIM RX6"},
3488 {"RX1 MIX1 INP3", "RX7", "SLIM RX7"},
3489 {"RX2 MIX1 INP1", "RX1", "SLIM RX1"},
3490 {"RX2 MIX1 INP1", "RX2", "SLIM RX2"},
3491 {"RX2 MIX1 INP1", "RX3", "SLIM RX3"},
3492 {"RX2 MIX1 INP1", "RX4", "SLIM RX4"},
3493 {"RX2 MIX1 INP1", "RX5", "SLIM RX5"},
3494 {"RX2 MIX1 INP1", "RX6", "SLIM RX6"},
3495 {"RX2 MIX1 INP1", "RX7", "SLIM RX7"},
3496 {"RX2 MIX1 INP1", "IIR1", "IIR1"},
Fred Oh456fcb52013-02-28 19:08:15 -08003497 {"RX2 MIX1 INP1", "IIR2", "IIR2"},
Kiran Kandic3b24402012-06-11 00:05:59 -07003498 {"RX2 MIX1 INP2", "RX1", "SLIM RX1"},
3499 {"RX2 MIX1 INP2", "RX2", "SLIM RX2"},
3500 {"RX2 MIX1 INP2", "RX3", "SLIM RX3"},
3501 {"RX2 MIX1 INP2", "RX4", "SLIM RX4"},
3502 {"RX2 MIX1 INP2", "RX5", "SLIM RX5"},
3503 {"RX2 MIX1 INP2", "RX6", "SLIM RX6"},
3504 {"RX2 MIX1 INP2", "RX7", "SLIM RX7"},
3505 {"RX2 MIX1 INP2", "IIR1", "IIR1"},
Fred Oh456fcb52013-02-28 19:08:15 -08003506 {"RX2 MIX1 INP2", "IIR2", "IIR2"},
Kiran Kandic3b24402012-06-11 00:05:59 -07003507 {"RX3 MIX1 INP1", "RX1", "SLIM RX1"},
3508 {"RX3 MIX1 INP1", "RX2", "SLIM RX2"},
3509 {"RX3 MIX1 INP1", "RX3", "SLIM RX3"},
3510 {"RX3 MIX1 INP1", "RX4", "SLIM RX4"},
3511 {"RX3 MIX1 INP1", "RX5", "SLIM RX5"},
3512 {"RX3 MIX1 INP1", "RX6", "SLIM RX6"},
3513 {"RX3 MIX1 INP1", "RX7", "SLIM RX7"},
3514 {"RX3 MIX1 INP1", "IIR1", "IIR1"},
Fred Oh456fcb52013-02-28 19:08:15 -08003515 {"RX3 MIX1 INP1", "IIR2", "IIR2"},
Kiran Kandic3b24402012-06-11 00:05:59 -07003516 {"RX3 MIX1 INP2", "RX1", "SLIM RX1"},
3517 {"RX3 MIX1 INP2", "RX2", "SLIM RX2"},
3518 {"RX3 MIX1 INP2", "RX3", "SLIM RX3"},
3519 {"RX3 MIX1 INP2", "RX4", "SLIM RX4"},
3520 {"RX3 MIX1 INP2", "RX5", "SLIM RX5"},
3521 {"RX3 MIX1 INP2", "RX6", "SLIM RX6"},
3522 {"RX3 MIX1 INP2", "RX7", "SLIM RX7"},
3523 {"RX3 MIX1 INP2", "IIR1", "IIR1"},
Fred Oh456fcb52013-02-28 19:08:15 -08003524 {"RX3 MIX1 INP2", "IIR2", "IIR2"},
Kiran Kandic3b24402012-06-11 00:05:59 -07003525 {"RX4 MIX1 INP1", "RX1", "SLIM RX1"},
3526 {"RX4 MIX1 INP1", "RX2", "SLIM RX2"},
3527 {"RX4 MIX1 INP1", "RX3", "SLIM RX3"},
3528 {"RX4 MIX1 INP1", "RX4", "SLIM RX4"},
3529 {"RX4 MIX1 INP1", "RX5", "SLIM RX5"},
3530 {"RX4 MIX1 INP1", "RX6", "SLIM RX6"},
3531 {"RX4 MIX1 INP1", "RX7", "SLIM RX7"},
3532 {"RX4 MIX1 INP1", "IIR1", "IIR1"},
Fred Oh456fcb52013-02-28 19:08:15 -08003533 {"RX4 MIX1 INP1", "IIR2", "IIR2"},
Kiran Kandic3b24402012-06-11 00:05:59 -07003534 {"RX4 MIX1 INP2", "RX1", "SLIM RX1"},
3535 {"RX4 MIX1 INP2", "RX2", "SLIM RX2"},
3536 {"RX4 MIX1 INP2", "RX3", "SLIM RX3"},
3537 {"RX4 MIX1 INP2", "RX5", "SLIM RX5"},
3538 {"RX4 MIX1 INP2", "RX4", "SLIM RX4"},
3539 {"RX4 MIX1 INP2", "RX6", "SLIM RX6"},
3540 {"RX4 MIX1 INP2", "RX7", "SLIM RX7"},
3541 {"RX4 MIX1 INP2", "IIR1", "IIR1"},
Fred Oh456fcb52013-02-28 19:08:15 -08003542 {"RX4 MIX1 INP2", "IIR2", "IIR2"},
Kiran Kandic3b24402012-06-11 00:05:59 -07003543 {"RX5 MIX1 INP1", "RX1", "SLIM RX1"},
3544 {"RX5 MIX1 INP1", "RX2", "SLIM RX2"},
3545 {"RX5 MIX1 INP1", "RX3", "SLIM RX3"},
3546 {"RX5 MIX1 INP1", "RX4", "SLIM RX4"},
3547 {"RX5 MIX1 INP1", "RX5", "SLIM RX5"},
3548 {"RX5 MIX1 INP1", "RX6", "SLIM RX6"},
3549 {"RX5 MIX1 INP1", "RX7", "SLIM RX7"},
3550 {"RX5 MIX1 INP1", "IIR1", "IIR1"},
Fred Oh456fcb52013-02-28 19:08:15 -08003551 {"RX5 MIX1 INP1", "IIR2", "IIR2"},
Kiran Kandic3b24402012-06-11 00:05:59 -07003552 {"RX5 MIX1 INP2", "RX1", "SLIM RX1"},
3553 {"RX5 MIX1 INP2", "RX2", "SLIM RX2"},
3554 {"RX5 MIX1 INP2", "RX3", "SLIM RX3"},
3555 {"RX5 MIX1 INP2", "RX4", "SLIM RX4"},
3556 {"RX5 MIX1 INP2", "RX5", "SLIM RX5"},
3557 {"RX5 MIX1 INP2", "RX6", "SLIM RX6"},
3558 {"RX5 MIX1 INP2", "RX7", "SLIM RX7"},
3559 {"RX5 MIX1 INP2", "IIR1", "IIR1"},
Fred Oh456fcb52013-02-28 19:08:15 -08003560 {"RX5 MIX1 INP2", "IIR2", "IIR2"},
Kiran Kandic3b24402012-06-11 00:05:59 -07003561 {"RX6 MIX1 INP1", "RX1", "SLIM RX1"},
3562 {"RX6 MIX1 INP1", "RX2", "SLIM RX2"},
3563 {"RX6 MIX1 INP1", "RX3", "SLIM RX3"},
3564 {"RX6 MIX1 INP1", "RX4", "SLIM RX4"},
3565 {"RX6 MIX1 INP1", "RX5", "SLIM RX5"},
3566 {"RX6 MIX1 INP1", "RX6", "SLIM RX6"},
3567 {"RX6 MIX1 INP1", "RX7", "SLIM RX7"},
3568 {"RX6 MIX1 INP1", "IIR1", "IIR1"},
Fred Oh456fcb52013-02-28 19:08:15 -08003569 {"RX6 MIX1 INP1", "IIR2", "IIR2"},
Kiran Kandic3b24402012-06-11 00:05:59 -07003570 {"RX6 MIX1 INP2", "RX1", "SLIM RX1"},
3571 {"RX6 MIX1 INP2", "RX2", "SLIM RX2"},
3572 {"RX6 MIX1 INP2", "RX3", "SLIM RX3"},
3573 {"RX6 MIX1 INP2", "RX4", "SLIM RX4"},
3574 {"RX6 MIX1 INP2", "RX5", "SLIM RX5"},
3575 {"RX6 MIX1 INP2", "RX6", "SLIM RX6"},
3576 {"RX6 MIX1 INP2", "RX7", "SLIM RX7"},
3577 {"RX6 MIX1 INP2", "IIR1", "IIR1"},
Fred Oh456fcb52013-02-28 19:08:15 -08003578 {"RX6 MIX1 INP2", "IIR2", "IIR2"},
Kiran Kandic3b24402012-06-11 00:05:59 -07003579 {"RX7 MIX1 INP1", "RX1", "SLIM RX1"},
3580 {"RX7 MIX1 INP1", "RX2", "SLIM RX2"},
3581 {"RX7 MIX1 INP1", "RX3", "SLIM RX3"},
3582 {"RX7 MIX1 INP1", "RX4", "SLIM RX4"},
3583 {"RX7 MIX1 INP1", "RX5", "SLIM RX5"},
3584 {"RX7 MIX1 INP1", "RX6", "SLIM RX6"},
3585 {"RX7 MIX1 INP1", "RX7", "SLIM RX7"},
3586 {"RX7 MIX1 INP1", "IIR1", "IIR1"},
Fred Oh456fcb52013-02-28 19:08:15 -08003587 {"RX7 MIX1 INP1", "IIR2", "IIR2"},
Kiran Kandic3b24402012-06-11 00:05:59 -07003588 {"RX7 MIX1 INP2", "RX1", "SLIM RX1"},
3589 {"RX7 MIX1 INP2", "RX2", "SLIM RX2"},
3590 {"RX7 MIX1 INP2", "RX3", "SLIM RX3"},
3591 {"RX7 MIX1 INP2", "RX4", "SLIM RX4"},
3592 {"RX7 MIX1 INP2", "RX5", "SLIM RX5"},
3593 {"RX7 MIX1 INP2", "RX6", "SLIM RX6"},
3594 {"RX7 MIX1 INP2", "RX7", "SLIM RX7"},
3595 {"RX7 MIX1 INP2", "IIR1", "IIR1"},
3596 {"RX1 MIX2 INP1", "IIR1", "IIR1"},
3597 {"RX1 MIX2 INP2", "IIR1", "IIR1"},
3598 {"RX2 MIX2 INP1", "IIR1", "IIR1"},
3599 {"RX2 MIX2 INP2", "IIR1", "IIR1"},
3600 {"RX7 MIX2 INP1", "IIR1", "IIR1"},
3601 {"RX7 MIX2 INP2", "IIR1", "IIR1"},
Fred Oh456fcb52013-02-28 19:08:15 -08003602 {"RX7 MIX1 INP2", "IIR2", "IIR2"},
3603 {"RX1 MIX2 INP1", "IIR2", "IIR2"},
3604 {"RX1 MIX2 INP2", "IIR2", "IIR2"},
3605 {"RX2 MIX2 INP1", "IIR2", "IIR2"},
3606 {"RX2 MIX2 INP2", "IIR2", "IIR2"},
3607 {"RX7 MIX2 INP1", "IIR2", "IIR2"},
3608 {"RX7 MIX2 INP2", "IIR2", "IIR2"},
Kiran Kandic3b24402012-06-11 00:05:59 -07003609
3610 /* Decimator Inputs */
3611 {"DEC1 MUX", "DMIC1", "DMIC1"},
3612 {"DEC1 MUX", "ADC6", "ADC6"},
3613 {"DEC1 MUX", NULL, "CDC_CONN"},
3614 {"DEC2 MUX", "DMIC2", "DMIC2"},
3615 {"DEC2 MUX", "ADC5", "ADC5"},
3616 {"DEC2 MUX", NULL, "CDC_CONN"},
3617 {"DEC3 MUX", "DMIC3", "DMIC3"},
3618 {"DEC3 MUX", "ADC4", "ADC4"},
3619 {"DEC3 MUX", NULL, "CDC_CONN"},
3620 {"DEC4 MUX", "DMIC4", "DMIC4"},
3621 {"DEC4 MUX", "ADC3", "ADC3"},
3622 {"DEC4 MUX", NULL, "CDC_CONN"},
3623 {"DEC5 MUX", "DMIC5", "DMIC5"},
3624 {"DEC5 MUX", "ADC2", "ADC2"},
3625 {"DEC5 MUX", NULL, "CDC_CONN"},
3626 {"DEC6 MUX", "DMIC6", "DMIC6"},
3627 {"DEC6 MUX", "ADC1", "ADC1"},
3628 {"DEC6 MUX", NULL, "CDC_CONN"},
3629 {"DEC7 MUX", "DMIC1", "DMIC1"},
3630 {"DEC7 MUX", "DMIC6", "DMIC6"},
3631 {"DEC7 MUX", "ADC1", "ADC1"},
3632 {"DEC7 MUX", "ADC6", "ADC6"},
3633 {"DEC7 MUX", NULL, "CDC_CONN"},
3634 {"DEC8 MUX", "DMIC2", "DMIC2"},
3635 {"DEC8 MUX", "DMIC5", "DMIC5"},
3636 {"DEC8 MUX", "ADC2", "ADC2"},
3637 {"DEC8 MUX", "ADC5", "ADC5"},
3638 {"DEC8 MUX", NULL, "CDC_CONN"},
3639 {"DEC9 MUX", "DMIC4", "DMIC4"},
3640 {"DEC9 MUX", "DMIC5", "DMIC5"},
3641 {"DEC9 MUX", "ADC2", "ADC2"},
3642 {"DEC9 MUX", "ADC3", "ADC3"},
3643 {"DEC9 MUX", NULL, "CDC_CONN"},
3644 {"DEC10 MUX", "DMIC3", "DMIC3"},
3645 {"DEC10 MUX", "DMIC6", "DMIC6"},
3646 {"DEC10 MUX", "ADC1", "ADC1"},
3647 {"DEC10 MUX", "ADC4", "ADC4"},
3648 {"DEC10 MUX", NULL, "CDC_CONN"},
3649
3650 /* ADC Connections */
3651 {"ADC1", NULL, "AMIC1"},
3652 {"ADC2", NULL, "AMIC2"},
3653 {"ADC3", NULL, "AMIC3"},
3654 {"ADC4", NULL, "AMIC4"},
3655 {"ADC5", NULL, "AMIC5"},
3656 {"ADC6", NULL, "AMIC6"},
3657
3658 /* AUX PGA Connections */
Kiran Kandic3b24402012-06-11 00:05:59 -07003659 {"EAR_PA_MIXER", "AUX_PGA_L Switch", "AUX_PGA_Left"},
Kiran Kandi4c56c592012-07-25 11:04:55 -07003660 {"HPHL_PA_MIXER", "AUX_PGA_L Switch", "AUX_PGA_Left"},
3661 {"HPHR_PA_MIXER", "AUX_PGA_R Switch", "AUX_PGA_Right"},
3662 {"LINEOUT1_PA_MIXER", "AUX_PGA_L Switch", "AUX_PGA_Left"},
3663 {"LINEOUT2_PA_MIXER", "AUX_PGA_R Switch", "AUX_PGA_Right"},
3664 {"LINEOUT3_PA_MIXER", "AUX_PGA_L Switch", "AUX_PGA_Left"},
3665 {"LINEOUT4_PA_MIXER", "AUX_PGA_R Switch", "AUX_PGA_Right"},
Kiran Kandic3b24402012-06-11 00:05:59 -07003666 {"AUX_PGA_Left", NULL, "AMIC5"},
3667 {"AUX_PGA_Right", NULL, "AMIC6"},
3668
Kiran Kandic3b24402012-06-11 00:05:59 -07003669 {"IIR1", NULL, "IIR1 INP1 MUX"},
3670 {"IIR1 INP1 MUX", "DEC1", "DEC1 MUX"},
3671 {"IIR1 INP1 MUX", "DEC2", "DEC2 MUX"},
3672 {"IIR1 INP1 MUX", "DEC3", "DEC3 MUX"},
3673 {"IIR1 INP1 MUX", "DEC4", "DEC4 MUX"},
3674 {"IIR1 INP1 MUX", "DEC5", "DEC5 MUX"},
3675 {"IIR1 INP1 MUX", "DEC6", "DEC6 MUX"},
3676 {"IIR1 INP1 MUX", "DEC7", "DEC7 MUX"},
3677 {"IIR1 INP1 MUX", "DEC8", "DEC8 MUX"},
3678 {"IIR1 INP1 MUX", "DEC9", "DEC9 MUX"},
3679 {"IIR1 INP1 MUX", "DEC10", "DEC10 MUX"},
3680
Fred Oh456fcb52013-02-28 19:08:15 -08003681 {"IIR2", NULL, "IIR2 INP1 MUX"},
3682 {"IIR2 INP1 MUX", "DEC1", "DEC1 MUX"},
3683 {"IIR2 INP1 MUX", "DEC2", "DEC2 MUX"},
3684 {"IIR2 INP1 MUX", "DEC3", "DEC3 MUX"},
3685 {"IIR2 INP1 MUX", "DEC4", "DEC4 MUX"},
3686 {"IIR2 INP1 MUX", "DEC5", "DEC5 MUX"},
3687 {"IIR2 INP1 MUX", "DEC6", "DEC6 MUX"},
3688 {"IIR2 INP1 MUX", "DEC7", "DEC7 MUX"},
3689 {"IIR2 INP1 MUX", "DEC8", "DEC8 MUX"},
3690 {"IIR2 INP1 MUX", "DEC9", "DEC9 MUX"},
3691 {"IIR2 INP1 MUX", "DEC10", "DEC10 MUX"},
3692
Kiran Kandic3b24402012-06-11 00:05:59 -07003693 {"MIC BIAS1 Internal1", NULL, "LDO_H"},
3694 {"MIC BIAS1 Internal2", NULL, "LDO_H"},
3695 {"MIC BIAS1 External", NULL, "LDO_H"},
3696 {"MIC BIAS2 Internal1", NULL, "LDO_H"},
3697 {"MIC BIAS2 Internal2", NULL, "LDO_H"},
3698 {"MIC BIAS2 Internal3", NULL, "LDO_H"},
3699 {"MIC BIAS2 External", NULL, "LDO_H"},
3700 {"MIC BIAS3 Internal1", NULL, "LDO_H"},
3701 {"MIC BIAS3 Internal2", NULL, "LDO_H"},
3702 {"MIC BIAS3 External", NULL, "LDO_H"},
3703 {"MIC BIAS4 External", NULL, "LDO_H"},
Gopikrishnaiah Anandana2627572013-02-26 13:30:50 -05003704
Kiran Kandic3b24402012-06-11 00:05:59 -07003705};
3706
3707static int taiko_readable(struct snd_soc_codec *ssc, unsigned int reg)
3708{
3709 return taiko_reg_readable[reg];
3710}
3711
3712static bool taiko_is_digital_gain_register(unsigned int reg)
3713{
3714 bool rtn = false;
3715 switch (reg) {
3716 case TAIKO_A_CDC_RX1_VOL_CTL_B2_CTL:
3717 case TAIKO_A_CDC_RX2_VOL_CTL_B2_CTL:
3718 case TAIKO_A_CDC_RX3_VOL_CTL_B2_CTL:
3719 case TAIKO_A_CDC_RX4_VOL_CTL_B2_CTL:
3720 case TAIKO_A_CDC_RX5_VOL_CTL_B2_CTL:
3721 case TAIKO_A_CDC_RX6_VOL_CTL_B2_CTL:
3722 case TAIKO_A_CDC_RX7_VOL_CTL_B2_CTL:
3723 case TAIKO_A_CDC_TX1_VOL_CTL_GAIN:
3724 case TAIKO_A_CDC_TX2_VOL_CTL_GAIN:
3725 case TAIKO_A_CDC_TX3_VOL_CTL_GAIN:
3726 case TAIKO_A_CDC_TX4_VOL_CTL_GAIN:
3727 case TAIKO_A_CDC_TX5_VOL_CTL_GAIN:
3728 case TAIKO_A_CDC_TX6_VOL_CTL_GAIN:
3729 case TAIKO_A_CDC_TX7_VOL_CTL_GAIN:
3730 case TAIKO_A_CDC_TX8_VOL_CTL_GAIN:
3731 case TAIKO_A_CDC_TX9_VOL_CTL_GAIN:
3732 case TAIKO_A_CDC_TX10_VOL_CTL_GAIN:
3733 rtn = true;
3734 break;
3735 default:
3736 break;
3737 }
3738 return rtn;
3739}
3740
3741static int taiko_volatile(struct snd_soc_codec *ssc, unsigned int reg)
3742{
Joonwoo Park1d05bb92013-03-07 16:55:06 -08003743 int i;
3744
Kiran Kandic3b24402012-06-11 00:05:59 -07003745 /* Registers lower than 0x100 are top level registers which can be
3746 * written by the Taiko core driver.
3747 */
3748
3749 if ((reg >= TAIKO_A_CDC_MBHC_EN_CTL) || (reg < 0x100))
3750 return 1;
3751
3752 /* IIR Coeff registers are not cacheable */
3753 if ((reg >= TAIKO_A_CDC_IIR1_COEF_B1_CTL) &&
3754 (reg <= TAIKO_A_CDC_IIR2_COEF_B2_CTL))
3755 return 1;
3756
Damir Didjusto2cb06bd2013-01-30 23:14:55 -08003757 /* ANC filter registers are not cacheable */
3758 if ((reg >= TAIKO_A_CDC_ANC1_IIR_B1_CTL) &&
3759 (reg <= TAIKO_A_CDC_ANC1_LPF_B2_CTL))
3760 return 1;
3761 if ((reg >= TAIKO_A_CDC_ANC2_IIR_B1_CTL) &&
3762 (reg <= TAIKO_A_CDC_ANC2_LPF_B2_CTL))
3763 return 1;
3764
Kiran Kandic3b24402012-06-11 00:05:59 -07003765 /* Digital gain register is not cacheable so we have to write
3766 * the setting even it is the same
3767 */
3768 if (taiko_is_digital_gain_register(reg))
3769 return 1;
3770
3771 /* HPH status registers */
3772 if (reg == TAIKO_A_RX_HPH_L_STATUS || reg == TAIKO_A_RX_HPH_R_STATUS)
3773 return 1;
3774
Joonwoo Parka8890262012-10-15 12:04:27 -07003775 if (reg == TAIKO_A_MBHC_INSERT_DET_STATUS)
3776 return 1;
3777
Joonwoo Park559a5bf2013-02-15 14:46:36 -08003778 switch (reg) {
3779 case TAIKO_A_CDC_SPKR_CLIPDET_VAL0:
3780 case TAIKO_A_CDC_SPKR_CLIPDET_VAL1:
3781 case TAIKO_A_CDC_SPKR_CLIPDET_VAL2:
3782 case TAIKO_A_CDC_SPKR_CLIPDET_VAL3:
3783 case TAIKO_A_CDC_SPKR_CLIPDET_VAL4:
3784 case TAIKO_A_CDC_SPKR_CLIPDET_VAL5:
3785 case TAIKO_A_CDC_SPKR_CLIPDET_VAL6:
3786 case TAIKO_A_CDC_SPKR_CLIPDET_VAL7:
3787 case TAIKO_A_CDC_VBAT_GAIN_MON_VAL:
3788 return 1;
3789 }
3790
Damir Didjustodcfdff82013-03-21 23:26:41 -07003791 for (i = 0; i < ARRAY_SIZE(audio_reg_cfg); i++)
3792 if (audio_reg_cfg[i].reg_logical_addr -
Joonwoo Park1d05bb92013-03-07 16:55:06 -08003793 TAIKO_REGISTER_START_OFFSET == reg)
3794 return 1;
3795
Kiran Kandic3b24402012-06-11 00:05:59 -07003796 return 0;
3797}
3798
Kiran Kandic3b24402012-06-11 00:05:59 -07003799static int taiko_write(struct snd_soc_codec *codec, unsigned int reg,
3800 unsigned int value)
3801{
3802 int ret;
Kuirong Wang906ac472012-07-09 12:54:44 -07003803
3804 if (reg == SND_SOC_NOPM)
3805 return 0;
3806
Kiran Kandic3b24402012-06-11 00:05:59 -07003807 BUG_ON(reg > TAIKO_MAX_REGISTER);
3808
3809 if (!taiko_volatile(codec, reg)) {
3810 ret = snd_soc_cache_write(codec, reg, value);
3811 if (ret != 0)
3812 dev_err(codec->dev, "Cache write to %x failed: %d\n",
3813 reg, ret);
3814 }
3815
3816 return wcd9xxx_reg_write(codec->control_data, reg, value);
3817}
3818static unsigned int taiko_read(struct snd_soc_codec *codec,
3819 unsigned int reg)
3820{
3821 unsigned int val;
3822 int ret;
3823
Kuirong Wang906ac472012-07-09 12:54:44 -07003824 if (reg == SND_SOC_NOPM)
3825 return 0;
3826
Kiran Kandic3b24402012-06-11 00:05:59 -07003827 BUG_ON(reg > TAIKO_MAX_REGISTER);
3828
3829 if (!taiko_volatile(codec, reg) && taiko_readable(codec, reg) &&
3830 reg < codec->driver->reg_cache_size) {
3831 ret = snd_soc_cache_read(codec, reg, &val);
3832 if (ret >= 0) {
3833 return val;
3834 } else
3835 dev_err(codec->dev, "Cache read from %x failed: %d\n",
3836 reg, ret);
3837 }
3838
3839 val = wcd9xxx_reg_read(codec->control_data, reg);
3840 return val;
3841}
3842
Kiran Kandic3b24402012-06-11 00:05:59 -07003843static int taiko_startup(struct snd_pcm_substream *substream,
3844 struct snd_soc_dai *dai)
3845{
3846 struct wcd9xxx *taiko_core = dev_get_drvdata(dai->codec->dev->parent);
3847 pr_debug("%s(): substream = %s stream = %d\n" , __func__,
3848 substream->name, substream->stream);
3849 if ((taiko_core != NULL) &&
3850 (taiko_core->dev != NULL) &&
3851 (taiko_core->dev->parent != NULL))
3852 pm_runtime_get_sync(taiko_core->dev->parent);
3853
3854 return 0;
3855}
3856
3857static void taiko_shutdown(struct snd_pcm_substream *substream,
3858 struct snd_soc_dai *dai)
3859{
3860 struct wcd9xxx *taiko_core = dev_get_drvdata(dai->codec->dev->parent);
3861 pr_debug("%s(): substream = %s stream = %d\n" , __func__,
3862 substream->name, substream->stream);
3863 if ((taiko_core != NULL) &&
3864 (taiko_core->dev != NULL) &&
3865 (taiko_core->dev->parent != NULL)) {
3866 pm_runtime_mark_last_busy(taiko_core->dev->parent);
3867 pm_runtime_put(taiko_core->dev->parent);
3868 }
3869}
3870
3871int taiko_mclk_enable(struct snd_soc_codec *codec, int mclk_enable, bool dapm)
3872{
3873 struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
3874
3875 pr_debug("%s: mclk_enable = %u, dapm = %d\n", __func__, mclk_enable,
3876 dapm);
Joonwoo Parka8890262012-10-15 12:04:27 -07003877
3878 WCD9XXX_BCL_LOCK(&taiko->resmgr);
Kiran Kandic3b24402012-06-11 00:05:59 -07003879 if (mclk_enable) {
Joonwoo Parka8890262012-10-15 12:04:27 -07003880 wcd9xxx_resmgr_get_bandgap(&taiko->resmgr,
3881 WCD9XXX_BANDGAP_AUDIO_MODE);
3882 wcd9xxx_resmgr_get_clk_block(&taiko->resmgr, WCD9XXX_CLK_MCLK);
Kiran Kandic3b24402012-06-11 00:05:59 -07003883 } else {
Joonwoo Parka8890262012-10-15 12:04:27 -07003884 /* Put clock and BG */
3885 wcd9xxx_resmgr_put_clk_block(&taiko->resmgr, WCD9XXX_CLK_MCLK);
3886 wcd9xxx_resmgr_put_bandgap(&taiko->resmgr,
3887 WCD9XXX_BANDGAP_AUDIO_MODE);
Kiran Kandic3b24402012-06-11 00:05:59 -07003888 }
Joonwoo Parka8890262012-10-15 12:04:27 -07003889 WCD9XXX_BCL_UNLOCK(&taiko->resmgr);
3890
Kiran Kandic3b24402012-06-11 00:05:59 -07003891 return 0;
3892}
3893
3894static int taiko_set_dai_sysclk(struct snd_soc_dai *dai,
3895 int clk_id, unsigned int freq, int dir)
3896{
Venkat Sudhira50a3762012-11-26 12:12:15 -08003897 pr_debug("%s\n", __func__);
Kiran Kandic3b24402012-06-11 00:05:59 -07003898 return 0;
3899}
3900
3901static int taiko_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
3902{
3903 u8 val = 0;
3904 struct taiko_priv *taiko = snd_soc_codec_get_drvdata(dai->codec);
3905
3906 pr_debug("%s\n", __func__);
3907 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
3908 case SND_SOC_DAIFMT_CBS_CFS:
3909 /* CPU is master */
3910 if (taiko->intf_type == WCD9XXX_INTERFACE_TYPE_I2C) {
3911 if (dai->id == AIF1_CAP)
3912 snd_soc_update_bits(dai->codec,
3913 TAIKO_A_CDC_CLK_TX_I2S_CTL,
3914 TAIKO_I2S_MASTER_MODE_MASK, 0);
3915 else if (dai->id == AIF1_PB)
3916 snd_soc_update_bits(dai->codec,
3917 TAIKO_A_CDC_CLK_RX_I2S_CTL,
3918 TAIKO_I2S_MASTER_MODE_MASK, 0);
3919 }
3920 break;
3921 case SND_SOC_DAIFMT_CBM_CFM:
3922 /* CPU is slave */
3923 if (taiko->intf_type == WCD9XXX_INTERFACE_TYPE_I2C) {
3924 val = TAIKO_I2S_MASTER_MODE_MASK;
3925 if (dai->id == AIF1_CAP)
3926 snd_soc_update_bits(dai->codec,
3927 TAIKO_A_CDC_CLK_TX_I2S_CTL, val, val);
3928 else if (dai->id == AIF1_PB)
3929 snd_soc_update_bits(dai->codec,
3930 TAIKO_A_CDC_CLK_RX_I2S_CTL, val, val);
3931 }
3932 break;
3933 default:
3934 return -EINVAL;
3935 }
3936 return 0;
3937}
3938
3939static int taiko_set_channel_map(struct snd_soc_dai *dai,
3940 unsigned int tx_num, unsigned int *tx_slot,
3941 unsigned int rx_num, unsigned int *rx_slot)
3942
3943{
Gopikrishnaiah Anandana2627572013-02-26 13:30:50 -05003944 struct wcd9xxx_codec_dai_data *dai_data = NULL;
Kiran Kandic3b24402012-06-11 00:05:59 -07003945 struct taiko_priv *taiko = snd_soc_codec_get_drvdata(dai->codec);
Kuirong Wang906ac472012-07-09 12:54:44 -07003946 struct wcd9xxx *core = dev_get_drvdata(dai->codec->dev->parent);
Kiran Kandic3b24402012-06-11 00:05:59 -07003947 if (!tx_slot && !rx_slot) {
3948 pr_err("%s: Invalid\n", __func__);
3949 return -EINVAL;
3950 }
Kuirong Wang906ac472012-07-09 12:54:44 -07003951 pr_debug("%s(): dai_name = %s DAI-ID %x tx_ch %d rx_ch %d\n"
3952 "taiko->intf_type %d\n",
3953 __func__, dai->name, dai->id, tx_num, rx_num,
3954 taiko->intf_type);
Kiran Kandic3b24402012-06-11 00:05:59 -07003955
Gopikrishnaiah Anandana2627572013-02-26 13:30:50 -05003956 if (taiko->intf_type == WCD9XXX_INTERFACE_TYPE_SLIMBUS) {
Kuirong Wang906ac472012-07-09 12:54:44 -07003957 wcd9xxx_init_slimslave(core, core->slim->laddr,
Gopikrishnaiah Anandana2627572013-02-26 13:30:50 -05003958 tx_num, tx_slot, rx_num, rx_slot);
3959 /*Reserve tx11 and tx12 for VI feedback path*/
3960 dai_data = &taiko->dai[AIF4_VIFEED];
3961 if (dai_data) {
3962 list_add_tail(&core->tx_chs[TAIKO_TX11].list,
3963 &dai_data->wcd9xxx_ch_list);
3964 list_add_tail(&core->tx_chs[TAIKO_TX12].list,
3965 &dai_data->wcd9xxx_ch_list);
3966 }
3967 }
Kuirong Wang906ac472012-07-09 12:54:44 -07003968 return 0;
3969}
3970
3971static int taiko_get_channel_map(struct snd_soc_dai *dai,
3972 unsigned int *tx_num, unsigned int *tx_slot,
3973 unsigned int *rx_num, unsigned int *rx_slot)
3974
3975{
3976 struct taiko_priv *taiko_p = snd_soc_codec_get_drvdata(dai->codec);
3977 u32 i = 0;
3978 struct wcd9xxx_ch *ch;
3979
3980 switch (dai->id) {
3981 case AIF1_PB:
3982 case AIF2_PB:
3983 case AIF3_PB:
3984 if (!rx_slot || !rx_num) {
3985 pr_err("%s: Invalid rx_slot %d or rx_num %d\n",
3986 __func__, (u32) rx_slot, (u32) rx_num);
3987 return -EINVAL;
Kiran Kandic3b24402012-06-11 00:05:59 -07003988 }
Kuirong Wang906ac472012-07-09 12:54:44 -07003989 list_for_each_entry(ch, &taiko_p->dai[dai->id].wcd9xxx_ch_list,
3990 list) {
Gopikrishnaiah Anandana8aec1f2013-01-23 14:26:27 -05003991 pr_debug("%s: slot_num %u ch->ch_num %d\n",
3992 __func__, i, ch->ch_num);
Kuirong Wang906ac472012-07-09 12:54:44 -07003993 rx_slot[i++] = ch->ch_num;
3994 }
3995 pr_debug("%s: rx_num %d\n", __func__, i);
3996 *rx_num = i;
3997 break;
3998 case AIF1_CAP:
3999 case AIF2_CAP:
4000 case AIF3_CAP:
Gopikrishnaiah Anandana2627572013-02-26 13:30:50 -05004001 case AIF4_VIFEED:
Joonwoo Park1d05bb92013-03-07 16:55:06 -08004002 case AIF4_MAD_TX:
Kuirong Wang906ac472012-07-09 12:54:44 -07004003 if (!tx_slot || !tx_num) {
4004 pr_err("%s: Invalid tx_slot %d or tx_num %d\n",
4005 __func__, (u32) tx_slot, (u32) tx_num);
4006 return -EINVAL;
4007 }
4008 list_for_each_entry(ch, &taiko_p->dai[dai->id].wcd9xxx_ch_list,
4009 list) {
Gopikrishnaiah Anandana8aec1f2013-01-23 14:26:27 -05004010 pr_debug("%s: slot_num %u ch->ch_num %d\n",
4011 __func__, i, ch->ch_num);
Kuirong Wang906ac472012-07-09 12:54:44 -07004012 tx_slot[i++] = ch->ch_num;
4013 }
4014 pr_debug("%s: tx_num %d\n", __func__, i);
4015 *tx_num = i;
4016 break;
4017
4018 default:
4019 pr_err("%s: Invalid DAI ID %x\n", __func__, dai->id);
4020 break;
4021 }
4022
4023 return 0;
4024}
4025
4026static int taiko_set_interpolator_rate(struct snd_soc_dai *dai,
4027 u8 rx_fs_rate_reg_val, u32 compander_fs, u32 sample_rate)
4028{
4029 u32 j;
4030 u8 rx_mix1_inp;
4031 u16 rx_mix_1_reg_1, rx_mix_1_reg_2;
4032 u16 rx_fs_reg;
4033 u8 rx_mix_1_reg_1_val, rx_mix_1_reg_2_val;
4034 struct snd_soc_codec *codec = dai->codec;
4035 struct wcd9xxx_ch *ch;
4036 struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
4037
4038 list_for_each_entry(ch, &taiko->dai[dai->id].wcd9xxx_ch_list, list) {
4039 /* for RX port starting from 16 instead of 10 like tabla */
4040 rx_mix1_inp = ch->port + RX_MIX1_INP_SEL_RX1 -
4041 TAIKO_TX_PORT_NUMBER;
4042 if ((rx_mix1_inp < RX_MIX1_INP_SEL_RX1) ||
4043 (rx_mix1_inp > RX_MIX1_INP_SEL_RX7)) {
4044 pr_err("%s: Invalid TAIKO_RX%u port. Dai ID is %d\n",
4045 __func__, rx_mix1_inp - 5 , dai->id);
4046 return -EINVAL;
4047 }
4048
4049 rx_mix_1_reg_1 = TAIKO_A_CDC_CONN_RX1_B1_CTL;
4050
4051 for (j = 0; j < NUM_INTERPOLATORS; j++) {
4052 rx_mix_1_reg_2 = rx_mix_1_reg_1 + 1;
4053
4054 rx_mix_1_reg_1_val = snd_soc_read(codec,
4055 rx_mix_1_reg_1);
4056 rx_mix_1_reg_2_val = snd_soc_read(codec,
4057 rx_mix_1_reg_2);
4058
4059 if (((rx_mix_1_reg_1_val & 0x0F) == rx_mix1_inp) ||
4060 (((rx_mix_1_reg_1_val >> 4) & 0x0F)
4061 == rx_mix1_inp) ||
4062 ((rx_mix_1_reg_2_val & 0x0F) == rx_mix1_inp)) {
4063
4064 rx_fs_reg = TAIKO_A_CDC_RX1_B5_CTL + 8 * j;
4065
4066 pr_debug("%s: AIF_PB DAI(%d) connected to RX%u\n",
4067 __func__, dai->id, j + 1);
4068
4069 pr_debug("%s: set RX%u sample rate to %u\n",
4070 __func__, j + 1, sample_rate);
4071
4072 snd_soc_update_bits(codec, rx_fs_reg,
4073 0xE0, rx_fs_rate_reg_val);
4074
4075 if (comp_rx_path[j] < COMPANDER_MAX)
4076 taiko->comp_fs[comp_rx_path[j]]
4077 = compander_fs;
4078 }
Kuirong Wang94761952013-03-07 16:19:35 -08004079 if (j < 2)
Kuirong Wang906ac472012-07-09 12:54:44 -07004080 rx_mix_1_reg_1 += 3;
4081 else
4082 rx_mix_1_reg_1 += 2;
Kiran Kandic3b24402012-06-11 00:05:59 -07004083 }
4084 }
4085 return 0;
4086}
4087
Kuirong Wang906ac472012-07-09 12:54:44 -07004088static int taiko_set_decimator_rate(struct snd_soc_dai *dai,
4089 u8 tx_fs_rate_reg_val, u32 sample_rate)
Kiran Kandic3b24402012-06-11 00:05:59 -07004090{
Kuirong Wang906ac472012-07-09 12:54:44 -07004091 struct snd_soc_codec *codec = dai->codec;
4092 struct wcd9xxx_ch *ch;
4093 struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
4094 u32 tx_port;
4095 u16 tx_port_reg, tx_fs_reg;
4096 u8 tx_port_reg_val;
4097 s8 decimator;
Kiran Kandic3b24402012-06-11 00:05:59 -07004098
Kuirong Wang906ac472012-07-09 12:54:44 -07004099 list_for_each_entry(ch, &taiko->dai[dai->id].wcd9xxx_ch_list, list) {
Kiran Kandic3b24402012-06-11 00:05:59 -07004100
Kuirong Wang906ac472012-07-09 12:54:44 -07004101 tx_port = ch->port + 1;
4102 pr_debug("%s: dai->id = %d, tx_port = %d",
4103 __func__, dai->id, tx_port);
4104
4105 if ((tx_port < 1) || (tx_port > NUM_DECIMATORS)) {
4106 pr_err("%s: Invalid SLIM TX%u port. DAI ID is %d\n",
4107 __func__, tx_port, dai->id);
4108 return -EINVAL;
4109 }
4110
4111 tx_port_reg = TAIKO_A_CDC_CONN_TX_SB_B1_CTL + (tx_port - 1);
4112 tx_port_reg_val = snd_soc_read(codec, tx_port_reg);
4113
4114 decimator = 0;
4115
4116 if ((tx_port >= 1) && (tx_port <= 6)) {
4117
4118 tx_port_reg_val = tx_port_reg_val & 0x0F;
4119 if (tx_port_reg_val == 0x8)
4120 decimator = tx_port;
4121
4122 } else if ((tx_port >= 7) && (tx_port <= NUM_DECIMATORS)) {
4123
4124 tx_port_reg_val = tx_port_reg_val & 0x1F;
4125
4126 if ((tx_port_reg_val >= 0x8) &&
4127 (tx_port_reg_val <= 0x11)) {
4128
4129 decimator = (tx_port_reg_val - 0x8) + 1;
4130 }
4131 }
4132
4133 if (decimator) { /* SLIM_TX port has a DEC as input */
4134
4135 tx_fs_reg = TAIKO_A_CDC_TX1_CLK_FS_CTL +
4136 8 * (decimator - 1);
4137
4138 pr_debug("%s: set DEC%u (-> SLIM_TX%u) rate to %u\n",
4139 __func__, decimator, tx_port, sample_rate);
4140
4141 snd_soc_update_bits(codec, tx_fs_reg, 0x07,
4142 tx_fs_rate_reg_val);
4143
4144 } else {
4145 if ((tx_port_reg_val >= 0x1) &&
4146 (tx_port_reg_val <= 0x7)) {
4147
4148 pr_debug("%s: RMIX%u going to SLIM TX%u\n",
4149 __func__, tx_port_reg_val, tx_port);
4150
4151 } else if ((tx_port_reg_val >= 0x8) &&
4152 (tx_port_reg_val <= 0x11)) {
4153
4154 pr_err("%s: ERROR: Should not be here\n",
4155 __func__);
4156 pr_err("%s: ERROR: DEC connected to SLIM TX%u\n",
4157 __func__, tx_port);
4158 return -EINVAL;
4159
4160 } else if (tx_port_reg_val == 0) {
4161 pr_debug("%s: no signal to SLIM TX%u\n",
4162 __func__, tx_port);
4163 } else {
4164 pr_err("%s: ERROR: wrong signal to SLIM TX%u\n",
4165 __func__, tx_port);
4166 pr_err("%s: ERROR: wrong signal = %u\n",
4167 __func__, tx_port_reg_val);
4168 return -EINVAL;
4169 }
4170 }
Kiran Kandic3b24402012-06-11 00:05:59 -07004171 }
Kiran Kandic3b24402012-06-11 00:05:59 -07004172 return 0;
4173}
4174
4175static int taiko_hw_params(struct snd_pcm_substream *substream,
4176 struct snd_pcm_hw_params *params,
4177 struct snd_soc_dai *dai)
4178{
4179 struct snd_soc_codec *codec = dai->codec;
4180 struct taiko_priv *taiko = snd_soc_codec_get_drvdata(dai->codec);
Kuirong Wang906ac472012-07-09 12:54:44 -07004181 u8 tx_fs_rate, rx_fs_rate;
Kiran Kandic3b24402012-06-11 00:05:59 -07004182 u32 compander_fs;
Kuirong Wang906ac472012-07-09 12:54:44 -07004183 int ret;
Kiran Kandic3b24402012-06-11 00:05:59 -07004184
4185 pr_debug("%s: dai_name = %s DAI-ID %x rate %d num_ch %d\n", __func__,
4186 dai->name, dai->id, params_rate(params),
4187 params_channels(params));
4188
4189 switch (params_rate(params)) {
4190 case 8000:
4191 tx_fs_rate = 0x00;
4192 rx_fs_rate = 0x00;
4193 compander_fs = COMPANDER_FS_8KHZ;
4194 break;
4195 case 16000:
4196 tx_fs_rate = 0x01;
4197 rx_fs_rate = 0x20;
4198 compander_fs = COMPANDER_FS_16KHZ;
4199 break;
4200 case 32000:
4201 tx_fs_rate = 0x02;
4202 rx_fs_rate = 0x40;
4203 compander_fs = COMPANDER_FS_32KHZ;
4204 break;
4205 case 48000:
4206 tx_fs_rate = 0x03;
4207 rx_fs_rate = 0x60;
4208 compander_fs = COMPANDER_FS_48KHZ;
4209 break;
4210 case 96000:
4211 tx_fs_rate = 0x04;
4212 rx_fs_rate = 0x80;
4213 compander_fs = COMPANDER_FS_96KHZ;
4214 break;
4215 case 192000:
4216 tx_fs_rate = 0x05;
4217 rx_fs_rate = 0xA0;
4218 compander_fs = COMPANDER_FS_192KHZ;
4219 break;
4220 default:
4221 pr_err("%s: Invalid sampling rate %d\n", __func__,
Kuirong Wang906ac472012-07-09 12:54:44 -07004222 params_rate(params));
Kiran Kandic3b24402012-06-11 00:05:59 -07004223 return -EINVAL;
4224 }
4225
Kuirong Wang906ac472012-07-09 12:54:44 -07004226 switch (substream->stream) {
4227 case SNDRV_PCM_STREAM_CAPTURE:
Gopikrishnaiah Anandana2627572013-02-26 13:30:50 -05004228 if (dai->id != AIF4_VIFEED) {
4229 ret = taiko_set_decimator_rate(dai, tx_fs_rate,
4230 params_rate(params));
4231 if (ret < 0) {
4232 pr_err("%s: set decimator rate failed %d\n",
4233 __func__, ret);
4234 return ret;
4235 }
Kiran Kandic3b24402012-06-11 00:05:59 -07004236 }
Kuirong Wang906ac472012-07-09 12:54:44 -07004237
Kiran Kandic3b24402012-06-11 00:05:59 -07004238 if (taiko->intf_type == WCD9XXX_INTERFACE_TYPE_I2C) {
4239 switch (params_format(params)) {
4240 case SNDRV_PCM_FORMAT_S16_LE:
4241 snd_soc_update_bits(codec,
4242 TAIKO_A_CDC_CLK_TX_I2S_CTL,
4243 0x20, 0x20);
4244 break;
4245 case SNDRV_PCM_FORMAT_S32_LE:
4246 snd_soc_update_bits(codec,
4247 TAIKO_A_CDC_CLK_TX_I2S_CTL,
4248 0x20, 0x00);
4249 break;
4250 default:
4251 pr_err("invalid format\n");
4252 break;
4253 }
4254 snd_soc_update_bits(codec, TAIKO_A_CDC_CLK_TX_I2S_CTL,
Kuirong Wang906ac472012-07-09 12:54:44 -07004255 0x07, tx_fs_rate);
Kiran Kandic3b24402012-06-11 00:05:59 -07004256 } else {
Kuirong Wang906ac472012-07-09 12:54:44 -07004257 taiko->dai[dai->id].rate = params_rate(params);
Kiran Kandic3b24402012-06-11 00:05:59 -07004258 }
Kuirong Wang906ac472012-07-09 12:54:44 -07004259 break;
Kiran Kandic3b24402012-06-11 00:05:59 -07004260
Kuirong Wang906ac472012-07-09 12:54:44 -07004261 case SNDRV_PCM_STREAM_PLAYBACK:
4262 ret = taiko_set_interpolator_rate(dai, rx_fs_rate,
4263 compander_fs,
4264 params_rate(params));
4265 if (ret < 0) {
4266 pr_err("%s: set decimator rate failed %d\n", __func__,
4267 ret);
4268 return ret;
Kiran Kandic3b24402012-06-11 00:05:59 -07004269 }
4270 if (taiko->intf_type == WCD9XXX_INTERFACE_TYPE_I2C) {
4271 switch (params_format(params)) {
4272 case SNDRV_PCM_FORMAT_S16_LE:
4273 snd_soc_update_bits(codec,
4274 TAIKO_A_CDC_CLK_RX_I2S_CTL,
4275 0x20, 0x20);
4276 break;
4277 case SNDRV_PCM_FORMAT_S32_LE:
4278 snd_soc_update_bits(codec,
4279 TAIKO_A_CDC_CLK_RX_I2S_CTL,
4280 0x20, 0x00);
4281 break;
4282 default:
4283 pr_err("invalid format\n");
4284 break;
4285 }
4286 snd_soc_update_bits(codec, TAIKO_A_CDC_CLK_RX_I2S_CTL,
Kuirong Wang906ac472012-07-09 12:54:44 -07004287 0x03, (rx_fs_rate >> 0x05));
Kiran Kandic3b24402012-06-11 00:05:59 -07004288 } else {
Bhalchandra Gajare5b40c532013-02-19 13:36:47 -08004289 switch (params_format(params)) {
4290 case SNDRV_PCM_FORMAT_S16_LE:
4291 snd_soc_update_bits(codec,
4292 TAIKO_A_CDC_CONN_RX_SB_B1_CTL,
4293 0xFF, 0xAA);
4294 snd_soc_update_bits(codec,
4295 TAIKO_A_CDC_CONN_RX_SB_B2_CTL,
4296 0xFF, 0x2A);
4297 taiko->dai[dai->id].bit_width = 16;
4298 break;
4299 case SNDRV_PCM_FORMAT_S24_LE:
4300 snd_soc_update_bits(codec,
4301 TAIKO_A_CDC_CONN_RX_SB_B1_CTL,
4302 0xFF, 0x00);
4303 snd_soc_update_bits(codec,
4304 TAIKO_A_CDC_CONN_RX_SB_B2_CTL,
4305 0xFF, 0x00);
4306 taiko->dai[dai->id].bit_width = 24;
4307 break;
4308 default:
4309 dev_err(codec->dev, "Invalid format\n");
4310 break;
4311 }
Kuirong Wang906ac472012-07-09 12:54:44 -07004312 taiko->dai[dai->id].rate = params_rate(params);
Kiran Kandic3b24402012-06-11 00:05:59 -07004313 }
Kuirong Wang906ac472012-07-09 12:54:44 -07004314 break;
4315 default:
4316 pr_err("%s: Invalid stream type %d\n", __func__,
4317 substream->stream);
4318 return -EINVAL;
Kiran Kandic3b24402012-06-11 00:05:59 -07004319 }
4320
4321 return 0;
4322}
4323
4324static struct snd_soc_dai_ops taiko_dai_ops = {
4325 .startup = taiko_startup,
4326 .shutdown = taiko_shutdown,
4327 .hw_params = taiko_hw_params,
4328 .set_sysclk = taiko_set_dai_sysclk,
4329 .set_fmt = taiko_set_dai_fmt,
4330 .set_channel_map = taiko_set_channel_map,
4331 .get_channel_map = taiko_get_channel_map,
4332};
4333
4334static struct snd_soc_dai_driver taiko_dai[] = {
4335 {
4336 .name = "taiko_rx1",
4337 .id = AIF1_PB,
4338 .playback = {
4339 .stream_name = "AIF1 Playback",
4340 .rates = WCD9320_RATES,
Bhalchandra Gajare5b40c532013-02-19 13:36:47 -08004341 .formats = TAIKO_FORMATS_S16_S24_LE,
Kiran Kandic3b24402012-06-11 00:05:59 -07004342 .rate_max = 192000,
4343 .rate_min = 8000,
4344 .channels_min = 1,
4345 .channels_max = 2,
4346 },
4347 .ops = &taiko_dai_ops,
4348 },
4349 {
4350 .name = "taiko_tx1",
4351 .id = AIF1_CAP,
4352 .capture = {
4353 .stream_name = "AIF1 Capture",
4354 .rates = WCD9320_RATES,
4355 .formats = TAIKO_FORMATS,
4356 .rate_max = 192000,
4357 .rate_min = 8000,
4358 .channels_min = 1,
4359 .channels_max = 4,
4360 },
4361 .ops = &taiko_dai_ops,
4362 },
4363 {
4364 .name = "taiko_rx2",
4365 .id = AIF2_PB,
4366 .playback = {
4367 .stream_name = "AIF2 Playback",
4368 .rates = WCD9320_RATES,
Bhalchandra Gajare5b40c532013-02-19 13:36:47 -08004369 .formats = TAIKO_FORMATS_S16_S24_LE,
Kiran Kandic3b24402012-06-11 00:05:59 -07004370 .rate_min = 8000,
4371 .rate_max = 192000,
4372 .channels_min = 1,
4373 .channels_max = 2,
4374 },
4375 .ops = &taiko_dai_ops,
4376 },
4377 {
4378 .name = "taiko_tx2",
4379 .id = AIF2_CAP,
4380 .capture = {
4381 .stream_name = "AIF2 Capture",
4382 .rates = WCD9320_RATES,
4383 .formats = TAIKO_FORMATS,
4384 .rate_max = 192000,
4385 .rate_min = 8000,
4386 .channels_min = 1,
Baruch Eruchimovitch64eb8da2013-04-08 14:33:17 +03004387 .channels_max = 5,
Kiran Kandic3b24402012-06-11 00:05:59 -07004388 },
4389 .ops = &taiko_dai_ops,
4390 },
4391 {
4392 .name = "taiko_tx3",
4393 .id = AIF3_CAP,
4394 .capture = {
4395 .stream_name = "AIF3 Capture",
4396 .rates = WCD9320_RATES,
4397 .formats = TAIKO_FORMATS,
4398 .rate_max = 48000,
4399 .rate_min = 8000,
4400 .channels_min = 1,
4401 .channels_max = 2,
4402 },
4403 .ops = &taiko_dai_ops,
4404 },
4405 {
4406 .name = "taiko_rx3",
4407 .id = AIF3_PB,
4408 .playback = {
4409 .stream_name = "AIF3 Playback",
4410 .rates = WCD9320_RATES,
Bhalchandra Gajare5b40c532013-02-19 13:36:47 -08004411 .formats = TAIKO_FORMATS_S16_S24_LE,
Kiran Kandic3b24402012-06-11 00:05:59 -07004412 .rate_min = 8000,
4413 .rate_max = 192000,
4414 .channels_min = 1,
4415 .channels_max = 2,
4416 },
4417 .ops = &taiko_dai_ops,
4418 },
Gopikrishnaiah Anandana2627572013-02-26 13:30:50 -05004419 {
4420 .name = "taiko_vifeedback",
4421 .id = AIF4_VIFEED,
4422 .capture = {
4423 .stream_name = "VIfeed",
4424 .rates = SNDRV_PCM_RATE_48000,
4425 .formats = TAIKO_FORMATS,
4426 .rate_max = 48000,
4427 .rate_min = 48000,
4428 .channels_min = 2,
4429 .channels_max = 2,
4430 },
4431 .ops = &taiko_dai_ops,
4432 },
Joonwoo Park1d05bb92013-03-07 16:55:06 -08004433 {
4434 .name = "taiko_mad1",
4435 .id = AIF4_MAD_TX,
4436 .capture = {
4437 .stream_name = "AIF4 MAD TX",
4438 .rates = SNDRV_PCM_RATE_16000,
4439 .formats = TAIKO_FORMATS,
4440 .rate_min = 16000,
4441 .rate_max = 16000,
4442 .channels_min = 1,
4443 .channels_max = 1,
4444 },
4445 .ops = &taiko_dai_ops,
4446 },
Kiran Kandic3b24402012-06-11 00:05:59 -07004447};
4448
4449static struct snd_soc_dai_driver taiko_i2s_dai[] = {
4450 {
4451 .name = "taiko_i2s_rx1",
Kuirong Wang906ac472012-07-09 12:54:44 -07004452 .id = AIF1_PB,
Kiran Kandic3b24402012-06-11 00:05:59 -07004453 .playback = {
4454 .stream_name = "AIF1 Playback",
4455 .rates = WCD9320_RATES,
4456 .formats = TAIKO_FORMATS,
4457 .rate_max = 192000,
4458 .rate_min = 8000,
4459 .channels_min = 1,
4460 .channels_max = 4,
4461 },
4462 .ops = &taiko_dai_ops,
4463 },
4464 {
4465 .name = "taiko_i2s_tx1",
Kuirong Wang906ac472012-07-09 12:54:44 -07004466 .id = AIF1_CAP,
Kiran Kandic3b24402012-06-11 00:05:59 -07004467 .capture = {
4468 .stream_name = "AIF1 Capture",
4469 .rates = WCD9320_RATES,
4470 .formats = TAIKO_FORMATS,
4471 .rate_max = 192000,
4472 .rate_min = 8000,
4473 .channels_min = 1,
4474 .channels_max = 4,
4475 },
4476 .ops = &taiko_dai_ops,
4477 },
Venkat Sudhir994193b2012-12-17 17:30:51 -08004478 {
4479 .name = "taiko_i2s_rx2",
4480 .id = AIF1_PB,
4481 .playback = {
4482 .stream_name = "AIF2 Playback",
4483 .rates = WCD9320_RATES,
4484 .formats = TAIKO_FORMATS,
4485 .rate_max = 192000,
4486 .rate_min = 8000,
4487 .channels_min = 1,
4488 .channels_max = 4,
4489 },
4490 .ops = &taiko_dai_ops,
4491 },
4492 {
4493 .name = "taiko_i2s_tx2",
4494 .id = AIF1_CAP,
4495 .capture = {
4496 .stream_name = "AIF2 Capture",
4497 .rates = WCD9320_RATES,
4498 .formats = TAIKO_FORMATS,
4499 .rate_max = 192000,
4500 .rate_min = 8000,
4501 .channels_min = 1,
4502 .channels_max = 4,
4503 },
4504 .ops = &taiko_dai_ops,
4505 },
Kiran Kandic3b24402012-06-11 00:05:59 -07004506};
4507
Joonwoo Park9bbb4d12012-11-09 19:58:11 -08004508static int taiko_codec_enable_slim_chmask(struct wcd9xxx_codec_dai_data *dai,
4509 bool up)
4510{
4511 int ret = 0;
4512 struct wcd9xxx_ch *ch;
4513
4514 if (up) {
4515 list_for_each_entry(ch, &dai->wcd9xxx_ch_list, list) {
4516 ret = wcd9xxx_get_slave_port(ch->ch_num);
4517 if (ret < 0) {
4518 pr_err("%s: Invalid slave port ID: %d\n",
4519 __func__, ret);
4520 ret = -EINVAL;
4521 } else {
4522 set_bit(ret, &dai->ch_mask);
4523 }
4524 }
4525 } else {
4526 ret = wait_event_timeout(dai->dai_wait, (dai->ch_mask == 0),
4527 msecs_to_jiffies(
4528 TAIKO_SLIM_CLOSE_TIMEOUT));
4529 if (!ret) {
4530 pr_err("%s: Slim close tx/rx wait timeout\n", __func__);
4531 ret = -ETIMEDOUT;
4532 } else {
4533 ret = 0;
4534 }
4535 }
4536 return ret;
4537}
4538
Kiran Kandic3b24402012-06-11 00:05:59 -07004539static int taiko_codec_enable_slimrx(struct snd_soc_dapm_widget *w,
Kuirong Wang906ac472012-07-09 12:54:44 -07004540 struct snd_kcontrol *kcontrol,
4541 int event)
Kiran Kandic3b24402012-06-11 00:05:59 -07004542{
Kuirong Wang906ac472012-07-09 12:54:44 -07004543 struct wcd9xxx *core;
Kiran Kandic3b24402012-06-11 00:05:59 -07004544 struct snd_soc_codec *codec = w->codec;
4545 struct taiko_priv *taiko_p = snd_soc_codec_get_drvdata(codec);
Joonwoo Park9bbb4d12012-11-09 19:58:11 -08004546 int ret = 0;
Kuirong Wang906ac472012-07-09 12:54:44 -07004547 struct wcd9xxx_codec_dai_data *dai;
4548
4549 core = dev_get_drvdata(codec->dev->parent);
4550
4551 pr_debug("%s: event called! codec name %s num_dai %d\n"
4552 "stream name %s event %d\n",
4553 __func__, w->codec->name, w->codec->num_dai, w->sname, event);
4554
Kiran Kandic3b24402012-06-11 00:05:59 -07004555 /* Execute the callback only if interface type is slimbus */
4556 if (taiko_p->intf_type != WCD9XXX_INTERFACE_TYPE_SLIMBUS)
4557 return 0;
4558
Kuirong Wang906ac472012-07-09 12:54:44 -07004559 dai = &taiko_p->dai[w->shift];
4560 pr_debug("%s: w->name %s w->shift %d event %d\n",
4561 __func__, w->name, w->shift, event);
Kiran Kandic3b24402012-06-11 00:05:59 -07004562
4563 switch (event) {
4564 case SND_SOC_DAPM_POST_PMU:
Joonwoo Park9bbb4d12012-11-09 19:58:11 -08004565 (void) taiko_codec_enable_slim_chmask(dai, true);
Kuirong Wang906ac472012-07-09 12:54:44 -07004566 ret = wcd9xxx_cfg_slim_sch_rx(core, &dai->wcd9xxx_ch_list,
4567 dai->rate, dai->bit_width,
4568 &dai->grph);
Kiran Kandic3b24402012-06-11 00:05:59 -07004569 break;
4570 case SND_SOC_DAPM_POST_PMD:
Kuirong Wang906ac472012-07-09 12:54:44 -07004571 ret = wcd9xxx_close_slim_sch_rx(core, &dai->wcd9xxx_ch_list,
4572 dai->grph);
Joonwoo Park9bbb4d12012-11-09 19:58:11 -08004573 ret = taiko_codec_enable_slim_chmask(dai, false);
4574 if (ret < 0) {
4575 ret = wcd9xxx_disconnect_port(core,
4576 &dai->wcd9xxx_ch_list,
4577 dai->grph);
4578 pr_debug("%s: Disconnect RX port, ret = %d\n",
4579 __func__, ret);
4580 }
Kuirong Wang906ac472012-07-09 12:54:44 -07004581 break;
Kiran Kandic3b24402012-06-11 00:05:59 -07004582 }
4583 return ret;
4584}
4585
Gopikrishnaiah Anandana2627572013-02-26 13:30:50 -05004586static int taiko_codec_enable_slimvi_feedback(struct snd_soc_dapm_widget *w,
4587 struct snd_kcontrol *kcontrol,
4588 int event)
4589{
4590 struct wcd9xxx *core = NULL;
4591 struct snd_soc_codec *codec = NULL;
4592 struct taiko_priv *taiko_p = NULL;
4593 u32 ret = 0;
4594 struct wcd9xxx_codec_dai_data *dai = NULL;
4595
4596 if (!w || !w->codec) {
4597 pr_err("%s invalid params\n", __func__);
4598 return -EINVAL;
4599 }
4600 codec = w->codec;
4601 taiko_p = snd_soc_codec_get_drvdata(codec);
4602 core = dev_get_drvdata(codec->dev->parent);
4603
4604 pr_debug("%s: event called! codec name %s num_dai %d stream name %s\n",
4605 __func__, w->codec->name, w->codec->num_dai, w->sname);
4606
4607 /* Execute the callback only if interface type is slimbus */
4608 if (taiko_p->intf_type != WCD9XXX_INTERFACE_TYPE_SLIMBUS) {
4609 pr_err("%s Interface is not correct", __func__);
4610 return 0;
4611 }
4612
4613 pr_debug("%s(): w->name %s event %d w->shift %d\n",
4614 __func__, w->name, event, w->shift);
4615 if (w->shift != AIF4_VIFEED) {
4616 pr_err("%s Error in enabling the tx path\n", __func__);
4617 ret = -EINVAL;
4618 goto out_vi;
4619 }
4620 dai = &taiko_p->dai[w->shift];
4621 switch (event) {
4622 case SND_SOC_DAPM_POST_PMU:
4623 /*Enable Clip Detection*/
4624 snd_soc_update_bits(codec, TAIKO_A_SPKR_DRV_CLIP_DET,
4625 0x8, 0x8);
4626 /*Enable V&I sensing*/
4627 snd_soc_update_bits(codec, TAIKO_A_SPKR_PROT_EN,
4628 0x88, 0x88);
4629 /*Enable spkr VI clocks*/
4630 snd_soc_update_bits(codec,
4631 TAIKO_A_CDC_CLK_TX_CLK_EN_B2_CTL, 0xC, 0xC);
4632 /*Enable Voltage Decimator*/
4633 snd_soc_update_bits(codec,
4634 TAIKO_A_CDC_CONN_TX_SB_B9_CTL, 0x1F, 0x12);
4635 /*Enable Current Decimator*/
4636 snd_soc_update_bits(codec,
4637 TAIKO_A_CDC_CONN_TX_SB_B10_CTL, 0x1F, 0x13);
4638 ret = wcd9xxx_cfg_slim_sch_tx(core, &dai->wcd9xxx_ch_list,
4639 dai->rate, dai->bit_width,
4640 &dai->grph);
4641 break;
4642 case SND_SOC_DAPM_POST_PMD:
4643 ret = wcd9xxx_close_slim_sch_tx(core, &dai->wcd9xxx_ch_list,
4644 dai->grph);
4645 if (ret)
4646 pr_err("%s error in close_slim_sch_tx %d\n",
4647 __func__, ret);
4648 /*Disable Voltage decimator*/
4649 snd_soc_update_bits(codec,
4650 TAIKO_A_CDC_CONN_TX_SB_B9_CTL, 0x1F, 0x0);
4651 /*Disable Current decimator*/
4652 snd_soc_update_bits(codec,
4653 TAIKO_A_CDC_CONN_TX_SB_B10_CTL, 0x1F, 0x0);
4654 /*Disable spkr VI clocks*/
4655 snd_soc_update_bits(codec, TAIKO_A_CDC_CLK_TX_CLK_EN_B2_CTL,
4656 0xC, 0x0);
4657 /*Disable V&I sensing*/
4658 snd_soc_update_bits(codec, TAIKO_A_SPKR_PROT_EN,
4659 0x88, 0x00);
4660 /*Disable clip detection*/
4661 snd_soc_update_bits(codec, TAIKO_A_SPKR_DRV_CLIP_DET,
4662 0x8, 0x0);
4663 break;
4664 }
4665out_vi:
4666 return ret;
4667}
4668
Kiran Kandic3b24402012-06-11 00:05:59 -07004669static int taiko_codec_enable_slimtx(struct snd_soc_dapm_widget *w,
Kuirong Wang906ac472012-07-09 12:54:44 -07004670 struct snd_kcontrol *kcontrol,
4671 int event)
Kiran Kandic3b24402012-06-11 00:05:59 -07004672{
Kuirong Wang906ac472012-07-09 12:54:44 -07004673 struct wcd9xxx *core;
Kiran Kandic3b24402012-06-11 00:05:59 -07004674 struct snd_soc_codec *codec = w->codec;
4675 struct taiko_priv *taiko_p = snd_soc_codec_get_drvdata(codec);
Kiran Kandic3b24402012-06-11 00:05:59 -07004676 u32 ret = 0;
Kuirong Wang906ac472012-07-09 12:54:44 -07004677 struct wcd9xxx_codec_dai_data *dai;
Kiran Kandic3b24402012-06-11 00:05:59 -07004678
Kuirong Wang906ac472012-07-09 12:54:44 -07004679 core = dev_get_drvdata(codec->dev->parent);
4680
4681 pr_debug("%s: event called! codec name %s num_dai %d stream name %s\n",
4682 __func__, w->codec->name, w->codec->num_dai, w->sname);
Kiran Kandic3b24402012-06-11 00:05:59 -07004683
4684 /* Execute the callback only if interface type is slimbus */
4685 if (taiko_p->intf_type != WCD9XXX_INTERFACE_TYPE_SLIMBUS)
4686 return 0;
4687
Kuirong Wang906ac472012-07-09 12:54:44 -07004688 pr_debug("%s(): w->name %s event %d w->shift %d\n",
4689 __func__, w->name, event, w->shift);
Kiran Kandic3b24402012-06-11 00:05:59 -07004690
Kuirong Wang906ac472012-07-09 12:54:44 -07004691 dai = &taiko_p->dai[w->shift];
Kiran Kandic3b24402012-06-11 00:05:59 -07004692 switch (event) {
4693 case SND_SOC_DAPM_POST_PMU:
Joonwoo Park9bbb4d12012-11-09 19:58:11 -08004694 (void) taiko_codec_enable_slim_chmask(dai, true);
Kuirong Wang906ac472012-07-09 12:54:44 -07004695 ret = wcd9xxx_cfg_slim_sch_tx(core, &dai->wcd9xxx_ch_list,
4696 dai->rate, dai->bit_width,
4697 &dai->grph);
Kiran Kandic3b24402012-06-11 00:05:59 -07004698 break;
4699 case SND_SOC_DAPM_POST_PMD:
Kuirong Wang906ac472012-07-09 12:54:44 -07004700 ret = wcd9xxx_close_slim_sch_tx(core, &dai->wcd9xxx_ch_list,
4701 dai->grph);
Joonwoo Park9bbb4d12012-11-09 19:58:11 -08004702 ret = taiko_codec_enable_slim_chmask(dai, false);
4703 if (ret < 0) {
4704 ret = wcd9xxx_disconnect_port(core,
4705 &dai->wcd9xxx_ch_list,
4706 dai->grph);
4707 pr_debug("%s: Disconnect RX port, ret = %d\n",
4708 __func__, ret);
4709 }
Kuirong Wang906ac472012-07-09 12:54:44 -07004710 break;
Kiran Kandic3b24402012-06-11 00:05:59 -07004711 }
4712 return ret;
4713}
4714
Kiran Kandi4c56c592012-07-25 11:04:55 -07004715static int taiko_codec_enable_ear_pa(struct snd_soc_dapm_widget *w,
4716 struct snd_kcontrol *kcontrol, int event)
4717{
4718 struct snd_soc_codec *codec = w->codec;
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08004719 struct taiko_priv *taiko_p = snd_soc_codec_get_drvdata(codec);
Kiran Kandi4c56c592012-07-25 11:04:55 -07004720
4721 pr_debug("%s %s %d\n", __func__, w->name, event);
4722
4723 switch (event) {
Kiran Kandi4c56c592012-07-25 11:04:55 -07004724 case SND_SOC_DAPM_POST_PMU:
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08004725 wcd9xxx_clsh_fsm(codec, &taiko_p->clsh_d,
4726 WCD9XXX_CLSH_STATE_EAR,
4727 WCD9XXX_CLSH_REQ_ENABLE,
4728 WCD9XXX_CLSH_EVENT_POST_PA);
Kiran Kandi4c56c592012-07-25 11:04:55 -07004729
4730 usleep_range(5000, 5000);
4731 break;
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08004732 case SND_SOC_DAPM_POST_PMD:
4733 wcd9xxx_clsh_fsm(codec, &taiko_p->clsh_d,
4734 WCD9XXX_CLSH_STATE_EAR,
4735 WCD9XXX_CLSH_REQ_DISABLE,
4736 WCD9XXX_CLSH_EVENT_POST_PA);
4737 usleep_range(5000, 5000);
4738 }
4739 return 0;
4740}
4741
4742static int taiko_codec_ear_dac_event(struct snd_soc_dapm_widget *w,
4743 struct snd_kcontrol *kcontrol, int event)
4744{
4745 struct snd_soc_codec *codec = w->codec;
4746 struct taiko_priv *taiko_p = snd_soc_codec_get_drvdata(codec);
4747
4748 pr_debug("%s %s %d\n", __func__, w->name, event);
4749
4750 switch (event) {
4751 case SND_SOC_DAPM_PRE_PMU:
4752 wcd9xxx_clsh_fsm(codec, &taiko_p->clsh_d,
4753 WCD9XXX_CLSH_STATE_EAR,
4754 WCD9XXX_CLSH_REQ_ENABLE,
4755 WCD9XXX_CLSH_EVENT_PRE_DAC);
4756 break;
4757 }
4758
4759 return 0;
4760}
4761
4762static int taiko_codec_dsm_mux_event(struct snd_soc_dapm_widget *w,
4763 struct snd_kcontrol *kcontrol, int event)
4764{
4765 struct snd_soc_codec *codec = w->codec;
4766 u8 reg_val, zoh_mux_val = 0x00;
4767
4768 pr_debug("%s: event = %d\n", __func__, event);
4769
4770 switch (event) {
4771 case SND_SOC_DAPM_POST_PMU:
4772 reg_val = snd_soc_read(codec, TAIKO_A_CDC_CONN_CLSH_CTL);
4773
4774 if ((reg_val & 0x30) == 0x10)
4775 zoh_mux_val = 0x04;
4776 else if ((reg_val & 0x30) == 0x20)
4777 zoh_mux_val = 0x08;
4778
4779 if (zoh_mux_val != 0x00)
4780 snd_soc_update_bits(codec,
4781 TAIKO_A_CDC_CONN_CLSH_CTL,
4782 0x0C, zoh_mux_val);
4783 break;
4784
4785 case SND_SOC_DAPM_POST_PMD:
4786 snd_soc_update_bits(codec, TAIKO_A_CDC_CONN_CLSH_CTL,
4787 0x0C, 0x00);
4788 break;
Kiran Kandi4c56c592012-07-25 11:04:55 -07004789 }
4790 return 0;
4791}
4792
Damir Didjusto2cb06bd2013-01-30 23:14:55 -08004793static int taiko_codec_enable_anc_ear(struct snd_soc_dapm_widget *w,
4794 struct snd_kcontrol *kcontrol, int event)
4795{
4796 struct snd_soc_codec *codec = w->codec;
4797 int ret = 0;
4798
4799 switch (event) {
4800 case SND_SOC_DAPM_PRE_PMU:
4801 ret = taiko_codec_enable_anc(w, kcontrol, event);
4802 msleep(50);
4803 snd_soc_update_bits(codec, TAIKO_A_RX_EAR_EN, 0x10, 0x10);
4804 break;
4805 case SND_SOC_DAPM_POST_PMU:
4806 ret = taiko_codec_enable_ear_pa(w, kcontrol, event);
4807 break;
4808 case SND_SOC_DAPM_PRE_PMD:
4809 snd_soc_update_bits(codec, TAIKO_A_RX_EAR_EN, 0x10, 0x00);
4810 msleep(40);
4811 ret |= taiko_codec_enable_anc(w, kcontrol, event);
4812 break;
4813 case SND_SOC_DAPM_POST_PMD:
4814 ret = taiko_codec_enable_ear_pa(w, kcontrol, event);
4815 break;
4816 }
4817 return ret;
4818}
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08004819
Kiran Kandic3b24402012-06-11 00:05:59 -07004820/* Todo: Have seperate dapm widgets for I2S and Slimbus.
4821 * Might Need to have callbacks registered only for slimbus
4822 */
4823static const struct snd_soc_dapm_widget taiko_dapm_widgets[] = {
4824 /*RX stuff */
4825 SND_SOC_DAPM_OUTPUT("EAR"),
4826
Kiran Kandi4c56c592012-07-25 11:04:55 -07004827 SND_SOC_DAPM_PGA_E("EAR PA", TAIKO_A_RX_EAR_EN, 4, 0, NULL, 0,
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08004828 taiko_codec_enable_ear_pa, SND_SOC_DAPM_POST_PMU |
4829 SND_SOC_DAPM_POST_PMD),
Kiran Kandic3b24402012-06-11 00:05:59 -07004830
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08004831 SND_SOC_DAPM_MIXER_E("DAC1", TAIKO_A_RX_EAR_EN, 6, 0, dac1_switch,
4832 ARRAY_SIZE(dac1_switch), taiko_codec_ear_dac_event,
4833 SND_SOC_DAPM_PRE_PMU),
Kiran Kandic3b24402012-06-11 00:05:59 -07004834
Kuirong Wang906ac472012-07-09 12:54:44 -07004835 SND_SOC_DAPM_AIF_IN_E("AIF1 PB", "AIF1 Playback", 0, SND_SOC_NOPM,
4836 AIF1_PB, 0, taiko_codec_enable_slimrx,
Kiran Kandic3b24402012-06-11 00:05:59 -07004837 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
Kuirong Wang906ac472012-07-09 12:54:44 -07004838 SND_SOC_DAPM_AIF_IN_E("AIF2 PB", "AIF2 Playback", 0, SND_SOC_NOPM,
4839 AIF2_PB, 0, taiko_codec_enable_slimrx,
Kiran Kandic3b24402012-06-11 00:05:59 -07004840 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
Kuirong Wang906ac472012-07-09 12:54:44 -07004841 SND_SOC_DAPM_AIF_IN_E("AIF3 PB", "AIF3 Playback", 0, SND_SOC_NOPM,
4842 AIF3_PB, 0, taiko_codec_enable_slimrx,
Kiran Kandic3b24402012-06-11 00:05:59 -07004843 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
4844
Kuirong Wang906ac472012-07-09 12:54:44 -07004845 SND_SOC_DAPM_MUX("SLIM RX1 MUX", SND_SOC_NOPM, TAIKO_RX1, 0,
4846 &slim_rx_mux[TAIKO_RX1]),
4847 SND_SOC_DAPM_MUX("SLIM RX2 MUX", SND_SOC_NOPM, TAIKO_RX2, 0,
4848 &slim_rx_mux[TAIKO_RX2]),
4849 SND_SOC_DAPM_MUX("SLIM RX3 MUX", SND_SOC_NOPM, TAIKO_RX3, 0,
4850 &slim_rx_mux[TAIKO_RX3]),
4851 SND_SOC_DAPM_MUX("SLIM RX4 MUX", SND_SOC_NOPM, TAIKO_RX4, 0,
4852 &slim_rx_mux[TAIKO_RX4]),
4853 SND_SOC_DAPM_MUX("SLIM RX5 MUX", SND_SOC_NOPM, TAIKO_RX5, 0,
4854 &slim_rx_mux[TAIKO_RX5]),
4855 SND_SOC_DAPM_MUX("SLIM RX6 MUX", SND_SOC_NOPM, TAIKO_RX6, 0,
4856 &slim_rx_mux[TAIKO_RX6]),
4857 SND_SOC_DAPM_MUX("SLIM RX7 MUX", SND_SOC_NOPM, TAIKO_RX7, 0,
4858 &slim_rx_mux[TAIKO_RX7]),
Kiran Kandic3b24402012-06-11 00:05:59 -07004859
Kuirong Wang906ac472012-07-09 12:54:44 -07004860 SND_SOC_DAPM_MIXER("SLIM RX1", SND_SOC_NOPM, 0, 0, NULL, 0),
4861 SND_SOC_DAPM_MIXER("SLIM RX2", SND_SOC_NOPM, 0, 0, NULL, 0),
4862 SND_SOC_DAPM_MIXER("SLIM RX3", SND_SOC_NOPM, 0, 0, NULL, 0),
4863 SND_SOC_DAPM_MIXER("SLIM RX4", SND_SOC_NOPM, 0, 0, NULL, 0),
4864 SND_SOC_DAPM_MIXER("SLIM RX5", SND_SOC_NOPM, 0, 0, NULL, 0),
4865 SND_SOC_DAPM_MIXER("SLIM RX6", SND_SOC_NOPM, 0, 0, NULL, 0),
4866 SND_SOC_DAPM_MIXER("SLIM RX7", SND_SOC_NOPM, 0, 0, NULL, 0),
Kiran Kandic3b24402012-06-11 00:05:59 -07004867
4868 /* Headphone */
4869 SND_SOC_DAPM_OUTPUT("HEADPHONE"),
4870 SND_SOC_DAPM_PGA_E("HPHL", TAIKO_A_RX_HPH_CNP_EN, 5, 0, NULL, 0,
4871 taiko_hph_pa_event, SND_SOC_DAPM_PRE_PMU |
Kiran Kandi4c56c592012-07-25 11:04:55 -07004872 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08004873 SND_SOC_DAPM_MIXER_E("HPHL DAC", TAIKO_A_RX_HPH_L_DAC_CTL, 7, 0,
4874 hphl_switch, ARRAY_SIZE(hphl_switch), taiko_hphl_dac_event,
4875 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
Kiran Kandic3b24402012-06-11 00:05:59 -07004876
4877 SND_SOC_DAPM_PGA_E("HPHR", TAIKO_A_RX_HPH_CNP_EN, 4, 0, NULL, 0,
4878 taiko_hph_pa_event, SND_SOC_DAPM_PRE_PMU |
Kiran Kandi4c56c592012-07-25 11:04:55 -07004879 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
Kiran Kandic3b24402012-06-11 00:05:59 -07004880
4881 SND_SOC_DAPM_DAC_E("HPHR DAC", NULL, TAIKO_A_RX_HPH_R_DAC_CTL, 7, 0,
4882 taiko_hphr_dac_event,
4883 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
4884
4885 /* Speaker */
4886 SND_SOC_DAPM_OUTPUT("LINEOUT1"),
4887 SND_SOC_DAPM_OUTPUT("LINEOUT2"),
4888 SND_SOC_DAPM_OUTPUT("LINEOUT3"),
4889 SND_SOC_DAPM_OUTPUT("LINEOUT4"),
Joonwoo Park7680b9f2012-07-13 11:36:48 -07004890 SND_SOC_DAPM_OUTPUT("SPK_OUT"),
Kiran Kandic3b24402012-06-11 00:05:59 -07004891
4892 SND_SOC_DAPM_PGA_E("LINEOUT1 PA", TAIKO_A_RX_LINE_CNP_EN, 0, 0, NULL,
4893 0, taiko_codec_enable_lineout, SND_SOC_DAPM_PRE_PMU |
4894 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
4895 SND_SOC_DAPM_PGA_E("LINEOUT2 PA", TAIKO_A_RX_LINE_CNP_EN, 1, 0, NULL,
4896 0, taiko_codec_enable_lineout, SND_SOC_DAPM_PRE_PMU |
4897 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
4898 SND_SOC_DAPM_PGA_E("LINEOUT3 PA", TAIKO_A_RX_LINE_CNP_EN, 2, 0, NULL,
4899 0, taiko_codec_enable_lineout, SND_SOC_DAPM_PRE_PMU |
4900 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
4901 SND_SOC_DAPM_PGA_E("LINEOUT4 PA", TAIKO_A_RX_LINE_CNP_EN, 3, 0, NULL,
4902 0, taiko_codec_enable_lineout, SND_SOC_DAPM_PRE_PMU |
4903 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
Joonwoo Park125cd4e2012-12-11 15:16:11 -08004904 SND_SOC_DAPM_PGA_E("SPK PA", SND_SOC_NOPM, 0, 0 , NULL,
4905 0, taiko_codec_enable_spk_pa,
4906 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
Kiran Kandic3b24402012-06-11 00:05:59 -07004907
4908 SND_SOC_DAPM_DAC_E("LINEOUT1 DAC", NULL, TAIKO_A_RX_LINE_1_DAC_CTL, 7, 0
4909 , taiko_lineout_dac_event,
4910 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
4911 SND_SOC_DAPM_DAC_E("LINEOUT2 DAC", NULL, TAIKO_A_RX_LINE_2_DAC_CTL, 7, 0
4912 , taiko_lineout_dac_event,
4913 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
4914 SND_SOC_DAPM_DAC_E("LINEOUT3 DAC", NULL, TAIKO_A_RX_LINE_3_DAC_CTL, 7, 0
4915 , taiko_lineout_dac_event,
4916 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
4917 SND_SOC_DAPM_SWITCH("LINEOUT3 DAC GROUND", SND_SOC_NOPM, 0, 0,
4918 &lineout3_ground_switch),
4919 SND_SOC_DAPM_DAC_E("LINEOUT4 DAC", NULL, TAIKO_A_RX_LINE_4_DAC_CTL, 7, 0
4920 , taiko_lineout_dac_event,
4921 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
4922 SND_SOC_DAPM_SWITCH("LINEOUT4 DAC GROUND", SND_SOC_NOPM, 0, 0,
4923 &lineout4_ground_switch),
4924
Joonwoo Park7680b9f2012-07-13 11:36:48 -07004925 SND_SOC_DAPM_DAC_E("SPK DAC", NULL, SND_SOC_NOPM, 0, 0,
4926 taiko_spk_dac_event,
4927 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
4928
Joonwoo Park125cd4e2012-12-11 15:16:11 -08004929 SND_SOC_DAPM_SUPPLY("VDD_SPKDRV", SND_SOC_NOPM, 0, 0,
4930 taiko_codec_enable_vdd_spkr,
4931 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
4932
Kiran Kandid2b46332012-10-05 12:04:00 -07004933 SND_SOC_DAPM_MIXER("RX1 MIX1", SND_SOC_NOPM, 0, 0, NULL, 0),
4934 SND_SOC_DAPM_MIXER("RX2 MIX1", SND_SOC_NOPM, 0, 0, NULL, 0),
4935 SND_SOC_DAPM_MIXER("RX7 MIX1", SND_SOC_NOPM, 0, 0, NULL, 0),
4936
Kiran Kandic3b24402012-06-11 00:05:59 -07004937 SND_SOC_DAPM_MIXER_E("RX1 MIX2", TAIKO_A_CDC_CLK_RX_B1_CTL, 0, 0, NULL,
Kiran Kandi7b7d2ff2012-09-14 14:52:14 -07004938 0, taiko_codec_enable_interpolator, SND_SOC_DAPM_PRE_PMU |
Kiran Kandic3b24402012-06-11 00:05:59 -07004939 SND_SOC_DAPM_POST_PMU),
4940 SND_SOC_DAPM_MIXER_E("RX2 MIX2", TAIKO_A_CDC_CLK_RX_B1_CTL, 1, 0, NULL,
Kiran Kandi7b7d2ff2012-09-14 14:52:14 -07004941 0, taiko_codec_enable_interpolator, SND_SOC_DAPM_PRE_PMU |
Kiran Kandic3b24402012-06-11 00:05:59 -07004942 SND_SOC_DAPM_POST_PMU),
Kiran Kandid2b46332012-10-05 12:04:00 -07004943 SND_SOC_DAPM_MIXER_E("RX3 MIX1", TAIKO_A_CDC_CLK_RX_B1_CTL, 2, 0, NULL,
Kiran Kandi7b7d2ff2012-09-14 14:52:14 -07004944 0, taiko_codec_enable_interpolator, SND_SOC_DAPM_PRE_PMU |
Kiran Kandic3b24402012-06-11 00:05:59 -07004945 SND_SOC_DAPM_POST_PMU),
4946 SND_SOC_DAPM_MIXER_E("RX4 MIX1", TAIKO_A_CDC_CLK_RX_B1_CTL, 3, 0, NULL,
Kiran Kandi7b7d2ff2012-09-14 14:52:14 -07004947 0, taiko_codec_enable_interpolator, SND_SOC_DAPM_PRE_PMU |
Kiran Kandic3b24402012-06-11 00:05:59 -07004948 SND_SOC_DAPM_POST_PMU),
4949 SND_SOC_DAPM_MIXER_E("RX5 MIX1", TAIKO_A_CDC_CLK_RX_B1_CTL, 4, 0, NULL,
Kiran Kandi7b7d2ff2012-09-14 14:52:14 -07004950 0, taiko_codec_enable_interpolator, SND_SOC_DAPM_PRE_PMU |
Kiran Kandic3b24402012-06-11 00:05:59 -07004951 SND_SOC_DAPM_POST_PMU),
4952 SND_SOC_DAPM_MIXER_E("RX6 MIX1", TAIKO_A_CDC_CLK_RX_B1_CTL, 5, 0, NULL,
Kiran Kandi7b7d2ff2012-09-14 14:52:14 -07004953 0, taiko_codec_enable_interpolator, SND_SOC_DAPM_PRE_PMU |
Kiran Kandic3b24402012-06-11 00:05:59 -07004954 SND_SOC_DAPM_POST_PMU),
Kiran Kandid2b46332012-10-05 12:04:00 -07004955 SND_SOC_DAPM_MIXER_E("RX7 MIX2", TAIKO_A_CDC_CLK_RX_B1_CTL, 6, 0, NULL,
Kiran Kandi7b7d2ff2012-09-14 14:52:14 -07004956 0, taiko_codec_enable_interpolator, SND_SOC_DAPM_PRE_PMU |
Kiran Kandic3b24402012-06-11 00:05:59 -07004957 SND_SOC_DAPM_POST_PMU),
4958
Kiran Kandic3b24402012-06-11 00:05:59 -07004959
4960 SND_SOC_DAPM_MIXER("RX1 CHAIN", TAIKO_A_CDC_RX1_B6_CTL, 5, 0, NULL, 0),
4961 SND_SOC_DAPM_MIXER("RX2 CHAIN", TAIKO_A_CDC_RX2_B6_CTL, 5, 0, NULL, 0),
4962
4963 SND_SOC_DAPM_MUX("RX1 MIX1 INP1", SND_SOC_NOPM, 0, 0,
4964 &rx_mix1_inp1_mux),
4965 SND_SOC_DAPM_MUX("RX1 MIX1 INP2", SND_SOC_NOPM, 0, 0,
4966 &rx_mix1_inp2_mux),
4967 SND_SOC_DAPM_MUX("RX1 MIX1 INP3", SND_SOC_NOPM, 0, 0,
4968 &rx_mix1_inp3_mux),
4969 SND_SOC_DAPM_MUX("RX2 MIX1 INP1", SND_SOC_NOPM, 0, 0,
4970 &rx2_mix1_inp1_mux),
4971 SND_SOC_DAPM_MUX("RX2 MIX1 INP2", SND_SOC_NOPM, 0, 0,
4972 &rx2_mix1_inp2_mux),
4973 SND_SOC_DAPM_MUX("RX3 MIX1 INP1", SND_SOC_NOPM, 0, 0,
4974 &rx3_mix1_inp1_mux),
4975 SND_SOC_DAPM_MUX("RX3 MIX1 INP2", SND_SOC_NOPM, 0, 0,
4976 &rx3_mix1_inp2_mux),
4977 SND_SOC_DAPM_MUX("RX4 MIX1 INP1", SND_SOC_NOPM, 0, 0,
4978 &rx4_mix1_inp1_mux),
4979 SND_SOC_DAPM_MUX("RX4 MIX1 INP2", SND_SOC_NOPM, 0, 0,
4980 &rx4_mix1_inp2_mux),
4981 SND_SOC_DAPM_MUX("RX5 MIX1 INP1", SND_SOC_NOPM, 0, 0,
4982 &rx5_mix1_inp1_mux),
4983 SND_SOC_DAPM_MUX("RX5 MIX1 INP2", SND_SOC_NOPM, 0, 0,
4984 &rx5_mix1_inp2_mux),
4985 SND_SOC_DAPM_MUX("RX6 MIX1 INP1", SND_SOC_NOPM, 0, 0,
4986 &rx6_mix1_inp1_mux),
4987 SND_SOC_DAPM_MUX("RX6 MIX1 INP2", SND_SOC_NOPM, 0, 0,
4988 &rx6_mix1_inp2_mux),
4989 SND_SOC_DAPM_MUX("RX7 MIX1 INP1", SND_SOC_NOPM, 0, 0,
4990 &rx7_mix1_inp1_mux),
4991 SND_SOC_DAPM_MUX("RX7 MIX1 INP2", SND_SOC_NOPM, 0, 0,
4992 &rx7_mix1_inp2_mux),
4993 SND_SOC_DAPM_MUX("RX1 MIX2 INP1", SND_SOC_NOPM, 0, 0,
4994 &rx1_mix2_inp1_mux),
4995 SND_SOC_DAPM_MUX("RX1 MIX2 INP2", SND_SOC_NOPM, 0, 0,
4996 &rx1_mix2_inp2_mux),
4997 SND_SOC_DAPM_MUX("RX2 MIX2 INP1", SND_SOC_NOPM, 0, 0,
4998 &rx2_mix2_inp1_mux),
4999 SND_SOC_DAPM_MUX("RX2 MIX2 INP2", SND_SOC_NOPM, 0, 0,
5000 &rx2_mix2_inp2_mux),
5001 SND_SOC_DAPM_MUX("RX7 MIX2 INP1", SND_SOC_NOPM, 0, 0,
5002 &rx7_mix2_inp1_mux),
5003 SND_SOC_DAPM_MUX("RX7 MIX2 INP2", SND_SOC_NOPM, 0, 0,
5004 &rx7_mix2_inp2_mux),
5005
Tanya Finkeldaaa6d12012-10-25 11:22:48 +02005006 SND_SOC_DAPM_MUX("RDAC5 MUX", SND_SOC_NOPM, 0, 0,
5007 &rx_dac5_mux),
5008 SND_SOC_DAPM_MUX("RDAC7 MUX", SND_SOC_NOPM, 0, 0,
5009 &rx_dac7_mux),
5010
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08005011 SND_SOC_DAPM_MUX_E("CLASS_H_DSM MUX", SND_SOC_NOPM, 0, 0,
5012 &class_h_dsm_mux, taiko_codec_dsm_mux_event,
5013 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
Kiran Kandi4c56c592012-07-25 11:04:55 -07005014
Kiran Kandic3b24402012-06-11 00:05:59 -07005015 SND_SOC_DAPM_SUPPLY("RX_BIAS", SND_SOC_NOPM, 0, 0,
5016 taiko_codec_enable_rx_bias, SND_SOC_DAPM_PRE_PMU |
5017 SND_SOC_DAPM_POST_PMD),
5018
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08005019 SND_SOC_DAPM_SUPPLY("CDC_I2S_RX_CONN", WCD9XXX_A_CDC_CLK_OTHR_CTL, 5, 0,
Joonwoo Park559a5bf2013-02-15 14:46:36 -08005020 NULL, 0),
5021
Kiran Kandic3b24402012-06-11 00:05:59 -07005022 /* TX */
5023
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08005024 SND_SOC_DAPM_SUPPLY("CDC_CONN", WCD9XXX_A_CDC_CLK_OTHR_CTL, 2, 0, NULL,
Kiran Kandic3b24402012-06-11 00:05:59 -07005025 0),
5026
5027 SND_SOC_DAPM_SUPPLY("LDO_H", TAIKO_A_LDO_H_MODE_1, 7, 0,
5028 taiko_codec_enable_ldo_h, SND_SOC_DAPM_POST_PMU),
5029
Joonwoo Parkc7731432012-10-17 12:41:44 -07005030 SND_SOC_DAPM_SUPPLY("COMP0_CLK", SND_SOC_NOPM, 0, 0,
Kiran Kandic3b24402012-06-11 00:05:59 -07005031 taiko_config_compander, SND_SOC_DAPM_PRE_PMU |
Bhalchandra Gajareed090e62013-03-29 16:11:49 -07005032 SND_SOC_DAPM_PRE_PMD),
Joonwoo Parkc7731432012-10-17 12:41:44 -07005033 SND_SOC_DAPM_SUPPLY("COMP1_CLK", SND_SOC_NOPM, 1, 0,
5034 taiko_config_compander, SND_SOC_DAPM_PRE_PMU |
Bhalchandra Gajareed090e62013-03-29 16:11:49 -07005035 SND_SOC_DAPM_PRE_PMD),
Joonwoo Parkc7731432012-10-17 12:41:44 -07005036 SND_SOC_DAPM_SUPPLY("COMP2_CLK", SND_SOC_NOPM, 2, 0,
Kiran Kandic3b24402012-06-11 00:05:59 -07005037 taiko_config_compander, SND_SOC_DAPM_PRE_PMU |
Bhalchandra Gajareed090e62013-03-29 16:11:49 -07005038 SND_SOC_DAPM_PRE_PMD),
Kiran Kandic3b24402012-06-11 00:05:59 -07005039
5040
5041 SND_SOC_DAPM_INPUT("AMIC1"),
Joonwoo Park3699ca32013-02-08 12:06:15 -08005042 SND_SOC_DAPM_MICBIAS_E("MIC BIAS1 External", SND_SOC_NOPM, 7, 0,
5043 taiko_codec_enable_micbias,
5044 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
5045 SND_SOC_DAPM_POST_PMD),
5046 SND_SOC_DAPM_MICBIAS_E("MIC BIAS1 Internal1", SND_SOC_NOPM, 7, 0,
5047 taiko_codec_enable_micbias,
5048 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
5049 SND_SOC_DAPM_POST_PMD),
5050 SND_SOC_DAPM_MICBIAS_E("MIC BIAS1 Internal2", SND_SOC_NOPM, 7, 0,
5051 taiko_codec_enable_micbias,
5052 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
5053 SND_SOC_DAPM_POST_PMD),
Kiran Kandic3b24402012-06-11 00:05:59 -07005054
5055 SND_SOC_DAPM_INPUT("AMIC3"),
Kiran Kandic3b24402012-06-11 00:05:59 -07005056
5057 SND_SOC_DAPM_INPUT("AMIC4"),
Kiran Kandic3b24402012-06-11 00:05:59 -07005058
5059 SND_SOC_DAPM_INPUT("AMIC5"),
Kiran Kandic3b24402012-06-11 00:05:59 -07005060
5061 SND_SOC_DAPM_INPUT("AMIC6"),
Kiran Kandic3b24402012-06-11 00:05:59 -07005062
5063 SND_SOC_DAPM_MUX_E("DEC1 MUX", TAIKO_A_CDC_CLK_TX_CLK_EN_B1_CTL, 0, 0,
5064 &dec1_mux, taiko_codec_enable_dec,
5065 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
5066 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
5067
5068 SND_SOC_DAPM_MUX_E("DEC2 MUX", TAIKO_A_CDC_CLK_TX_CLK_EN_B1_CTL, 1, 0,
5069 &dec2_mux, taiko_codec_enable_dec,
5070 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
5071 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
5072
5073 SND_SOC_DAPM_MUX_E("DEC3 MUX", TAIKO_A_CDC_CLK_TX_CLK_EN_B1_CTL, 2, 0,
5074 &dec3_mux, taiko_codec_enable_dec,
5075 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
5076 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
5077
5078 SND_SOC_DAPM_MUX_E("DEC4 MUX", TAIKO_A_CDC_CLK_TX_CLK_EN_B1_CTL, 3, 0,
5079 &dec4_mux, taiko_codec_enable_dec,
5080 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
5081 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
5082
5083 SND_SOC_DAPM_MUX_E("DEC5 MUX", TAIKO_A_CDC_CLK_TX_CLK_EN_B1_CTL, 4, 0,
5084 &dec5_mux, taiko_codec_enable_dec,
5085 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
5086 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
5087
5088 SND_SOC_DAPM_MUX_E("DEC6 MUX", TAIKO_A_CDC_CLK_TX_CLK_EN_B1_CTL, 5, 0,
5089 &dec6_mux, taiko_codec_enable_dec,
5090 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
5091 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
5092
5093 SND_SOC_DAPM_MUX_E("DEC7 MUX", TAIKO_A_CDC_CLK_TX_CLK_EN_B1_CTL, 6, 0,
5094 &dec7_mux, taiko_codec_enable_dec,
5095 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
5096 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
5097
5098 SND_SOC_DAPM_MUX_E("DEC8 MUX", TAIKO_A_CDC_CLK_TX_CLK_EN_B1_CTL, 7, 0,
5099 &dec8_mux, taiko_codec_enable_dec,
5100 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
5101 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
5102
5103 SND_SOC_DAPM_MUX_E("DEC9 MUX", TAIKO_A_CDC_CLK_TX_CLK_EN_B2_CTL, 0, 0,
5104 &dec9_mux, taiko_codec_enable_dec,
5105 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
5106 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
5107
5108 SND_SOC_DAPM_MUX_E("DEC10 MUX", TAIKO_A_CDC_CLK_TX_CLK_EN_B2_CTL, 1, 0,
5109 &dec10_mux, taiko_codec_enable_dec,
5110 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
5111 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
5112
5113 SND_SOC_DAPM_MUX("ANC1 MUX", SND_SOC_NOPM, 0, 0, &anc1_mux),
5114 SND_SOC_DAPM_MUX("ANC2 MUX", SND_SOC_NOPM, 0, 0, &anc2_mux),
5115
Damir Didjusto2cb06bd2013-01-30 23:14:55 -08005116 SND_SOC_DAPM_OUTPUT("ANC HEADPHONE"),
5117 SND_SOC_DAPM_PGA_E("ANC HPHL", SND_SOC_NOPM, 5, 0, NULL, 0,
5118 taiko_codec_enable_anc_hph,
5119 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD |
5120 SND_SOC_DAPM_POST_PMD | SND_SOC_DAPM_POST_PMU),
5121 SND_SOC_DAPM_PGA_E("ANC HPHR", SND_SOC_NOPM, 4, 0, NULL, 0,
5122 taiko_codec_enable_anc_hph, SND_SOC_DAPM_PRE_PMU |
5123 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD |
5124 SND_SOC_DAPM_POST_PMU),
5125 SND_SOC_DAPM_OUTPUT("ANC EAR"),
5126 SND_SOC_DAPM_PGA_E("ANC EAR PA", SND_SOC_NOPM, 0, 0, NULL, 0,
5127 taiko_codec_enable_anc_ear,
5128 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD |
5129 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
Kiran Kandic3b24402012-06-11 00:05:59 -07005130 SND_SOC_DAPM_MUX("ANC1 FB MUX", SND_SOC_NOPM, 0, 0, &anc1_fb_mux),
5131
5132 SND_SOC_DAPM_INPUT("AMIC2"),
Joonwoo Park3699ca32013-02-08 12:06:15 -08005133 SND_SOC_DAPM_MICBIAS_E("MIC BIAS2 External", SND_SOC_NOPM, 7, 0,
5134 taiko_codec_enable_micbias,
5135 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
5136 SND_SOC_DAPM_POST_PMD),
5137 SND_SOC_DAPM_MICBIAS_E("MIC BIAS2 Internal1", SND_SOC_NOPM, 7, 0,
5138 taiko_codec_enable_micbias,
5139 SND_SOC_DAPM_PRE_PMU |
5140 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
5141 SND_SOC_DAPM_MICBIAS_E("MIC BIAS2 Internal2", SND_SOC_NOPM, 7, 0,
5142 taiko_codec_enable_micbias,
5143 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
5144 SND_SOC_DAPM_POST_PMD),
5145 SND_SOC_DAPM_MICBIAS_E("MIC BIAS2 Internal3", SND_SOC_NOPM, 7, 0,
5146 taiko_codec_enable_micbias,
5147 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
5148 SND_SOC_DAPM_POST_PMD),
5149 SND_SOC_DAPM_MICBIAS_E("MIC BIAS3 External", SND_SOC_NOPM, 7, 0,
5150 taiko_codec_enable_micbias,
5151 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
5152 SND_SOC_DAPM_POST_PMD),
5153 SND_SOC_DAPM_MICBIAS_E("MIC BIAS3 Internal1", SND_SOC_NOPM, 7, 0,
5154 taiko_codec_enable_micbias,
5155 SND_SOC_DAPM_PRE_PMU |
5156 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
5157 SND_SOC_DAPM_MICBIAS_E("MIC BIAS3 Internal2", SND_SOC_NOPM, 7, 0,
5158 taiko_codec_enable_micbias,
5159 SND_SOC_DAPM_PRE_PMU |
5160 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
5161 SND_SOC_DAPM_MICBIAS_E("MIC BIAS4 External", SND_SOC_NOPM, 7,
5162 0, taiko_codec_enable_micbias,
5163 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
5164 SND_SOC_DAPM_POST_PMD),
Kiran Kandic3b24402012-06-11 00:05:59 -07005165
Kuirong Wang906ac472012-07-09 12:54:44 -07005166 SND_SOC_DAPM_AIF_OUT_E("AIF1 CAP", "AIF1 Capture", 0, SND_SOC_NOPM,
5167 AIF1_CAP, 0, taiko_codec_enable_slimtx,
5168 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
Kiran Kandic3b24402012-06-11 00:05:59 -07005169
Kuirong Wang906ac472012-07-09 12:54:44 -07005170 SND_SOC_DAPM_AIF_OUT_E("AIF2 CAP", "AIF2 Capture", 0, SND_SOC_NOPM,
5171 AIF2_CAP, 0, taiko_codec_enable_slimtx,
5172 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
Kiran Kandic3b24402012-06-11 00:05:59 -07005173
Kuirong Wang906ac472012-07-09 12:54:44 -07005174 SND_SOC_DAPM_AIF_OUT_E("AIF3 CAP", "AIF3 Capture", 0, SND_SOC_NOPM,
5175 AIF3_CAP, 0, taiko_codec_enable_slimtx,
5176 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
Kiran Kandic3b24402012-06-11 00:05:59 -07005177
Gopikrishnaiah Anandana2627572013-02-26 13:30:50 -05005178 SND_SOC_DAPM_AIF_OUT_E("AIF4 VI", "VIfeed", 0, SND_SOC_NOPM,
5179 AIF4_VIFEED, 0, taiko_codec_enable_slimvi_feedback,
5180 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
Joonwoo Park1d05bb92013-03-07 16:55:06 -08005181 SND_SOC_DAPM_AIF_OUT_E("AIF4 MAD", "AIF4 MAD TX", 0,
Joonwoo Park9ead0e92013-03-18 11:33:33 -07005182 SND_SOC_NOPM, 0, 0,
Joonwoo Park1d05bb92013-03-07 16:55:06 -08005183 taiko_codec_enable_mad, SND_SOC_DAPM_PRE_PMU),
Joonwoo Park9ead0e92013-03-18 11:33:33 -07005184 SND_SOC_DAPM_SWITCH("MADONOFF", SND_SOC_NOPM, 0, 0,
5185 &aif4_mad_switch),
Joonwoo Park1d05bb92013-03-07 16:55:06 -08005186 SND_SOC_DAPM_INPUT("MADINPUT"),
Gopikrishnaiah Anandana2627572013-02-26 13:30:50 -05005187
Kuirong Wang906ac472012-07-09 12:54:44 -07005188 SND_SOC_DAPM_MIXER("AIF1_CAP Mixer", SND_SOC_NOPM, AIF1_CAP, 0,
5189 aif_cap_mixer, ARRAY_SIZE(aif_cap_mixer)),
Kiran Kandic3b24402012-06-11 00:05:59 -07005190
Kuirong Wang906ac472012-07-09 12:54:44 -07005191 SND_SOC_DAPM_MIXER("AIF2_CAP Mixer", SND_SOC_NOPM, AIF2_CAP, 0,
5192 aif_cap_mixer, ARRAY_SIZE(aif_cap_mixer)),
Kiran Kandic3b24402012-06-11 00:05:59 -07005193
Kuirong Wang906ac472012-07-09 12:54:44 -07005194 SND_SOC_DAPM_MIXER("AIF3_CAP Mixer", SND_SOC_NOPM, AIF3_CAP, 0,
5195 aif_cap_mixer, ARRAY_SIZE(aif_cap_mixer)),
Kiran Kandic3b24402012-06-11 00:05:59 -07005196
Kuirong Wang906ac472012-07-09 12:54:44 -07005197 SND_SOC_DAPM_MUX("SLIM TX1 MUX", SND_SOC_NOPM, TAIKO_TX1, 0,
5198 &sb_tx1_mux),
5199 SND_SOC_DAPM_MUX("SLIM TX2 MUX", SND_SOC_NOPM, TAIKO_TX2, 0,
5200 &sb_tx2_mux),
5201 SND_SOC_DAPM_MUX("SLIM TX3 MUX", SND_SOC_NOPM, TAIKO_TX3, 0,
5202 &sb_tx3_mux),
5203 SND_SOC_DAPM_MUX("SLIM TX4 MUX", SND_SOC_NOPM, TAIKO_TX4, 0,
5204 &sb_tx4_mux),
5205 SND_SOC_DAPM_MUX("SLIM TX5 MUX", SND_SOC_NOPM, TAIKO_TX5, 0,
5206 &sb_tx5_mux),
5207 SND_SOC_DAPM_MUX("SLIM TX6 MUX", SND_SOC_NOPM, TAIKO_TX6, 0,
5208 &sb_tx6_mux),
5209 SND_SOC_DAPM_MUX("SLIM TX7 MUX", SND_SOC_NOPM, TAIKO_TX7, 0,
5210 &sb_tx7_mux),
5211 SND_SOC_DAPM_MUX("SLIM TX8 MUX", SND_SOC_NOPM, TAIKO_TX8, 0,
5212 &sb_tx8_mux),
5213 SND_SOC_DAPM_MUX("SLIM TX9 MUX", SND_SOC_NOPM, TAIKO_TX9, 0,
5214 &sb_tx9_mux),
5215 SND_SOC_DAPM_MUX("SLIM TX10 MUX", SND_SOC_NOPM, TAIKO_TX10, 0,
5216 &sb_tx10_mux),
Kiran Kandic3b24402012-06-11 00:05:59 -07005217
5218 /* Digital Mic Inputs */
5219 SND_SOC_DAPM_ADC_E("DMIC1", NULL, SND_SOC_NOPM, 0, 0,
5220 taiko_codec_enable_dmic, SND_SOC_DAPM_PRE_PMU |
5221 SND_SOC_DAPM_POST_PMD),
5222
5223 SND_SOC_DAPM_ADC_E("DMIC2", NULL, SND_SOC_NOPM, 0, 0,
5224 taiko_codec_enable_dmic, SND_SOC_DAPM_PRE_PMU |
5225 SND_SOC_DAPM_POST_PMD),
5226
5227 SND_SOC_DAPM_ADC_E("DMIC3", NULL, SND_SOC_NOPM, 0, 0,
5228 taiko_codec_enable_dmic, SND_SOC_DAPM_PRE_PMU |
5229 SND_SOC_DAPM_POST_PMD),
5230
5231 SND_SOC_DAPM_ADC_E("DMIC4", NULL, SND_SOC_NOPM, 0, 0,
5232 taiko_codec_enable_dmic, SND_SOC_DAPM_PRE_PMU |
5233 SND_SOC_DAPM_POST_PMD),
5234
5235 SND_SOC_DAPM_ADC_E("DMIC5", NULL, SND_SOC_NOPM, 0, 0,
5236 taiko_codec_enable_dmic, SND_SOC_DAPM_PRE_PMU |
5237 SND_SOC_DAPM_POST_PMD),
5238 SND_SOC_DAPM_ADC_E("DMIC6", NULL, SND_SOC_NOPM, 0, 0,
5239 taiko_codec_enable_dmic, SND_SOC_DAPM_PRE_PMU |
5240 SND_SOC_DAPM_POST_PMD),
5241
5242 /* Sidetone */
5243 SND_SOC_DAPM_MUX("IIR1 INP1 MUX", SND_SOC_NOPM, 0, 0, &iir1_inp1_mux),
5244 SND_SOC_DAPM_PGA("IIR1", TAIKO_A_CDC_CLK_SD_CTL, 0, 0, NULL, 0),
5245
Fred Oh456fcb52013-02-28 19:08:15 -08005246 SND_SOC_DAPM_MUX("IIR2 INP1 MUX", SND_SOC_NOPM, 0, 0, &iir2_inp1_mux),
5247 SND_SOC_DAPM_PGA("IIR2", TAIKO_A_CDC_CLK_SD_CTL, 1, 0, NULL, 0),
5248
Kiran Kandic3b24402012-06-11 00:05:59 -07005249 /* AUX PGA */
5250 SND_SOC_DAPM_ADC_E("AUX_PGA_Left", NULL, TAIKO_A_RX_AUX_SW_CTL, 7, 0,
5251 taiko_codec_enable_aux_pga, SND_SOC_DAPM_PRE_PMU |
5252 SND_SOC_DAPM_POST_PMD),
5253
5254 SND_SOC_DAPM_ADC_E("AUX_PGA_Right", NULL, TAIKO_A_RX_AUX_SW_CTL, 6, 0,
5255 taiko_codec_enable_aux_pga, SND_SOC_DAPM_PRE_PMU |
5256 SND_SOC_DAPM_POST_PMD),
5257
5258 /* Lineout, ear and HPH PA Mixers */
5259
5260 SND_SOC_DAPM_MIXER("EAR_PA_MIXER", SND_SOC_NOPM, 0, 0,
5261 ear_pa_mix, ARRAY_SIZE(ear_pa_mix)),
5262
5263 SND_SOC_DAPM_MIXER("HPHL_PA_MIXER", SND_SOC_NOPM, 0, 0,
5264 hphl_pa_mix, ARRAY_SIZE(hphl_pa_mix)),
5265
5266 SND_SOC_DAPM_MIXER("HPHR_PA_MIXER", SND_SOC_NOPM, 0, 0,
5267 hphr_pa_mix, ARRAY_SIZE(hphr_pa_mix)),
5268
5269 SND_SOC_DAPM_MIXER("LINEOUT1_PA_MIXER", SND_SOC_NOPM, 0, 0,
5270 lineout1_pa_mix, ARRAY_SIZE(lineout1_pa_mix)),
5271
5272 SND_SOC_DAPM_MIXER("LINEOUT2_PA_MIXER", SND_SOC_NOPM, 0, 0,
5273 lineout2_pa_mix, ARRAY_SIZE(lineout2_pa_mix)),
5274
5275 SND_SOC_DAPM_MIXER("LINEOUT3_PA_MIXER", SND_SOC_NOPM, 0, 0,
5276 lineout3_pa_mix, ARRAY_SIZE(lineout3_pa_mix)),
5277
5278 SND_SOC_DAPM_MIXER("LINEOUT4_PA_MIXER", SND_SOC_NOPM, 0, 0,
5279 lineout4_pa_mix, ARRAY_SIZE(lineout4_pa_mix)),
Kiran Kandic3b24402012-06-11 00:05:59 -07005280};
5281
Kiran Kandic3b24402012-06-11 00:05:59 -07005282static irqreturn_t taiko_slimbus_irq(int irq, void *data)
5283{
5284 struct taiko_priv *priv = data;
5285 struct snd_soc_codec *codec = priv->codec;
Joonwoo Park9bbb4d12012-11-09 19:58:11 -08005286 unsigned long status = 0;
5287 int i, j, port_id, k;
5288 u32 bit;
Kiran Kandic3b24402012-06-11 00:05:59 -07005289 u8 val;
Joonwoo Park9bbb4d12012-11-09 19:58:11 -08005290 bool tx, cleared;
Kiran Kandic3b24402012-06-11 00:05:59 -07005291
Joonwoo Park9bbb4d12012-11-09 19:58:11 -08005292 for (i = TAIKO_SLIM_PGD_PORT_INT_STATUS_RX_0, j = 0;
5293 i <= TAIKO_SLIM_PGD_PORT_INT_STATUS_TX_1; i++, j++) {
5294 val = wcd9xxx_interface_reg_read(codec->control_data, i);
5295 status |= ((u32)val << (8 * j));
5296 }
5297
5298 for_each_set_bit(j, &status, 32) {
5299 tx = (j >= 16 ? true : false);
5300 port_id = (tx ? j - 16 : j);
5301 val = wcd9xxx_interface_reg_read(codec->control_data,
5302 TAIKO_SLIM_PGD_PORT_INT_RX_SOURCE0 + j);
5303 if (val & TAIKO_SLIM_IRQ_OVERFLOW)
5304 pr_err_ratelimited(
5305 "%s: overflow error on %s port %d, value %x\n",
5306 __func__, (tx ? "TX" : "RX"), port_id, val);
5307 if (val & TAIKO_SLIM_IRQ_UNDERFLOW)
5308 pr_err_ratelimited(
5309 "%s: underflow error on %s port %d, value %x\n",
5310 __func__, (tx ? "TX" : "RX"), port_id, val);
5311 if (val & TAIKO_SLIM_IRQ_PORT_CLOSED) {
5312 /*
5313 * INT SOURCE register starts from RX to TX
5314 * but port number in the ch_mask is in opposite way
5315 */
5316 bit = (tx ? j - 16 : j + 16);
5317 pr_debug("%s: %s port %d closed value %x, bit %u\n",
5318 __func__, (tx ? "TX" : "RX"), port_id, val,
5319 bit);
5320 for (k = 0, cleared = false; k < NUM_CODEC_DAIS; k++) {
5321 pr_debug("%s: priv->dai[%d].ch_mask = 0x%lx\n",
5322 __func__, k, priv->dai[k].ch_mask);
5323 if (test_and_clear_bit(bit,
5324 &priv->dai[k].ch_mask)) {
5325 cleared = true;
5326 if (!priv->dai[k].ch_mask)
5327 wake_up(&priv->dai[k].dai_wait);
5328 /*
5329 * There are cases when multiple DAIs
5330 * might be using the same slimbus
5331 * channel. Hence don't break here.
5332 */
5333 }
5334 }
5335 WARN(!cleared,
5336 "Couldn't find slimbus %s port %d for closing\n",
5337 (tx ? "TX" : "RX"), port_id);
Kiran Kandic3b24402012-06-11 00:05:59 -07005338 }
5339 wcd9xxx_interface_reg_write(codec->control_data,
Joonwoo Park9bbb4d12012-11-09 19:58:11 -08005340 TAIKO_SLIM_PGD_PORT_INT_CLR_RX_0 +
5341 (j / 8),
5342 1 << (j % 8));
Joonwoo Parka8890262012-10-15 12:04:27 -07005343 }
Joonwoo Park9bbb4d12012-11-09 19:58:11 -08005344
Kiran Kandic3b24402012-06-11 00:05:59 -07005345 return IRQ_HANDLED;
5346}
5347
5348static int taiko_handle_pdata(struct taiko_priv *taiko)
5349{
5350 struct snd_soc_codec *codec = taiko->codec;
Joonwoo Parka8890262012-10-15 12:04:27 -07005351 struct wcd9xxx_pdata *pdata = taiko->resmgr.pdata;
Kiran Kandic3b24402012-06-11 00:05:59 -07005352 int k1, k2, k3, rc = 0;
Kiran Kandi725f8492012-08-06 13:45:16 -07005353 u8 leg_mode, txfe_bypass, txfe_buff, flag;
Kiran Kandic3b24402012-06-11 00:05:59 -07005354 u8 i = 0, j = 0;
5355 u8 val_txfe = 0, value = 0;
Damir Didjusto1a353ce2013-04-02 11:45:47 -07005356 u8 dmic_sample_rate_value = 0;
5357 u8 dmic_b1_ctl_value = 0, dmic_b2_ctl_value = 0;
5358 u8 anc_ctl_value = 0;
Kiran Kandic3b24402012-06-11 00:05:59 -07005359
5360 if (!pdata) {
Kiran Kandi725f8492012-08-06 13:45:16 -07005361 pr_err("%s: NULL pdata\n", __func__);
Kiran Kandic3b24402012-06-11 00:05:59 -07005362 rc = -ENODEV;
5363 goto done;
5364 }
5365
Kiran Kandi725f8492012-08-06 13:45:16 -07005366 leg_mode = pdata->amic_settings.legacy_mode;
5367 txfe_bypass = pdata->amic_settings.txfe_enable;
5368 txfe_buff = pdata->amic_settings.txfe_buff;
5369 flag = pdata->amic_settings.use_pdata;
5370
Kiran Kandic3b24402012-06-11 00:05:59 -07005371 /* Make sure settings are correct */
Joonwoo Parka8890262012-10-15 12:04:27 -07005372 if ((pdata->micbias.ldoh_v > WCD9XXX_LDOH_3P0_V) ||
5373 (pdata->micbias.bias1_cfilt_sel > WCD9XXX_CFILT3_SEL) ||
5374 (pdata->micbias.bias2_cfilt_sel > WCD9XXX_CFILT3_SEL) ||
5375 (pdata->micbias.bias3_cfilt_sel > WCD9XXX_CFILT3_SEL) ||
5376 (pdata->micbias.bias4_cfilt_sel > WCD9XXX_CFILT3_SEL)) {
Kiran Kandic3b24402012-06-11 00:05:59 -07005377 rc = -EINVAL;
5378 goto done;
5379 }
Kiran Kandic3b24402012-06-11 00:05:59 -07005380 /* figure out k value */
Joonwoo Parka8890262012-10-15 12:04:27 -07005381 k1 = wcd9xxx_resmgr_get_k_val(&taiko->resmgr, pdata->micbias.cfilt1_mv);
5382 k2 = wcd9xxx_resmgr_get_k_val(&taiko->resmgr, pdata->micbias.cfilt2_mv);
5383 k3 = wcd9xxx_resmgr_get_k_val(&taiko->resmgr, pdata->micbias.cfilt3_mv);
Kiran Kandic3b24402012-06-11 00:05:59 -07005384
5385 if (IS_ERR_VALUE(k1) || IS_ERR_VALUE(k2) || IS_ERR_VALUE(k3)) {
5386 rc = -EINVAL;
5387 goto done;
5388 }
Kiran Kandic3b24402012-06-11 00:05:59 -07005389 /* Set voltage level and always use LDO */
5390 snd_soc_update_bits(codec, TAIKO_A_LDO_H_MODE_1, 0x0C,
Joonwoo Parka8890262012-10-15 12:04:27 -07005391 (pdata->micbias.ldoh_v << 2));
Kiran Kandic3b24402012-06-11 00:05:59 -07005392
Joonwoo Parka8890262012-10-15 12:04:27 -07005393 snd_soc_update_bits(codec, TAIKO_A_MICB_CFILT_1_VAL, 0xFC, (k1 << 2));
5394 snd_soc_update_bits(codec, TAIKO_A_MICB_CFILT_2_VAL, 0xFC, (k2 << 2));
5395 snd_soc_update_bits(codec, TAIKO_A_MICB_CFILT_3_VAL, 0xFC, (k3 << 2));
Kiran Kandic3b24402012-06-11 00:05:59 -07005396
5397 snd_soc_update_bits(codec, TAIKO_A_MICB_1_CTL, 0x60,
Joonwoo Parka8890262012-10-15 12:04:27 -07005398 (pdata->micbias.bias1_cfilt_sel << 5));
Kiran Kandic3b24402012-06-11 00:05:59 -07005399 snd_soc_update_bits(codec, TAIKO_A_MICB_2_CTL, 0x60,
Joonwoo Parka8890262012-10-15 12:04:27 -07005400 (pdata->micbias.bias2_cfilt_sel << 5));
Kiran Kandic3b24402012-06-11 00:05:59 -07005401 snd_soc_update_bits(codec, TAIKO_A_MICB_3_CTL, 0x60,
Joonwoo Parka8890262012-10-15 12:04:27 -07005402 (pdata->micbias.bias3_cfilt_sel << 5));
5403 snd_soc_update_bits(codec, taiko->resmgr.reg_addr->micb_4_ctl, 0x60,
Kiran Kandic3b24402012-06-11 00:05:59 -07005404 (pdata->micbias.bias4_cfilt_sel << 5));
5405
5406 for (i = 0; i < 6; j++, i += 2) {
5407 if (flag & (0x01 << i)) {
5408 value = (leg_mode & (0x01 << i)) ? 0x10 : 0x00;
5409 val_txfe = (txfe_bypass & (0x01 << i)) ? 0x20 : 0x00;
5410 val_txfe = val_txfe |
5411 ((txfe_buff & (0x01 << i)) ? 0x10 : 0x00);
5412 snd_soc_update_bits(codec, TAIKO_A_TX_1_2_EN + j * 10,
5413 0x10, value);
5414 snd_soc_update_bits(codec,
5415 TAIKO_A_TX_1_2_TEST_EN + j * 10,
5416 0x30, val_txfe);
5417 }
5418 if (flag & (0x01 << (i + 1))) {
5419 value = (leg_mode & (0x01 << (i + 1))) ? 0x01 : 0x00;
5420 val_txfe = (txfe_bypass &
5421 (0x01 << (i + 1))) ? 0x02 : 0x00;
5422 val_txfe |= (txfe_buff &
5423 (0x01 << (i + 1))) ? 0x01 : 0x00;
5424 snd_soc_update_bits(codec, TAIKO_A_TX_1_2_EN + j * 10,
5425 0x01, value);
5426 snd_soc_update_bits(codec,
5427 TAIKO_A_TX_1_2_TEST_EN + j * 10,
5428 0x03, val_txfe);
5429 }
5430 }
5431 if (flag & 0x40) {
5432 value = (leg_mode & 0x40) ? 0x10 : 0x00;
5433 value = value | ((txfe_bypass & 0x40) ? 0x02 : 0x00);
5434 value = value | ((txfe_buff & 0x40) ? 0x01 : 0x00);
5435 snd_soc_update_bits(codec, TAIKO_A_TX_7_MBHC_EN,
5436 0x13, value);
5437 }
5438
5439 if (pdata->ocp.use_pdata) {
5440 /* not defined in CODEC specification */
5441 if (pdata->ocp.hph_ocp_limit == 1 ||
5442 pdata->ocp.hph_ocp_limit == 5) {
5443 rc = -EINVAL;
5444 goto done;
5445 }
5446 snd_soc_update_bits(codec, TAIKO_A_RX_COM_OCP_CTL,
5447 0x0F, pdata->ocp.num_attempts);
5448 snd_soc_write(codec, TAIKO_A_RX_COM_OCP_COUNT,
5449 ((pdata->ocp.run_time << 4) | pdata->ocp.wait_time));
5450 snd_soc_update_bits(codec, TAIKO_A_RX_HPH_OCP_CTL,
5451 0xE0, (pdata->ocp.hph_ocp_limit << 5));
5452 }
5453
5454 for (i = 0; i < ARRAY_SIZE(pdata->regulator); i++) {
Joonwoo Park448a8fc2013-04-10 15:25:58 -07005455 if (pdata->regulator[i].name &&
5456 !strncmp(pdata->regulator[i].name, "CDC_VDDA_RX", 11)) {
Kiran Kandic3b24402012-06-11 00:05:59 -07005457 if (pdata->regulator[i].min_uV == 1800000 &&
5458 pdata->regulator[i].max_uV == 1800000) {
5459 snd_soc_write(codec, TAIKO_A_BIAS_REF_CTL,
5460 0x1C);
5461 } else if (pdata->regulator[i].min_uV == 2200000 &&
5462 pdata->regulator[i].max_uV == 2200000) {
5463 snd_soc_write(codec, TAIKO_A_BIAS_REF_CTL,
5464 0x1E);
5465 } else {
5466 pr_err("%s: unsupported CDC_VDDA_RX voltage\n"
5467 "min %d, max %d\n", __func__,
5468 pdata->regulator[i].min_uV,
5469 pdata->regulator[i].max_uV);
5470 rc = -EINVAL;
5471 }
5472 break;
5473 }
5474 }
Kiran Kandi4c56c592012-07-25 11:04:55 -07005475
Joonwoo Park1848c762012-10-18 13:16:01 -07005476 /* Set micbias capless mode with tail current */
5477 value = (pdata->micbias.bias1_cap_mode == MICBIAS_EXT_BYP_CAP ?
5478 0x00 : 0x16);
5479 snd_soc_update_bits(codec, TAIKO_A_MICB_1_CTL, 0x1E, value);
5480 value = (pdata->micbias.bias2_cap_mode == MICBIAS_EXT_BYP_CAP ?
5481 0x00 : 0x16);
5482 snd_soc_update_bits(codec, TAIKO_A_MICB_2_CTL, 0x1E, value);
5483 value = (pdata->micbias.bias3_cap_mode == MICBIAS_EXT_BYP_CAP ?
5484 0x00 : 0x16);
5485 snd_soc_update_bits(codec, TAIKO_A_MICB_3_CTL, 0x1E, value);
5486 value = (pdata->micbias.bias4_cap_mode == MICBIAS_EXT_BYP_CAP ?
5487 0x00 : 0x16);
5488 snd_soc_update_bits(codec, TAIKO_A_MICB_4_CTL, 0x1E, value);
5489
Damir Didjusto1a353ce2013-04-02 11:45:47 -07005490 /* Set the DMIC sample rate */
5491 if (pdata->mclk_rate == TAIKO_MCLK_CLK_9P6HZ) {
5492 switch (pdata->dmic_sample_rate) {
5493 case TAIKO_DMIC_SAMPLE_RATE_2P4MHZ:
5494 dmic_sample_rate_value = TAIKO_DMIC_SAMPLE_RATE_DIV_4;
5495 dmic_b1_ctl_value = TAIKO_DMIC_B1_CTL_DIV_4;
5496 dmic_b2_ctl_value = TAIKO_DMIC_B2_CTL_DIV_4;
5497 anc_ctl_value = TAIKO_ANC_DMIC_X2_OFF;
5498 break;
5499 case TAIKO_DMIC_SAMPLE_RATE_4P8MHZ:
5500 dmic_sample_rate_value = TAIKO_DMIC_SAMPLE_RATE_DIV_2;
5501 dmic_b1_ctl_value = TAIKO_DMIC_B1_CTL_DIV_2;
5502 dmic_b2_ctl_value = TAIKO_DMIC_B2_CTL_DIV_2;
5503 anc_ctl_value = TAIKO_ANC_DMIC_X2_ON;
5504 break;
5505 case TAIKO_DMIC_SAMPLE_RATE_3P2MHZ:
5506 case TAIKO_DMIC_SAMPLE_RATE_UNDEFINED:
5507 dmic_sample_rate_value = TAIKO_DMIC_SAMPLE_RATE_DIV_3;
5508 dmic_b1_ctl_value = TAIKO_DMIC_B1_CTL_DIV_3;
5509 dmic_b2_ctl_value = TAIKO_DMIC_B2_CTL_DIV_3;
5510 anc_ctl_value = TAIKO_ANC_DMIC_X2_OFF;
5511 break;
5512 default:
5513 pr_err("%s Invalid sample rate %d for mclk %d\n",
5514 __func__, pdata->dmic_sample_rate, pdata->mclk_rate);
5515 rc = -EINVAL;
5516 goto done;
5517 break;
5518 }
5519 } else if (pdata->mclk_rate == TAIKO_MCLK_CLK_12P288MHZ) {
5520 switch (pdata->dmic_sample_rate) {
5521 case TAIKO_DMIC_SAMPLE_RATE_3P072MHZ:
5522 dmic_sample_rate_value = TAIKO_DMIC_SAMPLE_RATE_DIV_4;
5523 dmic_b1_ctl_value = TAIKO_DMIC_B1_CTL_DIV_4;
5524 dmic_b2_ctl_value = TAIKO_DMIC_B2_CTL_DIV_4;
5525 anc_ctl_value = TAIKO_ANC_DMIC_X2_OFF;
5526 break;
5527 case TAIKO_DMIC_SAMPLE_RATE_6P144MHZ:
5528 dmic_sample_rate_value = TAIKO_DMIC_SAMPLE_RATE_DIV_2;
5529 dmic_b1_ctl_value = TAIKO_DMIC_B1_CTL_DIV_2;
5530 dmic_b2_ctl_value = TAIKO_DMIC_B2_CTL_DIV_2;
5531 anc_ctl_value = TAIKO_ANC_DMIC_X2_ON;
5532 break;
5533 case TAIKO_DMIC_SAMPLE_RATE_4P096MHZ:
5534 case TAIKO_DMIC_SAMPLE_RATE_UNDEFINED:
5535 dmic_sample_rate_value = TAIKO_DMIC_SAMPLE_RATE_DIV_3;
5536 dmic_b1_ctl_value = TAIKO_DMIC_B1_CTL_DIV_3;
5537 dmic_b2_ctl_value = TAIKO_DMIC_B2_CTL_DIV_3;
5538 anc_ctl_value = TAIKO_ANC_DMIC_X2_OFF;
5539 break;
5540 default:
5541 pr_err("%s Invalid sample rate %d for mclk %d\n",
5542 __func__, pdata->dmic_sample_rate, pdata->mclk_rate);
5543 rc = -EINVAL;
5544 goto done;
5545 break;
5546 }
5547 } else {
5548 pr_err("%s MCLK is not set!\n", __func__);
5549 rc = -EINVAL;
5550 goto done;
5551 }
5552
5553 snd_soc_update_bits(codec, TAIKO_A_CDC_TX1_DMIC_CTL,
5554 0x7, dmic_sample_rate_value);
5555 snd_soc_update_bits(codec, TAIKO_A_CDC_TX2_DMIC_CTL,
5556 0x7, dmic_sample_rate_value);
5557 snd_soc_update_bits(codec, TAIKO_A_CDC_TX3_DMIC_CTL,
5558 0x7, dmic_sample_rate_value);
5559 snd_soc_update_bits(codec, TAIKO_A_CDC_TX4_DMIC_CTL,
5560 0x7, dmic_sample_rate_value);
5561 snd_soc_update_bits(codec, TAIKO_A_CDC_TX5_DMIC_CTL,
5562 0x7, dmic_sample_rate_value);
5563 snd_soc_update_bits(codec, TAIKO_A_CDC_TX6_DMIC_CTL,
5564 0x7, dmic_sample_rate_value);
5565 snd_soc_update_bits(codec, TAIKO_A_CDC_TX7_DMIC_CTL,
5566 0x7, dmic_sample_rate_value);
5567 snd_soc_update_bits(codec, TAIKO_A_CDC_TX8_DMIC_CTL,
5568 0x7, dmic_sample_rate_value);
5569 snd_soc_update_bits(codec, TAIKO_A_CDC_TX9_DMIC_CTL,
5570 0x7, dmic_sample_rate_value);
5571 snd_soc_update_bits(codec, TAIKO_A_CDC_TX10_DMIC_CTL,
5572 0x7, dmic_sample_rate_value);
5573 snd_soc_update_bits(codec, TAIKO_A_CDC_CLK_DMIC_B1_CTL,
5574 0xEE, dmic_b1_ctl_value);
5575 snd_soc_update_bits(codec, TAIKO_A_CDC_CLK_DMIC_B2_CTL,
5576 0xE, dmic_b2_ctl_value);
5577 snd_soc_update_bits(codec, TAIKO_A_CDC_ANC1_B2_CTL,
5578 0x1, anc_ctl_value);
5579
Kiran Kandic3b24402012-06-11 00:05:59 -07005580done:
5581 return rc;
5582}
5583
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08005584static const struct wcd9xxx_reg_mask_val taiko_reg_defaults[] = {
Kiran Kandic3b24402012-06-11 00:05:59 -07005585
Kiran Kandi4c56c592012-07-25 11:04:55 -07005586 /* set MCLk to 9.6 */
Gopikrishnaiah Anandana8aec1f2013-01-23 14:26:27 -05005587 TAIKO_REG_VAL(TAIKO_A_CHIP_CTL, 0x02),
Kiran Kandi4c56c592012-07-25 11:04:55 -07005588 TAIKO_REG_VAL(TAIKO_A_CDC_CLK_POWER_CTL, 0x03),
Kiran Kandic3b24402012-06-11 00:05:59 -07005589
Kiran Kandi4c56c592012-07-25 11:04:55 -07005590 /* EAR PA deafults */
5591 TAIKO_REG_VAL(TAIKO_A_RX_EAR_CMBUFF, 0x05),
Kiran Kandic3b24402012-06-11 00:05:59 -07005592
Kiran Kandi4c56c592012-07-25 11:04:55 -07005593 /* RX deafults */
Kiran Kandic3b24402012-06-11 00:05:59 -07005594 TAIKO_REG_VAL(TAIKO_A_CDC_RX1_B5_CTL, 0x78),
5595 TAIKO_REG_VAL(TAIKO_A_CDC_RX2_B5_CTL, 0x78),
5596 TAIKO_REG_VAL(TAIKO_A_CDC_RX3_B5_CTL, 0x78),
5597 TAIKO_REG_VAL(TAIKO_A_CDC_RX4_B5_CTL, 0x78),
5598 TAIKO_REG_VAL(TAIKO_A_CDC_RX5_B5_CTL, 0x78),
5599 TAIKO_REG_VAL(TAIKO_A_CDC_RX6_B5_CTL, 0x78),
5600 TAIKO_REG_VAL(TAIKO_A_CDC_RX7_B5_CTL, 0x78),
5601
Kiran Kandi4c56c592012-07-25 11:04:55 -07005602 /* RX1 and RX2 defaults */
Kiran Kandic3b24402012-06-11 00:05:59 -07005603 TAIKO_REG_VAL(TAIKO_A_CDC_RX1_B6_CTL, 0xA0),
5604 TAIKO_REG_VAL(TAIKO_A_CDC_RX2_B6_CTL, 0xA0),
5605
Kiran Kandi4c56c592012-07-25 11:04:55 -07005606 /* RX3 to RX7 defaults */
Kiran Kandic3b24402012-06-11 00:05:59 -07005607 TAIKO_REG_VAL(TAIKO_A_CDC_RX3_B6_CTL, 0x80),
5608 TAIKO_REG_VAL(TAIKO_A_CDC_RX4_B6_CTL, 0x80),
5609 TAIKO_REG_VAL(TAIKO_A_CDC_RX5_B6_CTL, 0x80),
5610 TAIKO_REG_VAL(TAIKO_A_CDC_RX6_B6_CTL, 0x80),
5611 TAIKO_REG_VAL(TAIKO_A_CDC_RX7_B6_CTL, 0x80),
Joonwoo Park1d05bb92013-03-07 16:55:06 -08005612
5613 /* MAD registers */
5614 TAIKO_REG_VAL(TAIKO_A_MAD_ANA_CTRL, 0xF1),
5615 TAIKO_REG_VAL(TAIKO_A_CDC_MAD_MAIN_CTL_1, 0x00),
5616 TAIKO_REG_VAL(TAIKO_A_CDC_MAD_MAIN_CTL_2, 0x00),
5617 TAIKO_REG_VAL(TAIKO_A_CDC_MAD_AUDIO_CTL_1, 0x00),
5618 /* Set SAMPLE_TX_EN bit */
5619 TAIKO_REG_VAL(TAIKO_A_CDC_MAD_AUDIO_CTL_2, 0x03),
5620 TAIKO_REG_VAL(TAIKO_A_CDC_MAD_AUDIO_CTL_3, 0x00),
5621 TAIKO_REG_VAL(TAIKO_A_CDC_MAD_AUDIO_CTL_4, 0x00),
5622 TAIKO_REG_VAL(TAIKO_A_CDC_MAD_AUDIO_CTL_5, 0x00),
5623 TAIKO_REG_VAL(TAIKO_A_CDC_MAD_AUDIO_CTL_6, 0x00),
5624 TAIKO_REG_VAL(TAIKO_A_CDC_MAD_AUDIO_CTL_7, 0x00),
5625 TAIKO_REG_VAL(TAIKO_A_CDC_MAD_AUDIO_CTL_8, 0x00),
5626 TAIKO_REG_VAL(TAIKO_A_CDC_MAD_AUDIO_IIR_CTL_PTR, 0x00),
5627 TAIKO_REG_VAL(TAIKO_A_CDC_MAD_AUDIO_IIR_CTL_VAL, 0x40),
5628 TAIKO_REG_VAL(TAIKO_A_CDC_DEBUG_B7_CTL, 0x00),
5629 TAIKO_REG_VAL(TAIKO_A_CDC_CLK_OTHR_RESET_B1_CTL, 0x00),
5630 TAIKO_REG_VAL(TAIKO_A_CDC_CLK_OTHR_CTL, 0x00),
5631 TAIKO_REG_VAL(TAIKO_A_CDC_CONN_MAD, 0x01),
Kiran Kandic3b24402012-06-11 00:05:59 -07005632};
5633
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08005634static const struct wcd9xxx_reg_mask_val taiko_1_0_reg_defaults[] = {
Kiran Kandi7b7d2ff2012-09-14 14:52:14 -07005635 /*
5636 * The following only need to be written for Taiko 1.0 parts.
5637 * Taiko 2.0 will have appropriate defaults for these registers.
5638 */
Joonwoo Park559a5bf2013-02-15 14:46:36 -08005639
5640 /* BUCK default */
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08005641 TAIKO_REG_VAL(WCD9XXX_A_BUCK_CTRL_CCL_4, 0x50),
5642
5643 /* Required defaults for class H operation */
5644 TAIKO_REG_VAL(TAIKO_A_RX_HPH_CHOP_CTL, 0xF4),
5645 TAIKO_REG_VAL(TAIKO_A_BIAS_CURR_CTL_2, 0x08),
5646 TAIKO_REG_VAL(WCD9XXX_A_BUCK_CTRL_CCL_1, 0x5B),
5647 TAIKO_REG_VAL(WCD9XXX_A_BUCK_CTRL_CCL_3, 0x60),
Joonwoo Park559a5bf2013-02-15 14:46:36 -08005648
Kiran Kandi7b7d2ff2012-09-14 14:52:14 -07005649 /* Choose max non-overlap time for NCP */
5650 TAIKO_REG_VAL(TAIKO_A_NCP_CLK, 0xFC),
5651 /* Use 25mV/50mV for deltap/m to reduce ripple */
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08005652 TAIKO_REG_VAL(WCD9XXX_A_BUCK_CTRL_VCL_1, 0x08),
Kiran Kandi7b7d2ff2012-09-14 14:52:14 -07005653 /*
5654 * Set DISABLE_MODE_SEL<1:0> to 0b10 (disable PWM in auto mode).
5655 * Note that the other bits of this register will be changed during
5656 * Rx PA bring up.
5657 */
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08005658 TAIKO_REG_VAL(WCD9XXX_A_BUCK_MODE_3, 0xCE),
Kiran Kandi7b7d2ff2012-09-14 14:52:14 -07005659 /* Reduce HPH DAC bias to 70% */
5660 TAIKO_REG_VAL(TAIKO_A_RX_HPH_BIAS_PA, 0x7A),
5661 /*Reduce EAR DAC bias to 70% */
5662 TAIKO_REG_VAL(TAIKO_A_RX_EAR_BIAS_PA, 0x76),
5663 /* Reduce LINE DAC bias to 70% */
5664 TAIKO_REG_VAL(TAIKO_A_RX_LINE_BIAS_PA, 0x78),
Joonwoo Parkd87ec4c2012-10-30 15:44:18 -07005665
5666 /*
5667 * There is a diode to pull down the micbias while doing
5668 * insertion detection. This diode can cause leakage.
5669 * Set bit 0 to 1 to prevent leakage.
5670 * Setting this bit of micbias 2 prevents leakage for all other micbias.
5671 */
5672 TAIKO_REG_VAL(TAIKO_A_MICB_2_MBHC, 0x41),
Joonwoo Park3c7bca62012-10-31 12:44:23 -07005673
5674 /* Disable TX7 internal biasing path which can cause leakage */
5675 TAIKO_REG_VAL(TAIKO_A_TX_SUP_SWITCH_CTRL_1, 0xBF),
Joonwoo Park03604052012-11-06 18:40:25 -08005676 /* Enable MICB 4 VDDIO switch to prevent leakage */
5677 TAIKO_REG_VAL(TAIKO_A_MICB_4_MBHC, 0x81),
Joonwoo Park125cd4e2012-12-11 15:16:11 -08005678
5679 /* Close leakage on the spkdrv */
5680 TAIKO_REG_VAL(TAIKO_A_SPKR_DRV_DBG_PWRSTG, 0x24),
Kiran Kandi7b7d2ff2012-09-14 14:52:14 -07005681};
5682
Joonwoo Park559a5bf2013-02-15 14:46:36 -08005683/*
5684 * Don't update TAIKO_A_CHIP_CTL, TAIKO_A_BUCK_CTRL_CCL_1 and
5685 * TAIKO_A_RX_EAR_CMBUFF as those are updated in taiko_reg_defaults
5686 */
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08005687static const struct wcd9xxx_reg_mask_val taiko_2_0_reg_defaults[] = {
Joonwoo Park559a5bf2013-02-15 14:46:36 -08005688 TAIKO_REG_VAL(TAIKO_A_CDC_TX_1_GAIN, 0x2),
5689 TAIKO_REG_VAL(TAIKO_A_CDC_TX_2_GAIN, 0x2),
5690 TAIKO_REG_VAL(TAIKO_A_CDC_TX_1_2_ADC_IB, 0x44),
5691 TAIKO_REG_VAL(TAIKO_A_CDC_TX_3_GAIN, 0x2),
5692 TAIKO_REG_VAL(TAIKO_A_CDC_TX_4_GAIN, 0x2),
5693 TAIKO_REG_VAL(TAIKO_A_CDC_TX_3_4_ADC_IB, 0x44),
5694 TAIKO_REG_VAL(TAIKO_A_CDC_TX_5_GAIN, 0x2),
5695 TAIKO_REG_VAL(TAIKO_A_CDC_TX_6_GAIN, 0x2),
5696 TAIKO_REG_VAL(TAIKO_A_CDC_TX_5_6_ADC_IB, 0x44),
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08005697 TAIKO_REG_VAL(WCD9XXX_A_BUCK_MODE_3, 0xCE),
5698 TAIKO_REG_VAL(WCD9XXX_A_BUCK_CTRL_VCL_1, 0x8),
5699 TAIKO_REG_VAL(WCD9XXX_A_BUCK_CTRL_CCL_4, 0x51),
Joonwoo Park559a5bf2013-02-15 14:46:36 -08005700 TAIKO_REG_VAL(TAIKO_A_NCP_DTEST, 0x10),
5701 TAIKO_REG_VAL(TAIKO_A_RX_HPH_CHOP_CTL, 0xA4),
5702 TAIKO_REG_VAL(TAIKO_A_RX_HPH_BIAS_PA, 0x7A),
5703 TAIKO_REG_VAL(TAIKO_A_RX_HPH_OCP_CTL, 0x69),
5704 TAIKO_REG_VAL(TAIKO_A_RX_HPH_CNP_WG_CTL, 0xDA),
5705 TAIKO_REG_VAL(TAIKO_A_RX_HPH_CNP_WG_TIME, 0x15),
5706 TAIKO_REG_VAL(TAIKO_A_RX_EAR_BIAS_PA, 0x76),
5707 TAIKO_REG_VAL(TAIKO_A_RX_EAR_CNP, 0xC0),
5708 TAIKO_REG_VAL(TAIKO_A_RX_LINE_BIAS_PA, 0x78),
5709 TAIKO_REG_VAL(TAIKO_A_RX_LINE_1_TEST, 0x2),
5710 TAIKO_REG_VAL(TAIKO_A_RX_LINE_2_TEST, 0x2),
5711 TAIKO_REG_VAL(TAIKO_A_RX_LINE_3_TEST, 0x2),
5712 TAIKO_REG_VAL(TAIKO_A_RX_LINE_4_TEST, 0x2),
5713 TAIKO_REG_VAL(TAIKO_A_SPKR_DRV_OCP_CTL, 0x97),
5714 TAIKO_REG_VAL(TAIKO_A_SPKR_DRV_CLIP_DET, 0x1),
5715 TAIKO_REG_VAL(TAIKO_A_SPKR_DRV_IEC, 0x0),
5716 TAIKO_REG_VAL(TAIKO_A_CDC_TX1_MUX_CTL, 0x48),
5717 TAIKO_REG_VAL(TAIKO_A_CDC_TX2_MUX_CTL, 0x48),
5718 TAIKO_REG_VAL(TAIKO_A_CDC_TX3_MUX_CTL, 0x48),
5719 TAIKO_REG_VAL(TAIKO_A_CDC_TX4_MUX_CTL, 0x48),
5720 TAIKO_REG_VAL(TAIKO_A_CDC_TX5_MUX_CTL, 0x48),
5721 TAIKO_REG_VAL(TAIKO_A_CDC_TX6_MUX_CTL, 0x48),
5722 TAIKO_REG_VAL(TAIKO_A_CDC_TX7_MUX_CTL, 0x48),
5723 TAIKO_REG_VAL(TAIKO_A_CDC_TX8_MUX_CTL, 0x48),
5724 TAIKO_REG_VAL(TAIKO_A_CDC_TX9_MUX_CTL, 0x48),
5725 TAIKO_REG_VAL(TAIKO_A_CDC_TX10_MUX_CTL, 0x48),
5726 TAIKO_REG_VAL(TAIKO_A_CDC_RX1_B4_CTL, 0x8),
Joonwoo Parkdbbdac02013-03-21 19:24:31 -07005727 TAIKO_REG_VAL(TAIKO_A_CDC_RX2_B4_CTL, 0x8),
5728 TAIKO_REG_VAL(TAIKO_A_CDC_RX3_B4_CTL, 0x8),
5729 TAIKO_REG_VAL(TAIKO_A_CDC_RX4_B4_CTL, 0x8),
5730 TAIKO_REG_VAL(TAIKO_A_CDC_RX5_B4_CTL, 0x8),
5731 TAIKO_REG_VAL(TAIKO_A_CDC_RX6_B4_CTL, 0x8),
5732 TAIKO_REG_VAL(TAIKO_A_CDC_RX7_B4_CTL, 0x8),
Joonwoo Park559a5bf2013-02-15 14:46:36 -08005733 TAIKO_REG_VAL(TAIKO_A_CDC_VBAT_GAIN_UPD_MON, 0x0),
5734 TAIKO_REG_VAL(TAIKO_A_CDC_PA_RAMP_B1_CTL, 0x0),
5735 TAIKO_REG_VAL(TAIKO_A_CDC_PA_RAMP_B2_CTL, 0x0),
5736 TAIKO_REG_VAL(TAIKO_A_CDC_PA_RAMP_B3_CTL, 0x0),
5737 TAIKO_REG_VAL(TAIKO_A_CDC_PA_RAMP_B4_CTL, 0x0),
5738 TAIKO_REG_VAL(TAIKO_A_CDC_SPKR_CLIPDET_B1_CTL, 0x0),
5739 TAIKO_REG_VAL(TAIKO_A_CDC_COMP0_B4_CTL, 0x37),
5740 TAIKO_REG_VAL(TAIKO_A_CDC_COMP0_B5_CTL, 0x7f),
5741};
5742
Kiran Kandic3b24402012-06-11 00:05:59 -07005743static void taiko_update_reg_defaults(struct snd_soc_codec *codec)
5744{
5745 u32 i;
Kiran Kandi7b7d2ff2012-09-14 14:52:14 -07005746 struct wcd9xxx *taiko_core = dev_get_drvdata(codec->dev->parent);
Kiran Kandic3b24402012-06-11 00:05:59 -07005747
Kiran Kandi7b7d2ff2012-09-14 14:52:14 -07005748 for (i = 0; i < ARRAY_SIZE(taiko_reg_defaults); i++)
5749 snd_soc_write(codec, taiko_reg_defaults[i].reg,
Joonwoo Park559a5bf2013-02-15 14:46:36 -08005750 taiko_reg_defaults[i].val);
Kiran Kandi7b7d2ff2012-09-14 14:52:14 -07005751
5752 if (TAIKO_IS_1_0(taiko_core->version)) {
5753 for (i = 0; i < ARRAY_SIZE(taiko_1_0_reg_defaults); i++)
5754 snd_soc_write(codec, taiko_1_0_reg_defaults[i].reg,
Joonwoo Park559a5bf2013-02-15 14:46:36 -08005755 taiko_1_0_reg_defaults[i].val);
5756 if (spkr_drv_wrnd == 1)
5757 snd_soc_write(codec, TAIKO_A_SPKR_DRV_EN, 0xEF);
5758 } else {
5759 for (i = 0; i < ARRAY_SIZE(taiko_2_0_reg_defaults); i++)
5760 snd_soc_write(codec, taiko_2_0_reg_defaults[i].reg,
5761 taiko_2_0_reg_defaults[i].val);
Joonwoo Park125cd4e2012-12-11 15:16:11 -08005762 spkr_drv_wrnd = -1;
Joonwoo Park559a5bf2013-02-15 14:46:36 -08005763 }
Kiran Kandic3b24402012-06-11 00:05:59 -07005764}
5765
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08005766static const struct wcd9xxx_reg_mask_val taiko_codec_reg_init_val[] = {
Kiran Kandic3b24402012-06-11 00:05:59 -07005767 /* Initialize current threshold to 350MA
5768 * number of wait and run cycles to 4096
5769 */
Kiran Kandi7b7d2ff2012-09-14 14:52:14 -07005770 {TAIKO_A_RX_HPH_OCP_CTL, 0xE1, 0x61},
Kiran Kandic3b24402012-06-11 00:05:59 -07005771 {TAIKO_A_RX_COM_OCP_COUNT, 0xFF, 0xFF},
Patrick Lai92833bf2012-12-01 10:31:35 -08005772 {TAIKO_A_RX_HPH_L_TEST, 0x01, 0x01},
5773 {TAIKO_A_RX_HPH_R_TEST, 0x01, 0x01},
Kiran Kandic3b24402012-06-11 00:05:59 -07005774
Kiran Kandic3b24402012-06-11 00:05:59 -07005775 /* Initialize gain registers to use register gain */
Kiran Kandi4c56c592012-07-25 11:04:55 -07005776 {TAIKO_A_RX_HPH_L_GAIN, 0x20, 0x20},
5777 {TAIKO_A_RX_HPH_R_GAIN, 0x20, 0x20},
5778 {TAIKO_A_RX_LINE_1_GAIN, 0x20, 0x20},
5779 {TAIKO_A_RX_LINE_2_GAIN, 0x20, 0x20},
5780 {TAIKO_A_RX_LINE_3_GAIN, 0x20, 0x20},
5781 {TAIKO_A_RX_LINE_4_GAIN, 0x20, 0x20},
Joonwoo Parkc7731432012-10-17 12:41:44 -07005782 {TAIKO_A_SPKR_DRV_GAIN, 0x04, 0x04},
Kiran Kandic3b24402012-06-11 00:05:59 -07005783
Kiran Kandic3b24402012-06-11 00:05:59 -07005784 /* Use 16 bit sample size for TX1 to TX6 */
5785 {TAIKO_A_CDC_CONN_TX_SB_B1_CTL, 0x30, 0x20},
5786 {TAIKO_A_CDC_CONN_TX_SB_B2_CTL, 0x30, 0x20},
5787 {TAIKO_A_CDC_CONN_TX_SB_B3_CTL, 0x30, 0x20},
5788 {TAIKO_A_CDC_CONN_TX_SB_B4_CTL, 0x30, 0x20},
5789 {TAIKO_A_CDC_CONN_TX_SB_B5_CTL, 0x30, 0x20},
5790 {TAIKO_A_CDC_CONN_TX_SB_B6_CTL, 0x30, 0x20},
5791
5792 /* Use 16 bit sample size for TX7 to TX10 */
5793 {TAIKO_A_CDC_CONN_TX_SB_B7_CTL, 0x60, 0x40},
5794 {TAIKO_A_CDC_CONN_TX_SB_B8_CTL, 0x60, 0x40},
5795 {TAIKO_A_CDC_CONN_TX_SB_B9_CTL, 0x60, 0x40},
5796 {TAIKO_A_CDC_CONN_TX_SB_B10_CTL, 0x60, 0x40},
5797
Kiran Kandic3b24402012-06-11 00:05:59 -07005798 /*enable HPF filter for TX paths */
5799 {TAIKO_A_CDC_TX1_MUX_CTL, 0x8, 0x0},
5800 {TAIKO_A_CDC_TX2_MUX_CTL, 0x8, 0x0},
5801 {TAIKO_A_CDC_TX3_MUX_CTL, 0x8, 0x0},
5802 {TAIKO_A_CDC_TX4_MUX_CTL, 0x8, 0x0},
5803 {TAIKO_A_CDC_TX5_MUX_CTL, 0x8, 0x0},
5804 {TAIKO_A_CDC_TX6_MUX_CTL, 0x8, 0x0},
5805 {TAIKO_A_CDC_TX7_MUX_CTL, 0x8, 0x0},
5806 {TAIKO_A_CDC_TX8_MUX_CTL, 0x8, 0x0},
5807 {TAIKO_A_CDC_TX9_MUX_CTL, 0x8, 0x0},
5808 {TAIKO_A_CDC_TX10_MUX_CTL, 0x8, 0x0},
5809
Joonwoo Parkc7731432012-10-17 12:41:44 -07005810 /* Compander zone selection */
5811 {TAIKO_A_CDC_COMP0_B4_CTL, 0x3F, 0x37},
5812 {TAIKO_A_CDC_COMP1_B4_CTL, 0x3F, 0x37},
5813 {TAIKO_A_CDC_COMP2_B4_CTL, 0x3F, 0x37},
5814 {TAIKO_A_CDC_COMP0_B5_CTL, 0x7F, 0x7F},
5815 {TAIKO_A_CDC_COMP1_B5_CTL, 0x7F, 0x7F},
5816 {TAIKO_A_CDC_COMP2_B5_CTL, 0x7F, 0x7F},
Bhalchandra Gajareef7810e2013-03-29 16:50:37 -07005817
5818 /*
5819 * Setup wavegen timer to 20msec and disable chopper
5820 * as default. This corresponds to Compander OFF
5821 */
5822 {TAIKO_A_RX_HPH_CNP_WG_CTL, 0xFF, 0xDB},
5823 {TAIKO_A_RX_HPH_CNP_WG_TIME, 0xFF, 0x58},
5824 {TAIKO_A_RX_HPH_BIAS_WG_OCP, 0xFF, 0x1A},
5825 {TAIKO_A_RX_HPH_CHOP_CTL, 0xFF, 0x24},
Bhalchandra Gajare9581aed2013-03-29 17:06:10 -07005826
5827 /* Choose max non-overlap time for NCP */
5828 {TAIKO_A_NCP_CLK, 0xFF, 0xFC},
5829
5830 /* Program the 0.85 volt VBG_REFERENCE */
5831 {TAIKO_A_BIAS_CURR_CTL_2, 0xFF, 0x04},
Kiran Kandic3b24402012-06-11 00:05:59 -07005832};
5833
5834static void taiko_codec_init_reg(struct snd_soc_codec *codec)
5835{
5836 u32 i;
5837
5838 for (i = 0; i < ARRAY_SIZE(taiko_codec_reg_init_val); i++)
5839 snd_soc_update_bits(codec, taiko_codec_reg_init_val[i].reg,
5840 taiko_codec_reg_init_val[i].mask,
5841 taiko_codec_reg_init_val[i].val);
5842}
5843
Joonwoo Park7680b9f2012-07-13 11:36:48 -07005844static int taiko_setup_irqs(struct taiko_priv *taiko)
5845{
Joonwoo Park7680b9f2012-07-13 11:36:48 -07005846 int i;
Joonwoo Parka8890262012-10-15 12:04:27 -07005847 int ret = 0;
Joonwoo Park7680b9f2012-07-13 11:36:48 -07005848 struct snd_soc_codec *codec = taiko->codec;
5849
Joonwoo Parkf6574c72012-10-10 17:29:57 -07005850 ret = wcd9xxx_request_irq(codec->control_data, WCD9XXX_IRQ_SLIMBUS,
Joonwoo Park7680b9f2012-07-13 11:36:48 -07005851 taiko_slimbus_irq, "SLIMBUS Slave", taiko);
5852 if (ret) {
5853 pr_err("%s: Failed to request irq %d\n", __func__,
Joonwoo Parkf6574c72012-10-10 17:29:57 -07005854 WCD9XXX_IRQ_SLIMBUS);
Joonwoo Parka8890262012-10-15 12:04:27 -07005855 goto exit;
Joonwoo Park7680b9f2012-07-13 11:36:48 -07005856 }
5857
5858 for (i = 0; i < WCD9XXX_SLIM_NUM_PORT_REG; i++)
5859 wcd9xxx_interface_reg_write(codec->control_data,
Joonwoo Parka8890262012-10-15 12:04:27 -07005860 TAIKO_SLIM_PGD_PORT_INT_EN0 + i,
5861 0xFF);
5862exit:
Joonwoo Park7680b9f2012-07-13 11:36:48 -07005863 return ret;
5864}
5865
Joonwoo Parka8890262012-10-15 12:04:27 -07005866int taiko_hs_detect(struct snd_soc_codec *codec,
5867 struct wcd9xxx_mbhc_config *mbhc_cfg)
5868{
5869 struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
5870 return wcd9xxx_mbhc_start(&taiko->mbhc, mbhc_cfg);
5871}
5872EXPORT_SYMBOL_GPL(taiko_hs_detect);
5873
Joonwoo Park1d05bb92013-03-07 16:55:06 -08005874static void taiko_init_slim_slave_cfg(struct snd_soc_codec *codec)
5875{
5876 struct taiko_priv *priv = snd_soc_codec_get_drvdata(codec);
5877 struct afe_param_cdc_slimbus_slave_cfg *cfg;
5878 struct wcd9xxx *wcd9xxx = codec->control_data;
5879 uint64_t eaddr = 0;
5880
5881 cfg = &priv->slimbus_slave_cfg;
5882 cfg->minor_version = 1;
5883 cfg->tx_slave_port_offset = 0;
5884 cfg->rx_slave_port_offset = 16;
5885
5886 memcpy(&eaddr, &wcd9xxx->slim->e_addr, sizeof(wcd9xxx->slim->e_addr));
5887 WARN_ON(sizeof(wcd9xxx->slim->e_addr) != 6);
5888 cfg->device_enum_addr_lsw = eaddr & 0xFFFFFFFF;
5889 cfg->device_enum_addr_msw = eaddr >> 32;
5890
5891 pr_debug("%s: slimbus logical address 0x%llx\n", __func__, eaddr);
5892}
5893
Ravishankar Sarawadi839fcf32012-11-14 12:13:00 -08005894static int taiko_post_reset_cb(struct wcd9xxx *wcd9xxx)
5895{
5896 int ret = 0;
5897 struct snd_soc_codec *codec;
5898 struct taiko_priv *taiko;
5899
5900 codec = (struct snd_soc_codec *)(wcd9xxx->ssr_priv);
5901 taiko = snd_soc_codec_get_drvdata(codec);
5902 mutex_lock(&codec->mutex);
5903 WCD9XXX_BCL_LOCK(&taiko->resmgr);
Ravishankar Sarawadi839fcf32012-11-14 12:13:00 -08005904
5905 if (codec->reg_def_copy) {
5906 pr_debug("%s: Update ASOC cache", __func__);
5907 kfree(codec->reg_cache);
5908 codec->reg_cache = kmemdup(codec->reg_def_copy,
5909 codec->reg_size, GFP_KERNEL);
5910 }
5911
Ravishankar Sarawadi2293efe2013-01-11 16:37:23 -08005912 wcd9xxx_resmgr_post_ssr(&taiko->resmgr);
5913 if (spkr_drv_wrnd == 1)
5914 snd_soc_update_bits(codec, TAIKO_A_SPKR_DRV_EN, 0x80, 0x80);
5915 WCD9XXX_BCL_UNLOCK(&taiko->resmgr);
5916
Ravishankar Sarawadi839fcf32012-11-14 12:13:00 -08005917 taiko_update_reg_defaults(codec);
5918 taiko_codec_init_reg(codec);
5919 ret = taiko_handle_pdata(taiko);
5920 if (IS_ERR_VALUE(ret))
5921 pr_err("%s: bad pdata\n", __func__);
Ravishankar Sarawadi2293efe2013-01-11 16:37:23 -08005922
Joonwoo Park1d05bb92013-03-07 16:55:06 -08005923 taiko_init_slim_slave_cfg(codec);
5924
Ravishankar Sarawadi2293efe2013-01-11 16:37:23 -08005925 wcd9xxx_mbhc_deinit(&taiko->mbhc);
Simmi Pateriya0a44d842013-04-03 01:12:42 +05305926 ret = wcd9xxx_mbhc_init(&taiko->mbhc, &taiko->resmgr, codec,
5927 WCD9XXX_MBHC_VERSION_TAIKO);
Ravishankar Sarawadi2293efe2013-01-11 16:37:23 -08005928 if (ret)
5929 pr_err("%s: mbhc init failed %d\n", __func__, ret);
5930 else
5931 wcd9xxx_mbhc_start(&taiko->mbhc, taiko->mbhc.mbhc_cfg);
Ravishankar Sarawadi839fcf32012-11-14 12:13:00 -08005932 mutex_unlock(&codec->mutex);
5933 return ret;
5934}
5935
Joonwoo Park1d05bb92013-03-07 16:55:06 -08005936void *taiko_get_afe_config(struct snd_soc_codec *codec,
5937 enum afe_config_type config_type)
5938{
5939 struct taiko_priv *priv = snd_soc_codec_get_drvdata(codec);
5940
5941 switch (config_type) {
5942 case AFE_SLIMBUS_SLAVE_CONFIG:
5943 return &priv->slimbus_slave_cfg;
5944 case AFE_CDC_REGISTERS_CONFIG:
Damir Didjustodcfdff82013-03-21 23:26:41 -07005945 return &taiko_audio_reg_cfg;
Joonwoo Park1d05bb92013-03-07 16:55:06 -08005946 case AFE_SLIMBUS_SLAVE_PORT_CONFIG:
5947 return &taiko_slimbus_slave_port_cfg;
Damir Didjustodcfdff82013-03-21 23:26:41 -07005948 case AFE_AANC_VERSION:
5949 return &taiko_cdc_aanc_version;
Joonwoo Park1d05bb92013-03-07 16:55:06 -08005950 default:
5951 pr_err("%s: Unknown config_type 0x%x\n", __func__, config_type);
5952 return NULL;
5953 }
5954}
Ravishankar Sarawadi839fcf32012-11-14 12:13:00 -08005955
Joonwoo Parka8890262012-10-15 12:04:27 -07005956static struct wcd9xxx_reg_address taiko_reg_address = {
5957 .micb_4_mbhc = TAIKO_A_MICB_4_MBHC,
5958 .micb_4_int_rbias = TAIKO_A_MICB_4_INT_RBIAS,
5959 .micb_4_ctl = TAIKO_A_MICB_4_CTL,
5960};
5961
Ravishankar Sarawadi839fcf32012-11-14 12:13:00 -08005962static int wcd9xxx_ssr_register(struct wcd9xxx *control,
5963 int (*post_reset_cb)(struct wcd9xxx *wcd9xxx), void *priv)
5964{
5965 control->post_reset = post_reset_cb;
5966 control->ssr_priv = priv;
5967 return 0;
5968}
5969
Joonwoo Park2a9170a2013-03-04 17:05:57 -08005970static const struct snd_soc_dapm_widget taiko_1_dapm_widgets[] = {
5971 SND_SOC_DAPM_ADC_E("ADC1", NULL, TAIKO_A_TX_1_2_EN, 7, 0,
5972 taiko_codec_enable_adc,
5973 SND_SOC_DAPM_PRE_PMU |
5974 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
5975 SND_SOC_DAPM_ADC_E("ADC2", NULL, TAIKO_A_TX_1_2_EN, 3, 0,
5976 taiko_codec_enable_adc,
5977 SND_SOC_DAPM_PRE_PMU |
5978 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
5979 SND_SOC_DAPM_ADC_E("ADC3", NULL, TAIKO_A_TX_3_4_EN, 7, 0,
5980 taiko_codec_enable_adc,
5981 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
5982 SND_SOC_DAPM_POST_PMD),
5983 SND_SOC_DAPM_ADC_E("ADC4", NULL, TAIKO_A_TX_3_4_EN, 3, 0,
5984 taiko_codec_enable_adc,
5985 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
5986 SND_SOC_DAPM_POST_PMD),
5987 SND_SOC_DAPM_ADC_E("ADC5", NULL, TAIKO_A_TX_5_6_EN, 7, 0,
5988 taiko_codec_enable_adc,
5989 SND_SOC_DAPM_POST_PMU),
5990 SND_SOC_DAPM_ADC_E("ADC6", NULL, TAIKO_A_TX_5_6_EN, 3, 0,
5991 taiko_codec_enable_adc,
5992 SND_SOC_DAPM_POST_PMU),
5993};
5994
5995static const struct snd_soc_dapm_widget taiko_2_dapm_widgets[] = {
5996 SND_SOC_DAPM_ADC_E("ADC1", NULL, TAIKO_A_CDC_TX_1_GAIN, 7, 0,
5997 taiko_codec_enable_adc,
5998 SND_SOC_DAPM_PRE_PMU |
5999 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
6000 SND_SOC_DAPM_ADC_E("ADC2", NULL, TAIKO_A_CDC_TX_2_GAIN, 7, 0,
6001 taiko_codec_enable_adc,
6002 SND_SOC_DAPM_PRE_PMU |
6003 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
6004 SND_SOC_DAPM_ADC_E("ADC3", NULL, TAIKO_A_CDC_TX_3_GAIN, 7, 0,
6005 taiko_codec_enable_adc,
6006 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
6007 SND_SOC_DAPM_POST_PMD),
6008 SND_SOC_DAPM_ADC_E("ADC4", NULL, TAIKO_A_CDC_TX_4_GAIN, 7, 0,
6009 taiko_codec_enable_adc,
6010 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
6011 SND_SOC_DAPM_POST_PMD),
6012 SND_SOC_DAPM_ADC_E("ADC5", NULL, TAIKO_A_CDC_TX_5_GAIN, 7, 0,
6013 taiko_codec_enable_adc,
6014 SND_SOC_DAPM_POST_PMU),
6015 SND_SOC_DAPM_ADC_E("ADC6", NULL, TAIKO_A_CDC_TX_6_GAIN, 7, 0,
6016 taiko_codec_enable_adc,
6017 SND_SOC_DAPM_POST_PMU),
6018};
6019
Joonwoo Park448a8fc2013-04-10 15:25:58 -07006020static struct regulator *taiko_codec_find_regulator(struct snd_soc_codec *codec,
6021 const char *name)
6022{
6023 int i;
6024 struct wcd9xxx *core = dev_get_drvdata(codec->dev->parent);
6025
6026 for (i = 0; i < core->num_of_supplies; i++) {
6027 if (core->supplies[i].supply &&
6028 !strcmp(core->supplies[i].supply, name))
6029 return core->supplies[i].consumer;
6030 }
6031
6032 return NULL;
6033}
6034
Kiran Kandic3b24402012-06-11 00:05:59 -07006035static int taiko_codec_probe(struct snd_soc_codec *codec)
6036{
6037 struct wcd9xxx *control;
6038 struct taiko_priv *taiko;
Joonwoo Parka8890262012-10-15 12:04:27 -07006039 struct wcd9xxx_pdata *pdata;
6040 struct wcd9xxx *wcd9xxx;
Kiran Kandic3b24402012-06-11 00:05:59 -07006041 struct snd_soc_dapm_context *dapm = &codec->dapm;
6042 int ret = 0;
6043 int i;
Kuirong Wang906ac472012-07-09 12:54:44 -07006044 void *ptr = NULL;
Joonwoo Park559a5bf2013-02-15 14:46:36 -08006045 struct wcd9xxx *core = dev_get_drvdata(codec->dev->parent);
Kiran Kandic3b24402012-06-11 00:05:59 -07006046
6047 codec->control_data = dev_get_drvdata(codec->dev->parent);
6048 control = codec->control_data;
6049
Ravishankar Sarawadi839fcf32012-11-14 12:13:00 -08006050 wcd9xxx_ssr_register(control, taiko_post_reset_cb, (void *)codec);
6051
Kiran Kandi4c56c592012-07-25 11:04:55 -07006052 dev_info(codec->dev, "%s()\n", __func__);
6053
Kiran Kandic3b24402012-06-11 00:05:59 -07006054 taiko = kzalloc(sizeof(struct taiko_priv), GFP_KERNEL);
6055 if (!taiko) {
6056 dev_err(codec->dev, "Failed to allocate private data\n");
6057 return -ENOMEM;
6058 }
6059 for (i = 0 ; i < NUM_DECIMATORS; i++) {
6060 tx_hpf_work[i].taiko = taiko;
6061 tx_hpf_work[i].decimator = i + 1;
6062 INIT_DELAYED_WORK(&tx_hpf_work[i].dwork,
6063 tx_hpf_corner_freq_callback);
6064 }
6065
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08006066
Kiran Kandic3b24402012-06-11 00:05:59 -07006067 snd_soc_codec_set_drvdata(codec, taiko);
6068
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08006069
Joonwoo Parka8890262012-10-15 12:04:27 -07006070 /* codec resmgr module init */
6071 wcd9xxx = codec->control_data;
6072 pdata = dev_get_platdata(codec->dev->parent);
6073 ret = wcd9xxx_resmgr_init(&taiko->resmgr, codec, wcd9xxx, pdata,
6074 &taiko_reg_address);
6075 if (ret) {
6076 pr_err("%s: wcd9xxx init failed %d\n", __func__, ret);
6077 return ret;
6078 }
6079
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08006080 taiko->clsh_d.buck_mv = taiko_codec_get_buck_mv(codec);
Joonwoo Parka08e0552013-03-05 18:28:23 -08006081 wcd9xxx_clsh_init(&taiko->clsh_d, &taiko->resmgr);
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08006082
Joonwoo Parka8890262012-10-15 12:04:27 -07006083 /* init and start mbhc */
Simmi Pateriya0a44d842013-04-03 01:12:42 +05306084 ret = wcd9xxx_mbhc_init(&taiko->mbhc, &taiko->resmgr, codec,
6085 WCD9XXX_MBHC_VERSION_TAIKO);
Joonwoo Parka8890262012-10-15 12:04:27 -07006086 if (ret) {
6087 pr_err("%s: mbhc init failed %d\n", __func__, ret);
6088 return ret;
6089 }
6090
Kiran Kandic3b24402012-06-11 00:05:59 -07006091 taiko->codec = codec;
Kiran Kandic3b24402012-06-11 00:05:59 -07006092 for (i = 0; i < COMPANDER_MAX; i++) {
6093 taiko->comp_enabled[i] = 0;
6094 taiko->comp_fs[i] = COMPANDER_FS_48KHZ;
6095 }
Kiran Kandic3b24402012-06-11 00:05:59 -07006096 taiko->intf_type = wcd9xxx_get_intf_type();
6097 taiko->aux_pga_cnt = 0;
6098 taiko->aux_l_gain = 0x1F;
6099 taiko->aux_r_gain = 0x1F;
Kiran Kandic3b24402012-06-11 00:05:59 -07006100 taiko_update_reg_defaults(codec);
Venkat Sudhira50a3762012-11-26 12:12:15 -08006101 pr_debug("%s: MCLK Rate = %x\n", __func__, wcd9xxx->mclk_rate);
6102 if (wcd9xxx->mclk_rate == TAIKO_MCLK_CLK_12P288MHZ)
Venkat Sudhir16d95e62013-02-04 16:57:33 -08006103 snd_soc_update_bits(codec, TAIKO_A_CHIP_CTL, 0x06, 0x0);
Venkat Sudhira50a3762012-11-26 12:12:15 -08006104 else if (wcd9xxx->mclk_rate == TAIKO_MCLK_CLK_9P6HZ)
Venkat Sudhir16d95e62013-02-04 16:57:33 -08006105 snd_soc_update_bits(codec, TAIKO_A_CHIP_CTL, 0x06, 0x2);
Kiran Kandic3b24402012-06-11 00:05:59 -07006106 taiko_codec_init_reg(codec);
6107 ret = taiko_handle_pdata(taiko);
6108 if (IS_ERR_VALUE(ret)) {
6109 pr_err("%s: bad pdata\n", __func__);
6110 goto err_pdata;
6111 }
6112
Joonwoo Park448a8fc2013-04-10 15:25:58 -07006113 taiko->spkdrv_reg = taiko_codec_find_regulator(codec,
6114 WCD9XXX_VDD_SPKDRV_NAME);
6115
Joonwoo Park125cd4e2012-12-11 15:16:11 -08006116 if (spkr_drv_wrnd > 0) {
6117 WCD9XXX_BCL_LOCK(&taiko->resmgr);
6118 wcd9xxx_resmgr_get_bandgap(&taiko->resmgr,
6119 WCD9XXX_BANDGAP_AUDIO_MODE);
6120 WCD9XXX_BCL_UNLOCK(&taiko->resmgr);
6121 }
6122
Kuirong Wang906ac472012-07-09 12:54:44 -07006123 ptr = kmalloc((sizeof(taiko_rx_chs) +
6124 sizeof(taiko_tx_chs)), GFP_KERNEL);
6125 if (!ptr) {
6126 pr_err("%s: no mem for slim chan ctl data\n", __func__);
6127 ret = -ENOMEM;
6128 goto err_nomem_slimch;
6129 }
6130
Kiran Kandic3b24402012-06-11 00:05:59 -07006131 if (taiko->intf_type == WCD9XXX_INTERFACE_TYPE_I2C) {
6132 snd_soc_dapm_new_controls(dapm, taiko_dapm_i2s_widgets,
6133 ARRAY_SIZE(taiko_dapm_i2s_widgets));
6134 snd_soc_dapm_add_routes(dapm, audio_i2s_map,
6135 ARRAY_SIZE(audio_i2s_map));
Joonwoo Park559a5bf2013-02-15 14:46:36 -08006136 if (TAIKO_IS_1_0(core->version))
6137 snd_soc_dapm_add_routes(dapm, audio_i2s_map_1_0,
6138 ARRAY_SIZE(audio_i2s_map_1_0));
6139 else
6140 snd_soc_dapm_add_routes(dapm, audio_i2s_map_2_0,
6141 ARRAY_SIZE(audio_i2s_map_2_0));
Kuirong Wang906ac472012-07-09 12:54:44 -07006142 for (i = 0; i < ARRAY_SIZE(taiko_i2s_dai); i++)
6143 INIT_LIST_HEAD(&taiko->dai[i].wcd9xxx_ch_list);
6144 } else if (taiko->intf_type == WCD9XXX_INTERFACE_TYPE_SLIMBUS) {
6145 for (i = 0; i < NUM_CODEC_DAIS; i++) {
6146 INIT_LIST_HEAD(&taiko->dai[i].wcd9xxx_ch_list);
6147 init_waitqueue_head(&taiko->dai[i].dai_wait);
6148 }
Joonwoo Park1d05bb92013-03-07 16:55:06 -08006149 taiko_slimbus_slave_port_cfg.slave_dev_intfdev_la =
6150 control->slim_slave->laddr;
6151 taiko_slimbus_slave_port_cfg.slave_dev_pgd_la =
6152 control->slim->laddr;
6153 taiko_slimbus_slave_port_cfg.slave_port_mapping[0] =
6154 TAIKO_MAD_SLIMBUS_TX_PORT;
6155
6156 taiko_init_slim_slave_cfg(codec);
Kiran Kandic3b24402012-06-11 00:05:59 -07006157 }
6158
Kiran Kandiec0db5c2013-03-08 16:03:58 -08006159 if (TAIKO_IS_1_0(control->version)) {
Joonwoo Park2a9170a2013-03-04 17:05:57 -08006160 snd_soc_dapm_new_controls(dapm, taiko_1_dapm_widgets,
6161 ARRAY_SIZE(taiko_1_dapm_widgets));
Kiran Kandiec0db5c2013-03-08 16:03:58 -08006162 snd_soc_add_codec_controls(codec,
6163 taiko_1_x_analog_gain_controls,
6164 ARRAY_SIZE(taiko_1_x_analog_gain_controls));
6165 } else {
Joonwoo Park2a9170a2013-03-04 17:05:57 -08006166 snd_soc_dapm_new_controls(dapm, taiko_2_dapm_widgets,
6167 ARRAY_SIZE(taiko_2_dapm_widgets));
Kiran Kandiec0db5c2013-03-08 16:03:58 -08006168 snd_soc_add_codec_controls(codec,
6169 taiko_2_x_analog_gain_controls,
6170 ARRAY_SIZE(taiko_2_x_analog_gain_controls));
6171 }
Joonwoo Park2a9170a2013-03-04 17:05:57 -08006172
Kuirong Wang906ac472012-07-09 12:54:44 -07006173 control->num_rx_port = TAIKO_RX_MAX;
6174 control->rx_chs = ptr;
6175 memcpy(control->rx_chs, taiko_rx_chs, sizeof(taiko_rx_chs));
6176 control->num_tx_port = TAIKO_TX_MAX;
6177 control->tx_chs = ptr + sizeof(taiko_rx_chs);
6178 memcpy(control->tx_chs, taiko_tx_chs, sizeof(taiko_tx_chs));
6179
Kiran Kandic3b24402012-06-11 00:05:59 -07006180 snd_soc_dapm_sync(dapm);
6181
Joonwoo Park7680b9f2012-07-13 11:36:48 -07006182 (void) taiko_setup_irqs(taiko);
Kiran Kandic3b24402012-06-11 00:05:59 -07006183
Joonwoo Park125cd4e2012-12-11 15:16:11 -08006184 atomic_set(&kp_taiko_priv, (unsigned long)taiko);
Damir Didjusto2cb06bd2013-01-30 23:14:55 -08006185 mutex_lock(&dapm->codec->mutex);
6186 snd_soc_dapm_disable_pin(dapm, "ANC HPHL");
6187 snd_soc_dapm_disable_pin(dapm, "ANC HPHR");
6188 snd_soc_dapm_disable_pin(dapm, "ANC HEADPHONE");
6189 snd_soc_dapm_disable_pin(dapm, "ANC EAR PA");
6190 snd_soc_dapm_disable_pin(dapm, "ANC EAR");
6191 snd_soc_dapm_sync(dapm);
6192 mutex_unlock(&dapm->codec->mutex);
Joonwoo Park125cd4e2012-12-11 15:16:11 -08006193
Kiran Kandic3b24402012-06-11 00:05:59 -07006194 codec->ignore_pmdown_time = 1;
6195 return ret;
6196
Kiran Kandic3b24402012-06-11 00:05:59 -07006197err_pdata:
Kuirong Wang906ac472012-07-09 12:54:44 -07006198 kfree(ptr);
6199err_nomem_slimch:
Kiran Kandic3b24402012-06-11 00:05:59 -07006200 kfree(taiko);
6201 return ret;
6202}
6203static int taiko_codec_remove(struct snd_soc_codec *codec)
6204{
Kiran Kandic3b24402012-06-11 00:05:59 -07006205 struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
Joonwoo Parka8890262012-10-15 12:04:27 -07006206
Joonwoo Park125cd4e2012-12-11 15:16:11 -08006207 WCD9XXX_BCL_LOCK(&taiko->resmgr);
6208 atomic_set(&kp_taiko_priv, 0);
6209
6210 if (spkr_drv_wrnd > 0)
6211 wcd9xxx_resmgr_put_bandgap(&taiko->resmgr,
6212 WCD9XXX_BANDGAP_AUDIO_MODE);
6213 WCD9XXX_BCL_UNLOCK(&taiko->resmgr);
6214
Joonwoo Parka8890262012-10-15 12:04:27 -07006215 /* cleanup MBHC */
6216 wcd9xxx_mbhc_deinit(&taiko->mbhc);
6217 /* cleanup resmgr */
6218 wcd9xxx_resmgr_deinit(&taiko->resmgr);
6219
Joonwoo Park448a8fc2013-04-10 15:25:58 -07006220 taiko->spkdrv_reg = NULL;
6221
Kiran Kandic3b24402012-06-11 00:05:59 -07006222 kfree(taiko);
6223 return 0;
6224}
6225static struct snd_soc_codec_driver soc_codec_dev_taiko = {
6226 .probe = taiko_codec_probe,
6227 .remove = taiko_codec_remove,
6228
6229 .read = taiko_read,
6230 .write = taiko_write,
6231
6232 .readable_register = taiko_readable,
6233 .volatile_register = taiko_volatile,
6234
6235 .reg_cache_size = TAIKO_CACHE_SIZE,
Kiran Kandi7b7d2ff2012-09-14 14:52:14 -07006236 .reg_cache_default = taiko_reset_reg_defaults,
Kiran Kandic3b24402012-06-11 00:05:59 -07006237 .reg_word_size = 1,
6238
6239 .controls = taiko_snd_controls,
6240 .num_controls = ARRAY_SIZE(taiko_snd_controls),
6241 .dapm_widgets = taiko_dapm_widgets,
6242 .num_dapm_widgets = ARRAY_SIZE(taiko_dapm_widgets),
6243 .dapm_routes = audio_map,
6244 .num_dapm_routes = ARRAY_SIZE(audio_map),
6245};
6246
6247#ifdef CONFIG_PM
6248static int taiko_suspend(struct device *dev)
6249{
6250 dev_dbg(dev, "%s: system suspend\n", __func__);
6251 return 0;
6252}
6253
6254static int taiko_resume(struct device *dev)
6255{
6256 struct platform_device *pdev = to_platform_device(dev);
6257 struct taiko_priv *taiko = platform_get_drvdata(pdev);
6258 dev_dbg(dev, "%s: system resume\n", __func__);
Joonwoo Parka8890262012-10-15 12:04:27 -07006259 /* Notify */
6260 wcd9xxx_resmgr_notifier_call(&taiko->resmgr, WCD9XXX_EVENT_POST_RESUME);
Kiran Kandic3b24402012-06-11 00:05:59 -07006261 return 0;
6262}
6263
6264static const struct dev_pm_ops taiko_pm_ops = {
6265 .suspend = taiko_suspend,
6266 .resume = taiko_resume,
6267};
6268#endif
6269
6270static int __devinit taiko_probe(struct platform_device *pdev)
6271{
6272 int ret = 0;
6273 if (wcd9xxx_get_intf_type() == WCD9XXX_INTERFACE_TYPE_SLIMBUS)
6274 ret = snd_soc_register_codec(&pdev->dev, &soc_codec_dev_taiko,
6275 taiko_dai, ARRAY_SIZE(taiko_dai));
6276 else if (wcd9xxx_get_intf_type() == WCD9XXX_INTERFACE_TYPE_I2C)
6277 ret = snd_soc_register_codec(&pdev->dev, &soc_codec_dev_taiko,
6278 taiko_i2s_dai, ARRAY_SIZE(taiko_i2s_dai));
6279 return ret;
6280}
6281static int __devexit taiko_remove(struct platform_device *pdev)
6282{
6283 snd_soc_unregister_codec(&pdev->dev);
6284 return 0;
6285}
6286static struct platform_driver taiko_codec_driver = {
6287 .probe = taiko_probe,
6288 .remove = taiko_remove,
6289 .driver = {
6290 .name = "taiko_codec",
6291 .owner = THIS_MODULE,
6292#ifdef CONFIG_PM
6293 .pm = &taiko_pm_ops,
6294#endif
6295 },
6296};
6297
6298static int __init taiko_codec_init(void)
6299{
6300 return platform_driver_register(&taiko_codec_driver);
6301}
6302
6303static void __exit taiko_codec_exit(void)
6304{
6305 platform_driver_unregister(&taiko_codec_driver);
6306}
6307
6308module_init(taiko_codec_init);
6309module_exit(taiko_codec_exit);
6310
6311MODULE_DESCRIPTION("Taiko codec driver");
6312MODULE_LICENSE("GPL v2");