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