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