aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorClemens Ladisch <clemens@ladisch.de>2006-11-06 03:18:34 -0500
committerJaroslav Kysela <perex@suse.cz>2007-02-09 03:01:14 -0500
commitde66d53e46f39de6ea3261609fdb92900bb34a42 (patch)
tree5d1530a9e52e51784ca0fd59619ffc4aa41020fc
parent219e281f4627a395aaceff0e4a257cd18608e145 (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.h14
-rw-r--r--sound/isa/Kconfig1
-rw-r--r--sound/isa/sb/sb16_csp.c61
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
118struct snd_sb_csp; 119struct snd_sb_csp;
119 120
121/* indices for the known CSP programs */
122enum {
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
164int snd_sb_csp_new(struct snd_sb *chip, int device, struct snd_hwdep ** rhwdep); 178int 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
358config SND_SB16_CSP 358config 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 */
162static void snd_sb_csp_free(struct snd_hwdep *hwdep) 162static 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
698static 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
707static 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;