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 <sound/core.h>
41 * 2*ADC 6*DAC no1 ringbuffer r/w on i2c bus
43 static inline void stac9460_put(struct snd_ice1712
*ice
, int reg
,
46 snd_vt1724_write_i2c(ice
, STAC9460_I2C_ADDR
, reg
, val
);
49 static inline unsigned char stac9460_get(struct snd_ice1712
*ice
, int reg
)
51 return snd_vt1724_read_i2c(ice
, STAC9460_I2C_ADDR
, reg
);
55 * 2*ADC 2*DAC no2 ringbuffer r/w on i2c bus
57 static inline void stac9460_2_put(struct snd_ice1712
*ice
, int reg
,
60 snd_vt1724_write_i2c(ice
, STAC9460_2_I2C_ADDR
, reg
, val
);
63 static inline unsigned char stac9460_2_get(struct snd_ice1712
*ice
, int reg
)
65 return snd_vt1724_read_i2c(ice
, STAC9460_2_I2C_ADDR
, reg
);
72 #define stac9460_dac_mute_info snd_ctl_boolean_mono_info
74 static int stac9460_dac_mute_get(struct snd_kcontrol
*kcontrol
,
75 struct snd_ctl_elem_value
*ucontrol
)
77 struct snd_ice1712
*ice
= snd_kcontrol_chip(kcontrol
);
81 if (kcontrol
->private_value
) {
82 idx
= STAC946X_MASTER_VOLUME
;
85 id
= snd_ctl_get_ioffidx(kcontrol
, &ucontrol
->id
);
86 idx
= id
+ STAC946X_LF_VOLUME
;
89 val
= stac9460_get(ice
, idx
);
91 val
= stac9460_2_get(ice
, idx
- 6);
92 ucontrol
->value
.integer
.value
[0] = (~val
>> 7) & 0x1;
96 static int stac9460_dac_mute_put(struct snd_kcontrol
*kcontrol
,
97 struct snd_ctl_elem_value
*ucontrol
)
99 struct snd_ice1712
*ice
= snd_kcontrol_chip(kcontrol
);
100 unsigned char new, old
;
104 if (kcontrol
->private_value
) {
105 idx
= STAC946X_MASTER_VOLUME
;
106 old
= stac9460_get(ice
, idx
);
107 new = (~ucontrol
->value
.integer
.value
[0] << 7 & 0x80) |
109 change
= (new != old
);
111 stac9460_put(ice
, idx
, new);
112 stac9460_2_put(ice
, idx
, new);
115 id
= snd_ctl_get_ioffidx(kcontrol
, &ucontrol
->id
);
116 idx
= id
+ STAC946X_LF_VOLUME
;
118 old
= stac9460_get(ice
, idx
);
120 old
= stac9460_2_get(ice
, idx
- 6);
121 new = (~ucontrol
->value
.integer
.value
[0] << 7 & 0x80) |
123 change
= (new != old
);
126 stac9460_put(ice
, idx
, new);
128 stac9460_2_put(ice
, idx
- 6, new);
135 * DAC volume attenuation mixer control
137 static int stac9460_dac_vol_info(struct snd_kcontrol
*kcontrol
,
138 struct snd_ctl_elem_info
*uinfo
)
140 uinfo
->type
= SNDRV_CTL_ELEM_TYPE_INTEGER
;
142 uinfo
->value
.integer
.min
= 0; /* mute */
143 uinfo
->value
.integer
.max
= 0x7f; /* 0dB */
147 static int stac9460_dac_vol_get(struct snd_kcontrol
*kcontrol
,
148 struct snd_ctl_elem_value
*ucontrol
)
150 struct snd_ice1712
*ice
= snd_kcontrol_chip(kcontrol
);
154 if (kcontrol
->private_value
) {
155 idx
= STAC946X_MASTER_VOLUME
;
158 id
= snd_ctl_get_ioffidx(kcontrol
, &ucontrol
->id
);
159 idx
= id
+ STAC946X_LF_VOLUME
;
162 vol
= stac9460_get(ice
, idx
) & 0x7f;
164 vol
= stac9460_2_get(ice
, idx
- 6) & 0x7f;
165 ucontrol
->value
.integer
.value
[0] = 0x7f - vol
;
169 static int stac9460_dac_vol_put(struct snd_kcontrol
*kcontrol
,
170 struct snd_ctl_elem_value
*ucontrol
)
172 struct snd_ice1712
*ice
= snd_kcontrol_chip(kcontrol
);
174 unsigned char tmp
, ovol
, nvol
;
177 if (kcontrol
->private_value
) {
178 idx
= STAC946X_MASTER_VOLUME
;
179 nvol
= ucontrol
->value
.integer
.value
[0] & 0x7f;
180 tmp
= stac9460_get(ice
, idx
);
181 ovol
= 0x7f - (tmp
& 0x7f);
182 change
= (ovol
!= nvol
);
184 stac9460_put(ice
, idx
, (0x7f - nvol
) | (tmp
& 0x80));
185 stac9460_2_put(ice
, idx
, (0x7f - nvol
) | (tmp
& 0x80));
188 id
= snd_ctl_get_ioffidx(kcontrol
, &ucontrol
->id
);
189 idx
= id
+ STAC946X_LF_VOLUME
;
190 nvol
= ucontrol
->value
.integer
.value
[0] & 0x7f;
192 tmp
= stac9460_get(ice
, idx
);
194 tmp
= stac9460_2_get(ice
, idx
- 6);
195 ovol
= 0x7f - (tmp
& 0x7f);
196 change
= (ovol
!= nvol
);
199 stac9460_put(ice
, idx
, (0x7f - nvol
) |
202 stac9460_2_put(ice
, idx
-6, (0x7f - nvol
) |
212 #define stac9460_adc_mute_info snd_ctl_boolean_stereo_info
214 static int stac9460_adc_mute_get(struct snd_kcontrol
*kcontrol
,
215 struct snd_ctl_elem_value
*ucontrol
)
217 struct snd_ice1712
*ice
= snd_kcontrol_chip(kcontrol
);
221 id
= snd_ctl_get_ioffidx(kcontrol
, &ucontrol
->id
);
223 for (i
= 0; i
< 2; ++i
) {
224 val
= stac9460_get(ice
, STAC946X_MIC_L_VOLUME
+ i
);
225 ucontrol
->value
.integer
.value
[i
] = ~val
>>7 & 0x1;
228 for (i
= 0; i
< 2; ++i
) {
229 val
= stac9460_2_get(ice
, STAC946X_MIC_L_VOLUME
+ i
);
230 ucontrol
->value
.integer
.value
[i
] = ~val
>>7 & 0x1;
236 static int stac9460_adc_mute_put(struct snd_kcontrol
*kcontrol
,
237 struct snd_ctl_elem_value
*ucontrol
)
239 struct snd_ice1712
*ice
= snd_kcontrol_chip(kcontrol
);
240 unsigned char new, old
;
244 id
= snd_ctl_get_ioffidx(kcontrol
, &ucontrol
->id
);
246 for (i
= 0; i
< 2; ++i
) {
247 reg
= STAC946X_MIC_L_VOLUME
+ i
;
248 old
= stac9460_get(ice
, reg
);
249 new = (~ucontrol
->value
.integer
.value
[i
]<<7&0x80) |
251 change
= (new != old
);
253 stac9460_put(ice
, reg
, new);
256 for (i
= 0; i
< 2; ++i
) {
257 reg
= STAC946X_MIC_L_VOLUME
+ i
;
258 old
= stac9460_2_get(ice
, reg
);
259 new = (~ucontrol
->value
.integer
.value
[i
]<<7&0x80) |
261 change
= (new != old
);
263 stac9460_2_put(ice
, reg
, new);
270 *ADC gain mixer control
272 static int stac9460_adc_vol_info(struct snd_kcontrol
*kcontrol
,
273 struct snd_ctl_elem_info
*uinfo
)
275 uinfo
->type
= SNDRV_CTL_ELEM_TYPE_INTEGER
;
277 uinfo
->value
.integer
.min
= 0; /* 0dB */
278 uinfo
->value
.integer
.max
= 0x0f; /* 22.5dB */
282 static int stac9460_adc_vol_get(struct snd_kcontrol
*kcontrol
,
283 struct snd_ctl_elem_value
*ucontrol
)
285 struct snd_ice1712
*ice
= snd_kcontrol_chip(kcontrol
);
289 id
= snd_ctl_get_ioffidx(kcontrol
, &ucontrol
->id
);
291 for (i
= 0; i
< 2; ++i
) {
292 reg
= STAC946X_MIC_L_VOLUME
+ i
;
293 vol
= stac9460_get(ice
, reg
) & 0x0f;
294 ucontrol
->value
.integer
.value
[i
] = 0x0f - vol
;
297 for (i
= 0; i
< 2; ++i
) {
298 reg
= STAC946X_MIC_L_VOLUME
+ i
;
299 vol
= stac9460_2_get(ice
, reg
) & 0x0f;
300 ucontrol
->value
.integer
.value
[i
] = 0x0f - vol
;
306 static int stac9460_adc_vol_put(struct snd_kcontrol
*kcontrol
,
307 struct snd_ctl_elem_value
*ucontrol
)
309 struct snd_ice1712
*ice
= snd_kcontrol_chip(kcontrol
);
311 unsigned char ovol
, nvol
;
314 id
= snd_ctl_get_ioffidx(kcontrol
, &ucontrol
->id
);
316 for (i
= 0; i
< 2; ++i
) {
317 reg
= STAC946X_MIC_L_VOLUME
+ i
;
318 nvol
= ucontrol
->value
.integer
.value
[i
] & 0x0f;
319 ovol
= 0x0f - stac9460_get(ice
, reg
);
320 change
= ((ovol
& 0x0f) != nvol
);
322 stac9460_put(ice
, reg
, (0x0f - nvol
) |
326 for (i
= 0; i
< 2; ++i
) {
327 reg
= STAC946X_MIC_L_VOLUME
+ i
;
328 nvol
= ucontrol
->value
.integer
.value
[i
] & 0x0f;
329 ovol
= 0x0f - stac9460_2_get(ice
, reg
);
330 change
= ((ovol
& 0x0f) != nvol
);
332 stac9460_2_put(ice
, reg
, (0x0f - nvol
) |
340 * MIC / LINE switch fonction
343 #define stac9460_mic_sw_info snd_ctl_boolean_mono_info
345 static int stac9460_mic_sw_get(struct snd_kcontrol
*kcontrol
,
346 struct snd_ctl_elem_value
*ucontrol
)
348 struct snd_ice1712
*ice
= snd_kcontrol_chip(kcontrol
);
352 id
= snd_ctl_get_ioffidx(kcontrol
, &ucontrol
->id
);
354 val
= stac9460_get(ice
, STAC946X_GENERAL_PURPOSE
);
356 val
= stac9460_2_get(ice
, STAC946X_GENERAL_PURPOSE
);
357 ucontrol
->value
.integer
.value
[0] = ~val
>>7 & 0x1;
361 static int stac9460_mic_sw_put(struct snd_kcontrol
*kcontrol
,
362 struct snd_ctl_elem_value
*ucontrol
)
364 struct snd_ice1712
*ice
= snd_kcontrol_chip(kcontrol
);
365 unsigned char new, old
;
368 id
= snd_ctl_get_ioffidx(kcontrol
, &ucontrol
->id
);
370 old
= stac9460_get(ice
, STAC946X_GENERAL_PURPOSE
);
372 old
= stac9460_2_get(ice
, STAC946X_GENERAL_PURPOSE
);
373 new = (~ucontrol
->value
.integer
.value
[0] << 7 & 0x80) | (old
& ~0x80);
374 change
= (new != old
);
377 stac9460_put(ice
, STAC946X_GENERAL_PURPOSE
, new);
379 stac9460_2_put(ice
, STAC946X_GENERAL_PURPOSE
, new);
387 static struct snd_kcontrol_new stac9640_controls
[] __devinitdata
= {
389 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
390 .name
= "Master Playback Switch",
391 .info
= stac9460_dac_mute_info
,
392 .get
= stac9460_dac_mute_get
,
393 .put
= stac9460_dac_mute_put
,
397 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
398 .name
= "Master Playback Volume",
399 .info
= stac9460_dac_vol_info
,
400 .get
= stac9460_dac_vol_get
,
401 .put
= stac9460_dac_vol_put
,
405 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
406 .name
= "MIC/Line switch",
408 .info
= stac9460_mic_sw_info
,
409 .get
= stac9460_mic_sw_get
,
410 .put
= stac9460_mic_sw_put
,
414 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
415 .name
= "DAC Switch",
417 .info
= stac9460_dac_mute_info
,
418 .get
= stac9460_dac_mute_get
,
419 .put
= stac9460_dac_mute_put
,
422 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
423 .name
= "DAC Volume",
425 .info
= stac9460_dac_vol_info
,
426 .get
= stac9460_dac_vol_get
,
427 .put
= stac9460_dac_vol_put
,
430 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
431 .name
= "ADC Switch",
433 .info
= stac9460_adc_mute_info
,
434 .get
= stac9460_adc_mute_get
,
435 .put
= stac9460_adc_mute_put
,
438 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
439 .name
= "ADC Volume",
441 .info
= stac9460_adc_vol_info
,
442 .get
= stac9460_adc_vol_get
,
443 .put
= stac9460_adc_vol_put
,
451 static int __devinit
wtm_add_controls(struct snd_ice1712
*ice
)
456 for (i
= 0; i
< ARRAY_SIZE(stac9640_controls
); i
++) {
457 err
= snd_ctl_add(ice
->card
,
458 snd_ctl_new1(&stac9640_controls
[i
], ice
));
465 static int __devinit
wtm_init(struct snd_ice1712
*ice
)
467 static unsigned short stac_inits_prodigy
[] = {
474 ice
->num_total_dacs
= 8;
475 ice
->num_total_adcs
= 4;
476 ice
->force_rdma1
= 1;
479 p
= stac_inits_prodigy
;
480 for (; *p
!= (unsigned short)-1; p
+= 2) {
481 stac9460_put(ice
, p
[0], p
[1]);
482 stac9460_2_put(ice
, p
[0], p
[1]);
488 static unsigned char wtm_eeprom
[] __devinitdata
= {
489 0x47, /*SYSCONF: clock 192KHz, 4ADC, 8DAC */
490 0x80, /* ACLINK : I2S */
491 0xf8, /* I2S: vol; 96k, 24bit, 192k */
492 0xc1 /*SPDIF: out-en, spidf ext out*/,
494 0xff, /* GPIO_DIR1 */
495 0x7f, /* GPIO_DIR2 */
496 0x9f, /* GPIO_MASK */
497 0xff, /* GPIO_MASK1 */
498 0x7f, /* GPIO_MASK2 */
499 0x16, /* GPIO_STATE */
500 0x80, /* GPIO_STATE1 */
501 0x00, /* GPIO_STATE2 */
506 struct snd_ice1712_card_info snd_vt1724_wtm_cards
[] __devinitdata
= {
508 .subvendor
= VT1724_SUBDEVICE_WTM
,
509 .name
= "ESI Waveterminal 192M",
511 .chip_init
= wtm_init
,
512 .build_controls
= wtm_add_controls
,
513 .eeprom_size
= sizeof(wtm_eeprom
),
514 .eeprom_data
= wtm_eeprom
,