Loading include/sound/emu10k1.h +6 −2 Original line number Diff line number Diff line Loading @@ -1692,8 +1692,8 @@ struct snd_emu1010 { unsigned int clock_fallback; unsigned int optical_in; /* 0:SPDIF, 1:ADAT */ unsigned int optical_out; /* 0:SPDIF, 1:ADAT */ struct work_struct firmware_work; struct work_struct clock_work; struct work_struct work; struct mutex lock; }; struct snd_emu10k1 { Loading Loading @@ -1842,12 +1842,16 @@ unsigned int snd_emu10k1_ptr20_read(struct snd_emu10k1 * emu, unsigned int reg, void snd_emu10k1_ptr20_write(struct snd_emu10k1 *emu, unsigned int reg, unsigned int chn, unsigned int data); int snd_emu10k1_spi_write(struct snd_emu10k1 * emu, unsigned int data); int snd_emu10k1_i2c_write(struct snd_emu10k1 *emu, u32 reg, u32 value); static inline void snd_emu1010_fpga_lock(struct snd_emu10k1 *emu) { mutex_lock(&emu->emu1010.lock); }; static inline void snd_emu1010_fpga_unlock(struct snd_emu10k1 *emu) { mutex_unlock(&emu->emu1010.lock); }; void snd_emu1010_fpga_write_lock(struct snd_emu10k1 *emu, u32 reg, u32 value); void snd_emu1010_fpga_write(struct snd_emu10k1 *emu, u32 reg, u32 value); void snd_emu1010_fpga_read(struct snd_emu10k1 *emu, u32 reg, u32 *value); void snd_emu1010_fpga_link_dst_src_write(struct snd_emu10k1 *emu, u32 dst, u32 src); u32 snd_emu1010_fpga_link_dst_src_read(struct snd_emu10k1 *emu, u32 dst); int snd_emu1010_get_raw_rate(struct snd_emu10k1 *emu, u8 src); void snd_emu1010_update_clock(struct snd_emu10k1 *emu); void snd_emu1010_load_firmware_entry(struct snd_emu10k1 *emu, int dock, const struct firmware *fw_entry); unsigned int snd_emu10k1_efx_read(struct snd_emu10k1 *emu, unsigned int pc); void snd_emu10k1_intr_enable(struct snd_emu10k1 *emu, unsigned int intrenb); void snd_emu10k1_intr_disable(struct snd_emu10k1 *emu, unsigned int intrenb); Loading sound/core/seq/seq_ump_convert.c +1 −1 Original line number Diff line number Diff line Loading @@ -428,7 +428,7 @@ static int cvt_ump_midi2_to_midi1(struct snd_seq_client *dest, midi1->note.group = midi2->note.group; midi1->note.status = midi2->note.status; midi1->note.channel = midi2->note.channel; switch (midi2->note.status << 4) { switch (midi2->note.status) { case UMP_MSG_STATUS_NOTE_ON: case UMP_MSG_STATUS_NOTE_OFF: midi1->note.note = midi2->note.note; Loading sound/pci/emu10k1/emu10k1.c +1 −2 Original line number Diff line number Diff line Loading @@ -189,8 +189,7 @@ static int snd_emu10k1_suspend(struct device *dev) emu->suspend = 1; cancel_work_sync(&emu->emu1010.firmware_work); cancel_work_sync(&emu->emu1010.clock_work); cancel_work_sync(&emu->emu1010.work); snd_ac97_suspend(emu->ac97); Loading sound/pci/emu10k1/emu10k1_main.c +91 −134 Original line number Diff line number Diff line Loading @@ -652,52 +652,6 @@ static int snd_emu10k1_cardbus_init(struct snd_emu10k1 *emu) return 0; } static int snd_emu1010_load_firmware_entry(struct snd_emu10k1 *emu, const struct firmware *fw_entry) { int n, i; u16 reg; u8 value; __always_unused u16 write_post; if (!fw_entry) return -EIO; /* The FPGA is a Xilinx Spartan IIE XC2S50E */ /* On E-MU 0404b it is a Xilinx Spartan III XC3S50 */ /* GPIO7 -> FPGA PGMN * GPIO6 -> FPGA CCLK * GPIO5 -> FPGA DIN * FPGA CONFIG OFF -> FPGA PGMN */ spin_lock_irq(&emu->emu_lock); outw(0x00, emu->port + A_GPIO); /* Set PGMN low for 100uS. */ write_post = inw(emu->port + A_GPIO); udelay(100); outw(0x80, emu->port + A_GPIO); /* Leave bit 7 set during netlist setup. */ write_post = inw(emu->port + A_GPIO); udelay(100); /* Allow FPGA memory to clean */ for (n = 0; n < fw_entry->size; n++) { value = fw_entry->data[n]; for (i = 0; i < 8; i++) { reg = 0x80; if (value & 0x1) reg = reg | 0x20; value = value >> 1; outw(reg, emu->port + A_GPIO); write_post = inw(emu->port + A_GPIO); outw(reg | 0x40, emu->port + A_GPIO); write_post = inw(emu->port + A_GPIO); } } /* After programming, set GPIO bit 4 high again. */ outw(0x10, emu->port + A_GPIO); write_post = inw(emu->port + A_GPIO); spin_unlock_irq(&emu->emu_lock); return 0; } /* firmware file names, per model, init-fw and dock-fw (optional) */ static const char * const firmware_names[5][2] = { [EMU_MODEL_EMU1010] = { Loading Loading @@ -729,72 +683,68 @@ static int snd_emu1010_load_firmware(struct snd_emu10k1 *emu, int dock, return err; } return snd_emu1010_load_firmware_entry(emu, *fw); snd_emu1010_load_firmware_entry(emu, dock, *fw); return 0; } static void emu1010_firmware_work(struct work_struct *work) static void snd_emu1010_load_dock_firmware(struct snd_emu10k1 *emu) { struct snd_emu10k1 *emu; u32 tmp, tmp2, reg; u32 tmp, tmp2; int err; emu = container_of(work, struct snd_emu10k1, emu1010.firmware_work); if (emu->card->shutdown) return; #ifdef CONFIG_PM_SLEEP if (emu->suspend) return; #endif snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, ®); /* OPTIONS: Which cards are attached to the EMU */ if (reg & EMU_HANA_OPTION_DOCK_OFFLINE) { /* Audio Dock attached */ /* Return to Audio Dock programming mode */ dev_info(emu->card->dev, "emu1010: Loading Audio Dock Firmware\n"); snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG, EMU_HANA_FPGA_CONFIG_AUDIODOCK); // The docking events clearly arrive prematurely - while the // Dock's FPGA seems to be successfully programmed, the Dock // fails to initialize subsequently if we don't give it some // time to "warm up" here. msleep(200); dev_info(emu->card->dev, "emu1010: Loading Audio Dock Firmware\n"); err = snd_emu1010_load_firmware(emu, 1, &emu->dock_fw); if (err < 0) return; snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG, 0); snd_emu1010_fpga_read(emu, EMU_HANA_ID, &tmp); dev_info(emu->card->dev, "emu1010: EMU_HANA+DOCK_ID = 0x%x\n", tmp); dev_dbg(emu->card->dev, "emu1010: EMU_HANA+DOCK_ID = 0x%x\n", tmp); if ((tmp & 0x1f) != 0x15) { /* FPGA failed to be programmed */ dev_info(emu->card->dev, "emu1010: Loading Audio Dock Firmware file failed, reg = 0x%x\n", dev_err(emu->card->dev, "emu1010: Loading Audio Dock Firmware failed, reg = 0x%x\n", tmp); return; } dev_info(emu->card->dev, "emu1010: Audio Dock Firmware loaded\n"); dev_info(emu->card->dev, "emu1010: Audio Dock Firmware loaded\n"); snd_emu1010_fpga_read(emu, EMU_DOCK_MAJOR_REV, &tmp); snd_emu1010_fpga_read(emu, EMU_DOCK_MINOR_REV, &tmp2); dev_info(emu->card->dev, "Audio Dock ver: %u.%u\n", tmp, tmp2); /* Sync clocking between 1010 and Dock */ /* Allow DLL to settle */ /* Allow DLL to settle, to sync clocking between 1010 and Dock */ msleep(10); } static void emu1010_dock_event(struct snd_emu10k1 *emu) { u32 reg; snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, ®); /* OPTIONS: Which cards are attached to the EMU */ if (reg & EMU_HANA_OPTION_DOCK_OFFLINE) { /* Audio Dock attached */ snd_emu1010_load_dock_firmware(emu); /* Unmute all. Default is muted after a firmware load */ snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE); } else if (!(reg & EMU_HANA_OPTION_DOCK_ONLINE)) { /* Audio Dock removed */ dev_info(emu->card->dev, "emu1010: Audio Dock detached\n"); /* The hardware auto-mutes all, so we unmute again */ snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE); } } static void emu1010_clock_work(struct work_struct *work) static void emu1010_clock_event(struct snd_emu10k1 *emu) { struct snd_emu10k1 *emu; struct snd_ctl_elem_id id; emu = container_of(work, struct snd_emu10k1, emu1010.clock_work); if (emu->card->shutdown) return; #ifdef CONFIG_PM_SLEEP if (emu->suspend) return; #endif spin_lock_irq(&emu->reg_lock); // This is the only thing that can actually happen. emu->emu1010.clock_source = emu->emu1010.clock_fallback; Loading @@ -805,21 +755,44 @@ static void emu1010_clock_work(struct work_struct *work) snd_ctl_notify(emu->card, SNDRV_CTL_EVENT_MASK_VALUE, &id); } static void emu1010_interrupt(struct snd_emu10k1 *emu) static void emu1010_work(struct work_struct *work) { struct snd_emu10k1 *emu; u32 sts; emu = container_of(work, struct snd_emu10k1, emu1010.work); if (emu->card->shutdown) return; #ifdef CONFIG_PM_SLEEP if (emu->suspend) return; #endif snd_emu1010_fpga_lock(emu); snd_emu1010_fpga_read(emu, EMU_HANA_IRQ_STATUS, &sts); if (sts & EMU_HANA_IRQ_DOCK_LOST) { /* Audio Dock removed */ dev_info(emu->card->dev, "emu1010: Audio Dock detached\n"); /* The hardware auto-mutes all, so we unmute again */ snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE); } else if (sts & EMU_HANA_IRQ_DOCK) { schedule_work(&emu->emu1010.firmware_work); } // The distinction of the IRQ status bits is unreliable, // so we dispatch later based on option card status. if (sts & (EMU_HANA_IRQ_DOCK | EMU_HANA_IRQ_DOCK_LOST)) emu1010_dock_event(emu); if (sts & EMU_HANA_IRQ_WCLK_CHANGED) schedule_work(&emu->emu1010.clock_work); emu1010_clock_event(emu); snd_emu1010_fpga_unlock(emu); } static void emu1010_interrupt(struct snd_emu10k1 *emu) { // We get an interrupt on each GPIO input pin change, but we // care only about the ones triggered by the dedicated pin. u16 sts = inw(emu->port + A_GPIO); u16 bit = emu->card_capabilities->ca0108_chip ? 0x2000 : 0x8000; if (!(sts & bit)) return; schedule_work(&emu->emu1010.work); } /* Loading @@ -841,32 +814,13 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 *emu) * Proper init follows in snd_emu10k1_init(). */ outl(HCFG_LOCKSOUNDCACHE | HCFG_LOCKTANKCACHE_MASK, emu->port + HCFG); /* Disable 48Volt power to Audio Dock */ snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_PWR, 0); /* ID, should read & 0x7f = 0x55. (Bit 7 is the IRQ bit) */ snd_emu1010_fpga_read(emu, EMU_HANA_ID, ®); dev_dbg(emu->card->dev, "reg1 = 0x%x\n", reg); if ((reg & 0x3f) == 0x15) { /* FPGA netlist already present so clear it */ /* Return to programming mode */ snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG, EMU_HANA_FPGA_CONFIG_HANA); } snd_emu1010_fpga_read(emu, EMU_HANA_ID, ®); dev_dbg(emu->card->dev, "reg2 = 0x%x\n", reg); if ((reg & 0x3f) == 0x15) { /* FPGA failed to return to programming mode */ dev_info(emu->card->dev, "emu1010: FPGA failed to return to programming mode\n"); return -ENODEV; } dev_info(emu->card->dev, "emu1010: EMU_HANA_ID = 0x%x\n", reg); snd_emu1010_fpga_lock(emu); dev_info(emu->card->dev, "emu1010: Loading Hana Firmware\n"); err = snd_emu1010_load_firmware(emu, 0, &emu->firmware); if (err < 0) { dev_info(emu->card->dev, "emu1010: Loading Firmware failed\n"); return err; goto fail; } /* ID, should read & 0x7f = 0x55 when FPGA programmed. */ Loading @@ -876,7 +830,8 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 *emu) dev_info(emu->card->dev, "emu1010: Loading Hana Firmware file failed, reg = 0x%x\n", reg); return -ENODEV; err = -ENODEV; goto fail; } dev_info(emu->card->dev, "emu1010: Hana Firmware loaded\n"); Loading @@ -889,7 +844,7 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 *emu) snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, ®); dev_info(emu->card->dev, "emu1010: Card options = 0x%x\n", reg); if (reg & EMU_HANA_OPTION_DOCK_OFFLINE) schedule_work(&emu->emu1010.firmware_work); snd_emu1010_load_dock_firmware(emu); if (emu->card_capabilities->no_adat) { emu->emu1010.optical_in = 0; /* IN_SPDIF */ emu->emu1010.optical_out = 0; /* OUT_SPDIF */ Loading Loading @@ -936,7 +891,9 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 *emu) // so it is safe to simply enable the outputs. snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE); return 0; fail: snd_emu1010_fpga_unlock(emu); return err; } /* * Create the EMU10K1 instance Loading @@ -958,10 +915,10 @@ static void snd_emu10k1_free(struct snd_card *card) } 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); snd_emu1010_fpga_write_lock(emu, EMU_HANA_DOCK_PWR, 0); } cancel_work_sync(&emu->emu1010.firmware_work); cancel_work_sync(&emu->emu1010.clock_work); cancel_work_sync(&emu->emu1010.work); mutex_destroy(&emu->emu1010.lock); release_firmware(emu->firmware); release_firmware(emu->dock_fw); snd_util_memhdr_free(emu->memhdr); Loading Loading @@ -1540,8 +1497,8 @@ int snd_emu10k1_create(struct snd_card *card, emu->irq = -1; emu->synth = NULL; emu->get_synth_voice = NULL; INIT_WORK(&emu->emu1010.firmware_work, emu1010_firmware_work); INIT_WORK(&emu->emu1010.clock_work, emu1010_clock_work); INIT_WORK(&emu->emu1010.work, emu1010_work); mutex_init(&emu->emu1010.lock); /* read revision & serial */ emu->revision = pci->revision; pci_read_config_dword(pci, PCI_SUBSYSTEM_VENDOR_ID, &emu->serial); Loading sound/pci/emu10k1/emumixer.c +13 −5 Original line number Diff line number Diff line Loading @@ -661,7 +661,9 @@ static int snd_emu1010_output_source_put(struct snd_kcontrol *kcontrol, change = (emu->emu1010.output_source[channel] != val); if (change) { emu->emu1010.output_source[channel] = val; snd_emu1010_fpga_lock(emu); snd_emu1010_output_source_apply(emu, channel, val); snd_emu1010_fpga_unlock(emu); } return change; } Loading Loading @@ -705,7 +707,9 @@ static int snd_emu1010_input_source_put(struct snd_kcontrol *kcontrol, change = (emu->emu1010.input_source[channel] != val); if (change) { emu->emu1010.input_source[channel] = val; snd_emu1010_fpga_lock(emu); snd_emu1010_input_source_apply(emu, channel, val); snd_emu1010_fpga_unlock(emu); } return change; } Loading Loading @@ -774,7 +778,7 @@ static int snd_emu1010_adc_pads_put(struct snd_kcontrol *kcontrol, struct snd_ct cache = cache & ~mask; change = (cache != emu->emu1010.adc_pads); if (change) { snd_emu1010_fpga_write(emu, EMU_HANA_ADC_PADS, cache ); snd_emu1010_fpga_write_lock(emu, EMU_HANA_ADC_PADS, cache ); emu->emu1010.adc_pads = cache; } Loading Loading @@ -832,7 +836,7 @@ static int snd_emu1010_dac_pads_put(struct snd_kcontrol *kcontrol, struct snd_ct cache = cache & ~mask; change = (cache != emu->emu1010.dac_pads); if (change) { snd_emu1010_fpga_write(emu, EMU_HANA_DAC_PADS, cache ); snd_emu1010_fpga_write_lock(emu, EMU_HANA_DAC_PADS, cache ); emu->emu1010.dac_pads = cache; } Loading Loading @@ -980,6 +984,7 @@ static int snd_emu1010_clock_source_put(struct snd_kcontrol *kcontrol, val = ucontrol->value.enumerated.item[0] ; if (val >= emu_ci->num) return -EINVAL; snd_emu1010_fpga_lock(emu); spin_lock_irq(&emu->reg_lock); change = (emu->emu1010.clock_source != val); if (change) { Loading @@ -996,6 +1001,7 @@ static int snd_emu1010_clock_source_put(struct snd_kcontrol *kcontrol, } else { spin_unlock_irq(&emu->reg_lock); } snd_emu1010_fpga_unlock(emu); return change; } Loading Loading @@ -1041,7 +1047,7 @@ static int snd_emu1010_clock_fallback_put(struct snd_kcontrol *kcontrol, change = (emu->emu1010.clock_fallback != val); if (change) { emu->emu1010.clock_fallback = val; snd_emu1010_fpga_write(emu, EMU_HANA_DEFCLOCK, 1 - val); snd_emu1010_fpga_write_lock(emu, EMU_HANA_DEFCLOCK, 1 - val); } return change; } Loading Loading @@ -1093,7 +1099,7 @@ static int snd_emu1010_optical_out_put(struct snd_kcontrol *kcontrol, emu->emu1010.optical_out = val; tmp = (emu->emu1010.optical_in ? EMU_HANA_OPTICAL_IN_ADAT : EMU_HANA_OPTICAL_IN_SPDIF) | (emu->emu1010.optical_out ? EMU_HANA_OPTICAL_OUT_ADAT : EMU_HANA_OPTICAL_OUT_SPDIF); snd_emu1010_fpga_write(emu, EMU_HANA_OPTICAL_TYPE, tmp); snd_emu1010_fpga_write_lock(emu, EMU_HANA_OPTICAL_TYPE, tmp); } return change; } Loading Loading @@ -1144,7 +1150,7 @@ static int snd_emu1010_optical_in_put(struct snd_kcontrol *kcontrol, emu->emu1010.optical_in = val; tmp = (emu->emu1010.optical_in ? EMU_HANA_OPTICAL_IN_ADAT : EMU_HANA_OPTICAL_IN_SPDIF) | (emu->emu1010.optical_out ? EMU_HANA_OPTICAL_OUT_ADAT : EMU_HANA_OPTICAL_OUT_SPDIF); snd_emu1010_fpga_write(emu, EMU_HANA_OPTICAL_TYPE, tmp); snd_emu1010_fpga_write_lock(emu, EMU_HANA_OPTICAL_TYPE, tmp); } return change; } Loading Loading @@ -2323,7 +2329,9 @@ int snd_emu10k1_mixer(struct snd_emu10k1 *emu, for (i = 0; i < emu_ri->n_outs; i++) emu->emu1010.output_source[i] = emu1010_map_source(emu_ri, emu_ri->out_dflts[i]); snd_emu1010_fpga_lock(emu); snd_emu1010_apply_sources(emu); snd_emu1010_fpga_unlock(emu); kctl = emu->ctl_clock_source = snd_ctl_new1(&snd_emu1010_clock_source, emu); err = snd_ctl_add(card, kctl); Loading Loading
include/sound/emu10k1.h +6 −2 Original line number Diff line number Diff line Loading @@ -1692,8 +1692,8 @@ struct snd_emu1010 { unsigned int clock_fallback; unsigned int optical_in; /* 0:SPDIF, 1:ADAT */ unsigned int optical_out; /* 0:SPDIF, 1:ADAT */ struct work_struct firmware_work; struct work_struct clock_work; struct work_struct work; struct mutex lock; }; struct snd_emu10k1 { Loading Loading @@ -1842,12 +1842,16 @@ unsigned int snd_emu10k1_ptr20_read(struct snd_emu10k1 * emu, unsigned int reg, void snd_emu10k1_ptr20_write(struct snd_emu10k1 *emu, unsigned int reg, unsigned int chn, unsigned int data); int snd_emu10k1_spi_write(struct snd_emu10k1 * emu, unsigned int data); int snd_emu10k1_i2c_write(struct snd_emu10k1 *emu, u32 reg, u32 value); static inline void snd_emu1010_fpga_lock(struct snd_emu10k1 *emu) { mutex_lock(&emu->emu1010.lock); }; static inline void snd_emu1010_fpga_unlock(struct snd_emu10k1 *emu) { mutex_unlock(&emu->emu1010.lock); }; void snd_emu1010_fpga_write_lock(struct snd_emu10k1 *emu, u32 reg, u32 value); void snd_emu1010_fpga_write(struct snd_emu10k1 *emu, u32 reg, u32 value); void snd_emu1010_fpga_read(struct snd_emu10k1 *emu, u32 reg, u32 *value); void snd_emu1010_fpga_link_dst_src_write(struct snd_emu10k1 *emu, u32 dst, u32 src); u32 snd_emu1010_fpga_link_dst_src_read(struct snd_emu10k1 *emu, u32 dst); int snd_emu1010_get_raw_rate(struct snd_emu10k1 *emu, u8 src); void snd_emu1010_update_clock(struct snd_emu10k1 *emu); void snd_emu1010_load_firmware_entry(struct snd_emu10k1 *emu, int dock, const struct firmware *fw_entry); unsigned int snd_emu10k1_efx_read(struct snd_emu10k1 *emu, unsigned int pc); void snd_emu10k1_intr_enable(struct snd_emu10k1 *emu, unsigned int intrenb); void snd_emu10k1_intr_disable(struct snd_emu10k1 *emu, unsigned int intrenb); Loading
sound/core/seq/seq_ump_convert.c +1 −1 Original line number Diff line number Diff line Loading @@ -428,7 +428,7 @@ static int cvt_ump_midi2_to_midi1(struct snd_seq_client *dest, midi1->note.group = midi2->note.group; midi1->note.status = midi2->note.status; midi1->note.channel = midi2->note.channel; switch (midi2->note.status << 4) { switch (midi2->note.status) { case UMP_MSG_STATUS_NOTE_ON: case UMP_MSG_STATUS_NOTE_OFF: midi1->note.note = midi2->note.note; Loading
sound/pci/emu10k1/emu10k1.c +1 −2 Original line number Diff line number Diff line Loading @@ -189,8 +189,7 @@ static int snd_emu10k1_suspend(struct device *dev) emu->suspend = 1; cancel_work_sync(&emu->emu1010.firmware_work); cancel_work_sync(&emu->emu1010.clock_work); cancel_work_sync(&emu->emu1010.work); snd_ac97_suspend(emu->ac97); Loading
sound/pci/emu10k1/emu10k1_main.c +91 −134 Original line number Diff line number Diff line Loading @@ -652,52 +652,6 @@ static int snd_emu10k1_cardbus_init(struct snd_emu10k1 *emu) return 0; } static int snd_emu1010_load_firmware_entry(struct snd_emu10k1 *emu, const struct firmware *fw_entry) { int n, i; u16 reg; u8 value; __always_unused u16 write_post; if (!fw_entry) return -EIO; /* The FPGA is a Xilinx Spartan IIE XC2S50E */ /* On E-MU 0404b it is a Xilinx Spartan III XC3S50 */ /* GPIO7 -> FPGA PGMN * GPIO6 -> FPGA CCLK * GPIO5 -> FPGA DIN * FPGA CONFIG OFF -> FPGA PGMN */ spin_lock_irq(&emu->emu_lock); outw(0x00, emu->port + A_GPIO); /* Set PGMN low for 100uS. */ write_post = inw(emu->port + A_GPIO); udelay(100); outw(0x80, emu->port + A_GPIO); /* Leave bit 7 set during netlist setup. */ write_post = inw(emu->port + A_GPIO); udelay(100); /* Allow FPGA memory to clean */ for (n = 0; n < fw_entry->size; n++) { value = fw_entry->data[n]; for (i = 0; i < 8; i++) { reg = 0x80; if (value & 0x1) reg = reg | 0x20; value = value >> 1; outw(reg, emu->port + A_GPIO); write_post = inw(emu->port + A_GPIO); outw(reg | 0x40, emu->port + A_GPIO); write_post = inw(emu->port + A_GPIO); } } /* After programming, set GPIO bit 4 high again. */ outw(0x10, emu->port + A_GPIO); write_post = inw(emu->port + A_GPIO); spin_unlock_irq(&emu->emu_lock); return 0; } /* firmware file names, per model, init-fw and dock-fw (optional) */ static const char * const firmware_names[5][2] = { [EMU_MODEL_EMU1010] = { Loading Loading @@ -729,72 +683,68 @@ static int snd_emu1010_load_firmware(struct snd_emu10k1 *emu, int dock, return err; } return snd_emu1010_load_firmware_entry(emu, *fw); snd_emu1010_load_firmware_entry(emu, dock, *fw); return 0; } static void emu1010_firmware_work(struct work_struct *work) static void snd_emu1010_load_dock_firmware(struct snd_emu10k1 *emu) { struct snd_emu10k1 *emu; u32 tmp, tmp2, reg; u32 tmp, tmp2; int err; emu = container_of(work, struct snd_emu10k1, emu1010.firmware_work); if (emu->card->shutdown) return; #ifdef CONFIG_PM_SLEEP if (emu->suspend) return; #endif snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, ®); /* OPTIONS: Which cards are attached to the EMU */ if (reg & EMU_HANA_OPTION_DOCK_OFFLINE) { /* Audio Dock attached */ /* Return to Audio Dock programming mode */ dev_info(emu->card->dev, "emu1010: Loading Audio Dock Firmware\n"); snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG, EMU_HANA_FPGA_CONFIG_AUDIODOCK); // The docking events clearly arrive prematurely - while the // Dock's FPGA seems to be successfully programmed, the Dock // fails to initialize subsequently if we don't give it some // time to "warm up" here. msleep(200); dev_info(emu->card->dev, "emu1010: Loading Audio Dock Firmware\n"); err = snd_emu1010_load_firmware(emu, 1, &emu->dock_fw); if (err < 0) return; snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG, 0); snd_emu1010_fpga_read(emu, EMU_HANA_ID, &tmp); dev_info(emu->card->dev, "emu1010: EMU_HANA+DOCK_ID = 0x%x\n", tmp); dev_dbg(emu->card->dev, "emu1010: EMU_HANA+DOCK_ID = 0x%x\n", tmp); if ((tmp & 0x1f) != 0x15) { /* FPGA failed to be programmed */ dev_info(emu->card->dev, "emu1010: Loading Audio Dock Firmware file failed, reg = 0x%x\n", dev_err(emu->card->dev, "emu1010: Loading Audio Dock Firmware failed, reg = 0x%x\n", tmp); return; } dev_info(emu->card->dev, "emu1010: Audio Dock Firmware loaded\n"); dev_info(emu->card->dev, "emu1010: Audio Dock Firmware loaded\n"); snd_emu1010_fpga_read(emu, EMU_DOCK_MAJOR_REV, &tmp); snd_emu1010_fpga_read(emu, EMU_DOCK_MINOR_REV, &tmp2); dev_info(emu->card->dev, "Audio Dock ver: %u.%u\n", tmp, tmp2); /* Sync clocking between 1010 and Dock */ /* Allow DLL to settle */ /* Allow DLL to settle, to sync clocking between 1010 and Dock */ msleep(10); } static void emu1010_dock_event(struct snd_emu10k1 *emu) { u32 reg; snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, ®); /* OPTIONS: Which cards are attached to the EMU */ if (reg & EMU_HANA_OPTION_DOCK_OFFLINE) { /* Audio Dock attached */ snd_emu1010_load_dock_firmware(emu); /* Unmute all. Default is muted after a firmware load */ snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE); } else if (!(reg & EMU_HANA_OPTION_DOCK_ONLINE)) { /* Audio Dock removed */ dev_info(emu->card->dev, "emu1010: Audio Dock detached\n"); /* The hardware auto-mutes all, so we unmute again */ snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE); } } static void emu1010_clock_work(struct work_struct *work) static void emu1010_clock_event(struct snd_emu10k1 *emu) { struct snd_emu10k1 *emu; struct snd_ctl_elem_id id; emu = container_of(work, struct snd_emu10k1, emu1010.clock_work); if (emu->card->shutdown) return; #ifdef CONFIG_PM_SLEEP if (emu->suspend) return; #endif spin_lock_irq(&emu->reg_lock); // This is the only thing that can actually happen. emu->emu1010.clock_source = emu->emu1010.clock_fallback; Loading @@ -805,21 +755,44 @@ static void emu1010_clock_work(struct work_struct *work) snd_ctl_notify(emu->card, SNDRV_CTL_EVENT_MASK_VALUE, &id); } static void emu1010_interrupt(struct snd_emu10k1 *emu) static void emu1010_work(struct work_struct *work) { struct snd_emu10k1 *emu; u32 sts; emu = container_of(work, struct snd_emu10k1, emu1010.work); if (emu->card->shutdown) return; #ifdef CONFIG_PM_SLEEP if (emu->suspend) return; #endif snd_emu1010_fpga_lock(emu); snd_emu1010_fpga_read(emu, EMU_HANA_IRQ_STATUS, &sts); if (sts & EMU_HANA_IRQ_DOCK_LOST) { /* Audio Dock removed */ dev_info(emu->card->dev, "emu1010: Audio Dock detached\n"); /* The hardware auto-mutes all, so we unmute again */ snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE); } else if (sts & EMU_HANA_IRQ_DOCK) { schedule_work(&emu->emu1010.firmware_work); } // The distinction of the IRQ status bits is unreliable, // so we dispatch later based on option card status. if (sts & (EMU_HANA_IRQ_DOCK | EMU_HANA_IRQ_DOCK_LOST)) emu1010_dock_event(emu); if (sts & EMU_HANA_IRQ_WCLK_CHANGED) schedule_work(&emu->emu1010.clock_work); emu1010_clock_event(emu); snd_emu1010_fpga_unlock(emu); } static void emu1010_interrupt(struct snd_emu10k1 *emu) { // We get an interrupt on each GPIO input pin change, but we // care only about the ones triggered by the dedicated pin. u16 sts = inw(emu->port + A_GPIO); u16 bit = emu->card_capabilities->ca0108_chip ? 0x2000 : 0x8000; if (!(sts & bit)) return; schedule_work(&emu->emu1010.work); } /* Loading @@ -841,32 +814,13 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 *emu) * Proper init follows in snd_emu10k1_init(). */ outl(HCFG_LOCKSOUNDCACHE | HCFG_LOCKTANKCACHE_MASK, emu->port + HCFG); /* Disable 48Volt power to Audio Dock */ snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_PWR, 0); /* ID, should read & 0x7f = 0x55. (Bit 7 is the IRQ bit) */ snd_emu1010_fpga_read(emu, EMU_HANA_ID, ®); dev_dbg(emu->card->dev, "reg1 = 0x%x\n", reg); if ((reg & 0x3f) == 0x15) { /* FPGA netlist already present so clear it */ /* Return to programming mode */ snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG, EMU_HANA_FPGA_CONFIG_HANA); } snd_emu1010_fpga_read(emu, EMU_HANA_ID, ®); dev_dbg(emu->card->dev, "reg2 = 0x%x\n", reg); if ((reg & 0x3f) == 0x15) { /* FPGA failed to return to programming mode */ dev_info(emu->card->dev, "emu1010: FPGA failed to return to programming mode\n"); return -ENODEV; } dev_info(emu->card->dev, "emu1010: EMU_HANA_ID = 0x%x\n", reg); snd_emu1010_fpga_lock(emu); dev_info(emu->card->dev, "emu1010: Loading Hana Firmware\n"); err = snd_emu1010_load_firmware(emu, 0, &emu->firmware); if (err < 0) { dev_info(emu->card->dev, "emu1010: Loading Firmware failed\n"); return err; goto fail; } /* ID, should read & 0x7f = 0x55 when FPGA programmed. */ Loading @@ -876,7 +830,8 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 *emu) dev_info(emu->card->dev, "emu1010: Loading Hana Firmware file failed, reg = 0x%x\n", reg); return -ENODEV; err = -ENODEV; goto fail; } dev_info(emu->card->dev, "emu1010: Hana Firmware loaded\n"); Loading @@ -889,7 +844,7 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 *emu) snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, ®); dev_info(emu->card->dev, "emu1010: Card options = 0x%x\n", reg); if (reg & EMU_HANA_OPTION_DOCK_OFFLINE) schedule_work(&emu->emu1010.firmware_work); snd_emu1010_load_dock_firmware(emu); if (emu->card_capabilities->no_adat) { emu->emu1010.optical_in = 0; /* IN_SPDIF */ emu->emu1010.optical_out = 0; /* OUT_SPDIF */ Loading Loading @@ -936,7 +891,9 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 *emu) // so it is safe to simply enable the outputs. snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE); return 0; fail: snd_emu1010_fpga_unlock(emu); return err; } /* * Create the EMU10K1 instance Loading @@ -958,10 +915,10 @@ static void snd_emu10k1_free(struct snd_card *card) } 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); snd_emu1010_fpga_write_lock(emu, EMU_HANA_DOCK_PWR, 0); } cancel_work_sync(&emu->emu1010.firmware_work); cancel_work_sync(&emu->emu1010.clock_work); cancel_work_sync(&emu->emu1010.work); mutex_destroy(&emu->emu1010.lock); release_firmware(emu->firmware); release_firmware(emu->dock_fw); snd_util_memhdr_free(emu->memhdr); Loading Loading @@ -1540,8 +1497,8 @@ int snd_emu10k1_create(struct snd_card *card, emu->irq = -1; emu->synth = NULL; emu->get_synth_voice = NULL; INIT_WORK(&emu->emu1010.firmware_work, emu1010_firmware_work); INIT_WORK(&emu->emu1010.clock_work, emu1010_clock_work); INIT_WORK(&emu->emu1010.work, emu1010_work); mutex_init(&emu->emu1010.lock); /* read revision & serial */ emu->revision = pci->revision; pci_read_config_dword(pci, PCI_SUBSYSTEM_VENDOR_ID, &emu->serial); Loading
sound/pci/emu10k1/emumixer.c +13 −5 Original line number Diff line number Diff line Loading @@ -661,7 +661,9 @@ static int snd_emu1010_output_source_put(struct snd_kcontrol *kcontrol, change = (emu->emu1010.output_source[channel] != val); if (change) { emu->emu1010.output_source[channel] = val; snd_emu1010_fpga_lock(emu); snd_emu1010_output_source_apply(emu, channel, val); snd_emu1010_fpga_unlock(emu); } return change; } Loading Loading @@ -705,7 +707,9 @@ static int snd_emu1010_input_source_put(struct snd_kcontrol *kcontrol, change = (emu->emu1010.input_source[channel] != val); if (change) { emu->emu1010.input_source[channel] = val; snd_emu1010_fpga_lock(emu); snd_emu1010_input_source_apply(emu, channel, val); snd_emu1010_fpga_unlock(emu); } return change; } Loading Loading @@ -774,7 +778,7 @@ static int snd_emu1010_adc_pads_put(struct snd_kcontrol *kcontrol, struct snd_ct cache = cache & ~mask; change = (cache != emu->emu1010.adc_pads); if (change) { snd_emu1010_fpga_write(emu, EMU_HANA_ADC_PADS, cache ); snd_emu1010_fpga_write_lock(emu, EMU_HANA_ADC_PADS, cache ); emu->emu1010.adc_pads = cache; } Loading Loading @@ -832,7 +836,7 @@ static int snd_emu1010_dac_pads_put(struct snd_kcontrol *kcontrol, struct snd_ct cache = cache & ~mask; change = (cache != emu->emu1010.dac_pads); if (change) { snd_emu1010_fpga_write(emu, EMU_HANA_DAC_PADS, cache ); snd_emu1010_fpga_write_lock(emu, EMU_HANA_DAC_PADS, cache ); emu->emu1010.dac_pads = cache; } Loading Loading @@ -980,6 +984,7 @@ static int snd_emu1010_clock_source_put(struct snd_kcontrol *kcontrol, val = ucontrol->value.enumerated.item[0] ; if (val >= emu_ci->num) return -EINVAL; snd_emu1010_fpga_lock(emu); spin_lock_irq(&emu->reg_lock); change = (emu->emu1010.clock_source != val); if (change) { Loading @@ -996,6 +1001,7 @@ static int snd_emu1010_clock_source_put(struct snd_kcontrol *kcontrol, } else { spin_unlock_irq(&emu->reg_lock); } snd_emu1010_fpga_unlock(emu); return change; } Loading Loading @@ -1041,7 +1047,7 @@ static int snd_emu1010_clock_fallback_put(struct snd_kcontrol *kcontrol, change = (emu->emu1010.clock_fallback != val); if (change) { emu->emu1010.clock_fallback = val; snd_emu1010_fpga_write(emu, EMU_HANA_DEFCLOCK, 1 - val); snd_emu1010_fpga_write_lock(emu, EMU_HANA_DEFCLOCK, 1 - val); } return change; } Loading Loading @@ -1093,7 +1099,7 @@ static int snd_emu1010_optical_out_put(struct snd_kcontrol *kcontrol, emu->emu1010.optical_out = val; tmp = (emu->emu1010.optical_in ? EMU_HANA_OPTICAL_IN_ADAT : EMU_HANA_OPTICAL_IN_SPDIF) | (emu->emu1010.optical_out ? EMU_HANA_OPTICAL_OUT_ADAT : EMU_HANA_OPTICAL_OUT_SPDIF); snd_emu1010_fpga_write(emu, EMU_HANA_OPTICAL_TYPE, tmp); snd_emu1010_fpga_write_lock(emu, EMU_HANA_OPTICAL_TYPE, tmp); } return change; } Loading Loading @@ -1144,7 +1150,7 @@ static int snd_emu1010_optical_in_put(struct snd_kcontrol *kcontrol, emu->emu1010.optical_in = val; tmp = (emu->emu1010.optical_in ? EMU_HANA_OPTICAL_IN_ADAT : EMU_HANA_OPTICAL_IN_SPDIF) | (emu->emu1010.optical_out ? EMU_HANA_OPTICAL_OUT_ADAT : EMU_HANA_OPTICAL_OUT_SPDIF); snd_emu1010_fpga_write(emu, EMU_HANA_OPTICAL_TYPE, tmp); snd_emu1010_fpga_write_lock(emu, EMU_HANA_OPTICAL_TYPE, tmp); } return change; } Loading Loading @@ -2323,7 +2329,9 @@ int snd_emu10k1_mixer(struct snd_emu10k1 *emu, for (i = 0; i < emu_ri->n_outs; i++) emu->emu1010.output_source[i] = emu1010_map_source(emu_ri, emu_ri->out_dflts[i]); snd_emu1010_fpga_lock(emu); snd_emu1010_apply_sources(emu); snd_emu1010_fpga_unlock(emu); kctl = emu->ctl_clock_source = snd_ctl_new1(&snd_emu1010_clock_source, emu); err = snd_ctl_add(card, kctl); Loading