blob: eb856c21de53617348bfe88d3ee8d56d0fe3552c [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;
2295
2296 dev_dbg(codec->dev, "%s %s %d\n", __func__, w->name, event);
2297
2298 if (w->reg == WCD934X_ANA_LO_1_2) {
2299 if (w->shift == 7) {
2300 lineout_vol_reg = WCD934X_CDC_RX3_RX_PATH_CTL;
2301 lineout_mix_vol_reg = WCD934X_CDC_RX3_RX_PATH_MIX_CTL;
2302 } else if (w->shift == 6) {
2303 lineout_vol_reg = WCD934X_CDC_RX4_RX_PATH_CTL;
2304 lineout_mix_vol_reg = WCD934X_CDC_RX4_RX_PATH_MIX_CTL;
2305 }
2306 } else {
2307 dev_err(codec->dev, "%s: Error enabling lineout PA\n",
2308 __func__);
2309 return -EINVAL;
2310 }
2311
2312 switch (event) {
2313 case SND_SOC_DAPM_PRE_PMU:
2314 tavil_codec_override(codec, CLS_AB, event);
2315 break;
2316 case SND_SOC_DAPM_POST_PMU:
2317 /*
2318 * 5ms sleep is required after PA is enabled as per
2319 * HW requirement
2320 */
2321 usleep_range(5000, 5500);
2322 snd_soc_update_bits(codec, lineout_vol_reg,
2323 0x10, 0x00);
2324 /* Remove mix path mute if it is enabled */
2325 if ((snd_soc_read(codec, lineout_mix_vol_reg)) & 0x10)
2326 snd_soc_update_bits(codec,
2327 lineout_mix_vol_reg,
2328 0x10, 0x00);
2329 break;
2330 case SND_SOC_DAPM_POST_PMD:
2331 /*
2332 * 5ms sleep is required after PA is disabled as per
2333 * HW requirement
2334 */
2335 usleep_range(5000, 5500);
2336 tavil_codec_override(codec, CLS_AB, event);
2337 default:
2338 break;
2339 };
2340
2341 return 0;
2342}
2343
2344static int tavil_codec_ear_dac_event(struct snd_soc_dapm_widget *w,
2345 struct snd_kcontrol *kcontrol,
2346 int event)
2347{
2348 int ret = 0;
2349 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
2350 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
2351
2352 dev_dbg(codec->dev, "%s %s %d\n", __func__, w->name, event);
2353
2354 switch (event) {
2355 case SND_SOC_DAPM_PRE_PMU:
2356 /* Disable AutoChop timer during power up */
2357 snd_soc_update_bits(codec, WCD934X_HPH_NEW_INT_HPH_TIMER1,
2358 0x02, 0x00);
2359
2360 if (tavil->anc_func)
2361 ret = tavil_codec_enable_anc(w, kcontrol, event);
2362
2363 wcd_clsh_fsm(codec, &tavil->clsh_d,
2364 WCD_CLSH_EVENT_PRE_DAC,
2365 WCD_CLSH_STATE_EAR,
2366 CLS_H_NORMAL);
2367 if (tavil->anc_func)
2368 snd_soc_update_bits(codec, WCD934X_CDC_RX0_RX_PATH_CFG0,
2369 0x10, 0x10);
2370 break;
2371 case SND_SOC_DAPM_POST_PMD:
2372 wcd_clsh_fsm(codec, &tavil->clsh_d,
2373 WCD_CLSH_EVENT_POST_PA,
2374 WCD_CLSH_STATE_EAR,
2375 CLS_H_NORMAL);
2376 break;
2377 default:
2378 break;
2379 };
2380
2381 return ret;
2382}
2383
2384static int tavil_codec_hphr_dac_event(struct snd_soc_dapm_widget *w,
2385 struct snd_kcontrol *kcontrol,
2386 int event)
2387{
2388 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
2389 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
2390 int hph_mode = tavil->hph_mode;
2391 u8 dem_inp;
2392 struct tavil_dsd_config *dsd_conf = tavil->dsd_config;
Meng Wangf45a20d2017-01-18 09:51:58 +08002393 int ret = 0;
Banajit Goswamide8271c2017-01-18 00:28:59 -08002394
2395 dev_dbg(codec->dev, "%s wname: %s event: %d hph_mode: %d\n", __func__,
2396 w->name, event, hph_mode);
2397
2398 switch (event) {
2399 case SND_SOC_DAPM_PRE_PMU:
Meng Wangf45a20d2017-01-18 09:51:58 +08002400 if (tavil->anc_func) {
2401 ret = tavil_codec_enable_anc(w, kcontrol, event);
2402 /* 40 msec delay is needed to avoid click and pop */
2403 msleep(40);
2404 }
Banajit Goswamide8271c2017-01-18 00:28:59 -08002405 /* Read DEM INP Select */
2406 dem_inp = snd_soc_read(codec, WCD934X_CDC_RX2_RX_PATH_SEC0) &
2407 0x03;
2408 if (((hph_mode == CLS_H_HIFI) || (hph_mode == CLS_H_LOHIFI) ||
2409 (hph_mode == CLS_H_LP)) && (dem_inp != 0x01)) {
2410 dev_err(codec->dev, "%s: DEM Input not set correctly, hph_mode: %d\n",
2411 __func__, hph_mode);
2412 return -EINVAL;
2413 }
2414 if ((hph_mode != CLS_H_LP) && (hph_mode != CLS_H_ULP))
2415 /* Ripple freq control enable */
2416 snd_soc_update_bits(codec,
2417 WCD934X_SIDO_NEW_VOUT_D_FREQ2,
2418 0x01, 0x01);
2419 /* Disable AutoChop timer during power up */
2420 snd_soc_update_bits(codec, WCD934X_HPH_NEW_INT_HPH_TIMER1,
2421 0x02, 0x00);
2422 /* Set RDAC gain */
2423 if (TAVIL_IS_1_0(tavil->wcd9xxx))
2424 snd_soc_update_bits(codec,
2425 WCD934X_HPH_NEW_INT_RDAC_GAIN_CTL,
2426 0xF0, 0x40);
2427 if (dsd_conf &&
2428 (snd_soc_read(codec, WCD934X_CDC_DSD1_PATH_CTL) & 0x01))
2429 hph_mode = CLS_H_HIFI;
2430
2431 wcd_clsh_fsm(codec, &tavil->clsh_d,
2432 WCD_CLSH_EVENT_PRE_DAC,
2433 WCD_CLSH_STATE_HPHR,
2434 hph_mode);
Meng Wangf45a20d2017-01-18 09:51:58 +08002435 if (tavil->anc_func)
2436 snd_soc_update_bits(codec,
2437 WCD934X_CDC_RX2_RX_PATH_CFG0,
2438 0x10, 0x10);
Banajit Goswamide8271c2017-01-18 00:28:59 -08002439 break;
2440 case SND_SOC_DAPM_POST_PMD:
2441 /* 1000us required as per HW requirement */
2442 usleep_range(1000, 1100);
2443 wcd_clsh_fsm(codec, &tavil->clsh_d,
2444 WCD_CLSH_EVENT_POST_PA,
2445 WCD_CLSH_STATE_HPHR,
2446 hph_mode);
2447 if ((hph_mode != CLS_H_LP) && (hph_mode != CLS_H_ULP))
2448 /* Ripple freq control disable */
2449 snd_soc_update_bits(codec,
2450 WCD934X_SIDO_NEW_VOUT_D_FREQ2,
2451 0x01, 0x0);
2452 /* Re-set RDAC gain */
2453 if (TAVIL_IS_1_0(tavil->wcd9xxx))
2454 snd_soc_update_bits(codec,
2455 WCD934X_HPH_NEW_INT_RDAC_GAIN_CTL,
2456 0xF0, 0x0);
2457 break;
2458 default:
2459 break;
2460 };
2461
2462 return 0;
2463}
2464
2465static int tavil_codec_hphl_dac_event(struct snd_soc_dapm_widget *w,
2466 struct snd_kcontrol *kcontrol,
2467 int event)
2468{
2469 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
2470 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
2471 int hph_mode = tavil->hph_mode;
2472 u8 dem_inp;
2473 int ret = 0;
2474 struct tavil_dsd_config *dsd_conf = tavil->dsd_config;
Phani Kumar Uppalapatib506bc02016-12-06 16:08:24 -08002475 uint32_t impedl = 0, impedr = 0;
Banajit Goswamide8271c2017-01-18 00:28:59 -08002476
2477 dev_dbg(codec->dev, "%s wname: %s event: %d hph_mode: %d\n", __func__,
2478 w->name, event, hph_mode);
2479
2480 switch (event) {
2481 case SND_SOC_DAPM_PRE_PMU:
Meng Wangf45a20d2017-01-18 09:51:58 +08002482 if (tavil->anc_func) {
2483 ret = tavil_codec_enable_anc(w, kcontrol, event);
2484 /* 40 msec delay is needed to avoid click and pop */
2485 msleep(40);
2486 }
Banajit Goswamide8271c2017-01-18 00:28:59 -08002487 /* Read DEM INP Select */
2488 dem_inp = snd_soc_read(codec, WCD934X_CDC_RX1_RX_PATH_SEC0) &
2489 0x03;
2490 if (((hph_mode == CLS_H_HIFI) || (hph_mode == CLS_H_LOHIFI) ||
2491 (hph_mode == CLS_H_LP)) && (dem_inp != 0x01)) {
2492 dev_err(codec->dev, "%s: DEM Input not set correctly, hph_mode: %d\n",
2493 __func__, hph_mode);
2494 return -EINVAL;
2495 }
2496 if ((hph_mode != CLS_H_LP) && (hph_mode != CLS_H_ULP))
2497 /* Ripple freq control enable */
2498 snd_soc_update_bits(codec,
2499 WCD934X_SIDO_NEW_VOUT_D_FREQ2,
2500 0x01, 0x01);
2501 /* Disable AutoChop timer during power up */
2502 snd_soc_update_bits(codec, WCD934X_HPH_NEW_INT_HPH_TIMER1,
2503 0x02, 0x00);
2504 /* Set RDAC gain */
2505 if (TAVIL_IS_1_0(tavil->wcd9xxx))
2506 snd_soc_update_bits(codec,
2507 WCD934X_HPH_NEW_INT_RDAC_GAIN_CTL,
2508 0xF0, 0x40);
2509 if (dsd_conf &&
2510 (snd_soc_read(codec, WCD934X_CDC_DSD0_PATH_CTL) & 0x01))
2511 hph_mode = CLS_H_HIFI;
2512
2513 wcd_clsh_fsm(codec, &tavil->clsh_d,
2514 WCD_CLSH_EVENT_PRE_DAC,
2515 WCD_CLSH_STATE_HPHL,
2516 hph_mode);
Phani Kumar Uppalapatib506bc02016-12-06 16:08:24 -08002517
Meng Wangf45a20d2017-01-18 09:51:58 +08002518 if (tavil->anc_func)
2519 snd_soc_update_bits(codec,
2520 WCD934X_CDC_RX1_RX_PATH_CFG0,
2521 0x10, 0x10);
2522
Phani Kumar Uppalapatib506bc02016-12-06 16:08:24 -08002523 ret = tavil_mbhc_get_impedance(tavil->mbhc,
2524 &impedl, &impedr);
2525 if (!ret) {
2526 wcd_clsh_imped_config(codec, impedl, false);
2527 set_bit(CLSH_Z_CONFIG, &tavil->status_mask);
2528 } else {
2529 dev_dbg(codec->dev, "%s: Failed to get mbhc impedance %d\n",
2530 __func__, ret);
2531 ret = 0;
2532 }
2533
Banajit Goswamide8271c2017-01-18 00:28:59 -08002534 break;
2535 case SND_SOC_DAPM_POST_PMD:
2536 /* 1000us required as per HW requirement */
2537 usleep_range(1000, 1100);
2538 wcd_clsh_fsm(codec, &tavil->clsh_d,
2539 WCD_CLSH_EVENT_POST_PA,
2540 WCD_CLSH_STATE_HPHL,
2541 hph_mode);
2542 if ((hph_mode != CLS_H_LP) && (hph_mode != CLS_H_ULP))
2543 /* Ripple freq control disable */
2544 snd_soc_update_bits(codec,
2545 WCD934X_SIDO_NEW_VOUT_D_FREQ2,
2546 0x01, 0x0);
2547 /* Re-set RDAC gain */
2548 if (TAVIL_IS_1_0(tavil->wcd9xxx))
2549 snd_soc_update_bits(codec,
2550 WCD934X_HPH_NEW_INT_RDAC_GAIN_CTL,
2551 0xF0, 0x0);
Phani Kumar Uppalapatib506bc02016-12-06 16:08:24 -08002552
2553 if (test_bit(CLSH_Z_CONFIG, &tavil->status_mask)) {
2554 wcd_clsh_imped_config(codec, impedl, true);
2555 clear_bit(CLSH_Z_CONFIG, &tavil->status_mask);
2556 }
Banajit Goswamide8271c2017-01-18 00:28:59 -08002557 break;
2558 default:
2559 break;
2560 };
2561
2562 return ret;
2563}
2564
2565static int tavil_codec_lineout_dac_event(struct snd_soc_dapm_widget *w,
2566 struct snd_kcontrol *kcontrol,
2567 int event)
2568{
2569 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
2570 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
2571
2572 dev_dbg(codec->dev, "%s %s %d\n", __func__, w->name, event);
2573
2574 switch (event) {
2575 case SND_SOC_DAPM_PRE_PMU:
2576 wcd_clsh_fsm(codec, &tavil->clsh_d,
2577 WCD_CLSH_EVENT_PRE_DAC,
2578 WCD_CLSH_STATE_LO,
2579 CLS_AB);
2580 break;
2581 case SND_SOC_DAPM_POST_PMD:
2582 wcd_clsh_fsm(codec, &tavil->clsh_d,
2583 WCD_CLSH_EVENT_POST_PA,
2584 WCD_CLSH_STATE_LO,
2585 CLS_AB);
2586 break;
2587 }
2588
2589 return 0;
2590}
2591
2592static int tavil_codec_spk_boost_event(struct snd_soc_dapm_widget *w,
2593 struct snd_kcontrol *kcontrol,
2594 int event)
2595{
2596 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
2597 u16 boost_path_ctl, boost_path_cfg1;
2598 u16 reg, reg_mix;
2599
2600 dev_dbg(codec->dev, "%s %s %d\n", __func__, w->name, event);
2601
2602 if (!strcmp(w->name, "RX INT7 CHAIN")) {
2603 boost_path_ctl = WCD934X_CDC_BOOST0_BOOST_PATH_CTL;
2604 boost_path_cfg1 = WCD934X_CDC_RX7_RX_PATH_CFG1;
2605 reg = WCD934X_CDC_RX7_RX_PATH_CTL;
2606 reg_mix = WCD934X_CDC_RX7_RX_PATH_MIX_CTL;
2607 } else if (!strcmp(w->name, "RX INT8 CHAIN")) {
2608 boost_path_ctl = WCD934X_CDC_BOOST1_BOOST_PATH_CTL;
2609 boost_path_cfg1 = WCD934X_CDC_RX8_RX_PATH_CFG1;
2610 reg = WCD934X_CDC_RX8_RX_PATH_CTL;
2611 reg_mix = WCD934X_CDC_RX8_RX_PATH_MIX_CTL;
2612 } else {
2613 dev_err(codec->dev, "%s: unknown widget: %s\n",
2614 __func__, w->name);
2615 return -EINVAL;
2616 }
2617
2618 switch (event) {
2619 case SND_SOC_DAPM_PRE_PMU:
2620 snd_soc_update_bits(codec, boost_path_cfg1, 0x01, 0x01);
2621 snd_soc_update_bits(codec, boost_path_ctl, 0x10, 0x10);
2622 snd_soc_update_bits(codec, reg, 0x10, 0x00);
2623 if ((snd_soc_read(codec, reg_mix)) & 0x10)
2624 snd_soc_update_bits(codec, reg_mix, 0x10, 0x00);
2625 break;
2626 case SND_SOC_DAPM_POST_PMD:
2627 snd_soc_update_bits(codec, boost_path_ctl, 0x10, 0x00);
2628 snd_soc_update_bits(codec, boost_path_cfg1, 0x01, 0x00);
2629 break;
2630 };
2631
2632 return 0;
2633}
2634
2635static int __tavil_codec_enable_swr(struct snd_soc_dapm_widget *w, int event)
2636{
2637 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
2638 struct tavil_priv *tavil;
2639 int ch_cnt = 0;
2640
2641 tavil = snd_soc_codec_get_drvdata(codec);
2642
2643 switch (event) {
2644 case SND_SOC_DAPM_PRE_PMU:
2645 if (((strnstr(w->name, "INT7_", sizeof("RX INT7_"))) ||
2646 (strnstr(w->name, "INT7 MIX2",
2647 sizeof("RX INT7 MIX2")))))
2648 tavil->swr.rx_7_count++;
2649 if ((strnstr(w->name, "INT8_", sizeof("RX INT8_"))) &&
2650 !tavil->swr.rx_8_count)
2651 tavil->swr.rx_8_count++;
2652 ch_cnt = !!(tavil->swr.rx_7_count) + tavil->swr.rx_8_count;
2653
2654 swrm_wcd_notify(tavil->swr.ctrl_data[0].swr_pdev,
2655 SWR_DEVICE_UP, NULL);
2656 swrm_wcd_notify(tavil->swr.ctrl_data[0].swr_pdev,
2657 SWR_SET_NUM_RX_CH, &ch_cnt);
2658 break;
2659 case SND_SOC_DAPM_POST_PMD:
2660 if ((strnstr(w->name, "INT7_", sizeof("RX INT7_"))) ||
2661 (strnstr(w->name, "INT7 MIX2",
2662 sizeof("RX INT7 MIX2"))))
2663 tavil->swr.rx_7_count--;
2664 if ((strnstr(w->name, "INT8_", sizeof("RX INT8_"))) &&
2665 tavil->swr.rx_8_count)
2666 tavil->swr.rx_8_count--;
2667 ch_cnt = !!(tavil->swr.rx_7_count) + tavil->swr.rx_8_count;
2668
2669 swrm_wcd_notify(tavil->swr.ctrl_data[0].swr_pdev,
2670 SWR_SET_NUM_RX_CH, &ch_cnt);
2671
2672 break;
2673 }
2674 dev_dbg(tavil->dev, "%s: %s: current swr ch cnt: %d\n",
2675 __func__, w->name, ch_cnt);
2676
2677 return 0;
2678}
2679
2680static int tavil_codec_enable_swr(struct snd_soc_dapm_widget *w,
2681 struct snd_kcontrol *kcontrol, int event)
2682{
2683 return __tavil_codec_enable_swr(w, event);
2684}
2685
2686static int tavil_codec_config_mad(struct snd_soc_codec *codec)
2687{
2688 int ret = 0;
2689 int idx;
2690 const struct firmware *fw;
2691 struct firmware_cal *hwdep_cal = NULL;
2692 struct wcd_mad_audio_cal *mad_cal = NULL;
2693 const void *data;
2694 const char *filename = WCD934X_MAD_AUDIO_FIRMWARE_PATH;
2695 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
2696 size_t cal_size;
2697
2698 hwdep_cal = wcdcal_get_fw_cal(tavil->fw_data, WCD9XXX_MAD_CAL);
2699 if (hwdep_cal) {
2700 data = hwdep_cal->data;
2701 cal_size = hwdep_cal->size;
2702 dev_dbg(codec->dev, "%s: using hwdep calibration\n",
2703 __func__);
2704 } else {
2705 ret = request_firmware(&fw, filename, codec->dev);
2706 if (ret || !fw) {
2707 dev_err(codec->dev,
2708 "%s: MAD firmware acquire failed, err = %d\n",
2709 __func__, ret);
2710 return -ENODEV;
2711 }
2712 data = fw->data;
2713 cal_size = fw->size;
2714 dev_dbg(codec->dev, "%s: using request_firmware calibration\n",
2715 __func__);
2716 }
2717
2718 if (cal_size < sizeof(*mad_cal)) {
2719 dev_err(codec->dev,
2720 "%s: Incorrect size %zd for MAD Cal, expected %zd\n",
2721 __func__, cal_size, sizeof(*mad_cal));
2722 ret = -ENOMEM;
2723 goto done;
2724 }
2725
2726 mad_cal = (struct wcd_mad_audio_cal *) (data);
2727 if (!mad_cal) {
2728 dev_err(codec->dev,
2729 "%s: Invalid calibration data\n",
2730 __func__);
2731 ret = -EINVAL;
2732 goto done;
2733 }
2734
2735 snd_soc_write(codec, WCD934X_SOC_MAD_MAIN_CTL_2,
2736 mad_cal->microphone_info.cycle_time);
2737 snd_soc_update_bits(codec, WCD934X_SOC_MAD_MAIN_CTL_1, 0xFF << 3,
2738 ((uint16_t)mad_cal->microphone_info.settle_time)
2739 << 3);
2740
2741 /* Audio */
2742 snd_soc_write(codec, WCD934X_SOC_MAD_AUDIO_CTL_8,
2743 mad_cal->audio_info.rms_omit_samples);
2744 snd_soc_update_bits(codec, WCD934X_SOC_MAD_AUDIO_CTL_1,
2745 0x07 << 4, mad_cal->audio_info.rms_comp_time << 4);
2746 snd_soc_update_bits(codec, WCD934X_SOC_MAD_AUDIO_CTL_2, 0x03 << 2,
2747 mad_cal->audio_info.detection_mechanism << 2);
2748 snd_soc_write(codec, WCD934X_SOC_MAD_AUDIO_CTL_7,
2749 mad_cal->audio_info.rms_diff_threshold & 0x3F);
2750 snd_soc_write(codec, WCD934X_SOC_MAD_AUDIO_CTL_5,
2751 mad_cal->audio_info.rms_threshold_lsb);
2752 snd_soc_write(codec, WCD934X_SOC_MAD_AUDIO_CTL_6,
2753 mad_cal->audio_info.rms_threshold_msb);
2754
2755 for (idx = 0; idx < ARRAY_SIZE(mad_cal->audio_info.iir_coefficients);
2756 idx++) {
2757 snd_soc_update_bits(codec, WCD934X_SOC_MAD_AUDIO_IIR_CTL_PTR,
2758 0x3F, idx);
2759 snd_soc_write(codec, WCD934X_SOC_MAD_AUDIO_IIR_CTL_VAL,
2760 mad_cal->audio_info.iir_coefficients[idx]);
2761 dev_dbg(codec->dev, "%s:MAD Audio IIR Coef[%d] = 0X%x",
2762 __func__, idx,
2763 mad_cal->audio_info.iir_coefficients[idx]);
2764 }
2765
2766 /* Beacon */
2767 snd_soc_write(codec, WCD934X_SOC_MAD_BEACON_CTL_8,
2768 mad_cal->beacon_info.rms_omit_samples);
2769 snd_soc_update_bits(codec, WCD934X_SOC_MAD_BEACON_CTL_1,
2770 0x07 << 4, mad_cal->beacon_info.rms_comp_time << 4);
2771 snd_soc_update_bits(codec, WCD934X_SOC_MAD_BEACON_CTL_2, 0x03 << 2,
2772 mad_cal->beacon_info.detection_mechanism << 2);
2773 snd_soc_write(codec, WCD934X_SOC_MAD_BEACON_CTL_7,
2774 mad_cal->beacon_info.rms_diff_threshold & 0x1F);
2775 snd_soc_write(codec, WCD934X_SOC_MAD_BEACON_CTL_5,
2776 mad_cal->beacon_info.rms_threshold_lsb);
2777 snd_soc_write(codec, WCD934X_SOC_MAD_BEACON_CTL_6,
2778 mad_cal->beacon_info.rms_threshold_msb);
2779
2780 for (idx = 0; idx < ARRAY_SIZE(mad_cal->beacon_info.iir_coefficients);
2781 idx++) {
2782 snd_soc_update_bits(codec, WCD934X_SOC_MAD_BEACON_IIR_CTL_PTR,
2783 0x3F, idx);
2784 snd_soc_write(codec, WCD934X_SOC_MAD_BEACON_IIR_CTL_VAL,
2785 mad_cal->beacon_info.iir_coefficients[idx]);
2786 dev_dbg(codec->dev, "%s:MAD Beacon IIR Coef[%d] = 0X%x",
2787 __func__, idx,
2788 mad_cal->beacon_info.iir_coefficients[idx]);
2789 }
2790
2791 /* Ultrasound */
2792 snd_soc_update_bits(codec, WCD934X_SOC_MAD_ULTR_CTL_1,
2793 0x07 << 4,
2794 mad_cal->ultrasound_info.rms_comp_time << 4);
2795 snd_soc_update_bits(codec, WCD934X_SOC_MAD_ULTR_CTL_2, 0x03 << 2,
2796 mad_cal->ultrasound_info.detection_mechanism << 2);
2797 snd_soc_write(codec, WCD934X_SOC_MAD_ULTR_CTL_7,
2798 mad_cal->ultrasound_info.rms_diff_threshold & 0x1F);
2799 snd_soc_write(codec, WCD934X_SOC_MAD_ULTR_CTL_5,
2800 mad_cal->ultrasound_info.rms_threshold_lsb);
2801 snd_soc_write(codec, WCD934X_SOC_MAD_ULTR_CTL_6,
2802 mad_cal->ultrasound_info.rms_threshold_msb);
2803
2804done:
2805 if (!hwdep_cal)
2806 release_firmware(fw);
2807
2808 return ret;
2809}
2810
2811static int __tavil_codec_enable_mad(struct snd_soc_codec *codec, bool enable)
2812{
2813 int rc = 0;
2814
2815 /* Return if CPE INPUT is DEC1 */
2816 if (snd_soc_read(codec, WCD934X_CPE_SS_SVA_CFG) & 0x04) {
2817 dev_dbg(codec->dev, "%s: MAD is bypassed, skip mad %s\n",
2818 __func__, enable ? "enable" : "disable");
2819 return rc;
2820 }
2821
2822 dev_dbg(codec->dev, "%s: enable = %s\n", __func__,
2823 enable ? "enable" : "disable");
2824
2825 if (enable) {
2826 snd_soc_update_bits(codec, WCD934X_SOC_MAD_AUDIO_CTL_2,
2827 0x03, 0x03);
2828 rc = tavil_codec_config_mad(codec);
Xiaoyu Ye1a2d8bd92017-01-31 18:54:15 -08002829 if (rc < 0) {
Banajit Goswamide8271c2017-01-18 00:28:59 -08002830 snd_soc_update_bits(codec, WCD934X_SOC_MAD_AUDIO_CTL_2,
2831 0x03, 0x00);
2832 goto done;
2833 }
2834
2835 /* Turn on MAD clk */
2836 snd_soc_update_bits(codec, WCD934X_CPE_SS_MAD_CTL,
2837 0x01, 0x01);
2838
2839 /* Undo reset for MAD */
2840 snd_soc_update_bits(codec, WCD934X_CPE_SS_MAD_CTL,
2841 0x02, 0x00);
Banajit Goswami1e0e29c2017-01-09 14:21:51 +05302842 snd_soc_update_bits(codec, WCD934X_CODEC_RPM_CLK_MCLK_CFG,
2843 0x04, 0x04);
Banajit Goswamide8271c2017-01-18 00:28:59 -08002844 } else {
2845 snd_soc_update_bits(codec, WCD934X_SOC_MAD_AUDIO_CTL_2,
2846 0x03, 0x00);
2847 /* Reset the MAD block */
2848 snd_soc_update_bits(codec, WCD934X_CPE_SS_MAD_CTL,
2849 0x02, 0x02);
2850 /* Turn off MAD clk */
2851 snd_soc_update_bits(codec, WCD934X_CPE_SS_MAD_CTL,
2852 0x01, 0x00);
Banajit Goswami1e0e29c2017-01-09 14:21:51 +05302853 snd_soc_update_bits(codec, WCD934X_CODEC_RPM_CLK_MCLK_CFG,
2854 0x04, 0x00);
Banajit Goswamide8271c2017-01-18 00:28:59 -08002855 }
2856done:
2857 return rc;
2858}
2859
2860static int tavil_codec_ape_enable_mad(struct snd_soc_dapm_widget *w,
2861 struct snd_kcontrol *kcontrol,
2862 int event)
2863{
2864 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
2865 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
2866 int rc = 0;
2867
2868 switch (event) {
2869 case SND_SOC_DAPM_PRE_PMU:
2870 snd_soc_update_bits(codec, WCD934X_CPE_SS_SVA_CFG, 0x40, 0x40);
2871 rc = __tavil_codec_enable_mad(codec, true);
2872 break;
2873 case SND_SOC_DAPM_PRE_PMD:
2874 snd_soc_update_bits(codec, WCD934X_CPE_SS_SVA_CFG, 0x40, 0x00);
2875 __tavil_codec_enable_mad(codec, false);
2876 break;
2877 }
2878
2879 dev_dbg(tavil->dev, "%s: event = %d\n", __func__, event);
2880 return rc;
2881}
2882
2883static int tavil_codec_cpe_mad_ctl(struct snd_soc_dapm_widget *w,
2884 struct snd_kcontrol *kcontrol, int event)
2885{
2886 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
2887 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
2888 int rc = 0;
2889
2890 switch (event) {
2891 case SND_SOC_DAPM_PRE_PMU:
2892 tavil->mad_switch_cnt++;
2893 if (tavil->mad_switch_cnt != 1)
2894 goto done;
2895
2896 snd_soc_update_bits(codec, WCD934X_CPE_SS_SVA_CFG, 0x20, 0x20);
2897 rc = __tavil_codec_enable_mad(codec, true);
Xiaoyu Ye1a2d8bd92017-01-31 18:54:15 -08002898 if (rc < 0) {
Banajit Goswamide8271c2017-01-18 00:28:59 -08002899 tavil->mad_switch_cnt--;
2900 goto done;
2901 }
2902
2903 break;
2904 case SND_SOC_DAPM_PRE_PMD:
2905 tavil->mad_switch_cnt--;
2906 if (tavil->mad_switch_cnt != 0)
2907 goto done;
2908
2909 snd_soc_update_bits(codec, WCD934X_CPE_SS_SVA_CFG, 0x20, 0x00);
2910 __tavil_codec_enable_mad(codec, false);
2911 break;
2912 }
2913done:
2914 dev_dbg(tavil->dev, "%s: event = %d, mad_switch_cnt = %d\n",
2915 __func__, event, tavil->mad_switch_cnt);
2916 return rc;
2917}
2918
2919static int tavil_get_asrc_mode(struct tavil_priv *tavil, int asrc,
2920 u8 main_sr, u8 mix_sr)
2921{
2922 u8 asrc_output_mode;
2923 int asrc_mode = CONV_88P2K_TO_384K;
2924
2925 if ((asrc < 0) || (asrc >= ASRC_MAX))
2926 return 0;
2927
2928 asrc_output_mode = tavil->asrc_output_mode[asrc];
2929
2930 if (asrc_output_mode) {
2931 /*
2932 * If Mix sample rate is < 96KHz, use 96K to 352.8K
2933 * conversion, or else use 384K to 352.8K conversion
2934 */
2935 if (mix_sr < 5)
2936 asrc_mode = CONV_96K_TO_352P8K;
2937 else
2938 asrc_mode = CONV_384K_TO_352P8K;
2939 } else {
2940 /* Integer main and Fractional mix path */
2941 if (main_sr < 8 && mix_sr > 9) {
2942 asrc_mode = CONV_352P8K_TO_384K;
2943 } else if (main_sr > 8 && mix_sr < 8) {
2944 /* Fractional main and Integer mix path */
2945 if (mix_sr < 5)
2946 asrc_mode = CONV_96K_TO_352P8K;
2947 else
2948 asrc_mode = CONV_384K_TO_352P8K;
2949 } else if (main_sr < 8 && mix_sr < 8) {
2950 /* Integer main and Integer mix path */
2951 asrc_mode = CONV_96K_TO_384K;
2952 }
2953 }
2954
2955 return asrc_mode;
2956}
2957
2958static int tavil_codec_enable_asrc(struct snd_soc_codec *codec,
2959 int asrc_in, int event)
2960{
2961 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
2962 u16 cfg_reg, ctl_reg, clk_reg, asrc_ctl, mix_ctl_reg;
2963 int asrc, ret = 0;
2964 u8 main_sr, mix_sr, asrc_mode = 0;
2965
2966 switch (asrc_in) {
2967 case ASRC_IN_HPHL:
2968 cfg_reg = WCD934X_CDC_RX1_RX_PATH_CFG0;
2969 ctl_reg = WCD934X_CDC_RX1_RX_PATH_CTL;
2970 clk_reg = WCD934X_MIXING_ASRC0_CLK_RST_CTL;
2971 asrc_ctl = WCD934X_MIXING_ASRC0_CTL1;
2972 asrc = ASRC0;
2973 break;
2974 case ASRC_IN_LO1:
2975 cfg_reg = WCD934X_CDC_RX3_RX_PATH_CFG0;
2976 ctl_reg = WCD934X_CDC_RX3_RX_PATH_CTL;
2977 clk_reg = WCD934X_MIXING_ASRC0_CLK_RST_CTL;
2978 asrc_ctl = WCD934X_MIXING_ASRC0_CTL1;
2979 asrc = ASRC0;
2980 break;
2981 case ASRC_IN_HPHR:
2982 cfg_reg = WCD934X_CDC_RX2_RX_PATH_CFG0;
2983 ctl_reg = WCD934X_CDC_RX2_RX_PATH_CTL;
2984 clk_reg = WCD934X_MIXING_ASRC1_CLK_RST_CTL;
2985 asrc_ctl = WCD934X_MIXING_ASRC1_CTL1;
2986 asrc = ASRC1;
2987 break;
2988 case ASRC_IN_LO2:
2989 cfg_reg = WCD934X_CDC_RX4_RX_PATH_CFG0;
2990 ctl_reg = WCD934X_CDC_RX4_RX_PATH_CTL;
2991 clk_reg = WCD934X_MIXING_ASRC1_CLK_RST_CTL;
2992 asrc_ctl = WCD934X_MIXING_ASRC1_CTL1;
2993 asrc = ASRC1;
2994 break;
2995 case ASRC_IN_SPKR1:
2996 cfg_reg = WCD934X_CDC_RX7_RX_PATH_CFG0;
2997 ctl_reg = WCD934X_CDC_RX7_RX_PATH_CTL;
2998 clk_reg = WCD934X_MIXING_ASRC2_CLK_RST_CTL;
2999 asrc_ctl = WCD934X_MIXING_ASRC2_CTL1;
3000 asrc = ASRC2;
3001 break;
3002 case ASRC_IN_SPKR2:
3003 cfg_reg = WCD934X_CDC_RX8_RX_PATH_CFG0;
3004 ctl_reg = WCD934X_CDC_RX8_RX_PATH_CTL;
3005 clk_reg = WCD934X_MIXING_ASRC3_CLK_RST_CTL;
3006 asrc_ctl = WCD934X_MIXING_ASRC3_CTL1;
3007 asrc = ASRC3;
3008 break;
3009 default:
3010 dev_err(codec->dev, "%s: Invalid asrc input :%d\n", __func__,
3011 asrc_in);
3012 ret = -EINVAL;
3013 goto done;
3014 };
3015
3016 switch (event) {
3017 case SND_SOC_DAPM_PRE_PMU:
3018 if (tavil->asrc_users[asrc] == 0) {
3019 snd_soc_update_bits(codec, cfg_reg, 0x80, 0x80);
3020 snd_soc_update_bits(codec, clk_reg, 0x01, 0x01);
3021 main_sr = snd_soc_read(codec, ctl_reg) & 0x0F;
3022 mix_ctl_reg = ctl_reg + 5;
3023 mix_sr = snd_soc_read(codec, mix_ctl_reg) & 0x0F;
3024 asrc_mode = tavil_get_asrc_mode(tavil, asrc,
3025 main_sr, mix_sr);
3026 dev_dbg(codec->dev, "%s: main_sr:%d mix_sr:%d asrc_mode %d\n",
3027 __func__, main_sr, mix_sr, asrc_mode);
3028 snd_soc_update_bits(codec, asrc_ctl, 0x07, asrc_mode);
3029 }
3030 tavil->asrc_users[asrc]++;
3031 break;
3032 case SND_SOC_DAPM_POST_PMD:
3033 tavil->asrc_users[asrc]--;
3034 if (tavil->asrc_users[asrc] <= 0) {
3035 tavil->asrc_users[asrc] = 0;
3036 snd_soc_update_bits(codec, asrc_ctl, 0x07, 0x00);
3037 snd_soc_update_bits(codec, cfg_reg, 0x80, 0x00);
3038 snd_soc_update_bits(codec, clk_reg, 0x01, 0x00);
3039 }
3040 break;
3041 };
3042
3043 dev_dbg(codec->dev, "%s: ASRC%d, users: %d\n",
3044 __func__, asrc, tavil->asrc_users[asrc]);
3045
3046done:
3047 return ret;
3048}
3049
3050static int tavil_codec_enable_asrc_resampler(struct snd_soc_dapm_widget *w,
3051 struct snd_kcontrol *kcontrol,
3052 int event)
3053{
3054 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
3055 int ret = 0;
3056 u8 cfg, asrc_in;
3057
3058 cfg = snd_soc_read(codec, WCD934X_CDC_RX_INP_MUX_SPLINE_ASRC_CFG0);
3059 if (!(cfg & 0xFF)) {
3060 dev_err(codec->dev, "%s: ASRC%u input not selected\n",
3061 __func__, w->shift);
3062 return -EINVAL;
3063 }
3064
3065 switch (w->shift) {
3066 case ASRC0:
3067 asrc_in = ((cfg & 0x03) == 1) ? ASRC_IN_HPHL : ASRC_IN_LO1;
3068 ret = tavil_codec_enable_asrc(codec, asrc_in, event);
3069 break;
3070 case ASRC1:
3071 asrc_in = ((cfg & 0x0C) == 4) ? ASRC_IN_HPHR : ASRC_IN_LO2;
3072 ret = tavil_codec_enable_asrc(codec, asrc_in, event);
3073 break;
3074 case ASRC2:
3075 asrc_in = ((cfg & 0x30) == 0x20) ? ASRC_IN_SPKR1 : ASRC_INVALID;
3076 ret = tavil_codec_enable_asrc(codec, asrc_in, event);
3077 break;
3078 case ASRC3:
3079 asrc_in = ((cfg & 0xC0) == 0x80) ? ASRC_IN_SPKR2 : ASRC_INVALID;
3080 ret = tavil_codec_enable_asrc(codec, asrc_in, event);
3081 break;
3082 default:
3083 dev_err(codec->dev, "%s: Invalid asrc:%u\n", __func__,
3084 w->shift);
3085 ret = -EINVAL;
3086 break;
3087 };
3088
3089 return ret;
3090}
3091
3092static int tavil_enable_native_supply(struct snd_soc_dapm_widget *w,
3093 struct snd_kcontrol *kcontrol, int event)
3094{
3095 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
3096 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
3097
3098 switch (event) {
3099 case SND_SOC_DAPM_PRE_PMU:
3100 if (++tavil->native_clk_users == 1) {
3101 snd_soc_update_bits(codec, WCD934X_CLK_SYS_PLL_ENABLES,
3102 0x01, 0x01);
3103 usleep_range(100, 120);
3104 snd_soc_update_bits(codec, WCD934X_CLK_SYS_MCLK2_PRG1,
3105 0x06, 0x02);
3106 snd_soc_update_bits(codec, WCD934X_CLK_SYS_MCLK2_PRG1,
3107 0x01, 0x01);
3108 snd_soc_update_bits(codec, WCD934X_CODEC_RPM_CLK_GATE,
3109 0x04, 0x00);
3110 usleep_range(30, 50);
3111 snd_soc_update_bits(codec,
3112 WCD934X_CDC_CLK_RST_CTRL_MCLK_CONTROL,
3113 0x02, 0x02);
3114 snd_soc_update_bits(codec,
3115 WCD934X_CDC_CLK_RST_CTRL_FS_CNT_CONTROL,
3116 0x10, 0x10);
3117 }
3118 break;
3119 case SND_SOC_DAPM_PRE_PMD:
3120 if (tavil->native_clk_users &&
3121 (--tavil->native_clk_users == 0)) {
3122 snd_soc_update_bits(codec,
3123 WCD934X_CDC_CLK_RST_CTRL_FS_CNT_CONTROL,
3124 0x10, 0x00);
3125 snd_soc_update_bits(codec,
3126 WCD934X_CDC_CLK_RST_CTRL_MCLK_CONTROL,
3127 0x02, 0x00);
3128 snd_soc_update_bits(codec, WCD934X_CODEC_RPM_CLK_GATE,
3129 0x04, 0x04);
3130 snd_soc_update_bits(codec, WCD934X_CLK_SYS_MCLK2_PRG1,
3131 0x01, 0x00);
3132 snd_soc_update_bits(codec, WCD934X_CLK_SYS_MCLK2_PRG1,
3133 0x06, 0x00);
3134 snd_soc_update_bits(codec, WCD934X_CLK_SYS_PLL_ENABLES,
3135 0x01, 0x00);
3136 }
3137 break;
3138 }
3139
3140 dev_dbg(codec->dev, "%s: native_clk_users: %d, event: %d\n",
3141 __func__, tavil->native_clk_users, event);
3142
3143 return 0;
3144}
3145
3146static void tavil_codec_hphdelay_lutbypass(struct snd_soc_codec *codec,
3147 u16 interp_idx, int event)
3148{
3149 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
3150 u8 hph_dly_mask;
3151 u16 hph_lut_bypass_reg = 0;
3152 u16 hph_comp_ctrl7 = 0;
3153
3154
3155 switch (interp_idx) {
3156 case INTERP_HPHL:
3157 hph_dly_mask = 1;
3158 hph_lut_bypass_reg = WCD934X_CDC_TOP_HPHL_COMP_LUT;
3159 hph_comp_ctrl7 = WCD934X_CDC_COMPANDER1_CTL7;
3160 break;
3161 case INTERP_HPHR:
3162 hph_dly_mask = 2;
3163 hph_lut_bypass_reg = WCD934X_CDC_TOP_HPHR_COMP_LUT;
3164 hph_comp_ctrl7 = WCD934X_CDC_COMPANDER2_CTL7;
3165 break;
3166 default:
3167 break;
3168 }
3169
3170 if (hph_lut_bypass_reg && SND_SOC_DAPM_EVENT_ON(event)) {
3171 snd_soc_update_bits(codec, WCD934X_CDC_CLSH_TEST0,
3172 hph_dly_mask, 0x0);
3173 snd_soc_update_bits(codec, hph_lut_bypass_reg, 0x80, 0x80);
3174 if (tavil->hph_mode == CLS_H_ULP)
3175 snd_soc_update_bits(codec, hph_comp_ctrl7, 0x20, 0x20);
3176 }
3177
3178 if (hph_lut_bypass_reg && SND_SOC_DAPM_EVENT_OFF(event)) {
3179 snd_soc_update_bits(codec, WCD934X_CDC_CLSH_TEST0,
3180 hph_dly_mask, hph_dly_mask);
3181 snd_soc_update_bits(codec, hph_lut_bypass_reg, 0x80, 0x00);
3182 snd_soc_update_bits(codec, hph_comp_ctrl7, 0x20, 0x0);
3183 }
3184}
3185
3186static void tavil_codec_hd2_control(struct tavil_priv *priv,
3187 u16 interp_idx, int event)
3188{
3189 u16 hd2_scale_reg;
3190 u16 hd2_enable_reg = 0;
3191 struct snd_soc_codec *codec = priv->codec;
3192
3193 if (TAVIL_IS_1_1(priv->wcd9xxx))
3194 return;
3195
3196 switch (interp_idx) {
3197 case INTERP_HPHL:
3198 hd2_scale_reg = WCD934X_CDC_RX1_RX_PATH_SEC3;
3199 hd2_enable_reg = WCD934X_CDC_RX1_RX_PATH_CFG0;
3200 break;
3201 case INTERP_HPHR:
3202 hd2_scale_reg = WCD934X_CDC_RX2_RX_PATH_SEC3;
3203 hd2_enable_reg = WCD934X_CDC_RX2_RX_PATH_CFG0;
3204 break;
3205 }
3206
3207 if (hd2_enable_reg && SND_SOC_DAPM_EVENT_ON(event)) {
3208 snd_soc_update_bits(codec, hd2_scale_reg, 0x3C, 0x14);
3209 snd_soc_update_bits(codec, hd2_enable_reg, 0x04, 0x04);
3210 }
3211
3212 if (hd2_enable_reg && SND_SOC_DAPM_EVENT_OFF(event)) {
3213 snd_soc_update_bits(codec, hd2_enable_reg, 0x04, 0x00);
3214 snd_soc_update_bits(codec, hd2_scale_reg, 0x3C, 0x00);
3215 }
3216}
3217
3218static int tavil_codec_config_ear_spkr_gain(struct snd_soc_codec *codec,
3219 int event, int gain_reg)
3220{
3221 int comp_gain_offset, val;
3222 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
3223
3224 switch (tavil->swr.spkr_mode) {
3225 /* Compander gain in SPKR_MODE1 case is 12 dB */
3226 case WCD934X_SPKR_MODE_1:
3227 comp_gain_offset = -12;
3228 break;
3229 /* Default case compander gain is 15 dB */
3230 default:
3231 comp_gain_offset = -15;
3232 break;
3233 }
3234
3235 switch (event) {
3236 case SND_SOC_DAPM_POST_PMU:
3237 /* Apply ear spkr gain only if compander is enabled */
3238 if (tavil->comp_enabled[COMPANDER_7] &&
3239 (gain_reg == WCD934X_CDC_RX7_RX_VOL_CTL ||
3240 gain_reg == WCD934X_CDC_RX7_RX_VOL_MIX_CTL) &&
3241 (tavil->ear_spkr_gain != 0)) {
3242 /* For example, val is -8(-12+5-1) for 4dB of gain */
3243 val = comp_gain_offset + tavil->ear_spkr_gain - 1;
3244 snd_soc_write(codec, gain_reg, val);
3245
3246 dev_dbg(codec->dev, "%s: RX7 Volume %d dB\n",
3247 __func__, val);
3248 }
3249 break;
3250 case SND_SOC_DAPM_POST_PMD:
3251 /*
3252 * Reset RX7 volume to 0 dB if compander is enabled and
3253 * ear_spkr_gain is non-zero.
3254 */
3255 if (tavil->comp_enabled[COMPANDER_7] &&
3256 (gain_reg == WCD934X_CDC_RX7_RX_VOL_CTL ||
3257 gain_reg == WCD934X_CDC_RX7_RX_VOL_MIX_CTL) &&
3258 (tavil->ear_spkr_gain != 0)) {
3259 snd_soc_write(codec, gain_reg, 0x0);
3260
3261 dev_dbg(codec->dev, "%s: Reset RX7 Volume to 0 dB\n",
3262 __func__);
3263 }
3264 break;
3265 }
3266
3267 return 0;
3268}
3269
3270static int tavil_config_compander(struct snd_soc_codec *codec, int interp_n,
3271 int event)
3272{
3273 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
3274 int comp;
3275 u16 comp_ctl0_reg, rx_path_cfg0_reg;
3276
3277 /* EAR does not have compander */
3278 if (!interp_n)
3279 return 0;
3280
3281 comp = interp_n - 1;
3282 dev_dbg(codec->dev, "%s: event %d compander %d, enabled %d\n",
3283 __func__, event, comp + 1, tavil->comp_enabled[comp]);
3284
3285 if (!tavil->comp_enabled[comp])
3286 return 0;
3287
3288 comp_ctl0_reg = WCD934X_CDC_COMPANDER1_CTL0 + (comp * 8);
3289 rx_path_cfg0_reg = WCD934X_CDC_RX1_RX_PATH_CFG0 + (comp * 20);
3290
3291 if (SND_SOC_DAPM_EVENT_ON(event)) {
3292 /* Enable Compander Clock */
3293 snd_soc_update_bits(codec, comp_ctl0_reg, 0x01, 0x01);
3294 snd_soc_update_bits(codec, comp_ctl0_reg, 0x02, 0x02);
3295 snd_soc_update_bits(codec, comp_ctl0_reg, 0x02, 0x00);
3296 snd_soc_update_bits(codec, rx_path_cfg0_reg, 0x02, 0x02);
3297 }
3298
3299 if (SND_SOC_DAPM_EVENT_OFF(event)) {
3300 snd_soc_update_bits(codec, rx_path_cfg0_reg, 0x02, 0x00);
3301 snd_soc_update_bits(codec, comp_ctl0_reg, 0x04, 0x04);
3302 snd_soc_update_bits(codec, comp_ctl0_reg, 0x02, 0x02);
3303 snd_soc_update_bits(codec, comp_ctl0_reg, 0x02, 0x00);
3304 snd_soc_update_bits(codec, comp_ctl0_reg, 0x01, 0x00);
3305 snd_soc_update_bits(codec, comp_ctl0_reg, 0x04, 0x00);
3306 }
3307
3308 return 0;
3309}
3310
3311static void tavil_codec_idle_detect_control(struct snd_soc_codec *codec,
3312 int interp, int event)
3313{
3314 int reg = 0, mask, val;
3315 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
3316
3317 if (!tavil->idle_det_cfg.hph_idle_detect_en)
3318 return;
3319
3320 if (interp == INTERP_HPHL) {
3321 reg = WCD934X_CDC_RX_IDLE_DET_PATH_CTL;
3322 mask = 0x01;
3323 val = 0x01;
3324 }
3325 if (interp == INTERP_HPHR) {
3326 reg = WCD934X_CDC_RX_IDLE_DET_PATH_CTL;
3327 mask = 0x02;
3328 val = 0x02;
3329 }
3330
3331 if (reg && SND_SOC_DAPM_EVENT_ON(event))
3332 snd_soc_update_bits(codec, reg, mask, val);
3333
3334 if (reg && SND_SOC_DAPM_EVENT_OFF(event)) {
3335 snd_soc_update_bits(codec, reg, mask, 0x00);
3336 tavil->idle_det_cfg.hph_idle_thr = 0;
3337 snd_soc_write(codec, WCD934X_CDC_RX_IDLE_DET_CFG3, 0x0);
3338 }
3339}
3340
3341/**
3342 * tavil_codec_enable_interp_clk - Enable main path Interpolator
3343 * clock.
3344 *
3345 * @codec: Codec instance
3346 * @event: Indicates speaker path gain offset value
3347 * @intp_idx: Interpolator index
3348 * Returns number of main clock users
3349 */
3350int tavil_codec_enable_interp_clk(struct snd_soc_codec *codec,
3351 int event, int interp_idx)
3352{
3353 struct tavil_priv *tavil;
3354 u16 main_reg;
3355
3356 if (!codec) {
3357 pr_err("%s: codec is NULL\n", __func__);
3358 return -EINVAL;
3359 }
3360
3361 tavil = snd_soc_codec_get_drvdata(codec);
3362 main_reg = WCD934X_CDC_RX0_RX_PATH_CTL + (interp_idx * 20);
3363
3364 if (SND_SOC_DAPM_EVENT_ON(event)) {
3365 if (tavil->main_clk_users[interp_idx] == 0) {
3366 /* Main path PGA mute enable */
3367 snd_soc_update_bits(codec, main_reg, 0x10, 0x10);
3368 /* Clk enable */
3369 snd_soc_update_bits(codec, main_reg, 0x20, 0x20);
3370 tavil_codec_idle_detect_control(codec, interp_idx,
3371 event);
3372 tavil_codec_hd2_control(tavil, interp_idx, event);
3373 tavil_codec_hphdelay_lutbypass(codec, interp_idx,
3374 event);
3375 tavil_config_compander(codec, interp_idx, event);
3376 }
3377 tavil->main_clk_users[interp_idx]++;
3378 }
3379
3380 if (SND_SOC_DAPM_EVENT_OFF(event)) {
3381 tavil->main_clk_users[interp_idx]--;
3382 if (tavil->main_clk_users[interp_idx] <= 0) {
3383 tavil->main_clk_users[interp_idx] = 0;
3384 tavil_config_compander(codec, interp_idx, event);
3385 tavil_codec_hphdelay_lutbypass(codec, interp_idx,
3386 event);
3387 tavil_codec_hd2_control(tavil, interp_idx, event);
3388 tavil_codec_idle_detect_control(codec, interp_idx,
3389 event);
3390 /* Clk Disable */
3391 snd_soc_update_bits(codec, main_reg, 0x20, 0x00);
3392 /* Reset enable and disable */
3393 snd_soc_update_bits(codec, main_reg, 0x40, 0x40);
3394 snd_soc_update_bits(codec, main_reg, 0x40, 0x00);
3395 /* Reset rate to 48K*/
3396 snd_soc_update_bits(codec, main_reg, 0x0F, 0x04);
3397 }
3398 }
3399
3400 dev_dbg(codec->dev, "%s event %d main_clk_users %d\n",
3401 __func__, event, tavil->main_clk_users[interp_idx]);
3402
3403 return tavil->main_clk_users[interp_idx];
3404}
3405EXPORT_SYMBOL(tavil_codec_enable_interp_clk);
3406
Meng Wangf45a20d2017-01-18 09:51:58 +08003407static int tavil_anc_out_switch_cb(struct snd_soc_dapm_widget *w,
3408 struct snd_kcontrol *kcontrol, int event)
3409{
3410 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
3411
3412 tavil_codec_enable_interp_clk(codec, event, w->shift);
3413
3414 return 0;
3415}
Banajit Goswamide8271c2017-01-18 00:28:59 -08003416static int tavil_codec_set_idle_detect_thr(struct snd_soc_codec *codec,
3417 int interp, int path_type)
3418{
3419 int port_id[4] = { 0, 0, 0, 0 };
3420 int *port_ptr, num_ports;
3421 int bit_width = 0, i;
3422 int mux_reg, mux_reg_val;
3423 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
3424 int dai_id, idle_thr;
3425
3426 if ((interp != INTERP_HPHL) && (interp != INTERP_HPHR))
3427 return 0;
3428
3429 if (!tavil->idle_det_cfg.hph_idle_detect_en)
3430 return 0;
3431
3432 port_ptr = &port_id[0];
3433 num_ports = 0;
3434
3435 /*
3436 * Read interpolator MUX input registers and find
3437 * which slimbus port is connected and store the port
3438 * numbers in port_id array.
3439 */
3440 if (path_type == INTERP_MIX_PATH) {
3441 mux_reg = WCD934X_CDC_RX_INP_MUX_RX_INT1_CFG1 +
3442 2 * (interp - 1);
3443 mux_reg_val = snd_soc_read(codec, mux_reg) & 0x0f;
3444
3445 if ((mux_reg_val >= INTn_2_INP_SEL_RX0) &&
3446 (mux_reg_val < INTn_2_INP_SEL_PROXIMITY)) {
3447 *port_ptr++ = mux_reg_val +
3448 WCD934X_RX_PORT_START_NUMBER - 1;
3449 num_ports++;
3450 }
3451 }
3452
3453 if (path_type == INTERP_MAIN_PATH) {
3454 mux_reg = WCD934X_CDC_RX_INP_MUX_RX_INT1_CFG0 +
3455 2 * (interp - 1);
3456 mux_reg_val = snd_soc_read(codec, mux_reg) & 0x0f;
3457 i = WCD934X_INTERP_MUX_NUM_INPUTS;
3458
3459 while (i) {
3460 if ((mux_reg_val >= INTn_1_INP_SEL_RX0) &&
3461 (mux_reg_val <= INTn_1_INP_SEL_RX7)) {
3462 *port_ptr++ = mux_reg_val +
3463 WCD934X_RX_PORT_START_NUMBER -
3464 INTn_1_INP_SEL_RX0;
3465 num_ports++;
3466 }
3467 mux_reg_val = (snd_soc_read(codec, mux_reg) &
3468 0xf0) >> 4;
3469 mux_reg += 1;
3470 i--;
3471 }
3472 }
3473
3474 dev_dbg(codec->dev, "%s: num_ports: %d, ports[%d %d %d %d]\n",
3475 __func__, num_ports, port_id[0], port_id[1],
3476 port_id[2], port_id[3]);
3477
3478 i = 0;
3479 while (num_ports) {
3480 dai_id = tavil_find_playback_dai_id_for_port(port_id[i++],
3481 tavil);
3482
3483 if ((dai_id >= 0) && (dai_id < NUM_CODEC_DAIS)) {
3484 dev_dbg(codec->dev, "%s: dai_id: %d bit_width: %d\n",
3485 __func__, dai_id,
3486 tavil->dai[dai_id].bit_width);
3487
3488 if (tavil->dai[dai_id].bit_width > bit_width)
3489 bit_width = tavil->dai[dai_id].bit_width;
3490 }
3491
3492 num_ports--;
3493 }
3494
3495 switch (bit_width) {
3496 case 16:
3497 idle_thr = 0xff; /* F16 */
3498 break;
3499 case 24:
3500 case 32:
3501 idle_thr = 0x03; /* F22 */
3502 break;
3503 default:
3504 idle_thr = 0x00;
3505 break;
3506 }
3507
3508 dev_dbg(codec->dev, "%s: (new) idle_thr: %d, (cur) idle_thr: %d\n",
3509 __func__, idle_thr, tavil->idle_det_cfg.hph_idle_thr);
3510
3511 if ((tavil->idle_det_cfg.hph_idle_thr == 0) ||
3512 (idle_thr < tavil->idle_det_cfg.hph_idle_thr)) {
3513 snd_soc_write(codec, WCD934X_CDC_RX_IDLE_DET_CFG3, idle_thr);
3514 tavil->idle_det_cfg.hph_idle_thr = idle_thr;
3515 }
3516
3517 return 0;
3518}
3519
3520static int tavil_codec_enable_mix_path(struct snd_soc_dapm_widget *w,
3521 struct snd_kcontrol *kcontrol,
3522 int event)
3523{
3524 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
3525 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
3526 u16 gain_reg, mix_reg;
3527 int offset_val = 0;
3528 int val = 0;
3529
3530 if (w->shift >= WCD934X_NUM_INTERPOLATORS ||
3531 w->shift == INTERP_LO3_NA || w->shift == INTERP_LO4_NA) {
3532 dev_err(codec->dev, "%s: Invalid Interpolator value %d for name %s\n",
3533 __func__, w->shift, w->name);
3534 return -EINVAL;
3535 };
3536
3537 gain_reg = WCD934X_CDC_RX0_RX_VOL_MIX_CTL +
3538 (w->shift * WCD934X_RX_PATH_CTL_OFFSET);
3539 mix_reg = WCD934X_CDC_RX0_RX_PATH_MIX_CTL +
3540 (w->shift * WCD934X_RX_PATH_CTL_OFFSET);
3541
3542 if (w->shift == INTERP_SPKR1 || w->shift == INTERP_SPKR2)
3543 __tavil_codec_enable_swr(w, event);
3544
3545 switch (event) {
3546 case SND_SOC_DAPM_PRE_PMU:
3547 tavil_codec_set_idle_detect_thr(codec, w->shift,
3548 INTERP_MIX_PATH);
3549 tavil_codec_enable_interp_clk(codec, event, w->shift);
3550 /* Clk enable */
3551 snd_soc_update_bits(codec, mix_reg, 0x20, 0x20);
3552 break;
3553 case SND_SOC_DAPM_POST_PMU:
3554 if ((tavil->swr.spkr_gain_offset ==
3555 WCD934X_RX_GAIN_OFFSET_M1P5_DB) &&
3556 (tavil->comp_enabled[COMPANDER_7] ||
3557 tavil->comp_enabled[COMPANDER_8]) &&
3558 (gain_reg == WCD934X_CDC_RX7_RX_VOL_MIX_CTL ||
3559 gain_reg == WCD934X_CDC_RX8_RX_VOL_MIX_CTL)) {
3560 snd_soc_update_bits(codec, WCD934X_CDC_RX7_RX_PATH_SEC1,
3561 0x01, 0x01);
3562 snd_soc_update_bits(codec,
3563 WCD934X_CDC_RX7_RX_PATH_MIX_SEC0,
3564 0x01, 0x01);
3565 snd_soc_update_bits(codec, WCD934X_CDC_RX8_RX_PATH_SEC1,
3566 0x01, 0x01);
3567 snd_soc_update_bits(codec,
3568 WCD934X_CDC_RX8_RX_PATH_MIX_SEC0,
3569 0x01, 0x01);
3570 offset_val = -2;
3571 }
3572 val = snd_soc_read(codec, gain_reg);
3573 val += offset_val;
3574 snd_soc_write(codec, gain_reg, val);
3575 tavil_codec_config_ear_spkr_gain(codec, event, gain_reg);
3576 break;
3577 case SND_SOC_DAPM_POST_PMD:
3578 /* Clk Disable */
3579 snd_soc_update_bits(codec, mix_reg, 0x20, 0x00);
3580 tavil_codec_enable_interp_clk(codec, event, w->shift);
3581 /* Reset enable and disable */
3582 snd_soc_update_bits(codec, mix_reg, 0x40, 0x40);
3583 snd_soc_update_bits(codec, mix_reg, 0x40, 0x00);
3584
3585 if ((tavil->swr.spkr_gain_offset ==
3586 WCD934X_RX_GAIN_OFFSET_M1P5_DB) &&
3587 (tavil->comp_enabled[COMPANDER_7] ||
3588 tavil->comp_enabled[COMPANDER_8]) &&
3589 (gain_reg == WCD934X_CDC_RX7_RX_VOL_MIX_CTL ||
3590 gain_reg == WCD934X_CDC_RX8_RX_VOL_MIX_CTL)) {
3591 snd_soc_update_bits(codec, WCD934X_CDC_RX7_RX_PATH_SEC1,
3592 0x01, 0x00);
3593 snd_soc_update_bits(codec,
3594 WCD934X_CDC_RX7_RX_PATH_MIX_SEC0,
3595 0x01, 0x00);
3596 snd_soc_update_bits(codec, WCD934X_CDC_RX8_RX_PATH_SEC1,
3597 0x01, 0x00);
3598 snd_soc_update_bits(codec,
3599 WCD934X_CDC_RX8_RX_PATH_MIX_SEC0,
3600 0x01, 0x00);
3601 offset_val = 2;
3602 val = snd_soc_read(codec, gain_reg);
3603 val += offset_val;
3604 snd_soc_write(codec, gain_reg, val);
3605 }
3606 tavil_codec_config_ear_spkr_gain(codec, event, gain_reg);
3607 break;
3608 };
3609 dev_dbg(codec->dev, "%s event %d name %s\n", __func__, event, w->name);
3610
3611 return 0;
3612}
3613
3614/**
3615 * tavil_get_dsd_config - Get pointer to dsd config structure
3616 *
3617 * @codec: pointer to snd_soc_codec structure
3618 *
3619 * Returns pointer to tavil_dsd_config structure
3620 */
3621struct tavil_dsd_config *tavil_get_dsd_config(struct snd_soc_codec *codec)
3622{
3623 struct tavil_priv *tavil;
3624
3625 if (!codec)
3626 return NULL;
3627
3628 tavil = snd_soc_codec_get_drvdata(codec);
3629
3630 if (!tavil)
3631 return NULL;
3632
3633 return tavil->dsd_config;
3634}
3635EXPORT_SYMBOL(tavil_get_dsd_config);
3636
3637static int tavil_codec_enable_main_path(struct snd_soc_dapm_widget *w,
3638 struct snd_kcontrol *kcontrol,
3639 int event)
3640{
3641 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
3642 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
3643 u16 gain_reg;
3644 u16 reg;
3645 int val;
3646 int offset_val = 0;
3647
3648 dev_dbg(codec->dev, "%s %d %s\n", __func__, event, w->name);
3649
3650 if (w->shift >= WCD934X_NUM_INTERPOLATORS ||
3651 w->shift == INTERP_LO3_NA || w->shift == INTERP_LO4_NA) {
3652 dev_err(codec->dev, "%s: Invalid Interpolator value %d for name %s\n",
3653 __func__, w->shift, w->name);
3654 return -EINVAL;
3655 };
3656
3657 reg = WCD934X_CDC_RX0_RX_PATH_CTL + (w->shift *
3658 WCD934X_RX_PATH_CTL_OFFSET);
3659 gain_reg = WCD934X_CDC_RX0_RX_VOL_CTL + (w->shift *
3660 WCD934X_RX_PATH_CTL_OFFSET);
3661
3662 switch (event) {
3663 case SND_SOC_DAPM_PRE_PMU:
3664 tavil_codec_set_idle_detect_thr(codec, w->shift,
3665 INTERP_MAIN_PATH);
3666 tavil_codec_enable_interp_clk(codec, event, w->shift);
3667 break;
3668 case SND_SOC_DAPM_POST_PMU:
3669 /* apply gain after int clk is enabled */
3670 if ((tavil->swr.spkr_gain_offset ==
3671 WCD934X_RX_GAIN_OFFSET_M1P5_DB) &&
3672 (tavil->comp_enabled[COMPANDER_7] ||
3673 tavil->comp_enabled[COMPANDER_8]) &&
3674 (gain_reg == WCD934X_CDC_RX7_RX_VOL_CTL ||
3675 gain_reg == WCD934X_CDC_RX8_RX_VOL_CTL)) {
3676 snd_soc_update_bits(codec, WCD934X_CDC_RX7_RX_PATH_SEC1,
3677 0x01, 0x01);
3678 snd_soc_update_bits(codec,
3679 WCD934X_CDC_RX7_RX_PATH_MIX_SEC0,
3680 0x01, 0x01);
3681 snd_soc_update_bits(codec, WCD934X_CDC_RX8_RX_PATH_SEC1,
3682 0x01, 0x01);
3683 snd_soc_update_bits(codec,
3684 WCD934X_CDC_RX8_RX_PATH_MIX_SEC0,
3685 0x01, 0x01);
3686 offset_val = -2;
3687 }
3688 val = snd_soc_read(codec, gain_reg);
3689 val += offset_val;
3690 snd_soc_write(codec, gain_reg, val);
3691 tavil_codec_config_ear_spkr_gain(codec, event, gain_reg);
3692 break;
3693 case SND_SOC_DAPM_POST_PMD:
3694 tavil_codec_enable_interp_clk(codec, event, w->shift);
3695
3696 if ((tavil->swr.spkr_gain_offset ==
3697 WCD934X_RX_GAIN_OFFSET_M1P5_DB) &&
3698 (tavil->comp_enabled[COMPANDER_7] ||
3699 tavil->comp_enabled[COMPANDER_8]) &&
3700 (gain_reg == WCD934X_CDC_RX7_RX_VOL_CTL ||
3701 gain_reg == WCD934X_CDC_RX8_RX_VOL_CTL)) {
3702 snd_soc_update_bits(codec, WCD934X_CDC_RX7_RX_PATH_SEC1,
3703 0x01, 0x00);
3704 snd_soc_update_bits(codec,
3705 WCD934X_CDC_RX7_RX_PATH_MIX_SEC0,
3706 0x01, 0x00);
3707 snd_soc_update_bits(codec, WCD934X_CDC_RX8_RX_PATH_SEC1,
3708 0x01, 0x00);
3709 snd_soc_update_bits(codec,
3710 WCD934X_CDC_RX8_RX_PATH_MIX_SEC0,
3711 0x01, 0x00);
3712 offset_val = 2;
3713 val = snd_soc_read(codec, gain_reg);
3714 val += offset_val;
3715 snd_soc_write(codec, gain_reg, val);
3716 }
3717 tavil_codec_config_ear_spkr_gain(codec, event, gain_reg);
3718 break;
3719 };
3720
3721 return 0;
3722}
3723
3724static int tavil_codec_set_iir_gain(struct snd_soc_dapm_widget *w,
3725 struct snd_kcontrol *kcontrol, int event)
3726{
3727 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
3728
3729 dev_dbg(codec->dev, "%s: event = %d\n", __func__, event);
3730
3731 switch (event) {
3732 case SND_SOC_DAPM_POST_PMU: /* fall through */
3733 case SND_SOC_DAPM_PRE_PMD:
3734 if (strnstr(w->name, "IIR0", sizeof("IIR0"))) {
3735 snd_soc_write(codec,
3736 WCD934X_CDC_SIDETONE_IIR0_IIR_GAIN_B1_CTL,
3737 snd_soc_read(codec,
3738 WCD934X_CDC_SIDETONE_IIR0_IIR_GAIN_B1_CTL));
3739 snd_soc_write(codec,
3740 WCD934X_CDC_SIDETONE_IIR0_IIR_GAIN_B2_CTL,
3741 snd_soc_read(codec,
3742 WCD934X_CDC_SIDETONE_IIR0_IIR_GAIN_B2_CTL));
3743 snd_soc_write(codec,
3744 WCD934X_CDC_SIDETONE_IIR0_IIR_GAIN_B3_CTL,
3745 snd_soc_read(codec,
3746 WCD934X_CDC_SIDETONE_IIR0_IIR_GAIN_B3_CTL));
3747 snd_soc_write(codec,
3748 WCD934X_CDC_SIDETONE_IIR0_IIR_GAIN_B4_CTL,
3749 snd_soc_read(codec,
3750 WCD934X_CDC_SIDETONE_IIR0_IIR_GAIN_B4_CTL));
3751 } else {
3752 snd_soc_write(codec,
3753 WCD934X_CDC_SIDETONE_IIR1_IIR_GAIN_B1_CTL,
3754 snd_soc_read(codec,
3755 WCD934X_CDC_SIDETONE_IIR1_IIR_GAIN_B1_CTL));
3756 snd_soc_write(codec,
3757 WCD934X_CDC_SIDETONE_IIR1_IIR_GAIN_B2_CTL,
3758 snd_soc_read(codec,
3759 WCD934X_CDC_SIDETONE_IIR1_IIR_GAIN_B2_CTL));
3760 snd_soc_write(codec,
3761 WCD934X_CDC_SIDETONE_IIR1_IIR_GAIN_B3_CTL,
3762 snd_soc_read(codec,
3763 WCD934X_CDC_SIDETONE_IIR1_IIR_GAIN_B3_CTL));
3764 }
3765 break;
3766 }
3767 return 0;
3768}
3769
3770static int tavil_codec_find_amic_input(struct snd_soc_codec *codec,
3771 int adc_mux_n)
3772{
3773 u16 mask, shift, adc_mux_in_reg;
3774 u16 amic_mux_sel_reg;
3775 bool is_amic;
3776
3777 if (adc_mux_n < 0 || adc_mux_n > WCD934X_MAX_VALID_ADC_MUX ||
3778 adc_mux_n == WCD934X_INVALID_ADC_MUX)
3779 return 0;
3780
3781 if (adc_mux_n < 3) {
3782 adc_mux_in_reg = WCD934X_CDC_TX_INP_MUX_ADC_MUX0_CFG1 +
3783 adc_mux_n;
3784 mask = 0x03;
3785 shift = 0;
3786 amic_mux_sel_reg = WCD934X_CDC_TX_INP_MUX_ADC_MUX0_CFG0 +
3787 2 * adc_mux_n;
3788 } else if (adc_mux_n < 4) {
3789 adc_mux_in_reg = WCD934X_CDC_TX_INP_MUX_ADC_MUX3_CFG1;
3790 mask = 0x03;
3791 shift = 0;
3792 amic_mux_sel_reg = WCD934X_CDC_TX_INP_MUX_ADC_MUX0_CFG0 +
3793 2 * adc_mux_n;
3794 } else if (adc_mux_n < 7) {
3795 adc_mux_in_reg = WCD934X_CDC_TX_INP_MUX_ADC_MUX0_CFG1 +
3796 (adc_mux_n - 4);
3797 mask = 0x0C;
3798 shift = 2;
3799 amic_mux_sel_reg = WCD934X_CDC_TX_INP_MUX_ADC_MUX4_CFG0 +
3800 adc_mux_n - 4;
3801 } else if (adc_mux_n < 8) {
3802 adc_mux_in_reg = WCD934X_CDC_TX_INP_MUX_ADC_MUX3_CFG1;
3803 mask = 0x0C;
3804 shift = 2;
3805 amic_mux_sel_reg = WCD934X_CDC_TX_INP_MUX_ADC_MUX4_CFG0 +
3806 adc_mux_n - 4;
3807 } else if (adc_mux_n < 12) {
3808 adc_mux_in_reg = WCD934X_CDC_TX_INP_MUX_ADC_MUX0_CFG1 +
3809 ((adc_mux_n == 8) ? (adc_mux_n - 8) :
3810 (adc_mux_n - 9));
3811 mask = 0x30;
3812 shift = 4;
3813 amic_mux_sel_reg = WCD934X_CDC_TX_INP_MUX_ADC_MUX4_CFG0 +
3814 adc_mux_n - 4;
3815 } else if (adc_mux_n < 13) {
3816 adc_mux_in_reg = WCD934X_CDC_TX_INP_MUX_ADC_MUX3_CFG1;
3817 mask = 0x30;
3818 shift = 4;
3819 amic_mux_sel_reg = WCD934X_CDC_TX_INP_MUX_ADC_MUX4_CFG0 +
3820 adc_mux_n - 4;
3821 } else {
3822 adc_mux_in_reg = WCD934X_CDC_TX_INP_MUX_ADC_MUX0_CFG1;
3823 mask = 0xC0;
3824 shift = 6;
3825 amic_mux_sel_reg = WCD934X_CDC_TX_INP_MUX_ADC_MUX4_CFG0 +
3826 adc_mux_n - 4;
3827 }
3828
3829 is_amic = (((snd_soc_read(codec, adc_mux_in_reg) & mask) >> shift)
3830 == 1);
3831 if (!is_amic)
3832 return 0;
3833
3834 return snd_soc_read(codec, amic_mux_sel_reg) & 0x07;
3835}
3836
3837static void tavil_codec_set_tx_hold(struct snd_soc_codec *codec,
3838 u16 amic_reg, bool set)
3839{
3840 u8 mask = 0x20;
3841 u8 val;
3842
3843 if (amic_reg == WCD934X_ANA_AMIC1 ||
3844 amic_reg == WCD934X_ANA_AMIC3)
3845 mask = 0x40;
3846
3847 val = set ? mask : 0x00;
3848
3849 switch (amic_reg) {
3850 case WCD934X_ANA_AMIC1:
3851 case WCD934X_ANA_AMIC2:
3852 snd_soc_update_bits(codec, WCD934X_ANA_AMIC2, mask, val);
3853 break;
3854 case WCD934X_ANA_AMIC3:
3855 case WCD934X_ANA_AMIC4:
3856 snd_soc_update_bits(codec, WCD934X_ANA_AMIC4, mask, val);
3857 break;
3858 default:
3859 dev_dbg(codec->dev, "%s: invalid amic: %d\n",
3860 __func__, amic_reg);
3861 break;
3862 }
3863}
3864
3865static int tavil_codec_tx_adc_cfg(struct snd_soc_dapm_widget *w,
3866 struct snd_kcontrol *kcontrol, int event)
3867{
3868 int adc_mux_n = w->shift;
3869 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
Meng Wangf45a20d2017-01-18 09:51:58 +08003870 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
Banajit Goswamide8271c2017-01-18 00:28:59 -08003871 int amic_n;
Banajit Goswamide8271c2017-01-18 00:28:59 -08003872
3873 dev_dbg(codec->dev, "%s: event: %d\n", __func__, event);
3874
3875 switch (event) {
3876 case SND_SOC_DAPM_POST_PMU:
3877 amic_n = tavil_codec_find_amic_input(codec, adc_mux_n);
3878 if (amic_n) {
Meng Wangf45a20d2017-01-18 09:51:58 +08003879 /*
3880 * Prevent ANC Rx pop by leaving Tx FE in HOLD
3881 * state until PA is up. Track AMIC being used
3882 * so we can release the HOLD later.
3883 */
3884 set_bit(ANC_MIC_AMIC1 + amic_n - 1,
3885 &tavil->status_mask);
Banajit Goswamide8271c2017-01-18 00:28:59 -08003886 }
3887 break;
3888 default:
3889 break;
3890 }
3891
3892 return 0;
3893}
3894
3895static u16 tavil_codec_get_amic_pwlvl_reg(struct snd_soc_codec *codec, int amic)
3896{
3897 u16 pwr_level_reg = 0;
3898
3899 switch (amic) {
3900 case 1:
3901 case 2:
3902 pwr_level_reg = WCD934X_ANA_AMIC1;
3903 break;
3904
3905 case 3:
3906 case 4:
3907 pwr_level_reg = WCD934X_ANA_AMIC3;
3908 break;
3909 default:
3910 dev_dbg(codec->dev, "%s: invalid amic: %d\n",
3911 __func__, amic);
3912 break;
3913 }
3914
3915 return pwr_level_reg;
3916}
3917
3918#define TX_HPF_CUT_OFF_FREQ_MASK 0x60
3919#define CF_MIN_3DB_4HZ 0x0
3920#define CF_MIN_3DB_75HZ 0x1
3921#define CF_MIN_3DB_150HZ 0x2
3922
3923static void tavil_tx_hpf_corner_freq_callback(struct work_struct *work)
3924{
3925 struct delayed_work *hpf_delayed_work;
3926 struct hpf_work *hpf_work;
3927 struct tavil_priv *tavil;
3928 struct snd_soc_codec *codec;
3929 u16 dec_cfg_reg, amic_reg, go_bit_reg;
3930 u8 hpf_cut_off_freq;
3931 int amic_n;
3932
3933 hpf_delayed_work = to_delayed_work(work);
3934 hpf_work = container_of(hpf_delayed_work, struct hpf_work, dwork);
3935 tavil = hpf_work->tavil;
3936 codec = tavil->codec;
3937 hpf_cut_off_freq = hpf_work->hpf_cut_off_freq;
3938
3939 dec_cfg_reg = WCD934X_CDC_TX0_TX_PATH_CFG0 + 16 * hpf_work->decimator;
3940 go_bit_reg = dec_cfg_reg + 7;
3941
3942 dev_dbg(codec->dev, "%s: decimator %u hpf_cut_of_freq 0x%x\n",
3943 __func__, hpf_work->decimator, hpf_cut_off_freq);
3944
3945 amic_n = tavil_codec_find_amic_input(codec, hpf_work->decimator);
3946 if (amic_n) {
3947 amic_reg = WCD934X_ANA_AMIC1 + amic_n - 1;
3948 tavil_codec_set_tx_hold(codec, amic_reg, false);
3949 }
3950 snd_soc_update_bits(codec, dec_cfg_reg, TX_HPF_CUT_OFF_FREQ_MASK,
3951 hpf_cut_off_freq << 5);
3952 snd_soc_update_bits(codec, go_bit_reg, 0x02, 0x02);
3953 /* Minimum 1 clk cycle delay is required as per HW spec */
3954 usleep_range(1000, 1010);
3955 snd_soc_update_bits(codec, go_bit_reg, 0x02, 0x00);
3956}
3957
3958static void tavil_tx_mute_update_callback(struct work_struct *work)
3959{
3960 struct tx_mute_work *tx_mute_dwork;
3961 struct tavil_priv *tavil;
3962 struct delayed_work *delayed_work;
3963 struct snd_soc_codec *codec;
3964 u16 tx_vol_ctl_reg, hpf_gate_reg;
3965
3966 delayed_work = to_delayed_work(work);
3967 tx_mute_dwork = container_of(delayed_work, struct tx_mute_work, dwork);
3968 tavil = tx_mute_dwork->tavil;
3969 codec = tavil->codec;
3970
3971 tx_vol_ctl_reg = WCD934X_CDC_TX0_TX_PATH_CTL +
3972 16 * tx_mute_dwork->decimator;
3973 hpf_gate_reg = WCD934X_CDC_TX0_TX_PATH_SEC2 +
3974 16 * tx_mute_dwork->decimator;
3975 snd_soc_update_bits(codec, tx_vol_ctl_reg, 0x10, 0x00);
3976}
3977
3978static int tavil_codec_enable_rx_path_clk(struct snd_soc_dapm_widget *w,
3979 struct snd_kcontrol *kcontrol, int event)
3980{
3981 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
3982 u16 sidetone_reg;
3983
3984 dev_dbg(codec->dev, "%s %d %d\n", __func__, event, w->shift);
3985 sidetone_reg = WCD934X_CDC_RX0_RX_PATH_CFG1 + 0x14*(w->shift);
3986
3987 switch (event) {
3988 case SND_SOC_DAPM_PRE_PMU:
3989 if (!strcmp(w->name, "RX INT7 MIX2 INP"))
3990 __tavil_codec_enable_swr(w, event);
3991 tavil_codec_enable_interp_clk(codec, event, w->shift);
3992 snd_soc_update_bits(codec, sidetone_reg, 0x10, 0x10);
3993 break;
3994 case SND_SOC_DAPM_POST_PMD:
3995 snd_soc_update_bits(codec, sidetone_reg, 0x10, 0x00);
3996 tavil_codec_enable_interp_clk(codec, event, w->shift);
3997 if (!strcmp(w->name, "RX INT7 MIX2 INP"))
3998 __tavil_codec_enable_swr(w, event);
3999 break;
4000 default:
4001 break;
4002 };
4003 return 0;
4004}
4005
4006static int tavil_codec_enable_dec(struct snd_soc_dapm_widget *w,
4007 struct snd_kcontrol *kcontrol, int event)
4008{
4009 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
4010 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
4011 unsigned int decimator;
4012 char *dec_adc_mux_name = NULL;
4013 char *widget_name = NULL;
4014 char *wname;
4015 int ret = 0, amic_n;
4016 u16 tx_vol_ctl_reg, pwr_level_reg = 0, dec_cfg_reg, hpf_gate_reg;
4017 u16 tx_gain_ctl_reg;
4018 char *dec;
4019 u8 hpf_cut_off_freq;
4020
4021 dev_dbg(codec->dev, "%s %d\n", __func__, event);
4022
4023 widget_name = kstrndup(w->name, 15, GFP_KERNEL);
4024 if (!widget_name)
4025 return -ENOMEM;
4026
4027 wname = widget_name;
4028 dec_adc_mux_name = strsep(&widget_name, " ");
4029 if (!dec_adc_mux_name) {
4030 dev_err(codec->dev, "%s: Invalid decimator = %s\n",
4031 __func__, w->name);
4032 ret = -EINVAL;
4033 goto out;
4034 }
4035 dec_adc_mux_name = widget_name;
4036
4037 dec = strpbrk(dec_adc_mux_name, "012345678");
4038 if (!dec) {
4039 dev_err(codec->dev, "%s: decimator index not found\n",
4040 __func__);
4041 ret = -EINVAL;
4042 goto out;
4043 }
4044
4045 ret = kstrtouint(dec, 10, &decimator);
4046 if (ret < 0) {
4047 dev_err(codec->dev, "%s: Invalid decimator = %s\n",
4048 __func__, wname);
4049 ret = -EINVAL;
4050 goto out;
4051 }
4052
4053 dev_dbg(codec->dev, "%s(): widget = %s decimator = %u\n", __func__,
4054 w->name, decimator);
4055
4056 tx_vol_ctl_reg = WCD934X_CDC_TX0_TX_PATH_CTL + 16 * decimator;
4057 hpf_gate_reg = WCD934X_CDC_TX0_TX_PATH_SEC2 + 16 * decimator;
4058 dec_cfg_reg = WCD934X_CDC_TX0_TX_PATH_CFG0 + 16 * decimator;
4059 tx_gain_ctl_reg = WCD934X_CDC_TX0_TX_VOL_CTL + 16 * decimator;
4060
4061 switch (event) {
4062 case SND_SOC_DAPM_PRE_PMU:
4063 amic_n = tavil_codec_find_amic_input(codec, decimator);
4064 if (amic_n)
4065 pwr_level_reg = tavil_codec_get_amic_pwlvl_reg(codec,
4066 amic_n);
4067
4068 if (pwr_level_reg) {
4069 switch ((snd_soc_read(codec, pwr_level_reg) &
4070 WCD934X_AMIC_PWR_LVL_MASK) >>
4071 WCD934X_AMIC_PWR_LVL_SHIFT) {
4072 case WCD934X_AMIC_PWR_LEVEL_LP:
4073 snd_soc_update_bits(codec, dec_cfg_reg,
4074 WCD934X_DEC_PWR_LVL_MASK,
4075 WCD934X_DEC_PWR_LVL_LP);
4076 break;
4077
4078 case WCD934X_AMIC_PWR_LEVEL_HP:
4079 snd_soc_update_bits(codec, dec_cfg_reg,
4080 WCD934X_DEC_PWR_LVL_MASK,
4081 WCD934X_DEC_PWR_LVL_HP);
4082 break;
4083 case WCD934X_AMIC_PWR_LEVEL_DEFAULT:
4084 default:
4085 snd_soc_update_bits(codec, dec_cfg_reg,
4086 WCD934X_DEC_PWR_LVL_MASK,
4087 WCD934X_DEC_PWR_LVL_DF);
4088 break;
4089 }
4090 }
4091 /* Enable TX PGA Mute */
4092 snd_soc_update_bits(codec, tx_vol_ctl_reg, 0x10, 0x10);
4093 break;
4094 case SND_SOC_DAPM_POST_PMU:
4095 hpf_cut_off_freq = (snd_soc_read(codec, dec_cfg_reg) &
4096 TX_HPF_CUT_OFF_FREQ_MASK) >> 5;
4097
4098 tavil->tx_hpf_work[decimator].hpf_cut_off_freq =
4099 hpf_cut_off_freq;
4100 if (hpf_cut_off_freq != CF_MIN_3DB_150HZ) {
4101 snd_soc_update_bits(codec, dec_cfg_reg,
4102 TX_HPF_CUT_OFF_FREQ_MASK,
4103 CF_MIN_3DB_150HZ << 5);
4104 snd_soc_update_bits(codec, hpf_gate_reg, 0x02, 0x02);
4105 /*
4106 * Minimum 1 clk cycle delay is required as per
4107 * HW spec.
4108 */
4109 usleep_range(1000, 1010);
4110 snd_soc_update_bits(codec, hpf_gate_reg, 0x02, 0x00);
4111 }
4112 /* schedule work queue to Remove Mute */
4113 schedule_delayed_work(&tavil->tx_mute_dwork[decimator].dwork,
4114 msecs_to_jiffies(tx_unmute_delay));
4115 if (tavil->tx_hpf_work[decimator].hpf_cut_off_freq !=
4116 CF_MIN_3DB_150HZ)
4117 schedule_delayed_work(
4118 &tavil->tx_hpf_work[decimator].dwork,
4119 msecs_to_jiffies(300));
4120 /* apply gain after decimator is enabled */
4121 snd_soc_write(codec, tx_gain_ctl_reg,
4122 snd_soc_read(codec, tx_gain_ctl_reg));
4123 break;
4124 case SND_SOC_DAPM_PRE_PMD:
4125 hpf_cut_off_freq =
4126 tavil->tx_hpf_work[decimator].hpf_cut_off_freq;
4127 snd_soc_update_bits(codec, tx_vol_ctl_reg, 0x10, 0x10);
4128 if (cancel_delayed_work_sync(
4129 &tavil->tx_hpf_work[decimator].dwork)) {
4130 if (hpf_cut_off_freq != CF_MIN_3DB_150HZ) {
4131 snd_soc_update_bits(codec, dec_cfg_reg,
4132 TX_HPF_CUT_OFF_FREQ_MASK,
4133 hpf_cut_off_freq << 5);
4134 snd_soc_update_bits(codec, hpf_gate_reg,
4135 0x02, 0x02);
4136 /*
4137 * Minimum 1 clk cycle delay is required as per
4138 * HW spec.
4139 */
4140 usleep_range(1000, 1010);
4141 snd_soc_update_bits(codec, hpf_gate_reg,
4142 0x02, 0x00);
4143 }
4144 }
4145 cancel_delayed_work_sync(
4146 &tavil->tx_mute_dwork[decimator].dwork);
4147 break;
4148 case SND_SOC_DAPM_POST_PMD:
4149 snd_soc_update_bits(codec, tx_vol_ctl_reg, 0x10, 0x00);
4150 snd_soc_update_bits(codec, dec_cfg_reg,
4151 WCD934X_DEC_PWR_LVL_MASK,
4152 WCD934X_DEC_PWR_LVL_DF);
4153 break;
4154 };
4155out:
4156 kfree(wname);
4157 return ret;
4158}
4159
4160static u32 tavil_get_dmic_sample_rate(struct snd_soc_codec *codec,
4161 unsigned int dmic,
4162 struct wcd9xxx_pdata *pdata)
4163{
4164 u8 tx_stream_fs;
4165 u8 adc_mux_index = 0, adc_mux_sel = 0;
4166 bool dec_found = false;
4167 u16 adc_mux_ctl_reg, tx_fs_reg;
4168 u32 dmic_fs;
4169
4170 while (dec_found == 0 && adc_mux_index < WCD934X_MAX_VALID_ADC_MUX) {
4171 if (adc_mux_index < 4) {
4172 adc_mux_ctl_reg = WCD934X_CDC_TX_INP_MUX_ADC_MUX0_CFG0 +
4173 (adc_mux_index * 2);
4174 } else if (adc_mux_index < WCD934X_INVALID_ADC_MUX) {
4175 adc_mux_ctl_reg = WCD934X_CDC_TX_INP_MUX_ADC_MUX4_CFG0 +
4176 adc_mux_index - 4;
4177 } else if (adc_mux_index == WCD934X_INVALID_ADC_MUX) {
4178 ++adc_mux_index;
4179 continue;
4180 }
4181 adc_mux_sel = ((snd_soc_read(codec, adc_mux_ctl_reg) &
4182 0xF8) >> 3) - 1;
4183
4184 if (adc_mux_sel == dmic) {
4185 dec_found = true;
4186 break;
4187 }
4188
4189 ++adc_mux_index;
4190 }
4191
4192 if (dec_found && adc_mux_index <= 8) {
4193 tx_fs_reg = WCD934X_CDC_TX0_TX_PATH_CTL + (16 * adc_mux_index);
4194 tx_stream_fs = snd_soc_read(codec, tx_fs_reg) & 0x0F;
4195 if (tx_stream_fs <= 4) {
4196 if (pdata->dmic_sample_rate <=
4197 WCD9XXX_DMIC_SAMPLE_RATE_2P4MHZ)
4198 dmic_fs = pdata->dmic_sample_rate;
4199 else
4200 dmic_fs = WCD9XXX_DMIC_SAMPLE_RATE_2P4MHZ;
4201 } else
4202 dmic_fs = WCD9XXX_DMIC_SAMPLE_RATE_4P8MHZ;
4203 } else {
4204 dmic_fs = pdata->dmic_sample_rate;
4205 }
4206
4207 return dmic_fs;
4208}
4209
4210static u8 tavil_get_dmic_clk_val(struct snd_soc_codec *codec,
4211 u32 mclk_rate, u32 dmic_clk_rate)
4212{
4213 u32 div_factor;
4214 u8 dmic_ctl_val;
4215
4216 dev_dbg(codec->dev,
4217 "%s: mclk_rate = %d, dmic_sample_rate = %d\n",
4218 __func__, mclk_rate, dmic_clk_rate);
4219
4220 /* Default value to return in case of error */
4221 if (mclk_rate == WCD934X_MCLK_CLK_9P6MHZ)
4222 dmic_ctl_val = WCD934X_DMIC_CLK_DIV_2;
4223 else
4224 dmic_ctl_val = WCD934X_DMIC_CLK_DIV_3;
4225
4226 if (dmic_clk_rate == 0) {
4227 dev_err(codec->dev,
4228 "%s: dmic_sample_rate cannot be 0\n",
4229 __func__);
4230 goto done;
4231 }
4232
4233 div_factor = mclk_rate / dmic_clk_rate;
4234 switch (div_factor) {
4235 case 2:
4236 dmic_ctl_val = WCD934X_DMIC_CLK_DIV_2;
4237 break;
4238 case 3:
4239 dmic_ctl_val = WCD934X_DMIC_CLK_DIV_3;
4240 break;
4241 case 4:
4242 dmic_ctl_val = WCD934X_DMIC_CLK_DIV_4;
4243 break;
4244 case 6:
4245 dmic_ctl_val = WCD934X_DMIC_CLK_DIV_6;
4246 break;
4247 case 8:
4248 dmic_ctl_val = WCD934X_DMIC_CLK_DIV_8;
4249 break;
4250 case 16:
4251 dmic_ctl_val = WCD934X_DMIC_CLK_DIV_16;
4252 break;
4253 default:
4254 dev_err(codec->dev,
4255 "%s: Invalid div_factor %u, clk_rate(%u), dmic_rate(%u)\n",
4256 __func__, div_factor, mclk_rate, dmic_clk_rate);
4257 break;
4258 }
4259
4260done:
4261 return dmic_ctl_val;
4262}
4263
4264static int tavil_codec_enable_adc(struct snd_soc_dapm_widget *w,
4265 struct snd_kcontrol *kcontrol, int event)
4266{
4267 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
4268
4269 dev_dbg(codec->dev, "%s: event:%d\n", __func__, event);
4270
4271 switch (event) {
4272 case SND_SOC_DAPM_PRE_PMU:
4273 tavil_codec_set_tx_hold(codec, w->reg, true);
4274 break;
4275 default:
4276 break;
4277 }
4278
4279 return 0;
4280}
4281
4282static int tavil_codec_enable_dmic(struct snd_soc_dapm_widget *w,
4283 struct snd_kcontrol *kcontrol, int event)
4284{
4285 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
4286 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
4287 struct wcd9xxx_pdata *pdata = dev_get_platdata(codec->dev->parent);
4288 u8 dmic_clk_en = 0x01;
4289 u16 dmic_clk_reg;
4290 s32 *dmic_clk_cnt;
4291 u8 dmic_rate_val, dmic_rate_shift = 1;
4292 unsigned int dmic;
4293 u32 dmic_sample_rate;
4294 int ret;
4295 char *wname;
4296
4297 wname = strpbrk(w->name, "012345");
4298 if (!wname) {
4299 dev_err(codec->dev, "%s: widget not found\n", __func__);
4300 return -EINVAL;
4301 }
4302
4303 ret = kstrtouint(wname, 10, &dmic);
4304 if (ret < 0) {
4305 dev_err(codec->dev, "%s: Invalid DMIC line on the codec\n",
4306 __func__);
4307 return -EINVAL;
4308 }
4309
4310 switch (dmic) {
4311 case 0:
4312 case 1:
4313 dmic_clk_cnt = &(tavil->dmic_0_1_clk_cnt);
4314 dmic_clk_reg = WCD934X_CPE_SS_DMIC0_CTL;
4315 break;
4316 case 2:
4317 case 3:
4318 dmic_clk_cnt = &(tavil->dmic_2_3_clk_cnt);
4319 dmic_clk_reg = WCD934X_CPE_SS_DMIC1_CTL;
4320 break;
4321 case 4:
4322 case 5:
4323 dmic_clk_cnt = &(tavil->dmic_4_5_clk_cnt);
4324 dmic_clk_reg = WCD934X_CPE_SS_DMIC2_CTL;
4325 break;
4326 default:
4327 dev_err(codec->dev, "%s: Invalid DMIC Selection\n",
4328 __func__);
4329 return -EINVAL;
4330 };
4331 dev_dbg(codec->dev, "%s: event %d DMIC%d dmic_clk_cnt %d\n",
4332 __func__, event, dmic, *dmic_clk_cnt);
4333
4334 switch (event) {
4335 case SND_SOC_DAPM_PRE_PMU:
4336 dmic_sample_rate = tavil_get_dmic_sample_rate(codec, dmic,
4337 pdata);
4338 dmic_rate_val =
4339 tavil_get_dmic_clk_val(codec,
4340 pdata->mclk_rate,
4341 dmic_sample_rate);
4342
4343 (*dmic_clk_cnt)++;
4344 if (*dmic_clk_cnt == 1) {
4345 snd_soc_update_bits(codec, dmic_clk_reg,
4346 0x07 << dmic_rate_shift,
4347 dmic_rate_val << dmic_rate_shift);
4348 snd_soc_update_bits(codec, dmic_clk_reg,
4349 dmic_clk_en, dmic_clk_en);
4350 }
4351
4352 break;
4353 case SND_SOC_DAPM_POST_PMD:
4354 dmic_rate_val =
4355 tavil_get_dmic_clk_val(codec,
4356 pdata->mclk_rate,
4357 pdata->mad_dmic_sample_rate);
4358 (*dmic_clk_cnt)--;
4359 if (*dmic_clk_cnt == 0) {
4360 snd_soc_update_bits(codec, dmic_clk_reg,
4361 dmic_clk_en, 0);
4362 snd_soc_update_bits(codec, dmic_clk_reg,
4363 0x07 << dmic_rate_shift,
4364 dmic_rate_val << dmic_rate_shift);
4365 }
4366 break;
4367 };
4368
4369 return 0;
4370}
4371
4372/*
4373 * tavil_mbhc_micb_adjust_voltage: adjust specific micbias voltage
4374 * @codec: handle to snd_soc_codec *
4375 * @req_volt: micbias voltage to be set
4376 * @micb_num: micbias to be set, e.g. micbias1 or micbias2
4377 *
4378 * return 0 if adjustment is success or error code in case of failure
4379 */
4380int tavil_mbhc_micb_adjust_voltage(struct snd_soc_codec *codec,
4381 int req_volt, int micb_num)
4382{
4383 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
4384 int cur_vout_ctl, req_vout_ctl;
4385 int micb_reg, micb_val, micb_en;
4386 int ret = 0;
4387
4388 switch (micb_num) {
4389 case MIC_BIAS_1:
4390 micb_reg = WCD934X_ANA_MICB1;
4391 break;
4392 case MIC_BIAS_2:
4393 micb_reg = WCD934X_ANA_MICB2;
4394 break;
4395 case MIC_BIAS_3:
4396 micb_reg = WCD934X_ANA_MICB3;
4397 break;
4398 case MIC_BIAS_4:
4399 micb_reg = WCD934X_ANA_MICB4;
4400 break;
4401 default:
4402 return -EINVAL;
4403 }
4404 mutex_lock(&tavil->micb_lock);
4405
4406 /*
4407 * If requested micbias voltage is same as current micbias
4408 * voltage, then just return. Otherwise, adjust voltage as
4409 * per requested value. If micbias is already enabled, then
4410 * to avoid slow micbias ramp-up or down enable pull-up
4411 * momentarily, change the micbias value and then re-enable
4412 * micbias.
4413 */
4414 micb_val = snd_soc_read(codec, micb_reg);
4415 micb_en = (micb_val & 0xC0) >> 6;
4416 cur_vout_ctl = micb_val & 0x3F;
4417
4418 req_vout_ctl = wcd934x_get_micb_vout_ctl_val(req_volt);
Xiaoyu Ye1a2d8bd92017-01-31 18:54:15 -08004419 if (req_vout_ctl < 0) {
Banajit Goswamide8271c2017-01-18 00:28:59 -08004420 ret = -EINVAL;
4421 goto exit;
4422 }
4423 if (cur_vout_ctl == req_vout_ctl) {
4424 ret = 0;
4425 goto exit;
4426 }
4427
4428 dev_dbg(codec->dev, "%s: micb_num: %d, cur_mv: %d, req_mv: %d, micb_en: %d\n",
4429 __func__, micb_num, WCD_VOUT_CTL_TO_MICB(cur_vout_ctl),
4430 req_volt, micb_en);
4431
4432 if (micb_en == 0x1)
4433 snd_soc_update_bits(codec, micb_reg, 0xC0, 0x80);
4434
4435 snd_soc_update_bits(codec, micb_reg, 0x3F, req_vout_ctl);
4436
4437 if (micb_en == 0x1) {
4438 snd_soc_update_bits(codec, micb_reg, 0xC0, 0x40);
4439 /*
4440 * Add 2ms delay as per HW requirement after enabling
4441 * micbias
4442 */
4443 usleep_range(2000, 2100);
4444 }
4445exit:
4446 mutex_unlock(&tavil->micb_lock);
4447 return ret;
4448}
4449EXPORT_SYMBOL(tavil_mbhc_micb_adjust_voltage);
4450
4451/*
4452 * tavil_micbias_control: enable/disable micbias
4453 * @codec: handle to snd_soc_codec *
4454 * @micb_num: micbias to be enabled/disabled, e.g. micbias1 or micbias2
4455 * @req: control requested, enable/disable or pullup enable/disable
4456 * @is_dapm: triggered by dapm or not
4457 *
4458 * return 0 if control is success or error code in case of failure
4459 */
4460int tavil_micbias_control(struct snd_soc_codec *codec,
4461 int micb_num, int req, bool is_dapm)
4462{
4463 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
4464 int micb_index = micb_num - 1;
4465 u16 micb_reg;
4466 int pre_off_event = 0, post_off_event = 0;
4467 int post_on_event = 0, post_dapm_off = 0;
4468 int post_dapm_on = 0;
4469
4470 if ((micb_index < 0) || (micb_index > TAVIL_MAX_MICBIAS - 1)) {
4471 dev_err(codec->dev, "%s: Invalid micbias index, micb_ind:%d\n",
4472 __func__, micb_index);
4473 return -EINVAL;
4474 }
4475
4476 switch (micb_num) {
4477 case MIC_BIAS_1:
4478 micb_reg = WCD934X_ANA_MICB1;
4479 break;
4480 case MIC_BIAS_2:
4481 micb_reg = WCD934X_ANA_MICB2;
4482 pre_off_event = WCD_EVENT_PRE_MICBIAS_2_OFF;
4483 post_off_event = WCD_EVENT_POST_MICBIAS_2_OFF;
4484 post_on_event = WCD_EVENT_POST_MICBIAS_2_ON;
4485 post_dapm_on = WCD_EVENT_POST_DAPM_MICBIAS_2_ON;
4486 post_dapm_off = WCD_EVENT_POST_DAPM_MICBIAS_2_OFF;
4487 break;
4488 case MIC_BIAS_3:
4489 micb_reg = WCD934X_ANA_MICB3;
4490 break;
4491 case MIC_BIAS_4:
4492 micb_reg = WCD934X_ANA_MICB4;
4493 break;
4494 default:
4495 dev_err(codec->dev, "%s: Invalid micbias number: %d\n",
4496 __func__, micb_num);
4497 return -EINVAL;
4498 }
4499 mutex_lock(&tavil->micb_lock);
4500
4501 switch (req) {
4502 case MICB_PULLUP_ENABLE:
4503 tavil->pullup_ref[micb_index]++;
4504 if ((tavil->pullup_ref[micb_index] == 1) &&
4505 (tavil->micb_ref[micb_index] == 0))
4506 snd_soc_update_bits(codec, micb_reg, 0xC0, 0x80);
4507 break;
4508 case MICB_PULLUP_DISABLE:
4509 if (tavil->pullup_ref[micb_index] > 0)
4510 tavil->pullup_ref[micb_index]--;
4511 if ((tavil->pullup_ref[micb_index] == 0) &&
4512 (tavil->micb_ref[micb_index] == 0))
4513 snd_soc_update_bits(codec, micb_reg, 0xC0, 0x00);
4514 break;
4515 case MICB_ENABLE:
4516 tavil->micb_ref[micb_index]++;
4517 if (tavil->micb_ref[micb_index] == 1) {
4518 snd_soc_update_bits(codec, micb_reg, 0xC0, 0x40);
4519 if (post_on_event && tavil->mbhc)
4520 blocking_notifier_call_chain(
4521 &tavil->mbhc->notifier,
4522 post_on_event,
4523 &tavil->mbhc->wcd_mbhc);
4524 }
4525 if (is_dapm && post_dapm_on && tavil->mbhc)
4526 blocking_notifier_call_chain(&tavil->mbhc->notifier,
4527 post_dapm_on, &tavil->mbhc->wcd_mbhc);
4528 break;
4529 case MICB_DISABLE:
4530 if (tavil->micb_ref[micb_index] > 0)
4531 tavil->micb_ref[micb_index]--;
4532 if ((tavil->micb_ref[micb_index] == 0) &&
4533 (tavil->pullup_ref[micb_index] > 0))
4534 snd_soc_update_bits(codec, micb_reg, 0xC0, 0x80);
4535 else if ((tavil->micb_ref[micb_index] == 0) &&
4536 (tavil->pullup_ref[micb_index] == 0)) {
4537 if (pre_off_event && tavil->mbhc)
4538 blocking_notifier_call_chain(
4539 &tavil->mbhc->notifier,
4540 pre_off_event,
4541 &tavil->mbhc->wcd_mbhc);
4542 snd_soc_update_bits(codec, micb_reg, 0xC0, 0x00);
4543 if (post_off_event && tavil->mbhc)
4544 blocking_notifier_call_chain(
4545 &tavil->mbhc->notifier,
4546 post_off_event,
4547 &tavil->mbhc->wcd_mbhc);
4548 }
4549 if (is_dapm && post_dapm_off && tavil->mbhc)
4550 blocking_notifier_call_chain(&tavil->mbhc->notifier,
4551 post_dapm_off, &tavil->mbhc->wcd_mbhc);
4552 break;
4553 };
4554
4555 dev_dbg(codec->dev, "%s: micb_num:%d, micb_ref: %d, pullup_ref: %d\n",
4556 __func__, micb_num, tavil->micb_ref[micb_index],
4557 tavil->pullup_ref[micb_index]);
4558
4559 mutex_unlock(&tavil->micb_lock);
4560
4561 return 0;
4562}
4563EXPORT_SYMBOL(tavil_micbias_control);
4564
4565static int __tavil_codec_enable_micbias(struct snd_soc_dapm_widget *w,
4566 int event)
4567{
4568 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
4569 int micb_num;
4570
4571 dev_dbg(codec->dev, "%s: wname: %s, event: %d\n",
4572 __func__, w->name, event);
4573
4574 if (strnstr(w->name, "MIC BIAS1", sizeof("MIC BIAS1")))
4575 micb_num = MIC_BIAS_1;
4576 else if (strnstr(w->name, "MIC BIAS2", sizeof("MIC BIAS2")))
4577 micb_num = MIC_BIAS_2;
4578 else if (strnstr(w->name, "MIC BIAS3", sizeof("MIC BIAS3")))
4579 micb_num = MIC_BIAS_3;
4580 else if (strnstr(w->name, "MIC BIAS4", sizeof("MIC BIAS4")))
4581 micb_num = MIC_BIAS_4;
4582 else
4583 return -EINVAL;
4584
4585 switch (event) {
4586 case SND_SOC_DAPM_PRE_PMU:
4587 /*
4588 * MIC BIAS can also be requested by MBHC,
4589 * so use ref count to handle micbias pullup
4590 * and enable requests
4591 */
4592 tavil_micbias_control(codec, micb_num, MICB_ENABLE, true);
4593 break;
4594 case SND_SOC_DAPM_POST_PMU:
4595 /* wait for cnp time */
4596 usleep_range(1000, 1100);
4597 break;
4598 case SND_SOC_DAPM_POST_PMD:
4599 tavil_micbias_control(codec, micb_num, MICB_DISABLE, true);
4600 break;
4601 };
4602
4603 return 0;
4604}
4605
4606/*
4607 * tavil_codec_enable_standalone_micbias - enable micbias standalone
4608 * @codec: pointer to codec instance
4609 * @micb_num: number of micbias to be enabled
4610 * @enable: true to enable micbias or false to disable
4611 *
4612 * This function is used to enable micbias (1, 2, 3 or 4) during
4613 * standalone independent of whether TX use-case is running or not
4614 *
4615 * Return: error code in case of failure or 0 for success
4616 */
4617int tavil_codec_enable_standalone_micbias(struct snd_soc_codec *codec,
4618 int micb_num,
4619 bool enable)
4620{
4621 const char * const micb_names[] = {
4622 DAPM_MICBIAS1_STANDALONE, DAPM_MICBIAS2_STANDALONE,
4623 DAPM_MICBIAS3_STANDALONE, DAPM_MICBIAS4_STANDALONE
4624 };
4625 int micb_index = micb_num - 1;
4626 int rc;
4627
4628 if (!codec) {
4629 pr_err("%s: Codec memory is NULL\n", __func__);
4630 return -EINVAL;
4631 }
4632
4633 if ((micb_index < 0) || (micb_index > TAVIL_MAX_MICBIAS - 1)) {
4634 dev_err(codec->dev, "%s: Invalid micbias index, micb_ind:%d\n",
4635 __func__, micb_index);
4636 return -EINVAL;
4637 }
4638
4639 if (enable)
4640 rc = snd_soc_dapm_force_enable_pin(
4641 snd_soc_codec_get_dapm(codec),
4642 micb_names[micb_index]);
4643 else
4644 rc = snd_soc_dapm_disable_pin(snd_soc_codec_get_dapm(codec),
4645 micb_names[micb_index]);
4646
4647 if (!rc)
4648 snd_soc_dapm_sync(snd_soc_codec_get_dapm(codec));
4649 else
4650 dev_err(codec->dev, "%s: micbias%d force %s pin failed\n",
4651 __func__, micb_num, (enable ? "enable" : "disable"));
4652
4653 return rc;
4654}
4655EXPORT_SYMBOL(tavil_codec_enable_standalone_micbias);
4656
4657static int tavil_codec_force_enable_micbias(struct snd_soc_dapm_widget *w,
4658 struct snd_kcontrol *kcontrol,
4659 int event)
4660{
4661 int ret = 0;
4662 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
4663 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
4664
4665 switch (event) {
4666 case SND_SOC_DAPM_PRE_PMU:
4667 wcd_resmgr_enable_master_bias(tavil->resmgr);
4668 tavil_cdc_mclk_enable(codec, true);
4669 ret = __tavil_codec_enable_micbias(w, SND_SOC_DAPM_PRE_PMU);
4670 /* Wait for 1ms for better cnp */
4671 usleep_range(1000, 1100);
4672 tavil_cdc_mclk_enable(codec, false);
4673 break;
4674 case SND_SOC_DAPM_POST_PMD:
4675 ret = __tavil_codec_enable_micbias(w, SND_SOC_DAPM_POST_PMD);
4676 wcd_resmgr_disable_master_bias(tavil->resmgr);
4677 break;
4678 }
4679
4680 return ret;
4681}
4682
4683static int tavil_codec_enable_micbias(struct snd_soc_dapm_widget *w,
4684 struct snd_kcontrol *kcontrol, int event)
4685{
4686 return __tavil_codec_enable_micbias(w, event);
4687}
4688
4689
4690static const struct reg_sequence tavil_hph_reset_tbl[] = {
4691 { WCD934X_HPH_CNP_EN, 0x80 },
4692 { WCD934X_HPH_CNP_WG_CTL, 0x9A },
4693 { WCD934X_HPH_CNP_WG_TIME, 0x14 },
4694 { WCD934X_HPH_OCP_CTL, 0x28 },
4695 { WCD934X_HPH_AUTO_CHOP, 0x16 },
4696 { WCD934X_HPH_CHOP_CTL, 0x83 },
4697 { WCD934X_HPH_PA_CTL1, 0x46 },
4698 { WCD934X_HPH_PA_CTL2, 0x50 },
4699 { WCD934X_HPH_L_EN, 0x80 },
4700 { WCD934X_HPH_L_TEST, 0xE0 },
4701 { WCD934X_HPH_L_ATEST, 0x50 },
4702 { WCD934X_HPH_R_EN, 0x80 },
4703 { WCD934X_HPH_R_TEST, 0xE0 },
4704 { WCD934X_HPH_R_ATEST, 0x54 },
4705 { WCD934X_HPH_RDAC_CLK_CTL1, 0x99 },
4706 { WCD934X_HPH_RDAC_CLK_CTL2, 0x9B },
4707 { WCD934X_HPH_RDAC_LDO_CTL, 0x33 },
4708 { WCD934X_HPH_RDAC_CHOP_CLK_LP_CTL, 0x00 },
4709 { WCD934X_HPH_REFBUFF_UHQA_CTL, 0xA8 },
4710};
4711
4712static const struct reg_sequence tavil_hph_reset_tbl_1_0[] = {
4713 { WCD934X_HPH_REFBUFF_LP_CTL, 0x0A },
4714 { WCD934X_HPH_L_DAC_CTL, 0x00 },
4715 { WCD934X_HPH_R_DAC_CTL, 0x00 },
4716 { WCD934X_HPH_NEW_ANA_HPH2, 0x00 },
4717 { WCD934X_HPH_NEW_ANA_HPH3, 0x00 },
4718 { WCD934X_HPH_NEW_INT_RDAC_GAIN_CTL, 0x00 },
4719 { WCD934X_HPH_NEW_INT_RDAC_HD2_CTL, 0xA0 },
4720 { WCD934X_HPH_NEW_INT_RDAC_VREF_CTL, 0x10 },
4721 { WCD934X_HPH_NEW_INT_RDAC_OVERRIDE_CTL, 0x00 },
4722 { WCD934X_HPH_NEW_INT_RDAC_MISC1, 0x00 },
4723 { WCD934X_HPH_NEW_INT_PA_MISC1, 0x22 },
4724 { WCD934X_HPH_NEW_INT_PA_MISC2, 0x00 },
4725 { WCD934X_HPH_NEW_INT_PA_RDAC_MISC, 0x00 },
4726 { WCD934X_HPH_NEW_INT_HPH_TIMER1, 0xFE },
4727 { WCD934X_HPH_NEW_INT_HPH_TIMER2, 0x2 },
4728 { WCD934X_HPH_NEW_INT_HPH_TIMER3, 0x4e},
4729 { WCD934X_HPH_NEW_INT_HPH_TIMER4, 0x54 },
4730 { WCD934X_HPH_NEW_INT_PA_RDAC_MISC2, 0x00 },
4731 { WCD934X_HPH_NEW_INT_PA_RDAC_MISC3, 0x00 },
4732};
4733
4734static const struct reg_sequence tavil_hph_reset_tbl_1_1[] = {
4735 { WCD934X_HPH_REFBUFF_LP_CTL, 0x0E },
4736 { WCD934X_HPH_L_DAC_CTL, 0x00 },
4737 { WCD934X_HPH_R_DAC_CTL, 0x00 },
4738 { WCD934X_HPH_NEW_ANA_HPH2, 0x00 },
4739 { WCD934X_HPH_NEW_ANA_HPH3, 0x00 },
4740 { WCD934X_HPH_NEW_INT_RDAC_GAIN_CTL, 0x40 },
4741 { WCD934X_HPH_NEW_INT_RDAC_HD2_CTL, 0x81 },
4742 { WCD934X_HPH_NEW_INT_RDAC_VREF_CTL, 0x10 },
4743 { WCD934X_HPH_NEW_INT_RDAC_OVERRIDE_CTL, 0x00 },
4744 { WCD934X_HPH_NEW_INT_RDAC_MISC1, 0x81 },
4745 { WCD934X_HPH_NEW_INT_PA_MISC1, 0x22 },
4746 { WCD934X_HPH_NEW_INT_PA_MISC2, 0x00 },
4747 { WCD934X_HPH_NEW_INT_PA_RDAC_MISC, 0x00 },
4748 { WCD934X_HPH_NEW_INT_HPH_TIMER1, 0xFE },
4749 { WCD934X_HPH_NEW_INT_HPH_TIMER2, 0x2 },
4750 { WCD934X_HPH_NEW_INT_HPH_TIMER3, 0x4e},
4751 { WCD934X_HPH_NEW_INT_HPH_TIMER4, 0x54 },
4752 { WCD934X_HPH_NEW_INT_PA_RDAC_MISC2, 0x00 },
4753 { WCD934X_HPH_NEW_INT_PA_RDAC_MISC3, 0x00 },
4754};
4755
4756static const struct tavil_reg_mask_val tavil_pa_disable[] = {
4757 { WCD934X_CDC_RX1_RX_PATH_CTL, 0x30, 0x10 }, /* RX1 mute enable */
4758 { WCD934X_CDC_RX2_RX_PATH_CTL, 0x30, 0x10 }, /* RX2 mute enable */
4759 { WCD934X_HPH_CNP_WG_CTL, 0x80, 0x00 }, /* GM3 boost disable */
4760 { WCD934X_ANA_HPH, 0x80, 0x00 }, /* HPHL PA disable */
4761 { WCD934X_ANA_HPH, 0x40, 0x00 }, /* HPHR PA disable */
4762 { WCD934X_ANA_HPH, 0x20, 0x00 }, /* HPHL REF dsable */
4763 { WCD934X_ANA_HPH, 0x10, 0x00 }, /* HPHR REF disable */
4764};
4765
4766static const struct tavil_reg_mask_val tavil_ocp_en_seq[] = {
4767 { WCD934X_RX_OCP_CTL, 0x0F, 0x02 }, /* OCP number of attempts is 2 */
4768 { WCD934X_HPH_OCP_CTL, 0xFA, 0x3A }, /* OCP current limit */
4769 { WCD934X_HPH_L_TEST, 0x01, 0x01 }, /* Enable HPHL OCP */
4770 { WCD934X_HPH_R_TEST, 0x01, 0x01 }, /* Enable HPHR OCP */
4771};
4772
4773static const struct tavil_reg_mask_val tavil_ocp_en_seq_1[] = {
4774 { WCD934X_RX_OCP_CTL, 0x0F, 0x02 }, /* OCP number of attempts is 2 */
4775 { WCD934X_HPH_OCP_CTL, 0xFA, 0x3A }, /* OCP current limit */
4776};
4777
4778/* LO-HIFI */
4779static const struct tavil_reg_mask_val tavil_pre_pa_en_lohifi[] = {
4780 { WCD934X_HPH_NEW_INT_HPH_TIMER1, 0x02, 0x00 },
4781 { WCD934X_FLYBACK_VNEG_CTRL_4, 0xf0, 0x80 },
4782 { WCD934X_HPH_NEW_INT_PA_MISC2, 0x20, 0x20 },
4783 { WCD934X_HPH_NEW_INT_RDAC_GAIN_CTL, 0xf0, 0x40 },
4784 { WCD934X_HPH_CNP_WG_CTL, 0x80, 0x00 },
4785 { WCD934X_RX_BIAS_HPH_LOWPOWER, 0xf0, 0xc0 },
4786 { WCD934X_HPH_PA_CTL1, 0x0e, 0x02 },
4787 { WCD934X_HPH_REFBUFF_LP_CTL, 0x06, 0x06 },
4788};
4789
4790static const struct tavil_reg_mask_val tavil_pre_pa_en[] = {
4791 { WCD934X_HPH_NEW_INT_HPH_TIMER1, 0x02, 0x00 },
4792 { WCD934X_HPH_NEW_INT_PA_MISC2, 0x20, 0x0 },
4793 { WCD934X_HPH_NEW_INT_RDAC_GAIN_CTL, 0xf0, 0x40 },
4794 { WCD934X_HPH_CNP_WG_CTL, 0x80, 0x00 },
4795 { WCD934X_RX_BIAS_HPH_LOWPOWER, 0xf0, 0x80 },
4796 { WCD934X_HPH_PA_CTL1, 0x0e, 0x06 },
4797 { WCD934X_HPH_REFBUFF_LP_CTL, 0x06, 0x06 },
4798};
4799
4800static const struct tavil_reg_mask_val tavil_post_pa_en[] = {
4801 { WCD934X_HPH_L_TEST, 0x01, 0x01 }, /* Enable HPHL OCP */
4802 { WCD934X_HPH_R_TEST, 0x01, 0x01 }, /* Enable HPHR OCP */
4803 { WCD934X_CDC_RX1_RX_PATH_CTL, 0x30, 0x20 }, /* RX1 mute disable */
4804 { WCD934X_CDC_RX2_RX_PATH_CTL, 0x30, 0x20 }, /* RX2 mute disable */
4805 { WCD934X_HPH_CNP_WG_CTL, 0x80, 0x80 }, /* GM3 boost enable */
4806 { WCD934X_HPH_NEW_INT_HPH_TIMER1, 0x02, 0x02 },
4807};
4808
4809static void tavil_codec_hph_reg_range_read(struct regmap *map, u8 *buf)
4810{
4811 regmap_bulk_read(map, WCD934X_HPH_CNP_EN, buf, TAVIL_HPH_REG_RANGE_1);
4812 regmap_bulk_read(map, WCD934X_HPH_NEW_ANA_HPH2,
4813 buf + TAVIL_HPH_REG_RANGE_1, TAVIL_HPH_REG_RANGE_2);
4814 regmap_bulk_read(map, WCD934X_HPH_NEW_INT_RDAC_GAIN_CTL,
4815 buf + TAVIL_HPH_REG_RANGE_1 + TAVIL_HPH_REG_RANGE_2,
4816 TAVIL_HPH_REG_RANGE_3);
4817}
4818
4819static void tavil_codec_hph_reg_recover(struct tavil_priv *tavil,
4820 struct regmap *map, int pa_status)
4821{
4822 int i;
4823 unsigned int reg;
4824
4825 blocking_notifier_call_chain(&tavil->mbhc->notifier,
4826 WCD_EVENT_OCP_OFF,
4827 &tavil->mbhc->wcd_mbhc);
4828
4829 if (pa_status & 0xC0)
4830 goto pa_en_restore;
4831
4832 dev_dbg(tavil->dev, "%s: HPH PA in disable state (0x%x)\n",
4833 __func__, pa_status);
4834
4835 regmap_write_bits(map, WCD934X_CDC_RX1_RX_PATH_CTL, 0x10, 0x10);
4836 regmap_write_bits(map, WCD934X_CDC_RX2_RX_PATH_CTL, 0x10, 0x10);
4837 regmap_write_bits(map, WCD934X_ANA_HPH, 0xC0, 0x00);
4838 regmap_write_bits(map, WCD934X_ANA_HPH, 0x30, 0x00);
4839 regmap_write_bits(map, WCD934X_CDC_RX1_RX_PATH_CTL, 0x10, 0x00);
4840 regmap_write_bits(map, WCD934X_CDC_RX2_RX_PATH_CTL, 0x10, 0x00);
4841
4842 /* Restore to HW defaults */
4843 regmap_multi_reg_write(map, tavil_hph_reset_tbl,
4844 ARRAY_SIZE(tavil_hph_reset_tbl));
4845 if (TAVIL_IS_1_1(tavil->wcd9xxx))
4846 regmap_multi_reg_write(map, tavil_hph_reset_tbl_1_1,
4847 ARRAY_SIZE(tavil_hph_reset_tbl_1_1));
4848 if (TAVIL_IS_1_0(tavil->wcd9xxx))
4849 regmap_multi_reg_write(map, tavil_hph_reset_tbl_1_0,
4850 ARRAY_SIZE(tavil_hph_reset_tbl_1_0));
4851
4852 for (i = 0; i < ARRAY_SIZE(tavil_ocp_en_seq); i++)
4853 regmap_write_bits(map, tavil_ocp_en_seq[i].reg,
4854 tavil_ocp_en_seq[i].mask,
4855 tavil_ocp_en_seq[i].val);
4856 goto end;
4857
4858
4859pa_en_restore:
4860 dev_dbg(tavil->dev, "%s: HPH PA in enable state (0x%x)\n",
4861 __func__, pa_status);
4862
4863 /* Disable PA and other registers before restoring */
4864 for (i = 0; i < ARRAY_SIZE(tavil_pa_disable); i++) {
4865 if (TAVIL_IS_1_1(tavil->wcd9xxx) &&
4866 (tavil_pa_disable[i].reg == WCD934X_HPH_CNP_WG_CTL))
4867 continue;
4868 regmap_write_bits(map, tavil_pa_disable[i].reg,
4869 tavil_pa_disable[i].mask,
4870 tavil_pa_disable[i].val);
4871 }
4872
4873 regmap_multi_reg_write(map, tavil_hph_reset_tbl,
4874 ARRAY_SIZE(tavil_hph_reset_tbl));
4875 if (TAVIL_IS_1_1(tavil->wcd9xxx))
4876 regmap_multi_reg_write(map, tavil_hph_reset_tbl_1_1,
4877 ARRAY_SIZE(tavil_hph_reset_tbl_1_1));
4878 if (TAVIL_IS_1_0(tavil->wcd9xxx))
4879 regmap_multi_reg_write(map, tavil_hph_reset_tbl_1_0,
4880 ARRAY_SIZE(tavil_hph_reset_tbl_1_0));
4881
4882 for (i = 0; i < ARRAY_SIZE(tavil_ocp_en_seq_1); i++)
4883 regmap_write_bits(map, tavil_ocp_en_seq_1[i].reg,
4884 tavil_ocp_en_seq_1[i].mask,
4885 tavil_ocp_en_seq_1[i].val);
4886
4887 if (tavil->hph_mode == CLS_H_LOHIFI) {
4888 for (i = 0; i < ARRAY_SIZE(tavil_pre_pa_en_lohifi); i++) {
4889 reg = tavil_pre_pa_en_lohifi[i].reg;
4890 if ((TAVIL_IS_1_1(tavil->wcd9xxx)) &&
4891 ((reg == WCD934X_HPH_NEW_INT_RDAC_GAIN_CTL) ||
4892 (reg == WCD934X_HPH_CNP_WG_CTL) ||
4893 (reg == WCD934X_HPH_REFBUFF_LP_CTL)))
4894 continue;
4895 regmap_write_bits(map,
4896 tavil_pre_pa_en_lohifi[i].reg,
4897 tavil_pre_pa_en_lohifi[i].mask,
4898 tavil_pre_pa_en_lohifi[i].val);
4899 }
4900 } else {
4901 for (i = 0; i < ARRAY_SIZE(tavil_pre_pa_en); i++) {
4902 reg = tavil_pre_pa_en[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, tavil_pre_pa_en[i].reg,
4909 tavil_pre_pa_en[i].mask,
4910 tavil_pre_pa_en[i].val);
4911 }
4912 }
4913
4914 if (TAVIL_IS_1_1(tavil->wcd9xxx)) {
4915 regmap_write(map, WCD934X_HPH_NEW_INT_RDAC_HD2_CTL_L, 0x84);
4916 regmap_write(map, WCD934X_HPH_NEW_INT_RDAC_HD2_CTL_R, 0x84);
4917 }
4918
4919 regmap_write_bits(map, WCD934X_ANA_HPH, 0x0C, pa_status & 0x0C);
4920 regmap_write_bits(map, WCD934X_ANA_HPH, 0x30, 0x30);
4921 /* wait for 100usec after HPH DAC is enabled */
4922 usleep_range(100, 110);
4923 regmap_write(map, WCD934X_ANA_HPH, pa_status);
4924 /* Sleep for 7msec after PA is enabled */
4925 usleep_range(7000, 7100);
4926
4927 for (i = 0; i < ARRAY_SIZE(tavil_post_pa_en); i++) {
4928 if ((TAVIL_IS_1_1(tavil->wcd9xxx)) &&
4929 (tavil_post_pa_en[i].reg == WCD934X_HPH_CNP_WG_CTL))
4930 continue;
4931 regmap_write_bits(map, tavil_post_pa_en[i].reg,
4932 tavil_post_pa_en[i].mask,
4933 tavil_post_pa_en[i].val);
4934 }
4935
4936end:
4937 tavil->mbhc->is_hph_recover = true;
4938 blocking_notifier_call_chain(
4939 &tavil->mbhc->notifier,
4940 WCD_EVENT_OCP_ON,
4941 &tavil->mbhc->wcd_mbhc);
4942}
4943
4944static int tavil_codec_reset_hph_registers(struct snd_soc_dapm_widget *w,
4945 struct snd_kcontrol *kcontrol,
4946 int event)
4947{
4948 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
4949 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
4950 struct wcd9xxx *wcd9xxx = dev_get_drvdata(codec->dev->parent);
4951 u8 cache_val[TAVIL_HPH_TOTAL_REG];
4952 u8 hw_val[TAVIL_HPH_TOTAL_REG];
4953 int pa_status;
4954 int ret;
4955
4956 dev_dbg(wcd9xxx->dev, "%s: event: %d\n", __func__, event);
4957
4958 switch (event) {
4959 case SND_SOC_DAPM_PRE_PMU:
4960 memset(cache_val, 0, TAVIL_HPH_TOTAL_REG);
4961 memset(hw_val, 0, TAVIL_HPH_TOTAL_REG);
4962
4963 regmap_read(wcd9xxx->regmap, WCD934X_ANA_HPH, &pa_status);
4964
4965 tavil_codec_hph_reg_range_read(wcd9xxx->regmap, cache_val);
4966
4967 /* Read register values from HW directly */
4968 regcache_cache_bypass(wcd9xxx->regmap, true);
4969 tavil_codec_hph_reg_range_read(wcd9xxx->regmap, hw_val);
4970 regcache_cache_bypass(wcd9xxx->regmap, false);
4971
4972 /* compare both the registers to know if there is corruption */
4973 ret = memcmp(cache_val, hw_val, TAVIL_HPH_TOTAL_REG);
4974
4975 /* If both the values are same, it means no corruption */
4976 if (ret) {
4977 dev_dbg(codec->dev, "%s: cache and hw reg are not same\n",
4978 __func__);
4979 tavil_codec_hph_reg_recover(tavil, wcd9xxx->regmap,
4980 pa_status);
4981 } else {
4982 dev_dbg(codec->dev, "%s: cache and hw reg are same\n",
4983 __func__);
4984 tavil->mbhc->is_hph_recover = false;
4985 }
4986 break;
4987 default:
4988 break;
4989 };
4990
4991 return 0;
4992}
4993
4994static int tavil_iir_enable_audio_mixer_get(struct snd_kcontrol *kcontrol,
4995 struct snd_ctl_elem_value *ucontrol)
4996{
4997 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
4998 int iir_idx = ((struct soc_multi_mixer_control *)
4999 kcontrol->private_value)->reg;
5000 int band_idx = ((struct soc_multi_mixer_control *)
5001 kcontrol->private_value)->shift;
5002 /* IIR filter band registers are at integer multiples of 16 */
5003 u16 iir_reg = WCD934X_CDC_SIDETONE_IIR0_IIR_CTL + 16 * iir_idx;
5004
5005 ucontrol->value.integer.value[0] = (snd_soc_read(codec, iir_reg) &
5006 (1 << band_idx)) != 0;
5007
5008 dev_dbg(codec->dev, "%s: IIR #%d band #%d enable %d\n", __func__,
5009 iir_idx, band_idx,
5010 (uint32_t)ucontrol->value.integer.value[0]);
5011 return 0;
5012}
5013
5014static int tavil_iir_enable_audio_mixer_put(struct snd_kcontrol *kcontrol,
5015 struct snd_ctl_elem_value *ucontrol)
5016{
5017 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
5018 int iir_idx = ((struct soc_multi_mixer_control *)
5019 kcontrol->private_value)->reg;
5020 int band_idx = ((struct soc_multi_mixer_control *)
5021 kcontrol->private_value)->shift;
5022 bool iir_band_en_status;
5023 int value = ucontrol->value.integer.value[0];
5024 u16 iir_reg = WCD934X_CDC_SIDETONE_IIR0_IIR_CTL + 16 * iir_idx;
5025
5026 /* Mask first 5 bits, 6-8 are reserved */
5027 snd_soc_update_bits(codec, iir_reg, (1 << band_idx),
5028 (value << band_idx));
5029
5030 iir_band_en_status = ((snd_soc_read(codec, iir_reg) &
5031 (1 << band_idx)) != 0);
5032 dev_dbg(codec->dev, "%s: IIR #%d band #%d enable %d\n", __func__,
5033 iir_idx, band_idx, iir_band_en_status);
5034 return 0;
5035}
5036
5037static uint32_t get_iir_band_coeff(struct snd_soc_codec *codec,
5038 int iir_idx, int band_idx,
5039 int coeff_idx)
5040{
5041 uint32_t value = 0;
5042
5043 /* Address does not automatically update if reading */
5044 snd_soc_write(codec,
5045 (WCD934X_CDC_SIDETONE_IIR0_IIR_COEF_B1_CTL + 16 * iir_idx),
5046 ((band_idx * BAND_MAX + coeff_idx)
5047 * sizeof(uint32_t)) & 0x7F);
5048
5049 value |= snd_soc_read(codec,
5050 (WCD934X_CDC_SIDETONE_IIR0_IIR_COEF_B2_CTL + 16 * iir_idx));
5051
5052 snd_soc_write(codec,
5053 (WCD934X_CDC_SIDETONE_IIR0_IIR_COEF_B1_CTL + 16 * iir_idx),
5054 ((band_idx * BAND_MAX + coeff_idx)
5055 * sizeof(uint32_t) + 1) & 0x7F);
5056
5057 value |= (snd_soc_read(codec,
5058 (WCD934X_CDC_SIDETONE_IIR0_IIR_COEF_B2_CTL +
5059 16 * iir_idx)) << 8);
5060
5061 snd_soc_write(codec,
5062 (WCD934X_CDC_SIDETONE_IIR0_IIR_COEF_B1_CTL + 16 * iir_idx),
5063 ((band_idx * BAND_MAX + coeff_idx)
5064 * sizeof(uint32_t) + 2) & 0x7F);
5065
5066 value |= (snd_soc_read(codec,
5067 (WCD934X_CDC_SIDETONE_IIR0_IIR_COEF_B2_CTL +
5068 16 * iir_idx)) << 16);
5069
5070 snd_soc_write(codec,
5071 (WCD934X_CDC_SIDETONE_IIR0_IIR_COEF_B1_CTL + 16 * iir_idx),
5072 ((band_idx * BAND_MAX + coeff_idx)
5073 * sizeof(uint32_t) + 3) & 0x7F);
5074
5075 /* Mask bits top 2 bits since they are reserved */
5076 value |= ((snd_soc_read(codec,
5077 (WCD934X_CDC_SIDETONE_IIR0_IIR_COEF_B2_CTL +
5078 16 * iir_idx)) & 0x3F) << 24);
5079
5080 return value;
5081}
5082
5083static int tavil_iir_band_audio_mixer_get(struct snd_kcontrol *kcontrol,
5084 struct snd_ctl_elem_value *ucontrol)
5085{
5086 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
5087 int iir_idx = ((struct soc_multi_mixer_control *)
5088 kcontrol->private_value)->reg;
5089 int band_idx = ((struct soc_multi_mixer_control *)
5090 kcontrol->private_value)->shift;
5091
5092 ucontrol->value.integer.value[0] =
5093 get_iir_band_coeff(codec, iir_idx, band_idx, 0);
5094 ucontrol->value.integer.value[1] =
5095 get_iir_band_coeff(codec, iir_idx, band_idx, 1);
5096 ucontrol->value.integer.value[2] =
5097 get_iir_band_coeff(codec, iir_idx, band_idx, 2);
5098 ucontrol->value.integer.value[3] =
5099 get_iir_band_coeff(codec, iir_idx, band_idx, 3);
5100 ucontrol->value.integer.value[4] =
5101 get_iir_band_coeff(codec, iir_idx, band_idx, 4);
5102
5103 dev_dbg(codec->dev, "%s: IIR #%d band #%d b0 = 0x%x\n"
5104 "%s: IIR #%d band #%d b1 = 0x%x\n"
5105 "%s: IIR #%d band #%d b2 = 0x%x\n"
5106 "%s: IIR #%d band #%d a1 = 0x%x\n"
5107 "%s: IIR #%d band #%d a2 = 0x%x\n",
5108 __func__, iir_idx, band_idx,
5109 (uint32_t)ucontrol->value.integer.value[0],
5110 __func__, iir_idx, band_idx,
5111 (uint32_t)ucontrol->value.integer.value[1],
5112 __func__, iir_idx, band_idx,
5113 (uint32_t)ucontrol->value.integer.value[2],
5114 __func__, iir_idx, band_idx,
5115 (uint32_t)ucontrol->value.integer.value[3],
5116 __func__, iir_idx, band_idx,
5117 (uint32_t)ucontrol->value.integer.value[4]);
5118 return 0;
5119}
5120
5121static void set_iir_band_coeff(struct snd_soc_codec *codec,
5122 int iir_idx, int band_idx,
5123 uint32_t value)
5124{
5125 snd_soc_write(codec,
5126 (WCD934X_CDC_SIDETONE_IIR0_IIR_COEF_B2_CTL + 16 * iir_idx),
5127 (value & 0xFF));
5128
5129 snd_soc_write(codec,
5130 (WCD934X_CDC_SIDETONE_IIR0_IIR_COEF_B2_CTL + 16 * iir_idx),
5131 (value >> 8) & 0xFF);
5132
5133 snd_soc_write(codec,
5134 (WCD934X_CDC_SIDETONE_IIR0_IIR_COEF_B2_CTL + 16 * iir_idx),
5135 (value >> 16) & 0xFF);
5136
5137 /* Mask top 2 bits, 7-8 are reserved */
5138 snd_soc_write(codec,
5139 (WCD934X_CDC_SIDETONE_IIR0_IIR_COEF_B2_CTL + 16 * iir_idx),
5140 (value >> 24) & 0x3F);
5141}
5142
5143static int tavil_iir_band_audio_mixer_put(struct snd_kcontrol *kcontrol,
5144 struct snd_ctl_elem_value *ucontrol)
5145{
5146 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
5147 int iir_idx = ((struct soc_multi_mixer_control *)
5148 kcontrol->private_value)->reg;
5149 int band_idx = ((struct soc_multi_mixer_control *)
5150 kcontrol->private_value)->shift;
5151
5152 /*
5153 * Mask top bit it is reserved
5154 * Updates addr automatically for each B2 write
5155 */
5156 snd_soc_write(codec,
5157 (WCD934X_CDC_SIDETONE_IIR0_IIR_COEF_B1_CTL + 16 * iir_idx),
5158 (band_idx * BAND_MAX * sizeof(uint32_t)) & 0x7F);
5159
5160 set_iir_band_coeff(codec, iir_idx, band_idx,
5161 ucontrol->value.integer.value[0]);
5162 set_iir_band_coeff(codec, iir_idx, band_idx,
5163 ucontrol->value.integer.value[1]);
5164 set_iir_band_coeff(codec, iir_idx, band_idx,
5165 ucontrol->value.integer.value[2]);
5166 set_iir_band_coeff(codec, iir_idx, band_idx,
5167 ucontrol->value.integer.value[3]);
5168 set_iir_band_coeff(codec, iir_idx, band_idx,
5169 ucontrol->value.integer.value[4]);
5170
5171 pr_debug("%s: IIR #%d band #%d b0 = 0x%x\n"
5172 "%s: IIR #%d band #%d b1 = 0x%x\n"
5173 "%s: IIR #%d band #%d b2 = 0x%x\n"
5174 "%s: IIR #%d band #%d a1 = 0x%x\n"
5175 "%s: IIR #%d band #%d a2 = 0x%x\n",
5176 __func__, iir_idx, band_idx,
5177 get_iir_band_coeff(codec, iir_idx, band_idx, 0),
5178 __func__, iir_idx, band_idx,
5179 get_iir_band_coeff(codec, iir_idx, band_idx, 1),
5180 __func__, iir_idx, band_idx,
5181 get_iir_band_coeff(codec, iir_idx, band_idx, 2),
5182 __func__, iir_idx, band_idx,
5183 get_iir_band_coeff(codec, iir_idx, band_idx, 3),
5184 __func__, iir_idx, band_idx,
5185 get_iir_band_coeff(codec, iir_idx, band_idx, 4));
5186 return 0;
5187}
5188
5189static int tavil_compander_get(struct snd_kcontrol *kcontrol,
5190 struct snd_ctl_elem_value *ucontrol)
5191{
5192
5193 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
5194 int comp = ((struct soc_multi_mixer_control *)
5195 kcontrol->private_value)->shift;
5196 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
5197
5198 ucontrol->value.integer.value[0] = tavil->comp_enabled[comp];
5199 return 0;
5200}
5201
5202static int tavil_compander_put(struct snd_kcontrol *kcontrol,
5203 struct snd_ctl_elem_value *ucontrol)
5204{
5205 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
5206 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
5207 int comp = ((struct soc_multi_mixer_control *)
5208 kcontrol->private_value)->shift;
5209 int value = ucontrol->value.integer.value[0];
5210
5211 dev_dbg(codec->dev, "%s: Compander %d enable current %d, new %d\n",
5212 __func__, comp + 1, tavil->comp_enabled[comp], value);
5213 tavil->comp_enabled[comp] = value;
5214
5215 /* Any specific register configuration for compander */
5216 switch (comp) {
5217 case COMPANDER_1:
5218 /* Set Gain Source Select based on compander enable/disable */
5219 snd_soc_update_bits(codec, WCD934X_HPH_L_EN, 0x20,
5220 (value ? 0x00:0x20));
5221 break;
5222 case COMPANDER_2:
5223 snd_soc_update_bits(codec, WCD934X_HPH_R_EN, 0x20,
5224 (value ? 0x00:0x20));
5225 break;
5226 case COMPANDER_3:
5227 case COMPANDER_4:
5228 case COMPANDER_7:
5229 case COMPANDER_8:
5230 break;
5231 default:
5232 /*
5233 * if compander is not enabled for any interpolator,
5234 * it does not cause any audio failure, so do not
5235 * return error in this case, but just print a log
5236 */
5237 dev_warn(codec->dev, "%s: unknown compander: %d\n",
5238 __func__, comp);
5239 };
5240 return 0;
5241}
5242
5243static int tavil_hph_asrc_mode_put(struct snd_kcontrol *kcontrol,
5244 struct snd_ctl_elem_value *ucontrol)
5245{
5246 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
5247 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
5248 int index = -EINVAL;
5249
5250 if (!strcmp(kcontrol->id.name, "ASRC0 Output Mode"))
5251 index = ASRC0;
5252 if (!strcmp(kcontrol->id.name, "ASRC1 Output Mode"))
5253 index = ASRC1;
5254
5255 if (tavil && (index >= 0) && (index < ASRC_MAX))
5256 tavil->asrc_output_mode[index] =
5257 ucontrol->value.integer.value[0];
5258
5259 return 0;
5260}
5261
5262static int tavil_hph_asrc_mode_get(struct snd_kcontrol *kcontrol,
5263 struct snd_ctl_elem_value *ucontrol)
5264{
5265 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
5266 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
5267 int val = 0;
5268 int index = -EINVAL;
5269
5270 if (!strcmp(kcontrol->id.name, "ASRC0 Output Mode"))
5271 index = ASRC0;
5272 if (!strcmp(kcontrol->id.name, "ASRC1 Output Mode"))
5273 index = ASRC1;
5274
5275 if (tavil && (index >= 0) && (index < ASRC_MAX))
5276 val = tavil->asrc_output_mode[index];
5277
5278 ucontrol->value.integer.value[0] = val;
5279
5280 return 0;
5281}
5282
5283static int tavil_hph_idle_detect_get(struct snd_kcontrol *kcontrol,
5284 struct snd_ctl_elem_value *ucontrol)
5285{
5286 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
5287 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
5288 int val = 0;
5289
5290 if (tavil)
5291 val = tavil->idle_det_cfg.hph_idle_detect_en;
5292
5293 ucontrol->value.integer.value[0] = val;
5294
5295 return 0;
5296}
5297
5298static int tavil_hph_idle_detect_put(struct snd_kcontrol *kcontrol,
5299 struct snd_ctl_elem_value *ucontrol)
5300{
5301 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
5302 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
5303
5304 if (tavil)
5305 tavil->idle_det_cfg.hph_idle_detect_en =
5306 ucontrol->value.integer.value[0];
5307
5308 return 0;
5309}
5310
5311static int tavil_dmic_pin_mode_get(struct snd_kcontrol *kcontrol,
5312 struct snd_ctl_elem_value *ucontrol)
5313{
5314 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
5315 u16 dmic_pin;
5316 u8 reg_val, pinctl_position;
5317
5318 pinctl_position = ((struct soc_multi_mixer_control *)
5319 kcontrol->private_value)->shift;
5320
5321 dmic_pin = pinctl_position & 0x07;
5322 reg_val = snd_soc_read(codec,
5323 WCD934X_TLMM_DMIC1_CLK_PINCFG + dmic_pin - 1);
5324
5325 ucontrol->value.integer.value[0] = !!reg_val;
5326
5327 return 0;
5328}
5329
5330static int tavil_dmic_pin_mode_put(struct snd_kcontrol *kcontrol,
5331 struct snd_ctl_elem_value *ucontrol)
5332{
5333 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
5334 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
5335 u16 ctl_reg, cfg_reg, dmic_pin;
5336 u8 ctl_val, cfg_val, pinctl_position, pinctl_mode, mask;
5337
5338 /* 0- high or low; 1- high Z */
5339 pinctl_mode = ucontrol->value.integer.value[0];
5340 pinctl_position = ((struct soc_multi_mixer_control *)
5341 kcontrol->private_value)->shift;
5342
5343 switch (pinctl_position >> 3) {
5344 case 0:
5345 ctl_reg = WCD934X_TEST_DEBUG_PIN_CTL_OE_0;
5346 break;
5347 case 1:
5348 ctl_reg = WCD934X_TEST_DEBUG_PIN_CTL_OE_1;
5349 break;
5350 case 2:
5351 ctl_reg = WCD934X_TEST_DEBUG_PIN_CTL_OE_2;
5352 break;
5353 case 3:
5354 ctl_reg = WCD934X_TEST_DEBUG_PIN_CTL_OE_3;
5355 break;
5356 default:
5357 dev_err(codec->dev, "%s: Invalid pinctl position = %d\n",
5358 __func__, pinctl_position);
5359 return -EINVAL;
5360 }
5361
5362 ctl_val = ~(pinctl_mode << (pinctl_position & 0x07));
5363 mask = 1 << (pinctl_position & 0x07);
5364 snd_soc_update_bits(codec, ctl_reg, mask, ctl_val);
5365
5366 dmic_pin = pinctl_position & 0x07;
5367 cfg_reg = WCD934X_TLMM_DMIC1_CLK_PINCFG + dmic_pin - 1;
5368 if (pinctl_mode) {
5369 if (tavil->intf_type == WCD9XXX_INTERFACE_TYPE_SLIMBUS)
5370 cfg_val = 0x6;
5371 else
5372 cfg_val = 0xD;
5373 } else
5374 cfg_val = 0;
5375 snd_soc_update_bits(codec, cfg_reg, 0x1F, cfg_val);
5376
5377 dev_dbg(codec->dev, "%s: reg=0x%x mask=0x%x val=%d reg=0x%x val=%d\n",
5378 __func__, ctl_reg, mask, ctl_val, cfg_reg, cfg_val);
5379
5380 return 0;
5381}
5382
5383static int tavil_amic_pwr_lvl_get(struct snd_kcontrol *kcontrol,
5384 struct snd_ctl_elem_value *ucontrol)
5385{
5386 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
Phani Kumar Uppalapatiafdc5a82016-12-16 17:06:27 -08005387 u16 amic_reg = 0;
Banajit Goswamide8271c2017-01-18 00:28:59 -08005388
5389 if (!strcmp(kcontrol->id.name, "AMIC_1_2 PWR MODE"))
5390 amic_reg = WCD934X_ANA_AMIC1;
5391 if (!strcmp(kcontrol->id.name, "AMIC_3_4 PWR MODE"))
5392 amic_reg = WCD934X_ANA_AMIC3;
Banajit Goswamide8271c2017-01-18 00:28:59 -08005393
Phani Kumar Uppalapatiafdc5a82016-12-16 17:06:27 -08005394 if (amic_reg)
5395 ucontrol->value.integer.value[0] =
5396 (snd_soc_read(codec, amic_reg) &
5397 WCD934X_AMIC_PWR_LVL_MASK) >>
5398 WCD934X_AMIC_PWR_LVL_SHIFT;
Banajit Goswamide8271c2017-01-18 00:28:59 -08005399 return 0;
5400}
5401
5402static int tavil_amic_pwr_lvl_put(struct snd_kcontrol *kcontrol,
5403 struct snd_ctl_elem_value *ucontrol)
5404{
5405 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
5406 u32 mode_val;
Phani Kumar Uppalapatiafdc5a82016-12-16 17:06:27 -08005407 u16 amic_reg = 0;
Banajit Goswamide8271c2017-01-18 00:28:59 -08005408
5409 mode_val = ucontrol->value.enumerated.item[0];
5410
5411 dev_dbg(codec->dev, "%s: mode: %d\n", __func__, mode_val);
5412
5413 if (!strcmp(kcontrol->id.name, "AMIC_1_2 PWR MODE"))
5414 amic_reg = WCD934X_ANA_AMIC1;
5415 if (!strcmp(kcontrol->id.name, "AMIC_3_4 PWR MODE"))
5416 amic_reg = WCD934X_ANA_AMIC3;
Banajit Goswamide8271c2017-01-18 00:28:59 -08005417
Phani Kumar Uppalapatiafdc5a82016-12-16 17:06:27 -08005418 if (amic_reg)
5419 snd_soc_update_bits(codec, amic_reg, WCD934X_AMIC_PWR_LVL_MASK,
5420 mode_val << WCD934X_AMIC_PWR_LVL_SHIFT);
Banajit Goswamide8271c2017-01-18 00:28:59 -08005421 return 0;
5422}
5423
5424static const char *const tavil_conn_mad_text[] = {
5425 "NOTUSED1", "ADC1", "ADC2", "ADC3", "ADC4", "NOTUSED5",
5426 "NOTUSED6", "NOTUSED2", "DMIC0", "DMIC1", "DMIC2", "DMIC3",
5427 "DMIC4", "DMIC5", "NOTUSED3", "NOTUSED4"
5428};
5429
5430static const struct soc_enum tavil_conn_mad_enum =
5431 SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(tavil_conn_mad_text),
5432 tavil_conn_mad_text);
5433
5434static int tavil_mad_input_get(struct snd_kcontrol *kcontrol,
5435 struct snd_ctl_elem_value *ucontrol)
5436{
5437 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
5438 u8 tavil_mad_input;
5439
5440 tavil_mad_input = snd_soc_read(codec, WCD934X_SOC_MAD_INP_SEL) & 0x0F;
5441 ucontrol->value.integer.value[0] = tavil_mad_input;
5442
5443 dev_dbg(codec->dev, "%s: tavil_mad_input = %s\n", __func__,
5444 tavil_conn_mad_text[tavil_mad_input]);
5445
5446 return 0;
5447}
5448
5449static int tavil_mad_input_put(struct snd_kcontrol *kcontrol,
5450 struct snd_ctl_elem_value *ucontrol)
5451{
5452 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
5453 struct snd_soc_card *card = codec->component.card;
5454 u8 tavil_mad_input;
5455 char mad_amic_input_widget[6];
5456 const char *mad_input_widget;
5457 const char *source_widget = NULL;
5458 u32 adc, i, mic_bias_found = 0;
5459 int ret = 0;
5460 char *mad_input;
5461 bool is_adc2_input = false;
5462
5463 tavil_mad_input = ucontrol->value.integer.value[0];
5464
Karthikeyan Mani5b976ab2016-12-12 11:04:01 -08005465 if (tavil_mad_input >= sizeof(tavil_conn_mad_text)/
5466 sizeof(tavil_conn_mad_text[0])) {
5467 dev_err(codec->dev,
5468 "%s: tavil_mad_input = %d out of bounds\n",
5469 __func__, tavil_mad_input);
5470 return -EINVAL;
5471 }
5472
Banajit Goswamide8271c2017-01-18 00:28:59 -08005473 if (strnstr(tavil_conn_mad_text[tavil_mad_input], "NOTUSED",
5474 sizeof("NOTUSED"))) {
5475 dev_dbg(codec->dev,
5476 "%s: Unsupported tavil_mad_input = %s\n",
5477 __func__, tavil_conn_mad_text[tavil_mad_input]);
5478 /* Make sure the MAD register is updated */
5479 snd_soc_update_bits(codec, WCD934X_ANA_MAD_SETUP,
5480 0x88, 0x00);
5481 return -EINVAL;
5482 }
5483
5484 if (strnstr(tavil_conn_mad_text[tavil_mad_input],
5485 "ADC", sizeof("ADC"))) {
5486 mad_input = strpbrk(tavil_conn_mad_text[tavil_mad_input],
5487 "1234");
5488 if (!mad_input) {
5489 dev_err(codec->dev, "%s: Invalid MAD input %s\n",
5490 __func__, tavil_conn_mad_text[tavil_mad_input]);
5491 return -EINVAL;
5492 }
5493
5494 ret = kstrtouint(mad_input, 10, &adc);
5495 if ((ret < 0) || (adc > 4)) {
5496 dev_err(codec->dev, "%s: Invalid ADC = %s\n", __func__,
5497 tavil_conn_mad_text[tavil_mad_input]);
5498 return -EINVAL;
5499 }
5500
5501 /*AMIC4 and AMIC5 share ADC4*/
5502 if ((adc == 4) &&
5503 (snd_soc_read(codec, WCD934X_TX_NEW_AMIC_4_5_SEL) & 0x10))
5504 adc = 5;
5505
5506 snprintf(mad_amic_input_widget, 6, "%s%u", "AMIC", adc);
5507
5508 mad_input_widget = mad_amic_input_widget;
5509 if (adc == 2)
5510 is_adc2_input = true;
5511 } else {
5512 /* DMIC type input widget*/
5513 mad_input_widget = tavil_conn_mad_text[tavil_mad_input];
5514 }
5515
5516 dev_dbg(codec->dev,
5517 "%s: tavil input widget = %s, adc_input = %s\n", __func__,
5518 mad_input_widget, is_adc2_input ? "true" : "false");
5519
5520 for (i = 0; i < card->num_of_dapm_routes; i++) {
5521 if (!strcmp(card->of_dapm_routes[i].sink, mad_input_widget)) {
5522 source_widget = card->of_dapm_routes[i].source;
5523 if (!source_widget) {
5524 dev_err(codec->dev,
5525 "%s: invalid source widget\n",
5526 __func__);
5527 return -EINVAL;
5528 }
5529
5530 if (strnstr(source_widget,
5531 "MIC BIAS1", sizeof("MIC BIAS1"))) {
5532 mic_bias_found = 1;
5533 break;
5534 } else if (strnstr(source_widget,
5535 "MIC BIAS2", sizeof("MIC BIAS2"))) {
5536 mic_bias_found = 2;
5537 break;
5538 } else if (strnstr(source_widget,
5539 "MIC BIAS3", sizeof("MIC BIAS3"))) {
5540 mic_bias_found = 3;
5541 break;
5542 } else if (strnstr(source_widget,
5543 "MIC BIAS4", sizeof("MIC BIAS4"))) {
5544 mic_bias_found = 4;
5545 break;
5546 }
5547 }
5548 }
5549
5550 if (!mic_bias_found) {
5551 dev_err(codec->dev, "%s: mic bias not found for input %s\n",
5552 __func__, mad_input_widget);
5553 return -EINVAL;
5554 }
5555
5556 dev_dbg(codec->dev, "%s: mic_bias found = %d\n", __func__,
5557 mic_bias_found);
5558
5559 snd_soc_update_bits(codec, WCD934X_SOC_MAD_INP_SEL,
5560 0x0F, tavil_mad_input);
5561 snd_soc_update_bits(codec, WCD934X_ANA_MAD_SETUP,
5562 0x07, mic_bias_found);
5563 /* for adc2 input, mad should be in micbias mode with BG enabled */
5564 if (is_adc2_input)
5565 snd_soc_update_bits(codec, WCD934X_ANA_MAD_SETUP,
5566 0x88, 0x88);
5567 else
5568 snd_soc_update_bits(codec, WCD934X_ANA_MAD_SETUP,
5569 0x88, 0x00);
5570 return 0;
5571}
5572
5573static int tavil_ear_pa_gain_get(struct snd_kcontrol *kcontrol,
5574 struct snd_ctl_elem_value *ucontrol)
5575{
5576 u8 ear_pa_gain;
5577 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
5578
5579 ear_pa_gain = snd_soc_read(codec, WCD934X_ANA_EAR);
5580
5581 ear_pa_gain = (ear_pa_gain & 0x70) >> 4;
5582
5583 ucontrol->value.integer.value[0] = ear_pa_gain;
5584
5585 dev_dbg(codec->dev, "%s: ear_pa_gain = 0x%x\n", __func__,
5586 ear_pa_gain);
5587
5588 return 0;
5589}
5590
5591static int tavil_ear_pa_gain_put(struct snd_kcontrol *kcontrol,
5592 struct snd_ctl_elem_value *ucontrol)
5593{
5594 u8 ear_pa_gain;
5595 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
5596
5597 dev_dbg(codec->dev, "%s: ucontrol->value.integer.value[0] = %ld\n",
5598 __func__, ucontrol->value.integer.value[0]);
5599
5600 ear_pa_gain = ucontrol->value.integer.value[0] << 4;
5601
5602 snd_soc_update_bits(codec, WCD934X_ANA_EAR, 0x70, ear_pa_gain);
5603 return 0;
5604}
5605
5606static int tavil_ear_spkr_pa_gain_get(struct snd_kcontrol *kcontrol,
5607 struct snd_ctl_elem_value *ucontrol)
5608{
5609 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
5610 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
5611
5612 ucontrol->value.integer.value[0] = tavil->ear_spkr_gain;
5613
5614 dev_dbg(codec->dev, "%s: ucontrol->value.integer.value[0] = %ld\n",
5615 __func__, ucontrol->value.integer.value[0]);
5616
5617 return 0;
5618}
5619
5620static int tavil_ear_spkr_pa_gain_put(struct snd_kcontrol *kcontrol,
5621 struct snd_ctl_elem_value *ucontrol)
5622{
5623 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
5624 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
5625
5626 tavil->ear_spkr_gain = ucontrol->value.integer.value[0];
5627
5628 dev_dbg(codec->dev, "%s: gain = %d\n", __func__, tavil->ear_spkr_gain);
5629
5630 return 0;
5631}
5632
5633static int tavil_rx_hph_mode_get(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 ucontrol->value.integer.value[0] = tavil->hph_mode;
5640 return 0;
5641}
5642
5643static int tavil_rx_hph_mode_put(struct snd_kcontrol *kcontrol,
5644 struct snd_ctl_elem_value *ucontrol)
5645{
5646 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
5647 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
5648 u32 mode_val;
5649
5650 mode_val = ucontrol->value.enumerated.item[0];
5651
5652 dev_dbg(codec->dev, "%s: mode: %d\n", __func__, mode_val);
5653
5654 if (mode_val == 0) {
5655 dev_warn(codec->dev, "%s:Invalid HPH Mode, default to Cls-H LOHiFi\n",
5656 __func__);
5657 mode_val = CLS_H_LOHIFI;
5658 }
5659 tavil->hph_mode = mode_val;
5660 return 0;
5661}
5662
5663static const char * const rx_hph_mode_mux_text[] = {
5664 "CLS_H_INVALID", "CLS_H_HIFI", "CLS_H_LP", "CLS_AB", "CLS_H_LOHIFI",
5665 "CLS_H_ULP", "CLS_AB_HIFI",
5666};
5667
5668static const struct soc_enum rx_hph_mode_mux_enum =
5669 SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(rx_hph_mode_mux_text),
5670 rx_hph_mode_mux_text);
5671
5672static const char *const tavil_anc_func_text[] = {"OFF", "ON"};
5673static const struct soc_enum tavil_anc_func_enum =
5674 SOC_ENUM_SINGLE_EXT(2, tavil_anc_func_text);
5675
5676/* Cutoff frequency for high pass filter */
5677static const char * const cf_text[] = {
5678 "CF_NEG_3DB_4HZ", "CF_NEG_3DB_75HZ", "CF_NEG_3DB_150HZ"
5679};
5680
5681static const char * const rx_cf_text[] = {
5682 "CF_NEG_3DB_4HZ", "CF_NEG_3DB_75HZ", "CF_NEG_3DB_150HZ",
5683 "CF_NEG_3DB_0P48HZ"
5684};
5685
5686static const char * const amic_pwr_lvl_text[] = {
5687 "LOW_PWR", "DEFAULT", "HIGH_PERF"
5688};
5689
5690static const char * const hph_idle_detect_text[] = {
5691 "OFF", "ON"
5692};
5693
5694static const char * const asrc_mode_text[] = {
5695 "INT", "FRAC"
5696};
5697
5698static const char * const tavil_ear_pa_gain_text[] = {
5699 "G_6_DB", "G_4P5_DB", "G_3_DB", "G_1P5_DB",
5700 "G_0_DB", "G_M2P5_DB", "UNDEFINED", "G_M12_DB"
5701};
5702
5703static const char * const tavil_ear_spkr_pa_gain_text[] = {
5704 "G_DEFAULT", "G_0_DB", "G_1_DB", "G_2_DB", "G_3_DB",
5705 "G_4_DB", "G_5_DB", "G_6_DB"
5706};
5707
5708static SOC_ENUM_SINGLE_EXT_DECL(tavil_ear_pa_gain_enum, tavil_ear_pa_gain_text);
5709static SOC_ENUM_SINGLE_EXT_DECL(tavil_ear_spkr_pa_gain_enum,
5710 tavil_ear_spkr_pa_gain_text);
5711static SOC_ENUM_SINGLE_EXT_DECL(amic_pwr_lvl_enum, amic_pwr_lvl_text);
5712static SOC_ENUM_SINGLE_EXT_DECL(hph_idle_detect_enum, hph_idle_detect_text);
5713static SOC_ENUM_SINGLE_EXT_DECL(asrc_mode_enum, asrc_mode_text);
5714static SOC_ENUM_SINGLE_DECL(cf_dec0_enum, WCD934X_CDC_TX0_TX_PATH_CFG0, 5,
5715 cf_text);
5716static SOC_ENUM_SINGLE_DECL(cf_dec1_enum, WCD934X_CDC_TX1_TX_PATH_CFG0, 5,
5717 cf_text);
5718static SOC_ENUM_SINGLE_DECL(cf_dec2_enum, WCD934X_CDC_TX2_TX_PATH_CFG0, 5,
5719 cf_text);
5720static SOC_ENUM_SINGLE_DECL(cf_dec3_enum, WCD934X_CDC_TX3_TX_PATH_CFG0, 5,
5721 cf_text);
5722static SOC_ENUM_SINGLE_DECL(cf_dec4_enum, WCD934X_CDC_TX4_TX_PATH_CFG0, 5,
5723 cf_text);
5724static SOC_ENUM_SINGLE_DECL(cf_dec5_enum, WCD934X_CDC_TX5_TX_PATH_CFG0, 5,
5725 cf_text);
5726static SOC_ENUM_SINGLE_DECL(cf_dec6_enum, WCD934X_CDC_TX6_TX_PATH_CFG0, 5,
5727 cf_text);
5728static SOC_ENUM_SINGLE_DECL(cf_dec7_enum, WCD934X_CDC_TX7_TX_PATH_CFG0, 5,
5729 cf_text);
5730static SOC_ENUM_SINGLE_DECL(cf_dec8_enum, WCD934X_CDC_TX8_TX_PATH_CFG0, 5,
5731 cf_text);
5732static SOC_ENUM_SINGLE_DECL(cf_int0_1_enum, WCD934X_CDC_RX0_RX_PATH_CFG2, 0,
5733 rx_cf_text);
5734static SOC_ENUM_SINGLE_DECL(cf_int0_2_enum, WCD934X_CDC_RX0_RX_PATH_MIX_CFG, 2,
5735 rx_cf_text);
5736static SOC_ENUM_SINGLE_DECL(cf_int1_1_enum, WCD934X_CDC_RX1_RX_PATH_CFG2, 0,
5737 rx_cf_text);
5738static SOC_ENUM_SINGLE_DECL(cf_int1_2_enum, WCD934X_CDC_RX1_RX_PATH_MIX_CFG, 2,
5739 rx_cf_text);
5740static SOC_ENUM_SINGLE_DECL(cf_int2_1_enum, WCD934X_CDC_RX2_RX_PATH_CFG2, 0,
5741 rx_cf_text);
5742static SOC_ENUM_SINGLE_DECL(cf_int2_2_enum, WCD934X_CDC_RX2_RX_PATH_MIX_CFG, 2,
5743 rx_cf_text);
5744static SOC_ENUM_SINGLE_DECL(cf_int3_1_enum, WCD934X_CDC_RX3_RX_PATH_CFG2, 0,
5745 rx_cf_text);
5746static SOC_ENUM_SINGLE_DECL(cf_int3_2_enum, WCD934X_CDC_RX3_RX_PATH_MIX_CFG, 2,
5747 rx_cf_text);
5748static SOC_ENUM_SINGLE_DECL(cf_int4_1_enum, WCD934X_CDC_RX4_RX_PATH_CFG2, 0,
5749 rx_cf_text);
5750static SOC_ENUM_SINGLE_DECL(cf_int4_2_enum, WCD934X_CDC_RX4_RX_PATH_MIX_CFG, 2,
5751 rx_cf_text);
5752static SOC_ENUM_SINGLE_DECL(cf_int7_1_enum, WCD934X_CDC_RX7_RX_PATH_CFG2, 0,
5753 rx_cf_text);
5754static SOC_ENUM_SINGLE_DECL(cf_int7_2_enum, WCD934X_CDC_RX7_RX_PATH_MIX_CFG, 2,
5755 rx_cf_text);
5756static SOC_ENUM_SINGLE_DECL(cf_int8_1_enum, WCD934X_CDC_RX8_RX_PATH_CFG2, 0,
5757 rx_cf_text);
5758static SOC_ENUM_SINGLE_DECL(cf_int8_2_enum, WCD934X_CDC_RX8_RX_PATH_MIX_CFG, 2,
5759 rx_cf_text);
5760
5761static const struct snd_kcontrol_new tavil_snd_controls[] = {
5762 SOC_ENUM_EXT("EAR PA Gain", tavil_ear_pa_gain_enum,
5763 tavil_ear_pa_gain_get, tavil_ear_pa_gain_put),
5764 SOC_ENUM_EXT("EAR SPKR PA Gain", tavil_ear_spkr_pa_gain_enum,
5765 tavil_ear_spkr_pa_gain_get, tavil_ear_spkr_pa_gain_put),
5766 SOC_SINGLE_TLV("HPHL Volume", WCD934X_HPH_L_EN, 0, 20, 1, line_gain),
5767 SOC_SINGLE_TLV("HPHR Volume", WCD934X_HPH_R_EN, 0, 20, 1, line_gain),
5768 SOC_SINGLE_TLV("LINEOUT1 Volume", WCD934X_DIFF_LO_LO1_COMPANDER,
5769 3, 16, 1, line_gain),
5770 SOC_SINGLE_TLV("LINEOUT2 Volume", WCD934X_DIFF_LO_LO2_COMPANDER,
5771 3, 16, 1, line_gain),
5772 SOC_SINGLE_TLV("ADC1 Volume", WCD934X_ANA_AMIC1, 0, 20, 0, analog_gain),
5773 SOC_SINGLE_TLV("ADC2 Volume", WCD934X_ANA_AMIC2, 0, 20, 0, analog_gain),
5774 SOC_SINGLE_TLV("ADC3 Volume", WCD934X_ANA_AMIC3, 0, 20, 0, analog_gain),
5775 SOC_SINGLE_TLV("ADC4 Volume", WCD934X_ANA_AMIC4, 0, 20, 0, analog_gain),
5776
5777 SOC_SINGLE_SX_TLV("RX0 Digital Volume", WCD934X_CDC_RX0_RX_VOL_CTL,
5778 0, -84, 40, digital_gain), /* -84dB min - 40dB max */
5779 SOC_SINGLE_SX_TLV("RX1 Digital Volume", WCD934X_CDC_RX1_RX_VOL_CTL,
5780 0, -84, 40, digital_gain),
5781 SOC_SINGLE_SX_TLV("RX2 Digital Volume", WCD934X_CDC_RX2_RX_VOL_CTL,
5782 0, -84, 40, digital_gain),
5783 SOC_SINGLE_SX_TLV("RX3 Digital Volume", WCD934X_CDC_RX3_RX_VOL_CTL,
5784 0, -84, 40, digital_gain),
5785 SOC_SINGLE_SX_TLV("RX4 Digital Volume", WCD934X_CDC_RX4_RX_VOL_CTL,
5786 0, -84, 40, digital_gain),
5787 SOC_SINGLE_SX_TLV("RX7 Digital Volume", WCD934X_CDC_RX7_RX_VOL_CTL,
5788 0, -84, 40, digital_gain),
5789 SOC_SINGLE_SX_TLV("RX8 Digital Volume", WCD934X_CDC_RX8_RX_VOL_CTL,
5790 0, -84, 40, digital_gain),
5791 SOC_SINGLE_SX_TLV("RX0 Mix Digital Volume",
5792 WCD934X_CDC_RX0_RX_VOL_MIX_CTL, 0, -84, 40, digital_gain),
5793 SOC_SINGLE_SX_TLV("RX1 Mix Digital Volume",
5794 WCD934X_CDC_RX1_RX_VOL_MIX_CTL, 0, -84, 40, digital_gain),
5795 SOC_SINGLE_SX_TLV("RX2 Mix Digital Volume",
5796 WCD934X_CDC_RX2_RX_VOL_MIX_CTL, 0, -84, 40, digital_gain),
5797 SOC_SINGLE_SX_TLV("RX3 Mix Digital Volume",
5798 WCD934X_CDC_RX3_RX_VOL_MIX_CTL, 0, -84, 40, digital_gain),
5799 SOC_SINGLE_SX_TLV("RX4 Mix Digital Volume",
5800 WCD934X_CDC_RX4_RX_VOL_MIX_CTL, 0, -84, 40, digital_gain),
5801 SOC_SINGLE_SX_TLV("RX7 Mix Digital Volume",
5802 WCD934X_CDC_RX7_RX_VOL_MIX_CTL, 0, -84, 40, digital_gain),
5803 SOC_SINGLE_SX_TLV("RX8 Mix Digital Volume",
5804 WCD934X_CDC_RX8_RX_VOL_MIX_CTL, 0, -84, 40, digital_gain),
5805
5806 SOC_SINGLE_SX_TLV("DEC0 Volume", WCD934X_CDC_TX0_TX_VOL_CTL, 0,
5807 -84, 40, digital_gain),
5808 SOC_SINGLE_SX_TLV("DEC1 Volume", WCD934X_CDC_TX1_TX_VOL_CTL, 0,
5809 -84, 40, digital_gain),
5810 SOC_SINGLE_SX_TLV("DEC2 Volume", WCD934X_CDC_TX2_TX_VOL_CTL, 0,
5811 -84, 40, digital_gain),
5812 SOC_SINGLE_SX_TLV("DEC3 Volume", WCD934X_CDC_TX3_TX_VOL_CTL, 0,
5813 -84, 40, digital_gain),
5814 SOC_SINGLE_SX_TLV("DEC4 Volume", WCD934X_CDC_TX4_TX_VOL_CTL, 0,
5815 -84, 40, digital_gain),
5816 SOC_SINGLE_SX_TLV("DEC5 Volume", WCD934X_CDC_TX5_TX_VOL_CTL, 0,
5817 -84, 40, digital_gain),
5818 SOC_SINGLE_SX_TLV("DEC6 Volume", WCD934X_CDC_TX6_TX_VOL_CTL, 0,
5819 -84, 40, digital_gain),
5820 SOC_SINGLE_SX_TLV("DEC7 Volume", WCD934X_CDC_TX7_TX_VOL_CTL, 0,
5821 -84, 40, digital_gain),
5822 SOC_SINGLE_SX_TLV("DEC8 Volume", WCD934X_CDC_TX8_TX_VOL_CTL, 0,
5823 -84, 40, digital_gain),
5824
5825 SOC_SINGLE_SX_TLV("IIR0 INP0 Volume",
5826 WCD934X_CDC_SIDETONE_IIR0_IIR_GAIN_B1_CTL, 0, -84, 40,
5827 digital_gain),
5828 SOC_SINGLE_SX_TLV("IIR0 INP1 Volume",
5829 WCD934X_CDC_SIDETONE_IIR0_IIR_GAIN_B2_CTL, 0, -84, 40,
5830 digital_gain),
5831 SOC_SINGLE_SX_TLV("IIR0 INP2 Volume",
5832 WCD934X_CDC_SIDETONE_IIR0_IIR_GAIN_B3_CTL, 0, -84, 40,
5833 digital_gain),
5834 SOC_SINGLE_SX_TLV("IIR0 INP3 Volume",
5835 WCD934X_CDC_SIDETONE_IIR0_IIR_GAIN_B4_CTL, 0, -84, 40,
5836 digital_gain),
5837 SOC_SINGLE_SX_TLV("IIR1 INP0 Volume",
5838 WCD934X_CDC_SIDETONE_IIR1_IIR_GAIN_B1_CTL, 0, -84, 40,
5839 digital_gain),
5840 SOC_SINGLE_SX_TLV("IIR1 INP1 Volume",
5841 WCD934X_CDC_SIDETONE_IIR1_IIR_GAIN_B2_CTL, 0, -84, 40,
5842 digital_gain),
5843 SOC_SINGLE_SX_TLV("IIR1 INP2 Volume",
5844 WCD934X_CDC_SIDETONE_IIR1_IIR_GAIN_B3_CTL, 0, -84, 40,
5845 digital_gain),
5846 SOC_SINGLE_SX_TLV("IIR1 INP3 Volume",
5847 WCD934X_CDC_SIDETONE_IIR1_IIR_GAIN_B4_CTL, 0, -84, 40,
5848 digital_gain),
5849
5850 SOC_SINGLE_EXT("ANC Slot", SND_SOC_NOPM, 0, 100, 0, tavil_get_anc_slot,
5851 tavil_put_anc_slot),
5852 SOC_ENUM_EXT("ANC Function", tavil_anc_func_enum, tavil_get_anc_func,
5853 tavil_put_anc_func),
5854
5855 SOC_ENUM("TX0 HPF cut off", cf_dec0_enum),
5856 SOC_ENUM("TX1 HPF cut off", cf_dec1_enum),
5857 SOC_ENUM("TX2 HPF cut off", cf_dec2_enum),
5858 SOC_ENUM("TX3 HPF cut off", cf_dec3_enum),
5859 SOC_ENUM("TX4 HPF cut off", cf_dec4_enum),
5860 SOC_ENUM("TX5 HPF cut off", cf_dec5_enum),
5861 SOC_ENUM("TX6 HPF cut off", cf_dec6_enum),
5862 SOC_ENUM("TX7 HPF cut off", cf_dec7_enum),
5863 SOC_ENUM("TX8 HPF cut off", cf_dec8_enum),
5864
5865 SOC_ENUM("RX INT0_1 HPF cut off", cf_int0_1_enum),
5866 SOC_ENUM("RX INT0_2 HPF cut off", cf_int0_2_enum),
5867 SOC_ENUM("RX INT1_1 HPF cut off", cf_int1_1_enum),
5868 SOC_ENUM("RX INT1_2 HPF cut off", cf_int1_2_enum),
5869 SOC_ENUM("RX INT2_1 HPF cut off", cf_int2_1_enum),
5870 SOC_ENUM("RX INT2_2 HPF cut off", cf_int2_2_enum),
5871 SOC_ENUM("RX INT3_1 HPF cut off", cf_int3_1_enum),
5872 SOC_ENUM("RX INT3_2 HPF cut off", cf_int3_2_enum),
5873 SOC_ENUM("RX INT4_1 HPF cut off", cf_int4_1_enum),
5874 SOC_ENUM("RX INT4_2 HPF cut off", cf_int4_2_enum),
5875 SOC_ENUM("RX INT7_1 HPF cut off", cf_int7_1_enum),
5876 SOC_ENUM("RX INT7_2 HPF cut off", cf_int7_2_enum),
5877 SOC_ENUM("RX INT8_1 HPF cut off", cf_int8_1_enum),
5878 SOC_ENUM("RX INT8_2 HPF cut off", cf_int8_2_enum),
5879
5880 SOC_ENUM_EXT("RX HPH Mode", rx_hph_mode_mux_enum,
5881 tavil_rx_hph_mode_get, tavil_rx_hph_mode_put),
5882
5883 SOC_SINGLE_EXT("IIR0 Enable Band1", IIR0, BAND1, 1, 0,
5884 tavil_iir_enable_audio_mixer_get,
5885 tavil_iir_enable_audio_mixer_put),
5886 SOC_SINGLE_EXT("IIR0 Enable Band2", IIR0, BAND2, 1, 0,
5887 tavil_iir_enable_audio_mixer_get,
5888 tavil_iir_enable_audio_mixer_put),
5889 SOC_SINGLE_EXT("IIR0 Enable Band3", IIR0, BAND3, 1, 0,
5890 tavil_iir_enable_audio_mixer_get,
5891 tavil_iir_enable_audio_mixer_put),
5892 SOC_SINGLE_EXT("IIR0 Enable Band4", IIR0, BAND4, 1, 0,
5893 tavil_iir_enable_audio_mixer_get,
5894 tavil_iir_enable_audio_mixer_put),
5895 SOC_SINGLE_EXT("IIR0 Enable Band5", IIR0, BAND5, 1, 0,
5896 tavil_iir_enable_audio_mixer_get,
5897 tavil_iir_enable_audio_mixer_put),
5898 SOC_SINGLE_EXT("IIR1 Enable Band1", IIR1, BAND1, 1, 0,
5899 tavil_iir_enable_audio_mixer_get,
5900 tavil_iir_enable_audio_mixer_put),
5901 SOC_SINGLE_EXT("IIR1 Enable Band2", IIR1, BAND2, 1, 0,
5902 tavil_iir_enable_audio_mixer_get,
5903 tavil_iir_enable_audio_mixer_put),
5904 SOC_SINGLE_EXT("IIR1 Enable Band3", IIR1, BAND3, 1, 0,
5905 tavil_iir_enable_audio_mixer_get,
5906 tavil_iir_enable_audio_mixer_put),
5907 SOC_SINGLE_EXT("IIR1 Enable Band4", IIR1, BAND4, 1, 0,
5908 tavil_iir_enable_audio_mixer_get,
5909 tavil_iir_enable_audio_mixer_put),
5910 SOC_SINGLE_EXT("IIR1 Enable Band5", IIR1, BAND5, 1, 0,
5911 tavil_iir_enable_audio_mixer_get,
5912 tavil_iir_enable_audio_mixer_put),
5913
5914 SOC_SINGLE_MULTI_EXT("IIR0 Band1", IIR0, BAND1, 255, 0, 5,
5915 tavil_iir_band_audio_mixer_get, tavil_iir_band_audio_mixer_put),
5916 SOC_SINGLE_MULTI_EXT("IIR0 Band2", IIR0, BAND2, 255, 0, 5,
5917 tavil_iir_band_audio_mixer_get, tavil_iir_band_audio_mixer_put),
5918 SOC_SINGLE_MULTI_EXT("IIR0 Band3", IIR0, BAND3, 255, 0, 5,
5919 tavil_iir_band_audio_mixer_get, tavil_iir_band_audio_mixer_put),
5920 SOC_SINGLE_MULTI_EXT("IIR0 Band4", IIR0, BAND4, 255, 0, 5,
5921 tavil_iir_band_audio_mixer_get, tavil_iir_band_audio_mixer_put),
5922 SOC_SINGLE_MULTI_EXT("IIR0 Band5", IIR0, BAND5, 255, 0, 5,
5923 tavil_iir_band_audio_mixer_get, tavil_iir_band_audio_mixer_put),
5924 SOC_SINGLE_MULTI_EXT("IIR1 Band1", IIR1, BAND1, 255, 0, 5,
5925 tavil_iir_band_audio_mixer_get, tavil_iir_band_audio_mixer_put),
5926 SOC_SINGLE_MULTI_EXT("IIR1 Band2", IIR1, BAND2, 255, 0, 5,
5927 tavil_iir_band_audio_mixer_get, tavil_iir_band_audio_mixer_put),
5928 SOC_SINGLE_MULTI_EXT("IIR1 Band3", IIR1, BAND3, 255, 0, 5,
5929 tavil_iir_band_audio_mixer_get, tavil_iir_band_audio_mixer_put),
5930 SOC_SINGLE_MULTI_EXT("IIR1 Band4", IIR1, BAND4, 255, 0, 5,
5931 tavil_iir_band_audio_mixer_get, tavil_iir_band_audio_mixer_put),
5932 SOC_SINGLE_MULTI_EXT("IIR1 Band5", IIR1, BAND5, 255, 0, 5,
5933 tavil_iir_band_audio_mixer_get, tavil_iir_band_audio_mixer_put),
5934
5935 SOC_SINGLE_EXT("COMP1 Switch", SND_SOC_NOPM, COMPANDER_1, 1, 0,
5936 tavil_compander_get, tavil_compander_put),
5937 SOC_SINGLE_EXT("COMP2 Switch", SND_SOC_NOPM, COMPANDER_2, 1, 0,
5938 tavil_compander_get, tavil_compander_put),
5939 SOC_SINGLE_EXT("COMP3 Switch", SND_SOC_NOPM, COMPANDER_3, 1, 0,
5940 tavil_compander_get, tavil_compander_put),
5941 SOC_SINGLE_EXT("COMP4 Switch", SND_SOC_NOPM, COMPANDER_4, 1, 0,
5942 tavil_compander_get, tavil_compander_put),
5943 SOC_SINGLE_EXT("COMP7 Switch", SND_SOC_NOPM, COMPANDER_7, 1, 0,
5944 tavil_compander_get, tavil_compander_put),
5945 SOC_SINGLE_EXT("COMP8 Switch", SND_SOC_NOPM, COMPANDER_8, 1, 0,
5946 tavil_compander_get, tavil_compander_put),
5947
5948 SOC_ENUM_EXT("ASRC0 Output Mode", asrc_mode_enum,
5949 tavil_hph_asrc_mode_get, tavil_hph_asrc_mode_put),
5950 SOC_ENUM_EXT("ASRC1 Output Mode", asrc_mode_enum,
5951 tavil_hph_asrc_mode_get, tavil_hph_asrc_mode_put),
5952
5953 SOC_ENUM_EXT("HPH Idle Detect", hph_idle_detect_enum,
5954 tavil_hph_idle_detect_get, tavil_hph_idle_detect_put),
5955
5956 SOC_ENUM_EXT("MAD Input", tavil_conn_mad_enum,
5957 tavil_mad_input_get, tavil_mad_input_put),
5958
5959 SOC_SINGLE_EXT("DMIC1_CLK_PIN_MODE", SND_SOC_NOPM, 17, 1, 0,
5960 tavil_dmic_pin_mode_get, tavil_dmic_pin_mode_put),
5961
5962 SOC_SINGLE_EXT("DMIC1_DATA_PIN_MODE", SND_SOC_NOPM, 18, 1, 0,
5963 tavil_dmic_pin_mode_get, tavil_dmic_pin_mode_put),
5964
5965 SOC_SINGLE_EXT("DMIC2_CLK_PIN_MODE", SND_SOC_NOPM, 19, 1, 0,
5966 tavil_dmic_pin_mode_get, tavil_dmic_pin_mode_put),
5967
5968 SOC_SINGLE_EXT("DMIC2_DATA_PIN_MODE", SND_SOC_NOPM, 20, 1, 0,
5969 tavil_dmic_pin_mode_get, tavil_dmic_pin_mode_put),
5970
5971 SOC_SINGLE_EXT("DMIC3_CLK_PIN_MODE", SND_SOC_NOPM, 21, 1, 0,
5972 tavil_dmic_pin_mode_get, tavil_dmic_pin_mode_put),
5973
5974 SOC_SINGLE_EXT("DMIC3_DATA_PIN_MODE", SND_SOC_NOPM, 22, 1, 0,
5975 tavil_dmic_pin_mode_get, tavil_dmic_pin_mode_put),
5976 SOC_ENUM_EXT("AMIC_1_2 PWR MODE", amic_pwr_lvl_enum,
5977 tavil_amic_pwr_lvl_get, tavil_amic_pwr_lvl_put),
5978 SOC_ENUM_EXT("AMIC_3_4 PWR MODE", amic_pwr_lvl_enum,
5979 tavil_amic_pwr_lvl_get, tavil_amic_pwr_lvl_put),
5980 SOC_ENUM_EXT("AMIC_5_6 PWR MODE", amic_pwr_lvl_enum,
5981 tavil_amic_pwr_lvl_get, tavil_amic_pwr_lvl_put),
5982};
5983
5984static int tavil_dec_enum_put(struct snd_kcontrol *kcontrol,
5985 struct snd_ctl_elem_value *ucontrol)
5986{
5987 struct snd_soc_dapm_widget_list *wlist =
5988 dapm_kcontrol_get_wlist(kcontrol);
5989 struct snd_soc_dapm_widget *widget = wlist->widgets[0];
5990 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(widget->dapm);
5991 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
5992 unsigned int val;
5993 u16 mic_sel_reg = 0;
5994 u8 mic_sel;
5995
5996 val = ucontrol->value.enumerated.item[0];
5997 if (val > e->items - 1)
5998 return -EINVAL;
5999
6000 dev_dbg(codec->dev, "%s: wname: %s, val: 0x%x\n", __func__,
6001 widget->name, val);
6002
6003 switch (e->reg) {
6004 case WCD934X_CDC_TX_INP_MUX_ADC_MUX0_CFG1:
6005 if (e->shift_l == 0)
6006 mic_sel_reg = WCD934X_CDC_TX0_TX_PATH_CFG0;
6007 else if (e->shift_l == 2)
6008 mic_sel_reg = WCD934X_CDC_TX4_TX_PATH_CFG0;
6009 else if (e->shift_l == 4)
6010 mic_sel_reg = WCD934X_CDC_TX8_TX_PATH_CFG0;
6011 break;
6012 case WCD934X_CDC_TX_INP_MUX_ADC_MUX1_CFG1:
6013 if (e->shift_l == 0)
6014 mic_sel_reg = WCD934X_CDC_TX1_TX_PATH_CFG0;
6015 else if (e->shift_l == 2)
6016 mic_sel_reg = WCD934X_CDC_TX5_TX_PATH_CFG0;
6017 break;
6018 case WCD934X_CDC_TX_INP_MUX_ADC_MUX2_CFG1:
6019 if (e->shift_l == 0)
6020 mic_sel_reg = WCD934X_CDC_TX2_TX_PATH_CFG0;
6021 else if (e->shift_l == 2)
6022 mic_sel_reg = WCD934X_CDC_TX6_TX_PATH_CFG0;
6023 break;
6024 case WCD934X_CDC_TX_INP_MUX_ADC_MUX3_CFG1:
6025 if (e->shift_l == 0)
6026 mic_sel_reg = WCD934X_CDC_TX3_TX_PATH_CFG0;
6027 else if (e->shift_l == 2)
6028 mic_sel_reg = WCD934X_CDC_TX7_TX_PATH_CFG0;
6029 break;
6030 default:
6031 dev_err(codec->dev, "%s: e->reg: 0x%x not expected\n",
6032 __func__, e->reg);
6033 return -EINVAL;
6034 }
6035
6036 /* ADC: 0, DMIC: 1 */
6037 mic_sel = val ? 0x0 : 0x1;
6038 if (mic_sel_reg)
6039 snd_soc_update_bits(codec, mic_sel_reg, 1 << 7, mic_sel << 7);
6040
6041 return snd_soc_dapm_put_enum_double(kcontrol, ucontrol);
6042}
6043
6044static int tavil_int_dem_inp_mux_put(struct snd_kcontrol *kcontrol,
6045 struct snd_ctl_elem_value *ucontrol)
6046{
6047 struct snd_soc_dapm_widget_list *wlist =
6048 dapm_kcontrol_get_wlist(kcontrol);
6049 struct snd_soc_dapm_widget *widget = wlist->widgets[0];
6050 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(widget->dapm);
6051 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
6052 unsigned int val;
6053 unsigned short look_ahead_dly_reg = WCD934X_CDC_RX0_RX_PATH_CFG0;
6054
6055 val = ucontrol->value.enumerated.item[0];
6056 if (val >= e->items)
6057 return -EINVAL;
6058
6059 dev_dbg(codec->dev, "%s: wname: %s, val: 0x%x\n", __func__,
6060 widget->name, val);
6061
6062 if (e->reg == WCD934X_CDC_RX0_RX_PATH_SEC0)
6063 look_ahead_dly_reg = WCD934X_CDC_RX0_RX_PATH_CFG0;
6064 else if (e->reg == WCD934X_CDC_RX1_RX_PATH_SEC0)
6065 look_ahead_dly_reg = WCD934X_CDC_RX1_RX_PATH_CFG0;
6066 else if (e->reg == WCD934X_CDC_RX2_RX_PATH_SEC0)
6067 look_ahead_dly_reg = WCD934X_CDC_RX2_RX_PATH_CFG0;
6068
6069 /* Set Look Ahead Delay */
6070 snd_soc_update_bits(codec, look_ahead_dly_reg,
6071 0x08, (val ? 0x08 : 0x00));
6072 /* Set DEM INP Select */
6073 return snd_soc_dapm_put_enum_double(kcontrol, ucontrol);
6074}
6075
6076static const char * const rx_int0_7_mix_mux_text[] = {
6077 "ZERO", "RX0", "RX1", "RX2", "RX3", "RX4", "RX5",
6078 "RX6", "RX7", "PROXIMITY"
6079};
6080
6081static const char * const rx_int_mix_mux_text[] = {
6082 "ZERO", "RX0", "RX1", "RX2", "RX3", "RX4", "RX5",
6083 "RX6", "RX7"
6084};
6085
6086static const char * const rx_prim_mix_text[] = {
6087 "ZERO", "DEC0", "DEC1", "IIR0", "IIR1", "RX0", "RX1", "RX2",
6088 "RX3", "RX4", "RX5", "RX6", "RX7"
6089};
6090
6091static const char * const rx_sidetone_mix_text[] = {
6092 "ZERO", "SRC0", "SRC1", "SRC_SUM"
6093};
6094
6095static const char * const cdc_if_tx0_mux_text[] = {
6096 "ZERO", "RX_MIX_TX0", "DEC0", "DEC0_192"
6097};
6098static const char * const cdc_if_tx1_mux_text[] = {
6099 "ZERO", "RX_MIX_TX1", "DEC1", "DEC1_192"
6100};
6101static const char * const cdc_if_tx2_mux_text[] = {
6102 "ZERO", "RX_MIX_TX2", "DEC2", "DEC2_192"
6103};
6104static const char * const cdc_if_tx3_mux_text[] = {
6105 "ZERO", "RX_MIX_TX3", "DEC3", "DEC3_192"
6106};
6107static const char * const cdc_if_tx4_mux_text[] = {
6108 "ZERO", "RX_MIX_TX4", "DEC4", "DEC4_192"
6109};
6110static const char * const cdc_if_tx5_mux_text[] = {
6111 "ZERO", "RX_MIX_TX5", "DEC5", "DEC5_192"
6112};
6113static const char * const cdc_if_tx6_mux_text[] = {
6114 "ZERO", "RX_MIX_TX6", "DEC6", "DEC6_192"
6115};
6116static const char * const cdc_if_tx7_mux_text[] = {
6117 "ZERO", "RX_MIX_TX7", "DEC7", "DEC7_192"
6118};
6119static const char * const cdc_if_tx8_mux_text[] = {
6120 "ZERO", "RX_MIX_TX8", "DEC8", "DEC8_192"
6121};
6122static const char * const cdc_if_tx9_mux_text[] = {
6123 "ZERO", "DEC7", "DEC7_192"
6124};
6125static const char * const cdc_if_tx10_mux_text[] = {
6126 "ZERO", "DEC6", "DEC6_192"
6127};
6128static const char * const cdc_if_tx11_mux_text[] = {
6129 "DEC_0_5", "DEC_9_12", "MAD_AUDIO", "MAD_BRDCST"
6130};
6131static const char * const cdc_if_tx11_inp1_mux_text[] = {
6132 "ZERO", "DEC0", "DEC1", "DEC2", "DEC3", "DEC4",
6133 "DEC5", "RX_MIX_TX5", "DEC9_10", "DEC11_12"
6134};
6135static const char * const cdc_if_tx13_mux_text[] = {
6136 "CDC_DEC_5", "MAD_BRDCST"
6137};
6138static const char * const cdc_if_tx13_inp1_mux_text[] = {
6139 "ZERO", "DEC5", "DEC5_192"
6140};
6141
6142static const char * const iir_inp_mux_text[] = {
6143 "ZERO", "DEC0", "DEC1", "DEC2", "DEC3", "DEC4", "DEC5", "DEC6",
6144 "DEC7", "DEC8", "RX0", "RX1", "RX2", "RX3", "RX4", "RX5", "RX6", "RX7"
6145};
6146
6147static const char * const rx_int_dem_inp_mux_text[] = {
6148 "NORMAL_DSM_OUT", "CLSH_DSM_OUT",
6149};
6150
6151static const char * const rx_int0_1_interp_mux_text[] = {
6152 "ZERO", "RX INT0_1 MIX1",
6153};
6154
6155static const char * const rx_int1_1_interp_mux_text[] = {
6156 "ZERO", "RX INT1_1 MIX1",
6157};
6158
6159static const char * const rx_int2_1_interp_mux_text[] = {
6160 "ZERO", "RX INT2_1 MIX1",
6161};
6162
6163static const char * const rx_int3_1_interp_mux_text[] = {
6164 "ZERO", "RX INT3_1 MIX1",
6165};
6166
6167static const char * const rx_int4_1_interp_mux_text[] = {
6168 "ZERO", "RX INT4_1 MIX1",
6169};
6170
6171static const char * const rx_int7_1_interp_mux_text[] = {
6172 "ZERO", "RX INT7_1 MIX1",
6173};
6174
6175static const char * const rx_int8_1_interp_mux_text[] = {
6176 "ZERO", "RX INT8_1 MIX1",
6177};
6178
6179static const char * const rx_int0_2_interp_mux_text[] = {
6180 "ZERO", "RX INT0_2 MUX",
6181};
6182
6183static const char * const rx_int1_2_interp_mux_text[] = {
6184 "ZERO", "RX INT1_2 MUX",
6185};
6186
6187static const char * const rx_int2_2_interp_mux_text[] = {
6188 "ZERO", "RX INT2_2 MUX",
6189};
6190
6191static const char * const rx_int3_2_interp_mux_text[] = {
6192 "ZERO", "RX INT3_2 MUX",
6193};
6194
6195static const char * const rx_int4_2_interp_mux_text[] = {
6196 "ZERO", "RX INT4_2 MUX",
6197};
6198
6199static const char * const rx_int7_2_interp_mux_text[] = {
6200 "ZERO", "RX INT7_2 MUX",
6201};
6202
6203static const char * const rx_int8_2_interp_mux_text[] = {
6204 "ZERO", "RX INT8_2 MUX",
6205};
6206
6207static const char * const mad_sel_txt[] = {
6208 "SPE", "MSM"
6209};
6210
6211static const char * const mad_inp_mux_txt[] = {
6212 "MAD", "DEC1"
6213};
6214
6215static const char * const adc_mux_text[] = {
6216 "DMIC", "AMIC", "ANC_FB_TUNE1", "ANC_FB_TUNE2"
6217};
6218
6219static const char * const dmic_mux_text[] = {
6220 "ZERO", "DMIC0", "DMIC1", "DMIC2", "DMIC3", "DMIC4", "DMIC5"
6221};
6222
6223static const char * const amic_mux_text[] = {
6224 "ZERO", "ADC1", "ADC2", "ADC3", "ADC4"
6225};
6226
6227static const char * const amic4_5_sel_text[] = {
6228 "AMIC4", "AMIC5"
6229};
6230
6231static const char * const anc0_fb_mux_text[] = {
6232 "ZERO", "ANC_IN_HPHL", "ANC_IN_EAR", "ANC_IN_EAR_SPKR",
6233 "ANC_IN_LO1"
6234};
6235
6236static const char * const anc1_fb_mux_text[] = {
6237 "ZERO", "ANC_IN_HPHR", "ANC_IN_LO2"
6238};
6239
6240static const char * const rx_echo_mux_text[] = {
6241 "ZERO", "RX_MIX0", "RX_MIX1", "RX_MIX2", "RX_MIX3", "RX_MIX4",
6242 "RX_MIX5", "RX_MIX6", "RX_MIX7", "RX_MIX8"
6243};
6244
6245static const char *const slim_rx_mux_text[] = {
6246 "ZERO", "AIF1_PB", "AIF2_PB", "AIF3_PB", "AIF4_PB"
6247};
6248
6249static const char *const cdc_if_rx0_mux_text[] = {
6250 "SLIM RX0", "I2S_0 RX0"
6251};
6252static const char *const cdc_if_rx1_mux_text[] = {
6253 "SLIM RX1", "I2S_0 RX1"
6254};
6255static const char *const cdc_if_rx2_mux_text[] = {
6256 "SLIM RX2", "I2S_0 RX2"
6257};
6258static const char *const cdc_if_rx3_mux_text[] = {
6259 "SLIM RX3", "I2S_0 RX3"
6260};
6261static const char *const cdc_if_rx4_mux_text[] = {
6262 "SLIM RX4", "I2S_0 RX4"
6263};
6264static const char *const cdc_if_rx5_mux_text[] = {
6265 "SLIM RX5", "I2S_0 RX5"
6266};
6267static const char *const cdc_if_rx6_mux_text[] = {
6268 "SLIM RX6", "I2S_0 RX6"
6269};
6270static const char *const cdc_if_rx7_mux_text[] = {
6271 "SLIM RX7", "I2S_0 RX7"
6272};
6273
6274static const char * const asrc0_mux_text[] = {
6275 "ZERO", "ASRC_IN_HPHL", "ASRC_IN_LO1",
6276};
6277
6278static const char * const asrc1_mux_text[] = {
6279 "ZERO", "ASRC_IN_HPHR", "ASRC_IN_LO2",
6280};
6281
6282static const char * const asrc2_mux_text[] = {
6283 "ZERO", "ASRC_IN_SPKR1",
6284};
6285
6286static const char * const asrc3_mux_text[] = {
6287 "ZERO", "ASRC_IN_SPKR2",
6288};
6289
6290static const char * const native_mux_text[] = {
6291 "OFF", "ON",
6292};
6293
6294static const struct snd_kcontrol_new aif4_vi_mixer[] = {
6295 SOC_SINGLE_EXT("SPKR_VI_1", SND_SOC_NOPM, WCD934X_TX14, 1, 0,
6296 tavil_vi_feed_mixer_get, tavil_vi_feed_mixer_put),
6297 SOC_SINGLE_EXT("SPKR_VI_2", SND_SOC_NOPM, WCD934X_TX15, 1, 0,
6298 tavil_vi_feed_mixer_get, tavil_vi_feed_mixer_put),
6299};
6300
6301static const struct snd_kcontrol_new aif1_cap_mixer[] = {
6302 SOC_SINGLE_EXT("SLIM TX0", SND_SOC_NOPM, WCD934X_TX0, 1, 0,
6303 slim_tx_mixer_get, slim_tx_mixer_put),
6304 SOC_SINGLE_EXT("SLIM TX1", SND_SOC_NOPM, WCD934X_TX1, 1, 0,
6305 slim_tx_mixer_get, slim_tx_mixer_put),
6306 SOC_SINGLE_EXT("SLIM TX2", SND_SOC_NOPM, WCD934X_TX2, 1, 0,
6307 slim_tx_mixer_get, slim_tx_mixer_put),
6308 SOC_SINGLE_EXT("SLIM TX3", SND_SOC_NOPM, WCD934X_TX3, 1, 0,
6309 slim_tx_mixer_get, slim_tx_mixer_put),
6310 SOC_SINGLE_EXT("SLIM TX4", SND_SOC_NOPM, WCD934X_TX4, 1, 0,
6311 slim_tx_mixer_get, slim_tx_mixer_put),
6312 SOC_SINGLE_EXT("SLIM TX5", SND_SOC_NOPM, WCD934X_TX5, 1, 0,
6313 slim_tx_mixer_get, slim_tx_mixer_put),
6314 SOC_SINGLE_EXT("SLIM TX6", SND_SOC_NOPM, WCD934X_TX6, 1, 0,
6315 slim_tx_mixer_get, slim_tx_mixer_put),
6316 SOC_SINGLE_EXT("SLIM TX7", SND_SOC_NOPM, WCD934X_TX7, 1, 0,
6317 slim_tx_mixer_get, slim_tx_mixer_put),
6318 SOC_SINGLE_EXT("SLIM TX8", SND_SOC_NOPM, WCD934X_TX8, 1, 0,
6319 slim_tx_mixer_get, slim_tx_mixer_put),
6320 SOC_SINGLE_EXT("SLIM TX9", SND_SOC_NOPM, WCD934X_TX9, 1, 0,
6321 slim_tx_mixer_get, slim_tx_mixer_put),
6322 SOC_SINGLE_EXT("SLIM TX10", SND_SOC_NOPM, WCD934X_TX10, 1, 0,
6323 slim_tx_mixer_get, slim_tx_mixer_put),
6324 SOC_SINGLE_EXT("SLIM TX11", SND_SOC_NOPM, WCD934X_TX11, 1, 0,
6325 slim_tx_mixer_get, slim_tx_mixer_put),
6326 SOC_SINGLE_EXT("SLIM TX13", SND_SOC_NOPM, WCD934X_TX13, 1, 0,
6327 slim_tx_mixer_get, slim_tx_mixer_put),
6328};
6329
6330static const struct snd_kcontrol_new aif2_cap_mixer[] = {
6331 SOC_SINGLE_EXT("SLIM TX0", SND_SOC_NOPM, WCD934X_TX0, 1, 0,
6332 slim_tx_mixer_get, slim_tx_mixer_put),
6333 SOC_SINGLE_EXT("SLIM TX1", SND_SOC_NOPM, WCD934X_TX1, 1, 0,
6334 slim_tx_mixer_get, slim_tx_mixer_put),
6335 SOC_SINGLE_EXT("SLIM TX2", SND_SOC_NOPM, WCD934X_TX2, 1, 0,
6336 slim_tx_mixer_get, slim_tx_mixer_put),
6337 SOC_SINGLE_EXT("SLIM TX3", SND_SOC_NOPM, WCD934X_TX3, 1, 0,
6338 slim_tx_mixer_get, slim_tx_mixer_put),
6339 SOC_SINGLE_EXT("SLIM TX4", SND_SOC_NOPM, WCD934X_TX4, 1, 0,
6340 slim_tx_mixer_get, slim_tx_mixer_put),
6341 SOC_SINGLE_EXT("SLIM TX5", SND_SOC_NOPM, WCD934X_TX5, 1, 0,
6342 slim_tx_mixer_get, slim_tx_mixer_put),
6343 SOC_SINGLE_EXT("SLIM TX6", SND_SOC_NOPM, WCD934X_TX6, 1, 0,
6344 slim_tx_mixer_get, slim_tx_mixer_put),
6345 SOC_SINGLE_EXT("SLIM TX7", SND_SOC_NOPM, WCD934X_TX7, 1, 0,
6346 slim_tx_mixer_get, slim_tx_mixer_put),
6347 SOC_SINGLE_EXT("SLIM TX8", SND_SOC_NOPM, WCD934X_TX8, 1, 0,
6348 slim_tx_mixer_get, slim_tx_mixer_put),
6349 SOC_SINGLE_EXT("SLIM TX9", SND_SOC_NOPM, WCD934X_TX9, 1, 0,
6350 slim_tx_mixer_get, slim_tx_mixer_put),
6351 SOC_SINGLE_EXT("SLIM TX10", SND_SOC_NOPM, WCD934X_TX10, 1, 0,
6352 slim_tx_mixer_get, slim_tx_mixer_put),
6353 SOC_SINGLE_EXT("SLIM TX11", SND_SOC_NOPM, WCD934X_TX11, 1, 0,
6354 slim_tx_mixer_get, slim_tx_mixer_put),
6355 SOC_SINGLE_EXT("SLIM TX13", SND_SOC_NOPM, WCD934X_TX13, 1, 0,
6356 slim_tx_mixer_get, slim_tx_mixer_put),
6357};
6358
6359static const struct snd_kcontrol_new aif3_cap_mixer[] = {
6360 SOC_SINGLE_EXT("SLIM TX0", SND_SOC_NOPM, WCD934X_TX0, 1, 0,
6361 slim_tx_mixer_get, slim_tx_mixer_put),
6362 SOC_SINGLE_EXT("SLIM TX1", SND_SOC_NOPM, WCD934X_TX1, 1, 0,
6363 slim_tx_mixer_get, slim_tx_mixer_put),
6364 SOC_SINGLE_EXT("SLIM TX2", SND_SOC_NOPM, WCD934X_TX2, 1, 0,
6365 slim_tx_mixer_get, slim_tx_mixer_put),
6366 SOC_SINGLE_EXT("SLIM TX3", SND_SOC_NOPM, WCD934X_TX3, 1, 0,
6367 slim_tx_mixer_get, slim_tx_mixer_put),
6368 SOC_SINGLE_EXT("SLIM TX4", SND_SOC_NOPM, WCD934X_TX4, 1, 0,
6369 slim_tx_mixer_get, slim_tx_mixer_put),
6370 SOC_SINGLE_EXT("SLIM TX5", SND_SOC_NOPM, WCD934X_TX5, 1, 0,
6371 slim_tx_mixer_get, slim_tx_mixer_put),
6372 SOC_SINGLE_EXT("SLIM TX6", SND_SOC_NOPM, WCD934X_TX6, 1, 0,
6373 slim_tx_mixer_get, slim_tx_mixer_put),
6374 SOC_SINGLE_EXT("SLIM TX7", SND_SOC_NOPM, WCD934X_TX7, 1, 0,
6375 slim_tx_mixer_get, slim_tx_mixer_put),
6376 SOC_SINGLE_EXT("SLIM TX8", SND_SOC_NOPM, WCD934X_TX8, 1, 0,
6377 slim_tx_mixer_get, slim_tx_mixer_put),
6378 SOC_SINGLE_EXT("SLIM TX9", SND_SOC_NOPM, WCD934X_TX9, 1, 0,
6379 slim_tx_mixer_get, slim_tx_mixer_put),
6380 SOC_SINGLE_EXT("SLIM TX10", SND_SOC_NOPM, WCD934X_TX10, 1, 0,
6381 slim_tx_mixer_get, slim_tx_mixer_put),
6382 SOC_SINGLE_EXT("SLIM TX11", SND_SOC_NOPM, WCD934X_TX11, 1, 0,
6383 slim_tx_mixer_get, slim_tx_mixer_put),
6384 SOC_SINGLE_EXT("SLIM TX13", SND_SOC_NOPM, WCD934X_TX13, 1, 0,
6385 slim_tx_mixer_get, slim_tx_mixer_put),
6386};
6387
6388static const struct snd_kcontrol_new aif4_mad_mixer[] = {
6389 SOC_SINGLE_EXT("SLIM TX13", SND_SOC_NOPM, WCD934X_TX13, 1, 0,
6390 slim_tx_mixer_get, slim_tx_mixer_put),
6391};
6392
6393WCD_DAPM_ENUM_EXT(slim_rx0, SND_SOC_NOPM, 0, slim_rx_mux_text,
6394 slim_rx_mux_get, slim_rx_mux_put);
6395WCD_DAPM_ENUM_EXT(slim_rx1, SND_SOC_NOPM, 0, slim_rx_mux_text,
6396 slim_rx_mux_get, slim_rx_mux_put);
6397WCD_DAPM_ENUM_EXT(slim_rx2, SND_SOC_NOPM, 0, slim_rx_mux_text,
6398 slim_rx_mux_get, slim_rx_mux_put);
6399WCD_DAPM_ENUM_EXT(slim_rx3, SND_SOC_NOPM, 0, slim_rx_mux_text,
6400 slim_rx_mux_get, slim_rx_mux_put);
6401WCD_DAPM_ENUM_EXT(slim_rx4, SND_SOC_NOPM, 0, slim_rx_mux_text,
6402 slim_rx_mux_get, slim_rx_mux_put);
6403WCD_DAPM_ENUM_EXT(slim_rx5, SND_SOC_NOPM, 0, slim_rx_mux_text,
6404 slim_rx_mux_get, slim_rx_mux_put);
6405WCD_DAPM_ENUM_EXT(slim_rx6, SND_SOC_NOPM, 0, slim_rx_mux_text,
6406 slim_rx_mux_get, slim_rx_mux_put);
6407WCD_DAPM_ENUM_EXT(slim_rx7, SND_SOC_NOPM, 0, slim_rx_mux_text,
6408 slim_rx_mux_get, slim_rx_mux_put);
6409
6410WCD_DAPM_ENUM(cdc_if_rx0, SND_SOC_NOPM, 0, cdc_if_rx0_mux_text);
6411WCD_DAPM_ENUM(cdc_if_rx1, SND_SOC_NOPM, 0, cdc_if_rx1_mux_text);
6412WCD_DAPM_ENUM(cdc_if_rx2, SND_SOC_NOPM, 0, cdc_if_rx2_mux_text);
6413WCD_DAPM_ENUM(cdc_if_rx3, SND_SOC_NOPM, 0, cdc_if_rx3_mux_text);
6414WCD_DAPM_ENUM(cdc_if_rx4, SND_SOC_NOPM, 0, cdc_if_rx4_mux_text);
6415WCD_DAPM_ENUM(cdc_if_rx5, SND_SOC_NOPM, 0, cdc_if_rx5_mux_text);
6416WCD_DAPM_ENUM(cdc_if_rx6, SND_SOC_NOPM, 0, cdc_if_rx6_mux_text);
6417WCD_DAPM_ENUM(cdc_if_rx7, SND_SOC_NOPM, 0, cdc_if_rx7_mux_text);
6418
6419WCD_DAPM_ENUM(rx_int0_2, WCD934X_CDC_RX_INP_MUX_RX_INT0_CFG1, 0,
6420 rx_int0_7_mix_mux_text);
6421WCD_DAPM_ENUM(rx_int1_2, WCD934X_CDC_RX_INP_MUX_RX_INT1_CFG1, 0,
6422 rx_int_mix_mux_text);
6423WCD_DAPM_ENUM(rx_int2_2, WCD934X_CDC_RX_INP_MUX_RX_INT2_CFG1, 0,
6424 rx_int_mix_mux_text);
6425WCD_DAPM_ENUM(rx_int3_2, WCD934X_CDC_RX_INP_MUX_RX_INT3_CFG1, 0,
6426 rx_int_mix_mux_text);
6427WCD_DAPM_ENUM(rx_int4_2, WCD934X_CDC_RX_INP_MUX_RX_INT4_CFG1, 0,
6428 rx_int_mix_mux_text);
6429WCD_DAPM_ENUM(rx_int7_2, WCD934X_CDC_RX_INP_MUX_RX_INT7_CFG1, 0,
6430 rx_int0_7_mix_mux_text);
6431WCD_DAPM_ENUM(rx_int8_2, WCD934X_CDC_RX_INP_MUX_RX_INT8_CFG1, 0,
6432 rx_int_mix_mux_text);
6433
6434WCD_DAPM_ENUM(rx_int0_1_mix_inp0, WCD934X_CDC_RX_INP_MUX_RX_INT0_CFG0, 0,
6435 rx_prim_mix_text);
6436WCD_DAPM_ENUM(rx_int0_1_mix_inp1, WCD934X_CDC_RX_INP_MUX_RX_INT0_CFG0, 4,
6437 rx_prim_mix_text);
6438WCD_DAPM_ENUM(rx_int0_1_mix_inp2, WCD934X_CDC_RX_INP_MUX_RX_INT0_CFG1, 4,
6439 rx_prim_mix_text);
6440WCD_DAPM_ENUM(rx_int1_1_mix_inp0, WCD934X_CDC_RX_INP_MUX_RX_INT1_CFG0, 0,
6441 rx_prim_mix_text);
6442WCD_DAPM_ENUM(rx_int1_1_mix_inp1, WCD934X_CDC_RX_INP_MUX_RX_INT1_CFG0, 4,
6443 rx_prim_mix_text);
6444WCD_DAPM_ENUM(rx_int1_1_mix_inp2, WCD934X_CDC_RX_INP_MUX_RX_INT1_CFG1, 4,
6445 rx_prim_mix_text);
6446WCD_DAPM_ENUM(rx_int2_1_mix_inp0, WCD934X_CDC_RX_INP_MUX_RX_INT2_CFG0, 0,
6447 rx_prim_mix_text);
6448WCD_DAPM_ENUM(rx_int2_1_mix_inp1, WCD934X_CDC_RX_INP_MUX_RX_INT2_CFG0, 4,
6449 rx_prim_mix_text);
6450WCD_DAPM_ENUM(rx_int2_1_mix_inp2, WCD934X_CDC_RX_INP_MUX_RX_INT2_CFG1, 4,
6451 rx_prim_mix_text);
6452WCD_DAPM_ENUM(rx_int3_1_mix_inp0, WCD934X_CDC_RX_INP_MUX_RX_INT3_CFG0, 0,
6453 rx_prim_mix_text);
6454WCD_DAPM_ENUM(rx_int3_1_mix_inp1, WCD934X_CDC_RX_INP_MUX_RX_INT3_CFG0, 4,
6455 rx_prim_mix_text);
6456WCD_DAPM_ENUM(rx_int3_1_mix_inp2, WCD934X_CDC_RX_INP_MUX_RX_INT3_CFG1, 4,
6457 rx_prim_mix_text);
6458WCD_DAPM_ENUM(rx_int4_1_mix_inp0, WCD934X_CDC_RX_INP_MUX_RX_INT4_CFG0, 0,
6459 rx_prim_mix_text);
6460WCD_DAPM_ENUM(rx_int4_1_mix_inp1, WCD934X_CDC_RX_INP_MUX_RX_INT4_CFG0, 4,
6461 rx_prim_mix_text);
6462WCD_DAPM_ENUM(rx_int4_1_mix_inp2, WCD934X_CDC_RX_INP_MUX_RX_INT4_CFG1, 4,
6463 rx_prim_mix_text);
6464WCD_DAPM_ENUM(rx_int7_1_mix_inp0, WCD934X_CDC_RX_INP_MUX_RX_INT7_CFG0, 0,
6465 rx_prim_mix_text);
6466WCD_DAPM_ENUM(rx_int7_1_mix_inp1, WCD934X_CDC_RX_INP_MUX_RX_INT7_CFG0, 4,
6467 rx_prim_mix_text);
6468WCD_DAPM_ENUM(rx_int7_1_mix_inp2, WCD934X_CDC_RX_INP_MUX_RX_INT7_CFG1, 4,
6469 rx_prim_mix_text);
6470WCD_DAPM_ENUM(rx_int8_1_mix_inp0, WCD934X_CDC_RX_INP_MUX_RX_INT8_CFG0, 0,
6471 rx_prim_mix_text);
6472WCD_DAPM_ENUM(rx_int8_1_mix_inp1, WCD934X_CDC_RX_INP_MUX_RX_INT8_CFG0, 4,
6473 rx_prim_mix_text);
6474WCD_DAPM_ENUM(rx_int8_1_mix_inp2, WCD934X_CDC_RX_INP_MUX_RX_INT8_CFG1, 4,
6475 rx_prim_mix_text);
6476
6477WCD_DAPM_ENUM(rx_int0_mix2_inp, WCD934X_CDC_RX_INP_MUX_SIDETONE_SRC_CFG0, 0,
6478 rx_sidetone_mix_text);
6479WCD_DAPM_ENUM(rx_int1_mix2_inp, WCD934X_CDC_RX_INP_MUX_SIDETONE_SRC_CFG0, 2,
6480 rx_sidetone_mix_text);
6481WCD_DAPM_ENUM(rx_int2_mix2_inp, WCD934X_CDC_RX_INP_MUX_SIDETONE_SRC_CFG0, 4,
6482 rx_sidetone_mix_text);
6483WCD_DAPM_ENUM(rx_int3_mix2_inp, WCD934X_CDC_RX_INP_MUX_SIDETONE_SRC_CFG0, 6,
6484 rx_sidetone_mix_text);
6485WCD_DAPM_ENUM(rx_int4_mix2_inp, WCD934X_CDC_RX_INP_MUX_SIDETONE_SRC_CFG1, 0,
6486 rx_sidetone_mix_text);
6487WCD_DAPM_ENUM(rx_int7_mix2_inp, WCD934X_CDC_RX_INP_MUX_SIDETONE_SRC_CFG1, 2,
6488 rx_sidetone_mix_text);
6489
6490WCD_DAPM_ENUM(tx_adc_mux10, WCD934X_CDC_TX_INP_MUX_ADC_MUX1_CFG1, 4,
6491 adc_mux_text);
6492WCD_DAPM_ENUM(tx_adc_mux11, WCD934X_CDC_TX_INP_MUX_ADC_MUX2_CFG1, 4,
6493 adc_mux_text);
6494WCD_DAPM_ENUM(tx_adc_mux12, WCD934X_CDC_TX_INP_MUX_ADC_MUX3_CFG1, 4,
6495 adc_mux_text);
6496WCD_DAPM_ENUM(tx_adc_mux13, WCD934X_CDC_TX_INP_MUX_ADC_MUX0_CFG1, 6,
6497 adc_mux_text);
6498
6499
6500WCD_DAPM_ENUM(tx_dmic_mux0, WCD934X_CDC_TX_INP_MUX_ADC_MUX0_CFG0, 3,
6501 dmic_mux_text);
6502WCD_DAPM_ENUM(tx_dmic_mux1, WCD934X_CDC_TX_INP_MUX_ADC_MUX1_CFG0, 3,
6503 dmic_mux_text);
6504WCD_DAPM_ENUM(tx_dmic_mux2, WCD934X_CDC_TX_INP_MUX_ADC_MUX2_CFG0, 3,
6505 dmic_mux_text);
6506WCD_DAPM_ENUM(tx_dmic_mux3, WCD934X_CDC_TX_INP_MUX_ADC_MUX3_CFG0, 3,
6507 dmic_mux_text);
6508WCD_DAPM_ENUM(tx_dmic_mux4, WCD934X_CDC_TX_INP_MUX_ADC_MUX4_CFG0, 3,
6509 dmic_mux_text);
6510WCD_DAPM_ENUM(tx_dmic_mux5, WCD934X_CDC_TX_INP_MUX_ADC_MUX5_CFG0, 3,
6511 dmic_mux_text);
6512WCD_DAPM_ENUM(tx_dmic_mux6, WCD934X_CDC_TX_INP_MUX_ADC_MUX6_CFG0, 3,
6513 dmic_mux_text);
6514WCD_DAPM_ENUM(tx_dmic_mux7, WCD934X_CDC_TX_INP_MUX_ADC_MUX7_CFG0, 3,
6515 dmic_mux_text);
6516WCD_DAPM_ENUM(tx_dmic_mux8, WCD934X_CDC_TX_INP_MUX_ADC_MUX8_CFG0, 3,
6517 dmic_mux_text);
6518WCD_DAPM_ENUM(tx_dmic_mux10, WCD934X_CDC_TX_INP_MUX_ADC_MUX10_CFG0, 3,
6519 dmic_mux_text);
6520WCD_DAPM_ENUM(tx_dmic_mux11, WCD934X_CDC_TX_INP_MUX_ADC_MUX11_CFG0, 3,
6521 dmic_mux_text);
6522WCD_DAPM_ENUM(tx_dmic_mux12, WCD934X_CDC_TX_INP_MUX_ADC_MUX12_CFG0, 3,
6523 dmic_mux_text);
6524WCD_DAPM_ENUM(tx_dmic_mux13, WCD934X_CDC_TX_INP_MUX_ADC_MUX13_CFG0, 3,
6525 dmic_mux_text);
6526
6527
6528WCD_DAPM_ENUM(tx_amic_mux0, WCD934X_CDC_TX_INP_MUX_ADC_MUX0_CFG0, 0,
6529 amic_mux_text);
6530WCD_DAPM_ENUM(tx_amic_mux1, WCD934X_CDC_TX_INP_MUX_ADC_MUX1_CFG0, 0,
6531 amic_mux_text);
6532WCD_DAPM_ENUM(tx_amic_mux2, WCD934X_CDC_TX_INP_MUX_ADC_MUX2_CFG0, 0,
6533 amic_mux_text);
6534WCD_DAPM_ENUM(tx_amic_mux3, WCD934X_CDC_TX_INP_MUX_ADC_MUX3_CFG0, 0,
6535 amic_mux_text);
6536WCD_DAPM_ENUM(tx_amic_mux4, WCD934X_CDC_TX_INP_MUX_ADC_MUX4_CFG0, 0,
6537 amic_mux_text);
6538WCD_DAPM_ENUM(tx_amic_mux5, WCD934X_CDC_TX_INP_MUX_ADC_MUX5_CFG0, 0,
6539 amic_mux_text);
6540WCD_DAPM_ENUM(tx_amic_mux6, WCD934X_CDC_TX_INP_MUX_ADC_MUX6_CFG0, 0,
6541 amic_mux_text);
6542WCD_DAPM_ENUM(tx_amic_mux7, WCD934X_CDC_TX_INP_MUX_ADC_MUX7_CFG0, 0,
6543 amic_mux_text);
6544WCD_DAPM_ENUM(tx_amic_mux8, WCD934X_CDC_TX_INP_MUX_ADC_MUX8_CFG0, 0,
6545 amic_mux_text);
6546WCD_DAPM_ENUM(tx_amic_mux10, WCD934X_CDC_TX_INP_MUX_ADC_MUX10_CFG0, 0,
6547 amic_mux_text);
6548WCD_DAPM_ENUM(tx_amic_mux11, WCD934X_CDC_TX_INP_MUX_ADC_MUX11_CFG0, 0,
6549 amic_mux_text);
6550WCD_DAPM_ENUM(tx_amic_mux12, WCD934X_CDC_TX_INP_MUX_ADC_MUX12_CFG0, 0,
6551 amic_mux_text);
6552WCD_DAPM_ENUM(tx_amic_mux13, WCD934X_CDC_TX_INP_MUX_ADC_MUX13_CFG0, 0,
6553 amic_mux_text);
6554
6555WCD_DAPM_ENUM(tx_amic4_5, WCD934X_TX_NEW_AMIC_4_5_SEL, 7, amic4_5_sel_text);
6556
6557WCD_DAPM_ENUM(cdc_if_tx0, WCD934X_CDC_IF_ROUTER_TX_MUX_CFG0, 0,
6558 cdc_if_tx0_mux_text);
6559WCD_DAPM_ENUM(cdc_if_tx1, WCD934X_CDC_IF_ROUTER_TX_MUX_CFG0, 2,
6560 cdc_if_tx1_mux_text);
6561WCD_DAPM_ENUM(cdc_if_tx2, WCD934X_CDC_IF_ROUTER_TX_MUX_CFG0, 4,
6562 cdc_if_tx2_mux_text);
6563WCD_DAPM_ENUM(cdc_if_tx3, WCD934X_CDC_IF_ROUTER_TX_MUX_CFG0, 6,
6564 cdc_if_tx3_mux_text);
6565WCD_DAPM_ENUM(cdc_if_tx4, WCD934X_CDC_IF_ROUTER_TX_MUX_CFG1, 0,
6566 cdc_if_tx4_mux_text);
6567WCD_DAPM_ENUM(cdc_if_tx5, WCD934X_CDC_IF_ROUTER_TX_MUX_CFG1, 2,
6568 cdc_if_tx5_mux_text);
6569WCD_DAPM_ENUM(cdc_if_tx6, WCD934X_CDC_IF_ROUTER_TX_MUX_CFG1, 4,
6570 cdc_if_tx6_mux_text);
6571WCD_DAPM_ENUM(cdc_if_tx7, WCD934X_CDC_IF_ROUTER_TX_MUX_CFG1, 6,
6572 cdc_if_tx7_mux_text);
6573WCD_DAPM_ENUM(cdc_if_tx8, WCD934X_CDC_IF_ROUTER_TX_MUX_CFG2, 0,
6574 cdc_if_tx8_mux_text);
6575WCD_DAPM_ENUM(cdc_if_tx9, WCD934X_CDC_IF_ROUTER_TX_MUX_CFG2, 2,
6576 cdc_if_tx9_mux_text);
6577WCD_DAPM_ENUM(cdc_if_tx10, WCD934X_CDC_IF_ROUTER_TX_MUX_CFG2, 4,
6578 cdc_if_tx10_mux_text);
6579WCD_DAPM_ENUM(cdc_if_tx11_inp1, WCD934X_CDC_IF_ROUTER_TX_MUX_CFG3, 0,
6580 cdc_if_tx11_inp1_mux_text);
6581WCD_DAPM_ENUM(cdc_if_tx11, WCD934X_DATA_HUB_SB_TX11_INP_CFG, 0,
6582 cdc_if_tx11_mux_text);
6583WCD_DAPM_ENUM(cdc_if_tx13_inp1, WCD934X_CDC_IF_ROUTER_TX_MUX_CFG3, 4,
6584 cdc_if_tx13_inp1_mux_text);
6585WCD_DAPM_ENUM(cdc_if_tx13, WCD934X_DATA_HUB_SB_TX13_INP_CFG, 0,
6586 cdc_if_tx13_mux_text);
6587
6588WCD_DAPM_ENUM(rx_mix_tx0, WCD934X_CDC_RX_INP_MUX_RX_MIX_CFG0, 0,
6589 rx_echo_mux_text);
6590WCD_DAPM_ENUM(rx_mix_tx1, WCD934X_CDC_RX_INP_MUX_RX_MIX_CFG0, 4,
6591 rx_echo_mux_text);
6592WCD_DAPM_ENUM(rx_mix_tx2, WCD934X_CDC_RX_INP_MUX_RX_MIX_CFG1, 0,
6593 rx_echo_mux_text);
6594WCD_DAPM_ENUM(rx_mix_tx3, WCD934X_CDC_RX_INP_MUX_RX_MIX_CFG1, 4,
6595 rx_echo_mux_text);
6596WCD_DAPM_ENUM(rx_mix_tx4, WCD934X_CDC_RX_INP_MUX_RX_MIX_CFG2, 0,
6597 rx_echo_mux_text);
6598WCD_DAPM_ENUM(rx_mix_tx5, WCD934X_CDC_RX_INP_MUX_RX_MIX_CFG2, 4,
6599 rx_echo_mux_text);
6600WCD_DAPM_ENUM(rx_mix_tx6, WCD934X_CDC_RX_INP_MUX_RX_MIX_CFG3, 0,
6601 rx_echo_mux_text);
6602WCD_DAPM_ENUM(rx_mix_tx7, WCD934X_CDC_RX_INP_MUX_RX_MIX_CFG3, 4,
6603 rx_echo_mux_text);
6604WCD_DAPM_ENUM(rx_mix_tx8, WCD934X_CDC_RX_INP_MUX_RX_MIX_CFG4, 0,
6605 rx_echo_mux_text);
6606
6607WCD_DAPM_ENUM(iir0_inp0, WCD934X_CDC_SIDETONE_IIR_INP_MUX_IIR0_MIX_CFG0, 0,
6608 iir_inp_mux_text);
6609WCD_DAPM_ENUM(iir0_inp1, WCD934X_CDC_SIDETONE_IIR_INP_MUX_IIR0_MIX_CFG1, 0,
6610 iir_inp_mux_text);
6611WCD_DAPM_ENUM(iir0_inp2, WCD934X_CDC_SIDETONE_IIR_INP_MUX_IIR0_MIX_CFG2, 0,
6612 iir_inp_mux_text);
6613WCD_DAPM_ENUM(iir0_inp3, WCD934X_CDC_SIDETONE_IIR_INP_MUX_IIR0_MIX_CFG3, 0,
6614 iir_inp_mux_text);
6615WCD_DAPM_ENUM(iir1_inp0, WCD934X_CDC_SIDETONE_IIR_INP_MUX_IIR1_MIX_CFG0, 0,
6616 iir_inp_mux_text);
6617WCD_DAPM_ENUM(iir1_inp1, WCD934X_CDC_SIDETONE_IIR_INP_MUX_IIR1_MIX_CFG1, 0,
6618 iir_inp_mux_text);
6619WCD_DAPM_ENUM(iir1_inp2, WCD934X_CDC_SIDETONE_IIR_INP_MUX_IIR1_MIX_CFG2, 0,
6620 iir_inp_mux_text);
6621WCD_DAPM_ENUM(iir1_inp3, WCD934X_CDC_SIDETONE_IIR_INP_MUX_IIR1_MIX_CFG3, 0,
6622 iir_inp_mux_text);
6623
6624WCD_DAPM_ENUM(rx_int0_1_interp, SND_SOC_NOPM, 0, rx_int0_1_interp_mux_text);
6625WCD_DAPM_ENUM(rx_int1_1_interp, SND_SOC_NOPM, 0, rx_int1_1_interp_mux_text);
6626WCD_DAPM_ENUM(rx_int2_1_interp, SND_SOC_NOPM, 0, rx_int2_1_interp_mux_text);
6627WCD_DAPM_ENUM(rx_int3_1_interp, SND_SOC_NOPM, 0, rx_int3_1_interp_mux_text);
6628WCD_DAPM_ENUM(rx_int4_1_interp, SND_SOC_NOPM, 0, rx_int4_1_interp_mux_text);
6629WCD_DAPM_ENUM(rx_int7_1_interp, SND_SOC_NOPM, 0, rx_int7_1_interp_mux_text);
6630WCD_DAPM_ENUM(rx_int8_1_interp, SND_SOC_NOPM, 0, rx_int8_1_interp_mux_text);
6631
6632WCD_DAPM_ENUM(rx_int0_2_interp, SND_SOC_NOPM, 0, rx_int0_2_interp_mux_text);
6633WCD_DAPM_ENUM(rx_int1_2_interp, SND_SOC_NOPM, 0, rx_int1_2_interp_mux_text);
6634WCD_DAPM_ENUM(rx_int2_2_interp, SND_SOC_NOPM, 0, rx_int2_2_interp_mux_text);
6635WCD_DAPM_ENUM(rx_int3_2_interp, SND_SOC_NOPM, 0, rx_int3_2_interp_mux_text);
6636WCD_DAPM_ENUM(rx_int4_2_interp, SND_SOC_NOPM, 0, rx_int4_2_interp_mux_text);
6637WCD_DAPM_ENUM(rx_int7_2_interp, SND_SOC_NOPM, 0, rx_int7_2_interp_mux_text);
6638WCD_DAPM_ENUM(rx_int8_2_interp, SND_SOC_NOPM, 0, rx_int8_2_interp_mux_text);
6639
6640WCD_DAPM_ENUM(mad_sel, WCD934X_CPE_SS_SVA_CFG, 0,
6641 mad_sel_txt);
6642
6643WCD_DAPM_ENUM(mad_inp_mux, WCD934X_CPE_SS_SVA_CFG, 2,
6644 mad_inp_mux_txt);
6645
6646WCD_DAPM_ENUM_EXT(rx_int0_dem_inp, WCD934X_CDC_RX0_RX_PATH_SEC0, 0,
6647 rx_int_dem_inp_mux_text, snd_soc_dapm_get_enum_double,
6648 tavil_int_dem_inp_mux_put);
6649WCD_DAPM_ENUM_EXT(rx_int1_dem_inp, WCD934X_CDC_RX1_RX_PATH_SEC0, 0,
6650 rx_int_dem_inp_mux_text, snd_soc_dapm_get_enum_double,
6651 tavil_int_dem_inp_mux_put);
6652WCD_DAPM_ENUM_EXT(rx_int2_dem_inp, WCD934X_CDC_RX2_RX_PATH_SEC0, 0,
6653 rx_int_dem_inp_mux_text, snd_soc_dapm_get_enum_double,
6654 tavil_int_dem_inp_mux_put);
6655
6656WCD_DAPM_ENUM_EXT(tx_adc_mux0, WCD934X_CDC_TX_INP_MUX_ADC_MUX0_CFG1, 0,
6657 adc_mux_text, snd_soc_dapm_get_enum_double, tavil_dec_enum_put);
6658WCD_DAPM_ENUM_EXT(tx_adc_mux1, WCD934X_CDC_TX_INP_MUX_ADC_MUX1_CFG1, 0,
6659 adc_mux_text, snd_soc_dapm_get_enum_double, tavil_dec_enum_put);
6660WCD_DAPM_ENUM_EXT(tx_adc_mux2, WCD934X_CDC_TX_INP_MUX_ADC_MUX2_CFG1, 0,
6661 adc_mux_text, snd_soc_dapm_get_enum_double, tavil_dec_enum_put);
6662WCD_DAPM_ENUM_EXT(tx_adc_mux3, WCD934X_CDC_TX_INP_MUX_ADC_MUX3_CFG1, 0,
6663 adc_mux_text, snd_soc_dapm_get_enum_double, tavil_dec_enum_put);
6664WCD_DAPM_ENUM_EXT(tx_adc_mux4, WCD934X_CDC_TX_INP_MUX_ADC_MUX0_CFG1, 2,
6665 adc_mux_text, snd_soc_dapm_get_enum_double, tavil_dec_enum_put);
6666WCD_DAPM_ENUM_EXT(tx_adc_mux5, WCD934X_CDC_TX_INP_MUX_ADC_MUX1_CFG1, 2,
6667 adc_mux_text, snd_soc_dapm_get_enum_double, tavil_dec_enum_put);
6668WCD_DAPM_ENUM_EXT(tx_adc_mux6, WCD934X_CDC_TX_INP_MUX_ADC_MUX2_CFG1, 2,
6669 adc_mux_text, snd_soc_dapm_get_enum_double, tavil_dec_enum_put);
6670WCD_DAPM_ENUM_EXT(tx_adc_mux7, WCD934X_CDC_TX_INP_MUX_ADC_MUX3_CFG1, 2,
6671 adc_mux_text, snd_soc_dapm_get_enum_double, tavil_dec_enum_put);
6672WCD_DAPM_ENUM_EXT(tx_adc_mux8, WCD934X_CDC_TX_INP_MUX_ADC_MUX0_CFG1, 4,
6673 adc_mux_text, snd_soc_dapm_get_enum_double, tavil_dec_enum_put);
6674
6675WCD_DAPM_ENUM(asrc0, WCD934X_CDC_RX_INP_MUX_SPLINE_ASRC_CFG0, 0,
6676 asrc0_mux_text);
6677WCD_DAPM_ENUM(asrc1, WCD934X_CDC_RX_INP_MUX_SPLINE_ASRC_CFG0, 2,
6678 asrc1_mux_text);
6679WCD_DAPM_ENUM(asrc2, WCD934X_CDC_RX_INP_MUX_SPLINE_ASRC_CFG0, 4,
6680 asrc2_mux_text);
6681WCD_DAPM_ENUM(asrc3, WCD934X_CDC_RX_INP_MUX_SPLINE_ASRC_CFG0, 6,
6682 asrc3_mux_text);
6683
6684WCD_DAPM_ENUM(int1_1_native, SND_SOC_NOPM, 0, native_mux_text);
6685WCD_DAPM_ENUM(int2_1_native, SND_SOC_NOPM, 0, native_mux_text);
6686WCD_DAPM_ENUM(int3_1_native, SND_SOC_NOPM, 0, native_mux_text);
6687WCD_DAPM_ENUM(int4_1_native, SND_SOC_NOPM, 0, native_mux_text);
6688
6689WCD_DAPM_ENUM(int1_2_native, SND_SOC_NOPM, 0, native_mux_text);
6690WCD_DAPM_ENUM(int2_2_native, SND_SOC_NOPM, 0, native_mux_text);
6691WCD_DAPM_ENUM(int3_2_native, SND_SOC_NOPM, 0, native_mux_text);
6692WCD_DAPM_ENUM(int4_2_native, SND_SOC_NOPM, 0, native_mux_text);
6693WCD_DAPM_ENUM(int7_2_native, SND_SOC_NOPM, 0, native_mux_text);
6694WCD_DAPM_ENUM(int8_2_native, SND_SOC_NOPM, 0, native_mux_text);
6695
6696WCD_DAPM_ENUM(anc0_fb, WCD934X_CDC_RX_INP_MUX_ANC_CFG0, 0, anc0_fb_mux_text);
6697WCD_DAPM_ENUM(anc1_fb, WCD934X_CDC_RX_INP_MUX_ANC_CFG0, 3, anc1_fb_mux_text);
6698
6699static const struct snd_kcontrol_new anc_ear_switch =
6700 SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0);
6701
6702static const struct snd_kcontrol_new anc_ear_spkr_switch =
6703 SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0);
6704
6705static const struct snd_kcontrol_new anc_spkr_pa_switch =
6706 SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0);
6707
Meng Wangf45a20d2017-01-18 09:51:58 +08006708static const struct snd_kcontrol_new anc_hphl_pa_switch =
6709 SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0);
6710
6711static const struct snd_kcontrol_new anc_hphr_pa_switch =
6712 SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0);
6713
Banajit Goswamide8271c2017-01-18 00:28:59 -08006714static const struct snd_kcontrol_new mad_cpe1_switch =
6715 SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0);
6716
6717static const struct snd_kcontrol_new mad_cpe2_switch =
6718 SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0);
6719
6720static const struct snd_kcontrol_new mad_brdcst_switch =
6721 SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0);
6722
6723static const struct snd_kcontrol_new adc_us_mux0_switch =
6724 SOC_DAPM_SINGLE("US_Switch", SND_SOC_NOPM, 0, 1, 0);
6725
6726static const struct snd_kcontrol_new adc_us_mux1_switch =
6727 SOC_DAPM_SINGLE("US_Switch", SND_SOC_NOPM, 0, 1, 0);
6728
6729static const struct snd_kcontrol_new adc_us_mux2_switch =
6730 SOC_DAPM_SINGLE("US_Switch", SND_SOC_NOPM, 0, 1, 0);
6731
6732static const struct snd_kcontrol_new adc_us_mux3_switch =
6733 SOC_DAPM_SINGLE("US_Switch", SND_SOC_NOPM, 0, 1, 0);
6734
6735static const struct snd_kcontrol_new adc_us_mux4_switch =
6736 SOC_DAPM_SINGLE("US_Switch", SND_SOC_NOPM, 0, 1, 0);
6737
6738static const struct snd_kcontrol_new adc_us_mux5_switch =
6739 SOC_DAPM_SINGLE("US_Switch", SND_SOC_NOPM, 0, 1, 0);
6740
6741static const struct snd_kcontrol_new adc_us_mux6_switch =
6742 SOC_DAPM_SINGLE("US_Switch", SND_SOC_NOPM, 0, 1, 0);
6743
6744static const struct snd_kcontrol_new adc_us_mux7_switch =
6745 SOC_DAPM_SINGLE("US_Switch", SND_SOC_NOPM, 0, 1, 0);
6746
6747static const struct snd_kcontrol_new adc_us_mux8_switch =
6748 SOC_DAPM_SINGLE("US_Switch", SND_SOC_NOPM, 0, 1, 0);
6749
6750static const struct snd_kcontrol_new rx_int1_asrc_switch[] = {
6751 SOC_DAPM_SINGLE("HPHL Switch", SND_SOC_NOPM, 0, 1, 0),
6752};
6753
6754static const struct snd_kcontrol_new rx_int2_asrc_switch[] = {
6755 SOC_DAPM_SINGLE("HPHR Switch", SND_SOC_NOPM, 0, 1, 0),
6756};
6757
6758static const struct snd_kcontrol_new rx_int3_asrc_switch[] = {
6759 SOC_DAPM_SINGLE("LO1 Switch", SND_SOC_NOPM, 0, 1, 0),
6760};
6761
6762static const struct snd_kcontrol_new rx_int4_asrc_switch[] = {
6763 SOC_DAPM_SINGLE("LO2 Switch", SND_SOC_NOPM, 0, 1, 0),
6764};
6765
6766static int tavil_dsd_mixer_get(struct snd_kcontrol *kcontrol,
6767 struct snd_ctl_elem_value *ucontrol)
6768{
6769 struct snd_soc_dapm_context *dapm =
6770 snd_soc_dapm_kcontrol_dapm(kcontrol);
6771 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(dapm);
6772 struct tavil_priv *tavil_p = snd_soc_codec_get_drvdata(codec);
6773 struct soc_mixer_control *mc =
6774 (struct soc_mixer_control *)kcontrol->private_value;
6775 struct tavil_dsd_config *dsd_conf = tavil_p->dsd_config;
6776 int val;
6777
6778 val = tavil_dsd_get_current_mixer_value(dsd_conf, mc->shift);
6779
6780 ucontrol->value.integer.value[0] = ((val < 0) ? 0 : val);
6781
6782 return 0;
6783}
6784
6785static int tavil_dsd_mixer_put(struct snd_kcontrol *kcontrol,
6786 struct snd_ctl_elem_value *ucontrol)
6787{
6788 struct soc_mixer_control *mc =
6789 (struct soc_mixer_control *)kcontrol->private_value;
6790 struct snd_soc_dapm_context *dapm =
6791 snd_soc_dapm_kcontrol_dapm(kcontrol);
6792 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(dapm);
6793 struct tavil_priv *tavil_p = snd_soc_codec_get_drvdata(codec);
6794 unsigned int wval = ucontrol->value.integer.value[0];
6795 struct tavil_dsd_config *dsd_conf = tavil_p->dsd_config;
6796
6797 if (!dsd_conf)
6798 return 0;
6799
6800 mutex_lock(&tavil_p->codec_mutex);
6801
6802 tavil_dsd_set_out_select(dsd_conf, mc->shift);
6803 tavil_dsd_set_mixer_value(dsd_conf, mc->shift, wval);
6804
6805 mutex_unlock(&tavil_p->codec_mutex);
6806 snd_soc_dapm_mixer_update_power(dapm, kcontrol, wval, NULL);
6807
6808 return 0;
6809}
6810
6811static const struct snd_kcontrol_new hphl_mixer[] = {
6812 SOC_SINGLE_EXT("DSD HPHL Switch", SND_SOC_NOPM, INTERP_HPHL, 1, 0,
6813 tavil_dsd_mixer_get, tavil_dsd_mixer_put),
6814};
6815
6816static const struct snd_kcontrol_new hphr_mixer[] = {
6817 SOC_SINGLE_EXT("DSD HPHR Switch", SND_SOC_NOPM, INTERP_HPHR, 1, 0,
6818 tavil_dsd_mixer_get, tavil_dsd_mixer_put),
6819};
6820
6821static const struct snd_soc_dapm_widget tavil_dapm_widgets[] = {
6822 SND_SOC_DAPM_AIF_IN_E("AIF1 PB", "AIF1 Playback", 0, SND_SOC_NOPM,
6823 AIF1_PB, 0, tavil_codec_enable_slimrx,
6824 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
6825 SND_SOC_DAPM_AIF_IN_E("AIF2 PB", "AIF2 Playback", 0, SND_SOC_NOPM,
6826 AIF2_PB, 0, tavil_codec_enable_slimrx,
6827 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
6828 SND_SOC_DAPM_AIF_IN_E("AIF3 PB", "AIF3 Playback", 0, SND_SOC_NOPM,
6829 AIF3_PB, 0, tavil_codec_enable_slimrx,
6830 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
6831 SND_SOC_DAPM_AIF_IN_E("AIF4 PB", "AIF4 Playback", 0, SND_SOC_NOPM,
6832 AIF4_PB, 0, tavil_codec_enable_slimrx,
6833 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
6834
6835 WCD_DAPM_MUX("SLIM RX0 MUX", WCD934X_RX0, slim_rx0),
6836 WCD_DAPM_MUX("SLIM RX1 MUX", WCD934X_RX1, slim_rx1),
6837 WCD_DAPM_MUX("SLIM RX2 MUX", WCD934X_RX2, slim_rx2),
6838 WCD_DAPM_MUX("SLIM RX3 MUX", WCD934X_RX3, slim_rx3),
6839 WCD_DAPM_MUX("SLIM RX4 MUX", WCD934X_RX4, slim_rx4),
6840 WCD_DAPM_MUX("SLIM RX5 MUX", WCD934X_RX5, slim_rx5),
6841 WCD_DAPM_MUX("SLIM RX6 MUX", WCD934X_RX6, slim_rx6),
6842 WCD_DAPM_MUX("SLIM RX7 MUX", WCD934X_RX7, slim_rx7),
6843
6844 SND_SOC_DAPM_MIXER("SLIM RX0", SND_SOC_NOPM, 0, 0, NULL, 0),
6845 SND_SOC_DAPM_MIXER("SLIM RX1", SND_SOC_NOPM, 0, 0, NULL, 0),
6846 SND_SOC_DAPM_MIXER("SLIM RX2", SND_SOC_NOPM, 0, 0, NULL, 0),
6847 SND_SOC_DAPM_MIXER("SLIM RX3", SND_SOC_NOPM, 0, 0, NULL, 0),
6848 SND_SOC_DAPM_MIXER("SLIM RX4", SND_SOC_NOPM, 0, 0, NULL, 0),
6849 SND_SOC_DAPM_MIXER("SLIM RX5", SND_SOC_NOPM, 0, 0, NULL, 0),
6850 SND_SOC_DAPM_MIXER("SLIM RX6", SND_SOC_NOPM, 0, 0, NULL, 0),
6851 SND_SOC_DAPM_MIXER("SLIM RX7", SND_SOC_NOPM, 0, 0, NULL, 0),
6852
6853 WCD_DAPM_MUX("CDC_IF RX0 MUX", WCD934X_RX0, cdc_if_rx0),
6854 WCD_DAPM_MUX("CDC_IF RX1 MUX", WCD934X_RX1, cdc_if_rx1),
6855 WCD_DAPM_MUX("CDC_IF RX2 MUX", WCD934X_RX2, cdc_if_rx2),
6856 WCD_DAPM_MUX("CDC_IF RX3 MUX", WCD934X_RX3, cdc_if_rx3),
6857 WCD_DAPM_MUX("CDC_IF RX4 MUX", WCD934X_RX4, cdc_if_rx4),
6858 WCD_DAPM_MUX("CDC_IF RX5 MUX", WCD934X_RX5, cdc_if_rx5),
6859 WCD_DAPM_MUX("CDC_IF RX6 MUX", WCD934X_RX6, cdc_if_rx6),
6860 WCD_DAPM_MUX("CDC_IF RX7 MUX", WCD934X_RX7, cdc_if_rx7),
6861
6862 SND_SOC_DAPM_MUX_E("RX INT0_2 MUX", SND_SOC_NOPM, INTERP_EAR, 0,
6863 &rx_int0_2_mux, tavil_codec_enable_mix_path,
6864 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
6865 SND_SOC_DAPM_POST_PMD),
6866 SND_SOC_DAPM_MUX_E("RX INT1_2 MUX", SND_SOC_NOPM, INTERP_HPHL, 0,
6867 &rx_int1_2_mux, tavil_codec_enable_mix_path,
6868 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
6869 SND_SOC_DAPM_POST_PMD),
6870 SND_SOC_DAPM_MUX_E("RX INT2_2 MUX", SND_SOC_NOPM, INTERP_HPHR, 0,
6871 &rx_int2_2_mux, tavil_codec_enable_mix_path,
6872 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
6873 SND_SOC_DAPM_POST_PMD),
6874 SND_SOC_DAPM_MUX_E("RX INT3_2 MUX", SND_SOC_NOPM, INTERP_LO1, 0,
6875 &rx_int3_2_mux, tavil_codec_enable_mix_path,
6876 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
6877 SND_SOC_DAPM_POST_PMD),
6878 SND_SOC_DAPM_MUX_E("RX INT4_2 MUX", SND_SOC_NOPM, INTERP_LO2, 0,
6879 &rx_int4_2_mux, tavil_codec_enable_mix_path,
6880 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
6881 SND_SOC_DAPM_POST_PMD),
6882 SND_SOC_DAPM_MUX_E("RX INT7_2 MUX", SND_SOC_NOPM, INTERP_SPKR1, 0,
6883 &rx_int7_2_mux, tavil_codec_enable_mix_path,
6884 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
6885 SND_SOC_DAPM_POST_PMD),
6886 SND_SOC_DAPM_MUX_E("RX INT8_2 MUX", SND_SOC_NOPM, INTERP_SPKR2, 0,
6887 &rx_int8_2_mux, tavil_codec_enable_mix_path,
6888 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
6889 SND_SOC_DAPM_POST_PMD),
6890
6891 WCD_DAPM_MUX("RX INT0_1 MIX1 INP0", 0, rx_int0_1_mix_inp0),
6892 WCD_DAPM_MUX("RX INT0_1 MIX1 INP1", 0, rx_int0_1_mix_inp1),
6893 WCD_DAPM_MUX("RX INT0_1 MIX1 INP2", 0, rx_int0_1_mix_inp2),
6894 WCD_DAPM_MUX("RX INT1_1 MIX1 INP0", 0, rx_int1_1_mix_inp0),
6895 WCD_DAPM_MUX("RX INT1_1 MIX1 INP1", 0, rx_int1_1_mix_inp1),
6896 WCD_DAPM_MUX("RX INT1_1 MIX1 INP2", 0, rx_int1_1_mix_inp2),
6897 WCD_DAPM_MUX("RX INT2_1 MIX1 INP0", 0, rx_int2_1_mix_inp0),
6898 WCD_DAPM_MUX("RX INT2_1 MIX1 INP1", 0, rx_int2_1_mix_inp1),
6899 WCD_DAPM_MUX("RX INT2_1 MIX1 INP2", 0, rx_int2_1_mix_inp2),
6900 WCD_DAPM_MUX("RX INT3_1 MIX1 INP0", 0, rx_int3_1_mix_inp0),
6901 WCD_DAPM_MUX("RX INT3_1 MIX1 INP1", 0, rx_int3_1_mix_inp1),
6902 WCD_DAPM_MUX("RX INT3_1 MIX1 INP2", 0, rx_int3_1_mix_inp2),
6903 WCD_DAPM_MUX("RX INT4_1 MIX1 INP0", 0, rx_int4_1_mix_inp0),
6904 WCD_DAPM_MUX("RX INT4_1 MIX1 INP1", 0, rx_int4_1_mix_inp1),
6905 WCD_DAPM_MUX("RX INT4_1 MIX1 INP2", 0, rx_int4_1_mix_inp2),
6906
6907 SND_SOC_DAPM_MUX_E("RX INT7_1 MIX1 INP0", SND_SOC_NOPM, 0, 0,
6908 &rx_int7_1_mix_inp0_mux, tavil_codec_enable_swr,
6909 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
6910 SND_SOC_DAPM_MUX_E("RX INT7_1 MIX1 INP1", SND_SOC_NOPM, 0, 0,
6911 &rx_int7_1_mix_inp1_mux, tavil_codec_enable_swr,
6912 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
6913 SND_SOC_DAPM_MUX_E("RX INT7_1 MIX1 INP2", SND_SOC_NOPM, 0, 0,
6914 &rx_int7_1_mix_inp2_mux, tavil_codec_enable_swr,
6915 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
6916 SND_SOC_DAPM_MUX_E("RX INT8_1 MIX1 INP0", SND_SOC_NOPM, 0, 0,
6917 &rx_int8_1_mix_inp0_mux, tavil_codec_enable_swr,
6918 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
6919 SND_SOC_DAPM_MUX_E("RX INT8_1 MIX1 INP1", SND_SOC_NOPM, 0, 0,
6920 &rx_int8_1_mix_inp1_mux, tavil_codec_enable_swr,
6921 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
6922 SND_SOC_DAPM_MUX_E("RX INT8_1 MIX1 INP2", SND_SOC_NOPM, 0, 0,
6923 &rx_int8_1_mix_inp2_mux, tavil_codec_enable_swr,
6924 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
6925
6926 SND_SOC_DAPM_MIXER("RX INT0_1 MIX1", SND_SOC_NOPM, 0, 0, NULL, 0),
6927 SND_SOC_DAPM_MIXER("RX INT0 SEC MIX", SND_SOC_NOPM, 0, 0, NULL, 0),
6928 SND_SOC_DAPM_MIXER("RX INT1_1 MIX1", SND_SOC_NOPM, 0, 0, NULL, 0),
6929 SND_SOC_DAPM_MIXER("RX INT1 SEC MIX", SND_SOC_NOPM, 0, 0,
6930 rx_int1_asrc_switch, ARRAY_SIZE(rx_int1_asrc_switch)),
6931 SND_SOC_DAPM_MIXER("RX INT2_1 MIX1", SND_SOC_NOPM, 0, 0, NULL, 0),
6932 SND_SOC_DAPM_MIXER("RX INT2 SEC MIX", SND_SOC_NOPM, 0, 0,
6933 rx_int2_asrc_switch, ARRAY_SIZE(rx_int2_asrc_switch)),
6934 SND_SOC_DAPM_MIXER("RX INT3_1 MIX1", SND_SOC_NOPM, 0, 0, NULL, 0),
6935 SND_SOC_DAPM_MIXER("RX INT3 SEC MIX", SND_SOC_NOPM, 0, 0,
6936 rx_int3_asrc_switch, ARRAY_SIZE(rx_int3_asrc_switch)),
6937 SND_SOC_DAPM_MIXER("RX INT4_1 MIX1", SND_SOC_NOPM, 0, 0, NULL, 0),
6938 SND_SOC_DAPM_MIXER("RX INT4 SEC MIX", SND_SOC_NOPM, 0, 0,
6939 rx_int4_asrc_switch, ARRAY_SIZE(rx_int4_asrc_switch)),
6940 SND_SOC_DAPM_MIXER("RX INT7_1 MIX1", SND_SOC_NOPM, 0, 0, NULL, 0),
6941 SND_SOC_DAPM_MIXER("RX INT7 SEC MIX", SND_SOC_NOPM, 0, 0, NULL, 0),
6942 SND_SOC_DAPM_MIXER("RX INT8_1 MIX1", SND_SOC_NOPM, 0, 0, NULL, 0),
6943 SND_SOC_DAPM_MIXER("RX INT8 SEC MIX", SND_SOC_NOPM, 0, 0, NULL, 0),
6944
6945 SND_SOC_DAPM_MIXER("RX INT0 MIX2", SND_SOC_NOPM, 0, 0, NULL, 0),
6946 SND_SOC_DAPM_MIXER("RX INT1 MIX2", SND_SOC_NOPM, 0, 0, NULL, 0),
6947 SND_SOC_DAPM_MIXER("RX INT1 MIX3", SND_SOC_NOPM, 0, 0, hphl_mixer,
6948 ARRAY_SIZE(hphl_mixer)),
6949 SND_SOC_DAPM_MIXER("RX INT2 MIX2", SND_SOC_NOPM, 0, 0, NULL, 0),
6950 SND_SOC_DAPM_MIXER("RX INT2 MIX3", SND_SOC_NOPM, 0, 0, hphr_mixer,
6951 ARRAY_SIZE(hphr_mixer)),
6952 SND_SOC_DAPM_MIXER("RX INT3 MIX2", SND_SOC_NOPM, 0, 0, NULL, 0),
6953 SND_SOC_DAPM_MIXER("RX INT4 MIX2", SND_SOC_NOPM, 0, 0, NULL, 0),
6954 SND_SOC_DAPM_MIXER("RX INT7 MIX2", SND_SOC_NOPM, 0, 0, NULL, 0),
6955 SND_SOC_DAPM_MIXER_E("RX INT7 CHAIN", SND_SOC_NOPM, 0, 0,
6956 NULL, 0, tavil_codec_spk_boost_event,
6957 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
6958 SND_SOC_DAPM_MIXER_E("RX INT8 CHAIN", SND_SOC_NOPM, 0, 0,
6959 NULL, 0, tavil_codec_spk_boost_event,
6960 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
6961
6962 SND_SOC_DAPM_MUX_E("RX INT0 MIX2 INP", SND_SOC_NOPM, INTERP_EAR,
6963 0, &rx_int0_mix2_inp_mux, tavil_codec_enable_rx_path_clk,
6964 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
6965 SND_SOC_DAPM_MUX_E("RX INT1 MIX2 INP", SND_SOC_NOPM, INTERP_HPHL,
6966 0, &rx_int1_mix2_inp_mux, tavil_codec_enable_rx_path_clk,
6967 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
6968 SND_SOC_DAPM_MUX_E("RX INT2 MIX2 INP", SND_SOC_NOPM, INTERP_HPHR,
6969 0, &rx_int2_mix2_inp_mux, tavil_codec_enable_rx_path_clk,
6970 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
6971 SND_SOC_DAPM_MUX_E("RX INT3 MIX2 INP", SND_SOC_NOPM, INTERP_LO1,
6972 0, &rx_int3_mix2_inp_mux, tavil_codec_enable_rx_path_clk,
6973 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
6974 SND_SOC_DAPM_MUX_E("RX INT4 MIX2 INP", SND_SOC_NOPM, INTERP_LO2,
6975 0, &rx_int4_mix2_inp_mux, tavil_codec_enable_rx_path_clk,
6976 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
6977 SND_SOC_DAPM_MUX_E("RX INT7 MIX2 INP", SND_SOC_NOPM, INTERP_SPKR1,
6978 0, &rx_int7_mix2_inp_mux, tavil_codec_enable_rx_path_clk,
6979 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
6980
6981 WCD_DAPM_MUX("CDC_IF TX0 MUX", WCD934X_TX0, cdc_if_tx0),
6982 WCD_DAPM_MUX("CDC_IF TX1 MUX", WCD934X_TX1, cdc_if_tx1),
6983 WCD_DAPM_MUX("CDC_IF TX2 MUX", WCD934X_TX2, cdc_if_tx2),
6984 WCD_DAPM_MUX("CDC_IF TX3 MUX", WCD934X_TX3, cdc_if_tx3),
6985 WCD_DAPM_MUX("CDC_IF TX4 MUX", WCD934X_TX4, cdc_if_tx4),
6986 WCD_DAPM_MUX("CDC_IF TX5 MUX", WCD934X_TX5, cdc_if_tx5),
6987 WCD_DAPM_MUX("CDC_IF TX6 MUX", WCD934X_TX6, cdc_if_tx6),
6988 WCD_DAPM_MUX("CDC_IF TX7 MUX", WCD934X_TX7, cdc_if_tx7),
6989 WCD_DAPM_MUX("CDC_IF TX8 MUX", WCD934X_TX8, cdc_if_tx8),
6990 WCD_DAPM_MUX("CDC_IF TX9 MUX", WCD934X_TX9, cdc_if_tx9),
6991 WCD_DAPM_MUX("CDC_IF TX10 MUX", WCD934X_TX10, cdc_if_tx10),
6992 WCD_DAPM_MUX("CDC_IF TX11 MUX", WCD934X_TX11, cdc_if_tx11),
6993 WCD_DAPM_MUX("CDC_IF TX11 INP1 MUX", WCD934X_TX11, cdc_if_tx11_inp1),
6994 WCD_DAPM_MUX("CDC_IF TX13 MUX", WCD934X_TX13, cdc_if_tx13),
6995 WCD_DAPM_MUX("CDC_IF TX13 INP1 MUX", WCD934X_TX13, cdc_if_tx13_inp1),
6996
6997 SND_SOC_DAPM_MUX_E("ADC MUX0", WCD934X_CDC_TX0_TX_PATH_CTL, 5, 0,
6998 &tx_adc_mux0_mux, tavil_codec_enable_dec,
6999 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
7000 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
7001
7002 SND_SOC_DAPM_MUX_E("ADC MUX1", WCD934X_CDC_TX1_TX_PATH_CTL, 5, 0,
7003 &tx_adc_mux1_mux, tavil_codec_enable_dec,
7004 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
7005 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
7006
7007 SND_SOC_DAPM_MUX_E("ADC MUX2", WCD934X_CDC_TX2_TX_PATH_CTL, 5, 0,
7008 &tx_adc_mux2_mux, tavil_codec_enable_dec,
7009 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
7010 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
7011
7012 SND_SOC_DAPM_MUX_E("ADC MUX3", WCD934X_CDC_TX3_TX_PATH_CTL, 5, 0,
7013 &tx_adc_mux3_mux, tavil_codec_enable_dec,
7014 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
7015 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
7016
7017 SND_SOC_DAPM_MUX_E("ADC MUX4", WCD934X_CDC_TX4_TX_PATH_CTL, 5, 0,
7018 &tx_adc_mux4_mux, tavil_codec_enable_dec,
7019 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
7020 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
7021
7022 SND_SOC_DAPM_MUX_E("ADC MUX5", WCD934X_CDC_TX5_TX_PATH_CTL, 5, 0,
7023 &tx_adc_mux5_mux, tavil_codec_enable_dec,
7024 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
7025 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
7026
7027 SND_SOC_DAPM_MUX_E("ADC MUX6", WCD934X_CDC_TX6_TX_PATH_CTL, 5, 0,
7028 &tx_adc_mux6_mux, tavil_codec_enable_dec,
7029 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
7030 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
7031
7032 SND_SOC_DAPM_MUX_E("ADC MUX7", WCD934X_CDC_TX7_TX_PATH_CTL, 5, 0,
7033 &tx_adc_mux7_mux, tavil_codec_enable_dec,
7034 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
7035 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
7036
7037 SND_SOC_DAPM_MUX_E("ADC MUX8", WCD934X_CDC_TX8_TX_PATH_CTL, 5, 0,
7038 &tx_adc_mux8_mux, tavil_codec_enable_dec,
7039 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
7040 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
7041
7042 SND_SOC_DAPM_MUX_E("ADC MUX10", SND_SOC_NOPM, 10, 0, &tx_adc_mux10_mux,
7043 tavil_codec_tx_adc_cfg, SND_SOC_DAPM_POST_PMU),
7044
7045 SND_SOC_DAPM_MUX_E("ADC MUX11", SND_SOC_NOPM, 11, 0, &tx_adc_mux11_mux,
7046 tavil_codec_tx_adc_cfg, SND_SOC_DAPM_POST_PMU),
7047
7048 SND_SOC_DAPM_MUX_E("ADC MUX12", SND_SOC_NOPM, 12, 0, &tx_adc_mux12_mux,
7049 tavil_codec_tx_adc_cfg, SND_SOC_DAPM_POST_PMU),
7050
7051 SND_SOC_DAPM_MUX_E("ADC MUX13", SND_SOC_NOPM, 13, 0, &tx_adc_mux13_mux,
7052 tavil_codec_tx_adc_cfg, SND_SOC_DAPM_POST_PMU),
7053
7054 WCD_DAPM_MUX("DMIC MUX0", 0, tx_dmic_mux0),
7055 WCD_DAPM_MUX("DMIC MUX1", 0, tx_dmic_mux1),
7056 WCD_DAPM_MUX("DMIC MUX2", 0, tx_dmic_mux2),
7057 WCD_DAPM_MUX("DMIC MUX3", 0, tx_dmic_mux3),
7058 WCD_DAPM_MUX("DMIC MUX4", 0, tx_dmic_mux4),
7059 WCD_DAPM_MUX("DMIC MUX5", 0, tx_dmic_mux5),
7060 WCD_DAPM_MUX("DMIC MUX6", 0, tx_dmic_mux6),
7061 WCD_DAPM_MUX("DMIC MUX7", 0, tx_dmic_mux7),
7062 WCD_DAPM_MUX("DMIC MUX8", 0, tx_dmic_mux8),
7063 WCD_DAPM_MUX("DMIC MUX10", 0, tx_dmic_mux10),
7064 WCD_DAPM_MUX("DMIC MUX11", 0, tx_dmic_mux11),
7065 WCD_DAPM_MUX("DMIC MUX12", 0, tx_dmic_mux12),
7066 WCD_DAPM_MUX("DMIC MUX13", 0, tx_dmic_mux13),
7067
7068 WCD_DAPM_MUX("AMIC MUX0", 0, tx_amic_mux0),
7069 WCD_DAPM_MUX("AMIC MUX1", 0, tx_amic_mux1),
7070 WCD_DAPM_MUX("AMIC MUX2", 0, tx_amic_mux2),
7071 WCD_DAPM_MUX("AMIC MUX3", 0, tx_amic_mux3),
7072 WCD_DAPM_MUX("AMIC MUX4", 0, tx_amic_mux4),
7073 WCD_DAPM_MUX("AMIC MUX5", 0, tx_amic_mux5),
7074 WCD_DAPM_MUX("AMIC MUX6", 0, tx_amic_mux6),
7075 WCD_DAPM_MUX("AMIC MUX7", 0, tx_amic_mux7),
7076 WCD_DAPM_MUX("AMIC MUX8", 0, tx_amic_mux8),
7077 WCD_DAPM_MUX("AMIC MUX10", 0, tx_amic_mux10),
7078 WCD_DAPM_MUX("AMIC MUX11", 0, tx_amic_mux11),
7079 WCD_DAPM_MUX("AMIC MUX12", 0, tx_amic_mux12),
7080 WCD_DAPM_MUX("AMIC MUX13", 0, tx_amic_mux13),
7081
7082 SND_SOC_DAPM_ADC_E("ADC1", NULL, WCD934X_ANA_AMIC1, 7, 0,
7083 tavil_codec_enable_adc, SND_SOC_DAPM_PRE_PMU),
7084 SND_SOC_DAPM_ADC_E("ADC2", NULL, WCD934X_ANA_AMIC2, 7, 0,
7085 tavil_codec_enable_adc, SND_SOC_DAPM_PRE_PMU),
7086 SND_SOC_DAPM_ADC_E("ADC3", NULL, WCD934X_ANA_AMIC3, 7, 0,
7087 tavil_codec_enable_adc, SND_SOC_DAPM_PRE_PMU),
7088 SND_SOC_DAPM_ADC_E("ADC4", NULL, WCD934X_ANA_AMIC4, 7, 0,
7089 tavil_codec_enable_adc, SND_SOC_DAPM_PRE_PMU),
7090
7091 WCD_DAPM_MUX("AMIC4_5 SEL", 0, tx_amic4_5),
7092
7093 WCD_DAPM_MUX("ANC0 FB MUX", 0, anc0_fb),
7094 WCD_DAPM_MUX("ANC1 FB MUX", 0, anc1_fb),
7095
7096 SND_SOC_DAPM_INPUT("AMIC1"),
7097 SND_SOC_DAPM_INPUT("AMIC2"),
7098 SND_SOC_DAPM_INPUT("AMIC3"),
7099 SND_SOC_DAPM_INPUT("AMIC4"),
7100 SND_SOC_DAPM_INPUT("AMIC5"),
7101
7102 SND_SOC_DAPM_MICBIAS_E("MIC BIAS1", SND_SOC_NOPM, 0, 0,
7103 tavil_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
7104 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
7105 SND_SOC_DAPM_MICBIAS_E("MIC BIAS2", SND_SOC_NOPM, 0, 0,
7106 tavil_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
7107 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
7108 SND_SOC_DAPM_MICBIAS_E("MIC BIAS3", SND_SOC_NOPM, 0, 0,
7109 tavil_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
7110 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
7111 SND_SOC_DAPM_MICBIAS_E("MIC BIAS4", SND_SOC_NOPM, 0, 0,
7112 tavil_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
7113 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
7114
7115 /*
7116 * Not supply widget, this is used to recover HPH registers.
7117 * It is not connected to any other widgets
7118 */
7119 SND_SOC_DAPM_SUPPLY("RESET_HPH_REGISTERS", SND_SOC_NOPM,
7120 0, 0, tavil_codec_reset_hph_registers,
7121 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
7122
7123 SND_SOC_DAPM_MICBIAS_E(DAPM_MICBIAS1_STANDALONE, SND_SOC_NOPM, 0, 0,
7124 tavil_codec_force_enable_micbias,
7125 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
7126 SND_SOC_DAPM_MICBIAS_E(DAPM_MICBIAS2_STANDALONE, SND_SOC_NOPM, 0, 0,
7127 tavil_codec_force_enable_micbias,
7128 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
7129 SND_SOC_DAPM_MICBIAS_E(DAPM_MICBIAS3_STANDALONE, SND_SOC_NOPM, 0, 0,
7130 tavil_codec_force_enable_micbias,
7131 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
7132 SND_SOC_DAPM_MICBIAS_E(DAPM_MICBIAS4_STANDALONE, SND_SOC_NOPM, 0, 0,
7133 tavil_codec_force_enable_micbias,
7134 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
7135
7136 SND_SOC_DAPM_AIF_OUT_E("AIF1 CAP", "AIF1 Capture", 0, SND_SOC_NOPM,
7137 AIF1_CAP, 0, tavil_codec_enable_slimtx,
7138 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
7139 SND_SOC_DAPM_AIF_OUT_E("AIF2 CAP", "AIF2 Capture", 0, SND_SOC_NOPM,
7140 AIF2_CAP, 0, tavil_codec_enable_slimtx,
7141 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
7142 SND_SOC_DAPM_AIF_OUT_E("AIF3 CAP", "AIF3 Capture", 0, SND_SOC_NOPM,
7143 AIF3_CAP, 0, tavil_codec_enable_slimtx,
7144 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
7145 SND_SOC_DAPM_MIXER("AIF1_CAP Mixer", SND_SOC_NOPM, AIF1_CAP, 0,
7146 aif1_cap_mixer, ARRAY_SIZE(aif1_cap_mixer)),
7147 SND_SOC_DAPM_MIXER("AIF2_CAP Mixer", SND_SOC_NOPM, AIF2_CAP, 0,
7148 aif2_cap_mixer, ARRAY_SIZE(aif2_cap_mixer)),
7149 SND_SOC_DAPM_MIXER("AIF3_CAP Mixer", SND_SOC_NOPM, AIF3_CAP, 0,
7150 aif3_cap_mixer, ARRAY_SIZE(aif3_cap_mixer)),
7151 SND_SOC_DAPM_MIXER("AIF4_MAD Mixer", SND_SOC_NOPM, AIF4_MAD_TX, 0,
7152 aif4_mad_mixer, ARRAY_SIZE(aif4_mad_mixer)),
7153
7154 SND_SOC_DAPM_AIF_OUT_E("AIF4 VI", "VIfeed", 0, SND_SOC_NOPM,
7155 AIF4_VIFEED, 0, tavil_codec_enable_slimvi_feedback,
7156 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
7157
7158 SND_SOC_DAPM_AIF_OUT("AIF4 MAD", "AIF4 MAD TX", 0,
7159 SND_SOC_NOPM, 0, 0),
7160
7161 SND_SOC_DAPM_MIXER("AIF4_VI Mixer", SND_SOC_NOPM, AIF4_VIFEED, 0,
7162 aif4_vi_mixer, ARRAY_SIZE(aif4_vi_mixer)),
7163 SND_SOC_DAPM_INPUT("VIINPUT"),
7164
7165 SND_SOC_DAPM_MIXER("SLIM TX0", SND_SOC_NOPM, 0, 0, NULL, 0),
7166 SND_SOC_DAPM_MIXER("SLIM TX1", SND_SOC_NOPM, 0, 0, NULL, 0),
7167 SND_SOC_DAPM_MIXER("SLIM TX2", SND_SOC_NOPM, 0, 0, NULL, 0),
7168 SND_SOC_DAPM_MIXER("SLIM TX3", SND_SOC_NOPM, 0, 0, NULL, 0),
7169 SND_SOC_DAPM_MIXER("SLIM TX4", SND_SOC_NOPM, 0, 0, NULL, 0),
7170 SND_SOC_DAPM_MIXER("SLIM TX5", SND_SOC_NOPM, 0, 0, NULL, 0),
7171 SND_SOC_DAPM_MIXER("SLIM TX6", SND_SOC_NOPM, 0, 0, NULL, 0),
7172 SND_SOC_DAPM_MIXER("SLIM TX7", SND_SOC_NOPM, 0, 0, NULL, 0),
7173 SND_SOC_DAPM_MIXER("SLIM TX8", SND_SOC_NOPM, 0, 0, NULL, 0),
7174 SND_SOC_DAPM_MIXER("SLIM TX9", SND_SOC_NOPM, 0, 0, NULL, 0),
7175 SND_SOC_DAPM_MIXER("SLIM TX10", SND_SOC_NOPM, 0, 0, NULL, 0),
7176 SND_SOC_DAPM_MIXER("SLIM TX11", SND_SOC_NOPM, 0, 0, NULL, 0),
7177 SND_SOC_DAPM_MIXER("SLIM TX13", SND_SOC_NOPM, 0, 0, NULL, 0),
7178
7179 /* Digital Mic Inputs */
7180 SND_SOC_DAPM_ADC_E("DMIC0", NULL, SND_SOC_NOPM, 0, 0,
7181 tavil_codec_enable_dmic,
7182 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
7183 SND_SOC_DAPM_ADC_E("DMIC1", NULL, SND_SOC_NOPM, 0, 0,
7184 tavil_codec_enable_dmic,
7185 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
7186 SND_SOC_DAPM_ADC_E("DMIC2", NULL, SND_SOC_NOPM, 0, 0,
7187 tavil_codec_enable_dmic,
7188 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
7189 SND_SOC_DAPM_ADC_E("DMIC3", NULL, SND_SOC_NOPM, 0, 0,
7190 tavil_codec_enable_dmic,
7191 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
7192 SND_SOC_DAPM_ADC_E("DMIC4", NULL, SND_SOC_NOPM, 0, 0,
7193 tavil_codec_enable_dmic,
7194 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
7195 SND_SOC_DAPM_ADC_E("DMIC5", NULL, SND_SOC_NOPM, 0, 0,
7196 tavil_codec_enable_dmic,
7197 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
7198
7199 WCD_DAPM_MUX("IIR0 INP0 MUX", 0, iir0_inp0),
7200 WCD_DAPM_MUX("IIR0 INP1 MUX", 0, iir0_inp1),
7201 WCD_DAPM_MUX("IIR0 INP2 MUX", 0, iir0_inp2),
7202 WCD_DAPM_MUX("IIR0 INP3 MUX", 0, iir0_inp3),
7203 WCD_DAPM_MUX("IIR1 INP0 MUX", 0, iir1_inp0),
7204 WCD_DAPM_MUX("IIR1 INP1 MUX", 0, iir1_inp1),
7205 WCD_DAPM_MUX("IIR1 INP2 MUX", 0, iir1_inp2),
7206 WCD_DAPM_MUX("IIR1 INP3 MUX", 0, iir1_inp3),
7207
7208 SND_SOC_DAPM_MIXER_E("IIR0", WCD934X_CDC_SIDETONE_IIR0_IIR_PATH_CTL,
7209 4, 0, NULL, 0, tavil_codec_set_iir_gain,
7210 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
7211 SND_SOC_DAPM_MIXER_E("IIR1", WCD934X_CDC_SIDETONE_IIR1_IIR_PATH_CTL,
7212 4, 0, NULL, 0, tavil_codec_set_iir_gain,
7213 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
7214 SND_SOC_DAPM_MIXER("SRC0", WCD934X_CDC_SIDETONE_SRC0_ST_SRC_PATH_CTL,
7215 4, 0, NULL, 0),
7216 SND_SOC_DAPM_MIXER("SRC1", WCD934X_CDC_SIDETONE_SRC1_ST_SRC_PATH_CTL,
7217 4, 0, NULL, 0),
7218
7219 WCD_DAPM_MUX("RX MIX TX0 MUX", 0, rx_mix_tx0),
7220 WCD_DAPM_MUX("RX MIX TX1 MUX", 0, rx_mix_tx1),
7221 WCD_DAPM_MUX("RX MIX TX2 MUX", 0, rx_mix_tx2),
7222 WCD_DAPM_MUX("RX MIX TX3 MUX", 0, rx_mix_tx3),
7223 WCD_DAPM_MUX("RX MIX TX4 MUX", 0, rx_mix_tx4),
7224 WCD_DAPM_MUX("RX MIX TX5 MUX", 0, rx_mix_tx5),
7225 WCD_DAPM_MUX("RX MIX TX6 MUX", 0, rx_mix_tx6),
7226 WCD_DAPM_MUX("RX MIX TX7 MUX", 0, rx_mix_tx7),
7227 WCD_DAPM_MUX("RX MIX TX8 MUX", 0, rx_mix_tx8),
7228 WCD_DAPM_MUX("RX INT0 DEM MUX", 0, rx_int0_dem_inp),
7229 WCD_DAPM_MUX("RX INT1 DEM MUX", 0, rx_int1_dem_inp),
7230 WCD_DAPM_MUX("RX INT2 DEM MUX", 0, rx_int2_dem_inp),
7231
7232 SND_SOC_DAPM_MUX_E("RX INT0_1 INTERP", SND_SOC_NOPM, INTERP_EAR, 0,
7233 &rx_int0_1_interp_mux, tavil_codec_enable_main_path,
7234 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
7235 SND_SOC_DAPM_POST_PMD),
7236 SND_SOC_DAPM_MUX_E("RX INT1_1 INTERP", SND_SOC_NOPM, INTERP_HPHL, 0,
7237 &rx_int1_1_interp_mux, tavil_codec_enable_main_path,
7238 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
7239 SND_SOC_DAPM_POST_PMD),
7240 SND_SOC_DAPM_MUX_E("RX INT2_1 INTERP", SND_SOC_NOPM, INTERP_HPHR, 0,
7241 &rx_int2_1_interp_mux, tavil_codec_enable_main_path,
7242 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
7243 SND_SOC_DAPM_POST_PMD),
7244 SND_SOC_DAPM_MUX_E("RX INT3_1 INTERP", SND_SOC_NOPM, INTERP_LO1, 0,
7245 &rx_int3_1_interp_mux, tavil_codec_enable_main_path,
7246 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
7247 SND_SOC_DAPM_POST_PMD),
7248 SND_SOC_DAPM_MUX_E("RX INT4_1 INTERP", SND_SOC_NOPM, INTERP_LO2, 0,
7249 &rx_int4_1_interp_mux, tavil_codec_enable_main_path,
7250 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
7251 SND_SOC_DAPM_POST_PMD),
7252 SND_SOC_DAPM_MUX_E("RX INT7_1 INTERP", SND_SOC_NOPM, INTERP_SPKR1, 0,
7253 &rx_int7_1_interp_mux, tavil_codec_enable_main_path,
7254 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
7255 SND_SOC_DAPM_POST_PMD),
7256 SND_SOC_DAPM_MUX_E("RX INT8_1 INTERP", SND_SOC_NOPM, INTERP_SPKR2, 0,
7257 &rx_int8_1_interp_mux, tavil_codec_enable_main_path,
7258 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
7259 SND_SOC_DAPM_POST_PMD),
7260
7261 WCD_DAPM_MUX("RX INT0_2 INTERP", 0, rx_int0_2_interp),
7262 WCD_DAPM_MUX("RX INT1_2 INTERP", 0, rx_int1_2_interp),
7263 WCD_DAPM_MUX("RX INT2_2 INTERP", 0, rx_int2_2_interp),
7264 WCD_DAPM_MUX("RX INT3_2 INTERP", 0, rx_int3_2_interp),
7265 WCD_DAPM_MUX("RX INT4_2 INTERP", 0, rx_int4_2_interp),
7266 WCD_DAPM_MUX("RX INT7_2 INTERP", 0, rx_int7_2_interp),
7267 WCD_DAPM_MUX("RX INT8_2 INTERP", 0, rx_int8_2_interp),
7268
7269 SND_SOC_DAPM_SWITCH("ADC US MUX0", WCD934X_CDC_TX0_TX_PATH_192_CTL, 0,
7270 0, &adc_us_mux0_switch),
7271 SND_SOC_DAPM_SWITCH("ADC US MUX1", WCD934X_CDC_TX1_TX_PATH_192_CTL, 0,
7272 0, &adc_us_mux1_switch),
7273 SND_SOC_DAPM_SWITCH("ADC US MUX2", WCD934X_CDC_TX2_TX_PATH_192_CTL, 0,
7274 0, &adc_us_mux2_switch),
7275 SND_SOC_DAPM_SWITCH("ADC US MUX3", WCD934X_CDC_TX3_TX_PATH_192_CTL, 0,
7276 0, &adc_us_mux3_switch),
7277 SND_SOC_DAPM_SWITCH("ADC US MUX4", WCD934X_CDC_TX4_TX_PATH_192_CTL, 0,
7278 0, &adc_us_mux4_switch),
7279 SND_SOC_DAPM_SWITCH("ADC US MUX5", WCD934X_CDC_TX5_TX_PATH_192_CTL, 0,
7280 0, &adc_us_mux5_switch),
7281 SND_SOC_DAPM_SWITCH("ADC US MUX6", WCD934X_CDC_TX6_TX_PATH_192_CTL, 0,
7282 0, &adc_us_mux6_switch),
7283 SND_SOC_DAPM_SWITCH("ADC US MUX7", WCD934X_CDC_TX7_TX_PATH_192_CTL, 0,
7284 0, &adc_us_mux7_switch),
7285 SND_SOC_DAPM_SWITCH("ADC US MUX8", WCD934X_CDC_TX8_TX_PATH_192_CTL, 0,
7286 0, &adc_us_mux8_switch),
7287
7288 /* MAD related widgets */
7289 SND_SOC_DAPM_INPUT("MAD_CPE_INPUT"),
7290 SND_SOC_DAPM_INPUT("MADINPUT"),
7291
7292 WCD_DAPM_MUX("MAD_SEL MUX", 0, mad_sel),
7293 WCD_DAPM_MUX("MAD_INP MUX", 0, mad_inp_mux),
7294
7295 SND_SOC_DAPM_SWITCH_E("MAD_BROADCAST", SND_SOC_NOPM, 0, 0,
7296 &mad_brdcst_switch, tavil_codec_ape_enable_mad,
7297 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD),
7298
7299 SND_SOC_DAPM_SWITCH_E("MAD_CPE1", SND_SOC_NOPM, 0, 0,
7300 &mad_cpe1_switch, tavil_codec_cpe_mad_ctl,
7301 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD),
7302 SND_SOC_DAPM_SWITCH_E("MAD_CPE2", SND_SOC_NOPM, 0, 0,
7303 &mad_cpe2_switch, tavil_codec_cpe_mad_ctl,
7304 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD),
7305
7306 SND_SOC_DAPM_OUTPUT("MAD_CPE_OUT1"),
7307 SND_SOC_DAPM_OUTPUT("MAD_CPE_OUT2"),
7308
7309 SND_SOC_DAPM_DAC_E("RX INT0 DAC", NULL, SND_SOC_NOPM,
7310 0, 0, tavil_codec_ear_dac_event,
7311 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
7312 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
7313 SND_SOC_DAPM_DAC_E("RX INT1 DAC", NULL, WCD934X_ANA_HPH,
7314 5, 0, tavil_codec_hphl_dac_event,
7315 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
7316 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
7317 SND_SOC_DAPM_DAC_E("RX INT2 DAC", NULL, WCD934X_ANA_HPH,
7318 4, 0, tavil_codec_hphr_dac_event,
7319 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
7320 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
7321 SND_SOC_DAPM_DAC_E("RX INT3 DAC", NULL, SND_SOC_NOPM,
7322 0, 0, tavil_codec_lineout_dac_event,
7323 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
7324 SND_SOC_DAPM_DAC_E("RX INT4 DAC", NULL, SND_SOC_NOPM,
7325 0, 0, tavil_codec_lineout_dac_event,
7326 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
7327
7328 SND_SOC_DAPM_PGA_E("EAR PA", WCD934X_ANA_EAR, 7, 0, NULL, 0,
7329 tavil_codec_enable_ear_pa,
7330 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
7331 SND_SOC_DAPM_PGA_E("HPHL PA", WCD934X_ANA_HPH, 7, 0, NULL, 0,
7332 tavil_codec_enable_hphl_pa,
7333 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
7334 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
7335 SND_SOC_DAPM_PGA_E("HPHR PA", WCD934X_ANA_HPH, 6, 0, NULL, 0,
7336 tavil_codec_enable_hphr_pa,
7337 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
7338 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
7339 SND_SOC_DAPM_PGA_E("LINEOUT1 PA", WCD934X_ANA_LO_1_2, 7, 0, NULL, 0,
7340 tavil_codec_enable_lineout_pa,
7341 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
7342 SND_SOC_DAPM_POST_PMD),
7343 SND_SOC_DAPM_PGA_E("LINEOUT2 PA", WCD934X_ANA_LO_1_2, 6, 0, NULL, 0,
7344 tavil_codec_enable_lineout_pa,
7345 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
7346 SND_SOC_DAPM_POST_PMD),
7347 SND_SOC_DAPM_PGA_E("ANC EAR PA", WCD934X_ANA_EAR, 7, 0, NULL, 0,
7348 tavil_codec_enable_ear_pa, SND_SOC_DAPM_POST_PMU |
7349 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
7350 SND_SOC_DAPM_PGA_E("ANC SPK1 PA", SND_SOC_NOPM, 0, 0, NULL, 0,
7351 tavil_codec_enable_spkr_anc,
7352 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
Meng Wangf45a20d2017-01-18 09:51:58 +08007353 SND_SOC_DAPM_PGA_E("ANC HPHL PA", SND_SOC_NOPM, 0, 0, NULL, 0,
7354 tavil_codec_enable_hphl_pa,
7355 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
7356 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
7357 SND_SOC_DAPM_PGA_E("ANC HPHR PA", SND_SOC_NOPM, 0, 0, NULL, 0,
7358 tavil_codec_enable_hphr_pa,
7359 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
7360 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
Banajit Goswamide8271c2017-01-18 00:28:59 -08007361
7362 SND_SOC_DAPM_OUTPUT("EAR"),
7363 SND_SOC_DAPM_OUTPUT("HPHL"),
7364 SND_SOC_DAPM_OUTPUT("HPHR"),
7365 SND_SOC_DAPM_OUTPUT("LINEOUT1"),
7366 SND_SOC_DAPM_OUTPUT("LINEOUT2"),
7367 SND_SOC_DAPM_OUTPUT("SPK1 OUT"),
7368 SND_SOC_DAPM_OUTPUT("SPK2 OUT"),
7369 SND_SOC_DAPM_OUTPUT("ANC EAR"),
Meng Wangf45a20d2017-01-18 09:51:58 +08007370 SND_SOC_DAPM_OUTPUT("ANC HPHL"),
7371 SND_SOC_DAPM_OUTPUT("ANC HPHR"),
Banajit Goswamide8271c2017-01-18 00:28:59 -08007372
7373 SND_SOC_DAPM_SWITCH("ANC OUT EAR Enable", SND_SOC_NOPM, 0, 0,
7374 &anc_ear_switch),
7375 SND_SOC_DAPM_SWITCH("ANC OUT EAR SPKR Enable", SND_SOC_NOPM, 0, 0,
7376 &anc_ear_spkr_switch),
7377 SND_SOC_DAPM_SWITCH("ANC SPKR PA Enable", SND_SOC_NOPM, 0, 0,
7378 &anc_spkr_pa_switch),
7379
Meng Wangf45a20d2017-01-18 09:51:58 +08007380 SND_SOC_DAPM_SWITCH_E("ANC OUT HPHL Enable", SND_SOC_NOPM, INTERP_HPHL,
7381 0, &anc_hphl_pa_switch, tavil_anc_out_switch_cb,
7382 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD),
7383 SND_SOC_DAPM_SWITCH_E("ANC OUT HPHR Enable", SND_SOC_NOPM, INTERP_HPHR,
7384 0, &anc_hphr_pa_switch, tavil_anc_out_switch_cb,
7385 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD),
7386
Banajit Goswamide8271c2017-01-18 00:28:59 -08007387 SND_SOC_DAPM_SUPPLY("RX_BIAS", SND_SOC_NOPM, 0, 0,
7388 tavil_codec_enable_rx_bias,
7389 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
7390
7391 SND_SOC_DAPM_SUPPLY("RX INT1 NATIVE SUPPLY", SND_SOC_NOPM,
7392 INTERP_HPHL, 0, tavil_enable_native_supply,
7393 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD),
7394 SND_SOC_DAPM_SUPPLY("RX INT2 NATIVE SUPPLY", SND_SOC_NOPM,
7395 INTERP_HPHR, 0, tavil_enable_native_supply,
7396 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD),
7397 SND_SOC_DAPM_SUPPLY("RX INT3 NATIVE SUPPLY", SND_SOC_NOPM,
7398 INTERP_LO1, 0, tavil_enable_native_supply,
7399 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD),
7400 SND_SOC_DAPM_SUPPLY("RX INT4 NATIVE SUPPLY", SND_SOC_NOPM,
7401 INTERP_LO2, 0, tavil_enable_native_supply,
7402 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD),
7403 SND_SOC_DAPM_SUPPLY("RX INT7 NATIVE SUPPLY", SND_SOC_NOPM,
7404 INTERP_SPKR1, 0, tavil_enable_native_supply,
7405 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD),
7406 SND_SOC_DAPM_SUPPLY("RX INT8 NATIVE SUPPLY", SND_SOC_NOPM,
7407 INTERP_SPKR2, 0, tavil_enable_native_supply,
7408 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD),
7409
7410 WCD_DAPM_MUX("RX INT1_1 NATIVE MUX", 0, int1_1_native),
7411 WCD_DAPM_MUX("RX INT2_1 NATIVE MUX", 0, int2_1_native),
7412 WCD_DAPM_MUX("RX INT3_1 NATIVE MUX", 0, int3_1_native),
7413 WCD_DAPM_MUX("RX INT4_1 NATIVE MUX", 0, int4_1_native),
7414
7415 WCD_DAPM_MUX("RX INT1_2 NATIVE MUX", 0, int1_2_native),
7416 WCD_DAPM_MUX("RX INT2_2 NATIVE MUX", 0, int2_2_native),
7417 WCD_DAPM_MUX("RX INT3_2 NATIVE MUX", 0, int3_2_native),
7418 WCD_DAPM_MUX("RX INT4_2 NATIVE MUX", 0, int4_2_native),
7419 WCD_DAPM_MUX("RX INT7_2 NATIVE MUX", 0, int7_2_native),
7420 WCD_DAPM_MUX("RX INT8_2 NATIVE MUX", 0, int8_2_native),
7421
7422 SND_SOC_DAPM_MUX_E("ASRC0 MUX", SND_SOC_NOPM, ASRC0, 0,
7423 &asrc0_mux, tavil_codec_enable_asrc_resampler,
7424 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
7425 SND_SOC_DAPM_MUX_E("ASRC1 MUX", SND_SOC_NOPM, ASRC1, 0,
7426 &asrc1_mux, tavil_codec_enable_asrc_resampler,
7427 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
7428 SND_SOC_DAPM_MUX_E("ASRC2 MUX", SND_SOC_NOPM, ASRC2, 0,
7429 &asrc2_mux, tavil_codec_enable_asrc_resampler,
7430 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
7431 SND_SOC_DAPM_MUX_E("ASRC3 MUX", SND_SOC_NOPM, ASRC3, 0,
7432 &asrc3_mux, tavil_codec_enable_asrc_resampler,
7433 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
7434};
7435
7436static int tavil_get_channel_map(struct snd_soc_dai *dai,
7437 unsigned int *tx_num, unsigned int *tx_slot,
7438 unsigned int *rx_num, unsigned int *rx_slot)
7439{
7440 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(dai->codec);
7441 u32 i = 0;
7442 struct wcd9xxx_ch *ch;
7443 int ret = 0;
7444
7445 switch (dai->id) {
7446 case AIF1_PB:
7447 case AIF2_PB:
7448 case AIF3_PB:
7449 case AIF4_PB:
7450 if (!rx_slot || !rx_num) {
7451 dev_err(tavil->dev, "%s: Invalid rx_slot 0x%pK or rx_num 0x%pK\n",
7452 __func__, rx_slot, rx_num);
7453 ret = -EINVAL;
7454 break;
7455 }
7456 list_for_each_entry(ch, &tavil->dai[dai->id].wcd9xxx_ch_list,
7457 list) {
7458 dev_dbg(tavil->dev, "%s: slot_num %u ch->ch_num %d\n",
7459 __func__, i, ch->ch_num);
7460 rx_slot[i++] = ch->ch_num;
7461 }
7462 *rx_num = i;
7463 dev_dbg(tavil->dev, "%s: dai_name = %s dai_id = %x rx_num = %d\n",
7464 __func__, dai->name, dai->id, i);
7465 if (*rx_num == 0) {
7466 dev_err(tavil->dev, "%s: Channel list empty for dai_name = %s dai_id = %x\n",
7467 __func__, dai->name, dai->id);
7468 ret = -EINVAL;
7469 }
7470 break;
7471 case AIF1_CAP:
7472 case AIF2_CAP:
7473 case AIF3_CAP:
7474 case AIF4_MAD_TX:
7475 case AIF4_VIFEED:
7476 if (!tx_slot || !tx_num) {
7477 dev_err(tavil->dev, "%s: Invalid tx_slot 0x%pK or tx_num 0x%pK\n",
7478 __func__, tx_slot, tx_num);
7479 ret = -EINVAL;
7480 break;
7481 }
7482 list_for_each_entry(ch, &tavil->dai[dai->id].wcd9xxx_ch_list,
7483 list) {
7484 dev_dbg(tavil->dev, "%s: slot_num %u ch->ch_num %d\n",
7485 __func__, i, ch->ch_num);
7486 tx_slot[i++] = ch->ch_num;
7487 }
7488 *tx_num = i;
7489 dev_dbg(tavil->dev, "%s: dai_name = %s dai_id = %x tx_num = %d\n",
7490 __func__, dai->name, dai->id, i);
7491 if (*tx_num == 0) {
7492 dev_err(tavil->dev, "%s: Channel list empty for dai_name = %s dai_id = %x\n",
7493 __func__, dai->name, dai->id);
7494 ret = -EINVAL;
7495 }
7496 break;
7497 default:
7498 dev_err(tavil->dev, "%s: Invalid DAI ID %x\n",
7499 __func__, dai->id);
7500 ret = -EINVAL;
7501 break;
7502 }
7503
7504 return ret;
7505}
7506
7507static int tavil_set_channel_map(struct snd_soc_dai *dai,
7508 unsigned int tx_num, unsigned int *tx_slot,
7509 unsigned int rx_num, unsigned int *rx_slot)
7510{
7511 struct tavil_priv *tavil;
7512 struct wcd9xxx *core;
7513 struct wcd9xxx_codec_dai_data *dai_data = NULL;
7514
7515 tavil = snd_soc_codec_get_drvdata(dai->codec);
7516 core = dev_get_drvdata(dai->codec->dev->parent);
7517
7518 if (!tx_slot || !rx_slot) {
7519 dev_err(tavil->dev, "%s: Invalid tx_slot 0x%pK, rx_slot 0x%pK\n",
7520 __func__, tx_slot, rx_slot);
7521 return -EINVAL;
7522 }
7523 dev_dbg(tavil->dev, "%s(): dai_name = %s DAI-ID %x tx_ch %d rx_ch %d\n",
7524 __func__, dai->name, dai->id, tx_num, rx_num);
7525
7526 wcd9xxx_init_slimslave(core, core->slim->laddr,
7527 tx_num, tx_slot, rx_num, rx_slot);
7528 /* Reserve TX13 for MAD data channel */
7529 dai_data = &tavil->dai[AIF4_MAD_TX];
7530 if (dai_data)
7531 list_add_tail(&core->tx_chs[WCD934X_TX13].list,
7532 &dai_data->wcd9xxx_ch_list);
7533
7534 return 0;
7535}
7536
7537static int tavil_startup(struct snd_pcm_substream *substream,
7538 struct snd_soc_dai *dai)
7539{
7540 pr_debug("%s(): substream = %s stream = %d\n", __func__,
7541 substream->name, substream->stream);
7542
7543 return 0;
7544}
7545
7546static void tavil_shutdown(struct snd_pcm_substream *substream,
7547 struct snd_soc_dai *dai)
7548{
7549 pr_debug("%s(): substream = %s stream = %d\n", __func__,
7550 substream->name, substream->stream);
7551}
7552
7553static int tavil_set_decimator_rate(struct snd_soc_dai *dai,
7554 u32 sample_rate)
7555{
7556 struct snd_soc_codec *codec = dai->codec;
7557 struct wcd9xxx_ch *ch;
7558 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
7559 u32 tx_port = 0, tx_fs_rate = 0;
7560 u8 shift = 0, shift_val = 0, tx_mux_sel = 0;
7561 int decimator = -1;
7562 u16 tx_port_reg = 0, tx_fs_reg = 0;
7563
7564 switch (sample_rate) {
7565 case 8000:
7566 tx_fs_rate = 0;
7567 break;
7568 case 16000:
7569 tx_fs_rate = 1;
7570 break;
7571 case 32000:
7572 tx_fs_rate = 3;
7573 break;
7574 case 48000:
7575 tx_fs_rate = 4;
7576 break;
7577 case 96000:
7578 tx_fs_rate = 5;
7579 break;
7580 case 192000:
7581 tx_fs_rate = 6;
7582 break;
7583 default:
7584 dev_err(tavil->dev, "%s: Invalid TX sample rate: %d\n",
7585 __func__, sample_rate);
7586 return -EINVAL;
7587
7588 };
7589
7590 list_for_each_entry(ch, &tavil->dai[dai->id].wcd9xxx_ch_list, list) {
7591 tx_port = ch->port;
7592 dev_dbg(codec->dev, "%s: dai->id = %d, tx_port = %d",
7593 __func__, dai->id, tx_port);
7594
7595 if ((tx_port < 0) || (tx_port == 12) || (tx_port >= 14)) {
7596 dev_err(codec->dev, "%s: Invalid SLIM TX%u port. DAI ID: %d\n",
7597 __func__, tx_port, dai->id);
7598 return -EINVAL;
7599 }
7600 /* Find the SB TX MUX input - which decimator is connected */
7601 if (tx_port < 4) {
7602 tx_port_reg = WCD934X_CDC_IF_ROUTER_TX_MUX_CFG0;
7603 shift = (tx_port << 1);
7604 shift_val = 0x03;
7605 } else if ((tx_port >= 4) && (tx_port < 8)) {
7606 tx_port_reg = WCD934X_CDC_IF_ROUTER_TX_MUX_CFG1;
7607 shift = ((tx_port - 4) << 1);
7608 shift_val = 0x03;
7609 } else if ((tx_port >= 8) && (tx_port < 11)) {
7610 tx_port_reg = WCD934X_CDC_IF_ROUTER_TX_MUX_CFG2;
7611 shift = ((tx_port - 8) << 1);
7612 shift_val = 0x03;
7613 } else if (tx_port == 11) {
7614 tx_port_reg = WCD934X_CDC_IF_ROUTER_TX_MUX_CFG3;
7615 shift = 0;
7616 shift_val = 0x0F;
7617 } else if (tx_port == 13) {
7618 tx_port_reg = WCD934X_CDC_IF_ROUTER_TX_MUX_CFG3;
7619 shift = 4;
7620 shift_val = 0x03;
7621 }
7622 tx_mux_sel = snd_soc_read(codec, tx_port_reg) &
7623 (shift_val << shift);
7624 tx_mux_sel = tx_mux_sel >> shift;
7625
7626 if (tx_port <= 8) {
7627 if ((tx_mux_sel == 0x2) || (tx_mux_sel == 0x3))
7628 decimator = tx_port;
7629 } else if (tx_port <= 10) {
7630 if ((tx_mux_sel == 0x1) || (tx_mux_sel == 0x2))
7631 decimator = ((tx_port == 9) ? 7 : 6);
7632 } else if (tx_port == 11) {
7633 if ((tx_mux_sel >= 1) && (tx_mux_sel < 7))
7634 decimator = tx_mux_sel - 1;
7635 } else if (tx_port == 13) {
7636 if ((tx_mux_sel == 0x1) || (tx_mux_sel == 0x2))
7637 decimator = 5;
7638 }
7639
7640 if (decimator >= 0) {
7641 tx_fs_reg = WCD934X_CDC_TX0_TX_PATH_CTL +
7642 16 * decimator;
7643 dev_dbg(codec->dev, "%s: set DEC%u (-> SLIM_TX%u) rate to %u\n",
7644 __func__, decimator, tx_port, sample_rate);
7645 snd_soc_update_bits(codec, tx_fs_reg, 0x0F, tx_fs_rate);
7646 } else if ((tx_port <= 8) && (tx_mux_sel == 0x01)) {
7647 /* Check if the TX Mux input is RX MIX TXn */
7648 dev_dbg(codec->dev, "%s: RX_MIX_TX%u going to CDC_IF TX%u\n",
7649 __func__, tx_port, tx_port);
7650 } else {
7651 dev_err(codec->dev, "%s: ERROR: Invalid decimator: %d\n",
7652 __func__, decimator);
7653 return -EINVAL;
7654 }
7655 }
7656 return 0;
7657}
7658
7659static int tavil_set_mix_interpolator_rate(struct snd_soc_dai *dai,
7660 u8 rate_reg_val,
7661 u32 sample_rate)
7662{
7663 u8 int_2_inp;
7664 u32 j;
7665 u16 int_mux_cfg1, int_fs_reg;
7666 u8 int_mux_cfg1_val;
7667 struct snd_soc_codec *codec = dai->codec;
7668 struct wcd9xxx_ch *ch;
7669 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
7670
7671 list_for_each_entry(ch, &tavil->dai[dai->id].wcd9xxx_ch_list, list) {
7672 int_2_inp = INTn_2_INP_SEL_RX0 + ch->port -
7673 WCD934X_RX_PORT_START_NUMBER;
7674 if ((int_2_inp < INTn_2_INP_SEL_RX0) ||
7675 (int_2_inp > INTn_2_INP_SEL_RX7)) {
7676 dev_err(codec->dev, "%s: Invalid RX%u port, Dai ID is %d\n",
7677 __func__,
7678 (ch->port - WCD934X_RX_PORT_START_NUMBER),
7679 dai->id);
7680 return -EINVAL;
7681 }
7682
7683 int_mux_cfg1 = WCD934X_CDC_RX_INP_MUX_RX_INT0_CFG1;
7684 for (j = 0; j < WCD934X_NUM_INTERPOLATORS; j++) {
7685 /* Interpolators 5 and 6 are not aviliable in Tavil */
7686 if (j == INTERP_LO3_NA || j == INTERP_LO4_NA) {
7687 int_mux_cfg1 += 2;
7688 continue;
7689 }
7690 int_mux_cfg1_val = snd_soc_read(codec, int_mux_cfg1) &
7691 0x0F;
7692 if (int_mux_cfg1_val == int_2_inp) {
7693 /*
7694 * Ear mix path supports only 48, 96, 192,
7695 * 384KHz only
7696 */
7697 if ((j == INTERP_EAR) &&
7698 (rate_reg_val < 0x4 ||
7699 rate_reg_val > 0x7)) {
7700 dev_err_ratelimited(codec->dev,
7701 "%s: Invalid rate for AIF_PB DAI(%d)\n",
7702 __func__, dai->id);
7703 return -EINVAL;
7704 }
7705
7706 int_fs_reg = WCD934X_CDC_RX0_RX_PATH_MIX_CTL +
7707 20 * j;
7708 dev_dbg(codec->dev, "%s: AIF_PB DAI(%d) connected to INT%u_2\n",
7709 __func__, dai->id, j);
7710 dev_dbg(codec->dev, "%s: set INT%u_2 sample rate to %u\n",
7711 __func__, j, sample_rate);
7712 snd_soc_update_bits(codec, int_fs_reg, 0x0F,
7713 rate_reg_val);
7714 }
7715 int_mux_cfg1 += 2;
7716 }
7717 }
7718 return 0;
7719}
7720
7721static int tavil_set_prim_interpolator_rate(struct snd_soc_dai *dai,
7722 u8 rate_reg_val,
7723 u32 sample_rate)
7724{
7725 u8 int_1_mix1_inp;
7726 u32 j;
7727 u16 int_mux_cfg0, int_mux_cfg1;
7728 u16 int_fs_reg;
7729 u8 int_mux_cfg0_val, int_mux_cfg1_val;
7730 u8 inp0_sel, inp1_sel, inp2_sel;
7731 struct snd_soc_codec *codec = dai->codec;
7732 struct wcd9xxx_ch *ch;
7733 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
7734 struct tavil_dsd_config *dsd_conf = tavil->dsd_config;
7735
7736 list_for_each_entry(ch, &tavil->dai[dai->id].wcd9xxx_ch_list, list) {
7737 int_1_mix1_inp = INTn_1_INP_SEL_RX0 + ch->port -
7738 WCD934X_RX_PORT_START_NUMBER;
7739 if ((int_1_mix1_inp < INTn_1_INP_SEL_RX0) ||
7740 (int_1_mix1_inp > INTn_1_INP_SEL_RX7)) {
7741 dev_err(codec->dev, "%s: Invalid RX%u port, Dai ID is %d\n",
7742 __func__,
7743 (ch->port - WCD934X_RX_PORT_START_NUMBER),
7744 dai->id);
7745 return -EINVAL;
7746 }
7747
7748 int_mux_cfg0 = WCD934X_CDC_RX_INP_MUX_RX_INT0_CFG0;
7749
7750 /*
7751 * Loop through all interpolator MUX inputs and find out
7752 * to which interpolator input, the slim rx port
7753 * is connected
7754 */
7755 for (j = 0; j < WCD934X_NUM_INTERPOLATORS; j++) {
7756 /* Interpolators 5 and 6 are not aviliable in Tavil */
7757 if (j == INTERP_LO3_NA || j == INTERP_LO4_NA) {
7758 int_mux_cfg0 += 2;
7759 continue;
7760 }
7761 int_mux_cfg1 = int_mux_cfg0 + 1;
7762
7763 int_mux_cfg0_val = snd_soc_read(codec, int_mux_cfg0);
7764 int_mux_cfg1_val = snd_soc_read(codec, int_mux_cfg1);
7765 inp0_sel = int_mux_cfg0_val & 0x0F;
7766 inp1_sel = (int_mux_cfg0_val >> 4) & 0x0F;
7767 inp2_sel = (int_mux_cfg1_val >> 4) & 0x0F;
7768 if ((inp0_sel == int_1_mix1_inp) ||
7769 (inp1_sel == int_1_mix1_inp) ||
7770 (inp2_sel == int_1_mix1_inp)) {
7771 /*
7772 * Ear and speaker primary path does not support
7773 * native sample rates
7774 */
7775 if ((j == INTERP_EAR || j == INTERP_SPKR1 ||
7776 j == INTERP_SPKR2) &&
7777 (rate_reg_val > 0x7)) {
7778 dev_err_ratelimited(codec->dev,
7779 "%s: Invalid rate for AIF_PB DAI(%d)\n",
7780 __func__, dai->id);
7781 return -EINVAL;
7782 }
7783
7784 int_fs_reg = WCD934X_CDC_RX0_RX_PATH_CTL +
7785 20 * j;
7786 dev_dbg(codec->dev,
7787 "%s: AIF_PB DAI(%d) connected to INT%u_1\n",
7788 __func__, dai->id, j);
7789 dev_dbg(codec->dev,
7790 "%s: set INT%u_1 sample rate to %u\n",
7791 __func__, j, sample_rate);
7792 snd_soc_update_bits(codec, int_fs_reg, 0x0F,
7793 rate_reg_val);
7794 }
7795 int_mux_cfg0 += 2;
7796 }
7797 if (dsd_conf)
7798 tavil_dsd_set_interp_rate(dsd_conf, ch->port,
7799 sample_rate, rate_reg_val);
7800 }
7801
7802 return 0;
7803}
7804
7805
7806static int tavil_set_interpolator_rate(struct snd_soc_dai *dai,
7807 u32 sample_rate)
7808{
7809 struct snd_soc_codec *codec = dai->codec;
7810 int rate_val = 0;
7811 int i, ret;
7812
7813 for (i = 0; i < ARRAY_SIZE(sr_val_tbl); i++) {
7814 if (sample_rate == sr_val_tbl[i].sample_rate) {
7815 rate_val = sr_val_tbl[i].rate_val;
7816 break;
7817 }
7818 }
7819 if ((i == ARRAY_SIZE(sr_val_tbl)) || (rate_val < 0)) {
7820 dev_err(codec->dev, "%s: Unsupported sample rate: %d\n",
7821 __func__, sample_rate);
7822 return -EINVAL;
7823 }
7824
7825 ret = tavil_set_prim_interpolator_rate(dai, (u8)rate_val, sample_rate);
7826 if (ret)
7827 return ret;
7828 ret = tavil_set_mix_interpolator_rate(dai, (u8)rate_val, sample_rate);
7829 if (ret)
7830 return ret;
7831
7832 return ret;
7833}
7834
7835static int tavil_prepare(struct snd_pcm_substream *substream,
7836 struct snd_soc_dai *dai)
7837{
7838 pr_debug("%s(): substream = %s stream = %d\n", __func__,
7839 substream->name, substream->stream);
7840 return 0;
7841}
7842
7843static int tavil_vi_hw_params(struct snd_pcm_substream *substream,
7844 struct snd_pcm_hw_params *params,
7845 struct snd_soc_dai *dai)
7846{
7847 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(dai->codec);
7848
7849 dev_dbg(tavil->dev, "%s: dai_name = %s DAI-ID %x rate %d num_ch %d\n",
7850 __func__, dai->name, dai->id, params_rate(params),
7851 params_channels(params));
7852
7853 tavil->dai[dai->id].rate = params_rate(params);
7854 tavil->dai[dai->id].bit_width = 32;
7855
7856 return 0;
7857}
7858
7859static int tavil_hw_params(struct snd_pcm_substream *substream,
7860 struct snd_pcm_hw_params *params,
7861 struct snd_soc_dai *dai)
7862{
7863 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(dai->codec);
7864 int ret = 0;
7865
7866 dev_dbg(tavil->dev, "%s: dai_name = %s DAI-ID %x rate %d num_ch %d\n",
7867 __func__, dai->name, dai->id, params_rate(params),
7868 params_channels(params));
7869
7870 switch (substream->stream) {
7871 case SNDRV_PCM_STREAM_PLAYBACK:
7872 ret = tavil_set_interpolator_rate(dai, params_rate(params));
7873 if (ret) {
7874 dev_err(tavil->dev, "%s: cannot set sample rate: %u\n",
7875 __func__, params_rate(params));
7876 return ret;
7877 }
7878 switch (params_width(params)) {
7879 case 16:
7880 tavil->dai[dai->id].bit_width = 16;
7881 break;
7882 case 24:
7883 tavil->dai[dai->id].bit_width = 24;
7884 break;
7885 case 32:
7886 tavil->dai[dai->id].bit_width = 32;
7887 break;
7888 default:
7889 return -EINVAL;
7890 }
7891 tavil->dai[dai->id].rate = params_rate(params);
7892 break;
7893 case SNDRV_PCM_STREAM_CAPTURE:
7894 if (dai->id != AIF4_MAD_TX)
7895 ret = tavil_set_decimator_rate(dai,
7896 params_rate(params));
7897 if (ret) {
7898 dev_err(tavil->dev, "%s: cannot set TX Decimator rate: %d\n",
7899 __func__, ret);
7900 return ret;
7901 }
7902 switch (params_width(params)) {
7903 case 16:
7904 tavil->dai[dai->id].bit_width = 16;
7905 break;
7906 case 24:
7907 tavil->dai[dai->id].bit_width = 24;
7908 break;
7909 default:
7910 dev_err(tavil->dev, "%s: Invalid format 0x%x\n",
7911 __func__, params_width(params));
7912 return -EINVAL;
7913 };
7914 tavil->dai[dai->id].rate = params_rate(params);
7915 break;
7916 default:
7917 dev_err(tavil->dev, "%s: Invalid stream type %d\n", __func__,
7918 substream->stream);
7919 return -EINVAL;
7920 };
7921
7922 return 0;
7923}
7924
7925static struct snd_soc_dai_ops tavil_dai_ops = {
7926 .startup = tavil_startup,
7927 .shutdown = tavil_shutdown,
7928 .hw_params = tavil_hw_params,
7929 .prepare = tavil_prepare,
7930 .set_channel_map = tavil_set_channel_map,
7931 .get_channel_map = tavil_get_channel_map,
7932};
7933
7934static struct snd_soc_dai_ops tavil_vi_dai_ops = {
7935 .hw_params = tavil_vi_hw_params,
7936 .set_channel_map = tavil_set_channel_map,
7937 .get_channel_map = tavil_get_channel_map,
7938};
7939
7940static struct snd_soc_dai_driver tavil_dai[] = {
7941 {
7942 .name = "tavil_rx1",
7943 .id = AIF1_PB,
7944 .playback = {
7945 .stream_name = "AIF1 Playback",
7946 .rates = WCD934X_RATES_MASK | WCD934X_FRAC_RATES_MASK,
7947 .formats = WCD934X_FORMATS_S16_S24_S32_LE,
7948 .rate_min = 8000,
7949 .rate_max = 384000,
7950 .channels_min = 1,
7951 .channels_max = 2,
7952 },
7953 .ops = &tavil_dai_ops,
7954 },
7955 {
7956 .name = "tavil_tx1",
7957 .id = AIF1_CAP,
7958 .capture = {
7959 .stream_name = "AIF1 Capture",
7960 .rates = WCD934X_RATES_MASK,
7961 .formats = WCD934X_FORMATS_S16_S24_LE,
7962 .rate_min = 8000,
7963 .rate_max = 192000,
7964 .channels_min = 1,
7965 .channels_max = 4,
7966 },
7967 .ops = &tavil_dai_ops,
7968 },
7969 {
7970 .name = "tavil_rx2",
7971 .id = AIF2_PB,
7972 .playback = {
7973 .stream_name = "AIF2 Playback",
7974 .rates = WCD934X_RATES_MASK | WCD934X_FRAC_RATES_MASK,
7975 .formats = WCD934X_FORMATS_S16_S24_S32_LE,
7976 .rate_min = 8000,
7977 .rate_max = 384000,
7978 .channels_min = 1,
7979 .channels_max = 2,
7980 },
7981 .ops = &tavil_dai_ops,
7982 },
7983 {
7984 .name = "tavil_tx2",
7985 .id = AIF2_CAP,
7986 .capture = {
7987 .stream_name = "AIF2 Capture",
7988 .rates = WCD934X_RATES_MASK,
7989 .formats = WCD934X_FORMATS_S16_S24_LE,
7990 .rate_min = 8000,
7991 .rate_max = 192000,
7992 .channels_min = 1,
7993 .channels_max = 4,
7994 },
7995 .ops = &tavil_dai_ops,
7996 },
7997 {
7998 .name = "tavil_rx3",
7999 .id = AIF3_PB,
8000 .playback = {
8001 .stream_name = "AIF3 Playback",
8002 .rates = WCD934X_RATES_MASK | WCD934X_FRAC_RATES_MASK,
8003 .formats = WCD934X_FORMATS_S16_S24_S32_LE,
8004 .rate_min = 8000,
8005 .rate_max = 384000,
8006 .channels_min = 1,
8007 .channels_max = 2,
8008 },
8009 .ops = &tavil_dai_ops,
8010 },
8011 {
8012 .name = "tavil_tx3",
8013 .id = AIF3_CAP,
8014 .capture = {
8015 .stream_name = "AIF3 Capture",
8016 .rates = WCD934X_RATES_MASK,
8017 .formats = WCD934X_FORMATS_S16_S24_LE,
8018 .rate_min = 8000,
8019 .rate_max = 192000,
8020 .channels_min = 1,
8021 .channels_max = 4,
8022 },
8023 .ops = &tavil_dai_ops,
8024 },
8025 {
8026 .name = "tavil_rx4",
8027 .id = AIF4_PB,
8028 .playback = {
8029 .stream_name = "AIF4 Playback",
8030 .rates = WCD934X_RATES_MASK | WCD934X_FRAC_RATES_MASK,
8031 .formats = WCD934X_FORMATS_S16_S24_S32_LE,
8032 .rate_min = 8000,
8033 .rate_max = 384000,
8034 .channels_min = 1,
8035 .channels_max = 2,
8036 },
8037 .ops = &tavil_dai_ops,
8038 },
8039 {
8040 .name = "tavil_vifeedback",
8041 .id = AIF4_VIFEED,
8042 .capture = {
8043 .stream_name = "VIfeed",
8044 .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_48000,
8045 .formats = WCD934X_FORMATS_S16_S24_S32_LE,
8046 .rate_min = 8000,
8047 .rate_max = 48000,
8048 .channels_min = 1,
8049 .channels_max = 4,
8050 },
8051 .ops = &tavil_vi_dai_ops,
8052 },
8053 {
8054 .name = "tavil_mad1",
8055 .id = AIF4_MAD_TX,
8056 .capture = {
8057 .stream_name = "AIF4 MAD TX",
8058 .rates = SNDRV_PCM_RATE_16000,
8059 .formats = WCD934X_FORMATS_S16_LE,
8060 .rate_min = 16000,
8061 .rate_max = 16000,
8062 .channels_min = 1,
8063 .channels_max = 1,
8064 },
8065 .ops = &tavil_dai_ops,
8066 },
8067};
8068
8069static void tavil_codec_power_gate_digital_core(struct tavil_priv *tavil)
8070{
8071 struct snd_soc_codec *codec = tavil->codec;
8072
8073 if (!codec)
8074 return;
8075
8076 mutex_lock(&tavil->power_lock);
8077 dev_dbg(codec->dev, "%s: Entering power gating function, %d\n",
8078 __func__, tavil->power_active_ref);
8079
8080 if (tavil->power_active_ref > 0)
8081 goto exit;
8082
8083 wcd9xxx_set_power_state(tavil->wcd9xxx,
8084 WCD_REGION_POWER_COLLAPSE_BEGIN,
8085 WCD9XXX_DIG_CORE_REGION_1);
8086 snd_soc_update_bits(codec, WCD934X_CODEC_RPM_PWR_CDC_DIG_HM_CTL,
8087 0x04, 0x04);
8088 snd_soc_update_bits(codec, WCD934X_CODEC_RPM_PWR_CDC_DIG_HM_CTL,
8089 0x01, 0x00);
8090 snd_soc_update_bits(codec, WCD934X_CODEC_RPM_PWR_CDC_DIG_HM_CTL,
8091 0x02, 0x00);
8092 wcd9xxx_set_power_state(tavil->wcd9xxx, WCD_REGION_POWER_DOWN,
8093 WCD9XXX_DIG_CORE_REGION_1);
8094exit:
8095 dev_dbg(codec->dev, "%s: Exiting power gating function, %d\n",
8096 __func__, tavil->power_active_ref);
8097 mutex_unlock(&tavil->power_lock);
8098}
8099
8100static void tavil_codec_power_gate_work(struct work_struct *work)
8101{
8102 struct tavil_priv *tavil;
8103 struct delayed_work *dwork;
8104 struct snd_soc_codec *codec;
8105
8106 dwork = to_delayed_work(work);
8107 tavil = container_of(dwork, struct tavil_priv, power_gate_work);
8108 codec = tavil->codec;
8109
8110 if (!codec)
8111 return;
8112
8113 tavil_codec_power_gate_digital_core(tavil);
8114}
8115
8116/* called under power_lock acquisition */
8117static int tavil_dig_core_remove_power_collapse(struct snd_soc_codec *codec)
8118{
8119 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
8120
8121 snd_soc_write(codec, WCD934X_CODEC_RPM_PWR_CDC_DIG_HM_CTL, 0x5);
8122 snd_soc_write(codec, WCD934X_CODEC_RPM_PWR_CDC_DIG_HM_CTL, 0x7);
Banajit Goswamide8271c2017-01-18 00:28:59 -08008123 snd_soc_update_bits(codec, WCD934X_CODEC_RPM_RST_CTL, 0x02, 0x00);
8124 snd_soc_update_bits(codec, WCD934X_CODEC_RPM_RST_CTL, 0x02, 0x02);
Phani Kumar Uppalapati7a489c52017-01-30 17:47:26 -08008125 snd_soc_write(codec, WCD934X_CODEC_RPM_PWR_CDC_DIG_HM_CTL, 0x3);
Banajit Goswamide8271c2017-01-18 00:28:59 -08008126
8127 wcd9xxx_set_power_state(tavil->wcd9xxx,
8128 WCD_REGION_POWER_COLLAPSE_REMOVE,
8129 WCD9XXX_DIG_CORE_REGION_1);
8130 regcache_mark_dirty(codec->component.regmap);
8131 regcache_sync_region(codec->component.regmap,
8132 WCD934X_DIG_CORE_REG_MIN,
8133 WCD934X_DIG_CORE_REG_MAX);
8134
8135 return 0;
8136}
8137
8138static int tavil_dig_core_power_collapse(struct tavil_priv *tavil,
8139 int req_state)
8140{
8141 struct snd_soc_codec *codec;
8142 int cur_state;
8143
8144 /* Exit if feature is disabled */
8145 if (!dig_core_collapse_enable)
8146 return 0;
8147
8148 mutex_lock(&tavil->power_lock);
8149 if (req_state == POWER_COLLAPSE)
8150 tavil->power_active_ref--;
8151 else if (req_state == POWER_RESUME)
8152 tavil->power_active_ref++;
8153 else
8154 goto unlock_mutex;
8155
8156 if (tavil->power_active_ref < 0) {
8157 dev_dbg(tavil->dev, "%s: power_active_ref is negative\n",
8158 __func__);
8159 goto unlock_mutex;
8160 }
8161
8162 codec = tavil->codec;
8163 if (!codec)
8164 goto unlock_mutex;
8165
8166 if (req_state == POWER_COLLAPSE) {
8167 if (tavil->power_active_ref == 0) {
8168 schedule_delayed_work(&tavil->power_gate_work,
8169 msecs_to_jiffies(dig_core_collapse_timer * 1000));
8170 }
8171 } else if (req_state == POWER_RESUME) {
8172 if (tavil->power_active_ref == 1) {
8173 /*
8174 * At this point, there can be two cases:
8175 * 1. Core already in power collapse state
8176 * 2. Timer kicked in and still did not expire or
8177 * waiting for the power_lock
8178 */
8179 cur_state = wcd9xxx_get_current_power_state(
8180 tavil->wcd9xxx,
8181 WCD9XXX_DIG_CORE_REGION_1);
8182 if (cur_state == WCD_REGION_POWER_DOWN) {
8183 tavil_dig_core_remove_power_collapse(codec);
8184 } else {
8185 mutex_unlock(&tavil->power_lock);
8186 cancel_delayed_work_sync(
8187 &tavil->power_gate_work);
8188 mutex_lock(&tavil->power_lock);
8189 }
8190 }
8191 }
8192
8193unlock_mutex:
8194 mutex_unlock(&tavil->power_lock);
8195
8196 return 0;
8197}
8198
8199static int tavil_cdc_req_mclk_enable(struct tavil_priv *tavil,
8200 bool enable)
8201{
8202 int ret = 0;
8203
8204 if (enable) {
8205 ret = clk_prepare_enable(tavil->wcd_ext_clk);
8206 if (ret) {
8207 dev_err(tavil->dev, "%s: ext clk enable failed\n",
8208 __func__);
8209 goto done;
8210 }
8211 /* get BG */
8212 wcd_resmgr_enable_master_bias(tavil->resmgr);
8213 /* get MCLK */
8214 wcd_resmgr_enable_clk_block(tavil->resmgr, WCD_CLK_MCLK);
8215 } else {
8216 /* put MCLK */
8217 wcd_resmgr_disable_clk_block(tavil->resmgr, WCD_CLK_MCLK);
8218 /* put BG */
8219 wcd_resmgr_disable_master_bias(tavil->resmgr);
8220 clk_disable_unprepare(tavil->wcd_ext_clk);
8221 }
8222
8223done:
8224 return ret;
8225}
8226
8227static int __tavil_cdc_mclk_enable_locked(struct tavil_priv *tavil,
8228 bool enable)
8229{
8230 int ret = 0;
8231
8232 if (!tavil->wcd_ext_clk) {
8233 dev_err(tavil->dev, "%s: wcd ext clock is NULL\n", __func__);
8234 return -EINVAL;
8235 }
8236
8237 dev_dbg(tavil->dev, "%s: mclk_enable = %u\n", __func__, enable);
8238
8239 if (enable) {
8240 tavil_dig_core_power_collapse(tavil, POWER_RESUME);
8241 tavil_vote_svs(tavil, true);
8242 ret = tavil_cdc_req_mclk_enable(tavil, true);
8243 if (ret)
8244 goto done;
8245 } else {
8246 tavil_cdc_req_mclk_enable(tavil, false);
8247 tavil_vote_svs(tavil, false);
8248 tavil_dig_core_power_collapse(tavil, POWER_COLLAPSE);
8249 }
8250
8251done:
8252 return ret;
8253}
8254
8255static int __tavil_cdc_mclk_enable(struct tavil_priv *tavil,
8256 bool enable)
8257{
8258 int ret;
8259
8260 WCD9XXX_V2_BG_CLK_LOCK(tavil->resmgr);
8261 ret = __tavil_cdc_mclk_enable_locked(tavil, enable);
8262 WCD9XXX_V2_BG_CLK_UNLOCK(tavil->resmgr);
8263
8264 return ret;
8265}
8266
8267static ssize_t tavil_codec_version_read(struct snd_info_entry *entry,
8268 void *file_private_data,
8269 struct file *file,
8270 char __user *buf, size_t count,
8271 loff_t pos)
8272{
8273 struct tavil_priv *tavil;
8274 struct wcd9xxx *wcd9xxx;
8275 char buffer[TAVIL_VERSION_ENTRY_SIZE];
8276 int len = 0;
8277
8278 tavil = (struct tavil_priv *) entry->private_data;
8279 if (!tavil) {
8280 pr_err("%s: tavil priv is null\n", __func__);
8281 return -EINVAL;
8282 }
8283
8284 wcd9xxx = tavil->wcd9xxx;
8285
8286 switch (wcd9xxx->version) {
8287 case TAVIL_VERSION_WCD9340_1_0:
8288 len = snprintf(buffer, sizeof(buffer), "WCD9340_1_0\n");
8289 break;
8290 case TAVIL_VERSION_WCD9341_1_0:
8291 len = snprintf(buffer, sizeof(buffer), "WCD9341_1_0\n");
8292 break;
8293 case TAVIL_VERSION_WCD9340_1_1:
8294 len = snprintf(buffer, sizeof(buffer), "WCD9340_1_1\n");
8295 break;
8296 case TAVIL_VERSION_WCD9341_1_1:
8297 len = snprintf(buffer, sizeof(buffer), "WCD9341_1_1\n");
8298 break;
8299 default:
8300 len = snprintf(buffer, sizeof(buffer), "VER_UNDEFINED\n");
8301 }
8302
8303 return simple_read_from_buffer(buf, count, &pos, buffer, len);
8304}
8305
8306static struct snd_info_entry_ops tavil_codec_info_ops = {
8307 .read = tavil_codec_version_read,
8308};
8309
8310/*
8311 * tavil_codec_info_create_codec_entry - creates wcd934x module
8312 * @codec_root: The parent directory
8313 * @codec: Codec instance
8314 *
8315 * Creates wcd934x module and version entry under the given
8316 * parent directory.
8317 *
8318 * Return: 0 on success or negative error code on failure.
8319 */
8320int tavil_codec_info_create_codec_entry(struct snd_info_entry *codec_root,
8321 struct snd_soc_codec *codec)
8322{
8323 struct snd_info_entry *version_entry;
8324 struct tavil_priv *tavil;
8325 struct snd_soc_card *card;
8326
8327 if (!codec_root || !codec)
8328 return -EINVAL;
8329
8330 tavil = snd_soc_codec_get_drvdata(codec);
8331 card = codec->component.card;
Banajit Goswami7f40ea42017-01-30 13:32:41 -08008332 tavil->entry = snd_info_create_subdir(codec_root->module,
8333 "tavil", codec_root);
Banajit Goswamide8271c2017-01-18 00:28:59 -08008334 if (!tavil->entry) {
8335 dev_dbg(codec->dev, "%s: failed to create wcd934x entry\n",
8336 __func__);
8337 return -ENOMEM;
8338 }
8339
8340 version_entry = snd_info_create_card_entry(card->snd_card,
8341 "version",
8342 tavil->entry);
8343 if (!version_entry) {
8344 dev_dbg(codec->dev, "%s: failed to create wcd934x version entry\n",
8345 __func__);
8346 return -ENOMEM;
8347 }
8348
8349 version_entry->private_data = tavil;
8350 version_entry->size = TAVIL_VERSION_ENTRY_SIZE;
8351 version_entry->content = SNDRV_INFO_CONTENT_DATA;
8352 version_entry->c.ops = &tavil_codec_info_ops;
8353
8354 if (snd_info_register(version_entry) < 0) {
8355 snd_info_free_entry(version_entry);
8356 return -ENOMEM;
8357 }
8358 tavil->version_entry = version_entry;
8359
8360 return 0;
8361}
8362EXPORT_SYMBOL(tavil_codec_info_create_codec_entry);
8363
8364/**
8365 * tavil_cdc_mclk_enable - Enable/disable codec mclk
8366 *
8367 * @codec: codec instance
8368 * @enable: Indicates clk enable or disable
8369 *
8370 * Returns 0 on Success and error on failure
8371 */
8372int tavil_cdc_mclk_enable(struct snd_soc_codec *codec, bool enable)
8373{
8374 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
8375
8376 return __tavil_cdc_mclk_enable(tavil, enable);
8377}
8378EXPORT_SYMBOL(tavil_cdc_mclk_enable);
8379
8380static int __tavil_codec_internal_rco_ctrl(struct snd_soc_codec *codec,
8381 bool enable)
8382{
8383 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
8384 int ret = 0;
8385
8386 if (enable) {
8387 if (wcd_resmgr_get_clk_type(tavil->resmgr) ==
8388 WCD_CLK_RCO) {
8389 ret = wcd_resmgr_enable_clk_block(tavil->resmgr,
8390 WCD_CLK_RCO);
8391 } else {
8392 ret = tavil_cdc_req_mclk_enable(tavil, true);
8393 if (ret) {
8394 dev_err(codec->dev,
8395 "%s: mclk_enable failed, err = %d\n",
8396 __func__, ret);
8397 goto done;
8398 }
8399 ret = wcd_resmgr_enable_clk_block(tavil->resmgr,
8400 WCD_CLK_RCO);
8401 ret |= tavil_cdc_req_mclk_enable(tavil, false);
8402 }
8403
8404 } else {
8405 ret = wcd_resmgr_disable_clk_block(tavil->resmgr,
8406 WCD_CLK_RCO);
8407 }
8408
8409 if (ret) {
8410 dev_err(codec->dev, "%s: Error in %s RCO\n",
8411 __func__, (enable ? "enabling" : "disabling"));
8412 ret = -EINVAL;
8413 }
8414
8415done:
8416 return ret;
8417}
8418
8419/*
8420 * tavil_codec_internal_rco_ctrl: Enable/Disable codec's RCO clock
8421 * @codec: Handle to the codec
8422 * @enable: Indicates whether clock should be enabled or disabled
8423 */
8424static int tavil_codec_internal_rco_ctrl(struct snd_soc_codec *codec,
8425 bool enable)
8426{
8427 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
8428 int ret = 0;
8429
8430 WCD9XXX_V2_BG_CLK_LOCK(tavil->resmgr);
8431 ret = __tavil_codec_internal_rco_ctrl(codec, enable);
8432 WCD9XXX_V2_BG_CLK_UNLOCK(tavil->resmgr);
8433 return ret;
8434}
8435
8436static const struct wcd_resmgr_cb tavil_resmgr_cb = {
8437 .cdc_rco_ctrl = __tavil_codec_internal_rco_ctrl,
8438};
8439
8440static const struct tavil_reg_mask_val tavil_codec_mclk2_1_1_defaults[] = {
8441 {WCD934X_CLK_SYS_MCLK2_PRG1, 0x60, 0x20},
8442};
8443
8444static const struct tavil_reg_mask_val tavil_codec_mclk2_1_0_defaults[] = {
8445 /*
8446 * PLL Settings:
8447 * Clock Root: MCLK2,
8448 * Clock Source: EXT_CLK,
8449 * Clock Destination: MCLK2
8450 * Clock Freq In: 19.2MHz,
8451 * Clock Freq Out: 11.2896MHz
8452 */
8453 {WCD934X_CLK_SYS_MCLK2_PRG1, 0x60, 0x20},
8454 {WCD934X_CLK_SYS_INT_POST_DIV_REG0, 0xFF, 0x5E},
8455 {WCD934X_CLK_SYS_INT_POST_DIV_REG1, 0x1F, 0x1F},
8456 {WCD934X_CLK_SYS_INT_REF_DIV_REG0, 0xFF, 0x54},
8457 {WCD934X_CLK_SYS_INT_REF_DIV_REG1, 0xFF, 0x01},
8458 {WCD934X_CLK_SYS_INT_FILTER_REG1, 0x07, 0x04},
8459 {WCD934X_CLK_SYS_INT_PLL_L_VAL, 0xFF, 0x93},
8460 {WCD934X_CLK_SYS_INT_PLL_N_VAL, 0xFF, 0xFA},
8461 {WCD934X_CLK_SYS_INT_TEST_REG0, 0xFF, 0x90},
8462 {WCD934X_CLK_SYS_INT_PFD_CP_DSM_PROG, 0xFF, 0x7E},
8463 {WCD934X_CLK_SYS_INT_VCO_PROG, 0xFF, 0xF8},
8464 {WCD934X_CLK_SYS_INT_TEST_REG1, 0xFF, 0x68},
8465 {WCD934X_CLK_SYS_INT_LDO_LOCK_CFG, 0xFF, 0x40},
8466 {WCD934X_CLK_SYS_INT_DIG_LOCK_DET_CFG, 0xFF, 0x32},
8467};
8468
8469static const struct tavil_reg_mask_val tavil_codec_reg_defaults[] = {
8470 {WCD934X_BIAS_VBG_FINE_ADJ, 0xFF, 0x75},
8471 {WCD934X_CODEC_CPR_SVS_CX_VDD, 0xFF, 0x7C}, /* value in svs mode */
8472 {WCD934X_CODEC_CPR_SVS2_CX_VDD, 0xFF, 0x58}, /* value in svs2 mode */
8473 {WCD934X_CDC_RX0_RX_PATH_DSMDEM_CTL, 0x01, 0x01},
8474 {WCD934X_CDC_RX1_RX_PATH_DSMDEM_CTL, 0x01, 0x01},
8475 {WCD934X_CDC_RX2_RX_PATH_DSMDEM_CTL, 0x01, 0x01},
8476 {WCD934X_CDC_RX3_RX_PATH_DSMDEM_CTL, 0x01, 0x01},
8477 {WCD934X_CDC_RX4_RX_PATH_DSMDEM_CTL, 0x01, 0x01},
8478 {WCD934X_CDC_RX7_RX_PATH_DSMDEM_CTL, 0x01, 0x01},
8479 {WCD934X_CDC_RX8_RX_PATH_DSMDEM_CTL, 0x01, 0x01},
8480 {WCD934X_CDC_COMPANDER8_CTL7, 0x1E, 0x18},
8481 {WCD934X_CDC_COMPANDER7_CTL7, 0x1E, 0x18},
8482 {WCD934X_CDC_RX0_RX_PATH_SEC0, 0x08, 0x0},
8483 {WCD934X_CDC_CLSH_DECAY_CTRL, 0x03, 0x0},
8484 {WCD934X_MICB1_TEST_CTL_2, 0x07, 0x01},
8485 {WCD934X_CDC_BOOST0_BOOST_CFG1, 0x3F, 0x12},
8486 {WCD934X_CDC_BOOST0_BOOST_CFG2, 0x1C, 0x08},
8487 {WCD934X_CDC_BOOST1_BOOST_CFG1, 0x3F, 0x12},
8488 {WCD934X_CDC_BOOST1_BOOST_CFG2, 0x1C, 0x08},
8489 {WCD934X_CPE_SS_CPARMAD_BUFRDY_INT_PERIOD, 0x1F, 0x09},
8490 {WCD934X_CDC_TX0_TX_PATH_CFG1, 0x01, 0x00},
8491 {WCD934X_CDC_TX1_TX_PATH_CFG1, 0x01, 0x00},
8492 {WCD934X_CDC_TX2_TX_PATH_CFG1, 0x01, 0x00},
8493 {WCD934X_CDC_TX3_TX_PATH_CFG1, 0x01, 0x00},
8494 {WCD934X_CDC_TX4_TX_PATH_CFG1, 0x01, 0x00},
8495 {WCD934X_CDC_TX5_TX_PATH_CFG1, 0x01, 0x00},
8496 {WCD934X_CDC_TX6_TX_PATH_CFG1, 0x01, 0x00},
8497 {WCD934X_CDC_TX7_TX_PATH_CFG1, 0x01, 0x00},
8498 {WCD934X_CDC_TX8_TX_PATH_CFG1, 0x01, 0x00},
8499 {WCD934X_RX_OCP_CTL, 0x0F, 0x02}, /* OCP number of attempts is 2 */
8500 {WCD934X_HPH_OCP_CTL, 0xFF, 0x3A}, /* OCP current limit */
8501 {WCD934X_HPH_L_TEST, 0x01, 0x01},
8502 {WCD934X_HPH_R_TEST, 0x01, 0x01},
8503 {WCD934X_CPE_FLL_CONFIG_CTL_2, 0xFF, 0x20},
8504};
8505
8506static const struct tavil_reg_mask_val tavil_codec_reg_init_1_1_val[] = {
8507 {WCD934X_CDC_COMPANDER1_CTL7, 0x1E, 0x06},
8508 {WCD934X_CDC_COMPANDER2_CTL7, 0x1E, 0x06},
8509 {WCD934X_HPH_NEW_INT_RDAC_HD2_CTL_L, 0xFF, 0x84},
8510 {WCD934X_HPH_NEW_INT_RDAC_HD2_CTL_R, 0xFF, 0x84},
8511 {WCD934X_CDC_RX3_RX_PATH_SEC0, 0xFC, 0xF4},
8512 {WCD934X_CDC_RX4_RX_PATH_SEC0, 0xFC, 0xF4},
8513};
8514
8515static const struct tavil_cpr_reg_defaults cpr_defaults[] = {
8516 { 0x00000820, 0x00000094 },
8517 { 0x00000fC0, 0x00000048 },
8518 { 0x0000f000, 0x00000044 },
8519 { 0x0000bb80, 0xC0000178 },
8520 { 0x00000000, 0x00000160 },
8521 { 0x10854522, 0x00000060 },
8522 { 0x10854509, 0x00000064 },
8523 { 0x108544dd, 0x00000068 },
8524 { 0x108544ad, 0x0000006C },
8525 { 0x0000077E, 0x00000070 },
8526 { 0x000007da, 0x00000074 },
8527 { 0x00000000, 0x00000078 },
8528 { 0x00000000, 0x0000007C },
8529 { 0x00042029, 0x00000080 },
8530 { 0x4002002A, 0x00000090 },
8531 { 0x4002002B, 0x00000090 },
8532};
8533
8534static const struct tavil_reg_mask_val tavil_codec_reg_init_common_val[] = {
8535 {WCD934X_CDC_CLSH_K2_MSB, 0x0F, 0x00},
8536 {WCD934X_CDC_CLSH_K2_LSB, 0xFF, 0x60},
8537 {WCD934X_CPE_SS_DMIC_CFG, 0x80, 0x00},
8538 {WCD934X_CDC_BOOST0_BOOST_CTL, 0x70, 0x50},
8539 {WCD934X_CDC_BOOST1_BOOST_CTL, 0x70, 0x50},
8540 {WCD934X_CDC_RX7_RX_PATH_CFG1, 0x08, 0x08},
8541 {WCD934X_CDC_RX8_RX_PATH_CFG1, 0x08, 0x08},
8542 {WCD934X_CDC_TOP_TOP_CFG1, 0x02, 0x02},
8543 {WCD934X_CDC_TOP_TOP_CFG1, 0x01, 0x01},
8544 {WCD934X_CDC_TX9_SPKR_PROT_PATH_CFG0, 0x01, 0x01},
8545 {WCD934X_CDC_TX10_SPKR_PROT_PATH_CFG0, 0x01, 0x01},
8546 {WCD934X_CDC_TX11_SPKR_PROT_PATH_CFG0, 0x01, 0x01},
8547 {WCD934X_CDC_TX12_SPKR_PROT_PATH_CFG0, 0x01, 0x01},
8548 {WCD934X_DATA_HUB_SB_TX11_INP_CFG, 0x01, 0x01},
8549 {WCD934X_CDC_CLK_RST_CTRL_FS_CNT_CONTROL, 0x01, 0x01},
8550 {WCD934X_CDC_COMPANDER7_CTL3, 0x80, 0x80},
8551 {WCD934X_CDC_COMPANDER8_CTL3, 0x80, 0x80},
8552 {WCD934X_CDC_COMPANDER7_CTL7, 0x01, 0x01},
8553 {WCD934X_CDC_COMPANDER8_CTL7, 0x01, 0x01},
8554 {WCD934X_CODEC_RPM_CLK_GATE, 0x08, 0x00},
8555 {WCD934X_TLMM_DMIC3_CLK_PINCFG, 0xFF, 0x0a},
8556 {WCD934X_TLMM_DMIC3_DATA_PINCFG, 0xFF, 0x0a},
8557 {WCD934X_CPE_SS_SVA_CFG, 0x60, 0x00},
8558};
8559
8560static void tavil_codec_init_reg(struct tavil_priv *priv)
8561{
8562 struct snd_soc_codec *codec = priv->codec;
8563 u32 i;
8564
8565 for (i = 0; i < ARRAY_SIZE(tavil_codec_reg_init_common_val); i++)
8566 snd_soc_update_bits(codec,
8567 tavil_codec_reg_init_common_val[i].reg,
8568 tavil_codec_reg_init_common_val[i].mask,
8569 tavil_codec_reg_init_common_val[i].val);
8570
8571 if (TAVIL_IS_1_1(priv->wcd9xxx)) {
8572 for (i = 0; i < ARRAY_SIZE(tavil_codec_reg_init_1_1_val); i++)
8573 snd_soc_update_bits(codec,
8574 tavil_codec_reg_init_1_1_val[i].reg,
8575 tavil_codec_reg_init_1_1_val[i].mask,
8576 tavil_codec_reg_init_1_1_val[i].val);
8577 }
8578}
8579
8580static void tavil_update_reg_defaults(struct tavil_priv *tavil)
8581{
8582 u32 i;
8583 struct wcd9xxx *wcd9xxx;
8584
8585 wcd9xxx = tavil->wcd9xxx;
8586 for (i = 0; i < ARRAY_SIZE(tavil_codec_reg_defaults); i++)
8587 regmap_update_bits(wcd9xxx->regmap,
8588 tavil_codec_reg_defaults[i].reg,
8589 tavil_codec_reg_defaults[i].mask,
8590 tavil_codec_reg_defaults[i].val);
8591}
8592
8593static void tavil_update_cpr_defaults(struct tavil_priv *tavil)
8594{
8595 int i;
8596 struct wcd9xxx *wcd9xxx;
8597
8598 wcd9xxx = tavil->wcd9xxx;
8599 if (!TAVIL_IS_1_1(wcd9xxx))
8600 return;
8601
8602 __tavil_cdc_mclk_enable(tavil, true);
8603
8604 regmap_write(wcd9xxx->regmap, WCD934X_CODEC_CPR_SVS2_MIN_CX_VDD, 0x2C);
8605 regmap_update_bits(wcd9xxx->regmap, WCD934X_CODEC_RPM_CLK_GATE,
8606 0x10, 0x00);
8607
8608 for (i = 0; i < ARRAY_SIZE(cpr_defaults); i++) {
8609 regmap_bulk_write(wcd9xxx->regmap,
8610 WCD934X_CODEC_CPR_WR_DATA_0,
8611 (u8 *)&cpr_defaults[i].wr_data, 4);
8612 regmap_bulk_write(wcd9xxx->regmap,
8613 WCD934X_CODEC_CPR_WR_ADDR_0,
8614 (u8 *)&cpr_defaults[i].wr_addr, 4);
8615 }
8616
8617 __tavil_cdc_mclk_enable(tavil, false);
8618}
8619
8620static void tavil_slim_interface_init_reg(struct snd_soc_codec *codec)
8621{
8622 int i;
8623 struct tavil_priv *priv = snd_soc_codec_get_drvdata(codec);
8624
8625 for (i = 0; i < WCD9XXX_SLIM_NUM_PORT_REG; i++)
8626 wcd9xxx_interface_reg_write(priv->wcd9xxx,
8627 WCD934X_SLIM_PGD_PORT_INT_RX_EN0 + i,
8628 0xFF);
8629}
8630
8631static irqreturn_t tavil_misc_irq(int irq, void *data)
8632{
8633 struct tavil_priv *tavil = data;
8634 int misc_val;
8635
8636 /* Find source of interrupt */
8637 regmap_read(tavil->wcd9xxx->regmap, WCD934X_INTR_CODEC_MISC_STATUS,
8638 &misc_val);
8639
8640 if (misc_val & 0x08) {
8641 dev_info(tavil->dev, "%s: irq: %d, DSD DC detected!\n",
8642 __func__, irq);
8643 /* DSD DC interrupt, reset DSD path */
8644 tavil_dsd_reset(tavil->dsd_config);
8645 } else {
8646 dev_err(tavil->dev, "%s: Codec misc irq: %d, val: 0x%x\n",
8647 __func__, irq, misc_val);
8648 }
8649
8650 /* Clear interrupt status */
8651 regmap_update_bits(tavil->wcd9xxx->regmap,
8652 WCD934X_INTR_CODEC_MISC_CLEAR, misc_val, 0x00);
8653
8654 return IRQ_HANDLED;
8655}
8656
8657static irqreturn_t tavil_slimbus_irq(int irq, void *data)
8658{
8659 struct tavil_priv *tavil = data;
8660 unsigned long status = 0;
8661 int i, j, port_id, k;
8662 u32 bit;
8663 u8 val, int_val = 0;
8664 bool tx, cleared;
8665 unsigned short reg = 0;
8666
8667 for (i = WCD934X_SLIM_PGD_PORT_INT_STATUS_RX_0, j = 0;
8668 i <= WCD934X_SLIM_PGD_PORT_INT_STATUS_TX_1; i++, j++) {
8669 val = wcd9xxx_interface_reg_read(tavil->wcd9xxx, i);
8670 status |= ((u32)val << (8 * j));
8671 }
8672
8673 for_each_set_bit(j, &status, 32) {
8674 tx = (j >= 16 ? true : false);
8675 port_id = (tx ? j - 16 : j);
8676 val = wcd9xxx_interface_reg_read(tavil->wcd9xxx,
8677 WCD934X_SLIM_PGD_PORT_INT_RX_SOURCE0 + j);
8678 if (val) {
8679 if (!tx)
8680 reg = WCD934X_SLIM_PGD_PORT_INT_RX_EN0 +
8681 (port_id / 8);
8682 else
8683 reg = WCD934X_SLIM_PGD_PORT_INT_TX_EN0 +
8684 (port_id / 8);
8685 int_val = wcd9xxx_interface_reg_read(
8686 tavil->wcd9xxx, reg);
8687 /*
8688 * Ignore interrupts for ports for which the
8689 * interrupts are not specifically enabled.
8690 */
8691 if (!(int_val & (1 << (port_id % 8))))
8692 continue;
8693 }
8694 if (val & WCD934X_SLIM_IRQ_OVERFLOW)
8695 dev_err_ratelimited(tavil->dev, "%s: overflow error on %s port %d, value %x\n",
8696 __func__, (tx ? "TX" : "RX"), port_id, val);
8697 if (val & WCD934X_SLIM_IRQ_UNDERFLOW)
8698 dev_err_ratelimited(tavil->dev, "%s: underflow error on %s port %d, value %x\n",
8699 __func__, (tx ? "TX" : "RX"), port_id, val);
8700 if ((val & WCD934X_SLIM_IRQ_OVERFLOW) ||
8701 (val & WCD934X_SLIM_IRQ_UNDERFLOW)) {
8702 if (!tx)
8703 reg = WCD934X_SLIM_PGD_PORT_INT_RX_EN0 +
8704 (port_id / 8);
8705 else
8706 reg = WCD934X_SLIM_PGD_PORT_INT_TX_EN0 +
8707 (port_id / 8);
8708 int_val = wcd9xxx_interface_reg_read(
8709 tavil->wcd9xxx, reg);
8710 if (int_val & (1 << (port_id % 8))) {
8711 int_val = int_val ^ (1 << (port_id % 8));
8712 wcd9xxx_interface_reg_write(tavil->wcd9xxx,
8713 reg, int_val);
8714 }
8715 }
8716 if (val & WCD934X_SLIM_IRQ_PORT_CLOSED) {
8717 /*
8718 * INT SOURCE register starts from RX to TX
8719 * but port number in the ch_mask is in opposite way
8720 */
8721 bit = (tx ? j - 16 : j + 16);
8722 dev_dbg(tavil->dev, "%s: %s port %d closed value %x, bit %u\n",
8723 __func__, (tx ? "TX" : "RX"), port_id, val,
8724 bit);
8725 for (k = 0, cleared = false; k < NUM_CODEC_DAIS; k++) {
8726 dev_dbg(tavil->dev, "%s: tavil->dai[%d].ch_mask = 0x%lx\n",
8727 __func__, k, tavil->dai[k].ch_mask);
8728 if (test_and_clear_bit(bit,
8729 &tavil->dai[k].ch_mask)) {
8730 cleared = true;
8731 if (!tavil->dai[k].ch_mask)
8732 wake_up(
8733 &tavil->dai[k].dai_wait);
8734 /*
8735 * There are cases when multiple DAIs
8736 * might be using the same slimbus
8737 * channel. Hence don't break here.
8738 */
8739 }
8740 }
8741 WARN(!cleared,
8742 "Couldn't find slimbus %s port %d for closing\n",
8743 (tx ? "TX" : "RX"), port_id);
8744 }
8745 wcd9xxx_interface_reg_write(tavil->wcd9xxx,
8746 WCD934X_SLIM_PGD_PORT_INT_CLR_RX_0 +
8747 (j / 8),
8748 1 << (j % 8));
8749 }
8750
8751 return IRQ_HANDLED;
8752}
8753
8754static int tavil_setup_irqs(struct tavil_priv *tavil)
8755{
8756 int ret = 0;
8757 struct snd_soc_codec *codec = tavil->codec;
8758 struct wcd9xxx *wcd9xxx = tavil->wcd9xxx;
8759 struct wcd9xxx_core_resource *core_res =
8760 &wcd9xxx->core_res;
8761
8762 ret = wcd9xxx_request_irq(core_res, WCD9XXX_IRQ_SLIMBUS,
8763 tavil_slimbus_irq, "SLIMBUS Slave", tavil);
8764 if (ret)
8765 dev_err(codec->dev, "%s: Failed to request irq %d\n", __func__,
8766 WCD9XXX_IRQ_SLIMBUS);
8767 else
8768 tavil_slim_interface_init_reg(codec);
8769
8770 /* Register for misc interrupts as well */
8771 ret = wcd9xxx_request_irq(core_res, WCD934X_IRQ_MISC,
8772 tavil_misc_irq, "CDC MISC Irq", tavil);
8773 if (ret)
8774 dev_err(codec->dev, "%s: Failed to request cdc misc irq\n",
8775 __func__);
8776
8777 return ret;
8778}
8779
8780static void tavil_init_slim_slave_cfg(struct snd_soc_codec *codec)
8781{
8782 struct tavil_priv *priv = snd_soc_codec_get_drvdata(codec);
8783 struct afe_param_cdc_slimbus_slave_cfg *cfg;
8784 struct wcd9xxx *wcd9xxx = priv->wcd9xxx;
8785 uint64_t eaddr = 0;
8786
8787 cfg = &priv->slimbus_slave_cfg;
8788 cfg->minor_version = 1;
8789 cfg->tx_slave_port_offset = 0;
8790 cfg->rx_slave_port_offset = 16;
8791
8792 memcpy(&eaddr, &wcd9xxx->slim->e_addr, sizeof(wcd9xxx->slim->e_addr));
8793 WARN_ON(sizeof(wcd9xxx->slim->e_addr) != 6);
8794 cfg->device_enum_addr_lsw = eaddr & 0xFFFFFFFF;
8795 cfg->device_enum_addr_msw = eaddr >> 32;
8796
8797 dev_dbg(codec->dev, "%s: slimbus logical address 0x%llx\n",
8798 __func__, eaddr);
8799}
8800
8801static void tavil_cleanup_irqs(struct tavil_priv *tavil)
8802{
8803 struct wcd9xxx *wcd9xxx = tavil->wcd9xxx;
8804 struct wcd9xxx_core_resource *core_res =
8805 &wcd9xxx->core_res;
8806
8807 wcd9xxx_free_irq(core_res, WCD9XXX_IRQ_SLIMBUS, tavil);
8808 wcd9xxx_free_irq(core_res, WCD934X_IRQ_MISC, tavil);
8809}
8810
8811/*
8812 * wcd934x_get_micb_vout_ctl_val: converts micbias from volts to register value
8813 * @micb_mv: micbias in mv
8814 *
8815 * return register value converted
8816 */
8817int wcd934x_get_micb_vout_ctl_val(u32 micb_mv)
8818{
8819 /* min micbias voltage is 1V and maximum is 2.85V */
8820 if (micb_mv < 1000 || micb_mv > 2850) {
8821 pr_err("%s: unsupported micbias voltage\n", __func__);
8822 return -EINVAL;
8823 }
8824
8825 return (micb_mv - 1000) / 50;
8826}
8827EXPORT_SYMBOL(wcd934x_get_micb_vout_ctl_val);
8828
8829static int tavil_handle_pdata(struct tavil_priv *tavil,
8830 struct wcd9xxx_pdata *pdata)
8831{
8832 struct snd_soc_codec *codec = tavil->codec;
8833 u8 mad_dmic_ctl_val;
8834 u8 anc_ctl_value;
8835 u32 def_dmic_rate, dmic_clk_drv;
8836 int vout_ctl_1, vout_ctl_2, vout_ctl_3, vout_ctl_4;
8837 int rc = 0;
8838
8839 if (!pdata) {
8840 dev_err(codec->dev, "%s: NULL pdata\n", __func__);
8841 return -ENODEV;
8842 }
8843
8844 /* set micbias voltage */
8845 vout_ctl_1 = wcd934x_get_micb_vout_ctl_val(pdata->micbias.micb1_mv);
8846 vout_ctl_2 = wcd934x_get_micb_vout_ctl_val(pdata->micbias.micb2_mv);
8847 vout_ctl_3 = wcd934x_get_micb_vout_ctl_val(pdata->micbias.micb3_mv);
8848 vout_ctl_4 = wcd934x_get_micb_vout_ctl_val(pdata->micbias.micb4_mv);
Xiaoyu Ye1a2d8bd92017-01-31 18:54:15 -08008849 if (vout_ctl_1 < 0 || vout_ctl_2 < 0 ||
8850 vout_ctl_3 < 0 || vout_ctl_4 < 0) {
Banajit Goswamide8271c2017-01-18 00:28:59 -08008851 rc = -EINVAL;
8852 goto done;
8853 }
8854 snd_soc_update_bits(codec, WCD934X_ANA_MICB1, 0x3F, vout_ctl_1);
8855 snd_soc_update_bits(codec, WCD934X_ANA_MICB2, 0x3F, vout_ctl_2);
8856 snd_soc_update_bits(codec, WCD934X_ANA_MICB3, 0x3F, vout_ctl_3);
8857 snd_soc_update_bits(codec, WCD934X_ANA_MICB4, 0x3F, vout_ctl_4);
8858
8859 /* Set the DMIC sample rate */
8860 switch (pdata->mclk_rate) {
8861 case WCD934X_MCLK_CLK_9P6MHZ:
8862 def_dmic_rate = WCD9XXX_DMIC_SAMPLE_RATE_4P8MHZ;
8863 break;
8864 case WCD934X_MCLK_CLK_12P288MHZ:
8865 def_dmic_rate = WCD9XXX_DMIC_SAMPLE_RATE_4P096MHZ;
8866 break;
8867 default:
8868 /* should never happen */
8869 dev_err(codec->dev, "%s: Invalid mclk_rate %d\n",
8870 __func__, pdata->mclk_rate);
8871 rc = -EINVAL;
8872 goto done;
8873 };
8874
8875 if (pdata->dmic_sample_rate ==
8876 WCD9XXX_DMIC_SAMPLE_RATE_UNDEFINED) {
8877 dev_info(codec->dev, "%s: dmic_rate invalid default = %d\n",
8878 __func__, def_dmic_rate);
8879 pdata->dmic_sample_rate = def_dmic_rate;
8880 }
8881 if (pdata->mad_dmic_sample_rate ==
8882 WCD9XXX_DMIC_SAMPLE_RATE_UNDEFINED) {
8883 dev_info(codec->dev, "%s: mad_dmic_rate invalid default = %d\n",
8884 __func__, def_dmic_rate);
8885 /*
8886 * use dmic_sample_rate as the default for MAD
8887 * if mad dmic sample rate is undefined
8888 */
8889 pdata->mad_dmic_sample_rate = pdata->dmic_sample_rate;
8890 }
8891
8892 if (pdata->dmic_clk_drv ==
8893 WCD9XXX_DMIC_CLK_DRIVE_UNDEFINED) {
8894 pdata->dmic_clk_drv = WCD934X_DMIC_CLK_DRIVE_DEFAULT;
Karthikeyan Mani3570e6c2016-11-14 11:05:53 -08008895 dev_dbg(codec->dev,
Banajit Goswamide8271c2017-01-18 00:28:59 -08008896 "%s: dmic_clk_strength invalid, default = %d\n",
8897 __func__, pdata->dmic_clk_drv);
8898 }
8899
8900 switch (pdata->dmic_clk_drv) {
8901 case 2:
8902 dmic_clk_drv = 0;
8903 break;
8904 case 4:
8905 dmic_clk_drv = 1;
8906 break;
8907 case 8:
8908 dmic_clk_drv = 2;
8909 break;
8910 case 16:
8911 dmic_clk_drv = 3;
8912 break;
8913 default:
8914 dev_err(codec->dev,
8915 "%s: invalid dmic_clk_drv %d, using default\n",
8916 __func__, pdata->dmic_clk_drv);
8917 dmic_clk_drv = 0;
8918 break;
8919 }
8920
8921 snd_soc_update_bits(codec, WCD934X_TEST_DEBUG_PAD_DRVCTL_0,
8922 0x0C, dmic_clk_drv << 2);
8923
8924 /*
8925 * Default the DMIC clk rates to mad_dmic_sample_rate,
8926 * whereas, the anc/txfe dmic rates to dmic_sample_rate
8927 * since the anc/txfe are independent of mad block.
8928 */
8929 mad_dmic_ctl_val = tavil_get_dmic_clk_val(tavil->codec,
8930 pdata->mclk_rate,
8931 pdata->mad_dmic_sample_rate);
8932 snd_soc_update_bits(codec, WCD934X_CPE_SS_DMIC0_CTL,
8933 0x0E, mad_dmic_ctl_val << 1);
8934 snd_soc_update_bits(codec, WCD934X_CPE_SS_DMIC1_CTL,
8935 0x0E, mad_dmic_ctl_val << 1);
8936 snd_soc_update_bits(codec, WCD934X_CPE_SS_DMIC2_CTL,
8937 0x0E, mad_dmic_ctl_val << 1);
8938
8939 if (dmic_clk_drv == WCD934X_DMIC_CLK_DIV_2)
8940 anc_ctl_value = WCD934X_ANC_DMIC_X2_FULL_RATE;
8941 else
8942 anc_ctl_value = WCD934X_ANC_DMIC_X2_HALF_RATE;
8943
8944 snd_soc_update_bits(codec, WCD934X_CDC_ANC0_MODE_2_CTL,
8945 0x40, anc_ctl_value << 6);
8946 snd_soc_update_bits(codec, WCD934X_CDC_ANC0_MODE_2_CTL,
8947 0x20, anc_ctl_value << 5);
8948 snd_soc_update_bits(codec, WCD934X_CDC_ANC1_MODE_2_CTL,
8949 0x40, anc_ctl_value << 6);
8950 snd_soc_update_bits(codec, WCD934X_CDC_ANC1_MODE_2_CTL,
8951 0x20, anc_ctl_value << 5);
8952
8953done:
8954 return rc;
8955}
8956
8957static void tavil_cdc_vote_svs(struct snd_soc_codec *codec, bool vote)
8958{
8959 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
8960
8961 return tavil_vote_svs(tavil, vote);
8962}
8963
8964struct wcd_dsp_cdc_cb cdc_cb = {
8965 .cdc_clk_en = tavil_codec_internal_rco_ctrl,
8966 .cdc_vote_svs = tavil_cdc_vote_svs,
8967};
8968
8969static int tavil_wdsp_initialize(struct snd_soc_codec *codec)
8970{
8971 struct wcd9xxx *control;
8972 struct tavil_priv *tavil;
8973 struct wcd_dsp_params params;
8974 int ret = 0;
8975
8976 control = dev_get_drvdata(codec->dev->parent);
8977 tavil = snd_soc_codec_get_drvdata(codec);
8978
8979 params.cb = &cdc_cb;
8980 params.irqs.cpe_ipc1_irq = WCD934X_IRQ_CPE1_INTR;
8981 params.irqs.cpe_err_irq = WCD934X_IRQ_CPE_ERROR;
8982 params.irqs.fatal_irqs = CPE_FATAL_IRQS;
8983 params.clk_rate = control->mclk_rate;
8984 params.dsp_instance = 0;
8985
8986 wcd_dsp_cntl_init(codec, &params, &tavil->wdsp_cntl);
8987 if (!tavil->wdsp_cntl) {
8988 dev_err(tavil->dev, "%s: wcd-dsp-control init failed\n",
8989 __func__);
8990 ret = -EINVAL;
8991 }
8992
8993 return ret;
8994}
8995
8996/*
8997 * tavil_soc_get_mbhc: get wcd934x_mbhc handle of corresponding codec
8998 * @codec: handle to snd_soc_codec *
8999 *
9000 * return wcd934x_mbhc handle or error code in case of failure
9001 */
9002struct wcd934x_mbhc *tavil_soc_get_mbhc(struct snd_soc_codec *codec)
9003{
9004 struct tavil_priv *tavil;
9005
9006 if (!codec) {
9007 pr_err("%s: Invalid params, NULL codec\n", __func__);
9008 return NULL;
9009 }
9010 tavil = snd_soc_codec_get_drvdata(codec);
9011
9012 if (!tavil) {
9013 pr_err("%s: Invalid params, NULL tavil\n", __func__);
9014 return NULL;
9015 }
9016
9017 return tavil->mbhc;
9018}
9019EXPORT_SYMBOL(tavil_soc_get_mbhc);
9020
9021static void tavil_mclk2_reg_defaults(struct tavil_priv *tavil)
9022{
9023 int i;
9024 struct snd_soc_codec *codec = tavil->codec;
9025
9026 if (TAVIL_IS_1_0(tavil->wcd9xxx)) {
9027 /* MCLK2 configuration */
9028 for (i = 0; i < ARRAY_SIZE(tavil_codec_mclk2_1_0_defaults); i++)
9029 snd_soc_update_bits(codec,
9030 tavil_codec_mclk2_1_0_defaults[i].reg,
9031 tavil_codec_mclk2_1_0_defaults[i].mask,
9032 tavil_codec_mclk2_1_0_defaults[i].val);
9033 }
9034 if (TAVIL_IS_1_1(tavil->wcd9xxx)) {
9035 /* MCLK2 configuration */
9036 for (i = 0; i < ARRAY_SIZE(tavil_codec_mclk2_1_1_defaults); i++)
9037 snd_soc_update_bits(codec,
9038 tavil_codec_mclk2_1_1_defaults[i].reg,
9039 tavil_codec_mclk2_1_1_defaults[i].mask,
9040 tavil_codec_mclk2_1_1_defaults[i].val);
9041 }
9042}
9043
9044static int tavil_device_down(struct wcd9xxx *wcd9xxx)
9045{
9046 struct snd_soc_codec *codec;
9047 struct tavil_priv *priv;
9048 int count;
9049
9050 codec = (struct snd_soc_codec *)(wcd9xxx->ssr_priv);
9051 priv = snd_soc_codec_get_drvdata(codec);
9052 swrm_wcd_notify(priv->swr.ctrl_data[0].swr_pdev,
9053 SWR_DEVICE_DOWN, NULL);
9054 tavil_dsd_reset(priv->dsd_config);
9055 snd_soc_card_change_online_state(codec->component.card, 0);
9056 for (count = 0; count < NUM_CODEC_DAIS; count++)
9057 priv->dai[count].bus_down_in_recovery = true;
9058 wcd_dsp_ssr_event(priv->wdsp_cntl, WCD_CDC_DOWN_EVENT);
9059 wcd_resmgr_set_sido_input_src_locked(priv->resmgr,
9060 SIDO_SOURCE_INTERNAL);
9061
9062 return 0;
9063}
9064
9065static int tavil_post_reset_cb(struct wcd9xxx *wcd9xxx)
9066{
9067 int i, ret = 0;
9068 struct wcd9xxx *control;
9069 struct snd_soc_codec *codec;
9070 struct tavil_priv *tavil;
9071 struct wcd9xxx_pdata *pdata;
9072 struct wcd_mbhc *mbhc;
9073
9074 codec = (struct snd_soc_codec *)(wcd9xxx->ssr_priv);
9075 tavil = snd_soc_codec_get_drvdata(codec);
9076 control = dev_get_drvdata(codec->dev->parent);
9077
9078 wcd9xxx_set_power_state(tavil->wcd9xxx,
9079 WCD_REGION_POWER_COLLAPSE_REMOVE,
9080 WCD9XXX_DIG_CORE_REGION_1);
9081
9082 mutex_lock(&tavil->codec_mutex);
Banajit Goswamide8271c2017-01-18 00:28:59 -08009083
Vidyakumar Athotaae60b992017-01-04 11:21:48 -08009084 tavil_vote_svs(tavil, true);
Banajit Goswamide8271c2017-01-18 00:28:59 -08009085 tavil_slimbus_slave_port_cfg.slave_dev_intfdev_la =
9086 control->slim_slave->laddr;
9087 tavil_slimbus_slave_port_cfg.slave_dev_pgd_la =
9088 control->slim->laddr;
9089 tavil_init_slim_slave_cfg(codec);
9090 snd_soc_card_change_online_state(codec->component.card, 1);
9091
Banajit Goswamide8271c2017-01-18 00:28:59 -08009092 for (i = 0; i < TAVIL_MAX_MICBIAS; i++)
9093 tavil->micb_ref[i] = 0;
9094
Banajit Goswamide8271c2017-01-18 00:28:59 -08009095 dev_dbg(codec->dev, "%s: MCLK Rate = %x\n",
9096 __func__, control->mclk_rate);
9097
9098 if (control->mclk_rate == WCD934X_MCLK_CLK_12P288MHZ)
9099 snd_soc_update_bits(codec, WCD934X_CODEC_RPM_CLK_MCLK_CFG,
9100 0x03, 0x00);
9101 else if (control->mclk_rate == WCD934X_MCLK_CLK_9P6MHZ)
9102 snd_soc_update_bits(codec, WCD934X_CODEC_RPM_CLK_MCLK_CFG,
9103 0x03, 0x01);
9104 wcd_resmgr_post_ssr_v2(tavil->resmgr);
9105 tavil_update_reg_defaults(tavil);
9106 tavil_codec_init_reg(tavil);
9107 __tavil_enable_efuse_sensing(tavil);
9108 tavil_mclk2_reg_defaults(tavil);
9109
9110 __tavil_cdc_mclk_enable(tavil, true);
9111 regcache_mark_dirty(codec->component.regmap);
9112 regcache_sync(codec->component.regmap);
9113 __tavil_cdc_mclk_enable(tavil, false);
9114
9115 tavil_update_cpr_defaults(tavil);
9116
9117 pdata = dev_get_platdata(codec->dev->parent);
9118 ret = tavil_handle_pdata(tavil, pdata);
Xiaoyu Ye1a2d8bd92017-01-31 18:54:15 -08009119 if (ret < 0)
Banajit Goswamide8271c2017-01-18 00:28:59 -08009120 dev_err(codec->dev, "%s: invalid pdata\n", __func__);
9121
9122 /* Initialize MBHC module */
9123 mbhc = &tavil->mbhc->wcd_mbhc;
9124 ret = tavil_mbhc_post_ssr_init(tavil->mbhc, codec);
9125 if (ret) {
9126 dev_err(codec->dev, "%s: mbhc initialization failed\n",
9127 __func__);
9128 goto done;
9129 } else {
9130 tavil_mbhc_hs_detect(codec, mbhc->mbhc_cfg);
9131 }
9132
9133 /* DSD initialization */
9134 ret = tavil_dsd_post_ssr_init(tavil->dsd_config);
9135 if (ret)
9136 dev_dbg(tavil->dev, "%s: DSD init failed\n", __func__);
9137
9138 tavil_cleanup_irqs(tavil);
9139 ret = tavil_setup_irqs(tavil);
9140 if (ret) {
9141 dev_err(codec->dev, "%s: tavil irq setup failed %d\n",
9142 __func__, ret);
9143 goto done;
9144 }
9145
9146 tavil_set_spkr_mode(codec, tavil->swr.spkr_mode);
9147 /*
9148 * Once the codec initialization is completed, the svs vote
9149 * can be released allowing the codec to go to SVS2.
9150 */
9151 tavil_vote_svs(tavil, false);
9152 wcd_dsp_ssr_event(tavil->wdsp_cntl, WCD_CDC_UP_EVENT);
9153
9154done:
9155 mutex_unlock(&tavil->codec_mutex);
9156 return ret;
9157}
9158
Banajit Goswami2be7b482017-02-03 23:32:37 -08009159static int tavil_soc_codec_probe(struct snd_soc_codec *codec)
Banajit Goswamide8271c2017-01-18 00:28:59 -08009160{
9161 struct wcd9xxx *control;
9162 struct tavil_priv *tavil;
9163 struct wcd9xxx_pdata *pdata;
9164 struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
9165 int i, ret;
9166 void *ptr = NULL;
9167
9168 control = dev_get_drvdata(codec->dev->parent);
9169
9170 dev_info(codec->dev, "%s()\n", __func__);
9171 tavil = snd_soc_codec_get_drvdata(codec);
9172 tavil->intf_type = wcd9xxx_get_intf_type();
9173
9174 control->dev_down = tavil_device_down;
9175 control->post_reset = tavil_post_reset_cb;
9176 control->ssr_priv = (void *)codec;
9177
9178 /* Resource Manager post Init */
9179 ret = wcd_resmgr_post_init(tavil->resmgr, &tavil_resmgr_cb, codec);
9180 if (ret) {
9181 dev_err(codec->dev, "%s: wcd resmgr post init failed\n",
9182 __func__);
9183 goto err;
9184 }
9185 /* Class-H Init */
9186 wcd_clsh_init(&tavil->clsh_d);
9187 /* Default HPH Mode to Class-H Low HiFi */
9188 tavil->hph_mode = CLS_H_LOHIFI;
9189
9190 tavil->fw_data = devm_kzalloc(codec->dev, sizeof(*(tavil->fw_data)),
9191 GFP_KERNEL);
9192 if (!tavil->fw_data)
9193 goto err;
9194
9195 set_bit(WCD9XXX_ANC_CAL, tavil->fw_data->cal_bit);
9196 set_bit(WCD9XXX_MBHC_CAL, tavil->fw_data->cal_bit);
9197 set_bit(WCD9XXX_MAD_CAL, tavil->fw_data->cal_bit);
9198 set_bit(WCD9XXX_VBAT_CAL, tavil->fw_data->cal_bit);
9199
9200 ret = wcd_cal_create_hwdep(tavil->fw_data,
9201 WCD9XXX_CODEC_HWDEP_NODE, codec);
Xiaoyu Ye1a2d8bd92017-01-31 18:54:15 -08009202 if (ret < 0) {
Banajit Goswamide8271c2017-01-18 00:28:59 -08009203 dev_err(codec->dev, "%s hwdep failed %d\n", __func__, ret);
9204 goto err_hwdep;
9205 }
9206
9207 /* Initialize MBHC module */
9208 ret = tavil_mbhc_init(&tavil->mbhc, codec, tavil->fw_data);
9209 if (ret) {
9210 pr_err("%s: mbhc initialization failed\n", __func__);
9211 goto err_hwdep;
9212 }
9213
9214 tavil->codec = codec;
9215 for (i = 0; i < COMPANDER_MAX; i++)
9216 tavil->comp_enabled[i] = 0;
9217
9218 tavil_codec_init_reg(tavil);
9219
9220 pdata = dev_get_platdata(codec->dev->parent);
9221 ret = tavil_handle_pdata(tavil, pdata);
Xiaoyu Ye1a2d8bd92017-01-31 18:54:15 -08009222 if (ret < 0) {
Banajit Goswamide8271c2017-01-18 00:28:59 -08009223 dev_err(codec->dev, "%s: bad pdata\n", __func__);
9224 goto err_hwdep;
9225 }
9226
9227 ptr = devm_kzalloc(codec->dev, (sizeof(tavil_rx_chs) +
9228 sizeof(tavil_tx_chs)), GFP_KERNEL);
9229 if (!ptr) {
9230 ret = -ENOMEM;
9231 goto err_hwdep;
9232 }
9233
9234 snd_soc_dapm_add_routes(dapm, tavil_slim_audio_map,
9235 ARRAY_SIZE(tavil_slim_audio_map));
9236 for (i = 0; i < NUM_CODEC_DAIS; i++) {
9237 INIT_LIST_HEAD(&tavil->dai[i].wcd9xxx_ch_list);
9238 init_waitqueue_head(&tavil->dai[i].dai_wait);
9239 }
9240 tavil_slimbus_slave_port_cfg.slave_dev_intfdev_la =
9241 control->slim_slave->laddr;
9242 tavil_slimbus_slave_port_cfg.slave_dev_pgd_la =
9243 control->slim->laddr;
9244 tavil_slimbus_slave_port_cfg.slave_port_mapping[0] =
9245 WCD934X_TX13;
9246 tavil_init_slim_slave_cfg(codec);
9247
9248 control->num_rx_port = WCD934X_RX_MAX;
9249 control->rx_chs = ptr;
9250 memcpy(control->rx_chs, tavil_rx_chs, sizeof(tavil_rx_chs));
9251 control->num_tx_port = WCD934X_TX_MAX;
9252 control->tx_chs = ptr + sizeof(tavil_rx_chs);
9253 memcpy(control->tx_chs, tavil_tx_chs, sizeof(tavil_tx_chs));
9254
9255 ret = tavil_setup_irqs(tavil);
9256 if (ret) {
9257 dev_err(tavil->dev, "%s: tavil irq setup failed %d\n",
9258 __func__, ret);
9259 goto err_pdata;
9260 }
9261
9262 for (i = 0; i < WCD934X_NUM_DECIMATORS; i++) {
9263 tavil->tx_hpf_work[i].tavil = tavil;
9264 tavil->tx_hpf_work[i].decimator = i;
9265 INIT_DELAYED_WORK(&tavil->tx_hpf_work[i].dwork,
9266 tavil_tx_hpf_corner_freq_callback);
9267
9268 tavil->tx_mute_dwork[i].tavil = tavil;
9269 tavil->tx_mute_dwork[i].decimator = i;
9270 INIT_DELAYED_WORK(&tavil->tx_mute_dwork[i].dwork,
9271 tavil_tx_mute_update_callback);
9272 }
9273
9274 tavil->spk_anc_dwork.tavil = tavil;
9275 INIT_DELAYED_WORK(&tavil->spk_anc_dwork.dwork,
9276 tavil_spk_anc_update_callback);
9277
9278 tavil_mclk2_reg_defaults(tavil);
9279
9280 /* DSD initialization */
9281 tavil->dsd_config = tavil_dsd_init(codec);
9282 if (IS_ERR_OR_NULL(tavil->dsd_config))
9283 dev_dbg(tavil->dev, "%s: DSD init failed\n", __func__);
9284
9285 mutex_lock(&tavil->codec_mutex);
9286 snd_soc_dapm_disable_pin(dapm, "ANC EAR PA");
9287 snd_soc_dapm_disable_pin(dapm, "ANC EAR");
Meng Wangf45a20d2017-01-18 09:51:58 +08009288 snd_soc_dapm_disable_pin(dapm, "ANC HPHL PA");
9289 snd_soc_dapm_disable_pin(dapm, "ANC HPHR PA");
9290 snd_soc_dapm_disable_pin(dapm, "ANC HPHL");
9291 snd_soc_dapm_disable_pin(dapm, "ANC HPHR");
Banajit Goswamide8271c2017-01-18 00:28:59 -08009292 snd_soc_dapm_enable_pin(dapm, "ANC SPK1 PA");
9293 mutex_unlock(&tavil->codec_mutex);
9294
9295 snd_soc_dapm_ignore_suspend(dapm, "AIF1 Playback");
9296 snd_soc_dapm_ignore_suspend(dapm, "AIF1 Capture");
9297 snd_soc_dapm_ignore_suspend(dapm, "AIF2 Playback");
9298 snd_soc_dapm_ignore_suspend(dapm, "AIF2 Capture");
9299 snd_soc_dapm_ignore_suspend(dapm, "AIF3 Playback");
9300 snd_soc_dapm_ignore_suspend(dapm, "AIF3 Capture");
9301 snd_soc_dapm_ignore_suspend(dapm, "AIF4 Playback");
9302 snd_soc_dapm_ignore_suspend(dapm, "VIfeed");
9303
9304 snd_soc_dapm_sync(dapm);
9305
9306 tavil_wdsp_initialize(codec);
9307
9308 /*
9309 * Once the codec initialization is completed, the svs vote
9310 * can be released allowing the codec to go to SVS2.
9311 */
9312 tavil_vote_svs(tavil, false);
9313
9314 return ret;
9315
9316err_pdata:
9317 devm_kfree(codec->dev, ptr);
9318 control->rx_chs = NULL;
9319 control->tx_chs = NULL;
9320err_hwdep:
9321 devm_kfree(codec->dev, tavil->fw_data);
9322 tavil->fw_data = NULL;
9323err:
9324 return ret;
9325}
9326
Banajit Goswami2be7b482017-02-03 23:32:37 -08009327static int tavil_soc_codec_remove(struct snd_soc_codec *codec)
Banajit Goswamide8271c2017-01-18 00:28:59 -08009328{
9329 struct wcd9xxx *control;
9330 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
9331
9332 control = dev_get_drvdata(codec->dev->parent);
9333 devm_kfree(codec->dev, control->rx_chs);
9334 control->rx_chs = NULL;
9335 control->tx_chs = NULL;
9336 tavil_cleanup_irqs(tavil);
9337
9338 if (tavil->wdsp_cntl)
9339 wcd_dsp_cntl_deinit(&tavil->wdsp_cntl);
9340
9341 /* Deinitialize MBHC module */
9342 tavil_mbhc_deinit(codec);
9343 tavil->mbhc = NULL;
Banajit Goswamie0b20e12017-02-05 18:11:11 -08009344
9345 return 0;
Banajit Goswamide8271c2017-01-18 00:28:59 -08009346}
9347
9348static struct regmap *tavil_get_regmap(struct device *dev)
9349{
9350 struct wcd9xxx *control = dev_get_drvdata(dev->parent);
9351
9352 return control->regmap;
9353}
9354
9355static struct snd_soc_codec_driver soc_codec_dev_tavil = {
Banajit Goswami2be7b482017-02-03 23:32:37 -08009356 .probe = tavil_soc_codec_probe,
9357 .remove = tavil_soc_codec_remove,
Banajit Goswamide8271c2017-01-18 00:28:59 -08009358 .get_regmap = tavil_get_regmap,
Banajit Goswami8e306f02016-12-15 20:49:07 -08009359 .component_driver = {
Banajit Goswamiaf472112017-01-29 22:15:11 -08009360 .controls = tavil_snd_controls,
9361 .num_controls = ARRAY_SIZE(tavil_snd_controls),
Banajit Goswami8e306f02016-12-15 20:49:07 -08009362 .dapm_widgets = tavil_dapm_widgets,
9363 .num_dapm_widgets = ARRAY_SIZE(tavil_dapm_widgets),
9364 .dapm_routes = tavil_audio_map,
9365 .num_dapm_routes = ARRAY_SIZE(tavil_audio_map),
9366 },
Banajit Goswamide8271c2017-01-18 00:28:59 -08009367};
9368
9369#ifdef CONFIG_PM
9370static int tavil_suspend(struct device *dev)
9371{
9372 struct platform_device *pdev = to_platform_device(dev);
9373 struct tavil_priv *tavil = platform_get_drvdata(pdev);
9374
9375 if (!tavil) {
9376 dev_err(dev, "%s: tavil private data is NULL\n", __func__);
9377 return -EINVAL;
9378 }
9379 dev_dbg(dev, "%s: system suspend\n", __func__);
9380 if (delayed_work_pending(&tavil->power_gate_work) &&
9381 cancel_delayed_work_sync(&tavil->power_gate_work))
9382 tavil_codec_power_gate_digital_core(tavil);
9383 return 0;
9384}
9385
9386static int tavil_resume(struct device *dev)
9387{
9388 struct platform_device *pdev = to_platform_device(dev);
9389 struct tavil_priv *tavil = platform_get_drvdata(pdev);
9390
9391 if (!tavil) {
9392 dev_err(dev, "%s: tavil private data is NULL\n", __func__);
9393 return -EINVAL;
9394 }
9395 dev_dbg(dev, "%s: system resume\n", __func__);
9396 return 0;
9397}
9398
9399static const struct dev_pm_ops tavil_pm_ops = {
9400 .suspend = tavil_suspend,
9401 .resume = tavil_resume,
9402};
9403#endif
9404
9405static int tavil_swrm_read(void *handle, int reg)
9406{
9407 struct tavil_priv *tavil;
9408 struct wcd9xxx *wcd9xxx;
9409 unsigned short swr_rd_addr_base;
9410 unsigned short swr_rd_data_base;
9411 int val, ret;
9412
9413 if (!handle) {
9414 pr_err("%s: NULL handle\n", __func__);
9415 return -EINVAL;
9416 }
9417 tavil = (struct tavil_priv *)handle;
9418 wcd9xxx = tavil->wcd9xxx;
9419
9420 dev_dbg(tavil->dev, "%s: Reading soundwire register, 0x%x\n",
9421 __func__, reg);
9422 swr_rd_addr_base = WCD934X_SWR_AHB_BRIDGE_RD_ADDR_0;
9423 swr_rd_data_base = WCD934X_SWR_AHB_BRIDGE_RD_DATA_0;
9424
9425 mutex_lock(&tavil->swr.read_mutex);
9426 ret = regmap_bulk_write(wcd9xxx->regmap, swr_rd_addr_base,
9427 (u8 *)&reg, 4);
9428 if (ret < 0) {
9429 dev_err(tavil->dev, "%s: RD Addr Failure\n", __func__);
9430 goto done;
9431 }
9432 ret = regmap_bulk_read(wcd9xxx->regmap, swr_rd_data_base,
9433 (u8 *)&val, 4);
9434 if (ret < 0) {
9435 dev_err(tavil->dev, "%s: RD Data Failure\n", __func__);
9436 goto done;
9437 }
9438 ret = val;
9439done:
9440 mutex_unlock(&tavil->swr.read_mutex);
9441
9442 return ret;
9443}
9444
9445static int tavil_swrm_bulk_write(void *handle, u32 *reg, u32 *val, size_t len)
9446{
9447 struct tavil_priv *tavil;
9448 struct wcd9xxx *wcd9xxx;
9449 struct wcd9xxx_reg_val *bulk_reg;
9450 unsigned short swr_wr_addr_base;
9451 unsigned short swr_wr_data_base;
9452 int i, j, ret;
9453
9454 if (!handle || !reg || !val) {
9455 pr_err("%s: NULL parameter\n", __func__);
9456 return -EINVAL;
9457 }
9458 if (len <= 0) {
9459 pr_err("%s: Invalid size: %zu\n", __func__, len);
9460 return -EINVAL;
9461 }
9462 tavil = (struct tavil_priv *)handle;
9463 wcd9xxx = tavil->wcd9xxx;
9464
9465 swr_wr_addr_base = WCD934X_SWR_AHB_BRIDGE_WR_ADDR_0;
9466 swr_wr_data_base = WCD934X_SWR_AHB_BRIDGE_WR_DATA_0;
9467
9468 bulk_reg = kzalloc((2 * len * sizeof(struct wcd9xxx_reg_val)),
9469 GFP_KERNEL);
9470 if (!bulk_reg)
9471 return -ENOMEM;
9472
9473 for (i = 0, j = 0; i < (len * 2); i += 2, j++) {
9474 bulk_reg[i].reg = swr_wr_data_base;
9475 bulk_reg[i].buf = (u8 *)(&val[j]);
9476 bulk_reg[i].bytes = 4;
9477 bulk_reg[i+1].reg = swr_wr_addr_base;
9478 bulk_reg[i+1].buf = (u8 *)(&reg[j]);
9479 bulk_reg[i+1].bytes = 4;
9480 }
9481
9482 mutex_lock(&tavil->swr.write_mutex);
9483 ret = wcd9xxx_slim_bulk_write(wcd9xxx, bulk_reg,
9484 (len * 2), false);
9485 if (ret) {
9486 dev_err(tavil->dev, "%s: swrm bulk write failed, ret: %d\n",
9487 __func__, ret);
9488 }
9489 mutex_unlock(&tavil->swr.write_mutex);
9490
9491 kfree(bulk_reg);
9492 return ret;
9493}
9494
9495static int tavil_swrm_write(void *handle, int reg, int val)
9496{
9497 struct tavil_priv *tavil;
9498 struct wcd9xxx *wcd9xxx;
9499 unsigned short swr_wr_addr_base;
9500 unsigned short swr_wr_data_base;
9501 struct wcd9xxx_reg_val bulk_reg[2];
9502 int ret;
9503
9504 if (!handle) {
9505 pr_err("%s: NULL handle\n", __func__);
9506 return -EINVAL;
9507 }
9508 tavil = (struct tavil_priv *)handle;
9509 wcd9xxx = tavil->wcd9xxx;
9510
9511 swr_wr_addr_base = WCD934X_SWR_AHB_BRIDGE_WR_ADDR_0;
9512 swr_wr_data_base = WCD934X_SWR_AHB_BRIDGE_WR_DATA_0;
9513
9514 /* First Write the Data to register */
9515 bulk_reg[0].reg = swr_wr_data_base;
9516 bulk_reg[0].buf = (u8 *)(&val);
9517 bulk_reg[0].bytes = 4;
9518 bulk_reg[1].reg = swr_wr_addr_base;
9519 bulk_reg[1].buf = (u8 *)(&reg);
9520 bulk_reg[1].bytes = 4;
9521
9522 mutex_lock(&tavil->swr.write_mutex);
9523 ret = wcd9xxx_slim_bulk_write(wcd9xxx, bulk_reg, 2, false);
9524 if (ret < 0)
9525 dev_err(tavil->dev, "%s: WR Data Failure\n", __func__);
9526 mutex_unlock(&tavil->swr.write_mutex);
9527
9528 return ret;
9529}
9530
9531static int tavil_swrm_clock(void *handle, bool enable)
9532{
9533 struct tavil_priv *tavil;
9534
9535 if (!handle) {
9536 pr_err("%s: NULL handle\n", __func__);
9537 return -EINVAL;
9538 }
9539 tavil = (struct tavil_priv *)handle;
9540
9541 mutex_lock(&tavil->swr.clk_mutex);
9542 dev_dbg(tavil->dev, "%s: swrm clock %s\n",
9543 __func__, (enable?"enable" : "disable"));
9544 if (enable) {
9545 tavil->swr.clk_users++;
9546 if (tavil->swr.clk_users == 1) {
9547 regmap_update_bits(tavil->wcd9xxx->regmap,
9548 WCD934X_TEST_DEBUG_NPL_DLY_TEST_1,
9549 0x10, 0x00);
9550 __tavil_cdc_mclk_enable(tavil, true);
9551 regmap_update_bits(tavil->wcd9xxx->regmap,
9552 WCD934X_CDC_CLK_RST_CTRL_SWR_CONTROL,
9553 0x01, 0x01);
9554 }
9555 } else {
9556 tavil->swr.clk_users--;
9557 if (tavil->swr.clk_users == 0) {
9558 regmap_update_bits(tavil->wcd9xxx->regmap,
9559 WCD934X_CDC_CLK_RST_CTRL_SWR_CONTROL,
9560 0x01, 0x00);
9561 __tavil_cdc_mclk_enable(tavil, false);
9562 regmap_update_bits(tavil->wcd9xxx->regmap,
9563 WCD934X_TEST_DEBUG_NPL_DLY_TEST_1,
9564 0x10, 0x10);
9565 }
9566 }
9567 dev_dbg(tavil->dev, "%s: swrm clock users %d\n",
9568 __func__, tavil->swr.clk_users);
9569 mutex_unlock(&tavil->swr.clk_mutex);
9570
9571 return 0;
9572}
9573
9574static int tavil_swrm_handle_irq(void *handle,
9575 irqreturn_t (*swrm_irq_handler)(int irq,
9576 void *data),
9577 void *swrm_handle,
9578 int action)
9579{
9580 struct tavil_priv *tavil;
9581 int ret = 0;
9582 struct wcd9xxx *wcd9xxx;
9583
9584 if (!handle) {
9585 pr_err("%s: NULL handle\n", __func__);
9586 return -EINVAL;
9587 }
9588 tavil = (struct tavil_priv *) handle;
9589 wcd9xxx = tavil->wcd9xxx;
9590
9591 if (action) {
9592 ret = wcd9xxx_request_irq(&wcd9xxx->core_res,
9593 WCD934X_IRQ_SOUNDWIRE,
9594 swrm_irq_handler,
9595 "Tavil SWR Master", swrm_handle);
9596 if (ret)
9597 dev_err(tavil->dev, "%s: Failed to request irq %d\n",
9598 __func__, WCD934X_IRQ_SOUNDWIRE);
9599 } else
9600 wcd9xxx_free_irq(&wcd9xxx->core_res, WCD934X_IRQ_SOUNDWIRE,
9601 swrm_handle);
9602
9603 return ret;
9604}
9605
9606static void tavil_codec_add_spi_device(struct tavil_priv *tavil,
9607 struct device_node *node)
9608{
9609 struct spi_master *master;
9610 struct spi_device *spi;
9611 u32 prop_value;
9612 int rc;
9613
9614 /* Read the master bus num from DT node */
9615 rc = of_property_read_u32(node, "qcom,master-bus-num",
9616 &prop_value);
Xiaoyu Ye1a2d8bd92017-01-31 18:54:15 -08009617 if (rc < 0) {
Banajit Goswamide8271c2017-01-18 00:28:59 -08009618 dev_err(tavil->dev, "%s: prop %s not found in node %s",
9619 __func__, "qcom,master-bus-num", node->full_name);
9620 goto done;
9621 }
9622
9623 /* Get the reference to SPI master */
9624 master = spi_busnum_to_master(prop_value);
9625 if (!master) {
9626 dev_err(tavil->dev, "%s: Invalid spi_master for bus_num %u\n",
9627 __func__, prop_value);
9628 goto done;
9629 }
9630
9631 /* Allocate the spi device */
9632 spi = spi_alloc_device(master);
9633 if (!spi) {
9634 dev_err(tavil->dev, "%s: spi_alloc_device failed\n",
9635 __func__);
9636 goto err_spi_alloc_dev;
9637 }
9638
9639 /* Initialize device properties */
9640 if (of_modalias_node(node, spi->modalias,
9641 sizeof(spi->modalias)) < 0) {
9642 dev_err(tavil->dev, "%s: cannot find modalias for %s\n",
9643 __func__, node->full_name);
9644 goto err_dt_parse;
9645 }
9646
9647 rc = of_property_read_u32(node, "qcom,chip-select",
9648 &prop_value);
Xiaoyu Ye1a2d8bd92017-01-31 18:54:15 -08009649 if (rc < 0) {
Banajit Goswamide8271c2017-01-18 00:28:59 -08009650 dev_err(tavil->dev, "%s: prop %s not found in node %s",
9651 __func__, "qcom,chip-select", node->full_name);
9652 goto err_dt_parse;
9653 }
9654 spi->chip_select = prop_value;
9655
9656 rc = of_property_read_u32(node, "qcom,max-frequency",
9657 &prop_value);
Xiaoyu Ye1a2d8bd92017-01-31 18:54:15 -08009658 if (rc < 0) {
Banajit Goswamide8271c2017-01-18 00:28:59 -08009659 dev_err(tavil->dev, "%s: prop %s not found in node %s",
9660 __func__, "qcom,max-frequency", node->full_name);
9661 goto err_dt_parse;
9662 }
9663 spi->max_speed_hz = prop_value;
9664
9665 spi->dev.of_node = node;
9666
9667 rc = spi_add_device(spi);
Xiaoyu Ye1a2d8bd92017-01-31 18:54:15 -08009668 if (rc < 0) {
Banajit Goswamide8271c2017-01-18 00:28:59 -08009669 dev_err(tavil->dev, "%s: spi_add_device failed\n", __func__);
9670 goto err_dt_parse;
9671 }
9672
9673 /* Put the reference to SPI master */
9674 put_device(&master->dev);
9675
9676 return;
9677
9678err_dt_parse:
9679 spi_dev_put(spi);
9680
9681err_spi_alloc_dev:
9682 /* Put the reference to SPI master */
9683 put_device(&master->dev);
9684done:
9685 return;
9686}
9687
9688static void tavil_add_child_devices(struct work_struct *work)
9689{
9690 struct tavil_priv *tavil;
9691 struct platform_device *pdev;
9692 struct device_node *node;
9693 struct wcd9xxx *wcd9xxx;
9694 struct tavil_swr_ctrl_data *swr_ctrl_data = NULL, *temp;
9695 int ret, ctrl_num = 0;
9696 struct wcd_swr_ctrl_platform_data *platdata;
9697 char plat_dev_name[WCD934X_STRING_LEN];
9698
9699 tavil = container_of(work, struct tavil_priv,
9700 tavil_add_child_devices_work);
9701 if (!tavil) {
9702 pr_err("%s: Memory for WCD934X does not exist\n",
9703 __func__);
9704 return;
9705 }
9706 wcd9xxx = tavil->wcd9xxx;
9707 if (!wcd9xxx) {
9708 pr_err("%s: Memory for WCD9XXX does not exist\n",
9709 __func__);
9710 return;
9711 }
9712 if (!wcd9xxx->dev->of_node) {
9713 dev_err(wcd9xxx->dev, "%s: DT node for wcd9xxx does not exist\n",
9714 __func__);
9715 return;
9716 }
9717
9718 platdata = &tavil->swr.plat_data;
9719
9720 for_each_child_of_node(wcd9xxx->dev->of_node, node) {
9721
9722 /* Parse and add the SPI device node */
9723 if (!strcmp(node->name, "wcd_spi")) {
9724 tavil_codec_add_spi_device(tavil, node);
9725 continue;
9726 }
9727
9728 /* Parse other child device nodes and add platform device */
9729 if (!strcmp(node->name, "swr_master"))
9730 strlcpy(plat_dev_name, "tavil_swr_ctrl",
9731 (WCD934X_STRING_LEN - 1));
9732 else if (strnstr(node->name, "msm_cdc_pinctrl",
9733 strlen("msm_cdc_pinctrl")) != NULL)
9734 strlcpy(plat_dev_name, node->name,
9735 (WCD934X_STRING_LEN - 1));
9736 else
9737 continue;
9738
9739 pdev = platform_device_alloc(plat_dev_name, -1);
9740 if (!pdev) {
9741 dev_err(wcd9xxx->dev, "%s: pdev memory alloc failed\n",
9742 __func__);
9743 ret = -ENOMEM;
9744 goto err_mem;
9745 }
9746 pdev->dev.parent = tavil->dev;
9747 pdev->dev.of_node = node;
9748
9749 if (strcmp(node->name, "swr_master") == 0) {
9750 ret = platform_device_add_data(pdev, platdata,
9751 sizeof(*platdata));
9752 if (ret) {
9753 dev_err(&pdev->dev,
9754 "%s: cannot add plat data ctrl:%d\n",
9755 __func__, ctrl_num);
9756 goto err_pdev_add;
9757 }
9758 }
9759
9760 ret = platform_device_add(pdev);
9761 if (ret) {
9762 dev_err(&pdev->dev,
9763 "%s: Cannot add platform device\n",
9764 __func__);
9765 goto err_pdev_add;
9766 }
9767
9768 if (strcmp(node->name, "swr_master") == 0) {
9769 temp = krealloc(swr_ctrl_data,
9770 (ctrl_num + 1) * sizeof(
9771 struct tavil_swr_ctrl_data),
9772 GFP_KERNEL);
9773 if (!temp) {
9774 dev_err(wcd9xxx->dev, "out of memory\n");
9775 ret = -ENOMEM;
9776 goto err_pdev_add;
9777 }
9778 swr_ctrl_data = temp;
9779 swr_ctrl_data[ctrl_num].swr_pdev = pdev;
9780 ctrl_num++;
9781 dev_dbg(&pdev->dev,
9782 "%s: Added soundwire ctrl device(s)\n",
9783 __func__);
9784 tavil->swr.ctrl_data = swr_ctrl_data;
9785 }
9786 }
9787
9788 return;
9789
9790err_pdev_add:
9791 platform_device_put(pdev);
9792err_mem:
9793 return;
9794}
9795
9796static int __tavil_enable_efuse_sensing(struct tavil_priv *tavil)
9797{
9798 int val, rc;
9799
9800 __tavil_cdc_mclk_enable(tavil, true);
9801
9802 regmap_update_bits(tavil->wcd9xxx->regmap,
9803 WCD934X_CHIP_TIER_CTRL_EFUSE_CTL, 0x1E, 0x10);
9804 regmap_update_bits(tavil->wcd9xxx->regmap,
9805 WCD934X_CHIP_TIER_CTRL_EFUSE_CTL, 0x01, 0x01);
9806
9807 /*
9808 * 5ms sleep required after enabling efuse control
9809 * before checking the status.
9810 */
9811 usleep_range(5000, 5500);
9812 rc = regmap_read(tavil->wcd9xxx->regmap,
9813 WCD934X_CHIP_TIER_CTRL_EFUSE_STATUS, &val);
9814 if (rc || (!(val & 0x01)))
9815 WARN(1, "%s: Efuse sense is not complete val=%x, ret=%d\n",
9816 __func__, val, rc);
9817
9818 __tavil_cdc_mclk_enable(tavil, false);
9819
9820 return rc;
9821}
9822
9823static void ___tavil_get_codec_fine_version(struct tavil_priv *tavil)
9824{
9825 int val1, val2, version;
9826 struct regmap *regmap;
9827 u16 id_minor;
9828 u32 version_mask = 0;
9829
9830 regmap = tavil->wcd9xxx->regmap;
9831 version = tavil->wcd9xxx->version;
9832 id_minor = tavil->wcd9xxx->codec_type->id_minor;
9833
9834 regmap_read(regmap, WCD934X_CHIP_TIER_CTRL_EFUSE_VAL_OUT14, &val1);
9835 regmap_read(regmap, WCD934X_CHIP_TIER_CTRL_EFUSE_VAL_OUT15, &val2);
9836
9837 dev_dbg(tavil->dev, "%s: chip version :0x%x 0x:%x\n",
9838 __func__, val1, val2);
9839
9840 version_mask |= (!!((u8)val1 & 0x80)) << DSD_DISABLED_MASK;
9841 version_mask |= (!!((u8)val2 & 0x01)) << SLNQ_DISABLED_MASK;
9842
9843 switch (version_mask) {
9844 case DSD_DISABLED | SLNQ_DISABLED:
9845 if (id_minor == cpu_to_le16(0))
9846 version = TAVIL_VERSION_WCD9340_1_0;
9847 else if (id_minor == cpu_to_le16(0x01))
9848 version = TAVIL_VERSION_WCD9340_1_1;
9849 break;
9850 case SLNQ_DISABLED:
9851 if (id_minor == cpu_to_le16(0))
9852 version = TAVIL_VERSION_WCD9341_1_0;
9853 else if (id_minor == cpu_to_le16(0x01))
9854 version = TAVIL_VERSION_WCD9341_1_1;
9855 break;
9856 }
9857
9858 tavil->wcd9xxx->version = version;
9859 tavil->wcd9xxx->codec_type->version = version;
9860}
9861
9862/*
9863 * tavil_get_wcd_dsp_cntl: Get the reference to wcd_dsp_cntl
9864 * @dev: Device pointer for codec device
9865 *
9866 * This API gets the reference to codec's struct wcd_dsp_cntl
9867 */
9868struct wcd_dsp_cntl *tavil_get_wcd_dsp_cntl(struct device *dev)
9869{
9870 struct platform_device *pdev;
9871 struct tavil_priv *tavil;
9872
9873 if (!dev) {
9874 pr_err("%s: Invalid device\n", __func__);
9875 return NULL;
9876 }
9877
9878 pdev = to_platform_device(dev);
9879 tavil = platform_get_drvdata(pdev);
9880
9881 return tavil->wdsp_cntl;
9882}
9883EXPORT_SYMBOL(tavil_get_wcd_dsp_cntl);
9884
9885static int tavil_probe(struct platform_device *pdev)
9886{
9887 int ret = 0;
9888 struct tavil_priv *tavil;
9889 struct clk *wcd_ext_clk;
9890 struct wcd9xxx_resmgr_v2 *resmgr;
9891 struct wcd9xxx_power_region *cdc_pwr;
9892
9893 tavil = devm_kzalloc(&pdev->dev, sizeof(struct tavil_priv),
9894 GFP_KERNEL);
9895 if (!tavil)
9896 return -ENOMEM;
9897
9898 platform_set_drvdata(pdev, tavil);
9899
9900 tavil->wcd9xxx = dev_get_drvdata(pdev->dev.parent);
9901 tavil->dev = &pdev->dev;
9902 INIT_DELAYED_WORK(&tavil->power_gate_work, tavil_codec_power_gate_work);
9903 mutex_init(&tavil->power_lock);
9904 INIT_WORK(&tavil->tavil_add_child_devices_work,
9905 tavil_add_child_devices);
9906 mutex_init(&tavil->micb_lock);
9907 mutex_init(&tavil->swr.read_mutex);
9908 mutex_init(&tavil->swr.write_mutex);
9909 mutex_init(&tavil->swr.clk_mutex);
9910 mutex_init(&tavil->codec_mutex);
9911 mutex_init(&tavil->svs_mutex);
9912
9913 /*
9914 * Codec hardware by default comes up in SVS mode.
9915 * Initialize the svs_ref_cnt to 1 to reflect the hardware
9916 * state in the driver.
9917 */
9918 tavil->svs_ref_cnt = 1;
9919
9920 cdc_pwr = devm_kzalloc(&pdev->dev, sizeof(struct wcd9xxx_power_region),
9921 GFP_KERNEL);
9922 if (!cdc_pwr) {
9923 ret = -ENOMEM;
9924 goto err_resmgr;
9925 }
9926 tavil->wcd9xxx->wcd9xxx_pwr[WCD9XXX_DIG_CORE_REGION_1] = cdc_pwr;
9927 cdc_pwr->pwr_collapse_reg_min = WCD934X_DIG_CORE_REG_MIN;
9928 cdc_pwr->pwr_collapse_reg_max = WCD934X_DIG_CORE_REG_MAX;
9929 wcd9xxx_set_power_state(tavil->wcd9xxx,
9930 WCD_REGION_POWER_COLLAPSE_REMOVE,
9931 WCD9XXX_DIG_CORE_REGION_1);
9932 /*
9933 * Init resource manager so that if child nodes such as SoundWire
9934 * requests for clock, resource manager can honor the request
9935 */
9936 resmgr = wcd_resmgr_init(&tavil->wcd9xxx->core_res, NULL);
9937 if (IS_ERR(resmgr)) {
9938 ret = PTR_ERR(resmgr);
9939 dev_err(&pdev->dev, "%s: Failed to initialize wcd resmgr\n",
9940 __func__);
9941 goto err_resmgr;
9942 }
9943 tavil->resmgr = resmgr;
9944 tavil->swr.plat_data.handle = (void *) tavil;
9945 tavil->swr.plat_data.read = tavil_swrm_read;
9946 tavil->swr.plat_data.write = tavil_swrm_write;
9947 tavil->swr.plat_data.bulk_write = tavil_swrm_bulk_write;
9948 tavil->swr.plat_data.clk = tavil_swrm_clock;
9949 tavil->swr.plat_data.handle_irq = tavil_swrm_handle_irq;
9950 tavil->swr.spkr_gain_offset = WCD934X_RX_GAIN_OFFSET_0_DB;
9951
9952 /* Register for Clock */
9953 wcd_ext_clk = clk_get(tavil->wcd9xxx->dev, "wcd_clk");
9954 if (IS_ERR(wcd_ext_clk)) {
9955 dev_err(tavil->wcd9xxx->dev, "%s: clk get %s failed\n",
9956 __func__, "wcd_ext_clk");
9957 goto err_clk;
9958 }
9959 tavil->wcd_ext_clk = wcd_ext_clk;
9960 set_bit(AUDIO_NOMINAL, &tavil->status_mask);
9961 /* Update codec register default values */
9962 dev_dbg(&pdev->dev, "%s: MCLK Rate = %x\n", __func__,
9963 tavil->wcd9xxx->mclk_rate);
9964 if (tavil->wcd9xxx->mclk_rate == WCD934X_MCLK_CLK_12P288MHZ)
9965 regmap_update_bits(tavil->wcd9xxx->regmap,
9966 WCD934X_CODEC_RPM_CLK_MCLK_CFG,
9967 0x03, 0x00);
9968 else if (tavil->wcd9xxx->mclk_rate == WCD934X_MCLK_CLK_9P6MHZ)
9969 regmap_update_bits(tavil->wcd9xxx->regmap,
9970 WCD934X_CODEC_RPM_CLK_MCLK_CFG,
9971 0x03, 0x01);
9972 tavil_update_reg_defaults(tavil);
9973 __tavil_enable_efuse_sensing(tavil);
9974 ___tavil_get_codec_fine_version(tavil);
9975 tavil_update_cpr_defaults(tavil);
9976
9977 /* Register with soc framework */
9978 ret = snd_soc_register_codec(&pdev->dev, &soc_codec_dev_tavil,
9979 tavil_dai, ARRAY_SIZE(tavil_dai));
9980 if (ret) {
9981 dev_err(&pdev->dev, "%s: Codec registration failed\n",
9982 __func__);
9983 goto err_cdc_reg;
9984 }
9985 schedule_work(&tavil->tavil_add_child_devices_work);
9986
9987 return ret;
9988
9989err_cdc_reg:
9990 clk_put(tavil->wcd_ext_clk);
9991err_clk:
9992 wcd_resmgr_remove(tavil->resmgr);
9993err_resmgr:
9994 mutex_destroy(&tavil->micb_lock);
9995 mutex_destroy(&tavil->svs_mutex);
9996 mutex_destroy(&tavil->codec_mutex);
9997 mutex_destroy(&tavil->swr.read_mutex);
9998 mutex_destroy(&tavil->swr.write_mutex);
9999 mutex_destroy(&tavil->swr.clk_mutex);
10000 devm_kfree(&pdev->dev, tavil);
10001
10002 return ret;
10003}
10004
10005static int tavil_remove(struct platform_device *pdev)
10006{
10007 struct tavil_priv *tavil;
10008
10009 tavil = platform_get_drvdata(pdev);
10010 if (!tavil)
10011 return -EINVAL;
10012
10013 mutex_destroy(&tavil->micb_lock);
10014 mutex_destroy(&tavil->svs_mutex);
10015 mutex_destroy(&tavil->codec_mutex);
10016 mutex_destroy(&tavil->swr.read_mutex);
10017 mutex_destroy(&tavil->swr.write_mutex);
10018 mutex_destroy(&tavil->swr.clk_mutex);
10019
10020 snd_soc_unregister_codec(&pdev->dev);
10021 clk_put(tavil->wcd_ext_clk);
10022 wcd_resmgr_remove(tavil->resmgr);
10023 if (tavil->dsd_config) {
10024 tavil_dsd_deinit(tavil->dsd_config);
10025 tavil->dsd_config = NULL;
10026 }
10027 devm_kfree(&pdev->dev, tavil);
10028 return 0;
10029}
10030
10031static struct platform_driver tavil_codec_driver = {
10032 .probe = tavil_probe,
10033 .remove = tavil_remove,
10034 .driver = {
10035 .name = "tavil_codec",
10036 .owner = THIS_MODULE,
10037#ifdef CONFIG_PM
10038 .pm = &tavil_pm_ops,
10039#endif
10040 },
10041};
10042
10043module_platform_driver(tavil_codec_driver);
10044
10045MODULE_DESCRIPTION("Tavil Codec driver");
10046MODULE_LICENSE("GPL v2");