Index: alsa-driver/alsa-kernel/include/emu10k1.h =================================================================== RCS file: /cvsroot/alsa/alsa-kernel/include/emu10k1.h,v retrieving revision 1.51 diff -u -r1.51 emu10k1.h --- alsa-driver/alsa-kernel/include/emu10k1.h 17 Nov 2004 13:38:10 -0000 1.51 +++ alsa-driver/alsa-kernel/include/emu10k1.h 21 Nov 2004 01:56:37 -0000 @@ -840,10 +840,10 @@ ((route[0] | (route[1] << 4) | (route[2] << 8) | (route[3] << 12)) << 16) #define snd_emu10k1_compose_audigy_fxrt1(route) \ -(((unsigned int)route[0] | ((unsigned int)route[1] << 8) | ((unsigned int)route[2] << 16) | ((unsigned int)route[3] << 12)) << 24) +((unsigned int)route[0] | ((unsigned int)route[1] << 8) | ((unsigned int)route[2] << 16) | ((unsigned int)route[3] << 24)) #define snd_emu10k1_compose_audigy_fxrt2(route) \ -(((unsigned int)route[4] | ((unsigned int)route[5] << 8) | ((unsigned int)route[6] << 16) | ((unsigned int)route[7] << 12)) << 24) +((unsigned int)route[4] | ((unsigned int)route[5] << 8) | ((unsigned int)route[6] << 16) | ((unsigned int)route[7] << 24)) typedef struct snd_emu10k1_memblk { snd_util_memblk_t mem; Index: alsa-driver/alsa-kernel/pci/emu10k1/emu10k1.c =================================================================== RCS file: /cvsroot/alsa/alsa-kernel/pci/emu10k1/emu10k1.c,v retrieving revision 1.29 diff -u -r1.29 emu10k1.c --- alsa-driver/alsa-kernel/pci/emu10k1/emu10k1.c 10 Nov 2004 09:49:12 -0000 1.29 +++ alsa-driver/alsa-kernel/pci/emu10k1/emu10k1.c 21 Nov 2004 01:56:37 -0000 @@ -2,6 +2,9 @@ * The driver for the EMU10K1 (SB Live!) based soundcards * Copyright (c) by Jaroslav Kysela * + * Copyright (c) by James Courtier-Dutton + * Added support for Audigy 2 Value. + * * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -17,6 +20,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * + * */ #include @@ -68,12 +72,27 @@ module_param_array(enable_ir, bool, NULL, 0444); MODULE_PARM_DESC(enable_ir, "Enable IR."); +/* + * Class 0401: 1102:0008 (rev 00) Subsystem: 1102:1001 -> Audigy2 Value Model:SB0400 + */ static struct pci_device_id snd_emu10k1_ids[] = { { 0x1102, 0x0002, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* EMU10K1 */ { 0x1102, 0x0004, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1 }, /* Audigy */ + { 0x1102, 0x0008, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1 }, /* Audigy 2 Value SB0400 */ { 0, } }; +/* + * Audigy 2 Value notes: + * A_IOCFG Input (GPIO) + * 0x400 = Front analog jack plugged in. (Green socket) + * 0x1000 = Read analog jack plugged in. (Black socket) + * 0x2000 = Center/LFE analog jack plugged in. (Orange socket) + * A_IOCFG Output (GPIO) + * 0x60 = Sound out of front Left. + * Win sets it to 0xXX61 + */ + MODULE_DEVICE_TABLE(pci, snd_emu10k1_ids); static int __devinit snd_card_emu10k1_probe(struct pci_dev *pci, @@ -161,7 +180,10 @@ } #endif - if (emu->audigy && (emu->revision == 4) ) { + if (emu->audigy && (emu->serial == 0x10011102) ) { + strcpy(card->driver, "Audigy2"); + strcpy(card->shortname, "Sound Blaster Audigy2_Value"); + } else if (emu->audigy && (emu->revision == 4) ) { strcpy(card->driver, "Audigy2"); strcpy(card->shortname, "Sound Blaster Audigy2"); } else if (emu->audigy) { @@ -174,7 +196,7 @@ strcpy(card->driver, "EMU10K1"); strcpy(card->shortname, "Sound Blaster Live!"); } - sprintf(card->longname, "%s (rev.%d) at 0x%lx, irq %i", card->shortname, emu->revision, emu->port, emu->irq); + sprintf(card->longname, "%s (rev.%d, serial:0x%x) at 0x%lx, irq %i", card->shortname, emu->revision, emu->serial, emu->port, emu->irq); if ((err = snd_card_register(card)) < 0) { snd_card_free(card); Index: alsa-driver/alsa-kernel/pci/emu10k1/emu10k1_main.c =================================================================== RCS file: /cvsroot/alsa/alsa-kernel/pci/emu10k1/emu10k1_main.c,v retrieving revision 1.39 diff -u -r1.39 emu10k1_main.c --- alsa-driver/alsa-kernel/pci/emu10k1/emu10k1_main.c 18 Nov 2004 14:52:51 -0000 1.39 +++ alsa-driver/alsa-kernel/pci/emu10k1/emu10k1_main.c 21 Nov 2004 01:56:37 -0000 @@ -3,6 +3,10 @@ * Creative Labs, Inc. * Routines for control of EMU10K1 chips * + * Copyright (c) by James Courtier-Dutton + * Added support for Audigy 2 Value. + * + * * BUGS: * -- * @@ -183,6 +187,26 @@ outl(0x6E0000, emu->port + 0x20); outl(0xFF00FF00, emu->port + 0x24); } + if (emu->audigy && (emu->serial == 0x10011102) ) { /* audigy2 Value */ + /* Hacks for Alice3 to work independent of haP16V driver */ + u32 tmp; + + snd_printk(KERN_ERR "Audigy2 value:Special config.\n"); + //Setup SRCMulti_I2S SamplingRate + tmp = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, 0); + tmp &= 0xfffff1ff; + tmp |= (0x2<<9); + snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, 0, tmp); + + /* Setup SRCSel (Enable Spdif,I2S SRCMulti) */ + outl(0x600000, emu->port + 0x20); + outl(0x14, emu->port + 0x24); + + /* Setup SRCMulti Input Audio Enable */ + outl(0x7b0000, emu->port + 0x20); + outl(0xFF000000, emu->port + 0x24); + } + /* * Clear page with silence & setup all pointers to this page @@ -267,6 +291,9 @@ * This has to be done after init ALice3 I2SOut beyond 48KHz. * So, sequence is important. */ outl(inl(emu->port + A_IOCFG) | 0x0040, emu->port + A_IOCFG); + } else if (emu->serial == 0x10011102) { /* audigy2 value */ + /* Unmute Analog now. */ + outl(inl(emu->port + A_IOCFG) | 0x0060, emu->port + A_IOCFG); } else { /* Disable routing from AC97 line out to Front speakers */ outl(inl(emu->port + A_IOCFG) | 0x0080, emu->port + A_IOCFG); @@ -590,7 +617,7 @@ *remu = NULL; // is_audigy = (int)pci->driver_data; - is_audigy = (pci->device == 0x0004); + is_audigy = (pci->device == 0x0004) || ( (pci->device == 0x0008) ); /* enable PCI device */ if ((err = pci_enable_device(pci)) < 0) Index: alsa-driver/alsa-kernel/pci/emu10k1/emufx.c =================================================================== RCS file: /cvsroot/alsa/alsa-kernel/pci/emu10k1/emufx.c,v retrieving revision 1.63 diff -u -r1.63 emufx.c --- alsa-driver/alsa-kernel/pci/emu10k1/emufx.c 10 Nov 2004 11:54:36 -0000 1.63 +++ alsa-driver/alsa-kernel/pci/emu10k1/emufx.c 21 Nov 2004 01:56:37 -0000 @@ -1351,8 +1351,12 @@ A_PUT_OUTPUT(A_EXTOUT_LFE, playback+5 + SND_EMU10K1_PLAYBACK_CHANNELS); /* ADC buffer */ +#ifdef EMU10K1_CAPTURE_DIGITAL_OUT + A_PUT_STEREO_OUTPUT(A_EXTOUT_ADC_CAP_L, A_EXTOUT_ADC_CAP_R, playback + SND_EMU10K1_PLAYBACK_CHANNELS); +#else A_PUT_OUTPUT(A_EXTOUT_ADC_CAP_L, capture); A_PUT_OUTPUT(A_EXTOUT_ADC_CAP_R, capture+1); +#endif /* * ok, set up done.. Index: alsa-driver/alsa-kernel/pci/emu10k1/emuproc.c =================================================================== RCS file: /cvsroot/alsa/alsa-kernel/pci/emu10k1/emuproc.c,v retrieving revision 1.21 diff -u -r1.21 emuproc.c --- alsa-driver/alsa-kernel/pci/emu10k1/emuproc.c 6 Sep 2004 15:05:19 -0000 1.21 +++ alsa-driver/alsa-kernel/pci/emu10k1/emuproc.c 21 Nov 2004 01:56:38 -0000 @@ -309,6 +309,153 @@ return 0; } +#ifdef CONFIG_SND_DEBUG +static void snd_emu_proc_io_reg_read(snd_info_entry_t *entry, + snd_info_buffer_t * buffer) +{ + emu10k1_t *emu = entry->private_data; + unsigned long value; + unsigned long flags; + int i; + snd_iprintf(buffer, "IO Registers:\n\n"); + for(i = 0; i < 0x40; i+=4) { + spin_lock_irqsave(&emu->emu_lock, flags); + value = inl(emu->port + i); + spin_unlock_irqrestore(&emu->emu_lock, flags); + snd_iprintf(buffer, "%02X: %08lX\n", i, value); + } +} + +static void snd_emu_proc_io_reg_write(snd_info_entry_t *entry, + snd_info_buffer_t * buffer) +{ + emu10k1_t *emu = entry->private_data; + unsigned long flags; + char line[64]; + u32 reg, val; + while (!snd_info_get_line(buffer, line, sizeof(line))) { + if (sscanf(line, "%x %x", ®, &val) != 2) + continue; + if ((reg < 0x40) && (reg >=0) && (val <= 0xffffffff) ) { + spin_lock_irqsave(&emu->emu_lock, flags); + outl(val, emu->port + (reg & 0xfffffffc)); + spin_unlock_irqrestore(&emu->emu_lock, flags); + } + } +} + +static unsigned int snd_ptr_read(emu10k1_t * emu, + unsigned int iobase, + unsigned int reg, + unsigned int chn) +{ + unsigned long flags; + unsigned int regptr, val; + + regptr = (reg << 16) | chn; + + spin_lock_irqsave(&emu->emu_lock, flags); + outl(regptr, emu->port + iobase + PTR); + val = inl(emu->port + iobase + DATA); + spin_unlock_irqrestore(&emu->emu_lock, flags); + return val; +} + +static void snd_ptr_write(emu10k1_t *emu, + unsigned int iobase, + unsigned int reg, + unsigned int chn, + unsigned int data) +{ + unsigned int regptr; + unsigned long flags; + + regptr = (reg << 16) | chn; + + spin_lock_irqsave(&emu->emu_lock, flags); + outl(regptr, emu->port + iobase + PTR); + outl(data, emu->port + iobase + DATA); + spin_unlock_irqrestore(&emu->emu_lock, flags); +} + + +static void snd_emu_proc_ptr_reg_read(snd_info_entry_t *entry, + snd_info_buffer_t * buffer, int iobase, int offset, int length) +{ + emu10k1_t *emu = entry->private_data; + unsigned long value; + int i,j; + if (offset+length > 0x80) { + snd_iprintf(buffer, "Input values out of range\n"); + return; + } + snd_iprintf(buffer, "Registers 0x%x\n", iobase); + for(i = offset; i < offset+length; i++) { + snd_iprintf(buffer, "%02X: ",i); + for (j = 0; j < 4; j++) { + if(iobase == 0) { + value = snd_ptr_read(emu, 0, i, j); + } else { + value = snd_ptr_read(emu, 0x20, i, j); + } + snd_iprintf(buffer, "%08lX ", value); + } + snd_iprintf(buffer, "\n"); + } +} + +static void snd_emu_proc_ptr_reg_write(snd_info_entry_t *entry, + snd_info_buffer_t * buffer, int iobase) +{ + emu10k1_t *emu = entry->private_data; + char line[64]; + unsigned int reg, channel_id , val; + while (!snd_info_get_line(buffer, line, sizeof(line))) { + if (sscanf(line, "%x %x %x", ®, &channel_id, &val) != 3) + continue; + if ((reg < 0x80) && (reg >=0) && (val <= 0xffffffff) && (channel_id >=0) && (channel_id <= 3) ) + snd_ptr_write(emu, iobase, reg, channel_id, val); + } +} +static void snd_emu_proc_ptr_reg_write00(snd_info_entry_t *entry, + snd_info_buffer_t * buffer) +{ + snd_emu_proc_ptr_reg_write(entry, buffer, 0); +} + +static void snd_emu_proc_ptr_reg_write20(snd_info_entry_t *entry, + snd_info_buffer_t * buffer) +{ + snd_emu_proc_ptr_reg_write(entry, buffer, 0x20); +} + + + +static void snd_emu_proc_ptr_reg_read00a(snd_info_entry_t *entry, + snd_info_buffer_t * buffer) +{ + snd_emu_proc_ptr_reg_read(entry, buffer, 0, 0, 0x40); +} + +static void snd_emu_proc_ptr_reg_read00b(snd_info_entry_t *entry, + snd_info_buffer_t * buffer) +{ + snd_emu_proc_ptr_reg_read(entry, buffer, 0, 0x40, 0x40); +} + +static void snd_emu_proc_ptr_reg_read20a(snd_info_entry_t *entry, + snd_info_buffer_t * buffer) +{ + snd_emu_proc_ptr_reg_read(entry, buffer, 0x20, 0, 0x40); +} + +static void snd_emu_proc_ptr_reg_read20b(snd_info_entry_t *entry, + snd_info_buffer_t * buffer) +{ + snd_emu_proc_ptr_reg_read(entry, buffer, 0x20, 0x40, 0x40); +} +#endif + static struct snd_info_entry_ops snd_emu10k1_proc_ops_fx8010 = { .read = snd_emu10k1_fx8010_read, }; @@ -316,6 +463,33 @@ int __devinit snd_emu10k1_proc_init(emu10k1_t * emu) { snd_info_entry_t *entry; +#ifdef CONFIG_SND_DEBUG + if(! snd_card_proc_new(emu->card, "io_regs", &entry)) { + snd_info_set_text_ops(entry, emu, 1024, snd_emu_proc_io_reg_read); + entry->c.text.write_size = 64; + entry->c.text.write = snd_emu_proc_io_reg_write; + } + if(! snd_card_proc_new(emu->card, "ptr_regs00a", &entry)) { + snd_info_set_text_ops(entry, emu, 1024, snd_emu_proc_ptr_reg_read00a); + entry->c.text.write_size = 64; + entry->c.text.write = snd_emu_proc_ptr_reg_write00; + } + if(! snd_card_proc_new(emu->card, "ptr_regs00b", &entry)) { + snd_info_set_text_ops(entry, emu, 1024, snd_emu_proc_ptr_reg_read00b); + entry->c.text.write_size = 64; + entry->c.text.write = snd_emu_proc_ptr_reg_write00; + } + if(! snd_card_proc_new(emu->card, "ptr_regs20a", &entry)) { + snd_info_set_text_ops(entry, emu, 1024, snd_emu_proc_ptr_reg_read20a); + entry->c.text.write_size = 64; + entry->c.text.write = snd_emu_proc_ptr_reg_write20; + } + if(! snd_card_proc_new(emu->card, "ptr_regs20b", &entry)) { + snd_info_set_text_ops(entry, emu, 1024, snd_emu_proc_ptr_reg_read20b); + entry->c.text.write_size = 64; + entry->c.text.write = snd_emu_proc_ptr_reg_write20; + } +#endif if (! snd_card_proc_new(emu->card, "emu10k1", &entry)) snd_info_set_text_ops(entry, emu, 1024, snd_emu10k1_proc_read);