1 // SPDX-License-Identifier: GPL-2.0
3 // nau8822.c -- NAU8822 ALSA Soc Audio driver
5 // Copyright 2017 Nuvoton Technology Crop.
7 // Author: David Lin <ctlin0@nuvoton.com>
8 // Co-author: John Hsu <kchsu0@nuvoton.com>
9 // Co-author: Seven Li <wtli@nuvoton.com>
13 #include <linux/module.h>
14 #include <linux/moduleparam.h>
15 #include <linux/kernel.h>
16 #include <linux/init.h>
17 #include <linux/delay.h>
19 #include <linux/i2c.h>
20 #include <linux/regmap.h>
21 #include <linux/slab.h>
22 #include <sound/core.h>
23 #include <sound/pcm.h>
24 #include <sound/pcm_params.h>
25 #include <sound/soc.h>
26 #include <sound/initval.h>
27 #include <sound/tlv.h>
28 #include <asm/div64.h>
31 #define NAU_PLL_FREQ_MAX 100000000
32 #define NAU_PLL_FREQ_MIN 90000000
33 #define NAU_PLL_REF_MAX 33000000
34 #define NAU_PLL_REF_MIN 8000000
35 #define NAU_PLL_OPTOP_MIN 6
37 static const int nau8822_mclk_scaler
[] = { 10, 15, 20, 30, 40, 60, 80, 120 };
39 static const struct reg_default nau8822_reg_defaults
[] = {
40 { NAU8822_REG_POWER_MANAGEMENT_1
, 0x0000 },
41 { NAU8822_REG_POWER_MANAGEMENT_2
, 0x0000 },
42 { NAU8822_REG_POWER_MANAGEMENT_3
, 0x0000 },
43 { NAU8822_REG_AUDIO_INTERFACE
, 0x0050 },
44 { NAU8822_REG_COMPANDING_CONTROL
, 0x0000 },
45 { NAU8822_REG_CLOCKING
, 0x0140 },
46 { NAU8822_REG_ADDITIONAL_CONTROL
, 0x0000 },
47 { NAU8822_REG_GPIO_CONTROL
, 0x0000 },
48 { NAU8822_REG_JACK_DETECT_CONTROL_1
, 0x0000 },
49 { NAU8822_REG_DAC_CONTROL
, 0x0000 },
50 { NAU8822_REG_LEFT_DAC_DIGITAL_VOLUME
, 0x00ff },
51 { NAU8822_REG_RIGHT_DAC_DIGITAL_VOLUME
, 0x00ff },
52 { NAU8822_REG_JACK_DETECT_CONTROL_2
, 0x0000 },
53 { NAU8822_REG_ADC_CONTROL
, 0x0100 },
54 { NAU8822_REG_LEFT_ADC_DIGITAL_VOLUME
, 0x00ff },
55 { NAU8822_REG_RIGHT_ADC_DIGITAL_VOLUME
, 0x00ff },
56 { NAU8822_REG_EQ1
, 0x012c },
57 { NAU8822_REG_EQ2
, 0x002c },
58 { NAU8822_REG_EQ3
, 0x002c },
59 { NAU8822_REG_EQ4
, 0x002c },
60 { NAU8822_REG_EQ5
, 0x002c },
61 { NAU8822_REG_DAC_LIMITER_1
, 0x0032 },
62 { NAU8822_REG_DAC_LIMITER_2
, 0x0000 },
63 { NAU8822_REG_NOTCH_FILTER_1
, 0x0000 },
64 { NAU8822_REG_NOTCH_FILTER_2
, 0x0000 },
65 { NAU8822_REG_NOTCH_FILTER_3
, 0x0000 },
66 { NAU8822_REG_NOTCH_FILTER_4
, 0x0000 },
67 { NAU8822_REG_ALC_CONTROL_1
, 0x0038 },
68 { NAU8822_REG_ALC_CONTROL_2
, 0x000b },
69 { NAU8822_REG_ALC_CONTROL_3
, 0x0032 },
70 { NAU8822_REG_NOISE_GATE
, 0x0010 },
71 { NAU8822_REG_PLL_N
, 0x0008 },
72 { NAU8822_REG_PLL_K1
, 0x000c },
73 { NAU8822_REG_PLL_K2
, 0x0093 },
74 { NAU8822_REG_PLL_K3
, 0x00e9 },
75 { NAU8822_REG_3D_CONTROL
, 0x0000 },
76 { NAU8822_REG_RIGHT_SPEAKER_CONTROL
, 0x0000 },
77 { NAU8822_REG_INPUT_CONTROL
, 0x0033 },
78 { NAU8822_REG_LEFT_INP_PGA_CONTROL
, 0x0010 },
79 { NAU8822_REG_RIGHT_INP_PGA_CONTROL
, 0x0010 },
80 { NAU8822_REG_LEFT_ADC_BOOST_CONTROL
, 0x0100 },
81 { NAU8822_REG_RIGHT_ADC_BOOST_CONTROL
, 0x0100 },
82 { NAU8822_REG_OUTPUT_CONTROL
, 0x0002 },
83 { NAU8822_REG_LEFT_MIXER_CONTROL
, 0x0001 },
84 { NAU8822_REG_RIGHT_MIXER_CONTROL
, 0x0001 },
85 { NAU8822_REG_LHP_VOLUME
, 0x0039 },
86 { NAU8822_REG_RHP_VOLUME
, 0x0039 },
87 { NAU8822_REG_LSPKOUT_VOLUME
, 0x0039 },
88 { NAU8822_REG_RSPKOUT_VOLUME
, 0x0039 },
89 { NAU8822_REG_AUX2_MIXER
, 0x0001 },
90 { NAU8822_REG_AUX1_MIXER
, 0x0001 },
91 { NAU8822_REG_POWER_MANAGEMENT_4
, 0x0000 },
92 { NAU8822_REG_LEFT_TIME_SLOT
, 0x0000 },
93 { NAU8822_REG_MISC
, 0x0020 },
94 { NAU8822_REG_RIGHT_TIME_SLOT
, 0x0000 },
95 { NAU8822_REG_DEVICE_REVISION
, 0x007f },
96 { NAU8822_REG_DEVICE_ID
, 0x001a },
97 { NAU8822_REG_DAC_DITHER
, 0x0114 },
98 { NAU8822_REG_ALC_ENHANCE_1
, 0x0000 },
99 { NAU8822_REG_ALC_ENHANCE_2
, 0x0000 },
100 { NAU8822_REG_192KHZ_SAMPLING
, 0x0008 },
101 { NAU8822_REG_MISC_CONTROL
, 0x0000 },
102 { NAU8822_REG_INPUT_TIEOFF
, 0x0000 },
103 { NAU8822_REG_POWER_REDUCTION
, 0x0000 },
104 { NAU8822_REG_AGC_PEAK2PEAK
, 0x0000 },
105 { NAU8822_REG_AGC_PEAK_DETECT
, 0x0000 },
106 { NAU8822_REG_AUTOMUTE_CONTROL
, 0x0000 },
107 { NAU8822_REG_OUTPUT_TIEOFF
, 0x0000 },
110 static bool nau8822_readable_reg(struct device
*dev
, unsigned int reg
)
113 case NAU8822_REG_RESET
... NAU8822_REG_JACK_DETECT_CONTROL_1
:
114 case NAU8822_REG_DAC_CONTROL
... NAU8822_REG_LEFT_ADC_DIGITAL_VOLUME
:
115 case NAU8822_REG_RIGHT_ADC_DIGITAL_VOLUME
:
116 case NAU8822_REG_EQ1
... NAU8822_REG_EQ5
:
117 case NAU8822_REG_DAC_LIMITER_1
... NAU8822_REG_DAC_LIMITER_2
:
118 case NAU8822_REG_NOTCH_FILTER_1
... NAU8822_REG_NOTCH_FILTER_4
:
119 case NAU8822_REG_ALC_CONTROL_1
...NAU8822_REG_PLL_K3
:
120 case NAU8822_REG_3D_CONTROL
:
121 case NAU8822_REG_RIGHT_SPEAKER_CONTROL
:
122 case NAU8822_REG_INPUT_CONTROL
... NAU8822_REG_LEFT_ADC_BOOST_CONTROL
:
123 case NAU8822_REG_RIGHT_ADC_BOOST_CONTROL
... NAU8822_REG_AUX1_MIXER
:
124 case NAU8822_REG_POWER_MANAGEMENT_4
... NAU8822_REG_DEVICE_ID
:
125 case NAU8822_REG_DAC_DITHER
:
126 case NAU8822_REG_ALC_ENHANCE_1
... NAU8822_REG_MISC_CONTROL
:
127 case NAU8822_REG_INPUT_TIEOFF
... NAU8822_REG_OUTPUT_TIEOFF
:
134 static bool nau8822_writeable_reg(struct device
*dev
, unsigned int reg
)
137 case NAU8822_REG_RESET
... NAU8822_REG_JACK_DETECT_CONTROL_1
:
138 case NAU8822_REG_DAC_CONTROL
... NAU8822_REG_LEFT_ADC_DIGITAL_VOLUME
:
139 case NAU8822_REG_RIGHT_ADC_DIGITAL_VOLUME
:
140 case NAU8822_REG_EQ1
... NAU8822_REG_EQ5
:
141 case NAU8822_REG_DAC_LIMITER_1
... NAU8822_REG_DAC_LIMITER_2
:
142 case NAU8822_REG_NOTCH_FILTER_1
... NAU8822_REG_NOTCH_FILTER_4
:
143 case NAU8822_REG_ALC_CONTROL_1
...NAU8822_REG_PLL_K3
:
144 case NAU8822_REG_3D_CONTROL
:
145 case NAU8822_REG_RIGHT_SPEAKER_CONTROL
:
146 case NAU8822_REG_INPUT_CONTROL
... NAU8822_REG_LEFT_ADC_BOOST_CONTROL
:
147 case NAU8822_REG_RIGHT_ADC_BOOST_CONTROL
... NAU8822_REG_AUX1_MIXER
:
148 case NAU8822_REG_POWER_MANAGEMENT_4
... NAU8822_REG_DEVICE_ID
:
149 case NAU8822_REG_DAC_DITHER
:
150 case NAU8822_REG_ALC_ENHANCE_1
... NAU8822_REG_MISC_CONTROL
:
151 case NAU8822_REG_INPUT_TIEOFF
... NAU8822_REG_OUTPUT_TIEOFF
:
158 static bool nau8822_volatile(struct device
*dev
, unsigned int reg
)
161 case NAU8822_REG_RESET
:
162 case NAU8822_REG_DEVICE_REVISION
:
163 case NAU8822_REG_DEVICE_ID
:
164 case NAU8822_REG_AGC_PEAK2PEAK
:
165 case NAU8822_REG_AGC_PEAK_DETECT
:
166 case NAU8822_REG_AUTOMUTE_CONTROL
:
173 /* The EQ parameters get function is to get the 5 band equalizer control.
174 * The regmap raw read can't work here because regmap doesn't provide
175 * value format for value width of 9 bits. Therefore, the driver reads data
176 * from cache and makes value format according to the endianness of
177 * bytes type control element.
179 static int nau8822_eq_get(struct snd_kcontrol
*kcontrol
,
180 struct snd_ctl_elem_value
*ucontrol
)
182 struct snd_soc_component
*component
=
183 snd_soc_kcontrol_component(kcontrol
);
184 struct soc_bytes_ext
*params
= (void *)kcontrol
->private_value
;
188 val
= (u16
*)ucontrol
->value
.bytes
.data
;
189 reg
= NAU8822_REG_EQ1
;
190 for (i
= 0; i
< params
->max
/ sizeof(u16
); i
++) {
191 reg_val
= snd_soc_component_read(component
, reg
+ i
);
192 /* conversion of 16-bit integers between native CPU format
193 * and big endian format
195 reg_val
= cpu_to_be16(reg_val
);
196 memcpy(val
+ i
, ®_val
, sizeof(reg_val
));
202 /* The EQ parameters put function is to make configuration of 5 band equalizer
203 * control. These configuration includes central frequency, equalizer gain,
204 * cut-off frequency, bandwidth control, and equalizer path.
205 * The regmap raw write can't work here because regmap doesn't provide
206 * register and value format for register with address 7 bits and value 9 bits.
207 * Therefore, the driver makes value format according to the endianness of
208 * bytes type control element and writes data to codec.
210 static int nau8822_eq_put(struct snd_kcontrol
*kcontrol
,
211 struct snd_ctl_elem_value
*ucontrol
)
213 struct snd_soc_component
*component
=
214 snd_soc_kcontrol_component(kcontrol
);
215 struct soc_bytes_ext
*params
= (void *)kcontrol
->private_value
;
220 data
= kmemdup(ucontrol
->value
.bytes
.data
,
221 params
->max
, GFP_KERNEL
| GFP_DMA
);
226 reg
= NAU8822_REG_EQ1
;
227 for (i
= 0; i
< params
->max
/ sizeof(u16
); i
++) {
228 /* conversion of 16-bit integers between native CPU format
229 * and big endian format
231 value
= be16_to_cpu(*(val
+ i
));
232 ret
= snd_soc_component_write(component
, reg
+ i
, value
);
234 dev_err(component
->dev
,
235 "EQ configuration fail, register: %x ret: %d\n",
246 static const char * const nau8822_companding
[] = {
247 "Off", "NC", "u-law", "A-law"};
249 static const struct soc_enum nau8822_companding_adc_enum
=
250 SOC_ENUM_SINGLE(NAU8822_REG_COMPANDING_CONTROL
, NAU8822_ADCCM_SFT
,
251 ARRAY_SIZE(nau8822_companding
), nau8822_companding
);
253 static const struct soc_enum nau8822_companding_dac_enum
=
254 SOC_ENUM_SINGLE(NAU8822_REG_COMPANDING_CONTROL
, NAU8822_DACCM_SFT
,
255 ARRAY_SIZE(nau8822_companding
), nau8822_companding
);
257 static const char * const nau8822_eqmode
[] = {"Capture", "Playback"};
259 static const struct soc_enum nau8822_eqmode_enum
=
260 SOC_ENUM_SINGLE(NAU8822_REG_EQ1
, NAU8822_EQM_SFT
,
261 ARRAY_SIZE(nau8822_eqmode
), nau8822_eqmode
);
263 static const char * const nau8822_alc1
[] = {"Off", "Right", "Left", "Both"};
264 static const char * const nau8822_alc3
[] = {"Normal", "Limiter"};
266 static const struct soc_enum nau8822_alc_enable_enum
=
267 SOC_ENUM_SINGLE(NAU8822_REG_ALC_CONTROL_1
, NAU8822_ALCEN_SFT
,
268 ARRAY_SIZE(nau8822_alc1
), nau8822_alc1
);
270 static const struct soc_enum nau8822_alc_mode_enum
=
271 SOC_ENUM_SINGLE(NAU8822_REG_ALC_CONTROL_3
, NAU8822_ALCM_SFT
,
272 ARRAY_SIZE(nau8822_alc3
), nau8822_alc3
);
274 static const DECLARE_TLV_DB_SCALE(digital_tlv
, -12750, 50, 1);
275 static const DECLARE_TLV_DB_SCALE(inpga_tlv
, -1200, 75, 0);
276 static const DECLARE_TLV_DB_SCALE(spk_tlv
, -5700, 100, 0);
277 static const DECLARE_TLV_DB_SCALE(pga_boost_tlv
, 0, 2000, 0);
278 static const DECLARE_TLV_DB_SCALE(boost_tlv
, -1500, 300, 1);
279 static const DECLARE_TLV_DB_SCALE(limiter_tlv
, 0, 100, 0);
281 static const struct snd_kcontrol_new nau8822_snd_controls
[] = {
282 SOC_ENUM("ADC Companding", nau8822_companding_adc_enum
),
283 SOC_ENUM("DAC Companding", nau8822_companding_dac_enum
),
285 SOC_ENUM("EQ Function", nau8822_eqmode_enum
),
286 SND_SOC_BYTES_EXT("EQ Parameters", 10,
287 nau8822_eq_get
, nau8822_eq_put
),
289 SOC_DOUBLE("DAC Inversion Switch",
290 NAU8822_REG_DAC_CONTROL
, 0, 1, 1, 0),
291 SOC_DOUBLE_R_TLV("PCM Volume",
292 NAU8822_REG_LEFT_DAC_DIGITAL_VOLUME
,
293 NAU8822_REG_RIGHT_DAC_DIGITAL_VOLUME
, 0, 255, 0, digital_tlv
),
295 SOC_SINGLE("High Pass Filter Switch",
296 NAU8822_REG_ADC_CONTROL
, 8, 1, 0),
297 SOC_SINGLE("High Pass Cut Off",
298 NAU8822_REG_ADC_CONTROL
, 4, 7, 0),
300 SOC_DOUBLE("ADC Inversion Switch",
301 NAU8822_REG_ADC_CONTROL
, 0, 1, 1, 0),
302 SOC_DOUBLE_R_TLV("ADC Volume",
303 NAU8822_REG_LEFT_ADC_DIGITAL_VOLUME
,
304 NAU8822_REG_RIGHT_ADC_DIGITAL_VOLUME
, 0, 255, 0, digital_tlv
),
306 SOC_SINGLE("DAC Limiter Switch",
307 NAU8822_REG_DAC_LIMITER_1
, 8, 1, 0),
308 SOC_SINGLE("DAC Limiter Decay",
309 NAU8822_REG_DAC_LIMITER_1
, 4, 15, 0),
310 SOC_SINGLE("DAC Limiter Attack",
311 NAU8822_REG_DAC_LIMITER_1
, 0, 15, 0),
312 SOC_SINGLE("DAC Limiter Threshold",
313 NAU8822_REG_DAC_LIMITER_2
, 4, 7, 0),
314 SOC_SINGLE_TLV("DAC Limiter Volume",
315 NAU8822_REG_DAC_LIMITER_2
, 0, 12, 0, limiter_tlv
),
317 SOC_ENUM("ALC Mode", nau8822_alc_mode_enum
),
318 SOC_ENUM("ALC Enable Switch", nau8822_alc_enable_enum
),
319 SOC_SINGLE("ALC Min Gain",
320 NAU8822_REG_ALC_CONTROL_1
, 0, 7, 0),
321 SOC_SINGLE("ALC Max Gain",
322 NAU8822_REG_ALC_CONTROL_1
, 3, 7, 0),
323 SOC_SINGLE("ALC Hold",
324 NAU8822_REG_ALC_CONTROL_2
, 4, 10, 0),
325 SOC_SINGLE("ALC Target",
326 NAU8822_REG_ALC_CONTROL_2
, 0, 15, 0),
327 SOC_SINGLE("ALC Decay",
328 NAU8822_REG_ALC_CONTROL_3
, 4, 10, 0),
329 SOC_SINGLE("ALC Attack",
330 NAU8822_REG_ALC_CONTROL_3
, 0, 10, 0),
331 SOC_SINGLE("ALC Noise Gate Switch",
332 NAU8822_REG_NOISE_GATE
, 3, 1, 0),
333 SOC_SINGLE("ALC Noise Gate Threshold",
334 NAU8822_REG_NOISE_GATE
, 0, 7, 0),
336 SOC_DOUBLE_R("PGA ZC Switch",
337 NAU8822_REG_LEFT_INP_PGA_CONTROL
,
338 NAU8822_REG_RIGHT_INP_PGA_CONTROL
,
340 SOC_DOUBLE_R_TLV("PGA Volume",
341 NAU8822_REG_LEFT_INP_PGA_CONTROL
,
342 NAU8822_REG_RIGHT_INP_PGA_CONTROL
, 0, 63, 0, inpga_tlv
),
344 SOC_DOUBLE_R("Headphone ZC Switch",
345 NAU8822_REG_LHP_VOLUME
,
346 NAU8822_REG_RHP_VOLUME
, 7, 1, 0),
347 SOC_DOUBLE_R("Headphone Playback Switch",
348 NAU8822_REG_LHP_VOLUME
,
349 NAU8822_REG_RHP_VOLUME
, 6, 1, 1),
350 SOC_DOUBLE_R_TLV("Headphone Volume",
351 NAU8822_REG_LHP_VOLUME
,
352 NAU8822_REG_RHP_VOLUME
, 0, 63, 0, spk_tlv
),
354 SOC_DOUBLE_R("Speaker ZC Switch",
355 NAU8822_REG_LSPKOUT_VOLUME
,
356 NAU8822_REG_RSPKOUT_VOLUME
, 7, 1, 0),
357 SOC_DOUBLE_R("Speaker Playback Switch",
358 NAU8822_REG_LSPKOUT_VOLUME
,
359 NAU8822_REG_RSPKOUT_VOLUME
, 6, 1, 1),
360 SOC_DOUBLE_R_TLV("Speaker Volume",
361 NAU8822_REG_LSPKOUT_VOLUME
,
362 NAU8822_REG_RSPKOUT_VOLUME
, 0, 63, 0, spk_tlv
),
364 SOC_DOUBLE_R("AUXOUT Playback Switch",
365 NAU8822_REG_AUX2_MIXER
,
366 NAU8822_REG_AUX1_MIXER
, 6, 1, 1),
368 SOC_DOUBLE_R_TLV("PGA Boost Volume",
369 NAU8822_REG_LEFT_ADC_BOOST_CONTROL
,
370 NAU8822_REG_RIGHT_ADC_BOOST_CONTROL
, 8, 1, 0, pga_boost_tlv
),
371 SOC_DOUBLE_R_TLV("L2/R2 Boost Volume",
372 NAU8822_REG_LEFT_ADC_BOOST_CONTROL
,
373 NAU8822_REG_RIGHT_ADC_BOOST_CONTROL
, 4, 7, 0, boost_tlv
),
374 SOC_DOUBLE_R_TLV("Aux Boost Volume",
375 NAU8822_REG_LEFT_ADC_BOOST_CONTROL
,
376 NAU8822_REG_RIGHT_ADC_BOOST_CONTROL
, 0, 7, 0, boost_tlv
),
378 SOC_SINGLE("DAC 128x Oversampling Switch",
379 NAU8822_REG_DAC_CONTROL
, 5, 1, 0),
380 SOC_SINGLE("ADC 128x Oversampling Switch",
381 NAU8822_REG_ADC_CONTROL
, 5, 1, 0),
384 /* LMAIN and RMAIN Mixer */
385 static const struct snd_kcontrol_new nau8822_left_out_mixer
[] = {
386 SOC_DAPM_SINGLE("LINMIX Switch",
387 NAU8822_REG_LEFT_MIXER_CONTROL
, 1, 1, 0),
388 SOC_DAPM_SINGLE("LAUX Switch",
389 NAU8822_REG_LEFT_MIXER_CONTROL
, 5, 1, 0),
390 SOC_DAPM_SINGLE("LDAC Switch",
391 NAU8822_REG_LEFT_MIXER_CONTROL
, 0, 1, 0),
392 SOC_DAPM_SINGLE("RDAC Switch",
393 NAU8822_REG_OUTPUT_CONTROL
, 5, 1, 0),
396 static const struct snd_kcontrol_new nau8822_right_out_mixer
[] = {
397 SOC_DAPM_SINGLE("RINMIX Switch",
398 NAU8822_REG_RIGHT_MIXER_CONTROL
, 1, 1, 0),
399 SOC_DAPM_SINGLE("RAUX Switch",
400 NAU8822_REG_RIGHT_MIXER_CONTROL
, 5, 1, 0),
401 SOC_DAPM_SINGLE("RDAC Switch",
402 NAU8822_REG_RIGHT_MIXER_CONTROL
, 0, 1, 0),
403 SOC_DAPM_SINGLE("LDAC Switch",
404 NAU8822_REG_OUTPUT_CONTROL
, 6, 1, 0),
407 /* AUX1 and AUX2 Mixer */
408 static const struct snd_kcontrol_new nau8822_auxout1_mixer
[] = {
409 SOC_DAPM_SINGLE("RDAC Switch", NAU8822_REG_AUX1_MIXER
, 0, 1, 0),
410 SOC_DAPM_SINGLE("RMIX Switch", NAU8822_REG_AUX1_MIXER
, 1, 1, 0),
411 SOC_DAPM_SINGLE("RINMIX Switch", NAU8822_REG_AUX1_MIXER
, 2, 1, 0),
412 SOC_DAPM_SINGLE("LDAC Switch", NAU8822_REG_AUX1_MIXER
, 3, 1, 0),
413 SOC_DAPM_SINGLE("LMIX Switch", NAU8822_REG_AUX1_MIXER
, 4, 1, 0),
416 static const struct snd_kcontrol_new nau8822_auxout2_mixer
[] = {
417 SOC_DAPM_SINGLE("LDAC Switch", NAU8822_REG_AUX2_MIXER
, 0, 1, 0),
418 SOC_DAPM_SINGLE("LMIX Switch", NAU8822_REG_AUX2_MIXER
, 1, 1, 0),
419 SOC_DAPM_SINGLE("LINMIX Switch", NAU8822_REG_AUX2_MIXER
, 2, 1, 0),
420 SOC_DAPM_SINGLE("AUX1MIX Output Switch",
421 NAU8822_REG_AUX2_MIXER
, 3, 1, 0),
425 static const struct snd_kcontrol_new nau8822_left_input_mixer
[] = {
426 SOC_DAPM_SINGLE("L2 Switch", NAU8822_REG_INPUT_CONTROL
, 2, 1, 0),
427 SOC_DAPM_SINGLE("MicN Switch", NAU8822_REG_INPUT_CONTROL
, 1, 1, 0),
428 SOC_DAPM_SINGLE("MicP Switch", NAU8822_REG_INPUT_CONTROL
, 0, 1, 0),
430 static const struct snd_kcontrol_new nau8822_right_input_mixer
[] = {
431 SOC_DAPM_SINGLE("R2 Switch", NAU8822_REG_INPUT_CONTROL
, 6, 1, 0),
432 SOC_DAPM_SINGLE("MicN Switch", NAU8822_REG_INPUT_CONTROL
, 5, 1, 0),
433 SOC_DAPM_SINGLE("MicP Switch", NAU8822_REG_INPUT_CONTROL
, 4, 1, 0),
436 /* Loopback Switch */
437 static const struct snd_kcontrol_new nau8822_loopback
=
438 SOC_DAPM_SINGLE("Switch", NAU8822_REG_COMPANDING_CONTROL
,
439 NAU8822_ADDAP_SFT
, 1, 0);
441 static int check_mclk_select_pll(struct snd_soc_dapm_widget
*source
,
442 struct snd_soc_dapm_widget
*sink
)
444 struct snd_soc_component
*component
=
445 snd_soc_dapm_to_component(source
->dapm
);
448 value
= snd_soc_component_read(component
, NAU8822_REG_CLOCKING
);
450 return (value
& NAU8822_CLKM_MASK
);
453 static const struct snd_soc_dapm_widget nau8822_dapm_widgets
[] = {
454 SND_SOC_DAPM_DAC("Left DAC", "Left HiFi Playback",
455 NAU8822_REG_POWER_MANAGEMENT_3
, 0, 0),
456 SND_SOC_DAPM_DAC("Right DAC", "Right HiFi Playback",
457 NAU8822_REG_POWER_MANAGEMENT_3
, 1, 0),
458 SND_SOC_DAPM_ADC("Left ADC", "Left HiFi Capture",
459 NAU8822_REG_POWER_MANAGEMENT_2
, 0, 0),
460 SND_SOC_DAPM_ADC("Right ADC", "Right HiFi Capture",
461 NAU8822_REG_POWER_MANAGEMENT_2
, 1, 0),
463 SOC_MIXER_ARRAY("Left Output Mixer",
464 NAU8822_REG_POWER_MANAGEMENT_3
, 2, 0, nau8822_left_out_mixer
),
465 SOC_MIXER_ARRAY("Right Output Mixer",
466 NAU8822_REG_POWER_MANAGEMENT_3
, 3, 0, nau8822_right_out_mixer
),
467 SOC_MIXER_ARRAY("AUX1 Output Mixer",
468 NAU8822_REG_POWER_MANAGEMENT_1
, 7, 0, nau8822_auxout1_mixer
),
469 SOC_MIXER_ARRAY("AUX2 Output Mixer",
470 NAU8822_REG_POWER_MANAGEMENT_1
, 6, 0, nau8822_auxout2_mixer
),
472 SOC_MIXER_ARRAY("Left Input Mixer",
473 NAU8822_REG_POWER_MANAGEMENT_2
,
474 2, 0, nau8822_left_input_mixer
),
475 SOC_MIXER_ARRAY("Right Input Mixer",
476 NAU8822_REG_POWER_MANAGEMENT_2
,
477 3, 0, nau8822_right_input_mixer
),
479 SND_SOC_DAPM_PGA("Left Boost Mixer",
480 NAU8822_REG_POWER_MANAGEMENT_2
, 4, 0, NULL
, 0),
481 SND_SOC_DAPM_PGA("Right Boost Mixer",
482 NAU8822_REG_POWER_MANAGEMENT_2
, 5, 0, NULL
, 0),
484 SND_SOC_DAPM_PGA("Left Capture PGA",
485 NAU8822_REG_LEFT_INP_PGA_CONTROL
, 6, 1, NULL
, 0),
486 SND_SOC_DAPM_PGA("Right Capture PGA",
487 NAU8822_REG_RIGHT_INP_PGA_CONTROL
, 6, 1, NULL
, 0),
489 SND_SOC_DAPM_PGA("Left Headphone Out",
490 NAU8822_REG_POWER_MANAGEMENT_2
, 7, 0, NULL
, 0),
491 SND_SOC_DAPM_PGA("Right Headphone Out",
492 NAU8822_REG_POWER_MANAGEMENT_2
, 8, 0, NULL
, 0),
494 SND_SOC_DAPM_PGA("Left Speaker Out",
495 NAU8822_REG_POWER_MANAGEMENT_3
, 6, 0, NULL
, 0),
496 SND_SOC_DAPM_PGA("Right Speaker Out",
497 NAU8822_REG_POWER_MANAGEMENT_3
, 5, 0, NULL
, 0),
499 SND_SOC_DAPM_PGA("AUX1 Out",
500 NAU8822_REG_POWER_MANAGEMENT_3
, 8, 0, NULL
, 0),
501 SND_SOC_DAPM_PGA("AUX2 Out",
502 NAU8822_REG_POWER_MANAGEMENT_3
, 7, 0, NULL
, 0),
504 SND_SOC_DAPM_SUPPLY("Mic Bias",
505 NAU8822_REG_POWER_MANAGEMENT_1
, 4, 0, NULL
, 0),
506 SND_SOC_DAPM_SUPPLY("PLL",
507 NAU8822_REG_POWER_MANAGEMENT_1
, 5, 0, NULL
, 0),
509 SND_SOC_DAPM_SWITCH("Digital Loopback", SND_SOC_NOPM
, 0, 0,
512 SND_SOC_DAPM_INPUT("LMICN"),
513 SND_SOC_DAPM_INPUT("LMICP"),
514 SND_SOC_DAPM_INPUT("RMICN"),
515 SND_SOC_DAPM_INPUT("RMICP"),
516 SND_SOC_DAPM_INPUT("LAUX"),
517 SND_SOC_DAPM_INPUT("RAUX"),
518 SND_SOC_DAPM_INPUT("L2"),
519 SND_SOC_DAPM_INPUT("R2"),
520 SND_SOC_DAPM_OUTPUT("LHP"),
521 SND_SOC_DAPM_OUTPUT("RHP"),
522 SND_SOC_DAPM_OUTPUT("LSPK"),
523 SND_SOC_DAPM_OUTPUT("RSPK"),
524 SND_SOC_DAPM_OUTPUT("AUXOUT1"),
525 SND_SOC_DAPM_OUTPUT("AUXOUT2"),
528 static const struct snd_soc_dapm_route nau8822_dapm_routes
[] = {
529 {"Right DAC", NULL
, "PLL", check_mclk_select_pll
},
530 {"Left DAC", NULL
, "PLL", check_mclk_select_pll
},
532 /* LMAIN and RMAIN Mixer */
533 {"Right Output Mixer", "LDAC Switch", "Left DAC"},
534 {"Right Output Mixer", "RDAC Switch", "Right DAC"},
535 {"Right Output Mixer", "RAUX Switch", "RAUX"},
536 {"Right Output Mixer", "RINMIX Switch", "Right Boost Mixer"},
538 {"Left Output Mixer", "LDAC Switch", "Left DAC"},
539 {"Left Output Mixer", "RDAC Switch", "Right DAC"},
540 {"Left Output Mixer", "LAUX Switch", "LAUX"},
541 {"Left Output Mixer", "LINMIX Switch", "Left Boost Mixer"},
543 /* AUX1 and AUX2 Mixer */
544 {"AUX1 Output Mixer", "RDAC Switch", "Right DAC"},
545 {"AUX1 Output Mixer", "RMIX Switch", "Right Output Mixer"},
546 {"AUX1 Output Mixer", "RINMIX Switch", "Right Boost Mixer"},
547 {"AUX1 Output Mixer", "LDAC Switch", "Left DAC"},
548 {"AUX1 Output Mixer", "LMIX Switch", "Left Output Mixer"},
550 {"AUX2 Output Mixer", "LDAC Switch", "Left DAC"},
551 {"AUX2 Output Mixer", "LMIX Switch", "Left Output Mixer"},
552 {"AUX2 Output Mixer", "LINMIX Switch", "Left Boost Mixer"},
553 {"AUX2 Output Mixer", "AUX1MIX Output Switch", "AUX1 Output Mixer"},
556 {"Right Headphone Out", NULL
, "Right Output Mixer"},
557 {"RHP", NULL
, "Right Headphone Out"},
559 {"Left Headphone Out", NULL
, "Left Output Mixer"},
560 {"LHP", NULL
, "Left Headphone Out"},
562 {"Right Speaker Out", NULL
, "Right Output Mixer"},
563 {"RSPK", NULL
, "Right Speaker Out"},
565 {"Left Speaker Out", NULL
, "Left Output Mixer"},
566 {"LSPK", NULL
, "Left Speaker Out"},
568 {"AUX1 Out", NULL
, "AUX1 Output Mixer"},
569 {"AUX2 Out", NULL
, "AUX2 Output Mixer"},
570 {"AUXOUT1", NULL
, "AUX1 Out"},
571 {"AUXOUT2", NULL
, "AUX2 Out"},
574 {"Right ADC", NULL
, "PLL", check_mclk_select_pll
},
575 {"Left ADC", NULL
, "PLL", check_mclk_select_pll
},
577 {"Right ADC", NULL
, "Right Boost Mixer"},
579 {"Right Boost Mixer", NULL
, "RAUX"},
580 {"Right Boost Mixer", NULL
, "Right Capture PGA"},
581 {"Right Boost Mixer", NULL
, "R2"},
583 {"Left ADC", NULL
, "Left Boost Mixer"},
585 {"Left Boost Mixer", NULL
, "LAUX"},
586 {"Left Boost Mixer", NULL
, "Left Capture PGA"},
587 {"Left Boost Mixer", NULL
, "L2"},
590 {"Right Capture PGA", NULL
, "Right Input Mixer"},
591 {"Left Capture PGA", NULL
, "Left Input Mixer"},
593 /* Enable Microphone Power */
594 {"Right Capture PGA", NULL
, "Mic Bias"},
595 {"Left Capture PGA", NULL
, "Mic Bias"},
597 {"Right Input Mixer", "R2 Switch", "R2"},
598 {"Right Input Mixer", "MicN Switch", "RMICN"},
599 {"Right Input Mixer", "MicP Switch", "RMICP"},
601 {"Left Input Mixer", "L2 Switch", "L2"},
602 {"Left Input Mixer", "MicN Switch", "LMICN"},
603 {"Left Input Mixer", "MicP Switch", "LMICP"},
605 /* Digital Loopback */
606 {"Digital Loopback", "Switch", "Left ADC"},
607 {"Digital Loopback", "Switch", "Right ADC"},
608 {"Left DAC", NULL
, "Digital Loopback"},
609 {"Right DAC", NULL
, "Digital Loopback"},
612 static int nau8822_set_dai_sysclk(struct snd_soc_dai
*dai
, int clk_id
,
613 unsigned int freq
, int dir
)
615 struct snd_soc_component
*component
= dai
->component
;
616 struct nau8822
*nau8822
= snd_soc_component_get_drvdata(component
);
618 nau8822
->div_id
= clk_id
;
619 nau8822
->sysclk
= freq
;
620 dev_dbg(component
->dev
, "master sysclk %dHz, source %s\n", freq
,
621 clk_id
== NAU8822_CLK_PLL
? "PLL" : "MCLK");
626 static int nau8822_calc_pll(unsigned int pll_in
, unsigned int fs
,
627 struct nau8822_pll
*pll_param
)
629 u64 f2
, f2_max
, pll_ratio
;
632 if (pll_in
> NAU_PLL_REF_MAX
|| pll_in
< NAU_PLL_REF_MIN
)
635 scal_sel
= ARRAY_SIZE(nau8822_mclk_scaler
);
637 for (i
= 0; i
< scal_sel
; i
++) {
638 f2
= 256 * fs
* 4 * nau8822_mclk_scaler
[i
] / 10;
639 if (f2
> NAU_PLL_FREQ_MIN
&& f2
< NAU_PLL_FREQ_MAX
&&
646 if (ARRAY_SIZE(nau8822_mclk_scaler
) == scal_sel
)
648 pll_param
->mclk_scaler
= scal_sel
;
651 /* Calculate the PLL 4-bit integer input and the PLL 24-bit fractional
652 * input; round up the 24+4bit.
654 pll_ratio
= div_u64(f2
<< 28, pll_in
);
655 pll_param
->pre_factor
= 0;
656 if (((pll_ratio
>> 28) & 0xF) < NAU_PLL_OPTOP_MIN
) {
658 pll_param
->pre_factor
= 1;
660 pll_param
->pll_int
= (pll_ratio
>> 28) & 0xF;
661 pll_param
->pll_frac
= ((pll_ratio
& 0xFFFFFFF) >> 4);
666 static int nau8822_config_clkdiv(struct snd_soc_dai
*dai
, int div
, int rate
)
668 struct snd_soc_component
*component
= dai
->component
;
669 struct nau8822
*nau8822
= snd_soc_component_get_drvdata(component
);
670 struct nau8822_pll
*pll
= &nau8822
->pll
;
673 switch (nau8822
->div_id
) {
674 case NAU8822_CLK_MCLK
:
675 /* Configure the master clock prescaler div to make system
676 * clock to approximate the internal master clock (IMCLK);
677 * and large or equal to IMCLK.
681 for (i
= 1; i
< ARRAY_SIZE(nau8822_mclk_scaler
); i
++) {
682 sclk
= (nau8822
->sysclk
* 10) / nau8822_mclk_scaler
[i
];
687 dev_dbg(component
->dev
, "master clock prescaler %x for fs %d\n",
690 /* master clock from MCLK and disable PLL */
691 snd_soc_component_update_bits(component
,
692 NAU8822_REG_CLOCKING
, NAU8822_MCLKSEL_MASK
,
693 (div
<< NAU8822_MCLKSEL_SFT
));
694 snd_soc_component_update_bits(component
,
695 NAU8822_REG_CLOCKING
, NAU8822_CLKM_MASK
,
699 case NAU8822_CLK_PLL
:
700 /* master clock from PLL and enable PLL */
701 if (pll
->mclk_scaler
!= div
) {
702 dev_err(component
->dev
,
703 "master clock prescaler not meet PLL parameters\n");
706 snd_soc_component_update_bits(component
,
707 NAU8822_REG_CLOCKING
, NAU8822_MCLKSEL_MASK
,
708 (div
<< NAU8822_MCLKSEL_SFT
));
709 snd_soc_component_update_bits(component
,
710 NAU8822_REG_CLOCKING
, NAU8822_CLKM_MASK
,
721 static int nau8822_set_pll(struct snd_soc_dai
*dai
, int pll_id
, int source
,
722 unsigned int freq_in
, unsigned int freq_out
)
724 struct snd_soc_component
*component
= dai
->component
;
725 struct nau8822
*nau8822
= snd_soc_component_get_drvdata(component
);
726 struct nau8822_pll
*pll_param
= &nau8822
->pll
;
731 ret
= nau8822_calc_pll(freq_in
, fs
, pll_param
);
733 dev_err(component
->dev
, "Unsupported input clock %d\n",
738 dev_info(component
->dev
,
739 "pll_int=%x pll_frac=%x mclk_scaler=%x pre_factor=%x\n",
740 pll_param
->pll_int
, pll_param
->pll_frac
,
741 pll_param
->mclk_scaler
, pll_param
->pre_factor
);
743 snd_soc_component_update_bits(component
,
744 NAU8822_REG_PLL_N
, NAU8822_PLLMCLK_DIV2
| NAU8822_PLLN_MASK
,
745 (pll_param
->pre_factor
? NAU8822_PLLMCLK_DIV2
: 0) |
747 snd_soc_component_write(component
,
748 NAU8822_REG_PLL_K1
, (pll_param
->pll_frac
>> NAU8822_PLLK1_SFT
) &
750 snd_soc_component_write(component
,
751 NAU8822_REG_PLL_K2
, (pll_param
->pll_frac
>> NAU8822_PLLK2_SFT
) &
753 snd_soc_component_write(component
,
754 NAU8822_REG_PLL_K3
, pll_param
->pll_frac
& NAU8822_PLLK3_MASK
);
755 snd_soc_component_update_bits(component
,
756 NAU8822_REG_CLOCKING
, NAU8822_MCLKSEL_MASK
,
757 pll_param
->mclk_scaler
<< NAU8822_MCLKSEL_SFT
);
758 snd_soc_component_update_bits(component
,
759 NAU8822_REG_CLOCKING
, NAU8822_CLKM_MASK
, NAU8822_CLKM_PLL
);
764 static int nau8822_set_dai_fmt(struct snd_soc_dai
*dai
, unsigned int fmt
)
766 struct snd_soc_component
*component
= dai
->component
;
767 u16 ctrl1_val
= 0, ctrl2_val
= 0;
769 dev_dbg(component
->dev
, "%s\n", __func__
);
771 switch (fmt
& SND_SOC_DAIFMT_MASTER_MASK
) {
772 case SND_SOC_DAIFMT_CBM_CFM
:
775 case SND_SOC_DAIFMT_CBS_CFS
:
782 switch (fmt
& SND_SOC_DAIFMT_FORMAT_MASK
) {
783 case SND_SOC_DAIFMT_I2S
:
786 case SND_SOC_DAIFMT_RIGHT_J
:
788 case SND_SOC_DAIFMT_LEFT_J
:
791 case SND_SOC_DAIFMT_DSP_A
:
798 switch (fmt
& SND_SOC_DAIFMT_INV_MASK
) {
799 case SND_SOC_DAIFMT_NB_NF
:
801 case SND_SOC_DAIFMT_IB_IF
:
804 case SND_SOC_DAIFMT_IB_NF
:
807 case SND_SOC_DAIFMT_NB_IF
:
814 snd_soc_component_update_bits(component
,
815 NAU8822_REG_AUDIO_INTERFACE
,
816 NAU8822_AIFMT_MASK
| NAU8822_LRP_MASK
| NAU8822_BCLKP_MASK
,
818 snd_soc_component_update_bits(component
,
819 NAU8822_REG_CLOCKING
, NAU8822_CLKIOEN_MASK
, ctrl2_val
);
824 static int nau8822_hw_params(struct snd_pcm_substream
*substream
,
825 struct snd_pcm_hw_params
*params
,
826 struct snd_soc_dai
*dai
)
828 struct snd_soc_component
*component
= dai
->component
;
829 struct nau8822
*nau8822
= snd_soc_component_get_drvdata(component
);
830 int val_len
= 0, val_rate
= 0;
831 unsigned int ctrl_val
, bclk_fs
, bclk_div
;
833 /* make BCLK and LRC divide configuration if the codec as master. */
834 ctrl_val
= snd_soc_component_read(component
, NAU8822_REG_CLOCKING
);
835 if (ctrl_val
& NAU8822_CLK_MASTER
) {
836 /* get the bclk and fs ratio */
837 bclk_fs
= snd_soc_params_to_bclk(params
) / params_rate(params
);
839 bclk_div
= NAU8822_BCLKDIV_8
;
840 else if (bclk_fs
<= 64)
841 bclk_div
= NAU8822_BCLKDIV_4
;
842 else if (bclk_fs
<= 128)
843 bclk_div
= NAU8822_BCLKDIV_2
;
846 snd_soc_component_update_bits(component
, NAU8822_REG_CLOCKING
,
847 NAU8822_BCLKSEL_MASK
, bclk_div
);
850 switch (params_format(params
)) {
851 case SNDRV_PCM_FORMAT_S16_LE
:
853 case SNDRV_PCM_FORMAT_S20_3LE
:
854 val_len
|= NAU8822_WLEN_20
;
856 case SNDRV_PCM_FORMAT_S24_LE
:
857 val_len
|= NAU8822_WLEN_24
;
859 case SNDRV_PCM_FORMAT_S32_LE
:
860 val_len
|= NAU8822_WLEN_32
;
866 switch (params_rate(params
)) {
868 val_rate
|= NAU8822_SMPLR_8K
;
871 val_rate
|= NAU8822_SMPLR_12K
;
874 val_rate
|= NAU8822_SMPLR_16K
;
877 val_rate
|= NAU8822_SMPLR_24K
;
880 val_rate
|= NAU8822_SMPLR_32K
;
889 snd_soc_component_update_bits(component
,
890 NAU8822_REG_AUDIO_INTERFACE
, NAU8822_WLEN_MASK
, val_len
);
891 snd_soc_component_update_bits(component
,
892 NAU8822_REG_ADDITIONAL_CONTROL
, NAU8822_SMPLR_MASK
, val_rate
);
894 /* If the master clock is from MCLK, provide the runtime FS for driver
895 * to get the master clock prescaler configuration.
897 if (nau8822
->div_id
== NAU8822_CLK_MCLK
)
898 nau8822_config_clkdiv(dai
, 0, params_rate(params
));
903 static int nau8822_mute(struct snd_soc_dai
*dai
, int mute
, int direction
)
905 struct snd_soc_component
*component
= dai
->component
;
907 dev_dbg(component
->dev
, "%s: %d\n", __func__
, mute
);
910 snd_soc_component_update_bits(component
,
911 NAU8822_REG_DAC_CONTROL
, 0x40, 0x40);
913 snd_soc_component_update_bits(component
,
914 NAU8822_REG_DAC_CONTROL
, 0x40, 0);
919 static int nau8822_set_bias_level(struct snd_soc_component
*component
,
920 enum snd_soc_bias_level level
)
923 case SND_SOC_BIAS_ON
:
924 case SND_SOC_BIAS_PREPARE
:
925 snd_soc_component_update_bits(component
,
926 NAU8822_REG_POWER_MANAGEMENT_1
,
927 NAU8822_REFIMP_MASK
, NAU8822_REFIMP_80K
);
930 case SND_SOC_BIAS_STANDBY
:
931 snd_soc_component_update_bits(component
,
932 NAU8822_REG_POWER_MANAGEMENT_1
,
933 NAU8822_IOBUF_EN
| NAU8822_ABIAS_EN
,
934 NAU8822_IOBUF_EN
| NAU8822_ABIAS_EN
);
936 if (snd_soc_component_get_bias_level(component
) ==
938 snd_soc_component_update_bits(component
,
939 NAU8822_REG_POWER_MANAGEMENT_1
,
940 NAU8822_REFIMP_MASK
, NAU8822_REFIMP_3K
);
943 snd_soc_component_update_bits(component
,
944 NAU8822_REG_POWER_MANAGEMENT_1
,
945 NAU8822_REFIMP_MASK
, NAU8822_REFIMP_300K
);
948 case SND_SOC_BIAS_OFF
:
949 snd_soc_component_write(component
,
950 NAU8822_REG_POWER_MANAGEMENT_1
, 0);
951 snd_soc_component_write(component
,
952 NAU8822_REG_POWER_MANAGEMENT_2
, 0);
953 snd_soc_component_write(component
,
954 NAU8822_REG_POWER_MANAGEMENT_3
, 0);
958 dev_dbg(component
->dev
, "%s: %d\n", __func__
, level
);
963 #define NAU8822_RATES (SNDRV_PCM_RATE_8000_48000)
965 #define NAU8822_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
966 SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
968 static const struct snd_soc_dai_ops nau8822_dai_ops
= {
969 .hw_params
= nau8822_hw_params
,
970 .mute_stream
= nau8822_mute
,
971 .set_fmt
= nau8822_set_dai_fmt
,
972 .set_sysclk
= nau8822_set_dai_sysclk
,
973 .set_pll
= nau8822_set_pll
,
974 .no_capture_mute
= 1,
977 static struct snd_soc_dai_driver nau8822_dai
= {
978 .name
= "nau8822-hifi",
980 .stream_name
= "Playback",
983 .rates
= NAU8822_RATES
,
984 .formats
= NAU8822_FORMATS
,
987 .stream_name
= "Capture",
990 .rates
= NAU8822_RATES
,
991 .formats
= NAU8822_FORMATS
,
993 .ops
= &nau8822_dai_ops
,
994 .symmetric_rates
= 1,
997 static int nau8822_suspend(struct snd_soc_component
*component
)
999 struct nau8822
*nau8822
= snd_soc_component_get_drvdata(component
);
1001 snd_soc_component_force_bias_level(component
, SND_SOC_BIAS_OFF
);
1003 regcache_mark_dirty(nau8822
->regmap
);
1008 static int nau8822_resume(struct snd_soc_component
*component
)
1010 struct nau8822
*nau8822
= snd_soc_component_get_drvdata(component
);
1012 regcache_sync(nau8822
->regmap
);
1014 snd_soc_component_force_bias_level(component
, SND_SOC_BIAS_STANDBY
);
1020 * These registers contain an "update" bit - bit 8. This means, for example,
1021 * that one can write new DAC digital volume for both channels, but only when
1022 * the update bit is set, will also the volume be updated - simultaneously for
1025 static const int update_reg
[] = {
1026 NAU8822_REG_LEFT_DAC_DIGITAL_VOLUME
,
1027 NAU8822_REG_RIGHT_DAC_DIGITAL_VOLUME
,
1028 NAU8822_REG_LEFT_ADC_DIGITAL_VOLUME
,
1029 NAU8822_REG_RIGHT_ADC_DIGITAL_VOLUME
,
1030 NAU8822_REG_LEFT_INP_PGA_CONTROL
,
1031 NAU8822_REG_RIGHT_INP_PGA_CONTROL
,
1032 NAU8822_REG_LHP_VOLUME
,
1033 NAU8822_REG_RHP_VOLUME
,
1034 NAU8822_REG_LSPKOUT_VOLUME
,
1035 NAU8822_REG_RSPKOUT_VOLUME
,
1038 static int nau8822_probe(struct snd_soc_component
*component
)
1043 * Set the update bit in all registers, that have one. This way all
1044 * writes to those registers will also cause the update bit to be
1047 for (i
= 0; i
< ARRAY_SIZE(update_reg
); i
++)
1048 snd_soc_component_update_bits(component
,
1049 update_reg
[i
], 0x100, 0x100);
1054 static const struct snd_soc_component_driver soc_component_dev_nau8822
= {
1055 .probe
= nau8822_probe
,
1056 .suspend
= nau8822_suspend
,
1057 .resume
= nau8822_resume
,
1058 .set_bias_level
= nau8822_set_bias_level
,
1059 .controls
= nau8822_snd_controls
,
1060 .num_controls
= ARRAY_SIZE(nau8822_snd_controls
),
1061 .dapm_widgets
= nau8822_dapm_widgets
,
1062 .num_dapm_widgets
= ARRAY_SIZE(nau8822_dapm_widgets
),
1063 .dapm_routes
= nau8822_dapm_routes
,
1064 .num_dapm_routes
= ARRAY_SIZE(nau8822_dapm_routes
),
1066 .use_pmdown_time
= 1,
1068 .non_legacy_dai_naming
= 1,
1071 static const struct regmap_config nau8822_regmap_config
= {
1075 .max_register
= NAU8822_REG_MAX_REGISTER
,
1076 .volatile_reg
= nau8822_volatile
,
1078 .readable_reg
= nau8822_readable_reg
,
1079 .writeable_reg
= nau8822_writeable_reg
,
1081 .cache_type
= REGCACHE_RBTREE
,
1082 .reg_defaults
= nau8822_reg_defaults
,
1083 .num_reg_defaults
= ARRAY_SIZE(nau8822_reg_defaults
),
1086 static int nau8822_i2c_probe(struct i2c_client
*i2c
,
1087 const struct i2c_device_id
*id
)
1089 struct device
*dev
= &i2c
->dev
;
1090 struct nau8822
*nau8822
= dev_get_platdata(dev
);
1094 nau8822
= devm_kzalloc(dev
, sizeof(*nau8822
), GFP_KERNEL
);
1095 if (nau8822
== NULL
)
1098 i2c_set_clientdata(i2c
, nau8822
);
1100 nau8822
->regmap
= devm_regmap_init_i2c(i2c
, &nau8822_regmap_config
);
1101 if (IS_ERR(nau8822
->regmap
)) {
1102 ret
= PTR_ERR(nau8822
->regmap
);
1103 dev_err(&i2c
->dev
, "Failed to allocate regmap: %d\n", ret
);
1108 /* Reset the codec */
1109 ret
= regmap_write(nau8822
->regmap
, NAU8822_REG_RESET
, 0x00);
1111 dev_err(&i2c
->dev
, "Failed to issue reset: %d\n", ret
);
1115 ret
= devm_snd_soc_register_component(dev
, &soc_component_dev_nau8822
,
1118 dev_err(&i2c
->dev
, "Failed to register CODEC: %d\n", ret
);
1125 static const struct i2c_device_id nau8822_i2c_id
[] = {
1129 MODULE_DEVICE_TABLE(i2c
, nau8822_i2c_id
);
1132 static const struct of_device_id nau8822_of_match
[] = {
1133 { .compatible
= "nuvoton,nau8822", },
1136 MODULE_DEVICE_TABLE(of
, nau8822_of_match
);
1139 static struct i2c_driver nau8822_i2c_driver
= {
1142 .of_match_table
= of_match_ptr(nau8822_of_match
),
1144 .probe
= nau8822_i2c_probe
,
1145 .id_table
= nau8822_i2c_id
,
1147 module_i2c_driver(nau8822_i2c_driver
);
1149 MODULE_DESCRIPTION("ASoC NAU8822 codec driver");
1150 MODULE_AUTHOR("David Lin <ctlin0@nuvoton.com>");
1151 MODULE_LICENSE("GPL v2");