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