On Tue, Sep 14, 2010 at 2:17 AM, Alan Horstmann gineera@aspect135.co.uk wrote:
I am trying to explain that there are 2 parts to this. The envy24 chip has config registers that are set up at init, in ice1712.c. Look for the uses of 'dxr_enable', and you will see that the ICE_EEP1_CODEC register is set to 0x60 unless its a DMX6fire. Terratec clearly change these at run-time (on Windows), as does the StAudio driver for DSP2000, but the Alsa driver sets this up at init only. Thus I am saying there is no mechanism in the driver to disable the digital stream pairs.
The other part, however, is the controls to switch the SPDIF etc inputs, specific to the EWS88D (and similar functions for the other cards). These are available to change at run-time. As the control get/set funcs are unique to the EWS88D there may be previously undetected bugs in them. The '6fire and DSP2000 controls do work fine, if comparison is any use. It comes down to use of 'printk()' and careful tracing of the failures!
I was thinking it might be something like this, and that the values I see in alsamixer/amixer reflect the start-up values set http://git.alsa-project.org/?p=alsa-kernel.git;a=blob_plain;f=sound/pci/ice1...
static struct snd_kcontrol_new snd_ice1712_ews88d_controls[] __devinitdata = { EWS88D_CONTROL(SNDRV_CTL_ELEM_IFACE_MIXER, "IEC958 Input Optical", 0, 1, 0), /* inverted */ EWS88D_CONTROL(SNDRV_CTL_ELEM_IFACE_MIXER, "ADAT Output Optical", 1, 0, 0), EWS88D_CONTROL(SNDRV_CTL_ELEM_IFACE_MIXER, "ADAT External Master Clock", 2, 0, 0), EWS88D_CONTROL(SNDRV_CTL_ELEM_IFACE_MIXER, "Enable ADAT", 3, 0, 0), EWS88D_CONTROL(SNDRV_CTL_ELEM_IFACE_MIXER, "ADAT Through", 4, 1, 0), };
Is there a better way of changing these defaults prior to start-up time other than recompiling?? Oh, and if I were to recompile and try to replace my existing snd-ice1712.so on my fedora12 setup (Runtime ALSA library: 1.0.23, Runtime ALSA drivers: 1.0.21) could I build against 1.0.23, or would I need to go back and build against a 1.0.21 to match all the other drivers and the rest of ALSA? ... I should probably wait till I've actually setup the fedora-13-based system for which this card is intended. That already runs 1.0.23 drivers anyways.
Also, the asymmetry between similar "put" code for the EWS88D and the DMX6Fire is striking. Isn't snd_ice1712_ews88d_control_put() doing something like setting the value to the same thing no matter whether true or false??
if (invert) { if (! ucontrol->value.integer.value[0]) ndata[shift >> 3] |= (1 << (shift & 7)); } else { if (ucontrol->value.integer.value[0]) ndata[shift >> 3] |= (1 << (shift & 7)); } change = (data[shift >> 3] != ndata[shift >> 3]);
Is there documentation or external comments on all these rather squirrely and obtuse data structures, perhaps remedying complaint at https://www.ohloh.net/p/alsa -- "Few source code comments" ?? ... Anybody explain what all those shifts and ands and or's actually do?
static int snd_ice1712_ews88d_control_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); struct ews_spec *spec = ice->spec; int shift = kcontrol->private_value & 0xff; int invert = (kcontrol->private_value >> 8) & 1; unsigned char data[2], ndata[2]; int change;
snd_i2c_lock(ice->i2c); if (snd_i2c_readbytes(spec->i2cdevs[EWS_I2C_88D], data, 2) != 2) { snd_i2c_unlock(ice->i2c); return -EIO; } ndata[shift >> 3] = data[shift >> 3] & ~(1 << (shift & 7)); if (invert) { if (! ucontrol->value.integer.value[0]) ndata[shift >> 3] |= (1 << (shift & 7)); } else { if (ucontrol->value.integer.value[0]) ndata[shift >> 3] |= (1 << (shift & 7)); } change = (data[shift >> 3] != ndata[shift >> 3]); if (change && snd_i2c_sendbytes(spec->i2cdevs[EWS_I2C_88D], data, 2) != 2) { snd_i2c_unlock(ice->i2c); return -EIO; } snd_i2c_unlock(ice->i2c); return change; }
static int snd_ice1712_6fire_control_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); int shift = kcontrol->private_value & 0xff; int invert = (kcontrol->private_value >> 8) & 1; int data, ndata; if ((data = snd_ice1712_6fire_read_pca(ice, PCF9554_REG_OUTPUT)) < 0) return data; ndata = data & ~(1 << shift); if (ucontrol->value.integer.value[0]) ndata |= (1 << shift); if (invert) ndata ^= (1 << shift); if (data != ndata) { snd_ice1712_6fire_write_pca(ice, PCF9554_REG_OUTPUT, (unsigned char)ndata); return 1; } return 0; }
-- Niels http://nielsmayer.com