diff options
author | Clemens Ladisch <clemens@ladisch.de> | 2006-11-06 03:18:34 -0500 |
---|---|---|
committer | Jaroslav Kysela <perex@suse.cz> | 2007-02-09 03:01:14 -0500 |
commit | de66d53e46f39de6ea3261609fdb92900bb34a42 (patch) | |
tree | 5d1530a9e52e51784ca0fd59619ffc4aa41020fc | |
parent | 219e281f4627a395aaceff0e4a257cd18608e145 (diff) |
[ALSA] sb16: add request_firmware()
Load the CSP programs using request_firmware(), if possible, instead of
using the built-in firmware blobs.
Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
Signed-off-by: Jaroslav Kysela <perex@suse.cz>
-rw-r--r-- | include/sound/sb16_csp.h | 14 | ||||
-rw-r--r-- | sound/isa/Kconfig | 1 | ||||
-rw-r--r-- | sound/isa/sb/sb16_csp.c | 61 |
3 files changed, 68 insertions, 8 deletions
diff --git a/include/sound/sb16_csp.h b/include/sound/sb16_csp.h index caf6fe21514d..736eac71d053 100644 --- a/include/sound/sb16_csp.h +++ b/include/sound/sb16_csp.h | |||
@@ -114,9 +114,21 @@ struct snd_sb_csp_info { | |||
114 | #ifdef __KERNEL__ | 114 | #ifdef __KERNEL__ |
115 | #include "sb.h" | 115 | #include "sb.h" |
116 | #include "hwdep.h" | 116 | #include "hwdep.h" |
117 | #include <linux/firmware.h> | ||
117 | 118 | ||
118 | struct snd_sb_csp; | 119 | struct snd_sb_csp; |
119 | 120 | ||
121 | /* indices for the known CSP programs */ | ||
122 | enum { | ||
123 | CSP_PROGRAM_MULAW, | ||
124 | CSP_PROGRAM_ALAW, | ||
125 | CSP_PROGRAM_ADPCM_INIT, | ||
126 | CSP_PROGRAM_ADPCM_PLAYBACK, | ||
127 | CSP_PROGRAM_ADPCM_CAPTURE, | ||
128 | |||
129 | CSP_PROGRAM_COUNT | ||
130 | }; | ||
131 | |||
120 | /* | 132 | /* |
121 | * CSP operators | 133 | * CSP operators |
122 | */ | 134 | */ |
@@ -159,6 +171,8 @@ struct snd_sb_csp { | |||
159 | struct snd_kcontrol *qsound_space; | 171 | struct snd_kcontrol *qsound_space; |
160 | 172 | ||
161 | struct mutex access_mutex; /* locking */ | 173 | struct mutex access_mutex; /* locking */ |
174 | |||
175 | const struct firmware *csp_programs[CSP_PROGRAM_COUNT]; | ||
162 | }; | 176 | }; |
163 | 177 | ||
164 | int snd_sb_csp_new(struct snd_sb *chip, int device, struct snd_hwdep ** rhwdep); | 178 | int snd_sb_csp_new(struct snd_sb *chip, int device, struct snd_hwdep ** rhwdep); |
diff --git a/sound/isa/Kconfig b/sound/isa/Kconfig index 57371f1a441f..565ed2add38b 100644 --- a/sound/isa/Kconfig +++ b/sound/isa/Kconfig | |||
@@ -358,6 +358,7 @@ config SND_SBAWE | |||
358 | config SND_SB16_CSP | 358 | config SND_SB16_CSP |
359 | bool "Sound Blaster 16/AWE CSP support" | 359 | bool "Sound Blaster 16/AWE CSP support" |
360 | depends on (SND_SB16 || SND_SBAWE) && (BROKEN || !PPC) | 360 | depends on (SND_SB16 || SND_SBAWE) && (BROKEN || !PPC) |
361 | select FW_LOADER | ||
361 | help | 362 | help |
362 | Say Y here to include support for the CSP core. This special | 363 | Say Y here to include support for the CSP core. This special |
363 | coprocessor can do variable tasks like various compression and | 364 | coprocessor can do variable tasks like various compression and |
diff --git a/sound/isa/sb/sb16_csp.c b/sound/isa/sb/sb16_csp.c index fcd638090a9e..3d9d7e0107ca 100644 --- a/sound/isa/sb/sb16_csp.c +++ b/sound/isa/sb/sb16_csp.c | |||
@@ -161,10 +161,13 @@ int snd_sb_csp_new(struct snd_sb *chip, int device, struct snd_hwdep ** rhwdep) | |||
161 | */ | 161 | */ |
162 | static void snd_sb_csp_free(struct snd_hwdep *hwdep) | 162 | static void snd_sb_csp_free(struct snd_hwdep *hwdep) |
163 | { | 163 | { |
164 | int i; | ||
164 | struct snd_sb_csp *p = hwdep->private_data; | 165 | struct snd_sb_csp *p = hwdep->private_data; |
165 | if (p) { | 166 | if (p) { |
166 | if (p->running & SNDRV_SB_CSP_ST_RUNNING) | 167 | if (p->running & SNDRV_SB_CSP_ST_RUNNING) |
167 | snd_sb_csp_stop(p); | 168 | snd_sb_csp_stop(p); |
169 | for (i = 0; i < ARRAY_SIZE(p->csp_programs); ++i) | ||
170 | release_firmware(p->csp_programs[i]); | ||
168 | kfree(p); | 171 | kfree(p); |
169 | } | 172 | } |
170 | } | 173 | } |
@@ -687,8 +690,50 @@ static int snd_sb_csp_load_user(struct snd_sb_csp * p, const unsigned char __use | |||
687 | return err; | 690 | return err; |
688 | } | 691 | } |
689 | 692 | ||
693 | #define FIRMWARE_IN_THE_KERNEL | ||
694 | |||
695 | #ifdef FIRMWARE_IN_THE_KERNEL | ||
690 | #include "sb16_csp_codecs.h" | 696 | #include "sb16_csp_codecs.h" |
691 | 697 | ||
698 | static const struct firmware snd_sb_csp_static_programs[] = { | ||
699 | { .data = mulaw_main, .size = sizeof mulaw_main }, | ||
700 | { .data = alaw_main, .size = sizeof alaw_main }, | ||
701 | { .data = ima_adpcm_init, .size = sizeof ima_adpcm_init }, | ||
702 | { .data = ima_adpcm_playback, .size = sizeof ima_adpcm_playback }, | ||
703 | { .data = ima_adpcm_capture, .size = sizeof ima_adpcm_capture }, | ||
704 | }; | ||
705 | #endif | ||
706 | |||
707 | static int snd_sb_csp_firmware_load(struct snd_sb_csp *p, int index, int flags) | ||
708 | { | ||
709 | static const char *const names[] = { | ||
710 | "sb16/mulaw_main.csp", | ||
711 | "sb16/alaw_main.csp", | ||
712 | "sb16/ima_adpcm_init.csp", | ||
713 | "sb16/ima_adpcm_playback.csp", | ||
714 | "sb16/ima_adpcm_capture.csp", | ||
715 | }; | ||
716 | const struct firmware *program; | ||
717 | int err; | ||
718 | |||
719 | BUILD_BUG_ON(ARRAY_SIZE(names) != CSP_PROGRAM_COUNT); | ||
720 | program = p->csp_programs[index]; | ||
721 | if (!program) { | ||
722 | err = request_firmware(&program, names[index], | ||
723 | p->chip->card->dev); | ||
724 | if (err >= 0) | ||
725 | p->csp_programs[index] = program; | ||
726 | else { | ||
727 | #ifdef FIRMWARE_IN_THE_KERNEL | ||
728 | program = &snd_sb_csp_static_programs[index]; | ||
729 | #else | ||
730 | return err; | ||
731 | #endif | ||
732 | } | ||
733 | } | ||
734 | return snd_sb_csp_load(p, program->data, program->size, flags); | ||
735 | } | ||
736 | |||
692 | /* | 737 | /* |
693 | * autoload hardware codec if necessary | 738 | * autoload hardware codec if necessary |
694 | * return 0 if CSP is loaded and ready to run (p->running != 0) | 739 | * return 0 if CSP is loaded and ready to run (p->running != 0) |
@@ -708,27 +753,27 @@ static int snd_sb_csp_autoload(struct snd_sb_csp * p, int pcm_sfmt, int play_rec | |||
708 | } else { | 753 | } else { |
709 | switch (pcm_sfmt) { | 754 | switch (pcm_sfmt) { |
710 | case SNDRV_PCM_FORMAT_MU_LAW: | 755 | case SNDRV_PCM_FORMAT_MU_LAW: |
711 | err = snd_sb_csp_load(p, &mulaw_main[0], sizeof(mulaw_main), 0); | 756 | err = snd_sb_csp_firmware_load(p, CSP_PROGRAM_MULAW, 0); |
712 | p->acc_format = SNDRV_PCM_FMTBIT_MU_LAW; | 757 | p->acc_format = SNDRV_PCM_FMTBIT_MU_LAW; |
713 | p->mode = SNDRV_SB_CSP_MODE_DSP_READ | SNDRV_SB_CSP_MODE_DSP_WRITE; | 758 | p->mode = SNDRV_SB_CSP_MODE_DSP_READ | SNDRV_SB_CSP_MODE_DSP_WRITE; |
714 | break; | 759 | break; |
715 | case SNDRV_PCM_FORMAT_A_LAW: | 760 | case SNDRV_PCM_FORMAT_A_LAW: |
716 | err = snd_sb_csp_load(p, &alaw_main[0], sizeof(alaw_main), 0); | 761 | err = snd_sb_csp_firmware_load(p, CSP_PROGRAM_ALAW, 0); |
717 | p->acc_format = SNDRV_PCM_FMTBIT_A_LAW; | 762 | p->acc_format = SNDRV_PCM_FMTBIT_A_LAW; |
718 | p->mode = SNDRV_SB_CSP_MODE_DSP_READ | SNDRV_SB_CSP_MODE_DSP_WRITE; | 763 | p->mode = SNDRV_SB_CSP_MODE_DSP_READ | SNDRV_SB_CSP_MODE_DSP_WRITE; |
719 | break; | 764 | break; |
720 | case SNDRV_PCM_FORMAT_IMA_ADPCM: | 765 | case SNDRV_PCM_FORMAT_IMA_ADPCM: |
721 | err = snd_sb_csp_load(p, &ima_adpcm_init[0], sizeof(ima_adpcm_init), | 766 | err = snd_sb_csp_firmware_load(p, CSP_PROGRAM_ADPCM_INIT, |
722 | SNDRV_SB_CSP_LOAD_INITBLOCK); | 767 | SNDRV_SB_CSP_LOAD_INITBLOCK); |
723 | if (err) | 768 | if (err) |
724 | break; | 769 | break; |
725 | if (play_rec_mode == SNDRV_SB_CSP_MODE_DSP_WRITE) { | 770 | if (play_rec_mode == SNDRV_SB_CSP_MODE_DSP_WRITE) { |
726 | err = snd_sb_csp_load(p, &ima_adpcm_playback[0], | 771 | err = snd_sb_csp_firmware_load |
727 | sizeof(ima_adpcm_playback), 0); | 772 | (p, CSP_PROGRAM_ADPCM_PLAYBACK, 0); |
728 | p->mode = SNDRV_SB_CSP_MODE_DSP_WRITE; | 773 | p->mode = SNDRV_SB_CSP_MODE_DSP_WRITE; |
729 | } else { | 774 | } else { |
730 | err = snd_sb_csp_load(p, &ima_adpcm_capture[0], | 775 | err = snd_sb_csp_firmware_load |
731 | sizeof(ima_adpcm_capture), 0); | 776 | (p, CSP_PROGRAM_ADPCM_CAPTURE, 0); |
732 | p->mode = SNDRV_SB_CSP_MODE_DSP_READ; | 777 | p->mode = SNDRV_SB_CSP_MODE_DSP_READ; |
733 | } | 778 | } |
734 | p->acc_format = SNDRV_PCM_FMTBIT_IMA_ADPCM; | 779 | p->acc_format = SNDRV_PCM_FMTBIT_IMA_ADPCM; |