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