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