提交 aeaa6203 编写于 作者: T Takashi Iwai

ALSA: emu10k1: Use workqueue instead of kthread for emu1010 fw polling

This patch is a cleanup of EMU1010 dock probing code in emu10k1 driver
to use work instead of kthread in a loop.  The work is lighter and
easier to control than kthread, in general.

Instead of a loop with the explicit sleep, we do simply
delayed-schedule the work.  At suspend/resume callbacks, the work is
canceled and restarted, respectively.
Signed-off-by: NTakashi Iwai <tiwai@suse.de>
上级 4e4dfe4c
...@@ -1688,7 +1688,8 @@ struct snd_emu1010 { ...@@ -1688,7 +1688,8 @@ struct snd_emu1010 {
unsigned int internal_clock; /* 44100 or 48000 */ unsigned int internal_clock; /* 44100 or 48000 */
unsigned int optical_in; /* 0:SPDIF, 1:ADAT */ unsigned int optical_in; /* 0:SPDIF, 1:ADAT */
unsigned int optical_out; /* 0:SPDIF, 1:ADAT */ unsigned int optical_out; /* 0:SPDIF, 1:ADAT */
struct task_struct *firmware_thread; struct delayed_work firmware_work;
u32 last_reg;
}; };
struct snd_emu10k1 { struct snd_emu10k1 {
......
...@@ -194,6 +194,9 @@ static int snd_card_emu10k1_probe(struct pci_dev *pci, ...@@ -194,6 +194,9 @@ static int snd_card_emu10k1_probe(struct pci_dev *pci,
if ((err = snd_card_register(card)) < 0) if ((err = snd_card_register(card)) < 0)
goto error; goto error;
if (emu->card_capabilities->emu_model)
schedule_delayed_work(&emu->emu1010.firmware_work, 0);
pci_set_drvdata(pci, card); pci_set_drvdata(pci, card);
dev++; dev++;
return 0; return 0;
...@@ -219,6 +222,8 @@ static int snd_emu10k1_suspend(struct device *dev) ...@@ -219,6 +222,8 @@ static int snd_emu10k1_suspend(struct device *dev)
emu->suspend = 1; emu->suspend = 1;
cancel_delayed_work_sync(&emu->emu1010.firmware_work);
snd_pcm_suspend_all(emu->pcm); snd_pcm_suspend_all(emu->pcm);
snd_pcm_suspend_all(emu->pcm_mic); snd_pcm_suspend_all(emu->pcm_mic);
snd_pcm_suspend_all(emu->pcm_efx); snd_pcm_suspend_all(emu->pcm_efx);
...@@ -252,6 +257,10 @@ static int snd_emu10k1_resume(struct device *dev) ...@@ -252,6 +257,10 @@ static int snd_emu10k1_resume(struct device *dev)
emu->suspend = 0; emu->suspend = 0;
snd_power_change_state(card, SNDRV_CTL_POWER_D0); 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; return 0;
} }
......
...@@ -32,7 +32,6 @@ ...@@ -32,7 +32,6 @@
*/ */
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/kthread.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/module.h> #include <linux/module.h>
...@@ -742,21 +741,19 @@ static int snd_emu1010_load_firmware(struct snd_emu10k1 *emu, int dock, ...@@ -742,21 +741,19 @@ static int snd_emu1010_load_firmware(struct snd_emu10k1 *emu, int dock,
return snd_emu1010_load_firmware_entry(emu, *fw); return snd_emu1010_load_firmware_entry(emu, *fw);
} }
static int emu1010_firmware_thread(void *data) static void emu1010_firmware_work(struct work_struct *work)
{ {
struct snd_emu10k1 *emu = data; struct snd_emu10k1 *emu;
u32 tmp, tmp2, reg; u32 tmp, tmp2, reg;
u32 last_reg = 0;
int err; int err;
for (;;) { emu = container_of(work, struct snd_emu10k1,
/* Delay to allow Audio Dock to settle */ emu1010.firmware_work.work);
msleep_interruptible(1000); if (emu->card->shutdown)
if (kthread_should_stop()) return;
break;
#ifdef CONFIG_PM_SLEEP #ifdef CONFIG_PM_SLEEP
if (emu->suspend) if (emu->suspend)
continue; return;
#endif #endif
snd_emu1010_fpga_read(emu, EMU_HANA_IRQ_STATUS, &tmp); /* IRQ Status */ snd_emu1010_fpga_read(emu, EMU_HANA_IRQ_STATUS, &tmp); /* IRQ Status */
snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, &reg); /* OPTIONS: Which cards are attached to the EMU */ snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, &reg); /* OPTIONS: Which cards are attached to the EMU */
...@@ -765,16 +762,16 @@ static int emu1010_firmware_thread(void *data) ...@@ -765,16 +762,16 @@ static int emu1010_firmware_thread(void *data)
/* Return to Audio Dock programming mode */ /* Return to Audio Dock programming mode */
dev_info(emu->card->dev, dev_info(emu->card->dev,
"emu1010: Loading Audio Dock Firmware\n"); "emu1010: Loading Audio Dock Firmware\n");
snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG, EMU_HANA_FPGA_CONFIG_AUDIODOCK); snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG,
EMU_HANA_FPGA_CONFIG_AUDIODOCK);
err = snd_emu1010_load_firmware(emu, 1, &emu->dock_fw); err = snd_emu1010_load_firmware(emu, 1, &emu->dock_fw);
if (err < 0) if (err < 0)
continue; goto next;
snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG, 0); snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG, 0);
snd_emu1010_fpga_read(emu, EMU_HANA_IRQ_STATUS, &tmp); snd_emu1010_fpga_read(emu, EMU_HANA_IRQ_STATUS, &tmp);
dev_info(emu->card->dev, dev_info(emu->card->dev,
"emu1010: EMU_HANA+DOCK_IRQ_STATUS = 0x%x\n", "emu1010: EMU_HANA+DOCK_IRQ_STATUS = 0x%x\n", tmp);
tmp);
/* ID, should read & 0x7f = 0x55 when FPGA programmed. */ /* ID, should read & 0x7f = 0x55 when FPGA programmed. */
snd_emu1010_fpga_read(emu, EMU_HANA_ID, &tmp); snd_emu1010_fpga_read(emu, EMU_HANA_ID, &tmp);
dev_info(emu->card->dev, dev_info(emu->card->dev,
...@@ -784,31 +781,30 @@ static int emu1010_firmware_thread(void *data) ...@@ -784,31 +781,30 @@ static int emu1010_firmware_thread(void *data)
dev_info(emu->card->dev, dev_info(emu->card->dev,
"emu1010: Loading Audio Dock Firmware file failed, reg = 0x%x\n", "emu1010: Loading Audio Dock Firmware file failed, reg = 0x%x\n",
tmp); tmp);
continue; goto next;
} }
dev_info(emu->card->dev, dev_info(emu->card->dev,
"emu1010: Audio Dock Firmware loaded\n"); "emu1010: Audio Dock Firmware loaded\n");
snd_emu1010_fpga_read(emu, EMU_DOCK_MAJOR_REV, &tmp); snd_emu1010_fpga_read(emu, EMU_DOCK_MAJOR_REV, &tmp);
snd_emu1010_fpga_read(emu, EMU_DOCK_MINOR_REV, &tmp2); snd_emu1010_fpga_read(emu, EMU_DOCK_MINOR_REV, &tmp2);
dev_info(emu->card->dev, "Audio Dock ver: %u.%u\n", dev_info(emu->card->dev, "Audio Dock ver: %u.%u\n", tmp, tmp2);
tmp, tmp2);
/* Sync clocking between 1010 and Dock */ /* Sync clocking between 1010 and Dock */
/* Allow DLL to settle */ /* Allow DLL to settle */
msleep(10); msleep(10);
/* Unmute all. Default is muted after a firmware load */ /* Unmute all. Default is muted after a firmware load */
snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE); snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE);
} else if (!reg && last_reg) { } else if (!reg && emu->emu1010.last_reg) {
/* Audio Dock removed */ /* Audio Dock removed */
dev_info(emu->card->dev, dev_info(emu->card->dev, "emu1010: Audio Dock detached\n");
"emu1010: Audio Dock detached\n");
/* Unmute all */ /* Unmute all */
snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE); snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE);
} }
last_reg = reg; next:
} emu->emu1010.last_reg = reg;
dev_info(emu->card->dev, "emu1010: firmware thread stopping\n"); if (!emu->card->shutdown)
return 0; schedule_delayed_work(&emu->emu1010.firmware_work,
msecs_to_jiffies(1000));
} }
/* /*
...@@ -1114,22 +1110,6 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 *emu) ...@@ -1114,22 +1110,6 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 *emu)
snd_emu1010_fpga_read(emu, EMU_HANA_SPDIF_MODE, &tmp); snd_emu1010_fpga_read(emu, EMU_HANA_SPDIF_MODE, &tmp);
snd_emu1010_fpga_write(emu, EMU_HANA_SPDIF_MODE, 0x10); /* SPDIF Format spdif (or 0x11 for aes/ebu) */ 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 */
if (!emu->emu1010.firmware_thread) {
emu->emu1010.firmware_thread =
kthread_create(emu1010_firmware_thread, emu,
"emu1010_firmware");
if (IS_ERR(emu->emu1010.firmware_thread)) {
err = PTR_ERR(emu->emu1010.firmware_thread);
emu->emu1010.firmware_thread = NULL;
dev_info(emu->card->dev,
"emu1010: Creating thread failed\n");
return err;
}
wake_up_process(emu->emu1010.firmware_thread);
}
#if 0 #if 0
snd_emu1010_fpga_link_dst_src_write(emu, snd_emu1010_fpga_link_dst_src_write(emu,
EMU_DST_HAMOA_DAC_LEFT1, EMU_SRC_ALICE_EMU32B + 2); /* ALICE2 bus 0xa2 */ EMU_DST_HAMOA_DAC_LEFT1, EMU_SRC_ALICE_EMU32B + 2); /* ALICE2 bus 0xa2 */
...@@ -1287,8 +1267,7 @@ static int snd_emu10k1_free(struct snd_emu10k1 *emu) ...@@ -1287,8 +1267,7 @@ static int snd_emu10k1_free(struct snd_emu10k1 *emu)
/* Disable 48Volt power to Audio Dock */ /* Disable 48Volt power to Audio Dock */
snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_PWR, 0); snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_PWR, 0);
} }
if (emu->emu1010.firmware_thread) cancel_delayed_work_sync(&emu->emu1010.firmware_work);
kthread_stop(emu->emu1010.firmware_thread);
release_firmware(emu->firmware); release_firmware(emu->firmware);
release_firmware(emu->dock_fw); release_firmware(emu->dock_fw);
if (emu->irq >= 0) if (emu->irq >= 0)
...@@ -1830,6 +1809,7 @@ int snd_emu10k1_create(struct snd_card *card, ...@@ -1830,6 +1809,7 @@ int snd_emu10k1_create(struct snd_card *card,
emu->irq = -1; emu->irq = -1;
emu->synth = NULL; emu->synth = NULL;
emu->get_synth_voice = NULL; emu->get_synth_voice = NULL;
INIT_DELAYED_WORK(&emu->emu1010.firmware_work, emu1010_firmware_work);
/* read revision & serial */ /* read revision & serial */
emu->revision = pci->revision; emu->revision = pci->revision;
pci_read_config_dword(pci, PCI_SUBSYSTEM_VENDOR_ID, &emu->serial); pci_read_config_dword(pci, PCI_SUBSYSTEM_VENDOR_ID, &emu->serial);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册