[ALSA] Changed Jaroslav Kysela's e-mail from perex@suse.cz to perex@perex.cz
[safe/jmp/linux-2.6] / sound / pci / ice1712 / wtm.c
1 /*
2  *      ALSA driver for ICEnsemble VT1724 (Envy24HT)
3  *      
4  *      Lowlevel functions for Ego Sys Waveterminal 192M
5  *
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.
14  *
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.
19  *
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
23  *      
24  */     
25
26
27
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>
35
36 #include "ice1712.h"
37 #include "envy24ht.h"
38 #include "wtm.h"
39 #include "stac946x.h"
40
41
42 /*
43  *      2*ADC 6*DAC no1 ringbuffer r/w on i2c bus 
44  */
45 static inline void stac9460_put(struct snd_ice1712 *ice, int reg, 
46                                                 unsigned char val)
47 {
48         snd_vt1724_write_i2c(ice, STAC9460_I2C_ADDR, reg, val);
49 }
50
51 static inline unsigned char stac9460_get(struct snd_ice1712 *ice, int reg)
52 {
53         return snd_vt1724_read_i2c(ice, STAC9460_I2C_ADDR, reg);
54 }
55
56 /*
57  *      2*ADC 2*DAC no2 ringbuffer r/w on i2c bus
58  */
59 static inline void stac9460_2_put(struct snd_ice1712 *ice, int reg,
60                                                 unsigned char val)
61 {
62         snd_vt1724_write_i2c(ice, STAC9460_2_I2C_ADDR, reg, val);
63 }
64
65 static inline unsigned char stac9460_2_get(struct snd_ice1712 *ice, int reg)
66 {
67         return snd_vt1724_read_i2c(ice, STAC9460_2_I2C_ADDR, reg);
68 }
69
70
71 /*
72  *      DAC mute control
73  */
74 #define stac9460_dac_mute_info          snd_ctl_boolean_mono_info
75
76 static int stac9460_dac_mute_get(struct snd_kcontrol *kcontrol,
77                                 struct snd_ctl_elem_value *ucontrol)
78 {
79         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
80         unsigned char val;
81         int idx, id;
82
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;
89         }
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;
96 }
97
98 static int stac9460_dac_mute_put(struct snd_kcontrol *kcontrol,
99                                 struct snd_ctl_elem_value *ucontrol)
100 {
101         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
102         unsigned char new, old;
103         int id, idx;
104         int change;
105
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);
115                 }
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);
131                 }
132         }
133         return change;
134 }
135
136 /*
137  *      DAC volume attenuation mixer control
138  */
139 static int stac9460_dac_vol_info(struct snd_kcontrol *kcontrol,
140                                 struct snd_ctl_elem_info *uinfo)
141 {
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;
147 }
148
149 static int stac9460_dac_vol_get(struct snd_kcontrol *kcontrol,
150                                 struct snd_ctl_elem_value *ucontrol)
151 {
152         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
153         int idx, id;
154         unsigned char vol;
155
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;
162         }
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;
169 }
170
171 static int stac9460_dac_vol_put(struct snd_kcontrol *kcontrol,
172                                 struct snd_ctl_elem_value *ucontrol)
173 {
174         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
175         int idx, id;
176         unsigned char tmp, ovol, nvol;
177         int change;
178
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));
188                 }
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));
206                 }
207         }
208         return change;
209 }
210
211 /*
212  * ADC mute control
213  */
214 #define stac9460_adc_mute_info          snd_ctl_boolean_stereo_info
215
216 static int stac9460_adc_mute_get(struct snd_kcontrol *kcontrol,
217                                 struct snd_ctl_elem_value *ucontrol)
218 {
219         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
220         unsigned char val;
221         int i, id;
222         
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;
228                 }
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;
233                 }
234         }
235         return 0;
236 }
237
238 static int stac9460_adc_mute_put(struct snd_kcontrol *kcontrol,
239                                 struct snd_ctl_elem_value *ucontrol)
240 {
241         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
242         unsigned char new, old;
243         int i, reg, id;
244         int change;
245         
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);
256                 }
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);
266                 }
267         }
268         return change;
269 }
270
271 /*
272  *ADC gain mixer control
273  */
274 static int stac9460_adc_vol_info(struct snd_kcontrol *kcontrol,
275                                 struct snd_ctl_elem_info *uinfo)
276 {
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;
282 }
283
284 static int stac9460_adc_vol_get(struct snd_kcontrol *kcontrol,
285                                 struct snd_ctl_elem_value *ucontrol)
286 {
287         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
288         int i, reg, id;
289         unsigned char vol;
290         
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;
297                 }
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;
303                 }
304         }
305         return 0;
306 }
307
308 static int stac9460_adc_vol_put(struct snd_kcontrol *kcontrol,
309                         struct snd_ctl_elem_value *ucontrol)
310 {
311         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
312         int i, reg, id;
313         unsigned char ovol, nvol;
314         int change;
315         
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));
326                 }
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));
336                 }
337         }
338         return change;
339 }
340
341 /*
342  * MIC / LINE switch fonction
343  */
344
345 #define stac9460_mic_sw_info            snd_ctl_boolean_mono_info
346
347 static int stac9460_mic_sw_get(struct snd_kcontrol *kcontrol,
348                         struct snd_ctl_elem_value *ucontrol)
349 {
350         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
351         unsigned char val;
352         int id;
353                 
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;
361 }
362
363 static int stac9460_mic_sw_put(struct snd_kcontrol *kcontrol,
364                         struct snd_ctl_elem_value *ucontrol)
365 {
366         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
367         unsigned char new, old;
368         int change, id;
369
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);
382         }
383         return change;
384 }
385
386 /*
387  * Control tabs
388  */
389 static struct snd_kcontrol_new stac9640_controls[] __devinitdata = {
390         {
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
397         },
398         {
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,
405         },
406         {
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,
413
414         },
415         {
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,
422         },
423         {
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,
430         },
431         {
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,
438         },
439         {
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,
446
447         }       
448 };
449
450
451
452 /*INIT*/
453 static int __devinit wtm_add_controls(struct snd_ice1712 *ice)
454 {
455         unsigned int i;
456         int err;
457
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;
463         }
464         return 0;
465 }
466
467 static int __devinit wtm_init(struct snd_ice1712 *ice)
468 {
469         static unsigned short stac_inits_prodigy[] = {
470                 STAC946X_RESET, 0,
471                 (unsigned short)-1
472         };
473         unsigned short *p;
474                 
475         /*WTM 192M*/
476         ice->num_total_dacs = 8;
477         ice->num_total_adcs = 4;
478         ice->force_rdma1 = 1;
479
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]);
485         }
486         return 0;
487 }
488
489
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 */
504 };
505
506
507 /*entry point*/
508 struct snd_ice1712_card_info snd_vt1724_wtm_cards[] __devinitdata = {
509         {
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,
517         },
518         {} /*terminator*/
519 };