2 * ALSA driver for ICEnsemble VT1724 (Envy24HT)
4 * Lowlevel functions for Ego Sys Waveterminal 192M
6 * Copyright (c) 2006 Guedez Clement <klem.dev@gmail.com>
7 * Some functions are taken from the Prodigy192 driver
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 #include <sound/driver.h>
30 #include <linux/delay.h>
31 #include <linux/interrupt.h>
32 #include <linux/init.h>
33 #include <linux/slab.h>
34 #include <sound/core.h>
43 * 2*ADC 6*DAC no1 ringbuffer r/w on i2c bus
45 static inline void stac9460_put(struct snd_ice1712 *ice, int reg,
48 snd_vt1724_write_i2c(ice, STAC9460_I2C_ADDR, reg, val);
51 static inline unsigned char stac9460_get(struct snd_ice1712 *ice, int reg)
53 return snd_vt1724_read_i2c(ice, STAC9460_I2C_ADDR, reg);
57 * 2*ADC 2*DAC no2 ringbuffer r/w on i2c bus
59 static inline void stac9460_2_put(struct snd_ice1712 *ice, int reg,
62 snd_vt1724_write_i2c(ice, STAC9460_2_I2C_ADDR, reg, val);
65 static inline unsigned char stac9460_2_get(struct snd_ice1712 *ice, int reg)
67 return snd_vt1724_read_i2c(ice, STAC9460_2_I2C_ADDR, reg);
74 #define stac9460_dac_mute_info snd_ctl_boolean_mono_info
76 static int stac9460_dac_mute_get(struct snd_kcontrol *kcontrol,
77 struct snd_ctl_elem_value *ucontrol)
79 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
83 if (kcontrol->private_value) {
84 idx = STAC946X_MASTER_VOLUME;
87 id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
88 idx = id + STAC946X_LF_VOLUME;
91 val = stac9460_get(ice, idx);
93 val = stac9460_2_get(ice,idx - 6);
94 ucontrol->value.integer.value[0] = (~val >> 7) & 0x1;
98 static int stac9460_dac_mute_put(struct snd_kcontrol *kcontrol,
99 struct snd_ctl_elem_value *ucontrol)
101 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
102 unsigned char new, old;
106 if (kcontrol->private_value) {
107 idx = STAC946X_MASTER_VOLUME;
108 old = stac9460_get(ice, idx);
109 new = (~ucontrol->value.integer.value[0]<< 7 & 0x80) |
111 change = (new != old);
113 stac9460_put(ice, idx, new);
114 stac9460_2_put(ice, idx, new);
117 id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
118 idx = id + STAC946X_LF_VOLUME;
120 old = stac9460_get(ice, idx);
122 old = stac9460_2_get(ice, idx - 6);
123 new = (~ucontrol->value.integer.value[0]<< 7 & 0x80) |
125 change = (new != old);
128 stac9460_put(ice, idx, new);
130 stac9460_2_put(ice, idx - 6, new);
137 * DAC volume attenuation mixer control
139 static int stac9460_dac_vol_info(struct snd_kcontrol *kcontrol,
140 struct snd_ctl_elem_info *uinfo)
142 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
144 uinfo->value.integer.min = 0; /* mute */
145 uinfo->value.integer.max = 0x7f; /* 0dB */
149 static int stac9460_dac_vol_get(struct snd_kcontrol *kcontrol,
150 struct snd_ctl_elem_value *ucontrol)
152 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
156 if (kcontrol->private_value) {
157 idx = STAC946X_MASTER_VOLUME;
160 id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
161 idx = id + STAC946X_LF_VOLUME;
164 vol = stac9460_get(ice, idx) & 0x7f;
166 vol = stac9460_2_get(ice, idx - 6) & 0x7f;
167 ucontrol->value.integer.value[0] = 0x7f - vol;
171 static int stac9460_dac_vol_put(struct snd_kcontrol *kcontrol,
172 struct snd_ctl_elem_value *ucontrol)
174 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
176 unsigned char tmp, ovol, nvol;
179 if (kcontrol->private_value) {
180 idx = STAC946X_MASTER_VOLUME;
181 nvol = ucontrol->value.integer.value[0];
182 tmp = stac9460_get(ice, idx);
183 ovol = 0x7f - (tmp & 0x7f);
184 change = (ovol != nvol);
186 stac9460_put(ice, idx, (0x7f - nvol) | (tmp & 0x80));
187 stac9460_2_put(ice, idx, (0x7f - nvol) | (tmp & 0x80));
190 id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
191 idx = id + STAC946X_LF_VOLUME;
192 nvol = ucontrol->value.integer.value[0];
194 tmp = stac9460_get(ice, idx);
196 tmp = stac9460_2_get(ice, idx - 6);
197 ovol = 0x7f - (tmp & 0x7f);
198 change = (ovol != nvol);
201 stac9460_put(ice, idx, (0x7f - nvol) |
204 stac9460_2_put(ice, idx-6, (0x7f - nvol) |
214 #define stac9460_adc_mute_info snd_ctl_boolean_stereo_info
216 static int stac9460_adc_mute_get(struct snd_kcontrol *kcontrol,
217 struct snd_ctl_elem_value *ucontrol)
219 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
223 id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
225 for (i = 0; i < 2; ++i) {
226 val = stac9460_get(ice, STAC946X_MIC_L_VOLUME + i);
227 ucontrol->value.integer.value[i] = ~val>>7 & 0x1;
230 for (i = 0; i < 2; ++i) {
231 val = stac9460_2_get(ice, STAC946X_MIC_L_VOLUME + i);
232 ucontrol->value.integer.value[i] = ~val>>7 & 0x1;
238 static int stac9460_adc_mute_put(struct snd_kcontrol *kcontrol,
239 struct snd_ctl_elem_value *ucontrol)
241 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
242 unsigned char new, old;
246 id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
248 for (i = 0; i < 2; ++i) {
249 reg = STAC946X_MIC_L_VOLUME + i;
250 old = stac9460_get(ice, reg);
251 new = (~ucontrol->value.integer.value[i]<<7&0x80) |
253 change = (new != old);
255 stac9460_put(ice, reg, new);
258 for (i = 0; i < 2; ++i) {
259 reg = STAC946X_MIC_L_VOLUME + i;
260 old = stac9460_2_get(ice, reg);
261 new = (~ucontrol->value.integer.value[i]<<7&0x80) |
263 change = (new != old);
265 stac9460_2_put(ice, reg, new);
272 *ADC gain mixer control
274 static int stac9460_adc_vol_info(struct snd_kcontrol *kcontrol,
275 struct snd_ctl_elem_info *uinfo)
277 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
279 uinfo->value.integer.min = 0; /* 0dB */
280 uinfo->value.integer.max = 0x0f; /* 22.5dB */
284 static int stac9460_adc_vol_get(struct snd_kcontrol *kcontrol,
285 struct snd_ctl_elem_value *ucontrol)
287 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
291 id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
293 for (i = 0; i < 2; ++i) {
294 reg = STAC946X_MIC_L_VOLUME + i;
295 vol = stac9460_get(ice, reg) & 0x0f;
296 ucontrol->value.integer.value[i] = 0x0f - vol;
299 for (i = 0; i < 2; ++i) {
300 reg = STAC946X_MIC_L_VOLUME + i;
301 vol = stac9460_2_get(ice, reg) & 0x0f;
302 ucontrol->value.integer.value[i] = 0x0f - vol;
308 static int stac9460_adc_vol_put(struct snd_kcontrol *kcontrol,
309 struct snd_ctl_elem_value *ucontrol)
311 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
313 unsigned char ovol, nvol;
316 id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
318 for (i = 0; i < 2; ++i) {
319 reg = STAC946X_MIC_L_VOLUME + i;
320 nvol = ucontrol->value.integer.value[i];
321 ovol = 0x0f - stac9460_get(ice, reg);
322 change = ((ovol & 0x0f) != nvol);
324 stac9460_put(ice, reg, (0x0f - nvol) |
328 for (i = 0; i < 2; ++i) {
329 reg = STAC946X_MIC_L_VOLUME + i;
330 nvol = ucontrol->value.integer.value[i];
331 ovol = 0x0f - stac9460_2_get(ice, reg);
332 change = ((ovol & 0x0f) != nvol);
334 stac9460_2_put(ice, reg, (0x0f - nvol) |
342 * MIC / LINE switch fonction
345 #define stac9460_mic_sw_info snd_ctl_boolean_mono_info
347 static int stac9460_mic_sw_get(struct snd_kcontrol *kcontrol,
348 struct snd_ctl_elem_value *ucontrol)
350 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
354 id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
356 val = stac9460_get(ice, STAC946X_GENERAL_PURPOSE);
358 val = stac9460_2_get(ice, STAC946X_GENERAL_PURPOSE);
359 ucontrol->value.integer.value[0] = ~val>>7 & 0x1;
363 static int stac9460_mic_sw_put(struct snd_kcontrol *kcontrol,
364 struct snd_ctl_elem_value *ucontrol)
366 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
367 unsigned char new, old;
370 id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
372 old = stac9460_get(ice, STAC946X_GENERAL_PURPOSE);
374 old = stac9460_2_get(ice, STAC946X_GENERAL_PURPOSE);
375 new = (~ucontrol->value.integer.value[0]<< 7 & 0x80) | (old & ~0x80);
376 change = (new != old);
379 stac9460_put(ice, STAC946X_GENERAL_PURPOSE, new);
381 stac9460_2_put(ice, STAC946X_GENERAL_PURPOSE, new);
389 static struct snd_kcontrol_new stac9640_controls[] __devinitdata = {
391 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
392 .name = "Master Playback Switch",
393 .info = stac9460_dac_mute_info,
394 .get = stac9460_dac_mute_get,
395 .put = stac9460_dac_mute_put,
399 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
400 .name = "Master Playback Volume",
401 .info = stac9460_dac_vol_info,
402 .get = stac9460_dac_vol_get,
403 .put = stac9460_dac_vol_put,
407 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
408 .name = "MIC/Line switch",
410 .info = stac9460_mic_sw_info,
411 .get = stac9460_mic_sw_get,
412 .put = stac9460_mic_sw_put,
416 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
417 .name = "DAC Switch",
419 .info = stac9460_dac_mute_info,
420 .get = stac9460_dac_mute_get,
421 .put = stac9460_dac_mute_put,
424 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
425 .name = "DAC Volume",
427 .info = stac9460_dac_vol_info,
428 .get = stac9460_dac_vol_get,
429 .put = stac9460_dac_vol_put,
432 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
433 .name = "ADC Switch",
435 .info = stac9460_adc_mute_info,
436 .get = stac9460_adc_mute_get,
437 .put = stac9460_adc_mute_put,
440 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
441 .name = "ADC Volume",
443 .info = stac9460_adc_vol_info,
444 .get = stac9460_adc_vol_get,
445 .put = stac9460_adc_vol_put,
453 static int __devinit wtm_add_controls(struct snd_ice1712 *ice)
458 for (i = 0; i < ARRAY_SIZE(stac9640_controls); i++) {
459 err = snd_ctl_add(ice->card,
460 snd_ctl_new1(&stac9640_controls[i], ice));
467 static int __devinit wtm_init(struct snd_ice1712 *ice)
469 static unsigned short stac_inits_prodigy[] = {
476 ice->num_total_dacs = 8;
477 ice->num_total_adcs = 4;
478 ice->force_rdma1 = 1;
481 p = stac_inits_prodigy;
482 for (; *p != (unsigned short)-1; p += 2) {
483 stac9460_put(ice, p[0], p[1]);
484 stac9460_2_put(ice, p[0], p[1]);
490 static unsigned char wtm_eeprom[] __devinitdata = {
491 0x47, /*SYSCONF: clock 192KHz, 4ADC, 8DAC */
492 0x80, /* ACLINK : I2S */
493 0xf8, /* I2S: vol; 96k, 24bit, 192k */
494 0xc1 /*SPDIF: out-en, spidf ext out*/,
496 0xff, /* GPIO_DIR1 */
497 0x7f, /* GPIO_DIR2 */
498 0x9f, /* GPIO_MASK */
499 0xff, /* GPIO_MASK1 */
500 0x7f, /* GPIO_MASK2 */
501 0x16, /* GPIO_STATE */
502 0x80, /* GPIO_STATE1 */
503 0x00, /* GPIO_STATE2 */
508 struct snd_ice1712_card_info snd_vt1724_wtm_cards[] __devinitdata = {
510 .subvendor = VT1724_SUBDEVICE_WTM,
511 .name = "ESI Waveterminal 192M",
513 .chip_init = wtm_init,
514 .build_controls = wtm_add_controls,
515 .eeprom_size = sizeof(wtm_eeprom),
516 .eeprom_data = wtm_eeprom,