xref: /linux/sound/soc/codecs/max98390.c (revision 3cea33b6f2d7782d1be17c71509986f33ee93541)
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>
13a6e3f4f3SSteve Lee #include <linux/gpio.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_dsm_calibrate(struct snd_soc_component *component);
165a6e3f4f3SSteve Lee 
166a6e3f4f3SSteve Lee static int max98390_dai_set_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
167a6e3f4f3SSteve Lee {
168a6e3f4f3SSteve Lee 	struct snd_soc_component *component = codec_dai->component;
169a6e3f4f3SSteve Lee 	struct max98390_priv *max98390 =
170a6e3f4f3SSteve Lee 		snd_soc_component_get_drvdata(component);
171a6e3f4f3SSteve Lee 	unsigned int mode;
172a6e3f4f3SSteve Lee 	unsigned int format;
173a6e3f4f3SSteve Lee 	unsigned int invert = 0;
174a6e3f4f3SSteve Lee 
175a6e3f4f3SSteve Lee 	dev_dbg(component->dev, "%s: fmt 0x%08X\n", __func__, fmt);
176a6e3f4f3SSteve Lee 
177a6e3f4f3SSteve Lee 	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
178a6e3f4f3SSteve Lee 	case SND_SOC_DAIFMT_CBS_CFS:
179a6e3f4f3SSteve Lee 		mode = MAX98390_PCM_MASTER_MODE_SLAVE;
180a6e3f4f3SSteve Lee 		break;
181a6e3f4f3SSteve Lee 	case SND_SOC_DAIFMT_CBM_CFM:
182a6e3f4f3SSteve Lee 		max98390->master = true;
183a6e3f4f3SSteve Lee 		mode = MAX98390_PCM_MASTER_MODE_MASTER;
184a6e3f4f3SSteve Lee 		break;
185a6e3f4f3SSteve Lee 	default:
186a6e3f4f3SSteve Lee 		dev_err(component->dev, "DAI clock mode unsupported\n");
187a6e3f4f3SSteve Lee 		return -EINVAL;
188a6e3f4f3SSteve Lee 	}
189a6e3f4f3SSteve Lee 
190a6e3f4f3SSteve Lee 	regmap_update_bits(max98390->regmap,
191a6e3f4f3SSteve Lee 		MAX98390_PCM_MASTER_MODE,
192a6e3f4f3SSteve Lee 		MAX98390_PCM_MASTER_MODE_MASK,
193a6e3f4f3SSteve Lee 		mode);
194a6e3f4f3SSteve Lee 
195a6e3f4f3SSteve Lee 	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
196a6e3f4f3SSteve Lee 	case SND_SOC_DAIFMT_NB_NF:
197a6e3f4f3SSteve Lee 		break;
198a6e3f4f3SSteve Lee 	case SND_SOC_DAIFMT_IB_NF:
199a6e3f4f3SSteve Lee 		invert = MAX98390_PCM_MODE_CFG_PCM_BCLKEDGE;
200a6e3f4f3SSteve Lee 		break;
201a6e3f4f3SSteve Lee 	default:
202a6e3f4f3SSteve Lee 		dev_err(component->dev, "DAI invert mode unsupported\n");
203a6e3f4f3SSteve Lee 		return -EINVAL;
204a6e3f4f3SSteve Lee 	}
205a6e3f4f3SSteve Lee 
206a6e3f4f3SSteve Lee 	regmap_update_bits(max98390->regmap,
207a6e3f4f3SSteve Lee 		MAX98390_PCM_MODE_CFG,
208a6e3f4f3SSteve Lee 		MAX98390_PCM_MODE_CFG_PCM_BCLKEDGE,
209a6e3f4f3SSteve Lee 		invert);
210a6e3f4f3SSteve Lee 
211a6e3f4f3SSteve Lee 	/* interface format */
212a6e3f4f3SSteve Lee 	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
213a6e3f4f3SSteve Lee 	case SND_SOC_DAIFMT_I2S:
214a6e3f4f3SSteve Lee 		format = MAX98390_PCM_FORMAT_I2S;
215a6e3f4f3SSteve Lee 		break;
216a6e3f4f3SSteve Lee 	case SND_SOC_DAIFMT_LEFT_J:
217a6e3f4f3SSteve Lee 		format = MAX98390_PCM_FORMAT_LJ;
218a6e3f4f3SSteve Lee 		break;
219a6e3f4f3SSteve Lee 	case SND_SOC_DAIFMT_DSP_A:
220a6e3f4f3SSteve Lee 		format = MAX98390_PCM_FORMAT_TDM_MODE1;
221a6e3f4f3SSteve Lee 		break;
222a6e3f4f3SSteve Lee 	case SND_SOC_DAIFMT_DSP_B:
223a6e3f4f3SSteve Lee 		format = MAX98390_PCM_FORMAT_TDM_MODE0;
224a6e3f4f3SSteve Lee 		break;
225a6e3f4f3SSteve Lee 	default:
226a6e3f4f3SSteve Lee 		return -EINVAL;
227a6e3f4f3SSteve Lee 	}
228a6e3f4f3SSteve Lee 
229a6e3f4f3SSteve Lee 	regmap_update_bits(max98390->regmap,
230a6e3f4f3SSteve Lee 		MAX98390_PCM_MODE_CFG,
231a6e3f4f3SSteve Lee 		MAX98390_PCM_MODE_CFG_FORMAT_MASK,
232a6e3f4f3SSteve Lee 		format << MAX98390_PCM_MODE_CFG_FORMAT_SHIFT);
233a6e3f4f3SSteve Lee 
234a6e3f4f3SSteve Lee 	return 0;
235a6e3f4f3SSteve Lee }
236a6e3f4f3SSteve Lee 
237a6e3f4f3SSteve Lee static int max98390_get_bclk_sel(int bclk)
238a6e3f4f3SSteve Lee {
239a6e3f4f3SSteve Lee 	int i;
240a6e3f4f3SSteve Lee 	/* BCLKs per LRCLK */
241a6e3f4f3SSteve Lee 	static int bclk_sel_table[] = {
242a6e3f4f3SSteve Lee 		32, 48, 64, 96, 128, 192, 256, 320, 384, 512,
243a6e3f4f3SSteve Lee 	};
244a6e3f4f3SSteve Lee 	/* match BCLKs per LRCLK */
245a6e3f4f3SSteve Lee 	for (i = 0; i < ARRAY_SIZE(bclk_sel_table); i++) {
246a6e3f4f3SSteve Lee 		if (bclk_sel_table[i] == bclk)
247a6e3f4f3SSteve Lee 			return i + 2;
248a6e3f4f3SSteve Lee 	}
249a6e3f4f3SSteve Lee 	return 0;
250a6e3f4f3SSteve Lee }
251a6e3f4f3SSteve Lee 
252a6e3f4f3SSteve Lee static int max98390_set_clock(struct snd_soc_component *component,
253a6e3f4f3SSteve Lee 		struct snd_pcm_hw_params *params)
254a6e3f4f3SSteve Lee {
255a6e3f4f3SSteve Lee 	struct max98390_priv *max98390 =
256a6e3f4f3SSteve Lee 		snd_soc_component_get_drvdata(component);
257a6e3f4f3SSteve Lee 	/* codec MCLK rate in master mode */
258a6e3f4f3SSteve Lee 	static int rate_table[] = {
259a6e3f4f3SSteve Lee 		5644800, 6000000, 6144000, 6500000,
260a6e3f4f3SSteve Lee 		9600000, 11289600, 12000000, 12288000,
261a6e3f4f3SSteve Lee 		13000000, 19200000,
262a6e3f4f3SSteve Lee 	};
263a6e3f4f3SSteve Lee 	/* BCLK/LRCLK ratio calculation */
264a6e3f4f3SSteve Lee 	int blr_clk_ratio = params_channels(params)
265a6e3f4f3SSteve Lee 		* snd_pcm_format_width(params_format(params));
266a6e3f4f3SSteve Lee 	int value;
267a6e3f4f3SSteve Lee 
268a6e3f4f3SSteve Lee 	if (max98390->master) {
269a6e3f4f3SSteve Lee 		int i;
270a6e3f4f3SSteve Lee 		/* match rate to closest value */
271a6e3f4f3SSteve Lee 		for (i = 0; i < ARRAY_SIZE(rate_table); i++) {
272a6e3f4f3SSteve Lee 			if (rate_table[i] >= max98390->sysclk)
273a6e3f4f3SSteve Lee 				break;
274a6e3f4f3SSteve Lee 		}
275a6e3f4f3SSteve Lee 		if (i == ARRAY_SIZE(rate_table)) {
276a6e3f4f3SSteve Lee 			dev_err(component->dev, "failed to find proper clock rate.\n");
277a6e3f4f3SSteve Lee 			return -EINVAL;
278a6e3f4f3SSteve Lee 		}
279a6e3f4f3SSteve Lee 
280a6e3f4f3SSteve Lee 		regmap_update_bits(max98390->regmap,
281a6e3f4f3SSteve Lee 			MAX98390_PCM_MASTER_MODE,
282a6e3f4f3SSteve Lee 			MAX98390_PCM_MASTER_MODE_MCLK_MASK,
283a6e3f4f3SSteve Lee 			i << MAX98390_PCM_MASTER_MODE_MCLK_RATE_SHIFT);
284a6e3f4f3SSteve Lee 	}
285a6e3f4f3SSteve Lee 
286a6e3f4f3SSteve Lee 	if (!max98390->tdm_mode) {
287a6e3f4f3SSteve Lee 		/* BCLK configuration */
288a6e3f4f3SSteve Lee 		value = max98390_get_bclk_sel(blr_clk_ratio);
289a6e3f4f3SSteve Lee 		if (!value) {
290a6e3f4f3SSteve Lee 			dev_err(component->dev, "format unsupported %d\n",
291a6e3f4f3SSteve Lee 				params_format(params));
292a6e3f4f3SSteve Lee 			return -EINVAL;
293a6e3f4f3SSteve Lee 		}
294a6e3f4f3SSteve Lee 
295a6e3f4f3SSteve Lee 		regmap_update_bits(max98390->regmap,
296a6e3f4f3SSteve Lee 			MAX98390_PCM_CLK_SETUP,
297a6e3f4f3SSteve Lee 			MAX98390_PCM_CLK_SETUP_BSEL_MASK,
298a6e3f4f3SSteve Lee 			value);
299a6e3f4f3SSteve Lee 	}
300a6e3f4f3SSteve Lee 	return 0;
301a6e3f4f3SSteve Lee }
302a6e3f4f3SSteve Lee 
303a6e3f4f3SSteve Lee static int max98390_dai_hw_params(struct snd_pcm_substream *substream,
304a6e3f4f3SSteve Lee 		struct snd_pcm_hw_params *params,
305a6e3f4f3SSteve Lee 		struct snd_soc_dai *dai)
306a6e3f4f3SSteve Lee {
307a6e3f4f3SSteve Lee 	struct snd_soc_component *component =
308a6e3f4f3SSteve Lee 		dai->component;
309a6e3f4f3SSteve Lee 	struct max98390_priv *max98390 =
310a6e3f4f3SSteve Lee 		snd_soc_component_get_drvdata(component);
311a6e3f4f3SSteve Lee 
312a6e3f4f3SSteve Lee 	unsigned int sampling_rate;
313a6e3f4f3SSteve Lee 	unsigned int chan_sz;
314a6e3f4f3SSteve Lee 
315a6e3f4f3SSteve Lee 	/* pcm mode configuration */
316a6e3f4f3SSteve Lee 	switch (snd_pcm_format_width(params_format(params))) {
317a6e3f4f3SSteve Lee 	case 16:
318a6e3f4f3SSteve Lee 		chan_sz = MAX98390_PCM_MODE_CFG_CHANSZ_16;
319a6e3f4f3SSteve Lee 		break;
320a6e3f4f3SSteve Lee 	case 24:
321a6e3f4f3SSteve Lee 		chan_sz = MAX98390_PCM_MODE_CFG_CHANSZ_24;
322a6e3f4f3SSteve Lee 		break;
323a6e3f4f3SSteve Lee 	case 32:
324a6e3f4f3SSteve Lee 		chan_sz = MAX98390_PCM_MODE_CFG_CHANSZ_32;
325a6e3f4f3SSteve Lee 		break;
326a6e3f4f3SSteve Lee 	default:
327a6e3f4f3SSteve Lee 		dev_err(component->dev, "format unsupported %d\n",
328a6e3f4f3SSteve Lee 			params_format(params));
329a6e3f4f3SSteve Lee 		goto err;
330a6e3f4f3SSteve Lee 	}
331a6e3f4f3SSteve Lee 
332a6e3f4f3SSteve Lee 	regmap_update_bits(max98390->regmap,
333a6e3f4f3SSteve Lee 		MAX98390_PCM_MODE_CFG,
334a6e3f4f3SSteve Lee 		MAX98390_PCM_MODE_CFG_CHANSZ_MASK, chan_sz);
335a6e3f4f3SSteve Lee 
336a6e3f4f3SSteve Lee 	dev_dbg(component->dev, "format supported %d",
337a6e3f4f3SSteve Lee 		params_format(params));
338a6e3f4f3SSteve Lee 
339a6e3f4f3SSteve Lee 	/* sampling rate configuration */
340a6e3f4f3SSteve Lee 	switch (params_rate(params)) {
341a6e3f4f3SSteve Lee 	case 8000:
342a6e3f4f3SSteve Lee 		sampling_rate = MAX98390_PCM_SR_SET1_SR_8000;
343a6e3f4f3SSteve Lee 		break;
344a6e3f4f3SSteve Lee 	case 11025:
345a6e3f4f3SSteve Lee 		sampling_rate = MAX98390_PCM_SR_SET1_SR_11025;
346a6e3f4f3SSteve Lee 		break;
347a6e3f4f3SSteve Lee 	case 12000:
348a6e3f4f3SSteve Lee 		sampling_rate = MAX98390_PCM_SR_SET1_SR_12000;
349a6e3f4f3SSteve Lee 		break;
350a6e3f4f3SSteve Lee 	case 16000:
351a6e3f4f3SSteve Lee 		sampling_rate = MAX98390_PCM_SR_SET1_SR_16000;
352a6e3f4f3SSteve Lee 		break;
353a6e3f4f3SSteve Lee 	case 22050:
354a6e3f4f3SSteve Lee 		sampling_rate = MAX98390_PCM_SR_SET1_SR_22050;
355a6e3f4f3SSteve Lee 		break;
356a6e3f4f3SSteve Lee 	case 24000:
357a6e3f4f3SSteve Lee 		sampling_rate = MAX98390_PCM_SR_SET1_SR_24000;
358a6e3f4f3SSteve Lee 		break;
359a6e3f4f3SSteve Lee 	case 32000:
360a6e3f4f3SSteve Lee 		sampling_rate = MAX98390_PCM_SR_SET1_SR_32000;
361a6e3f4f3SSteve Lee 		break;
362a6e3f4f3SSteve Lee 	case 44100:
363a6e3f4f3SSteve Lee 		sampling_rate = MAX98390_PCM_SR_SET1_SR_44100;
364a6e3f4f3SSteve Lee 		break;
365a6e3f4f3SSteve Lee 	case 48000:
366a6e3f4f3SSteve Lee 		sampling_rate = MAX98390_PCM_SR_SET1_SR_48000;
367a6e3f4f3SSteve Lee 		break;
368a6e3f4f3SSteve Lee 	default:
369a6e3f4f3SSteve Lee 		dev_err(component->dev, "rate %d not supported\n",
370a6e3f4f3SSteve Lee 			params_rate(params));
371a6e3f4f3SSteve Lee 		goto err;
372a6e3f4f3SSteve Lee 	}
373a6e3f4f3SSteve Lee 
374a6e3f4f3SSteve Lee 	/* set DAI_SR to correct LRCLK frequency */
375a6e3f4f3SSteve Lee 	regmap_update_bits(max98390->regmap,
376a6e3f4f3SSteve Lee 		MAX98390_PCM_SR_SETUP,
377a6e3f4f3SSteve Lee 		MAX98390_PCM_SR_SET1_SR_MASK,
378a6e3f4f3SSteve Lee 		sampling_rate);
379a6e3f4f3SSteve Lee 
380a6e3f4f3SSteve Lee 	return max98390_set_clock(component, params);
381a6e3f4f3SSteve Lee err:
382a6e3f4f3SSteve Lee 	return -EINVAL;
383a6e3f4f3SSteve Lee }
384a6e3f4f3SSteve Lee 
385a6e3f4f3SSteve Lee static int max98390_dai_tdm_slot(struct snd_soc_dai *dai,
386a6e3f4f3SSteve Lee 		unsigned int tx_mask, unsigned int rx_mask,
387a6e3f4f3SSteve Lee 		int slots, int slot_width)
388a6e3f4f3SSteve Lee {
389a6e3f4f3SSteve Lee 	struct snd_soc_component *component = dai->component;
390a6e3f4f3SSteve Lee 	struct max98390_priv *max98390 =
391a6e3f4f3SSteve Lee 		snd_soc_component_get_drvdata(component);
392a6e3f4f3SSteve Lee 
393a6e3f4f3SSteve Lee 	int bsel;
394a6e3f4f3SSteve Lee 	unsigned int chan_sz;
395a6e3f4f3SSteve Lee 
396a6e3f4f3SSteve Lee 	if (!tx_mask && !rx_mask && !slots && !slot_width)
397a6e3f4f3SSteve Lee 		max98390->tdm_mode = false;
398a6e3f4f3SSteve Lee 	else
399a6e3f4f3SSteve Lee 		max98390->tdm_mode = true;
400a6e3f4f3SSteve Lee 
401a6e3f4f3SSteve Lee 	dev_dbg(component->dev,
402a6e3f4f3SSteve Lee 		"Tdm mode : %d\n", max98390->tdm_mode);
403a6e3f4f3SSteve Lee 
404a6e3f4f3SSteve Lee 	/* BCLK configuration */
405a6e3f4f3SSteve Lee 	bsel = max98390_get_bclk_sel(slots * slot_width);
406a6e3f4f3SSteve Lee 	if (!bsel) {
407a6e3f4f3SSteve Lee 		dev_err(component->dev, "BCLK %d not supported\n",
408a6e3f4f3SSteve Lee 			slots * slot_width);
409a6e3f4f3SSteve Lee 		return -EINVAL;
410a6e3f4f3SSteve Lee 	}
411a6e3f4f3SSteve Lee 
412a6e3f4f3SSteve Lee 	regmap_update_bits(max98390->regmap,
413a6e3f4f3SSteve Lee 		MAX98390_PCM_CLK_SETUP,
414a6e3f4f3SSteve Lee 		MAX98390_PCM_CLK_SETUP_BSEL_MASK,
415a6e3f4f3SSteve Lee 		bsel);
416a6e3f4f3SSteve Lee 
417a6e3f4f3SSteve Lee 	/* Channel size configuration */
418a6e3f4f3SSteve Lee 	switch (slot_width) {
419a6e3f4f3SSteve Lee 	case 16:
420a6e3f4f3SSteve Lee 		chan_sz = MAX98390_PCM_MODE_CFG_CHANSZ_16;
421a6e3f4f3SSteve Lee 		break;
422a6e3f4f3SSteve Lee 	case 24:
423a6e3f4f3SSteve Lee 		chan_sz = MAX98390_PCM_MODE_CFG_CHANSZ_24;
424a6e3f4f3SSteve Lee 		break;
425a6e3f4f3SSteve Lee 	case 32:
426a6e3f4f3SSteve Lee 		chan_sz = MAX98390_PCM_MODE_CFG_CHANSZ_32;
427a6e3f4f3SSteve Lee 		break;
428a6e3f4f3SSteve Lee 	default:
429a6e3f4f3SSteve Lee 		dev_err(component->dev, "format unsupported %d\n",
430a6e3f4f3SSteve Lee 			slot_width);
431a6e3f4f3SSteve Lee 		return -EINVAL;
432a6e3f4f3SSteve Lee 	}
433a6e3f4f3SSteve Lee 
434a6e3f4f3SSteve Lee 	regmap_update_bits(max98390->regmap,
435a6e3f4f3SSteve Lee 		MAX98390_PCM_MODE_CFG,
436a6e3f4f3SSteve Lee 		MAX98390_PCM_MODE_CFG_CHANSZ_MASK, chan_sz);
437a6e3f4f3SSteve Lee 
438a6e3f4f3SSteve Lee 	/* Rx slot configuration */
439a6e3f4f3SSteve Lee 	regmap_write(max98390->regmap,
440a6e3f4f3SSteve Lee 		MAX98390_PCM_RX_EN_A,
441a6e3f4f3SSteve Lee 		rx_mask & 0xFF);
442a6e3f4f3SSteve Lee 	regmap_write(max98390->regmap,
443a6e3f4f3SSteve Lee 		MAX98390_PCM_RX_EN_B,
444a6e3f4f3SSteve Lee 		(rx_mask & 0xFF00) >> 8);
445a6e3f4f3SSteve Lee 
446a6e3f4f3SSteve Lee 	/* Tx slot Hi-Z configuration */
447a6e3f4f3SSteve Lee 	regmap_write(max98390->regmap,
448a6e3f4f3SSteve Lee 		MAX98390_PCM_TX_HIZ_CTRL_A,
449a6e3f4f3SSteve Lee 		~tx_mask & 0xFF);
450a6e3f4f3SSteve Lee 	regmap_write(max98390->regmap,
451a6e3f4f3SSteve Lee 		MAX98390_PCM_TX_HIZ_CTRL_B,
452a6e3f4f3SSteve Lee 		(~tx_mask & 0xFF00) >> 8);
453a6e3f4f3SSteve Lee 
454a6e3f4f3SSteve Lee 	return 0;
455a6e3f4f3SSteve Lee }
456a6e3f4f3SSteve Lee 
457a6e3f4f3SSteve Lee static int max98390_dai_set_sysclk(struct snd_soc_dai *dai,
458a6e3f4f3SSteve Lee 		int clk_id, unsigned int freq, int dir)
459a6e3f4f3SSteve Lee {
460a6e3f4f3SSteve Lee 	struct snd_soc_component *component = dai->component;
461a6e3f4f3SSteve Lee 	struct max98390_priv *max98390 =
462a6e3f4f3SSteve Lee 		snd_soc_component_get_drvdata(component);
463a6e3f4f3SSteve Lee 
464a6e3f4f3SSteve Lee 	max98390->sysclk = freq;
465a6e3f4f3SSteve Lee 	return 0;
466a6e3f4f3SSteve Lee }
467a6e3f4f3SSteve Lee 
468a6e3f4f3SSteve Lee static const struct snd_soc_dai_ops max98390_dai_ops = {
469a6e3f4f3SSteve Lee 	.set_sysclk = max98390_dai_set_sysclk,
470a6e3f4f3SSteve Lee 	.set_fmt = max98390_dai_set_fmt,
471a6e3f4f3SSteve Lee 	.hw_params = max98390_dai_hw_params,
472a6e3f4f3SSteve Lee 	.set_tdm_slot = max98390_dai_tdm_slot,
473a6e3f4f3SSteve Lee };
474a6e3f4f3SSteve Lee 
475a6e3f4f3SSteve Lee static int max98390_dac_event(struct snd_soc_dapm_widget *w,
476a6e3f4f3SSteve Lee 		struct snd_kcontrol *kcontrol, int event)
477a6e3f4f3SSteve Lee {
478a6e3f4f3SSteve Lee 	struct snd_soc_component *component =
479a6e3f4f3SSteve Lee 		snd_soc_dapm_to_component(w->dapm);
480a6e3f4f3SSteve Lee 	struct max98390_priv *max98390 =
481a6e3f4f3SSteve Lee 		snd_soc_component_get_drvdata(component);
482a6e3f4f3SSteve Lee 
483a6e3f4f3SSteve Lee 	switch (event) {
484a6e3f4f3SSteve Lee 	case SND_SOC_DAPM_POST_PMU:
485a6e3f4f3SSteve Lee 		regmap_update_bits(max98390->regmap,
486a6e3f4f3SSteve Lee 			MAX98390_R203A_AMP_EN,
487a6e3f4f3SSteve Lee 			MAX98390_AMP_EN_MASK, 1);
488a6e3f4f3SSteve Lee 		regmap_update_bits(max98390->regmap,
489a6e3f4f3SSteve Lee 			MAX98390_R23FF_GLOBAL_EN,
490a6e3f4f3SSteve Lee 			MAX98390_GLOBAL_EN_MASK, 1);
491a6e3f4f3SSteve Lee 		break;
492a6e3f4f3SSteve Lee 	case SND_SOC_DAPM_POST_PMD:
493a6e3f4f3SSteve Lee 		regmap_update_bits(max98390->regmap,
494a6e3f4f3SSteve Lee 			MAX98390_R23FF_GLOBAL_EN,
495a6e3f4f3SSteve Lee 			MAX98390_GLOBAL_EN_MASK, 0);
496a6e3f4f3SSteve Lee 		regmap_update_bits(max98390->regmap,
497a6e3f4f3SSteve Lee 			MAX98390_R203A_AMP_EN,
498a6e3f4f3SSteve Lee 			MAX98390_AMP_EN_MASK, 0);
499a6e3f4f3SSteve Lee 		break;
500a6e3f4f3SSteve Lee 	}
501a6e3f4f3SSteve Lee 	return 0;
502a6e3f4f3SSteve Lee }
503a6e3f4f3SSteve Lee 
504a6e3f4f3SSteve Lee static const char * const max98390_switch_text[] = {
505a6e3f4f3SSteve Lee 	"Left", "Right", "LeftRight"};
506a6e3f4f3SSteve Lee 
507a6e3f4f3SSteve Lee static const char * const max98390_boost_voltage_text[] = {
508a6e3f4f3SSteve Lee 	"6.5V", "6.625V", "6.75V", "6.875V", "7V", "7.125V", "7.25V", "7.375V",
509a6e3f4f3SSteve Lee 	"7.5V", "7.625V", "7.75V", "7.875V", "8V", "8.125V", "8.25V", "8.375V",
510a6e3f4f3SSteve Lee 	"8.5V", "8.625V", "8.75V", "8.875V", "9V", "9.125V", "9.25V", "9.375V",
511a6e3f4f3SSteve Lee 	"9.5V", "9.625V", "9.75V", "9.875V", "10V"
512a6e3f4f3SSteve Lee };
513a6e3f4f3SSteve Lee 
514a6e3f4f3SSteve Lee static SOC_ENUM_SINGLE_DECL(max98390_boost_voltage,
515a6e3f4f3SSteve Lee 		MAX98390_BOOST_CTRL0, 0,
516a6e3f4f3SSteve Lee 		max98390_boost_voltage_text);
517a6e3f4f3SSteve Lee 
518a6e3f4f3SSteve Lee static DECLARE_TLV_DB_SCALE(max98390_spk_tlv, 300, 300, 0);
519a6e3f4f3SSteve Lee static DECLARE_TLV_DB_SCALE(max98390_digital_tlv, -8000, 50, 0);
520a6e3f4f3SSteve Lee 
521a6e3f4f3SSteve Lee static const char * const max98390_current_limit_text[] = {
522a6e3f4f3SSteve Lee 	"0.00A", "0.50A", "1.00A", "1.05A", "1.10A", "1.15A", "1.20A", "1.25A",
523a6e3f4f3SSteve Lee 	"1.30A", "1.35A", "1.40A", "1.45A", "1.50A", "1.55A", "1.60A", "1.65A",
524a6e3f4f3SSteve Lee 	"1.70A", "1.75A", "1.80A", "1.85A", "1.90A", "1.95A", "2.00A", "2.05A",
525a6e3f4f3SSteve Lee 	"2.10A", "2.15A", "2.20A", "2.25A", "2.30A", "2.35A", "2.40A", "2.45A",
526a6e3f4f3SSteve Lee 	"2.50A", "2.55A", "2.60A", "2.65A", "2.70A", "2.75A", "2.80A", "2.85A",
527a6e3f4f3SSteve Lee 	"2.90A", "2.95A", "3.00A", "3.05A", "3.10A", "3.15A", "3.20A", "3.25A",
528a6e3f4f3SSteve Lee 	"3.30A", "3.35A", "3.40A", "3.45A", "3.50A", "3.55A", "3.60A", "3.65A",
529a6e3f4f3SSteve Lee 	"3.70A", "3.75A", "3.80A", "3.85A", "3.90A", "3.95A", "4.00A", "4.05A",
530a6e3f4f3SSteve Lee 	"4.10A"
531a6e3f4f3SSteve Lee };
532a6e3f4f3SSteve Lee 
533a6e3f4f3SSteve Lee static SOC_ENUM_SINGLE_DECL(max98390_current_limit,
534a6e3f4f3SSteve Lee 		MAX98390_BOOST_CTRL1, 0,
535a6e3f4f3SSteve Lee 		max98390_current_limit_text);
536a6e3f4f3SSteve Lee 
537a6e3f4f3SSteve Lee static int max98390_ref_rdc_put(struct snd_kcontrol *kcontrol,
538a6e3f4f3SSteve Lee 		struct snd_ctl_elem_value *ucontrol)
539a6e3f4f3SSteve Lee {
540a6e3f4f3SSteve Lee 	struct snd_soc_component *component =
541a6e3f4f3SSteve Lee 		snd_soc_kcontrol_component(kcontrol);
542a6e3f4f3SSteve Lee 	struct max98390_priv *max98390 =
543a6e3f4f3SSteve Lee 		snd_soc_component_get_drvdata(component);
544a6e3f4f3SSteve Lee 
545a6e3f4f3SSteve Lee 	max98390->ref_rdc_value = ucontrol->value.integer.value[0];
546a6e3f4f3SSteve Lee 
547a6e3f4f3SSteve Lee 	regmap_write(max98390->regmap, DSM_TPROT_RECIP_RDC_ROOM_BYTE0,
548a6e3f4f3SSteve Lee 		max98390->ref_rdc_value & 0x000000ff);
549a6e3f4f3SSteve Lee 	regmap_write(max98390->regmap, DSM_TPROT_RECIP_RDC_ROOM_BYTE1,
550a6e3f4f3SSteve Lee 		(max98390->ref_rdc_value >> 8) & 0x000000ff);
551a6e3f4f3SSteve Lee 	regmap_write(max98390->regmap, DSM_TPROT_RECIP_RDC_ROOM_BYTE2,
552a6e3f4f3SSteve Lee 		(max98390->ref_rdc_value >> 16) & 0x000000ff);
553a6e3f4f3SSteve Lee 
554a6e3f4f3SSteve Lee 	return 0;
555a6e3f4f3SSteve Lee }
556a6e3f4f3SSteve Lee 
557a6e3f4f3SSteve Lee static int max98390_ref_rdc_get(struct snd_kcontrol *kcontrol,
558a6e3f4f3SSteve Lee 		struct snd_ctl_elem_value *ucontrol)
559a6e3f4f3SSteve Lee {
560a6e3f4f3SSteve Lee 	struct snd_soc_component *component =
561a6e3f4f3SSteve Lee 		snd_soc_kcontrol_component(kcontrol);
562a6e3f4f3SSteve Lee 	struct max98390_priv *max98390 =
563a6e3f4f3SSteve Lee 		snd_soc_component_get_drvdata(component);
564a6e3f4f3SSteve Lee 
565a6e3f4f3SSteve Lee 	ucontrol->value.integer.value[0] = max98390->ref_rdc_value;
566a6e3f4f3SSteve Lee 
567a6e3f4f3SSteve Lee 	return 0;
568a6e3f4f3SSteve Lee }
569a6e3f4f3SSteve Lee 
570a6e3f4f3SSteve Lee static int max98390_ambient_temp_put(struct snd_kcontrol *kcontrol,
571a6e3f4f3SSteve Lee 		struct snd_ctl_elem_value *ucontrol)
572a6e3f4f3SSteve Lee {
573a6e3f4f3SSteve Lee 	struct snd_soc_component *component =
574a6e3f4f3SSteve Lee 		snd_soc_kcontrol_component(kcontrol);
575a6e3f4f3SSteve Lee 	struct max98390_priv *max98390 =
576a6e3f4f3SSteve Lee 		snd_soc_component_get_drvdata(component);
577a6e3f4f3SSteve Lee 
578a6e3f4f3SSteve Lee 	max98390->ambient_temp_value = ucontrol->value.integer.value[0];
579a6e3f4f3SSteve Lee 
580a6e3f4f3SSteve Lee 	regmap_write(max98390->regmap, DSM_TPROT_ROOM_TEMPERATURE_BYTE1,
581a6e3f4f3SSteve Lee 		(max98390->ambient_temp_value >> 8) & 0x000000ff);
582a6e3f4f3SSteve Lee 	regmap_write(max98390->regmap, DSM_TPROT_ROOM_TEMPERATURE_BYTE0,
583a6e3f4f3SSteve Lee 		(max98390->ambient_temp_value) & 0x000000ff);
584a6e3f4f3SSteve Lee 
585a6e3f4f3SSteve Lee 	return 0;
586a6e3f4f3SSteve Lee }
587a6e3f4f3SSteve Lee 
588a6e3f4f3SSteve Lee static int max98390_ambient_temp_get(struct snd_kcontrol *kcontrol,
589a6e3f4f3SSteve Lee 		struct snd_ctl_elem_value *ucontrol)
590a6e3f4f3SSteve Lee {
591a6e3f4f3SSteve Lee 	struct snd_soc_component *component =
592a6e3f4f3SSteve Lee 		snd_soc_kcontrol_component(kcontrol);
593a6e3f4f3SSteve Lee 	struct max98390_priv *max98390 =
594a6e3f4f3SSteve Lee 		snd_soc_component_get_drvdata(component);
595a6e3f4f3SSteve Lee 
596a6e3f4f3SSteve Lee 	ucontrol->value.integer.value[0] = max98390->ambient_temp_value;
597a6e3f4f3SSteve Lee 
598a6e3f4f3SSteve Lee 	return 0;
599a6e3f4f3SSteve Lee }
600a6e3f4f3SSteve Lee 
601a6e3f4f3SSteve Lee static int max98390_adaptive_rdc_put(struct snd_kcontrol *kcontrol,
602a6e3f4f3SSteve Lee 		struct snd_ctl_elem_value *ucontrol)
603a6e3f4f3SSteve Lee {
604a6e3f4f3SSteve Lee 	struct snd_soc_component *component =
605a6e3f4f3SSteve Lee 		snd_soc_kcontrol_component(kcontrol);
606a6e3f4f3SSteve Lee 
607a6e3f4f3SSteve Lee 	dev_warn(component->dev, "Put adaptive rdc not supported\n");
608a6e3f4f3SSteve Lee 
609a6e3f4f3SSteve Lee 	return 0;
610a6e3f4f3SSteve Lee }
611a6e3f4f3SSteve Lee 
612a6e3f4f3SSteve Lee static int max98390_adaptive_rdc_get(struct snd_kcontrol *kcontrol,
613a6e3f4f3SSteve Lee 		struct snd_ctl_elem_value *ucontrol)
614a6e3f4f3SSteve Lee {
615a6e3f4f3SSteve Lee 	int rdc, rdc0;
616a6e3f4f3SSteve Lee 	struct snd_soc_component *component =
617a6e3f4f3SSteve Lee 		snd_soc_kcontrol_component(kcontrol);
618a6e3f4f3SSteve Lee 	struct max98390_priv *max98390 =
619a6e3f4f3SSteve Lee 		snd_soc_component_get_drvdata(component);
620a6e3f4f3SSteve Lee 
621a6e3f4f3SSteve Lee 	regmap_read(max98390->regmap, THERMAL_RDC_RD_BACK_BYTE1, &rdc);
622a6e3f4f3SSteve Lee 	regmap_read(max98390->regmap, THERMAL_RDC_RD_BACK_BYTE0, &rdc0);
623a6e3f4f3SSteve Lee 	ucontrol->value.integer.value[0] = rdc0 | rdc << 8;
624a6e3f4f3SSteve Lee 
625a6e3f4f3SSteve Lee 	return 0;
626a6e3f4f3SSteve Lee }
627a6e3f4f3SSteve Lee 
628a6e3f4f3SSteve Lee static int max98390_dsm_calib_get(struct snd_kcontrol *kcontrol,
629a6e3f4f3SSteve Lee 		struct snd_ctl_elem_value *ucontrol)
630a6e3f4f3SSteve Lee {
631a6e3f4f3SSteve Lee 	/* Do nothing */
632a6e3f4f3SSteve Lee 	return 0;
633a6e3f4f3SSteve Lee }
634a6e3f4f3SSteve Lee 
635a6e3f4f3SSteve Lee static int max98390_dsm_calib_put(struct snd_kcontrol *kcontrol,
636a6e3f4f3SSteve Lee 		struct snd_ctl_elem_value *ucontrol)
637a6e3f4f3SSteve Lee {
638a6e3f4f3SSteve Lee 	struct snd_soc_component *component =
639a6e3f4f3SSteve Lee 		snd_soc_kcontrol_component(kcontrol);
640a6e3f4f3SSteve Lee 
641a6e3f4f3SSteve Lee 	max98390_dsm_calibrate(component);
642a6e3f4f3SSteve Lee 
643a6e3f4f3SSteve Lee 	return 0;
644a6e3f4f3SSteve Lee }
645a6e3f4f3SSteve Lee 
646a6e3f4f3SSteve Lee static const struct snd_kcontrol_new max98390_snd_controls[] = {
647a6e3f4f3SSteve Lee 	SOC_SINGLE_TLV("Digital Volume", DSM_VOL_CTRL,
648a6e3f4f3SSteve Lee 		0, 184, 0,
649a6e3f4f3SSteve Lee 		max98390_digital_tlv),
650a6e3f4f3SSteve Lee 	SOC_SINGLE_TLV("Speaker Volume", MAX98390_R203D_SPK_GAIN,
651a6e3f4f3SSteve Lee 		0, 6, 0,
652a6e3f4f3SSteve Lee 		max98390_spk_tlv),
653a6e3f4f3SSteve Lee 	SOC_SINGLE("Ramp Up Bypass Switch", MAX98390_R2039_AMP_DSP_CFG,
654a6e3f4f3SSteve Lee 		MAX98390_AMP_DSP_CFG_RMP_UP_SHIFT, 1, 0),
655a6e3f4f3SSteve Lee 	SOC_SINGLE("Ramp Down Bypass Switch", MAX98390_R2039_AMP_DSP_CFG,
656a6e3f4f3SSteve Lee 		MAX98390_AMP_DSP_CFG_RMP_DN_SHIFT, 1, 0),
657a6e3f4f3SSteve Lee 	SOC_SINGLE("Boost Clock Phase", MAX98390_BOOST_CTRL3,
658a6e3f4f3SSteve Lee 		MAX98390_BOOST_CLK_PHASE_CFG_SHIFT, 3, 0),
659a6e3f4f3SSteve Lee 	SOC_ENUM("Boost Output Voltage", max98390_boost_voltage),
660a6e3f4f3SSteve Lee 	SOC_ENUM("Current Limit", max98390_current_limit),
661a6e3f4f3SSteve Lee 	SOC_SINGLE_EXT("DSM Rdc", SND_SOC_NOPM, 0, 0xffffff, 0,
662a6e3f4f3SSteve Lee 		max98390_ref_rdc_get, max98390_ref_rdc_put),
663a6e3f4f3SSteve Lee 	SOC_SINGLE_EXT("DSM Ambient Temp", SND_SOC_NOPM, 0, 0xffff, 0,
664a6e3f4f3SSteve Lee 		max98390_ambient_temp_get, max98390_ambient_temp_put),
665a6e3f4f3SSteve Lee 	SOC_SINGLE_EXT("DSM Adaptive Rdc", SND_SOC_NOPM, 0, 0xffff, 0,
666a6e3f4f3SSteve Lee 		max98390_adaptive_rdc_get, max98390_adaptive_rdc_put),
667a6e3f4f3SSteve Lee 	SOC_SINGLE_EXT("DSM Calibration", SND_SOC_NOPM, 0, 1, 0,
668a6e3f4f3SSteve Lee 		max98390_dsm_calib_get, max98390_dsm_calib_put),
669a6e3f4f3SSteve Lee };
670a6e3f4f3SSteve Lee 
671a6e3f4f3SSteve Lee static const struct soc_enum dai_sel_enum =
672a6e3f4f3SSteve Lee 	SOC_ENUM_SINGLE(MAX98390_PCM_CH_SRC_1,
673a6e3f4f3SSteve Lee 		MAX98390_PCM_RX_CH_SRC_SHIFT,
674a6e3f4f3SSteve Lee 		3, max98390_switch_text);
675a6e3f4f3SSteve Lee 
676a6e3f4f3SSteve Lee static const struct snd_kcontrol_new max98390_dai_controls =
677a6e3f4f3SSteve Lee 	SOC_DAPM_ENUM("DAI Sel", dai_sel_enum);
678a6e3f4f3SSteve Lee 
679a6e3f4f3SSteve Lee static const struct snd_soc_dapm_widget max98390_dapm_widgets[] = {
680a6e3f4f3SSteve Lee 	SND_SOC_DAPM_DAC_E("Amp Enable", "HiFi Playback",
681dc5fb6d2SSteve Lee 		SND_SOC_NOPM, 0, 0, max98390_dac_event,
682a6e3f4f3SSteve Lee 		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
683a6e3f4f3SSteve Lee 	SND_SOC_DAPM_MUX("DAI Sel Mux", SND_SOC_NOPM, 0, 0,
684a6e3f4f3SSteve Lee 		&max98390_dai_controls),
685a6e3f4f3SSteve Lee 	SND_SOC_DAPM_OUTPUT("BE_OUT"),
686a6e3f4f3SSteve Lee };
687a6e3f4f3SSteve Lee 
688a6e3f4f3SSteve Lee static const struct snd_soc_dapm_route max98390_audio_map[] = {
689a6e3f4f3SSteve Lee 	/* Plabyack */
690a6e3f4f3SSteve Lee 	{"DAI Sel Mux", "Left", "Amp Enable"},
691a6e3f4f3SSteve Lee 	{"DAI Sel Mux", "Right", "Amp Enable"},
692a6e3f4f3SSteve Lee 	{"DAI Sel Mux", "LeftRight", "Amp Enable"},
693a6e3f4f3SSteve Lee 	{"BE_OUT", NULL, "DAI Sel Mux"},
694a6e3f4f3SSteve Lee };
695a6e3f4f3SSteve Lee 
696a6e3f4f3SSteve Lee static bool max98390_readable_register(struct device *dev, unsigned int reg)
697a6e3f4f3SSteve Lee {
698a6e3f4f3SSteve Lee 	switch (reg) {
699a6e3f4f3SSteve Lee 	case MAX98390_SOFTWARE_RESET ... MAX98390_INT_EN3:
700a6e3f4f3SSteve Lee 	case MAX98390_IRQ_CTRL ... MAX98390_WDOG_CTRL:
701a6e3f4f3SSteve Lee 	case MAX98390_MEAS_ADC_THERM_WARN_THRESH
702a6e3f4f3SSteve Lee 		... MAX98390_BROWNOUT_INFINITE_HOLD:
7034008b29eSSteve Lee 	case MAX98390_BROWNOUT_LVL_HOLD ... DSMIG_DEBUZZER_THRESHOLD:
7044008b29eSSteve Lee 	case DSM_VOL_ENA ... MAX98390_R24FF_REV_ID:
705a6e3f4f3SSteve Lee 		return true;
706a6e3f4f3SSteve Lee 	default:
707a6e3f4f3SSteve Lee 		return false;
708a6e3f4f3SSteve Lee 	}
709a6e3f4f3SSteve Lee };
710a6e3f4f3SSteve Lee 
711a6e3f4f3SSteve Lee static bool max98390_volatile_reg(struct device *dev, unsigned int reg)
712a6e3f4f3SSteve Lee {
713a6e3f4f3SSteve Lee 	switch (reg) {
714a6e3f4f3SSteve Lee 	case MAX98390_SOFTWARE_RESET ... MAX98390_INT_EN3:
715a6e3f4f3SSteve Lee 	case MAX98390_MEAS_ADC_CH0_READ ... MAX98390_MEAS_ADC_CH2_READ:
716a6e3f4f3SSteve Lee 	case MAX98390_PWR_GATE_STATUS ... MAX98390_BROWNOUT_STATUS:
717a6e3f4f3SSteve Lee 	case MAX98390_BROWNOUT_LOWEST_STATUS:
718a6e3f4f3SSteve Lee 	case MAX98390_ENV_TRACK_BOOST_VOUT_READ:
719a6e3f4f3SSteve Lee 	case DSM_STBASS_HPF_B0_BYTE0 ... DSM_DEBUZZER_ATTACK_TIME_BYTE2:
7204008b29eSSteve Lee 	case THERMAL_RDC_RD_BACK_BYTE1 ... DSMIG_DEBUZZER_THRESHOLD:
721a6e3f4f3SSteve Lee 	case DSM_THERMAL_GAIN ... DSM_WBDRC_GAIN:
722a6e3f4f3SSteve Lee 		return true;
723a6e3f4f3SSteve Lee 	default:
724a6e3f4f3SSteve Lee 		return false;
725a6e3f4f3SSteve Lee 	}
726a6e3f4f3SSteve Lee }
727a6e3f4f3SSteve Lee 
728a6e3f4f3SSteve Lee #define MAX98390_RATES SNDRV_PCM_RATE_8000_48000
729a6e3f4f3SSteve Lee 
730a6e3f4f3SSteve Lee #define MAX98390_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \
731a6e3f4f3SSteve Lee 	SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
732a6e3f4f3SSteve Lee 
733a6e3f4f3SSteve Lee static struct snd_soc_dai_driver max98390_dai[] = {
734a6e3f4f3SSteve Lee 	{
735a6e3f4f3SSteve Lee 		.name = "max98390-aif1",
736a6e3f4f3SSteve Lee 		.playback = {
737a6e3f4f3SSteve Lee 			.stream_name = "HiFi Playback",
738a6e3f4f3SSteve Lee 			.channels_min = 1,
739a6e3f4f3SSteve Lee 			.channels_max = 2,
740a6e3f4f3SSteve Lee 			.rates = MAX98390_RATES,
741a6e3f4f3SSteve Lee 			.formats = MAX98390_FORMATS,
742a6e3f4f3SSteve Lee 		},
743a6e3f4f3SSteve Lee 		.capture = {
744a6e3f4f3SSteve Lee 			.stream_name = "HiFi Capture",
745a6e3f4f3SSteve Lee 			.channels_min = 1,
746a6e3f4f3SSteve Lee 			.channels_max = 2,
747a6e3f4f3SSteve Lee 			.rates = MAX98390_RATES,
748a6e3f4f3SSteve Lee 			.formats = MAX98390_FORMATS,
749a6e3f4f3SSteve Lee 		},
750a6e3f4f3SSteve Lee 		.ops = &max98390_dai_ops,
751a6e3f4f3SSteve Lee 	}
752a6e3f4f3SSteve Lee };
753a6e3f4f3SSteve Lee 
754a6e3f4f3SSteve Lee static int max98390_dsm_init(struct snd_soc_component *component)
755a6e3f4f3SSteve Lee {
756a6e3f4f3SSteve Lee 	int ret;
75797ed3e50SSteve Lee 	int param_size, param_start_addr;
758a6e3f4f3SSteve Lee 	char filename[128];
759a6e3f4f3SSteve Lee 	const char *vendor, *product;
760a6e3f4f3SSteve Lee 	struct max98390_priv *max98390 =
761a6e3f4f3SSteve Lee 		snd_soc_component_get_drvdata(component);
762a6e3f4f3SSteve Lee 	const struct firmware *fw;
763a6e3f4f3SSteve Lee 	char *dsm_param;
764a6e3f4f3SSteve Lee 
765a6e3f4f3SSteve Lee 	vendor = dmi_get_system_info(DMI_SYS_VENDOR);
766a6e3f4f3SSteve Lee 	product = dmi_get_system_info(DMI_PRODUCT_NAME);
767a6e3f4f3SSteve Lee 
768a6e3f4f3SSteve Lee 	if (vendor && product) {
769a6e3f4f3SSteve Lee 		snprintf(filename, sizeof(filename), "dsm_param_%s_%s.bin",
770a6e3f4f3SSteve Lee 			vendor, product);
771a6e3f4f3SSteve Lee 	} else {
772a6e3f4f3SSteve Lee 		sprintf(filename, "dsm_param.bin");
773a6e3f4f3SSteve Lee 	}
774a6e3f4f3SSteve Lee 	ret = request_firmware(&fw, filename, component->dev);
775a6e3f4f3SSteve Lee 	if (ret) {
776a6e3f4f3SSteve Lee 		ret = request_firmware(&fw, "dsm_param.bin", component->dev);
777a6e3f4f3SSteve Lee 		if (ret)
778a6e3f4f3SSteve Lee 			goto err;
779a6e3f4f3SSteve Lee 	}
780a6e3f4f3SSteve Lee 
781a6e3f4f3SSteve Lee 	dev_dbg(component->dev,
782678916ecSTakashi Iwai 		"max98390: param fw size %zd\n",
783a6e3f4f3SSteve Lee 		fw->size);
78497ed3e50SSteve Lee 	if (fw->size < MAX98390_DSM_PARAM_MIN_SIZE) {
78597ed3e50SSteve Lee 		dev_err(component->dev,
78697ed3e50SSteve Lee 			"param fw is invalid.\n");
787*3cea33b6SDan Carpenter 		ret = -EINVAL;
78897ed3e50SSteve Lee 		goto err_alloc;
78997ed3e50SSteve Lee 	}
790a6e3f4f3SSteve Lee 	dsm_param = (char *)fw->data;
79197ed3e50SSteve Lee 	param_start_addr = (dsm_param[0] & 0xff) | (dsm_param[1] & 0xff) << 8;
79297ed3e50SSteve Lee 	param_size = (dsm_param[2] & 0xff) | (dsm_param[3] & 0xff) << 8;
79397ed3e50SSteve Lee 	if (param_size > MAX98390_DSM_PARAM_MAX_SIZE ||
794aa785705SSteve Lee 		param_start_addr < MAX98390_IRQ_CTRL ||
79597ed3e50SSteve Lee 		fw->size < param_size + MAX98390_DSM_PAYLOAD_OFFSET) {
79697ed3e50SSteve Lee 		dev_err(component->dev,
79797ed3e50SSteve Lee 			"param fw is invalid.\n");
798*3cea33b6SDan Carpenter 		ret = -EINVAL;
79997ed3e50SSteve Lee 		goto err_alloc;
80097ed3e50SSteve Lee 	}
80197ed3e50SSteve Lee 	regmap_write(max98390->regmap, MAX98390_R203A_AMP_EN, 0x80);
802a6e3f4f3SSteve Lee 	dsm_param += MAX98390_DSM_PAYLOAD_OFFSET;
80397ed3e50SSteve Lee 	regmap_bulk_write(max98390->regmap, param_start_addr,
80497ed3e50SSteve Lee 		dsm_param, param_size);
805a6e3f4f3SSteve Lee 	regmap_write(max98390->regmap, MAX98390_R23E1_DSP_GLOBAL_EN, 0x01);
806a6e3f4f3SSteve Lee 
80797ed3e50SSteve Lee err_alloc:
80897ed3e50SSteve Lee 	release_firmware(fw);
809a6e3f4f3SSteve Lee err:
810a6e3f4f3SSteve Lee 	return ret;
811a6e3f4f3SSteve Lee }
812a6e3f4f3SSteve Lee 
813a6e3f4f3SSteve Lee static int max98390_dsm_calibrate(struct snd_soc_component *component)
814a6e3f4f3SSteve Lee {
815a6e3f4f3SSteve Lee 	unsigned int rdc, rdc_cal_result, temp;
816a6e3f4f3SSteve Lee 	unsigned int rdc_integer, rdc_factor;
817a6e3f4f3SSteve Lee 	struct max98390_priv *max98390 =
818a6e3f4f3SSteve Lee 		snd_soc_component_get_drvdata(component);
819a6e3f4f3SSteve Lee 
820a6e3f4f3SSteve Lee 	regmap_write(max98390->regmap, MAX98390_R203A_AMP_EN, 0x81);
821a6e3f4f3SSteve Lee 	regmap_write(max98390->regmap, MAX98390_R23FF_GLOBAL_EN, 0x01);
822a6e3f4f3SSteve Lee 
823a6e3f4f3SSteve Lee 	regmap_read(max98390->regmap,
824a6e3f4f3SSteve Lee 		THERMAL_RDC_RD_BACK_BYTE1, &rdc);
825a6e3f4f3SSteve Lee 	regmap_read(max98390->regmap,
826a6e3f4f3SSteve Lee 		THERMAL_RDC_RD_BACK_BYTE0, &rdc_cal_result);
827a6e3f4f3SSteve Lee 	rdc_cal_result |= (rdc << 8) & 0x0000FFFF;
828a6e3f4f3SSteve Lee 	if (rdc_cal_result)
829a6e3f4f3SSteve Lee 		max98390->ref_rdc_value = 268435456U / rdc_cal_result;
830a6e3f4f3SSteve Lee 
831a6e3f4f3SSteve Lee 	regmap_read(max98390->regmap, MAX98390_MEAS_ADC_CH2_READ, &temp);
832a6e3f4f3SSteve Lee 	max98390->ambient_temp_value = temp * 52 - 1188;
833a6e3f4f3SSteve Lee 
834a6e3f4f3SSteve Lee 	rdc_integer =  rdc_cal_result * 937  / 65536;
835a6e3f4f3SSteve Lee 	rdc_factor = ((rdc_cal_result * 937 * 100) / 65536)
836a6e3f4f3SSteve Lee 					- (rdc_integer * 100);
837a6e3f4f3SSteve Lee 
838a6e3f4f3SSteve Lee 	dev_info(component->dev, "rdc resistance about %d.%02d ohm, reg=0x%X temp reg=0x%X\n",
839a6e3f4f3SSteve Lee 		 rdc_integer, rdc_factor, rdc_cal_result, temp);
840a6e3f4f3SSteve Lee 
841a6e3f4f3SSteve Lee 	regmap_write(max98390->regmap, MAX98390_R23FF_GLOBAL_EN, 0x00);
842a6e3f4f3SSteve Lee 	regmap_write(max98390->regmap, MAX98390_R203A_AMP_EN, 0x80);
843a6e3f4f3SSteve Lee 
844a6e3f4f3SSteve Lee 	return 0;
845a6e3f4f3SSteve Lee }
846a6e3f4f3SSteve Lee 
8479ba4af79SSteve Lee static void max98390_init_regs(struct snd_soc_component *component)
8489ba4af79SSteve Lee {
8499ba4af79SSteve Lee 	struct max98390_priv *max98390 =
8509ba4af79SSteve Lee 		snd_soc_component_get_drvdata(component);
8519ba4af79SSteve Lee 
8529ba4af79SSteve Lee 	regmap_write(max98390->regmap, MAX98390_CLK_MON, 0x6f);
8539ba4af79SSteve Lee 	regmap_write(max98390->regmap, MAX98390_DAT_MON, 0x00);
8549ba4af79SSteve Lee 	regmap_write(max98390->regmap, MAX98390_PWR_GATE_CTL, 0x00);
8559ba4af79SSteve Lee 	regmap_write(max98390->regmap, MAX98390_PCM_RX_EN_A, 0x03);
8569ba4af79SSteve Lee 	regmap_write(max98390->regmap, MAX98390_ENV_TRACK_VOUT_HEADROOM, 0x0e);
8579ba4af79SSteve Lee 	regmap_write(max98390->regmap, MAX98390_BOOST_BYPASS1, 0x46);
8589ba4af79SSteve Lee 	regmap_write(max98390->regmap, MAX98390_FET_SCALING3, 0x03);
8599ba4af79SSteve Lee }
8609ba4af79SSteve Lee 
861a6e3f4f3SSteve Lee static int max98390_probe(struct snd_soc_component *component)
862a6e3f4f3SSteve Lee {
863a6e3f4f3SSteve Lee 	struct max98390_priv *max98390 =
864a6e3f4f3SSteve Lee 		snd_soc_component_get_drvdata(component);
865a6e3f4f3SSteve Lee 
866a6e3f4f3SSteve Lee 	regmap_write(max98390->regmap, MAX98390_SOFTWARE_RESET, 0x01);
867a6e3f4f3SSteve Lee 	/* Sleep reset settle time */
868a6e3f4f3SSteve Lee 	msleep(20);
869a6e3f4f3SSteve Lee 
8709ba4af79SSteve Lee 	/* Amp init setting */
8719ba4af79SSteve Lee 	max98390_init_regs(component);
872aa785705SSteve Lee 	/* Update dsm bin param */
873aa785705SSteve Lee 	max98390_dsm_init(component);
874a6e3f4f3SSteve Lee 
875a6e3f4f3SSteve Lee 	/* Dsm Setting */
876a6e3f4f3SSteve Lee 	if (max98390->ref_rdc_value) {
877a6e3f4f3SSteve Lee 		regmap_write(max98390->regmap, DSM_TPROT_RECIP_RDC_ROOM_BYTE0,
878a6e3f4f3SSteve Lee 			max98390->ref_rdc_value & 0x000000ff);
879a6e3f4f3SSteve Lee 		regmap_write(max98390->regmap, DSM_TPROT_RECIP_RDC_ROOM_BYTE1,
880a6e3f4f3SSteve Lee 			(max98390->ref_rdc_value >> 8) & 0x000000ff);
881a6e3f4f3SSteve Lee 		regmap_write(max98390->regmap, DSM_TPROT_RECIP_RDC_ROOM_BYTE2,
882a6e3f4f3SSteve Lee 			(max98390->ref_rdc_value >> 16) & 0x000000ff);
883a6e3f4f3SSteve Lee 	}
884a6e3f4f3SSteve Lee 	if (max98390->ambient_temp_value) {
885a6e3f4f3SSteve Lee 		regmap_write(max98390->regmap, DSM_TPROT_ROOM_TEMPERATURE_BYTE1,
886a6e3f4f3SSteve Lee 			(max98390->ambient_temp_value >> 8) & 0x000000ff);
887a6e3f4f3SSteve Lee 		regmap_write(max98390->regmap, DSM_TPROT_ROOM_TEMPERATURE_BYTE0,
888a6e3f4f3SSteve Lee 			(max98390->ambient_temp_value) & 0x000000ff);
889a6e3f4f3SSteve Lee 	}
890a6e3f4f3SSteve Lee 
891a6e3f4f3SSteve Lee 	return 0;
892a6e3f4f3SSteve Lee }
893a6e3f4f3SSteve Lee 
894a6e3f4f3SSteve Lee #ifdef CONFIG_PM_SLEEP
895a6e3f4f3SSteve Lee static int max98390_suspend(struct device *dev)
896a6e3f4f3SSteve Lee {
897a6e3f4f3SSteve Lee 	struct max98390_priv *max98390 = dev_get_drvdata(dev);
898a6e3f4f3SSteve Lee 
899a6e3f4f3SSteve Lee 	dev_dbg(dev, "%s:Enter\n", __func__);
900a6e3f4f3SSteve Lee 
901a6e3f4f3SSteve Lee 	regcache_cache_only(max98390->regmap, true);
902a6e3f4f3SSteve Lee 	regcache_mark_dirty(max98390->regmap);
903a6e3f4f3SSteve Lee 
904a6e3f4f3SSteve Lee 	return 0;
905a6e3f4f3SSteve Lee }
906a6e3f4f3SSteve Lee 
907a6e3f4f3SSteve Lee static int max98390_resume(struct device *dev)
908a6e3f4f3SSteve Lee {
909a6e3f4f3SSteve Lee 	struct max98390_priv *max98390 = dev_get_drvdata(dev);
910a6e3f4f3SSteve Lee 
911a6e3f4f3SSteve Lee 	dev_dbg(dev, "%s:Enter\n", __func__);
912a6e3f4f3SSteve Lee 
913a6e3f4f3SSteve Lee 	regcache_cache_only(max98390->regmap, false);
914a6e3f4f3SSteve Lee 	regcache_sync(max98390->regmap);
915a6e3f4f3SSteve Lee 
916a6e3f4f3SSteve Lee 	return 0;
917a6e3f4f3SSteve Lee }
918a6e3f4f3SSteve Lee #endif
919a6e3f4f3SSteve Lee 
920a6e3f4f3SSteve Lee static const struct dev_pm_ops max98390_pm = {
921a6e3f4f3SSteve Lee 	SET_SYSTEM_SLEEP_PM_OPS(max98390_suspend, max98390_resume)
922a6e3f4f3SSteve Lee };
923a6e3f4f3SSteve Lee 
924a6e3f4f3SSteve Lee static const struct snd_soc_component_driver soc_codec_dev_max98390 = {
925a6e3f4f3SSteve Lee 	.probe			= max98390_probe,
926a6e3f4f3SSteve Lee 	.controls		= max98390_snd_controls,
927a6e3f4f3SSteve Lee 	.num_controls		= ARRAY_SIZE(max98390_snd_controls),
928a6e3f4f3SSteve Lee 	.dapm_widgets		= max98390_dapm_widgets,
929a6e3f4f3SSteve Lee 	.num_dapm_widgets	= ARRAY_SIZE(max98390_dapm_widgets),
930a6e3f4f3SSteve Lee 	.dapm_routes		= max98390_audio_map,
931a6e3f4f3SSteve Lee 	.num_dapm_routes	= ARRAY_SIZE(max98390_audio_map),
932a6e3f4f3SSteve Lee 	.idle_bias_on		= 1,
933a6e3f4f3SSteve Lee 	.use_pmdown_time	= 1,
934a6e3f4f3SSteve Lee 	.endianness		= 1,
935a6e3f4f3SSteve Lee 	.non_legacy_dai_naming	= 1,
936a6e3f4f3SSteve Lee };
937a6e3f4f3SSteve Lee 
938a6e3f4f3SSteve Lee static const struct regmap_config max98390_regmap = {
939a6e3f4f3SSteve Lee 	.reg_bits         = 16,
940a6e3f4f3SSteve Lee 	.val_bits         = 8,
941a6e3f4f3SSteve Lee 	.max_register     = MAX98390_R24FF_REV_ID,
942a6e3f4f3SSteve Lee 	.reg_defaults     = max98390_reg_defaults,
943a6e3f4f3SSteve Lee 	.num_reg_defaults = ARRAY_SIZE(max98390_reg_defaults),
944a6e3f4f3SSteve Lee 	.readable_reg	  = max98390_readable_register,
945a6e3f4f3SSteve Lee 	.volatile_reg	  = max98390_volatile_reg,
946a6e3f4f3SSteve Lee 	.cache_type       = REGCACHE_RBTREE,
947a6e3f4f3SSteve Lee };
948a6e3f4f3SSteve Lee 
949a6e3f4f3SSteve Lee static int max98390_i2c_probe(struct i2c_client *i2c,
950a6e3f4f3SSteve Lee 		const struct i2c_device_id *id)
951a6e3f4f3SSteve Lee {
952a6e3f4f3SSteve Lee 	int ret = 0;
953a6e3f4f3SSteve Lee 	int reg = 0;
954a6e3f4f3SSteve Lee 
955a6e3f4f3SSteve Lee 	struct max98390_priv *max98390 = NULL;
956a6e3f4f3SSteve Lee 	struct i2c_adapter *adapter = to_i2c_adapter(i2c->dev.parent);
957a6e3f4f3SSteve Lee 
958a6e3f4f3SSteve Lee 	ret = i2c_check_functionality(adapter,
959a6e3f4f3SSteve Lee 		I2C_FUNC_SMBUS_BYTE
960a6e3f4f3SSteve Lee 		| I2C_FUNC_SMBUS_BYTE_DATA);
961a6e3f4f3SSteve Lee 	if (!ret) {
962a6e3f4f3SSteve Lee 		dev_err(&i2c->dev, "I2C check functionality failed\n");
963a6e3f4f3SSteve Lee 		return -ENXIO;
964a6e3f4f3SSteve Lee 	}
965a6e3f4f3SSteve Lee 
966a6e3f4f3SSteve Lee 	max98390 = devm_kzalloc(&i2c->dev, sizeof(*max98390), GFP_KERNEL);
967a6e3f4f3SSteve Lee 	if (!max98390) {
968a6e3f4f3SSteve Lee 		ret = -ENOMEM;
969a6e3f4f3SSteve Lee 		return ret;
970a6e3f4f3SSteve Lee 	}
971a6e3f4f3SSteve Lee 	i2c_set_clientdata(i2c, max98390);
972a6e3f4f3SSteve Lee 
973a6e3f4f3SSteve Lee 	ret = device_property_read_u32(&i2c->dev, "maxim,temperature_calib",
974a6e3f4f3SSteve Lee 				       &max98390->ambient_temp_value);
975a6e3f4f3SSteve Lee 	if (ret) {
976a6e3f4f3SSteve Lee 		dev_info(&i2c->dev,
977a6e3f4f3SSteve Lee 			 "no optional property 'temperature_calib' found, default:\n");
978a6e3f4f3SSteve Lee 	}
979a6e3f4f3SSteve Lee 	ret = device_property_read_u32(&i2c->dev, "maxim,r0_calib",
980a6e3f4f3SSteve Lee 				       &max98390->ref_rdc_value);
981a6e3f4f3SSteve Lee 	if (ret) {
982a6e3f4f3SSteve Lee 		dev_info(&i2c->dev,
983a6e3f4f3SSteve Lee 			 "no optional property 'r0_calib' found, default:\n");
984a6e3f4f3SSteve Lee 	}
985a6e3f4f3SSteve Lee 
986a6e3f4f3SSteve Lee 	dev_info(&i2c->dev,
987a6e3f4f3SSteve Lee 		"%s: r0_calib: 0x%x,temperature_calib: 0x%x",
988a6e3f4f3SSteve Lee 		__func__, max98390->ref_rdc_value,
989a6e3f4f3SSteve Lee 		max98390->ambient_temp_value);
990a6e3f4f3SSteve Lee 
991a6e3f4f3SSteve Lee 	/* regmap initialization */
992a6e3f4f3SSteve Lee 	max98390->regmap = devm_regmap_init_i2c(i2c, &max98390_regmap);
993a6e3f4f3SSteve Lee 	if (IS_ERR(max98390->regmap)) {
994a6e3f4f3SSteve Lee 		ret = PTR_ERR(max98390->regmap);
995a6e3f4f3SSteve Lee 		dev_err(&i2c->dev,
996a6e3f4f3SSteve Lee 			"Failed to allocate regmap: %d\n", ret);
997a6e3f4f3SSteve Lee 		return ret;
998a6e3f4f3SSteve Lee 	}
999a6e3f4f3SSteve Lee 
1000a6e3f4f3SSteve Lee 	/* Check Revision ID */
1001a6e3f4f3SSteve Lee 	ret = regmap_read(max98390->regmap,
1002a6e3f4f3SSteve Lee 		MAX98390_R24FF_REV_ID, &reg);
1003a6e3f4f3SSteve Lee 	if (ret) {
1004a6e3f4f3SSteve Lee 		dev_err(&i2c->dev,
1005a6e3f4f3SSteve Lee 			"ret=%d, Failed to read: 0x%02X\n",
1006a6e3f4f3SSteve Lee 			ret, MAX98390_R24FF_REV_ID);
1007a6e3f4f3SSteve Lee 		return ret;
1008a6e3f4f3SSteve Lee 	}
1009a6e3f4f3SSteve Lee 	dev_info(&i2c->dev, "MAX98390 revisionID: 0x%02X\n", reg);
1010a6e3f4f3SSteve Lee 
1011a6e3f4f3SSteve Lee 	ret = devm_snd_soc_register_component(&i2c->dev,
1012a6e3f4f3SSteve Lee 			&soc_codec_dev_max98390,
1013a6e3f4f3SSteve Lee 			max98390_dai, ARRAY_SIZE(max98390_dai));
1014a6e3f4f3SSteve Lee 
1015a6e3f4f3SSteve Lee 	return ret;
1016a6e3f4f3SSteve Lee }
1017a6e3f4f3SSteve Lee 
1018a6e3f4f3SSteve Lee static const struct i2c_device_id max98390_i2c_id[] = {
1019a6e3f4f3SSteve Lee 	{ "max98390", 0},
1020a6e3f4f3SSteve Lee 	{},
1021a6e3f4f3SSteve Lee };
1022a6e3f4f3SSteve Lee 
1023a6e3f4f3SSteve Lee MODULE_DEVICE_TABLE(i2c, max98390_i2c_id);
1024a6e3f4f3SSteve Lee 
1025a6e3f4f3SSteve Lee #if defined(CONFIG_OF)
1026a6e3f4f3SSteve Lee static const struct of_device_id max98390_of_match[] = {
1027a6e3f4f3SSteve Lee 	{ .compatible = "maxim,max98390", },
1028a6e3f4f3SSteve Lee 	{}
1029a6e3f4f3SSteve Lee };
1030a6e3f4f3SSteve Lee MODULE_DEVICE_TABLE(of, max98390_of_match);
1031a6e3f4f3SSteve Lee #endif
1032a6e3f4f3SSteve Lee 
1033a6e3f4f3SSteve Lee #ifdef CONFIG_ACPI
1034a6e3f4f3SSteve Lee static const struct acpi_device_id max98390_acpi_match[] = {
1035a6e3f4f3SSteve Lee 	{ "MX98390", 0 },
1036a6e3f4f3SSteve Lee 	{},
1037a6e3f4f3SSteve Lee };
1038a6e3f4f3SSteve Lee MODULE_DEVICE_TABLE(acpi, max98390_acpi_match);
1039a6e3f4f3SSteve Lee #endif
1040a6e3f4f3SSteve Lee 
1041a6e3f4f3SSteve Lee static struct i2c_driver max98390_i2c_driver = {
1042a6e3f4f3SSteve Lee 	.driver = {
1043a6e3f4f3SSteve Lee 		.name = "max98390",
1044a6e3f4f3SSteve Lee 		.of_match_table = of_match_ptr(max98390_of_match),
1045a6e3f4f3SSteve Lee 		.acpi_match_table = ACPI_PTR(max98390_acpi_match),
1046a6e3f4f3SSteve Lee 		.pm = &max98390_pm,
1047a6e3f4f3SSteve Lee 	},
1048a6e3f4f3SSteve Lee 	.probe = max98390_i2c_probe,
1049a6e3f4f3SSteve Lee 	.id_table = max98390_i2c_id,
1050a6e3f4f3SSteve Lee };
1051a6e3f4f3SSteve Lee 
1052a6e3f4f3SSteve Lee module_i2c_driver(max98390_i2c_driver)
1053a6e3f4f3SSteve Lee 
1054a6e3f4f3SSteve Lee MODULE_DESCRIPTION("ALSA SoC MAX98390 driver");
1055a6e3f4f3SSteve Lee MODULE_AUTHOR("Steve Lee <steves.lee@maximintegrated.com>");
1056a6e3f4f3SSteve Lee MODULE_LICENSE("GPL");
1057