Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/sound/soc/codecs/alc5623.c
10817 views
1
/*
2
* alc5623.c -- alc562[123] ALSA Soc Audio driver
3
*
4
* Copyright 2008 Realtek Microelectronics
5
* Author: flove <[email protected]> Ethan <[email protected]>
6
*
7
* Copyright 2010 Arnaud Patard <[email protected]>
8
*
9
*
10
* Based on WM8753.c
11
*
12
* This program is free software; you can redistribute it and/or modify
13
* it under the terms of the GNU General Public License version 2 as
14
* published by the Free Software Foundation.
15
*
16
*/
17
18
#include <linux/module.h>
19
#include <linux/kernel.h>
20
#include <linux/init.h>
21
#include <linux/delay.h>
22
#include <linux/pm.h>
23
#include <linux/i2c.h>
24
#include <linux/slab.h>
25
#include <linux/platform_device.h>
26
#include <sound/core.h>
27
#include <sound/pcm.h>
28
#include <sound/pcm_params.h>
29
#include <sound/tlv.h>
30
#include <sound/soc.h>
31
#include <sound/initval.h>
32
#include <sound/alc5623.h>
33
34
#include "alc5623.h"
35
36
static int caps_charge = 2000;
37
module_param(caps_charge, int, 0);
38
MODULE_PARM_DESC(caps_charge, "ALC5623 cap charge time (msecs)");
39
40
/* codec private data */
41
struct alc5623_priv {
42
enum snd_soc_control_type control_type;
43
void *control_data;
44
struct mutex mutex;
45
u8 id;
46
unsigned int sysclk;
47
u16 reg_cache[ALC5623_VENDOR_ID2+2];
48
unsigned int add_ctrl;
49
unsigned int jack_det_ctrl;
50
};
51
52
static void alc5623_fill_cache(struct snd_soc_codec *codec)
53
{
54
int i, step = codec->driver->reg_cache_step;
55
u16 *cache = codec->reg_cache;
56
57
/* not really efficient ... */
58
for (i = 0 ; i < codec->driver->reg_cache_size ; i += step)
59
cache[i] = codec->hw_read(codec, i);
60
}
61
62
static inline int alc5623_reset(struct snd_soc_codec *codec)
63
{
64
return snd_soc_write(codec, ALC5623_RESET, 0);
65
}
66
67
static int amp_mixer_event(struct snd_soc_dapm_widget *w,
68
struct snd_kcontrol *kcontrol, int event)
69
{
70
/* to power-on/off class-d amp generators/speaker */
71
/* need to write to 'index-46h' register : */
72
/* so write index num (here 0x46) to reg 0x6a */
73
/* and then 0xffff/0 to reg 0x6c */
74
snd_soc_write(w->codec, ALC5623_HID_CTRL_INDEX, 0x46);
75
76
switch (event) {
77
case SND_SOC_DAPM_PRE_PMU:
78
snd_soc_write(w->codec, ALC5623_HID_CTRL_DATA, 0xFFFF);
79
break;
80
case SND_SOC_DAPM_POST_PMD:
81
snd_soc_write(w->codec, ALC5623_HID_CTRL_DATA, 0);
82
break;
83
}
84
85
return 0;
86
}
87
88
/*
89
* ALC5623 Controls
90
*/
91
92
static const DECLARE_TLV_DB_SCALE(vol_tlv, -3450, 150, 0);
93
static const DECLARE_TLV_DB_SCALE(hp_tlv, -4650, 150, 0);
94
static const DECLARE_TLV_DB_SCALE(adc_rec_tlv, -1650, 150, 0);
95
static const unsigned int boost_tlv[] = {
96
TLV_DB_RANGE_HEAD(3),
97
0, 0, TLV_DB_SCALE_ITEM(0, 0, 0),
98
1, 1, TLV_DB_SCALE_ITEM(2000, 0, 0),
99
2, 2, TLV_DB_SCALE_ITEM(3000, 0, 0),
100
};
101
static const DECLARE_TLV_DB_SCALE(dig_tlv, 0, 600, 0);
102
103
static const struct snd_kcontrol_new rt5621_vol_snd_controls[] = {
104
SOC_DOUBLE_TLV("Speaker Playback Volume",
105
ALC5623_SPK_OUT_VOL, 8, 0, 31, 1, hp_tlv),
106
SOC_DOUBLE("Speaker Playback Switch",
107
ALC5623_SPK_OUT_VOL, 15, 7, 1, 1),
108
SOC_DOUBLE_TLV("Headphone Playback Volume",
109
ALC5623_HP_OUT_VOL, 8, 0, 31, 1, hp_tlv),
110
SOC_DOUBLE("Headphone Playback Switch",
111
ALC5623_HP_OUT_VOL, 15, 7, 1, 1),
112
};
113
114
static const struct snd_kcontrol_new rt5622_vol_snd_controls[] = {
115
SOC_DOUBLE_TLV("Speaker Playback Volume",
116
ALC5623_SPK_OUT_VOL, 8, 0, 31, 1, hp_tlv),
117
SOC_DOUBLE("Speaker Playback Switch",
118
ALC5623_SPK_OUT_VOL, 15, 7, 1, 1),
119
SOC_DOUBLE_TLV("Line Playback Volume",
120
ALC5623_HP_OUT_VOL, 8, 0, 31, 1, hp_tlv),
121
SOC_DOUBLE("Line Playback Switch",
122
ALC5623_HP_OUT_VOL, 15, 7, 1, 1),
123
};
124
125
static const struct snd_kcontrol_new alc5623_vol_snd_controls[] = {
126
SOC_DOUBLE_TLV("Line Playback Volume",
127
ALC5623_SPK_OUT_VOL, 8, 0, 31, 1, hp_tlv),
128
SOC_DOUBLE("Line Playback Switch",
129
ALC5623_SPK_OUT_VOL, 15, 7, 1, 1),
130
SOC_DOUBLE_TLV("Headphone Playback Volume",
131
ALC5623_HP_OUT_VOL, 8, 0, 31, 1, hp_tlv),
132
SOC_DOUBLE("Headphone Playback Switch",
133
ALC5623_HP_OUT_VOL, 15, 7, 1, 1),
134
};
135
136
static const struct snd_kcontrol_new alc5623_snd_controls[] = {
137
SOC_DOUBLE_TLV("Auxout Playback Volume",
138
ALC5623_MONO_AUX_OUT_VOL, 8, 0, 31, 1, hp_tlv),
139
SOC_DOUBLE("Auxout Playback Switch",
140
ALC5623_MONO_AUX_OUT_VOL, 15, 7, 1, 1),
141
SOC_DOUBLE_TLV("PCM Playback Volume",
142
ALC5623_STEREO_DAC_VOL, 8, 0, 31, 1, vol_tlv),
143
SOC_DOUBLE_TLV("AuxI Capture Volume",
144
ALC5623_AUXIN_VOL, 8, 0, 31, 1, vol_tlv),
145
SOC_DOUBLE_TLV("LineIn Capture Volume",
146
ALC5623_LINE_IN_VOL, 8, 0, 31, 1, vol_tlv),
147
SOC_SINGLE_TLV("Mic1 Capture Volume",
148
ALC5623_MIC_VOL, 8, 31, 1, vol_tlv),
149
SOC_SINGLE_TLV("Mic2 Capture Volume",
150
ALC5623_MIC_VOL, 0, 31, 1, vol_tlv),
151
SOC_DOUBLE_TLV("Rec Capture Volume",
152
ALC5623_ADC_REC_GAIN, 7, 0, 31, 0, adc_rec_tlv),
153
SOC_SINGLE_TLV("Mic 1 Boost Volume",
154
ALC5623_MIC_CTRL, 10, 2, 0, boost_tlv),
155
SOC_SINGLE_TLV("Mic 2 Boost Volume",
156
ALC5623_MIC_CTRL, 8, 2, 0, boost_tlv),
157
SOC_SINGLE_TLV("Digital Boost Volume",
158
ALC5623_ADD_CTRL_REG, 4, 3, 0, dig_tlv),
159
};
160
161
/*
162
* DAPM Controls
163
*/
164
static const struct snd_kcontrol_new alc5623_hp_mixer_controls[] = {
165
SOC_DAPM_SINGLE("LI2HP Playback Switch", ALC5623_LINE_IN_VOL, 15, 1, 1),
166
SOC_DAPM_SINGLE("AUXI2HP Playback Switch", ALC5623_AUXIN_VOL, 15, 1, 1),
167
SOC_DAPM_SINGLE("MIC12HP Playback Switch", ALC5623_MIC_ROUTING_CTRL, 15, 1, 1),
168
SOC_DAPM_SINGLE("MIC22HP Playback Switch", ALC5623_MIC_ROUTING_CTRL, 7, 1, 1),
169
SOC_DAPM_SINGLE("DAC2HP Playback Switch", ALC5623_STEREO_DAC_VOL, 15, 1, 1),
170
};
171
172
static const struct snd_kcontrol_new alc5623_hpl_mixer_controls[] = {
173
SOC_DAPM_SINGLE("ADC2HP_L Playback Switch", ALC5623_ADC_REC_GAIN, 15, 1, 1),
174
};
175
176
static const struct snd_kcontrol_new alc5623_hpr_mixer_controls[] = {
177
SOC_DAPM_SINGLE("ADC2HP_R Playback Switch", ALC5623_ADC_REC_GAIN, 14, 1, 1),
178
};
179
180
static const struct snd_kcontrol_new alc5623_mono_mixer_controls[] = {
181
SOC_DAPM_SINGLE("ADC2MONO_L Playback Switch", ALC5623_ADC_REC_GAIN, 13, 1, 1),
182
SOC_DAPM_SINGLE("ADC2MONO_R Playback Switch", ALC5623_ADC_REC_GAIN, 12, 1, 1),
183
SOC_DAPM_SINGLE("LI2MONO Playback Switch", ALC5623_LINE_IN_VOL, 13, 1, 1),
184
SOC_DAPM_SINGLE("AUXI2MONO Playback Switch", ALC5623_AUXIN_VOL, 13, 1, 1),
185
SOC_DAPM_SINGLE("MIC12MONO Playback Switch", ALC5623_MIC_ROUTING_CTRL, 13, 1, 1),
186
SOC_DAPM_SINGLE("MIC22MONO Playback Switch", ALC5623_MIC_ROUTING_CTRL, 5, 1, 1),
187
SOC_DAPM_SINGLE("DAC2MONO Playback Switch", ALC5623_STEREO_DAC_VOL, 13, 1, 1),
188
};
189
190
static const struct snd_kcontrol_new alc5623_speaker_mixer_controls[] = {
191
SOC_DAPM_SINGLE("LI2SPK Playback Switch", ALC5623_LINE_IN_VOL, 14, 1, 1),
192
SOC_DAPM_SINGLE("AUXI2SPK Playback Switch", ALC5623_AUXIN_VOL, 14, 1, 1),
193
SOC_DAPM_SINGLE("MIC12SPK Playback Switch", ALC5623_MIC_ROUTING_CTRL, 14, 1, 1),
194
SOC_DAPM_SINGLE("MIC22SPK Playback Switch", ALC5623_MIC_ROUTING_CTRL, 6, 1, 1),
195
SOC_DAPM_SINGLE("DAC2SPK Playback Switch", ALC5623_STEREO_DAC_VOL, 14, 1, 1),
196
};
197
198
/* Left Record Mixer */
199
static const struct snd_kcontrol_new alc5623_captureL_mixer_controls[] = {
200
SOC_DAPM_SINGLE("Mic1 Capture Switch", ALC5623_ADC_REC_MIXER, 14, 1, 1),
201
SOC_DAPM_SINGLE("Mic2 Capture Switch", ALC5623_ADC_REC_MIXER, 13, 1, 1),
202
SOC_DAPM_SINGLE("LineInL Capture Switch", ALC5623_ADC_REC_MIXER, 12, 1, 1),
203
SOC_DAPM_SINGLE("Left AuxI Capture Switch", ALC5623_ADC_REC_MIXER, 11, 1, 1),
204
SOC_DAPM_SINGLE("HPMixerL Capture Switch", ALC5623_ADC_REC_MIXER, 10, 1, 1),
205
SOC_DAPM_SINGLE("SPKMixer Capture Switch", ALC5623_ADC_REC_MIXER, 9, 1, 1),
206
SOC_DAPM_SINGLE("MonoMixer Capture Switch", ALC5623_ADC_REC_MIXER, 8, 1, 1),
207
};
208
209
/* Right Record Mixer */
210
static const struct snd_kcontrol_new alc5623_captureR_mixer_controls[] = {
211
SOC_DAPM_SINGLE("Mic1 Capture Switch", ALC5623_ADC_REC_MIXER, 6, 1, 1),
212
SOC_DAPM_SINGLE("Mic2 Capture Switch", ALC5623_ADC_REC_MIXER, 5, 1, 1),
213
SOC_DAPM_SINGLE("LineInR Capture Switch", ALC5623_ADC_REC_MIXER, 4, 1, 1),
214
SOC_DAPM_SINGLE("Right AuxI Capture Switch", ALC5623_ADC_REC_MIXER, 3, 1, 1),
215
SOC_DAPM_SINGLE("HPMixerR Capture Switch", ALC5623_ADC_REC_MIXER, 2, 1, 1),
216
SOC_DAPM_SINGLE("SPKMixer Capture Switch", ALC5623_ADC_REC_MIXER, 1, 1, 1),
217
SOC_DAPM_SINGLE("MonoMixer Capture Switch", ALC5623_ADC_REC_MIXER, 0, 1, 1),
218
};
219
220
static const char *alc5623_spk_n_sour_sel[] = {
221
"RN/-R", "RP/+R", "LN/-R", "Vmid" };
222
static const char *alc5623_hpl_out_input_sel[] = {
223
"Vmid", "HP Left Mix"};
224
static const char *alc5623_hpr_out_input_sel[] = {
225
"Vmid", "HP Right Mix"};
226
static const char *alc5623_spkout_input_sel[] = {
227
"Vmid", "HPOut Mix", "Speaker Mix", "Mono Mix"};
228
static const char *alc5623_aux_out_input_sel[] = {
229
"Vmid", "HPOut Mix", "Speaker Mix", "Mono Mix"};
230
231
/* auxout output mux */
232
static const struct soc_enum alc5623_aux_out_input_enum =
233
SOC_ENUM_SINGLE(ALC5623_OUTPUT_MIXER_CTRL, 6, 4, alc5623_aux_out_input_sel);
234
static const struct snd_kcontrol_new alc5623_auxout_mux_controls =
235
SOC_DAPM_ENUM("Route", alc5623_aux_out_input_enum);
236
237
/* speaker output mux */
238
static const struct soc_enum alc5623_spkout_input_enum =
239
SOC_ENUM_SINGLE(ALC5623_OUTPUT_MIXER_CTRL, 10, 4, alc5623_spkout_input_sel);
240
static const struct snd_kcontrol_new alc5623_spkout_mux_controls =
241
SOC_DAPM_ENUM("Route", alc5623_spkout_input_enum);
242
243
/* headphone left output mux */
244
static const struct soc_enum alc5623_hpl_out_input_enum =
245
SOC_ENUM_SINGLE(ALC5623_OUTPUT_MIXER_CTRL, 9, 2, alc5623_hpl_out_input_sel);
246
static const struct snd_kcontrol_new alc5623_hpl_out_mux_controls =
247
SOC_DAPM_ENUM("Route", alc5623_hpl_out_input_enum);
248
249
/* headphone right output mux */
250
static const struct soc_enum alc5623_hpr_out_input_enum =
251
SOC_ENUM_SINGLE(ALC5623_OUTPUT_MIXER_CTRL, 8, 2, alc5623_hpr_out_input_sel);
252
static const struct snd_kcontrol_new alc5623_hpr_out_mux_controls =
253
SOC_DAPM_ENUM("Route", alc5623_hpr_out_input_enum);
254
255
/* speaker output N select */
256
static const struct soc_enum alc5623_spk_n_sour_enum =
257
SOC_ENUM_SINGLE(ALC5623_OUTPUT_MIXER_CTRL, 14, 4, alc5623_spk_n_sour_sel);
258
static const struct snd_kcontrol_new alc5623_spkoutn_mux_controls =
259
SOC_DAPM_ENUM("Route", alc5623_spk_n_sour_enum);
260
261
static const struct snd_soc_dapm_widget alc5623_dapm_widgets[] = {
262
/* Muxes */
263
SND_SOC_DAPM_MUX("AuxOut Mux", SND_SOC_NOPM, 0, 0,
264
&alc5623_auxout_mux_controls),
265
SND_SOC_DAPM_MUX("SpeakerOut Mux", SND_SOC_NOPM, 0, 0,
266
&alc5623_spkout_mux_controls),
267
SND_SOC_DAPM_MUX("Left Headphone Mux", SND_SOC_NOPM, 0, 0,
268
&alc5623_hpl_out_mux_controls),
269
SND_SOC_DAPM_MUX("Right Headphone Mux", SND_SOC_NOPM, 0, 0,
270
&alc5623_hpr_out_mux_controls),
271
SND_SOC_DAPM_MUX("SpeakerOut N Mux", SND_SOC_NOPM, 0, 0,
272
&alc5623_spkoutn_mux_controls),
273
274
/* output mixers */
275
SND_SOC_DAPM_MIXER("HP Mix", SND_SOC_NOPM, 0, 0,
276
&alc5623_hp_mixer_controls[0],
277
ARRAY_SIZE(alc5623_hp_mixer_controls)),
278
SND_SOC_DAPM_MIXER("HPR Mix", ALC5623_PWR_MANAG_ADD2, 4, 0,
279
&alc5623_hpr_mixer_controls[0],
280
ARRAY_SIZE(alc5623_hpr_mixer_controls)),
281
SND_SOC_DAPM_MIXER("HPL Mix", ALC5623_PWR_MANAG_ADD2, 5, 0,
282
&alc5623_hpl_mixer_controls[0],
283
ARRAY_SIZE(alc5623_hpl_mixer_controls)),
284
SND_SOC_DAPM_MIXER("HPOut Mix", SND_SOC_NOPM, 0, 0, NULL, 0),
285
SND_SOC_DAPM_MIXER("Mono Mix", ALC5623_PWR_MANAG_ADD2, 2, 0,
286
&alc5623_mono_mixer_controls[0],
287
ARRAY_SIZE(alc5623_mono_mixer_controls)),
288
SND_SOC_DAPM_MIXER("Speaker Mix", ALC5623_PWR_MANAG_ADD2, 3, 0,
289
&alc5623_speaker_mixer_controls[0],
290
ARRAY_SIZE(alc5623_speaker_mixer_controls)),
291
292
/* input mixers */
293
SND_SOC_DAPM_MIXER("Left Capture Mix", ALC5623_PWR_MANAG_ADD2, 1, 0,
294
&alc5623_captureL_mixer_controls[0],
295
ARRAY_SIZE(alc5623_captureL_mixer_controls)),
296
SND_SOC_DAPM_MIXER("Right Capture Mix", ALC5623_PWR_MANAG_ADD2, 0, 0,
297
&alc5623_captureR_mixer_controls[0],
298
ARRAY_SIZE(alc5623_captureR_mixer_controls)),
299
300
SND_SOC_DAPM_DAC("Left DAC", "Left HiFi Playback",
301
ALC5623_PWR_MANAG_ADD2, 9, 0),
302
SND_SOC_DAPM_DAC("Right DAC", "Right HiFi Playback",
303
ALC5623_PWR_MANAG_ADD2, 8, 0),
304
SND_SOC_DAPM_MIXER("I2S Mix", ALC5623_PWR_MANAG_ADD1, 15, 0, NULL, 0),
305
SND_SOC_DAPM_MIXER("AuxI Mix", SND_SOC_NOPM, 0, 0, NULL, 0),
306
SND_SOC_DAPM_MIXER("Line Mix", SND_SOC_NOPM, 0, 0, NULL, 0),
307
SND_SOC_DAPM_ADC("Left ADC", "Left HiFi Capture",
308
ALC5623_PWR_MANAG_ADD2, 7, 0),
309
SND_SOC_DAPM_ADC("Right ADC", "Right HiFi Capture",
310
ALC5623_PWR_MANAG_ADD2, 6, 0),
311
SND_SOC_DAPM_PGA("Left Headphone", ALC5623_PWR_MANAG_ADD3, 10, 0, NULL, 0),
312
SND_SOC_DAPM_PGA("Right Headphone", ALC5623_PWR_MANAG_ADD3, 9, 0, NULL, 0),
313
SND_SOC_DAPM_PGA("SpeakerOut", ALC5623_PWR_MANAG_ADD3, 12, 0, NULL, 0),
314
SND_SOC_DAPM_PGA("Left AuxOut", ALC5623_PWR_MANAG_ADD3, 14, 0, NULL, 0),
315
SND_SOC_DAPM_PGA("Right AuxOut", ALC5623_PWR_MANAG_ADD3, 13, 0, NULL, 0),
316
SND_SOC_DAPM_PGA("Left LineIn", ALC5623_PWR_MANAG_ADD3, 7, 0, NULL, 0),
317
SND_SOC_DAPM_PGA("Right LineIn", ALC5623_PWR_MANAG_ADD3, 6, 0, NULL, 0),
318
SND_SOC_DAPM_PGA("Left AuxI", ALC5623_PWR_MANAG_ADD3, 5, 0, NULL, 0),
319
SND_SOC_DAPM_PGA("Right AuxI", ALC5623_PWR_MANAG_ADD3, 4, 0, NULL, 0),
320
SND_SOC_DAPM_PGA("MIC1 PGA", ALC5623_PWR_MANAG_ADD3, 3, 0, NULL, 0),
321
SND_SOC_DAPM_PGA("MIC2 PGA", ALC5623_PWR_MANAG_ADD3, 2, 0, NULL, 0),
322
SND_SOC_DAPM_PGA("MIC1 Pre Amp", ALC5623_PWR_MANAG_ADD3, 1, 0, NULL, 0),
323
SND_SOC_DAPM_PGA("MIC2 Pre Amp", ALC5623_PWR_MANAG_ADD3, 0, 0, NULL, 0),
324
SND_SOC_DAPM_MICBIAS("Mic Bias1", ALC5623_PWR_MANAG_ADD1, 11, 0),
325
326
SND_SOC_DAPM_OUTPUT("AUXOUTL"),
327
SND_SOC_DAPM_OUTPUT("AUXOUTR"),
328
SND_SOC_DAPM_OUTPUT("HPL"),
329
SND_SOC_DAPM_OUTPUT("HPR"),
330
SND_SOC_DAPM_OUTPUT("SPKOUT"),
331
SND_SOC_DAPM_OUTPUT("SPKOUTN"),
332
SND_SOC_DAPM_INPUT("LINEINL"),
333
SND_SOC_DAPM_INPUT("LINEINR"),
334
SND_SOC_DAPM_INPUT("AUXINL"),
335
SND_SOC_DAPM_INPUT("AUXINR"),
336
SND_SOC_DAPM_INPUT("MIC1"),
337
SND_SOC_DAPM_INPUT("MIC2"),
338
SND_SOC_DAPM_VMID("Vmid"),
339
};
340
341
static const char *alc5623_amp_names[] = {"AB Amp", "D Amp"};
342
static const struct soc_enum alc5623_amp_enum =
343
SOC_ENUM_SINGLE(ALC5623_OUTPUT_MIXER_CTRL, 13, 2, alc5623_amp_names);
344
static const struct snd_kcontrol_new alc5623_amp_mux_controls =
345
SOC_DAPM_ENUM("Route", alc5623_amp_enum);
346
347
static const struct snd_soc_dapm_widget alc5623_dapm_amp_widgets[] = {
348
SND_SOC_DAPM_PGA_E("D Amp", ALC5623_PWR_MANAG_ADD2, 14, 0, NULL, 0,
349
amp_mixer_event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
350
SND_SOC_DAPM_PGA("AB Amp", ALC5623_PWR_MANAG_ADD2, 15, 0, NULL, 0),
351
SND_SOC_DAPM_MUX("AB-D Amp Mux", SND_SOC_NOPM, 0, 0,
352
&alc5623_amp_mux_controls),
353
};
354
355
static const struct snd_soc_dapm_route intercon[] = {
356
/* virtual mixer - mixes left & right channels */
357
{"I2S Mix", NULL, "Left DAC"},
358
{"I2S Mix", NULL, "Right DAC"},
359
{"Line Mix", NULL, "Right LineIn"},
360
{"Line Mix", NULL, "Left LineIn"},
361
{"AuxI Mix", NULL, "Left AuxI"},
362
{"AuxI Mix", NULL, "Right AuxI"},
363
{"AUXOUTL", NULL, "Left AuxOut"},
364
{"AUXOUTR", NULL, "Right AuxOut"},
365
366
/* HP mixer */
367
{"HPL Mix", "ADC2HP_L Playback Switch", "Left Capture Mix"},
368
{"HPL Mix", NULL, "HP Mix"},
369
{"HPR Mix", "ADC2HP_R Playback Switch", "Right Capture Mix"},
370
{"HPR Mix", NULL, "HP Mix"},
371
{"HP Mix", "LI2HP Playback Switch", "Line Mix"},
372
{"HP Mix", "AUXI2HP Playback Switch", "AuxI Mix"},
373
{"HP Mix", "MIC12HP Playback Switch", "MIC1 PGA"},
374
{"HP Mix", "MIC22HP Playback Switch", "MIC2 PGA"},
375
{"HP Mix", "DAC2HP Playback Switch", "I2S Mix"},
376
377
/* speaker mixer */
378
{"Speaker Mix", "LI2SPK Playback Switch", "Line Mix"},
379
{"Speaker Mix", "AUXI2SPK Playback Switch", "AuxI Mix"},
380
{"Speaker Mix", "MIC12SPK Playback Switch", "MIC1 PGA"},
381
{"Speaker Mix", "MIC22SPK Playback Switch", "MIC2 PGA"},
382
{"Speaker Mix", "DAC2SPK Playback Switch", "I2S Mix"},
383
384
/* mono mixer */
385
{"Mono Mix", "ADC2MONO_L Playback Switch", "Left Capture Mix"},
386
{"Mono Mix", "ADC2MONO_R Playback Switch", "Right Capture Mix"},
387
{"Mono Mix", "LI2MONO Playback Switch", "Line Mix"},
388
{"Mono Mix", "AUXI2MONO Playback Switch", "AuxI Mix"},
389
{"Mono Mix", "MIC12MONO Playback Switch", "MIC1 PGA"},
390
{"Mono Mix", "MIC22MONO Playback Switch", "MIC2 PGA"},
391
{"Mono Mix", "DAC2MONO Playback Switch", "I2S Mix"},
392
393
/* Left record mixer */
394
{"Left Capture Mix", "LineInL Capture Switch", "LINEINL"},
395
{"Left Capture Mix", "Left AuxI Capture Switch", "AUXINL"},
396
{"Left Capture Mix", "Mic1 Capture Switch", "MIC1 Pre Amp"},
397
{"Left Capture Mix", "Mic2 Capture Switch", "MIC2 Pre Amp"},
398
{"Left Capture Mix", "HPMixerL Capture Switch", "HPL Mix"},
399
{"Left Capture Mix", "SPKMixer Capture Switch", "Speaker Mix"},
400
{"Left Capture Mix", "MonoMixer Capture Switch", "Mono Mix"},
401
402
/*Right record mixer */
403
{"Right Capture Mix", "LineInR Capture Switch", "LINEINR"},
404
{"Right Capture Mix", "Right AuxI Capture Switch", "AUXINR"},
405
{"Right Capture Mix", "Mic1 Capture Switch", "MIC1 Pre Amp"},
406
{"Right Capture Mix", "Mic2 Capture Switch", "MIC2 Pre Amp"},
407
{"Right Capture Mix", "HPMixerR Capture Switch", "HPR Mix"},
408
{"Right Capture Mix", "SPKMixer Capture Switch", "Speaker Mix"},
409
{"Right Capture Mix", "MonoMixer Capture Switch", "Mono Mix"},
410
411
/* headphone left mux */
412
{"Left Headphone Mux", "HP Left Mix", "HPL Mix"},
413
{"Left Headphone Mux", "Vmid", "Vmid"},
414
415
/* headphone right mux */
416
{"Right Headphone Mux", "HP Right Mix", "HPR Mix"},
417
{"Right Headphone Mux", "Vmid", "Vmid"},
418
419
/* speaker out mux */
420
{"SpeakerOut Mux", "Vmid", "Vmid"},
421
{"SpeakerOut Mux", "HPOut Mix", "HPOut Mix"},
422
{"SpeakerOut Mux", "Speaker Mix", "Speaker Mix"},
423
{"SpeakerOut Mux", "Mono Mix", "Mono Mix"},
424
425
/* Mono/Aux Out mux */
426
{"AuxOut Mux", "Vmid", "Vmid"},
427
{"AuxOut Mux", "HPOut Mix", "HPOut Mix"},
428
{"AuxOut Mux", "Speaker Mix", "Speaker Mix"},
429
{"AuxOut Mux", "Mono Mix", "Mono Mix"},
430
431
/* output pga */
432
{"HPL", NULL, "Left Headphone"},
433
{"Left Headphone", NULL, "Left Headphone Mux"},
434
{"HPR", NULL, "Right Headphone"},
435
{"Right Headphone", NULL, "Right Headphone Mux"},
436
{"Left AuxOut", NULL, "AuxOut Mux"},
437
{"Right AuxOut", NULL, "AuxOut Mux"},
438
439
/* input pga */
440
{"Left LineIn", NULL, "LINEINL"},
441
{"Right LineIn", NULL, "LINEINR"},
442
{"Left AuxI", NULL, "AUXINL"},
443
{"Right AuxI", NULL, "AUXINR"},
444
{"MIC1 Pre Amp", NULL, "MIC1"},
445
{"MIC2 Pre Amp", NULL, "MIC2"},
446
{"MIC1 PGA", NULL, "MIC1 Pre Amp"},
447
{"MIC2 PGA", NULL, "MIC2 Pre Amp"},
448
449
/* left ADC */
450
{"Left ADC", NULL, "Left Capture Mix"},
451
452
/* right ADC */
453
{"Right ADC", NULL, "Right Capture Mix"},
454
455
{"SpeakerOut N Mux", "RN/-R", "SpeakerOut"},
456
{"SpeakerOut N Mux", "RP/+R", "SpeakerOut"},
457
{"SpeakerOut N Mux", "LN/-R", "SpeakerOut"},
458
{"SpeakerOut N Mux", "Vmid", "Vmid"},
459
460
{"SPKOUT", NULL, "SpeakerOut"},
461
{"SPKOUTN", NULL, "SpeakerOut N Mux"},
462
};
463
464
static const struct snd_soc_dapm_route intercon_spk[] = {
465
{"SpeakerOut", NULL, "SpeakerOut Mux"},
466
};
467
468
static const struct snd_soc_dapm_route intercon_amp_spk[] = {
469
{"AB Amp", NULL, "SpeakerOut Mux"},
470
{"D Amp", NULL, "SpeakerOut Mux"},
471
{"AB-D Amp Mux", "AB Amp", "AB Amp"},
472
{"AB-D Amp Mux", "D Amp", "D Amp"},
473
{"SpeakerOut", NULL, "AB-D Amp Mux"},
474
};
475
476
/* PLL divisors */
477
struct _pll_div {
478
u32 pll_in;
479
u32 pll_out;
480
u16 regvalue;
481
};
482
483
/* Note : pll code from original alc5623 driver. Not sure of how good it is */
484
/* useful only for master mode */
485
static const struct _pll_div codec_master_pll_div[] = {
486
487
{ 2048000, 8192000, 0x0ea0},
488
{ 3686400, 8192000, 0x4e27},
489
{ 12000000, 8192000, 0x456b},
490
{ 13000000, 8192000, 0x495f},
491
{ 13100000, 8192000, 0x0320},
492
{ 2048000, 11289600, 0xf637},
493
{ 3686400, 11289600, 0x2f22},
494
{ 12000000, 11289600, 0x3e2f},
495
{ 13000000, 11289600, 0x4d5b},
496
{ 13100000, 11289600, 0x363b},
497
{ 2048000, 16384000, 0x1ea0},
498
{ 3686400, 16384000, 0x9e27},
499
{ 12000000, 16384000, 0x452b},
500
{ 13000000, 16384000, 0x542f},
501
{ 13100000, 16384000, 0x03a0},
502
{ 2048000, 16934400, 0xe625},
503
{ 3686400, 16934400, 0x9126},
504
{ 12000000, 16934400, 0x4d2c},
505
{ 13000000, 16934400, 0x742f},
506
{ 13100000, 16934400, 0x3c27},
507
{ 2048000, 22579200, 0x2aa0},
508
{ 3686400, 22579200, 0x2f20},
509
{ 12000000, 22579200, 0x7e2f},
510
{ 13000000, 22579200, 0x742f},
511
{ 13100000, 22579200, 0x3c27},
512
{ 2048000, 24576000, 0x2ea0},
513
{ 3686400, 24576000, 0xee27},
514
{ 12000000, 24576000, 0x2915},
515
{ 13000000, 24576000, 0x772e},
516
{ 13100000, 24576000, 0x0d20},
517
};
518
519
static const struct _pll_div codec_slave_pll_div[] = {
520
521
{ 1024000, 16384000, 0x3ea0},
522
{ 1411200, 22579200, 0x3ea0},
523
{ 1536000, 24576000, 0x3ea0},
524
{ 2048000, 16384000, 0x1ea0},
525
{ 2822400, 22579200, 0x1ea0},
526
{ 3072000, 24576000, 0x1ea0},
527
528
};
529
530
static int alc5623_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id,
531
int source, unsigned int freq_in, unsigned int freq_out)
532
{
533
int i;
534
struct snd_soc_codec *codec = codec_dai->codec;
535
int gbl_clk = 0, pll_div = 0;
536
u16 reg;
537
538
if (pll_id < ALC5623_PLL_FR_MCLK || pll_id > ALC5623_PLL_FR_BCK)
539
return -ENODEV;
540
541
/* Disable PLL power */
542
snd_soc_update_bits(codec, ALC5623_PWR_MANAG_ADD2,
543
ALC5623_PWR_ADD2_PLL,
544
0);
545
546
/* pll is not used in slave mode */
547
reg = snd_soc_read(codec, ALC5623_DAI_CONTROL);
548
if (reg & ALC5623_DAI_SDP_SLAVE_MODE)
549
return 0;
550
551
if (!freq_in || !freq_out)
552
return 0;
553
554
switch (pll_id) {
555
case ALC5623_PLL_FR_MCLK:
556
for (i = 0; i < ARRAY_SIZE(codec_master_pll_div); i++) {
557
if (codec_master_pll_div[i].pll_in == freq_in
558
&& codec_master_pll_div[i].pll_out == freq_out) {
559
/* PLL source from MCLK */
560
pll_div = codec_master_pll_div[i].regvalue;
561
break;
562
}
563
}
564
break;
565
case ALC5623_PLL_FR_BCK:
566
for (i = 0; i < ARRAY_SIZE(codec_slave_pll_div); i++) {
567
if (codec_slave_pll_div[i].pll_in == freq_in
568
&& codec_slave_pll_div[i].pll_out == freq_out) {
569
/* PLL source from Bitclk */
570
gbl_clk = ALC5623_GBL_CLK_PLL_SOUR_SEL_BITCLK;
571
pll_div = codec_slave_pll_div[i].regvalue;
572
break;
573
}
574
}
575
break;
576
default:
577
return -EINVAL;
578
}
579
580
if (!pll_div)
581
return -EINVAL;
582
583
snd_soc_write(codec, ALC5623_GLOBAL_CLK_CTRL_REG, gbl_clk);
584
snd_soc_write(codec, ALC5623_PLL_CTRL, pll_div);
585
snd_soc_update_bits(codec, ALC5623_PWR_MANAG_ADD2,
586
ALC5623_PWR_ADD2_PLL,
587
ALC5623_PWR_ADD2_PLL);
588
gbl_clk |= ALC5623_GBL_CLK_SYS_SOUR_SEL_PLL;
589
snd_soc_write(codec, ALC5623_GLOBAL_CLK_CTRL_REG, gbl_clk);
590
591
return 0;
592
}
593
594
struct _coeff_div {
595
u16 fs;
596
u16 regvalue;
597
};
598
599
/* codec hifi mclk (after PLL) clock divider coefficients */
600
/* values inspired from column BCLK=32Fs of Appendix A table */
601
static const struct _coeff_div coeff_div[] = {
602
{256*8, 0x3a69},
603
{384*8, 0x3c6b},
604
{256*4, 0x2a69},
605
{384*4, 0x2c6b},
606
{256*2, 0x1a69},
607
{384*2, 0x1c6b},
608
{256*1, 0x0a69},
609
{384*1, 0x0c6b},
610
};
611
612
static int get_coeff(struct snd_soc_codec *codec, int rate)
613
{
614
struct alc5623_priv *alc5623 = snd_soc_codec_get_drvdata(codec);
615
int i;
616
617
for (i = 0; i < ARRAY_SIZE(coeff_div); i++) {
618
if (coeff_div[i].fs * rate == alc5623->sysclk)
619
return i;
620
}
621
return -EINVAL;
622
}
623
624
/*
625
* Clock after PLL and dividers
626
*/
627
static int alc5623_set_dai_sysclk(struct snd_soc_dai *codec_dai,
628
int clk_id, unsigned int freq, int dir)
629
{
630
struct snd_soc_codec *codec = codec_dai->codec;
631
struct alc5623_priv *alc5623 = snd_soc_codec_get_drvdata(codec);
632
633
switch (freq) {
634
case 8192000:
635
case 11289600:
636
case 12288000:
637
case 16384000:
638
case 16934400:
639
case 18432000:
640
case 22579200:
641
case 24576000:
642
alc5623->sysclk = freq;
643
return 0;
644
}
645
return -EINVAL;
646
}
647
648
static int alc5623_set_dai_fmt(struct snd_soc_dai *codec_dai,
649
unsigned int fmt)
650
{
651
struct snd_soc_codec *codec = codec_dai->codec;
652
u16 iface = 0;
653
654
/* set master/slave audio interface */
655
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
656
case SND_SOC_DAIFMT_CBM_CFM:
657
iface = ALC5623_DAI_SDP_MASTER_MODE;
658
break;
659
case SND_SOC_DAIFMT_CBS_CFS:
660
iface = ALC5623_DAI_SDP_SLAVE_MODE;
661
break;
662
default:
663
return -EINVAL;
664
}
665
666
/* interface format */
667
switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
668
case SND_SOC_DAIFMT_I2S:
669
iface |= ALC5623_DAI_I2S_DF_I2S;
670
break;
671
case SND_SOC_DAIFMT_RIGHT_J:
672
iface |= ALC5623_DAI_I2S_DF_RIGHT;
673
break;
674
case SND_SOC_DAIFMT_LEFT_J:
675
iface |= ALC5623_DAI_I2S_DF_LEFT;
676
break;
677
case SND_SOC_DAIFMT_DSP_A:
678
iface |= ALC5623_DAI_I2S_DF_PCM;
679
break;
680
case SND_SOC_DAIFMT_DSP_B:
681
iface |= ALC5623_DAI_I2S_DF_PCM | ALC5623_DAI_I2S_PCM_MODE;
682
break;
683
default:
684
return -EINVAL;
685
}
686
687
/* clock inversion */
688
switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
689
case SND_SOC_DAIFMT_NB_NF:
690
break;
691
case SND_SOC_DAIFMT_IB_IF:
692
iface |= ALC5623_DAI_MAIN_I2S_BCLK_POL_CTRL;
693
break;
694
case SND_SOC_DAIFMT_IB_NF:
695
iface |= ALC5623_DAI_MAIN_I2S_BCLK_POL_CTRL;
696
break;
697
case SND_SOC_DAIFMT_NB_IF:
698
break;
699
default:
700
return -EINVAL;
701
}
702
703
return snd_soc_write(codec, ALC5623_DAI_CONTROL, iface);
704
}
705
706
static int alc5623_pcm_hw_params(struct snd_pcm_substream *substream,
707
struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
708
{
709
struct snd_soc_pcm_runtime *rtd = substream->private_data;
710
struct snd_soc_codec *codec = rtd->codec;
711
struct alc5623_priv *alc5623 = snd_soc_codec_get_drvdata(codec);
712
int coeff, rate;
713
u16 iface;
714
715
iface = snd_soc_read(codec, ALC5623_DAI_CONTROL);
716
iface &= ~ALC5623_DAI_I2S_DL_MASK;
717
718
/* bit size */
719
switch (params_format(params)) {
720
case SNDRV_PCM_FORMAT_S16_LE:
721
iface |= ALC5623_DAI_I2S_DL_16;
722
break;
723
case SNDRV_PCM_FORMAT_S20_3LE:
724
iface |= ALC5623_DAI_I2S_DL_20;
725
break;
726
case SNDRV_PCM_FORMAT_S24_LE:
727
iface |= ALC5623_DAI_I2S_DL_24;
728
break;
729
case SNDRV_PCM_FORMAT_S32_LE:
730
iface |= ALC5623_DAI_I2S_DL_32;
731
break;
732
default:
733
return -EINVAL;
734
}
735
736
/* set iface & srate */
737
snd_soc_write(codec, ALC5623_DAI_CONTROL, iface);
738
rate = params_rate(params);
739
coeff = get_coeff(codec, rate);
740
if (coeff < 0)
741
return -EINVAL;
742
743
coeff = coeff_div[coeff].regvalue;
744
dev_dbg(codec->dev, "%s: sysclk=%d,rate=%d,coeff=0x%04x\n",
745
__func__, alc5623->sysclk, rate, coeff);
746
snd_soc_write(codec, ALC5623_STEREO_AD_DA_CLK_CTRL, coeff);
747
748
return 0;
749
}
750
751
static int alc5623_mute(struct snd_soc_dai *dai, int mute)
752
{
753
struct snd_soc_codec *codec = dai->codec;
754
u16 hp_mute = ALC5623_MISC_M_DAC_L_INPUT | ALC5623_MISC_M_DAC_R_INPUT;
755
u16 mute_reg = snd_soc_read(codec, ALC5623_MISC_CTRL) & ~hp_mute;
756
757
if (mute)
758
mute_reg |= hp_mute;
759
760
return snd_soc_write(codec, ALC5623_MISC_CTRL, mute_reg);
761
}
762
763
#define ALC5623_ADD2_POWER_EN (ALC5623_PWR_ADD2_VREF \
764
| ALC5623_PWR_ADD2_DAC_REF_CIR)
765
766
#define ALC5623_ADD3_POWER_EN (ALC5623_PWR_ADD3_MAIN_BIAS \
767
| ALC5623_PWR_ADD3_MIC1_BOOST_AD)
768
769
#define ALC5623_ADD1_POWER_EN \
770
(ALC5623_PWR_ADD1_SHORT_CURR_DET_EN | ALC5623_PWR_ADD1_SOFTGEN_EN \
771
| ALC5623_PWR_ADD1_DEPOP_BUF_HP | ALC5623_PWR_ADD1_HP_OUT_AMP \
772
| ALC5623_PWR_ADD1_HP_OUT_ENH_AMP)
773
774
#define ALC5623_ADD1_POWER_EN_5622 \
775
(ALC5623_PWR_ADD1_SHORT_CURR_DET_EN \
776
| ALC5623_PWR_ADD1_HP_OUT_AMP)
777
778
static void enable_power_depop(struct snd_soc_codec *codec)
779
{
780
struct alc5623_priv *alc5623 = snd_soc_codec_get_drvdata(codec);
781
782
snd_soc_update_bits(codec, ALC5623_PWR_MANAG_ADD1,
783
ALC5623_PWR_ADD1_SOFTGEN_EN,
784
ALC5623_PWR_ADD1_SOFTGEN_EN);
785
786
snd_soc_write(codec, ALC5623_PWR_MANAG_ADD3, ALC5623_ADD3_POWER_EN);
787
788
snd_soc_update_bits(codec, ALC5623_MISC_CTRL,
789
ALC5623_MISC_HP_DEPOP_MODE2_EN,
790
ALC5623_MISC_HP_DEPOP_MODE2_EN);
791
792
msleep(500);
793
794
snd_soc_write(codec, ALC5623_PWR_MANAG_ADD2, ALC5623_ADD2_POWER_EN);
795
796
/* avoid writing '1' into 5622 reserved bits */
797
if (alc5623->id == 0x22)
798
snd_soc_write(codec, ALC5623_PWR_MANAG_ADD1,
799
ALC5623_ADD1_POWER_EN_5622);
800
else
801
snd_soc_write(codec, ALC5623_PWR_MANAG_ADD1,
802
ALC5623_ADD1_POWER_EN);
803
804
/* disable HP Depop2 */
805
snd_soc_update_bits(codec, ALC5623_MISC_CTRL,
806
ALC5623_MISC_HP_DEPOP_MODE2_EN,
807
0);
808
809
}
810
811
static int alc5623_set_bias_level(struct snd_soc_codec *codec,
812
enum snd_soc_bias_level level)
813
{
814
switch (level) {
815
case SND_SOC_BIAS_ON:
816
enable_power_depop(codec);
817
break;
818
case SND_SOC_BIAS_PREPARE:
819
break;
820
case SND_SOC_BIAS_STANDBY:
821
/* everything off except vref/vmid, */
822
snd_soc_write(codec, ALC5623_PWR_MANAG_ADD2,
823
ALC5623_PWR_ADD2_VREF);
824
snd_soc_write(codec, ALC5623_PWR_MANAG_ADD3,
825
ALC5623_PWR_ADD3_MAIN_BIAS);
826
break;
827
case SND_SOC_BIAS_OFF:
828
/* everything off, dac mute, inactive */
829
snd_soc_write(codec, ALC5623_PWR_MANAG_ADD2, 0);
830
snd_soc_write(codec, ALC5623_PWR_MANAG_ADD3, 0);
831
snd_soc_write(codec, ALC5623_PWR_MANAG_ADD1, 0);
832
break;
833
}
834
codec->dapm.bias_level = level;
835
return 0;
836
}
837
838
#define ALC5623_FORMATS (SNDRV_PCM_FMTBIT_S16_LE \
839
| SNDRV_PCM_FMTBIT_S24_LE \
840
| SNDRV_PCM_FMTBIT_S32_LE)
841
842
static struct snd_soc_dai_ops alc5623_dai_ops = {
843
.hw_params = alc5623_pcm_hw_params,
844
.digital_mute = alc5623_mute,
845
.set_fmt = alc5623_set_dai_fmt,
846
.set_sysclk = alc5623_set_dai_sysclk,
847
.set_pll = alc5623_set_dai_pll,
848
};
849
850
static struct snd_soc_dai_driver alc5623_dai = {
851
.name = "alc5623-hifi",
852
.playback = {
853
.stream_name = "Playback",
854
.channels_min = 1,
855
.channels_max = 2,
856
.rate_min = 8000,
857
.rate_max = 48000,
858
.rates = SNDRV_PCM_RATE_8000_48000,
859
.formats = ALC5623_FORMATS,},
860
.capture = {
861
.stream_name = "Capture",
862
.channels_min = 1,
863
.channels_max = 2,
864
.rate_min = 8000,
865
.rate_max = 48000,
866
.rates = SNDRV_PCM_RATE_8000_48000,
867
.formats = ALC5623_FORMATS,},
868
869
.ops = &alc5623_dai_ops,
870
};
871
872
static int alc5623_suspend(struct snd_soc_codec *codec, pm_message_t mesg)
873
{
874
alc5623_set_bias_level(codec, SND_SOC_BIAS_OFF);
875
return 0;
876
}
877
878
static int alc5623_resume(struct snd_soc_codec *codec)
879
{
880
int i, step = codec->driver->reg_cache_step;
881
u16 *cache = codec->reg_cache;
882
883
/* Sync reg_cache with the hardware */
884
for (i = 2 ; i < codec->driver->reg_cache_size ; i += step)
885
snd_soc_write(codec, i, cache[i]);
886
887
alc5623_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
888
889
/* charge alc5623 caps */
890
if (codec->dapm.suspend_bias_level == SND_SOC_BIAS_ON) {
891
alc5623_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
892
codec->dapm.bias_level = SND_SOC_BIAS_ON;
893
alc5623_set_bias_level(codec, codec->dapm.bias_level);
894
}
895
896
return 0;
897
}
898
899
static int alc5623_probe(struct snd_soc_codec *codec)
900
{
901
struct alc5623_priv *alc5623 = snd_soc_codec_get_drvdata(codec);
902
struct snd_soc_dapm_context *dapm = &codec->dapm;
903
int ret;
904
905
ret = snd_soc_codec_set_cache_io(codec, 8, 16, alc5623->control_type);
906
if (ret < 0) {
907
dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
908
return ret;
909
}
910
911
alc5623_reset(codec);
912
alc5623_fill_cache(codec);
913
914
/* power on device */
915
alc5623_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
916
917
if (alc5623->add_ctrl) {
918
snd_soc_write(codec, ALC5623_ADD_CTRL_REG,
919
alc5623->add_ctrl);
920
}
921
922
if (alc5623->jack_det_ctrl) {
923
snd_soc_write(codec, ALC5623_JACK_DET_CTRL,
924
alc5623->jack_det_ctrl);
925
}
926
927
switch (alc5623->id) {
928
case 0x21:
929
snd_soc_add_controls(codec, rt5621_vol_snd_controls,
930
ARRAY_SIZE(rt5621_vol_snd_controls));
931
break;
932
case 0x22:
933
snd_soc_add_controls(codec, rt5622_vol_snd_controls,
934
ARRAY_SIZE(rt5622_vol_snd_controls));
935
break;
936
case 0x23:
937
snd_soc_add_controls(codec, alc5623_vol_snd_controls,
938
ARRAY_SIZE(alc5623_vol_snd_controls));
939
break;
940
default:
941
return -EINVAL;
942
}
943
944
snd_soc_add_controls(codec, alc5623_snd_controls,
945
ARRAY_SIZE(alc5623_snd_controls));
946
947
snd_soc_dapm_new_controls(dapm, alc5623_dapm_widgets,
948
ARRAY_SIZE(alc5623_dapm_widgets));
949
950
/* set up audio path interconnects */
951
snd_soc_dapm_add_routes(dapm, intercon, ARRAY_SIZE(intercon));
952
953
switch (alc5623->id) {
954
case 0x21:
955
case 0x22:
956
snd_soc_dapm_new_controls(dapm, alc5623_dapm_amp_widgets,
957
ARRAY_SIZE(alc5623_dapm_amp_widgets));
958
snd_soc_dapm_add_routes(dapm, intercon_amp_spk,
959
ARRAY_SIZE(intercon_amp_spk));
960
break;
961
case 0x23:
962
snd_soc_dapm_add_routes(dapm, intercon_spk,
963
ARRAY_SIZE(intercon_spk));
964
break;
965
default:
966
return -EINVAL;
967
}
968
969
return ret;
970
}
971
972
/* power down chip */
973
static int alc5623_remove(struct snd_soc_codec *codec)
974
{
975
alc5623_set_bias_level(codec, SND_SOC_BIAS_OFF);
976
return 0;
977
}
978
979
static struct snd_soc_codec_driver soc_codec_device_alc5623 = {
980
.probe = alc5623_probe,
981
.remove = alc5623_remove,
982
.suspend = alc5623_suspend,
983
.resume = alc5623_resume,
984
.set_bias_level = alc5623_set_bias_level,
985
.reg_cache_size = ALC5623_VENDOR_ID2+2,
986
.reg_word_size = sizeof(u16),
987
.reg_cache_step = 2,
988
};
989
990
/*
991
* ALC5623 2 wire address is determined by A1 pin
992
* state during powerup.
993
* low = 0x1a
994
* high = 0x1b
995
*/
996
static int alc5623_i2c_probe(struct i2c_client *client,
997
const struct i2c_device_id *id)
998
{
999
struct alc5623_platform_data *pdata;
1000
struct alc5623_priv *alc5623;
1001
int ret, vid1, vid2;
1002
1003
vid1 = i2c_smbus_read_word_data(client, ALC5623_VENDOR_ID1);
1004
if (vid1 < 0) {
1005
dev_err(&client->dev, "failed to read I2C\n");
1006
return -EIO;
1007
}
1008
vid1 = ((vid1 & 0xff) << 8) | (vid1 >> 8);
1009
1010
vid2 = i2c_smbus_read_byte_data(client, ALC5623_VENDOR_ID2);
1011
if (vid2 < 0) {
1012
dev_err(&client->dev, "failed to read I2C\n");
1013
return -EIO;
1014
}
1015
1016
if ((vid1 != 0x10ec) || (vid2 != id->driver_data)) {
1017
dev_err(&client->dev, "unknown or wrong codec\n");
1018
dev_err(&client->dev, "Expected %x:%lx, got %x:%x\n",
1019
0x10ec, id->driver_data,
1020
vid1, vid2);
1021
return -ENODEV;
1022
}
1023
1024
dev_dbg(&client->dev, "Found codec id : alc56%02x\n", vid2);
1025
1026
alc5623 = kzalloc(sizeof(struct alc5623_priv), GFP_KERNEL);
1027
if (alc5623 == NULL)
1028
return -ENOMEM;
1029
1030
pdata = client->dev.platform_data;
1031
if (pdata) {
1032
alc5623->add_ctrl = pdata->add_ctrl;
1033
alc5623->jack_det_ctrl = pdata->jack_det_ctrl;
1034
}
1035
1036
alc5623->id = vid2;
1037
switch (alc5623->id) {
1038
case 0x21:
1039
alc5623_dai.name = "alc5621-hifi";
1040
break;
1041
case 0x22:
1042
alc5623_dai.name = "alc5622-hifi";
1043
break;
1044
case 0x23:
1045
alc5623_dai.name = "alc5623-hifi";
1046
break;
1047
default:
1048
kfree(alc5623);
1049
return -EINVAL;
1050
}
1051
1052
i2c_set_clientdata(client, alc5623);
1053
alc5623->control_data = client;
1054
alc5623->control_type = SND_SOC_I2C;
1055
mutex_init(&alc5623->mutex);
1056
1057
ret = snd_soc_register_codec(&client->dev,
1058
&soc_codec_device_alc5623, &alc5623_dai, 1);
1059
if (ret != 0) {
1060
dev_err(&client->dev, "Failed to register codec: %d\n", ret);
1061
kfree(alc5623);
1062
}
1063
1064
return ret;
1065
}
1066
1067
static int alc5623_i2c_remove(struct i2c_client *client)
1068
{
1069
struct alc5623_priv *alc5623 = i2c_get_clientdata(client);
1070
1071
snd_soc_unregister_codec(&client->dev);
1072
kfree(alc5623);
1073
return 0;
1074
}
1075
1076
static const struct i2c_device_id alc5623_i2c_table[] = {
1077
{"alc5621", 0x21},
1078
{"alc5622", 0x22},
1079
{"alc5623", 0x23},
1080
{}
1081
};
1082
MODULE_DEVICE_TABLE(i2c, alc5623_i2c_table);
1083
1084
/* i2c codec control layer */
1085
static struct i2c_driver alc5623_i2c_driver = {
1086
.driver = {
1087
.name = "alc562x-codec",
1088
.owner = THIS_MODULE,
1089
},
1090
.probe = alc5623_i2c_probe,
1091
.remove = __devexit_p(alc5623_i2c_remove),
1092
.id_table = alc5623_i2c_table,
1093
};
1094
1095
static int __init alc5623_modinit(void)
1096
{
1097
int ret;
1098
1099
ret = i2c_add_driver(&alc5623_i2c_driver);
1100
if (ret != 0) {
1101
printk(KERN_ERR "%s: can't add i2c driver", __func__);
1102
return ret;
1103
}
1104
1105
return ret;
1106
}
1107
module_init(alc5623_modinit);
1108
1109
static void __exit alc5623_modexit(void)
1110
{
1111
i2c_del_driver(&alc5623_i2c_driver);
1112
}
1113
module_exit(alc5623_modexit);
1114
1115
MODULE_DESCRIPTION("ASoC alc5621/2/3 driver");
1116
MODULE_AUTHOR("Arnaud Patard <[email protected]>");
1117
MODULE_LICENSE("GPL");
1118
1119