1f6cdab5fSClement Guedez /* 2f6cdab5fSClement Guedez * ALSA driver for ICEnsemble VT1724 (Envy24HT) 3f6cdab5fSClement Guedez * 4f6cdab5fSClement Guedez * Lowlevel functions for Ego Sys Waveterminal 192M 5f6cdab5fSClement Guedez * 6f6cdab5fSClement Guedez * Copyright (c) 2006 Guedez Clement <klem.dev@gmail.com> 7f6cdab5fSClement Guedez * Some functions are taken from the Prodigy192 driver 8f6cdab5fSClement Guedez * source 9f6cdab5fSClement Guedez * 10f6cdab5fSClement Guedez * This program is free software; you can redistribute it and/or modify 11f6cdab5fSClement Guedez * it under the terms of the GNU General Public License as published by 12f6cdab5fSClement Guedez * the Free Software Foundation; either version 2 of the License, or 13f6cdab5fSClement Guedez * (at your option) any later version. 14f6cdab5fSClement Guedez * 15f6cdab5fSClement Guedez * This program is distributed in the hope that it will be useful, 16f6cdab5fSClement Guedez * but WITHOUT ANY WARRANTY; without even the implied warranty of 17f6cdab5fSClement Guedez * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18f6cdab5fSClement Guedez * GNU General Public License for more details. 19f6cdab5fSClement Guedez * 20f6cdab5fSClement Guedez * You should have received a copy of the GNU General Public License 21f6cdab5fSClement Guedez * along with this program; if not, write to the Free Software 22f6cdab5fSClement Guedez * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 23f6cdab5fSClement Guedez * 24f6cdab5fSClement Guedez */ 25f6cdab5fSClement Guedez 26f6cdab5fSClement Guedez 27f6cdab5fSClement Guedez 28f6cdab5fSClement Guedez #include <sound/driver.h> 29f6cdab5fSClement Guedez #include <asm/io.h> 30f6cdab5fSClement Guedez #include <linux/delay.h> 31f6cdab5fSClement Guedez #include <linux/interrupt.h> 32f6cdab5fSClement Guedez #include <linux/init.h> 33f6cdab5fSClement Guedez #include <linux/slab.h> 34f6cdab5fSClement Guedez #include <sound/core.h> 35f6cdab5fSClement Guedez 36f6cdab5fSClement Guedez #include "ice1712.h" 37f6cdab5fSClement Guedez #include "envy24ht.h" 38f6cdab5fSClement Guedez #include "wtm.h" 39f6cdab5fSClement Guedez #include "stac946x.h" 40f6cdab5fSClement Guedez 41f6cdab5fSClement Guedez 42f6cdab5fSClement Guedez /* 43f6cdab5fSClement Guedez * 2*ADC 6*DAC no1 ringbuffer r/w on i2c bus 44f6cdab5fSClement Guedez */ 45f6cdab5fSClement Guedez static inline void stac9460_put(struct snd_ice1712 *ice, int reg, 46f6cdab5fSClement Guedez unsigned char val) 47f6cdab5fSClement Guedez { 48f6cdab5fSClement Guedez snd_vt1724_write_i2c(ice, STAC9460_I2C_ADDR, reg, val); 49f6cdab5fSClement Guedez } 50f6cdab5fSClement Guedez 51f6cdab5fSClement Guedez static inline unsigned char stac9460_get(struct snd_ice1712 *ice, int reg) 52f6cdab5fSClement Guedez { 53f6cdab5fSClement Guedez return snd_vt1724_read_i2c(ice, STAC9460_I2C_ADDR, reg); 54f6cdab5fSClement Guedez } 55f6cdab5fSClement Guedez 56f6cdab5fSClement Guedez /* 57f6cdab5fSClement Guedez * 2*ADC 2*DAC no2 ringbuffer r/w on i2c bus 58f6cdab5fSClement Guedez */ 59f6cdab5fSClement Guedez static inline void stac9460_2_put(struct snd_ice1712 *ice, int reg, 60f6cdab5fSClement Guedez unsigned char val) 61f6cdab5fSClement Guedez { 62f6cdab5fSClement Guedez snd_vt1724_write_i2c(ice, STAC9460_2_I2C_ADDR, reg, val); 63f6cdab5fSClement Guedez } 64f6cdab5fSClement Guedez 65f6cdab5fSClement Guedez static inline unsigned char stac9460_2_get(struct snd_ice1712 *ice, int reg) 66f6cdab5fSClement Guedez { 67f6cdab5fSClement Guedez return snd_vt1724_read_i2c(ice, STAC9460_2_I2C_ADDR, reg); 68f6cdab5fSClement Guedez } 69f6cdab5fSClement Guedez 70f6cdab5fSClement Guedez 71f6cdab5fSClement Guedez /* 72f6cdab5fSClement Guedez * DAC mute control 73f6cdab5fSClement Guedez */ 74a5ce8890STakashi Iwai #define stac9460_dac_mute_info snd_ctl_boolean_mono_info 75f6cdab5fSClement Guedez 76f6cdab5fSClement Guedez static int stac9460_dac_mute_get(struct snd_kcontrol *kcontrol, 77f6cdab5fSClement Guedez struct snd_ctl_elem_value *ucontrol) 78f6cdab5fSClement Guedez { 79f6cdab5fSClement Guedez struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 80f6cdab5fSClement Guedez unsigned char val; 81f6cdab5fSClement Guedez int idx, id; 82f6cdab5fSClement Guedez 83f6cdab5fSClement Guedez if (kcontrol->private_value) { 84f6cdab5fSClement Guedez idx = STAC946X_MASTER_VOLUME; 85f6cdab5fSClement Guedez id = 0; 86f6cdab5fSClement Guedez } else { 87f6cdab5fSClement Guedez id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); 88f6cdab5fSClement Guedez idx = id + STAC946X_LF_VOLUME; 89f6cdab5fSClement Guedez } 90f6cdab5fSClement Guedez if (id < 6) 91f6cdab5fSClement Guedez val = stac9460_get(ice, idx); 92f6cdab5fSClement Guedez else 93f6cdab5fSClement Guedez val = stac9460_2_get(ice,idx - 6); 94f6cdab5fSClement Guedez ucontrol->value.integer.value[0] = (~val >> 7) & 0x1; 95f6cdab5fSClement Guedez return 0; 96f6cdab5fSClement Guedez } 97f6cdab5fSClement Guedez 98f6cdab5fSClement Guedez static int stac9460_dac_mute_put(struct snd_kcontrol *kcontrol, 99f6cdab5fSClement Guedez struct snd_ctl_elem_value *ucontrol) 100f6cdab5fSClement Guedez { 101f6cdab5fSClement Guedez struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 102f6cdab5fSClement Guedez unsigned char new, old; 103f6cdab5fSClement Guedez int id, idx; 104f6cdab5fSClement Guedez int change; 105f6cdab5fSClement Guedez 106f6cdab5fSClement Guedez if (kcontrol->private_value) { 107f6cdab5fSClement Guedez idx = STAC946X_MASTER_VOLUME; 108f6cdab5fSClement Guedez old = stac9460_get(ice, idx); 109f6cdab5fSClement Guedez new = (~ucontrol->value.integer.value[0]<< 7 & 0x80) | 110f6cdab5fSClement Guedez (old & ~0x80); 111f6cdab5fSClement Guedez change = (new != old); 112f6cdab5fSClement Guedez if (change) { 113f6cdab5fSClement Guedez stac9460_put(ice, idx, new); 114f6cdab5fSClement Guedez stac9460_2_put(ice, idx, new); 115f6cdab5fSClement Guedez } 116f6cdab5fSClement Guedez } else { 117f6cdab5fSClement Guedez id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); 118f6cdab5fSClement Guedez idx = id + STAC946X_LF_VOLUME; 119f6cdab5fSClement Guedez if (id < 6) 120f6cdab5fSClement Guedez old = stac9460_get(ice, idx); 121f6cdab5fSClement Guedez else 122f6cdab5fSClement Guedez old = stac9460_2_get(ice, idx - 6); 123f6cdab5fSClement Guedez new = (~ucontrol->value.integer.value[0]<< 7 & 0x80) | 124f6cdab5fSClement Guedez (old & ~0x80); 125f6cdab5fSClement Guedez change = (new != old); 126f6cdab5fSClement Guedez if (change) { 127f6cdab5fSClement Guedez if (id < 6) 128f6cdab5fSClement Guedez stac9460_put(ice, idx, new); 129f6cdab5fSClement Guedez else 130f6cdab5fSClement Guedez stac9460_2_put(ice, idx - 6, new); 131f6cdab5fSClement Guedez } 132f6cdab5fSClement Guedez } 133f6cdab5fSClement Guedez return change; 134f6cdab5fSClement Guedez } 135f6cdab5fSClement Guedez 136f6cdab5fSClement Guedez /* 137f6cdab5fSClement Guedez * DAC volume attenuation mixer control 138f6cdab5fSClement Guedez */ 139f6cdab5fSClement Guedez static int stac9460_dac_vol_info(struct snd_kcontrol *kcontrol, 140f6cdab5fSClement Guedez struct snd_ctl_elem_info *uinfo) 141f6cdab5fSClement Guedez { 142f6cdab5fSClement Guedez uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 143f6cdab5fSClement Guedez uinfo->count = 1; 144f6cdab5fSClement Guedez uinfo->value.integer.min = 0; /* mute */ 145f6cdab5fSClement Guedez uinfo->value.integer.max = 0x7f; /* 0dB */ 146f6cdab5fSClement Guedez return 0; 147f6cdab5fSClement Guedez } 148f6cdab5fSClement Guedez 149f6cdab5fSClement Guedez static int stac9460_dac_vol_get(struct snd_kcontrol *kcontrol, 150f6cdab5fSClement Guedez struct snd_ctl_elem_value *ucontrol) 151f6cdab5fSClement Guedez { 152f6cdab5fSClement Guedez struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 153f6cdab5fSClement Guedez int idx, id; 154f6cdab5fSClement Guedez unsigned char vol; 155f6cdab5fSClement Guedez 156f6cdab5fSClement Guedez if (kcontrol->private_value) { 157f6cdab5fSClement Guedez idx = STAC946X_MASTER_VOLUME; 158f6cdab5fSClement Guedez id = 0; 159f6cdab5fSClement Guedez } else { 160f6cdab5fSClement Guedez id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); 161f6cdab5fSClement Guedez idx = id + STAC946X_LF_VOLUME; 162f6cdab5fSClement Guedez } 163f6cdab5fSClement Guedez if (id < 6) 164f6cdab5fSClement Guedez vol = stac9460_get(ice, idx) & 0x7f; 165f6cdab5fSClement Guedez else 166f6cdab5fSClement Guedez vol = stac9460_2_get(ice, idx - 6) & 0x7f; 167f6cdab5fSClement Guedez ucontrol->value.integer.value[0] = 0x7f - vol; 168f6cdab5fSClement Guedez return 0; 169f6cdab5fSClement Guedez } 170f6cdab5fSClement Guedez 171f6cdab5fSClement Guedez static int stac9460_dac_vol_put(struct snd_kcontrol *kcontrol, 172f6cdab5fSClement Guedez struct snd_ctl_elem_value *ucontrol) 173f6cdab5fSClement Guedez { 174f6cdab5fSClement Guedez struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 175f6cdab5fSClement Guedez int idx, id; 176f6cdab5fSClement Guedez unsigned char tmp, ovol, nvol; 177f6cdab5fSClement Guedez int change; 178f6cdab5fSClement Guedez 179f6cdab5fSClement Guedez if (kcontrol->private_value) { 180f6cdab5fSClement Guedez idx = STAC946X_MASTER_VOLUME; 181*9cd17cd2STakashi Iwai nvol = ucontrol->value.integer.value[0] & 0x7f; 182f6cdab5fSClement Guedez tmp = stac9460_get(ice, idx); 183f6cdab5fSClement Guedez ovol = 0x7f - (tmp & 0x7f); 184f6cdab5fSClement Guedez change = (ovol != nvol); 185f6cdab5fSClement Guedez if (change) { 186f6cdab5fSClement Guedez stac9460_put(ice, idx, (0x7f - nvol) | (tmp & 0x80)); 187f6cdab5fSClement Guedez stac9460_2_put(ice, idx, (0x7f - nvol) | (tmp & 0x80)); 188f6cdab5fSClement Guedez } 189f6cdab5fSClement Guedez } else { 190f6cdab5fSClement Guedez id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); 191f6cdab5fSClement Guedez idx = id + STAC946X_LF_VOLUME; 192*9cd17cd2STakashi Iwai nvol = ucontrol->value.integer.value[0] & 0x7f; 193f6cdab5fSClement Guedez if (id < 6) 194f6cdab5fSClement Guedez tmp = stac9460_get(ice, idx); 195f6cdab5fSClement Guedez else 196f6cdab5fSClement Guedez tmp = stac9460_2_get(ice, idx - 6); 197f6cdab5fSClement Guedez ovol = 0x7f - (tmp & 0x7f); 198f6cdab5fSClement Guedez change = (ovol != nvol); 199f6cdab5fSClement Guedez if (change) { 200f6cdab5fSClement Guedez if (id < 6) 201f6cdab5fSClement Guedez stac9460_put(ice, idx, (0x7f - nvol) | 202f6cdab5fSClement Guedez (tmp & 0x80)); 203f6cdab5fSClement Guedez else 204f6cdab5fSClement Guedez stac9460_2_put(ice, idx-6, (0x7f - nvol) | 205f6cdab5fSClement Guedez (tmp & 0x80)); 206f6cdab5fSClement Guedez } 207f6cdab5fSClement Guedez } 208f6cdab5fSClement Guedez return change; 209f6cdab5fSClement Guedez } 210f6cdab5fSClement Guedez 211f6cdab5fSClement Guedez /* 212f6cdab5fSClement Guedez * ADC mute control 213f6cdab5fSClement Guedez */ 214a5ce8890STakashi Iwai #define stac9460_adc_mute_info snd_ctl_boolean_stereo_info 215f6cdab5fSClement Guedez 216f6cdab5fSClement Guedez static int stac9460_adc_mute_get(struct snd_kcontrol *kcontrol, 217f6cdab5fSClement Guedez struct snd_ctl_elem_value *ucontrol) 218f6cdab5fSClement Guedez { 219f6cdab5fSClement Guedez struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 220f6cdab5fSClement Guedez unsigned char val; 221f6cdab5fSClement Guedez int i, id; 222f6cdab5fSClement Guedez 223f6cdab5fSClement Guedez id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); 224f6cdab5fSClement Guedez if (id == 0) { 225f6cdab5fSClement Guedez for (i = 0; i < 2; ++i) { 226f6cdab5fSClement Guedez val = stac9460_get(ice, STAC946X_MIC_L_VOLUME + i); 227f6cdab5fSClement Guedez ucontrol->value.integer.value[i] = ~val>>7 & 0x1; 228f6cdab5fSClement Guedez } 229f6cdab5fSClement Guedez } else { 230f6cdab5fSClement Guedez for (i = 0; i < 2; ++i) { 231f6cdab5fSClement Guedez val = stac9460_2_get(ice, STAC946X_MIC_L_VOLUME + i); 232f6cdab5fSClement Guedez ucontrol->value.integer.value[i] = ~val>>7 & 0x1; 233f6cdab5fSClement Guedez } 234f6cdab5fSClement Guedez } 235f6cdab5fSClement Guedez return 0; 236f6cdab5fSClement Guedez } 237f6cdab5fSClement Guedez 238f6cdab5fSClement Guedez static int stac9460_adc_mute_put(struct snd_kcontrol *kcontrol, 239f6cdab5fSClement Guedez struct snd_ctl_elem_value *ucontrol) 240f6cdab5fSClement Guedez { 241f6cdab5fSClement Guedez struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 242f6cdab5fSClement Guedez unsigned char new, old; 243f6cdab5fSClement Guedez int i, reg, id; 244f6cdab5fSClement Guedez int change; 245f6cdab5fSClement Guedez 246f6cdab5fSClement Guedez id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); 247f6cdab5fSClement Guedez if (id == 0) { 248f6cdab5fSClement Guedez for (i = 0; i < 2; ++i) { 249f6cdab5fSClement Guedez reg = STAC946X_MIC_L_VOLUME + i; 250f6cdab5fSClement Guedez old = stac9460_get(ice, reg); 251f6cdab5fSClement Guedez new = (~ucontrol->value.integer.value[i]<<7&0x80) | 252f6cdab5fSClement Guedez (old&~0x80); 253f6cdab5fSClement Guedez change = (new != old); 254f6cdab5fSClement Guedez if (change) 255f6cdab5fSClement Guedez stac9460_put(ice, reg, new); 256f6cdab5fSClement Guedez } 257f6cdab5fSClement Guedez } else { 258f6cdab5fSClement Guedez for (i = 0; i < 2; ++i) { 259f6cdab5fSClement Guedez reg = STAC946X_MIC_L_VOLUME + i; 260f6cdab5fSClement Guedez old = stac9460_2_get(ice, reg); 261f6cdab5fSClement Guedez new = (~ucontrol->value.integer.value[i]<<7&0x80) | 262f6cdab5fSClement Guedez (old&~0x80); 263f6cdab5fSClement Guedez change = (new != old); 264f6cdab5fSClement Guedez if (change) 265f6cdab5fSClement Guedez stac9460_2_put(ice, reg, new); 266f6cdab5fSClement Guedez } 267f6cdab5fSClement Guedez } 268f6cdab5fSClement Guedez return change; 269f6cdab5fSClement Guedez } 270f6cdab5fSClement Guedez 271f6cdab5fSClement Guedez /* 272f6cdab5fSClement Guedez *ADC gain mixer control 273f6cdab5fSClement Guedez */ 274f6cdab5fSClement Guedez static int stac9460_adc_vol_info(struct snd_kcontrol *kcontrol, 275f6cdab5fSClement Guedez struct snd_ctl_elem_info *uinfo) 276f6cdab5fSClement Guedez { 277f6cdab5fSClement Guedez uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 278f6cdab5fSClement Guedez uinfo->count = 2; 279f6cdab5fSClement Guedez uinfo->value.integer.min = 0; /* 0dB */ 280f6cdab5fSClement Guedez uinfo->value.integer.max = 0x0f; /* 22.5dB */ 281f6cdab5fSClement Guedez return 0; 282f6cdab5fSClement Guedez } 283f6cdab5fSClement Guedez 284f6cdab5fSClement Guedez static int stac9460_adc_vol_get(struct snd_kcontrol *kcontrol, 285f6cdab5fSClement Guedez struct snd_ctl_elem_value *ucontrol) 286f6cdab5fSClement Guedez { 287f6cdab5fSClement Guedez struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 288f6cdab5fSClement Guedez int i, reg, id; 289f6cdab5fSClement Guedez unsigned char vol; 290f6cdab5fSClement Guedez 291f6cdab5fSClement Guedez id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); 292f6cdab5fSClement Guedez if (id == 0) { 293f6cdab5fSClement Guedez for (i = 0; i < 2; ++i) { 294f6cdab5fSClement Guedez reg = STAC946X_MIC_L_VOLUME + i; 295f6cdab5fSClement Guedez vol = stac9460_get(ice, reg) & 0x0f; 296f6cdab5fSClement Guedez ucontrol->value.integer.value[i] = 0x0f - vol; 297f6cdab5fSClement Guedez } 298f6cdab5fSClement Guedez } else { 299f6cdab5fSClement Guedez for (i = 0; i < 2; ++i) { 300f6cdab5fSClement Guedez reg = STAC946X_MIC_L_VOLUME + i; 301f6cdab5fSClement Guedez vol = stac9460_2_get(ice, reg) & 0x0f; 302f6cdab5fSClement Guedez ucontrol->value.integer.value[i] = 0x0f - vol; 303f6cdab5fSClement Guedez } 304f6cdab5fSClement Guedez } 305f6cdab5fSClement Guedez return 0; 306f6cdab5fSClement Guedez } 307f6cdab5fSClement Guedez 308f6cdab5fSClement Guedez static int stac9460_adc_vol_put(struct snd_kcontrol *kcontrol, 309f6cdab5fSClement Guedez struct snd_ctl_elem_value *ucontrol) 310f6cdab5fSClement Guedez { 311f6cdab5fSClement Guedez struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 312f6cdab5fSClement Guedez int i, reg, id; 313f6cdab5fSClement Guedez unsigned char ovol, nvol; 314f6cdab5fSClement Guedez int change; 315f6cdab5fSClement Guedez 316f6cdab5fSClement Guedez id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); 317f6cdab5fSClement Guedez if (id == 0) { 318f6cdab5fSClement Guedez for (i = 0; i < 2; ++i) { 319f6cdab5fSClement Guedez reg = STAC946X_MIC_L_VOLUME + i; 320*9cd17cd2STakashi Iwai nvol = ucontrol->value.integer.value[i] & 0x0f; 321f6cdab5fSClement Guedez ovol = 0x0f - stac9460_get(ice, reg); 322f6cdab5fSClement Guedez change = ((ovol & 0x0f) != nvol); 323f6cdab5fSClement Guedez if (change) 324f6cdab5fSClement Guedez stac9460_put(ice, reg, (0x0f - nvol) | 325f6cdab5fSClement Guedez (ovol & ~0x0f)); 326f6cdab5fSClement Guedez } 327f6cdab5fSClement Guedez } else { 328f6cdab5fSClement Guedez for (i = 0; i < 2; ++i) { 329f6cdab5fSClement Guedez reg = STAC946X_MIC_L_VOLUME + i; 330*9cd17cd2STakashi Iwai nvol = ucontrol->value.integer.value[i] & 0x0f; 331f6cdab5fSClement Guedez ovol = 0x0f - stac9460_2_get(ice, reg); 332f6cdab5fSClement Guedez change = ((ovol & 0x0f) != nvol); 333f6cdab5fSClement Guedez if (change) 334f6cdab5fSClement Guedez stac9460_2_put(ice, reg, (0x0f - nvol) | 335f6cdab5fSClement Guedez (ovol & ~0x0f)); 336f6cdab5fSClement Guedez } 337f6cdab5fSClement Guedez } 338f6cdab5fSClement Guedez return change; 339f6cdab5fSClement Guedez } 340f6cdab5fSClement Guedez 341f6cdab5fSClement Guedez /* 342f6cdab5fSClement Guedez * MIC / LINE switch fonction 343f6cdab5fSClement Guedez */ 344f6cdab5fSClement Guedez 345a5ce8890STakashi Iwai #define stac9460_mic_sw_info snd_ctl_boolean_mono_info 346f6cdab5fSClement Guedez 347f6cdab5fSClement Guedez static int stac9460_mic_sw_get(struct snd_kcontrol *kcontrol, 348f6cdab5fSClement Guedez struct snd_ctl_elem_value *ucontrol) 349f6cdab5fSClement Guedez { 350f6cdab5fSClement Guedez struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 351f6cdab5fSClement Guedez unsigned char val; 352f6cdab5fSClement Guedez int id; 353f6cdab5fSClement Guedez 354f6cdab5fSClement Guedez id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); 355f6cdab5fSClement Guedez if (id == 0) 356f6cdab5fSClement Guedez val = stac9460_get(ice, STAC946X_GENERAL_PURPOSE); 357f6cdab5fSClement Guedez else 358f6cdab5fSClement Guedez val = stac9460_2_get(ice, STAC946X_GENERAL_PURPOSE); 359f6cdab5fSClement Guedez ucontrol->value.integer.value[0] = ~val>>7 & 0x1; 360f6cdab5fSClement Guedez return 0; 361f6cdab5fSClement Guedez } 362f6cdab5fSClement Guedez 363f6cdab5fSClement Guedez static int stac9460_mic_sw_put(struct snd_kcontrol *kcontrol, 364f6cdab5fSClement Guedez struct snd_ctl_elem_value *ucontrol) 365f6cdab5fSClement Guedez { 366f6cdab5fSClement Guedez struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 367f6cdab5fSClement Guedez unsigned char new, old; 368f6cdab5fSClement Guedez int change, id; 369f6cdab5fSClement Guedez 370f6cdab5fSClement Guedez id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); 371f6cdab5fSClement Guedez if (id == 0) 372f6cdab5fSClement Guedez old = stac9460_get(ice, STAC946X_GENERAL_PURPOSE); 373f6cdab5fSClement Guedez else 374f6cdab5fSClement Guedez old = stac9460_2_get(ice, STAC946X_GENERAL_PURPOSE); 375f6cdab5fSClement Guedez new = (~ucontrol->value.integer.value[0]<< 7 & 0x80) | (old & ~0x80); 376f6cdab5fSClement Guedez change = (new != old); 377f6cdab5fSClement Guedez if (change) { 378f6cdab5fSClement Guedez if (id == 0) 379f6cdab5fSClement Guedez stac9460_put(ice, STAC946X_GENERAL_PURPOSE, new); 380f6cdab5fSClement Guedez else 381f6cdab5fSClement Guedez stac9460_2_put(ice, STAC946X_GENERAL_PURPOSE, new); 382f6cdab5fSClement Guedez } 383f6cdab5fSClement Guedez return change; 384f6cdab5fSClement Guedez } 385f6cdab5fSClement Guedez 386f6cdab5fSClement Guedez /* 387f6cdab5fSClement Guedez * Control tabs 388f6cdab5fSClement Guedez */ 3891b60f6b0STakashi Iwai static struct snd_kcontrol_new stac9640_controls[] __devinitdata = { 390f6cdab5fSClement Guedez { 391f6cdab5fSClement Guedez .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 392f6cdab5fSClement Guedez .name = "Master Playback Switch", 393f6cdab5fSClement Guedez .info = stac9460_dac_mute_info, 394f6cdab5fSClement Guedez .get = stac9460_dac_mute_get, 395f6cdab5fSClement Guedez .put = stac9460_dac_mute_put, 396f6cdab5fSClement Guedez .private_value = 1 397f6cdab5fSClement Guedez }, 398f6cdab5fSClement Guedez { 399f6cdab5fSClement Guedez .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 400f6cdab5fSClement Guedez .name = "Master Playback Volume", 401f6cdab5fSClement Guedez .info = stac9460_dac_vol_info, 402f6cdab5fSClement Guedez .get = stac9460_dac_vol_get, 403f6cdab5fSClement Guedez .put = stac9460_dac_vol_put, 404f6cdab5fSClement Guedez .private_value = 1, 405f6cdab5fSClement Guedez }, 406f6cdab5fSClement Guedez { 407f6cdab5fSClement Guedez .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 408f6cdab5fSClement Guedez .name = "MIC/Line switch", 409f6cdab5fSClement Guedez .count = 2, 410f6cdab5fSClement Guedez .info = stac9460_mic_sw_info, 411f6cdab5fSClement Guedez .get = stac9460_mic_sw_get, 412f6cdab5fSClement Guedez .put = stac9460_mic_sw_put, 413f6cdab5fSClement Guedez 414f6cdab5fSClement Guedez }, 415f6cdab5fSClement Guedez { 416f6cdab5fSClement Guedez .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 417f6cdab5fSClement Guedez .name = "DAC Switch", 418f6cdab5fSClement Guedez .count = 8, 419f6cdab5fSClement Guedez .info = stac9460_dac_mute_info, 420f6cdab5fSClement Guedez .get = stac9460_dac_mute_get, 421f6cdab5fSClement Guedez .put = stac9460_dac_mute_put, 422f6cdab5fSClement Guedez }, 423f6cdab5fSClement Guedez { 424f6cdab5fSClement Guedez .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 425f6cdab5fSClement Guedez .name = "DAC Volume", 426f6cdab5fSClement Guedez .count = 8, 427f6cdab5fSClement Guedez .info = stac9460_dac_vol_info, 428f6cdab5fSClement Guedez .get = stac9460_dac_vol_get, 429f6cdab5fSClement Guedez .put = stac9460_dac_vol_put, 430f6cdab5fSClement Guedez }, 431f6cdab5fSClement Guedez { 432f6cdab5fSClement Guedez .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 433f6cdab5fSClement Guedez .name = "ADC Switch", 434f6cdab5fSClement Guedez .count = 2, 435f6cdab5fSClement Guedez .info = stac9460_adc_mute_info, 436f6cdab5fSClement Guedez .get = stac9460_adc_mute_get, 437f6cdab5fSClement Guedez .put = stac9460_adc_mute_put, 438f6cdab5fSClement Guedez }, 439f6cdab5fSClement Guedez { 440f6cdab5fSClement Guedez .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 441f6cdab5fSClement Guedez .name = "ADC Volume", 442f6cdab5fSClement Guedez .count = 2, 443f6cdab5fSClement Guedez .info = stac9460_adc_vol_info, 444f6cdab5fSClement Guedez .get = stac9460_adc_vol_get, 445f6cdab5fSClement Guedez .put = stac9460_adc_vol_put, 446f6cdab5fSClement Guedez 447f6cdab5fSClement Guedez } 448f6cdab5fSClement Guedez }; 449f6cdab5fSClement Guedez 450f6cdab5fSClement Guedez 451f6cdab5fSClement Guedez 452f6cdab5fSClement Guedez /*INIT*/ 453f6cdab5fSClement Guedez static int __devinit wtm_add_controls(struct snd_ice1712 *ice) 454f6cdab5fSClement Guedez { 455f6cdab5fSClement Guedez unsigned int i; 456f6cdab5fSClement Guedez int err; 457f6cdab5fSClement Guedez 458f6cdab5fSClement Guedez for (i = 0; i < ARRAY_SIZE(stac9640_controls); i++) { 459f6cdab5fSClement Guedez err = snd_ctl_add(ice->card, 460f6cdab5fSClement Guedez snd_ctl_new1(&stac9640_controls[i], ice)); 461f6cdab5fSClement Guedez if (err < 0) 462f6cdab5fSClement Guedez return err; 463f6cdab5fSClement Guedez } 464f6cdab5fSClement Guedez return 0; 465f6cdab5fSClement Guedez } 466f6cdab5fSClement Guedez 467f6cdab5fSClement Guedez static int __devinit wtm_init(struct snd_ice1712 *ice) 468f6cdab5fSClement Guedez { 469f6cdab5fSClement Guedez static unsigned short stac_inits_prodigy[] = { 470f6cdab5fSClement Guedez STAC946X_RESET, 0, 471f6cdab5fSClement Guedez (unsigned short)-1 472f6cdab5fSClement Guedez }; 473f6cdab5fSClement Guedez unsigned short *p; 474f6cdab5fSClement Guedez 475f6cdab5fSClement Guedez /*WTM 192M*/ 476f6cdab5fSClement Guedez ice->num_total_dacs = 8; 477f6cdab5fSClement Guedez ice->num_total_adcs = 4; 478f6cdab5fSClement Guedez ice->force_rdma1 = 1; 479f6cdab5fSClement Guedez 480f6cdab5fSClement Guedez /*initialize codec*/ 481f6cdab5fSClement Guedez p = stac_inits_prodigy; 482f6cdab5fSClement Guedez for (; *p != (unsigned short)-1; p += 2) { 483f6cdab5fSClement Guedez stac9460_put(ice, p[0], p[1]); 484f6cdab5fSClement Guedez stac9460_2_put(ice, p[0], p[1]); 485f6cdab5fSClement Guedez } 486f6cdab5fSClement Guedez return 0; 487f6cdab5fSClement Guedez } 488f6cdab5fSClement Guedez 489f6cdab5fSClement Guedez 490f6cdab5fSClement Guedez static unsigned char wtm_eeprom[] __devinitdata = { 491f6cdab5fSClement Guedez 0x47, /*SYSCONF: clock 192KHz, 4ADC, 8DAC */ 492f6cdab5fSClement Guedez 0x80, /* ACLINK : I2S */ 493f6cdab5fSClement Guedez 0xf8, /* I2S: vol; 96k, 24bit, 192k */ 494f6cdab5fSClement Guedez 0xc1 /*SPDIF: out-en, spidf ext out*/, 495f6cdab5fSClement Guedez 0x9f, /* GPIO_DIR */ 496f6cdab5fSClement Guedez 0xff, /* GPIO_DIR1 */ 497f6cdab5fSClement Guedez 0x7f, /* GPIO_DIR2 */ 498f6cdab5fSClement Guedez 0x9f, /* GPIO_MASK */ 499f6cdab5fSClement Guedez 0xff, /* GPIO_MASK1 */ 500f6cdab5fSClement Guedez 0x7f, /* GPIO_MASK2 */ 501f6cdab5fSClement Guedez 0x16, /* GPIO_STATE */ 502f6cdab5fSClement Guedez 0x80, /* GPIO_STATE1 */ 503f6cdab5fSClement Guedez 0x00, /* GPIO_STATE2 */ 504f6cdab5fSClement Guedez }; 505f6cdab5fSClement Guedez 506f6cdab5fSClement Guedez 507f6cdab5fSClement Guedez /*entry point*/ 508f6cdab5fSClement Guedez struct snd_ice1712_card_info snd_vt1724_wtm_cards[] __devinitdata = { 509f6cdab5fSClement Guedez { 510f6cdab5fSClement Guedez .subvendor = VT1724_SUBDEVICE_WTM, 511f6cdab5fSClement Guedez .name = "ESI Waveterminal 192M", 512f6cdab5fSClement Guedez .model = "WT192M", 513f6cdab5fSClement Guedez .chip_init = wtm_init, 514f6cdab5fSClement Guedez .build_controls = wtm_add_controls, 515f6cdab5fSClement Guedez .eeprom_size = sizeof(wtm_eeprom), 516f6cdab5fSClement Guedez .eeprom_data = wtm_eeprom, 517f6cdab5fSClement Guedez }, 518f6cdab5fSClement Guedez {} /*terminator*/ 519f6cdab5fSClement Guedez }; 520