aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/ac97
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2008-05-30 03:22:22 -0400
committerTakashi Iwai <tiwai@suse.de>2008-05-30 03:26:09 -0400
commit23ce1547638443f0053dd674e728062c48ff0e39 (patch)
tree8b5fde61f1e55633c3420b8dd6f9794f1bf02067 /sound/pci/ac97
parentc18f68e4d809a517ed8df540bac2993a4f14d9a4 (diff)
[ALSA] Make ak4531 local to ens1370 driver
The ak4531 module is used only by ens1370 driver (and unlikely that any other will use it ever). Let's make it local to ens1370. Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci/ac97')
-rw-r--r--sound/pci/ac97/Makefile3
-rw-r--r--sound/pci/ac97/ak4531_codec.c508
2 files changed, 0 insertions, 511 deletions
diff --git a/sound/pci/ac97/Makefile b/sound/pci/ac97/Makefile
index ae36950f2568..41fa322f0971 100644
--- a/sound/pci/ac97/Makefile
+++ b/sound/pci/ac97/Makefile
@@ -6,8 +6,5 @@
6snd-ac97-codec-y := ac97_codec.o ac97_pcm.o 6snd-ac97-codec-y := ac97_codec.o ac97_pcm.o
7snd-ac97-codec-$(CONFIG_PROC_FS) += ac97_proc.o 7snd-ac97-codec-$(CONFIG_PROC_FS) += ac97_proc.o
8 8
9snd-ak4531-codec-objs := ak4531_codec.o
10
11# Toplevel Module Dependency 9# Toplevel Module Dependency
12obj-$(CONFIG_SND_AC97_CODEC) += snd-ac97-codec.o 10obj-$(CONFIG_SND_AC97_CODEC) += snd-ac97-codec.o
13obj-$(CONFIG_SND_ENS1370) += snd-ak4531-codec.o
diff --git a/sound/pci/ac97/ak4531_codec.c b/sound/pci/ac97/ak4531_codec.c
deleted file mode 100644
index c0c1633999ea..000000000000
--- a/sound/pci/ac97/ak4531_codec.c
+++ /dev/null
@@ -1,508 +0,0 @@
1/*
2 * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
3 * Universal routines for AK4531 codec
4 *
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20 */
21
22#include <linux/delay.h>
23#include <linux/init.h>
24#include <linux/slab.h>
25#include <linux/mutex.h>
26
27#include <sound/core.h>
28#include <sound/ak4531_codec.h>
29#include <sound/tlv.h>
30
31MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
32MODULE_DESCRIPTION("Universal routines for AK4531 codec");
33MODULE_LICENSE("GPL");
34
35#ifdef CONFIG_PROC_FS
36static void snd_ak4531_proc_init(struct snd_card *card, struct snd_ak4531 *ak4531);
37#else
38#define snd_ak4531_proc_init(card,ak)
39#endif
40
41/*
42 *
43 */
44
45#if 0
46
47static void snd_ak4531_dump(struct snd_ak4531 *ak4531)
48{
49 int idx;
50
51 for (idx = 0; idx < 0x19; idx++)
52 printk("ak4531 0x%x: 0x%x\n", idx, ak4531->regs[idx]);
53}
54
55#endif
56
57/*
58 *
59 */
60
61#define AK4531_SINGLE(xname, xindex, reg, shift, mask, invert) \
62{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
63 .info = snd_ak4531_info_single, \
64 .get = snd_ak4531_get_single, .put = snd_ak4531_put_single, \
65 .private_value = reg | (shift << 16) | (mask << 24) | (invert << 22) }
66#define AK4531_SINGLE_TLV(xname, xindex, reg, shift, mask, invert, xtlv) \
67{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
68 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ, \
69 .name = xname, .index = xindex, \
70 .info = snd_ak4531_info_single, \
71 .get = snd_ak4531_get_single, .put = snd_ak4531_put_single, \
72 .private_value = reg | (shift << 16) | (mask << 24) | (invert << 22), \
73 .tlv = { .p = (xtlv) } }
74
75static int snd_ak4531_info_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
76{
77 int mask = (kcontrol->private_value >> 24) & 0xff;
78
79 uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;
80 uinfo->count = 1;
81 uinfo->value.integer.min = 0;
82 uinfo->value.integer.max = mask;
83 return 0;
84}
85
86static int snd_ak4531_get_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
87{
88 struct snd_ak4531 *ak4531 = snd_kcontrol_chip(kcontrol);
89 int reg = kcontrol->private_value & 0xff;
90 int shift = (kcontrol->private_value >> 16) & 0x07;
91 int mask = (kcontrol->private_value >> 24) & 0xff;
92 int invert = (kcontrol->private_value >> 22) & 1;
93 int val;
94
95 mutex_lock(&ak4531->reg_mutex);
96 val = (ak4531->regs[reg] >> shift) & mask;
97 mutex_unlock(&ak4531->reg_mutex);
98 if (invert) {
99 val = mask - val;
100 }
101 ucontrol->value.integer.value[0] = val;
102 return 0;
103}
104
105static int snd_ak4531_put_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
106{
107 struct snd_ak4531 *ak4531 = snd_kcontrol_chip(kcontrol);
108 int reg = kcontrol->private_value & 0xff;
109 int shift = (kcontrol->private_value >> 16) & 0x07;
110 int mask = (kcontrol->private_value >> 24) & 0xff;
111 int invert = (kcontrol->private_value >> 22) & 1;
112 int change;
113 int val;
114
115 val = ucontrol->value.integer.value[0] & mask;
116 if (invert) {
117 val = mask - val;
118 }
119 val <<= shift;
120 mutex_lock(&ak4531->reg_mutex);
121 val = (ak4531->regs[reg] & ~(mask << shift)) | val;
122 change = val != ak4531->regs[reg];
123 ak4531->write(ak4531, reg, ak4531->regs[reg] = val);
124 mutex_unlock(&ak4531->reg_mutex);
125 return change;
126}
127
128#define AK4531_DOUBLE(xname, xindex, left_reg, right_reg, left_shift, right_shift, mask, invert) \
129{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
130 .info = snd_ak4531_info_double, \
131 .get = snd_ak4531_get_double, .put = snd_ak4531_put_double, \
132 .private_value = left_reg | (right_reg << 8) | (left_shift << 16) | (right_shift << 19) | (mask << 24) | (invert << 22) }
133#define AK4531_DOUBLE_TLV(xname, xindex, left_reg, right_reg, left_shift, right_shift, mask, invert, xtlv) \
134{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
135 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ, \
136 .name = xname, .index = xindex, \
137 .info = snd_ak4531_info_double, \
138 .get = snd_ak4531_get_double, .put = snd_ak4531_put_double, \
139 .private_value = left_reg | (right_reg << 8) | (left_shift << 16) | (right_shift << 19) | (mask << 24) | (invert << 22), \
140 .tlv = { .p = (xtlv) } }
141
142static int snd_ak4531_info_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
143{
144 int mask = (kcontrol->private_value >> 24) & 0xff;
145
146 uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;
147 uinfo->count = 2;
148 uinfo->value.integer.min = 0;
149 uinfo->value.integer.max = mask;
150 return 0;
151}
152
153static int snd_ak4531_get_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
154{
155 struct snd_ak4531 *ak4531 = snd_kcontrol_chip(kcontrol);
156 int left_reg = kcontrol->private_value & 0xff;
157 int right_reg = (kcontrol->private_value >> 8) & 0xff;
158 int left_shift = (kcontrol->private_value >> 16) & 0x07;
159 int right_shift = (kcontrol->private_value >> 19) & 0x07;
160 int mask = (kcontrol->private_value >> 24) & 0xff;
161 int invert = (kcontrol->private_value >> 22) & 1;
162 int left, right;
163
164 mutex_lock(&ak4531->reg_mutex);
165 left = (ak4531->regs[left_reg] >> left_shift) & mask;
166 right = (ak4531->regs[right_reg] >> right_shift) & mask;
167 mutex_unlock(&ak4531->reg_mutex);
168 if (invert) {
169 left = mask - left;
170 right = mask - right;
171 }
172 ucontrol->value.integer.value[0] = left;
173 ucontrol->value.integer.value[1] = right;
174 return 0;
175}
176
177static int snd_ak4531_put_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
178{
179 struct snd_ak4531 *ak4531 = snd_kcontrol_chip(kcontrol);
180 int left_reg = kcontrol->private_value & 0xff;
181 int right_reg = (kcontrol->private_value >> 8) & 0xff;
182 int left_shift = (kcontrol->private_value >> 16) & 0x07;
183 int right_shift = (kcontrol->private_value >> 19) & 0x07;
184 int mask = (kcontrol->private_value >> 24) & 0xff;
185 int invert = (kcontrol->private_value >> 22) & 1;
186 int change;
187 int left, right;
188
189 left = ucontrol->value.integer.value[0] & mask;
190 right = ucontrol->value.integer.value[1] & mask;
191 if (invert) {
192 left = mask - left;
193 right = mask - right;
194 }
195 left <<= left_shift;
196 right <<= right_shift;
197 mutex_lock(&ak4531->reg_mutex);
198 if (left_reg == right_reg) {
199 left = (ak4531->regs[left_reg] & ~((mask << left_shift) | (mask << right_shift))) | left | right;
200 change = left != ak4531->regs[left_reg];
201 ak4531->write(ak4531, left_reg, ak4531->regs[left_reg] = left);
202 } else {
203 left = (ak4531->regs[left_reg] & ~(mask << left_shift)) | left;
204 right = (ak4531->regs[right_reg] & ~(mask << right_shift)) | right;
205 change = left != ak4531->regs[left_reg] || right != ak4531->regs[right_reg];
206 ak4531->write(ak4531, left_reg, ak4531->regs[left_reg] = left);
207 ak4531->write(ak4531, right_reg, ak4531->regs[right_reg] = right);
208 }
209 mutex_unlock(&ak4531->reg_mutex);
210 return change;
211}
212
213#define AK4531_INPUT_SW(xname, xindex, reg1, reg2, left_shift, right_shift) \
214{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
215 .info = snd_ak4531_info_input_sw, \
216 .get = snd_ak4531_get_input_sw, .put = snd_ak4531_put_input_sw, \
217 .private_value = reg1 | (reg2 << 8) | (left_shift << 16) | (right_shift << 24) }
218
219static int snd_ak4531_info_input_sw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
220{
221 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
222 uinfo->count = 4;
223 uinfo->value.integer.min = 0;
224 uinfo->value.integer.max = 1;
225 return 0;
226}
227
228static int snd_ak4531_get_input_sw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
229{
230 struct snd_ak4531 *ak4531 = snd_kcontrol_chip(kcontrol);
231 int reg1 = kcontrol->private_value & 0xff;
232 int reg2 = (kcontrol->private_value >> 8) & 0xff;
233 int left_shift = (kcontrol->private_value >> 16) & 0x0f;
234 int right_shift = (kcontrol->private_value >> 24) & 0x0f;
235
236 mutex_lock(&ak4531->reg_mutex);
237 ucontrol->value.integer.value[0] = (ak4531->regs[reg1] >> left_shift) & 1;
238 ucontrol->value.integer.value[1] = (ak4531->regs[reg2] >> left_shift) & 1;
239 ucontrol->value.integer.value[2] = (ak4531->regs[reg1] >> right_shift) & 1;
240 ucontrol->value.integer.value[3] = (ak4531->regs[reg2] >> right_shift) & 1;
241 mutex_unlock(&ak4531->reg_mutex);
242 return 0;
243}
244
245static int snd_ak4531_put_input_sw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
246{
247 struct snd_ak4531 *ak4531 = snd_kcontrol_chip(kcontrol);
248 int reg1 = kcontrol->private_value & 0xff;
249 int reg2 = (kcontrol->private_value >> 8) & 0xff;
250 int left_shift = (kcontrol->private_value >> 16) & 0x0f;
251 int right_shift = (kcontrol->private_value >> 24) & 0x0f;
252 int change;
253 int val1, val2;
254
255 mutex_lock(&ak4531->reg_mutex);
256 val1 = ak4531->regs[reg1] & ~((1 << left_shift) | (1 << right_shift));
257 val2 = ak4531->regs[reg2] & ~((1 << left_shift) | (1 << right_shift));
258 val1 |= (ucontrol->value.integer.value[0] & 1) << left_shift;
259 val2 |= (ucontrol->value.integer.value[1] & 1) << left_shift;
260 val1 |= (ucontrol->value.integer.value[2] & 1) << right_shift;
261 val2 |= (ucontrol->value.integer.value[3] & 1) << right_shift;
262 change = val1 != ak4531->regs[reg1] || val2 != ak4531->regs[reg2];
263 ak4531->write(ak4531, reg1, ak4531->regs[reg1] = val1);
264 ak4531->write(ak4531, reg2, ak4531->regs[reg2] = val2);
265 mutex_unlock(&ak4531->reg_mutex);
266 return change;
267}
268
269static const DECLARE_TLV_DB_SCALE(db_scale_master, -6200, 200, 0);
270static const DECLARE_TLV_DB_SCALE(db_scale_mono, -2800, 400, 0);
271static const DECLARE_TLV_DB_SCALE(db_scale_input, -5000, 200, 0);
272
273static struct snd_kcontrol_new snd_ak4531_controls[] = {
274
275AK4531_DOUBLE_TLV("Master Playback Switch", 0,
276 AK4531_LMASTER, AK4531_RMASTER, 7, 7, 1, 1,
277 db_scale_master),
278AK4531_DOUBLE("Master Playback Volume", 0, AK4531_LMASTER, AK4531_RMASTER, 0, 0, 0x1f, 1),
279
280AK4531_SINGLE_TLV("Master Mono Playback Switch", 0, AK4531_MONO_OUT, 7, 1, 1,
281 db_scale_mono),
282AK4531_SINGLE("Master Mono Playback Volume", 0, AK4531_MONO_OUT, 0, 0x07, 1),
283
284AK4531_DOUBLE("PCM Switch", 0, AK4531_LVOICE, AK4531_RVOICE, 7, 7, 1, 1),
285AK4531_DOUBLE_TLV("PCM Volume", 0, AK4531_LVOICE, AK4531_RVOICE, 0, 0, 0x1f, 1,
286 db_scale_input),
287AK4531_DOUBLE("PCM Playback Switch", 0, AK4531_OUT_SW2, AK4531_OUT_SW2, 3, 2, 1, 0),
288AK4531_DOUBLE("PCM Capture Switch", 0, AK4531_LIN_SW2, AK4531_RIN_SW2, 2, 2, 1, 0),
289
290AK4531_DOUBLE("PCM Switch", 1, AK4531_LFM, AK4531_RFM, 7, 7, 1, 1),
291AK4531_DOUBLE_TLV("PCM Volume", 1, AK4531_LFM, AK4531_RFM, 0, 0, 0x1f, 1,
292 db_scale_input),
293AK4531_DOUBLE("PCM Playback Switch", 1, AK4531_OUT_SW1, AK4531_OUT_SW1, 6, 5, 1, 0),
294AK4531_INPUT_SW("PCM Capture Route", 1, AK4531_LIN_SW1, AK4531_RIN_SW1, 6, 5),
295
296AK4531_DOUBLE("CD Switch", 0, AK4531_LCD, AK4531_RCD, 7, 7, 1, 1),
297AK4531_DOUBLE_TLV("CD Volume", 0, AK4531_LCD, AK4531_RCD, 0, 0, 0x1f, 1,
298 db_scale_input),
299AK4531_DOUBLE("CD Playback Switch", 0, AK4531_OUT_SW1, AK4531_OUT_SW1, 2, 1, 1, 0),
300AK4531_INPUT_SW("CD Capture Route", 0, AK4531_LIN_SW1, AK4531_RIN_SW1, 2, 1),
301
302AK4531_DOUBLE("Line Switch", 0, AK4531_LLINE, AK4531_RLINE, 7, 7, 1, 1),
303AK4531_DOUBLE_TLV("Line Volume", 0, AK4531_LLINE, AK4531_RLINE, 0, 0, 0x1f, 1,
304 db_scale_input),
305AK4531_DOUBLE("Line Playback Switch", 0, AK4531_OUT_SW1, AK4531_OUT_SW1, 4, 3, 1, 0),
306AK4531_INPUT_SW("Line Capture Route", 0, AK4531_LIN_SW1, AK4531_RIN_SW1, 4, 3),
307
308AK4531_DOUBLE("Aux Switch", 0, AK4531_LAUXA, AK4531_RAUXA, 7, 7, 1, 1),
309AK4531_DOUBLE_TLV("Aux Volume", 0, AK4531_LAUXA, AK4531_RAUXA, 0, 0, 0x1f, 1,
310 db_scale_input),
311AK4531_DOUBLE("Aux Playback Switch", 0, AK4531_OUT_SW2, AK4531_OUT_SW2, 5, 4, 1, 0),
312AK4531_INPUT_SW("Aux Capture Route", 0, AK4531_LIN_SW2, AK4531_RIN_SW2, 4, 3),
313
314AK4531_SINGLE("Mono Switch", 0, AK4531_MONO1, 7, 1, 1),
315AK4531_SINGLE_TLV("Mono Volume", 0, AK4531_MONO1, 0, 0x1f, 1, db_scale_input),
316AK4531_SINGLE("Mono Playback Switch", 0, AK4531_OUT_SW2, 0, 1, 0),
317AK4531_DOUBLE("Mono Capture Switch", 0, AK4531_LIN_SW2, AK4531_RIN_SW2, 0, 0, 1, 0),
318
319AK4531_SINGLE("Mono Switch", 1, AK4531_MONO2, 7, 1, 1),
320AK4531_SINGLE_TLV("Mono Volume", 1, AK4531_MONO2, 0, 0x1f, 1, db_scale_input),
321AK4531_SINGLE("Mono Playback Switch", 1, AK4531_OUT_SW2, 1, 1, 0),
322AK4531_DOUBLE("Mono Capture Switch", 1, AK4531_LIN_SW2, AK4531_RIN_SW2, 1, 1, 1, 0),
323
324AK4531_SINGLE_TLV("Mic Volume", 0, AK4531_MIC, 0, 0x1f, 1, db_scale_input),
325AK4531_SINGLE("Mic Switch", 0, AK4531_MIC, 7, 1, 1),
326AK4531_SINGLE("Mic Playback Switch", 0, AK4531_OUT_SW1, 0, 1, 0),
327AK4531_DOUBLE("Mic Capture Switch", 0, AK4531_LIN_SW1, AK4531_RIN_SW1, 0, 0, 1, 0),
328
329AK4531_DOUBLE("Mic Bypass Capture Switch", 0, AK4531_LIN_SW2, AK4531_RIN_SW2, 7, 7, 1, 0),
330AK4531_DOUBLE("Mono1 Bypass Capture Switch", 0, AK4531_LIN_SW2, AK4531_RIN_SW2, 6, 6, 1, 0),
331AK4531_DOUBLE("Mono2 Bypass Capture Switch", 0, AK4531_LIN_SW2, AK4531_RIN_SW2, 5, 5, 1, 0),
332
333AK4531_SINGLE("AD Input Select", 0, AK4531_AD_IN, 0, 1, 0),
334AK4531_SINGLE("Mic Boost (+30dB)", 0, AK4531_MIC_GAIN, 0, 1, 0)
335};
336
337static int snd_ak4531_free(struct snd_ak4531 *ak4531)
338{
339 if (ak4531) {
340 if (ak4531->private_free)
341 ak4531->private_free(ak4531);
342 kfree(ak4531);
343 }
344 return 0;
345}
346
347static int snd_ak4531_dev_free(struct snd_device *device)
348{
349 struct snd_ak4531 *ak4531 = device->device_data;
350 return snd_ak4531_free(ak4531);
351}
352
353static u8 snd_ak4531_initial_map[0x19 + 1] = {
354 0x9f, /* 00: Master Volume Lch */
355 0x9f, /* 01: Master Volume Rch */
356 0x9f, /* 02: Voice Volume Lch */
357 0x9f, /* 03: Voice Volume Rch */
358 0x9f, /* 04: FM Volume Lch */
359 0x9f, /* 05: FM Volume Rch */
360 0x9f, /* 06: CD Audio Volume Lch */
361 0x9f, /* 07: CD Audio Volume Rch */
362 0x9f, /* 08: Line Volume Lch */
363 0x9f, /* 09: Line Volume Rch */
364 0x9f, /* 0a: Aux Volume Lch */
365 0x9f, /* 0b: Aux Volume Rch */
366 0x9f, /* 0c: Mono1 Volume */
367 0x9f, /* 0d: Mono2 Volume */
368 0x9f, /* 0e: Mic Volume */
369 0x87, /* 0f: Mono-out Volume */
370 0x00, /* 10: Output Mixer SW1 */
371 0x00, /* 11: Output Mixer SW2 */
372 0x00, /* 12: Lch Input Mixer SW1 */
373 0x00, /* 13: Rch Input Mixer SW1 */
374 0x00, /* 14: Lch Input Mixer SW2 */
375 0x00, /* 15: Rch Input Mixer SW2 */
376 0x00, /* 16: Reset & Power Down */
377 0x00, /* 17: Clock Select */
378 0x00, /* 18: AD Input Select */
379 0x01 /* 19: Mic Amp Setup */
380};
381
382int snd_ak4531_mixer(struct snd_card *card, struct snd_ak4531 *_ak4531,
383 struct snd_ak4531 **rak4531)
384{
385 unsigned int idx;
386 int err;
387 struct snd_ak4531 *ak4531;
388 static struct snd_device_ops ops = {
389 .dev_free = snd_ak4531_dev_free,
390 };
391
392 snd_assert(rak4531 != NULL, return -EINVAL);
393 *rak4531 = NULL;
394 snd_assert(card != NULL && _ak4531 != NULL, return -EINVAL);
395 ak4531 = kzalloc(sizeof(*ak4531), GFP_KERNEL);
396 if (ak4531 == NULL)
397 return -ENOMEM;
398 *ak4531 = *_ak4531;
399 mutex_init(&ak4531->reg_mutex);
400 if ((err = snd_component_add(card, "AK4531")) < 0) {
401 snd_ak4531_free(ak4531);
402 return err;
403 }
404 strcpy(card->mixername, "Asahi Kasei AK4531");
405 ak4531->write(ak4531, AK4531_RESET, 0x03); /* no RST, PD */
406 udelay(100);
407 ak4531->write(ak4531, AK4531_CLOCK, 0x00); /* CODEC ADC and CODEC DAC use {LR,B}CLK2 and run off LRCLK2 PLL */
408 for (idx = 0; idx <= 0x19; idx++) {
409 if (idx == AK4531_RESET || idx == AK4531_CLOCK)
410 continue;
411 ak4531->write(ak4531, idx, ak4531->regs[idx] = snd_ak4531_initial_map[idx]); /* recording source is mixer */
412 }
413 for (idx = 0; idx < ARRAY_SIZE(snd_ak4531_controls); idx++) {
414 if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_ak4531_controls[idx], ak4531))) < 0) {
415 snd_ak4531_free(ak4531);
416 return err;
417 }
418 }
419 snd_ak4531_proc_init(card, ak4531);
420 if ((err = snd_device_new(card, SNDRV_DEV_CODEC, ak4531, &ops)) < 0) {
421 snd_ak4531_free(ak4531);
422 return err;
423 }
424
425#if 0
426 snd_ak4531_dump(ak4531);
427#endif
428 *rak4531 = ak4531;
429 return 0;
430}
431
432/*
433 * power management
434 */
435#ifdef CONFIG_PM
436void snd_ak4531_suspend(struct snd_ak4531 *ak4531)
437{
438 /* mute */
439 ak4531->write(ak4531, AK4531_LMASTER, 0x9f);
440 ak4531->write(ak4531, AK4531_RMASTER, 0x9f);
441 /* powerdown */
442 ak4531->write(ak4531, AK4531_RESET, 0x01);
443}
444
445void snd_ak4531_resume(struct snd_ak4531 *ak4531)
446{
447 int idx;
448
449 /* initialize */
450 ak4531->write(ak4531, AK4531_RESET, 0x03);
451 udelay(100);
452 ak4531->write(ak4531, AK4531_CLOCK, 0x00);
453 /* restore mixer registers */
454 for (idx = 0; idx <= 0x19; idx++) {
455 if (idx == AK4531_RESET || idx == AK4531_CLOCK)
456 continue;
457 ak4531->write(ak4531, idx, ak4531->regs[idx]);
458 }
459}
460#endif
461
462#ifdef CONFIG_PROC_FS
463/*
464 * /proc interface
465 */
466
467static void snd_ak4531_proc_read(struct snd_info_entry *entry,
468 struct snd_info_buffer *buffer)
469{
470 struct snd_ak4531 *ak4531 = entry->private_data;
471
472 snd_iprintf(buffer, "Asahi Kasei AK4531\n\n");
473 snd_iprintf(buffer, "Recording source : %s\n"
474 "MIC gain : %s\n",
475 ak4531->regs[AK4531_AD_IN] & 1 ? "external" : "mixer",
476 ak4531->regs[AK4531_MIC_GAIN] & 1 ? "+30dB" : "+0dB");
477}
478
479static void snd_ak4531_proc_init(struct snd_card *card, struct snd_ak4531 *ak4531)
480{
481 struct snd_info_entry *entry;
482
483 if (! snd_card_proc_new(card, "ak4531", &entry))
484 snd_info_set_text_ops(entry, ak4531, snd_ak4531_proc_read);
485}
486#endif
487
488EXPORT_SYMBOL(snd_ak4531_mixer);
489#ifdef CONFIG_PM
490EXPORT_SYMBOL(snd_ak4531_suspend);
491EXPORT_SYMBOL(snd_ak4531_resume);
492#endif
493
494/*
495 * INIT part
496 */
497
498static int __init alsa_ak4531_init(void)
499{
500 return 0;
501}
502
503static void __exit alsa_ak4531_exit(void)
504{
505}
506
507module_init(alsa_ak4531_init)
508module_exit(alsa_ak4531_exit)