1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* |
3 | * max98927.c -- MAX98927 ALSA Soc Audio driver |
4 | * |
5 | * Copyright (C) 2016-2017 Maxim Integrated Products |
6 | * Author: Ryan Lee <ryans.lee@maximintegrated.com> |
7 | */ |
8 | |
9 | #include <linux/acpi.h> |
10 | #include <linux/i2c.h> |
11 | #include <linux/module.h> |
12 | #include <linux/regmap.h> |
13 | #include <linux/slab.h> |
14 | #include <linux/cdev.h> |
15 | #include <sound/pcm.h> |
16 | #include <sound/pcm_params.h> |
17 | #include <sound/soc.h> |
18 | #include <linux/gpio/consumer.h> |
19 | #include <sound/tlv.h> |
20 | #include "max98927.h" |
21 | |
22 | static struct reg_default max98927_reg[] = { |
23 | {MAX98927_R0001_INT_RAW1, 0x00}, |
24 | {MAX98927_R0002_INT_RAW2, 0x00}, |
25 | {MAX98927_R0003_INT_RAW3, 0x00}, |
26 | {MAX98927_R0004_INT_STATE1, 0x00}, |
27 | {MAX98927_R0005_INT_STATE2, 0x00}, |
28 | {MAX98927_R0006_INT_STATE3, 0x00}, |
29 | {MAX98927_R0007_INT_FLAG1, 0x00}, |
30 | {MAX98927_R0008_INT_FLAG2, 0x00}, |
31 | {MAX98927_R0009_INT_FLAG3, 0x00}, |
32 | {MAX98927_R000A_INT_EN1, 0x00}, |
33 | {MAX98927_R000B_INT_EN2, 0x00}, |
34 | {MAX98927_R000C_INT_EN3, 0x00}, |
35 | {MAX98927_R000D_INT_FLAG_CLR1, 0x00}, |
36 | {MAX98927_R000E_INT_FLAG_CLR2, 0x00}, |
37 | {MAX98927_R000F_INT_FLAG_CLR3, 0x00}, |
38 | {MAX98927_R0010_IRQ_CTRL, 0x00}, |
39 | {MAX98927_R0011_CLK_MON, 0x00}, |
40 | {MAX98927_R0012_WDOG_CTRL, 0x00}, |
41 | {MAX98927_R0013_WDOG_RST, 0x00}, |
42 | {MAX98927_R0014_MEAS_ADC_THERM_WARN_THRESH, 0x75}, |
43 | {MAX98927_R0015_MEAS_ADC_THERM_SHDN_THRESH, 0x8c}, |
44 | {MAX98927_R0016_MEAS_ADC_THERM_HYSTERESIS, 0x08}, |
45 | {MAX98927_R0017_PIN_CFG, 0x55}, |
46 | {MAX98927_R0018_PCM_RX_EN_A, 0x00}, |
47 | {MAX98927_R0019_PCM_RX_EN_B, 0x00}, |
48 | {MAX98927_R001A_PCM_TX_EN_A, 0x00}, |
49 | {MAX98927_R001B_PCM_TX_EN_B, 0x00}, |
50 | {MAX98927_R001C_PCM_TX_HIZ_CTRL_A, 0x00}, |
51 | {MAX98927_R001D_PCM_TX_HIZ_CTRL_B, 0x00}, |
52 | {MAX98927_R001E_PCM_TX_CH_SRC_A, 0x00}, |
53 | {MAX98927_R001F_PCM_TX_CH_SRC_B, 0x00}, |
54 | {MAX98927_R0020_PCM_MODE_CFG, 0x40}, |
55 | {MAX98927_R0021_PCM_MASTER_MODE, 0x00}, |
56 | {MAX98927_R0022_PCM_CLK_SETUP, 0x22}, |
57 | {MAX98927_R0023_PCM_SR_SETUP1, 0x00}, |
58 | {MAX98927_R0024_PCM_SR_SETUP2, 0x00}, |
59 | {MAX98927_R0025_PCM_TO_SPK_MONOMIX_A, 0x00}, |
60 | {MAX98927_R0026_PCM_TO_SPK_MONOMIX_B, 0x00}, |
61 | {MAX98927_R0027_ICC_RX_EN_A, 0x00}, |
62 | {MAX98927_R0028_ICC_RX_EN_B, 0x00}, |
63 | {MAX98927_R002B_ICC_TX_EN_A, 0x00}, |
64 | {MAX98927_R002C_ICC_TX_EN_B, 0x00}, |
65 | {MAX98927_R002E_ICC_HIZ_MANUAL_MODE, 0x00}, |
66 | {MAX98927_R002F_ICC_TX_HIZ_EN_A, 0x00}, |
67 | {MAX98927_R0030_ICC_TX_HIZ_EN_B, 0x00}, |
68 | {MAX98927_R0031_ICC_LNK_EN, 0x00}, |
69 | {MAX98927_R0032_PDM_TX_EN, 0x00}, |
70 | {MAX98927_R0033_PDM_TX_HIZ_CTRL, 0x00}, |
71 | {MAX98927_R0034_PDM_TX_CTRL, 0x00}, |
72 | {MAX98927_R0035_PDM_RX_CTRL, 0x00}, |
73 | {MAX98927_R0036_AMP_VOL_CTRL, 0x00}, |
74 | {MAX98927_R0037_AMP_DSP_CFG, 0x02}, |
75 | {MAX98927_R0038_TONE_GEN_DC_CFG, 0x00}, |
76 | {MAX98927_R0039_DRE_CTRL, 0x01}, |
77 | {MAX98927_R003A_AMP_EN, 0x00}, |
78 | {MAX98927_R003B_SPK_SRC_SEL, 0x00}, |
79 | {MAX98927_R003C_SPK_GAIN, 0x00}, |
80 | {MAX98927_R003D_SSM_CFG, 0x04}, |
81 | {MAX98927_R003E_MEAS_EN, 0x00}, |
82 | {MAX98927_R003F_MEAS_DSP_CFG, 0x04}, |
83 | {MAX98927_R0040_BOOST_CTRL0, 0x00}, |
84 | {MAX98927_R0041_BOOST_CTRL3, 0x00}, |
85 | {MAX98927_R0042_BOOST_CTRL1, 0x00}, |
86 | {MAX98927_R0043_MEAS_ADC_CFG, 0x00}, |
87 | {MAX98927_R0044_MEAS_ADC_BASE_MSB, 0x01}, |
88 | {MAX98927_R0045_MEAS_ADC_BASE_LSB, 0x00}, |
89 | {MAX98927_R0046_ADC_CH0_DIVIDE, 0x00}, |
90 | {MAX98927_R0047_ADC_CH1_DIVIDE, 0x00}, |
91 | {MAX98927_R0048_ADC_CH2_DIVIDE, 0x00}, |
92 | {MAX98927_R0049_ADC_CH0_FILT_CFG, 0x00}, |
93 | {MAX98927_R004A_ADC_CH1_FILT_CFG, 0x00}, |
94 | {MAX98927_R004B_ADC_CH2_FILT_CFG, 0x00}, |
95 | {MAX98927_R004C_MEAS_ADC_CH0_READ, 0x00}, |
96 | {MAX98927_R004D_MEAS_ADC_CH1_READ, 0x00}, |
97 | {MAX98927_R004E_MEAS_ADC_CH2_READ, 0x00}, |
98 | {MAX98927_R0051_BROWNOUT_STATUS, 0x00}, |
99 | {MAX98927_R0052_BROWNOUT_EN, 0x00}, |
100 | {MAX98927_R0053_BROWNOUT_INFINITE_HOLD, 0x00}, |
101 | {MAX98927_R0054_BROWNOUT_INFINITE_HOLD_CLR, 0x00}, |
102 | {MAX98927_R0055_BROWNOUT_LVL_HOLD, 0x00}, |
103 | {MAX98927_R005A_BROWNOUT_LVL1_THRESH, 0x00}, |
104 | {MAX98927_R005B_BROWNOUT_LVL2_THRESH, 0x00}, |
105 | {MAX98927_R005C_BROWNOUT_LVL3_THRESH, 0x00}, |
106 | {MAX98927_R005D_BROWNOUT_LVL4_THRESH, 0x00}, |
107 | {MAX98927_R005E_BROWNOUT_THRESH_HYSTERYSIS, 0x00}, |
108 | {MAX98927_R005F_BROWNOUT_AMP_LIMITER_ATK_REL, 0x00}, |
109 | {MAX98927_R0060_BROWNOUT_AMP_GAIN_ATK_REL, 0x00}, |
110 | {MAX98927_R0061_BROWNOUT_AMP1_CLIP_MODE, 0x00}, |
111 | {MAX98927_R0072_BROWNOUT_LVL1_CUR_LIMIT, 0x00}, |
112 | {MAX98927_R0073_BROWNOUT_LVL1_AMP1_CTRL1, 0x00}, |
113 | {MAX98927_R0074_BROWNOUT_LVL1_AMP1_CTRL2, 0x00}, |
114 | {MAX98927_R0075_BROWNOUT_LVL1_AMP1_CTRL3, 0x00}, |
115 | {MAX98927_R0076_BROWNOUT_LVL2_CUR_LIMIT, 0x00}, |
116 | {MAX98927_R0077_BROWNOUT_LVL2_AMP1_CTRL1, 0x00}, |
117 | {MAX98927_R0078_BROWNOUT_LVL2_AMP1_CTRL2, 0x00}, |
118 | {MAX98927_R0079_BROWNOUT_LVL2_AMP1_CTRL3, 0x00}, |
119 | {MAX98927_R007A_BROWNOUT_LVL3_CUR_LIMIT, 0x00}, |
120 | {MAX98927_R007B_BROWNOUT_LVL3_AMP1_CTRL1, 0x00}, |
121 | {MAX98927_R007C_BROWNOUT_LVL3_AMP1_CTRL2, 0x00}, |
122 | {MAX98927_R007D_BROWNOUT_LVL3_AMP1_CTRL3, 0x00}, |
123 | {MAX98927_R007E_BROWNOUT_LVL4_CUR_LIMIT, 0x00}, |
124 | {MAX98927_R007F_BROWNOUT_LVL4_AMP1_CTRL1, 0x00}, |
125 | {MAX98927_R0080_BROWNOUT_LVL4_AMP1_CTRL2, 0x00}, |
126 | {MAX98927_R0081_BROWNOUT_LVL4_AMP1_CTRL3, 0x00}, |
127 | {MAX98927_R0082_ENV_TRACK_VOUT_HEADROOM, 0x00}, |
128 | {MAX98927_R0083_ENV_TRACK_BOOST_VOUT_DELAY, 0x00}, |
129 | {MAX98927_R0084_ENV_TRACK_REL_RATE, 0x00}, |
130 | {MAX98927_R0085_ENV_TRACK_HOLD_RATE, 0x00}, |
131 | {MAX98927_R0086_ENV_TRACK_CTRL, 0x00}, |
132 | {MAX98927_R0087_ENV_TRACK_BOOST_VOUT_READ, 0x00}, |
133 | {MAX98927_R00FF_GLOBAL_SHDN, 0x00}, |
134 | {MAX98927_R0100_SOFT_RESET, 0x00}, |
135 | {MAX98927_R01FF_REV_ID, 0x40}, |
136 | }; |
137 | |
138 | static int max98927_dai_set_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) |
139 | { |
140 | struct snd_soc_component *component = codec_dai->component; |
141 | struct max98927_priv *max98927 = snd_soc_component_get_drvdata(c: component); |
142 | unsigned int mode = 0; |
143 | unsigned int format = 0; |
144 | bool use_pdm = false; |
145 | unsigned int invert = 0; |
146 | |
147 | dev_dbg(component->dev, "%s: fmt 0x%08X\n" , __func__, fmt); |
148 | |
149 | switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { |
150 | case SND_SOC_DAIFMT_CBC_CFC: |
151 | max98927->provider = false; |
152 | mode = MAX98927_PCM_MASTER_MODE_SLAVE; |
153 | break; |
154 | case SND_SOC_DAIFMT_CBP_CFP: |
155 | max98927->provider = true; |
156 | mode = MAX98927_PCM_MASTER_MODE_MASTER; |
157 | break; |
158 | default: |
159 | dev_err(component->dev, "DAI clock mode unsupported\n" ); |
160 | return -EINVAL; |
161 | } |
162 | |
163 | regmap_update_bits(map: max98927->regmap, MAX98927_R0021_PCM_MASTER_MODE, |
164 | MAX98927_PCM_MASTER_MODE_MASK, val: mode); |
165 | |
166 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { |
167 | case SND_SOC_DAIFMT_NB_NF: |
168 | break; |
169 | case SND_SOC_DAIFMT_IB_NF: |
170 | invert = MAX98927_PCM_MODE_CFG_PCM_BCLKEDGE; |
171 | break; |
172 | default: |
173 | dev_err(component->dev, "DAI invert mode unsupported\n" ); |
174 | return -EINVAL; |
175 | } |
176 | |
177 | regmap_update_bits(map: max98927->regmap, MAX98927_R0020_PCM_MODE_CFG, |
178 | MAX98927_PCM_MODE_CFG_PCM_BCLKEDGE, val: invert); |
179 | |
180 | /* interface format */ |
181 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { |
182 | case SND_SOC_DAIFMT_I2S: |
183 | format = MAX98927_PCM_FORMAT_I2S; |
184 | break; |
185 | case SND_SOC_DAIFMT_LEFT_J: |
186 | format = MAX98927_PCM_FORMAT_LJ; |
187 | break; |
188 | case SND_SOC_DAIFMT_DSP_A: |
189 | format = MAX98927_PCM_FORMAT_TDM_MODE1; |
190 | break; |
191 | case SND_SOC_DAIFMT_DSP_B: |
192 | format = MAX98927_PCM_FORMAT_TDM_MODE0; |
193 | break; |
194 | case SND_SOC_DAIFMT_PDM: |
195 | use_pdm = true; |
196 | break; |
197 | default: |
198 | return -EINVAL; |
199 | } |
200 | max98927->iface = fmt & SND_SOC_DAIFMT_FORMAT_MASK; |
201 | |
202 | if (!use_pdm) { |
203 | /* pcm channel configuration */ |
204 | regmap_update_bits(map: max98927->regmap, MAX98927_R0018_PCM_RX_EN_A, |
205 | MAX98927_PCM_RX_CH0_EN | MAX98927_PCM_RX_CH1_EN, |
206 | MAX98927_PCM_RX_CH0_EN | MAX98927_PCM_RX_CH1_EN); |
207 | |
208 | regmap_update_bits(map: max98927->regmap, |
209 | MAX98927_R0020_PCM_MODE_CFG, |
210 | MAX98927_PCM_MODE_CFG_FORMAT_MASK, |
211 | val: format << MAX98927_PCM_MODE_CFG_FORMAT_SHIFT); |
212 | |
213 | regmap_update_bits(map: max98927->regmap, MAX98927_R003B_SPK_SRC_SEL, |
214 | MAX98927_SPK_SRC_MASK, val: 0); |
215 | |
216 | regmap_update_bits(map: max98927->regmap, MAX98927_R0035_PDM_RX_CTRL, |
217 | MAX98927_PDM_RX_EN_MASK, val: 0); |
218 | } else { |
219 | /* pdm channel configuration */ |
220 | regmap_update_bits(map: max98927->regmap, MAX98927_R0035_PDM_RX_CTRL, |
221 | MAX98927_PDM_RX_EN_MASK, val: 1); |
222 | |
223 | regmap_update_bits(map: max98927->regmap, MAX98927_R003B_SPK_SRC_SEL, |
224 | MAX98927_SPK_SRC_MASK, val: 3); |
225 | |
226 | regmap_update_bits(map: max98927->regmap, MAX98927_R0018_PCM_RX_EN_A, |
227 | MAX98927_PCM_RX_CH0_EN | MAX98927_PCM_RX_CH1_EN, |
228 | val: 0); |
229 | } |
230 | return 0; |
231 | } |
232 | |
233 | /* codec MCLK rate in master mode */ |
234 | static const int rate_table[] = { |
235 | 5644800, 6000000, 6144000, 6500000, |
236 | 9600000, 11289600, 12000000, 12288000, |
237 | 13000000, 19200000, |
238 | }; |
239 | |
240 | /* BCLKs per LRCLK */ |
241 | static const int bclk_sel_table[] = { |
242 | 32, 48, 64, 96, 128, 192, 256, 384, 512, |
243 | }; |
244 | |
245 | static int max98927_get_bclk_sel(int bclk) |
246 | { |
247 | int i; |
248 | /* match BCLKs per LRCLK */ |
249 | for (i = 0; i < ARRAY_SIZE(bclk_sel_table); i++) { |
250 | if (bclk_sel_table[i] == bclk) |
251 | return i + 2; |
252 | } |
253 | return 0; |
254 | } |
255 | static int max98927_set_clock(struct max98927_priv *max98927, |
256 | struct snd_pcm_hw_params *params) |
257 | { |
258 | struct snd_soc_component *component = max98927->component; |
259 | /* BCLK/LRCLK ratio calculation */ |
260 | int blr_clk_ratio = params_channels(p: params) * max98927->ch_size; |
261 | int value; |
262 | |
263 | if (max98927->provider) { |
264 | int i; |
265 | /* match rate to closest value */ |
266 | for (i = 0; i < ARRAY_SIZE(rate_table); i++) { |
267 | if (rate_table[i] >= max98927->sysclk) |
268 | break; |
269 | } |
270 | if (i == ARRAY_SIZE(rate_table)) { |
271 | dev_err(component->dev, "failed to find proper clock rate.\n" ); |
272 | return -EINVAL; |
273 | } |
274 | regmap_update_bits(map: max98927->regmap, |
275 | MAX98927_R0021_PCM_MASTER_MODE, |
276 | MAX98927_PCM_MASTER_MODE_MCLK_MASK, |
277 | val: i << MAX98927_PCM_MASTER_MODE_MCLK_RATE_SHIFT); |
278 | } |
279 | |
280 | if (!max98927->tdm_mode) { |
281 | /* BCLK configuration */ |
282 | value = max98927_get_bclk_sel(bclk: blr_clk_ratio); |
283 | if (!value) { |
284 | dev_err(component->dev, "format unsupported %d\n" , |
285 | params_format(params)); |
286 | return -EINVAL; |
287 | } |
288 | |
289 | regmap_update_bits(map: max98927->regmap, |
290 | MAX98927_R0022_PCM_CLK_SETUP, |
291 | MAX98927_PCM_CLK_SETUP_BSEL_MASK, val: value); |
292 | } |
293 | return 0; |
294 | } |
295 | |
296 | static int max98927_dai_hw_params(struct snd_pcm_substream *substream, |
297 | struct snd_pcm_hw_params *params, |
298 | struct snd_soc_dai *dai) |
299 | { |
300 | struct snd_soc_component *component = dai->component; |
301 | struct max98927_priv *max98927 = snd_soc_component_get_drvdata(c: component); |
302 | unsigned int sampling_rate = 0; |
303 | unsigned int chan_sz = 0; |
304 | |
305 | /* pcm mode configuration */ |
306 | switch (snd_pcm_format_width(format: params_format(p: params))) { |
307 | case 16: |
308 | chan_sz = MAX98927_PCM_MODE_CFG_CHANSZ_16; |
309 | break; |
310 | case 24: |
311 | chan_sz = MAX98927_PCM_MODE_CFG_CHANSZ_24; |
312 | break; |
313 | case 32: |
314 | chan_sz = MAX98927_PCM_MODE_CFG_CHANSZ_32; |
315 | break; |
316 | default: |
317 | dev_err(component->dev, "format unsupported %d\n" , |
318 | params_format(params)); |
319 | goto err; |
320 | } |
321 | |
322 | max98927->ch_size = snd_pcm_format_width(format: params_format(p: params)); |
323 | |
324 | regmap_update_bits(map: max98927->regmap, MAX98927_R0020_PCM_MODE_CFG, |
325 | MAX98927_PCM_MODE_CFG_CHANSZ_MASK, val: chan_sz); |
326 | |
327 | dev_dbg(component->dev, "format supported %d" , |
328 | params_format(params)); |
329 | |
330 | /* sampling rate configuration */ |
331 | switch (params_rate(p: params)) { |
332 | case 8000: |
333 | sampling_rate = MAX98927_PCM_SR_SET1_SR_8000; |
334 | break; |
335 | case 11025: |
336 | sampling_rate = MAX98927_PCM_SR_SET1_SR_11025; |
337 | break; |
338 | case 12000: |
339 | sampling_rate = MAX98927_PCM_SR_SET1_SR_12000; |
340 | break; |
341 | case 16000: |
342 | sampling_rate = MAX98927_PCM_SR_SET1_SR_16000; |
343 | break; |
344 | case 22050: |
345 | sampling_rate = MAX98927_PCM_SR_SET1_SR_22050; |
346 | break; |
347 | case 24000: |
348 | sampling_rate = MAX98927_PCM_SR_SET1_SR_24000; |
349 | break; |
350 | case 32000: |
351 | sampling_rate = MAX98927_PCM_SR_SET1_SR_32000; |
352 | break; |
353 | case 44100: |
354 | sampling_rate = MAX98927_PCM_SR_SET1_SR_44100; |
355 | break; |
356 | case 48000: |
357 | sampling_rate = MAX98927_PCM_SR_SET1_SR_48000; |
358 | break; |
359 | default: |
360 | dev_err(component->dev, "rate %d not supported\n" , |
361 | params_rate(params)); |
362 | goto err; |
363 | } |
364 | /* set DAI_SR to correct LRCLK frequency */ |
365 | regmap_update_bits(map: max98927->regmap, MAX98927_R0023_PCM_SR_SETUP1, |
366 | MAX98927_PCM_SR_SET1_SR_MASK, val: sampling_rate); |
367 | regmap_update_bits(map: max98927->regmap, MAX98927_R0024_PCM_SR_SETUP2, |
368 | MAX98927_PCM_SR_SET2_SR_MASK, |
369 | val: sampling_rate << MAX98927_PCM_SR_SET2_SR_SHIFT); |
370 | |
371 | /* set sampling rate of IV */ |
372 | if (max98927->interleave_mode && |
373 | sampling_rate > MAX98927_PCM_SR_SET1_SR_16000) |
374 | regmap_update_bits(map: max98927->regmap, |
375 | MAX98927_R0024_PCM_SR_SETUP2, |
376 | MAX98927_PCM_SR_SET2_IVADC_SR_MASK, |
377 | val: sampling_rate - 3); |
378 | else |
379 | regmap_update_bits(map: max98927->regmap, |
380 | MAX98927_R0024_PCM_SR_SETUP2, |
381 | MAX98927_PCM_SR_SET2_IVADC_SR_MASK, |
382 | val: sampling_rate); |
383 | return max98927_set_clock(max98927, params); |
384 | err: |
385 | return -EINVAL; |
386 | } |
387 | |
388 | static int max98927_dai_tdm_slot(struct snd_soc_dai *dai, |
389 | unsigned int tx_mask, unsigned int rx_mask, |
390 | int slots, int slot_width) |
391 | { |
392 | struct snd_soc_component *component = dai->component; |
393 | struct max98927_priv *max98927 = snd_soc_component_get_drvdata(c: component); |
394 | int bsel = 0; |
395 | unsigned int chan_sz = 0; |
396 | |
397 | max98927->tdm_mode = true; |
398 | |
399 | /* BCLK configuration */ |
400 | bsel = max98927_get_bclk_sel(bclk: slots * slot_width); |
401 | if (bsel == 0) { |
402 | dev_err(component->dev, "BCLK %d not supported\n" , |
403 | slots * slot_width); |
404 | return -EINVAL; |
405 | } |
406 | |
407 | regmap_update_bits(map: max98927->regmap, MAX98927_R0022_PCM_CLK_SETUP, |
408 | MAX98927_PCM_CLK_SETUP_BSEL_MASK, val: bsel); |
409 | |
410 | /* Channel size configuration */ |
411 | switch (slot_width) { |
412 | case 16: |
413 | chan_sz = MAX98927_PCM_MODE_CFG_CHANSZ_16; |
414 | break; |
415 | case 24: |
416 | chan_sz = MAX98927_PCM_MODE_CFG_CHANSZ_24; |
417 | break; |
418 | case 32: |
419 | chan_sz = MAX98927_PCM_MODE_CFG_CHANSZ_32; |
420 | break; |
421 | default: |
422 | dev_err(component->dev, "format unsupported %d\n" , |
423 | slot_width); |
424 | return -EINVAL; |
425 | } |
426 | |
427 | regmap_update_bits(map: max98927->regmap, MAX98927_R0020_PCM_MODE_CFG, |
428 | MAX98927_PCM_MODE_CFG_CHANSZ_MASK, val: chan_sz); |
429 | |
430 | /* Rx slot configuration */ |
431 | regmap_write(map: max98927->regmap, MAX98927_R0018_PCM_RX_EN_A, |
432 | val: rx_mask & 0xFF); |
433 | regmap_write(map: max98927->regmap, MAX98927_R0019_PCM_RX_EN_B, |
434 | val: (rx_mask & 0xFF00) >> 8); |
435 | |
436 | /* Tx slot configuration */ |
437 | regmap_write(map: max98927->regmap, MAX98927_R001A_PCM_TX_EN_A, |
438 | val: tx_mask & 0xFF); |
439 | regmap_write(map: max98927->regmap, MAX98927_R001B_PCM_TX_EN_B, |
440 | val: (tx_mask & 0xFF00) >> 8); |
441 | |
442 | /* Tx slot Hi-Z configuration */ |
443 | regmap_write(map: max98927->regmap, MAX98927_R001C_PCM_TX_HIZ_CTRL_A, |
444 | val: ~tx_mask & 0xFF); |
445 | regmap_write(map: max98927->regmap, MAX98927_R001D_PCM_TX_HIZ_CTRL_B, |
446 | val: (~tx_mask & 0xFF00) >> 8); |
447 | |
448 | return 0; |
449 | } |
450 | |
451 | #define MAX98927_RATES SNDRV_PCM_RATE_8000_48000 |
452 | |
453 | #define MAX98927_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \ |
454 | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) |
455 | |
456 | static int max98927_dai_set_sysclk(struct snd_soc_dai *dai, |
457 | int clk_id, unsigned int freq, int dir) |
458 | { |
459 | struct snd_soc_component *component = dai->component; |
460 | struct max98927_priv *max98927 = snd_soc_component_get_drvdata(c: component); |
461 | |
462 | max98927->sysclk = freq; |
463 | return 0; |
464 | } |
465 | |
466 | static const struct snd_soc_dai_ops max98927_dai_ops = { |
467 | .set_sysclk = max98927_dai_set_sysclk, |
468 | .set_fmt = max98927_dai_set_fmt, |
469 | .hw_params = max98927_dai_hw_params, |
470 | .set_tdm_slot = max98927_dai_tdm_slot, |
471 | }; |
472 | |
473 | static int max98927_dac_event(struct snd_soc_dapm_widget *w, |
474 | struct snd_kcontrol *kcontrol, int event) |
475 | { |
476 | struct snd_soc_component *component = snd_soc_dapm_to_component(dapm: w->dapm); |
477 | struct max98927_priv *max98927 = snd_soc_component_get_drvdata(c: component); |
478 | |
479 | switch (event) { |
480 | case SND_SOC_DAPM_PRE_PMU: |
481 | max98927->tdm_mode = false; |
482 | break; |
483 | case SND_SOC_DAPM_POST_PMU: |
484 | regmap_update_bits(map: max98927->regmap, MAX98927_R003A_AMP_EN, |
485 | MAX98927_AMP_EN_MASK, val: 1); |
486 | regmap_update_bits(map: max98927->regmap, MAX98927_R00FF_GLOBAL_SHDN, |
487 | MAX98927_GLOBAL_EN_MASK, val: 1); |
488 | break; |
489 | case SND_SOC_DAPM_POST_PMD: |
490 | regmap_update_bits(map: max98927->regmap, MAX98927_R00FF_GLOBAL_SHDN, |
491 | MAX98927_GLOBAL_EN_MASK, val: 0); |
492 | regmap_update_bits(map: max98927->regmap, MAX98927_R003A_AMP_EN, |
493 | MAX98927_AMP_EN_MASK, val: 0); |
494 | break; |
495 | default: |
496 | return 0; |
497 | } |
498 | return 0; |
499 | } |
500 | |
501 | static const char * const max98927_switch_text[] = { |
502 | "Left" , "Right" , "LeftRight" }; |
503 | |
504 | static const struct soc_enum dai_sel_enum = |
505 | SOC_ENUM_SINGLE(MAX98927_R0025_PCM_TO_SPK_MONOMIX_A, |
506 | MAX98927_PCM_TO_SPK_MONOMIX_CFG_SHIFT, 3, |
507 | max98927_switch_text); |
508 | |
509 | static const struct snd_kcontrol_new max98927_dai_controls = |
510 | SOC_DAPM_ENUM("DAI Sel" , dai_sel_enum); |
511 | |
512 | static const struct snd_kcontrol_new max98927_vi_control = |
513 | SOC_DAPM_SINGLE("Switch" , MAX98927_R003F_MEAS_DSP_CFG, 2, 1, 0); |
514 | |
515 | static const struct snd_soc_dapm_widget max98927_dapm_widgets[] = { |
516 | SND_SOC_DAPM_DAC_E("Amp Enable" , "HiFi Playback" , MAX98927_R003A_AMP_EN, |
517 | 0, 0, max98927_dac_event, |
518 | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), |
519 | SND_SOC_DAPM_MUX("DAI Sel Mux" , SND_SOC_NOPM, 0, 0, |
520 | &max98927_dai_controls), |
521 | SND_SOC_DAPM_OUTPUT("BE_OUT" ), |
522 | SND_SOC_DAPM_AIF_OUT("Voltage Sense" , "HiFi Capture" , 0, |
523 | MAX98927_R003E_MEAS_EN, 0, 0), |
524 | SND_SOC_DAPM_AIF_OUT("Current Sense" , "HiFi Capture" , 0, |
525 | MAX98927_R003E_MEAS_EN, 1, 0), |
526 | SND_SOC_DAPM_SWITCH("VI Sense" , SND_SOC_NOPM, 0, 0, |
527 | &max98927_vi_control), |
528 | SND_SOC_DAPM_SIGGEN("VMON" ), |
529 | SND_SOC_DAPM_SIGGEN("IMON" ), |
530 | }; |
531 | |
532 | static DECLARE_TLV_DB_SCALE(max98927_spk_tlv, 300, 300, 0); |
533 | static DECLARE_TLV_DB_SCALE(max98927_digital_tlv, -1600, 25, 0); |
534 | |
535 | static bool max98927_readable_register(struct device *dev, unsigned int reg) |
536 | { |
537 | switch (reg) { |
538 | case MAX98927_R0001_INT_RAW1 ... MAX98927_R0028_ICC_RX_EN_B: |
539 | case MAX98927_R002B_ICC_TX_EN_A ... MAX98927_R002C_ICC_TX_EN_B: |
540 | case MAX98927_R002E_ICC_HIZ_MANUAL_MODE |
541 | ... MAX98927_R004E_MEAS_ADC_CH2_READ: |
542 | case MAX98927_R0051_BROWNOUT_STATUS |
543 | ... MAX98927_R0055_BROWNOUT_LVL_HOLD: |
544 | case MAX98927_R005A_BROWNOUT_LVL1_THRESH |
545 | ... MAX98927_R0061_BROWNOUT_AMP1_CLIP_MODE: |
546 | case MAX98927_R0072_BROWNOUT_LVL1_CUR_LIMIT |
547 | ... MAX98927_R0087_ENV_TRACK_BOOST_VOUT_READ: |
548 | case MAX98927_R00FF_GLOBAL_SHDN: |
549 | case MAX98927_R0100_SOFT_RESET: |
550 | case MAX98927_R01FF_REV_ID: |
551 | return true; |
552 | default: |
553 | return false; |
554 | } |
555 | }; |
556 | |
557 | static bool max98927_volatile_reg(struct device *dev, unsigned int reg) |
558 | { |
559 | switch (reg) { |
560 | case MAX98927_R0001_INT_RAW1 ... MAX98927_R0009_INT_FLAG3: |
561 | case MAX98927_R004C_MEAS_ADC_CH0_READ: |
562 | case MAX98927_R004D_MEAS_ADC_CH1_READ: |
563 | case MAX98927_R004E_MEAS_ADC_CH2_READ: |
564 | case MAX98927_R0051_BROWNOUT_STATUS: |
565 | case MAX98927_R0087_ENV_TRACK_BOOST_VOUT_READ: |
566 | case MAX98927_R01FF_REV_ID: |
567 | case MAX98927_R0100_SOFT_RESET: |
568 | return true; |
569 | default: |
570 | return false; |
571 | } |
572 | } |
573 | |
574 | static const char * const max98927_boost_voltage_text[] = { |
575 | "6.5V" , "6.625V" , "6.75V" , "6.875V" , "7V" , "7.125V" , "7.25V" , "7.375V" , |
576 | "7.5V" , "7.625V" , "7.75V" , "7.875V" , "8V" , "8.125V" , "8.25V" , "8.375V" , |
577 | "8.5V" , "8.625V" , "8.75V" , "8.875V" , "9V" , "9.125V" , "9.25V" , "9.375V" , |
578 | "9.5V" , "9.625V" , "9.75V" , "9.875V" , "10V" |
579 | }; |
580 | |
581 | static SOC_ENUM_SINGLE_DECL(max98927_boost_voltage, |
582 | MAX98927_R0040_BOOST_CTRL0, 0, |
583 | max98927_boost_voltage_text); |
584 | |
585 | static const char * const max98927_current_limit_text[] = { |
586 | "1.00A" , "1.10A" , "1.20A" , "1.30A" , "1.40A" , "1.50A" , "1.60A" , "1.70A" , |
587 | "1.80A" , "1.90A" , "2.00A" , "2.10A" , "2.20A" , "2.30A" , "2.40A" , "2.50A" , |
588 | "2.60A" , "2.70A" , "2.80A" , "2.90A" , "3.00A" , "3.10A" , "3.20A" , "3.30A" , |
589 | "3.40A" , "3.50A" , "3.60A" , "3.70A" , "3.80A" , "3.90A" , "4.00A" , "4.10A" |
590 | }; |
591 | |
592 | static SOC_ENUM_SINGLE_DECL(max98927_current_limit, |
593 | MAX98927_R0042_BOOST_CTRL1, 1, |
594 | max98927_current_limit_text); |
595 | |
596 | static const struct snd_kcontrol_new max98927_snd_controls[] = { |
597 | SOC_SINGLE_TLV("Speaker Volume" , MAX98927_R003C_SPK_GAIN, 0, 6, 0, |
598 | max98927_spk_tlv), |
599 | SOC_SINGLE_TLV("Digital Volume" , MAX98927_R0036_AMP_VOL_CTRL, |
600 | 0, (1 << MAX98927_AMP_VOL_WIDTH) - 1, 0, |
601 | max98927_digital_tlv), |
602 | SOC_SINGLE("Amp DSP Switch" , MAX98927_R0052_BROWNOUT_EN, |
603 | MAX98927_BROWNOUT_DSP_SHIFT, 1, 0), |
604 | SOC_SINGLE("Ramp Switch" , MAX98927_R0037_AMP_DSP_CFG, |
605 | MAX98927_AMP_DSP_CFG_RMP_SHIFT, 1, 0), |
606 | SOC_SINGLE("DRE Switch" , MAX98927_R0039_DRE_CTRL, MAX98927_DRE_EN_SHIFT, |
607 | 1, 0), |
608 | SOC_SINGLE("Volume Location Switch" , MAX98927_R0036_AMP_VOL_CTRL, |
609 | MAX98927_AMP_VOL_SEL_SHIFT, 1, 0), |
610 | SOC_ENUM("Boost Output Voltage" , max98927_boost_voltage), |
611 | SOC_ENUM("Current Limit" , max98927_current_limit), |
612 | }; |
613 | |
614 | static const struct snd_soc_dapm_route max98927_audio_map[] = { |
615 | /* Plabyack */ |
616 | {"DAI Sel Mux" , "Left" , "Amp Enable" }, |
617 | {"DAI Sel Mux" , "Right" , "Amp Enable" }, |
618 | {"DAI Sel Mux" , "LeftRight" , "Amp Enable" }, |
619 | {"BE_OUT" , NULL, "DAI Sel Mux" }, |
620 | /* Capture */ |
621 | { "VI Sense" , "Switch" , "VMON" }, |
622 | { "VI Sense" , "Switch" , "IMON" }, |
623 | { "Voltage Sense" , NULL, "VI Sense" }, |
624 | { "Current Sense" , NULL, "VI Sense" }, |
625 | }; |
626 | |
627 | static struct snd_soc_dai_driver max98927_dai[] = { |
628 | { |
629 | .name = "max98927-aif1" , |
630 | .playback = { |
631 | .stream_name = "HiFi Playback" , |
632 | .channels_min = 1, |
633 | .channels_max = 2, |
634 | .rates = MAX98927_RATES, |
635 | .formats = MAX98927_FORMATS, |
636 | }, |
637 | .capture = { |
638 | .stream_name = "HiFi Capture" , |
639 | .channels_min = 1, |
640 | .channels_max = 2, |
641 | .rates = MAX98927_RATES, |
642 | .formats = MAX98927_FORMATS, |
643 | }, |
644 | .ops = &max98927_dai_ops, |
645 | } |
646 | }; |
647 | |
648 | static int max98927_probe(struct snd_soc_component *component) |
649 | { |
650 | struct max98927_priv *max98927 = snd_soc_component_get_drvdata(c: component); |
651 | |
652 | max98927->component = component; |
653 | |
654 | /* Software Reset */ |
655 | regmap_write(map: max98927->regmap, MAX98927_R0100_SOFT_RESET, |
656 | MAX98927_SOFT_RESET); |
657 | |
658 | /* IV default slot configuration */ |
659 | regmap_write(map: max98927->regmap, MAX98927_R001C_PCM_TX_HIZ_CTRL_A, val: 0xFF); |
660 | regmap_write(map: max98927->regmap, MAX98927_R001D_PCM_TX_HIZ_CTRL_B, val: 0xFF); |
661 | regmap_write(map: max98927->regmap, MAX98927_R0025_PCM_TO_SPK_MONOMIX_A, |
662 | val: 0x80); |
663 | regmap_write(map: max98927->regmap, MAX98927_R0026_PCM_TO_SPK_MONOMIX_B, |
664 | val: 0x1); |
665 | /* Set inital volume (+13dB) */ |
666 | regmap_write(map: max98927->regmap, MAX98927_R0036_AMP_VOL_CTRL, val: 0x38); |
667 | regmap_write(map: max98927->regmap, MAX98927_R003C_SPK_GAIN, val: 0x05); |
668 | /* Enable DC blocker */ |
669 | regmap_write(map: max98927->regmap, MAX98927_R0037_AMP_DSP_CFG, val: 0x03); |
670 | /* Enable IMON VMON DC blocker */ |
671 | regmap_write(map: max98927->regmap, MAX98927_R003F_MEAS_DSP_CFG, val: 0xF7); |
672 | /* Boost Output Voltage & Current limit */ |
673 | regmap_write(map: max98927->regmap, MAX98927_R0040_BOOST_CTRL0, val: 0x1C); |
674 | regmap_write(map: max98927->regmap, MAX98927_R0042_BOOST_CTRL1, val: 0x3E); |
675 | /* Measurement ADC config */ |
676 | regmap_write(map: max98927->regmap, MAX98927_R0043_MEAS_ADC_CFG, val: 0x04); |
677 | regmap_write(map: max98927->regmap, MAX98927_R0044_MEAS_ADC_BASE_MSB, val: 0x00); |
678 | regmap_write(map: max98927->regmap, MAX98927_R0045_MEAS_ADC_BASE_LSB, val: 0x24); |
679 | /* Brownout Level */ |
680 | regmap_write(map: max98927->regmap, MAX98927_R007F_BROWNOUT_LVL4_AMP1_CTRL1, |
681 | val: 0x06); |
682 | /* Envelope Tracking configuration */ |
683 | regmap_write(map: max98927->regmap, MAX98927_R0082_ENV_TRACK_VOUT_HEADROOM, |
684 | val: 0x08); |
685 | regmap_write(map: max98927->regmap, MAX98927_R0086_ENV_TRACK_CTRL, val: 0x01); |
686 | regmap_write(map: max98927->regmap, MAX98927_R0087_ENV_TRACK_BOOST_VOUT_READ, |
687 | val: 0x10); |
688 | |
689 | /* voltage, current slot configuration */ |
690 | regmap_write(map: max98927->regmap, MAX98927_R001E_PCM_TX_CH_SRC_A, |
691 | val: (max98927->i_l_slot << MAX98927_PCM_TX_CH_SRC_A_I_SHIFT | max98927->v_l_slot) & 0xFF); |
692 | |
693 | if (max98927->v_l_slot < 8) { |
694 | regmap_update_bits(map: max98927->regmap, |
695 | MAX98927_R001C_PCM_TX_HIZ_CTRL_A, |
696 | mask: 1 << max98927->v_l_slot, val: 0); |
697 | regmap_update_bits(map: max98927->regmap, MAX98927_R001A_PCM_TX_EN_A, |
698 | mask: 1 << max98927->v_l_slot, |
699 | val: 1 << max98927->v_l_slot); |
700 | } else { |
701 | regmap_update_bits(map: max98927->regmap, |
702 | MAX98927_R001D_PCM_TX_HIZ_CTRL_B, |
703 | mask: 1 << (max98927->v_l_slot - 8), val: 0); |
704 | regmap_update_bits(map: max98927->regmap, MAX98927_R001B_PCM_TX_EN_B, |
705 | mask: 1 << (max98927->v_l_slot - 8), |
706 | val: 1 << (max98927->v_l_slot - 8)); |
707 | } |
708 | |
709 | if (max98927->i_l_slot < 8) { |
710 | regmap_update_bits(map: max98927->regmap, |
711 | MAX98927_R001C_PCM_TX_HIZ_CTRL_A, |
712 | mask: 1 << max98927->i_l_slot, val: 0); |
713 | regmap_update_bits(map: max98927->regmap, MAX98927_R001A_PCM_TX_EN_A, |
714 | mask: 1 << max98927->i_l_slot, |
715 | val: 1 << max98927->i_l_slot); |
716 | } else { |
717 | regmap_update_bits(map: max98927->regmap, |
718 | MAX98927_R001D_PCM_TX_HIZ_CTRL_B, |
719 | mask: 1 << (max98927->i_l_slot - 8), val: 0); |
720 | regmap_update_bits(map: max98927->regmap, MAX98927_R001B_PCM_TX_EN_B, |
721 | mask: 1 << (max98927->i_l_slot - 8), |
722 | val: 1 << (max98927->i_l_slot - 8)); |
723 | } |
724 | |
725 | /* Set interleave mode */ |
726 | if (max98927->interleave_mode) |
727 | regmap_update_bits(map: max98927->regmap, |
728 | MAX98927_R001F_PCM_TX_CH_SRC_B, |
729 | MAX98927_PCM_TX_CH_INTERLEAVE_MASK, |
730 | MAX98927_PCM_TX_CH_INTERLEAVE_MASK); |
731 | return 0; |
732 | } |
733 | |
734 | #ifdef CONFIG_PM_SLEEP |
735 | static int max98927_suspend(struct device *dev) |
736 | { |
737 | struct max98927_priv *max98927 = dev_get_drvdata(dev); |
738 | |
739 | regcache_cache_only(map: max98927->regmap, enable: true); |
740 | regcache_mark_dirty(map: max98927->regmap); |
741 | return 0; |
742 | } |
743 | static int max98927_resume(struct device *dev) |
744 | { |
745 | struct max98927_priv *max98927 = dev_get_drvdata(dev); |
746 | |
747 | regmap_write(map: max98927->regmap, MAX98927_R0100_SOFT_RESET, |
748 | MAX98927_SOFT_RESET); |
749 | regcache_cache_only(map: max98927->regmap, enable: false); |
750 | regcache_sync(map: max98927->regmap); |
751 | return 0; |
752 | } |
753 | #endif |
754 | |
755 | static const struct dev_pm_ops max98927_pm = { |
756 | SET_SYSTEM_SLEEP_PM_OPS(max98927_suspend, max98927_resume) |
757 | }; |
758 | |
759 | static const struct snd_soc_component_driver soc_component_dev_max98927 = { |
760 | .probe = max98927_probe, |
761 | .controls = max98927_snd_controls, |
762 | .num_controls = ARRAY_SIZE(max98927_snd_controls), |
763 | .dapm_widgets = max98927_dapm_widgets, |
764 | .num_dapm_widgets = ARRAY_SIZE(max98927_dapm_widgets), |
765 | .dapm_routes = max98927_audio_map, |
766 | .num_dapm_routes = ARRAY_SIZE(max98927_audio_map), |
767 | .idle_bias_on = 1, |
768 | .use_pmdown_time = 1, |
769 | .endianness = 1, |
770 | }; |
771 | |
772 | static const struct regmap_config max98927_regmap = { |
773 | .reg_bits = 16, |
774 | .val_bits = 8, |
775 | .max_register = MAX98927_R01FF_REV_ID, |
776 | .reg_defaults = max98927_reg, |
777 | .num_reg_defaults = ARRAY_SIZE(max98927_reg), |
778 | .readable_reg = max98927_readable_register, |
779 | .volatile_reg = max98927_volatile_reg, |
780 | .cache_type = REGCACHE_RBTREE, |
781 | }; |
782 | |
783 | static void max98927_slot_config(struct i2c_client *i2c, |
784 | struct max98927_priv *max98927) |
785 | { |
786 | int value; |
787 | struct device *dev = &i2c->dev; |
788 | |
789 | if (!device_property_read_u32(dev, propname: "vmon-slot-no" , val: &value)) |
790 | max98927->v_l_slot = value & 0xF; |
791 | else |
792 | max98927->v_l_slot = 0; |
793 | |
794 | if (!device_property_read_u32(dev, propname: "imon-slot-no" , val: &value)) |
795 | max98927->i_l_slot = value & 0xF; |
796 | else |
797 | max98927->i_l_slot = 1; |
798 | } |
799 | |
800 | static int max98927_i2c_probe(struct i2c_client *i2c) |
801 | { |
802 | |
803 | int ret = 0, value; |
804 | int reg = 0; |
805 | struct max98927_priv *max98927 = NULL; |
806 | |
807 | max98927 = devm_kzalloc(dev: &i2c->dev, size: sizeof(*max98927), GFP_KERNEL); |
808 | if (!max98927) { |
809 | ret = -ENOMEM; |
810 | return ret; |
811 | } |
812 | i2c_set_clientdata(client: i2c, data: max98927); |
813 | |
814 | /* update interleave mode info */ |
815 | if (of_property_read_bool(np: i2c->dev.of_node, propname: "maxim,interleave-mode" )) { |
816 | max98927->interleave_mode = true; |
817 | } else { |
818 | if (!of_property_read_u32(np: i2c->dev.of_node, propname: "interleave_mode" , |
819 | out_value: &value)) |
820 | if (value > 0) |
821 | max98927->interleave_mode = true; |
822 | } |
823 | |
824 | /* regmap initialization */ |
825 | max98927->regmap |
826 | = devm_regmap_init_i2c(i2c, &max98927_regmap); |
827 | if (IS_ERR(ptr: max98927->regmap)) { |
828 | ret = PTR_ERR(ptr: max98927->regmap); |
829 | dev_err(&i2c->dev, |
830 | "Failed to allocate regmap: %d\n" , ret); |
831 | return ret; |
832 | } |
833 | |
834 | max98927->reset_gpio = devm_gpiod_get_optional(dev: &i2c->dev, con_id: "reset" , |
835 | flags: GPIOD_OUT_HIGH); |
836 | if (IS_ERR(ptr: max98927->reset_gpio)) { |
837 | ret = PTR_ERR(ptr: max98927->reset_gpio); |
838 | return dev_err_probe(dev: &i2c->dev, err: ret, fmt: "failed to request GPIO reset pin" ); |
839 | } |
840 | |
841 | if (max98927->reset_gpio) { |
842 | gpiod_set_value_cansleep(desc: max98927->reset_gpio, value: 0); |
843 | /* Wait for i2c port to be ready */ |
844 | usleep_range(min: 5000, max: 6000); |
845 | } |
846 | |
847 | /* Check Revision ID */ |
848 | ret = regmap_read(map: max98927->regmap, MAX98927_R01FF_REV_ID, val: ®); |
849 | if (ret < 0) { |
850 | dev_err(&i2c->dev, |
851 | "Failed to read: 0x%02X\n" , MAX98927_R01FF_REV_ID); |
852 | return ret; |
853 | } |
854 | dev_info(&i2c->dev, "MAX98927 revisionID: 0x%02X\n" , reg); |
855 | |
856 | /* voltage/current slot configuration */ |
857 | max98927_slot_config(i2c, max98927); |
858 | |
859 | /* codec registeration */ |
860 | ret = devm_snd_soc_register_component(dev: &i2c->dev, |
861 | component_driver: &soc_component_dev_max98927, |
862 | dai_drv: max98927_dai, ARRAY_SIZE(max98927_dai)); |
863 | if (ret < 0) |
864 | dev_err(&i2c->dev, "Failed to register component: %d\n" , ret); |
865 | |
866 | return ret; |
867 | } |
868 | |
869 | static void max98927_i2c_remove(struct i2c_client *i2c) |
870 | { |
871 | struct max98927_priv *max98927 = i2c_get_clientdata(client: i2c); |
872 | |
873 | if (max98927->reset_gpio) |
874 | gpiod_set_value_cansleep(desc: max98927->reset_gpio, value: 1); |
875 | } |
876 | |
877 | static const struct i2c_device_id max98927_i2c_id[] = { |
878 | { "max98927" , 0}, |
879 | { }, |
880 | }; |
881 | |
882 | MODULE_DEVICE_TABLE(i2c, max98927_i2c_id); |
883 | |
884 | #if defined(CONFIG_OF) |
885 | static const struct of_device_id max98927_of_match[] = { |
886 | { .compatible = "maxim,max98927" , }, |
887 | { } |
888 | }; |
889 | MODULE_DEVICE_TABLE(of, max98927_of_match); |
890 | #endif |
891 | |
892 | #ifdef CONFIG_ACPI |
893 | static const struct acpi_device_id max98927_acpi_match[] = { |
894 | { "MX98927" , 0 }, |
895 | {}, |
896 | }; |
897 | MODULE_DEVICE_TABLE(acpi, max98927_acpi_match); |
898 | #endif |
899 | |
900 | static struct i2c_driver max98927_i2c_driver = { |
901 | .driver = { |
902 | .name = "max98927" , |
903 | .of_match_table = of_match_ptr(max98927_of_match), |
904 | .acpi_match_table = ACPI_PTR(max98927_acpi_match), |
905 | .pm = &max98927_pm, |
906 | }, |
907 | .probe = max98927_i2c_probe, |
908 | .remove = max98927_i2c_remove, |
909 | .id_table = max98927_i2c_id, |
910 | }; |
911 | |
912 | module_i2c_driver(max98927_i2c_driver) |
913 | |
914 | MODULE_DESCRIPTION("ALSA SoC MAX98927 driver" ); |
915 | MODULE_AUTHOR("Ryan Lee <ryans.lee@maximintegrated.com>" ); |
916 | MODULE_LICENSE("GPL" ); |
917 | |