[ALSA] wavefront - Use standard firmware loader

Use the standard firmware loader for loading ICS2115 OS firmware file.
This is the last old bad guy that is still using sys_open() and sys_read()
calls, and now all should be gone.
The patch also adds the missing description of module options related
with wavefront_synth.c.
Due to this rewrite, user will have to copy or make symlink the firmware
file appropriately to the standard firmware path such as /lib/firmware.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Jaroslav Kysela <perex@suse.cz>
This commit is contained in:
Takashi Iwai 2007-08-21 15:20:26 +02:00 committed by Jaroslav Kysela
parent 33bf17abf9
commit c2b1239a9f
3 changed files with 92 additions and 81 deletions

View File

@ -1716,8 +1716,52 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
dma2 - DMA2 # for CS4232 PCM interface.
isapnp - ISA PnP detection - 0 = disable, 1 = enable (default)
The below are options for wavefront_synth features:
wf_raw - Assume that we need to boot the OS (default:no)
If yes, then during driver loading, the state of the board is
ignored, and we reset the board and load the firmware anyway.
fx_raw - Assume that the FX process needs help (default:yes)
If false, we'll leave the FX processor in whatever state it is
when the driver is loaded. The default is to download the
microprogram and associated coefficients to set it up for
"default" operation, whatever that means.
debug_default - Debug parameters for card initialization
wait_usecs - How long to wait without sleeping, usecs
(default:150)
This magic number seems to give pretty optimal throughput
based on my limited experimentation.
If you want to play around with it and find a better value, be
my guest. Remember, the idea is to get a number that causes us
to just busy wait for as many WaveFront commands as possible,
without coming up with a number so large that we hog the whole
CPU.
Specifically, with this number, out of about 134,000 status
waits, only about 250 result in a sleep.
sleep_interval - How long to sleep when waiting for reply
(default: 100)
sleep_tries - How many times to try sleeping during a wait
(default: 50)
ospath - Pathname to processed ICS2115 OS firmware
(default:wavefront.os)
The path name of the ISC2115 OS firmware. In the recent
version, it's handled via firmware loader framework, so it
must be installed in the proper path, typically,
/lib/firmware.
reset_time - How long to wait for a reset to take effect
(default:2)
ramcheck_time - How many seconds to wait for the RAM test
(default:20)
osrun_time - How many seconds to wait for the ICS2115 OS
(default:10)
This module supports multiple cards and ISA PnP.
Note: the firmware file "wavefront.os" was located in the earlier
version in /etc. Now it's loaded via firmware loader, and
must be in the proper firmware path, such as /lib/firmware.
Copy (or symlink) the file appropriately if you get an error
regarding firmware downloading after upgrading the kernel.
Module snd-sonicvibes
---------------------

View File

@ -414,7 +414,7 @@ config SND_SSCAPE
config SND_WAVEFRONT
tristate "Turtle Beach Maui,Tropez,Tropez+ (Wavefront)"
depends on SND
select FW_LOADER if !SND_WAVEFRONT_FIRMWARE_IN_KERNEL
select FW_LOADER
select SND_OPL3_LIB
select SND_MPU401_UART
select SND_CS4231_LIB
@ -430,8 +430,9 @@ config SND_WAVEFRONT_FIRMWARE_IN_KERNEL
depends on SND_WAVEFRONT
default y
help
Say Y here to include the static firmware built in the kernel
for the Wavefront driver. If you choose N here, you need to
install the firmware files from the alsa-firmware package.
Say Y here to include the static firmware for FX DSP built in
the kernel for the Wavefront driver. If you choose N here,
you need to install the firmware files from the
alsa-firmware package.
endmenu

View File

