xref: /linux/sound/soc/codecs/max98390.c (revision 9dd28b467c35eef320a2974f6b1f209343ad8704)
1a6e3f4f3SSteve Lee // SPDX-License-Identifier: GPL-2.0-or-later
2a6e3f4f3SSteve Lee /*
3a6e3f4f3SSteve Lee  * max98390.c  --  MAX98390 ALSA Soc Audio driver
4a6e3f4f3SSteve Lee  *
5a6e3f4f3SSteve Lee  * Copyright (C) 2020 Maxim Integrated Products
6a6e3f4f3SSteve Lee  *
7a6e3f4f3SSteve Lee  */
8a6e3f4f3SSteve Lee 
9a6e3f4f3SSteve Lee #include <linux/acpi.h>
10a6e3f4f3SSteve Lee #include <linux/cdev.h>
11a6e3f4f3SSteve Lee #include <linux/dmi.h>
12a6e3f4f3SSteve Lee #include <linux/firmware.h>
13aa7407f8SRandy Dunlap #include <linux/gpio/consumer.h>
14a6e3f4f3SSteve Lee #include <linux/i2c.h>
15a6e3f4f3SSteve Lee #include <linux/module.h>
16a6e3f4f3SSteve Lee #include <linux/of_gpio.h>
17a6e3f4f3SSteve Lee #include <linux/regmap.h>
18a6e3f4f3SSteve Lee #include <linux/slab.h>
19a6e3f4f3SSteve Lee #include <linux/time.h>
20a6e3f4f3SSteve Lee #include <sound/pcm.h>
21a6e3f4f3SSteve Lee #include <sound/pcm_params.h>
22a6e3f4f3SSteve Lee #include <sound/soc.h>
23a6e3f4f3SSteve Lee #include <sound/tlv.h>
24a6e3f4f3SSteve Lee 
25a6e3f4f3SSteve Lee #include "max98390.h"
26a6e3f4f3SSteve Lee 
27a6e3f4f3SSteve Lee static struct reg_default max98390_reg_defaults[] = {
28a6e3f4f3SSteve Lee 	{MAX98390_INT_EN1, 0xf0},
29a6e3f4f3SSteve Lee 	{MAX98390_INT_EN2, 0x00},
30a6e3f4f3SSteve Lee 	{MAX98390_INT_EN3, 0x00},
31a6e3f4f3SSteve Lee 	{MAX98390_INT_FLAG_CLR1, 0x00},
32a6e3f4f3SSteve Lee 	{MAX98390_INT_FLAG_CLR2, 0x00},
33a6e3f4f3SSteve Lee 	{MAX98390_INT_FLAG_CLR3, 0x00},
34a6e3f4f3SSteve Lee 	{MAX98390_IRQ_CTRL, 0x01},
35a6e3f4f3SSteve Lee 	{MAX98390_CLK_MON, 0x6d},
36a6e3f4f3SSteve Lee 	{MAX98390_DAT_MON, 0x03},
37a6e3f4f3SSteve Lee 	{MAX98390_WDOG_CTRL, 0x00},
38a6e3f4f3SSteve Lee 	{MAX98390_WDOG_RST, 0x00},
39a6e3f4f3SSteve Lee 	{MAX98390_MEAS_ADC_THERM_WARN_THRESH, 0x75},
40a6e3f4f3SSteve Lee 	{MAX98390_MEAS_ADC_THERM_SHDN_THRESH, 0x8c},
41a6e3f4f3SSteve Lee 	{MAX98390_MEAS_ADC_THERM_HYSTERESIS, 0x08},
42a6e3f4f3SSteve Lee 	{MAX98390_PIN_CFG, 0x55},
43a6e3f4f3SSteve Lee 	{MAX98390_PCM_RX_EN_A, 0x00},
44a6e3f4f3SSteve Lee 	{MAX98390_PCM_RX_EN_B, 0x00},
45a6e3f4f3SSteve Lee 	{MAX98390_PCM_TX_EN_A, 0x00},
46a6e3f4f3SSteve Lee 	{MAX98390_PCM_TX_EN_B, 0x00},
47a6e3f4f3SSteve Lee 	{MAX98390_PCM_TX_HIZ_CTRL_A, 0xff},
48a6e3f4f3SSteve Lee 	{MAX98390_PCM_TX_HIZ_CTRL_B, 0xff},
49a6e3f4f3SSteve Lee 	{MAX98390_PCM_CH_SRC_1, 0x00},
50a6e3f4f3SSteve Lee 	{MAX98390_PCM_CH_SRC_2, 0x00},
51a6e3f4f3SSteve Lee 	{MAX98390_PCM_CH_SRC_3, 0x00},
52a6e3f4f3SSteve Lee 	{MAX98390_PCM_MODE_CFG, 0xc0},
53a6e3f4f3SSteve Lee 	{MAX98390_PCM_MASTER_MODE, 0x1c},
54a6e3f4f3SSteve Lee 	{MAX98390_PCM_CLK_SETUP, 0x44},
55a6e3f4f3SSteve Lee 	{MAX98390_PCM_SR_SETUP, 0x08},
56a6e3f4f3SSteve Lee 	{MAX98390_ICC_RX_EN_A, 0x00},
57a6e3f4f3SSteve Lee 	{MAX98390_ICC_RX_EN_B, 0x00},
58a6e3f4f3SSteve Lee 	{MAX98390_ICC_TX_EN_A, 0x00},
59a6e3f4f3SSteve Lee 	{MAX98390_ICC_TX_EN_B, 0x00},
60a6e3f4f3SSteve Lee 	{MAX98390_ICC_HIZ_MANUAL_MODE, 0x00},
61a6e3f4f3SSteve Lee 	{MAX98390_ICC_TX_HIZ_EN_A, 0x00},
62a6e3f4f3SSteve Lee 	{MAX98390_ICC_TX_HIZ_EN_B, 0x00},
63a6e3f4f3SSteve Lee 	{MAX98390_ICC_LNK_EN, 0x00},
64a6e3f4f3SSteve Lee 	{MAX98390_R2039_AMP_DSP_CFG, 0x0f},
65a6e3f4f3SSteve Lee 	{MAX98390_R203A_AMP_EN, 0x81},
66a6e3f4f3SSteve Lee 	{MAX98390_TONE_GEN_DC_CFG, 0x00},
67a6e3f4f3SSteve Lee 	{MAX98390_SPK_SRC_SEL, 0x00},
68a6e3f4f3SSteve Lee 	{MAX98390_SSM_CFG, 0x85},
69a6e3f4f3SSteve Lee 	{MAX98390_MEAS_EN, 0x03},
70a6e3f4f3SSteve Lee 	{MAX98390_MEAS_DSP_CFG, 0x0f},
71a6e3f4f3SSteve Lee 	{MAX98390_BOOST_CTRL0, 0x1c},
72a6e3f4f3SSteve Lee 	{MAX98390_BOOST_CTRL3, 0x01},
73a6e3f4f3SSteve Lee 	{MAX98390_BOOST_CTRL1, 0x40},
74a6e3f4f3SSteve Lee 	{MAX98390_MEAS_ADC_CFG, 0x07},
75a6e3f4f3SSteve Lee 	{MAX98390_MEAS_ADC_BASE_MSB, 0x00},
76a6e3f4f3SSteve Lee 	{MAX98390_MEAS_ADC_BASE_LSB, 0x23},
77a6e3f4f3SSteve Lee 	{MAX98390_ADC_CH0_DIVIDE, 0x00},
78a6e3f4f3SSteve Lee 	{MAX98390_ADC_CH1_DIVIDE, 0x00},
79a6e3f4f3SSteve Lee 	{MAX98390_ADC_CH2_DIVIDE, 0x00},
80a6e3f4f3SSteve Lee 	{MAX98390_ADC_CH0_FILT_CFG, 0x00},
81a6e3f4f3SSteve Lee 	{MAX98390_ADC_CH1_FILT_CFG, 0x00},
82a6e3f4f3SSteve Lee 	{MAX98390_ADC_CH2_FILT_CFG, 0x00},
83a6e3f4f3SSteve Lee 	{MAX98390_PWR_GATE_CTL, 0x2c},
84a6e3f4f3SSteve Lee 	{MAX98390_BROWNOUT_EN, 0x00},
85a6e3f4f3SSteve Lee 	{MAX98390_BROWNOUT_INFINITE_HOLD, 0x00},
86a6e3f4f3SSteve Lee 	{MAX98390_BROWNOUT_INFINITE_HOLD_CLR, 0x00},
87a6e3f4f3SSteve Lee 	{MAX98390_BROWNOUT_LVL_HOLD, 0x00},
88a6e3f4f3SSteve Lee 	{MAX98390_BROWNOUT_LVL1_THRESH, 0x00},
89a6e3f4f3SSteve Lee 	{MAX98390_BROWNOUT_LVL2_THRESH, 0x00},
90a6e3f4f3SSteve Lee 	{MAX98390_BROWNOUT_LVL3_THRESH, 0x00},
91a6e3f4f3SSteve Lee 	{MAX98390_BROWNOUT_LVL4_THRESH, 0x00},
92a6e3f4f3SSteve Lee 	{MAX98390_BROWNOUT_THRESH_HYSTERYSIS, 0x00},
93a6e3f4f3SSteve Lee 	{MAX98390_BROWNOUT_AMP_LIMITER_ATK_REL, 0x1f},
94a6e3f4f3SSteve Lee 	{MAX98390_BROWNOUT_AMP_GAIN_ATK_REL, 0x00},
95a6e3f4f3SSteve Lee 	{MAX98390_BROWNOUT_AMP1_CLIP_MODE, 0x00},
96a6e3f4f3SSteve Lee 	{MAX98390_BROWNOUT_LVL1_CUR_LIMIT, 0x00},
97a6e3f4f3SSteve Lee 	{MAX98390_BROWNOUT_LVL1_AMP1_CTRL1, 0x00},
98a6e3f4f3SSteve Lee 	{MAX98390_BROWNOUT_LVL1_AMP1_CTRL2, 0x00},
99a6e3f4f3SSteve Lee 	{MAX98390_BROWNOUT_LVL1_AMP1_CTRL3, 0x00},
100a6e3f4f3SSteve Lee 	{MAX98390_BROWNOUT_LVL2_CUR_LIMIT, 0x00},
101a6e3f4f3SSteve Lee 	{MAX98390_BROWNOUT_LVL2_AMP1_CTRL1, 0x00},
102a6e3f4f3SSteve Lee 	{MAX98390_BROWNOUT_LVL2_AMP1_CTRL2, 0x00},
103a6e3f4f3SSteve Lee 	{MAX98390_BROWNOUT_LVL2_AMP1_CTRL3, 0x00},
104a6e3f4f3SSteve Lee 	{MAX98390_BROWNOUT_LVL3_CUR_LIMIT, 0x00},
105a6e3f4f3SSteve Lee 	{MAX98390_BROWNOUT_LVL3_AMP1_CTRL1, 0x00},
106a6e3f4f3SSteve Lee 	{MAX98390_BROWNOUT_LVL3_AMP1_CTRL2, 0x00},
107a6e3f4f3SSteve Lee 	{MAX98390_BROWNOUT_LVL3_AMP1_CTRL3, 0x00},
108a6e3f4f3SSteve Lee 	{MAX98390_BROWNOUT_LVL4_CUR_LIMIT, 0x00},
109a6e3f4f3SSteve Lee 	{MAX98390_BROWNOUT_LVL4_AMP1_CTRL1, 0x00},
110a6e3f4f3SSteve Lee 	{MAX98390_BROWNOUT_LVL4_AMP1_CTRL2, 0x00},
111a6e3f4f3SSteve Lee 	{MAX98390_BROWNOUT_LVL4_AMP1_CTRL3, 0x00},
112a6e3f4f3SSteve Lee 	{MAX98390_BROWNOUT_ILIM_HLD, 0x00},
113a6e3f4f3SSteve Lee 	{MAX98390_BROWNOUT_LIM_HLD, 0x00},
114a6e3f4f3SSteve Lee 	{MAX98390_BROWNOUT_CLIP_HLD, 0x00},
115a6e3f4f3SSteve Lee 	{MAX98390_BROWNOUT_GAIN_HLD, 0x00},
116a6e3f4f3SSteve Lee 	{MAX98390_ENV_TRACK_VOUT_HEADROOM, 0x0f},
117a6e3f4f3SSteve Lee 	{MAX98390_ENV_TRACK_BOOST_VOUT_DELAY, 0x80},
118a6e3f4f3SSteve Lee 	{MAX98390_ENV_TRACK_REL_RATE, 0x07},
119a6e3f4f3SSteve Lee 	{MAX98390_ENV_TRACK_HOLD_RATE, 0x07},
120a6e3f4f3SSteve Lee 	{MAX98390_ENV_TRACK_CTRL, 0x01},
121a6e3f4f3SSteve Lee 	{MAX98390_BOOST_BYPASS1, 0x49},
122a6e3f4f3SSteve Lee 	{MAX98390_BOOST_BYPASS2, 0x2b},
123a6e3f4f3SSteve Lee 	{MAX98390_BOOST_BYPASS3, 0x08},
124a6e3f4f3SSteve Lee 	{MAX98390_FET_SCALING1, 0x00},
125a6e3f4f3SSteve Lee 	{MAX98390_FET_SCALING2, 0x03},
126a6e3f4f3SSteve Lee 	{MAX98390_FET_SCALING3, 0x00},
127a6e3f4f3SSteve Lee 	{MAX98390_FET_SCALING4, 0x07},
128a6e3f4f3SSteve Lee 	{MAX98390_SPK_SPEEDUP, 0x00},
129a6e3f4f3SSteve Lee 	{DSMIG_WB_DRC_RELEASE_TIME_1, 0x00},
130a6e3f4f3SSteve Lee 	{DSMIG_WB_DRC_RELEASE_TIME_2, 0x00},
131a6e3f4f3SSteve Lee 	{DSMIG_WB_DRC_ATTACK_TIME_1, 0x00},
132a6e3f4f3SSteve Lee 	{DSMIG_WB_DRC_ATTACK_TIME_2, 0x00},
133a6e3f4f3SSteve Lee 	{DSMIG_WB_DRC_COMPRESSION_RATIO, 0x00},
134a6e3f4f3SSteve Lee 	{DSMIG_WB_DRC_COMPRESSION_THRESHOLD, 0x00},
135a6e3f4f3SSteve Lee 	{DSMIG_WB_DRC_MAKEUPGAIN, 0x00},
136a6e3f4f3SSteve Lee 	{DSMIG_WB_DRC_NOISE_GATE_THRESHOLD, 0x00},
137a6e3f4f3SSteve Lee 	{DSMIG_WBDRC_HPF_ENABLE, 0x00},
138a6e3f4f3SSteve Lee 	{DSMIG_WB_DRC_TEST_SMOOTHER_OUT_EN, 0x00},
139a6e3f4f3SSteve Lee 	{DSMIG_PPR_THRESHOLD, 0x00},
140a6e3f4f3SSteve Lee 	{DSM_STEREO_BASS_CHANNEL_SELECT, 0x00},
141a6e3f4f3SSteve Lee 	{DSM_TPROT_THRESHOLD_BYTE0, 0x00},
142a6e3f4f3SSteve Lee 	{DSM_TPROT_THRESHOLD_BYTE1, 0x00},
143a6e3f4f3SSteve Lee 	{DSM_TPROT_ROOM_TEMPERATURE_BYTE0, 0x00},
144a6e3f4f3SSteve Lee 	{DSM_TPROT_ROOM_TEMPERATURE_BYTE1, 0x00},
145a6e3f4f3SSteve Lee 	{DSM_TPROT_RECIP_RDC_ROOM_BYTE0, 0x00},
146a6e3f4f3SSteve Lee 	{DSM_TPROT_RECIP_RDC_ROOM_BYTE1, 0x00},
147a6e3f4f3SSteve Lee 	{DSM_TPROT_RECIP_RDC_ROOM_BYTE2, 0x00},
148a6e3f4f3SSteve Lee 	{DSM_TPROT_RECIP_TCONST_BYTE0, 0x00},
149a6e3f4f3SSteve Lee 	{DSM_TPROT_RECIP_TCONST_BYTE1, 0x00},
150a6e3f4f3SSteve Lee 	{DSM_TPROT_RECIP_TCONST_BYTE2, 0x00},
151a6e3f4f3SSteve Lee 	{DSM_THERMAL_ATTENUATION_SETTINGS, 0x00},
152a6e3f4f3SSteve Lee 	{DSM_THERMAL_PILOT_TONE_ATTENUATION, 0x00},
153a6e3f4f3SSteve Lee 	{DSM_TPROT_PG_TEMP_THRESH_BYTE0, 0x00},
154a6e3f4f3SSteve Lee 	{DSM_TPROT_PG_TEMP_THRESH_BYTE1, 0x00},
155a6e3f4f3SSteve Lee 	{DSMIG_DEBUZZER_THRESHOLD, 0x00},
156a6e3f4f3SSteve Lee 	{DSMIG_DEBUZZER_ALPHA_COEF_TEST_ONLY, 0x08},
157a6e3f4f3SSteve Lee 	{DSM_VOL_ENA, 0x20},
158a6e3f4f3SSteve Lee 	{DSM_VOL_CTRL, 0xa0},
159a6e3f4f3SSteve Lee 	{DSMIG_EN, 0x00},
160a6e3f4f3SSteve Lee 	{MAX98390_R23E1_DSP_GLOBAL_EN, 0x00},
161a6e3f4f3SSteve Lee 	{MAX98390_R23FF_GLOBAL_EN, 0x00},
162a6e3f4f3SSteve Lee };
163a6e3f4f3SSteve Lee 
164a6e3f4f3SSteve Lee static int max98390_dai_set_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
165a6e3f4f3SSteve Lee {
166a6e3f4f3SSteve Lee 	struct snd_soc_component *component = codec_dai->component;
167a6e3f4f3SSteve Lee 	struct max98390_priv *max98390 =
168a6e3f4f3SSteve Lee 		snd_soc_component_get_drvdata(component);
169a6e3f4f3SSteve Lee 	unsigned int mode;
170a6e3f4f3SSteve Lee 	unsigned int format;
171a6e3f4f3SSteve Lee 	unsigned int invert = 0;
172a6e3f4f3SSteve Lee 
173a6e3f4f3SSteve Lee 	dev_dbg(component->dev, "%s: fmt 0x%08X\n", __func__, fmt);
174a6e3f4f3SSteve Lee 
175c536d745SMark Brown 	switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) {
176c536d745SMark Brown 	case SND_SOC_DAIFMT_CBC_CFC:
177a6e3f4f3SSteve Lee 		mode = MAX98390_PCM_MASTER_MODE_SLAVE;
178a6e3f4f3SSteve Lee 		break;
179c536d745SMark Brown 	case SND_SOC_DAIFMT_CBP_CFP:
180c536d745SMark Brown 		max98390->provider = true;
181a6e3f4f3SSteve Lee 		mode = MAX98390_PCM_MASTER_MODE_MASTER;
182a6e3f4f3SSteve Lee 		break;
183a6e3f4f3SSteve Lee 	default:
184a6e3f4f3SSteve Lee 		dev_err(component->dev, "DAI clock mode unsupported\n");
185a6e3f4f3SSteve Lee 		return -EINVAL;
186a6e3f4f3SSteve Lee 	}
187a6e3f4f3SSteve Lee 
188a6e3f4f3SSteve Lee 	regmap_update_bits(max98390->regmap,
189a6e3f4f3SSteve Lee 		MAX98390_PCM_MASTER_MODE,
190a6e3f4f3SSteve Lee 		MAX98390_PCM_MASTER_MODE_MASK,
191a6e3f4f3SSteve Lee 		mode);
192a6e3f4f3SSteve Lee 
193a6e3f4f3SSteve Lee 	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
194a6e3f4f3SSteve Lee 	case SND_SOC_DAIFMT_NB_NF:
195a6e3f4f3SSteve Lee 		break;
196a6e3f4f3SSteve Lee 	case SND_SOC_DAIFMT_IB_NF:
197a6e3f4f3SSteve Lee 		invert = MAX98390_PCM_MODE_CFG_PCM_BCLKEDGE;
198a6e3f4f3SSteve Lee 		break;
199a6e3f4f3SSteve Lee 	default:
200a6e3f4f3SSteve Lee 		dev_err(component->dev, "DAI invert mode unsupported\n");
201a6e3f4f3SSteve Lee 		return -EINVAL;
202a6e3f4f3SSteve Lee 	}
203a6e3f4f3SSteve Lee 
204a6e3f4f3SSteve Lee 	regmap_update_bits(max98390->regmap,
205a6e3f4f3SSteve Lee 		MAX98390_PCM_MODE_CFG,
206a6e3f4f3SSteve Lee 		MAX98390_PCM_MODE_CFG_PCM_BCLKEDGE,
207a6e3f4f3SSteve Lee 		invert);
208a6e3f4f3SSteve Lee 
209a6e3f4f3SSteve Lee 	/* interface format */
210a6e3f4f3SSteve Lee 	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
211a6e3f4f3SSteve Lee 	case SND_SOC_DAIFMT_I2S:
212a6e3f4f3SSteve Lee 		format = MAX98390_PCM_FORMAT_I2S;
213a6e3f4f3SSteve Lee 		break;
214a6e3f4f3SSteve Lee 	case SND_SOC_DAIFMT_LEFT_J:
215a6e3f4f3SSteve Lee 		format = MAX98390_PCM_FORMAT_LJ;
216a6e3f4f3SSteve Lee 		break;
217a6e3f4f3SSteve Lee 	case SND_SOC_DAIFMT_DSP_A:
218a6e3f4f3SSteve Lee 		format = MAX98390_PCM_FORMAT_TDM_MODE1;
219a6e3f4f3SSteve Lee 		break;
220a6e3f4f3SSteve Lee 	case SND_SOC_DAIFMT_DSP_B:
221a6e3f4f3SSteve Lee 		format = MAX98390_PCM_FORMAT_TDM_MODE0;
222a6e3f4f3SSteve Lee 		break;
223a6e3f4f3SSteve Lee 	default:
224a6e3f4f3SSteve Lee 		return -EINVAL;
225a6e3f4f3SSteve Lee 	}
226a6e3f4f3SSteve Lee 
227a6e3f4f3SSteve Lee 	regmap_update_bits(max98390->regmap,
228a6e3f4f3SSteve Lee 		MAX98390_PCM_MODE_CFG,
229a6e3f4f3SSteve Lee 		MAX98390_PCM_MODE_CFG_FORMAT_MASK,
230a6e3f4f3SSteve Lee 		format << MAX98390_PCM_MODE_CFG_FORMAT_SHIFT);
231a6e3f4f3SSteve Lee 
232a6e3f4f3SSteve Lee 	return 0;
233a6e3f4f3SSteve Lee }
234a6e3f4f3SSteve Lee 
235a6e3f4f3SSteve Lee static int max98390_get_bclk_sel(int bclk)
236a6e3f4f3SSteve Lee {
237a6e3f4f3SSteve Lee 	int i;
238a6e3f4f3SSteve Lee 	/* BCLKs per LRCLK */
239a6e3f4f3SSteve Lee 	static int bclk_sel_table[] = {
240a6e3f4f3SSteve Lee 		32, 48, 64, 96, 128, 192, 256, 320, 384, 512,
241a6e3f4f3SSteve Lee 	};
242a6e3f4f3SSteve Lee 	/* match BCLKs per LRCLK */
243a6e3f4f3SSteve Lee 	for (i = 0; i < ARRAY_SIZE(bclk_sel_table); i++) {
244a6e3f4f3SSteve Lee 		if (bclk_sel_table[i] == bclk)
245a6e3f4f3SSteve Lee 			return i + 2;
246a6e3f4f3SSteve Lee 	}
247a6e3f4f3SSteve Lee 	return 0;
248a6e3f4f3SSteve Lee }
249a6e3f4f3SSteve Lee 
250a6e3f4f3SSteve Lee static int max98390_set_clock(struct snd_soc_component *component,
251a6e3f4f3SSteve Lee 		struct snd_pcm_hw_params *params)
252a6e3f4f3SSteve Lee {
253a6e3f4f3SSteve Lee 	struct max98390_priv *max98390 =
254a6e3f4f3SSteve Lee 		snd_soc_component_get_drvdata(component);
255a6e3f4f3SSteve Lee 	/* codec MCLK rate in master mode */
256a6e3f4f3SSteve Lee 	static int rate_table[] = {
257a6e3f4f3SSteve Lee 		5644800, 6000000, 6144000, 6500000,
258a6e3f4f3SSteve Lee 		9600000, 11289600, 12000000, 12288000,
259a6e3f4f3SSteve Lee 		13000000, 19200000,
260a6e3f4f3SSteve Lee 	};
261a6e3f4f3SSteve Lee 	/* BCLK/LRCLK ratio calculation */
262a6e3f4f3SSteve Lee 	int blr_clk_ratio = params_channels(params)
263a6e3f4f3SSteve Lee 		* snd_pcm_format_width(params_format(params));
264a6e3f4f3SSteve Lee 	int value;
265a6e3f4f3SSteve Lee 
266c536d745SMark Brown 	if (max98390->provider) {
267a6e3f4f3SSteve Lee 		int i;
268a6e3f4f3SSteve Lee 		/* match rate to closest value */
269a6e3f4f3SSteve Lee 		for (i = 0; i < ARRAY_SIZE(rate_table); i++) {
270a6e3f4f3SSteve Lee 			if (rate_table[i] >= max98390->sysclk)
271a6e3f4f3SSteve Lee 				break;
272a6e3f4f3SSteve Lee 		}
273a6e3f4f3SSteve Lee 		if (i == ARRAY_SIZE(rate_table)) {
274a6e3f4f3SSteve Lee 			dev_err(component->dev, "failed to find proper clock rate.\n");
275a6e3f4f3SSteve Lee 			return -EINVAL;
276a6e3f4f3SSteve Lee 		}
277a6e3f4f3SSteve Lee 
278a6e3f4f3SSteve Lee 		regmap_update_bits(max98390->regmap,
279a6e3f4f3SSteve Lee 			MAX98390_PCM_MASTER_MODE,
280a6e3f4f3SSteve Lee 			MAX98390_PCM_MASTER_MODE_MCLK_MASK,
281a6e3f4f3SSteve Lee 			i << MAX98390_PCM_MASTER_MODE_MCLK_RATE_SHIFT);
282a6e3f4f3SSteve Lee 	}
283a6e3f4f3SSteve Lee 
284a6e3f4f3SSteve Lee 	if (!max98390->tdm_mode) {
285a6e3f4f3SSteve Lee 		/* BCLK configuration */
286a6e3f4f3SSteve Lee 		value = max98390_get_bclk_sel(blr_clk_ratio);
287a6e3f4f3SSteve Lee 		if (!value) {
288a6e3f4f3SSteve Lee 			dev_err(component->dev, "format unsupported %d\n",
289a6e3f4f3SSteve Lee 				params_format(params));
290a6e3f4f3SSteve Lee 			return -EINVAL;
291a6e3f4f3SSteve Lee 		}
292a6e3f4f3SSteve Lee 
293a6e3f4f3SSteve Lee 		regmap_update_bits(max98390->regmap,
294a6e3f4f3SSteve Lee 			MAX98390_PCM_CLK_SETUP,
295a6e3f4f3SSteve Lee 			MAX98390_PCM_CLK_SETUP_BSEL_MASK,
296a6e3f4f3SSteve Lee 			value);
297a6e3f4f3SSteve Lee 	}
298a6e3f4f3SSteve Lee 	return 0;
299a6e3f4f3SSteve Lee }
300a6e3f4f3SSteve Lee 
301a6e3f4f3SSteve Lee static int max98390_dai_hw_params(struct snd_pcm_substream *substream,
302a6e3f4f3SSteve Lee 		struct snd_pcm_hw_params *params,
303a6e3f4f3SSteve Lee 		struct snd_soc_dai *dai)
304a6e3f4f3SSteve Lee {
305a6e3f4f3SSteve Lee 	struct snd_soc_component *component =
306a6e3f4f3SSteve Lee 		dai->component;
307a6e3f4f3SSteve Lee 	struct max98390_priv *max98390 =
308a6e3f4f3SSteve Lee 		snd_soc_component_get_drvdata(component);
309a6e3f4f3SSteve Lee 
310a6e3f4f3SSteve Lee 	unsigned int sampling_rate;
311a6e3f4f3SSteve Lee 	unsigned int chan_sz;
312a6e3f4f3SSteve Lee 
313a6e3f4f3SSteve Lee 	/* pcm mode configuration */
314a6e3f4f3SSteve Lee 	switch (snd_pcm_format_width(params_format(params))) {
315a6e3f4f3SSteve Lee 	case 16:
316a6e3f4f3SSteve Lee 		chan_sz = MAX98390_PCM_MODE_CFG_CHANSZ_16;
317a6e3f4f3SSteve Lee 		break;
318a6e3f4f3SSteve Lee 	case 24:
319a6e3f4f3SSteve Lee 		chan_sz = MAX98390_PCM_MODE_CFG_CHANSZ_24;
320a6e3f4f3SSteve Lee 		break;
321a6e3f4f3SSteve Lee 	case 32:
322a6e3f4f3SSteve Lee 		chan_sz = MAX98390_PCM_MODE_CFG_CHANSZ_32;
323a6e3f4f3SSteve Lee 		break;
324a6e3f4f3SSteve Lee 	default:
325a6e3f4f3SSteve Lee 		dev_err(component->dev, "format unsupported %d\n",
326a6e3f4f3SSteve Lee 			params_format(params));
327a6e3f4f3SSteve Lee 		goto err;
328a6e3f4f3SSteve Lee 	}
329a6e3f4f3SSteve Lee 
330a6e3f4f3SSteve Lee 	regmap_update_bits(max98390->regmap,
331a6e3f4f3SSteve Lee 		MAX98390_PCM_MODE_CFG,
332a6e3f4f3SSteve Lee 		MAX98390_PCM_MODE_CFG_CHANSZ_MASK, chan_sz);
333a6e3f4f3SSteve Lee 
334a6e3f4f3SSteve Lee 	dev_dbg(component->dev, "format supported %d",
335a6e3f4f3SSteve Lee 		params_format(params));
336a6e3f4f3SSteve Lee 
337a6e3f4f3SSteve Lee 	/* sampling rate configuration */
338a6e3f4f3SSteve Lee 	switch (params_rate(params)) {
339a6e3f4f3SSteve Lee 	case 8000:
340a6e3f4f3SSteve Lee 		sampling_rate = MAX98390_PCM_SR_SET1_SR_8000;
341a6e3f4f3SSteve Lee 		break;
342a6e3f4f3SSteve Lee 	case 11025:
343a6e3f4f3SSteve Lee 		sampling_rate = MAX98390_PCM_SR_SET1_SR_11025;
344a6e3f4f3SSteve Lee 		break;
345a6e3f4f3SSteve Lee 	case 12000:
346a6e3f4f3SSteve Lee 		sampling_rate = MAX98390_PCM_SR_SET1_SR_12000;
347a6e3f4f3SSteve Lee 		break;
348a6e3f4f3SSteve Lee 	case 16000:
349a6e3f4f3SSteve Lee 		sampling_rate = MAX98390_PCM_SR_SET1_SR_16000;
350a6e3f4f3SSteve Lee 		break;
351a6e3f4f3SSteve Lee 	case 22050:
352a6e3f4f3SSteve Lee 		sampling_rate = MAX98390_PCM_SR_SET1_SR_22050;
353a6e3f4f3SSteve Lee 		break;
354a6e3f4f3SSteve Lee 	case 24000:
355a6e3f4f3SSteve Lee 		sampling_rate = MAX98390_PCM_SR_SET1_SR_24000;
356a6e3f4f3SSteve Lee 		break;
357a6e3f4f3SSteve Lee 	case 32000:
358a6e3f4f3SSteve Lee 		sampling_rate = MAX98390_PCM_SR_SET1_SR_32000;
359a6e3f4f3SSteve Lee 		break;
360a6e3f4f3SSteve Lee 	case 44100:
361a6e3f4f3SSteve Lee 		sampling_rate = MAX98390_PCM_SR_SET1_SR_44100;
362a6e3f4f3SSteve Lee 		break;
363a6e3f4f3SSteve Lee 	case 48000:
364a6e3f4f3SSteve Lee 		sampling_rate = MAX98390_PCM_SR_SET1_SR_48000;
365a6e3f4f3SSteve Lee 		break;
366a6e3f4f3SSteve Lee 	default:
367a6e3f4f3SSteve Lee 		dev_err(component->dev, "rate %d not supported\n",
368a6e3f4f3SSteve Lee 			params_rate(params));
369a6e3f4f3SSteve Lee 		goto err;
370a6e3f4f3SSteve Lee 	}
371a6e3f4f3SSteve Lee 
372a6e3f4f3SSteve Lee 	/* set DAI_SR to correct LRCLK frequency */
373a6e3f4f3SSteve Lee 	regmap_update_bits(max98390->regmap,
374a6e3f4f3SSteve Lee 		MAX98390_PCM_SR_SETUP,
375a6e3f4f3SSteve Lee 		MAX98390_PCM_SR_SET1_SR_MASK,
376a6e3f4f3SSteve Lee 		sampling_rate);
377a6e3f4f3SSteve Lee 
378a6e3f4f3SSteve Lee 	return max98390_set_clock(component, params);
379a6e3f4f3SSteve Lee err:
380a6e3f4f3SSteve Lee 	return -EINVAL;
381a6e3f4f3SSteve Lee }
382a6e3f4f3SSteve Lee 
383a6e3f4f3SSteve Lee static int max98390_dai_tdm_slot(struct snd_soc_dai *dai,
384a6e3f4f3SSteve Lee 		unsigned int tx_mask, unsigned int rx_mask,
385a6e3f4f3SSteve Lee 		int slots, int slot_width)
386a6e3f4f3SSteve Lee {
387a6e3f4f3SSteve Lee 	struct snd_soc_component *component = dai->component;
388a6e3f4f3SSteve Lee 	struct max98390_priv *max98390 =
389a6e3f4f3SSteve Lee 		snd_soc_component_get_drvdata(component);
390a6e3f4f3SSteve Lee 
391a6e3f4f3SSteve Lee 	int bsel;
392a6e3f4f3SSteve Lee 	unsigned int chan_sz;
393a6e3f4f3SSteve Lee 
394a6e3f4f3SSteve Lee 	if (!tx_mask && !rx_mask && !slots && !slot_width)
395a6e3f4f3SSteve Lee 		max98390->tdm_mode = false;
396a6e3f4f3SSteve Lee 	else
397a6e3f4f3SSteve Lee 		max98390->tdm_mode = true;
398a6e3f4f3SSteve Lee 
399a6e3f4f3SSteve Lee 	dev_dbg(component->dev,
400a6e3f4f3SSteve Lee 		"Tdm mode : %d\n", max98390->tdm_mode);
401a6e3f4f3SSteve Lee 
402a6e3f4f3SSteve Lee 	/* BCLK configuration */
403a6e3f4f3SSteve Lee 	bsel = max98390_get_bclk_sel(slots * slot_width);
404a6e3f4f3SSteve Lee 	if (!bsel) {
405a6e3f4f3SSteve Lee 		dev_err(component->dev, "BCLK %d not supported\n",
406a6e3f4f3SSteve Lee 			slots * slot_width);
407a6e3f4f3SSteve Lee 		return -EINVAL;
408a6e3f4f3SSteve Lee 	}
409a6e3f4f3SSteve Lee 
410a6e3f4f3SSteve Lee 	regmap_update_bits(max98390->regmap,
411a6e3f4f3SSteve Lee 		MAX98390_PCM_CLK_SETUP,
412a6e3f4f3SSteve Lee 		MAX98390_PCM_CLK_SETUP_BSEL_MASK,
413a6e3f4f3SSteve Lee 		bsel);
414a6e3f4f3SSteve Lee 
415a6e3f4f3SSteve Lee 	/* Channel size configuration */
416a6e3f4f3SSteve Lee 	switch (slot_width) {
417a6e3f4f3SSteve Lee 	case 16:
418a6e3f4f3SSteve Lee 		chan_sz = MAX98390_PCM_MODE_CFG_CHANSZ_16;
419a6e3f4f3SSteve Lee 		break;
420a6e3f4f3SSteve Lee 	case 24:
421a6e3f4f3SSteve Lee 		chan_sz = MAX98390_PCM_MODE_CFG_CHANSZ_24;
422a6e3f4f3SSteve Lee 		break;
423a6e3f4f3SSteve Lee 	case 32:
424a6e3f4f3SSteve Lee 		chan_sz = MAX98390_PCM_MODE_CFG_CHANSZ_32;
425a6e3f4f3SSteve Lee 		break;
426a6e3f4f3SSteve Lee 	default:
427a6e3f4f3SSteve Lee 		dev_err(component->dev, "format unsupported %d\n",
428a6e3f4f3SSteve Lee 			slot_width);
429a6e3f4f3SSteve Lee 		return -EINVAL;
430a6e3f4f3SSteve Lee 	}
431a6e3f4f3SSteve Lee 
432a6e3f4f3SSteve Lee 	regmap_update_bits(max98390->regmap,
433a6e3f4f3SSteve Lee 		MAX98390_PCM_MODE_CFG,
434a6e3f4f3SSteve Lee 		MAX98390_PCM_MODE_CFG_CHANSZ_MASK, chan_sz);
435a6e3f4f3SSteve Lee 
436a6e3f4f3SSteve Lee 	/* Rx slot configuration */
437a6e3f4f3SSteve Lee 	regmap_write(max98390->regmap,
438a6e3f4f3SSteve Lee 		MAX98390_PCM_RX_EN_A,
439a6e3f4f3SSteve Lee 		rx_mask & 0xFF);
440a6e3f4f3SSteve Lee 	regmap_write(max98390->regmap,
441a6e3f4f3SSteve Lee 		MAX98390_PCM_RX_EN_B,
442a6e3f4f3SSteve Lee 		(rx_mask & 0xFF00) >> 8);
443a6e3f4f3SSteve Lee 
444a6e3f4f3SSteve Lee 	/* Tx slot Hi-Z configuration */
445a6e3f4f3SSteve Lee 	regmap_write(max98390->regmap,
446a6e3f4f3SSteve Lee 		MAX98390_PCM_TX_HIZ_CTRL_A,
447a6e3f4f3SSteve Lee 		~tx_mask & 0xFF);
448a6e3f4f3SSteve Lee 	regmap_write(max98390->regmap,
449a6e3f4f3SSteve Lee 		MAX98390_PCM_TX_HIZ_CTRL_B,
450a6e3f4f3SSteve Lee 		(~tx_mask & 0xFF00) >> 8);
451a6e3f4f3SSteve Lee 
452a6e3f4f3SSteve Lee 	return 0;
453a6e3f4f3SSteve Lee }
454a6e3f4f3SSteve Lee 
455a6e3f4f3SSteve Lee static int max98390_dai_set_sysclk(struct snd_soc_dai *dai,
456a6e3f4f3SSteve Lee 		int clk_id, unsigned int freq, int dir)
457a6e3f4f3SSteve Lee {
458a6e3f4f3SSteve Lee 	struct snd_soc_component *component = dai->component;
459a6e3f4f3SSteve Lee 	struct max98390_priv *max98390 =
460a6e3f4f3SSteve Lee 		snd_soc_component_get_drvdata(component);
461a6e3f4f3SSteve Lee 
462a6e3f4f3SSteve Lee 	max98390->sysclk = freq;
463a6e3f4f3SSteve Lee 	return 0;
464a6e3f4f3SSteve Lee }
465a6e3f4f3SSteve Lee 
466a6e3f4f3SSteve Lee static const struct snd_soc_dai_ops max98390_dai_ops = {
467a6e3f4f3SSteve Lee 	.set_sysclk = max98390_dai_set_sysclk,
468a6e3f4f3SSteve Lee 	.set_fmt = max98390_dai_set_fmt,
469a6e3f4f3SSteve Lee 	.hw_params = max98390_dai_hw_params,
470a6e3f4f3SSteve Lee 	.set_tdm_slot = max98390_dai_tdm_slot,
471a6e3f4f3SSteve Lee };
472a6e3f4f3SSteve Lee 
473a6e3f4f3SSteve Lee static int max98390_dac_event(struct snd_soc_dapm_widget *w,
474a6e3f4f3SSteve Lee 		struct snd_kcontrol *kcontrol, int event)
475a6e3f4f3SSteve Lee {
476a6e3f4f3SSteve Lee 	struct snd_soc_component *component =
477a6e3f4f3SSteve Lee 		snd_soc_dapm_to_component(w->dapm);
478a6e3f4f3SSteve Lee 	struct max98390_priv *max98390 =
479a6e3f4f3SSteve Lee 		snd_soc_component_get_drvdata(component);
480a6e3f4f3SSteve Lee 
481a6e3f4f3SSteve Lee 	switch (event) {
482a6e3f4f3SSteve Lee 	case SND_SOC_DAPM_POST_PMU:
483a6e3f4f3SSteve Lee 		regmap_update_bits(max98390->regmap,
484a6e3f4f3SSteve Lee 			MAX98390_R203A_AMP_EN,
485a6e3f4f3SSteve Lee 			MAX98390_AMP_EN_MASK, 1);
486a6e3f4f3SSteve Lee 		regmap_update_bits(max98390->regmap,
487a6e3f4f3SSteve Lee 			MAX98390_R23FF_GLOBAL_EN,
488a6e3f4f3SSteve Lee 			MAX98390_GLOBAL_EN_MASK, 1);
489a6e3f4f3SSteve Lee 		break;
490a6e3f4f3SSteve Lee 	case SND_SOC_DAPM_POST_PMD:
491a6e3f4f3SSteve Lee 		regmap_update_bits(max98390->regmap,
492a6e3f4f3SSteve Lee 			MAX98390_R23FF_GLOBAL_EN,
493a6e3f4f3SSteve Lee 			MAX98390_GLOBAL_EN_MASK, 0);
494a6e3f4f3SSteve Lee 		regmap_update_bits(max98390->regmap,
495a6e3f4f3SSteve Lee 			MAX98390_R203A_AMP_EN,
496a6e3f4f3SSteve Lee 			MAX98390_AMP_EN_MASK, 0);
497a6e3f4f3SSteve Lee 		break;
498a6e3f4f3SSteve Lee 	}
499a6e3f4f3SSteve Lee 	return 0;
500a6e3f4f3SSteve Lee }
501a6e3f4f3SSteve Lee 
502a6e3f4f3SSteve Lee static const char * const max98390_switch_text[] = {
503a6e3f4f3SSteve Lee 	"Left", "Right", "LeftRight"};
504a6e3f4f3SSteve Lee 
505a6e3f4f3SSteve Lee static const char * const max98390_boost_voltage_text[] = {
506a6e3f4f3SSteve Lee 	"6.5V", "6.625V", "6.75V", "6.875V", "7V", "7.125V", "7.25V", "7.375V",
507a6e3f4f3SSteve Lee 	"7.5V", "7.625V", "7.75V", "7.875V", "8V", "8.125V", "8.25V", "8.375V",
508a6e3f4f3SSteve Lee 	"8.5V", "8.625V", "8.75V", "8.875V", "9V", "9.125V", "9.25V", "9.375V",
509a6e3f4f3SSteve Lee 	"9.5V", "9.625V", "9.75V", "9.875V", "10V"
510a6e3f4f3SSteve Lee };
511a6e3f4f3SSteve Lee 
512a6e3f4f3SSteve Lee static SOC_ENUM_SINGLE_DECL(max98390_boost_voltage,
513a6e3f4f3SSteve Lee 		MAX98390_BOOST_CTRL0, 0,
514a6e3f4f3SSteve Lee 		max98390_boost_voltage_text);
515a6e3f4f3SSteve Lee 
516a6e3f4f3SSteve Lee static DECLARE_TLV_DB_SCALE(max98390_spk_tlv, 300, 300, 0);
517a6e3f4f3SSteve Lee static DECLARE_TLV_DB_SCALE(max98390_digital_tlv, -8000, 50, 0);
518a6e3f4f3SSteve Lee 
519a6e3f4f3SSteve Lee static const char * const max98390_current_limit_text[] = {
520a6e3f4f3SSteve Lee 	"0.00A", "0.50A", "1.00A", "1.05A", "1.10A", "1.15A", "1.20A", "1.25A",
521a6e3f4f3SSteve Lee 	"1.30A", "1.35A", "1.40A", "1.45A", "1.50A", "1.55A", "1.60A", "1.65A",
522a6e3f4f3SSteve Lee 	"1.70A", "1.75A", "1.80A", "1.85A", "1.90A", "1.95A", "2.00A", "2.05A",
523a6e3f4f3SSteve Lee 	"2.10A", "2.15A", "2.20A", "2.25A", "2.30A", "2.35A", "2.40A", "2.45A",
524a6e3f4f3SSteve Lee 	"2.50A", "2.55A", "2.60A", "2.65A", "2.70A", "2.75A", "2.80A", "2.85A",
525a6e3f4f3SSteve Lee 	"2.90A", "2.95A", "3.00A", "3.05A", "3.10A", "3.15A", "3.20A", "3.25A",
526a6e3f4f3SSteve Lee 	"3.30A", "3.35A", "3.40A", "3.45A", "3.50A", "3.55A", "3.60A", "3.65A",
527a6e3f4f3SSteve Lee 	"3.70A", "3.75A", "3.80A", "3.85A", "3.90A", "3.95A", "4.00A", "4.05A",
528a6e3f4f3SSteve Lee 	"4.10A"
529a6e3f4f3SSteve Lee };
530a6e3f4f3SSteve Lee 
531a6e3f4f3SSteve Lee static SOC_ENUM_SINGLE_DECL(max98390_current_limit,
532a6e3f4f3SSteve Lee 		MAX98390_BOOST_CTRL1, 0,
533a6e3f4f3SSteve Lee 		max98390_current_limit_text);
534a6e3f4f3SSteve Lee 
535a6e3f4f3SSteve Lee static int max98390_ref_rdc_put(struct snd_kcontrol *kcontrol,
536a6e3f4f3SSteve Lee 		struct snd_ctl_elem_value *ucontrol)
537a6e3f4f3SSteve Lee {
538a6e3f4f3SSteve Lee 	struct snd_soc_component *component =
539a6e3f4f3SSteve Lee 		snd_soc_kcontrol_component(kcontrol);
540a6e3f4f3SSteve Lee 	struct max98390_priv *max98390 =
541a6e3f4f3SSteve Lee 		snd_soc_component_get_drvdata(component);
542a6e3f4f3SSteve Lee 
543a6e3f4f3SSteve Lee 	max98390->ref_rdc_value = ucontrol->value.integer.value[0];
544a6e3f4f3SSteve Lee 
545a6e3f4f3SSteve Lee 	regmap_write(max98390->regmap, DSM_TPROT_RECIP_RDC_ROOM_BYTE0,
546a6e3f4f3SSteve Lee 		max98390->ref_rdc_value & 0x000000ff);
547a6e3f4f3SSteve Lee 	regmap_write(max98390->regmap, DSM_TPROT_RECIP_RDC_ROOM_BYTE1,
548a6e3f4f3SSteve Lee 		(max98390->ref_rdc_value >> 8) & 0x000000ff);
549a6e3f4f3SSteve Lee 	regmap_write(max98390->regmap, DSM_TPROT_RECIP_RDC_ROOM_BYTE2,
550a6e3f4f3SSteve Lee 		(max98390->ref_rdc_value >> 16) & 0x000000ff);
551a6e3f4f3SSteve Lee 
552a6e3f4f3SSteve Lee 	return 0;
553a6e3f4f3SSteve Lee }
554a6e3f4f3SSteve Lee 
555a6e3f4f3SSteve Lee static int max98390_ref_rdc_get(struct snd_kcontrol *kcontrol,
556a6e3f4f3SSteve Lee 		struct snd_ctl_elem_value *ucontrol)
557a6e3f4f3SSteve Lee {
558a6e3f4f3SSteve Lee 	struct snd_soc_component *component =
559a6e3f4f3SSteve Lee 		snd_soc_kcontrol_component(kcontrol);
560a6e3f4f3SSteve Lee 	struct max98390_priv *max98390 =
561a6e3f4f3SSteve Lee 		snd_soc_component_get_drvdata(component);
562a6e3f4f3SSteve Lee 
563a6e3f4f3SSteve Lee 	ucontrol->value.integer.value[0] = max98390->ref_rdc_value;
564a6e3f4f3SSteve Lee 
565a6e3f4f3SSteve Lee 	return 0;
566a6e3f4f3SSteve Lee }
567a6e3f4f3SSteve Lee 
568a6e3f4f3SSteve Lee static int max98390_ambient_temp_put(struct snd_kcontrol *kcontrol,
569a6e3f4f3SSteve Lee 		struct snd_ctl_elem_value *ucontrol)
570a6e3f4f3SSteve Lee {
571a6e3f4f3SSteve Lee 	struct snd_soc_component *component =
572a6e3f4f3SSteve Lee 		snd_soc_kcontrol_component(kcontrol);
573a6e3f4f3SSteve Lee 	struct max98390_priv *max98390 =
574a6e3f4f3SSteve Lee 		snd_soc_component_get_drvdata(component);
575a6e3f4f3SSteve Lee 
576a6e3f4f3SSteve Lee 	max98390->ambient_temp_value = ucontrol->value.integer.value[0];
577a6e3f4f3SSteve Lee 
578a6e3f4f3SSteve Lee 	regmap_write(max98390->regmap, DSM_TPROT_ROOM_TEMPERATURE_BYTE1,
579a6e3f4f3SSteve Lee 		(max98390->ambient_temp_value >> 8) & 0x000000ff);
580a6e3f4f3SSteve Lee 	regmap_write(max98390->regmap, DSM_TPROT_ROOM_TEMPERATURE_BYTE0,
581a6e3f4f3SSteve Lee 		(max98390->ambient_temp_value) & 0x000000ff);
582a6e3f4f3SSteve Lee 
583a6e3f4f3SSteve Lee 	return 0;
584a6e3f4f3SSteve Lee }
585a6e3f4f3SSteve Lee 
586a6e3f4f3SSteve Lee static int max98390_ambient_temp_get(struct snd_kcontrol *kcontrol,
587a6e3f4f3SSteve Lee 		struct snd_ctl_elem_value *ucontrol)
588a6e3f4f3SSteve Lee {
589a6e3f4f3SSteve Lee 	struct snd_soc_component *component =
590a6e3f4f3SSteve Lee 		snd_soc_kcontrol_component(kcontrol);
591a6e3f4f3SSteve Lee 	struct max98390_priv *max98390 =
592a6e3f4f3SSteve Lee 		snd_soc_component_get_drvdata(component);
593a6e3f4f3SSteve Lee 
594a6e3f4f3SSteve Lee 	ucontrol->value.integer.value[0] = max98390->ambient_temp_value;
595a6e3f4f3SSteve Lee 
596a6e3f4f3SSteve Lee 	return 0;
597a6e3f4f3SSteve Lee }
598a6e3f4f3SSteve Lee 
599a6e3f4f3SSteve Lee static int max98390_adaptive_rdc_put(struct snd_kcontrol *kcontrol,
600a6e3f4f3SSteve Lee 		struct snd_ctl_elem_value *ucontrol)
601a6e3f4f3SSteve Lee {
602a6e3f4f3SSteve Lee 	struct snd_soc_component *component =
603a6e3f4f3SSteve Lee 		snd_soc_kcontrol_component(kcontrol);
604a6e3f4f3SSteve Lee 
605a6e3f4f3SSteve Lee 	dev_warn(component->dev, "Put adaptive rdc not supported\n");
606a6e3f4f3SSteve Lee 
607a6e3f4f3SSteve Lee 	return 0;
608a6e3f4f3SSteve Lee }
609a6e3f4f3SSteve Lee 
610a6e3f4f3SSteve Lee static int max98390_adaptive_rdc_get(struct snd_kcontrol *kcontrol,
611a6e3f4f3SSteve Lee 		struct snd_ctl_elem_value *ucontrol)
612a6e3f4f3SSteve Lee {
613a6e3f4f3SSteve Lee 	int rdc, rdc0;
614a6e3f4f3SSteve Lee 	struct snd_soc_component *component =
615a6e3f4f3SSteve Lee 		snd_soc_kcontrol_component(kcontrol);
616a6e3f4f3SSteve Lee 	struct max98390_priv *max98390 =
617a6e3f4f3SSteve Lee 		snd_soc_component_get_drvdata(component);
618a6e3f4f3SSteve Lee 
619a6e3f4f3SSteve Lee 	regmap_read(max98390->regmap, THERMAL_RDC_RD_BACK_BYTE1, &rdc);
620a6e3f4f3SSteve Lee 	regmap_read(max98390->regmap, THERMAL_RDC_RD_BACK_BYTE0, &rdc0);
621a6e3f4f3SSteve Lee 	ucontrol->value.integer.value[0] = rdc0 | rdc << 8;
622a6e3f4f3SSteve Lee 
623a6e3f4f3SSteve Lee 	return 0;
624a6e3f4f3SSteve Lee }
625a6e3f4f3SSteve Lee 
626a6e3f4f3SSteve Lee static int max98390_dsm_calib_get(struct snd_kcontrol *kcontrol,
627a6e3f4f3SSteve Lee 		struct snd_ctl_elem_value *ucontrol)
628a6e3f4f3SSteve Lee {
629a6e3f4f3SSteve Lee 	/* Do nothing */
630a6e3f4f3SSteve Lee 	return 0;
631a6e3f4f3SSteve Lee }
632a6e3f4f3SSteve Lee 
633a6e3f4f3SSteve Lee static int max98390_dsm_calib_put(struct snd_kcontrol *kcontrol,
634a6e3f4f3SSteve Lee 		struct snd_ctl_elem_value *ucontrol)
635a6e3f4f3SSteve Lee {
636*9dd28b46SPeter Ujfalusi 	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
637*9dd28b46SPeter Ujfalusi 	struct max98390_priv *max98390 = snd_soc_component_get_drvdata(component);
638*9dd28b46SPeter Ujfalusi 	struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component);
639*9dd28b46SPeter Ujfalusi 	unsigned int rdc, rdc_cal_result, rdc_integer, rdc_factor, temp, val;
640*9dd28b46SPeter Ujfalusi 
641*9dd28b46SPeter Ujfalusi 	snd_soc_dapm_mutex_lock(dapm);
642a6e3f4f3SSteve Lee 
6436ac24610SSteve Lee 	regmap_read(max98390->regmap, MAX98390_R23FF_GLOBAL_EN, &val);
644*9dd28b46SPeter Ujfalusi 	if (!val) {
645*9dd28b46SPeter Ujfalusi 		/* Enable the codec for the duration of calibration readout */
646*9dd28b46SPeter Ujfalusi 		regmap_update_bits(max98390->regmap, MAX98390_R203A_AMP_EN,
647*9dd28b46SPeter Ujfalusi 				   MAX98390_AMP_EN_MASK, 1);
648*9dd28b46SPeter Ujfalusi 		regmap_update_bits(max98390->regmap, MAX98390_R23FF_GLOBAL_EN,
649*9dd28b46SPeter Ujfalusi 				   MAX98390_GLOBAL_EN_MASK, 1);
6506ac24610SSteve Lee 	}
651a6e3f4f3SSteve Lee 
652*9dd28b46SPeter Ujfalusi 	regmap_read(max98390->regmap, THERMAL_RDC_RD_BACK_BYTE1, &rdc);
653*9dd28b46SPeter Ujfalusi 	regmap_read(max98390->regmap, THERMAL_RDC_RD_BACK_BYTE0, &rdc_cal_result);
654*9dd28b46SPeter Ujfalusi 	regmap_read(max98390->regmap, MAX98390_MEAS_ADC_CH2_READ, &temp);
655*9dd28b46SPeter Ujfalusi 
656*9dd28b46SPeter Ujfalusi 	if (!val) {
657*9dd28b46SPeter Ujfalusi 		/* Disable the codec if it was disabled */
658*9dd28b46SPeter Ujfalusi 		regmap_update_bits(max98390->regmap, MAX98390_R23FF_GLOBAL_EN,
659*9dd28b46SPeter Ujfalusi 				   MAX98390_GLOBAL_EN_MASK, 0);
660*9dd28b46SPeter Ujfalusi 		regmap_update_bits(max98390->regmap, MAX98390_R203A_AMP_EN,
661*9dd28b46SPeter Ujfalusi 				   MAX98390_AMP_EN_MASK, 0);
662*9dd28b46SPeter Ujfalusi 	}
663*9dd28b46SPeter Ujfalusi 
664*9dd28b46SPeter Ujfalusi 	snd_soc_dapm_mutex_unlock(dapm);
665*9dd28b46SPeter Ujfalusi 
666*9dd28b46SPeter Ujfalusi 	rdc_cal_result |= (rdc << 8) & 0x0000FFFF;
667*9dd28b46SPeter Ujfalusi 	if (rdc_cal_result)
668*9dd28b46SPeter Ujfalusi 		max98390->ref_rdc_value = 268435456U / rdc_cal_result;
669*9dd28b46SPeter Ujfalusi 
670*9dd28b46SPeter Ujfalusi 	max98390->ambient_temp_value = temp * 52 - 1188;
671*9dd28b46SPeter Ujfalusi 
672*9dd28b46SPeter Ujfalusi 	rdc_integer =  rdc_cal_result * 937  / 65536;
673*9dd28b46SPeter Ujfalusi 	rdc_factor = ((rdc_cal_result * 937 * 100) / 65536) - (rdc_integer * 100);
674*9dd28b46SPeter Ujfalusi 
675*9dd28b46SPeter Ujfalusi 	dev_info(component->dev,
676*9dd28b46SPeter Ujfalusi 		 "rdc resistance about %d.%02d ohm, reg=0x%X temp reg=0x%X\n",
677*9dd28b46SPeter Ujfalusi 		 rdc_integer, rdc_factor, rdc_cal_result, temp);
678*9dd28b46SPeter Ujfalusi 
679a6e3f4f3SSteve Lee 	return 0;
680a6e3f4f3SSteve Lee }
681a6e3f4f3SSteve Lee 
682a6e3f4f3SSteve Lee static const struct snd_kcontrol_new max98390_snd_controls[] = {
683a6e3f4f3SSteve Lee 	SOC_SINGLE_TLV("Digital Volume", DSM_VOL_CTRL,
684a6e3f4f3SSteve Lee 		0, 184, 0,
685a6e3f4f3SSteve Lee 		max98390_digital_tlv),
686a6e3f4f3SSteve Lee 	SOC_SINGLE_TLV("Speaker Volume", MAX98390_R203D_SPK_GAIN,
687a6e3f4f3SSteve Lee 		0, 6, 0,
688a6e3f4f3SSteve Lee 		max98390_spk_tlv),
689a6e3f4f3SSteve Lee 	SOC_SINGLE("Ramp Up Bypass Switch", MAX98390_R2039_AMP_DSP_CFG,
690a6e3f4f3SSteve Lee 		MAX98390_AMP_DSP_CFG_RMP_UP_SHIFT, 1, 0),
691a6e3f4f3SSteve Lee 	SOC_SINGLE("Ramp Down Bypass Switch", MAX98390_R2039_AMP_DSP_CFG,
692a6e3f4f3SSteve Lee 		MAX98390_AMP_DSP_CFG_RMP_DN_SHIFT, 1, 0),
693a6e3f4f3SSteve Lee 	SOC_SINGLE("Boost Clock Phase", MAX98390_BOOST_CTRL3,
694a6e3f4f3SSteve Lee 		MAX98390_BOOST_CLK_PHASE_CFG_SHIFT, 3, 0),
695a6e3f4f3SSteve Lee 	SOC_ENUM("Boost Output Voltage", max98390_boost_voltage),
696a6e3f4f3SSteve Lee 	SOC_ENUM("Current Limit", max98390_current_limit),
697a6e3f4f3SSteve Lee 	SOC_SINGLE_EXT("DSM Rdc", SND_SOC_NOPM, 0, 0xffffff, 0,
698a6e3f4f3SSteve Lee 		max98390_ref_rdc_get, max98390_ref_rdc_put),
699a6e3f4f3SSteve Lee 	SOC_SINGLE_EXT("DSM Ambient Temp", SND_SOC_NOPM, 0, 0xffff, 0,
700a6e3f4f3SSteve Lee 		max98390_ambient_temp_get, max98390_ambient_temp_put),
701a6e3f4f3SSteve Lee 	SOC_SINGLE_EXT("DSM Adaptive Rdc", SND_SOC_NOPM, 0, 0xffff, 0,
702a6e3f4f3SSteve Lee 		max98390_adaptive_rdc_get, max98390_adaptive_rdc_put),
703a6e3f4f3SSteve Lee 	SOC_SINGLE_EXT("DSM Calibration", SND_SOC_NOPM, 0, 1, 0,
704a6e3f4f3SSteve Lee 		max98390_dsm_calib_get, max98390_dsm_calib_put),
705a6e3f4f3SSteve Lee };
706a6e3f4f3SSteve Lee 
707a6e3f4f3SSteve Lee static const struct soc_enum dai_sel_enum =
708a6e3f4f3SSteve Lee 	SOC_ENUM_SINGLE(MAX98390_PCM_CH_SRC_1,
709a6e3f4f3SSteve Lee 		MAX98390_PCM_RX_CH_SRC_SHIFT,
710a6e3f4f3SSteve Lee 		3, max98390_switch_text);
711a6e3f4f3SSteve Lee 
712a6e3f4f3SSteve Lee static const struct snd_kcontrol_new max98390_dai_controls =
713a6e3f4f3SSteve Lee 	SOC_DAPM_ENUM("DAI Sel", dai_sel_enum);
714a6e3f4f3SSteve Lee 
715a6e3f4f3SSteve Lee static const struct snd_soc_dapm_widget max98390_dapm_widgets[] = {
716a6e3f4f3SSteve Lee 	SND_SOC_DAPM_DAC_E("Amp Enable", "HiFi Playback",
717dc5fb6d2SSteve Lee 		SND_SOC_NOPM, 0, 0, max98390_dac_event,
718a6e3f4f3SSteve Lee 		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
719a6e3f4f3SSteve Lee 	SND_SOC_DAPM_MUX("DAI Sel Mux", SND_SOC_NOPM, 0, 0,
720a6e3f4f3SSteve Lee 		&max98390_dai_controls),
721a6e3f4f3SSteve Lee 	SND_SOC_DAPM_OUTPUT("BE_OUT"),
722a6e3f4f3SSteve Lee };
723a6e3f4f3SSteve Lee 
724a6e3f4f3SSteve Lee static const struct snd_soc_dapm_route max98390_audio_map[] = {
725a6e3f4f3SSteve Lee 	/* Plabyack */
726a6e3f4f3SSteve Lee 	{"DAI Sel Mux", "Left", "Amp Enable"},
727a6e3f4f3SSteve Lee 	{"DAI Sel Mux", "Right", "Amp Enable"},
728a6e3f4f3SSteve Lee 	{"DAI Sel Mux", "LeftRight", "Amp Enable"},
729a6e3f4f3SSteve Lee 	{"BE_OUT", NULL, "DAI Sel Mux"},
730a6e3f4f3SSteve Lee };
731a6e3f4f3SSteve Lee 
732a6e3f4f3SSteve Lee static bool max98390_readable_register(struct device *dev, unsigned int reg)
733a6e3f4f3SSteve Lee {
734a6e3f4f3SSteve Lee 	switch (reg) {
735a6e3f4f3SSteve Lee 	case MAX98390_SOFTWARE_RESET ... MAX98390_INT_EN3:
736a6e3f4f3SSteve Lee 	case MAX98390_IRQ_CTRL ... MAX98390_WDOG_CTRL:
737a6e3f4f3SSteve Lee 	case MAX98390_MEAS_ADC_THERM_WARN_THRESH
738a6e3f4f3SSteve Lee 		... MAX98390_BROWNOUT_INFINITE_HOLD:
7394008b29eSSteve Lee 	case MAX98390_BROWNOUT_LVL_HOLD ... DSMIG_DEBUZZER_THRESHOLD:
7404008b29eSSteve Lee 	case DSM_VOL_ENA ... MAX98390_R24FF_REV_ID:
741a6e3f4f3SSteve Lee 		return true;
742a6e3f4f3SSteve Lee 	default:
743a6e3f4f3SSteve Lee 		return false;
744a6e3f4f3SSteve Lee 	}
745a6e3f4f3SSteve Lee };
746a6e3f4f3SSteve Lee 
747a6e3f4f3SSteve Lee static bool max98390_volatile_reg(struct device *dev, unsigned int reg)
748a6e3f4f3SSteve Lee {
749a6e3f4f3SSteve Lee 	switch (reg) {
750a6e3f4f3SSteve Lee 	case MAX98390_SOFTWARE_RESET ... MAX98390_INT_EN3:
751a6e3f4f3SSteve Lee 	case MAX98390_MEAS_ADC_CH0_READ ... MAX98390_MEAS_ADC_CH2_READ:
752a6e3f4f3SSteve Lee 	case MAX98390_PWR_GATE_STATUS ... MAX98390_BROWNOUT_STATUS:
753a6e3f4f3SSteve Lee 	case MAX98390_BROWNOUT_LOWEST_STATUS:
754a6e3f4f3SSteve Lee 	case MAX98390_ENV_TRACK_BOOST_VOUT_READ:
755a6e3f4f3SSteve Lee 	case DSM_STBASS_HPF_B0_BYTE0 ... DSM_DEBUZZER_ATTACK_TIME_BYTE2:
7564008b29eSSteve Lee 	case THERMAL_RDC_RD_BACK_BYTE1 ... DSMIG_DEBUZZER_THRESHOLD:
757a6e3f4f3SSteve Lee 	case DSM_THERMAL_GAIN ... DSM_WBDRC_GAIN:
758a6e3f4f3SSteve Lee 		return true;
759a6e3f4f3SSteve Lee 	default:
760a6e3f4f3SSteve Lee 		return false;
761a6e3f4f3SSteve Lee 	}
762a6e3f4f3SSteve Lee }
763a6e3f4f3SSteve Lee 
764a6e3f4f3SSteve Lee #define MAX98390_RATES SNDRV_PCM_RATE_8000_48000
765a6e3f4f3SSteve Lee 
766a6e3f4f3SSteve Lee #define MAX98390_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \
767a6e3f4f3SSteve Lee 	SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
768a6e3f4f3SSteve Lee 
769a6e3f4f3SSteve Lee static struct snd_soc_dai_driver max98390_dai[] = {
770a6e3f4f3SSteve Lee 	{
771a6e3f4f3SSteve Lee 		.name = "max98390-aif1",
772a6e3f4f3SSteve Lee 		.playback = {
773a6e3f4f3SSteve Lee 			.stream_name = "HiFi Playback",
774a6e3f4f3SSteve Lee 			.channels_min = 1,
775a6e3f4f3SSteve Lee 			.channels_max = 2,
776a6e3f4f3SSteve Lee 			.rates = MAX98390_RATES,
777a6e3f4f3SSteve Lee 			.formats = MAX98390_FORMATS,
778a6e3f4f3SSteve Lee 		},
779a6e3f4f3SSteve Lee 		.capture = {
780a6e3f4f3SSteve Lee 			.stream_name = "HiFi Capture",
781a6e3f4f3SSteve Lee 			.channels_min = 1,
782a6e3f4f3SSteve Lee 			.channels_max = 2,
783a6e3f4f3SSteve Lee 			.rates = MAX98390_RATES,
784a6e3f4f3SSteve Lee 			.formats = MAX98390_FORMATS,
785a6e3f4f3SSteve Lee 		},
786a6e3f4f3SSteve Lee 		.ops = &max98390_dai_ops,
787a6e3f4f3SSteve Lee 	}
788a6e3f4f3SSteve Lee };
789a6e3f4f3SSteve Lee 
790a6e3f4f3SSteve Lee static int max98390_dsm_init(struct snd_soc_component *component)
791a6e3f4f3SSteve Lee {
792a6e3f4f3SSteve Lee 	int ret;
79397ed3e50SSteve Lee 	int param_size, param_start_addr;
794a6e3f4f3SSteve Lee 	char filename[128];
795a6e3f4f3SSteve Lee 	const char *vendor, *product;
796a6e3f4f3SSteve Lee 	struct max98390_priv *max98390 =
797a6e3f4f3SSteve Lee 		snd_soc_component_get_drvdata(component);
798a6e3f4f3SSteve Lee 	const struct firmware *fw;
799a6e3f4f3SSteve Lee 	char *dsm_param;
800a6e3f4f3SSteve Lee 
801a6e3f4f3SSteve Lee 	vendor = dmi_get_system_info(DMI_SYS_VENDOR);
802a6e3f4f3SSteve Lee 	product = dmi_get_system_info(DMI_PRODUCT_NAME);
803a6e3f4f3SSteve Lee 
804a10facb7SSteve Lee 	if (!strcmp(max98390->dsm_param_name, "default")) {
805a6e3f4f3SSteve Lee 		if (vendor && product) {
806a10facb7SSteve Lee 			snprintf(filename, sizeof(filename),
807a10facb7SSteve Lee 				"dsm_param_%s_%s.bin", vendor, product);
808a6e3f4f3SSteve Lee 		} else {
809a6e3f4f3SSteve Lee 			sprintf(filename, "dsm_param.bin");
810a6e3f4f3SSteve Lee 		}
811a10facb7SSteve Lee 	} else {
812a10facb7SSteve Lee 		snprintf(filename, sizeof(filename), "%s",
813a10facb7SSteve Lee 			max98390->dsm_param_name);
814a10facb7SSteve Lee 	}
815a6e3f4f3SSteve Lee 	ret = request_firmware(&fw, filename, component->dev);
816a6e3f4f3SSteve Lee 	if (ret) {
817a6e3f4f3SSteve Lee 		ret = request_firmware(&fw, "dsm_param.bin", component->dev);
818a10facb7SSteve Lee 		if (ret) {
819a10facb7SSteve Lee 			ret = request_firmware(&fw, "dsmparam.bin",
820a10facb7SSteve Lee 				component->dev);
821a6e3f4f3SSteve Lee 			if (ret)
822a6e3f4f3SSteve Lee 				goto err;
823a6e3f4f3SSteve Lee 		}
824a10facb7SSteve Lee 	}
825a6e3f4f3SSteve Lee 
826a6e3f4f3SSteve Lee 	dev_dbg(component->dev,
827678916ecSTakashi Iwai 		"max98390: param fw size %zd\n",
828a6e3f4f3SSteve Lee 		fw->size);
82997ed3e50SSteve Lee 	if (fw->size < MAX98390_DSM_PARAM_MIN_SIZE) {
83097ed3e50SSteve Lee 		dev_err(component->dev,
83197ed3e50SSteve Lee 			"param fw is invalid.\n");
8323cea33b6SDan Carpenter 		ret = -EINVAL;
83397ed3e50SSteve Lee 		goto err_alloc;
83497ed3e50SSteve Lee 	}
835a6e3f4f3SSteve Lee 	dsm_param = (char *)fw->data;
83697ed3e50SSteve Lee 	param_start_addr = (dsm_param[0] & 0xff) | (dsm_param[1] & 0xff) << 8;
83797ed3e50SSteve Lee 	param_size = (dsm_param[2] & 0xff) | (dsm_param[3] & 0xff) << 8;
83897ed3e50SSteve Lee 	if (param_size > MAX98390_DSM_PARAM_MAX_SIZE ||
839aa785705SSteve Lee 		param_start_addr < MAX98390_IRQ_CTRL ||
84097ed3e50SSteve Lee 		fw->size < param_size + MAX98390_DSM_PAYLOAD_OFFSET) {
84197ed3e50SSteve Lee 		dev_err(component->dev,
84297ed3e50SSteve Lee 			"param fw is invalid.\n");
8433cea33b6SDan Carpenter 		ret = -EINVAL;
84497ed3e50SSteve Lee 		goto err_alloc;
84597ed3e50SSteve Lee 	}
84697ed3e50SSteve Lee 	regmap_write(max98390->regmap, MAX98390_R203A_AMP_EN, 0x80);
847a6e3f4f3SSteve Lee 	dsm_param += MAX98390_DSM_PAYLOAD_OFFSET;
84897ed3e50SSteve Lee 	regmap_bulk_write(max98390->regmap, param_start_addr,
84997ed3e50SSteve Lee 		dsm_param, param_size);
850a6e3f4f3SSteve Lee 	regmap_write(max98390->regmap, MAX98390_R23E1_DSP_GLOBAL_EN, 0x01);
851a6e3f4f3SSteve Lee 
85297ed3e50SSteve Lee err_alloc:
85397ed3e50SSteve Lee 	release_firmware(fw);
854a6e3f4f3SSteve Lee err:
855a6e3f4f3SSteve Lee 	return ret;
856a6e3f4f3SSteve Lee }
857a6e3f4f3SSteve Lee 
8589ba4af79SSteve Lee static void max98390_init_regs(struct snd_soc_component *component)
8599ba4af79SSteve Lee {
8609ba4af79SSteve Lee 	struct max98390_priv *max98390 =
8619ba4af79SSteve Lee 		snd_soc_component_get_drvdata(component);
8629ba4af79SSteve Lee 
8639ba4af79SSteve Lee 	regmap_write(max98390->regmap, MAX98390_CLK_MON, 0x6f);
8649ba4af79SSteve Lee 	regmap_write(max98390->regmap, MAX98390_DAT_MON, 0x00);
8659ba4af79SSteve Lee 	regmap_write(max98390->regmap, MAX98390_PWR_GATE_CTL, 0x00);
8669ba4af79SSteve Lee 	regmap_write(max98390->regmap, MAX98390_PCM_RX_EN_A, 0x03);
8679ba4af79SSteve Lee 	regmap_write(max98390->regmap, MAX98390_ENV_TRACK_VOUT_HEADROOM, 0x0e);
8689ba4af79SSteve Lee 	regmap_write(max98390->regmap, MAX98390_BOOST_BYPASS1, 0x46);
8699ba4af79SSteve Lee 	regmap_write(max98390->regmap, MAX98390_FET_SCALING3, 0x03);
870e5870bd0SSteve Lee 
871e5870bd0SSteve Lee 	/* voltage, current slot configuration */
872e5870bd0SSteve Lee 	regmap_write(max98390->regmap,
873e5870bd0SSteve Lee 		MAX98390_PCM_CH_SRC_2,
874e5870bd0SSteve Lee 		(max98390->i_l_slot << 4 |
875e5870bd0SSteve Lee 		max98390->v_l_slot)&0xFF);
876e5870bd0SSteve Lee 
877e5870bd0SSteve Lee 	if (max98390->v_l_slot < 8) {
878e5870bd0SSteve Lee 		regmap_update_bits(max98390->regmap,
879e5870bd0SSteve Lee 			MAX98390_PCM_TX_HIZ_CTRL_A,
880e5870bd0SSteve Lee 			1 << max98390->v_l_slot, 0);
881e5870bd0SSteve Lee 		regmap_update_bits(max98390->regmap,
882e5870bd0SSteve Lee 			MAX98390_PCM_TX_EN_A,
883e5870bd0SSteve Lee 			1 << max98390->v_l_slot,
884e5870bd0SSteve Lee 			1 << max98390->v_l_slot);
885e5870bd0SSteve Lee 	} else {
886e5870bd0SSteve Lee 		regmap_update_bits(max98390->regmap,
887e5870bd0SSteve Lee 			MAX98390_PCM_TX_HIZ_CTRL_B,
888e5870bd0SSteve Lee 			1 << (max98390->v_l_slot - 8), 0);
889e5870bd0SSteve Lee 		regmap_update_bits(max98390->regmap,
890e5870bd0SSteve Lee 			MAX98390_PCM_TX_EN_B,
891e5870bd0SSteve Lee 			1 << (max98390->v_l_slot - 8),
892e5870bd0SSteve Lee 			1 << (max98390->v_l_slot - 8));
893e5870bd0SSteve Lee 	}
894e5870bd0SSteve Lee 
895e5870bd0SSteve Lee 	if (max98390->i_l_slot < 8) {
896e5870bd0SSteve Lee 		regmap_update_bits(max98390->regmap,
897e5870bd0SSteve Lee 			MAX98390_PCM_TX_HIZ_CTRL_A,
898e5870bd0SSteve Lee 			1 << max98390->i_l_slot, 0);
899e5870bd0SSteve Lee 		regmap_update_bits(max98390->regmap,
900e5870bd0SSteve Lee 			MAX98390_PCM_TX_EN_A,
901e5870bd0SSteve Lee 			1 << max98390->i_l_slot,
902e5870bd0SSteve Lee 			1 << max98390->i_l_slot);
903e5870bd0SSteve Lee 	} else {
904e5870bd0SSteve Lee 		regmap_update_bits(max98390->regmap,
905e5870bd0SSteve Lee 			MAX98390_PCM_TX_HIZ_CTRL_B,
906e5870bd0SSteve Lee 			1 << (max98390->i_l_slot - 8), 0);
907e5870bd0SSteve Lee 		regmap_update_bits(max98390->regmap,
908e5870bd0SSteve Lee 			MAX98390_PCM_TX_EN_B,
909e5870bd0SSteve Lee 			1 << (max98390->i_l_slot - 8),
910e5870bd0SSteve Lee 			1 << (max98390->i_l_slot - 8));
911e5870bd0SSteve Lee 	}
9129ba4af79SSteve Lee }
9139ba4af79SSteve Lee 
914a6e3f4f3SSteve Lee static int max98390_probe(struct snd_soc_component *component)
915a6e3f4f3SSteve Lee {
916a6e3f4f3SSteve Lee 	struct max98390_priv *max98390 =
917a6e3f4f3SSteve Lee 		snd_soc_component_get_drvdata(component);
918a6e3f4f3SSteve Lee 
919a6e3f4f3SSteve Lee 	regmap_write(max98390->regmap, MAX98390_SOFTWARE_RESET, 0x01);
920a6e3f4f3SSteve Lee 	/* Sleep reset settle time */
921a6e3f4f3SSteve Lee 	msleep(20);
922a6e3f4f3SSteve Lee 
9239ba4af79SSteve Lee 	/* Amp init setting */
9249ba4af79SSteve Lee 	max98390_init_regs(component);
925aa785705SSteve Lee 	/* Update dsm bin param */
926aa785705SSteve Lee 	max98390_dsm_init(component);
927a6e3f4f3SSteve Lee 
928a6e3f4f3SSteve Lee 	/* Dsm Setting */
929a6e3f4f3SSteve Lee 	if (max98390->ref_rdc_value) {
930a6e3f4f3SSteve Lee 		regmap_write(max98390->regmap, DSM_TPROT_RECIP_RDC_ROOM_BYTE0,
931a6e3f4f3SSteve Lee 			max98390->ref_rdc_value & 0x000000ff);
932a6e3f4f3SSteve Lee 		regmap_write(max98390->regmap, DSM_TPROT_RECIP_RDC_ROOM_BYTE1,
933a6e3f4f3SSteve Lee 			(max98390->ref_rdc_value >> 8) & 0x000000ff);
934a6e3f4f3SSteve Lee 		regmap_write(max98390->regmap, DSM_TPROT_RECIP_RDC_ROOM_BYTE2,
935a6e3f4f3SSteve Lee 			(max98390->ref_rdc_value >> 16) & 0x000000ff);
936a6e3f4f3SSteve Lee 	}
937a6e3f4f3SSteve Lee 	if (max98390->ambient_temp_value) {
938a6e3f4f3SSteve Lee 		regmap_write(max98390->regmap, DSM_TPROT_ROOM_TEMPERATURE_BYTE1,
939a6e3f4f3SSteve Lee 			(max98390->ambient_temp_value >> 8) & 0x000000ff);
940a6e3f4f3SSteve Lee 		regmap_write(max98390->regmap, DSM_TPROT_ROOM_TEMPERATURE_BYTE0,
941a6e3f4f3SSteve Lee 			(max98390->ambient_temp_value) & 0x000000ff);
942a6e3f4f3SSteve Lee 	}
943a6e3f4f3SSteve Lee 
944a6e3f4f3SSteve Lee 	return 0;
945a6e3f4f3SSteve Lee }
946a6e3f4f3SSteve Lee 
947a6e3f4f3SSteve Lee #ifdef CONFIG_PM_SLEEP
948a6e3f4f3SSteve Lee static int max98390_suspend(struct device *dev)
949a6e3f4f3SSteve Lee {
950a6e3f4f3SSteve Lee 	struct max98390_priv *max98390 = dev_get_drvdata(dev);
951a6e3f4f3SSteve Lee 
952a6e3f4f3SSteve Lee 	dev_dbg(dev, "%s:Enter\n", __func__);
953a6e3f4f3SSteve Lee 
954a6e3f4f3SSteve Lee 	regcache_cache_only(max98390->regmap, true);
955a6e3f4f3SSteve Lee 	regcache_mark_dirty(max98390->regmap);
956a6e3f4f3SSteve Lee 
957a6e3f4f3SSteve Lee 	return 0;
958a6e3f4f3SSteve Lee }
959a6e3f4f3SSteve Lee 
960a6e3f4f3SSteve Lee static int max98390_resume(struct device *dev)
961a6e3f4f3SSteve Lee {
962a6e3f4f3SSteve Lee 	struct max98390_priv *max98390 = dev_get_drvdata(dev);
963a6e3f4f3SSteve Lee 
964a6e3f4f3SSteve Lee 	dev_dbg(dev, "%s:Enter\n", __func__);
965a6e3f4f3SSteve Lee 
966a6e3f4f3SSteve Lee 	regcache_cache_only(max98390->regmap, false);
967a6e3f4f3SSteve Lee 	regcache_sync(max98390->regmap);
968a6e3f4f3SSteve Lee 
969a6e3f4f3SSteve Lee 	return 0;
970a6e3f4f3SSteve Lee }
971a6e3f4f3SSteve Lee #endif
972a6e3f4f3SSteve Lee 
973a6e3f4f3SSteve Lee static const struct dev_pm_ops max98390_pm = {
974a6e3f4f3SSteve Lee 	SET_SYSTEM_SLEEP_PM_OPS(max98390_suspend, max98390_resume)
975a6e3f4f3SSteve Lee };
976a6e3f4f3SSteve Lee 
977a6e3f4f3SSteve Lee static const struct snd_soc_component_driver soc_codec_dev_max98390 = {
978a6e3f4f3SSteve Lee 	.probe			= max98390_probe,
979a6e3f4f3SSteve Lee 	.controls		= max98390_snd_controls,
980a6e3f4f3SSteve Lee 	.num_controls		= ARRAY_SIZE(max98390_snd_controls),
981a6e3f4f3SSteve Lee 	.dapm_widgets		= max98390_dapm_widgets,
982a6e3f4f3SSteve Lee 	.num_dapm_widgets	= ARRAY_SIZE(max98390_dapm_widgets),
983a6e3f4f3SSteve Lee 	.dapm_routes		= max98390_audio_map,
984a6e3f4f3SSteve Lee 	.num_dapm_routes	= ARRAY_SIZE(max98390_audio_map),
985a6e3f4f3SSteve Lee 	.idle_bias_on		= 1,
986a6e3f4f3SSteve Lee 	.use_pmdown_time	= 1,
987a6e3f4f3SSteve Lee 	.endianness		= 1,
988a6e3f4f3SSteve Lee };
989a6e3f4f3SSteve Lee 
990a6e3f4f3SSteve Lee static const struct regmap_config max98390_regmap = {
991a6e3f4f3SSteve Lee 	.reg_bits         = 16,
992a6e3f4f3SSteve Lee 	.val_bits         = 8,
993a6e3f4f3SSteve Lee 	.max_register     = MAX98390_R24FF_REV_ID,
994a6e3f4f3SSteve Lee 	.reg_defaults     = max98390_reg_defaults,
995a6e3f4f3SSteve Lee 	.num_reg_defaults = ARRAY_SIZE(max98390_reg_defaults),
996a6e3f4f3SSteve Lee 	.readable_reg	  = max98390_readable_register,
997a6e3f4f3SSteve Lee 	.volatile_reg	  = max98390_volatile_reg,
998a6e3f4f3SSteve Lee 	.cache_type       = REGCACHE_RBTREE,
999a6e3f4f3SSteve Lee };
1000a6e3f4f3SSteve Lee 
1001e5870bd0SSteve Lee static void max98390_slot_config(struct i2c_client *i2c,
1002e5870bd0SSteve Lee 	struct max98390_priv *max98390)
1003e5870bd0SSteve Lee {
1004e5870bd0SSteve Lee 	int value;
1005e5870bd0SSteve Lee 	struct device *dev = &i2c->dev;
1006e5870bd0SSteve Lee 
1007e5870bd0SSteve Lee 	if (!device_property_read_u32(dev, "maxim,vmon-slot-no", &value))
1008e5870bd0SSteve Lee 		max98390->v_l_slot = value & 0xF;
1009e5870bd0SSteve Lee 	else
1010e5870bd0SSteve Lee 		max98390->v_l_slot = 0;
1011e5870bd0SSteve Lee 
1012e5870bd0SSteve Lee 	if (!device_property_read_u32(dev, "maxim,imon-slot-no", &value))
1013e5870bd0SSteve Lee 		max98390->i_l_slot = value & 0xF;
1014e5870bd0SSteve Lee 	else
1015e5870bd0SSteve Lee 		max98390->i_l_slot = 1;
1016e5870bd0SSteve Lee }
1017e5870bd0SSteve Lee 
1018fead49e3SStephen Kitt static int max98390_i2c_probe(struct i2c_client *i2c)
1019a6e3f4f3SSteve Lee {
1020a6e3f4f3SSteve Lee 	int ret = 0;
1021a6e3f4f3SSteve Lee 	int reg = 0;
1022a6e3f4f3SSteve Lee 
1023a6e3f4f3SSteve Lee 	struct max98390_priv *max98390 = NULL;
10240f9a84b2SWolfram Sang 	struct i2c_adapter *adapter = i2c->adapter;
1025397ff024SSteve Lee 	struct gpio_desc *reset_gpio;
1026a6e3f4f3SSteve Lee 
1027a6e3f4f3SSteve Lee 	ret = i2c_check_functionality(adapter,
1028a6e3f4f3SSteve Lee 		I2C_FUNC_SMBUS_BYTE
1029a6e3f4f3SSteve Lee 		| I2C_FUNC_SMBUS_BYTE_DATA);
1030a6e3f4f3SSteve Lee 	if (!ret) {
1031a6e3f4f3SSteve Lee 		dev_err(&i2c->dev, "I2C check functionality failed\n");
1032a6e3f4f3SSteve Lee 		return -ENXIO;
1033a6e3f4f3SSteve Lee 	}
1034a6e3f4f3SSteve Lee 
1035a6e3f4f3SSteve Lee 	max98390 = devm_kzalloc(&i2c->dev, sizeof(*max98390), GFP_KERNEL);
1036a6e3f4f3SSteve Lee 	if (!max98390) {
1037a6e3f4f3SSteve Lee 		ret = -ENOMEM;
1038a6e3f4f3SSteve Lee 		return ret;
1039a6e3f4f3SSteve Lee 	}
1040a6e3f4f3SSteve Lee 	i2c_set_clientdata(i2c, max98390);
1041a6e3f4f3SSteve Lee 
1042a6e3f4f3SSteve Lee 	ret = device_property_read_u32(&i2c->dev, "maxim,temperature_calib",
1043a6e3f4f3SSteve Lee 				       &max98390->ambient_temp_value);
1044a6e3f4f3SSteve Lee 	if (ret) {
1045a6e3f4f3SSteve Lee 		dev_info(&i2c->dev,
1046a6e3f4f3SSteve Lee 			 "no optional property 'temperature_calib' found, default:\n");
1047a6e3f4f3SSteve Lee 	}
1048a6e3f4f3SSteve Lee 	ret = device_property_read_u32(&i2c->dev, "maxim,r0_calib",
1049a6e3f4f3SSteve Lee 				       &max98390->ref_rdc_value);
1050a6e3f4f3SSteve Lee 	if (ret) {
1051a6e3f4f3SSteve Lee 		dev_info(&i2c->dev,
1052a6e3f4f3SSteve Lee 			 "no optional property 'r0_calib' found, default:\n");
1053a6e3f4f3SSteve Lee 	}
1054a6e3f4f3SSteve Lee 
1055a6e3f4f3SSteve Lee 	dev_info(&i2c->dev,
1056a6e3f4f3SSteve Lee 		"%s: r0_calib: 0x%x,temperature_calib: 0x%x",
1057a6e3f4f3SSteve Lee 		__func__, max98390->ref_rdc_value,
1058a6e3f4f3SSteve Lee 		max98390->ambient_temp_value);
1059a6e3f4f3SSteve Lee 
1060a10facb7SSteve Lee 	ret = device_property_read_string(&i2c->dev, "maxim,dsm_param_name",
1061a10facb7SSteve Lee 				       &max98390->dsm_param_name);
1062a10facb7SSteve Lee 	if (ret)
1063a10facb7SSteve Lee 		max98390->dsm_param_name = "default";
1064a10facb7SSteve Lee 
1065e5870bd0SSteve Lee 	/* voltage/current slot configuration */
1066e5870bd0SSteve Lee 	max98390_slot_config(i2c, max98390);
1067e5870bd0SSteve Lee 
1068a6e3f4f3SSteve Lee 	/* regmap initialization */
1069a6e3f4f3SSteve Lee 	max98390->regmap = devm_regmap_init_i2c(i2c, &max98390_regmap);
1070a6e3f4f3SSteve Lee 	if (IS_ERR(max98390->regmap)) {
1071a6e3f4f3SSteve Lee 		ret = PTR_ERR(max98390->regmap);
1072a6e3f4f3SSteve Lee 		dev_err(&i2c->dev,
1073a6e3f4f3SSteve Lee 			"Failed to allocate regmap: %d\n", ret);
1074a6e3f4f3SSteve Lee 		return ret;
1075a6e3f4f3SSteve Lee 	}
1076a6e3f4f3SSteve Lee 
1077397ff024SSteve Lee 	reset_gpio = devm_gpiod_get_optional(&i2c->dev,
1078397ff024SSteve Lee 					     "reset", GPIOD_OUT_HIGH);
1079397ff024SSteve Lee 
1080397ff024SSteve Lee 	/* Power on device */
1081397ff024SSteve Lee 	if (reset_gpio) {
1082397ff024SSteve Lee 		usleep_range(1000, 2000);
1083397ff024SSteve Lee 		/* bring out of reset */
1084397ff024SSteve Lee 		gpiod_set_value_cansleep(reset_gpio, 0);
1085397ff024SSteve Lee 		usleep_range(1000, 2000);
1086397ff024SSteve Lee 	}
1087397ff024SSteve Lee 
1088a6e3f4f3SSteve Lee 	/* Check Revision ID */
1089a6e3f4f3SSteve Lee 	ret = regmap_read(max98390->regmap,
1090a6e3f4f3SSteve Lee 		MAX98390_R24FF_REV_ID, &reg);
1091a6e3f4f3SSteve Lee 	if (ret) {
1092a6e3f4f3SSteve Lee 		dev_err(&i2c->dev,
1093a6e3f4f3SSteve Lee 			"ret=%d, Failed to read: 0x%02X\n",
1094a6e3f4f3SSteve Lee 			ret, MAX98390_R24FF_REV_ID);
1095a6e3f4f3SSteve Lee 		return ret;
1096a6e3f4f3SSteve Lee 	}
1097a6e3f4f3SSteve Lee 	dev_info(&i2c->dev, "MAX98390 revisionID: 0x%02X\n", reg);
1098a6e3f4f3SSteve Lee 
1099a6e3f4f3SSteve Lee 	ret = devm_snd_soc_register_component(&i2c->dev,
1100a6e3f4f3SSteve Lee 			&soc_codec_dev_max98390,
1101a6e3f4f3SSteve Lee 			max98390_dai, ARRAY_SIZE(max98390_dai));
1102a6e3f4f3SSteve Lee 
1103a6e3f4f3SSteve Lee 	return ret;
1104a6e3f4f3SSteve Lee }
1105a6e3f4f3SSteve Lee 
1106a6e3f4f3SSteve Lee static const struct i2c_device_id max98390_i2c_id[] = {
1107a6e3f4f3SSteve Lee 	{ "max98390", 0},
1108a6e3f4f3SSteve Lee 	{},
1109a6e3f4f3SSteve Lee };
1110a6e3f4f3SSteve Lee 
1111a6e3f4f3SSteve Lee MODULE_DEVICE_TABLE(i2c, max98390_i2c_id);
1112a6e3f4f3SSteve Lee 
1113a6e3f4f3SSteve Lee #if defined(CONFIG_OF)
1114a6e3f4f3SSteve Lee static const struct of_device_id max98390_of_match[] = {
1115a6e3f4f3SSteve Lee 	{ .compatible = "maxim,max98390", },
1116a6e3f4f3SSteve Lee 	{}
1117a6e3f4f3SSteve Lee };
1118a6e3f4f3SSteve Lee MODULE_DEVICE_TABLE(of, max98390_of_match);
1119a6e3f4f3SSteve Lee #endif
1120a6e3f4f3SSteve Lee 
1121a6e3f4f3SSteve Lee #ifdef CONFIG_ACPI
1122a6e3f4f3SSteve Lee static const struct acpi_device_id max98390_acpi_match[] = {
1123a6e3f4f3SSteve Lee 	{ "MX98390", 0 },
1124a6e3f4f3SSteve Lee 	{},
1125a6e3f4f3SSteve Lee };
1126a6e3f4f3SSteve Lee MODULE_DEVICE_TABLE(acpi, max98390_acpi_match);
1127a6e3f4f3SSteve Lee #endif
1128a6e3f4f3SSteve Lee 
1129a6e3f4f3SSteve Lee static struct i2c_driver max98390_i2c_driver = {
1130a6e3f4f3SSteve Lee 	.driver = {
1131a6e3f4f3SSteve Lee 		.name = "max98390",
1132a6e3f4f3SSteve Lee 		.of_match_table = of_match_ptr(max98390_of_match),
1133a6e3f4f3SSteve Lee 		.acpi_match_table = ACPI_PTR(max98390_acpi_match),
1134a6e3f4f3SSteve Lee 		.pm = &max98390_pm,
1135a6e3f4f3SSteve Lee 	},
1136fead49e3SStephen Kitt 	.probe_new = max98390_i2c_probe,
1137a6e3f4f3SSteve Lee 	.id_table = max98390_i2c_id,
1138a6e3f4f3SSteve Lee };
1139a6e3f4f3SSteve Lee 
1140a6e3f4f3SSteve Lee module_i2c_driver(max98390_i2c_driver)
1141a6e3f4f3SSteve Lee 
1142a6e3f4f3SSteve Lee MODULE_DESCRIPTION("ALSA SoC MAX98390 driver");
1143a6e3f4f3SSteve Lee MODULE_AUTHOR("Steve Lee <steves.lee@maximintegrated.com>");
1144a6e3f4f3SSteve Lee MODULE_LICENSE("GPL");
1145