blob: c0a32f3a3ffc851604795317f8d38eff8f2d2519 [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{
Banajit Goswamide8271c2017-01-18 00:28:59 -08008098 mutex_lock(&tavil->power_lock);
Phani Kumar Uppalapatib893bbb2017-01-30 18:12:59 -08008099 dev_dbg(tavil->dev, "%s: Entering power gating function, %d\n",
Banajit Goswamide8271c2017-01-18 00:28:59 -08008100 __func__, tavil->power_active_ref);
8101
8102 if (tavil->power_active_ref > 0)
8103 goto exit;
8104
8105 wcd9xxx_set_power_state(tavil->wcd9xxx,
8106 WCD_REGION_POWER_COLLAPSE_BEGIN,
8107 WCD9XXX_DIG_CORE_REGION_1);
Phani Kumar Uppalapatib893bbb2017-01-30 18:12:59 -08008108 regmap_update_bits(tavil->wcd9xxx->regmap,
8109 WCD934X_CODEC_RPM_PWR_CDC_DIG_HM_CTL, 0x04, 0x04);
8110 regmap_update_bits(tavil->wcd9xxx->regmap,
8111 WCD934X_CODEC_RPM_PWR_CDC_DIG_HM_CTL, 0x01, 0x00);
8112 regmap_update_bits(tavil->wcd9xxx->regmap,
8113 WCD934X_CODEC_RPM_PWR_CDC_DIG_HM_CTL, 0x02, 0x00);
Banajit Goswamide8271c2017-01-18 00:28:59 -08008114 wcd9xxx_set_power_state(tavil->wcd9xxx, WCD_REGION_POWER_DOWN,
8115 WCD9XXX_DIG_CORE_REGION_1);
8116exit:
Phani Kumar Uppalapatib893bbb2017-01-30 18:12:59 -08008117 dev_dbg(tavil->dev, "%s: Exiting power gating function, %d\n",
Banajit Goswamide8271c2017-01-18 00:28:59 -08008118 __func__, tavil->power_active_ref);
8119 mutex_unlock(&tavil->power_lock);
8120}
8121
8122static void tavil_codec_power_gate_work(struct work_struct *work)
8123{
8124 struct tavil_priv *tavil;
8125 struct delayed_work *dwork;
Banajit Goswamide8271c2017-01-18 00:28:59 -08008126
8127 dwork = to_delayed_work(work);
8128 tavil = container_of(dwork, struct tavil_priv, power_gate_work);
Banajit Goswamide8271c2017-01-18 00:28:59 -08008129
8130 tavil_codec_power_gate_digital_core(tavil);
8131}
8132
8133/* called under power_lock acquisition */
Phani Kumar Uppalapatib893bbb2017-01-30 18:12:59 -08008134static int tavil_dig_core_remove_power_collapse(struct tavil_priv *tavil)
Banajit Goswamide8271c2017-01-18 00:28:59 -08008135{
Phani Kumar Uppalapatib893bbb2017-01-30 18:12:59 -08008136 regmap_write(tavil->wcd9xxx->regmap,
8137 WCD934X_CODEC_RPM_PWR_CDC_DIG_HM_CTL, 0x05);
8138 regmap_write(tavil->wcd9xxx->regmap,
8139 WCD934X_CODEC_RPM_PWR_CDC_DIG_HM_CTL, 0x07);
8140 regmap_update_bits(tavil->wcd9xxx->regmap,
8141 WCD934X_CODEC_RPM_RST_CTL, 0x02, 0x00);
8142 regmap_update_bits(tavil->wcd9xxx->regmap,
8143 WCD934X_CODEC_RPM_RST_CTL, 0x02, 0x02);
8144 regmap_write(tavil->wcd9xxx->regmap,
8145 WCD934X_CODEC_RPM_PWR_CDC_DIG_HM_CTL, 0x03);
Banajit Goswamide8271c2017-01-18 00:28:59 -08008146
8147 wcd9xxx_set_power_state(tavil->wcd9xxx,
8148 WCD_REGION_POWER_COLLAPSE_REMOVE,
8149 WCD9XXX_DIG_CORE_REGION_1);
Phani Kumar Uppalapatib893bbb2017-01-30 18:12:59 -08008150 regcache_mark_dirty(tavil->wcd9xxx->regmap);
8151 regcache_sync_region(tavil->wcd9xxx->regmap,
Banajit Goswamide8271c2017-01-18 00:28:59 -08008152 WCD934X_DIG_CORE_REG_MIN,
8153 WCD934X_DIG_CORE_REG_MAX);
8154
8155 return 0;
8156}
8157
8158static int tavil_dig_core_power_collapse(struct tavil_priv *tavil,
8159 int req_state)
8160{
Banajit Goswamide8271c2017-01-18 00:28:59 -08008161 int cur_state;
8162
8163 /* Exit if feature is disabled */
8164 if (!dig_core_collapse_enable)
8165 return 0;
8166
8167 mutex_lock(&tavil->power_lock);
8168 if (req_state == POWER_COLLAPSE)
8169 tavil->power_active_ref--;
8170 else if (req_state == POWER_RESUME)
8171 tavil->power_active_ref++;
8172 else
8173 goto unlock_mutex;
8174
8175 if (tavil->power_active_ref < 0) {
8176 dev_dbg(tavil->dev, "%s: power_active_ref is negative\n",
8177 __func__);
8178 goto unlock_mutex;
8179 }
8180
Banajit Goswamide8271c2017-01-18 00:28:59 -08008181 if (req_state == POWER_COLLAPSE) {
8182 if (tavil->power_active_ref == 0) {
8183 schedule_delayed_work(&tavil->power_gate_work,
8184 msecs_to_jiffies(dig_core_collapse_timer * 1000));
8185 }
8186 } else if (req_state == POWER_RESUME) {
8187 if (tavil->power_active_ref == 1) {
8188 /*
8189 * At this point, there can be two cases:
8190 * 1. Core already in power collapse state
8191 * 2. Timer kicked in and still did not expire or
8192 * waiting for the power_lock
8193 */
8194 cur_state = wcd9xxx_get_current_power_state(
8195 tavil->wcd9xxx,
8196 WCD9XXX_DIG_CORE_REGION_1);
8197 if (cur_state == WCD_REGION_POWER_DOWN) {
Phani Kumar Uppalapatib893bbb2017-01-30 18:12:59 -08008198 tavil_dig_core_remove_power_collapse(tavil);
Banajit Goswamide8271c2017-01-18 00:28:59 -08008199 } else {
8200 mutex_unlock(&tavil->power_lock);
8201 cancel_delayed_work_sync(
8202 &tavil->power_gate_work);
8203 mutex_lock(&tavil->power_lock);
8204 }
8205 }
8206 }
8207
8208unlock_mutex:
8209 mutex_unlock(&tavil->power_lock);
8210
8211 return 0;
8212}
8213
8214static int tavil_cdc_req_mclk_enable(struct tavil_priv *tavil,
8215 bool enable)
8216{
8217 int ret = 0;
8218
8219 if (enable) {
8220 ret = clk_prepare_enable(tavil->wcd_ext_clk);
8221 if (ret) {
8222 dev_err(tavil->dev, "%s: ext clk enable failed\n",
8223 __func__);
8224 goto done;
8225 }
8226 /* get BG */
8227 wcd_resmgr_enable_master_bias(tavil->resmgr);
8228 /* get MCLK */
8229 wcd_resmgr_enable_clk_block(tavil->resmgr, WCD_CLK_MCLK);
8230 } else {
8231 /* put MCLK */
8232 wcd_resmgr_disable_clk_block(tavil->resmgr, WCD_CLK_MCLK);
8233 /* put BG */
8234 wcd_resmgr_disable_master_bias(tavil->resmgr);
8235 clk_disable_unprepare(tavil->wcd_ext_clk);
8236 }
8237
8238done:
8239 return ret;
8240}
8241
8242static int __tavil_cdc_mclk_enable_locked(struct tavil_priv *tavil,
8243 bool enable)
8244{
8245 int ret = 0;
8246
8247 if (!tavil->wcd_ext_clk) {
8248 dev_err(tavil->dev, "%s: wcd ext clock is NULL\n", __func__);
8249 return -EINVAL;
8250 }
8251
8252 dev_dbg(tavil->dev, "%s: mclk_enable = %u\n", __func__, enable);
8253
8254 if (enable) {
8255 tavil_dig_core_power_collapse(tavil, POWER_RESUME);
8256 tavil_vote_svs(tavil, true);
8257 ret = tavil_cdc_req_mclk_enable(tavil, true);
8258 if (ret)
8259 goto done;
8260 } else {
8261 tavil_cdc_req_mclk_enable(tavil, false);
8262 tavil_vote_svs(tavil, false);
8263 tavil_dig_core_power_collapse(tavil, POWER_COLLAPSE);
8264 }
8265
8266done:
8267 return ret;
8268}
8269
8270static int __tavil_cdc_mclk_enable(struct tavil_priv *tavil,
8271 bool enable)
8272{
8273 int ret;
8274
8275 WCD9XXX_V2_BG_CLK_LOCK(tavil->resmgr);
8276 ret = __tavil_cdc_mclk_enable_locked(tavil, enable);
8277 WCD9XXX_V2_BG_CLK_UNLOCK(tavil->resmgr);
8278
8279 return ret;
8280}
8281
8282static ssize_t tavil_codec_version_read(struct snd_info_entry *entry,
8283 void *file_private_data,
8284 struct file *file,
8285 char __user *buf, size_t count,
8286 loff_t pos)
8287{
8288 struct tavil_priv *tavil;
8289 struct wcd9xxx *wcd9xxx;
8290 char buffer[TAVIL_VERSION_ENTRY_SIZE];
8291 int len = 0;
8292
8293 tavil = (struct tavil_priv *) entry->private_data;
8294 if (!tavil) {
8295 pr_err("%s: tavil priv is null\n", __func__);
8296 return -EINVAL;
8297 }
8298
8299 wcd9xxx = tavil->wcd9xxx;
8300
8301 switch (wcd9xxx->version) {
8302 case TAVIL_VERSION_WCD9340_1_0:
8303 len = snprintf(buffer, sizeof(buffer), "WCD9340_1_0\n");
8304 break;
8305 case TAVIL_VERSION_WCD9341_1_0:
8306 len = snprintf(buffer, sizeof(buffer), "WCD9341_1_0\n");
8307 break;
8308 case TAVIL_VERSION_WCD9340_1_1:
8309 len = snprintf(buffer, sizeof(buffer), "WCD9340_1_1\n");
8310 break;
8311 case TAVIL_VERSION_WCD9341_1_1:
8312 len = snprintf(buffer, sizeof(buffer), "WCD9341_1_1\n");
8313 break;
8314 default:
8315 len = snprintf(buffer, sizeof(buffer), "VER_UNDEFINED\n");
8316 }
8317
8318 return simple_read_from_buffer(buf, count, &pos, buffer, len);
8319}
8320
8321static struct snd_info_entry_ops tavil_codec_info_ops = {
8322 .read = tavil_codec_version_read,
8323};
8324
8325/*
8326 * tavil_codec_info_create_codec_entry - creates wcd934x module
8327 * @codec_root: The parent directory
8328 * @codec: Codec instance
8329 *
8330 * Creates wcd934x module and version entry under the given
8331 * parent directory.
8332 *
8333 * Return: 0 on success or negative error code on failure.
8334 */
8335int tavil_codec_info_create_codec_entry(struct snd_info_entry *codec_root,
8336 struct snd_soc_codec *codec)
8337{
8338 struct snd_info_entry *version_entry;
8339 struct tavil_priv *tavil;
8340 struct snd_soc_card *card;
8341
8342 if (!codec_root || !codec)
8343 return -EINVAL;
8344
8345 tavil = snd_soc_codec_get_drvdata(codec);
8346 card = codec->component.card;
Banajit Goswami7f40ea42017-01-30 13:32:41 -08008347 tavil->entry = snd_info_create_subdir(codec_root->module,
8348 "tavil", codec_root);
Banajit Goswamide8271c2017-01-18 00:28:59 -08008349 if (!tavil->entry) {
8350 dev_dbg(codec->dev, "%s: failed to create wcd934x entry\n",
8351 __func__);
8352 return -ENOMEM;
8353 }
8354
8355 version_entry = snd_info_create_card_entry(card->snd_card,
8356 "version",
8357 tavil->entry);
8358 if (!version_entry) {
8359 dev_dbg(codec->dev, "%s: failed to create wcd934x version entry\n",
8360 __func__);
8361 return -ENOMEM;
8362 }
8363
8364 version_entry->private_data = tavil;
8365 version_entry->size = TAVIL_VERSION_ENTRY_SIZE;
8366 version_entry->content = SNDRV_INFO_CONTENT_DATA;
8367 version_entry->c.ops = &tavil_codec_info_ops;
8368
8369 if (snd_info_register(version_entry) < 0) {
8370 snd_info_free_entry(version_entry);
8371 return -ENOMEM;
8372 }
8373 tavil->version_entry = version_entry;
8374
8375 return 0;
8376}
8377EXPORT_SYMBOL(tavil_codec_info_create_codec_entry);
8378
8379/**
8380 * tavil_cdc_mclk_enable - Enable/disable codec mclk
8381 *
8382 * @codec: codec instance
8383 * @enable: Indicates clk enable or disable
8384 *
8385 * Returns 0 on Success and error on failure
8386 */
8387int tavil_cdc_mclk_enable(struct snd_soc_codec *codec, bool enable)
8388{
8389 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
8390
8391 return __tavil_cdc_mclk_enable(tavil, enable);
8392}
8393EXPORT_SYMBOL(tavil_cdc_mclk_enable);
8394
8395static int __tavil_codec_internal_rco_ctrl(struct snd_soc_codec *codec,
8396 bool enable)
8397{
8398 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
8399 int ret = 0;
8400
8401 if (enable) {
8402 if (wcd_resmgr_get_clk_type(tavil->resmgr) ==
8403 WCD_CLK_RCO) {
8404 ret = wcd_resmgr_enable_clk_block(tavil->resmgr,
8405 WCD_CLK_RCO);
8406 } else {
8407 ret = tavil_cdc_req_mclk_enable(tavil, true);
8408 if (ret) {
8409 dev_err(codec->dev,
8410 "%s: mclk_enable failed, err = %d\n",
8411 __func__, ret);
8412 goto done;
8413 }
8414 ret = wcd_resmgr_enable_clk_block(tavil->resmgr,
8415 WCD_CLK_RCO);
8416 ret |= tavil_cdc_req_mclk_enable(tavil, false);
8417 }
8418
8419 } else {
8420 ret = wcd_resmgr_disable_clk_block(tavil->resmgr,
8421 WCD_CLK_RCO);
8422 }
8423
8424 if (ret) {
8425 dev_err(codec->dev, "%s: Error in %s RCO\n",
8426 __func__, (enable ? "enabling" : "disabling"));
8427 ret = -EINVAL;
8428 }
8429
8430done:
8431 return ret;
8432}
8433
8434/*
8435 * tavil_codec_internal_rco_ctrl: Enable/Disable codec's RCO clock
8436 * @codec: Handle to the codec
8437 * @enable: Indicates whether clock should be enabled or disabled
8438 */
8439static int tavil_codec_internal_rco_ctrl(struct snd_soc_codec *codec,
8440 bool enable)
8441{
8442 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
8443 int ret = 0;
8444
8445 WCD9XXX_V2_BG_CLK_LOCK(tavil->resmgr);
8446 ret = __tavil_codec_internal_rco_ctrl(codec, enable);
8447 WCD9XXX_V2_BG_CLK_UNLOCK(tavil->resmgr);
8448 return ret;
8449}
8450
8451static const struct wcd_resmgr_cb tavil_resmgr_cb = {
8452 .cdc_rco_ctrl = __tavil_codec_internal_rco_ctrl,
8453};
8454
8455static const struct tavil_reg_mask_val tavil_codec_mclk2_1_1_defaults[] = {
8456 {WCD934X_CLK_SYS_MCLK2_PRG1, 0x60, 0x20},
8457};
8458
8459static const struct tavil_reg_mask_val tavil_codec_mclk2_1_0_defaults[] = {
8460 /*
8461 * PLL Settings:
8462 * Clock Root: MCLK2,
8463 * Clock Source: EXT_CLK,
8464 * Clock Destination: MCLK2
8465 * Clock Freq In: 19.2MHz,
8466 * Clock Freq Out: 11.2896MHz
8467 */
8468 {WCD934X_CLK_SYS_MCLK2_PRG1, 0x60, 0x20},
8469 {WCD934X_CLK_SYS_INT_POST_DIV_REG0, 0xFF, 0x5E},
8470 {WCD934X_CLK_SYS_INT_POST_DIV_REG1, 0x1F, 0x1F},
8471 {WCD934X_CLK_SYS_INT_REF_DIV_REG0, 0xFF, 0x54},
8472 {WCD934X_CLK_SYS_INT_REF_DIV_REG1, 0xFF, 0x01},
8473 {WCD934X_CLK_SYS_INT_FILTER_REG1, 0x07, 0x04},
8474 {WCD934X_CLK_SYS_INT_PLL_L_VAL, 0xFF, 0x93},
8475 {WCD934X_CLK_SYS_INT_PLL_N_VAL, 0xFF, 0xFA},
8476 {WCD934X_CLK_SYS_INT_TEST_REG0, 0xFF, 0x90},
8477 {WCD934X_CLK_SYS_INT_PFD_CP_DSM_PROG, 0xFF, 0x7E},
8478 {WCD934X_CLK_SYS_INT_VCO_PROG, 0xFF, 0xF8},
8479 {WCD934X_CLK_SYS_INT_TEST_REG1, 0xFF, 0x68},
8480 {WCD934X_CLK_SYS_INT_LDO_LOCK_CFG, 0xFF, 0x40},
8481 {WCD934X_CLK_SYS_INT_DIG_LOCK_DET_CFG, 0xFF, 0x32},
8482};
8483
8484static const struct tavil_reg_mask_val tavil_codec_reg_defaults[] = {
8485 {WCD934X_BIAS_VBG_FINE_ADJ, 0xFF, 0x75},
8486 {WCD934X_CODEC_CPR_SVS_CX_VDD, 0xFF, 0x7C}, /* value in svs mode */
8487 {WCD934X_CODEC_CPR_SVS2_CX_VDD, 0xFF, 0x58}, /* value in svs2 mode */
8488 {WCD934X_CDC_RX0_RX_PATH_DSMDEM_CTL, 0x01, 0x01},
8489 {WCD934X_CDC_RX1_RX_PATH_DSMDEM_CTL, 0x01, 0x01},
8490 {WCD934X_CDC_RX2_RX_PATH_DSMDEM_CTL, 0x01, 0x01},
8491 {WCD934X_CDC_RX3_RX_PATH_DSMDEM_CTL, 0x01, 0x01},
8492 {WCD934X_CDC_RX4_RX_PATH_DSMDEM_CTL, 0x01, 0x01},
8493 {WCD934X_CDC_RX7_RX_PATH_DSMDEM_CTL, 0x01, 0x01},
8494 {WCD934X_CDC_RX8_RX_PATH_DSMDEM_CTL, 0x01, 0x01},
8495 {WCD934X_CDC_COMPANDER8_CTL7, 0x1E, 0x18},
8496 {WCD934X_CDC_COMPANDER7_CTL7, 0x1E, 0x18},
8497 {WCD934X_CDC_RX0_RX_PATH_SEC0, 0x08, 0x0},
8498 {WCD934X_CDC_CLSH_DECAY_CTRL, 0x03, 0x0},
8499 {WCD934X_MICB1_TEST_CTL_2, 0x07, 0x01},
8500 {WCD934X_CDC_BOOST0_BOOST_CFG1, 0x3F, 0x12},
8501 {WCD934X_CDC_BOOST0_BOOST_CFG2, 0x1C, 0x08},
8502 {WCD934X_CDC_BOOST1_BOOST_CFG1, 0x3F, 0x12},
8503 {WCD934X_CDC_BOOST1_BOOST_CFG2, 0x1C, 0x08},
8504 {WCD934X_CPE_SS_CPARMAD_BUFRDY_INT_PERIOD, 0x1F, 0x09},
8505 {WCD934X_CDC_TX0_TX_PATH_CFG1, 0x01, 0x00},
8506 {WCD934X_CDC_TX1_TX_PATH_CFG1, 0x01, 0x00},
8507 {WCD934X_CDC_TX2_TX_PATH_CFG1, 0x01, 0x00},
8508 {WCD934X_CDC_TX3_TX_PATH_CFG1, 0x01, 0x00},
8509 {WCD934X_CDC_TX4_TX_PATH_CFG1, 0x01, 0x00},
8510 {WCD934X_CDC_TX5_TX_PATH_CFG1, 0x01, 0x00},
8511 {WCD934X_CDC_TX6_TX_PATH_CFG1, 0x01, 0x00},
8512 {WCD934X_CDC_TX7_TX_PATH_CFG1, 0x01, 0x00},
8513 {WCD934X_CDC_TX8_TX_PATH_CFG1, 0x01, 0x00},
8514 {WCD934X_RX_OCP_CTL, 0x0F, 0x02}, /* OCP number of attempts is 2 */
8515 {WCD934X_HPH_OCP_CTL, 0xFF, 0x3A}, /* OCP current limit */
8516 {WCD934X_HPH_L_TEST, 0x01, 0x01},
8517 {WCD934X_HPH_R_TEST, 0x01, 0x01},
8518 {WCD934X_CPE_FLL_CONFIG_CTL_2, 0xFF, 0x20},
Xiaoyu Yeaeb64262017-05-08 16:25:38 -07008519 {WCD934X_MBHC_NEW_CTL_2, 0x0C, 0x00},
Banajit Goswamide8271c2017-01-18 00:28:59 -08008520};
8521
8522static const struct tavil_reg_mask_val tavil_codec_reg_init_1_1_val[] = {
8523 {WCD934X_CDC_COMPANDER1_CTL7, 0x1E, 0x06},
8524 {WCD934X_CDC_COMPANDER2_CTL7, 0x1E, 0x06},
8525 {WCD934X_HPH_NEW_INT_RDAC_HD2_CTL_L, 0xFF, 0x84},
8526 {WCD934X_HPH_NEW_INT_RDAC_HD2_CTL_R, 0xFF, 0x84},
8527 {WCD934X_CDC_RX3_RX_PATH_SEC0, 0xFC, 0xF4},
8528 {WCD934X_CDC_RX4_RX_PATH_SEC0, 0xFC, 0xF4},
8529};
8530
8531static const struct tavil_cpr_reg_defaults cpr_defaults[] = {
8532 { 0x00000820, 0x00000094 },
8533 { 0x00000fC0, 0x00000048 },
8534 { 0x0000f000, 0x00000044 },
8535 { 0x0000bb80, 0xC0000178 },
8536 { 0x00000000, 0x00000160 },
8537 { 0x10854522, 0x00000060 },
8538 { 0x10854509, 0x00000064 },
8539 { 0x108544dd, 0x00000068 },
8540 { 0x108544ad, 0x0000006C },
8541 { 0x0000077E, 0x00000070 },
8542 { 0x000007da, 0x00000074 },
8543 { 0x00000000, 0x00000078 },
8544 { 0x00000000, 0x0000007C },
8545 { 0x00042029, 0x00000080 },
8546 { 0x4002002A, 0x00000090 },
8547 { 0x4002002B, 0x00000090 },
8548};
8549
8550static const struct tavil_reg_mask_val tavil_codec_reg_init_common_val[] = {
8551 {WCD934X_CDC_CLSH_K2_MSB, 0x0F, 0x00},
8552 {WCD934X_CDC_CLSH_K2_LSB, 0xFF, 0x60},
8553 {WCD934X_CPE_SS_DMIC_CFG, 0x80, 0x00},
8554 {WCD934X_CDC_BOOST0_BOOST_CTL, 0x70, 0x50},
8555 {WCD934X_CDC_BOOST1_BOOST_CTL, 0x70, 0x50},
8556 {WCD934X_CDC_RX7_RX_PATH_CFG1, 0x08, 0x08},
8557 {WCD934X_CDC_RX8_RX_PATH_CFG1, 0x08, 0x08},
8558 {WCD934X_CDC_TOP_TOP_CFG1, 0x02, 0x02},
8559 {WCD934X_CDC_TOP_TOP_CFG1, 0x01, 0x01},
8560 {WCD934X_CDC_TX9_SPKR_PROT_PATH_CFG0, 0x01, 0x01},
8561 {WCD934X_CDC_TX10_SPKR_PROT_PATH_CFG0, 0x01, 0x01},
8562 {WCD934X_CDC_TX11_SPKR_PROT_PATH_CFG0, 0x01, 0x01},
8563 {WCD934X_CDC_TX12_SPKR_PROT_PATH_CFG0, 0x01, 0x01},
8564 {WCD934X_DATA_HUB_SB_TX11_INP_CFG, 0x01, 0x01},
8565 {WCD934X_CDC_CLK_RST_CTRL_FS_CNT_CONTROL, 0x01, 0x01},
8566 {WCD934X_CDC_COMPANDER7_CTL3, 0x80, 0x80},
8567 {WCD934X_CDC_COMPANDER8_CTL3, 0x80, 0x80},
8568 {WCD934X_CDC_COMPANDER7_CTL7, 0x01, 0x01},
8569 {WCD934X_CDC_COMPANDER8_CTL7, 0x01, 0x01},
8570 {WCD934X_CODEC_RPM_CLK_GATE, 0x08, 0x00},
8571 {WCD934X_TLMM_DMIC3_CLK_PINCFG, 0xFF, 0x0a},
8572 {WCD934X_TLMM_DMIC3_DATA_PINCFG, 0xFF, 0x0a},
8573 {WCD934X_CPE_SS_SVA_CFG, 0x60, 0x00},
8574};
8575
8576static void tavil_codec_init_reg(struct tavil_priv *priv)
8577{
8578 struct snd_soc_codec *codec = priv->codec;
8579 u32 i;
8580
8581 for (i = 0; i < ARRAY_SIZE(tavil_codec_reg_init_common_val); i++)
8582 snd_soc_update_bits(codec,
8583 tavil_codec_reg_init_common_val[i].reg,
8584 tavil_codec_reg_init_common_val[i].mask,
8585 tavil_codec_reg_init_common_val[i].val);
8586
8587 if (TAVIL_IS_1_1(priv->wcd9xxx)) {
8588 for (i = 0; i < ARRAY_SIZE(tavil_codec_reg_init_1_1_val); i++)
8589 snd_soc_update_bits(codec,
8590 tavil_codec_reg_init_1_1_val[i].reg,
8591 tavil_codec_reg_init_1_1_val[i].mask,
8592 tavil_codec_reg_init_1_1_val[i].val);
8593 }
8594}
8595
8596static void tavil_update_reg_defaults(struct tavil_priv *tavil)
8597{
8598 u32 i;
8599 struct wcd9xxx *wcd9xxx;
8600
8601 wcd9xxx = tavil->wcd9xxx;
8602 for (i = 0; i < ARRAY_SIZE(tavil_codec_reg_defaults); i++)
8603 regmap_update_bits(wcd9xxx->regmap,
8604 tavil_codec_reg_defaults[i].reg,
8605 tavil_codec_reg_defaults[i].mask,
8606 tavil_codec_reg_defaults[i].val);
8607}
8608
8609static void tavil_update_cpr_defaults(struct tavil_priv *tavil)
8610{
8611 int i;
8612 struct wcd9xxx *wcd9xxx;
8613
8614 wcd9xxx = tavil->wcd9xxx;
8615 if (!TAVIL_IS_1_1(wcd9xxx))
8616 return;
8617
8618 __tavil_cdc_mclk_enable(tavil, true);
8619
8620 regmap_write(wcd9xxx->regmap, WCD934X_CODEC_CPR_SVS2_MIN_CX_VDD, 0x2C);
8621 regmap_update_bits(wcd9xxx->regmap, WCD934X_CODEC_RPM_CLK_GATE,
8622 0x10, 0x00);
8623
8624 for (i = 0; i < ARRAY_SIZE(cpr_defaults); i++) {
8625 regmap_bulk_write(wcd9xxx->regmap,
8626 WCD934X_CODEC_CPR_WR_DATA_0,
8627 (u8 *)&cpr_defaults[i].wr_data, 4);
8628 regmap_bulk_write(wcd9xxx->regmap,
8629 WCD934X_CODEC_CPR_WR_ADDR_0,
8630 (u8 *)&cpr_defaults[i].wr_addr, 4);
8631 }
8632
8633 __tavil_cdc_mclk_enable(tavil, false);
8634}
8635
8636static void tavil_slim_interface_init_reg(struct snd_soc_codec *codec)
8637{
8638 int i;
8639 struct tavil_priv *priv = snd_soc_codec_get_drvdata(codec);
8640
8641 for (i = 0; i < WCD9XXX_SLIM_NUM_PORT_REG; i++)
8642 wcd9xxx_interface_reg_write(priv->wcd9xxx,
8643 WCD934X_SLIM_PGD_PORT_INT_RX_EN0 + i,
8644 0xFF);
8645}
8646
8647static irqreturn_t tavil_misc_irq(int irq, void *data)
8648{
8649 struct tavil_priv *tavil = data;
8650 int misc_val;
8651
8652 /* Find source of interrupt */
8653 regmap_read(tavil->wcd9xxx->regmap, WCD934X_INTR_CODEC_MISC_STATUS,
8654 &misc_val);
8655
8656 if (misc_val & 0x08) {
8657 dev_info(tavil->dev, "%s: irq: %d, DSD DC detected!\n",
8658 __func__, irq);
8659 /* DSD DC interrupt, reset DSD path */
8660 tavil_dsd_reset(tavil->dsd_config);
8661 } else {
8662 dev_err(tavil->dev, "%s: Codec misc irq: %d, val: 0x%x\n",
8663 __func__, irq, misc_val);
8664 }
8665
8666 /* Clear interrupt status */
8667 regmap_update_bits(tavil->wcd9xxx->regmap,
8668 WCD934X_INTR_CODEC_MISC_CLEAR, misc_val, 0x00);
8669
8670 return IRQ_HANDLED;
8671}
8672
8673static irqreturn_t tavil_slimbus_irq(int irq, void *data)
8674{
8675 struct tavil_priv *tavil = data;
8676 unsigned long status = 0;
8677 int i, j, port_id, k;
8678 u32 bit;
8679 u8 val, int_val = 0;
8680 bool tx, cleared;
8681 unsigned short reg = 0;
8682
8683 for (i = WCD934X_SLIM_PGD_PORT_INT_STATUS_RX_0, j = 0;
8684 i <= WCD934X_SLIM_PGD_PORT_INT_STATUS_TX_1; i++, j++) {
8685 val = wcd9xxx_interface_reg_read(tavil->wcd9xxx, i);
8686 status |= ((u32)val << (8 * j));
8687 }
8688
8689 for_each_set_bit(j, &status, 32) {
8690 tx = (j >= 16 ? true : false);
8691 port_id = (tx ? j - 16 : j);
8692 val = wcd9xxx_interface_reg_read(tavil->wcd9xxx,
8693 WCD934X_SLIM_PGD_PORT_INT_RX_SOURCE0 + j);
8694 if (val) {
8695 if (!tx)
8696 reg = WCD934X_SLIM_PGD_PORT_INT_RX_EN0 +
8697 (port_id / 8);
8698 else
8699 reg = WCD934X_SLIM_PGD_PORT_INT_TX_EN0 +
8700 (port_id / 8);
8701 int_val = wcd9xxx_interface_reg_read(
8702 tavil->wcd9xxx, reg);
8703 /*
8704 * Ignore interrupts for ports for which the
8705 * interrupts are not specifically enabled.
8706 */
8707 if (!(int_val & (1 << (port_id % 8))))
8708 continue;
8709 }
8710 if (val & WCD934X_SLIM_IRQ_OVERFLOW)
8711 dev_err_ratelimited(tavil->dev, "%s: overflow error on %s port %d, value %x\n",
8712 __func__, (tx ? "TX" : "RX"), port_id, val);
8713 if (val & WCD934X_SLIM_IRQ_UNDERFLOW)
8714 dev_err_ratelimited(tavil->dev, "%s: underflow error on %s port %d, value %x\n",
8715 __func__, (tx ? "TX" : "RX"), port_id, val);
8716 if ((val & WCD934X_SLIM_IRQ_OVERFLOW) ||
8717 (val & WCD934X_SLIM_IRQ_UNDERFLOW)) {
8718 if (!tx)
8719 reg = WCD934X_SLIM_PGD_PORT_INT_RX_EN0 +
8720 (port_id / 8);
8721 else
8722 reg = WCD934X_SLIM_PGD_PORT_INT_TX_EN0 +
8723 (port_id / 8);
8724 int_val = wcd9xxx_interface_reg_read(
8725 tavil->wcd9xxx, reg);
8726 if (int_val & (1 << (port_id % 8))) {
8727 int_val = int_val ^ (1 << (port_id % 8));
8728 wcd9xxx_interface_reg_write(tavil->wcd9xxx,
8729 reg, int_val);
8730 }
8731 }
8732 if (val & WCD934X_SLIM_IRQ_PORT_CLOSED) {
8733 /*
8734 * INT SOURCE register starts from RX to TX
8735 * but port number in the ch_mask is in opposite way
8736 */
8737 bit = (tx ? j - 16 : j + 16);
8738 dev_dbg(tavil->dev, "%s: %s port %d closed value %x, bit %u\n",
8739 __func__, (tx ? "TX" : "RX"), port_id, val,
8740 bit);
8741 for (k = 0, cleared = false; k < NUM_CODEC_DAIS; k++) {
8742 dev_dbg(tavil->dev, "%s: tavil->dai[%d].ch_mask = 0x%lx\n",
8743 __func__, k, tavil->dai[k].ch_mask);
8744 if (test_and_clear_bit(bit,
8745 &tavil->dai[k].ch_mask)) {
8746 cleared = true;
8747 if (!tavil->dai[k].ch_mask)
8748 wake_up(
8749 &tavil->dai[k].dai_wait);
8750 /*
8751 * There are cases when multiple DAIs
8752 * might be using the same slimbus
8753 * channel. Hence don't break here.
8754 */
8755 }
8756 }
8757 WARN(!cleared,
8758 "Couldn't find slimbus %s port %d for closing\n",
8759 (tx ? "TX" : "RX"), port_id);
8760 }
8761 wcd9xxx_interface_reg_write(tavil->wcd9xxx,
8762 WCD934X_SLIM_PGD_PORT_INT_CLR_RX_0 +
8763 (j / 8),
8764 1 << (j % 8));
8765 }
8766
8767 return IRQ_HANDLED;
8768}
8769
8770static int tavil_setup_irqs(struct tavil_priv *tavil)
8771{
8772 int ret = 0;
8773 struct snd_soc_codec *codec = tavil->codec;
8774 struct wcd9xxx *wcd9xxx = tavil->wcd9xxx;
8775 struct wcd9xxx_core_resource *core_res =
8776 &wcd9xxx->core_res;
8777
8778 ret = wcd9xxx_request_irq(core_res, WCD9XXX_IRQ_SLIMBUS,
8779 tavil_slimbus_irq, "SLIMBUS Slave", tavil);
8780 if (ret)
8781 dev_err(codec->dev, "%s: Failed to request irq %d\n", __func__,
8782 WCD9XXX_IRQ_SLIMBUS);
8783 else
8784 tavil_slim_interface_init_reg(codec);
8785
8786 /* Register for misc interrupts as well */
8787 ret = wcd9xxx_request_irq(core_res, WCD934X_IRQ_MISC,
8788 tavil_misc_irq, "CDC MISC Irq", tavil);
8789 if (ret)
8790 dev_err(codec->dev, "%s: Failed to request cdc misc irq\n",
8791 __func__);
8792
8793 return ret;
8794}
8795
8796static void tavil_init_slim_slave_cfg(struct snd_soc_codec *codec)
8797{
8798 struct tavil_priv *priv = snd_soc_codec_get_drvdata(codec);
8799 struct afe_param_cdc_slimbus_slave_cfg *cfg;
8800 struct wcd9xxx *wcd9xxx = priv->wcd9xxx;
8801 uint64_t eaddr = 0;
8802
8803 cfg = &priv->slimbus_slave_cfg;
8804 cfg->minor_version = 1;
8805 cfg->tx_slave_port_offset = 0;
8806 cfg->rx_slave_port_offset = 16;
8807
8808 memcpy(&eaddr, &wcd9xxx->slim->e_addr, sizeof(wcd9xxx->slim->e_addr));
8809 WARN_ON(sizeof(wcd9xxx->slim->e_addr) != 6);
8810 cfg->device_enum_addr_lsw = eaddr & 0xFFFFFFFF;
8811 cfg->device_enum_addr_msw = eaddr >> 32;
8812
8813 dev_dbg(codec->dev, "%s: slimbus logical address 0x%llx\n",
8814 __func__, eaddr);
8815}
8816
8817static void tavil_cleanup_irqs(struct tavil_priv *tavil)
8818{
8819 struct wcd9xxx *wcd9xxx = tavil->wcd9xxx;
8820 struct wcd9xxx_core_resource *core_res =
8821 &wcd9xxx->core_res;
8822
8823 wcd9xxx_free_irq(core_res, WCD9XXX_IRQ_SLIMBUS, tavil);
8824 wcd9xxx_free_irq(core_res, WCD934X_IRQ_MISC, tavil);
8825}
8826
8827/*
8828 * wcd934x_get_micb_vout_ctl_val: converts micbias from volts to register value
8829 * @micb_mv: micbias in mv
8830 *
8831 * return register value converted
8832 */
8833int wcd934x_get_micb_vout_ctl_val(u32 micb_mv)
8834{
8835 /* min micbias voltage is 1V and maximum is 2.85V */
8836 if (micb_mv < 1000 || micb_mv > 2850) {
8837 pr_err("%s: unsupported micbias voltage\n", __func__);
8838 return -EINVAL;
8839 }
8840
8841 return (micb_mv - 1000) / 50;
8842}
8843EXPORT_SYMBOL(wcd934x_get_micb_vout_ctl_val);
8844
8845static int tavil_handle_pdata(struct tavil_priv *tavil,
8846 struct wcd9xxx_pdata *pdata)
8847{
8848 struct snd_soc_codec *codec = tavil->codec;
8849 u8 mad_dmic_ctl_val;
8850 u8 anc_ctl_value;
8851 u32 def_dmic_rate, dmic_clk_drv;
8852 int vout_ctl_1, vout_ctl_2, vout_ctl_3, vout_ctl_4;
8853 int rc = 0;
8854
8855 if (!pdata) {
8856 dev_err(codec->dev, "%s: NULL pdata\n", __func__);
8857 return -ENODEV;
8858 }
8859
8860 /* set micbias voltage */
8861 vout_ctl_1 = wcd934x_get_micb_vout_ctl_val(pdata->micbias.micb1_mv);
8862 vout_ctl_2 = wcd934x_get_micb_vout_ctl_val(pdata->micbias.micb2_mv);
8863 vout_ctl_3 = wcd934x_get_micb_vout_ctl_val(pdata->micbias.micb3_mv);
8864 vout_ctl_4 = wcd934x_get_micb_vout_ctl_val(pdata->micbias.micb4_mv);
Xiaoyu Ye1a2d8bd92017-01-31 18:54:15 -08008865 if (vout_ctl_1 < 0 || vout_ctl_2 < 0 ||
8866 vout_ctl_3 < 0 || vout_ctl_4 < 0) {
Banajit Goswamide8271c2017-01-18 00:28:59 -08008867 rc = -EINVAL;
8868 goto done;
8869 }
8870 snd_soc_update_bits(codec, WCD934X_ANA_MICB1, 0x3F, vout_ctl_1);
8871 snd_soc_update_bits(codec, WCD934X_ANA_MICB2, 0x3F, vout_ctl_2);
8872 snd_soc_update_bits(codec, WCD934X_ANA_MICB3, 0x3F, vout_ctl_3);
8873 snd_soc_update_bits(codec, WCD934X_ANA_MICB4, 0x3F, vout_ctl_4);
8874
8875 /* Set the DMIC sample rate */
8876 switch (pdata->mclk_rate) {
8877 case WCD934X_MCLK_CLK_9P6MHZ:
8878 def_dmic_rate = WCD9XXX_DMIC_SAMPLE_RATE_4P8MHZ;
8879 break;
8880 case WCD934X_MCLK_CLK_12P288MHZ:
8881 def_dmic_rate = WCD9XXX_DMIC_SAMPLE_RATE_4P096MHZ;
8882 break;
8883 default:
8884 /* should never happen */
8885 dev_err(codec->dev, "%s: Invalid mclk_rate %d\n",
8886 __func__, pdata->mclk_rate);
8887 rc = -EINVAL;
8888 goto done;
8889 };
8890
8891 if (pdata->dmic_sample_rate ==
8892 WCD9XXX_DMIC_SAMPLE_RATE_UNDEFINED) {
8893 dev_info(codec->dev, "%s: dmic_rate invalid default = %d\n",
8894 __func__, def_dmic_rate);
8895 pdata->dmic_sample_rate = def_dmic_rate;
8896 }
8897 if (pdata->mad_dmic_sample_rate ==
8898 WCD9XXX_DMIC_SAMPLE_RATE_UNDEFINED) {
8899 dev_info(codec->dev, "%s: mad_dmic_rate invalid default = %d\n",
8900 __func__, def_dmic_rate);
8901 /*
8902 * use dmic_sample_rate as the default for MAD
8903 * if mad dmic sample rate is undefined
8904 */
8905 pdata->mad_dmic_sample_rate = pdata->dmic_sample_rate;
8906 }
8907
8908 if (pdata->dmic_clk_drv ==
8909 WCD9XXX_DMIC_CLK_DRIVE_UNDEFINED) {
8910 pdata->dmic_clk_drv = WCD934X_DMIC_CLK_DRIVE_DEFAULT;
Karthikeyan Mani3570e6c2016-11-14 11:05:53 -08008911 dev_dbg(codec->dev,
Banajit Goswamide8271c2017-01-18 00:28:59 -08008912 "%s: dmic_clk_strength invalid, default = %d\n",
8913 __func__, pdata->dmic_clk_drv);
8914 }
8915
8916 switch (pdata->dmic_clk_drv) {
8917 case 2:
8918 dmic_clk_drv = 0;
8919 break;
8920 case 4:
8921 dmic_clk_drv = 1;
8922 break;
8923 case 8:
8924 dmic_clk_drv = 2;
8925 break;
8926 case 16:
8927 dmic_clk_drv = 3;
8928 break;
8929 default:
8930 dev_err(codec->dev,
8931 "%s: invalid dmic_clk_drv %d, using default\n",
8932 __func__, pdata->dmic_clk_drv);
8933 dmic_clk_drv = 0;
8934 break;
8935 }
8936
8937 snd_soc_update_bits(codec, WCD934X_TEST_DEBUG_PAD_DRVCTL_0,
8938 0x0C, dmic_clk_drv << 2);
8939
8940 /*
8941 * Default the DMIC clk rates to mad_dmic_sample_rate,
8942 * whereas, the anc/txfe dmic rates to dmic_sample_rate
8943 * since the anc/txfe are independent of mad block.
8944 */
8945 mad_dmic_ctl_val = tavil_get_dmic_clk_val(tavil->codec,
8946 pdata->mclk_rate,
8947 pdata->mad_dmic_sample_rate);
8948 snd_soc_update_bits(codec, WCD934X_CPE_SS_DMIC0_CTL,
8949 0x0E, mad_dmic_ctl_val << 1);
8950 snd_soc_update_bits(codec, WCD934X_CPE_SS_DMIC1_CTL,
8951 0x0E, mad_dmic_ctl_val << 1);
8952 snd_soc_update_bits(codec, WCD934X_CPE_SS_DMIC2_CTL,
8953 0x0E, mad_dmic_ctl_val << 1);
8954
8955 if (dmic_clk_drv == WCD934X_DMIC_CLK_DIV_2)
8956 anc_ctl_value = WCD934X_ANC_DMIC_X2_FULL_RATE;
8957 else
8958 anc_ctl_value = WCD934X_ANC_DMIC_X2_HALF_RATE;
8959
8960 snd_soc_update_bits(codec, WCD934X_CDC_ANC0_MODE_2_CTL,
8961 0x40, anc_ctl_value << 6);
8962 snd_soc_update_bits(codec, WCD934X_CDC_ANC0_MODE_2_CTL,
8963 0x20, anc_ctl_value << 5);
8964 snd_soc_update_bits(codec, WCD934X_CDC_ANC1_MODE_2_CTL,
8965 0x40, anc_ctl_value << 6);
8966 snd_soc_update_bits(codec, WCD934X_CDC_ANC1_MODE_2_CTL,
8967 0x20, anc_ctl_value << 5);
8968
8969done:
8970 return rc;
8971}
8972
8973static void tavil_cdc_vote_svs(struct snd_soc_codec *codec, bool vote)
8974{
8975 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
8976
8977 return tavil_vote_svs(tavil, vote);
8978}
8979
8980struct wcd_dsp_cdc_cb cdc_cb = {
8981 .cdc_clk_en = tavil_codec_internal_rco_ctrl,
8982 .cdc_vote_svs = tavil_cdc_vote_svs,
8983};
8984
8985static int tavil_wdsp_initialize(struct snd_soc_codec *codec)
8986{
8987 struct wcd9xxx *control;
8988 struct tavil_priv *tavil;
8989 struct wcd_dsp_params params;
8990 int ret = 0;
8991
8992 control = dev_get_drvdata(codec->dev->parent);
8993 tavil = snd_soc_codec_get_drvdata(codec);
8994
8995 params.cb = &cdc_cb;
8996 params.irqs.cpe_ipc1_irq = WCD934X_IRQ_CPE1_INTR;
8997 params.irqs.cpe_err_irq = WCD934X_IRQ_CPE_ERROR;
8998 params.irqs.fatal_irqs = CPE_FATAL_IRQS;
8999 params.clk_rate = control->mclk_rate;
9000 params.dsp_instance = 0;
9001
9002 wcd_dsp_cntl_init(codec, &params, &tavil->wdsp_cntl);
9003 if (!tavil->wdsp_cntl) {
9004 dev_err(tavil->dev, "%s: wcd-dsp-control init failed\n",
9005 __func__);
9006 ret = -EINVAL;
9007 }
9008
9009 return ret;
9010}
9011
9012/*
9013 * tavil_soc_get_mbhc: get wcd934x_mbhc handle of corresponding codec
9014 * @codec: handle to snd_soc_codec *
9015 *
9016 * return wcd934x_mbhc handle or error code in case of failure
9017 */
9018struct wcd934x_mbhc *tavil_soc_get_mbhc(struct snd_soc_codec *codec)
9019{
9020 struct tavil_priv *tavil;
9021
9022 if (!codec) {
9023 pr_err("%s: Invalid params, NULL codec\n", __func__);
9024 return NULL;
9025 }
9026 tavil = snd_soc_codec_get_drvdata(codec);
9027
9028 if (!tavil) {
9029 pr_err("%s: Invalid params, NULL tavil\n", __func__);
9030 return NULL;
9031 }
9032
9033 return tavil->mbhc;
9034}
9035EXPORT_SYMBOL(tavil_soc_get_mbhc);
9036
9037static void tavil_mclk2_reg_defaults(struct tavil_priv *tavil)
9038{
9039 int i;
9040 struct snd_soc_codec *codec = tavil->codec;
9041
9042 if (TAVIL_IS_1_0(tavil->wcd9xxx)) {
9043 /* MCLK2 configuration */
9044 for (i = 0; i < ARRAY_SIZE(tavil_codec_mclk2_1_0_defaults); i++)
9045 snd_soc_update_bits(codec,
9046 tavil_codec_mclk2_1_0_defaults[i].reg,
9047 tavil_codec_mclk2_1_0_defaults[i].mask,
9048 tavil_codec_mclk2_1_0_defaults[i].val);
9049 }
9050 if (TAVIL_IS_1_1(tavil->wcd9xxx)) {
9051 /* MCLK2 configuration */
9052 for (i = 0; i < ARRAY_SIZE(tavil_codec_mclk2_1_1_defaults); i++)
9053 snd_soc_update_bits(codec,
9054 tavil_codec_mclk2_1_1_defaults[i].reg,
9055 tavil_codec_mclk2_1_1_defaults[i].mask,
9056 tavil_codec_mclk2_1_1_defaults[i].val);
9057 }
9058}
9059
9060static int tavil_device_down(struct wcd9xxx *wcd9xxx)
9061{
9062 struct snd_soc_codec *codec;
9063 struct tavil_priv *priv;
9064 int count;
9065
9066 codec = (struct snd_soc_codec *)(wcd9xxx->ssr_priv);
9067 priv = snd_soc_codec_get_drvdata(codec);
9068 swrm_wcd_notify(priv->swr.ctrl_data[0].swr_pdev,
9069 SWR_DEVICE_DOWN, NULL);
9070 tavil_dsd_reset(priv->dsd_config);
9071 snd_soc_card_change_online_state(codec->component.card, 0);
9072 for (count = 0; count < NUM_CODEC_DAIS; count++)
9073 priv->dai[count].bus_down_in_recovery = true;
9074 wcd_dsp_ssr_event(priv->wdsp_cntl, WCD_CDC_DOWN_EVENT);
9075 wcd_resmgr_set_sido_input_src_locked(priv->resmgr,
9076 SIDO_SOURCE_INTERNAL);
9077
9078 return 0;
9079}
9080
9081static int tavil_post_reset_cb(struct wcd9xxx *wcd9xxx)
9082{
9083 int i, ret = 0;
9084 struct wcd9xxx *control;
9085 struct snd_soc_codec *codec;
9086 struct tavil_priv *tavil;
9087 struct wcd9xxx_pdata *pdata;
9088 struct wcd_mbhc *mbhc;
9089
9090 codec = (struct snd_soc_codec *)(wcd9xxx->ssr_priv);
9091 tavil = snd_soc_codec_get_drvdata(codec);
9092 control = dev_get_drvdata(codec->dev->parent);
9093
9094 wcd9xxx_set_power_state(tavil->wcd9xxx,
9095 WCD_REGION_POWER_COLLAPSE_REMOVE,
9096 WCD9XXX_DIG_CORE_REGION_1);
9097
9098 mutex_lock(&tavil->codec_mutex);
Banajit Goswamide8271c2017-01-18 00:28:59 -08009099
Vidyakumar Athotaae60b992017-01-04 11:21:48 -08009100 tavil_vote_svs(tavil, true);
Banajit Goswamide8271c2017-01-18 00:28:59 -08009101 tavil_slimbus_slave_port_cfg.slave_dev_intfdev_la =
9102 control->slim_slave->laddr;
9103 tavil_slimbus_slave_port_cfg.slave_dev_pgd_la =
9104 control->slim->laddr;
9105 tavil_init_slim_slave_cfg(codec);
9106 snd_soc_card_change_online_state(codec->component.card, 1);
9107
Banajit Goswamide8271c2017-01-18 00:28:59 -08009108 for (i = 0; i < TAVIL_MAX_MICBIAS; i++)
9109 tavil->micb_ref[i] = 0;
9110
Banajit Goswamide8271c2017-01-18 00:28:59 -08009111 dev_dbg(codec->dev, "%s: MCLK Rate = %x\n",
9112 __func__, control->mclk_rate);
9113
9114 if (control->mclk_rate == WCD934X_MCLK_CLK_12P288MHZ)
9115 snd_soc_update_bits(codec, WCD934X_CODEC_RPM_CLK_MCLK_CFG,
9116 0x03, 0x00);
9117 else if (control->mclk_rate == WCD934X_MCLK_CLK_9P6MHZ)
9118 snd_soc_update_bits(codec, WCD934X_CODEC_RPM_CLK_MCLK_CFG,
9119 0x03, 0x01);
9120 wcd_resmgr_post_ssr_v2(tavil->resmgr);
9121 tavil_update_reg_defaults(tavil);
9122 tavil_codec_init_reg(tavil);
9123 __tavil_enable_efuse_sensing(tavil);
9124 tavil_mclk2_reg_defaults(tavil);
9125
9126 __tavil_cdc_mclk_enable(tavil, true);
9127 regcache_mark_dirty(codec->component.regmap);
9128 regcache_sync(codec->component.regmap);
9129 __tavil_cdc_mclk_enable(tavil, false);
9130
9131 tavil_update_cpr_defaults(tavil);
9132
9133 pdata = dev_get_platdata(codec->dev->parent);
9134 ret = tavil_handle_pdata(tavil, pdata);
Xiaoyu Ye1a2d8bd92017-01-31 18:54:15 -08009135 if (ret < 0)
Banajit Goswamide8271c2017-01-18 00:28:59 -08009136 dev_err(codec->dev, "%s: invalid pdata\n", __func__);
9137
9138 /* Initialize MBHC module */
9139 mbhc = &tavil->mbhc->wcd_mbhc;
9140 ret = tavil_mbhc_post_ssr_init(tavil->mbhc, codec);
9141 if (ret) {
9142 dev_err(codec->dev, "%s: mbhc initialization failed\n",
9143 __func__);
9144 goto done;
9145 } else {
9146 tavil_mbhc_hs_detect(codec, mbhc->mbhc_cfg);
9147 }
9148
9149 /* DSD initialization */
9150 ret = tavil_dsd_post_ssr_init(tavil->dsd_config);
9151 if (ret)
9152 dev_dbg(tavil->dev, "%s: DSD init failed\n", __func__);
9153
9154 tavil_cleanup_irqs(tavil);
9155 ret = tavil_setup_irqs(tavil);
9156 if (ret) {
9157 dev_err(codec->dev, "%s: tavil irq setup failed %d\n",
9158 __func__, ret);
9159 goto done;
9160 }
9161
9162 tavil_set_spkr_mode(codec, tavil->swr.spkr_mode);
9163 /*
9164 * Once the codec initialization is completed, the svs vote
9165 * can be released allowing the codec to go to SVS2.
9166 */
9167 tavil_vote_svs(tavil, false);
9168 wcd_dsp_ssr_event(tavil->wdsp_cntl, WCD_CDC_UP_EVENT);
9169
9170done:
9171 mutex_unlock(&tavil->codec_mutex);
9172 return ret;
9173}
9174
Banajit Goswami2be7b482017-02-03 23:32:37 -08009175static int tavil_soc_codec_probe(struct snd_soc_codec *codec)
Banajit Goswamide8271c2017-01-18 00:28:59 -08009176{
9177 struct wcd9xxx *control;
9178 struct tavil_priv *tavil;
9179 struct wcd9xxx_pdata *pdata;
9180 struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
9181 int i, ret;
9182 void *ptr = NULL;
9183
9184 control = dev_get_drvdata(codec->dev->parent);
9185
9186 dev_info(codec->dev, "%s()\n", __func__);
9187 tavil = snd_soc_codec_get_drvdata(codec);
9188 tavil->intf_type = wcd9xxx_get_intf_type();
9189
9190 control->dev_down = tavil_device_down;
9191 control->post_reset = tavil_post_reset_cb;
9192 control->ssr_priv = (void *)codec;
9193
9194 /* Resource Manager post Init */
9195 ret = wcd_resmgr_post_init(tavil->resmgr, &tavil_resmgr_cb, codec);
9196 if (ret) {
9197 dev_err(codec->dev, "%s: wcd resmgr post init failed\n",
9198 __func__);
9199 goto err;
9200 }
9201 /* Class-H Init */
9202 wcd_clsh_init(&tavil->clsh_d);
9203 /* Default HPH Mode to Class-H Low HiFi */
9204 tavil->hph_mode = CLS_H_LOHIFI;
9205
9206 tavil->fw_data = devm_kzalloc(codec->dev, sizeof(*(tavil->fw_data)),
9207 GFP_KERNEL);
9208 if (!tavil->fw_data)
9209 goto err;
9210
9211 set_bit(WCD9XXX_ANC_CAL, tavil->fw_data->cal_bit);
9212 set_bit(WCD9XXX_MBHC_CAL, tavil->fw_data->cal_bit);
9213 set_bit(WCD9XXX_MAD_CAL, tavil->fw_data->cal_bit);
9214 set_bit(WCD9XXX_VBAT_CAL, tavil->fw_data->cal_bit);
9215
9216 ret = wcd_cal_create_hwdep(tavil->fw_data,
9217 WCD9XXX_CODEC_HWDEP_NODE, codec);
Xiaoyu Ye1a2d8bd92017-01-31 18:54:15 -08009218 if (ret < 0) {
Banajit Goswamide8271c2017-01-18 00:28:59 -08009219 dev_err(codec->dev, "%s hwdep failed %d\n", __func__, ret);
9220 goto err_hwdep;
9221 }
9222
9223 /* Initialize MBHC module */
9224 ret = tavil_mbhc_init(&tavil->mbhc, codec, tavil->fw_data);
9225 if (ret) {
9226 pr_err("%s: mbhc initialization failed\n", __func__);
9227 goto err_hwdep;
9228 }
9229
9230 tavil->codec = codec;
9231 for (i = 0; i < COMPANDER_MAX; i++)
9232 tavil->comp_enabled[i] = 0;
9233
9234 tavil_codec_init_reg(tavil);
9235
9236 pdata = dev_get_platdata(codec->dev->parent);
9237 ret = tavil_handle_pdata(tavil, pdata);
Xiaoyu Ye1a2d8bd92017-01-31 18:54:15 -08009238 if (ret < 0) {
Banajit Goswamide8271c2017-01-18 00:28:59 -08009239 dev_err(codec->dev, "%s: bad pdata\n", __func__);
9240 goto err_hwdep;
9241 }
9242
9243 ptr = devm_kzalloc(codec->dev, (sizeof(tavil_rx_chs) +
9244 sizeof(tavil_tx_chs)), GFP_KERNEL);
9245 if (!ptr) {
9246 ret = -ENOMEM;
9247 goto err_hwdep;
9248 }
9249
9250 snd_soc_dapm_add_routes(dapm, tavil_slim_audio_map,
9251 ARRAY_SIZE(tavil_slim_audio_map));
9252 for (i = 0; i < NUM_CODEC_DAIS; i++) {
9253 INIT_LIST_HEAD(&tavil->dai[i].wcd9xxx_ch_list);
9254 init_waitqueue_head(&tavil->dai[i].dai_wait);
9255 }
9256 tavil_slimbus_slave_port_cfg.slave_dev_intfdev_la =
9257 control->slim_slave->laddr;
9258 tavil_slimbus_slave_port_cfg.slave_dev_pgd_la =
9259 control->slim->laddr;
9260 tavil_slimbus_slave_port_cfg.slave_port_mapping[0] =
9261 WCD934X_TX13;
9262 tavil_init_slim_slave_cfg(codec);
9263
9264 control->num_rx_port = WCD934X_RX_MAX;
9265 control->rx_chs = ptr;
9266 memcpy(control->rx_chs, tavil_rx_chs, sizeof(tavil_rx_chs));
9267 control->num_tx_port = WCD934X_TX_MAX;
9268 control->tx_chs = ptr + sizeof(tavil_rx_chs);
9269 memcpy(control->tx_chs, tavil_tx_chs, sizeof(tavil_tx_chs));
9270
9271 ret = tavil_setup_irqs(tavil);
9272 if (ret) {
9273 dev_err(tavil->dev, "%s: tavil irq setup failed %d\n",
9274 __func__, ret);
9275 goto err_pdata;
9276 }
9277
9278 for (i = 0; i < WCD934X_NUM_DECIMATORS; i++) {
9279 tavil->tx_hpf_work[i].tavil = tavil;
9280 tavil->tx_hpf_work[i].decimator = i;
9281 INIT_DELAYED_WORK(&tavil->tx_hpf_work[i].dwork,
9282 tavil_tx_hpf_corner_freq_callback);
9283
9284 tavil->tx_mute_dwork[i].tavil = tavil;
9285 tavil->tx_mute_dwork[i].decimator = i;
9286 INIT_DELAYED_WORK(&tavil->tx_mute_dwork[i].dwork,
9287 tavil_tx_mute_update_callback);
9288 }
9289
9290 tavil->spk_anc_dwork.tavil = tavil;
9291 INIT_DELAYED_WORK(&tavil->spk_anc_dwork.dwork,
9292 tavil_spk_anc_update_callback);
9293
9294 tavil_mclk2_reg_defaults(tavil);
9295
9296 /* DSD initialization */
9297 tavil->dsd_config = tavil_dsd_init(codec);
9298 if (IS_ERR_OR_NULL(tavil->dsd_config))
9299 dev_dbg(tavil->dev, "%s: DSD init failed\n", __func__);
9300
9301 mutex_lock(&tavil->codec_mutex);
9302 snd_soc_dapm_disable_pin(dapm, "ANC EAR PA");
9303 snd_soc_dapm_disable_pin(dapm, "ANC EAR");
Meng Wangf45a20d2017-01-18 09:51:58 +08009304 snd_soc_dapm_disable_pin(dapm, "ANC HPHL PA");
9305 snd_soc_dapm_disable_pin(dapm, "ANC HPHR PA");
9306 snd_soc_dapm_disable_pin(dapm, "ANC HPHL");
9307 snd_soc_dapm_disable_pin(dapm, "ANC HPHR");
Banajit Goswamide8271c2017-01-18 00:28:59 -08009308 snd_soc_dapm_enable_pin(dapm, "ANC SPK1 PA");
9309 mutex_unlock(&tavil->codec_mutex);
9310
9311 snd_soc_dapm_ignore_suspend(dapm, "AIF1 Playback");
9312 snd_soc_dapm_ignore_suspend(dapm, "AIF1 Capture");
9313 snd_soc_dapm_ignore_suspend(dapm, "AIF2 Playback");
9314 snd_soc_dapm_ignore_suspend(dapm, "AIF2 Capture");
9315 snd_soc_dapm_ignore_suspend(dapm, "AIF3 Playback");
9316 snd_soc_dapm_ignore_suspend(dapm, "AIF3 Capture");
9317 snd_soc_dapm_ignore_suspend(dapm, "AIF4 Playback");
Walter Yangb893afb2017-02-28 14:59:15 +08009318 snd_soc_dapm_ignore_suspend(dapm, "AIF4 MAD TX");
Banajit Goswamide8271c2017-01-18 00:28:59 -08009319 snd_soc_dapm_ignore_suspend(dapm, "VIfeed");
9320
9321 snd_soc_dapm_sync(dapm);
9322
9323 tavil_wdsp_initialize(codec);
9324
9325 /*
9326 * Once the codec initialization is completed, the svs vote
9327 * can be released allowing the codec to go to SVS2.
9328 */
9329 tavil_vote_svs(tavil, false);
9330
9331 return ret;
9332
9333err_pdata:
9334 devm_kfree(codec->dev, ptr);
9335 control->rx_chs = NULL;
9336 control->tx_chs = NULL;
9337err_hwdep:
9338 devm_kfree(codec->dev, tavil->fw_data);
9339 tavil->fw_data = NULL;
9340err:
9341 return ret;
9342}
9343
Banajit Goswami2be7b482017-02-03 23:32:37 -08009344static int tavil_soc_codec_remove(struct snd_soc_codec *codec)
Banajit Goswamide8271c2017-01-18 00:28:59 -08009345{
9346 struct wcd9xxx *control;
9347 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
9348
9349 control = dev_get_drvdata(codec->dev->parent);
9350 devm_kfree(codec->dev, control->rx_chs);
9351 control->rx_chs = NULL;
9352 control->tx_chs = NULL;
9353 tavil_cleanup_irqs(tavil);
9354
9355 if (tavil->wdsp_cntl)
9356 wcd_dsp_cntl_deinit(&tavil->wdsp_cntl);
9357
9358 /* Deinitialize MBHC module */
9359 tavil_mbhc_deinit(codec);
9360 tavil->mbhc = NULL;
Banajit Goswamie0b20e12017-02-05 18:11:11 -08009361
9362 return 0;
Banajit Goswamide8271c2017-01-18 00:28:59 -08009363}
9364
9365static struct regmap *tavil_get_regmap(struct device *dev)
9366{
9367 struct wcd9xxx *control = dev_get_drvdata(dev->parent);
9368
9369 return control->regmap;
9370}
9371
9372static struct snd_soc_codec_driver soc_codec_dev_tavil = {
Banajit Goswami2be7b482017-02-03 23:32:37 -08009373 .probe = tavil_soc_codec_probe,
9374 .remove = tavil_soc_codec_remove,
Banajit Goswamide8271c2017-01-18 00:28:59 -08009375 .get_regmap = tavil_get_regmap,
Banajit Goswami8e306f02016-12-15 20:49:07 -08009376 .component_driver = {
Banajit Goswamiaf472112017-01-29 22:15:11 -08009377 .controls = tavil_snd_controls,
9378 .num_controls = ARRAY_SIZE(tavil_snd_controls),
Banajit Goswami8e306f02016-12-15 20:49:07 -08009379 .dapm_widgets = tavil_dapm_widgets,
9380 .num_dapm_widgets = ARRAY_SIZE(tavil_dapm_widgets),
9381 .dapm_routes = tavil_audio_map,
9382 .num_dapm_routes = ARRAY_SIZE(tavil_audio_map),
9383 },
Banajit Goswamide8271c2017-01-18 00:28:59 -08009384};
9385
9386#ifdef CONFIG_PM
9387static int tavil_suspend(struct device *dev)
9388{
9389 struct platform_device *pdev = to_platform_device(dev);
9390 struct tavil_priv *tavil = platform_get_drvdata(pdev);
9391
9392 if (!tavil) {
9393 dev_err(dev, "%s: tavil private data is NULL\n", __func__);
9394 return -EINVAL;
9395 }
9396 dev_dbg(dev, "%s: system suspend\n", __func__);
9397 if (delayed_work_pending(&tavil->power_gate_work) &&
9398 cancel_delayed_work_sync(&tavil->power_gate_work))
9399 tavil_codec_power_gate_digital_core(tavil);
9400 return 0;
9401}
9402
9403static int tavil_resume(struct device *dev)
9404{
9405 struct platform_device *pdev = to_platform_device(dev);
9406 struct tavil_priv *tavil = platform_get_drvdata(pdev);
9407
9408 if (!tavil) {
9409 dev_err(dev, "%s: tavil private data is NULL\n", __func__);
9410 return -EINVAL;
9411 }
9412 dev_dbg(dev, "%s: system resume\n", __func__);
9413 return 0;
9414}
9415
9416static const struct dev_pm_ops tavil_pm_ops = {
9417 .suspend = tavil_suspend,
9418 .resume = tavil_resume,
9419};
9420#endif
9421
9422static int tavil_swrm_read(void *handle, int reg)
9423{
9424 struct tavil_priv *tavil;
9425 struct wcd9xxx *wcd9xxx;
9426 unsigned short swr_rd_addr_base;
9427 unsigned short swr_rd_data_base;
9428 int val, ret;
9429
9430 if (!handle) {
9431 pr_err("%s: NULL handle\n", __func__);
9432 return -EINVAL;
9433 }
9434 tavil = (struct tavil_priv *)handle;
9435 wcd9xxx = tavil->wcd9xxx;
9436
9437 dev_dbg(tavil->dev, "%s: Reading soundwire register, 0x%x\n",
9438 __func__, reg);
9439 swr_rd_addr_base = WCD934X_SWR_AHB_BRIDGE_RD_ADDR_0;
9440 swr_rd_data_base = WCD934X_SWR_AHB_BRIDGE_RD_DATA_0;
9441
9442 mutex_lock(&tavil->swr.read_mutex);
9443 ret = regmap_bulk_write(wcd9xxx->regmap, swr_rd_addr_base,
9444 (u8 *)&reg, 4);
9445 if (ret < 0) {
9446 dev_err(tavil->dev, "%s: RD Addr Failure\n", __func__);
9447 goto done;
9448 }
9449 ret = regmap_bulk_read(wcd9xxx->regmap, swr_rd_data_base,
9450 (u8 *)&val, 4);
9451 if (ret < 0) {
9452 dev_err(tavil->dev, "%s: RD Data Failure\n", __func__);
9453 goto done;
9454 }
9455 ret = val;
9456done:
9457 mutex_unlock(&tavil->swr.read_mutex);
9458
9459 return ret;
9460}
9461
9462static int tavil_swrm_bulk_write(void *handle, u32 *reg, u32 *val, size_t len)
9463{
9464 struct tavil_priv *tavil;
9465 struct wcd9xxx *wcd9xxx;
9466 struct wcd9xxx_reg_val *bulk_reg;
9467 unsigned short swr_wr_addr_base;
9468 unsigned short swr_wr_data_base;
9469 int i, j, ret;
9470
9471 if (!handle || !reg || !val) {
9472 pr_err("%s: NULL parameter\n", __func__);
9473 return -EINVAL;
9474 }
9475 if (len <= 0) {
9476 pr_err("%s: Invalid size: %zu\n", __func__, len);
9477 return -EINVAL;
9478 }
9479 tavil = (struct tavil_priv *)handle;
9480 wcd9xxx = tavil->wcd9xxx;
9481
9482 swr_wr_addr_base = WCD934X_SWR_AHB_BRIDGE_WR_ADDR_0;
9483 swr_wr_data_base = WCD934X_SWR_AHB_BRIDGE_WR_DATA_0;
9484
9485 bulk_reg = kzalloc((2 * len * sizeof(struct wcd9xxx_reg_val)),
9486 GFP_KERNEL);
9487 if (!bulk_reg)
9488 return -ENOMEM;
9489
9490 for (i = 0, j = 0; i < (len * 2); i += 2, j++) {
9491 bulk_reg[i].reg = swr_wr_data_base;
9492 bulk_reg[i].buf = (u8 *)(&val[j]);
9493 bulk_reg[i].bytes = 4;
9494 bulk_reg[i+1].reg = swr_wr_addr_base;
9495 bulk_reg[i+1].buf = (u8 *)(&reg[j]);
9496 bulk_reg[i+1].bytes = 4;
9497 }
9498
9499 mutex_lock(&tavil->swr.write_mutex);
9500 ret = wcd9xxx_slim_bulk_write(wcd9xxx, bulk_reg,
9501 (len * 2), false);
9502 if (ret) {
9503 dev_err(tavil->dev, "%s: swrm bulk write failed, ret: %d\n",
9504 __func__, ret);
9505 }
9506 mutex_unlock(&tavil->swr.write_mutex);
9507
9508 kfree(bulk_reg);
9509 return ret;
9510}
9511
9512static int tavil_swrm_write(void *handle, int reg, int val)
9513{
9514 struct tavil_priv *tavil;
9515 struct wcd9xxx *wcd9xxx;
9516 unsigned short swr_wr_addr_base;
9517 unsigned short swr_wr_data_base;
9518 struct wcd9xxx_reg_val bulk_reg[2];
9519 int ret;
9520
9521 if (!handle) {
9522 pr_err("%s: NULL handle\n", __func__);
9523 return -EINVAL;
9524 }
9525 tavil = (struct tavil_priv *)handle;
9526 wcd9xxx = tavil->wcd9xxx;
9527
9528 swr_wr_addr_base = WCD934X_SWR_AHB_BRIDGE_WR_ADDR_0;
9529 swr_wr_data_base = WCD934X_SWR_AHB_BRIDGE_WR_DATA_0;
9530
9531 /* First Write the Data to register */
9532 bulk_reg[0].reg = swr_wr_data_base;
9533 bulk_reg[0].buf = (u8 *)(&val);
9534 bulk_reg[0].bytes = 4;
9535 bulk_reg[1].reg = swr_wr_addr_base;
9536 bulk_reg[1].buf = (u8 *)(&reg);
9537 bulk_reg[1].bytes = 4;
9538
9539 mutex_lock(&tavil->swr.write_mutex);
9540 ret = wcd9xxx_slim_bulk_write(wcd9xxx, bulk_reg, 2, false);
9541 if (ret < 0)
9542 dev_err(tavil->dev, "%s: WR Data Failure\n", __func__);
9543 mutex_unlock(&tavil->swr.write_mutex);
9544
9545 return ret;
9546}
9547
9548static int tavil_swrm_clock(void *handle, bool enable)
9549{
9550 struct tavil_priv *tavil;
9551
9552 if (!handle) {
9553 pr_err("%s: NULL handle\n", __func__);
9554 return -EINVAL;
9555 }
9556 tavil = (struct tavil_priv *)handle;
9557
9558 mutex_lock(&tavil->swr.clk_mutex);
9559 dev_dbg(tavil->dev, "%s: swrm clock %s\n",
9560 __func__, (enable?"enable" : "disable"));
9561 if (enable) {
9562 tavil->swr.clk_users++;
9563 if (tavil->swr.clk_users == 1) {
9564 regmap_update_bits(tavil->wcd9xxx->regmap,
9565 WCD934X_TEST_DEBUG_NPL_DLY_TEST_1,
9566 0x10, 0x00);
9567 __tavil_cdc_mclk_enable(tavil, true);
9568 regmap_update_bits(tavil->wcd9xxx->regmap,
9569 WCD934X_CDC_CLK_RST_CTRL_SWR_CONTROL,
9570 0x01, 0x01);
9571 }
9572 } else {
9573 tavil->swr.clk_users--;
9574 if (tavil->swr.clk_users == 0) {
9575 regmap_update_bits(tavil->wcd9xxx->regmap,
9576 WCD934X_CDC_CLK_RST_CTRL_SWR_CONTROL,
9577 0x01, 0x00);
9578 __tavil_cdc_mclk_enable(tavil, false);
9579 regmap_update_bits(tavil->wcd9xxx->regmap,
9580 WCD934X_TEST_DEBUG_NPL_DLY_TEST_1,
9581 0x10, 0x10);
9582 }
9583 }
9584 dev_dbg(tavil->dev, "%s: swrm clock users %d\n",
9585 __func__, tavil->swr.clk_users);
9586 mutex_unlock(&tavil->swr.clk_mutex);
9587
9588 return 0;
9589}
9590
9591static int tavil_swrm_handle_irq(void *handle,
9592 irqreturn_t (*swrm_irq_handler)(int irq,
9593 void *data),
9594 void *swrm_handle,
9595 int action)
9596{
9597 struct tavil_priv *tavil;
9598 int ret = 0;
9599 struct wcd9xxx *wcd9xxx;
9600
9601 if (!handle) {
9602 pr_err("%s: NULL handle\n", __func__);
9603 return -EINVAL;
9604 }
9605 tavil = (struct tavil_priv *) handle;
9606 wcd9xxx = tavil->wcd9xxx;
9607
9608 if (action) {
9609 ret = wcd9xxx_request_irq(&wcd9xxx->core_res,
9610 WCD934X_IRQ_SOUNDWIRE,
9611 swrm_irq_handler,
9612 "Tavil SWR Master", swrm_handle);
9613 if (ret)
9614 dev_err(tavil->dev, "%s: Failed to request irq %d\n",
9615 __func__, WCD934X_IRQ_SOUNDWIRE);
9616 } else
9617 wcd9xxx_free_irq(&wcd9xxx->core_res, WCD934X_IRQ_SOUNDWIRE,
9618 swrm_handle);
9619
9620 return ret;
9621}
9622
9623static void tavil_codec_add_spi_device(struct tavil_priv *tavil,
9624 struct device_node *node)
9625{
9626 struct spi_master *master;
9627 struct spi_device *spi;
9628 u32 prop_value;
9629 int rc;
9630
9631 /* Read the master bus num from DT node */
9632 rc = of_property_read_u32(node, "qcom,master-bus-num",
9633 &prop_value);
Xiaoyu Ye1a2d8bd92017-01-31 18:54:15 -08009634 if (rc < 0) {
Banajit Goswamide8271c2017-01-18 00:28:59 -08009635 dev_err(tavil->dev, "%s: prop %s not found in node %s",
9636 __func__, "qcom,master-bus-num", node->full_name);
9637 goto done;
9638 }
9639
9640 /* Get the reference to SPI master */
9641 master = spi_busnum_to_master(prop_value);
9642 if (!master) {
9643 dev_err(tavil->dev, "%s: Invalid spi_master for bus_num %u\n",
9644 __func__, prop_value);
9645 goto done;
9646 }
9647
9648 /* Allocate the spi device */
9649 spi = spi_alloc_device(master);
9650 if (!spi) {
9651 dev_err(tavil->dev, "%s: spi_alloc_device failed\n",
9652 __func__);
9653 goto err_spi_alloc_dev;
9654 }
9655
9656 /* Initialize device properties */
9657 if (of_modalias_node(node, spi->modalias,
9658 sizeof(spi->modalias)) < 0) {
9659 dev_err(tavil->dev, "%s: cannot find modalias for %s\n",
9660 __func__, node->full_name);
9661 goto err_dt_parse;
9662 }
9663
9664 rc = of_property_read_u32(node, "qcom,chip-select",
9665 &prop_value);
Xiaoyu Ye1a2d8bd92017-01-31 18:54:15 -08009666 if (rc < 0) {
Banajit Goswamide8271c2017-01-18 00:28:59 -08009667 dev_err(tavil->dev, "%s: prop %s not found in node %s",
9668 __func__, "qcom,chip-select", node->full_name);
9669 goto err_dt_parse;
9670 }
9671 spi->chip_select = prop_value;
9672
9673 rc = of_property_read_u32(node, "qcom,max-frequency",
9674 &prop_value);
Xiaoyu Ye1a2d8bd92017-01-31 18:54:15 -08009675 if (rc < 0) {
Banajit Goswamide8271c2017-01-18 00:28:59 -08009676 dev_err(tavil->dev, "%s: prop %s not found in node %s",
9677 __func__, "qcom,max-frequency", node->full_name);
9678 goto err_dt_parse;
9679 }
9680 spi->max_speed_hz = prop_value;
9681
9682 spi->dev.of_node = node;
9683
9684 rc = spi_add_device(spi);
Xiaoyu Ye1a2d8bd92017-01-31 18:54:15 -08009685 if (rc < 0) {
Banajit Goswamide8271c2017-01-18 00:28:59 -08009686 dev_err(tavil->dev, "%s: spi_add_device failed\n", __func__);
9687 goto err_dt_parse;
9688 }
9689
9690 /* Put the reference to SPI master */
9691 put_device(&master->dev);
9692
9693 return;
9694
9695err_dt_parse:
9696 spi_dev_put(spi);
9697
9698err_spi_alloc_dev:
9699 /* Put the reference to SPI master */
9700 put_device(&master->dev);
9701done:
9702 return;
9703}
9704
9705static void tavil_add_child_devices(struct work_struct *work)
9706{
9707 struct tavil_priv *tavil;
9708 struct platform_device *pdev;
9709 struct device_node *node;
9710 struct wcd9xxx *wcd9xxx;
9711 struct tavil_swr_ctrl_data *swr_ctrl_data = NULL, *temp;
9712 int ret, ctrl_num = 0;
9713 struct wcd_swr_ctrl_platform_data *platdata;
9714 char plat_dev_name[WCD934X_STRING_LEN];
9715
9716 tavil = container_of(work, struct tavil_priv,
9717 tavil_add_child_devices_work);
9718 if (!tavil) {
9719 pr_err("%s: Memory for WCD934X does not exist\n",
9720 __func__);
9721 return;
9722 }
9723 wcd9xxx = tavil->wcd9xxx;
9724 if (!wcd9xxx) {
9725 pr_err("%s: Memory for WCD9XXX does not exist\n",
9726 __func__);
9727 return;
9728 }
9729 if (!wcd9xxx->dev->of_node) {
9730 dev_err(wcd9xxx->dev, "%s: DT node for wcd9xxx does not exist\n",
9731 __func__);
9732 return;
9733 }
9734
9735 platdata = &tavil->swr.plat_data;
9736
9737 for_each_child_of_node(wcd9xxx->dev->of_node, node) {
9738
9739 /* Parse and add the SPI device node */
9740 if (!strcmp(node->name, "wcd_spi")) {
9741 tavil_codec_add_spi_device(tavil, node);
9742 continue;
9743 }
9744
9745 /* Parse other child device nodes and add platform device */
9746 if (!strcmp(node->name, "swr_master"))
9747 strlcpy(plat_dev_name, "tavil_swr_ctrl",
9748 (WCD934X_STRING_LEN - 1));
9749 else if (strnstr(node->name, "msm_cdc_pinctrl",
9750 strlen("msm_cdc_pinctrl")) != NULL)
9751 strlcpy(plat_dev_name, node->name,
9752 (WCD934X_STRING_LEN - 1));
9753 else
9754 continue;
9755
9756 pdev = platform_device_alloc(plat_dev_name, -1);
9757 if (!pdev) {
9758 dev_err(wcd9xxx->dev, "%s: pdev memory alloc failed\n",
9759 __func__);
9760 ret = -ENOMEM;
9761 goto err_mem;
9762 }
9763 pdev->dev.parent = tavil->dev;
9764 pdev->dev.of_node = node;
9765
9766 if (strcmp(node->name, "swr_master") == 0) {
9767 ret = platform_device_add_data(pdev, platdata,
9768 sizeof(*platdata));
9769 if (ret) {
9770 dev_err(&pdev->dev,
9771 "%s: cannot add plat data ctrl:%d\n",
9772 __func__, ctrl_num);
9773 goto err_pdev_add;
9774 }
9775 }
9776
9777 ret = platform_device_add(pdev);
9778 if (ret) {
9779 dev_err(&pdev->dev,
9780 "%s: Cannot add platform device\n",
9781 __func__);
9782 goto err_pdev_add;
9783 }
9784
9785 if (strcmp(node->name, "swr_master") == 0) {
9786 temp = krealloc(swr_ctrl_data,
9787 (ctrl_num + 1) * sizeof(
9788 struct tavil_swr_ctrl_data),
9789 GFP_KERNEL);
9790 if (!temp) {
9791 dev_err(wcd9xxx->dev, "out of memory\n");
9792 ret = -ENOMEM;
9793 goto err_pdev_add;
9794 }
9795 swr_ctrl_data = temp;
9796 swr_ctrl_data[ctrl_num].swr_pdev = pdev;
9797 ctrl_num++;
9798 dev_dbg(&pdev->dev,
9799 "%s: Added soundwire ctrl device(s)\n",
9800 __func__);
9801 tavil->swr.ctrl_data = swr_ctrl_data;
9802 }
9803 }
9804
9805 return;
9806
9807err_pdev_add:
9808 platform_device_put(pdev);
9809err_mem:
9810 return;
9811}
9812
9813static int __tavil_enable_efuse_sensing(struct tavil_priv *tavil)
9814{
9815 int val, rc;
9816
9817 __tavil_cdc_mclk_enable(tavil, true);
9818
9819 regmap_update_bits(tavil->wcd9xxx->regmap,
9820 WCD934X_CHIP_TIER_CTRL_EFUSE_CTL, 0x1E, 0x10);
9821 regmap_update_bits(tavil->wcd9xxx->regmap,
9822 WCD934X_CHIP_TIER_CTRL_EFUSE_CTL, 0x01, 0x01);
9823
9824 /*
9825 * 5ms sleep required after enabling efuse control
9826 * before checking the status.
9827 */
9828 usleep_range(5000, 5500);
9829 rc = regmap_read(tavil->wcd9xxx->regmap,
9830 WCD934X_CHIP_TIER_CTRL_EFUSE_STATUS, &val);
9831 if (rc || (!(val & 0x01)))
9832 WARN(1, "%s: Efuse sense is not complete val=%x, ret=%d\n",
9833 __func__, val, rc);
9834
9835 __tavil_cdc_mclk_enable(tavil, false);
9836
9837 return rc;
9838}
9839
9840static void ___tavil_get_codec_fine_version(struct tavil_priv *tavil)
9841{
9842 int val1, val2, version;
9843 struct regmap *regmap;
9844 u16 id_minor;
9845 u32 version_mask = 0;
9846
9847 regmap = tavil->wcd9xxx->regmap;
9848 version = tavil->wcd9xxx->version;
9849 id_minor = tavil->wcd9xxx->codec_type->id_minor;
9850
9851 regmap_read(regmap, WCD934X_CHIP_TIER_CTRL_EFUSE_VAL_OUT14, &val1);
9852 regmap_read(regmap, WCD934X_CHIP_TIER_CTRL_EFUSE_VAL_OUT15, &val2);
9853
9854 dev_dbg(tavil->dev, "%s: chip version :0x%x 0x:%x\n",
9855 __func__, val1, val2);
9856
9857 version_mask |= (!!((u8)val1 & 0x80)) << DSD_DISABLED_MASK;
9858 version_mask |= (!!((u8)val2 & 0x01)) << SLNQ_DISABLED_MASK;
9859
9860 switch (version_mask) {
9861 case DSD_DISABLED | SLNQ_DISABLED:
9862 if (id_minor == cpu_to_le16(0))
9863 version = TAVIL_VERSION_WCD9340_1_0;
9864 else if (id_minor == cpu_to_le16(0x01))
9865 version = TAVIL_VERSION_WCD9340_1_1;
9866 break;
9867 case SLNQ_DISABLED:
9868 if (id_minor == cpu_to_le16(0))
9869 version = TAVIL_VERSION_WCD9341_1_0;
9870 else if (id_minor == cpu_to_le16(0x01))
9871 version = TAVIL_VERSION_WCD9341_1_1;
9872 break;
9873 }
9874
9875 tavil->wcd9xxx->version = version;
9876 tavil->wcd9xxx->codec_type->version = version;
9877}
9878
9879/*
9880 * tavil_get_wcd_dsp_cntl: Get the reference to wcd_dsp_cntl
9881 * @dev: Device pointer for codec device
9882 *
9883 * This API gets the reference to codec's struct wcd_dsp_cntl
9884 */
9885struct wcd_dsp_cntl *tavil_get_wcd_dsp_cntl(struct device *dev)
9886{
9887 struct platform_device *pdev;
9888 struct tavil_priv *tavil;
9889
9890 if (!dev) {
9891 pr_err("%s: Invalid device\n", __func__);
9892 return NULL;
9893 }
9894
9895 pdev = to_platform_device(dev);
9896 tavil = platform_get_drvdata(pdev);
9897
9898 return tavil->wdsp_cntl;
9899}
9900EXPORT_SYMBOL(tavil_get_wcd_dsp_cntl);
9901
9902static int tavil_probe(struct platform_device *pdev)
9903{
9904 int ret = 0;
9905 struct tavil_priv *tavil;
9906 struct clk *wcd_ext_clk;
9907 struct wcd9xxx_resmgr_v2 *resmgr;
9908 struct wcd9xxx_power_region *cdc_pwr;
9909
9910 tavil = devm_kzalloc(&pdev->dev, sizeof(struct tavil_priv),
9911 GFP_KERNEL);
9912 if (!tavil)
9913 return -ENOMEM;
9914
9915 platform_set_drvdata(pdev, tavil);
9916
9917 tavil->wcd9xxx = dev_get_drvdata(pdev->dev.parent);
9918 tavil->dev = &pdev->dev;
9919 INIT_DELAYED_WORK(&tavil->power_gate_work, tavil_codec_power_gate_work);
9920 mutex_init(&tavil->power_lock);
9921 INIT_WORK(&tavil->tavil_add_child_devices_work,
9922 tavil_add_child_devices);
9923 mutex_init(&tavil->micb_lock);
9924 mutex_init(&tavil->swr.read_mutex);
9925 mutex_init(&tavil->swr.write_mutex);
9926 mutex_init(&tavil->swr.clk_mutex);
9927 mutex_init(&tavil->codec_mutex);
9928 mutex_init(&tavil->svs_mutex);
9929
9930 /*
9931 * Codec hardware by default comes up in SVS mode.
9932 * Initialize the svs_ref_cnt to 1 to reflect the hardware
9933 * state in the driver.
9934 */
9935 tavil->svs_ref_cnt = 1;
9936
9937 cdc_pwr = devm_kzalloc(&pdev->dev, sizeof(struct wcd9xxx_power_region),
9938 GFP_KERNEL);
9939 if (!cdc_pwr) {
9940 ret = -ENOMEM;
9941 goto err_resmgr;
9942 }
9943 tavil->wcd9xxx->wcd9xxx_pwr[WCD9XXX_DIG_CORE_REGION_1] = cdc_pwr;
9944 cdc_pwr->pwr_collapse_reg_min = WCD934X_DIG_CORE_REG_MIN;
9945 cdc_pwr->pwr_collapse_reg_max = WCD934X_DIG_CORE_REG_MAX;
9946 wcd9xxx_set_power_state(tavil->wcd9xxx,
9947 WCD_REGION_POWER_COLLAPSE_REMOVE,
9948 WCD9XXX_DIG_CORE_REGION_1);
9949 /*
9950 * Init resource manager so that if child nodes such as SoundWire
9951 * requests for clock, resource manager can honor the request
9952 */
9953 resmgr = wcd_resmgr_init(&tavil->wcd9xxx->core_res, NULL);
9954 if (IS_ERR(resmgr)) {
9955 ret = PTR_ERR(resmgr);
9956 dev_err(&pdev->dev, "%s: Failed to initialize wcd resmgr\n",
9957 __func__);
9958 goto err_resmgr;
9959 }
9960 tavil->resmgr = resmgr;
9961 tavil->swr.plat_data.handle = (void *) tavil;
9962 tavil->swr.plat_data.read = tavil_swrm_read;
9963 tavil->swr.plat_data.write = tavil_swrm_write;
9964 tavil->swr.plat_data.bulk_write = tavil_swrm_bulk_write;
9965 tavil->swr.plat_data.clk = tavil_swrm_clock;
9966 tavil->swr.plat_data.handle_irq = tavil_swrm_handle_irq;
9967 tavil->swr.spkr_gain_offset = WCD934X_RX_GAIN_OFFSET_0_DB;
9968
9969 /* Register for Clock */
9970 wcd_ext_clk = clk_get(tavil->wcd9xxx->dev, "wcd_clk");
9971 if (IS_ERR(wcd_ext_clk)) {
9972 dev_err(tavil->wcd9xxx->dev, "%s: clk get %s failed\n",
9973 __func__, "wcd_ext_clk");
9974 goto err_clk;
9975 }
9976 tavil->wcd_ext_clk = wcd_ext_clk;
9977 set_bit(AUDIO_NOMINAL, &tavil->status_mask);
9978 /* Update codec register default values */
9979 dev_dbg(&pdev->dev, "%s: MCLK Rate = %x\n", __func__,
9980 tavil->wcd9xxx->mclk_rate);
9981 if (tavil->wcd9xxx->mclk_rate == WCD934X_MCLK_CLK_12P288MHZ)
9982 regmap_update_bits(tavil->wcd9xxx->regmap,
9983 WCD934X_CODEC_RPM_CLK_MCLK_CFG,
9984 0x03, 0x00);
9985 else if (tavil->wcd9xxx->mclk_rate == WCD934X_MCLK_CLK_9P6MHZ)
9986 regmap_update_bits(tavil->wcd9xxx->regmap,
9987 WCD934X_CODEC_RPM_CLK_MCLK_CFG,
9988 0x03, 0x01);
9989 tavil_update_reg_defaults(tavil);
9990 __tavil_enable_efuse_sensing(tavil);
9991 ___tavil_get_codec_fine_version(tavil);
9992 tavil_update_cpr_defaults(tavil);
9993
9994 /* Register with soc framework */
9995 ret = snd_soc_register_codec(&pdev->dev, &soc_codec_dev_tavil,
9996 tavil_dai, ARRAY_SIZE(tavil_dai));
9997 if (ret) {
9998 dev_err(&pdev->dev, "%s: Codec registration failed\n",
9999 __func__);
10000 goto err_cdc_reg;
10001 }
10002 schedule_work(&tavil->tavil_add_child_devices_work);
10003
10004 return ret;
10005
10006err_cdc_reg:
10007 clk_put(tavil->wcd_ext_clk);
10008err_clk:
10009 wcd_resmgr_remove(tavil->resmgr);
10010err_resmgr:
10011 mutex_destroy(&tavil->micb_lock);
10012 mutex_destroy(&tavil->svs_mutex);
10013 mutex_destroy(&tavil->codec_mutex);
10014 mutex_destroy(&tavil->swr.read_mutex);
10015 mutex_destroy(&tavil->swr.write_mutex);
10016 mutex_destroy(&tavil->swr.clk_mutex);
10017 devm_kfree(&pdev->dev, tavil);
10018
10019 return ret;
10020}
10021
10022static int tavil_remove(struct platform_device *pdev)
10023{
10024 struct tavil_priv *tavil;
10025
10026 tavil = platform_get_drvdata(pdev);
10027 if (!tavil)
10028 return -EINVAL;
10029
10030 mutex_destroy(&tavil->micb_lock);
10031 mutex_destroy(&tavil->svs_mutex);
10032 mutex_destroy(&tavil->codec_mutex);
10033 mutex_destroy(&tavil->swr.read_mutex);
10034 mutex_destroy(&tavil->swr.write_mutex);
10035 mutex_destroy(&tavil->swr.clk_mutex);
10036
10037 snd_soc_unregister_codec(&pdev->dev);
10038 clk_put(tavil->wcd_ext_clk);
10039 wcd_resmgr_remove(tavil->resmgr);
10040 if (tavil->dsd_config) {
10041 tavil_dsd_deinit(tavil->dsd_config);
10042 tavil->dsd_config = NULL;
10043 }
10044 devm_kfree(&pdev->dev, tavil);
10045 return 0;
10046}
10047
10048static struct platform_driver tavil_codec_driver = {
10049 .probe = tavil_probe,
10050 .remove = tavil_remove,
10051 .driver = {
10052 .name = "tavil_codec",
10053 .owner = THIS_MODULE,
10054#ifdef CONFIG_PM
10055 .pm = &tavil_pm_ops,
10056#endif
10057 },
10058};
10059
10060module_platform_driver(tavil_codec_driver);
10061
10062MODULE_DESCRIPTION("Tavil Codec driver");
10063MODULE_LICENSE("GPL v2");