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
29 #include <linux/delay.h>
30 #include <linux/interrupt.h>
31 #include <linux/init.h>
32 #include <linux/slab.h>
33 #include <sound/core.h>
42 * 2*ADC 6*DAC no1 ringbuffer r/w on i2c bus
44 static inline void stac9460_put(struct snd_ice1712
*ice
, int reg
,
47 snd_vt1724_write_i2c(ice
, STAC9460_I2C_ADDR
, reg
, val
);
50 static inline unsigned char stac9460_get(struct snd_ice1712
*ice
, int reg
)
52 return snd_vt1724_read_i2c(ice
, STAC9460_I2C_ADDR
, reg
);
56 * 2*ADC 2*DAC no2 ringbuffer r/w on i2c bus
58 static inline void stac9460_2_put(struct snd_ice1712
*ice
, int reg
,
61 snd_vt1724_write_i2c(ice
, STAC9460_2_I2C_ADDR
, reg
, val
);
64 static inline unsigned char stac9460_2_get(struct snd_ice1712
*ice
, int reg
)
66 return snd_vt1724_read_i2c(ice
, STAC9460_2_I2C_ADDR
, reg
);
73 #define stac9460_dac_mute_info snd_ctl_boolean_mono_info
75 static int stac9460_dac_mute_get(struct snd_kcontrol
*kcontrol
,
76 struct snd_ctl_elem_value
*ucontrol
)
78 struct snd_ice1712
*ice
= snd_kcontrol_chip(kcontrol
);
82 if (kcontrol
->private_value
) {
83 idx
= STAC946X_MASTER_VOLUME
;
86 id
= snd_ctl_get_ioffidx(kcontrol
, &ucontrol
->id
);
87 idx
= id
+ STAC946X_LF_VOLUME
;
90 val
= stac9460_get(ice
, idx
);
92 val
= stac9460_2_get(ice
, idx
- 6);
93 ucontrol
->value
.integer
.value
[0] = (~val
>> 7) & 0x1;
97 static int stac9460_dac_mute_put(struct snd_kcontrol
*kcontrol
,
98 struct snd_ctl_elem_value
*ucontrol
)
100 struct snd_ice1712
*ice
= snd_kcontrol_chip(kcontrol
);
101 unsigned char new, old
;
105 if (kcontrol
->private_value
) {
106 idx
= STAC946X_MASTER_VOLUME
;
107 old
= stac9460_get(ice
, idx
);
108 new = (~ucontrol
->value
.integer
.value
[0] << 7 & 0x80) |
110 change
= (new != old
);
112 stac9460_put(ice
, idx
, new);
113 stac9460_2_put(ice
, idx
, new);
116 id
= snd_ctl_get_ioffidx(kcontrol
, &ucontrol
->id
);
117 idx
= id
+ STAC946X_LF_VOLUME
;
119 old
= stac9460_get(ice
, idx
);
121 old
= stac9460_2_get(ice
, idx
- 6);
122 new = (~ucontrol
->value
.integer
.value
[0] << 7 & 0x80) |
124 change
= (new != old
);
127 stac9460_put(ice
, idx
, new);
129 stac9460_2_put(ice
, idx
- 6, new);
136 * DAC volume attenuation mixer control
138 static int stac9460_dac_vol_info(struct snd_kcontrol
*kcontrol
,
139 struct snd_ctl_elem_info
*uinfo
)
141 uinfo
->type
= SNDRV_CTL_ELEM_TYPE_INTEGER
;
143 uinfo
->value
.integer
.min
= 0; /* mute */
144 uinfo
->value
.integer
.max
= 0x7f; /* 0dB */
148 static int stac9460_dac_vol_get(struct snd_kcontrol
*kcontrol
,
149 struct snd_ctl_elem_value
*ucontrol
)
151 struct snd_ice1712
*ice
= snd_kcontrol_chip(kcontrol
);
155 if (kcontrol
->private_value
) {
156 idx
= STAC946X_MASTER_VOLUME
;
159 id
= snd_ctl_get_ioffidx(kcontrol
, &ucontrol
->id
);
160 idx
= id
+ STAC946X_LF_VOLUME
;
163 vol
= stac9460_get(ice
, idx
) & 0x7f;
165 vol
= stac9460_2_get(ice
, idx
- 6) & 0x7f;
166 ucontrol
->value
.integer
.value
[0] = 0x7f - vol
;
170 static int stac9460_dac_vol_put(struct snd_kcontrol
*kcontrol
,
171 struct snd_ctl_elem_value
*ucontrol
)
173 struct snd_ice1712
*ice
= snd_kcontrol_chip(kcontrol
);
175 unsigned char tmp
, ovol
, nvol
;
178 if (kcontrol
->private_value
) {
179 idx
= STAC946X_MASTER_VOLUME
;
180 nvol
= ucontrol
->value
.integer
.value
[0] & 0x7f;
181 tmp
= stac9460_get(ice
, idx
);
182 ovol
= 0x7f - (tmp
& 0x7f);
183 change
= (ovol
!= nvol
);
185 stac9460_put(ice
, idx
, (0x7f - nvol
) | (tmp
& 0x80));
186 stac9460_2_put(ice
, idx
, (0x7f - nvol
) | (tmp
& 0x80));
189 id
= snd_ctl_get_ioffidx(kcontrol
, &ucontrol
->id
);
190 idx
= id
+ STAC946X_LF_VOLUME
;
191 nvol
= ucontrol
->value
.integer
.value
[0] & 0x7f;
193 tmp
= stac9460_get(ice
, idx
);
195 tmp
= stac9460_2_get(ice
, idx
- 6);
196 ovol
= 0x7f - (tmp
& 0x7f);
197 change
= (ovol
!= nvol
);
200 stac9460_put(ice
, idx
, (0x7f - nvol
) |
203 stac9460_2_put(ice
, idx
-6, (0x7f - nvol
) |
213 #define stac9460_adc_mute_info snd_ctl_boolean_stereo_info
215 static int stac9460_adc_mute_get(struct snd_kcontrol
*kcontrol
,
216 struct snd_ctl_elem_value
*ucontrol
)
218 struct snd_ice1712
*ice
= snd_kcontrol_chip(kcontrol
);
222 id
= snd_ctl_get_ioffidx(kcontrol
, &ucontrol
->id
);
224 for (i
= 0; i
< 2; ++i
) {
225 val
= stac9460_get(ice
, STAC946X_MIC_L_VOLUME
+ i
);
226 ucontrol
->value
.integer
.value
[i
] = ~val
>>7 & 0x1;
229 for (i
= 0; i
< 2; ++i
) {
230 val
= stac9460_2_get(ice
, STAC946X_MIC_L_VOLUME
+ i
);
231 ucontrol
->value
.integer
.value
[i
] = ~val
>>7 & 0x1;
237 static int stac9460_adc_mute_put(struct snd_kcontrol
*kcontrol
,
238 struct snd_ctl_elem_value
*ucontrol
)
240 struct snd_ice1712
*ice
= snd_kcontrol_chip(kcontrol
);
241 unsigned char new, old
;
245 id
= snd_ctl_get_ioffidx(kcontrol
, &ucontrol
->id
);
247 for (i
= 0; i
< 2; ++i
) {
248 reg
= STAC946X_MIC_L_VOLUME
+ i
;
249 old
= stac9460_get(ice
, reg
);
250 new = (~ucontrol
->value
.integer
.value
[i
]<<7&0x80) |
252 change
= (new != old
);
254 stac9460_put(ice
, reg
, new);
257 for (i
= 0; i
< 2; ++i
) {
258 reg
= STAC946X_MIC_L_VOLUME
+ i
;
259 old
= stac9460_2_get(ice
, reg
);
260 new = (~ucontrol
->value
.integer
.value
[i
]<<7&0x80) |
262 change
= (new != old
);
264 stac9460_2_put(ice
, reg
, new);
271 *ADC gain mixer control
273 static int stac9460_adc_vol_info(struct snd_kcontrol
*kcontrol
,
274 struct snd_ctl_elem_info
*uinfo
)
276 uinfo
->type
= SNDRV_CTL_ELEM_TYPE_INTEGER
;
278 uinfo
->value
.integer
.min
= 0; /* 0dB */
279 uinfo
->value
.integer
.max
= 0x0f; /* 22.5dB */
283 static int stac9460_adc_vol_get(struct snd_kcontrol
*kcontrol
,
284 struct snd_ctl_elem_value
*ucontrol
)
286 struct snd_ice1712
*ice
= snd_kcontrol_chip(kcontrol
);
290 id
= snd_ctl_get_ioffidx(kcontrol
, &ucontrol
->id
);
292 for (i
= 0; i
< 2; ++i
) {
293 reg
= STAC946X_MIC_L_VOLUME
+ i
;
294 vol
= stac9460_get(ice
, reg
) & 0x0f;
295 ucontrol
->value
.integer
.value
[i
] = 0x0f - vol
;
298 for (i
= 0; i
< 2; ++i
) {
299 reg
= STAC946X_MIC_L_VOLUME
+ i
;
300 vol
= stac9460_2_get(ice
, reg
) & 0x0f;
301 ucontrol
->value
.integer
.value
[i
] = 0x0f - vol
;
307 static int stac9460_adc_vol_put(struct snd_kcontrol
*kcontrol
,
308 struct snd_ctl_elem_value
*ucontrol
)
310 struct snd_ice1712
*ice
= snd_kcontrol_chip(kcontrol
);
312 unsigned char ovol
, nvol
;
315 id
= snd_ctl_get_ioffidx(kcontrol
, &ucontrol
->id
);
317 for (i
= 0; i
< 2; ++i
) {
318 reg
= STAC946X_MIC_L_VOLUME
+ i
;
319 nvol
= ucontrol
->value
.integer
.value
[i
] & 0x0f;
320 ovol
= 0x0f - stac9460_get(ice
, reg
);
321 change
= ((ovol
& 0x0f) != nvol
);
323 stac9460_put(ice
, reg
, (0x0f - nvol
) |
327 for (i
= 0; i
< 2; ++i
) {
328 reg
= STAC946X_MIC_L_VOLUME
+ i
;
329 nvol
= ucontrol
->value
.integer
.value
[i
] & 0x0f;
330 ovol
= 0x0f - stac9460_2_get(ice
, reg
);
331 change
= ((ovol
& 0x0f) != nvol
);
333 stac9460_2_put(ice
, reg
, (0x0f - nvol
) |
341 * MIC / LINE switch fonction
344 #define stac9460_mic_sw_info snd_ctl_boolean_mono_info
346 static int stac9460_mic_sw_get(struct snd_kcontrol
*kcontrol
,
347 struct snd_ctl_elem_value
*ucontrol
)
349 struct snd_ice1712
*ice
= snd_kcontrol_chip(kcontrol
);
353 id
= snd_ctl_get_ioffidx(kcontrol
, &ucontrol
->id
);
355 val
= stac9460_get(ice
, STAC946X_GENERAL_PURPOSE
);
357 val
= stac9460_2_get(ice
, STAC946X_GENERAL_PURPOSE
);
358 ucontrol
->value
.integer
.value
[0] = ~val
>>7 & 0x1;
362 static int stac9460_mic_sw_put(struct snd_kcontrol
*kcontrol
,
363 struct snd_ctl_elem_value
*ucontrol
)
365 struct snd_ice1712
*ice
= snd_kcontrol_chip(kcontrol
);
366 unsigned char new, old
;
369 id
= snd_ctl_get_ioffidx(kcontrol
, &ucontrol
->id
);
371 old
= stac9460_get(ice
, STAC946X_GENERAL_PURPOSE
);
373 old
= stac9460_2_get(ice
, STAC946X_GENERAL_PURPOSE
);
374 new = (~ucontrol
->value
.integer
.value
[0] << 7 & 0x80) | (old
& ~0x80);
375 change
= (new != old
);
378 stac9460_put(ice
, STAC946X_GENERAL_PURPOSE
, new);
380 stac9460_2_put(ice
, STAC946X_GENERAL_PURPOSE
, new);
388 static struct snd_kcontrol_new stac9640_controls
[] __devinitdata
= {
390 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
391 .name
= "Master Playback Switch",
392 .info
= stac9460_dac_mute_info
,
393 .get
= stac9460_dac_mute_get
,
394 .put
= stac9460_dac_mute_put
,
398 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
399 .name
= "Master Playback Volume",
400 .info
= stac9460_dac_vol_info
,
401 .get
= stac9460_dac_vol_get
,
402 .put
= stac9460_dac_vol_put
,
406 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
407 .name
= "MIC/Line switch",
409 .info
= stac9460_mic_sw_info
,
410 .get
= stac9460_mic_sw_get
,
411 .put
= stac9460_mic_sw_put
,
415 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
416 .name
= "DAC Switch",
418 .info
= stac9460_dac_mute_info
,
419 .get
= stac9460_dac_mute_get
,
420 .put
= stac9460_dac_mute_put
,
423 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
424 .name
= "DAC Volume",
426 .info
= stac9460_dac_vol_info
,
427 .get
= stac9460_dac_vol_get
,
428 .put
= stac9460_dac_vol_put
,
431 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
432 .name
= "ADC Switch",
434 .info
= stac9460_adc_mute_info
,
435 .get
= stac9460_adc_mute_get
,
436 .put
= stac9460_adc_mute_put
,
439 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
440 .name
= "ADC Volume",
442 .info
= stac9460_adc_vol_info
,
443 .get
= stac9460_adc_vol_get
,
444 .put
= stac9460_adc_vol_put
,
452 static int __devinit
wtm_add_controls(struct snd_ice1712
*ice
)
457 for (i
= 0; i
< ARRAY_SIZE(stac9640_controls
); i
++) {
458 err
= snd_ctl_add(ice
->card
,
459 snd_ctl_new1(&stac9640_controls
[i
], ice
));
466 static int __devinit
wtm_init(struct snd_ice1712
*ice
)
468 static unsigned short stac_inits_prodigy
[] = {
475 ice
->num_total_dacs
= 8;
476 ice
->num_total_adcs
= 4;
477 ice
->force_rdma1
= 1;
480 p
= stac_inits_prodigy
;
481 for (; *p
!= (unsigned short)-1; p
+= 2) {
482 stac9460_put(ice
, p
[0], p
[1]);
483 stac9460_2_put(ice
, p
[0], p
[1]);
489 static unsigned char wtm_eeprom
[] __devinitdata
= {
490 0x47, /*SYSCONF: clock 192KHz, 4ADC, 8DAC */
491 0x80, /* ACLINK : I2S */
492 0xf8, /* I2S: vol; 96k, 24bit, 192k */
493 0xc1 /*SPDIF: out-en, spidf ext out*/,
495 0xff, /* GPIO_DIR1 */
496 0x7f, /* GPIO_DIR2 */
497 0x9f, /* GPIO_MASK */
498 0xff, /* GPIO_MASK1 */
499 0x7f, /* GPIO_MASK2 */
500 0x16, /* GPIO_STATE */
501 0x80, /* GPIO_STATE1 */
502 0x00, /* GPIO_STATE2 */
507 struct snd_ice1712_card_info snd_vt1724_wtm_cards
[] __devinitdata
= {
509 .subvendor
= VT1724_SUBDEVICE_WTM
,
510 .name
= "ESI Waveterminal 192M",
512 .chip_init
= wtm_init
,
513 .build_controls
= wtm_add_controls
,
514 .eeprom_size
= sizeof(wtm_eeprom
),
515 .eeprom_data
= wtm_eeprom
,