@ -27,6 +27,7 @@
#include <linux/delay.h>
#include <linux/time.h>
#include <linux/wait.h>
#include <linux/firmware.h>
#include <linux/moduleparam.h>
#include <sound/core.h>
#include <sound/snd_wavefront.h>
@ -53,9 +54,8 @@ static int debug_default = 0; /* you can set this to control debugging
/* XXX this needs to be made firmware and hardware version dependent */
static char *ospath = "/etc/sound/wavefront.os"; /* where to find a processed
version of the WaveFront OS
*/
#define DEFAULT_OSPATH "wavefront.os"
static char *ospath = DEFAULT_OSPATH; /* the firmware file name */
static int wait_usecs = 150; /* This magic number seems to give pretty optimal
throughput based on my limited experimentation.
@ -97,7 +97,7 @@ MODULE_PARM_DESC(sleep_interval, "how long to sleep when waiting for reply");
module_param(sleep_tries, int, 0444);
MODULE_PARM_DESC(sleep_tries, "how many times to try sleeping during a wait");
module_param(ospath, charp, 0444);
MODULE_PARM_DESC(ospath, "full pathname to processed ICS2115 OS firmware");
MODULE_PARM_DESC(ospath, "pathname to processed ICS2115 OS firmware");
module_param(reset_time, int, 0444);
MODULE_PARM_DESC(reset_time, "how long to wait for a reset to take effect");
module_param(ramcheck_time, int, 0444);
@ -1938,111 +1938,75 @@ wavefront_reset_to_cleanliness (snd_wavefront_t *dev)
return (1);
}
#include <linux/fs.h>
#include <linux/mm.h>
#include <linux/slab.h>
#include <linux/unistd.h>
#include <linux/syscalls.h>
#include <asm/uaccess.h>
static int __devinit
wavefront_download_firmware (snd_wavefront_t *dev, char *path)
{
unsigned char section[WF_SECTION_MAX];
signed char section_length; /* yes, just a char; max value is WF_SECTION_MAX */
unsigned char *buf;
int len, err;
int section_cnt_downloaded = 0;
int fd;
int c;
int i;
mm_segment_t fs;
const struct firmware *firmware;
/* This tries to be a bit cleverer than the stuff Alan Cox did for
the generic sound firmware, in that it actually knows
something about the structure of the Motorola firmware. In
particular, it uses a version that has been stripped of the
20K of useless header information, and had section lengths
added, making it possible to load the entire OS without any
[kv]malloc() activity, since the longest entity we ever read is
42 bytes (well, WF_SECTION_MAX) long.
*/
fs = get_fs();
set_fs (get_ds());
if ((fd = sys_open ((char __user *) path, 0, 0)) < 0) {
snd_printk ("Unable to load \"%s\".\n",
path);
err = request_firmware(&firmware, path, dev->card->dev);
if (err < 0) {
snd_printk(KERN_ERR "firmware (%s) download failed!!!\n", path);
return 1;
}
while (1) {
int x;
if ((x = sys_read (fd, (char __user *) &section_length, sizeof (section_length))) !=
sizeof (section_length)) {
snd_printk ("firmware read error.\n");
goto failure;
}
if (section_length == 0) {
len = 0;
buf = firmware->data;
for (;;) {
int section_length = *(signed char *)buf;
if (section_length == 0)
break;
}
if (section_length < 0 || section_length > WF_SECTION_MAX) {
snd_printk ("invalid firmware section length %d\n",
section_length);
snd_printk(KERN_ERR
"invalid firmware section length %d\n",
section_length);
goto failure;
}
buf++;
len++;
if (sys_read (fd, (char __user *) section, section_length) != section_length) {
snd_printk ("firmware section "
"read error.\n");
if (firmware->size < len + section_length) {
snd_printk(KERN_ERR "firmware section read error.\n");
goto failure;
}
/* Send command */
if (wavefront_write (dev, WFC_DOWNLOAD_OS)) {
if (wavefront_write(dev, WFC_DOWNLOAD_OS))
goto failure;
}
for (i = 0; i < section_length; i++) {
if (wavefront_write (dev, section[i])) {
for (; section_length; section_length--) {
if (wavefront_write(dev, *buf))
goto failure;
}
buf++;
len++;
}
/* get ACK */
if (wavefront_wait (dev, STAT_CAN_READ)) {
if ((c = inb (dev->data_port)) != WF_ACK) {
snd_printk ("download "
"of section #%d not "
"acknowledged, ack = 0x%x\n",
section_cnt_downloaded + 1, c);
goto failure;
}
} else {
snd_printk ("time out for firmware ACK.\n");
if (!wavefront_wait(dev, STAT_CAN_READ)) {
snd_printk(KERN_ERR "time out for firmware ACK.\n");
goto failure;
}
err = inb(dev->data_port);
if (err != WF_ACK) {
snd_printk(KERN_ERR
"download of section #%d not "
"acknowledged, ack = 0x%x\n",
section_cnt_downloaded + 1, err);
goto failure;
}
section_cnt_downloaded++;
}
sys_close (fd);
set_fs (fs);
release_firmware(firmware);
return 0;
failure:
sys_close (fd);
set_fs (fs);
snd_printk ("firmware download failed!!!\n");
release_firmware(firmware);
snd_printk(KERN_ERR "firmware download failed!!!\n");
return 1;
}
@ -2232,3 +2196,5 @@ snd_wavefront_detect (snd_wavefront_card_t *card)
return 0;
}
MODULE_FIRMWARE(DEFAULT_OSPATH);