diff options
author | Takashi Iwai <tiwai@suse.de> | 2009-12-01 09:57:01 -0500 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2009-12-01 09:57:01 -0500 |
commit | 980f31c46b3c7895ad926fbb43c8edac6ce193ff (patch) | |
tree | ec61a87b42ce8e6eb24554d8a56173ef75aefdd2 /sound | |
parent | 9e298f449e667833c4cafad040ce8025a8ba1eed (diff) | |
parent | 6ef80706184be792499a4485a7957f2660b6a076 (diff) |
Merge branch 'topic/ice1724-quartet' into topic/hda
Diffstat (limited to 'sound')
-rw-r--r-- | sound/i2c/other/Makefile | 3 | ||||
-rw-r--r-- | sound/i2c/other/ak4113.c | 639 | ||||
-rw-r--r-- | sound/i2c/other/ak4xxx-adda.c | 136 | ||||
-rw-r--r-- | sound/pci/ice1712/Makefile | 2 | ||||
-rw-r--r-- | sound/pci/ice1712/ice1712.c | 12 | ||||
-rw-r--r-- | sound/pci/ice1712/ice1712.h | 14 | ||||
-rw-r--r-- | sound/pci/ice1712/ice1724.c | 103 | ||||
-rw-r--r-- | sound/pci/ice1712/juli.c | 24 | ||||
-rw-r--r-- | sound/pci/ice1712/quartet.c | 1130 | ||||
-rw-r--r-- | sound/pci/ice1712/quartet.h | 10 |
10 files changed, 1995 insertions, 78 deletions
diff --git a/sound/i2c/other/Makefile b/sound/i2c/other/Makefile index 703d954238f4..2dad40f3f622 100644 --- a/sound/i2c/other/Makefile +++ b/sound/i2c/other/Makefile | |||
@@ -5,6 +5,7 @@ | |||
5 | 5 | ||
6 | snd-ak4114-objs := ak4114.o | 6 | snd-ak4114-objs := ak4114.o |
7 | snd-ak4117-objs := ak4117.o | 7 | snd-ak4117-objs := ak4117.o |
8 | snd-ak4113-objs := ak4113.o | ||
8 | snd-ak4xxx-adda-objs := ak4xxx-adda.o | 9 | snd-ak4xxx-adda-objs := ak4xxx-adda.o |
9 | snd-pt2258-objs := pt2258.o | 10 | snd-pt2258-objs := pt2258.o |
10 | snd-tea575x-tuner-objs := tea575x-tuner.o | 11 | snd-tea575x-tuner-objs := tea575x-tuner.o |
@@ -12,5 +13,5 @@ snd-tea575x-tuner-objs := tea575x-tuner.o | |||
12 | # Module Dependency | 13 | # Module Dependency |
13 | obj-$(CONFIG_SND_PDAUDIOCF) += snd-ak4117.o | 14 | obj-$(CONFIG_SND_PDAUDIOCF) += snd-ak4117.o |
14 | obj-$(CONFIG_SND_ICE1712) += snd-ak4xxx-adda.o | 15 | obj-$(CONFIG_SND_ICE1712) += snd-ak4xxx-adda.o |
15 | obj-$(CONFIG_SND_ICE1724) += snd-ak4114.o snd-ak4xxx-adda.o snd-pt2258.o | 16 | obj-$(CONFIG_SND_ICE1724) += snd-ak4114.o snd-ak4113.o snd-ak4xxx-adda.o snd-pt2258.o |
16 | obj-$(CONFIG_SND_FM801_TEA575X) += snd-tea575x-tuner.o | 17 | obj-$(CONFIG_SND_FM801_TEA575X) += snd-tea575x-tuner.o |
diff --git a/sound/i2c/other/ak4113.c b/sound/i2c/other/ak4113.c new file mode 100644 index 000000000000..fff62cc8607c --- /dev/null +++ b/sound/i2c/other/ak4113.c | |||
@@ -0,0 +1,639 @@ | |||
1 | /* | ||
2 | * Routines for control of the AK4113 via I2C/4-wire serial interface | ||
3 | * IEC958 (S/PDIF) receiver by Asahi Kasei | ||
4 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> | ||
5 | * Copyright (c) by Pavel Hofman <pavel.hofman@ivitera.com> | ||
6 | * | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
21 | * | ||
22 | */ | ||
23 | |||
24 | #include <linux/slab.h> | ||
25 | #include <linux/delay.h> | ||
26 | #include <sound/core.h> | ||
27 | #include <sound/control.h> | ||
28 | #include <sound/pcm.h> | ||
29 | #include <sound/ak4113.h> | ||
30 | #include <sound/asoundef.h> | ||
31 | #include <sound/info.h> | ||
32 | |||
33 | MODULE_AUTHOR("Pavel Hofman <pavel.hofman@ivitera.com>"); | ||
34 | MODULE_DESCRIPTION("AK4113 IEC958 (S/PDIF) receiver by Asahi Kasei"); | ||
35 | MODULE_LICENSE("GPL"); | ||
36 | |||
37 | #define AK4113_ADDR 0x00 /* fixed address */ | ||
38 | |||
39 | static void ak4113_stats(struct work_struct *work); | ||
40 | static void ak4113_init_regs(struct ak4113 *chip); | ||
41 | |||
42 | |||
43 | static void reg_write(struct ak4113 *ak4113, unsigned char reg, | ||
44 | unsigned char val) | ||
45 | { | ||
46 | ak4113->write(ak4113->private_data, reg, val); | ||
47 | if (reg < sizeof(ak4113->regmap)) | ||
48 | ak4113->regmap[reg] = val; | ||
49 | } | ||
50 | |||
51 | static inline unsigned char reg_read(struct ak4113 *ak4113, unsigned char reg) | ||
52 | { | ||
53 | return ak4113->read(ak4113->private_data, reg); | ||
54 | } | ||
55 | |||
56 | static void snd_ak4113_free(struct ak4113 *chip) | ||
57 | { | ||
58 | chip->init = 1; /* don't schedule new work */ | ||
59 | mb(); | ||
60 | cancel_delayed_work(&chip->work); | ||
61 | flush_scheduled_work(); | ||
62 | kfree(chip); | ||
63 | } | ||
64 | |||
65 | static int snd_ak4113_dev_free(struct snd_device *device) | ||
66 | { | ||
67 | struct ak4113 *chip = device->device_data; | ||
68 | snd_ak4113_free(chip); | ||
69 | return 0; | ||
70 | } | ||
71 | |||
72 | int snd_ak4113_create(struct snd_card *card, ak4113_read_t *read, | ||
73 | ak4113_write_t *write, const unsigned char pgm[5], | ||
74 | void *private_data, struct ak4113 **r_ak4113) | ||
75 | { | ||
76 | struct ak4113 *chip; | ||
77 | int err = 0; | ||
78 | unsigned char reg; | ||
79 | static struct snd_device_ops ops = { | ||
80 | .dev_free = snd_ak4113_dev_free, | ||
81 | }; | ||
82 | |||
83 | chip = kzalloc(sizeof(*chip), GFP_KERNEL); | ||
84 | if (chip == NULL) | ||
85 | return -ENOMEM; | ||
86 | spin_lock_init(&chip->lock); | ||
87 | chip->card = card; | ||
88 | chip->read = read; | ||
89 | chip->write = write; | ||
90 | chip->private_data = private_data; | ||
91 | INIT_DELAYED_WORK(&chip->work, ak4113_stats); | ||
92 | |||
93 | for (reg = 0; reg < AK4113_WRITABLE_REGS ; reg++) | ||
94 | chip->regmap[reg] = pgm[reg]; | ||
95 | ak4113_init_regs(chip); | ||
96 | |||
97 | chip->rcs0 = reg_read(chip, AK4113_REG_RCS0) & ~(AK4113_QINT | | ||
98 | AK4113_CINT | AK4113_STC); | ||
99 | chip->rcs1 = reg_read(chip, AK4113_REG_RCS1); | ||
100 | chip->rcs2 = reg_read(chip, AK4113_REG_RCS2); | ||
101 | err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops); | ||
102 | if (err < 0) | ||
103 | goto __fail; | ||
104 | |||
105 | if (r_ak4113) | ||
106 | *r_ak4113 = chip; | ||
107 | return 0; | ||
108 | |||
109 | __fail: | ||
110 | snd_ak4113_free(chip); | ||
111 | return err < 0 ? err : -EIO; | ||
112 | } | ||
113 | EXPORT_SYMBOL_GPL(snd_ak4113_create); | ||
114 | |||
115 | void snd_ak4113_reg_write(struct ak4113 *chip, unsigned char reg, | ||
116 | unsigned char mask, unsigned char val) | ||
117 | { | ||
118 | if (reg >= AK4113_WRITABLE_REGS) | ||
119 | return; | ||
120 | reg_write(chip, reg, (chip->regmap[reg] & ~mask) | val); | ||
121 | } | ||
122 | EXPORT_SYMBOL_GPL(snd_ak4113_reg_write); | ||
123 | |||
124 | static void ak4113_init_regs(struct ak4113 *chip) | ||
125 | { | ||
126 | unsigned char old = chip->regmap[AK4113_REG_PWRDN], reg; | ||
127 | |||
128 | /* bring the chip to reset state and powerdown state */ | ||
129 | reg_write(chip, AK4113_REG_PWRDN, old & ~(AK4113_RST|AK4113_PWN)); | ||
130 | udelay(200); | ||
131 | /* release reset, but leave powerdown */ | ||
132 | reg_write(chip, AK4113_REG_PWRDN, (old | AK4113_RST) & ~AK4113_PWN); | ||
133 | udelay(200); | ||
134 | for (reg = 1; reg < AK4113_WRITABLE_REGS; reg++) | ||
135 | reg_write(chip, reg, chip->regmap[reg]); | ||
136 | /* release powerdown, everything is initialized now */ | ||
137 | reg_write(chip, AK4113_REG_PWRDN, old | AK4113_RST | AK4113_PWN); | ||
138 | } | ||
139 | |||
140 | void snd_ak4113_reinit(struct ak4113 *chip) | ||
141 | { | ||
142 | chip->init = 1; | ||
143 | mb(); | ||
144 | flush_scheduled_work(); | ||
145 | ak4113_init_regs(chip); | ||
146 | /* bring up statistics / event queing */ | ||
147 | chip->init = 0; | ||
148 | if (chip->kctls[0]) | ||
149 | schedule_delayed_work(&chip->work, HZ / 10); | ||
150 | } | ||
151 | EXPORT_SYMBOL_GPL(snd_ak4113_reinit); | ||
152 | |||
153 | static unsigned int external_rate(unsigned char rcs1) | ||
154 | { | ||
155 | switch (rcs1 & (AK4113_FS0|AK4113_FS1|AK4113_FS2|AK4113_FS3)) { | ||
156 | case AK4113_FS_8000HZ: | ||
157 | return 8000; | ||
158 | case AK4113_FS_11025HZ: | ||
159 | return 11025; | ||
160 | case AK4113_FS_16000HZ: | ||
161 | return 16000; | ||
162 | case AK4113_FS_22050HZ: | ||
163 | return 22050; | ||
164 | case AK4113_FS_24000HZ: | ||
165 | return 24000; | ||
166 | case AK4113_FS_32000HZ: | ||
167 | return 32000; | ||
168 | case AK4113_FS_44100HZ: | ||
169 | return 44100; | ||
170 | case AK4113_FS_48000HZ: | ||
171 | return 48000; | ||
172 | case AK4113_FS_64000HZ: | ||
173 | return 64000; | ||
174 | case AK4113_FS_88200HZ: | ||
175 | return 88200; | ||
176 | case AK4113_FS_96000HZ: | ||
177 | return 96000; | ||
178 | case AK4113_FS_176400HZ: | ||
179 | return 176400; | ||
180 | case AK4113_FS_192000HZ: | ||
181 | return 192000; | ||
182 | default: | ||
183 | return 0; | ||
184 | } | ||
185 | } | ||
186 | |||
187 | static int snd_ak4113_in_error_info(struct snd_kcontrol *kcontrol, | ||
188 | struct snd_ctl_elem_info *uinfo) | ||
189 | { | ||
190 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | ||
191 | uinfo->count = 1; | ||
192 | uinfo->value.integer.min = 0; | ||
193 | uinfo->value.integer.max = LONG_MAX; | ||
194 | return 0; | ||
195 | } | ||
196 | |||
197 | static int snd_ak4113_in_error_get(struct snd_kcontrol *kcontrol, | ||
198 | struct snd_ctl_elem_value *ucontrol) | ||
199 | { | ||
200 | struct ak4113 *chip = snd_kcontrol_chip(kcontrol); | ||
201 | long *ptr; | ||
202 | |||
203 | spin_lock_irq(&chip->lock); | ||
204 | ptr = (long *)(((char *)chip) + kcontrol->private_value); | ||
205 | ucontrol->value.integer.value[0] = *ptr; | ||
206 | *ptr = 0; | ||
207 | spin_unlock_irq(&chip->lock); | ||
208 | return 0; | ||
209 | } | ||
210 | |||
211 | #define snd_ak4113_in_bit_info snd_ctl_boolean_mono_info | ||
212 | |||
213 | static int snd_ak4113_in_bit_get(struct snd_kcontrol *kcontrol, | ||
214 | struct snd_ctl_elem_value *ucontrol) | ||
215 | { | ||
216 | struct ak4113 *chip = snd_kcontrol_chip(kcontrol); | ||
217 | unsigned char reg = kcontrol->private_value & 0xff; | ||
218 | unsigned char bit = (kcontrol->private_value >> 8) & 0xff; | ||
219 | unsigned char inv = (kcontrol->private_value >> 31) & 1; | ||
220 | |||
221 | ucontrol->value.integer.value[0] = | ||
222 | ((reg_read(chip, reg) & (1 << bit)) ? 1 : 0) ^ inv; | ||
223 | return 0; | ||
224 | } | ||
225 | |||
226 | static int snd_ak4113_rx_info(struct snd_kcontrol *kcontrol, | ||
227 | struct snd_ctl_elem_info *uinfo) | ||
228 | { | ||
229 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | ||
230 | uinfo->count = 1; | ||
231 | uinfo->value.integer.min = 0; | ||
232 | uinfo->value.integer.max = 5; | ||
233 | return 0; | ||
234 | } | ||
235 | |||
236 | static int snd_ak4113_rx_get(struct snd_kcontrol *kcontrol, | ||
237 | struct snd_ctl_elem_value *ucontrol) | ||
238 | { | ||
239 | struct ak4113 *chip = snd_kcontrol_chip(kcontrol); | ||
240 | |||
241 | ucontrol->value.integer.value[0] = | ||
242 | (AK4113_IPS(chip->regmap[AK4113_REG_IO1])); | ||
243 | return 0; | ||
244 | } | ||
245 | |||
246 | static int snd_ak4113_rx_put(struct snd_kcontrol *kcontrol, | ||
247 | struct snd_ctl_elem_value *ucontrol) | ||
248 | { | ||
249 | struct ak4113 *chip = snd_kcontrol_chip(kcontrol); | ||
250 | int change; | ||
251 | u8 old_val; | ||
252 | |||
253 | spin_lock_irq(&chip->lock); | ||
254 | old_val = chip->regmap[AK4113_REG_IO1]; | ||
255 | change = ucontrol->value.integer.value[0] != AK4113_IPS(old_val); | ||
256 | if (change) | ||
257 | reg_write(chip, AK4113_REG_IO1, | ||
258 | (old_val & (~AK4113_IPS(0xff))) | | ||
259 | (AK4113_IPS(ucontrol->value.integer.value[0]))); | ||
260 | spin_unlock_irq(&chip->lock); | ||
261 | return change; | ||
262 | } | ||
263 | |||
264 | static int snd_ak4113_rate_info(struct snd_kcontrol *kcontrol, | ||
265 | struct snd_ctl_elem_info *uinfo) | ||
266 | { | ||
267 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | ||
268 | uinfo->count = 1; | ||
269 | uinfo->value.integer.min = 0; | ||
270 | uinfo->value.integer.max = 192000; | ||
271 | return 0; | ||
272 | } | ||
273 | |||
274 | static int snd_ak4113_rate_get(struct snd_kcontrol *kcontrol, | ||
275 | struct snd_ctl_elem_value *ucontrol) | ||
276 | { | ||
277 | struct ak4113 *chip = snd_kcontrol_chip(kcontrol); | ||
278 | |||
279 | ucontrol->value.integer.value[0] = external_rate(reg_read(chip, | ||
280 | AK4113_REG_RCS1)); | ||
281 | return 0; | ||
282 | } | ||
283 | |||
284 | static int snd_ak4113_spdif_info(struct snd_kcontrol *kcontrol, | ||
285 | struct snd_ctl_elem_info *uinfo) | ||
286 | { | ||
287 | uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; | ||
288 | uinfo->count = 1; | ||
289 | return 0; | ||
290 | } | ||
291 | |||
292 | static int snd_ak4113_spdif_get(struct snd_kcontrol *kcontrol, | ||
293 | struct snd_ctl_elem_value *ucontrol) | ||
294 | { | ||
295 | struct ak4113 *chip = snd_kcontrol_chip(kcontrol); | ||
296 | unsigned i; | ||
297 | |||
298 | for (i = 0; i < AK4113_REG_RXCSB_SIZE; i++) | ||
299 | ucontrol->value.iec958.status[i] = reg_read(chip, | ||
300 | AK4113_REG_RXCSB0 + i); | ||
301 | return 0; | ||
302 | } | ||
303 | |||
304 | static int snd_ak4113_spdif_mask_info(struct snd_kcontrol *kcontrol, | ||
305 | struct snd_ctl_elem_info *uinfo) | ||
306 | { | ||
307 | uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; | ||
308 | uinfo->count = 1; | ||
309 | return 0; | ||
310 | } | ||
311 | |||
312 | static int snd_ak4113_spdif_mask_get(struct snd_kcontrol *kcontrol, | ||
313 | struct snd_ctl_elem_value *ucontrol) | ||
314 | { | ||
315 | memset(ucontrol->value.iec958.status, 0xff, AK4113_REG_RXCSB_SIZE); | ||
316 | return 0; | ||
317 | } | ||
318 | |||
319 | static int snd_ak4113_spdif_pinfo(struct snd_kcontrol *kcontrol, | ||
320 | struct snd_ctl_elem_info *uinfo) | ||
321 | { | ||
322 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | ||
323 | uinfo->value.integer.min = 0; | ||
324 | uinfo->value.integer.max = 0xffff; | ||
325 | uinfo->count = 4; | ||
326 | return 0; | ||
327 | } | ||
328 | |||
329 | static int snd_ak4113_spdif_pget(struct snd_kcontrol *kcontrol, | ||
330 | struct snd_ctl_elem_value *ucontrol) | ||
331 | { | ||
332 | struct ak4113 *chip = snd_kcontrol_chip(kcontrol); | ||
333 | unsigned short tmp; | ||
334 | |||
335 | ucontrol->value.integer.value[0] = 0xf8f2; | ||
336 | ucontrol->value.integer.value[1] = 0x4e1f; | ||
337 | tmp = reg_read(chip, AK4113_REG_Pc0) | | ||
338 | (reg_read(chip, AK4113_REG_Pc1) << 8); | ||
339 | ucontrol->value.integer.value[2] = tmp; | ||
340 | tmp = reg_read(chip, AK4113_REG_Pd0) | | ||
341 | (reg_read(chip, AK4113_REG_Pd1) << 8); | ||
342 | ucontrol->value.integer.value[3] = tmp; | ||
343 | return 0; | ||
344 | } | ||
345 | |||
346 | static int snd_ak4113_spdif_qinfo(struct snd_kcontrol *kcontrol, | ||
347 | struct snd_ctl_elem_info *uinfo) | ||
348 | { | ||
349 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES; | ||
350 | uinfo->count = AK4113_REG_QSUB_SIZE; | ||
351 | return 0; | ||
352 | } | ||
353 | |||
354 | static int snd_ak4113_spdif_qget(struct snd_kcontrol *kcontrol, | ||
355 | struct snd_ctl_elem_value *ucontrol) | ||
356 | { | ||
357 | struct ak4113 *chip = snd_kcontrol_chip(kcontrol); | ||
358 | unsigned i; | ||
359 | |||
360 | for (i = 0; i < AK4113_REG_QSUB_SIZE; i++) | ||
361 | ucontrol->value.bytes.data[i] = reg_read(chip, | ||
362 | AK4113_REG_QSUB_ADDR + i); | ||
363 | return 0; | ||
364 | } | ||
365 | |||
366 | /* Don't forget to change AK4113_CONTROLS define!!! */ | ||
367 | static struct snd_kcontrol_new snd_ak4113_iec958_controls[] = { | ||
368 | { | ||
369 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, | ||
370 | .name = "IEC958 Parity Errors", | ||
371 | .access = SNDRV_CTL_ELEM_ACCESS_READ | | ||
372 | SNDRV_CTL_ELEM_ACCESS_VOLATILE, | ||
373 | .info = snd_ak4113_in_error_info, | ||
374 | .get = snd_ak4113_in_error_get, | ||
375 | .private_value = offsetof(struct ak4113, parity_errors), | ||
376 | }, | ||
377 | { | ||
378 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, | ||
379 | .name = "IEC958 V-Bit Errors", | ||
380 | .access = SNDRV_CTL_ELEM_ACCESS_READ | | ||
381 | SNDRV_CTL_ELEM_ACCESS_VOLATILE, | ||
382 | .info = snd_ak4113_in_error_info, | ||
383 | .get = snd_ak4113_in_error_get, | ||
384 | .private_value = offsetof(struct ak4113, v_bit_errors), | ||
385 | }, | ||
386 | { | ||
387 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, | ||
388 | .name = "IEC958 C-CRC Errors", | ||
389 | .access = SNDRV_CTL_ELEM_ACCESS_READ | | ||
390 | SNDRV_CTL_ELEM_ACCESS_VOLATILE, | ||
391 | .info = snd_ak4113_in_error_info, | ||
392 | .get = snd_ak4113_in_error_get, | ||
393 | .private_value = offsetof(struct ak4113, ccrc_errors), | ||
394 | }, | ||
395 | { | ||
396 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, | ||
397 | .name = "IEC958 Q-CRC Errors", | ||
398 | .access = SNDRV_CTL_ELEM_ACCESS_READ | | ||
399 | SNDRV_CTL_ELEM_ACCESS_VOLATILE, | ||
400 | .info = snd_ak4113_in_error_info, | ||
401 | .get = snd_ak4113_in_error_get, | ||
402 | .private_value = offsetof(struct ak4113, qcrc_errors), | ||
403 | }, | ||
404 | { | ||
405 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, | ||
406 | .name = "IEC958 External Rate", | ||
407 | .access = SNDRV_CTL_ELEM_ACCESS_READ | | ||
408 | SNDRV_CTL_ELEM_ACCESS_VOLATILE, | ||
409 | .info = snd_ak4113_rate_info, | ||
410 | .get = snd_ak4113_rate_get, | ||
411 | }, | ||
412 | { | ||
413 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, | ||
414 | .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, MASK), | ||
415 | .access = SNDRV_CTL_ELEM_ACCESS_READ, | ||
416 | .info = snd_ak4113_spdif_mask_info, | ||
417 | .get = snd_ak4113_spdif_mask_get, | ||
418 | }, | ||
419 | { | ||
420 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, | ||
421 | .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, DEFAULT), | ||
422 | .access = SNDRV_CTL_ELEM_ACCESS_READ | | ||
423 | SNDRV_CTL_ELEM_ACCESS_VOLATILE, | ||
424 | .info = snd_ak4113_spdif_info, | ||
425 | .get = snd_ak4113_spdif_get, | ||
426 | }, | ||
427 | { | ||
428 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, | ||
429 | .name = "IEC958 Preample Capture Default", | ||
430 | .access = SNDRV_CTL_ELEM_ACCESS_READ | | ||
431 | SNDRV_CTL_ELEM_ACCESS_VOLATILE, | ||
432 | .info = snd_ak4113_spdif_pinfo, | ||
433 | .get = snd_ak4113_spdif_pget, | ||
434 | }, | ||
435 | { | ||
436 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, | ||
437 | .name = "IEC958 Q-subcode Capture Default", | ||
438 | .access = SNDRV_CTL_ELEM_ACCESS_READ | | ||
439 | SNDRV_CTL_ELEM_ACCESS_VOLATILE, | ||
440 | .info = snd_ak4113_spdif_qinfo, | ||
441 | .get = snd_ak4113_spdif_qget, | ||
442 | }, | ||
443 | { | ||
444 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, | ||
445 | .name = "IEC958 Audio", | ||
446 | .access = SNDRV_CTL_ELEM_ACCESS_READ | | ||
447 | SNDRV_CTL_ELEM_ACCESS_VOLATILE, | ||
448 | .info = snd_ak4113_in_bit_info, | ||
449 | .get = snd_ak4113_in_bit_get, | ||
450 | .private_value = (1<<31) | (1<<8) | AK4113_REG_RCS0, | ||
451 | }, | ||
452 | { | ||
453 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, | ||
454 | .name = "IEC958 Non-PCM Bitstream", | ||
455 | .access = SNDRV_CTL_ELEM_ACCESS_READ | | ||
456 | SNDRV_CTL_ELEM_ACCESS_VOLATILE, | ||
457 | .info = snd_ak4113_in_bit_info, | ||
458 | .get = snd_ak4113_in_bit_get, | ||
459 | .private_value = (0<<8) | AK4113_REG_RCS1, | ||
460 | }, | ||
461 | { | ||
462 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, | ||
463 | .name = "IEC958 DTS Bitstream", | ||
464 | .access = SNDRV_CTL_ELEM_ACCESS_READ | | ||
465 | SNDRV_CTL_ELEM_ACCESS_VOLATILE, | ||
466 | .info = snd_ak4113_in_bit_info, | ||
467 | .get = snd_ak4113_in_bit_get, | ||
468 | .private_value = (1<<8) | AK4113_REG_RCS1, | ||
469 | }, | ||
470 | { | ||
471 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, | ||
472 | .name = "AK4113 Input Select", | ||
473 | .access = SNDRV_CTL_ELEM_ACCESS_READ | | ||
474 | SNDRV_CTL_ELEM_ACCESS_WRITE, | ||
475 | .info = snd_ak4113_rx_info, | ||
476 | .get = snd_ak4113_rx_get, | ||
477 | .put = snd_ak4113_rx_put, | ||
478 | } | ||
479 | }; | ||
480 | |||
481 | static void snd_ak4113_proc_regs_read(struct snd_info_entry *entry, | ||
482 | struct snd_info_buffer *buffer) | ||
483 | { | ||
484 | struct ak4113 *ak4113 = entry->private_data; | ||
485 | int reg, val; | ||
486 | /* all ak4113 registers 0x00 - 0x1c */ | ||
487 | for (reg = 0; reg < 0x1d; reg++) { | ||
488 | val = reg_read(ak4113, reg); | ||
489 | snd_iprintf(buffer, "0x%02x = 0x%02x\n", reg, val); | ||
490 | } | ||
491 | } | ||
492 | |||
493 | static void snd_ak4113_proc_init(struct ak4113 *ak4113) | ||
494 | { | ||
495 | struct snd_info_entry *entry; | ||
496 | if (!snd_card_proc_new(ak4113->card, "ak4113", &entry)) | ||
497 | snd_info_set_text_ops(entry, ak4113, snd_ak4113_proc_regs_read); | ||
498 | } | ||
499 | |||
500 | int snd_ak4113_build(struct ak4113 *ak4113, | ||
501 | struct snd_pcm_substream *cap_substream) | ||
502 | { | ||
503 | struct snd_kcontrol *kctl; | ||
504 | unsigned int idx; | ||
505 | int err; | ||
506 | |||
507 | if (snd_BUG_ON(!cap_substream)) | ||
508 | return -EINVAL; | ||
509 | ak4113->substream = cap_substream; | ||
510 | for (idx = 0; idx < AK4113_CONTROLS; idx++) { | ||
511 | kctl = snd_ctl_new1(&snd_ak4113_iec958_controls[idx], ak4113); | ||
512 | if (kctl == NULL) | ||
513 | return -ENOMEM; | ||
514 | kctl->id.device = cap_substream->pcm->device; | ||
515 | kctl->id.subdevice = cap_substream->number; | ||
516 | err = snd_ctl_add(ak4113->card, kctl); | ||
517 | if (err < 0) | ||
518 | return err; | ||
519 | ak4113->kctls[idx] = kctl; | ||
520 | } | ||
521 | snd_ak4113_proc_init(ak4113); | ||
522 | /* trigger workq */ | ||
523 | schedule_delayed_work(&ak4113->work, HZ / 10); | ||
524 | return 0; | ||
525 | } | ||
526 | EXPORT_SYMBOL_GPL(snd_ak4113_build); | ||
527 | |||
528 | int snd_ak4113_external_rate(struct ak4113 *ak4113) | ||
529 | { | ||
530 | unsigned char rcs1; | ||
531 | |||
532 | rcs1 = reg_read(ak4113, AK4113_REG_RCS1); | ||
533 | return external_rate(rcs1); | ||
534 | } | ||
535 | EXPORT_SYMBOL_GPL(snd_ak4113_external_rate); | ||
536 | |||
537 | int snd_ak4113_check_rate_and_errors(struct ak4113 *ak4113, unsigned int flags) | ||
538 | { | ||
539 | struct snd_pcm_runtime *runtime = | ||
540 | ak4113->substream ? ak4113->substream->runtime : NULL; | ||
541 | unsigned long _flags; | ||
542 | int res = 0; | ||
543 | unsigned char rcs0, rcs1, rcs2; | ||
544 | unsigned char c0, c1; | ||
545 | |||
546 | rcs1 = reg_read(ak4113, AK4113_REG_RCS1); | ||
547 | if (flags & AK4113_CHECK_NO_STAT) | ||
548 | goto __rate; | ||
549 | rcs0 = reg_read(ak4113, AK4113_REG_RCS0); | ||
550 | rcs2 = reg_read(ak4113, AK4113_REG_RCS2); | ||
551 | spin_lock_irqsave(&ak4113->lock, _flags); | ||
552 | if (rcs0 & AK4113_PAR) | ||
553 | ak4113->parity_errors++; | ||
554 | if (rcs0 & AK4113_V) | ||
555 | ak4113->v_bit_errors++; | ||
556 | if (rcs2 & AK4113_CCRC) | ||
557 | ak4113->ccrc_errors++; | ||
558 | if (rcs2 & AK4113_QCRC) | ||
559 | ak4113->qcrc_errors++; | ||
560 | c0 = (ak4113->rcs0 & (AK4113_QINT | AK4113_CINT | AK4113_STC | | ||
561 | AK4113_AUDION | AK4113_AUTO | AK4113_UNLCK)) ^ | ||
562 | (rcs0 & (AK4113_QINT | AK4113_CINT | AK4113_STC | | ||
563 | AK4113_AUDION | AK4113_AUTO | AK4113_UNLCK)); | ||
564 | c1 = (ak4113->rcs1 & (AK4113_DTSCD | AK4113_NPCM | AK4113_PEM | | ||
565 | AK4113_DAT | 0xf0)) ^ | ||
566 | (rcs1 & (AK4113_DTSCD | AK4113_NPCM | AK4113_PEM | | ||
567 | AK4113_DAT | 0xf0)); | ||
568 | ak4113->rcs0 = rcs0 & ~(AK4113_QINT | AK4113_CINT | AK4113_STC); | ||
569 | ak4113->rcs1 = rcs1; | ||
570 | ak4113->rcs2 = rcs2; | ||
571 | spin_unlock_irqrestore(&ak4113->lock, _flags); | ||
572 | |||
573 | if (rcs0 & AK4113_PAR) | ||
574 | snd_ctl_notify(ak4113->card, SNDRV_CTL_EVENT_MASK_VALUE, | ||
575 | &ak4113->kctls[0]->id); | ||
576 | if (rcs0 & AK4113_V) | ||
577 | snd_ctl_notify(ak4113->card, SNDRV_CTL_EVENT_MASK_VALUE, | ||
578 | &ak4113->kctls[1]->id); | ||
579 | if (rcs2 & AK4113_CCRC) | ||
580 | snd_ctl_notify(ak4113->card, SNDRV_CTL_EVENT_MASK_VALUE, | ||
581 | &ak4113->kctls[2]->id); | ||
582 | if (rcs2 & AK4113_QCRC) | ||
583 | snd_ctl_notify(ak4113->card, SNDRV_CTL_EVENT_MASK_VALUE, | ||
584 | &ak4113->kctls[3]->id); | ||
585 | |||
586 | /* rate change */ | ||
587 | if (c1 & 0xf0) | ||
588 | snd_ctl_notify(ak4113->card, SNDRV_CTL_EVENT_MASK_VALUE, | ||
589 | &ak4113->kctls[4]->id); | ||
590 | |||
591 | if ((c1 & AK4113_PEM) | (c0 & AK4113_CINT)) | ||
592 | snd_ctl_notify(ak4113->card, SNDRV_CTL_EVENT_MASK_VALUE, | ||
593 | &ak4113->kctls[6]->id); | ||
594 | if (c0 & AK4113_QINT) | ||
595 | snd_ctl_notify(ak4113->card, SNDRV_CTL_EVENT_MASK_VALUE, | ||
596 | &ak4113->kctls[8]->id); | ||
597 | |||
598 | if (c0 & AK4113_AUDION) | ||
599 | snd_ctl_notify(ak4113->card, SNDRV_CTL_EVENT_MASK_VALUE, | ||
600 | &ak4113->kctls[9]->id); | ||
601 | if (c1 & AK4113_NPCM) | ||
602 | snd_ctl_notify(ak4113->card, SNDRV_CTL_EVENT_MASK_VALUE, | ||
603 | &ak4113->kctls[10]->id); | ||
604 | if (c1 & AK4113_DTSCD) | ||
605 | snd_ctl_notify(ak4113->card, SNDRV_CTL_EVENT_MASK_VALUE, | ||
606 | &ak4113->kctls[11]->id); | ||
607 | |||
608 | if (ak4113->change_callback && (c0 | c1) != 0) | ||
609 | ak4113->change_callback(ak4113, c0, c1); | ||
610 | |||
611 | __rate: | ||
612 | /* compare rate */ | ||
613 | res = external_rate(rcs1); | ||
614 | if (!(flags & AK4113_CHECK_NO_RATE) && runtime && | ||
615 | (runtime->rate != res)) { | ||
616 | snd_pcm_stream_lock_irqsave(ak4113->substream, _flags); | ||
617 | if (snd_pcm_running(ak4113->substream)) { | ||
618 | /*printk(KERN_DEBUG "rate changed (%i <- %i)\n", | ||
619 | * runtime->rate, res); */ | ||
620 | snd_pcm_stop(ak4113->substream, | ||
621 | SNDRV_PCM_STATE_DRAINING); | ||
622 | wake_up(&runtime->sleep); | ||
623 | res = 1; | ||
624 | } | ||
625 | snd_pcm_stream_unlock_irqrestore(ak4113->substream, _flags); | ||
626 | } | ||
627 | return res; | ||
628 | } | ||
629 | EXPORT_SYMBOL_GPL(snd_ak4113_check_rate_and_errors); | ||
630 | |||
631 | static void ak4113_stats(struct work_struct *work) | ||
632 | { | ||
633 | struct ak4113 *chip = container_of(work, struct ak4113, work.work); | ||
634 | |||
635 | if (!chip->init) | ||
636 | snd_ak4113_check_rate_and_errors(chip, chip->check_flags); | ||
637 | |||
638 | schedule_delayed_work(&chip->work, HZ / 10); | ||
639 | } | ||
diff --git a/sound/i2c/other/ak4xxx-adda.c b/sound/i2c/other/ak4xxx-adda.c index ee47abab764e..1adb8a3c2b62 100644 --- a/sound/i2c/other/ak4xxx-adda.c +++ b/sound/i2c/other/ak4xxx-adda.c | |||
@@ -19,7 +19,7 @@ | |||
19 | * along with this program; if not, write to the Free Software | 19 | * along with this program; if not, write to the Free Software |
20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
21 | * | 21 | * |
22 | */ | 22 | */ |
23 | 23 | ||
24 | #include <asm/io.h> | 24 | #include <asm/io.h> |
25 | #include <linux/delay.h> | 25 | #include <linux/delay.h> |
@@ -29,6 +29,7 @@ | |||
29 | #include <sound/control.h> | 29 | #include <sound/control.h> |
30 | #include <sound/tlv.h> | 30 | #include <sound/tlv.h> |
31 | #include <sound/ak4xxx-adda.h> | 31 | #include <sound/ak4xxx-adda.h> |
32 | #include <sound/info.h> | ||
32 | 33 | ||
33 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>, Takashi Iwai <tiwai@suse.de>"); | 34 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>, Takashi Iwai <tiwai@suse.de>"); |
34 | MODULE_DESCRIPTION("Routines for control of AK452x / AK43xx AD/DA converters"); | 35 | MODULE_DESCRIPTION("Routines for control of AK452x / AK43xx AD/DA converters"); |
@@ -52,26 +53,21 @@ EXPORT_SYMBOL(snd_akm4xxx_write); | |||
52 | static void ak4524_reset(struct snd_akm4xxx *ak, int state) | 53 | static void ak4524_reset(struct snd_akm4xxx *ak, int state) |
53 | { | 54 | { |
54 | unsigned int chip; | 55 | unsigned int chip; |
55 | unsigned char reg, maxreg; | 56 | unsigned char reg; |
56 | 57 | ||
57 | if (ak->type == SND_AK4528) | ||
58 | maxreg = 0x06; | ||
59 | else | ||
60 | maxreg = 0x08; | ||
61 | for (chip = 0; chip < ak->num_dacs/2; chip++) { | 58 | for (chip = 0; chip < ak->num_dacs/2; chip++) { |
62 | snd_akm4xxx_write(ak, chip, 0x01, state ? 0x00 : 0x03); | 59 | snd_akm4xxx_write(ak, chip, 0x01, state ? 0x00 : 0x03); |
63 | if (state) | 60 | if (state) |
64 | continue; | 61 | continue; |
65 | /* DAC volumes */ | 62 | /* DAC volumes */ |
66 | for (reg = 0x04; reg < maxreg; reg++) | 63 | for (reg = 0x04; reg < ak->total_regs; reg++) |
67 | snd_akm4xxx_write(ak, chip, reg, | 64 | snd_akm4xxx_write(ak, chip, reg, |
68 | snd_akm4xxx_get(ak, chip, reg)); | 65 | snd_akm4xxx_get(ak, chip, reg)); |
69 | } | 66 | } |
70 | } | 67 | } |
71 | 68 | ||
72 | /* reset procedure for AK4355 and AK4358 */ | 69 | /* reset procedure for AK4355 and AK4358 */ |
73 | static void ak435X_reset(struct snd_akm4xxx *ak, int state, | 70 | static void ak435X_reset(struct snd_akm4xxx *ak, int state) |
74 | unsigned char total_regs) | ||
75 | { | 71 | { |
76 | unsigned char reg; | 72 | unsigned char reg; |
77 | 73 | ||
@@ -79,7 +75,7 @@ static void ak435X_reset(struct snd_akm4xxx *ak, int state, | |||
79 | snd_akm4xxx_write(ak, 0, 0x01, 0x02); /* reset and soft-mute */ | 75 | snd_akm4xxx_write(ak, 0, 0x01, 0x02); /* reset and soft-mute */ |
80 | return; | 76 | return; |
81 | } | 77 | } |
82 | for (reg = 0x00; reg < total_regs; reg++) | 78 | for (reg = 0x00; reg < ak->total_regs; reg++) |
83 | if (reg != 0x01) | 79 | if (reg != 0x01) |
84 | snd_akm4xxx_write(ak, 0, reg, | 80 | snd_akm4xxx_write(ak, 0, reg, |
85 | snd_akm4xxx_get(ak, 0, reg)); | 81 | snd_akm4xxx_get(ak, 0, reg)); |
@@ -91,12 +87,11 @@ static void ak4381_reset(struct snd_akm4xxx *ak, int state) | |||
91 | { | 87 | { |
92 | unsigned int chip; | 88 | unsigned int chip; |
93 | unsigned char reg; | 89 | unsigned char reg; |
94 | |||
95 | for (chip = 0; chip < ak->num_dacs/2; chip++) { | 90 | for (chip = 0; chip < ak->num_dacs/2; chip++) { |
96 | snd_akm4xxx_write(ak, chip, 0x00, state ? 0x0c : 0x0f); | 91 | snd_akm4xxx_write(ak, chip, 0x00, state ? 0x0c : 0x0f); |
97 | if (state) | 92 | if (state) |
98 | continue; | 93 | continue; |
99 | for (reg = 0x01; reg < 0x05; reg++) | 94 | for (reg = 0x01; reg < ak->total_regs; reg++) |
100 | snd_akm4xxx_write(ak, chip, reg, | 95 | snd_akm4xxx_write(ak, chip, reg, |
101 | snd_akm4xxx_get(ak, chip, reg)); | 96 | snd_akm4xxx_get(ak, chip, reg)); |
102 | } | 97 | } |
@@ -113,16 +108,17 @@ void snd_akm4xxx_reset(struct snd_akm4xxx *ak, int state) | |||
113 | switch (ak->type) { | 108 | switch (ak->type) { |
114 | case SND_AK4524: | 109 | case SND_AK4524: |
115 | case SND_AK4528: | 110 | case SND_AK4528: |
111 | case SND_AK4620: | ||
116 | ak4524_reset(ak, state); | 112 | ak4524_reset(ak, state); |
117 | break; | 113 | break; |
118 | case SND_AK4529: | 114 | case SND_AK4529: |
119 | /* FIXME: needed for ak4529? */ | 115 | /* FIXME: needed for ak4529? */ |
120 | break; | 116 | break; |
121 | case SND_AK4355: | 117 | case SND_AK4355: |
122 | ak435X_reset(ak, state, 0x0b); | 118 | ak435X_reset(ak, state); |
123 | break; | 119 | break; |
124 | case SND_AK4358: | 120 | case SND_AK4358: |
125 | ak435X_reset(ak, state, 0x10); | 121 | ak435X_reset(ak, state); |
126 | break; | 122 | break; |
127 | case SND_AK4381: | 123 | case SND_AK4381: |
128 | ak4381_reset(ak, state); | 124 | ak4381_reset(ak, state); |
@@ -139,7 +135,7 @@ EXPORT_SYMBOL(snd_akm4xxx_reset); | |||
139 | * Volume conversion table for non-linear volumes | 135 | * Volume conversion table for non-linear volumes |
140 | * from -63.5dB (mute) to 0dB step 0.5dB | 136 | * from -63.5dB (mute) to 0dB step 0.5dB |
141 | * | 137 | * |
142 | * Used for AK4524 input/ouput attenuation, AK4528, and | 138 | * Used for AK4524/AK4620 input/ouput attenuation, AK4528, and |
143 | * AK5365 input attenuation | 139 | * AK5365 input attenuation |
144 | */ | 140 | */ |
145 | static const unsigned char vol_cvt_datt[128] = { | 141 | static const unsigned char vol_cvt_datt[128] = { |
@@ -259,8 +255,22 @@ void snd_akm4xxx_init(struct snd_akm4xxx *ak) | |||
259 | 0x00, 0x0f, /* 0: power-up, un-reset */ | 255 | 0x00, 0x0f, /* 0: power-up, un-reset */ |
260 | 0xff, 0xff | 256 | 0xff, 0xff |
261 | }; | 257 | }; |
258 | static const unsigned char inits_ak4620[] = { | ||
259 | 0x00, 0x07, /* 0: normal */ | ||
260 | 0x01, 0x00, /* 0: reset */ | ||
261 | 0x01, 0x02, /* 1: RSTAD */ | ||
262 | 0x01, 0x03, /* 1: RSTDA */ | ||
263 | 0x01, 0x0f, /* 1: normal */ | ||
264 | 0x02, 0x60, /* 2: 24bit I2S */ | ||
265 | 0x03, 0x01, /* 3: deemphasis off */ | ||
266 | 0x04, 0x00, /* 4: LIN muted */ | ||
267 | 0x05, 0x00, /* 5: RIN muted */ | ||
268 | 0x06, 0x00, /* 6: LOUT muted */ | ||
269 | 0x07, 0x00, /* 7: ROUT muted */ | ||
270 | 0xff, 0xff | ||
271 | }; | ||
262 | 272 | ||
263 | int chip, num_chips; | 273 | int chip; |
264 | const unsigned char *ptr, *inits; | 274 | const unsigned char *ptr, *inits; |
265 | unsigned char reg, data; | 275 | unsigned char reg, data; |
266 | 276 | ||
@@ -270,42 +280,64 @@ void snd_akm4xxx_init(struct snd_akm4xxx *ak) | |||
270 | switch (ak->type) { | 280 | switch (ak->type) { |
271 | case SND_AK4524: | 281 | case SND_AK4524: |
272 | inits = inits_ak4524; | 282 | inits = inits_ak4524; |
273 | num_chips = ak->num_dacs / 2; | 283 | ak->num_chips = ak->num_dacs / 2; |
284 | ak->name = "ak4524"; | ||
285 | ak->total_regs = 0x08; | ||
274 | break; | 286 | break; |
275 | case SND_AK4528: | 287 | case SND_AK4528: |
276 | inits = inits_ak4528; | 288 | inits = inits_ak4528; |
277 | num_chips = ak->num_dacs / 2; | 289 | ak->num_chips = ak->num_dacs / 2; |
290 | ak->name = "ak4528"; | ||
291 | ak->total_regs = 0x06; | ||
278 | break; | 292 | break; |
279 | case SND_AK4529: | 293 | case SND_AK4529: |
280 | inits = inits_ak4529; | 294 | inits = inits_ak4529; |
281 | num_chips = 1; | 295 | ak->num_chips = 1; |
296 | ak->name = "ak4529"; | ||
297 | ak->total_regs = 0x0d; | ||
282 | break; | 298 | break; |
283 | case SND_AK4355: | 299 | case SND_AK4355: |
284 | inits = inits_ak4355; | 300 | inits = inits_ak4355; |
285 | num_chips = 1; | 301 | ak->num_chips = 1; |
302 | ak->name = "ak4355"; | ||
303 | ak->total_regs = 0x0b; | ||
286 | break; | 304 | break; |
287 | case SND_AK4358: | 305 | case SND_AK4358: |
288 | inits = inits_ak4358; | 306 | inits = inits_ak4358; |
289 | num_chips = 1; | 307 | ak->num_chips = 1; |
308 | ak->name = "ak4358"; | ||
309 | ak->total_regs = 0x10; | ||
290 | break; | 310 | break; |
291 | case SND_AK4381: | 311 | case SND_AK4381: |
292 | inits = inits_ak4381; | 312 | inits = inits_ak4381; |
293 | num_chips = ak->num_dacs / 2; | 313 | ak->num_chips = ak->num_dacs / 2; |
314 | ak->name = "ak4381"; | ||
315 | ak->total_regs = 0x05; | ||
294 | break; | 316 | break; |
295 | case SND_AK5365: | 317 | case SND_AK5365: |
296 | /* FIXME: any init sequence? */ | 318 | /* FIXME: any init sequence? */ |
319 | ak->num_chips = 1; | ||
320 | ak->name = "ak5365"; | ||
321 | ak->total_regs = 0x08; | ||
297 | return; | 322 | return; |
323 | case SND_AK4620: | ||
324 | inits = inits_ak4620; | ||
325 | ak->num_chips = ak->num_dacs / 2; | ||
326 | ak->name = "ak4620"; | ||
327 | ak->total_regs = 0x08; | ||
328 | break; | ||
298 | default: | 329 | default: |
299 | snd_BUG(); | 330 | snd_BUG(); |
300 | return; | 331 | return; |
301 | } | 332 | } |
302 | 333 | ||
303 | for (chip = 0; chip < num_chips; chip++) { | 334 | for (chip = 0; chip < ak->num_chips; chip++) { |
304 | ptr = inits; | 335 | ptr = inits; |
305 | while (*ptr != 0xff) { | 336 | while (*ptr != 0xff) { |
306 | reg = *ptr++; | 337 | reg = *ptr++; |
307 | data = *ptr++; | 338 | data = *ptr++; |
308 | snd_akm4xxx_write(ak, chip, reg, data); | 339 | snd_akm4xxx_write(ak, chip, reg, data); |
340 | udelay(10); | ||
309 | } | 341 | } |
310 | } | 342 | } |
311 | } | 343 | } |
@@ -688,6 +720,12 @@ static int build_dac_controls(struct snd_akm4xxx *ak) | |||
688 | AK_COMPOSE(idx/2, (idx%2) + 3, 0, 255); | 720 | AK_COMPOSE(idx/2, (idx%2) + 3, 0, 255); |
689 | knew.tlv.p = db_scale_linear; | 721 | knew.tlv.p = db_scale_linear; |
690 | break; | 722 | break; |
723 | case SND_AK4620: | ||
724 | /* register 6 & 7 */ | ||
725 | knew.private_value = | ||
726 | AK_COMPOSE(idx/2, (idx%2) + 6, 0, 255); | ||
727 | knew.tlv.p = db_scale_linear; | ||
728 | break; | ||
691 | default: | 729 | default: |
692 | return -EINVAL; | 730 | return -EINVAL; |
693 | } | 731 | } |
@@ -704,10 +742,12 @@ static int build_dac_controls(struct snd_akm4xxx *ak) | |||
704 | 742 | ||
705 | static int build_adc_controls(struct snd_akm4xxx *ak) | 743 | static int build_adc_controls(struct snd_akm4xxx *ak) |
706 | { | 744 | { |
707 | int idx, err, mixer_ch, num_stereo; | 745 | int idx, err, mixer_ch, num_stereo, max_steps; |
708 | struct snd_kcontrol_new knew; | 746 | struct snd_kcontrol_new knew; |
709 | 747 | ||
710 | mixer_ch = 0; | 748 | mixer_ch = 0; |
749 | if (ak->type == SND_AK4528) | ||
750 | return 0; /* no controls */ | ||
711 | for (idx = 0; idx < ak->num_adcs;) { | 751 | for (idx = 0; idx < ak->num_adcs;) { |
712 | memset(&knew, 0, sizeof(knew)); | 752 | memset(&knew, 0, sizeof(knew)); |
713 | if (! ak->adc_info || ! ak->adc_info[mixer_ch].name) { | 753 | if (! ak->adc_info || ! ak->adc_info[mixer_ch].name) { |
@@ -733,13 +773,12 @@ static int build_adc_controls(struct snd_akm4xxx *ak) | |||
733 | } | 773 | } |
734 | /* register 4 & 5 */ | 774 | /* register 4 & 5 */ |
735 | if (ak->type == SND_AK5365) | 775 | if (ak->type == SND_AK5365) |
736 | knew.private_value = | 776 | max_steps = 152; |
737 | AK_COMPOSE(idx/2, (idx%2) + 4, 0, 151) | | ||
738 | AK_VOL_CVT | AK_IPGA; | ||
739 | else | 777 | else |
740 | knew.private_value = | 778 | max_steps = 164; |
741 | AK_COMPOSE(idx/2, (idx%2) + 4, 0, 163) | | 779 | knew.private_value = |
742 | AK_VOL_CVT | AK_IPGA; | 780 | AK_COMPOSE(idx/2, (idx%2) + 4, 0, max_steps) | |
781 | AK_VOL_CVT | AK_IPGA; | ||
743 | knew.tlv.p = db_scale_vol_datt; | 782 | knew.tlv.p = db_scale_vol_datt; |
744 | err = snd_ctl_add(ak->card, snd_ctl_new1(&knew, ak)); | 783 | err = snd_ctl_add(ak->card, snd_ctl_new1(&knew, ak)); |
745 | if (err < 0) | 784 | if (err < 0) |
@@ -808,6 +847,7 @@ static int build_deemphasis(struct snd_akm4xxx *ak, int num_emphs) | |||
808 | switch (ak->type) { | 847 | switch (ak->type) { |
809 | case SND_AK4524: | 848 | case SND_AK4524: |
810 | case SND_AK4528: | 849 | case SND_AK4528: |
850 | case SND_AK4620: | ||
811 | /* register 3 */ | 851 | /* register 3 */ |
812 | knew.private_value = AK_COMPOSE(idx, 3, 0, 0); | 852 | knew.private_value = AK_COMPOSE(idx, 3, 0, 0); |
813 | break; | 853 | break; |
@@ -834,6 +874,35 @@ static int build_deemphasis(struct snd_akm4xxx *ak, int num_emphs) | |||
834 | return 0; | 874 | return 0; |
835 | } | 875 | } |
836 | 876 | ||
877 | #ifdef CONFIG_PROC_FS | ||
878 | static void proc_regs_read(struct snd_info_entry *entry, | ||
879 | struct snd_info_buffer *buffer) | ||
880 | { | ||
881 | struct snd_akm4xxx *ak = (struct snd_akm4xxx *)entry->private_data; | ||
882 | int reg, val, chip; | ||
883 | for (chip = 0; chip < ak->num_chips; chip++) { | ||
884 | for (reg = 0; reg < ak->total_regs; reg++) { | ||
885 | val = snd_akm4xxx_get(ak, chip, reg); | ||
886 | snd_iprintf(buffer, "chip %d: 0x%02x = 0x%02x\n", chip, | ||
887 | reg, val); | ||
888 | } | ||
889 | } | ||
890 | } | ||
891 | |||
892 | static int proc_init(struct snd_akm4xxx *ak) | ||
893 | { | ||
894 | struct snd_info_entry *entry; | ||
895 | int err; | ||
896 | err = snd_card_proc_new(ak->card, ak->name, &entry); | ||
897 | if (err < 0) | ||
898 | return err; | ||
899 | snd_info_set_text_ops(entry, ak, proc_regs_read); | ||
900 | return 0; | ||
901 | } | ||
902 | #else /* !CONFIG_PROC_FS */ | ||
903 | static int proc_init(struct snd_akm4xxx *ak) {} | ||
904 | #endif | ||
905 | |||
837 | int snd_akm4xxx_build_controls(struct snd_akm4xxx *ak) | 906 | int snd_akm4xxx_build_controls(struct snd_akm4xxx *ak) |
838 | { | 907 | { |
839 | int err, num_emphs; | 908 | int err, num_emphs; |
@@ -845,18 +914,21 @@ int snd_akm4xxx_build_controls(struct snd_akm4xxx *ak) | |||
845 | err = build_adc_controls(ak); | 914 | err = build_adc_controls(ak); |
846 | if (err < 0) | 915 | if (err < 0) |
847 | return err; | 916 | return err; |
848 | |||
849 | if (ak->type == SND_AK4355 || ak->type == SND_AK4358) | 917 | if (ak->type == SND_AK4355 || ak->type == SND_AK4358) |
850 | num_emphs = 1; | 918 | num_emphs = 1; |
919 | else if (ak->type == SND_AK4620) | ||
920 | num_emphs = 0; | ||
851 | else | 921 | else |
852 | num_emphs = ak->num_dacs / 2; | 922 | num_emphs = ak->num_dacs / 2; |
853 | err = build_deemphasis(ak, num_emphs); | 923 | err = build_deemphasis(ak, num_emphs); |
854 | if (err < 0) | 924 | if (err < 0) |
855 | return err; | 925 | return err; |
926 | err = proc_init(ak); | ||
927 | if (err < 0) | ||
928 | return err; | ||
856 | 929 | ||
857 | return 0; | 930 | return 0; |
858 | } | 931 | } |
859 | |||
860 | EXPORT_SYMBOL(snd_akm4xxx_build_controls); | 932 | EXPORT_SYMBOL(snd_akm4xxx_build_controls); |
861 | 933 | ||
862 | static int __init alsa_akm4xxx_module_init(void) | 934 | static int __init alsa_akm4xxx_module_init(void) |
diff --git a/sound/pci/ice1712/Makefile b/sound/pci/ice1712/Makefile index 536eae2ccf94..f7ce33f00ea5 100644 --- a/sound/pci/ice1712/Makefile +++ b/sound/pci/ice1712/Makefile | |||
@@ -5,7 +5,7 @@ | |||
5 | 5 | ||
6 | snd-ice17xx-ak4xxx-objs := ak4xxx.o | 6 | snd-ice17xx-ak4xxx-objs := ak4xxx.o |
7 | snd-ice1712-objs := ice1712.o delta.o hoontech.o ews.o | 7 | snd-ice1712-objs := ice1712.o delta.o hoontech.o ews.o |
8 | snd-ice1724-objs := ice1724.o amp.o revo.o aureon.o vt1720_mobo.o pontis.o prodigy192.o prodigy_hifi.o juli.o phase.o wtm.o se.o maya44.o | 8 | snd-ice1724-objs := ice1724.o amp.o revo.o aureon.o vt1720_mobo.o pontis.o prodigy192.o prodigy_hifi.o juli.o phase.o wtm.o se.o maya44.o quartet.o |
9 | 9 | ||
10 | # Toplevel Module Dependency | 10 | # Toplevel Module Dependency |
11 | obj-$(CONFIG_SND_ICE1712) += snd-ice1712.o snd-ice17xx-ak4xxx.o | 11 | obj-$(CONFIG_SND_ICE1712) += snd-ice1712.o snd-ice17xx-ak4xxx.o |
diff --git a/sound/pci/ice1712/ice1712.c b/sound/pci/ice1712/ice1712.c index d74033a2cfbe..c7cff6f8168a 100644 --- a/sound/pci/ice1712/ice1712.c +++ b/sound/pci/ice1712/ice1712.c | |||
@@ -298,6 +298,16 @@ static void snd_ice1712_set_gpio_dir(struct snd_ice1712 *ice, unsigned int data) | |||
298 | inb(ICEREG(ice, DATA)); /* dummy read for pci-posting */ | 298 | inb(ICEREG(ice, DATA)); /* dummy read for pci-posting */ |
299 | } | 299 | } |
300 | 300 | ||
301 | static unsigned int snd_ice1712_get_gpio_dir(struct snd_ice1712 *ice) | ||
302 | { | ||
303 | return snd_ice1712_read(ice, ICE1712_IREG_GPIO_DIRECTION); | ||
304 | } | ||
305 | |||
306 | static unsigned int snd_ice1712_get_gpio_mask(struct snd_ice1712 *ice) | ||
307 | { | ||
308 | return snd_ice1712_read(ice, ICE1712_IREG_GPIO_WRITE_MASK); | ||
309 | } | ||
310 | |||
301 | static void snd_ice1712_set_gpio_mask(struct snd_ice1712 *ice, unsigned int data) | 311 | static void snd_ice1712_set_gpio_mask(struct snd_ice1712 *ice, unsigned int data) |
302 | { | 312 | { |
303 | snd_ice1712_write(ice, ICE1712_IREG_GPIO_WRITE_MASK, data); | 313 | snd_ice1712_write(ice, ICE1712_IREG_GPIO_WRITE_MASK, data); |
@@ -2557,7 +2567,9 @@ static int __devinit snd_ice1712_create(struct snd_card *card, | |||
2557 | mutex_init(&ice->i2c_mutex); | 2567 | mutex_init(&ice->i2c_mutex); |
2558 | mutex_init(&ice->open_mutex); | 2568 | mutex_init(&ice->open_mutex); |
2559 | ice->gpio.set_mask = snd_ice1712_set_gpio_mask; | 2569 | ice->gpio.set_mask = snd_ice1712_set_gpio_mask; |
2570 | ice->gpio.get_mask = snd_ice1712_get_gpio_mask; | ||
2560 | ice->gpio.set_dir = snd_ice1712_set_gpio_dir; | 2571 | ice->gpio.set_dir = snd_ice1712_set_gpio_dir; |
2572 | ice->gpio.get_dir = snd_ice1712_get_gpio_dir; | ||
2561 | ice->gpio.set_data = snd_ice1712_set_gpio_data; | 2573 | ice->gpio.set_data = snd_ice1712_set_gpio_data; |
2562 | ice->gpio.get_data = snd_ice1712_get_gpio_data; | 2574 | ice->gpio.get_data = snd_ice1712_get_gpio_data; |
2563 | 2575 | ||
diff --git a/sound/pci/ice1712/ice1712.h b/sound/pci/ice1712/ice1712.h index 9da2dae64c5b..4615bca39e18 100644 --- a/sound/pci/ice1712/ice1712.h +++ b/sound/pci/ice1712/ice1712.h | |||
@@ -359,7 +359,9 @@ struct snd_ice1712 { | |||
359 | unsigned int saved[2]; /* for ewx_i2c */ | 359 | unsigned int saved[2]; /* for ewx_i2c */ |
360 | /* operators */ | 360 | /* operators */ |
361 | void (*set_mask)(struct snd_ice1712 *ice, unsigned int data); | 361 | void (*set_mask)(struct snd_ice1712 *ice, unsigned int data); |
362 | unsigned int (*get_mask)(struct snd_ice1712 *ice); | ||
362 | void (*set_dir)(struct snd_ice1712 *ice, unsigned int data); | 363 | void (*set_dir)(struct snd_ice1712 *ice, unsigned int data); |
364 | unsigned int (*get_dir)(struct snd_ice1712 *ice); | ||
363 | void (*set_data)(struct snd_ice1712 *ice, unsigned int data); | 365 | void (*set_data)(struct snd_ice1712 *ice, unsigned int data); |
364 | unsigned int (*get_data)(struct snd_ice1712 *ice); | 366 | unsigned int (*get_data)(struct snd_ice1712 *ice); |
365 | /* misc operators - move to another place? */ | 367 | /* misc operators - move to another place? */ |
@@ -377,8 +379,11 @@ struct snd_ice1712 { | |||
377 | unsigned int (*get_rate)(struct snd_ice1712 *ice); | 379 | unsigned int (*get_rate)(struct snd_ice1712 *ice); |
378 | void (*set_rate)(struct snd_ice1712 *ice, unsigned int rate); | 380 | void (*set_rate)(struct snd_ice1712 *ice, unsigned int rate); |
379 | unsigned char (*set_mclk)(struct snd_ice1712 *ice, unsigned int rate); | 381 | unsigned char (*set_mclk)(struct snd_ice1712 *ice, unsigned int rate); |
380 | void (*set_spdif_clock)(struct snd_ice1712 *ice); | 382 | int (*set_spdif_clock)(struct snd_ice1712 *ice, int type); |
381 | 383 | int (*get_spdif_master_type)(struct snd_ice1712 *ice); | |
384 | char **ext_clock_names; | ||
385 | int ext_clock_count; | ||
386 | void (*pro_open)(struct snd_ice1712 *, struct snd_pcm_substream *); | ||
382 | #ifdef CONFIG_PM | 387 | #ifdef CONFIG_PM |
383 | int (*pm_suspend)(struct snd_ice1712 *); | 388 | int (*pm_suspend)(struct snd_ice1712 *); |
384 | int (*pm_resume)(struct snd_ice1712 *); | 389 | int (*pm_resume)(struct snd_ice1712 *); |
@@ -399,6 +404,11 @@ static inline void snd_ice1712_gpio_set_dir(struct snd_ice1712 *ice, unsigned in | |||
399 | ice->gpio.set_dir(ice, bits); | 404 | ice->gpio.set_dir(ice, bits); |
400 | } | 405 | } |
401 | 406 | ||
407 | static inline unsigned int snd_ice1712_gpio_get_dir(struct snd_ice1712 *ice) | ||
408 | { | ||
409 | return ice->gpio.get_dir(ice); | ||
410 | } | ||
411 | |||
402 | static inline void snd_ice1712_gpio_set_mask(struct snd_ice1712 *ice, unsigned int bits) | 412 | static inline void snd_ice1712_gpio_set_mask(struct snd_ice1712 *ice, unsigned int bits) |
403 | { | 413 | { |
404 | ice->gpio.set_mask(ice, bits); | 414 | ice->gpio.set_mask(ice, bits); |
diff --git a/sound/pci/ice1712/ice1724.c b/sound/pci/ice1712/ice1724.c index 10fc92c05574..ae29073eea93 100644 --- a/sound/pci/ice1712/ice1724.c +++ b/sound/pci/ice1712/ice1724.c | |||
@@ -53,6 +53,7 @@ | |||
53 | #include "phase.h" | 53 | #include "phase.h" |
54 | #include "wtm.h" | 54 | #include "wtm.h" |
55 | #include "se.h" | 55 | #include "se.h" |
56 | #include "quartet.h" | ||
56 | 57 | ||
57 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); | 58 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); |
58 | MODULE_DESCRIPTION("VIA ICEnsemble ICE1724/1720 (Envy24HT/PT)"); | 59 | MODULE_DESCRIPTION("VIA ICEnsemble ICE1724/1720 (Envy24HT/PT)"); |
@@ -70,6 +71,7 @@ MODULE_SUPPORTED_DEVICE("{" | |||
70 | PHASE_DEVICE_DESC | 71 | PHASE_DEVICE_DESC |
71 | WTM_DEVICE_DESC | 72 | WTM_DEVICE_DESC |
72 | SE_DEVICE_DESC | 73 | SE_DEVICE_DESC |
74 | QTET_DEVICE_DESC | ||
73 | "{VIA,VT1720}," | 75 | "{VIA,VT1720}," |
74 | "{VIA,VT1724}," | 76 | "{VIA,VT1724}," |
75 | "{ICEnsemble,Generic ICE1724}," | 77 | "{ICEnsemble,Generic ICE1724}," |
@@ -104,6 +106,8 @@ static int PRO_RATE_LOCKED; | |||
104 | static int PRO_RATE_RESET = 1; | 106 | static int PRO_RATE_RESET = 1; |
105 | static unsigned int PRO_RATE_DEFAULT = 44100; | 107 | static unsigned int PRO_RATE_DEFAULT = 44100; |
106 | 108 | ||
109 | static char *ext_clock_names[1] = { "IEC958 In" }; | ||
110 | |||
107 | /* | 111 | /* |
108 | * Basic I/O | 112 | * Basic I/O |
109 | */ | 113 | */ |
@@ -118,9 +122,12 @@ static inline int stdclock_is_spdif_master(struct snd_ice1712 *ice) | |||
118 | return (inb(ICEMT1724(ice, RATE)) & VT1724_SPDIF_MASTER) ? 1 : 0; | 122 | return (inb(ICEMT1724(ice, RATE)) & VT1724_SPDIF_MASTER) ? 1 : 0; |
119 | } | 123 | } |
120 | 124 | ||
125 | /* | ||
126 | * locking rate makes sense only for internal clock mode | ||
127 | */ | ||
121 | static inline int is_pro_rate_locked(struct snd_ice1712 *ice) | 128 | static inline int is_pro_rate_locked(struct snd_ice1712 *ice) |
122 | { | 129 | { |
123 | return ice->is_spdif_master(ice) || PRO_RATE_LOCKED; | 130 | return (!ice->is_spdif_master(ice)) && PRO_RATE_LOCKED; |
124 | } | 131 | } |
125 | 132 | ||
126 | /* | 133 | /* |
@@ -196,6 +203,12 @@ static void snd_vt1724_set_gpio_dir(struct snd_ice1712 *ice, unsigned int data) | |||
196 | inw(ICEREG1724(ice, GPIO_DIRECTION)); /* dummy read for pci-posting */ | 203 | inw(ICEREG1724(ice, GPIO_DIRECTION)); /* dummy read for pci-posting */ |
197 | } | 204 | } |
198 | 205 | ||
206 | /* get gpio direction 0 = read, 1 = write */ | ||
207 | static unsigned int snd_vt1724_get_gpio_dir(struct snd_ice1712 *ice) | ||
208 | { | ||
209 | return inl(ICEREG1724(ice, GPIO_DIRECTION)); | ||
210 | } | ||
211 | |||
199 | /* set the gpio mask (0 = writable) */ | 212 | /* set the gpio mask (0 = writable) */ |
200 | static void snd_vt1724_set_gpio_mask(struct snd_ice1712 *ice, unsigned int data) | 213 | static void snd_vt1724_set_gpio_mask(struct snd_ice1712 *ice, unsigned int data) |
201 | { | 214 | { |
@@ -205,6 +218,17 @@ static void snd_vt1724_set_gpio_mask(struct snd_ice1712 *ice, unsigned int data) | |||
205 | inw(ICEREG1724(ice, GPIO_WRITE_MASK)); /* dummy read for pci-posting */ | 218 | inw(ICEREG1724(ice, GPIO_WRITE_MASK)); /* dummy read for pci-posting */ |
206 | } | 219 | } |
207 | 220 | ||
221 | static unsigned int snd_vt1724_get_gpio_mask(struct snd_ice1712 *ice) | ||
222 | { | ||
223 | unsigned int mask; | ||
224 | if (!ice->vt1720) | ||
225 | mask = (unsigned int)inb(ICEREG1724(ice, GPIO_WRITE_MASK_22)); | ||
226 | else | ||
227 | mask = 0; | ||
228 | mask = (mask << 16) | inw(ICEREG1724(ice, GPIO_WRITE_MASK)); | ||
229 | return mask; | ||
230 | } | ||
231 | |||
208 | static void snd_vt1724_set_gpio_data(struct snd_ice1712 *ice, unsigned int data) | 232 | static void snd_vt1724_set_gpio_data(struct snd_ice1712 *ice, unsigned int data) |
209 | { | 233 | { |
210 | outw(data, ICEREG1724(ice, GPIO_DATA)); | 234 | outw(data, ICEREG1724(ice, GPIO_DATA)); |
@@ -651,16 +675,22 @@ static int snd_vt1724_set_pro_rate(struct snd_ice1712 *ice, unsigned int rate, | |||
651 | return ((rate == ice->cur_rate) && !force) ? 0 : -EBUSY; | 675 | return ((rate == ice->cur_rate) && !force) ? 0 : -EBUSY; |
652 | } | 676 | } |
653 | if (!force && is_pro_rate_locked(ice)) { | 677 | if (!force && is_pro_rate_locked(ice)) { |
678 | /* comparing required and current rate - makes sense for | ||
679 | * internal clock only */ | ||
654 | spin_unlock_irqrestore(&ice->reg_lock, flags); | 680 | spin_unlock_irqrestore(&ice->reg_lock, flags); |
655 | return (rate == ice->cur_rate) ? 0 : -EBUSY; | 681 | return (rate == ice->cur_rate) ? 0 : -EBUSY; |
656 | } | 682 | } |
657 | 683 | ||
658 | old_rate = ice->get_rate(ice); | 684 | if (force || !ice->is_spdif_master(ice)) { |
659 | if (force || (old_rate != rate)) | 685 | /* force means the rate was switched by ucontrol, otherwise |
660 | ice->set_rate(ice, rate); | 686 | * setting clock rate for internal clock mode */ |
661 | else if (rate == ice->cur_rate) { | 687 | old_rate = ice->get_rate(ice); |
662 | spin_unlock_irqrestore(&ice->reg_lock, flags); | 688 | if (force || (old_rate != rate)) |
663 | return 0; | 689 | ice->set_rate(ice, rate); |
690 | else if (rate == ice->cur_rate) { | ||
691 | spin_unlock_irqrestore(&ice->reg_lock, flags); | ||
692 | return 0; | ||
693 | } | ||
664 | } | 694 | } |
665 | 695 | ||
666 | ice->cur_rate = rate; | 696 | ice->cur_rate = rate; |
@@ -1016,6 +1046,8 @@ static int snd_vt1724_playback_pro_open(struct snd_pcm_substream *substream) | |||
1016 | VT1724_BUFFER_ALIGN); | 1046 | VT1724_BUFFER_ALIGN); |
1017 | snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, | 1047 | snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, |
1018 | VT1724_BUFFER_ALIGN); | 1048 | VT1724_BUFFER_ALIGN); |
1049 | if (ice->pro_open) | ||
1050 | ice->pro_open(ice, substream); | ||
1019 | return 0; | 1051 | return 0; |
1020 | } | 1052 | } |
1021 | 1053 | ||
@@ -1034,6 +1066,8 @@ static int snd_vt1724_capture_pro_open(struct snd_pcm_substream *substream) | |||
1034 | VT1724_BUFFER_ALIGN); | 1066 | VT1724_BUFFER_ALIGN); |
1035 | snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, | 1067 | snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, |
1036 | VT1724_BUFFER_ALIGN); | 1068 | VT1724_BUFFER_ALIGN); |
1069 | if (ice->pro_open) | ||
1070 | ice->pro_open(ice, substream); | ||
1037 | return 0; | 1071 | return 0; |
1038 | } | 1072 | } |
1039 | 1073 | ||
@@ -1787,15 +1821,21 @@ static int snd_vt1724_pro_internal_clock_info(struct snd_kcontrol *kcontrol, | |||
1787 | struct snd_ctl_elem_info *uinfo) | 1821 | struct snd_ctl_elem_info *uinfo) |
1788 | { | 1822 | { |
1789 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); | 1823 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); |
1790 | 1824 | int hw_rates_count = ice->hw_rates->count; | |
1791 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | 1825 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; |
1792 | uinfo->count = 1; | 1826 | uinfo->count = 1; |
1793 | uinfo->value.enumerated.items = ice->hw_rates->count + 1; | 1827 | |
1828 | uinfo->value.enumerated.items = hw_rates_count + ice->ext_clock_count; | ||
1829 | /* upper limit - keep at top */ | ||
1794 | if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) | 1830 | if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) |
1795 | uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1; | 1831 | uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1; |
1796 | if (uinfo->value.enumerated.item == uinfo->value.enumerated.items - 1) | 1832 | if (uinfo->value.enumerated.item >= hw_rates_count) |
1797 | strcpy(uinfo->value.enumerated.name, "IEC958 Input"); | 1833 | /* ext_clock items */ |
1834 | strcpy(uinfo->value.enumerated.name, | ||
1835 | ice->ext_clock_names[ | ||
1836 | uinfo->value.enumerated.item - hw_rates_count]); | ||
1798 | else | 1837 | else |
1838 | /* int clock items */ | ||
1799 | sprintf(uinfo->value.enumerated.name, "%d", | 1839 | sprintf(uinfo->value.enumerated.name, "%d", |
1800 | ice->hw_rates->list[uinfo->value.enumerated.item]); | 1840 | ice->hw_rates->list[uinfo->value.enumerated.item]); |
1801 | return 0; | 1841 | return 0; |
@@ -1809,7 +1849,8 @@ static int snd_vt1724_pro_internal_clock_get(struct snd_kcontrol *kcontrol, | |||
1809 | 1849 | ||
1810 | spin_lock_irq(&ice->reg_lock); | 1850 | spin_lock_irq(&ice->reg_lock); |
1811 | if (ice->is_spdif_master(ice)) { | 1851 | if (ice->is_spdif_master(ice)) { |
1812 | ucontrol->value.enumerated.item[0] = ice->hw_rates->count; | 1852 | ucontrol->value.enumerated.item[0] = ice->hw_rates->count + |
1853 | ice->get_spdif_master_type(ice); | ||
1813 | } else { | 1854 | } else { |
1814 | rate = ice->get_rate(ice); | 1855 | rate = ice->get_rate(ice); |
1815 | ucontrol->value.enumerated.item[0] = 0; | 1856 | ucontrol->value.enumerated.item[0] = 0; |
@@ -1824,8 +1865,14 @@ static int snd_vt1724_pro_internal_clock_get(struct snd_kcontrol *kcontrol, | |||
1824 | return 0; | 1865 | return 0; |
1825 | } | 1866 | } |
1826 | 1867 | ||
1868 | static int stdclock_get_spdif_master_type(struct snd_ice1712 *ice) | ||
1869 | { | ||
1870 | /* standard external clock - only single type - SPDIF IN */ | ||
1871 | return 0; | ||
1872 | } | ||
1873 | |||
1827 | /* setting clock to external - SPDIF */ | 1874 | /* setting clock to external - SPDIF */ |
1828 | static void stdclock_set_spdif_clock(struct snd_ice1712 *ice) | 1875 | static int stdclock_set_spdif_clock(struct snd_ice1712 *ice, int type) |
1829 | { | 1876 | { |
1830 | unsigned char oval; | 1877 | unsigned char oval; |
1831 | unsigned char i2s_oval; | 1878 | unsigned char i2s_oval; |
@@ -1834,27 +1881,30 @@ static void stdclock_set_spdif_clock(struct snd_ice1712 *ice) | |||
1834 | /* setting 256fs */ | 1881 | /* setting 256fs */ |
1835 | i2s_oval = inb(ICEMT1724(ice, I2S_FORMAT)); | 1882 | i2s_oval = inb(ICEMT1724(ice, I2S_FORMAT)); |
1836 | outb(i2s_oval & ~VT1724_MT_I2S_MCLK_128X, ICEMT1724(ice, I2S_FORMAT)); | 1883 | outb(i2s_oval & ~VT1724_MT_I2S_MCLK_128X, ICEMT1724(ice, I2S_FORMAT)); |
1884 | return 0; | ||
1837 | } | 1885 | } |
1838 | 1886 | ||
1887 | |||
1839 | static int snd_vt1724_pro_internal_clock_put(struct snd_kcontrol *kcontrol, | 1888 | static int snd_vt1724_pro_internal_clock_put(struct snd_kcontrol *kcontrol, |
1840 | struct snd_ctl_elem_value *ucontrol) | 1889 | struct snd_ctl_elem_value *ucontrol) |
1841 | { | 1890 | { |
1842 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); | 1891 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); |
1843 | unsigned int old_rate, new_rate; | 1892 | unsigned int old_rate, new_rate; |
1844 | unsigned int item = ucontrol->value.enumerated.item[0]; | 1893 | unsigned int item = ucontrol->value.enumerated.item[0]; |
1845 | unsigned int spdif = ice->hw_rates->count; | 1894 | unsigned int first_ext_clock = ice->hw_rates->count; |
1846 | 1895 | ||
1847 | if (item > spdif) | 1896 | if (item > first_ext_clock + ice->ext_clock_count - 1) |
1848 | return -EINVAL; | 1897 | return -EINVAL; |
1849 | 1898 | ||
1899 | /* if rate = 0 => external clock */ | ||
1850 | spin_lock_irq(&ice->reg_lock); | 1900 | spin_lock_irq(&ice->reg_lock); |
1851 | if (ice->is_spdif_master(ice)) | 1901 | if (ice->is_spdif_master(ice)) |
1852 | old_rate = 0; | 1902 | old_rate = 0; |
1853 | else | 1903 | else |
1854 | old_rate = ice->get_rate(ice); | 1904 | old_rate = ice->get_rate(ice); |
1855 | if (item == spdif) { | 1905 | if (item >= first_ext_clock) { |
1856 | /* switching to external clock via SPDIF */ | 1906 | /* switching to external clock */ |
1857 | ice->set_spdif_clock(ice); | 1907 | ice->set_spdif_clock(ice, item - first_ext_clock); |
1858 | new_rate = 0; | 1908 | new_rate = 0; |
1859 | } else { | 1909 | } else { |
1860 | /* internal on-card clock */ | 1910 | /* internal on-card clock */ |
@@ -1866,7 +1916,7 @@ static int snd_vt1724_pro_internal_clock_put(struct snd_kcontrol *kcontrol, | |||
1866 | } | 1916 | } |
1867 | spin_unlock_irq(&ice->reg_lock); | 1917 | spin_unlock_irq(&ice->reg_lock); |
1868 | 1918 | ||
1869 | /* the first reset to the SPDIF master mode? */ | 1919 | /* the first switch to the ext. clock mode? */ |
1870 | if (old_rate != new_rate && !new_rate) { | 1920 | if (old_rate != new_rate && !new_rate) { |
1871 | /* notify akm chips as well */ | 1921 | /* notify akm chips as well */ |
1872 | unsigned int i; | 1922 | unsigned int i; |
@@ -2136,6 +2186,7 @@ static struct snd_ice1712_card_info *card_tables[] __devinitdata = { | |||
2136 | snd_vt1724_phase_cards, | 2186 | snd_vt1724_phase_cards, |
2137 | snd_vt1724_wtm_cards, | 2187 | snd_vt1724_wtm_cards, |
2138 | snd_vt1724_se_cards, | 2188 | snd_vt1724_se_cards, |
2189 | snd_vt1724_qtet_cards, | ||
2139 | NULL, | 2190 | NULL, |
2140 | }; | 2191 | }; |
2141 | 2192 | ||
@@ -2434,7 +2485,9 @@ static int __devinit snd_vt1724_create(struct snd_card *card, | |||
2434 | mutex_init(&ice->open_mutex); | 2485 | mutex_init(&ice->open_mutex); |
2435 | mutex_init(&ice->i2c_mutex); | 2486 | mutex_init(&ice->i2c_mutex); |
2436 | ice->gpio.set_mask = snd_vt1724_set_gpio_mask; | 2487 | ice->gpio.set_mask = snd_vt1724_set_gpio_mask; |
2488 | ice->gpio.get_mask = snd_vt1724_get_gpio_mask; | ||
2437 | ice->gpio.set_dir = snd_vt1724_set_gpio_dir; | 2489 | ice->gpio.set_dir = snd_vt1724_set_gpio_dir; |
2490 | ice->gpio.get_dir = snd_vt1724_get_gpio_dir; | ||
2438 | ice->gpio.set_data = snd_vt1724_set_gpio_data; | 2491 | ice->gpio.set_data = snd_vt1724_set_gpio_data; |
2439 | ice->gpio.get_data = snd_vt1724_get_gpio_data; | 2492 | ice->gpio.get_data = snd_vt1724_get_gpio_data; |
2440 | ice->card = card; | 2493 | ice->card = card; |
@@ -2522,6 +2575,9 @@ static int __devinit snd_vt1724_probe(struct pci_dev *pci, | |||
2522 | return err; | 2575 | return err; |
2523 | } | 2576 | } |
2524 | 2577 | ||
2578 | /* field init before calling chip_init */ | ||
2579 | ice->ext_clock_count = 0; | ||
2580 | |||
2525 | for (tbl = card_tables; *tbl; tbl++) { | 2581 | for (tbl = card_tables; *tbl; tbl++) { |
2526 | for (c = *tbl; c->subvendor; c++) { | 2582 | for (c = *tbl; c->subvendor; c++) { |
2527 | if (c->subvendor == ice->eeprom.subvendor) { | 2583 | if (c->subvendor == ice->eeprom.subvendor) { |
@@ -2560,6 +2616,13 @@ __found: | |||
2560 | ice->set_mclk = stdclock_set_mclk; | 2616 | ice->set_mclk = stdclock_set_mclk; |
2561 | if (!ice->set_spdif_clock) | 2617 | if (!ice->set_spdif_clock) |
2562 | ice->set_spdif_clock = stdclock_set_spdif_clock; | 2618 | ice->set_spdif_clock = stdclock_set_spdif_clock; |
2619 | if (!ice->get_spdif_master_type) | ||
2620 | ice->get_spdif_master_type = stdclock_get_spdif_master_type; | ||
2621 | if (!ice->ext_clock_names) | ||
2622 | ice->ext_clock_names = ext_clock_names; | ||
2623 | if (!ice->ext_clock_count) | ||
2624 | ice->ext_clock_count = ARRAY_SIZE(ext_clock_names); | ||
2625 | |||
2563 | if (!ice->hw_rates) | 2626 | if (!ice->hw_rates) |
2564 | set_std_hw_rates(ice); | 2627 | set_std_hw_rates(ice); |
2565 | 2628 | ||
@@ -2719,7 +2782,7 @@ static int snd_vt1724_resume(struct pci_dev *pci) | |||
2719 | 2782 | ||
2720 | if (ice->pm_saved_is_spdif_master) { | 2783 | if (ice->pm_saved_is_spdif_master) { |
2721 | /* switching to external clock via SPDIF */ | 2784 | /* switching to external clock via SPDIF */ |
2722 | ice->set_spdif_clock(ice); | 2785 | ice->set_spdif_clock(ice, 0); |
2723 | } else { | 2786 | } else { |
2724 | /* internal on-card clock */ | 2787 | /* internal on-card clock */ |
2725 | snd_vt1724_set_pro_rate(ice, ice->pro_rate_default, 1); | 2788 | snd_vt1724_set_pro_rate(ice, ice->pro_rate_default, 1); |
diff --git a/sound/pci/ice1712/juli.c b/sound/pci/ice1712/juli.c index fd948bfd9aef..4bed9633a4cd 100644 --- a/sound/pci/ice1712/juli.c +++ b/sound/pci/ice1712/juli.c | |||
@@ -412,25 +412,6 @@ static struct snd_kcontrol_new juli_mute_controls[] __devinitdata = { | |||
412 | }, | 412 | }, |
413 | }; | 413 | }; |
414 | 414 | ||
415 | |||
416 | static void ak4358_proc_regs_read(struct snd_info_entry *entry, | ||
417 | struct snd_info_buffer *buffer) | ||
418 | { | ||
419 | struct snd_ice1712 *ice = (struct snd_ice1712 *)entry->private_data; | ||
420 | int reg, val; | ||
421 | for (reg = 0; reg <= 0xf; reg++) { | ||
422 | val = snd_akm4xxx_get(ice->akm, 0, reg); | ||
423 | snd_iprintf(buffer, "0x%02x = 0x%02x\n", reg, val); | ||
424 | } | ||
425 | } | ||
426 | |||
427 | static void ak4358_proc_init(struct snd_ice1712 *ice) | ||
428 | { | ||
429 | struct snd_info_entry *entry; | ||
430 | if (!snd_card_proc_new(ice->card, "ak4358_codec", &entry)) | ||
431 | snd_info_set_text_ops(entry, ice, ak4358_proc_regs_read); | ||
432 | } | ||
433 | |||
434 | static char *slave_vols[] __devinitdata = { | 415 | static char *slave_vols[] __devinitdata = { |
435 | PCM_VOLUME, | 416 | PCM_VOLUME, |
436 | MONITOR_AN_IN_VOLUME, | 417 | MONITOR_AN_IN_VOLUME, |
@@ -496,8 +477,6 @@ static int __devinit juli_add_controls(struct snd_ice1712 *ice) | |||
496 | /* only capture SPDIF over AK4114 */ | 477 | /* only capture SPDIF over AK4114 */ |
497 | err = snd_ak4114_build(spec->ak4114, NULL, | 478 | err = snd_ak4114_build(spec->ak4114, NULL, |
498 | ice->pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream); | 479 | ice->pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream); |
499 | |||
500 | ak4358_proc_init(ice); | ||
501 | if (err < 0) | 480 | if (err < 0) |
502 | return err; | 481 | return err; |
503 | return 0; | 482 | return 0; |
@@ -550,13 +529,14 @@ static inline unsigned char juli_set_mclk(struct snd_ice1712 *ice, | |||
550 | } | 529 | } |
551 | 530 | ||
552 | /* setting clock to external - SPDIF */ | 531 | /* setting clock to external - SPDIF */ |
553 | static void juli_set_spdif_clock(struct snd_ice1712 *ice) | 532 | static int juli_set_spdif_clock(struct snd_ice1712 *ice, int type) |
554 | { | 533 | { |
555 | unsigned int old; | 534 | unsigned int old; |
556 | old = ice->gpio.get_data(ice); | 535 | old = ice->gpio.get_data(ice); |
557 | /* external clock (= 0), multiply 1x, 48kHz */ | 536 | /* external clock (= 0), multiply 1x, 48kHz */ |
558 | ice->gpio.set_data(ice, (old & ~GPIO_RATE_MASK) | GPIO_MULTI_1X | | 537 | ice->gpio.set_data(ice, (old & ~GPIO_RATE_MASK) | GPIO_MULTI_1X | |
559 | GPIO_FREQ_48KHZ); | 538 | GPIO_FREQ_48KHZ); |
539 | return 0; | ||
560 | } | 540 | } |
561 | 541 | ||
562 | /* Called when ak4114 detects change in the input SPDIF stream */ | 542 | /* Called when ak4114 detects change in the input SPDIF stream */ |
diff --git a/sound/pci/ice1712/quartet.c b/sound/pci/ice1712/quartet.c new file mode 100644 index 000000000000..1948632787e6 --- /dev/null +++ b/sound/pci/ice1712/quartet.c | |||
@@ -0,0 +1,1130 @@ | |||
1 | /* | ||
2 | * ALSA driver for ICEnsemble VT1724 (Envy24HT) | ||
3 | * | ||
4 | * Lowlevel functions for Infrasonic Quartet | ||
5 | * | ||
6 | * Copyright (c) 2009 Pavel Hofman <pavel.hofman@ivitera.com> | ||
7 | * | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
22 | * | ||
23 | */ | ||
24 | |||
25 | #include <asm/io.h> | ||
26 | #include <linux/delay.h> | ||
27 | #include <linux/interrupt.h> | ||
28 | #include <linux/init.h> | ||
29 | #include <linux/slab.h> | ||
30 | #include <sound/core.h> | ||
31 | #include <sound/tlv.h> | ||
32 | #include <sound/info.h> | ||
33 | |||
34 | #include "ice1712.h" | ||
35 | #include "envy24ht.h" | ||
36 | #include <sound/ak4113.h> | ||
37 | #include "quartet.h" | ||
38 | |||
39 | struct qtet_spec { | ||
40 | struct ak4113 *ak4113; | ||
41 | unsigned int scr; /* system control register */ | ||
42 | unsigned int mcr; /* monitoring control register */ | ||
43 | unsigned int cpld; /* cpld register */ | ||
44 | }; | ||
45 | |||
46 | struct qtet_kcontrol_private { | ||
47 | unsigned int bit; | ||
48 | void (*set_register)(struct snd_ice1712 *ice, unsigned int val); | ||
49 | unsigned int (*get_register)(struct snd_ice1712 *ice); | ||
50 | unsigned char *texts[2]; | ||
51 | }; | ||
52 | |||
53 | enum { | ||
54 | IN12_SEL = 0, | ||
55 | IN34_SEL, | ||
56 | AIN34_SEL, | ||
57 | COAX_OUT, | ||
58 | IN12_MON12, | ||
59 | IN12_MON34, | ||
60 | IN34_MON12, | ||
61 | IN34_MON34, | ||
62 | OUT12_MON34, | ||
63 | OUT34_MON12, | ||
64 | }; | ||
65 | |||
66 | static char *ext_clock_names[3] = {"IEC958 In", "Word Clock 1xFS", | ||
67 | "Word Clock 256xFS"}; | ||
68 | |||
69 | /* chip address on I2C bus */ | ||
70 | #define AK4113_ADDR 0x26 /* S/PDIF receiver */ | ||
71 | |||
72 | /* chip address on SPI bus */ | ||
73 | #define AK4620_ADDR 0x02 /* ADC/DAC */ | ||
74 | |||
75 | |||
76 | /* | ||
77 | * GPIO pins | ||
78 | */ | ||
79 | |||
80 | /* GPIO0 - O - DATA0, def. 0 */ | ||
81 | #define GPIO_D0 (1<<0) | ||
82 | /* GPIO1 - I/O - DATA1, Jack Detect Input0 (0:present, 1:missing), def. 1 */ | ||
83 | #define GPIO_D1_JACKDTC0 (1<<1) | ||
84 | /* GPIO2 - I/O - DATA2, Jack Detect Input1 (0:present, 1:missing), def. 1 */ | ||
85 | #define GPIO_D2_JACKDTC1 (1<<2) | ||
86 | /* GPIO3 - I/O - DATA3, def. 1 */ | ||
87 | #define GPIO_D3 (1<<3) | ||
88 | /* GPIO4 - I/O - DATA4, SPI CDTO, def. 1 */ | ||
89 | #define GPIO_D4_SPI_CDTO (1<<4) | ||
90 | /* GPIO5 - I/O - DATA5, SPI CCLK, def. 1 */ | ||
91 | #define GPIO_D5_SPI_CCLK (1<<5) | ||
92 | /* GPIO6 - I/O - DATA6, Cable Detect Input (0:detected, 1:not detected */ | ||
93 | #define GPIO_D6_CD (1<<6) | ||
94 | /* GPIO7 - I/O - DATA7, Device Detect Input (0:detected, 1:not detected */ | ||
95 | #define GPIO_D7_DD (1<<7) | ||
96 | /* GPIO8 - O - CPLD Chip Select, def. 1 */ | ||
97 | #define GPIO_CPLD_CSN (1<<8) | ||
98 | /* GPIO9 - O - CPLD register read/write (0:write, 1:read), def. 0 */ | ||
99 | #define GPIO_CPLD_RW (1<<9) | ||
100 | /* GPIO10 - O - SPI Chip Select for CODEC#0, def. 1 */ | ||
101 | #define GPIO_SPI_CSN0 (1<<10) | ||
102 | /* GPIO11 - O - SPI Chip Select for CODEC#1, def. 1 */ | ||
103 | #define GPIO_SPI_CSN1 (1<<11) | ||
104 | /* GPIO12 - O - Ex. Register Output Enable (0:enable, 1:disable), def. 1, | ||
105 | * init 0 */ | ||
106 | #define GPIO_EX_GPIOE (1<<12) | ||
107 | /* GPIO13 - O - Ex. Register0 Chip Select for System Control Register, | ||
108 | * def. 1 */ | ||
109 | #define GPIO_SCR (1<<13) | ||
110 | /* GPIO14 - O - Ex. Register1 Chip Select for Monitor Control Register, | ||
111 | * def. 1 */ | ||
112 | #define GPIO_MCR (1<<14) | ||
113 | |||
114 | #define GPIO_SPI_ALL (GPIO_D4_SPI_CDTO | GPIO_D5_SPI_CCLK |\ | ||
115 | GPIO_SPI_CSN0 | GPIO_SPI_CSN1) | ||
116 | |||
117 | #define GPIO_DATA_MASK (GPIO_D0 | GPIO_D1_JACKDTC0 | \ | ||
118 | GPIO_D2_JACKDTC1 | GPIO_D3 | \ | ||
119 | GPIO_D4_SPI_CDTO | GPIO_D5_SPI_CCLK | \ | ||
120 | GPIO_D6_CD | GPIO_D7_DD) | ||
121 | |||
122 | /* System Control Register GPIO_SCR data bits */ | ||
123 | /* Mic/Line select relay (0:line, 1:mic) */ | ||
124 | #define SCR_RELAY GPIO_D0 | ||
125 | /* Phantom power drive control (0:5V, 1:48V) */ | ||
126 | #define SCR_PHP_V GPIO_D1_JACKDTC0 | ||
127 | /* H/W mute control (0:Normal, 1:Mute) */ | ||
128 | #define SCR_MUTE GPIO_D2_JACKDTC1 | ||
129 | /* Phantom power control (0:Phantom on, 1:off) */ | ||
130 | #define SCR_PHP GPIO_D3 | ||
131 | /* Analog input 1/2 Source Select */ | ||
132 | #define SCR_AIN12_SEL0 GPIO_D4_SPI_CDTO | ||
133 | #define SCR_AIN12_SEL1 GPIO_D5_SPI_CCLK | ||
134 | /* Analog input 3/4 Source Select (0:line, 1:hi-z) */ | ||
135 | #define SCR_AIN34_SEL GPIO_D6_CD | ||
136 | /* Codec Power Down (0:power down, 1:normal) */ | ||
137 | #define SCR_CODEC_PDN GPIO_D7_DD | ||
138 | |||
139 | #define SCR_AIN12_LINE (0) | ||
140 | #define SCR_AIN12_MIC (SCR_AIN12_SEL0) | ||
141 | #define SCR_AIN12_LOWCUT (SCR_AIN12_SEL1 | SCR_AIN12_SEL0) | ||
142 | |||
143 | /* Monitor Control Register GPIO_MCR data bits */ | ||
144 | /* Input 1/2 to Monitor 1/2 (0:off, 1:on) */ | ||
145 | #define MCR_IN12_MON12 GPIO_D0 | ||
146 | /* Input 1/2 to Monitor 3/4 (0:off, 1:on) */ | ||
147 | #define MCR_IN12_MON34 GPIO_D1_JACKDTC0 | ||
148 | /* Input 3/4 to Monitor 1/2 (0:off, 1:on) */ | ||
149 | #define MCR_IN34_MON12 GPIO_D2_JACKDTC1 | ||
150 | /* Input 3/4 to Monitor 3/4 (0:off, 1:on) */ | ||
151 | #define MCR_IN34_MON34 GPIO_D3 | ||
152 | /* Output to Monitor 1/2 (0:off, 1:on) */ | ||
153 | #define MCR_OUT34_MON12 GPIO_D4_SPI_CDTO | ||
154 | /* Output to Monitor 3/4 (0:off, 1:on) */ | ||
155 | #define MCR_OUT12_MON34 GPIO_D5_SPI_CCLK | ||
156 | |||
157 | /* CPLD Register DATA bits */ | ||
158 | /* Clock Rate Select */ | ||
159 | #define CPLD_CKS0 GPIO_D0 | ||
160 | #define CPLD_CKS1 GPIO_D1_JACKDTC0 | ||
161 | #define CPLD_CKS2 GPIO_D2_JACKDTC1 | ||
162 | /* Sync Source Select (0:Internal, 1:External) */ | ||
163 | #define CPLD_SYNC_SEL GPIO_D3 | ||
164 | /* Word Clock FS Select (0:FS, 1:256FS) */ | ||
165 | #define CPLD_WORD_SEL GPIO_D4_SPI_CDTO | ||
166 | /* Coaxial Output Source (IS-Link) (0:SPDIF, 1:I2S) */ | ||
167 | #define CPLD_COAX_OUT GPIO_D5_SPI_CCLK | ||
168 | /* Input 1/2 Source Select (0:Analog12, 1:An34) */ | ||
169 | #define CPLD_IN12_SEL GPIO_D6_CD | ||
170 | /* Input 3/4 Source Select (0:Analog34, 1:Digital In) */ | ||
171 | #define CPLD_IN34_SEL GPIO_D7_DD | ||
172 | |||
173 | /* internal clock (CPLD_SYNC_SEL = 0) options */ | ||
174 | #define CPLD_CKS_44100HZ (0) | ||
175 | #define CPLD_CKS_48000HZ (CPLD_CKS0) | ||
176 | #define CPLD_CKS_88200HZ (CPLD_CKS1) | ||
177 | #define CPLD_CKS_96000HZ (CPLD_CKS1 | CPLD_CKS0) | ||
178 | #define CPLD_CKS_176400HZ (CPLD_CKS2) | ||
179 | #define CPLD_CKS_192000HZ (CPLD_CKS2 | CPLD_CKS0) | ||
180 | |||
181 | #define CPLD_CKS_MASK (CPLD_CKS0 | CPLD_CKS1 | CPLD_CKS2) | ||
182 | |||
183 | /* external clock (CPLD_SYNC_SEL = 1) options */ | ||
184 | /* external clock - SPDIF */ | ||
185 | #define CPLD_EXT_SPDIF (0 | CPLD_SYNC_SEL) | ||
186 | /* external clock - WordClock 1xfs */ | ||
187 | #define CPLD_EXT_WORDCLOCK_1FS (CPLD_CKS1 | CPLD_SYNC_SEL) | ||
188 | /* external clock - WordClock 256xfs */ | ||
189 | #define CPLD_EXT_WORDCLOCK_256FS (CPLD_CKS1 | CPLD_WORD_SEL |\ | ||
190 | CPLD_SYNC_SEL) | ||
191 | |||
192 | #define EXT_SPDIF_TYPE 0 | ||
193 | #define EXT_WORDCLOCK_1FS_TYPE 1 | ||
194 | #define EXT_WORDCLOCK_256FS_TYPE 2 | ||
195 | |||
196 | #define AK4620_DFS0 (1<<0) | ||
197 | #define AK4620_DFS1 (1<<1) | ||
198 | #define AK4620_CKS0 (1<<2) | ||
199 | #define AK4620_CKS1 (1<<3) | ||
200 | /* Clock and Format Control register */ | ||
201 | #define AK4620_DFS_REG 0x02 | ||
202 | |||
203 | /* Deem and Volume Control register */ | ||
204 | #define AK4620_DEEMVOL_REG 0x03 | ||
205 | #define AK4620_SMUTE (1<<7) | ||
206 | |||
207 | /* | ||
208 | * Conversion from int value to its binary form. Used for debugging. | ||
209 | * The output buffer must be allocated prior to calling the function. | ||
210 | */ | ||
211 | static char *get_binary(char *buffer, int value) | ||
212 | { | ||
213 | int i, j, pos; | ||
214 | pos = 0; | ||
215 | for (i = 0; i < 4; ++i) { | ||
216 | for (j = 0; j < 8; ++j) { | ||
217 | if (value & (1 << (31-(i*8 + j)))) | ||
218 | buffer[pos] = '1'; | ||
219 | else | ||
220 | buffer[pos] = '0'; | ||
221 | pos++; | ||
222 | } | ||
223 | if (i < 3) { | ||
224 | buffer[pos] = ' '; | ||
225 | pos++; | ||
226 | } | ||
227 | } | ||
228 | buffer[pos] = '\0'; | ||
229 | return buffer; | ||
230 | } | ||
231 | |||
232 | /* | ||
233 | * Initial setup of the conversion array GPIO <-> rate | ||
234 | */ | ||
235 | static unsigned int qtet_rates[] = { | ||
236 | 44100, 48000, 88200, | ||
237 | 96000, 176400, 192000, | ||
238 | }; | ||
239 | |||
240 | static unsigned int cks_vals[] = { | ||
241 | CPLD_CKS_44100HZ, CPLD_CKS_48000HZ, CPLD_CKS_88200HZ, | ||
242 | CPLD_CKS_96000HZ, CPLD_CKS_176400HZ, CPLD_CKS_192000HZ, | ||
243 | }; | ||
244 | |||
245 | static struct snd_pcm_hw_constraint_list qtet_rates_info = { | ||
246 | .count = ARRAY_SIZE(qtet_rates), | ||
247 | .list = qtet_rates, | ||
248 | .mask = 0, | ||
249 | }; | ||
250 | |||
251 | static void qtet_ak4113_write(void *private_data, unsigned char reg, | ||
252 | unsigned char val) | ||
253 | { | ||
254 | snd_vt1724_write_i2c((struct snd_ice1712 *)private_data, AK4113_ADDR, | ||
255 | reg, val); | ||
256 | } | ||
257 | |||
258 | static unsigned char qtet_ak4113_read(void *private_data, unsigned char reg) | ||
259 | { | ||
260 | return snd_vt1724_read_i2c((struct snd_ice1712 *)private_data, | ||
261 | AK4113_ADDR, reg); | ||
262 | } | ||
263 | |||
264 | |||
265 | /* | ||
266 | * AK4620 section | ||
267 | */ | ||
268 | |||
269 | /* | ||
270 | * Write data to addr register of ak4620 | ||
271 | */ | ||
272 | static void qtet_akm_write(struct snd_akm4xxx *ak, int chip, | ||
273 | unsigned char addr, unsigned char data) | ||
274 | { | ||
275 | unsigned int tmp, orig_dir; | ||
276 | int idx; | ||
277 | unsigned int addrdata; | ||
278 | struct snd_ice1712 *ice = ak->private_data[0]; | ||
279 | |||
280 | if (snd_BUG_ON(chip < 0 || chip >= 4)) | ||
281 | return; | ||
282 | /*printk(KERN_DEBUG "Writing to AK4620: chip=%d, addr=0x%x, | ||
283 | data=0x%x\n", chip, addr, data);*/ | ||
284 | orig_dir = ice->gpio.get_dir(ice); | ||
285 | ice->gpio.set_dir(ice, orig_dir | GPIO_SPI_ALL); | ||
286 | /* set mask - only SPI bits */ | ||
287 | ice->gpio.set_mask(ice, ~GPIO_SPI_ALL); | ||
288 | |||
289 | tmp = ice->gpio.get_data(ice); | ||
290 | /* high all */ | ||
291 | tmp |= GPIO_SPI_ALL; | ||
292 | ice->gpio.set_data(ice, tmp); | ||
293 | udelay(100); | ||
294 | /* drop chip select */ | ||
295 | if (chip) | ||
296 | /* CODEC 1 */ | ||
297 | tmp &= ~GPIO_SPI_CSN1; | ||
298 | else | ||
299 | tmp &= ~GPIO_SPI_CSN0; | ||
300 | ice->gpio.set_data(ice, tmp); | ||
301 | udelay(100); | ||
302 | |||
303 | /* build I2C address + data byte */ | ||
304 | addrdata = (AK4620_ADDR << 6) | 0x20 | (addr & 0x1f); | ||
305 | addrdata = (addrdata << 8) | data; | ||
306 | for (idx = 15; idx >= 0; idx--) { | ||
307 | /* drop clock */ | ||
308 | tmp &= ~GPIO_D5_SPI_CCLK; | ||
309 | ice->gpio.set_data(ice, tmp); | ||
310 | udelay(100); | ||
311 | /* set data */ | ||
312 | if (addrdata & (1 << idx)) | ||
313 | tmp |= GPIO_D4_SPI_CDTO; | ||
314 | else | ||
315 | tmp &= ~GPIO_D4_SPI_CDTO; | ||
316 | ice->gpio.set_data(ice, tmp); | ||
317 | udelay(100); | ||
318 | /* raise clock */ | ||
319 | tmp |= GPIO_D5_SPI_CCLK; | ||
320 | ice->gpio.set_data(ice, tmp); | ||
321 | udelay(100); | ||
322 | } | ||
323 | /* all back to 1 */ | ||
324 | tmp |= GPIO_SPI_ALL; | ||
325 | ice->gpio.set_data(ice, tmp); | ||
326 | udelay(100); | ||
327 | |||
328 | /* return all gpios to non-writable */ | ||
329 | ice->gpio.set_mask(ice, 0xffffff); | ||
330 | /* restore GPIOs direction */ | ||
331 | ice->gpio.set_dir(ice, orig_dir); | ||
332 | } | ||
333 | |||
334 | static void qtet_akm_set_regs(struct snd_akm4xxx *ak, unsigned char addr, | ||
335 | unsigned char mask, unsigned char value) | ||
336 | { | ||
337 | unsigned char tmp; | ||
338 | int chip; | ||
339 | for (chip = 0; chip < ak->num_chips; chip++) { | ||
340 | tmp = snd_akm4xxx_get(ak, chip, addr); | ||
341 | /* clear the bits */ | ||
342 | tmp &= ~mask; | ||
343 | /* set the new bits */ | ||
344 | tmp |= value; | ||
345 | snd_akm4xxx_write(ak, chip, addr, tmp); | ||
346 | } | ||
347 | } | ||
348 | |||
349 | /* | ||
350 | * change the rate of AK4620 | ||
351 | */ | ||
352 | static void qtet_akm_set_rate_val(struct snd_akm4xxx *ak, unsigned int rate) | ||
353 | { | ||
354 | unsigned char ak4620_dfs; | ||
355 | |||
356 | if (rate == 0) /* no hint - S/PDIF input is master or the new spdif | ||
357 | input rate undetected, simply return */ | ||
358 | return; | ||
359 | |||
360 | /* adjust DFS on codecs - see datasheet */ | ||
361 | if (rate > 108000) | ||
362 | ak4620_dfs = AK4620_DFS1 | AK4620_CKS1; | ||
363 | else if (rate > 54000) | ||
364 | ak4620_dfs = AK4620_DFS0 | AK4620_CKS0; | ||
365 | else | ||
366 | ak4620_dfs = 0; | ||
367 | |||
368 | /* set new value */ | ||
369 | qtet_akm_set_regs(ak, AK4620_DFS_REG, AK4620_DFS0 | AK4620_DFS1 | | ||
370 | AK4620_CKS0 | AK4620_CKS1, ak4620_dfs); | ||
371 | } | ||
372 | |||
373 | #define AK_CONTROL(xname, xch) { .name = xname, .num_channels = xch } | ||
374 | |||
375 | #define PCM_12_PLAYBACK_VOLUME "PCM 1/2 Playback Volume" | ||
376 | #define PCM_34_PLAYBACK_VOLUME "PCM 3/4 Playback Volume" | ||
377 | #define PCM_12_CAPTURE_VOLUME "PCM 1/2 Capture Volume" | ||
378 | #define PCM_34_CAPTURE_VOLUME "PCM 3/4 Capture Volume" | ||
379 | |||
380 | static const struct snd_akm4xxx_dac_channel qtet_dac[] = { | ||
381 | AK_CONTROL(PCM_12_PLAYBACK_VOLUME, 2), | ||
382 | AK_CONTROL(PCM_34_PLAYBACK_VOLUME, 2), | ||
383 | }; | ||
384 | |||
385 | static const struct snd_akm4xxx_adc_channel qtet_adc[] = { | ||
386 | AK_CONTROL(PCM_12_CAPTURE_VOLUME, 2), | ||
387 | AK_CONTROL(PCM_34_CAPTURE_VOLUME, 2), | ||
388 | }; | ||
389 | |||
390 | static struct snd_akm4xxx akm_qtet_dac __devinitdata = { | ||
391 | .type = SND_AK4620, | ||
392 | .num_dacs = 4, /* DAC1 - Output 12 | ||
393 | */ | ||
394 | .num_adcs = 4, /* ADC1 - Input 12 | ||
395 | */ | ||
396 | .ops = { | ||
397 | .write = qtet_akm_write, | ||
398 | .set_rate_val = qtet_akm_set_rate_val, | ||
399 | }, | ||
400 | .dac_info = qtet_dac, | ||
401 | .adc_info = qtet_adc, | ||
402 | }; | ||
403 | |||
404 | /* Communication routines with the CPLD */ | ||
405 | |||
406 | |||
407 | /* Writes data to external register reg, both reg and data are | ||
408 | * GPIO representations */ | ||
409 | static void reg_write(struct snd_ice1712 *ice, unsigned int reg, | ||
410 | unsigned int data) | ||
411 | { | ||
412 | unsigned int tmp; | ||
413 | |||
414 | mutex_lock(&ice->gpio_mutex); | ||
415 | /* set direction of used GPIOs*/ | ||
416 | /* all outputs */ | ||
417 | tmp = 0x00ffff; | ||
418 | ice->gpio.set_dir(ice, tmp); | ||
419 | /* mask - writable bits */ | ||
420 | ice->gpio.set_mask(ice, ~(tmp)); | ||
421 | /* write the data */ | ||
422 | tmp = ice->gpio.get_data(ice); | ||
423 | tmp &= ~GPIO_DATA_MASK; | ||
424 | tmp |= data; | ||
425 | ice->gpio.set_data(ice, tmp); | ||
426 | udelay(100); | ||
427 | /* drop output enable */ | ||
428 | tmp &= ~GPIO_EX_GPIOE; | ||
429 | ice->gpio.set_data(ice, tmp); | ||
430 | udelay(100); | ||
431 | /* drop the register gpio */ | ||
432 | tmp &= ~reg; | ||
433 | ice->gpio.set_data(ice, tmp); | ||
434 | udelay(100); | ||
435 | /* raise the register GPIO */ | ||
436 | tmp |= reg; | ||
437 | ice->gpio.set_data(ice, tmp); | ||
438 | udelay(100); | ||
439 | |||
440 | /* raise all data gpios */ | ||
441 | tmp |= GPIO_DATA_MASK; | ||
442 | ice->gpio.set_data(ice, tmp); | ||
443 | /* mask - immutable bits */ | ||
444 | ice->gpio.set_mask(ice, 0xffffff); | ||
445 | /* outputs only 8-15 */ | ||
446 | ice->gpio.set_dir(ice, 0x00ff00); | ||
447 | mutex_unlock(&ice->gpio_mutex); | ||
448 | } | ||
449 | |||
450 | static unsigned int get_scr(struct snd_ice1712 *ice) | ||
451 | { | ||
452 | struct qtet_spec *spec = ice->spec; | ||
453 | return spec->scr; | ||
454 | } | ||
455 | |||
456 | static unsigned int get_mcr(struct snd_ice1712 *ice) | ||
457 | { | ||
458 | struct qtet_spec *spec = ice->spec; | ||
459 | return spec->mcr; | ||
460 | } | ||
461 | |||
462 | static unsigned int get_cpld(struct snd_ice1712 *ice) | ||
463 | { | ||
464 | struct qtet_spec *spec = ice->spec; | ||
465 | return spec->cpld; | ||
466 | } | ||
467 | |||
468 | static void set_scr(struct snd_ice1712 *ice, unsigned int val) | ||
469 | { | ||
470 | struct qtet_spec *spec = ice->spec; | ||
471 | reg_write(ice, GPIO_SCR, val); | ||
472 | spec->scr = val; | ||
473 | } | ||
474 | |||
475 | static void set_mcr(struct snd_ice1712 *ice, unsigned int val) | ||
476 | { | ||
477 | struct qtet_spec *spec = ice->spec; | ||
478 | reg_write(ice, GPIO_MCR, val); | ||
479 | spec->mcr = val; | ||
480 | } | ||
481 | |||
482 | static void set_cpld(struct snd_ice1712 *ice, unsigned int val) | ||
483 | { | ||
484 | struct qtet_spec *spec = ice->spec; | ||
485 | reg_write(ice, GPIO_CPLD_CSN, val); | ||
486 | spec->cpld = val; | ||
487 | } | ||
488 | #ifdef CONFIG_PROC_FS | ||
489 | static void proc_regs_read(struct snd_info_entry *entry, | ||
490 | struct snd_info_buffer *buffer) | ||
491 | { | ||
492 | struct snd_ice1712 *ice = entry->private_data; | ||
493 | char bin_buffer[36]; | ||
494 | |||
495 | snd_iprintf(buffer, "SCR: %s\n", get_binary(bin_buffer, | ||
496 | get_scr(ice))); | ||
497 | snd_iprintf(buffer, "MCR: %s\n", get_binary(bin_buffer, | ||
498 | get_mcr(ice))); | ||
499 | snd_iprintf(buffer, "CPLD: %s\n", get_binary(bin_buffer, | ||
500 | get_cpld(ice))); | ||
501 | } | ||
502 | |||
503 | static void proc_init(struct snd_ice1712 *ice) | ||
504 | { | ||
505 | struct snd_info_entry *entry; | ||
506 | if (!snd_card_proc_new(ice->card, "quartet", &entry)) | ||
507 | snd_info_set_text_ops(entry, ice, proc_regs_read); | ||
508 | } | ||
509 | #else /* !CONFIG_PROC_FS */ | ||
510 | static void proc_init(struct snd_ice1712 *ice) {} | ||
511 | #endif | ||
512 | |||
513 | static int qtet_mute_get(struct snd_kcontrol *kcontrol, | ||
514 | struct snd_ctl_elem_value *ucontrol) | ||
515 | { | ||
516 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); | ||
517 | unsigned int val; | ||
518 | val = get_scr(ice) & SCR_MUTE; | ||
519 | ucontrol->value.integer.value[0] = (val) ? 0 : 1; | ||
520 | return 0; | ||
521 | } | ||
522 | |||
523 | static int qtet_mute_put(struct snd_kcontrol *kcontrol, | ||
524 | struct snd_ctl_elem_value *ucontrol) | ||
525 | { | ||
526 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); | ||
527 | unsigned int old, new, smute; | ||
528 | old = get_scr(ice) & SCR_MUTE; | ||
529 | if (ucontrol->value.integer.value[0]) { | ||
530 | /* unmute */ | ||
531 | new = 0; | ||
532 | /* un-smuting DAC */ | ||
533 | smute = 0; | ||
534 | } else { | ||
535 | /* mute */ | ||
536 | new = SCR_MUTE; | ||
537 | /* smuting DAC */ | ||
538 | smute = AK4620_SMUTE; | ||
539 | } | ||
540 | if (old != new) { | ||
541 | struct snd_akm4xxx *ak = ice->akm; | ||
542 | set_scr(ice, (get_scr(ice) & ~SCR_MUTE) | new); | ||
543 | /* set smute */ | ||
544 | qtet_akm_set_regs(ak, AK4620_DEEMVOL_REG, AK4620_SMUTE, smute); | ||
545 | return 1; | ||
546 | } | ||
547 | /* no change */ | ||
548 | return 0; | ||
549 | } | ||
550 | |||
551 | static int qtet_ain12_enum_info(struct snd_kcontrol *kcontrol, | ||
552 | struct snd_ctl_elem_info *uinfo) | ||
553 | { | ||
554 | static char *texts[3] = {"Line In 1/2", "Mic", "Mic + Low-cut"}; | ||
555 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | ||
556 | uinfo->count = 1; | ||
557 | uinfo->value.enumerated.items = ARRAY_SIZE(texts); | ||
558 | |||
559 | if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) | ||
560 | uinfo->value.enumerated.item = | ||
561 | uinfo->value.enumerated.items - 1; | ||
562 | strcpy(uinfo->value.enumerated.name, | ||
563 | texts[uinfo->value.enumerated.item]); | ||
564 | |||
565 | return 0; | ||
566 | } | ||
567 | |||
568 | static int qtet_ain12_sw_get(struct snd_kcontrol *kcontrol, | ||
569 | struct snd_ctl_elem_value *ucontrol) | ||
570 | { | ||
571 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); | ||
572 | unsigned int val, result; | ||
573 | val = get_scr(ice) & (SCR_AIN12_SEL1 | SCR_AIN12_SEL0); | ||
574 | switch (val) { | ||
575 | case SCR_AIN12_LINE: | ||
576 | result = 0; | ||
577 | break; | ||
578 | case SCR_AIN12_MIC: | ||
579 | result = 1; | ||
580 | break; | ||
581 | case SCR_AIN12_LOWCUT: | ||
582 | result = 2; | ||
583 | break; | ||
584 | default: | ||
585 | /* BUG - no other combinations allowed */ | ||
586 | snd_BUG(); | ||
587 | result = 0; | ||
588 | } | ||
589 | ucontrol->value.integer.value[0] = result; | ||
590 | return 0; | ||
591 | } | ||
592 | |||
593 | static int qtet_ain12_sw_put(struct snd_kcontrol *kcontrol, | ||
594 | struct snd_ctl_elem_value *ucontrol) | ||
595 | { | ||
596 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); | ||
597 | unsigned int old, new, tmp, masked_old; | ||
598 | old = new = get_scr(ice); | ||
599 | masked_old = old & (SCR_AIN12_SEL1 | SCR_AIN12_SEL0); | ||
600 | tmp = ucontrol->value.integer.value[0]; | ||
601 | if (tmp == 2) | ||
602 | tmp = 3; /* binary 10 is not supported */ | ||
603 | tmp <<= 4; /* shifting to SCR_AIN12_SEL0 */ | ||
604 | if (tmp != masked_old) { | ||
605 | /* change requested */ | ||
606 | switch (tmp) { | ||
607 | case SCR_AIN12_LINE: | ||
608 | new = old & ~(SCR_AIN12_SEL1 | SCR_AIN12_SEL0); | ||
609 | set_scr(ice, new); | ||
610 | /* turn off relay */ | ||
611 | new &= ~SCR_RELAY; | ||
612 | set_scr(ice, new); | ||
613 | break; | ||
614 | case SCR_AIN12_MIC: | ||
615 | /* turn on relay */ | ||
616 | new = old | SCR_RELAY; | ||
617 | set_scr(ice, new); | ||
618 | new = (new & ~SCR_AIN12_SEL1) | SCR_AIN12_SEL0; | ||
619 | set_scr(ice, new); | ||
620 | break; | ||
621 | case SCR_AIN12_LOWCUT: | ||
622 | /* turn on relay */ | ||
623 | new = old | SCR_RELAY; | ||
624 | set_scr(ice, new); | ||
625 | new |= SCR_AIN12_SEL1 | SCR_AIN12_SEL0; | ||
626 | set_scr(ice, new); | ||
627 | break; | ||
628 | default: | ||
629 | snd_BUG(); | ||
630 | } | ||
631 | return 1; | ||
632 | } | ||
633 | /* no change */ | ||
634 | return 0; | ||
635 | } | ||
636 | |||
637 | static int qtet_php_get(struct snd_kcontrol *kcontrol, | ||
638 | struct snd_ctl_elem_value *ucontrol) | ||
639 | { | ||
640 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); | ||
641 | unsigned int val; | ||
642 | /* if phantom voltage =48V, phantom on */ | ||
643 | val = get_scr(ice) & SCR_PHP_V; | ||
644 | ucontrol->value.integer.value[0] = val ? 1 : 0; | ||
645 | return 0; | ||
646 | } | ||
647 | |||
648 | static int qtet_php_put(struct snd_kcontrol *kcontrol, | ||
649 | struct snd_ctl_elem_value *ucontrol) | ||
650 | { | ||
651 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); | ||
652 | unsigned int old, new; | ||
653 | old = new = get_scr(ice); | ||
654 | if (ucontrol->value.integer.value[0] /* phantom on requested */ | ||
655 | && (~old & SCR_PHP_V)) /* 0 = voltage 5V */ { | ||
656 | /* is off, turn on */ | ||
657 | /* turn voltage on first, = 1 */ | ||
658 | new = old | SCR_PHP_V; | ||
659 | set_scr(ice, new); | ||
660 | /* turn phantom on, = 0 */ | ||
661 | new &= ~SCR_PHP; | ||
662 | set_scr(ice, new); | ||
663 | } else if (!ucontrol->value.integer.value[0] && (old & SCR_PHP_V)) { | ||
664 | /* phantom off requested and 1 = voltage 48V */ | ||
665 | /* is on, turn off */ | ||
666 | /* turn voltage off first, = 0 */ | ||
667 | new = old & ~SCR_PHP_V; | ||
668 | set_scr(ice, new); | ||
669 | /* turn phantom off, = 1 */ | ||
670 | new |= SCR_PHP; | ||
671 | set_scr(ice, new); | ||
672 | } | ||
673 | if (old != new) | ||
674 | return 1; | ||
675 | /* no change */ | ||
676 | return 0; | ||
677 | } | ||
678 | |||
679 | #define PRIV_SW(xid, xbit, xreg) [xid] = {.bit = xbit,\ | ||
680 | .set_register = set_##xreg,\ | ||
681 | .get_register = get_##xreg, } | ||
682 | |||
683 | |||
684 | #define PRIV_ENUM2(xid, xbit, xreg, xtext1, xtext2) [xid] = {.bit = xbit,\ | ||
685 | .set_register = set_##xreg,\ | ||
686 | .get_register = get_##xreg,\ | ||
687 | .texts = {xtext1, xtext2} } | ||
688 | |||
689 | static struct qtet_kcontrol_private qtet_privates[] = { | ||
690 | PRIV_ENUM2(IN12_SEL, CPLD_IN12_SEL, cpld, "An In 1/2", "An In 3/4"), | ||
691 | PRIV_ENUM2(IN34_SEL, CPLD_IN34_SEL, cpld, "An In 3/4", "IEC958 In"), | ||
692 | PRIV_ENUM2(AIN34_SEL, SCR_AIN34_SEL, scr, "Line In 3/4", "Hi-Z"), | ||
693 | PRIV_ENUM2(COAX_OUT, CPLD_COAX_OUT, cpld, "IEC958", "I2S"), | ||
694 | PRIV_SW(IN12_MON12, MCR_IN12_MON12, mcr), | ||
695 | PRIV_SW(IN12_MON34, MCR_IN12_MON34, mcr), | ||
696 | PRIV_SW(IN34_MON12, MCR_IN34_MON12, mcr), | ||
697 | PRIV_SW(IN34_MON34, MCR_IN34_MON34, mcr), | ||
698 | PRIV_SW(OUT12_MON34, MCR_OUT12_MON34, mcr), | ||
699 | PRIV_SW(OUT34_MON12, MCR_OUT34_MON12, mcr), | ||
700 | }; | ||
701 | |||
702 | static int qtet_enum_info(struct snd_kcontrol *kcontrol, | ||
703 | struct snd_ctl_elem_info *uinfo) | ||
704 | { | ||
705 | struct qtet_kcontrol_private private = | ||
706 | qtet_privates[kcontrol->private_value]; | ||
707 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | ||
708 | uinfo->count = 1; | ||
709 | uinfo->value.enumerated.items = ARRAY_SIZE(private.texts); | ||
710 | |||
711 | if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) | ||
712 | uinfo->value.enumerated.item = | ||
713 | uinfo->value.enumerated.items - 1; | ||
714 | strcpy(uinfo->value.enumerated.name, | ||
715 | private.texts[uinfo->value.enumerated.item]); | ||
716 | |||
717 | return 0; | ||
718 | } | ||
719 | |||
720 | static int qtet_sw_get(struct snd_kcontrol *kcontrol, | ||
721 | struct snd_ctl_elem_value *ucontrol) | ||
722 | { | ||
723 | struct qtet_kcontrol_private private = | ||
724 | qtet_privates[kcontrol->private_value]; | ||
725 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); | ||
726 | ucontrol->value.integer.value[0] = | ||
727 | (private.get_register(ice) & private.bit) ? 1 : 0; | ||
728 | return 0; | ||
729 | } | ||
730 | |||
731 | static int qtet_sw_put(struct snd_kcontrol *kcontrol, | ||
732 | struct snd_ctl_elem_value *ucontrol) | ||
733 | { | ||
734 | struct qtet_kcontrol_private private = | ||
735 | qtet_privates[kcontrol->private_value]; | ||
736 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); | ||
737 | unsigned int old, new; | ||
738 | old = private.get_register(ice); | ||
739 | if (ucontrol->value.integer.value[0]) | ||
740 | new = old | private.bit; | ||
741 | else | ||
742 | new = old & ~private.bit; | ||
743 | if (old != new) { | ||
744 | private.set_register(ice, new); | ||
745 | return 1; | ||
746 | } | ||
747 | /* no change */ | ||
748 | return 0; | ||
749 | } | ||
750 | |||
751 | #define qtet_sw_info snd_ctl_boolean_mono_info | ||
752 | |||
753 | #define QTET_CONTROL(xname, xtype, xpriv) \ | ||
754 | {.iface = SNDRV_CTL_ELEM_IFACE_MIXER,\ | ||
755 | .name = xname,\ | ||
756 | .info = qtet_##xtype##_info,\ | ||
757 | .get = qtet_sw_get,\ | ||
758 | .put = qtet_sw_put,\ | ||
759 | .private_value = xpriv } | ||
760 | |||
761 | static struct snd_kcontrol_new qtet_controls[] __devinitdata = { | ||
762 | { | ||
763 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
764 | .name = "Master Playback Switch", | ||
765 | .info = qtet_sw_info, | ||
766 | .get = qtet_mute_get, | ||
767 | .put = qtet_mute_put, | ||
768 | .private_value = 0 | ||
769 | }, | ||
770 | { | ||
771 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
772 | .name = "Phantom Power", | ||
773 | .info = qtet_sw_info, | ||
774 | .get = qtet_php_get, | ||
775 | .put = qtet_php_put, | ||
776 | .private_value = 0 | ||
777 | }, | ||
778 | { | ||
779 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
780 | .name = "Analog In 1/2 Capture Switch", | ||
781 | .info = qtet_ain12_enum_info, | ||
782 | .get = qtet_ain12_sw_get, | ||
783 | .put = qtet_ain12_sw_put, | ||
784 | .private_value = 0 | ||
785 | }, | ||
786 | QTET_CONTROL("Analog In 3/4 Capture Switch", enum, AIN34_SEL), | ||
787 | QTET_CONTROL("PCM In 1/2 Capture Switch", enum, IN12_SEL), | ||
788 | QTET_CONTROL("PCM In 3/4 Capture Switch", enum, IN34_SEL), | ||
789 | QTET_CONTROL("Coax Output Source", enum, COAX_OUT), | ||
790 | QTET_CONTROL("Analog In 1/2 to Monitor 1/2", sw, IN12_MON12), | ||
791 | QTET_CONTROL("Analog In 1/2 to Monitor 3/4", sw, IN12_MON34), | ||
792 | QTET_CONTROL("Analog In 3/4 to Monitor 1/2", sw, IN34_MON12), | ||
793 | QTET_CONTROL("Analog In 3/4 to Monitor 3/4", sw, IN34_MON34), | ||
794 | QTET_CONTROL("Output 1/2 to Monitor 3/4", sw, OUT12_MON34), | ||
795 | QTET_CONTROL("Output 3/4 to Monitor 1/2", sw, OUT34_MON12), | ||
796 | }; | ||
797 | |||
798 | static char *slave_vols[] __devinitdata = { | ||
799 | PCM_12_PLAYBACK_VOLUME, | ||
800 | PCM_34_PLAYBACK_VOLUME, | ||
801 | NULL | ||
802 | }; | ||
803 | |||
804 | static __devinitdata | ||
805 | DECLARE_TLV_DB_SCALE(qtet_master_db_scale, -6350, 50, 1); | ||
806 | |||
807 | static struct snd_kcontrol __devinit *ctl_find(struct snd_card *card, | ||
808 | const char *name) | ||
809 | { | ||
810 | struct snd_ctl_elem_id sid; | ||
811 | memset(&sid, 0, sizeof(sid)); | ||
812 | /* FIXME: strcpy is bad. */ | ||
813 | strcpy(sid.name, name); | ||
814 | sid.iface = SNDRV_CTL_ELEM_IFACE_MIXER; | ||
815 | return snd_ctl_find_id(card, &sid); | ||
816 | } | ||
817 | |||
818 | static void __devinit add_slaves(struct snd_card *card, | ||
819 | struct snd_kcontrol *master, char **list) | ||
820 | { | ||
821 | for (; *list; list++) { | ||
822 | struct snd_kcontrol *slave = ctl_find(card, *list); | ||
823 | if (slave) | ||
824 | snd_ctl_add_slave(master, slave); | ||
825 | } | ||
826 | } | ||
827 | |||
828 | static int __devinit qtet_add_controls(struct snd_ice1712 *ice) | ||
829 | { | ||
830 | struct qtet_spec *spec = ice->spec; | ||
831 | int err, i; | ||
832 | struct snd_kcontrol *vmaster; | ||
833 | err = snd_ice1712_akm4xxx_build_controls(ice); | ||
834 | if (err < 0) | ||
835 | return err; | ||
836 | for (i = 0; i < ARRAY_SIZE(qtet_controls); i++) { | ||
837 | err = snd_ctl_add(ice->card, | ||
838 | snd_ctl_new1(&qtet_controls[i], ice)); | ||
839 | if (err < 0) | ||
840 | return err; | ||
841 | } | ||
842 | |||
843 | /* Create virtual master control */ | ||
844 | vmaster = snd_ctl_make_virtual_master("Master Playback Volume", | ||
845 | qtet_master_db_scale); | ||
846 | if (!vmaster) | ||
847 | return -ENOMEM; | ||
848 | add_slaves(ice->card, vmaster, slave_vols); | ||
849 | err = snd_ctl_add(ice->card, vmaster); | ||
850 | if (err < 0) | ||
851 | return err; | ||
852 | /* only capture SPDIF over AK4113 */ | ||
853 | err = snd_ak4113_build(spec->ak4113, | ||
854 | ice->pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream); | ||
855 | if (err < 0) | ||
856 | return err; | ||
857 | return 0; | ||
858 | } | ||
859 | |||
860 | static inline int qtet_is_spdif_master(struct snd_ice1712 *ice) | ||
861 | { | ||
862 | /* CPLD_SYNC_SEL: 0 = internal, 1 = external (i.e. spdif master) */ | ||
863 | return (get_cpld(ice) & CPLD_SYNC_SEL) ? 1 : 0; | ||
864 | } | ||
865 | |||
866 | static unsigned int qtet_get_rate(struct snd_ice1712 *ice) | ||
867 | { | ||
868 | int i; | ||
869 | unsigned char result; | ||
870 | |||
871 | result = get_cpld(ice) & CPLD_CKS_MASK; | ||
872 | for (i = 0; i < ARRAY_SIZE(cks_vals); i++) | ||
873 | if (cks_vals[i] == result) | ||
874 | return qtet_rates[i]; | ||
875 | return 0; | ||
876 | } | ||
877 | |||
878 | static int get_cks_val(int rate) | ||
879 | { | ||
880 | int i; | ||
881 | for (i = 0; i < ARRAY_SIZE(qtet_rates); i++) | ||
882 | if (qtet_rates[i] == rate) | ||
883 | return cks_vals[i]; | ||
884 | return 0; | ||
885 | } | ||
886 | |||
887 | /* setting new rate */ | ||
888 | static void qtet_set_rate(struct snd_ice1712 *ice, unsigned int rate) | ||
889 | { | ||
890 | unsigned int new; | ||
891 | unsigned char val; | ||
892 | /* switching ice1724 to external clock - supplied by ext. circuits */ | ||
893 | val = inb(ICEMT1724(ice, RATE)); | ||
894 | outb(val | VT1724_SPDIF_MASTER, ICEMT1724(ice, RATE)); | ||
895 | |||
896 | new = (get_cpld(ice) & ~CPLD_CKS_MASK) | get_cks_val(rate); | ||
897 | /* switch to internal clock, drop CPLD_SYNC_SEL */ | ||
898 | new &= ~CPLD_SYNC_SEL; | ||
899 | /* printk(KERN_DEBUG "QT - set_rate: old %x, new %x\n", | ||
900 | get_cpld(ice), new); */ | ||
901 | set_cpld(ice, new); | ||
902 | } | ||
903 | |||
904 | static inline unsigned char qtet_set_mclk(struct snd_ice1712 *ice, | ||
905 | unsigned int rate) | ||
906 | { | ||
907 | /* no change in master clock */ | ||
908 | return 0; | ||
909 | } | ||
910 | |||
911 | /* setting clock to external - SPDIF */ | ||
912 | static int qtet_set_spdif_clock(struct snd_ice1712 *ice, int type) | ||
913 | { | ||
914 | unsigned int old, new; | ||
915 | |||
916 | old = new = get_cpld(ice); | ||
917 | new &= ~(CPLD_CKS_MASK | CPLD_WORD_SEL); | ||
918 | switch (type) { | ||
919 | case EXT_SPDIF_TYPE: | ||
920 | new |= CPLD_EXT_SPDIF; | ||
921 | break; | ||
922 | case EXT_WORDCLOCK_1FS_TYPE: | ||
923 | new |= CPLD_EXT_WORDCLOCK_1FS; | ||
924 | break; | ||
925 | case EXT_WORDCLOCK_256FS_TYPE: | ||
926 | new |= CPLD_EXT_WORDCLOCK_256FS; | ||
927 | break; | ||
928 | default: | ||
929 | snd_BUG(); | ||
930 | } | ||
931 | if (old != new) { | ||
932 | set_cpld(ice, new); | ||
933 | /* changed */ | ||
934 | return 1; | ||
935 | } | ||
936 | return 0; | ||
937 | } | ||
938 | |||
939 | static int qtet_get_spdif_master_type(struct snd_ice1712 *ice) | ||
940 | { | ||
941 | unsigned int val; | ||
942 | int result; | ||
943 | val = get_cpld(ice); | ||
944 | /* checking only rate/clock-related bits */ | ||
945 | val &= (CPLD_CKS_MASK | CPLD_WORD_SEL | CPLD_SYNC_SEL); | ||
946 | if (!(val & CPLD_SYNC_SEL)) { | ||
947 | /* switched to internal clock, is not any external type */ | ||
948 | result = -1; | ||
949 | } else { | ||
950 | switch (val) { | ||
951 | case (CPLD_EXT_SPDIF): | ||
952 | result = EXT_SPDIF_TYPE; | ||
953 | break; | ||
954 | case (CPLD_EXT_WORDCLOCK_1FS): | ||
955 | result = EXT_WORDCLOCK_1FS_TYPE; | ||
956 | break; | ||
957 | case (CPLD_EXT_WORDCLOCK_256FS): | ||
958 | result = EXT_WORDCLOCK_256FS_TYPE; | ||
959 | break; | ||
960 | default: | ||
961 | /* undefined combination of external clock setup */ | ||
962 | snd_BUG(); | ||
963 | result = 0; | ||
964 | } | ||
965 | } | ||
966 | return result; | ||
967 | } | ||
968 | |||
969 | /* Called when ak4113 detects change in the input SPDIF stream */ | ||
970 | static void qtet_ak4113_change(struct ak4113 *ak4113, unsigned char c0, | ||
971 | unsigned char c1) | ||
972 | { | ||
973 | struct snd_ice1712 *ice = ak4113->change_callback_private; | ||
974 | int rate; | ||
975 | if ((qtet_get_spdif_master_type(ice) == EXT_SPDIF_TYPE) && | ||
976 | c1) { | ||
977 | /* only for SPDIF master mode, rate was changed */ | ||
978 | rate = snd_ak4113_external_rate(ak4113); | ||
979 | /* printk(KERN_DEBUG "ak4113 - input rate changed to %d\n", | ||
980 | rate); */ | ||
981 | qtet_akm_set_rate_val(ice->akm, rate); | ||
982 | } | ||
983 | } | ||
984 | |||
985 | /* | ||
986 | * If clock slaved to SPDIF-IN, setting runtime rate | ||
987 | * to the detected external rate | ||
988 | */ | ||
989 | static void qtet_spdif_in_open(struct snd_ice1712 *ice, | ||
990 | struct snd_pcm_substream *substream) | ||
991 | { | ||
992 | struct qtet_spec *spec = ice->spec; | ||
993 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
994 | int rate; | ||
995 | |||
996 | if (qtet_get_spdif_master_type(ice) != EXT_SPDIF_TYPE) | ||
997 | /* not external SPDIF, no rate limitation */ | ||
998 | return; | ||
999 | /* only external SPDIF can detect incoming sample rate */ | ||
1000 | rate = snd_ak4113_external_rate(spec->ak4113); | ||
1001 | if (rate >= runtime->hw.rate_min && rate <= runtime->hw.rate_max) { | ||
1002 | runtime->hw.rate_min = rate; | ||
1003 | runtime->hw.rate_max = rate; | ||
1004 | } | ||
1005 | } | ||
1006 | |||
1007 | /* | ||
1008 | * initialize the chip | ||
1009 | */ | ||
1010 | static int __devinit qtet_init(struct snd_ice1712 *ice) | ||
1011 | { | ||
1012 | static const unsigned char ak4113_init_vals[] = { | ||
1013 | /* AK4113_REG_PWRDN */ AK4113_RST | AK4113_PWN | | ||
1014 | AK4113_OCKS0 | AK4113_OCKS1, | ||
1015 | /* AK4113_REQ_FORMAT */ AK4113_DIF_I24I2S | AK4113_VTX | | ||
1016 | AK4113_DEM_OFF | AK4113_DEAU, | ||
1017 | /* AK4113_REG_IO0 */ AK4113_OPS2 | AK4113_TXE | | ||
1018 | AK4113_XTL_24_576M, | ||
1019 | /* AK4113_REG_IO1 */ AK4113_EFH_1024LRCLK | AK4113_IPS(0), | ||
1020 | /* AK4113_REG_INT0_MASK */ 0, | ||
1021 | /* AK4113_REG_INT1_MASK */ 0, | ||
1022 | /* AK4113_REG_DATDTS */ 0, | ||
1023 | }; | ||
1024 | int err; | ||
1025 | struct qtet_spec *spec; | ||
1026 | struct snd_akm4xxx *ak; | ||
1027 | unsigned char val; | ||
1028 | |||
1029 | /* switching ice1724 to external clock - supplied by ext. circuits */ | ||
1030 | val = inb(ICEMT1724(ice, RATE)); | ||
1031 | outb(val | VT1724_SPDIF_MASTER, ICEMT1724(ice, RATE)); | ||
1032 | |||
1033 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | ||
1034 | if (!spec) | ||
1035 | return -ENOMEM; | ||
1036 | /* qtet is clocked by Xilinx array */ | ||
1037 | ice->hw_rates = &qtet_rates_info; | ||
1038 | ice->is_spdif_master = qtet_is_spdif_master; | ||
1039 | ice->get_rate = qtet_get_rate; | ||
1040 | ice->set_rate = qtet_set_rate; | ||
1041 | ice->set_mclk = qtet_set_mclk; | ||
1042 | ice->set_spdif_clock = qtet_set_spdif_clock; | ||
1043 | ice->get_spdif_master_type = qtet_get_spdif_master_type; | ||
1044 | ice->ext_clock_names = ext_clock_names; | ||
1045 | ice->ext_clock_count = ARRAY_SIZE(ext_clock_names); | ||
1046 | /* since Qtet can detect correct SPDIF-in rate, all streams can be | ||
1047 | * limited to this specific rate */ | ||
1048 | ice->spdif.ops.open = ice->pro_open = qtet_spdif_in_open; | ||
1049 | ice->spec = spec; | ||
1050 | |||
1051 | /* Mute Off */ | ||
1052 | /* SCR Initialize*/ | ||
1053 | /* keep codec power down first */ | ||
1054 | set_scr(ice, SCR_PHP); | ||
1055 | udelay(1); | ||
1056 | /* codec power up */ | ||
1057 | set_scr(ice, SCR_PHP | SCR_CODEC_PDN); | ||
1058 | |||
1059 | /* MCR Initialize */ | ||
1060 | set_mcr(ice, 0); | ||
1061 | |||
1062 | /* CPLD Initialize */ | ||
1063 | set_cpld(ice, 0); | ||
1064 | |||
1065 | |||
1066 | ice->num_total_dacs = 2; | ||
1067 | ice->num_total_adcs = 2; | ||
1068 | |||
1069 | ice->akm = kcalloc(2, sizeof(struct snd_akm4xxx), GFP_KERNEL); | ||
1070 | ak = ice->akm; | ||
1071 | if (!ak) | ||
1072 | return -ENOMEM; | ||
1073 | /* only one codec with two chips */ | ||
1074 | ice->akm_codecs = 1; | ||
1075 | err = snd_ice1712_akm4xxx_init(ak, &akm_qtet_dac, NULL, ice); | ||
1076 | if (err < 0) | ||
1077 | return err; | ||
1078 | err = snd_ak4113_create(ice->card, | ||
1079 | qtet_ak4113_read, | ||
1080 | qtet_ak4113_write, | ||
1081 | ak4113_init_vals, | ||
1082 | ice, &spec->ak4113); | ||
1083 | if (err < 0) | ||
1084 | return err; | ||
1085 | /* callback for codecs rate setting */ | ||
1086 | spec->ak4113->change_callback = qtet_ak4113_change; | ||
1087 | spec->ak4113->change_callback_private = ice; | ||
1088 | /* AK41143 in Quartet can detect external rate correctly | ||
1089 | * (i.e. check_flags = 0) */ | ||
1090 | spec->ak4113->check_flags = 0; | ||
1091 | |||
1092 | proc_init(ice); | ||
1093 | |||
1094 | qtet_set_rate(ice, 44100); | ||
1095 | return 0; | ||
1096 | } | ||
1097 | |||
1098 | static unsigned char qtet_eeprom[] __devinitdata = { | ||
1099 | [ICE_EEP2_SYSCONF] = 0x28, /* clock 256(24MHz), mpu401, 1xADC, | ||
1100 | 1xDACs, SPDIF in */ | ||
1101 | [ICE_EEP2_ACLINK] = 0x80, /* I2S */ | ||
1102 | [ICE_EEP2_I2S] = 0x78, /* 96k, 24bit, 192k */ | ||
1103 | [ICE_EEP2_SPDIF] = 0xc3, /* out-en, out-int, in, out-ext */ | ||
1104 | [ICE_EEP2_GPIO_DIR] = 0x00, /* 0-7 inputs, switched to output | ||
1105 | only during output operations */ | ||
1106 | [ICE_EEP2_GPIO_DIR1] = 0xff, /* 8-15 outputs */ | ||
1107 | [ICE_EEP2_GPIO_DIR2] = 0x00, | ||
1108 | [ICE_EEP2_GPIO_MASK] = 0xff, /* changed only for OUT operations */ | ||
1109 | [ICE_EEP2_GPIO_MASK1] = 0x00, | ||
1110 | [ICE_EEP2_GPIO_MASK2] = 0xff, | ||
1111 | |||
1112 | [ICE_EEP2_GPIO_STATE] = 0x00, /* inputs */ | ||
1113 | [ICE_EEP2_GPIO_STATE1] = 0x7d, /* all 1, but GPIO_CPLD_RW | ||
1114 | and GPIO15 always zero */ | ||
1115 | [ICE_EEP2_GPIO_STATE2] = 0x00, /* inputs */ | ||
1116 | }; | ||
1117 | |||
1118 | /* entry point */ | ||
1119 | struct snd_ice1712_card_info snd_vt1724_qtet_cards[] __devinitdata = { | ||
1120 | { | ||
1121 | .subvendor = VT1724_SUBDEVICE_QTET, | ||
1122 | .name = "Infrasonic Quartet", | ||
1123 | .model = "quartet", | ||
1124 | .chip_init = qtet_init, | ||
1125 | .build_controls = qtet_add_controls, | ||
1126 | .eeprom_size = sizeof(qtet_eeprom), | ||
1127 | .eeprom_data = qtet_eeprom, | ||
1128 | }, | ||
1129 | { } /* terminator */ | ||
1130 | }; | ||
diff --git a/sound/pci/ice1712/quartet.h b/sound/pci/ice1712/quartet.h new file mode 100644 index 000000000000..80809b72439a --- /dev/null +++ b/sound/pci/ice1712/quartet.h | |||
@@ -0,0 +1,10 @@ | |||
1 | #ifndef __SOUND_QTET_H | ||
2 | #define __SOUND_QTET_H | ||
3 | |||
4 | #define QTET_DEVICE_DESC "{Infrasonic,Quartet}," | ||
5 | |||
6 | #define VT1724_SUBDEVICE_QTET 0x30305349 /* Infrasonic Quartet */ | ||
7 | |||
8 | extern struct snd_ice1712_card_info snd_vt1724_qtet_cards[]; | ||
9 | |||
10 | #endif /* __SOUND_QTET_H */ | ||