aboutsummaryrefslogtreecommitdiffstats
path: root/sound/isa/sb/sb16_csp.c
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 /sound/isa/sb/sb16_csp.c
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>
Diffstat (limited to 'sound/isa/sb/sb16_csp.c')
-rw-r--r--sound/isa/sb/sb16_csp.c61
1 files changed, 53 insertions, 8 deletions
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;