0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035 #include <linux/delay.h>
0036 #include <linux/interrupt.h>
0037 #include <linux/init.h>
0038 #include <linux/slab.h>
0039 #include <linux/mutex.h>
0040
0041 #include <sound/core.h>
0042
0043 #include "ice1712.h"
0044 #include "envy24ht.h"
0045 #include "aureon.h"
0046 #include <sound/tlv.h>
0047
0048
0049 struct aureon_spec {
0050 unsigned short stac9744[64];
0051 unsigned int cs8415_mux;
0052 unsigned short master[2];
0053 unsigned short vol[8];
0054 unsigned char pca9554_out;
0055 };
0056
0057
0058 #define WM_DAC_ATTEN 0x00
0059 #define WM_DAC_MASTER_ATTEN 0x08
0060 #define WM_DAC_DIG_ATTEN 0x09
0061 #define WM_DAC_DIG_MASTER_ATTEN 0x11
0062 #define WM_PHASE_SWAP 0x12
0063 #define WM_DAC_CTRL1 0x13
0064 #define WM_MUTE 0x14
0065 #define WM_DAC_CTRL2 0x15
0066 #define WM_INT_CTRL 0x16
0067 #define WM_MASTER 0x17
0068 #define WM_POWERDOWN 0x18
0069 #define WM_ADC_GAIN 0x19
0070 #define WM_ADC_MUX 0x1b
0071 #define WM_OUT_MUX1 0x1c
0072 #define WM_OUT_MUX2 0x1e
0073 #define WM_RESET 0x1f
0074
0075
0076 #define CS8415_CTRL1 0x01
0077 #define CS8415_CTRL2 0x02
0078 #define CS8415_QSUB 0x14
0079 #define CS8415_RATIO 0x1E
0080 #define CS8415_C_BUFFER 0x20
0081 #define CS8415_ID 0x7F
0082
0083
0084 #define PCA9554_DEV 0x40
0085 #define PCA9554_IN 0x00
0086 #define PCA9554_OUT 0x01
0087 #define PCA9554_INVERT 0x02
0088 #define PCA9554_DIR 0x03
0089
0090
0091
0092
0093
0094
0095
0096
0097 static void aureon_pca9554_write(struct snd_ice1712 *ice, unsigned char reg,
0098 unsigned char data)
0099 {
0100 unsigned int tmp;
0101 int i, j;
0102 unsigned char dev = PCA9554_DEV;
0103 unsigned char val = 0;
0104
0105 tmp = snd_ice1712_gpio_read(ice);
0106
0107 snd_ice1712_gpio_set_mask(ice, ~(AUREON_SPI_MOSI|AUREON_SPI_CLK|
0108 AUREON_WM_RW|AUREON_WM_CS|
0109 AUREON_CS8415_CS));
0110 tmp |= AUREON_WM_RW;
0111 tmp |= AUREON_CS8415_CS | AUREON_WM_CS;
0112
0113 tmp &= ~AUREON_SPI_MOSI;
0114 tmp &= ~AUREON_SPI_CLK;
0115 snd_ice1712_gpio_write(ice, tmp);
0116 udelay(50);
0117
0118
0119
0120
0121
0122 tmp |= AUREON_SPI_CLK;
0123 snd_ice1712_gpio_write(ice, tmp);
0124 udelay(50);
0125 tmp |= AUREON_SPI_MOSI;
0126 snd_ice1712_gpio_write(ice, tmp);
0127 udelay(100);
0128 tmp &= ~AUREON_SPI_MOSI;
0129 snd_ice1712_gpio_write(ice, tmp);
0130 udelay(50);
0131 tmp &= ~AUREON_SPI_CLK;
0132 snd_ice1712_gpio_write(ice, tmp);
0133 udelay(100);
0134
0135
0136
0137
0138 for (j = 0; j < 3; j++) {
0139 switch (j) {
0140 case 0:
0141 val = dev;
0142 break;
0143 case 1:
0144 val = reg;
0145 break;
0146 case 2:
0147 val = data;
0148 break;
0149 }
0150 for (i = 7; i >= 0; i--) {
0151 tmp &= ~AUREON_SPI_CLK;
0152 snd_ice1712_gpio_write(ice, tmp);
0153 udelay(40);
0154 if (val & (1 << i))
0155 tmp |= AUREON_SPI_MOSI;
0156 else
0157 tmp &= ~AUREON_SPI_MOSI;
0158 snd_ice1712_gpio_write(ice, tmp);
0159 udelay(40);
0160 tmp |= AUREON_SPI_CLK;
0161 snd_ice1712_gpio_write(ice, tmp);
0162 udelay(40);
0163 }
0164 tmp &= ~AUREON_SPI_CLK;
0165 snd_ice1712_gpio_write(ice, tmp);
0166 udelay(40);
0167 tmp |= AUREON_SPI_CLK;
0168 snd_ice1712_gpio_write(ice, tmp);
0169 udelay(40);
0170 tmp &= ~AUREON_SPI_CLK;
0171 snd_ice1712_gpio_write(ice, tmp);
0172 udelay(40);
0173 }
0174 tmp &= ~AUREON_SPI_CLK;
0175 snd_ice1712_gpio_write(ice, tmp);
0176 udelay(40);
0177 tmp &= ~AUREON_SPI_MOSI;
0178 snd_ice1712_gpio_write(ice, tmp);
0179 udelay(40);
0180 tmp |= AUREON_SPI_CLK;
0181 snd_ice1712_gpio_write(ice, tmp);
0182 udelay(50);
0183 tmp |= AUREON_SPI_MOSI;
0184 snd_ice1712_gpio_write(ice, tmp);
0185 udelay(100);
0186 }
0187
0188 static int aureon_universe_inmux_info(struct snd_kcontrol *kcontrol,
0189 struct snd_ctl_elem_info *uinfo)
0190 {
0191 static const char * const texts[3] =
0192 {"Internal Aux", "Wavetable", "Rear Line-In"};
0193
0194 return snd_ctl_enum_info(uinfo, 1, 3, texts);
0195 }
0196
0197 static int aureon_universe_inmux_get(struct snd_kcontrol *kcontrol,
0198 struct snd_ctl_elem_value *ucontrol)
0199 {
0200 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
0201 struct aureon_spec *spec = ice->spec;
0202 ucontrol->value.enumerated.item[0] = spec->pca9554_out;
0203 return 0;
0204 }
0205
0206 static int aureon_universe_inmux_put(struct snd_kcontrol *kcontrol,
0207 struct snd_ctl_elem_value *ucontrol)
0208 {
0209 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
0210 struct aureon_spec *spec = ice->spec;
0211 unsigned char oval, nval;
0212 int change;
0213
0214 nval = ucontrol->value.enumerated.item[0];
0215 if (nval >= 3)
0216 return -EINVAL;
0217 snd_ice1712_save_gpio_status(ice);
0218 oval = spec->pca9554_out;
0219 change = (oval != nval);
0220 if (change) {
0221 aureon_pca9554_write(ice, PCA9554_OUT, nval);
0222 spec->pca9554_out = nval;
0223 }
0224 snd_ice1712_restore_gpio_status(ice);
0225 return change;
0226 }
0227
0228
0229 static void aureon_ac97_write(struct snd_ice1712 *ice, unsigned short reg,
0230 unsigned short val)
0231 {
0232 struct aureon_spec *spec = ice->spec;
0233 unsigned int tmp;
0234
0235
0236 tmp = (snd_ice1712_gpio_read(ice) & ~0xFF) | (reg & 0x7F);
0237 snd_ice1712_gpio_write(ice, tmp);
0238 udelay(10);
0239 tmp |= AUREON_AC97_ADDR;
0240 snd_ice1712_gpio_write(ice, tmp);
0241 udelay(10);
0242 tmp &= ~AUREON_AC97_ADDR;
0243 snd_ice1712_gpio_write(ice, tmp);
0244 udelay(10);
0245
0246
0247 tmp &= ~AUREON_AC97_DATA_MASK;
0248 tmp |= val & AUREON_AC97_DATA_MASK;
0249 snd_ice1712_gpio_write(ice, tmp);
0250 udelay(10);
0251 tmp |= AUREON_AC97_DATA_LOW;
0252 snd_ice1712_gpio_write(ice, tmp);
0253 udelay(10);
0254 tmp &= ~AUREON_AC97_DATA_LOW;
0255 snd_ice1712_gpio_write(ice, tmp);
0256 udelay(10);
0257
0258
0259 tmp &= ~AUREON_AC97_DATA_MASK;
0260 tmp |= (val >> 8) & AUREON_AC97_DATA_MASK;
0261
0262 snd_ice1712_gpio_write(ice, tmp);
0263 udelay(10);
0264 tmp |= AUREON_AC97_DATA_HIGH;
0265 snd_ice1712_gpio_write(ice, tmp);
0266 udelay(10);
0267 tmp &= ~AUREON_AC97_DATA_HIGH;
0268 snd_ice1712_gpio_write(ice, tmp);
0269 udelay(10);
0270
0271
0272 tmp |= AUREON_AC97_COMMIT;
0273 snd_ice1712_gpio_write(ice, tmp);
0274 udelay(10);
0275 tmp &= ~AUREON_AC97_COMMIT;
0276 snd_ice1712_gpio_write(ice, tmp);
0277 udelay(10);
0278
0279
0280 spec->stac9744[(reg & 0x7F) >> 1] = val;
0281 }
0282
0283 static unsigned short aureon_ac97_read(struct snd_ice1712 *ice, unsigned short reg)
0284 {
0285 struct aureon_spec *spec = ice->spec;
0286 return spec->stac9744[(reg & 0x7F) >> 1];
0287 }
0288
0289
0290
0291
0292 static int aureon_ac97_init(struct snd_ice1712 *ice)
0293 {
0294 struct aureon_spec *spec = ice->spec;
0295 int i;
0296 static const unsigned short ac97_defaults[] = {
0297 0x00, 0x9640,
0298 0x02, 0x8000,
0299 0x04, 0x8000,
0300 0x06, 0x8000,
0301 0x0C, 0x8008,
0302 0x0E, 0x8008,
0303 0x10, 0x8808,
0304 0x12, 0x8808,
0305 0x14, 0x8808,
0306 0x16, 0x8808,
0307 0x18, 0x8808,
0308 0x1C, 0x8000,
0309 0x26, 0x000F,
0310 0x28, 0x0201,
0311 0x2C, 0xBB80,
0312 0x32, 0xBB80,
0313 0x7C, 0x8384,
0314 0x7E, 0x7644,
0315 (unsigned short)-1
0316 };
0317 unsigned int tmp;
0318
0319
0320 tmp = (snd_ice1712_gpio_read(ice) | AUREON_AC97_RESET) & ~AUREON_AC97_DATA_MASK;
0321 snd_ice1712_gpio_write(ice, tmp);
0322 udelay(3);
0323
0324 tmp &= ~AUREON_AC97_RESET;
0325 snd_ice1712_gpio_write(ice, tmp);
0326 udelay(3);
0327
0328 tmp |= AUREON_AC97_RESET;
0329 snd_ice1712_gpio_write(ice, tmp);
0330 udelay(3);
0331
0332 memset(&spec->stac9744, 0, sizeof(spec->stac9744));
0333 for (i = 0; ac97_defaults[i] != (unsigned short)-1; i += 2)
0334 spec->stac9744[(ac97_defaults[i]) >> 1] = ac97_defaults[i+1];
0335
0336
0337 aureon_ac97_write(ice, AC97_MASTER, 0x0000);
0338
0339 return 0;
0340 }
0341
0342 #define AUREON_AC97_STEREO 0x80
0343
0344
0345
0346
0347 static int aureon_ac97_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
0348 {
0349 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
0350 uinfo->count = kcontrol->private_value & AUREON_AC97_STEREO ? 2 : 1;
0351 uinfo->value.integer.min = 0;
0352 uinfo->value.integer.max = 31;
0353 return 0;
0354 }
0355
0356 static int aureon_ac97_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
0357 {
0358 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
0359 unsigned short vol;
0360
0361 mutex_lock(&ice->gpio_mutex);
0362
0363 vol = aureon_ac97_read(ice, kcontrol->private_value & 0x7F);
0364 ucontrol->value.integer.value[0] = 0x1F - (vol & 0x1F);
0365 if (kcontrol->private_value & AUREON_AC97_STEREO)
0366 ucontrol->value.integer.value[1] = 0x1F - ((vol >> 8) & 0x1F);
0367
0368 mutex_unlock(&ice->gpio_mutex);
0369 return 0;
0370 }
0371
0372 static int aureon_ac97_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
0373 {
0374 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
0375 unsigned short ovol, nvol;
0376 int change;
0377
0378 snd_ice1712_save_gpio_status(ice);
0379
0380 ovol = aureon_ac97_read(ice, kcontrol->private_value & 0x7F);
0381 nvol = (0x1F - ucontrol->value.integer.value[0]) & 0x001F;
0382 if (kcontrol->private_value & AUREON_AC97_STEREO)
0383 nvol |= ((0x1F - ucontrol->value.integer.value[1]) << 8) & 0x1F00;
0384 nvol |= ovol & ~0x1F1F;
0385
0386 change = (ovol != nvol);
0387 if (change)
0388 aureon_ac97_write(ice, kcontrol->private_value & 0x7F, nvol);
0389
0390 snd_ice1712_restore_gpio_status(ice);
0391
0392 return change;
0393 }
0394
0395
0396
0397
0398 #define aureon_ac97_mute_info snd_ctl_boolean_mono_info
0399
0400 static int aureon_ac97_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
0401 {
0402 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
0403
0404 mutex_lock(&ice->gpio_mutex);
0405
0406 ucontrol->value.integer.value[0] = aureon_ac97_read(ice,
0407 kcontrol->private_value & 0x7F) & 0x8000 ? 0 : 1;
0408
0409 mutex_unlock(&ice->gpio_mutex);
0410 return 0;
0411 }
0412
0413 static int aureon_ac97_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
0414 {
0415 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
0416 unsigned short ovol, nvol;
0417 int change;
0418
0419 snd_ice1712_save_gpio_status(ice);
0420
0421 ovol = aureon_ac97_read(ice, kcontrol->private_value & 0x7F);
0422 nvol = (ucontrol->value.integer.value[0] ? 0x0000 : 0x8000) | (ovol & ~0x8000);
0423
0424 change = (ovol != nvol);
0425 if (change)
0426 aureon_ac97_write(ice, kcontrol->private_value & 0x7F, nvol);
0427
0428 snd_ice1712_restore_gpio_status(ice);
0429
0430 return change;
0431 }
0432
0433
0434
0435
0436 #define aureon_ac97_micboost_info snd_ctl_boolean_mono_info
0437
0438 static int aureon_ac97_micboost_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
0439 {
0440 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
0441
0442 mutex_lock(&ice->gpio_mutex);
0443
0444 ucontrol->value.integer.value[0] = aureon_ac97_read(ice, AC97_MIC) & 0x0020 ? 0 : 1;
0445
0446 mutex_unlock(&ice->gpio_mutex);
0447 return 0;
0448 }
0449
0450 static int aureon_ac97_micboost_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
0451 {
0452 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
0453 unsigned short ovol, nvol;
0454 int change;
0455
0456 snd_ice1712_save_gpio_status(ice);
0457
0458 ovol = aureon_ac97_read(ice, AC97_MIC);
0459 nvol = (ucontrol->value.integer.value[0] ? 0x0000 : 0x0020) | (ovol & ~0x0020);
0460
0461 change = (ovol != nvol);
0462 if (change)
0463 aureon_ac97_write(ice, AC97_MIC, nvol);
0464
0465 snd_ice1712_restore_gpio_status(ice);
0466
0467 return change;
0468 }
0469
0470
0471
0472
0473 static void aureon_spi_write(struct snd_ice1712 *ice, unsigned int cs, unsigned int data, int bits)
0474 {
0475 unsigned int tmp;
0476 int i;
0477 unsigned int mosi, clk;
0478
0479 tmp = snd_ice1712_gpio_read(ice);
0480
0481 if (ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71LT ||
0482 ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71XT) {
0483 snd_ice1712_gpio_set_mask(ice, ~(PRODIGY_SPI_MOSI|PRODIGY_SPI_CLK|PRODIGY_WM_CS));
0484 mosi = PRODIGY_SPI_MOSI;
0485 clk = PRODIGY_SPI_CLK;
0486 } else {
0487 snd_ice1712_gpio_set_mask(ice, ~(AUREON_WM_RW|AUREON_SPI_MOSI|AUREON_SPI_CLK|
0488 AUREON_WM_CS|AUREON_CS8415_CS));
0489 mosi = AUREON_SPI_MOSI;
0490 clk = AUREON_SPI_CLK;
0491
0492 tmp |= AUREON_WM_RW;
0493 }
0494
0495 tmp &= ~cs;
0496 snd_ice1712_gpio_write(ice, tmp);
0497 udelay(1);
0498
0499 for (i = bits - 1; i >= 0; i--) {
0500 tmp &= ~clk;
0501 snd_ice1712_gpio_write(ice, tmp);
0502 udelay(1);
0503 if (data & (1 << i))
0504 tmp |= mosi;
0505 else
0506 tmp &= ~mosi;
0507 snd_ice1712_gpio_write(ice, tmp);
0508 udelay(1);
0509 tmp |= clk;
0510 snd_ice1712_gpio_write(ice, tmp);
0511 udelay(1);
0512 }
0513
0514 tmp &= ~clk;
0515 tmp |= cs;
0516 snd_ice1712_gpio_write(ice, tmp);
0517 udelay(1);
0518 tmp |= clk;
0519 snd_ice1712_gpio_write(ice, tmp);
0520 udelay(1);
0521 }
0522
0523
0524
0525
0526 static void aureon_spi_read(struct snd_ice1712 *ice, unsigned int cs,
0527 unsigned int data, int bits, unsigned char *buffer, int size)
0528 {
0529 int i, j;
0530 unsigned int tmp;
0531
0532 tmp = (snd_ice1712_gpio_read(ice) & ~AUREON_SPI_CLK) | AUREON_CS8415_CS|AUREON_WM_CS;
0533 snd_ice1712_gpio_write(ice, tmp);
0534 tmp &= ~cs;
0535 snd_ice1712_gpio_write(ice, tmp);
0536 udelay(1);
0537
0538 for (i = bits-1; i >= 0; i--) {
0539 if (data & (1 << i))
0540 tmp |= AUREON_SPI_MOSI;
0541 else
0542 tmp &= ~AUREON_SPI_MOSI;
0543 snd_ice1712_gpio_write(ice, tmp);
0544 udelay(1);
0545
0546 tmp |= AUREON_SPI_CLK;
0547 snd_ice1712_gpio_write(ice, tmp);
0548 udelay(1);
0549
0550 tmp &= ~AUREON_SPI_CLK;
0551 snd_ice1712_gpio_write(ice, tmp);
0552 udelay(1);
0553 }
0554
0555 for (j = 0; j < size; j++) {
0556 unsigned char outdata = 0;
0557 for (i = 7; i >= 0; i--) {
0558 tmp = snd_ice1712_gpio_read(ice);
0559 outdata <<= 1;
0560 outdata |= (tmp & AUREON_SPI_MISO) ? 1 : 0;
0561 udelay(1);
0562
0563 tmp |= AUREON_SPI_CLK;
0564 snd_ice1712_gpio_write(ice, tmp);
0565 udelay(1);
0566
0567 tmp &= ~AUREON_SPI_CLK;
0568 snd_ice1712_gpio_write(ice, tmp);
0569 udelay(1);
0570 }
0571 buffer[j] = outdata;
0572 }
0573
0574 tmp |= cs;
0575 snd_ice1712_gpio_write(ice, tmp);
0576 }
0577
0578 static unsigned char aureon_cs8415_get(struct snd_ice1712 *ice, int reg)
0579 {
0580 unsigned char val;
0581 aureon_spi_write(ice, AUREON_CS8415_CS, 0x2000 | reg, 16);
0582 aureon_spi_read(ice, AUREON_CS8415_CS, 0x21, 8, &val, 1);
0583 return val;
0584 }
0585
0586 static void aureon_cs8415_read(struct snd_ice1712 *ice, int reg,
0587 unsigned char *buffer, int size)
0588 {
0589 aureon_spi_write(ice, AUREON_CS8415_CS, 0x2000 | reg, 16);
0590 aureon_spi_read(ice, AUREON_CS8415_CS, 0x21, 8, buffer, size);
0591 }
0592
0593 static void aureon_cs8415_put(struct snd_ice1712 *ice, int reg,
0594 unsigned char val)
0595 {
0596 aureon_spi_write(ice, AUREON_CS8415_CS, 0x200000 | (reg << 8) | val, 24);
0597 }
0598
0599
0600
0601
0602 static unsigned short wm_get(struct snd_ice1712 *ice, int reg)
0603 {
0604 reg <<= 1;
0605 return ((unsigned short)ice->akm[0].images[reg] << 8) |
0606 ice->akm[0].images[reg + 1];
0607 }
0608
0609
0610
0611
0612 static void wm_put_nocache(struct snd_ice1712 *ice, int reg, unsigned short val)
0613 {
0614 aureon_spi_write(ice,
0615 ((ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71LT ||
0616 ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71XT) ?
0617 PRODIGY_WM_CS : AUREON_WM_CS),
0618 (reg << 9) | (val & 0x1ff), 16);
0619 }
0620
0621
0622
0623
0624 static void wm_put(struct snd_ice1712 *ice, int reg, unsigned short val)
0625 {
0626 wm_put_nocache(ice, reg, val);
0627 reg <<= 1;
0628 ice->akm[0].images[reg] = val >> 8;
0629 ice->akm[0].images[reg + 1] = val;
0630 }
0631
0632
0633
0634 #define aureon_mono_bool_info snd_ctl_boolean_mono_info
0635
0636
0637
0638
0639 #define aureon_ac97_mmute_info snd_ctl_boolean_mono_info
0640
0641 static int aureon_ac97_mmute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
0642 {
0643 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
0644
0645 mutex_lock(&ice->gpio_mutex);
0646
0647 ucontrol->value.integer.value[0] = (wm_get(ice, WM_OUT_MUX1) >> 1) & 0x01;
0648
0649 mutex_unlock(&ice->gpio_mutex);
0650 return 0;
0651 }
0652
0653 static int aureon_ac97_mmute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
0654 {
0655 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
0656 unsigned short ovol, nvol;
0657 int change;
0658
0659 snd_ice1712_save_gpio_status(ice);
0660
0661 ovol = wm_get(ice, WM_OUT_MUX1);
0662 nvol = (ovol & ~0x02) | (ucontrol->value.integer.value[0] ? 0x02 : 0x00);
0663 change = (ovol != nvol);
0664 if (change)
0665 wm_put(ice, WM_OUT_MUX1, nvol);
0666
0667 snd_ice1712_restore_gpio_status(ice);
0668
0669 return change;
0670 }
0671
0672 static const DECLARE_TLV_DB_SCALE(db_scale_wm_dac, -10000, 100, 1);
0673 static const DECLARE_TLV_DB_SCALE(db_scale_wm_pcm, -6400, 50, 1);
0674 static const DECLARE_TLV_DB_SCALE(db_scale_wm_adc, -1200, 100, 0);
0675 static const DECLARE_TLV_DB_SCALE(db_scale_ac97_master, -4650, 150, 0);
0676 static const DECLARE_TLV_DB_SCALE(db_scale_ac97_gain, -3450, 150, 0);
0677
0678 #define WM_VOL_MAX 100
0679 #define WM_VOL_CNT 101
0680 #define WM_VOL_MUTE 0x8000
0681
0682 static void wm_set_vol(struct snd_ice1712 *ice, unsigned int index, unsigned short vol, unsigned short master)
0683 {
0684 unsigned char nvol;
0685
0686 if ((master & WM_VOL_MUTE) || (vol & WM_VOL_MUTE)) {
0687 nvol = 0;
0688 } else {
0689 nvol = ((vol % WM_VOL_CNT) * (master % WM_VOL_CNT)) /
0690 WM_VOL_MAX;
0691 nvol += 0x1b;
0692 }
0693
0694 wm_put(ice, index, nvol);
0695 wm_put_nocache(ice, index, 0x180 | nvol);
0696 }
0697
0698
0699
0700
0701 #define wm_pcm_mute_info snd_ctl_boolean_mono_info
0702
0703 static int wm_pcm_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
0704 {
0705 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
0706
0707 mutex_lock(&ice->gpio_mutex);
0708 ucontrol->value.integer.value[0] = (wm_get(ice, WM_MUTE) & 0x10) ? 0 : 1;
0709 mutex_unlock(&ice->gpio_mutex);
0710 return 0;
0711 }
0712
0713 static int wm_pcm_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
0714 {
0715 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
0716 unsigned short nval, oval;
0717 int change;
0718
0719 snd_ice1712_save_gpio_status(ice);
0720 oval = wm_get(ice, WM_MUTE);
0721 nval = (oval & ~0x10) | (ucontrol->value.integer.value[0] ? 0 : 0x10);
0722 change = (oval != nval);
0723 if (change)
0724 wm_put(ice, WM_MUTE, nval);
0725 snd_ice1712_restore_gpio_status(ice);
0726
0727 return change;
0728 }
0729
0730
0731
0732
0733 static int wm_master_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
0734 {
0735 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
0736 uinfo->count = 2;
0737 uinfo->value.integer.min = 0;
0738 uinfo->value.integer.max = WM_VOL_MAX;
0739 return 0;
0740 }
0741
0742 static int wm_master_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
0743 {
0744 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
0745 struct aureon_spec *spec = ice->spec;
0746 int i;
0747 for (i = 0; i < 2; i++)
0748 ucontrol->value.integer.value[i] =
0749 spec->master[i] & ~WM_VOL_MUTE;
0750 return 0;
0751 }
0752
0753 static int wm_master_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
0754 {
0755 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
0756 struct aureon_spec *spec = ice->spec;
0757 int ch, change = 0;
0758
0759 snd_ice1712_save_gpio_status(ice);
0760 for (ch = 0; ch < 2; ch++) {
0761 unsigned int vol = ucontrol->value.integer.value[ch];
0762 if (vol > WM_VOL_MAX)
0763 vol = WM_VOL_MAX;
0764 vol |= spec->master[ch] & WM_VOL_MUTE;
0765 if (vol != spec->master[ch]) {
0766 int dac;
0767 spec->master[ch] = vol;
0768 for (dac = 0; dac < ice->num_total_dacs; dac += 2)
0769 wm_set_vol(ice, WM_DAC_ATTEN + dac + ch,
0770 spec->vol[dac + ch],
0771 spec->master[ch]);
0772 change = 1;
0773 }
0774 }
0775 snd_ice1712_restore_gpio_status(ice);
0776 return change;
0777 }
0778
0779
0780
0781
0782 static int wm_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
0783 {
0784 int voices = kcontrol->private_value >> 8;
0785 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
0786 uinfo->count = voices;
0787 uinfo->value.integer.min = 0;
0788 uinfo->value.integer.max = WM_VOL_MAX;
0789 return 0;
0790 }
0791
0792 static int wm_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
0793 {
0794 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
0795 struct aureon_spec *spec = ice->spec;
0796 int i, ofs, voices;
0797
0798 voices = kcontrol->private_value >> 8;
0799 ofs = kcontrol->private_value & 0xff;
0800 for (i = 0; i < voices; i++)
0801 ucontrol->value.integer.value[i] =
0802 spec->vol[ofs+i] & ~WM_VOL_MUTE;
0803 return 0;
0804 }
0805
0806 static int wm_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
0807 {
0808 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
0809 struct aureon_spec *spec = ice->spec;
0810 int i, idx, ofs, voices;
0811 int change = 0;
0812
0813 voices = kcontrol->private_value >> 8;
0814 ofs = kcontrol->private_value & 0xff;
0815 snd_ice1712_save_gpio_status(ice);
0816 for (i = 0; i < voices; i++) {
0817 unsigned int vol = ucontrol->value.integer.value[i];
0818 if (vol > WM_VOL_MAX)
0819 vol = WM_VOL_MAX;
0820 vol |= spec->vol[ofs+i] & WM_VOL_MUTE;
0821 if (vol != spec->vol[ofs+i]) {
0822 spec->vol[ofs+i] = vol;
0823 idx = WM_DAC_ATTEN + ofs + i;
0824 wm_set_vol(ice, idx, spec->vol[ofs + i],
0825 spec->master[i]);
0826 change = 1;
0827 }
0828 }
0829 snd_ice1712_restore_gpio_status(ice);
0830 return change;
0831 }
0832
0833
0834
0835
0836 static int wm_mute_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
0837 {
0838 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
0839 uinfo->count = kcontrol->private_value >> 8;
0840 uinfo->value.integer.min = 0;
0841 uinfo->value.integer.max = 1;
0842 return 0;
0843 }
0844
0845 static int wm_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
0846 {
0847 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
0848 struct aureon_spec *spec = ice->spec;
0849 int voices, ofs, i;
0850
0851 voices = kcontrol->private_value >> 8;
0852 ofs = kcontrol->private_value & 0xFF;
0853
0854 for (i = 0; i < voices; i++)
0855 ucontrol->value.integer.value[i] =
0856 (spec->vol[ofs + i] & WM_VOL_MUTE) ? 0 : 1;
0857 return 0;
0858 }
0859
0860 static int wm_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
0861 {
0862 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
0863 struct aureon_spec *spec = ice->spec;
0864 int change = 0, voices, ofs, i;
0865
0866 voices = kcontrol->private_value >> 8;
0867 ofs = kcontrol->private_value & 0xFF;
0868
0869 snd_ice1712_save_gpio_status(ice);
0870 for (i = 0; i < voices; i++) {
0871 int val = (spec->vol[ofs + i] & WM_VOL_MUTE) ? 0 : 1;
0872 if (ucontrol->value.integer.value[i] != val) {
0873 spec->vol[ofs + i] &= ~WM_VOL_MUTE;
0874 spec->vol[ofs + i] |=
0875 ucontrol->value.integer.value[i] ? 0 : WM_VOL_MUTE;
0876 wm_set_vol(ice, ofs + i, spec->vol[ofs + i],
0877 spec->master[i]);
0878 change = 1;
0879 }
0880 }
0881 snd_ice1712_restore_gpio_status(ice);
0882
0883 return change;
0884 }
0885
0886
0887
0888
0889 #define wm_master_mute_info snd_ctl_boolean_stereo_info
0890
0891 static int wm_master_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
0892 {
0893 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
0894 struct aureon_spec *spec = ice->spec;
0895
0896 ucontrol->value.integer.value[0] =
0897 (spec->master[0] & WM_VOL_MUTE) ? 0 : 1;
0898 ucontrol->value.integer.value[1] =
0899 (spec->master[1] & WM_VOL_MUTE) ? 0 : 1;
0900 return 0;
0901 }
0902
0903 static int wm_master_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
0904 {
0905 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
0906 struct aureon_spec *spec = ice->spec;
0907 int change = 0, i;
0908
0909 snd_ice1712_save_gpio_status(ice);
0910 for (i = 0; i < 2; i++) {
0911 int val = (spec->master[i] & WM_VOL_MUTE) ? 0 : 1;
0912 if (ucontrol->value.integer.value[i] != val) {
0913 int dac;
0914 spec->master[i] &= ~WM_VOL_MUTE;
0915 spec->master[i] |=
0916 ucontrol->value.integer.value[i] ? 0 : WM_VOL_MUTE;
0917 for (dac = 0; dac < ice->num_total_dacs; dac += 2)
0918 wm_set_vol(ice, WM_DAC_ATTEN + dac + i,
0919 spec->vol[dac + i],
0920 spec->master[i]);
0921 change = 1;
0922 }
0923 }
0924 snd_ice1712_restore_gpio_status(ice);
0925
0926 return change;
0927 }
0928
0929
0930 #define PCM_0dB 0xff
0931 #define PCM_RES 128
0932 #define PCM_MIN (PCM_0dB - PCM_RES)
0933 static int wm_pcm_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
0934 {
0935 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
0936 uinfo->count = 1;
0937 uinfo->value.integer.min = 0;
0938 uinfo->value.integer.max = PCM_RES;
0939 return 0;
0940 }
0941
0942 static int wm_pcm_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
0943 {
0944 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
0945 unsigned short val;
0946
0947 mutex_lock(&ice->gpio_mutex);
0948 val = wm_get(ice, WM_DAC_DIG_MASTER_ATTEN) & 0xff;
0949 val = val > PCM_MIN ? (val - PCM_MIN) : 0;
0950 ucontrol->value.integer.value[0] = val;
0951 mutex_unlock(&ice->gpio_mutex);
0952 return 0;
0953 }
0954
0955 static int wm_pcm_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
0956 {
0957 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
0958 unsigned short ovol, nvol;
0959 int change = 0;
0960
0961 nvol = ucontrol->value.integer.value[0];
0962 if (nvol > PCM_RES)
0963 return -EINVAL;
0964 snd_ice1712_save_gpio_status(ice);
0965 nvol = (nvol ? (nvol + PCM_MIN) : 0) & 0xff;
0966 ovol = wm_get(ice, WM_DAC_DIG_MASTER_ATTEN) & 0xff;
0967 if (ovol != nvol) {
0968 wm_put(ice, WM_DAC_DIG_MASTER_ATTEN, nvol);
0969 wm_put_nocache(ice, WM_DAC_DIG_MASTER_ATTEN, nvol | 0x100);
0970 change = 1;
0971 }
0972 snd_ice1712_restore_gpio_status(ice);
0973 return change;
0974 }
0975
0976
0977
0978
0979 #define wm_adc_mute_info snd_ctl_boolean_stereo_info
0980
0981 static int wm_adc_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
0982 {
0983 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
0984 unsigned short val;
0985 int i;
0986
0987 mutex_lock(&ice->gpio_mutex);
0988 for (i = 0; i < 2; i++) {
0989 val = wm_get(ice, WM_ADC_GAIN + i);
0990 ucontrol->value.integer.value[i] = ~val>>5 & 0x1;
0991 }
0992 mutex_unlock(&ice->gpio_mutex);
0993 return 0;
0994 }
0995
0996 static int wm_adc_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
0997 {
0998 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
0999 unsigned short new, old;
1000 int i, change = 0;
1001
1002 snd_ice1712_save_gpio_status(ice);
1003 for (i = 0; i < 2; i++) {
1004 old = wm_get(ice, WM_ADC_GAIN + i);
1005 new = (~ucontrol->value.integer.value[i]<<5&0x20) | (old&~0x20);
1006 if (new != old) {
1007 wm_put(ice, WM_ADC_GAIN + i, new);
1008 change = 1;
1009 }
1010 }
1011 snd_ice1712_restore_gpio_status(ice);
1012
1013 return change;
1014 }
1015
1016
1017
1018
1019 static int wm_adc_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1020 {
1021 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1022 uinfo->count = 2;
1023 uinfo->value.integer.min = 0;
1024 uinfo->value.integer.max = 0x1f;
1025 return 0;
1026 }
1027
1028 static int wm_adc_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1029 {
1030 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1031 int i, idx;
1032 unsigned short vol;
1033
1034 mutex_lock(&ice->gpio_mutex);
1035 for (i = 0; i < 2; i++) {
1036 idx = WM_ADC_GAIN + i;
1037 vol = wm_get(ice, idx) & 0x1f;
1038 ucontrol->value.integer.value[i] = vol;
1039 }
1040 mutex_unlock(&ice->gpio_mutex);
1041 return 0;
1042 }
1043
1044 static int wm_adc_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1045 {
1046 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1047 int i, idx;
1048 unsigned short ovol, nvol;
1049 int change = 0;
1050
1051 snd_ice1712_save_gpio_status(ice);
1052 for (i = 0; i < 2; i++) {
1053 idx = WM_ADC_GAIN + i;
1054 nvol = ucontrol->value.integer.value[i] & 0x1f;
1055 ovol = wm_get(ice, idx);
1056 if ((ovol & 0x1f) != nvol) {
1057 wm_put(ice, idx, nvol | (ovol & ~0x1f));
1058 change = 1;
1059 }
1060 }
1061 snd_ice1712_restore_gpio_status(ice);
1062 return change;
1063 }
1064
1065
1066
1067
1068 static int wm_adc_mux_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1069 {
1070 static const char * const texts[] = {
1071 "CD",
1072 "Aux",
1073 "Line",
1074 "Mic",
1075 "AC97"
1076 };
1077 static const char * const universe_texts[] = {
1078 "Aux1",
1079 "CD",
1080 "Phono",
1081 "Line",
1082 "Aux2",
1083 "Mic",
1084 "Aux3",
1085 "AC97"
1086 };
1087 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1088
1089 if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON71_UNIVERSE)
1090 return snd_ctl_enum_info(uinfo, 2, 8, universe_texts);
1091 else
1092 return snd_ctl_enum_info(uinfo, 2, 5, texts);
1093 }
1094
1095 static int wm_adc_mux_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1096 {
1097 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1098 unsigned short val;
1099
1100 mutex_lock(&ice->gpio_mutex);
1101 val = wm_get(ice, WM_ADC_MUX);
1102 ucontrol->value.enumerated.item[0] = val & 7;
1103 ucontrol->value.enumerated.item[1] = (val >> 4) & 7;
1104 mutex_unlock(&ice->gpio_mutex);
1105 return 0;
1106 }
1107
1108 static int wm_adc_mux_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1109 {
1110 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1111 unsigned short oval, nval;
1112 int change;
1113
1114 snd_ice1712_save_gpio_status(ice);
1115 oval = wm_get(ice, WM_ADC_MUX);
1116 nval = oval & ~0x77;
1117 nval |= ucontrol->value.enumerated.item[0] & 7;
1118 nval |= (ucontrol->value.enumerated.item[1] & 7) << 4;
1119 change = (oval != nval);
1120 if (change)
1121 wm_put(ice, WM_ADC_MUX, nval);
1122 snd_ice1712_restore_gpio_status(ice);
1123 return change;
1124 }
1125
1126
1127
1128
1129 static int aureon_cs8415_mux_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1130 {
1131 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1132 static const char * const aureon_texts[] = {
1133 "CD",
1134 "Optical"
1135 };
1136 static const char * const prodigy_texts[] = {
1137 "CD",
1138 "Coax"
1139 };
1140 if (ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71)
1141 return snd_ctl_enum_info(uinfo, 1, 2, prodigy_texts);
1142 else
1143 return snd_ctl_enum_info(uinfo, 1, 2, aureon_texts);
1144 }
1145
1146 static int aureon_cs8415_mux_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1147 {
1148 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1149 struct aureon_spec *spec = ice->spec;
1150
1151
1152
1153 ucontrol->value.enumerated.item[0] = spec->cs8415_mux;
1154
1155 return 0;
1156 }
1157
1158 static int aureon_cs8415_mux_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1159 {
1160 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1161 struct aureon_spec *spec = ice->spec;
1162 unsigned short oval, nval;
1163 int change;
1164
1165 snd_ice1712_save_gpio_status(ice);
1166 oval = aureon_cs8415_get(ice, CS8415_CTRL2);
1167 nval = oval & ~0x07;
1168 nval |= ucontrol->value.enumerated.item[0] & 7;
1169 change = (oval != nval);
1170 if (change)
1171 aureon_cs8415_put(ice, CS8415_CTRL2, nval);
1172 snd_ice1712_restore_gpio_status(ice);
1173 spec->cs8415_mux = ucontrol->value.enumerated.item[0];
1174 return change;
1175 }
1176
1177 static int aureon_cs8415_rate_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1178 {
1179 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1180 uinfo->count = 1;
1181 uinfo->value.integer.min = 0;
1182 uinfo->value.integer.max = 192000;
1183 return 0;
1184 }
1185
1186 static int aureon_cs8415_rate_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1187 {
1188 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1189 unsigned char ratio;
1190 ratio = aureon_cs8415_get(ice, CS8415_RATIO);
1191 ucontrol->value.integer.value[0] = (int)((unsigned int)ratio * 750);
1192 return 0;
1193 }
1194
1195
1196
1197
1198 #define aureon_cs8415_mute_info snd_ctl_boolean_mono_info
1199
1200 static int aureon_cs8415_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1201 {
1202 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1203 snd_ice1712_save_gpio_status(ice);
1204 ucontrol->value.integer.value[0] = (aureon_cs8415_get(ice, CS8415_CTRL1) & 0x20) ? 0 : 1;
1205 snd_ice1712_restore_gpio_status(ice);
1206 return 0;
1207 }
1208
1209 static int aureon_cs8415_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1210 {
1211 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1212 unsigned char oval, nval;
1213 int change;
1214 snd_ice1712_save_gpio_status(ice);
1215 oval = aureon_cs8415_get(ice, CS8415_CTRL1);
1216 if (ucontrol->value.integer.value[0])
1217 nval = oval & ~0x20;
1218 else
1219 nval = oval | 0x20;
1220 change = (oval != nval);
1221 if (change)
1222 aureon_cs8415_put(ice, CS8415_CTRL1, nval);
1223 snd_ice1712_restore_gpio_status(ice);
1224 return change;
1225 }
1226
1227
1228
1229
1230 static int aureon_cs8415_qsub_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1231 {
1232 uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
1233 uinfo->count = 10;
1234 return 0;
1235 }
1236
1237 static int aureon_cs8415_qsub_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1238 {
1239 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1240
1241 snd_ice1712_save_gpio_status(ice);
1242 aureon_cs8415_read(ice, CS8415_QSUB, ucontrol->value.bytes.data, 10);
1243 snd_ice1712_restore_gpio_status(ice);
1244
1245 return 0;
1246 }
1247
1248 static int aureon_cs8415_spdif_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1249 {
1250 uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
1251 uinfo->count = 1;
1252 return 0;
1253 }
1254
1255 static int aureon_cs8415_mask_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1256 {
1257 memset(ucontrol->value.iec958.status, 0xFF, 24);
1258 return 0;
1259 }
1260
1261 static int aureon_cs8415_spdif_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1262 {
1263 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1264
1265 snd_ice1712_save_gpio_status(ice);
1266 aureon_cs8415_read(ice, CS8415_C_BUFFER, ucontrol->value.iec958.status, 24);
1267 snd_ice1712_restore_gpio_status(ice);
1268 return 0;
1269 }
1270
1271
1272
1273
1274 static int aureon_set_headphone_amp(struct snd_ice1712 *ice, int enable)
1275 {
1276 unsigned int tmp, tmp2;
1277
1278 tmp2 = tmp = snd_ice1712_gpio_read(ice);
1279 if (enable)
1280 if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT &&
1281 ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71XT)
1282 tmp |= AUREON_HP_SEL;
1283 else
1284 tmp |= PRODIGY_HP_SEL;
1285 else
1286 if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT &&
1287 ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71XT)
1288 tmp &= ~AUREON_HP_SEL;
1289 else
1290 tmp &= ~PRODIGY_HP_SEL;
1291 if (tmp != tmp2) {
1292 snd_ice1712_gpio_write(ice, tmp);
1293 return 1;
1294 }
1295 return 0;
1296 }
1297
1298 static int aureon_get_headphone_amp(struct snd_ice1712 *ice)
1299 {
1300 unsigned int tmp = snd_ice1712_gpio_read(ice);
1301
1302 return (tmp & AUREON_HP_SEL) != 0;
1303 }
1304
1305 #define aureon_hpamp_info snd_ctl_boolean_mono_info
1306
1307 static int aureon_hpamp_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1308 {
1309 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1310
1311 ucontrol->value.integer.value[0] = aureon_get_headphone_amp(ice);
1312 return 0;
1313 }
1314
1315
1316 static int aureon_hpamp_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1317 {
1318 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1319
1320 return aureon_set_headphone_amp(ice, ucontrol->value.integer.value[0]);
1321 }
1322
1323
1324
1325
1326
1327 #define aureon_deemp_info snd_ctl_boolean_mono_info
1328
1329 static int aureon_deemp_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1330 {
1331 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1332 ucontrol->value.integer.value[0] = (wm_get(ice, WM_DAC_CTRL2) & 0xf) == 0xf;
1333 return 0;
1334 }
1335
1336 static int aureon_deemp_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1337 {
1338 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1339 int temp, temp2;
1340 temp2 = temp = wm_get(ice, WM_DAC_CTRL2);
1341 if (ucontrol->value.integer.value[0])
1342 temp |= 0xf;
1343 else
1344 temp &= ~0xf;
1345 if (temp != temp2) {
1346 wm_put(ice, WM_DAC_CTRL2, temp);
1347 return 1;
1348 }
1349 return 0;
1350 }
1351
1352
1353
1354
1355 static int aureon_oversampling_info(struct snd_kcontrol *k, struct snd_ctl_elem_info *uinfo)
1356 {
1357 static const char * const texts[2] = { "128x", "64x" };
1358
1359 return snd_ctl_enum_info(uinfo, 1, 2, texts);
1360 }
1361
1362 static int aureon_oversampling_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1363 {
1364 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1365 ucontrol->value.enumerated.item[0] = (wm_get(ice, WM_MASTER) & 0x8) == 0x8;
1366 return 0;
1367 }
1368
1369 static int aureon_oversampling_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1370 {
1371 int temp, temp2;
1372 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1373
1374 temp2 = temp = wm_get(ice, WM_MASTER);
1375
1376 if (ucontrol->value.enumerated.item[0])
1377 temp |= 0x8;
1378 else
1379 temp &= ~0x8;
1380
1381 if (temp != temp2) {
1382 wm_put(ice, WM_MASTER, temp);
1383 return 1;
1384 }
1385 return 0;
1386 }
1387
1388
1389
1390
1391
1392 static const struct snd_kcontrol_new aureon_dac_controls[] = {
1393 {
1394 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1395 .name = "Master Playback Switch",
1396 .info = wm_master_mute_info,
1397 .get = wm_master_mute_get,
1398 .put = wm_master_mute_put
1399 },
1400 {
1401 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1402 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1403 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1404 .name = "Master Playback Volume",
1405 .info = wm_master_vol_info,
1406 .get = wm_master_vol_get,
1407 .put = wm_master_vol_put,
1408 .tlv = { .p = db_scale_wm_dac }
1409 },
1410 {
1411 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1412 .name = "Front Playback Switch",
1413 .info = wm_mute_info,
1414 .get = wm_mute_get,
1415 .put = wm_mute_put,
1416 .private_value = (2 << 8) | 0
1417 },
1418 {
1419 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1420 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1421 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1422 .name = "Front Playback Volume",
1423 .info = wm_vol_info,
1424 .get = wm_vol_get,
1425 .put = wm_vol_put,
1426 .private_value = (2 << 8) | 0,
1427 .tlv = { .p = db_scale_wm_dac }
1428 },
1429 {
1430 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1431 .name = "Rear Playback Switch",
1432 .info = wm_mute_info,
1433 .get = wm_mute_get,
1434 .put = wm_mute_put,
1435 .private_value = (2 << 8) | 2
1436 },
1437 {
1438 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1439 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1440 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1441 .name = "Rear Playback Volume",
1442 .info = wm_vol_info,
1443 .get = wm_vol_get,
1444 .put = wm_vol_put,
1445 .private_value = (2 << 8) | 2,
1446 .tlv = { .p = db_scale_wm_dac }
1447 },
1448 {
1449 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1450 .name = "Center Playback Switch",
1451 .info = wm_mute_info,
1452 .get = wm_mute_get,
1453 .put = wm_mute_put,
1454 .private_value = (1 << 8) | 4
1455 },
1456 {
1457 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1458 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1459 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1460 .name = "Center Playback Volume",
1461 .info = wm_vol_info,
1462 .get = wm_vol_get,
1463 .put = wm_vol_put,
1464 .private_value = (1 << 8) | 4,
1465 .tlv = { .p = db_scale_wm_dac }
1466 },
1467 {
1468 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1469 .name = "LFE Playback Switch",
1470 .info = wm_mute_info,
1471 .get = wm_mute_get,
1472 .put = wm_mute_put,
1473 .private_value = (1 << 8) | 5
1474 },
1475 {
1476 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1477 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1478 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1479 .name = "LFE Playback Volume",
1480 .info = wm_vol_info,
1481 .get = wm_vol_get,
1482 .put = wm_vol_put,
1483 .private_value = (1 << 8) | 5,
1484 .tlv = { .p = db_scale_wm_dac }
1485 },
1486 {
1487 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1488 .name = "Side Playback Switch",
1489 .info = wm_mute_info,
1490 .get = wm_mute_get,
1491 .put = wm_mute_put,
1492 .private_value = (2 << 8) | 6
1493 },
1494 {
1495 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1496 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1497 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1498 .name = "Side Playback Volume",
1499 .info = wm_vol_info,
1500 .get = wm_vol_get,
1501 .put = wm_vol_put,
1502 .private_value = (2 << 8) | 6,
1503 .tlv = { .p = db_scale_wm_dac }
1504 }
1505 };
1506
1507 static const struct snd_kcontrol_new wm_controls[] = {
1508 {
1509 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1510 .name = "PCM Playback Switch",
1511 .info = wm_pcm_mute_info,
1512 .get = wm_pcm_mute_get,
1513 .put = wm_pcm_mute_put
1514 },
1515 {
1516 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1517 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1518 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1519 .name = "PCM Playback Volume",
1520 .info = wm_pcm_vol_info,
1521 .get = wm_pcm_vol_get,
1522 .put = wm_pcm_vol_put,
1523 .tlv = { .p = db_scale_wm_pcm }
1524 },
1525 {
1526 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1527 .name = "Capture Switch",
1528 .info = wm_adc_mute_info,
1529 .get = wm_adc_mute_get,
1530 .put = wm_adc_mute_put,
1531 },
1532 {
1533 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1534 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1535 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1536 .name = "Capture Volume",
1537 .info = wm_adc_vol_info,
1538 .get = wm_adc_vol_get,
1539 .put = wm_adc_vol_put,
1540 .tlv = { .p = db_scale_wm_adc }
1541 },
1542 {
1543 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1544 .name = "Capture Source",
1545 .info = wm_adc_mux_info,
1546 .get = wm_adc_mux_get,
1547 .put = wm_adc_mux_put,
1548 .private_value = 5
1549 },
1550 {
1551 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1552 .name = "External Amplifier",
1553 .info = aureon_hpamp_info,
1554 .get = aureon_hpamp_get,
1555 .put = aureon_hpamp_put
1556 },
1557 {
1558 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1559 .name = "DAC Deemphasis Switch",
1560 .info = aureon_deemp_info,
1561 .get = aureon_deemp_get,
1562 .put = aureon_deemp_put
1563 },
1564 {
1565 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1566 .name = "ADC Oversampling",
1567 .info = aureon_oversampling_info,
1568 .get = aureon_oversampling_get,
1569 .put = aureon_oversampling_put
1570 }
1571 };
1572
1573 static const struct snd_kcontrol_new ac97_controls[] = {
1574 {
1575 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1576 .name = "AC97 Playback Switch",
1577 .info = aureon_ac97_mmute_info,
1578 .get = aureon_ac97_mmute_get,
1579 .put = aureon_ac97_mmute_put,
1580 .private_value = AC97_MASTER
1581 },
1582 {
1583 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1584 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1585 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1586 .name = "AC97 Playback Volume",
1587 .info = aureon_ac97_vol_info,
1588 .get = aureon_ac97_vol_get,
1589 .put = aureon_ac97_vol_put,
1590 .private_value = AC97_MASTER|AUREON_AC97_STEREO,
1591 .tlv = { .p = db_scale_ac97_master }
1592 },
1593 {
1594 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1595 .name = "CD Playback Switch",
1596 .info = aureon_ac97_mute_info,
1597 .get = aureon_ac97_mute_get,
1598 .put = aureon_ac97_mute_put,
1599 .private_value = AC97_CD
1600 },
1601 {
1602 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1603 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1604 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1605 .name = "CD Playback Volume",
1606 .info = aureon_ac97_vol_info,
1607 .get = aureon_ac97_vol_get,
1608 .put = aureon_ac97_vol_put,
1609 .private_value = AC97_CD|AUREON_AC97_STEREO,
1610 .tlv = { .p = db_scale_ac97_gain }
1611 },
1612 {
1613 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1614 .name = "Aux Playback Switch",
1615 .info = aureon_ac97_mute_info,
1616 .get = aureon_ac97_mute_get,
1617 .put = aureon_ac97_mute_put,
1618 .private_value = AC97_AUX,
1619 },
1620 {
1621 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1622 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1623 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1624 .name = "Aux Playback Volume",
1625 .info = aureon_ac97_vol_info,
1626 .get = aureon_ac97_vol_get,
1627 .put = aureon_ac97_vol_put,
1628 .private_value = AC97_AUX|AUREON_AC97_STEREO,
1629 .tlv = { .p = db_scale_ac97_gain }
1630 },
1631 {
1632 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1633 .name = "Line Playback Switch",
1634 .info = aureon_ac97_mute_info,
1635 .get = aureon_ac97_mute_get,
1636 .put = aureon_ac97_mute_put,
1637 .private_value = AC97_LINE
1638 },
1639 {
1640 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1641 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1642 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1643 .name = "Line Playback Volume",
1644 .info = aureon_ac97_vol_info,
1645 .get = aureon_ac97_vol_get,
1646 .put = aureon_ac97_vol_put,
1647 .private_value = AC97_LINE|AUREON_AC97_STEREO,
1648 .tlv = { .p = db_scale_ac97_gain }
1649 },
1650 {
1651 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1652 .name = "Mic Playback Switch",
1653 .info = aureon_ac97_mute_info,
1654 .get = aureon_ac97_mute_get,
1655 .put = aureon_ac97_mute_put,
1656 .private_value = AC97_MIC
1657 },
1658 {
1659 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1660 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1661 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1662 .name = "Mic Playback Volume",
1663 .info = aureon_ac97_vol_info,
1664 .get = aureon_ac97_vol_get,
1665 .put = aureon_ac97_vol_put,
1666 .private_value = AC97_MIC,
1667 .tlv = { .p = db_scale_ac97_gain }
1668 },
1669 {
1670 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1671 .name = "Mic Boost (+20dB)",
1672 .info = aureon_ac97_micboost_info,
1673 .get = aureon_ac97_micboost_get,
1674 .put = aureon_ac97_micboost_put
1675 }
1676 };
1677
1678 static const struct snd_kcontrol_new universe_ac97_controls[] = {
1679 {
1680 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1681 .name = "AC97 Playback Switch",
1682 .info = aureon_ac97_mmute_info,
1683 .get = aureon_ac97_mmute_get,
1684 .put = aureon_ac97_mmute_put,
1685 .private_value = AC97_MASTER
1686 },
1687 {
1688 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1689 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1690 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1691 .name = "AC97 Playback Volume",
1692 .info = aureon_ac97_vol_info,
1693 .get = aureon_ac97_vol_get,
1694 .put = aureon_ac97_vol_put,
1695 .private_value = AC97_MASTER|AUREON_AC97_STEREO,
1696 .tlv = { .p = db_scale_ac97_master }
1697 },
1698 {
1699 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1700 .name = "CD Playback Switch",
1701 .info = aureon_ac97_mute_info,
1702 .get = aureon_ac97_mute_get,
1703 .put = aureon_ac97_mute_put,
1704 .private_value = AC97_AUX
1705 },
1706 {
1707 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1708 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1709 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1710 .name = "CD Playback Volume",
1711 .info = aureon_ac97_vol_info,
1712 .get = aureon_ac97_vol_get,
1713 .put = aureon_ac97_vol_put,
1714 .private_value = AC97_AUX|AUREON_AC97_STEREO,
1715 .tlv = { .p = db_scale_ac97_gain }
1716 },
1717 {
1718 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1719 .name = "Phono Playback Switch",
1720 .info = aureon_ac97_mute_info,
1721 .get = aureon_ac97_mute_get,
1722 .put = aureon_ac97_mute_put,
1723 .private_value = AC97_CD
1724 },
1725 {
1726 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1727 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1728 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1729 .name = "Phono Playback Volume",
1730 .info = aureon_ac97_vol_info,
1731 .get = aureon_ac97_vol_get,
1732 .put = aureon_ac97_vol_put,
1733 .private_value = AC97_CD|AUREON_AC97_STEREO,
1734 .tlv = { .p = db_scale_ac97_gain }
1735 },
1736 {
1737 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1738 .name = "Line Playback Switch",
1739 .info = aureon_ac97_mute_info,
1740 .get = aureon_ac97_mute_get,
1741 .put = aureon_ac97_mute_put,
1742 .private_value = AC97_LINE
1743 },
1744 {
1745 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1746 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1747 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1748 .name = "Line Playback Volume",
1749 .info = aureon_ac97_vol_info,
1750 .get = aureon_ac97_vol_get,
1751 .put = aureon_ac97_vol_put,
1752 .private_value = AC97_LINE|AUREON_AC97_STEREO,
1753 .tlv = { .p = db_scale_ac97_gain }
1754 },
1755 {
1756 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1757 .name = "Mic Playback Switch",
1758 .info = aureon_ac97_mute_info,
1759 .get = aureon_ac97_mute_get,
1760 .put = aureon_ac97_mute_put,
1761 .private_value = AC97_MIC
1762 },
1763 {
1764 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1765 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1766 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1767 .name = "Mic Playback Volume",
1768 .info = aureon_ac97_vol_info,
1769 .get = aureon_ac97_vol_get,
1770 .put = aureon_ac97_vol_put,
1771 .private_value = AC97_MIC,
1772 .tlv = { .p = db_scale_ac97_gain }
1773 },
1774 {
1775 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1776 .name = "Mic Boost (+20dB)",
1777 .info = aureon_ac97_micboost_info,
1778 .get = aureon_ac97_micboost_get,
1779 .put = aureon_ac97_micboost_put
1780 },
1781 {
1782 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1783 .name = "Aux Playback Switch",
1784 .info = aureon_ac97_mute_info,
1785 .get = aureon_ac97_mute_get,
1786 .put = aureon_ac97_mute_put,
1787 .private_value = AC97_VIDEO,
1788 },
1789 {
1790 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1791 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1792 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1793 .name = "Aux Playback Volume",
1794 .info = aureon_ac97_vol_info,
1795 .get = aureon_ac97_vol_get,
1796 .put = aureon_ac97_vol_put,
1797 .private_value = AC97_VIDEO|AUREON_AC97_STEREO,
1798 .tlv = { .p = db_scale_ac97_gain }
1799 },
1800 {
1801 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1802 .name = "Aux Source",
1803 .info = aureon_universe_inmux_info,
1804 .get = aureon_universe_inmux_get,
1805 .put = aureon_universe_inmux_put
1806 }
1807
1808 };
1809
1810 static const struct snd_kcontrol_new cs8415_controls[] = {
1811 {
1812 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1813 .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, SWITCH),
1814 .info = aureon_cs8415_mute_info,
1815 .get = aureon_cs8415_mute_get,
1816 .put = aureon_cs8415_mute_put
1817 },
1818 {
1819 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1820 .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, NONE) "Source",
1821 .info = aureon_cs8415_mux_info,
1822 .get = aureon_cs8415_mux_get,
1823 .put = aureon_cs8415_mux_put,
1824 },
1825 {
1826 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
1827 .name = SNDRV_CTL_NAME_IEC958("Q-subcode ", CAPTURE, DEFAULT),
1828 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
1829 .info = aureon_cs8415_qsub_info,
1830 .get = aureon_cs8415_qsub_get,
1831 },
1832 {
1833 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
1834 .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, MASK),
1835 .access = SNDRV_CTL_ELEM_ACCESS_READ,
1836 .info = aureon_cs8415_spdif_info,
1837 .get = aureon_cs8415_mask_get
1838 },
1839 {
1840 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
1841 .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, DEFAULT),
1842 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
1843 .info = aureon_cs8415_spdif_info,
1844 .get = aureon_cs8415_spdif_get
1845 },
1846 {
1847 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
1848 .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, NONE) "Rate",
1849 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
1850 .info = aureon_cs8415_rate_info,
1851 .get = aureon_cs8415_rate_get
1852 }
1853 };
1854
1855 static int aureon_add_controls(struct snd_ice1712 *ice)
1856 {
1857 unsigned int i, counts;
1858 int err;
1859
1860 counts = ARRAY_SIZE(aureon_dac_controls);
1861 if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON51_SKY)
1862 counts -= 2;
1863 for (i = 0; i < counts; i++) {
1864 err = snd_ctl_add(ice->card, snd_ctl_new1(&aureon_dac_controls[i], ice));
1865 if (err < 0)
1866 return err;
1867 }
1868
1869 for (i = 0; i < ARRAY_SIZE(wm_controls); i++) {
1870 err = snd_ctl_add(ice->card, snd_ctl_new1(&wm_controls[i], ice));
1871 if (err < 0)
1872 return err;
1873 }
1874
1875 if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON71_UNIVERSE) {
1876 for (i = 0; i < ARRAY_SIZE(universe_ac97_controls); i++) {
1877 err = snd_ctl_add(ice->card, snd_ctl_new1(&universe_ac97_controls[i], ice));
1878 if (err < 0)
1879 return err;
1880 }
1881 } else if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT &&
1882 ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71XT) {
1883 for (i = 0; i < ARRAY_SIZE(ac97_controls); i++) {
1884 err = snd_ctl_add(ice->card, snd_ctl_new1(&ac97_controls[i], ice));
1885 if (err < 0)
1886 return err;
1887 }
1888 }
1889
1890 if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT &&
1891 ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71XT) {
1892 unsigned char id;
1893 snd_ice1712_save_gpio_status(ice);
1894 id = aureon_cs8415_get(ice, CS8415_ID);
1895 if (id != 0x41)
1896 dev_info(ice->card->dev,
1897 "No CS8415 chip. Skipping CS8415 controls.\n");
1898 else if ((id & 0x0F) != 0x01)
1899 dev_info(ice->card->dev,
1900 "Detected unsupported CS8415 rev. (%c)\n",
1901 (char)((id & 0x0F) + 'A' - 1));
1902 else {
1903 for (i = 0; i < ARRAY_SIZE(cs8415_controls); i++) {
1904 struct snd_kcontrol *kctl;
1905 err = snd_ctl_add(ice->card, (kctl = snd_ctl_new1(&cs8415_controls[i], ice)));
1906 if (err < 0)
1907 return err;
1908 if (i > 1)
1909 kctl->id.device = ice->pcm->device;
1910 }
1911 }
1912 snd_ice1712_restore_gpio_status(ice);
1913 }
1914
1915 return 0;
1916 }
1917
1918
1919
1920
1921 static int aureon_reset(struct snd_ice1712 *ice)
1922 {
1923 static const unsigned short wm_inits_aureon[] = {
1924
1925 0x1b, 0x044,
1926 0x1c, 0x00B,
1927 0x1d, 0x009,
1928
1929 0x18, 0x000,
1930
1931 0x16, 0x122,
1932 0x17, 0x022,
1933 0x00, 0,
1934 0x01, 0,
1935 0x02, 0,
1936 0x03, 0,
1937 0x04, 0,
1938 0x05, 0,
1939 0x06, 0,
1940 0x07, 0,
1941 0x08, 0x100,
1942 0x09, 0xff,
1943 0x0a, 0xff,
1944 0x0b, 0xff,
1945 0x0c, 0xff,
1946 0x0d, 0xff,
1947 0x0e, 0xff,
1948 0x0f, 0xff,
1949 0x10, 0xff,
1950 0x11, 0x1ff,
1951 0x12, 0x000,
1952 0x13, 0x090,
1953 0x14, 0x000,
1954 0x15, 0x000,
1955 0x19, 0x000,
1956 0x1a, 0x000,
1957 (unsigned short)-1
1958 };
1959 static const unsigned short wm_inits_prodigy[] = {
1960
1961
1962 0x1b, 0x000,
1963 0x1c, 0x009,
1964 0x1d, 0x009,
1965
1966 0x18, 0x000,
1967
1968 0x16, 0x022,
1969 0x17, 0x006,
1970
1971 0x00, 0,
1972 0x01, 0,
1973 0x02, 0,
1974 0x03, 0,
1975 0x04, 0,
1976 0x05, 0,
1977 0x06, 0,
1978 0x07, 0,
1979 0x08, 0x100,
1980
1981 0x09, 0x7f,
1982 0x0a, 0x7f,
1983 0x0b, 0x7f,
1984 0x0c, 0x7f,
1985 0x0d, 0x7f,
1986 0x0e, 0x7f,
1987 0x0f, 0x7f,
1988 0x10, 0x7f,
1989 0x11, 0x1FF,
1990
1991 0x12, 0x000,
1992 0x13, 0x090,
1993 0x14, 0x000,
1994 0x15, 0x000,
1995
1996 0x19, 0x000,
1997 0x1a, 0x000,
1998 (unsigned short)-1
1999
2000 };
2001 static const unsigned short cs_inits[] = {
2002 0x0441,
2003 0x0180,
2004 0x0201,
2005 0x0605,
2006 (unsigned short)-1
2007 };
2008 unsigned int tmp;
2009 const unsigned short *p;
2010 int err;
2011 struct aureon_spec *spec = ice->spec;
2012
2013 err = aureon_ac97_init(ice);
2014 if (err != 0)
2015 return err;
2016
2017 snd_ice1712_gpio_set_dir(ice, 0x5fffff);
2018
2019
2020 snd_ice1712_save_gpio_status(ice);
2021 snd_ice1712_gpio_set_mask(ice, ~(AUREON_WM_RESET|AUREON_WM_CS|AUREON_CS8415_CS|AUREON_HP_SEL));
2022
2023 tmp = snd_ice1712_gpio_read(ice);
2024 tmp &= ~AUREON_WM_RESET;
2025 snd_ice1712_gpio_write(ice, tmp);
2026 udelay(1);
2027 tmp |= AUREON_WM_CS | AUREON_CS8415_CS;
2028 snd_ice1712_gpio_write(ice, tmp);
2029 udelay(1);
2030 tmp |= AUREON_WM_RESET;
2031 snd_ice1712_gpio_write(ice, tmp);
2032 udelay(1);
2033
2034
2035 if (ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71 ||
2036 ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71LT ||
2037 ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71XT)
2038 p = wm_inits_prodigy;
2039 else
2040 p = wm_inits_aureon;
2041 for (; *p != (unsigned short)-1; p += 2)
2042 wm_put(ice, p[0], p[1]);
2043
2044
2045 if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT &&
2046 ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71XT) {
2047 for (p = cs_inits; *p != (unsigned short)-1; p++)
2048 aureon_spi_write(ice, AUREON_CS8415_CS, *p | 0x200000, 24);
2049 spec->cs8415_mux = 1;
2050
2051 aureon_set_headphone_amp(ice, 1);
2052 }
2053
2054 snd_ice1712_restore_gpio_status(ice);
2055
2056
2057 aureon_pca9554_write(ice, PCA9554_DIR, 0x00);
2058 aureon_pca9554_write(ice, PCA9554_OUT, 0x00);
2059 return 0;
2060 }
2061
2062
2063
2064
2065 #ifdef CONFIG_PM_SLEEP
2066 static int aureon_resume(struct snd_ice1712 *ice)
2067 {
2068 struct aureon_spec *spec = ice->spec;
2069 int err, i;
2070
2071 err = aureon_reset(ice);
2072 if (err != 0)
2073 return err;
2074
2075
2076
2077 for (i = 0; i < ice->num_total_dacs; i++)
2078 wm_set_vol(ice, i, spec->vol[i], spec->master[i % 2]);
2079 return 0;
2080 }
2081 #endif
2082
2083
2084
2085
2086 static int aureon_init(struct snd_ice1712 *ice)
2087 {
2088 struct aureon_spec *spec;
2089 int i, err;
2090
2091 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
2092 if (!spec)
2093 return -ENOMEM;
2094 ice->spec = spec;
2095
2096 if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON51_SKY) {
2097 ice->num_total_dacs = 6;
2098 ice->num_total_adcs = 2;
2099 } else {
2100
2101 ice->num_total_dacs = 8;
2102 ice->num_total_adcs = 2;
2103 }
2104
2105
2106 ice->akm = kzalloc(sizeof(struct snd_akm4xxx), GFP_KERNEL);
2107 if (!ice->akm)
2108 return -ENOMEM;
2109 ice->akm_codecs = 1;
2110
2111 err = aureon_reset(ice);
2112 if (err != 0)
2113 return err;
2114
2115 spec->master[0] = WM_VOL_MUTE;
2116 spec->master[1] = WM_VOL_MUTE;
2117 for (i = 0; i < ice->num_total_dacs; i++) {
2118 spec->vol[i] = WM_VOL_MUTE;
2119 wm_set_vol(ice, i, spec->vol[i], spec->master[i % 2]);
2120 }
2121
2122 #ifdef CONFIG_PM_SLEEP
2123 ice->pm_resume = aureon_resume;
2124 ice->pm_suspend_enabled = 1;
2125 #endif
2126
2127 return 0;
2128 }
2129
2130
2131
2132
2133
2134
2135
2136 static const unsigned char aureon51_eeprom[] = {
2137 [ICE_EEP2_SYSCONF] = 0x0a,
2138 [ICE_EEP2_ACLINK] = 0x80,
2139 [ICE_EEP2_I2S] = 0xfc,
2140 [ICE_EEP2_SPDIF] = 0xc3,
2141 [ICE_EEP2_GPIO_DIR] = 0xff,
2142 [ICE_EEP2_GPIO_DIR1] = 0xff,
2143 [ICE_EEP2_GPIO_DIR2] = 0x5f,
2144 [ICE_EEP2_GPIO_MASK] = 0x00,
2145 [ICE_EEP2_GPIO_MASK1] = 0x00,
2146 [ICE_EEP2_GPIO_MASK2] = 0x00,
2147 [ICE_EEP2_GPIO_STATE] = 0x00,
2148 [ICE_EEP2_GPIO_STATE1] = 0x00,
2149 [ICE_EEP2_GPIO_STATE2] = 0x00,
2150 };
2151
2152 static const unsigned char aureon71_eeprom[] = {
2153 [ICE_EEP2_SYSCONF] = 0x0b,
2154 [ICE_EEP2_ACLINK] = 0x80,
2155 [ICE_EEP2_I2S] = 0xfc,
2156 [ICE_EEP2_SPDIF] = 0xc3,
2157 [ICE_EEP2_GPIO_DIR] = 0xff,
2158 [ICE_EEP2_GPIO_DIR1] = 0xff,
2159 [ICE_EEP2_GPIO_DIR2] = 0x5f,
2160 [ICE_EEP2_GPIO_MASK] = 0x00,
2161 [ICE_EEP2_GPIO_MASK1] = 0x00,
2162 [ICE_EEP2_GPIO_MASK2] = 0x00,
2163 [ICE_EEP2_GPIO_STATE] = 0x00,
2164 [ICE_EEP2_GPIO_STATE1] = 0x00,
2165 [ICE_EEP2_GPIO_STATE2] = 0x00,
2166 };
2167 #define prodigy71_eeprom aureon71_eeprom
2168
2169 static const unsigned char aureon71_universe_eeprom[] = {
2170 [ICE_EEP2_SYSCONF] = 0x2b,
2171
2172
2173 [ICE_EEP2_ACLINK] = 0x80,
2174 [ICE_EEP2_I2S] = 0xfc,
2175 [ICE_EEP2_SPDIF] = 0xc3,
2176 [ICE_EEP2_GPIO_DIR] = 0xff,
2177 [ICE_EEP2_GPIO_DIR1] = 0xff,
2178 [ICE_EEP2_GPIO_DIR2] = 0x5f,
2179 [ICE_EEP2_GPIO_MASK] = 0x00,
2180 [ICE_EEP2_GPIO_MASK1] = 0x00,
2181 [ICE_EEP2_GPIO_MASK2] = 0x00,
2182 [ICE_EEP2_GPIO_STATE] = 0x00,
2183 [ICE_EEP2_GPIO_STATE1] = 0x00,
2184 [ICE_EEP2_GPIO_STATE2] = 0x00,
2185 };
2186
2187 static const unsigned char prodigy71lt_eeprom[] = {
2188 [ICE_EEP2_SYSCONF] = 0x4b,
2189 [ICE_EEP2_ACLINK] = 0x80,
2190 [ICE_EEP2_I2S] = 0xfc,
2191 [ICE_EEP2_SPDIF] = 0xc3,
2192 [ICE_EEP2_GPIO_DIR] = 0xff,
2193 [ICE_EEP2_GPIO_DIR1] = 0xff,
2194 [ICE_EEP2_GPIO_DIR2] = 0x5f,
2195 [ICE_EEP2_GPIO_MASK] = 0x00,
2196 [ICE_EEP2_GPIO_MASK1] = 0x00,
2197 [ICE_EEP2_GPIO_MASK2] = 0x00,
2198 [ICE_EEP2_GPIO_STATE] = 0x00,
2199 [ICE_EEP2_GPIO_STATE1] = 0x00,
2200 [ICE_EEP2_GPIO_STATE2] = 0x00,
2201 };
2202 #define prodigy71xt_eeprom prodigy71lt_eeprom
2203
2204
2205 struct snd_ice1712_card_info snd_vt1724_aureon_cards[] = {
2206 {
2207 .subvendor = VT1724_SUBDEVICE_AUREON51_SKY,
2208 .name = "Terratec Aureon 5.1-Sky",
2209 .model = "aureon51",
2210 .chip_init = aureon_init,
2211 .build_controls = aureon_add_controls,
2212 .eeprom_size = sizeof(aureon51_eeprom),
2213 .eeprom_data = aureon51_eeprom,
2214 .driver = "Aureon51",
2215 },
2216 {
2217 .subvendor = VT1724_SUBDEVICE_AUREON71_SPACE,
2218 .name = "Terratec Aureon 7.1-Space",
2219 .model = "aureon71",
2220 .chip_init = aureon_init,
2221 .build_controls = aureon_add_controls,
2222 .eeprom_size = sizeof(aureon71_eeprom),
2223 .eeprom_data = aureon71_eeprom,
2224 .driver = "Aureon71",
2225 },
2226 {
2227 .subvendor = VT1724_SUBDEVICE_AUREON71_UNIVERSE,
2228 .name = "Terratec Aureon 7.1-Universe",
2229 .model = "universe",
2230 .chip_init = aureon_init,
2231 .build_controls = aureon_add_controls,
2232 .eeprom_size = sizeof(aureon71_universe_eeprom),
2233 .eeprom_data = aureon71_universe_eeprom,
2234 .driver = "Aureon71Univ",
2235 },
2236 {
2237 .subvendor = VT1724_SUBDEVICE_PRODIGY71,
2238 .name = "Audiotrak Prodigy 7.1",
2239 .model = "prodigy71",
2240 .chip_init = aureon_init,
2241 .build_controls = aureon_add_controls,
2242 .eeprom_size = sizeof(prodigy71_eeprom),
2243 .eeprom_data = prodigy71_eeprom,
2244 .driver = "Prodigy71",
2245 },
2246 {
2247 .subvendor = VT1724_SUBDEVICE_PRODIGY71LT,
2248 .name = "Audiotrak Prodigy 7.1 LT",
2249 .model = "prodigy71lt",
2250 .chip_init = aureon_init,
2251 .build_controls = aureon_add_controls,
2252 .eeprom_size = sizeof(prodigy71lt_eeprom),
2253 .eeprom_data = prodigy71lt_eeprom,
2254 .driver = "Prodigy71LT",
2255 },
2256 {
2257 .subvendor = VT1724_SUBDEVICE_PRODIGY71XT,
2258 .name = "Audiotrak Prodigy 7.1 XT",
2259 .model = "prodigy71xt",
2260 .chip_init = aureon_init,
2261 .build_controls = aureon_add_controls,
2262 .eeprom_size = sizeof(prodigy71xt_eeprom),
2263 .eeprom_data = prodigy71xt_eeprom,
2264 .driver = "Prodigy71LT",
2265 },
2266 { }
2267 };