0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include <linux/delay.h>
0012 #include <linux/interrupt.h>
0013 #include <linux/init.h>
0014 #include <linux/slab.h>
0015 #include <sound/core.h>
0016 #include <sound/tlv.h>
0017
0018 #include "ice1712.h"
0019 #include "envy24ht.h"
0020 #include "se.h"
0021
0022 struct se_spec {
0023 struct {
0024 unsigned char ch1, ch2;
0025 } vol[8];
0026 };
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093
0094
0095
0096
0097
0098
0099
0100
0101
0102 static void se200pci_WM8740_init(struct snd_ice1712 *ice)
0103 {
0104
0105 }
0106
0107
0108 static void se200pci_WM8740_set_pro_rate(struct snd_ice1712 *ice,
0109 unsigned int rate)
0110 {
0111
0112 }
0113
0114
0115
0116
0117
0118
0119 static void se200pci_WM8766_write(struct snd_ice1712 *ice,
0120 unsigned int addr, unsigned int data)
0121 {
0122 unsigned int st;
0123 unsigned int bits;
0124 int i;
0125 const unsigned int DATA = 0x010000;
0126 const unsigned int CLOCK = 0x020000;
0127 const unsigned int LOAD = 0x040000;
0128 const unsigned int ALL_MASK = (DATA | CLOCK | LOAD);
0129
0130 snd_ice1712_save_gpio_status(ice);
0131
0132 st = ((addr & 0x7f) << 9) | (data & 0x1ff);
0133 snd_ice1712_gpio_set_dir(ice, ice->gpio.direction | ALL_MASK);
0134 snd_ice1712_gpio_set_mask(ice, ice->gpio.write_mask & ~ALL_MASK);
0135 bits = snd_ice1712_gpio_read(ice) & ~ALL_MASK;
0136
0137 snd_ice1712_gpio_write(ice, bits);
0138 for (i = 0; i < 16; i++) {
0139 udelay(1);
0140 bits &= ~CLOCK;
0141 st = (st << 1);
0142 if (st & 0x10000)
0143 bits |= DATA;
0144 else
0145 bits &= ~DATA;
0146
0147 snd_ice1712_gpio_write(ice, bits);
0148
0149 udelay(1);
0150 bits |= CLOCK;
0151 snd_ice1712_gpio_write(ice, bits);
0152 }
0153
0154 udelay(1);
0155 bits |= LOAD;
0156 snd_ice1712_gpio_write(ice, bits);
0157
0158 udelay(1);
0159 bits |= (DATA | CLOCK);
0160 snd_ice1712_gpio_write(ice, bits);
0161
0162 snd_ice1712_restore_gpio_status(ice);
0163 }
0164
0165 static void se200pci_WM8766_set_volume(struct snd_ice1712 *ice, int ch,
0166 unsigned int vol1, unsigned int vol2)
0167 {
0168 switch (ch) {
0169 case 0:
0170 se200pci_WM8766_write(ice, 0x000, vol1);
0171 se200pci_WM8766_write(ice, 0x001, vol2 | 0x100);
0172 break;
0173 case 1:
0174 se200pci_WM8766_write(ice, 0x004, vol1);
0175 se200pci_WM8766_write(ice, 0x005, vol2 | 0x100);
0176 break;
0177 case 2:
0178 se200pci_WM8766_write(ice, 0x006, vol1);
0179 se200pci_WM8766_write(ice, 0x007, vol2 | 0x100);
0180 break;
0181 }
0182 }
0183
0184 static void se200pci_WM8766_init(struct snd_ice1712 *ice)
0185 {
0186 se200pci_WM8766_write(ice, 0x1f, 0x000);
0187 udelay(10);
0188
0189 se200pci_WM8766_set_volume(ice, 0, 0, 0);
0190 se200pci_WM8766_set_volume(ice, 1, 0, 0);
0191 se200pci_WM8766_set_volume(ice, 2, 0, 0);
0192
0193 se200pci_WM8766_write(ice, 0x03, 0x022);
0194 se200pci_WM8766_write(ice, 0x0a, 0x080);
0195 se200pci_WM8766_write(ice, 0x12, 0x000);
0196 se200pci_WM8766_write(ice, 0x15, 0x000);
0197 se200pci_WM8766_write(ice, 0x09, 0x000);
0198
0199 se200pci_WM8766_write(ice, 0x02, 0x124);
0200 se200pci_WM8766_write(ice, 0x02, 0x120);
0201 }
0202
0203 static void se200pci_WM8766_set_pro_rate(struct snd_ice1712 *ice,
0204 unsigned int rate)
0205 {
0206 if (rate > 96000)
0207 se200pci_WM8766_write(ice, 0x0a, 0x000);
0208 else
0209 se200pci_WM8766_write(ice, 0x0a, 0x080);
0210 }
0211
0212
0213
0214
0215
0216
0217 static void se200pci_WM8776_write(struct snd_ice1712 *ice,
0218 unsigned int addr, unsigned int data)
0219 {
0220 unsigned int val;
0221
0222 val = (addr << 9) | data;
0223 snd_vt1724_write_i2c(ice, 0x34, val >> 8, val & 0xff);
0224 }
0225
0226
0227 static void se200pci_WM8776_set_output_volume(struct snd_ice1712 *ice,
0228 unsigned int vol1, unsigned int vol2)
0229 {
0230 se200pci_WM8776_write(ice, 0x03, vol1);
0231 se200pci_WM8776_write(ice, 0x04, vol2 | 0x100);
0232 }
0233
0234 static void se200pci_WM8776_set_input_volume(struct snd_ice1712 *ice,
0235 unsigned int vol1, unsigned int vol2)
0236 {
0237 se200pci_WM8776_write(ice, 0x0e, vol1);
0238 se200pci_WM8776_write(ice, 0x0f, vol2 | 0x100);
0239 }
0240
0241 static const char * const se200pci_sel[] = {
0242 "LINE-IN", "CD-IN", "MIC-IN", "ALL-MIX", NULL
0243 };
0244
0245 static void se200pci_WM8776_set_input_selector(struct snd_ice1712 *ice,
0246 unsigned int sel)
0247 {
0248 static const unsigned char vals[] = {
0249
0250 0x10, 0x04, 0x08, 0x1c, 0x03
0251 };
0252 if (sel > 4)
0253 sel = 4;
0254 se200pci_WM8776_write(ice, 0x15, vals[sel]);
0255 }
0256
0257 static void se200pci_WM8776_set_afl(struct snd_ice1712 *ice, unsigned int afl)
0258 {
0259
0260 if (afl)
0261 se200pci_WM8776_write(ice, 0x16, 0x005);
0262 else
0263 se200pci_WM8776_write(ice, 0x16, 0x001);
0264 }
0265
0266 static const char * const se200pci_agc[] = {
0267 "Off", "LimiterMode", "ALCMode", NULL
0268 };
0269
0270 static void se200pci_WM8776_set_agc(struct snd_ice1712 *ice, unsigned int agc)
0271 {
0272
0273 switch (agc) {
0274 case 0:
0275 se200pci_WM8776_write(ice, 0x11, 0x000);
0276 break;
0277 case 1:
0278 se200pci_WM8776_write(ice, 0x10, 0x07b);
0279 se200pci_WM8776_write(ice, 0x11, 0x100);
0280 break;
0281 case 2:
0282 se200pci_WM8776_write(ice, 0x10, 0x1fb);
0283 se200pci_WM8776_write(ice, 0x11, 0x100);
0284 break;
0285 }
0286 }
0287
0288 static void se200pci_WM8776_init(struct snd_ice1712 *ice)
0289 {
0290 int i;
0291 static const unsigned short default_values[] = {
0292 0x100, 0x100, 0x100,
0293 0x100, 0x100, 0x100,
0294 0x000, 0x090, 0x000, 0x000,
0295 0x022, 0x022, 0x022,
0296 0x008, 0x0cf, 0x0cf, 0x07b, 0x000,
0297 0x032, 0x000, 0x0a6, 0x001, 0x001
0298 };
0299
0300 se200pci_WM8776_write(ice, 0x17, 0x000);
0301
0302
0303 udelay(10);
0304
0305 for (i = 0; i < ARRAY_SIZE(default_values); i++)
0306 se200pci_WM8776_write(ice, i, default_values[i]);
0307
0308 se200pci_WM8776_set_input_selector(ice, 0);
0309 se200pci_WM8776_set_afl(ice, 0);
0310 se200pci_WM8776_set_agc(ice, 0);
0311 se200pci_WM8776_set_input_volume(ice, 0, 0);
0312 se200pci_WM8776_set_output_volume(ice, 0, 0);
0313
0314
0315 se200pci_WM8776_write(ice, 0x00, 0);
0316 se200pci_WM8776_write(ice, 0x01, 0);
0317 se200pci_WM8776_write(ice, 0x02, 0x100);
0318 se200pci_WM8776_write(ice, 0x0d, 0x080);
0319 }
0320
0321 static void se200pci_WM8776_set_pro_rate(struct snd_ice1712 *ice,
0322 unsigned int rate)
0323 {
0324
0325 }
0326
0327
0328
0329
0330
0331
0332 static void se200pci_set_pro_rate(struct snd_ice1712 *ice, unsigned int rate)
0333 {
0334 se200pci_WM8740_set_pro_rate(ice, rate);
0335 se200pci_WM8766_set_pro_rate(ice, rate);
0336 se200pci_WM8776_set_pro_rate(ice, rate);
0337 }
0338
0339 struct se200pci_control {
0340 const char *name;
0341 enum {
0342 WM8766,
0343 WM8776in,
0344 WM8776out,
0345 WM8776sel,
0346 WM8776agc,
0347 WM8776afl
0348 } target;
0349 enum { VOLUME1, VOLUME2, BOOLEAN, ENUM } type;
0350 int ch;
0351 const char * const *member;
0352 const char *comment;
0353 };
0354
0355 static const struct se200pci_control se200pci_cont[] = {
0356 {
0357 .name = "Front Playback Volume",
0358 .target = WM8776out,
0359 .type = VOLUME1,
0360 .comment = "Front(green)"
0361 },
0362 {
0363 .name = "Side Playback Volume",
0364 .target = WM8766,
0365 .type = VOLUME1,
0366 .ch = 1,
0367 .comment = "Surround(orange)"
0368 },
0369 {
0370 .name = "Surround Playback Volume",
0371 .target = WM8766,
0372 .type = VOLUME1,
0373 .ch = 2,
0374 .comment = "SurroundBack(white)"
0375 },
0376 {
0377 .name = "CLFE Playback Volume",
0378 .target = WM8766,
0379 .type = VOLUME1,
0380 .ch = 0,
0381 .comment = "Center(Lch)&SubWoofer(Rch)(black)"
0382 },
0383 {
0384 .name = "Capture Volume",
0385 .target = WM8776in,
0386 .type = VOLUME2
0387 },
0388 {
0389 .name = "Capture Select",
0390 .target = WM8776sel,
0391 .type = ENUM,
0392 .member = se200pci_sel
0393 },
0394 {
0395 .name = "AGC Capture Mode",
0396 .target = WM8776agc,
0397 .type = ENUM,
0398 .member = se200pci_agc
0399 },
0400 {
0401 .name = "AFL Bypass Playback Switch",
0402 .target = WM8776afl,
0403 .type = BOOLEAN
0404 }
0405 };
0406
0407 static int se200pci_get_enum_count(int n)
0408 {
0409 const char * const *member;
0410 int c;
0411
0412 member = se200pci_cont[n].member;
0413 if (!member)
0414 return 0;
0415 for (c = 0; member[c]; c++)
0416 ;
0417 return c;
0418 }
0419
0420 static int se200pci_cont_volume_info(struct snd_kcontrol *kc,
0421 struct snd_ctl_elem_info *uinfo)
0422 {
0423 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
0424 uinfo->count = 2;
0425 uinfo->value.integer.min = 0;
0426 uinfo->value.integer.max = 0xff;
0427 return 0;
0428 }
0429
0430 #define se200pci_cont_boolean_info snd_ctl_boolean_mono_info
0431
0432 static int se200pci_cont_enum_info(struct snd_kcontrol *kc,
0433 struct snd_ctl_elem_info *uinfo)
0434 {
0435 int n, c;
0436
0437 n = kc->private_value;
0438 c = se200pci_get_enum_count(n);
0439 if (!c)
0440 return -EINVAL;
0441 return snd_ctl_enum_info(uinfo, 1, c, se200pci_cont[n].member);
0442 }
0443
0444 static int se200pci_cont_volume_get(struct snd_kcontrol *kc,
0445 struct snd_ctl_elem_value *uc)
0446 {
0447 struct snd_ice1712 *ice = snd_kcontrol_chip(kc);
0448 struct se_spec *spec = ice->spec;
0449 int n = kc->private_value;
0450 uc->value.integer.value[0] = spec->vol[n].ch1;
0451 uc->value.integer.value[1] = spec->vol[n].ch2;
0452 return 0;
0453 }
0454
0455 static int se200pci_cont_boolean_get(struct snd_kcontrol *kc,
0456 struct snd_ctl_elem_value *uc)
0457 {
0458 struct snd_ice1712 *ice = snd_kcontrol_chip(kc);
0459 struct se_spec *spec = ice->spec;
0460 int n = kc->private_value;
0461 uc->value.integer.value[0] = spec->vol[n].ch1;
0462 return 0;
0463 }
0464
0465 static int se200pci_cont_enum_get(struct snd_kcontrol *kc,
0466 struct snd_ctl_elem_value *uc)
0467 {
0468 struct snd_ice1712 *ice = snd_kcontrol_chip(kc);
0469 struct se_spec *spec = ice->spec;
0470 int n = kc->private_value;
0471 uc->value.enumerated.item[0] = spec->vol[n].ch1;
0472 return 0;
0473 }
0474
0475 static void se200pci_cont_update(struct snd_ice1712 *ice, int n)
0476 {
0477 struct se_spec *spec = ice->spec;
0478 switch (se200pci_cont[n].target) {
0479 case WM8766:
0480 se200pci_WM8766_set_volume(ice,
0481 se200pci_cont[n].ch,
0482 spec->vol[n].ch1,
0483 spec->vol[n].ch2);
0484 break;
0485
0486 case WM8776in:
0487 se200pci_WM8776_set_input_volume(ice,
0488 spec->vol[n].ch1,
0489 spec->vol[n].ch2);
0490 break;
0491
0492 case WM8776out:
0493 se200pci_WM8776_set_output_volume(ice,
0494 spec->vol[n].ch1,
0495 spec->vol[n].ch2);
0496 break;
0497
0498 case WM8776sel:
0499 se200pci_WM8776_set_input_selector(ice,
0500 spec->vol[n].ch1);
0501 break;
0502
0503 case WM8776agc:
0504 se200pci_WM8776_set_agc(ice, spec->vol[n].ch1);
0505 break;
0506
0507 case WM8776afl:
0508 se200pci_WM8776_set_afl(ice, spec->vol[n].ch1);
0509 break;
0510
0511 default:
0512 break;
0513 }
0514 }
0515
0516 static int se200pci_cont_volume_put(struct snd_kcontrol *kc,
0517 struct snd_ctl_elem_value *uc)
0518 {
0519 struct snd_ice1712 *ice = snd_kcontrol_chip(kc);
0520 struct se_spec *spec = ice->spec;
0521 int n = kc->private_value;
0522 unsigned int vol1, vol2;
0523 int changed;
0524
0525 changed = 0;
0526 vol1 = uc->value.integer.value[0] & 0xff;
0527 vol2 = uc->value.integer.value[1] & 0xff;
0528 if (spec->vol[n].ch1 != vol1) {
0529 spec->vol[n].ch1 = vol1;
0530 changed = 1;
0531 }
0532 if (spec->vol[n].ch2 != vol2) {
0533 spec->vol[n].ch2 = vol2;
0534 changed = 1;
0535 }
0536 if (changed)
0537 se200pci_cont_update(ice, n);
0538
0539 return changed;
0540 }
0541
0542 static int se200pci_cont_boolean_put(struct snd_kcontrol *kc,
0543 struct snd_ctl_elem_value *uc)
0544 {
0545 struct snd_ice1712 *ice = snd_kcontrol_chip(kc);
0546 struct se_spec *spec = ice->spec;
0547 int n = kc->private_value;
0548 unsigned int vol1;
0549
0550 vol1 = !!uc->value.integer.value[0];
0551 if (spec->vol[n].ch1 != vol1) {
0552 spec->vol[n].ch1 = vol1;
0553 se200pci_cont_update(ice, n);
0554 return 1;
0555 }
0556 return 0;
0557 }
0558
0559 static int se200pci_cont_enum_put(struct snd_kcontrol *kc,
0560 struct snd_ctl_elem_value *uc)
0561 {
0562 struct snd_ice1712 *ice = snd_kcontrol_chip(kc);
0563 struct se_spec *spec = ice->spec;
0564 int n = kc->private_value;
0565 unsigned int vol1;
0566
0567 vol1 = uc->value.enumerated.item[0];
0568 if (vol1 >= se200pci_get_enum_count(n))
0569 return -EINVAL;
0570 if (spec->vol[n].ch1 != vol1) {
0571 spec->vol[n].ch1 = vol1;
0572 se200pci_cont_update(ice, n);
0573 return 1;
0574 }
0575 return 0;
0576 }
0577
0578 static const DECLARE_TLV_DB_SCALE(db_scale_gain1, -12750, 50, 1);
0579 static const DECLARE_TLV_DB_SCALE(db_scale_gain2, -10350, 50, 1);
0580
0581 static int se200pci_add_controls(struct snd_ice1712 *ice)
0582 {
0583 int i;
0584 struct snd_kcontrol_new cont;
0585 int err;
0586
0587 memset(&cont, 0, sizeof(cont));
0588 cont.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
0589 for (i = 0; i < ARRAY_SIZE(se200pci_cont); i++) {
0590 cont.private_value = i;
0591 cont.name = se200pci_cont[i].name;
0592 cont.access = SNDRV_CTL_ELEM_ACCESS_READWRITE;
0593 cont.tlv.p = NULL;
0594 switch (se200pci_cont[i].type) {
0595 case VOLUME1:
0596 case VOLUME2:
0597 cont.info = se200pci_cont_volume_info;
0598 cont.get = se200pci_cont_volume_get;
0599 cont.put = se200pci_cont_volume_put;
0600 cont.access |= SNDRV_CTL_ELEM_ACCESS_TLV_READ;
0601 if (se200pci_cont[i].type == VOLUME1)
0602 cont.tlv.p = db_scale_gain1;
0603 else
0604 cont.tlv.p = db_scale_gain2;
0605 break;
0606 case BOOLEAN:
0607 cont.info = se200pci_cont_boolean_info;
0608 cont.get = se200pci_cont_boolean_get;
0609 cont.put = se200pci_cont_boolean_put;
0610 break;
0611 case ENUM:
0612 cont.info = se200pci_cont_enum_info;
0613 cont.get = se200pci_cont_enum_get;
0614 cont.put = se200pci_cont_enum_put;
0615 break;
0616 default:
0617 snd_BUG();
0618 return -EINVAL;
0619 }
0620 err = snd_ctl_add(ice->card, snd_ctl_new1(&cont, ice));
0621 if (err < 0)
0622 return err;
0623 }
0624
0625 return 0;
0626 }
0627
0628
0629
0630
0631
0632
0633
0634
0635
0636
0637
0638
0639
0640
0641
0642
0643
0644
0645
0646
0647
0648
0649
0650
0651
0652
0653
0654
0655
0656
0657
0658
0659 static int se_init(struct snd_ice1712 *ice)
0660 {
0661 struct se_spec *spec;
0662
0663 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
0664 if (!spec)
0665 return -ENOMEM;
0666 ice->spec = spec;
0667
0668 if (ice->eeprom.subvendor == VT1724_SUBDEVICE_SE90PCI) {
0669 ice->num_total_dacs = 2;
0670 ice->num_total_adcs = 0;
0671 ice->vt1720 = 1;
0672 return 0;
0673
0674 } else if (ice->eeprom.subvendor == VT1724_SUBDEVICE_SE200PCI) {
0675 ice->num_total_dacs = 8;
0676 ice->num_total_adcs = 2;
0677 se200pci_WM8740_init(ice);
0678 se200pci_WM8766_init(ice);
0679 se200pci_WM8776_init(ice);
0680 ice->gpio.set_pro_rate = se200pci_set_pro_rate;
0681 return 0;
0682 }
0683
0684 return -ENOENT;
0685 }
0686
0687 static int se_add_controls(struct snd_ice1712 *ice)
0688 {
0689 int err;
0690
0691 err = 0;
0692
0693 if (ice->eeprom.subvendor == VT1724_SUBDEVICE_SE200PCI)
0694 err = se200pci_add_controls(ice);
0695
0696 return err;
0697 }
0698
0699
0700
0701
0702
0703
0704 static const unsigned char se200pci_eeprom[] = {
0705 [ICE_EEP2_SYSCONF] = 0x4b,
0706 [ICE_EEP2_ACLINK] = 0x80,
0707 [ICE_EEP2_I2S] = 0x78,
0708 [ICE_EEP2_SPDIF] = 0xc3,
0709
0710 [ICE_EEP2_GPIO_DIR] = 0x02,
0711 [ICE_EEP2_GPIO_DIR1] = 0x00,
0712 [ICE_EEP2_GPIO_DIR2] = 0x07,
0713
0714 [ICE_EEP2_GPIO_MASK] = 0x00,
0715 [ICE_EEP2_GPIO_MASK1] = 0x00,
0716 [ICE_EEP2_GPIO_MASK2] = 0x00,
0717
0718 [ICE_EEP2_GPIO_STATE] = 0x00,
0719 [ICE_EEP2_GPIO_STATE1] = 0x00,
0720 [ICE_EEP2_GPIO_STATE2] = 0x07,
0721 };
0722
0723 static const unsigned char se90pci_eeprom[] = {
0724 [ICE_EEP2_SYSCONF] = 0x4b,
0725 [ICE_EEP2_ACLINK] = 0x80,
0726 [ICE_EEP2_I2S] = 0x78,
0727 [ICE_EEP2_SPDIF] = 0xc3,
0728
0729
0730 };
0731
0732 struct snd_ice1712_card_info snd_vt1724_se_cards[] = {
0733 {
0734 .subvendor = VT1724_SUBDEVICE_SE200PCI,
0735 .name = "ONKYO SE200PCI",
0736 .model = "se200pci",
0737 .chip_init = se_init,
0738 .build_controls = se_add_controls,
0739 .eeprom_size = sizeof(se200pci_eeprom),
0740 .eeprom_data = se200pci_eeprom,
0741 },
0742 {
0743 .subvendor = VT1724_SUBDEVICE_SE90PCI,
0744 .name = "ONKYO SE90PCI",
0745 .model = "se90pci",
0746 .chip_init = se_init,
0747 .build_controls = se_add_controls,
0748 .eeprom_size = sizeof(se90pci_eeprom),
0749 .eeprom_data = se90pci_eeprom,
0750 },
0751 {}
0752 };