2 * ALSA driver for ICEnsemble VT1724 (Envy24HT)
4 * Lowlevel functions for Terratec Aureon cards
6 * Copyright (c) 2003 Takashi Iwai <tiwai@suse.de>
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.
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.
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
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
30 * - writing over SPI is implemented but reading is not yet.
31 * the SPDIF-in channel status, etc. can be read from CS chip.
33 * - DAC digital volumes are not implemented in the mixer.
34 * if they show better response than DAC analog volumes, we can use them
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.
43 #include <sound/driver.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>
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 */
75 * write data in the SPI mode
77 static void aureon_spi_write(ice1712_t *ice, unsigned int cs, unsigned int data, int bits)
82 tmp = snd_ice1712_gpio_read(ice);
84 snd_ice1712_gpio_set_mask(ice, ~(AUREON_WM_RW|AUREON_WM_DATA|AUREON_WM_CLK|
85 AUREON_WM_CS|AUREON_CS8415_CS));
88 snd_ice1712_gpio_write(ice, tmp);
91 for (i = bits - 1; i >= 0; i--) {
92 tmp &= ~AUREON_WM_CLK;
93 snd_ice1712_gpio_write(ice, tmp);
96 tmp |= AUREON_WM_DATA;
98 tmp &= ~AUREON_WM_DATA;
99 snd_ice1712_gpio_write(ice, tmp);
101 tmp |= AUREON_WM_CLK;
102 snd_ice1712_gpio_write(ice, tmp);
106 tmp &= ~AUREON_WM_CLK;
108 snd_ice1712_gpio_write(ice, tmp);
110 tmp |= AUREON_WM_CLK;
111 snd_ice1712_gpio_write(ice, tmp);
117 * get the current register value of WM codec
119 static unsigned short wm_get(ice1712_t *ice, int reg)
122 return ((unsigned short)ice->akm[0].images[reg] << 8) |
123 ice->akm[0].images[reg + 1];
127 * set the register value of WM codec and remember it
129 static void wm_put(ice1712_t *ice, int reg, unsigned short val)
131 aureon_spi_write(ice, AUREON_WM_CS, (reg << 9) | (val & 0x1ff), 16);
133 ice->akm[0].images[reg] = val >> 8;
134 ice->akm[0].images[reg + 1] = val;
138 * DAC volume attenuation mixer control
140 static int wm_dac_vol_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
142 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
144 uinfo->value.integer.min = 0; /* mute */
145 uinfo->value.integer.max = 101; /* 0dB */
149 static int wm_dac_vol_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
151 ice1712_t *ice = snd_kcontrol_chip(kcontrol);
155 down(&ice->gpio_mutex);
156 if (kcontrol->private_value)
157 idx = WM_DAC_MASTER_ATTEN;
159 idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id) + WM_DAC_ATTEN;
160 vol = wm_get(ice, idx) & 0x7f;
162 ucontrol->value.integer.value[0] = 0;
164 ucontrol->value.integer.value[0] = vol - 0x1a;
165 up(&ice->gpio_mutex);
169 static int wm_dac_vol_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
171 ice1712_t *ice = snd_kcontrol_chip(kcontrol);
173 unsigned short ovol, nvol;
176 snd_ice1712_save_gpio_status(ice);
177 if (kcontrol->private_value)
178 idx = WM_DAC_MASTER_ATTEN;
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);
185 if (nvol <= 0x1a && ovol <= 0x1a)
188 wm_put(ice, idx, nvol | 0x180); /* update on zero detect */
190 snd_ice1712_restore_gpio_status(ice);
195 * ADC gain mixer control
197 static int wm_adc_vol_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
199 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
201 uinfo->value.integer.min = 0; /* -12dB */
202 uinfo->value.integer.max = 0x1f; /* 19dB */
206 static int wm_adc_vol_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
208 ice1712_t *ice = snd_kcontrol_chip(kcontrol);
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);
220 static int wm_adc_vol_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
222 ice1712_t *ice = snd_kcontrol_chip(kcontrol);
224 unsigned short ovol, nvol;
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);
233 wm_put(ice, idx, nvol);
234 snd_ice1712_restore_gpio_status(ice);
239 * ADC input mux mixer control
241 static int wm_adc_mux_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
243 static char *texts[] = {
253 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
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]);
262 static int wm_adc_mux_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *ucontrol)
264 ice1712_t *ice = snd_kcontrol_chip(kcontrol);
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);
275 static int wm_adc_mux_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *ucontrol)
277 ice1712_t *ice = snd_kcontrol_chip(kcontrol);
278 unsigned short oval, nval;
281 snd_ice1712_save_gpio_status(ice);
282 oval = wm_get(ice, WM_ADC_MUX);
284 nval |= ucontrol->value.integer.value[0] & 7;
285 nval |= (ucontrol->value.integer.value[1] & 7) << 4;
286 change = (oval != nval);
288 wm_put(ice, WM_ADC_MUX, nval);
289 snd_ice1712_restore_gpio_status(ice);
297 static snd_kcontrol_new_t aureon51_dac_control __devinitdata = {
298 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
299 .name = "DAC Volume",
301 .info = wm_dac_vol_info,
302 .get = wm_dac_vol_get,
303 .put = wm_dac_vol_put,
306 static snd_kcontrol_new_t aureon71_dac_control __devinitdata = {
307 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
308 .name = "DAC Volume",
310 .info = wm_dac_vol_info,
311 .get = wm_dac_vol_get,
312 .put = wm_dac_vol_put,
315 static snd_kcontrol_new_t wm_controls[] __devinitdata = {
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,
325 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
326 .name = "ADC Volume",
328 .info = wm_adc_vol_info,
329 .get = wm_adc_vol_get,
330 .put = wm_adc_vol_put,
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,
342 static int __devinit aureon_add_controls(ice1712_t *ice)
347 if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON51_SKY)
348 err = snd_ctl_add(ice->card, snd_ctl_new1(&aureon51_dac_control, ice));
350 err = snd_ctl_add(ice->card, snd_ctl_new1(&aureon71_dac_control, ice));
354 for (i = 0; i < ARRAY_SIZE(wm_controls); i++) {
355 err = snd_ctl_add(ice->card, snd_ctl_new1(&wm_controls[i], ice));
364 * initialize the chip
366 static int __devinit aureon_init(ice1712_t *ice)
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 */
374 0x18, 0x000, /* All power-up */
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 */
403 static unsigned short cs_inits[] = {
405 0x0100, /* no mute */
407 0x0600, /* slave, 24bit */
412 if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON51_SKY) {
413 ice->num_total_dacs = 6;
414 ice->num_total_adcs = 6;
416 ice->num_total_dacs = 8;
417 ice->num_total_adcs = 8;
420 /* to remeber the register values */
421 ice->akm = snd_kcalloc(sizeof(akm4xxx_t), GFP_KERNEL);
426 snd_ice1712_gpio_set_dir(ice, 0xbfffff); /* fix this for the time being */
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);
435 tmp |= AUREON_WM_CS | AUREON_CS8415_CS;
436 snd_ice1712_gpio_write(ice, tmp);
438 tmp |= AUREON_WM_RESET;
439 snd_ice1712_gpio_write(ice, tmp);
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]);
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);
451 snd_ice1712_restore_gpio_status(ice);
458 * Aureon boards don't provide the EEPROM data except for the vendor IDs.
459 * hence the driver needs to sets up it properly.
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 */
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 */
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 */
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 */
495 struct snd_ice1712_card_info snd_vt1724_aureon_cards[] __devinitdata = {
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,
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,