Hello Takashi, Here is a tested patch for Audiotrak Prodigy 192: Fixes:--------* correct card specific ice1724 initialization* working IEC958 output of the card* renamed capture controls New features:------------------* analog input switch (line-in/mic)* optional ak4114 based MI/ODI/O card detection & support: IEC958 input, digital input switch (toslink/coax) Unresolved issues-----------------------* Analog and digital input enums are listed on playback panel of alsamixer, I do not know how to push them onto the capture one. diff -r 42321871a7dc pci/ice1712/prodigy192.c--- a/pci/ice1712/prodigy192.c Thu Apr 05 17:08:57 2007 +0200+++ b/pci/ice1712/prodigy192.c Fri Apr 06 21:23:23 2007 +0200@@ -2,6 +2,28 @@ * ALSA driver for ICEnsemble VT1724 (Envy24HT) * * Lowlevel functions for AudioTrak Prodigy 192 cards+ * Supported IEC958 input from optional MI/ODI/O add-on card.+ *+ * Specifics (SW, HW):+ * -------------------+ * * 49.5MHz crystal+ * * SPDIF-OUT on the card:+ * - coax (through isolation transformer)/toslink supplied by 74HC04 gates - 3 in parallel+ * - output switched between on-board CD drive dig-out connector and ice1724 SPDTX pin,+ * using 74HC02 NOR gates, controlled by GPIO20 (0 = CD dig-out, 1 = SPDTX)+ * * SPDTX goes straight to MI/ODI/O card's SPDIF-OUT coax+ *+ * * MI/ODI/O card: AK4114 based, used for iec958 input only+ * - toslink input -> RX0+ * - coax input -> RX1+ * - 4wire protocol:+ * AK4114 ICE1724+ * ------------------------------+ * CDTO (pin 32) -- GPIO11 pin 86+ * CDTI (pin 33) -- GPIO10 pin 77+ * CCLK (pin 34) -- GPIO9 pin 76+ * CSN (pin 35) -- GPIO8 pin 75+ * - output data Mode 7 (24bit, I2S, slave) * * Copyright (c) 2003 Takashi Iwai <tiwai@xxxxxxx> * Copyright (c) 2003 Dimitromanolakis Apostolos <apostol@xxxxxxxxxxxxxx>@@ -356,6 +378,48 @@ static int aureon_oversampling_put(struc return 0; } #endif+static int stac9460_mic_sw_info(struct snd_kcontrol *kcontrol,+ struct snd_ctl_elem_info *uinfo)+{+ static char *texts[2] = { "Line In", "Mic"};++ uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;+ uinfo->count = 1;+ uinfo->value.enumerated.items = 2;++ if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)+ uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;+ strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);++ return 0;+}+++static int stac9460_mic_sw_get(struct snd_kcontrol *kcontrol,+ struct snd_ctl_elem_value *ucontrol)+{+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);+ unsigned char val;+ + val = stac9460_get(ice, STAC946X_GENERAL_PURPOSE);+ ucontrol->value.enumerated.item[0] = val>>7 & 0x1;+ return 0;+}++static int stac9460_mic_sw_put(struct snd_kcontrol *kcontrol,+ struct snd_ctl_elem_value *ucontrol)+{+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);+ unsigned char new, old;+ int change;+ old = stac9460_get(ice, STAC946X_GENERAL_PURPOSE);+ new = (ucontrol->value.enumerated.item[0]<< 7 & 0x80) | (old & ~0x80);+ change = (new != old);+ if (change) {+ stac9460_put(ice, STAC946X_GENERAL_PURPOSE, new);+ }+ return change;+} static const DECLARE_TLV_DB_SCALE(db_scale_dac, -19125, 75, 0); static const DECLARE_TLV_DB_SCALE(db_scale_adc, 0, 150, 0);@@ -406,7 +470,7 @@ static struct snd_kcontrol_new stac_cont }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER,- .name = "ADC Switch",+ .name = "ADC Capture Switch", .count = 1, .info = stac9460_adc_mute_info, .get = stac9460_adc_mute_get,@@ -417,13 +481,21 @@ static struct snd_kcontrol_new stac_cont .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ),- .name = "ADC Volume",+ .name = "ADC Capture Volume", .count = 1, .info = stac9460_adc_vol_info, .get = stac9460_adc_vol_get, .put = stac9460_adc_vol_put, .tlv = { .p = db_scale_adc } },+ {+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,+ .name = "Analog Capture Input",+ .info = stac9460_mic_sw_info,+ .get = stac9460_mic_sw_get,+ .put = stac9460_mic_sw_put,++ }, #if 0 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER,@@ -456,6 +528,204 @@ static struct snd_kcontrol_new stac_cont #endif }; ++/* AK4114 - ICE1724 connections on Prodigy192 + MI/ODI/O */+/* CDTO (pin 32) -- GPIO11 pin 86+ * CDTI (pin 33) -- GPIO10 pin 77+ * CCLK (pin 34) -- GPIO9 pin 76+ * CSN (pin 35) -- GPIO8 pin 75+ */+#define AK4114_ADDR 0x00 /* C1-C0: Chip Address (According to datasheet fixed to “00”) */++/*+ * 4wire ak4114 protocol - writing data+ */+static void write_data(struct snd_ice1712 *ice, unsigned int gpio,+ unsigned int data, int idx)+{+ for (; idx >= 0; idx--) {+ /* drop clock */+ gpio &= ~VT1724_PRODIGY192_CCLK;+ snd_ice1712_gpio_write(ice, gpio);+ udelay(1);+ /* set data */+ if (data & (1 << idx))+ gpio |= VT1724_PRODIGY192_CDOUT;+ else+ gpio &= ~VT1724_PRODIGY192_CDOUT;+ snd_ice1712_gpio_write(ice, gpio);+ udelay(1);+ /* raise clock */+ gpio |= VT1724_PRODIGY192_CCLK;+ snd_ice1712_gpio_write(ice, gpio);+ udelay(1);+ }+}++/*+ * 4wire ak4114 protocol - reading data+ */+static unsigned char read_data(struct snd_ice1712 *ice, unsigned int gpio,+ int idx)+{+ unsigned char data = 0;++ for (; idx >= 0; idx--) {+ /* drop clock */+ gpio &= ~VT1724_PRODIGY192_CCLK;+ snd_ice1712_gpio_write(ice, gpio);+ udelay(1);+ /* read data */+ if (snd_ice1712_gpio_read(ice) & VT1724_PRODIGY192_CDIN)+ data |= (1 << idx);+ udelay(1);+ /* raise clock */+ gpio |= VT1724_PRODIGY192_CCLK;+ snd_ice1712_gpio_write(ice, gpio);+ udelay(1);+ }+ return data;+}+/*+ * 4wire ak4114 protocol - starting sequence+ */+static unsigned int prodigy192_4wire_start(struct snd_ice1712 *ice)+{+ unsigned int tmp;++ snd_ice1712_save_gpio_status(ice);+ tmp = snd_ice1712_gpio_read(ice);++ tmp |= VT1724_PRODIGY192_CCLK; /* high at init */+ tmp &= ~VT1724_PRODIGY192_CS; /* drop chip select */+ snd_ice1712_gpio_write(ice, tmp);+ udelay(1);+ return tmp;+}++/*+ * 4wire ak4114 protocol - final sequence+ */+static void prodigy192_4wire_finish(struct snd_ice1712 *ice, unsigned int tmp)+{+ tmp |= VT1724_PRODIGY192_CS; /* raise chip select */+ snd_ice1712_gpio_write(ice, tmp);+ udelay(1);+ snd_ice1712_restore_gpio_status(ice);+}++/*+ * Write data to addr register of ak4114 + */+static void prodigy192_ak4114_write(void *private_data, unsigned char addr,+ unsigned char data)+{+ struct snd_ice1712 *ice = private_data;+ unsigned int tmp, addrdata;+ tmp = prodigy192_4wire_start(ice);+ addrdata = (AK4114_ADDR << 6) | 0x20 | (addr & 0x1f);+ addrdata = (addrdata << 8) | data;+ write_data(ice, tmp, addrdata, 15);+ prodigy192_4wire_finish(ice, tmp);+}++/*+ * Read data from addr register of ak4114 + */+static unsigned char prodigy192_ak4114_read(void *private_data, unsigned char addr)+{+ struct snd_ice1712 *ice = private_data;+ unsigned int tmp;+ unsigned char data;++ tmp = prodigy192_4wire_start(ice);+ write_data(ice, tmp, (AK4114_ADDR << 6) | (addr & 0x1f), 7);+ data = read_data(ice, tmp, 7);+ prodigy192_4wire_finish(ice, tmp);+ return data;+}+++static int ak4114_input_sw_info(struct snd_kcontrol *kcontrol,+ struct snd_ctl_elem_info *uinfo)+{+ static char *texts[2] = { "Toslink", "Coax"};++ uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;+ uinfo->count = 1;+ uinfo->value.enumerated.items = 2;+ if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)+ uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;+ strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);+ return 0;+}+++static int ak4114_input_sw_get(struct snd_kcontrol *kcontrol,+ struct snd_ctl_elem_value *ucontrol)+{+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);+ unsigned char val;+ + val = prodigy192_ak4114_read(ice, AK4114_REG_IO1);+ /* AK4114_IPS0 bit = 0 -> RX0 = Toslink+ * AK4114_IPS0 bit = 1 -> RX1 = Coax+ */+ ucontrol->value.enumerated.item[0] = (val & AK4114_IPS0) ? 1 : 0;+ return 0;+}++static int ak4114_input_sw_put(struct snd_kcontrol *kcontrol,+ struct snd_ctl_elem_value *ucontrol)+{+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);+ unsigned char new, old, itemvalue;+ int change;+ old = prodigy192_ak4114_read(ice, AK4114_REG_IO1);+ itemvalue = (ucontrol->value.enumerated.item[0]) ? 0xff : 0x00; /* AK4114_IPS0 could be any bit */++ new = (itemvalue & AK4114_IPS0) | (old & ~AK4114_IPS0);+ change = (new != old);+ if (change) {+ prodigy192_ak4114_write(ice, AK4114_REG_IO1, new);+ }+ return change;+}+++static const struct snd_kcontrol_new ak4114_controls[] __devinitdata = {+ {+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,+ .name = "MIODIO IEC958 Capture Input",+ .info = ak4114_input_sw_info,+ .get = ak4114_input_sw_get,+ .put = ak4114_input_sw_put,++ }+};+++static int prodigy192_ak4114_init(struct snd_ice1712 *ice)+{+ static const unsigned char ak4114_init_vals[] = {+ AK4114_RST | AK4114_PWN | AK4114_OCKS0 | AK4114_OCKS1,+ AK4114_DIF_I24I2S, /* ice1724 expects I2S and provides clock*/+ AK4114_TX1E,+ AK4114_EFH_1024 | AK4114_DIT, /* default input RX0*/+ 0,+ 0+ };+ static const unsigned char ak4114_init_txcsb[] = {+ 0x41, 0x02, 0x2c, 0x00, 0x00+ };++ return snd_ak4114_create(ice->card,+ prodigy192_ak4114_read,+ prodigy192_ak4114_write,+ ak4114_init_vals, ak4114_init_txcsb,+ ice, &ice->spec.prodigy192.ak4114);+}+ static int __devinit prodigy192_add_controls(struct snd_ice1712 *ice) { unsigned int i;@@ -466,9 +736,43 @@ static int __devinit prodigy192_add_cont if (err < 0) return err; }- return 0;-}-+ if (ice->spec.prodigy192.ak4114) {+ /* ak4114 is connected */+ for (i = 0; i < ARRAY_SIZE(ak4114_controls); i++) {+ err = snd_ctl_add(ice->card, snd_ctl_new1(&ak4114_controls[i], ice));+ if (err < 0)+ return err;+ }+ err = snd_ak4114_build(ice->spec.prodigy192.ak4114,+ NULL, /* ak4114 in MIO/DI/O handles no IEC958 output */+ ice->pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream);+ }+ if (err < 0)+ return err;+ return 0;+}++/*+ * check for presence of MI/ODI/O add-on card with digital inputs+ */+static int prodigy192_miodio_exists(struct snd_ice1712 *ice)+{++ unsigned char orig_value;+ const unsigned char test_data = 0xd1; /* random value */+ unsigned char addr = AK4114_REG_INT0_MASK; /* random SAFE address */+ int exists = 0;++ orig_value = prodigy192_ak4114_read(ice, addr);+ prodigy192_ak4114_write(ice, addr, test_data);+ if (prodigy192_ak4114_read(ice, addr) == test_data) {+ /* ak4114 seems to communicate, apparently exists */+ /* writing back original value */+ prodigy192_ak4114_write(ice, addr, orig_value);+ exists = 1;+ }+ return exists;+} /* * initialize the chip@@ -487,16 +791,31 @@ static int __devinit prodigy192_init(str (unsigned short)-1 }; const unsigned short *p;+ int err = 0; /* prodigy 192 */ ice->num_total_dacs = 6; ice->num_total_adcs = 2;+ ice->vt1720= 0; /* ice1724, e.g. 23 GPIOs */ /* initialize codec */ p = stac_inits_prodigy; for (; *p != (unsigned short)-1; p += 2) stac9460_put(ice, p[0], p[1]); ++ /* MI/ODI/O add on card with AK4114 */+ if (prodigy192_miodio_exists(ice)) {+ err = prodigy192_ak4114_init(ice);+ /* from this moment if err = 0 then ice->spec.prodigy192.ak4114 should not be null */+ //printk(KERN_DEBUG "AK4114 initialized with status %d\n", err);+ }+ else {+ //printk(KERN_DEBUG "AK4114 not found\n");+ }+ if (err < 0)+ return err;+ return 0; } @@ -507,19 +826,19 @@ static int __devinit prodigy192_init(str */ static unsigned char prodigy71_eeprom[] __devinitdata = {- [ICE_EEP2_SYSCONF] = 0x2b, /* clock 512, mpu401, spdif-in/ADC, 4DACs */+ [ICE_EEP2_SYSCONF] = 0x6a, /* 49MHz crystal, mpu401, spdif-in+ 1 stereo ADC, 3 stereo DACs */ [ICE_EEP2_ACLINK] = 0x80, /* I2S */ [ICE_EEP2_I2S] = 0xf8, /* vol, 96k, 24bit, 192k */ [ICE_EEP2_SPDIF] = 0xc3, /* out-en, out-int, spdif-in */ [ICE_EEP2_GPIO_DIR] = 0xff,- [ICE_EEP2_GPIO_DIR1] = 0xff,+ [ICE_EEP2_GPIO_DIR1] = ~(VT1724_PRODIGY192_CDIN >> 8) , [ICE_EEP2_GPIO_DIR2] = 0xbf, [ICE_EEP2_GPIO_MASK] = 0x00, [ICE_EEP2_GPIO_MASK1] = 0x00, [ICE_EEP2_GPIO_MASK2] = 0x00, [ICE_EEP2_GPIO_STATE] = 0x00, [ICE_EEP2_GPIO_STATE1] = 0x00,- [ICE_EEP2_GPIO_STATE2] = 0x00,+ [ICE_EEP2_GPIO_STATE2] = 0x10, /* GPIO20: 0 = CD drive dig. output, 1 = SPDIF-OUT from ice1724 */ }; diff -r 42321871a7dc pci/ice1712/prodigy192.h--- a/pci/ice1712/prodigy192.h Thu Apr 05 17:08:57 2007 +0200+++ b/pci/ice1712/prodigy192.h Fri Apr 06 20:30:12 2007 +0200@@ -5,6 +5,13 @@ #define PRODIGY192_STAC9460_ADDR 0x54 #define VT1724_SUBDEVICE_PRODIGY192VE 0x34495345 /* PRODIGY 192 VE */+/*+ * AudioTrak Prodigy192 GPIO definitions for MI/ODI/O card with AK4114 (SPDIF-IN)+ */+#define VT1724_PRODIGY192_CS (1 << 8) /*GPIO8, pin 75 */+#define VT1724_PRODIGY192_CCLK (1 << 9) /*GPIO9, pin 76 */+#define VT1724_PRODIGY192_CDOUT (1 << 10) /*GPIO10, pin 77 */+#define VT1724_PRODIGY192_CDIN (1 << 11) /*GPIO11, pin 86 */ extern struct snd_ice1712_card_info snd_vt1724_prodigy192_cards[]; _______________________________________________Alsa-devel mailing listAlsa-devel@xxxxxxxxxxxxxxxxxxxx://mailman.alsa-project.org/mailman/listinfo/alsa-devel