diff options
author | James Courtier-Dutton <James@superbug.co.uk> | 2005-12-04 12:03:03 -0500 |
---|---|---|
committer | Jaroslav Kysela <perex@suse.cz> | 2006-01-03 06:30:15 -0500 |
commit | 19b99fbaed2e2971b756311435c67e84431d8515 (patch) | |
tree | 78f0c968f8bed1a5ce82edd00d793be6f3a73d4c /sound/pci/emu10k1/emu10k1_main.c | |
parent | 481ba7727fa08deb389b5a2e550e04df24d3f37d (diff) |
[ALSA] emu10k1: Partial support for Creative emu1212m
Modules: EMU10K1/EMU10K2 driver
Distorted sound now comes from the Audio Out socket. Still more work to do.
Signed-off-by: James Courtier-Dutton <James@superbug.co.uk>
Diffstat (limited to 'sound/pci/emu10k1/emu10k1_main.c')
-rw-r--r-- | sound/pci/emu10k1/emu10k1_main.c | 150 |
1 files changed, 146 insertions, 4 deletions
diff --git a/sound/pci/emu10k1/emu10k1_main.c b/sound/pci/emu10k1/emu10k1_main.c index 175f8aac8de5..f6cf589593b9 100644 --- a/sound/pci/emu10k1/emu10k1_main.c +++ b/sound/pci/emu10k1/emu10k1_main.c | |||
@@ -42,6 +42,7 @@ | |||
42 | #include "p16v.h" | 42 | #include "p16v.h" |
43 | #include "tina2.h" | 43 | #include "tina2.h" |
44 | 44 | ||
45 | |||
45 | /************************************************************************* | 46 | /************************************************************************* |
46 | * EMU10K1 init / done | 47 | * EMU10K1 init / done |
47 | *************************************************************************/ | 48 | *************************************************************************/ |
@@ -217,7 +218,9 @@ static int snd_emu10k1_init(struct snd_emu10k1 *emu, int enable_ir, int resume) | |||
217 | outl(HCFG_LOCKTANKCACHE_MASK | HCFG_AUTOMUTE | HCFG_JOYENABLE, emu->port + HCFG); | 218 | outl(HCFG_LOCKTANKCACHE_MASK | HCFG_AUTOMUTE | HCFG_JOYENABLE, emu->port + HCFG); |
218 | 219 | ||
219 | if (enable_ir) { /* enable IR for SB Live */ | 220 | if (enable_ir) { /* enable IR for SB Live */ |
220 | if (emu->audigy) { | 221 | if ( emu->card_capabilities->emu1212m) { |
222 | ; /* Disable all access to A_IOCFG for the emu1212m */ | ||
223 | } else if (emu->audigy) { | ||
221 | unsigned int reg = inl(emu->port + A_IOCFG); | 224 | unsigned int reg = inl(emu->port + A_IOCFG); |
222 | outl(reg | A_IOCFG_GPOUT2, emu->port + A_IOCFG); | 225 | outl(reg | A_IOCFG_GPOUT2, emu->port + A_IOCFG); |
223 | udelay(500); | 226 | udelay(500); |
@@ -234,7 +237,9 @@ static int snd_emu10k1_init(struct snd_emu10k1 *emu, int enable_ir, int resume) | |||
234 | } | 237 | } |
235 | } | 238 | } |
236 | 239 | ||
237 | if (emu->audigy) { /* enable analog output */ | 240 | if ( emu->card_capabilities->emu1212m) { |
241 | ; /* Disable all access to A_IOCFG for the emu1212m */ | ||
242 | } else if (emu->audigy) { /* enable analog output */ | ||
238 | unsigned int reg = inl(emu->port + A_IOCFG); | 243 | unsigned int reg = inl(emu->port + A_IOCFG); |
239 | outl(reg | A_IOCFG_GPOUT0, emu->port + A_IOCFG); | 244 | outl(reg | A_IOCFG_GPOUT0, emu->port + A_IOCFG); |
240 | } | 245 | } |
@@ -250,7 +255,9 @@ static void snd_emu10k1_audio_enable(struct snd_emu10k1 *emu) | |||
250 | outl(inl(emu->port + HCFG) | HCFG_AUDIOENABLE, emu->port + HCFG); | 255 | outl(inl(emu->port + HCFG) | HCFG_AUDIOENABLE, emu->port + HCFG); |
251 | 256 | ||
252 | /* Enable analog/digital outs on audigy */ | 257 | /* Enable analog/digital outs on audigy */ |
253 | if (emu->audigy) { | 258 | if ( emu->card_capabilities->emu1212m) { |
259 | ; /* Disable all access to A_IOCFG for the emu1212m */ | ||
260 | } else if (emu->audigy) { | ||
254 | outl(inl(emu->port + A_IOCFG) & ~0x44, emu->port + A_IOCFG); | 261 | outl(inl(emu->port + A_IOCFG) & ~0x44, emu->port + A_IOCFG); |
255 | 262 | ||
256 | if (emu->card_capabilities->ca0151_chip) { /* audigy2 */ | 263 | if (emu->card_capabilities->ca0151_chip) { /* audigy2 */ |
@@ -542,6 +549,136 @@ static int __devinit snd_emu10k1_cardbus_init(struct snd_emu10k1 * emu) | |||
542 | return 0; | 549 | return 0; |
543 | } | 550 | } |
544 | 551 | ||
552 | static int snd_emu1212m_fpga_write(struct snd_emu10k1 * emu, int reg, int value) | ||
553 | { | ||
554 | if (reg<0 || reg>0x3f) | ||
555 | return 1; | ||
556 | reg+=0x40; /* 0x40 upwards are registers. */ | ||
557 | if (value<0 || value>0x3f) /* 0 to 0x3f are values */ | ||
558 | return 1; | ||
559 | outl(reg, emu->port + A_IOCFG); | ||
560 | outl(reg | 0x80, emu->port + A_IOCFG); /* High bit clocks the value into the fpga. */ | ||
561 | outl(value, emu->port + A_IOCFG); | ||
562 | outl(value | 0x80 , emu->port + A_IOCFG); /* High bit clocks the value into the fpga. */ | ||
563 | |||
564 | return 0; | ||
565 | } | ||
566 | |||
567 | static int snd_emu1212m_fpga_read(struct snd_emu10k1 * emu, int reg, int *value) | ||
568 | { | ||
569 | if (reg<0 || reg>0x3f) | ||
570 | return 1; | ||
571 | reg+=0x40; /* 0x40 upwards are registers. */ | ||
572 | outl(reg, emu->port + A_IOCFG); | ||
573 | outl(reg | 0x80, emu->port + A_IOCFG); /* High bit clocks the value into the fpga. */ | ||
574 | *value = inl(emu->port + A_IOCFG); | ||
575 | |||
576 | return 0; | ||
577 | } | ||
578 | |||
579 | static int snd_emu1212m_fpga_netlist_write(struct snd_emu10k1 * emu, int reg, int value) | ||
580 | { | ||
581 | snd_emu1212m_fpga_write(emu, 0x00, ((reg >> 8) & 0x3f) ); | ||
582 | snd_emu1212m_fpga_write(emu, 0x01, (reg & 0x3f) ); | ||
583 | snd_emu1212m_fpga_write(emu, 0x02, ((value >> 8) & 0x3f) ); | ||
584 | snd_emu1212m_fpga_write(emu, 0x03, (value & 0x3f) ); | ||
585 | |||
586 | return 0; | ||
587 | } | ||
588 | |||
589 | static int __devinit snd_emu10k1_emu1212m_init(struct snd_emu10k1 * emu) | ||
590 | { | ||
591 | unsigned int i; | ||
592 | int tmp; | ||
593 | |||
594 | snd_printk(KERN_ERR "emu1212m: Special config.\n"); | ||
595 | outl(0x0005a00c, emu->port + HCFG); | ||
596 | outl(0x0005a004, emu->port + HCFG); | ||
597 | outl(0x0005a000, emu->port + HCFG); | ||
598 | outl(0x0005a000, emu->port + HCFG); | ||
599 | |||
600 | snd_emu1212m_fpga_read(emu, 0x22, &tmp ); | ||
601 | snd_emu1212m_fpga_read(emu, 0x23, &tmp ); | ||
602 | snd_emu1212m_fpga_read(emu, 0x24, &tmp ); | ||
603 | snd_emu1212m_fpga_write(emu, 0x04, 0x01 ); | ||
604 | snd_emu1212m_fpga_read(emu, 0x0b, &tmp ); | ||
605 | snd_emu1212m_fpga_write(emu, 0x0b, 0x01 ); | ||
606 | snd_emu1212m_fpga_read(emu, 0x10, &tmp ); | ||
607 | snd_emu1212m_fpga_write(emu, 0x10, 0x00 ); | ||
608 | snd_emu1212m_fpga_read(emu, 0x11, &tmp ); | ||
609 | snd_emu1212m_fpga_write(emu, 0x11, 0x30 ); | ||
610 | snd_emu1212m_fpga_read(emu, 0x13, &tmp ); | ||
611 | snd_emu1212m_fpga_write(emu, 0x13, 0x0f ); | ||
612 | snd_emu1212m_fpga_read(emu, 0x11, &tmp ); | ||
613 | snd_emu1212m_fpga_write(emu, 0x11, 0x30 ); | ||
614 | snd_emu1212m_fpga_read(emu, 0x0a, &tmp ); | ||
615 | snd_emu1212m_fpga_write(emu, 0x0a, 0x10 ); | ||
616 | snd_emu1212m_fpga_write(emu, 0x0c, 0x19 ); | ||
617 | snd_emu1212m_fpga_write(emu, 0x12, 0x0c ); | ||
618 | snd_emu1212m_fpga_write(emu, 0x09, 0x0f ); | ||
619 | snd_emu1212m_fpga_write(emu, 0x06, 0x00 ); | ||
620 | snd_emu1212m_fpga_write(emu, 0x05, 0x00 ); | ||
621 | snd_emu1212m_fpga_write(emu, 0x0e, 0x12 ); | ||
622 | snd_emu1212m_fpga_netlist_write(emu, 0x0000, 0x0200); | ||
623 | snd_emu1212m_fpga_netlist_write(emu, 0x0001, 0x0201); | ||
624 | snd_emu1212m_fpga_netlist_write(emu, 0x0002, 0x0500); | ||
625 | snd_emu1212m_fpga_netlist_write(emu, 0x0003, 0x0501); | ||
626 | snd_emu1212m_fpga_netlist_write(emu, 0x0004, 0x0400); | ||
627 | snd_emu1212m_fpga_netlist_write(emu, 0x0005, 0x0401); | ||
628 | snd_emu1212m_fpga_netlist_write(emu, 0x0006, 0x0402); | ||
629 | snd_emu1212m_fpga_netlist_write(emu, 0x0007, 0x0403); | ||
630 | snd_emu1212m_fpga_netlist_write(emu, 0x0008, 0x0404); | ||
631 | snd_emu1212m_fpga_netlist_write(emu, 0x0009, 0x0405); | ||
632 | snd_emu1212m_fpga_netlist_write(emu, 0x000a, 0x0406); | ||
633 | snd_emu1212m_fpga_netlist_write(emu, 0x000b, 0x0407); | ||
634 | snd_emu1212m_fpga_netlist_write(emu, 0x000c, 0x0100); | ||
635 | snd_emu1212m_fpga_netlist_write(emu, 0x000d, 0x0104); | ||
636 | snd_emu1212m_fpga_netlist_write(emu, 0x000e, 0x0200); | ||
637 | snd_emu1212m_fpga_netlist_write(emu, 0x000f, 0x0201); | ||
638 | for (i=0;i < 0x20;i++) { | ||
639 | snd_emu1212m_fpga_netlist_write(emu, 0x0100+i, 0x0000); | ||
640 | } | ||
641 | for (i=0;i < 4;i++) { | ||
642 | snd_emu1212m_fpga_netlist_write(emu, 0x0200+i, 0x0000); | ||
643 | } | ||
644 | for (i=0;i < 7;i++) { | ||
645 | snd_emu1212m_fpga_netlist_write(emu, 0x0300+i, 0x0000); | ||
646 | } | ||
647 | for (i=0;i < 7;i++) { | ||
648 | snd_emu1212m_fpga_netlist_write(emu, 0x0400+i, 0x0000); | ||
649 | } | ||
650 | snd_emu1212m_fpga_netlist_write(emu, 0x0500, 0x0108); | ||
651 | snd_emu1212m_fpga_netlist_write(emu, 0x0501, 0x010c); | ||
652 | snd_emu1212m_fpga_netlist_write(emu, 0x0600, 0x0110); | ||
653 | snd_emu1212m_fpga_netlist_write(emu, 0x0601, 0x0114); | ||
654 | snd_emu1212m_fpga_netlist_write(emu, 0x0700, 0x0118); | ||
655 | snd_emu1212m_fpga_netlist_write(emu, 0x0701, 0x011c); | ||
656 | snd_emu1212m_fpga_write(emu, 0x07, 0x01 ); | ||
657 | |||
658 | snd_emu1212m_fpga_read(emu, 0x21, &tmp ); | ||
659 | |||
660 | outl(0x0000a000, emu->port + HCFG); | ||
661 | outl(0x0000a001, emu->port + HCFG); | ||
662 | /* Initial boot complete. Now patches */ | ||
663 | |||
664 | snd_emu1212m_fpga_read(emu, 0x21, &tmp ); | ||
665 | snd_emu1212m_fpga_write(emu, 0x0c, 0x19 ); | ||
666 | snd_emu1212m_fpga_write(emu, 0x12, 0x0c ); | ||
667 | snd_emu1212m_fpga_write(emu, 0x0c, 0x19 ); | ||
668 | snd_emu1212m_fpga_write(emu, 0x12, 0x0c ); | ||
669 | snd_emu1212m_fpga_read(emu, 0x0a, &tmp ); | ||
670 | snd_emu1212m_fpga_write(emu, 0x0a, 0x10 ); | ||
671 | |||
672 | snd_emu1212m_fpga_read(emu, 0x20, &tmp ); | ||
673 | snd_emu1212m_fpga_read(emu, 0x21, &tmp ); | ||
674 | |||
675 | snd_emu1212m_fpga_netlist_write(emu, 0x0300, 0x0312); | ||
676 | snd_emu1212m_fpga_netlist_write(emu, 0x0301, 0x0313); | ||
677 | snd_emu1212m_fpga_netlist_write(emu, 0x0200, 0x0302); | ||
678 | snd_emu1212m_fpga_netlist_write(emu, 0x0201, 0x0303); | ||
679 | |||
680 | return 0; | ||
681 | } | ||
545 | /* | 682 | /* |
546 | * Create the EMU10K1 instance | 683 | * Create the EMU10K1 instance |
547 | */ | 684 | */ |
@@ -623,7 +760,7 @@ static struct snd_emu_chip_details emu_chip_details[] = { | |||
623 | .id = "EMU1212m", | 760 | .id = "EMU1212m", |
624 | .emu10k2_chip = 1, | 761 | .emu10k2_chip = 1, |
625 | .ca0102_chip = 1, | 762 | .ca0102_chip = 1, |
626 | .ecard = 1} , | 763 | .emu1212m = 1} , |
627 | /* Tested by James@superbug.co.uk 3rd July 2005 */ | 764 | /* Tested by James@superbug.co.uk 3rd July 2005 */ |
628 | {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x20071102, | 765 | {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x20071102, |
629 | .driver = "Audigy2", .name = "Audigy 4 PRO [SB0380]", | 766 | .driver = "Audigy2", .name = "Audigy 4 PRO [SB0380]", |
@@ -1013,6 +1150,11 @@ int __devinit snd_emu10k1_create(struct snd_card *card, | |||
1013 | } else if (emu->card_capabilities->ca_cardbus_chip) { | 1150 | } else if (emu->card_capabilities->ca_cardbus_chip) { |
1014 | if ((err = snd_emu10k1_cardbus_init(emu)) < 0) | 1151 | if ((err = snd_emu10k1_cardbus_init(emu)) < 0) |
1015 | goto error; | 1152 | goto error; |
1153 | } else if (emu->card_capabilities->emu1212m) { | ||
1154 | if ((err = snd_emu10k1_emu1212m_init(emu)) < 0) { | ||
1155 | snd_emu10k1_free(emu); | ||
1156 | return err; | ||
1157 | } | ||
1016 | } else { | 1158 | } else { |
1017 | /* 5.1: Enable the additional AC97 Slots. If the emu10k1 version | 1159 | /* 5.1: Enable the additional AC97 Slots. If the emu10k1 version |
1018 | does not support this, it shouldn't do any harm */ | 1160 | does not support this, it shouldn't do any harm */ |