Meanwhile I discover Linux during my studies, and the digital music possibilities.
Instead of buying a new card I write the driver, thanks to the Open Source.
So it's a driver for the Ego Sys Waterminal 192M only (I don't have a 192L or 192X card to test driver support)
I join the patch which contain the source file, and the modification needed
The patch is based on the 1.0.14rc1 driver source file (which compile correctly on my computer if you want to know)
also the ice1724 driver is in the kernel directory, I put my driver in the "alsa-source/pci/ice1724" directory as wanted for test it.
I test my driver with jack and music software associated, during a long time for stability, and it's working fine with a clean sound
the Ego Sys Waveterminal192M is composed of :
- 1 Via Envy24ht chip
- 2 sigmatel stac9640 (like the one in prodigy192) for the 4 ADC and 8 DAC needed
- 1 ak4114 (as the Ego Sys Julia) for S/PDIF
Work :
- the 8 analog outputs
- analog inputs 1&2
- mic input 1
- integrated S/PDIF output
- extern S/PDIF output
- optical output
Don't Work (for the moment !) :
- midi I/O
- analog inputs 3&4
- mic input 2
- S/PDIF input
- optical input
And I would ask if the midi has even working on a ice1724 card ? Because there is so few function in ice1724.c and just one value in my driver source for midi management, but it's freeze my computer when I want to read or write my midi port. I don't see what can be the problem.
I hope you will put my driver in the alsa tree
thanks
diff -urN --exclude=sound alsa-driver-1.0.14rc1.old/alsa-kernel/pci/ice1712/ice1724.c alsa-driver-1.0.14rc1/alsa-kernel/pci/ice1712/ice1724.c --- alsa-driver-1.0.14rc1.old/alsa-kernel/pci/ice1712/ice1724.c 2006-12-11 21:04:12.000000000 +0100 +++ alsa-driver-1.0.14rc1/alsa-kernel/pci/ice1712/ice1724.c 2006-12-11 21:10:16.000000000 +0100 @@ -50,7 +50,7 @@ #include "prodigy192.h" #include "juli.h" #include "phase.h" - +#include "wtm.h" MODULE_AUTHOR("Jaroslav Kysela <perex@xxxxxxx>"); MODULE_DESCRIPTION("VIA ICEnsemble ICE1724/1720 (Envy24HT/PT)"); @@ -64,6 +64,7 @@ PRODIGY192_DEVICE_DESC JULI_DEVICE_DESC PHASE_DEVICE_DESC + WTM_DEVICE_DESC "{VIA,VT1720}," "{VIA,VT1724}," "{ICEnsemble,Generic ICE1724}," @@ -1958,6 +1959,7 @@ snd_vt1724_prodigy192_cards, snd_vt1724_juli_cards, snd_vt1724_phase_cards, + snd_vt1724_WTM_cards, NULL, }; diff -urN --exclude=sound alsa-driver-1.0.14rc1.old/alsa-kernel/pci/ice1712/Makefile alsa-driver-1.0.14rc1/alsa-kernel/pci/ice1712/Makefile --- alsa-driver-1.0.14rc1.old/alsa-kernel/pci/ice1712/Makefile 2006-12-11 21:04:12.000000000 +0100 +++ alsa-driver-1.0.14rc1/alsa-kernel/pci/ice1712/Makefile 2006-12-11 21:07:04.000000000 +0100 @@ -5,7 +5,7 @@ snd-ice17xx-ak4xxx-objs := ak4xxx.o snd-ice1712-objs := ice1712.o delta.o hoontech.o ews.o -snd-ice1724-objs := ice1724.o amp.o revo.o aureon.o vt1720_mobo.o pontis.o prodigy192.o juli.o phase.o +snd-ice1724-objs := ice1724.o amp.o revo.o aureon.o vt1720_mobo.o pontis.o prodigy192.o juli.o phase.o wtm.o # Toplevel Module Dependency obj-$(CONFIG_SND_ICE1712) += snd-ice1712.o snd-ice17xx-ak4xxx.o diff -urN --exclude=sound alsa-driver-1.0.14rc1.old/alsa-kernel/pci/ice1712/wtm.h alsa-driver-1.0.14rc1/alsa-kernel/pci/ice1712/wtm.h --- alsa-driver-1.0.14rc1.old/alsa-kernel/pci/ice1712/wtm.h 1970-01-01 01:00:00.000000000 +0100 +++ alsa-driver-1.0.14rc1/alsa-kernel/pci/ice1712/wtm.h 2006-12-11 21:06:28.000000000 +0100 @@ -0,0 +1,21 @@ +#ifndef __SOUND_WTM_H +#define __SOUND_WTM_H + +//ID +#define WTM_DEVICE_DESC "{EGO SYS INC,WaveTerminal 192M}," + +#define VT1724_SUBDEVICE_WTM 0x36495345 /* WT192M ver1.0 */ + +/* + *chip addresses on I2C bus + */ + +#define AK4114_ADDR 0x20 /*S/PDIF receiver*/ +#define STAC9460_I2C_ADDR 0x54 /* ADC*2 | DAC*6 */ +#define STAC9460_2_I2C_ADDR 0x56 /* ADC|DAC *2 */ + + +extern struct snd_ice1712_card_info snd_vt1724_WTM_cards[]; + +#endif /* __SOUND_WTM_H */ + diff -urN --exclude=sound alsa-driver-1.0.14rc1.old/pci/ice1712/wtm.c alsa-driver-1.0.14rc1/pci/ice1712/wtm.c --- alsa-driver-1.0.14rc1.old/pci/ice1712/wtm.c 1970-01-01 01:00:00.000000000 +0100 +++ alsa-driver-1.0.14rc1/pci/ice1712/wtm.c 2006-12-12 00:17:16.000000000 +0100 @@ -0,0 +1,510 @@ +/* + * ALSA driver for ICEnsemble VT1724 (Envy24HT) + * + * Lowlevel functions for Ego Sys Waveterminal 192M + * + * Copyright (c) 2006 Guedez Clement <klem.dev@xxxxxxxxx> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + + + +#include <sound/driver.h> +#include <asm/io.h> +#include <linux/delay.h> +#include <linux/interrupt.h> +#include <linux/init.h> +#include <linux/slab.h> +#include <sound/core.h> + +#include "../../alsa-kernel/pci/ice1712/ice1712.h" +#include "../../alsa-kernel/pci/ice1712/envy24ht.h" +#include "../../alsa-kernel/pci/ice1712/wtm.h" +#include "../../alsa-kernel/pci/ice1712/stac946x.h" + + +/* + * 2*ADC 6*DAC no1 ringbuffer r/w on i2c bus + */ + +static inline void stac9460_put(struct snd_ice1712 *ice, int reg, unsigned char val) +{ + snd_vt1724_write_i2c(ice, STAC9460_I2C_ADDR, reg, val); +} +static inline unsigned char stac9460_get(struct snd_ice1712 *ice, int reg) +{ + return snd_vt1724_read_i2c(ice, STAC9460_I2C_ADDR, reg); +} + +/* + * 2*ADC 2*DAC no2 ringbuffer r/w on i2c bus + */ +static inline void stac9460_2_put(struct snd_ice1712 *ice, int reg, unsigned char val) +{ + snd_vt1724_write_i2c(ice, STAC9460_2_I2C_ADDR, reg, val); +} +static inline unsigned char stac9460_2_get(struct snd_ice1712 *ice, int reg) +{ + return snd_vt1724_read_i2c(ice, STAC9460_2_I2C_ADDR, reg); +} + +/* + * DAC mute control + */ +static int stac9460_dac_mute_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; + uinfo->count = 1; + uinfo->value.integer.min = 0; + return 0; +} +static int stac9460_dac_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) +{ + struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); + unsigned char val; + int idx,id; + + if (kcontrol->private_value){ + idx = STAC946X_MASTER_VOLUME; + id=0; + } + else{ + id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); + idx = id + STAC946X_LF_VOLUME; + } + if(id<6) val = stac9460_get(ice, idx); + else val = stac9460_2_get(ice,idx-6); + ucontrol->value.integer.value[0] = (~val >> 7) & 0x1; + return 0; +} + +static int stac9460_dac_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) +{ + struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); + unsigned char new, old; + int id,idx; + int change; + + if (kcontrol->private_value){ + idx = STAC946X_MASTER_VOLUME; + old = stac9460_get(ice, idx); + new = (~ucontrol->value.integer.value[0]<< 7 & 0x80) | (old & ~0x80); + change = (new != old); + if (change){ + stac9460_put(ice, idx, new); + stac9460_2_put(ice, idx, new); + } + } + else{ + id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); + idx = id + STAC946X_LF_VOLUME; + if(id<6) old = stac9460_get(ice, idx); + else old = stac9460_2_get(ice, idx-6); + new = (~ucontrol->value.integer.value[0]<< 7 & 0x80) | (old & ~0x80); + change = (new != old); + if (change){ + if(id<6) stac9460_put(ice, idx, new); + else stac9460_2_put(ice, idx-6, new); + } + } + return change; +} + +/* + * DAC volume attenuation mixer control + */ +static int stac9460_dac_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + uinfo->count = 1; + uinfo->value.integer.min = 0; /* mute */ + uinfo->value.integer.max = 0x7f; /* 0dB */ + return 0; +} +static int stac9460_dac_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) +{ + struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); + int idx,id; + unsigned char vol; + if (kcontrol->private_value){ + idx = STAC946X_MASTER_VOLUME; + id=0; + } + else{ + id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); + idx = id + STAC946X_LF_VOLUME; + } + if(id<6) vol = stac9460_get(ice, idx) & 0x7f; + else vol = stac9460_2_get(ice, idx-6) & 0x7f; + ucontrol->value.integer.value[0] = 0x7f - vol; + + return 0; +} +static int stac9460_dac_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) +{ + struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); + int idx,id; + unsigned char tmp, ovol, nvol; + int change; + + if (kcontrol->private_value){ + idx = STAC946X_MASTER_VOLUME; + nvol = ucontrol->value.integer.value[0]; + tmp = stac9460_get(ice, idx); + ovol = 0x7f - (tmp & 0x7f); + change = (ovol != nvol); + if (change) { + stac9460_put(ice, idx, (0x7f - nvol) | (tmp & 0x80)); + stac9460_2_put(ice, idx, (0x7f - nvol) | (tmp & 0x80)); + } + } + else{ + id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); + idx = id + STAC946X_LF_VOLUME; + nvol = ucontrol->value.integer.value[0]; + if(id<6) tmp = stac9460_get(ice, idx); + else tmp = stac9460_2_get(ice, idx-6); + ovol = 0x7f - (tmp & 0x7f); + change = (ovol != nvol); + if (change) { + if(id<6) stac9460_put(ice, idx, (0x7f - nvol) | (tmp & 0x80)); + else stac9460_2_put(ice, idx-6, (0x7f - nvol) | (tmp & 0x80)); + } + } + return change; +} + +/* + * ADC mute control + */ +static int stac9460_adc_mute_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; + uinfo->count = 2; + uinfo->value.integer.min = 0; + uinfo->value.integer.max = 1; + return 0; +} +static int stac9460_adc_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) +{ + struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); + unsigned char val; + int i,id; + + id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); + + if(id==0){ + for (i = 0; i < 2; ++i) { + val = stac9460_get(ice, STAC946X_MIC_L_VOLUME + i); + ucontrol->value.integer.value[i] = ~val>>7 & 0x1; + } + } + else{ + for (i = 0; i < 2; ++i) { + val = stac9460_2_get(ice, STAC946X_MIC_L_VOLUME + i); + ucontrol->value.integer.value[i] = ~val>>7 & 0x1; + } + } + return 0; +} +static int stac9460_adc_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) +{ + struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); + unsigned char new, old; + int i, reg,id; + int change; + + id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); + + if(id==0){ + for (i = 0; i < 2; ++i) { + reg = STAC946X_MIC_L_VOLUME + i; + old = stac9460_get(ice, reg); + new = (~ucontrol->value.integer.value[i]<<7&0x80) | (old&~0x80); + change = (new != old); + if (change) + stac9460_put(ice, reg, new); + } + } + else{ + for (i = 0; i < 2; ++i) { + reg = STAC946X_MIC_L_VOLUME + i; + old = stac9460_2_get(ice, reg); + new = (~ucontrol->value.integer.value[i]<<7&0x80) | (old&~0x80); + change = (new != old); + if (change) + stac9460_2_put(ice, reg, new); + } + } + return change; +} +/* + *ADC gain mixer control + */ +static int stac9460_adc_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + uinfo->count = 2; + uinfo->value.integer.min = 0; /* 0dB */ + uinfo->value.integer.max = 0x0f; /* 22.5dB */ + return 0; +} +static int stac9460_adc_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) +{ + struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); + int i, reg,id; + unsigned char vol; + + id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); + + if(id==0){ + for (i = 0; i < 2; ++i) { + reg = STAC946X_MIC_L_VOLUME + i; + vol = stac9460_get(ice, reg) & 0x0f; + ucontrol->value.integer.value[i] = 0x0f - vol; + } + } + else{ + for (i = 0; i < 2; ++i) { + reg = STAC946X_MIC_L_VOLUME + i; + vol = stac9460_2_get(ice, reg) & 0x0f; + ucontrol->value.integer.value[i] = 0x0f - vol; + } + } + return 0; +} +static int stac9460_adc_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) +{ + struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); + int i, reg,id; + unsigned char ovol, nvol; + int change; + + id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); + + if(id==0){ + for (i = 0; i < 2; ++i) { + reg = STAC946X_MIC_L_VOLUME + i; + nvol = ucontrol->value.integer.value[i]; + ovol = 0x0f - stac9460_get(ice, reg); + change = ((ovol & 0x0f) != nvol); + if (change) + stac9460_put(ice, reg, (0x0f - nvol) | (ovol & ~0x0f)); + } + } + else{ + for (i = 0; i < 2; ++i) { + reg = STAC946X_MIC_L_VOLUME + i; + nvol = ucontrol->value.integer.value[i]; + ovol = 0x0f - stac9460_2_get(ice, reg); + change = ((ovol & 0x0f) != nvol); + if (change) + stac9460_2_put(ice, reg, (0x0f - nvol) | (ovol & ~0x0f)); + } + } + return change; +} + +/* + * MIC / LINE switch fonction + */ + +static int stac9460_mic_sw_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; + uinfo->count = 1; + uinfo->value.integer.min = 0; + uinfo->value.integer.max = 1; + 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; + int id; + + id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); + + if(id==0) val = stac9460_get(ice, STAC946X_GENERAL_PURPOSE); + if(id==1) val = stac9460_2_get(ice, STAC946X_GENERAL_PURPOSE); + ucontrol->value.integer.value[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,id; + + id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); + + if(id==0) old = stac9460_get(ice, STAC946X_GENERAL_PURPOSE); + if(id==1) old = stac9460_2_get(ice, STAC946X_GENERAL_PURPOSE); + new = (~ucontrol->value.integer.value[0]<< 7 & 0x80) | (old & ~0x80); + change = (new != old); + if (change) + { + if(id==0) stac9460_put(ice, STAC946X_GENERAL_PURPOSE, new); + if(id==1) stac9460_2_put(ice, STAC946X_GENERAL_PURPOSE, new); + } + return change; +} + +/* + * Control tabs + */ + +static struct snd_kcontrol_new stac9640_controls[] __devinitdata = { + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Master Playback Switch", + .info = stac9460_dac_mute_info, + .get = stac9460_dac_mute_get, + .put = stac9460_dac_mute_put, + .private_value = 1 + }, + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Master Playback Volume", + .info = stac9460_dac_vol_info, + .get = stac9460_dac_vol_get, + .put = stac9460_dac_vol_put, + .private_value = 1, + }, + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "MIC/Line switch", + .count = 2, + .info = stac9460_mic_sw_info, + .get = stac9460_mic_sw_get, + .put = stac9460_mic_sw_put, + + }, + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "DAC Switch", + .count = 8, + .info = stac9460_dac_mute_info, + .get = stac9460_dac_mute_get, + .put = stac9460_dac_mute_put, + }, + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "DAC Volume", + .count = 8, + .info = stac9460_dac_vol_info, + .get = stac9460_dac_vol_get, + .put = stac9460_dac_vol_put, + }, + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "ADC Switch", + .count = 2, + .info = stac9460_adc_mute_info, + .get = stac9460_adc_mute_get, + .put = stac9460_adc_mute_put, + }, + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "ADC Volume", + .count = 2, + .info = stac9460_adc_vol_info, + .get = stac9460_adc_vol_get, + .put = stac9460_adc_vol_put, + + } +}; + + + + + +/*INIT*/ + +static int __devinit WTM_add_controls(struct snd_ice1712 *ice) +{ + unsigned int i; + int err; + + for(i = 0; i < ARRAY_SIZE(stac9640_controls); i++) { + err = snd_ctl_add(ice->card, snd_ctl_new1(&stac9640_controls[i], ice)); + if (err < 0) + return err; + } + return 0; +} + +static int __devinit WTM_init(struct snd_ice1712 *ice) +{ + static unsigned short stac_inits_prodigy[] = { + STAC946X_RESET, 0, + (unsigned short)-1 + }; + unsigned short *p; + + + /*WTM 192M*/ + ice->num_total_dacs = 8; + ice->num_total_adcs = 4; + ice->force_rdma1=1; + + /*initialize codec*/ + p = stac_inits_prodigy; + for (; *p != (unsigned short)-1; p += 2) + { + stac9460_put(ice, p[0], p[1]); + stac9460_2_put(ice, p[0], p[1]); + } + + return 0; +} + + +static unsigned char WTM_eeprom[] __devinitdata = { + 0x47, /*SYSCONF: clock 192KHz, 4ADC, 8DAC */ +// 0x67, /* SYSCONF: clock 192KHz, mpu401, 4ADC, 8 DAC */ + 0x80, /* ACLINK : I2S */ + 0xf8, /* I2S: vol; 96k, 24bit, 192k */ + 0xc1 /*SPDIF: out-en, spidf ext out*/, + //0xc3, /* SPDIF: out-en, spdif-ext i/o*/ + 0x9f, /* GPIO_DIR */ + 0xff, /* GPIO_DIR1 */ + 0x7f, /* GPIO_DIR2 */ + 0x9f, /* GPIO_MASK */ + 0xff, /* GPIO_MASK1 */ + 0x7f, /* GPIO_MASK2 */ + 0x16, /* GPIO_STATE */ + 0x80, /* GPIO_STATE1 */ + 0x00, /* GPIO_STATE2 */ +}; + + + + +/*entry point*/ +struct snd_ice1712_card_info snd_vt1724_WTM_cards[] __devinitdata = { + { + .subvendor = VT1724_SUBDEVICE_WTM, + .name = "Ego Sys Waveterminal 192M", + .model = "WT192M", + .chip_init = WTM_init, + .build_controls = WTM_add_controls, + .eeprom_size = sizeof(WTM_eeprom), + .eeprom_data = WTM_eeprom, + }, + {} /*terminator*/ +};
------------------------------------------------------------------------- Take Surveys. Earn Cash. Influence the Future of IT Join SourceForge.net's Techsay panel and you'll get the chance to share your opinions on IT & business topics through brief surveys - and earn cash http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________ Alsa-devel mailing list Alsa-devel@xxxxxxxxxxxxxxxxxxxxx https://lists.sourceforge.net/lists/listinfo/alsa-devel