2 * ALSA driver for ICEnsemble VT1724 (Envy24HT)
4 * Lowlevel functions for AudioTrak Prodigy 192 cards
5 * Supported IEC958 input from optional MI/ODI/O add-on card.
10 * * SPDIF-OUT on the card:
11 * - coax (through isolation transformer)/toslink supplied by
12 * 74HC04 gates - 3 in parallel
13 * - output switched between on-board CD drive dig-out connector
14 * and ice1724 SPDTX pin, using 74HC02 NOR gates, controlled
15 * by GPIO20 (0 = CD dig-out, 1 = SPDTX)
16 * * SPDTX goes straight to MI/ODI/O card's SPDIF-OUT coax
18 * * MI/ODI/O card: AK4114 based, used for iec958 input only
19 * - toslink input -> RX0
23 * ------------------------------
24 * CDTO (pin 32) -- GPIO11 pin 86
25 * CDTI (pin 33) -- GPIO10 pin 77
26 * CCLK (pin 34) -- GPIO9 pin 76
27 * CSN (pin 35) -- GPIO8 pin 75
28 * - output data Mode 7 (24bit, I2S, slave)
30 * Copyright (c) 2003 Takashi Iwai <tiwai@suse.de>
31 * Copyright (c) 2003 Dimitromanolakis Apostolos <apostol@cs.utoronto.ca>
32 * Copyright (c) 2004 Kouichi ONO <co2b@ceres.dti.ne.jp>
34 * This program is free software; you can redistribute it and/or modify
35 * it under the terms of the GNU General Public License as published by
36 * the Free Software Foundation; either version 2 of the License, or
37 * (at your option) any later version.
39 * This program is distributed in the hope that it will be useful,
40 * but WITHOUT ANY WARRANTY; without even the implied warranty of
41 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
42 * GNU General Public License for more details.
44 * You should have received a copy of the GNU General Public License
45 * along with this program; if not, write to the Free Software
46 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
50 #include <sound/driver.h>
52 #include <linux/delay.h>
53 #include <linux/interrupt.h>
54 #include <linux/init.h>
55 #include <linux/slab.h>
56 #include <sound/core.h>
60 #include "prodigy192.h"
62 #include <sound/tlv.h>
64 static inline void stac9460_put(struct snd_ice1712 *ice, int reg, unsigned char val)
66 snd_vt1724_write_i2c(ice, PRODIGY192_STAC9460_ADDR, reg, val);
69 static inline unsigned char stac9460_get(struct snd_ice1712 *ice, int reg)
71 return snd_vt1724_read_i2c(ice, PRODIGY192_STAC9460_ADDR, reg);
77 static int stac9460_dac_mute_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
79 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
81 uinfo->value.integer.min = 0;
82 uinfo->value.integer.max = 1;
86 static int stac9460_dac_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
88 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
92 if (kcontrol->private_value)
93 idx = STAC946X_MASTER_VOLUME;
95 idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id) + STAC946X_LF_VOLUME;
96 val = stac9460_get(ice, idx);
97 ucontrol->value.integer.value[0] = (~val >> 7) & 0x1;
101 static int stac9460_dac_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
103 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
104 unsigned char new, old;
108 if (kcontrol->private_value)
109 idx = STAC946X_MASTER_VOLUME;
111 idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id) + STAC946X_LF_VOLUME;
112 old = stac9460_get(ice, idx);
113 new = (~ucontrol->value.integer.value[0]<< 7 & 0x80) | (old & ~0x80);
114 change = (new != old);
116 stac9460_put(ice, idx, new);
122 * DAC volume attenuation mixer control
124 static int stac9460_dac_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
126 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
128 uinfo->value.integer.min = 0; /* mute */
129 uinfo->value.integer.max = 0x7f; /* 0dB */
133 static int stac9460_dac_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
135 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
139 if (kcontrol->private_value)
140 idx = STAC946X_MASTER_VOLUME;
142 idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id) + STAC946X_LF_VOLUME;
143 vol = stac9460_get(ice, idx) & 0x7f;
144 ucontrol->value.integer.value[0] = 0x7f - vol;
149 static int stac9460_dac_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
151 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
153 unsigned char tmp, ovol, nvol;
156 if (kcontrol->private_value)
157 idx = STAC946X_MASTER_VOLUME;
159 idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id) + STAC946X_LF_VOLUME;
160 nvol = ucontrol->value.integer.value[0];
161 tmp = stac9460_get(ice, idx);
162 ovol = 0x7f - (tmp & 0x7f);
163 change = (ovol != nvol);
165 stac9460_put(ice, idx, (0x7f - nvol) | (tmp & 0x80));
173 static int stac9460_adc_mute_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
175 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
177 uinfo->value.integer.min = 0;
178 uinfo->value.integer.max = 1;
182 static int stac9460_adc_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
184 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
188 for (i = 0; i < 2; ++i) {
189 val = stac9460_get(ice, STAC946X_MIC_L_VOLUME + i);
190 ucontrol->value.integer.value[i] = ~val>>7 & 0x1;
196 static int stac9460_adc_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
198 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
199 unsigned char new, old;
203 for (i = 0; i < 2; ++i) {
204 reg = STAC946X_MIC_L_VOLUME + i;
205 old = stac9460_get(ice, reg);
206 new = (~ucontrol->value.integer.value[i]<<7&0x80) | (old&~0x80);
207 change = (new != old);
209 stac9460_put(ice, reg, new);
216 * ADC gain mixer control
218 static int stac9460_adc_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
220 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
222 uinfo->value.integer.min = 0; /* 0dB */
223 uinfo->value.integer.max = 0x0f; /* 22.5dB */
227 static int stac9460_adc_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
229 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
233 for (i = 0; i < 2; ++i) {
234 reg = STAC946X_MIC_L_VOLUME + i;
235 vol = stac9460_get(ice, reg) & 0x0f;
236 ucontrol->value.integer.value[i] = 0x0f - vol;
242 static int stac9460_adc_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
244 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
246 unsigned char ovol, nvol;
249 for (i = 0; i < 2; ++i) {
250 reg = STAC946X_MIC_L_VOLUME + i;
251 nvol = ucontrol->value.integer.value[i];
252 ovol = 0x0f - stac9460_get(ice, reg);
253 change = ((ovol & 0x0f) != nvol);
255 stac9460_put(ice, reg, (0x0f - nvol) | (ovol & ~0x0f));
263 * Headphone Amplifier
265 static int aureon_set_headphone_amp(struct snd_ice1712 *ice, int enable)
267 unsigned int tmp, tmp2;
269 tmp2 = tmp = snd_ice1712_gpio_read(ice);
271 tmp |= AUREON_HP_SEL;
273 tmp &= ~ AUREON_HP_SEL;
275 snd_ice1712_gpio_write(ice, tmp);
281 static int aureon_get_headphone_amp(struct snd_ice1712 *ice)
283 unsigned int tmp = snd_ice1712_gpio_read(ice);
285 return ( tmp & AUREON_HP_SEL )!= 0;
288 static int aureon_bool_info(struct snd_kcontrol *k, struct snd_ctl_elem_info *uinfo)
290 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
292 uinfo->value.integer.min = 0;
293 uinfo->value.integer.max = 1;
297 static int aureon_hpamp_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
299 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
301 ucontrol->value.integer.value[0] = aureon_get_headphone_amp(ice);
306 static int aureon_hpamp_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
308 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
310 return aureon_set_headphone_amp(ice,ucontrol->value.integer.value[0]);
316 static int aureon_deemp_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
318 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
319 ucontrol->value.integer.value[0] = (wm_get(ice, WM_DAC_CTRL2) & 0xf) == 0xf;
323 static int aureon_deemp_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
325 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
327 temp2 = temp = wm_get(ice, WM_DAC_CTRL2);
328 if (ucontrol->value.integer.value[0])
333 wm_put(ice, WM_DAC_CTRL2, temp);
342 static int aureon_oversampling_info(struct snd_kcontrol *k, struct snd_ctl_elem_info *uinfo)
344 static char *texts[2] = { "128x", "64x" };
346 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
348 uinfo->value.enumerated.items = 2;
350 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
351 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
352 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
357 static int aureon_oversampling_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
359 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
360 ucontrol->value.enumerated.item[0] = (wm_get(ice, WM_MASTER) & 0x8) == 0x8;
364 static int aureon_oversampling_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
367 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
369 temp2 = temp = wm_get(ice, WM_MASTER);
371 if (ucontrol->value.enumerated.item[0])
377 wm_put(ice, WM_MASTER, temp);
383 static int stac9460_mic_sw_info(struct snd_kcontrol *kcontrol,
384 struct snd_ctl_elem_info *uinfo)
386 static char *texts[2] = { "Line In", "Mic" };
388 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
390 uinfo->value.enumerated.items = 2;
392 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
393 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
394 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
400 static int stac9460_mic_sw_get(struct snd_kcontrol *kcontrol,
401 struct snd_ctl_elem_value *ucontrol)
403 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
406 val = stac9460_get(ice, STAC946X_GENERAL_PURPOSE);
407 ucontrol->value.enumerated.item[0] = (val >> 7) & 0x1;
411 static int stac9460_mic_sw_put(struct snd_kcontrol *kcontrol,
412 struct snd_ctl_elem_value *ucontrol)
414 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
415 unsigned char new, old;
417 old = stac9460_get(ice, STAC946X_GENERAL_PURPOSE);
418 new = (ucontrol->value.enumerated.item[0] << 7 & 0x80) | (old & ~0x80);
419 change = (new != old);
421 stac9460_put(ice, STAC946X_GENERAL_PURPOSE, new);
425 static const DECLARE_TLV_DB_SCALE(db_scale_dac, -19125, 75, 0);
426 static const DECLARE_TLV_DB_SCALE(db_scale_adc, 0, 150, 0);
432 static struct snd_kcontrol_new stac_controls[] __devinitdata = {
434 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
435 .name = "Master Playback Switch",
436 .info = stac9460_dac_mute_info,
437 .get = stac9460_dac_mute_get,
438 .put = stac9460_dac_mute_put,
440 .tlv = { .p = db_scale_dac }
443 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
444 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
445 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
446 .name = "Master Playback Volume",
447 .info = stac9460_dac_vol_info,
448 .get = stac9460_dac_vol_get,
449 .put = stac9460_dac_vol_put,
451 .tlv = { .p = db_scale_dac }
454 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
455 .name = "DAC Switch",
457 .info = stac9460_dac_mute_info,
458 .get = stac9460_dac_mute_get,
459 .put = stac9460_dac_mute_put,
462 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
463 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
464 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
465 .name = "DAC Volume",
467 .info = stac9460_dac_vol_info,
468 .get = stac9460_dac_vol_get,
469 .put = stac9460_dac_vol_put,
470 .tlv = { .p = db_scale_dac }
473 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
474 .name = "ADC Capture Switch",
476 .info = stac9460_adc_mute_info,
477 .get = stac9460_adc_mute_get,
478 .put = stac9460_adc_mute_put,
482 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
483 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
484 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
485 .name = "ADC Capture Volume",
487 .info = stac9460_adc_vol_info,
488 .get = stac9460_adc_vol_get,
489 .put = stac9460_adc_vol_put,
490 .tlv = { .p = db_scale_adc }
493 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
494 .name = "Analog Capture Input",
495 .info = stac9460_mic_sw_info,
496 .get = stac9460_mic_sw_get,
497 .put = stac9460_mic_sw_put,
502 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
503 .name = "Capture Route",
504 .info = wm_adc_mux_info,
505 .get = wm_adc_mux_get,
506 .put = wm_adc_mux_put,
509 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
510 .name = "Headphone Amplifier Switch",
511 .info = aureon_bool_info,
512 .get = aureon_hpamp_get,
513 .put = aureon_hpamp_put
516 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
517 .name = "DAC Deemphasis Switch",
518 .info = aureon_bool_info,
519 .get = aureon_deemp_get,
520 .put = aureon_deemp_put
523 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
524 .name = "ADC Oversampling",
525 .info = aureon_oversampling_info,
526 .get = aureon_oversampling_get,
527 .put = aureon_oversampling_put
533 /* AK4114 - ICE1724 connections on Prodigy192 + MI/ODI/O */
534 /* CDTO (pin 32) -- GPIO11 pin 86
535 * CDTI (pin 33) -- GPIO10 pin 77
536 * CCLK (pin 34) -- GPIO9 pin 76
537 * CSN (pin 35) -- GPIO8 pin 75
539 #define AK4114_ADDR 0x00 /* C1-C0: Chip Address
540 * (According to datasheet fixed to “00”)
544 * 4wire ak4114 protocol - writing data
546 static void write_data(struct snd_ice1712 *ice, unsigned int gpio,
547 unsigned int data, int idx)
549 for (; idx >= 0; idx--) {
551 gpio &= ~VT1724_PRODIGY192_CCLK;
552 snd_ice1712_gpio_write(ice, gpio);
555 if (data & (1 << idx))
556 gpio |= VT1724_PRODIGY192_CDOUT;
558 gpio &= ~VT1724_PRODIGY192_CDOUT;
559 snd_ice1712_gpio_write(ice, gpio);
562 gpio |= VT1724_PRODIGY192_CCLK;
563 snd_ice1712_gpio_write(ice, gpio);
569 * 4wire ak4114 protocol - reading data
571 static unsigned char read_data(struct snd_ice1712 *ice, unsigned int gpio,
574 unsigned char data = 0;
576 for (; idx >= 0; idx--) {
578 gpio &= ~VT1724_PRODIGY192_CCLK;
579 snd_ice1712_gpio_write(ice, gpio);
582 if (snd_ice1712_gpio_read(ice) & VT1724_PRODIGY192_CDIN)
586 gpio |= VT1724_PRODIGY192_CCLK;
587 snd_ice1712_gpio_write(ice, gpio);
593 * 4wire ak4114 protocol - starting sequence
595 static unsigned int prodigy192_4wire_start(struct snd_ice1712 *ice)
599 snd_ice1712_save_gpio_status(ice);
600 tmp = snd_ice1712_gpio_read(ice);
602 tmp |= VT1724_PRODIGY192_CCLK; /* high at init */
603 tmp &= ~VT1724_PRODIGY192_CS; /* drop chip select */
604 snd_ice1712_gpio_write(ice, tmp);
610 * 4wire ak4114 protocol - final sequence
612 static void prodigy192_4wire_finish(struct snd_ice1712 *ice, unsigned int tmp)
614 tmp |= VT1724_PRODIGY192_CS; /* raise chip select */
615 snd_ice1712_gpio_write(ice, tmp);
617 snd_ice1712_restore_gpio_status(ice);
621 * Write data to addr register of ak4114
623 static void prodigy192_ak4114_write(void *private_data, unsigned char addr,
626 struct snd_ice1712 *ice = private_data;
627 unsigned int tmp, addrdata;
628 tmp = prodigy192_4wire_start(ice);
629 addrdata = (AK4114_ADDR << 6) | 0x20 | (addr & 0x1f);
630 addrdata = (addrdata << 8) | data;
631 write_data(ice, tmp, addrdata, 15);
632 prodigy192_4wire_finish(ice, tmp);
636 * Read data from addr register of ak4114
638 static unsigned char prodigy192_ak4114_read(void *private_data,
641 struct snd_ice1712 *ice = private_data;
645 tmp = prodigy192_4wire_start(ice);
646 write_data(ice, tmp, (AK4114_ADDR << 6) | (addr & 0x1f), 7);
647 data = read_data(ice, tmp, 7);
648 prodigy192_4wire_finish(ice, tmp);
653 static int ak4114_input_sw_info(struct snd_kcontrol *kcontrol,
654 struct snd_ctl_elem_info *uinfo)
656 static char *texts[2] = { "Toslink", "Coax" };
658 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
660 uinfo->value.enumerated.items = 2;
661 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
662 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
663 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
668 static int ak4114_input_sw_get(struct snd_kcontrol *kcontrol,
669 struct snd_ctl_elem_value *ucontrol)
671 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
674 val = prodigy192_ak4114_read(ice, AK4114_REG_IO1);
675 /* AK4114_IPS0 bit = 0 -> RX0 = Toslink
676 * AK4114_IPS0 bit = 1 -> RX1 = Coax
678 ucontrol->value.enumerated.item[0] = (val & AK4114_IPS0) ? 1 : 0;
682 static int ak4114_input_sw_put(struct snd_kcontrol *kcontrol,
683 struct snd_ctl_elem_value *ucontrol)
685 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
686 unsigned char new, old, itemvalue;
689 old = prodigy192_ak4114_read(ice, AK4114_REG_IO1);
690 /* AK4114_IPS0 could be any bit */
691 itemvalue = (ucontrol->value.enumerated.item[0]) ? 0xff : 0x00;
693 new = (itemvalue & AK4114_IPS0) | (old & ~AK4114_IPS0);
694 change = (new != old);
696 prodigy192_ak4114_write(ice, AK4114_REG_IO1, new);
701 static const struct snd_kcontrol_new ak4114_controls[] __devinitdata = {
703 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
704 .name = "MIODIO IEC958 Capture Input",
705 .info = ak4114_input_sw_info,
706 .get = ak4114_input_sw_get,
707 .put = ak4114_input_sw_put,
713 static int prodigy192_ak4114_init(struct snd_ice1712 *ice)
715 static const unsigned char ak4114_init_vals[] = {
716 AK4114_RST | AK4114_PWN | AK4114_OCKS0 | AK4114_OCKS1,
717 AK4114_DIF_I24I2S, /* ice1724 expects I2S and provides clock */
719 AK4114_EFH_1024 | AK4114_DIT, /* default input RX0 */
723 static const unsigned char ak4114_init_txcsb[] = {
724 0x41, 0x02, 0x2c, 0x00, 0x00
727 return snd_ak4114_create(ice->card,
728 prodigy192_ak4114_read,
729 prodigy192_ak4114_write,
730 ak4114_init_vals, ak4114_init_txcsb,
731 ice, &ice->spec.prodigy192.ak4114);
734 static int __devinit prodigy192_add_controls(struct snd_ice1712 *ice)
739 for (i = 0; i < ARRAY_SIZE(stac_controls); i++) {
740 err = snd_ctl_add(ice->card,
741 snd_ctl_new1(&stac_controls[i], ice));
745 if (ice->spec.prodigy192.ak4114) {
746 /* ak4114 is connected */
747 for (i = 0; i < ARRAY_SIZE(ak4114_controls); i++) {
748 err = snd_ctl_add(ice->card,
749 snd_ctl_new1(&ak4114_controls[i],
754 err = snd_ak4114_build(ice->spec.prodigy192.ak4114,
755 NULL, /* ak4114 in MIO/DI/O handles no IEC958 output */
756 ice->pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream);
764 * check for presence of MI/ODI/O add-on card with digital inputs
766 static int prodigy192_miodio_exists(struct snd_ice1712 *ice)
769 unsigned char orig_value;
770 const unsigned char test_data = 0xd1; /* random value */
771 unsigned char addr = AK4114_REG_INT0_MASK; /* random SAFE address */
774 orig_value = prodigy192_ak4114_read(ice, addr);
775 prodigy192_ak4114_write(ice, addr, test_data);
776 if (prodigy192_ak4114_read(ice, addr) == test_data) {
777 /* ak4114 seems to communicate, apparently exists */
778 /* writing back original value */
779 prodigy192_ak4114_write(ice, addr, orig_value);
786 * initialize the chip
788 static int __devinit prodigy192_init(struct snd_ice1712 *ice)
790 static const unsigned short stac_inits_prodigy[] = {
792 /* STAC946X_MASTER_VOLUME, 0,
793 STAC946X_LF_VOLUME, 0,
794 STAC946X_RF_VOLUME, 0,
795 STAC946X_LR_VOLUME, 0,
796 STAC946X_RR_VOLUME, 0,
797 STAC946X_CENTER_VOLUME, 0,
798 STAC946X_LFE_VOLUME, 0,*/
801 const unsigned short *p;
805 ice->num_total_dacs = 6;
806 ice->num_total_adcs = 2;
807 ice->vt1720 = 0; /* ice1724, e.g. 23 GPIOs */
809 /* initialize codec */
810 p = stac_inits_prodigy;
811 for (; *p != (unsigned short)-1; p += 2)
812 stac9460_put(ice, p[0], p[1]);
814 /* MI/ODI/O add on card with AK4114 */
815 if (prodigy192_miodio_exists(ice)) {
816 err = prodigy192_ak4114_init(ice);
817 /* from this moment if err = 0 then
818 * ice->spec.prodigy192.ak4114 should not be null
820 snd_printdd("AK4114 initialized with status %d\n", err);
822 snd_printdd("AK4114 not found\n");
831 * Aureon boards don't provide the EEPROM data except for the vendor IDs.
832 * hence the driver needs to sets up it properly.
835 static unsigned char prodigy71_eeprom[] __devinitdata = {
836 [ICE_EEP2_SYSCONF] = 0x6a, /* 49MHz crystal, mpu401,
837 * spdif-in+ 1 stereo ADC,
840 [ICE_EEP2_ACLINK] = 0x80, /* I2S */
841 [ICE_EEP2_I2S] = 0xf8, /* vol, 96k, 24bit, 192k */
842 [ICE_EEP2_SPDIF] = 0xc3, /* out-en, out-int, spdif-in */
843 [ICE_EEP2_GPIO_DIR] = 0xff,
844 [ICE_EEP2_GPIO_DIR1] = ~(VT1724_PRODIGY192_CDIN >> 8) ,
845 [ICE_EEP2_GPIO_DIR2] = 0xbf,
846 [ICE_EEP2_GPIO_MASK] = 0x00,
847 [ICE_EEP2_GPIO_MASK1] = 0x00,
848 [ICE_EEP2_GPIO_MASK2] = 0x00,
849 [ICE_EEP2_GPIO_STATE] = 0x00,
850 [ICE_EEP2_GPIO_STATE1] = 0x00,
851 [ICE_EEP2_GPIO_STATE2] = 0x10, /* GPIO20: 0 = CD drive dig. input
853 * 1 = SPDIF-OUT from ice1724
859 struct snd_ice1712_card_info snd_vt1724_prodigy192_cards[] __devinitdata = {
861 .subvendor = VT1724_SUBDEVICE_PRODIGY192VE,
862 .name = "Audiotrak Prodigy 192",
863 .model = "prodigy192",
864 .chip_init = prodigy192_init,
865 .build_controls = prodigy192_add_controls,
866 .eeprom_size = sizeof(prodigy71_eeprom),
867 .eeprom_data = prodigy71_eeprom,