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