blob: d5aaa381ec64cc4b7f6cd8f97baaa1ad1cb60e23 [file] [log] [blame]
Banajit Goswamide8271c2017-01-18 00:28:59 -08001/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
2 *
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>
21#include <linux/wait.h>
22#include <linux/bitops.h>
23#include <linux/clk.h>
24#include <linux/delay.h>
25#include <linux/pm_runtime.h>
26#include <linux/kernel.h>
27#include <linux/gpio.h>
28#include <linux/regmap.h>
29#include <linux/spi/spi.h>
30#include <linux/mfd/wcd9xxx/core.h>
31#include <linux/mfd/wcd9xxx/wcd9xxx-irq.h>
32#include <linux/mfd/wcd9xxx/wcd9xxx_registers.h>
33#include <linux/mfd/wcd934x/registers.h>
34#include <linux/mfd/wcd9xxx/pdata.h>
35#include <linux/regulator/consumer.h>
36#include <linux/soundwire/swr-wcd.h>
37#include <sound/pcm.h>
38#include <sound/pcm_params.h>
39#include <sound/soc.h>
40#include <sound/soc-dapm.h>
41#include <sound/tlv.h>
42#include <sound/info.h>
43#include "wcd934x.h"
44#include "wcd934x-mbhc.h"
45#include "wcd934x-routing.h"
46#include "wcd934x-dsp-cntl.h"
47#include "../wcd9xxx-common-v2.h"
48#include "../wcd9xxx-resmgr-v2.h"
49#include "../wcdcal-hwdep.h"
50#include "wcd934x-dsd.h"
51
52#define WCD934X_RATES_MASK (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |\
53 SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 |\
54 SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000 |\
55 SNDRV_PCM_RATE_384000)
56/* Fractional Rates */
57#define WCD934X_FRAC_RATES_MASK (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_88200 |\
58 SNDRV_PCM_RATE_176400)
59
60#define WCD934X_FORMATS_S16_S24_LE (SNDRV_PCM_FMTBIT_S16_LE | \
61 SNDRV_PCM_FMTBIT_S24_LE)
62
63#define WCD934X_FORMATS_S16_S24_S32_LE (SNDRV_PCM_FMTBIT_S16_LE | \
64 SNDRV_PCM_FMTBIT_S24_LE | \
65 SNDRV_PCM_FMTBIT_S32_LE)
66
67#define WCD934X_FORMATS_S16_LE (SNDRV_PCM_FMTBIT_S16_LE)
68
69/* Macros for packing register writes into a U32 */
70#define WCD934X_PACKED_REG_SIZE sizeof(u32)
71#define WCD934X_CODEC_UNPACK_ENTRY(packed, reg, mask, val) \
72 do { \
73 ((reg) = ((packed >> 16) & (0xffff))); \
74 ((mask) = ((packed >> 8) & (0xff))); \
75 ((val) = ((packed) & (0xff))); \
76 } while (0)
77
78#define STRING(name) #name
79#define WCD_DAPM_ENUM(name, reg, offset, text) \
80static SOC_ENUM_SINGLE_DECL(name##_enum, reg, offset, text); \
81static const struct snd_kcontrol_new name##_mux = \
82 SOC_DAPM_ENUM(STRING(name), name##_enum)
83
84#define WCD_DAPM_ENUM_EXT(name, reg, offset, text, getname, putname) \
85static SOC_ENUM_SINGLE_DECL(name##_enum, reg, offset, text); \
86static const struct snd_kcontrol_new name##_mux = \
87 SOC_DAPM_ENUM_EXT(STRING(name), name##_enum, getname, putname)
88
89#define WCD_DAPM_MUX(name, shift, kctl) \
90 SND_SOC_DAPM_MUX(name, SND_SOC_NOPM, shift, 0, &kctl##_mux)
91
92/*
93 * Timeout in milli seconds and it is the wait time for
94 * slim channel removal interrupt to receive.
95 */
96#define WCD934X_SLIM_CLOSE_TIMEOUT 1000
97#define WCD934X_SLIM_IRQ_OVERFLOW (1 << 0)
98#define WCD934X_SLIM_IRQ_UNDERFLOW (1 << 1)
99#define WCD934X_SLIM_IRQ_PORT_CLOSED (1 << 2)
100#define WCD934X_MCLK_CLK_12P288MHZ 12288000
101#define WCD934X_MCLK_CLK_9P6MHZ 9600000
102
103#define WCD934X_INTERP_MUX_NUM_INPUTS 3
104#define WCD934X_NUM_INTERPOLATORS 9
105#define WCD934X_NUM_DECIMATORS 9
106#define WCD934X_RX_PATH_CTL_OFFSET 20
107
108#define BYTE_BIT_MASK(nr) (1 << ((nr) % BITS_PER_BYTE))
109
110#define WCD934X_REG_BITS 8
111#define WCD934X_MAX_VALID_ADC_MUX 13
112#define WCD934X_INVALID_ADC_MUX 9
113
114#define WCD934X_AMIC_PWR_LEVEL_LP 0
115#define WCD934X_AMIC_PWR_LEVEL_DEFAULT 1
116#define WCD934X_AMIC_PWR_LEVEL_HP 2
117#define WCD934X_AMIC_PWR_LVL_MASK 0x60
118#define WCD934X_AMIC_PWR_LVL_SHIFT 0x5
119
120#define WCD934X_DEC_PWR_LVL_MASK 0x06
121#define WCD934X_DEC_PWR_LVL_LP 0x02
122#define WCD934X_DEC_PWR_LVL_HP 0x04
123#define WCD934X_DEC_PWR_LVL_DF 0x00
124#define WCD934X_STRING_LEN 100
125
126#define WCD934X_DIG_CORE_REG_MIN WCD934X_CDC_ANC0_CLK_RESET_CTL
127#define WCD934X_DIG_CORE_REG_MAX 0xFFF
128
129#define WCD934X_MAX_MICBIAS 4
130#define DAPM_MICBIAS1_STANDALONE "MIC BIAS1 Standalone"
131#define DAPM_MICBIAS2_STANDALONE "MIC BIAS2 Standalone"
132#define DAPM_MICBIAS3_STANDALONE "MIC BIAS3 Standalone"
133#define DAPM_MICBIAS4_STANDALONE "MIC BIAS4 Standalone"
134
135#define TX_HPF_CUT_OFF_FREQ_MASK 0x60
136#define CF_MIN_3DB_4HZ 0x0
137#define CF_MIN_3DB_75HZ 0x1
138#define CF_MIN_3DB_150HZ 0x2
139
140#define CPE_ERR_WDOG_BITE BIT(0)
141#define CPE_FATAL_IRQS CPE_ERR_WDOG_BITE
142
143#define WCD934X_MAD_AUDIO_FIRMWARE_PATH "wcd934x/wcd934x_mad_audio.bin"
144
145#define TAVIL_VERSION_ENTRY_SIZE 17
146
147#define WCD934X_DIG_CORE_COLLAPSE_TIMER_MS (5 * 1000)
148
149enum {
150 POWER_COLLAPSE,
151 POWER_RESUME,
152};
153
154static int dig_core_collapse_enable = 1;
155module_param(dig_core_collapse_enable, int, 0664);
156MODULE_PARM_DESC(dig_core_collapse_enable, "enable/disable power gating");
157
158/* dig_core_collapse timer in seconds */
159static int dig_core_collapse_timer = (WCD934X_DIG_CORE_COLLAPSE_TIMER_MS/1000);
160module_param(dig_core_collapse_timer, int, 0664);
161MODULE_PARM_DESC(dig_core_collapse_timer, "timer for power gating");
162
163#define TAVIL_HPH_REG_RANGE_1 (WCD934X_HPH_R_DAC_CTL - WCD934X_HPH_CNP_EN + 1)
164#define TAVIL_HPH_REG_RANGE_2 (WCD934X_HPH_NEW_ANA_HPH3 -\
165 WCD934X_HPH_NEW_ANA_HPH2 + 1)
166#define TAVIL_HPH_REG_RANGE_3 (WCD934X_HPH_NEW_INT_PA_RDAC_MISC3 -\
167 WCD934X_HPH_NEW_INT_RDAC_GAIN_CTL + 1)
168#define TAVIL_HPH_TOTAL_REG (TAVIL_HPH_REG_RANGE_1 + TAVIL_HPH_REG_RANGE_2 +\
169 TAVIL_HPH_REG_RANGE_3)
170
171enum {
172 VI_SENSE_1,
173 VI_SENSE_2,
174 AUDIO_NOMINAL,
175 HPH_PA_DELAY,
Phani Kumar Uppalapatib506bc02016-12-06 16:08:24 -0800176 CLSH_Z_CONFIG,
Meng Wangf45a20d2017-01-18 09:51:58 +0800177 ANC_MIC_AMIC1,
178 ANC_MIC_AMIC2,
179 ANC_MIC_AMIC3,
180 ANC_MIC_AMIC4,
Banajit Goswamide8271c2017-01-18 00:28:59 -0800181};
182
183enum {
184 AIF1_PB = 0,
185 AIF1_CAP,
186 AIF2_PB,
187 AIF2_CAP,
188 AIF3_PB,
189 AIF3_CAP,
190 AIF4_PB,
191 AIF4_VIFEED,
192 AIF4_MAD_TX,
193 NUM_CODEC_DAIS,
194};
195
196enum {
197 INTn_1_INP_SEL_ZERO = 0,
198 INTn_1_INP_SEL_DEC0,
199 INTn_1_INP_SEL_DEC1,
200 INTn_1_INP_SEL_IIR0,
201 INTn_1_INP_SEL_IIR1,
202 INTn_1_INP_SEL_RX0,
203 INTn_1_INP_SEL_RX1,
204 INTn_1_INP_SEL_RX2,
205 INTn_1_INP_SEL_RX3,
206 INTn_1_INP_SEL_RX4,
207 INTn_1_INP_SEL_RX5,
208 INTn_1_INP_SEL_RX6,
209 INTn_1_INP_SEL_RX7,
210};
211
212enum {
213 INTn_2_INP_SEL_ZERO = 0,
214 INTn_2_INP_SEL_RX0,
215 INTn_2_INP_SEL_RX1,
216 INTn_2_INP_SEL_RX2,
217 INTn_2_INP_SEL_RX3,
218 INTn_2_INP_SEL_RX4,
219 INTn_2_INP_SEL_RX5,
220 INTn_2_INP_SEL_RX6,
221 INTn_2_INP_SEL_RX7,
222 INTn_2_INP_SEL_PROXIMITY,
223};
224
225enum {
226 INTERP_MAIN_PATH,
227 INTERP_MIX_PATH,
228};
229
230struct tavil_idle_detect_config {
231 u8 hph_idle_thr;
232 u8 hph_idle_detect_en;
233};
234
235static const struct intr_data wcd934x_intr_table[] = {
236 {WCD9XXX_IRQ_SLIMBUS, false},
237 {WCD934X_IRQ_MBHC_SW_DET, true},
238 {WCD934X_IRQ_MBHC_BUTTON_PRESS_DET, true},
239 {WCD934X_IRQ_MBHC_BUTTON_RELEASE_DET, true},
240 {WCD934X_IRQ_MBHC_ELECT_INS_REM_DET, true},
241 {WCD934X_IRQ_MBHC_ELECT_INS_REM_LEG_DET, true},
242 {WCD934X_IRQ_MISC, false},
243 {WCD934X_IRQ_HPH_PA_CNPL_COMPLETE, false},
244 {WCD934X_IRQ_HPH_PA_CNPR_COMPLETE, false},
245 {WCD934X_IRQ_EAR_PA_CNP_COMPLETE, false},
246 {WCD934X_IRQ_LINE_PA1_CNP_COMPLETE, false},
247 {WCD934X_IRQ_LINE_PA2_CNP_COMPLETE, false},
248 {WCD934X_IRQ_SLNQ_ANALOG_ERROR, false},
249 {WCD934X_IRQ_RESERVED_3, false},
250 {WCD934X_IRQ_HPH_PA_OCPL_FAULT, false},
251 {WCD934X_IRQ_HPH_PA_OCPR_FAULT, false},
252 {WCD934X_IRQ_EAR_PA_OCP_FAULT, false},
253 {WCD934X_IRQ_SOUNDWIRE, false},
254 {WCD934X_IRQ_VDD_DIG_RAMP_COMPLETE, false},
255 {WCD934X_IRQ_RCO_ERROR, false},
256 {WCD934X_IRQ_CPE_ERROR, false},
257 {WCD934X_IRQ_MAD_AUDIO, false},
258 {WCD934X_IRQ_MAD_BEACON, false},
259 {WCD934X_IRQ_CPE1_INTR, true},
260 {WCD934X_IRQ_RESERVED_4, false},
261 {WCD934X_IRQ_MAD_ULTRASOUND, false},
262 {WCD934X_IRQ_VBAT_ATTACK, false},
263 {WCD934X_IRQ_VBAT_RESTORE, false},
264};
265
266struct tavil_cpr_reg_defaults {
267 int wr_data;
268 int wr_addr;
269};
270
271struct interp_sample_rate {
272 int sample_rate;
273 int rate_val;
274};
275
276static struct interp_sample_rate sr_val_tbl[] = {
277 {8000, 0x0}, {16000, 0x1}, {32000, 0x3}, {48000, 0x4}, {96000, 0x5},
278 {192000, 0x6}, {384000, 0x7}, {44100, 0x9}, {88200, 0xA},
279 {176400, 0xB}, {352800, 0xC},
280};
281
282static const struct wcd9xxx_ch tavil_rx_chs[WCD934X_RX_MAX] = {
283 WCD9XXX_CH(WCD934X_RX_PORT_START_NUMBER, 0),
284 WCD9XXX_CH(WCD934X_RX_PORT_START_NUMBER + 1, 1),
285 WCD9XXX_CH(WCD934X_RX_PORT_START_NUMBER + 2, 2),
286 WCD9XXX_CH(WCD934X_RX_PORT_START_NUMBER + 3, 3),
287 WCD9XXX_CH(WCD934X_RX_PORT_START_NUMBER + 4, 4),
288 WCD9XXX_CH(WCD934X_RX_PORT_START_NUMBER + 5, 5),
289 WCD9XXX_CH(WCD934X_RX_PORT_START_NUMBER + 6, 6),
290 WCD9XXX_CH(WCD934X_RX_PORT_START_NUMBER + 7, 7),
291};
292
293static const struct wcd9xxx_ch tavil_tx_chs[WCD934X_TX_MAX] = {
294 WCD9XXX_CH(0, 0),
295 WCD9XXX_CH(1, 1),
296 WCD9XXX_CH(2, 2),
297 WCD9XXX_CH(3, 3),
298 WCD9XXX_CH(4, 4),
299 WCD9XXX_CH(5, 5),
300 WCD9XXX_CH(6, 6),
301 WCD9XXX_CH(7, 7),
302 WCD9XXX_CH(8, 8),
303 WCD9XXX_CH(9, 9),
304 WCD9XXX_CH(10, 10),
305 WCD9XXX_CH(11, 11),
306 WCD9XXX_CH(12, 12),
307 WCD9XXX_CH(13, 13),
308 WCD9XXX_CH(14, 14),
309 WCD9XXX_CH(15, 15),
310};
311
312static const u32 vport_slim_check_table[NUM_CODEC_DAIS] = {
313 0, /* AIF1_PB */
314 BIT(AIF2_CAP) | BIT(AIF3_CAP) | BIT(AIF4_MAD_TX), /* AIF1_CAP */
315 0, /* AIF2_PB */
316 BIT(AIF1_CAP) | BIT(AIF3_CAP) | BIT(AIF4_MAD_TX), /* AIF2_CAP */
317 0, /* AIF3_PB */
318 BIT(AIF1_CAP) | BIT(AIF2_CAP) | BIT(AIF4_MAD_TX), /* AIF3_CAP */
319 0, /* AIF4_PB */
320};
321
322/* Codec supports 2 IIR filters */
323enum {
324 IIR0 = 0,
325 IIR1,
326 IIR_MAX,
327};
328
329/* Each IIR has 5 Filter Stages */
330enum {
331 BAND1 = 0,
332 BAND2,
333 BAND3,
334 BAND4,
335 BAND5,
336 BAND_MAX,
337};
338
339enum {
340 COMPANDER_1, /* HPH_L */
341 COMPANDER_2, /* HPH_R */
342 COMPANDER_3, /* LO1_DIFF */
343 COMPANDER_4, /* LO2_DIFF */
344 COMPANDER_5, /* LO3_SE - not used in Tavil */
345 COMPANDER_6, /* LO4_SE - not used in Tavil */
346 COMPANDER_7, /* SWR SPK CH1 */
347 COMPANDER_8, /* SWR SPK CH2 */
348 COMPANDER_MAX,
349};
350
351enum {
352 ASRC_IN_HPHL,
353 ASRC_IN_LO1,
354 ASRC_IN_HPHR,
355 ASRC_IN_LO2,
356 ASRC_IN_SPKR1,
357 ASRC_IN_SPKR2,
358 ASRC_INVALID,
359};
360
361enum {
362 ASRC0,
363 ASRC1,
364 ASRC2,
365 ASRC3,
366 ASRC_MAX,
367};
368
369enum {
370 CONV_88P2K_TO_384K,
371 CONV_96K_TO_352P8K,
372 CONV_352P8K_TO_384K,
373 CONV_384K_TO_352P8K,
374 CONV_384K_TO_384K,
375 CONV_96K_TO_384K,
376};
377
378static struct afe_param_slimbus_slave_port_cfg tavil_slimbus_slave_port_cfg = {
379 .minor_version = 1,
380 .slimbus_dev_id = AFE_SLIMBUS_DEVICE_1,
381 .slave_dev_pgd_la = 0,
382 .slave_dev_intfdev_la = 0,
383 .bit_width = 16,
384 .data_format = 0,
385 .num_channels = 1
386};
387
388static struct afe_param_cdc_reg_page_cfg tavil_cdc_reg_page_cfg = {
389 .minor_version = AFE_API_VERSION_CDC_REG_PAGE_CFG,
390 .enable = 1,
391 .proc_id = AFE_CDC_REG_PAGE_ASSIGN_PROC_ID_1,
392};
393
394static struct afe_param_cdc_reg_cfg audio_reg_cfg[] = {
395 {
396 1,
397 (WCD934X_REGISTER_START_OFFSET + WCD934X_SOC_MAD_MAIN_CTL_1),
398 HW_MAD_AUDIO_ENABLE, 0x1, WCD934X_REG_BITS, 0
399 },
400 {
401 1,
402 (WCD934X_REGISTER_START_OFFSET + WCD934X_SOC_MAD_AUDIO_CTL_3),
403 HW_MAD_AUDIO_SLEEP_TIME, 0xF, WCD934X_REG_BITS, 0
404 },
405 {
406 1,
407 (WCD934X_REGISTER_START_OFFSET + WCD934X_SOC_MAD_AUDIO_CTL_4),
408 HW_MAD_TX_AUDIO_SWITCH_OFF, 0x1, WCD934X_REG_BITS, 0
409 },
410 {
411 1,
412 (WCD934X_REGISTER_START_OFFSET + WCD934X_INTR_CFG),
413 MAD_AUDIO_INT_DEST_SELECT_REG, 0x2, WCD934X_REG_BITS, 0
414 },
415 {
416 1,
417 (WCD934X_REGISTER_START_OFFSET + WCD934X_INTR_PIN2_MASK3),
418 MAD_AUDIO_INT_MASK_REG, 0x1, WCD934X_REG_BITS, 0
419 },
420 {
421 1,
422 (WCD934X_REGISTER_START_OFFSET + WCD934X_INTR_PIN2_STATUS3),
423 MAD_AUDIO_INT_STATUS_REG, 0x1, WCD934X_REG_BITS, 0
424 },
425 {
426 1,
427 (WCD934X_REGISTER_START_OFFSET + WCD934X_INTR_PIN2_CLEAR3),
428 MAD_AUDIO_INT_CLEAR_REG, 0x1, WCD934X_REG_BITS, 0
429 },
430 {
431 1,
432 (WCD934X_REGISTER_START_OFFSET + WCD934X_SB_PGD_PORT_TX_BASE),
433 SB_PGD_PORT_TX_WATERMARK_N, 0x1E, WCD934X_REG_BITS, 0x1
434 },
435 {
436 1,
437 (WCD934X_REGISTER_START_OFFSET + WCD934X_SB_PGD_PORT_TX_BASE),
438 SB_PGD_PORT_TX_ENABLE_N, 0x1, WCD934X_REG_BITS, 0x1
439 },
440 {
441 1,
442 (WCD934X_REGISTER_START_OFFSET + WCD934X_SB_PGD_PORT_RX_BASE),
443 SB_PGD_PORT_RX_WATERMARK_N, 0x1E, WCD934X_REG_BITS, 0x1
444 },
445 {
446 1,
447 (WCD934X_REGISTER_START_OFFSET + WCD934X_SB_PGD_PORT_RX_BASE),
448 SB_PGD_PORT_RX_ENABLE_N, 0x1, WCD934X_REG_BITS, 0x1
449 },
450 {
451 1,
452 (WCD934X_REGISTER_START_OFFSET +
453 WCD934X_CDC_ANC0_IIR_ADAPT_CTL),
454 AANC_FF_GAIN_ADAPTIVE, 0x4, WCD934X_REG_BITS, 0
455 },
456 {
457 1,
458 (WCD934X_REGISTER_START_OFFSET +
459 WCD934X_CDC_ANC0_IIR_ADAPT_CTL),
460 AANC_FFGAIN_ADAPTIVE_EN, 0x8, WCD934X_REG_BITS, 0
461 },
462 {
463 1,
464 (WCD934X_REGISTER_START_OFFSET +
465 WCD934X_CDC_ANC0_FF_A_GAIN_CTL),
466 AANC_GAIN_CONTROL, 0xFF, WCD934X_REG_BITS, 0
467 },
468 {
469 1,
470 (WCD934X_REGISTER_START_OFFSET +
471 SB_PGD_TX_PORT_MULTI_CHANNEL_0(0)),
472 SB_PGD_TX_PORTn_MULTI_CHNL_0, 0xFF, WCD934X_REG_BITS, 0x4
473 },
474 {
475 1,
476 (WCD934X_REGISTER_START_OFFSET +
477 SB_PGD_TX_PORT_MULTI_CHANNEL_1(0)),
478 SB_PGD_TX_PORTn_MULTI_CHNL_1, 0xFF, WCD934X_REG_BITS, 0x4
479 },
480 {
481 1,
482 (WCD934X_REGISTER_START_OFFSET +
483 SB_PGD_RX_PORT_MULTI_CHANNEL_0(0x180, 0)),
484 SB_PGD_RX_PORTn_MULTI_CHNL_0, 0xFF, WCD934X_REG_BITS, 0x4
485 },
486 {
487 1,
488 (WCD934X_REGISTER_START_OFFSET +
489 SB_PGD_RX_PORT_MULTI_CHANNEL_0(0x181, 0)),
490 SB_PGD_RX_PORTn_MULTI_CHNL_1, 0xFF, WCD934X_REG_BITS, 0x4
491 },
492};
493
494static struct afe_param_cdc_reg_cfg_data tavil_audio_reg_cfg = {
495 .num_registers = ARRAY_SIZE(audio_reg_cfg),
496 .reg_data = audio_reg_cfg,
497};
498
499static struct afe_param_id_cdc_aanc_version tavil_cdc_aanc_version = {
500 .cdc_aanc_minor_version = AFE_API_VERSION_CDC_AANC_VERSION,
501 .aanc_hw_version = AANC_HW_BLOCK_VERSION_2,
502};
503
504static const DECLARE_TLV_DB_SCALE(digital_gain, 0, 1, 0);
505static const DECLARE_TLV_DB_SCALE(line_gain, 0, 7, 1);
506static const DECLARE_TLV_DB_SCALE(analog_gain, 0, 25, 1);
507
508#define WCD934X_TX_UNMUTE_DELAY_MS 25
509
510static int tx_unmute_delay = WCD934X_TX_UNMUTE_DELAY_MS;
511module_param(tx_unmute_delay, int, 0664);
512MODULE_PARM_DESC(tx_unmute_delay, "delay to unmute the tx path");
513
Meng Wangf45a20d2017-01-18 09:51:58 +0800514static void tavil_codec_set_tx_hold(struct snd_soc_codec *, u16, bool);
Banajit Goswamide8271c2017-01-18 00:28:59 -0800515
516/* Hold instance to soundwire platform device */
517struct tavil_swr_ctrl_data {
518 struct platform_device *swr_pdev;
519};
520
521struct wcd_swr_ctrl_platform_data {
522 void *handle; /* holds codec private data */
523 int (*read)(void *handle, int reg);
524 int (*write)(void *handle, int reg, int val);
525 int (*bulk_write)(void *handle, u32 *reg, u32 *val, size_t len);
526 int (*clk)(void *handle, bool enable);
527 int (*handle_irq)(void *handle,
528 irqreturn_t (*swrm_irq_handler)(int irq, void *data),
529 void *swrm_handle, int action);
530};
531
532/* Holds all Soundwire and speaker related information */
533struct wcd934x_swr {
534 struct tavil_swr_ctrl_data *ctrl_data;
535 struct wcd_swr_ctrl_platform_data plat_data;
536 struct mutex read_mutex;
537 struct mutex write_mutex;
538 struct mutex clk_mutex;
539 int spkr_gain_offset;
540 int spkr_mode;
541 int clk_users;
542 int rx_7_count;
543 int rx_8_count;
544};
545
546struct tx_mute_work {
547 struct tavil_priv *tavil;
548 u8 decimator;
549 struct delayed_work dwork;
550};
551
552#define WCD934X_SPK_ANC_EN_DELAY_MS 350
553static int spk_anc_en_delay = WCD934X_SPK_ANC_EN_DELAY_MS;
554module_param(spk_anc_en_delay, int, 0664);
555MODULE_PARM_DESC(spk_anc_en_delay, "delay to enable anc in speaker path");
556
557struct spk_anc_work {
558 struct tavil_priv *tavil;
559 struct delayed_work dwork;
560};
561
562struct hpf_work {
563 struct tavil_priv *tavil;
564 u8 decimator;
565 u8 hpf_cut_off_freq;
566 struct delayed_work dwork;
567};
568
569struct tavil_priv {
570 struct device *dev;
571 struct wcd9xxx *wcd9xxx;
572 struct snd_soc_codec *codec;
573 u32 rx_bias_count;
574 s32 dmic_0_1_clk_cnt;
575 s32 dmic_2_3_clk_cnt;
576 s32 dmic_4_5_clk_cnt;
577 s32 micb_ref[TAVIL_MAX_MICBIAS];
578 s32 pullup_ref[TAVIL_MAX_MICBIAS];
579
580 /* ANC related */
581 u32 anc_slot;
582 bool anc_func;
583
584 /* compander */
585 int comp_enabled[COMPANDER_MAX];
586 int ear_spkr_gain;
587
588 /* class h specific data */
589 struct wcd_clsh_cdc_data clsh_d;
590 /* Tavil Interpolator Mode Select for EAR, HPH_L and HPH_R */
591 u32 hph_mode;
592
593 /* Mad switch reference count */
594 int mad_switch_cnt;
595
596 /* track tavil interface type */
597 u8 intf_type;
598
599 /* to track the status */
600 unsigned long status_mask;
601
602 struct afe_param_cdc_slimbus_slave_cfg slimbus_slave_cfg;
603
604 /* num of slim ports required */
605 struct wcd9xxx_codec_dai_data dai[NUM_CODEC_DAIS];
606 /* Port values for Rx and Tx codec_dai */
607 unsigned int rx_port_value[WCD934X_RX_MAX];
608 unsigned int tx_port_value;
609
610 struct wcd9xxx_resmgr_v2 *resmgr;
611 struct wcd934x_swr swr;
612 struct mutex micb_lock;
613
614 struct delayed_work power_gate_work;
615 struct mutex power_lock;
616
617 struct clk *wcd_ext_clk;
618
619 /* mbhc module */
620 struct wcd934x_mbhc *mbhc;
621
622 struct mutex codec_mutex;
623 struct work_struct tavil_add_child_devices_work;
624 struct hpf_work tx_hpf_work[WCD934X_NUM_DECIMATORS];
625 struct tx_mute_work tx_mute_dwork[WCD934X_NUM_DECIMATORS];
626 struct spk_anc_work spk_anc_dwork;
627
628 unsigned int vi_feed_value;
629
630 /* DSP control */
631 struct wcd_dsp_cntl *wdsp_cntl;
632
633 /* cal info for codec */
634 struct fw_info *fw_data;
635
636 /* Entry for version info */
637 struct snd_info_entry *entry;
638 struct snd_info_entry *version_entry;
639
640 /* SVS voting related */
641 struct mutex svs_mutex;
642 int svs_ref_cnt;
643
644 int native_clk_users;
645 /* ASRC users count */
646 int asrc_users[ASRC_MAX];
647 int asrc_output_mode[ASRC_MAX];
648 /* Main path clock users count */
649 int main_clk_users[WCD934X_NUM_INTERPOLATORS];
650 struct tavil_dsd_config *dsd_config;
651 struct tavil_idle_detect_config idle_det_cfg;
652
653 int power_active_ref;
654};
655
656static const struct tavil_reg_mask_val tavil_spkr_default[] = {
657 {WCD934X_CDC_COMPANDER7_CTL3, 0x80, 0x80},
658 {WCD934X_CDC_COMPANDER8_CTL3, 0x80, 0x80},
659 {WCD934X_CDC_COMPANDER7_CTL7, 0x01, 0x01},
660 {WCD934X_CDC_COMPANDER8_CTL7, 0x01, 0x01},
661 {WCD934X_CDC_BOOST0_BOOST_CTL, 0x7C, 0x50},
662 {WCD934X_CDC_BOOST1_BOOST_CTL, 0x7C, 0x50},
663};
664
665static const struct tavil_reg_mask_val tavil_spkr_mode1[] = {
666 {WCD934X_CDC_COMPANDER7_CTL3, 0x80, 0x00},
667 {WCD934X_CDC_COMPANDER8_CTL3, 0x80, 0x00},
668 {WCD934X_CDC_COMPANDER7_CTL7, 0x01, 0x00},
669 {WCD934X_CDC_COMPANDER8_CTL7, 0x01, 0x00},
670 {WCD934X_CDC_BOOST0_BOOST_CTL, 0x7C, 0x44},
671 {WCD934X_CDC_BOOST1_BOOST_CTL, 0x7C, 0x44},
672};
673
674static int __tavil_enable_efuse_sensing(struct tavil_priv *tavil);
675
676/*
677 * wcd934x_get_codec_info: Get codec specific information
678 *
679 * @wcd9xxx: pointer to wcd9xxx structure
680 * @wcd_type: pointer to wcd9xxx_codec_type structure
681 *
682 * Returns 0 for success or negative error code for failure
683 */
684int wcd934x_get_codec_info(struct wcd9xxx *wcd9xxx,
685 struct wcd9xxx_codec_type *wcd_type)
686{
687 u16 id_minor, id_major;
688 struct regmap *wcd_regmap;
689 int rc, version = -1;
690
691 if (!wcd9xxx || !wcd_type)
692 return -EINVAL;
693
694 if (!wcd9xxx->regmap) {
695 dev_err(wcd9xxx->dev, "%s: wcd9xxx regmap is null\n", __func__);
696 return -EINVAL;
697 }
698 wcd_regmap = wcd9xxx->regmap;
699
700 rc = regmap_bulk_read(wcd_regmap, WCD934X_CHIP_TIER_CTRL_CHIP_ID_BYTE0,
701 (u8 *)&id_minor, sizeof(u16));
702 if (rc)
703 return -EINVAL;
704
705 rc = regmap_bulk_read(wcd_regmap, WCD934X_CHIP_TIER_CTRL_CHIP_ID_BYTE2,
706 (u8 *)&id_major, sizeof(u16));
707 if (rc)
708 return -EINVAL;
709
710 dev_info(wcd9xxx->dev, "%s: wcd9xxx chip id major 0x%x, minor 0x%x\n",
711 __func__, id_major, id_minor);
712
713 if (id_major != TAVIL_MAJOR)
714 goto version_unknown;
715
716 /*
717 * As fine version info cannot be retrieved before tavil probe.
718 * Assign coarse versions for possible future use before tavil probe.
719 */
720 if (id_minor == cpu_to_le16(0))
721 version = TAVIL_VERSION_1_0;
722 else if (id_minor == cpu_to_le16(0x01))
723 version = TAVIL_VERSION_1_1;
724
725version_unknown:
726 if (version < 0)
727 dev_err(wcd9xxx->dev, "%s: wcd934x version unknown\n",
728 __func__);
729
730 /* Fill codec type info */
731 wcd_type->id_major = id_major;
732 wcd_type->id_minor = id_minor;
733 wcd_type->num_irqs = WCD934X_NUM_IRQS;
734 wcd_type->version = version;
735 wcd_type->slim_slave_type = WCD9XXX_SLIM_SLAVE_ADDR_TYPE_1;
736 wcd_type->i2c_chip_status = 0x01;
737 wcd_type->intr_tbl = wcd934x_intr_table;
738 wcd_type->intr_tbl_size = ARRAY_SIZE(wcd934x_intr_table);
739
740 wcd_type->intr_reg[WCD9XXX_INTR_STATUS_BASE] =
741 WCD934X_INTR_PIN1_STATUS0;
742 wcd_type->intr_reg[WCD9XXX_INTR_CLEAR_BASE] =
743 WCD934X_INTR_PIN1_CLEAR0;
744 wcd_type->intr_reg[WCD9XXX_INTR_MASK_BASE] =
745 WCD934X_INTR_PIN1_MASK0;
746 wcd_type->intr_reg[WCD9XXX_INTR_LEVEL_BASE] =
747 WCD934X_INTR_LEVEL0;
748 wcd_type->intr_reg[WCD9XXX_INTR_CLR_COMMIT] =
749 WCD934X_INTR_CLR_COMMIT;
750
751 return rc;
752}
753EXPORT_SYMBOL(wcd934x_get_codec_info);
754
755/*
756 * wcd934x_bringdown: Bringdown WCD Codec
757 *
758 * @wcd9xxx: Pointer to wcd9xxx structure
759 *
760 * Returns 0 for success or negative error code for failure
761 */
762int wcd934x_bringdown(struct wcd9xxx *wcd9xxx)
763{
764 if (!wcd9xxx || !wcd9xxx->regmap)
765 return -EINVAL;
766
767 regmap_write(wcd9xxx->regmap, WCD934X_CODEC_RPM_PWR_CDC_DIG_HM_CTL,
768 0x04);
769
770 return 0;
771}
772EXPORT_SYMBOL(wcd934x_bringdown);
773
774/*
775 * wcd934x_bringup: Bringup WCD Codec
776 *
777 * @wcd9xxx: Pointer to the wcd9xxx structure
778 *
779 * Returns 0 for success or negative error code for failure
780 */
781int wcd934x_bringup(struct wcd9xxx *wcd9xxx)
782{
783 struct regmap *wcd_regmap;
784
785 if (!wcd9xxx)
786 return -EINVAL;
787
788 if (!wcd9xxx->regmap) {
789 dev_err(wcd9xxx->dev, "%s: wcd9xxx regmap is null!\n",
790 __func__);
791 return -EINVAL;
792 }
793 wcd_regmap = wcd9xxx->regmap;
794
795 regmap_write(wcd_regmap, WCD934X_CODEC_RPM_RST_CTL, 0x01);
796 regmap_write(wcd_regmap, WCD934X_SIDO_NEW_VOUT_A_STARTUP, 0x19);
797 regmap_write(wcd_regmap, WCD934X_SIDO_NEW_VOUT_D_STARTUP, 0x15);
798 regmap_write(wcd_regmap, WCD934X_CODEC_RPM_PWR_CDC_DIG_HM_CTL, 0x5);
799 regmap_write(wcd_regmap, WCD934X_CODEC_RPM_PWR_CDC_DIG_HM_CTL, 0x7);
800 regmap_write(wcd_regmap, WCD934X_CODEC_RPM_PWR_CDC_DIG_HM_CTL, 0x3);
801 regmap_write(wcd_regmap, WCD934X_CODEC_RPM_RST_CTL, 0x3);
802 regmap_write(wcd_regmap, WCD934X_CODEC_RPM_RST_CTL, 0x7);
803
804 return 0;
805}
806EXPORT_SYMBOL(wcd934x_bringup);
807
808/**
809 * tavil_set_spkr_gain_offset - offset the speaker path
810 * gain with the given offset value.
811 *
812 * @codec: codec instance
813 * @offset: Indicates speaker path gain offset value.
814 *
815 * Returns 0 on success or -EINVAL on error.
816 */
817int tavil_set_spkr_gain_offset(struct snd_soc_codec *codec, int offset)
818{
819 struct tavil_priv *priv = snd_soc_codec_get_drvdata(codec);
820
821 if (!priv)
822 return -EINVAL;
823
824 priv->swr.spkr_gain_offset = offset;
825 return 0;
826}
827EXPORT_SYMBOL(tavil_set_spkr_gain_offset);
828
829/**
830 * tavil_set_spkr_mode - Configures speaker compander and smartboost
831 * settings based on speaker mode.
832 *
833 * @codec: codec instance
834 * @mode: Indicates speaker configuration mode.
835 *
836 * Returns 0 on success or -EINVAL on error.
837 */
838int tavil_set_spkr_mode(struct snd_soc_codec *codec, int mode)
839{
840 struct tavil_priv *priv = snd_soc_codec_get_drvdata(codec);
841 int i;
842 const struct tavil_reg_mask_val *regs;
843 int size;
844
845 if (!priv)
846 return -EINVAL;
847
848 switch (mode) {
849 case WCD934X_SPKR_MODE_1:
850 regs = tavil_spkr_mode1;
851 size = ARRAY_SIZE(tavil_spkr_mode1);
852 break;
853 default:
854 regs = tavil_spkr_default;
855 size = ARRAY_SIZE(tavil_spkr_default);
856 break;
857 }
858
859 priv->swr.spkr_mode = mode;
860 for (i = 0; i < size; i++)
861 snd_soc_update_bits(codec, regs[i].reg,
862 regs[i].mask, regs[i].val);
863 return 0;
864}
865EXPORT_SYMBOL(tavil_set_spkr_mode);
866
867/**
868 * tavil_get_afe_config - returns specific codec configuration to afe to write
869 *
870 * @codec: codec instance
871 * @config_type: Indicates type of configuration to write.
872 */
873void *tavil_get_afe_config(struct snd_soc_codec *codec,
874 enum afe_config_type config_type)
875{
876 struct tavil_priv *priv = snd_soc_codec_get_drvdata(codec);
877
878 switch (config_type) {
879 case AFE_SLIMBUS_SLAVE_CONFIG:
880 return &priv->slimbus_slave_cfg;
881 case AFE_CDC_REGISTERS_CONFIG:
882 return &tavil_audio_reg_cfg;
883 case AFE_SLIMBUS_SLAVE_PORT_CONFIG:
884 return &tavil_slimbus_slave_port_cfg;
885 case AFE_AANC_VERSION:
886 return &tavil_cdc_aanc_version;
887 case AFE_CDC_REGISTER_PAGE_CONFIG:
888 return &tavil_cdc_reg_page_cfg;
889 default:
890 dev_info(codec->dev, "%s: Unknown config_type 0x%x\n",
891 __func__, config_type);
892 return NULL;
893 }
894}
895EXPORT_SYMBOL(tavil_get_afe_config);
896
897static bool is_tavil_playback_dai(int dai_id)
898{
899 if ((dai_id == AIF1_PB) || (dai_id == AIF2_PB) ||
900 (dai_id == AIF3_PB) || (dai_id == AIF4_PB))
901 return true;
902
903 return false;
904}
905
906static int tavil_find_playback_dai_id_for_port(int port_id,
907 struct tavil_priv *tavil)
908{
909 struct wcd9xxx_codec_dai_data *dai;
910 struct wcd9xxx_ch *ch;
911 int i, slv_port_id;
912
913 for (i = AIF1_PB; i < NUM_CODEC_DAIS; i++) {
914 if (!is_tavil_playback_dai(i))
915 continue;
916
917 dai = &tavil->dai[i];
918 list_for_each_entry(ch, &dai->wcd9xxx_ch_list, list) {
919 slv_port_id = wcd9xxx_get_slave_port(ch->ch_num);
920 if ((slv_port_id > 0) && (slv_port_id == port_id))
921 return i;
922 }
923 }
924
925 return -EINVAL;
926}
927
928static void tavil_vote_svs(struct tavil_priv *tavil, bool vote)
929{
930 struct wcd9xxx *wcd9xxx;
931
932 wcd9xxx = tavil->wcd9xxx;
933
934 mutex_lock(&tavil->svs_mutex);
935 if (vote) {
936 tavil->svs_ref_cnt++;
937 if (tavil->svs_ref_cnt == 1)
938 regmap_update_bits(wcd9xxx->regmap,
939 WCD934X_CPE_SS_PWR_SYS_PSTATE_CTL_0,
940 0x01, 0x01);
941 } else {
942 /* Do not decrement ref count if it is already 0 */
943 if (tavil->svs_ref_cnt == 0)
944 goto done;
945
946 tavil->svs_ref_cnt--;
947 if (tavil->svs_ref_cnt == 0)
948 regmap_update_bits(wcd9xxx->regmap,
949 WCD934X_CPE_SS_PWR_SYS_PSTATE_CTL_0,
950 0x01, 0x00);
951 }
952done:
953 dev_dbg(tavil->dev, "%s: vote = %s, updated ref cnt = %u\n", __func__,
954 vote ? "vote" : "Unvote", tavil->svs_ref_cnt);
955 mutex_unlock(&tavil->svs_mutex);
956}
957
958static int tavil_get_anc_slot(struct snd_kcontrol *kcontrol,
959 struct snd_ctl_elem_value *ucontrol)
960{
961 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
962 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
963
964 ucontrol->value.integer.value[0] = tavil->anc_slot;
965 return 0;
966}
967
968static int tavil_put_anc_slot(struct snd_kcontrol *kcontrol,
969 struct snd_ctl_elem_value *ucontrol)
970{
971 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
972 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
973
974 tavil->anc_slot = ucontrol->value.integer.value[0];
975 return 0;
976}
977
978static int tavil_get_anc_func(struct snd_kcontrol *kcontrol,
979 struct snd_ctl_elem_value *ucontrol)
980{
981 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
982 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
983
984 ucontrol->value.integer.value[0] = (tavil->anc_func == true ? 1 : 0);
985 return 0;
986}
987
988static int tavil_put_anc_func(struct snd_kcontrol *kcontrol,
989 struct snd_ctl_elem_value *ucontrol)
990{
991 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
992 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
993 struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
994
995 mutex_lock(&tavil->codec_mutex);
996 tavil->anc_func = (!ucontrol->value.integer.value[0] ? false : true);
997 dev_dbg(codec->dev, "%s: anc_func %x", __func__, tavil->anc_func);
998
999 if (tavil->anc_func == true) {
1000 snd_soc_dapm_enable_pin(dapm, "ANC EAR PA");
1001 snd_soc_dapm_enable_pin(dapm, "ANC EAR");
1002 snd_soc_dapm_enable_pin(dapm, "ANC SPK1 PA");
Meng Wangf45a20d2017-01-18 09:51:58 +08001003 snd_soc_dapm_enable_pin(dapm, "ANC HPHL PA");
1004 snd_soc_dapm_enable_pin(dapm, "ANC HPHR PA");
1005 snd_soc_dapm_enable_pin(dapm, "ANC HPHL");
1006 snd_soc_dapm_enable_pin(dapm, "ANC HPHR");
Banajit Goswamide8271c2017-01-18 00:28:59 -08001007 snd_soc_dapm_disable_pin(dapm, "EAR PA");
1008 snd_soc_dapm_disable_pin(dapm, "EAR");
Meng Wangf45a20d2017-01-18 09:51:58 +08001009 snd_soc_dapm_disable_pin(dapm, "HPHL PA");
1010 snd_soc_dapm_disable_pin(dapm, "HPHR PA");
1011 snd_soc_dapm_disable_pin(dapm, "HPHL");
1012 snd_soc_dapm_disable_pin(dapm, "HPHR");
Banajit Goswamide8271c2017-01-18 00:28:59 -08001013 } else {
1014 snd_soc_dapm_disable_pin(dapm, "ANC EAR PA");
1015 snd_soc_dapm_disable_pin(dapm, "ANC EAR");
1016 snd_soc_dapm_disable_pin(dapm, "ANC SPK1 PA");
Meng Wangf45a20d2017-01-18 09:51:58 +08001017 snd_soc_dapm_disable_pin(dapm, "ANC HPHL PA");
1018 snd_soc_dapm_disable_pin(dapm, "ANC HPHR PA");
1019 snd_soc_dapm_disable_pin(dapm, "ANC HPHL");
1020 snd_soc_dapm_disable_pin(dapm, "ANC HPHR");
Banajit Goswamide8271c2017-01-18 00:28:59 -08001021 snd_soc_dapm_enable_pin(dapm, "EAR PA");
1022 snd_soc_dapm_enable_pin(dapm, "EAR");
Meng Wangf45a20d2017-01-18 09:51:58 +08001023 snd_soc_dapm_enable_pin(dapm, "HPHL");
1024 snd_soc_dapm_enable_pin(dapm, "HPHR");
1025 snd_soc_dapm_enable_pin(dapm, "HPHL PA");
1026 snd_soc_dapm_enable_pin(dapm, "HPHR PA");
Banajit Goswamide8271c2017-01-18 00:28:59 -08001027 }
1028 mutex_unlock(&tavil->codec_mutex);
1029
1030 snd_soc_dapm_sync(dapm);
1031 return 0;
1032}
1033
1034static int tavil_codec_enable_anc(struct snd_soc_dapm_widget *w,
1035 struct snd_kcontrol *kcontrol, int event)
1036{
1037 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
1038 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
1039 const char *filename;
1040 const struct firmware *fw;
1041 int i;
1042 int ret = 0;
1043 int num_anc_slots;
1044 struct wcd9xxx_anc_header *anc_head;
1045 struct firmware_cal *hwdep_cal = NULL;
1046 u32 anc_writes_size = 0;
1047 u32 anc_cal_size = 0;
1048 int anc_size_remaining;
1049 u32 *anc_ptr;
1050 u16 reg;
1051 u8 mask, val;
1052 size_t cal_size;
1053 const void *data;
1054
1055 if (!tavil->anc_func)
1056 return 0;
1057
1058 switch (event) {
1059 case SND_SOC_DAPM_PRE_PMU:
1060 hwdep_cal = wcdcal_get_fw_cal(tavil->fw_data, WCD9XXX_ANC_CAL);
1061 if (hwdep_cal) {
1062 data = hwdep_cal->data;
1063 cal_size = hwdep_cal->size;
1064 dev_dbg(codec->dev, "%s: using hwdep calibration, cal_size %zd",
1065 __func__, cal_size);
1066 } else {
1067 filename = "WCD934X/WCD934X_anc.bin";
1068 ret = request_firmware(&fw, filename, codec->dev);
Xiaoyu Ye1a2d8bd92017-01-31 18:54:15 -08001069 if (ret < 0) {
Banajit Goswamide8271c2017-01-18 00:28:59 -08001070 dev_err(codec->dev, "%s: Failed to acquire ANC data: %d\n",
1071 __func__, ret);
1072 return ret;
1073 }
1074 if (!fw) {
1075 dev_err(codec->dev, "%s: Failed to get anc fw\n",
1076 __func__);
1077 return -ENODEV;
1078 }
1079 data = fw->data;
1080 cal_size = fw->size;
1081 dev_dbg(codec->dev, "%s: using request_firmware calibration\n",
1082 __func__);
1083 }
1084 if (cal_size < sizeof(struct wcd9xxx_anc_header)) {
1085 dev_err(codec->dev, "%s: Invalid cal_size %zd\n",
1086 __func__, cal_size);
1087 ret = -EINVAL;
1088 goto err;
1089 }
1090 /* First number is the number of register writes */
1091 anc_head = (struct wcd9xxx_anc_header *)(data);
1092 anc_ptr = (u32 *)(data + sizeof(struct wcd9xxx_anc_header));
1093 anc_size_remaining = cal_size -
1094 sizeof(struct wcd9xxx_anc_header);
1095 num_anc_slots = anc_head->num_anc_slots;
1096
1097 if (tavil->anc_slot >= num_anc_slots) {
1098 dev_err(codec->dev, "%s: Invalid ANC slot selected\n",
1099 __func__);
1100 ret = -EINVAL;
1101 goto err;
1102 }
1103 for (i = 0; i < num_anc_slots; i++) {
1104 if (anc_size_remaining < WCD934X_PACKED_REG_SIZE) {
1105 dev_err(codec->dev, "%s: Invalid register format\n",
1106 __func__);
1107 ret = -EINVAL;
1108 goto err;
1109 }
1110 anc_writes_size = (u32)(*anc_ptr);
1111 anc_size_remaining -= sizeof(u32);
1112 anc_ptr += 1;
1113
1114 if ((anc_writes_size * WCD934X_PACKED_REG_SIZE) >
1115 anc_size_remaining) {
1116 dev_err(codec->dev, "%s: Invalid register format\n",
1117 __func__);
1118 ret = -EINVAL;
1119 goto err;
1120 }
1121
1122 if (tavil->anc_slot == i)
1123 break;
1124
1125 anc_size_remaining -= (anc_writes_size *
1126 WCD934X_PACKED_REG_SIZE);
1127 anc_ptr += anc_writes_size;
1128 }
1129 if (i == num_anc_slots) {
1130 dev_err(codec->dev, "%s: Selected ANC slot not present\n",
1131 __func__);
1132 ret = -EINVAL;
1133 goto err;
1134 }
1135
1136 anc_cal_size = anc_writes_size;
1137 for (i = 0; i < anc_writes_size; i++) {
1138 WCD934X_CODEC_UNPACK_ENTRY(anc_ptr[i], reg, mask, val);
1139 snd_soc_write(codec, reg, (val & mask));
1140 }
1141
1142 /* Rate converter clk enable and set bypass mode */
Meng Wangf45a20d2017-01-18 09:51:58 +08001143 if (!strcmp(w->name, "RX INT0 DAC") ||
1144 !strcmp(w->name, "RX INT1 DAC") ||
1145 !strcmp(w->name, "ANC SPK1 PA")) {
1146 snd_soc_update_bits(codec,
1147 WCD934X_CDC_ANC0_RC_COMMON_CTL,
1148 0x05, 0x05);
1149 if (!strcmp(w->name, "RX INT1 DAC")) {
1150 snd_soc_update_bits(codec,
1151 WCD934X_CDC_ANC0_FIFO_COMMON_CTL,
1152 0x66, 0x66);
1153 }
1154 } else if (!strcmp(w->name, "RX INT2 DAC")) {
1155 snd_soc_update_bits(codec,
1156 WCD934X_CDC_ANC1_RC_COMMON_CTL,
1157 0x05, 0x05);
1158 snd_soc_update_bits(codec,
1159 WCD934X_CDC_ANC1_FIFO_COMMON_CTL,
1160 0x66, 0x66);
1161 }
1162 if (!strcmp(w->name, "RX INT1 DAC"))
1163 snd_soc_update_bits(codec,
1164 WCD934X_CDC_ANC0_CLK_RESET_CTL, 0x08, 0x08);
1165 else if (!strcmp(w->name, "RX INT2 DAC"))
1166 snd_soc_update_bits(codec,
1167 WCD934X_CDC_ANC1_CLK_RESET_CTL, 0x08, 0x08);
1168
Banajit Goswamide8271c2017-01-18 00:28:59 -08001169 if (!hwdep_cal)
1170 release_firmware(fw);
1171 break;
Meng Wangf45a20d2017-01-18 09:51:58 +08001172
1173 case SND_SOC_DAPM_POST_PMU:
1174 if (!strcmp(w->name, "ANC HPHL PA") ||
1175 !strcmp(w->name, "ANC HPHR PA")) {
1176 /* Remove ANC Rx from reset */
1177 snd_soc_update_bits(codec,
1178 WCD934X_CDC_ANC0_CLK_RESET_CTL,
1179 0x08, 0x00);
1180 snd_soc_update_bits(codec,
1181 WCD934X_CDC_ANC1_CLK_RESET_CTL,
1182 0x08, 0x00);
1183 }
1184
1185 break;
1186
Banajit Goswamide8271c2017-01-18 00:28:59 -08001187 case SND_SOC_DAPM_POST_PMD:
1188 snd_soc_update_bits(codec, WCD934X_CDC_ANC0_RC_COMMON_CTL,
1189 0x05, 0x00);
1190 if (!strcmp(w->name, "ANC EAR PA") ||
Meng Wangf45a20d2017-01-18 09:51:58 +08001191 !strcmp(w->name, "ANC SPK1 PA") ||
1192 !strcmp(w->name, "ANC HPHL PA")) {
Banajit Goswamide8271c2017-01-18 00:28:59 -08001193 snd_soc_update_bits(codec, WCD934X_CDC_ANC0_MODE_1_CTL,
1194 0x30, 0x00);
1195 msleep(50);
1196 snd_soc_update_bits(codec, WCD934X_CDC_ANC0_MODE_1_CTL,
1197 0x01, 0x00);
1198 snd_soc_update_bits(codec,
1199 WCD934X_CDC_ANC0_CLK_RESET_CTL,
1200 0x38, 0x38);
1201 snd_soc_update_bits(codec,
1202 WCD934X_CDC_ANC0_CLK_RESET_CTL,
1203 0x07, 0x00);
1204 snd_soc_update_bits(codec,
1205 WCD934X_CDC_ANC0_CLK_RESET_CTL,
1206 0x38, 0x00);
Meng Wangf45a20d2017-01-18 09:51:58 +08001207 } else if (!strcmp(w->name, "ANC HPHR PA")) {
1208 snd_soc_update_bits(codec, WCD934X_CDC_ANC1_MODE_1_CTL,
1209 0x30, 0x00);
1210 msleep(50);
1211 snd_soc_update_bits(codec, WCD934X_CDC_ANC1_MODE_1_CTL,
1212 0x01, 0x00);
1213 snd_soc_update_bits(codec,
1214 WCD934X_CDC_ANC1_CLK_RESET_CTL,
1215 0x38, 0x38);
1216 snd_soc_update_bits(codec,
1217 WCD934X_CDC_ANC1_CLK_RESET_CTL,
1218 0x07, 0x00);
1219 snd_soc_update_bits(codec,
1220 WCD934X_CDC_ANC1_CLK_RESET_CTL,
1221 0x38, 0x00);
Banajit Goswamide8271c2017-01-18 00:28:59 -08001222 }
1223 break;
1224 }
1225
1226 return 0;
1227err:
1228 if (!hwdep_cal)
1229 release_firmware(fw);
1230 return ret;
1231}
1232
1233static int tavil_vi_feed_mixer_get(struct snd_kcontrol *kcontrol,
1234 struct snd_ctl_elem_value *ucontrol)
1235{
1236 struct snd_soc_dapm_widget_list *wlist =
1237 dapm_kcontrol_get_wlist(kcontrol);
1238 struct snd_soc_dapm_widget *widget = wlist->widgets[0];
1239 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(widget->dapm);
1240 struct tavil_priv *tavil_p = snd_soc_codec_get_drvdata(codec);
1241
1242 ucontrol->value.integer.value[0] = tavil_p->vi_feed_value;
1243
1244 return 0;
1245}
1246
1247static int tavil_vi_feed_mixer_put(struct snd_kcontrol *kcontrol,
1248 struct snd_ctl_elem_value *ucontrol)
1249{
1250 struct snd_soc_dapm_widget_list *wlist =
1251 dapm_kcontrol_get_wlist(kcontrol);
1252 struct snd_soc_dapm_widget *widget = wlist->widgets[0];
1253 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(widget->dapm);
1254 struct tavil_priv *tavil_p = snd_soc_codec_get_drvdata(codec);
1255 struct wcd9xxx *core = dev_get_drvdata(codec->dev->parent);
1256 struct soc_multi_mixer_control *mixer =
1257 ((struct soc_multi_mixer_control *)kcontrol->private_value);
1258 u32 dai_id = widget->shift;
1259 u32 port_id = mixer->shift;
1260 u32 enable = ucontrol->value.integer.value[0];
1261
1262 dev_dbg(codec->dev, "%s: enable: %d, port_id:%d, dai_id: %d\n",
1263 __func__, enable, port_id, dai_id);
1264
1265 tavil_p->vi_feed_value = ucontrol->value.integer.value[0];
1266
1267 mutex_lock(&tavil_p->codec_mutex);
1268 if (enable) {
1269 if (port_id == WCD934X_TX14 && !test_bit(VI_SENSE_1,
1270 &tavil_p->status_mask)) {
1271 list_add_tail(&core->tx_chs[WCD934X_TX14].list,
1272 &tavil_p->dai[dai_id].wcd9xxx_ch_list);
1273 set_bit(VI_SENSE_1, &tavil_p->status_mask);
1274 }
1275 if (port_id == WCD934X_TX15 && !test_bit(VI_SENSE_2,
1276 &tavil_p->status_mask)) {
1277 list_add_tail(&core->tx_chs[WCD934X_TX15].list,
1278 &tavil_p->dai[dai_id].wcd9xxx_ch_list);
1279 set_bit(VI_SENSE_2, &tavil_p->status_mask);
1280 }
1281 } else {
1282 if (port_id == WCD934X_TX14 && test_bit(VI_SENSE_1,
1283 &tavil_p->status_mask)) {
1284 list_del_init(&core->tx_chs[WCD934X_TX14].list);
1285 clear_bit(VI_SENSE_1, &tavil_p->status_mask);
1286 }
1287 if (port_id == WCD934X_TX15 && test_bit(VI_SENSE_2,
1288 &tavil_p->status_mask)) {
1289 list_del_init(&core->tx_chs[WCD934X_TX15].list);
1290 clear_bit(VI_SENSE_2, &tavil_p->status_mask);
1291 }
1292 }
1293 mutex_unlock(&tavil_p->codec_mutex);
1294 snd_soc_dapm_mixer_update_power(widget->dapm, kcontrol, enable, NULL);
1295
1296 return 0;
1297}
1298
1299static int slim_tx_mixer_get(struct snd_kcontrol *kcontrol,
1300 struct snd_ctl_elem_value *ucontrol)
1301{
1302 struct snd_soc_dapm_widget_list *wlist =
1303 dapm_kcontrol_get_wlist(kcontrol);
1304 struct snd_soc_dapm_widget *widget = wlist->widgets[0];
1305 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(widget->dapm);
1306 struct tavil_priv *tavil_p = snd_soc_codec_get_drvdata(codec);
1307
1308 ucontrol->value.integer.value[0] = tavil_p->tx_port_value;
1309 return 0;
1310}
1311
1312static int slim_tx_mixer_put(struct snd_kcontrol *kcontrol,
1313 struct snd_ctl_elem_value *ucontrol)
1314{
1315 struct snd_soc_dapm_widget_list *wlist =
1316 dapm_kcontrol_get_wlist(kcontrol);
1317 struct snd_soc_dapm_widget *widget = wlist->widgets[0];
1318 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(widget->dapm);
1319 struct tavil_priv *tavil_p = snd_soc_codec_get_drvdata(codec);
1320 struct wcd9xxx *core = dev_get_drvdata(codec->dev->parent);
1321 struct snd_soc_dapm_update *update = NULL;
1322 struct soc_multi_mixer_control *mixer =
1323 ((struct soc_multi_mixer_control *)kcontrol->private_value);
1324 u32 dai_id = widget->shift;
1325 u32 port_id = mixer->shift;
1326 u32 enable = ucontrol->value.integer.value[0];
1327 u32 vtable;
1328
1329 dev_dbg(codec->dev, "%s: wname %s cname %s value %u shift %d item %ld\n",
1330 __func__,
1331 widget->name, ucontrol->id.name, tavil_p->tx_port_value,
1332 widget->shift, ucontrol->value.integer.value[0]);
1333
1334 mutex_lock(&tavil_p->codec_mutex);
1335 if (dai_id >= ARRAY_SIZE(vport_slim_check_table)) {
1336 dev_err(codec->dev, "%s: dai_id: %d, out of bounds\n",
1337 __func__, dai_id);
1338 mutex_unlock(&tavil_p->codec_mutex);
1339 return -EINVAL;
1340 }
1341 vtable = vport_slim_check_table[dai_id];
1342
1343 switch (dai_id) {
1344 case AIF1_CAP:
1345 case AIF2_CAP:
1346 case AIF3_CAP:
1347 /* only add to the list if value not set */
1348 if (enable && !(tavil_p->tx_port_value & 1 << port_id)) {
1349 if (wcd9xxx_tx_vport_validation(vtable, port_id,
1350 tavil_p->dai, NUM_CODEC_DAIS)) {
1351 dev_dbg(codec->dev, "%s: TX%u is used by other virtual port\n",
1352 __func__, port_id);
1353 mutex_unlock(&tavil_p->codec_mutex);
1354 return 0;
1355 }
1356 tavil_p->tx_port_value |= 1 << port_id;
1357 list_add_tail(&core->tx_chs[port_id].list,
1358 &tavil_p->dai[dai_id].wcd9xxx_ch_list);
1359 } else if (!enable && (tavil_p->tx_port_value &
1360 1 << port_id)) {
1361 tavil_p->tx_port_value &= ~(1 << port_id);
1362 list_del_init(&core->tx_chs[port_id].list);
1363 } else {
1364 if (enable)
1365 dev_dbg(codec->dev, "%s: TX%u port is used by\n"
1366 "this virtual port\n",
1367 __func__, port_id);
1368 else
1369 dev_dbg(codec->dev, "%s: TX%u port is not used by\n"
1370 "this virtual port\n",
1371 __func__, port_id);
1372 /* avoid update power function */
1373 mutex_unlock(&tavil_p->codec_mutex);
1374 return 0;
1375 }
1376 break;
1377 case AIF4_MAD_TX:
1378 break;
1379 default:
1380 dev_err(codec->dev, "Unknown AIF %d\n", dai_id);
1381 mutex_unlock(&tavil_p->codec_mutex);
1382 return -EINVAL;
1383 }
1384 dev_dbg(codec->dev, "%s: name %s sname %s updated value %u shift %d\n",
1385 __func__, widget->name, widget->sname, tavil_p->tx_port_value,
1386 widget->shift);
1387
1388 mutex_unlock(&tavil_p->codec_mutex);
1389 snd_soc_dapm_mixer_update_power(widget->dapm, kcontrol, enable, update);
1390
1391 return 0;
1392}
1393
1394static int slim_rx_mux_get(struct snd_kcontrol *kcontrol,
1395 struct snd_ctl_elem_value *ucontrol)
1396{
1397 struct snd_soc_dapm_widget_list *wlist =
1398 dapm_kcontrol_get_wlist(kcontrol);
1399 struct snd_soc_dapm_widget *widget = wlist->widgets[0];
1400 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(widget->dapm);
1401 struct tavil_priv *tavil_p = snd_soc_codec_get_drvdata(codec);
1402
1403 ucontrol->value.enumerated.item[0] =
1404 tavil_p->rx_port_value[widget->shift];
1405 return 0;
1406}
1407
1408static int slim_rx_mux_put(struct snd_kcontrol *kcontrol,
1409 struct snd_ctl_elem_value *ucontrol)
1410{
1411 struct snd_soc_dapm_widget_list *wlist =
1412 dapm_kcontrol_get_wlist(kcontrol);
1413 struct snd_soc_dapm_widget *widget = wlist->widgets[0];
1414 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(widget->dapm);
1415 struct tavil_priv *tavil_p = snd_soc_codec_get_drvdata(codec);
1416 struct wcd9xxx *core = dev_get_drvdata(codec->dev->parent);
1417 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
1418 struct snd_soc_dapm_update *update = NULL;
1419 unsigned int rx_port_value;
1420 u32 port_id = widget->shift;
1421
1422 tavil_p->rx_port_value[port_id] = ucontrol->value.enumerated.item[0];
1423 rx_port_value = tavil_p->rx_port_value[port_id];
1424
1425 mutex_lock(&tavil_p->codec_mutex);
1426 dev_dbg(codec->dev, "%s: wname %s cname %s value %u shift %d item %ld\n",
1427 __func__, widget->name, ucontrol->id.name,
1428 rx_port_value, widget->shift,
1429 ucontrol->value.integer.value[0]);
1430
1431 /* value need to match the Virtual port and AIF number */
1432 switch (rx_port_value) {
1433 case 0:
1434 list_del_init(&core->rx_chs[port_id].list);
1435 break;
1436 case 1:
1437 if (wcd9xxx_rx_vport_validation(port_id +
1438 WCD934X_RX_PORT_START_NUMBER,
1439 &tavil_p->dai[AIF1_PB].wcd9xxx_ch_list)) {
1440 dev_dbg(codec->dev, "%s: RX%u is used by current requesting AIF_PB itself\n",
1441 __func__, port_id);
1442 goto rtn;
1443 }
1444 list_add_tail(&core->rx_chs[port_id].list,
1445 &tavil_p->dai[AIF1_PB].wcd9xxx_ch_list);
1446 break;
1447 case 2:
1448 if (wcd9xxx_rx_vport_validation(port_id +
1449 WCD934X_RX_PORT_START_NUMBER,
1450 &tavil_p->dai[AIF2_PB].wcd9xxx_ch_list)) {
1451 dev_dbg(codec->dev, "%s: RX%u is used by current requesting AIF_PB itself\n",
1452 __func__, port_id);
1453 goto rtn;
1454 }
1455 list_add_tail(&core->rx_chs[port_id].list,
1456 &tavil_p->dai[AIF2_PB].wcd9xxx_ch_list);
1457 break;
1458 case 3:
1459 if (wcd9xxx_rx_vport_validation(port_id +
1460 WCD934X_RX_PORT_START_NUMBER,
1461 &tavil_p->dai[AIF3_PB].wcd9xxx_ch_list)) {
1462 dev_dbg(codec->dev, "%s: RX%u is used by current requesting AIF_PB itself\n",
1463 __func__, port_id);
1464 goto rtn;
1465 }
1466 list_add_tail(&core->rx_chs[port_id].list,
1467 &tavil_p->dai[AIF3_PB].wcd9xxx_ch_list);
1468 break;
1469 case 4:
1470 if (wcd9xxx_rx_vport_validation(port_id +
1471 WCD934X_RX_PORT_START_NUMBER,
1472 &tavil_p->dai[AIF4_PB].wcd9xxx_ch_list)) {
1473 dev_dbg(codec->dev, "%s: RX%u is used by current requesting AIF_PB itself\n",
1474 __func__, port_id);
1475 goto rtn;
1476 }
1477 list_add_tail(&core->rx_chs[port_id].list,
1478 &tavil_p->dai[AIF4_PB].wcd9xxx_ch_list);
1479 break;
1480 default:
1481 dev_err(codec->dev, "Unknown AIF %d\n", rx_port_value);
1482 goto err;
1483 }
1484rtn:
1485 mutex_unlock(&tavil_p->codec_mutex);
1486 snd_soc_dapm_mux_update_power(widget->dapm, kcontrol,
1487 rx_port_value, e, update);
1488
1489 return 0;
1490err:
1491 mutex_unlock(&tavil_p->codec_mutex);
1492 return -EINVAL;
1493}
1494
1495static void tavil_codec_enable_slim_port_intr(
1496 struct wcd9xxx_codec_dai_data *dai,
1497 struct snd_soc_codec *codec)
1498{
1499 struct wcd9xxx_ch *ch;
1500 int port_num = 0;
1501 unsigned short reg = 0;
1502 u8 val = 0;
1503 struct tavil_priv *tavil_p;
1504
1505 if (!dai || !codec) {
1506 pr_err("%s: Invalid params\n", __func__);
1507 return;
1508 }
1509
1510 tavil_p = snd_soc_codec_get_drvdata(codec);
1511 list_for_each_entry(ch, &dai->wcd9xxx_ch_list, list) {
1512 if (ch->port >= WCD934X_RX_PORT_START_NUMBER) {
1513 port_num = ch->port - WCD934X_RX_PORT_START_NUMBER;
1514 reg = WCD934X_SLIM_PGD_PORT_INT_RX_EN0 + (port_num / 8);
1515 val = wcd9xxx_interface_reg_read(tavil_p->wcd9xxx,
1516 reg);
1517 if (!(val & BYTE_BIT_MASK(port_num))) {
1518 val |= BYTE_BIT_MASK(port_num);
1519 wcd9xxx_interface_reg_write(
1520 tavil_p->wcd9xxx, reg, val);
1521 val = wcd9xxx_interface_reg_read(
1522 tavil_p->wcd9xxx, reg);
1523 }
1524 } else {
1525 port_num = ch->port;
1526 reg = WCD934X_SLIM_PGD_PORT_INT_TX_EN0 + (port_num / 8);
1527 val = wcd9xxx_interface_reg_read(tavil_p->wcd9xxx,
1528 reg);
1529 if (!(val & BYTE_BIT_MASK(port_num))) {
1530 val |= BYTE_BIT_MASK(port_num);
1531 wcd9xxx_interface_reg_write(tavil_p->wcd9xxx,
1532 reg, val);
1533 val = wcd9xxx_interface_reg_read(
1534 tavil_p->wcd9xxx, reg);
1535 }
1536 }
1537 }
1538}
1539
1540static int tavil_codec_enable_slim_chmask(struct wcd9xxx_codec_dai_data *dai,
1541 bool up)
1542{
1543 int ret = 0;
1544 struct wcd9xxx_ch *ch;
1545
1546 if (up) {
1547 list_for_each_entry(ch, &dai->wcd9xxx_ch_list, list) {
1548 ret = wcd9xxx_get_slave_port(ch->ch_num);
1549 if (ret < 0) {
1550 pr_err("%s: Invalid slave port ID: %d\n",
1551 __func__, ret);
1552 ret = -EINVAL;
1553 } else {
1554 set_bit(ret, &dai->ch_mask);
1555 }
1556 }
1557 } else {
1558 ret = wait_event_timeout(dai->dai_wait, (dai->ch_mask == 0),
1559 msecs_to_jiffies(
1560 WCD934X_SLIM_CLOSE_TIMEOUT));
1561 if (!ret) {
1562 pr_err("%s: Slim close tx/rx wait timeout, ch_mask:0x%lx\n",
1563 __func__, dai->ch_mask);
1564 ret = -ETIMEDOUT;
1565 } else {
1566 ret = 0;
1567 }
1568 }
1569 return ret;
1570}
1571
1572static void tavil_codec_mute_dsd(struct snd_soc_codec *codec,
1573 struct list_head *ch_list)
1574{
1575 u8 dsd0_in;
1576 u8 dsd1_in;
1577 struct wcd9xxx_ch *ch;
1578
1579 /* Read DSD Input Ports */
1580 dsd0_in = (snd_soc_read(codec, WCD934X_CDC_DSD0_CFG0) & 0x3C) >> 2;
1581 dsd1_in = (snd_soc_read(codec, WCD934X_CDC_DSD1_CFG0) & 0x3C) >> 2;
1582
1583 if ((dsd0_in == 0) && (dsd1_in == 0))
1584 return;
1585
1586 /*
1587 * Check if the ports getting disabled are connected to DSD inputs.
1588 * If connected, enable DSD mute to avoid DC entering into DSD Filter
1589 */
1590 list_for_each_entry(ch, ch_list, list) {
1591 if (ch->port == (dsd0_in + WCD934X_RX_PORT_START_NUMBER - 1))
1592 snd_soc_update_bits(codec, WCD934X_CDC_DSD0_CFG2,
1593 0x04, 0x04);
1594 if (ch->port == (dsd1_in + WCD934X_RX_PORT_START_NUMBER - 1))
1595 snd_soc_update_bits(codec, WCD934X_CDC_DSD1_CFG2,
1596 0x04, 0x04);
1597 }
1598}
1599
1600static int tavil_codec_enable_slimrx(struct snd_soc_dapm_widget *w,
1601 struct snd_kcontrol *kcontrol,
1602 int event)
1603{
1604 struct wcd9xxx *core;
1605 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
1606 struct tavil_priv *tavil_p = snd_soc_codec_get_drvdata(codec);
1607 int ret = 0;
1608 struct wcd9xxx_codec_dai_data *dai;
1609 struct tavil_dsd_config *dsd_conf = tavil_p->dsd_config;
1610
1611 core = dev_get_drvdata(codec->dev->parent);
1612
1613 dev_dbg(codec->dev, "%s: event called! codec name %s num_dai %d\n"
1614 "stream name %s event %d\n",
1615 __func__, codec->component.name,
1616 codec->component.num_dai, w->sname, event);
1617
1618 dai = &tavil_p->dai[w->shift];
1619 dev_dbg(codec->dev, "%s: w->name %s w->shift %d event %d\n",
1620 __func__, w->name, w->shift, event);
1621
1622 switch (event) {
1623 case SND_SOC_DAPM_POST_PMU:
1624 dai->bus_down_in_recovery = false;
1625 tavil_codec_enable_slim_port_intr(dai, codec);
1626 (void) tavil_codec_enable_slim_chmask(dai, true);
1627 ret = wcd9xxx_cfg_slim_sch_rx(core, &dai->wcd9xxx_ch_list,
1628 dai->rate, dai->bit_width,
1629 &dai->grph);
1630 break;
1631 case SND_SOC_DAPM_POST_PMD:
1632 if (dsd_conf)
1633 tavil_codec_mute_dsd(codec, &dai->wcd9xxx_ch_list);
1634
1635 ret = wcd9xxx_disconnect_port(core, &dai->wcd9xxx_ch_list,
1636 dai->grph);
1637 dev_dbg(codec->dev, "%s: Disconnect RX port, ret = %d\n",
1638 __func__, ret);
1639
1640 if (!dai->bus_down_in_recovery)
1641 ret = tavil_codec_enable_slim_chmask(dai, false);
1642 else
1643 dev_dbg(codec->dev,
1644 "%s: bus in recovery skip enable slim_chmask",
1645 __func__);
1646 ret = wcd9xxx_close_slim_sch_rx(core, &dai->wcd9xxx_ch_list,
1647 dai->grph);
1648 break;
1649 }
1650 return ret;
1651}
1652
1653static int tavil_codec_enable_slimtx(struct snd_soc_dapm_widget *w,
1654 struct snd_kcontrol *kcontrol,
1655 int event)
1656{
1657 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
1658 struct tavil_priv *tavil_p = snd_soc_codec_get_drvdata(codec);
1659 struct wcd9xxx_codec_dai_data *dai;
1660 struct wcd9xxx *core;
1661 int ret = 0;
1662
1663 dev_dbg(codec->dev,
1664 "%s: w->name %s, w->shift = %d, num_dai %d stream name %s\n",
1665 __func__, w->name, w->shift,
1666 codec->component.num_dai, w->sname);
1667
1668 dai = &tavil_p->dai[w->shift];
1669 core = dev_get_drvdata(codec->dev->parent);
1670
1671 switch (event) {
1672 case SND_SOC_DAPM_POST_PMU:
1673 dai->bus_down_in_recovery = false;
1674 tavil_codec_enable_slim_port_intr(dai, codec);
1675 (void) tavil_codec_enable_slim_chmask(dai, true);
1676 ret = wcd9xxx_cfg_slim_sch_tx(core, &dai->wcd9xxx_ch_list,
1677 dai->rate, dai->bit_width,
1678 &dai->grph);
1679 break;
1680 case SND_SOC_DAPM_POST_PMD:
1681 ret = wcd9xxx_close_slim_sch_tx(core, &dai->wcd9xxx_ch_list,
1682 dai->grph);
1683 if (!dai->bus_down_in_recovery)
1684 ret = tavil_codec_enable_slim_chmask(dai, false);
1685 if (ret < 0) {
1686 ret = wcd9xxx_disconnect_port(core,
1687 &dai->wcd9xxx_ch_list,
1688 dai->grph);
1689 dev_dbg(codec->dev, "%s: Disconnect RX port, ret = %d\n",
1690 __func__, ret);
1691 }
1692 break;
1693 }
1694 return ret;
1695}
1696
1697static int tavil_codec_enable_slimvi_feedback(struct snd_soc_dapm_widget *w,
1698 struct snd_kcontrol *kcontrol,
1699 int event)
1700{
1701 struct wcd9xxx *core = NULL;
1702 struct snd_soc_codec *codec = NULL;
1703 struct tavil_priv *tavil_p = NULL;
1704 int ret = 0;
1705 struct wcd9xxx_codec_dai_data *dai = NULL;
1706
1707 codec = snd_soc_dapm_to_codec(w->dapm);
1708 tavil_p = snd_soc_codec_get_drvdata(codec);
1709 core = dev_get_drvdata(codec->dev->parent);
1710
1711 dev_dbg(codec->dev,
1712 "%s: num_dai %d stream name %s w->name %s event %d shift %d\n",
1713 __func__, codec->component.num_dai, w->sname,
1714 w->name, event, w->shift);
1715
1716 if (w->shift != AIF4_VIFEED) {
1717 pr_err("%s Error in enabling the tx path\n", __func__);
1718 ret = -EINVAL;
1719 goto done;
1720 }
1721 dai = &tavil_p->dai[w->shift];
1722 switch (event) {
1723 case SND_SOC_DAPM_POST_PMU:
1724 if (test_bit(VI_SENSE_1, &tavil_p->status_mask)) {
1725 dev_dbg(codec->dev, "%s: spkr1 enabled\n", __func__);
1726 /* Enable V&I sensing */
1727 snd_soc_update_bits(codec,
1728 WCD934X_CDC_TX9_SPKR_PROT_PATH_CTL, 0x20, 0x20);
1729 snd_soc_update_bits(codec,
1730 WCD934X_CDC_TX10_SPKR_PROT_PATH_CTL, 0x20,
1731 0x20);
1732 snd_soc_update_bits(codec,
1733 WCD934X_CDC_TX9_SPKR_PROT_PATH_CTL, 0x0F, 0x00);
1734 snd_soc_update_bits(codec,
1735 WCD934X_CDC_TX10_SPKR_PROT_PATH_CTL, 0x0F,
1736 0x00);
1737 snd_soc_update_bits(codec,
1738 WCD934X_CDC_TX9_SPKR_PROT_PATH_CTL, 0x10, 0x10);
1739 snd_soc_update_bits(codec,
1740 WCD934X_CDC_TX10_SPKR_PROT_PATH_CTL, 0x10,
1741 0x10);
1742 snd_soc_update_bits(codec,
1743 WCD934X_CDC_TX9_SPKR_PROT_PATH_CTL, 0x20, 0x00);
1744 snd_soc_update_bits(codec,
1745 WCD934X_CDC_TX10_SPKR_PROT_PATH_CTL, 0x20,
1746 0x00);
1747 }
1748 if (test_bit(VI_SENSE_2, &tavil_p->status_mask)) {
1749 pr_debug("%s: spkr2 enabled\n", __func__);
1750 /* Enable V&I sensing */
1751 snd_soc_update_bits(codec,
1752 WCD934X_CDC_TX11_SPKR_PROT_PATH_CTL, 0x20,
1753 0x20);
1754 snd_soc_update_bits(codec,
1755 WCD934X_CDC_TX12_SPKR_PROT_PATH_CTL, 0x20,
1756 0x20);
1757 snd_soc_update_bits(codec,
1758 WCD934X_CDC_TX11_SPKR_PROT_PATH_CTL, 0x0F,
1759 0x00);
1760 snd_soc_update_bits(codec,
1761 WCD934X_CDC_TX12_SPKR_PROT_PATH_CTL, 0x0F,
1762 0x00);
1763 snd_soc_update_bits(codec,
1764 WCD934X_CDC_TX11_SPKR_PROT_PATH_CTL, 0x10,
1765 0x10);
1766 snd_soc_update_bits(codec,
1767 WCD934X_CDC_TX12_SPKR_PROT_PATH_CTL, 0x10,
1768 0x10);
1769 snd_soc_update_bits(codec,
1770 WCD934X_CDC_TX11_SPKR_PROT_PATH_CTL, 0x20,
1771 0x00);
1772 snd_soc_update_bits(codec,
1773 WCD934X_CDC_TX12_SPKR_PROT_PATH_CTL, 0x20,
1774 0x00);
1775 }
1776 dai->bus_down_in_recovery = false;
1777 tavil_codec_enable_slim_port_intr(dai, codec);
1778 (void) tavil_codec_enable_slim_chmask(dai, true);
1779 ret = wcd9xxx_cfg_slim_sch_tx(core, &dai->wcd9xxx_ch_list,
1780 dai->rate, dai->bit_width,
1781 &dai->grph);
1782 break;
1783 case SND_SOC_DAPM_POST_PMD:
1784 ret = wcd9xxx_close_slim_sch_tx(core, &dai->wcd9xxx_ch_list,
1785 dai->grph);
1786 if (ret)
1787 dev_err(codec->dev, "%s error in close_slim_sch_tx %d\n",
1788 __func__, ret);
1789 if (!dai->bus_down_in_recovery)
1790 ret = tavil_codec_enable_slim_chmask(dai, false);
1791 if (ret < 0) {
1792 ret = wcd9xxx_disconnect_port(core,
1793 &dai->wcd9xxx_ch_list,
1794 dai->grph);
1795 dev_dbg(codec->dev, "%s: Disconnect TX port, ret = %d\n",
1796 __func__, ret);
1797 }
1798 if (test_bit(VI_SENSE_1, &tavil_p->status_mask)) {
1799 /* Disable V&I sensing */
1800 dev_dbg(codec->dev, "%s: spkr1 disabled\n", __func__);
1801 snd_soc_update_bits(codec,
1802 WCD934X_CDC_TX9_SPKR_PROT_PATH_CTL, 0x20, 0x20);
1803 snd_soc_update_bits(codec,
1804 WCD934X_CDC_TX10_SPKR_PROT_PATH_CTL, 0x20,
1805 0x20);
1806 snd_soc_update_bits(codec,
1807 WCD934X_CDC_TX9_SPKR_PROT_PATH_CTL, 0x10, 0x00);
1808 snd_soc_update_bits(codec,
1809 WCD934X_CDC_TX10_SPKR_PROT_PATH_CTL, 0x10,
1810 0x00);
1811 }
1812 if (test_bit(VI_SENSE_2, &tavil_p->status_mask)) {
1813 /* Disable V&I sensing */
1814 dev_dbg(codec->dev, "%s: spkr2 disabled\n", __func__);
1815 snd_soc_update_bits(codec,
1816 WCD934X_CDC_TX11_SPKR_PROT_PATH_CTL, 0x20,
1817 0x20);
1818 snd_soc_update_bits(codec,
1819 WCD934X_CDC_TX12_SPKR_PROT_PATH_CTL, 0x20,
1820 0x20);
1821 snd_soc_update_bits(codec,
1822 WCD934X_CDC_TX11_SPKR_PROT_PATH_CTL, 0x10,
1823 0x00);
1824 snd_soc_update_bits(codec,
1825 WCD934X_CDC_TX12_SPKR_PROT_PATH_CTL, 0x10,
1826 0x00);
1827 }
1828 break;
1829 }
1830done:
1831 return ret;
1832}
1833
1834static int tavil_codec_enable_rx_bias(struct snd_soc_dapm_widget *w,
1835 struct snd_kcontrol *kcontrol, int event)
1836{
1837 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
1838 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
1839
1840 dev_dbg(codec->dev, "%s %s %d\n", __func__, w->name, event);
1841
1842 switch (event) {
1843 case SND_SOC_DAPM_PRE_PMU:
1844 tavil->rx_bias_count++;
1845 if (tavil->rx_bias_count == 1) {
1846 snd_soc_update_bits(codec, WCD934X_ANA_RX_SUPPLIES,
1847 0x01, 0x01);
1848 }
1849 break;
1850 case SND_SOC_DAPM_POST_PMD:
1851 tavil->rx_bias_count--;
1852 if (!tavil->rx_bias_count)
1853 snd_soc_update_bits(codec, WCD934X_ANA_RX_SUPPLIES,
1854 0x01, 0x00);
1855 break;
1856 };
1857 dev_dbg(codec->dev, "%s: Current RX BIAS user count: %d\n", __func__,
1858 tavil->rx_bias_count);
1859
1860 return 0;
1861}
1862
1863static void tavil_spk_anc_update_callback(struct work_struct *work)
1864{
1865 struct spk_anc_work *spk_anc_dwork;
1866 struct tavil_priv *tavil;
1867 struct delayed_work *delayed_work;
1868 struct snd_soc_codec *codec;
1869
1870 delayed_work = to_delayed_work(work);
1871 spk_anc_dwork = container_of(delayed_work, struct spk_anc_work, dwork);
1872 tavil = spk_anc_dwork->tavil;
1873 codec = tavil->codec;
1874
1875 snd_soc_update_bits(codec, WCD934X_CDC_RX7_RX_PATH_CFG0, 0x10, 0x10);
1876}
1877
1878static int tavil_codec_enable_spkr_anc(struct snd_soc_dapm_widget *w,
1879 struct snd_kcontrol *kcontrol,
1880 int event)
1881{
1882 int ret = 0;
1883 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
1884 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
1885
1886 if (!tavil->anc_func)
1887 return 0;
1888
1889 dev_dbg(codec->dev, "%s: w: %s event: %d anc: %d\n", __func__,
1890 w->name, event, tavil->anc_func);
1891
1892 switch (event) {
1893 case SND_SOC_DAPM_PRE_PMU:
1894 ret = tavil_codec_enable_anc(w, kcontrol, event);
1895 schedule_delayed_work(&tavil->spk_anc_dwork.dwork,
1896 msecs_to_jiffies(spk_anc_en_delay));
1897 break;
1898 case SND_SOC_DAPM_POST_PMD:
1899 cancel_delayed_work_sync(&tavil->spk_anc_dwork.dwork);
1900 snd_soc_update_bits(codec, WCD934X_CDC_RX7_RX_PATH_CFG0,
1901 0x10, 0x00);
1902 ret = tavil_codec_enable_anc(w, kcontrol, event);
1903 break;
1904 }
1905 return ret;
1906}
1907
1908static int tavil_codec_enable_ear_pa(struct snd_soc_dapm_widget *w,
1909 struct snd_kcontrol *kcontrol,
1910 int event)
1911{
1912 int ret = 0;
1913 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
1914
1915 dev_dbg(codec->dev, "%s %s %d\n", __func__, w->name, event);
1916
1917 switch (event) {
1918 case SND_SOC_DAPM_POST_PMU:
1919 /*
1920 * 5ms sleep is required after PA is enabled as per
1921 * HW requirement
1922 */
1923 usleep_range(5000, 5500);
1924 snd_soc_update_bits(codec, WCD934X_CDC_RX0_RX_PATH_CTL,
1925 0x10, 0x00);
1926 /* Remove mix path mute if it is enabled */
1927 if ((snd_soc_read(codec, WCD934X_CDC_RX0_RX_PATH_MIX_CTL)) &
1928 0x10)
1929 snd_soc_update_bits(codec,
1930 WCD934X_CDC_RX0_RX_PATH_MIX_CTL,
1931 0x10, 0x00);
1932 break;
1933 case SND_SOC_DAPM_POST_PMD:
1934 /*
1935 * 5ms sleep is required after PA is disabled as per
1936 * HW requirement
1937 */
1938 usleep_range(5000, 5500);
1939
1940 if (!(strcmp(w->name, "ANC EAR PA"))) {
1941 ret = tavil_codec_enable_anc(w, kcontrol, event);
1942 snd_soc_update_bits(codec, WCD934X_CDC_RX0_RX_PATH_CFG0,
1943 0x10, 0x00);
1944 }
1945 break;
1946 };
1947
1948 return ret;
1949}
1950
1951static void tavil_codec_override(struct snd_soc_codec *codec, int mode,
1952 int event)
1953{
1954 if (mode == CLS_AB || mode == CLS_AB_HIFI) {
1955 switch (event) {
1956 case SND_SOC_DAPM_PRE_PMU:
1957 case SND_SOC_DAPM_POST_PMU:
Karthikeyan Mani387d3982016-12-09 16:39:42 -08001958 snd_soc_update_bits(codec,
1959 WCD9XXX_A_ANA_RX_SUPPLIES, 0x02, 0x02);
Banajit Goswamide8271c2017-01-18 00:28:59 -08001960 break;
1961 case SND_SOC_DAPM_POST_PMD:
1962 snd_soc_update_bits(codec,
1963 WCD9XXX_A_ANA_RX_SUPPLIES, 0x02, 0x00);
1964 break;
1965 }
1966 }
1967}
1968
Meng Wangf45a20d2017-01-18 09:51:58 +08001969static void tavil_codec_clear_anc_tx_hold(struct tavil_priv *tavil)
1970{
1971 if (test_and_clear_bit(ANC_MIC_AMIC1, &tavil->status_mask))
1972 tavil_codec_set_tx_hold(tavil->codec, WCD934X_ANA_AMIC1, false);
1973 if (test_and_clear_bit(ANC_MIC_AMIC2, &tavil->status_mask))
1974 tavil_codec_set_tx_hold(tavil->codec, WCD934X_ANA_AMIC2, false);
1975 if (test_and_clear_bit(ANC_MIC_AMIC3, &tavil->status_mask))
1976 tavil_codec_set_tx_hold(tavil->codec, WCD934X_ANA_AMIC3, false);
1977 if (test_and_clear_bit(ANC_MIC_AMIC4, &tavil->status_mask))
1978 tavil_codec_set_tx_hold(tavil->codec, WCD934X_ANA_AMIC4, false);
1979}
1980
Banajit Goswamide8271c2017-01-18 00:28:59 -08001981static int tavil_codec_enable_hphr_pa(struct snd_soc_dapm_widget *w,
1982 struct snd_kcontrol *kcontrol,
1983 int event)
1984{
1985 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
1986 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
1987 struct tavil_dsd_config *dsd_conf = tavil->dsd_config;
Meng Wangf45a20d2017-01-18 09:51:58 +08001988 int ret = 0;
Banajit Goswamide8271c2017-01-18 00:28:59 -08001989
1990 dev_dbg(codec->dev, "%s %s %d\n", __func__, w->name, event);
1991
1992 switch (event) {
1993 case SND_SOC_DAPM_PRE_PMU:
1994 if (TAVIL_IS_1_0(tavil->wcd9xxx))
1995 snd_soc_update_bits(codec, WCD934X_HPH_REFBUFF_LP_CTL,
1996 0x06, (0x03 << 1));
Meng Wangf45a20d2017-01-18 09:51:58 +08001997
1998 if ((!(strcmp(w->name, "ANC HPHR PA"))) &&
1999 (test_bit(HPH_PA_DELAY, &tavil->status_mask)))
2000 snd_soc_update_bits(codec, WCD934X_ANA_HPH, 0xC0, 0xC0);
2001
Banajit Goswamide8271c2017-01-18 00:28:59 -08002002 set_bit(HPH_PA_DELAY, &tavil->status_mask);
2003 if (dsd_conf &&
2004 (snd_soc_read(codec, WCD934X_CDC_DSD1_PATH_CTL) & 0x01)) {
2005 /* Set regulator mode to AB if DSD is enabled */
2006 snd_soc_update_bits(codec, WCD934X_ANA_RX_SUPPLIES,
2007 0x02, 0x02);
2008 }
2009 break;
2010 case SND_SOC_DAPM_POST_PMU:
Meng Wangf45a20d2017-01-18 09:51:58 +08002011 if ((!(strcmp(w->name, "ANC HPHR PA")))) {
2012 if ((snd_soc_read(codec, WCD934X_ANA_HPH) & 0xC0)
2013 != 0xC0)
2014 /*
2015 * If PA_EN is not set (potentially in ANC case)
2016 * then do nothing for POST_PMU and let left
2017 * channel handle everything.
2018 */
2019 break;
2020 }
Banajit Goswamide8271c2017-01-18 00:28:59 -08002021 /*
2022 * 7ms sleep is required after PA is enabled as per
Sudheer Papothi3be76772017-01-11 06:08:13 +05302023 * HW requirement. If compander is disabled, then
2024 * 20ms delay is needed.
Banajit Goswamide8271c2017-01-18 00:28:59 -08002025 */
2026 if (test_bit(HPH_PA_DELAY, &tavil->status_mask)) {
Sudheer Papothi3be76772017-01-11 06:08:13 +05302027 if (!tavil->comp_enabled[COMPANDER_2])
2028 usleep_range(20000, 20100);
2029 else
2030 usleep_range(7000, 7100);
Banajit Goswamide8271c2017-01-18 00:28:59 -08002031 clear_bit(HPH_PA_DELAY, &tavil->status_mask);
2032 }
Meng Wangf45a20d2017-01-18 09:51:58 +08002033 if (tavil->anc_func) {
2034 /* Clear Tx FE HOLD if both PAs are enabled */
2035 if ((snd_soc_read(tavil->codec, WCD934X_ANA_HPH) &
2036 0xC0) == 0xC0)
2037 tavil_codec_clear_anc_tx_hold(tavil);
2038 }
Banajit Goswamide8271c2017-01-18 00:28:59 -08002039
2040 snd_soc_update_bits(codec, WCD934X_HPH_R_TEST, 0x01, 0x01);
2041
2042 /* Remove mute */
2043 snd_soc_update_bits(codec, WCD934X_CDC_RX2_RX_PATH_CTL,
2044 0x10, 0x00);
2045 /* Enable GM3 boost */
2046 snd_soc_update_bits(codec, WCD934X_HPH_CNP_WG_CTL,
2047 0x80, 0x80);
2048 /* Enable AutoChop timer at the end of power up */
2049 snd_soc_update_bits(codec, WCD934X_HPH_NEW_INT_HPH_TIMER1,
2050 0x02, 0x02);
2051 /* Remove mix path mute if it is enabled */
2052 if ((snd_soc_read(codec, WCD934X_CDC_RX2_RX_PATH_MIX_CTL)) &
2053 0x10)
2054 snd_soc_update_bits(codec,
2055 WCD934X_CDC_RX2_RX_PATH_MIX_CTL,
2056 0x10, 0x00);
2057 if (dsd_conf &&
2058 (snd_soc_read(codec, WCD934X_CDC_DSD1_PATH_CTL) & 0x01))
2059 snd_soc_update_bits(codec, WCD934X_CDC_DSD1_CFG2,
2060 0x04, 0x00);
Meng Wangf45a20d2017-01-18 09:51:58 +08002061 if (!(strcmp(w->name, "ANC HPHR PA"))) {
2062 pr_debug("%s:Do everything needed for left channel\n",
2063 __func__);
2064 /* Do everything needed for left channel */
2065 snd_soc_update_bits(codec, WCD934X_HPH_L_TEST,
2066 0x01, 0x01);
2067
2068 /* Remove mute */
2069 snd_soc_update_bits(codec, WCD934X_CDC_RX1_RX_PATH_CTL,
2070 0x10, 0x00);
2071
2072 /* Remove mix path mute if it is enabled */
2073 if ((snd_soc_read(codec,
2074 WCD934X_CDC_RX1_RX_PATH_MIX_CTL)) &
2075 0x10)
2076 snd_soc_update_bits(codec,
2077 WCD934X_CDC_RX1_RX_PATH_MIX_CTL,
2078 0x10, 0x00);
2079
2080 if (dsd_conf && (snd_soc_read(codec,
2081 WCD934X_CDC_DSD0_PATH_CTL) &
2082 0x01))
2083 snd_soc_update_bits(codec,
2084 WCD934X_CDC_DSD0_CFG2,
2085 0x04, 0x00);
2086 /* Remove ANC Rx from reset */
2087 ret = tavil_codec_enable_anc(w, kcontrol, event);
2088 }
Banajit Goswamide8271c2017-01-18 00:28:59 -08002089 tavil_codec_override(codec, tavil->hph_mode, event);
2090 break;
2091 case SND_SOC_DAPM_PRE_PMD:
2092 blocking_notifier_call_chain(&tavil->mbhc->notifier,
2093 WCD_EVENT_PRE_HPHR_PA_OFF,
2094 &tavil->mbhc->wcd_mbhc);
2095 /* Enable DSD Mute before PA disable */
2096 if (dsd_conf &&
2097 (snd_soc_read(codec, WCD934X_CDC_DSD1_PATH_CTL) & 0x01))
2098 snd_soc_update_bits(codec, WCD934X_CDC_DSD1_CFG2,
2099 0x04, 0x04);
2100 snd_soc_update_bits(codec, WCD934X_HPH_R_TEST, 0x01, 0x00);
2101 snd_soc_update_bits(codec, WCD934X_CDC_RX2_RX_PATH_CTL,
2102 0x10, 0x10);
Sudheer Papothi3be76772017-01-11 06:08:13 +05302103 snd_soc_update_bits(codec, WCD934X_CDC_RX2_RX_PATH_MIX_CTL,
2104 0x10, 0x10);
Meng Wangf45a20d2017-01-18 09:51:58 +08002105 if (!(strcmp(w->name, "ANC HPHR PA")))
2106 snd_soc_update_bits(codec, WCD934X_ANA_HPH, 0x40, 0x00);
Banajit Goswamide8271c2017-01-18 00:28:59 -08002107 break;
2108 case SND_SOC_DAPM_POST_PMD:
Sudheer Papothi3be76772017-01-11 06:08:13 +05302109 /*
2110 * 5ms sleep is required after PA disable. If compander is
2111 * disabled, then 20ms delay is needed after PA disable.
2112 */
2113 if (!tavil->comp_enabled[COMPANDER_2])
2114 usleep_range(20000, 20100);
2115 else
2116 usleep_range(5000, 5100);
Banajit Goswamide8271c2017-01-18 00:28:59 -08002117 tavil_codec_override(codec, tavil->hph_mode, event);
2118 blocking_notifier_call_chain(&tavil->mbhc->notifier,
2119 WCD_EVENT_POST_HPHR_PA_OFF,
2120 &tavil->mbhc->wcd_mbhc);
2121 if (TAVIL_IS_1_0(tavil->wcd9xxx))
2122 snd_soc_update_bits(codec, WCD934X_HPH_REFBUFF_LP_CTL,
2123 0x06, 0x0);
Meng Wangf45a20d2017-01-18 09:51:58 +08002124 if (!(strcmp(w->name, "ANC HPHR PA"))) {
2125 ret = tavil_codec_enable_anc(w, kcontrol, event);
2126 snd_soc_update_bits(codec,
2127 WCD934X_CDC_RX2_RX_PATH_CFG0,
2128 0x10, 0x00);
2129 }
Banajit Goswamide8271c2017-01-18 00:28:59 -08002130 break;
2131 };
2132
Meng Wangf45a20d2017-01-18 09:51:58 +08002133 return ret;
Banajit Goswamide8271c2017-01-18 00:28:59 -08002134}
2135
2136static int tavil_codec_enable_hphl_pa(struct snd_soc_dapm_widget *w,
2137 struct snd_kcontrol *kcontrol,
2138 int event)
2139{
2140 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
2141 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
2142 struct tavil_dsd_config *dsd_conf = tavil->dsd_config;
Meng Wangf45a20d2017-01-18 09:51:58 +08002143 int ret = 0;
Banajit Goswamide8271c2017-01-18 00:28:59 -08002144
2145 dev_dbg(codec->dev, "%s %s %d\n", __func__, w->name, event);
2146
2147 switch (event) {
2148 case SND_SOC_DAPM_PRE_PMU:
2149 if (TAVIL_IS_1_0(tavil->wcd9xxx))
2150 snd_soc_update_bits(codec, WCD934X_HPH_REFBUFF_LP_CTL,
2151 0x06, (0x03 << 1));
Meng Wangf45a20d2017-01-18 09:51:58 +08002152 if ((!(strcmp(w->name, "ANC HPHL PA"))) &&
2153 (test_bit(HPH_PA_DELAY, &tavil->status_mask)))
2154 snd_soc_update_bits(codec, WCD934X_ANA_HPH,
2155 0xC0, 0xC0);
Banajit Goswamide8271c2017-01-18 00:28:59 -08002156 set_bit(HPH_PA_DELAY, &tavil->status_mask);
2157 if (dsd_conf &&
2158 (snd_soc_read(codec, WCD934X_CDC_DSD0_PATH_CTL) & 0x01)) {
2159 /* Set regulator mode to AB if DSD is enabled */
2160 snd_soc_update_bits(codec, WCD934X_ANA_RX_SUPPLIES,
2161 0x02, 0x02);
2162 }
2163 break;
2164 case SND_SOC_DAPM_POST_PMU:
Meng Wangf45a20d2017-01-18 09:51:58 +08002165 if (!(strcmp(w->name, "ANC HPHL PA"))) {
2166 if ((snd_soc_read(codec, WCD934X_ANA_HPH) & 0xC0)
2167 != 0xC0)
2168 /*
2169 * If PA_EN is not set (potentially in ANC
2170 * case) then do nothing for POST_PMU and
2171 * let right channel handle everything.
2172 */
2173 break;
2174 }
Banajit Goswamide8271c2017-01-18 00:28:59 -08002175 /*
2176 * 7ms sleep is required after PA is enabled as per
Sudheer Papothi3be76772017-01-11 06:08:13 +05302177 * HW requirement. If compander is disabled, then
2178 * 20ms delay is needed.
Banajit Goswamide8271c2017-01-18 00:28:59 -08002179 */
2180 if (test_bit(HPH_PA_DELAY, &tavil->status_mask)) {
Sudheer Papothi3be76772017-01-11 06:08:13 +05302181 if (!tavil->comp_enabled[COMPANDER_1])
2182 usleep_range(20000, 20100);
2183 else
2184 usleep_range(7000, 7100);
Banajit Goswamide8271c2017-01-18 00:28:59 -08002185 clear_bit(HPH_PA_DELAY, &tavil->status_mask);
2186 }
Meng Wangf45a20d2017-01-18 09:51:58 +08002187 if (tavil->anc_func) {
2188 /* Clear Tx FE HOLD if both PAs are enabled */
2189 if ((snd_soc_read(tavil->codec, WCD934X_ANA_HPH) &
2190 0xC0) == 0xC0)
2191 tavil_codec_clear_anc_tx_hold(tavil);
2192 }
2193
Banajit Goswamide8271c2017-01-18 00:28:59 -08002194 snd_soc_update_bits(codec, WCD934X_HPH_L_TEST, 0x01, 0x01);
2195 /* Remove Mute on primary path */
2196 snd_soc_update_bits(codec, WCD934X_CDC_RX1_RX_PATH_CTL,
2197 0x10, 0x00);
2198 /* Enable GM3 boost */
2199 snd_soc_update_bits(codec, WCD934X_HPH_CNP_WG_CTL,
2200 0x80, 0x80);
2201 /* Enable AutoChop timer at the end of power up */
2202 snd_soc_update_bits(codec, WCD934X_HPH_NEW_INT_HPH_TIMER1,
2203 0x02, 0x02);
2204 /* Remove mix path mute if it is enabled */
2205 if ((snd_soc_read(codec, WCD934X_CDC_RX1_RX_PATH_MIX_CTL)) &
2206 0x10)
2207 snd_soc_update_bits(codec,
2208 WCD934X_CDC_RX1_RX_PATH_MIX_CTL,
2209 0x10, 0x00);
2210 if (dsd_conf &&
2211 (snd_soc_read(codec, WCD934X_CDC_DSD0_PATH_CTL) & 0x01))
2212 snd_soc_update_bits(codec, WCD934X_CDC_DSD0_CFG2,
2213 0x04, 0x00);
Meng Wangf45a20d2017-01-18 09:51:58 +08002214 if (!(strcmp(w->name, "ANC HPHL PA"))) {
2215 pr_debug("%s:Do everything needed for right channel\n",
2216 __func__);
2217
2218 /* Do everything needed for right channel */
2219 snd_soc_update_bits(codec, WCD934X_HPH_R_TEST,
2220 0x01, 0x01);
2221
2222 /* Remove mute */
2223 snd_soc_update_bits(codec, WCD934X_CDC_RX2_RX_PATH_CTL,
2224 0x10, 0x00);
2225
2226 /* Remove mix path mute if it is enabled */
2227 if ((snd_soc_read(codec,
2228 WCD934X_CDC_RX2_RX_PATH_MIX_CTL)) &
2229 0x10)
2230 snd_soc_update_bits(codec,
2231 WCD934X_CDC_RX2_RX_PATH_MIX_CTL,
2232 0x10, 0x00);
2233 if (dsd_conf && (snd_soc_read(codec,
2234 WCD934X_CDC_DSD1_PATH_CTL) & 0x01))
2235 snd_soc_update_bits(codec,
2236 WCD934X_CDC_DSD1_CFG2,
2237 0x04, 0x00);
2238 /* Remove ANC Rx from reset */
2239 ret = tavil_codec_enable_anc(w, kcontrol, event);
2240 }
Banajit Goswamide8271c2017-01-18 00:28:59 -08002241 tavil_codec_override(codec, tavil->hph_mode, event);
2242 break;
2243 case SND_SOC_DAPM_PRE_PMD:
2244 blocking_notifier_call_chain(&tavil->mbhc->notifier,
2245 WCD_EVENT_PRE_HPHL_PA_OFF,
2246 &tavil->mbhc->wcd_mbhc);
2247 /* Enable DSD Mute before PA disable */
2248 if (dsd_conf &&
2249 (snd_soc_read(codec, WCD934X_CDC_DSD0_PATH_CTL) & 0x01))
2250 snd_soc_update_bits(codec, WCD934X_CDC_DSD0_CFG2,
2251 0x04, 0x04);
2252
2253 snd_soc_update_bits(codec, WCD934X_HPH_L_TEST, 0x01, 0x00);
2254 snd_soc_update_bits(codec, WCD934X_CDC_RX1_RX_PATH_CTL,
2255 0x10, 0x10);
Sudheer Papothi3be76772017-01-11 06:08:13 +05302256 snd_soc_update_bits(codec, WCD934X_CDC_RX1_RX_PATH_MIX_CTL,
2257 0x10, 0x10);
Meng Wangf45a20d2017-01-18 09:51:58 +08002258 if (!(strcmp(w->name, "ANC HPHL PA")))
2259 snd_soc_update_bits(codec, WCD934X_ANA_HPH,
2260 0x80, 0x00);
Banajit Goswamide8271c2017-01-18 00:28:59 -08002261 break;
2262 case SND_SOC_DAPM_POST_PMD:
Sudheer Papothi3be76772017-01-11 06:08:13 +05302263 /*
2264 * 5ms sleep is required after PA disable. If compander is
2265 * disabled, then 20ms delay is needed after PA disable.
2266 */
2267 if (!tavil->comp_enabled[COMPANDER_1])
2268 usleep_range(20000, 20100);
2269 else
2270 usleep_range(5000, 5100);
Banajit Goswamide8271c2017-01-18 00:28:59 -08002271 tavil_codec_override(codec, tavil->hph_mode, event);
2272 blocking_notifier_call_chain(&tavil->mbhc->notifier,
2273 WCD_EVENT_POST_HPHL_PA_OFF,
2274 &tavil->mbhc->wcd_mbhc);
2275 if (TAVIL_IS_1_0(tavil->wcd9xxx))
2276 snd_soc_update_bits(codec, WCD934X_HPH_REFBUFF_LP_CTL,
2277 0x06, 0x0);
Meng Wangf45a20d2017-01-18 09:51:58 +08002278 if (!(strcmp(w->name, "ANC HPHL PA"))) {
2279 ret = tavil_codec_enable_anc(w, kcontrol, event);
2280 snd_soc_update_bits(codec,
2281 WCD934X_CDC_RX1_RX_PATH_CFG0, 0x10, 0x00);
2282 }
Banajit Goswamide8271c2017-01-18 00:28:59 -08002283 break;
2284 };
2285
Meng Wangf45a20d2017-01-18 09:51:58 +08002286 return ret;
Banajit Goswamide8271c2017-01-18 00:28:59 -08002287}
2288
2289static int tavil_codec_enable_lineout_pa(struct snd_soc_dapm_widget *w,
2290 struct snd_kcontrol *kcontrol,
2291 int event)
2292{
2293 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
2294 u16 lineout_vol_reg = 0, lineout_mix_vol_reg = 0;
Phani Kumar Uppalapatia1f87022017-01-25 19:13:13 -08002295 u16 dsd_mute_reg = 0, dsd_clk_reg = 0;
2296 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
2297 struct tavil_dsd_config *dsd_conf = tavil->dsd_config;
Banajit Goswamide8271c2017-01-18 00:28:59 -08002298
2299 dev_dbg(codec->dev, "%s %s %d\n", __func__, w->name, event);
2300
2301 if (w->reg == WCD934X_ANA_LO_1_2) {
2302 if (w->shift == 7) {
2303 lineout_vol_reg = WCD934X_CDC_RX3_RX_PATH_CTL;
2304 lineout_mix_vol_reg = WCD934X_CDC_RX3_RX_PATH_MIX_CTL;
Phani Kumar Uppalapatia1f87022017-01-25 19:13:13 -08002305 dsd_mute_reg = WCD934X_CDC_DSD0_CFG2;
2306 dsd_clk_reg = WCD934X_CDC_DSD0_PATH_CTL;
Banajit Goswamide8271c2017-01-18 00:28:59 -08002307 } else if (w->shift == 6) {
2308 lineout_vol_reg = WCD934X_CDC_RX4_RX_PATH_CTL;
2309 lineout_mix_vol_reg = WCD934X_CDC_RX4_RX_PATH_MIX_CTL;
Phani Kumar Uppalapatia1f87022017-01-25 19:13:13 -08002310 dsd_mute_reg = WCD934X_CDC_DSD1_CFG2;
2311 dsd_clk_reg = WCD934X_CDC_DSD1_PATH_CTL;
Banajit Goswamide8271c2017-01-18 00:28:59 -08002312 }
2313 } else {
2314 dev_err(codec->dev, "%s: Error enabling lineout PA\n",
2315 __func__);
2316 return -EINVAL;
2317 }
2318
2319 switch (event) {
2320 case SND_SOC_DAPM_PRE_PMU:
2321 tavil_codec_override(codec, CLS_AB, event);
2322 break;
2323 case SND_SOC_DAPM_POST_PMU:
2324 /*
2325 * 5ms sleep is required after PA is enabled as per
2326 * HW requirement
2327 */
2328 usleep_range(5000, 5500);
2329 snd_soc_update_bits(codec, lineout_vol_reg,
2330 0x10, 0x00);
2331 /* Remove mix path mute if it is enabled */
2332 if ((snd_soc_read(codec, lineout_mix_vol_reg)) & 0x10)
2333 snd_soc_update_bits(codec,
2334 lineout_mix_vol_reg,
2335 0x10, 0x00);
Phani Kumar Uppalapatia1f87022017-01-25 19:13:13 -08002336 if (dsd_conf && (snd_soc_read(codec, dsd_clk_reg) & 0x01))
2337 snd_soc_update_bits(codec, dsd_mute_reg, 0x04, 0x00);
2338 break;
2339 case SND_SOC_DAPM_PRE_PMD:
2340 if (dsd_conf && (snd_soc_read(codec, dsd_clk_reg) & 0x01))
2341 snd_soc_update_bits(codec, dsd_mute_reg, 0x04, 0x04);
Banajit Goswamide8271c2017-01-18 00:28:59 -08002342 break;
2343 case SND_SOC_DAPM_POST_PMD:
2344 /*
2345 * 5ms sleep is required after PA is disabled as per
2346 * HW requirement
2347 */
2348 usleep_range(5000, 5500);
2349 tavil_codec_override(codec, CLS_AB, event);
2350 default:
2351 break;
2352 };
2353
2354 return 0;
2355}
2356
2357static int tavil_codec_ear_dac_event(struct snd_soc_dapm_widget *w,
2358 struct snd_kcontrol *kcontrol,
2359 int event)
2360{
2361 int ret = 0;
2362 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
2363 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
2364
2365 dev_dbg(codec->dev, "%s %s %d\n", __func__, w->name, event);
2366
2367 switch (event) {
2368 case SND_SOC_DAPM_PRE_PMU:
2369 /* Disable AutoChop timer during power up */
2370 snd_soc_update_bits(codec, WCD934X_HPH_NEW_INT_HPH_TIMER1,
2371 0x02, 0x00);
2372
2373 if (tavil->anc_func)
2374 ret = tavil_codec_enable_anc(w, kcontrol, event);
2375
2376 wcd_clsh_fsm(codec, &tavil->clsh_d,
2377 WCD_CLSH_EVENT_PRE_DAC,
2378 WCD_CLSH_STATE_EAR,
2379 CLS_H_NORMAL);
2380 if (tavil->anc_func)
2381 snd_soc_update_bits(codec, WCD934X_CDC_RX0_RX_PATH_CFG0,
2382 0x10, 0x10);
2383 break;
2384 case SND_SOC_DAPM_POST_PMD:
2385 wcd_clsh_fsm(codec, &tavil->clsh_d,
2386 WCD_CLSH_EVENT_POST_PA,
2387 WCD_CLSH_STATE_EAR,
2388 CLS_H_NORMAL);
2389 break;
2390 default:
2391 break;
2392 };
2393
2394 return ret;
2395}
2396
2397static int tavil_codec_hphr_dac_event(struct snd_soc_dapm_widget *w,
2398 struct snd_kcontrol *kcontrol,
2399 int event)
2400{
2401 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
2402 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
2403 int hph_mode = tavil->hph_mode;
2404 u8 dem_inp;
2405 struct tavil_dsd_config *dsd_conf = tavil->dsd_config;
Meng Wangf45a20d2017-01-18 09:51:58 +08002406 int ret = 0;
Banajit Goswamide8271c2017-01-18 00:28:59 -08002407
2408 dev_dbg(codec->dev, "%s wname: %s event: %d hph_mode: %d\n", __func__,
2409 w->name, event, hph_mode);
2410
2411 switch (event) {
2412 case SND_SOC_DAPM_PRE_PMU:
Meng Wangf45a20d2017-01-18 09:51:58 +08002413 if (tavil->anc_func) {
2414 ret = tavil_codec_enable_anc(w, kcontrol, event);
2415 /* 40 msec delay is needed to avoid click and pop */
2416 msleep(40);
2417 }
Banajit Goswamide8271c2017-01-18 00:28:59 -08002418 /* Read DEM INP Select */
2419 dem_inp = snd_soc_read(codec, WCD934X_CDC_RX2_RX_PATH_SEC0) &
2420 0x03;
2421 if (((hph_mode == CLS_H_HIFI) || (hph_mode == CLS_H_LOHIFI) ||
2422 (hph_mode == CLS_H_LP)) && (dem_inp != 0x01)) {
2423 dev_err(codec->dev, "%s: DEM Input not set correctly, hph_mode: %d\n",
2424 __func__, hph_mode);
2425 return -EINVAL;
2426 }
2427 if ((hph_mode != CLS_H_LP) && (hph_mode != CLS_H_ULP))
2428 /* Ripple freq control enable */
2429 snd_soc_update_bits(codec,
2430 WCD934X_SIDO_NEW_VOUT_D_FREQ2,
2431 0x01, 0x01);
2432 /* Disable AutoChop timer during power up */
2433 snd_soc_update_bits(codec, WCD934X_HPH_NEW_INT_HPH_TIMER1,
2434 0x02, 0x00);
2435 /* Set RDAC gain */
2436 if (TAVIL_IS_1_0(tavil->wcd9xxx))
2437 snd_soc_update_bits(codec,
2438 WCD934X_HPH_NEW_INT_RDAC_GAIN_CTL,
2439 0xF0, 0x40);
2440 if (dsd_conf &&
2441 (snd_soc_read(codec, WCD934X_CDC_DSD1_PATH_CTL) & 0x01))
2442 hph_mode = CLS_H_HIFI;
2443
2444 wcd_clsh_fsm(codec, &tavil->clsh_d,
2445 WCD_CLSH_EVENT_PRE_DAC,
2446 WCD_CLSH_STATE_HPHR,
2447 hph_mode);
Meng Wangf45a20d2017-01-18 09:51:58 +08002448 if (tavil->anc_func)
2449 snd_soc_update_bits(codec,
2450 WCD934X_CDC_RX2_RX_PATH_CFG0,
2451 0x10, 0x10);
Banajit Goswamide8271c2017-01-18 00:28:59 -08002452 break;
2453 case SND_SOC_DAPM_POST_PMD:
2454 /* 1000us required as per HW requirement */
2455 usleep_range(1000, 1100);
2456 wcd_clsh_fsm(codec, &tavil->clsh_d,
2457 WCD_CLSH_EVENT_POST_PA,
2458 WCD_CLSH_STATE_HPHR,
2459 hph_mode);
2460 if ((hph_mode != CLS_H_LP) && (hph_mode != CLS_H_ULP))
2461 /* Ripple freq control disable */
2462 snd_soc_update_bits(codec,
2463 WCD934X_SIDO_NEW_VOUT_D_FREQ2,
2464 0x01, 0x0);
2465 /* Re-set RDAC gain */
2466 if (TAVIL_IS_1_0(tavil->wcd9xxx))
2467 snd_soc_update_bits(codec,
2468 WCD934X_HPH_NEW_INT_RDAC_GAIN_CTL,
2469 0xF0, 0x0);
2470 break;
2471 default:
2472 break;
2473 };
2474
2475 return 0;
2476}
2477
2478static int tavil_codec_hphl_dac_event(struct snd_soc_dapm_widget *w,
2479 struct snd_kcontrol *kcontrol,
2480 int event)
2481{
2482 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
2483 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
2484 int hph_mode = tavil->hph_mode;
2485 u8 dem_inp;
2486 int ret = 0;
2487 struct tavil_dsd_config *dsd_conf = tavil->dsd_config;
Phani Kumar Uppalapatib506bc02016-12-06 16:08:24 -08002488 uint32_t impedl = 0, impedr = 0;
Banajit Goswamide8271c2017-01-18 00:28:59 -08002489
2490 dev_dbg(codec->dev, "%s wname: %s event: %d hph_mode: %d\n", __func__,
2491 w->name, event, hph_mode);
2492
2493 switch (event) {
2494 case SND_SOC_DAPM_PRE_PMU:
Meng Wangf45a20d2017-01-18 09:51:58 +08002495 if (tavil->anc_func) {
2496 ret = tavil_codec_enable_anc(w, kcontrol, event);
2497 /* 40 msec delay is needed to avoid click and pop */
2498 msleep(40);
2499 }
Banajit Goswamide8271c2017-01-18 00:28:59 -08002500 /* Read DEM INP Select */
2501 dem_inp = snd_soc_read(codec, WCD934X_CDC_RX1_RX_PATH_SEC0) &
2502 0x03;
2503 if (((hph_mode == CLS_H_HIFI) || (hph_mode == CLS_H_LOHIFI) ||
2504 (hph_mode == CLS_H_LP)) && (dem_inp != 0x01)) {
2505 dev_err(codec->dev, "%s: DEM Input not set correctly, hph_mode: %d\n",
2506 __func__, hph_mode);
2507 return -EINVAL;
2508 }
2509 if ((hph_mode != CLS_H_LP) && (hph_mode != CLS_H_ULP))
2510 /* Ripple freq control enable */
2511 snd_soc_update_bits(codec,
2512 WCD934X_SIDO_NEW_VOUT_D_FREQ2,
2513 0x01, 0x01);
2514 /* Disable AutoChop timer during power up */
2515 snd_soc_update_bits(codec, WCD934X_HPH_NEW_INT_HPH_TIMER1,
2516 0x02, 0x00);
2517 /* Set RDAC gain */
2518 if (TAVIL_IS_1_0(tavil->wcd9xxx))
2519 snd_soc_update_bits(codec,
2520 WCD934X_HPH_NEW_INT_RDAC_GAIN_CTL,
2521 0xF0, 0x40);
2522 if (dsd_conf &&
2523 (snd_soc_read(codec, WCD934X_CDC_DSD0_PATH_CTL) & 0x01))
2524 hph_mode = CLS_H_HIFI;
2525
2526 wcd_clsh_fsm(codec, &tavil->clsh_d,
2527 WCD_CLSH_EVENT_PRE_DAC,
2528 WCD_CLSH_STATE_HPHL,
2529 hph_mode);
Phani Kumar Uppalapatib506bc02016-12-06 16:08:24 -08002530
Meng Wangf45a20d2017-01-18 09:51:58 +08002531 if (tavil->anc_func)
2532 snd_soc_update_bits(codec,
2533 WCD934X_CDC_RX1_RX_PATH_CFG0,
2534 0x10, 0x10);
2535
Phani Kumar Uppalapatib506bc02016-12-06 16:08:24 -08002536 ret = tavil_mbhc_get_impedance(tavil->mbhc,
2537 &impedl, &impedr);
2538 if (!ret) {
2539 wcd_clsh_imped_config(codec, impedl, false);
2540 set_bit(CLSH_Z_CONFIG, &tavil->status_mask);
2541 } else {
2542 dev_dbg(codec->dev, "%s: Failed to get mbhc impedance %d\n",
2543 __func__, ret);
2544 ret = 0;
2545 }
2546
Banajit Goswamide8271c2017-01-18 00:28:59 -08002547 break;
2548 case SND_SOC_DAPM_POST_PMD:
2549 /* 1000us required as per HW requirement */
2550 usleep_range(1000, 1100);
2551 wcd_clsh_fsm(codec, &tavil->clsh_d,
2552 WCD_CLSH_EVENT_POST_PA,
2553 WCD_CLSH_STATE_HPHL,
2554 hph_mode);
2555 if ((hph_mode != CLS_H_LP) && (hph_mode != CLS_H_ULP))
2556 /* Ripple freq control disable */
2557 snd_soc_update_bits(codec,
2558 WCD934X_SIDO_NEW_VOUT_D_FREQ2,
2559 0x01, 0x0);
2560 /* Re-set RDAC gain */
2561 if (TAVIL_IS_1_0(tavil->wcd9xxx))
2562 snd_soc_update_bits(codec,
2563 WCD934X_HPH_NEW_INT_RDAC_GAIN_CTL,
2564 0xF0, 0x0);
Phani Kumar Uppalapatib506bc02016-12-06 16:08:24 -08002565
2566 if (test_bit(CLSH_Z_CONFIG, &tavil->status_mask)) {
2567 wcd_clsh_imped_config(codec, impedl, true);
2568 clear_bit(CLSH_Z_CONFIG, &tavil->status_mask);
2569 }
Banajit Goswamide8271c2017-01-18 00:28:59 -08002570 break;
2571 default:
2572 break;
2573 };
2574
2575 return ret;
2576}
2577
2578static int tavil_codec_lineout_dac_event(struct snd_soc_dapm_widget *w,
2579 struct snd_kcontrol *kcontrol,
2580 int event)
2581{
2582 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
2583 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
2584
2585 dev_dbg(codec->dev, "%s %s %d\n", __func__, w->name, event);
2586
2587 switch (event) {
2588 case SND_SOC_DAPM_PRE_PMU:
2589 wcd_clsh_fsm(codec, &tavil->clsh_d,
2590 WCD_CLSH_EVENT_PRE_DAC,
2591 WCD_CLSH_STATE_LO,
2592 CLS_AB);
2593 break;
2594 case SND_SOC_DAPM_POST_PMD:
2595 wcd_clsh_fsm(codec, &tavil->clsh_d,
2596 WCD_CLSH_EVENT_POST_PA,
2597 WCD_CLSH_STATE_LO,
2598 CLS_AB);
2599 break;
2600 }
2601
2602 return 0;
2603}
2604
2605static int tavil_codec_spk_boost_event(struct snd_soc_dapm_widget *w,
2606 struct snd_kcontrol *kcontrol,
2607 int event)
2608{
2609 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
2610 u16 boost_path_ctl, boost_path_cfg1;
2611 u16 reg, reg_mix;
2612
2613 dev_dbg(codec->dev, "%s %s %d\n", __func__, w->name, event);
2614
2615 if (!strcmp(w->name, "RX INT7 CHAIN")) {
2616 boost_path_ctl = WCD934X_CDC_BOOST0_BOOST_PATH_CTL;
2617 boost_path_cfg1 = WCD934X_CDC_RX7_RX_PATH_CFG1;
2618 reg = WCD934X_CDC_RX7_RX_PATH_CTL;
2619 reg_mix = WCD934X_CDC_RX7_RX_PATH_MIX_CTL;
2620 } else if (!strcmp(w->name, "RX INT8 CHAIN")) {
2621 boost_path_ctl = WCD934X_CDC_BOOST1_BOOST_PATH_CTL;
2622 boost_path_cfg1 = WCD934X_CDC_RX8_RX_PATH_CFG1;
2623 reg = WCD934X_CDC_RX8_RX_PATH_CTL;
2624 reg_mix = WCD934X_CDC_RX8_RX_PATH_MIX_CTL;
2625 } else {
2626 dev_err(codec->dev, "%s: unknown widget: %s\n",
2627 __func__, w->name);
2628 return -EINVAL;
2629 }
2630
2631 switch (event) {
2632 case SND_SOC_DAPM_PRE_PMU:
2633 snd_soc_update_bits(codec, boost_path_cfg1, 0x01, 0x01);
2634 snd_soc_update_bits(codec, boost_path_ctl, 0x10, 0x10);
2635 snd_soc_update_bits(codec, reg, 0x10, 0x00);
2636 if ((snd_soc_read(codec, reg_mix)) & 0x10)
2637 snd_soc_update_bits(codec, reg_mix, 0x10, 0x00);
2638 break;
2639 case SND_SOC_DAPM_POST_PMD:
2640 snd_soc_update_bits(codec, boost_path_ctl, 0x10, 0x00);
2641 snd_soc_update_bits(codec, boost_path_cfg1, 0x01, 0x00);
2642 break;
2643 };
2644
2645 return 0;
2646}
2647
2648static int __tavil_codec_enable_swr(struct snd_soc_dapm_widget *w, int event)
2649{
2650 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
2651 struct tavil_priv *tavil;
2652 int ch_cnt = 0;
2653
2654 tavil = snd_soc_codec_get_drvdata(codec);
2655
2656 switch (event) {
2657 case SND_SOC_DAPM_PRE_PMU:
2658 if (((strnstr(w->name, "INT7_", sizeof("RX INT7_"))) ||
2659 (strnstr(w->name, "INT7 MIX2",
2660 sizeof("RX INT7 MIX2")))))
2661 tavil->swr.rx_7_count++;
2662 if ((strnstr(w->name, "INT8_", sizeof("RX INT8_"))) &&
2663 !tavil->swr.rx_8_count)
2664 tavil->swr.rx_8_count++;
2665 ch_cnt = !!(tavil->swr.rx_7_count) + tavil->swr.rx_8_count;
2666
2667 swrm_wcd_notify(tavil->swr.ctrl_data[0].swr_pdev,
2668 SWR_DEVICE_UP, NULL);
2669 swrm_wcd_notify(tavil->swr.ctrl_data[0].swr_pdev,
2670 SWR_SET_NUM_RX_CH, &ch_cnt);
2671 break;
2672 case SND_SOC_DAPM_POST_PMD:
2673 if ((strnstr(w->name, "INT7_", sizeof("RX INT7_"))) ||
2674 (strnstr(w->name, "INT7 MIX2",
2675 sizeof("RX INT7 MIX2"))))
2676 tavil->swr.rx_7_count--;
2677 if ((strnstr(w->name, "INT8_", sizeof("RX INT8_"))) &&
2678 tavil->swr.rx_8_count)
2679 tavil->swr.rx_8_count--;
2680 ch_cnt = !!(tavil->swr.rx_7_count) + tavil->swr.rx_8_count;
2681
2682 swrm_wcd_notify(tavil->swr.ctrl_data[0].swr_pdev,
2683 SWR_SET_NUM_RX_CH, &ch_cnt);
2684
2685 break;
2686 }
2687 dev_dbg(tavil->dev, "%s: %s: current swr ch cnt: %d\n",
2688 __func__, w->name, ch_cnt);
2689
2690 return 0;
2691}
2692
2693static int tavil_codec_enable_swr(struct snd_soc_dapm_widget *w,
2694 struct snd_kcontrol *kcontrol, int event)
2695{
2696 return __tavil_codec_enable_swr(w, event);
2697}
2698
2699static int tavil_codec_config_mad(struct snd_soc_codec *codec)
2700{
2701 int ret = 0;
2702 int idx;
2703 const struct firmware *fw;
2704 struct firmware_cal *hwdep_cal = NULL;
2705 struct wcd_mad_audio_cal *mad_cal = NULL;
2706 const void *data;
2707 const char *filename = WCD934X_MAD_AUDIO_FIRMWARE_PATH;
2708 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
2709 size_t cal_size;
2710
2711 hwdep_cal = wcdcal_get_fw_cal(tavil->fw_data, WCD9XXX_MAD_CAL);
2712 if (hwdep_cal) {
2713 data = hwdep_cal->data;
2714 cal_size = hwdep_cal->size;
2715 dev_dbg(codec->dev, "%s: using hwdep calibration\n",
2716 __func__);
2717 } else {
2718 ret = request_firmware(&fw, filename, codec->dev);
2719 if (ret || !fw) {
2720 dev_err(codec->dev,
2721 "%s: MAD firmware acquire failed, err = %d\n",
2722 __func__, ret);
2723 return -ENODEV;
2724 }
2725 data = fw->data;
2726 cal_size = fw->size;
2727 dev_dbg(codec->dev, "%s: using request_firmware calibration\n",
2728 __func__);
2729 }
2730
2731 if (cal_size < sizeof(*mad_cal)) {
2732 dev_err(codec->dev,
2733 "%s: Incorrect size %zd for MAD Cal, expected %zd\n",
2734 __func__, cal_size, sizeof(*mad_cal));
2735 ret = -ENOMEM;
2736 goto done;
2737 }
2738
2739 mad_cal = (struct wcd_mad_audio_cal *) (data);
2740 if (!mad_cal) {
2741 dev_err(codec->dev,
2742 "%s: Invalid calibration data\n",
2743 __func__);
2744 ret = -EINVAL;
2745 goto done;
2746 }
2747
2748 snd_soc_write(codec, WCD934X_SOC_MAD_MAIN_CTL_2,
2749 mad_cal->microphone_info.cycle_time);
2750 snd_soc_update_bits(codec, WCD934X_SOC_MAD_MAIN_CTL_1, 0xFF << 3,
2751 ((uint16_t)mad_cal->microphone_info.settle_time)
2752 << 3);
2753
2754 /* Audio */
2755 snd_soc_write(codec, WCD934X_SOC_MAD_AUDIO_CTL_8,
2756 mad_cal->audio_info.rms_omit_samples);
2757 snd_soc_update_bits(codec, WCD934X_SOC_MAD_AUDIO_CTL_1,
2758 0x07 << 4, mad_cal->audio_info.rms_comp_time << 4);
2759 snd_soc_update_bits(codec, WCD934X_SOC_MAD_AUDIO_CTL_2, 0x03 << 2,
2760 mad_cal->audio_info.detection_mechanism << 2);
2761 snd_soc_write(codec, WCD934X_SOC_MAD_AUDIO_CTL_7,
2762 mad_cal->audio_info.rms_diff_threshold & 0x3F);
2763 snd_soc_write(codec, WCD934X_SOC_MAD_AUDIO_CTL_5,
2764 mad_cal->audio_info.rms_threshold_lsb);
2765 snd_soc_write(codec, WCD934X_SOC_MAD_AUDIO_CTL_6,
2766 mad_cal->audio_info.rms_threshold_msb);
2767
2768 for (idx = 0; idx < ARRAY_SIZE(mad_cal->audio_info.iir_coefficients);
2769 idx++) {
2770 snd_soc_update_bits(codec, WCD934X_SOC_MAD_AUDIO_IIR_CTL_PTR,
2771 0x3F, idx);
2772 snd_soc_write(codec, WCD934X_SOC_MAD_AUDIO_IIR_CTL_VAL,
2773 mad_cal->audio_info.iir_coefficients[idx]);
2774 dev_dbg(codec->dev, "%s:MAD Audio IIR Coef[%d] = 0X%x",
2775 __func__, idx,
2776 mad_cal->audio_info.iir_coefficients[idx]);
2777 }
2778
2779 /* Beacon */
2780 snd_soc_write(codec, WCD934X_SOC_MAD_BEACON_CTL_8,
2781 mad_cal->beacon_info.rms_omit_samples);
2782 snd_soc_update_bits(codec, WCD934X_SOC_MAD_BEACON_CTL_1,
2783 0x07 << 4, mad_cal->beacon_info.rms_comp_time << 4);
2784 snd_soc_update_bits(codec, WCD934X_SOC_MAD_BEACON_CTL_2, 0x03 << 2,
2785 mad_cal->beacon_info.detection_mechanism << 2);
2786 snd_soc_write(codec, WCD934X_SOC_MAD_BEACON_CTL_7,
2787 mad_cal->beacon_info.rms_diff_threshold & 0x1F);
2788 snd_soc_write(codec, WCD934X_SOC_MAD_BEACON_CTL_5,
2789 mad_cal->beacon_info.rms_threshold_lsb);
2790 snd_soc_write(codec, WCD934X_SOC_MAD_BEACON_CTL_6,
2791 mad_cal->beacon_info.rms_threshold_msb);
2792
2793 for (idx = 0; idx < ARRAY_SIZE(mad_cal->beacon_info.iir_coefficients);
2794 idx++) {
2795 snd_soc_update_bits(codec, WCD934X_SOC_MAD_BEACON_IIR_CTL_PTR,
2796 0x3F, idx);
2797 snd_soc_write(codec, WCD934X_SOC_MAD_BEACON_IIR_CTL_VAL,
2798 mad_cal->beacon_info.iir_coefficients[idx]);
2799 dev_dbg(codec->dev, "%s:MAD Beacon IIR Coef[%d] = 0X%x",
2800 __func__, idx,
2801 mad_cal->beacon_info.iir_coefficients[idx]);
2802 }
2803
2804 /* Ultrasound */
2805 snd_soc_update_bits(codec, WCD934X_SOC_MAD_ULTR_CTL_1,
2806 0x07 << 4,
2807 mad_cal->ultrasound_info.rms_comp_time << 4);
2808 snd_soc_update_bits(codec, WCD934X_SOC_MAD_ULTR_CTL_2, 0x03 << 2,
2809 mad_cal->ultrasound_info.detection_mechanism << 2);
2810 snd_soc_write(codec, WCD934X_SOC_MAD_ULTR_CTL_7,
2811 mad_cal->ultrasound_info.rms_diff_threshold & 0x1F);
2812 snd_soc_write(codec, WCD934X_SOC_MAD_ULTR_CTL_5,
2813 mad_cal->ultrasound_info.rms_threshold_lsb);
2814 snd_soc_write(codec, WCD934X_SOC_MAD_ULTR_CTL_6,
2815 mad_cal->ultrasound_info.rms_threshold_msb);
2816
2817done:
2818 if (!hwdep_cal)
2819 release_firmware(fw);
2820
2821 return ret;
2822}
2823
2824static int __tavil_codec_enable_mad(struct snd_soc_codec *codec, bool enable)
2825{
2826 int rc = 0;
2827
2828 /* Return if CPE INPUT is DEC1 */
2829 if (snd_soc_read(codec, WCD934X_CPE_SS_SVA_CFG) & 0x04) {
2830 dev_dbg(codec->dev, "%s: MAD is bypassed, skip mad %s\n",
2831 __func__, enable ? "enable" : "disable");
2832 return rc;
2833 }
2834
2835 dev_dbg(codec->dev, "%s: enable = %s\n", __func__,
2836 enable ? "enable" : "disable");
2837
2838 if (enable) {
2839 snd_soc_update_bits(codec, WCD934X_SOC_MAD_AUDIO_CTL_2,
2840 0x03, 0x03);
2841 rc = tavil_codec_config_mad(codec);
Xiaoyu Ye1a2d8bd92017-01-31 18:54:15 -08002842 if (rc < 0) {
Banajit Goswamide8271c2017-01-18 00:28:59 -08002843 snd_soc_update_bits(codec, WCD934X_SOC_MAD_AUDIO_CTL_2,
2844 0x03, 0x00);
2845 goto done;
2846 }
2847
2848 /* Turn on MAD clk */
2849 snd_soc_update_bits(codec, WCD934X_CPE_SS_MAD_CTL,
2850 0x01, 0x01);
2851
2852 /* Undo reset for MAD */
2853 snd_soc_update_bits(codec, WCD934X_CPE_SS_MAD_CTL,
2854 0x02, 0x00);
Banajit Goswami1e0e29c2017-01-09 14:21:51 +05302855 snd_soc_update_bits(codec, WCD934X_CODEC_RPM_CLK_MCLK_CFG,
2856 0x04, 0x04);
Banajit Goswamide8271c2017-01-18 00:28:59 -08002857 } else {
2858 snd_soc_update_bits(codec, WCD934X_SOC_MAD_AUDIO_CTL_2,
2859 0x03, 0x00);
2860 /* Reset the MAD block */
2861 snd_soc_update_bits(codec, WCD934X_CPE_SS_MAD_CTL,
2862 0x02, 0x02);
2863 /* Turn off MAD clk */
2864 snd_soc_update_bits(codec, WCD934X_CPE_SS_MAD_CTL,
2865 0x01, 0x00);
Banajit Goswami1e0e29c2017-01-09 14:21:51 +05302866 snd_soc_update_bits(codec, WCD934X_CODEC_RPM_CLK_MCLK_CFG,
2867 0x04, 0x00);
Banajit Goswamide8271c2017-01-18 00:28:59 -08002868 }
2869done:
2870 return rc;
2871}
2872
2873static int tavil_codec_ape_enable_mad(struct snd_soc_dapm_widget *w,
2874 struct snd_kcontrol *kcontrol,
2875 int event)
2876{
2877 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
2878 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
2879 int rc = 0;
2880
2881 switch (event) {
2882 case SND_SOC_DAPM_PRE_PMU:
2883 snd_soc_update_bits(codec, WCD934X_CPE_SS_SVA_CFG, 0x40, 0x40);
2884 rc = __tavil_codec_enable_mad(codec, true);
2885 break;
2886 case SND_SOC_DAPM_PRE_PMD:
2887 snd_soc_update_bits(codec, WCD934X_CPE_SS_SVA_CFG, 0x40, 0x00);
2888 __tavil_codec_enable_mad(codec, false);
2889 break;
2890 }
2891
2892 dev_dbg(tavil->dev, "%s: event = %d\n", __func__, event);
2893 return rc;
2894}
2895
2896static int tavil_codec_cpe_mad_ctl(struct snd_soc_dapm_widget *w,
2897 struct snd_kcontrol *kcontrol, int event)
2898{
2899 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
2900 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
2901 int rc = 0;
2902
2903 switch (event) {
2904 case SND_SOC_DAPM_PRE_PMU:
2905 tavil->mad_switch_cnt++;
2906 if (tavil->mad_switch_cnt != 1)
2907 goto done;
2908
2909 snd_soc_update_bits(codec, WCD934X_CPE_SS_SVA_CFG, 0x20, 0x20);
2910 rc = __tavil_codec_enable_mad(codec, true);
Xiaoyu Ye1a2d8bd92017-01-31 18:54:15 -08002911 if (rc < 0) {
Banajit Goswamide8271c2017-01-18 00:28:59 -08002912 tavil->mad_switch_cnt--;
2913 goto done;
2914 }
2915
2916 break;
2917 case SND_SOC_DAPM_PRE_PMD:
2918 tavil->mad_switch_cnt--;
2919 if (tavil->mad_switch_cnt != 0)
2920 goto done;
2921
2922 snd_soc_update_bits(codec, WCD934X_CPE_SS_SVA_CFG, 0x20, 0x00);
2923 __tavil_codec_enable_mad(codec, false);
2924 break;
2925 }
2926done:
2927 dev_dbg(tavil->dev, "%s: event = %d, mad_switch_cnt = %d\n",
2928 __func__, event, tavil->mad_switch_cnt);
2929 return rc;
2930}
2931
2932static int tavil_get_asrc_mode(struct tavil_priv *tavil, int asrc,
2933 u8 main_sr, u8 mix_sr)
2934{
2935 u8 asrc_output_mode;
2936 int asrc_mode = CONV_88P2K_TO_384K;
2937
2938 if ((asrc < 0) || (asrc >= ASRC_MAX))
2939 return 0;
2940
2941 asrc_output_mode = tavil->asrc_output_mode[asrc];
2942
2943 if (asrc_output_mode) {
2944 /*
2945 * If Mix sample rate is < 96KHz, use 96K to 352.8K
2946 * conversion, or else use 384K to 352.8K conversion
2947 */
2948 if (mix_sr < 5)
2949 asrc_mode = CONV_96K_TO_352P8K;
2950 else
2951 asrc_mode = CONV_384K_TO_352P8K;
2952 } else {
2953 /* Integer main and Fractional mix path */
2954 if (main_sr < 8 && mix_sr > 9) {
2955 asrc_mode = CONV_352P8K_TO_384K;
2956 } else if (main_sr > 8 && mix_sr < 8) {
2957 /* Fractional main and Integer mix path */
2958 if (mix_sr < 5)
2959 asrc_mode = CONV_96K_TO_352P8K;
2960 else
2961 asrc_mode = CONV_384K_TO_352P8K;
2962 } else if (main_sr < 8 && mix_sr < 8) {
2963 /* Integer main and Integer mix path */
2964 asrc_mode = CONV_96K_TO_384K;
2965 }
2966 }
2967
2968 return asrc_mode;
2969}
2970
2971static int tavil_codec_enable_asrc(struct snd_soc_codec *codec,
2972 int asrc_in, int event)
2973{
2974 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
2975 u16 cfg_reg, ctl_reg, clk_reg, asrc_ctl, mix_ctl_reg;
2976 int asrc, ret = 0;
2977 u8 main_sr, mix_sr, asrc_mode = 0;
2978
2979 switch (asrc_in) {
2980 case ASRC_IN_HPHL:
2981 cfg_reg = WCD934X_CDC_RX1_RX_PATH_CFG0;
2982 ctl_reg = WCD934X_CDC_RX1_RX_PATH_CTL;
2983 clk_reg = WCD934X_MIXING_ASRC0_CLK_RST_CTL;
2984 asrc_ctl = WCD934X_MIXING_ASRC0_CTL1;
2985 asrc = ASRC0;
2986 break;
2987 case ASRC_IN_LO1:
2988 cfg_reg = WCD934X_CDC_RX3_RX_PATH_CFG0;
2989 ctl_reg = WCD934X_CDC_RX3_RX_PATH_CTL;
2990 clk_reg = WCD934X_MIXING_ASRC0_CLK_RST_CTL;
2991 asrc_ctl = WCD934X_MIXING_ASRC0_CTL1;
2992 asrc = ASRC0;
2993 break;
2994 case ASRC_IN_HPHR:
2995 cfg_reg = WCD934X_CDC_RX2_RX_PATH_CFG0;
2996 ctl_reg = WCD934X_CDC_RX2_RX_PATH_CTL;
2997 clk_reg = WCD934X_MIXING_ASRC1_CLK_RST_CTL;
2998 asrc_ctl = WCD934X_MIXING_ASRC1_CTL1;
2999 asrc = ASRC1;
3000 break;
3001 case ASRC_IN_LO2:
3002 cfg_reg = WCD934X_CDC_RX4_RX_PATH_CFG0;
3003 ctl_reg = WCD934X_CDC_RX4_RX_PATH_CTL;
3004 clk_reg = WCD934X_MIXING_ASRC1_CLK_RST_CTL;
3005 asrc_ctl = WCD934X_MIXING_ASRC1_CTL1;
3006 asrc = ASRC1;
3007 break;
3008 case ASRC_IN_SPKR1:
3009 cfg_reg = WCD934X_CDC_RX7_RX_PATH_CFG0;
3010 ctl_reg = WCD934X_CDC_RX7_RX_PATH_CTL;
3011 clk_reg = WCD934X_MIXING_ASRC2_CLK_RST_CTL;
3012 asrc_ctl = WCD934X_MIXING_ASRC2_CTL1;
3013 asrc = ASRC2;
3014 break;
3015 case ASRC_IN_SPKR2:
3016 cfg_reg = WCD934X_CDC_RX8_RX_PATH_CFG0;
3017 ctl_reg = WCD934X_CDC_RX8_RX_PATH_CTL;
3018 clk_reg = WCD934X_MIXING_ASRC3_CLK_RST_CTL;
3019 asrc_ctl = WCD934X_MIXING_ASRC3_CTL1;
3020 asrc = ASRC3;
3021 break;
3022 default:
3023 dev_err(codec->dev, "%s: Invalid asrc input :%d\n", __func__,
3024 asrc_in);
3025 ret = -EINVAL;
3026 goto done;
3027 };
3028
3029 switch (event) {
3030 case SND_SOC_DAPM_PRE_PMU:
3031 if (tavil->asrc_users[asrc] == 0) {
3032 snd_soc_update_bits(codec, cfg_reg, 0x80, 0x80);
3033 snd_soc_update_bits(codec, clk_reg, 0x01, 0x01);
3034 main_sr = snd_soc_read(codec, ctl_reg) & 0x0F;
3035 mix_ctl_reg = ctl_reg + 5;
3036 mix_sr = snd_soc_read(codec, mix_ctl_reg) & 0x0F;
3037 asrc_mode = tavil_get_asrc_mode(tavil, asrc,
3038 main_sr, mix_sr);
3039 dev_dbg(codec->dev, "%s: main_sr:%d mix_sr:%d asrc_mode %d\n",
3040 __func__, main_sr, mix_sr, asrc_mode);
3041 snd_soc_update_bits(codec, asrc_ctl, 0x07, asrc_mode);
3042 }
3043 tavil->asrc_users[asrc]++;
3044 break;
3045 case SND_SOC_DAPM_POST_PMD:
3046 tavil->asrc_users[asrc]--;
3047 if (tavil->asrc_users[asrc] <= 0) {
3048 tavil->asrc_users[asrc] = 0;
3049 snd_soc_update_bits(codec, asrc_ctl, 0x07, 0x00);
3050 snd_soc_update_bits(codec, cfg_reg, 0x80, 0x00);
3051 snd_soc_update_bits(codec, clk_reg, 0x01, 0x00);
3052 }
3053 break;
3054 };
3055
3056 dev_dbg(codec->dev, "%s: ASRC%d, users: %d\n",
3057 __func__, asrc, tavil->asrc_users[asrc]);
3058
3059done:
3060 return ret;
3061}
3062
3063static int tavil_codec_enable_asrc_resampler(struct snd_soc_dapm_widget *w,
3064 struct snd_kcontrol *kcontrol,
3065 int event)
3066{
3067 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
3068 int ret = 0;
3069 u8 cfg, asrc_in;
3070
3071 cfg = snd_soc_read(codec, WCD934X_CDC_RX_INP_MUX_SPLINE_ASRC_CFG0);
3072 if (!(cfg & 0xFF)) {
3073 dev_err(codec->dev, "%s: ASRC%u input not selected\n",
3074 __func__, w->shift);
3075 return -EINVAL;
3076 }
3077
3078 switch (w->shift) {
3079 case ASRC0:
3080 asrc_in = ((cfg & 0x03) == 1) ? ASRC_IN_HPHL : ASRC_IN_LO1;
3081 ret = tavil_codec_enable_asrc(codec, asrc_in, event);
3082 break;
3083 case ASRC1:
3084 asrc_in = ((cfg & 0x0C) == 4) ? ASRC_IN_HPHR : ASRC_IN_LO2;
3085 ret = tavil_codec_enable_asrc(codec, asrc_in, event);
3086 break;
3087 case ASRC2:
3088 asrc_in = ((cfg & 0x30) == 0x20) ? ASRC_IN_SPKR1 : ASRC_INVALID;
3089 ret = tavil_codec_enable_asrc(codec, asrc_in, event);
3090 break;
3091 case ASRC3:
3092 asrc_in = ((cfg & 0xC0) == 0x80) ? ASRC_IN_SPKR2 : ASRC_INVALID;
3093 ret = tavil_codec_enable_asrc(codec, asrc_in, event);
3094 break;
3095 default:
3096 dev_err(codec->dev, "%s: Invalid asrc:%u\n", __func__,
3097 w->shift);
3098 ret = -EINVAL;
3099 break;
3100 };
3101
3102 return ret;
3103}
3104
3105static int tavil_enable_native_supply(struct snd_soc_dapm_widget *w,
3106 struct snd_kcontrol *kcontrol, int event)
3107{
3108 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
3109 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
3110
3111 switch (event) {
3112 case SND_SOC_DAPM_PRE_PMU:
3113 if (++tavil->native_clk_users == 1) {
3114 snd_soc_update_bits(codec, WCD934X_CLK_SYS_PLL_ENABLES,
3115 0x01, 0x01);
3116 usleep_range(100, 120);
3117 snd_soc_update_bits(codec, WCD934X_CLK_SYS_MCLK2_PRG1,
3118 0x06, 0x02);
3119 snd_soc_update_bits(codec, WCD934X_CLK_SYS_MCLK2_PRG1,
3120 0x01, 0x01);
3121 snd_soc_update_bits(codec, WCD934X_CODEC_RPM_CLK_GATE,
3122 0x04, 0x00);
3123 usleep_range(30, 50);
3124 snd_soc_update_bits(codec,
3125 WCD934X_CDC_CLK_RST_CTRL_MCLK_CONTROL,
3126 0x02, 0x02);
3127 snd_soc_update_bits(codec,
3128 WCD934X_CDC_CLK_RST_CTRL_FS_CNT_CONTROL,
3129 0x10, 0x10);
3130 }
3131 break;
3132 case SND_SOC_DAPM_PRE_PMD:
3133 if (tavil->native_clk_users &&
3134 (--tavil->native_clk_users == 0)) {
3135 snd_soc_update_bits(codec,
3136 WCD934X_CDC_CLK_RST_CTRL_FS_CNT_CONTROL,
3137 0x10, 0x00);
3138 snd_soc_update_bits(codec,
3139 WCD934X_CDC_CLK_RST_CTRL_MCLK_CONTROL,
3140 0x02, 0x00);
3141 snd_soc_update_bits(codec, WCD934X_CODEC_RPM_CLK_GATE,
3142 0x04, 0x04);
3143 snd_soc_update_bits(codec, WCD934X_CLK_SYS_MCLK2_PRG1,
3144 0x01, 0x00);
3145 snd_soc_update_bits(codec, WCD934X_CLK_SYS_MCLK2_PRG1,
3146 0x06, 0x00);
3147 snd_soc_update_bits(codec, WCD934X_CLK_SYS_PLL_ENABLES,
3148 0x01, 0x00);
3149 }
3150 break;
3151 }
3152
3153 dev_dbg(codec->dev, "%s: native_clk_users: %d, event: %d\n",
3154 __func__, tavil->native_clk_users, event);
3155
3156 return 0;
3157}
3158
3159static void tavil_codec_hphdelay_lutbypass(struct snd_soc_codec *codec,
3160 u16 interp_idx, int event)
3161{
3162 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
3163 u8 hph_dly_mask;
3164 u16 hph_lut_bypass_reg = 0;
3165 u16 hph_comp_ctrl7 = 0;
3166
3167
3168 switch (interp_idx) {
3169 case INTERP_HPHL:
3170 hph_dly_mask = 1;
3171 hph_lut_bypass_reg = WCD934X_CDC_TOP_HPHL_COMP_LUT;
3172 hph_comp_ctrl7 = WCD934X_CDC_COMPANDER1_CTL7;
3173 break;
3174 case INTERP_HPHR:
3175 hph_dly_mask = 2;
3176 hph_lut_bypass_reg = WCD934X_CDC_TOP_HPHR_COMP_LUT;
3177 hph_comp_ctrl7 = WCD934X_CDC_COMPANDER2_CTL7;
3178 break;
3179 default:
3180 break;
3181 }
3182
3183 if (hph_lut_bypass_reg && SND_SOC_DAPM_EVENT_ON(event)) {
3184 snd_soc_update_bits(codec, WCD934X_CDC_CLSH_TEST0,
3185 hph_dly_mask, 0x0);
3186 snd_soc_update_bits(codec, hph_lut_bypass_reg, 0x80, 0x80);
3187 if (tavil->hph_mode == CLS_H_ULP)
3188 snd_soc_update_bits(codec, hph_comp_ctrl7, 0x20, 0x20);
3189 }
3190
3191 if (hph_lut_bypass_reg && SND_SOC_DAPM_EVENT_OFF(event)) {
3192 snd_soc_update_bits(codec, WCD934X_CDC_CLSH_TEST0,
3193 hph_dly_mask, hph_dly_mask);
3194 snd_soc_update_bits(codec, hph_lut_bypass_reg, 0x80, 0x00);
3195 snd_soc_update_bits(codec, hph_comp_ctrl7, 0x20, 0x0);
3196 }
3197}
3198
3199static void tavil_codec_hd2_control(struct tavil_priv *priv,
3200 u16 interp_idx, int event)
3201{
3202 u16 hd2_scale_reg;
3203 u16 hd2_enable_reg = 0;
3204 struct snd_soc_codec *codec = priv->codec;
3205
3206 if (TAVIL_IS_1_1(priv->wcd9xxx))
3207 return;
3208
3209 switch (interp_idx) {
3210 case INTERP_HPHL:
3211 hd2_scale_reg = WCD934X_CDC_RX1_RX_PATH_SEC3;
3212 hd2_enable_reg = WCD934X_CDC_RX1_RX_PATH_CFG0;
3213 break;
3214 case INTERP_HPHR:
3215 hd2_scale_reg = WCD934X_CDC_RX2_RX_PATH_SEC3;
3216 hd2_enable_reg = WCD934X_CDC_RX2_RX_PATH_CFG0;
3217 break;
3218 }
3219
3220 if (hd2_enable_reg && SND_SOC_DAPM_EVENT_ON(event)) {
3221 snd_soc_update_bits(codec, hd2_scale_reg, 0x3C, 0x14);
3222 snd_soc_update_bits(codec, hd2_enable_reg, 0x04, 0x04);
3223 }
3224
3225 if (hd2_enable_reg && SND_SOC_DAPM_EVENT_OFF(event)) {
3226 snd_soc_update_bits(codec, hd2_enable_reg, 0x04, 0x00);
3227 snd_soc_update_bits(codec, hd2_scale_reg, 0x3C, 0x00);
3228 }
3229}
3230
3231static int tavil_codec_config_ear_spkr_gain(struct snd_soc_codec *codec,
3232 int event, int gain_reg)
3233{
3234 int comp_gain_offset, val;
3235 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
3236
3237 switch (tavil->swr.spkr_mode) {
3238 /* Compander gain in SPKR_MODE1 case is 12 dB */
3239 case WCD934X_SPKR_MODE_1:
3240 comp_gain_offset = -12;
3241 break;
3242 /* Default case compander gain is 15 dB */
3243 default:
3244 comp_gain_offset = -15;
3245 break;
3246 }
3247
3248 switch (event) {
3249 case SND_SOC_DAPM_POST_PMU:
3250 /* Apply ear spkr gain only if compander is enabled */
3251 if (tavil->comp_enabled[COMPANDER_7] &&
3252 (gain_reg == WCD934X_CDC_RX7_RX_VOL_CTL ||
3253 gain_reg == WCD934X_CDC_RX7_RX_VOL_MIX_CTL) &&
3254 (tavil->ear_spkr_gain != 0)) {
3255 /* For example, val is -8(-12+5-1) for 4dB of gain */
3256 val = comp_gain_offset + tavil->ear_spkr_gain - 1;
3257 snd_soc_write(codec, gain_reg, val);
3258
3259 dev_dbg(codec->dev, "%s: RX7 Volume %d dB\n",
3260 __func__, val);
3261 }
3262 break;
3263 case SND_SOC_DAPM_POST_PMD:
3264 /*
3265 * Reset RX7 volume to 0 dB if compander is enabled and
3266 * ear_spkr_gain is non-zero.
3267 */
3268 if (tavil->comp_enabled[COMPANDER_7] &&
3269 (gain_reg == WCD934X_CDC_RX7_RX_VOL_CTL ||
3270 gain_reg == WCD934X_CDC_RX7_RX_VOL_MIX_CTL) &&
3271 (tavil->ear_spkr_gain != 0)) {
3272 snd_soc_write(codec, gain_reg, 0x0);
3273
3274 dev_dbg(codec->dev, "%s: Reset RX7 Volume to 0 dB\n",
3275 __func__);
3276 }
3277 break;
3278 }
3279
3280 return 0;
3281}
3282
3283static int tavil_config_compander(struct snd_soc_codec *codec, int interp_n,
3284 int event)
3285{
3286 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
3287 int comp;
3288 u16 comp_ctl0_reg, rx_path_cfg0_reg;
3289
3290 /* EAR does not have compander */
3291 if (!interp_n)
3292 return 0;
3293
3294 comp = interp_n - 1;
3295 dev_dbg(codec->dev, "%s: event %d compander %d, enabled %d\n",
3296 __func__, event, comp + 1, tavil->comp_enabled[comp]);
3297
3298 if (!tavil->comp_enabled[comp])
3299 return 0;
3300
3301 comp_ctl0_reg = WCD934X_CDC_COMPANDER1_CTL0 + (comp * 8);
3302 rx_path_cfg0_reg = WCD934X_CDC_RX1_RX_PATH_CFG0 + (comp * 20);
3303
3304 if (SND_SOC_DAPM_EVENT_ON(event)) {
3305 /* Enable Compander Clock */
3306 snd_soc_update_bits(codec, comp_ctl0_reg, 0x01, 0x01);
3307 snd_soc_update_bits(codec, comp_ctl0_reg, 0x02, 0x02);
3308 snd_soc_update_bits(codec, comp_ctl0_reg, 0x02, 0x00);
3309 snd_soc_update_bits(codec, rx_path_cfg0_reg, 0x02, 0x02);
3310 }
3311
3312 if (SND_SOC_DAPM_EVENT_OFF(event)) {
3313 snd_soc_update_bits(codec, rx_path_cfg0_reg, 0x02, 0x00);
3314 snd_soc_update_bits(codec, comp_ctl0_reg, 0x04, 0x04);
3315 snd_soc_update_bits(codec, comp_ctl0_reg, 0x02, 0x02);
3316 snd_soc_update_bits(codec, comp_ctl0_reg, 0x02, 0x00);
3317 snd_soc_update_bits(codec, comp_ctl0_reg, 0x01, 0x00);
3318 snd_soc_update_bits(codec, comp_ctl0_reg, 0x04, 0x00);
3319 }
3320
3321 return 0;
3322}
3323
3324static void tavil_codec_idle_detect_control(struct snd_soc_codec *codec,
3325 int interp, int event)
3326{
3327 int reg = 0, mask, val;
3328 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
3329
3330 if (!tavil->idle_det_cfg.hph_idle_detect_en)
3331 return;
3332
3333 if (interp == INTERP_HPHL) {
3334 reg = WCD934X_CDC_RX_IDLE_DET_PATH_CTL;
3335 mask = 0x01;
3336 val = 0x01;
3337 }
3338 if (interp == INTERP_HPHR) {
3339 reg = WCD934X_CDC_RX_IDLE_DET_PATH_CTL;
3340 mask = 0x02;
3341 val = 0x02;
3342 }
3343
3344 if (reg && SND_SOC_DAPM_EVENT_ON(event))
3345 snd_soc_update_bits(codec, reg, mask, val);
3346
3347 if (reg && SND_SOC_DAPM_EVENT_OFF(event)) {
3348 snd_soc_update_bits(codec, reg, mask, 0x00);
3349 tavil->idle_det_cfg.hph_idle_thr = 0;
3350 snd_soc_write(codec, WCD934X_CDC_RX_IDLE_DET_CFG3, 0x0);
3351 }
3352}
3353
3354/**
3355 * tavil_codec_enable_interp_clk - Enable main path Interpolator
3356 * clock.
3357 *
3358 * @codec: Codec instance
3359 * @event: Indicates speaker path gain offset value
3360 * @intp_idx: Interpolator index
3361 * Returns number of main clock users
3362 */
3363int tavil_codec_enable_interp_clk(struct snd_soc_codec *codec,
3364 int event, int interp_idx)
3365{
3366 struct tavil_priv *tavil;
3367 u16 main_reg;
3368
3369 if (!codec) {
3370 pr_err("%s: codec is NULL\n", __func__);
3371 return -EINVAL;
3372 }
3373
3374 tavil = snd_soc_codec_get_drvdata(codec);
3375 main_reg = WCD934X_CDC_RX0_RX_PATH_CTL + (interp_idx * 20);
3376
3377 if (SND_SOC_DAPM_EVENT_ON(event)) {
3378 if (tavil->main_clk_users[interp_idx] == 0) {
3379 /* Main path PGA mute enable */
3380 snd_soc_update_bits(codec, main_reg, 0x10, 0x10);
3381 /* Clk enable */
3382 snd_soc_update_bits(codec, main_reg, 0x20, 0x20);
3383 tavil_codec_idle_detect_control(codec, interp_idx,
3384 event);
3385 tavil_codec_hd2_control(tavil, interp_idx, event);
3386 tavil_codec_hphdelay_lutbypass(codec, interp_idx,
3387 event);
3388 tavil_config_compander(codec, interp_idx, event);
3389 }
3390 tavil->main_clk_users[interp_idx]++;
3391 }
3392
3393 if (SND_SOC_DAPM_EVENT_OFF(event)) {
3394 tavil->main_clk_users[interp_idx]--;
3395 if (tavil->main_clk_users[interp_idx] <= 0) {
3396 tavil->main_clk_users[interp_idx] = 0;
3397 tavil_config_compander(codec, interp_idx, event);
3398 tavil_codec_hphdelay_lutbypass(codec, interp_idx,
3399 event);
3400 tavil_codec_hd2_control(tavil, interp_idx, event);
3401 tavil_codec_idle_detect_control(codec, interp_idx,
3402 event);
3403 /* Clk Disable */
3404 snd_soc_update_bits(codec, main_reg, 0x20, 0x00);
3405 /* Reset enable and disable */
3406 snd_soc_update_bits(codec, main_reg, 0x40, 0x40);
3407 snd_soc_update_bits(codec, main_reg, 0x40, 0x00);
3408 /* Reset rate to 48K*/
3409 snd_soc_update_bits(codec, main_reg, 0x0F, 0x04);
3410 }
3411 }
3412
3413 dev_dbg(codec->dev, "%s event %d main_clk_users %d\n",
3414 __func__, event, tavil->main_clk_users[interp_idx]);
3415
3416 return tavil->main_clk_users[interp_idx];
3417}
3418EXPORT_SYMBOL(tavil_codec_enable_interp_clk);
3419
Meng Wangf45a20d2017-01-18 09:51:58 +08003420static int tavil_anc_out_switch_cb(struct snd_soc_dapm_widget *w,
3421 struct snd_kcontrol *kcontrol, int event)
3422{
3423 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
3424
3425 tavil_codec_enable_interp_clk(codec, event, w->shift);
3426
3427 return 0;
3428}
Banajit Goswamide8271c2017-01-18 00:28:59 -08003429static int tavil_codec_set_idle_detect_thr(struct snd_soc_codec *codec,
3430 int interp, int path_type)
3431{
3432 int port_id[4] = { 0, 0, 0, 0 };
3433 int *port_ptr, num_ports;
3434 int bit_width = 0, i;
3435 int mux_reg, mux_reg_val;
3436 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
3437 int dai_id, idle_thr;
3438
3439 if ((interp != INTERP_HPHL) && (interp != INTERP_HPHR))
3440 return 0;
3441
3442 if (!tavil->idle_det_cfg.hph_idle_detect_en)
3443 return 0;
3444
3445 port_ptr = &port_id[0];
3446 num_ports = 0;
3447
3448 /*
3449 * Read interpolator MUX input registers and find
3450 * which slimbus port is connected and store the port
3451 * numbers in port_id array.
3452 */
3453 if (path_type == INTERP_MIX_PATH) {
3454 mux_reg = WCD934X_CDC_RX_INP_MUX_RX_INT1_CFG1 +
3455 2 * (interp - 1);
3456 mux_reg_val = snd_soc_read(codec, mux_reg) & 0x0f;
3457
3458 if ((mux_reg_val >= INTn_2_INP_SEL_RX0) &&
3459 (mux_reg_val < INTn_2_INP_SEL_PROXIMITY)) {
3460 *port_ptr++ = mux_reg_val +
3461 WCD934X_RX_PORT_START_NUMBER - 1;
3462 num_ports++;
3463 }
3464 }
3465
3466 if (path_type == INTERP_MAIN_PATH) {
3467 mux_reg = WCD934X_CDC_RX_INP_MUX_RX_INT1_CFG0 +
3468 2 * (interp - 1);
3469 mux_reg_val = snd_soc_read(codec, mux_reg) & 0x0f;
3470 i = WCD934X_INTERP_MUX_NUM_INPUTS;
3471
3472 while (i) {
3473 if ((mux_reg_val >= INTn_1_INP_SEL_RX0) &&
3474 (mux_reg_val <= INTn_1_INP_SEL_RX7)) {
3475 *port_ptr++ = mux_reg_val +
3476 WCD934X_RX_PORT_START_NUMBER -
3477 INTn_1_INP_SEL_RX0;
3478 num_ports++;
3479 }
3480 mux_reg_val = (snd_soc_read(codec, mux_reg) &
3481 0xf0) >> 4;
3482 mux_reg += 1;
3483 i--;
3484 }
3485 }
3486
3487 dev_dbg(codec->dev, "%s: num_ports: %d, ports[%d %d %d %d]\n",
3488 __func__, num_ports, port_id[0], port_id[1],
3489 port_id[2], port_id[3]);
3490
3491 i = 0;
3492 while (num_ports) {
3493 dai_id = tavil_find_playback_dai_id_for_port(port_id[i++],
3494 tavil);
3495
3496 if ((dai_id >= 0) && (dai_id < NUM_CODEC_DAIS)) {
3497 dev_dbg(codec->dev, "%s: dai_id: %d bit_width: %d\n",
3498 __func__, dai_id,
3499 tavil->dai[dai_id].bit_width);
3500
3501 if (tavil->dai[dai_id].bit_width > bit_width)
3502 bit_width = tavil->dai[dai_id].bit_width;
3503 }
3504
3505 num_ports--;
3506 }
3507
3508 switch (bit_width) {
3509 case 16:
3510 idle_thr = 0xff; /* F16 */
3511 break;
3512 case 24:
3513 case 32:
3514 idle_thr = 0x03; /* F22 */
3515 break;
3516 default:
3517 idle_thr = 0x00;
3518 break;
3519 }
3520
3521 dev_dbg(codec->dev, "%s: (new) idle_thr: %d, (cur) idle_thr: %d\n",
3522 __func__, idle_thr, tavil->idle_det_cfg.hph_idle_thr);
3523
3524 if ((tavil->idle_det_cfg.hph_idle_thr == 0) ||
3525 (idle_thr < tavil->idle_det_cfg.hph_idle_thr)) {
3526 snd_soc_write(codec, WCD934X_CDC_RX_IDLE_DET_CFG3, idle_thr);
3527 tavil->idle_det_cfg.hph_idle_thr = idle_thr;
3528 }
3529
3530 return 0;
3531}
3532
3533static int tavil_codec_enable_mix_path(struct snd_soc_dapm_widget *w,
3534 struct snd_kcontrol *kcontrol,
3535 int event)
3536{
3537 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
3538 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
3539 u16 gain_reg, mix_reg;
3540 int offset_val = 0;
3541 int val = 0;
3542
3543 if (w->shift >= WCD934X_NUM_INTERPOLATORS ||
3544 w->shift == INTERP_LO3_NA || w->shift == INTERP_LO4_NA) {
3545 dev_err(codec->dev, "%s: Invalid Interpolator value %d for name %s\n",
3546 __func__, w->shift, w->name);
3547 return -EINVAL;
3548 };
3549
3550 gain_reg = WCD934X_CDC_RX0_RX_VOL_MIX_CTL +
3551 (w->shift * WCD934X_RX_PATH_CTL_OFFSET);
3552 mix_reg = WCD934X_CDC_RX0_RX_PATH_MIX_CTL +
3553 (w->shift * WCD934X_RX_PATH_CTL_OFFSET);
3554
3555 if (w->shift == INTERP_SPKR1 || w->shift == INTERP_SPKR2)
3556 __tavil_codec_enable_swr(w, event);
3557
3558 switch (event) {
3559 case SND_SOC_DAPM_PRE_PMU:
3560 tavil_codec_set_idle_detect_thr(codec, w->shift,
3561 INTERP_MIX_PATH);
3562 tavil_codec_enable_interp_clk(codec, event, w->shift);
3563 /* Clk enable */
3564 snd_soc_update_bits(codec, mix_reg, 0x20, 0x20);
3565 break;
3566 case SND_SOC_DAPM_POST_PMU:
3567 if ((tavil->swr.spkr_gain_offset ==
3568 WCD934X_RX_GAIN_OFFSET_M1P5_DB) &&
3569 (tavil->comp_enabled[COMPANDER_7] ||
3570 tavil->comp_enabled[COMPANDER_8]) &&
3571 (gain_reg == WCD934X_CDC_RX7_RX_VOL_MIX_CTL ||
3572 gain_reg == WCD934X_CDC_RX8_RX_VOL_MIX_CTL)) {
3573 snd_soc_update_bits(codec, WCD934X_CDC_RX7_RX_PATH_SEC1,
3574 0x01, 0x01);
3575 snd_soc_update_bits(codec,
3576 WCD934X_CDC_RX7_RX_PATH_MIX_SEC0,
3577 0x01, 0x01);
3578 snd_soc_update_bits(codec, WCD934X_CDC_RX8_RX_PATH_SEC1,
3579 0x01, 0x01);
3580 snd_soc_update_bits(codec,
3581 WCD934X_CDC_RX8_RX_PATH_MIX_SEC0,
3582 0x01, 0x01);
3583 offset_val = -2;
3584 }
3585 val = snd_soc_read(codec, gain_reg);
3586 val += offset_val;
3587 snd_soc_write(codec, gain_reg, val);
3588 tavil_codec_config_ear_spkr_gain(codec, event, gain_reg);
3589 break;
3590 case SND_SOC_DAPM_POST_PMD:
3591 /* Clk Disable */
3592 snd_soc_update_bits(codec, mix_reg, 0x20, 0x00);
3593 tavil_codec_enable_interp_clk(codec, event, w->shift);
3594 /* Reset enable and disable */
3595 snd_soc_update_bits(codec, mix_reg, 0x40, 0x40);
3596 snd_soc_update_bits(codec, mix_reg, 0x40, 0x00);
3597
3598 if ((tavil->swr.spkr_gain_offset ==
3599 WCD934X_RX_GAIN_OFFSET_M1P5_DB) &&
3600 (tavil->comp_enabled[COMPANDER_7] ||
3601 tavil->comp_enabled[COMPANDER_8]) &&
3602 (gain_reg == WCD934X_CDC_RX7_RX_VOL_MIX_CTL ||
3603 gain_reg == WCD934X_CDC_RX8_RX_VOL_MIX_CTL)) {
3604 snd_soc_update_bits(codec, WCD934X_CDC_RX7_RX_PATH_SEC1,
3605 0x01, 0x00);
3606 snd_soc_update_bits(codec,
3607 WCD934X_CDC_RX7_RX_PATH_MIX_SEC0,
3608 0x01, 0x00);
3609 snd_soc_update_bits(codec, WCD934X_CDC_RX8_RX_PATH_SEC1,
3610 0x01, 0x00);
3611 snd_soc_update_bits(codec,
3612 WCD934X_CDC_RX8_RX_PATH_MIX_SEC0,
3613 0x01, 0x00);
3614 offset_val = 2;
3615 val = snd_soc_read(codec, gain_reg);
3616 val += offset_val;
3617 snd_soc_write(codec, gain_reg, val);
3618 }
3619 tavil_codec_config_ear_spkr_gain(codec, event, gain_reg);
3620 break;
3621 };
3622 dev_dbg(codec->dev, "%s event %d name %s\n", __func__, event, w->name);
3623
3624 return 0;
3625}
3626
3627/**
3628 * tavil_get_dsd_config - Get pointer to dsd config structure
3629 *
3630 * @codec: pointer to snd_soc_codec structure
3631 *
3632 * Returns pointer to tavil_dsd_config structure
3633 */
3634struct tavil_dsd_config *tavil_get_dsd_config(struct snd_soc_codec *codec)
3635{
3636 struct tavil_priv *tavil;
3637
3638 if (!codec)
3639 return NULL;
3640
3641 tavil = snd_soc_codec_get_drvdata(codec);
3642
3643 if (!tavil)
3644 return NULL;
3645
3646 return tavil->dsd_config;
3647}
3648EXPORT_SYMBOL(tavil_get_dsd_config);
3649
3650static int tavil_codec_enable_main_path(struct snd_soc_dapm_widget *w,
3651 struct snd_kcontrol *kcontrol,
3652 int event)
3653{
3654 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
3655 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
3656 u16 gain_reg;
3657 u16 reg;
3658 int val;
3659 int offset_val = 0;
3660
3661 dev_dbg(codec->dev, "%s %d %s\n", __func__, event, w->name);
3662
3663 if (w->shift >= WCD934X_NUM_INTERPOLATORS ||
3664 w->shift == INTERP_LO3_NA || w->shift == INTERP_LO4_NA) {
3665 dev_err(codec->dev, "%s: Invalid Interpolator value %d for name %s\n",
3666 __func__, w->shift, w->name);
3667 return -EINVAL;
3668 };
3669
3670 reg = WCD934X_CDC_RX0_RX_PATH_CTL + (w->shift *
3671 WCD934X_RX_PATH_CTL_OFFSET);
3672 gain_reg = WCD934X_CDC_RX0_RX_VOL_CTL + (w->shift *
3673 WCD934X_RX_PATH_CTL_OFFSET);
3674
3675 switch (event) {
3676 case SND_SOC_DAPM_PRE_PMU:
3677 tavil_codec_set_idle_detect_thr(codec, w->shift,
3678 INTERP_MAIN_PATH);
3679 tavil_codec_enable_interp_clk(codec, event, w->shift);
3680 break;
3681 case SND_SOC_DAPM_POST_PMU:
3682 /* apply gain after int clk is enabled */
3683 if ((tavil->swr.spkr_gain_offset ==
3684 WCD934X_RX_GAIN_OFFSET_M1P5_DB) &&
3685 (tavil->comp_enabled[COMPANDER_7] ||
3686 tavil->comp_enabled[COMPANDER_8]) &&
3687 (gain_reg == WCD934X_CDC_RX7_RX_VOL_CTL ||
3688 gain_reg == WCD934X_CDC_RX8_RX_VOL_CTL)) {
3689 snd_soc_update_bits(codec, WCD934X_CDC_RX7_RX_PATH_SEC1,
3690 0x01, 0x01);
3691 snd_soc_update_bits(codec,
3692 WCD934X_CDC_RX7_RX_PATH_MIX_SEC0,
3693 0x01, 0x01);
3694 snd_soc_update_bits(codec, WCD934X_CDC_RX8_RX_PATH_SEC1,
3695 0x01, 0x01);
3696 snd_soc_update_bits(codec,
3697 WCD934X_CDC_RX8_RX_PATH_MIX_SEC0,
3698 0x01, 0x01);
3699 offset_val = -2;
3700 }
3701 val = snd_soc_read(codec, gain_reg);
3702 val += offset_val;
3703 snd_soc_write(codec, gain_reg, val);
3704 tavil_codec_config_ear_spkr_gain(codec, event, gain_reg);
3705 break;
3706 case SND_SOC_DAPM_POST_PMD:
3707 tavil_codec_enable_interp_clk(codec, event, w->shift);
3708
3709 if ((tavil->swr.spkr_gain_offset ==
3710 WCD934X_RX_GAIN_OFFSET_M1P5_DB) &&
3711 (tavil->comp_enabled[COMPANDER_7] ||
3712 tavil->comp_enabled[COMPANDER_8]) &&
3713 (gain_reg == WCD934X_CDC_RX7_RX_VOL_CTL ||
3714 gain_reg == WCD934X_CDC_RX8_RX_VOL_CTL)) {
3715 snd_soc_update_bits(codec, WCD934X_CDC_RX7_RX_PATH_SEC1,
3716 0x01, 0x00);
3717 snd_soc_update_bits(codec,
3718 WCD934X_CDC_RX7_RX_PATH_MIX_SEC0,
3719 0x01, 0x00);
3720 snd_soc_update_bits(codec, WCD934X_CDC_RX8_RX_PATH_SEC1,
3721 0x01, 0x00);
3722 snd_soc_update_bits(codec,
3723 WCD934X_CDC_RX8_RX_PATH_MIX_SEC0,
3724 0x01, 0x00);
3725 offset_val = 2;
3726 val = snd_soc_read(codec, gain_reg);
3727 val += offset_val;
3728 snd_soc_write(codec, gain_reg, val);
3729 }
3730 tavil_codec_config_ear_spkr_gain(codec, event, gain_reg);
3731 break;
3732 };
3733
3734 return 0;
3735}
3736
3737static int tavil_codec_set_iir_gain(struct snd_soc_dapm_widget *w,
3738 struct snd_kcontrol *kcontrol, int event)
3739{
3740 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
3741
3742 dev_dbg(codec->dev, "%s: event = %d\n", __func__, event);
3743
3744 switch (event) {
3745 case SND_SOC_DAPM_POST_PMU: /* fall through */
3746 case SND_SOC_DAPM_PRE_PMD:
3747 if (strnstr(w->name, "IIR0", sizeof("IIR0"))) {
3748 snd_soc_write(codec,
3749 WCD934X_CDC_SIDETONE_IIR0_IIR_GAIN_B1_CTL,
3750 snd_soc_read(codec,
3751 WCD934X_CDC_SIDETONE_IIR0_IIR_GAIN_B1_CTL));
3752 snd_soc_write(codec,
3753 WCD934X_CDC_SIDETONE_IIR0_IIR_GAIN_B2_CTL,
3754 snd_soc_read(codec,
3755 WCD934X_CDC_SIDETONE_IIR0_IIR_GAIN_B2_CTL));
3756 snd_soc_write(codec,
3757 WCD934X_CDC_SIDETONE_IIR0_IIR_GAIN_B3_CTL,
3758 snd_soc_read(codec,
3759 WCD934X_CDC_SIDETONE_IIR0_IIR_GAIN_B3_CTL));
3760 snd_soc_write(codec,
3761 WCD934X_CDC_SIDETONE_IIR0_IIR_GAIN_B4_CTL,
3762 snd_soc_read(codec,
3763 WCD934X_CDC_SIDETONE_IIR0_IIR_GAIN_B4_CTL));
3764 } else {
3765 snd_soc_write(codec,
3766 WCD934X_CDC_SIDETONE_IIR1_IIR_GAIN_B1_CTL,
3767 snd_soc_read(codec,
3768 WCD934X_CDC_SIDETONE_IIR1_IIR_GAIN_B1_CTL));
3769 snd_soc_write(codec,
3770 WCD934X_CDC_SIDETONE_IIR1_IIR_GAIN_B2_CTL,
3771 snd_soc_read(codec,
3772 WCD934X_CDC_SIDETONE_IIR1_IIR_GAIN_B2_CTL));
3773 snd_soc_write(codec,
3774 WCD934X_CDC_SIDETONE_IIR1_IIR_GAIN_B3_CTL,
3775 snd_soc_read(codec,
3776 WCD934X_CDC_SIDETONE_IIR1_IIR_GAIN_B3_CTL));
3777 }
3778 break;
3779 }
3780 return 0;
3781}
3782
3783static int tavil_codec_find_amic_input(struct snd_soc_codec *codec,
3784 int adc_mux_n)
3785{
3786 u16 mask, shift, adc_mux_in_reg;
3787 u16 amic_mux_sel_reg;
3788 bool is_amic;
3789
3790 if (adc_mux_n < 0 || adc_mux_n > WCD934X_MAX_VALID_ADC_MUX ||
3791 adc_mux_n == WCD934X_INVALID_ADC_MUX)
3792 return 0;
3793
3794 if (adc_mux_n < 3) {
3795 adc_mux_in_reg = WCD934X_CDC_TX_INP_MUX_ADC_MUX0_CFG1 +
3796 adc_mux_n;
3797 mask = 0x03;
3798 shift = 0;
3799 amic_mux_sel_reg = WCD934X_CDC_TX_INP_MUX_ADC_MUX0_CFG0 +
3800 2 * adc_mux_n;
3801 } else if (adc_mux_n < 4) {
3802 adc_mux_in_reg = WCD934X_CDC_TX_INP_MUX_ADC_MUX3_CFG1;
3803 mask = 0x03;
3804 shift = 0;
3805 amic_mux_sel_reg = WCD934X_CDC_TX_INP_MUX_ADC_MUX0_CFG0 +
3806 2 * adc_mux_n;
3807 } else if (adc_mux_n < 7) {
3808 adc_mux_in_reg = WCD934X_CDC_TX_INP_MUX_ADC_MUX0_CFG1 +
3809 (adc_mux_n - 4);
3810 mask = 0x0C;
3811 shift = 2;
3812 amic_mux_sel_reg = WCD934X_CDC_TX_INP_MUX_ADC_MUX4_CFG0 +
3813 adc_mux_n - 4;
3814 } else if (adc_mux_n < 8) {
3815 adc_mux_in_reg = WCD934X_CDC_TX_INP_MUX_ADC_MUX3_CFG1;
3816 mask = 0x0C;
3817 shift = 2;
3818 amic_mux_sel_reg = WCD934X_CDC_TX_INP_MUX_ADC_MUX4_CFG0 +
3819 adc_mux_n - 4;
3820 } else if (adc_mux_n < 12) {
3821 adc_mux_in_reg = WCD934X_CDC_TX_INP_MUX_ADC_MUX0_CFG1 +
3822 ((adc_mux_n == 8) ? (adc_mux_n - 8) :
3823 (adc_mux_n - 9));
3824 mask = 0x30;
3825 shift = 4;
3826 amic_mux_sel_reg = WCD934X_CDC_TX_INP_MUX_ADC_MUX4_CFG0 +
3827 adc_mux_n - 4;
3828 } else if (adc_mux_n < 13) {
3829 adc_mux_in_reg = WCD934X_CDC_TX_INP_MUX_ADC_MUX3_CFG1;
3830 mask = 0x30;
3831 shift = 4;
3832 amic_mux_sel_reg = WCD934X_CDC_TX_INP_MUX_ADC_MUX4_CFG0 +
3833 adc_mux_n - 4;
3834 } else {
3835 adc_mux_in_reg = WCD934X_CDC_TX_INP_MUX_ADC_MUX0_CFG1;
3836 mask = 0xC0;
3837 shift = 6;
3838 amic_mux_sel_reg = WCD934X_CDC_TX_INP_MUX_ADC_MUX4_CFG0 +
3839 adc_mux_n - 4;
3840 }
3841
3842 is_amic = (((snd_soc_read(codec, adc_mux_in_reg) & mask) >> shift)
3843 == 1);
3844 if (!is_amic)
3845 return 0;
3846
3847 return snd_soc_read(codec, amic_mux_sel_reg) & 0x07;
3848}
3849
3850static void tavil_codec_set_tx_hold(struct snd_soc_codec *codec,
3851 u16 amic_reg, bool set)
3852{
3853 u8 mask = 0x20;
3854 u8 val;
3855
3856 if (amic_reg == WCD934X_ANA_AMIC1 ||
3857 amic_reg == WCD934X_ANA_AMIC3)
3858 mask = 0x40;
3859
3860 val = set ? mask : 0x00;
3861
3862 switch (amic_reg) {
3863 case WCD934X_ANA_AMIC1:
3864 case WCD934X_ANA_AMIC2:
3865 snd_soc_update_bits(codec, WCD934X_ANA_AMIC2, mask, val);
3866 break;
3867 case WCD934X_ANA_AMIC3:
3868 case WCD934X_ANA_AMIC4:
3869 snd_soc_update_bits(codec, WCD934X_ANA_AMIC4, mask, val);
3870 break;
3871 default:
3872 dev_dbg(codec->dev, "%s: invalid amic: %d\n",
3873 __func__, amic_reg);
3874 break;
3875 }
3876}
3877
3878static int tavil_codec_tx_adc_cfg(struct snd_soc_dapm_widget *w,
3879 struct snd_kcontrol *kcontrol, int event)
3880{
3881 int adc_mux_n = w->shift;
3882 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
Meng Wangf45a20d2017-01-18 09:51:58 +08003883 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
Banajit Goswamide8271c2017-01-18 00:28:59 -08003884 int amic_n;
Banajit Goswamide8271c2017-01-18 00:28:59 -08003885
3886 dev_dbg(codec->dev, "%s: event: %d\n", __func__, event);
3887
3888 switch (event) {
3889 case SND_SOC_DAPM_POST_PMU:
3890 amic_n = tavil_codec_find_amic_input(codec, adc_mux_n);
3891 if (amic_n) {
Meng Wangf45a20d2017-01-18 09:51:58 +08003892 /*
3893 * Prevent ANC Rx pop by leaving Tx FE in HOLD
3894 * state until PA is up. Track AMIC being used
3895 * so we can release the HOLD later.
3896 */
3897 set_bit(ANC_MIC_AMIC1 + amic_n - 1,
3898 &tavil->status_mask);
Banajit Goswamide8271c2017-01-18 00:28:59 -08003899 }
3900 break;
3901 default:
3902 break;
3903 }
3904
3905 return 0;
3906}
3907
3908static u16 tavil_codec_get_amic_pwlvl_reg(struct snd_soc_codec *codec, int amic)
3909{
3910 u16 pwr_level_reg = 0;
3911
3912 switch (amic) {
3913 case 1:
3914 case 2:
3915 pwr_level_reg = WCD934X_ANA_AMIC1;
3916 break;
3917
3918 case 3:
3919 case 4:
3920 pwr_level_reg = WCD934X_ANA_AMIC3;
3921 break;
3922 default:
3923 dev_dbg(codec->dev, "%s: invalid amic: %d\n",
3924 __func__, amic);
3925 break;
3926 }
3927
3928 return pwr_level_reg;
3929}
3930
3931#define TX_HPF_CUT_OFF_FREQ_MASK 0x60
3932#define CF_MIN_3DB_4HZ 0x0
3933#define CF_MIN_3DB_75HZ 0x1
3934#define CF_MIN_3DB_150HZ 0x2
3935
3936static void tavil_tx_hpf_corner_freq_callback(struct work_struct *work)
3937{
3938 struct delayed_work *hpf_delayed_work;
3939 struct hpf_work *hpf_work;
3940 struct tavil_priv *tavil;
3941 struct snd_soc_codec *codec;
3942 u16 dec_cfg_reg, amic_reg, go_bit_reg;
3943 u8 hpf_cut_off_freq;
3944 int amic_n;
3945
3946 hpf_delayed_work = to_delayed_work(work);
3947 hpf_work = container_of(hpf_delayed_work, struct hpf_work, dwork);
3948 tavil = hpf_work->tavil;
3949 codec = tavil->codec;
3950 hpf_cut_off_freq = hpf_work->hpf_cut_off_freq;
3951
3952 dec_cfg_reg = WCD934X_CDC_TX0_TX_PATH_CFG0 + 16 * hpf_work->decimator;
3953 go_bit_reg = dec_cfg_reg + 7;
3954
3955 dev_dbg(codec->dev, "%s: decimator %u hpf_cut_of_freq 0x%x\n",
3956 __func__, hpf_work->decimator, hpf_cut_off_freq);
3957
3958 amic_n = tavil_codec_find_amic_input(codec, hpf_work->decimator);
3959 if (amic_n) {
3960 amic_reg = WCD934X_ANA_AMIC1 + amic_n - 1;
3961 tavil_codec_set_tx_hold(codec, amic_reg, false);
3962 }
3963 snd_soc_update_bits(codec, dec_cfg_reg, TX_HPF_CUT_OFF_FREQ_MASK,
3964 hpf_cut_off_freq << 5);
3965 snd_soc_update_bits(codec, go_bit_reg, 0x02, 0x02);
3966 /* Minimum 1 clk cycle delay is required as per HW spec */
3967 usleep_range(1000, 1010);
3968 snd_soc_update_bits(codec, go_bit_reg, 0x02, 0x00);
3969}
3970
3971static void tavil_tx_mute_update_callback(struct work_struct *work)
3972{
3973 struct tx_mute_work *tx_mute_dwork;
3974 struct tavil_priv *tavil;
3975 struct delayed_work *delayed_work;
3976 struct snd_soc_codec *codec;
3977 u16 tx_vol_ctl_reg, hpf_gate_reg;
3978
3979 delayed_work = to_delayed_work(work);
3980 tx_mute_dwork = container_of(delayed_work, struct tx_mute_work, dwork);
3981 tavil = tx_mute_dwork->tavil;
3982 codec = tavil->codec;
3983
3984 tx_vol_ctl_reg = WCD934X_CDC_TX0_TX_PATH_CTL +
3985 16 * tx_mute_dwork->decimator;
3986 hpf_gate_reg = WCD934X_CDC_TX0_TX_PATH_SEC2 +
3987 16 * tx_mute_dwork->decimator;
3988 snd_soc_update_bits(codec, tx_vol_ctl_reg, 0x10, 0x00);
3989}
3990
3991static int tavil_codec_enable_rx_path_clk(struct snd_soc_dapm_widget *w,
3992 struct snd_kcontrol *kcontrol, int event)
3993{
3994 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
3995 u16 sidetone_reg;
3996
3997 dev_dbg(codec->dev, "%s %d %d\n", __func__, event, w->shift);
3998 sidetone_reg = WCD934X_CDC_RX0_RX_PATH_CFG1 + 0x14*(w->shift);
3999
4000 switch (event) {
4001 case SND_SOC_DAPM_PRE_PMU:
4002 if (!strcmp(w->name, "RX INT7 MIX2 INP"))
4003 __tavil_codec_enable_swr(w, event);
4004 tavil_codec_enable_interp_clk(codec, event, w->shift);
4005 snd_soc_update_bits(codec, sidetone_reg, 0x10, 0x10);
4006 break;
4007 case SND_SOC_DAPM_POST_PMD:
4008 snd_soc_update_bits(codec, sidetone_reg, 0x10, 0x00);
4009 tavil_codec_enable_interp_clk(codec, event, w->shift);
4010 if (!strcmp(w->name, "RX INT7 MIX2 INP"))
4011 __tavil_codec_enable_swr(w, event);
4012 break;
4013 default:
4014 break;
4015 };
4016 return 0;
4017}
4018
4019static int tavil_codec_enable_dec(struct snd_soc_dapm_widget *w,
4020 struct snd_kcontrol *kcontrol, int event)
4021{
4022 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
4023 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
4024 unsigned int decimator;
4025 char *dec_adc_mux_name = NULL;
4026 char *widget_name = NULL;
4027 char *wname;
4028 int ret = 0, amic_n;
4029 u16 tx_vol_ctl_reg, pwr_level_reg = 0, dec_cfg_reg, hpf_gate_reg;
4030 u16 tx_gain_ctl_reg;
4031 char *dec;
4032 u8 hpf_cut_off_freq;
4033
4034 dev_dbg(codec->dev, "%s %d\n", __func__, event);
4035
4036 widget_name = kstrndup(w->name, 15, GFP_KERNEL);
4037 if (!widget_name)
4038 return -ENOMEM;
4039
4040 wname = widget_name;
4041 dec_adc_mux_name = strsep(&widget_name, " ");
4042 if (!dec_adc_mux_name) {
4043 dev_err(codec->dev, "%s: Invalid decimator = %s\n",
4044 __func__, w->name);
4045 ret = -EINVAL;
4046 goto out;
4047 }
4048 dec_adc_mux_name = widget_name;
4049
4050 dec = strpbrk(dec_adc_mux_name, "012345678");
4051 if (!dec) {
4052 dev_err(codec->dev, "%s: decimator index not found\n",
4053 __func__);
4054 ret = -EINVAL;
4055 goto out;
4056 }
4057
4058 ret = kstrtouint(dec, 10, &decimator);
4059 if (ret < 0) {
4060 dev_err(codec->dev, "%s: Invalid decimator = %s\n",
4061 __func__, wname);
4062 ret = -EINVAL;
4063 goto out;
4064 }
4065
4066 dev_dbg(codec->dev, "%s(): widget = %s decimator = %u\n", __func__,
4067 w->name, decimator);
4068
4069 tx_vol_ctl_reg = WCD934X_CDC_TX0_TX_PATH_CTL + 16 * decimator;
4070 hpf_gate_reg = WCD934X_CDC_TX0_TX_PATH_SEC2 + 16 * decimator;
4071 dec_cfg_reg = WCD934X_CDC_TX0_TX_PATH_CFG0 + 16 * decimator;
4072 tx_gain_ctl_reg = WCD934X_CDC_TX0_TX_VOL_CTL + 16 * decimator;
4073
4074 switch (event) {
4075 case SND_SOC_DAPM_PRE_PMU:
4076 amic_n = tavil_codec_find_amic_input(codec, decimator);
4077 if (amic_n)
4078 pwr_level_reg = tavil_codec_get_amic_pwlvl_reg(codec,
4079 amic_n);
4080
4081 if (pwr_level_reg) {
4082 switch ((snd_soc_read(codec, pwr_level_reg) &
4083 WCD934X_AMIC_PWR_LVL_MASK) >>
4084 WCD934X_AMIC_PWR_LVL_SHIFT) {
4085 case WCD934X_AMIC_PWR_LEVEL_LP:
4086 snd_soc_update_bits(codec, dec_cfg_reg,
4087 WCD934X_DEC_PWR_LVL_MASK,
4088 WCD934X_DEC_PWR_LVL_LP);
4089 break;
4090
4091 case WCD934X_AMIC_PWR_LEVEL_HP:
4092 snd_soc_update_bits(codec, dec_cfg_reg,
4093 WCD934X_DEC_PWR_LVL_MASK,
4094 WCD934X_DEC_PWR_LVL_HP);
4095 break;
4096 case WCD934X_AMIC_PWR_LEVEL_DEFAULT:
4097 default:
4098 snd_soc_update_bits(codec, dec_cfg_reg,
4099 WCD934X_DEC_PWR_LVL_MASK,
4100 WCD934X_DEC_PWR_LVL_DF);
4101 break;
4102 }
4103 }
4104 /* Enable TX PGA Mute */
4105 snd_soc_update_bits(codec, tx_vol_ctl_reg, 0x10, 0x10);
4106 break;
4107 case SND_SOC_DAPM_POST_PMU:
4108 hpf_cut_off_freq = (snd_soc_read(codec, dec_cfg_reg) &
4109 TX_HPF_CUT_OFF_FREQ_MASK) >> 5;
4110
4111 tavil->tx_hpf_work[decimator].hpf_cut_off_freq =
4112 hpf_cut_off_freq;
4113 if (hpf_cut_off_freq != CF_MIN_3DB_150HZ) {
4114 snd_soc_update_bits(codec, dec_cfg_reg,
4115 TX_HPF_CUT_OFF_FREQ_MASK,
4116 CF_MIN_3DB_150HZ << 5);
4117 snd_soc_update_bits(codec, hpf_gate_reg, 0x02, 0x02);
4118 /*
4119 * Minimum 1 clk cycle delay is required as per
4120 * HW spec.
4121 */
4122 usleep_range(1000, 1010);
4123 snd_soc_update_bits(codec, hpf_gate_reg, 0x02, 0x00);
4124 }
4125 /* schedule work queue to Remove Mute */
4126 schedule_delayed_work(&tavil->tx_mute_dwork[decimator].dwork,
4127 msecs_to_jiffies(tx_unmute_delay));
4128 if (tavil->tx_hpf_work[decimator].hpf_cut_off_freq !=
4129 CF_MIN_3DB_150HZ)
4130 schedule_delayed_work(
4131 &tavil->tx_hpf_work[decimator].dwork,
4132 msecs_to_jiffies(300));
4133 /* apply gain after decimator is enabled */
4134 snd_soc_write(codec, tx_gain_ctl_reg,
4135 snd_soc_read(codec, tx_gain_ctl_reg));
4136 break;
4137 case SND_SOC_DAPM_PRE_PMD:
4138 hpf_cut_off_freq =
4139 tavil->tx_hpf_work[decimator].hpf_cut_off_freq;
4140 snd_soc_update_bits(codec, tx_vol_ctl_reg, 0x10, 0x10);
4141 if (cancel_delayed_work_sync(
4142 &tavil->tx_hpf_work[decimator].dwork)) {
4143 if (hpf_cut_off_freq != CF_MIN_3DB_150HZ) {
4144 snd_soc_update_bits(codec, dec_cfg_reg,
4145 TX_HPF_CUT_OFF_FREQ_MASK,
4146 hpf_cut_off_freq << 5);
4147 snd_soc_update_bits(codec, hpf_gate_reg,
4148 0x02, 0x02);
4149 /*
4150 * Minimum 1 clk cycle delay is required as per
4151 * HW spec.
4152 */
4153 usleep_range(1000, 1010);
4154 snd_soc_update_bits(codec, hpf_gate_reg,
4155 0x02, 0x00);
4156 }
4157 }
4158 cancel_delayed_work_sync(
4159 &tavil->tx_mute_dwork[decimator].dwork);
4160 break;
4161 case SND_SOC_DAPM_POST_PMD:
4162 snd_soc_update_bits(codec, tx_vol_ctl_reg, 0x10, 0x00);
4163 snd_soc_update_bits(codec, dec_cfg_reg,
4164 WCD934X_DEC_PWR_LVL_MASK,
4165 WCD934X_DEC_PWR_LVL_DF);
4166 break;
4167 };
4168out:
4169 kfree(wname);
4170 return ret;
4171}
4172
4173static u32 tavil_get_dmic_sample_rate(struct snd_soc_codec *codec,
4174 unsigned int dmic,
4175 struct wcd9xxx_pdata *pdata)
4176{
4177 u8 tx_stream_fs;
4178 u8 adc_mux_index = 0, adc_mux_sel = 0;
4179 bool dec_found = false;
4180 u16 adc_mux_ctl_reg, tx_fs_reg;
4181 u32 dmic_fs;
4182
4183 while (dec_found == 0 && adc_mux_index < WCD934X_MAX_VALID_ADC_MUX) {
4184 if (adc_mux_index < 4) {
4185 adc_mux_ctl_reg = WCD934X_CDC_TX_INP_MUX_ADC_MUX0_CFG0 +
4186 (adc_mux_index * 2);
4187 } else if (adc_mux_index < WCD934X_INVALID_ADC_MUX) {
4188 adc_mux_ctl_reg = WCD934X_CDC_TX_INP_MUX_ADC_MUX4_CFG0 +
4189 adc_mux_index - 4;
4190 } else if (adc_mux_index == WCD934X_INVALID_ADC_MUX) {
4191 ++adc_mux_index;
4192 continue;
4193 }
4194 adc_mux_sel = ((snd_soc_read(codec, adc_mux_ctl_reg) &
4195 0xF8) >> 3) - 1;
4196
4197 if (adc_mux_sel == dmic) {
4198 dec_found = true;
4199 break;
4200 }
4201
4202 ++adc_mux_index;
4203 }
4204
4205 if (dec_found && adc_mux_index <= 8) {
4206 tx_fs_reg = WCD934X_CDC_TX0_TX_PATH_CTL + (16 * adc_mux_index);
4207 tx_stream_fs = snd_soc_read(codec, tx_fs_reg) & 0x0F;
4208 if (tx_stream_fs <= 4) {
4209 if (pdata->dmic_sample_rate <=
4210 WCD9XXX_DMIC_SAMPLE_RATE_2P4MHZ)
4211 dmic_fs = pdata->dmic_sample_rate;
4212 else
4213 dmic_fs = WCD9XXX_DMIC_SAMPLE_RATE_2P4MHZ;
4214 } else
4215 dmic_fs = WCD9XXX_DMIC_SAMPLE_RATE_4P8MHZ;
4216 } else {
4217 dmic_fs = pdata->dmic_sample_rate;
4218 }
4219
4220 return dmic_fs;
4221}
4222
4223static u8 tavil_get_dmic_clk_val(struct snd_soc_codec *codec,
4224 u32 mclk_rate, u32 dmic_clk_rate)
4225{
4226 u32 div_factor;
4227 u8 dmic_ctl_val;
4228
4229 dev_dbg(codec->dev,
4230 "%s: mclk_rate = %d, dmic_sample_rate = %d\n",
4231 __func__, mclk_rate, dmic_clk_rate);
4232
4233 /* Default value to return in case of error */
4234 if (mclk_rate == WCD934X_MCLK_CLK_9P6MHZ)
4235 dmic_ctl_val = WCD934X_DMIC_CLK_DIV_2;
4236 else
4237 dmic_ctl_val = WCD934X_DMIC_CLK_DIV_3;
4238
4239 if (dmic_clk_rate == 0) {
4240 dev_err(codec->dev,
4241 "%s: dmic_sample_rate cannot be 0\n",
4242 __func__);
4243 goto done;
4244 }
4245
4246 div_factor = mclk_rate / dmic_clk_rate;
4247 switch (div_factor) {
4248 case 2:
4249 dmic_ctl_val = WCD934X_DMIC_CLK_DIV_2;
4250 break;
4251 case 3:
4252 dmic_ctl_val = WCD934X_DMIC_CLK_DIV_3;
4253 break;
4254 case 4:
4255 dmic_ctl_val = WCD934X_DMIC_CLK_DIV_4;
4256 break;
4257 case 6:
4258 dmic_ctl_val = WCD934X_DMIC_CLK_DIV_6;
4259 break;
4260 case 8:
4261 dmic_ctl_val = WCD934X_DMIC_CLK_DIV_8;
4262 break;
4263 case 16:
4264 dmic_ctl_val = WCD934X_DMIC_CLK_DIV_16;
4265 break;
4266 default:
4267 dev_err(codec->dev,
4268 "%s: Invalid div_factor %u, clk_rate(%u), dmic_rate(%u)\n",
4269 __func__, div_factor, mclk_rate, dmic_clk_rate);
4270 break;
4271 }
4272
4273done:
4274 return dmic_ctl_val;
4275}
4276
4277static int tavil_codec_enable_adc(struct snd_soc_dapm_widget *w,
4278 struct snd_kcontrol *kcontrol, int event)
4279{
4280 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
4281
4282 dev_dbg(codec->dev, "%s: event:%d\n", __func__, event);
4283
4284 switch (event) {
4285 case SND_SOC_DAPM_PRE_PMU:
4286 tavil_codec_set_tx_hold(codec, w->reg, true);
4287 break;
4288 default:
4289 break;
4290 }
4291
4292 return 0;
4293}
4294
4295static int tavil_codec_enable_dmic(struct snd_soc_dapm_widget *w,
4296 struct snd_kcontrol *kcontrol, int event)
4297{
4298 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
4299 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
4300 struct wcd9xxx_pdata *pdata = dev_get_platdata(codec->dev->parent);
4301 u8 dmic_clk_en = 0x01;
4302 u16 dmic_clk_reg;
4303 s32 *dmic_clk_cnt;
4304 u8 dmic_rate_val, dmic_rate_shift = 1;
4305 unsigned int dmic;
4306 u32 dmic_sample_rate;
4307 int ret;
4308 char *wname;
4309
4310 wname = strpbrk(w->name, "012345");
4311 if (!wname) {
4312 dev_err(codec->dev, "%s: widget not found\n", __func__);
4313 return -EINVAL;
4314 }
4315
4316 ret = kstrtouint(wname, 10, &dmic);
4317 if (ret < 0) {
4318 dev_err(codec->dev, "%s: Invalid DMIC line on the codec\n",
4319 __func__);
4320 return -EINVAL;
4321 }
4322
4323 switch (dmic) {
4324 case 0:
4325 case 1:
4326 dmic_clk_cnt = &(tavil->dmic_0_1_clk_cnt);
4327 dmic_clk_reg = WCD934X_CPE_SS_DMIC0_CTL;
4328 break;
4329 case 2:
4330 case 3:
4331 dmic_clk_cnt = &(tavil->dmic_2_3_clk_cnt);
4332 dmic_clk_reg = WCD934X_CPE_SS_DMIC1_CTL;
4333 break;
4334 case 4:
4335 case 5:
4336 dmic_clk_cnt = &(tavil->dmic_4_5_clk_cnt);
4337 dmic_clk_reg = WCD934X_CPE_SS_DMIC2_CTL;
4338 break;
4339 default:
4340 dev_err(codec->dev, "%s: Invalid DMIC Selection\n",
4341 __func__);
4342 return -EINVAL;
4343 };
4344 dev_dbg(codec->dev, "%s: event %d DMIC%d dmic_clk_cnt %d\n",
4345 __func__, event, dmic, *dmic_clk_cnt);
4346
4347 switch (event) {
4348 case SND_SOC_DAPM_PRE_PMU:
4349 dmic_sample_rate = tavil_get_dmic_sample_rate(codec, dmic,
4350 pdata);
4351 dmic_rate_val =
4352 tavil_get_dmic_clk_val(codec,
4353 pdata->mclk_rate,
4354 dmic_sample_rate);
4355
4356 (*dmic_clk_cnt)++;
4357 if (*dmic_clk_cnt == 1) {
4358 snd_soc_update_bits(codec, dmic_clk_reg,
4359 0x07 << dmic_rate_shift,
4360 dmic_rate_val << dmic_rate_shift);
4361 snd_soc_update_bits(codec, dmic_clk_reg,
4362 dmic_clk_en, dmic_clk_en);
4363 }
4364
4365 break;
4366 case SND_SOC_DAPM_POST_PMD:
4367 dmic_rate_val =
4368 tavil_get_dmic_clk_val(codec,
4369 pdata->mclk_rate,
4370 pdata->mad_dmic_sample_rate);
4371 (*dmic_clk_cnt)--;
4372 if (*dmic_clk_cnt == 0) {
4373 snd_soc_update_bits(codec, dmic_clk_reg,
4374 dmic_clk_en, 0);
4375 snd_soc_update_bits(codec, dmic_clk_reg,
4376 0x07 << dmic_rate_shift,
4377 dmic_rate_val << dmic_rate_shift);
4378 }
4379 break;
4380 };
4381
4382 return 0;
4383}
4384
4385/*
4386 * tavil_mbhc_micb_adjust_voltage: adjust specific micbias voltage
4387 * @codec: handle to snd_soc_codec *
4388 * @req_volt: micbias voltage to be set
4389 * @micb_num: micbias to be set, e.g. micbias1 or micbias2
4390 *
4391 * return 0 if adjustment is success or error code in case of failure
4392 */
4393int tavil_mbhc_micb_adjust_voltage(struct snd_soc_codec *codec,
4394 int req_volt, int micb_num)
4395{
4396 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
4397 int cur_vout_ctl, req_vout_ctl;
4398 int micb_reg, micb_val, micb_en;
4399 int ret = 0;
4400
4401 switch (micb_num) {
4402 case MIC_BIAS_1:
4403 micb_reg = WCD934X_ANA_MICB1;
4404 break;
4405 case MIC_BIAS_2:
4406 micb_reg = WCD934X_ANA_MICB2;
4407 break;
4408 case MIC_BIAS_3:
4409 micb_reg = WCD934X_ANA_MICB3;
4410 break;
4411 case MIC_BIAS_4:
4412 micb_reg = WCD934X_ANA_MICB4;
4413 break;
4414 default:
4415 return -EINVAL;
4416 }
4417 mutex_lock(&tavil->micb_lock);
4418
4419 /*
4420 * If requested micbias voltage is same as current micbias
4421 * voltage, then just return. Otherwise, adjust voltage as
4422 * per requested value. If micbias is already enabled, then
4423 * to avoid slow micbias ramp-up or down enable pull-up
4424 * momentarily, change the micbias value and then re-enable
4425 * micbias.
4426 */
4427 micb_val = snd_soc_read(codec, micb_reg);
4428 micb_en = (micb_val & 0xC0) >> 6;
4429 cur_vout_ctl = micb_val & 0x3F;
4430
4431 req_vout_ctl = wcd934x_get_micb_vout_ctl_val(req_volt);
Xiaoyu Ye1a2d8bd92017-01-31 18:54:15 -08004432 if (req_vout_ctl < 0) {
Banajit Goswamide8271c2017-01-18 00:28:59 -08004433 ret = -EINVAL;
4434 goto exit;
4435 }
4436 if (cur_vout_ctl == req_vout_ctl) {
4437 ret = 0;
4438 goto exit;
4439 }
4440
4441 dev_dbg(codec->dev, "%s: micb_num: %d, cur_mv: %d, req_mv: %d, micb_en: %d\n",
4442 __func__, micb_num, WCD_VOUT_CTL_TO_MICB(cur_vout_ctl),
4443 req_volt, micb_en);
4444
4445 if (micb_en == 0x1)
4446 snd_soc_update_bits(codec, micb_reg, 0xC0, 0x80);
4447
4448 snd_soc_update_bits(codec, micb_reg, 0x3F, req_vout_ctl);
4449
4450 if (micb_en == 0x1) {
4451 snd_soc_update_bits(codec, micb_reg, 0xC0, 0x40);
4452 /*
4453 * Add 2ms delay as per HW requirement after enabling
4454 * micbias
4455 */
4456 usleep_range(2000, 2100);
4457 }
4458exit:
4459 mutex_unlock(&tavil->micb_lock);
4460 return ret;
4461}
4462EXPORT_SYMBOL(tavil_mbhc_micb_adjust_voltage);
4463
4464/*
4465 * tavil_micbias_control: enable/disable micbias
4466 * @codec: handle to snd_soc_codec *
4467 * @micb_num: micbias to be enabled/disabled, e.g. micbias1 or micbias2
4468 * @req: control requested, enable/disable or pullup enable/disable
4469 * @is_dapm: triggered by dapm or not
4470 *
4471 * return 0 if control is success or error code in case of failure
4472 */
4473int tavil_micbias_control(struct snd_soc_codec *codec,
4474 int micb_num, int req, bool is_dapm)
4475{
4476 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
4477 int micb_index = micb_num - 1;
4478 u16 micb_reg;
4479 int pre_off_event = 0, post_off_event = 0;
4480 int post_on_event = 0, post_dapm_off = 0;
4481 int post_dapm_on = 0;
4482
4483 if ((micb_index < 0) || (micb_index > TAVIL_MAX_MICBIAS - 1)) {
4484 dev_err(codec->dev, "%s: Invalid micbias index, micb_ind:%d\n",
4485 __func__, micb_index);
4486 return -EINVAL;
4487 }
4488
4489 switch (micb_num) {
4490 case MIC_BIAS_1:
4491 micb_reg = WCD934X_ANA_MICB1;
4492 break;
4493 case MIC_BIAS_2:
4494 micb_reg = WCD934X_ANA_MICB2;
4495 pre_off_event = WCD_EVENT_PRE_MICBIAS_2_OFF;
4496 post_off_event = WCD_EVENT_POST_MICBIAS_2_OFF;
4497 post_on_event = WCD_EVENT_POST_MICBIAS_2_ON;
4498 post_dapm_on = WCD_EVENT_POST_DAPM_MICBIAS_2_ON;
4499 post_dapm_off = WCD_EVENT_POST_DAPM_MICBIAS_2_OFF;
4500 break;
4501 case MIC_BIAS_3:
4502 micb_reg = WCD934X_ANA_MICB3;
4503 break;
4504 case MIC_BIAS_4:
4505 micb_reg = WCD934X_ANA_MICB4;
4506 break;
4507 default:
4508 dev_err(codec->dev, "%s: Invalid micbias number: %d\n",
4509 __func__, micb_num);
4510 return -EINVAL;
4511 }
4512 mutex_lock(&tavil->micb_lock);
4513
4514 switch (req) {
4515 case MICB_PULLUP_ENABLE:
4516 tavil->pullup_ref[micb_index]++;
4517 if ((tavil->pullup_ref[micb_index] == 1) &&
4518 (tavil->micb_ref[micb_index] == 0))
4519 snd_soc_update_bits(codec, micb_reg, 0xC0, 0x80);
4520 break;
4521 case MICB_PULLUP_DISABLE:
4522 if (tavil->pullup_ref[micb_index] > 0)
4523 tavil->pullup_ref[micb_index]--;
4524 if ((tavil->pullup_ref[micb_index] == 0) &&
4525 (tavil->micb_ref[micb_index] == 0))
4526 snd_soc_update_bits(codec, micb_reg, 0xC0, 0x00);
4527 break;
4528 case MICB_ENABLE:
4529 tavil->micb_ref[micb_index]++;
4530 if (tavil->micb_ref[micb_index] == 1) {
4531 snd_soc_update_bits(codec, micb_reg, 0xC0, 0x40);
4532 if (post_on_event && tavil->mbhc)
4533 blocking_notifier_call_chain(
4534 &tavil->mbhc->notifier,
4535 post_on_event,
4536 &tavil->mbhc->wcd_mbhc);
4537 }
4538 if (is_dapm && post_dapm_on && tavil->mbhc)
4539 blocking_notifier_call_chain(&tavil->mbhc->notifier,
4540 post_dapm_on, &tavil->mbhc->wcd_mbhc);
4541 break;
4542 case MICB_DISABLE:
4543 if (tavil->micb_ref[micb_index] > 0)
4544 tavil->micb_ref[micb_index]--;
4545 if ((tavil->micb_ref[micb_index] == 0) &&
4546 (tavil->pullup_ref[micb_index] > 0))
4547 snd_soc_update_bits(codec, micb_reg, 0xC0, 0x80);
4548 else if ((tavil->micb_ref[micb_index] == 0) &&
4549 (tavil->pullup_ref[micb_index] == 0)) {
4550 if (pre_off_event && tavil->mbhc)
4551 blocking_notifier_call_chain(
4552 &tavil->mbhc->notifier,
4553 pre_off_event,
4554 &tavil->mbhc->wcd_mbhc);
4555 snd_soc_update_bits(codec, micb_reg, 0xC0, 0x00);
4556 if (post_off_event && tavil->mbhc)
4557 blocking_notifier_call_chain(
4558 &tavil->mbhc->notifier,
4559 post_off_event,
4560 &tavil->mbhc->wcd_mbhc);
4561 }
4562 if (is_dapm && post_dapm_off && tavil->mbhc)
4563 blocking_notifier_call_chain(&tavil->mbhc->notifier,
4564 post_dapm_off, &tavil->mbhc->wcd_mbhc);
4565 break;
4566 };
4567
4568 dev_dbg(codec->dev, "%s: micb_num:%d, micb_ref: %d, pullup_ref: %d\n",
4569 __func__, micb_num, tavil->micb_ref[micb_index],
4570 tavil->pullup_ref[micb_index]);
4571
4572 mutex_unlock(&tavil->micb_lock);
4573
4574 return 0;
4575}
4576EXPORT_SYMBOL(tavil_micbias_control);
4577
4578static int __tavil_codec_enable_micbias(struct snd_soc_dapm_widget *w,
4579 int event)
4580{
4581 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
4582 int micb_num;
4583
4584 dev_dbg(codec->dev, "%s: wname: %s, event: %d\n",
4585 __func__, w->name, event);
4586
4587 if (strnstr(w->name, "MIC BIAS1", sizeof("MIC BIAS1")))
4588 micb_num = MIC_BIAS_1;
4589 else if (strnstr(w->name, "MIC BIAS2", sizeof("MIC BIAS2")))
4590 micb_num = MIC_BIAS_2;
4591 else if (strnstr(w->name, "MIC BIAS3", sizeof("MIC BIAS3")))
4592 micb_num = MIC_BIAS_3;
4593 else if (strnstr(w->name, "MIC BIAS4", sizeof("MIC BIAS4")))
4594 micb_num = MIC_BIAS_4;
4595 else
4596 return -EINVAL;
4597
4598 switch (event) {
4599 case SND_SOC_DAPM_PRE_PMU:
4600 /*
4601 * MIC BIAS can also be requested by MBHC,
4602 * so use ref count to handle micbias pullup
4603 * and enable requests
4604 */
4605 tavil_micbias_control(codec, micb_num, MICB_ENABLE, true);
4606 break;
4607 case SND_SOC_DAPM_POST_PMU:
4608 /* wait for cnp time */
4609 usleep_range(1000, 1100);
4610 break;
4611 case SND_SOC_DAPM_POST_PMD:
4612 tavil_micbias_control(codec, micb_num, MICB_DISABLE, true);
4613 break;
4614 };
4615
4616 return 0;
4617}
4618
4619/*
4620 * tavil_codec_enable_standalone_micbias - enable micbias standalone
4621 * @codec: pointer to codec instance
4622 * @micb_num: number of micbias to be enabled
4623 * @enable: true to enable micbias or false to disable
4624 *
4625 * This function is used to enable micbias (1, 2, 3 or 4) during
4626 * standalone independent of whether TX use-case is running or not
4627 *
4628 * Return: error code in case of failure or 0 for success
4629 */
4630int tavil_codec_enable_standalone_micbias(struct snd_soc_codec *codec,
4631 int micb_num,
4632 bool enable)
4633{
4634 const char * const micb_names[] = {
4635 DAPM_MICBIAS1_STANDALONE, DAPM_MICBIAS2_STANDALONE,
4636 DAPM_MICBIAS3_STANDALONE, DAPM_MICBIAS4_STANDALONE
4637 };
4638 int micb_index = micb_num - 1;
4639 int rc;
4640
4641 if (!codec) {
4642 pr_err("%s: Codec memory is NULL\n", __func__);
4643 return -EINVAL;
4644 }
4645
4646 if ((micb_index < 0) || (micb_index > TAVIL_MAX_MICBIAS - 1)) {
4647 dev_err(codec->dev, "%s: Invalid micbias index, micb_ind:%d\n",
4648 __func__, micb_index);
4649 return -EINVAL;
4650 }
4651
4652 if (enable)
4653 rc = snd_soc_dapm_force_enable_pin(
4654 snd_soc_codec_get_dapm(codec),
4655 micb_names[micb_index]);
4656 else
4657 rc = snd_soc_dapm_disable_pin(snd_soc_codec_get_dapm(codec),
4658 micb_names[micb_index]);
4659
4660 if (!rc)
4661 snd_soc_dapm_sync(snd_soc_codec_get_dapm(codec));
4662 else
4663 dev_err(codec->dev, "%s: micbias%d force %s pin failed\n",
4664 __func__, micb_num, (enable ? "enable" : "disable"));
4665
4666 return rc;
4667}
4668EXPORT_SYMBOL(tavil_codec_enable_standalone_micbias);
4669
4670static int tavil_codec_force_enable_micbias(struct snd_soc_dapm_widget *w,
4671 struct snd_kcontrol *kcontrol,
4672 int event)
4673{
4674 int ret = 0;
4675 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
4676 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
4677
4678 switch (event) {
4679 case SND_SOC_DAPM_PRE_PMU:
4680 wcd_resmgr_enable_master_bias(tavil->resmgr);
4681 tavil_cdc_mclk_enable(codec, true);
4682 ret = __tavil_codec_enable_micbias(w, SND_SOC_DAPM_PRE_PMU);
4683 /* Wait for 1ms for better cnp */
4684 usleep_range(1000, 1100);
4685 tavil_cdc_mclk_enable(codec, false);
4686 break;
4687 case SND_SOC_DAPM_POST_PMD:
4688 ret = __tavil_codec_enable_micbias(w, SND_SOC_DAPM_POST_PMD);
4689 wcd_resmgr_disable_master_bias(tavil->resmgr);
4690 break;
4691 }
4692
4693 return ret;
4694}
4695
4696static int tavil_codec_enable_micbias(struct snd_soc_dapm_widget *w,
4697 struct snd_kcontrol *kcontrol, int event)
4698{
4699 return __tavil_codec_enable_micbias(w, event);
4700}
4701
4702
4703static const struct reg_sequence tavil_hph_reset_tbl[] = {
4704 { WCD934X_HPH_CNP_EN, 0x80 },
4705 { WCD934X_HPH_CNP_WG_CTL, 0x9A },
4706 { WCD934X_HPH_CNP_WG_TIME, 0x14 },
4707 { WCD934X_HPH_OCP_CTL, 0x28 },
4708 { WCD934X_HPH_AUTO_CHOP, 0x16 },
4709 { WCD934X_HPH_CHOP_CTL, 0x83 },
4710 { WCD934X_HPH_PA_CTL1, 0x46 },
4711 { WCD934X_HPH_PA_CTL2, 0x50 },
4712 { WCD934X_HPH_L_EN, 0x80 },
4713 { WCD934X_HPH_L_TEST, 0xE0 },
4714 { WCD934X_HPH_L_ATEST, 0x50 },
4715 { WCD934X_HPH_R_EN, 0x80 },
4716 { WCD934X_HPH_R_TEST, 0xE0 },
4717 { WCD934X_HPH_R_ATEST, 0x54 },
4718 { WCD934X_HPH_RDAC_CLK_CTL1, 0x99 },
4719 { WCD934X_HPH_RDAC_CLK_CTL2, 0x9B },
4720 { WCD934X_HPH_RDAC_LDO_CTL, 0x33 },
4721 { WCD934X_HPH_RDAC_CHOP_CLK_LP_CTL, 0x00 },
4722 { WCD934X_HPH_REFBUFF_UHQA_CTL, 0xA8 },
4723};
4724
4725static const struct reg_sequence tavil_hph_reset_tbl_1_0[] = {
4726 { WCD934X_HPH_REFBUFF_LP_CTL, 0x0A },
4727 { WCD934X_HPH_L_DAC_CTL, 0x00 },
4728 { WCD934X_HPH_R_DAC_CTL, 0x00 },
4729 { WCD934X_HPH_NEW_ANA_HPH2, 0x00 },
4730 { WCD934X_HPH_NEW_ANA_HPH3, 0x00 },
4731 { WCD934X_HPH_NEW_INT_RDAC_GAIN_CTL, 0x00 },
4732 { WCD934X_HPH_NEW_INT_RDAC_HD2_CTL, 0xA0 },
4733 { WCD934X_HPH_NEW_INT_RDAC_VREF_CTL, 0x10 },
4734 { WCD934X_HPH_NEW_INT_RDAC_OVERRIDE_CTL, 0x00 },
4735 { WCD934X_HPH_NEW_INT_RDAC_MISC1, 0x00 },
4736 { WCD934X_HPH_NEW_INT_PA_MISC1, 0x22 },
4737 { WCD934X_HPH_NEW_INT_PA_MISC2, 0x00 },
4738 { WCD934X_HPH_NEW_INT_PA_RDAC_MISC, 0x00 },
4739 { WCD934X_HPH_NEW_INT_HPH_TIMER1, 0xFE },
4740 { WCD934X_HPH_NEW_INT_HPH_TIMER2, 0x2 },
4741 { WCD934X_HPH_NEW_INT_HPH_TIMER3, 0x4e},
4742 { WCD934X_HPH_NEW_INT_HPH_TIMER4, 0x54 },
4743 { WCD934X_HPH_NEW_INT_PA_RDAC_MISC2, 0x00 },
4744 { WCD934X_HPH_NEW_INT_PA_RDAC_MISC3, 0x00 },
4745};
4746
4747static const struct reg_sequence tavil_hph_reset_tbl_1_1[] = {
4748 { WCD934X_HPH_REFBUFF_LP_CTL, 0x0E },
4749 { WCD934X_HPH_L_DAC_CTL, 0x00 },
4750 { WCD934X_HPH_R_DAC_CTL, 0x00 },
4751 { WCD934X_HPH_NEW_ANA_HPH2, 0x00 },
4752 { WCD934X_HPH_NEW_ANA_HPH3, 0x00 },
4753 { WCD934X_HPH_NEW_INT_RDAC_GAIN_CTL, 0x40 },
4754 { WCD934X_HPH_NEW_INT_RDAC_HD2_CTL, 0x81 },
4755 { WCD934X_HPH_NEW_INT_RDAC_VREF_CTL, 0x10 },
4756 { WCD934X_HPH_NEW_INT_RDAC_OVERRIDE_CTL, 0x00 },
4757 { WCD934X_HPH_NEW_INT_RDAC_MISC1, 0x81 },
4758 { WCD934X_HPH_NEW_INT_PA_MISC1, 0x22 },
4759 { WCD934X_HPH_NEW_INT_PA_MISC2, 0x00 },
4760 { WCD934X_HPH_NEW_INT_PA_RDAC_MISC, 0x00 },
4761 { WCD934X_HPH_NEW_INT_HPH_TIMER1, 0xFE },
4762 { WCD934X_HPH_NEW_INT_HPH_TIMER2, 0x2 },
4763 { WCD934X_HPH_NEW_INT_HPH_TIMER3, 0x4e},
4764 { WCD934X_HPH_NEW_INT_HPH_TIMER4, 0x54 },
4765 { WCD934X_HPH_NEW_INT_PA_RDAC_MISC2, 0x00 },
4766 { WCD934X_HPH_NEW_INT_PA_RDAC_MISC3, 0x00 },
4767};
4768
4769static const struct tavil_reg_mask_val tavil_pa_disable[] = {
4770 { WCD934X_CDC_RX1_RX_PATH_CTL, 0x30, 0x10 }, /* RX1 mute enable */
4771 { WCD934X_CDC_RX2_RX_PATH_CTL, 0x30, 0x10 }, /* RX2 mute enable */
4772 { WCD934X_HPH_CNP_WG_CTL, 0x80, 0x00 }, /* GM3 boost disable */
4773 { WCD934X_ANA_HPH, 0x80, 0x00 }, /* HPHL PA disable */
4774 { WCD934X_ANA_HPH, 0x40, 0x00 }, /* HPHR PA disable */
4775 { WCD934X_ANA_HPH, 0x20, 0x00 }, /* HPHL REF dsable */
4776 { WCD934X_ANA_HPH, 0x10, 0x00 }, /* HPHR REF disable */
4777};
4778
4779static const struct tavil_reg_mask_val tavil_ocp_en_seq[] = {
4780 { WCD934X_RX_OCP_CTL, 0x0F, 0x02 }, /* OCP number of attempts is 2 */
4781 { WCD934X_HPH_OCP_CTL, 0xFA, 0x3A }, /* OCP current limit */
4782 { WCD934X_HPH_L_TEST, 0x01, 0x01 }, /* Enable HPHL OCP */
4783 { WCD934X_HPH_R_TEST, 0x01, 0x01 }, /* Enable HPHR OCP */
4784};
4785
4786static const struct tavil_reg_mask_val tavil_ocp_en_seq_1[] = {
4787 { WCD934X_RX_OCP_CTL, 0x0F, 0x02 }, /* OCP number of attempts is 2 */
4788 { WCD934X_HPH_OCP_CTL, 0xFA, 0x3A }, /* OCP current limit */
4789};
4790
4791/* LO-HIFI */
4792static const struct tavil_reg_mask_val tavil_pre_pa_en_lohifi[] = {
4793 { WCD934X_HPH_NEW_INT_HPH_TIMER1, 0x02, 0x00 },
4794 { WCD934X_FLYBACK_VNEG_CTRL_4, 0xf0, 0x80 },
4795 { WCD934X_HPH_NEW_INT_PA_MISC2, 0x20, 0x20 },
4796 { WCD934X_HPH_NEW_INT_RDAC_GAIN_CTL, 0xf0, 0x40 },
4797 { WCD934X_HPH_CNP_WG_CTL, 0x80, 0x00 },
4798 { WCD934X_RX_BIAS_HPH_LOWPOWER, 0xf0, 0xc0 },
4799 { WCD934X_HPH_PA_CTL1, 0x0e, 0x02 },
4800 { WCD934X_HPH_REFBUFF_LP_CTL, 0x06, 0x06 },
4801};
4802
4803static const struct tavil_reg_mask_val tavil_pre_pa_en[] = {
4804 { WCD934X_HPH_NEW_INT_HPH_TIMER1, 0x02, 0x00 },
4805 { WCD934X_HPH_NEW_INT_PA_MISC2, 0x20, 0x0 },
4806 { WCD934X_HPH_NEW_INT_RDAC_GAIN_CTL, 0xf0, 0x40 },
4807 { WCD934X_HPH_CNP_WG_CTL, 0x80, 0x00 },
4808 { WCD934X_RX_BIAS_HPH_LOWPOWER, 0xf0, 0x80 },
4809 { WCD934X_HPH_PA_CTL1, 0x0e, 0x06 },
4810 { WCD934X_HPH_REFBUFF_LP_CTL, 0x06, 0x06 },
4811};
4812
4813static const struct tavil_reg_mask_val tavil_post_pa_en[] = {
4814 { WCD934X_HPH_L_TEST, 0x01, 0x01 }, /* Enable HPHL OCP */
4815 { WCD934X_HPH_R_TEST, 0x01, 0x01 }, /* Enable HPHR OCP */
4816 { WCD934X_CDC_RX1_RX_PATH_CTL, 0x30, 0x20 }, /* RX1 mute disable */
4817 { WCD934X_CDC_RX2_RX_PATH_CTL, 0x30, 0x20 }, /* RX2 mute disable */
4818 { WCD934X_HPH_CNP_WG_CTL, 0x80, 0x80 }, /* GM3 boost enable */
4819 { WCD934X_HPH_NEW_INT_HPH_TIMER1, 0x02, 0x02 },
4820};
4821
4822static void tavil_codec_hph_reg_range_read(struct regmap *map, u8 *buf)
4823{
4824 regmap_bulk_read(map, WCD934X_HPH_CNP_EN, buf, TAVIL_HPH_REG_RANGE_1);
4825 regmap_bulk_read(map, WCD934X_HPH_NEW_ANA_HPH2,
4826 buf + TAVIL_HPH_REG_RANGE_1, TAVIL_HPH_REG_RANGE_2);
4827 regmap_bulk_read(map, WCD934X_HPH_NEW_INT_RDAC_GAIN_CTL,
4828 buf + TAVIL_HPH_REG_RANGE_1 + TAVIL_HPH_REG_RANGE_2,
4829 TAVIL_HPH_REG_RANGE_3);
4830}
4831
4832static void tavil_codec_hph_reg_recover(struct tavil_priv *tavil,
4833 struct regmap *map, int pa_status)
4834{
4835 int i;
4836 unsigned int reg;
4837
4838 blocking_notifier_call_chain(&tavil->mbhc->notifier,
4839 WCD_EVENT_OCP_OFF,
4840 &tavil->mbhc->wcd_mbhc);
4841
4842 if (pa_status & 0xC0)
4843 goto pa_en_restore;
4844
4845 dev_dbg(tavil->dev, "%s: HPH PA in disable state (0x%x)\n",
4846 __func__, pa_status);
4847
4848 regmap_write_bits(map, WCD934X_CDC_RX1_RX_PATH_CTL, 0x10, 0x10);
4849 regmap_write_bits(map, WCD934X_CDC_RX2_RX_PATH_CTL, 0x10, 0x10);
4850 regmap_write_bits(map, WCD934X_ANA_HPH, 0xC0, 0x00);
4851 regmap_write_bits(map, WCD934X_ANA_HPH, 0x30, 0x00);
4852 regmap_write_bits(map, WCD934X_CDC_RX1_RX_PATH_CTL, 0x10, 0x00);
4853 regmap_write_bits(map, WCD934X_CDC_RX2_RX_PATH_CTL, 0x10, 0x00);
4854
4855 /* Restore to HW defaults */
4856 regmap_multi_reg_write(map, tavil_hph_reset_tbl,
4857 ARRAY_SIZE(tavil_hph_reset_tbl));
4858 if (TAVIL_IS_1_1(tavil->wcd9xxx))
4859 regmap_multi_reg_write(map, tavil_hph_reset_tbl_1_1,
4860 ARRAY_SIZE(tavil_hph_reset_tbl_1_1));
4861 if (TAVIL_IS_1_0(tavil->wcd9xxx))
4862 regmap_multi_reg_write(map, tavil_hph_reset_tbl_1_0,
4863 ARRAY_SIZE(tavil_hph_reset_tbl_1_0));
4864
4865 for (i = 0; i < ARRAY_SIZE(tavil_ocp_en_seq); i++)
4866 regmap_write_bits(map, tavil_ocp_en_seq[i].reg,
4867 tavil_ocp_en_seq[i].mask,
4868 tavil_ocp_en_seq[i].val);
4869 goto end;
4870
4871
4872pa_en_restore:
4873 dev_dbg(tavil->dev, "%s: HPH PA in enable state (0x%x)\n",
4874 __func__, pa_status);
4875
4876 /* Disable PA and other registers before restoring */
4877 for (i = 0; i < ARRAY_SIZE(tavil_pa_disable); i++) {
4878 if (TAVIL_IS_1_1(tavil->wcd9xxx) &&
4879 (tavil_pa_disable[i].reg == WCD934X_HPH_CNP_WG_CTL))
4880 continue;
4881 regmap_write_bits(map, tavil_pa_disable[i].reg,
4882 tavil_pa_disable[i].mask,
4883 tavil_pa_disable[i].val);
4884 }
4885
4886 regmap_multi_reg_write(map, tavil_hph_reset_tbl,
4887 ARRAY_SIZE(tavil_hph_reset_tbl));
4888 if (TAVIL_IS_1_1(tavil->wcd9xxx))
4889 regmap_multi_reg_write(map, tavil_hph_reset_tbl_1_1,
4890 ARRAY_SIZE(tavil_hph_reset_tbl_1_1));
4891 if (TAVIL_IS_1_0(tavil->wcd9xxx))
4892 regmap_multi_reg_write(map, tavil_hph_reset_tbl_1_0,
4893 ARRAY_SIZE(tavil_hph_reset_tbl_1_0));
4894
4895 for (i = 0; i < ARRAY_SIZE(tavil_ocp_en_seq_1); i++)
4896 regmap_write_bits(map, tavil_ocp_en_seq_1[i].reg,
4897 tavil_ocp_en_seq_1[i].mask,
4898 tavil_ocp_en_seq_1[i].val);
4899
4900 if (tavil->hph_mode == CLS_H_LOHIFI) {
4901 for (i = 0; i < ARRAY_SIZE(tavil_pre_pa_en_lohifi); i++) {
4902 reg = tavil_pre_pa_en_lohifi[i].reg;
4903 if ((TAVIL_IS_1_1(tavil->wcd9xxx)) &&
4904 ((reg == WCD934X_HPH_NEW_INT_RDAC_GAIN_CTL) ||
4905 (reg == WCD934X_HPH_CNP_WG_CTL) ||
4906 (reg == WCD934X_HPH_REFBUFF_LP_CTL)))
4907 continue;
4908 regmap_write_bits(map,
4909 tavil_pre_pa_en_lohifi[i].reg,
4910 tavil_pre_pa_en_lohifi[i].mask,
4911 tavil_pre_pa_en_lohifi[i].val);
4912 }
4913 } else {
4914 for (i = 0; i < ARRAY_SIZE(tavil_pre_pa_en); i++) {
4915 reg = tavil_pre_pa_en[i].reg;
4916 if ((TAVIL_IS_1_1(tavil->wcd9xxx)) &&
4917 ((reg == WCD934X_HPH_NEW_INT_RDAC_GAIN_CTL) ||
4918 (reg == WCD934X_HPH_CNP_WG_CTL) ||
4919 (reg == WCD934X_HPH_REFBUFF_LP_CTL)))
4920 continue;
4921 regmap_write_bits(map, tavil_pre_pa_en[i].reg,
4922 tavil_pre_pa_en[i].mask,
4923 tavil_pre_pa_en[i].val);
4924 }
4925 }
4926
4927 if (TAVIL_IS_1_1(tavil->wcd9xxx)) {
4928 regmap_write(map, WCD934X_HPH_NEW_INT_RDAC_HD2_CTL_L, 0x84);
4929 regmap_write(map, WCD934X_HPH_NEW_INT_RDAC_HD2_CTL_R, 0x84);
4930 }
4931
4932 regmap_write_bits(map, WCD934X_ANA_HPH, 0x0C, pa_status & 0x0C);
4933 regmap_write_bits(map, WCD934X_ANA_HPH, 0x30, 0x30);
4934 /* wait for 100usec after HPH DAC is enabled */
4935 usleep_range(100, 110);
4936 regmap_write(map, WCD934X_ANA_HPH, pa_status);
4937 /* Sleep for 7msec after PA is enabled */
4938 usleep_range(7000, 7100);
4939
4940 for (i = 0; i < ARRAY_SIZE(tavil_post_pa_en); i++) {
4941 if ((TAVIL_IS_1_1(tavil->wcd9xxx)) &&
4942 (tavil_post_pa_en[i].reg == WCD934X_HPH_CNP_WG_CTL))
4943 continue;
4944 regmap_write_bits(map, tavil_post_pa_en[i].reg,
4945 tavil_post_pa_en[i].mask,
4946 tavil_post_pa_en[i].val);
4947 }
4948
4949end:
4950 tavil->mbhc->is_hph_recover = true;
4951 blocking_notifier_call_chain(
4952 &tavil->mbhc->notifier,
4953 WCD_EVENT_OCP_ON,
4954 &tavil->mbhc->wcd_mbhc);
4955}
4956
4957static int tavil_codec_reset_hph_registers(struct snd_soc_dapm_widget *w,
4958 struct snd_kcontrol *kcontrol,
4959 int event)
4960{
4961 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
4962 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
4963 struct wcd9xxx *wcd9xxx = dev_get_drvdata(codec->dev->parent);
4964 u8 cache_val[TAVIL_HPH_TOTAL_REG];
4965 u8 hw_val[TAVIL_HPH_TOTAL_REG];
4966 int pa_status;
4967 int ret;
4968
4969 dev_dbg(wcd9xxx->dev, "%s: event: %d\n", __func__, event);
4970
4971 switch (event) {
4972 case SND_SOC_DAPM_PRE_PMU:
4973 memset(cache_val, 0, TAVIL_HPH_TOTAL_REG);
4974 memset(hw_val, 0, TAVIL_HPH_TOTAL_REG);
4975
4976 regmap_read(wcd9xxx->regmap, WCD934X_ANA_HPH, &pa_status);
4977
4978 tavil_codec_hph_reg_range_read(wcd9xxx->regmap, cache_val);
4979
4980 /* Read register values from HW directly */
4981 regcache_cache_bypass(wcd9xxx->regmap, true);
4982 tavil_codec_hph_reg_range_read(wcd9xxx->regmap, hw_val);
4983 regcache_cache_bypass(wcd9xxx->regmap, false);
4984
4985 /* compare both the registers to know if there is corruption */
4986 ret = memcmp(cache_val, hw_val, TAVIL_HPH_TOTAL_REG);
4987
4988 /* If both the values are same, it means no corruption */
4989 if (ret) {
4990 dev_dbg(codec->dev, "%s: cache and hw reg are not same\n",
4991 __func__);
4992 tavil_codec_hph_reg_recover(tavil, wcd9xxx->regmap,
4993 pa_status);
4994 } else {
4995 dev_dbg(codec->dev, "%s: cache and hw reg are same\n",
4996 __func__);
4997 tavil->mbhc->is_hph_recover = false;
4998 }
4999 break;
5000 default:
5001 break;
5002 };
5003
5004 return 0;
5005}
5006
5007static int tavil_iir_enable_audio_mixer_get(struct snd_kcontrol *kcontrol,
5008 struct snd_ctl_elem_value *ucontrol)
5009{
5010 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
5011 int iir_idx = ((struct soc_multi_mixer_control *)
5012 kcontrol->private_value)->reg;
5013 int band_idx = ((struct soc_multi_mixer_control *)
5014 kcontrol->private_value)->shift;
5015 /* IIR filter band registers are at integer multiples of 16 */
5016 u16 iir_reg = WCD934X_CDC_SIDETONE_IIR0_IIR_CTL + 16 * iir_idx;
5017
5018 ucontrol->value.integer.value[0] = (snd_soc_read(codec, iir_reg) &
5019 (1 << band_idx)) != 0;
5020
5021 dev_dbg(codec->dev, "%s: IIR #%d band #%d enable %d\n", __func__,
5022 iir_idx, band_idx,
5023 (uint32_t)ucontrol->value.integer.value[0]);
5024 return 0;
5025}
5026
5027static int tavil_iir_enable_audio_mixer_put(struct snd_kcontrol *kcontrol,
5028 struct snd_ctl_elem_value *ucontrol)
5029{
5030 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
5031 int iir_idx = ((struct soc_multi_mixer_control *)
5032 kcontrol->private_value)->reg;
5033 int band_idx = ((struct soc_multi_mixer_control *)
5034 kcontrol->private_value)->shift;
5035 bool iir_band_en_status;
5036 int value = ucontrol->value.integer.value[0];
5037 u16 iir_reg = WCD934X_CDC_SIDETONE_IIR0_IIR_CTL + 16 * iir_idx;
5038
5039 /* Mask first 5 bits, 6-8 are reserved */
5040 snd_soc_update_bits(codec, iir_reg, (1 << band_idx),
5041 (value << band_idx));
5042
5043 iir_band_en_status = ((snd_soc_read(codec, iir_reg) &
5044 (1 << band_idx)) != 0);
5045 dev_dbg(codec->dev, "%s: IIR #%d band #%d enable %d\n", __func__,
5046 iir_idx, band_idx, iir_band_en_status);
5047 return 0;
5048}
5049
5050static uint32_t get_iir_band_coeff(struct snd_soc_codec *codec,
5051 int iir_idx, int band_idx,
5052 int coeff_idx)
5053{
5054 uint32_t value = 0;
5055
5056 /* Address does not automatically update if reading */
5057 snd_soc_write(codec,
5058 (WCD934X_CDC_SIDETONE_IIR0_IIR_COEF_B1_CTL + 16 * iir_idx),
5059 ((band_idx * BAND_MAX + coeff_idx)
5060 * sizeof(uint32_t)) & 0x7F);
5061
5062 value |= snd_soc_read(codec,
5063 (WCD934X_CDC_SIDETONE_IIR0_IIR_COEF_B2_CTL + 16 * iir_idx));
5064
5065 snd_soc_write(codec,
5066 (WCD934X_CDC_SIDETONE_IIR0_IIR_COEF_B1_CTL + 16 * iir_idx),
5067 ((band_idx * BAND_MAX + coeff_idx)
5068 * sizeof(uint32_t) + 1) & 0x7F);
5069
5070 value |= (snd_soc_read(codec,
5071 (WCD934X_CDC_SIDETONE_IIR0_IIR_COEF_B2_CTL +
5072 16 * iir_idx)) << 8);
5073
5074 snd_soc_write(codec,
5075 (WCD934X_CDC_SIDETONE_IIR0_IIR_COEF_B1_CTL + 16 * iir_idx),
5076 ((band_idx * BAND_MAX + coeff_idx)
5077 * sizeof(uint32_t) + 2) & 0x7F);
5078
5079 value |= (snd_soc_read(codec,
5080 (WCD934X_CDC_SIDETONE_IIR0_IIR_COEF_B2_CTL +
5081 16 * iir_idx)) << 16);
5082
5083 snd_soc_write(codec,
5084 (WCD934X_CDC_SIDETONE_IIR0_IIR_COEF_B1_CTL + 16 * iir_idx),
5085 ((band_idx * BAND_MAX + coeff_idx)
5086 * sizeof(uint32_t) + 3) & 0x7F);
5087
5088 /* Mask bits top 2 bits since they are reserved */
5089 value |= ((snd_soc_read(codec,
5090 (WCD934X_CDC_SIDETONE_IIR0_IIR_COEF_B2_CTL +
5091 16 * iir_idx)) & 0x3F) << 24);
5092
5093 return value;
5094}
5095
5096static int tavil_iir_band_audio_mixer_get(struct snd_kcontrol *kcontrol,
5097 struct snd_ctl_elem_value *ucontrol)
5098{
5099 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
5100 int iir_idx = ((struct soc_multi_mixer_control *)
5101 kcontrol->private_value)->reg;
5102 int band_idx = ((struct soc_multi_mixer_control *)
5103 kcontrol->private_value)->shift;
5104
5105 ucontrol->value.integer.value[0] =
5106 get_iir_band_coeff(codec, iir_idx, band_idx, 0);
5107 ucontrol->value.integer.value[1] =
5108 get_iir_band_coeff(codec, iir_idx, band_idx, 1);
5109 ucontrol->value.integer.value[2] =
5110 get_iir_band_coeff(codec, iir_idx, band_idx, 2);
5111 ucontrol->value.integer.value[3] =
5112 get_iir_band_coeff(codec, iir_idx, band_idx, 3);
5113 ucontrol->value.integer.value[4] =
5114 get_iir_band_coeff(codec, iir_idx, band_idx, 4);
5115
5116 dev_dbg(codec->dev, "%s: IIR #%d band #%d b0 = 0x%x\n"
5117 "%s: IIR #%d band #%d b1 = 0x%x\n"
5118 "%s: IIR #%d band #%d b2 = 0x%x\n"
5119 "%s: IIR #%d band #%d a1 = 0x%x\n"
5120 "%s: IIR #%d band #%d a2 = 0x%x\n",
5121 __func__, iir_idx, band_idx,
5122 (uint32_t)ucontrol->value.integer.value[0],
5123 __func__, iir_idx, band_idx,
5124 (uint32_t)ucontrol->value.integer.value[1],
5125 __func__, iir_idx, band_idx,
5126 (uint32_t)ucontrol->value.integer.value[2],
5127 __func__, iir_idx, band_idx,
5128 (uint32_t)ucontrol->value.integer.value[3],
5129 __func__, iir_idx, band_idx,
5130 (uint32_t)ucontrol->value.integer.value[4]);
5131 return 0;
5132}
5133
5134static void set_iir_band_coeff(struct snd_soc_codec *codec,
5135 int iir_idx, int band_idx,
5136 uint32_t value)
5137{
5138 snd_soc_write(codec,
5139 (WCD934X_CDC_SIDETONE_IIR0_IIR_COEF_B2_CTL + 16 * iir_idx),
5140 (value & 0xFF));
5141
5142 snd_soc_write(codec,
5143 (WCD934X_CDC_SIDETONE_IIR0_IIR_COEF_B2_CTL + 16 * iir_idx),
5144 (value >> 8) & 0xFF);
5145
5146 snd_soc_write(codec,
5147 (WCD934X_CDC_SIDETONE_IIR0_IIR_COEF_B2_CTL + 16 * iir_idx),
5148 (value >> 16) & 0xFF);
5149
5150 /* Mask top 2 bits, 7-8 are reserved */
5151 snd_soc_write(codec,
5152 (WCD934X_CDC_SIDETONE_IIR0_IIR_COEF_B2_CTL + 16 * iir_idx),
5153 (value >> 24) & 0x3F);
5154}
5155
5156static int tavil_iir_band_audio_mixer_put(struct snd_kcontrol *kcontrol,
5157 struct snd_ctl_elem_value *ucontrol)
5158{
5159 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
5160 int iir_idx = ((struct soc_multi_mixer_control *)
5161 kcontrol->private_value)->reg;
5162 int band_idx = ((struct soc_multi_mixer_control *)
5163 kcontrol->private_value)->shift;
5164
5165 /*
5166 * Mask top bit it is reserved
5167 * Updates addr automatically for each B2 write
5168 */
5169 snd_soc_write(codec,
5170 (WCD934X_CDC_SIDETONE_IIR0_IIR_COEF_B1_CTL + 16 * iir_idx),
5171 (band_idx * BAND_MAX * sizeof(uint32_t)) & 0x7F);
5172
5173 set_iir_band_coeff(codec, iir_idx, band_idx,
5174 ucontrol->value.integer.value[0]);
5175 set_iir_band_coeff(codec, iir_idx, band_idx,
5176 ucontrol->value.integer.value[1]);
5177 set_iir_band_coeff(codec, iir_idx, band_idx,
5178 ucontrol->value.integer.value[2]);
5179 set_iir_band_coeff(codec, iir_idx, band_idx,
5180 ucontrol->value.integer.value[3]);
5181 set_iir_band_coeff(codec, iir_idx, band_idx,
5182 ucontrol->value.integer.value[4]);
5183
5184 pr_debug("%s: IIR #%d band #%d b0 = 0x%x\n"
5185 "%s: IIR #%d band #%d b1 = 0x%x\n"
5186 "%s: IIR #%d band #%d b2 = 0x%x\n"
5187 "%s: IIR #%d band #%d a1 = 0x%x\n"
5188 "%s: IIR #%d band #%d a2 = 0x%x\n",
5189 __func__, iir_idx, band_idx,
5190 get_iir_band_coeff(codec, iir_idx, band_idx, 0),
5191 __func__, iir_idx, band_idx,
5192 get_iir_band_coeff(codec, iir_idx, band_idx, 1),
5193 __func__, iir_idx, band_idx,
5194 get_iir_band_coeff(codec, iir_idx, band_idx, 2),
5195 __func__, iir_idx, band_idx,
5196 get_iir_band_coeff(codec, iir_idx, band_idx, 3),
5197 __func__, iir_idx, band_idx,
5198 get_iir_band_coeff(codec, iir_idx, band_idx, 4));
5199 return 0;
5200}
5201
5202static int tavil_compander_get(struct snd_kcontrol *kcontrol,
5203 struct snd_ctl_elem_value *ucontrol)
5204{
5205
5206 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
5207 int comp = ((struct soc_multi_mixer_control *)
5208 kcontrol->private_value)->shift;
5209 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
5210
5211 ucontrol->value.integer.value[0] = tavil->comp_enabled[comp];
5212 return 0;
5213}
5214
5215static int tavil_compander_put(struct snd_kcontrol *kcontrol,
5216 struct snd_ctl_elem_value *ucontrol)
5217{
5218 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
5219 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
5220 int comp = ((struct soc_multi_mixer_control *)
5221 kcontrol->private_value)->shift;
5222 int value = ucontrol->value.integer.value[0];
5223
5224 dev_dbg(codec->dev, "%s: Compander %d enable current %d, new %d\n",
5225 __func__, comp + 1, tavil->comp_enabled[comp], value);
5226 tavil->comp_enabled[comp] = value;
5227
5228 /* Any specific register configuration for compander */
5229 switch (comp) {
5230 case COMPANDER_1:
5231 /* Set Gain Source Select based on compander enable/disable */
5232 snd_soc_update_bits(codec, WCD934X_HPH_L_EN, 0x20,
5233 (value ? 0x00:0x20));
5234 break;
5235 case COMPANDER_2:
5236 snd_soc_update_bits(codec, WCD934X_HPH_R_EN, 0x20,
5237 (value ? 0x00:0x20));
5238 break;
5239 case COMPANDER_3:
5240 case COMPANDER_4:
5241 case COMPANDER_7:
5242 case COMPANDER_8:
5243 break;
5244 default:
5245 /*
5246 * if compander is not enabled for any interpolator,
5247 * it does not cause any audio failure, so do not
5248 * return error in this case, but just print a log
5249 */
5250 dev_warn(codec->dev, "%s: unknown compander: %d\n",
5251 __func__, comp);
5252 };
5253 return 0;
5254}
5255
5256static int tavil_hph_asrc_mode_put(struct snd_kcontrol *kcontrol,
5257 struct snd_ctl_elem_value *ucontrol)
5258{
5259 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
5260 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
5261 int index = -EINVAL;
5262
5263 if (!strcmp(kcontrol->id.name, "ASRC0 Output Mode"))
5264 index = ASRC0;
5265 if (!strcmp(kcontrol->id.name, "ASRC1 Output Mode"))
5266 index = ASRC1;
5267
5268 if (tavil && (index >= 0) && (index < ASRC_MAX))
5269 tavil->asrc_output_mode[index] =
5270 ucontrol->value.integer.value[0];
5271
5272 return 0;
5273}
5274
5275static int tavil_hph_asrc_mode_get(struct snd_kcontrol *kcontrol,
5276 struct snd_ctl_elem_value *ucontrol)
5277{
5278 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
5279 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
5280 int val = 0;
5281 int index = -EINVAL;
5282
5283 if (!strcmp(kcontrol->id.name, "ASRC0 Output Mode"))
5284 index = ASRC0;
5285 if (!strcmp(kcontrol->id.name, "ASRC1 Output Mode"))
5286 index = ASRC1;
5287
5288 if (tavil && (index >= 0) && (index < ASRC_MAX))
5289 val = tavil->asrc_output_mode[index];
5290
5291 ucontrol->value.integer.value[0] = val;
5292
5293 return 0;
5294}
5295
5296static int tavil_hph_idle_detect_get(struct snd_kcontrol *kcontrol,
5297 struct snd_ctl_elem_value *ucontrol)
5298{
5299 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
5300 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
5301 int val = 0;
5302
5303 if (tavil)
5304 val = tavil->idle_det_cfg.hph_idle_detect_en;
5305
5306 ucontrol->value.integer.value[0] = val;
5307
5308 return 0;
5309}
5310
5311static int tavil_hph_idle_detect_put(struct snd_kcontrol *kcontrol,
5312 struct snd_ctl_elem_value *ucontrol)
5313{
5314 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
5315 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
5316
5317 if (tavil)
5318 tavil->idle_det_cfg.hph_idle_detect_en =
5319 ucontrol->value.integer.value[0];
5320
5321 return 0;
5322}
5323
5324static int tavil_dmic_pin_mode_get(struct snd_kcontrol *kcontrol,
5325 struct snd_ctl_elem_value *ucontrol)
5326{
5327 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
5328 u16 dmic_pin;
5329 u8 reg_val, pinctl_position;
5330
5331 pinctl_position = ((struct soc_multi_mixer_control *)
5332 kcontrol->private_value)->shift;
5333
5334 dmic_pin = pinctl_position & 0x07;
5335 reg_val = snd_soc_read(codec,
5336 WCD934X_TLMM_DMIC1_CLK_PINCFG + dmic_pin - 1);
5337
5338 ucontrol->value.integer.value[0] = !!reg_val;
5339
5340 return 0;
5341}
5342
5343static int tavil_dmic_pin_mode_put(struct snd_kcontrol *kcontrol,
5344 struct snd_ctl_elem_value *ucontrol)
5345{
5346 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
5347 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
5348 u16 ctl_reg, cfg_reg, dmic_pin;
5349 u8 ctl_val, cfg_val, pinctl_position, pinctl_mode, mask;
5350
5351 /* 0- high or low; 1- high Z */
5352 pinctl_mode = ucontrol->value.integer.value[0];
5353 pinctl_position = ((struct soc_multi_mixer_control *)
5354 kcontrol->private_value)->shift;
5355
5356 switch (pinctl_position >> 3) {
5357 case 0:
5358 ctl_reg = WCD934X_TEST_DEBUG_PIN_CTL_OE_0;
5359 break;
5360 case 1:
5361 ctl_reg = WCD934X_TEST_DEBUG_PIN_CTL_OE_1;
5362 break;
5363 case 2:
5364 ctl_reg = WCD934X_TEST_DEBUG_PIN_CTL_OE_2;
5365 break;
5366 case 3:
5367 ctl_reg = WCD934X_TEST_DEBUG_PIN_CTL_OE_3;
5368 break;
5369 default:
5370 dev_err(codec->dev, "%s: Invalid pinctl position = %d\n",
5371 __func__, pinctl_position);
5372 return -EINVAL;
5373 }
5374
5375 ctl_val = ~(pinctl_mode << (pinctl_position & 0x07));
5376 mask = 1 << (pinctl_position & 0x07);
5377 snd_soc_update_bits(codec, ctl_reg, mask, ctl_val);
5378
5379 dmic_pin = pinctl_position & 0x07;
5380 cfg_reg = WCD934X_TLMM_DMIC1_CLK_PINCFG + dmic_pin - 1;
5381 if (pinctl_mode) {
5382 if (tavil->intf_type == WCD9XXX_INTERFACE_TYPE_SLIMBUS)
5383 cfg_val = 0x6;
5384 else
5385 cfg_val = 0xD;
5386 } else
5387 cfg_val = 0;
5388 snd_soc_update_bits(codec, cfg_reg, 0x1F, cfg_val);
5389
5390 dev_dbg(codec->dev, "%s: reg=0x%x mask=0x%x val=%d reg=0x%x val=%d\n",
5391 __func__, ctl_reg, mask, ctl_val, cfg_reg, cfg_val);
5392
5393 return 0;
5394}
5395
5396static int tavil_amic_pwr_lvl_get(struct snd_kcontrol *kcontrol,
5397 struct snd_ctl_elem_value *ucontrol)
5398{
5399 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
Phani Kumar Uppalapatiafdc5a82016-12-16 17:06:27 -08005400 u16 amic_reg = 0;
Banajit Goswamide8271c2017-01-18 00:28:59 -08005401
5402 if (!strcmp(kcontrol->id.name, "AMIC_1_2 PWR MODE"))
5403 amic_reg = WCD934X_ANA_AMIC1;
5404 if (!strcmp(kcontrol->id.name, "AMIC_3_4 PWR MODE"))
5405 amic_reg = WCD934X_ANA_AMIC3;
Banajit Goswamide8271c2017-01-18 00:28:59 -08005406
Phani Kumar Uppalapatiafdc5a82016-12-16 17:06:27 -08005407 if (amic_reg)
5408 ucontrol->value.integer.value[0] =
5409 (snd_soc_read(codec, amic_reg) &
5410 WCD934X_AMIC_PWR_LVL_MASK) >>
5411 WCD934X_AMIC_PWR_LVL_SHIFT;
Banajit Goswamide8271c2017-01-18 00:28:59 -08005412 return 0;
5413}
5414
5415static int tavil_amic_pwr_lvl_put(struct snd_kcontrol *kcontrol,
5416 struct snd_ctl_elem_value *ucontrol)
5417{
5418 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
5419 u32 mode_val;
Phani Kumar Uppalapatiafdc5a82016-12-16 17:06:27 -08005420 u16 amic_reg = 0;
Banajit Goswamide8271c2017-01-18 00:28:59 -08005421
5422 mode_val = ucontrol->value.enumerated.item[0];
5423
5424 dev_dbg(codec->dev, "%s: mode: %d\n", __func__, mode_val);
5425
5426 if (!strcmp(kcontrol->id.name, "AMIC_1_2 PWR MODE"))
5427 amic_reg = WCD934X_ANA_AMIC1;
5428 if (!strcmp(kcontrol->id.name, "AMIC_3_4 PWR MODE"))
5429 amic_reg = WCD934X_ANA_AMIC3;
Banajit Goswamide8271c2017-01-18 00:28:59 -08005430
Phani Kumar Uppalapatiafdc5a82016-12-16 17:06:27 -08005431 if (amic_reg)
5432 snd_soc_update_bits(codec, amic_reg, WCD934X_AMIC_PWR_LVL_MASK,
5433 mode_val << WCD934X_AMIC_PWR_LVL_SHIFT);
Banajit Goswamide8271c2017-01-18 00:28:59 -08005434 return 0;
5435}
5436
5437static const char *const tavil_conn_mad_text[] = {
5438 "NOTUSED1", "ADC1", "ADC2", "ADC3", "ADC4", "NOTUSED5",
5439 "NOTUSED6", "NOTUSED2", "DMIC0", "DMIC1", "DMIC2", "DMIC3",
5440 "DMIC4", "DMIC5", "NOTUSED3", "NOTUSED4"
5441};
5442
5443static const struct soc_enum tavil_conn_mad_enum =
5444 SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(tavil_conn_mad_text),
5445 tavil_conn_mad_text);
5446
5447static int tavil_mad_input_get(struct snd_kcontrol *kcontrol,
5448 struct snd_ctl_elem_value *ucontrol)
5449{
5450 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
5451 u8 tavil_mad_input;
5452
5453 tavil_mad_input = snd_soc_read(codec, WCD934X_SOC_MAD_INP_SEL) & 0x0F;
5454 ucontrol->value.integer.value[0] = tavil_mad_input;
5455
5456 dev_dbg(codec->dev, "%s: tavil_mad_input = %s\n", __func__,
5457 tavil_conn_mad_text[tavil_mad_input]);
5458
5459 return 0;
5460}
5461
5462static int tavil_mad_input_put(struct snd_kcontrol *kcontrol,
5463 struct snd_ctl_elem_value *ucontrol)
5464{
5465 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
5466 struct snd_soc_card *card = codec->component.card;
5467 u8 tavil_mad_input;
5468 char mad_amic_input_widget[6];
5469 const char *mad_input_widget;
5470 const char *source_widget = NULL;
5471 u32 adc, i, mic_bias_found = 0;
5472 int ret = 0;
5473 char *mad_input;
5474 bool is_adc2_input = false;
5475
5476 tavil_mad_input = ucontrol->value.integer.value[0];
5477
Karthikeyan Mani5b976ab2016-12-12 11:04:01 -08005478 if (tavil_mad_input >= sizeof(tavil_conn_mad_text)/
5479 sizeof(tavil_conn_mad_text[0])) {
5480 dev_err(codec->dev,
5481 "%s: tavil_mad_input = %d out of bounds\n",
5482 __func__, tavil_mad_input);
5483 return -EINVAL;
5484 }
5485
Banajit Goswamide8271c2017-01-18 00:28:59 -08005486 if (strnstr(tavil_conn_mad_text[tavil_mad_input], "NOTUSED",
5487 sizeof("NOTUSED"))) {
5488 dev_dbg(codec->dev,
5489 "%s: Unsupported tavil_mad_input = %s\n",
5490 __func__, tavil_conn_mad_text[tavil_mad_input]);
5491 /* Make sure the MAD register is updated */
5492 snd_soc_update_bits(codec, WCD934X_ANA_MAD_SETUP,
5493 0x88, 0x00);
5494 return -EINVAL;
5495 }
5496
5497 if (strnstr(tavil_conn_mad_text[tavil_mad_input],
5498 "ADC", sizeof("ADC"))) {
5499 mad_input = strpbrk(tavil_conn_mad_text[tavil_mad_input],
5500 "1234");
5501 if (!mad_input) {
5502 dev_err(codec->dev, "%s: Invalid MAD input %s\n",
5503 __func__, tavil_conn_mad_text[tavil_mad_input]);
5504 return -EINVAL;
5505 }
5506
5507 ret = kstrtouint(mad_input, 10, &adc);
5508 if ((ret < 0) || (adc > 4)) {
5509 dev_err(codec->dev, "%s: Invalid ADC = %s\n", __func__,
5510 tavil_conn_mad_text[tavil_mad_input]);
5511 return -EINVAL;
5512 }
5513
5514 /*AMIC4 and AMIC5 share ADC4*/
5515 if ((adc == 4) &&
5516 (snd_soc_read(codec, WCD934X_TX_NEW_AMIC_4_5_SEL) & 0x10))
5517 adc = 5;
5518
5519 snprintf(mad_amic_input_widget, 6, "%s%u", "AMIC", adc);
5520
5521 mad_input_widget = mad_amic_input_widget;
5522 if (adc == 2)
5523 is_adc2_input = true;
5524 } else {
5525 /* DMIC type input widget*/
5526 mad_input_widget = tavil_conn_mad_text[tavil_mad_input];
5527 }
5528
5529 dev_dbg(codec->dev,
5530 "%s: tavil input widget = %s, adc_input = %s\n", __func__,
5531 mad_input_widget, is_adc2_input ? "true" : "false");
5532
5533 for (i = 0; i < card->num_of_dapm_routes; i++) {
5534 if (!strcmp(card->of_dapm_routes[i].sink, mad_input_widget)) {
5535 source_widget = card->of_dapm_routes[i].source;
5536 if (!source_widget) {
5537 dev_err(codec->dev,
5538 "%s: invalid source widget\n",
5539 __func__);
5540 return -EINVAL;
5541 }
5542
5543 if (strnstr(source_widget,
5544 "MIC BIAS1", sizeof("MIC BIAS1"))) {
5545 mic_bias_found = 1;
5546 break;
5547 } else if (strnstr(source_widget,
5548 "MIC BIAS2", sizeof("MIC BIAS2"))) {
5549 mic_bias_found = 2;
5550 break;
5551 } else if (strnstr(source_widget,
5552 "MIC BIAS3", sizeof("MIC BIAS3"))) {
5553 mic_bias_found = 3;
5554 break;
5555 } else if (strnstr(source_widget,
5556 "MIC BIAS4", sizeof("MIC BIAS4"))) {
5557 mic_bias_found = 4;
5558 break;
5559 }
5560 }
5561 }
5562
5563 if (!mic_bias_found) {
5564 dev_err(codec->dev, "%s: mic bias not found for input %s\n",
5565 __func__, mad_input_widget);
5566 return -EINVAL;
5567 }
5568
5569 dev_dbg(codec->dev, "%s: mic_bias found = %d\n", __func__,
5570 mic_bias_found);
5571
5572 snd_soc_update_bits(codec, WCD934X_SOC_MAD_INP_SEL,
5573 0x0F, tavil_mad_input);
5574 snd_soc_update_bits(codec, WCD934X_ANA_MAD_SETUP,
5575 0x07, mic_bias_found);
5576 /* for adc2 input, mad should be in micbias mode with BG enabled */
5577 if (is_adc2_input)
5578 snd_soc_update_bits(codec, WCD934X_ANA_MAD_SETUP,
5579 0x88, 0x88);
5580 else
5581 snd_soc_update_bits(codec, WCD934X_ANA_MAD_SETUP,
5582 0x88, 0x00);
5583 return 0;
5584}
5585
5586static int tavil_ear_pa_gain_get(struct snd_kcontrol *kcontrol,
5587 struct snd_ctl_elem_value *ucontrol)
5588{
5589 u8 ear_pa_gain;
5590 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
5591
5592 ear_pa_gain = snd_soc_read(codec, WCD934X_ANA_EAR);
5593
5594 ear_pa_gain = (ear_pa_gain & 0x70) >> 4;
5595
5596 ucontrol->value.integer.value[0] = ear_pa_gain;
5597
5598 dev_dbg(codec->dev, "%s: ear_pa_gain = 0x%x\n", __func__,
5599 ear_pa_gain);
5600
5601 return 0;
5602}
5603
5604static int tavil_ear_pa_gain_put(struct snd_kcontrol *kcontrol,
5605 struct snd_ctl_elem_value *ucontrol)
5606{
5607 u8 ear_pa_gain;
5608 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
5609
5610 dev_dbg(codec->dev, "%s: ucontrol->value.integer.value[0] = %ld\n",
5611 __func__, ucontrol->value.integer.value[0]);
5612
5613 ear_pa_gain = ucontrol->value.integer.value[0] << 4;
5614
5615 snd_soc_update_bits(codec, WCD934X_ANA_EAR, 0x70, ear_pa_gain);
5616 return 0;
5617}
5618
5619static int tavil_ear_spkr_pa_gain_get(struct snd_kcontrol *kcontrol,
5620 struct snd_ctl_elem_value *ucontrol)
5621{
5622 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
5623 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
5624
5625 ucontrol->value.integer.value[0] = tavil->ear_spkr_gain;
5626
5627 dev_dbg(codec->dev, "%s: ucontrol->value.integer.value[0] = %ld\n",
5628 __func__, ucontrol->value.integer.value[0]);
5629
5630 return 0;
5631}
5632
5633static int tavil_ear_spkr_pa_gain_put(struct snd_kcontrol *kcontrol,
5634 struct snd_ctl_elem_value *ucontrol)
5635{
5636 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
5637 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
5638
5639 tavil->ear_spkr_gain = ucontrol->value.integer.value[0];
5640
5641 dev_dbg(codec->dev, "%s: gain = %d\n", __func__, tavil->ear_spkr_gain);
5642
5643 return 0;
5644}
5645
5646static int tavil_rx_hph_mode_get(struct snd_kcontrol *kcontrol,
5647 struct snd_ctl_elem_value *ucontrol)
5648{
5649 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
5650 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
5651
5652 ucontrol->value.integer.value[0] = tavil->hph_mode;
5653 return 0;
5654}
5655
5656static int tavil_rx_hph_mode_put(struct snd_kcontrol *kcontrol,
5657 struct snd_ctl_elem_value *ucontrol)
5658{
5659 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
5660 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
5661 u32 mode_val;
5662
5663 mode_val = ucontrol->value.enumerated.item[0];
5664
5665 dev_dbg(codec->dev, "%s: mode: %d\n", __func__, mode_val);
5666
5667 if (mode_val == 0) {
5668 dev_warn(codec->dev, "%s:Invalid HPH Mode, default to Cls-H LOHiFi\n",
5669 __func__);
5670 mode_val = CLS_H_LOHIFI;
5671 }
5672 tavil->hph_mode = mode_val;
5673 return 0;
5674}
5675
5676static const char * const rx_hph_mode_mux_text[] = {
5677 "CLS_H_INVALID", "CLS_H_HIFI", "CLS_H_LP", "CLS_AB", "CLS_H_LOHIFI",
5678 "CLS_H_ULP", "CLS_AB_HIFI",
5679};
5680
5681static const struct soc_enum rx_hph_mode_mux_enum =
5682 SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(rx_hph_mode_mux_text),
5683 rx_hph_mode_mux_text);
5684
5685static const char *const tavil_anc_func_text[] = {"OFF", "ON"};
5686static const struct soc_enum tavil_anc_func_enum =
5687 SOC_ENUM_SINGLE_EXT(2, tavil_anc_func_text);
5688
5689/* Cutoff frequency for high pass filter */
5690static const char * const cf_text[] = {
5691 "CF_NEG_3DB_4HZ", "CF_NEG_3DB_75HZ", "CF_NEG_3DB_150HZ"
5692};
5693
5694static const char * const rx_cf_text[] = {
5695 "CF_NEG_3DB_4HZ", "CF_NEG_3DB_75HZ", "CF_NEG_3DB_150HZ",
5696 "CF_NEG_3DB_0P48HZ"
5697};
5698
5699static const char * const amic_pwr_lvl_text[] = {
5700 "LOW_PWR", "DEFAULT", "HIGH_PERF"
5701};
5702
5703static const char * const hph_idle_detect_text[] = {
5704 "OFF", "ON"
5705};
5706
5707static const char * const asrc_mode_text[] = {
5708 "INT", "FRAC"
5709};
5710
5711static const char * const tavil_ear_pa_gain_text[] = {
5712 "G_6_DB", "G_4P5_DB", "G_3_DB", "G_1P5_DB",
5713 "G_0_DB", "G_M2P5_DB", "UNDEFINED", "G_M12_DB"
5714};
5715
5716static const char * const tavil_ear_spkr_pa_gain_text[] = {
5717 "G_DEFAULT", "G_0_DB", "G_1_DB", "G_2_DB", "G_3_DB",
5718 "G_4_DB", "G_5_DB", "G_6_DB"
5719};
5720
5721static SOC_ENUM_SINGLE_EXT_DECL(tavil_ear_pa_gain_enum, tavil_ear_pa_gain_text);
5722static SOC_ENUM_SINGLE_EXT_DECL(tavil_ear_spkr_pa_gain_enum,
5723 tavil_ear_spkr_pa_gain_text);
5724static SOC_ENUM_SINGLE_EXT_DECL(amic_pwr_lvl_enum, amic_pwr_lvl_text);
5725static SOC_ENUM_SINGLE_EXT_DECL(hph_idle_detect_enum, hph_idle_detect_text);
5726static SOC_ENUM_SINGLE_EXT_DECL(asrc_mode_enum, asrc_mode_text);
5727static SOC_ENUM_SINGLE_DECL(cf_dec0_enum, WCD934X_CDC_TX0_TX_PATH_CFG0, 5,
5728 cf_text);
5729static SOC_ENUM_SINGLE_DECL(cf_dec1_enum, WCD934X_CDC_TX1_TX_PATH_CFG0, 5,
5730 cf_text);
5731static SOC_ENUM_SINGLE_DECL(cf_dec2_enum, WCD934X_CDC_TX2_TX_PATH_CFG0, 5,
5732 cf_text);
5733static SOC_ENUM_SINGLE_DECL(cf_dec3_enum, WCD934X_CDC_TX3_TX_PATH_CFG0, 5,
5734 cf_text);
5735static SOC_ENUM_SINGLE_DECL(cf_dec4_enum, WCD934X_CDC_TX4_TX_PATH_CFG0, 5,
5736 cf_text);
5737static SOC_ENUM_SINGLE_DECL(cf_dec5_enum, WCD934X_CDC_TX5_TX_PATH_CFG0, 5,
5738 cf_text);
5739static SOC_ENUM_SINGLE_DECL(cf_dec6_enum, WCD934X_CDC_TX6_TX_PATH_CFG0, 5,
5740 cf_text);
5741static SOC_ENUM_SINGLE_DECL(cf_dec7_enum, WCD934X_CDC_TX7_TX_PATH_CFG0, 5,
5742 cf_text);
5743static SOC_ENUM_SINGLE_DECL(cf_dec8_enum, WCD934X_CDC_TX8_TX_PATH_CFG0, 5,
5744 cf_text);
5745static SOC_ENUM_SINGLE_DECL(cf_int0_1_enum, WCD934X_CDC_RX0_RX_PATH_CFG2, 0,
5746 rx_cf_text);
5747static SOC_ENUM_SINGLE_DECL(cf_int0_2_enum, WCD934X_CDC_RX0_RX_PATH_MIX_CFG, 2,
5748 rx_cf_text);
5749static SOC_ENUM_SINGLE_DECL(cf_int1_1_enum, WCD934X_CDC_RX1_RX_PATH_CFG2, 0,
5750 rx_cf_text);
5751static SOC_ENUM_SINGLE_DECL(cf_int1_2_enum, WCD934X_CDC_RX1_RX_PATH_MIX_CFG, 2,
5752 rx_cf_text);
5753static SOC_ENUM_SINGLE_DECL(cf_int2_1_enum, WCD934X_CDC_RX2_RX_PATH_CFG2, 0,
5754 rx_cf_text);
5755static SOC_ENUM_SINGLE_DECL(cf_int2_2_enum, WCD934X_CDC_RX2_RX_PATH_MIX_CFG, 2,
5756 rx_cf_text);
5757static SOC_ENUM_SINGLE_DECL(cf_int3_1_enum, WCD934X_CDC_RX3_RX_PATH_CFG2, 0,
5758 rx_cf_text);
5759static SOC_ENUM_SINGLE_DECL(cf_int3_2_enum, WCD934X_CDC_RX3_RX_PATH_MIX_CFG, 2,
5760 rx_cf_text);
5761static SOC_ENUM_SINGLE_DECL(cf_int4_1_enum, WCD934X_CDC_RX4_RX_PATH_CFG2, 0,
5762 rx_cf_text);
5763static SOC_ENUM_SINGLE_DECL(cf_int4_2_enum, WCD934X_CDC_RX4_RX_PATH_MIX_CFG, 2,
5764 rx_cf_text);
5765static SOC_ENUM_SINGLE_DECL(cf_int7_1_enum, WCD934X_CDC_RX7_RX_PATH_CFG2, 0,
5766 rx_cf_text);
5767static SOC_ENUM_SINGLE_DECL(cf_int7_2_enum, WCD934X_CDC_RX7_RX_PATH_MIX_CFG, 2,
5768 rx_cf_text);
5769static SOC_ENUM_SINGLE_DECL(cf_int8_1_enum, WCD934X_CDC_RX8_RX_PATH_CFG2, 0,
5770 rx_cf_text);
5771static SOC_ENUM_SINGLE_DECL(cf_int8_2_enum, WCD934X_CDC_RX8_RX_PATH_MIX_CFG, 2,
5772 rx_cf_text);
5773
5774static const struct snd_kcontrol_new tavil_snd_controls[] = {
5775 SOC_ENUM_EXT("EAR PA Gain", tavil_ear_pa_gain_enum,
5776 tavil_ear_pa_gain_get, tavil_ear_pa_gain_put),
5777 SOC_ENUM_EXT("EAR SPKR PA Gain", tavil_ear_spkr_pa_gain_enum,
5778 tavil_ear_spkr_pa_gain_get, tavil_ear_spkr_pa_gain_put),
5779 SOC_SINGLE_TLV("HPHL Volume", WCD934X_HPH_L_EN, 0, 20, 1, line_gain),
5780 SOC_SINGLE_TLV("HPHR Volume", WCD934X_HPH_R_EN, 0, 20, 1, line_gain),
5781 SOC_SINGLE_TLV("LINEOUT1 Volume", WCD934X_DIFF_LO_LO1_COMPANDER,
5782 3, 16, 1, line_gain),
5783 SOC_SINGLE_TLV("LINEOUT2 Volume", WCD934X_DIFF_LO_LO2_COMPANDER,
5784 3, 16, 1, line_gain),
5785 SOC_SINGLE_TLV("ADC1 Volume", WCD934X_ANA_AMIC1, 0, 20, 0, analog_gain),
5786 SOC_SINGLE_TLV("ADC2 Volume", WCD934X_ANA_AMIC2, 0, 20, 0, analog_gain),
5787 SOC_SINGLE_TLV("ADC3 Volume", WCD934X_ANA_AMIC3, 0, 20, 0, analog_gain),
5788 SOC_SINGLE_TLV("ADC4 Volume", WCD934X_ANA_AMIC4, 0, 20, 0, analog_gain),
5789
5790 SOC_SINGLE_SX_TLV("RX0 Digital Volume", WCD934X_CDC_RX0_RX_VOL_CTL,
5791 0, -84, 40, digital_gain), /* -84dB min - 40dB max */
5792 SOC_SINGLE_SX_TLV("RX1 Digital Volume", WCD934X_CDC_RX1_RX_VOL_CTL,
5793 0, -84, 40, digital_gain),
5794 SOC_SINGLE_SX_TLV("RX2 Digital Volume", WCD934X_CDC_RX2_RX_VOL_CTL,
5795 0, -84, 40, digital_gain),
5796 SOC_SINGLE_SX_TLV("RX3 Digital Volume", WCD934X_CDC_RX3_RX_VOL_CTL,
5797 0, -84, 40, digital_gain),
5798 SOC_SINGLE_SX_TLV("RX4 Digital Volume", WCD934X_CDC_RX4_RX_VOL_CTL,
5799 0, -84, 40, digital_gain),
5800 SOC_SINGLE_SX_TLV("RX7 Digital Volume", WCD934X_CDC_RX7_RX_VOL_CTL,
5801 0, -84, 40, digital_gain),
5802 SOC_SINGLE_SX_TLV("RX8 Digital Volume", WCD934X_CDC_RX8_RX_VOL_CTL,
5803 0, -84, 40, digital_gain),
5804 SOC_SINGLE_SX_TLV("RX0 Mix Digital Volume",
5805 WCD934X_CDC_RX0_RX_VOL_MIX_CTL, 0, -84, 40, digital_gain),
5806 SOC_SINGLE_SX_TLV("RX1 Mix Digital Volume",
5807 WCD934X_CDC_RX1_RX_VOL_MIX_CTL, 0, -84, 40, digital_gain),
5808 SOC_SINGLE_SX_TLV("RX2 Mix Digital Volume",
5809 WCD934X_CDC_RX2_RX_VOL_MIX_CTL, 0, -84, 40, digital_gain),
5810 SOC_SINGLE_SX_TLV("RX3 Mix Digital Volume",
5811 WCD934X_CDC_RX3_RX_VOL_MIX_CTL, 0, -84, 40, digital_gain),
5812 SOC_SINGLE_SX_TLV("RX4 Mix Digital Volume",
5813 WCD934X_CDC_RX4_RX_VOL_MIX_CTL, 0, -84, 40, digital_gain),
5814 SOC_SINGLE_SX_TLV("RX7 Mix Digital Volume",
5815 WCD934X_CDC_RX7_RX_VOL_MIX_CTL, 0, -84, 40, digital_gain),
5816 SOC_SINGLE_SX_TLV("RX8 Mix Digital Volume",
5817 WCD934X_CDC_RX8_RX_VOL_MIX_CTL, 0, -84, 40, digital_gain),
5818
5819 SOC_SINGLE_SX_TLV("DEC0 Volume", WCD934X_CDC_TX0_TX_VOL_CTL, 0,
5820 -84, 40, digital_gain),
5821 SOC_SINGLE_SX_TLV("DEC1 Volume", WCD934X_CDC_TX1_TX_VOL_CTL, 0,
5822 -84, 40, digital_gain),
5823 SOC_SINGLE_SX_TLV("DEC2 Volume", WCD934X_CDC_TX2_TX_VOL_CTL, 0,
5824 -84, 40, digital_gain),
5825 SOC_SINGLE_SX_TLV("DEC3 Volume", WCD934X_CDC_TX3_TX_VOL_CTL, 0,
5826 -84, 40, digital_gain),
5827 SOC_SINGLE_SX_TLV("DEC4 Volume", WCD934X_CDC_TX4_TX_VOL_CTL, 0,
5828 -84, 40, digital_gain),
5829 SOC_SINGLE_SX_TLV("DEC5 Volume", WCD934X_CDC_TX5_TX_VOL_CTL, 0,
5830 -84, 40, digital_gain),
5831 SOC_SINGLE_SX_TLV("DEC6 Volume", WCD934X_CDC_TX6_TX_VOL_CTL, 0,
5832 -84, 40, digital_gain),
5833 SOC_SINGLE_SX_TLV("DEC7 Volume", WCD934X_CDC_TX7_TX_VOL_CTL, 0,
5834 -84, 40, digital_gain),
5835 SOC_SINGLE_SX_TLV("DEC8 Volume", WCD934X_CDC_TX8_TX_VOL_CTL, 0,
5836 -84, 40, digital_gain),
5837
5838 SOC_SINGLE_SX_TLV("IIR0 INP0 Volume",
5839 WCD934X_CDC_SIDETONE_IIR0_IIR_GAIN_B1_CTL, 0, -84, 40,
5840 digital_gain),
5841 SOC_SINGLE_SX_TLV("IIR0 INP1 Volume",
5842 WCD934X_CDC_SIDETONE_IIR0_IIR_GAIN_B2_CTL, 0, -84, 40,
5843 digital_gain),
5844 SOC_SINGLE_SX_TLV("IIR0 INP2 Volume",
5845 WCD934X_CDC_SIDETONE_IIR0_IIR_GAIN_B3_CTL, 0, -84, 40,
5846 digital_gain),
5847 SOC_SINGLE_SX_TLV("IIR0 INP3 Volume",
5848 WCD934X_CDC_SIDETONE_IIR0_IIR_GAIN_B4_CTL, 0, -84, 40,
5849 digital_gain),
5850 SOC_SINGLE_SX_TLV("IIR1 INP0 Volume",
5851 WCD934X_CDC_SIDETONE_IIR1_IIR_GAIN_B1_CTL, 0, -84, 40,
5852 digital_gain),
5853 SOC_SINGLE_SX_TLV("IIR1 INP1 Volume",
5854 WCD934X_CDC_SIDETONE_IIR1_IIR_GAIN_B2_CTL, 0, -84, 40,
5855 digital_gain),
5856 SOC_SINGLE_SX_TLV("IIR1 INP2 Volume",
5857 WCD934X_CDC_SIDETONE_IIR1_IIR_GAIN_B3_CTL, 0, -84, 40,
5858 digital_gain),
5859 SOC_SINGLE_SX_TLV("IIR1 INP3 Volume",
5860 WCD934X_CDC_SIDETONE_IIR1_IIR_GAIN_B4_CTL, 0, -84, 40,
5861 digital_gain),
5862
5863 SOC_SINGLE_EXT("ANC Slot", SND_SOC_NOPM, 0, 100, 0, tavil_get_anc_slot,
5864 tavil_put_anc_slot),
5865 SOC_ENUM_EXT("ANC Function", tavil_anc_func_enum, tavil_get_anc_func,
5866 tavil_put_anc_func),
5867
5868 SOC_ENUM("TX0 HPF cut off", cf_dec0_enum),
5869 SOC_ENUM("TX1 HPF cut off", cf_dec1_enum),
5870 SOC_ENUM("TX2 HPF cut off", cf_dec2_enum),
5871 SOC_ENUM("TX3 HPF cut off", cf_dec3_enum),
5872 SOC_ENUM("TX4 HPF cut off", cf_dec4_enum),
5873 SOC_ENUM("TX5 HPF cut off", cf_dec5_enum),
5874 SOC_ENUM("TX6 HPF cut off", cf_dec6_enum),
5875 SOC_ENUM("TX7 HPF cut off", cf_dec7_enum),
5876 SOC_ENUM("TX8 HPF cut off", cf_dec8_enum),
5877
5878 SOC_ENUM("RX INT0_1 HPF cut off", cf_int0_1_enum),
5879 SOC_ENUM("RX INT0_2 HPF cut off", cf_int0_2_enum),
5880 SOC_ENUM("RX INT1_1 HPF cut off", cf_int1_1_enum),
5881 SOC_ENUM("RX INT1_2 HPF cut off", cf_int1_2_enum),
5882 SOC_ENUM("RX INT2_1 HPF cut off", cf_int2_1_enum),
5883 SOC_ENUM("RX INT2_2 HPF cut off", cf_int2_2_enum),
5884 SOC_ENUM("RX INT3_1 HPF cut off", cf_int3_1_enum),
5885 SOC_ENUM("RX INT3_2 HPF cut off", cf_int3_2_enum),
5886 SOC_ENUM("RX INT4_1 HPF cut off", cf_int4_1_enum),
5887 SOC_ENUM("RX INT4_2 HPF cut off", cf_int4_2_enum),
5888 SOC_ENUM("RX INT7_1 HPF cut off", cf_int7_1_enum),
5889 SOC_ENUM("RX INT7_2 HPF cut off", cf_int7_2_enum),
5890 SOC_ENUM("RX INT8_1 HPF cut off", cf_int8_1_enum),
5891 SOC_ENUM("RX INT8_2 HPF cut off", cf_int8_2_enum),
5892
5893 SOC_ENUM_EXT("RX HPH Mode", rx_hph_mode_mux_enum,
5894 tavil_rx_hph_mode_get, tavil_rx_hph_mode_put),
5895
5896 SOC_SINGLE_EXT("IIR0 Enable Band1", IIR0, BAND1, 1, 0,
5897 tavil_iir_enable_audio_mixer_get,
5898 tavil_iir_enable_audio_mixer_put),
5899 SOC_SINGLE_EXT("IIR0 Enable Band2", IIR0, BAND2, 1, 0,
5900 tavil_iir_enable_audio_mixer_get,
5901 tavil_iir_enable_audio_mixer_put),
5902 SOC_SINGLE_EXT("IIR0 Enable Band3", IIR0, BAND3, 1, 0,
5903 tavil_iir_enable_audio_mixer_get,
5904 tavil_iir_enable_audio_mixer_put),
5905 SOC_SINGLE_EXT("IIR0 Enable Band4", IIR0, BAND4, 1, 0,
5906 tavil_iir_enable_audio_mixer_get,
5907 tavil_iir_enable_audio_mixer_put),
5908 SOC_SINGLE_EXT("IIR0 Enable Band5", IIR0, BAND5, 1, 0,
5909 tavil_iir_enable_audio_mixer_get,
5910 tavil_iir_enable_audio_mixer_put),
5911 SOC_SINGLE_EXT("IIR1 Enable Band1", IIR1, BAND1, 1, 0,
5912 tavil_iir_enable_audio_mixer_get,
5913 tavil_iir_enable_audio_mixer_put),
5914 SOC_SINGLE_EXT("IIR1 Enable Band2", IIR1, BAND2, 1, 0,
5915 tavil_iir_enable_audio_mixer_get,
5916 tavil_iir_enable_audio_mixer_put),
5917 SOC_SINGLE_EXT("IIR1 Enable Band3", IIR1, BAND3, 1, 0,
5918 tavil_iir_enable_audio_mixer_get,
5919 tavil_iir_enable_audio_mixer_put),
5920 SOC_SINGLE_EXT("IIR1 Enable Band4", IIR1, BAND4, 1, 0,
5921 tavil_iir_enable_audio_mixer_get,
5922 tavil_iir_enable_audio_mixer_put),
5923 SOC_SINGLE_EXT("IIR1 Enable Band5", IIR1, BAND5, 1, 0,
5924 tavil_iir_enable_audio_mixer_get,
5925 tavil_iir_enable_audio_mixer_put),
5926
5927 SOC_SINGLE_MULTI_EXT("IIR0 Band1", IIR0, BAND1, 255, 0, 5,
5928 tavil_iir_band_audio_mixer_get, tavil_iir_band_audio_mixer_put),
5929 SOC_SINGLE_MULTI_EXT("IIR0 Band2", IIR0, BAND2, 255, 0, 5,
5930 tavil_iir_band_audio_mixer_get, tavil_iir_band_audio_mixer_put),
5931 SOC_SINGLE_MULTI_EXT("IIR0 Band3", IIR0, BAND3, 255, 0, 5,
5932 tavil_iir_band_audio_mixer_get, tavil_iir_band_audio_mixer_put),
5933 SOC_SINGLE_MULTI_EXT("IIR0 Band4", IIR0, BAND4, 255, 0, 5,
5934 tavil_iir_band_audio_mixer_get, tavil_iir_band_audio_mixer_put),
5935 SOC_SINGLE_MULTI_EXT("IIR0 Band5", IIR0, BAND5, 255, 0, 5,
5936 tavil_iir_band_audio_mixer_get, tavil_iir_band_audio_mixer_put),
5937 SOC_SINGLE_MULTI_EXT("IIR1 Band1", IIR1, BAND1, 255, 0, 5,
5938 tavil_iir_band_audio_mixer_get, tavil_iir_band_audio_mixer_put),
5939 SOC_SINGLE_MULTI_EXT("IIR1 Band2", IIR1, BAND2, 255, 0, 5,
5940 tavil_iir_band_audio_mixer_get, tavil_iir_band_audio_mixer_put),
5941 SOC_SINGLE_MULTI_EXT("IIR1 Band3", IIR1, BAND3, 255, 0, 5,
5942 tavil_iir_band_audio_mixer_get, tavil_iir_band_audio_mixer_put),
5943 SOC_SINGLE_MULTI_EXT("IIR1 Band4", IIR1, BAND4, 255, 0, 5,
5944 tavil_iir_band_audio_mixer_get, tavil_iir_band_audio_mixer_put),
5945 SOC_SINGLE_MULTI_EXT("IIR1 Band5", IIR1, BAND5, 255, 0, 5,
5946 tavil_iir_band_audio_mixer_get, tavil_iir_band_audio_mixer_put),
5947
5948 SOC_SINGLE_EXT("COMP1 Switch", SND_SOC_NOPM, COMPANDER_1, 1, 0,
5949 tavil_compander_get, tavil_compander_put),
5950 SOC_SINGLE_EXT("COMP2 Switch", SND_SOC_NOPM, COMPANDER_2, 1, 0,
5951 tavil_compander_get, tavil_compander_put),
5952 SOC_SINGLE_EXT("COMP3 Switch", SND_SOC_NOPM, COMPANDER_3, 1, 0,
5953 tavil_compander_get, tavil_compander_put),
5954 SOC_SINGLE_EXT("COMP4 Switch", SND_SOC_NOPM, COMPANDER_4, 1, 0,
5955 tavil_compander_get, tavil_compander_put),
5956 SOC_SINGLE_EXT("COMP7 Switch", SND_SOC_NOPM, COMPANDER_7, 1, 0,
5957 tavil_compander_get, tavil_compander_put),
5958 SOC_SINGLE_EXT("COMP8 Switch", SND_SOC_NOPM, COMPANDER_8, 1, 0,
5959 tavil_compander_get, tavil_compander_put),
5960
5961 SOC_ENUM_EXT("ASRC0 Output Mode", asrc_mode_enum,
5962 tavil_hph_asrc_mode_get, tavil_hph_asrc_mode_put),
5963 SOC_ENUM_EXT("ASRC1 Output Mode", asrc_mode_enum,
5964 tavil_hph_asrc_mode_get, tavil_hph_asrc_mode_put),
5965
5966 SOC_ENUM_EXT("HPH Idle Detect", hph_idle_detect_enum,
5967 tavil_hph_idle_detect_get, tavil_hph_idle_detect_put),
5968
5969 SOC_ENUM_EXT("MAD Input", tavil_conn_mad_enum,
5970 tavil_mad_input_get, tavil_mad_input_put),
5971
5972 SOC_SINGLE_EXT("DMIC1_CLK_PIN_MODE", SND_SOC_NOPM, 17, 1, 0,
5973 tavil_dmic_pin_mode_get, tavil_dmic_pin_mode_put),
5974
5975 SOC_SINGLE_EXT("DMIC1_DATA_PIN_MODE", SND_SOC_NOPM, 18, 1, 0,
5976 tavil_dmic_pin_mode_get, tavil_dmic_pin_mode_put),
5977
5978 SOC_SINGLE_EXT("DMIC2_CLK_PIN_MODE", SND_SOC_NOPM, 19, 1, 0,
5979 tavil_dmic_pin_mode_get, tavil_dmic_pin_mode_put),
5980
5981 SOC_SINGLE_EXT("DMIC2_DATA_PIN_MODE", SND_SOC_NOPM, 20, 1, 0,
5982 tavil_dmic_pin_mode_get, tavil_dmic_pin_mode_put),
5983
5984 SOC_SINGLE_EXT("DMIC3_CLK_PIN_MODE", SND_SOC_NOPM, 21, 1, 0,
5985 tavil_dmic_pin_mode_get, tavil_dmic_pin_mode_put),
5986
5987 SOC_SINGLE_EXT("DMIC3_DATA_PIN_MODE", SND_SOC_NOPM, 22, 1, 0,
5988 tavil_dmic_pin_mode_get, tavil_dmic_pin_mode_put),
5989 SOC_ENUM_EXT("AMIC_1_2 PWR MODE", amic_pwr_lvl_enum,
5990 tavil_amic_pwr_lvl_get, tavil_amic_pwr_lvl_put),
5991 SOC_ENUM_EXT("AMIC_3_4 PWR MODE", amic_pwr_lvl_enum,
5992 tavil_amic_pwr_lvl_get, tavil_amic_pwr_lvl_put),
5993 SOC_ENUM_EXT("AMIC_5_6 PWR MODE", amic_pwr_lvl_enum,
5994 tavil_amic_pwr_lvl_get, tavil_amic_pwr_lvl_put),
5995};
5996
5997static int tavil_dec_enum_put(struct snd_kcontrol *kcontrol,
5998 struct snd_ctl_elem_value *ucontrol)
5999{
6000 struct snd_soc_dapm_widget_list *wlist =
6001 dapm_kcontrol_get_wlist(kcontrol);
6002 struct snd_soc_dapm_widget *widget = wlist->widgets[0];
6003 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(widget->dapm);
6004 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
6005 unsigned int val;
6006 u16 mic_sel_reg = 0;
6007 u8 mic_sel;
6008
6009 val = ucontrol->value.enumerated.item[0];
6010 if (val > e->items - 1)
6011 return -EINVAL;
6012
6013 dev_dbg(codec->dev, "%s: wname: %s, val: 0x%x\n", __func__,
6014 widget->name, val);
6015
6016 switch (e->reg) {
6017 case WCD934X_CDC_TX_INP_MUX_ADC_MUX0_CFG1:
6018 if (e->shift_l == 0)
6019 mic_sel_reg = WCD934X_CDC_TX0_TX_PATH_CFG0;
6020 else if (e->shift_l == 2)
6021 mic_sel_reg = WCD934X_CDC_TX4_TX_PATH_CFG0;
6022 else if (e->shift_l == 4)
6023 mic_sel_reg = WCD934X_CDC_TX8_TX_PATH_CFG0;
6024 break;
6025 case WCD934X_CDC_TX_INP_MUX_ADC_MUX1_CFG1:
6026 if (e->shift_l == 0)
6027 mic_sel_reg = WCD934X_CDC_TX1_TX_PATH_CFG0;
6028 else if (e->shift_l == 2)
6029 mic_sel_reg = WCD934X_CDC_TX5_TX_PATH_CFG0;
6030 break;
6031 case WCD934X_CDC_TX_INP_MUX_ADC_MUX2_CFG1:
6032 if (e->shift_l == 0)
6033 mic_sel_reg = WCD934X_CDC_TX2_TX_PATH_CFG0;
6034 else if (e->shift_l == 2)
6035 mic_sel_reg = WCD934X_CDC_TX6_TX_PATH_CFG0;
6036 break;
6037 case WCD934X_CDC_TX_INP_MUX_ADC_MUX3_CFG1:
6038 if (e->shift_l == 0)
6039 mic_sel_reg = WCD934X_CDC_TX3_TX_PATH_CFG0;
6040 else if (e->shift_l == 2)
6041 mic_sel_reg = WCD934X_CDC_TX7_TX_PATH_CFG0;
6042 break;
6043 default:
6044 dev_err(codec->dev, "%s: e->reg: 0x%x not expected\n",
6045 __func__, e->reg);
6046 return -EINVAL;
6047 }
6048
6049 /* ADC: 0, DMIC: 1 */
6050 mic_sel = val ? 0x0 : 0x1;
6051 if (mic_sel_reg)
6052 snd_soc_update_bits(codec, mic_sel_reg, 1 << 7, mic_sel << 7);
6053
6054 return snd_soc_dapm_put_enum_double(kcontrol, ucontrol);
6055}
6056
6057static int tavil_int_dem_inp_mux_put(struct snd_kcontrol *kcontrol,
6058 struct snd_ctl_elem_value *ucontrol)
6059{
6060 struct snd_soc_dapm_widget_list *wlist =
6061 dapm_kcontrol_get_wlist(kcontrol);
6062 struct snd_soc_dapm_widget *widget = wlist->widgets[0];
6063 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(widget->dapm);
6064 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
6065 unsigned int val;
6066 unsigned short look_ahead_dly_reg = WCD934X_CDC_RX0_RX_PATH_CFG0;
6067
6068 val = ucontrol->value.enumerated.item[0];
6069 if (val >= e->items)
6070 return -EINVAL;
6071
6072 dev_dbg(codec->dev, "%s: wname: %s, val: 0x%x\n", __func__,
6073 widget->name, val);
6074
6075 if (e->reg == WCD934X_CDC_RX0_RX_PATH_SEC0)
6076 look_ahead_dly_reg = WCD934X_CDC_RX0_RX_PATH_CFG0;
6077 else if (e->reg == WCD934X_CDC_RX1_RX_PATH_SEC0)
6078 look_ahead_dly_reg = WCD934X_CDC_RX1_RX_PATH_CFG0;
6079 else if (e->reg == WCD934X_CDC_RX2_RX_PATH_SEC0)
6080 look_ahead_dly_reg = WCD934X_CDC_RX2_RX_PATH_CFG0;
6081
6082 /* Set Look Ahead Delay */
6083 snd_soc_update_bits(codec, look_ahead_dly_reg,
6084 0x08, (val ? 0x08 : 0x00));
6085 /* Set DEM INP Select */
6086 return snd_soc_dapm_put_enum_double(kcontrol, ucontrol);
6087}
6088
6089static const char * const rx_int0_7_mix_mux_text[] = {
6090 "ZERO", "RX0", "RX1", "RX2", "RX3", "RX4", "RX5",
6091 "RX6", "RX7", "PROXIMITY"
6092};
6093
6094static const char * const rx_int_mix_mux_text[] = {
6095 "ZERO", "RX0", "RX1", "RX2", "RX3", "RX4", "RX5",
6096 "RX6", "RX7"
6097};
6098
6099static const char * const rx_prim_mix_text[] = {
6100 "ZERO", "DEC0", "DEC1", "IIR0", "IIR1", "RX0", "RX1", "RX2",
6101 "RX3", "RX4", "RX5", "RX6", "RX7"
6102};
6103
6104static const char * const rx_sidetone_mix_text[] = {
6105 "ZERO", "SRC0", "SRC1", "SRC_SUM"
6106};
6107
6108static const char * const cdc_if_tx0_mux_text[] = {
6109 "ZERO", "RX_MIX_TX0", "DEC0", "DEC0_192"
6110};
6111static const char * const cdc_if_tx1_mux_text[] = {
6112 "ZERO", "RX_MIX_TX1", "DEC1", "DEC1_192"
6113};
6114static const char * const cdc_if_tx2_mux_text[] = {
6115 "ZERO", "RX_MIX_TX2", "DEC2", "DEC2_192"
6116};
6117static const char * const cdc_if_tx3_mux_text[] = {
6118 "ZERO", "RX_MIX_TX3", "DEC3", "DEC3_192"
6119};
6120static const char * const cdc_if_tx4_mux_text[] = {
6121 "ZERO", "RX_MIX_TX4", "DEC4", "DEC4_192"
6122};
6123static const char * const cdc_if_tx5_mux_text[] = {
6124 "ZERO", "RX_MIX_TX5", "DEC5", "DEC5_192"
6125};
6126static const char * const cdc_if_tx6_mux_text[] = {
6127 "ZERO", "RX_MIX_TX6", "DEC6", "DEC6_192"
6128};
6129static const char * const cdc_if_tx7_mux_text[] = {
6130 "ZERO", "RX_MIX_TX7", "DEC7", "DEC7_192"
6131};
6132static const char * const cdc_if_tx8_mux_text[] = {
6133 "ZERO", "RX_MIX_TX8", "DEC8", "DEC8_192"
6134};
6135static const char * const cdc_if_tx9_mux_text[] = {
6136 "ZERO", "DEC7", "DEC7_192"
6137};
6138static const char * const cdc_if_tx10_mux_text[] = {
6139 "ZERO", "DEC6", "DEC6_192"
6140};
6141static const char * const cdc_if_tx11_mux_text[] = {
6142 "DEC_0_5", "DEC_9_12", "MAD_AUDIO", "MAD_BRDCST"
6143};
6144static const char * const cdc_if_tx11_inp1_mux_text[] = {
6145 "ZERO", "DEC0", "DEC1", "DEC2", "DEC3", "DEC4",
6146 "DEC5", "RX_MIX_TX5", "DEC9_10", "DEC11_12"
6147};
6148static const char * const cdc_if_tx13_mux_text[] = {
6149 "CDC_DEC_5", "MAD_BRDCST"
6150};
6151static const char * const cdc_if_tx13_inp1_mux_text[] = {
6152 "ZERO", "DEC5", "DEC5_192"
6153};
6154
6155static const char * const iir_inp_mux_text[] = {
6156 "ZERO", "DEC0", "DEC1", "DEC2", "DEC3", "DEC4", "DEC5", "DEC6",
6157 "DEC7", "DEC8", "RX0", "RX1", "RX2", "RX3", "RX4", "RX5", "RX6", "RX7"
6158};
6159
6160static const char * const rx_int_dem_inp_mux_text[] = {
6161 "NORMAL_DSM_OUT", "CLSH_DSM_OUT",
6162};
6163
6164static const char * const rx_int0_1_interp_mux_text[] = {
6165 "ZERO", "RX INT0_1 MIX1",
6166};
6167
6168static const char * const rx_int1_1_interp_mux_text[] = {
6169 "ZERO", "RX INT1_1 MIX1",
6170};
6171
6172static const char * const rx_int2_1_interp_mux_text[] = {
6173 "ZERO", "RX INT2_1 MIX1",
6174};
6175
6176static const char * const rx_int3_1_interp_mux_text[] = {
6177 "ZERO", "RX INT3_1 MIX1",
6178};
6179
6180static const char * const rx_int4_1_interp_mux_text[] = {
6181 "ZERO", "RX INT4_1 MIX1",
6182};
6183
6184static const char * const rx_int7_1_interp_mux_text[] = {
6185 "ZERO", "RX INT7_1 MIX1",
6186};
6187
6188static const char * const rx_int8_1_interp_mux_text[] = {
6189 "ZERO", "RX INT8_1 MIX1",
6190};
6191
6192static const char * const rx_int0_2_interp_mux_text[] = {
6193 "ZERO", "RX INT0_2 MUX",
6194};
6195
6196static const char * const rx_int1_2_interp_mux_text[] = {
6197 "ZERO", "RX INT1_2 MUX",
6198};
6199
6200static const char * const rx_int2_2_interp_mux_text[] = {
6201 "ZERO", "RX INT2_2 MUX",
6202};
6203
6204static const char * const rx_int3_2_interp_mux_text[] = {
6205 "ZERO", "RX INT3_2 MUX",
6206};
6207
6208static const char * const rx_int4_2_interp_mux_text[] = {
6209 "ZERO", "RX INT4_2 MUX",
6210};
6211
6212static const char * const rx_int7_2_interp_mux_text[] = {
6213 "ZERO", "RX INT7_2 MUX",
6214};
6215
6216static const char * const rx_int8_2_interp_mux_text[] = {
6217 "ZERO", "RX INT8_2 MUX",
6218};
6219
6220static const char * const mad_sel_txt[] = {
6221 "SPE", "MSM"
6222};
6223
6224static const char * const mad_inp_mux_txt[] = {
6225 "MAD", "DEC1"
6226};
6227
6228static const char * const adc_mux_text[] = {
6229 "DMIC", "AMIC", "ANC_FB_TUNE1", "ANC_FB_TUNE2"
6230};
6231
6232static const char * const dmic_mux_text[] = {
6233 "ZERO", "DMIC0", "DMIC1", "DMIC2", "DMIC3", "DMIC4", "DMIC5"
6234};
6235
6236static const char * const amic_mux_text[] = {
6237 "ZERO", "ADC1", "ADC2", "ADC3", "ADC4"
6238};
6239
6240static const char * const amic4_5_sel_text[] = {
6241 "AMIC4", "AMIC5"
6242};
6243
6244static const char * const anc0_fb_mux_text[] = {
6245 "ZERO", "ANC_IN_HPHL", "ANC_IN_EAR", "ANC_IN_EAR_SPKR",
6246 "ANC_IN_LO1"
6247};
6248
6249static const char * const anc1_fb_mux_text[] = {
6250 "ZERO", "ANC_IN_HPHR", "ANC_IN_LO2"
6251};
6252
6253static const char * const rx_echo_mux_text[] = {
6254 "ZERO", "RX_MIX0", "RX_MIX1", "RX_MIX2", "RX_MIX3", "RX_MIX4",
6255 "RX_MIX5", "RX_MIX6", "RX_MIX7", "RX_MIX8"
6256};
6257
6258static const char *const slim_rx_mux_text[] = {
6259 "ZERO", "AIF1_PB", "AIF2_PB", "AIF3_PB", "AIF4_PB"
6260};
6261
6262static const char *const cdc_if_rx0_mux_text[] = {
6263 "SLIM RX0", "I2S_0 RX0"
6264};
6265static const char *const cdc_if_rx1_mux_text[] = {
6266 "SLIM RX1", "I2S_0 RX1"
6267};
6268static const char *const cdc_if_rx2_mux_text[] = {
6269 "SLIM RX2", "I2S_0 RX2"
6270};
6271static const char *const cdc_if_rx3_mux_text[] = {
6272 "SLIM RX3", "I2S_0 RX3"
6273};
6274static const char *const cdc_if_rx4_mux_text[] = {
6275 "SLIM RX4", "I2S_0 RX4"
6276};
6277static const char *const cdc_if_rx5_mux_text[] = {
6278 "SLIM RX5", "I2S_0 RX5"
6279};
6280static const char *const cdc_if_rx6_mux_text[] = {
6281 "SLIM RX6", "I2S_0 RX6"
6282};
6283static const char *const cdc_if_rx7_mux_text[] = {
6284 "SLIM RX7", "I2S_0 RX7"
6285};
6286
6287static const char * const asrc0_mux_text[] = {
6288 "ZERO", "ASRC_IN_HPHL", "ASRC_IN_LO1",
6289};
6290
6291static const char * const asrc1_mux_text[] = {
6292 "ZERO", "ASRC_IN_HPHR", "ASRC_IN_LO2",
6293};
6294
6295static const char * const asrc2_mux_text[] = {
6296 "ZERO", "ASRC_IN_SPKR1",
6297};
6298
6299static const char * const asrc3_mux_text[] = {
6300 "ZERO", "ASRC_IN_SPKR2",
6301};
6302
6303static const char * const native_mux_text[] = {
6304 "OFF", "ON",
6305};
6306
6307static const struct snd_kcontrol_new aif4_vi_mixer[] = {
6308 SOC_SINGLE_EXT("SPKR_VI_1", SND_SOC_NOPM, WCD934X_TX14, 1, 0,
6309 tavil_vi_feed_mixer_get, tavil_vi_feed_mixer_put),
6310 SOC_SINGLE_EXT("SPKR_VI_2", SND_SOC_NOPM, WCD934X_TX15, 1, 0,
6311 tavil_vi_feed_mixer_get, tavil_vi_feed_mixer_put),
6312};
6313
6314static const struct snd_kcontrol_new aif1_cap_mixer[] = {
6315 SOC_SINGLE_EXT("SLIM TX0", SND_SOC_NOPM, WCD934X_TX0, 1, 0,
6316 slim_tx_mixer_get, slim_tx_mixer_put),
6317 SOC_SINGLE_EXT("SLIM TX1", SND_SOC_NOPM, WCD934X_TX1, 1, 0,
6318 slim_tx_mixer_get, slim_tx_mixer_put),
6319 SOC_SINGLE_EXT("SLIM TX2", SND_SOC_NOPM, WCD934X_TX2, 1, 0,
6320 slim_tx_mixer_get, slim_tx_mixer_put),
6321 SOC_SINGLE_EXT("SLIM TX3", SND_SOC_NOPM, WCD934X_TX3, 1, 0,
6322 slim_tx_mixer_get, slim_tx_mixer_put),
6323 SOC_SINGLE_EXT("SLIM TX4", SND_SOC_NOPM, WCD934X_TX4, 1, 0,
6324 slim_tx_mixer_get, slim_tx_mixer_put),
6325 SOC_SINGLE_EXT("SLIM TX5", SND_SOC_NOPM, WCD934X_TX5, 1, 0,
6326 slim_tx_mixer_get, slim_tx_mixer_put),
6327 SOC_SINGLE_EXT("SLIM TX6", SND_SOC_NOPM, WCD934X_TX6, 1, 0,
6328 slim_tx_mixer_get, slim_tx_mixer_put),
6329 SOC_SINGLE_EXT("SLIM TX7", SND_SOC_NOPM, WCD934X_TX7, 1, 0,
6330 slim_tx_mixer_get, slim_tx_mixer_put),
6331 SOC_SINGLE_EXT("SLIM TX8", SND_SOC_NOPM, WCD934X_TX8, 1, 0,
6332 slim_tx_mixer_get, slim_tx_mixer_put),
6333 SOC_SINGLE_EXT("SLIM TX9", SND_SOC_NOPM, WCD934X_TX9, 1, 0,
6334 slim_tx_mixer_get, slim_tx_mixer_put),
6335 SOC_SINGLE_EXT("SLIM TX10", SND_SOC_NOPM, WCD934X_TX10, 1, 0,
6336 slim_tx_mixer_get, slim_tx_mixer_put),
6337 SOC_SINGLE_EXT("SLIM TX11", SND_SOC_NOPM, WCD934X_TX11, 1, 0,
6338 slim_tx_mixer_get, slim_tx_mixer_put),
6339 SOC_SINGLE_EXT("SLIM TX13", SND_SOC_NOPM, WCD934X_TX13, 1, 0,
6340 slim_tx_mixer_get, slim_tx_mixer_put),
6341};
6342
6343static const struct snd_kcontrol_new aif2_cap_mixer[] = {
6344 SOC_SINGLE_EXT("SLIM TX0", SND_SOC_NOPM, WCD934X_TX0, 1, 0,
6345 slim_tx_mixer_get, slim_tx_mixer_put),
6346 SOC_SINGLE_EXT("SLIM TX1", SND_SOC_NOPM, WCD934X_TX1, 1, 0,
6347 slim_tx_mixer_get, slim_tx_mixer_put),
6348 SOC_SINGLE_EXT("SLIM TX2", SND_SOC_NOPM, WCD934X_TX2, 1, 0,
6349 slim_tx_mixer_get, slim_tx_mixer_put),
6350 SOC_SINGLE_EXT("SLIM TX3", SND_SOC_NOPM, WCD934X_TX3, 1, 0,
6351 slim_tx_mixer_get, slim_tx_mixer_put),
6352 SOC_SINGLE_EXT("SLIM TX4", SND_SOC_NOPM, WCD934X_TX4, 1, 0,
6353 slim_tx_mixer_get, slim_tx_mixer_put),
6354 SOC_SINGLE_EXT("SLIM TX5", SND_SOC_NOPM, WCD934X_TX5, 1, 0,
6355 slim_tx_mixer_get, slim_tx_mixer_put),
6356 SOC_SINGLE_EXT("SLIM TX6", SND_SOC_NOPM, WCD934X_TX6, 1, 0,
6357 slim_tx_mixer_get, slim_tx_mixer_put),
6358 SOC_SINGLE_EXT("SLIM TX7", SND_SOC_NOPM, WCD934X_TX7, 1, 0,
6359 slim_tx_mixer_get, slim_tx_mixer_put),
6360 SOC_SINGLE_EXT("SLIM TX8", SND_SOC_NOPM, WCD934X_TX8, 1, 0,
6361 slim_tx_mixer_get, slim_tx_mixer_put),
6362 SOC_SINGLE_EXT("SLIM TX9", SND_SOC_NOPM, WCD934X_TX9, 1, 0,
6363 slim_tx_mixer_get, slim_tx_mixer_put),
6364 SOC_SINGLE_EXT("SLIM TX10", SND_SOC_NOPM, WCD934X_TX10, 1, 0,
6365 slim_tx_mixer_get, slim_tx_mixer_put),
6366 SOC_SINGLE_EXT("SLIM TX11", SND_SOC_NOPM, WCD934X_TX11, 1, 0,
6367 slim_tx_mixer_get, slim_tx_mixer_put),
6368 SOC_SINGLE_EXT("SLIM TX13", SND_SOC_NOPM, WCD934X_TX13, 1, 0,
6369 slim_tx_mixer_get, slim_tx_mixer_put),
6370};
6371
6372static const struct snd_kcontrol_new aif3_cap_mixer[] = {
6373 SOC_SINGLE_EXT("SLIM TX0", SND_SOC_NOPM, WCD934X_TX0, 1, 0,
6374 slim_tx_mixer_get, slim_tx_mixer_put),
6375 SOC_SINGLE_EXT("SLIM TX1", SND_SOC_NOPM, WCD934X_TX1, 1, 0,
6376 slim_tx_mixer_get, slim_tx_mixer_put),
6377 SOC_SINGLE_EXT("SLIM TX2", SND_SOC_NOPM, WCD934X_TX2, 1, 0,
6378 slim_tx_mixer_get, slim_tx_mixer_put),
6379 SOC_SINGLE_EXT("SLIM TX3", SND_SOC_NOPM, WCD934X_TX3, 1, 0,
6380 slim_tx_mixer_get, slim_tx_mixer_put),
6381 SOC_SINGLE_EXT("SLIM TX4", SND_SOC_NOPM, WCD934X_TX4, 1, 0,
6382 slim_tx_mixer_get, slim_tx_mixer_put),
6383 SOC_SINGLE_EXT("SLIM TX5", SND_SOC_NOPM, WCD934X_TX5, 1, 0,
6384 slim_tx_mixer_get, slim_tx_mixer_put),
6385 SOC_SINGLE_EXT("SLIM TX6", SND_SOC_NOPM, WCD934X_TX6, 1, 0,
6386 slim_tx_mixer_get, slim_tx_mixer_put),
6387 SOC_SINGLE_EXT("SLIM TX7", SND_SOC_NOPM, WCD934X_TX7, 1, 0,
6388 slim_tx_mixer_get, slim_tx_mixer_put),
6389 SOC_SINGLE_EXT("SLIM TX8", SND_SOC_NOPM, WCD934X_TX8, 1, 0,
6390 slim_tx_mixer_get, slim_tx_mixer_put),
6391 SOC_SINGLE_EXT("SLIM TX9", SND_SOC_NOPM, WCD934X_TX9, 1, 0,
6392 slim_tx_mixer_get, slim_tx_mixer_put),
6393 SOC_SINGLE_EXT("SLIM TX10", SND_SOC_NOPM, WCD934X_TX10, 1, 0,
6394 slim_tx_mixer_get, slim_tx_mixer_put),
6395 SOC_SINGLE_EXT("SLIM TX11", SND_SOC_NOPM, WCD934X_TX11, 1, 0,
6396 slim_tx_mixer_get, slim_tx_mixer_put),
6397 SOC_SINGLE_EXT("SLIM TX13", SND_SOC_NOPM, WCD934X_TX13, 1, 0,
6398 slim_tx_mixer_get, slim_tx_mixer_put),
6399};
6400
6401static const struct snd_kcontrol_new aif4_mad_mixer[] = {
6402 SOC_SINGLE_EXT("SLIM TX13", SND_SOC_NOPM, WCD934X_TX13, 1, 0,
6403 slim_tx_mixer_get, slim_tx_mixer_put),
6404};
6405
6406WCD_DAPM_ENUM_EXT(slim_rx0, SND_SOC_NOPM, 0, slim_rx_mux_text,
6407 slim_rx_mux_get, slim_rx_mux_put);
6408WCD_DAPM_ENUM_EXT(slim_rx1, SND_SOC_NOPM, 0, slim_rx_mux_text,
6409 slim_rx_mux_get, slim_rx_mux_put);
6410WCD_DAPM_ENUM_EXT(slim_rx2, SND_SOC_NOPM, 0, slim_rx_mux_text,
6411 slim_rx_mux_get, slim_rx_mux_put);
6412WCD_DAPM_ENUM_EXT(slim_rx3, SND_SOC_NOPM, 0, slim_rx_mux_text,
6413 slim_rx_mux_get, slim_rx_mux_put);
6414WCD_DAPM_ENUM_EXT(slim_rx4, SND_SOC_NOPM, 0, slim_rx_mux_text,
6415 slim_rx_mux_get, slim_rx_mux_put);
6416WCD_DAPM_ENUM_EXT(slim_rx5, SND_SOC_NOPM, 0, slim_rx_mux_text,
6417 slim_rx_mux_get, slim_rx_mux_put);
6418WCD_DAPM_ENUM_EXT(slim_rx6, SND_SOC_NOPM, 0, slim_rx_mux_text,
6419 slim_rx_mux_get, slim_rx_mux_put);
6420WCD_DAPM_ENUM_EXT(slim_rx7, SND_SOC_NOPM, 0, slim_rx_mux_text,
6421 slim_rx_mux_get, slim_rx_mux_put);
6422
6423WCD_DAPM_ENUM(cdc_if_rx0, SND_SOC_NOPM, 0, cdc_if_rx0_mux_text);
6424WCD_DAPM_ENUM(cdc_if_rx1, SND_SOC_NOPM, 0, cdc_if_rx1_mux_text);
6425WCD_DAPM_ENUM(cdc_if_rx2, SND_SOC_NOPM, 0, cdc_if_rx2_mux_text);
6426WCD_DAPM_ENUM(cdc_if_rx3, SND_SOC_NOPM, 0, cdc_if_rx3_mux_text);
6427WCD_DAPM_ENUM(cdc_if_rx4, SND_SOC_NOPM, 0, cdc_if_rx4_mux_text);
6428WCD_DAPM_ENUM(cdc_if_rx5, SND_SOC_NOPM, 0, cdc_if_rx5_mux_text);
6429WCD_DAPM_ENUM(cdc_if_rx6, SND_SOC_NOPM, 0, cdc_if_rx6_mux_text);
6430WCD_DAPM_ENUM(cdc_if_rx7, SND_SOC_NOPM, 0, cdc_if_rx7_mux_text);
6431
6432WCD_DAPM_ENUM(rx_int0_2, WCD934X_CDC_RX_INP_MUX_RX_INT0_CFG1, 0,
6433 rx_int0_7_mix_mux_text);
6434WCD_DAPM_ENUM(rx_int1_2, WCD934X_CDC_RX_INP_MUX_RX_INT1_CFG1, 0,
6435 rx_int_mix_mux_text);
6436WCD_DAPM_ENUM(rx_int2_2, WCD934X_CDC_RX_INP_MUX_RX_INT2_CFG1, 0,
6437 rx_int_mix_mux_text);
6438WCD_DAPM_ENUM(rx_int3_2, WCD934X_CDC_RX_INP_MUX_RX_INT3_CFG1, 0,
6439 rx_int_mix_mux_text);
6440WCD_DAPM_ENUM(rx_int4_2, WCD934X_CDC_RX_INP_MUX_RX_INT4_CFG1, 0,
6441 rx_int_mix_mux_text);
6442WCD_DAPM_ENUM(rx_int7_2, WCD934X_CDC_RX_INP_MUX_RX_INT7_CFG1, 0,
6443 rx_int0_7_mix_mux_text);
6444WCD_DAPM_ENUM(rx_int8_2, WCD934X_CDC_RX_INP_MUX_RX_INT8_CFG1, 0,
6445 rx_int_mix_mux_text);
6446
6447WCD_DAPM_ENUM(rx_int0_1_mix_inp0, WCD934X_CDC_RX_INP_MUX_RX_INT0_CFG0, 0,
6448 rx_prim_mix_text);
6449WCD_DAPM_ENUM(rx_int0_1_mix_inp1, WCD934X_CDC_RX_INP_MUX_RX_INT0_CFG0, 4,
6450 rx_prim_mix_text);
6451WCD_DAPM_ENUM(rx_int0_1_mix_inp2, WCD934X_CDC_RX_INP_MUX_RX_INT0_CFG1, 4,
6452 rx_prim_mix_text);
6453WCD_DAPM_ENUM(rx_int1_1_mix_inp0, WCD934X_CDC_RX_INP_MUX_RX_INT1_CFG0, 0,
6454 rx_prim_mix_text);
6455WCD_DAPM_ENUM(rx_int1_1_mix_inp1, WCD934X_CDC_RX_INP_MUX_RX_INT1_CFG0, 4,
6456 rx_prim_mix_text);
6457WCD_DAPM_ENUM(rx_int1_1_mix_inp2, WCD934X_CDC_RX_INP_MUX_RX_INT1_CFG1, 4,
6458 rx_prim_mix_text);
6459WCD_DAPM_ENUM(rx_int2_1_mix_inp0, WCD934X_CDC_RX_INP_MUX_RX_INT2_CFG0, 0,
6460 rx_prim_mix_text);
6461WCD_DAPM_ENUM(rx_int2_1_mix_inp1, WCD934X_CDC_RX_INP_MUX_RX_INT2_CFG0, 4,
6462 rx_prim_mix_text);
6463WCD_DAPM_ENUM(rx_int2_1_mix_inp2, WCD934X_CDC_RX_INP_MUX_RX_INT2_CFG1, 4,
6464 rx_prim_mix_text);
6465WCD_DAPM_ENUM(rx_int3_1_mix_inp0, WCD934X_CDC_RX_INP_MUX_RX_INT3_CFG0, 0,
6466 rx_prim_mix_text);
6467WCD_DAPM_ENUM(rx_int3_1_mix_inp1, WCD934X_CDC_RX_INP_MUX_RX_INT3_CFG0, 4,
6468 rx_prim_mix_text);
6469WCD_DAPM_ENUM(rx_int3_1_mix_inp2, WCD934X_CDC_RX_INP_MUX_RX_INT3_CFG1, 4,
6470 rx_prim_mix_text);
6471WCD_DAPM_ENUM(rx_int4_1_mix_inp0, WCD934X_CDC_RX_INP_MUX_RX_INT4_CFG0, 0,
6472 rx_prim_mix_text);
6473WCD_DAPM_ENUM(rx_int4_1_mix_inp1, WCD934X_CDC_RX_INP_MUX_RX_INT4_CFG0, 4,
6474 rx_prim_mix_text);
6475WCD_DAPM_ENUM(rx_int4_1_mix_inp2, WCD934X_CDC_RX_INP_MUX_RX_INT4_CFG1, 4,
6476 rx_prim_mix_text);
6477WCD_DAPM_ENUM(rx_int7_1_mix_inp0, WCD934X_CDC_RX_INP_MUX_RX_INT7_CFG0, 0,
6478 rx_prim_mix_text);
6479WCD_DAPM_ENUM(rx_int7_1_mix_inp1, WCD934X_CDC_RX_INP_MUX_RX_INT7_CFG0, 4,
6480 rx_prim_mix_text);
6481WCD_DAPM_ENUM(rx_int7_1_mix_inp2, WCD934X_CDC_RX_INP_MUX_RX_INT7_CFG1, 4,
6482 rx_prim_mix_text);
6483WCD_DAPM_ENUM(rx_int8_1_mix_inp0, WCD934X_CDC_RX_INP_MUX_RX_INT8_CFG0, 0,
6484 rx_prim_mix_text);
6485WCD_DAPM_ENUM(rx_int8_1_mix_inp1, WCD934X_CDC_RX_INP_MUX_RX_INT8_CFG0, 4,
6486 rx_prim_mix_text);
6487WCD_DAPM_ENUM(rx_int8_1_mix_inp2, WCD934X_CDC_RX_INP_MUX_RX_INT8_CFG1, 4,
6488 rx_prim_mix_text);
6489
6490WCD_DAPM_ENUM(rx_int0_mix2_inp, WCD934X_CDC_RX_INP_MUX_SIDETONE_SRC_CFG0, 0,
6491 rx_sidetone_mix_text);
6492WCD_DAPM_ENUM(rx_int1_mix2_inp, WCD934X_CDC_RX_INP_MUX_SIDETONE_SRC_CFG0, 2,
6493 rx_sidetone_mix_text);
6494WCD_DAPM_ENUM(rx_int2_mix2_inp, WCD934X_CDC_RX_INP_MUX_SIDETONE_SRC_CFG0, 4,
6495 rx_sidetone_mix_text);
6496WCD_DAPM_ENUM(rx_int3_mix2_inp, WCD934X_CDC_RX_INP_MUX_SIDETONE_SRC_CFG0, 6,
6497 rx_sidetone_mix_text);
6498WCD_DAPM_ENUM(rx_int4_mix2_inp, WCD934X_CDC_RX_INP_MUX_SIDETONE_SRC_CFG1, 0,
6499 rx_sidetone_mix_text);
6500WCD_DAPM_ENUM(rx_int7_mix2_inp, WCD934X_CDC_RX_INP_MUX_SIDETONE_SRC_CFG1, 2,
6501 rx_sidetone_mix_text);
6502
6503WCD_DAPM_ENUM(tx_adc_mux10, WCD934X_CDC_TX_INP_MUX_ADC_MUX1_CFG1, 4,
6504 adc_mux_text);
6505WCD_DAPM_ENUM(tx_adc_mux11, WCD934X_CDC_TX_INP_MUX_ADC_MUX2_CFG1, 4,
6506 adc_mux_text);
6507WCD_DAPM_ENUM(tx_adc_mux12, WCD934X_CDC_TX_INP_MUX_ADC_MUX3_CFG1, 4,
6508 adc_mux_text);
6509WCD_DAPM_ENUM(tx_adc_mux13, WCD934X_CDC_TX_INP_MUX_ADC_MUX0_CFG1, 6,
6510 adc_mux_text);
6511
6512
6513WCD_DAPM_ENUM(tx_dmic_mux0, WCD934X_CDC_TX_INP_MUX_ADC_MUX0_CFG0, 3,
6514 dmic_mux_text);
6515WCD_DAPM_ENUM(tx_dmic_mux1, WCD934X_CDC_TX_INP_MUX_ADC_MUX1_CFG0, 3,
6516 dmic_mux_text);
6517WCD_DAPM_ENUM(tx_dmic_mux2, WCD934X_CDC_TX_INP_MUX_ADC_MUX2_CFG0, 3,
6518 dmic_mux_text);
6519WCD_DAPM_ENUM(tx_dmic_mux3, WCD934X_CDC_TX_INP_MUX_ADC_MUX3_CFG0, 3,
6520 dmic_mux_text);
6521WCD_DAPM_ENUM(tx_dmic_mux4, WCD934X_CDC_TX_INP_MUX_ADC_MUX4_CFG0, 3,
6522 dmic_mux_text);
6523WCD_DAPM_ENUM(tx_dmic_mux5, WCD934X_CDC_TX_INP_MUX_ADC_MUX5_CFG0, 3,
6524 dmic_mux_text);
6525WCD_DAPM_ENUM(tx_dmic_mux6, WCD934X_CDC_TX_INP_MUX_ADC_MUX6_CFG0, 3,
6526 dmic_mux_text);
6527WCD_DAPM_ENUM(tx_dmic_mux7, WCD934X_CDC_TX_INP_MUX_ADC_MUX7_CFG0, 3,
6528 dmic_mux_text);
6529WCD_DAPM_ENUM(tx_dmic_mux8, WCD934X_CDC_TX_INP_MUX_ADC_MUX8_CFG0, 3,
6530 dmic_mux_text);
6531WCD_DAPM_ENUM(tx_dmic_mux10, WCD934X_CDC_TX_INP_MUX_ADC_MUX10_CFG0, 3,
6532 dmic_mux_text);
6533WCD_DAPM_ENUM(tx_dmic_mux11, WCD934X_CDC_TX_INP_MUX_ADC_MUX11_CFG0, 3,
6534 dmic_mux_text);
6535WCD_DAPM_ENUM(tx_dmic_mux12, WCD934X_CDC_TX_INP_MUX_ADC_MUX12_CFG0, 3,
6536 dmic_mux_text);
6537WCD_DAPM_ENUM(tx_dmic_mux13, WCD934X_CDC_TX_INP_MUX_ADC_MUX13_CFG0, 3,
6538 dmic_mux_text);
6539
6540
6541WCD_DAPM_ENUM(tx_amic_mux0, WCD934X_CDC_TX_INP_MUX_ADC_MUX0_CFG0, 0,
6542 amic_mux_text);
6543WCD_DAPM_ENUM(tx_amic_mux1, WCD934X_CDC_TX_INP_MUX_ADC_MUX1_CFG0, 0,
6544 amic_mux_text);
6545WCD_DAPM_ENUM(tx_amic_mux2, WCD934X_CDC_TX_INP_MUX_ADC_MUX2_CFG0, 0,
6546 amic_mux_text);
6547WCD_DAPM_ENUM(tx_amic_mux3, WCD934X_CDC_TX_INP_MUX_ADC_MUX3_CFG0, 0,
6548 amic_mux_text);
6549WCD_DAPM_ENUM(tx_amic_mux4, WCD934X_CDC_TX_INP_MUX_ADC_MUX4_CFG0, 0,
6550 amic_mux_text);
6551WCD_DAPM_ENUM(tx_amic_mux5, WCD934X_CDC_TX_INP_MUX_ADC_MUX5_CFG0, 0,
6552 amic_mux_text);
6553WCD_DAPM_ENUM(tx_amic_mux6, WCD934X_CDC_TX_INP_MUX_ADC_MUX6_CFG0, 0,
6554 amic_mux_text);
6555WCD_DAPM_ENUM(tx_amic_mux7, WCD934X_CDC_TX_INP_MUX_ADC_MUX7_CFG0, 0,
6556 amic_mux_text);
6557WCD_DAPM_ENUM(tx_amic_mux8, WCD934X_CDC_TX_INP_MUX_ADC_MUX8_CFG0, 0,
6558 amic_mux_text);
6559WCD_DAPM_ENUM(tx_amic_mux10, WCD934X_CDC_TX_INP_MUX_ADC_MUX10_CFG0, 0,
6560 amic_mux_text);
6561WCD_DAPM_ENUM(tx_amic_mux11, WCD934X_CDC_TX_INP_MUX_ADC_MUX11_CFG0, 0,
6562 amic_mux_text);
6563WCD_DAPM_ENUM(tx_amic_mux12, WCD934X_CDC_TX_INP_MUX_ADC_MUX12_CFG0, 0,
6564 amic_mux_text);
6565WCD_DAPM_ENUM(tx_amic_mux13, WCD934X_CDC_TX_INP_MUX_ADC_MUX13_CFG0, 0,
6566 amic_mux_text);
6567
6568WCD_DAPM_ENUM(tx_amic4_5, WCD934X_TX_NEW_AMIC_4_5_SEL, 7, amic4_5_sel_text);
6569
6570WCD_DAPM_ENUM(cdc_if_tx0, WCD934X_CDC_IF_ROUTER_TX_MUX_CFG0, 0,
6571 cdc_if_tx0_mux_text);
6572WCD_DAPM_ENUM(cdc_if_tx1, WCD934X_CDC_IF_ROUTER_TX_MUX_CFG0, 2,
6573 cdc_if_tx1_mux_text);
6574WCD_DAPM_ENUM(cdc_if_tx2, WCD934X_CDC_IF_ROUTER_TX_MUX_CFG0, 4,
6575 cdc_if_tx2_mux_text);
6576WCD_DAPM_ENUM(cdc_if_tx3, WCD934X_CDC_IF_ROUTER_TX_MUX_CFG0, 6,
6577 cdc_if_tx3_mux_text);
6578WCD_DAPM_ENUM(cdc_if_tx4, WCD934X_CDC_IF_ROUTER_TX_MUX_CFG1, 0,
6579 cdc_if_tx4_mux_text);
6580WCD_DAPM_ENUM(cdc_if_tx5, WCD934X_CDC_IF_ROUTER_TX_MUX_CFG1, 2,
6581 cdc_if_tx5_mux_text);
6582WCD_DAPM_ENUM(cdc_if_tx6, WCD934X_CDC_IF_ROUTER_TX_MUX_CFG1, 4,
6583 cdc_if_tx6_mux_text);
6584WCD_DAPM_ENUM(cdc_if_tx7, WCD934X_CDC_IF_ROUTER_TX_MUX_CFG1, 6,
6585 cdc_if_tx7_mux_text);
6586WCD_DAPM_ENUM(cdc_if_tx8, WCD934X_CDC_IF_ROUTER_TX_MUX_CFG2, 0,
6587 cdc_if_tx8_mux_text);
6588WCD_DAPM_ENUM(cdc_if_tx9, WCD934X_CDC_IF_ROUTER_TX_MUX_CFG2, 2,
6589 cdc_if_tx9_mux_text);
6590WCD_DAPM_ENUM(cdc_if_tx10, WCD934X_CDC_IF_ROUTER_TX_MUX_CFG2, 4,
6591 cdc_if_tx10_mux_text);
6592WCD_DAPM_ENUM(cdc_if_tx11_inp1, WCD934X_CDC_IF_ROUTER_TX_MUX_CFG3, 0,
6593 cdc_if_tx11_inp1_mux_text);
6594WCD_DAPM_ENUM(cdc_if_tx11, WCD934X_DATA_HUB_SB_TX11_INP_CFG, 0,
6595 cdc_if_tx11_mux_text);
6596WCD_DAPM_ENUM(cdc_if_tx13_inp1, WCD934X_CDC_IF_ROUTER_TX_MUX_CFG3, 4,
6597 cdc_if_tx13_inp1_mux_text);
6598WCD_DAPM_ENUM(cdc_if_tx13, WCD934X_DATA_HUB_SB_TX13_INP_CFG, 0,
6599 cdc_if_tx13_mux_text);
6600
6601WCD_DAPM_ENUM(rx_mix_tx0, WCD934X_CDC_RX_INP_MUX_RX_MIX_CFG0, 0,
6602 rx_echo_mux_text);
6603WCD_DAPM_ENUM(rx_mix_tx1, WCD934X_CDC_RX_INP_MUX_RX_MIX_CFG0, 4,
6604 rx_echo_mux_text);
6605WCD_DAPM_ENUM(rx_mix_tx2, WCD934X_CDC_RX_INP_MUX_RX_MIX_CFG1, 0,
6606 rx_echo_mux_text);
6607WCD_DAPM_ENUM(rx_mix_tx3, WCD934X_CDC_RX_INP_MUX_RX_MIX_CFG1, 4,
6608 rx_echo_mux_text);
6609WCD_DAPM_ENUM(rx_mix_tx4, WCD934X_CDC_RX_INP_MUX_RX_MIX_CFG2, 0,
6610 rx_echo_mux_text);
6611WCD_DAPM_ENUM(rx_mix_tx5, WCD934X_CDC_RX_INP_MUX_RX_MIX_CFG2, 4,
6612 rx_echo_mux_text);
6613WCD_DAPM_ENUM(rx_mix_tx6, WCD934X_CDC_RX_INP_MUX_RX_MIX_CFG3, 0,
6614 rx_echo_mux_text);
6615WCD_DAPM_ENUM(rx_mix_tx7, WCD934X_CDC_RX_INP_MUX_RX_MIX_CFG3, 4,
6616 rx_echo_mux_text);
6617WCD_DAPM_ENUM(rx_mix_tx8, WCD934X_CDC_RX_INP_MUX_RX_MIX_CFG4, 0,
6618 rx_echo_mux_text);
6619
6620WCD_DAPM_ENUM(iir0_inp0, WCD934X_CDC_SIDETONE_IIR_INP_MUX_IIR0_MIX_CFG0, 0,
6621 iir_inp_mux_text);
6622WCD_DAPM_ENUM(iir0_inp1, WCD934X_CDC_SIDETONE_IIR_INP_MUX_IIR0_MIX_CFG1, 0,
6623 iir_inp_mux_text);
6624WCD_DAPM_ENUM(iir0_inp2, WCD934X_CDC_SIDETONE_IIR_INP_MUX_IIR0_MIX_CFG2, 0,
6625 iir_inp_mux_text);
6626WCD_DAPM_ENUM(iir0_inp3, WCD934X_CDC_SIDETONE_IIR_INP_MUX_IIR0_MIX_CFG3, 0,
6627 iir_inp_mux_text);
6628WCD_DAPM_ENUM(iir1_inp0, WCD934X_CDC_SIDETONE_IIR_INP_MUX_IIR1_MIX_CFG0, 0,
6629 iir_inp_mux_text);
6630WCD_DAPM_ENUM(iir1_inp1, WCD934X_CDC_SIDETONE_IIR_INP_MUX_IIR1_MIX_CFG1, 0,
6631 iir_inp_mux_text);
6632WCD_DAPM_ENUM(iir1_inp2, WCD934X_CDC_SIDETONE_IIR_INP_MUX_IIR1_MIX_CFG2, 0,
6633 iir_inp_mux_text);
6634WCD_DAPM_ENUM(iir1_inp3, WCD934X_CDC_SIDETONE_IIR_INP_MUX_IIR1_MIX_CFG3, 0,
6635 iir_inp_mux_text);
6636
6637WCD_DAPM_ENUM(rx_int0_1_interp, SND_SOC_NOPM, 0, rx_int0_1_interp_mux_text);
6638WCD_DAPM_ENUM(rx_int1_1_interp, SND_SOC_NOPM, 0, rx_int1_1_interp_mux_text);
6639WCD_DAPM_ENUM(rx_int2_1_interp, SND_SOC_NOPM, 0, rx_int2_1_interp_mux_text);
6640WCD_DAPM_ENUM(rx_int3_1_interp, SND_SOC_NOPM, 0, rx_int3_1_interp_mux_text);
6641WCD_DAPM_ENUM(rx_int4_1_interp, SND_SOC_NOPM, 0, rx_int4_1_interp_mux_text);
6642WCD_DAPM_ENUM(rx_int7_1_interp, SND_SOC_NOPM, 0, rx_int7_1_interp_mux_text);
6643WCD_DAPM_ENUM(rx_int8_1_interp, SND_SOC_NOPM, 0, rx_int8_1_interp_mux_text);
6644
6645WCD_DAPM_ENUM(rx_int0_2_interp, SND_SOC_NOPM, 0, rx_int0_2_interp_mux_text);
6646WCD_DAPM_ENUM(rx_int1_2_interp, SND_SOC_NOPM, 0, rx_int1_2_interp_mux_text);
6647WCD_DAPM_ENUM(rx_int2_2_interp, SND_SOC_NOPM, 0, rx_int2_2_interp_mux_text);
6648WCD_DAPM_ENUM(rx_int3_2_interp, SND_SOC_NOPM, 0, rx_int3_2_interp_mux_text);
6649WCD_DAPM_ENUM(rx_int4_2_interp, SND_SOC_NOPM, 0, rx_int4_2_interp_mux_text);
6650WCD_DAPM_ENUM(rx_int7_2_interp, SND_SOC_NOPM, 0, rx_int7_2_interp_mux_text);
6651WCD_DAPM_ENUM(rx_int8_2_interp, SND_SOC_NOPM, 0, rx_int8_2_interp_mux_text);
6652
6653WCD_DAPM_ENUM(mad_sel, WCD934X_CPE_SS_SVA_CFG, 0,
6654 mad_sel_txt);
6655
6656WCD_DAPM_ENUM(mad_inp_mux, WCD934X_CPE_SS_SVA_CFG, 2,
6657 mad_inp_mux_txt);
6658
6659WCD_DAPM_ENUM_EXT(rx_int0_dem_inp, WCD934X_CDC_RX0_RX_PATH_SEC0, 0,
6660 rx_int_dem_inp_mux_text, snd_soc_dapm_get_enum_double,
6661 tavil_int_dem_inp_mux_put);
6662WCD_DAPM_ENUM_EXT(rx_int1_dem_inp, WCD934X_CDC_RX1_RX_PATH_SEC0, 0,
6663 rx_int_dem_inp_mux_text, snd_soc_dapm_get_enum_double,
6664 tavil_int_dem_inp_mux_put);
6665WCD_DAPM_ENUM_EXT(rx_int2_dem_inp, WCD934X_CDC_RX2_RX_PATH_SEC0, 0,
6666 rx_int_dem_inp_mux_text, snd_soc_dapm_get_enum_double,
6667 tavil_int_dem_inp_mux_put);
6668
6669WCD_DAPM_ENUM_EXT(tx_adc_mux0, WCD934X_CDC_TX_INP_MUX_ADC_MUX0_CFG1, 0,
6670 adc_mux_text, snd_soc_dapm_get_enum_double, tavil_dec_enum_put);
6671WCD_DAPM_ENUM_EXT(tx_adc_mux1, WCD934X_CDC_TX_INP_MUX_ADC_MUX1_CFG1, 0,
6672 adc_mux_text, snd_soc_dapm_get_enum_double, tavil_dec_enum_put);
6673WCD_DAPM_ENUM_EXT(tx_adc_mux2, WCD934X_CDC_TX_INP_MUX_ADC_MUX2_CFG1, 0,
6674 adc_mux_text, snd_soc_dapm_get_enum_double, tavil_dec_enum_put);
6675WCD_DAPM_ENUM_EXT(tx_adc_mux3, WCD934X_CDC_TX_INP_MUX_ADC_MUX3_CFG1, 0,
6676 adc_mux_text, snd_soc_dapm_get_enum_double, tavil_dec_enum_put);
6677WCD_DAPM_ENUM_EXT(tx_adc_mux4, WCD934X_CDC_TX_INP_MUX_ADC_MUX0_CFG1, 2,
6678 adc_mux_text, snd_soc_dapm_get_enum_double, tavil_dec_enum_put);
6679WCD_DAPM_ENUM_EXT(tx_adc_mux5, WCD934X_CDC_TX_INP_MUX_ADC_MUX1_CFG1, 2,
6680 adc_mux_text, snd_soc_dapm_get_enum_double, tavil_dec_enum_put);
6681WCD_DAPM_ENUM_EXT(tx_adc_mux6, WCD934X_CDC_TX_INP_MUX_ADC_MUX2_CFG1, 2,
6682 adc_mux_text, snd_soc_dapm_get_enum_double, tavil_dec_enum_put);
6683WCD_DAPM_ENUM_EXT(tx_adc_mux7, WCD934X_CDC_TX_INP_MUX_ADC_MUX3_CFG1, 2,
6684 adc_mux_text, snd_soc_dapm_get_enum_double, tavil_dec_enum_put);
6685WCD_DAPM_ENUM_EXT(tx_adc_mux8, WCD934X_CDC_TX_INP_MUX_ADC_MUX0_CFG1, 4,
6686 adc_mux_text, snd_soc_dapm_get_enum_double, tavil_dec_enum_put);
6687
6688WCD_DAPM_ENUM(asrc0, WCD934X_CDC_RX_INP_MUX_SPLINE_ASRC_CFG0, 0,
6689 asrc0_mux_text);
6690WCD_DAPM_ENUM(asrc1, WCD934X_CDC_RX_INP_MUX_SPLINE_ASRC_CFG0, 2,
6691 asrc1_mux_text);
6692WCD_DAPM_ENUM(asrc2, WCD934X_CDC_RX_INP_MUX_SPLINE_ASRC_CFG0, 4,
6693 asrc2_mux_text);
6694WCD_DAPM_ENUM(asrc3, WCD934X_CDC_RX_INP_MUX_SPLINE_ASRC_CFG0, 6,
6695 asrc3_mux_text);
6696
6697WCD_DAPM_ENUM(int1_1_native, SND_SOC_NOPM, 0, native_mux_text);
6698WCD_DAPM_ENUM(int2_1_native, SND_SOC_NOPM, 0, native_mux_text);
6699WCD_DAPM_ENUM(int3_1_native, SND_SOC_NOPM, 0, native_mux_text);
6700WCD_DAPM_ENUM(int4_1_native, SND_SOC_NOPM, 0, native_mux_text);
6701
6702WCD_DAPM_ENUM(int1_2_native, SND_SOC_NOPM, 0, native_mux_text);
6703WCD_DAPM_ENUM(int2_2_native, SND_SOC_NOPM, 0, native_mux_text);
6704WCD_DAPM_ENUM(int3_2_native, SND_SOC_NOPM, 0, native_mux_text);
6705WCD_DAPM_ENUM(int4_2_native, SND_SOC_NOPM, 0, native_mux_text);
6706WCD_DAPM_ENUM(int7_2_native, SND_SOC_NOPM, 0, native_mux_text);
6707WCD_DAPM_ENUM(int8_2_native, SND_SOC_NOPM, 0, native_mux_text);
6708
6709WCD_DAPM_ENUM(anc0_fb, WCD934X_CDC_RX_INP_MUX_ANC_CFG0, 0, anc0_fb_mux_text);
6710WCD_DAPM_ENUM(anc1_fb, WCD934X_CDC_RX_INP_MUX_ANC_CFG0, 3, anc1_fb_mux_text);
6711
6712static const struct snd_kcontrol_new anc_ear_switch =
6713 SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0);
6714
6715static const struct snd_kcontrol_new anc_ear_spkr_switch =
6716 SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0);
6717
6718static const struct snd_kcontrol_new anc_spkr_pa_switch =
6719 SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0);
6720
Meng Wangf45a20d2017-01-18 09:51:58 +08006721static const struct snd_kcontrol_new anc_hphl_pa_switch =
6722 SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0);
6723
6724static const struct snd_kcontrol_new anc_hphr_pa_switch =
6725 SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0);
6726
Banajit Goswamide8271c2017-01-18 00:28:59 -08006727static const struct snd_kcontrol_new mad_cpe1_switch =
6728 SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0);
6729
6730static const struct snd_kcontrol_new mad_cpe2_switch =
6731 SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0);
6732
6733static const struct snd_kcontrol_new mad_brdcst_switch =
6734 SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0);
6735
6736static const struct snd_kcontrol_new adc_us_mux0_switch =
6737 SOC_DAPM_SINGLE("US_Switch", SND_SOC_NOPM, 0, 1, 0);
6738
6739static const struct snd_kcontrol_new adc_us_mux1_switch =
6740 SOC_DAPM_SINGLE("US_Switch", SND_SOC_NOPM, 0, 1, 0);
6741
6742static const struct snd_kcontrol_new adc_us_mux2_switch =
6743 SOC_DAPM_SINGLE("US_Switch", SND_SOC_NOPM, 0, 1, 0);
6744
6745static const struct snd_kcontrol_new adc_us_mux3_switch =
6746 SOC_DAPM_SINGLE("US_Switch", SND_SOC_NOPM, 0, 1, 0);
6747
6748static const struct snd_kcontrol_new adc_us_mux4_switch =
6749 SOC_DAPM_SINGLE("US_Switch", SND_SOC_NOPM, 0, 1, 0);
6750
6751static const struct snd_kcontrol_new adc_us_mux5_switch =
6752 SOC_DAPM_SINGLE("US_Switch", SND_SOC_NOPM, 0, 1, 0);
6753
6754static const struct snd_kcontrol_new adc_us_mux6_switch =
6755 SOC_DAPM_SINGLE("US_Switch", SND_SOC_NOPM, 0, 1, 0);
6756
6757static const struct snd_kcontrol_new adc_us_mux7_switch =
6758 SOC_DAPM_SINGLE("US_Switch", SND_SOC_NOPM, 0, 1, 0);
6759
6760static const struct snd_kcontrol_new adc_us_mux8_switch =
6761 SOC_DAPM_SINGLE("US_Switch", SND_SOC_NOPM, 0, 1, 0);
6762
6763static const struct snd_kcontrol_new rx_int1_asrc_switch[] = {
6764 SOC_DAPM_SINGLE("HPHL Switch", SND_SOC_NOPM, 0, 1, 0),
6765};
6766
6767static const struct snd_kcontrol_new rx_int2_asrc_switch[] = {
6768 SOC_DAPM_SINGLE("HPHR Switch", SND_SOC_NOPM, 0, 1, 0),
6769};
6770
6771static const struct snd_kcontrol_new rx_int3_asrc_switch[] = {
6772 SOC_DAPM_SINGLE("LO1 Switch", SND_SOC_NOPM, 0, 1, 0),
6773};
6774
6775static const struct snd_kcontrol_new rx_int4_asrc_switch[] = {
6776 SOC_DAPM_SINGLE("LO2 Switch", SND_SOC_NOPM, 0, 1, 0),
6777};
6778
6779static int tavil_dsd_mixer_get(struct snd_kcontrol *kcontrol,
6780 struct snd_ctl_elem_value *ucontrol)
6781{
6782 struct snd_soc_dapm_context *dapm =
6783 snd_soc_dapm_kcontrol_dapm(kcontrol);
6784 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(dapm);
6785 struct tavil_priv *tavil_p = snd_soc_codec_get_drvdata(codec);
6786 struct soc_mixer_control *mc =
6787 (struct soc_mixer_control *)kcontrol->private_value;
6788 struct tavil_dsd_config *dsd_conf = tavil_p->dsd_config;
6789 int val;
6790
6791 val = tavil_dsd_get_current_mixer_value(dsd_conf, mc->shift);
6792
6793 ucontrol->value.integer.value[0] = ((val < 0) ? 0 : val);
6794
6795 return 0;
6796}
6797
6798static int tavil_dsd_mixer_put(struct snd_kcontrol *kcontrol,
6799 struct snd_ctl_elem_value *ucontrol)
6800{
6801 struct soc_mixer_control *mc =
6802 (struct soc_mixer_control *)kcontrol->private_value;
6803 struct snd_soc_dapm_context *dapm =
6804 snd_soc_dapm_kcontrol_dapm(kcontrol);
6805 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(dapm);
6806 struct tavil_priv *tavil_p = snd_soc_codec_get_drvdata(codec);
6807 unsigned int wval = ucontrol->value.integer.value[0];
6808 struct tavil_dsd_config *dsd_conf = tavil_p->dsd_config;
6809
6810 if (!dsd_conf)
6811 return 0;
6812
6813 mutex_lock(&tavil_p->codec_mutex);
6814
6815 tavil_dsd_set_out_select(dsd_conf, mc->shift);
6816 tavil_dsd_set_mixer_value(dsd_conf, mc->shift, wval);
6817
6818 mutex_unlock(&tavil_p->codec_mutex);
6819 snd_soc_dapm_mixer_update_power(dapm, kcontrol, wval, NULL);
6820
6821 return 0;
6822}
6823
6824static const struct snd_kcontrol_new hphl_mixer[] = {
6825 SOC_SINGLE_EXT("DSD HPHL Switch", SND_SOC_NOPM, INTERP_HPHL, 1, 0,
6826 tavil_dsd_mixer_get, tavil_dsd_mixer_put),
6827};
6828
6829static const struct snd_kcontrol_new hphr_mixer[] = {
6830 SOC_SINGLE_EXT("DSD HPHR Switch", SND_SOC_NOPM, INTERP_HPHR, 1, 0,
6831 tavil_dsd_mixer_get, tavil_dsd_mixer_put),
6832};
6833
Phani Kumar Uppalapatia1f87022017-01-25 19:13:13 -08006834static const struct snd_kcontrol_new lo1_mixer[] = {
6835 SOC_SINGLE_EXT("DSD LO1 Switch", SND_SOC_NOPM, INTERP_LO1, 1, 0,
6836 tavil_dsd_mixer_get, tavil_dsd_mixer_put),
6837};
6838
6839static const struct snd_kcontrol_new lo2_mixer[] = {
6840 SOC_SINGLE_EXT("DSD LO2 Switch", SND_SOC_NOPM, INTERP_LO2, 1, 0,
6841 tavil_dsd_mixer_get, tavil_dsd_mixer_put),
6842};
6843
Banajit Goswamide8271c2017-01-18 00:28:59 -08006844static const struct snd_soc_dapm_widget tavil_dapm_widgets[] = {
6845 SND_SOC_DAPM_AIF_IN_E("AIF1 PB", "AIF1 Playback", 0, SND_SOC_NOPM,
6846 AIF1_PB, 0, tavil_codec_enable_slimrx,
6847 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
6848 SND_SOC_DAPM_AIF_IN_E("AIF2 PB", "AIF2 Playback", 0, SND_SOC_NOPM,
6849 AIF2_PB, 0, tavil_codec_enable_slimrx,
6850 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
6851 SND_SOC_DAPM_AIF_IN_E("AIF3 PB", "AIF3 Playback", 0, SND_SOC_NOPM,
6852 AIF3_PB, 0, tavil_codec_enable_slimrx,
6853 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
6854 SND_SOC_DAPM_AIF_IN_E("AIF4 PB", "AIF4 Playback", 0, SND_SOC_NOPM,
6855 AIF4_PB, 0, tavil_codec_enable_slimrx,
6856 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
6857
6858 WCD_DAPM_MUX("SLIM RX0 MUX", WCD934X_RX0, slim_rx0),
6859 WCD_DAPM_MUX("SLIM RX1 MUX", WCD934X_RX1, slim_rx1),
6860 WCD_DAPM_MUX("SLIM RX2 MUX", WCD934X_RX2, slim_rx2),
6861 WCD_DAPM_MUX("SLIM RX3 MUX", WCD934X_RX3, slim_rx3),
6862 WCD_DAPM_MUX("SLIM RX4 MUX", WCD934X_RX4, slim_rx4),
6863 WCD_DAPM_MUX("SLIM RX5 MUX", WCD934X_RX5, slim_rx5),
6864 WCD_DAPM_MUX("SLIM RX6 MUX", WCD934X_RX6, slim_rx6),
6865 WCD_DAPM_MUX("SLIM RX7 MUX", WCD934X_RX7, slim_rx7),
6866
6867 SND_SOC_DAPM_MIXER("SLIM RX0", SND_SOC_NOPM, 0, 0, NULL, 0),
6868 SND_SOC_DAPM_MIXER("SLIM RX1", SND_SOC_NOPM, 0, 0, NULL, 0),
6869 SND_SOC_DAPM_MIXER("SLIM RX2", SND_SOC_NOPM, 0, 0, NULL, 0),
6870 SND_SOC_DAPM_MIXER("SLIM RX3", SND_SOC_NOPM, 0, 0, NULL, 0),
6871 SND_SOC_DAPM_MIXER("SLIM RX4", SND_SOC_NOPM, 0, 0, NULL, 0),
6872 SND_SOC_DAPM_MIXER("SLIM RX5", SND_SOC_NOPM, 0, 0, NULL, 0),
6873 SND_SOC_DAPM_MIXER("SLIM RX6", SND_SOC_NOPM, 0, 0, NULL, 0),
6874 SND_SOC_DAPM_MIXER("SLIM RX7", SND_SOC_NOPM, 0, 0, NULL, 0),
6875
6876 WCD_DAPM_MUX("CDC_IF RX0 MUX", WCD934X_RX0, cdc_if_rx0),
6877 WCD_DAPM_MUX("CDC_IF RX1 MUX", WCD934X_RX1, cdc_if_rx1),
6878 WCD_DAPM_MUX("CDC_IF RX2 MUX", WCD934X_RX2, cdc_if_rx2),
6879 WCD_DAPM_MUX("CDC_IF RX3 MUX", WCD934X_RX3, cdc_if_rx3),
6880 WCD_DAPM_MUX("CDC_IF RX4 MUX", WCD934X_RX4, cdc_if_rx4),
6881 WCD_DAPM_MUX("CDC_IF RX5 MUX", WCD934X_RX5, cdc_if_rx5),
6882 WCD_DAPM_MUX("CDC_IF RX6 MUX", WCD934X_RX6, cdc_if_rx6),
6883 WCD_DAPM_MUX("CDC_IF RX7 MUX", WCD934X_RX7, cdc_if_rx7),
6884
6885 SND_SOC_DAPM_MUX_E("RX INT0_2 MUX", SND_SOC_NOPM, INTERP_EAR, 0,
6886 &rx_int0_2_mux, tavil_codec_enable_mix_path,
6887 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
6888 SND_SOC_DAPM_POST_PMD),
6889 SND_SOC_DAPM_MUX_E("RX INT1_2 MUX", SND_SOC_NOPM, INTERP_HPHL, 0,
6890 &rx_int1_2_mux, tavil_codec_enable_mix_path,
6891 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
6892 SND_SOC_DAPM_POST_PMD),
6893 SND_SOC_DAPM_MUX_E("RX INT2_2 MUX", SND_SOC_NOPM, INTERP_HPHR, 0,
6894 &rx_int2_2_mux, tavil_codec_enable_mix_path,
6895 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
6896 SND_SOC_DAPM_POST_PMD),
6897 SND_SOC_DAPM_MUX_E("RX INT3_2 MUX", SND_SOC_NOPM, INTERP_LO1, 0,
6898 &rx_int3_2_mux, tavil_codec_enable_mix_path,
6899 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
6900 SND_SOC_DAPM_POST_PMD),
6901 SND_SOC_DAPM_MUX_E("RX INT4_2 MUX", SND_SOC_NOPM, INTERP_LO2, 0,
6902 &rx_int4_2_mux, tavil_codec_enable_mix_path,
6903 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
6904 SND_SOC_DAPM_POST_PMD),
6905 SND_SOC_DAPM_MUX_E("RX INT7_2 MUX", SND_SOC_NOPM, INTERP_SPKR1, 0,
6906 &rx_int7_2_mux, tavil_codec_enable_mix_path,
6907 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
6908 SND_SOC_DAPM_POST_PMD),
6909 SND_SOC_DAPM_MUX_E("RX INT8_2 MUX", SND_SOC_NOPM, INTERP_SPKR2, 0,
6910 &rx_int8_2_mux, tavil_codec_enable_mix_path,
6911 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
6912 SND_SOC_DAPM_POST_PMD),
6913
6914 WCD_DAPM_MUX("RX INT0_1 MIX1 INP0", 0, rx_int0_1_mix_inp0),
6915 WCD_DAPM_MUX("RX INT0_1 MIX1 INP1", 0, rx_int0_1_mix_inp1),
6916 WCD_DAPM_MUX("RX INT0_1 MIX1 INP2", 0, rx_int0_1_mix_inp2),
6917 WCD_DAPM_MUX("RX INT1_1 MIX1 INP0", 0, rx_int1_1_mix_inp0),
6918 WCD_DAPM_MUX("RX INT1_1 MIX1 INP1", 0, rx_int1_1_mix_inp1),
6919 WCD_DAPM_MUX("RX INT1_1 MIX1 INP2", 0, rx_int1_1_mix_inp2),
6920 WCD_DAPM_MUX("RX INT2_1 MIX1 INP0", 0, rx_int2_1_mix_inp0),
6921 WCD_DAPM_MUX("RX INT2_1 MIX1 INP1", 0, rx_int2_1_mix_inp1),
6922 WCD_DAPM_MUX("RX INT2_1 MIX1 INP2", 0, rx_int2_1_mix_inp2),
6923 WCD_DAPM_MUX("RX INT3_1 MIX1 INP0", 0, rx_int3_1_mix_inp0),
6924 WCD_DAPM_MUX("RX INT3_1 MIX1 INP1", 0, rx_int3_1_mix_inp1),
6925 WCD_DAPM_MUX("RX INT3_1 MIX1 INP2", 0, rx_int3_1_mix_inp2),
6926 WCD_DAPM_MUX("RX INT4_1 MIX1 INP0", 0, rx_int4_1_mix_inp0),
6927 WCD_DAPM_MUX("RX INT4_1 MIX1 INP1", 0, rx_int4_1_mix_inp1),
6928 WCD_DAPM_MUX("RX INT4_1 MIX1 INP2", 0, rx_int4_1_mix_inp2),
6929
6930 SND_SOC_DAPM_MUX_E("RX INT7_1 MIX1 INP0", SND_SOC_NOPM, 0, 0,
6931 &rx_int7_1_mix_inp0_mux, tavil_codec_enable_swr,
6932 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
6933 SND_SOC_DAPM_MUX_E("RX INT7_1 MIX1 INP1", SND_SOC_NOPM, 0, 0,
6934 &rx_int7_1_mix_inp1_mux, tavil_codec_enable_swr,
6935 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
6936 SND_SOC_DAPM_MUX_E("RX INT7_1 MIX1 INP2", SND_SOC_NOPM, 0, 0,
6937 &rx_int7_1_mix_inp2_mux, tavil_codec_enable_swr,
6938 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
6939 SND_SOC_DAPM_MUX_E("RX INT8_1 MIX1 INP0", SND_SOC_NOPM, 0, 0,
6940 &rx_int8_1_mix_inp0_mux, tavil_codec_enable_swr,
6941 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
6942 SND_SOC_DAPM_MUX_E("RX INT8_1 MIX1 INP1", SND_SOC_NOPM, 0, 0,
6943 &rx_int8_1_mix_inp1_mux, tavil_codec_enable_swr,
6944 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
6945 SND_SOC_DAPM_MUX_E("RX INT8_1 MIX1 INP2", SND_SOC_NOPM, 0, 0,
6946 &rx_int8_1_mix_inp2_mux, tavil_codec_enable_swr,
6947 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
6948
6949 SND_SOC_DAPM_MIXER("RX INT0_1 MIX1", SND_SOC_NOPM, 0, 0, NULL, 0),
6950 SND_SOC_DAPM_MIXER("RX INT0 SEC MIX", SND_SOC_NOPM, 0, 0, NULL, 0),
6951 SND_SOC_DAPM_MIXER("RX INT1_1 MIX1", SND_SOC_NOPM, 0, 0, NULL, 0),
6952 SND_SOC_DAPM_MIXER("RX INT1 SEC MIX", SND_SOC_NOPM, 0, 0,
6953 rx_int1_asrc_switch, ARRAY_SIZE(rx_int1_asrc_switch)),
6954 SND_SOC_DAPM_MIXER("RX INT2_1 MIX1", SND_SOC_NOPM, 0, 0, NULL, 0),
6955 SND_SOC_DAPM_MIXER("RX INT2 SEC MIX", SND_SOC_NOPM, 0, 0,
6956 rx_int2_asrc_switch, ARRAY_SIZE(rx_int2_asrc_switch)),
6957 SND_SOC_DAPM_MIXER("RX INT3_1 MIX1", SND_SOC_NOPM, 0, 0, NULL, 0),
6958 SND_SOC_DAPM_MIXER("RX INT3 SEC MIX", SND_SOC_NOPM, 0, 0,
6959 rx_int3_asrc_switch, ARRAY_SIZE(rx_int3_asrc_switch)),
6960 SND_SOC_DAPM_MIXER("RX INT4_1 MIX1", SND_SOC_NOPM, 0, 0, NULL, 0),
6961 SND_SOC_DAPM_MIXER("RX INT4 SEC MIX", SND_SOC_NOPM, 0, 0,
6962 rx_int4_asrc_switch, ARRAY_SIZE(rx_int4_asrc_switch)),
6963 SND_SOC_DAPM_MIXER("RX INT7_1 MIX1", SND_SOC_NOPM, 0, 0, NULL, 0),
6964 SND_SOC_DAPM_MIXER("RX INT7 SEC MIX", SND_SOC_NOPM, 0, 0, NULL, 0),
6965 SND_SOC_DAPM_MIXER("RX INT8_1 MIX1", SND_SOC_NOPM, 0, 0, NULL, 0),
6966 SND_SOC_DAPM_MIXER("RX INT8 SEC MIX", SND_SOC_NOPM, 0, 0, NULL, 0),
6967
6968 SND_SOC_DAPM_MIXER("RX INT0 MIX2", SND_SOC_NOPM, 0, 0, NULL, 0),
6969 SND_SOC_DAPM_MIXER("RX INT1 MIX2", SND_SOC_NOPM, 0, 0, NULL, 0),
6970 SND_SOC_DAPM_MIXER("RX INT1 MIX3", SND_SOC_NOPM, 0, 0, hphl_mixer,
6971 ARRAY_SIZE(hphl_mixer)),
6972 SND_SOC_DAPM_MIXER("RX INT2 MIX2", SND_SOC_NOPM, 0, 0, NULL, 0),
6973 SND_SOC_DAPM_MIXER("RX INT2 MIX3", SND_SOC_NOPM, 0, 0, hphr_mixer,
6974 ARRAY_SIZE(hphr_mixer)),
6975 SND_SOC_DAPM_MIXER("RX INT3 MIX2", SND_SOC_NOPM, 0, 0, NULL, 0),
Phani Kumar Uppalapatia1f87022017-01-25 19:13:13 -08006976 SND_SOC_DAPM_MIXER("RX INT3 MIX3", SND_SOC_NOPM, 0, 0, lo1_mixer,
6977 ARRAY_SIZE(lo1_mixer)),
Banajit Goswamide8271c2017-01-18 00:28:59 -08006978 SND_SOC_DAPM_MIXER("RX INT4 MIX2", SND_SOC_NOPM, 0, 0, NULL, 0),
Phani Kumar Uppalapatia1f87022017-01-25 19:13:13 -08006979 SND_SOC_DAPM_MIXER("RX INT4 MIX3", SND_SOC_NOPM, 0, 0, lo2_mixer,
6980 ARRAY_SIZE(lo2_mixer)),
Banajit Goswamide8271c2017-01-18 00:28:59 -08006981 SND_SOC_DAPM_MIXER("RX INT7 MIX2", SND_SOC_NOPM, 0, 0, NULL, 0),
6982 SND_SOC_DAPM_MIXER_E("RX INT7 CHAIN", SND_SOC_NOPM, 0, 0,
6983 NULL, 0, tavil_codec_spk_boost_event,
6984 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
6985 SND_SOC_DAPM_MIXER_E("RX INT8 CHAIN", SND_SOC_NOPM, 0, 0,
6986 NULL, 0, tavil_codec_spk_boost_event,
6987 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
6988
6989 SND_SOC_DAPM_MUX_E("RX INT0 MIX2 INP", SND_SOC_NOPM, INTERP_EAR,
6990 0, &rx_int0_mix2_inp_mux, tavil_codec_enable_rx_path_clk,
6991 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
6992 SND_SOC_DAPM_MUX_E("RX INT1 MIX2 INP", SND_SOC_NOPM, INTERP_HPHL,
6993 0, &rx_int1_mix2_inp_mux, tavil_codec_enable_rx_path_clk,
6994 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
6995 SND_SOC_DAPM_MUX_E("RX INT2 MIX2 INP", SND_SOC_NOPM, INTERP_HPHR,
6996 0, &rx_int2_mix2_inp_mux, tavil_codec_enable_rx_path_clk,
6997 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
6998 SND_SOC_DAPM_MUX_E("RX INT3 MIX2 INP", SND_SOC_NOPM, INTERP_LO1,
6999 0, &rx_int3_mix2_inp_mux, tavil_codec_enable_rx_path_clk,
7000 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
7001 SND_SOC_DAPM_MUX_E("RX INT4 MIX2 INP", SND_SOC_NOPM, INTERP_LO2,
7002 0, &rx_int4_mix2_inp_mux, tavil_codec_enable_rx_path_clk,
7003 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
7004 SND_SOC_DAPM_MUX_E("RX INT7 MIX2 INP", SND_SOC_NOPM, INTERP_SPKR1,
7005 0, &rx_int7_mix2_inp_mux, tavil_codec_enable_rx_path_clk,
7006 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
7007
7008 WCD_DAPM_MUX("CDC_IF TX0 MUX", WCD934X_TX0, cdc_if_tx0),
7009 WCD_DAPM_MUX("CDC_IF TX1 MUX", WCD934X_TX1, cdc_if_tx1),
7010 WCD_DAPM_MUX("CDC_IF TX2 MUX", WCD934X_TX2, cdc_if_tx2),
7011 WCD_DAPM_MUX("CDC_IF TX3 MUX", WCD934X_TX3, cdc_if_tx3),
7012 WCD_DAPM_MUX("CDC_IF TX4 MUX", WCD934X_TX4, cdc_if_tx4),
7013 WCD_DAPM_MUX("CDC_IF TX5 MUX", WCD934X_TX5, cdc_if_tx5),
7014 WCD_DAPM_MUX("CDC_IF TX6 MUX", WCD934X_TX6, cdc_if_tx6),
7015 WCD_DAPM_MUX("CDC_IF TX7 MUX", WCD934X_TX7, cdc_if_tx7),
7016 WCD_DAPM_MUX("CDC_IF TX8 MUX", WCD934X_TX8, cdc_if_tx8),
7017 WCD_DAPM_MUX("CDC_IF TX9 MUX", WCD934X_TX9, cdc_if_tx9),
7018 WCD_DAPM_MUX("CDC_IF TX10 MUX", WCD934X_TX10, cdc_if_tx10),
7019 WCD_DAPM_MUX("CDC_IF TX11 MUX", WCD934X_TX11, cdc_if_tx11),
7020 WCD_DAPM_MUX("CDC_IF TX11 INP1 MUX", WCD934X_TX11, cdc_if_tx11_inp1),
7021 WCD_DAPM_MUX("CDC_IF TX13 MUX", WCD934X_TX13, cdc_if_tx13),
7022 WCD_DAPM_MUX("CDC_IF TX13 INP1 MUX", WCD934X_TX13, cdc_if_tx13_inp1),
7023
7024 SND_SOC_DAPM_MUX_E("ADC MUX0", WCD934X_CDC_TX0_TX_PATH_CTL, 5, 0,
7025 &tx_adc_mux0_mux, tavil_codec_enable_dec,
7026 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
7027 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
7028
7029 SND_SOC_DAPM_MUX_E("ADC MUX1", WCD934X_CDC_TX1_TX_PATH_CTL, 5, 0,
7030 &tx_adc_mux1_mux, tavil_codec_enable_dec,
7031 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
7032 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
7033
7034 SND_SOC_DAPM_MUX_E("ADC MUX2", WCD934X_CDC_TX2_TX_PATH_CTL, 5, 0,
7035 &tx_adc_mux2_mux, tavil_codec_enable_dec,
7036 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
7037 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
7038
7039 SND_SOC_DAPM_MUX_E("ADC MUX3", WCD934X_CDC_TX3_TX_PATH_CTL, 5, 0,
7040 &tx_adc_mux3_mux, tavil_codec_enable_dec,
7041 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
7042 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
7043
7044 SND_SOC_DAPM_MUX_E("ADC MUX4", WCD934X_CDC_TX4_TX_PATH_CTL, 5, 0,
7045 &tx_adc_mux4_mux, tavil_codec_enable_dec,
7046 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
7047 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
7048
7049 SND_SOC_DAPM_MUX_E("ADC MUX5", WCD934X_CDC_TX5_TX_PATH_CTL, 5, 0,
7050 &tx_adc_mux5_mux, tavil_codec_enable_dec,
7051 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
7052 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
7053
7054 SND_SOC_DAPM_MUX_E("ADC MUX6", WCD934X_CDC_TX6_TX_PATH_CTL, 5, 0,
7055 &tx_adc_mux6_mux, tavil_codec_enable_dec,
7056 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
7057 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
7058
7059 SND_SOC_DAPM_MUX_E("ADC MUX7", WCD934X_CDC_TX7_TX_PATH_CTL, 5, 0,
7060 &tx_adc_mux7_mux, tavil_codec_enable_dec,
7061 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
7062 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
7063
7064 SND_SOC_DAPM_MUX_E("ADC MUX8", WCD934X_CDC_TX8_TX_PATH_CTL, 5, 0,
7065 &tx_adc_mux8_mux, tavil_codec_enable_dec,
7066 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
7067 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
7068
7069 SND_SOC_DAPM_MUX_E("ADC MUX10", SND_SOC_NOPM, 10, 0, &tx_adc_mux10_mux,
7070 tavil_codec_tx_adc_cfg, SND_SOC_DAPM_POST_PMU),
7071
7072 SND_SOC_DAPM_MUX_E("ADC MUX11", SND_SOC_NOPM, 11, 0, &tx_adc_mux11_mux,
7073 tavil_codec_tx_adc_cfg, SND_SOC_DAPM_POST_PMU),
7074
7075 SND_SOC_DAPM_MUX_E("ADC MUX12", SND_SOC_NOPM, 12, 0, &tx_adc_mux12_mux,
7076 tavil_codec_tx_adc_cfg, SND_SOC_DAPM_POST_PMU),
7077
7078 SND_SOC_DAPM_MUX_E("ADC MUX13", SND_SOC_NOPM, 13, 0, &tx_adc_mux13_mux,
7079 tavil_codec_tx_adc_cfg, SND_SOC_DAPM_POST_PMU),
7080
7081 WCD_DAPM_MUX("DMIC MUX0", 0, tx_dmic_mux0),
7082 WCD_DAPM_MUX("DMIC MUX1", 0, tx_dmic_mux1),
7083 WCD_DAPM_MUX("DMIC MUX2", 0, tx_dmic_mux2),
7084 WCD_DAPM_MUX("DMIC MUX3", 0, tx_dmic_mux3),
7085 WCD_DAPM_MUX("DMIC MUX4", 0, tx_dmic_mux4),
7086 WCD_DAPM_MUX("DMIC MUX5", 0, tx_dmic_mux5),
7087 WCD_DAPM_MUX("DMIC MUX6", 0, tx_dmic_mux6),
7088 WCD_DAPM_MUX("DMIC MUX7", 0, tx_dmic_mux7),
7089 WCD_DAPM_MUX("DMIC MUX8", 0, tx_dmic_mux8),
7090 WCD_DAPM_MUX("DMIC MUX10", 0, tx_dmic_mux10),
7091 WCD_DAPM_MUX("DMIC MUX11", 0, tx_dmic_mux11),
7092 WCD_DAPM_MUX("DMIC MUX12", 0, tx_dmic_mux12),
7093 WCD_DAPM_MUX("DMIC MUX13", 0, tx_dmic_mux13),
7094
7095 WCD_DAPM_MUX("AMIC MUX0", 0, tx_amic_mux0),
7096 WCD_DAPM_MUX("AMIC MUX1", 0, tx_amic_mux1),
7097 WCD_DAPM_MUX("AMIC MUX2", 0, tx_amic_mux2),
7098 WCD_DAPM_MUX("AMIC MUX3", 0, tx_amic_mux3),
7099 WCD_DAPM_MUX("AMIC MUX4", 0, tx_amic_mux4),
7100 WCD_DAPM_MUX("AMIC MUX5", 0, tx_amic_mux5),
7101 WCD_DAPM_MUX("AMIC MUX6", 0, tx_amic_mux6),
7102 WCD_DAPM_MUX("AMIC MUX7", 0, tx_amic_mux7),
7103 WCD_DAPM_MUX("AMIC MUX8", 0, tx_amic_mux8),
7104 WCD_DAPM_MUX("AMIC MUX10", 0, tx_amic_mux10),
7105 WCD_DAPM_MUX("AMIC MUX11", 0, tx_amic_mux11),
7106 WCD_DAPM_MUX("AMIC MUX12", 0, tx_amic_mux12),
7107 WCD_DAPM_MUX("AMIC MUX13", 0, tx_amic_mux13),
7108
7109 SND_SOC_DAPM_ADC_E("ADC1", NULL, WCD934X_ANA_AMIC1, 7, 0,
7110 tavil_codec_enable_adc, SND_SOC_DAPM_PRE_PMU),
7111 SND_SOC_DAPM_ADC_E("ADC2", NULL, WCD934X_ANA_AMIC2, 7, 0,
7112 tavil_codec_enable_adc, SND_SOC_DAPM_PRE_PMU),
7113 SND_SOC_DAPM_ADC_E("ADC3", NULL, WCD934X_ANA_AMIC3, 7, 0,
7114 tavil_codec_enable_adc, SND_SOC_DAPM_PRE_PMU),
7115 SND_SOC_DAPM_ADC_E("ADC4", NULL, WCD934X_ANA_AMIC4, 7, 0,
7116 tavil_codec_enable_adc, SND_SOC_DAPM_PRE_PMU),
7117
7118 WCD_DAPM_MUX("AMIC4_5 SEL", 0, tx_amic4_5),
7119
7120 WCD_DAPM_MUX("ANC0 FB MUX", 0, anc0_fb),
7121 WCD_DAPM_MUX("ANC1 FB MUX", 0, anc1_fb),
7122
7123 SND_SOC_DAPM_INPUT("AMIC1"),
7124 SND_SOC_DAPM_INPUT("AMIC2"),
7125 SND_SOC_DAPM_INPUT("AMIC3"),
7126 SND_SOC_DAPM_INPUT("AMIC4"),
7127 SND_SOC_DAPM_INPUT("AMIC5"),
7128
7129 SND_SOC_DAPM_MICBIAS_E("MIC BIAS1", SND_SOC_NOPM, 0, 0,
7130 tavil_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
7131 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
7132 SND_SOC_DAPM_MICBIAS_E("MIC BIAS2", SND_SOC_NOPM, 0, 0,
7133 tavil_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
7134 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
7135 SND_SOC_DAPM_MICBIAS_E("MIC BIAS3", SND_SOC_NOPM, 0, 0,
7136 tavil_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
7137 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
7138 SND_SOC_DAPM_MICBIAS_E("MIC BIAS4", SND_SOC_NOPM, 0, 0,
7139 tavil_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
7140 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
7141
7142 /*
7143 * Not supply widget, this is used to recover HPH registers.
7144 * It is not connected to any other widgets
7145 */
7146 SND_SOC_DAPM_SUPPLY("RESET_HPH_REGISTERS", SND_SOC_NOPM,
7147 0, 0, tavil_codec_reset_hph_registers,
7148 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
7149
7150 SND_SOC_DAPM_MICBIAS_E(DAPM_MICBIAS1_STANDALONE, SND_SOC_NOPM, 0, 0,
7151 tavil_codec_force_enable_micbias,
7152 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
7153 SND_SOC_DAPM_MICBIAS_E(DAPM_MICBIAS2_STANDALONE, SND_SOC_NOPM, 0, 0,
7154 tavil_codec_force_enable_micbias,
7155 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
7156 SND_SOC_DAPM_MICBIAS_E(DAPM_MICBIAS3_STANDALONE, SND_SOC_NOPM, 0, 0,
7157 tavil_codec_force_enable_micbias,
7158 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
7159 SND_SOC_DAPM_MICBIAS_E(DAPM_MICBIAS4_STANDALONE, SND_SOC_NOPM, 0, 0,
7160 tavil_codec_force_enable_micbias,
7161 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
7162
7163 SND_SOC_DAPM_AIF_OUT_E("AIF1 CAP", "AIF1 Capture", 0, SND_SOC_NOPM,
7164 AIF1_CAP, 0, tavil_codec_enable_slimtx,
7165 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
7166 SND_SOC_DAPM_AIF_OUT_E("AIF2 CAP", "AIF2 Capture", 0, SND_SOC_NOPM,
7167 AIF2_CAP, 0, tavil_codec_enable_slimtx,
7168 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
7169 SND_SOC_DAPM_AIF_OUT_E("AIF3 CAP", "AIF3 Capture", 0, SND_SOC_NOPM,
7170 AIF3_CAP, 0, tavil_codec_enable_slimtx,
7171 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
7172 SND_SOC_DAPM_MIXER("AIF1_CAP Mixer", SND_SOC_NOPM, AIF1_CAP, 0,
7173 aif1_cap_mixer, ARRAY_SIZE(aif1_cap_mixer)),
7174 SND_SOC_DAPM_MIXER("AIF2_CAP Mixer", SND_SOC_NOPM, AIF2_CAP, 0,
7175 aif2_cap_mixer, ARRAY_SIZE(aif2_cap_mixer)),
7176 SND_SOC_DAPM_MIXER("AIF3_CAP Mixer", SND_SOC_NOPM, AIF3_CAP, 0,
7177 aif3_cap_mixer, ARRAY_SIZE(aif3_cap_mixer)),
7178 SND_SOC_DAPM_MIXER("AIF4_MAD Mixer", SND_SOC_NOPM, AIF4_MAD_TX, 0,
7179 aif4_mad_mixer, ARRAY_SIZE(aif4_mad_mixer)),
7180
7181 SND_SOC_DAPM_AIF_OUT_E("AIF4 VI", "VIfeed", 0, SND_SOC_NOPM,
7182 AIF4_VIFEED, 0, tavil_codec_enable_slimvi_feedback,
7183 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
7184
7185 SND_SOC_DAPM_AIF_OUT("AIF4 MAD", "AIF4 MAD TX", 0,
7186 SND_SOC_NOPM, 0, 0),
7187
7188 SND_SOC_DAPM_MIXER("AIF4_VI Mixer", SND_SOC_NOPM, AIF4_VIFEED, 0,
7189 aif4_vi_mixer, ARRAY_SIZE(aif4_vi_mixer)),
7190 SND_SOC_DAPM_INPUT("VIINPUT"),
7191
7192 SND_SOC_DAPM_MIXER("SLIM TX0", SND_SOC_NOPM, 0, 0, NULL, 0),
7193 SND_SOC_DAPM_MIXER("SLIM TX1", SND_SOC_NOPM, 0, 0, NULL, 0),
7194 SND_SOC_DAPM_MIXER("SLIM TX2", SND_SOC_NOPM, 0, 0, NULL, 0),
7195 SND_SOC_DAPM_MIXER("SLIM TX3", SND_SOC_NOPM, 0, 0, NULL, 0),
7196 SND_SOC_DAPM_MIXER("SLIM TX4", SND_SOC_NOPM, 0, 0, NULL, 0),
7197 SND_SOC_DAPM_MIXER("SLIM TX5", SND_SOC_NOPM, 0, 0, NULL, 0),
7198 SND_SOC_DAPM_MIXER("SLIM TX6", SND_SOC_NOPM, 0, 0, NULL, 0),
7199 SND_SOC_DAPM_MIXER("SLIM TX7", SND_SOC_NOPM, 0, 0, NULL, 0),
7200 SND_SOC_DAPM_MIXER("SLIM TX8", SND_SOC_NOPM, 0, 0, NULL, 0),
7201 SND_SOC_DAPM_MIXER("SLIM TX9", SND_SOC_NOPM, 0, 0, NULL, 0),
7202 SND_SOC_DAPM_MIXER("SLIM TX10", SND_SOC_NOPM, 0, 0, NULL, 0),
7203 SND_SOC_DAPM_MIXER("SLIM TX11", SND_SOC_NOPM, 0, 0, NULL, 0),
7204 SND_SOC_DAPM_MIXER("SLIM TX13", SND_SOC_NOPM, 0, 0, NULL, 0),
7205
7206 /* Digital Mic Inputs */
7207 SND_SOC_DAPM_ADC_E("DMIC0", NULL, SND_SOC_NOPM, 0, 0,
7208 tavil_codec_enable_dmic,
7209 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
7210 SND_SOC_DAPM_ADC_E("DMIC1", NULL, SND_SOC_NOPM, 0, 0,
7211 tavil_codec_enable_dmic,
7212 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
7213 SND_SOC_DAPM_ADC_E("DMIC2", NULL, SND_SOC_NOPM, 0, 0,
7214 tavil_codec_enable_dmic,
7215 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
7216 SND_SOC_DAPM_ADC_E("DMIC3", NULL, SND_SOC_NOPM, 0, 0,
7217 tavil_codec_enable_dmic,
7218 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
7219 SND_SOC_DAPM_ADC_E("DMIC4", NULL, SND_SOC_NOPM, 0, 0,
7220 tavil_codec_enable_dmic,
7221 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
7222 SND_SOC_DAPM_ADC_E("DMIC5", NULL, SND_SOC_NOPM, 0, 0,
7223 tavil_codec_enable_dmic,
7224 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
7225
7226 WCD_DAPM_MUX("IIR0 INP0 MUX", 0, iir0_inp0),
7227 WCD_DAPM_MUX("IIR0 INP1 MUX", 0, iir0_inp1),
7228 WCD_DAPM_MUX("IIR0 INP2 MUX", 0, iir0_inp2),
7229 WCD_DAPM_MUX("IIR0 INP3 MUX", 0, iir0_inp3),
7230 WCD_DAPM_MUX("IIR1 INP0 MUX", 0, iir1_inp0),
7231 WCD_DAPM_MUX("IIR1 INP1 MUX", 0, iir1_inp1),
7232 WCD_DAPM_MUX("IIR1 INP2 MUX", 0, iir1_inp2),
7233 WCD_DAPM_MUX("IIR1 INP3 MUX", 0, iir1_inp3),
7234
7235 SND_SOC_DAPM_MIXER_E("IIR0", WCD934X_CDC_SIDETONE_IIR0_IIR_PATH_CTL,
7236 4, 0, NULL, 0, tavil_codec_set_iir_gain,
7237 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
7238 SND_SOC_DAPM_MIXER_E("IIR1", WCD934X_CDC_SIDETONE_IIR1_IIR_PATH_CTL,
7239 4, 0, NULL, 0, tavil_codec_set_iir_gain,
7240 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
7241 SND_SOC_DAPM_MIXER("SRC0", WCD934X_CDC_SIDETONE_SRC0_ST_SRC_PATH_CTL,
7242 4, 0, NULL, 0),
7243 SND_SOC_DAPM_MIXER("SRC1", WCD934X_CDC_SIDETONE_SRC1_ST_SRC_PATH_CTL,
7244 4, 0, NULL, 0),
7245
7246 WCD_DAPM_MUX("RX MIX TX0 MUX", 0, rx_mix_tx0),
7247 WCD_DAPM_MUX("RX MIX TX1 MUX", 0, rx_mix_tx1),
7248 WCD_DAPM_MUX("RX MIX TX2 MUX", 0, rx_mix_tx2),
7249 WCD_DAPM_MUX("RX MIX TX3 MUX", 0, rx_mix_tx3),
7250 WCD_DAPM_MUX("RX MIX TX4 MUX", 0, rx_mix_tx4),
7251 WCD_DAPM_MUX("RX MIX TX5 MUX", 0, rx_mix_tx5),
7252 WCD_DAPM_MUX("RX MIX TX6 MUX", 0, rx_mix_tx6),
7253 WCD_DAPM_MUX("RX MIX TX7 MUX", 0, rx_mix_tx7),
7254 WCD_DAPM_MUX("RX MIX TX8 MUX", 0, rx_mix_tx8),
7255 WCD_DAPM_MUX("RX INT0 DEM MUX", 0, rx_int0_dem_inp),
7256 WCD_DAPM_MUX("RX INT1 DEM MUX", 0, rx_int1_dem_inp),
7257 WCD_DAPM_MUX("RX INT2 DEM MUX", 0, rx_int2_dem_inp),
7258
7259 SND_SOC_DAPM_MUX_E("RX INT0_1 INTERP", SND_SOC_NOPM, INTERP_EAR, 0,
7260 &rx_int0_1_interp_mux, tavil_codec_enable_main_path,
7261 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
7262 SND_SOC_DAPM_POST_PMD),
7263 SND_SOC_DAPM_MUX_E("RX INT1_1 INTERP", SND_SOC_NOPM, INTERP_HPHL, 0,
7264 &rx_int1_1_interp_mux, tavil_codec_enable_main_path,
7265 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
7266 SND_SOC_DAPM_POST_PMD),
7267 SND_SOC_DAPM_MUX_E("RX INT2_1 INTERP", SND_SOC_NOPM, INTERP_HPHR, 0,
7268 &rx_int2_1_interp_mux, tavil_codec_enable_main_path,
7269 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
7270 SND_SOC_DAPM_POST_PMD),
7271 SND_SOC_DAPM_MUX_E("RX INT3_1 INTERP", SND_SOC_NOPM, INTERP_LO1, 0,
7272 &rx_int3_1_interp_mux, tavil_codec_enable_main_path,
7273 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
7274 SND_SOC_DAPM_POST_PMD),
7275 SND_SOC_DAPM_MUX_E("RX INT4_1 INTERP", SND_SOC_NOPM, INTERP_LO2, 0,
7276 &rx_int4_1_interp_mux, tavil_codec_enable_main_path,
7277 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
7278 SND_SOC_DAPM_POST_PMD),
7279 SND_SOC_DAPM_MUX_E("RX INT7_1 INTERP", SND_SOC_NOPM, INTERP_SPKR1, 0,
7280 &rx_int7_1_interp_mux, tavil_codec_enable_main_path,
7281 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
7282 SND_SOC_DAPM_POST_PMD),
7283 SND_SOC_DAPM_MUX_E("RX INT8_1 INTERP", SND_SOC_NOPM, INTERP_SPKR2, 0,
7284 &rx_int8_1_interp_mux, tavil_codec_enable_main_path,
7285 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
7286 SND_SOC_DAPM_POST_PMD),
7287
7288 WCD_DAPM_MUX("RX INT0_2 INTERP", 0, rx_int0_2_interp),
7289 WCD_DAPM_MUX("RX INT1_2 INTERP", 0, rx_int1_2_interp),
7290 WCD_DAPM_MUX("RX INT2_2 INTERP", 0, rx_int2_2_interp),
7291 WCD_DAPM_MUX("RX INT3_2 INTERP", 0, rx_int3_2_interp),
7292 WCD_DAPM_MUX("RX INT4_2 INTERP", 0, rx_int4_2_interp),
7293 WCD_DAPM_MUX("RX INT7_2 INTERP", 0, rx_int7_2_interp),
7294 WCD_DAPM_MUX("RX INT8_2 INTERP", 0, rx_int8_2_interp),
7295
7296 SND_SOC_DAPM_SWITCH("ADC US MUX0", WCD934X_CDC_TX0_TX_PATH_192_CTL, 0,
7297 0, &adc_us_mux0_switch),
7298 SND_SOC_DAPM_SWITCH("ADC US MUX1", WCD934X_CDC_TX1_TX_PATH_192_CTL, 0,
7299 0, &adc_us_mux1_switch),
7300 SND_SOC_DAPM_SWITCH("ADC US MUX2", WCD934X_CDC_TX2_TX_PATH_192_CTL, 0,
7301 0, &adc_us_mux2_switch),
7302 SND_SOC_DAPM_SWITCH("ADC US MUX3", WCD934X_CDC_TX3_TX_PATH_192_CTL, 0,
7303 0, &adc_us_mux3_switch),
7304 SND_SOC_DAPM_SWITCH("ADC US MUX4", WCD934X_CDC_TX4_TX_PATH_192_CTL, 0,
7305 0, &adc_us_mux4_switch),
7306 SND_SOC_DAPM_SWITCH("ADC US MUX5", WCD934X_CDC_TX5_TX_PATH_192_CTL, 0,
7307 0, &adc_us_mux5_switch),
7308 SND_SOC_DAPM_SWITCH("ADC US MUX6", WCD934X_CDC_TX6_TX_PATH_192_CTL, 0,
7309 0, &adc_us_mux6_switch),
7310 SND_SOC_DAPM_SWITCH("ADC US MUX7", WCD934X_CDC_TX7_TX_PATH_192_CTL, 0,
7311 0, &adc_us_mux7_switch),
7312 SND_SOC_DAPM_SWITCH("ADC US MUX8", WCD934X_CDC_TX8_TX_PATH_192_CTL, 0,
7313 0, &adc_us_mux8_switch),
7314
7315 /* MAD related widgets */
7316 SND_SOC_DAPM_INPUT("MAD_CPE_INPUT"),
7317 SND_SOC_DAPM_INPUT("MADINPUT"),
7318
7319 WCD_DAPM_MUX("MAD_SEL MUX", 0, mad_sel),
7320 WCD_DAPM_MUX("MAD_INP MUX", 0, mad_inp_mux),
7321
7322 SND_SOC_DAPM_SWITCH_E("MAD_BROADCAST", SND_SOC_NOPM, 0, 0,
7323 &mad_brdcst_switch, tavil_codec_ape_enable_mad,
7324 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD),
7325
7326 SND_SOC_DAPM_SWITCH_E("MAD_CPE1", SND_SOC_NOPM, 0, 0,
7327 &mad_cpe1_switch, tavil_codec_cpe_mad_ctl,
7328 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD),
7329 SND_SOC_DAPM_SWITCH_E("MAD_CPE2", SND_SOC_NOPM, 0, 0,
7330 &mad_cpe2_switch, tavil_codec_cpe_mad_ctl,
7331 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD),
7332
7333 SND_SOC_DAPM_OUTPUT("MAD_CPE_OUT1"),
7334 SND_SOC_DAPM_OUTPUT("MAD_CPE_OUT2"),
7335
7336 SND_SOC_DAPM_DAC_E("RX INT0 DAC", NULL, SND_SOC_NOPM,
7337 0, 0, tavil_codec_ear_dac_event,
7338 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
7339 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
7340 SND_SOC_DAPM_DAC_E("RX INT1 DAC", NULL, WCD934X_ANA_HPH,
7341 5, 0, tavil_codec_hphl_dac_event,
7342 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
7343 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
7344 SND_SOC_DAPM_DAC_E("RX INT2 DAC", NULL, WCD934X_ANA_HPH,
7345 4, 0, tavil_codec_hphr_dac_event,
7346 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
7347 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
7348 SND_SOC_DAPM_DAC_E("RX INT3 DAC", NULL, SND_SOC_NOPM,
7349 0, 0, tavil_codec_lineout_dac_event,
7350 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
7351 SND_SOC_DAPM_DAC_E("RX INT4 DAC", NULL, SND_SOC_NOPM,
7352 0, 0, tavil_codec_lineout_dac_event,
7353 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
7354
7355 SND_SOC_DAPM_PGA_E("EAR PA", WCD934X_ANA_EAR, 7, 0, NULL, 0,
7356 tavil_codec_enable_ear_pa,
7357 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
7358 SND_SOC_DAPM_PGA_E("HPHL PA", WCD934X_ANA_HPH, 7, 0, NULL, 0,
7359 tavil_codec_enable_hphl_pa,
7360 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
7361 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
7362 SND_SOC_DAPM_PGA_E("HPHR PA", WCD934X_ANA_HPH, 6, 0, NULL, 0,
7363 tavil_codec_enable_hphr_pa,
7364 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
7365 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
7366 SND_SOC_DAPM_PGA_E("LINEOUT1 PA", WCD934X_ANA_LO_1_2, 7, 0, NULL, 0,
7367 tavil_codec_enable_lineout_pa,
7368 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
Phani Kumar Uppalapatia1f87022017-01-25 19:13:13 -08007369 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
Banajit Goswamide8271c2017-01-18 00:28:59 -08007370 SND_SOC_DAPM_PGA_E("LINEOUT2 PA", WCD934X_ANA_LO_1_2, 6, 0, NULL, 0,
7371 tavil_codec_enable_lineout_pa,
7372 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
Phani Kumar Uppalapatia1f87022017-01-25 19:13:13 -08007373 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
Banajit Goswamide8271c2017-01-18 00:28:59 -08007374 SND_SOC_DAPM_PGA_E("ANC EAR PA", WCD934X_ANA_EAR, 7, 0, NULL, 0,
7375 tavil_codec_enable_ear_pa, SND_SOC_DAPM_POST_PMU |
7376 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
7377 SND_SOC_DAPM_PGA_E("ANC SPK1 PA", SND_SOC_NOPM, 0, 0, NULL, 0,
7378 tavil_codec_enable_spkr_anc,
7379 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
Meng Wangf45a20d2017-01-18 09:51:58 +08007380 SND_SOC_DAPM_PGA_E("ANC HPHL PA", SND_SOC_NOPM, 0, 0, NULL, 0,
7381 tavil_codec_enable_hphl_pa,
7382 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
7383 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
7384 SND_SOC_DAPM_PGA_E("ANC HPHR PA", SND_SOC_NOPM, 0, 0, NULL, 0,
7385 tavil_codec_enable_hphr_pa,
7386 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
7387 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
Banajit Goswamide8271c2017-01-18 00:28:59 -08007388
7389 SND_SOC_DAPM_OUTPUT("EAR"),
7390 SND_SOC_DAPM_OUTPUT("HPHL"),
7391 SND_SOC_DAPM_OUTPUT("HPHR"),
7392 SND_SOC_DAPM_OUTPUT("LINEOUT1"),
7393 SND_SOC_DAPM_OUTPUT("LINEOUT2"),
7394 SND_SOC_DAPM_OUTPUT("SPK1 OUT"),
7395 SND_SOC_DAPM_OUTPUT("SPK2 OUT"),
7396 SND_SOC_DAPM_OUTPUT("ANC EAR"),
Meng Wangf45a20d2017-01-18 09:51:58 +08007397 SND_SOC_DAPM_OUTPUT("ANC HPHL"),
7398 SND_SOC_DAPM_OUTPUT("ANC HPHR"),
Banajit Goswamide8271c2017-01-18 00:28:59 -08007399
7400 SND_SOC_DAPM_SWITCH("ANC OUT EAR Enable", SND_SOC_NOPM, 0, 0,
7401 &anc_ear_switch),
7402 SND_SOC_DAPM_SWITCH("ANC OUT EAR SPKR Enable", SND_SOC_NOPM, 0, 0,
7403 &anc_ear_spkr_switch),
7404 SND_SOC_DAPM_SWITCH("ANC SPKR PA Enable", SND_SOC_NOPM, 0, 0,
7405 &anc_spkr_pa_switch),
7406
Meng Wangf45a20d2017-01-18 09:51:58 +08007407 SND_SOC_DAPM_SWITCH_E("ANC OUT HPHL Enable", SND_SOC_NOPM, INTERP_HPHL,
7408 0, &anc_hphl_pa_switch, tavil_anc_out_switch_cb,
7409 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD),
7410 SND_SOC_DAPM_SWITCH_E("ANC OUT HPHR Enable", SND_SOC_NOPM, INTERP_HPHR,
7411 0, &anc_hphr_pa_switch, tavil_anc_out_switch_cb,
7412 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD),
7413
Banajit Goswamide8271c2017-01-18 00:28:59 -08007414 SND_SOC_DAPM_SUPPLY("RX_BIAS", SND_SOC_NOPM, 0, 0,
7415 tavil_codec_enable_rx_bias,
7416 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
7417
7418 SND_SOC_DAPM_SUPPLY("RX INT1 NATIVE SUPPLY", SND_SOC_NOPM,
7419 INTERP_HPHL, 0, tavil_enable_native_supply,
7420 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD),
7421 SND_SOC_DAPM_SUPPLY("RX INT2 NATIVE SUPPLY", SND_SOC_NOPM,
7422 INTERP_HPHR, 0, tavil_enable_native_supply,
7423 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD),
7424 SND_SOC_DAPM_SUPPLY("RX INT3 NATIVE SUPPLY", SND_SOC_NOPM,
7425 INTERP_LO1, 0, tavil_enable_native_supply,
7426 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD),
7427 SND_SOC_DAPM_SUPPLY("RX INT4 NATIVE SUPPLY", SND_SOC_NOPM,
7428 INTERP_LO2, 0, tavil_enable_native_supply,
7429 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD),
7430 SND_SOC_DAPM_SUPPLY("RX INT7 NATIVE SUPPLY", SND_SOC_NOPM,
7431 INTERP_SPKR1, 0, tavil_enable_native_supply,
7432 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD),
7433 SND_SOC_DAPM_SUPPLY("RX INT8 NATIVE SUPPLY", SND_SOC_NOPM,
7434 INTERP_SPKR2, 0, tavil_enable_native_supply,
7435 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD),
7436
7437 WCD_DAPM_MUX("RX INT1_1 NATIVE MUX", 0, int1_1_native),
7438 WCD_DAPM_MUX("RX INT2_1 NATIVE MUX", 0, int2_1_native),
7439 WCD_DAPM_MUX("RX INT3_1 NATIVE MUX", 0, int3_1_native),
7440 WCD_DAPM_MUX("RX INT4_1 NATIVE MUX", 0, int4_1_native),
7441
7442 WCD_DAPM_MUX("RX INT1_2 NATIVE MUX", 0, int1_2_native),
7443 WCD_DAPM_MUX("RX INT2_2 NATIVE MUX", 0, int2_2_native),
7444 WCD_DAPM_MUX("RX INT3_2 NATIVE MUX", 0, int3_2_native),
7445 WCD_DAPM_MUX("RX INT4_2 NATIVE MUX", 0, int4_2_native),
7446 WCD_DAPM_MUX("RX INT7_2 NATIVE MUX", 0, int7_2_native),
7447 WCD_DAPM_MUX("RX INT8_2 NATIVE MUX", 0, int8_2_native),
7448
7449 SND_SOC_DAPM_MUX_E("ASRC0 MUX", SND_SOC_NOPM, ASRC0, 0,
7450 &asrc0_mux, tavil_codec_enable_asrc_resampler,
7451 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
7452 SND_SOC_DAPM_MUX_E("ASRC1 MUX", SND_SOC_NOPM, ASRC1, 0,
7453 &asrc1_mux, tavil_codec_enable_asrc_resampler,
7454 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
7455 SND_SOC_DAPM_MUX_E("ASRC2 MUX", SND_SOC_NOPM, ASRC2, 0,
7456 &asrc2_mux, tavil_codec_enable_asrc_resampler,
7457 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
7458 SND_SOC_DAPM_MUX_E("ASRC3 MUX", SND_SOC_NOPM, ASRC3, 0,
7459 &asrc3_mux, tavil_codec_enable_asrc_resampler,
7460 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
7461};
7462
7463static int tavil_get_channel_map(struct snd_soc_dai *dai,
7464 unsigned int *tx_num, unsigned int *tx_slot,
7465 unsigned int *rx_num, unsigned int *rx_slot)
7466{
7467 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(dai->codec);
7468 u32 i = 0;
7469 struct wcd9xxx_ch *ch;
7470 int ret = 0;
7471
7472 switch (dai->id) {
7473 case AIF1_PB:
7474 case AIF2_PB:
7475 case AIF3_PB:
7476 case AIF4_PB:
7477 if (!rx_slot || !rx_num) {
7478 dev_err(tavil->dev, "%s: Invalid rx_slot 0x%pK or rx_num 0x%pK\n",
7479 __func__, rx_slot, rx_num);
7480 ret = -EINVAL;
7481 break;
7482 }
7483 list_for_each_entry(ch, &tavil->dai[dai->id].wcd9xxx_ch_list,
7484 list) {
7485 dev_dbg(tavil->dev, "%s: slot_num %u ch->ch_num %d\n",
7486 __func__, i, ch->ch_num);
7487 rx_slot[i++] = ch->ch_num;
7488 }
7489 *rx_num = i;
7490 dev_dbg(tavil->dev, "%s: dai_name = %s dai_id = %x rx_num = %d\n",
7491 __func__, dai->name, dai->id, i);
7492 if (*rx_num == 0) {
7493 dev_err(tavil->dev, "%s: Channel list empty for dai_name = %s dai_id = %x\n",
7494 __func__, dai->name, dai->id);
7495 ret = -EINVAL;
7496 }
7497 break;
7498 case AIF1_CAP:
7499 case AIF2_CAP:
7500 case AIF3_CAP:
7501 case AIF4_MAD_TX:
7502 case AIF4_VIFEED:
7503 if (!tx_slot || !tx_num) {
7504 dev_err(tavil->dev, "%s: Invalid tx_slot 0x%pK or tx_num 0x%pK\n",
7505 __func__, tx_slot, tx_num);
7506 ret = -EINVAL;
7507 break;
7508 }
7509 list_for_each_entry(ch, &tavil->dai[dai->id].wcd9xxx_ch_list,
7510 list) {
7511 dev_dbg(tavil->dev, "%s: slot_num %u ch->ch_num %d\n",
7512 __func__, i, ch->ch_num);
7513 tx_slot[i++] = ch->ch_num;
7514 }
7515 *tx_num = i;
7516 dev_dbg(tavil->dev, "%s: dai_name = %s dai_id = %x tx_num = %d\n",
7517 __func__, dai->name, dai->id, i);
7518 if (*tx_num == 0) {
7519 dev_err(tavil->dev, "%s: Channel list empty for dai_name = %s dai_id = %x\n",
7520 __func__, dai->name, dai->id);
7521 ret = -EINVAL;
7522 }
7523 break;
7524 default:
7525 dev_err(tavil->dev, "%s: Invalid DAI ID %x\n",
7526 __func__, dai->id);
7527 ret = -EINVAL;
7528 break;
7529 }
7530
7531 return ret;
7532}
7533
7534static int tavil_set_channel_map(struct snd_soc_dai *dai,
7535 unsigned int tx_num, unsigned int *tx_slot,
7536 unsigned int rx_num, unsigned int *rx_slot)
7537{
7538 struct tavil_priv *tavil;
7539 struct wcd9xxx *core;
7540 struct wcd9xxx_codec_dai_data *dai_data = NULL;
7541
7542 tavil = snd_soc_codec_get_drvdata(dai->codec);
7543 core = dev_get_drvdata(dai->codec->dev->parent);
7544
7545 if (!tx_slot || !rx_slot) {
7546 dev_err(tavil->dev, "%s: Invalid tx_slot 0x%pK, rx_slot 0x%pK\n",
7547 __func__, tx_slot, rx_slot);
7548 return -EINVAL;
7549 }
7550 dev_dbg(tavil->dev, "%s(): dai_name = %s DAI-ID %x tx_ch %d rx_ch %d\n",
7551 __func__, dai->name, dai->id, tx_num, rx_num);
7552
7553 wcd9xxx_init_slimslave(core, core->slim->laddr,
7554 tx_num, tx_slot, rx_num, rx_slot);
7555 /* Reserve TX13 for MAD data channel */
7556 dai_data = &tavil->dai[AIF4_MAD_TX];
7557 if (dai_data)
7558 list_add_tail(&core->tx_chs[WCD934X_TX13].list,
7559 &dai_data->wcd9xxx_ch_list);
7560
7561 return 0;
7562}
7563
7564static int tavil_startup(struct snd_pcm_substream *substream,
7565 struct snd_soc_dai *dai)
7566{
7567 pr_debug("%s(): substream = %s stream = %d\n", __func__,
7568 substream->name, substream->stream);
7569
7570 return 0;
7571}
7572
7573static void tavil_shutdown(struct snd_pcm_substream *substream,
7574 struct snd_soc_dai *dai)
7575{
7576 pr_debug("%s(): substream = %s stream = %d\n", __func__,
7577 substream->name, substream->stream);
7578}
7579
7580static int tavil_set_decimator_rate(struct snd_soc_dai *dai,
7581 u32 sample_rate)
7582{
7583 struct snd_soc_codec *codec = dai->codec;
7584 struct wcd9xxx_ch *ch;
7585 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
7586 u32 tx_port = 0, tx_fs_rate = 0;
7587 u8 shift = 0, shift_val = 0, tx_mux_sel = 0;
7588 int decimator = -1;
7589 u16 tx_port_reg = 0, tx_fs_reg = 0;
7590
7591 switch (sample_rate) {
7592 case 8000:
7593 tx_fs_rate = 0;
7594 break;
7595 case 16000:
7596 tx_fs_rate = 1;
7597 break;
7598 case 32000:
7599 tx_fs_rate = 3;
7600 break;
7601 case 48000:
7602 tx_fs_rate = 4;
7603 break;
7604 case 96000:
7605 tx_fs_rate = 5;
7606 break;
7607 case 192000:
7608 tx_fs_rate = 6;
7609 break;
7610 default:
7611 dev_err(tavil->dev, "%s: Invalid TX sample rate: %d\n",
7612 __func__, sample_rate);
7613 return -EINVAL;
7614
7615 };
7616
7617 list_for_each_entry(ch, &tavil->dai[dai->id].wcd9xxx_ch_list, list) {
7618 tx_port = ch->port;
7619 dev_dbg(codec->dev, "%s: dai->id = %d, tx_port = %d",
7620 __func__, dai->id, tx_port);
7621
7622 if ((tx_port < 0) || (tx_port == 12) || (tx_port >= 14)) {
7623 dev_err(codec->dev, "%s: Invalid SLIM TX%u port. DAI ID: %d\n",
7624 __func__, tx_port, dai->id);
7625 return -EINVAL;
7626 }
7627 /* Find the SB TX MUX input - which decimator is connected */
7628 if (tx_port < 4) {
7629 tx_port_reg = WCD934X_CDC_IF_ROUTER_TX_MUX_CFG0;
7630 shift = (tx_port << 1);
7631 shift_val = 0x03;
7632 } else if ((tx_port >= 4) && (tx_port < 8)) {
7633 tx_port_reg = WCD934X_CDC_IF_ROUTER_TX_MUX_CFG1;
7634 shift = ((tx_port - 4) << 1);
7635 shift_val = 0x03;
7636 } else if ((tx_port >= 8) && (tx_port < 11)) {
7637 tx_port_reg = WCD934X_CDC_IF_ROUTER_TX_MUX_CFG2;
7638 shift = ((tx_port - 8) << 1);
7639 shift_val = 0x03;
7640 } else if (tx_port == 11) {
7641 tx_port_reg = WCD934X_CDC_IF_ROUTER_TX_MUX_CFG3;
7642 shift = 0;
7643 shift_val = 0x0F;
7644 } else if (tx_port == 13) {
7645 tx_port_reg = WCD934X_CDC_IF_ROUTER_TX_MUX_CFG3;
7646 shift = 4;
7647 shift_val = 0x03;
7648 }
7649 tx_mux_sel = snd_soc_read(codec, tx_port_reg) &
7650 (shift_val << shift);
7651 tx_mux_sel = tx_mux_sel >> shift;
7652
7653 if (tx_port <= 8) {
7654 if ((tx_mux_sel == 0x2) || (tx_mux_sel == 0x3))
7655 decimator = tx_port;
7656 } else if (tx_port <= 10) {
7657 if ((tx_mux_sel == 0x1) || (tx_mux_sel == 0x2))
7658 decimator = ((tx_port == 9) ? 7 : 6);
7659 } else if (tx_port == 11) {
7660 if ((tx_mux_sel >= 1) && (tx_mux_sel < 7))
7661 decimator = tx_mux_sel - 1;
7662 } else if (tx_port == 13) {
7663 if ((tx_mux_sel == 0x1) || (tx_mux_sel == 0x2))
7664 decimator = 5;
7665 }
7666
7667 if (decimator >= 0) {
7668 tx_fs_reg = WCD934X_CDC_TX0_TX_PATH_CTL +
7669 16 * decimator;
7670 dev_dbg(codec->dev, "%s: set DEC%u (-> SLIM_TX%u) rate to %u\n",
7671 __func__, decimator, tx_port, sample_rate);
7672 snd_soc_update_bits(codec, tx_fs_reg, 0x0F, tx_fs_rate);
7673 } else if ((tx_port <= 8) && (tx_mux_sel == 0x01)) {
7674 /* Check if the TX Mux input is RX MIX TXn */
7675 dev_dbg(codec->dev, "%s: RX_MIX_TX%u going to CDC_IF TX%u\n",
7676 __func__, tx_port, tx_port);
7677 } else {
7678 dev_err(codec->dev, "%s: ERROR: Invalid decimator: %d\n",
7679 __func__, decimator);
7680 return -EINVAL;
7681 }
7682 }
7683 return 0;
7684}
7685
7686static int tavil_set_mix_interpolator_rate(struct snd_soc_dai *dai,
7687 u8 rate_reg_val,
7688 u32 sample_rate)
7689{
7690 u8 int_2_inp;
7691 u32 j;
7692 u16 int_mux_cfg1, int_fs_reg;
7693 u8 int_mux_cfg1_val;
7694 struct snd_soc_codec *codec = dai->codec;
7695 struct wcd9xxx_ch *ch;
7696 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
7697
7698 list_for_each_entry(ch, &tavil->dai[dai->id].wcd9xxx_ch_list, list) {
7699 int_2_inp = INTn_2_INP_SEL_RX0 + ch->port -
7700 WCD934X_RX_PORT_START_NUMBER;
7701 if ((int_2_inp < INTn_2_INP_SEL_RX0) ||
7702 (int_2_inp > INTn_2_INP_SEL_RX7)) {
7703 dev_err(codec->dev, "%s: Invalid RX%u port, Dai ID is %d\n",
7704 __func__,
7705 (ch->port - WCD934X_RX_PORT_START_NUMBER),
7706 dai->id);
7707 return -EINVAL;
7708 }
7709
7710 int_mux_cfg1 = WCD934X_CDC_RX_INP_MUX_RX_INT0_CFG1;
7711 for (j = 0; j < WCD934X_NUM_INTERPOLATORS; j++) {
7712 /* Interpolators 5 and 6 are not aviliable in Tavil */
7713 if (j == INTERP_LO3_NA || j == INTERP_LO4_NA) {
7714 int_mux_cfg1 += 2;
7715 continue;
7716 }
7717 int_mux_cfg1_val = snd_soc_read(codec, int_mux_cfg1) &
7718 0x0F;
7719 if (int_mux_cfg1_val == int_2_inp) {
7720 /*
7721 * Ear mix path supports only 48, 96, 192,
7722 * 384KHz only
7723 */
7724 if ((j == INTERP_EAR) &&
7725 (rate_reg_val < 0x4 ||
7726 rate_reg_val > 0x7)) {
7727 dev_err_ratelimited(codec->dev,
7728 "%s: Invalid rate for AIF_PB DAI(%d)\n",
7729 __func__, dai->id);
7730 return -EINVAL;
7731 }
7732
7733 int_fs_reg = WCD934X_CDC_RX0_RX_PATH_MIX_CTL +
7734 20 * j;
7735 dev_dbg(codec->dev, "%s: AIF_PB DAI(%d) connected to INT%u_2\n",
7736 __func__, dai->id, j);
7737 dev_dbg(codec->dev, "%s: set INT%u_2 sample rate to %u\n",
7738 __func__, j, sample_rate);
7739 snd_soc_update_bits(codec, int_fs_reg, 0x0F,
7740 rate_reg_val);
7741 }
7742 int_mux_cfg1 += 2;
7743 }
7744 }
7745 return 0;
7746}
7747
7748static int tavil_set_prim_interpolator_rate(struct snd_soc_dai *dai,
7749 u8 rate_reg_val,
7750 u32 sample_rate)
7751{
7752 u8 int_1_mix1_inp;
7753 u32 j;
7754 u16 int_mux_cfg0, int_mux_cfg1;
7755 u16 int_fs_reg;
7756 u8 int_mux_cfg0_val, int_mux_cfg1_val;
7757 u8 inp0_sel, inp1_sel, inp2_sel;
7758 struct snd_soc_codec *codec = dai->codec;
7759 struct wcd9xxx_ch *ch;
7760 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
7761 struct tavil_dsd_config *dsd_conf = tavil->dsd_config;
7762
7763 list_for_each_entry(ch, &tavil->dai[dai->id].wcd9xxx_ch_list, list) {
7764 int_1_mix1_inp = INTn_1_INP_SEL_RX0 + ch->port -
7765 WCD934X_RX_PORT_START_NUMBER;
7766 if ((int_1_mix1_inp < INTn_1_INP_SEL_RX0) ||
7767 (int_1_mix1_inp > INTn_1_INP_SEL_RX7)) {
7768 dev_err(codec->dev, "%s: Invalid RX%u port, Dai ID is %d\n",
7769 __func__,
7770 (ch->port - WCD934X_RX_PORT_START_NUMBER),
7771 dai->id);
7772 return -EINVAL;
7773 }
7774
7775 int_mux_cfg0 = WCD934X_CDC_RX_INP_MUX_RX_INT0_CFG0;
7776
7777 /*
7778 * Loop through all interpolator MUX inputs and find out
7779 * to which interpolator input, the slim rx port
7780 * is connected
7781 */
7782 for (j = 0; j < WCD934X_NUM_INTERPOLATORS; j++) {
7783 /* Interpolators 5 and 6 are not aviliable in Tavil */
7784 if (j == INTERP_LO3_NA || j == INTERP_LO4_NA) {
7785 int_mux_cfg0 += 2;
7786 continue;
7787 }
7788 int_mux_cfg1 = int_mux_cfg0 + 1;
7789
7790 int_mux_cfg0_val = snd_soc_read(codec, int_mux_cfg0);
7791 int_mux_cfg1_val = snd_soc_read(codec, int_mux_cfg1);
7792 inp0_sel = int_mux_cfg0_val & 0x0F;
7793 inp1_sel = (int_mux_cfg0_val >> 4) & 0x0F;
7794 inp2_sel = (int_mux_cfg1_val >> 4) & 0x0F;
7795 if ((inp0_sel == int_1_mix1_inp) ||
7796 (inp1_sel == int_1_mix1_inp) ||
7797 (inp2_sel == int_1_mix1_inp)) {
7798 /*
7799 * Ear and speaker primary path does not support
7800 * native sample rates
7801 */
7802 if ((j == INTERP_EAR || j == INTERP_SPKR1 ||
7803 j == INTERP_SPKR2) &&
7804 (rate_reg_val > 0x7)) {
7805 dev_err_ratelimited(codec->dev,
7806 "%s: Invalid rate for AIF_PB DAI(%d)\n",
7807 __func__, dai->id);
7808 return -EINVAL;
7809 }
7810
7811 int_fs_reg = WCD934X_CDC_RX0_RX_PATH_CTL +
7812 20 * j;
7813 dev_dbg(codec->dev,
7814 "%s: AIF_PB DAI(%d) connected to INT%u_1\n",
7815 __func__, dai->id, j);
7816 dev_dbg(codec->dev,
7817 "%s: set INT%u_1 sample rate to %u\n",
7818 __func__, j, sample_rate);
7819 snd_soc_update_bits(codec, int_fs_reg, 0x0F,
7820 rate_reg_val);
7821 }
7822 int_mux_cfg0 += 2;
7823 }
7824 if (dsd_conf)
7825 tavil_dsd_set_interp_rate(dsd_conf, ch->port,
7826 sample_rate, rate_reg_val);
7827 }
7828
7829 return 0;
7830}
7831
7832
7833static int tavil_set_interpolator_rate(struct snd_soc_dai *dai,
7834 u32 sample_rate)
7835{
7836 struct snd_soc_codec *codec = dai->codec;
7837 int rate_val = 0;
7838 int i, ret;
7839
7840 for (i = 0; i < ARRAY_SIZE(sr_val_tbl); i++) {
7841 if (sample_rate == sr_val_tbl[i].sample_rate) {
7842 rate_val = sr_val_tbl[i].rate_val;
7843 break;
7844 }
7845 }
7846 if ((i == ARRAY_SIZE(sr_val_tbl)) || (rate_val < 0)) {
7847 dev_err(codec->dev, "%s: Unsupported sample rate: %d\n",
7848 __func__, sample_rate);
7849 return -EINVAL;
7850 }
7851
7852 ret = tavil_set_prim_interpolator_rate(dai, (u8)rate_val, sample_rate);
7853 if (ret)
7854 return ret;
7855 ret = tavil_set_mix_interpolator_rate(dai, (u8)rate_val, sample_rate);
7856 if (ret)
7857 return ret;
7858
7859 return ret;
7860}
7861
7862static int tavil_prepare(struct snd_pcm_substream *substream,
7863 struct snd_soc_dai *dai)
7864{
7865 pr_debug("%s(): substream = %s stream = %d\n", __func__,
7866 substream->name, substream->stream);
7867 return 0;
7868}
7869
7870static int tavil_vi_hw_params(struct snd_pcm_substream *substream,
7871 struct snd_pcm_hw_params *params,
7872 struct snd_soc_dai *dai)
7873{
7874 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(dai->codec);
7875
7876 dev_dbg(tavil->dev, "%s: dai_name = %s DAI-ID %x rate %d num_ch %d\n",
7877 __func__, dai->name, dai->id, params_rate(params),
7878 params_channels(params));
7879
7880 tavil->dai[dai->id].rate = params_rate(params);
7881 tavil->dai[dai->id].bit_width = 32;
7882
7883 return 0;
7884}
7885
7886static int tavil_hw_params(struct snd_pcm_substream *substream,
7887 struct snd_pcm_hw_params *params,
7888 struct snd_soc_dai *dai)
7889{
7890 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(dai->codec);
7891 int ret = 0;
7892
7893 dev_dbg(tavil->dev, "%s: dai_name = %s DAI-ID %x rate %d num_ch %d\n",
7894 __func__, dai->name, dai->id, params_rate(params),
7895 params_channels(params));
7896
7897 switch (substream->stream) {
7898 case SNDRV_PCM_STREAM_PLAYBACK:
7899 ret = tavil_set_interpolator_rate(dai, params_rate(params));
7900 if (ret) {
7901 dev_err(tavil->dev, "%s: cannot set sample rate: %u\n",
7902 __func__, params_rate(params));
7903 return ret;
7904 }
7905 switch (params_width(params)) {
7906 case 16:
7907 tavil->dai[dai->id].bit_width = 16;
7908 break;
7909 case 24:
7910 tavil->dai[dai->id].bit_width = 24;
7911 break;
7912 case 32:
7913 tavil->dai[dai->id].bit_width = 32;
7914 break;
7915 default:
7916 return -EINVAL;
7917 }
7918 tavil->dai[dai->id].rate = params_rate(params);
7919 break;
7920 case SNDRV_PCM_STREAM_CAPTURE:
7921 if (dai->id != AIF4_MAD_TX)
7922 ret = tavil_set_decimator_rate(dai,
7923 params_rate(params));
7924 if (ret) {
7925 dev_err(tavil->dev, "%s: cannot set TX Decimator rate: %d\n",
7926 __func__, ret);
7927 return ret;
7928 }
7929 switch (params_width(params)) {
7930 case 16:
7931 tavil->dai[dai->id].bit_width = 16;
7932 break;
7933 case 24:
7934 tavil->dai[dai->id].bit_width = 24;
7935 break;
7936 default:
7937 dev_err(tavil->dev, "%s: Invalid format 0x%x\n",
7938 __func__, params_width(params));
7939 return -EINVAL;
7940 };
7941 tavil->dai[dai->id].rate = params_rate(params);
7942 break;
7943 default:
7944 dev_err(tavil->dev, "%s: Invalid stream type %d\n", __func__,
7945 substream->stream);
7946 return -EINVAL;
7947 };
7948
7949 return 0;
7950}
7951
7952static struct snd_soc_dai_ops tavil_dai_ops = {
7953 .startup = tavil_startup,
7954 .shutdown = tavil_shutdown,
7955 .hw_params = tavil_hw_params,
7956 .prepare = tavil_prepare,
7957 .set_channel_map = tavil_set_channel_map,
7958 .get_channel_map = tavil_get_channel_map,
7959};
7960
7961static struct snd_soc_dai_ops tavil_vi_dai_ops = {
7962 .hw_params = tavil_vi_hw_params,
7963 .set_channel_map = tavil_set_channel_map,
7964 .get_channel_map = tavil_get_channel_map,
7965};
7966
7967static struct snd_soc_dai_driver tavil_dai[] = {
7968 {
7969 .name = "tavil_rx1",
7970 .id = AIF1_PB,
7971 .playback = {
7972 .stream_name = "AIF1 Playback",
7973 .rates = WCD934X_RATES_MASK | WCD934X_FRAC_RATES_MASK,
7974 .formats = WCD934X_FORMATS_S16_S24_S32_LE,
7975 .rate_min = 8000,
7976 .rate_max = 384000,
7977 .channels_min = 1,
7978 .channels_max = 2,
7979 },
7980 .ops = &tavil_dai_ops,
7981 },
7982 {
7983 .name = "tavil_tx1",
7984 .id = AIF1_CAP,
7985 .capture = {
7986 .stream_name = "AIF1 Capture",
7987 .rates = WCD934X_RATES_MASK,
7988 .formats = WCD934X_FORMATS_S16_S24_LE,
7989 .rate_min = 8000,
7990 .rate_max = 192000,
7991 .channels_min = 1,
7992 .channels_max = 4,
7993 },
7994 .ops = &tavil_dai_ops,
7995 },
7996 {
7997 .name = "tavil_rx2",
7998 .id = AIF2_PB,
7999 .playback = {
8000 .stream_name = "AIF2 Playback",
8001 .rates = WCD934X_RATES_MASK | WCD934X_FRAC_RATES_MASK,
8002 .formats = WCD934X_FORMATS_S16_S24_S32_LE,
8003 .rate_min = 8000,
8004 .rate_max = 384000,
8005 .channels_min = 1,
8006 .channels_max = 2,
8007 },
8008 .ops = &tavil_dai_ops,
8009 },
8010 {
8011 .name = "tavil_tx2",
8012 .id = AIF2_CAP,
8013 .capture = {
8014 .stream_name = "AIF2 Capture",
8015 .rates = WCD934X_RATES_MASK,
8016 .formats = WCD934X_FORMATS_S16_S24_LE,
8017 .rate_min = 8000,
8018 .rate_max = 192000,
8019 .channels_min = 1,
8020 .channels_max = 4,
8021 },
8022 .ops = &tavil_dai_ops,
8023 },
8024 {
8025 .name = "tavil_rx3",
8026 .id = AIF3_PB,
8027 .playback = {
8028 .stream_name = "AIF3 Playback",
8029 .rates = WCD934X_RATES_MASK | WCD934X_FRAC_RATES_MASK,
8030 .formats = WCD934X_FORMATS_S16_S24_S32_LE,
8031 .rate_min = 8000,
8032 .rate_max = 384000,
8033 .channels_min = 1,
8034 .channels_max = 2,
8035 },
8036 .ops = &tavil_dai_ops,
8037 },
8038 {
8039 .name = "tavil_tx3",
8040 .id = AIF3_CAP,
8041 .capture = {
8042 .stream_name = "AIF3 Capture",
8043 .rates = WCD934X_RATES_MASK,
8044 .formats = WCD934X_FORMATS_S16_S24_LE,
8045 .rate_min = 8000,
8046 .rate_max = 192000,
8047 .channels_min = 1,
8048 .channels_max = 4,
8049 },
8050 .ops = &tavil_dai_ops,
8051 },
8052 {
8053 .name = "tavil_rx4",
8054 .id = AIF4_PB,
8055 .playback = {
8056 .stream_name = "AIF4 Playback",
8057 .rates = WCD934X_RATES_MASK | WCD934X_FRAC_RATES_MASK,
8058 .formats = WCD934X_FORMATS_S16_S24_S32_LE,
8059 .rate_min = 8000,
8060 .rate_max = 384000,
8061 .channels_min = 1,
8062 .channels_max = 2,
8063 },
8064 .ops = &tavil_dai_ops,
8065 },
8066 {
8067 .name = "tavil_vifeedback",
8068 .id = AIF4_VIFEED,
8069 .capture = {
8070 .stream_name = "VIfeed",
8071 .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_48000,
8072 .formats = WCD934X_FORMATS_S16_S24_S32_LE,
8073 .rate_min = 8000,
8074 .rate_max = 48000,
8075 .channels_min = 1,
8076 .channels_max = 4,
8077 },
8078 .ops = &tavil_vi_dai_ops,
8079 },
8080 {
8081 .name = "tavil_mad1",
8082 .id = AIF4_MAD_TX,
8083 .capture = {
8084 .stream_name = "AIF4 MAD TX",
8085 .rates = SNDRV_PCM_RATE_16000,
8086 .formats = WCD934X_FORMATS_S16_LE,
8087 .rate_min = 16000,
8088 .rate_max = 16000,
8089 .channels_min = 1,
8090 .channels_max = 1,
8091 },
8092 .ops = &tavil_dai_ops,
8093 },
8094};
8095
8096static void tavil_codec_power_gate_digital_core(struct tavil_priv *tavil)
8097{
8098 struct snd_soc_codec *codec = tavil->codec;
8099
8100 if (!codec)
8101 return;
8102
8103 mutex_lock(&tavil->power_lock);
8104 dev_dbg(codec->dev, "%s: Entering power gating function, %d\n",
8105 __func__, tavil->power_active_ref);
8106
8107 if (tavil->power_active_ref > 0)
8108 goto exit;
8109
8110 wcd9xxx_set_power_state(tavil->wcd9xxx,
8111 WCD_REGION_POWER_COLLAPSE_BEGIN,
8112 WCD9XXX_DIG_CORE_REGION_1);
8113 snd_soc_update_bits(codec, WCD934X_CODEC_RPM_PWR_CDC_DIG_HM_CTL,
8114 0x04, 0x04);
8115 snd_soc_update_bits(codec, WCD934X_CODEC_RPM_PWR_CDC_DIG_HM_CTL,
8116 0x01, 0x00);
8117 snd_soc_update_bits(codec, WCD934X_CODEC_RPM_PWR_CDC_DIG_HM_CTL,
8118 0x02, 0x00);
8119 wcd9xxx_set_power_state(tavil->wcd9xxx, WCD_REGION_POWER_DOWN,
8120 WCD9XXX_DIG_CORE_REGION_1);
8121exit:
8122 dev_dbg(codec->dev, "%s: Exiting power gating function, %d\n",
8123 __func__, tavil->power_active_ref);
8124 mutex_unlock(&tavil->power_lock);
8125}
8126
8127static void tavil_codec_power_gate_work(struct work_struct *work)
8128{
8129 struct tavil_priv *tavil;
8130 struct delayed_work *dwork;
8131 struct snd_soc_codec *codec;
8132
8133 dwork = to_delayed_work(work);
8134 tavil = container_of(dwork, struct tavil_priv, power_gate_work);
8135 codec = tavil->codec;
8136
8137 if (!codec)
8138 return;
8139
8140 tavil_codec_power_gate_digital_core(tavil);
8141}
8142
8143/* called under power_lock acquisition */
8144static int tavil_dig_core_remove_power_collapse(struct snd_soc_codec *codec)
8145{
8146 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
8147
8148 snd_soc_write(codec, WCD934X_CODEC_RPM_PWR_CDC_DIG_HM_CTL, 0x5);
8149 snd_soc_write(codec, WCD934X_CODEC_RPM_PWR_CDC_DIG_HM_CTL, 0x7);
Banajit Goswamide8271c2017-01-18 00:28:59 -08008150 snd_soc_update_bits(codec, WCD934X_CODEC_RPM_RST_CTL, 0x02, 0x00);
8151 snd_soc_update_bits(codec, WCD934X_CODEC_RPM_RST_CTL, 0x02, 0x02);
Phani Kumar Uppalapati7a489c52017-01-30 17:47:26 -08008152 snd_soc_write(codec, WCD934X_CODEC_RPM_PWR_CDC_DIG_HM_CTL, 0x3);
Banajit Goswamide8271c2017-01-18 00:28:59 -08008153
8154 wcd9xxx_set_power_state(tavil->wcd9xxx,
8155 WCD_REGION_POWER_COLLAPSE_REMOVE,
8156 WCD9XXX_DIG_CORE_REGION_1);
8157 regcache_mark_dirty(codec->component.regmap);
8158 regcache_sync_region(codec->component.regmap,
8159 WCD934X_DIG_CORE_REG_MIN,
8160 WCD934X_DIG_CORE_REG_MAX);
8161
8162 return 0;
8163}
8164
8165static int tavil_dig_core_power_collapse(struct tavil_priv *tavil,
8166 int req_state)
8167{
8168 struct snd_soc_codec *codec;
8169 int cur_state;
8170
8171 /* Exit if feature is disabled */
8172 if (!dig_core_collapse_enable)
8173 return 0;
8174
8175 mutex_lock(&tavil->power_lock);
8176 if (req_state == POWER_COLLAPSE)
8177 tavil->power_active_ref--;
8178 else if (req_state == POWER_RESUME)
8179 tavil->power_active_ref++;
8180 else
8181 goto unlock_mutex;
8182
8183 if (tavil->power_active_ref < 0) {
8184 dev_dbg(tavil->dev, "%s: power_active_ref is negative\n",
8185 __func__);
8186 goto unlock_mutex;
8187 }
8188
8189 codec = tavil->codec;
8190 if (!codec)
8191 goto unlock_mutex;
8192
8193 if (req_state == POWER_COLLAPSE) {
8194 if (tavil->power_active_ref == 0) {
8195 schedule_delayed_work(&tavil->power_gate_work,
8196 msecs_to_jiffies(dig_core_collapse_timer * 1000));
8197 }
8198 } else if (req_state == POWER_RESUME) {
8199 if (tavil->power_active_ref == 1) {
8200 /*
8201 * At this point, there can be two cases:
8202 * 1. Core already in power collapse state
8203 * 2. Timer kicked in and still did not expire or
8204 * waiting for the power_lock
8205 */
8206 cur_state = wcd9xxx_get_current_power_state(
8207 tavil->wcd9xxx,
8208 WCD9XXX_DIG_CORE_REGION_1);
8209 if (cur_state == WCD_REGION_POWER_DOWN) {
8210 tavil_dig_core_remove_power_collapse(codec);
8211 } else {
8212 mutex_unlock(&tavil->power_lock);
8213 cancel_delayed_work_sync(
8214 &tavil->power_gate_work);
8215 mutex_lock(&tavil->power_lock);
8216 }
8217 }
8218 }
8219
8220unlock_mutex:
8221 mutex_unlock(&tavil->power_lock);
8222
8223 return 0;
8224}
8225
8226static int tavil_cdc_req_mclk_enable(struct tavil_priv *tavil,
8227 bool enable)
8228{
8229 int ret = 0;
8230
8231 if (enable) {
8232 ret = clk_prepare_enable(tavil->wcd_ext_clk);
8233 if (ret) {
8234 dev_err(tavil->dev, "%s: ext clk enable failed\n",
8235 __func__);
8236 goto done;
8237 }
8238 /* get BG */
8239 wcd_resmgr_enable_master_bias(tavil->resmgr);
8240 /* get MCLK */
8241 wcd_resmgr_enable_clk_block(tavil->resmgr, WCD_CLK_MCLK);
8242 } else {
8243 /* put MCLK */
8244 wcd_resmgr_disable_clk_block(tavil->resmgr, WCD_CLK_MCLK);
8245 /* put BG */
8246 wcd_resmgr_disable_master_bias(tavil->resmgr);
8247 clk_disable_unprepare(tavil->wcd_ext_clk);
8248 }
8249
8250done:
8251 return ret;
8252}
8253
8254static int __tavil_cdc_mclk_enable_locked(struct tavil_priv *tavil,
8255 bool enable)
8256{
8257 int ret = 0;
8258
8259 if (!tavil->wcd_ext_clk) {
8260 dev_err(tavil->dev, "%s: wcd ext clock is NULL\n", __func__);
8261 return -EINVAL;
8262 }
8263
8264 dev_dbg(tavil->dev, "%s: mclk_enable = %u\n", __func__, enable);
8265
8266 if (enable) {
8267 tavil_dig_core_power_collapse(tavil, POWER_RESUME);
8268 tavil_vote_svs(tavil, true);
8269 ret = tavil_cdc_req_mclk_enable(tavil, true);
8270 if (ret)
8271 goto done;
8272 } else {
8273 tavil_cdc_req_mclk_enable(tavil, false);
8274 tavil_vote_svs(tavil, false);
8275 tavil_dig_core_power_collapse(tavil, POWER_COLLAPSE);
8276 }
8277
8278done:
8279 return ret;
8280}
8281
8282static int __tavil_cdc_mclk_enable(struct tavil_priv *tavil,
8283 bool enable)
8284{
8285 int ret;
8286
8287 WCD9XXX_V2_BG_CLK_LOCK(tavil->resmgr);
8288 ret = __tavil_cdc_mclk_enable_locked(tavil, enable);
8289 WCD9XXX_V2_BG_CLK_UNLOCK(tavil->resmgr);
8290
8291 return ret;
8292}
8293
8294static ssize_t tavil_codec_version_read(struct snd_info_entry *entry,
8295 void *file_private_data,
8296 struct file *file,
8297 char __user *buf, size_t count,
8298 loff_t pos)
8299{
8300 struct tavil_priv *tavil;
8301 struct wcd9xxx *wcd9xxx;
8302 char buffer[TAVIL_VERSION_ENTRY_SIZE];
8303 int len = 0;
8304
8305 tavil = (struct tavil_priv *) entry->private_data;
8306 if (!tavil) {
8307 pr_err("%s: tavil priv is null\n", __func__);
8308 return -EINVAL;
8309 }
8310
8311 wcd9xxx = tavil->wcd9xxx;
8312
8313 switch (wcd9xxx->version) {
8314 case TAVIL_VERSION_WCD9340_1_0:
8315 len = snprintf(buffer, sizeof(buffer), "WCD9340_1_0\n");
8316 break;
8317 case TAVIL_VERSION_WCD9341_1_0:
8318 len = snprintf(buffer, sizeof(buffer), "WCD9341_1_0\n");
8319 break;
8320 case TAVIL_VERSION_WCD9340_1_1:
8321 len = snprintf(buffer, sizeof(buffer), "WCD9340_1_1\n");
8322 break;
8323 case TAVIL_VERSION_WCD9341_1_1:
8324 len = snprintf(buffer, sizeof(buffer), "WCD9341_1_1\n");
8325 break;
8326 default:
8327 len = snprintf(buffer, sizeof(buffer), "VER_UNDEFINED\n");
8328 }
8329
8330 return simple_read_from_buffer(buf, count, &pos, buffer, len);
8331}
8332
8333static struct snd_info_entry_ops tavil_codec_info_ops = {
8334 .read = tavil_codec_version_read,
8335};
8336
8337/*
8338 * tavil_codec_info_create_codec_entry - creates wcd934x module
8339 * @codec_root: The parent directory
8340 * @codec: Codec instance
8341 *
8342 * Creates wcd934x module and version entry under the given
8343 * parent directory.
8344 *
8345 * Return: 0 on success or negative error code on failure.
8346 */
8347int tavil_codec_info_create_codec_entry(struct snd_info_entry *codec_root,
8348 struct snd_soc_codec *codec)
8349{
8350 struct snd_info_entry *version_entry;
8351 struct tavil_priv *tavil;
8352 struct snd_soc_card *card;
8353
8354 if (!codec_root || !codec)
8355 return -EINVAL;
8356
8357 tavil = snd_soc_codec_get_drvdata(codec);
8358 card = codec->component.card;
Banajit Goswami7f40ea42017-01-30 13:32:41 -08008359 tavil->entry = snd_info_create_subdir(codec_root->module,
8360 "tavil", codec_root);
Banajit Goswamide8271c2017-01-18 00:28:59 -08008361 if (!tavil->entry) {
8362 dev_dbg(codec->dev, "%s: failed to create wcd934x entry\n",
8363 __func__);
8364 return -ENOMEM;
8365 }
8366
8367 version_entry = snd_info_create_card_entry(card->snd_card,
8368 "version",
8369 tavil->entry);
8370 if (!version_entry) {
8371 dev_dbg(codec->dev, "%s: failed to create wcd934x version entry\n",
8372 __func__);
8373 return -ENOMEM;
8374 }
8375
8376 version_entry->private_data = tavil;
8377 version_entry->size = TAVIL_VERSION_ENTRY_SIZE;
8378 version_entry->content = SNDRV_INFO_CONTENT_DATA;
8379 version_entry->c.ops = &tavil_codec_info_ops;
8380
8381 if (snd_info_register(version_entry) < 0) {
8382 snd_info_free_entry(version_entry);
8383 return -ENOMEM;
8384 }
8385 tavil->version_entry = version_entry;
8386
8387 return 0;
8388}
8389EXPORT_SYMBOL(tavil_codec_info_create_codec_entry);
8390
8391/**
8392 * tavil_cdc_mclk_enable - Enable/disable codec mclk
8393 *
8394 * @codec: codec instance
8395 * @enable: Indicates clk enable or disable
8396 *
8397 * Returns 0 on Success and error on failure
8398 */
8399int tavil_cdc_mclk_enable(struct snd_soc_codec *codec, bool enable)
8400{
8401 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
8402
8403 return __tavil_cdc_mclk_enable(tavil, enable);
8404}
8405EXPORT_SYMBOL(tavil_cdc_mclk_enable);
8406
8407static int __tavil_codec_internal_rco_ctrl(struct snd_soc_codec *codec,
8408 bool enable)
8409{
8410 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
8411 int ret = 0;
8412
8413 if (enable) {
8414 if (wcd_resmgr_get_clk_type(tavil->resmgr) ==
8415 WCD_CLK_RCO) {
8416 ret = wcd_resmgr_enable_clk_block(tavil->resmgr,
8417 WCD_CLK_RCO);
8418 } else {
8419 ret = tavil_cdc_req_mclk_enable(tavil, true);
8420 if (ret) {
8421 dev_err(codec->dev,
8422 "%s: mclk_enable failed, err = %d\n",
8423 __func__, ret);
8424 goto done;
8425 }
8426 ret = wcd_resmgr_enable_clk_block(tavil->resmgr,
8427 WCD_CLK_RCO);
8428 ret |= tavil_cdc_req_mclk_enable(tavil, false);
8429 }
8430
8431 } else {
8432 ret = wcd_resmgr_disable_clk_block(tavil->resmgr,
8433 WCD_CLK_RCO);
8434 }
8435
8436 if (ret) {
8437 dev_err(codec->dev, "%s: Error in %s RCO\n",
8438 __func__, (enable ? "enabling" : "disabling"));
8439 ret = -EINVAL;
8440 }
8441
8442done:
8443 return ret;
8444}
8445
8446/*
8447 * tavil_codec_internal_rco_ctrl: Enable/Disable codec's RCO clock
8448 * @codec: Handle to the codec
8449 * @enable: Indicates whether clock should be enabled or disabled
8450 */
8451static int tavil_codec_internal_rco_ctrl(struct snd_soc_codec *codec,
8452 bool enable)
8453{
8454 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
8455 int ret = 0;
8456
8457 WCD9XXX_V2_BG_CLK_LOCK(tavil->resmgr);
8458 ret = __tavil_codec_internal_rco_ctrl(codec, enable);
8459 WCD9XXX_V2_BG_CLK_UNLOCK(tavil->resmgr);
8460 return ret;
8461}
8462
8463static const struct wcd_resmgr_cb tavil_resmgr_cb = {
8464 .cdc_rco_ctrl = __tavil_codec_internal_rco_ctrl,
8465};
8466
8467static const struct tavil_reg_mask_val tavil_codec_mclk2_1_1_defaults[] = {
8468 {WCD934X_CLK_SYS_MCLK2_PRG1, 0x60, 0x20},
8469};
8470
8471static const struct tavil_reg_mask_val tavil_codec_mclk2_1_0_defaults[] = {
8472 /*
8473 * PLL Settings:
8474 * Clock Root: MCLK2,
8475 * Clock Source: EXT_CLK,
8476 * Clock Destination: MCLK2
8477 * Clock Freq In: 19.2MHz,
8478 * Clock Freq Out: 11.2896MHz
8479 */
8480 {WCD934X_CLK_SYS_MCLK2_PRG1, 0x60, 0x20},
8481 {WCD934X_CLK_SYS_INT_POST_DIV_REG0, 0xFF, 0x5E},
8482 {WCD934X_CLK_SYS_INT_POST_DIV_REG1, 0x1F, 0x1F},
8483 {WCD934X_CLK_SYS_INT_REF_DIV_REG0, 0xFF, 0x54},
8484 {WCD934X_CLK_SYS_INT_REF_DIV_REG1, 0xFF, 0x01},
8485 {WCD934X_CLK_SYS_INT_FILTER_REG1, 0x07, 0x04},
8486 {WCD934X_CLK_SYS_INT_PLL_L_VAL, 0xFF, 0x93},
8487 {WCD934X_CLK_SYS_INT_PLL_N_VAL, 0xFF, 0xFA},
8488 {WCD934X_CLK_SYS_INT_TEST_REG0, 0xFF, 0x90},
8489 {WCD934X_CLK_SYS_INT_PFD_CP_DSM_PROG, 0xFF, 0x7E},
8490 {WCD934X_CLK_SYS_INT_VCO_PROG, 0xFF, 0xF8},
8491 {WCD934X_CLK_SYS_INT_TEST_REG1, 0xFF, 0x68},
8492 {WCD934X_CLK_SYS_INT_LDO_LOCK_CFG, 0xFF, 0x40},
8493 {WCD934X_CLK_SYS_INT_DIG_LOCK_DET_CFG, 0xFF, 0x32},
8494};
8495
8496static const struct tavil_reg_mask_val tavil_codec_reg_defaults[] = {
8497 {WCD934X_BIAS_VBG_FINE_ADJ, 0xFF, 0x75},
8498 {WCD934X_CODEC_CPR_SVS_CX_VDD, 0xFF, 0x7C}, /* value in svs mode */
8499 {WCD934X_CODEC_CPR_SVS2_CX_VDD, 0xFF, 0x58}, /* value in svs2 mode */
8500 {WCD934X_CDC_RX0_RX_PATH_DSMDEM_CTL, 0x01, 0x01},
8501 {WCD934X_CDC_RX1_RX_PATH_DSMDEM_CTL, 0x01, 0x01},
8502 {WCD934X_CDC_RX2_RX_PATH_DSMDEM_CTL, 0x01, 0x01},
8503 {WCD934X_CDC_RX3_RX_PATH_DSMDEM_CTL, 0x01, 0x01},
8504 {WCD934X_CDC_RX4_RX_PATH_DSMDEM_CTL, 0x01, 0x01},
8505 {WCD934X_CDC_RX7_RX_PATH_DSMDEM_CTL, 0x01, 0x01},
8506 {WCD934X_CDC_RX8_RX_PATH_DSMDEM_CTL, 0x01, 0x01},
8507 {WCD934X_CDC_COMPANDER8_CTL7, 0x1E, 0x18},
8508 {WCD934X_CDC_COMPANDER7_CTL7, 0x1E, 0x18},
8509 {WCD934X_CDC_RX0_RX_PATH_SEC0, 0x08, 0x0},
8510 {WCD934X_CDC_CLSH_DECAY_CTRL, 0x03, 0x0},
8511 {WCD934X_MICB1_TEST_CTL_2, 0x07, 0x01},
8512 {WCD934X_CDC_BOOST0_BOOST_CFG1, 0x3F, 0x12},
8513 {WCD934X_CDC_BOOST0_BOOST_CFG2, 0x1C, 0x08},
8514 {WCD934X_CDC_BOOST1_BOOST_CFG1, 0x3F, 0x12},
8515 {WCD934X_CDC_BOOST1_BOOST_CFG2, 0x1C, 0x08},
8516 {WCD934X_CPE_SS_CPARMAD_BUFRDY_INT_PERIOD, 0x1F, 0x09},
8517 {WCD934X_CDC_TX0_TX_PATH_CFG1, 0x01, 0x00},
8518 {WCD934X_CDC_TX1_TX_PATH_CFG1, 0x01, 0x00},
8519 {WCD934X_CDC_TX2_TX_PATH_CFG1, 0x01, 0x00},
8520 {WCD934X_CDC_TX3_TX_PATH_CFG1, 0x01, 0x00},
8521 {WCD934X_CDC_TX4_TX_PATH_CFG1, 0x01, 0x00},
8522 {WCD934X_CDC_TX5_TX_PATH_CFG1, 0x01, 0x00},
8523 {WCD934X_CDC_TX6_TX_PATH_CFG1, 0x01, 0x00},
8524 {WCD934X_CDC_TX7_TX_PATH_CFG1, 0x01, 0x00},
8525 {WCD934X_CDC_TX8_TX_PATH_CFG1, 0x01, 0x00},
8526 {WCD934X_RX_OCP_CTL, 0x0F, 0x02}, /* OCP number of attempts is 2 */
8527 {WCD934X_HPH_OCP_CTL, 0xFF, 0x3A}, /* OCP current limit */
8528 {WCD934X_HPH_L_TEST, 0x01, 0x01},
8529 {WCD934X_HPH_R_TEST, 0x01, 0x01},
8530 {WCD934X_CPE_FLL_CONFIG_CTL_2, 0xFF, 0x20},
8531};
8532
8533static const struct tavil_reg_mask_val tavil_codec_reg_init_1_1_val[] = {
8534 {WCD934X_CDC_COMPANDER1_CTL7, 0x1E, 0x06},
8535 {WCD934X_CDC_COMPANDER2_CTL7, 0x1E, 0x06},
8536 {WCD934X_HPH_NEW_INT_RDAC_HD2_CTL_L, 0xFF, 0x84},
8537 {WCD934X_HPH_NEW_INT_RDAC_HD2_CTL_R, 0xFF, 0x84},
8538 {WCD934X_CDC_RX3_RX_PATH_SEC0, 0xFC, 0xF4},
8539 {WCD934X_CDC_RX4_RX_PATH_SEC0, 0xFC, 0xF4},
8540};
8541
8542static const struct tavil_cpr_reg_defaults cpr_defaults[] = {
8543 { 0x00000820, 0x00000094 },
8544 { 0x00000fC0, 0x00000048 },
8545 { 0x0000f000, 0x00000044 },
8546 { 0x0000bb80, 0xC0000178 },
8547 { 0x00000000, 0x00000160 },
8548 { 0x10854522, 0x00000060 },
8549 { 0x10854509, 0x00000064 },
8550 { 0x108544dd, 0x00000068 },
8551 { 0x108544ad, 0x0000006C },
8552 { 0x0000077E, 0x00000070 },
8553 { 0x000007da, 0x00000074 },
8554 { 0x00000000, 0x00000078 },
8555 { 0x00000000, 0x0000007C },
8556 { 0x00042029, 0x00000080 },
8557 { 0x4002002A, 0x00000090 },
8558 { 0x4002002B, 0x00000090 },
8559};
8560
8561static const struct tavil_reg_mask_val tavil_codec_reg_init_common_val[] = {
8562 {WCD934X_CDC_CLSH_K2_MSB, 0x0F, 0x00},
8563 {WCD934X_CDC_CLSH_K2_LSB, 0xFF, 0x60},
8564 {WCD934X_CPE_SS_DMIC_CFG, 0x80, 0x00},
8565 {WCD934X_CDC_BOOST0_BOOST_CTL, 0x70, 0x50},
8566 {WCD934X_CDC_BOOST1_BOOST_CTL, 0x70, 0x50},
8567 {WCD934X_CDC_RX7_RX_PATH_CFG1, 0x08, 0x08},
8568 {WCD934X_CDC_RX8_RX_PATH_CFG1, 0x08, 0x08},
8569 {WCD934X_CDC_TOP_TOP_CFG1, 0x02, 0x02},
8570 {WCD934X_CDC_TOP_TOP_CFG1, 0x01, 0x01},
8571 {WCD934X_CDC_TX9_SPKR_PROT_PATH_CFG0, 0x01, 0x01},
8572 {WCD934X_CDC_TX10_SPKR_PROT_PATH_CFG0, 0x01, 0x01},
8573 {WCD934X_CDC_TX11_SPKR_PROT_PATH_CFG0, 0x01, 0x01},
8574 {WCD934X_CDC_TX12_SPKR_PROT_PATH_CFG0, 0x01, 0x01},
8575 {WCD934X_DATA_HUB_SB_TX11_INP_CFG, 0x01, 0x01},
8576 {WCD934X_CDC_CLK_RST_CTRL_FS_CNT_CONTROL, 0x01, 0x01},
8577 {WCD934X_CDC_COMPANDER7_CTL3, 0x80, 0x80},
8578 {WCD934X_CDC_COMPANDER8_CTL3, 0x80, 0x80},
8579 {WCD934X_CDC_COMPANDER7_CTL7, 0x01, 0x01},
8580 {WCD934X_CDC_COMPANDER8_CTL7, 0x01, 0x01},
8581 {WCD934X_CODEC_RPM_CLK_GATE, 0x08, 0x00},
8582 {WCD934X_TLMM_DMIC3_CLK_PINCFG, 0xFF, 0x0a},
8583 {WCD934X_TLMM_DMIC3_DATA_PINCFG, 0xFF, 0x0a},
8584 {WCD934X_CPE_SS_SVA_CFG, 0x60, 0x00},
8585};
8586
8587static void tavil_codec_init_reg(struct tavil_priv *priv)
8588{
8589 struct snd_soc_codec *codec = priv->codec;
8590 u32 i;
8591
8592 for (i = 0; i < ARRAY_SIZE(tavil_codec_reg_init_common_val); i++)
8593 snd_soc_update_bits(codec,
8594 tavil_codec_reg_init_common_val[i].reg,
8595 tavil_codec_reg_init_common_val[i].mask,
8596 tavil_codec_reg_init_common_val[i].val);
8597
8598 if (TAVIL_IS_1_1(priv->wcd9xxx)) {
8599 for (i = 0; i < ARRAY_SIZE(tavil_codec_reg_init_1_1_val); i++)
8600 snd_soc_update_bits(codec,
8601 tavil_codec_reg_init_1_1_val[i].reg,
8602 tavil_codec_reg_init_1_1_val[i].mask,
8603 tavil_codec_reg_init_1_1_val[i].val);
8604 }
8605}
8606
8607static void tavil_update_reg_defaults(struct tavil_priv *tavil)
8608{
8609 u32 i;
8610 struct wcd9xxx *wcd9xxx;
8611
8612 wcd9xxx = tavil->wcd9xxx;
8613 for (i = 0; i < ARRAY_SIZE(tavil_codec_reg_defaults); i++)
8614 regmap_update_bits(wcd9xxx->regmap,
8615 tavil_codec_reg_defaults[i].reg,
8616 tavil_codec_reg_defaults[i].mask,
8617 tavil_codec_reg_defaults[i].val);
8618}
8619
8620static void tavil_update_cpr_defaults(struct tavil_priv *tavil)
8621{
8622 int i;
8623 struct wcd9xxx *wcd9xxx;
8624
8625 wcd9xxx = tavil->wcd9xxx;
8626 if (!TAVIL_IS_1_1(wcd9xxx))
8627 return;
8628
8629 __tavil_cdc_mclk_enable(tavil, true);
8630
8631 regmap_write(wcd9xxx->regmap, WCD934X_CODEC_CPR_SVS2_MIN_CX_VDD, 0x2C);
8632 regmap_update_bits(wcd9xxx->regmap, WCD934X_CODEC_RPM_CLK_GATE,
8633 0x10, 0x00);
8634
8635 for (i = 0; i < ARRAY_SIZE(cpr_defaults); i++) {
8636 regmap_bulk_write(wcd9xxx->regmap,
8637 WCD934X_CODEC_CPR_WR_DATA_0,
8638 (u8 *)&cpr_defaults[i].wr_data, 4);
8639 regmap_bulk_write(wcd9xxx->regmap,
8640 WCD934X_CODEC_CPR_WR_ADDR_0,
8641 (u8 *)&cpr_defaults[i].wr_addr, 4);
8642 }
8643
8644 __tavil_cdc_mclk_enable(tavil, false);
8645}
8646
8647static void tavil_slim_interface_init_reg(struct snd_soc_codec *codec)
8648{
8649 int i;
8650 struct tavil_priv *priv = snd_soc_codec_get_drvdata(codec);
8651
8652 for (i = 0; i < WCD9XXX_SLIM_NUM_PORT_REG; i++)
8653 wcd9xxx_interface_reg_write(priv->wcd9xxx,
8654 WCD934X_SLIM_PGD_PORT_INT_RX_EN0 + i,
8655 0xFF);
8656}
8657
8658static irqreturn_t tavil_misc_irq(int irq, void *data)
8659{
8660 struct tavil_priv *tavil = data;
8661 int misc_val;
8662
8663 /* Find source of interrupt */
8664 regmap_read(tavil->wcd9xxx->regmap, WCD934X_INTR_CODEC_MISC_STATUS,
8665 &misc_val);
8666
8667 if (misc_val & 0x08) {
8668 dev_info(tavil->dev, "%s: irq: %d, DSD DC detected!\n",
8669 __func__, irq);
8670 /* DSD DC interrupt, reset DSD path */
8671 tavil_dsd_reset(tavil->dsd_config);
8672 } else {
8673 dev_err(tavil->dev, "%s: Codec misc irq: %d, val: 0x%x\n",
8674 __func__, irq, misc_val);
8675 }
8676
8677 /* Clear interrupt status */
8678 regmap_update_bits(tavil->wcd9xxx->regmap,
8679 WCD934X_INTR_CODEC_MISC_CLEAR, misc_val, 0x00);
8680
8681 return IRQ_HANDLED;
8682}
8683
8684static irqreturn_t tavil_slimbus_irq(int irq, void *data)
8685{
8686 struct tavil_priv *tavil = data;
8687 unsigned long status = 0;
8688 int i, j, port_id, k;
8689 u32 bit;
8690 u8 val, int_val = 0;
8691 bool tx, cleared;
8692 unsigned short reg = 0;
8693
8694 for (i = WCD934X_SLIM_PGD_PORT_INT_STATUS_RX_0, j = 0;
8695 i <= WCD934X_SLIM_PGD_PORT_INT_STATUS_TX_1; i++, j++) {
8696 val = wcd9xxx_interface_reg_read(tavil->wcd9xxx, i);
8697 status |= ((u32)val << (8 * j));
8698 }
8699
8700 for_each_set_bit(j, &status, 32) {
8701 tx = (j >= 16 ? true : false);
8702 port_id = (tx ? j - 16 : j);
8703 val = wcd9xxx_interface_reg_read(tavil->wcd9xxx,
8704 WCD934X_SLIM_PGD_PORT_INT_RX_SOURCE0 + j);
8705 if (val) {
8706 if (!tx)
8707 reg = WCD934X_SLIM_PGD_PORT_INT_RX_EN0 +
8708 (port_id / 8);
8709 else
8710 reg = WCD934X_SLIM_PGD_PORT_INT_TX_EN0 +
8711 (port_id / 8);
8712 int_val = wcd9xxx_interface_reg_read(
8713 tavil->wcd9xxx, reg);
8714 /*
8715 * Ignore interrupts for ports for which the
8716 * interrupts are not specifically enabled.
8717 */
8718 if (!(int_val & (1 << (port_id % 8))))
8719 continue;
8720 }
8721 if (val & WCD934X_SLIM_IRQ_OVERFLOW)
8722 dev_err_ratelimited(tavil->dev, "%s: overflow error on %s port %d, value %x\n",
8723 __func__, (tx ? "TX" : "RX"), port_id, val);
8724 if (val & WCD934X_SLIM_IRQ_UNDERFLOW)
8725 dev_err_ratelimited(tavil->dev, "%s: underflow error on %s port %d, value %x\n",
8726 __func__, (tx ? "TX" : "RX"), port_id, val);
8727 if ((val & WCD934X_SLIM_IRQ_OVERFLOW) ||
8728 (val & WCD934X_SLIM_IRQ_UNDERFLOW)) {
8729 if (!tx)
8730 reg = WCD934X_SLIM_PGD_PORT_INT_RX_EN0 +
8731 (port_id / 8);
8732 else
8733 reg = WCD934X_SLIM_PGD_PORT_INT_TX_EN0 +
8734 (port_id / 8);
8735 int_val = wcd9xxx_interface_reg_read(
8736 tavil->wcd9xxx, reg);
8737 if (int_val & (1 << (port_id % 8))) {
8738 int_val = int_val ^ (1 << (port_id % 8));
8739 wcd9xxx_interface_reg_write(tavil->wcd9xxx,
8740 reg, int_val);
8741 }
8742 }
8743 if (val & WCD934X_SLIM_IRQ_PORT_CLOSED) {
8744 /*
8745 * INT SOURCE register starts from RX to TX
8746 * but port number in the ch_mask is in opposite way
8747 */
8748 bit = (tx ? j - 16 : j + 16);
8749 dev_dbg(tavil->dev, "%s: %s port %d closed value %x, bit %u\n",
8750 __func__, (tx ? "TX" : "RX"), port_id, val,
8751 bit);
8752 for (k = 0, cleared = false; k < NUM_CODEC_DAIS; k++) {
8753 dev_dbg(tavil->dev, "%s: tavil->dai[%d].ch_mask = 0x%lx\n",
8754 __func__, k, tavil->dai[k].ch_mask);
8755 if (test_and_clear_bit(bit,
8756 &tavil->dai[k].ch_mask)) {
8757 cleared = true;
8758 if (!tavil->dai[k].ch_mask)
8759 wake_up(
8760 &tavil->dai[k].dai_wait);
8761 /*
8762 * There are cases when multiple DAIs
8763 * might be using the same slimbus
8764 * channel. Hence don't break here.
8765 */
8766 }
8767 }
8768 WARN(!cleared,
8769 "Couldn't find slimbus %s port %d for closing\n",
8770 (tx ? "TX" : "RX"), port_id);
8771 }
8772 wcd9xxx_interface_reg_write(tavil->wcd9xxx,
8773 WCD934X_SLIM_PGD_PORT_INT_CLR_RX_0 +
8774 (j / 8),
8775 1 << (j % 8));
8776 }
8777
8778 return IRQ_HANDLED;
8779}
8780
8781static int tavil_setup_irqs(struct tavil_priv *tavil)
8782{
8783 int ret = 0;
8784 struct snd_soc_codec *codec = tavil->codec;
8785 struct wcd9xxx *wcd9xxx = tavil->wcd9xxx;
8786 struct wcd9xxx_core_resource *core_res =
8787 &wcd9xxx->core_res;
8788
8789 ret = wcd9xxx_request_irq(core_res, WCD9XXX_IRQ_SLIMBUS,
8790 tavil_slimbus_irq, "SLIMBUS Slave", tavil);
8791 if (ret)
8792 dev_err(codec->dev, "%s: Failed to request irq %d\n", __func__,
8793 WCD9XXX_IRQ_SLIMBUS);
8794 else
8795 tavil_slim_interface_init_reg(codec);
8796
8797 /* Register for misc interrupts as well */
8798 ret = wcd9xxx_request_irq(core_res, WCD934X_IRQ_MISC,
8799 tavil_misc_irq, "CDC MISC Irq", tavil);
8800 if (ret)
8801 dev_err(codec->dev, "%s: Failed to request cdc misc irq\n",
8802 __func__);
8803
8804 return ret;
8805}
8806
8807static void tavil_init_slim_slave_cfg(struct snd_soc_codec *codec)
8808{
8809 struct tavil_priv *priv = snd_soc_codec_get_drvdata(codec);
8810 struct afe_param_cdc_slimbus_slave_cfg *cfg;
8811 struct wcd9xxx *wcd9xxx = priv->wcd9xxx;
8812 uint64_t eaddr = 0;
8813
8814 cfg = &priv->slimbus_slave_cfg;
8815 cfg->minor_version = 1;
8816 cfg->tx_slave_port_offset = 0;
8817 cfg->rx_slave_port_offset = 16;
8818
8819 memcpy(&eaddr, &wcd9xxx->slim->e_addr, sizeof(wcd9xxx->slim->e_addr));
8820 WARN_ON(sizeof(wcd9xxx->slim->e_addr) != 6);
8821 cfg->device_enum_addr_lsw = eaddr & 0xFFFFFFFF;
8822 cfg->device_enum_addr_msw = eaddr >> 32;
8823
8824 dev_dbg(codec->dev, "%s: slimbus logical address 0x%llx\n",
8825 __func__, eaddr);
8826}
8827
8828static void tavil_cleanup_irqs(struct tavil_priv *tavil)
8829{
8830 struct wcd9xxx *wcd9xxx = tavil->wcd9xxx;
8831 struct wcd9xxx_core_resource *core_res =
8832 &wcd9xxx->core_res;
8833
8834 wcd9xxx_free_irq(core_res, WCD9XXX_IRQ_SLIMBUS, tavil);
8835 wcd9xxx_free_irq(core_res, WCD934X_IRQ_MISC, tavil);
8836}
8837
8838/*
8839 * wcd934x_get_micb_vout_ctl_val: converts micbias from volts to register value
8840 * @micb_mv: micbias in mv
8841 *
8842 * return register value converted
8843 */
8844int wcd934x_get_micb_vout_ctl_val(u32 micb_mv)
8845{
8846 /* min micbias voltage is 1V and maximum is 2.85V */
8847 if (micb_mv < 1000 || micb_mv > 2850) {
8848 pr_err("%s: unsupported micbias voltage\n", __func__);
8849 return -EINVAL;
8850 }
8851
8852 return (micb_mv - 1000) / 50;
8853}
8854EXPORT_SYMBOL(wcd934x_get_micb_vout_ctl_val);
8855
8856static int tavil_handle_pdata(struct tavil_priv *tavil,
8857 struct wcd9xxx_pdata *pdata)
8858{
8859 struct snd_soc_codec *codec = tavil->codec;
8860 u8 mad_dmic_ctl_val;
8861 u8 anc_ctl_value;
8862 u32 def_dmic_rate, dmic_clk_drv;
8863 int vout_ctl_1, vout_ctl_2, vout_ctl_3, vout_ctl_4;
8864 int rc = 0;
8865
8866 if (!pdata) {
8867 dev_err(codec->dev, "%s: NULL pdata\n", __func__);
8868 return -ENODEV;
8869 }
8870
8871 /* set micbias voltage */
8872 vout_ctl_1 = wcd934x_get_micb_vout_ctl_val(pdata->micbias.micb1_mv);
8873 vout_ctl_2 = wcd934x_get_micb_vout_ctl_val(pdata->micbias.micb2_mv);
8874 vout_ctl_3 = wcd934x_get_micb_vout_ctl_val(pdata->micbias.micb3_mv);
8875 vout_ctl_4 = wcd934x_get_micb_vout_ctl_val(pdata->micbias.micb4_mv);
Xiaoyu Ye1a2d8bd92017-01-31 18:54:15 -08008876 if (vout_ctl_1 < 0 || vout_ctl_2 < 0 ||
8877 vout_ctl_3 < 0 || vout_ctl_4 < 0) {
Banajit Goswamide8271c2017-01-18 00:28:59 -08008878 rc = -EINVAL;
8879 goto done;
8880 }
8881 snd_soc_update_bits(codec, WCD934X_ANA_MICB1, 0x3F, vout_ctl_1);
8882 snd_soc_update_bits(codec, WCD934X_ANA_MICB2, 0x3F, vout_ctl_2);
8883 snd_soc_update_bits(codec, WCD934X_ANA_MICB3, 0x3F, vout_ctl_3);
8884 snd_soc_update_bits(codec, WCD934X_ANA_MICB4, 0x3F, vout_ctl_4);
8885
8886 /* Set the DMIC sample rate */
8887 switch (pdata->mclk_rate) {
8888 case WCD934X_MCLK_CLK_9P6MHZ:
8889 def_dmic_rate = WCD9XXX_DMIC_SAMPLE_RATE_4P8MHZ;
8890 break;
8891 case WCD934X_MCLK_CLK_12P288MHZ:
8892 def_dmic_rate = WCD9XXX_DMIC_SAMPLE_RATE_4P096MHZ;
8893 break;
8894 default:
8895 /* should never happen */
8896 dev_err(codec->dev, "%s: Invalid mclk_rate %d\n",
8897 __func__, pdata->mclk_rate);
8898 rc = -EINVAL;
8899 goto done;
8900 };
8901
8902 if (pdata->dmic_sample_rate ==
8903 WCD9XXX_DMIC_SAMPLE_RATE_UNDEFINED) {
8904 dev_info(codec->dev, "%s: dmic_rate invalid default = %d\n",
8905 __func__, def_dmic_rate);
8906 pdata->dmic_sample_rate = def_dmic_rate;
8907 }
8908 if (pdata->mad_dmic_sample_rate ==
8909 WCD9XXX_DMIC_SAMPLE_RATE_UNDEFINED) {
8910 dev_info(codec->dev, "%s: mad_dmic_rate invalid default = %d\n",
8911 __func__, def_dmic_rate);
8912 /*
8913 * use dmic_sample_rate as the default for MAD
8914 * if mad dmic sample rate is undefined
8915 */
8916 pdata->mad_dmic_sample_rate = pdata->dmic_sample_rate;
8917 }
8918
8919 if (pdata->dmic_clk_drv ==
8920 WCD9XXX_DMIC_CLK_DRIVE_UNDEFINED) {
8921 pdata->dmic_clk_drv = WCD934X_DMIC_CLK_DRIVE_DEFAULT;
Karthikeyan Mani3570e6c2016-11-14 11:05:53 -08008922 dev_dbg(codec->dev,
Banajit Goswamide8271c2017-01-18 00:28:59 -08008923 "%s: dmic_clk_strength invalid, default = %d\n",
8924 __func__, pdata->dmic_clk_drv);
8925 }
8926
8927 switch (pdata->dmic_clk_drv) {
8928 case 2:
8929 dmic_clk_drv = 0;
8930 break;
8931 case 4:
8932 dmic_clk_drv = 1;
8933 break;
8934 case 8:
8935 dmic_clk_drv = 2;
8936 break;
8937 case 16:
8938 dmic_clk_drv = 3;
8939 break;
8940 default:
8941 dev_err(codec->dev,
8942 "%s: invalid dmic_clk_drv %d, using default\n",
8943 __func__, pdata->dmic_clk_drv);
8944 dmic_clk_drv = 0;
8945 break;
8946 }
8947
8948 snd_soc_update_bits(codec, WCD934X_TEST_DEBUG_PAD_DRVCTL_0,
8949 0x0C, dmic_clk_drv << 2);
8950
8951 /*
8952 * Default the DMIC clk rates to mad_dmic_sample_rate,
8953 * whereas, the anc/txfe dmic rates to dmic_sample_rate
8954 * since the anc/txfe are independent of mad block.
8955 */
8956 mad_dmic_ctl_val = tavil_get_dmic_clk_val(tavil->codec,
8957 pdata->mclk_rate,
8958 pdata->mad_dmic_sample_rate);
8959 snd_soc_update_bits(codec, WCD934X_CPE_SS_DMIC0_CTL,
8960 0x0E, mad_dmic_ctl_val << 1);
8961 snd_soc_update_bits(codec, WCD934X_CPE_SS_DMIC1_CTL,
8962 0x0E, mad_dmic_ctl_val << 1);
8963 snd_soc_update_bits(codec, WCD934X_CPE_SS_DMIC2_CTL,
8964 0x0E, mad_dmic_ctl_val << 1);
8965
8966 if (dmic_clk_drv == WCD934X_DMIC_CLK_DIV_2)
8967 anc_ctl_value = WCD934X_ANC_DMIC_X2_FULL_RATE;
8968 else
8969 anc_ctl_value = WCD934X_ANC_DMIC_X2_HALF_RATE;
8970
8971 snd_soc_update_bits(codec, WCD934X_CDC_ANC0_MODE_2_CTL,
8972 0x40, anc_ctl_value << 6);
8973 snd_soc_update_bits(codec, WCD934X_CDC_ANC0_MODE_2_CTL,
8974 0x20, anc_ctl_value << 5);
8975 snd_soc_update_bits(codec, WCD934X_CDC_ANC1_MODE_2_CTL,
8976 0x40, anc_ctl_value << 6);
8977 snd_soc_update_bits(codec, WCD934X_CDC_ANC1_MODE_2_CTL,
8978 0x20, anc_ctl_value << 5);
8979
8980done:
8981 return rc;
8982}
8983
8984static void tavil_cdc_vote_svs(struct snd_soc_codec *codec, bool vote)
8985{
8986 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
8987
8988 return tavil_vote_svs(tavil, vote);
8989}
8990
8991struct wcd_dsp_cdc_cb cdc_cb = {
8992 .cdc_clk_en = tavil_codec_internal_rco_ctrl,
8993 .cdc_vote_svs = tavil_cdc_vote_svs,
8994};
8995
8996static int tavil_wdsp_initialize(struct snd_soc_codec *codec)
8997{
8998 struct wcd9xxx *control;
8999 struct tavil_priv *tavil;
9000 struct wcd_dsp_params params;
9001 int ret = 0;
9002
9003 control = dev_get_drvdata(codec->dev->parent);
9004 tavil = snd_soc_codec_get_drvdata(codec);
9005
9006 params.cb = &cdc_cb;
9007 params.irqs.cpe_ipc1_irq = WCD934X_IRQ_CPE1_INTR;
9008 params.irqs.cpe_err_irq = WCD934X_IRQ_CPE_ERROR;
9009 params.irqs.fatal_irqs = CPE_FATAL_IRQS;
9010 params.clk_rate = control->mclk_rate;
9011 params.dsp_instance = 0;
9012
9013 wcd_dsp_cntl_init(codec, &params, &tavil->wdsp_cntl);
9014 if (!tavil->wdsp_cntl) {
9015 dev_err(tavil->dev, "%s: wcd-dsp-control init failed\n",
9016 __func__);
9017 ret = -EINVAL;
9018 }
9019
9020 return ret;
9021}
9022
9023/*
9024 * tavil_soc_get_mbhc: get wcd934x_mbhc handle of corresponding codec
9025 * @codec: handle to snd_soc_codec *
9026 *
9027 * return wcd934x_mbhc handle or error code in case of failure
9028 */
9029struct wcd934x_mbhc *tavil_soc_get_mbhc(struct snd_soc_codec *codec)
9030{
9031 struct tavil_priv *tavil;
9032
9033 if (!codec) {
9034 pr_err("%s: Invalid params, NULL codec\n", __func__);
9035 return NULL;
9036 }
9037 tavil = snd_soc_codec_get_drvdata(codec);
9038
9039 if (!tavil) {
9040 pr_err("%s: Invalid params, NULL tavil\n", __func__);
9041 return NULL;
9042 }
9043
9044 return tavil->mbhc;
9045}
9046EXPORT_SYMBOL(tavil_soc_get_mbhc);
9047
9048static void tavil_mclk2_reg_defaults(struct tavil_priv *tavil)
9049{
9050 int i;
9051 struct snd_soc_codec *codec = tavil->codec;
9052
9053 if (TAVIL_IS_1_0(tavil->wcd9xxx)) {
9054 /* MCLK2 configuration */
9055 for (i = 0; i < ARRAY_SIZE(tavil_codec_mclk2_1_0_defaults); i++)
9056 snd_soc_update_bits(codec,
9057 tavil_codec_mclk2_1_0_defaults[i].reg,
9058 tavil_codec_mclk2_1_0_defaults[i].mask,
9059 tavil_codec_mclk2_1_0_defaults[i].val);
9060 }
9061 if (TAVIL_IS_1_1(tavil->wcd9xxx)) {
9062 /* MCLK2 configuration */
9063 for (i = 0; i < ARRAY_SIZE(tavil_codec_mclk2_1_1_defaults); i++)
9064 snd_soc_update_bits(codec,
9065 tavil_codec_mclk2_1_1_defaults[i].reg,
9066 tavil_codec_mclk2_1_1_defaults[i].mask,
9067 tavil_codec_mclk2_1_1_defaults[i].val);
9068 }
9069}
9070
9071static int tavil_device_down(struct wcd9xxx *wcd9xxx)
9072{
9073 struct snd_soc_codec *codec;
9074 struct tavil_priv *priv;
9075 int count;
9076
9077 codec = (struct snd_soc_codec *)(wcd9xxx->ssr_priv);
9078 priv = snd_soc_codec_get_drvdata(codec);
9079 swrm_wcd_notify(priv->swr.ctrl_data[0].swr_pdev,
9080 SWR_DEVICE_DOWN, NULL);
9081 tavil_dsd_reset(priv->dsd_config);
9082 snd_soc_card_change_online_state(codec->component.card, 0);
9083 for (count = 0; count < NUM_CODEC_DAIS; count++)
9084 priv->dai[count].bus_down_in_recovery = true;
9085 wcd_dsp_ssr_event(priv->wdsp_cntl, WCD_CDC_DOWN_EVENT);
9086 wcd_resmgr_set_sido_input_src_locked(priv->resmgr,
9087 SIDO_SOURCE_INTERNAL);
9088
9089 return 0;
9090}
9091
9092static int tavil_post_reset_cb(struct wcd9xxx *wcd9xxx)
9093{
9094 int i, ret = 0;
9095 struct wcd9xxx *control;
9096 struct snd_soc_codec *codec;
9097 struct tavil_priv *tavil;
9098 struct wcd9xxx_pdata *pdata;
9099 struct wcd_mbhc *mbhc;
9100
9101 codec = (struct snd_soc_codec *)(wcd9xxx->ssr_priv);
9102 tavil = snd_soc_codec_get_drvdata(codec);
9103 control = dev_get_drvdata(codec->dev->parent);
9104
9105 wcd9xxx_set_power_state(tavil->wcd9xxx,
9106 WCD_REGION_POWER_COLLAPSE_REMOVE,
9107 WCD9XXX_DIG_CORE_REGION_1);
9108
9109 mutex_lock(&tavil->codec_mutex);
Banajit Goswamide8271c2017-01-18 00:28:59 -08009110
Vidyakumar Athotaae60b992017-01-04 11:21:48 -08009111 tavil_vote_svs(tavil, true);
Banajit Goswamide8271c2017-01-18 00:28:59 -08009112 tavil_slimbus_slave_port_cfg.slave_dev_intfdev_la =
9113 control->slim_slave->laddr;
9114 tavil_slimbus_slave_port_cfg.slave_dev_pgd_la =
9115 control->slim->laddr;
9116 tavil_init_slim_slave_cfg(codec);
9117 snd_soc_card_change_online_state(codec->component.card, 1);
9118
Banajit Goswamide8271c2017-01-18 00:28:59 -08009119 for (i = 0; i < TAVIL_MAX_MICBIAS; i++)
9120 tavil->micb_ref[i] = 0;
9121
Banajit Goswamide8271c2017-01-18 00:28:59 -08009122 dev_dbg(codec->dev, "%s: MCLK Rate = %x\n",
9123 __func__, control->mclk_rate);
9124
9125 if (control->mclk_rate == WCD934X_MCLK_CLK_12P288MHZ)
9126 snd_soc_update_bits(codec, WCD934X_CODEC_RPM_CLK_MCLK_CFG,
9127 0x03, 0x00);
9128 else if (control->mclk_rate == WCD934X_MCLK_CLK_9P6MHZ)
9129 snd_soc_update_bits(codec, WCD934X_CODEC_RPM_CLK_MCLK_CFG,
9130 0x03, 0x01);
9131 wcd_resmgr_post_ssr_v2(tavil->resmgr);
9132 tavil_update_reg_defaults(tavil);
9133 tavil_codec_init_reg(tavil);
9134 __tavil_enable_efuse_sensing(tavil);
9135 tavil_mclk2_reg_defaults(tavil);
9136
9137 __tavil_cdc_mclk_enable(tavil, true);
9138 regcache_mark_dirty(codec->component.regmap);
9139 regcache_sync(codec->component.regmap);
9140 __tavil_cdc_mclk_enable(tavil, false);
9141
9142 tavil_update_cpr_defaults(tavil);
9143
9144 pdata = dev_get_platdata(codec->dev->parent);
9145 ret = tavil_handle_pdata(tavil, pdata);
Xiaoyu Ye1a2d8bd92017-01-31 18:54:15 -08009146 if (ret < 0)
Banajit Goswamide8271c2017-01-18 00:28:59 -08009147 dev_err(codec->dev, "%s: invalid pdata\n", __func__);
9148
9149 /* Initialize MBHC module */
9150 mbhc = &tavil->mbhc->wcd_mbhc;
9151 ret = tavil_mbhc_post_ssr_init(tavil->mbhc, codec);
9152 if (ret) {
9153 dev_err(codec->dev, "%s: mbhc initialization failed\n",
9154 __func__);
9155 goto done;
9156 } else {
9157 tavil_mbhc_hs_detect(codec, mbhc->mbhc_cfg);
9158 }
9159
9160 /* DSD initialization */
9161 ret = tavil_dsd_post_ssr_init(tavil->dsd_config);
9162 if (ret)
9163 dev_dbg(tavil->dev, "%s: DSD init failed\n", __func__);
9164
9165 tavil_cleanup_irqs(tavil);
9166 ret = tavil_setup_irqs(tavil);
9167 if (ret) {
9168 dev_err(codec->dev, "%s: tavil irq setup failed %d\n",
9169 __func__, ret);
9170 goto done;
9171 }
9172
9173 tavil_set_spkr_mode(codec, tavil->swr.spkr_mode);
9174 /*
9175 * Once the codec initialization is completed, the svs vote
9176 * can be released allowing the codec to go to SVS2.
9177 */
9178 tavil_vote_svs(tavil, false);
9179 wcd_dsp_ssr_event(tavil->wdsp_cntl, WCD_CDC_UP_EVENT);
9180
9181done:
9182 mutex_unlock(&tavil->codec_mutex);
9183 return ret;
9184}
9185
Banajit Goswami2be7b482017-02-03 23:32:37 -08009186static int tavil_soc_codec_probe(struct snd_soc_codec *codec)
Banajit Goswamide8271c2017-01-18 00:28:59 -08009187{
9188 struct wcd9xxx *control;
9189 struct tavil_priv *tavil;
9190 struct wcd9xxx_pdata *pdata;
9191 struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
9192 int i, ret;
9193 void *ptr = NULL;
9194
9195 control = dev_get_drvdata(codec->dev->parent);
9196
9197 dev_info(codec->dev, "%s()\n", __func__);
9198 tavil = snd_soc_codec_get_drvdata(codec);
9199 tavil->intf_type = wcd9xxx_get_intf_type();
9200
9201 control->dev_down = tavil_device_down;
9202 control->post_reset = tavil_post_reset_cb;
9203 control->ssr_priv = (void *)codec;
9204
9205 /* Resource Manager post Init */
9206 ret = wcd_resmgr_post_init(tavil->resmgr, &tavil_resmgr_cb, codec);
9207 if (ret) {
9208 dev_err(codec->dev, "%s: wcd resmgr post init failed\n",
9209 __func__);
9210 goto err;
9211 }
9212 /* Class-H Init */
9213 wcd_clsh_init(&tavil->clsh_d);
9214 /* Default HPH Mode to Class-H Low HiFi */
9215 tavil->hph_mode = CLS_H_LOHIFI;
9216
9217 tavil->fw_data = devm_kzalloc(codec->dev, sizeof(*(tavil->fw_data)),
9218 GFP_KERNEL);
9219 if (!tavil->fw_data)
9220 goto err;
9221
9222 set_bit(WCD9XXX_ANC_CAL, tavil->fw_data->cal_bit);
9223 set_bit(WCD9XXX_MBHC_CAL, tavil->fw_data->cal_bit);
9224 set_bit(WCD9XXX_MAD_CAL, tavil->fw_data->cal_bit);
9225 set_bit(WCD9XXX_VBAT_CAL, tavil->fw_data->cal_bit);
9226
9227 ret = wcd_cal_create_hwdep(tavil->fw_data,
9228 WCD9XXX_CODEC_HWDEP_NODE, codec);
Xiaoyu Ye1a2d8bd92017-01-31 18:54:15 -08009229 if (ret < 0) {
Banajit Goswamide8271c2017-01-18 00:28:59 -08009230 dev_err(codec->dev, "%s hwdep failed %d\n", __func__, ret);
9231 goto err_hwdep;
9232 }
9233
9234 /* Initialize MBHC module */
9235 ret = tavil_mbhc_init(&tavil->mbhc, codec, tavil->fw_data);
9236 if (ret) {
9237 pr_err("%s: mbhc initialization failed\n", __func__);
9238 goto err_hwdep;
9239 }
9240
9241 tavil->codec = codec;
9242 for (i = 0; i < COMPANDER_MAX; i++)
9243 tavil->comp_enabled[i] = 0;
9244
9245 tavil_codec_init_reg(tavil);
9246
9247 pdata = dev_get_platdata(codec->dev->parent);
9248 ret = tavil_handle_pdata(tavil, pdata);
Xiaoyu Ye1a2d8bd92017-01-31 18:54:15 -08009249 if (ret < 0) {
Banajit Goswamide8271c2017-01-18 00:28:59 -08009250 dev_err(codec->dev, "%s: bad pdata\n", __func__);
9251 goto err_hwdep;
9252 }
9253
9254 ptr = devm_kzalloc(codec->dev, (sizeof(tavil_rx_chs) +
9255 sizeof(tavil_tx_chs)), GFP_KERNEL);
9256 if (!ptr) {
9257 ret = -ENOMEM;
9258 goto err_hwdep;
9259 }
9260
9261 snd_soc_dapm_add_routes(dapm, tavil_slim_audio_map,
9262 ARRAY_SIZE(tavil_slim_audio_map));
9263 for (i = 0; i < NUM_CODEC_DAIS; i++) {
9264 INIT_LIST_HEAD(&tavil->dai[i].wcd9xxx_ch_list);
9265 init_waitqueue_head(&tavil->dai[i].dai_wait);
9266 }
9267 tavil_slimbus_slave_port_cfg.slave_dev_intfdev_la =
9268 control->slim_slave->laddr;
9269 tavil_slimbus_slave_port_cfg.slave_dev_pgd_la =
9270 control->slim->laddr;
9271 tavil_slimbus_slave_port_cfg.slave_port_mapping[0] =
9272 WCD934X_TX13;
9273 tavil_init_slim_slave_cfg(codec);
9274
9275 control->num_rx_port = WCD934X_RX_MAX;
9276 control->rx_chs = ptr;
9277 memcpy(control->rx_chs, tavil_rx_chs, sizeof(tavil_rx_chs));
9278 control->num_tx_port = WCD934X_TX_MAX;
9279 control->tx_chs = ptr + sizeof(tavil_rx_chs);
9280 memcpy(control->tx_chs, tavil_tx_chs, sizeof(tavil_tx_chs));
9281
9282 ret = tavil_setup_irqs(tavil);
9283 if (ret) {
9284 dev_err(tavil->dev, "%s: tavil irq setup failed %d\n",
9285 __func__, ret);
9286 goto err_pdata;
9287 }
9288
9289 for (i = 0; i < WCD934X_NUM_DECIMATORS; i++) {
9290 tavil->tx_hpf_work[i].tavil = tavil;
9291 tavil->tx_hpf_work[i].decimator = i;
9292 INIT_DELAYED_WORK(&tavil->tx_hpf_work[i].dwork,
9293 tavil_tx_hpf_corner_freq_callback);
9294
9295 tavil->tx_mute_dwork[i].tavil = tavil;
9296 tavil->tx_mute_dwork[i].decimator = i;
9297 INIT_DELAYED_WORK(&tavil->tx_mute_dwork[i].dwork,
9298 tavil_tx_mute_update_callback);
9299 }
9300
9301 tavil->spk_anc_dwork.tavil = tavil;
9302 INIT_DELAYED_WORK(&tavil->spk_anc_dwork.dwork,
9303 tavil_spk_anc_update_callback);
9304
9305 tavil_mclk2_reg_defaults(tavil);
9306
9307 /* DSD initialization */
9308 tavil->dsd_config = tavil_dsd_init(codec);
9309 if (IS_ERR_OR_NULL(tavil->dsd_config))
9310 dev_dbg(tavil->dev, "%s: DSD init failed\n", __func__);
9311
9312 mutex_lock(&tavil->codec_mutex);
9313 snd_soc_dapm_disable_pin(dapm, "ANC EAR PA");
9314 snd_soc_dapm_disable_pin(dapm, "ANC EAR");
Meng Wangf45a20d2017-01-18 09:51:58 +08009315 snd_soc_dapm_disable_pin(dapm, "ANC HPHL PA");
9316 snd_soc_dapm_disable_pin(dapm, "ANC HPHR PA");
9317 snd_soc_dapm_disable_pin(dapm, "ANC HPHL");
9318 snd_soc_dapm_disable_pin(dapm, "ANC HPHR");
Banajit Goswamide8271c2017-01-18 00:28:59 -08009319 snd_soc_dapm_enable_pin(dapm, "ANC SPK1 PA");
9320 mutex_unlock(&tavil->codec_mutex);
9321
9322 snd_soc_dapm_ignore_suspend(dapm, "AIF1 Playback");
9323 snd_soc_dapm_ignore_suspend(dapm, "AIF1 Capture");
9324 snd_soc_dapm_ignore_suspend(dapm, "AIF2 Playback");
9325 snd_soc_dapm_ignore_suspend(dapm, "AIF2 Capture");
9326 snd_soc_dapm_ignore_suspend(dapm, "AIF3 Playback");
9327 snd_soc_dapm_ignore_suspend(dapm, "AIF3 Capture");
9328 snd_soc_dapm_ignore_suspend(dapm, "AIF4 Playback");
9329 snd_soc_dapm_ignore_suspend(dapm, "VIfeed");
9330
9331 snd_soc_dapm_sync(dapm);
9332
9333 tavil_wdsp_initialize(codec);
9334
9335 /*
9336 * Once the codec initialization is completed, the svs vote
9337 * can be released allowing the codec to go to SVS2.
9338 */
9339 tavil_vote_svs(tavil, false);
9340
9341 return ret;
9342
9343err_pdata:
9344 devm_kfree(codec->dev, ptr);
9345 control->rx_chs = NULL;
9346 control->tx_chs = NULL;
9347err_hwdep:
9348 devm_kfree(codec->dev, tavil->fw_data);
9349 tavil->fw_data = NULL;
9350err:
9351 return ret;
9352}
9353
Banajit Goswami2be7b482017-02-03 23:32:37 -08009354static int tavil_soc_codec_remove(struct snd_soc_codec *codec)
Banajit Goswamide8271c2017-01-18 00:28:59 -08009355{
9356 struct wcd9xxx *control;
9357 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
9358
9359 control = dev_get_drvdata(codec->dev->parent);
9360 devm_kfree(codec->dev, control->rx_chs);
9361 control->rx_chs = NULL;
9362 control->tx_chs = NULL;
9363 tavil_cleanup_irqs(tavil);
9364
9365 if (tavil->wdsp_cntl)
9366 wcd_dsp_cntl_deinit(&tavil->wdsp_cntl);
9367
9368 /* Deinitialize MBHC module */
9369 tavil_mbhc_deinit(codec);
9370 tavil->mbhc = NULL;
Banajit Goswamie0b20e12017-02-05 18:11:11 -08009371
9372 return 0;
Banajit Goswamide8271c2017-01-18 00:28:59 -08009373}
9374
9375static struct regmap *tavil_get_regmap(struct device *dev)
9376{
9377 struct wcd9xxx *control = dev_get_drvdata(dev->parent);
9378
9379 return control->regmap;
9380}
9381
9382static struct snd_soc_codec_driver soc_codec_dev_tavil = {
Banajit Goswami2be7b482017-02-03 23:32:37 -08009383 .probe = tavil_soc_codec_probe,
9384 .remove = tavil_soc_codec_remove,
Banajit Goswamide8271c2017-01-18 00:28:59 -08009385 .get_regmap = tavil_get_regmap,
Banajit Goswami8e306f02016-12-15 20:49:07 -08009386 .component_driver = {
Banajit Goswamiaf472112017-01-29 22:15:11 -08009387 .controls = tavil_snd_controls,
9388 .num_controls = ARRAY_SIZE(tavil_snd_controls),
Banajit Goswami8e306f02016-12-15 20:49:07 -08009389 .dapm_widgets = tavil_dapm_widgets,
9390 .num_dapm_widgets = ARRAY_SIZE(tavil_dapm_widgets),
9391 .dapm_routes = tavil_audio_map,
9392 .num_dapm_routes = ARRAY_SIZE(tavil_audio_map),
9393 },
Banajit Goswamide8271c2017-01-18 00:28:59 -08009394};
9395
9396#ifdef CONFIG_PM
9397static int tavil_suspend(struct device *dev)
9398{
9399 struct platform_device *pdev = to_platform_device(dev);
9400 struct tavil_priv *tavil = platform_get_drvdata(pdev);
9401
9402 if (!tavil) {
9403 dev_err(dev, "%s: tavil private data is NULL\n", __func__);
9404 return -EINVAL;
9405 }
9406 dev_dbg(dev, "%s: system suspend\n", __func__);
9407 if (delayed_work_pending(&tavil->power_gate_work) &&
9408 cancel_delayed_work_sync(&tavil->power_gate_work))
9409 tavil_codec_power_gate_digital_core(tavil);
9410 return 0;
9411}
9412
9413static int tavil_resume(struct device *dev)
9414{
9415 struct platform_device *pdev = to_platform_device(dev);
9416 struct tavil_priv *tavil = platform_get_drvdata(pdev);
9417
9418 if (!tavil) {
9419 dev_err(dev, "%s: tavil private data is NULL\n", __func__);
9420 return -EINVAL;
9421 }
9422 dev_dbg(dev, "%s: system resume\n", __func__);
9423 return 0;
9424}
9425
9426static const struct dev_pm_ops tavil_pm_ops = {
9427 .suspend = tavil_suspend,
9428 .resume = tavil_resume,
9429};
9430#endif
9431
9432static int tavil_swrm_read(void *handle, int reg)
9433{
9434 struct tavil_priv *tavil;
9435 struct wcd9xxx *wcd9xxx;
9436 unsigned short swr_rd_addr_base;
9437 unsigned short swr_rd_data_base;
9438 int val, ret;
9439
9440 if (!handle) {
9441 pr_err("%s: NULL handle\n", __func__);
9442 return -EINVAL;
9443 }
9444 tavil = (struct tavil_priv *)handle;
9445 wcd9xxx = tavil->wcd9xxx;
9446
9447 dev_dbg(tavil->dev, "%s: Reading soundwire register, 0x%x\n",
9448 __func__, reg);
9449 swr_rd_addr_base = WCD934X_SWR_AHB_BRIDGE_RD_ADDR_0;
9450 swr_rd_data_base = WCD934X_SWR_AHB_BRIDGE_RD_DATA_0;
9451
9452 mutex_lock(&tavil->swr.read_mutex);
9453 ret = regmap_bulk_write(wcd9xxx->regmap, swr_rd_addr_base,
9454 (u8 *)&reg, 4);
9455 if (ret < 0) {
9456 dev_err(tavil->dev, "%s: RD Addr Failure\n", __func__);
9457 goto done;
9458 }
9459 ret = regmap_bulk_read(wcd9xxx->regmap, swr_rd_data_base,
9460 (u8 *)&val, 4);
9461 if (ret < 0) {
9462 dev_err(tavil->dev, "%s: RD Data Failure\n", __func__);
9463 goto done;
9464 }
9465 ret = val;
9466done:
9467 mutex_unlock(&tavil->swr.read_mutex);
9468
9469 return ret;
9470}
9471
9472static int tavil_swrm_bulk_write(void *handle, u32 *reg, u32 *val, size_t len)
9473{
9474 struct tavil_priv *tavil;
9475 struct wcd9xxx *wcd9xxx;
9476 struct wcd9xxx_reg_val *bulk_reg;
9477 unsigned short swr_wr_addr_base;
9478 unsigned short swr_wr_data_base;
9479 int i, j, ret;
9480
9481 if (!handle || !reg || !val) {
9482 pr_err("%s: NULL parameter\n", __func__);
9483 return -EINVAL;
9484 }
9485 if (len <= 0) {
9486 pr_err("%s: Invalid size: %zu\n", __func__, len);
9487 return -EINVAL;
9488 }
9489 tavil = (struct tavil_priv *)handle;
9490 wcd9xxx = tavil->wcd9xxx;
9491
9492 swr_wr_addr_base = WCD934X_SWR_AHB_BRIDGE_WR_ADDR_0;
9493 swr_wr_data_base = WCD934X_SWR_AHB_BRIDGE_WR_DATA_0;
9494
9495 bulk_reg = kzalloc((2 * len * sizeof(struct wcd9xxx_reg_val)),
9496 GFP_KERNEL);
9497 if (!bulk_reg)
9498 return -ENOMEM;
9499
9500 for (i = 0, j = 0; i < (len * 2); i += 2, j++) {
9501 bulk_reg[i].reg = swr_wr_data_base;
9502 bulk_reg[i].buf = (u8 *)(&val[j]);
9503 bulk_reg[i].bytes = 4;
9504 bulk_reg[i+1].reg = swr_wr_addr_base;
9505 bulk_reg[i+1].buf = (u8 *)(&reg[j]);
9506 bulk_reg[i+1].bytes = 4;
9507 }
9508
9509 mutex_lock(&tavil->swr.write_mutex);
9510 ret = wcd9xxx_slim_bulk_write(wcd9xxx, bulk_reg,
9511 (len * 2), false);
9512 if (ret) {
9513 dev_err(tavil->dev, "%s: swrm bulk write failed, ret: %d\n",
9514 __func__, ret);
9515 }
9516 mutex_unlock(&tavil->swr.write_mutex);
9517
9518 kfree(bulk_reg);
9519 return ret;
9520}
9521
9522static int tavil_swrm_write(void *handle, int reg, int val)
9523{
9524 struct tavil_priv *tavil;
9525 struct wcd9xxx *wcd9xxx;
9526 unsigned short swr_wr_addr_base;
9527 unsigned short swr_wr_data_base;
9528 struct wcd9xxx_reg_val bulk_reg[2];
9529 int ret;
9530
9531 if (!handle) {
9532 pr_err("%s: NULL handle\n", __func__);
9533 return -EINVAL;
9534 }
9535 tavil = (struct tavil_priv *)handle;
9536 wcd9xxx = tavil->wcd9xxx;
9537
9538 swr_wr_addr_base = WCD934X_SWR_AHB_BRIDGE_WR_ADDR_0;
9539 swr_wr_data_base = WCD934X_SWR_AHB_BRIDGE_WR_DATA_0;
9540
9541 /* First Write the Data to register */
9542 bulk_reg[0].reg = swr_wr_data_base;
9543 bulk_reg[0].buf = (u8 *)(&val);
9544 bulk_reg[0].bytes = 4;
9545 bulk_reg[1].reg = swr_wr_addr_base;
9546 bulk_reg[1].buf = (u8 *)(&reg);
9547 bulk_reg[1].bytes = 4;
9548
9549 mutex_lock(&tavil->swr.write_mutex);
9550 ret = wcd9xxx_slim_bulk_write(wcd9xxx, bulk_reg, 2, false);
9551 if (ret < 0)
9552 dev_err(tavil->dev, "%s: WR Data Failure\n", __func__);
9553 mutex_unlock(&tavil->swr.write_mutex);
9554
9555 return ret;
9556}
9557
9558static int tavil_swrm_clock(void *handle, bool enable)
9559{
9560 struct tavil_priv *tavil;
9561
9562 if (!handle) {
9563 pr_err("%s: NULL handle\n", __func__);
9564 return -EINVAL;
9565 }
9566 tavil = (struct tavil_priv *)handle;
9567
9568 mutex_lock(&tavil->swr.clk_mutex);
9569 dev_dbg(tavil->dev, "%s: swrm clock %s\n",
9570 __func__, (enable?"enable" : "disable"));
9571 if (enable) {
9572 tavil->swr.clk_users++;
9573 if (tavil->swr.clk_users == 1) {
9574 regmap_update_bits(tavil->wcd9xxx->regmap,
9575 WCD934X_TEST_DEBUG_NPL_DLY_TEST_1,
9576 0x10, 0x00);
9577 __tavil_cdc_mclk_enable(tavil, true);
9578 regmap_update_bits(tavil->wcd9xxx->regmap,
9579 WCD934X_CDC_CLK_RST_CTRL_SWR_CONTROL,
9580 0x01, 0x01);
9581 }
9582 } else {
9583 tavil->swr.clk_users--;
9584 if (tavil->swr.clk_users == 0) {
9585 regmap_update_bits(tavil->wcd9xxx->regmap,
9586 WCD934X_CDC_CLK_RST_CTRL_SWR_CONTROL,
9587 0x01, 0x00);
9588 __tavil_cdc_mclk_enable(tavil, false);
9589 regmap_update_bits(tavil->wcd9xxx->regmap,
9590 WCD934X_TEST_DEBUG_NPL_DLY_TEST_1,
9591 0x10, 0x10);
9592 }
9593 }
9594 dev_dbg(tavil->dev, "%s: swrm clock users %d\n",
9595 __func__, tavil->swr.clk_users);
9596 mutex_unlock(&tavil->swr.clk_mutex);
9597
9598 return 0;
9599}
9600
9601static int tavil_swrm_handle_irq(void *handle,
9602 irqreturn_t (*swrm_irq_handler)(int irq,
9603 void *data),
9604 void *swrm_handle,
9605 int action)
9606{
9607 struct tavil_priv *tavil;
9608 int ret = 0;
9609 struct wcd9xxx *wcd9xxx;
9610
9611 if (!handle) {
9612 pr_err("%s: NULL handle\n", __func__);
9613 return -EINVAL;
9614 }
9615 tavil = (struct tavil_priv *) handle;
9616 wcd9xxx = tavil->wcd9xxx;
9617
9618 if (action) {
9619 ret = wcd9xxx_request_irq(&wcd9xxx->core_res,
9620 WCD934X_IRQ_SOUNDWIRE,
9621 swrm_irq_handler,
9622 "Tavil SWR Master", swrm_handle);
9623 if (ret)
9624 dev_err(tavil->dev, "%s: Failed to request irq %d\n",
9625 __func__, WCD934X_IRQ_SOUNDWIRE);
9626 } else
9627 wcd9xxx_free_irq(&wcd9xxx->core_res, WCD934X_IRQ_SOUNDWIRE,
9628 swrm_handle);
9629
9630 return ret;
9631}
9632
9633static void tavil_codec_add_spi_device(struct tavil_priv *tavil,
9634 struct device_node *node)
9635{
9636 struct spi_master *master;
9637 struct spi_device *spi;
9638 u32 prop_value;
9639 int rc;
9640
9641 /* Read the master bus num from DT node */
9642 rc = of_property_read_u32(node, "qcom,master-bus-num",
9643 &prop_value);
Xiaoyu Ye1a2d8bd92017-01-31 18:54:15 -08009644 if (rc < 0) {
Banajit Goswamide8271c2017-01-18 00:28:59 -08009645 dev_err(tavil->dev, "%s: prop %s not found in node %s",
9646 __func__, "qcom,master-bus-num", node->full_name);
9647 goto done;
9648 }
9649
9650 /* Get the reference to SPI master */
9651 master = spi_busnum_to_master(prop_value);
9652 if (!master) {
9653 dev_err(tavil->dev, "%s: Invalid spi_master for bus_num %u\n",
9654 __func__, prop_value);
9655 goto done;
9656 }
9657
9658 /* Allocate the spi device */
9659 spi = spi_alloc_device(master);
9660 if (!spi) {
9661 dev_err(tavil->dev, "%s: spi_alloc_device failed\n",
9662 __func__);
9663 goto err_spi_alloc_dev;
9664 }
9665
9666 /* Initialize device properties */
9667 if (of_modalias_node(node, spi->modalias,
9668 sizeof(spi->modalias)) < 0) {
9669 dev_err(tavil->dev, "%s: cannot find modalias for %s\n",
9670 __func__, node->full_name);
9671 goto err_dt_parse;
9672 }
9673
9674 rc = of_property_read_u32(node, "qcom,chip-select",
9675 &prop_value);
Xiaoyu Ye1a2d8bd92017-01-31 18:54:15 -08009676 if (rc < 0) {
Banajit Goswamide8271c2017-01-18 00:28:59 -08009677 dev_err(tavil->dev, "%s: prop %s not found in node %s",
9678 __func__, "qcom,chip-select", node->full_name);
9679 goto err_dt_parse;
9680 }
9681 spi->chip_select = prop_value;
9682
9683 rc = of_property_read_u32(node, "qcom,max-frequency",
9684 &prop_value);
Xiaoyu Ye1a2d8bd92017-01-31 18:54:15 -08009685 if (rc < 0) {
Banajit Goswamide8271c2017-01-18 00:28:59 -08009686 dev_err(tavil->dev, "%s: prop %s not found in node %s",
9687 __func__, "qcom,max-frequency", node->full_name);
9688 goto err_dt_parse;
9689 }
9690 spi->max_speed_hz = prop_value;
9691
9692 spi->dev.of_node = node;
9693
9694 rc = spi_add_device(spi);
Xiaoyu Ye1a2d8bd92017-01-31 18:54:15 -08009695 if (rc < 0) {
Banajit Goswamide8271c2017-01-18 00:28:59 -08009696 dev_err(tavil->dev, "%s: spi_add_device failed\n", __func__);
9697 goto err_dt_parse;
9698 }
9699
9700 /* Put the reference to SPI master */
9701 put_device(&master->dev);
9702
9703 return;
9704
9705err_dt_parse:
9706 spi_dev_put(spi);
9707
9708err_spi_alloc_dev:
9709 /* Put the reference to SPI master */
9710 put_device(&master->dev);
9711done:
9712 return;
9713}
9714
9715static void tavil_add_child_devices(struct work_struct *work)
9716{
9717 struct tavil_priv *tavil;
9718 struct platform_device *pdev;
9719 struct device_node *node;
9720 struct wcd9xxx *wcd9xxx;
9721 struct tavil_swr_ctrl_data *swr_ctrl_data = NULL, *temp;
9722 int ret, ctrl_num = 0;
9723 struct wcd_swr_ctrl_platform_data *platdata;
9724 char plat_dev_name[WCD934X_STRING_LEN];
9725
9726 tavil = container_of(work, struct tavil_priv,
9727 tavil_add_child_devices_work);
9728 if (!tavil) {
9729 pr_err("%s: Memory for WCD934X does not exist\n",
9730 __func__);
9731 return;
9732 }
9733 wcd9xxx = tavil->wcd9xxx;
9734 if (!wcd9xxx) {
9735 pr_err("%s: Memory for WCD9XXX does not exist\n",
9736 __func__);
9737 return;
9738 }
9739 if (!wcd9xxx->dev->of_node) {
9740 dev_err(wcd9xxx->dev, "%s: DT node for wcd9xxx does not exist\n",
9741 __func__);
9742 return;
9743 }
9744
9745 platdata = &tavil->swr.plat_data;
9746
9747 for_each_child_of_node(wcd9xxx->dev->of_node, node) {
9748
9749 /* Parse and add the SPI device node */
9750 if (!strcmp(node->name, "wcd_spi")) {
9751 tavil_codec_add_spi_device(tavil, node);
9752 continue;
9753 }
9754
9755 /* Parse other child device nodes and add platform device */
9756 if (!strcmp(node->name, "swr_master"))
9757 strlcpy(plat_dev_name, "tavil_swr_ctrl",
9758 (WCD934X_STRING_LEN - 1));
9759 else if (strnstr(node->name, "msm_cdc_pinctrl",
9760 strlen("msm_cdc_pinctrl")) != NULL)
9761 strlcpy(plat_dev_name, node->name,
9762 (WCD934X_STRING_LEN - 1));
9763 else
9764 continue;
9765
9766 pdev = platform_device_alloc(plat_dev_name, -1);
9767 if (!pdev) {
9768 dev_err(wcd9xxx->dev, "%s: pdev memory alloc failed\n",
9769 __func__);
9770 ret = -ENOMEM;
9771 goto err_mem;
9772 }
9773 pdev->dev.parent = tavil->dev;
9774 pdev->dev.of_node = node;
9775
9776 if (strcmp(node->name, "swr_master") == 0) {
9777 ret = platform_device_add_data(pdev, platdata,
9778 sizeof(*platdata));
9779 if (ret) {
9780 dev_err(&pdev->dev,
9781 "%s: cannot add plat data ctrl:%d\n",
9782 __func__, ctrl_num);
9783 goto err_pdev_add;
9784 }
9785 }
9786
9787 ret = platform_device_add(pdev);
9788 if (ret) {
9789 dev_err(&pdev->dev,
9790 "%s: Cannot add platform device\n",
9791 __func__);
9792 goto err_pdev_add;
9793 }
9794
9795 if (strcmp(node->name, "swr_master") == 0) {
9796 temp = krealloc(swr_ctrl_data,
9797 (ctrl_num + 1) * sizeof(
9798 struct tavil_swr_ctrl_data),
9799 GFP_KERNEL);
9800 if (!temp) {
9801 dev_err(wcd9xxx->dev, "out of memory\n");
9802 ret = -ENOMEM;
9803 goto err_pdev_add;
9804 }
9805 swr_ctrl_data = temp;
9806 swr_ctrl_data[ctrl_num].swr_pdev = pdev;
9807 ctrl_num++;
9808 dev_dbg(&pdev->dev,
9809 "%s: Added soundwire ctrl device(s)\n",
9810 __func__);
9811 tavil->swr.ctrl_data = swr_ctrl_data;
9812 }
9813 }
9814
9815 return;
9816
9817err_pdev_add:
9818 platform_device_put(pdev);
9819err_mem:
9820 return;
9821}
9822
9823static int __tavil_enable_efuse_sensing(struct tavil_priv *tavil)
9824{
9825 int val, rc;
9826
9827 __tavil_cdc_mclk_enable(tavil, true);
9828
9829 regmap_update_bits(tavil->wcd9xxx->regmap,
9830 WCD934X_CHIP_TIER_CTRL_EFUSE_CTL, 0x1E, 0x10);
9831 regmap_update_bits(tavil->wcd9xxx->regmap,
9832 WCD934X_CHIP_TIER_CTRL_EFUSE_CTL, 0x01, 0x01);
9833
9834 /*
9835 * 5ms sleep required after enabling efuse control
9836 * before checking the status.
9837 */
9838 usleep_range(5000, 5500);
9839 rc = regmap_read(tavil->wcd9xxx->regmap,
9840 WCD934X_CHIP_TIER_CTRL_EFUSE_STATUS, &val);
9841 if (rc || (!(val & 0x01)))
9842 WARN(1, "%s: Efuse sense is not complete val=%x, ret=%d\n",
9843 __func__, val, rc);
9844
9845 __tavil_cdc_mclk_enable(tavil, false);
9846
9847 return rc;
9848}
9849
9850static void ___tavil_get_codec_fine_version(struct tavil_priv *tavil)
9851{
9852 int val1, val2, version;
9853 struct regmap *regmap;
9854 u16 id_minor;
9855 u32 version_mask = 0;
9856
9857 regmap = tavil->wcd9xxx->regmap;
9858 version = tavil->wcd9xxx->version;
9859 id_minor = tavil->wcd9xxx->codec_type->id_minor;
9860
9861 regmap_read(regmap, WCD934X_CHIP_TIER_CTRL_EFUSE_VAL_OUT14, &val1);
9862 regmap_read(regmap, WCD934X_CHIP_TIER_CTRL_EFUSE_VAL_OUT15, &val2);
9863
9864 dev_dbg(tavil->dev, "%s: chip version :0x%x 0x:%x\n",
9865 __func__, val1, val2);
9866
9867 version_mask |= (!!((u8)val1 & 0x80)) << DSD_DISABLED_MASK;
9868 version_mask |= (!!((u8)val2 & 0x01)) << SLNQ_DISABLED_MASK;
9869
9870 switch (version_mask) {
9871 case DSD_DISABLED | SLNQ_DISABLED:
9872 if (id_minor == cpu_to_le16(0))
9873 version = TAVIL_VERSION_WCD9340_1_0;
9874 else if (id_minor == cpu_to_le16(0x01))
9875 version = TAVIL_VERSION_WCD9340_1_1;
9876 break;
9877 case SLNQ_DISABLED:
9878 if (id_minor == cpu_to_le16(0))
9879 version = TAVIL_VERSION_WCD9341_1_0;
9880 else if (id_minor == cpu_to_le16(0x01))
9881 version = TAVIL_VERSION_WCD9341_1_1;
9882 break;
9883 }
9884
9885 tavil->wcd9xxx->version = version;
9886 tavil->wcd9xxx->codec_type->version = version;
9887}
9888
9889/*
9890 * tavil_get_wcd_dsp_cntl: Get the reference to wcd_dsp_cntl
9891 * @dev: Device pointer for codec device
9892 *
9893 * This API gets the reference to codec's struct wcd_dsp_cntl
9894 */
9895struct wcd_dsp_cntl *tavil_get_wcd_dsp_cntl(struct device *dev)
9896{
9897 struct platform_device *pdev;
9898 struct tavil_priv *tavil;
9899
9900 if (!dev) {
9901 pr_err("%s: Invalid device\n", __func__);
9902 return NULL;
9903 }
9904
9905 pdev = to_platform_device(dev);
9906 tavil = platform_get_drvdata(pdev);
9907
9908 return tavil->wdsp_cntl;
9909}
9910EXPORT_SYMBOL(tavil_get_wcd_dsp_cntl);
9911
9912static int tavil_probe(struct platform_device *pdev)
9913{
9914 int ret = 0;
9915 struct tavil_priv *tavil;
9916 struct clk *wcd_ext_clk;
9917 struct wcd9xxx_resmgr_v2 *resmgr;
9918 struct wcd9xxx_power_region *cdc_pwr;
9919
9920 tavil = devm_kzalloc(&pdev->dev, sizeof(struct tavil_priv),
9921 GFP_KERNEL);
9922 if (!tavil)
9923 return -ENOMEM;
9924
9925 platform_set_drvdata(pdev, tavil);
9926
9927 tavil->wcd9xxx = dev_get_drvdata(pdev->dev.parent);
9928 tavil->dev = &pdev->dev;
9929 INIT_DELAYED_WORK(&tavil->power_gate_work, tavil_codec_power_gate_work);
9930 mutex_init(&tavil->power_lock);
9931 INIT_WORK(&tavil->tavil_add_child_devices_work,
9932 tavil_add_child_devices);
9933 mutex_init(&tavil->micb_lock);
9934 mutex_init(&tavil->swr.read_mutex);
9935 mutex_init(&tavil->swr.write_mutex);
9936 mutex_init(&tavil->swr.clk_mutex);
9937 mutex_init(&tavil->codec_mutex);
9938 mutex_init(&tavil->svs_mutex);
9939
9940 /*
9941 * Codec hardware by default comes up in SVS mode.
9942 * Initialize the svs_ref_cnt to 1 to reflect the hardware
9943 * state in the driver.
9944 */
9945 tavil->svs_ref_cnt = 1;
9946
9947 cdc_pwr = devm_kzalloc(&pdev->dev, sizeof(struct wcd9xxx_power_region),
9948 GFP_KERNEL);
9949 if (!cdc_pwr) {
9950 ret = -ENOMEM;
9951 goto err_resmgr;
9952 }
9953 tavil->wcd9xxx->wcd9xxx_pwr[WCD9XXX_DIG_CORE_REGION_1] = cdc_pwr;
9954 cdc_pwr->pwr_collapse_reg_min = WCD934X_DIG_CORE_REG_MIN;
9955 cdc_pwr->pwr_collapse_reg_max = WCD934X_DIG_CORE_REG_MAX;
9956 wcd9xxx_set_power_state(tavil->wcd9xxx,
9957 WCD_REGION_POWER_COLLAPSE_REMOVE,
9958 WCD9XXX_DIG_CORE_REGION_1);
9959 /*
9960 * Init resource manager so that if child nodes such as SoundWire
9961 * requests for clock, resource manager can honor the request
9962 */
9963 resmgr = wcd_resmgr_init(&tavil->wcd9xxx->core_res, NULL);
9964 if (IS_ERR(resmgr)) {
9965 ret = PTR_ERR(resmgr);
9966 dev_err(&pdev->dev, "%s: Failed to initialize wcd resmgr\n",
9967 __func__);
9968 goto err_resmgr;
9969 }
9970 tavil->resmgr = resmgr;
9971 tavil->swr.plat_data.handle = (void *) tavil;
9972 tavil->swr.plat_data.read = tavil_swrm_read;
9973 tavil->swr.plat_data.write = tavil_swrm_write;
9974 tavil->swr.plat_data.bulk_write = tavil_swrm_bulk_write;
9975 tavil->swr.plat_data.clk = tavil_swrm_clock;
9976 tavil->swr.plat_data.handle_irq = tavil_swrm_handle_irq;
9977 tavil->swr.spkr_gain_offset = WCD934X_RX_GAIN_OFFSET_0_DB;
9978
9979 /* Register for Clock */
9980 wcd_ext_clk = clk_get(tavil->wcd9xxx->dev, "wcd_clk");
9981 if (IS_ERR(wcd_ext_clk)) {
9982 dev_err(tavil->wcd9xxx->dev, "%s: clk get %s failed\n",
9983 __func__, "wcd_ext_clk");
9984 goto err_clk;
9985 }
9986 tavil->wcd_ext_clk = wcd_ext_clk;
9987 set_bit(AUDIO_NOMINAL, &tavil->status_mask);
9988 /* Update codec register default values */
9989 dev_dbg(&pdev->dev, "%s: MCLK Rate = %x\n", __func__,
9990 tavil->wcd9xxx->mclk_rate);
9991 if (tavil->wcd9xxx->mclk_rate == WCD934X_MCLK_CLK_12P288MHZ)
9992 regmap_update_bits(tavil->wcd9xxx->regmap,
9993 WCD934X_CODEC_RPM_CLK_MCLK_CFG,
9994 0x03, 0x00);
9995 else if (tavil->wcd9xxx->mclk_rate == WCD934X_MCLK_CLK_9P6MHZ)
9996 regmap_update_bits(tavil->wcd9xxx->regmap,
9997 WCD934X_CODEC_RPM_CLK_MCLK_CFG,
9998 0x03, 0x01);
9999 tavil_update_reg_defaults(tavil);
10000 __tavil_enable_efuse_sensing(tavil);
10001 ___tavil_get_codec_fine_version(tavil);
10002 tavil_update_cpr_defaults(tavil);
10003
10004 /* Register with soc framework */
10005 ret = snd_soc_register_codec(&pdev->dev, &soc_codec_dev_tavil,
10006 tavil_dai, ARRAY_SIZE(tavil_dai));
10007 if (ret) {
10008 dev_err(&pdev->dev, "%s: Codec registration failed\n",
10009 __func__);
10010 goto err_cdc_reg;
10011 }
10012 schedule_work(&tavil->tavil_add_child_devices_work);
10013
10014 return ret;
10015
10016err_cdc_reg:
10017 clk_put(tavil->wcd_ext_clk);
10018err_clk:
10019 wcd_resmgr_remove(tavil->resmgr);
10020err_resmgr:
10021 mutex_destroy(&tavil->micb_lock);
10022 mutex_destroy(&tavil->svs_mutex);
10023 mutex_destroy(&tavil->codec_mutex);
10024 mutex_destroy(&tavil->swr.read_mutex);
10025 mutex_destroy(&tavil->swr.write_mutex);
10026 mutex_destroy(&tavil->swr.clk_mutex);
10027 devm_kfree(&pdev->dev, tavil);
10028
10029 return ret;
10030}
10031
10032static int tavil_remove(struct platform_device *pdev)
10033{
10034 struct tavil_priv *tavil;
10035
10036 tavil = platform_get_drvdata(pdev);
10037 if (!tavil)
10038 return -EINVAL;
10039
10040 mutex_destroy(&tavil->micb_lock);
10041 mutex_destroy(&tavil->svs_mutex);
10042 mutex_destroy(&tavil->codec_mutex);
10043 mutex_destroy(&tavil->swr.read_mutex);
10044 mutex_destroy(&tavil->swr.write_mutex);
10045 mutex_destroy(&tavil->swr.clk_mutex);
10046
10047 snd_soc_unregister_codec(&pdev->dev);
10048 clk_put(tavil->wcd_ext_clk);
10049 wcd_resmgr_remove(tavil->resmgr);
10050 if (tavil->dsd_config) {
10051 tavil_dsd_deinit(tavil->dsd_config);
10052 tavil->dsd_config = NULL;
10053 }
10054 devm_kfree(&pdev->dev, tavil);
10055 return 0;
10056}
10057
10058static struct platform_driver tavil_codec_driver = {
10059 .probe = tavil_probe,
10060 .remove = tavil_remove,
10061 .driver = {
10062 .name = "tavil_codec",
10063 .owner = THIS_MODULE,
10064#ifdef CONFIG_PM
10065 .pm = &tavil_pm_ops,
10066#endif
10067 },
10068};
10069
10070module_platform_driver(tavil_codec_driver);
10071
10072MODULE_DESCRIPTION("Tavil Codec driver");
10073MODULE_LICENSE("GPL v2");