ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-2.6.6.tar.bz2
[linux-2.6.git] / sound / pci / ice1712 / aureon.c
1 /*
2  *   ALSA driver for ICEnsemble VT1724 (Envy24HT)
3  *
4  *   Lowlevel functions for Terratec Aureon cards
5  *
6  *      Copyright (c) 2003 Takashi Iwai <tiwai@suse.de>
7  *
8  *   This program is free software; you can redistribute it and/or modify
9  *   it under the terms of the GNU General Public License as published by
10  *   the Free Software Foundation; either version 2 of the License, or
11  *   (at your option) any later version.
12  *
13  *   This program is distributed in the hope that it will be useful,
14  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *   GNU General Public License for more details.
17  *
18  *   You should have received a copy of the GNU General Public License
19  *   along with this program; if not, write to the Free Software
20  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
21  *
22  *
23  * NOTES:
24  *
25  * - we reuse the akm4xxx_t record for storing the wm8770 codec data.
26  *   both wm and akm codecs are pretty similar, so we can integrate
27  *   both controls in the future, once if wm codecs are reused in
28  *   many boards.
29  *
30  * - writing over SPI is implemented but reading is not yet.
31  *   the SPDIF-in channel status, etc. can be read from CS chip.
32  *
33  * - DAC digital volumes are not implemented in the mixer.
34  *   if they show better response than DAC analog volumes, we can use them
35  *   instead.
36  *
37  * - Aureon boards are equipped with AC97 codec, too.  it's used to do
38  *   the analog mixing but not easily controllable (it's not connected
39  *   directly from envy24ht chip).  so let's leave it as it is.
40  *
41  */      
42
43 #include <sound/driver.h>
44 #include <asm/io.h>
45 #include <linux/delay.h>
46 #include <linux/interrupt.h>
47 #include <linux/init.h>
48 #include <linux/slab.h>
49 #include <sound/core.h>
50
51 #include "ice1712.h"
52 #include "envy24ht.h"
53 #include "aureon.h"
54
55 /* WM8770 registers */
56 #define WM_DAC_ATTEN            0x00    /* DAC1-8 analog attenuation */
57 #define WM_DAC_MASTER_ATTEN     0x08    /* DAC master analog attenuation */
58 #define WM_DAC_DIG_ATTEN        0x09    /* DAC1-8 digital attenuation */
59 #define WM_DAC_DIG_MATER_ATTEN  0x11    /* DAC master digital attenuation */
60 #define WM_PHASE_SWAP           0x12    /* DAC phase */
61 #define WM_DAC_CTRL1            0x13    /* DAC control bits */
62 #define WM_MUTE                 0x14    /* mute controls */
63 #define WM_DAC_CTRL2            0x15    /* de-emphasis and zefo-flag */
64 #define WM_INT_CTRL             0x16    /* interface control */
65 #define WM_MASTER               0x17    /* master clock and mode */
66 #define WM_POWERDOWN            0x18    /* power-down controls */
67 #define WM_ADC_GAIN             0x19    /* ADC gain L(19)/R(1a) */
68 #define WM_ADC_MUX              0x1b    /* input MUX */
69 #define WM_OUT_MUX1             0x1c    /* output MUX */
70 #define WM_OUT_MUX2             0x1e    /* output MUX */
71 #define WM_RESET                0x1f    /* software reset */
72
73
74 /*
75  * write data in the SPI mode
76  */
77 static void aureon_spi_write(ice1712_t *ice, unsigned int cs, unsigned int data, int bits)
78 {
79         unsigned int tmp;
80         int i;
81
82         tmp = snd_ice1712_gpio_read(ice);
83
84         snd_ice1712_gpio_set_mask(ice, ~(AUREON_WM_RW|AUREON_WM_DATA|AUREON_WM_CLK|
85                                          AUREON_WM_CS|AUREON_CS8415_CS));
86         tmp |= AUREON_WM_RW;
87         tmp &= ~cs;
88         snd_ice1712_gpio_write(ice, tmp);
89         udelay(1);
90
91         for (i = bits - 1; i >= 0; i--) {
92                 tmp &= ~AUREON_WM_CLK;
93                 snd_ice1712_gpio_write(ice, tmp);
94                 udelay(1);
95                 if (data & (1 << i))
96                         tmp |= AUREON_WM_DATA;
97                 else
98                         tmp &= ~AUREON_WM_DATA;
99                 snd_ice1712_gpio_write(ice, tmp);
100                 udelay(1);
101                 tmp |= AUREON_WM_CLK;
102                 snd_ice1712_gpio_write(ice, tmp);
103                 udelay(1);
104         }
105
106         tmp &= ~AUREON_WM_CLK;
107         tmp |= cs;
108         snd_ice1712_gpio_write(ice, tmp);
109         udelay(1);
110         tmp |= AUREON_WM_CLK;
111         snd_ice1712_gpio_write(ice, tmp);
112         udelay(1);
113 }
114      
115
116 /*
117  * get the current register value of WM codec
118  */
119 static unsigned short wm_get(ice1712_t *ice, int reg)
120 {
121         reg <<= 1;
122         return ((unsigned short)ice->akm[0].images[reg] << 8) |
123                 ice->akm[0].images[reg + 1];
124 }
125
126 /*
127  * set the register value of WM codec and remember it
128  */
129 static void wm_put(ice1712_t *ice, int reg, unsigned short val)
130 {
131         aureon_spi_write(ice, AUREON_WM_CS, (reg << 9) | (val & 0x1ff), 16);
132         reg <<= 1;
133         ice->akm[0].images[reg] = val >> 8;
134         ice->akm[0].images[reg + 1] = val;
135 }
136
137 /*
138  * DAC volume attenuation mixer control
139  */
140 static int wm_dac_vol_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *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 = 101;         /* 0dB */
146         return 0;
147 }
148
149 static int wm_dac_vol_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
150 {
151         ice1712_t *ice = snd_kcontrol_chip(kcontrol);
152         int idx;
153         unsigned short vol;
154
155         down(&ice->gpio_mutex);
156         if (kcontrol->private_value)
157                 idx = WM_DAC_MASTER_ATTEN;
158         else
159                 idx  = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id) + WM_DAC_ATTEN;
160         vol = wm_get(ice, idx) & 0x7f;
161         if (vol <= 0x1a)
162                 ucontrol->value.integer.value[0] = 0;
163         else
164                 ucontrol->value.integer.value[0] = vol - 0x1a;
165         up(&ice->gpio_mutex);
166         return 0;
167 }
168
169 static int wm_dac_vol_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
170 {
171         ice1712_t *ice = snd_kcontrol_chip(kcontrol);
172         int idx;
173         unsigned short ovol, nvol;
174         int change;
175
176         snd_ice1712_save_gpio_status(ice);
177         if (kcontrol->private_value)
178                 idx = WM_DAC_MASTER_ATTEN;
179         else
180                 idx  = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id) + WM_DAC_ATTEN;
181         nvol = ucontrol->value.integer.value[0] + 0x1a;
182         ovol = wm_get(ice, idx) & 0x7f;
183         change = (ovol != nvol);
184         if (change) {
185                 if (nvol <= 0x1a && ovol <= 0x1a)
186                         change = 0;
187                 else
188                         wm_put(ice, idx, nvol | 0x180); /* update on zero detect */
189         }
190         snd_ice1712_restore_gpio_status(ice);
191         return change;
192 }
193
194 /*
195  * ADC gain mixer control
196  */
197 static int wm_adc_vol_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
198 {
199         uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
200         uinfo->count = 1;
201         uinfo->value.integer.min = 0;           /* -12dB */
202         uinfo->value.integer.max = 0x1f;        /* 19dB */
203         return 0;
204 }
205
206 static int wm_adc_vol_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
207 {
208         ice1712_t *ice = snd_kcontrol_chip(kcontrol);
209         int idx;
210         unsigned short vol;
211
212         down(&ice->gpio_mutex);
213         idx  = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id) + WM_ADC_GAIN;
214         vol = wm_get(ice, idx) & 0x1f;
215         ucontrol->value.integer.value[0] = vol;
216         up(&ice->gpio_mutex);
217         return 0;
218 }
219
220 static int wm_adc_vol_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
221 {
222         ice1712_t *ice = snd_kcontrol_chip(kcontrol);
223         int idx;
224         unsigned short ovol, nvol;
225         int change;
226
227         snd_ice1712_save_gpio_status(ice);
228         idx  = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id) + WM_ADC_GAIN;
229         nvol = ucontrol->value.integer.value[0];
230         ovol = wm_get(ice, idx) & 0x1f;
231         change = (ovol != nvol);
232         if (change)
233                 wm_put(ice, idx, nvol);
234         snd_ice1712_restore_gpio_status(ice);
235         return change;
236 }
237
238 /*
239  * ADC input mux mixer control
240  */
241 static int wm_adc_mux_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
242 {
243         static char *texts[] = {
244                 "CD Left",
245                 "CD Right",
246                 "Aux Left",
247                 "Aux Right",
248                 "Line Left",
249                 "Line Right",
250                 "Mic Left",
251                 "Mic Right",
252         };
253         uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
254         uinfo->count = 2;
255         uinfo->value.enumerated.items = 8;
256         if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
257                 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
258         strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
259         return 0;
260 }
261
262 static int wm_adc_mux_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *ucontrol)
263 {
264         ice1712_t *ice = snd_kcontrol_chip(kcontrol);
265         unsigned short val;
266
267         down(&ice->gpio_mutex);
268         val = wm_get(ice, WM_ADC_MUX);
269         ucontrol->value.integer.value[0] = val & 7;
270         ucontrol->value.integer.value[1] = (val >> 4) & 7;
271         up(&ice->gpio_mutex);
272         return 0;
273 }
274
275 static int wm_adc_mux_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *ucontrol)
276 {
277         ice1712_t *ice = snd_kcontrol_chip(kcontrol);
278         unsigned short oval, nval;
279         int change;
280
281         snd_ice1712_save_gpio_status(ice);
282         oval = wm_get(ice, WM_ADC_MUX);
283         nval = oval & ~0x77;
284         nval |= ucontrol->value.integer.value[0] & 7;
285         nval |= (ucontrol->value.integer.value[1] & 7) << 4;
286         change = (oval != nval);
287         if (change)
288                 wm_put(ice, WM_ADC_MUX, nval);
289         snd_ice1712_restore_gpio_status(ice);
290         return 0;
291 }
292
293 /*
294  * mixers
295  */
296
297 static snd_kcontrol_new_t aureon51_dac_control __devinitdata = {
298         .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
299         .name = "DAC Volume",
300         .count = 6,
301         .info = wm_dac_vol_info,
302         .get = wm_dac_vol_get,
303         .put = wm_dac_vol_put,
304 };
305
306 static snd_kcontrol_new_t aureon71_dac_control __devinitdata = {
307         .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
308         .name = "DAC Volume",
309         .count = 8,
310         .info = wm_dac_vol_info,
311         .get = wm_dac_vol_get,
312         .put = wm_dac_vol_put,
313 };
314
315 static snd_kcontrol_new_t wm_controls[] __devinitdata = {
316         {
317                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
318                 .name = "Master Playback Volume",
319                 .info = wm_dac_vol_info,
320                 .get = wm_dac_vol_get,
321                 .put = wm_dac_vol_put,
322                 .private_value = 1,
323         },
324         {
325                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
326                 .name = "ADC Volume",
327                 .count = 2,
328                 .info = wm_adc_vol_info,
329                 .get = wm_adc_vol_get,
330                 .put = wm_adc_vol_put,
331         },
332         {
333                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
334                 .name = "Capture Route",
335                 .info = wm_adc_mux_info,
336                 .get = wm_adc_mux_get,
337                 .put = wm_adc_mux_put,
338         },
339 };
340
341
342 static int __devinit aureon_add_controls(ice1712_t *ice)
343 {
344         unsigned int i;
345         int err;
346
347         if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON51_SKY)
348                 err = snd_ctl_add(ice->card, snd_ctl_new1(&aureon51_dac_control, ice));
349         else
350                 err = snd_ctl_add(ice->card, snd_ctl_new1(&aureon71_dac_control, ice));
351         if (err < 0)
352                 return err;
353
354         for (i = 0; i < ARRAY_SIZE(wm_controls); i++) {
355                 err = snd_ctl_add(ice->card, snd_ctl_new1(&wm_controls[i], ice));
356                 if (err < 0)
357                         return err;
358         }
359         return 0;
360 }
361
362
363 /*
364  * initialize the chip
365  */
366 static int __devinit aureon_init(ice1712_t *ice)
367 {
368         static unsigned short wm_inits[] = {
369                 /* These come first to reduce init pop noise */
370                 0x1b, 0x000,            /* ADC Mux */
371                 0x1c, 0x009,            /* Out Mux1 */
372                 0x1d, 0x009,            /* Out Mux2 */
373
374                 0x18, 0x000,            /* All power-up */
375
376                 0x16, 0x122,            /* I2S, normal polarity, 24bit */
377                 0x17, 0x022,            /* 256fs, slave mode */
378                 0x00, 0,                /* DAC1 analog mute */
379                 0x01, 0,                /* DAC2 analog mute */
380                 0x02, 0,                /* DAC3 analog mute */
381                 0x03, 0,                /* DAC4 analog mute */
382                 0x04, 0,                /* DAC5 analog mute */
383                 0x05, 0,                /* DAC6 analog mute */
384                 0x06, 0,                /* DAC7 analog mute */
385                 0x07, 0,                /* DAC8 analog mute */
386                 0x08, 0x100,            /* master analog mute */
387                 0x09, 0xff,             /* DAC1 digital full */
388                 0x0a, 0xff,             /* DAC2 digital full */
389                 0x0b, 0xff,             /* DAC3 digital full */
390                 0x0c, 0xff,             /* DAC4 digital full */
391                 0x0d, 0xff,             /* DAC5 digital full */
392                 0x0e, 0xff,             /* DAC6 digital full */
393                 0x0f, 0xff,             /* DAC7 digital full */
394                 0x10, 0xff,             /* DAC8 digital full */
395                 0x11, 0x1ff,            /* master digital full */
396                 0x12, 0x000,            /* phase normal */
397                 0x13, 0x090,            /* unmute DAC L/R */
398                 0x14, 0x000,            /* all unmute */
399                 0x15, 0x000,            /* no deemphasis, no ZFLG */
400                 0x19, 0x000,            /* -12dB ADC/L */
401                 0x1a, 0x000,            /* -12dB ADC/R */
402         };
403         static unsigned short cs_inits[] = {
404                 0x0441, /* RUN */
405                 0x0100, /* no mute */
406                 0x0200, /* */
407                 0x0600, /* slave, 24bit */
408         };
409         unsigned int tmp;
410         unsigned int i;
411
412         if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON51_SKY) {
413                 ice->num_total_dacs = 6;
414                 ice->num_total_adcs = 6;
415         } else {
416                 ice->num_total_dacs = 8;
417                 ice->num_total_adcs = 8;
418         }
419
420         /* to remeber the register values */
421         ice->akm = snd_kcalloc(sizeof(akm4xxx_t), GFP_KERNEL);
422         if (! ice->akm)
423                 return -ENOMEM;
424         ice->akm_codecs = 1;
425
426         snd_ice1712_gpio_set_dir(ice, 0xbfffff); /* fix this for the time being */
427
428         /* reset the wm codec as the SPI mode */
429         snd_ice1712_save_gpio_status(ice);
430         snd_ice1712_gpio_set_mask(ice, ~(AUREON_WM_RESET|AUREON_WM_CS|AUREON_CS8415_CS));
431         tmp = snd_ice1712_gpio_read(ice);
432         tmp &= ~AUREON_WM_RESET;
433         snd_ice1712_gpio_write(ice, tmp);
434         udelay(1);
435         tmp |= AUREON_WM_CS | AUREON_CS8415_CS;
436         snd_ice1712_gpio_write(ice, tmp);
437         udelay(1);
438         tmp |= AUREON_WM_RESET;
439         snd_ice1712_gpio_write(ice, tmp);
440         udelay(1);
441
442         /* initialize WM8770 codec */
443         for (i = 0; i < ARRAY_SIZE(wm_inits); i += 2)
444                 wm_put(ice, wm_inits[i], wm_inits[i+1]);
445
446         /* initialize CS8415A codec */
447         for (i = 0; i < ARRAY_SIZE(cs_inits); i++)
448                 aureon_spi_write(ice, AUREON_CS8415_CS,
449                                  cs_inits[i] | 0x200000, 24);
450
451         snd_ice1712_restore_gpio_status(ice);
452
453         return 0;
454 }
455
456
457 /*
458  * Aureon boards don't provide the EEPROM data except for the vendor IDs.
459  * hence the driver needs to sets up it properly.
460  */
461
462 static unsigned char aureon51_eeprom[] __devinitdata = {
463         0x12,   /* SYSCONF: clock 512, mpu401, spdif-in/ADC, 3DACs */
464         0x80,   /* ACLINK: I2S */
465         0xf8,   /* I2S: vol, 96k, 24bit, 192k */
466         0xc3,   /* SPDIF: out-en, out-int, spdif-in */
467         0xff,   /* GPIO_DIR */
468         0xff,   /* GPIO_DIR1 */
469         0xbf,   /* GPIO_DIR2 */
470         0xff,   /* GPIO_MASK */
471         0xff,   /* GPIO_MASK1 */
472         0xff,   /* GPIO_MASK2 */
473         0x00,   /* GPIO_STATE */
474         0x00,   /* GPIO_STATE1 */
475         0x00,   /* GPIO_STATE2 */
476 };
477
478 static unsigned char aureon71_eeprom[] __devinitdata = {
479         0x13,   /* SYSCONF: clock 512, mpu401, spdif-in/ADC, 4DACs */
480         0x80,   /* ACLINK: I2S */
481         0xf8,   /* I2S: vol, 96k, 24bit, 192k */
482         0xc3,   /* SPDIF: out-en, out-int, spdif-in */
483         0xff,   /* GPIO_DIR */
484         0xff,   /* GPIO_DIR1 */
485         0xbf,   /* GPIO_DIR2 */
486         0x00,   /* GPIO_MASK */
487         0x00,   /* GPIO_MASK1 */
488         0x00,   /* GPIO_MASK2 */
489         0x00,   /* GPIO_STATE */
490         0x00,   /* GPIO_STATE1 */
491         0x00,   /* GPIO_STATE2 */
492 };
493
494 /* entry point */
495 struct snd_ice1712_card_info snd_vt1724_aureon_cards[] __devinitdata = {
496         {
497                 .subvendor = VT1724_SUBDEVICE_AUREON51_SKY,
498                 .name = "Terratec Aureon 5.1-Sky",
499                 .chip_init = aureon_init,
500                 .build_controls = aureon_add_controls,
501                 .eeprom_size = sizeof(aureon51_eeprom),
502                 .eeprom_data = aureon51_eeprom,
503         },
504         {
505                 .subvendor = VT1724_SUBDEVICE_AUREON71_SPACE,
506                 .name = "Terratec Aureon 7.1-Space",
507                 .chip_init = aureon_init,
508                 .build_controls = aureon_add_controls,
509                 .eeprom_size = sizeof(aureon71_eeprom),
510                 .eeprom_data = aureon71_eeprom,
511         },
512         { } /* terminator */
513 };