Merge git://git.kernel.org/pub/scm/linux/kernel/git/czankel/xtensa-2.6
[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 <linux/io.h>
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>
34
35 #include "ice1712.h"
36 #include "envy24ht.h"
37 #include "wtm.h"
38 #include "stac946x.h"
39
40
41 /*
42  *      2*ADC 6*DAC no1 ringbuffer r/w on i2c bus
43  */
44 static inline void stac9460_put(struct snd_ice1712 *ice, int reg,
45                                                 unsigned char val)
46 {
47         snd_vt1724_write_i2c(ice, STAC9460_I2C_ADDR, reg, val);
48 }
49
50 static inline unsigned char stac9460_get(struct snd_ice1712 *ice, int reg)
51 {
52         return snd_vt1724_read_i2c(ice, STAC9460_I2C_ADDR, reg);
53 }
54
55 /*
56  *      2*ADC 2*DAC no2 ringbuffer r/w on i2c bus
57  */
58 static inline void stac9460_2_put(struct snd_ice1712 *ice, int reg,
59                                                 unsigned char val)
60 {
61         snd_vt1724_write_i2c(ice, STAC9460_2_I2C_ADDR, reg, val);
62 }
63
64 static inline unsigned char stac9460_2_get(struct snd_ice1712 *ice, int reg)
65 {
66         return snd_vt1724_read_i2c(ice, STAC9460_2_I2C_ADDR, reg);
67 }
68
69
70 /*
71  *      DAC mute control
72  */
73 #define stac9460_dac_mute_info          snd_ctl_boolean_mono_info
74
75 static int stac9460_dac_mute_get(struct snd_kcontrol *kcontrol,
76                                 struct snd_ctl_elem_value *ucontrol)
77 {
78         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
79         unsigned char val;
80         int idx, id;
81
82         if (kcontrol->private_value) {
83                 idx = STAC946X_MASTER_VOLUME;
84                 id = 0;
85         } else {
86                 id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
87                 idx = id + STAC946X_LF_VOLUME;
88         }
89         if (id < 6)
90                 val = stac9460_get(ice, idx);
91         else
92                 val = stac9460_2_get(ice, idx - 6);
93         ucontrol->value.integer.value[0] = (~val >> 7) & 0x1;
94         return 0;
95 }
96
97 static int stac9460_dac_mute_put(struct snd_kcontrol *kcontrol,
98                                 struct snd_ctl_elem_value *ucontrol)
99 {
100         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
101         unsigned char new, old;
102         int id, idx;
103         int change;
104
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) |
109                                                         (old & ~0x80);
110                 change = (new != old);
111                 if (change) {
112                         stac9460_put(ice, idx, new);
113                         stac9460_2_put(ice, idx, new);
114                 }
115         } else {
116                 id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
117                 idx = id + STAC946X_LF_VOLUME;
118                 if (id < 6)
119                         old = stac9460_get(ice, idx);
120                 else
121                         old = stac9460_2_get(ice, idx - 6);
122                 new = (~ucontrol->value.integer.value[0] << 7 & 0x80) |
123                                                         (old & ~0x80);
124                 change = (new != old);
125                 if (change) {
126                         if (id < 6)
127                                 stac9460_put(ice, idx, new);
128                         else
129                                 stac9460_2_put(ice, idx - 6, new);
130                 }
131         }
132         return change;
133 }
134
135 /*
136  *      DAC volume attenuation mixer control
137  */
138 static int stac9460_dac_vol_info(struct snd_kcontrol *kcontrol,
139                                 struct snd_ctl_elem_info *uinfo)
140 {
141         uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
142         uinfo->count = 1;
143         uinfo->value.integer.min = 0;                   /* mute */
144         uinfo->value.integer.max = 0x7f;                /* 0dB */
145         return 0;
146 }
147
148 static int stac9460_dac_vol_get(struct snd_kcontrol *kcontrol,
149                                 struct snd_ctl_elem_value *ucontrol)
150 {
151         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
152         int idx, id;
153         unsigned char vol;
154
155         if (kcontrol->private_value) {
156                 idx = STAC946X_MASTER_VOLUME;
157                 id = 0;
158         } else {
159                 id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
160                 idx = id + STAC946X_LF_VOLUME;
161         }
162         if (id < 6)
163                 vol = stac9460_get(ice, idx) & 0x7f;
164         else
165                 vol = stac9460_2_get(ice, idx - 6) & 0x7f;
166         ucontrol->value.integer.value[0] = 0x7f - vol;
167         return 0;
168 }
169
170 static int stac9460_dac_vol_put(struct snd_kcontrol *kcontrol,
171                                 struct snd_ctl_elem_value *ucontrol)
172 {
173         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
174         int idx, id;
175         unsigned char tmp, ovol, nvol;
176         int change;
177
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);
184                 if (change) {
185                         stac9460_put(ice, idx, (0x7f - nvol) | (tmp & 0x80));
186                         stac9460_2_put(ice, idx, (0x7f - nvol) | (tmp & 0x80));
187                 }
188         } else {
189                 id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
190                 idx = id + STAC946X_LF_VOLUME;
191                 nvol = ucontrol->value.integer.value[0] & 0x7f;
192                 if (id < 6)
193                         tmp = stac9460_get(ice, idx);
194                 else
195                         tmp = stac9460_2_get(ice, idx - 6);
196                 ovol = 0x7f - (tmp & 0x7f);
197                 change = (ovol != nvol);
198                 if (change) {
199                         if (id < 6)
200                                 stac9460_put(ice, idx, (0x7f - nvol) |
201                                                         (tmp & 0x80));
202                         else
203                                 stac9460_2_put(ice, idx-6, (0x7f - nvol) |
204                                                         (tmp & 0x80));
205                 }
206         }
207         return change;
208 }
209
210 /*
211  * ADC mute control
212  */
213 #define stac9460_adc_mute_info          snd_ctl_boolean_stereo_info
214
215 static int stac9460_adc_mute_get(struct snd_kcontrol *kcontrol,
216                                 struct snd_ctl_elem_value *ucontrol)
217 {
218         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
219         unsigned char val;
220         int i, id;
221
222         id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
223         if (id == 0) {
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;
227                 }
228         } else {
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;
232                 }
233         }
234         return 0;
235 }
236
237 static int stac9460_adc_mute_put(struct snd_kcontrol *kcontrol,
238                                 struct snd_ctl_elem_value *ucontrol)
239 {
240         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
241         unsigned char new, old;
242         int i, reg, id;
243         int change;
244
245         id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
246         if (id == 0) {
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) |
251                                                                 (old&~0x80);
252                         change = (new != old);
253                         if (change)
254                                 stac9460_put(ice, reg, new);
255                 }
256         } else {
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) |
261                                                                 (old&~0x80);
262                         change = (new != old);
263                         if (change)
264                                 stac9460_2_put(ice, reg, new);
265                 }
266         }
267         return change;
268 }
269
270 /*
271  *ADC gain mixer control
272  */
273 static int stac9460_adc_vol_info(struct snd_kcontrol *kcontrol,
274                                 struct snd_ctl_elem_info *uinfo)
275 {
276         uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
277         uinfo->count = 2;
278         uinfo->value.integer.min = 0;           /* 0dB */
279         uinfo->value.integer.max = 0x0f;        /* 22.5dB */
280         return 0;
281 }
282
283 static int stac9460_adc_vol_get(struct snd_kcontrol *kcontrol,
284                                 struct snd_ctl_elem_value *ucontrol)
285 {
286         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
287         int i, reg, id;
288         unsigned char vol;
289
290         id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
291         if (id == 0) {
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;
296                 }
297         } else {
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;
302                 }
303         }
304         return 0;
305 }
306
307 static int stac9460_adc_vol_put(struct snd_kcontrol *kcontrol,
308                                 struct snd_ctl_elem_value *ucontrol)
309 {
310         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
311         int i, reg, id;
312         unsigned char ovol, nvol;
313         int change;
314
315         id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
316         if (id == 0) {
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);
322                         if (change)
323                                 stac9460_put(ice, reg, (0x0f - nvol) |
324                                                         (ovol & ~0x0f));
325                 }
326         } else {
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);
332                         if (change)
333                                 stac9460_2_put(ice, reg, (0x0f - nvol) |
334                                                         (ovol & ~0x0f));
335                 }
336         }
337         return change;
338 }
339
340 /*
341  * MIC / LINE switch fonction
342  */
343
344 #define stac9460_mic_sw_info            snd_ctl_boolean_mono_info
345
346 static int stac9460_mic_sw_get(struct snd_kcontrol *kcontrol,
347                                 struct snd_ctl_elem_value *ucontrol)
348 {
349         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
350         unsigned char val;
351         int id;
352
353         id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
354         if (id == 0)
355                 val = stac9460_get(ice, STAC946X_GENERAL_PURPOSE);
356         else
357                 val = stac9460_2_get(ice, STAC946X_GENERAL_PURPOSE);
358         ucontrol->value.integer.value[0] = ~val>>7 & 0x1;
359         return 0;
360 }
361
362 static int stac9460_mic_sw_put(struct snd_kcontrol *kcontrol,
363                                 struct snd_ctl_elem_value *ucontrol)
364 {
365         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
366         unsigned char new, old;
367         int change, id;
368
369         id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
370         if (id == 0)
371                 old = stac9460_get(ice, STAC946X_GENERAL_PURPOSE);
372         else
373                 old = stac9460_2_get(ice, STAC946X_GENERAL_PURPOSE);
374         new = (~ucontrol->value.integer.value[0] << 7 & 0x80) | (old & ~0x80);
375         change = (new != old);
376         if (change) {
377                 if (id == 0)
378                         stac9460_put(ice, STAC946X_GENERAL_PURPOSE, new);
379                 else
380                         stac9460_2_put(ice, STAC946X_GENERAL_PURPOSE, new);
381         }
382         return change;
383 }
384
385 /*
386  * Control tabs
387  */
388 static struct snd_kcontrol_new stac9640_controls[] __devinitdata = {
389         {
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,
395                 .private_value = 1
396         },
397         {
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,
403                 .private_value = 1,
404         },
405         {
406                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
407                 .name = "MIC/Line switch",
408                 .count = 2,
409                 .info = stac9460_mic_sw_info,
410                 .get = stac9460_mic_sw_get,
411                 .put = stac9460_mic_sw_put,
412
413         },
414         {
415                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
416                 .name = "DAC Switch",
417                 .count = 8,
418                 .info = stac9460_dac_mute_info,
419                 .get = stac9460_dac_mute_get,
420                 .put = stac9460_dac_mute_put,
421         },
422         {
423                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
424                 .name = "DAC Volume",
425                 .count = 8,
426                 .info = stac9460_dac_vol_info,
427                 .get = stac9460_dac_vol_get,
428                 .put = stac9460_dac_vol_put,
429         },
430         {
431                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
432                 .name = "ADC Switch",
433                 .count = 2,
434                 .info = stac9460_adc_mute_info,
435                 .get = stac9460_adc_mute_get,
436                 .put = stac9460_adc_mute_put,
437         },
438         {
439                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
440                 .name = "ADC Volume",
441                 .count = 2,
442                 .info = stac9460_adc_vol_info,
443                 .get = stac9460_adc_vol_get,
444                 .put = stac9460_adc_vol_put,
445
446         }
447 };
448
449
450
451 /*INIT*/
452 static int __devinit wtm_add_controls(struct snd_ice1712 *ice)
453 {
454         unsigned int i;
455         int err;
456
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));
460                 if (err < 0)
461                         return err;
462         }
463         return 0;
464 }
465
466 static int __devinit wtm_init(struct snd_ice1712 *ice)
467 {
468         static unsigned short stac_inits_prodigy[] = {
469                 STAC946X_RESET, 0,
470                 (unsigned short)-1
471         };
472         unsigned short *p;
473
474         /*WTM 192M*/
475         ice->num_total_dacs = 8;
476         ice->num_total_adcs = 4;
477         ice->force_rdma1 = 1;
478
479         /*initialize codec*/
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]);
484         }
485         return 0;
486 }
487
488
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*/,
494         0x9f,   /* GPIO_DIR */
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 */
503 };
504
505
506 /*entry point*/
507 struct snd_ice1712_card_info snd_vt1724_wtm_cards[] __devinitdata = {
508         {
509                 .subvendor = VT1724_SUBDEVICE_WTM,
510                 .name = "ESI Waveterminal 192M",
511                 .model = "WT192M",
512                 .chip_init = wtm_init,
513                 .build_controls = wtm_add_controls,
514                 .eeprom_size = sizeof(wtm_eeprom),
515                 .eeprom_data = wtm_eeprom,
516         },
517         {} /*terminator*/
518 };