2 * alc5632.c -- ALC5632 ALSA SoC Audio Codec
4 * Copyright (C) 2011 The AC100 Kernel Team <ac100@lists.lauchpad.net>
6 * Authors: Leon Romanovsky <leon@leon.nu>
7 * Andrey Danin <danindrey@mail.ru>
8 * Ilya Petrov <ilya.muromec@gmail.com>
9 * Marc Dietrich <marvin24@gmx.de>
11 * Based on alc5623.c by Arnaud Patard
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License version 2 as
15 * published by the Free Software Foundation.
18 #include <linux/module.h>
19 #include <linux/kernel.h>
20 #include <linux/init.h>
21 #include <linux/delay.h>
23 #include <linux/i2c.h>
24 #include <linux/slab.h>
25 #include <sound/core.h>
26 #include <sound/pcm.h>
27 #include <sound/pcm_params.h>
28 #include <sound/tlv.h>
29 #include <sound/soc.h>
30 #include <sound/initval.h>
35 * ALC5632 register cache
37 static const u16 alc5632_reg_defaults
[] = {
38 0x59B4, 0x0000, 0x8080, 0x0000, /* 0 */
39 0x8080, 0x0000, 0x8080, 0x0000, /* 4 */
40 0xC800, 0x0000, 0xE808, 0x0000, /* 8 */
41 0x1010, 0x0000, 0x0808, 0x0000, /* 12 */
42 0xEE0F, 0x0000, 0xCBCB, 0x0000, /* 16 */
43 0x7F7F, 0x0000, 0x0000, 0x0000, /* 20 */
44 0xE010, 0x0000, 0x0000, 0x0000, /* 24 */
45 0x8008, 0x0000, 0x0000, 0x0000, /* 28 */
46 0x0000, 0x0000, 0x0000, 0x0000, /* 32 */
47 0x00C0, 0x0000, 0xEF00, 0x0000, /* 36 */
48 0x0000, 0x0000, 0x0000, 0x0000, /* 40 */
49 0x0000, 0x0000, 0x0000, 0x0000, /* 44 */
50 0x0000, 0x0000, 0x0000, 0x0000, /* 48 */
51 0x8000, 0x0000, 0x0000, 0x0000, /* 52 */
52 0x0000, 0x0000, 0x0000, 0x0000, /* 56 */
53 0x0000, 0x0000, 0x8000, 0x0000, /* 60 */
54 0x0C0A, 0x0000, 0x0000, 0x0000, /* 64 */
55 0x0000, 0x0000, 0x0000, 0x0000, /* 68 */
56 0x0000, 0x0000, 0x0000, 0x0000, /* 72 */
57 0xBE3E, 0x0000, 0xBE3E, 0x0000, /* 76 */
58 0x0000, 0x0000, 0x0000, 0x0000, /* 80 */
59 0x803A, 0x0000, 0x0000, 0x0000, /* 84 */
60 0x0000, 0x0000, 0x0009, 0x0000, /* 88 */
61 0x0000, 0x0000, 0x3000, 0x0000, /* 92 */
62 0x3075, 0x0000, 0x1010, 0x0000, /* 96 */
63 0x3110, 0x0000, 0x0000, 0x0000, /* 100 */
64 0x0553, 0x0000, 0x0000, 0x0000, /* 104 */
65 0x0000, 0x0000, 0x0000, 0x0000, /* 108 */
68 /* codec private data */
70 enum snd_soc_control_type control_type
;
75 static int alc5632_volatile_register(struct snd_soc_codec
*codec
,
80 case ALC5632_PWR_DOWN_CTRL_STATUS
:
81 case ALC5632_GPIO_PIN_STATUS
:
82 case ALC5632_OVER_CURR_STATUS
:
83 case ALC5632_HID_CTRL_DATA
:
94 static inline int alc5632_reset(struct snd_soc_codec
*codec
)
96 snd_soc_write(codec
, ALC5632_RESET
, 0);
97 return snd_soc_read(codec
, ALC5632_RESET
);
100 static int amp_mixer_event(struct snd_soc_dapm_widget
*w
,
101 struct snd_kcontrol
*kcontrol
, int event
)
103 /* to power-on/off class-d amp generators/speaker */
104 /* need to write to 'index-46h' register : */
105 /* so write index num (here 0x46) to reg 0x6a */
106 /* and then 0xffff/0 to reg 0x6c */
107 snd_soc_write(w
->codec
, ALC5632_HID_CTRL_INDEX
, 0x46);
110 case SND_SOC_DAPM_PRE_PMU
:
111 snd_soc_write(w
->codec
, ALC5632_HID_CTRL_DATA
, 0xFFFF);
113 case SND_SOC_DAPM_POST_PMD
:
114 snd_soc_write(w
->codec
, ALC5632_HID_CTRL_DATA
, 0);
125 /* -34.5db min scale, 1.5db steps, no mute */
126 static const DECLARE_TLV_DB_SCALE(vol_tlv
, -3450, 150, 0);
127 /* -46.5db min scale, 1.5db steps, no mute */
128 static const DECLARE_TLV_DB_SCALE(hp_tlv
, -4650, 150, 0);
129 /* -16.5db min scale, 1.5db steps, no mute */
130 static const DECLARE_TLV_DB_SCALE(adc_rec_tlv
, -1650, 150, 0);
131 static const unsigned int boost_tlv
[] = {
132 TLV_DB_RANGE_HEAD(3),
133 0, 0, TLV_DB_SCALE_ITEM(0, 0, 0),
134 1, 1, TLV_DB_SCALE_ITEM(2000, 0, 0),
135 2, 2, TLV_DB_SCALE_ITEM(3000, 0, 0),
137 /* 0db min scale, 6 db steps, no mute */
138 static const DECLARE_TLV_DB_SCALE(dig_tlv
, 0, 600, 0);
139 /* 0db min scalem 0.75db steps, no mute */
140 static const DECLARE_TLV_DB_SCALE(vdac_tlv
, -3525, 075, 0);
142 static const struct snd_kcontrol_new alc5632_vol_snd_controls
[] = {
143 /* left starts at bit 8, right at bit 0 */
144 /* 31 steps (5 bit), -46.5db scale */
145 SOC_DOUBLE_TLV("Line Playback Volume",
146 ALC5632_SPK_OUT_VOL
, 8, 0, 31, 1, hp_tlv
),
147 /* bit 15 mutes left, bit 7 right */
148 SOC_DOUBLE("Line Playback Switch",
149 ALC5632_SPK_OUT_VOL
, 15, 7, 1, 1),
150 SOC_DOUBLE_TLV("Headphone Playback Volume",
151 ALC5632_HP_OUT_VOL
, 8, 0, 31, 1, hp_tlv
),
152 SOC_DOUBLE("Headphone Playback Switch",
153 ALC5632_HP_OUT_VOL
, 15, 7, 1, 1),
156 static const struct snd_kcontrol_new alc5632_snd_controls
[] = {
157 SOC_DOUBLE_TLV("Auxout Playback Volume",
158 ALC5632_AUX_OUT_VOL
, 8, 0, 31, 1, hp_tlv
),
159 SOC_DOUBLE("Auxout Playback Switch",
160 ALC5632_AUX_OUT_VOL
, 15, 7, 1, 1),
161 SOC_SINGLE_TLV("Voice DAC Playback Volume",
162 ALC5632_VOICE_DAC_VOL
, 0, 63, 0, vdac_tlv
),
163 SOC_SINGLE_TLV("Phone Capture Volume",
164 ALC5632_PHONE_IN_VOL
, 8, 31, 1, vol_tlv
),
165 SOC_DOUBLE_TLV("LineIn Capture Volume",
166 ALC5632_LINE_IN_VOL
, 8, 0, 31, 1, vol_tlv
),
167 SOC_DOUBLE_TLV("Stereo DAC Playback Volume",
168 ALC5632_STEREO_DAC_IN_VOL
, 8, 0, 63, 1, vdac_tlv
),
169 SOC_DOUBLE("Stereo DAC Playback Switch",
170 ALC5632_STEREO_DAC_IN_VOL
, 15, 7, 1, 1),
171 SOC_SINGLE_TLV("Mic1 Capture Volume",
172 ALC5632_MIC_VOL
, 8, 31, 1, vol_tlv
),
173 SOC_SINGLE_TLV("Mic2 Capture Volume",
174 ALC5632_MIC_VOL
, 0, 31, 1, vol_tlv
),
175 SOC_DOUBLE_TLV("Rec Capture Volume",
176 ALC5632_ADC_REC_GAIN
, 8, 0, 31, 0, adc_rec_tlv
),
177 SOC_SINGLE_TLV("Mic 1 Boost Volume",
178 ALC5632_MIC_CTRL
, 10, 2, 0, boost_tlv
),
179 SOC_SINGLE_TLV("Mic 2 Boost Volume",
180 ALC5632_MIC_CTRL
, 8, 2, 0, boost_tlv
),
181 SOC_SINGLE_TLV("Digital Boost Volume",
182 ALC5632_DIGI_BOOST_CTRL
, 0, 7, 0, dig_tlv
),
188 static const struct snd_kcontrol_new alc5632_hp_mixer_controls
[] = {
189 SOC_DAPM_SINGLE("LI2HP Playback Switch", ALC5632_LINE_IN_VOL
, 15, 1, 1),
190 SOC_DAPM_SINGLE("PHONE2HP Playback Switch", ALC5632_PHONE_IN_VOL
, 15, 1, 1),
191 SOC_DAPM_SINGLE("MIC12HP Playback Switch", ALC5632_MIC_ROUTING_CTRL
, 15, 1, 1),
192 SOC_DAPM_SINGLE("MIC22HP Playback Switch", ALC5632_MIC_ROUTING_CTRL
, 11, 1, 1),
193 SOC_DAPM_SINGLE("VOICE2HP Playback Switch", ALC5632_VOICE_DAC_VOL
, 15, 1, 1),
196 static const struct snd_kcontrol_new alc5632_hpl_mixer_controls
[] = {
197 SOC_DAPM_SINGLE("ADC2HP_L Playback Switch", ALC5632_ADC_REC_GAIN
, 15, 1, 1),
198 SOC_DAPM_SINGLE("DACL2HP Playback Switch", ALC5632_MIC_ROUTING_CTRL
, 3, 1, 1),
201 static const struct snd_kcontrol_new alc5632_hpr_mixer_controls
[] = {
202 SOC_DAPM_SINGLE("ADC2HP_R Playback Switch", ALC5632_ADC_REC_GAIN
, 7, 1, 1),
203 SOC_DAPM_SINGLE("DACR2HP Playback Switch", ALC5632_MIC_ROUTING_CTRL
, 2, 1, 1),
206 static const struct snd_kcontrol_new alc5632_mono_mixer_controls
[] = {
207 SOC_DAPM_SINGLE("ADC2MONO_L Playback Switch", ALC5632_ADC_REC_GAIN
, 14, 1, 1),
208 SOC_DAPM_SINGLE("ADC2MONO_R Playback Switch", ALC5632_ADC_REC_GAIN
, 6, 1, 1),
209 SOC_DAPM_SINGLE("LI2MONO Playback Switch", ALC5632_LINE_IN_VOL
, 13, 1, 1),
210 SOC_DAPM_SINGLE("MIC12MONO Playback Switch",
211 ALC5632_MIC_ROUTING_CTRL
, 13, 1, 1),
212 SOC_DAPM_SINGLE("MIC22MONO Playback Switch",
213 ALC5632_MIC_ROUTING_CTRL
, 9, 1, 1),
214 SOC_DAPM_SINGLE("DAC2MONO Playback Switch", ALC5632_MIC_ROUTING_CTRL
, 0, 1, 1),
215 SOC_DAPM_SINGLE("VOICE2MONO Playback Switch", ALC5632_VOICE_DAC_VOL
, 13, 1, 1),
218 static const struct snd_kcontrol_new alc5632_speaker_mixer_controls
[] = {
219 SOC_DAPM_SINGLE("LI2SPK Playback Switch", ALC5632_LINE_IN_VOL
, 14, 1, 1),
220 SOC_DAPM_SINGLE("PHONE2SPK Playback Switch", ALC5632_PHONE_IN_VOL
, 14, 1, 1),
221 SOC_DAPM_SINGLE("MIC12SPK Playback Switch",
222 ALC5632_MIC_ROUTING_CTRL
, 14, 1, 1),
223 SOC_DAPM_SINGLE("MIC22SPK Playback Switch",
224 ALC5632_MIC_ROUTING_CTRL
, 10, 1, 1),
225 SOC_DAPM_SINGLE("DAC2SPK Playback Switch", ALC5632_MIC_ROUTING_CTRL
, 1, 1, 1),
226 SOC_DAPM_SINGLE("VOICE2SPK Playback Switch", ALC5632_VOICE_DAC_VOL
, 14, 1, 1),
229 /* Left Record Mixer */
230 static const struct snd_kcontrol_new alc5632_captureL_mixer_controls
[] = {
231 SOC_DAPM_SINGLE("Mic1 Capture Switch", ALC5632_ADC_REC_MIXER
, 14, 1, 1),
232 SOC_DAPM_SINGLE("Mic2 Capture Switch", ALC5632_ADC_REC_MIXER
, 13, 1, 1),
233 SOC_DAPM_SINGLE("LineInL Capture Switch", ALC5632_ADC_REC_MIXER
, 12, 1, 1),
234 SOC_DAPM_SINGLE("Left Phone Capture Switch", ALC5632_ADC_REC_MIXER
, 11, 1, 1),
235 SOC_DAPM_SINGLE("HPMixerL Capture Switch", ALC5632_ADC_REC_MIXER
, 10, 1, 1),
236 SOC_DAPM_SINGLE("SPKMixer Capture Switch", ALC5632_ADC_REC_MIXER
, 9, 1, 1),
237 SOC_DAPM_SINGLE("MonoMixer Capture Switch", ALC5632_ADC_REC_MIXER
, 8, 1, 1),
240 /* Right Record Mixer */
241 static const struct snd_kcontrol_new alc5632_captureR_mixer_controls
[] = {
242 SOC_DAPM_SINGLE("Mic1 Capture Switch", ALC5632_ADC_REC_MIXER
, 6, 1, 1),
243 SOC_DAPM_SINGLE("Mic2 Capture Switch", ALC5632_ADC_REC_MIXER
, 5, 1, 1),
244 SOC_DAPM_SINGLE("LineInR Capture Switch", ALC5632_ADC_REC_MIXER
, 4, 1, 1),
245 SOC_DAPM_SINGLE("Right Phone Capture Switch", ALC5632_ADC_REC_MIXER
, 3, 1, 1),
246 SOC_DAPM_SINGLE("HPMixerR Capture Switch", ALC5632_ADC_REC_MIXER
, 2, 1, 1),
247 SOC_DAPM_SINGLE("SPKMixer Capture Switch", ALC5632_ADC_REC_MIXER
, 1, 1, 1),
248 SOC_DAPM_SINGLE("MonoMixer Capture Switch", ALC5632_ADC_REC_MIXER
, 0, 1, 1),
251 static const char *alc5632_spk_n_sour_sel
[] = {
252 "RN/-R", "RP/+R", "LN/-R", "Mute"};
253 static const char *alc5632_hpl_out_input_sel
[] = {
254 "Vmid", "HP Left Mix"};
255 static const char *alc5632_hpr_out_input_sel
[] = {
256 "Vmid", "HP Right Mix"};
257 static const char *alc5632_spkout_input_sel
[] = {
258 "Vmid", "HPOut Mix", "Speaker Mix", "Mono Mix"};
259 static const char *alc5632_aux_out_input_sel
[] = {
260 "Vmid", "HPOut Mix", "Speaker Mix", "Mono Mix"};
262 /* auxout output mux */
263 static const struct soc_enum alc5632_aux_out_input_enum
=
264 SOC_ENUM_SINGLE(ALC5632_OUTPUT_MIXER_CTRL
, 6, 4, alc5632_aux_out_input_sel
);
265 static const struct snd_kcontrol_new alc5632_auxout_mux_controls
=
266 SOC_DAPM_ENUM("AuxOut Mux", alc5632_aux_out_input_enum
);
268 /* speaker output mux */
269 static const struct soc_enum alc5632_spkout_input_enum
=
270 SOC_ENUM_SINGLE(ALC5632_OUTPUT_MIXER_CTRL
, 10, 4, alc5632_spkout_input_sel
);
271 static const struct snd_kcontrol_new alc5632_spkout_mux_controls
=
272 SOC_DAPM_ENUM("SpeakerOut Mux", alc5632_spkout_input_enum
);
274 /* headphone left output mux */
275 static const struct soc_enum alc5632_hpl_out_input_enum
=
276 SOC_ENUM_SINGLE(ALC5632_OUTPUT_MIXER_CTRL
, 9, 2, alc5632_hpl_out_input_sel
);
277 static const struct snd_kcontrol_new alc5632_hpl_out_mux_controls
=
278 SOC_DAPM_ENUM("Left Headphone Mux", alc5632_hpl_out_input_enum
);
280 /* headphone right output mux */
281 static const struct soc_enum alc5632_hpr_out_input_enum
=
282 SOC_ENUM_SINGLE(ALC5632_OUTPUT_MIXER_CTRL
, 8, 2, alc5632_hpr_out_input_sel
);
283 static const struct snd_kcontrol_new alc5632_hpr_out_mux_controls
=
284 SOC_DAPM_ENUM("Right Headphone Mux", alc5632_hpr_out_input_enum
);
286 /* speaker output N select */
287 static const struct soc_enum alc5632_spk_n_sour_enum
=
288 SOC_ENUM_SINGLE(ALC5632_OUTPUT_MIXER_CTRL
, 14, 4, alc5632_spk_n_sour_sel
);
289 static const struct snd_kcontrol_new alc5632_spkoutn_mux_controls
=
290 SOC_DAPM_ENUM("SpeakerOut N Mux", alc5632_spk_n_sour_enum
);
292 /* speaker amplifier */
293 static const char *alc5632_amp_names
[] = {"AB Amp", "D Amp"};
294 static const struct soc_enum alc5632_amp_enum
=
295 SOC_ENUM_SINGLE(ALC5632_OUTPUT_MIXER_CTRL
, 13, 2, alc5632_amp_names
);
296 static const struct snd_kcontrol_new alc5632_amp_mux_controls
=
297 SOC_DAPM_ENUM("AB-D Amp Mux", alc5632_amp_enum
);
300 static const struct snd_soc_dapm_widget alc5632_dapm_widgets
[] = {
302 SND_SOC_DAPM_MUX("AuxOut Mux", SND_SOC_NOPM
, 0, 0,
303 &alc5632_auxout_mux_controls
),
304 SND_SOC_DAPM_MUX("SpeakerOut Mux", SND_SOC_NOPM
, 0, 0,
305 &alc5632_spkout_mux_controls
),
306 SND_SOC_DAPM_MUX("Left Headphone Mux", SND_SOC_NOPM
, 0, 0,
307 &alc5632_hpl_out_mux_controls
),
308 SND_SOC_DAPM_MUX("Right Headphone Mux", SND_SOC_NOPM
, 0, 0,
309 &alc5632_hpr_out_mux_controls
),
310 SND_SOC_DAPM_MUX("SpeakerOut N Mux", SND_SOC_NOPM
, 0, 0,
311 &alc5632_spkoutn_mux_controls
),
314 SND_SOC_DAPM_MIXER("HP Mix", SND_SOC_NOPM
, 0, 0,
315 &alc5632_hp_mixer_controls
[0],
316 ARRAY_SIZE(alc5632_hp_mixer_controls
)),
317 SND_SOC_DAPM_MIXER("HPR Mix", ALC5632_PWR_MANAG_ADD2
, 4, 0,
318 &alc5632_hpr_mixer_controls
[0],
319 ARRAY_SIZE(alc5632_hpr_mixer_controls
)),
320 SND_SOC_DAPM_MIXER("HPL Mix", ALC5632_PWR_MANAG_ADD2
, 5, 0,
321 &alc5632_hpl_mixer_controls
[0],
322 ARRAY_SIZE(alc5632_hpl_mixer_controls
)),
323 SND_SOC_DAPM_MIXER("HPOut Mix", SND_SOC_NOPM
, 0, 0, NULL
, 0),
324 SND_SOC_DAPM_MIXER("Mono Mix", ALC5632_PWR_MANAG_ADD2
, 2, 0,
325 &alc5632_mono_mixer_controls
[0],
326 ARRAY_SIZE(alc5632_mono_mixer_controls
)),
327 SND_SOC_DAPM_MIXER("Speaker Mix", ALC5632_PWR_MANAG_ADD2
, 3, 0,
328 &alc5632_speaker_mixer_controls
[0],
329 ARRAY_SIZE(alc5632_speaker_mixer_controls
)),
332 SND_SOC_DAPM_MIXER("Left Capture Mix", ALC5632_PWR_MANAG_ADD2
, 1, 0,
333 &alc5632_captureL_mixer_controls
[0],
334 ARRAY_SIZE(alc5632_captureL_mixer_controls
)),
335 SND_SOC_DAPM_MIXER("Right Capture Mix", ALC5632_PWR_MANAG_ADD2
, 0, 0,
336 &alc5632_captureR_mixer_controls
[0],
337 ARRAY_SIZE(alc5632_captureR_mixer_controls
)),
339 SND_SOC_DAPM_DAC("Left DAC", "HiFi Playback",
340 ALC5632_PWR_MANAG_ADD2
, 9, 0),
341 SND_SOC_DAPM_DAC("Right DAC", "HiFi Playback",
342 ALC5632_PWR_MANAG_ADD2
, 8, 0),
343 SND_SOC_DAPM_MIXER("DAC Left Channel", ALC5632_PWR_MANAG_ADD1
, 15, 0, NULL
, 0),
344 SND_SOC_DAPM_MIXER("DAC Right Channel",
345 ALC5632_PWR_MANAG_ADD1
, 14, 0, NULL
, 0),
346 SND_SOC_DAPM_MIXER("I2S Mix", ALC5632_PWR_MANAG_ADD1
, 11, 0, NULL
, 0),
347 SND_SOC_DAPM_MIXER("Phone Mix", SND_SOC_NOPM
, 0, 0, NULL
, 0),
348 SND_SOC_DAPM_MIXER("Line Mix", SND_SOC_NOPM
, 0, 0, NULL
, 0),
349 SND_SOC_DAPM_ADC("Left ADC", "HiFi Capture",
350 ALC5632_PWR_MANAG_ADD2
, 7, 0),
351 SND_SOC_DAPM_ADC("Right ADC", "HiFi Capture",
352 ALC5632_PWR_MANAG_ADD2
, 6, 0),
353 SND_SOC_DAPM_PGA("Left Headphone", ALC5632_PWR_MANAG_ADD3
, 11, 0, NULL
, 0),
354 SND_SOC_DAPM_PGA("Right Headphone", ALC5632_PWR_MANAG_ADD3
, 10, 0, NULL
, 0),
355 SND_SOC_DAPM_PGA("Left Speaker", ALC5632_PWR_MANAG_ADD3
, 13, 0, NULL
, 0),
356 SND_SOC_DAPM_PGA("Right Speaker", ALC5632_PWR_MANAG_ADD3
, 12, 0, NULL
, 0),
357 SND_SOC_DAPM_PGA("Aux Out", ALC5632_PWR_MANAG_ADD3
, 14, 0, NULL
, 0),
358 SND_SOC_DAPM_PGA("Left LineIn", ALC5632_PWR_MANAG_ADD3
, 7, 0, NULL
, 0),
359 SND_SOC_DAPM_PGA("Right LineIn", ALC5632_PWR_MANAG_ADD3
, 6, 0, NULL
, 0),
360 SND_SOC_DAPM_PGA("Phone", ALC5632_PWR_MANAG_ADD3
, 5, 0, NULL
, 0),
361 SND_SOC_DAPM_PGA("Phone ADMix", ALC5632_PWR_MANAG_ADD3
, 4, 0, NULL
, 0),
362 SND_SOC_DAPM_PGA("MIC1 PGA", ALC5632_PWR_MANAG_ADD3
, 3, 0, NULL
, 0),
363 SND_SOC_DAPM_PGA("MIC2 PGA", ALC5632_PWR_MANAG_ADD3
, 2, 0, NULL
, 0),
364 SND_SOC_DAPM_PGA("MIC1 Pre Amp", ALC5632_PWR_MANAG_ADD3
, 1, 0, NULL
, 0),
365 SND_SOC_DAPM_PGA("MIC2 Pre Amp", ALC5632_PWR_MANAG_ADD3
, 0, 0, NULL
, 0),
366 SND_SOC_DAPM_SUPPLY("Mic Bias1", ALC5632_PWR_MANAG_ADD1
, 3, 0, NULL
, 0),
367 SND_SOC_DAPM_SUPPLY("Mic Bias2", ALC5632_PWR_MANAG_ADD1
, 2, 0, NULL
, 0),
369 SND_SOC_DAPM_PGA_E("D Amp", ALC5632_PWR_MANAG_ADD2
, 14, 0, NULL
, 0,
370 amp_mixer_event
, SND_SOC_DAPM_PRE_PMU
| SND_SOC_DAPM_POST_PMD
),
371 SND_SOC_DAPM_PGA("AB Amp", ALC5632_PWR_MANAG_ADD2
, 15, 0, NULL
, 0),
372 SND_SOC_DAPM_MUX("AB-D Amp Mux", ALC5632_PWR_MANAG_ADD1
, 10, 0,
373 &alc5632_amp_mux_controls
),
375 SND_SOC_DAPM_OUTPUT("AUXOUT"),
376 SND_SOC_DAPM_OUTPUT("HPL"),
377 SND_SOC_DAPM_OUTPUT("HPR"),
378 SND_SOC_DAPM_OUTPUT("SPKOUT"),
379 SND_SOC_DAPM_OUTPUT("SPKOUTN"),
380 SND_SOC_DAPM_INPUT("LINEINL"),
381 SND_SOC_DAPM_INPUT("LINEINR"),
382 SND_SOC_DAPM_INPUT("PHONEP"),
383 SND_SOC_DAPM_INPUT("PHONEN"),
384 SND_SOC_DAPM_INPUT("MIC1"),
385 SND_SOC_DAPM_INPUT("MIC2"),
386 SND_SOC_DAPM_VMID("Vmid"),
390 static const struct snd_soc_dapm_route alc5632_dapm_routes
[] = {
391 /* virtual mixer - mixes left & right channels */
392 {"I2S Mix", NULL
, "Left DAC"},
393 {"I2S Mix", NULL
, "Right DAC"},
394 {"Line Mix", NULL
, "Right LineIn"},
395 {"Line Mix", NULL
, "Left LineIn"},
396 {"Phone Mix", NULL
, "Phone"},
397 {"Phone Mix", NULL
, "Phone ADMix"},
398 {"AUXOUT", NULL
, "Aux Out"},
401 {"DAC Right Channel", NULL
, "I2S Mix"},
402 {"DAC Left Channel", NULL
, "I2S Mix"},
405 {"HPL Mix", "ADC2HP_L Playback Switch", "Left Capture Mix"},
406 {"HPL Mix", NULL
, "HP Mix"},
407 {"HPR Mix", "ADC2HP_R Playback Switch", "Right Capture Mix"},
408 {"HPR Mix", NULL
, "HP Mix"},
409 {"HP Mix", "LI2HP Playback Switch", "Line Mix"},
410 {"HP Mix", "PHONE2HP Playback Switch", "Phone Mix"},
411 {"HP Mix", "MIC12HP Playback Switch", "MIC1 PGA"},
412 {"HP Mix", "MIC22HP Playback Switch", "MIC2 PGA"},
414 {"HPR Mix", "DACR2HP Playback Switch", "DAC Right Channel"},
415 {"HPL Mix", "DACL2HP Playback Switch", "DAC Left Channel"},
418 {"Speaker Mix", "LI2SPK Playback Switch", "Line Mix"},
419 {"Speaker Mix", "PHONE2SPK Playback Switch", "Phone Mix"},
420 {"Speaker Mix", "MIC12SPK Playback Switch", "MIC1 PGA"},
421 {"Speaker Mix", "MIC22SPK Playback Switch", "MIC2 PGA"},
422 {"Speaker Mix", "DAC2SPK Playback Switch", "DAC Left Channel"},
427 {"Mono Mix", "ADC2MONO_L Playback Switch", "Left Capture Mix"},
428 {"Mono Mix", "ADC2MONO_R Playback Switch", "Right Capture Mix"},
429 {"Mono Mix", "LI2MONO Playback Switch", "Line Mix"},
430 {"Mono Mix", "VOICE2MONO Playback Switch", "Phone Mix"},
431 {"Mono Mix", "MIC12MONO Playback Switch", "MIC1 PGA"},
432 {"Mono Mix", "MIC22MONO Playback Switch", "MIC2 PGA"},
433 {"Mono Mix", "DAC2MONO Playback Switch", "DAC Left Channel"},
435 /* Left record mixer */
436 {"Left Capture Mix", "LineInL Capture Switch", "LINEINL"},
437 {"Left Capture Mix", "Left Phone Capture Switch", "PHONEN"},
438 {"Left Capture Mix", "Mic1 Capture Switch", "MIC1 Pre Amp"},
439 {"Left Capture Mix", "Mic2 Capture Switch", "MIC2 Pre Amp"},
440 {"Left Capture Mix", "HPMixerL Capture Switch", "HPL Mix"},
441 {"Left Capture Mix", "SPKMixer Capture Switch", "Speaker Mix"},
442 {"Left Capture Mix", "MonoMixer Capture Switch", "Mono Mix"},
444 /*Right record mixer */
445 {"Right Capture Mix", "LineInR Capture Switch", "LINEINR"},
446 {"Right Capture Mix", "Right Phone Capture Switch", "PHONEP"},
447 {"Right Capture Mix", "Mic1 Capture Switch", "MIC1 Pre Amp"},
448 {"Right Capture Mix", "Mic2 Capture Switch", "MIC2 Pre Amp"},
449 {"Right Capture Mix", "HPMixerR Capture Switch", "HPR Mix"},
450 {"Right Capture Mix", "SPKMixer Capture Switch", "Speaker Mix"},
451 {"Right Capture Mix", "MonoMixer Capture Switch", "Mono Mix"},
453 /* headphone left mux */
454 {"Left Headphone Mux", "HP Left Mix", "HPL Mix"},
455 {"Left Headphone Mux", "Vmid", "Vmid"},
457 /* headphone right mux */
458 {"Right Headphone Mux", "HP Right Mix", "HPR Mix"},
459 {"Right Headphone Mux", "Vmid", "Vmid"},
461 /* speaker out mux */
462 {"SpeakerOut Mux", "Vmid", "Vmid"},
463 {"SpeakerOut Mux", "HPOut Mix", "HPOut Mix"},
464 {"SpeakerOut Mux", "Speaker Mix", "Speaker Mix"},
465 {"SpeakerOut Mux", "Mono Mix", "Mono Mix"},
467 /* Mono/Aux Out mux */
468 {"AuxOut Mux", "Vmid", "Vmid"},
469 {"AuxOut Mux", "HPOut Mix", "HPOut Mix"},
470 {"AuxOut Mux", "Speaker Mix", "Speaker Mix"},
471 {"AuxOut Mux", "Mono Mix", "Mono Mix"},
474 {"HPL", NULL
, "Left Headphone"},
475 {"Left Headphone", NULL
, "Left Headphone Mux"},
476 {"HPR", NULL
, "Right Headphone"},
477 {"Right Headphone", NULL
, "Right Headphone Mux"},
478 {"Aux Out", NULL
, "AuxOut Mux"},
481 {"Left LineIn", NULL
, "LINEINL"},
482 {"Right LineIn", NULL
, "LINEINR"},
483 {"Phone", NULL
, "PHONEP"},
484 {"MIC1 Pre Amp", NULL
, "MIC1"},
485 {"MIC2 Pre Amp", NULL
, "MIC2"},
486 {"MIC1 PGA", NULL
, "MIC1 Pre Amp"},
487 {"MIC2 PGA", NULL
, "MIC2 Pre Amp"},
490 {"Left ADC", NULL
, "Left Capture Mix"},
493 {"Right ADC", NULL
, "Right Capture Mix"},
495 {"SpeakerOut N Mux", "RN/-R", "Left Speaker"},
496 {"SpeakerOut N Mux", "RP/+R", "Left Speaker"},
497 {"SpeakerOut N Mux", "LN/-R", "Left Speaker"},
498 {"SpeakerOut N Mux", "Mute", "Vmid"},
500 {"SpeakerOut N Mux", "RN/-R", "Right Speaker"},
501 {"SpeakerOut N Mux", "RP/+R", "Right Speaker"},
502 {"SpeakerOut N Mux", "LN/-R", "Right Speaker"},
503 {"SpeakerOut N Mux", "Mute", "Vmid"},
505 {"AB Amp", NULL
, "SpeakerOut Mux"},
506 {"D Amp", NULL
, "SpeakerOut Mux"},
507 {"AB-D Amp Mux", "AB Amp", "AB Amp"},
508 {"AB-D Amp Mux", "D Amp", "D Amp"},
509 {"Left Speaker", NULL
, "AB-D Amp Mux"},
510 {"Right Speaker", NULL
, "AB-D Amp Mux"},
512 {"SPKOUT", NULL
, "Left Speaker"},
513 {"SPKOUT", NULL
, "Right Speaker"},
515 {"SPKOUTN", NULL
, "SpeakerOut N Mux"},
526 /* Note : pll code from original alc5632 driver. Not sure of how good it is */
527 /* usefull only for master mode */
528 static const struct _pll_div codec_master_pll_div
[] = {
530 { 2048000, 8192000, 0x0ea0},
531 { 3686400, 8192000, 0x4e27},
532 { 12000000, 8192000, 0x456b},
533 { 13000000, 8192000, 0x495f},
534 { 13100000, 8192000, 0x0320},
535 { 2048000, 11289600, 0xf637},
536 { 3686400, 11289600, 0x2f22},
537 { 12000000, 11289600, 0x3e2f},
538 { 13000000, 11289600, 0x4d5b},
539 { 13100000, 11289600, 0x363b},
540 { 2048000, 16384000, 0x1ea0},
541 { 3686400, 16384000, 0x9e27},
542 { 12000000, 16384000, 0x452b},
543 { 13000000, 16384000, 0x542f},
544 { 13100000, 16384000, 0x03a0},
545 { 2048000, 16934400, 0xe625},
546 { 3686400, 16934400, 0x9126},
547 { 12000000, 16934400, 0x4d2c},
548 { 13000000, 16934400, 0x742f},
549 { 13100000, 16934400, 0x3c27},
550 { 2048000, 22579200, 0x2aa0},
551 { 3686400, 22579200, 0x2f20},
552 { 12000000, 22579200, 0x7e2f},
553 { 13000000, 22579200, 0x742f},
554 { 13100000, 22579200, 0x3c27},
555 { 2048000, 24576000, 0x2ea0},
556 { 3686400, 24576000, 0xee27},
557 { 12000000, 24576000, 0x2915},
558 { 13000000, 24576000, 0x772e},
559 { 13100000, 24576000, 0x0d20},
562 /* FOUT = MCLK*(N+2)/((M+2)*(K+2))
563 N: bit 15:8 (div 2 .. div 257)
565 M: bit 3:0 (div 2 .. div 17)
567 same as for 5623 - thanks!
570 static const struct _pll_div codec_slave_pll_div
[] = {
572 { 1024000, 16384000, 0x3ea0},
573 { 1411200, 22579200, 0x3ea0},
574 { 1536000, 24576000, 0x3ea0},
575 { 2048000, 16384000, 0x1ea0},
576 { 2822400, 22579200, 0x1ea0},
577 { 3072000, 24576000, 0x1ea0},
581 static int alc5632_set_dai_pll(struct snd_soc_dai
*codec_dai
, int pll_id
,
582 int source
, unsigned int freq_in
, unsigned int freq_out
)
585 struct snd_soc_codec
*codec
= codec_dai
->codec
;
586 int gbl_clk
= 0, pll_div
= 0;
589 if (pll_id
< ALC5632_PLL_FR_MCLK
|| pll_id
> ALC5632_PLL_FR_VBCLK
)
592 /* Disable PLL power */
593 snd_soc_update_bits(codec
, ALC5632_PWR_MANAG_ADD2
,
594 ALC5632_PWR_ADD2_PLL1
,
596 snd_soc_update_bits(codec
, ALC5632_PWR_MANAG_ADD2
,
597 ALC5632_PWR_ADD2_PLL2
,
600 /* pll is not used in slave mode */
601 reg
= snd_soc_read(codec
, ALC5632_DAI_CONTROL
);
602 if (reg
& ALC5632_DAI_SDP_SLAVE_MODE
)
605 if (!freq_in
|| !freq_out
)
609 case ALC5632_PLL_FR_MCLK
:
610 for (i
= 0; i
< ARRAY_SIZE(codec_master_pll_div
); i
++) {
611 if (codec_master_pll_div
[i
].pll_in
== freq_in
612 && codec_master_pll_div
[i
].pll_out
== freq_out
) {
613 /* PLL source from MCLK */
614 pll_div
= codec_master_pll_div
[i
].regvalue
;
619 case ALC5632_PLL_FR_BCLK
:
620 for (i
= 0; i
< ARRAY_SIZE(codec_slave_pll_div
); i
++) {
621 if (codec_slave_pll_div
[i
].pll_in
== freq_in
622 && codec_slave_pll_div
[i
].pll_out
== freq_out
) {
623 /* PLL source from Bitclk */
624 gbl_clk
= ALC5632_PLL_FR_BCLK
;
625 pll_div
= codec_slave_pll_div
[i
].regvalue
;
630 case ALC5632_PLL_FR_VBCLK
:
631 for (i
= 0; i
< ARRAY_SIZE(codec_slave_pll_div
); i
++) {
632 if (codec_slave_pll_div
[i
].pll_in
== freq_in
633 && codec_slave_pll_div
[i
].pll_out
== freq_out
) {
634 /* PLL source from voice clock */
635 gbl_clk
= ALC5632_PLL_FR_VBCLK
;
636 pll_div
= codec_slave_pll_div
[i
].regvalue
;
648 /* choose MCLK/BCLK/VBCLK */
649 snd_soc_write(codec
, ALC5632_GPCR2
, gbl_clk
);
650 /* choose PLL1 clock rate */
651 snd_soc_write(codec
, ALC5632_PLL1_CTRL
, pll_div
);
653 snd_soc_update_bits(codec
, ALC5632_PWR_MANAG_ADD2
,
654 ALC5632_PWR_ADD2_PLL1
,
655 ALC5632_PWR_ADD2_PLL1
);
657 snd_soc_update_bits(codec
, ALC5632_PWR_MANAG_ADD2
,
658 ALC5632_PWR_ADD2_PLL2
,
659 ALC5632_PWR_ADD2_PLL2
);
660 /* use PLL1 as main SYSCLK */
661 snd_soc_update_bits(codec
, ALC5632_GPCR1
,
662 ALC5632_GPCR1_CLK_SYS_SRC_SEL_PLL1
,
663 ALC5632_GPCR1_CLK_SYS_SRC_SEL_PLL1
);
673 /* codec hifi mclk (after PLL) clock divider coefficients */
674 /* values inspired from column BCLK=32Fs of Appendix A table */
675 static const struct _coeff_div coeff_div
[] = {
679 static int get_coeff(struct snd_soc_codec
*codec
, int rate
)
681 struct alc5632_priv
*alc5632
= snd_soc_codec_get_drvdata(codec
);
684 for (i
= 0; i
< ARRAY_SIZE(coeff_div
); i
++) {
685 if (coeff_div
[i
].fs
* rate
== alc5632
->sysclk
)
692 * Clock after PLL and dividers
694 static int alc5632_set_dai_sysclk(struct snd_soc_dai
*codec_dai
,
695 int clk_id
, unsigned int freq
, int dir
)
697 struct snd_soc_codec
*codec
= codec_dai
->codec
;
698 struct alc5632_priv
*alc5632
= snd_soc_codec_get_drvdata(codec
);
709 alc5632
->sysclk
= freq
;
715 static int alc5632_set_dai_fmt(struct snd_soc_dai
*codec_dai
,
718 struct snd_soc_codec
*codec
= codec_dai
->codec
;
721 /* set master/slave audio interface */
722 switch (fmt
& SND_SOC_DAIFMT_MASTER_MASK
) {
723 case SND_SOC_DAIFMT_CBM_CFM
:
724 iface
= ALC5632_DAI_SDP_MASTER_MODE
;
726 case SND_SOC_DAIFMT_CBS_CFS
:
727 iface
= ALC5632_DAI_SDP_SLAVE_MODE
;
733 /* interface format */
734 switch (fmt
& SND_SOC_DAIFMT_FORMAT_MASK
) {
735 case SND_SOC_DAIFMT_I2S
:
736 iface
|= ALC5632_DAI_I2S_DF_I2S
;
738 case SND_SOC_DAIFMT_LEFT_J
:
739 iface
|= ALC5632_DAI_I2S_DF_LEFT
;
741 case SND_SOC_DAIFMT_DSP_A
:
742 iface
|= ALC5632_DAI_I2S_DF_PCM_A
;
744 case SND_SOC_DAIFMT_DSP_B
:
745 iface
|= ALC5632_DAI_I2S_DF_PCM_B
;
751 /* clock inversion */
752 switch (fmt
& SND_SOC_DAIFMT_INV_MASK
) {
753 case SND_SOC_DAIFMT_NB_NF
:
755 case SND_SOC_DAIFMT_IB_IF
:
756 iface
|= ALC5632_DAI_MAIN_I2S_BCLK_POL_CTRL
;
758 case SND_SOC_DAIFMT_IB_NF
:
759 iface
|= ALC5632_DAI_MAIN_I2S_BCLK_POL_CTRL
;
761 case SND_SOC_DAIFMT_NB_IF
:
767 return snd_soc_write(codec
, ALC5632_DAI_CONTROL
, iface
);
770 static int alc5632_pcm_hw_params(struct snd_pcm_substream
*substream
,
771 struct snd_pcm_hw_params
*params
, struct snd_soc_dai
*dai
)
773 struct snd_soc_pcm_runtime
*rtd
= substream
->private_data
;
774 struct snd_soc_codec
*codec
= rtd
->codec
;
778 iface
= snd_soc_read(codec
, ALC5632_DAI_CONTROL
);
779 iface
&= ~ALC5632_DAI_I2S_DL_MASK
;
782 switch (params_format(params
)) {
783 case SNDRV_PCM_FORMAT_S16_LE
:
784 iface
|= ALC5632_DAI_I2S_DL_16
;
786 case SNDRV_PCM_FORMAT_S20_3LE
:
787 iface
|= ALC5632_DAI_I2S_DL_20
;
789 case SNDRV_PCM_FORMAT_S24_LE
:
790 iface
|= ALC5632_DAI_I2S_DL_24
;
796 /* set iface & srate */
797 snd_soc_write(codec
, ALC5632_DAI_CONTROL
, iface
);
798 rate
= params_rate(params
);
799 coeff
= get_coeff(codec
, rate
);
803 coeff
= coeff_div
[coeff
].regvalue
;
804 snd_soc_write(codec
, ALC5632_DAC_CLK_CTRL1
, coeff
);
809 static int alc5632_mute(struct snd_soc_dai
*dai
, int mute
)
811 struct snd_soc_codec
*codec
= dai
->codec
;
812 u16 hp_mute
= ALC5632_MISC_HP_DEPOP_MUTE_L
813 |ALC5632_MISC_HP_DEPOP_MUTE_R
;
814 u16 mute_reg
= snd_soc_read(codec
, ALC5632_MISC_CTRL
) & ~hp_mute
;
819 return snd_soc_write(codec
, ALC5632_MISC_CTRL
, mute_reg
);
822 #define ALC5632_ADD2_POWER_EN (ALC5632_PWR_ADD2_VREF)
824 #define ALC5632_ADD3_POWER_EN (ALC5632_PWR_ADD3_MIC1_BOOST_AD)
826 #define ALC5632_ADD1_POWER_EN \
827 (ALC5632_PWR_ADD1_DAC_REF \
828 | ALC5632_PWR_ADD1_SOFTGEN_EN \
829 | ALC5632_PWR_ADD1_HP_OUT_AMP \
830 | ALC5632_PWR_ADD1_HP_OUT_ENH_AMP \
831 | ALC5632_PWR_ADD1_MAIN_BIAS)
833 static void enable_power_depop(struct snd_soc_codec
*codec
)
835 snd_soc_update_bits(codec
, ALC5632_PWR_MANAG_ADD1
,
836 ALC5632_PWR_ADD1_SOFTGEN_EN
,
837 ALC5632_PWR_ADD1_SOFTGEN_EN
);
839 snd_soc_update_bits(codec
, ALC5632_PWR_MANAG_ADD3
,
840 ALC5632_ADD3_POWER_EN
,
841 ALC5632_ADD3_POWER_EN
);
843 snd_soc_update_bits(codec
, ALC5632_MISC_CTRL
,
844 ALC5632_MISC_HP_DEPOP_MODE2_EN
,
845 ALC5632_MISC_HP_DEPOP_MODE2_EN
);
847 /* "normal" mode: 0 @ 26 */
848 /* set all PR0-7 mixers to 0 */
849 snd_soc_update_bits(codec
, ALC5632_PWR_DOWN_CTRL_STATUS
,
850 ALC5632_PWR_DOWN_CTRL_STATUS_MASK
,
855 snd_soc_update_bits(codec
, ALC5632_PWR_MANAG_ADD2
,
856 ALC5632_ADD2_POWER_EN
,
857 ALC5632_ADD2_POWER_EN
);
859 snd_soc_update_bits(codec
, ALC5632_PWR_MANAG_ADD1
,
860 ALC5632_ADD1_POWER_EN
,
861 ALC5632_ADD1_POWER_EN
);
863 /* disable HP Depop2 */
864 snd_soc_update_bits(codec
, ALC5632_MISC_CTRL
,
865 ALC5632_MISC_HP_DEPOP_MODE2_EN
,
870 static int alc5632_set_bias_level(struct snd_soc_codec
*codec
,
871 enum snd_soc_bias_level level
)
874 case SND_SOC_BIAS_ON
:
875 enable_power_depop(codec
);
877 case SND_SOC_BIAS_PREPARE
:
879 case SND_SOC_BIAS_STANDBY
:
880 /* everything off except vref/vmid, */
881 snd_soc_update_bits(codec
, ALC5632_PWR_MANAG_ADD1
,
882 ALC5632_PWR_MANAG_ADD1_MASK
,
883 ALC5632_PWR_ADD1_MAIN_BIAS
);
884 snd_soc_update_bits(codec
, ALC5632_PWR_MANAG_ADD2
,
885 ALC5632_PWR_MANAG_ADD2_MASK
,
886 ALC5632_PWR_ADD2_VREF
);
887 /* "normal" mode: 0 @ 26 */
888 snd_soc_update_bits(codec
, ALC5632_PWR_DOWN_CTRL_STATUS
,
889 ALC5632_PWR_DOWN_CTRL_STATUS_MASK
,
890 0xffff ^ (ALC5632_PWR_VREF_PR3
891 | ALC5632_PWR_VREF_PR2
));
893 case SND_SOC_BIAS_OFF
:
894 /* everything off, dac mute, inactive */
895 snd_soc_update_bits(codec
, ALC5632_PWR_MANAG_ADD2
,
896 ALC5632_PWR_MANAG_ADD2_MASK
, 0);
897 snd_soc_update_bits(codec
, ALC5632_PWR_MANAG_ADD3
,
898 ALC5632_PWR_MANAG_ADD3_MASK
, 0);
899 snd_soc_update_bits(codec
, ALC5632_PWR_MANAG_ADD1
,
900 ALC5632_PWR_MANAG_ADD1_MASK
, 0);
903 codec
->dapm
.bias_level
= level
;
907 #define ALC5632_FORMATS (SNDRV_PCM_FMTBIT_S16_LE \
908 | SNDRV_PCM_FMTBIT_S24_LE \
909 | SNDRV_PCM_FMTBIT_S32_LE)
911 static struct snd_soc_dai_ops alc5632_dai_ops
= {
912 .hw_params
= alc5632_pcm_hw_params
,
913 .digital_mute
= alc5632_mute
,
914 .set_fmt
= alc5632_set_dai_fmt
,
915 .set_sysclk
= alc5632_set_dai_sysclk
,
916 .set_pll
= alc5632_set_dai_pll
,
919 static struct snd_soc_dai_driver alc5632_dai
= {
920 .name
= "alc5632-hifi",
922 .stream_name
= "HiFi Playback",
927 .rates
= SNDRV_PCM_RATE_8000_48000
,
928 .formats
= ALC5632_FORMATS
,},
930 .stream_name
= "HiFi Capture",
935 .rates
= SNDRV_PCM_RATE_8000_48000
,
936 .formats
= ALC5632_FORMATS
,},
938 .ops
= &alc5632_dai_ops
,
939 .symmetric_rates
= 1,
942 static int alc5632_suspend(struct snd_soc_codec
*codec
, pm_message_t mesg
)
944 alc5632_set_bias_level(codec
, SND_SOC_BIAS_OFF
);
948 static int alc5632_resume(struct snd_soc_codec
*codec
)
952 /* mark cache as needed to sync */
953 codec
->cache_sync
= 1;
955 ret
= snd_soc_cache_sync(codec
);
957 dev_err(codec
->dev
, "Failed to sync cache: %d\n", ret
);
961 alc5632_set_bias_level(codec
, SND_SOC_BIAS_STANDBY
);
965 static int alc5632_probe(struct snd_soc_codec
*codec
)
967 struct alc5632_priv
*alc5632
= snd_soc_codec_get_drvdata(codec
);
970 ret
= snd_soc_codec_set_cache_io(codec
, 8, 16, alc5632
->control_type
);
972 dev_err(codec
->dev
, "Failed to set cache I/O: %d\n", ret
);
976 alc5632_reset(codec
);
978 /* power on device */
979 alc5632_set_bias_level(codec
, SND_SOC_BIAS_STANDBY
);
981 switch (alc5632
->id
) {
983 snd_soc_add_controls(codec
, alc5632_vol_snd_controls
,
984 ARRAY_SIZE(alc5632_vol_snd_controls
));
993 /* power down chip */
994 static int alc5632_remove(struct snd_soc_codec
*codec
)
996 alc5632_set_bias_level(codec
, SND_SOC_BIAS_OFF
);
1000 static struct snd_soc_codec_driver soc_codec_device_alc5632
= {
1001 .probe
= alc5632_probe
,
1002 .remove
= alc5632_remove
,
1003 .suspend
= alc5632_suspend
,
1004 .resume
= alc5632_resume
,
1005 .set_bias_level
= alc5632_set_bias_level
,
1006 .reg_word_size
= sizeof(u16
),
1007 .reg_cache_step
= 2,
1008 .reg_cache_default
= alc5632_reg_defaults
,
1009 .reg_cache_size
= ARRAY_SIZE(alc5632_reg_defaults
),
1010 .volatile_register
= alc5632_volatile_register
,
1011 .controls
= alc5632_snd_controls
,
1012 .num_controls
= ARRAY_SIZE(alc5632_snd_controls
),
1013 .dapm_widgets
= alc5632_dapm_widgets
,
1014 .num_dapm_widgets
= ARRAY_SIZE(alc5632_dapm_widgets
),
1015 .dapm_routes
= alc5632_dapm_routes
,
1016 .num_dapm_routes
= ARRAY_SIZE(alc5632_dapm_routes
),
1020 * alc5632 2 wire address is determined by A1 pin
1021 * state during powerup.
1025 static int alc5632_i2c_probe(struct i2c_client
*client
,
1026 const struct i2c_device_id
*id
)
1028 struct alc5632_priv
*alc5632
;
1029 int ret
, vid1
, vid2
;
1031 vid1
= i2c_smbus_read_word_data(client
, ALC5632_VENDOR_ID1
);
1033 dev_err(&client
->dev
, "failed to read I2C\n");
1036 dev_info(&client
->dev
, "got vid1: %x\n", vid1
);
1038 vid1
= ((vid1
& 0xff) << 8) | (vid1
>> 8);
1040 vid2
= i2c_smbus_read_word_data(client
, ALC5632_VENDOR_ID2
);
1042 dev_err(&client
->dev
, "failed to read I2C\n");
1045 dev_info(&client
->dev
, "got vid2: %x\n", vid2
);
1047 vid2
= (vid2
& 0xff);
1049 if ((vid1
!= 0x10ec) || (vid2
!= id
->driver_data
)) {
1050 dev_err(&client
->dev
, "unknown or wrong codec\n");
1051 dev_err(&client
->dev
, "Expected %x:%lx, got %x:%x\n",
1052 0x10ec, id
->driver_data
,
1057 alc5632
= devm_kzalloc(&client
->dev
,
1058 sizeof(struct alc5632_priv
), GFP_KERNEL
);
1059 if (alc5632
== NULL
)
1063 switch (alc5632
->id
) {
1065 alc5632_dai
.name
= "alc5632-hifi";
1071 i2c_set_clientdata(client
, alc5632
);
1072 alc5632
->control_type
= SND_SOC_I2C
;
1074 ret
= snd_soc_register_codec(&client
->dev
,
1075 &soc_codec_device_alc5632
, &alc5632_dai
, 1);
1077 dev_err(&client
->dev
, "Failed to register codec: %d\n", ret
);
1082 static int alc5632_i2c_remove(struct i2c_client
*client
)
1084 snd_soc_unregister_codec(&client
->dev
);
1089 static const struct i2c_device_id alc5632_i2c_table
[] = {
1093 MODULE_DEVICE_TABLE(i2c
, alc5632_i2c_table
);
1095 /* i2c codec control layer */
1096 static struct i2c_driver alc5632_i2c_driver
= {
1099 .owner
= THIS_MODULE
,
1101 .probe
= alc5632_i2c_probe
,
1102 .remove
= __devexit_p(alc5632_i2c_remove
),
1103 .id_table
= alc5632_i2c_table
,
1106 static int __init
alc5632_modinit(void)
1110 ret
= i2c_add_driver(&alc5632_i2c_driver
);
1112 printk(KERN_ERR
"%s: can't add i2c driver", __func__
);
1118 module_init(alc5632_modinit
);
1120 static void __exit
alc5632_modexit(void)
1122 i2c_del_driver(&alc5632_i2c_driver
);
1124 module_exit(alc5632_modexit
);
1126 MODULE_DESCRIPTION("ASoC ALC5632 driver");
1127 MODULE_AUTHOR("Leon Romanovsky <leon@leon.nu>");
1128 MODULE_LICENSE("GPL");