diff options
author | Clemens Ladisch <clemens@ladisch.de> | 2006-11-06 03:26:41 -0500 |
---|---|---|
committer | Jaroslav Kysela <perex@suse.cz> | 2007-02-09 03:01:18 -0500 |
commit | 81d7724a8ee84693befbd60d730199ffb3988f29 (patch) | |
tree | 0fdaad0f2427729ffbe088ff78979aa8aa65a59f /sound/pci/maestro3.c | |
parent | 2493a6d18b1f5df59c7bcfeefcbde70bee146490 (diff) |
[ALSA] maestro3: add request_firmware()
Load the ASSP codes using request_firmware(), if possible, instead of
using the built-in blobs.
Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
Signed-off-by: Jaroslav Kysela <perex@suse.cz>
Diffstat (limited to 'sound/pci/maestro3.c')
-rw-r--r-- | sound/pci/maestro3.c | 79 |
1 files changed, 73 insertions, 6 deletions
diff --git a/sound/pci/maestro3.c b/sound/pci/maestro3.c index 6efe6d5ade1e..053ea4fdbffd 100644 --- a/sound/pci/maestro3.c +++ b/sound/pci/maestro3.c | |||
@@ -41,6 +41,7 @@ | |||
41 | #include <linux/slab.h> | 41 | #include <linux/slab.h> |
42 | #include <linux/vmalloc.h> | 42 | #include <linux/vmalloc.h> |
43 | #include <linux/moduleparam.h> | 43 | #include <linux/moduleparam.h> |
44 | #include <linux/firmware.h> | ||
44 | #include <sound/core.h> | 45 | #include <sound/core.h> |
45 | #include <sound/info.h> | 46 | #include <sound/info.h> |
46 | #include <sound/control.h> | 47 | #include <sound/control.h> |
@@ -48,6 +49,7 @@ | |||
48 | #include <sound/mpu401.h> | 49 | #include <sound/mpu401.h> |
49 | #include <sound/ac97_codec.h> | 50 | #include <sound/ac97_codec.h> |
50 | #include <sound/initval.h> | 51 | #include <sound/initval.h> |
52 | #include <asm/byteorder.h> | ||
51 | 53 | ||
52 | MODULE_AUTHOR("Zach Brown <zab@zabbo.net>, Takashi Iwai <tiwai@suse.de>"); | 54 | MODULE_AUTHOR("Zach Brown <zab@zabbo.net>, Takashi Iwai <tiwai@suse.de>"); |
53 | MODULE_DESCRIPTION("ESS Maestro3 PCI"); | 55 | MODULE_DESCRIPTION("ESS Maestro3 PCI"); |
@@ -864,6 +866,9 @@ struct snd_m3 { | |||
864 | #ifdef CONFIG_PM | 866 | #ifdef CONFIG_PM |
865 | u16 *suspend_mem; | 867 | u16 *suspend_mem; |
866 | #endif | 868 | #endif |
869 | |||
870 | const struct firmware *assp_kernel_image; | ||
871 | const struct firmware *assp_minisrc_image; | ||
867 | }; | 872 | }; |
868 | 873 | ||
869 | /* | 874 | /* |
@@ -2132,6 +2137,10 @@ static int __devinit snd_m3_mixer(struct snd_m3 *chip) | |||
2132 | } | 2137 | } |
2133 | 2138 | ||
2134 | 2139 | ||
2140 | #define FIRMWARE_IN_THE_KERNEL | ||
2141 | |||
2142 | #ifdef FIRMWARE_IN_THE_KERNEL | ||
2143 | |||
2135 | /* | 2144 | /* |
2136 | * DSP Code images | 2145 | * DSP Code images |
2137 | */ | 2146 | */ |
@@ -2260,6 +2269,30 @@ static const u16 assp_minisrc_image[] = { | |||
2260 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, | 2269 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
2261 | }; | 2270 | }; |
2262 | 2271 | ||
2272 | static const struct firmware assp_kernel = { | ||
2273 | .data = (u8 *)assp_kernel_image, | ||
2274 | .size = sizeof assp_kernel_image | ||
2275 | }; | ||
2276 | static const struct firmware assp_minisrc = { | ||
2277 | .data = (u8 *)assp_minisrc_image, | ||
2278 | .size = sizeof assp_minisrc_image | ||
2279 | }; | ||
2280 | |||
2281 | #endif /* FIRMWARE_IN_THE_KERNEL */ | ||
2282 | |||
2283 | #ifdef __LITTLE_ENDIAN | ||
2284 | static inline void snd_m3_convert_from_le(const struct firmware *fw) { } | ||
2285 | #else | ||
2286 | static void snd_m3_convert_from_le(const struct firmware *fw) | ||
2287 | { | ||
2288 | int i; | ||
2289 | u16 *data = (u16 *)fw->data; | ||
2290 | |||
2291 | for (i = 0; i < fw->size / 2; ++i) | ||
2292 | le16_to_cpus(&data[i]); | ||
2293 | } | ||
2294 | #endif | ||
2295 | |||
2263 | 2296 | ||
2264 | /* | 2297 | /* |
2265 | * initialize ASSP | 2298 | * initialize ASSP |
@@ -2274,6 +2307,7 @@ static const u16 minisrc_lpf[MINISRC_LPF_LEN] = { | |||
2274 | static void snd_m3_assp_init(struct snd_m3 *chip) | 2307 | static void snd_m3_assp_init(struct snd_m3 *chip) |
2275 | { | 2308 | { |
2276 | unsigned int i; | 2309 | unsigned int i; |
2310 | u16 *data; | ||
2277 | 2311 | ||
2278 | /* zero kernel data */ | 2312 | /* zero kernel data */ |
2279 | for (i = 0; i < (REV_B_DATA_MEMORY_UNIT_LENGTH * NUM_UNITS_KERNEL_DATA) / 2; i++) | 2313 | for (i = 0; i < (REV_B_DATA_MEMORY_UNIT_LENGTH * NUM_UNITS_KERNEL_DATA) / 2; i++) |
@@ -2291,10 +2325,10 @@ static void snd_m3_assp_init(struct snd_m3 *chip) | |||
2291 | KDATA_DMA_XFER0); | 2325 | KDATA_DMA_XFER0); |
2292 | 2326 | ||
2293 | /* write kernel into code memory.. */ | 2327 | /* write kernel into code memory.. */ |
2294 | for (i = 0 ; i < ARRAY_SIZE(assp_kernel_image); i++) { | 2328 | data = (u16 *)chip->assp_kernel_image->data; |
2329 | for (i = 0 ; i * 2 < chip->assp_kernel_image->size; i++) { | ||
2295 | snd_m3_assp_write(chip, MEMTYPE_INTERNAL_CODE, | 2330 | snd_m3_assp_write(chip, MEMTYPE_INTERNAL_CODE, |
2296 | REV_B_CODE_MEMORY_BEGIN + i, | 2331 | REV_B_CODE_MEMORY_BEGIN + i, data[i]); |
2297 | assp_kernel_image[i]); | ||
2298 | } | 2332 | } |
2299 | 2333 | ||
2300 | /* | 2334 | /* |
@@ -2303,10 +2337,10 @@ static void snd_m3_assp_init(struct snd_m3 *chip) | |||
2303 | * drop it there. It seems that the minisrc doesn't | 2337 | * drop it there. It seems that the minisrc doesn't |
2304 | * need vectors, so we won't bother with them.. | 2338 | * need vectors, so we won't bother with them.. |
2305 | */ | 2339 | */ |
2306 | for (i = 0; i < ARRAY_SIZE(assp_minisrc_image); i++) { | 2340 | data = (u16 *)chip->assp_minisrc_image->data; |
2341 | for (i = 0; i * 2 < chip->assp_minisrc_image->size; i++) { | ||
2307 | snd_m3_assp_write(chip, MEMTYPE_INTERNAL_CODE, | 2342 | snd_m3_assp_write(chip, MEMTYPE_INTERNAL_CODE, |
2308 | 0x400 + i, | 2343 | 0x400 + i, data[i]); |
2309 | assp_minisrc_image[i]); | ||
2310 | } | 2344 | } |
2311 | 2345 | ||
2312 | /* | 2346 | /* |
@@ -2553,6 +2587,15 @@ static int snd_m3_free(struct snd_m3 *chip) | |||
2553 | if (chip->iobase) | 2587 | if (chip->iobase) |
2554 | pci_release_regions(chip->pci); | 2588 | pci_release_regions(chip->pci); |
2555 | 2589 | ||
2590 | #ifdef FIRMWARE_IN_THE_KERNEL | ||
2591 | if (chip->assp_kernel_image != &assp_kernel) | ||
2592 | #endif | ||
2593 | release_firmware(chip->assp_kernel_image); | ||
2594 | #ifdef FIRMWARE_IN_THE_KERNEL | ||
2595 | if (chip->assp_minisrc_image != &assp_minisrc) | ||
2596 | #endif | ||
2597 | release_firmware(chip->assp_minisrc_image); | ||
2598 | |||
2556 | pci_disable_device(chip->pci); | 2599 | pci_disable_device(chip->pci); |
2557 | kfree(chip); | 2600 | kfree(chip); |
2558 | return 0; | 2601 | return 0; |
@@ -2744,6 +2787,30 @@ snd_m3_create(struct snd_card *card, struct pci_dev *pci, | |||
2744 | return -ENOMEM; | 2787 | return -ENOMEM; |
2745 | } | 2788 | } |
2746 | 2789 | ||
2790 | err = request_firmware(&chip->assp_kernel_image, | ||
2791 | "ess/maestro3_assp_kernel.fw", &pci->dev); | ||
2792 | if (err < 0) { | ||
2793 | #ifdef FIRMWARE_IN_THE_KERNEL | ||
2794 | chip->assp_kernel_image = &assp_kernel; | ||
2795 | #else | ||
2796 | snd_m3_free(chip); | ||
2797 | return err; | ||
2798 | #endif | ||
2799 | } else | ||
2800 | snd_m3_convert_from_le(chip->assp_kernel_image); | ||
2801 | |||
2802 | err = request_firmware(&chip->assp_minisrc_image, | ||
2803 | "ess/maestro3_assp_minisrc.fw", &pci->dev); | ||
2804 | if (err < 0) { | ||
2805 | #ifdef FIRMWARE_IN_THE_KERNEL | ||
2806 | chip->assp_minisrc_image = &assp_minisrc; | ||
2807 | #else | ||
2808 | snd_m3_free(chip); | ||
2809 | return err; | ||
2810 | #endif | ||
2811 | } else | ||
2812 | snd_m3_convert_from_le(chip->assp_minisrc_image); | ||
2813 | |||
2747 | if ((err = pci_request_regions(pci, card->driver)) < 0) { | 2814 | if ((err = pci_request_regions(pci, card->driver)) < 0) { |
2748 | snd_m3_free(chip); | 2815 | snd_m3_free(chip); |
2749 | return err; | 2816 | return err; |