Linux 2.6.24.5
[linux/fpc-iii.git] / sound / pci / ice1712 / wtm.c
blob7fcce0a506d65e516e272f901b49d97fac6022af
1 /*
2 * ALSA driver for ICEnsemble VT1724 (Envy24HT)
3 *
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
8 * source
9 *
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
24 */
28 #include <sound/driver.h>
29 #include <asm/io.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>
36 #include "ice1712.h"
37 #include "envy24ht.h"
38 #include "wtm.h"
39 #include "stac946x.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,
46 unsigned char val)
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,
60 unsigned char val)
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);
72 * DAC mute control
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);
80 unsigned char val;
81 int idx, id;
83 if (kcontrol->private_value) {
84 idx = STAC946X_MASTER_VOLUME;
85 id = 0;
86 } else {
87 id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
88 idx = id + STAC946X_LF_VOLUME;
90 if (id < 6)
91 val = stac9460_get(ice, idx);
92 else
93 val = stac9460_2_get(ice,idx - 6);
94 ucontrol->value.integer.value[0] = (~val >> 7) & 0x1;
95 return 0;
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;
103 int id, idx;
104 int change;
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) |
110 (old & ~0x80);
111 change = (new != old);
112 if (change) {
113 stac9460_put(ice, idx, new);
114 stac9460_2_put(ice, idx, new);
116 } else {
117 id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
118 idx = id + STAC946X_LF_VOLUME;
119 if (id < 6)
120 old = stac9460_get(ice, idx);
121 else
122 old = stac9460_2_get(ice, idx - 6);
123 new = (~ucontrol->value.integer.value[0]<< 7 & 0x80) |
124 (old & ~0x80);
125 change = (new != old);
126 if (change) {
127 if (id < 6)
128 stac9460_put(ice, idx, new);
129 else
130 stac9460_2_put(ice, idx - 6, new);
133 return change;
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;
143 uinfo->count = 1;
144 uinfo->value.integer.min = 0; /* mute */
145 uinfo->value.integer.max = 0x7f; /* 0dB */
146 return 0;
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);
153 int idx, id;
154 unsigned char vol;
156 if (kcontrol->private_value) {
157 idx = STAC946X_MASTER_VOLUME;
158 id = 0;
159 } else {
160 id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
161 idx = id + STAC946X_LF_VOLUME;
163 if (id < 6)
164 vol = stac9460_get(ice, idx) & 0x7f;
165 else
166 vol = stac9460_2_get(ice, idx - 6) & 0x7f;
167 ucontrol->value.integer.value[0] = 0x7f - vol;
168 return 0;
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);
175 int idx, id;
176 unsigned char tmp, ovol, nvol;
177 int change;
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);
185 if (change) {
186 stac9460_put(ice, idx, (0x7f - nvol) | (tmp & 0x80));
187 stac9460_2_put(ice, idx, (0x7f - nvol) | (tmp & 0x80));
189 } else {
190 id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
191 idx = id + STAC946X_LF_VOLUME;
192 nvol = ucontrol->value.integer.value[0];
193 if (id < 6)
194 tmp = stac9460_get(ice, idx);
195 else
196 tmp = stac9460_2_get(ice, idx - 6);
197 ovol = 0x7f - (tmp & 0x7f);
198 change = (ovol != nvol);
199 if (change) {
200 if (id < 6)
201 stac9460_put(ice, idx, (0x7f - nvol) |
202 (tmp & 0x80));
203 else
204 stac9460_2_put(ice, idx-6, (0x7f - nvol) |
205 (tmp & 0x80));
208 return change;
212 * ADC mute control
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);
220 unsigned char val;
221 int i, id;
223 id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
224 if (id == 0) {
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;
229 } else {
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;
235 return 0;
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;
243 int i, reg, id;
244 int change;
246 id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
247 if (id == 0) {
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) |
252 (old&~0x80);
253 change = (new != old);
254 if (change)
255 stac9460_put(ice, reg, new);
257 } else {
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) |
262 (old&~0x80);
263 change = (new != old);
264 if (change)
265 stac9460_2_put(ice, reg, new);
268 return change;
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;
278 uinfo->count = 2;
279 uinfo->value.integer.min = 0; /* 0dB */
280 uinfo->value.integer.max = 0x0f; /* 22.5dB */
281 return 0;
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);
288 int i, reg, id;
289 unsigned char vol;
291 id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
292 if (id == 0) {
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;
298 } else {
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;
305 return 0;
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);
312 int i, reg, id;
313 unsigned char ovol, nvol;
314 int change;
316 id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
317 if (id == 0) {
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);
323 if (change)
324 stac9460_put(ice, reg, (0x0f - nvol) |
325 (ovol & ~0x0f));
327 } else {
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);
333 if (change)
334 stac9460_2_put(ice, reg, (0x0f - nvol) |
335 (ovol & ~0x0f));
338 return change;
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);
351 unsigned char val;
352 int id;
354 id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
355 if (id == 0)
356 val = stac9460_get(ice, STAC946X_GENERAL_PURPOSE);
357 else
358 val = stac9460_2_get(ice, STAC946X_GENERAL_PURPOSE);
359 ucontrol->value.integer.value[0] = ~val>>7 & 0x1;
360 return 0;
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;
368 int change, id;
370 id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
371 if (id == 0)
372 old = stac9460_get(ice, STAC946X_GENERAL_PURPOSE);
373 else
374 old = stac9460_2_get(ice, STAC946X_GENERAL_PURPOSE);
375 new = (~ucontrol->value.integer.value[0]<< 7 & 0x80) | (old & ~0x80);
376 change = (new != old);
377 if (change) {
378 if (id == 0)
379 stac9460_put(ice, STAC946X_GENERAL_PURPOSE, new);
380 else
381 stac9460_2_put(ice, STAC946X_GENERAL_PURPOSE, new);
383 return change;
387 * Control tabs
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,
396 .private_value = 1
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,
404 .private_value = 1,
407 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
408 .name = "MIC/Line switch",
409 .count = 2,
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",
418 .count = 8,
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",
426 .count = 8,
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",
434 .count = 2,
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",
442 .count = 2,
443 .info = stac9460_adc_vol_info,
444 .get = stac9460_adc_vol_get,
445 .put = stac9460_adc_vol_put,
452 /*INIT*/
453 static int __devinit wtm_add_controls(struct snd_ice1712 *ice)
455 unsigned int i;
456 int err;
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));
461 if (err < 0)
462 return err;
464 return 0;
467 static int __devinit wtm_init(struct snd_ice1712 *ice)
469 static unsigned short stac_inits_prodigy[] = {
470 STAC946X_RESET, 0,
471 (unsigned short)-1
473 unsigned short *p;
475 /*WTM 192M*/
476 ice->num_total_dacs = 8;
477 ice->num_total_adcs = 4;
478 ice->force_rdma1 = 1;
480 /*initialize codec*/
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]);
486 return 0;
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*/,
495 0x9f, /* GPIO_DIR */
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 */
507 /*entry point*/
508 struct snd_ice1712_card_info snd_vt1724_wtm_cards[] __devinitdata = {
510 .subvendor = VT1724_SUBDEVICE_WTM,
511 .name = "ESI Waveterminal 192M",
512 .model = "WT192M",
513 .chip_init = wtm_init,
514 .build_controls = wtm_add_controls,
515 .eeprom_size = sizeof(wtm_eeprom),
516 .eeprom_data = wtm_eeprom,
518 {} /*terminator*/