+ },
+ .dac_info = juli_dac,
+};
+
+#define juli_mute_info snd_ctl_boolean_mono_info
+
+static int juli_mute_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
+ unsigned int val;
+ val = ice->gpio.get_data(ice) & (unsigned int) kcontrol->private_value;
+ if (kcontrol->private_value == GPIO_MUTE_CONTROL)
+ /* val 0 = signal on */
+ ucontrol->value.integer.value[0] = (val) ? 0 : 1;
+ else
+ /* val 1 = signal on */
+ ucontrol->value.integer.value[0] = (val) ? 1 : 0;
+ return 0;
+}
+
+static int juli_mute_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
+ unsigned int old_gpio, new_gpio;
+ old_gpio = ice->gpio.get_data(ice);
+ if (ucontrol->value.integer.value[0]) {
+ /* unmute */
+ if (kcontrol->private_value == GPIO_MUTE_CONTROL) {
+ /* 0 = signal on */
+ new_gpio = old_gpio & ~GPIO_MUTE_CONTROL;
+ /* un-smuting DAC */
+ snd_akm4xxx_write(ice->akm, 0, 0x01, 0x01);
+ } else
+ /* 1 = signal on */
+ new_gpio = old_gpio |
+ (unsigned int) kcontrol->private_value;
+ } else {
+ /* mute */
+ if (kcontrol->private_value == GPIO_MUTE_CONTROL) {
+ /* 1 = signal off */
+ new_gpio = old_gpio | GPIO_MUTE_CONTROL;
+ /* smuting DAC */
+ snd_akm4xxx_write(ice->akm, 0, 0x01, 0x03);
+ } else
+ /* 0 = signal off */
+ new_gpio = old_gpio &
+ ~((unsigned int) kcontrol->private_value);
+ }
+ /* printk("JULI - mute/unmute: control_value: 0x%x, old_gpio: 0x%x, \
+ new_gpio 0x%x\n",
+ (unsigned int)ucontrol->value.integer.value[0], old_gpio,
+ new_gpio); */
+ if (old_gpio != new_gpio) {
+ ice->gpio.set_data(ice, new_gpio);
+ return 1;
+ }
+ /* no change */
+ return 0;
+}
+
+static struct snd_kcontrol_new juli_mute_controls[] __devinitdata = {
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Master Playback Switch",
+ .info = juli_mute_info,
+ .get = juli_mute_get,
+ .put = juli_mute_put,
+ .private_value = GPIO_MUTE_CONTROL,
+ },
+ /* Although the following functionality respects the succint NDA'd
+ * documentation from the card manufacturer, and the same way of
+ * operation is coded in OSS Juli driver, only Digital Out monitor
+ * seems to work. Surprisingly, Analog input monitor outputs Digital
+ * output data. The two are independent, as enabling both doubles
+ * volume of the monitor sound.
+ *
+ * Checking traces on the board suggests the functionality described
+ * by the manufacturer is correct - I2S from ADC and AK4114
+ * go to ICE as well as to Xilinx, I2S inputs of DAC2,3,4 (the monitor
+ * inputs) are fed from Xilinx.
+ *
+ * I even checked traces on board and coded a support in driver for
+ * an alternative possiblity - the unused I2S ICE output channels
+ * switched to HW-IN/SPDIF-IN and providing the monitoring signal to
+ * the DAC - to no avail. The I2S outputs seem to be unconnected.
+ *
+ * The windows driver supports the monitoring correctly.
+ */
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Monitor Analog In Switch",
+ .info = juli_mute_info,
+ .get = juli_mute_get,
+ .put = juli_mute_put,
+ .private_value = GPIO_ANAIN_MONITOR,
+ },
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Monitor Digital Out Switch",
+ .info = juli_mute_info,
+ .get = juli_mute_get,
+ .put = juli_mute_put,
+ .private_value = GPIO_DIGOUT_MONITOR,
+ },
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Monitor Digital In Switch",
+ .info = juli_mute_info,
+ .get = juli_mute_get,
+ .put = juli_mute_put,
+ .private_value = GPIO_DIGIN_MONITOR,
+ },
+};
+
+
+static void ak4358_proc_regs_read(struct snd_info_entry *entry,
+ struct snd_info_buffer *buffer)
+{
+ struct snd_ice1712 *ice = (struct snd_ice1712 *)entry->private_data;
+ int reg, val;
+ for (reg = 0; reg <= 0xf; reg++) {
+ val = snd_akm4xxx_get(ice->akm, 0, reg);
+ snd_iprintf(buffer, "0x%02x = 0x%02x\n", reg, val);