1
2
3
4
5
6
7
8
9#include <linux/delay.h>
10#include <linux/i2c.h>
11#include <linux/module.h>
12#include <linux/regmap.h>
13#include <sound/pcm_params.h>
14#include <sound/soc.h>
15#include <sound/tlv.h>
16#include "max9867.h"
17
18static const char *const max9867_spmode[] = {
19 "Stereo Diff", "Mono Diff",
20 "Stereo Cap", "Mono Cap",
21 "Stereo Single", "Mono Single",
22 "Stereo Single Fast", "Mono Single Fast"
23};
24static const char *const max9867_filter_text[] = {"IIR", "FIR"};
25
26static SOC_ENUM_SINGLE_DECL(max9867_filter, MAX9867_CODECFLTR, 7,
27 max9867_filter_text);
28static SOC_ENUM_SINGLE_DECL(max9867_spkmode, MAX9867_MODECONFIG, 0,
29 max9867_spmode);
30static const SNDRV_CTL_TLVD_DECLARE_DB_RANGE(max9867_master_tlv,
31 0, 2, TLV_DB_SCALE_ITEM(-8600, 200, 1),
32 3, 17, TLV_DB_SCALE_ITEM(-7800, 400, 0),
33 18, 25, TLV_DB_SCALE_ITEM(-2000, 200, 0),
34 26, 34, TLV_DB_SCALE_ITEM( -500, 100, 0),
35 35, 40, TLV_DB_SCALE_ITEM( 350, 50, 0),
36);
37static DECLARE_TLV_DB_SCALE(max9867_mic_tlv, 0, 100, 0);
38static DECLARE_TLV_DB_SCALE(max9867_line_tlv, -600, 200, 0);
39static DECLARE_TLV_DB_SCALE(max9867_adc_tlv, -1200, 100, 0);
40static DECLARE_TLV_DB_SCALE(max9867_dac_tlv, -1500, 100, 0);
41static DECLARE_TLV_DB_SCALE(max9867_dacboost_tlv, 0, 600, 0);
42static const SNDRV_CTL_TLVD_DECLARE_DB_RANGE(max9867_micboost_tlv,
43 0, 2, TLV_DB_SCALE_ITEM(-2000, 2000, 1),
44 3, 3, TLV_DB_SCALE_ITEM(3000, 0, 0),
45);
46
47static const struct snd_kcontrol_new max9867_snd_controls[] = {
48 SOC_DOUBLE_R_TLV("Master Playback Volume", MAX9867_LEFTVOL,
49 MAX9867_RIGHTVOL, 0, 41, 1, max9867_master_tlv),
50 SOC_DOUBLE_R_TLV("Line Capture Volume", MAX9867_LEFTLINELVL,
51 MAX9867_RIGHTLINELVL, 0, 15, 1, max9867_line_tlv),
52 SOC_DOUBLE_R_TLV("Mic Capture Volume", MAX9867_LEFTMICGAIN,
53 MAX9867_RIGHTMICGAIN, 0, 20, 1, max9867_mic_tlv),
54 SOC_DOUBLE_R_TLV("Mic Boost Capture Volume", MAX9867_LEFTMICGAIN,
55 MAX9867_RIGHTMICGAIN, 5, 4, 0, max9867_micboost_tlv),
56 SOC_SINGLE("Digital Sidetone Volume", MAX9867_SIDETONE, 0, 31, 1),
57 SOC_SINGLE_TLV("Digital Playback Volume", MAX9867_DACLEVEL, 0, 15, 1,
58 max9867_dac_tlv),
59 SOC_SINGLE_TLV("Digital Boost Playback Volume", MAX9867_DACLEVEL, 4, 3, 0,
60 max9867_dacboost_tlv),
61 SOC_DOUBLE_TLV("Digital Capture Volume", MAX9867_ADCLEVEL, 0, 4, 15, 1,
62 max9867_adc_tlv),
63 SOC_ENUM("Speaker Mode", max9867_spkmode),
64 SOC_SINGLE("Volume Smoothing Switch", MAX9867_MODECONFIG, 6, 1, 0),
65 SOC_SINGLE("Line ZC Switch", MAX9867_MODECONFIG, 5, 1, 0),
66 SOC_ENUM("DSP Filter", max9867_filter),
67};
68
69
70static const struct snd_kcontrol_new max9867_input_mixer_controls[] = {
71 SOC_DAPM_DOUBLE("Line Capture Switch", MAX9867_INPUTCONFIG, 7, 5, 1, 0),
72 SOC_DAPM_DOUBLE("Mic Capture Switch", MAX9867_INPUTCONFIG, 6, 4, 1, 0),
73};
74
75
76static const struct snd_kcontrol_new max9867_output_mixer_controls[] = {
77 SOC_DAPM_DOUBLE_R("Line Bypass Switch",
78 MAX9867_LEFTLINELVL, MAX9867_RIGHTLINELVL, 6, 1, 1),
79};
80
81
82static const struct snd_kcontrol_new max9867_sidetone_mixer_controls[] = {
83 SOC_DAPM_DOUBLE("Sidetone Switch", MAX9867_SIDETONE, 6, 7, 1, 0),
84};
85
86
87static const struct snd_kcontrol_new max9867_line_out_control =
88 SOC_DAPM_DOUBLE_R("Switch",
89 MAX9867_LEFTVOL, MAX9867_RIGHTVOL, 6, 1, 1);
90
91
92static const struct snd_soc_dapm_widget max9867_dapm_widgets[] = {
93 SND_SOC_DAPM_INPUT("MICL"),
94 SND_SOC_DAPM_INPUT("MICR"),
95 SND_SOC_DAPM_INPUT("LINL"),
96 SND_SOC_DAPM_INPUT("LINR"),
97
98 SND_SOC_DAPM_PGA("Left Line Input", MAX9867_PWRMAN, 6, 0, NULL, 0),
99 SND_SOC_DAPM_PGA("Right Line Input", MAX9867_PWRMAN, 5, 0, NULL, 0),
100 SND_SOC_DAPM_MIXER_NAMED_CTL("Input Mixer", SND_SOC_NOPM, 0, 0,
101 max9867_input_mixer_controls,
102 ARRAY_SIZE(max9867_input_mixer_controls)),
103 SND_SOC_DAPM_ADC("ADCL", "HiFi Capture", MAX9867_PWRMAN, 1, 0),
104 SND_SOC_DAPM_ADC("ADCR", "HiFi Capture", MAX9867_PWRMAN, 0, 0),
105
106 SND_SOC_DAPM_MIXER("Digital", SND_SOC_NOPM, 0, 0,
107 max9867_sidetone_mixer_controls,
108 ARRAY_SIZE(max9867_sidetone_mixer_controls)),
109 SND_SOC_DAPM_MIXER_NAMED_CTL("Output Mixer", SND_SOC_NOPM, 0, 0,
110 max9867_output_mixer_controls,
111 ARRAY_SIZE(max9867_output_mixer_controls)),
112 SND_SOC_DAPM_DAC("DACL", "HiFi Playback", MAX9867_PWRMAN, 3, 0),
113 SND_SOC_DAPM_DAC("DACR", "HiFi Playback", MAX9867_PWRMAN, 2, 0),
114 SND_SOC_DAPM_SWITCH("Master Playback", SND_SOC_NOPM, 0, 0,
115 &max9867_line_out_control),
116 SND_SOC_DAPM_OUTPUT("LOUT"),
117 SND_SOC_DAPM_OUTPUT("ROUT"),
118};
119
120static const struct snd_soc_dapm_route max9867_audio_map[] = {
121 {"Left Line Input", NULL, "LINL"},
122 {"Right Line Input", NULL, "LINR"},
123 {"Input Mixer", "Mic Capture Switch", "MICL"},
124 {"Input Mixer", "Mic Capture Switch", "MICR"},
125 {"Input Mixer", "Line Capture Switch", "Left Line Input"},
126 {"Input Mixer", "Line Capture Switch", "Right Line Input"},
127 {"ADCL", NULL, "Input Mixer"},
128 {"ADCR", NULL, "Input Mixer"},
129
130 {"Digital", "Sidetone Switch", "ADCL"},
131 {"Digital", "Sidetone Switch", "ADCR"},
132 {"DACL", NULL, "Digital"},
133 {"DACR", NULL, "Digital"},
134
135 {"Output Mixer", "Line Bypass Switch", "Left Line Input"},
136 {"Output Mixer", "Line Bypass Switch", "Right Line Input"},
137 {"Output Mixer", NULL, "DACL"},
138 {"Output Mixer", NULL, "DACR"},
139 {"Master Playback", "Switch", "Output Mixer"},
140 {"LOUT", NULL, "Master Playback"},
141 {"ROUT", NULL, "Master Playback"},
142};
143
144static const unsigned int max9867_rates_44k1[] = {
145 11025, 22050, 44100,
146};
147
148static const struct snd_pcm_hw_constraint_list max9867_constraints_44k1 = {
149 .list = max9867_rates_44k1,
150 .count = ARRAY_SIZE(max9867_rates_44k1),
151};
152
153static const unsigned int max9867_rates_48k[] = {
154 8000, 16000, 32000, 48000,
155};
156
157static const struct snd_pcm_hw_constraint_list max9867_constraints_48k = {
158 .list = max9867_rates_48k,
159 .count = ARRAY_SIZE(max9867_rates_48k),
160};
161
162struct max9867_priv {
163 struct regmap *regmap;
164 const struct snd_pcm_hw_constraint_list *constraints;
165 unsigned int sysclk, pclk;
166 bool master, dsp_a;
167};
168
169static int max9867_startup(struct snd_pcm_substream *substream,
170 struct snd_soc_dai *dai)
171{
172 struct max9867_priv *max9867 =
173 snd_soc_component_get_drvdata(dai->component);
174
175 if (max9867->constraints)
176 snd_pcm_hw_constraint_list(substream->runtime, 0,
177 SNDRV_PCM_HW_PARAM_RATE, max9867->constraints);
178
179 return 0;
180}
181
182static int max9867_dai_hw_params(struct snd_pcm_substream *substream,
183 struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
184{
185 int value;
186 unsigned long int rate, ratio;
187 struct snd_soc_component *component = dai->component;
188 struct max9867_priv *max9867 = snd_soc_component_get_drvdata(component);
189 unsigned int ni = DIV_ROUND_CLOSEST_ULL(96ULL * 0x10000 * params_rate(params),
190 max9867->pclk);
191
192
193 regmap_update_bits(max9867->regmap, MAX9867_AUDIOCLKHIGH,
194 MAX9867_NI_HIGH_MASK, (0xFF00 & ni) >> 8);
195 regmap_update_bits(max9867->regmap, MAX9867_AUDIOCLKLOW,
196 MAX9867_NI_LOW_MASK, 0x00FF & ni);
197 if (max9867->master) {
198 if (max9867->dsp_a) {
199 value = MAX9867_IFC1B_48X;
200 } else {
201 rate = params_rate(params) * 2 * params_width(params);
202 ratio = max9867->pclk / rate;
203 switch (params_width(params)) {
204 case 8:
205 case 16:
206 switch (ratio) {
207 case 2:
208 value = MAX9867_IFC1B_PCLK_2;
209 break;
210 case 4:
211 value = MAX9867_IFC1B_PCLK_4;
212 break;
213 case 8:
214 value = MAX9867_IFC1B_PCLK_8;
215 break;
216 case 16:
217 value = MAX9867_IFC1B_PCLK_16;
218 break;
219 default:
220 return -EINVAL;
221 }
222 break;
223 case 24:
224 value = MAX9867_IFC1B_48X;
225 break;
226 case 32:
227 value = MAX9867_IFC1B_64X;
228 break;
229 default:
230 return -EINVAL;
231 }
232 }
233 regmap_update_bits(max9867->regmap, MAX9867_IFC1B,
234 MAX9867_IFC1B_BCLK_MASK, value);
235 } else {
236
237
238
239
240 regmap_update_bits(max9867->regmap, MAX9867_AUDIOCLKLOW,
241 MAX9867_RAPID_LOCK, MAX9867_RAPID_LOCK);
242 regmap_update_bits(max9867->regmap, MAX9867_AUDIOCLKHIGH,
243 MAX9867_PLL, MAX9867_PLL);
244 }
245 return 0;
246}
247
248static int max9867_mute(struct snd_soc_dai *dai, int mute)
249{
250 struct snd_soc_component *component = dai->component;
251 struct max9867_priv *max9867 = snd_soc_component_get_drvdata(component);
252
253 return regmap_update_bits(max9867->regmap, MAX9867_DACLEVEL,
254 1 << 6, !!mute << 6);
255}
256
257static int max9867_set_dai_sysclk(struct snd_soc_dai *codec_dai,
258 int clk_id, unsigned int freq, int dir)
259{
260 struct snd_soc_component *component = codec_dai->component;
261 struct max9867_priv *max9867 = snd_soc_component_get_drvdata(component);
262 int value = 0;
263
264
265 if (freq >= 10000000 && freq <= 20000000) {
266 value |= MAX9867_PSCLK_10_20;
267 max9867->pclk = freq;
268 } else if (freq >= 20000000 && freq <= 40000000) {
269 value |= MAX9867_PSCLK_20_40;
270 max9867->pclk = freq / 2;
271 } else if (freq >= 40000000 && freq <= 60000000) {
272 value |= MAX9867_PSCLK_40_60;
273 max9867->pclk = freq / 4;
274 } else {
275 dev_err(component->dev,
276 "Invalid clock frequency %uHz (required 10-60MHz)\n",
277 freq);
278 return -EINVAL;
279 }
280 if (freq % 48000 == 0)
281 max9867->constraints = &max9867_constraints_48k;
282 else if (freq % 44100 == 0)
283 max9867->constraints = &max9867_constraints_44k1;
284 else
285 dev_warn(component->dev,
286 "Unable to set exact rate with %uHz clock frequency\n",
287 freq);
288 max9867->sysclk = freq;
289 value = value << MAX9867_PSCLK_SHIFT;
290
291 value &= ~MAX9867_FREQ_MASK;
292 regmap_update_bits(max9867->regmap, MAX9867_SYSCLK,
293 MAX9867_PSCLK_MASK, value);
294 return 0;
295}
296
297static int max9867_dai_set_fmt(struct snd_soc_dai *codec_dai,
298 unsigned int fmt)
299{
300 struct snd_soc_component *component = codec_dai->component;
301 struct max9867_priv *max9867 = snd_soc_component_get_drvdata(component);
302 u8 iface1A, iface1B;
303
304 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
305 case SND_SOC_DAIFMT_CBM_CFM:
306 max9867->master = true;
307 iface1A = MAX9867_MASTER;
308 iface1B = MAX9867_IFC1B_48X;
309 break;
310 case SND_SOC_DAIFMT_CBS_CFS:
311 max9867->master = false;
312 iface1A = iface1B = 0;
313 break;
314 default:
315 return -EINVAL;
316 }
317
318 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
319 case SND_SOC_DAIFMT_I2S:
320 max9867->dsp_a = false;
321 iface1A |= MAX9867_I2S_DLY;
322 break;
323 case SND_SOC_DAIFMT_DSP_A:
324 max9867->dsp_a = true;
325 iface1A |= MAX9867_TDM_MODE | MAX9867_SDOUT_HIZ;
326 break;
327 default:
328 return -EINVAL;
329 }
330
331
332 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
333 case SND_SOC_DAIFMT_NB_NF:
334 break;
335 case SND_SOC_DAIFMT_IB_IF:
336 iface1A |= MAX9867_WCI_MODE | MAX9867_BCI_MODE;
337 break;
338 case SND_SOC_DAIFMT_IB_NF:
339 iface1A |= MAX9867_BCI_MODE;
340 break;
341 case SND_SOC_DAIFMT_NB_IF:
342 iface1A |= MAX9867_WCI_MODE;
343 break;
344 default:
345 return -EINVAL;
346 }
347
348 regmap_write(max9867->regmap, MAX9867_IFC1A, iface1A);
349 regmap_write(max9867->regmap, MAX9867_IFC1B, iface1B);
350
351 return 0;
352}
353
354static const struct snd_soc_dai_ops max9867_dai_ops = {
355 .set_sysclk = max9867_set_dai_sysclk,
356 .set_fmt = max9867_dai_set_fmt,
357 .digital_mute = max9867_mute,
358 .startup = max9867_startup,
359 .hw_params = max9867_dai_hw_params,
360};
361
362static struct snd_soc_dai_driver max9867_dai[] = {
363 {
364 .name = "max9867-aif1",
365 .playback = {
366 .stream_name = "HiFi Playback",
367 .channels_min = 2,
368 .channels_max = 2,
369 .rates = SNDRV_PCM_RATE_8000_48000,
370 .formats = SNDRV_PCM_FMTBIT_S16_LE,
371 },
372 .capture = {
373 .stream_name = "HiFi Capture",
374 .channels_min = 2,
375 .channels_max = 2,
376 .rates = SNDRV_PCM_RATE_8000_48000,
377 .formats = SNDRV_PCM_FMTBIT_S16_LE,
378 },
379 .ops = &max9867_dai_ops,
380 .symmetric_rates = 1,
381 }
382};
383
384#ifdef CONFIG_PM
385static int max9867_suspend(struct snd_soc_component *component)
386{
387 snd_soc_component_force_bias_level(component, SND_SOC_BIAS_OFF);
388
389 return 0;
390}
391
392static int max9867_resume(struct snd_soc_component *component)
393{
394 snd_soc_component_force_bias_level(component, SND_SOC_BIAS_STANDBY);
395
396 return 0;
397}
398#else
399#define max9867_suspend NULL
400#define max9867_resume NULL
401#endif
402
403static int max9867_set_bias_level(struct snd_soc_component *component,
404 enum snd_soc_bias_level level)
405{
406 int err;
407 struct max9867_priv *max9867 = snd_soc_component_get_drvdata(component);
408
409 switch (level) {
410 case SND_SOC_BIAS_STANDBY:
411 if (snd_soc_component_get_bias_level(component) == SND_SOC_BIAS_OFF) {
412 err = regcache_sync(max9867->regmap);
413 if (err)
414 return err;
415
416 err = regmap_update_bits(max9867->regmap, MAX9867_PWRMAN,
417 MAX9867_SHTDOWN, MAX9867_SHTDOWN);
418 if (err)
419 return err;
420 }
421 break;
422 case SND_SOC_BIAS_OFF:
423 err = regmap_update_bits(max9867->regmap, MAX9867_PWRMAN,
424 MAX9867_SHTDOWN, 0);
425 if (err)
426 return err;
427
428 regcache_mark_dirty(max9867->regmap);
429 break;
430 default:
431 break;
432 }
433
434 return 0;
435}
436
437static const struct snd_soc_component_driver max9867_component = {
438 .controls = max9867_snd_controls,
439 .num_controls = ARRAY_SIZE(max9867_snd_controls),
440 .dapm_routes = max9867_audio_map,
441 .num_dapm_routes = ARRAY_SIZE(max9867_audio_map),
442 .dapm_widgets = max9867_dapm_widgets,
443 .num_dapm_widgets = ARRAY_SIZE(max9867_dapm_widgets),
444 .suspend = max9867_suspend,
445 .resume = max9867_resume,
446 .set_bias_level = max9867_set_bias_level,
447 .idle_bias_on = 1,
448 .use_pmdown_time = 1,
449 .endianness = 1,
450 .non_legacy_dai_naming = 1,
451};
452
453static bool max9867_volatile_register(struct device *dev, unsigned int reg)
454{
455 switch (reg) {
456 case MAX9867_STATUS:
457 case MAX9867_JACKSTATUS:
458 case MAX9867_AUXHIGH:
459 case MAX9867_AUXLOW:
460 return true;
461 default:
462 return false;
463 }
464}
465
466static const struct reg_default max9867_reg[] = {
467 { 0x04, 0x00 },
468 { 0x05, 0x00 },
469 { 0x06, 0x00 },
470 { 0x07, 0x00 },
471 { 0x08, 0x00 },
472 { 0x09, 0x00 },
473 { 0x0A, 0x00 },
474 { 0x0B, 0x00 },
475 { 0x0C, 0x00 },
476 { 0x0D, 0x00 },
477 { 0x0E, 0x40 },
478 { 0x0F, 0x40 },
479 { 0x10, 0x00 },
480 { 0x11, 0x00 },
481 { 0x12, 0x00 },
482 { 0x13, 0x00 },
483 { 0x14, 0x00 },
484 { 0x15, 0x00 },
485 { 0x16, 0x00 },
486 { 0x17, 0x00 },
487};
488
489static const struct regmap_config max9867_regmap = {
490 .reg_bits = 8,
491 .val_bits = 8,
492 .max_register = MAX9867_REVISION,
493 .reg_defaults = max9867_reg,
494 .num_reg_defaults = ARRAY_SIZE(max9867_reg),
495 .volatile_reg = max9867_volatile_register,
496 .cache_type = REGCACHE_RBTREE,
497};
498
499static int max9867_i2c_probe(struct i2c_client *i2c,
500 const struct i2c_device_id *id)
501{
502 struct max9867_priv *max9867;
503 int ret, reg;
504
505 max9867 = devm_kzalloc(&i2c->dev, sizeof(*max9867), GFP_KERNEL);
506 if (!max9867)
507 return -ENOMEM;
508
509 i2c_set_clientdata(i2c, max9867);
510 max9867->regmap = devm_regmap_init_i2c(i2c, &max9867_regmap);
511 if (IS_ERR(max9867->regmap)) {
512 ret = PTR_ERR(max9867->regmap);
513 dev_err(&i2c->dev, "Failed to allocate regmap: %d\n", ret);
514 return ret;
515 }
516 ret = regmap_read(max9867->regmap, MAX9867_REVISION, ®);
517 if (ret < 0) {
518 dev_err(&i2c->dev, "Failed to read: %d\n", ret);
519 return ret;
520 }
521 dev_info(&i2c->dev, "device revision: %x\n", reg);
522 ret = devm_snd_soc_register_component(&i2c->dev, &max9867_component,
523 max9867_dai, ARRAY_SIZE(max9867_dai));
524 if (ret < 0)
525 dev_err(&i2c->dev, "Failed to register component: %d\n", ret);
526 return ret;
527}
528
529static const struct i2c_device_id max9867_i2c_id[] = {
530 { "max9867", 0 },
531 { }
532};
533MODULE_DEVICE_TABLE(i2c, max9867_i2c_id);
534
535static const struct of_device_id max9867_of_match[] = {
536 { .compatible = "maxim,max9867", },
537 { }
538};
539MODULE_DEVICE_TABLE(of, max9867_of_match);
540
541static struct i2c_driver max9867_i2c_driver = {
542 .driver = {
543 .name = "max9867",
544 .of_match_table = of_match_ptr(max9867_of_match),
545 },
546 .probe = max9867_i2c_probe,
547 .id_table = max9867_i2c_id,
548};
549
550module_i2c_driver(max9867_i2c_driver);
551
552MODULE_AUTHOR("Ladislav Michl <ladis@linux-mips.org>");
553MODULE_DESCRIPTION("ASoC MAX9867 driver");
554MODULE_LICENSE("GPL");
555