blob: 9c81cc4fa753246433a7c72543816a14530511cb [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"
Patrick Laiff5a5782013-05-05 00:13:00 -070044#define TAIKO_VALIDATE_RX_SBPORT_RANGE(port) ((port >= 16) && (port <= 22))
45#define TAIKO_CONVERT_RX_SBPORT_ID(port) (port - 16) /* RX1 port ID = 0 */
Joonwoo Park1d05bb92013-03-07 16:55:06 -080046
Bhalchandra Gajare9581aed2013-03-29 17:06:10 -070047#define TAIKO_HPH_PA_SETTLE_COMP_ON 3000
Bhalchandra Gajareef7810e2013-03-29 16:50:37 -070048#define TAIKO_HPH_PA_SETTLE_COMP_OFF 13000
49
Joonwoo Parkccccba72013-04-26 11:19:46 -070050#define DAPM_MICBIAS2_EXTERNAL_STANDALONE "MIC BIAS2 External Standalone"
51
Joonwoo Park125cd4e2012-12-11 15:16:11 -080052static atomic_t kp_taiko_priv;
53static int spkr_drv_wrnd_param_set(const char *val,
54 const struct kernel_param *kp);
55static int spkr_drv_wrnd = 1;
56
57static struct kernel_param_ops spkr_drv_wrnd_param_ops = {
58 .set = spkr_drv_wrnd_param_set,
59 .get = param_get_int,
60};
Joonwoo Park1d05bb92013-03-07 16:55:06 -080061
62static struct afe_param_slimbus_slave_port_cfg taiko_slimbus_slave_port_cfg = {
63 .minor_version = 1,
64 .slimbus_dev_id = AFE_SLIMBUS_DEVICE_1,
65 .slave_dev_pgd_la = 0,
66 .slave_dev_intfdev_la = 0,
67 .bit_width = 16,
68 .data_format = 0,
69 .num_channels = 1
70};
71
72enum {
73 RESERVED = 0,
74 AANC_LPF_FF_FB = 1,
75 AANC_LPF_COEFF_MSB,
76 AANC_LPF_COEFF_LSB,
77 HW_MAD_AUDIO_ENABLE,
78 HW_MAD_ULTR_ENABLE,
79 HW_MAD_BEACON_ENABLE,
80 HW_MAD_AUDIO_SLEEP_TIME,
81 HW_MAD_ULTR_SLEEP_TIME,
82 HW_MAD_BEACON_SLEEP_TIME,
83 HW_MAD_TX_AUDIO_SWITCH_OFF,
84 HW_MAD_TX_ULTR_SWITCH_OFF,
85 HW_MAD_TX_BEACON_SWITCH_OFF,
86 MAD_AUDIO_INT_DEST_SELECT_REG,
87 MAD_ULT_INT_DEST_SELECT_REG,
88 MAD_BEACON_INT_DEST_SELECT_REG,
89 MAD_CLIP_INT_DEST_SELECT_REG,
90 MAD_VBAT_INT_DEST_SELECT_REG,
91 MAD_AUDIO_INT_MASK_REG,
92 MAD_ULT_INT_MASK_REG,
93 MAD_BEACON_INT_MASK_REG,
94 MAD_CLIP_INT_MASK_REG,
95 MAD_VBAT_INT_MASK_REG,
96 MAD_AUDIO_INT_STATUS_REG,
97 MAD_ULT_INT_STATUS_REG,
98 MAD_BEACON_INT_STATUS_REG,
99 MAD_CLIP_INT_STATUS_REG,
100 MAD_VBAT_INT_STATUS_REG,
101 MAD_AUDIO_INT_CLEAR_REG,
102 MAD_ULT_INT_CLEAR_REG,
103 MAD_BEACON_INT_CLEAR_REG,
104 MAD_CLIP_INT_CLEAR_REG,
105 MAD_VBAT_INT_CLEAR_REG,
106 SB_PGD_PORT_TX_WATERMARK_n,
107 SB_PGD_PORT_TX_ENABLE_n,
108 SB_PGD_PORT_RX_WATERMARK_n,
109 SB_PGD_PORT_RX_ENABLE_n,
Damir Didjustodcfdff82013-03-21 23:26:41 -0700110 SB_PGD_TX_PORTn_MULTI_CHNL_0,
111 SB_PGD_TX_PORTn_MULTI_CHNL_1,
112 SB_PGD_RX_PORTn_MULTI_CHNL_0,
113 SB_PGD_RX_PORTn_MULTI_CHNL_1,
114 AANC_FF_GAIN_ADAPTIVE,
115 AANC_FFGAIN_ADAPTIVE_EN,
116 AANC_GAIN_CONTROL,
Gopikrishnaiah Anandaneb51dd72013-04-09 11:39:55 -0400117 SPKR_CLIP_PIPE_BANK_SEL,
118 SPKR_CLIPDET_VAL0,
119 SPKR_CLIPDET_VAL1,
120 SPKR_CLIPDET_VAL2,
121 SPKR_CLIPDET_VAL3,
122 SPKR_CLIPDET_VAL4,
123 SPKR_CLIPDET_VAL5,
124 SPKR_CLIPDET_VAL6,
125 SPKR_CLIPDET_VAL7,
Joonwoo Park1d05bb92013-03-07 16:55:06 -0800126 MAX_CFG_REGISTERS,
127};
128
Damir Didjustodcfdff82013-03-21 23:26:41 -0700129static struct afe_param_cdc_reg_cfg audio_reg_cfg[] = {
Joonwoo Park1d05bb92013-03-07 16:55:06 -0800130 {
131 1,
132 (TAIKO_REGISTER_START_OFFSET + TAIKO_A_CDC_MAD_MAIN_CTL_1),
133 HW_MAD_AUDIO_ENABLE, 0x1, 8, 0
134 },
135 {
136 1,
137 (TAIKO_REGISTER_START_OFFSET + TAIKO_A_CDC_MAD_AUDIO_CTL_3),
138 HW_MAD_AUDIO_SLEEP_TIME, 0xF, 8, 0
139 },
140 {
141 1,
142 (TAIKO_REGISTER_START_OFFSET + TAIKO_A_CDC_MAD_AUDIO_CTL_4),
143 HW_MAD_TX_AUDIO_SWITCH_OFF, 0x1, 8, 0
144 },
145 {
146 1,
147 (TAIKO_REGISTER_START_OFFSET + TAIKO_A_INTR_DESTN3),
148 MAD_AUDIO_INT_DEST_SELECT_REG, 0x1, 8, 0
149 },
150 {
151 1,
152 (TAIKO_REGISTER_START_OFFSET + TAIKO_A_INTR_MASK3),
153 MAD_AUDIO_INT_MASK_REG, 0x1, 8, 0
154 },
155 {
156 1,
157 (TAIKO_REGISTER_START_OFFSET + TAIKO_A_INTR_STATUS3),
158 MAD_AUDIO_INT_STATUS_REG, 0x1, 8, 0
159 },
160 {
161 1,
162 (TAIKO_REGISTER_START_OFFSET + TAIKO_A_INTR_CLEAR3),
163 MAD_AUDIO_INT_CLEAR_REG, 0x1, 8, 0
164 },
165 {
166 1,
167 (TAIKO_REGISTER_START_OFFSET + TAIKO_SB_PGD_PORT_TX_BASE),
168 SB_PGD_PORT_TX_WATERMARK_n, 0x1E, 8, 0x1
169 },
170 {
171 1,
172 (TAIKO_REGISTER_START_OFFSET + TAIKO_SB_PGD_PORT_TX_BASE),
173 SB_PGD_PORT_TX_ENABLE_n, 0x1, 8, 0x1
174 },
175 {
176 1,
177 (TAIKO_REGISTER_START_OFFSET + TAIKO_SB_PGD_PORT_RX_BASE),
178 SB_PGD_PORT_RX_WATERMARK_n, 0x1E, 8, 0x1
179 },
180 {
181 1,
182 (TAIKO_REGISTER_START_OFFSET + TAIKO_SB_PGD_PORT_RX_BASE),
183 SB_PGD_PORT_RX_ENABLE_n, 0x1, 8, 0x1
Damir Didjustodcfdff82013-03-21 23:26:41 -0700184 },
185 { 1,
186 (TAIKO_REGISTER_START_OFFSET + TAIKO_A_CDC_ANC1_IIR_B1_CTL),
187 AANC_FF_GAIN_ADAPTIVE, 0x4, 8, 0
188 },
189 { 1,
190 (TAIKO_REGISTER_START_OFFSET + TAIKO_A_CDC_ANC1_IIR_B1_CTL),
191 AANC_FFGAIN_ADAPTIVE_EN, 0x8, 8, 0
192 },
193 {
194 1,
195 (TAIKO_REGISTER_START_OFFSET + TAIKO_A_CDC_ANC1_GAIN_CTL),
196 AANC_GAIN_CONTROL, 0xFF, 8, 0
197 },
Gopikrishnaiah Anandaneb51dd72013-04-09 11:39:55 -0400198 {
199 1,
200 (TAIKO_REGISTER_START_OFFSET + TAIKO_A_INTR_DESTN3),
201 MAD_CLIP_INT_DEST_SELECT_REG, 0x8, 8, 0
202 },
203 {
204 1,
205 (TAIKO_REGISTER_START_OFFSET + TAIKO_A_INTR_MASK3),
206 MAD_CLIP_INT_MASK_REG, 0x8, 8, 0
207 },
208 {
209 1,
210 (TAIKO_REGISTER_START_OFFSET + TAIKO_A_INTR_STATUS3),
211 MAD_CLIP_INT_STATUS_REG, 0x8, 8, 0
212 },
213 {
214 1,
215 (TAIKO_REGISTER_START_OFFSET + TAIKO_A_INTR_CLEAR3),
216 MAD_CLIP_INT_CLEAR_REG, 0x8, 8, 0
217 },
218};
219
220static struct afe_param_cdc_reg_cfg clip_reg_cfg[] = {
221 {
222 1,
223 (TAIKO_REGISTER_START_OFFSET + TAIKO_A_CDC_SPKR_CLIPDET_B1_CTL),
Gopikrishnaiah Anandand3b89c02013-04-16 11:22:15 -0400224 SPKR_CLIP_PIPE_BANK_SEL, 0x3, 8, 0
Gopikrishnaiah Anandaneb51dd72013-04-09 11:39:55 -0400225 },
226 {
227 1,
228 (TAIKO_REGISTER_START_OFFSET + TAIKO_A_CDC_SPKR_CLIPDET_VAL0),
Gopikrishnaiah Anandand3b89c02013-04-16 11:22:15 -0400229 SPKR_CLIPDET_VAL0, 0xff, 8, 0
Gopikrishnaiah Anandaneb51dd72013-04-09 11:39:55 -0400230 },
231 {
232 1,
233 (TAIKO_REGISTER_START_OFFSET + TAIKO_A_CDC_SPKR_CLIPDET_VAL1),
Gopikrishnaiah Anandand3b89c02013-04-16 11:22:15 -0400234 SPKR_CLIPDET_VAL1, 0xff, 8, 0
Gopikrishnaiah Anandaneb51dd72013-04-09 11:39:55 -0400235 },
236 {
237 1,
238 (TAIKO_REGISTER_START_OFFSET + TAIKO_A_CDC_SPKR_CLIPDET_VAL2),
Gopikrishnaiah Anandand3b89c02013-04-16 11:22:15 -0400239 SPKR_CLIPDET_VAL2, 0xff, 8, 0
Gopikrishnaiah Anandaneb51dd72013-04-09 11:39:55 -0400240 },
241 {
242 1,
243 (TAIKO_REGISTER_START_OFFSET + TAIKO_A_CDC_SPKR_CLIPDET_VAL3),
Gopikrishnaiah Anandand3b89c02013-04-16 11:22:15 -0400244 SPKR_CLIPDET_VAL3, 0xff, 8, 0
Gopikrishnaiah Anandaneb51dd72013-04-09 11:39:55 -0400245 },
246 {
247 1,
248 (TAIKO_REGISTER_START_OFFSET + TAIKO_A_CDC_SPKR_CLIPDET_VAL4),
Gopikrishnaiah Anandand3b89c02013-04-16 11:22:15 -0400249 SPKR_CLIPDET_VAL4, 0xff, 8, 0
Gopikrishnaiah Anandaneb51dd72013-04-09 11:39:55 -0400250 },
251 {
252 1,
253 (TAIKO_REGISTER_START_OFFSET + TAIKO_A_CDC_SPKR_CLIPDET_VAL5),
Gopikrishnaiah Anandand3b89c02013-04-16 11:22:15 -0400254 SPKR_CLIPDET_VAL5, 0xff, 8, 0
Gopikrishnaiah Anandaneb51dd72013-04-09 11:39:55 -0400255 },
256 {
257 1,
258 (TAIKO_REGISTER_START_OFFSET + TAIKO_A_CDC_SPKR_CLIPDET_VAL6),
Gopikrishnaiah Anandand3b89c02013-04-16 11:22:15 -0400259 SPKR_CLIPDET_VAL6, 0xff, 8, 0
Gopikrishnaiah Anandaneb51dd72013-04-09 11:39:55 -0400260 },
261 {
262 1,
263 (TAIKO_REGISTER_START_OFFSET + TAIKO_A_CDC_SPKR_CLIPDET_VAL7),
Gopikrishnaiah Anandand3b89c02013-04-16 11:22:15 -0400264 SPKR_CLIPDET_VAL7, 0xff, 8, 0
Gopikrishnaiah Anandaneb51dd72013-04-09 11:39:55 -0400265 },
Joonwoo Park1d05bb92013-03-07 16:55:06 -0800266};
267
Damir Didjustodcfdff82013-03-21 23:26:41 -0700268static struct afe_param_cdc_reg_cfg_data taiko_audio_reg_cfg = {
269 .num_registers = ARRAY_SIZE(audio_reg_cfg),
270 .reg_data = audio_reg_cfg,
271};
272
Gopikrishnaiah Anandaneb51dd72013-04-09 11:39:55 -0400273static struct afe_param_cdc_reg_cfg_data taiko_clip_reg_cfg = {
274 .num_registers = ARRAY_SIZE(clip_reg_cfg),
275 .reg_data = clip_reg_cfg,
276};
277
Damir Didjustodcfdff82013-03-21 23:26:41 -0700278static struct afe_param_id_cdc_aanc_version taiko_cdc_aanc_version = {
279 .cdc_aanc_minor_version = AFE_API_VERSION_CDC_AANC_VERSION,
280 .aanc_hw_version = AANC_HW_BLOCK_VERSION_2,
Joonwoo Park1d05bb92013-03-07 16:55:06 -0800281};
282
Gopikrishnaiah Anandaneb51dd72013-04-09 11:39:55 -0400283static struct afe_param_id_clip_bank_sel clip_bank_sel = {
284 .minor_version = AFE_API_VERSION_CLIP_BANK_SEL_CFG,
285 .num_banks = AFE_CLIP_MAX_BANKS,
286 .bank_map = {0, 1, 2, 3},
287};
288
Joonwoo Park125cd4e2012-12-11 15:16:11 -0800289module_param_cb(spkr_drv_wrnd, &spkr_drv_wrnd_param_ops, &spkr_drv_wrnd, 0644);
290MODULE_PARM_DESC(spkr_drv_wrnd,
291 "Run software workaround to avoid leakage on the speaker drive");
292
Kiran Kandic3b24402012-06-11 00:05:59 -0700293#define WCD9320_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |\
294 SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 |\
295 SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000)
296
Kiran Kandic3b24402012-06-11 00:05:59 -0700297#define NUM_DECIMATORS 10
298#define NUM_INTERPOLATORS 7
299#define BITS_PER_REG 8
Kuirong Wang906ac472012-07-09 12:54:44 -0700300#define TAIKO_TX_PORT_NUMBER 16
Kuirong Wang80aca0d2013-05-09 14:51:09 -0700301#define TAIKO_RX_PORT_START_NUMBER 16
Kiran Kandic3b24402012-06-11 00:05:59 -0700302
Kiran Kandic3b24402012-06-11 00:05:59 -0700303#define TAIKO_I2S_MASTER_MODE_MASK 0x08
Damir Didjusto1a353ce2013-04-02 11:45:47 -0700304
305#define TAIKO_DMIC_SAMPLE_RATE_DIV_2 0x0
306#define TAIKO_DMIC_SAMPLE_RATE_DIV_3 0x1
307#define TAIKO_DMIC_SAMPLE_RATE_DIV_4 0x2
308
309#define TAIKO_DMIC_B1_CTL_DIV_2 0x00
310#define TAIKO_DMIC_B1_CTL_DIV_3 0x22
311#define TAIKO_DMIC_B1_CTL_DIV_4 0x44
312
313#define TAIKO_DMIC_B2_CTL_DIV_2 0x00
314#define TAIKO_DMIC_B2_CTL_DIV_3 0x02
315#define TAIKO_DMIC_B2_CTL_DIV_4 0x04
316
317#define TAIKO_ANC_DMIC_X2_ON 0x1
318#define TAIKO_ANC_DMIC_X2_OFF 0x0
Joonwoo Park9bbb4d12012-11-09 19:58:11 -0800319
320#define TAIKO_SLIM_CLOSE_TIMEOUT 1000
321#define TAIKO_SLIM_IRQ_OVERFLOW (1 << 0)
322#define TAIKO_SLIM_IRQ_UNDERFLOW (1 << 1)
323#define TAIKO_SLIM_IRQ_PORT_CLOSED (1 << 2)
Venkat Sudhira50a3762012-11-26 12:12:15 -0800324#define TAIKO_MCLK_CLK_12P288MHZ 12288000
Phani Kumar Uppalapati43bc4152013-05-24 00:44:20 -0700325#define TAIKO_MCLK_CLK_9P6MHZ 9600000
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -0800326
Bhalchandra Gajare5b40c532013-02-19 13:36:47 -0800327#define TAIKO_FORMATS_S16_S24_LE (SNDRV_PCM_FMTBIT_S16_LE | \
328 SNDRV_PCM_FORMAT_S24_LE)
329
330#define TAIKO_FORMATS (SNDRV_PCM_FMTBIT_S16_LE)
331
Kuirong Wang906ac472012-07-09 12:54:44 -0700332enum {
333 AIF1_PB = 0,
334 AIF1_CAP,
335 AIF2_PB,
336 AIF2_CAP,
337 AIF3_PB,
338 AIF3_CAP,
Gopikrishnaiah Anandana2627572013-02-26 13:30:50 -0500339 AIF4_VIFEED,
Joonwoo Park1d05bb92013-03-07 16:55:06 -0800340 AIF4_MAD_TX,
Kuirong Wang906ac472012-07-09 12:54:44 -0700341 NUM_CODEC_DAIS,
Kiran Kandic3b24402012-06-11 00:05:59 -0700342};
343
Kuirong Wang906ac472012-07-09 12:54:44 -0700344enum {
345 RX_MIX1_INP_SEL_ZERO = 0,
346 RX_MIX1_INP_SEL_SRC1,
347 RX_MIX1_INP_SEL_SRC2,
348 RX_MIX1_INP_SEL_IIR1,
349 RX_MIX1_INP_SEL_IIR2,
350 RX_MIX1_INP_SEL_RX1,
351 RX_MIX1_INP_SEL_RX2,
352 RX_MIX1_INP_SEL_RX3,
353 RX_MIX1_INP_SEL_RX4,
354 RX_MIX1_INP_SEL_RX5,
355 RX_MIX1_INP_SEL_RX6,
356 RX_MIX1_INP_SEL_RX7,
357 RX_MIX1_INP_SEL_AUXRX,
358};
359
360#define TAIKO_COMP_DIGITAL_GAIN_OFFSET 3
361
Kiran Kandic3b24402012-06-11 00:05:59 -0700362static const DECLARE_TLV_DB_SCALE(digital_gain, 0, 1, 0);
363static const DECLARE_TLV_DB_SCALE(line_gain, 0, 7, 1);
364static const DECLARE_TLV_DB_SCALE(analog_gain, 0, 25, 1);
365static struct snd_soc_dai_driver taiko_dai[];
366static const DECLARE_TLV_DB_SCALE(aux_pga_gain, 0, 2, 0);
367
Kiran Kandic3b24402012-06-11 00:05:59 -0700368/* Codec supports 2 IIR filters */
369enum {
370 IIR1 = 0,
371 IIR2,
372 IIR_MAX,
373};
374/* Codec supports 5 bands */
375enum {
376 BAND1 = 0,
377 BAND2,
378 BAND3,
379 BAND4,
380 BAND5,
381 BAND_MAX,
382};
383
384enum {
Joonwoo Parkc7731432012-10-17 12:41:44 -0700385 COMPANDER_0,
386 COMPANDER_1,
Kiran Kandic3b24402012-06-11 00:05:59 -0700387 COMPANDER_2,
388 COMPANDER_MAX,
389};
390
391enum {
392 COMPANDER_FS_8KHZ = 0,
393 COMPANDER_FS_16KHZ,
394 COMPANDER_FS_32KHZ,
395 COMPANDER_FS_48KHZ,
396 COMPANDER_FS_96KHZ,
397 COMPANDER_FS_192KHZ,
398 COMPANDER_FS_MAX,
399};
400
Kiran Kandic3b24402012-06-11 00:05:59 -0700401struct comp_sample_dependent_params {
402 u32 peak_det_timeout;
403 u32 rms_meter_div_fact;
404 u32 rms_meter_resamp_fact;
405};
406
Kiran Kandic3b24402012-06-11 00:05:59 -0700407struct hpf_work {
408 struct taiko_priv *taiko;
409 u32 decimator;
410 u8 tx_hpf_cut_of_freq;
411 struct delayed_work dwork;
412};
413
414static struct hpf_work tx_hpf_work[NUM_DECIMATORS];
415
Kuirong Wang906ac472012-07-09 12:54:44 -0700416static const struct wcd9xxx_ch taiko_rx_chs[TAIKO_RX_MAX] = {
Kuirong Wang80aca0d2013-05-09 14:51:09 -0700417 WCD9XXX_CH(TAIKO_RX_PORT_START_NUMBER, 0),
418 WCD9XXX_CH(TAIKO_RX_PORT_START_NUMBER + 1, 1),
419 WCD9XXX_CH(TAIKO_RX_PORT_START_NUMBER + 2, 2),
420 WCD9XXX_CH(TAIKO_RX_PORT_START_NUMBER + 3, 3),
421 WCD9XXX_CH(TAIKO_RX_PORT_START_NUMBER + 4, 4),
422 WCD9XXX_CH(TAIKO_RX_PORT_START_NUMBER + 5, 5),
423 WCD9XXX_CH(TAIKO_RX_PORT_START_NUMBER + 6, 6),
424 WCD9XXX_CH(TAIKO_RX_PORT_START_NUMBER + 7, 7),
425 WCD9XXX_CH(TAIKO_RX_PORT_START_NUMBER + 8, 8),
426 WCD9XXX_CH(TAIKO_RX_PORT_START_NUMBER + 9, 9),
427 WCD9XXX_CH(TAIKO_RX_PORT_START_NUMBER + 10, 10),
428 WCD9XXX_CH(TAIKO_RX_PORT_START_NUMBER + 11, 11),
429 WCD9XXX_CH(TAIKO_RX_PORT_START_NUMBER + 12, 12),
Kuirong Wang906ac472012-07-09 12:54:44 -0700430};
431
432static const struct wcd9xxx_ch taiko_tx_chs[TAIKO_TX_MAX] = {
433 WCD9XXX_CH(0, 0),
434 WCD9XXX_CH(1, 1),
435 WCD9XXX_CH(2, 2),
436 WCD9XXX_CH(3, 3),
437 WCD9XXX_CH(4, 4),
438 WCD9XXX_CH(5, 5),
439 WCD9XXX_CH(6, 6),
440 WCD9XXX_CH(7, 7),
441 WCD9XXX_CH(8, 8),
442 WCD9XXX_CH(9, 9),
443 WCD9XXX_CH(10, 10),
444 WCD9XXX_CH(11, 11),
445 WCD9XXX_CH(12, 12),
446 WCD9XXX_CH(13, 13),
447 WCD9XXX_CH(14, 14),
448 WCD9XXX_CH(15, 15),
449};
450
451static const u32 vport_check_table[NUM_CODEC_DAIS] = {
452 0, /* AIF1_PB */
453 (1 << AIF2_CAP) | (1 << AIF3_CAP), /* AIF1_CAP */
454 0, /* AIF2_PB */
455 (1 << AIF1_CAP) | (1 << AIF3_CAP), /* AIF2_CAP */
456 0, /* AIF2_PB */
457 (1 << AIF1_CAP) | (1 << AIF2_CAP), /* AIF2_CAP */
458};
459
Venkat Sudhir96dd28c2012-12-04 17:00:19 -0800460static const u32 vport_i2s_check_table[NUM_CODEC_DAIS] = {
461 0, /* AIF1_PB */
462 0, /* AIF1_CAP */
Venkat Sudhir994193b2012-12-17 17:30:51 -0800463 0, /* AIF2_PB */
464 0, /* AIF2_CAP */
Venkat Sudhir96dd28c2012-12-04 17:00:19 -0800465};
466
Kiran Kandic3b24402012-06-11 00:05:59 -0700467struct taiko_priv {
468 struct snd_soc_codec *codec;
Kiran Kandic3b24402012-06-11 00:05:59 -0700469 u32 adc_count;
Kiran Kandic3b24402012-06-11 00:05:59 -0700470 u32 rx_bias_count;
471 s32 dmic_1_2_clk_cnt;
472 s32 dmic_3_4_clk_cnt;
473 s32 dmic_5_6_clk_cnt;
Joonwoo Parkccccba72013-04-26 11:19:46 -0700474 s32 ldo_h_users;
475 s32 micb_2_users;
Kiran Kandic3b24402012-06-11 00:05:59 -0700476
Kiran Kandic3b24402012-06-11 00:05:59 -0700477 u32 anc_slot;
Damir Didjusto2cb06bd2013-01-30 23:14:55 -0800478 bool anc_func;
Kiran Kandic3b24402012-06-11 00:05:59 -0700479
Kiran Kandic3b24402012-06-11 00:05:59 -0700480 /*track taiko interface type*/
481 u8 intf_type;
482
Kiran Kandic3b24402012-06-11 00:05:59 -0700483 /* num of slim ports required */
Kuirong Wang906ac472012-07-09 12:54:44 -0700484 struct wcd9xxx_codec_dai_data dai[NUM_CODEC_DAIS];
Kiran Kandic3b24402012-06-11 00:05:59 -0700485
486 /*compander*/
487 int comp_enabled[COMPANDER_MAX];
488 u32 comp_fs[COMPANDER_MAX];
489
490 /* Maintain the status of AUX PGA */
491 int aux_pga_cnt;
492 u8 aux_l_gain;
493 u8 aux_r_gain;
494
Joonwoo Park125cd4e2012-12-11 15:16:11 -0800495 bool spkr_pa_widget_on;
Joonwoo Park448a8fc2013-04-10 15:25:58 -0700496 struct regulator *spkdrv_reg;
Joonwoo Park125cd4e2012-12-11 15:16:11 -0800497
Joonwoo Park88bfa842013-04-15 16:59:21 -0700498 bool mbhc_started;
499
Joonwoo Park1d05bb92013-03-07 16:55:06 -0800500 struct afe_param_cdc_slimbus_slave_cfg slimbus_slave_cfg;
501
Joonwoo Parka8890262012-10-15 12:04:27 -0700502 /* resmgr module */
503 struct wcd9xxx_resmgr resmgr;
504 /* mbhc module */
505 struct wcd9xxx_mbhc mbhc;
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -0800506
507 /* class h specific data */
508 struct wcd9xxx_clsh_cdc_data clsh_d;
Kiran Kandia1bed422013-05-28 18:29:12 -0700509
510 int (*machine_codec_event_cb)(struct snd_soc_codec *codec,
511 enum wcd9xxx_codec_event);
Kiran Kandic3b24402012-06-11 00:05:59 -0700512};
513
Kiran Kandic3b24402012-06-11 00:05:59 -0700514static const u32 comp_shift[] = {
Joonwoo Parkc7731432012-10-17 12:41:44 -0700515 4, /* Compander 0's clock source is on interpolator 7 */
Kiran Kandic3b24402012-06-11 00:05:59 -0700516 0,
517 2,
518};
519
520static const int comp_rx_path[] = {
521 COMPANDER_1,
522 COMPANDER_1,
523 COMPANDER_2,
524 COMPANDER_2,
525 COMPANDER_2,
526 COMPANDER_2,
Joonwoo Parkc7731432012-10-17 12:41:44 -0700527 COMPANDER_0,
Kiran Kandic3b24402012-06-11 00:05:59 -0700528 COMPANDER_MAX,
529};
530
531static const struct comp_sample_dependent_params comp_samp_params[] = {
532 {
Joonwoo Parkc7731432012-10-17 12:41:44 -0700533 /* 8 Khz */
Bhalchandra Gajareed090e62013-03-29 16:11:49 -0700534 .peak_det_timeout = 0x06,
Joonwoo Parkc7731432012-10-17 12:41:44 -0700535 .rms_meter_div_fact = 0x09,
536 .rms_meter_resamp_fact = 0x06,
Kiran Kandic3b24402012-06-11 00:05:59 -0700537 },
538 {
Joonwoo Parkc7731432012-10-17 12:41:44 -0700539 /* 16 Khz */
Bhalchandra Gajareed090e62013-03-29 16:11:49 -0700540 .peak_det_timeout = 0x07,
Joonwoo Parkc7731432012-10-17 12:41:44 -0700541 .rms_meter_div_fact = 0x0A,
542 .rms_meter_resamp_fact = 0x0C,
543 },
544 {
545 /* 32 Khz */
Bhalchandra Gajareed090e62013-03-29 16:11:49 -0700546 .peak_det_timeout = 0x08,
Joonwoo Parkc7731432012-10-17 12:41:44 -0700547 .rms_meter_div_fact = 0x0B,
548 .rms_meter_resamp_fact = 0x1E,
549 },
550 {
551 /* 48 Khz */
Bhalchandra Gajareed090e62013-03-29 16:11:49 -0700552 .peak_det_timeout = 0x09,
Joonwoo Parkc7731432012-10-17 12:41:44 -0700553 .rms_meter_div_fact = 0x0B,
Kiran Kandic3b24402012-06-11 00:05:59 -0700554 .rms_meter_resamp_fact = 0x28,
555 },
Kiran Kandic3b24402012-06-11 00:05:59 -0700556 {
Joonwoo Parkc7731432012-10-17 12:41:44 -0700557 /* 96 Khz */
Bhalchandra Gajareed090e62013-03-29 16:11:49 -0700558 .peak_det_timeout = 0x0A,
Joonwoo Parkc7731432012-10-17 12:41:44 -0700559 .rms_meter_div_fact = 0x0C,
560 .rms_meter_resamp_fact = 0x50,
Kiran Kandic3b24402012-06-11 00:05:59 -0700561 },
Kiran Kandic3b24402012-06-11 00:05:59 -0700562 {
Joonwoo Parkc7731432012-10-17 12:41:44 -0700563 /* 192 Khz */
Bhalchandra Gajareed090e62013-03-29 16:11:49 -0700564 .peak_det_timeout = 0x0B,
565 .rms_meter_div_fact = 0xC,
566 .rms_meter_resamp_fact = 0x50,
Kiran Kandic3b24402012-06-11 00:05:59 -0700567 },
568};
569
570static unsigned short rx_digital_gain_reg[] = {
571 TAIKO_A_CDC_RX1_VOL_CTL_B2_CTL,
572 TAIKO_A_CDC_RX2_VOL_CTL_B2_CTL,
573 TAIKO_A_CDC_RX3_VOL_CTL_B2_CTL,
574 TAIKO_A_CDC_RX4_VOL_CTL_B2_CTL,
575 TAIKO_A_CDC_RX5_VOL_CTL_B2_CTL,
576 TAIKO_A_CDC_RX6_VOL_CTL_B2_CTL,
577 TAIKO_A_CDC_RX7_VOL_CTL_B2_CTL,
578};
579
580
581static unsigned short tx_digital_gain_reg[] = {
582 TAIKO_A_CDC_TX1_VOL_CTL_GAIN,
583 TAIKO_A_CDC_TX2_VOL_CTL_GAIN,
584 TAIKO_A_CDC_TX3_VOL_CTL_GAIN,
585 TAIKO_A_CDC_TX4_VOL_CTL_GAIN,
586 TAIKO_A_CDC_TX5_VOL_CTL_GAIN,
587 TAIKO_A_CDC_TX6_VOL_CTL_GAIN,
588 TAIKO_A_CDC_TX7_VOL_CTL_GAIN,
589 TAIKO_A_CDC_TX8_VOL_CTL_GAIN,
590 TAIKO_A_CDC_TX9_VOL_CTL_GAIN,
591 TAIKO_A_CDC_TX10_VOL_CTL_GAIN,
592};
593
Joonwoo Park125cd4e2012-12-11 15:16:11 -0800594static int spkr_drv_wrnd_param_set(const char *val,
595 const struct kernel_param *kp)
596{
597 struct snd_soc_codec *codec;
598 int ret, old;
599 struct taiko_priv *priv;
600
601 priv = (struct taiko_priv *)atomic_read(&kp_taiko_priv);
602 if (!priv) {
603 pr_debug("%s: codec isn't yet registered\n", __func__);
604 return 0;
605 }
606
Joonwoo Park973fd352013-06-19 11:38:53 -0700607 codec = priv->codec;
608 mutex_lock(&codec->mutex);
Joonwoo Park125cd4e2012-12-11 15:16:11 -0800609 old = spkr_drv_wrnd;
610 ret = param_set_int(val, kp);
611 if (ret) {
Joonwoo Park973fd352013-06-19 11:38:53 -0700612 mutex_unlock(&codec->mutex);
Joonwoo Park125cd4e2012-12-11 15:16:11 -0800613 return ret;
614 }
615
616 pr_debug("%s: spkr_drv_wrnd %d -> %d\n", __func__, old, spkr_drv_wrnd);
Joonwoo Park973fd352013-06-19 11:38:53 -0700617 if ((old == -1 || old == 0) && spkr_drv_wrnd == 1) {
Joonwoo Park533b3682013-06-13 11:41:21 -0700618 WCD9XXX_BG_CLK_LOCK(&priv->resmgr);
Joonwoo Park125cd4e2012-12-11 15:16:11 -0800619 wcd9xxx_resmgr_get_bandgap(&priv->resmgr,
620 WCD9XXX_BANDGAP_AUDIO_MODE);
Joonwoo Park533b3682013-06-13 11:41:21 -0700621 WCD9XXX_BG_CLK_UNLOCK(&priv->resmgr);
Joonwoo Park125cd4e2012-12-11 15:16:11 -0800622 snd_soc_update_bits(codec, TAIKO_A_SPKR_DRV_EN, 0x80, 0x80);
623 } else if (old == 1 && spkr_drv_wrnd == 0) {
Joonwoo Park533b3682013-06-13 11:41:21 -0700624 WCD9XXX_BG_CLK_LOCK(&priv->resmgr);
Joonwoo Park125cd4e2012-12-11 15:16:11 -0800625 wcd9xxx_resmgr_put_bandgap(&priv->resmgr,
626 WCD9XXX_BANDGAP_AUDIO_MODE);
Joonwoo Park533b3682013-06-13 11:41:21 -0700627 WCD9XXX_BG_CLK_UNLOCK(&priv->resmgr);
Joonwoo Park125cd4e2012-12-11 15:16:11 -0800628 if (!priv->spkr_pa_widget_on)
629 snd_soc_update_bits(codec, TAIKO_A_SPKR_DRV_EN, 0x80,
630 0x00);
631 }
Joonwoo Park973fd352013-06-19 11:38:53 -0700632 mutex_unlock(&codec->mutex);
Joonwoo Park125cd4e2012-12-11 15:16:11 -0800633
Joonwoo Park125cd4e2012-12-11 15:16:11 -0800634 return 0;
635}
636
Kiran Kandic3b24402012-06-11 00:05:59 -0700637static int taiko_get_anc_slot(struct snd_kcontrol *kcontrol,
638 struct snd_ctl_elem_value *ucontrol)
639{
640 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
641 struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
642 ucontrol->value.integer.value[0] = taiko->anc_slot;
643 return 0;
644}
645
646static int taiko_put_anc_slot(struct snd_kcontrol *kcontrol,
647 struct snd_ctl_elem_value *ucontrol)
648{
649 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
650 struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
651 taiko->anc_slot = ucontrol->value.integer.value[0];
652 return 0;
653}
654
Damir Didjusto2cb06bd2013-01-30 23:14:55 -0800655static int taiko_get_anc_func(struct snd_kcontrol *kcontrol,
656 struct snd_ctl_elem_value *ucontrol)
657{
658 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
659 struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
660
661 ucontrol->value.integer.value[0] = (taiko->anc_func == true ? 1 : 0);
662 return 0;
663}
664
665static int taiko_put_anc_func(struct snd_kcontrol *kcontrol,
666 struct snd_ctl_elem_value *ucontrol)
667{
668 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
669 struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
670 struct snd_soc_dapm_context *dapm = &codec->dapm;
671
672 mutex_lock(&dapm->codec->mutex);
673 taiko->anc_func = (!ucontrol->value.integer.value[0] ? false : true);
674
675 dev_dbg(codec->dev, "%s: anc_func %x", __func__, taiko->anc_func);
676
677 if (taiko->anc_func == true) {
678 snd_soc_dapm_enable_pin(dapm, "ANC HPHR");
679 snd_soc_dapm_enable_pin(dapm, "ANC HPHL");
680 snd_soc_dapm_enable_pin(dapm, "ANC HEADPHONE");
681 snd_soc_dapm_enable_pin(dapm, "ANC EAR PA");
682 snd_soc_dapm_enable_pin(dapm, "ANC EAR");
683 snd_soc_dapm_disable_pin(dapm, "HPHR");
684 snd_soc_dapm_disable_pin(dapm, "HPHL");
685 snd_soc_dapm_disable_pin(dapm, "HEADPHONE");
686 snd_soc_dapm_disable_pin(dapm, "EAR PA");
687 snd_soc_dapm_disable_pin(dapm, "EAR");
688 } else {
689 snd_soc_dapm_disable_pin(dapm, "ANC HPHR");
690 snd_soc_dapm_disable_pin(dapm, "ANC HPHL");
691 snd_soc_dapm_disable_pin(dapm, "ANC HEADPHONE");
692 snd_soc_dapm_disable_pin(dapm, "ANC EAR PA");
693 snd_soc_dapm_disable_pin(dapm, "ANC EAR");
694 snd_soc_dapm_enable_pin(dapm, "HPHR");
695 snd_soc_dapm_enable_pin(dapm, "HPHL");
696 snd_soc_dapm_enable_pin(dapm, "HEADPHONE");
697 snd_soc_dapm_enable_pin(dapm, "EAR PA");
698 snd_soc_dapm_enable_pin(dapm, "EAR");
699 }
700 snd_soc_dapm_sync(dapm);
701 mutex_unlock(&dapm->codec->mutex);
702 return 0;
703}
704
Kiran Kandic3b24402012-06-11 00:05:59 -0700705static int taiko_get_iir_enable_audio_mixer(
706 struct snd_kcontrol *kcontrol,
707 struct snd_ctl_elem_value *ucontrol)
708{
709 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
710 int iir_idx = ((struct soc_multi_mixer_control *)
711 kcontrol->private_value)->reg;
712 int band_idx = ((struct soc_multi_mixer_control *)
713 kcontrol->private_value)->shift;
714
715 ucontrol->value.integer.value[0] =
Ben Romberger205e14d2013-02-06 12:31:53 -0800716 (snd_soc_read(codec, (TAIKO_A_CDC_IIR1_CTL + 16 * iir_idx)) &
717 (1 << band_idx)) != 0;
Kiran Kandic3b24402012-06-11 00:05:59 -0700718
719 pr_debug("%s: IIR #%d band #%d enable %d\n", __func__,
720 iir_idx, band_idx,
721 (uint32_t)ucontrol->value.integer.value[0]);
722 return 0;
723}
724
725static int taiko_put_iir_enable_audio_mixer(
726 struct snd_kcontrol *kcontrol,
727 struct snd_ctl_elem_value *ucontrol)
728{
729 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
730 int iir_idx = ((struct soc_multi_mixer_control *)
731 kcontrol->private_value)->reg;
732 int band_idx = ((struct soc_multi_mixer_control *)
733 kcontrol->private_value)->shift;
734 int value = ucontrol->value.integer.value[0];
735
736 /* Mask first 5 bits, 6-8 are reserved */
737 snd_soc_update_bits(codec, (TAIKO_A_CDC_IIR1_CTL + 16 * iir_idx),
738 (1 << band_idx), (value << band_idx));
739
740 pr_debug("%s: IIR #%d band #%d enable %d\n", __func__,
Ben Romberger205e14d2013-02-06 12:31:53 -0800741 iir_idx, band_idx,
742 ((snd_soc_read(codec, (TAIKO_A_CDC_IIR1_CTL + 16 * iir_idx)) &
743 (1 << band_idx)) != 0));
Kiran Kandic3b24402012-06-11 00:05:59 -0700744 return 0;
745}
746static uint32_t get_iir_band_coeff(struct snd_soc_codec *codec,
747 int iir_idx, int band_idx,
748 int coeff_idx)
749{
Ben Romberger205e14d2013-02-06 12:31:53 -0800750 uint32_t value = 0;
751
Kiran Kandic3b24402012-06-11 00:05:59 -0700752 /* Address does not automatically update if reading */
753 snd_soc_write(codec,
754 (TAIKO_A_CDC_IIR1_COEF_B1_CTL + 16 * iir_idx),
Ben Romberger205e14d2013-02-06 12:31:53 -0800755 ((band_idx * BAND_MAX + coeff_idx)
756 * sizeof(uint32_t)) & 0x7F);
757
758 value |= snd_soc_read(codec,
759 (TAIKO_A_CDC_IIR1_COEF_B2_CTL + 16 * iir_idx));
760
761 snd_soc_write(codec,
762 (TAIKO_A_CDC_IIR1_COEF_B1_CTL + 16 * iir_idx),
763 ((band_idx * BAND_MAX + coeff_idx)
764 * sizeof(uint32_t) + 1) & 0x7F);
765
766 value |= (snd_soc_read(codec,
767 (TAIKO_A_CDC_IIR1_COEF_B2_CTL + 16 * iir_idx)) << 8);
768
769 snd_soc_write(codec,
770 (TAIKO_A_CDC_IIR1_COEF_B1_CTL + 16 * iir_idx),
771 ((band_idx * BAND_MAX + coeff_idx)
772 * sizeof(uint32_t) + 2) & 0x7F);
773
774 value |= (snd_soc_read(codec,
775 (TAIKO_A_CDC_IIR1_COEF_B2_CTL + 16 * iir_idx)) << 16);
776
777 snd_soc_write(codec,
778 (TAIKO_A_CDC_IIR1_COEF_B1_CTL + 16 * iir_idx),
779 ((band_idx * BAND_MAX + coeff_idx)
780 * sizeof(uint32_t) + 3) & 0x7F);
Kiran Kandic3b24402012-06-11 00:05:59 -0700781
782 /* Mask bits top 2 bits since they are reserved */
Ben Romberger205e14d2013-02-06 12:31:53 -0800783 value |= ((snd_soc_read(codec,
784 (TAIKO_A_CDC_IIR1_COEF_B2_CTL + 16 * iir_idx)) & 0x3F) << 24);
785
786 return value;
Kiran Kandic3b24402012-06-11 00:05:59 -0700787}
788
789static int taiko_get_iir_band_audio_mixer(
790 struct snd_kcontrol *kcontrol,
791 struct snd_ctl_elem_value *ucontrol)
792{
793 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
794 int iir_idx = ((struct soc_multi_mixer_control *)
795 kcontrol->private_value)->reg;
796 int band_idx = ((struct soc_multi_mixer_control *)
797 kcontrol->private_value)->shift;
798
799 ucontrol->value.integer.value[0] =
800 get_iir_band_coeff(codec, iir_idx, band_idx, 0);
801 ucontrol->value.integer.value[1] =
802 get_iir_band_coeff(codec, iir_idx, band_idx, 1);
803 ucontrol->value.integer.value[2] =
804 get_iir_band_coeff(codec, iir_idx, band_idx, 2);
805 ucontrol->value.integer.value[3] =
806 get_iir_band_coeff(codec, iir_idx, band_idx, 3);
807 ucontrol->value.integer.value[4] =
808 get_iir_band_coeff(codec, iir_idx, band_idx, 4);
809
810 pr_debug("%s: IIR #%d band #%d b0 = 0x%x\n"
811 "%s: IIR #%d band #%d b1 = 0x%x\n"
812 "%s: IIR #%d band #%d b2 = 0x%x\n"
813 "%s: IIR #%d band #%d a1 = 0x%x\n"
814 "%s: IIR #%d band #%d a2 = 0x%x\n",
815 __func__, iir_idx, band_idx,
816 (uint32_t)ucontrol->value.integer.value[0],
817 __func__, iir_idx, band_idx,
818 (uint32_t)ucontrol->value.integer.value[1],
819 __func__, iir_idx, band_idx,
820 (uint32_t)ucontrol->value.integer.value[2],
821 __func__, iir_idx, band_idx,
822 (uint32_t)ucontrol->value.integer.value[3],
823 __func__, iir_idx, band_idx,
824 (uint32_t)ucontrol->value.integer.value[4]);
825 return 0;
826}
827
828static void set_iir_band_coeff(struct snd_soc_codec *codec,
829 int iir_idx, int band_idx,
Ben Romberger205e14d2013-02-06 12:31:53 -0800830 uint32_t value)
Kiran Kandic3b24402012-06-11 00:05:59 -0700831{
Kiran Kandic3b24402012-06-11 00:05:59 -0700832 snd_soc_write(codec,
Ben Romberger205e14d2013-02-06 12:31:53 -0800833 (TAIKO_A_CDC_IIR1_COEF_B2_CTL + 16 * iir_idx),
834 (value & 0xFF));
835
836 snd_soc_write(codec,
837 (TAIKO_A_CDC_IIR1_COEF_B2_CTL + 16 * iir_idx),
838 (value >> 8) & 0xFF);
839
840 snd_soc_write(codec,
841 (TAIKO_A_CDC_IIR1_COEF_B2_CTL + 16 * iir_idx),
842 (value >> 16) & 0xFF);
Kiran Kandic3b24402012-06-11 00:05:59 -0700843
844 /* Mask top 2 bits, 7-8 are reserved */
845 snd_soc_write(codec,
846 (TAIKO_A_CDC_IIR1_COEF_B2_CTL + 16 * iir_idx),
847 (value >> 24) & 0x3F);
Kiran Kandic3b24402012-06-11 00:05:59 -0700848}
849
850static int taiko_put_iir_band_audio_mixer(
851 struct snd_kcontrol *kcontrol,
852 struct snd_ctl_elem_value *ucontrol)
853{
854 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
855 int iir_idx = ((struct soc_multi_mixer_control *)
856 kcontrol->private_value)->reg;
857 int band_idx = ((struct soc_multi_mixer_control *)
858 kcontrol->private_value)->shift;
859
Ben Romberger205e14d2013-02-06 12:31:53 -0800860 /* Mask top bit it is reserved */
861 /* Updates addr automatically for each B2 write */
862 snd_soc_write(codec,
863 (TAIKO_A_CDC_IIR1_COEF_B1_CTL + 16 * iir_idx),
864 (band_idx * BAND_MAX * sizeof(uint32_t)) & 0x7F);
865
866 set_iir_band_coeff(codec, iir_idx, band_idx,
Kiran Kandic3b24402012-06-11 00:05:59 -0700867 ucontrol->value.integer.value[0]);
Ben Romberger205e14d2013-02-06 12:31:53 -0800868 set_iir_band_coeff(codec, iir_idx, band_idx,
Kiran Kandic3b24402012-06-11 00:05:59 -0700869 ucontrol->value.integer.value[1]);
Ben Romberger205e14d2013-02-06 12:31:53 -0800870 set_iir_band_coeff(codec, iir_idx, band_idx,
Kiran Kandic3b24402012-06-11 00:05:59 -0700871 ucontrol->value.integer.value[2]);
Ben Romberger205e14d2013-02-06 12:31:53 -0800872 set_iir_band_coeff(codec, iir_idx, band_idx,
Kiran Kandic3b24402012-06-11 00:05:59 -0700873 ucontrol->value.integer.value[3]);
Ben Romberger205e14d2013-02-06 12:31:53 -0800874 set_iir_band_coeff(codec, iir_idx, band_idx,
Kiran Kandic3b24402012-06-11 00:05:59 -0700875 ucontrol->value.integer.value[4]);
876
877 pr_debug("%s: IIR #%d band #%d b0 = 0x%x\n"
878 "%s: IIR #%d band #%d b1 = 0x%x\n"
879 "%s: IIR #%d band #%d b2 = 0x%x\n"
880 "%s: IIR #%d band #%d a1 = 0x%x\n"
881 "%s: IIR #%d band #%d a2 = 0x%x\n",
882 __func__, iir_idx, band_idx,
883 get_iir_band_coeff(codec, iir_idx, band_idx, 0),
884 __func__, iir_idx, band_idx,
885 get_iir_band_coeff(codec, iir_idx, band_idx, 1),
886 __func__, iir_idx, band_idx,
887 get_iir_band_coeff(codec, iir_idx, band_idx, 2),
888 __func__, iir_idx, band_idx,
889 get_iir_band_coeff(codec, iir_idx, band_idx, 3),
890 __func__, iir_idx, band_idx,
891 get_iir_band_coeff(codec, iir_idx, band_idx, 4));
892 return 0;
893}
894
Kiran Kandic3b24402012-06-11 00:05:59 -0700895static int taiko_get_compander(struct snd_kcontrol *kcontrol,
Joonwoo Parkc7731432012-10-17 12:41:44 -0700896 struct snd_ctl_elem_value *ucontrol)
Kiran Kandic3b24402012-06-11 00:05:59 -0700897{
898
899 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
900 int comp = ((struct soc_multi_mixer_control *)
Joonwoo Parkc7731432012-10-17 12:41:44 -0700901 kcontrol->private_value)->shift;
Kiran Kandic3b24402012-06-11 00:05:59 -0700902 struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
903
904 ucontrol->value.integer.value[0] = taiko->comp_enabled[comp];
Kiran Kandic3b24402012-06-11 00:05:59 -0700905 return 0;
906}
907
908static int taiko_set_compander(struct snd_kcontrol *kcontrol,
Joonwoo Parkc7731432012-10-17 12:41:44 -0700909 struct snd_ctl_elem_value *ucontrol)
Kiran Kandic3b24402012-06-11 00:05:59 -0700910{
911 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
912 struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
913 int comp = ((struct soc_multi_mixer_control *)
Joonwoo Parkc7731432012-10-17 12:41:44 -0700914 kcontrol->private_value)->shift;
Kiran Kandic3b24402012-06-11 00:05:59 -0700915 int value = ucontrol->value.integer.value[0];
916
Joonwoo Parkc7731432012-10-17 12:41:44 -0700917 pr_debug("%s: Compander %d enable current %d, new %d\n",
918 __func__, comp, taiko->comp_enabled[comp], value);
Kiran Kandic3b24402012-06-11 00:05:59 -0700919 taiko->comp_enabled[comp] = value;
Bhalchandra Gajareef7810e2013-03-29 16:50:37 -0700920
921 if (comp == COMPANDER_1 &&
922 taiko->comp_enabled[comp] == 1) {
923 /* Wavegen to 5 msec */
924 snd_soc_write(codec, TAIKO_A_RX_HPH_CNP_WG_CTL, 0xDA);
925 snd_soc_write(codec, TAIKO_A_RX_HPH_CNP_WG_TIME, 0x15);
926 snd_soc_write(codec, TAIKO_A_RX_HPH_BIAS_WG_OCP, 0x2A);
927
928 /* Enable Chopper */
929 snd_soc_update_bits(codec,
930 TAIKO_A_RX_HPH_CHOP_CTL, 0x80, 0x80);
Bhalchandra Gajare9581aed2013-03-29 17:06:10 -0700931
932 snd_soc_write(codec, TAIKO_A_NCP_DTEST, 0x20);
Bhalchandra Gajareef7810e2013-03-29 16:50:37 -0700933 pr_debug("%s: Enabled Chopper and set wavegen to 5 msec\n",
934 __func__);
935 } else if (comp == COMPANDER_1 &&
936 taiko->comp_enabled[comp] == 0) {
937 /* Wavegen to 20 msec */
938 snd_soc_write(codec, TAIKO_A_RX_HPH_CNP_WG_CTL, 0xDB);
939 snd_soc_write(codec, TAIKO_A_RX_HPH_CNP_WG_TIME, 0x58);
940 snd_soc_write(codec, TAIKO_A_RX_HPH_BIAS_WG_OCP, 0x1A);
941
942 /* Disable CHOPPER block */
943 snd_soc_update_bits(codec,
944 TAIKO_A_RX_HPH_CHOP_CTL, 0x80, 0x00);
Bhalchandra Gajare9581aed2013-03-29 17:06:10 -0700945
946 snd_soc_write(codec, TAIKO_A_NCP_DTEST, 0x10);
Bhalchandra Gajareef7810e2013-03-29 16:50:37 -0700947 pr_debug("%s: Disabled Chopper and set wavegen to 20 msec\n",
948 __func__);
949 }
Kiran Kandic3b24402012-06-11 00:05:59 -0700950 return 0;
951}
952
Joonwoo Parkc7731432012-10-17 12:41:44 -0700953static int taiko_config_gain_compander(struct snd_soc_codec *codec,
954 int comp, bool enable)
955{
956 int ret = 0;
957
958 switch (comp) {
959 case COMPANDER_0:
960 snd_soc_update_bits(codec, TAIKO_A_SPKR_DRV_GAIN,
961 1 << 2, !enable << 2);
962 break;
963 case COMPANDER_1:
964 snd_soc_update_bits(codec, TAIKO_A_RX_HPH_L_GAIN,
965 1 << 5, !enable << 5);
966 snd_soc_update_bits(codec, TAIKO_A_RX_HPH_R_GAIN,
967 1 << 5, !enable << 5);
968 break;
969 case COMPANDER_2:
970 snd_soc_update_bits(codec, TAIKO_A_RX_LINE_1_GAIN,
971 1 << 5, !enable << 5);
972 snd_soc_update_bits(codec, TAIKO_A_RX_LINE_3_GAIN,
973 1 << 5, !enable << 5);
974 snd_soc_update_bits(codec, TAIKO_A_RX_LINE_2_GAIN,
975 1 << 5, !enable << 5);
976 snd_soc_update_bits(codec, TAIKO_A_RX_LINE_4_GAIN,
977 1 << 5, !enable << 5);
978 break;
979 default:
980 WARN_ON(1);
981 ret = -EINVAL;
982 }
983
984 return ret;
985}
986
987static void taiko_discharge_comp(struct snd_soc_codec *codec, int comp)
988{
Bhalchandra Gajareed090e62013-03-29 16:11:49 -0700989 /* Level meter DIV Factor to 5*/
Joonwoo Parkc7731432012-10-17 12:41:44 -0700990 snd_soc_update_bits(codec, TAIKO_A_CDC_COMP0_B2_CTL + (comp * 8), 0xF0,
Bhalchandra Gajareed090e62013-03-29 16:11:49 -0700991 0x05 << 4);
992 /* RMS meter Sampling to 0x01 */
993 snd_soc_write(codec, TAIKO_A_CDC_COMP0_B3_CTL + (comp * 8), 0x01);
994
995 /* Worst case timeout for compander CnP sleep timeout */
996 usleep_range(3000, 3000);
997}
998
999static enum wcd9xxx_buck_volt taiko_codec_get_buck_mv(
1000 struct snd_soc_codec *codec)
1001{
1002 int buck_volt = WCD9XXX_CDC_BUCK_UNSUPPORTED;
1003 struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
1004 struct wcd9xxx_pdata *pdata = taiko->resmgr.pdata;
1005 int i;
1006
1007 for (i = 0; i < ARRAY_SIZE(pdata->regulator); i++) {
1008 if (!strncmp(pdata->regulator[i].name,
1009 WCD9XXX_SUPPLY_BUCK_NAME,
1010 sizeof(WCD9XXX_SUPPLY_BUCK_NAME))) {
1011 if ((pdata->regulator[i].min_uV ==
1012 WCD9XXX_CDC_BUCK_MV_1P8) ||
1013 (pdata->regulator[i].min_uV ==
1014 WCD9XXX_CDC_BUCK_MV_2P15))
1015 buck_volt = pdata->regulator[i].min_uV;
1016 break;
1017 }
1018 }
1019 return buck_volt;
Joonwoo Parkc7731432012-10-17 12:41:44 -07001020}
Kiran Kandic3b24402012-06-11 00:05:59 -07001021
1022static int taiko_config_compander(struct snd_soc_dapm_widget *w,
Joonwoo Parkc7731432012-10-17 12:41:44 -07001023 struct snd_kcontrol *kcontrol, int event)
Kiran Kandic3b24402012-06-11 00:05:59 -07001024{
Bhalchandra Gajareed090e62013-03-29 16:11:49 -07001025 int mask, enable_mask;
Kiran Kandic3b24402012-06-11 00:05:59 -07001026 struct snd_soc_codec *codec = w->codec;
1027 struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
Joonwoo Parkc7731432012-10-17 12:41:44 -07001028 const int comp = w->shift;
1029 const u32 rate = taiko->comp_fs[comp];
1030 const struct comp_sample_dependent_params *comp_params =
1031 &comp_samp_params[rate];
Bhalchandra Gajareed090e62013-03-29 16:11:49 -07001032 enum wcd9xxx_buck_volt buck_mv;
Kiran Kandic3b24402012-06-11 00:05:59 -07001033
Joonwoo Parkc7731432012-10-17 12:41:44 -07001034 pr_debug("%s: %s event %d compander %d, enabled %d", __func__,
1035 w->name, event, comp, taiko->comp_enabled[comp]);
1036
1037 if (!taiko->comp_enabled[comp])
1038 return 0;
1039
1040 /* Compander 0 has single channel */
1041 mask = (comp == COMPANDER_0 ? 0x01 : 0x03);
Bhalchandra Gajareed090e62013-03-29 16:11:49 -07001042 enable_mask = (comp == COMPANDER_0 ? 0x02 : 0x03);
1043 buck_mv = taiko_codec_get_buck_mv(codec);
Kiran Kandid2b46332012-10-05 12:04:00 -07001044
Kiran Kandic3b24402012-06-11 00:05:59 -07001045 switch (event) {
1046 case SND_SOC_DAPM_PRE_PMU:
Bhalchandra Gajareed090e62013-03-29 16:11:49 -07001047 /* Set compander Sample rate */
1048 snd_soc_update_bits(codec,
1049 TAIKO_A_CDC_COMP0_FS_CFG + (comp * 8),
1050 0x07, rate);
1051 /* Set the static gain offset */
1052 if (comp == COMPANDER_1
Kuirong Wang865534c2013-06-25 14:32:51 -07001053 && buck_mv == WCD9XXX_CDC_BUCK_MV_1P8) {
Bhalchandra Gajareed090e62013-03-29 16:11:49 -07001054 snd_soc_update_bits(codec,
1055 TAIKO_A_CDC_COMP0_B4_CTL + (comp * 8),
1056 0x80, 0x80);
1057 } else {
1058 snd_soc_update_bits(codec,
1059 TAIKO_A_CDC_COMP0_B4_CTL + (comp * 8),
1060 0x80, 0x00);
1061 }
1062 /* Enable RX interpolation path compander clocks */
Joonwoo Parkc7731432012-10-17 12:41:44 -07001063 snd_soc_update_bits(codec, TAIKO_A_CDC_CLK_RX_B2_CTL,
1064 mask << comp_shift[comp],
1065 mask << comp_shift[comp]);
Joonwoo Parkc7731432012-10-17 12:41:44 -07001066 /* Toggle compander reset bits */
1067 snd_soc_update_bits(codec, TAIKO_A_CDC_CLK_OTHR_RESET_B2_CTL,
1068 mask << comp_shift[comp],
1069 mask << comp_shift[comp]);
1070 snd_soc_update_bits(codec, TAIKO_A_CDC_CLK_OTHR_RESET_B2_CTL,
1071 mask << comp_shift[comp], 0);
Bhalchandra Gajareed090e62013-03-29 16:11:49 -07001072
1073 /* Set gain source to compander */
1074 taiko_config_gain_compander(codec, comp, true);
1075
1076 /* Compander enable */
1077 snd_soc_update_bits(codec, TAIKO_A_CDC_COMP0_B1_CTL +
1078 (comp * 8), enable_mask, enable_mask);
1079
1080 taiko_discharge_comp(codec, comp);
1081
Joonwoo Parkc7731432012-10-17 12:41:44 -07001082 /* Set sample rate dependent paramater */
Joonwoo Parkc7731432012-10-17 12:41:44 -07001083 snd_soc_write(codec, TAIKO_A_CDC_COMP0_B3_CTL + (comp * 8),
1084 comp_params->rms_meter_resamp_fact);
1085 snd_soc_update_bits(codec,
1086 TAIKO_A_CDC_COMP0_B2_CTL + (comp * 8),
Joonwoo Parkc7731432012-10-17 12:41:44 -07001087 0xF0, comp_params->rms_meter_div_fact << 4);
Bhalchandra Gajareed090e62013-03-29 16:11:49 -07001088 snd_soc_update_bits(codec,
1089 TAIKO_A_CDC_COMP0_B2_CTL + (comp * 8),
1090 0x0F, comp_params->peak_det_timeout);
Kiran Kandic3b24402012-06-11 00:05:59 -07001091 break;
1092 case SND_SOC_DAPM_PRE_PMD:
Joonwoo Parkc7731432012-10-17 12:41:44 -07001093 /* Disable compander */
1094 snd_soc_update_bits(codec,
1095 TAIKO_A_CDC_COMP0_B1_CTL + (comp * 8),
Bhalchandra Gajareed090e62013-03-29 16:11:49 -07001096 enable_mask, 0x00);
1097
1098 /* Toggle compander reset bits */
1099 snd_soc_update_bits(codec, TAIKO_A_CDC_CLK_OTHR_RESET_B2_CTL,
1100 mask << comp_shift[comp],
1101 mask << comp_shift[comp]);
1102 snd_soc_update_bits(codec, TAIKO_A_CDC_CLK_OTHR_RESET_B2_CTL,
1103 mask << comp_shift[comp], 0);
1104
Joonwoo Parkc7731432012-10-17 12:41:44 -07001105 /* Turn off the clock for compander in pair */
1106 snd_soc_update_bits(codec, TAIKO_A_CDC_CLK_RX_B2_CTL,
1107 mask << comp_shift[comp], 0);
Bhalchandra Gajareed090e62013-03-29 16:11:49 -07001108
Joonwoo Parkc7731432012-10-17 12:41:44 -07001109 /* Set gain source to register */
1110 taiko_config_gain_compander(codec, comp, false);
Kiran Kandic3b24402012-06-11 00:05:59 -07001111 break;
1112 }
1113 return 0;
1114}
1115
Kiran Kandiec0db5c2013-03-08 16:03:58 -08001116
Kiran Kandic3b24402012-06-11 00:05:59 -07001117
Damir Didjusto2cb06bd2013-01-30 23:14:55 -08001118static const char *const taiko_anc_func_text[] = {"OFF", "ON"};
1119static const struct soc_enum taiko_anc_func_enum =
1120 SOC_ENUM_SINGLE_EXT(2, taiko_anc_func_text);
1121
1122static const char *const tabla_ear_pa_gain_text[] = {"POS_6_DB", "POS_2_DB"};
1123static const struct soc_enum tabla_ear_pa_gain_enum[] = {
1124 SOC_ENUM_SINGLE_EXT(2, tabla_ear_pa_gain_text),
1125};
1126
Kiran Kandic3b24402012-06-11 00:05:59 -07001127/*cut of frequency for high pass filter*/
1128static const char * const cf_text[] = {
1129 "MIN_3DB_4Hz", "MIN_3DB_75Hz", "MIN_3DB_150Hz"
1130};
1131
1132static const struct soc_enum cf_dec1_enum =
1133 SOC_ENUM_SINGLE(TAIKO_A_CDC_TX1_MUX_CTL, 4, 3, cf_text);
1134
1135static const struct soc_enum cf_dec2_enum =
1136 SOC_ENUM_SINGLE(TAIKO_A_CDC_TX2_MUX_CTL, 4, 3, cf_text);
1137
1138static const struct soc_enum cf_dec3_enum =
1139 SOC_ENUM_SINGLE(TAIKO_A_CDC_TX3_MUX_CTL, 4, 3, cf_text);
1140
1141static const struct soc_enum cf_dec4_enum =
1142 SOC_ENUM_SINGLE(TAIKO_A_CDC_TX4_MUX_CTL, 4, 3, cf_text);
1143
1144static const struct soc_enum cf_dec5_enum =
1145 SOC_ENUM_SINGLE(TAIKO_A_CDC_TX5_MUX_CTL, 4, 3, cf_text);
1146
1147static const struct soc_enum cf_dec6_enum =
1148 SOC_ENUM_SINGLE(TAIKO_A_CDC_TX6_MUX_CTL, 4, 3, cf_text);
1149
1150static const struct soc_enum cf_dec7_enum =
1151 SOC_ENUM_SINGLE(TAIKO_A_CDC_TX7_MUX_CTL, 4, 3, cf_text);
1152
1153static const struct soc_enum cf_dec8_enum =
1154 SOC_ENUM_SINGLE(TAIKO_A_CDC_TX8_MUX_CTL, 4, 3, cf_text);
1155
1156static const struct soc_enum cf_dec9_enum =
1157 SOC_ENUM_SINGLE(TAIKO_A_CDC_TX9_MUX_CTL, 4, 3, cf_text);
1158
1159static const struct soc_enum cf_dec10_enum =
1160 SOC_ENUM_SINGLE(TAIKO_A_CDC_TX10_MUX_CTL, 4, 3, cf_text);
1161
1162static const struct soc_enum cf_rxmix1_enum =
Joonwoo Park2000a982013-03-01 14:50:31 -08001163 SOC_ENUM_SINGLE(TAIKO_A_CDC_RX1_B4_CTL, 0, 3, cf_text);
Kiran Kandic3b24402012-06-11 00:05:59 -07001164
1165static const struct soc_enum cf_rxmix2_enum =
Joonwoo Park2000a982013-03-01 14:50:31 -08001166 SOC_ENUM_SINGLE(TAIKO_A_CDC_RX2_B4_CTL, 0, 3, cf_text);
Kiran Kandic3b24402012-06-11 00:05:59 -07001167
1168static const struct soc_enum cf_rxmix3_enum =
Joonwoo Park2000a982013-03-01 14:50:31 -08001169 SOC_ENUM_SINGLE(TAIKO_A_CDC_RX3_B4_CTL, 0, 3, cf_text);
Kiran Kandic3b24402012-06-11 00:05:59 -07001170
1171static const struct soc_enum cf_rxmix4_enum =
Joonwoo Park2000a982013-03-01 14:50:31 -08001172 SOC_ENUM_SINGLE(TAIKO_A_CDC_RX4_B4_CTL, 0, 3, cf_text);
Kiran Kandic3b24402012-06-11 00:05:59 -07001173
1174static const struct soc_enum cf_rxmix5_enum =
Joonwoo Park2000a982013-03-01 14:50:31 -08001175 SOC_ENUM_SINGLE(TAIKO_A_CDC_RX5_B4_CTL, 0, 3, cf_text)
Kiran Kandic3b24402012-06-11 00:05:59 -07001176;
1177static const struct soc_enum cf_rxmix6_enum =
Joonwoo Park2000a982013-03-01 14:50:31 -08001178 SOC_ENUM_SINGLE(TAIKO_A_CDC_RX6_B4_CTL, 0, 3, cf_text);
Kiran Kandic3b24402012-06-11 00:05:59 -07001179
1180static const struct soc_enum cf_rxmix7_enum =
Joonwoo Park2000a982013-03-01 14:50:31 -08001181 SOC_ENUM_SINGLE(TAIKO_A_CDC_RX7_B4_CTL, 0, 3, cf_text);
Kiran Kandic3b24402012-06-11 00:05:59 -07001182
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08001183static const char * const class_h_dsm_text[] = {
1184 "ZERO", "DSM_HPHL_RX1", "DSM_SPKR_RX7"
1185};
1186
1187static const struct soc_enum class_h_dsm_enum =
1188 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_CLSH_CTL, 4, 3, class_h_dsm_text);
1189
1190static const struct snd_kcontrol_new class_h_dsm_mux =
1191 SOC_DAPM_ENUM("CLASS_H_DSM MUX Mux", class_h_dsm_enum);
1192
1193
Kiran Kandic3b24402012-06-11 00:05:59 -07001194static const struct snd_kcontrol_new taiko_snd_controls[] = {
1195
Kiran Kandic3b24402012-06-11 00:05:59 -07001196 SOC_SINGLE_S8_TLV("RX1 Digital Volume", TAIKO_A_CDC_RX1_VOL_CTL_B2_CTL,
1197 -84, 40, digital_gain),
1198 SOC_SINGLE_S8_TLV("RX2 Digital Volume", TAIKO_A_CDC_RX2_VOL_CTL_B2_CTL,
1199 -84, 40, digital_gain),
1200 SOC_SINGLE_S8_TLV("RX3 Digital Volume", TAIKO_A_CDC_RX3_VOL_CTL_B2_CTL,
1201 -84, 40, digital_gain),
1202 SOC_SINGLE_S8_TLV("RX4 Digital Volume", TAIKO_A_CDC_RX4_VOL_CTL_B2_CTL,
1203 -84, 40, digital_gain),
1204 SOC_SINGLE_S8_TLV("RX5 Digital Volume", TAIKO_A_CDC_RX5_VOL_CTL_B2_CTL,
1205 -84, 40, digital_gain),
1206 SOC_SINGLE_S8_TLV("RX6 Digital Volume", TAIKO_A_CDC_RX6_VOL_CTL_B2_CTL,
1207 -84, 40, digital_gain),
1208 SOC_SINGLE_S8_TLV("RX7 Digital Volume", TAIKO_A_CDC_RX7_VOL_CTL_B2_CTL,
1209 -84, 40, digital_gain),
1210
1211 SOC_SINGLE_S8_TLV("DEC1 Volume", TAIKO_A_CDC_TX1_VOL_CTL_GAIN, -84, 40,
1212 digital_gain),
1213 SOC_SINGLE_S8_TLV("DEC2 Volume", TAIKO_A_CDC_TX2_VOL_CTL_GAIN, -84, 40,
1214 digital_gain),
1215 SOC_SINGLE_S8_TLV("DEC3 Volume", TAIKO_A_CDC_TX3_VOL_CTL_GAIN, -84, 40,
1216 digital_gain),
1217 SOC_SINGLE_S8_TLV("DEC4 Volume", TAIKO_A_CDC_TX4_VOL_CTL_GAIN, -84, 40,
1218 digital_gain),
1219 SOC_SINGLE_S8_TLV("DEC5 Volume", TAIKO_A_CDC_TX5_VOL_CTL_GAIN, -84, 40,
1220 digital_gain),
1221 SOC_SINGLE_S8_TLV("DEC6 Volume", TAIKO_A_CDC_TX6_VOL_CTL_GAIN, -84, 40,
1222 digital_gain),
1223 SOC_SINGLE_S8_TLV("DEC7 Volume", TAIKO_A_CDC_TX7_VOL_CTL_GAIN, -84, 40,
1224 digital_gain),
1225 SOC_SINGLE_S8_TLV("DEC8 Volume", TAIKO_A_CDC_TX8_VOL_CTL_GAIN, -84, 40,
1226 digital_gain),
1227 SOC_SINGLE_S8_TLV("DEC9 Volume", TAIKO_A_CDC_TX9_VOL_CTL_GAIN, -84, 40,
1228 digital_gain),
1229 SOC_SINGLE_S8_TLV("DEC10 Volume", TAIKO_A_CDC_TX10_VOL_CTL_GAIN, -84,
1230 40, digital_gain),
Kiran Kandiec0db5c2013-03-08 16:03:58 -08001231
Kiran Kandic3b24402012-06-11 00:05:59 -07001232 SOC_SINGLE_S8_TLV("IIR1 INP1 Volume", TAIKO_A_CDC_IIR1_GAIN_B1_CTL, -84,
1233 40, digital_gain),
1234 SOC_SINGLE_S8_TLV("IIR1 INP2 Volume", TAIKO_A_CDC_IIR1_GAIN_B2_CTL, -84,
1235 40, digital_gain),
1236 SOC_SINGLE_S8_TLV("IIR1 INP3 Volume", TAIKO_A_CDC_IIR1_GAIN_B3_CTL, -84,
1237 40, digital_gain),
1238 SOC_SINGLE_S8_TLV("IIR1 INP4 Volume", TAIKO_A_CDC_IIR1_GAIN_B4_CTL, -84,
1239 40, digital_gain),
Fred Oh456fcb52013-02-28 19:08:15 -08001240 SOC_SINGLE_S8_TLV("IIR2 INP1 Volume", TAIKO_A_CDC_IIR2_GAIN_B1_CTL, -84,
1241 40, digital_gain),
1242 SOC_SINGLE_S8_TLV("IIR2 INP2 Volume", TAIKO_A_CDC_IIR2_GAIN_B2_CTL, -84,
1243 40, digital_gain),
1244 SOC_SINGLE_S8_TLV("IIR2 INP3 Volume", TAIKO_A_CDC_IIR2_GAIN_B3_CTL, -84,
1245 40, digital_gain),
1246 SOC_SINGLE_S8_TLV("IIR2 INP4 Volume", TAIKO_A_CDC_IIR2_GAIN_B4_CTL, -84,
1247 40, digital_gain),
Kiran Kandic3b24402012-06-11 00:05:59 -07001248
Damir Didjusto2cb06bd2013-01-30 23:14:55 -08001249 SOC_SINGLE_EXT("ANC Slot", SND_SOC_NOPM, 0, 100, 0, taiko_get_anc_slot,
Kiran Kandic3b24402012-06-11 00:05:59 -07001250 taiko_put_anc_slot),
Damir Didjusto2cb06bd2013-01-30 23:14:55 -08001251 SOC_ENUM_EXT("ANC Function", taiko_anc_func_enum, taiko_get_anc_func,
1252 taiko_put_anc_func),
Kiran Kandiec0db5c2013-03-08 16:03:58 -08001253
Kiran Kandic3b24402012-06-11 00:05:59 -07001254 SOC_ENUM("TX1 HPF cut off", cf_dec1_enum),
1255 SOC_ENUM("TX2 HPF cut off", cf_dec2_enum),
1256 SOC_ENUM("TX3 HPF cut off", cf_dec3_enum),
1257 SOC_ENUM("TX4 HPF cut off", cf_dec4_enum),
1258 SOC_ENUM("TX5 HPF cut off", cf_dec5_enum),
1259 SOC_ENUM("TX6 HPF cut off", cf_dec6_enum),
1260 SOC_ENUM("TX7 HPF cut off", cf_dec7_enum),
1261 SOC_ENUM("TX8 HPF cut off", cf_dec8_enum),
1262 SOC_ENUM("TX9 HPF cut off", cf_dec9_enum),
1263 SOC_ENUM("TX10 HPF cut off", cf_dec10_enum),
1264
1265 SOC_SINGLE("TX1 HPF Switch", TAIKO_A_CDC_TX1_MUX_CTL, 3, 1, 0),
1266 SOC_SINGLE("TX2 HPF Switch", TAIKO_A_CDC_TX2_MUX_CTL, 3, 1, 0),
1267 SOC_SINGLE("TX3 HPF Switch", TAIKO_A_CDC_TX3_MUX_CTL, 3, 1, 0),
1268 SOC_SINGLE("TX4 HPF Switch", TAIKO_A_CDC_TX4_MUX_CTL, 3, 1, 0),
1269 SOC_SINGLE("TX5 HPF Switch", TAIKO_A_CDC_TX5_MUX_CTL, 3, 1, 0),
1270 SOC_SINGLE("TX6 HPF Switch", TAIKO_A_CDC_TX6_MUX_CTL, 3, 1, 0),
1271 SOC_SINGLE("TX7 HPF Switch", TAIKO_A_CDC_TX7_MUX_CTL, 3, 1, 0),
1272 SOC_SINGLE("TX8 HPF Switch", TAIKO_A_CDC_TX8_MUX_CTL, 3, 1, 0),
1273 SOC_SINGLE("TX9 HPF Switch", TAIKO_A_CDC_TX9_MUX_CTL, 3, 1, 0),
1274 SOC_SINGLE("TX10 HPF Switch", TAIKO_A_CDC_TX10_MUX_CTL, 3, 1, 0),
1275
1276 SOC_SINGLE("RX1 HPF Switch", TAIKO_A_CDC_RX1_B5_CTL, 2, 1, 0),
1277 SOC_SINGLE("RX2 HPF Switch", TAIKO_A_CDC_RX2_B5_CTL, 2, 1, 0),
1278 SOC_SINGLE("RX3 HPF Switch", TAIKO_A_CDC_RX3_B5_CTL, 2, 1, 0),
1279 SOC_SINGLE("RX4 HPF Switch", TAIKO_A_CDC_RX4_B5_CTL, 2, 1, 0),
1280 SOC_SINGLE("RX5 HPF Switch", TAIKO_A_CDC_RX5_B5_CTL, 2, 1, 0),
1281 SOC_SINGLE("RX6 HPF Switch", TAIKO_A_CDC_RX6_B5_CTL, 2, 1, 0),
1282 SOC_SINGLE("RX7 HPF Switch", TAIKO_A_CDC_RX7_B5_CTL, 2, 1, 0),
1283
1284 SOC_ENUM("RX1 HPF cut off", cf_rxmix1_enum),
1285 SOC_ENUM("RX2 HPF cut off", cf_rxmix2_enum),
1286 SOC_ENUM("RX3 HPF cut off", cf_rxmix3_enum),
1287 SOC_ENUM("RX4 HPF cut off", cf_rxmix4_enum),
1288 SOC_ENUM("RX5 HPF cut off", cf_rxmix5_enum),
1289 SOC_ENUM("RX6 HPF cut off", cf_rxmix6_enum),
1290 SOC_ENUM("RX7 HPF cut off", cf_rxmix7_enum),
1291
1292 SOC_SINGLE_EXT("IIR1 Enable Band1", IIR1, BAND1, 1, 0,
1293 taiko_get_iir_enable_audio_mixer, taiko_put_iir_enable_audio_mixer),
1294 SOC_SINGLE_EXT("IIR1 Enable Band2", IIR1, BAND2, 1, 0,
1295 taiko_get_iir_enable_audio_mixer, taiko_put_iir_enable_audio_mixer),
1296 SOC_SINGLE_EXT("IIR1 Enable Band3", IIR1, BAND3, 1, 0,
1297 taiko_get_iir_enable_audio_mixer, taiko_put_iir_enable_audio_mixer),
1298 SOC_SINGLE_EXT("IIR1 Enable Band4", IIR1, BAND4, 1, 0,
1299 taiko_get_iir_enable_audio_mixer, taiko_put_iir_enable_audio_mixer),
1300 SOC_SINGLE_EXT("IIR1 Enable Band5", IIR1, BAND5, 1, 0,
1301 taiko_get_iir_enable_audio_mixer, taiko_put_iir_enable_audio_mixer),
1302 SOC_SINGLE_EXT("IIR2 Enable Band1", IIR2, BAND1, 1, 0,
1303 taiko_get_iir_enable_audio_mixer, taiko_put_iir_enable_audio_mixer),
1304 SOC_SINGLE_EXT("IIR2 Enable Band2", IIR2, BAND2, 1, 0,
1305 taiko_get_iir_enable_audio_mixer, taiko_put_iir_enable_audio_mixer),
1306 SOC_SINGLE_EXT("IIR2 Enable Band3", IIR2, BAND3, 1, 0,
1307 taiko_get_iir_enable_audio_mixer, taiko_put_iir_enable_audio_mixer),
1308 SOC_SINGLE_EXT("IIR2 Enable Band4", IIR2, BAND4, 1, 0,
1309 taiko_get_iir_enable_audio_mixer, taiko_put_iir_enable_audio_mixer),
1310 SOC_SINGLE_EXT("IIR2 Enable Band5", IIR2, BAND5, 1, 0,
1311 taiko_get_iir_enable_audio_mixer, taiko_put_iir_enable_audio_mixer),
1312
1313 SOC_SINGLE_MULTI_EXT("IIR1 Band1", IIR1, BAND1, 255, 0, 5,
1314 taiko_get_iir_band_audio_mixer, taiko_put_iir_band_audio_mixer),
1315 SOC_SINGLE_MULTI_EXT("IIR1 Band2", IIR1, BAND2, 255, 0, 5,
1316 taiko_get_iir_band_audio_mixer, taiko_put_iir_band_audio_mixer),
1317 SOC_SINGLE_MULTI_EXT("IIR1 Band3", IIR1, BAND3, 255, 0, 5,
1318 taiko_get_iir_band_audio_mixer, taiko_put_iir_band_audio_mixer),
1319 SOC_SINGLE_MULTI_EXT("IIR1 Band4", IIR1, BAND4, 255, 0, 5,
1320 taiko_get_iir_band_audio_mixer, taiko_put_iir_band_audio_mixer),
1321 SOC_SINGLE_MULTI_EXT("IIR1 Band5", IIR1, BAND5, 255, 0, 5,
1322 taiko_get_iir_band_audio_mixer, taiko_put_iir_band_audio_mixer),
1323 SOC_SINGLE_MULTI_EXT("IIR2 Band1", IIR2, BAND1, 255, 0, 5,
1324 taiko_get_iir_band_audio_mixer, taiko_put_iir_band_audio_mixer),
1325 SOC_SINGLE_MULTI_EXT("IIR2 Band2", IIR2, BAND2, 255, 0, 5,
1326 taiko_get_iir_band_audio_mixer, taiko_put_iir_band_audio_mixer),
1327 SOC_SINGLE_MULTI_EXT("IIR2 Band3", IIR2, BAND3, 255, 0, 5,
1328 taiko_get_iir_band_audio_mixer, taiko_put_iir_band_audio_mixer),
1329 SOC_SINGLE_MULTI_EXT("IIR2 Band4", IIR2, BAND4, 255, 0, 5,
1330 taiko_get_iir_band_audio_mixer, taiko_put_iir_band_audio_mixer),
1331 SOC_SINGLE_MULTI_EXT("IIR2 Band5", IIR2, BAND5, 255, 0, 5,
1332 taiko_get_iir_band_audio_mixer, taiko_put_iir_band_audio_mixer),
1333
Joonwoo Parkc7731432012-10-17 12:41:44 -07001334 SOC_SINGLE_EXT("COMP0 Switch", SND_SOC_NOPM, COMPANDER_0, 1, 0,
1335 taiko_get_compander, taiko_set_compander),
1336 SOC_SINGLE_EXT("COMP1 Switch", SND_SOC_NOPM, COMPANDER_1, 1, 0,
1337 taiko_get_compander, taiko_set_compander),
1338 SOC_SINGLE_EXT("COMP2 Switch", SND_SOC_NOPM, COMPANDER_2, 1, 0,
1339 taiko_get_compander, taiko_set_compander),
Kiran Kandic3b24402012-06-11 00:05:59 -07001340
1341};
1342
Kiran Kandiec0db5c2013-03-08 16:03:58 -08001343static int taiko_pa_gain_get(struct snd_kcontrol *kcontrol,
1344 struct snd_ctl_elem_value *ucontrol)
1345{
1346 u8 ear_pa_gain;
1347 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
1348
1349 ear_pa_gain = snd_soc_read(codec, TAIKO_A_RX_EAR_GAIN);
1350
1351 ear_pa_gain = ear_pa_gain >> 5;
1352
1353 ucontrol->value.integer.value[0] = ear_pa_gain;
1354
1355 pr_debug("%s: ear_pa_gain = 0x%x\n", __func__, ear_pa_gain);
1356
1357 return 0;
1358}
1359
1360static int taiko_pa_gain_put(struct snd_kcontrol *kcontrol,
1361 struct snd_ctl_elem_value *ucontrol)
1362{
1363 u8 ear_pa_gain;
1364 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
1365
1366 pr_debug("%s: ucontrol->value.integer.value[0] = %ld\n", __func__,
1367 ucontrol->value.integer.value[0]);
1368
1369 ear_pa_gain = ucontrol->value.integer.value[0] << 5;
1370
1371 snd_soc_update_bits(codec, TAIKO_A_RX_EAR_GAIN, 0xE0, ear_pa_gain);
1372 return 0;
1373}
1374
1375static const char * const taiko_1_x_ear_pa_gain_text[] = {
1376 "POS_6_DB", "UNDEFINED_1", "UNDEFINED_2", "UNDEFINED_3", "POS_2_DB",
1377 "NEG_2P5_DB", "UNDEFINED_4", "NEG_12_DB"
1378};
1379
1380static const struct soc_enum taiko_1_x_ear_pa_gain_enum =
1381 SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(taiko_1_x_ear_pa_gain_text),
1382 taiko_1_x_ear_pa_gain_text);
1383
1384static const struct snd_kcontrol_new taiko_1_x_analog_gain_controls[] = {
1385
1386 SOC_ENUM_EXT("EAR PA Gain", taiko_1_x_ear_pa_gain_enum,
1387 taiko_pa_gain_get, taiko_pa_gain_put),
1388
1389 SOC_SINGLE_TLV("HPHL Volume", TAIKO_A_RX_HPH_L_GAIN, 0, 20, 1,
1390 line_gain),
1391 SOC_SINGLE_TLV("HPHR Volume", TAIKO_A_RX_HPH_R_GAIN, 0, 20, 1,
1392 line_gain),
1393
1394 SOC_SINGLE_TLV("LINEOUT1 Volume", TAIKO_A_RX_LINE_1_GAIN, 0, 20, 1,
1395 line_gain),
1396 SOC_SINGLE_TLV("LINEOUT2 Volume", TAIKO_A_RX_LINE_2_GAIN, 0, 20, 1,
1397 line_gain),
1398 SOC_SINGLE_TLV("LINEOUT3 Volume", TAIKO_A_RX_LINE_3_GAIN, 0, 20, 1,
1399 line_gain),
1400 SOC_SINGLE_TLV("LINEOUT4 Volume", TAIKO_A_RX_LINE_4_GAIN, 0, 20, 1,
1401 line_gain),
1402
1403 SOC_SINGLE_TLV("SPK DRV Volume", TAIKO_A_SPKR_DRV_GAIN, 3, 7, 1,
1404 line_gain),
1405
1406 SOC_SINGLE_TLV("ADC1 Volume", TAIKO_A_TX_1_2_EN, 5, 3, 0, analog_gain),
1407 SOC_SINGLE_TLV("ADC2 Volume", TAIKO_A_TX_1_2_EN, 1, 3, 0, analog_gain),
1408 SOC_SINGLE_TLV("ADC3 Volume", TAIKO_A_TX_3_4_EN, 5, 3, 0, analog_gain),
1409 SOC_SINGLE_TLV("ADC4 Volume", TAIKO_A_TX_3_4_EN, 1, 3, 0, analog_gain),
1410 SOC_SINGLE_TLV("ADC5 Volume", TAIKO_A_TX_5_6_EN, 5, 3, 0, analog_gain),
1411 SOC_SINGLE_TLV("ADC6 Volume", TAIKO_A_TX_5_6_EN, 1, 3, 0, analog_gain),
1412};
1413
1414static const char * const taiko_2_x_ear_pa_gain_text[] = {
1415 "POS_6_DB", "POS_4P5_DB", "POS_3_DB", "POS_1P5_DB",
1416 "POS_0_DB", "NEG_2P5_DB", "UNDEFINED", "NEG_12_DB"
1417};
1418
1419static const struct soc_enum taiko_2_x_ear_pa_gain_enum =
1420 SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(taiko_2_x_ear_pa_gain_text),
1421 taiko_2_x_ear_pa_gain_text);
1422
1423static const struct snd_kcontrol_new taiko_2_x_analog_gain_controls[] = {
1424
1425 SOC_ENUM_EXT("EAR PA Gain", taiko_2_x_ear_pa_gain_enum,
1426 taiko_pa_gain_get, taiko_pa_gain_put),
1427
1428 SOC_SINGLE_TLV("HPHL Volume", TAIKO_A_RX_HPH_L_GAIN, 0, 20, 1,
1429 line_gain),
1430 SOC_SINGLE_TLV("HPHR Volume", TAIKO_A_RX_HPH_R_GAIN, 0, 20, 1,
1431 line_gain),
1432
1433 SOC_SINGLE_TLV("LINEOUT1 Volume", TAIKO_A_RX_LINE_1_GAIN, 0, 20, 1,
1434 line_gain),
1435 SOC_SINGLE_TLV("LINEOUT2 Volume", TAIKO_A_RX_LINE_2_GAIN, 0, 20, 1,
1436 line_gain),
1437 SOC_SINGLE_TLV("LINEOUT3 Volume", TAIKO_A_RX_LINE_3_GAIN, 0, 20, 1,
1438 line_gain),
1439 SOC_SINGLE_TLV("LINEOUT4 Volume", TAIKO_A_RX_LINE_4_GAIN, 0, 20, 1,
1440 line_gain),
1441
1442 SOC_SINGLE_TLV("SPK DRV Volume", TAIKO_A_SPKR_DRV_GAIN, 3, 8, 1,
1443 line_gain),
1444
1445 SOC_SINGLE_TLV("ADC1 Volume", TAIKO_A_CDC_TX_1_GAIN, 2, 19, 0,
1446 analog_gain),
1447 SOC_SINGLE_TLV("ADC2 Volume", TAIKO_A_CDC_TX_2_GAIN, 2, 19, 0,
1448 analog_gain),
1449 SOC_SINGLE_TLV("ADC3 Volume", TAIKO_A_CDC_TX_3_GAIN, 2, 19, 0,
1450 analog_gain),
1451 SOC_SINGLE_TLV("ADC4 Volume", TAIKO_A_CDC_TX_4_GAIN, 2, 19, 0,
1452 analog_gain),
1453 SOC_SINGLE_TLV("ADC5 Volume", TAIKO_A_CDC_TX_5_GAIN, 2, 19, 0,
1454 analog_gain),
1455 SOC_SINGLE_TLV("ADC6 Volume", TAIKO_A_CDC_TX_6_GAIN, 2, 19, 0,
1456 analog_gain),
1457};
1458
Joonwoo Parkb755e9e2013-05-28 13:14:05 -07001459static int taiko_hph_impedance_get(struct snd_kcontrol *kcontrol,
1460 struct snd_ctl_elem_value *ucontrol)
1461{
1462 uint32_t zl, zr;
1463 bool hphr;
1464 struct soc_multi_mixer_control *mc;
1465 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
1466 struct taiko_priv *priv = snd_soc_codec_get_drvdata(codec);
1467
1468 mc = (struct soc_multi_mixer_control *)(kcontrol->private_value);
1469
1470 hphr = mc->shift;
1471 wcd9xxx_mbhc_get_impedance(&priv->mbhc, &zl, &zr);
1472 pr_debug("%s: zl %u, zr %u\n", __func__, zl, zr);
1473 ucontrol->value.integer.value[0] = hphr ? zr : zl;
1474
1475 return 0;
1476}
1477
1478static const struct snd_kcontrol_new impedance_detect_controls[] = {
1479 SOC_SINGLE_EXT("HPHL Impedance", 0, 0, UINT_MAX, 0,
1480 taiko_hph_impedance_get, NULL),
1481 SOC_SINGLE_EXT("HPHR Impedance", 0, 1, UINT_MAX, 0,
1482 taiko_hph_impedance_get, NULL),
1483};
1484
Kiran Kandic3b24402012-06-11 00:05:59 -07001485static const char * const rx_mix1_text[] = {
1486 "ZERO", "SRC1", "SRC2", "IIR1", "IIR2", "RX1", "RX2", "RX3", "RX4",
1487 "RX5", "RX6", "RX7"
1488};
1489
1490static const char * const rx_mix2_text[] = {
1491 "ZERO", "SRC1", "SRC2", "IIR1", "IIR2"
1492};
1493
Tanya Finkeldaaa6d12012-10-25 11:22:48 +02001494static const char * const rx_rdac5_text[] = {
1495 "DEM4", "DEM3_INV"
Kiran Kandic3b24402012-06-11 00:05:59 -07001496};
1497
Tanya Finkeldaaa6d12012-10-25 11:22:48 +02001498static const char * const rx_rdac7_text[] = {
1499 "DEM6", "DEM5_INV"
1500};
1501
1502
Kiran Kandic3b24402012-06-11 00:05:59 -07001503static const char * const sb_tx1_mux_text[] = {
1504 "ZERO", "RMIX1", "RMIX2", "RMIX3", "RMIX4", "RMIX5", "RMIX6", "RMIX7",
1505 "DEC1"
1506};
1507
1508static const char * const sb_tx2_mux_text[] = {
1509 "ZERO", "RMIX1", "RMIX2", "RMIX3", "RMIX4", "RMIX5", "RMIX6", "RMIX7",
1510 "DEC2"
1511};
1512
1513static const char * const sb_tx3_mux_text[] = {
1514 "ZERO", "RMIX1", "RMIX2", "RMIX3", "RMIX4", "RMIX5", "RMIX6", "RMIX7",
1515 "DEC3"
1516};
1517
1518static const char * const sb_tx4_mux_text[] = {
1519 "ZERO", "RMIX1", "RMIX2", "RMIX3", "RMIX4", "RMIX5", "RMIX6", "RMIX7",
1520 "DEC4"
1521};
1522
1523static const char * const sb_tx5_mux_text[] = {
1524 "ZERO", "RMIX1", "RMIX2", "RMIX3", "RMIX4", "RMIX5", "RMIX6", "RMIX7",
1525 "DEC5"
1526};
1527
1528static const char * const sb_tx6_mux_text[] = {
1529 "ZERO", "RMIX1", "RMIX2", "RMIX3", "RMIX4", "RMIX5", "RMIX6", "RMIX7",
1530 "DEC6"
1531};
1532
1533static const char * const sb_tx7_to_tx10_mux_text[] = {
1534 "ZERO", "RMIX1", "RMIX2", "RMIX3", "RMIX4", "RMIX5", "RMIX6", "RMIX7",
1535 "DEC1", "DEC2", "DEC3", "DEC4", "DEC5", "DEC6", "DEC7", "DEC8",
1536 "DEC9", "DEC10"
1537};
1538
1539static const char * const dec1_mux_text[] = {
1540 "ZERO", "DMIC1", "ADC6",
1541};
1542
1543static const char * const dec2_mux_text[] = {
1544 "ZERO", "DMIC2", "ADC5",
1545};
1546
1547static const char * const dec3_mux_text[] = {
1548 "ZERO", "DMIC3", "ADC4",
1549};
1550
1551static const char * const dec4_mux_text[] = {
1552 "ZERO", "DMIC4", "ADC3",
1553};
1554
1555static const char * const dec5_mux_text[] = {
1556 "ZERO", "DMIC5", "ADC2",
1557};
1558
1559static const char * const dec6_mux_text[] = {
1560 "ZERO", "DMIC6", "ADC1",
1561};
1562
1563static const char * const dec7_mux_text[] = {
1564 "ZERO", "DMIC1", "DMIC6", "ADC1", "ADC6", "ANC1_FB", "ANC2_FB",
1565};
1566
1567static const char * const dec8_mux_text[] = {
1568 "ZERO", "DMIC2", "DMIC5", "ADC2", "ADC5",
1569};
1570
1571static const char * const dec9_mux_text[] = {
1572 "ZERO", "DMIC4", "DMIC5", "ADC2", "ADC3", "ADCMB", "ANC1_FB", "ANC2_FB",
1573};
1574
1575static const char * const dec10_mux_text[] = {
1576 "ZERO", "DMIC3", "DMIC6", "ADC1", "ADC4", "ADCMB", "ANC1_FB", "ANC2_FB",
1577};
1578
1579static const char * const anc_mux_text[] = {
1580 "ZERO", "ADC1", "ADC2", "ADC3", "ADC4", "ADC5", "ADC6", "ADC_MB",
1581 "RSVD_1", "DMIC1", "DMIC2", "DMIC3", "DMIC4", "DMIC5", "DMIC6"
1582};
1583
1584static const char * const anc1_fb_mux_text[] = {
1585 "ZERO", "EAR_HPH_L", "EAR_LINE_1",
1586};
1587
Fred Oh456fcb52013-02-28 19:08:15 -08001588static const char * const iir_inp1_text[] = {
Kiran Kandic3b24402012-06-11 00:05:59 -07001589 "ZERO", "DEC1", "DEC2", "DEC3", "DEC4", "DEC5", "DEC6", "DEC7", "DEC8",
1590 "DEC9", "DEC10", "RX1", "RX2", "RX3", "RX4", "RX5", "RX6", "RX7"
1591};
1592
1593static const struct soc_enum rx_mix1_inp1_chain_enum =
1594 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_RX1_B1_CTL, 0, 12, rx_mix1_text);
1595
1596static const struct soc_enum rx_mix1_inp2_chain_enum =
1597 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_RX1_B1_CTL, 4, 12, rx_mix1_text);
1598
1599static const struct soc_enum rx_mix1_inp3_chain_enum =
1600 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_RX1_B2_CTL, 0, 12, rx_mix1_text);
1601
1602static const struct soc_enum rx2_mix1_inp1_chain_enum =
1603 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_RX2_B1_CTL, 0, 12, rx_mix1_text);
1604
1605static const struct soc_enum rx2_mix1_inp2_chain_enum =
1606 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_RX2_B1_CTL, 4, 12, rx_mix1_text);
1607
1608static const struct soc_enum rx3_mix1_inp1_chain_enum =
1609 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_RX3_B1_CTL, 0, 12, rx_mix1_text);
1610
1611static const struct soc_enum rx3_mix1_inp2_chain_enum =
1612 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_RX3_B1_CTL, 4, 12, rx_mix1_text);
1613
1614static const struct soc_enum rx4_mix1_inp1_chain_enum =
1615 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_RX4_B1_CTL, 0, 12, rx_mix1_text);
1616
1617static const struct soc_enum rx4_mix1_inp2_chain_enum =
1618 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_RX4_B1_CTL, 4, 12, rx_mix1_text);
1619
1620static const struct soc_enum rx5_mix1_inp1_chain_enum =
1621 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_RX5_B1_CTL, 0, 12, rx_mix1_text);
1622
1623static const struct soc_enum rx5_mix1_inp2_chain_enum =
1624 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_RX5_B1_CTL, 4, 12, rx_mix1_text);
1625
1626static const struct soc_enum rx6_mix1_inp1_chain_enum =
1627 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_RX6_B1_CTL, 0, 12, rx_mix1_text);
1628
1629static const struct soc_enum rx6_mix1_inp2_chain_enum =
1630 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_RX6_B1_CTL, 4, 12, rx_mix1_text);
1631
1632static const struct soc_enum rx7_mix1_inp1_chain_enum =
1633 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_RX7_B1_CTL, 0, 12, rx_mix1_text);
1634
1635static const struct soc_enum rx7_mix1_inp2_chain_enum =
1636 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_RX7_B1_CTL, 4, 12, rx_mix1_text);
1637
1638static const struct soc_enum rx1_mix2_inp1_chain_enum =
1639 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_RX1_B3_CTL, 0, 5, rx_mix2_text);
1640
1641static const struct soc_enum rx1_mix2_inp2_chain_enum =
1642 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_RX1_B3_CTL, 3, 5, rx_mix2_text);
1643
1644static const struct soc_enum rx2_mix2_inp1_chain_enum =
1645 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_RX2_B3_CTL, 0, 5, rx_mix2_text);
1646
1647static const struct soc_enum rx2_mix2_inp2_chain_enum =
1648 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_RX2_B3_CTL, 3, 5, rx_mix2_text);
1649
1650static const struct soc_enum rx7_mix2_inp1_chain_enum =
1651 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_RX7_B3_CTL, 0, 5, rx_mix2_text);
1652
1653static const struct soc_enum rx7_mix2_inp2_chain_enum =
1654 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_RX7_B3_CTL, 3, 5, rx_mix2_text);
1655
Tanya Finkeldaaa6d12012-10-25 11:22:48 +02001656static const struct soc_enum rx_rdac5_enum =
1657 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_MISC, 2, 2, rx_rdac5_text);
Kiran Kandic3b24402012-06-11 00:05:59 -07001658
Tanya Finkeldaaa6d12012-10-25 11:22:48 +02001659static const struct soc_enum rx_rdac7_enum =
1660 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_MISC, 1, 2, rx_rdac7_text);
Kiran Kandic3b24402012-06-11 00:05:59 -07001661
1662static const struct soc_enum sb_tx1_mux_enum =
1663 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_TX_SB_B1_CTL, 0, 9, sb_tx1_mux_text);
1664
1665static const struct soc_enum sb_tx2_mux_enum =
1666 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_TX_SB_B2_CTL, 0, 9, sb_tx2_mux_text);
1667
1668static const struct soc_enum sb_tx3_mux_enum =
1669 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_TX_SB_B3_CTL, 0, 9, sb_tx3_mux_text);
1670
1671static const struct soc_enum sb_tx4_mux_enum =
1672 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_TX_SB_B4_CTL, 0, 9, sb_tx4_mux_text);
1673
1674static const struct soc_enum sb_tx5_mux_enum =
1675 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_TX_SB_B5_CTL, 0, 9, sb_tx5_mux_text);
1676
1677static const struct soc_enum sb_tx6_mux_enum =
1678 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_TX_SB_B6_CTL, 0, 9, sb_tx6_mux_text);
1679
1680static const struct soc_enum sb_tx7_mux_enum =
1681 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_TX_SB_B7_CTL, 0, 18,
1682 sb_tx7_to_tx10_mux_text);
1683
1684static const struct soc_enum sb_tx8_mux_enum =
1685 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_TX_SB_B8_CTL, 0, 18,
1686 sb_tx7_to_tx10_mux_text);
1687
1688static const struct soc_enum sb_tx9_mux_enum =
1689 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_TX_SB_B9_CTL, 0, 18,
1690 sb_tx7_to_tx10_mux_text);
1691
1692static const struct soc_enum sb_tx10_mux_enum =
1693 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_TX_SB_B10_CTL, 0, 18,
1694 sb_tx7_to_tx10_mux_text);
1695
1696static const struct soc_enum dec1_mux_enum =
1697 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_TX_B1_CTL, 0, 3, dec1_mux_text);
1698
1699static const struct soc_enum dec2_mux_enum =
1700 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_TX_B1_CTL, 2, 3, dec2_mux_text);
1701
1702static const struct soc_enum dec3_mux_enum =
1703 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_TX_B1_CTL, 4, 3, dec3_mux_text);
1704
1705static const struct soc_enum dec4_mux_enum =
1706 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_TX_B1_CTL, 6, 3, dec4_mux_text);
1707
1708static const struct soc_enum dec5_mux_enum =
1709 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_TX_B2_CTL, 0, 3, dec5_mux_text);
1710
1711static const struct soc_enum dec6_mux_enum =
1712 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_TX_B2_CTL, 2, 3, dec6_mux_text);
1713
1714static const struct soc_enum dec7_mux_enum =
1715 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_TX_B2_CTL, 4, 7, dec7_mux_text);
1716
1717static const struct soc_enum dec8_mux_enum =
1718 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_TX_B3_CTL, 0, 7, dec8_mux_text);
1719
1720static const struct soc_enum dec9_mux_enum =
1721 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_TX_B3_CTL, 3, 8, dec9_mux_text);
1722
1723static const struct soc_enum dec10_mux_enum =
1724 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_TX_B4_CTL, 0, 8, dec10_mux_text);
1725
1726static const struct soc_enum anc1_mux_enum =
1727 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_ANC_B1_CTL, 0, 16, anc_mux_text);
1728
1729static const struct soc_enum anc2_mux_enum =
1730 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_ANC_B1_CTL, 4, 16, anc_mux_text);
1731
1732static const struct soc_enum anc1_fb_mux_enum =
1733 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_ANC_B2_CTL, 0, 3, anc1_fb_mux_text);
1734
1735static const struct soc_enum iir1_inp1_mux_enum =
Fred Oh456fcb52013-02-28 19:08:15 -08001736 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_EQ1_B1_CTL, 0, 18, iir_inp1_text);
1737
1738static const struct soc_enum iir2_inp1_mux_enum =
1739 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_EQ2_B1_CTL, 0, 18, iir_inp1_text);
Kiran Kandic3b24402012-06-11 00:05:59 -07001740
1741static const struct snd_kcontrol_new rx_mix1_inp1_mux =
1742 SOC_DAPM_ENUM("RX1 MIX1 INP1 Mux", rx_mix1_inp1_chain_enum);
1743
1744static const struct snd_kcontrol_new rx_mix1_inp2_mux =
1745 SOC_DAPM_ENUM("RX1 MIX1 INP2 Mux", rx_mix1_inp2_chain_enum);
1746
1747static const struct snd_kcontrol_new rx_mix1_inp3_mux =
1748 SOC_DAPM_ENUM("RX1 MIX1 INP3 Mux", rx_mix1_inp3_chain_enum);
1749
1750static const struct snd_kcontrol_new rx2_mix1_inp1_mux =
1751 SOC_DAPM_ENUM("RX2 MIX1 INP1 Mux", rx2_mix1_inp1_chain_enum);
1752
1753static const struct snd_kcontrol_new rx2_mix1_inp2_mux =
1754 SOC_DAPM_ENUM("RX2 MIX1 INP2 Mux", rx2_mix1_inp2_chain_enum);
1755
1756static const struct snd_kcontrol_new rx3_mix1_inp1_mux =
1757 SOC_DAPM_ENUM("RX3 MIX1 INP1 Mux", rx3_mix1_inp1_chain_enum);
1758
1759static const struct snd_kcontrol_new rx3_mix1_inp2_mux =
1760 SOC_DAPM_ENUM("RX3 MIX1 INP2 Mux", rx3_mix1_inp2_chain_enum);
1761
1762static const struct snd_kcontrol_new rx4_mix1_inp1_mux =
1763 SOC_DAPM_ENUM("RX4 MIX1 INP1 Mux", rx4_mix1_inp1_chain_enum);
1764
1765static const struct snd_kcontrol_new rx4_mix1_inp2_mux =
1766 SOC_DAPM_ENUM("RX4 MIX1 INP2 Mux", rx4_mix1_inp2_chain_enum);
1767
1768static const struct snd_kcontrol_new rx5_mix1_inp1_mux =
1769 SOC_DAPM_ENUM("RX5 MIX1 INP1 Mux", rx5_mix1_inp1_chain_enum);
1770
1771static const struct snd_kcontrol_new rx5_mix1_inp2_mux =
1772 SOC_DAPM_ENUM("RX5 MIX1 INP2 Mux", rx5_mix1_inp2_chain_enum);
1773
1774static const struct snd_kcontrol_new rx6_mix1_inp1_mux =
1775 SOC_DAPM_ENUM("RX6 MIX1 INP1 Mux", rx6_mix1_inp1_chain_enum);
1776
1777static const struct snd_kcontrol_new rx6_mix1_inp2_mux =
1778 SOC_DAPM_ENUM("RX6 MIX1 INP2 Mux", rx6_mix1_inp2_chain_enum);
1779
1780static const struct snd_kcontrol_new rx7_mix1_inp1_mux =
1781 SOC_DAPM_ENUM("RX7 MIX1 INP1 Mux", rx7_mix1_inp1_chain_enum);
1782
1783static const struct snd_kcontrol_new rx7_mix1_inp2_mux =
1784 SOC_DAPM_ENUM("RX7 MIX1 INP2 Mux", rx7_mix1_inp2_chain_enum);
1785
1786static const struct snd_kcontrol_new rx1_mix2_inp1_mux =
1787 SOC_DAPM_ENUM("RX1 MIX2 INP1 Mux", rx1_mix2_inp1_chain_enum);
1788
1789static const struct snd_kcontrol_new rx1_mix2_inp2_mux =
1790 SOC_DAPM_ENUM("RX1 MIX2 INP2 Mux", rx1_mix2_inp2_chain_enum);
1791
1792static const struct snd_kcontrol_new rx2_mix2_inp1_mux =
1793 SOC_DAPM_ENUM("RX2 MIX2 INP1 Mux", rx2_mix2_inp1_chain_enum);
1794
1795static const struct snd_kcontrol_new rx2_mix2_inp2_mux =
1796 SOC_DAPM_ENUM("RX2 MIX2 INP2 Mux", rx2_mix2_inp2_chain_enum);
1797
1798static const struct snd_kcontrol_new rx7_mix2_inp1_mux =
1799 SOC_DAPM_ENUM("RX7 MIX2 INP1 Mux", rx7_mix2_inp1_chain_enum);
1800
1801static const struct snd_kcontrol_new rx7_mix2_inp2_mux =
1802 SOC_DAPM_ENUM("RX7 MIX2 INP2 Mux", rx7_mix2_inp2_chain_enum);
1803
Tanya Finkeldaaa6d12012-10-25 11:22:48 +02001804static const struct snd_kcontrol_new rx_dac5_mux =
1805 SOC_DAPM_ENUM("RDAC5 MUX Mux", rx_rdac5_enum);
Kiran Kandic3b24402012-06-11 00:05:59 -07001806
Tanya Finkeldaaa6d12012-10-25 11:22:48 +02001807static const struct snd_kcontrol_new rx_dac7_mux =
1808 SOC_DAPM_ENUM("RDAC7 MUX Mux", rx_rdac7_enum);
Kiran Kandic3b24402012-06-11 00:05:59 -07001809
1810static const struct snd_kcontrol_new sb_tx1_mux =
1811 SOC_DAPM_ENUM("SLIM TX1 MUX Mux", sb_tx1_mux_enum);
1812
1813static const struct snd_kcontrol_new sb_tx2_mux =
1814 SOC_DAPM_ENUM("SLIM TX2 MUX Mux", sb_tx2_mux_enum);
1815
1816static const struct snd_kcontrol_new sb_tx3_mux =
1817 SOC_DAPM_ENUM("SLIM TX3 MUX Mux", sb_tx3_mux_enum);
1818
1819static const struct snd_kcontrol_new sb_tx4_mux =
1820 SOC_DAPM_ENUM("SLIM TX4 MUX Mux", sb_tx4_mux_enum);
1821
1822static const struct snd_kcontrol_new sb_tx5_mux =
1823 SOC_DAPM_ENUM("SLIM TX5 MUX Mux", sb_tx5_mux_enum);
1824
1825static const struct snd_kcontrol_new sb_tx6_mux =
1826 SOC_DAPM_ENUM("SLIM TX6 MUX Mux", sb_tx6_mux_enum);
1827
1828static const struct snd_kcontrol_new sb_tx7_mux =
1829 SOC_DAPM_ENUM("SLIM TX7 MUX Mux", sb_tx7_mux_enum);
1830
1831static const struct snd_kcontrol_new sb_tx8_mux =
1832 SOC_DAPM_ENUM("SLIM TX8 MUX Mux", sb_tx8_mux_enum);
1833
1834static const struct snd_kcontrol_new sb_tx9_mux =
1835 SOC_DAPM_ENUM("SLIM TX9 MUX Mux", sb_tx9_mux_enum);
1836
1837static const struct snd_kcontrol_new sb_tx10_mux =
1838 SOC_DAPM_ENUM("SLIM TX10 MUX Mux", sb_tx10_mux_enum);
1839
1840
1841static int wcd9320_put_dec_enum(struct snd_kcontrol *kcontrol,
1842 struct snd_ctl_elem_value *ucontrol)
1843{
1844 struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol);
1845 struct snd_soc_dapm_widget *w = wlist->widgets[0];
1846 struct snd_soc_codec *codec = w->codec;
1847 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
1848 unsigned int dec_mux, decimator;
1849 char *dec_name = NULL;
1850 char *widget_name = NULL;
1851 char *temp;
1852 u16 tx_mux_ctl_reg;
1853 u8 adc_dmic_sel = 0x0;
1854 int ret = 0;
1855
1856 if (ucontrol->value.enumerated.item[0] > e->max - 1)
1857 return -EINVAL;
1858
1859 dec_mux = ucontrol->value.enumerated.item[0];
1860
1861 widget_name = kstrndup(w->name, 15, GFP_KERNEL);
1862 if (!widget_name)
1863 return -ENOMEM;
1864 temp = widget_name;
1865
1866 dec_name = strsep(&widget_name, " ");
1867 widget_name = temp;
1868 if (!dec_name) {
1869 pr_err("%s: Invalid decimator = %s\n", __func__, w->name);
1870 ret = -EINVAL;
1871 goto out;
1872 }
1873
1874 ret = kstrtouint(strpbrk(dec_name, "123456789"), 10, &decimator);
1875 if (ret < 0) {
1876 pr_err("%s: Invalid decimator = %s\n", __func__, dec_name);
1877 ret = -EINVAL;
1878 goto out;
1879 }
1880
1881 dev_dbg(w->dapm->dev, "%s(): widget = %s decimator = %u dec_mux = %u\n"
1882 , __func__, w->name, decimator, dec_mux);
1883
1884
1885 switch (decimator) {
1886 case 1:
1887 case 2:
1888 case 3:
1889 case 4:
1890 case 5:
1891 case 6:
1892 if (dec_mux == 1)
1893 adc_dmic_sel = 0x1;
1894 else
1895 adc_dmic_sel = 0x0;
1896 break;
1897 case 7:
1898 case 8:
1899 case 9:
1900 case 10:
1901 if ((dec_mux == 1) || (dec_mux == 2))
1902 adc_dmic_sel = 0x1;
1903 else
1904 adc_dmic_sel = 0x0;
1905 break;
1906 default:
1907 pr_err("%s: Invalid Decimator = %u\n", __func__, decimator);
1908 ret = -EINVAL;
1909 goto out;
1910 }
1911
1912 tx_mux_ctl_reg = TAIKO_A_CDC_TX1_MUX_CTL + 8 * (decimator - 1);
1913
1914 snd_soc_update_bits(codec, tx_mux_ctl_reg, 0x1, adc_dmic_sel);
1915
1916 ret = snd_soc_dapm_put_enum_double(kcontrol, ucontrol);
1917
1918out:
1919 kfree(widget_name);
1920 return ret;
1921}
1922
1923#define WCD9320_DEC_ENUM(xname, xenum) \
1924{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
1925 .info = snd_soc_info_enum_double, \
1926 .get = snd_soc_dapm_get_enum_double, \
1927 .put = wcd9320_put_dec_enum, \
1928 .private_value = (unsigned long)&xenum }
1929
1930static const struct snd_kcontrol_new dec1_mux =
1931 WCD9320_DEC_ENUM("DEC1 MUX Mux", dec1_mux_enum);
1932
1933static const struct snd_kcontrol_new dec2_mux =
1934 WCD9320_DEC_ENUM("DEC2 MUX Mux", dec2_mux_enum);
1935
1936static const struct snd_kcontrol_new dec3_mux =
1937 WCD9320_DEC_ENUM("DEC3 MUX Mux", dec3_mux_enum);
1938
1939static const struct snd_kcontrol_new dec4_mux =
1940 WCD9320_DEC_ENUM("DEC4 MUX Mux", dec4_mux_enum);
1941
1942static const struct snd_kcontrol_new dec5_mux =
1943 WCD9320_DEC_ENUM("DEC5 MUX Mux", dec5_mux_enum);
1944
1945static const struct snd_kcontrol_new dec6_mux =
1946 WCD9320_DEC_ENUM("DEC6 MUX Mux", dec6_mux_enum);
1947
1948static const struct snd_kcontrol_new dec7_mux =
1949 WCD9320_DEC_ENUM("DEC7 MUX Mux", dec7_mux_enum);
1950
1951static const struct snd_kcontrol_new dec8_mux =
1952 WCD9320_DEC_ENUM("DEC8 MUX Mux", dec8_mux_enum);
1953
1954static const struct snd_kcontrol_new dec9_mux =
1955 WCD9320_DEC_ENUM("DEC9 MUX Mux", dec9_mux_enum);
1956
1957static const struct snd_kcontrol_new dec10_mux =
1958 WCD9320_DEC_ENUM("DEC10 MUX Mux", dec10_mux_enum);
1959
1960static const struct snd_kcontrol_new iir1_inp1_mux =
1961 SOC_DAPM_ENUM("IIR1 INP1 Mux", iir1_inp1_mux_enum);
1962
Fred Oh456fcb52013-02-28 19:08:15 -08001963static const struct snd_kcontrol_new iir2_inp1_mux =
1964 SOC_DAPM_ENUM("IIR2 INP1 Mux", iir2_inp1_mux_enum);
1965
Kiran Kandic3b24402012-06-11 00:05:59 -07001966static const struct snd_kcontrol_new anc1_mux =
1967 SOC_DAPM_ENUM("ANC1 MUX Mux", anc1_mux_enum);
1968
1969static const struct snd_kcontrol_new anc2_mux =
1970 SOC_DAPM_ENUM("ANC2 MUX Mux", anc2_mux_enum);
1971
1972static const struct snd_kcontrol_new anc1_fb_mux =
1973 SOC_DAPM_ENUM("ANC1 FB MUX Mux", anc1_fb_mux_enum);
1974
1975static const struct snd_kcontrol_new dac1_switch[] = {
1976 SOC_DAPM_SINGLE("Switch", TAIKO_A_RX_EAR_EN, 5, 1, 0)
1977};
1978static const struct snd_kcontrol_new hphl_switch[] = {
1979 SOC_DAPM_SINGLE("Switch", TAIKO_A_RX_HPH_L_DAC_CTL, 6, 1, 0)
1980};
1981
1982static const struct snd_kcontrol_new hphl_pa_mix[] = {
1983 SOC_DAPM_SINGLE("AUX_PGA_L Switch", TAIKO_A_RX_PA_AUX_IN_CONN,
1984 7, 1, 0),
1985};
1986
1987static const struct snd_kcontrol_new hphr_pa_mix[] = {
1988 SOC_DAPM_SINGLE("AUX_PGA_R Switch", TAIKO_A_RX_PA_AUX_IN_CONN,
1989 6, 1, 0),
1990};
1991
1992static const struct snd_kcontrol_new ear_pa_mix[] = {
1993 SOC_DAPM_SINGLE("AUX_PGA_L Switch", TAIKO_A_RX_PA_AUX_IN_CONN,
1994 5, 1, 0),
1995};
1996static const struct snd_kcontrol_new lineout1_pa_mix[] = {
1997 SOC_DAPM_SINGLE("AUX_PGA_L Switch", TAIKO_A_RX_PA_AUX_IN_CONN,
1998 4, 1, 0),
1999};
2000
2001static const struct snd_kcontrol_new lineout2_pa_mix[] = {
2002 SOC_DAPM_SINGLE("AUX_PGA_R Switch", TAIKO_A_RX_PA_AUX_IN_CONN,
2003 3, 1, 0),
2004};
2005
2006static const struct snd_kcontrol_new lineout3_pa_mix[] = {
2007 SOC_DAPM_SINGLE("AUX_PGA_L Switch", TAIKO_A_RX_PA_AUX_IN_CONN,
2008 2, 1, 0),
2009};
2010
2011static const struct snd_kcontrol_new lineout4_pa_mix[] = {
2012 SOC_DAPM_SINGLE("AUX_PGA_R Switch", TAIKO_A_RX_PA_AUX_IN_CONN,
2013 1, 1, 0),
2014};
2015
2016static const struct snd_kcontrol_new lineout3_ground_switch =
2017 SOC_DAPM_SINGLE("Switch", TAIKO_A_RX_LINE_3_DAC_CTL, 6, 1, 0);
2018
2019static const struct snd_kcontrol_new lineout4_ground_switch =
2020 SOC_DAPM_SINGLE("Switch", TAIKO_A_RX_LINE_4_DAC_CTL, 6, 1, 0);
2021
Joonwoo Park9ead0e92013-03-18 11:33:33 -07002022static const struct snd_kcontrol_new aif4_mad_switch =
2023 SOC_DAPM_SINGLE("Switch", TAIKO_A_CDC_CLK_OTHR_CTL, 4, 1, 0);
2024
Kuirong Wang906ac472012-07-09 12:54:44 -07002025/* virtual port entries */
2026static int slim_tx_mixer_get(struct snd_kcontrol *kcontrol,
2027 struct snd_ctl_elem_value *ucontrol)
2028{
2029 struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol);
2030 struct snd_soc_dapm_widget *widget = wlist->widgets[0];
2031
2032 ucontrol->value.integer.value[0] = widget->value;
2033 return 0;
2034}
2035
2036static int slim_tx_mixer_put(struct snd_kcontrol *kcontrol,
2037 struct snd_ctl_elem_value *ucontrol)
2038{
2039 struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol);
2040 struct snd_soc_dapm_widget *widget = wlist->widgets[0];
2041 struct snd_soc_codec *codec = widget->codec;
2042 struct taiko_priv *taiko_p = snd_soc_codec_get_drvdata(codec);
2043 struct wcd9xxx *core = dev_get_drvdata(codec->dev->parent);
2044 struct soc_multi_mixer_control *mixer =
2045 ((struct soc_multi_mixer_control *)kcontrol->private_value);
2046 u32 dai_id = widget->shift;
2047 u32 port_id = mixer->shift;
2048 u32 enable = ucontrol->value.integer.value[0];
Venkat Sudhir96dd28c2012-12-04 17:00:19 -08002049 u32 vtable = vport_check_table[dai_id];
Kuirong Wang906ac472012-07-09 12:54:44 -07002050
2051
2052 pr_debug("%s: wname %s cname %s value %u shift %d item %ld\n", __func__,
2053 widget->name, ucontrol->id.name, widget->value, widget->shift,
2054 ucontrol->value.integer.value[0]);
2055
2056 mutex_lock(&codec->mutex);
2057
2058 if (taiko_p->intf_type != WCD9XXX_INTERFACE_TYPE_SLIMBUS) {
2059 if (dai_id != AIF1_CAP) {
2060 dev_err(codec->dev, "%s: invalid AIF for I2C mode\n",
2061 __func__);
2062 mutex_unlock(&codec->mutex);
2063 return -EINVAL;
2064 }
2065 }
Venkat Sudhira41630a2012-10-27 00:57:31 -07002066 switch (dai_id) {
2067 case AIF1_CAP:
2068 case AIF2_CAP:
2069 case AIF3_CAP:
2070 /* only add to the list if value not set
2071 */
2072 if (enable && !(widget->value & 1 << port_id)) {
Venkat Sudhir96dd28c2012-12-04 17:00:19 -08002073
2074 if (taiko_p->intf_type ==
2075 WCD9XXX_INTERFACE_TYPE_SLIMBUS)
2076 vtable = vport_check_table[dai_id];
2077 if (taiko_p->intf_type ==
2078 WCD9XXX_INTERFACE_TYPE_I2C)
2079 vtable = vport_i2s_check_table[dai_id];
2080
Venkat Sudhira41630a2012-10-27 00:57:31 -07002081 if (wcd9xxx_tx_vport_validation(
Venkat Sudhir96dd28c2012-12-04 17:00:19 -08002082 vtable,
Kuirong Wangdcc392e2012-10-19 00:33:38 -07002083 port_id,
2084 taiko_p->dai)) {
Kuirong Wang80aca0d2013-05-09 14:51:09 -07002085 dev_dbg(codec->dev, "%s: TX%u is used by other virtual port\n",
Venkat Sudhira41630a2012-10-27 00:57:31 -07002086 __func__, port_id + 1);
2087 mutex_unlock(&codec->mutex);
Kuirong Wang80aca0d2013-05-09 14:51:09 -07002088 return 0;
Venkat Sudhira41630a2012-10-27 00:57:31 -07002089 }
2090 widget->value |= 1 << port_id;
2091 list_add_tail(&core->tx_chs[port_id].list,
Kuirong Wang906ac472012-07-09 12:54:44 -07002092 &taiko_p->dai[dai_id].wcd9xxx_ch_list
Venkat Sudhira41630a2012-10-27 00:57:31 -07002093 );
2094 } else if (!enable && (widget->value & 1 << port_id)) {
2095 widget->value &= ~(1 << port_id);
2096 list_del_init(&core->tx_chs[port_id].list);
2097 } else {
2098 if (enable)
Kuirong Wang80aca0d2013-05-09 14:51:09 -07002099 dev_dbg(codec->dev, "%s: TX%u port is used by\n"
Venkat Sudhira41630a2012-10-27 00:57:31 -07002100 "this virtual port\n",
2101 __func__, port_id + 1);
2102 else
Kuirong Wang80aca0d2013-05-09 14:51:09 -07002103 dev_dbg(codec->dev, "%s: TX%u port is not used by\n"
Venkat Sudhira41630a2012-10-27 00:57:31 -07002104 "this virtual port\n",
2105 __func__, port_id + 1);
2106 /* avoid update power function */
2107 mutex_unlock(&codec->mutex);
2108 return 0;
2109 }
2110 break;
2111 default:
2112 pr_err("Unknown AIF %d\n", dai_id);
Kuirong Wang906ac472012-07-09 12:54:44 -07002113 mutex_unlock(&codec->mutex);
Venkat Sudhira41630a2012-10-27 00:57:31 -07002114 return -EINVAL;
Kuirong Wang906ac472012-07-09 12:54:44 -07002115 }
Kuirong Wang906ac472012-07-09 12:54:44 -07002116 pr_debug("%s: name %s sname %s updated value %u shift %d\n", __func__,
2117 widget->name, widget->sname, widget->value, widget->shift);
2118
2119 snd_soc_dapm_mixer_update_power(widget, kcontrol, enable);
2120
2121 mutex_unlock(&codec->mutex);
2122 return 0;
2123}
2124
2125static int slim_rx_mux_get(struct snd_kcontrol *kcontrol,
2126 struct snd_ctl_elem_value *ucontrol)
2127{
2128 struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol);
2129 struct snd_soc_dapm_widget *widget = wlist->widgets[0];
2130
2131 ucontrol->value.enumerated.item[0] = widget->value;
2132 return 0;
2133}
2134
2135static const char *const slim_rx_mux_text[] = {
2136 "ZERO", "AIF1_PB", "AIF2_PB", "AIF3_PB"
2137};
2138
2139static int slim_rx_mux_put(struct snd_kcontrol *kcontrol,
2140 struct snd_ctl_elem_value *ucontrol)
2141{
2142 struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol);
2143 struct snd_soc_dapm_widget *widget = wlist->widgets[0];
2144 struct snd_soc_codec *codec = widget->codec;
2145 struct taiko_priv *taiko_p = snd_soc_codec_get_drvdata(codec);
2146 struct wcd9xxx *core = dev_get_drvdata(codec->dev->parent);
2147 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
2148 u32 port_id = widget->shift;
2149
2150 pr_debug("%s: wname %s cname %s value %u shift %d item %ld\n", __func__,
2151 widget->name, ucontrol->id.name, widget->value, widget->shift,
2152 ucontrol->value.integer.value[0]);
2153
2154 widget->value = ucontrol->value.enumerated.item[0];
2155
2156 mutex_lock(&codec->mutex);
2157
2158 if (taiko_p->intf_type != WCD9XXX_INTERFACE_TYPE_SLIMBUS) {
Venkat Sudhir994193b2012-12-17 17:30:51 -08002159 if (widget->value > 2) {
Kuirong Wang906ac472012-07-09 12:54:44 -07002160 dev_err(codec->dev, "%s: invalid AIF for I2C mode\n",
2161 __func__);
Kuirong Wangdcc392e2012-10-19 00:33:38 -07002162 goto err;
Kuirong Wang906ac472012-07-09 12:54:44 -07002163 }
2164 }
2165 /* value need to match the Virtual port and AIF number
2166 */
2167 switch (widget->value) {
2168 case 0:
2169 list_del_init(&core->rx_chs[port_id].list);
2170 break;
2171 case 1:
Kuirong Wang80aca0d2013-05-09 14:51:09 -07002172 if (wcd9xxx_rx_vport_validation(port_id +
2173 TAIKO_RX_PORT_START_NUMBER,
2174 &taiko_p->dai[AIF1_PB].wcd9xxx_ch_list)) {
2175 dev_dbg(codec->dev, "%s: RX%u is used by current requesting AIF_PB itself\n",
2176 __func__, port_id + 1);
2177 goto rtn;
2178 }
Kuirong Wang906ac472012-07-09 12:54:44 -07002179 list_add_tail(&core->rx_chs[port_id].list,
2180 &taiko_p->dai[AIF1_PB].wcd9xxx_ch_list);
2181 break;
2182 case 2:
Kuirong Wang80aca0d2013-05-09 14:51:09 -07002183 if (wcd9xxx_rx_vport_validation(port_id +
2184 TAIKO_RX_PORT_START_NUMBER,
2185 &taiko_p->dai[AIF2_PB].wcd9xxx_ch_list)) {
2186 dev_dbg(codec->dev, "%s: RX%u is used by current requesting AIF_PB itself\n",
2187 __func__, port_id + 1);
2188 goto rtn;
2189 }
Kuirong Wang906ac472012-07-09 12:54:44 -07002190 list_add_tail(&core->rx_chs[port_id].list,
2191 &taiko_p->dai[AIF2_PB].wcd9xxx_ch_list);
2192 break;
2193 case 3:
Kuirong Wang80aca0d2013-05-09 14:51:09 -07002194 if (wcd9xxx_rx_vport_validation(port_id +
2195 TAIKO_RX_PORT_START_NUMBER,
2196 &taiko_p->dai[AIF3_PB].wcd9xxx_ch_list)) {
2197 dev_dbg(codec->dev, "%s: RX%u is used by current requesting AIF_PB itself\n",
2198 __func__, port_id + 1);
2199 goto rtn;
2200 }
Kuirong Wang906ac472012-07-09 12:54:44 -07002201 list_add_tail(&core->rx_chs[port_id].list,
2202 &taiko_p->dai[AIF3_PB].wcd9xxx_ch_list);
2203 break;
2204 default:
2205 pr_err("Unknown AIF %d\n", widget->value);
Kuirong Wangdcc392e2012-10-19 00:33:38 -07002206 goto err;
Kuirong Wang906ac472012-07-09 12:54:44 -07002207 }
Kuirong Wang80aca0d2013-05-09 14:51:09 -07002208rtn:
Kuirong Wang906ac472012-07-09 12:54:44 -07002209 snd_soc_dapm_mux_update_power(widget, kcontrol, 1, widget->value, e);
2210
2211 mutex_unlock(&codec->mutex);
2212 return 0;
Kuirong Wangdcc392e2012-10-19 00:33:38 -07002213err:
2214 mutex_unlock(&codec->mutex);
2215 return -EINVAL;
Kuirong Wang906ac472012-07-09 12:54:44 -07002216}
2217
2218static const struct soc_enum slim_rx_mux_enum =
2219 SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(slim_rx_mux_text), slim_rx_mux_text);
2220
2221static const struct snd_kcontrol_new slim_rx_mux[TAIKO_RX_MAX] = {
2222 SOC_DAPM_ENUM_EXT("SLIM RX1 Mux", slim_rx_mux_enum,
2223 slim_rx_mux_get, slim_rx_mux_put),
2224 SOC_DAPM_ENUM_EXT("SLIM RX2 Mux", slim_rx_mux_enum,
2225 slim_rx_mux_get, slim_rx_mux_put),
2226 SOC_DAPM_ENUM_EXT("SLIM RX3 Mux", slim_rx_mux_enum,
2227 slim_rx_mux_get, slim_rx_mux_put),
2228 SOC_DAPM_ENUM_EXT("SLIM RX4 Mux", slim_rx_mux_enum,
2229 slim_rx_mux_get, slim_rx_mux_put),
2230 SOC_DAPM_ENUM_EXT("SLIM RX5 Mux", slim_rx_mux_enum,
2231 slim_rx_mux_get, slim_rx_mux_put),
2232 SOC_DAPM_ENUM_EXT("SLIM RX6 Mux", slim_rx_mux_enum,
2233 slim_rx_mux_get, slim_rx_mux_put),
2234 SOC_DAPM_ENUM_EXT("SLIM RX7 Mux", slim_rx_mux_enum,
2235 slim_rx_mux_get, slim_rx_mux_put),
2236};
2237
2238static const struct snd_kcontrol_new aif_cap_mixer[] = {
2239 SOC_SINGLE_EXT("SLIM TX1", SND_SOC_NOPM, TAIKO_TX1, 1, 0,
2240 slim_tx_mixer_get, slim_tx_mixer_put),
2241 SOC_SINGLE_EXT("SLIM TX2", SND_SOC_NOPM, TAIKO_TX2, 1, 0,
2242 slim_tx_mixer_get, slim_tx_mixer_put),
2243 SOC_SINGLE_EXT("SLIM TX3", SND_SOC_NOPM, TAIKO_TX3, 1, 0,
2244 slim_tx_mixer_get, slim_tx_mixer_put),
2245 SOC_SINGLE_EXT("SLIM TX4", SND_SOC_NOPM, TAIKO_TX4, 1, 0,
2246 slim_tx_mixer_get, slim_tx_mixer_put),
2247 SOC_SINGLE_EXT("SLIM TX5", SND_SOC_NOPM, TAIKO_TX5, 1, 0,
2248 slim_tx_mixer_get, slim_tx_mixer_put),
2249 SOC_SINGLE_EXT("SLIM TX6", SND_SOC_NOPM, TAIKO_TX6, 1, 0,
2250 slim_tx_mixer_get, slim_tx_mixer_put),
2251 SOC_SINGLE_EXT("SLIM TX7", SND_SOC_NOPM, TAIKO_TX7, 1, 0,
2252 slim_tx_mixer_get, slim_tx_mixer_put),
2253 SOC_SINGLE_EXT("SLIM TX8", SND_SOC_NOPM, TAIKO_TX8, 1, 0,
2254 slim_tx_mixer_get, slim_tx_mixer_put),
2255 SOC_SINGLE_EXT("SLIM TX9", SND_SOC_NOPM, TAIKO_TX9, 1, 0,
2256 slim_tx_mixer_get, slim_tx_mixer_put),
2257 SOC_SINGLE_EXT("SLIM TX10", SND_SOC_NOPM, TAIKO_TX10, 1, 0,
2258 slim_tx_mixer_get, slim_tx_mixer_put),
2259};
2260
Kiran Kandic3b24402012-06-11 00:05:59 -07002261static void taiko_codec_enable_adc_block(struct snd_soc_codec *codec,
2262 int enable)
2263{
2264 struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
2265
2266 pr_debug("%s %d\n", __func__, enable);
2267
2268 if (enable) {
2269 taiko->adc_count++;
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08002270 snd_soc_update_bits(codec, WCD9XXX_A_CDC_CLK_OTHR_CTL,
2271 0x2, 0x2);
Kiran Kandic3b24402012-06-11 00:05:59 -07002272 } else {
2273 taiko->adc_count--;
2274 if (!taiko->adc_count)
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08002275 snd_soc_update_bits(codec, WCD9XXX_A_CDC_CLK_OTHR_CTL,
Kiran Kandic3b24402012-06-11 00:05:59 -07002276 0x2, 0x0);
2277 }
2278}
2279
2280static int taiko_codec_enable_adc(struct snd_soc_dapm_widget *w,
2281 struct snd_kcontrol *kcontrol, int event)
2282{
2283 struct snd_soc_codec *codec = w->codec;
2284 u16 adc_reg;
2285 u8 init_bit_shift;
Joonwoo Park2a9170a2013-03-04 17:05:57 -08002286 struct wcd9xxx *core = dev_get_drvdata(codec->dev->parent);
Kiran Kandic3b24402012-06-11 00:05:59 -07002287
2288 pr_debug("%s %d\n", __func__, event);
2289
Joonwoo Park2a9170a2013-03-04 17:05:57 -08002290 if (TAIKO_IS_1_0(core->version)) {
2291 if (w->reg == TAIKO_A_TX_1_2_EN) {
2292 adc_reg = TAIKO_A_TX_1_2_TEST_CTL;
2293 } else if (w->reg == TAIKO_A_TX_3_4_EN) {
2294 adc_reg = TAIKO_A_TX_3_4_TEST_CTL;
2295 } else if (w->reg == TAIKO_A_TX_5_6_EN) {
2296 adc_reg = TAIKO_A_TX_5_6_TEST_CTL;
2297 } else {
2298 pr_err("%s: Error, invalid adc register\n", __func__);
2299 return -EINVAL;
2300 }
Kiran Kandic3b24402012-06-11 00:05:59 -07002301
Joonwoo Park2a9170a2013-03-04 17:05:57 -08002302 if (w->shift == 3) {
2303 init_bit_shift = 6;
2304 } else if (w->shift == 7) {
2305 init_bit_shift = 7;
2306 } else {
2307 pr_err("%s: Error, invalid init bit postion adc register\n",
2308 __func__);
2309 return -EINVAL;
2310 }
2311 } else {
2312 switch (w->reg) {
2313 case TAIKO_A_CDC_TX_1_GAIN:
2314 adc_reg = TAIKO_A_TX_1_2_TEST_CTL;
2315 init_bit_shift = 7;
2316 break;
2317 case TAIKO_A_CDC_TX_2_GAIN:
2318 adc_reg = TAIKO_A_TX_1_2_TEST_CTL;
2319 init_bit_shift = 6;
2320 break;
2321 case TAIKO_A_CDC_TX_3_GAIN:
2322 adc_reg = TAIKO_A_TX_3_4_TEST_CTL;
2323 init_bit_shift = 7;
2324 break;
2325 case TAIKO_A_CDC_TX_4_GAIN:
2326 adc_reg = TAIKO_A_TX_3_4_TEST_CTL;
2327 init_bit_shift = 6;
2328 break;
2329 case TAIKO_A_CDC_TX_5_GAIN:
2330 adc_reg = TAIKO_A_TX_5_6_TEST_CTL;
2331 init_bit_shift = 7;
2332 break;
2333 case TAIKO_A_CDC_TX_6_GAIN:
2334 adc_reg = TAIKO_A_TX_5_6_TEST_CTL;
2335 init_bit_shift = 6;
2336 break;
2337 default:
2338 pr_err("%s: Error, invalid adc register\n", __func__);
2339 return -EINVAL;
2340 }
Kiran Kandic3b24402012-06-11 00:05:59 -07002341 }
2342
2343 switch (event) {
2344 case SND_SOC_DAPM_PRE_PMU:
2345 taiko_codec_enable_adc_block(codec, 1);
2346 snd_soc_update_bits(codec, adc_reg, 1 << init_bit_shift,
2347 1 << init_bit_shift);
2348 break;
2349 case SND_SOC_DAPM_POST_PMU:
Kiran Kandic3b24402012-06-11 00:05:59 -07002350 snd_soc_update_bits(codec, adc_reg, 1 << init_bit_shift, 0x00);
Kiran Kandic3b24402012-06-11 00:05:59 -07002351 break;
2352 case SND_SOC_DAPM_POST_PMD:
2353 taiko_codec_enable_adc_block(codec, 0);
2354 break;
2355 }
2356 return 0;
2357}
2358
Kiran Kandic3b24402012-06-11 00:05:59 -07002359static int taiko_codec_enable_aux_pga(struct snd_soc_dapm_widget *w,
2360 struct snd_kcontrol *kcontrol, int event)
2361{
2362 struct snd_soc_codec *codec = w->codec;
2363 struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
2364
2365 pr_debug("%s: %d\n", __func__, event);
2366
2367 switch (event) {
2368 case SND_SOC_DAPM_PRE_PMU:
Joonwoo Park533b3682013-06-13 11:41:21 -07002369 WCD9XXX_BG_CLK_LOCK(&taiko->resmgr);
Joonwoo Parka8890262012-10-15 12:04:27 -07002370 wcd9xxx_resmgr_get_bandgap(&taiko->resmgr,
2371 WCD9XXX_BANDGAP_AUDIO_MODE);
2372 /* AUX PGA requires RCO or MCLK */
2373 wcd9xxx_resmgr_get_clk_block(&taiko->resmgr, WCD9XXX_CLK_RCO);
2374 wcd9xxx_resmgr_enable_rx_bias(&taiko->resmgr, 1);
Joonwoo Park533b3682013-06-13 11:41:21 -07002375 WCD9XXX_BG_CLK_UNLOCK(&taiko->resmgr);
Kiran Kandic3b24402012-06-11 00:05:59 -07002376 break;
2377
2378 case SND_SOC_DAPM_POST_PMD:
Joonwoo Park533b3682013-06-13 11:41:21 -07002379 WCD9XXX_BG_CLK_LOCK(&taiko->resmgr);
Joonwoo Parka8890262012-10-15 12:04:27 -07002380 wcd9xxx_resmgr_enable_rx_bias(&taiko->resmgr, 0);
2381 wcd9xxx_resmgr_put_bandgap(&taiko->resmgr,
2382 WCD9XXX_BANDGAP_AUDIO_MODE);
2383 wcd9xxx_resmgr_put_clk_block(&taiko->resmgr, WCD9XXX_CLK_RCO);
Joonwoo Park533b3682013-06-13 11:41:21 -07002384 WCD9XXX_BG_CLK_UNLOCK(&taiko->resmgr);
Kiran Kandic3b24402012-06-11 00:05:59 -07002385 break;
2386 }
2387 return 0;
2388}
2389
2390static int taiko_codec_enable_lineout(struct snd_soc_dapm_widget *w,
2391 struct snd_kcontrol *kcontrol, int event)
2392{
2393 struct snd_soc_codec *codec = w->codec;
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08002394 struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
Kiran Kandic3b24402012-06-11 00:05:59 -07002395 u16 lineout_gain_reg;
2396
2397 pr_debug("%s %d %s\n", __func__, event, w->name);
2398
2399 switch (w->shift) {
2400 case 0:
2401 lineout_gain_reg = TAIKO_A_RX_LINE_1_GAIN;
2402 break;
2403 case 1:
2404 lineout_gain_reg = TAIKO_A_RX_LINE_2_GAIN;
2405 break;
2406 case 2:
2407 lineout_gain_reg = TAIKO_A_RX_LINE_3_GAIN;
2408 break;
2409 case 3:
2410 lineout_gain_reg = TAIKO_A_RX_LINE_4_GAIN;
2411 break;
2412 default:
2413 pr_err("%s: Error, incorrect lineout register value\n",
2414 __func__);
2415 return -EINVAL;
2416 }
2417
2418 switch (event) {
2419 case SND_SOC_DAPM_PRE_PMU:
2420 snd_soc_update_bits(codec, lineout_gain_reg, 0x40, 0x40);
2421 break;
2422 case SND_SOC_DAPM_POST_PMU:
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08002423 wcd9xxx_clsh_fsm(codec, &taiko->clsh_d,
2424 WCD9XXX_CLSH_STATE_LO,
2425 WCD9XXX_CLSH_REQ_ENABLE,
2426 WCD9XXX_CLSH_EVENT_POST_PA);
2427 pr_debug("%s: sleeping 3 ms after %s PA turn on\n",
Kiran Kandic3b24402012-06-11 00:05:59 -07002428 __func__, w->name);
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08002429 usleep_range(3000, 3000);
Kiran Kandic3b24402012-06-11 00:05:59 -07002430 break;
2431 case SND_SOC_DAPM_POST_PMD:
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08002432 wcd9xxx_clsh_fsm(codec, &taiko->clsh_d,
2433 WCD9XXX_CLSH_STATE_LO,
2434 WCD9XXX_CLSH_REQ_DISABLE,
2435 WCD9XXX_CLSH_EVENT_POST_PA);
Kiran Kandic3b24402012-06-11 00:05:59 -07002436 snd_soc_update_bits(codec, lineout_gain_reg, 0x40, 0x00);
2437 break;
2438 }
2439 return 0;
2440}
2441
Joonwoo Park7680b9f2012-07-13 11:36:48 -07002442static int taiko_codec_enable_spk_pa(struct snd_soc_dapm_widget *w,
2443 struct snd_kcontrol *kcontrol, int event)
2444{
Joonwoo Park125cd4e2012-12-11 15:16:11 -08002445 struct snd_soc_codec *codec = w->codec;
2446 struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
2447
2448 pr_debug("%s: %d %s\n", __func__, event, w->name);
Joonwoo Park125cd4e2012-12-11 15:16:11 -08002449 switch (event) {
2450 case SND_SOC_DAPM_PRE_PMU:
2451 taiko->spkr_pa_widget_on = true;
2452 snd_soc_update_bits(codec, TAIKO_A_SPKR_DRV_EN, 0x80, 0x80);
2453 break;
2454 case SND_SOC_DAPM_POST_PMD:
2455 taiko->spkr_pa_widget_on = false;
2456 snd_soc_update_bits(codec, TAIKO_A_SPKR_DRV_EN, 0x80, 0x00);
2457 break;
2458 }
Joonwoo Park7680b9f2012-07-13 11:36:48 -07002459 return 0;
2460}
Kiran Kandic3b24402012-06-11 00:05:59 -07002461
2462static int taiko_codec_enable_dmic(struct snd_soc_dapm_widget *w,
2463 struct snd_kcontrol *kcontrol, int event)
2464{
2465 struct snd_soc_codec *codec = w->codec;
2466 struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
2467 u8 dmic_clk_en;
2468 u16 dmic_clk_reg;
2469 s32 *dmic_clk_cnt;
2470 unsigned int dmic;
2471 int ret;
2472
2473 ret = kstrtouint(strpbrk(w->name, "123456"), 10, &dmic);
2474 if (ret < 0) {
2475 pr_err("%s: Invalid DMIC line on the codec\n", __func__);
2476 return -EINVAL;
2477 }
2478
2479 switch (dmic) {
2480 case 1:
2481 case 2:
2482 dmic_clk_en = 0x01;
2483 dmic_clk_cnt = &(taiko->dmic_1_2_clk_cnt);
2484 dmic_clk_reg = TAIKO_A_CDC_CLK_DMIC_B1_CTL;
2485 pr_debug("%s() event %d DMIC%d dmic_1_2_clk_cnt %d\n",
2486 __func__, event, dmic, *dmic_clk_cnt);
2487
2488 break;
2489
2490 case 3:
2491 case 4:
2492 dmic_clk_en = 0x10;
2493 dmic_clk_cnt = &(taiko->dmic_3_4_clk_cnt);
2494 dmic_clk_reg = TAIKO_A_CDC_CLK_DMIC_B1_CTL;
2495
2496 pr_debug("%s() event %d DMIC%d dmic_3_4_clk_cnt %d\n",
2497 __func__, event, dmic, *dmic_clk_cnt);
2498 break;
2499
2500 case 5:
2501 case 6:
2502 dmic_clk_en = 0x01;
2503 dmic_clk_cnt = &(taiko->dmic_5_6_clk_cnt);
2504 dmic_clk_reg = TAIKO_A_CDC_CLK_DMIC_B2_CTL;
2505
2506 pr_debug("%s() event %d DMIC%d dmic_5_6_clk_cnt %d\n",
2507 __func__, event, dmic, *dmic_clk_cnt);
2508
2509 break;
2510
2511 default:
2512 pr_err("%s: Invalid DMIC Selection\n", __func__);
2513 return -EINVAL;
2514 }
2515
2516 switch (event) {
2517 case SND_SOC_DAPM_PRE_PMU:
2518
2519 (*dmic_clk_cnt)++;
2520 if (*dmic_clk_cnt == 1)
2521 snd_soc_update_bits(codec, dmic_clk_reg,
2522 dmic_clk_en, dmic_clk_en);
2523
2524 break;
2525 case SND_SOC_DAPM_POST_PMD:
2526
2527 (*dmic_clk_cnt)--;
2528 if (*dmic_clk_cnt == 0)
2529 snd_soc_update_bits(codec, dmic_clk_reg,
2530 dmic_clk_en, 0);
2531 break;
2532 }
2533 return 0;
2534}
2535
Joonwoo Park1d05bb92013-03-07 16:55:06 -08002536static int taiko_codec_config_mad(struct snd_soc_codec *codec)
2537{
2538 int ret;
2539 const struct firmware *fw;
2540 struct mad_audio_cal *mad_cal;
2541 const char *filename = TAIKO_MAD_AUDIO_FIRMWARE_PATH;
2542
2543 pr_debug("%s: enter\n", __func__);
2544 ret = request_firmware(&fw, filename, codec->dev);
2545 if (ret != 0) {
2546 pr_err("Failed to acquire MAD firwmare data %s: %d\n", filename,
2547 ret);
2548 return -ENODEV;
2549 }
2550
2551 if (fw->size < sizeof(struct mad_audio_cal)) {
2552 pr_err("%s: incorrect firmware size %u\n", __func__, fw->size);
2553 release_firmware(fw);
2554 return -ENOMEM;
2555 }
2556
2557 mad_cal = (struct mad_audio_cal *)(fw->data);
2558 if (!mad_cal) {
2559 pr_err("%s: Invalid calibration data\n", __func__);
2560 release_firmware(fw);
2561 return -EINVAL;
2562 }
2563
2564 snd_soc_update_bits(codec, TAIKO_A_CDC_CONN_MAD,
2565 0x0F, mad_cal->microphone_info.input_microphone);
2566 snd_soc_write(codec, TAIKO_A_CDC_MAD_MAIN_CTL_2,
2567 mad_cal->microphone_info.cycle_time);
2568 snd_soc_update_bits(codec, TAIKO_A_CDC_MAD_MAIN_CTL_1, 0xFF << 3,
2569 ((uint16_t)mad_cal->microphone_info.settle_time)
2570 << 3);
2571
2572 /* Audio */
2573 snd_soc_write(codec, TAIKO_A_CDC_MAD_AUDIO_CTL_8,
2574 mad_cal->audio_info.rms_omit_samples);
2575 snd_soc_update_bits(codec, TAIKO_A_CDC_MAD_AUDIO_CTL_1,
2576 0x07 << 4, mad_cal->audio_info.rms_comp_time << 4);
2577 snd_soc_update_bits(codec, TAIKO_A_CDC_MAD_AUDIO_CTL_2, 0x03 << 2,
2578 mad_cal->audio_info.detection_mechanism << 2);
2579 snd_soc_write(codec, TAIKO_A_CDC_MAD_AUDIO_CTL_7,
2580 mad_cal->audio_info.rms_diff_threshold & 0x3F);
2581 snd_soc_write(codec, TAIKO_A_CDC_MAD_AUDIO_CTL_5,
2582 mad_cal->audio_info.rms_threshold_lsb);
2583 snd_soc_write(codec, TAIKO_A_CDC_MAD_AUDIO_CTL_6,
2584 mad_cal->audio_info.rms_threshold_msb);
2585
2586
2587 /* Beacon */
2588 snd_soc_write(codec, TAIKO_A_CDC_MAD_BEACON_CTL_8,
2589 mad_cal->beacon_info.rms_omit_samples);
2590 snd_soc_update_bits(codec, TAIKO_A_CDC_MAD_BEACON_CTL_1,
2591 0x07 << 4, mad_cal->beacon_info.rms_comp_time);
2592 snd_soc_update_bits(codec, TAIKO_A_CDC_MAD_BEACON_CTL_2, 0x03 << 2,
2593 mad_cal->beacon_info.detection_mechanism << 2);
2594 snd_soc_write(codec, TAIKO_A_CDC_MAD_BEACON_CTL_7,
2595 mad_cal->beacon_info.rms_diff_threshold & 0x1F);
2596 snd_soc_write(codec, TAIKO_A_CDC_MAD_BEACON_CTL_5,
2597 mad_cal->beacon_info.rms_threshold_lsb);
2598 snd_soc_write(codec, TAIKO_A_CDC_MAD_BEACON_CTL_6,
2599 mad_cal->beacon_info.rms_threshold_msb);
2600
2601 /* Ultrasound */
2602 snd_soc_update_bits(codec, TAIKO_A_CDC_MAD_BEACON_CTL_1,
2603 0x07 << 4, mad_cal->beacon_info.rms_comp_time);
2604 snd_soc_update_bits(codec, TAIKO_A_CDC_MAD_ULTR_CTL_2, 0x03 << 2,
2605 mad_cal->ultrasound_info.detection_mechanism);
2606 snd_soc_write(codec, TAIKO_A_CDC_MAD_ULTR_CTL_7,
2607 mad_cal->ultrasound_info.rms_diff_threshold & 0x1F);
2608 snd_soc_write(codec, TAIKO_A_CDC_MAD_ULTR_CTL_5,
2609 mad_cal->ultrasound_info.rms_threshold_lsb);
2610 snd_soc_write(codec, TAIKO_A_CDC_MAD_ULTR_CTL_6,
2611 mad_cal->ultrasound_info.rms_threshold_msb);
2612
2613 release_firmware(fw);
2614 pr_debug("%s: leave ret %d\n", __func__, ret);
2615
2616 return ret;
2617}
2618
2619static int taiko_codec_enable_mad(struct snd_soc_dapm_widget *w,
2620 struct snd_kcontrol *kcontrol, int event)
2621{
2622 struct snd_soc_codec *codec = w->codec;
2623 int ret = 0;
2624
2625 pr_debug("%s %d\n", __func__, event);
2626 switch (event) {
2627 case SND_SOC_DAPM_PRE_PMU:
2628 ret = taiko_codec_config_mad(codec);
2629 if (ret) {
2630 pr_err("%s: Failed to config MAD\n", __func__);
2631 break;
2632 }
2633 break;
2634 }
2635 return ret;
2636}
2637
Kiran Kandic3b24402012-06-11 00:05:59 -07002638static int taiko_codec_enable_micbias(struct snd_soc_dapm_widget *w,
2639 struct snd_kcontrol *kcontrol, int event)
2640{
2641 struct snd_soc_codec *codec = w->codec;
2642 struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
Joonwoo Park3699ca32013-02-08 12:06:15 -08002643 u16 micb_int_reg = 0, micb_ctl_reg = 0;
Kiran Kandic3b24402012-06-11 00:05:59 -07002644 u8 cfilt_sel_val = 0;
2645 char *internal1_text = "Internal1";
2646 char *internal2_text = "Internal2";
2647 char *internal3_text = "Internal3";
Joonwoo Parka8890262012-10-15 12:04:27 -07002648 enum wcd9xxx_notify_event e_post_off, e_pre_on, e_post_on;
Kiran Kandic3b24402012-06-11 00:05:59 -07002649
Joonwoo Park3699ca32013-02-08 12:06:15 -08002650 pr_debug("%s: w->name %s event %d\n", __func__, w->name, event);
2651 if (strnstr(w->name, "MIC BIAS1", sizeof("MIC BIAS1"))) {
2652 micb_ctl_reg = TAIKO_A_MICB_1_CTL;
Kiran Kandic3b24402012-06-11 00:05:59 -07002653 micb_int_reg = TAIKO_A_MICB_1_INT_RBIAS;
Joonwoo Parka8890262012-10-15 12:04:27 -07002654 cfilt_sel_val = taiko->resmgr.pdata->micbias.bias1_cfilt_sel;
2655 e_pre_on = WCD9XXX_EVENT_PRE_MICBIAS_1_ON;
2656 e_post_on = WCD9XXX_EVENT_POST_MICBIAS_1_ON;
2657 e_post_off = WCD9XXX_EVENT_POST_MICBIAS_1_OFF;
Joonwoo Park3699ca32013-02-08 12:06:15 -08002658 } else if (strnstr(w->name, "MIC BIAS2", sizeof("MIC BIAS2"))) {
2659 micb_ctl_reg = TAIKO_A_MICB_2_CTL;
Kiran Kandic3b24402012-06-11 00:05:59 -07002660 micb_int_reg = TAIKO_A_MICB_2_INT_RBIAS;
Joonwoo Parka8890262012-10-15 12:04:27 -07002661 cfilt_sel_val = taiko->resmgr.pdata->micbias.bias2_cfilt_sel;
2662 e_pre_on = WCD9XXX_EVENT_PRE_MICBIAS_2_ON;
2663 e_post_on = WCD9XXX_EVENT_POST_MICBIAS_2_ON;
2664 e_post_off = WCD9XXX_EVENT_POST_MICBIAS_2_OFF;
Joonwoo Park3699ca32013-02-08 12:06:15 -08002665 } else if (strnstr(w->name, "MIC BIAS3", sizeof("MIC BIAS3"))) {
Damir Didjusto6e4f9d22013-03-07 10:10:57 -08002666 micb_ctl_reg = TAIKO_A_MICB_3_CTL;
Kiran Kandic3b24402012-06-11 00:05:59 -07002667 micb_int_reg = TAIKO_A_MICB_3_INT_RBIAS;
Joonwoo Parka8890262012-10-15 12:04:27 -07002668 cfilt_sel_val = taiko->resmgr.pdata->micbias.bias3_cfilt_sel;
2669 e_pre_on = WCD9XXX_EVENT_PRE_MICBIAS_3_ON;
2670 e_post_on = WCD9XXX_EVENT_POST_MICBIAS_3_ON;
2671 e_post_off = WCD9XXX_EVENT_POST_MICBIAS_3_OFF;
Joonwoo Park3699ca32013-02-08 12:06:15 -08002672 } else if (strnstr(w->name, "MIC BIAS4", sizeof("MIC BIAS4"))) {
Damir Didjusto6e4f9d22013-03-07 10:10:57 -08002673 micb_ctl_reg = TAIKO_A_MICB_4_CTL;
Joonwoo Parka8890262012-10-15 12:04:27 -07002674 micb_int_reg = taiko->resmgr.reg_addr->micb_4_int_rbias;
2675 cfilt_sel_val = taiko->resmgr.pdata->micbias.bias4_cfilt_sel;
2676 e_pre_on = WCD9XXX_EVENT_PRE_MICBIAS_4_ON;
2677 e_post_on = WCD9XXX_EVENT_POST_MICBIAS_4_ON;
2678 e_post_off = WCD9XXX_EVENT_POST_MICBIAS_4_OFF;
Joonwoo Park3699ca32013-02-08 12:06:15 -08002679 } else {
2680 pr_err("%s: Error, invalid micbias %s\n", __func__, w->name);
Kiran Kandic3b24402012-06-11 00:05:59 -07002681 return -EINVAL;
2682 }
2683
2684 switch (event) {
2685 case SND_SOC_DAPM_PRE_PMU:
Joonwoo Parka8890262012-10-15 12:04:27 -07002686 /* Let MBHC module know so micbias switch to be off */
2687 wcd9xxx_resmgr_notifier_call(&taiko->resmgr, e_pre_on);
Kiran Kandic3b24402012-06-11 00:05:59 -07002688
Joonwoo Parka8890262012-10-15 12:04:27 -07002689 /* Get cfilt */
2690 wcd9xxx_resmgr_cfilt_get(&taiko->resmgr, cfilt_sel_val);
Kiran Kandic3b24402012-06-11 00:05:59 -07002691
2692 if (strnstr(w->name, internal1_text, 30))
2693 snd_soc_update_bits(codec, micb_int_reg, 0xE0, 0xE0);
2694 else if (strnstr(w->name, internal2_text, 30))
2695 snd_soc_update_bits(codec, micb_int_reg, 0x1C, 0x1C);
2696 else if (strnstr(w->name, internal3_text, 30))
2697 snd_soc_update_bits(codec, micb_int_reg, 0x3, 0x3);
2698
Joonwoo Parkccccba72013-04-26 11:19:46 -07002699 if (taiko->mbhc_started && micb_ctl_reg == TAIKO_A_MICB_2_CTL) {
2700 if (++taiko->micb_2_users == 1) {
2701 if (taiko->resmgr.pdata->
2702 micbias.bias2_is_headset_only)
2703 wcd9xxx_resmgr_add_cond_update_bits(
2704 &taiko->resmgr,
2705 WCD9XXX_COND_HPH_MIC,
2706 micb_ctl_reg, w->shift,
2707 false);
2708 else
2709 snd_soc_update_bits(codec, micb_ctl_reg,
2710 1 << w->shift,
2711 1 << w->shift);
2712 }
2713 pr_debug("%s: micb_2_users %d\n", __func__,
2714 taiko->micb_2_users);
2715 } else {
Joonwoo Park3699ca32013-02-08 12:06:15 -08002716 snd_soc_update_bits(codec, micb_ctl_reg, 1 << w->shift,
2717 1 << w->shift);
Joonwoo Parkccccba72013-04-26 11:19:46 -07002718 }
Kiran Kandic3b24402012-06-11 00:05:59 -07002719 break;
2720 case SND_SOC_DAPM_POST_PMU:
Kiran Kandic3b24402012-06-11 00:05:59 -07002721 usleep_range(20000, 20000);
Joonwoo Parka8890262012-10-15 12:04:27 -07002722 /* Let MBHC module know so micbias is on */
2723 wcd9xxx_resmgr_notifier_call(&taiko->resmgr, e_post_on);
Kiran Kandic3b24402012-06-11 00:05:59 -07002724 break;
Kiran Kandic3b24402012-06-11 00:05:59 -07002725 case SND_SOC_DAPM_POST_PMD:
Joonwoo Parkccccba72013-04-26 11:19:46 -07002726 if (taiko->mbhc_started && micb_ctl_reg == TAIKO_A_MICB_2_CTL) {
2727 if (--taiko->micb_2_users == 0) {
2728 if (taiko->resmgr.pdata->
2729 micbias.bias2_is_headset_only)
2730 wcd9xxx_resmgr_rm_cond_update_bits(
2731 &taiko->resmgr,
2732 WCD9XXX_COND_HPH_MIC,
2733 micb_ctl_reg, 7, false);
2734 else
2735 snd_soc_update_bits(codec, micb_ctl_reg,
2736 1 << w->shift, 0);
2737 }
2738 pr_debug("%s: micb_2_users %d\n", __func__,
2739 taiko->micb_2_users);
2740 WARN(taiko->micb_2_users < 0,
2741 "Unexpected micbias users %d\n",
2742 taiko->micb_2_users);
2743 } else {
Joonwoo Park3699ca32013-02-08 12:06:15 -08002744 snd_soc_update_bits(codec, micb_ctl_reg, 1 << w->shift,
2745 0);
Joonwoo Parkccccba72013-04-26 11:19:46 -07002746 }
Joonwoo Park3699ca32013-02-08 12:06:15 -08002747
Joonwoo Parka8890262012-10-15 12:04:27 -07002748 /* Let MBHC module know so micbias switch to be off */
2749 wcd9xxx_resmgr_notifier_call(&taiko->resmgr, e_post_off);
Kiran Kandic3b24402012-06-11 00:05:59 -07002750
2751 if (strnstr(w->name, internal1_text, 30))
2752 snd_soc_update_bits(codec, micb_int_reg, 0x80, 0x00);
2753 else if (strnstr(w->name, internal2_text, 30))
2754 snd_soc_update_bits(codec, micb_int_reg, 0x10, 0x00);
2755 else if (strnstr(w->name, internal3_text, 30))
2756 snd_soc_update_bits(codec, micb_int_reg, 0x2, 0x0);
2757
Joonwoo Parka8890262012-10-15 12:04:27 -07002758 /* Put cfilt */
2759 wcd9xxx_resmgr_cfilt_put(&taiko->resmgr, cfilt_sel_val);
Kiran Kandic3b24402012-06-11 00:05:59 -07002760 break;
2761 }
2762
2763 return 0;
2764}
2765
Joonwoo Parkccccba72013-04-26 11:19:46 -07002766/* called under codec_resource_lock acquisition */
2767static int taiko_enable_mbhc_micbias(struct snd_soc_codec *codec, bool enable)
2768{
2769 int rc;
2770
2771 if (enable)
2772 rc = snd_soc_dapm_force_enable_pin(&codec->dapm,
2773 DAPM_MICBIAS2_EXTERNAL_STANDALONE);
2774 else
2775 rc = snd_soc_dapm_disable_pin(&codec->dapm,
2776 DAPM_MICBIAS2_EXTERNAL_STANDALONE);
2777 if (!rc)
2778 snd_soc_dapm_sync(&codec->dapm);
2779 pr_debug("%s: leave ret %d\n", __func__, rc);
2780 return rc;
2781}
Kiran Kandic3b24402012-06-11 00:05:59 -07002782
2783static void tx_hpf_corner_freq_callback(struct work_struct *work)
2784{
2785 struct delayed_work *hpf_delayed_work;
2786 struct hpf_work *hpf_work;
2787 struct taiko_priv *taiko;
2788 struct snd_soc_codec *codec;
2789 u16 tx_mux_ctl_reg;
2790 u8 hpf_cut_of_freq;
2791
2792 hpf_delayed_work = to_delayed_work(work);
2793 hpf_work = container_of(hpf_delayed_work, struct hpf_work, dwork);
2794 taiko = hpf_work->taiko;
2795 codec = hpf_work->taiko->codec;
2796 hpf_cut_of_freq = hpf_work->tx_hpf_cut_of_freq;
2797
2798 tx_mux_ctl_reg = TAIKO_A_CDC_TX1_MUX_CTL +
2799 (hpf_work->decimator - 1) * 8;
2800
2801 pr_debug("%s(): decimator %u hpf_cut_of_freq 0x%x\n", __func__,
2802 hpf_work->decimator, (unsigned int)hpf_cut_of_freq);
2803
2804 snd_soc_update_bits(codec, tx_mux_ctl_reg, 0x30, hpf_cut_of_freq << 4);
2805}
2806
2807#define TX_MUX_CTL_CUT_OFF_FREQ_MASK 0x30
2808#define CF_MIN_3DB_4HZ 0x0
2809#define CF_MIN_3DB_75HZ 0x1
2810#define CF_MIN_3DB_150HZ 0x2
2811
2812static int taiko_codec_enable_dec(struct snd_soc_dapm_widget *w,
2813 struct snd_kcontrol *kcontrol, int event)
2814{
2815 struct snd_soc_codec *codec = w->codec;
2816 unsigned int decimator;
2817 char *dec_name = NULL;
2818 char *widget_name = NULL;
2819 char *temp;
2820 int ret = 0;
2821 u16 dec_reset_reg, tx_vol_ctl_reg, tx_mux_ctl_reg;
2822 u8 dec_hpf_cut_of_freq;
2823 int offset;
2824
2825
2826 pr_debug("%s %d\n", __func__, event);
2827
2828 widget_name = kstrndup(w->name, 15, GFP_KERNEL);
2829 if (!widget_name)
2830 return -ENOMEM;
2831 temp = widget_name;
2832
2833 dec_name = strsep(&widget_name, " ");
2834 widget_name = temp;
2835 if (!dec_name) {
2836 pr_err("%s: Invalid decimator = %s\n", __func__, w->name);
2837 ret = -EINVAL;
2838 goto out;
2839 }
2840
2841 ret = kstrtouint(strpbrk(dec_name, "123456789"), 10, &decimator);
2842 if (ret < 0) {
2843 pr_err("%s: Invalid decimator = %s\n", __func__, dec_name);
2844 ret = -EINVAL;
2845 goto out;
2846 }
2847
2848 pr_debug("%s(): widget = %s dec_name = %s decimator = %u\n", __func__,
2849 w->name, dec_name, decimator);
2850
2851 if (w->reg == TAIKO_A_CDC_CLK_TX_CLK_EN_B1_CTL) {
2852 dec_reset_reg = TAIKO_A_CDC_CLK_TX_RESET_B1_CTL;
2853 offset = 0;
2854 } else if (w->reg == TAIKO_A_CDC_CLK_TX_CLK_EN_B2_CTL) {
2855 dec_reset_reg = TAIKO_A_CDC_CLK_TX_RESET_B2_CTL;
2856 offset = 8;
2857 } else {
2858 pr_err("%s: Error, incorrect dec\n", __func__);
2859 return -EINVAL;
2860 }
2861
2862 tx_vol_ctl_reg = TAIKO_A_CDC_TX1_VOL_CTL_CFG + 8 * (decimator - 1);
2863 tx_mux_ctl_reg = TAIKO_A_CDC_TX1_MUX_CTL + 8 * (decimator - 1);
2864
2865 switch (event) {
2866 case SND_SOC_DAPM_PRE_PMU:
2867
2868 /* Enableable TX digital mute */
2869 snd_soc_update_bits(codec, tx_vol_ctl_reg, 0x01, 0x01);
2870
2871 snd_soc_update_bits(codec, dec_reset_reg, 1 << w->shift,
2872 1 << w->shift);
2873 snd_soc_update_bits(codec, dec_reset_reg, 1 << w->shift, 0x0);
2874
2875 dec_hpf_cut_of_freq = snd_soc_read(codec, tx_mux_ctl_reg);
2876
2877 dec_hpf_cut_of_freq = (dec_hpf_cut_of_freq & 0x30) >> 4;
2878
2879 tx_hpf_work[decimator - 1].tx_hpf_cut_of_freq =
2880 dec_hpf_cut_of_freq;
2881
2882 if ((dec_hpf_cut_of_freq != CF_MIN_3DB_150HZ)) {
2883
2884 /* set cut of freq to CF_MIN_3DB_150HZ (0x1); */
2885 snd_soc_update_bits(codec, tx_mux_ctl_reg, 0x30,
2886 CF_MIN_3DB_150HZ << 4);
2887 }
2888
2889 /* enable HPF */
2890 snd_soc_update_bits(codec, tx_mux_ctl_reg , 0x08, 0x00);
2891
2892 break;
2893
2894 case SND_SOC_DAPM_POST_PMU:
2895
2896 /* Disable TX digital mute */
2897 snd_soc_update_bits(codec, tx_vol_ctl_reg, 0x01, 0x00);
2898
2899 if (tx_hpf_work[decimator - 1].tx_hpf_cut_of_freq !=
2900 CF_MIN_3DB_150HZ) {
2901
2902 schedule_delayed_work(&tx_hpf_work[decimator - 1].dwork,
2903 msecs_to_jiffies(300));
2904 }
2905 /* apply the digital gain after the decimator is enabled*/
Damir Didjustoed406e22012-11-16 15:44:57 -08002906 if ((w->shift + offset) < ARRAY_SIZE(tx_digital_gain_reg))
Kiran Kandic3b24402012-06-11 00:05:59 -07002907 snd_soc_write(codec,
2908 tx_digital_gain_reg[w->shift + offset],
2909 snd_soc_read(codec,
2910 tx_digital_gain_reg[w->shift + offset])
2911 );
2912
2913 break;
2914
2915 case SND_SOC_DAPM_PRE_PMD:
2916
2917 snd_soc_update_bits(codec, tx_vol_ctl_reg, 0x01, 0x01);
2918 cancel_delayed_work_sync(&tx_hpf_work[decimator - 1].dwork);
2919 break;
2920
2921 case SND_SOC_DAPM_POST_PMD:
2922
2923 snd_soc_update_bits(codec, tx_mux_ctl_reg, 0x08, 0x08);
2924 snd_soc_update_bits(codec, tx_mux_ctl_reg, 0x30,
2925 (tx_hpf_work[decimator - 1].tx_hpf_cut_of_freq) << 4);
2926
2927 break;
2928 }
2929out:
2930 kfree(widget_name);
2931 return ret;
2932}
2933
Joonwoo Park125cd4e2012-12-11 15:16:11 -08002934static int taiko_codec_enable_vdd_spkr(struct snd_soc_dapm_widget *w,
2935 struct snd_kcontrol *kcontrol, int event)
2936{
2937 int ret = 0;
2938 struct snd_soc_codec *codec = w->codec;
2939 struct wcd9xxx *core = dev_get_drvdata(codec->dev->parent);
Joonwoo Park448a8fc2013-04-10 15:25:58 -07002940 struct taiko_priv *priv = snd_soc_codec_get_drvdata(codec);
Joonwoo Park125cd4e2012-12-11 15:16:11 -08002941
2942 pr_debug("%s: %d %s\n", __func__, event, w->name);
Joonwoo Park448a8fc2013-04-10 15:25:58 -07002943
2944 WARN_ONCE(!priv->spkdrv_reg, "SPKDRV supply %s isn't defined\n",
2945 WCD9XXX_VDD_SPKDRV_NAME);
Joonwoo Park125cd4e2012-12-11 15:16:11 -08002946 switch (event) {
2947 case SND_SOC_DAPM_PRE_PMU:
Joonwoo Park448a8fc2013-04-10 15:25:58 -07002948 if (priv->spkdrv_reg) {
2949 ret = regulator_enable(priv->spkdrv_reg);
2950 if (ret)
2951 pr_err("%s: Failed to enable spkdrv_reg %s\n",
2952 __func__, WCD9XXX_VDD_SPKDRV_NAME);
2953 }
Joonwoo Park125cd4e2012-12-11 15:16:11 -08002954 if (spkr_drv_wrnd > 0) {
2955 WARN_ON(!(snd_soc_read(codec, TAIKO_A_SPKR_DRV_EN) &
2956 0x80));
2957 snd_soc_update_bits(codec, TAIKO_A_SPKR_DRV_EN, 0x80,
2958 0x00);
2959 }
2960 if (TAIKO_IS_1_0(core->version))
2961 snd_soc_update_bits(codec, TAIKO_A_SPKR_DRV_DBG_PWRSTG,
2962 0x24, 0x00);
2963 break;
2964 case SND_SOC_DAPM_POST_PMD:
2965 if (TAIKO_IS_1_0(core->version))
2966 snd_soc_update_bits(codec, TAIKO_A_SPKR_DRV_DBG_PWRSTG,
2967 0x24, 0x24);
2968 if (spkr_drv_wrnd > 0) {
2969 WARN_ON(!!(snd_soc_read(codec, TAIKO_A_SPKR_DRV_EN) &
2970 0x80));
2971 snd_soc_update_bits(codec, TAIKO_A_SPKR_DRV_EN, 0x80,
2972 0x80);
2973 }
Joonwoo Park448a8fc2013-04-10 15:25:58 -07002974 if (priv->spkdrv_reg) {
2975 ret = regulator_disable(priv->spkdrv_reg);
2976 if (ret)
2977 pr_err("%s: Failed to disable spkdrv_reg %s\n",
2978 __func__, WCD9XXX_VDD_SPKDRV_NAME);
2979 }
Joonwoo Park125cd4e2012-12-11 15:16:11 -08002980 break;
2981 }
2982
2983 return ret;
2984}
2985
Kiran Kandi7b7d2ff2012-09-14 14:52:14 -07002986static int taiko_codec_enable_interpolator(struct snd_soc_dapm_widget *w,
Kiran Kandic3b24402012-06-11 00:05:59 -07002987 struct snd_kcontrol *kcontrol, int event)
2988{
2989 struct snd_soc_codec *codec = w->codec;
2990
2991 pr_debug("%s %d %s\n", __func__, event, w->name);
2992
2993 switch (event) {
2994 case SND_SOC_DAPM_PRE_PMU:
2995 snd_soc_update_bits(codec, TAIKO_A_CDC_CLK_RX_RESET_CTL,
2996 1 << w->shift, 1 << w->shift);
2997 snd_soc_update_bits(codec, TAIKO_A_CDC_CLK_RX_RESET_CTL,
2998 1 << w->shift, 0x0);
2999 break;
3000 case SND_SOC_DAPM_POST_PMU:
3001 /* apply the digital gain after the interpolator is enabled*/
3002 if ((w->shift) < ARRAY_SIZE(rx_digital_gain_reg))
3003 snd_soc_write(codec,
3004 rx_digital_gain_reg[w->shift],
3005 snd_soc_read(codec,
3006 rx_digital_gain_reg[w->shift])
3007 );
3008 break;
3009 }
3010 return 0;
3011}
3012
Joonwoo Parkccccba72013-04-26 11:19:46 -07003013/* called under codec_resource_lock acquisition */
3014static int __taiko_codec_enable_ldo_h(struct snd_soc_dapm_widget *w,
3015 struct snd_kcontrol *kcontrol, int event)
Kiran Kandic3b24402012-06-11 00:05:59 -07003016{
Joonwoo Parkccccba72013-04-26 11:19:46 -07003017 struct snd_soc_codec *codec = w->codec;
3018 struct taiko_priv *priv = snd_soc_codec_get_drvdata(codec);
3019
3020 pr_debug("%s: enter\n", __func__);
Kiran Kandic3b24402012-06-11 00:05:59 -07003021 switch (event) {
Joonwoo Parkccccba72013-04-26 11:19:46 -07003022 case SND_SOC_DAPM_PRE_PMU:
Joonwoo Park533b3682013-06-13 11:41:21 -07003023 /*
3024 * ldo_h_users is protected by codec->mutex, don't need
3025 * additional mutex
3026 */
Joonwoo Parkccccba72013-04-26 11:19:46 -07003027 if (++priv->ldo_h_users == 1) {
Joonwoo Park533b3682013-06-13 11:41:21 -07003028 WCD9XXX_BG_CLK_LOCK(&priv->resmgr);
Joonwoo Parkccccba72013-04-26 11:19:46 -07003029 wcd9xxx_resmgr_get_bandgap(&priv->resmgr,
3030 WCD9XXX_BANDGAP_AUDIO_MODE);
3031 wcd9xxx_resmgr_get_clk_block(&priv->resmgr,
3032 WCD9XXX_CLK_RCO);
3033 snd_soc_update_bits(codec, TAIKO_A_LDO_H_MODE_1, 1 << 7,
3034 1 << 7);
3035 wcd9xxx_resmgr_put_clk_block(&priv->resmgr,
3036 WCD9XXX_CLK_RCO);
Joonwoo Park533b3682013-06-13 11:41:21 -07003037 WCD9XXX_BG_CLK_UNLOCK(&priv->resmgr);
Joonwoo Parkccccba72013-04-26 11:19:46 -07003038 pr_debug("%s: ldo_h_users %d\n", __func__,
3039 priv->ldo_h_users);
3040 /* LDO enable requires 1ms to settle down */
3041 usleep_range(1000, 1000);
3042 }
3043 break;
Kiran Kandic3b24402012-06-11 00:05:59 -07003044 case SND_SOC_DAPM_POST_PMD:
Joonwoo Parkccccba72013-04-26 11:19:46 -07003045 if (--priv->ldo_h_users == 0) {
Joonwoo Park533b3682013-06-13 11:41:21 -07003046 WCD9XXX_BG_CLK_LOCK(&priv->resmgr);
Joonwoo Parkccccba72013-04-26 11:19:46 -07003047 wcd9xxx_resmgr_get_clk_block(&priv->resmgr,
3048 WCD9XXX_CLK_RCO);
3049 snd_soc_update_bits(codec, TAIKO_A_LDO_H_MODE_1, 1 << 7,
3050 0);
3051 wcd9xxx_resmgr_put_clk_block(&priv->resmgr,
3052 WCD9XXX_CLK_RCO);
3053 wcd9xxx_resmgr_put_bandgap(&priv->resmgr,
3054 WCD9XXX_BANDGAP_AUDIO_MODE);
Joonwoo Park533b3682013-06-13 11:41:21 -07003055 WCD9XXX_BG_CLK_UNLOCK(&priv->resmgr);
Joonwoo Parkccccba72013-04-26 11:19:46 -07003056 pr_debug("%s: ldo_h_users %d\n", __func__,
3057 priv->ldo_h_users);
3058 }
3059 WARN(priv->ldo_h_users < 0, "Unexpected ldo_h users %d\n",
3060 priv->ldo_h_users);
Kiran Kandic3b24402012-06-11 00:05:59 -07003061 break;
3062 }
Joonwoo Parkccccba72013-04-26 11:19:46 -07003063 pr_debug("%s: leave\n", __func__);
Kiran Kandic3b24402012-06-11 00:05:59 -07003064 return 0;
3065}
3066
Joonwoo Parkccccba72013-04-26 11:19:46 -07003067static int taiko_codec_enable_ldo_h(struct snd_soc_dapm_widget *w,
3068 struct snd_kcontrol *kcontrol, int event)
3069{
3070 int rc;
Joonwoo Parkccccba72013-04-26 11:19:46 -07003071 rc = __taiko_codec_enable_ldo_h(w, kcontrol, event);
Joonwoo Parkccccba72013-04-26 11:19:46 -07003072 return rc;
3073}
3074
Kiran Kandic3b24402012-06-11 00:05:59 -07003075static int taiko_codec_enable_rx_bias(struct snd_soc_dapm_widget *w,
3076 struct snd_kcontrol *kcontrol, int event)
3077{
3078 struct snd_soc_codec *codec = w->codec;
Joonwoo Parka8890262012-10-15 12:04:27 -07003079 struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
Kiran Kandic3b24402012-06-11 00:05:59 -07003080
3081 pr_debug("%s %d\n", __func__, event);
3082
3083 switch (event) {
3084 case SND_SOC_DAPM_PRE_PMU:
Joonwoo Parka8890262012-10-15 12:04:27 -07003085 wcd9xxx_resmgr_enable_rx_bias(&taiko->resmgr, 1);
Kiran Kandic3b24402012-06-11 00:05:59 -07003086 break;
3087 case SND_SOC_DAPM_POST_PMD:
Joonwoo Parka8890262012-10-15 12:04:27 -07003088 wcd9xxx_resmgr_enable_rx_bias(&taiko->resmgr, 0);
Kiran Kandic3b24402012-06-11 00:05:59 -07003089 break;
3090 }
3091 return 0;
3092}
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08003093
3094static int taiko_hphl_dac_event(struct snd_soc_dapm_widget *w,
Kiran Kandic3b24402012-06-11 00:05:59 -07003095 struct snd_kcontrol *kcontrol, int event)
3096{
3097 struct snd_soc_codec *codec = w->codec;
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08003098 struct taiko_priv *taiko_p = snd_soc_codec_get_drvdata(codec);
Santosh Mardi93a69192013-07-03 23:37:29 +05303099 uint32_t impedl, impedr;
3100 int ret = 0;
Kiran Kandic3b24402012-06-11 00:05:59 -07003101
3102 pr_debug("%s %s %d\n", __func__, w->name, event);
3103
3104 switch (event) {
3105 case SND_SOC_DAPM_PRE_PMU:
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08003106 snd_soc_update_bits(codec, TAIKO_A_CDC_CLK_RDAC_CLK_EN_CTL,
3107 0x02, 0x02);
3108 wcd9xxx_clsh_fsm(codec, &taiko_p->clsh_d,
3109 WCD9XXX_CLSH_STATE_HPHL,
3110 WCD9XXX_CLSH_REQ_ENABLE,
3111 WCD9XXX_CLSH_EVENT_PRE_DAC);
Santosh Mardi93a69192013-07-03 23:37:29 +05303112 ret = wcd9xxx_mbhc_get_impedance(&taiko_p->mbhc,
3113 &impedl, &impedr);
3114 if (!ret)
3115 wcd9xxx_clsh_imped_config(codec, impedl);
3116 else
3117 dev_err(codec->dev, "Failed to get mbhc impedance %d\n",
3118 ret);
Kiran Kandic3b24402012-06-11 00:05:59 -07003119 break;
3120 case SND_SOC_DAPM_POST_PMD:
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08003121 snd_soc_update_bits(codec, TAIKO_A_CDC_CLK_RDAC_CLK_EN_CTL,
3122 0x02, 0x00);
3123 }
3124 return 0;
3125}
3126
3127static int taiko_hphr_dac_event(struct snd_soc_dapm_widget *w,
3128 struct snd_kcontrol *kcontrol, int event)
3129{
3130 struct snd_soc_codec *codec = w->codec;
3131 struct taiko_priv *taiko_p = snd_soc_codec_get_drvdata(codec);
3132
3133 pr_debug("%s %s %d\n", __func__, w->name, event);
3134
3135 switch (event) {
3136 case SND_SOC_DAPM_PRE_PMU:
3137 snd_soc_update_bits(codec, TAIKO_A_CDC_CLK_RDAC_CLK_EN_CTL,
3138 0x04, 0x04);
3139 snd_soc_update_bits(codec, w->reg, 0x40, 0x40);
3140 wcd9xxx_clsh_fsm(codec, &taiko_p->clsh_d,
3141 WCD9XXX_CLSH_STATE_HPHR,
3142 WCD9XXX_CLSH_REQ_ENABLE,
3143 WCD9XXX_CLSH_EVENT_PRE_DAC);
3144 break;
3145 case SND_SOC_DAPM_POST_PMD:
3146 snd_soc_update_bits(codec, TAIKO_A_CDC_CLK_RDAC_CLK_EN_CTL,
3147 0x04, 0x00);
Kiran Kandic3b24402012-06-11 00:05:59 -07003148 snd_soc_update_bits(codec, w->reg, 0x40, 0x00);
3149 break;
3150 }
3151 return 0;
3152}
3153
Damir Didjusto2cb06bd2013-01-30 23:14:55 -08003154static int taiko_codec_enable_anc(struct snd_soc_dapm_widget *w,
3155 struct snd_kcontrol *kcontrol, int event)
3156{
3157 struct snd_soc_codec *codec = w->codec;
3158 const char *filename;
3159 const struct firmware *fw;
3160 int i;
3161 int ret;
3162 int num_anc_slots;
Simmi Pateriyadf675e92013-04-05 01:15:54 +05303163 struct wcd9xxx_anc_header *anc_head;
Damir Didjusto2cb06bd2013-01-30 23:14:55 -08003164 struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
3165 u32 anc_writes_size = 0;
3166 int anc_size_remaining;
3167 u32 *anc_ptr;
3168 u16 reg;
3169 u8 mask, val, old_val;
3170
3171
3172 if (taiko->anc_func == 0)
3173 return 0;
3174
3175 switch (event) {
3176 case SND_SOC_DAPM_PRE_PMU:
3177 filename = "wcd9320/wcd9320_anc.bin";
3178
3179 ret = request_firmware(&fw, filename, codec->dev);
3180 if (ret != 0) {
3181 dev_err(codec->dev, "Failed to acquire ANC data: %d\n",
3182 ret);
3183 return -ENODEV;
3184 }
3185
Simmi Pateriyadf675e92013-04-05 01:15:54 +05303186 if (fw->size < sizeof(struct wcd9xxx_anc_header)) {
Damir Didjusto2cb06bd2013-01-30 23:14:55 -08003187 dev_err(codec->dev, "Not enough data\n");
3188 release_firmware(fw);
3189 return -ENOMEM;
3190 }
3191
3192 /* First number is the number of register writes */
Simmi Pateriyadf675e92013-04-05 01:15:54 +05303193 anc_head = (struct wcd9xxx_anc_header *)(fw->data);
3194 anc_ptr = (u32 *)((u32)fw->data +
3195 sizeof(struct wcd9xxx_anc_header));
3196 anc_size_remaining = fw->size -
3197 sizeof(struct wcd9xxx_anc_header);
Damir Didjusto2cb06bd2013-01-30 23:14:55 -08003198 num_anc_slots = anc_head->num_anc_slots;
3199
3200 if (taiko->anc_slot >= num_anc_slots) {
3201 dev_err(codec->dev, "Invalid ANC slot selected\n");
3202 release_firmware(fw);
3203 return -EINVAL;
3204 }
3205 for (i = 0; i < num_anc_slots; i++) {
3206 if (anc_size_remaining < TAIKO_PACKED_REG_SIZE) {
3207 dev_err(codec->dev, "Invalid register format\n");
3208 release_firmware(fw);
3209 return -EINVAL;
3210 }
3211 anc_writes_size = (u32)(*anc_ptr);
3212 anc_size_remaining -= sizeof(u32);
3213 anc_ptr += 1;
3214
3215 if (anc_writes_size * TAIKO_PACKED_REG_SIZE
3216 > anc_size_remaining) {
3217 dev_err(codec->dev, "Invalid register format\n");
3218 release_firmware(fw);
3219 return -ENOMEM;
3220 }
3221
3222 if (taiko->anc_slot == i)
3223 break;
3224
3225 anc_size_remaining -= (anc_writes_size *
3226 TAIKO_PACKED_REG_SIZE);
3227 anc_ptr += anc_writes_size;
3228 }
3229 if (i == num_anc_slots) {
3230 dev_err(codec->dev, "Selected ANC slot not present\n");
3231 release_firmware(fw);
3232 return -ENOMEM;
3233 }
3234 for (i = 0; i < anc_writes_size; i++) {
3235 TAIKO_CODEC_UNPACK_ENTRY(anc_ptr[i], reg,
3236 mask, val);
3237 old_val = snd_soc_read(codec, reg);
3238 snd_soc_write(codec, reg, (old_val & ~mask) |
3239 (val & mask));
3240 }
3241 release_firmware(fw);
3242 break;
Damir Didjustoaf0085c2013-05-02 17:47:45 -07003243 case SND_SOC_DAPM_PRE_PMD:
Damir Didjusto2cb06bd2013-01-30 23:14:55 -08003244 msleep(40);
3245 snd_soc_update_bits(codec, TAIKO_A_CDC_ANC1_B1_CTL, 0x01, 0x00);
3246 snd_soc_update_bits(codec, TAIKO_A_CDC_ANC2_B1_CTL, 0x02, 0x00);
3247 msleep(20);
3248 snd_soc_write(codec, TAIKO_A_CDC_CLK_ANC_RESET_CTL, 0x0F);
3249 snd_soc_write(codec, TAIKO_A_CDC_CLK_ANC_CLK_EN_CTL, 0);
3250 snd_soc_write(codec, TAIKO_A_CDC_CLK_ANC_RESET_CTL, 0xFF);
3251 break;
3252 }
3253 return 0;
3254}
3255
Kiran Kandic3b24402012-06-11 00:05:59 -07003256static int taiko_hph_pa_event(struct snd_soc_dapm_widget *w,
Joonwoo Parka8890262012-10-15 12:04:27 -07003257 struct snd_kcontrol *kcontrol, int event)
Kiran Kandic3b24402012-06-11 00:05:59 -07003258{
3259 struct snd_soc_codec *codec = w->codec;
3260 struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
Joonwoo Parka8890262012-10-15 12:04:27 -07003261 enum wcd9xxx_notify_event e_pre_on, e_post_off;
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08003262 u8 req_clsh_state;
Bhalchandra Gajareef7810e2013-03-29 16:50:37 -07003263 u32 pa_settle_time = TAIKO_HPH_PA_SETTLE_COMP_OFF;
Joonwoo Parka8890262012-10-15 12:04:27 -07003264
Kiran Kandi4c56c592012-07-25 11:04:55 -07003265 pr_debug("%s: %s event = %d\n", __func__, w->name, event);
Joonwoo Parka8890262012-10-15 12:04:27 -07003266 if (w->shift == 5) {
Joonwoo Parka8890262012-10-15 12:04:27 -07003267 e_pre_on = WCD9XXX_EVENT_PRE_HPHL_PA_ON;
3268 e_post_off = WCD9XXX_EVENT_POST_HPHL_PA_OFF;
Patrick Lai453cd742013-03-02 16:51:27 -08003269 req_clsh_state = WCD9XXX_CLSH_STATE_HPHL;
3270 } else if (w->shift == 4) {
3271 e_pre_on = WCD9XXX_EVENT_PRE_HPHR_PA_ON;
3272 e_post_off = WCD9XXX_EVENT_POST_HPHR_PA_OFF;
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08003273 req_clsh_state = WCD9XXX_CLSH_STATE_HPHR;
Joonwoo Parka8890262012-10-15 12:04:27 -07003274 } else {
3275 pr_err("%s: Invalid w->shift %d\n", __func__, w->shift);
3276 return -EINVAL;
3277 }
Kiran Kandic3b24402012-06-11 00:05:59 -07003278
Bhalchandra Gajareef7810e2013-03-29 16:50:37 -07003279 if (taiko->comp_enabled[COMPANDER_1])
3280 pa_settle_time = TAIKO_HPH_PA_SETTLE_COMP_ON;
3281
Kiran Kandic3b24402012-06-11 00:05:59 -07003282 switch (event) {
3283 case SND_SOC_DAPM_PRE_PMU:
Joonwoo Parka8890262012-10-15 12:04:27 -07003284 /* Let MBHC module know PA is turning on */
3285 wcd9xxx_resmgr_notifier_call(&taiko->resmgr, e_pre_on);
Kiran Kandic3b24402012-06-11 00:05:59 -07003286 break;
3287
Kiran Kandi4c56c592012-07-25 11:04:55 -07003288 case SND_SOC_DAPM_POST_PMU:
Bhalchandra Gajareef7810e2013-03-29 16:50:37 -07003289 usleep_range(pa_settle_time, pa_settle_time + 1000);
3290 pr_debug("%s: sleep %d us after %s PA enable\n", __func__,
3291 pa_settle_time, w->name);
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08003292 wcd9xxx_clsh_fsm(codec, &taiko->clsh_d,
3293 req_clsh_state,
3294 WCD9XXX_CLSH_REQ_ENABLE,
3295 WCD9XXX_CLSH_EVENT_POST_PA);
Kiran Kandi4c56c592012-07-25 11:04:55 -07003296
Kiran Kandi4c56c592012-07-25 11:04:55 -07003297 break;
3298
Kiran Kandic3b24402012-06-11 00:05:59 -07003299 case SND_SOC_DAPM_POST_PMD:
Bhalchandra Gajareef7810e2013-03-29 16:50:37 -07003300 usleep_range(pa_settle_time, pa_settle_time + 1000);
3301 pr_debug("%s: sleep %d us after %s PA disable\n", __func__,
3302 pa_settle_time, w->name);
3303
Joonwoo Parka8890262012-10-15 12:04:27 -07003304 /* Let MBHC module know PA turned off */
3305 wcd9xxx_resmgr_notifier_call(&taiko->resmgr, e_post_off);
3306
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08003307 wcd9xxx_clsh_fsm(codec, &taiko->clsh_d,
3308 req_clsh_state,
3309 WCD9XXX_CLSH_REQ_DISABLE,
3310 WCD9XXX_CLSH_EVENT_POST_PA);
3311
Kiran Kandic3b24402012-06-11 00:05:59 -07003312 break;
3313 }
3314 return 0;
3315}
3316
Damir Didjusto2cb06bd2013-01-30 23:14:55 -08003317static int taiko_codec_enable_anc_hph(struct snd_soc_dapm_widget *w,
3318 struct snd_kcontrol *kcontrol, int event)
3319{
3320 struct snd_soc_codec *codec = w->codec;
3321 int ret = 0;
3322
3323 switch (event) {
3324 case SND_SOC_DAPM_PRE_PMU:
3325 ret = taiko_hph_pa_event(w, kcontrol, event);
3326 if (w->shift == 4) {
3327 ret |= taiko_codec_enable_anc(w, kcontrol, event);
3328 msleep(50);
3329 }
3330 break;
3331 case SND_SOC_DAPM_POST_PMU:
3332 if (w->shift == 4) {
3333 snd_soc_update_bits(codec,
3334 TAIKO_A_RX_HPH_CNP_EN, 0x30, 0x30);
3335 msleep(30);
3336 }
3337 ret = taiko_hph_pa_event(w, kcontrol, event);
3338 break;
3339 case SND_SOC_DAPM_PRE_PMD:
3340 if (w->shift == 5) {
3341 snd_soc_update_bits(codec,
3342 TAIKO_A_RX_HPH_CNP_EN, 0x30, 0x00);
3343 msleep(40);
Damir Didjusto2cb06bd2013-01-30 23:14:55 -08003344 snd_soc_update_bits(codec,
3345 TAIKO_A_TX_7_MBHC_EN, 0x80, 00);
3346 ret |= taiko_codec_enable_anc(w, kcontrol, event);
3347 }
3348 case SND_SOC_DAPM_POST_PMD:
3349 ret = taiko_hph_pa_event(w, kcontrol, event);
3350 break;
3351 }
3352 return ret;
3353}
3354
Kiran Kandic3b24402012-06-11 00:05:59 -07003355static const struct snd_soc_dapm_widget taiko_dapm_i2s_widgets[] = {
3356 SND_SOC_DAPM_SUPPLY("RX_I2S_CLK", TAIKO_A_CDC_CLK_RX_I2S_CTL,
3357 4, 0, NULL, 0),
3358 SND_SOC_DAPM_SUPPLY("TX_I2S_CLK", TAIKO_A_CDC_CLK_TX_I2S_CTL, 4,
3359 0, NULL, 0),
3360};
3361
3362static int taiko_lineout_dac_event(struct snd_soc_dapm_widget *w,
3363 struct snd_kcontrol *kcontrol, int event)
3364{
3365 struct snd_soc_codec *codec = w->codec;
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08003366 struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
Kiran Kandic3b24402012-06-11 00:05:59 -07003367
3368 pr_debug("%s %s %d\n", __func__, w->name, event);
3369
3370 switch (event) {
3371 case SND_SOC_DAPM_PRE_PMU:
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08003372 wcd9xxx_clsh_fsm(codec, &taiko->clsh_d,
3373 WCD9XXX_CLSH_STATE_LO,
3374 WCD9XXX_CLSH_REQ_ENABLE,
3375 WCD9XXX_CLSH_EVENT_PRE_DAC);
Kiran Kandic3b24402012-06-11 00:05:59 -07003376 snd_soc_update_bits(codec, w->reg, 0x40, 0x40);
3377 break;
3378
3379 case SND_SOC_DAPM_POST_PMD:
3380 snd_soc_update_bits(codec, w->reg, 0x40, 0x00);
3381 break;
3382 }
3383 return 0;
3384}
3385
Joonwoo Park7680b9f2012-07-13 11:36:48 -07003386static int taiko_spk_dac_event(struct snd_soc_dapm_widget *w,
3387 struct snd_kcontrol *kcontrol, int event)
3388{
3389 pr_debug("%s %s %d\n", __func__, w->name, event);
3390 return 0;
3391}
3392
Kiran Kandic3b24402012-06-11 00:05:59 -07003393static const struct snd_soc_dapm_route audio_i2s_map[] = {
Kiran Kandic3b24402012-06-11 00:05:59 -07003394 {"SLIM RX1", NULL, "RX_I2S_CLK"},
3395 {"SLIM RX2", NULL, "RX_I2S_CLK"},
3396 {"SLIM RX3", NULL, "RX_I2S_CLK"},
3397 {"SLIM RX4", NULL, "RX_I2S_CLK"},
3398
Venkat Sudhira41630a2012-10-27 00:57:31 -07003399 {"SLIM TX7 MUX", NULL, "TX_I2S_CLK"},
3400 {"SLIM TX8 MUX", NULL, "TX_I2S_CLK"},
3401 {"SLIM TX9 MUX", NULL, "TX_I2S_CLK"},
3402 {"SLIM TX10 MUX", NULL, "TX_I2S_CLK"},
Kiran Kandic3b24402012-06-11 00:05:59 -07003403};
3404
Joonwoo Park559a5bf2013-02-15 14:46:36 -08003405static const struct snd_soc_dapm_route audio_i2s_map_1_0[] = {
3406 {"RX_I2S_CLK", NULL, "CDC_CONN"},
3407};
3408
3409static const struct snd_soc_dapm_route audio_i2s_map_2_0[] = {
3410 {"RX_I2S_CLK", NULL, "CDC_I2S_RX_CONN"},
3411};
3412
Kiran Kandic3b24402012-06-11 00:05:59 -07003413static const struct snd_soc_dapm_route audio_map[] = {
3414 /* SLIMBUS Connections */
Kuirong Wang906ac472012-07-09 12:54:44 -07003415 {"AIF1 CAP", NULL, "AIF1_CAP Mixer"},
3416 {"AIF2 CAP", NULL, "AIF2_CAP Mixer"},
3417 {"AIF3 CAP", NULL, "AIF3_CAP Mixer"},
Gopikrishnaiah Anandana2627572013-02-26 13:30:50 -05003418 {"AIF4 VI", NULL, "SPK_OUT"},
Kiran Kandic3b24402012-06-11 00:05:59 -07003419
Joonwoo Park1d05bb92013-03-07 16:55:06 -08003420 /* MAD */
3421 {"AIF4 MAD", NULL, "CDC_CONN"},
Joonwoo Park9ead0e92013-03-18 11:33:33 -07003422 {"MADONOFF", "Switch", "MADINPUT"},
3423 {"AIF4 MAD", NULL, "MADONOFF"},
Joonwoo Park1d05bb92013-03-07 16:55:06 -08003424
Kuirong Wang906ac472012-07-09 12:54:44 -07003425 /* SLIM_MIXER("AIF1_CAP Mixer"),*/
3426 {"AIF1_CAP Mixer", "SLIM TX1", "SLIM TX1 MUX"},
3427 {"AIF1_CAP Mixer", "SLIM TX2", "SLIM TX2 MUX"},
3428 {"AIF1_CAP Mixer", "SLIM TX3", "SLIM TX3 MUX"},
3429 {"AIF1_CAP Mixer", "SLIM TX4", "SLIM TX4 MUX"},
3430 {"AIF1_CAP Mixer", "SLIM TX5", "SLIM TX5 MUX"},
3431 {"AIF1_CAP Mixer", "SLIM TX6", "SLIM TX6 MUX"},
3432 {"AIF1_CAP Mixer", "SLIM TX7", "SLIM TX7 MUX"},
3433 {"AIF1_CAP Mixer", "SLIM TX8", "SLIM TX8 MUX"},
3434 {"AIF1_CAP Mixer", "SLIM TX9", "SLIM TX9 MUX"},
3435 {"AIF1_CAP Mixer", "SLIM TX10", "SLIM TX10 MUX"},
3436 /* SLIM_MIXER("AIF2_CAP Mixer"),*/
3437 {"AIF2_CAP Mixer", "SLIM TX1", "SLIM TX1 MUX"},
3438 {"AIF2_CAP Mixer", "SLIM TX2", "SLIM TX2 MUX"},
3439 {"AIF2_CAP Mixer", "SLIM TX3", "SLIM TX3 MUX"},
3440 {"AIF2_CAP Mixer", "SLIM TX4", "SLIM TX4 MUX"},
3441 {"AIF2_CAP Mixer", "SLIM TX5", "SLIM TX5 MUX"},
3442 {"AIF2_CAP Mixer", "SLIM TX6", "SLIM TX6 MUX"},
3443 {"AIF2_CAP Mixer", "SLIM TX7", "SLIM TX7 MUX"},
3444 {"AIF2_CAP Mixer", "SLIM TX8", "SLIM TX8 MUX"},
3445 {"AIF2_CAP Mixer", "SLIM TX9", "SLIM TX9 MUX"},
3446 {"AIF2_CAP Mixer", "SLIM TX10", "SLIM TX10 MUX"},
3447 /* SLIM_MIXER("AIF3_CAP Mixer"),*/
3448 {"AIF3_CAP Mixer", "SLIM TX1", "SLIM TX1 MUX"},
3449 {"AIF3_CAP Mixer", "SLIM TX2", "SLIM TX2 MUX"},
3450 {"AIF3_CAP Mixer", "SLIM TX3", "SLIM TX3 MUX"},
3451 {"AIF3_CAP Mixer", "SLIM TX4", "SLIM TX4 MUX"},
3452 {"AIF3_CAP Mixer", "SLIM TX5", "SLIM TX5 MUX"},
3453 {"AIF3_CAP Mixer", "SLIM TX6", "SLIM TX6 MUX"},
3454 {"AIF3_CAP Mixer", "SLIM TX7", "SLIM TX7 MUX"},
3455 {"AIF3_CAP Mixer", "SLIM TX8", "SLIM TX8 MUX"},
3456 {"AIF3_CAP Mixer", "SLIM TX9", "SLIM TX9 MUX"},
3457 {"AIF3_CAP Mixer", "SLIM TX10", "SLIM TX10 MUX"},
3458
Kiran Kandic3b24402012-06-11 00:05:59 -07003459 {"SLIM TX1 MUX", "DEC1", "DEC1 MUX"},
3460
Kiran Kandic3b24402012-06-11 00:05:59 -07003461 {"SLIM TX2 MUX", "DEC2", "DEC2 MUX"},
3462
Kiran Kandic3b24402012-06-11 00:05:59 -07003463 {"SLIM TX3 MUX", "DEC3", "DEC3 MUX"},
3464 {"SLIM TX3 MUX", "RMIX1", "RX1 MIX1"},
3465 {"SLIM TX3 MUX", "RMIX2", "RX2 MIX1"},
3466 {"SLIM TX3 MUX", "RMIX3", "RX3 MIX1"},
3467 {"SLIM TX3 MUX", "RMIX4", "RX4 MIX1"},
3468 {"SLIM TX3 MUX", "RMIX5", "RX5 MIX1"},
3469 {"SLIM TX3 MUX", "RMIX6", "RX6 MIX1"},
3470 {"SLIM TX3 MUX", "RMIX7", "RX7 MIX1"},
3471
Kiran Kandic3b24402012-06-11 00:05:59 -07003472 {"SLIM TX4 MUX", "DEC4", "DEC4 MUX"},
3473
Kiran Kandic3b24402012-06-11 00:05:59 -07003474 {"SLIM TX5 MUX", "DEC5", "DEC5 MUX"},
3475 {"SLIM TX5 MUX", "RMIX1", "RX1 MIX1"},
3476 {"SLIM TX5 MUX", "RMIX2", "RX2 MIX1"},
3477 {"SLIM TX5 MUX", "RMIX3", "RX3 MIX1"},
3478 {"SLIM TX5 MUX", "RMIX4", "RX4 MIX1"},
3479 {"SLIM TX5 MUX", "RMIX5", "RX5 MIX1"},
3480 {"SLIM TX5 MUX", "RMIX6", "RX6 MIX1"},
3481 {"SLIM TX5 MUX", "RMIX7", "RX7 MIX1"},
3482
Kiran Kandic3b24402012-06-11 00:05:59 -07003483 {"SLIM TX6 MUX", "DEC6", "DEC6 MUX"},
3484
Kiran Kandic3b24402012-06-11 00:05:59 -07003485 {"SLIM TX7 MUX", "DEC1", "DEC1 MUX"},
3486 {"SLIM TX7 MUX", "DEC2", "DEC2 MUX"},
3487 {"SLIM TX7 MUX", "DEC3", "DEC3 MUX"},
3488 {"SLIM TX7 MUX", "DEC4", "DEC4 MUX"},
3489 {"SLIM TX7 MUX", "DEC5", "DEC5 MUX"},
3490 {"SLIM TX7 MUX", "DEC6", "DEC6 MUX"},
3491 {"SLIM TX7 MUX", "DEC7", "DEC7 MUX"},
3492 {"SLIM TX7 MUX", "DEC8", "DEC8 MUX"},
3493 {"SLIM TX7 MUX", "DEC9", "DEC9 MUX"},
3494 {"SLIM TX7 MUX", "DEC10", "DEC10 MUX"},
3495 {"SLIM TX7 MUX", "RMIX1", "RX1 MIX1"},
3496 {"SLIM TX7 MUX", "RMIX2", "RX2 MIX1"},
3497 {"SLIM TX7 MUX", "RMIX3", "RX3 MIX1"},
3498 {"SLIM TX7 MUX", "RMIX4", "RX4 MIX1"},
3499 {"SLIM TX7 MUX", "RMIX5", "RX5 MIX1"},
3500 {"SLIM TX7 MUX", "RMIX6", "RX6 MIX1"},
3501 {"SLIM TX7 MUX", "RMIX7", "RX7 MIX1"},
3502
Kiran Kandic3b24402012-06-11 00:05:59 -07003503 {"SLIM TX8 MUX", "DEC1", "DEC1 MUX"},
3504 {"SLIM TX8 MUX", "DEC2", "DEC2 MUX"},
3505 {"SLIM TX8 MUX", "DEC3", "DEC3 MUX"},
3506 {"SLIM TX8 MUX", "DEC4", "DEC4 MUX"},
3507 {"SLIM TX8 MUX", "DEC5", "DEC5 MUX"},
3508 {"SLIM TX8 MUX", "DEC6", "DEC6 MUX"},
3509 {"SLIM TX8 MUX", "DEC7", "DEC7 MUX"},
3510 {"SLIM TX8 MUX", "DEC8", "DEC8 MUX"},
3511 {"SLIM TX8 MUX", "DEC9", "DEC9 MUX"},
3512 {"SLIM TX8 MUX", "DEC10", "DEC10 MUX"},
3513
Kiran Kandic3b24402012-06-11 00:05:59 -07003514 {"SLIM TX9 MUX", "DEC1", "DEC1 MUX"},
3515 {"SLIM TX9 MUX", "DEC2", "DEC2 MUX"},
3516 {"SLIM TX9 MUX", "DEC3", "DEC3 MUX"},
3517 {"SLIM TX9 MUX", "DEC4", "DEC4 MUX"},
3518 {"SLIM TX9 MUX", "DEC5", "DEC5 MUX"},
3519 {"SLIM TX9 MUX", "DEC6", "DEC6 MUX"},
3520 {"SLIM TX9 MUX", "DEC7", "DEC7 MUX"},
3521 {"SLIM TX9 MUX", "DEC8", "DEC8 MUX"},
3522 {"SLIM TX9 MUX", "DEC9", "DEC9 MUX"},
3523 {"SLIM TX9 MUX", "DEC10", "DEC10 MUX"},
3524
Kiran Kandic3b24402012-06-11 00:05:59 -07003525 {"SLIM TX10 MUX", "DEC1", "DEC1 MUX"},
3526 {"SLIM TX10 MUX", "DEC2", "DEC2 MUX"},
3527 {"SLIM TX10 MUX", "DEC3", "DEC3 MUX"},
3528 {"SLIM TX10 MUX", "DEC4", "DEC4 MUX"},
3529 {"SLIM TX10 MUX", "DEC5", "DEC5 MUX"},
3530 {"SLIM TX10 MUX", "DEC6", "DEC6 MUX"},
3531 {"SLIM TX10 MUX", "DEC7", "DEC7 MUX"},
3532 {"SLIM TX10 MUX", "DEC8", "DEC8 MUX"},
3533 {"SLIM TX10 MUX", "DEC9", "DEC9 MUX"},
3534 {"SLIM TX10 MUX", "DEC10", "DEC10 MUX"},
3535
3536 /* Earpiece (RX MIX1) */
3537 {"EAR", NULL, "EAR PA"},
3538 {"EAR PA", NULL, "EAR_PA_MIXER"},
3539 {"EAR_PA_MIXER", NULL, "DAC1"},
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08003540 {"DAC1", NULL, "RX_BIAS"},
Kiran Kandic3b24402012-06-11 00:05:59 -07003541
Damir Didjusto2cb06bd2013-01-30 23:14:55 -08003542 {"ANC EAR", NULL, "ANC EAR PA"},
3543 {"ANC EAR PA", NULL, "EAR_PA_MIXER"},
Kiran Kandic3b24402012-06-11 00:05:59 -07003544 {"ANC1 FB MUX", "EAR_HPH_L", "RX1 MIX2"},
3545 {"ANC1 FB MUX", "EAR_LINE_1", "RX2 MIX2"},
Kiran Kandic3b24402012-06-11 00:05:59 -07003546
3547 /* Headset (RX MIX1 and RX MIX2) */
3548 {"HEADPHONE", NULL, "HPHL"},
3549 {"HEADPHONE", NULL, "HPHR"},
3550
3551 {"HPHL", NULL, "HPHL_PA_MIXER"},
3552 {"HPHL_PA_MIXER", NULL, "HPHL DAC"},
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08003553 {"HPHL DAC", NULL, "RX_BIAS"},
Kiran Kandic3b24402012-06-11 00:05:59 -07003554
3555 {"HPHR", NULL, "HPHR_PA_MIXER"},
3556 {"HPHR_PA_MIXER", NULL, "HPHR DAC"},
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08003557 {"HPHR DAC", NULL, "RX_BIAS"},
Kiran Kandic3b24402012-06-11 00:05:59 -07003558
Damir Didjusto2cb06bd2013-01-30 23:14:55 -08003559 {"ANC HEADPHONE", NULL, "ANC HPHL"},
3560 {"ANC HEADPHONE", NULL, "ANC HPHR"},
3561
3562 {"ANC HPHL", NULL, "HPHL_PA_MIXER"},
3563 {"ANC HPHR", NULL, "HPHR_PA_MIXER"},
3564
Kiran Kandic3b24402012-06-11 00:05:59 -07003565 {"ANC1 MUX", "ADC1", "ADC1"},
3566 {"ANC1 MUX", "ADC2", "ADC2"},
3567 {"ANC1 MUX", "ADC3", "ADC3"},
3568 {"ANC1 MUX", "ADC4", "ADC4"},
Damir Didjusto2cb06bd2013-01-30 23:14:55 -08003569 {"ANC1 MUX", "DMIC1", "DMIC1"},
3570 {"ANC1 MUX", "DMIC2", "DMIC2"},
3571 {"ANC1 MUX", "DMIC3", "DMIC3"},
3572 {"ANC1 MUX", "DMIC4", "DMIC4"},
3573 {"ANC1 MUX", "DMIC5", "DMIC5"},
3574 {"ANC1 MUX", "DMIC6", "DMIC6"},
Kiran Kandic3b24402012-06-11 00:05:59 -07003575 {"ANC2 MUX", "ADC1", "ADC1"},
3576 {"ANC2 MUX", "ADC2", "ADC2"},
3577 {"ANC2 MUX", "ADC3", "ADC3"},
3578 {"ANC2 MUX", "ADC4", "ADC4"},
3579
Damir Didjusto2cb06bd2013-01-30 23:14:55 -08003580 {"ANC HPHR", NULL, "CDC_CONN"},
Kiran Kandic3b24402012-06-11 00:05:59 -07003581
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08003582 {"DAC1", "Switch", "CLASS_H_DSM MUX"},
3583 {"HPHL DAC", "Switch", "CLASS_H_DSM MUX"},
Kiran Kandic3b24402012-06-11 00:05:59 -07003584 {"HPHR DAC", NULL, "RX2 CHAIN"},
3585
3586 {"LINEOUT1", NULL, "LINEOUT1 PA"},
3587 {"LINEOUT2", NULL, "LINEOUT2 PA"},
3588 {"LINEOUT3", NULL, "LINEOUT3 PA"},
3589 {"LINEOUT4", NULL, "LINEOUT4 PA"},
Joonwoo Park7680b9f2012-07-13 11:36:48 -07003590 {"SPK_OUT", NULL, "SPK PA"},
Kiran Kandic3b24402012-06-11 00:05:59 -07003591
3592 {"LINEOUT1 PA", NULL, "LINEOUT1_PA_MIXER"},
3593 {"LINEOUT1_PA_MIXER", NULL, "LINEOUT1 DAC"},
Tanya Finkelfe634462012-10-23 22:12:07 +02003594
Kiran Kandic3b24402012-06-11 00:05:59 -07003595 {"LINEOUT2 PA", NULL, "LINEOUT2_PA_MIXER"},
3596 {"LINEOUT2_PA_MIXER", NULL, "LINEOUT2 DAC"},
Tanya Finkelfe634462012-10-23 22:12:07 +02003597
Kiran Kandic3b24402012-06-11 00:05:59 -07003598 {"LINEOUT3 PA", NULL, "LINEOUT3_PA_MIXER"},
3599 {"LINEOUT3_PA_MIXER", NULL, "LINEOUT3 DAC"},
Tanya Finkelfe634462012-10-23 22:12:07 +02003600
Kiran Kandic3b24402012-06-11 00:05:59 -07003601 {"LINEOUT4 PA", NULL, "LINEOUT4_PA_MIXER"},
3602 {"LINEOUT4_PA_MIXER", NULL, "LINEOUT4 DAC"},
3603
3604 {"LINEOUT1 DAC", NULL, "RX3 MIX1"},
3605
Tanya Finkeldaaa6d12012-10-25 11:22:48 +02003606 {"RDAC5 MUX", "DEM3_INV", "RX3 MIX1"},
3607 {"RDAC5 MUX", "DEM4", "RX4 MIX1"},
3608
3609 {"LINEOUT3 DAC", NULL, "RDAC5 MUX"},
Kiran Kandic3b24402012-06-11 00:05:59 -07003610
3611 {"LINEOUT2 DAC", NULL, "RX5 MIX1"},
3612
Tanya Finkeldaaa6d12012-10-25 11:22:48 +02003613 {"RDAC7 MUX", "DEM5_INV", "RX5 MIX1"},
3614 {"RDAC7 MUX", "DEM6", "RX6 MIX1"},
3615
3616 {"LINEOUT4 DAC", NULL, "RDAC7 MUX"},
Kiran Kandic3b24402012-06-11 00:05:59 -07003617
Joonwoo Park7680b9f2012-07-13 11:36:48 -07003618 {"SPK PA", NULL, "SPK DAC"},
Kiran Kandid2b46332012-10-05 12:04:00 -07003619 {"SPK DAC", NULL, "RX7 MIX2"},
Joonwoo Park125cd4e2012-12-11 15:16:11 -08003620 {"SPK DAC", NULL, "VDD_SPKDRV"},
Joonwoo Park7680b9f2012-07-13 11:36:48 -07003621
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08003622 {"CLASS_H_DSM MUX", "DSM_HPHL_RX1", "RX1 CHAIN"},
3623
Kiran Kandic3b24402012-06-11 00:05:59 -07003624 {"RX1 CHAIN", NULL, "RX1 MIX2"},
3625 {"RX2 CHAIN", NULL, "RX2 MIX2"},
Damir Didjusto2cb06bd2013-01-30 23:14:55 -08003626 {"RX1 MIX2", NULL, "ANC1 MUX"},
3627 {"RX2 MIX2", NULL, "ANC2 MUX"},
Kiran Kandic3b24402012-06-11 00:05:59 -07003628
Kiran Kandic3b24402012-06-11 00:05:59 -07003629 {"LINEOUT1 DAC", NULL, "RX_BIAS"},
3630 {"LINEOUT2 DAC", NULL, "RX_BIAS"},
3631 {"LINEOUT3 DAC", NULL, "RX_BIAS"},
3632 {"LINEOUT4 DAC", NULL, "RX_BIAS"},
Joonwoo Park7680b9f2012-07-13 11:36:48 -07003633 {"SPK DAC", NULL, "RX_BIAS"},
Kiran Kandic3b24402012-06-11 00:05:59 -07003634
Joonwoo Parkc7731432012-10-17 12:41:44 -07003635 {"RX7 MIX1", NULL, "COMP0_CLK"},
Kiran Kandic3b24402012-06-11 00:05:59 -07003636 {"RX1 MIX1", NULL, "COMP1_CLK"},
3637 {"RX2 MIX1", NULL, "COMP1_CLK"},
3638 {"RX3 MIX1", NULL, "COMP2_CLK"},
3639 {"RX5 MIX1", NULL, "COMP2_CLK"},
3640
Kiran Kandic3b24402012-06-11 00:05:59 -07003641 {"RX1 MIX1", NULL, "RX1 MIX1 INP1"},
3642 {"RX1 MIX1", NULL, "RX1 MIX1 INP2"},
3643 {"RX1 MIX1", NULL, "RX1 MIX1 INP3"},
3644 {"RX2 MIX1", NULL, "RX2 MIX1 INP1"},
3645 {"RX2 MIX1", NULL, "RX2 MIX1 INP2"},
3646 {"RX3 MIX1", NULL, "RX3 MIX1 INP1"},
3647 {"RX3 MIX1", NULL, "RX3 MIX1 INP2"},
3648 {"RX4 MIX1", NULL, "RX4 MIX1 INP1"},
3649 {"RX4 MIX1", NULL, "RX4 MIX1 INP2"},
3650 {"RX5 MIX1", NULL, "RX5 MIX1 INP1"},
3651 {"RX5 MIX1", NULL, "RX5 MIX1 INP2"},
3652 {"RX6 MIX1", NULL, "RX6 MIX1 INP1"},
3653 {"RX6 MIX1", NULL, "RX6 MIX1 INP2"},
3654 {"RX7 MIX1", NULL, "RX7 MIX1 INP1"},
3655 {"RX7 MIX1", NULL, "RX7 MIX1 INP2"},
3656 {"RX1 MIX2", NULL, "RX1 MIX1"},
3657 {"RX1 MIX2", NULL, "RX1 MIX2 INP1"},
3658 {"RX1 MIX2", NULL, "RX1 MIX2 INP2"},
3659 {"RX2 MIX2", NULL, "RX2 MIX1"},
3660 {"RX2 MIX2", NULL, "RX2 MIX2 INP1"},
3661 {"RX2 MIX2", NULL, "RX2 MIX2 INP2"},
3662 {"RX7 MIX2", NULL, "RX7 MIX1"},
3663 {"RX7 MIX2", NULL, "RX7 MIX2 INP1"},
3664 {"RX7 MIX2", NULL, "RX7 MIX2 INP2"},
3665
Kuirong Wang906ac472012-07-09 12:54:44 -07003666 /* SLIM_MUX("AIF1_PB", "AIF1 PB"),*/
3667 {"SLIM RX1 MUX", "AIF1_PB", "AIF1 PB"},
3668 {"SLIM RX2 MUX", "AIF1_PB", "AIF1 PB"},
3669 {"SLIM RX3 MUX", "AIF1_PB", "AIF1 PB"},
3670 {"SLIM RX4 MUX", "AIF1_PB", "AIF1 PB"},
3671 {"SLIM RX5 MUX", "AIF1_PB", "AIF1 PB"},
3672 {"SLIM RX6 MUX", "AIF1_PB", "AIF1 PB"},
3673 {"SLIM RX7 MUX", "AIF1_PB", "AIF1 PB"},
3674 /* SLIM_MUX("AIF2_PB", "AIF2 PB"),*/
3675 {"SLIM RX1 MUX", "AIF2_PB", "AIF2 PB"},
3676 {"SLIM RX2 MUX", "AIF2_PB", "AIF2 PB"},
3677 {"SLIM RX3 MUX", "AIF2_PB", "AIF2 PB"},
3678 {"SLIM RX4 MUX", "AIF2_PB", "AIF2 PB"},
3679 {"SLIM RX5 MUX", "AIF2_PB", "AIF2 PB"},
3680 {"SLIM RX6 MUX", "AIF2_PB", "AIF2 PB"},
3681 {"SLIM RX7 MUX", "AIF2_PB", "AIF2 PB"},
3682 /* SLIM_MUX("AIF3_PB", "AIF3 PB"),*/
3683 {"SLIM RX1 MUX", "AIF3_PB", "AIF3 PB"},
3684 {"SLIM RX2 MUX", "AIF3_PB", "AIF3 PB"},
3685 {"SLIM RX3 MUX", "AIF3_PB", "AIF3 PB"},
3686 {"SLIM RX4 MUX", "AIF3_PB", "AIF3 PB"},
3687 {"SLIM RX5 MUX", "AIF3_PB", "AIF3 PB"},
3688 {"SLIM RX6 MUX", "AIF3_PB", "AIF3 PB"},
3689 {"SLIM RX7 MUX", "AIF3_PB", "AIF3 PB"},
3690
3691 {"SLIM RX1", NULL, "SLIM RX1 MUX"},
3692 {"SLIM RX2", NULL, "SLIM RX2 MUX"},
3693 {"SLIM RX3", NULL, "SLIM RX3 MUX"},
3694 {"SLIM RX4", NULL, "SLIM RX4 MUX"},
3695 {"SLIM RX5", NULL, "SLIM RX5 MUX"},
3696 {"SLIM RX6", NULL, "SLIM RX6 MUX"},
3697 {"SLIM RX7", NULL, "SLIM RX7 MUX"},
3698
Kiran Kandic3b24402012-06-11 00:05:59 -07003699 {"RX1 MIX1 INP1", "RX1", "SLIM RX1"},
3700 {"RX1 MIX1 INP1", "RX2", "SLIM RX2"},
3701 {"RX1 MIX1 INP1", "RX3", "SLIM RX3"},
3702 {"RX1 MIX1 INP1", "RX4", "SLIM RX4"},
3703 {"RX1 MIX1 INP1", "RX5", "SLIM RX5"},
3704 {"RX1 MIX1 INP1", "RX6", "SLIM RX6"},
3705 {"RX1 MIX1 INP1", "RX7", "SLIM RX7"},
3706 {"RX1 MIX1 INP1", "IIR1", "IIR1"},
Fred Oh456fcb52013-02-28 19:08:15 -08003707 {"RX1 MIX1 INP1", "IIR2", "IIR2"},
Kiran Kandic3b24402012-06-11 00:05:59 -07003708 {"RX1 MIX1 INP2", "RX1", "SLIM RX1"},
3709 {"RX1 MIX1 INP2", "RX2", "SLIM RX2"},
3710 {"RX1 MIX1 INP2", "RX3", "SLIM RX3"},
3711 {"RX1 MIX1 INP2", "RX4", "SLIM RX4"},
3712 {"RX1 MIX1 INP2", "RX5", "SLIM RX5"},
3713 {"RX1 MIX1 INP2", "RX6", "SLIM RX6"},
3714 {"RX1 MIX1 INP2", "RX7", "SLIM RX7"},
3715 {"RX1 MIX1 INP2", "IIR1", "IIR1"},
Fred Oh456fcb52013-02-28 19:08:15 -08003716 {"RX1 MIX1 INP2", "IIR2", "IIR2"},
Kiran Kandic3b24402012-06-11 00:05:59 -07003717 {"RX1 MIX1 INP3", "RX1", "SLIM RX1"},
3718 {"RX1 MIX1 INP3", "RX2", "SLIM RX2"},
3719 {"RX1 MIX1 INP3", "RX3", "SLIM RX3"},
3720 {"RX1 MIX1 INP3", "RX4", "SLIM RX4"},
3721 {"RX1 MIX1 INP3", "RX5", "SLIM RX5"},
3722 {"RX1 MIX1 INP3", "RX6", "SLIM RX6"},
3723 {"RX1 MIX1 INP3", "RX7", "SLIM RX7"},
3724 {"RX2 MIX1 INP1", "RX1", "SLIM RX1"},
3725 {"RX2 MIX1 INP1", "RX2", "SLIM RX2"},
3726 {"RX2 MIX1 INP1", "RX3", "SLIM RX3"},
3727 {"RX2 MIX1 INP1", "RX4", "SLIM RX4"},
3728 {"RX2 MIX1 INP1", "RX5", "SLIM RX5"},
3729 {"RX2 MIX1 INP1", "RX6", "SLIM RX6"},
3730 {"RX2 MIX1 INP1", "RX7", "SLIM RX7"},
3731 {"RX2 MIX1 INP1", "IIR1", "IIR1"},
Fred Oh456fcb52013-02-28 19:08:15 -08003732 {"RX2 MIX1 INP1", "IIR2", "IIR2"},
Kiran Kandic3b24402012-06-11 00:05:59 -07003733 {"RX2 MIX1 INP2", "RX1", "SLIM RX1"},
3734 {"RX2 MIX1 INP2", "RX2", "SLIM RX2"},
3735 {"RX2 MIX1 INP2", "RX3", "SLIM RX3"},
3736 {"RX2 MIX1 INP2", "RX4", "SLIM RX4"},
3737 {"RX2 MIX1 INP2", "RX5", "SLIM RX5"},
3738 {"RX2 MIX1 INP2", "RX6", "SLIM RX6"},
3739 {"RX2 MIX1 INP2", "RX7", "SLIM RX7"},
3740 {"RX2 MIX1 INP2", "IIR1", "IIR1"},
Fred Oh456fcb52013-02-28 19:08:15 -08003741 {"RX2 MIX1 INP2", "IIR2", "IIR2"},
Kiran Kandic3b24402012-06-11 00:05:59 -07003742 {"RX3 MIX1 INP1", "RX1", "SLIM RX1"},
3743 {"RX3 MIX1 INP1", "RX2", "SLIM RX2"},
3744 {"RX3 MIX1 INP1", "RX3", "SLIM RX3"},
3745 {"RX3 MIX1 INP1", "RX4", "SLIM RX4"},
3746 {"RX3 MIX1 INP1", "RX5", "SLIM RX5"},
3747 {"RX3 MIX1 INP1", "RX6", "SLIM RX6"},
3748 {"RX3 MIX1 INP1", "RX7", "SLIM RX7"},
3749 {"RX3 MIX1 INP1", "IIR1", "IIR1"},
Fred Oh456fcb52013-02-28 19:08:15 -08003750 {"RX3 MIX1 INP1", "IIR2", "IIR2"},
Kiran Kandic3b24402012-06-11 00:05:59 -07003751 {"RX3 MIX1 INP2", "RX1", "SLIM RX1"},
3752 {"RX3 MIX1 INP2", "RX2", "SLIM RX2"},
3753 {"RX3 MIX1 INP2", "RX3", "SLIM RX3"},
3754 {"RX3 MIX1 INP2", "RX4", "SLIM RX4"},
3755 {"RX3 MIX1 INP2", "RX5", "SLIM RX5"},
3756 {"RX3 MIX1 INP2", "RX6", "SLIM RX6"},
3757 {"RX3 MIX1 INP2", "RX7", "SLIM RX7"},
3758 {"RX3 MIX1 INP2", "IIR1", "IIR1"},
Fred Oh456fcb52013-02-28 19:08:15 -08003759 {"RX3 MIX1 INP2", "IIR2", "IIR2"},
Kiran Kandic3b24402012-06-11 00:05:59 -07003760 {"RX4 MIX1 INP1", "RX1", "SLIM RX1"},
3761 {"RX4 MIX1 INP1", "RX2", "SLIM RX2"},
3762 {"RX4 MIX1 INP1", "RX3", "SLIM RX3"},
3763 {"RX4 MIX1 INP1", "RX4", "SLIM RX4"},
3764 {"RX4 MIX1 INP1", "RX5", "SLIM RX5"},
3765 {"RX4 MIX1 INP1", "RX6", "SLIM RX6"},
3766 {"RX4 MIX1 INP1", "RX7", "SLIM RX7"},
3767 {"RX4 MIX1 INP1", "IIR1", "IIR1"},
Fred Oh456fcb52013-02-28 19:08:15 -08003768 {"RX4 MIX1 INP1", "IIR2", "IIR2"},
Kiran Kandic3b24402012-06-11 00:05:59 -07003769 {"RX4 MIX1 INP2", "RX1", "SLIM RX1"},
3770 {"RX4 MIX1 INP2", "RX2", "SLIM RX2"},
3771 {"RX4 MIX1 INP2", "RX3", "SLIM RX3"},
3772 {"RX4 MIX1 INP2", "RX5", "SLIM RX5"},
3773 {"RX4 MIX1 INP2", "RX4", "SLIM RX4"},
3774 {"RX4 MIX1 INP2", "RX6", "SLIM RX6"},
3775 {"RX4 MIX1 INP2", "RX7", "SLIM RX7"},
3776 {"RX4 MIX1 INP2", "IIR1", "IIR1"},
Fred Oh456fcb52013-02-28 19:08:15 -08003777 {"RX4 MIX1 INP2", "IIR2", "IIR2"},
Kiran Kandic3b24402012-06-11 00:05:59 -07003778 {"RX5 MIX1 INP1", "RX1", "SLIM RX1"},
3779 {"RX5 MIX1 INP1", "RX2", "SLIM RX2"},
3780 {"RX5 MIX1 INP1", "RX3", "SLIM RX3"},
3781 {"RX5 MIX1 INP1", "RX4", "SLIM RX4"},
3782 {"RX5 MIX1 INP1", "RX5", "SLIM RX5"},
3783 {"RX5 MIX1 INP1", "RX6", "SLIM RX6"},
3784 {"RX5 MIX1 INP1", "RX7", "SLIM RX7"},
3785 {"RX5 MIX1 INP1", "IIR1", "IIR1"},
Fred Oh456fcb52013-02-28 19:08:15 -08003786 {"RX5 MIX1 INP1", "IIR2", "IIR2"},
Kiran Kandic3b24402012-06-11 00:05:59 -07003787 {"RX5 MIX1 INP2", "RX1", "SLIM RX1"},
3788 {"RX5 MIX1 INP2", "RX2", "SLIM RX2"},
3789 {"RX5 MIX1 INP2", "RX3", "SLIM RX3"},
3790 {"RX5 MIX1 INP2", "RX4", "SLIM RX4"},
3791 {"RX5 MIX1 INP2", "RX5", "SLIM RX5"},
3792 {"RX5 MIX1 INP2", "RX6", "SLIM RX6"},
3793 {"RX5 MIX1 INP2", "RX7", "SLIM RX7"},
3794 {"RX5 MIX1 INP2", "IIR1", "IIR1"},
Fred Oh456fcb52013-02-28 19:08:15 -08003795 {"RX5 MIX1 INP2", "IIR2", "IIR2"},
Kiran Kandic3b24402012-06-11 00:05:59 -07003796 {"RX6 MIX1 INP1", "RX1", "SLIM RX1"},
3797 {"RX6 MIX1 INP1", "RX2", "SLIM RX2"},
3798 {"RX6 MIX1 INP1", "RX3", "SLIM RX3"},
3799 {"RX6 MIX1 INP1", "RX4", "SLIM RX4"},
3800 {"RX6 MIX1 INP1", "RX5", "SLIM RX5"},
3801 {"RX6 MIX1 INP1", "RX6", "SLIM RX6"},
3802 {"RX6 MIX1 INP1", "RX7", "SLIM RX7"},
3803 {"RX6 MIX1 INP1", "IIR1", "IIR1"},
Fred Oh456fcb52013-02-28 19:08:15 -08003804 {"RX6 MIX1 INP1", "IIR2", "IIR2"},
Kiran Kandic3b24402012-06-11 00:05:59 -07003805 {"RX6 MIX1 INP2", "RX1", "SLIM RX1"},
3806 {"RX6 MIX1 INP2", "RX2", "SLIM RX2"},
3807 {"RX6 MIX1 INP2", "RX3", "SLIM RX3"},
3808 {"RX6 MIX1 INP2", "RX4", "SLIM RX4"},
3809 {"RX6 MIX1 INP2", "RX5", "SLIM RX5"},
3810 {"RX6 MIX1 INP2", "RX6", "SLIM RX6"},
3811 {"RX6 MIX1 INP2", "RX7", "SLIM RX7"},
3812 {"RX6 MIX1 INP2", "IIR1", "IIR1"},
Fred Oh456fcb52013-02-28 19:08:15 -08003813 {"RX6 MIX1 INP2", "IIR2", "IIR2"},
Kiran Kandic3b24402012-06-11 00:05:59 -07003814 {"RX7 MIX1 INP1", "RX1", "SLIM RX1"},
3815 {"RX7 MIX1 INP1", "RX2", "SLIM RX2"},
3816 {"RX7 MIX1 INP1", "RX3", "SLIM RX3"},
3817 {"RX7 MIX1 INP1", "RX4", "SLIM RX4"},
3818 {"RX7 MIX1 INP1", "RX5", "SLIM RX5"},
3819 {"RX7 MIX1 INP1", "RX6", "SLIM RX6"},
3820 {"RX7 MIX1 INP1", "RX7", "SLIM RX7"},
3821 {"RX7 MIX1 INP1", "IIR1", "IIR1"},
Fred Oh456fcb52013-02-28 19:08:15 -08003822 {"RX7 MIX1 INP1", "IIR2", "IIR2"},
Kiran Kandic3b24402012-06-11 00:05:59 -07003823 {"RX7 MIX1 INP2", "RX1", "SLIM RX1"},
3824 {"RX7 MIX1 INP2", "RX2", "SLIM RX2"},
3825 {"RX7 MIX1 INP2", "RX3", "SLIM RX3"},
3826 {"RX7 MIX1 INP2", "RX4", "SLIM RX4"},
3827 {"RX7 MIX1 INP2", "RX5", "SLIM RX5"},
3828 {"RX7 MIX1 INP2", "RX6", "SLIM RX6"},
3829 {"RX7 MIX1 INP2", "RX7", "SLIM RX7"},
3830 {"RX7 MIX1 INP2", "IIR1", "IIR1"},
Kiran Kandibd85d772013-05-19 19:03:43 -07003831 {"RX7 MIX1 INP2", "IIR2", "IIR2"},
3832
3833 /* IIR1, IIR2 inputs to Second RX Mixer on RX1, RX2 and RX7 chains. */
Kiran Kandic3b24402012-06-11 00:05:59 -07003834 {"RX1 MIX2 INP1", "IIR1", "IIR1"},
3835 {"RX1 MIX2 INP2", "IIR1", "IIR1"},
3836 {"RX2 MIX2 INP1", "IIR1", "IIR1"},
3837 {"RX2 MIX2 INP2", "IIR1", "IIR1"},
3838 {"RX7 MIX2 INP1", "IIR1", "IIR1"},
3839 {"RX7 MIX2 INP2", "IIR1", "IIR1"},
Fred Oh456fcb52013-02-28 19:08:15 -08003840 {"RX1 MIX2 INP1", "IIR2", "IIR2"},
3841 {"RX1 MIX2 INP2", "IIR2", "IIR2"},
3842 {"RX2 MIX2 INP1", "IIR2", "IIR2"},
3843 {"RX2 MIX2 INP2", "IIR2", "IIR2"},
3844 {"RX7 MIX2 INP1", "IIR2", "IIR2"},
3845 {"RX7 MIX2 INP2", "IIR2", "IIR2"},
Kiran Kandic3b24402012-06-11 00:05:59 -07003846
3847 /* Decimator Inputs */
3848 {"DEC1 MUX", "DMIC1", "DMIC1"},
3849 {"DEC1 MUX", "ADC6", "ADC6"},
3850 {"DEC1 MUX", NULL, "CDC_CONN"},
3851 {"DEC2 MUX", "DMIC2", "DMIC2"},
3852 {"DEC2 MUX", "ADC5", "ADC5"},
3853 {"DEC2 MUX", NULL, "CDC_CONN"},
3854 {"DEC3 MUX", "DMIC3", "DMIC3"},
3855 {"DEC3 MUX", "ADC4", "ADC4"},
3856 {"DEC3 MUX", NULL, "CDC_CONN"},
3857 {"DEC4 MUX", "DMIC4", "DMIC4"},
3858 {"DEC4 MUX", "ADC3", "ADC3"},
3859 {"DEC4 MUX", NULL, "CDC_CONN"},
3860 {"DEC5 MUX", "DMIC5", "DMIC5"},
3861 {"DEC5 MUX", "ADC2", "ADC2"},
3862 {"DEC5 MUX", NULL, "CDC_CONN"},
3863 {"DEC6 MUX", "DMIC6", "DMIC6"},
3864 {"DEC6 MUX", "ADC1", "ADC1"},
3865 {"DEC6 MUX", NULL, "CDC_CONN"},
3866 {"DEC7 MUX", "DMIC1", "DMIC1"},
3867 {"DEC7 MUX", "DMIC6", "DMIC6"},
3868 {"DEC7 MUX", "ADC1", "ADC1"},
3869 {"DEC7 MUX", "ADC6", "ADC6"},
3870 {"DEC7 MUX", NULL, "CDC_CONN"},
3871 {"DEC8 MUX", "DMIC2", "DMIC2"},
3872 {"DEC8 MUX", "DMIC5", "DMIC5"},
3873 {"DEC8 MUX", "ADC2", "ADC2"},
3874 {"DEC8 MUX", "ADC5", "ADC5"},
3875 {"DEC8 MUX", NULL, "CDC_CONN"},
3876 {"DEC9 MUX", "DMIC4", "DMIC4"},
3877 {"DEC9 MUX", "DMIC5", "DMIC5"},
3878 {"DEC9 MUX", "ADC2", "ADC2"},
3879 {"DEC9 MUX", "ADC3", "ADC3"},
3880 {"DEC9 MUX", NULL, "CDC_CONN"},
3881 {"DEC10 MUX", "DMIC3", "DMIC3"},
3882 {"DEC10 MUX", "DMIC6", "DMIC6"},
3883 {"DEC10 MUX", "ADC1", "ADC1"},
3884 {"DEC10 MUX", "ADC4", "ADC4"},
3885 {"DEC10 MUX", NULL, "CDC_CONN"},
3886
3887 /* ADC Connections */
3888 {"ADC1", NULL, "AMIC1"},
3889 {"ADC2", NULL, "AMIC2"},
3890 {"ADC3", NULL, "AMIC3"},
3891 {"ADC4", NULL, "AMIC4"},
3892 {"ADC5", NULL, "AMIC5"},
3893 {"ADC6", NULL, "AMIC6"},
3894
3895 /* AUX PGA Connections */
Kiran Kandic3b24402012-06-11 00:05:59 -07003896 {"EAR_PA_MIXER", "AUX_PGA_L Switch", "AUX_PGA_Left"},
Kiran Kandi4c56c592012-07-25 11:04:55 -07003897 {"HPHL_PA_MIXER", "AUX_PGA_L Switch", "AUX_PGA_Left"},
3898 {"HPHR_PA_MIXER", "AUX_PGA_R Switch", "AUX_PGA_Right"},
3899 {"LINEOUT1_PA_MIXER", "AUX_PGA_L Switch", "AUX_PGA_Left"},
3900 {"LINEOUT2_PA_MIXER", "AUX_PGA_R Switch", "AUX_PGA_Right"},
3901 {"LINEOUT3_PA_MIXER", "AUX_PGA_L Switch", "AUX_PGA_Left"},
3902 {"LINEOUT4_PA_MIXER", "AUX_PGA_R Switch", "AUX_PGA_Right"},
Kiran Kandic3b24402012-06-11 00:05:59 -07003903 {"AUX_PGA_Left", NULL, "AMIC5"},
3904 {"AUX_PGA_Right", NULL, "AMIC6"},
3905
Kiran Kandic3b24402012-06-11 00:05:59 -07003906 {"IIR1", NULL, "IIR1 INP1 MUX"},
3907 {"IIR1 INP1 MUX", "DEC1", "DEC1 MUX"},
3908 {"IIR1 INP1 MUX", "DEC2", "DEC2 MUX"},
3909 {"IIR1 INP1 MUX", "DEC3", "DEC3 MUX"},
3910 {"IIR1 INP1 MUX", "DEC4", "DEC4 MUX"},
3911 {"IIR1 INP1 MUX", "DEC5", "DEC5 MUX"},
3912 {"IIR1 INP1 MUX", "DEC6", "DEC6 MUX"},
3913 {"IIR1 INP1 MUX", "DEC7", "DEC7 MUX"},
3914 {"IIR1 INP1 MUX", "DEC8", "DEC8 MUX"},
3915 {"IIR1 INP1 MUX", "DEC9", "DEC9 MUX"},
3916 {"IIR1 INP1 MUX", "DEC10", "DEC10 MUX"},
Kiran Kandibd85d772013-05-19 19:03:43 -07003917 {"IIR1 INP1 MUX", "RX1", "SLIM RX1"},
3918 {"IIR1 INP1 MUX", "RX2", "SLIM RX2"},
3919 {"IIR1 INP1 MUX", "RX3", "SLIM RX3"},
3920 {"IIR1 INP1 MUX", "RX4", "SLIM RX4"},
3921 {"IIR1 INP1 MUX", "RX5", "SLIM RX5"},
3922 {"IIR1 INP1 MUX", "RX6", "SLIM RX6"},
3923 {"IIR1 INP1 MUX", "RX7", "SLIM RX7"},
Kiran Kandic3b24402012-06-11 00:05:59 -07003924
Fred Oh456fcb52013-02-28 19:08:15 -08003925 {"IIR2", NULL, "IIR2 INP1 MUX"},
3926 {"IIR2 INP1 MUX", "DEC1", "DEC1 MUX"},
3927 {"IIR2 INP1 MUX", "DEC2", "DEC2 MUX"},
3928 {"IIR2 INP1 MUX", "DEC3", "DEC3 MUX"},
3929 {"IIR2 INP1 MUX", "DEC4", "DEC4 MUX"},
3930 {"IIR2 INP1 MUX", "DEC5", "DEC5 MUX"},
3931 {"IIR2 INP1 MUX", "DEC6", "DEC6 MUX"},
3932 {"IIR2 INP1 MUX", "DEC7", "DEC7 MUX"},
3933 {"IIR2 INP1 MUX", "DEC8", "DEC8 MUX"},
3934 {"IIR2 INP1 MUX", "DEC9", "DEC9 MUX"},
3935 {"IIR2 INP1 MUX", "DEC10", "DEC10 MUX"},
Kiran Kandibd85d772013-05-19 19:03:43 -07003936 {"IIR2 INP1 MUX", "RX1", "SLIM RX1"},
3937 {"IIR2 INP1 MUX", "RX2", "SLIM RX2"},
3938 {"IIR2 INP1 MUX", "RX3", "SLIM RX3"},
3939 {"IIR2 INP1 MUX", "RX4", "SLIM RX4"},
3940 {"IIR2 INP1 MUX", "RX5", "SLIM RX5"},
3941 {"IIR2 INP1 MUX", "RX6", "SLIM RX6"},
3942 {"IIR2 INP1 MUX", "RX7", "SLIM RX7"},
Fred Oh456fcb52013-02-28 19:08:15 -08003943
Kiran Kandic3b24402012-06-11 00:05:59 -07003944 {"MIC BIAS1 Internal1", NULL, "LDO_H"},
3945 {"MIC BIAS1 Internal2", NULL, "LDO_H"},
3946 {"MIC BIAS1 External", NULL, "LDO_H"},
3947 {"MIC BIAS2 Internal1", NULL, "LDO_H"},
3948 {"MIC BIAS2 Internal2", NULL, "LDO_H"},
3949 {"MIC BIAS2 Internal3", NULL, "LDO_H"},
3950 {"MIC BIAS2 External", NULL, "LDO_H"},
3951 {"MIC BIAS3 Internal1", NULL, "LDO_H"},
3952 {"MIC BIAS3 Internal2", NULL, "LDO_H"},
3953 {"MIC BIAS3 External", NULL, "LDO_H"},
3954 {"MIC BIAS4 External", NULL, "LDO_H"},
Joonwoo Parkccccba72013-04-26 11:19:46 -07003955 {DAPM_MICBIAS2_EXTERNAL_STANDALONE, NULL, "LDO_H Standalone"},
Kiran Kandic3b24402012-06-11 00:05:59 -07003956};
3957
3958static int taiko_readable(struct snd_soc_codec *ssc, unsigned int reg)
3959{
3960 return taiko_reg_readable[reg];
3961}
3962
3963static bool taiko_is_digital_gain_register(unsigned int reg)
3964{
3965 bool rtn = false;
3966 switch (reg) {
3967 case TAIKO_A_CDC_RX1_VOL_CTL_B2_CTL:
3968 case TAIKO_A_CDC_RX2_VOL_CTL_B2_CTL:
3969 case TAIKO_A_CDC_RX3_VOL_CTL_B2_CTL:
3970 case TAIKO_A_CDC_RX4_VOL_CTL_B2_CTL:
3971 case TAIKO_A_CDC_RX5_VOL_CTL_B2_CTL:
3972 case TAIKO_A_CDC_RX6_VOL_CTL_B2_CTL:
3973 case TAIKO_A_CDC_RX7_VOL_CTL_B2_CTL:
3974 case TAIKO_A_CDC_TX1_VOL_CTL_GAIN:
3975 case TAIKO_A_CDC_TX2_VOL_CTL_GAIN:
3976 case TAIKO_A_CDC_TX3_VOL_CTL_GAIN:
3977 case TAIKO_A_CDC_TX4_VOL_CTL_GAIN:
3978 case TAIKO_A_CDC_TX5_VOL_CTL_GAIN:
3979 case TAIKO_A_CDC_TX6_VOL_CTL_GAIN:
3980 case TAIKO_A_CDC_TX7_VOL_CTL_GAIN:
3981 case TAIKO_A_CDC_TX8_VOL_CTL_GAIN:
3982 case TAIKO_A_CDC_TX9_VOL_CTL_GAIN:
3983 case TAIKO_A_CDC_TX10_VOL_CTL_GAIN:
3984 rtn = true;
3985 break;
3986 default:
3987 break;
3988 }
3989 return rtn;
3990}
3991
3992static int taiko_volatile(struct snd_soc_codec *ssc, unsigned int reg)
3993{
Joonwoo Park1d05bb92013-03-07 16:55:06 -08003994 int i;
3995
Kiran Kandic3b24402012-06-11 00:05:59 -07003996 /* Registers lower than 0x100 are top level registers which can be
3997 * written by the Taiko core driver.
3998 */
3999
4000 if ((reg >= TAIKO_A_CDC_MBHC_EN_CTL) || (reg < 0x100))
4001 return 1;
4002
4003 /* IIR Coeff registers are not cacheable */
4004 if ((reg >= TAIKO_A_CDC_IIR1_COEF_B1_CTL) &&
4005 (reg <= TAIKO_A_CDC_IIR2_COEF_B2_CTL))
4006 return 1;
4007
Damir Didjusto2cb06bd2013-01-30 23:14:55 -08004008 /* ANC filter registers are not cacheable */
4009 if ((reg >= TAIKO_A_CDC_ANC1_IIR_B1_CTL) &&
4010 (reg <= TAIKO_A_CDC_ANC1_LPF_B2_CTL))
4011 return 1;
4012 if ((reg >= TAIKO_A_CDC_ANC2_IIR_B1_CTL) &&
4013 (reg <= TAIKO_A_CDC_ANC2_LPF_B2_CTL))
4014 return 1;
4015
Kiran Kandic3b24402012-06-11 00:05:59 -07004016 /* Digital gain register is not cacheable so we have to write
4017 * the setting even it is the same
4018 */
4019 if (taiko_is_digital_gain_register(reg))
4020 return 1;
4021
4022 /* HPH status registers */
4023 if (reg == TAIKO_A_RX_HPH_L_STATUS || reg == TAIKO_A_RX_HPH_R_STATUS)
4024 return 1;
4025
Joonwoo Parka8890262012-10-15 12:04:27 -07004026 if (reg == TAIKO_A_MBHC_INSERT_DET_STATUS)
4027 return 1;
4028
Joonwoo Park559a5bf2013-02-15 14:46:36 -08004029 switch (reg) {
4030 case TAIKO_A_CDC_SPKR_CLIPDET_VAL0:
4031 case TAIKO_A_CDC_SPKR_CLIPDET_VAL1:
4032 case TAIKO_A_CDC_SPKR_CLIPDET_VAL2:
4033 case TAIKO_A_CDC_SPKR_CLIPDET_VAL3:
4034 case TAIKO_A_CDC_SPKR_CLIPDET_VAL4:
4035 case TAIKO_A_CDC_SPKR_CLIPDET_VAL5:
4036 case TAIKO_A_CDC_SPKR_CLIPDET_VAL6:
4037 case TAIKO_A_CDC_SPKR_CLIPDET_VAL7:
4038 case TAIKO_A_CDC_VBAT_GAIN_MON_VAL:
4039 return 1;
4040 }
4041
Damir Didjustodcfdff82013-03-21 23:26:41 -07004042 for (i = 0; i < ARRAY_SIZE(audio_reg_cfg); i++)
4043 if (audio_reg_cfg[i].reg_logical_addr -
Joonwoo Park1d05bb92013-03-07 16:55:06 -08004044 TAIKO_REGISTER_START_OFFSET == reg)
4045 return 1;
4046
Kiran Kandic3b24402012-06-11 00:05:59 -07004047 return 0;
4048}
4049
Kiran Kandic3b24402012-06-11 00:05:59 -07004050static int taiko_write(struct snd_soc_codec *codec, unsigned int reg,
4051 unsigned int value)
4052{
4053 int ret;
Kuirong Wang906ac472012-07-09 12:54:44 -07004054
4055 if (reg == SND_SOC_NOPM)
4056 return 0;
4057
Kiran Kandic3b24402012-06-11 00:05:59 -07004058 BUG_ON(reg > TAIKO_MAX_REGISTER);
4059
4060 if (!taiko_volatile(codec, reg)) {
4061 ret = snd_soc_cache_write(codec, reg, value);
4062 if (ret != 0)
4063 dev_err(codec->dev, "Cache write to %x failed: %d\n",
4064 reg, ret);
4065 }
4066
4067 return wcd9xxx_reg_write(codec->control_data, reg, value);
4068}
4069static unsigned int taiko_read(struct snd_soc_codec *codec,
4070 unsigned int reg)
4071{
4072 unsigned int val;
4073 int ret;
4074
Kuirong Wang906ac472012-07-09 12:54:44 -07004075 if (reg == SND_SOC_NOPM)
4076 return 0;
4077
Kiran Kandic3b24402012-06-11 00:05:59 -07004078 BUG_ON(reg > TAIKO_MAX_REGISTER);
4079
4080 if (!taiko_volatile(codec, reg) && taiko_readable(codec, reg) &&
4081 reg < codec->driver->reg_cache_size) {
4082 ret = snd_soc_cache_read(codec, reg, &val);
4083 if (ret >= 0) {
4084 return val;
4085 } else
4086 dev_err(codec->dev, "Cache read from %x failed: %d\n",
4087 reg, ret);
4088 }
4089
4090 val = wcd9xxx_reg_read(codec->control_data, reg);
4091 return val;
4092}
4093
Kiran Kandic3b24402012-06-11 00:05:59 -07004094static int taiko_startup(struct snd_pcm_substream *substream,
4095 struct snd_soc_dai *dai)
4096{
4097 struct wcd9xxx *taiko_core = dev_get_drvdata(dai->codec->dev->parent);
4098 pr_debug("%s(): substream = %s stream = %d\n" , __func__,
4099 substream->name, substream->stream);
4100 if ((taiko_core != NULL) &&
4101 (taiko_core->dev != NULL) &&
4102 (taiko_core->dev->parent != NULL))
4103 pm_runtime_get_sync(taiko_core->dev->parent);
4104
4105 return 0;
4106}
4107
4108static void taiko_shutdown(struct snd_pcm_substream *substream,
4109 struct snd_soc_dai *dai)
4110{
4111 struct wcd9xxx *taiko_core = dev_get_drvdata(dai->codec->dev->parent);
4112 pr_debug("%s(): substream = %s stream = %d\n" , __func__,
4113 substream->name, substream->stream);
4114 if ((taiko_core != NULL) &&
4115 (taiko_core->dev != NULL) &&
4116 (taiko_core->dev->parent != NULL)) {
4117 pm_runtime_mark_last_busy(taiko_core->dev->parent);
4118 pm_runtime_put(taiko_core->dev->parent);
4119 }
4120}
4121
4122int taiko_mclk_enable(struct snd_soc_codec *codec, int mclk_enable, bool dapm)
4123{
4124 struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
4125
4126 pr_debug("%s: mclk_enable = %u, dapm = %d\n", __func__, mclk_enable,
4127 dapm);
Joonwoo Parka8890262012-10-15 12:04:27 -07004128
Joonwoo Park533b3682013-06-13 11:41:21 -07004129 WCD9XXX_BG_CLK_LOCK(&taiko->resmgr);
Kiran Kandic3b24402012-06-11 00:05:59 -07004130 if (mclk_enable) {
Joonwoo Parka8890262012-10-15 12:04:27 -07004131 wcd9xxx_resmgr_get_bandgap(&taiko->resmgr,
4132 WCD9XXX_BANDGAP_AUDIO_MODE);
4133 wcd9xxx_resmgr_get_clk_block(&taiko->resmgr, WCD9XXX_CLK_MCLK);
Kiran Kandic3b24402012-06-11 00:05:59 -07004134 } else {
Joonwoo Parka8890262012-10-15 12:04:27 -07004135 /* Put clock and BG */
4136 wcd9xxx_resmgr_put_clk_block(&taiko->resmgr, WCD9XXX_CLK_MCLK);
4137 wcd9xxx_resmgr_put_bandgap(&taiko->resmgr,
4138 WCD9XXX_BANDGAP_AUDIO_MODE);
Kiran Kandic3b24402012-06-11 00:05:59 -07004139 }
Joonwoo Park533b3682013-06-13 11:41:21 -07004140 WCD9XXX_BG_CLK_UNLOCK(&taiko->resmgr);
Joonwoo Parka8890262012-10-15 12:04:27 -07004141
Kiran Kandic3b24402012-06-11 00:05:59 -07004142 return 0;
4143}
4144
4145static int taiko_set_dai_sysclk(struct snd_soc_dai *dai,
4146 int clk_id, unsigned int freq, int dir)
4147{
Venkat Sudhira50a3762012-11-26 12:12:15 -08004148 pr_debug("%s\n", __func__);
Kiran Kandic3b24402012-06-11 00:05:59 -07004149 return 0;
4150}
4151
4152static int taiko_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
4153{
4154 u8 val = 0;
4155 struct taiko_priv *taiko = snd_soc_codec_get_drvdata(dai->codec);
4156
4157 pr_debug("%s\n", __func__);
4158 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
4159 case SND_SOC_DAIFMT_CBS_CFS:
4160 /* CPU is master */
4161 if (taiko->intf_type == WCD9XXX_INTERFACE_TYPE_I2C) {
4162 if (dai->id == AIF1_CAP)
4163 snd_soc_update_bits(dai->codec,
4164 TAIKO_A_CDC_CLK_TX_I2S_CTL,
4165 TAIKO_I2S_MASTER_MODE_MASK, 0);
4166 else if (dai->id == AIF1_PB)
4167 snd_soc_update_bits(dai->codec,
4168 TAIKO_A_CDC_CLK_RX_I2S_CTL,
4169 TAIKO_I2S_MASTER_MODE_MASK, 0);
4170 }
4171 break;
4172 case SND_SOC_DAIFMT_CBM_CFM:
4173 /* CPU is slave */
4174 if (taiko->intf_type == WCD9XXX_INTERFACE_TYPE_I2C) {
4175 val = TAIKO_I2S_MASTER_MODE_MASK;
4176 if (dai->id == AIF1_CAP)
4177 snd_soc_update_bits(dai->codec,
4178 TAIKO_A_CDC_CLK_TX_I2S_CTL, val, val);
4179 else if (dai->id == AIF1_PB)
4180 snd_soc_update_bits(dai->codec,
4181 TAIKO_A_CDC_CLK_RX_I2S_CTL, val, val);
4182 }
4183 break;
4184 default:
4185 return -EINVAL;
4186 }
4187 return 0;
4188}
4189
4190static int taiko_set_channel_map(struct snd_soc_dai *dai,
4191 unsigned int tx_num, unsigned int *tx_slot,
4192 unsigned int rx_num, unsigned int *rx_slot)
4193
4194{
Gopikrishnaiah Anandana2627572013-02-26 13:30:50 -05004195 struct wcd9xxx_codec_dai_data *dai_data = NULL;
Kiran Kandic3b24402012-06-11 00:05:59 -07004196 struct taiko_priv *taiko = snd_soc_codec_get_drvdata(dai->codec);
Kuirong Wang906ac472012-07-09 12:54:44 -07004197 struct wcd9xxx *core = dev_get_drvdata(dai->codec->dev->parent);
Kiran Kandic3b24402012-06-11 00:05:59 -07004198 if (!tx_slot && !rx_slot) {
4199 pr_err("%s: Invalid\n", __func__);
4200 return -EINVAL;
4201 }
Kuirong Wang906ac472012-07-09 12:54:44 -07004202 pr_debug("%s(): dai_name = %s DAI-ID %x tx_ch %d rx_ch %d\n"
4203 "taiko->intf_type %d\n",
4204 __func__, dai->name, dai->id, tx_num, rx_num,
4205 taiko->intf_type);
Kiran Kandic3b24402012-06-11 00:05:59 -07004206
Gopikrishnaiah Anandana2627572013-02-26 13:30:50 -05004207 if (taiko->intf_type == WCD9XXX_INTERFACE_TYPE_SLIMBUS) {
Kuirong Wang906ac472012-07-09 12:54:44 -07004208 wcd9xxx_init_slimslave(core, core->slim->laddr,
Gopikrishnaiah Anandana2627572013-02-26 13:30:50 -05004209 tx_num, tx_slot, rx_num, rx_slot);
4210 /*Reserve tx11 and tx12 for VI feedback path*/
4211 dai_data = &taiko->dai[AIF4_VIFEED];
4212 if (dai_data) {
4213 list_add_tail(&core->tx_chs[TAIKO_TX11].list,
4214 &dai_data->wcd9xxx_ch_list);
4215 list_add_tail(&core->tx_chs[TAIKO_TX12].list,
4216 &dai_data->wcd9xxx_ch_list);
4217 }
4218 }
Kuirong Wang906ac472012-07-09 12:54:44 -07004219 return 0;
4220}
4221
4222static int taiko_get_channel_map(struct snd_soc_dai *dai,
4223 unsigned int *tx_num, unsigned int *tx_slot,
4224 unsigned int *rx_num, unsigned int *rx_slot)
4225
4226{
4227 struct taiko_priv *taiko_p = snd_soc_codec_get_drvdata(dai->codec);
4228 u32 i = 0;
4229 struct wcd9xxx_ch *ch;
4230
4231 switch (dai->id) {
4232 case AIF1_PB:
4233 case AIF2_PB:
4234 case AIF3_PB:
4235 if (!rx_slot || !rx_num) {
4236 pr_err("%s: Invalid rx_slot %d or rx_num %d\n",
4237 __func__, (u32) rx_slot, (u32) rx_num);
4238 return -EINVAL;
Kiran Kandic3b24402012-06-11 00:05:59 -07004239 }
Kuirong Wang906ac472012-07-09 12:54:44 -07004240 list_for_each_entry(ch, &taiko_p->dai[dai->id].wcd9xxx_ch_list,
4241 list) {
Gopikrishnaiah Anandana8aec1f2013-01-23 14:26:27 -05004242 pr_debug("%s: slot_num %u ch->ch_num %d\n",
4243 __func__, i, ch->ch_num);
Kuirong Wang906ac472012-07-09 12:54:44 -07004244 rx_slot[i++] = ch->ch_num;
4245 }
4246 pr_debug("%s: rx_num %d\n", __func__, i);
4247 *rx_num = i;
4248 break;
4249 case AIF1_CAP:
4250 case AIF2_CAP:
4251 case AIF3_CAP:
Gopikrishnaiah Anandana2627572013-02-26 13:30:50 -05004252 case AIF4_VIFEED:
Joonwoo Park1d05bb92013-03-07 16:55:06 -08004253 case AIF4_MAD_TX:
Kuirong Wang906ac472012-07-09 12:54:44 -07004254 if (!tx_slot || !tx_num) {
4255 pr_err("%s: Invalid tx_slot %d or tx_num %d\n",
4256 __func__, (u32) tx_slot, (u32) tx_num);
4257 return -EINVAL;
4258 }
4259 list_for_each_entry(ch, &taiko_p->dai[dai->id].wcd9xxx_ch_list,
4260 list) {
Gopikrishnaiah Anandana8aec1f2013-01-23 14:26:27 -05004261 pr_debug("%s: slot_num %u ch->ch_num %d\n",
4262 __func__, i, ch->ch_num);
Kuirong Wang906ac472012-07-09 12:54:44 -07004263 tx_slot[i++] = ch->ch_num;
4264 }
4265 pr_debug("%s: tx_num %d\n", __func__, i);
4266 *tx_num = i;
4267 break;
4268
4269 default:
4270 pr_err("%s: Invalid DAI ID %x\n", __func__, dai->id);
4271 break;
4272 }
4273
4274 return 0;
4275}
4276
4277static int taiko_set_interpolator_rate(struct snd_soc_dai *dai,
4278 u8 rx_fs_rate_reg_val, u32 compander_fs, u32 sample_rate)
4279{
4280 u32 j;
4281 u8 rx_mix1_inp;
4282 u16 rx_mix_1_reg_1, rx_mix_1_reg_2;
4283 u16 rx_fs_reg;
4284 u8 rx_mix_1_reg_1_val, rx_mix_1_reg_2_val;
4285 struct snd_soc_codec *codec = dai->codec;
4286 struct wcd9xxx_ch *ch;
4287 struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
4288
4289 list_for_each_entry(ch, &taiko->dai[dai->id].wcd9xxx_ch_list, list) {
4290 /* for RX port starting from 16 instead of 10 like tabla */
4291 rx_mix1_inp = ch->port + RX_MIX1_INP_SEL_RX1 -
4292 TAIKO_TX_PORT_NUMBER;
4293 if ((rx_mix1_inp < RX_MIX1_INP_SEL_RX1) ||
4294 (rx_mix1_inp > RX_MIX1_INP_SEL_RX7)) {
4295 pr_err("%s: Invalid TAIKO_RX%u port. Dai ID is %d\n",
4296 __func__, rx_mix1_inp - 5 , dai->id);
4297 return -EINVAL;
4298 }
4299
4300 rx_mix_1_reg_1 = TAIKO_A_CDC_CONN_RX1_B1_CTL;
4301
4302 for (j = 0; j < NUM_INTERPOLATORS; j++) {
4303 rx_mix_1_reg_2 = rx_mix_1_reg_1 + 1;
4304
4305 rx_mix_1_reg_1_val = snd_soc_read(codec,
4306 rx_mix_1_reg_1);
4307 rx_mix_1_reg_2_val = snd_soc_read(codec,
4308 rx_mix_1_reg_2);
4309
4310 if (((rx_mix_1_reg_1_val & 0x0F) == rx_mix1_inp) ||
4311 (((rx_mix_1_reg_1_val >> 4) & 0x0F)
4312 == rx_mix1_inp) ||
4313 ((rx_mix_1_reg_2_val & 0x0F) == rx_mix1_inp)) {
4314
4315 rx_fs_reg = TAIKO_A_CDC_RX1_B5_CTL + 8 * j;
4316
4317 pr_debug("%s: AIF_PB DAI(%d) connected to RX%u\n",
4318 __func__, dai->id, j + 1);
4319
4320 pr_debug("%s: set RX%u sample rate to %u\n",
4321 __func__, j + 1, sample_rate);
4322
4323 snd_soc_update_bits(codec, rx_fs_reg,
4324 0xE0, rx_fs_rate_reg_val);
4325
4326 if (comp_rx_path[j] < COMPANDER_MAX)
4327 taiko->comp_fs[comp_rx_path[j]]
4328 = compander_fs;
4329 }
Kuirong Wang94761952013-03-07 16:19:35 -08004330 if (j < 2)
Kuirong Wang906ac472012-07-09 12:54:44 -07004331 rx_mix_1_reg_1 += 3;
4332 else
4333 rx_mix_1_reg_1 += 2;
Kiran Kandic3b24402012-06-11 00:05:59 -07004334 }
4335 }
4336 return 0;
4337}
4338
Kuirong Wang906ac472012-07-09 12:54:44 -07004339static int taiko_set_decimator_rate(struct snd_soc_dai *dai,
4340 u8 tx_fs_rate_reg_val, u32 sample_rate)
Kiran Kandic3b24402012-06-11 00:05:59 -07004341{
Kuirong Wang906ac472012-07-09 12:54:44 -07004342 struct snd_soc_codec *codec = dai->codec;
4343 struct wcd9xxx_ch *ch;
4344 struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
4345 u32 tx_port;
4346 u16 tx_port_reg, tx_fs_reg;
4347 u8 tx_port_reg_val;
4348 s8 decimator;
Kiran Kandic3b24402012-06-11 00:05:59 -07004349
Kuirong Wang906ac472012-07-09 12:54:44 -07004350 list_for_each_entry(ch, &taiko->dai[dai->id].wcd9xxx_ch_list, list) {
Kiran Kandic3b24402012-06-11 00:05:59 -07004351
Kuirong Wang906ac472012-07-09 12:54:44 -07004352 tx_port = ch->port + 1;
4353 pr_debug("%s: dai->id = %d, tx_port = %d",
4354 __func__, dai->id, tx_port);
4355
4356 if ((tx_port < 1) || (tx_port > NUM_DECIMATORS)) {
4357 pr_err("%s: Invalid SLIM TX%u port. DAI ID is %d\n",
4358 __func__, tx_port, dai->id);
4359 return -EINVAL;
4360 }
4361
4362 tx_port_reg = TAIKO_A_CDC_CONN_TX_SB_B1_CTL + (tx_port - 1);
4363 tx_port_reg_val = snd_soc_read(codec, tx_port_reg);
4364
4365 decimator = 0;
4366
4367 if ((tx_port >= 1) && (tx_port <= 6)) {
4368
4369 tx_port_reg_val = tx_port_reg_val & 0x0F;
4370 if (tx_port_reg_val == 0x8)
4371 decimator = tx_port;
4372
4373 } else if ((tx_port >= 7) && (tx_port <= NUM_DECIMATORS)) {
4374
4375 tx_port_reg_val = tx_port_reg_val & 0x1F;
4376
4377 if ((tx_port_reg_val >= 0x8) &&
4378 (tx_port_reg_val <= 0x11)) {
4379
4380 decimator = (tx_port_reg_val - 0x8) + 1;
4381 }
4382 }
4383
4384 if (decimator) { /* SLIM_TX port has a DEC as input */
4385
4386 tx_fs_reg = TAIKO_A_CDC_TX1_CLK_FS_CTL +
4387 8 * (decimator - 1);
4388
4389 pr_debug("%s: set DEC%u (-> SLIM_TX%u) rate to %u\n",
4390 __func__, decimator, tx_port, sample_rate);
4391
4392 snd_soc_update_bits(codec, tx_fs_reg, 0x07,
4393 tx_fs_rate_reg_val);
4394
4395 } else {
4396 if ((tx_port_reg_val >= 0x1) &&
4397 (tx_port_reg_val <= 0x7)) {
4398
4399 pr_debug("%s: RMIX%u going to SLIM TX%u\n",
4400 __func__, tx_port_reg_val, tx_port);
4401
4402 } else if ((tx_port_reg_val >= 0x8) &&
4403 (tx_port_reg_val <= 0x11)) {
4404
4405 pr_err("%s: ERROR: Should not be here\n",
4406 __func__);
4407 pr_err("%s: ERROR: DEC connected to SLIM TX%u\n",
4408 __func__, tx_port);
4409 return -EINVAL;
4410
4411 } else if (tx_port_reg_val == 0) {
4412 pr_debug("%s: no signal to SLIM TX%u\n",
4413 __func__, tx_port);
4414 } else {
4415 pr_err("%s: ERROR: wrong signal to SLIM TX%u\n",
4416 __func__, tx_port);
4417 pr_err("%s: ERROR: wrong signal = %u\n",
4418 __func__, tx_port_reg_val);
4419 return -EINVAL;
4420 }
4421 }
Kiran Kandic3b24402012-06-11 00:05:59 -07004422 }
Kiran Kandic3b24402012-06-11 00:05:59 -07004423 return 0;
4424}
4425
Patrick Laiff5a5782013-05-05 00:13:00 -07004426static void taiko_set_rxsb_port_format(struct snd_pcm_hw_params *params,
4427 struct snd_soc_dai *dai)
4428{
4429 struct snd_soc_codec *codec = dai->codec;
4430 struct taiko_priv *taiko_p = snd_soc_codec_get_drvdata(codec);
4431 struct wcd9xxx_codec_dai_data *cdc_dai;
4432 struct wcd9xxx_ch *ch;
4433 int port;
4434 u8 bit_sel;
4435 u16 sb_ctl_reg, field_shift;
4436
4437 switch (params_format(params)) {
4438 case SNDRV_PCM_FORMAT_S16_LE:
4439 bit_sel = 0x2;
4440 taiko_p->dai[dai->id].bit_width = 16;
4441 break;
4442 case SNDRV_PCM_FORMAT_S24_LE:
4443 bit_sel = 0x0;
4444 taiko_p->dai[dai->id].bit_width = 24;
4445 break;
4446 default:
4447 dev_err(codec->dev, "Invalid format\n");
4448 return;
4449 }
4450
4451 cdc_dai = &taiko_p->dai[dai->id];
4452
4453 list_for_each_entry(ch, &cdc_dai->wcd9xxx_ch_list, list) {
4454 port = wcd9xxx_get_slave_port(ch->ch_num);
4455
4456 if (IS_ERR_VALUE(port) ||
4457 !TAIKO_VALIDATE_RX_SBPORT_RANGE(port)) {
4458 dev_warn(codec->dev,
4459 "%s: invalid port ID %d returned for RX DAI\n",
4460 __func__, port);
4461 return;
4462 }
4463
4464 port = TAIKO_CONVERT_RX_SBPORT_ID(port);
4465
4466 if (port <= 3) {
4467 sb_ctl_reg = TAIKO_A_CDC_CONN_RX_SB_B1_CTL;
4468 field_shift = port << 1;
4469 } else if (port <= 6) {
4470 sb_ctl_reg = TAIKO_A_CDC_CONN_RX_SB_B2_CTL;
4471 field_shift = (port - 4) << 1;
4472 } else { /* should not happen */
4473 dev_warn(codec->dev,
4474 "%s: bad port ID %d\n", __func__, port);
4475 return;
4476 }
4477
4478 dev_dbg(codec->dev, "%s: sb_ctl_reg %x field_shift %x\n",
4479 __func__, sb_ctl_reg, field_shift);
4480 snd_soc_update_bits(codec, sb_ctl_reg, 0x3 << field_shift,
4481 bit_sel << field_shift);
4482 }
4483}
4484
Kiran Kandic3b24402012-06-11 00:05:59 -07004485static int taiko_hw_params(struct snd_pcm_substream *substream,
4486 struct snd_pcm_hw_params *params,
4487 struct snd_soc_dai *dai)
4488{
4489 struct snd_soc_codec *codec = dai->codec;
4490 struct taiko_priv *taiko = snd_soc_codec_get_drvdata(dai->codec);
Kuirong Wang906ac472012-07-09 12:54:44 -07004491 u8 tx_fs_rate, rx_fs_rate;
Kiran Kandic3b24402012-06-11 00:05:59 -07004492 u32 compander_fs;
Kuirong Wang906ac472012-07-09 12:54:44 -07004493 int ret;
Kiran Kandic3b24402012-06-11 00:05:59 -07004494
4495 pr_debug("%s: dai_name = %s DAI-ID %x rate %d num_ch %d\n", __func__,
4496 dai->name, dai->id, params_rate(params),
4497 params_channels(params));
4498
4499 switch (params_rate(params)) {
4500 case 8000:
4501 tx_fs_rate = 0x00;
4502 rx_fs_rate = 0x00;
4503 compander_fs = COMPANDER_FS_8KHZ;
4504 break;
4505 case 16000:
4506 tx_fs_rate = 0x01;
4507 rx_fs_rate = 0x20;
4508 compander_fs = COMPANDER_FS_16KHZ;
4509 break;
4510 case 32000:
4511 tx_fs_rate = 0x02;
4512 rx_fs_rate = 0x40;
4513 compander_fs = COMPANDER_FS_32KHZ;
4514 break;
4515 case 48000:
4516 tx_fs_rate = 0x03;
4517 rx_fs_rate = 0x60;
4518 compander_fs = COMPANDER_FS_48KHZ;
4519 break;
4520 case 96000:
4521 tx_fs_rate = 0x04;
4522 rx_fs_rate = 0x80;
4523 compander_fs = COMPANDER_FS_96KHZ;
4524 break;
4525 case 192000:
4526 tx_fs_rate = 0x05;
4527 rx_fs_rate = 0xA0;
4528 compander_fs = COMPANDER_FS_192KHZ;
4529 break;
4530 default:
4531 pr_err("%s: Invalid sampling rate %d\n", __func__,
Kuirong Wang906ac472012-07-09 12:54:44 -07004532 params_rate(params));
Kiran Kandic3b24402012-06-11 00:05:59 -07004533 return -EINVAL;
4534 }
4535
Kuirong Wang906ac472012-07-09 12:54:44 -07004536 switch (substream->stream) {
4537 case SNDRV_PCM_STREAM_CAPTURE:
Gopikrishnaiah Anandana2627572013-02-26 13:30:50 -05004538 if (dai->id != AIF4_VIFEED) {
4539 ret = taiko_set_decimator_rate(dai, tx_fs_rate,
4540 params_rate(params));
4541 if (ret < 0) {
4542 pr_err("%s: set decimator rate failed %d\n",
4543 __func__, ret);
4544 return ret;
4545 }
Kiran Kandic3b24402012-06-11 00:05:59 -07004546 }
Kuirong Wang906ac472012-07-09 12:54:44 -07004547
Kiran Kandic3b24402012-06-11 00:05:59 -07004548 if (taiko->intf_type == WCD9XXX_INTERFACE_TYPE_I2C) {
4549 switch (params_format(params)) {
4550 case SNDRV_PCM_FORMAT_S16_LE:
4551 snd_soc_update_bits(codec,
4552 TAIKO_A_CDC_CLK_TX_I2S_CTL,
4553 0x20, 0x20);
4554 break;
4555 case SNDRV_PCM_FORMAT_S32_LE:
4556 snd_soc_update_bits(codec,
4557 TAIKO_A_CDC_CLK_TX_I2S_CTL,
4558 0x20, 0x00);
4559 break;
4560 default:
4561 pr_err("invalid format\n");
4562 break;
4563 }
4564 snd_soc_update_bits(codec, TAIKO_A_CDC_CLK_TX_I2S_CTL,
Kuirong Wang906ac472012-07-09 12:54:44 -07004565 0x07, tx_fs_rate);
Kiran Kandic3b24402012-06-11 00:05:59 -07004566 } else {
Kuirong Wang906ac472012-07-09 12:54:44 -07004567 taiko->dai[dai->id].rate = params_rate(params);
Kiran Kandic3b24402012-06-11 00:05:59 -07004568 }
Kuirong Wang906ac472012-07-09 12:54:44 -07004569 break;
Kiran Kandic3b24402012-06-11 00:05:59 -07004570
Kuirong Wang906ac472012-07-09 12:54:44 -07004571 case SNDRV_PCM_STREAM_PLAYBACK:
4572 ret = taiko_set_interpolator_rate(dai, rx_fs_rate,
4573 compander_fs,
4574 params_rate(params));
4575 if (ret < 0) {
4576 pr_err("%s: set decimator rate failed %d\n", __func__,
4577 ret);
4578 return ret;
Kiran Kandic3b24402012-06-11 00:05:59 -07004579 }
4580 if (taiko->intf_type == WCD9XXX_INTERFACE_TYPE_I2C) {
4581 switch (params_format(params)) {
4582 case SNDRV_PCM_FORMAT_S16_LE:
4583 snd_soc_update_bits(codec,
4584 TAIKO_A_CDC_CLK_RX_I2S_CTL,
4585 0x20, 0x20);
4586 break;
4587 case SNDRV_PCM_FORMAT_S32_LE:
4588 snd_soc_update_bits(codec,
4589 TAIKO_A_CDC_CLK_RX_I2S_CTL,
4590 0x20, 0x00);
4591 break;
4592 default:
4593 pr_err("invalid format\n");
4594 break;
4595 }
4596 snd_soc_update_bits(codec, TAIKO_A_CDC_CLK_RX_I2S_CTL,
Kuirong Wang906ac472012-07-09 12:54:44 -07004597 0x03, (rx_fs_rate >> 0x05));
Kiran Kandic3b24402012-06-11 00:05:59 -07004598 } else {
Patrick Laiff5a5782013-05-05 00:13:00 -07004599 taiko_set_rxsb_port_format(params, dai);
Kuirong Wang906ac472012-07-09 12:54:44 -07004600 taiko->dai[dai->id].rate = params_rate(params);
Kiran Kandic3b24402012-06-11 00:05:59 -07004601 }
Kuirong Wang906ac472012-07-09 12:54:44 -07004602 break;
4603 default:
4604 pr_err("%s: Invalid stream type %d\n", __func__,
4605 substream->stream);
4606 return -EINVAL;
Kiran Kandic3b24402012-06-11 00:05:59 -07004607 }
4608
4609 return 0;
4610}
4611
4612static struct snd_soc_dai_ops taiko_dai_ops = {
4613 .startup = taiko_startup,
4614 .shutdown = taiko_shutdown,
4615 .hw_params = taiko_hw_params,
4616 .set_sysclk = taiko_set_dai_sysclk,
4617 .set_fmt = taiko_set_dai_fmt,
4618 .set_channel_map = taiko_set_channel_map,
4619 .get_channel_map = taiko_get_channel_map,
4620};
4621
4622static struct snd_soc_dai_driver taiko_dai[] = {
4623 {
4624 .name = "taiko_rx1",
4625 .id = AIF1_PB,
4626 .playback = {
4627 .stream_name = "AIF1 Playback",
4628 .rates = WCD9320_RATES,
Bhalchandra Gajare5b40c532013-02-19 13:36:47 -08004629 .formats = TAIKO_FORMATS_S16_S24_LE,
Kiran Kandic3b24402012-06-11 00:05:59 -07004630 .rate_max = 192000,
4631 .rate_min = 8000,
4632 .channels_min = 1,
4633 .channels_max = 2,
4634 },
4635 .ops = &taiko_dai_ops,
4636 },
4637 {
4638 .name = "taiko_tx1",
4639 .id = AIF1_CAP,
4640 .capture = {
4641 .stream_name = "AIF1 Capture",
4642 .rates = WCD9320_RATES,
4643 .formats = TAIKO_FORMATS,
4644 .rate_max = 192000,
4645 .rate_min = 8000,
4646 .channels_min = 1,
4647 .channels_max = 4,
4648 },
4649 .ops = &taiko_dai_ops,
4650 },
4651 {
4652 .name = "taiko_rx2",
4653 .id = AIF2_PB,
4654 .playback = {
4655 .stream_name = "AIF2 Playback",
4656 .rates = WCD9320_RATES,
Bhalchandra Gajare5b40c532013-02-19 13:36:47 -08004657 .formats = TAIKO_FORMATS_S16_S24_LE,
Kiran Kandic3b24402012-06-11 00:05:59 -07004658 .rate_min = 8000,
4659 .rate_max = 192000,
4660 .channels_min = 1,
4661 .channels_max = 2,
4662 },
4663 .ops = &taiko_dai_ops,
4664 },
4665 {
4666 .name = "taiko_tx2",
4667 .id = AIF2_CAP,
4668 .capture = {
4669 .stream_name = "AIF2 Capture",
4670 .rates = WCD9320_RATES,
4671 .formats = TAIKO_FORMATS,
4672 .rate_max = 192000,
4673 .rate_min = 8000,
4674 .channels_min = 1,
Ravit Dennis895a5572013-06-05 16:34:42 +03004675 .channels_max = 8,
Kiran Kandic3b24402012-06-11 00:05:59 -07004676 },
4677 .ops = &taiko_dai_ops,
4678 },
4679 {
4680 .name = "taiko_tx3",
4681 .id = AIF3_CAP,
4682 .capture = {
4683 .stream_name = "AIF3 Capture",
4684 .rates = WCD9320_RATES,
4685 .formats = TAIKO_FORMATS,
4686 .rate_max = 48000,
4687 .rate_min = 8000,
4688 .channels_min = 1,
4689 .channels_max = 2,
4690 },
4691 .ops = &taiko_dai_ops,
4692 },
4693 {
4694 .name = "taiko_rx3",
4695 .id = AIF3_PB,
4696 .playback = {
4697 .stream_name = "AIF3 Playback",
4698 .rates = WCD9320_RATES,
Bhalchandra Gajare5b40c532013-02-19 13:36:47 -08004699 .formats = TAIKO_FORMATS_S16_S24_LE,
Kiran Kandic3b24402012-06-11 00:05:59 -07004700 .rate_min = 8000,
4701 .rate_max = 192000,
4702 .channels_min = 1,
4703 .channels_max = 2,
4704 },
4705 .ops = &taiko_dai_ops,
4706 },
Gopikrishnaiah Anandana2627572013-02-26 13:30:50 -05004707 {
4708 .name = "taiko_vifeedback",
4709 .id = AIF4_VIFEED,
4710 .capture = {
4711 .stream_name = "VIfeed",
4712 .rates = SNDRV_PCM_RATE_48000,
4713 .formats = TAIKO_FORMATS,
4714 .rate_max = 48000,
4715 .rate_min = 48000,
4716 .channels_min = 2,
4717 .channels_max = 2,
4718 },
4719 .ops = &taiko_dai_ops,
4720 },
Joonwoo Park1d05bb92013-03-07 16:55:06 -08004721 {
4722 .name = "taiko_mad1",
4723 .id = AIF4_MAD_TX,
4724 .capture = {
4725 .stream_name = "AIF4 MAD TX",
4726 .rates = SNDRV_PCM_RATE_16000,
4727 .formats = TAIKO_FORMATS,
4728 .rate_min = 16000,
4729 .rate_max = 16000,
4730 .channels_min = 1,
4731 .channels_max = 1,
4732 },
4733 .ops = &taiko_dai_ops,
4734 },
Kiran Kandic3b24402012-06-11 00:05:59 -07004735};
4736
4737static struct snd_soc_dai_driver taiko_i2s_dai[] = {
4738 {
4739 .name = "taiko_i2s_rx1",
Kuirong Wang906ac472012-07-09 12:54:44 -07004740 .id = AIF1_PB,
Kiran Kandic3b24402012-06-11 00:05:59 -07004741 .playback = {
4742 .stream_name = "AIF1 Playback",
4743 .rates = WCD9320_RATES,
4744 .formats = TAIKO_FORMATS,
4745 .rate_max = 192000,
4746 .rate_min = 8000,
4747 .channels_min = 1,
4748 .channels_max = 4,
4749 },
4750 .ops = &taiko_dai_ops,
4751 },
4752 {
4753 .name = "taiko_i2s_tx1",
Kuirong Wang906ac472012-07-09 12:54:44 -07004754 .id = AIF1_CAP,
Kiran Kandic3b24402012-06-11 00:05:59 -07004755 .capture = {
4756 .stream_name = "AIF1 Capture",
4757 .rates = WCD9320_RATES,
4758 .formats = TAIKO_FORMATS,
4759 .rate_max = 192000,
4760 .rate_min = 8000,
4761 .channels_min = 1,
4762 .channels_max = 4,
4763 },
4764 .ops = &taiko_dai_ops,
4765 },
Venkat Sudhir994193b2012-12-17 17:30:51 -08004766 {
4767 .name = "taiko_i2s_rx2",
4768 .id = AIF1_PB,
4769 .playback = {
4770 .stream_name = "AIF2 Playback",
4771 .rates = WCD9320_RATES,
4772 .formats = TAIKO_FORMATS,
4773 .rate_max = 192000,
4774 .rate_min = 8000,
4775 .channels_min = 1,
4776 .channels_max = 4,
4777 },
4778 .ops = &taiko_dai_ops,
4779 },
4780 {
4781 .name = "taiko_i2s_tx2",
4782 .id = AIF1_CAP,
4783 .capture = {
4784 .stream_name = "AIF2 Capture",
4785 .rates = WCD9320_RATES,
4786 .formats = TAIKO_FORMATS,
4787 .rate_max = 192000,
4788 .rate_min = 8000,
4789 .channels_min = 1,
4790 .channels_max = 4,
4791 },
4792 .ops = &taiko_dai_ops,
4793 },
Kiran Kandic3b24402012-06-11 00:05:59 -07004794};
4795
Joonwoo Park9bbb4d12012-11-09 19:58:11 -08004796static int taiko_codec_enable_slim_chmask(struct wcd9xxx_codec_dai_data *dai,
4797 bool up)
4798{
4799 int ret = 0;
4800 struct wcd9xxx_ch *ch;
4801
4802 if (up) {
4803 list_for_each_entry(ch, &dai->wcd9xxx_ch_list, list) {
4804 ret = wcd9xxx_get_slave_port(ch->ch_num);
4805 if (ret < 0) {
4806 pr_err("%s: Invalid slave port ID: %d\n",
4807 __func__, ret);
4808 ret = -EINVAL;
4809 } else {
4810 set_bit(ret, &dai->ch_mask);
4811 }
4812 }
4813 } else {
4814 ret = wait_event_timeout(dai->dai_wait, (dai->ch_mask == 0),
4815 msecs_to_jiffies(
4816 TAIKO_SLIM_CLOSE_TIMEOUT));
4817 if (!ret) {
4818 pr_err("%s: Slim close tx/rx wait timeout\n", __func__);
4819 ret = -ETIMEDOUT;
4820 } else {
4821 ret = 0;
4822 }
4823 }
4824 return ret;
4825}
4826
Kiran Kandic3b24402012-06-11 00:05:59 -07004827static int taiko_codec_enable_slimrx(struct snd_soc_dapm_widget *w,
Kuirong Wang906ac472012-07-09 12:54:44 -07004828 struct snd_kcontrol *kcontrol,
4829 int event)
Kiran Kandic3b24402012-06-11 00:05:59 -07004830{
Kuirong Wang906ac472012-07-09 12:54:44 -07004831 struct wcd9xxx *core;
Kiran Kandic3b24402012-06-11 00:05:59 -07004832 struct snd_soc_codec *codec = w->codec;
4833 struct taiko_priv *taiko_p = snd_soc_codec_get_drvdata(codec);
Joonwoo Park9bbb4d12012-11-09 19:58:11 -08004834 int ret = 0;
Kuirong Wang906ac472012-07-09 12:54:44 -07004835 struct wcd9xxx_codec_dai_data *dai;
4836
4837 core = dev_get_drvdata(codec->dev->parent);
4838
4839 pr_debug("%s: event called! codec name %s num_dai %d\n"
4840 "stream name %s event %d\n",
4841 __func__, w->codec->name, w->codec->num_dai, w->sname, event);
4842
Kiran Kandic3b24402012-06-11 00:05:59 -07004843 /* Execute the callback only if interface type is slimbus */
4844 if (taiko_p->intf_type != WCD9XXX_INTERFACE_TYPE_SLIMBUS)
4845 return 0;
4846
Kuirong Wang906ac472012-07-09 12:54:44 -07004847 dai = &taiko_p->dai[w->shift];
4848 pr_debug("%s: w->name %s w->shift %d event %d\n",
4849 __func__, w->name, w->shift, event);
Kiran Kandic3b24402012-06-11 00:05:59 -07004850
4851 switch (event) {
4852 case SND_SOC_DAPM_POST_PMU:
Joonwoo Park9bbb4d12012-11-09 19:58:11 -08004853 (void) taiko_codec_enable_slim_chmask(dai, true);
Kuirong Wang906ac472012-07-09 12:54:44 -07004854 ret = wcd9xxx_cfg_slim_sch_rx(core, &dai->wcd9xxx_ch_list,
4855 dai->rate, dai->bit_width,
4856 &dai->grph);
Kiran Kandic3b24402012-06-11 00:05:59 -07004857 break;
4858 case SND_SOC_DAPM_POST_PMD:
Kuirong Wang906ac472012-07-09 12:54:44 -07004859 ret = wcd9xxx_close_slim_sch_rx(core, &dai->wcd9xxx_ch_list,
4860 dai->grph);
Joonwoo Park9bbb4d12012-11-09 19:58:11 -08004861 ret = taiko_codec_enable_slim_chmask(dai, false);
4862 if (ret < 0) {
4863 ret = wcd9xxx_disconnect_port(core,
4864 &dai->wcd9xxx_ch_list,
4865 dai->grph);
4866 pr_debug("%s: Disconnect RX port, ret = %d\n",
4867 __func__, ret);
4868 }
Kuirong Wang906ac472012-07-09 12:54:44 -07004869 break;
Kiran Kandic3b24402012-06-11 00:05:59 -07004870 }
4871 return ret;
4872}
4873
Gopikrishnaiah Anandana2627572013-02-26 13:30:50 -05004874static int taiko_codec_enable_slimvi_feedback(struct snd_soc_dapm_widget *w,
4875 struct snd_kcontrol *kcontrol,
4876 int event)
4877{
4878 struct wcd9xxx *core = NULL;
4879 struct snd_soc_codec *codec = NULL;
4880 struct taiko_priv *taiko_p = NULL;
4881 u32 ret = 0;
4882 struct wcd9xxx_codec_dai_data *dai = NULL;
4883
4884 if (!w || !w->codec) {
4885 pr_err("%s invalid params\n", __func__);
4886 return -EINVAL;
4887 }
4888 codec = w->codec;
4889 taiko_p = snd_soc_codec_get_drvdata(codec);
4890 core = dev_get_drvdata(codec->dev->parent);
4891
4892 pr_debug("%s: event called! codec name %s num_dai %d stream name %s\n",
4893 __func__, w->codec->name, w->codec->num_dai, w->sname);
4894
4895 /* Execute the callback only if interface type is slimbus */
4896 if (taiko_p->intf_type != WCD9XXX_INTERFACE_TYPE_SLIMBUS) {
4897 pr_err("%s Interface is not correct", __func__);
4898 return 0;
4899 }
4900
4901 pr_debug("%s(): w->name %s event %d w->shift %d\n",
4902 __func__, w->name, event, w->shift);
4903 if (w->shift != AIF4_VIFEED) {
4904 pr_err("%s Error in enabling the tx path\n", __func__);
4905 ret = -EINVAL;
4906 goto out_vi;
4907 }
4908 dai = &taiko_p->dai[w->shift];
4909 switch (event) {
4910 case SND_SOC_DAPM_POST_PMU:
Gopikrishnaiah Anandana2627572013-02-26 13:30:50 -05004911 /*Enable V&I sensing*/
4912 snd_soc_update_bits(codec, TAIKO_A_SPKR_PROT_EN,
4913 0x88, 0x88);
4914 /*Enable spkr VI clocks*/
4915 snd_soc_update_bits(codec,
4916 TAIKO_A_CDC_CLK_TX_CLK_EN_B2_CTL, 0xC, 0xC);
4917 /*Enable Voltage Decimator*/
4918 snd_soc_update_bits(codec,
4919 TAIKO_A_CDC_CONN_TX_SB_B9_CTL, 0x1F, 0x12);
4920 /*Enable Current Decimator*/
4921 snd_soc_update_bits(codec,
4922 TAIKO_A_CDC_CONN_TX_SB_B10_CTL, 0x1F, 0x13);
Gopikrishnaiah Anandand3b89c02013-04-16 11:22:15 -04004923 (void) taiko_codec_enable_slim_chmask(dai, true);
Gopikrishnaiah Anandana2627572013-02-26 13:30:50 -05004924 ret = wcd9xxx_cfg_slim_sch_tx(core, &dai->wcd9xxx_ch_list,
4925 dai->rate, dai->bit_width,
4926 &dai->grph);
4927 break;
4928 case SND_SOC_DAPM_POST_PMD:
4929 ret = wcd9xxx_close_slim_sch_tx(core, &dai->wcd9xxx_ch_list,
4930 dai->grph);
4931 if (ret)
4932 pr_err("%s error in close_slim_sch_tx %d\n",
4933 __func__, ret);
4934 /*Disable Voltage decimator*/
4935 snd_soc_update_bits(codec,
4936 TAIKO_A_CDC_CONN_TX_SB_B9_CTL, 0x1F, 0x0);
4937 /*Disable Current decimator*/
4938 snd_soc_update_bits(codec,
4939 TAIKO_A_CDC_CONN_TX_SB_B10_CTL, 0x1F, 0x0);
4940 /*Disable spkr VI clocks*/
4941 snd_soc_update_bits(codec, TAIKO_A_CDC_CLK_TX_CLK_EN_B2_CTL,
4942 0xC, 0x0);
4943 /*Disable V&I sensing*/
4944 snd_soc_update_bits(codec, TAIKO_A_SPKR_PROT_EN,
4945 0x88, 0x00);
Gopikrishnaiah Anandana2627572013-02-26 13:30:50 -05004946 break;
4947 }
4948out_vi:
4949 return ret;
4950}
4951
Kiran Kandic3b24402012-06-11 00:05:59 -07004952static int taiko_codec_enable_slimtx(struct snd_soc_dapm_widget *w,
Kuirong Wang906ac472012-07-09 12:54:44 -07004953 struct snd_kcontrol *kcontrol,
4954 int event)
Kiran Kandic3b24402012-06-11 00:05:59 -07004955{
Kuirong Wang906ac472012-07-09 12:54:44 -07004956 struct wcd9xxx *core;
Kiran Kandic3b24402012-06-11 00:05:59 -07004957 struct snd_soc_codec *codec = w->codec;
4958 struct taiko_priv *taiko_p = snd_soc_codec_get_drvdata(codec);
Kiran Kandic3b24402012-06-11 00:05:59 -07004959 u32 ret = 0;
Kuirong Wang906ac472012-07-09 12:54:44 -07004960 struct wcd9xxx_codec_dai_data *dai;
Kiran Kandic3b24402012-06-11 00:05:59 -07004961
Kuirong Wang906ac472012-07-09 12:54:44 -07004962 core = dev_get_drvdata(codec->dev->parent);
4963
4964 pr_debug("%s: event called! codec name %s num_dai %d stream name %s\n",
4965 __func__, w->codec->name, w->codec->num_dai, w->sname);
Kiran Kandic3b24402012-06-11 00:05:59 -07004966
4967 /* Execute the callback only if interface type is slimbus */
4968 if (taiko_p->intf_type != WCD9XXX_INTERFACE_TYPE_SLIMBUS)
4969 return 0;
4970
Kuirong Wang906ac472012-07-09 12:54:44 -07004971 pr_debug("%s(): w->name %s event %d w->shift %d\n",
4972 __func__, w->name, event, w->shift);
Kiran Kandic3b24402012-06-11 00:05:59 -07004973
Kuirong Wang906ac472012-07-09 12:54:44 -07004974 dai = &taiko_p->dai[w->shift];
Kiran Kandic3b24402012-06-11 00:05:59 -07004975 switch (event) {
4976 case SND_SOC_DAPM_POST_PMU:
Joonwoo Park9bbb4d12012-11-09 19:58:11 -08004977 (void) taiko_codec_enable_slim_chmask(dai, true);
Kuirong Wang906ac472012-07-09 12:54:44 -07004978 ret = wcd9xxx_cfg_slim_sch_tx(core, &dai->wcd9xxx_ch_list,
4979 dai->rate, dai->bit_width,
4980 &dai->grph);
Kiran Kandic3b24402012-06-11 00:05:59 -07004981 break;
4982 case SND_SOC_DAPM_POST_PMD:
Kuirong Wang906ac472012-07-09 12:54:44 -07004983 ret = wcd9xxx_close_slim_sch_tx(core, &dai->wcd9xxx_ch_list,
4984 dai->grph);
Joonwoo Park9bbb4d12012-11-09 19:58:11 -08004985 ret = taiko_codec_enable_slim_chmask(dai, false);
4986 if (ret < 0) {
4987 ret = wcd9xxx_disconnect_port(core,
4988 &dai->wcd9xxx_ch_list,
4989 dai->grph);
4990 pr_debug("%s: Disconnect RX port, ret = %d\n",
4991 __func__, ret);
4992 }
Kuirong Wang906ac472012-07-09 12:54:44 -07004993 break;
Kiran Kandic3b24402012-06-11 00:05:59 -07004994 }
4995 return ret;
4996}
4997
Kiran Kandi4c56c592012-07-25 11:04:55 -07004998static int taiko_codec_enable_ear_pa(struct snd_soc_dapm_widget *w,
4999 struct snd_kcontrol *kcontrol, int event)
5000{
5001 struct snd_soc_codec *codec = w->codec;
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08005002 struct taiko_priv *taiko_p = snd_soc_codec_get_drvdata(codec);
Kiran Kandi4c56c592012-07-25 11:04:55 -07005003
5004 pr_debug("%s %s %d\n", __func__, w->name, event);
5005
5006 switch (event) {
Kiran Kandi4c56c592012-07-25 11:04:55 -07005007 case SND_SOC_DAPM_POST_PMU:
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08005008 wcd9xxx_clsh_fsm(codec, &taiko_p->clsh_d,
5009 WCD9XXX_CLSH_STATE_EAR,
5010 WCD9XXX_CLSH_REQ_ENABLE,
5011 WCD9XXX_CLSH_EVENT_POST_PA);
Kiran Kandi4c56c592012-07-25 11:04:55 -07005012
5013 usleep_range(5000, 5000);
5014 break;
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08005015 case SND_SOC_DAPM_POST_PMD:
5016 wcd9xxx_clsh_fsm(codec, &taiko_p->clsh_d,
5017 WCD9XXX_CLSH_STATE_EAR,
5018 WCD9XXX_CLSH_REQ_DISABLE,
5019 WCD9XXX_CLSH_EVENT_POST_PA);
5020 usleep_range(5000, 5000);
5021 }
5022 return 0;
5023}
5024
5025static int taiko_codec_ear_dac_event(struct snd_soc_dapm_widget *w,
5026 struct snd_kcontrol *kcontrol, int event)
5027{
5028 struct snd_soc_codec *codec = w->codec;
5029 struct taiko_priv *taiko_p = snd_soc_codec_get_drvdata(codec);
5030
5031 pr_debug("%s %s %d\n", __func__, w->name, event);
5032
5033 switch (event) {
5034 case SND_SOC_DAPM_PRE_PMU:
5035 wcd9xxx_clsh_fsm(codec, &taiko_p->clsh_d,
5036 WCD9XXX_CLSH_STATE_EAR,
5037 WCD9XXX_CLSH_REQ_ENABLE,
5038 WCD9XXX_CLSH_EVENT_PRE_DAC);
5039 break;
5040 }
5041
5042 return 0;
5043}
5044
5045static int taiko_codec_dsm_mux_event(struct snd_soc_dapm_widget *w,
5046 struct snd_kcontrol *kcontrol, int event)
5047{
5048 struct snd_soc_codec *codec = w->codec;
5049 u8 reg_val, zoh_mux_val = 0x00;
5050
5051 pr_debug("%s: event = %d\n", __func__, event);
5052
5053 switch (event) {
5054 case SND_SOC_DAPM_POST_PMU:
5055 reg_val = snd_soc_read(codec, TAIKO_A_CDC_CONN_CLSH_CTL);
5056
5057 if ((reg_val & 0x30) == 0x10)
5058 zoh_mux_val = 0x04;
5059 else if ((reg_val & 0x30) == 0x20)
5060 zoh_mux_val = 0x08;
5061
5062 if (zoh_mux_val != 0x00)
5063 snd_soc_update_bits(codec,
5064 TAIKO_A_CDC_CONN_CLSH_CTL,
5065 0x0C, zoh_mux_val);
5066 break;
5067
5068 case SND_SOC_DAPM_POST_PMD:
5069 snd_soc_update_bits(codec, TAIKO_A_CDC_CONN_CLSH_CTL,
5070 0x0C, 0x00);
5071 break;
Kiran Kandi4c56c592012-07-25 11:04:55 -07005072 }
5073 return 0;
5074}
5075
Damir Didjusto2cb06bd2013-01-30 23:14:55 -08005076static int taiko_codec_enable_anc_ear(struct snd_soc_dapm_widget *w,
5077 struct snd_kcontrol *kcontrol, int event)
5078{
5079 struct snd_soc_codec *codec = w->codec;
5080 int ret = 0;
5081
5082 switch (event) {
5083 case SND_SOC_DAPM_PRE_PMU:
5084 ret = taiko_codec_enable_anc(w, kcontrol, event);
5085 msleep(50);
5086 snd_soc_update_bits(codec, TAIKO_A_RX_EAR_EN, 0x10, 0x10);
5087 break;
5088 case SND_SOC_DAPM_POST_PMU:
5089 ret = taiko_codec_enable_ear_pa(w, kcontrol, event);
5090 break;
5091 case SND_SOC_DAPM_PRE_PMD:
5092 snd_soc_update_bits(codec, TAIKO_A_RX_EAR_EN, 0x10, 0x00);
5093 msleep(40);
5094 ret |= taiko_codec_enable_anc(w, kcontrol, event);
5095 break;
5096 case SND_SOC_DAPM_POST_PMD:
5097 ret = taiko_codec_enable_ear_pa(w, kcontrol, event);
5098 break;
5099 }
5100 return ret;
5101}
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08005102
Kiran Kandic3b24402012-06-11 00:05:59 -07005103/* Todo: Have seperate dapm widgets for I2S and Slimbus.
5104 * Might Need to have callbacks registered only for slimbus
5105 */
5106static const struct snd_soc_dapm_widget taiko_dapm_widgets[] = {
5107 /*RX stuff */
5108 SND_SOC_DAPM_OUTPUT("EAR"),
5109
Kiran Kandi4c56c592012-07-25 11:04:55 -07005110 SND_SOC_DAPM_PGA_E("EAR PA", TAIKO_A_RX_EAR_EN, 4, 0, NULL, 0,
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08005111 taiko_codec_enable_ear_pa, SND_SOC_DAPM_POST_PMU |
5112 SND_SOC_DAPM_POST_PMD),
Kiran Kandic3b24402012-06-11 00:05:59 -07005113
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08005114 SND_SOC_DAPM_MIXER_E("DAC1", TAIKO_A_RX_EAR_EN, 6, 0, dac1_switch,
5115 ARRAY_SIZE(dac1_switch), taiko_codec_ear_dac_event,
5116 SND_SOC_DAPM_PRE_PMU),
Kiran Kandic3b24402012-06-11 00:05:59 -07005117
Kuirong Wang906ac472012-07-09 12:54:44 -07005118 SND_SOC_DAPM_AIF_IN_E("AIF1 PB", "AIF1 Playback", 0, SND_SOC_NOPM,
5119 AIF1_PB, 0, taiko_codec_enable_slimrx,
Kiran Kandic3b24402012-06-11 00:05:59 -07005120 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
Kuirong Wang906ac472012-07-09 12:54:44 -07005121 SND_SOC_DAPM_AIF_IN_E("AIF2 PB", "AIF2 Playback", 0, SND_SOC_NOPM,
5122 AIF2_PB, 0, taiko_codec_enable_slimrx,
Kiran Kandic3b24402012-06-11 00:05:59 -07005123 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
Kuirong Wang906ac472012-07-09 12:54:44 -07005124 SND_SOC_DAPM_AIF_IN_E("AIF3 PB", "AIF3 Playback", 0, SND_SOC_NOPM,
5125 AIF3_PB, 0, taiko_codec_enable_slimrx,
Kiran Kandic3b24402012-06-11 00:05:59 -07005126 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
5127
Kuirong Wang906ac472012-07-09 12:54:44 -07005128 SND_SOC_DAPM_MUX("SLIM RX1 MUX", SND_SOC_NOPM, TAIKO_RX1, 0,
5129 &slim_rx_mux[TAIKO_RX1]),
5130 SND_SOC_DAPM_MUX("SLIM RX2 MUX", SND_SOC_NOPM, TAIKO_RX2, 0,
5131 &slim_rx_mux[TAIKO_RX2]),
5132 SND_SOC_DAPM_MUX("SLIM RX3 MUX", SND_SOC_NOPM, TAIKO_RX3, 0,
5133 &slim_rx_mux[TAIKO_RX3]),
5134 SND_SOC_DAPM_MUX("SLIM RX4 MUX", SND_SOC_NOPM, TAIKO_RX4, 0,
5135 &slim_rx_mux[TAIKO_RX4]),
5136 SND_SOC_DAPM_MUX("SLIM RX5 MUX", SND_SOC_NOPM, TAIKO_RX5, 0,
5137 &slim_rx_mux[TAIKO_RX5]),
5138 SND_SOC_DAPM_MUX("SLIM RX6 MUX", SND_SOC_NOPM, TAIKO_RX6, 0,
5139 &slim_rx_mux[TAIKO_RX6]),
5140 SND_SOC_DAPM_MUX("SLIM RX7 MUX", SND_SOC_NOPM, TAIKO_RX7, 0,
5141 &slim_rx_mux[TAIKO_RX7]),
Kiran Kandic3b24402012-06-11 00:05:59 -07005142
Kuirong Wang906ac472012-07-09 12:54:44 -07005143 SND_SOC_DAPM_MIXER("SLIM RX1", SND_SOC_NOPM, 0, 0, NULL, 0),
5144 SND_SOC_DAPM_MIXER("SLIM RX2", SND_SOC_NOPM, 0, 0, NULL, 0),
5145 SND_SOC_DAPM_MIXER("SLIM RX3", SND_SOC_NOPM, 0, 0, NULL, 0),
5146 SND_SOC_DAPM_MIXER("SLIM RX4", SND_SOC_NOPM, 0, 0, NULL, 0),
5147 SND_SOC_DAPM_MIXER("SLIM RX5", SND_SOC_NOPM, 0, 0, NULL, 0),
5148 SND_SOC_DAPM_MIXER("SLIM RX6", SND_SOC_NOPM, 0, 0, NULL, 0),
5149 SND_SOC_DAPM_MIXER("SLIM RX7", SND_SOC_NOPM, 0, 0, NULL, 0),
Kiran Kandic3b24402012-06-11 00:05:59 -07005150
5151 /* Headphone */
5152 SND_SOC_DAPM_OUTPUT("HEADPHONE"),
5153 SND_SOC_DAPM_PGA_E("HPHL", TAIKO_A_RX_HPH_CNP_EN, 5, 0, NULL, 0,
5154 taiko_hph_pa_event, SND_SOC_DAPM_PRE_PMU |
Kiran Kandi4c56c592012-07-25 11:04:55 -07005155 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08005156 SND_SOC_DAPM_MIXER_E("HPHL DAC", TAIKO_A_RX_HPH_L_DAC_CTL, 7, 0,
5157 hphl_switch, ARRAY_SIZE(hphl_switch), taiko_hphl_dac_event,
5158 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
Kiran Kandic3b24402012-06-11 00:05:59 -07005159
5160 SND_SOC_DAPM_PGA_E("HPHR", TAIKO_A_RX_HPH_CNP_EN, 4, 0, NULL, 0,
5161 taiko_hph_pa_event, SND_SOC_DAPM_PRE_PMU |
Kiran Kandi4c56c592012-07-25 11:04:55 -07005162 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
Kiran Kandic3b24402012-06-11 00:05:59 -07005163
5164 SND_SOC_DAPM_DAC_E("HPHR DAC", NULL, TAIKO_A_RX_HPH_R_DAC_CTL, 7, 0,
5165 taiko_hphr_dac_event,
5166 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
5167
5168 /* Speaker */
5169 SND_SOC_DAPM_OUTPUT("LINEOUT1"),
5170 SND_SOC_DAPM_OUTPUT("LINEOUT2"),
5171 SND_SOC_DAPM_OUTPUT("LINEOUT3"),
5172 SND_SOC_DAPM_OUTPUT("LINEOUT4"),
Joonwoo Park7680b9f2012-07-13 11:36:48 -07005173 SND_SOC_DAPM_OUTPUT("SPK_OUT"),
Kiran Kandic3b24402012-06-11 00:05:59 -07005174
5175 SND_SOC_DAPM_PGA_E("LINEOUT1 PA", TAIKO_A_RX_LINE_CNP_EN, 0, 0, NULL,
5176 0, taiko_codec_enable_lineout, SND_SOC_DAPM_PRE_PMU |
5177 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
5178 SND_SOC_DAPM_PGA_E("LINEOUT2 PA", TAIKO_A_RX_LINE_CNP_EN, 1, 0, NULL,
5179 0, taiko_codec_enable_lineout, SND_SOC_DAPM_PRE_PMU |
5180 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
5181 SND_SOC_DAPM_PGA_E("LINEOUT3 PA", TAIKO_A_RX_LINE_CNP_EN, 2, 0, NULL,
5182 0, taiko_codec_enable_lineout, SND_SOC_DAPM_PRE_PMU |
5183 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
5184 SND_SOC_DAPM_PGA_E("LINEOUT4 PA", TAIKO_A_RX_LINE_CNP_EN, 3, 0, NULL,
5185 0, taiko_codec_enable_lineout, SND_SOC_DAPM_PRE_PMU |
5186 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
Joonwoo Park125cd4e2012-12-11 15:16:11 -08005187 SND_SOC_DAPM_PGA_E("SPK PA", SND_SOC_NOPM, 0, 0 , NULL,
5188 0, taiko_codec_enable_spk_pa,
5189 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
Kiran Kandic3b24402012-06-11 00:05:59 -07005190
5191 SND_SOC_DAPM_DAC_E("LINEOUT1 DAC", NULL, TAIKO_A_RX_LINE_1_DAC_CTL, 7, 0
5192 , taiko_lineout_dac_event,
5193 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
5194 SND_SOC_DAPM_DAC_E("LINEOUT2 DAC", NULL, TAIKO_A_RX_LINE_2_DAC_CTL, 7, 0
5195 , taiko_lineout_dac_event,
5196 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
5197 SND_SOC_DAPM_DAC_E("LINEOUT3 DAC", NULL, TAIKO_A_RX_LINE_3_DAC_CTL, 7, 0
5198 , taiko_lineout_dac_event,
5199 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
5200 SND_SOC_DAPM_SWITCH("LINEOUT3 DAC GROUND", SND_SOC_NOPM, 0, 0,
5201 &lineout3_ground_switch),
5202 SND_SOC_DAPM_DAC_E("LINEOUT4 DAC", NULL, TAIKO_A_RX_LINE_4_DAC_CTL, 7, 0
5203 , taiko_lineout_dac_event,
5204 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
5205 SND_SOC_DAPM_SWITCH("LINEOUT4 DAC GROUND", SND_SOC_NOPM, 0, 0,
5206 &lineout4_ground_switch),
5207
Joonwoo Park7680b9f2012-07-13 11:36:48 -07005208 SND_SOC_DAPM_DAC_E("SPK DAC", NULL, SND_SOC_NOPM, 0, 0,
5209 taiko_spk_dac_event,
5210 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
5211
Joonwoo Park125cd4e2012-12-11 15:16:11 -08005212 SND_SOC_DAPM_SUPPLY("VDD_SPKDRV", SND_SOC_NOPM, 0, 0,
5213 taiko_codec_enable_vdd_spkr,
5214 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
5215
Kiran Kandid2b46332012-10-05 12:04:00 -07005216 SND_SOC_DAPM_MIXER("RX1 MIX1", SND_SOC_NOPM, 0, 0, NULL, 0),
5217 SND_SOC_DAPM_MIXER("RX2 MIX1", SND_SOC_NOPM, 0, 0, NULL, 0),
5218 SND_SOC_DAPM_MIXER("RX7 MIX1", SND_SOC_NOPM, 0, 0, NULL, 0),
5219
Kiran Kandic3b24402012-06-11 00:05:59 -07005220 SND_SOC_DAPM_MIXER_E("RX1 MIX2", TAIKO_A_CDC_CLK_RX_B1_CTL, 0, 0, NULL,
Kiran Kandi7b7d2ff2012-09-14 14:52:14 -07005221 0, taiko_codec_enable_interpolator, SND_SOC_DAPM_PRE_PMU |
Kiran Kandic3b24402012-06-11 00:05:59 -07005222 SND_SOC_DAPM_POST_PMU),
5223 SND_SOC_DAPM_MIXER_E("RX2 MIX2", TAIKO_A_CDC_CLK_RX_B1_CTL, 1, 0, NULL,
Kiran Kandi7b7d2ff2012-09-14 14:52:14 -07005224 0, taiko_codec_enable_interpolator, SND_SOC_DAPM_PRE_PMU |
Kiran Kandic3b24402012-06-11 00:05:59 -07005225 SND_SOC_DAPM_POST_PMU),
Kiran Kandid2b46332012-10-05 12:04:00 -07005226 SND_SOC_DAPM_MIXER_E("RX3 MIX1", TAIKO_A_CDC_CLK_RX_B1_CTL, 2, 0, NULL,
Kiran Kandi7b7d2ff2012-09-14 14:52:14 -07005227 0, taiko_codec_enable_interpolator, SND_SOC_DAPM_PRE_PMU |
Kiran Kandic3b24402012-06-11 00:05:59 -07005228 SND_SOC_DAPM_POST_PMU),
5229 SND_SOC_DAPM_MIXER_E("RX4 MIX1", TAIKO_A_CDC_CLK_RX_B1_CTL, 3, 0, NULL,
Kiran Kandi7b7d2ff2012-09-14 14:52:14 -07005230 0, taiko_codec_enable_interpolator, SND_SOC_DAPM_PRE_PMU |
Kiran Kandic3b24402012-06-11 00:05:59 -07005231 SND_SOC_DAPM_POST_PMU),
5232 SND_SOC_DAPM_MIXER_E("RX5 MIX1", TAIKO_A_CDC_CLK_RX_B1_CTL, 4, 0, NULL,
Kiran Kandi7b7d2ff2012-09-14 14:52:14 -07005233 0, taiko_codec_enable_interpolator, SND_SOC_DAPM_PRE_PMU |
Kiran Kandic3b24402012-06-11 00:05:59 -07005234 SND_SOC_DAPM_POST_PMU),
5235 SND_SOC_DAPM_MIXER_E("RX6 MIX1", TAIKO_A_CDC_CLK_RX_B1_CTL, 5, 0, NULL,
Kiran Kandi7b7d2ff2012-09-14 14:52:14 -07005236 0, taiko_codec_enable_interpolator, SND_SOC_DAPM_PRE_PMU |
Kiran Kandic3b24402012-06-11 00:05:59 -07005237 SND_SOC_DAPM_POST_PMU),
Kiran Kandid2b46332012-10-05 12:04:00 -07005238 SND_SOC_DAPM_MIXER_E("RX7 MIX2", TAIKO_A_CDC_CLK_RX_B1_CTL, 6, 0, NULL,
Kiran Kandi7b7d2ff2012-09-14 14:52:14 -07005239 0, taiko_codec_enable_interpolator, SND_SOC_DAPM_PRE_PMU |
Kiran Kandic3b24402012-06-11 00:05:59 -07005240 SND_SOC_DAPM_POST_PMU),
5241
Kiran Kandic3b24402012-06-11 00:05:59 -07005242
5243 SND_SOC_DAPM_MIXER("RX1 CHAIN", TAIKO_A_CDC_RX1_B6_CTL, 5, 0, NULL, 0),
5244 SND_SOC_DAPM_MIXER("RX2 CHAIN", TAIKO_A_CDC_RX2_B6_CTL, 5, 0, NULL, 0),
5245
5246 SND_SOC_DAPM_MUX("RX1 MIX1 INP1", SND_SOC_NOPM, 0, 0,
5247 &rx_mix1_inp1_mux),
5248 SND_SOC_DAPM_MUX("RX1 MIX1 INP2", SND_SOC_NOPM, 0, 0,
5249 &rx_mix1_inp2_mux),
5250 SND_SOC_DAPM_MUX("RX1 MIX1 INP3", SND_SOC_NOPM, 0, 0,
5251 &rx_mix1_inp3_mux),
5252 SND_SOC_DAPM_MUX("RX2 MIX1 INP1", SND_SOC_NOPM, 0, 0,
5253 &rx2_mix1_inp1_mux),
5254 SND_SOC_DAPM_MUX("RX2 MIX1 INP2", SND_SOC_NOPM, 0, 0,
5255 &rx2_mix1_inp2_mux),
5256 SND_SOC_DAPM_MUX("RX3 MIX1 INP1", SND_SOC_NOPM, 0, 0,
5257 &rx3_mix1_inp1_mux),
5258 SND_SOC_DAPM_MUX("RX3 MIX1 INP2", SND_SOC_NOPM, 0, 0,
5259 &rx3_mix1_inp2_mux),
5260 SND_SOC_DAPM_MUX("RX4 MIX1 INP1", SND_SOC_NOPM, 0, 0,
5261 &rx4_mix1_inp1_mux),
5262 SND_SOC_DAPM_MUX("RX4 MIX1 INP2", SND_SOC_NOPM, 0, 0,
5263 &rx4_mix1_inp2_mux),
5264 SND_SOC_DAPM_MUX("RX5 MIX1 INP1", SND_SOC_NOPM, 0, 0,
5265 &rx5_mix1_inp1_mux),
5266 SND_SOC_DAPM_MUX("RX5 MIX1 INP2", SND_SOC_NOPM, 0, 0,
5267 &rx5_mix1_inp2_mux),
5268 SND_SOC_DAPM_MUX("RX6 MIX1 INP1", SND_SOC_NOPM, 0, 0,
5269 &rx6_mix1_inp1_mux),
5270 SND_SOC_DAPM_MUX("RX6 MIX1 INP2", SND_SOC_NOPM, 0, 0,
5271 &rx6_mix1_inp2_mux),
5272 SND_SOC_DAPM_MUX("RX7 MIX1 INP1", SND_SOC_NOPM, 0, 0,
5273 &rx7_mix1_inp1_mux),
5274 SND_SOC_DAPM_MUX("RX7 MIX1 INP2", SND_SOC_NOPM, 0, 0,
5275 &rx7_mix1_inp2_mux),
5276 SND_SOC_DAPM_MUX("RX1 MIX2 INP1", SND_SOC_NOPM, 0, 0,
5277 &rx1_mix2_inp1_mux),
5278 SND_SOC_DAPM_MUX("RX1 MIX2 INP2", SND_SOC_NOPM, 0, 0,
5279 &rx1_mix2_inp2_mux),
5280 SND_SOC_DAPM_MUX("RX2 MIX2 INP1", SND_SOC_NOPM, 0, 0,
5281 &rx2_mix2_inp1_mux),
5282 SND_SOC_DAPM_MUX("RX2 MIX2 INP2", SND_SOC_NOPM, 0, 0,
5283 &rx2_mix2_inp2_mux),
5284 SND_SOC_DAPM_MUX("RX7 MIX2 INP1", SND_SOC_NOPM, 0, 0,
5285 &rx7_mix2_inp1_mux),
5286 SND_SOC_DAPM_MUX("RX7 MIX2 INP2", SND_SOC_NOPM, 0, 0,
5287 &rx7_mix2_inp2_mux),
5288
Tanya Finkeldaaa6d12012-10-25 11:22:48 +02005289 SND_SOC_DAPM_MUX("RDAC5 MUX", SND_SOC_NOPM, 0, 0,
5290 &rx_dac5_mux),
5291 SND_SOC_DAPM_MUX("RDAC7 MUX", SND_SOC_NOPM, 0, 0,
5292 &rx_dac7_mux),
5293
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08005294 SND_SOC_DAPM_MUX_E("CLASS_H_DSM MUX", SND_SOC_NOPM, 0, 0,
5295 &class_h_dsm_mux, taiko_codec_dsm_mux_event,
5296 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
Kiran Kandi4c56c592012-07-25 11:04:55 -07005297
Kiran Kandic3b24402012-06-11 00:05:59 -07005298 SND_SOC_DAPM_SUPPLY("RX_BIAS", SND_SOC_NOPM, 0, 0,
5299 taiko_codec_enable_rx_bias, SND_SOC_DAPM_PRE_PMU |
5300 SND_SOC_DAPM_POST_PMD),
5301
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08005302 SND_SOC_DAPM_SUPPLY("CDC_I2S_RX_CONN", WCD9XXX_A_CDC_CLK_OTHR_CTL, 5, 0,
Joonwoo Park559a5bf2013-02-15 14:46:36 -08005303 NULL, 0),
5304
Kiran Kandic3b24402012-06-11 00:05:59 -07005305 /* TX */
5306
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08005307 SND_SOC_DAPM_SUPPLY("CDC_CONN", WCD9XXX_A_CDC_CLK_OTHR_CTL, 2, 0, NULL,
Kiran Kandic3b24402012-06-11 00:05:59 -07005308 0),
5309
Joonwoo Parkccccba72013-04-26 11:19:46 -07005310 SND_SOC_DAPM_SUPPLY("LDO_H", SND_SOC_NOPM, 7, 0,
5311 taiko_codec_enable_ldo_h,
5312 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
5313 /*
5314 * DAPM 'LDO_H Standalone' is to be powered by mbhc driver after
5315 * acquring codec_resource lock.
5316 * So call __taiko_codec_enable_ldo_h instead and avoid deadlock.
5317 */
5318 SND_SOC_DAPM_SUPPLY("LDO_H Standalone", SND_SOC_NOPM, 7, 0,
5319 __taiko_codec_enable_ldo_h,
5320 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
Kiran Kandic3b24402012-06-11 00:05:59 -07005321
Joonwoo Parkc7731432012-10-17 12:41:44 -07005322 SND_SOC_DAPM_SUPPLY("COMP0_CLK", SND_SOC_NOPM, 0, 0,
Kiran Kandic3b24402012-06-11 00:05:59 -07005323 taiko_config_compander, SND_SOC_DAPM_PRE_PMU |
Bhalchandra Gajareed090e62013-03-29 16:11:49 -07005324 SND_SOC_DAPM_PRE_PMD),
Joonwoo Parkc7731432012-10-17 12:41:44 -07005325 SND_SOC_DAPM_SUPPLY("COMP1_CLK", SND_SOC_NOPM, 1, 0,
5326 taiko_config_compander, SND_SOC_DAPM_PRE_PMU |
Bhalchandra Gajareed090e62013-03-29 16:11:49 -07005327 SND_SOC_DAPM_PRE_PMD),
Joonwoo Parkc7731432012-10-17 12:41:44 -07005328 SND_SOC_DAPM_SUPPLY("COMP2_CLK", SND_SOC_NOPM, 2, 0,
Kiran Kandic3b24402012-06-11 00:05:59 -07005329 taiko_config_compander, SND_SOC_DAPM_PRE_PMU |
Bhalchandra Gajareed090e62013-03-29 16:11:49 -07005330 SND_SOC_DAPM_PRE_PMD),
Kiran Kandic3b24402012-06-11 00:05:59 -07005331
5332
5333 SND_SOC_DAPM_INPUT("AMIC1"),
Joonwoo Park3699ca32013-02-08 12:06:15 -08005334 SND_SOC_DAPM_MICBIAS_E("MIC BIAS1 External", SND_SOC_NOPM, 7, 0,
5335 taiko_codec_enable_micbias,
5336 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
5337 SND_SOC_DAPM_POST_PMD),
5338 SND_SOC_DAPM_MICBIAS_E("MIC BIAS1 Internal1", SND_SOC_NOPM, 7, 0,
5339 taiko_codec_enable_micbias,
5340 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
5341 SND_SOC_DAPM_POST_PMD),
5342 SND_SOC_DAPM_MICBIAS_E("MIC BIAS1 Internal2", SND_SOC_NOPM, 7, 0,
5343 taiko_codec_enable_micbias,
5344 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
5345 SND_SOC_DAPM_POST_PMD),
Kiran Kandic3b24402012-06-11 00:05:59 -07005346
5347 SND_SOC_DAPM_INPUT("AMIC3"),
Kiran Kandic3b24402012-06-11 00:05:59 -07005348
5349 SND_SOC_DAPM_INPUT("AMIC4"),
Kiran Kandic3b24402012-06-11 00:05:59 -07005350
5351 SND_SOC_DAPM_INPUT("AMIC5"),
Kiran Kandic3b24402012-06-11 00:05:59 -07005352
5353 SND_SOC_DAPM_INPUT("AMIC6"),
Kiran Kandic3b24402012-06-11 00:05:59 -07005354
5355 SND_SOC_DAPM_MUX_E("DEC1 MUX", TAIKO_A_CDC_CLK_TX_CLK_EN_B1_CTL, 0, 0,
5356 &dec1_mux, taiko_codec_enable_dec,
5357 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
5358 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
5359
5360 SND_SOC_DAPM_MUX_E("DEC2 MUX", TAIKO_A_CDC_CLK_TX_CLK_EN_B1_CTL, 1, 0,
5361 &dec2_mux, taiko_codec_enable_dec,
5362 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
5363 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
5364
5365 SND_SOC_DAPM_MUX_E("DEC3 MUX", TAIKO_A_CDC_CLK_TX_CLK_EN_B1_CTL, 2, 0,
5366 &dec3_mux, taiko_codec_enable_dec,
5367 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
5368 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
5369
5370 SND_SOC_DAPM_MUX_E("DEC4 MUX", TAIKO_A_CDC_CLK_TX_CLK_EN_B1_CTL, 3, 0,
5371 &dec4_mux, taiko_codec_enable_dec,
5372 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
5373 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
5374
5375 SND_SOC_DAPM_MUX_E("DEC5 MUX", TAIKO_A_CDC_CLK_TX_CLK_EN_B1_CTL, 4, 0,
5376 &dec5_mux, taiko_codec_enable_dec,
5377 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
5378 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
5379
5380 SND_SOC_DAPM_MUX_E("DEC6 MUX", TAIKO_A_CDC_CLK_TX_CLK_EN_B1_CTL, 5, 0,
5381 &dec6_mux, taiko_codec_enable_dec,
5382 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
5383 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
5384
5385 SND_SOC_DAPM_MUX_E("DEC7 MUX", TAIKO_A_CDC_CLK_TX_CLK_EN_B1_CTL, 6, 0,
5386 &dec7_mux, taiko_codec_enable_dec,
5387 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
5388 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
5389
5390 SND_SOC_DAPM_MUX_E("DEC8 MUX", TAIKO_A_CDC_CLK_TX_CLK_EN_B1_CTL, 7, 0,
5391 &dec8_mux, taiko_codec_enable_dec,
5392 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
5393 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
5394
5395 SND_SOC_DAPM_MUX_E("DEC9 MUX", TAIKO_A_CDC_CLK_TX_CLK_EN_B2_CTL, 0, 0,
5396 &dec9_mux, taiko_codec_enable_dec,
5397 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
5398 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
5399
5400 SND_SOC_DAPM_MUX_E("DEC10 MUX", TAIKO_A_CDC_CLK_TX_CLK_EN_B2_CTL, 1, 0,
5401 &dec10_mux, taiko_codec_enable_dec,
5402 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
5403 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
5404
5405 SND_SOC_DAPM_MUX("ANC1 MUX", SND_SOC_NOPM, 0, 0, &anc1_mux),
5406 SND_SOC_DAPM_MUX("ANC2 MUX", SND_SOC_NOPM, 0, 0, &anc2_mux),
5407
Damir Didjusto2cb06bd2013-01-30 23:14:55 -08005408 SND_SOC_DAPM_OUTPUT("ANC HEADPHONE"),
5409 SND_SOC_DAPM_PGA_E("ANC HPHL", SND_SOC_NOPM, 5, 0, NULL, 0,
5410 taiko_codec_enable_anc_hph,
5411 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD |
5412 SND_SOC_DAPM_POST_PMD | SND_SOC_DAPM_POST_PMU),
5413 SND_SOC_DAPM_PGA_E("ANC HPHR", SND_SOC_NOPM, 4, 0, NULL, 0,
5414 taiko_codec_enable_anc_hph, SND_SOC_DAPM_PRE_PMU |
5415 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD |
5416 SND_SOC_DAPM_POST_PMU),
5417 SND_SOC_DAPM_OUTPUT("ANC EAR"),
5418 SND_SOC_DAPM_PGA_E("ANC EAR PA", SND_SOC_NOPM, 0, 0, NULL, 0,
5419 taiko_codec_enable_anc_ear,
5420 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD |
5421 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
Kiran Kandic3b24402012-06-11 00:05:59 -07005422 SND_SOC_DAPM_MUX("ANC1 FB MUX", SND_SOC_NOPM, 0, 0, &anc1_fb_mux),
5423
5424 SND_SOC_DAPM_INPUT("AMIC2"),
Joonwoo Parkccccba72013-04-26 11:19:46 -07005425 SND_SOC_DAPM_MICBIAS_E(DAPM_MICBIAS2_EXTERNAL_STANDALONE, SND_SOC_NOPM,
5426 7, 0, taiko_codec_enable_micbias,
5427 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
5428 SND_SOC_DAPM_POST_PMD),
Joonwoo Park3699ca32013-02-08 12:06:15 -08005429 SND_SOC_DAPM_MICBIAS_E("MIC BIAS2 External", SND_SOC_NOPM, 7, 0,
5430 taiko_codec_enable_micbias,
5431 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
5432 SND_SOC_DAPM_POST_PMD),
5433 SND_SOC_DAPM_MICBIAS_E("MIC BIAS2 Internal1", SND_SOC_NOPM, 7, 0,
5434 taiko_codec_enable_micbias,
5435 SND_SOC_DAPM_PRE_PMU |
5436 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
5437 SND_SOC_DAPM_MICBIAS_E("MIC BIAS2 Internal2", SND_SOC_NOPM, 7, 0,
5438 taiko_codec_enable_micbias,
5439 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
5440 SND_SOC_DAPM_POST_PMD),
5441 SND_SOC_DAPM_MICBIAS_E("MIC BIAS2 Internal3", SND_SOC_NOPM, 7, 0,
5442 taiko_codec_enable_micbias,
5443 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
5444 SND_SOC_DAPM_POST_PMD),
5445 SND_SOC_DAPM_MICBIAS_E("MIC BIAS3 External", SND_SOC_NOPM, 7, 0,
5446 taiko_codec_enable_micbias,
5447 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
5448 SND_SOC_DAPM_POST_PMD),
5449 SND_SOC_DAPM_MICBIAS_E("MIC BIAS3 Internal1", SND_SOC_NOPM, 7, 0,
5450 taiko_codec_enable_micbias,
5451 SND_SOC_DAPM_PRE_PMU |
5452 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
5453 SND_SOC_DAPM_MICBIAS_E("MIC BIAS3 Internal2", SND_SOC_NOPM, 7, 0,
5454 taiko_codec_enable_micbias,
5455 SND_SOC_DAPM_PRE_PMU |
5456 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
5457 SND_SOC_DAPM_MICBIAS_E("MIC BIAS4 External", SND_SOC_NOPM, 7,
5458 0, taiko_codec_enable_micbias,
5459 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
5460 SND_SOC_DAPM_POST_PMD),
Kiran Kandic3b24402012-06-11 00:05:59 -07005461
Kuirong Wang906ac472012-07-09 12:54:44 -07005462 SND_SOC_DAPM_AIF_OUT_E("AIF1 CAP", "AIF1 Capture", 0, SND_SOC_NOPM,
5463 AIF1_CAP, 0, taiko_codec_enable_slimtx,
5464 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
Kiran Kandic3b24402012-06-11 00:05:59 -07005465
Kuirong Wang906ac472012-07-09 12:54:44 -07005466 SND_SOC_DAPM_AIF_OUT_E("AIF2 CAP", "AIF2 Capture", 0, SND_SOC_NOPM,
5467 AIF2_CAP, 0, taiko_codec_enable_slimtx,
5468 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
Kiran Kandic3b24402012-06-11 00:05:59 -07005469
Kuirong Wang906ac472012-07-09 12:54:44 -07005470 SND_SOC_DAPM_AIF_OUT_E("AIF3 CAP", "AIF3 Capture", 0, SND_SOC_NOPM,
5471 AIF3_CAP, 0, taiko_codec_enable_slimtx,
5472 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
Kiran Kandic3b24402012-06-11 00:05:59 -07005473
Gopikrishnaiah Anandana2627572013-02-26 13:30:50 -05005474 SND_SOC_DAPM_AIF_OUT_E("AIF4 VI", "VIfeed", 0, SND_SOC_NOPM,
5475 AIF4_VIFEED, 0, taiko_codec_enable_slimvi_feedback,
5476 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
Joonwoo Park1d05bb92013-03-07 16:55:06 -08005477 SND_SOC_DAPM_AIF_OUT_E("AIF4 MAD", "AIF4 MAD TX", 0,
Joonwoo Park9ead0e92013-03-18 11:33:33 -07005478 SND_SOC_NOPM, 0, 0,
Joonwoo Park1d05bb92013-03-07 16:55:06 -08005479 taiko_codec_enable_mad, SND_SOC_DAPM_PRE_PMU),
Joonwoo Park9ead0e92013-03-18 11:33:33 -07005480 SND_SOC_DAPM_SWITCH("MADONOFF", SND_SOC_NOPM, 0, 0,
5481 &aif4_mad_switch),
Joonwoo Park1d05bb92013-03-07 16:55:06 -08005482 SND_SOC_DAPM_INPUT("MADINPUT"),
Gopikrishnaiah Anandana2627572013-02-26 13:30:50 -05005483
Kuirong Wang906ac472012-07-09 12:54:44 -07005484 SND_SOC_DAPM_MIXER("AIF1_CAP Mixer", SND_SOC_NOPM, AIF1_CAP, 0,
5485 aif_cap_mixer, ARRAY_SIZE(aif_cap_mixer)),
Kiran Kandic3b24402012-06-11 00:05:59 -07005486
Kuirong Wang906ac472012-07-09 12:54:44 -07005487 SND_SOC_DAPM_MIXER("AIF2_CAP Mixer", SND_SOC_NOPM, AIF2_CAP, 0,
5488 aif_cap_mixer, ARRAY_SIZE(aif_cap_mixer)),
Kiran Kandic3b24402012-06-11 00:05:59 -07005489
Kuirong Wang906ac472012-07-09 12:54:44 -07005490 SND_SOC_DAPM_MIXER("AIF3_CAP Mixer", SND_SOC_NOPM, AIF3_CAP, 0,
5491 aif_cap_mixer, ARRAY_SIZE(aif_cap_mixer)),
Kiran Kandic3b24402012-06-11 00:05:59 -07005492
Kuirong Wang906ac472012-07-09 12:54:44 -07005493 SND_SOC_DAPM_MUX("SLIM TX1 MUX", SND_SOC_NOPM, TAIKO_TX1, 0,
5494 &sb_tx1_mux),
5495 SND_SOC_DAPM_MUX("SLIM TX2 MUX", SND_SOC_NOPM, TAIKO_TX2, 0,
5496 &sb_tx2_mux),
5497 SND_SOC_DAPM_MUX("SLIM TX3 MUX", SND_SOC_NOPM, TAIKO_TX3, 0,
5498 &sb_tx3_mux),
5499 SND_SOC_DAPM_MUX("SLIM TX4 MUX", SND_SOC_NOPM, TAIKO_TX4, 0,
5500 &sb_tx4_mux),
5501 SND_SOC_DAPM_MUX("SLIM TX5 MUX", SND_SOC_NOPM, TAIKO_TX5, 0,
5502 &sb_tx5_mux),
5503 SND_SOC_DAPM_MUX("SLIM TX6 MUX", SND_SOC_NOPM, TAIKO_TX6, 0,
5504 &sb_tx6_mux),
5505 SND_SOC_DAPM_MUX("SLIM TX7 MUX", SND_SOC_NOPM, TAIKO_TX7, 0,
5506 &sb_tx7_mux),
5507 SND_SOC_DAPM_MUX("SLIM TX8 MUX", SND_SOC_NOPM, TAIKO_TX8, 0,
5508 &sb_tx8_mux),
5509 SND_SOC_DAPM_MUX("SLIM TX9 MUX", SND_SOC_NOPM, TAIKO_TX9, 0,
5510 &sb_tx9_mux),
5511 SND_SOC_DAPM_MUX("SLIM TX10 MUX", SND_SOC_NOPM, TAIKO_TX10, 0,
5512 &sb_tx10_mux),
Kiran Kandic3b24402012-06-11 00:05:59 -07005513
5514 /* Digital Mic Inputs */
5515 SND_SOC_DAPM_ADC_E("DMIC1", NULL, SND_SOC_NOPM, 0, 0,
5516 taiko_codec_enable_dmic, SND_SOC_DAPM_PRE_PMU |
5517 SND_SOC_DAPM_POST_PMD),
5518
5519 SND_SOC_DAPM_ADC_E("DMIC2", NULL, SND_SOC_NOPM, 0, 0,
5520 taiko_codec_enable_dmic, SND_SOC_DAPM_PRE_PMU |
5521 SND_SOC_DAPM_POST_PMD),
5522
5523 SND_SOC_DAPM_ADC_E("DMIC3", NULL, SND_SOC_NOPM, 0, 0,
5524 taiko_codec_enable_dmic, SND_SOC_DAPM_PRE_PMU |
5525 SND_SOC_DAPM_POST_PMD),
5526
5527 SND_SOC_DAPM_ADC_E("DMIC4", NULL, SND_SOC_NOPM, 0, 0,
5528 taiko_codec_enable_dmic, SND_SOC_DAPM_PRE_PMU |
5529 SND_SOC_DAPM_POST_PMD),
5530
5531 SND_SOC_DAPM_ADC_E("DMIC5", NULL, SND_SOC_NOPM, 0, 0,
5532 taiko_codec_enable_dmic, SND_SOC_DAPM_PRE_PMU |
5533 SND_SOC_DAPM_POST_PMD),
5534 SND_SOC_DAPM_ADC_E("DMIC6", NULL, SND_SOC_NOPM, 0, 0,
5535 taiko_codec_enable_dmic, SND_SOC_DAPM_PRE_PMU |
5536 SND_SOC_DAPM_POST_PMD),
5537
5538 /* Sidetone */
5539 SND_SOC_DAPM_MUX("IIR1 INP1 MUX", SND_SOC_NOPM, 0, 0, &iir1_inp1_mux),
Kiran Kandibd85d772013-05-19 19:03:43 -07005540 SND_SOC_DAPM_MIXER("IIR1", TAIKO_A_CDC_CLK_SD_CTL, 0, 0, NULL, 0),
Kiran Kandic3b24402012-06-11 00:05:59 -07005541
Fred Oh456fcb52013-02-28 19:08:15 -08005542 SND_SOC_DAPM_MUX("IIR2 INP1 MUX", SND_SOC_NOPM, 0, 0, &iir2_inp1_mux),
Kiran Kandibd85d772013-05-19 19:03:43 -07005543 SND_SOC_DAPM_MIXER("IIR2", TAIKO_A_CDC_CLK_SD_CTL, 1, 0, NULL, 0),
Fred Oh456fcb52013-02-28 19:08:15 -08005544
Kiran Kandic3b24402012-06-11 00:05:59 -07005545 /* AUX PGA */
5546 SND_SOC_DAPM_ADC_E("AUX_PGA_Left", NULL, TAIKO_A_RX_AUX_SW_CTL, 7, 0,
5547 taiko_codec_enable_aux_pga, SND_SOC_DAPM_PRE_PMU |
5548 SND_SOC_DAPM_POST_PMD),
5549
5550 SND_SOC_DAPM_ADC_E("AUX_PGA_Right", NULL, TAIKO_A_RX_AUX_SW_CTL, 6, 0,
5551 taiko_codec_enable_aux_pga, SND_SOC_DAPM_PRE_PMU |
5552 SND_SOC_DAPM_POST_PMD),
5553
5554 /* Lineout, ear and HPH PA Mixers */
5555
5556 SND_SOC_DAPM_MIXER("EAR_PA_MIXER", SND_SOC_NOPM, 0, 0,
5557 ear_pa_mix, ARRAY_SIZE(ear_pa_mix)),
5558
5559 SND_SOC_DAPM_MIXER("HPHL_PA_MIXER", SND_SOC_NOPM, 0, 0,
5560 hphl_pa_mix, ARRAY_SIZE(hphl_pa_mix)),
5561
5562 SND_SOC_DAPM_MIXER("HPHR_PA_MIXER", SND_SOC_NOPM, 0, 0,
5563 hphr_pa_mix, ARRAY_SIZE(hphr_pa_mix)),
5564
5565 SND_SOC_DAPM_MIXER("LINEOUT1_PA_MIXER", SND_SOC_NOPM, 0, 0,
5566 lineout1_pa_mix, ARRAY_SIZE(lineout1_pa_mix)),
5567
5568 SND_SOC_DAPM_MIXER("LINEOUT2_PA_MIXER", SND_SOC_NOPM, 0, 0,
5569 lineout2_pa_mix, ARRAY_SIZE(lineout2_pa_mix)),
5570
5571 SND_SOC_DAPM_MIXER("LINEOUT3_PA_MIXER", SND_SOC_NOPM, 0, 0,
5572 lineout3_pa_mix, ARRAY_SIZE(lineout3_pa_mix)),
5573
5574 SND_SOC_DAPM_MIXER("LINEOUT4_PA_MIXER", SND_SOC_NOPM, 0, 0,
5575 lineout4_pa_mix, ARRAY_SIZE(lineout4_pa_mix)),
Kiran Kandic3b24402012-06-11 00:05:59 -07005576};
5577
Kiran Kandic3b24402012-06-11 00:05:59 -07005578static irqreturn_t taiko_slimbus_irq(int irq, void *data)
5579{
5580 struct taiko_priv *priv = data;
5581 struct snd_soc_codec *codec = priv->codec;
Joonwoo Park9bbb4d12012-11-09 19:58:11 -08005582 unsigned long status = 0;
5583 int i, j, port_id, k;
5584 u32 bit;
Kiran Kandic3b24402012-06-11 00:05:59 -07005585 u8 val;
Joonwoo Park9bbb4d12012-11-09 19:58:11 -08005586 bool tx, cleared;
Kiran Kandic3b24402012-06-11 00:05:59 -07005587
Joonwoo Park9bbb4d12012-11-09 19:58:11 -08005588 for (i = TAIKO_SLIM_PGD_PORT_INT_STATUS_RX_0, j = 0;
5589 i <= TAIKO_SLIM_PGD_PORT_INT_STATUS_TX_1; i++, j++) {
5590 val = wcd9xxx_interface_reg_read(codec->control_data, i);
5591 status |= ((u32)val << (8 * j));
5592 }
5593
5594 for_each_set_bit(j, &status, 32) {
5595 tx = (j >= 16 ? true : false);
5596 port_id = (tx ? j - 16 : j);
5597 val = wcd9xxx_interface_reg_read(codec->control_data,
5598 TAIKO_SLIM_PGD_PORT_INT_RX_SOURCE0 + j);
5599 if (val & TAIKO_SLIM_IRQ_OVERFLOW)
5600 pr_err_ratelimited(
5601 "%s: overflow error on %s port %d, value %x\n",
5602 __func__, (tx ? "TX" : "RX"), port_id, val);
5603 if (val & TAIKO_SLIM_IRQ_UNDERFLOW)
5604 pr_err_ratelimited(
5605 "%s: underflow error on %s port %d, value %x\n",
5606 __func__, (tx ? "TX" : "RX"), port_id, val);
5607 if (val & TAIKO_SLIM_IRQ_PORT_CLOSED) {
5608 /*
5609 * INT SOURCE register starts from RX to TX
5610 * but port number in the ch_mask is in opposite way
5611 */
5612 bit = (tx ? j - 16 : j + 16);
5613 pr_debug("%s: %s port %d closed value %x, bit %u\n",
5614 __func__, (tx ? "TX" : "RX"), port_id, val,
5615 bit);
5616 for (k = 0, cleared = false; k < NUM_CODEC_DAIS; k++) {
5617 pr_debug("%s: priv->dai[%d].ch_mask = 0x%lx\n",
5618 __func__, k, priv->dai[k].ch_mask);
5619 if (test_and_clear_bit(bit,
5620 &priv->dai[k].ch_mask)) {
5621 cleared = true;
5622 if (!priv->dai[k].ch_mask)
5623 wake_up(&priv->dai[k].dai_wait);
5624 /*
5625 * There are cases when multiple DAIs
5626 * might be using the same slimbus
5627 * channel. Hence don't break here.
5628 */
5629 }
5630 }
5631 WARN(!cleared,
5632 "Couldn't find slimbus %s port %d for closing\n",
5633 (tx ? "TX" : "RX"), port_id);
Kiran Kandic3b24402012-06-11 00:05:59 -07005634 }
5635 wcd9xxx_interface_reg_write(codec->control_data,
Joonwoo Park9bbb4d12012-11-09 19:58:11 -08005636 TAIKO_SLIM_PGD_PORT_INT_CLR_RX_0 +
5637 (j / 8),
5638 1 << (j % 8));
Joonwoo Parka8890262012-10-15 12:04:27 -07005639 }
Joonwoo Park9bbb4d12012-11-09 19:58:11 -08005640
Kiran Kandic3b24402012-06-11 00:05:59 -07005641 return IRQ_HANDLED;
5642}
5643
5644static int taiko_handle_pdata(struct taiko_priv *taiko)
5645{
5646 struct snd_soc_codec *codec = taiko->codec;
Joonwoo Parka8890262012-10-15 12:04:27 -07005647 struct wcd9xxx_pdata *pdata = taiko->resmgr.pdata;
Kiran Kandic3b24402012-06-11 00:05:59 -07005648 int k1, k2, k3, rc = 0;
Kiran Kandi725f8492012-08-06 13:45:16 -07005649 u8 leg_mode, txfe_bypass, txfe_buff, flag;
Kiran Kandic3b24402012-06-11 00:05:59 -07005650 u8 i = 0, j = 0;
5651 u8 val_txfe = 0, value = 0;
Damir Didjusto1a353ce2013-04-02 11:45:47 -07005652 u8 dmic_sample_rate_value = 0;
5653 u8 dmic_b1_ctl_value = 0, dmic_b2_ctl_value = 0;
5654 u8 anc_ctl_value = 0;
Kiran Kandic3b24402012-06-11 00:05:59 -07005655
5656 if (!pdata) {
Kiran Kandi725f8492012-08-06 13:45:16 -07005657 pr_err("%s: NULL pdata\n", __func__);
Kiran Kandic3b24402012-06-11 00:05:59 -07005658 rc = -ENODEV;
5659 goto done;
5660 }
5661
Kiran Kandi725f8492012-08-06 13:45:16 -07005662 leg_mode = pdata->amic_settings.legacy_mode;
5663 txfe_bypass = pdata->amic_settings.txfe_enable;
5664 txfe_buff = pdata->amic_settings.txfe_buff;
5665 flag = pdata->amic_settings.use_pdata;
5666
Kiran Kandic3b24402012-06-11 00:05:59 -07005667 /* Make sure settings are correct */
Joonwoo Parka8890262012-10-15 12:04:27 -07005668 if ((pdata->micbias.ldoh_v > WCD9XXX_LDOH_3P0_V) ||
5669 (pdata->micbias.bias1_cfilt_sel > WCD9XXX_CFILT3_SEL) ||
5670 (pdata->micbias.bias2_cfilt_sel > WCD9XXX_CFILT3_SEL) ||
5671 (pdata->micbias.bias3_cfilt_sel > WCD9XXX_CFILT3_SEL) ||
5672 (pdata->micbias.bias4_cfilt_sel > WCD9XXX_CFILT3_SEL)) {
Kiran Kandic3b24402012-06-11 00:05:59 -07005673 rc = -EINVAL;
5674 goto done;
5675 }
Kiran Kandic3b24402012-06-11 00:05:59 -07005676 /* figure out k value */
Joonwoo Parka8890262012-10-15 12:04:27 -07005677 k1 = wcd9xxx_resmgr_get_k_val(&taiko->resmgr, pdata->micbias.cfilt1_mv);
5678 k2 = wcd9xxx_resmgr_get_k_val(&taiko->resmgr, pdata->micbias.cfilt2_mv);
5679 k3 = wcd9xxx_resmgr_get_k_val(&taiko->resmgr, pdata->micbias.cfilt3_mv);
Kiran Kandic3b24402012-06-11 00:05:59 -07005680
5681 if (IS_ERR_VALUE(k1) || IS_ERR_VALUE(k2) || IS_ERR_VALUE(k3)) {
5682 rc = -EINVAL;
5683 goto done;
5684 }
Kiran Kandic3b24402012-06-11 00:05:59 -07005685 /* Set voltage level and always use LDO */
5686 snd_soc_update_bits(codec, TAIKO_A_LDO_H_MODE_1, 0x0C,
Joonwoo Parka8890262012-10-15 12:04:27 -07005687 (pdata->micbias.ldoh_v << 2));
Kiran Kandic3b24402012-06-11 00:05:59 -07005688
Joonwoo Parka8890262012-10-15 12:04:27 -07005689 snd_soc_update_bits(codec, TAIKO_A_MICB_CFILT_1_VAL, 0xFC, (k1 << 2));
5690 snd_soc_update_bits(codec, TAIKO_A_MICB_CFILT_2_VAL, 0xFC, (k2 << 2));
5691 snd_soc_update_bits(codec, TAIKO_A_MICB_CFILT_3_VAL, 0xFC, (k3 << 2));
Kiran Kandic3b24402012-06-11 00:05:59 -07005692
5693 snd_soc_update_bits(codec, TAIKO_A_MICB_1_CTL, 0x60,
Joonwoo Parka8890262012-10-15 12:04:27 -07005694 (pdata->micbias.bias1_cfilt_sel << 5));
Kiran Kandic3b24402012-06-11 00:05:59 -07005695 snd_soc_update_bits(codec, TAIKO_A_MICB_2_CTL, 0x60,
Joonwoo Parka8890262012-10-15 12:04:27 -07005696 (pdata->micbias.bias2_cfilt_sel << 5));
Kiran Kandic3b24402012-06-11 00:05:59 -07005697 snd_soc_update_bits(codec, TAIKO_A_MICB_3_CTL, 0x60,
Joonwoo Parka8890262012-10-15 12:04:27 -07005698 (pdata->micbias.bias3_cfilt_sel << 5));
5699 snd_soc_update_bits(codec, taiko->resmgr.reg_addr->micb_4_ctl, 0x60,
Kiran Kandic3b24402012-06-11 00:05:59 -07005700 (pdata->micbias.bias4_cfilt_sel << 5));
5701
5702 for (i = 0; i < 6; j++, i += 2) {
5703 if (flag & (0x01 << i)) {
5704 value = (leg_mode & (0x01 << i)) ? 0x10 : 0x00;
5705 val_txfe = (txfe_bypass & (0x01 << i)) ? 0x20 : 0x00;
5706 val_txfe = val_txfe |
5707 ((txfe_buff & (0x01 << i)) ? 0x10 : 0x00);
5708 snd_soc_update_bits(codec, TAIKO_A_TX_1_2_EN + j * 10,
5709 0x10, value);
5710 snd_soc_update_bits(codec,
5711 TAIKO_A_TX_1_2_TEST_EN + j * 10,
5712 0x30, val_txfe);
5713 }
5714 if (flag & (0x01 << (i + 1))) {
5715 value = (leg_mode & (0x01 << (i + 1))) ? 0x01 : 0x00;
5716 val_txfe = (txfe_bypass &
5717 (0x01 << (i + 1))) ? 0x02 : 0x00;
5718 val_txfe |= (txfe_buff &
5719 (0x01 << (i + 1))) ? 0x01 : 0x00;
5720 snd_soc_update_bits(codec, TAIKO_A_TX_1_2_EN + j * 10,
5721 0x01, value);
5722 snd_soc_update_bits(codec,
5723 TAIKO_A_TX_1_2_TEST_EN + j * 10,
5724 0x03, val_txfe);
5725 }
5726 }
5727 if (flag & 0x40) {
5728 value = (leg_mode & 0x40) ? 0x10 : 0x00;
5729 value = value | ((txfe_bypass & 0x40) ? 0x02 : 0x00);
5730 value = value | ((txfe_buff & 0x40) ? 0x01 : 0x00);
5731 snd_soc_update_bits(codec, TAIKO_A_TX_7_MBHC_EN,
5732 0x13, value);
5733 }
5734
5735 if (pdata->ocp.use_pdata) {
5736 /* not defined in CODEC specification */
5737 if (pdata->ocp.hph_ocp_limit == 1 ||
5738 pdata->ocp.hph_ocp_limit == 5) {
5739 rc = -EINVAL;
5740 goto done;
5741 }
5742 snd_soc_update_bits(codec, TAIKO_A_RX_COM_OCP_CTL,
5743 0x0F, pdata->ocp.num_attempts);
5744 snd_soc_write(codec, TAIKO_A_RX_COM_OCP_COUNT,
5745 ((pdata->ocp.run_time << 4) | pdata->ocp.wait_time));
5746 snd_soc_update_bits(codec, TAIKO_A_RX_HPH_OCP_CTL,
5747 0xE0, (pdata->ocp.hph_ocp_limit << 5));
5748 }
5749
5750 for (i = 0; i < ARRAY_SIZE(pdata->regulator); i++) {
Joonwoo Park448a8fc2013-04-10 15:25:58 -07005751 if (pdata->regulator[i].name &&
5752 !strncmp(pdata->regulator[i].name, "CDC_VDDA_RX", 11)) {
Kiran Kandic3b24402012-06-11 00:05:59 -07005753 if (pdata->regulator[i].min_uV == 1800000 &&
5754 pdata->regulator[i].max_uV == 1800000) {
5755 snd_soc_write(codec, TAIKO_A_BIAS_REF_CTL,
5756 0x1C);
5757 } else if (pdata->regulator[i].min_uV == 2200000 &&
5758 pdata->regulator[i].max_uV == 2200000) {
5759 snd_soc_write(codec, TAIKO_A_BIAS_REF_CTL,
5760 0x1E);
5761 } else {
5762 pr_err("%s: unsupported CDC_VDDA_RX voltage\n"
5763 "min %d, max %d\n", __func__,
5764 pdata->regulator[i].min_uV,
5765 pdata->regulator[i].max_uV);
5766 rc = -EINVAL;
5767 }
5768 break;
5769 }
5770 }
Kiran Kandi4c56c592012-07-25 11:04:55 -07005771
Joonwoo Park1848c762012-10-18 13:16:01 -07005772 /* Set micbias capless mode with tail current */
5773 value = (pdata->micbias.bias1_cap_mode == MICBIAS_EXT_BYP_CAP ?
5774 0x00 : 0x16);
5775 snd_soc_update_bits(codec, TAIKO_A_MICB_1_CTL, 0x1E, value);
5776 value = (pdata->micbias.bias2_cap_mode == MICBIAS_EXT_BYP_CAP ?
5777 0x00 : 0x16);
5778 snd_soc_update_bits(codec, TAIKO_A_MICB_2_CTL, 0x1E, value);
5779 value = (pdata->micbias.bias3_cap_mode == MICBIAS_EXT_BYP_CAP ?
5780 0x00 : 0x16);
5781 snd_soc_update_bits(codec, TAIKO_A_MICB_3_CTL, 0x1E, value);
5782 value = (pdata->micbias.bias4_cap_mode == MICBIAS_EXT_BYP_CAP ?
5783 0x00 : 0x16);
5784 snd_soc_update_bits(codec, TAIKO_A_MICB_4_CTL, 0x1E, value);
5785
Damir Didjusto1a353ce2013-04-02 11:45:47 -07005786 /* Set the DMIC sample rate */
Phani Kumar Uppalapati43bc4152013-05-24 00:44:20 -07005787 if (pdata->mclk_rate == TAIKO_MCLK_CLK_9P6MHZ) {
Damir Didjusto1a353ce2013-04-02 11:45:47 -07005788 switch (pdata->dmic_sample_rate) {
5789 case TAIKO_DMIC_SAMPLE_RATE_2P4MHZ:
5790 dmic_sample_rate_value = TAIKO_DMIC_SAMPLE_RATE_DIV_4;
5791 dmic_b1_ctl_value = TAIKO_DMIC_B1_CTL_DIV_4;
5792 dmic_b2_ctl_value = TAIKO_DMIC_B2_CTL_DIV_4;
5793 anc_ctl_value = TAIKO_ANC_DMIC_X2_OFF;
5794 break;
5795 case TAIKO_DMIC_SAMPLE_RATE_4P8MHZ:
5796 dmic_sample_rate_value = TAIKO_DMIC_SAMPLE_RATE_DIV_2;
5797 dmic_b1_ctl_value = TAIKO_DMIC_B1_CTL_DIV_2;
5798 dmic_b2_ctl_value = TAIKO_DMIC_B2_CTL_DIV_2;
5799 anc_ctl_value = TAIKO_ANC_DMIC_X2_ON;
5800 break;
5801 case TAIKO_DMIC_SAMPLE_RATE_3P2MHZ:
5802 case TAIKO_DMIC_SAMPLE_RATE_UNDEFINED:
5803 dmic_sample_rate_value = TAIKO_DMIC_SAMPLE_RATE_DIV_3;
5804 dmic_b1_ctl_value = TAIKO_DMIC_B1_CTL_DIV_3;
5805 dmic_b2_ctl_value = TAIKO_DMIC_B2_CTL_DIV_3;
5806 anc_ctl_value = TAIKO_ANC_DMIC_X2_OFF;
5807 break;
5808 default:
5809 pr_err("%s Invalid sample rate %d for mclk %d\n",
5810 __func__, pdata->dmic_sample_rate, pdata->mclk_rate);
5811 rc = -EINVAL;
5812 goto done;
5813 break;
5814 }
5815 } else if (pdata->mclk_rate == TAIKO_MCLK_CLK_12P288MHZ) {
5816 switch (pdata->dmic_sample_rate) {
5817 case TAIKO_DMIC_SAMPLE_RATE_3P072MHZ:
5818 dmic_sample_rate_value = TAIKO_DMIC_SAMPLE_RATE_DIV_4;
5819 dmic_b1_ctl_value = TAIKO_DMIC_B1_CTL_DIV_4;
5820 dmic_b2_ctl_value = TAIKO_DMIC_B2_CTL_DIV_4;
5821 anc_ctl_value = TAIKO_ANC_DMIC_X2_OFF;
5822 break;
5823 case TAIKO_DMIC_SAMPLE_RATE_6P144MHZ:
5824 dmic_sample_rate_value = TAIKO_DMIC_SAMPLE_RATE_DIV_2;
5825 dmic_b1_ctl_value = TAIKO_DMIC_B1_CTL_DIV_2;
5826 dmic_b2_ctl_value = TAIKO_DMIC_B2_CTL_DIV_2;
5827 anc_ctl_value = TAIKO_ANC_DMIC_X2_ON;
5828 break;
5829 case TAIKO_DMIC_SAMPLE_RATE_4P096MHZ:
5830 case TAIKO_DMIC_SAMPLE_RATE_UNDEFINED:
5831 dmic_sample_rate_value = TAIKO_DMIC_SAMPLE_RATE_DIV_3;
5832 dmic_b1_ctl_value = TAIKO_DMIC_B1_CTL_DIV_3;
5833 dmic_b2_ctl_value = TAIKO_DMIC_B2_CTL_DIV_3;
5834 anc_ctl_value = TAIKO_ANC_DMIC_X2_OFF;
5835 break;
5836 default:
5837 pr_err("%s Invalid sample rate %d for mclk %d\n",
5838 __func__, pdata->dmic_sample_rate, pdata->mclk_rate);
5839 rc = -EINVAL;
5840 goto done;
5841 break;
5842 }
5843 } else {
5844 pr_err("%s MCLK is not set!\n", __func__);
5845 rc = -EINVAL;
5846 goto done;
5847 }
5848
5849 snd_soc_update_bits(codec, TAIKO_A_CDC_TX1_DMIC_CTL,
5850 0x7, dmic_sample_rate_value);
5851 snd_soc_update_bits(codec, TAIKO_A_CDC_TX2_DMIC_CTL,
5852 0x7, dmic_sample_rate_value);
5853 snd_soc_update_bits(codec, TAIKO_A_CDC_TX3_DMIC_CTL,
5854 0x7, dmic_sample_rate_value);
5855 snd_soc_update_bits(codec, TAIKO_A_CDC_TX4_DMIC_CTL,
5856 0x7, dmic_sample_rate_value);
5857 snd_soc_update_bits(codec, TAIKO_A_CDC_TX5_DMIC_CTL,
5858 0x7, dmic_sample_rate_value);
5859 snd_soc_update_bits(codec, TAIKO_A_CDC_TX6_DMIC_CTL,
5860 0x7, dmic_sample_rate_value);
5861 snd_soc_update_bits(codec, TAIKO_A_CDC_TX7_DMIC_CTL,
5862 0x7, dmic_sample_rate_value);
5863 snd_soc_update_bits(codec, TAIKO_A_CDC_TX8_DMIC_CTL,
5864 0x7, dmic_sample_rate_value);
5865 snd_soc_update_bits(codec, TAIKO_A_CDC_TX9_DMIC_CTL,
5866 0x7, dmic_sample_rate_value);
5867 snd_soc_update_bits(codec, TAIKO_A_CDC_TX10_DMIC_CTL,
5868 0x7, dmic_sample_rate_value);
5869 snd_soc_update_bits(codec, TAIKO_A_CDC_CLK_DMIC_B1_CTL,
5870 0xEE, dmic_b1_ctl_value);
5871 snd_soc_update_bits(codec, TAIKO_A_CDC_CLK_DMIC_B2_CTL,
5872 0xE, dmic_b2_ctl_value);
5873 snd_soc_update_bits(codec, TAIKO_A_CDC_ANC1_B2_CTL,
5874 0x1, anc_ctl_value);
5875
Kiran Kandic3b24402012-06-11 00:05:59 -07005876done:
5877 return rc;
5878}
5879
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08005880static const struct wcd9xxx_reg_mask_val taiko_reg_defaults[] = {
Kiran Kandic3b24402012-06-11 00:05:59 -07005881
Kiran Kandi4c56c592012-07-25 11:04:55 -07005882 /* set MCLk to 9.6 */
Gopikrishnaiah Anandana8aec1f2013-01-23 14:26:27 -05005883 TAIKO_REG_VAL(TAIKO_A_CHIP_CTL, 0x02),
Kiran Kandi4c56c592012-07-25 11:04:55 -07005884 TAIKO_REG_VAL(TAIKO_A_CDC_CLK_POWER_CTL, 0x03),
Kiran Kandic3b24402012-06-11 00:05:59 -07005885
Kiran Kandi4c56c592012-07-25 11:04:55 -07005886 /* EAR PA deafults */
5887 TAIKO_REG_VAL(TAIKO_A_RX_EAR_CMBUFF, 0x05),
Kiran Kandic3b24402012-06-11 00:05:59 -07005888
Kiran Kandi4c56c592012-07-25 11:04:55 -07005889 /* RX deafults */
Kiran Kandic3b24402012-06-11 00:05:59 -07005890 TAIKO_REG_VAL(TAIKO_A_CDC_RX1_B5_CTL, 0x78),
5891 TAIKO_REG_VAL(TAIKO_A_CDC_RX2_B5_CTL, 0x78),
5892 TAIKO_REG_VAL(TAIKO_A_CDC_RX3_B5_CTL, 0x78),
5893 TAIKO_REG_VAL(TAIKO_A_CDC_RX4_B5_CTL, 0x78),
5894 TAIKO_REG_VAL(TAIKO_A_CDC_RX5_B5_CTL, 0x78),
5895 TAIKO_REG_VAL(TAIKO_A_CDC_RX6_B5_CTL, 0x78),
5896 TAIKO_REG_VAL(TAIKO_A_CDC_RX7_B5_CTL, 0x78),
5897
Kiran Kandi4c56c592012-07-25 11:04:55 -07005898 /* RX1 and RX2 defaults */
Kiran Kandic3b24402012-06-11 00:05:59 -07005899 TAIKO_REG_VAL(TAIKO_A_CDC_RX1_B6_CTL, 0xA0),
5900 TAIKO_REG_VAL(TAIKO_A_CDC_RX2_B6_CTL, 0xA0),
5901
Kiran Kandi4c56c592012-07-25 11:04:55 -07005902 /* RX3 to RX7 defaults */
Kiran Kandic3b24402012-06-11 00:05:59 -07005903 TAIKO_REG_VAL(TAIKO_A_CDC_RX3_B6_CTL, 0x80),
5904 TAIKO_REG_VAL(TAIKO_A_CDC_RX4_B6_CTL, 0x80),
5905 TAIKO_REG_VAL(TAIKO_A_CDC_RX5_B6_CTL, 0x80),
5906 TAIKO_REG_VAL(TAIKO_A_CDC_RX6_B6_CTL, 0x80),
5907 TAIKO_REG_VAL(TAIKO_A_CDC_RX7_B6_CTL, 0x80),
Joonwoo Park1d05bb92013-03-07 16:55:06 -08005908
5909 /* MAD registers */
5910 TAIKO_REG_VAL(TAIKO_A_MAD_ANA_CTRL, 0xF1),
5911 TAIKO_REG_VAL(TAIKO_A_CDC_MAD_MAIN_CTL_1, 0x00),
5912 TAIKO_REG_VAL(TAIKO_A_CDC_MAD_MAIN_CTL_2, 0x00),
5913 TAIKO_REG_VAL(TAIKO_A_CDC_MAD_AUDIO_CTL_1, 0x00),
5914 /* Set SAMPLE_TX_EN bit */
5915 TAIKO_REG_VAL(TAIKO_A_CDC_MAD_AUDIO_CTL_2, 0x03),
5916 TAIKO_REG_VAL(TAIKO_A_CDC_MAD_AUDIO_CTL_3, 0x00),
5917 TAIKO_REG_VAL(TAIKO_A_CDC_MAD_AUDIO_CTL_4, 0x00),
5918 TAIKO_REG_VAL(TAIKO_A_CDC_MAD_AUDIO_CTL_5, 0x00),
5919 TAIKO_REG_VAL(TAIKO_A_CDC_MAD_AUDIO_CTL_6, 0x00),
5920 TAIKO_REG_VAL(TAIKO_A_CDC_MAD_AUDIO_CTL_7, 0x00),
5921 TAIKO_REG_VAL(TAIKO_A_CDC_MAD_AUDIO_CTL_8, 0x00),
5922 TAIKO_REG_VAL(TAIKO_A_CDC_MAD_AUDIO_IIR_CTL_PTR, 0x00),
5923 TAIKO_REG_VAL(TAIKO_A_CDC_MAD_AUDIO_IIR_CTL_VAL, 0x40),
5924 TAIKO_REG_VAL(TAIKO_A_CDC_DEBUG_B7_CTL, 0x00),
5925 TAIKO_REG_VAL(TAIKO_A_CDC_CLK_OTHR_RESET_B1_CTL, 0x00),
5926 TAIKO_REG_VAL(TAIKO_A_CDC_CLK_OTHR_CTL, 0x00),
5927 TAIKO_REG_VAL(TAIKO_A_CDC_CONN_MAD, 0x01),
Bhalchandra Gajareafdb1b12013-06-10 13:45:28 -07005928
5929 /* Set HPH Path to low power mode */
5930 TAIKO_REG_VAL(TAIKO_A_RX_HPH_BIAS_PA, 0x55),
Kiran Kandic3b24402012-06-11 00:05:59 -07005931};
5932
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08005933static const struct wcd9xxx_reg_mask_val taiko_1_0_reg_defaults[] = {
Kiran Kandi7b7d2ff2012-09-14 14:52:14 -07005934 /*
5935 * The following only need to be written for Taiko 1.0 parts.
5936 * Taiko 2.0 will have appropriate defaults for these registers.
5937 */
Joonwoo Park559a5bf2013-02-15 14:46:36 -08005938
5939 /* BUCK default */
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08005940 TAIKO_REG_VAL(WCD9XXX_A_BUCK_CTRL_CCL_4, 0x50),
5941
5942 /* Required defaults for class H operation */
5943 TAIKO_REG_VAL(TAIKO_A_RX_HPH_CHOP_CTL, 0xF4),
5944 TAIKO_REG_VAL(TAIKO_A_BIAS_CURR_CTL_2, 0x08),
5945 TAIKO_REG_VAL(WCD9XXX_A_BUCK_CTRL_CCL_1, 0x5B),
5946 TAIKO_REG_VAL(WCD9XXX_A_BUCK_CTRL_CCL_3, 0x60),
Joonwoo Park559a5bf2013-02-15 14:46:36 -08005947
Kiran Kandi7b7d2ff2012-09-14 14:52:14 -07005948 /* Choose max non-overlap time for NCP */
5949 TAIKO_REG_VAL(TAIKO_A_NCP_CLK, 0xFC),
5950 /* Use 25mV/50mV for deltap/m to reduce ripple */
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08005951 TAIKO_REG_VAL(WCD9XXX_A_BUCK_CTRL_VCL_1, 0x08),
Kiran Kandi7b7d2ff2012-09-14 14:52:14 -07005952 /*
5953 * Set DISABLE_MODE_SEL<1:0> to 0b10 (disable PWM in auto mode).
5954 * Note that the other bits of this register will be changed during
5955 * Rx PA bring up.
5956 */
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08005957 TAIKO_REG_VAL(WCD9XXX_A_BUCK_MODE_3, 0xCE),
Kiran Kandi7b7d2ff2012-09-14 14:52:14 -07005958 /*Reduce EAR DAC bias to 70% */
5959 TAIKO_REG_VAL(TAIKO_A_RX_EAR_BIAS_PA, 0x76),
5960 /* Reduce LINE DAC bias to 70% */
5961 TAIKO_REG_VAL(TAIKO_A_RX_LINE_BIAS_PA, 0x78),
Joonwoo Parkd87ec4c2012-10-30 15:44:18 -07005962
5963 /*
5964 * There is a diode to pull down the micbias while doing
5965 * insertion detection. This diode can cause leakage.
5966 * Set bit 0 to 1 to prevent leakage.
5967 * Setting this bit of micbias 2 prevents leakage for all other micbias.
5968 */
5969 TAIKO_REG_VAL(TAIKO_A_MICB_2_MBHC, 0x41),
Joonwoo Park3c7bca62012-10-31 12:44:23 -07005970
5971 /* Disable TX7 internal biasing path which can cause leakage */
5972 TAIKO_REG_VAL(TAIKO_A_TX_SUP_SWITCH_CTRL_1, 0xBF),
Joonwoo Park03604052012-11-06 18:40:25 -08005973 /* Enable MICB 4 VDDIO switch to prevent leakage */
5974 TAIKO_REG_VAL(TAIKO_A_MICB_4_MBHC, 0x81),
Joonwoo Park125cd4e2012-12-11 15:16:11 -08005975
5976 /* Close leakage on the spkdrv */
5977 TAIKO_REG_VAL(TAIKO_A_SPKR_DRV_DBG_PWRSTG, 0x24),
Kiran Kandi7b7d2ff2012-09-14 14:52:14 -07005978};
5979
Joonwoo Park559a5bf2013-02-15 14:46:36 -08005980/*
5981 * Don't update TAIKO_A_CHIP_CTL, TAIKO_A_BUCK_CTRL_CCL_1 and
5982 * TAIKO_A_RX_EAR_CMBUFF as those are updated in taiko_reg_defaults
5983 */
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08005984static const struct wcd9xxx_reg_mask_val taiko_2_0_reg_defaults[] = {
Joonwoo Park559a5bf2013-02-15 14:46:36 -08005985 TAIKO_REG_VAL(TAIKO_A_CDC_TX_1_GAIN, 0x2),
5986 TAIKO_REG_VAL(TAIKO_A_CDC_TX_2_GAIN, 0x2),
5987 TAIKO_REG_VAL(TAIKO_A_CDC_TX_1_2_ADC_IB, 0x44),
5988 TAIKO_REG_VAL(TAIKO_A_CDC_TX_3_GAIN, 0x2),
5989 TAIKO_REG_VAL(TAIKO_A_CDC_TX_4_GAIN, 0x2),
5990 TAIKO_REG_VAL(TAIKO_A_CDC_TX_3_4_ADC_IB, 0x44),
5991 TAIKO_REG_VAL(TAIKO_A_CDC_TX_5_GAIN, 0x2),
5992 TAIKO_REG_VAL(TAIKO_A_CDC_TX_6_GAIN, 0x2),
5993 TAIKO_REG_VAL(TAIKO_A_CDC_TX_5_6_ADC_IB, 0x44),
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08005994 TAIKO_REG_VAL(WCD9XXX_A_BUCK_MODE_3, 0xCE),
5995 TAIKO_REG_VAL(WCD9XXX_A_BUCK_CTRL_VCL_1, 0x8),
5996 TAIKO_REG_VAL(WCD9XXX_A_BUCK_CTRL_CCL_4, 0x51),
Joonwoo Park559a5bf2013-02-15 14:46:36 -08005997 TAIKO_REG_VAL(TAIKO_A_NCP_DTEST, 0x10),
5998 TAIKO_REG_VAL(TAIKO_A_RX_HPH_CHOP_CTL, 0xA4),
Joonwoo Park559a5bf2013-02-15 14:46:36 -08005999 TAIKO_REG_VAL(TAIKO_A_RX_HPH_OCP_CTL, 0x69),
6000 TAIKO_REG_VAL(TAIKO_A_RX_HPH_CNP_WG_CTL, 0xDA),
6001 TAIKO_REG_VAL(TAIKO_A_RX_HPH_CNP_WG_TIME, 0x15),
6002 TAIKO_REG_VAL(TAIKO_A_RX_EAR_BIAS_PA, 0x76),
6003 TAIKO_REG_VAL(TAIKO_A_RX_EAR_CNP, 0xC0),
6004 TAIKO_REG_VAL(TAIKO_A_RX_LINE_BIAS_PA, 0x78),
6005 TAIKO_REG_VAL(TAIKO_A_RX_LINE_1_TEST, 0x2),
6006 TAIKO_REG_VAL(TAIKO_A_RX_LINE_2_TEST, 0x2),
6007 TAIKO_REG_VAL(TAIKO_A_RX_LINE_3_TEST, 0x2),
6008 TAIKO_REG_VAL(TAIKO_A_RX_LINE_4_TEST, 0x2),
6009 TAIKO_REG_VAL(TAIKO_A_SPKR_DRV_OCP_CTL, 0x97),
6010 TAIKO_REG_VAL(TAIKO_A_SPKR_DRV_CLIP_DET, 0x1),
6011 TAIKO_REG_VAL(TAIKO_A_SPKR_DRV_IEC, 0x0),
6012 TAIKO_REG_VAL(TAIKO_A_CDC_TX1_MUX_CTL, 0x48),
6013 TAIKO_REG_VAL(TAIKO_A_CDC_TX2_MUX_CTL, 0x48),
6014 TAIKO_REG_VAL(TAIKO_A_CDC_TX3_MUX_CTL, 0x48),
6015 TAIKO_REG_VAL(TAIKO_A_CDC_TX4_MUX_CTL, 0x48),
6016 TAIKO_REG_VAL(TAIKO_A_CDC_TX5_MUX_CTL, 0x48),
6017 TAIKO_REG_VAL(TAIKO_A_CDC_TX6_MUX_CTL, 0x48),
6018 TAIKO_REG_VAL(TAIKO_A_CDC_TX7_MUX_CTL, 0x48),
6019 TAIKO_REG_VAL(TAIKO_A_CDC_TX8_MUX_CTL, 0x48),
6020 TAIKO_REG_VAL(TAIKO_A_CDC_TX9_MUX_CTL, 0x48),
6021 TAIKO_REG_VAL(TAIKO_A_CDC_TX10_MUX_CTL, 0x48),
6022 TAIKO_REG_VAL(TAIKO_A_CDC_RX1_B4_CTL, 0x8),
Joonwoo Parkdbbdac02013-03-21 19:24:31 -07006023 TAIKO_REG_VAL(TAIKO_A_CDC_RX2_B4_CTL, 0x8),
6024 TAIKO_REG_VAL(TAIKO_A_CDC_RX3_B4_CTL, 0x8),
6025 TAIKO_REG_VAL(TAIKO_A_CDC_RX4_B4_CTL, 0x8),
6026 TAIKO_REG_VAL(TAIKO_A_CDC_RX5_B4_CTL, 0x8),
6027 TAIKO_REG_VAL(TAIKO_A_CDC_RX6_B4_CTL, 0x8),
6028 TAIKO_REG_VAL(TAIKO_A_CDC_RX7_B4_CTL, 0x8),
Joonwoo Park559a5bf2013-02-15 14:46:36 -08006029 TAIKO_REG_VAL(TAIKO_A_CDC_VBAT_GAIN_UPD_MON, 0x0),
6030 TAIKO_REG_VAL(TAIKO_A_CDC_PA_RAMP_B1_CTL, 0x0),
6031 TAIKO_REG_VAL(TAIKO_A_CDC_PA_RAMP_B2_CTL, 0x0),
6032 TAIKO_REG_VAL(TAIKO_A_CDC_PA_RAMP_B3_CTL, 0x0),
6033 TAIKO_REG_VAL(TAIKO_A_CDC_PA_RAMP_B4_CTL, 0x0),
6034 TAIKO_REG_VAL(TAIKO_A_CDC_SPKR_CLIPDET_B1_CTL, 0x0),
6035 TAIKO_REG_VAL(TAIKO_A_CDC_COMP0_B4_CTL, 0x37),
6036 TAIKO_REG_VAL(TAIKO_A_CDC_COMP0_B5_CTL, 0x7f),
6037};
6038
Kiran Kandic3b24402012-06-11 00:05:59 -07006039static void taiko_update_reg_defaults(struct snd_soc_codec *codec)
6040{
6041 u32 i;
Kiran Kandi7b7d2ff2012-09-14 14:52:14 -07006042 struct wcd9xxx *taiko_core = dev_get_drvdata(codec->dev->parent);
Kiran Kandic3b24402012-06-11 00:05:59 -07006043
Kiran Kandi7b7d2ff2012-09-14 14:52:14 -07006044 for (i = 0; i < ARRAY_SIZE(taiko_reg_defaults); i++)
6045 snd_soc_write(codec, taiko_reg_defaults[i].reg,
Joonwoo Park559a5bf2013-02-15 14:46:36 -08006046 taiko_reg_defaults[i].val);
Kiran Kandi7b7d2ff2012-09-14 14:52:14 -07006047
6048 if (TAIKO_IS_1_0(taiko_core->version)) {
6049 for (i = 0; i < ARRAY_SIZE(taiko_1_0_reg_defaults); i++)
6050 snd_soc_write(codec, taiko_1_0_reg_defaults[i].reg,
Joonwoo Park559a5bf2013-02-15 14:46:36 -08006051 taiko_1_0_reg_defaults[i].val);
6052 if (spkr_drv_wrnd == 1)
6053 snd_soc_write(codec, TAIKO_A_SPKR_DRV_EN, 0xEF);
6054 } else {
6055 for (i = 0; i < ARRAY_SIZE(taiko_2_0_reg_defaults); i++)
6056 snd_soc_write(codec, taiko_2_0_reg_defaults[i].reg,
6057 taiko_2_0_reg_defaults[i].val);
Joonwoo Park125cd4e2012-12-11 15:16:11 -08006058 spkr_drv_wrnd = -1;
Joonwoo Park559a5bf2013-02-15 14:46:36 -08006059 }
Kiran Kandic3b24402012-06-11 00:05:59 -07006060}
6061
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08006062static const struct wcd9xxx_reg_mask_val taiko_codec_reg_init_val[] = {
Kiran Kandic3b24402012-06-11 00:05:59 -07006063 /* Initialize current threshold to 350MA
6064 * number of wait and run cycles to 4096
6065 */
Kiran Kandi7b7d2ff2012-09-14 14:52:14 -07006066 {TAIKO_A_RX_HPH_OCP_CTL, 0xE1, 0x61},
Kiran Kandic3b24402012-06-11 00:05:59 -07006067 {TAIKO_A_RX_COM_OCP_COUNT, 0xFF, 0xFF},
Patrick Lai92833bf2012-12-01 10:31:35 -08006068 {TAIKO_A_RX_HPH_L_TEST, 0x01, 0x01},
6069 {TAIKO_A_RX_HPH_R_TEST, 0x01, 0x01},
Kiran Kandic3b24402012-06-11 00:05:59 -07006070
Kiran Kandic3b24402012-06-11 00:05:59 -07006071 /* Initialize gain registers to use register gain */
Kiran Kandi4c56c592012-07-25 11:04:55 -07006072 {TAIKO_A_RX_HPH_L_GAIN, 0x20, 0x20},
6073 {TAIKO_A_RX_HPH_R_GAIN, 0x20, 0x20},
6074 {TAIKO_A_RX_LINE_1_GAIN, 0x20, 0x20},
6075 {TAIKO_A_RX_LINE_2_GAIN, 0x20, 0x20},
6076 {TAIKO_A_RX_LINE_3_GAIN, 0x20, 0x20},
6077 {TAIKO_A_RX_LINE_4_GAIN, 0x20, 0x20},
Joonwoo Parkc7731432012-10-17 12:41:44 -07006078 {TAIKO_A_SPKR_DRV_GAIN, 0x04, 0x04},
Kiran Kandic3b24402012-06-11 00:05:59 -07006079
Kiran Kandic3b24402012-06-11 00:05:59 -07006080 /* Use 16 bit sample size for TX1 to TX6 */
6081 {TAIKO_A_CDC_CONN_TX_SB_B1_CTL, 0x30, 0x20},
6082 {TAIKO_A_CDC_CONN_TX_SB_B2_CTL, 0x30, 0x20},
6083 {TAIKO_A_CDC_CONN_TX_SB_B3_CTL, 0x30, 0x20},
6084 {TAIKO_A_CDC_CONN_TX_SB_B4_CTL, 0x30, 0x20},
6085 {TAIKO_A_CDC_CONN_TX_SB_B5_CTL, 0x30, 0x20},
6086 {TAIKO_A_CDC_CONN_TX_SB_B6_CTL, 0x30, 0x20},
6087
6088 /* Use 16 bit sample size for TX7 to TX10 */
6089 {TAIKO_A_CDC_CONN_TX_SB_B7_CTL, 0x60, 0x40},
6090 {TAIKO_A_CDC_CONN_TX_SB_B8_CTL, 0x60, 0x40},
6091 {TAIKO_A_CDC_CONN_TX_SB_B9_CTL, 0x60, 0x40},
6092 {TAIKO_A_CDC_CONN_TX_SB_B10_CTL, 0x60, 0x40},
6093
Kiran Kandic3b24402012-06-11 00:05:59 -07006094 /*enable HPF filter for TX paths */
6095 {TAIKO_A_CDC_TX1_MUX_CTL, 0x8, 0x0},
6096 {TAIKO_A_CDC_TX2_MUX_CTL, 0x8, 0x0},
6097 {TAIKO_A_CDC_TX3_MUX_CTL, 0x8, 0x0},
6098 {TAIKO_A_CDC_TX4_MUX_CTL, 0x8, 0x0},
6099 {TAIKO_A_CDC_TX5_MUX_CTL, 0x8, 0x0},
6100 {TAIKO_A_CDC_TX6_MUX_CTL, 0x8, 0x0},
6101 {TAIKO_A_CDC_TX7_MUX_CTL, 0x8, 0x0},
6102 {TAIKO_A_CDC_TX8_MUX_CTL, 0x8, 0x0},
6103 {TAIKO_A_CDC_TX9_MUX_CTL, 0x8, 0x0},
6104 {TAIKO_A_CDC_TX10_MUX_CTL, 0x8, 0x0},
6105
Joonwoo Parkc7731432012-10-17 12:41:44 -07006106 /* Compander zone selection */
6107 {TAIKO_A_CDC_COMP0_B4_CTL, 0x3F, 0x37},
6108 {TAIKO_A_CDC_COMP1_B4_CTL, 0x3F, 0x37},
6109 {TAIKO_A_CDC_COMP2_B4_CTL, 0x3F, 0x37},
6110 {TAIKO_A_CDC_COMP0_B5_CTL, 0x7F, 0x7F},
6111 {TAIKO_A_CDC_COMP1_B5_CTL, 0x7F, 0x7F},
6112 {TAIKO_A_CDC_COMP2_B5_CTL, 0x7F, 0x7F},
Bhalchandra Gajareef7810e2013-03-29 16:50:37 -07006113
6114 /*
6115 * Setup wavegen timer to 20msec and disable chopper
6116 * as default. This corresponds to Compander OFF
6117 */
6118 {TAIKO_A_RX_HPH_CNP_WG_CTL, 0xFF, 0xDB},
6119 {TAIKO_A_RX_HPH_CNP_WG_TIME, 0xFF, 0x58},
6120 {TAIKO_A_RX_HPH_BIAS_WG_OCP, 0xFF, 0x1A},
6121 {TAIKO_A_RX_HPH_CHOP_CTL, 0xFF, 0x24},
Bhalchandra Gajare9581aed2013-03-29 17:06:10 -07006122
6123 /* Choose max non-overlap time for NCP */
6124 {TAIKO_A_NCP_CLK, 0xFF, 0xFC},
6125
6126 /* Program the 0.85 volt VBG_REFERENCE */
6127 {TAIKO_A_BIAS_CURR_CTL_2, 0xFF, 0x04},
Kiran Kandic3b24402012-06-11 00:05:59 -07006128};
6129
6130static void taiko_codec_init_reg(struct snd_soc_codec *codec)
6131{
6132 u32 i;
6133
6134 for (i = 0; i < ARRAY_SIZE(taiko_codec_reg_init_val); i++)
6135 snd_soc_update_bits(codec, taiko_codec_reg_init_val[i].reg,
6136 taiko_codec_reg_init_val[i].mask,
6137 taiko_codec_reg_init_val[i].val);
6138}
6139
Ravishankar Sarawadi7b700362013-04-18 15:56:02 -07006140static void taiko_slim_interface_init_reg(struct snd_soc_codec *codec)
Joonwoo Park7680b9f2012-07-13 11:36:48 -07006141{
Joonwoo Park7680b9f2012-07-13 11:36:48 -07006142 int i;
Joonwoo Park7680b9f2012-07-13 11:36:48 -07006143
6144 for (i = 0; i < WCD9XXX_SLIM_NUM_PORT_REG; i++)
6145 wcd9xxx_interface_reg_write(codec->control_data,
Joonwoo Parka8890262012-10-15 12:04:27 -07006146 TAIKO_SLIM_PGD_PORT_INT_EN0 + i,
6147 0xFF);
Ravishankar Sarawadi7b700362013-04-18 15:56:02 -07006148}
6149
6150static int taiko_setup_irqs(struct taiko_priv *taiko)
6151{
6152 int ret = 0;
6153 struct snd_soc_codec *codec = taiko->codec;
6154
6155 ret = wcd9xxx_request_irq(codec->control_data, WCD9XXX_IRQ_SLIMBUS,
6156 taiko_slimbus_irq, "SLIMBUS Slave", taiko);
6157 if (ret)
6158 pr_err("%s: Failed to request irq %d\n", __func__,
6159 WCD9XXX_IRQ_SLIMBUS);
6160 else
6161 taiko_slim_interface_init_reg(codec);
6162
Joonwoo Park7680b9f2012-07-13 11:36:48 -07006163 return ret;
6164}
6165
Ravishankar Sarawadi7b700362013-04-18 15:56:02 -07006166static void taiko_cleanup_irqs(struct taiko_priv *taiko)
6167{
6168 struct snd_soc_codec *codec = taiko->codec;
6169
6170 wcd9xxx_free_irq(codec->control_data, WCD9XXX_IRQ_SLIMBUS, taiko);
6171}
6172
Joonwoo Parka8890262012-10-15 12:04:27 -07006173int taiko_hs_detect(struct snd_soc_codec *codec,
6174 struct wcd9xxx_mbhc_config *mbhc_cfg)
6175{
Joonwoo Park88bfa842013-04-15 16:59:21 -07006176 int rc;
Joonwoo Parka8890262012-10-15 12:04:27 -07006177 struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
Joonwoo Park88bfa842013-04-15 16:59:21 -07006178 rc = wcd9xxx_mbhc_start(&taiko->mbhc, mbhc_cfg);
6179 if (!rc)
6180 taiko->mbhc_started = true;
6181 return rc;
Joonwoo Parka8890262012-10-15 12:04:27 -07006182}
6183EXPORT_SYMBOL_GPL(taiko_hs_detect);
6184
Kiran Kandia1bed422013-05-28 18:29:12 -07006185void taiko_event_register(
6186 int (*machine_event_cb)(struct snd_soc_codec *codec,
6187 enum wcd9xxx_codec_event),
6188 struct snd_soc_codec *codec)
6189{
6190 struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
6191 taiko->machine_codec_event_cb = machine_event_cb;
6192}
6193EXPORT_SYMBOL_GPL(taiko_event_register);
6194
Joonwoo Park1d05bb92013-03-07 16:55:06 -08006195static void taiko_init_slim_slave_cfg(struct snd_soc_codec *codec)
6196{
6197 struct taiko_priv *priv = snd_soc_codec_get_drvdata(codec);
6198 struct afe_param_cdc_slimbus_slave_cfg *cfg;
6199 struct wcd9xxx *wcd9xxx = codec->control_data;
6200 uint64_t eaddr = 0;
6201
6202 cfg = &priv->slimbus_slave_cfg;
6203 cfg->minor_version = 1;
6204 cfg->tx_slave_port_offset = 0;
6205 cfg->rx_slave_port_offset = 16;
6206
6207 memcpy(&eaddr, &wcd9xxx->slim->e_addr, sizeof(wcd9xxx->slim->e_addr));
6208 WARN_ON(sizeof(wcd9xxx->slim->e_addr) != 6);
6209 cfg->device_enum_addr_lsw = eaddr & 0xFFFFFFFF;
6210 cfg->device_enum_addr_msw = eaddr >> 32;
6211
6212 pr_debug("%s: slimbus logical address 0x%llx\n", __func__, eaddr);
6213}
6214
Joonwoo Park8ffa2812013-08-07 19:01:30 -07006215static int taiko_device_down(struct wcd9xxx *wcd9xxx)
6216{
6217 struct snd_soc_codec *codec;
6218
6219 codec = (struct snd_soc_codec *)(wcd9xxx->ssr_priv);
6220 snd_soc_card_change_online_state(codec->card, 0);
6221
6222 return 0;
6223}
6224
Ravishankar Sarawadi839fcf32012-11-14 12:13:00 -08006225static int taiko_post_reset_cb(struct wcd9xxx *wcd9xxx)
6226{
6227 int ret = 0;
6228 struct snd_soc_codec *codec;
6229 struct taiko_priv *taiko;
Phani Kumar Uppalapati43bc4152013-05-24 00:44:20 -07006230 int rco_clk_rate;
Ravishankar Sarawadi839fcf32012-11-14 12:13:00 -08006231
6232 codec = (struct snd_soc_codec *)(wcd9xxx->ssr_priv);
6233 taiko = snd_soc_codec_get_drvdata(codec);
Ravishankar Sarawadi839fcf32012-11-14 12:13:00 -08006234
Joonwoo Park8ffa2812013-08-07 19:01:30 -07006235 snd_soc_card_change_online_state(codec->card, 1);
6236
6237 mutex_lock(&codec->mutex);
Ravishankar Sarawadi839fcf32012-11-14 12:13:00 -08006238 if (codec->reg_def_copy) {
6239 pr_debug("%s: Update ASOC cache", __func__);
6240 kfree(codec->reg_cache);
6241 codec->reg_cache = kmemdup(codec->reg_def_copy,
6242 codec->reg_size, GFP_KERNEL);
6243 }
6244
Ravishankar Sarawadi2293efe2013-01-11 16:37:23 -08006245 if (spkr_drv_wrnd == 1)
6246 snd_soc_update_bits(codec, TAIKO_A_SPKR_DRV_EN, 0x80, 0x80);
Ravishankar Sarawadi2293efe2013-01-11 16:37:23 -08006247
Ravishankar Sarawadi839fcf32012-11-14 12:13:00 -08006248 taiko_update_reg_defaults(codec);
6249 taiko_codec_init_reg(codec);
6250 ret = taiko_handle_pdata(taiko);
6251 if (IS_ERR_VALUE(ret))
6252 pr_err("%s: bad pdata\n", __func__);
Ravishankar Sarawadi2293efe2013-01-11 16:37:23 -08006253
Joonwoo Park1d05bb92013-03-07 16:55:06 -08006254 taiko_init_slim_slave_cfg(codec);
Ravishankar Sarawadi7b700362013-04-18 15:56:02 -07006255 taiko_slim_interface_init_reg(codec);
Joonwoo Park1d05bb92013-03-07 16:55:06 -08006256
Joonwoo Park865bcf02013-07-15 14:05:32 -07006257 wcd9xxx_resmgr_post_ssr(&taiko->resmgr);
6258
Joonwoo Park88bfa842013-04-15 16:59:21 -07006259 if (taiko->mbhc_started) {
6260 wcd9xxx_mbhc_deinit(&taiko->mbhc);
6261 taiko->mbhc_started = false;
Phani Kumar Uppalapati43bc4152013-05-24 00:44:20 -07006262
6263 if (TAIKO_IS_1_0(wcd9xxx->version))
6264 rco_clk_rate = TAIKO_MCLK_CLK_12P288MHZ;
6265 else
6266 rco_clk_rate = TAIKO_MCLK_CLK_9P6MHZ;
6267
Joonwoo Park88bfa842013-04-15 16:59:21 -07006268 ret = wcd9xxx_mbhc_init(&taiko->mbhc, &taiko->resmgr, codec,
Joonwoo Parkccccba72013-04-26 11:19:46 -07006269 taiko_enable_mbhc_micbias,
Phani Kumar Uppalapatid7549e12013-07-12 22:22:03 -07006270 NULL, rco_clk_rate, true);
Joonwoo Park88bfa842013-04-15 16:59:21 -07006271 if (ret) {
6272 pr_err("%s: mbhc init failed %d\n", __func__, ret);
6273 } else {
6274 ret = wcd9xxx_mbhc_start(&taiko->mbhc,
6275 taiko->mbhc.mbhc_cfg);
6276 if (!ret)
6277 taiko->mbhc_started = true;
6278 }
6279 }
Kiran Kandia1bed422013-05-28 18:29:12 -07006280 taiko->machine_codec_event_cb(codec, WCD9XXX_CODEC_EVENT_CODEC_UP);
6281
Ravishankar Sarawadi839fcf32012-11-14 12:13:00 -08006282 mutex_unlock(&codec->mutex);
6283 return ret;
6284}
6285
Joonwoo Park1d05bb92013-03-07 16:55:06 -08006286void *taiko_get_afe_config(struct snd_soc_codec *codec,
6287 enum afe_config_type config_type)
6288{
6289 struct taiko_priv *priv = snd_soc_codec_get_drvdata(codec);
Gopikrishnaiah Anandaneb51dd72013-04-09 11:39:55 -04006290 struct wcd9xxx *taiko_core = dev_get_drvdata(codec->dev->parent);
Joonwoo Park1d05bb92013-03-07 16:55:06 -08006291
6292 switch (config_type) {
6293 case AFE_SLIMBUS_SLAVE_CONFIG:
6294 return &priv->slimbus_slave_cfg;
6295 case AFE_CDC_REGISTERS_CONFIG:
Damir Didjustodcfdff82013-03-21 23:26:41 -07006296 return &taiko_audio_reg_cfg;
Joonwoo Park1d05bb92013-03-07 16:55:06 -08006297 case AFE_SLIMBUS_SLAVE_PORT_CONFIG:
6298 return &taiko_slimbus_slave_port_cfg;
Damir Didjustodcfdff82013-03-21 23:26:41 -07006299 case AFE_AANC_VERSION:
6300 return &taiko_cdc_aanc_version;
Gopikrishnaiah Anandaneb51dd72013-04-09 11:39:55 -04006301 case AFE_CLIP_BANK_SEL:
6302 if (!TAIKO_IS_1_0(taiko_core->version))
6303 return &clip_bank_sel;
6304 else
6305 return NULL;
6306 case AFE_CDC_CLIP_REGISTERS_CONFIG:
6307 if (!TAIKO_IS_1_0(taiko_core->version))
6308 return &taiko_clip_reg_cfg;
6309 else
6310 return NULL;
Joonwoo Park1d05bb92013-03-07 16:55:06 -08006311 default:
6312 pr_err("%s: Unknown config_type 0x%x\n", __func__, config_type);
6313 return NULL;
6314 }
6315}
Ravishankar Sarawadi839fcf32012-11-14 12:13:00 -08006316
Joonwoo Parka8890262012-10-15 12:04:27 -07006317static struct wcd9xxx_reg_address taiko_reg_address = {
6318 .micb_4_mbhc = TAIKO_A_MICB_4_MBHC,
6319 .micb_4_int_rbias = TAIKO_A_MICB_4_INT_RBIAS,
6320 .micb_4_ctl = TAIKO_A_MICB_4_CTL,
6321};
6322
Ravishankar Sarawadi839fcf32012-11-14 12:13:00 -08006323static int wcd9xxx_ssr_register(struct wcd9xxx *control,
Joonwoo Park8ffa2812013-08-07 19:01:30 -07006324 int (*device_down_cb)(struct wcd9xxx *wcd9xxx),
6325 int (*device_up_cb)(struct wcd9xxx *wcd9xxx),
6326 void *priv)
Ravishankar Sarawadi839fcf32012-11-14 12:13:00 -08006327{
Joonwoo Park8ffa2812013-08-07 19:01:30 -07006328 control->dev_down = device_down_cb;
6329 control->post_reset = device_up_cb;
Ravishankar Sarawadi839fcf32012-11-14 12:13:00 -08006330 control->ssr_priv = priv;
6331 return 0;
6332}
6333
Joonwoo Park2a9170a2013-03-04 17:05:57 -08006334static const struct snd_soc_dapm_widget taiko_1_dapm_widgets[] = {
6335 SND_SOC_DAPM_ADC_E("ADC1", NULL, TAIKO_A_TX_1_2_EN, 7, 0,
6336 taiko_codec_enable_adc,
6337 SND_SOC_DAPM_PRE_PMU |
6338 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
6339 SND_SOC_DAPM_ADC_E("ADC2", NULL, TAIKO_A_TX_1_2_EN, 3, 0,
6340 taiko_codec_enable_adc,
6341 SND_SOC_DAPM_PRE_PMU |
6342 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
6343 SND_SOC_DAPM_ADC_E("ADC3", NULL, TAIKO_A_TX_3_4_EN, 7, 0,
6344 taiko_codec_enable_adc,
6345 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
6346 SND_SOC_DAPM_POST_PMD),
6347 SND_SOC_DAPM_ADC_E("ADC4", NULL, TAIKO_A_TX_3_4_EN, 3, 0,
6348 taiko_codec_enable_adc,
6349 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
6350 SND_SOC_DAPM_POST_PMD),
6351 SND_SOC_DAPM_ADC_E("ADC5", NULL, TAIKO_A_TX_5_6_EN, 7, 0,
6352 taiko_codec_enable_adc,
6353 SND_SOC_DAPM_POST_PMU),
6354 SND_SOC_DAPM_ADC_E("ADC6", NULL, TAIKO_A_TX_5_6_EN, 3, 0,
6355 taiko_codec_enable_adc,
6356 SND_SOC_DAPM_POST_PMU),
6357};
6358
6359static const struct snd_soc_dapm_widget taiko_2_dapm_widgets[] = {
6360 SND_SOC_DAPM_ADC_E("ADC1", NULL, TAIKO_A_CDC_TX_1_GAIN, 7, 0,
6361 taiko_codec_enable_adc,
6362 SND_SOC_DAPM_PRE_PMU |
6363 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
6364 SND_SOC_DAPM_ADC_E("ADC2", NULL, TAIKO_A_CDC_TX_2_GAIN, 7, 0,
6365 taiko_codec_enable_adc,
6366 SND_SOC_DAPM_PRE_PMU |
6367 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
6368 SND_SOC_DAPM_ADC_E("ADC3", NULL, TAIKO_A_CDC_TX_3_GAIN, 7, 0,
6369 taiko_codec_enable_adc,
6370 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
6371 SND_SOC_DAPM_POST_PMD),
6372 SND_SOC_DAPM_ADC_E("ADC4", NULL, TAIKO_A_CDC_TX_4_GAIN, 7, 0,
6373 taiko_codec_enable_adc,
6374 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
6375 SND_SOC_DAPM_POST_PMD),
6376 SND_SOC_DAPM_ADC_E("ADC5", NULL, TAIKO_A_CDC_TX_5_GAIN, 7, 0,
6377 taiko_codec_enable_adc,
6378 SND_SOC_DAPM_POST_PMU),
6379 SND_SOC_DAPM_ADC_E("ADC6", NULL, TAIKO_A_CDC_TX_6_GAIN, 7, 0,
6380 taiko_codec_enable_adc,
6381 SND_SOC_DAPM_POST_PMU),
6382};
6383
Joonwoo Park448a8fc2013-04-10 15:25:58 -07006384static struct regulator *taiko_codec_find_regulator(struct snd_soc_codec *codec,
6385 const char *name)
6386{
6387 int i;
6388 struct wcd9xxx *core = dev_get_drvdata(codec->dev->parent);
6389
6390 for (i = 0; i < core->num_of_supplies; i++) {
6391 if (core->supplies[i].supply &&
6392 !strcmp(core->supplies[i].supply, name))
6393 return core->supplies[i].consumer;
6394 }
6395
6396 return NULL;
6397}
6398
Kiran Kandic3b24402012-06-11 00:05:59 -07006399static int taiko_codec_probe(struct snd_soc_codec *codec)
6400{
6401 struct wcd9xxx *control;
6402 struct taiko_priv *taiko;
Joonwoo Parka8890262012-10-15 12:04:27 -07006403 struct wcd9xxx_pdata *pdata;
6404 struct wcd9xxx *wcd9xxx;
Kiran Kandic3b24402012-06-11 00:05:59 -07006405 struct snd_soc_dapm_context *dapm = &codec->dapm;
6406 int ret = 0;
Phani Kumar Uppalapati43bc4152013-05-24 00:44:20 -07006407 int i, rco_clk_rate;
Kuirong Wang906ac472012-07-09 12:54:44 -07006408 void *ptr = NULL;
Joonwoo Park559a5bf2013-02-15 14:46:36 -08006409 struct wcd9xxx *core = dev_get_drvdata(codec->dev->parent);
Kiran Kandic3b24402012-06-11 00:05:59 -07006410
6411 codec->control_data = dev_get_drvdata(codec->dev->parent);
6412 control = codec->control_data;
6413
Joonwoo Park8ffa2812013-08-07 19:01:30 -07006414 wcd9xxx_ssr_register(control, taiko_device_down,
6415 taiko_post_reset_cb, (void *)codec);
Ravishankar Sarawadi839fcf32012-11-14 12:13:00 -08006416
Kiran Kandi4c56c592012-07-25 11:04:55 -07006417 dev_info(codec->dev, "%s()\n", __func__);
6418
Kiran Kandic3b24402012-06-11 00:05:59 -07006419 taiko = kzalloc(sizeof(struct taiko_priv), GFP_KERNEL);
6420 if (!taiko) {
6421 dev_err(codec->dev, "Failed to allocate private data\n");
6422 return -ENOMEM;
6423 }
6424 for (i = 0 ; i < NUM_DECIMATORS; i++) {
6425 tx_hpf_work[i].taiko = taiko;
6426 tx_hpf_work[i].decimator = i + 1;
6427 INIT_DELAYED_WORK(&tx_hpf_work[i].dwork,
6428 tx_hpf_corner_freq_callback);
6429 }
6430
Kiran Kandic3b24402012-06-11 00:05:59 -07006431 snd_soc_codec_set_drvdata(codec, taiko);
6432
Joonwoo Parka8890262012-10-15 12:04:27 -07006433 /* codec resmgr module init */
6434 wcd9xxx = codec->control_data;
6435 pdata = dev_get_platdata(codec->dev->parent);
6436 ret = wcd9xxx_resmgr_init(&taiko->resmgr, codec, wcd9xxx, pdata,
6437 &taiko_reg_address);
6438 if (ret) {
6439 pr_err("%s: wcd9xxx init failed %d\n", __func__, ret);
Ravishankar Sarawadi7b700362013-04-18 15:56:02 -07006440 goto err_init;
Joonwoo Parka8890262012-10-15 12:04:27 -07006441 }
6442
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08006443 taiko->clsh_d.buck_mv = taiko_codec_get_buck_mv(codec);
Bhalchandra Gajare7c739522013-06-20 15:31:02 -07006444 /* Taiko does not support dynamic switching of vdd_cp */
6445 taiko->clsh_d.is_dynamic_vdd_cp = false;
Joonwoo Parka08e0552013-03-05 18:28:23 -08006446 wcd9xxx_clsh_init(&taiko->clsh_d, &taiko->resmgr);
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08006447
Phani Kumar Uppalapati43bc4152013-05-24 00:44:20 -07006448 if (TAIKO_IS_1_0(core->version))
6449 rco_clk_rate = TAIKO_MCLK_CLK_12P288MHZ;
6450 else
6451 rco_clk_rate = TAIKO_MCLK_CLK_9P6MHZ;
6452
Joonwoo Parka8890262012-10-15 12:04:27 -07006453 /* init and start mbhc */
Simmi Pateriya0a44d842013-04-03 01:12:42 +05306454 ret = wcd9xxx_mbhc_init(&taiko->mbhc, &taiko->resmgr, codec,
Joonwoo Parkccccba72013-04-26 11:19:46 -07006455 taiko_enable_mbhc_micbias,
Phani Kumar Uppalapatid7549e12013-07-12 22:22:03 -07006456 NULL, rco_clk_rate, true);
Joonwoo Parka8890262012-10-15 12:04:27 -07006457 if (ret) {
6458 pr_err("%s: mbhc init failed %d\n", __func__, ret);
Ravishankar Sarawadi7b700362013-04-18 15:56:02 -07006459 goto err_init;
Joonwoo Parka8890262012-10-15 12:04:27 -07006460 }
6461
Kiran Kandic3b24402012-06-11 00:05:59 -07006462 taiko->codec = codec;
Kiran Kandic3b24402012-06-11 00:05:59 -07006463 for (i = 0; i < COMPANDER_MAX; i++) {
6464 taiko->comp_enabled[i] = 0;
6465 taiko->comp_fs[i] = COMPANDER_FS_48KHZ;
6466 }
Kiran Kandic3b24402012-06-11 00:05:59 -07006467 taiko->intf_type = wcd9xxx_get_intf_type();
6468 taiko->aux_pga_cnt = 0;
6469 taiko->aux_l_gain = 0x1F;
6470 taiko->aux_r_gain = 0x1F;
Joonwoo Parkccccba72013-04-26 11:19:46 -07006471 taiko->ldo_h_users = 0;
6472 taiko->micb_2_users = 0;
Kiran Kandic3b24402012-06-11 00:05:59 -07006473 taiko_update_reg_defaults(codec);
Venkat Sudhira50a3762012-11-26 12:12:15 -08006474 pr_debug("%s: MCLK Rate = %x\n", __func__, wcd9xxx->mclk_rate);
6475 if (wcd9xxx->mclk_rate == TAIKO_MCLK_CLK_12P288MHZ)
Venkat Sudhir16d95e62013-02-04 16:57:33 -08006476 snd_soc_update_bits(codec, TAIKO_A_CHIP_CTL, 0x06, 0x0);
Phani Kumar Uppalapati43bc4152013-05-24 00:44:20 -07006477 else if (wcd9xxx->mclk_rate == TAIKO_MCLK_CLK_9P6MHZ)
Venkat Sudhir16d95e62013-02-04 16:57:33 -08006478 snd_soc_update_bits(codec, TAIKO_A_CHIP_CTL, 0x06, 0x2);
Kiran Kandic3b24402012-06-11 00:05:59 -07006479 taiko_codec_init_reg(codec);
6480 ret = taiko_handle_pdata(taiko);
6481 if (IS_ERR_VALUE(ret)) {
6482 pr_err("%s: bad pdata\n", __func__);
6483 goto err_pdata;
6484 }
6485
Joonwoo Park448a8fc2013-04-10 15:25:58 -07006486 taiko->spkdrv_reg = taiko_codec_find_regulator(codec,
6487 WCD9XXX_VDD_SPKDRV_NAME);
6488
Joonwoo Park125cd4e2012-12-11 15:16:11 -08006489 if (spkr_drv_wrnd > 0) {
Joonwoo Park533b3682013-06-13 11:41:21 -07006490 WCD9XXX_BG_CLK_LOCK(&taiko->resmgr);
Joonwoo Park125cd4e2012-12-11 15:16:11 -08006491 wcd9xxx_resmgr_get_bandgap(&taiko->resmgr,
6492 WCD9XXX_BANDGAP_AUDIO_MODE);
Joonwoo Park533b3682013-06-13 11:41:21 -07006493 WCD9XXX_BG_CLK_UNLOCK(&taiko->resmgr);
Joonwoo Park125cd4e2012-12-11 15:16:11 -08006494 }
6495
Kuirong Wang906ac472012-07-09 12:54:44 -07006496 ptr = kmalloc((sizeof(taiko_rx_chs) +
6497 sizeof(taiko_tx_chs)), GFP_KERNEL);
6498 if (!ptr) {
6499 pr_err("%s: no mem for slim chan ctl data\n", __func__);
6500 ret = -ENOMEM;
6501 goto err_nomem_slimch;
6502 }
6503
Kiran Kandic3b24402012-06-11 00:05:59 -07006504 if (taiko->intf_type == WCD9XXX_INTERFACE_TYPE_I2C) {
6505 snd_soc_dapm_new_controls(dapm, taiko_dapm_i2s_widgets,
6506 ARRAY_SIZE(taiko_dapm_i2s_widgets));
6507 snd_soc_dapm_add_routes(dapm, audio_i2s_map,
6508 ARRAY_SIZE(audio_i2s_map));
Joonwoo Park559a5bf2013-02-15 14:46:36 -08006509 if (TAIKO_IS_1_0(core->version))
6510 snd_soc_dapm_add_routes(dapm, audio_i2s_map_1_0,
6511 ARRAY_SIZE(audio_i2s_map_1_0));
6512 else
6513 snd_soc_dapm_add_routes(dapm, audio_i2s_map_2_0,
6514 ARRAY_SIZE(audio_i2s_map_2_0));
Kuirong Wang906ac472012-07-09 12:54:44 -07006515 for (i = 0; i < ARRAY_SIZE(taiko_i2s_dai); i++)
6516 INIT_LIST_HEAD(&taiko->dai[i].wcd9xxx_ch_list);
6517 } else if (taiko->intf_type == WCD9XXX_INTERFACE_TYPE_SLIMBUS) {
6518 for (i = 0; i < NUM_CODEC_DAIS; i++) {
6519 INIT_LIST_HEAD(&taiko->dai[i].wcd9xxx_ch_list);
6520 init_waitqueue_head(&taiko->dai[i].dai_wait);
6521 }
Joonwoo Park1d05bb92013-03-07 16:55:06 -08006522 taiko_slimbus_slave_port_cfg.slave_dev_intfdev_la =
6523 control->slim_slave->laddr;
6524 taiko_slimbus_slave_port_cfg.slave_dev_pgd_la =
6525 control->slim->laddr;
6526 taiko_slimbus_slave_port_cfg.slave_port_mapping[0] =
6527 TAIKO_MAD_SLIMBUS_TX_PORT;
6528
6529 taiko_init_slim_slave_cfg(codec);
Kiran Kandic3b24402012-06-11 00:05:59 -07006530 }
6531
Kiran Kandiec0db5c2013-03-08 16:03:58 -08006532 if (TAIKO_IS_1_0(control->version)) {
Joonwoo Park2a9170a2013-03-04 17:05:57 -08006533 snd_soc_dapm_new_controls(dapm, taiko_1_dapm_widgets,
6534 ARRAY_SIZE(taiko_1_dapm_widgets));
Kiran Kandiec0db5c2013-03-08 16:03:58 -08006535 snd_soc_add_codec_controls(codec,
6536 taiko_1_x_analog_gain_controls,
6537 ARRAY_SIZE(taiko_1_x_analog_gain_controls));
6538 } else {
Joonwoo Park2a9170a2013-03-04 17:05:57 -08006539 snd_soc_dapm_new_controls(dapm, taiko_2_dapm_widgets,
6540 ARRAY_SIZE(taiko_2_dapm_widgets));
Kiran Kandiec0db5c2013-03-08 16:03:58 -08006541 snd_soc_add_codec_controls(codec,
6542 taiko_2_x_analog_gain_controls,
6543 ARRAY_SIZE(taiko_2_x_analog_gain_controls));
6544 }
Joonwoo Park2a9170a2013-03-04 17:05:57 -08006545
Joonwoo Parkb755e9e2013-05-28 13:14:05 -07006546 snd_soc_add_codec_controls(codec, impedance_detect_controls,
6547 ARRAY_SIZE(impedance_detect_controls));
6548
Kuirong Wang906ac472012-07-09 12:54:44 -07006549 control->num_rx_port = TAIKO_RX_MAX;
6550 control->rx_chs = ptr;
6551 memcpy(control->rx_chs, taiko_rx_chs, sizeof(taiko_rx_chs));
6552 control->num_tx_port = TAIKO_TX_MAX;
6553 control->tx_chs = ptr + sizeof(taiko_rx_chs);
6554 memcpy(control->tx_chs, taiko_tx_chs, sizeof(taiko_tx_chs));
6555
Kiran Kandic3b24402012-06-11 00:05:59 -07006556 snd_soc_dapm_sync(dapm);
6557
Ravishankar Sarawadi7b700362013-04-18 15:56:02 -07006558 ret = taiko_setup_irqs(taiko);
6559 if (ret) {
6560 pr_err("%s: taiko irq setup failed %d\n", __func__, ret);
6561 goto err_irq;
6562 }
Kiran Kandic3b24402012-06-11 00:05:59 -07006563
Joonwoo Park125cd4e2012-12-11 15:16:11 -08006564 atomic_set(&kp_taiko_priv, (unsigned long)taiko);
Damir Didjusto2cb06bd2013-01-30 23:14:55 -08006565 mutex_lock(&dapm->codec->mutex);
6566 snd_soc_dapm_disable_pin(dapm, "ANC HPHL");
6567 snd_soc_dapm_disable_pin(dapm, "ANC HPHR");
6568 snd_soc_dapm_disable_pin(dapm, "ANC HEADPHONE");
6569 snd_soc_dapm_disable_pin(dapm, "ANC EAR PA");
6570 snd_soc_dapm_disable_pin(dapm, "ANC EAR");
6571 snd_soc_dapm_sync(dapm);
6572 mutex_unlock(&dapm->codec->mutex);
Joonwoo Park125cd4e2012-12-11 15:16:11 -08006573
Kiran Kandic3b24402012-06-11 00:05:59 -07006574 codec->ignore_pmdown_time = 1;
6575 return ret;
6576
Ravishankar Sarawadi7b700362013-04-18 15:56:02 -07006577err_irq:
6578 taiko_cleanup_irqs(taiko);
Kiran Kandic3b24402012-06-11 00:05:59 -07006579err_pdata:
Kuirong Wang906ac472012-07-09 12:54:44 -07006580 kfree(ptr);
6581err_nomem_slimch:
Kiran Kandic3b24402012-06-11 00:05:59 -07006582 kfree(taiko);
Ravishankar Sarawadi7b700362013-04-18 15:56:02 -07006583err_init:
Kiran Kandic3b24402012-06-11 00:05:59 -07006584 return ret;
6585}
6586static int taiko_codec_remove(struct snd_soc_codec *codec)
6587{
Kiran Kandic3b24402012-06-11 00:05:59 -07006588 struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
Joonwoo Parka8890262012-10-15 12:04:27 -07006589
Joonwoo Park533b3682013-06-13 11:41:21 -07006590 WCD9XXX_BG_CLK_LOCK(&taiko->resmgr);
Joonwoo Park125cd4e2012-12-11 15:16:11 -08006591 atomic_set(&kp_taiko_priv, 0);
6592
6593 if (spkr_drv_wrnd > 0)
6594 wcd9xxx_resmgr_put_bandgap(&taiko->resmgr,
6595 WCD9XXX_BANDGAP_AUDIO_MODE);
Joonwoo Park533b3682013-06-13 11:41:21 -07006596 WCD9XXX_BG_CLK_UNLOCK(&taiko->resmgr);
Joonwoo Park125cd4e2012-12-11 15:16:11 -08006597
Ravishankar Sarawadi7b700362013-04-18 15:56:02 -07006598 taiko_cleanup_irqs(taiko);
6599
Joonwoo Parka8890262012-10-15 12:04:27 -07006600 /* cleanup MBHC */
6601 wcd9xxx_mbhc_deinit(&taiko->mbhc);
6602 /* cleanup resmgr */
6603 wcd9xxx_resmgr_deinit(&taiko->resmgr);
6604
Joonwoo Park448a8fc2013-04-10 15:25:58 -07006605 taiko->spkdrv_reg = NULL;
6606
Kiran Kandic3b24402012-06-11 00:05:59 -07006607 kfree(taiko);
6608 return 0;
6609}
6610static struct snd_soc_codec_driver soc_codec_dev_taiko = {
6611 .probe = taiko_codec_probe,
6612 .remove = taiko_codec_remove,
6613
6614 .read = taiko_read,
6615 .write = taiko_write,
6616
6617 .readable_register = taiko_readable,
6618 .volatile_register = taiko_volatile,
6619
6620 .reg_cache_size = TAIKO_CACHE_SIZE,
Kiran Kandi7b7d2ff2012-09-14 14:52:14 -07006621 .reg_cache_default = taiko_reset_reg_defaults,
Kiran Kandic3b24402012-06-11 00:05:59 -07006622 .reg_word_size = 1,
6623
6624 .controls = taiko_snd_controls,
6625 .num_controls = ARRAY_SIZE(taiko_snd_controls),
6626 .dapm_widgets = taiko_dapm_widgets,
6627 .num_dapm_widgets = ARRAY_SIZE(taiko_dapm_widgets),
6628 .dapm_routes = audio_map,
6629 .num_dapm_routes = ARRAY_SIZE(audio_map),
6630};
6631
6632#ifdef CONFIG_PM
6633static int taiko_suspend(struct device *dev)
6634{
6635 dev_dbg(dev, "%s: system suspend\n", __func__);
6636 return 0;
6637}
6638
6639static int taiko_resume(struct device *dev)
6640{
6641 struct platform_device *pdev = to_platform_device(dev);
6642 struct taiko_priv *taiko = platform_get_drvdata(pdev);
6643 dev_dbg(dev, "%s: system resume\n", __func__);
Joonwoo Parka8890262012-10-15 12:04:27 -07006644 /* Notify */
6645 wcd9xxx_resmgr_notifier_call(&taiko->resmgr, WCD9XXX_EVENT_POST_RESUME);
Kiran Kandic3b24402012-06-11 00:05:59 -07006646 return 0;
6647}
6648
6649static const struct dev_pm_ops taiko_pm_ops = {
6650 .suspend = taiko_suspend,
6651 .resume = taiko_resume,
6652};
6653#endif
6654
6655static int __devinit taiko_probe(struct platform_device *pdev)
6656{
6657 int ret = 0;
6658 if (wcd9xxx_get_intf_type() == WCD9XXX_INTERFACE_TYPE_SLIMBUS)
6659 ret = snd_soc_register_codec(&pdev->dev, &soc_codec_dev_taiko,
6660 taiko_dai, ARRAY_SIZE(taiko_dai));
6661 else if (wcd9xxx_get_intf_type() == WCD9XXX_INTERFACE_TYPE_I2C)
6662 ret = snd_soc_register_codec(&pdev->dev, &soc_codec_dev_taiko,
6663 taiko_i2s_dai, ARRAY_SIZE(taiko_i2s_dai));
6664 return ret;
6665}
6666static int __devexit taiko_remove(struct platform_device *pdev)
6667{
6668 snd_soc_unregister_codec(&pdev->dev);
6669 return 0;
6670}
6671static struct platform_driver taiko_codec_driver = {
6672 .probe = taiko_probe,
6673 .remove = taiko_remove,
6674 .driver = {
6675 .name = "taiko_codec",
6676 .owner = THIS_MODULE,
6677#ifdef CONFIG_PM
6678 .pm = &taiko_pm_ops,
6679#endif
6680 },
6681};
6682
6683static int __init taiko_codec_init(void)
6684{
6685 return platform_driver_register(&taiko_codec_driver);
6686}
6687
6688static void __exit taiko_codec_exit(void)
6689{
6690 platform_driver_unregister(&taiko_codec_driver);
6691}
6692
6693module_init(taiko_codec_init);
6694module_exit(taiko_codec_exit);
6695
6696MODULE_DESCRIPTION("Taiko codec driver");
6697MODULE_LICENSE("GPL v2");