xref: /linux/sound/soc/codecs/max98396.c (revision 0ea5c948cb64bab5bc7a5516774eb8536f05aa0d)
1b5858113SRyan Lee // SPDX-License-Identifier: GPL-2.0
2b5858113SRyan Lee // Copyright (c) 2022, Analog Devices Inc.
3b5858113SRyan Lee 
40b7f644fSHui Tang #include <linux/gpio/consumer.h>
5b5858113SRyan Lee #include <linux/i2c.h>
6b5858113SRyan Lee #include <linux/module.h>
7b5858113SRyan Lee #include <sound/pcm_params.h>
8703ee055SDaniel Mack #include <linux/regulator/consumer.h>
9b5858113SRyan Lee #include <sound/soc.h>
10b5858113SRyan Lee #include <sound/tlv.h>
11b5858113SRyan Lee #include "max98396.h"
12b5858113SRyan Lee 
13703ee055SDaniel Mack static const char * const max98396_core_supplies[MAX98396_NUM_CORE_SUPPLIES] = {
14703ee055SDaniel Mack 	"avdd",
15703ee055SDaniel Mack 	"dvdd",
16703ee055SDaniel Mack 	"dvddio",
17703ee055SDaniel Mack };
18703ee055SDaniel Mack 
19b5858113SRyan Lee static struct reg_default max98396_reg[] = {
20b5858113SRyan Lee 	{MAX98396_R2000_SW_RESET, 0x00},
21b5858113SRyan Lee 	{MAX98396_R2001_INT_RAW1, 0x00},
22b5858113SRyan Lee 	{MAX98396_R2002_INT_RAW2, 0x00},
23b5858113SRyan Lee 	{MAX98396_R2003_INT_RAW3, 0x00},
24b5858113SRyan Lee 	{MAX98396_R2004_INT_RAW4, 0x00},
25b5858113SRyan Lee 	{MAX98396_R2006_INT_STATE1, 0x00},
26b5858113SRyan Lee 	{MAX98396_R2007_INT_STATE2, 0x00},
27b5858113SRyan Lee 	{MAX98396_R2008_INT_STATE3, 0x00},
28b5858113SRyan Lee 	{MAX98396_R2009_INT_STATE4, 0x00},
29b5858113SRyan Lee 	{MAX98396_R200B_INT_FLAG1, 0x00},
30b5858113SRyan Lee 	{MAX98396_R200C_INT_FLAG2, 0x00},
31b5858113SRyan Lee 	{MAX98396_R200D_INT_FLAG3, 0x00},
32b5858113SRyan Lee 	{MAX98396_R200E_INT_FLAG4, 0x00},
33b5858113SRyan Lee 	{MAX98396_R2010_INT_EN1, 0x02},
34b5858113SRyan Lee 	{MAX98396_R2011_INT_EN2, 0x00},
35b5858113SRyan Lee 	{MAX98396_R2012_INT_EN3, 0x00},
36b5858113SRyan Lee 	{MAX98396_R2013_INT_EN4, 0x00},
37b5858113SRyan Lee 	{MAX98396_R2015_INT_FLAG_CLR1, 0x00},
38b5858113SRyan Lee 	{MAX98396_R2016_INT_FLAG_CLR2, 0x00},
39b5858113SRyan Lee 	{MAX98396_R2017_INT_FLAG_CLR3, 0x00},
40b5858113SRyan Lee 	{MAX98396_R2018_INT_FLAG_CLR4, 0x00},
41b5858113SRyan Lee 	{MAX98396_R201F_IRQ_CTRL, 0x00},
42b5858113SRyan Lee 	{MAX98396_R2020_THERM_WARN_THRESH, 0x46},
43b5858113SRyan Lee 	{MAX98396_R2021_THERM_WARN_THRESH2, 0x46},
44b5858113SRyan Lee 	{MAX98396_R2022_THERM_SHDN_THRESH, 0x64},
45b5858113SRyan Lee 	{MAX98396_R2023_THERM_HYSTERESIS, 0x02},
46b5858113SRyan Lee 	{MAX98396_R2024_THERM_FOLDBACK_SET, 0xC5},
47b5858113SRyan Lee 	{MAX98396_R2027_THERM_FOLDBACK_EN, 0x01},
48b5858113SRyan Lee 	{MAX98396_R2030_NOISEGATE_MODE_CTRL, 0x32},
49b5858113SRyan Lee 	{MAX98396_R2033_NOISEGATE_MODE_EN, 0x00},
50b5858113SRyan Lee 	{MAX98396_R2038_CLK_MON_CTRL, 0x00},
51b5858113SRyan Lee 	{MAX98396_R2039_DATA_MON_CTRL, 0x00},
52b5858113SRyan Lee 	{MAX98396_R203F_ENABLE_CTRLS, 0x0F},
53b5858113SRyan Lee 	{MAX98396_R2040_PIN_CFG, 0x55},
54b5858113SRyan Lee 	{MAX98396_R2041_PCM_MODE_CFG, 0xC0},
55b5858113SRyan Lee 	{MAX98396_R2042_PCM_CLK_SETUP, 0x04},
56b5858113SRyan Lee 	{MAX98396_R2043_PCM_SR_SETUP, 0x88},
57b5858113SRyan Lee 	{MAX98396_R2044_PCM_TX_CTRL_1, 0x00},
58b5858113SRyan Lee 	{MAX98396_R2045_PCM_TX_CTRL_2, 0x00},
59b5858113SRyan Lee 	{MAX98396_R2046_PCM_TX_CTRL_3, 0x00},
60b5858113SRyan Lee 	{MAX98396_R2047_PCM_TX_CTRL_4, 0x00},
61b5858113SRyan Lee 	{MAX98396_R2048_PCM_TX_CTRL_5, 0x00},
62b5858113SRyan Lee 	{MAX98396_R2049_PCM_TX_CTRL_6, 0x00},
63b5858113SRyan Lee 	{MAX98396_R204A_PCM_TX_CTRL_7, 0x00},
64b5858113SRyan Lee 	{MAX98396_R204B_PCM_TX_CTRL_8, 0x00},
65b5858113SRyan Lee 	{MAX98396_R204C_PCM_TX_HIZ_CTRL_1, 0xFF},
66b5858113SRyan Lee 	{MAX98396_R204D_PCM_TX_HIZ_CTRL_2, 0xFF},
67b5858113SRyan Lee 	{MAX98396_R204E_PCM_TX_HIZ_CTRL_3, 0xFF},
68b5858113SRyan Lee 	{MAX98396_R204F_PCM_TX_HIZ_CTRL_4, 0xFF},
69b5858113SRyan Lee 	{MAX98396_R2050_PCM_TX_HIZ_CTRL_5, 0xFF},
70b5858113SRyan Lee 	{MAX98396_R2051_PCM_TX_HIZ_CTRL_6, 0xFF},
71b5858113SRyan Lee 	{MAX98396_R2052_PCM_TX_HIZ_CTRL_7, 0xFF},
72b5858113SRyan Lee 	{MAX98396_R2053_PCM_TX_HIZ_CTRL_8, 0xFF},
73b5858113SRyan Lee 	{MAX98396_R2055_PCM_RX_SRC1, 0x00},
74b5858113SRyan Lee 	{MAX98396_R2056_PCM_RX_SRC2, 0x00},
75b5858113SRyan Lee 	{MAX98396_R2058_PCM_BYPASS_SRC, 0x00},
76b5858113SRyan Lee 	{MAX98396_R205D_PCM_TX_SRC_EN, 0x00},
77b5858113SRyan Lee 	{MAX98396_R205E_PCM_RX_EN, 0x00},
78b5858113SRyan Lee 	{MAX98396_R205F_PCM_TX_EN, 0x00},
79b5858113SRyan Lee 	{MAX98396_R2070_ICC_RX_EN_A, 0x00},
80b5858113SRyan Lee 	{MAX98396_R2071_ICC_RX_EN_B, 0x00},
81b5858113SRyan Lee 	{MAX98396_R2072_ICC_TX_CTRL, 0x00},
82b5858113SRyan Lee 	{MAX98396_R207F_ICC_EN, 0x00},
83b5858113SRyan Lee 	{MAX98396_R2083_TONE_GEN_DC_CFG, 0x04},
84b5858113SRyan Lee 	{MAX98396_R2084_TONE_GEN_DC_LVL1, 0x00},
85b5858113SRyan Lee 	{MAX98396_R2085_TONE_GEN_DC_LVL2, 0x00},
86b5858113SRyan Lee 	{MAX98396_R2086_TONE_GEN_DC_LVL3, 0x00},
87b5858113SRyan Lee 	{MAX98396_R208F_TONE_GEN_EN, 0x00},
88b5858113SRyan Lee 	{MAX98396_R2090_AMP_VOL_CTRL, 0x00},
89b5858113SRyan Lee 	{MAX98396_R2091_AMP_PATH_GAIN, 0x0B},
90b5858113SRyan Lee 	{MAX98396_R2092_AMP_DSP_CFG, 0x23},
91b5858113SRyan Lee 	{MAX98396_R2093_SSM_CFG, 0x0D},
92b5858113SRyan Lee 	{MAX98396_R2094_SPK_CLS_DG_THRESH, 0x12},
93b5858113SRyan Lee 	{MAX98396_R2095_SPK_CLS_DG_HDR, 0x17},
94b5858113SRyan Lee 	{MAX98396_R2096_SPK_CLS_DG_HOLD_TIME, 0x17},
95b5858113SRyan Lee 	{MAX98396_R2097_SPK_CLS_DG_DELAY, 0x00},
96b5858113SRyan Lee 	{MAX98396_R2098_SPK_CLS_DG_MODE, 0x00},
97b5858113SRyan Lee 	{MAX98396_R2099_SPK_CLS_DG_VBAT_LVL, 0x03},
98b5858113SRyan Lee 	{MAX98396_R209A_SPK_EDGE_CTRL, 0x00},
99b5858113SRyan Lee 	{MAX98396_R209C_SPK_EDGE_CTRL1, 0x0A},
100b5858113SRyan Lee 	{MAX98396_R209D_SPK_EDGE_CTRL2, 0xAA},
101b5858113SRyan Lee 	{MAX98396_R209E_AMP_CLIP_GAIN, 0x00},
102b5858113SRyan Lee 	{MAX98396_R209F_BYPASS_PATH_CFG, 0x00},
103b5858113SRyan Lee 	{MAX98396_R20A0_AMP_SUPPLY_CTL, 0x00},
104b5858113SRyan Lee 	{MAX98396_R20AF_AMP_EN, 0x00},
105b5858113SRyan Lee 	{MAX98396_R20B0_ADC_SR, 0x30},
106b5858113SRyan Lee 	{MAX98396_R20B1_ADC_PVDD_CFG, 0x00},
107b5858113SRyan Lee 	{MAX98396_R20B2_ADC_VBAT_CFG, 0x00},
108b5858113SRyan Lee 	{MAX98396_R20B3_ADC_THERMAL_CFG, 0x00},
109b5858113SRyan Lee 	{MAX98396_R20B4_ADC_READBACK_CTRL1, 0x00},
110b5858113SRyan Lee 	{MAX98396_R20B5_ADC_READBACK_CTRL2, 0x00},
111b5858113SRyan Lee 	{MAX98396_R20B6_ADC_PVDD_READBACK_MSB, 0x00},
112b5858113SRyan Lee 	{MAX98396_R20B7_ADC_PVDD_READBACK_LSB, 0x00},
113b5858113SRyan Lee 	{MAX98396_R20B8_ADC_VBAT_READBACK_MSB, 0x00},
114b5858113SRyan Lee 	{MAX98396_R20B9_ADC_VBAT_READBACK_LSB, 0x00},
115b5858113SRyan Lee 	{MAX98396_R20BA_ADC_TEMP_READBACK_MSB, 0x00},
116b5858113SRyan Lee 	{MAX98396_R20BB_ADC_TEMP_READBACK_LSB, 0x00},
117b5858113SRyan Lee 	{MAX98396_R20BC_ADC_LO_PVDD_READBACK_MSB, 0x00},
118b5858113SRyan Lee 	{MAX98396_R20BD_ADC_LO_PVDD_READBACK_LSB, 0x00},
119b5858113SRyan Lee 	{MAX98396_R20BE_ADC_LO_VBAT_READBACK_MSB, 0x00},
120b5858113SRyan Lee 	{MAX98396_R20BF_ADC_LO_VBAT_READBACK_LSB, 0x00},
121b5858113SRyan Lee 	{MAX98396_R20C7_ADC_CFG, 0x00},
122b5858113SRyan Lee 	{MAX98396_R20D0_DHT_CFG1, 0x00},
123b5858113SRyan Lee 	{MAX98396_R20D1_LIMITER_CFG1, 0x08},
124b5858113SRyan Lee 	{MAX98396_R20D2_LIMITER_CFG2, 0x00},
125b5858113SRyan Lee 	{MAX98396_R20D3_DHT_CFG2, 0x14},
126b5858113SRyan Lee 	{MAX98396_R20D4_DHT_CFG3, 0x02},
127b5858113SRyan Lee 	{MAX98396_R20D5_DHT_CFG4, 0x04},
128b5858113SRyan Lee 	{MAX98396_R20D6_DHT_HYSTERESIS_CFG, 0x07},
129b5858113SRyan Lee 	{MAX98396_R20DF_DHT_EN, 0x00},
130b5858113SRyan Lee 	{MAX98396_R20E0_IV_SENSE_PATH_CFG, 0x04},
131b5858113SRyan Lee 	{MAX98396_R20E4_IV_SENSE_PATH_EN, 0x00},
132b5858113SRyan Lee 	{MAX98396_R20E5_BPE_STATE, 0x00},
133b5858113SRyan Lee 	{MAX98396_R20E6_BPE_L3_THRESH_MSB, 0x00},
134b5858113SRyan Lee 	{MAX98396_R20E7_BPE_L3_THRESH_LSB, 0x00},
135b5858113SRyan Lee 	{MAX98396_R20E8_BPE_L2_THRESH_MSB, 0x00},
136b5858113SRyan Lee 	{MAX98396_R20E9_BPE_L2_THRESH_LSB, 0x00},
137b5858113SRyan Lee 	{MAX98396_R20EA_BPE_L1_THRESH_MSB, 0x00},
138b5858113SRyan Lee 	{MAX98396_R20EB_BPE_L1_THRESH_LSB, 0x00},
139b5858113SRyan Lee 	{MAX98396_R20EC_BPE_L0_THRESH_MSB, 0x00},
140b5858113SRyan Lee 	{MAX98396_R20ED_BPE_L0_THRESH_LSB, 0x00},
141b5858113SRyan Lee 	{MAX98396_R20EE_BPE_L3_DWELL_HOLD_TIME, 0x00},
142b5858113SRyan Lee 	{MAX98396_R20EF_BPE_L2_DWELL_HOLD_TIME, 0x00},
143b5858113SRyan Lee 	{MAX98396_R20F0_BPE_L1_DWELL_HOLD_TIME, 0x00},
144b5858113SRyan Lee 	{MAX98396_R20F1_BPE_L0_HOLD_TIME, 0x00},
145b5858113SRyan Lee 	{MAX98396_R20F2_BPE_L3_ATTACK_REL_STEP, 0x00},
146b5858113SRyan Lee 	{MAX98396_R20F3_BPE_L2_ATTACK_REL_STEP, 0x00},
147b5858113SRyan Lee 	{MAX98396_R20F4_BPE_L1_ATTACK_REL_STEP, 0x00},
148b5858113SRyan Lee 	{MAX98396_R20F5_BPE_L0_ATTACK_REL_STEP, 0x00},
149b5858113SRyan Lee 	{MAX98396_R20F6_BPE_L3_MAX_GAIN_ATTN, 0x00},
150b5858113SRyan Lee 	{MAX98396_R20F7_BPE_L2_MAX_GAIN_ATTN, 0x00},
151b5858113SRyan Lee 	{MAX98396_R20F8_BPE_L1_MAX_GAIN_ATTN, 0x00},
152b5858113SRyan Lee 	{MAX98396_R20F9_BPE_L0_MAX_GAIN_ATTN, 0x00},
153b5858113SRyan Lee 	{MAX98396_R20FA_BPE_L3_ATT_REL_RATE, 0x00},
154b5858113SRyan Lee 	{MAX98396_R20FB_BPE_L2_ATT_REL_RATE, 0x00},
155b5858113SRyan Lee 	{MAX98396_R20FC_BPE_L1_ATT_REL_RATE, 0x00},
156b5858113SRyan Lee 	{MAX98396_R20FD_BPE_L0_ATT_REL_RATE, 0x00},
157b5858113SRyan Lee 	{MAX98396_R20FE_BPE_L3_LIMITER_CFG, 0x00},
158b5858113SRyan Lee 	{MAX98396_R20FF_BPE_L2_LIMITER_CFG, 0x00},
159b5858113SRyan Lee 	{MAX98396_R2100_BPE_L1_LIMITER_CFG, 0x00},
160b5858113SRyan Lee 	{MAX98396_R2101_BPE_L0_LIMITER_CFG, 0x00},
161b5858113SRyan Lee 	{MAX98396_R2102_BPE_L3_LIM_ATT_REL_RATE, 0x00},
162b5858113SRyan Lee 	{MAX98396_R2103_BPE_L2_LIM_ATT_REL_RATE, 0x00},
163b5858113SRyan Lee 	{MAX98396_R2104_BPE_L1_LIM_ATT_REL_RATE, 0x00},
164b5858113SRyan Lee 	{MAX98396_R2105_BPE_L0_LIM_ATT_REL_RATE, 0x00},
165b5858113SRyan Lee 	{MAX98396_R2106_BPE_THRESH_HYSTERESIS, 0x00},
166b5858113SRyan Lee 	{MAX98396_R2107_BPE_INFINITE_HOLD_CLR, 0x00},
167b5858113SRyan Lee 	{MAX98396_R2108_BPE_SUPPLY_SRC, 0x00},
168b5858113SRyan Lee 	{MAX98396_R2109_BPE_LOW_STATE, 0x00},
169b5858113SRyan Lee 	{MAX98396_R210A_BPE_LOW_GAIN, 0x00},
170b5858113SRyan Lee 	{MAX98396_R210B_BPE_LOW_LIMITER, 0x00},
171b5858113SRyan Lee 	{MAX98396_R210D_BPE_EN, 0x00},
172b5858113SRyan Lee 	{MAX98396_R210E_AUTO_RESTART, 0x00},
173b5858113SRyan Lee 	{MAX98396_R210F_GLOBAL_EN, 0x00},
174b5858113SRyan Lee 	{MAX98396_R21FF_REVISION_ID, 0x00},
175b5858113SRyan Lee };
176b5858113SRyan Lee 
177b5858113SRyan Lee static struct reg_default max98397_reg[] = {
178b5858113SRyan Lee 	{MAX98396_R2000_SW_RESET, 0x00},
179b5858113SRyan Lee 	{MAX98396_R2001_INT_RAW1, 0x00},
180b5858113SRyan Lee 	{MAX98396_R2002_INT_RAW2, 0x00},
181b5858113SRyan Lee 	{MAX98396_R2003_INT_RAW3, 0x00},
182b5858113SRyan Lee 	{MAX98396_R2004_INT_RAW4, 0x00},
183b5858113SRyan Lee 	{MAX98396_R2006_INT_STATE1, 0x00},
184b5858113SRyan Lee 	{MAX98396_R2007_INT_STATE2, 0x00},
185b5858113SRyan Lee 	{MAX98396_R2008_INT_STATE3, 0x00},
186b5858113SRyan Lee 	{MAX98396_R2009_INT_STATE4, 0x00},
187b5858113SRyan Lee 	{MAX98396_R200B_INT_FLAG1, 0x00},
188b5858113SRyan Lee 	{MAX98396_R200C_INT_FLAG2, 0x00},
189b5858113SRyan Lee 	{MAX98396_R200D_INT_FLAG3, 0x00},
190b5858113SRyan Lee 	{MAX98396_R200E_INT_FLAG4, 0x00},
191b5858113SRyan Lee 	{MAX98396_R2010_INT_EN1, 0x02},
192b5858113SRyan Lee 	{MAX98396_R2011_INT_EN2, 0x00},
193b5858113SRyan Lee 	{MAX98396_R2012_INT_EN3, 0x00},
194b5858113SRyan Lee 	{MAX98396_R2013_INT_EN4, 0x00},
195b5858113SRyan Lee 	{MAX98396_R2015_INT_FLAG_CLR1, 0x00},
196b5858113SRyan Lee 	{MAX98396_R2016_INT_FLAG_CLR2, 0x00},
197b5858113SRyan Lee 	{MAX98396_R2017_INT_FLAG_CLR3, 0x00},
198b5858113SRyan Lee 	{MAX98396_R2018_INT_FLAG_CLR4, 0x00},
199b5858113SRyan Lee 	{MAX98396_R201F_IRQ_CTRL, 0x00},
200b5858113SRyan Lee 	{MAX98396_R2020_THERM_WARN_THRESH, 0x46},
201b5858113SRyan Lee 	{MAX98396_R2021_THERM_WARN_THRESH2, 0x46},
202b5858113SRyan Lee 	{MAX98396_R2022_THERM_SHDN_THRESH, 0x64},
203b5858113SRyan Lee 	{MAX98396_R2023_THERM_HYSTERESIS, 0x02},
204b5858113SRyan Lee 	{MAX98396_R2024_THERM_FOLDBACK_SET, 0xC5},
205b5858113SRyan Lee 	{MAX98396_R2027_THERM_FOLDBACK_EN, 0x01},
206b5858113SRyan Lee 	{MAX98396_R2030_NOISEGATE_MODE_CTRL, 0x32},
207b5858113SRyan Lee 	{MAX98396_R2033_NOISEGATE_MODE_EN, 0x00},
208b5858113SRyan Lee 	{MAX98396_R2038_CLK_MON_CTRL, 0x00},
209b5858113SRyan Lee 	{MAX98396_R2039_DATA_MON_CTRL, 0x00},
210b5858113SRyan Lee 	{MAX98397_R203A_SPK_MON_THRESH, 0x03},
211b5858113SRyan Lee 	{MAX98396_R203F_ENABLE_CTRLS, 0x0F},
212b5858113SRyan Lee 	{MAX98396_R2040_PIN_CFG, 0x55},
213b5858113SRyan Lee 	{MAX98396_R2041_PCM_MODE_CFG, 0xC0},
214b5858113SRyan Lee 	{MAX98396_R2042_PCM_CLK_SETUP, 0x04},
215b5858113SRyan Lee 	{MAX98396_R2043_PCM_SR_SETUP, 0x88},
216b5858113SRyan Lee 	{MAX98396_R2044_PCM_TX_CTRL_1, 0x00},
217b5858113SRyan Lee 	{MAX98396_R2045_PCM_TX_CTRL_2, 0x00},
218b5858113SRyan Lee 	{MAX98396_R2046_PCM_TX_CTRL_3, 0x00},
219b5858113SRyan Lee 	{MAX98396_R2047_PCM_TX_CTRL_4, 0x00},
220b5858113SRyan Lee 	{MAX98396_R2048_PCM_TX_CTRL_5, 0x00},
221b5858113SRyan Lee 	{MAX98396_R2049_PCM_TX_CTRL_6, 0x00},
222b5858113SRyan Lee 	{MAX98396_R204A_PCM_TX_CTRL_7, 0x00},
223b5858113SRyan Lee 	{MAX98396_R204B_PCM_TX_CTRL_8, 0x00},
224b5858113SRyan Lee 	{MAX98397_R204C_PCM_TX_CTRL_9, 0x00},
225b5858113SRyan Lee 	{MAX98397_R204D_PCM_TX_HIZ_CTRL_1, 0xFF},
226b5858113SRyan Lee 	{MAX98397_R204E_PCM_TX_HIZ_CTRL_2, 0xFF},
227b5858113SRyan Lee 	{MAX98397_R204F_PCM_TX_HIZ_CTRL_3, 0xFF},
228b5858113SRyan Lee 	{MAX98397_R2050_PCM_TX_HIZ_CTRL_4, 0xFF},
229b5858113SRyan Lee 	{MAX98397_R2051_PCM_TX_HIZ_CTRL_5, 0xFF},
230b5858113SRyan Lee 	{MAX98397_R2052_PCM_TX_HIZ_CTRL_6, 0xFF},
231b5858113SRyan Lee 	{MAX98397_R2053_PCM_TX_HIZ_CTRL_7, 0xFF},
232b5858113SRyan Lee 	{MAX98397_R2054_PCM_TX_HIZ_CTRL_8, 0xFF},
233b5858113SRyan Lee 	{MAX98397_R2056_PCM_RX_SRC1, 0x00},
234b5858113SRyan Lee 	{MAX98397_R2057_PCM_RX_SRC2, 0x00},
235b5858113SRyan Lee 	{MAX98396_R2058_PCM_BYPASS_SRC, 0x00},
236b5858113SRyan Lee 	{MAX98396_R205D_PCM_TX_SRC_EN, 0x00},
237b5858113SRyan Lee 	{MAX98396_R205E_PCM_RX_EN, 0x00},
238b5858113SRyan Lee 	{MAX98396_R205F_PCM_TX_EN, 0x00},
239b5858113SRyan Lee 	{MAX98397_R2060_PCM_TX_SUPPLY_SEL, 0x00},
240b5858113SRyan Lee 	{MAX98396_R2070_ICC_RX_EN_A, 0x00},
241b5858113SRyan Lee 	{MAX98396_R2071_ICC_RX_EN_B, 0x00},
242b5858113SRyan Lee 	{MAX98396_R2072_ICC_TX_CTRL, 0x00},
243b5858113SRyan Lee 	{MAX98396_R207F_ICC_EN, 0x00},
244b5858113SRyan Lee 	{MAX98396_R2083_TONE_GEN_DC_CFG, 0x04},
245b5858113SRyan Lee 	{MAX98396_R2084_TONE_GEN_DC_LVL1, 0x00},
246b5858113SRyan Lee 	{MAX98396_R2085_TONE_GEN_DC_LVL2, 0x00},
247b5858113SRyan Lee 	{MAX98396_R2086_TONE_GEN_DC_LVL3, 0x00},
248b5858113SRyan Lee 	{MAX98396_R208F_TONE_GEN_EN, 0x00},
249b5858113SRyan Lee 	{MAX98396_R2090_AMP_VOL_CTRL, 0x00},
250b5858113SRyan Lee 	{MAX98396_R2091_AMP_PATH_GAIN, 0x12},
251b5858113SRyan Lee 	{MAX98396_R2092_AMP_DSP_CFG, 0x22},
252b5858113SRyan Lee 	{MAX98396_R2093_SSM_CFG, 0x08},
253b5858113SRyan Lee 	{MAX98396_R2094_SPK_CLS_DG_THRESH, 0x12},
254b5858113SRyan Lee 	{MAX98396_R2095_SPK_CLS_DG_HDR, 0x17},
255b5858113SRyan Lee 	{MAX98396_R2096_SPK_CLS_DG_HOLD_TIME, 0x17},
256b5858113SRyan Lee 	{MAX98396_R2097_SPK_CLS_DG_DELAY, 0x00},
257b5858113SRyan Lee 	{MAX98396_R2098_SPK_CLS_DG_MODE, 0x00},
258b5858113SRyan Lee 	{MAX98396_R2099_SPK_CLS_DG_VBAT_LVL, 0x03},
259b5858113SRyan Lee 	{MAX98396_R209A_SPK_EDGE_CTRL, 0x00},
260b5858113SRyan Lee 	{MAX98397_R209B_SPK_PATH_WB_ONLY, 0x00},
261b5858113SRyan Lee 	{MAX98396_R209C_SPK_EDGE_CTRL1, 0x03},
262b5858113SRyan Lee 	{MAX98396_R209D_SPK_EDGE_CTRL2, 0xFC},
263b5858113SRyan Lee 	{MAX98396_R209E_AMP_CLIP_GAIN, 0x00},
264b5858113SRyan Lee 	{MAX98396_R209F_BYPASS_PATH_CFG, 0x00},
265b5858113SRyan Lee 	{MAX98396_R20AF_AMP_EN, 0x00},
266b5858113SRyan Lee 	{MAX98396_R20B0_ADC_SR, 0x30},
267b5858113SRyan Lee 	{MAX98396_R20B1_ADC_PVDD_CFG, 0x00},
268b5858113SRyan Lee 	{MAX98396_R20B2_ADC_VBAT_CFG, 0x00},
269b5858113SRyan Lee 	{MAX98396_R20B3_ADC_THERMAL_CFG, 0x00},
270b5858113SRyan Lee 	{MAX98397_R20B4_ADC_VDDH_CFG, 0x00},
271b5858113SRyan Lee 	{MAX98397_R20B5_ADC_READBACK_CTRL1, 0x00},
272b5858113SRyan Lee 	{MAX98397_R20B6_ADC_READBACK_CTRL2, 0x00},
273b5858113SRyan Lee 	{MAX98397_R20B7_ADC_PVDD_READBACK_MSB, 0x00},
274b5858113SRyan Lee 	{MAX98397_R20B8_ADC_PVDD_READBACK_LSB, 0x00},
275b5858113SRyan Lee 	{MAX98397_R20B9_ADC_VBAT_READBACK_MSB, 0x00},
276b5858113SRyan Lee 	{MAX98397_R20BA_ADC_VBAT_READBACK_LSB, 0x00},
277b5858113SRyan Lee 	{MAX98397_R20BB_ADC_TEMP_READBACK_MSB, 0x00},
278b5858113SRyan Lee 	{MAX98397_R20BC_ADC_TEMP_READBACK_LSB, 0x00},
279b5858113SRyan Lee 	{MAX98397_R20BD_ADC_VDDH__READBACK_MSB, 0x00},
280b5858113SRyan Lee 	{MAX98397_R20BE_ADC_VDDH_READBACK_LSB, 0x00},
281b5858113SRyan Lee 	{MAX98396_R20BF_ADC_LO_VBAT_READBACK_LSB, 0x00},
282b5858113SRyan Lee 	{MAX98397_R20C3_ADC_LO_VDDH_READBACK_MSB, 0x00},
283b5858113SRyan Lee 	{MAX98397_R20C4_ADC_LO_VDDH_READBACK_LSB, 0x00},
284b5858113SRyan Lee 	{MAX98397_R20C5_MEAS_ADC_OPTIMAL_MODE, 0x04},
285b5858113SRyan Lee 	{MAX98396_R20C7_ADC_CFG, 0x00},
286b5858113SRyan Lee 	{MAX98396_R20D0_DHT_CFG1, 0x00},
287b5858113SRyan Lee 	{MAX98396_R20D1_LIMITER_CFG1, 0x08},
288b5858113SRyan Lee 	{MAX98396_R20D2_LIMITER_CFG2, 0x00},
289b5858113SRyan Lee 	{MAX98396_R20D3_DHT_CFG2, 0x14},
290b5858113SRyan Lee 	{MAX98396_R20D4_DHT_CFG3, 0x02},
291b5858113SRyan Lee 	{MAX98396_R20D5_DHT_CFG4, 0x04},
292b5858113SRyan Lee 	{MAX98396_R20D6_DHT_HYSTERESIS_CFG, 0x07},
293b5858113SRyan Lee 	{MAX98396_R20DF_DHT_EN, 0x00},
294b5858113SRyan Lee 	{MAX98396_R20E0_IV_SENSE_PATH_CFG, 0x04},
295b5858113SRyan Lee 	{MAX98396_R20E4_IV_SENSE_PATH_EN, 0x00},
296b5858113SRyan Lee 	{MAX98396_R20E5_BPE_STATE, 0x00},
297b5858113SRyan Lee 	{MAX98396_R20E6_BPE_L3_THRESH_MSB, 0x00},
298b5858113SRyan Lee 	{MAX98396_R20E7_BPE_L3_THRESH_LSB, 0x00},
299b5858113SRyan Lee 	{MAX98396_R20E8_BPE_L2_THRESH_MSB, 0x00},
300b5858113SRyan Lee 	{MAX98396_R20E9_BPE_L2_THRESH_LSB, 0x00},
301b5858113SRyan Lee 	{MAX98396_R20EA_BPE_L1_THRESH_MSB, 0x00},
302b5858113SRyan Lee 	{MAX98396_R20EB_BPE_L1_THRESH_LSB, 0x00},
303b5858113SRyan Lee 	{MAX98396_R20EC_BPE_L0_THRESH_MSB, 0x00},
304b5858113SRyan Lee 	{MAX98396_R20ED_BPE_L0_THRESH_LSB, 0x00},
305b5858113SRyan Lee 	{MAX98396_R20EE_BPE_L3_DWELL_HOLD_TIME, 0x00},
306b5858113SRyan Lee 	{MAX98396_R20EF_BPE_L2_DWELL_HOLD_TIME, 0x00},
307b5858113SRyan Lee 	{MAX98396_R20F0_BPE_L1_DWELL_HOLD_TIME, 0x00},
308b5858113SRyan Lee 	{MAX98396_R20F1_BPE_L0_HOLD_TIME, 0x00},
309b5858113SRyan Lee 	{MAX98396_R20F2_BPE_L3_ATTACK_REL_STEP, 0x00},
310b5858113SRyan Lee 	{MAX98396_R20F3_BPE_L2_ATTACK_REL_STEP, 0x00},
311b5858113SRyan Lee 	{MAX98396_R20F4_BPE_L1_ATTACK_REL_STEP, 0x00},
312b5858113SRyan Lee 	{MAX98396_R20F5_BPE_L0_ATTACK_REL_STEP, 0x00},
313b5858113SRyan Lee 	{MAX98396_R20F6_BPE_L3_MAX_GAIN_ATTN, 0x00},
314b5858113SRyan Lee 	{MAX98396_R20F7_BPE_L2_MAX_GAIN_ATTN, 0x00},
315b5858113SRyan Lee 	{MAX98396_R20F8_BPE_L1_MAX_GAIN_ATTN, 0x00},
316b5858113SRyan Lee 	{MAX98396_R20F9_BPE_L0_MAX_GAIN_ATTN, 0x00},
317b5858113SRyan Lee 	{MAX98396_R20FA_BPE_L3_ATT_REL_RATE, 0x00},
318b5858113SRyan Lee 	{MAX98396_R20FB_BPE_L2_ATT_REL_RATE, 0x00},
319b5858113SRyan Lee 	{MAX98396_R20FC_BPE_L1_ATT_REL_RATE, 0x00},
320b5858113SRyan Lee 	{MAX98396_R20FD_BPE_L0_ATT_REL_RATE, 0x00},
321b5858113SRyan Lee 	{MAX98396_R20FE_BPE_L3_LIMITER_CFG, 0x00},
322b5858113SRyan Lee 	{MAX98396_R20FF_BPE_L2_LIMITER_CFG, 0x00},
323b5858113SRyan Lee 	{MAX98396_R2100_BPE_L1_LIMITER_CFG, 0x00},
324b5858113SRyan Lee 	{MAX98396_R2101_BPE_L0_LIMITER_CFG, 0x00},
325b5858113SRyan Lee 	{MAX98396_R2102_BPE_L3_LIM_ATT_REL_RATE, 0x00},
326b5858113SRyan Lee 	{MAX98396_R2103_BPE_L2_LIM_ATT_REL_RATE, 0x00},
327b5858113SRyan Lee 	{MAX98396_R2104_BPE_L1_LIM_ATT_REL_RATE, 0x00},
328b5858113SRyan Lee 	{MAX98396_R2105_BPE_L0_LIM_ATT_REL_RATE, 0x00},
329b5858113SRyan Lee 	{MAX98396_R2106_BPE_THRESH_HYSTERESIS, 0x00},
330b5858113SRyan Lee 	{MAX98396_R2107_BPE_INFINITE_HOLD_CLR, 0x00},
331b5858113SRyan Lee 	{MAX98396_R2108_BPE_SUPPLY_SRC, 0x00},
332b5858113SRyan Lee 	{MAX98396_R2109_BPE_LOW_STATE, 0x00},
333b5858113SRyan Lee 	{MAX98396_R210A_BPE_LOW_GAIN, 0x00},
334b5858113SRyan Lee 	{MAX98396_R210B_BPE_LOW_LIMITER, 0x00},
335b5858113SRyan Lee 	{MAX98396_R210D_BPE_EN, 0x00},
336b5858113SRyan Lee 	{MAX98396_R210E_AUTO_RESTART, 0x00},
337b5858113SRyan Lee 	{MAX98396_R210F_GLOBAL_EN, 0x00},
338b5858113SRyan Lee 	{MAX98397_R22FF_REVISION_ID, 0x00},
339b5858113SRyan Lee };
340b5858113SRyan Lee 
max98396_global_enable_onoff(struct regmap * regmap,bool onoff)341b5858113SRyan Lee static void max98396_global_enable_onoff(struct regmap *regmap, bool onoff)
342b5858113SRyan Lee {
343b5858113SRyan Lee 	regmap_write(regmap, MAX98396_R210F_GLOBAL_EN, onoff ? 1 : 0);
344b5858113SRyan Lee 	usleep_range(11000, 12000);
345b5858113SRyan Lee }
346b5858113SRyan Lee 
max98396_dai_set_fmt(struct snd_soc_dai * codec_dai,unsigned int fmt)347b5858113SRyan Lee static int max98396_dai_set_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
348b5858113SRyan Lee {
349b5858113SRyan Lee 	struct snd_soc_component *component = codec_dai->component;
350b5858113SRyan Lee 	struct max98396_priv *max98396 = snd_soc_component_get_drvdata(component);
351c529fd62SDaniel Mack 	unsigned int format_mask, format = 0;
352b5858113SRyan Lee 	unsigned int bclk_pol = 0;
353b5858113SRyan Lee 	int ret, status;
354b5858113SRyan Lee 	int reg;
355b5858113SRyan Lee 	bool update = false;
356b5858113SRyan Lee 
357c529fd62SDaniel Mack 	format_mask = MAX98396_PCM_MODE_CFG_FORMAT_MASK |
358c529fd62SDaniel Mack 		      MAX98396_PCM_MODE_CFG_LRCLKEDGE;
359c529fd62SDaniel Mack 
360b5858113SRyan Lee 	dev_dbg(component->dev, "%s: fmt 0x%08X\n", __func__, fmt);
361b5858113SRyan Lee 
362b5858113SRyan Lee 	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
363b5858113SRyan Lee 	case SND_SOC_DAIFMT_NB_NF:
364b5858113SRyan Lee 		break;
365b5858113SRyan Lee 	case SND_SOC_DAIFMT_NB_IF:
366b5858113SRyan Lee 		format = MAX98396_PCM_MODE_CFG_LRCLKEDGE;
367b5858113SRyan Lee 		break;
368b5858113SRyan Lee 	case SND_SOC_DAIFMT_IB_NF:
369b5858113SRyan Lee 		bclk_pol = MAX98396_PCM_MODE_CFG_BCLKEDGE;
370b5858113SRyan Lee 		break;
371b5858113SRyan Lee 	case SND_SOC_DAIFMT_IB_IF:
372b5858113SRyan Lee 		bclk_pol = MAX98396_PCM_MODE_CFG_BCLKEDGE;
373b5858113SRyan Lee 		format = MAX98396_PCM_MODE_CFG_LRCLKEDGE;
374b5858113SRyan Lee 		break;
375b5858113SRyan Lee 
376b5858113SRyan Lee 	default:
377a8c1dc9eSDaniel Mack 		dev_err(component->dev, "DAI invert mode %d unsupported\n",
378a8c1dc9eSDaniel Mack 			fmt & SND_SOC_DAIFMT_INV_MASK);
379b5858113SRyan Lee 		return -EINVAL;
380b5858113SRyan Lee 	}
381b5858113SRyan Lee 
382b5858113SRyan Lee 	/* interface format */
383b5858113SRyan Lee 	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
384b5858113SRyan Lee 	case SND_SOC_DAIFMT_I2S:
385b5858113SRyan Lee 		format |= MAX98396_PCM_FORMAT_I2S;
386b5858113SRyan Lee 		break;
387b5858113SRyan Lee 	case SND_SOC_DAIFMT_LEFT_J:
388b5858113SRyan Lee 		format |= MAX98396_PCM_FORMAT_LJ;
389b5858113SRyan Lee 		break;
390b5858113SRyan Lee 	case SND_SOC_DAIFMT_DSP_A:
391b5858113SRyan Lee 		format |= MAX98396_PCM_FORMAT_TDM_MODE1;
392b5858113SRyan Lee 		break;
393b5858113SRyan Lee 	case SND_SOC_DAIFMT_DSP_B:
394b5858113SRyan Lee 		format |= MAX98396_PCM_FORMAT_TDM_MODE0;
395b5858113SRyan Lee 		break;
396b5858113SRyan Lee 	default:
397a8c1dc9eSDaniel Mack 		dev_err(component->dev, "DAI format %d unsupported\n",
398a8c1dc9eSDaniel Mack 			fmt & SND_SOC_DAIFMT_FORMAT_MASK);
399b5858113SRyan Lee 		return -EINVAL;
400b5858113SRyan Lee 	}
401b5858113SRyan Lee 
402b5858113SRyan Lee 	ret = regmap_read(max98396->regmap, MAX98396_R210F_GLOBAL_EN, &status);
403b5858113SRyan Lee 	if (ret < 0)
404b5858113SRyan Lee 		return -EINVAL;
405b5858113SRyan Lee 
406b5858113SRyan Lee 	if (status) {
407b5858113SRyan Lee 		ret = regmap_read(max98396->regmap, MAX98396_R2041_PCM_MODE_CFG, &reg);
408b5858113SRyan Lee 		if (ret < 0)
409b5858113SRyan Lee 			return -EINVAL;
410c529fd62SDaniel Mack 		if (format != (reg & format_mask)) {
411b5858113SRyan Lee 			update = true;
412b5858113SRyan Lee 		} else {
413b5858113SRyan Lee 			ret = regmap_read(max98396->regmap,
414b5858113SRyan Lee 					  MAX98396_R2042_PCM_CLK_SETUP, &reg);
415b5858113SRyan Lee 			if (ret < 0)
416b5858113SRyan Lee 				return -EINVAL;
417b5858113SRyan Lee 			if (bclk_pol != (reg & MAX98396_PCM_MODE_CFG_BCLKEDGE))
418b5858113SRyan Lee 				update = true;
419b5858113SRyan Lee 		}
420b5858113SRyan Lee 		/* GLOBAL_EN OFF prior to pcm mode, clock configuration change */
421b5858113SRyan Lee 		if (update)
422b5858113SRyan Lee 			max98396_global_enable_onoff(max98396->regmap, false);
423b5858113SRyan Lee 	}
424b5858113SRyan Lee 
425b5858113SRyan Lee 	regmap_update_bits(max98396->regmap,
426b5858113SRyan Lee 			   MAX98396_R2041_PCM_MODE_CFG,
427c529fd62SDaniel Mack 			   format_mask, format);
428b5858113SRyan Lee 
429b5858113SRyan Lee 	regmap_update_bits(max98396->regmap,
430b5858113SRyan Lee 			   MAX98396_R2042_PCM_CLK_SETUP,
431b5858113SRyan Lee 			   MAX98396_PCM_MODE_CFG_BCLKEDGE,
432b5858113SRyan Lee 			   bclk_pol);
433b5858113SRyan Lee 
434b5858113SRyan Lee 	if (status && update)
435b5858113SRyan Lee 		max98396_global_enable_onoff(max98396->regmap, true);
436b5858113SRyan Lee 
437b5858113SRyan Lee 	return 0;
438b5858113SRyan Lee }
439b5858113SRyan Lee 
440d29e0a6eSDaniel Mack #define MAX98396_BSEL_32	0x2
441d29e0a6eSDaniel Mack #define MAX98396_BSEL_48	0x3
442d29e0a6eSDaniel Mack #define MAX98396_BSEL_64	0x4
443d29e0a6eSDaniel Mack #define MAX98396_BSEL_96	0x5
444d29e0a6eSDaniel Mack #define MAX98396_BSEL_128	0x6
445d29e0a6eSDaniel Mack #define MAX98396_BSEL_192	0x7
446d29e0a6eSDaniel Mack #define MAX98396_BSEL_256	0x8
447d29e0a6eSDaniel Mack #define MAX98396_BSEL_384	0x9
448d29e0a6eSDaniel Mack #define MAX98396_BSEL_512	0xa
449d29e0a6eSDaniel Mack #define MAX98396_BSEL_320	0xb
450d29e0a6eSDaniel Mack #define MAX98396_BSEL_250	0xc
451d29e0a6eSDaniel Mack #define MAX98396_BSEL_125	0xd
452d29e0a6eSDaniel Mack 
453d29e0a6eSDaniel Mack /* Refer to table 5 in the datasheet */
454d29e0a6eSDaniel Mack static const struct max98396_pcm_config {
455d29e0a6eSDaniel Mack 	int in, out, width, bsel, max_sr;
456d29e0a6eSDaniel Mack } max98396_pcm_configs[] = {
457d29e0a6eSDaniel Mack 	{ .in = 2,  .out = 4,  .width = 16, .bsel = MAX98396_BSEL_32,  .max_sr = 192000 },
458d29e0a6eSDaniel Mack 	{ .in = 2,  .out = 6,  .width = 24, .bsel = MAX98396_BSEL_48,  .max_sr = 192000 },
459d29e0a6eSDaniel Mack 	{ .in = 2,  .out = 8,  .width = 32, .bsel = MAX98396_BSEL_64,  .max_sr = 192000 },
460d29e0a6eSDaniel Mack 	{ .in = 3,  .out = 15, .width = 32, .bsel = MAX98396_BSEL_125, .max_sr = 192000 },
461d29e0a6eSDaniel Mack 	{ .in = 4,  .out = 8,  .width = 16, .bsel = MAX98396_BSEL_64,  .max_sr = 192000 },
462d29e0a6eSDaniel Mack 	{ .in = 4,  .out = 12, .width = 24, .bsel = MAX98396_BSEL_96,  .max_sr = 192000 },
463d29e0a6eSDaniel Mack 	{ .in = 4,  .out = 16, .width = 32, .bsel = MAX98396_BSEL_128, .max_sr = 192000 },
464d29e0a6eSDaniel Mack 	{ .in = 5,  .out = 15, .width = 24, .bsel = MAX98396_BSEL_125, .max_sr = 192000 },
465d29e0a6eSDaniel Mack 	{ .in = 7,  .out = 15, .width = 16, .bsel = MAX98396_BSEL_125, .max_sr = 192000 },
466d29e0a6eSDaniel Mack 	{ .in = 2,  .out = 4,  .width = 16, .bsel = MAX98396_BSEL_32,  .max_sr = 96000  },
467d29e0a6eSDaniel Mack 	{ .in = 2,  .out = 6,  .width = 24, .bsel = MAX98396_BSEL_48,  .max_sr = 96000  },
468d29e0a6eSDaniel Mack 	{ .in = 2,  .out = 8,  .width = 32, .bsel = MAX98396_BSEL_64,  .max_sr = 96000  },
469d29e0a6eSDaniel Mack 	{ .in = 3,  .out = 15, .width = 32, .bsel = MAX98396_BSEL_125, .max_sr = 96000  },
470d29e0a6eSDaniel Mack 	{ .in = 4,  .out = 8,  .width = 16, .bsel = MAX98396_BSEL_64,  .max_sr = 96000  },
471d29e0a6eSDaniel Mack 	{ .in = 4,  .out = 12, .width = 24, .bsel = MAX98396_BSEL_96,  .max_sr = 96000  },
472d29e0a6eSDaniel Mack 	{ .in = 4,  .out = 16, .width = 32, .bsel = MAX98396_BSEL_128, .max_sr = 96000  },
473d29e0a6eSDaniel Mack 	{ .in = 5,  .out = 15, .width = 24, .bsel = MAX98396_BSEL_125, .max_sr = 96000  },
474d29e0a6eSDaniel Mack 	{ .in = 7,  .out = 15, .width = 16, .bsel = MAX98396_BSEL_125, .max_sr = 96000  },
475d29e0a6eSDaniel Mack 	{ .in = 7,  .out = 31, .width = 32, .bsel = MAX98396_BSEL_250, .max_sr = 96000  },
476d29e0a6eSDaniel Mack 	{ .in = 8,  .out = 16, .width = 16, .bsel = MAX98396_BSEL_128, .max_sr = 96000  },
477d29e0a6eSDaniel Mack 	{ .in = 8,  .out = 24, .width = 24, .bsel = MAX98396_BSEL_192, .max_sr = 96000  },
478d29e0a6eSDaniel Mack 	{ .in = 8,  .out = 32, .width = 32, .bsel = MAX98396_BSEL_256, .max_sr = 96000  },
479d29e0a6eSDaniel Mack 	{ .in = 10, .out = 31, .width = 24, .bsel = MAX98396_BSEL_250, .max_sr = 96000  },
480d29e0a6eSDaniel Mack 	{ .in = 15, .out = 31, .width = 16, .bsel = MAX98396_BSEL_250, .max_sr = 96000  },
481d29e0a6eSDaniel Mack 	{ .in = 16, .out = 32, .width = 16, .bsel = MAX98396_BSEL_256, .max_sr = 96000  },
482d29e0a6eSDaniel Mack 	{ .in = 7,  .out = 31, .width = 32, .bsel = MAX98396_BSEL_250, .max_sr = 48000  },
483d29e0a6eSDaniel Mack 	{ .in = 10, .out = 31, .width = 24, .bsel = MAX98396_BSEL_250, .max_sr = 48000  },
484d29e0a6eSDaniel Mack 	{ .in = 10, .out = 40, .width = 32, .bsel = MAX98396_BSEL_320, .max_sr = 48000  },
485d29e0a6eSDaniel Mack 	{ .in = 15, .out = 31, .width = 16, .bsel = MAX98396_BSEL_250, .max_sr = 48000  },
486d29e0a6eSDaniel Mack 	{ .in = 16, .out = 48, .width = 24, .bsel = MAX98396_BSEL_384, .max_sr = 48000  },
487d29e0a6eSDaniel Mack 	{ .in = 16, .out = 64, .width = 32, .bsel = MAX98396_BSEL_512, .max_sr = 48000  },
488b5858113SRyan Lee };
489b5858113SRyan Lee 
max98396_pcm_config_index(int in_slots,int out_slots,int width)490d29e0a6eSDaniel Mack static int max98396_pcm_config_index(int in_slots, int out_slots, int width)
491b5858113SRyan Lee {
492b5858113SRyan Lee 	int i;
493d29e0a6eSDaniel Mack 
494d29e0a6eSDaniel Mack 	for (i = 0; i < ARRAY_SIZE(max98396_pcm_configs); i++) {
495d29e0a6eSDaniel Mack 		const struct max98396_pcm_config *c = &max98396_pcm_configs[i];
496d29e0a6eSDaniel Mack 
497d29e0a6eSDaniel Mack 		if (in_slots == c->in && out_slots <= c->out && width == c->width)
498d29e0a6eSDaniel Mack 			return i;
499b5858113SRyan Lee 	}
500b5858113SRyan Lee 
501d29e0a6eSDaniel Mack 	return -1;
502b5858113SRyan Lee }
503b5858113SRyan Lee 
max98396_dai_hw_params(struct snd_pcm_substream * substream,struct snd_pcm_hw_params * params,struct snd_soc_dai * dai)504b5858113SRyan Lee static int max98396_dai_hw_params(struct snd_pcm_substream *substream,
505b5858113SRyan Lee 				  struct snd_pcm_hw_params *params,
506b5858113SRyan Lee 				  struct snd_soc_dai *dai)
507b5858113SRyan Lee {
508b5858113SRyan Lee 	struct snd_soc_component *component = dai->component;
509b5858113SRyan Lee 	struct max98396_priv *max98396 = snd_soc_component_get_drvdata(component);
510b5858113SRyan Lee 	unsigned int sampling_rate = 0;
511b5858113SRyan Lee 	unsigned int chan_sz = 0;
512d29e0a6eSDaniel Mack 	int ret, reg, status, bsel = 0;
513b5858113SRyan Lee 	bool update = false;
514b5858113SRyan Lee 
515b5858113SRyan Lee 	/* pcm mode configuration */
516b5858113SRyan Lee 	switch (snd_pcm_format_width(params_format(params))) {
517b5858113SRyan Lee 	case 16:
518b5858113SRyan Lee 		chan_sz = MAX98396_PCM_MODE_CFG_CHANSZ_16;
519b5858113SRyan Lee 		break;
520b5858113SRyan Lee 	case 24:
521b5858113SRyan Lee 		chan_sz = MAX98396_PCM_MODE_CFG_CHANSZ_24;
522b5858113SRyan Lee 		break;
523b5858113SRyan Lee 	case 32:
524b5858113SRyan Lee 		chan_sz = MAX98396_PCM_MODE_CFG_CHANSZ_32;
525b5858113SRyan Lee 		break;
526b5858113SRyan Lee 	default:
527b5858113SRyan Lee 		dev_err(component->dev, "format unsupported %d\n",
528b5858113SRyan Lee 			params_format(params));
529b5858113SRyan Lee 		goto err;
530b5858113SRyan Lee 	}
531b5858113SRyan Lee 
532b5858113SRyan Lee 	dev_dbg(component->dev, "format supported %d",
533b5858113SRyan Lee 		params_format(params));
534b5858113SRyan Lee 
535b5858113SRyan Lee 	/* sampling rate configuration */
536b5858113SRyan Lee 	switch (params_rate(params)) {
537b5858113SRyan Lee 	case 8000:
538b5858113SRyan Lee 		sampling_rate = MAX98396_PCM_SR_8000;
539b5858113SRyan Lee 		break;
540b5858113SRyan Lee 	case 11025:
541b5858113SRyan Lee 		sampling_rate = MAX98396_PCM_SR_11025;
542b5858113SRyan Lee 		break;
543b5858113SRyan Lee 	case 12000:
544b5858113SRyan Lee 		sampling_rate = MAX98396_PCM_SR_12000;
545b5858113SRyan Lee 		break;
546b5858113SRyan Lee 	case 16000:
547b5858113SRyan Lee 		sampling_rate = MAX98396_PCM_SR_16000;
548b5858113SRyan Lee 		break;
549b5858113SRyan Lee 	case 22050:
550b5858113SRyan Lee 		sampling_rate = MAX98396_PCM_SR_22050;
551b5858113SRyan Lee 		break;
552b5858113SRyan Lee 	case 24000:
553b5858113SRyan Lee 		sampling_rate = MAX98396_PCM_SR_24000;
554b5858113SRyan Lee 		break;
555b5858113SRyan Lee 	case 32000:
556b5858113SRyan Lee 		sampling_rate = MAX98396_PCM_SR_32000;
557b5858113SRyan Lee 		break;
558b5858113SRyan Lee 	case 44100:
559b5858113SRyan Lee 		sampling_rate = MAX98396_PCM_SR_44100;
560b5858113SRyan Lee 		break;
561b5858113SRyan Lee 	case 48000:
562b5858113SRyan Lee 		sampling_rate = MAX98396_PCM_SR_48000;
563b5858113SRyan Lee 		break;
564b5858113SRyan Lee 	case 88200:
565b5858113SRyan Lee 		sampling_rate = MAX98396_PCM_SR_88200;
566b5858113SRyan Lee 		break;
567b5858113SRyan Lee 	case 96000:
568b5858113SRyan Lee 		sampling_rate = MAX98396_PCM_SR_96000;
569b5858113SRyan Lee 		break;
570b5858113SRyan Lee 	case 192000:
571b5858113SRyan Lee 		sampling_rate = MAX98396_PCM_SR_192000;
572b5858113SRyan Lee 		break;
573b5858113SRyan Lee 	default:
574b5858113SRyan Lee 		dev_err(component->dev, "rate %d not supported\n",
575b5858113SRyan Lee 			params_rate(params));
576b5858113SRyan Lee 		goto err;
577b5858113SRyan Lee 	}
578b5858113SRyan Lee 
579d29e0a6eSDaniel Mack 	if (max98396->tdm_mode) {
580d29e0a6eSDaniel Mack 		if (params_rate(params) > max98396->tdm_max_samplerate) {
581d29e0a6eSDaniel Mack 			dev_err(component->dev, "TDM sample rate %d too high",
582d29e0a6eSDaniel Mack 				params_rate(params));
583d29e0a6eSDaniel Mack 			goto err;
584d29e0a6eSDaniel Mack 		}
585d29e0a6eSDaniel Mack 	} else {
586d29e0a6eSDaniel Mack 		/* BCLK configuration */
587d29e0a6eSDaniel Mack 		ret = max98396_pcm_config_index(params_channels(params),
588d29e0a6eSDaniel Mack 						params_channels(params),
589d29e0a6eSDaniel Mack 						snd_pcm_format_width(params_format(params)));
590d29e0a6eSDaniel Mack 		if (ret < 0) {
591d29e0a6eSDaniel Mack 			dev_err(component->dev,
592d29e0a6eSDaniel Mack 				"no PCM config for %d channels, format %d\n",
593d29e0a6eSDaniel Mack 				params_channels(params), params_format(params));
594d29e0a6eSDaniel Mack 			goto err;
595d29e0a6eSDaniel Mack 		}
596d29e0a6eSDaniel Mack 
597d29e0a6eSDaniel Mack 		bsel = max98396_pcm_configs[ret].bsel;
598d29e0a6eSDaniel Mack 
599d29e0a6eSDaniel Mack 		if (params_rate(params) > max98396_pcm_configs[ret].max_sr) {
600d29e0a6eSDaniel Mack 			dev_err(component->dev, "sample rate %d too high",
601d29e0a6eSDaniel Mack 				params_rate(params));
602d29e0a6eSDaniel Mack 			goto err;
603d29e0a6eSDaniel Mack 		}
604d29e0a6eSDaniel Mack 	}
605d29e0a6eSDaniel Mack 
606b5858113SRyan Lee 	ret = regmap_read(max98396->regmap, MAX98396_R210F_GLOBAL_EN, &status);
607b5858113SRyan Lee 	if (ret < 0)
608b5858113SRyan Lee 		goto err;
609b5858113SRyan Lee 
610b5858113SRyan Lee 	if (status) {
611b5858113SRyan Lee 		ret = regmap_read(max98396->regmap, MAX98396_R2041_PCM_MODE_CFG, &reg);
612b5858113SRyan Lee 		if (ret < 0)
613b5858113SRyan Lee 			goto err;
614b5858113SRyan Lee 		if (chan_sz != (reg & MAX98396_PCM_MODE_CFG_CHANSZ_MASK)) {
615b5858113SRyan Lee 			update = true;
616b5858113SRyan Lee 		} else {
617b5858113SRyan Lee 			ret = regmap_read(max98396->regmap, MAX98396_R2043_PCM_SR_SETUP, &reg);
618b5858113SRyan Lee 			if (ret < 0)
619b5858113SRyan Lee 				goto err;
620b5858113SRyan Lee 			if (sampling_rate != (reg & MAX98396_PCM_SR_MASK))
621b5858113SRyan Lee 				update = true;
622b5858113SRyan Lee 		}
623b5858113SRyan Lee 
624b5858113SRyan Lee 		/* GLOBAL_EN OFF prior to channel size and sampling rate change */
625b5858113SRyan Lee 		if (update)
626b5858113SRyan Lee 			max98396_global_enable_onoff(max98396->regmap, false);
627b5858113SRyan Lee 	}
628b5858113SRyan Lee 
629b5858113SRyan Lee 	/* set channel size */
630b5858113SRyan Lee 	regmap_update_bits(max98396->regmap, MAX98396_R2041_PCM_MODE_CFG,
631b5858113SRyan Lee 			   MAX98396_PCM_MODE_CFG_CHANSZ_MASK, chan_sz);
632b5858113SRyan Lee 
633b5858113SRyan Lee 	/* set DAI_SR to correct LRCLK frequency */
634b5858113SRyan Lee 	regmap_update_bits(max98396->regmap, MAX98396_R2043_PCM_SR_SETUP,
635b5858113SRyan Lee 			   MAX98396_PCM_SR_MASK, sampling_rate);
636b5858113SRyan Lee 
637b5858113SRyan Lee 	/* set sampling rate of IV */
638b5858113SRyan Lee 	if (max98396->interleave_mode &&
639b5858113SRyan Lee 	    sampling_rate > MAX98396_PCM_SR_16000)
640b5858113SRyan Lee 		regmap_update_bits(max98396->regmap,
641b5858113SRyan Lee 				   MAX98396_R2043_PCM_SR_SETUP,
642b5858113SRyan Lee 				   MAX98396_IVADC_SR_MASK,
643b5858113SRyan Lee 				   (sampling_rate - 3)
644b5858113SRyan Lee 				   << MAX98396_IVADC_SR_SHIFT);
645b5858113SRyan Lee 	else
646b5858113SRyan Lee 		regmap_update_bits(max98396->regmap,
647b5858113SRyan Lee 				   MAX98396_R2043_PCM_SR_SETUP,
648b5858113SRyan Lee 				   MAX98396_IVADC_SR_MASK,
649b5858113SRyan Lee 				   sampling_rate << MAX98396_IVADC_SR_SHIFT);
650b5858113SRyan Lee 
651d29e0a6eSDaniel Mack 	if (bsel)
652d29e0a6eSDaniel Mack 		regmap_update_bits(max98396->regmap,
653d29e0a6eSDaniel Mack 				MAX98396_R2042_PCM_CLK_SETUP,
654d29e0a6eSDaniel Mack 				MAX98396_PCM_CLK_SETUP_BSEL_MASK,
655d29e0a6eSDaniel Mack 				bsel);
656b5858113SRyan Lee 
657b5858113SRyan Lee 	if (status && update)
658b5858113SRyan Lee 		max98396_global_enable_onoff(max98396->regmap, true);
659b5858113SRyan Lee 
660d29e0a6eSDaniel Mack 	return 0;
661b5858113SRyan Lee 
662b5858113SRyan Lee err:
663b5858113SRyan Lee 	return -EINVAL;
664b5858113SRyan Lee }
665b5858113SRyan Lee 
max98396_dai_tdm_slot(struct snd_soc_dai * dai,unsigned int tx_mask,unsigned int rx_mask,int slots,int slot_width)666b5858113SRyan Lee static int max98396_dai_tdm_slot(struct snd_soc_dai *dai,
667b5858113SRyan Lee 				 unsigned int tx_mask, unsigned int rx_mask,
668b5858113SRyan Lee 				 int slots, int slot_width)
669b5858113SRyan Lee {
670b5858113SRyan Lee 	struct snd_soc_component *component = dai->component;
671b5858113SRyan Lee 	struct max98396_priv *max98396 =
672b5858113SRyan Lee 		snd_soc_component_get_drvdata(component);
673b5858113SRyan Lee 	int bsel;
674b5858113SRyan Lee 	unsigned int chan_sz = 0;
675b5858113SRyan Lee 	int ret, status;
676b5858113SRyan Lee 	int reg;
677b5858113SRyan Lee 	bool update = false;
678b5858113SRyan Lee 
679b5858113SRyan Lee 	if (!tx_mask && !rx_mask && !slots && !slot_width)
680b5858113SRyan Lee 		max98396->tdm_mode = false;
681b5858113SRyan Lee 	else
682b5858113SRyan Lee 		max98396->tdm_mode = true;
683b5858113SRyan Lee 
684b5858113SRyan Lee 	/* BCLK configuration */
685d29e0a6eSDaniel Mack 	ret = max98396_pcm_config_index(slots, slots, slot_width);
686d29e0a6eSDaniel Mack 	if (ret < 0) {
687d29e0a6eSDaniel Mack 		dev_err(component->dev, "no TDM config for %d slots %d bits\n",
688d29e0a6eSDaniel Mack 			slots, slot_width);
689b5858113SRyan Lee 		return -EINVAL;
690b5858113SRyan Lee 	}
691b5858113SRyan Lee 
692d29e0a6eSDaniel Mack 	bsel = max98396_pcm_configs[ret].bsel;
693d29e0a6eSDaniel Mack 	max98396->tdm_max_samplerate = max98396_pcm_configs[ret].max_sr;
694d29e0a6eSDaniel Mack 
695b5858113SRyan Lee 	/* Channel size configuration */
696b5858113SRyan Lee 	switch (slot_width) {
697b5858113SRyan Lee 	case 16:
698b5858113SRyan Lee 		chan_sz = MAX98396_PCM_MODE_CFG_CHANSZ_16;
699b5858113SRyan Lee 		break;
700b5858113SRyan Lee 	case 24:
701b5858113SRyan Lee 		chan_sz = MAX98396_PCM_MODE_CFG_CHANSZ_24;
702b5858113SRyan Lee 		break;
703b5858113SRyan Lee 	case 32:
704b5858113SRyan Lee 		chan_sz = MAX98396_PCM_MODE_CFG_CHANSZ_32;
705b5858113SRyan Lee 		break;
706b5858113SRyan Lee 	default:
707a8c1dc9eSDaniel Mack 		dev_err(component->dev, "slot width %d unsupported\n",
708b5858113SRyan Lee 			slot_width);
709b5858113SRyan Lee 		return -EINVAL;
710b5858113SRyan Lee 	}
711b5858113SRyan Lee 
712b5858113SRyan Lee 	ret = regmap_read(max98396->regmap, MAX98396_R210F_GLOBAL_EN, &status);
713b5858113SRyan Lee 	if (ret < 0)
714b5858113SRyan Lee 		return -EINVAL;
715b5858113SRyan Lee 
716b5858113SRyan Lee 	if (status) {
717b5858113SRyan Lee 		ret = regmap_read(max98396->regmap, MAX98396_R2042_PCM_CLK_SETUP, &reg);
718b5858113SRyan Lee 		if (ret < 0)
719b5858113SRyan Lee 			return -EINVAL;
720b5858113SRyan Lee 		if (bsel != (reg & MAX98396_PCM_CLK_SETUP_BSEL_MASK)) {
721b5858113SRyan Lee 			update = true;
722b5858113SRyan Lee 		} else {
723b5858113SRyan Lee 			ret = regmap_read(max98396->regmap, MAX98396_R2041_PCM_MODE_CFG, &reg);
724b5858113SRyan Lee 			if (ret < 0)
725b5858113SRyan Lee 				return -EINVAL;
726b5858113SRyan Lee 			if (chan_sz != (reg & MAX98396_PCM_MODE_CFG_CHANSZ_MASK))
727b5858113SRyan Lee 				update = true;
728b5858113SRyan Lee 		}
729b5858113SRyan Lee 
730b5858113SRyan Lee 		/* GLOBAL_EN OFF prior to channel size and BCLK per LRCLK change */
731b5858113SRyan Lee 		if (update)
732b5858113SRyan Lee 			max98396_global_enable_onoff(max98396->regmap, false);
733b5858113SRyan Lee 	}
734b5858113SRyan Lee 
735b5858113SRyan Lee 	regmap_update_bits(max98396->regmap,
736b5858113SRyan Lee 			   MAX98396_R2042_PCM_CLK_SETUP,
737b5858113SRyan Lee 			   MAX98396_PCM_CLK_SETUP_BSEL_MASK,
738b5858113SRyan Lee 			   bsel);
739b5858113SRyan Lee 
740b5858113SRyan Lee 	regmap_update_bits(max98396->regmap,
741b5858113SRyan Lee 			   MAX98396_R2041_PCM_MODE_CFG,
742b5858113SRyan Lee 			   MAX98396_PCM_MODE_CFG_CHANSZ_MASK, chan_sz);
743b5858113SRyan Lee 
744b5858113SRyan Lee 	/* Rx slot configuration */
745b5858113SRyan Lee 	if (max98396->device_id == CODEC_TYPE_MAX98396) {
746b5858113SRyan Lee 		regmap_update_bits(max98396->regmap,
747b5858113SRyan Lee 				   MAX98396_R2056_PCM_RX_SRC2,
748b5858113SRyan Lee 				   MAX98396_PCM_DMIX_CH0_SRC_MASK,
749b5858113SRyan Lee 				   rx_mask);
750b5858113SRyan Lee 		regmap_update_bits(max98396->regmap,
751b5858113SRyan Lee 				   MAX98396_R2056_PCM_RX_SRC2,
752b5858113SRyan Lee 				   MAX98396_PCM_DMIX_CH1_SRC_MASK,
753b5858113SRyan Lee 				   rx_mask << MAX98396_PCM_DMIX_CH1_SHIFT);
754b5858113SRyan Lee 	} else {
755b5858113SRyan Lee 		regmap_update_bits(max98396->regmap,
756b5858113SRyan Lee 				   MAX98397_R2057_PCM_RX_SRC2,
757b5858113SRyan Lee 				   MAX98396_PCM_DMIX_CH0_SRC_MASK,
758b5858113SRyan Lee 				   rx_mask);
759b5858113SRyan Lee 		regmap_update_bits(max98396->regmap,
760b5858113SRyan Lee 				   MAX98397_R2057_PCM_RX_SRC2,
761b5858113SRyan Lee 				   MAX98396_PCM_DMIX_CH1_SRC_MASK,
762b5858113SRyan Lee 				   rx_mask << MAX98396_PCM_DMIX_CH1_SHIFT);
763b5858113SRyan Lee 	}
764b5858113SRyan Lee 
765b5858113SRyan Lee 	/* Tx slot Hi-Z configuration */
766b5858113SRyan Lee 	if (max98396->device_id == CODEC_TYPE_MAX98396) {
767b5858113SRyan Lee 		regmap_write(max98396->regmap,
768b5858113SRyan Lee 			     MAX98396_R2053_PCM_TX_HIZ_CTRL_8,
769b5858113SRyan Lee 			     ~tx_mask & 0xFF);
770b5858113SRyan Lee 		regmap_write(max98396->regmap,
771b5858113SRyan Lee 			     MAX98396_R2052_PCM_TX_HIZ_CTRL_7,
772b5858113SRyan Lee 			     (~tx_mask & 0xFF00) >> 8);
773b5858113SRyan Lee 	} else {
774b5858113SRyan Lee 		regmap_write(max98396->regmap,
775b5858113SRyan Lee 			     MAX98397_R2054_PCM_TX_HIZ_CTRL_8,
776b5858113SRyan Lee 			     ~tx_mask & 0xFF);
777b5858113SRyan Lee 		regmap_write(max98396->regmap,
778b5858113SRyan Lee 			     MAX98397_R2053_PCM_TX_HIZ_CTRL_7,
779b5858113SRyan Lee 			     (~tx_mask & 0xFF00) >> 8);
780b5858113SRyan Lee 	}
781b5858113SRyan Lee 
782b5858113SRyan Lee 	if (status && update)
783b5858113SRyan Lee 		max98396_global_enable_onoff(max98396->regmap, true);
784b5858113SRyan Lee 
785b5858113SRyan Lee 	return 0;
786b5858113SRyan Lee }
787b5858113SRyan Lee 
788b5858113SRyan Lee #define MAX98396_RATES SNDRV_PCM_RATE_8000_192000
789b5858113SRyan Lee 
790b5858113SRyan Lee #define MAX98396_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \
791b5858113SRyan Lee 	SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
792b5858113SRyan Lee 
793b5858113SRyan Lee static const struct snd_soc_dai_ops max98396_dai_ops = {
794b5858113SRyan Lee 	.set_fmt = max98396_dai_set_fmt,
795b5858113SRyan Lee 	.hw_params = max98396_dai_hw_params,
796b5858113SRyan Lee 	.set_tdm_slot = max98396_dai_tdm_slot,
797b5858113SRyan Lee };
798b5858113SRyan Lee 
max98396_dac_event(struct snd_soc_dapm_widget * w,struct snd_kcontrol * kcontrol,int event)799b5858113SRyan Lee static int max98396_dac_event(struct snd_soc_dapm_widget *w,
800b5858113SRyan Lee 			      struct snd_kcontrol *kcontrol, int event)
801b5858113SRyan Lee {
802b5858113SRyan Lee 	struct snd_soc_component *component =
803b5858113SRyan Lee 		snd_soc_dapm_to_component(w->dapm);
804b5858113SRyan Lee 	struct max98396_priv *max98396 =
805b5858113SRyan Lee 		snd_soc_component_get_drvdata(component);
806b5858113SRyan Lee 
807b5858113SRyan Lee 	switch (event) {
808b5858113SRyan Lee 	case SND_SOC_DAPM_POST_PMU:
809b5858113SRyan Lee 		max98396_global_enable_onoff(max98396->regmap, true);
810b5858113SRyan Lee 		break;
811b5858113SRyan Lee 	case SND_SOC_DAPM_PRE_PMD:
812b5858113SRyan Lee 		max98396_global_enable_onoff(max98396->regmap, false);
813b5858113SRyan Lee 
814b5858113SRyan Lee 		max98396->tdm_mode = false;
815b5858113SRyan Lee 		break;
816b5858113SRyan Lee 	default:
817b5858113SRyan Lee 		return 0;
818b5858113SRyan Lee 	}
819b5858113SRyan Lee 	return 0;
820b5858113SRyan Lee }
821b5858113SRyan Lee 
max98396_readable_register(struct device * dev,unsigned int reg)822b5858113SRyan Lee static bool max98396_readable_register(struct device *dev, unsigned int reg)
823b5858113SRyan Lee {
824b5858113SRyan Lee 	switch (reg) {
825b5858113SRyan Lee 	case MAX98396_R2001_INT_RAW1 ... MAX98396_R2004_INT_RAW4:
826b5858113SRyan Lee 	case MAX98396_R2006_INT_STATE1 ... MAX98396_R2009_INT_STATE4:
827b5858113SRyan Lee 	case MAX98396_R200B_INT_FLAG1 ... MAX98396_R200E_INT_FLAG4:
828b5858113SRyan Lee 	case MAX98396_R2010_INT_EN1 ... MAX98396_R2013_INT_EN4:
829b5858113SRyan Lee 	case MAX98396_R2015_INT_FLAG_CLR1 ... MAX98396_R2018_INT_FLAG_CLR4:
830b5858113SRyan Lee 	case MAX98396_R201F_IRQ_CTRL ... MAX98396_R2024_THERM_FOLDBACK_SET:
831b5858113SRyan Lee 	case MAX98396_R2027_THERM_FOLDBACK_EN:
832b5858113SRyan Lee 	case MAX98396_R2030_NOISEGATE_MODE_CTRL:
833b5858113SRyan Lee 	case MAX98396_R2033_NOISEGATE_MODE_EN:
834b5858113SRyan Lee 	case MAX98396_R2038_CLK_MON_CTRL ... MAX98396_R2039_DATA_MON_CTRL:
835b5858113SRyan Lee 	case MAX98396_R203F_ENABLE_CTRLS ... MAX98396_R2053_PCM_TX_HIZ_CTRL_8:
836b5858113SRyan Lee 	case MAX98396_R2055_PCM_RX_SRC1 ... MAX98396_R2056_PCM_RX_SRC2:
837b5858113SRyan Lee 	case MAX98396_R2058_PCM_BYPASS_SRC:
838b5858113SRyan Lee 	case MAX98396_R205D_PCM_TX_SRC_EN ... MAX98396_R205F_PCM_TX_EN:
839b5858113SRyan Lee 	case MAX98396_R2070_ICC_RX_EN_A... MAX98396_R2072_ICC_TX_CTRL:
840b5858113SRyan Lee 	case MAX98396_R207F_ICC_EN:
841b5858113SRyan Lee 	case MAX98396_R2083_TONE_GEN_DC_CFG ... MAX98396_R2086_TONE_GEN_DC_LVL3:
842b5858113SRyan Lee 	case MAX98396_R208F_TONE_GEN_EN ... MAX98396_R209A_SPK_EDGE_CTRL:
843b5858113SRyan Lee 	case MAX98396_R209C_SPK_EDGE_CTRL1 ... MAX98396_R20A0_AMP_SUPPLY_CTL:
844b5858113SRyan Lee 	case MAX98396_R20AF_AMP_EN ... MAX98396_R20BF_ADC_LO_VBAT_READBACK_LSB:
845b5858113SRyan Lee 	case MAX98396_R20C7_ADC_CFG:
846b5858113SRyan Lee 	case MAX98396_R20D0_DHT_CFG1 ... MAX98396_R20D6_DHT_HYSTERESIS_CFG:
847b5858113SRyan Lee 	case MAX98396_R20DF_DHT_EN:
848b5858113SRyan Lee 	case MAX98396_R20E0_IV_SENSE_PATH_CFG:
849b5858113SRyan Lee 	case MAX98396_R20E4_IV_SENSE_PATH_EN
850b5858113SRyan Lee 		... MAX98396_R2106_BPE_THRESH_HYSTERESIS:
851b5858113SRyan Lee 	case MAX98396_R2108_BPE_SUPPLY_SRC ... MAX98396_R210B_BPE_LOW_LIMITER:
852b5858113SRyan Lee 	case MAX98396_R210D_BPE_EN ... MAX98396_R210F_GLOBAL_EN:
853b5858113SRyan Lee 	case MAX98396_R21FF_REVISION_ID:
854b5858113SRyan Lee 		return true;
855b5858113SRyan Lee 	default:
856b5858113SRyan Lee 		return false;
857b5858113SRyan Lee 	}
858b5858113SRyan Lee };
859b5858113SRyan Lee 
max98396_volatile_reg(struct device * dev,unsigned int reg)860b5858113SRyan Lee static bool max98396_volatile_reg(struct device *dev, unsigned int reg)
861b5858113SRyan Lee {
862b5858113SRyan Lee 	switch (reg) {
863b5858113SRyan Lee 	case MAX98396_R2000_SW_RESET:
864b5858113SRyan Lee 	case MAX98396_R2001_INT_RAW1 ... MAX98396_R200E_INT_FLAG4:
865b5858113SRyan Lee 	case MAX98396_R2041_PCM_MODE_CFG:
866b5858113SRyan Lee 	case MAX98396_R20B6_ADC_PVDD_READBACK_MSB
867b5858113SRyan Lee 		... MAX98396_R20BF_ADC_LO_VBAT_READBACK_LSB:
868b5858113SRyan Lee 	case MAX98396_R20E5_BPE_STATE:
869b5858113SRyan Lee 	case MAX98396_R2109_BPE_LOW_STATE
870b5858113SRyan Lee 		... MAX98396_R210B_BPE_LOW_LIMITER:
871b5858113SRyan Lee 	case MAX98396_R210F_GLOBAL_EN:
872b5858113SRyan Lee 	case MAX98396_R21FF_REVISION_ID:
873b5858113SRyan Lee 		return true;
874b5858113SRyan Lee 	default:
875b5858113SRyan Lee 		return false;
876b5858113SRyan Lee 	}
877b5858113SRyan Lee }
878b5858113SRyan Lee 
max98397_readable_register(struct device * dev,unsigned int reg)879b5858113SRyan Lee static bool max98397_readable_register(struct device *dev, unsigned int reg)
880b5858113SRyan Lee {
881b5858113SRyan Lee 	switch (reg) {
882b5858113SRyan Lee 	case MAX98396_R2001_INT_RAW1 ... MAX98396_R2004_INT_RAW4:
883b5858113SRyan Lee 	case MAX98396_R2006_INT_STATE1 ... MAX98396_R2009_INT_STATE4:
884b5858113SRyan Lee 	case MAX98396_R200B_INT_FLAG1 ... MAX98396_R200E_INT_FLAG4:
885b5858113SRyan Lee 	case MAX98396_R2010_INT_EN1 ... MAX98396_R2013_INT_EN4:
886b5858113SRyan Lee 	case MAX98396_R2015_INT_FLAG_CLR1 ... MAX98396_R2018_INT_FLAG_CLR4:
887b5858113SRyan Lee 	case MAX98396_R201F_IRQ_CTRL ... MAX98396_R2024_THERM_FOLDBACK_SET:
888b5858113SRyan Lee 	case MAX98396_R2027_THERM_FOLDBACK_EN:
889b5858113SRyan Lee 	case MAX98396_R2030_NOISEGATE_MODE_CTRL:
890b5858113SRyan Lee 	case MAX98396_R2033_NOISEGATE_MODE_EN:
891b5858113SRyan Lee 	case MAX98396_R2038_CLK_MON_CTRL ... MAX98397_R203A_SPK_MON_THRESH:
892b5858113SRyan Lee 	case MAX98396_R203F_ENABLE_CTRLS ... MAX98397_R2054_PCM_TX_HIZ_CTRL_8:
893b5858113SRyan Lee 	case MAX98397_R2056_PCM_RX_SRC1... MAX98396_R2058_PCM_BYPASS_SRC:
894b5858113SRyan Lee 	case MAX98396_R205D_PCM_TX_SRC_EN ... MAX98397_R2060_PCM_TX_SUPPLY_SEL:
895b5858113SRyan Lee 	case MAX98396_R2070_ICC_RX_EN_A... MAX98396_R2072_ICC_TX_CTRL:
896b5858113SRyan Lee 	case MAX98396_R207F_ICC_EN:
897b5858113SRyan Lee 	case MAX98396_R2083_TONE_GEN_DC_CFG ... MAX98396_R2086_TONE_GEN_DC_LVL3:
898b5858113SRyan Lee 	case MAX98396_R208F_TONE_GEN_EN ... MAX98396_R209F_BYPASS_PATH_CFG:
899b5858113SRyan Lee 	case MAX98396_R20AF_AMP_EN ... MAX98397_R20C5_MEAS_ADC_OPTIMAL_MODE:
900b5858113SRyan Lee 	case MAX98396_R20C7_ADC_CFG:
901b5858113SRyan Lee 	case MAX98396_R20D0_DHT_CFG1 ... MAX98396_R20D6_DHT_HYSTERESIS_CFG:
902b5858113SRyan Lee 	case MAX98396_R20DF_DHT_EN:
903b5858113SRyan Lee 	case MAX98396_R20E0_IV_SENSE_PATH_CFG:
904b5858113SRyan Lee 	case MAX98396_R20E4_IV_SENSE_PATH_EN
905b5858113SRyan Lee 		... MAX98396_R2106_BPE_THRESH_HYSTERESIS:
906b5858113SRyan Lee 	case MAX98396_R2108_BPE_SUPPLY_SRC ... MAX98396_R210B_BPE_LOW_LIMITER:
907b5858113SRyan Lee 	case MAX98396_R210D_BPE_EN ... MAX98396_R210F_GLOBAL_EN:
908b5858113SRyan Lee 	case MAX98397_R22FF_REVISION_ID:
909b5858113SRyan Lee 		return true;
910b5858113SRyan Lee 	default:
911b5858113SRyan Lee 		return false;
912b5858113SRyan Lee 	}
913b5858113SRyan Lee };
914b5858113SRyan Lee 
max98397_volatile_reg(struct device * dev,unsigned int reg)915b5858113SRyan Lee static bool max98397_volatile_reg(struct device *dev, unsigned int reg)
916b5858113SRyan Lee {
917b5858113SRyan Lee 	switch (reg) {
918b5858113SRyan Lee 	case MAX98396_R2001_INT_RAW1 ... MAX98396_R200E_INT_FLAG4:
919b5858113SRyan Lee 	case MAX98396_R2041_PCM_MODE_CFG:
920b5858113SRyan Lee 	case MAX98397_R20B7_ADC_PVDD_READBACK_MSB
921b5858113SRyan Lee 		... MAX98397_R20C4_ADC_LO_VDDH_READBACK_LSB:
922b5858113SRyan Lee 	case MAX98396_R20E5_BPE_STATE:
923b5858113SRyan Lee 	case MAX98396_R2109_BPE_LOW_STATE
924b5858113SRyan Lee 		... MAX98396_R210B_BPE_LOW_LIMITER:
925b5858113SRyan Lee 	case MAX98396_R210F_GLOBAL_EN:
926b5858113SRyan Lee 	case MAX98397_R22FF_REVISION_ID:
927b5858113SRyan Lee 		return true;
928b5858113SRyan Lee 	default:
929b5858113SRyan Lee 		return false;
930b5858113SRyan Lee 	}
931b5858113SRyan Lee }
932b5858113SRyan Lee 
933b5858113SRyan Lee static const char * const max98396_op_mod_text[] = {
934b5858113SRyan Lee 	"DG", "PVDD", "VBAT",
935b5858113SRyan Lee };
936b5858113SRyan Lee 
937b5858113SRyan Lee static SOC_ENUM_SINGLE_DECL(max98396_op_mod_enum,
938b5858113SRyan Lee 			    MAX98396_R2098_SPK_CLS_DG_MODE,
939b5858113SRyan Lee 			    0, max98396_op_mod_text);
940b5858113SRyan Lee 
941b5858113SRyan Lee static DECLARE_TLV_DB_SCALE(max98396_digital_tlv, -6350, 50, 1);
942b5858113SRyan Lee static const DECLARE_TLV_DB_RANGE(max98396_spk_tlv,
943b5858113SRyan Lee 	0, 0x11, TLV_DB_SCALE_ITEM(400, 100, 0),
944b5858113SRyan Lee );
945b5858113SRyan Lee static DECLARE_TLV_DB_RANGE(max98397_digital_tlv,
946b5858113SRyan Lee 	0, 0x4A, TLV_DB_SCALE_ITEM(TLV_DB_GAIN_MUTE, 0, 1),
947b5858113SRyan Lee 	0x4B, 0xFF, TLV_DB_SCALE_ITEM(-9000, 50, 0),
948b5858113SRyan Lee );
949b5858113SRyan Lee static const DECLARE_TLV_DB_RANGE(max98397_spk_tlv,
950b5858113SRyan Lee 	0, 0x15, TLV_DB_SCALE_ITEM(600, 100, 0),
951b5858113SRyan Lee );
952b5858113SRyan Lee 
max98396_mux_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)953b5858113SRyan Lee static int max98396_mux_get(struct snd_kcontrol *kcontrol,
954b5858113SRyan Lee 			    struct snd_ctl_elem_value *ucontrol)
955b5858113SRyan Lee {
956b5858113SRyan Lee 	struct snd_soc_component *component =
957b5858113SRyan Lee 		snd_soc_dapm_kcontrol_component(kcontrol);
958b5858113SRyan Lee 	struct max98396_priv *max98396 = snd_soc_component_get_drvdata(component);
959b5858113SRyan Lee 	int reg, val;
960b5858113SRyan Lee 
961b5858113SRyan Lee 	if (max98396->device_id == CODEC_TYPE_MAX98396)
962b5858113SRyan Lee 		reg = MAX98396_R2055_PCM_RX_SRC1;
963b5858113SRyan Lee 	else
964b5858113SRyan Lee 		reg = MAX98397_R2056_PCM_RX_SRC1;
965b5858113SRyan Lee 
966b5858113SRyan Lee 	regmap_read(max98396->regmap, reg, &val);
967b5858113SRyan Lee 
968b5858113SRyan Lee 	ucontrol->value.enumerated.item[0] = val;
969b5858113SRyan Lee 
970b5858113SRyan Lee 	return 0;
971b5858113SRyan Lee }
972b5858113SRyan Lee 
max98396_mux_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)973b5858113SRyan Lee static int max98396_mux_put(struct snd_kcontrol *kcontrol,
974b5858113SRyan Lee 			    struct snd_ctl_elem_value *ucontrol)
975b5858113SRyan Lee {
976b5858113SRyan Lee 	struct snd_soc_component *component =
977b5858113SRyan Lee 		snd_soc_dapm_kcontrol_component(kcontrol);
978b5858113SRyan Lee 	struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kcontrol);
979b5858113SRyan Lee 	struct max98396_priv *max98396 = snd_soc_component_get_drvdata(component);
980b5858113SRyan Lee 	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
981b5858113SRyan Lee 	unsigned int *item = ucontrol->value.enumerated.item;
982b5858113SRyan Lee 	int reg, val;
983b5858113SRyan Lee 	int change;
984b5858113SRyan Lee 
985b5858113SRyan Lee 	if (item[0] >= e->items)
986b5858113SRyan Lee 		return -EINVAL;
987b5858113SRyan Lee 
988b5858113SRyan Lee 	val = snd_soc_enum_item_to_val(e, item[0]) << e->shift_l;
989b5858113SRyan Lee 
990b5858113SRyan Lee 	if (max98396->device_id == CODEC_TYPE_MAX98396)
991b5858113SRyan Lee 		reg = MAX98396_R2055_PCM_RX_SRC1;
992b5858113SRyan Lee 	else
993b5858113SRyan Lee 		reg = MAX98397_R2056_PCM_RX_SRC1;
994b5858113SRyan Lee 
995b5858113SRyan Lee 	change = snd_soc_component_test_bits(component, reg,
996b5858113SRyan Lee 					     MAX98396_PCM_RX_MASK, val);
997b5858113SRyan Lee 
998b5858113SRyan Lee 	if (change)
999b5858113SRyan Lee 		regmap_update_bits(max98396->regmap, reg,
1000b5858113SRyan Lee 				   MAX98396_PCM_RX_MASK, val);
1001b5858113SRyan Lee 
1002b5858113SRyan Lee 	snd_soc_dapm_mux_update_power(dapm, kcontrol, item[0], e, NULL);
1003b5858113SRyan Lee 
1004b5858113SRyan Lee 	return change;
1005b5858113SRyan Lee }
1006b5858113SRyan Lee 
1007b5858113SRyan Lee static const char * const max98396_switch_text[] = {
1008b5858113SRyan Lee 	"Left", "Right", "LeftRight"};
1009b5858113SRyan Lee 
1010b5858113SRyan Lee static SOC_ENUM_SINGLE_DECL(dai_sel_enum, SND_SOC_NOPM, 0,
1011b5858113SRyan Lee 			    max98396_switch_text);
1012b5858113SRyan Lee 
1013b5858113SRyan Lee static const struct snd_kcontrol_new max98396_dai_mux =
1014b5858113SRyan Lee 	SOC_DAPM_ENUM_EXT("DAI Sel Mux", dai_sel_enum,
1015b5858113SRyan Lee 			  max98396_mux_get, max98396_mux_put);
1016b5858113SRyan Lee 
1017b5858113SRyan Lee static const struct snd_kcontrol_new max98396_vi_control =
1018b5858113SRyan Lee 	SOC_DAPM_SINGLE("Switch", MAX98396_R205F_PCM_TX_EN, 0, 1, 0);
1019b5858113SRyan Lee 
1020b5858113SRyan Lee static const struct snd_soc_dapm_widget max98396_dapm_widgets[] = {
1021b5858113SRyan Lee 	SND_SOC_DAPM_DAC_E("Amp Enable", "HiFi Playback",
1022b5858113SRyan Lee 			   MAX98396_R20AF_AMP_EN, 0, 0, max98396_dac_event,
1023b5858113SRyan Lee 			   SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
1024b5858113SRyan Lee 	SND_SOC_DAPM_MUX("DAI Sel Mux", SND_SOC_NOPM, 0, 0,
1025b5858113SRyan Lee 			 &max98396_dai_mux),
1026b5858113SRyan Lee 	SND_SOC_DAPM_OUTPUT("BE_OUT"),
1027b5858113SRyan Lee 	SND_SOC_DAPM_AIF_OUT("Voltage Sense", "HiFi Capture", 0,
1028b5858113SRyan Lee 			     MAX98396_R20E4_IV_SENSE_PATH_EN, 0, 0),
1029b5858113SRyan Lee 	SND_SOC_DAPM_AIF_OUT("Current Sense", "HiFi Capture", 0,
1030b5858113SRyan Lee 			     MAX98396_R20E4_IV_SENSE_PATH_EN, 1, 0),
1031b5858113SRyan Lee 	SND_SOC_DAPM_SWITCH("VI Sense", SND_SOC_NOPM, 0, 0,
1032b5858113SRyan Lee 			    &max98396_vi_control),
1033b5858113SRyan Lee 	SND_SOC_DAPM_SIGGEN("VMON"),
1034b5858113SRyan Lee 	SND_SOC_DAPM_SIGGEN("IMON"),
1035b5858113SRyan Lee 	SND_SOC_DAPM_SIGGEN("FBMON"),
1036b5858113SRyan Lee };
1037b5858113SRyan Lee 
1038b5858113SRyan Lee static const char * const max98396_thermal_thresh_text[] = {
1039b5858113SRyan Lee 	"50C", "51C", "52C", "53C", "54C", "55C", "56C", "57C",
1040b5858113SRyan Lee 	"58C", "59C", "60C", "61C", "62C", "63C", "64C", "65C",
1041b5858113SRyan Lee 	"66C", "67C", "68C", "69C", "70C", "71C", "72C", "73C",
1042b5858113SRyan Lee 	"74C", "75C", "76C", "77C", "78C", "79C", "80C", "81C",
1043b5858113SRyan Lee 	"82C", "83C", "84C", "85C", "86C", "87C", "88C", "89C",
1044b5858113SRyan Lee 	"90C", "91C", "92C", "93C", "94C", "95C", "96C", "97C",
1045b5858113SRyan Lee 	"98C", "99C", "100C", "101C", "102C", "103C", "104C", "105C",
1046b5858113SRyan Lee 	"106C", "107C", "108C", "109C", "110C", "111C", "112C", "113C",
1047b5858113SRyan Lee 	"114C", "115C", "116C", "117C", "118C", "119C", "120C", "121C",
1048b5858113SRyan Lee 	"122C", "123C", "124C", "125C", "126C", "127C", "128C", "129C",
1049b5858113SRyan Lee 	"130C", "131C", "132C", "133C", "134C", "135C", "136C", "137C",
1050b5858113SRyan Lee 	"138C", "139C", "140C", "141C", "142C", "143C", "144C", "145C",
1051b5858113SRyan Lee 	"146C", "147C", "148C", "149C", "150C"
1052b5858113SRyan Lee };
1053b5858113SRyan Lee 
1054b5858113SRyan Lee static SOC_ENUM_SINGLE_DECL(max98396_thermal_warn_thresh1_enum,
1055b5858113SRyan Lee 			    MAX98396_R2020_THERM_WARN_THRESH, 0,
1056b5858113SRyan Lee 			    max98396_thermal_thresh_text);
1057b5858113SRyan Lee 
1058b5858113SRyan Lee static SOC_ENUM_SINGLE_DECL(max98396_thermal_warn_thresh2_enum,
1059b5858113SRyan Lee 			    MAX98396_R2021_THERM_WARN_THRESH2, 0,
1060b5858113SRyan Lee 			    max98396_thermal_thresh_text);
1061b5858113SRyan Lee 
1062b5858113SRyan Lee static SOC_ENUM_SINGLE_DECL(max98396_thermal_shdn_thresh_enum,
1063b5858113SRyan Lee 			    MAX98396_R2022_THERM_SHDN_THRESH, 0,
1064b5858113SRyan Lee 			    max98396_thermal_thresh_text);
1065b5858113SRyan Lee 
1066b5858113SRyan Lee static const char * const max98396_thermal_hyteresis_text[] = {
1067b5858113SRyan Lee 	"2C", "5C", "7C", "10C"
1068b5858113SRyan Lee };
1069b5858113SRyan Lee 
1070b5858113SRyan Lee static SOC_ENUM_SINGLE_DECL(max98396_thermal_hysteresis_enum,
1071b5858113SRyan Lee 			    MAX98396_R2023_THERM_HYSTERESIS, 0,
1072b5858113SRyan Lee 			    max98396_thermal_hyteresis_text);
1073b5858113SRyan Lee 
1074b5858113SRyan Lee static const char * const max98396_foldback_slope_text[] = {
1075b5858113SRyan Lee 	"0.25", "0.5", "1.0", "2.0"
1076b5858113SRyan Lee };
1077b5858113SRyan Lee 
1078b5858113SRyan Lee static SOC_ENUM_SINGLE_DECL(max98396_thermal_fb_slope1_enum,
1079b5858113SRyan Lee 			    MAX98396_R2024_THERM_FOLDBACK_SET,
1080b5858113SRyan Lee 			    MAX98396_THERM_FB_SLOPE1_SHIFT,
1081b5858113SRyan Lee 			    max98396_foldback_slope_text);
1082b5858113SRyan Lee 
1083b5858113SRyan Lee static SOC_ENUM_SINGLE_DECL(max98396_thermal_fb_slope2_enum,
1084b5858113SRyan Lee 			    MAX98396_R2024_THERM_FOLDBACK_SET,
1085b5858113SRyan Lee 			    MAX98396_THERM_FB_SLOPE2_SHIFT,
1086b5858113SRyan Lee 			    max98396_foldback_slope_text);
1087b5858113SRyan Lee 
1088b5858113SRyan Lee static const char * const max98396_foldback_reltime_text[] = {
1089b5858113SRyan Lee 	"3ms", "10ms", "100ms", "300ms"
1090b5858113SRyan Lee };
1091b5858113SRyan Lee 
1092b5858113SRyan Lee static SOC_ENUM_SINGLE_DECL(max98396_thermal_fb_reltime_enum,
1093b5858113SRyan Lee 			    MAX98396_R2024_THERM_FOLDBACK_SET,
1094b5858113SRyan Lee 			    MAX98396_THERM_FB_REL_SHIFT,
1095b5858113SRyan Lee 			    max98396_foldback_reltime_text);
1096b5858113SRyan Lee 
1097b5858113SRyan Lee static const char * const max98396_foldback_holdtime_text[] = {
1098b5858113SRyan Lee 	"0ms", "20ms", "40ms", "80ms"
1099b5858113SRyan Lee };
1100b5858113SRyan Lee 
1101b5858113SRyan Lee static SOC_ENUM_SINGLE_DECL(max98396_thermal_fb_holdtime_enum,
1102b5858113SRyan Lee 			    MAX98396_R2024_THERM_FOLDBACK_SET,
1103b5858113SRyan Lee 			    MAX98396_THERM_FB_HOLD_SHIFT,
1104b5858113SRyan Lee 			    max98396_foldback_holdtime_text);
1105b5858113SRyan Lee 
max98396_adc_value_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)1106b5858113SRyan Lee static int max98396_adc_value_get(struct snd_kcontrol *kcontrol,
1107b5858113SRyan Lee 				  struct snd_ctl_elem_value *ucontrol)
1108b5858113SRyan Lee {
1109b5858113SRyan Lee 	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
1110b5858113SRyan Lee 	struct soc_mixer_control *mc =
1111b5858113SRyan Lee 		(struct soc_mixer_control *)kcontrol->private_value;
1112b5858113SRyan Lee 	struct max98396_priv *max98396 = snd_soc_component_get_drvdata(component);
1113b5858113SRyan Lee 	int ret;
1114b5858113SRyan Lee 	u8 val[2];
1115b5858113SRyan Lee 	int reg = mc->reg;
1116b5858113SRyan Lee 
1117b5858113SRyan Lee 	/* ADC value is not available if the device is powered down */
1118b5858113SRyan Lee 	if (snd_soc_component_get_bias_level(component) == SND_SOC_BIAS_OFF)
1119b5858113SRyan Lee 		goto exit;
1120b5858113SRyan Lee 
1121b5858113SRyan Lee 	if (max98396->device_id == CODEC_TYPE_MAX98397) {
1122b5858113SRyan Lee 		switch (mc->reg) {
1123b5858113SRyan Lee 		case MAX98396_R20B6_ADC_PVDD_READBACK_MSB:
1124b5858113SRyan Lee 			reg = MAX98397_R20B7_ADC_PVDD_READBACK_MSB;
1125b5858113SRyan Lee 			break;
1126b5858113SRyan Lee 		case MAX98396_R20B8_ADC_VBAT_READBACK_MSB:
1127b5858113SRyan Lee 			reg = MAX98397_R20B9_ADC_VBAT_READBACK_MSB;
1128b5858113SRyan Lee 			break;
1129b5858113SRyan Lee 		case MAX98396_R20BA_ADC_TEMP_READBACK_MSB:
1130b5858113SRyan Lee 			reg = MAX98397_R20BB_ADC_TEMP_READBACK_MSB;
1131b5858113SRyan Lee 			break;
1132b5858113SRyan Lee 		default:
1133b5858113SRyan Lee 			goto exit;
1134b5858113SRyan Lee 		}
1135b5858113SRyan Lee 	}
1136b5858113SRyan Lee 
1137b5858113SRyan Lee 	ret = regmap_raw_read(max98396->regmap, reg, &val, 2);
1138b5858113SRyan Lee 	if (ret)
1139b5858113SRyan Lee 		goto exit;
1140b5858113SRyan Lee 
1141b5858113SRyan Lee 	/* ADC readback bits[8:0] rearrangement */
1142b5858113SRyan Lee 	ucontrol->value.integer.value[0] = (val[0] << 1) | (val[1] & 1);
1143b5858113SRyan Lee 	return 0;
1144b5858113SRyan Lee 
1145b5858113SRyan Lee exit:
1146b5858113SRyan Lee 	ucontrol->value.integer.value[0] = 0;
1147b5858113SRyan Lee 	return 0;
1148b5858113SRyan Lee }
1149b5858113SRyan Lee 
1150b5858113SRyan Lee static const struct snd_kcontrol_new max98396_snd_controls[] = {
1151b5858113SRyan Lee 	/* Volume */
1152b5858113SRyan Lee 	SOC_SINGLE_TLV("Digital Volume", MAX98396_R2090_AMP_VOL_CTRL,
1153b5858113SRyan Lee 		       0, 0x7F, 1, max98396_digital_tlv),
1154b5858113SRyan Lee 	SOC_SINGLE_TLV("Speaker Volume", MAX98396_R2091_AMP_PATH_GAIN,
1155b5858113SRyan Lee 		       0, 0x11, 0, max98396_spk_tlv),
1156b5858113SRyan Lee 	/* Volume Ramp Up/Down Enable*/
1157b5858113SRyan Lee 	SOC_SINGLE("Ramp Up Switch", MAX98396_R2092_AMP_DSP_CFG,
1158b5858113SRyan Lee 		   MAX98396_DSP_SPK_VOL_RMPUP_SHIFT, 1, 0),
1159b5858113SRyan Lee 	SOC_SINGLE("Ramp Down Switch", MAX98396_R2092_AMP_DSP_CFG,
1160b5858113SRyan Lee 		   MAX98396_DSP_SPK_VOL_RMPDN_SHIFT, 1, 0),
1161b5858113SRyan Lee 	/* Clock Monitor Enable */
1162b5858113SRyan Lee 	SOC_SINGLE("CLK Monitor Switch", MAX98396_R203F_ENABLE_CTRLS,
1163b5858113SRyan Lee 		   MAX98396_CTRL_CMON_EN_SHIFT, 1, 0),
1164b5858113SRyan Lee 	/* Dither Enable */
1165b5858113SRyan Lee 	SOC_SINGLE("Dither Switch", MAX98396_R2092_AMP_DSP_CFG,
1166b5858113SRyan Lee 		   MAX98396_DSP_SPK_DITH_EN_SHIFT, 1, 0),
1167b5858113SRyan Lee 	SOC_SINGLE("IV Dither Switch", MAX98396_R20E0_IV_SENSE_PATH_CFG,
1168b5858113SRyan Lee 		   MAX98396_IV_SENSE_DITH_EN_SHIFT, 1, 0),
1169b5858113SRyan Lee 	/* DC Blocker Enable */
1170b5858113SRyan Lee 	SOC_SINGLE("DC Blocker Switch", MAX98396_R2092_AMP_DSP_CFG,
1171b5858113SRyan Lee 		   MAX98396_DSP_SPK_DCBLK_EN_SHIFT, 1, 0),
1172b5858113SRyan Lee 	SOC_SINGLE("IV DC Blocker Switch", MAX98396_R20E0_IV_SENSE_PATH_CFG,
1173b5858113SRyan Lee 		   MAX98396_IV_SENSE_DCBLK_EN_SHIFT, 3, 0),
1174b5858113SRyan Lee 	/* Speaker Safe Mode Enable */
1175b5858113SRyan Lee 	SOC_SINGLE("Safe Mode Switch", MAX98396_R2092_AMP_DSP_CFG,
1176b5858113SRyan Lee 		   MAX98396_DSP_SPK_SAFE_EN_SHIFT, 1, 0),
1177b5858113SRyan Lee 	/* Wideband Filter Enable */
1178b5858113SRyan Lee 	SOC_SINGLE("WB Filter Switch", MAX98396_R2092_AMP_DSP_CFG,
1179b5858113SRyan Lee 		   MAX98396_DSP_SPK_WB_FLT_EN_SHIFT, 1, 0),
1180b5858113SRyan Lee 	SOC_SINGLE("IV WB Filter Switch", MAX98396_R20E0_IV_SENSE_PATH_CFG,
1181b5858113SRyan Lee 		   MAX98396_IV_SENSE_WB_FLT_EN_SHIFT, 1, 0),
1182b5858113SRyan Lee 	/* Dynamic Headroom Tracking */
1183b5858113SRyan Lee 	SOC_SINGLE("DHT Switch", MAX98396_R20DF_DHT_EN, 0, 1, 0),
1184b5858113SRyan Lee 	/* Brownout Protection Engine */
1185b5858113SRyan Lee 	SOC_SINGLE("BPE Switch", MAX98396_R210D_BPE_EN, 0, 1, 0),
1186b5858113SRyan Lee 	SOC_SINGLE("BPE Limiter Switch", MAX98396_R210D_BPE_EN, 1, 1, 0),
1187b5858113SRyan Lee 	/* Bypass Path Enable */
1188b5858113SRyan Lee 	SOC_SINGLE("Bypass Path Switch",
1189b5858113SRyan Lee 		   MAX98396_R205E_PCM_RX_EN, 1, 1, 0),
1190b5858113SRyan Lee 	/* Speaker Operation Mode */
1191b5858113SRyan Lee 	SOC_ENUM("OP Mode", max98396_op_mod_enum),
1192b5858113SRyan Lee 	/* Auto Restart functions */
1193b5858113SRyan Lee 	SOC_SINGLE("CMON Auto Restart Switch", MAX98396_R2038_CLK_MON_CTRL,
1194b5858113SRyan Lee 		   MAX98396_CLK_MON_AUTO_RESTART_SHIFT, 1, 0),
1195b5858113SRyan Lee 	SOC_SINGLE("PVDD Auto Restart Switch", MAX98396_R210E_AUTO_RESTART,
1196b5858113SRyan Lee 		   MAX98396_PVDD_UVLO_RESTART_SHFT, 1, 0),
1197b5858113SRyan Lee 	SOC_SINGLE("VBAT Auto Restart Switch", MAX98396_R210E_AUTO_RESTART,
1198b5858113SRyan Lee 		   MAX98396_VBAT_UVLO_RESTART_SHFT, 1, 0),
1199b5858113SRyan Lee 	SOC_SINGLE("THERM Auto Restart Switch", MAX98396_R210E_AUTO_RESTART,
1200b5858113SRyan Lee 		   MAX98396_THEM_SHDN_RESTART_SHFT, 1, 0),
1201b5858113SRyan Lee 	SOC_SINGLE("OVC Auto Restart Switch", MAX98396_R210E_AUTO_RESTART,
1202b5858113SRyan Lee 		   MAX98396_OVC_RESTART_SHFT, 1, 0),
1203b5858113SRyan Lee 	/* Thermal Threshold */
1204b5858113SRyan Lee 	SOC_ENUM("THERM Thresh1", max98396_thermal_warn_thresh1_enum),
1205b5858113SRyan Lee 	SOC_ENUM("THERM Thresh2", max98396_thermal_warn_thresh2_enum),
1206b5858113SRyan Lee 	SOC_ENUM("THERM SHDN Thresh", max98396_thermal_shdn_thresh_enum),
1207b5858113SRyan Lee 	SOC_ENUM("THERM Hysteresis", max98396_thermal_hysteresis_enum),
1208b5858113SRyan Lee 	SOC_SINGLE("THERM Foldback Switch",
1209b5858113SRyan Lee 		   MAX98396_R2027_THERM_FOLDBACK_EN, 0, 1, 0),
1210b5858113SRyan Lee 	SOC_ENUM("THERM Slope1", max98396_thermal_fb_slope1_enum),
1211b5858113SRyan Lee 	SOC_ENUM("THERM Slope2", max98396_thermal_fb_slope2_enum),
1212b5858113SRyan Lee 	SOC_ENUM("THERM Release", max98396_thermal_fb_reltime_enum),
1213b5858113SRyan Lee 	SOC_ENUM("THERM Hold", max98396_thermal_fb_holdtime_enum),
1214b5858113SRyan Lee 	/* ADC */
1215b5858113SRyan Lee 	SOC_SINGLE_EXT("ADC PVDD", MAX98396_R20B6_ADC_PVDD_READBACK_MSB, 0, 0x1FF, 0,
1216b5858113SRyan Lee 		       max98396_adc_value_get, NULL),
1217b5858113SRyan Lee 	SOC_SINGLE_EXT("ADC VBAT", MAX98396_R20B8_ADC_VBAT_READBACK_MSB, 0, 0x1FF, 0,
1218b5858113SRyan Lee 		       max98396_adc_value_get, NULL),
1219b5858113SRyan Lee 	SOC_SINGLE_EXT("ADC TEMP", MAX98396_R20BA_ADC_TEMP_READBACK_MSB, 0, 0x1FF, 0,
1220b5858113SRyan Lee 		       max98396_adc_value_get, NULL),
1221b5858113SRyan Lee };
1222b5858113SRyan Lee 
1223b5858113SRyan Lee static const struct snd_kcontrol_new max98397_snd_controls[] = {
1224b5858113SRyan Lee 	/* Volume */
1225b5858113SRyan Lee 	SOC_SINGLE_TLV("Digital Volume", MAX98396_R2090_AMP_VOL_CTRL,
1226b5858113SRyan Lee 		       0, 0xFF, 1, max98397_digital_tlv),
1227b5858113SRyan Lee 	SOC_SINGLE_TLV("Speaker Volume", MAX98396_R2091_AMP_PATH_GAIN,
1228b5858113SRyan Lee 		       0, 0x15, 0, max98397_spk_tlv),
1229b5858113SRyan Lee 	/* Volume Ramp Up/Down Enable*/
1230b5858113SRyan Lee 	SOC_SINGLE("Ramp Up Switch", MAX98396_R2092_AMP_DSP_CFG,
1231b5858113SRyan Lee 		   MAX98396_DSP_SPK_VOL_RMPUP_SHIFT, 1, 0),
1232b5858113SRyan Lee 	SOC_SINGLE("Ramp Down Switch", MAX98396_R2092_AMP_DSP_CFG,
1233b5858113SRyan Lee 		   MAX98396_DSP_SPK_VOL_RMPDN_SHIFT, 1, 0),
1234b5858113SRyan Lee 	/* Clock Monitor Enable */
1235b5858113SRyan Lee 	SOC_SINGLE("CLK Monitor Switch", MAX98396_R203F_ENABLE_CTRLS,
1236b5858113SRyan Lee 		   MAX98396_CTRL_CMON_EN_SHIFT, 1, 0),
1237b5858113SRyan Lee 	/* Dither Enable */
1238b5858113SRyan Lee 	SOC_SINGLE("Dither Switch", MAX98396_R2092_AMP_DSP_CFG,
1239b5858113SRyan Lee 		   MAX98396_DSP_SPK_DITH_EN_SHIFT, 1, 0),
1240b5858113SRyan Lee 	SOC_SINGLE("IV Dither Switch", MAX98396_R20E0_IV_SENSE_PATH_CFG,
1241b5858113SRyan Lee 		   MAX98396_IV_SENSE_DITH_EN_SHIFT, 1, 0),
1242b5858113SRyan Lee 	/* DC Blocker Enable */
1243b5858113SRyan Lee 	SOC_SINGLE("DC Blocker Switch", MAX98396_R2092_AMP_DSP_CFG,
1244b5858113SRyan Lee 		   MAX98396_DSP_SPK_DCBLK_EN_SHIFT, 1, 0),
1245b5858113SRyan Lee 	SOC_SINGLE("IV DC Blocker Switch", MAX98396_R20E0_IV_SENSE_PATH_CFG,
1246b5858113SRyan Lee 		   MAX98396_IV_SENSE_DCBLK_EN_SHIFT, 3, 0),
1247b5858113SRyan Lee 	/* Speaker Safe Mode Enable */
1248b5858113SRyan Lee 	SOC_SINGLE("Safe Mode Switch", MAX98396_R2092_AMP_DSP_CFG,
1249b5858113SRyan Lee 		   MAX98396_DSP_SPK_SAFE_EN_SHIFT, 1, 0),
1250b5858113SRyan Lee 	/* Wideband Filter Enable */
1251b5858113SRyan Lee 	SOC_SINGLE("WB Filter Switch", MAX98396_R2092_AMP_DSP_CFG,
1252b5858113SRyan Lee 		   MAX98396_DSP_SPK_WB_FLT_EN_SHIFT, 1, 0),
1253b5858113SRyan Lee 	SOC_SINGLE("IV WB Filter Switch", MAX98396_R20E0_IV_SENSE_PATH_CFG,
1254b5858113SRyan Lee 		   MAX98396_IV_SENSE_WB_FLT_EN_SHIFT, 1, 0),
1255b5858113SRyan Lee 	/* Dynamic Headroom Tracking */
1256b5858113SRyan Lee 	SOC_SINGLE("DHT Switch", MAX98396_R20DF_DHT_EN, 0, 1, 0),
1257b5858113SRyan Lee 	/* Brownout Protection Engine */
1258b5858113SRyan Lee 	SOC_SINGLE("BPE Switch", MAX98396_R210D_BPE_EN, 0, 1, 0),
1259b5858113SRyan Lee 	SOC_SINGLE("BPE Limiter Switch", MAX98396_R210D_BPE_EN, 1, 1, 0),
1260b5858113SRyan Lee 	/* Bypass Path Enable */
1261b5858113SRyan Lee 	SOC_SINGLE("Bypass Path Switch",
1262b5858113SRyan Lee 		   MAX98396_R205E_PCM_RX_EN, 1, 1, 0),
1263b5858113SRyan Lee 	/* Speaker Operation Mode */
1264b5858113SRyan Lee 	SOC_ENUM("OP Mode", max98396_op_mod_enum),
1265b5858113SRyan Lee 	/* Auto Restart functions */
1266b5858113SRyan Lee 	SOC_SINGLE("CMON Auto Restart Switch", MAX98396_R2038_CLK_MON_CTRL,
1267b5858113SRyan Lee 		   MAX98396_CLK_MON_AUTO_RESTART_SHIFT, 1, 0),
1268b5858113SRyan Lee 	SOC_SINGLE("PVDD Auto Restart Switch", MAX98396_R210E_AUTO_RESTART,
1269b5858113SRyan Lee 		   MAX98396_PVDD_UVLO_RESTART_SHFT, 1, 0),
1270b5858113SRyan Lee 	SOC_SINGLE("VBAT Auto Restart Switch", MAX98396_R210E_AUTO_RESTART,
1271b5858113SRyan Lee 		   MAX98396_VBAT_UVLO_RESTART_SHFT, 1, 0),
1272b5858113SRyan Lee 	SOC_SINGLE("THERM Auto Restart Switch", MAX98396_R210E_AUTO_RESTART,
1273b5858113SRyan Lee 		   MAX98396_THEM_SHDN_RESTART_SHFT, 1, 0),
1274b5858113SRyan Lee 	SOC_SINGLE("OVC Auto Restart Switch", MAX98396_R210E_AUTO_RESTART,
1275b5858113SRyan Lee 		   MAX98396_OVC_RESTART_SHFT, 1, 0),
1276b5858113SRyan Lee 	/* Thermal Threshold */
1277b5858113SRyan Lee 	SOC_ENUM("THERM Thresh1", max98396_thermal_warn_thresh1_enum),
1278b5858113SRyan Lee 	SOC_ENUM("THERM Thresh2", max98396_thermal_warn_thresh2_enum),
1279b5858113SRyan Lee 	SOC_ENUM("THERM SHDN Thresh", max98396_thermal_shdn_thresh_enum),
1280b5858113SRyan Lee 	SOC_ENUM("THERM Hysteresis", max98396_thermal_hysteresis_enum),
1281b5858113SRyan Lee 	SOC_SINGLE("THERM Foldback Switch",
1282b5858113SRyan Lee 		   MAX98396_R2027_THERM_FOLDBACK_EN, 0, 1, 0),
1283b5858113SRyan Lee 	SOC_ENUM("THERM Slope1", max98396_thermal_fb_slope1_enum),
1284b5858113SRyan Lee 	SOC_ENUM("THERM Slope2", max98396_thermal_fb_slope2_enum),
1285b5858113SRyan Lee 	SOC_ENUM("THERM Release", max98396_thermal_fb_reltime_enum),
1286b5858113SRyan Lee 	SOC_ENUM("THERM Hold", max98396_thermal_fb_holdtime_enum),
1287b5858113SRyan Lee 	/* ADC */
1288b5858113SRyan Lee 	SOC_SINGLE_EXT("ADC PVDD", MAX98396_R20B6_ADC_PVDD_READBACK_MSB, 0, 0x1FF, 0,
1289b5858113SRyan Lee 		       max98396_adc_value_get, NULL),
1290b5858113SRyan Lee 	SOC_SINGLE_EXT("ADC VBAT", MAX98396_R20B8_ADC_VBAT_READBACK_MSB, 0, 0x1FF, 0,
1291b5858113SRyan Lee 		       max98396_adc_value_get, NULL),
1292b5858113SRyan Lee 	SOC_SINGLE_EXT("ADC TEMP", MAX98396_R20BA_ADC_TEMP_READBACK_MSB, 0, 0x1FF, 0,
1293b5858113SRyan Lee 		       max98396_adc_value_get, NULL),
1294b5858113SRyan Lee };
1295b5858113SRyan Lee 
1296b5858113SRyan Lee static const struct snd_soc_dapm_route max98396_audio_map[] = {
1297b5858113SRyan Lee 	/* Plabyack */
1298b5858113SRyan Lee 	{"DAI Sel Mux", "Left", "Amp Enable"},
1299b5858113SRyan Lee 	{"DAI Sel Mux", "Right", "Amp Enable"},
1300b5858113SRyan Lee 	{"DAI Sel Mux", "LeftRight", "Amp Enable"},
1301b5858113SRyan Lee 	{"BE_OUT", NULL, "DAI Sel Mux"},
1302b5858113SRyan Lee 	/* Capture */
1303b5858113SRyan Lee 	{ "VI Sense", "Switch", "VMON" },
1304b5858113SRyan Lee 	{ "VI Sense", "Switch", "IMON" },
1305b5858113SRyan Lee 	{ "Voltage Sense", NULL, "VI Sense" },
1306b5858113SRyan Lee 	{ "Current Sense", NULL, "VI Sense" },
1307b5858113SRyan Lee };
1308b5858113SRyan Lee 
1309b5858113SRyan Lee static struct snd_soc_dai_driver max98396_dai[] = {
1310b5858113SRyan Lee 	{
1311b5858113SRyan Lee 		.name = "max98396-aif1",
1312b5858113SRyan Lee 		.playback = {
1313b5858113SRyan Lee 			.stream_name = "HiFi Playback",
1314b5858113SRyan Lee 			.channels_min = 1,
1315b5858113SRyan Lee 			.channels_max = 2,
1316b5858113SRyan Lee 			.rates = MAX98396_RATES,
1317b5858113SRyan Lee 			.formats = MAX98396_FORMATS,
1318b5858113SRyan Lee 		},
1319b5858113SRyan Lee 		.capture = {
1320b5858113SRyan Lee 			.stream_name = "HiFi Capture",
1321b5858113SRyan Lee 			.channels_min = 1,
1322b5858113SRyan Lee 			.channels_max = 2,
1323b5858113SRyan Lee 			.rates = MAX98396_RATES,
1324b5858113SRyan Lee 			.formats = MAX98396_FORMATS,
1325b5858113SRyan Lee 		},
1326b5858113SRyan Lee 		.ops = &max98396_dai_ops,
1327b5858113SRyan Lee 	}
1328b5858113SRyan Lee };
1329b5858113SRyan Lee 
1330b5858113SRyan Lee static struct snd_soc_dai_driver max98397_dai[] = {
1331b5858113SRyan Lee 	{
1332b5858113SRyan Lee 		.name = "max98397-aif1",
1333b5858113SRyan Lee 		.playback = {
1334b5858113SRyan Lee 			.stream_name = "HiFi Playback",
1335b5858113SRyan Lee 			.channels_min = 1,
1336b5858113SRyan Lee 			.channels_max = 2,
1337b5858113SRyan Lee 			.rates = MAX98396_RATES,
1338b5858113SRyan Lee 			.formats = MAX98396_FORMATS,
1339b5858113SRyan Lee 		},
1340b5858113SRyan Lee 		.capture = {
1341b5858113SRyan Lee 			.stream_name = "HiFi Capture",
1342b5858113SRyan Lee 			.channels_min = 1,
1343b5858113SRyan Lee 			.channels_max = 2,
1344b5858113SRyan Lee 			.rates = MAX98396_RATES,
1345b5858113SRyan Lee 			.formats = MAX98396_FORMATS,
1346b5858113SRyan Lee 		},
1347b5858113SRyan Lee 		.ops = &max98396_dai_ops,
1348b5858113SRyan Lee 	}
1349b5858113SRyan Lee };
1350b5858113SRyan Lee 
max98396_reset(struct max98396_priv * max98396,struct device * dev)1351b5858113SRyan Lee static void max98396_reset(struct max98396_priv *max98396, struct device *dev)
1352b5858113SRyan Lee {
1353b5858113SRyan Lee 	int ret, reg, count;
1354b5858113SRyan Lee 
1355b5858113SRyan Lee 	/* Software Reset */
1356b5858113SRyan Lee 	ret = regmap_write(max98396->regmap,
1357b5858113SRyan Lee 			   MAX98396_R2000_SW_RESET, 1);
1358b5858113SRyan Lee 	if (ret)
1359b5858113SRyan Lee 		dev_err(dev, "Reset command failed. (ret:%d)\n", ret);
1360b5858113SRyan Lee 
1361b5858113SRyan Lee 	count = 0;
1362b5858113SRyan Lee 	while (count < 3) {
1363b5858113SRyan Lee 		usleep_range(5000, 6000);
1364b5858113SRyan Lee 		/* Software Reset Verification */
1365b5858113SRyan Lee 		ret = regmap_read(max98396->regmap,
1366b5858113SRyan Lee 				  GET_REG_ADDR_REV_ID(max98396->device_id), &reg);
1367b5858113SRyan Lee 		if (!ret) {
1368b5858113SRyan Lee 			dev_info(dev, "Reset completed (retry:%d)\n", count);
1369b5858113SRyan Lee 			return;
1370b5858113SRyan Lee 		}
1371b5858113SRyan Lee 		count++;
1372b5858113SRyan Lee 	}
1373b5858113SRyan Lee 	dev_err(dev, "Reset failed. (ret:%d)\n", ret);
1374b5858113SRyan Lee }
1375b5858113SRyan Lee 
max98396_probe(struct snd_soc_component * component)1376b5858113SRyan Lee static int max98396_probe(struct snd_soc_component *component)
1377b5858113SRyan Lee {
1378b5858113SRyan Lee 	struct max98396_priv *max98396 =
1379b5858113SRyan Lee 		snd_soc_component_get_drvdata(component);
1380b5858113SRyan Lee 
1381b5858113SRyan Lee 	/* Software Reset */
1382b5858113SRyan Lee 	max98396_reset(max98396, component->dev);
1383b5858113SRyan Lee 
1384b5858113SRyan Lee 	/* L/R mix configuration */
1385b5858113SRyan Lee 	if (max98396->device_id == CODEC_TYPE_MAX98396) {
1386b5858113SRyan Lee 		regmap_write(max98396->regmap,
1387b5858113SRyan Lee 			     MAX98396_R2055_PCM_RX_SRC1, 0x02);
1388b5858113SRyan Lee 		regmap_write(max98396->regmap,
1389b5858113SRyan Lee 			     MAX98396_R2056_PCM_RX_SRC2, 0x10);
1390b5858113SRyan Lee 	} else {
1391b5858113SRyan Lee 		regmap_write(max98396->regmap,
1392b5858113SRyan Lee 			     MAX98397_R2056_PCM_RX_SRC1, 0x02);
1393b5858113SRyan Lee 		regmap_write(max98396->regmap,
1394b5858113SRyan Lee 			     MAX98397_R2057_PCM_RX_SRC2, 0x10);
1395b5858113SRyan Lee 	}
1396703ee055SDaniel Mack 	/* Supply control */
1397703ee055SDaniel Mack 	regmap_update_bits(max98396->regmap,
1398703ee055SDaniel Mack 			   MAX98396_R20A0_AMP_SUPPLY_CTL,
1399703ee055SDaniel Mack 			   MAX98396_AMP_SUPPLY_NOVBAT,
1400703ee055SDaniel Mack 			   (max98396->vbat == NULL) ?
1401703ee055SDaniel Mack 				MAX98396_AMP_SUPPLY_NOVBAT : 0);
1402b5858113SRyan Lee 	/* Enable DC blocker */
1403b5858113SRyan Lee 	regmap_update_bits(max98396->regmap,
1404b5858113SRyan Lee 			   MAX98396_R2092_AMP_DSP_CFG, 1, 1);
1405b5858113SRyan Lee 	/* Enable IV Monitor DC blocker */
1406b5858113SRyan Lee 	regmap_update_bits(max98396->regmap,
1407b5858113SRyan Lee 			   MAX98396_R20E0_IV_SENSE_PATH_CFG,
1408b5858113SRyan Lee 			   MAX98396_IV_SENSE_DCBLK_EN_MASK,
1409b5858113SRyan Lee 			   MAX98396_IV_SENSE_DCBLK_EN_MASK);
1410b5858113SRyan Lee 	/* Configure default data output sources */
1411b5858113SRyan Lee 	regmap_write(max98396->regmap,
1412b5858113SRyan Lee 		     MAX98396_R205D_PCM_TX_SRC_EN, 3);
1413b5858113SRyan Lee 	/* Enable Wideband Filter */
1414b5858113SRyan Lee 	regmap_update_bits(max98396->regmap,
1415b5858113SRyan Lee 			   MAX98396_R2092_AMP_DSP_CFG, 0x40, 0x40);
1416b5858113SRyan Lee 	/* Enable IV Wideband Filter */
1417b5858113SRyan Lee 	regmap_update_bits(max98396->regmap,
1418b5858113SRyan Lee 			   MAX98396_R20E0_IV_SENSE_PATH_CFG, 8, 8);
1419b5858113SRyan Lee 
1420b5858113SRyan Lee 	/* Enable Bypass Source */
1421b5858113SRyan Lee 	regmap_write(max98396->regmap,
1422b5858113SRyan Lee 		     MAX98396_R2058_PCM_BYPASS_SRC,
1423b5858113SRyan Lee 		     max98396->bypass_slot);
1424b5858113SRyan Lee 	/* Voltage, current slot configuration */
1425b5858113SRyan Lee 	regmap_write(max98396->regmap,
1426b5858113SRyan Lee 		     MAX98396_R2044_PCM_TX_CTRL_1,
1427b5858113SRyan Lee 		     max98396->v_slot);
1428b5858113SRyan Lee 	regmap_write(max98396->regmap,
1429b5858113SRyan Lee 		     MAX98396_R2045_PCM_TX_CTRL_2,
1430b5858113SRyan Lee 		     max98396->i_slot);
1431f42924b4SDaniel Mack 	regmap_write(max98396->regmap,
1432f42924b4SDaniel Mack 		     MAX98396_R204A_PCM_TX_CTRL_7,
1433f42924b4SDaniel Mack 		     max98396->spkfb_slot);
1434b5858113SRyan Lee 
1435b5858113SRyan Lee 	if (max98396->v_slot < 8)
1436b5858113SRyan Lee 		if (max98396->device_id == CODEC_TYPE_MAX98396)
1437b5858113SRyan Lee 			regmap_update_bits(max98396->regmap,
1438b5858113SRyan Lee 					   MAX98396_R2053_PCM_TX_HIZ_CTRL_8,
1439b5858113SRyan Lee 					   1 << max98396->v_slot, 0);
1440b5858113SRyan Lee 		else
1441b5858113SRyan Lee 			regmap_update_bits(max98396->regmap,
1442b5858113SRyan Lee 					   MAX98397_R2054_PCM_TX_HIZ_CTRL_8,
1443b5858113SRyan Lee 					   1 << max98396->v_slot, 0);
1444b5858113SRyan Lee 	else
1445b5858113SRyan Lee 		if (max98396->device_id == CODEC_TYPE_MAX98396)
1446b5858113SRyan Lee 			regmap_update_bits(max98396->regmap,
1447b5858113SRyan Lee 					   MAX98396_R2052_PCM_TX_HIZ_CTRL_7,
1448b5858113SRyan Lee 					   1 << (max98396->v_slot - 8), 0);
1449b5858113SRyan Lee 		else
1450b5858113SRyan Lee 			regmap_update_bits(max98396->regmap,
1451b5858113SRyan Lee 					   MAX98397_R2053_PCM_TX_HIZ_CTRL_7,
1452b5858113SRyan Lee 					   1 << (max98396->v_slot - 8), 0);
1453b5858113SRyan Lee 
1454b5858113SRyan Lee 	if (max98396->i_slot < 8)
1455b5858113SRyan Lee 		if (max98396->device_id == CODEC_TYPE_MAX98396)
1456b5858113SRyan Lee 			regmap_update_bits(max98396->regmap,
1457b5858113SRyan Lee 					   MAX98396_R2053_PCM_TX_HIZ_CTRL_8,
1458b5858113SRyan Lee 					   1 << max98396->i_slot, 0);
1459b5858113SRyan Lee 		else
1460b5858113SRyan Lee 			regmap_update_bits(max98396->regmap,
1461b5858113SRyan Lee 					   MAX98397_R2054_PCM_TX_HIZ_CTRL_8,
1462b5858113SRyan Lee 					   1 << max98396->i_slot, 0);
1463b5858113SRyan Lee 	else
1464b5858113SRyan Lee 		if (max98396->device_id == CODEC_TYPE_MAX98396)
1465b5858113SRyan Lee 			regmap_update_bits(max98396->regmap,
1466b5858113SRyan Lee 					   MAX98396_R2052_PCM_TX_HIZ_CTRL_7,
1467b5858113SRyan Lee 					   1 << (max98396->i_slot - 8), 0);
1468b5858113SRyan Lee 		else
1469b5858113SRyan Lee 			regmap_update_bits(max98396->regmap,
1470b5858113SRyan Lee 					   MAX98397_R2053_PCM_TX_HIZ_CTRL_7,
1471b5858113SRyan Lee 					   1 << (max98396->i_slot - 8), 0);
1472b5858113SRyan Lee 
1473b5858113SRyan Lee 	/* Set interleave mode */
1474b5858113SRyan Lee 	if (max98396->interleave_mode)
1475b5858113SRyan Lee 		regmap_update_bits(max98396->regmap,
1476b5858113SRyan Lee 				   MAX98396_R2041_PCM_MODE_CFG,
1477b5858113SRyan Lee 				   MAX98396_PCM_TX_CH_INTERLEAVE_MASK,
1478b5858113SRyan Lee 				   MAX98396_PCM_TX_CH_INTERLEAVE_MASK);
1479b5858113SRyan Lee 
1480b5858113SRyan Lee 	regmap_update_bits(max98396->regmap,
1481b5858113SRyan Lee 			   MAX98396_R2038_CLK_MON_CTRL,
1482b5858113SRyan Lee 			   MAX98396_CLK_MON_AUTO_RESTART_MASK,
1483b5858113SRyan Lee 			   MAX98396_CLK_MON_AUTO_RESTART_MASK);
1484b5858113SRyan Lee 
148533b7504aSDaniel Mack 	regmap_update_bits(max98396->regmap,
148633b7504aSDaniel Mack 			   MAX98396_R203F_ENABLE_CTRLS,
148733b7504aSDaniel Mack 			   MAX98396_CTRL_DMON_STUCK_EN_MASK,
148833b7504aSDaniel Mack 			   max98396->dmon_stuck_enable ?
148933b7504aSDaniel Mack 				MAX98396_CTRL_DMON_STUCK_EN_MASK : 0);
149033b7504aSDaniel Mack 
149133b7504aSDaniel Mack 	regmap_update_bits(max98396->regmap,
149233b7504aSDaniel Mack 			   MAX98396_R203F_ENABLE_CTRLS,
149333b7504aSDaniel Mack 			   MAX98396_CTRL_DMON_MAG_EN_MASK,
149433b7504aSDaniel Mack 			   max98396->dmon_mag_enable ?
149533b7504aSDaniel Mack 				MAX98396_CTRL_DMON_MAG_EN_MASK : 0);
149633b7504aSDaniel Mack 
149733b7504aSDaniel Mack 	switch (max98396->dmon_duration) {
149833b7504aSDaniel Mack 	case 64:
149933b7504aSDaniel Mack 		regmap_update_bits(max98396->regmap,
150033b7504aSDaniel Mack 				   MAX98396_R2039_DATA_MON_CTRL,
150133b7504aSDaniel Mack 				   MAX98396_DMON_DURATION_MASK, 0);
150233b7504aSDaniel Mack 		break;
150333b7504aSDaniel Mack 	case 256:
150433b7504aSDaniel Mack 		regmap_update_bits(max98396->regmap,
150533b7504aSDaniel Mack 				   MAX98396_R2039_DATA_MON_CTRL,
150633b7504aSDaniel Mack 				   MAX98396_DMON_DURATION_MASK, 1);
150733b7504aSDaniel Mack 		break;
150833b7504aSDaniel Mack 	case 1024:
150933b7504aSDaniel Mack 		regmap_update_bits(max98396->regmap,
151033b7504aSDaniel Mack 				   MAX98396_R2039_DATA_MON_CTRL,
151133b7504aSDaniel Mack 				   MAX98396_DMON_DURATION_MASK, 2);
151233b7504aSDaniel Mack 		break;
151333b7504aSDaniel Mack 	case 4096:
151433b7504aSDaniel Mack 		regmap_update_bits(max98396->regmap,
151533b7504aSDaniel Mack 				   MAX98396_R2039_DATA_MON_CTRL,
151633b7504aSDaniel Mack 				   MAX98396_DMON_DURATION_MASK, 3);
151733b7504aSDaniel Mack 		break;
151833b7504aSDaniel Mack 	default:
151933b7504aSDaniel Mack 		dev_err(component->dev, "Invalid DMON duration %d\n",
152033b7504aSDaniel Mack 			max98396->dmon_duration);
152133b7504aSDaniel Mack 	}
152233b7504aSDaniel Mack 
152333b7504aSDaniel Mack 	switch (max98396->dmon_stuck_threshold) {
152433b7504aSDaniel Mack 	case 15:
152533b7504aSDaniel Mack 		regmap_update_bits(max98396->regmap,
152633b7504aSDaniel Mack 				   MAX98396_R2039_DATA_MON_CTRL,
152733b7504aSDaniel Mack 				   MAX98396_DMON_STUCK_THRESH_MASK,
152833b7504aSDaniel Mack 				   0 << MAX98396_DMON_STUCK_THRESH_SHIFT);
152933b7504aSDaniel Mack 		break;
153033b7504aSDaniel Mack 	case 13:
153133b7504aSDaniel Mack 		regmap_update_bits(max98396->regmap,
153233b7504aSDaniel Mack 				   MAX98396_R2039_DATA_MON_CTRL,
153333b7504aSDaniel Mack 				   MAX98396_DMON_STUCK_THRESH_MASK,
153433b7504aSDaniel Mack 				   1 << MAX98396_DMON_STUCK_THRESH_SHIFT);
153533b7504aSDaniel Mack 		break;
153633b7504aSDaniel Mack 	case 22:
153733b7504aSDaniel Mack 		regmap_update_bits(max98396->regmap,
153833b7504aSDaniel Mack 				   MAX98396_R2039_DATA_MON_CTRL,
153933b7504aSDaniel Mack 				   MAX98396_DMON_STUCK_THRESH_MASK,
154033b7504aSDaniel Mack 				   2 << MAX98396_DMON_STUCK_THRESH_SHIFT);
154133b7504aSDaniel Mack 		break;
154233b7504aSDaniel Mack 	case 9:
154333b7504aSDaniel Mack 		regmap_update_bits(max98396->regmap,
154433b7504aSDaniel Mack 				   MAX98396_R2039_DATA_MON_CTRL,
154533b7504aSDaniel Mack 				   MAX98396_DMON_STUCK_THRESH_MASK,
154633b7504aSDaniel Mack 				   3 << MAX98396_DMON_STUCK_THRESH_SHIFT);
154733b7504aSDaniel Mack 		break;
154833b7504aSDaniel Mack 	default:
154933b7504aSDaniel Mack 		dev_err(component->dev, "Invalid DMON stuck threshold %d\n",
155033b7504aSDaniel Mack 			max98396->dmon_stuck_threshold);
155133b7504aSDaniel Mack 	}
155233b7504aSDaniel Mack 
155333b7504aSDaniel Mack 	switch (max98396->dmon_mag_threshold) {
155433b7504aSDaniel Mack 	case 2 ... 5:
155533b7504aSDaniel Mack 		regmap_update_bits(max98396->regmap,
155633b7504aSDaniel Mack 				   MAX98396_R2039_DATA_MON_CTRL,
155733b7504aSDaniel Mack 				   MAX98396_DMON_STUCK_THRESH_MASK,
155833b7504aSDaniel Mack 				   (5 - max98396->dmon_mag_threshold)
155933b7504aSDaniel Mack 					<< MAX98396_DMON_MAG_THRESH_SHIFT);
156033b7504aSDaniel Mack 		break;
156133b7504aSDaniel Mack 	default:
156233b7504aSDaniel Mack 		dev_err(component->dev, "Invalid DMON magnitude threshold %d\n",
156333b7504aSDaniel Mack 			max98396->dmon_mag_threshold);
156433b7504aSDaniel Mack 	}
156533b7504aSDaniel Mack 
1566b5858113SRyan Lee 	/* Speaker Amplifier PCM RX Enable by default */
1567b5858113SRyan Lee 	regmap_update_bits(max98396->regmap,
1568b5858113SRyan Lee 			   MAX98396_R205E_PCM_RX_EN,
1569b5858113SRyan Lee 			   MAX98396_PCM_RX_EN_MASK, 1);
1570b5858113SRyan Lee 
1571b5858113SRyan Lee 	return 0;
1572b5858113SRyan Lee }
1573b5858113SRyan Lee 
1574b5858113SRyan Lee #ifdef CONFIG_PM_SLEEP
max98396_suspend(struct device * dev)1575b5858113SRyan Lee static int max98396_suspend(struct device *dev)
1576b5858113SRyan Lee {
1577b5858113SRyan Lee 	struct max98396_priv *max98396 = dev_get_drvdata(dev);
1578b5858113SRyan Lee 
1579b5858113SRyan Lee 	regcache_cache_only(max98396->regmap, true);
1580b5858113SRyan Lee 	regcache_mark_dirty(max98396->regmap);
1581703ee055SDaniel Mack 	regulator_bulk_disable(MAX98396_NUM_CORE_SUPPLIES,
1582703ee055SDaniel Mack 			       max98396->core_supplies);
1583703ee055SDaniel Mack 	if (max98396->pvdd)
1584703ee055SDaniel Mack 		regulator_disable(max98396->pvdd);
1585703ee055SDaniel Mack 
1586703ee055SDaniel Mack 	if (max98396->vbat)
1587703ee055SDaniel Mack 		regulator_disable(max98396->vbat);
1588703ee055SDaniel Mack 
1589b5858113SRyan Lee 	return 0;
1590b5858113SRyan Lee }
1591b5858113SRyan Lee 
max98396_resume(struct device * dev)1592b5858113SRyan Lee static int max98396_resume(struct device *dev)
1593b5858113SRyan Lee {
1594b5858113SRyan Lee 	struct max98396_priv *max98396 = dev_get_drvdata(dev);
1595703ee055SDaniel Mack 	int ret;
1596703ee055SDaniel Mack 
1597703ee055SDaniel Mack 	ret = regulator_bulk_enable(MAX98396_NUM_CORE_SUPPLIES,
1598703ee055SDaniel Mack 				    max98396->core_supplies);
1599703ee055SDaniel Mack 	if (ret < 0)
1600703ee055SDaniel Mack 		return ret;
1601703ee055SDaniel Mack 
1602703ee055SDaniel Mack 	if (max98396->pvdd) {
1603703ee055SDaniel Mack 		ret = regulator_enable(max98396->pvdd);
1604703ee055SDaniel Mack 		if (ret < 0)
1605703ee055SDaniel Mack 			return ret;
1606703ee055SDaniel Mack 	}
1607703ee055SDaniel Mack 
1608703ee055SDaniel Mack 	if (max98396->vbat) {
1609703ee055SDaniel Mack 		ret = regulator_enable(max98396->vbat);
1610703ee055SDaniel Mack 		if (ret < 0)
1611703ee055SDaniel Mack 			return ret;
1612703ee055SDaniel Mack 	}
1613b5858113SRyan Lee 
1614b5858113SRyan Lee 	regcache_cache_only(max98396->regmap, false);
1615b5858113SRyan Lee 	max98396_reset(max98396, dev);
1616b5858113SRyan Lee 	regcache_sync(max98396->regmap);
1617b5858113SRyan Lee 	return 0;
1618b5858113SRyan Lee }
1619b5858113SRyan Lee #endif
1620b5858113SRyan Lee 
1621b5858113SRyan Lee static const struct dev_pm_ops max98396_pm = {
1622b5858113SRyan Lee 	SET_SYSTEM_SLEEP_PM_OPS(max98396_suspend, max98396_resume)
1623b5858113SRyan Lee };
1624b5858113SRyan Lee 
1625b5858113SRyan Lee static const struct snd_soc_component_driver soc_codec_dev_max98396 = {
1626b5858113SRyan Lee 	.probe			= max98396_probe,
1627b5858113SRyan Lee 	.controls		= max98396_snd_controls,
1628b5858113SRyan Lee 	.num_controls		= ARRAY_SIZE(max98396_snd_controls),
1629b5858113SRyan Lee 	.dapm_widgets		= max98396_dapm_widgets,
1630b5858113SRyan Lee 	.num_dapm_widgets	= ARRAY_SIZE(max98396_dapm_widgets),
1631b5858113SRyan Lee 	.dapm_routes		= max98396_audio_map,
1632b5858113SRyan Lee 	.num_dapm_routes	= ARRAY_SIZE(max98396_audio_map),
1633b5858113SRyan Lee 	.idle_bias_on		= 1,
1634b5858113SRyan Lee 	.use_pmdown_time	= 1,
1635b5858113SRyan Lee 	.endianness		= 1,
1636b5858113SRyan Lee };
1637b5858113SRyan Lee 
1638b5858113SRyan Lee static const struct snd_soc_component_driver soc_codec_dev_max98397 = {
1639b5858113SRyan Lee 	.probe			= max98396_probe,
1640b5858113SRyan Lee 	.controls		= max98397_snd_controls,
1641b5858113SRyan Lee 	.num_controls		= ARRAY_SIZE(max98397_snd_controls),
1642b5858113SRyan Lee 	.dapm_widgets		= max98396_dapm_widgets,
1643b5858113SRyan Lee 	.num_dapm_widgets	= ARRAY_SIZE(max98396_dapm_widgets),
1644b5858113SRyan Lee 	.dapm_routes		= max98396_audio_map,
1645b5858113SRyan Lee 	.num_dapm_routes	= ARRAY_SIZE(max98396_audio_map),
1646b5858113SRyan Lee 	.idle_bias_on		= 1,
1647b5858113SRyan Lee 	.use_pmdown_time	= 1,
1648b5858113SRyan Lee 	.endianness		= 1,
1649b5858113SRyan Lee };
1650b5858113SRyan Lee 
1651b5858113SRyan Lee static const struct regmap_config max98396_regmap = {
1652b5858113SRyan Lee 	.reg_bits = 16,
1653b5858113SRyan Lee 	.val_bits = 8,
1654b5858113SRyan Lee 	.max_register = MAX98396_R21FF_REVISION_ID,
1655b5858113SRyan Lee 	.reg_defaults  = max98396_reg,
1656b5858113SRyan Lee 	.num_reg_defaults = ARRAY_SIZE(max98396_reg),
1657b5858113SRyan Lee 	.readable_reg = max98396_readable_register,
1658b5858113SRyan Lee 	.volatile_reg = max98396_volatile_reg,
1659b5858113SRyan Lee 	.cache_type = REGCACHE_RBTREE,
1660b5858113SRyan Lee };
1661b5858113SRyan Lee 
1662b5858113SRyan Lee static const struct regmap_config max98397_regmap = {
1663b5858113SRyan Lee 	.reg_bits = 16,
1664b5858113SRyan Lee 	.val_bits = 8,
1665b5858113SRyan Lee 	.max_register = MAX98397_R22FF_REVISION_ID,
1666b5858113SRyan Lee 	.reg_defaults  = max98397_reg,
1667b5858113SRyan Lee 	.num_reg_defaults = ARRAY_SIZE(max98397_reg),
1668b5858113SRyan Lee 	.readable_reg = max98397_readable_register,
1669b5858113SRyan Lee 	.volatile_reg = max98397_volatile_reg,
1670b5858113SRyan Lee 	.cache_type = REGCACHE_RBTREE,
1671b5858113SRyan Lee };
1672b5858113SRyan Lee 
max98396_read_device_property(struct device * dev,struct max98396_priv * max98396)1673b5858113SRyan Lee static void max98396_read_device_property(struct device *dev,
1674b5858113SRyan Lee 					  struct max98396_priv *max98396)
1675b5858113SRyan Lee {
1676b5858113SRyan Lee 	int value;
1677b5858113SRyan Lee 
1678b5858113SRyan Lee 	if (!device_property_read_u32(dev, "adi,vmon-slot-no", &value))
1679b5858113SRyan Lee 		max98396->v_slot = value & 0xF;
1680b5858113SRyan Lee 	else
1681b5858113SRyan Lee 		max98396->v_slot = 0;
1682b5858113SRyan Lee 
1683b5858113SRyan Lee 	if (!device_property_read_u32(dev, "adi,imon-slot-no", &value))
1684b5858113SRyan Lee 		max98396->i_slot = value & 0xF;
1685b5858113SRyan Lee 	else
1686b5858113SRyan Lee 		max98396->i_slot = 1;
1687b5858113SRyan Lee 
1688f42924b4SDaniel Mack 	if (!device_property_read_u32(dev, "adi,spkfb-slot-no", &value))
1689f42924b4SDaniel Mack 		max98396->spkfb_slot = value & 0xF;
1690f42924b4SDaniel Mack 	else
1691f42924b4SDaniel Mack 		max98396->spkfb_slot = 2;
1692f42924b4SDaniel Mack 
1693b5858113SRyan Lee 	if (!device_property_read_u32(dev, "adi,bypass-slot-no", &value))
1694b5858113SRyan Lee 		max98396->bypass_slot = value & 0xF;
1695b5858113SRyan Lee 	else
1696b5858113SRyan Lee 		max98396->bypass_slot = 0;
169733b7504aSDaniel Mack 
169833b7504aSDaniel Mack 	max98396->dmon_stuck_enable =
169933b7504aSDaniel Mack 		device_property_read_bool(dev, "adi,dmon-stuck-enable");
170033b7504aSDaniel Mack 
170133b7504aSDaniel Mack 	if (!device_property_read_u32(dev, "adi,dmon-stuck-threshold-bits", &value))
170233b7504aSDaniel Mack 		max98396->dmon_stuck_threshold = value;
170333b7504aSDaniel Mack 	else
170433b7504aSDaniel Mack 		max98396->dmon_stuck_threshold = 15;
170533b7504aSDaniel Mack 
170633b7504aSDaniel Mack 	max98396->dmon_mag_enable =
170733b7504aSDaniel Mack 		device_property_read_bool(dev, "adi,dmon-magnitude-enable");
170833b7504aSDaniel Mack 
170933b7504aSDaniel Mack 	if (!device_property_read_u32(dev, "adi,dmon-magnitude-threshold-bits", &value))
171033b7504aSDaniel Mack 		max98396->dmon_mag_threshold = value;
171133b7504aSDaniel Mack 	else
171233b7504aSDaniel Mack 		max98396->dmon_mag_threshold = 5;
171333b7504aSDaniel Mack 
171433b7504aSDaniel Mack 	if (!device_property_read_u32(dev, "adi,dmon-duration-ms", &value))
171533b7504aSDaniel Mack 		max98396->dmon_duration = value;
171633b7504aSDaniel Mack 	else
171733b7504aSDaniel Mack 		max98396->dmon_duration = 64;
1718b5858113SRyan Lee }
1719b5858113SRyan Lee 
max98396_core_supplies_disable(void * priv)1720703ee055SDaniel Mack static void max98396_core_supplies_disable(void *priv)
1721703ee055SDaniel Mack {
1722703ee055SDaniel Mack 	struct max98396_priv *max98396 = priv;
1723703ee055SDaniel Mack 
1724703ee055SDaniel Mack 	regulator_bulk_disable(MAX98396_NUM_CORE_SUPPLIES,
1725703ee055SDaniel Mack 			       max98396->core_supplies);
1726703ee055SDaniel Mack }
1727703ee055SDaniel Mack 
max98396_supply_disable(void * r)1728703ee055SDaniel Mack static void max98396_supply_disable(void *r)
1729703ee055SDaniel Mack {
1730703ee055SDaniel Mack 	regulator_disable((struct regulator *) r);
1731703ee055SDaniel Mack }
1732703ee055SDaniel Mack 
max98396_i2c_probe(struct i2c_client * i2c)17332ff85020SUwe Kleine-König static int max98396_i2c_probe(struct i2c_client *i2c)
1734b5858113SRyan Lee {
17352ff85020SUwe Kleine-König 	const struct i2c_device_id *id = i2c_client_get_device_id(i2c);
1736b5858113SRyan Lee 	struct max98396_priv *max98396 = NULL;
1737703ee055SDaniel Mack 	int i, ret, reg;
1738b5858113SRyan Lee 
1739b5858113SRyan Lee 	max98396 = devm_kzalloc(&i2c->dev, sizeof(*max98396), GFP_KERNEL);
1740b5858113SRyan Lee 
1741b5858113SRyan Lee 	if (!max98396) {
1742b5858113SRyan Lee 		ret = -ENOMEM;
1743b5858113SRyan Lee 		return ret;
1744b5858113SRyan Lee 	}
1745b5858113SRyan Lee 	i2c_set_clientdata(i2c, max98396);
1746b5858113SRyan Lee 
1747b5858113SRyan Lee 	max98396->device_id =  id->driver_data;
1748b5858113SRyan Lee 
1749b5858113SRyan Lee 	/* regmap initialization */
1750b5858113SRyan Lee 	if (max98396->device_id == CODEC_TYPE_MAX98396)
1751b5858113SRyan Lee 		max98396->regmap = devm_regmap_init_i2c(i2c, &max98396_regmap);
1752b5858113SRyan Lee 
1753b5858113SRyan Lee 	else
1754b5858113SRyan Lee 		max98396->regmap = devm_regmap_init_i2c(i2c, &max98397_regmap);
1755b5858113SRyan Lee 
1756b5858113SRyan Lee 	if (IS_ERR(max98396->regmap)) {
1757b5858113SRyan Lee 		ret = PTR_ERR(max98396->regmap);
1758b5858113SRyan Lee 		dev_err(&i2c->dev,
1759b5858113SRyan Lee 			"Failed to allocate regmap: %d\n", ret);
1760b5858113SRyan Lee 		return ret;
1761b5858113SRyan Lee 	}
1762b5858113SRyan Lee 
1763703ee055SDaniel Mack 	/* Obtain regulator supplies */
1764703ee055SDaniel Mack 	for (i = 0; i < MAX98396_NUM_CORE_SUPPLIES; i++)
1765703ee055SDaniel Mack 		max98396->core_supplies[i].supply = max98396_core_supplies[i];
1766703ee055SDaniel Mack 
1767703ee055SDaniel Mack 	ret = devm_regulator_bulk_get(&i2c->dev, MAX98396_NUM_CORE_SUPPLIES,
1768703ee055SDaniel Mack 				      max98396->core_supplies);
1769703ee055SDaniel Mack 	if (ret < 0) {
1770703ee055SDaniel Mack 		dev_err(&i2c->dev, "Failed to request core supplies: %d\n", ret);
1771703ee055SDaniel Mack 		return ret;
1772703ee055SDaniel Mack 	}
1773703ee055SDaniel Mack 
1774703ee055SDaniel Mack 	max98396->vbat = devm_regulator_get_optional(&i2c->dev, "vbat");
1775703ee055SDaniel Mack 	if (IS_ERR(max98396->vbat)) {
1776703ee055SDaniel Mack 		if (PTR_ERR(max98396->vbat) == -EPROBE_DEFER)
1777703ee055SDaniel Mack 			return -EPROBE_DEFER;
1778703ee055SDaniel Mack 
1779703ee055SDaniel Mack 		max98396->vbat = NULL;
1780703ee055SDaniel Mack 	}
1781703ee055SDaniel Mack 
1782703ee055SDaniel Mack 	max98396->pvdd = devm_regulator_get_optional(&i2c->dev, "pvdd");
1783703ee055SDaniel Mack 	if (IS_ERR(max98396->pvdd)) {
1784703ee055SDaniel Mack 		if (PTR_ERR(max98396->pvdd) == -EPROBE_DEFER)
1785703ee055SDaniel Mack 			return -EPROBE_DEFER;
1786703ee055SDaniel Mack 
1787703ee055SDaniel Mack 		max98396->pvdd = NULL;
1788703ee055SDaniel Mack 	}
1789703ee055SDaniel Mack 
1790703ee055SDaniel Mack 	ret = regulator_bulk_enable(MAX98396_NUM_CORE_SUPPLIES,
1791703ee055SDaniel Mack 				    max98396->core_supplies);
1792703ee055SDaniel Mack 	if (ret < 0) {
1793703ee055SDaniel Mack 		dev_err(&i2c->dev, "Unable to enable core supplies: %d", ret);
1794703ee055SDaniel Mack 		return ret;
1795703ee055SDaniel Mack 	}
1796703ee055SDaniel Mack 
1797703ee055SDaniel Mack 	ret = devm_add_action_or_reset(&i2c->dev, max98396_core_supplies_disable,
1798703ee055SDaniel Mack 				       max98396);
1799703ee055SDaniel Mack 	if (ret < 0)
1800703ee055SDaniel Mack 		return ret;
1801703ee055SDaniel Mack 
1802703ee055SDaniel Mack 	if (max98396->pvdd) {
1803703ee055SDaniel Mack 		ret = regulator_enable(max98396->pvdd);
1804703ee055SDaniel Mack 		if (ret < 0)
1805703ee055SDaniel Mack 			return ret;
1806703ee055SDaniel Mack 
1807703ee055SDaniel Mack 		ret = devm_add_action_or_reset(&i2c->dev,
1808703ee055SDaniel Mack 					       max98396_supply_disable,
1809703ee055SDaniel Mack 					       max98396->pvdd);
1810703ee055SDaniel Mack 		if (ret < 0)
1811703ee055SDaniel Mack 			return ret;
1812703ee055SDaniel Mack 	}
1813703ee055SDaniel Mack 
1814703ee055SDaniel Mack 	if (max98396->vbat) {
1815703ee055SDaniel Mack 		ret = regulator_enable(max98396->vbat);
1816703ee055SDaniel Mack 		if (ret < 0)
1817703ee055SDaniel Mack 			return ret;
1818703ee055SDaniel Mack 
1819703ee055SDaniel Mack 		ret = devm_add_action_or_reset(&i2c->dev,
1820703ee055SDaniel Mack 					       max98396_supply_disable,
1821703ee055SDaniel Mack 					       max98396->vbat);
1822703ee055SDaniel Mack 		if (ret < 0)
1823703ee055SDaniel Mack 			return ret;
1824703ee055SDaniel Mack 	}
1825703ee055SDaniel Mack 
1826b5858113SRyan Lee 	/* update interleave mode info */
1827b5858113SRyan Lee 	if (device_property_read_bool(&i2c->dev, "adi,interleave_mode"))
1828b5858113SRyan Lee 		max98396->interleave_mode = true;
1829b5858113SRyan Lee 	else
1830b5858113SRyan Lee 		max98396->interleave_mode = false;
1831b5858113SRyan Lee 
1832b5858113SRyan Lee 	/* voltage/current slot & gpio configuration */
1833b5858113SRyan Lee 	max98396_read_device_property(&i2c->dev, max98396);
1834b5858113SRyan Lee 
1835b5858113SRyan Lee 	/* Reset the Device */
1836b5858113SRyan Lee 	max98396->reset_gpio = devm_gpiod_get_optional(&i2c->dev,
1837b5858113SRyan Lee 						       "reset", GPIOD_OUT_HIGH);
1838b5858113SRyan Lee 	if (IS_ERR(max98396->reset_gpio)) {
1839b5858113SRyan Lee 		ret = PTR_ERR(max98396->reset_gpio);
1840b5858113SRyan Lee 		dev_err(&i2c->dev, "Unable to request GPIO pin: %d.\n", ret);
1841b5858113SRyan Lee 		return ret;
1842b5858113SRyan Lee 	}
1843b5858113SRyan Lee 
1844b5858113SRyan Lee 	if (max98396->reset_gpio) {
1845b5858113SRyan Lee 		usleep_range(5000, 6000);
1846b5858113SRyan Lee 		gpiod_set_value_cansleep(max98396->reset_gpio, 0);
1847b5858113SRyan Lee 		/* Wait for the hw reset done */
1848b5858113SRyan Lee 		usleep_range(5000, 6000);
1849b5858113SRyan Lee 	}
1850b5858113SRyan Lee 
1851b5858113SRyan Lee 	ret = regmap_read(max98396->regmap,
1852b5858113SRyan Lee 			  GET_REG_ADDR_REV_ID(max98396->device_id), &reg);
1853b5858113SRyan Lee 	if (ret < 0) {
1854b5858113SRyan Lee 		dev_err(&i2c->dev, "%s: failed to read revision of the device.\n",  id->name);
1855b5858113SRyan Lee 		return ret;
1856b5858113SRyan Lee 	}
1857b5858113SRyan Lee 	dev_info(&i2c->dev, "%s revision ID: 0x%02X\n", id->name, reg);
1858b5858113SRyan Lee 
1859b5858113SRyan Lee 	/* codec registration */
1860b5858113SRyan Lee 	if (max98396->device_id == CODEC_TYPE_MAX98396)
1861b5858113SRyan Lee 		ret = devm_snd_soc_register_component(&i2c->dev,
1862b5858113SRyan Lee 						      &soc_codec_dev_max98396,
1863b5858113SRyan Lee 						      max98396_dai,
1864b5858113SRyan Lee 						      ARRAY_SIZE(max98396_dai));
1865b5858113SRyan Lee 	else
1866b5858113SRyan Lee 		ret = devm_snd_soc_register_component(&i2c->dev,
1867b5858113SRyan Lee 						      &soc_codec_dev_max98397,
1868b5858113SRyan Lee 						      max98397_dai,
1869b5858113SRyan Lee 						      ARRAY_SIZE(max98397_dai));
1870b5858113SRyan Lee 	if (ret < 0)
1871b5858113SRyan Lee 		dev_err(&i2c->dev, "Failed to register codec: %d\n", ret);
1872b5858113SRyan Lee 
1873b5858113SRyan Lee 	return ret;
1874b5858113SRyan Lee }
1875b5858113SRyan Lee 
1876b5858113SRyan Lee static const struct i2c_device_id max98396_i2c_id[] = {
1877b5858113SRyan Lee 	{ "max98396", CODEC_TYPE_MAX98396},
1878b5858113SRyan Lee 	{ "max98397", CODEC_TYPE_MAX98397},
1879b5858113SRyan Lee 	{ },
1880b5858113SRyan Lee };
1881b5858113SRyan Lee 
1882b5858113SRyan Lee MODULE_DEVICE_TABLE(i2c, max98396_i2c_id);
1883b5858113SRyan Lee 
1884b5858113SRyan Lee #if defined(CONFIG_OF)
1885b5858113SRyan Lee static const struct of_device_id max98396_of_match[] = {
1886b5858113SRyan Lee 	{ .compatible = "adi,max98396", },
1887b5858113SRyan Lee 	{ .compatible = "adi,max98397", },
1888b5858113SRyan Lee 	{ }
1889b5858113SRyan Lee };
1890b5858113SRyan Lee MODULE_DEVICE_TABLE(of, max98396_of_match);
1891b5858113SRyan Lee #endif
1892b5858113SRyan Lee 
1893b5858113SRyan Lee #ifdef CONFIG_ACPI
1894b5858113SRyan Lee static const struct acpi_device_id max98396_acpi_match[] = {
1895b5858113SRyan Lee 	{ "ADS8396", 0 },
1896b5858113SRyan Lee 	{ "ADS8397", 0 },
1897b5858113SRyan Lee 	{},
1898b5858113SRyan Lee };
1899b5858113SRyan Lee MODULE_DEVICE_TABLE(acpi, max98396_acpi_match);
1900b5858113SRyan Lee #endif
1901b5858113SRyan Lee 
1902b5858113SRyan Lee static struct i2c_driver max98396_i2c_driver = {
1903b5858113SRyan Lee 	.driver = {
1904b5858113SRyan Lee 		.name = "max98396",
1905b5858113SRyan Lee 		.of_match_table = of_match_ptr(max98396_of_match),
1906b5858113SRyan Lee 		.acpi_match_table = ACPI_PTR(max98396_acpi_match),
1907b5858113SRyan Lee 		.pm = &max98396_pm,
1908b5858113SRyan Lee 	},
1909*9abcd240SUwe Kleine-König 	.probe = max98396_i2c_probe,
1910b5858113SRyan Lee 	.id_table = max98396_i2c_id,
1911b5858113SRyan Lee };
1912b5858113SRyan Lee 
1913b5858113SRyan Lee module_i2c_driver(max98396_i2c_driver)
1914b5858113SRyan Lee 
1915b5858113SRyan Lee MODULE_DESCRIPTION("ALSA SoC MAX98396 driver");
1916b5858113SRyan Lee MODULE_AUTHOR("Ryan Lee <ryans.lee@analog.com>");
1917b5858113SRyan Lee MODULE_LICENSE("GPL");
1918