diff options
Diffstat (limited to 'sound/pci/emu10k1')
-rw-r--r-- | sound/pci/emu10k1/emu10k1.c | 1 | ||||
-rw-r--r-- | sound/pci/emu10k1/emu10k1_callback.c | 15 | ||||
-rw-r--r-- | sound/pci/emu10k1/emu10k1_main.c | 342 | ||||
-rw-r--r-- | sound/pci/emu10k1/emu10k1_synth.c | 45 | ||||
-rw-r--r-- | sound/pci/emu10k1/emu10k1_synth_local.h | 1 | ||||
-rw-r--r-- | sound/pci/emu10k1/emu10k1x.c | 3 | ||||
-rw-r--r-- | sound/pci/emu10k1/emufx.c | 9 | ||||
-rw-r--r-- | sound/pci/emu10k1/emumixer.c | 276 | ||||
-rw-r--r-- | sound/pci/emu10k1/emumpu401.c | 1 | ||||
-rw-r--r-- | sound/pci/emu10k1/emupcm.c | 9 | ||||
-rw-r--r-- | sound/pci/emu10k1/emuproc.c | 5 | ||||
-rw-r--r-- | sound/pci/emu10k1/io.c | 60 | ||||
-rw-r--r-- | sound/pci/emu10k1/irq.c | 9 | ||||
-rw-r--r-- | sound/pci/emu10k1/memory.c | 1 | ||||
-rw-r--r-- | sound/pci/emu10k1/p16v.c | 1 | ||||
-rw-r--r-- | sound/pci/emu10k1/timer.c | 1 | ||||
-rw-r--r-- | sound/pci/emu10k1/voice.c | 1 |
17 files changed, 552 insertions, 228 deletions
diff --git a/sound/pci/emu10k1/emu10k1.c b/sound/pci/emu10k1/emu10k1.c index 9680caf..8354c1a 100644 --- a/sound/pci/emu10k1/emu10k1.c +++ b/sound/pci/emu10k1/emu10k1.c @@ -23,7 +23,6 @@ * */ -#include <sound/driver.h> #include <linux/init.h> #include <linux/pci.h> #include <linux/time.h> diff --git a/sound/pci/emu10k1/emu10k1_callback.c b/sound/pci/emu10k1/emu10k1_callback.c index 01965bd..45088eb 100644 --- a/sound/pci/emu10k1/emu10k1_callback.c +++ b/sound/pci/emu10k1/emu10k1_callback.c @@ -35,9 +35,9 @@ struct best_voice { /* * prototypes */ -static void lookup_voices(struct snd_emux *emu, struct snd_emu10k1 *hw, +static void lookup_voices(struct snd_emux *emux, struct snd_emu10k1 *hw, struct best_voice *best, int active_only); -static struct snd_emux_voice *get_voice(struct snd_emux *emu, +static struct snd_emux_voice *get_voice(struct snd_emux *emux, struct snd_emux_port *port); static int start_voice(struct snd_emux_voice *vp); static void trigger_voice(struct snd_emux_voice *vp); @@ -45,7 +45,6 @@ static void release_voice(struct snd_emux_voice *vp); static void update_voice(struct snd_emux_voice *vp, int update); static void terminate_voice(struct snd_emux_voice *vp); static void free_voice(struct snd_emux_voice *vp); - static void set_fmmod(struct snd_emu10k1 *hw, struct snd_emux_voice *vp); static void set_fm2frq2(struct snd_emu10k1 *hw, struct snd_emux_voice *vp); static void set_filterQ(struct snd_emu10k1 *hw, struct snd_emux_voice *vp); @@ -75,9 +74,9 @@ static struct snd_emux_operators emu10k1_ops = { }; void -snd_emu10k1_ops_setup(struct snd_emux *emu) +snd_emu10k1_ops_setup(struct snd_emux *emux) { - emu->ops = emu10k1_ops; + emux->ops = emu10k1_ops; } @@ -166,7 +165,11 @@ free_voice(struct snd_emux_voice *vp) struct snd_emu10k1 *hw; hw = vp->hw; - if (vp->ch >= 0) { + /* FIXME: emu10k1_synth is broken. */ + /* This can get called with hw == 0 */ + /* Problem apparent on plug, unplug then plug */ + /* on the Audigy 2 ZS Notebook. */ + if (hw && (vp->ch >= 0)) { snd_emu10k1_ptr_write(hw, IFATN, vp->ch, 0xff00); snd_emu10k1_ptr_write(hw, DCYSUSV, vp->ch, 0x807f | DCYSUSV_CHANNELENABLE_MASK); // snd_emu10k1_ptr_write(hw, DCYSUSV, vp->ch, 0); diff --git a/sound/pci/emu10k1/emu10k1_main.c b/sound/pci/emu10k1/emu10k1_main.c index 97c41d7..9a9b977 100644 --- a/sound/pci/emu10k1/emu10k1_main.c +++ b/sound/pci/emu10k1/emu10k1_main.c @@ -33,7 +33,6 @@ #include <linux/sched.h> #include <linux/kthread.h> -#include <sound/driver.h> #include <linux/delay.h> #include <linux/init.h> #include <linux/interrupt.h> @@ -55,12 +54,14 @@ #define DOCK_FILENAME "emu/audio_dock.fw" #define EMU1010B_FILENAME "emu/emu1010b.fw" #define MICRO_DOCK_FILENAME "emu/micro_dock.fw" +#define EMU0404_FILENAME "emu/emu0404.fw" #define EMU1010_NOTEBOOK_FILENAME "emu/emu1010_notebook.fw" MODULE_FIRMWARE(HANA_FILENAME); MODULE_FIRMWARE(DOCK_FILENAME); MODULE_FIRMWARE(EMU1010B_FILENAME); MODULE_FIRMWARE(MICRO_DOCK_FILENAME); +MODULE_FIRMWARE(EMU0404_FILENAME); MODULE_FIRMWARE(EMU1010_NOTEBOOK_FILENAME); @@ -258,7 +259,6 @@ static int snd_emu10k1_init(struct snd_emu10k1 *emu, int enable_ir, int resume) * GPIO7: Unknown */ outl(0x76, emu->port + A_IOCFG); /* Windows uses 0x3f76 */ - } if (emu->card_capabilities->i2c_adc) { /* Audigy 2 ZS Notebook with ADC Wolfson WM8775 */ int size, n; @@ -274,7 +274,6 @@ static int snd_emu10k1_init(struct snd_emu10k1 *emu, int enable_ir, int resume) emu->i2c_capture_volume[n][0]= 0xcf; emu->i2c_capture_volume[n][1]= 0xcf; } - } @@ -288,7 +287,7 @@ static int snd_emu10k1_init(struct snd_emu10k1 *emu, int enable_ir, int resume) snd_emu10k1_ptr_write(emu, MAPB, ch, silent_page); } - if (emu->card_capabilities->emu1010) { + if (emu->card_capabilities->emu_model) { outl(HCFG_AUTOMUTE_ASYNC | HCFG_EMU32_SLAVE | HCFG_AUDIOENABLE, emu->port + HCFG); @@ -318,7 +317,7 @@ static int snd_emu10k1_init(struct snd_emu10k1 *emu, int enable_ir, int resume) outl(HCFG_LOCKTANKCACHE_MASK | HCFG_AUTOMUTE | HCFG_JOYENABLE, emu->port + HCFG); if (enable_ir) { /* enable IR for SB Live */ - if (emu->card_capabilities->emu1010) { + if (emu->card_capabilities->emu_model) { ; /* Disable all access to A_IOCFG for the emu1010 */ } else if (emu->card_capabilities->i2c_adc) { ; /* Disable A_IOCFG for Audigy 2 ZS Notebook */ @@ -339,7 +338,7 @@ static int snd_emu10k1_init(struct snd_emu10k1 *emu, int enable_ir, int resume) } } - if (emu->card_capabilities->emu1010) { + if (emu->card_capabilities->emu_model) { ; /* Disable all access to A_IOCFG for the emu1010 */ } else if (emu->card_capabilities->i2c_adc) { ; /* Disable A_IOCFG for Audigy 2 ZS Notebook */ @@ -359,7 +358,7 @@ static void snd_emu10k1_audio_enable(struct snd_emu10k1 *emu) outl(inl(emu->port + HCFG) | HCFG_AUDIOENABLE, emu->port + HCFG); /* Enable analog/digital outs on audigy */ - if (emu->card_capabilities->emu1010) { + if (emu->card_capabilities->emu_model) { ; /* Disable all access to A_IOCFG for the emu1010 */ } else if (emu->card_capabilities->i2c_adc) { ; /* Disable A_IOCFG for Audigy 2 ZS Notebook */ @@ -652,6 +651,8 @@ static int snd_emu10k1_cardbus_init(struct snd_emu10k1 * emu) value = inl(special_port); snd_emu10k1_ptr20_write(emu, TINA2_VOLUME, 0, 0xfefefefe); /* Defaults to 0x30303030 */ + /* Delay to give time for ADC chip to switch on. It needs 113ms */ + msleep(200); return 0; } @@ -661,6 +662,8 @@ static int snd_emu1010_load_firmware(struct snd_emu10k1 * emu, const char * file int n, i; int reg; int value; + unsigned int write_post; + unsigned long flags; const struct firmware *fw_entry; if ((err = request_firmware(&fw_entry, filename, &emu->pci->dev)) != 0) { @@ -668,12 +671,6 @@ static int snd_emu1010_load_firmware(struct snd_emu10k1 * emu, const char * file return err; } snd_printk(KERN_INFO "firmware size=0x%zx\n", fw_entry->size); -#if 0 - if (fw_entry->size != 0x133a4) { - snd_printk(KERN_ERR "firmware: %s wrong size.\n",filename); - return -EINVAL; - } -#endif /* The FPGA is a Xilinx Spartan IIE XC2S50E */ /* GPIO7 -> FPGA PGMN @@ -681,9 +678,12 @@ static int snd_emu1010_load_firmware(struct snd_emu10k1 * emu, const char * file * GPIO5 -> FPGA DIN * FPGA CONFIG OFF -> FPGA PGMN */ + spin_lock_irqsave(&emu->emu_lock, flags); outl(0x00, emu->port + A_IOCFG); /* Set PGMN low for 1uS. */ - udelay(1); + write_post = inl(emu->port + A_IOCFG); + udelay(100); outl(0x80, emu->port + A_IOCFG); /* Leave bit 7 set during netlist setup. */ + write_post = inl(emu->port + A_IOCFG); udelay(100); /* Allow FPGA memory to clean */ for(n = 0; n < fw_entry->size; n++) { value=fw_entry->data[n]; @@ -693,18 +693,22 @@ static int snd_emu1010_load_firmware(struct snd_emu10k1 * emu, const char * file reg = reg | 0x20; value = value >> 1; outl(reg, emu->port + A_IOCFG); + write_post = inl(emu->port + A_IOCFG); outl(reg | 0x40, emu->port + A_IOCFG); + write_post = inl(emu->port + A_IOCFG); } } /* After programming, set GPIO bit 4 high again. */ outl(0x10, emu->port + A_IOCFG); - + write_post = inl(emu->port + A_IOCFG); + spin_unlock_irqrestore(&emu->emu_lock, flags); release_firmware(fw_entry); return 0; } -int emu1010_firmware_thread(void *data) { +static int emu1010_firmware_thread(void *data) +{ struct snd_emu10k1 * emu = data; int tmp,tmp2; int reg; @@ -712,7 +716,7 @@ int emu1010_firmware_thread(void *data) { for (;;) { /* Delay to allow Audio Dock to settle */ - msleep(1000); + msleep_interruptible(1000); if (kthread_should_stop()) break; snd_emu1010_fpga_read(emu, EMU_HANA_IRQ_STATUS, &tmp ); /* IRQ Status */ @@ -722,17 +726,20 @@ int emu1010_firmware_thread(void *data) { /* Return to Audio Dock programming mode */ snd_printk(KERN_INFO "emu1010: Loading Audio Dock Firmware\n"); snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG, EMU_HANA_FPGA_CONFIG_AUDIODOCK ); - if (emu->card_capabilities->emu1010 == 1) { + if (emu->card_capabilities->emu_model == + EMU_MODEL_EMU1010) { if ((err = snd_emu1010_load_firmware(emu, DOCK_FILENAME)) != 0) { - return err; + continue; } - } else if (emu->card_capabilities->emu1010 == 2) { + } else if (emu->card_capabilities->emu_model == + EMU_MODEL_EMU1010B) { if ((err = snd_emu1010_load_firmware(emu, MICRO_DOCK_FILENAME)) != 0) { - return err; + continue; } - } else if (emu->card_capabilities->emu1010 == 3) { + } else if (emu->card_capabilities->emu_model == + EMU_MODEL_EMU1616) { if ((err = snd_emu1010_load_firmware(emu, MICRO_DOCK_FILENAME)) != 0) { - return err; + continue; } } @@ -745,8 +752,7 @@ int emu1010_firmware_thread(void *data) { if ((reg & 0x1f) != 0x15) { /* FPGA failed to be programmed */ snd_printk(KERN_INFO "emu1010: Loading Audio Dock Firmware file failed, reg=0x%x\n", reg); - return 0; - return -ENODEV; + continue; } snd_printk(KERN_INFO "emu1010: Audio Dock Firmware loaded\n"); snd_emu1010_fpga_read(emu, EMU_DOCK_MAJOR_REV, &tmp ); @@ -757,9 +763,9 @@ int emu1010_firmware_thread(void *data) { msleep(10); /* Unmute all. Default is muted after a firmware load */ snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE ); - break; } } + snd_printk(KERN_INFO "emu1010: firmware thread stopping\n"); return 0; } @@ -800,6 +806,7 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 * emu) int tmp,tmp2; int reg; int err; + const char *filename = NULL; snd_printk(KERN_INFO "emu1010: Special config.\n"); /* AC97 2.1, Any 16Meg of 4Gig address, Auto-Mute, EMU32 Slave, @@ -841,21 +848,31 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 * emu) return -ENODEV; } snd_printk(KERN_INFO "emu1010: EMU_HANA_ID=0x%x\n",reg); - if (emu->card_capabilities->emu1010 == 1) { - if ((err = snd_emu1010_load_firmware(emu, HANA_FILENAME)) != 0) { - snd_printk(KERN_INFO "emu1010: Loading Hana Firmware file %s failed\n", HANA_FILENAME); - return err; - } - } else if (emu->card_capabilities->emu1010 == 2) { - if ((err = snd_emu1010_load_firmware(emu, EMU1010B_FILENAME)) != 0) { - snd_printk(KERN_INFO "emu1010: Loading Firmware file %s failed\n", EMU1010B_FILENAME); - return err; - } - } else if (emu->card_capabilities->emu1010 == 3) { - if ((err = snd_emu1010_load_firmware(emu, EMU1010_NOTEBOOK_FILENAME)) != 0) { - snd_printk(KERN_INFO "emu1010: Loading Firmware file %s failed\n", EMU1010_NOTEBOOK_FILENAME); - return err; - } + switch (emu->card_capabilities->emu_model) { + case EMU_MODEL_EMU1010: + filename = HANA_FILENAME; + break; + case EMU_MODEL_EMU1010B: + filename = EMU1010B_FILENAME; + break; + case EMU_MODEL_EMU1616: + filename = EMU1010_NOTEBOOK_FILENAME; + break; + case EMU_MODEL_EMU0404: + filename = EMU0404_FILENAME; + break; + default: + filename = NULL; + return -ENODEV; + break; + } + snd_printk(KERN_INFO "emu1010: filename %s testing\n", filename); + err = snd_emu1010_load_firmware(emu, filename); + if (err != 0) { + snd_printk( + KERN_INFO "emu1010: Loading Firmware file %s failed\n", + filename); + return err; } /* ID, should read & 0x7f = 0x55 when FPGA programmed. */ @@ -1074,10 +1091,12 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 * emu) snd_emu1010_fpga_write(emu, EMU_HANA_SPDIF_MODE, 0x10 ); /* SPDIF Format spdif (or 0x11 for aes/ebu) */ /* Start Micro/Audio Dock firmware loader thread */ - emu->emu1010.firmware_thread = kthread_create(&emu1010_firmware_thread, - emu, - "emu1010_firmware"); - wake_up_process(emu->emu1010.firmware_thread); + if (!emu->emu1010.firmware_thread) { + emu->emu1010.firmware_thread = + kthread_create(emu1010_firmware_thread, emu, + "emu1010_firmware"); + wake_up_process(emu->emu1010.firmware_thread); + } #if 0 snd_emu1010_fpga_link_dst_src_write(emu, @@ -1090,79 +1109,114 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 * emu) EMU_DST_HANA_SPDIF_RIGHT1, EMU_SRC_ALICE_EMU32A + 3); /* ALICE2 bus 0xb3 */ #endif /* Default outputs */ - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_DOCK_DAC1_LEFT1, EMU_SRC_ALICE_EMU32A + 0); /* ALICE2 bus 0xa0 */ - emu->emu1010.output_source[0] = 21; - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_DOCK_DAC1_RIGHT1, EMU_SRC_ALICE_EMU32A + 1); - emu->emu1010.output_source[1] = 22; - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_DOCK_DAC2_LEFT1, EMU_SRC_ALICE_EMU32A + 2); - emu->emu1010.output_source[2] = 23; - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_DOCK_DAC2_RIGHT1, EMU_SRC_ALICE_EMU32A + 3); - emu->emu1010.output_source[3] = 24; - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_DOCK_DAC3_LEFT1, EMU_SRC_ALICE_EMU32A + 4); - emu->emu1010.output_source[4] = 25; - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_DOCK_DAC3_RIGHT1, EMU_SRC_ALICE_EMU32A + 5); - emu->emu1010.output_source[5] = 26; - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_DOCK_DAC4_LEFT1, EMU_SRC_ALICE_EMU32A + 6); - emu->emu1010.output_source[6] = 27; - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_DOCK_DAC4_RIGHT1, EMU_SRC_ALICE_EMU32A + 7); - emu->emu1010.output_source[7] = 28; - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_DOCK_PHONES_LEFT1, EMU_SRC_ALICE_EMU32A + 0); /* ALICE2 bus 0xa0 */ - emu->emu1010.output_source[8] = 21; - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_DOCK_PHONES_RIGHT1, EMU_SRC_ALICE_EMU32A + 1); - emu->emu1010.output_source[9] = 22; - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_DOCK_SPDIF_LEFT1, EMU_SRC_ALICE_EMU32A + 0); /* ALICE2 bus 0xa0 */ - emu->emu1010.output_source[10] = 21; - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_DOCK_SPDIF_RIGHT1, EMU_SRC_ALICE_EMU32A + 1); - emu->emu1010.output_source[11] = 22; - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_HANA_SPDIF_LEFT1, EMU_SRC_ALICE_EMU32A + 0); /* ALICE2 bus 0xa0 */ - emu->emu1010.output_source[12] = 21; - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_HANA_SPDIF_RIGHT1, EMU_SRC_ALICE_EMU32A + 1); - emu->emu1010.output_source[13] = 22; - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_HAMOA_DAC_LEFT1, EMU_SRC_ALICE_EMU32A + 0); /* ALICE2 bus 0xa0 */ - emu->emu1010.output_source[14] = 21; - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_HAMOA_DAC_RIGHT1, EMU_SRC_ALICE_EMU32A + 1); - emu->emu1010.output_source[15] = 22; - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_HANA_ADAT, EMU_SRC_ALICE_EMU32A + 0); /* ALICE2 bus 0xa0 */ - emu->emu1010.output_source[16] = 21; - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_HANA_ADAT + 1, EMU_SRC_ALICE_EMU32A + 1); - emu->emu1010.output_source[17] = 22; - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_HANA_ADAT + 2, EMU_SRC_ALICE_EMU32A + 2); - emu->emu1010.output_source[18] = 23; - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_HANA_ADAT + 3, EMU_SRC_ALICE_EMU32A + 3); - emu->emu1010.output_source[19] = 24; - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_HANA_ADAT + 4, EMU_SRC_ALICE_EMU32A + 4); - emu->emu1010.output_source[20] = 25; - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_HANA_ADAT + 5, EMU_SRC_ALICE_EMU32A + 5); - emu->emu1010.output_source[21] = 26; - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_HANA_ADAT + 6, EMU_SRC_ALICE_EMU32A + 6); - emu->emu1010.output_source[22] = 27; - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_HANA_ADAT + 7, EMU_SRC_ALICE_EMU32A + 7); - emu->emu1010.output_source[23] = 28; - + if (emu->card_capabilities->emu_model == EMU_MODEL_EMU1616) { + /* 1616(M) cardbus default outputs */ + /* ALICE2 bus 0xa0 */ + snd_emu1010_fpga_link_dst_src_write(emu, + EMU_DST_DOCK_DAC1_LEFT1, EMU_SRC_ALICE_EMU32A + 0); + emu->emu1010.output_source[0] = 17; + snd_emu1010_fpga_link_dst_src_write(emu, + EMU_DST_DOCK_DAC1_RIGHT1, EMU_SRC_ALICE_EMU32A + 1); + emu->emu1010.output_source[1] = 18; + snd_emu1010_fpga_link_dst_src_write(emu, + EMU_DST_DOCK_DAC2_LEFT1, EMU_SRC_ALICE_EMU32A + 2); + emu->emu1010.output_source[2] = 19; + snd_emu1010_fpga_link_dst_src_write(emu, + EMU_DST_DOCK_DAC2_RIGHT1, EMU_SRC_ALICE_EMU32A + 3); + emu->emu1010.output_source[3] = 20; + snd_emu1010_fpga_link_dst_src_write(emu, + EMU_DST_DOCK_DAC3_LEFT1, EMU_SRC_ALICE_EMU32A + 4); + emu->emu1010.output_source[4] = 21; + snd_emu1010_fpga_link_dst_src_write(emu, + EMU_DST_DOCK_DAC3_RIGHT1, EMU_SRC_ALICE_EMU32A + 5); + emu->emu1010.output_source[5] = 22; + /* ALICE2 bus 0xa0 */ + snd_emu1010_fpga_link_dst_src_write(emu, + EMU_DST_MANA_DAC_LEFT, EMU_SRC_ALICE_EMU32A + 0); + emu->emu1010.output_source[16] = 17; + snd_emu1010_fpga_link_dst_src_write(emu, + EMU_DST_MANA_DAC_RIGHT, EMU_SRC_ALICE_EMU32A + 1); + emu->emu1010.output_source[17] = 18; + } else { + /* ALICE2 bus 0xa0 */ + snd_emu1010_fpga_link_dst_src_write(emu, + EMU_DST_DOCK_DAC1_LEFT1, EMU_SRC_ALICE_EMU32A + 0); + emu->emu1010.output_source[0] = 21; + snd_emu1010_fpga_link_dst_src_write(emu, + EMU_DST_DOCK_DAC1_RIGHT1, EMU_SRC_ALICE_EMU32A + 1); + emu->emu1010.output_source[1] = 22; + snd_emu1010_fpga_link_dst_src_write(emu, + EMU_DST_DOCK_DAC2_LEFT1, EMU_SRC_ALICE_EMU32A + 2); + emu->emu1010.output_source[2] = 23; + snd_emu1010_fpga_link_dst_src_write(emu, + EMU_DST_DOCK_DAC2_RIGHT1, EMU_SRC_ALICE_EMU32A + 3); + emu->emu1010.output_source[3] = 24; + snd_emu1010_fpga_link_dst_src_write(emu, + EMU_DST_DOCK_DAC3_LEFT1, EMU_SRC_ALICE_EMU32A + 4); + emu->emu1010.output_source[4] = 25; + snd_emu1010_fpga_link_dst_src_write(emu, + EMU_DST_DOCK_DAC3_RIGHT1, EMU_SRC_ALICE_EMU32A + 5); + emu->emu1010.output_source[5] = 26; + snd_emu1010_fpga_link_dst_src_write(emu, + EMU_DST_DOCK_DAC4_LEFT1, EMU_SRC_ALICE_EMU32A + 6); + emu->emu1010.output_source[6] = 27; + snd_emu1010_fpga_link_dst_src_write(emu, + EMU_DST_DOCK_DAC4_RIGHT1, EMU_SRC_ALICE_EMU32A + 7); + emu->emu1010.output_source[7] = 28; + /* ALICE2 bus 0xa0 */ + snd_emu1010_fpga_link_dst_src_write(emu, + EMU_DST_DOCK_PHONES_LEFT1, EMU_SRC_ALICE_EMU32A + 0); + emu->emu1010.output_source[8] = 21; + snd_emu1010_fpga_link_dst_src_write(emu, + EMU_DST_DOCK_PHONES_RIGHT1, EMU_SRC_ALICE_EMU32A + 1); + emu->emu1010.output_source[9] = 22; + /* ALICE2 bus 0xa0 */ + snd_emu1010_fpga_link_dst_src_write(emu, + EMU_DST_DOCK_SPDIF_LEFT1, EMU_SRC_ALICE_EMU32A + 0); + emu->emu1010.output_source[10] = 21; + snd_emu1010_fpga_link_dst_src_write(emu, + EMU_DST_DOCK_SPDIF_RIGHT1, EMU_SRC_ALICE_EMU32A + 1); + emu->emu1010.output_source[11] = 22; + /* ALICE2 bus 0xa0 */ + snd_emu1010_fpga_link_dst_src_write(emu, + EMU_DST_HANA_SPDIF_LEFT1, EMU_SRC_ALICE_EMU32A + 0); + emu->emu1010.output_source[12] = 21; + snd_emu1010_fpga_link_dst_src_write(emu, + EMU_DST_HANA_SPDIF_RIGHT1, EMU_SRC_ALICE_EMU32A + 1); + emu->emu1010.output_source[13] = 22; + /* ALICE2 bus 0xa0 */ + snd_emu1010_fpga_link_dst_src_write(emu, + EMU_DST_HAMOA_DAC_LEFT1, EMU_SRC_ALICE_EMU32A + 0); + emu->emu1010.output_source[14] = 21; + snd_emu1010_fpga_link_dst_src_write(emu, + EMU_DST_HAMOA_DAC_RIGHT1, EMU_SRC_ALICE_EMU32A + 1); + emu->emu1010.output_source[15] = 22; + /* ALICE2 bus 0xa0 */ + snd_emu1010_fpga_link_dst_src_write(emu, + EMU_DST_HANA_ADAT, EMU_SRC_ALICE_EMU32A + 0); + emu->emu1010.output_source[16] = 21; + snd_emu1010_fpga_link_dst_src_write(emu, + EMU_DST_HANA_ADAT + 1, EMU_SRC_ALICE_EMU32A + 1); + emu->emu1010.output_source[17] = 22; + snd_emu1010_fpga_link_dst_src_write(emu, + EMU_DST_HANA_ADAT + 2, EMU_SRC_ALICE_EMU32A + 2); + emu->emu1010.output_source[18] = 23; + snd_emu1010_fpga_link_dst_src_write(emu, + EMU_DST_HANA_ADAT + 3, EMU_SRC_ALICE_EMU32A + 3); + emu->emu1010.output_source[19] = 24; + snd_emu1010_fpga_link_dst_src_write(emu, + EMU_DST_HANA_ADAT + 4, EMU_SRC_ALICE_EMU32A + 4); + emu->emu1010.output_source[20] = 25; + snd_emu1010_fpga_link_dst_src_write(emu, + EMU_DST_HANA_ADAT + 5, EMU_SRC_ALICE_EMU32A + 5); + emu->emu1010.output_source[21] = 26; + snd_emu1010_fpga_link_dst_src_write(emu, + EMU_DST_HANA_ADAT + 6, EMU_SRC_ALICE_EMU32A + 6); + emu->emu1010.output_source[22] = 27; + snd_emu1010_fpga_link_dst_src_write(emu, + EMU_DST_HANA_ADAT + 7, EMU_SRC_ALICE_EMU32A + 7); + emu->emu1010.output_source[23] = 28; + } /* TEMP: Select SPDIF in/out */ //snd_emu1010_fpga_write(emu, EMU_HANA_OPTICAL_TYPE, 0x0); /* Output spdif */ @@ -1202,11 +1256,12 @@ static int snd_emu10k1_free(struct snd_emu10k1 *emu) } snd_emu10k1_free_efx(emu); } - if (emu->card_capabilities->emu1010) { + if (emu->card_capabilities->emu_model == EMU_MODEL_EMU1010) { /* Disable 48Volt power to Audio Dock */ snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_PWR, 0 ); - kthread_stop(emu->emu1010.firmware_thread); } + if (emu->emu1010.firmware_thread) + kthread_stop(emu->emu1010.firmware_thread); if (emu->memhdr) snd_util_memhdr_free(emu->memhdr); if (emu->silent_page.area) @@ -1338,6 +1393,7 @@ static struct snd_emu_chip_details emu_chip_details[] = { .spi_dac = 1, .i2c_adc = 1, .spk71 = 1} , + /* Tested by James@superbug.co.uk 4th Nov 2007. */ {.vendor = 0x1102, .device = 0x0008, .subsystem = 0x42011102, .driver = "Audigy2", .name = "E-mu 1010 Notebook [MAEM8950]", .id = "EMU1010", @@ -1345,28 +1401,46 @@ static struct snd_emu_chip_details emu_chip_details[] = { .ca0108_chip = 1, .ca_cardbus_chip = 1, .spk71 = 1 , - .emu1010 = 3} , + .emu_model = EMU_MODEL_EMU1616}, + /* Tested by James@superbug.co.uk 4th Nov 2007. */ {.vendor = 0x1102, .device = 0x0008, .subsystem = 0x40041102, .driver = "Audigy2", .name = "E-mu 1010b PCI [MAEM????]", .id = "EMU1010", .emu10k2_chip = 1, .ca0108_chip = 1, - .spk71 = 1 , - .emu1010 = 2} , + .spk71 = 1, + .emu_model = EMU_MODEL_EMU1010B}, + /* Tested by James@superbug.co.uk 8th July 2005. */ + {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x40011102, + .driver = "Audigy2", .name = "E-mu 1010 [4001]", + .id = "EMU1010", + .emu10k2_chip = 1, + .ca0102_chip = 1, + .spk71 = 1, + .emu_model = EMU_MODEL_EMU1010}, /* Emu 1010 */ + /* EMU0404b */ + {.vendor = 0x1102, .device = 0x0008, .subsystem = 0x40021102, + .driver = "Audigy2", .name = "E-mu 0404b [4002]", + .id = "EMU0404", + .emu10k2_chip = 1, + .ca0108_chip = 1, + .spk71 = 1, + .emu_model = EMU_MODEL_EMU0404}, /* EMU 0404 */ + /* Tested by James@superbug.co.uk 20-3-2007. */ + {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x40021102, + .driver = "Audigy2", .name = "E-mu 0404 [4002]", + .id = "EMU0404", + .emu10k2_chip = 1, + .ca0102_chip = 1, + .spk71 = 1, + .emu_model = EMU_MODEL_EMU0404}, /* EMU 0404 */ + /* Audigy4 (Not PRO) SB0610 */ {.vendor = 0x1102, .device = 0x0008, .driver = "Audigy2", .name = "Audigy 2 Value [Unknown]", .id = "Audigy2", .emu10k2_chip = 1, .ca0108_chip = 1, .ac97_chip = 1} , - /* Tested by James@superbug.co.uk 8th July 2005. No sound available yet. */ - {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x40011102, - .driver = "Audigy2", .name = "E-mu 1010 [4001]", - .id = "EMU1010", - .emu10k2_chip = 1, - .ca0102_chip = 1, - .spk71 = 1, - .emu1010 = 1} , /* Tested by James@superbug.co.uk 3rd July 2005 */ {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x20071102, .driver = "Audigy2", .name = "Audigy 4 PRO [SB0380]", @@ -1654,6 +1728,8 @@ int __devinit snd_emu10k1_create(struct snd_card *card, emu->card = card; spin_lock_init(&emu->reg_lock); spin_lock_init(&emu->emu_lock); + spin_lock_init(&emu->spi_lock); + spin_lock_init(&emu->i2c_lock); spin_lock_init(&emu->voice_lock); spin_lock_init(&emu->synth_lock); spin_lock_init(&emu->memblk_lock); @@ -1794,7 +1870,7 @@ int __devinit snd_emu10k1_create(struct snd_card *card, if (emu->card_capabilities->ecard) { if ((err = snd_emu10k1_ecard_init(emu)) < 0) goto error; - } else if (emu->card_capabilities->emu1010) { + } else if (emu->card_capabilities->emu_model) { if ((err = snd_emu10k1_emu1010_init(emu)) < 0) { snd_emu10k1_free(emu); return err; @@ -1943,7 +2019,7 @@ void snd_emu10k1_resume_init(struct snd_emu10k1 *emu) snd_emu10k1_cardbus_init(emu); if (emu->card_capabilities->ecard) snd_emu10k1_ecard_init(emu); - else if (emu->card_capabilities->emu1010) + else if (emu->card_capabilities->emu_model) snd_emu10k1_emu1010_init(emu); else snd_emu10k1_ptr_write(emu, AC97SLOT, 0, AC97SLOT_CNTR|AC97SLOT_LFE); diff --git a/sound/pci/emu10k1/emu10k1_synth.c b/sound/pci/emu10k1/emu10k1_synth.c index 204995a..ad7b714 100644 --- a/sound/pci/emu10k1/emu10k1_synth.c +++ b/sound/pci/emu10k1/emu10k1_synth.c @@ -30,7 +30,7 @@ MODULE_LICENSE("GPL"); */ static int snd_emu10k1_synth_new_device(struct snd_seq_device *dev) { - struct snd_emux *emu; + struct snd_emux *emux; struct snd_emu10k1 *hw; struct snd_emu10k1_synth_arg *arg; unsigned long flags; @@ -46,53 +46,56 @@ static int snd_emu10k1_synth_new_device(struct snd_seq_device *dev) else if (arg->max_voices > 64) arg->max_voices = 64; - if (snd_emux_new(&emu) < 0) + if (snd_emux_new(&emux) < 0) return -ENOMEM; - snd_emu10k1_ops_setup(emu); - emu->hw = hw = arg->hwptr; - emu->max_voices = arg->max_voices; - emu->num_ports = arg->seq_ports; - emu->pitch_shift = -501; - emu->memhdr = hw->memhdr; - emu->midi_ports = arg->seq_ports < 2 ? arg->seq_ports : 2; /* maximum two ports */ - emu->midi_devidx = hw->audigy ? 2 : 1; /* audigy has two external midis */ - emu->linear_panning = 0; - emu->hwdep_idx = 2; /* FIXED */ - - if (snd_emux_register(emu, dev->card, arg->index, "Emu10k1") < 0) { - snd_emux_free(emu); + snd_emu10k1_ops_setup(emux); + hw = arg->hwptr; + emux->hw = hw; + emux->max_voices = arg->max_voices; + emux->num_ports = arg->seq_ports; + emux->pitch_shift = -501; + emux->memhdr = hw->memhdr; + /* maximum two ports */ + emux->midi_ports = arg->seq_ports < 2 ? arg->seq_ports : 2; + /* audigy has two external midis */ + emux->midi_devidx = hw->audigy ? 2 : 1; + emux->linear_panning = 0; + emux->hwdep_idx = 2; /* FIXED */ + + if (snd_emux_register(emux, dev->card, arg->index, "Emu10k1") < 0) { + snd_emux_free(emux); return -ENOMEM; } spin_lock_irqsave(&hw->voice_lock, flags); - hw->synth = emu; + hw->synth = emux; hw->get_synth_voice = snd_emu10k1_synth_get_voice; spin_unlock_irqrestore(&hw->voice_lock, flags); - dev->driver_data = emu; + dev->driver_data = emux; return 0; } static int snd_emu10k1_synth_delete_device(struct snd_seq_device *dev) { - struct snd_emux *emu; + struct snd_emux *emux; struct snd_emu10k1 *hw; unsigned long flags; if (dev->driver_data == NULL) return 0; /* not registered actually */ - emu = dev->driver_data; + emux = dev->driver_data; - hw = emu->hw; + hw = emux->hw; spin_lock_irqsave(&hw->voice_lock, flags); hw->synth = NULL; hw->get_synth_voice = NULL; spin_unlock_irqrestore(&hw->voice_lock, flags); - snd_emux_free(emu); + snd_emux_free(emux); return 0; } diff --git a/sound/pci/emu10k1/emu10k1_synth_local.h b/sound/pci/emu10k1/emu10k1_synth_local.h index 308ddc8..25f328f 100644 --- a/sound/pci/emu10k1/emu10k1_synth_local.h +++ b/sound/pci/emu10k1/emu10k1_synth_local.h @@ -20,7 +20,6 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include <sound/driver.h> #include <linux/time.h> #include <sound/core.h> #include <sound/emu10k1_synth.h> diff --git a/sound/pci/emu10k1/emu10k1x.c b/sound/pci/emu10k1/emu10k1x.c index 1ec7eba..5512abd 100644 --- a/sound/pci/emu10k1/emu10k1x.c +++ b/sound/pci/emu10k1/emu10k1x.c @@ -29,7 +29,6 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ -#include <sound/driver.h> #include <linux/init.h> #include <linux/interrupt.h> #include <linux/pci.h> @@ -1583,6 +1582,8 @@ static int __devinit snd_emu10k1x_probe(struct pci_dev *pci, sprintf(card->longname, "%s at 0x%lx irq %i", card->shortname, chip->port, chip->irq); + snd_card_set_dev(card, &pci->dev); + if ((err = snd_card_register(card)) < 0) { snd_card_free(card); return err; diff --git a/sound/pci/emu10k1/emufx.c b/sound/pci/emu10k1/emufx.c index 9bf1cd5..71dc4c8 100644 --- a/sound/pci/emu10k1/emufx.c +++ b/sound/pci/emu10k1/emufx.c @@ -28,7 +28,6 @@ * */ -#include <sound/driver.h> #include <linux/pci.h> #include <linux/capability.h> #include <linux/delay.h> @@ -666,7 +665,7 @@ static unsigned int *copy_tlv(const unsigned int __user *_tlv) return NULL; if (data[1] >= MAX_TLV_SIZE) return NULL; - tlv = kmalloc(data[1] * 4 + sizeof(data), GFP_KERNEL); + tlv = kmalloc(data[1] + sizeof(data), GFP_KERNEL); if (!tlv) return NULL; memcpy(tlv, data, sizeof(data)); @@ -1262,7 +1261,7 @@ static int __devinit _snd_emu10k1_audigy_init_efx(struct snd_emu10k1 *emu) A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input)) /* emu1212 DSP 0 and DSP 1 Capture */ - if (emu->card_capabilities->emu1010) { + if (emu->card_capabilities->emu_model) { if (emu->card_capabilities->ca0108_chip) { /* Note:JCD:No longer bit shift lower 16bits to upper 16bits of 32bit value. */ A_OP(icode, &ptr, iMACINT0, A_GPR(tmp), A_C_00000000, A3_EMU32IN(0x0), A_C_00000001); @@ -1516,7 +1515,7 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input)) /* digital outputs */ /* A_PUT_STEREO_OUTPUT(A_EXTOUT_FRONT_L, A_EXTOUT_FRONT_R, playback + SND_EMU10K1_PLAYBACK_CHANNELS); */ - if (emu->card_capabilities->emu1010) { + if (emu->card_capabilities->emu_model) { /* EMU1010 Outputs from PCM Front, Rear, Center, LFE, Side */ snd_printk("EMU outputs on\n"); for (z = 0; z < 8; z++) { @@ -1564,7 +1563,7 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input)) A_PUT_OUTPUT(A_EXTOUT_ADC_CAP_R, capture+1); #endif - if (emu->card_capabilities->emu1010) { + if (emu->card_capabilities->emu_model) { if (emu->card_capabilities->ca0108_chip) { snd_printk("EMU2 inputs on\n"); for (z = 0; z < 0x10; z++) { diff --git a/sound/pci/emu10k1/emumixer.c b/sound/pci/emu10k1/emumixer.c index ccacd7b..fd22120 100644 --- a/sound/pci/emu10k1/emumixer.c +++ b/sound/pci/emu10k1/emumixer.c @@ -30,7 +30,6 @@ * */ -#include <sound/driver.h> #include <linux/time.h> #include <linux/init.h> #include <sound/core.h> @@ -140,6 +139,61 @@ static char *emu1010_src_texts[] = { "DSP 31", }; +/* 1616(m) cardbus */ + +static char *emu1616_src_texts[] = { + "Silence", + "Dock Mic A", + "Dock Mic B", + "Dock ADC1 Left", + "Dock ADC1 Right", + "Dock ADC2 Left", + "Dock ADC2 Right", + "Dock SPDIF Left", + "Dock SPDIF Right", + "ADAT 0", + "ADAT 1", + "ADAT 2", + "ADAT 3", + "ADAT 4", + "ADAT 5", + "ADAT 6", + "ADAT 7", + "DSP 0", + "DSP 1", + "DSP 2", + "DSP 3", + "DSP 4", + "DSP 5", + "DSP 6", + "DSP 7", + "DSP 8", + "DSP 9", + "DSP 10", + "DSP 11", + "DSP 12", + "DSP 13", + "DSP 14", + "DSP 15", + "DSP 16", + "DSP 17", + "DSP 18", + "DSP 19", + "DSP 20", + "DSP 21", + "DSP 22", + "DSP 23", + "DSP 24", + "DSP 25", + "DSP 26", + "DSP 27", + "DSP 28", + "DSP 29", + "DSP 30", + "DSP 31", +}; + + /* * List of data sources available for each destination */ @@ -199,6 +253,59 @@ static unsigned int emu1010_src_regs[] = { EMU_SRC_ALICE_EMU32B+0xf, /* 52 */ }; +/* 1616(m) cardbus */ +static unsigned int emu1616_src_regs[] = { + EMU_SRC_SILENCE, + EMU_SRC_DOCK_MIC_A1, + EMU_SRC_DOCK_MIC_B1, + EMU_SRC_DOCK_ADC1_LEFT1, + EMU_SRC_DOCK_ADC1_RIGHT1, + EMU_SRC_DOCK_ADC2_LEFT1, + EMU_SRC_DOCK_ADC2_RIGHT1, + EMU_SRC_MDOCK_SPDIF_LEFT1, + EMU_SRC_MDOCK_SPDIF_RIGHT1, + EMU_SRC_MDOCK_ADAT, + EMU_SRC_MDOCK_ADAT+1, + EMU_SRC_MDOCK_ADAT+2, + EMU_SRC_MDOCK_ADAT+3, + EMU_SRC_MDOCK_ADAT+4, + EMU_SRC_MDOCK_ADAT+5, + EMU_SRC_MDOCK_ADAT+6, + EMU_SRC_MDOCK_ADAT+7, + EMU_SRC_ALICE_EMU32A, + EMU_SRC_ALICE_EMU32A+1, + EMU_SRC_ALICE_EMU32A+2, + EMU_SRC_ALICE_EMU32A+3, + EMU_SRC_ALICE_EMU32A+4, + EMU_SRC_ALICE_EMU32A+5, + EMU_SRC_ALICE_EMU32A+6, + EMU_SRC_ALICE_EMU32A+7, + EMU_SRC_ALICE_EMU32A+8, + EMU_SRC_ALICE_EMU32A+9, + EMU_SRC_ALICE_EMU32A+0xa, + EMU_SRC_ALICE_EMU32A+0xb, + EMU_SRC_ALICE_EMU32A+0xc, + EMU_SRC_ALICE_EMU32A+0xd, + EMU_SRC_ALICE_EMU32A+0xe, + EMU_SRC_ALICE_EMU32A+0xf, + EMU_SRC_ALICE_EMU32B, + EMU_SRC_ALICE_EMU32B+1, + EMU_SRC_ALICE_EMU32B+2, + EMU_SRC_ALICE_EMU32B+3, + EMU_SRC_ALICE_EMU32B+4, + EMU_SRC_ALICE_EMU32B+5, + EMU_SRC_ALICE_EMU32B+6, + EMU_SRC_ALICE_EMU32B+7, + EMU_SRC_ALICE_EMU32B+8, + EMU_SRC_ALICE_EMU32B+9, + EMU_SRC_ALICE_EMU32B+0xa, + EMU_SRC_ALICE_EMU32B+0xb, + EMU_SRC_ALICE_EMU32B+0xc, + EMU_SRC_ALICE_EMU32B+0xd, + EMU_SRC_ALICE_EMU32B+0xe, + EMU_SRC_ALICE_EMU32B+0xf, +}; + /* * Data destinations - physical EMU outputs. * Each destination has an enum mixer control to choose a data source @@ -230,6 +337,28 @@ static unsigned int emu1010_output_dst[] = { EMU_DST_HANA_ADAT+7, /* 23 */ }; +/* 1616(m) cardbus */ +static unsigned int emu1616_output_dst[] = { + EMU_DST_DOCK_DAC1_LEFT1, + EMU_DST_DOCK_DAC1_RIGHT1, + EMU_DST_DOCK_DAC2_LEFT1, + EMU_DST_DOCK_DAC2_RIGHT1, + EMU_DST_DOCK_DAC3_LEFT1, + EMU_DST_DOCK_DAC3_RIGHT1, + EMU_DST_MDOCK_SPDIF_LEFT1, + EMU_DST_MDOCK_SPDIF_RIGHT1, + EMU_DST_MDOCK_ADAT, + EMU_DST_MDOCK_ADAT+1, + EMU_DST_MDOCK_ADAT+2, + EMU_DST_MDOCK_ADAT+3, + EMU_DST_MDOCK_ADAT+4, + EMU_DST_MDOCK_ADAT+5, + EMU_DST_MDOCK_ADAT+6, + EMU_DST_MDOCK_ADAT+7, + EMU_DST_MANA_DAC_LEFT, + EMU_DST_MANA_DAC_RIGHT, +}; + /* * Data destinations - HANA outputs going to Alice2 (audigy) for * capture (EMU32 + I2S links) @@ -260,14 +389,26 @@ static unsigned int emu1010_input_dst[] = { EMU_DST_ALICE_I2S2_RIGHT, }; -static int snd_emu1010_input_output_source_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) +static int snd_emu1010_input_output_source_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) { + struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); + char **items; + uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; uinfo->count = 1; - uinfo->value.enumerated.items = 53; + if (emu->card_capabilities->emu_model == EMU_MODEL_EMU1616) { + uinfo->value.enumerated.items = 49; + items = emu1616_src_texts; + } else { + uinfo->value.enumerated.items = 53; + items = emu1010_src_texts; + } if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) - uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1; - strcpy(uinfo->value.enumerated.name, emu1010_src_texts[uinfo->value.enumerated.item]); + uinfo->value.enumerated.item = + uinfo->value.enumerated.items - 1; + strcpy(uinfo->value.enumerated.name, + items[uinfo->value.enumerated.item]); return 0; } @@ -279,7 +420,9 @@ static int snd_emu1010_output_source_get(struct snd_kcontrol *kcontrol, channel = (kcontrol->private_value) & 0xff; /* Limit: emu1010_output_dst, emu->emu1010.output_source */ - if (channel >= 24) + if (channel >= 24 || + (emu->card_capabilities->emu_model == EMU_MODEL_EMU1616 && + channel >= 18)) return -EINVAL; ucontrol->value.enumerated.item[0] = emu->emu1010.output_source[channel]; return 0; @@ -289,24 +432,30 @@ static int snd_emu1010_output_source_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); - int change = 0; unsigned int val; unsigned int channel; val = ucontrol->value.enumerated.item[0]; - if (val >= 53) + if (val >= 53 || + (emu->card_capabilities->emu_model == EMU_MODEL_EMU1616 && + val >= 49)) return -EINVAL; channel = (kcontrol->private_value) & 0xff; /* Limit: emu1010_output_dst, emu->emu1010.output_source */ - if (channel >= 24) + if (channel >= 24 || + (emu->card_capabilities->emu_model == EMU_MODEL_EMU1616 && + channel >= 18)) return -EINVAL; - if (emu->emu1010.output_source[channel] != val) { - emu->emu1010.output_source[channel] = val; - change = 1; + if (emu->emu1010.output_source[channel] == val) + return 0; + emu->emu1010.output_source[channel] = val; + if (emu->card_capabilities->emu_model == EMU_MODEL_EMU1616) + snd_emu1010_fpga_link_dst_src_write(emu, + emu1616_output_dst[channel], emu1616_src_regs[val]); + else snd_emu1010_fpga_link_dst_src_write(emu, emu1010_output_dst[channel], emu1010_src_regs[val]); - } - return change; + return 1; } static int snd_emu1010_input_source_get(struct snd_kcontrol *kcontrol, @@ -327,24 +476,28 @@ static int snd_emu1010_input_source_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); - int change = 0; unsigned int val; unsigned int channel; val = ucontrol->value.enumerated.item[0]; - if (val >= 53) + if (val >= 53 || + (emu->card_capabilities->emu_model == EMU_MODEL_EMU1616 && + val >= 49)) return -EINVAL; channel = (kcontrol->private_value) & 0xff; /* Limit: emu1010_input_dst, emu->emu1010.input_source */ if (channel >= 22) return -EINVAL; - if (emu->emu1010.input_source[channel] != val) { - emu->emu1010.input_source[channel] = val; - change = 1; + if (emu->emu1010.input_source[channel] == val) + return 0; + emu->emu1010.input_source[channel] = val; + if (emu->card_capabilities->emu_model == EMU_MODEL_EMU1616) + snd_emu1010_fpga_link_dst_src_write(emu, + emu1010_input_dst[channel], emu1616_src_regs[val]); + else snd_emu1010_fpga_link_dst_src_write(emu, emu1010_input_dst[channel], emu1010_src_regs[val]); - } - return change; + return 1; } #define EMU1010_SOURCE_OUTPUT(xname,chid) \ @@ -384,6 +537,30 @@ static struct snd_kcontrol_new snd_emu1010_output_enum_ctls[] __devinitdata = { EMU1010_SOURCE_OUTPUT("1010 ADAT 7 Playback Enum", 0x17), }; + +/* 1616(m) cardbus */ +static struct snd_kcontrol_new snd_emu1616_output_enum_ctls[] __devinitdata = { + EMU1010_SOURCE_OUTPUT("Dock DAC1 Left Playback Enum", 0), + EMU1010_SOURCE_OUTPUT("Dock DAC1 Right Playback Enum", 1), + EMU1010_SOURCE_OUTPUT("Dock DAC2 Left Playback Enum", 2), + EMU1010_SOURCE_OUTPUT("Dock DAC2 Right Playback Enum", 3), + EMU1010_SOURCE_OUTPUT("Dock DAC3 Left Playback Enum", 4), + EMU1010_SOURCE_OUTPUT("Dock DAC3 Right Playback Enum", 5), + EMU1010_SOURCE_OUTPUT("Dock SPDIF Left Playback Enum", 6), + EMU1010_SOURCE_OUTPUT("Dock SPDIF Right Playback Enum", 7), + EMU1010_SOURCE_OUTPUT("Dock ADAT 0 Playback Enum", 8), + EMU1010_SOURCE_OUTPUT("Dock ADAT 1 Playback Enum", 9), + EMU1010_SOURCE_OUTPUT("Dock ADAT 2 Playback Enum", 0xa), + EMU1010_SOURCE_OUTPUT("Dock ADAT 3 Playback Enum", 0xb), + EMU1010_SOURCE_OUTPUT("Dock ADAT 4 Playback Enum", 0xc), + EMU1010_SOURCE_OUTPUT("Dock ADAT 5 Playback Enum", 0xd), + EMU1010_SOURCE_OUTPUT("Dock ADAT 6 Playback Enum", 0xe), + EMU1010_SOURCE_OUTPUT("Dock ADAT 7 Playback Enum", 0xf), + EMU1010_SOURCE_OUTPUT("Mana DAC Left Playback Enum", 0x10), + EMU1010_SOURCE_OUTPUT("Mana DAC Right Playback Enum", 0x11), +}; + + #define EMU1010_SOURCE_INPUT(xname,chid) \ { \ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ @@ -1793,7 +1970,7 @@ int __devinit snd_emu10k1_mixer(struct snd_emu10k1 *emu, return err; } - if ( emu->card_capabilities->emu1010) { + if (emu->card_capabilities->emu_model) { ; /* Disable the snd_audigy_spdif_shared_spdif */ } else if (emu->audigy) { if ((kctl = snd_ctl_new1(&snd_audigy_shared_spdif, emu)) == NULL) @@ -1818,30 +1995,73 @@ int __devinit snd_emu10k1_mixer(struct snd_emu10k1 *emu, return err; } - if ( emu->card_capabilities->emu1010) { + if (emu->card_capabilities->emu_model == EMU_MODEL_EMU1616) { + /* 1616(m) cardbus */ + int i; + + for (i = 0; i < ARRAY_SIZE(snd_emu1616_output_enum_ctls); i++) { + err = snd_ctl_add(card, + snd_ctl_new1(&snd_emu1616_output_enum_ctls[i], + emu)); + if (err < 0) + return err; + } + for (i = 0; i < ARRAY_SIZE(snd_emu1010_input_enum_ctls); i++) { + err = snd_ctl_add(card, + snd_ctl_new1(&snd_emu1010_input_enum_ctls[i], + emu)); + if (err < 0) + return err; + } + for (i = 0; i < ARRAY_SIZE(snd_emu1010_adc_pads) - 2; i++) { + err = snd_ctl_add(card, + snd_ctl_new1(&snd_emu1010_adc_pads[i], emu)); + if (err < 0) + return err; + } + for (i = 0; i < ARRAY_SIZE(snd_emu1010_dac_pads) - 2; i++) { + err = snd_ctl_add(card, + snd_ctl_new1(&snd_emu1010_dac_pads[i], emu)); + if (err < 0) + return err; + } + err = snd_ctl_add(card, + snd_ctl_new1(&snd_emu1010_internal_clock, emu)); + if (err < 0) + return err; + + } else if (emu->card_capabilities->emu_model) { + /* all other e-mu cards for now */ int i; for (i = 0; i < ARRAY_SIZE(snd_emu1010_output_enum_ctls); i++) { - err = snd_ctl_add(card, snd_ctl_new1(&snd_emu1010_output_enum_ctls[i], emu)); + err = snd_ctl_add(card, + snd_ctl_new1(&snd_emu1010_output_enum_ctls[i], + emu)); if (err < 0) return err; } for (i = 0; i < ARRAY_SIZE(snd_emu1010_input_enum_ctls); i++) { - err = snd_ctl_add(card, snd_ctl_new1(&snd_emu1010_input_enum_ctls[i], emu)); + err = snd_ctl_add(card, + snd_ctl_new1(&snd_emu1010_input_enum_ctls[i], + emu)); if (err < 0) return err; } for (i = 0; i < ARRAY_SIZE(snd_emu1010_adc_pads); i++) { - err = snd_ctl_add(card, snd_ctl_new1(&snd_emu1010_adc_pads[i], emu)); + err = snd_ctl_add(card, + snd_ctl_new1(&snd_emu1010_adc_pads[i], emu)); if (err < 0) return err; } for (i = 0; i < ARRAY_SIZE(snd_emu1010_dac_pads); i++) { - err = snd_ctl_add(card, snd_ctl_new1(&snd_emu1010_dac_pads[i], emu)); + err = snd_ctl_add(card, + snd_ctl_new1(&snd_emu1010_dac_pads[i], emu)); if (err < 0) return err; } - err = snd_ctl_add(card, snd_ctl_new1(&snd_emu1010_internal_clock, emu)); + err = snd_ctl_add(card, + snd_ctl_new1(&snd_emu1010_internal_clock, emu)); if (err < 0) return err; } diff --git a/sound/pci/emu10k1/emumpu401.c b/sound/pci/emu10k1/emumpu401.c index 04c7cf7..c4d76d1 100644 --- a/sound/pci/emu10k1/emumpu401.c +++ b/sound/pci/emu10k1/emumpu401.c @@ -19,7 +19,6 @@ * */ -#include <sound/driver.h> #include <linux/time.h> #include <linux/init.h> #include <sound/core.h> diff --git a/sound/pci/emu10k1/emupcm.c b/sound/pci/emu10k1/emupcm.c index 5ce5bef..cf9276d 100644 --- a/sound/pci/emu10k1/emupcm.c +++ b/sound/pci/emu10k1/emupcm.c @@ -26,7 +26,6 @@ * */ -#include <sound/driver.h> #include <linux/pci.h> #include <linux/delay.h> #include <linux/slab.h> @@ -358,7 +357,7 @@ static void snd_emu10k1_pcm_init_voice(struct snd_emu10k1 *emu, snd_emu10k1_ptr_write(emu, PTRX, voice, (send_amount[0] << 8) | send_amount[1]); snd_emu10k1_ptr_write(emu, DSL, voice, end_addr | (send_amount[3] << 24)); snd_emu10k1_ptr_write(emu, PSST, voice, start_addr | (send_amount[2] << 24)); - if (emu->card_capabilities->emu1010) + if (emu->card_capabilities->emu_model) pitch_target = PITCH_48000; /* Disable interpolators on emu1010 card */ else pitch_target = emu10k1_calc_pitch_target(runtime->rate); @@ -701,7 +700,7 @@ static void snd_emu10k1_playback_trigger_voice(struct snd_emu10k1 *emu, struct s voice = evoice->number; pitch = snd_emu10k1_rate_to_pitch(runtime->rate) >> 8; - if (emu->card_capabilities->emu1010) + if (emu->card_capabilities->emu_model) pitch_target = PITCH_48000; /* Disable interpolators on emu1010 card */ else pitch_target = emu10k1_calc_pitch_target(runtime->rate); @@ -1232,7 +1231,7 @@ static int snd_emu10k1_capture_efx_open(struct snd_pcm_substream *substream) runtime->hw.rates = SNDRV_PCM_RATE_48000; runtime->hw.rate_min = runtime->hw.rate_max = 48000; spin_lock_irq(&emu->reg_lock); - if (emu->card_capabilities->emu1010) { + if (emu->card_capabilities->emu_model) { /* Nb. of channels has been increased to 16 */ /* TODO * SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE @@ -1791,7 +1790,7 @@ int __devinit snd_emu10k1_pcm_efx(struct snd_emu10k1 * emu, int device, struct s /* emu->efx_voices_mask[0] = FXWC_DEFAULTROUTE_C | FXWC_DEFAULTROUTE_A; */ if (emu->audigy) { emu->efx_voices_mask[0] = 0; - if (emu->card_capabilities->emu1010) + if (emu->card_capabilities->emu_model) /* Pavel Hofman - 32 voices will be used for * capture (write mode) - * each bit = corresponding voice diff --git a/sound/pci/emu10k1/emuproc.c b/sound/pci/emu10k1/emuproc.c index c3fb10e..f3caa3f 100644 --- a/sound/pci/emu10k1/emuproc.c +++ b/sound/pci/emu10k1/emuproc.c @@ -28,7 +28,6 @@ * */ -#include <sound/driver.h> #include <linux/slab.h> #include <linux/init.h> #include <sound/core.h> @@ -245,7 +244,7 @@ static void snd_emu10k1_proc_spdif_read(struct snd_info_entry *entry, unsigned long flags; u32 rate; - if (emu->card_capabilities->emu1010) { + if (emu->card_capabilities->emu_model) { spin_lock_irqsave(&emu->emu_lock, flags); snd_emu1010_fpga_read(emu, 0x38, &value); spin_unlock_irqrestore(&emu->emu_lock, flags); @@ -585,7 +584,7 @@ int __devinit snd_emu10k1_proc_init(struct snd_emu10k1 * emu) { struct snd_info_entry *entry; #ifdef CONFIG_SND_DEBUG - if (emu->card_capabilities->emu1010) { + if (emu->card_capabilities->emu_model) { if (! snd_card_proc_new(emu->card, "emu1010_regs", &entry)) snd_info_set_text_ops(entry, emu, snd_emu_proc_emu1010_reg_read); } diff --git a/sound/pci/emu10k1/io.c b/sound/pci/emu10k1/io.c index 6702c15..b5a802b 100644 --- a/sound/pci/emu10k1/io.c +++ b/sound/pci/emu10k1/io.c @@ -25,7 +25,6 @@ * */ -#include <sound/driver.h> #include <linux/time.h> #include <sound/core.h> #include <sound/emu10k1.h> @@ -71,6 +70,11 @@ void snd_emu10k1_ptr_write(struct snd_emu10k1 *emu, unsigned int reg, unsigned i unsigned long flags; unsigned int mask; + if (!emu) { + snd_printk(KERN_ERR "ptr_write: emu is null!\n"); + dump_stack(); + return; + } mask = emu->audigy ? A_PTR_ADDRESS_MASK : PTR_ADDRESS_MASK; regptr = ((reg << 16) & mask) | (chn & PTR_CHANNELNUM_MASK); @@ -135,15 +139,23 @@ int snd_emu10k1_spi_write(struct snd_emu10k1 * emu, unsigned int reset, set; unsigned int reg, tmp; int n, result; + int err = 0; + + /* This function is not re-entrant, so protect against it. */ + spin_lock(&emu->spi_lock); if (emu->card_capabilities->ca0108_chip) reg = 0x3c; /* PTR20, reg 0x3c */ else { /* For other chip types the SPI register * is currently unknown. */ - return 1; + err = 1; + goto spi_write_exit; + } + if (data > 0xffff) { + /* Only 16bit values allowed */ + err = 1; + goto spi_write_exit; } - if (data > 0xffff) /* Only 16bit values allowed */ - return 1; tmp = snd_emu10k1_ptr20_read(emu, reg, 0); reset = (tmp & ~0x3ffff) | 0x20000; /* Set xxx20000 */ @@ -161,11 +173,17 @@ int snd_emu10k1_spi_write(struct snd_emu10k1 * emu, break; } } - if (result) /* Timed out */ - return 1; + if (result) { + /* Timed out */ + err = 1; + goto spi_write_exit; + } snd_emu10k1_ptr20_write(emu, reg, 0, reset | data); tmp = snd_emu10k1_ptr20_read(emu, reg, 0); /* Write post */ - return 0; + err = 0; +spi_write_exit: + spin_unlock(&emu->spi_lock); + return err; } /* The ADC does not support i2c read, so only write is implemented */ @@ -177,15 +195,17 @@ int snd_emu10k1_i2c_write(struct snd_emu10k1 *emu, int timeout = 0; int status; int retry; + int err = 0; + if ((reg > 0x7f) || (value > 0x1ff)) { snd_printk(KERN_ERR "i2c_write: invalid values.\n"); return -EINVAL; } + /* This function is not re-entrant, so protect against it. */ + spin_lock(&emu->i2c_lock); + tmp = reg << 25 | value << 16; - // snd_printk("I2C-write:reg=0x%x, value=0x%x\n", reg, value); - /* Not sure what this I2C channel controls. */ - /* snd_emu10k1_ptr_write(emu, P17V_I2C_0, 0, tmp); */ /* This controls the I2C connected to the WM8775 ADC Codec */ snd_emu10k1_ptr20_write(emu, P17V_I2C_1, 0, tmp); @@ -193,17 +213,14 @@ int snd_emu10k1_i2c_write(struct snd_emu10k1 *emu, for (retry = 0; retry < 10; retry++) { /* Send the data to i2c */ - //tmp = snd_emu10k1_ptr_read(emu, P17V_I2C_ADDR, 0); - //tmp = tmp & ~(I2C_A_ADC_READ|I2C_A_ADC_LAST|I2C_A_ADC_START|I2C_A_ADC_ADD_MASK); tmp = 0; tmp = tmp | (I2C_A_ADC_LAST|I2C_A_ADC_START|I2C_A_ADC_ADD); snd_emu10k1_ptr20_write(emu, P17V_I2C_ADDR, 0, tmp); /* Wait till the transaction ends */ while (1) { - udelay(10); + mdelay(1); status = snd_emu10k1_ptr20_read(emu, P17V_I2C_ADDR, 0); - // snd_printk("I2C:status=0x%x\n", status); timeout++; if ((status & I2C_A_ADC_START) == 0) break; @@ -220,19 +237,26 @@ int snd_emu10k1_i2c_write(struct snd_emu10k1 *emu, if (retry == 10) { snd_printk(KERN_ERR "Writing to ADC failed!\n"); - return -EINVAL; + snd_printk(KERN_ERR "status=0x%x, reg=%d, value=%d\n", + status, reg, value); + /* dump_stack(); */ + err = -EINVAL; } - return 0; + spin_unlock(&emu->i2c_lock); + return err; } int snd_emu1010_fpga_write(struct snd_emu10k1 * emu, u32 reg, u32 value) { + unsigned long flags; + if (reg > 0x3f) return 1; reg += 0x40; /* 0x40 upwards are registers. */ if (value < 0 || value > 0x3f) /* 0 to 0x3f are values */ return 1; + spin_lock_irqsave(&emu->emu_lock, flags); outl(reg, emu->port + A_IOCFG); udelay(10); outl(reg | 0x80, emu->port + A_IOCFG); /* High bit clocks the value into the fpga. */ @@ -240,20 +264,24 @@ int snd_emu1010_fpga_write(struct snd_emu10k1 * emu, u32 reg, u32 value) outl(value, emu->port + A_IOCFG); udelay(10); outl(value | 0x80 , emu->port + A_IOCFG); /* High bit clocks the value into the fpga. */ + spin_unlock_irqrestore(&emu->emu_lock, flags); return 0; } int snd_emu1010_fpga_read(struct snd_emu10k1 * emu, u32 reg, u32 *value) { + unsigned long flags; if (reg > 0x3f) return 1; reg += 0x40; /* 0x40 upwards are registers. */ + spin_lock_irqsave(&emu->emu_lock, flags); outl(reg, emu->port + A_IOCFG); udelay(10); outl(reg | 0x80, emu->port + A_IOCFG); /* High bit clocks the value into the fpga. */ udelay(10); *value = ((inl(emu->port + A_IOCFG) >> 8) & 0x7f); + spin_unlock_irqrestore(&emu->emu_lock, flags); return 0; } diff --git a/sound/pci/emu10k1/irq.c b/sound/pci/emu10k1/irq.c index 3c114b4..30bfed6 100644 --- a/sound/pci/emu10k1/irq.c +++ b/sound/pci/emu10k1/irq.c @@ -25,7 +25,6 @@ * */ -#include <sound/driver.h> #include <linux/time.h> #include <sound/core.h> #include <sound/emu10k1.h> @@ -35,9 +34,10 @@ irqreturn_t snd_emu10k1_interrupt(int irq, void *dev_id) struct snd_emu10k1 *emu = dev_id; unsigned int status, status2, orig_status, orig_status2; int handled = 0; + int timeout = 0; - while ((status = inl(emu->port + IPR)) != 0) { - //snd_printk(KERN_INFO "emu10k1 irq - status = 0x%x\n", status); + while (((status = inl(emu->port + IPR)) != 0) && (timeout < 1000)) { + timeout++; orig_status = status; handled = 1; if ((status & 0xffffffff) == 0xffffffff) { @@ -201,5 +201,8 @@ irqreturn_t snd_emu10k1_interrupt(int irq, void *dev_id) } outl(orig_status, emu->port + IPR); /* ack all */ } + if (timeout == 1000) + snd_printk(KERN_INFO "emu10k1 irq routine failure\n"); + return IRQ_RETVAL(handled); } diff --git a/sound/pci/emu10k1/memory.c b/sound/pci/emu10k1/memory.c index 48097c6..916c1db 100644 --- a/sound/pci/emu10k1/memory.c +++ b/sound/pci/emu10k1/memory.c @@ -21,7 +21,6 @@ * */ -#include <sound/driver.h> #include <linux/pci.h> #include <linux/time.h> #include <linux/mutex.h> diff --git a/sound/pci/emu10k1/p16v.c b/sound/pci/emu10k1/p16v.c index 9fd3135..749a21b 100644 --- a/sound/pci/emu10k1/p16v.c +++ b/sound/pci/emu10k1/p16v.c @@ -87,7 +87,6 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ -#include <sound/driver.h> #include <linux/delay.h> #include <linux/init.h> #include <linux/interrupt.h> diff --git a/sound/pci/emu10k1/timer.c b/sound/pci/emu10k1/timer.c index 6295b2d..72321e9 100644 --- a/sound/pci/emu10k1/timer.c +++ b/sound/pci/emu10k1/timer.c @@ -25,7 +25,6 @@ * */ -#include <sound/driver.h> #include <linux/time.h> #include <sound/core.h> #include <sound/emu10k1.h> diff --git a/sound/pci/emu10k1/voice.c b/sound/pci/emu10k1/voice.c index 04fa849..958cb2a 100644 --- a/sound/pci/emu10k1/voice.c +++ b/sound/pci/emu10k1/voice.c @@ -28,7 +28,6 @@ * */ -#include <sound/driver.h> #include <linux/time.h> #include <sound/core.h> #include <sound/emu10k1.h> |