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 <linux/delay.h> 29f6cdab5fSClement Guedez #include <linux/interrupt.h> 30f6cdab5fSClement Guedez #include <linux/init.h> 31f6cdab5fSClement Guedez #include <sound/core.h> 32f6cdab5fSClement Guedez 33f6cdab5fSClement Guedez #include "ice1712.h" 34f6cdab5fSClement Guedez #include "envy24ht.h" 35f6cdab5fSClement Guedez #include "wtm.h" 36f6cdab5fSClement Guedez #include "stac946x.h" 37f6cdab5fSClement Guedez 38f6cdab5fSClement Guedez 39f6cdab5fSClement Guedez /* 40f6cdab5fSClement Guedez * 2*ADC 6*DAC no1 ringbuffer r/w on i2c bus 41f6cdab5fSClement Guedez */ 42f6cdab5fSClement Guedez static inline void stac9460_put(struct snd_ice1712 *ice, int reg, 43f6cdab5fSClement Guedez unsigned char val) 44f6cdab5fSClement Guedez { 45f6cdab5fSClement Guedez snd_vt1724_write_i2c(ice, STAC9460_I2C_ADDR, reg, val); 46f6cdab5fSClement Guedez } 47f6cdab5fSClement Guedez 48f6cdab5fSClement Guedez static inline unsigned char stac9460_get(struct snd_ice1712 *ice, int reg) 49f6cdab5fSClement Guedez { 50f6cdab5fSClement Guedez return snd_vt1724_read_i2c(ice, STAC9460_I2C_ADDR, reg); 51f6cdab5fSClement Guedez } 52f6cdab5fSClement Guedez 53f6cdab5fSClement Guedez /* 54f6cdab5fSClement Guedez * 2*ADC 2*DAC no2 ringbuffer r/w on i2c bus 55f6cdab5fSClement Guedez */ 56f6cdab5fSClement Guedez static inline void stac9460_2_put(struct snd_ice1712 *ice, int reg, 57f6cdab5fSClement Guedez unsigned char val) 58f6cdab5fSClement Guedez { 59f6cdab5fSClement Guedez snd_vt1724_write_i2c(ice, STAC9460_2_I2C_ADDR, reg, val); 60f6cdab5fSClement Guedez } 61f6cdab5fSClement Guedez 62f6cdab5fSClement Guedez static inline unsigned char stac9460_2_get(struct snd_ice1712 *ice, int reg) 63f6cdab5fSClement Guedez { 64f6cdab5fSClement Guedez return snd_vt1724_read_i2c(ice, STAC9460_2_I2C_ADDR, reg); 65f6cdab5fSClement Guedez } 66f6cdab5fSClement Guedez 67f6cdab5fSClement Guedez 68f6cdab5fSClement Guedez /* 69f6cdab5fSClement Guedez * DAC mute control 70f6cdab5fSClement Guedez */ 71a5ce8890STakashi Iwai #define stac9460_dac_mute_info snd_ctl_boolean_mono_info 72f6cdab5fSClement Guedez 73f6cdab5fSClement Guedez static int stac9460_dac_mute_get(struct snd_kcontrol *kcontrol, 74f6cdab5fSClement Guedez struct snd_ctl_elem_value *ucontrol) 75f6cdab5fSClement Guedez { 76f6cdab5fSClement Guedez struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 77f6cdab5fSClement Guedez unsigned char val; 78f6cdab5fSClement Guedez int idx, id; 79f6cdab5fSClement Guedez 80f6cdab5fSClement Guedez if (kcontrol->private_value) { 81f6cdab5fSClement Guedez idx = STAC946X_MASTER_VOLUME; 82f6cdab5fSClement Guedez id = 0; 83f6cdab5fSClement Guedez } else { 84f6cdab5fSClement Guedez id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); 85f6cdab5fSClement Guedez idx = id + STAC946X_LF_VOLUME; 86f6cdab5fSClement Guedez } 87f6cdab5fSClement Guedez if (id < 6) 88f6cdab5fSClement Guedez val = stac9460_get(ice, idx); 89f6cdab5fSClement Guedez else 90f6cdab5fSClement Guedez val = stac9460_2_get(ice, idx - 6); 91f6cdab5fSClement Guedez ucontrol->value.integer.value[0] = (~val >> 7) & 0x1; 92f6cdab5fSClement Guedez return 0; 93f6cdab5fSClement Guedez } 94f6cdab5fSClement Guedez 95f6cdab5fSClement Guedez static int stac9460_dac_mute_put(struct snd_kcontrol *kcontrol, 96f6cdab5fSClement Guedez struct snd_ctl_elem_value *ucontrol) 97f6cdab5fSClement Guedez { 98f6cdab5fSClement Guedez struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 99f6cdab5fSClement Guedez unsigned char new, old; 100f6cdab5fSClement Guedez int id, idx; 101f6cdab5fSClement Guedez int change; 102f6cdab5fSClement Guedez 103f6cdab5fSClement Guedez if (kcontrol->private_value) { 104f6cdab5fSClement Guedez idx = STAC946X_MASTER_VOLUME; 105f6cdab5fSClement Guedez old = stac9460_get(ice, idx); 106f6cdab5fSClement Guedez new = (~ucontrol->value.integer.value[0] << 7 & 0x80) | 107f6cdab5fSClement Guedez (old & ~0x80); 108f6cdab5fSClement Guedez change = (new != old); 109f6cdab5fSClement Guedez if (change) { 110f6cdab5fSClement Guedez stac9460_put(ice, idx, new); 111f6cdab5fSClement Guedez stac9460_2_put(ice, idx, new); 112f6cdab5fSClement Guedez } 113f6cdab5fSClement Guedez } else { 114f6cdab5fSClement Guedez id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); 115f6cdab5fSClement Guedez idx = id + STAC946X_LF_VOLUME; 116f6cdab5fSClement Guedez if (id < 6) 117f6cdab5fSClement Guedez old = stac9460_get(ice, idx); 118f6cdab5fSClement Guedez else 119f6cdab5fSClement Guedez old = stac9460_2_get(ice, idx - 6); 120f6cdab5fSClement Guedez new = (~ucontrol->value.integer.value[0] << 7 & 0x80) | 121f6cdab5fSClement Guedez (old & ~0x80); 122f6cdab5fSClement Guedez change = (new != old); 123f6cdab5fSClement Guedez if (change) { 124f6cdab5fSClement Guedez if (id < 6) 125f6cdab5fSClement Guedez stac9460_put(ice, idx, new); 126f6cdab5fSClement Guedez else 127f6cdab5fSClement Guedez stac9460_2_put(ice, idx - 6, new); 128f6cdab5fSClement Guedez } 129f6cdab5fSClement Guedez } 130f6cdab5fSClement Guedez return change; 131f6cdab5fSClement Guedez } 132f6cdab5fSClement Guedez 133f6cdab5fSClement Guedez /* 134f6cdab5fSClement Guedez * DAC volume attenuation mixer control 135f6cdab5fSClement Guedez */ 136f6cdab5fSClement Guedez static int stac9460_dac_vol_info(struct snd_kcontrol *kcontrol, 137f6cdab5fSClement Guedez struct snd_ctl_elem_info *uinfo) 138f6cdab5fSClement Guedez { 139f6cdab5fSClement Guedez uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 140f6cdab5fSClement Guedez uinfo->count = 1; 141f6cdab5fSClement Guedez uinfo->value.integer.min = 0; /* mute */ 142f6cdab5fSClement Guedez uinfo->value.integer.max = 0x7f; /* 0dB */ 143f6cdab5fSClement Guedez return 0; 144f6cdab5fSClement Guedez } 145f6cdab5fSClement Guedez 146f6cdab5fSClement Guedez static int stac9460_dac_vol_get(struct snd_kcontrol *kcontrol, 147f6cdab5fSClement Guedez struct snd_ctl_elem_value *ucontrol) 148f6cdab5fSClement Guedez { 149f6cdab5fSClement Guedez struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 150f6cdab5fSClement Guedez int idx, id; 151f6cdab5fSClement Guedez unsigned char vol; 152f6cdab5fSClement Guedez 153f6cdab5fSClement Guedez if (kcontrol->private_value) { 154f6cdab5fSClement Guedez idx = STAC946X_MASTER_VOLUME; 155f6cdab5fSClement Guedez id = 0; 156f6cdab5fSClement Guedez } else { 157f6cdab5fSClement Guedez id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); 158f6cdab5fSClement Guedez idx = id + STAC946X_LF_VOLUME; 159f6cdab5fSClement Guedez } 160f6cdab5fSClement Guedez if (id < 6) 161f6cdab5fSClement Guedez vol = stac9460_get(ice, idx) & 0x7f; 162f6cdab5fSClement Guedez else 163f6cdab5fSClement Guedez vol = stac9460_2_get(ice, idx - 6) & 0x7f; 164f6cdab5fSClement Guedez ucontrol->value.integer.value[0] = 0x7f - vol; 165f6cdab5fSClement Guedez return 0; 166f6cdab5fSClement Guedez } 167f6cdab5fSClement Guedez 168f6cdab5fSClement Guedez static int stac9460_dac_vol_put(struct snd_kcontrol *kcontrol, 169f6cdab5fSClement Guedez struct snd_ctl_elem_value *ucontrol) 170f6cdab5fSClement Guedez { 171f6cdab5fSClement Guedez struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 172f6cdab5fSClement Guedez int idx, id; 173f6cdab5fSClement Guedez unsigned char tmp, ovol, nvol; 174f6cdab5fSClement Guedez int change; 175f6cdab5fSClement Guedez 176f6cdab5fSClement Guedez if (kcontrol->private_value) { 177f6cdab5fSClement Guedez idx = STAC946X_MASTER_VOLUME; 1789cd17cd2STakashi Iwai nvol = ucontrol->value.integer.value[0] & 0x7f; 179f6cdab5fSClement Guedez tmp = stac9460_get(ice, idx); 180f6cdab5fSClement Guedez ovol = 0x7f - (tmp & 0x7f); 181f6cdab5fSClement Guedez change = (ovol != nvol); 182f6cdab5fSClement Guedez if (change) { 183f6cdab5fSClement Guedez stac9460_put(ice, idx, (0x7f - nvol) | (tmp & 0x80)); 184f6cdab5fSClement Guedez stac9460_2_put(ice, idx, (0x7f - nvol) | (tmp & 0x80)); 185f6cdab5fSClement Guedez } 186f6cdab5fSClement Guedez } else { 187f6cdab5fSClement Guedez id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); 188f6cdab5fSClement Guedez idx = id + STAC946X_LF_VOLUME; 1899cd17cd2STakashi Iwai nvol = ucontrol->value.integer.value[0] & 0x7f; 190f6cdab5fSClement Guedez if (id < 6) 191f6cdab5fSClement Guedez tmp = stac9460_get(ice, idx); 192f6cdab5fSClement Guedez else 193f6cdab5fSClement Guedez tmp = stac9460_2_get(ice, idx - 6); 194f6cdab5fSClement Guedez ovol = 0x7f - (tmp & 0x7f); 195f6cdab5fSClement Guedez change = (ovol != nvol); 196f6cdab5fSClement Guedez if (change) { 197f6cdab5fSClement Guedez if (id < 6) 198f6cdab5fSClement Guedez stac9460_put(ice, idx, (0x7f - nvol) | 199f6cdab5fSClement Guedez (tmp & 0x80)); 200f6cdab5fSClement Guedez else 201f6cdab5fSClement Guedez stac9460_2_put(ice, idx-6, (0x7f - nvol) | 202f6cdab5fSClement Guedez (tmp & 0x80)); 203f6cdab5fSClement Guedez } 204f6cdab5fSClement Guedez } 205f6cdab5fSClement Guedez return change; 206f6cdab5fSClement Guedez } 207f6cdab5fSClement Guedez 208f6cdab5fSClement Guedez /* 209f6cdab5fSClement Guedez * ADC mute control 210f6cdab5fSClement Guedez */ 211a5ce8890STakashi Iwai #define stac9460_adc_mute_info snd_ctl_boolean_stereo_info 212f6cdab5fSClement Guedez 213f6cdab5fSClement Guedez static int stac9460_adc_mute_get(struct snd_kcontrol *kcontrol, 214f6cdab5fSClement Guedez struct snd_ctl_elem_value *ucontrol) 215f6cdab5fSClement Guedez { 216f6cdab5fSClement Guedez struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 217f6cdab5fSClement Guedez unsigned char val; 218f6cdab5fSClement Guedez int i, id; 219f6cdab5fSClement Guedez 220f6cdab5fSClement Guedez id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); 221f6cdab5fSClement Guedez if (id == 0) { 222f6cdab5fSClement Guedez for (i = 0; i < 2; ++i) { 223f6cdab5fSClement Guedez val = stac9460_get(ice, STAC946X_MIC_L_VOLUME + i); 224f6cdab5fSClement Guedez ucontrol->value.integer.value[i] = ~val>>7 & 0x1; 225f6cdab5fSClement Guedez } 226f6cdab5fSClement Guedez } else { 227f6cdab5fSClement Guedez for (i = 0; i < 2; ++i) { 228f6cdab5fSClement Guedez val = stac9460_2_get(ice, STAC946X_MIC_L_VOLUME + i); 229f6cdab5fSClement Guedez ucontrol->value.integer.value[i] = ~val>>7 & 0x1; 230f6cdab5fSClement Guedez } 231f6cdab5fSClement Guedez } 232f6cdab5fSClement Guedez return 0; 233f6cdab5fSClement Guedez } 234f6cdab5fSClement Guedez 235f6cdab5fSClement Guedez static int stac9460_adc_mute_put(struct snd_kcontrol *kcontrol, 236f6cdab5fSClement Guedez struct snd_ctl_elem_value *ucontrol) 237f6cdab5fSClement Guedez { 238f6cdab5fSClement Guedez struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 239f6cdab5fSClement Guedez unsigned char new, old; 240f6cdab5fSClement Guedez int i, reg, id; 241f6cdab5fSClement Guedez int change; 242f6cdab5fSClement Guedez 243f6cdab5fSClement Guedez id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); 244f6cdab5fSClement Guedez if (id == 0) { 245f6cdab5fSClement Guedez for (i = 0; i < 2; ++i) { 246f6cdab5fSClement Guedez reg = STAC946X_MIC_L_VOLUME + i; 247f6cdab5fSClement Guedez old = stac9460_get(ice, reg); 248f6cdab5fSClement Guedez new = (~ucontrol->value.integer.value[i]<<7&0x80) | 249f6cdab5fSClement Guedez (old&~0x80); 250f6cdab5fSClement Guedez change = (new != old); 251f6cdab5fSClement Guedez if (change) 252f6cdab5fSClement Guedez stac9460_put(ice, reg, new); 253f6cdab5fSClement Guedez } 254f6cdab5fSClement Guedez } else { 255f6cdab5fSClement Guedez for (i = 0; i < 2; ++i) { 256f6cdab5fSClement Guedez reg = STAC946X_MIC_L_VOLUME + i; 257f6cdab5fSClement Guedez old = stac9460_2_get(ice, reg); 258f6cdab5fSClement Guedez new = (~ucontrol->value.integer.value[i]<<7&0x80) | 259f6cdab5fSClement Guedez (old&~0x80); 260f6cdab5fSClement Guedez change = (new != old); 261f6cdab5fSClement Guedez if (change) 262f6cdab5fSClement Guedez stac9460_2_put(ice, reg, new); 263f6cdab5fSClement Guedez } 264f6cdab5fSClement Guedez } 265f6cdab5fSClement Guedez return change; 266f6cdab5fSClement Guedez } 267f6cdab5fSClement Guedez 268f6cdab5fSClement Guedez /* 269f6cdab5fSClement Guedez *ADC gain mixer control 270f6cdab5fSClement Guedez */ 271f6cdab5fSClement Guedez static int stac9460_adc_vol_info(struct snd_kcontrol *kcontrol, 272f6cdab5fSClement Guedez struct snd_ctl_elem_info *uinfo) 273f6cdab5fSClement Guedez { 274f6cdab5fSClement Guedez uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 275f6cdab5fSClement Guedez uinfo->count = 2; 276f6cdab5fSClement Guedez uinfo->value.integer.min = 0; /* 0dB */ 277f6cdab5fSClement Guedez uinfo->value.integer.max = 0x0f; /* 22.5dB */ 278f6cdab5fSClement Guedez return 0; 279f6cdab5fSClement Guedez } 280f6cdab5fSClement Guedez 281f6cdab5fSClement Guedez static int stac9460_adc_vol_get(struct snd_kcontrol *kcontrol, 282f6cdab5fSClement Guedez struct snd_ctl_elem_value *ucontrol) 283f6cdab5fSClement Guedez { 284f6cdab5fSClement Guedez struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 285f6cdab5fSClement Guedez int i, reg, id; 286f6cdab5fSClement Guedez unsigned char vol; 287f6cdab5fSClement Guedez 288f6cdab5fSClement Guedez id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); 289f6cdab5fSClement Guedez if (id == 0) { 290f6cdab5fSClement Guedez for (i = 0; i < 2; ++i) { 291f6cdab5fSClement Guedez reg = STAC946X_MIC_L_VOLUME + i; 292f6cdab5fSClement Guedez vol = stac9460_get(ice, reg) & 0x0f; 293f6cdab5fSClement Guedez ucontrol->value.integer.value[i] = 0x0f - vol; 294f6cdab5fSClement Guedez } 295f6cdab5fSClement Guedez } else { 296f6cdab5fSClement Guedez for (i = 0; i < 2; ++i) { 297f6cdab5fSClement Guedez reg = STAC946X_MIC_L_VOLUME + i; 298f6cdab5fSClement Guedez vol = stac9460_2_get(ice, reg) & 0x0f; 299f6cdab5fSClement Guedez ucontrol->value.integer.value[i] = 0x0f - vol; 300f6cdab5fSClement Guedez } 301f6cdab5fSClement Guedez } 302f6cdab5fSClement Guedez return 0; 303f6cdab5fSClement Guedez } 304f6cdab5fSClement Guedez 305f6cdab5fSClement Guedez static int stac9460_adc_vol_put(struct snd_kcontrol *kcontrol, 306f6cdab5fSClement Guedez struct snd_ctl_elem_value *ucontrol) 307f6cdab5fSClement Guedez { 308f6cdab5fSClement Guedez struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 309f6cdab5fSClement Guedez int i, reg, id; 310f6cdab5fSClement Guedez unsigned char ovol, nvol; 311f6cdab5fSClement Guedez int change; 312f6cdab5fSClement Guedez 313f6cdab5fSClement Guedez id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); 314f6cdab5fSClement Guedez if (id == 0) { 315f6cdab5fSClement Guedez for (i = 0; i < 2; ++i) { 316f6cdab5fSClement Guedez reg = STAC946X_MIC_L_VOLUME + i; 3179cd17cd2STakashi Iwai nvol = ucontrol->value.integer.value[i] & 0x0f; 318f6cdab5fSClement Guedez ovol = 0x0f - stac9460_get(ice, reg); 319f6cdab5fSClement Guedez change = ((ovol & 0x0f) != nvol); 320f6cdab5fSClement Guedez if (change) 321f6cdab5fSClement Guedez stac9460_put(ice, reg, (0x0f - nvol) | 322f6cdab5fSClement Guedez (ovol & ~0x0f)); 323f6cdab5fSClement Guedez } 324f6cdab5fSClement Guedez } else { 325f6cdab5fSClement Guedez for (i = 0; i < 2; ++i) { 326f6cdab5fSClement Guedez reg = STAC946X_MIC_L_VOLUME + i; 3279cd17cd2STakashi Iwai nvol = ucontrol->value.integer.value[i] & 0x0f; 328f6cdab5fSClement Guedez ovol = 0x0f - stac9460_2_get(ice, reg); 329f6cdab5fSClement Guedez change = ((ovol & 0x0f) != nvol); 330f6cdab5fSClement Guedez if (change) 331f6cdab5fSClement Guedez stac9460_2_put(ice, reg, (0x0f - nvol) | 332f6cdab5fSClement Guedez (ovol & ~0x0f)); 333f6cdab5fSClement Guedez } 334f6cdab5fSClement Guedez } 335f6cdab5fSClement Guedez return change; 336f6cdab5fSClement Guedez } 337f6cdab5fSClement Guedez 338f6cdab5fSClement Guedez /* 339f6cdab5fSClement Guedez * MIC / LINE switch fonction 340f6cdab5fSClement Guedez */ 341f6cdab5fSClement Guedez 342a5ce8890STakashi Iwai #define stac9460_mic_sw_info snd_ctl_boolean_mono_info 343f6cdab5fSClement Guedez 344f6cdab5fSClement Guedez static int stac9460_mic_sw_get(struct snd_kcontrol *kcontrol, 345f6cdab5fSClement Guedez struct snd_ctl_elem_value *ucontrol) 346f6cdab5fSClement Guedez { 347f6cdab5fSClement Guedez struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 348f6cdab5fSClement Guedez unsigned char val; 349f6cdab5fSClement Guedez int id; 350f6cdab5fSClement Guedez 351f6cdab5fSClement Guedez id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); 352f6cdab5fSClement Guedez if (id == 0) 353f6cdab5fSClement Guedez val = stac9460_get(ice, STAC946X_GENERAL_PURPOSE); 354f6cdab5fSClement Guedez else 355f6cdab5fSClement Guedez val = stac9460_2_get(ice, STAC946X_GENERAL_PURPOSE); 356f6cdab5fSClement Guedez ucontrol->value.integer.value[0] = ~val>>7 & 0x1; 357f6cdab5fSClement Guedez return 0; 358f6cdab5fSClement Guedez } 359f6cdab5fSClement Guedez 360f6cdab5fSClement Guedez static int stac9460_mic_sw_put(struct snd_kcontrol *kcontrol, 361f6cdab5fSClement Guedez struct snd_ctl_elem_value *ucontrol) 362f6cdab5fSClement Guedez { 363f6cdab5fSClement Guedez struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 364f6cdab5fSClement Guedez unsigned char new, old; 365f6cdab5fSClement Guedez int change, id; 366f6cdab5fSClement Guedez 367f6cdab5fSClement Guedez id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); 368f6cdab5fSClement Guedez if (id == 0) 369f6cdab5fSClement Guedez old = stac9460_get(ice, STAC946X_GENERAL_PURPOSE); 370f6cdab5fSClement Guedez else 371f6cdab5fSClement Guedez old = stac9460_2_get(ice, STAC946X_GENERAL_PURPOSE); 372f6cdab5fSClement Guedez new = (~ucontrol->value.integer.value[0] << 7 & 0x80) | (old & ~0x80); 373f6cdab5fSClement Guedez change = (new != old); 374f6cdab5fSClement Guedez if (change) { 375f6cdab5fSClement Guedez if (id == 0) 376f6cdab5fSClement Guedez stac9460_put(ice, STAC946X_GENERAL_PURPOSE, new); 377f6cdab5fSClement Guedez else 378f6cdab5fSClement Guedez stac9460_2_put(ice, STAC946X_GENERAL_PURPOSE, new); 379f6cdab5fSClement Guedez } 380f6cdab5fSClement Guedez return change; 381f6cdab5fSClement Guedez } 382f6cdab5fSClement Guedez 383f6cdab5fSClement Guedez /* 384f6cdab5fSClement Guedez * Control tabs 385f6cdab5fSClement Guedez */ 386e23e7a14SBill Pemberton static struct snd_kcontrol_new stac9640_controls[] = { 387f6cdab5fSClement Guedez { 388f6cdab5fSClement Guedez .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 389f6cdab5fSClement Guedez .name = "Master Playback Switch", 390f6cdab5fSClement Guedez .info = stac9460_dac_mute_info, 391f6cdab5fSClement Guedez .get = stac9460_dac_mute_get, 392f6cdab5fSClement Guedez .put = stac9460_dac_mute_put, 393f6cdab5fSClement Guedez .private_value = 1 394f6cdab5fSClement Guedez }, 395f6cdab5fSClement Guedez { 396f6cdab5fSClement Guedez .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 397f6cdab5fSClement Guedez .name = "Master Playback Volume", 398f6cdab5fSClement Guedez .info = stac9460_dac_vol_info, 399f6cdab5fSClement Guedez .get = stac9460_dac_vol_get, 400f6cdab5fSClement Guedez .put = stac9460_dac_vol_put, 401f6cdab5fSClement Guedez .private_value = 1, 402f6cdab5fSClement Guedez }, 403f6cdab5fSClement Guedez { 404f6cdab5fSClement Guedez .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 405f6cdab5fSClement Guedez .name = "MIC/Line switch", 406f6cdab5fSClement Guedez .count = 2, 407f6cdab5fSClement Guedez .info = stac9460_mic_sw_info, 408f6cdab5fSClement Guedez .get = stac9460_mic_sw_get, 409f6cdab5fSClement Guedez .put = stac9460_mic_sw_put, 410f6cdab5fSClement Guedez 411f6cdab5fSClement Guedez }, 412f6cdab5fSClement Guedez { 413f6cdab5fSClement Guedez .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 414f6cdab5fSClement Guedez .name = "DAC Switch", 415f6cdab5fSClement Guedez .count = 8, 416f6cdab5fSClement Guedez .info = stac9460_dac_mute_info, 417f6cdab5fSClement Guedez .get = stac9460_dac_mute_get, 418f6cdab5fSClement Guedez .put = stac9460_dac_mute_put, 419f6cdab5fSClement Guedez }, 420f6cdab5fSClement Guedez { 421f6cdab5fSClement Guedez .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 422f6cdab5fSClement Guedez .name = "DAC Volume", 423f6cdab5fSClement Guedez .count = 8, 424f6cdab5fSClement Guedez .info = stac9460_dac_vol_info, 425f6cdab5fSClement Guedez .get = stac9460_dac_vol_get, 426f6cdab5fSClement Guedez .put = stac9460_dac_vol_put, 427f6cdab5fSClement Guedez }, 428f6cdab5fSClement Guedez { 429f6cdab5fSClement Guedez .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 430f6cdab5fSClement Guedez .name = "ADC Switch", 431f6cdab5fSClement Guedez .count = 2, 432f6cdab5fSClement Guedez .info = stac9460_adc_mute_info, 433f6cdab5fSClement Guedez .get = stac9460_adc_mute_get, 434f6cdab5fSClement Guedez .put = stac9460_adc_mute_put, 435f6cdab5fSClement Guedez }, 436f6cdab5fSClement Guedez { 437f6cdab5fSClement Guedez .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 438f6cdab5fSClement Guedez .name = "ADC Volume", 439f6cdab5fSClement Guedez .count = 2, 440f6cdab5fSClement Guedez .info = stac9460_adc_vol_info, 441f6cdab5fSClement Guedez .get = stac9460_adc_vol_get, 442f6cdab5fSClement Guedez .put = stac9460_adc_vol_put, 443f6cdab5fSClement Guedez 444f6cdab5fSClement Guedez } 445f6cdab5fSClement Guedez }; 446f6cdab5fSClement Guedez 447f6cdab5fSClement Guedez 448f6cdab5fSClement Guedez 449f6cdab5fSClement Guedez /*INIT*/ 450e23e7a14SBill Pemberton static int wtm_add_controls(struct snd_ice1712 *ice) 451f6cdab5fSClement Guedez { 452f6cdab5fSClement Guedez unsigned int i; 453f6cdab5fSClement Guedez int err; 454f6cdab5fSClement Guedez 455f6cdab5fSClement Guedez for (i = 0; i < ARRAY_SIZE(stac9640_controls); i++) { 456f6cdab5fSClement Guedez err = snd_ctl_add(ice->card, 457f6cdab5fSClement Guedez snd_ctl_new1(&stac9640_controls[i], ice)); 458f6cdab5fSClement Guedez if (err < 0) 459f6cdab5fSClement Guedez return err; 460f6cdab5fSClement Guedez } 461f6cdab5fSClement Guedez return 0; 462f6cdab5fSClement Guedez } 463f6cdab5fSClement Guedez 464e23e7a14SBill Pemberton static int wtm_init(struct snd_ice1712 *ice) 465f6cdab5fSClement Guedez { 466b56df151SClément Guedez static unsigned short stac_inits_wtm[] = { 467f6cdab5fSClement Guedez STAC946X_RESET, 0, 468f6cdab5fSClement Guedez (unsigned short)-1 469f6cdab5fSClement Guedez }; 470f6cdab5fSClement Guedez unsigned short *p; 471f6cdab5fSClement Guedez 472f6cdab5fSClement Guedez /*WTM 192M*/ 473f6cdab5fSClement Guedez ice->num_total_dacs = 8; 474f6cdab5fSClement Guedez ice->num_total_adcs = 4; 475f6cdab5fSClement Guedez ice->force_rdma1 = 1; 476f6cdab5fSClement Guedez 477f6cdab5fSClement Guedez /*initialize codec*/ 478b56df151SClément Guedez p = stac_inits_wtm; 479f6cdab5fSClement Guedez for (; *p != (unsigned short)-1; p += 2) { 480f6cdab5fSClement Guedez stac9460_put(ice, p[0], p[1]); 481f6cdab5fSClement Guedez stac9460_2_put(ice, p[0], p[1]); 482f6cdab5fSClement Guedez } 483f6cdab5fSClement Guedez return 0; 484f6cdab5fSClement Guedez } 485f6cdab5fSClement Guedez 486f6cdab5fSClement Guedez 487e23e7a14SBill Pemberton static unsigned char wtm_eeprom[] = { 488*f8a8b3a8SClément Guedez [ICE_EEP2_SYSCONF] = 0x67, /*SYSCONF: clock 192KHz, mpu401, 489*f8a8b3a8SClément Guedez 4ADC, 8DAC */ 4907127744aSClément Guedez [ICE_EEP2_ACLINK] = 0x80, /* ACLINK : I2S */ 4917127744aSClément Guedez [ICE_EEP2_I2S] = 0xf8, /* I2S: vol; 96k, 24bit, 192k */ 4927127744aSClément Guedez [ICE_EEP2_SPDIF] = 0xc1, /*SPDIF: out-en, spidf ext out*/ 4937127744aSClément Guedez [ICE_EEP2_GPIO_DIR] = 0x9f, 4947127744aSClément Guedez [ICE_EEP2_GPIO_DIR1] = 0xff, 4957127744aSClément Guedez [ICE_EEP2_GPIO_DIR2] = 0x7f, 4967127744aSClément Guedez [ICE_EEP2_GPIO_MASK] = 0x9f, 4977127744aSClément Guedez [ICE_EEP2_GPIO_MASK1] = 0xff, 4987127744aSClément Guedez [ICE_EEP2_GPIO_MASK2] = 0x7f, 4997127744aSClément Guedez [ICE_EEP2_GPIO_STATE] = 0x16, 5007127744aSClément Guedez [ICE_EEP2_GPIO_STATE1] = 0x80, 5017127744aSClément Guedez [ICE_EEP2_GPIO_STATE2] = 0x00, 502f6cdab5fSClement Guedez }; 503f6cdab5fSClement Guedez 504f6cdab5fSClement Guedez 505f6cdab5fSClement Guedez /*entry point*/ 506e23e7a14SBill Pemberton struct snd_ice1712_card_info snd_vt1724_wtm_cards[] = { 507f6cdab5fSClement Guedez { 508f6cdab5fSClement Guedez .subvendor = VT1724_SUBDEVICE_WTM, 509f6cdab5fSClement Guedez .name = "ESI Waveterminal 192M", 510f6cdab5fSClement Guedez .model = "WT192M", 511f6cdab5fSClement Guedez .chip_init = wtm_init, 512f6cdab5fSClement Guedez .build_controls = wtm_add_controls, 513f6cdab5fSClement Guedez .eeprom_size = sizeof(wtm_eeprom), 514f6cdab5fSClement Guedez .eeprom_data = wtm_eeprom, 515f6cdab5fSClement Guedez }, 516f6cdab5fSClement Guedez {} /*terminator*/ 517f6cdab5fSClement Guedez }; 518