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