ALSA: emu10k1: make E-MU dock monitoring interrupt-driven
... instead of using a one-second polling timer. Signed-off-by: Oswald Buddenhagen <oswald.buddenhagen@gmx.de> Link: https://lore.kernel.org/r/20230710065956.1246364-1-oswald.buddenhagen@gmx.de Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
parent
7d43f51e40
commit
fbb64eedf5
|
@ -1678,8 +1678,7 @@ struct snd_emu1010 {
|
|||
unsigned int clock_fallback;
|
||||
unsigned int optical_in; /* 0:SPDIF, 1:ADAT */
|
||||
unsigned int optical_out; /* 0:SPDIF, 1:ADAT */
|
||||
struct delayed_work firmware_work;
|
||||
u32 last_reg;
|
||||
struct work_struct firmware_work;
|
||||
};
|
||||
|
||||
struct snd_emu10k1 {
|
||||
|
@ -1761,6 +1760,7 @@ struct snd_emu10k1 {
|
|||
void (*capture_efx_interrupt)(struct snd_emu10k1 *emu, unsigned int status);
|
||||
void (*spdif_interrupt)(struct snd_emu10k1 *emu, unsigned int status);
|
||||
void (*dsp_interrupt)(struct snd_emu10k1 *emu);
|
||||
void (*gpio_interrupt)(struct snd_emu10k1 *emu);
|
||||
void (*p16v_interrupt)(struct snd_emu10k1 *emu);
|
||||
|
||||
struct snd_pcm_substream *pcm_capture_substream;
|
||||
|
|
|
@ -176,9 +176,6 @@ static int snd_card_emu10k1_probe(struct pci_dev *pci,
|
|||
if (err < 0)
|
||||
return err;
|
||||
|
||||
if (emu->card_capabilities->emu_model)
|
||||
schedule_delayed_work(&emu->emu1010.firmware_work, 0);
|
||||
|
||||
pci_set_drvdata(pci, card);
|
||||
dev++;
|
||||
return 0;
|
||||
|
@ -194,7 +191,7 @@ static int snd_emu10k1_suspend(struct device *dev)
|
|||
|
||||
emu->suspend = 1;
|
||||
|
||||
cancel_delayed_work_sync(&emu->emu1010.firmware_work);
|
||||
cancel_work_sync(&emu->emu1010.firmware_work);
|
||||
|
||||
snd_ac97_suspend(emu->ac97);
|
||||
|
||||
|
@ -224,9 +221,6 @@ static int snd_emu10k1_resume(struct device *dev)
|
|||
|
||||
snd_power_change_state(card, SNDRV_CTL_POWER_D0);
|
||||
|
||||
if (emu->card_capabilities->emu_model)
|
||||
schedule_delayed_work(&emu->emu1010.firmware_work, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -391,7 +391,10 @@ static void snd_emu10k1_audio_enable(struct snd_emu10k1 *emu)
|
|||
}
|
||||
#endif
|
||||
|
||||
snd_emu10k1_intr_enable(emu, INTE_PCIERRORENABLE);
|
||||
if (emu->card_capabilities->emu_model)
|
||||
snd_emu10k1_intr_enable(emu, INTE_PCIERRORENABLE | INTE_A_GPIOENABLE);
|
||||
else
|
||||
snd_emu10k1_intr_enable(emu, INTE_PCIERRORENABLE);
|
||||
}
|
||||
|
||||
int snd_emu10k1_done(struct snd_emu10k1 *emu)
|
||||
|
@ -745,14 +748,13 @@ static void emu1010_firmware_work(struct work_struct *work)
|
|||
int err;
|
||||
|
||||
emu = container_of(work, struct snd_emu10k1,
|
||||
emu1010.firmware_work.work);
|
||||
emu1010.firmware_work);
|
||||
if (emu->card->shutdown)
|
||||
return;
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
if (emu->suspend)
|
||||
return;
|
||||
#endif
|
||||
snd_emu1010_fpga_read(emu, EMU_HANA_IRQ_STATUS, &tmp); /* IRQ Status */
|
||||
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 */
|
||||
|
@ -763,13 +765,8 @@ static void emu1010_firmware_work(struct work_struct *work)
|
|||
EMU_HANA_FPGA_CONFIG_AUDIODOCK);
|
||||
err = snd_emu1010_load_firmware(emu, 1, &emu->dock_fw);
|
||||
if (err < 0)
|
||||
goto next;
|
||||
|
||||
return;
|
||||
snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG, 0);
|
||||
snd_emu1010_fpga_read(emu, EMU_HANA_IRQ_STATUS, &tmp);
|
||||
dev_info(emu->card->dev,
|
||||
"emu1010: EMU_HANA+DOCK_IRQ_STATUS = 0x%x\n", tmp);
|
||||
/* ID, should read & 0x7f = 0x55 when FPGA programmed. */
|
||||
snd_emu1010_fpga_read(emu, EMU_HANA_ID, &tmp);
|
||||
dev_info(emu->card->dev,
|
||||
"emu1010: EMU_HANA+DOCK_ID = 0x%x\n", tmp);
|
||||
|
@ -778,7 +775,7 @@ static void emu1010_firmware_work(struct work_struct *work)
|
|||
dev_info(emu->card->dev,
|
||||
"emu1010: Loading Audio Dock Firmware file failed, reg = 0x%x\n",
|
||||
tmp);
|
||||
goto next;
|
||||
return;
|
||||
}
|
||||
dev_info(emu->card->dev,
|
||||
"emu1010: Audio Dock Firmware loaded\n");
|
||||
|
@ -790,18 +787,22 @@ static void emu1010_firmware_work(struct work_struct *work)
|
|||
msleep(10);
|
||||
/* Unmute all. Default is muted after a firmware load */
|
||||
snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE);
|
||||
} else if (!reg && emu->emu1010.last_reg) {
|
||||
}
|
||||
}
|
||||
|
||||
static void emu1010_interrupt(struct snd_emu10k1 *emu)
|
||||
{
|
||||
u32 sts;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
next:
|
||||
emu->emu1010.last_reg = reg;
|
||||
if (!emu->card->shutdown)
|
||||
schedule_delayed_work(&emu->emu1010.firmware_work,
|
||||
msecs_to_jiffies(1000));
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -870,6 +871,8 @@ 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);
|
||||
if (emu->card_capabilities->no_adat) {
|
||||
emu->emu1010.optical_in = 0; /* IN_SPDIF */
|
||||
emu->emu1010.optical_out = 0; /* OUT_SPDIF */
|
||||
|
@ -895,10 +898,12 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 *emu)
|
|||
/* MIDI routing */
|
||||
snd_emu1010_fpga_write(emu, EMU_HANA_MIDI_IN, EMU_HANA_MIDI_INA_FROM_HAMOA | EMU_HANA_MIDI_INB_FROM_DOCK2);
|
||||
snd_emu1010_fpga_write(emu, EMU_HANA_MIDI_OUT, EMU_HANA_MIDI_OUT_DOCK2 | EMU_HANA_MIDI_OUT_SYNC2);
|
||||
/* IRQ Enable: All on */
|
||||
/* snd_emu1010_fpga_write(emu, EMU_HANA_IRQ_ENABLE, 0x0f); */
|
||||
/* IRQ Enable: All off */
|
||||
snd_emu1010_fpga_write(emu, EMU_HANA_IRQ_ENABLE, 0x00);
|
||||
|
||||
emu->gpio_interrupt = emu1010_interrupt;
|
||||
// Note: The Audigy INTE is set later
|
||||
snd_emu1010_fpga_write(emu, EMU_HANA_IRQ_ENABLE,
|
||||
EMU_HANA_IRQ_DOCK | EMU_HANA_IRQ_DOCK_LOST);
|
||||
snd_emu1010_fpga_read(emu, EMU_HANA_IRQ_STATUS, ®); // Clear pending IRQs
|
||||
|
||||
emu->emu1010.clock_source = 1; /* 48000 */
|
||||
emu->emu1010.clock_fallback = 1; /* 48000 */
|
||||
|
@ -938,7 +943,7 @@ static void snd_emu10k1_free(struct snd_card *card)
|
|||
/* Disable 48Volt power to Audio Dock */
|
||||
snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_PWR, 0);
|
||||
}
|
||||
cancel_delayed_work_sync(&emu->emu1010.firmware_work);
|
||||
cancel_work_sync(&emu->emu1010.firmware_work);
|
||||
release_firmware(emu->firmware);
|
||||
release_firmware(emu->dock_fw);
|
||||
snd_util_memhdr_free(emu->memhdr);
|
||||
|
@ -1517,7 +1522,7 @@ int snd_emu10k1_create(struct snd_card *card,
|
|||
emu->irq = -1;
|
||||
emu->synth = NULL;
|
||||
emu->get_synth_voice = NULL;
|
||||
INIT_DELAYED_WORK(&emu->emu1010.firmware_work, emu1010_firmware_work);
|
||||
INIT_WORK(&emu->emu1010.firmware_work, emu1010_firmware_work);
|
||||
/* read revision & serial */
|
||||
emu->revision = pci->revision;
|
||||
pci_read_config_dword(pci, PCI_SUBSYSTEM_VENDOR_ID, &emu->serial);
|
||||
|
|
|
@ -302,6 +302,8 @@ static void snd_emu1010_fpga_read_locked(struct snd_emu10k1 *emu, u32 reg, u32 *
|
|||
{
|
||||
// The higest input pin is used as the designated interrupt trigger,
|
||||
// so it needs to be masked out.
|
||||
// But note that any other input pin change will also cause an IRQ,
|
||||
// so using this function often causes an IRQ as a side effect.
|
||||
u32 mask = emu->card_capabilities->ca0108_chip ? 0x1f : 0x7f;
|
||||
if (snd_BUG_ON(reg > 0x3f))
|
||||
return;
|
||||
|
|
|
@ -149,6 +149,13 @@ irqreturn_t snd_emu10k1_interrupt(int irq, void *dev_id)
|
|||
outl(0, emu->port + INTE2);
|
||||
status &= ~IPR_P16V;
|
||||
}
|
||||
if (status & IPR_A_GPIO) {
|
||||
if (emu->gpio_interrupt)
|
||||
emu->gpio_interrupt(emu);
|
||||
else
|
||||
snd_emu10k1_intr_disable(emu, INTE_A_GPIOENABLE);
|
||||
status &= ~IPR_A_GPIO;
|
||||
}
|
||||
|
||||
if (status) {
|
||||
dev_err(emu->card->dev,
|
||||
|
|
Loading…
Reference in New Issue