diff options
author | Takashi Iwai <tiwai@suse.de> | 2012-11-22 10:55:11 -0500 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2012-11-22 11:48:07 -0500 |
commit | 90caaef6a1ce2ec6675b1dc5afd57767954ab7e8 (patch) | |
tree | 30a46cb8716a243fe250267ab1df899cecbc2707 | |
parent | 7009fa568b126a07b2de8ead103e378534453830 (diff) |
ALSA: hdsp: improve firmware caching
As the recent firmware code tries to reread and cache the firmware by
itself, it's even better to keep the struct firmware data instead of
keeping a local copy. Also, it makes little sense to disable the fw
loader for this driver, so added the explicit dependency, too.
Last, but not least, allocate the firmware data loaded via ioctl in
vmalloc'ed buffer instead, as the firmware size isn't that small.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
-rw-r--r-- | sound/pci/Kconfig | 1 | ||||
-rw-r--r-- | sound/pci/rme9652/hdsp.c | 62 |
2 files changed, 35 insertions, 28 deletions
diff --git a/sound/pci/Kconfig b/sound/pci/Kconfig index 59dbb7035da..947cfb4eb30 100644 --- a/sound/pci/Kconfig +++ b/sound/pci/Kconfig | |||
@@ -572,6 +572,7 @@ source "sound/pci/hda/Kconfig" | |||
572 | 572 | ||
573 | config SND_HDSP | 573 | config SND_HDSP |
574 | tristate "RME Hammerfall DSP Audio" | 574 | tristate "RME Hammerfall DSP Audio" |
575 | select FW_LOADER | ||
575 | select SND_HWDEP | 576 | select SND_HWDEP |
576 | select SND_RAWMIDI | 577 | select SND_RAWMIDI |
577 | select SND_PCM | 578 | select SND_PCM |
diff --git a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c index 0d6930c4f4b..b8ddbb18f14 100644 --- a/sound/pci/rme9652/hdsp.c +++ b/sound/pci/rme9652/hdsp.c | |||
@@ -59,13 +59,11 @@ MODULE_LICENSE("GPL"); | |||
59 | MODULE_SUPPORTED_DEVICE("{{RME Hammerfall-DSP}," | 59 | MODULE_SUPPORTED_DEVICE("{{RME Hammerfall-DSP}," |
60 | "{RME HDSP-9652}," | 60 | "{RME HDSP-9652}," |
61 | "{RME HDSP-9632}}"); | 61 | "{RME HDSP-9632}}"); |
62 | #ifdef HDSP_FW_LOADER | ||
63 | MODULE_FIRMWARE("rpm_firmware.bin"); | 62 | MODULE_FIRMWARE("rpm_firmware.bin"); |
64 | MODULE_FIRMWARE("multiface_firmware.bin"); | 63 | MODULE_FIRMWARE("multiface_firmware.bin"); |
65 | MODULE_FIRMWARE("multiface_firmware_rev11.bin"); | 64 | MODULE_FIRMWARE("multiface_firmware_rev11.bin"); |
66 | MODULE_FIRMWARE("digiface_firmware.bin"); | 65 | MODULE_FIRMWARE("digiface_firmware.bin"); |
67 | MODULE_FIRMWARE("digiface_firmware_rev11.bin"); | 66 | MODULE_FIRMWARE("digiface_firmware_rev11.bin"); |
68 | #endif | ||
69 | 67 | ||
70 | #define HDSP_MAX_CHANNELS 26 | 68 | #define HDSP_MAX_CHANNELS 26 |
71 | #define HDSP_MAX_DS_CHANNELS 14 | 69 | #define HDSP_MAX_DS_CHANNELS 14 |
@@ -423,12 +421,7 @@ MODULE_FIRMWARE("digiface_firmware_rev11.bin"); | |||
423 | #define HDSP_DMA_AREA_BYTES ((HDSP_MAX_CHANNELS+1) * HDSP_CHANNEL_BUFFER_BYTES) | 421 | #define HDSP_DMA_AREA_BYTES ((HDSP_MAX_CHANNELS+1) * HDSP_CHANNEL_BUFFER_BYTES) |
424 | #define HDSP_DMA_AREA_KILOBYTES (HDSP_DMA_AREA_BYTES/1024) | 422 | #define HDSP_DMA_AREA_KILOBYTES (HDSP_DMA_AREA_BYTES/1024) |
425 | 423 | ||
426 | /* use hotplug firmware loader? */ | 424 | #define HDSP_FIRMWARE_SIZE (24413 * 4) |
427 | #if defined(CONFIG_FW_LOADER) || defined(CONFIG_FW_LOADER_MODULE) | ||
428 | #if !defined(HDSP_USE_HWDEP_LOADER) | ||
429 | #define HDSP_FW_LOADER | ||
430 | #endif | ||
431 | #endif | ||
432 | 425 | ||
433 | struct hdsp_9632_meters { | 426 | struct hdsp_9632_meters { |
434 | u32 input_peak[16]; | 427 | u32 input_peak[16]; |
@@ -475,7 +468,8 @@ struct hdsp { | |||
475 | enum HDSP_IO_Type io_type; /* ditto, but for code use */ | 468 | enum HDSP_IO_Type io_type; /* ditto, but for code use */ |
476 | unsigned short firmware_rev; | 469 | unsigned short firmware_rev; |
477 | unsigned short state; /* stores state bits */ | 470 | unsigned short state; /* stores state bits */ |
478 | u32 firmware_cache[24413]; /* this helps recover from accidental iobox power failure */ | 471 | const struct firmware *firmware; |
472 | u32 *fw_uploaded; | ||
479 | size_t period_bytes; /* guess what this is */ | 473 | size_t period_bytes; /* guess what this is */ |
480 | unsigned char max_channels; | 474 | unsigned char max_channels; |
481 | unsigned char qs_in_channels; /* quad speed mode for H9632 */ | 475 | unsigned char qs_in_channels; /* quad speed mode for H9632 */ |
@@ -712,6 +706,17 @@ static int snd_hdsp_load_firmware_from_cache(struct hdsp *hdsp) { | |||
712 | 706 | ||
713 | int i; | 707 | int i; |
714 | unsigned long flags; | 708 | unsigned long flags; |
709 | const u32 *cache; | ||
710 | |||
711 | if (hdsp->fw_uploaded) | ||
712 | cache = hdsp->fw_uploaded; | ||
713 | else { | ||
714 | if (!hdsp->firmware) | ||
715 | return -ENODEV; | ||
716 | cache = (u32 *)hdsp->firmware->data; | ||
717 | if (!cache) | ||
718 | return -ENODEV; | ||
719 | } | ||
715 | 720 | ||
716 | if ((hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DllError) != 0) { | 721 | if ((hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DllError) != 0) { |
717 | 722 | ||
@@ -727,8 +732,8 @@ static int snd_hdsp_load_firmware_from_cache(struct hdsp *hdsp) { | |||
727 | 732 | ||
728 | hdsp_write (hdsp, HDSP_control2Reg, HDSP_S_LOAD); | 733 | hdsp_write (hdsp, HDSP_control2Reg, HDSP_S_LOAD); |
729 | 734 | ||
730 | for (i = 0; i < 24413; ++i) { | 735 | for (i = 0; i < HDSP_FIRMWARE_SIZE / 4; ++i) { |
731 | hdsp_write(hdsp, HDSP_fifoData, hdsp->firmware_cache[i]); | 736 | hdsp_write(hdsp, HDSP_fifoData, cache[i]); |
732 | if (hdsp_fifo_wait (hdsp, 127, HDSP_LONG_WAIT)) { | 737 | if (hdsp_fifo_wait (hdsp, 127, HDSP_LONG_WAIT)) { |
733 | snd_printk ("Hammerfall-DSP: timeout during firmware loading\n"); | 738 | snd_printk ("Hammerfall-DSP: timeout during firmware loading\n"); |
734 | return -EIO; | 739 | return -EIO; |
@@ -798,9 +803,7 @@ static int hdsp_get_iobox_version (struct hdsp *hdsp) | |||
798 | } | 803 | } |
799 | 804 | ||
800 | 805 | ||
801 | #ifdef HDSP_FW_LOADER | ||
802 | static int hdsp_request_fw_loader(struct hdsp *hdsp); | 806 | static int hdsp_request_fw_loader(struct hdsp *hdsp); |
803 | #endif | ||
804 | 807 | ||
805 | static int hdsp_check_for_firmware (struct hdsp *hdsp, int load_on_demand) | 808 | static int hdsp_check_for_firmware (struct hdsp *hdsp, int load_on_demand) |
806 | { | 809 | { |
@@ -813,10 +816,8 @@ static int hdsp_check_for_firmware (struct hdsp *hdsp, int load_on_demand) | |||
813 | snd_printk(KERN_ERR "Hammerfall-DSP: firmware not present.\n"); | 816 | snd_printk(KERN_ERR "Hammerfall-DSP: firmware not present.\n"); |
814 | /* try to load firmware */ | 817 | /* try to load firmware */ |
815 | if (! (hdsp->state & HDSP_FirmwareCached)) { | 818 | if (! (hdsp->state & HDSP_FirmwareCached)) { |
816 | #ifdef HDSP_FW_LOADER | ||
817 | if (! hdsp_request_fw_loader(hdsp)) | 819 | if (! hdsp_request_fw_loader(hdsp)) |
818 | return 0; | 820 | return 0; |
819 | #endif | ||
820 | snd_printk(KERN_ERR | 821 | snd_printk(KERN_ERR |
821 | "Hammerfall-DSP: No firmware loaded nor " | 822 | "Hammerfall-DSP: No firmware loaded nor " |
822 | "cached, please upload firmware.\n"); | 823 | "cached, please upload firmware.\n"); |
@@ -3673,9 +3674,7 @@ snd_hdsp_proc_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer) | |||
3673 | } | 3674 | } |
3674 | } else { | 3675 | } else { |
3675 | int err = -EINVAL; | 3676 | int err = -EINVAL; |
3676 | #ifdef HDSP_FW_LOADER | ||
3677 | err = hdsp_request_fw_loader(hdsp); | 3677 | err = hdsp_request_fw_loader(hdsp); |
3678 | #endif | ||
3679 | if (err < 0) { | 3678 | if (err < 0) { |
3680 | snd_iprintf(buffer, | 3679 | snd_iprintf(buffer, |
3681 | "No firmware loaded nor cached, " | 3680 | "No firmware loaded nor cached, " |
@@ -5100,8 +5099,18 @@ static int snd_hdsp_hwdep_ioctl(struct snd_hwdep *hw, struct file *file, unsigne | |||
5100 | if (hdsp_check_for_iobox (hdsp)) | 5099 | if (hdsp_check_for_iobox (hdsp)) |
5101 | return -EIO; | 5100 | return -EIO; |
5102 | 5101 | ||
5103 | if (copy_from_user(hdsp->firmware_cache, firmware_data, sizeof(hdsp->firmware_cache)) != 0) | 5102 | if (!hdsp->fw_uploaded) { |
5103 | hdsp->fw_uploaded = vmalloc(HDSP_FIRMWARE_SIZE); | ||
5104 | if (!hdsp->fw_uploaded) | ||
5105 | return -ENOMEM; | ||
5106 | } | ||
5107 | |||
5108 | if (copy_from_user(hdsp->fw_uploaded, firmware_data, | ||
5109 | HDSP_FIRMWARE_SIZE)) { | ||
5110 | vfree(hdsp->fw_uploaded); | ||
5111 | hdsp->fw_uploaded = NULL; | ||
5104 | return -EFAULT; | 5112 | return -EFAULT; |
5113 | } | ||
5105 | 5114 | ||
5106 | hdsp->state |= HDSP_FirmwareCached; | 5115 | hdsp->state |= HDSP_FirmwareCached; |
5107 | 5116 | ||
@@ -5330,7 +5339,6 @@ static int snd_hdsp_create_alsa_devices(struct snd_card *card, struct hdsp *hdsp | |||
5330 | return 0; | 5339 | return 0; |
5331 | } | 5340 | } |
5332 | 5341 | ||
5333 | #ifdef HDSP_FW_LOADER | ||
5334 | /* load firmware via hotplug fw loader */ | 5342 | /* load firmware via hotplug fw loader */ |
5335 | static int hdsp_request_fw_loader(struct hdsp *hdsp) | 5343 | static int hdsp_request_fw_loader(struct hdsp *hdsp) |
5336 | { | 5344 | { |
@@ -5373,16 +5381,13 @@ static int hdsp_request_fw_loader(struct hdsp *hdsp) | |||
5373 | snd_printk(KERN_ERR "Hammerfall-DSP: cannot load firmware %s\n", fwfile); | 5381 | snd_printk(KERN_ERR "Hammerfall-DSP: cannot load firmware %s\n", fwfile); |
5374 | return -ENOENT; | 5382 | return -ENOENT; |
5375 | } | 5383 | } |
5376 | if (fw->size < sizeof(hdsp->firmware_cache)) { | 5384 | if (fw->size < HDSP_FIRMWARE_SIZE) { |
5377 | snd_printk(KERN_ERR "Hammerfall-DSP: too short firmware size %d (expected %d)\n", | 5385 | snd_printk(KERN_ERR "Hammerfall-DSP: too short firmware size %d (expected %d)\n", |
5378 | (int)fw->size, (int)sizeof(hdsp->firmware_cache)); | 5386 | (int)fw->size, HDSP_FIRMWARE_SIZE); |
5379 | release_firmware(fw); | ||
5380 | return -EINVAL; | 5387 | return -EINVAL; |
5381 | } | 5388 | } |
5382 | 5389 | ||
5383 | memcpy(hdsp->firmware_cache, fw->data, sizeof(hdsp->firmware_cache)); | 5390 | hdsp->firmware = fw; |
5384 | |||
5385 | release_firmware(fw); | ||
5386 | 5391 | ||
5387 | hdsp->state |= HDSP_FirmwareCached; | 5392 | hdsp->state |= HDSP_FirmwareCached; |
5388 | 5393 | ||
@@ -5406,7 +5411,6 @@ static int hdsp_request_fw_loader(struct hdsp *hdsp) | |||
5406 | } | 5411 | } |
5407 | return 0; | 5412 | return 0; |
5408 | } | 5413 | } |
5409 | #endif | ||
5410 | 5414 | ||
5411 | static int __devinit snd_hdsp_create(struct snd_card *card, | 5415 | static int __devinit snd_hdsp_create(struct snd_card *card, |
5412 | struct hdsp *hdsp) | 5416 | struct hdsp *hdsp) |
@@ -5504,7 +5508,6 @@ static int __devinit snd_hdsp_create(struct snd_card *card, | |||
5504 | return err; | 5508 | return err; |
5505 | 5509 | ||
5506 | if ((hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DllError) != 0) { | 5510 | if ((hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DllError) != 0) { |
5507 | #ifdef HDSP_FW_LOADER | ||
5508 | if ((err = hdsp_request_fw_loader(hdsp)) < 0) | 5511 | if ((err = hdsp_request_fw_loader(hdsp)) < 0) |
5509 | /* we don't fail as this can happen | 5512 | /* we don't fail as this can happen |
5510 | if userspace is not ready for | 5513 | if userspace is not ready for |
@@ -5514,7 +5517,6 @@ static int __devinit snd_hdsp_create(struct snd_card *card, | |||
5514 | else | 5517 | else |
5515 | /* init is complete, we return */ | 5518 | /* init is complete, we return */ |
5516 | return 0; | 5519 | return 0; |
5517 | #endif | ||
5518 | /* we defer initialization */ | 5520 | /* we defer initialization */ |
5519 | snd_printk(KERN_INFO "Hammerfall-DSP: card initialization pending : waiting for firmware\n"); | 5521 | snd_printk(KERN_INFO "Hammerfall-DSP: card initialization pending : waiting for firmware\n"); |
5520 | if ((err = snd_hdsp_create_hwdep(card, hdsp)) < 0) | 5522 | if ((err = snd_hdsp_create_hwdep(card, hdsp)) < 0) |
@@ -5568,6 +5570,10 @@ static int snd_hdsp_free(struct hdsp *hdsp) | |||
5568 | 5570 | ||
5569 | snd_hdsp_free_buffers(hdsp); | 5571 | snd_hdsp_free_buffers(hdsp); |
5570 | 5572 | ||
5573 | if (hdsp->firmware) | ||
5574 | release_firmware(hdsp->firmware); | ||
5575 | vfree(hdsp->fw_uploaded); | ||
5576 | |||
5571 | if (hdsp->iobase) | 5577 | if (hdsp->iobase) |
5572 | iounmap(hdsp->iobase); | 5578 | iounmap(hdsp->iobase); |
5573 | 5579 | ||