mirror of
				git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
				synced 2025-10-31 16:54:21 +00:00 
			
		
		
		
	[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:
		
							parent
							
								
									33bf17abf9
								
							
						
					
					
						commit
						c2b1239a9f
					
				
					 3 changed files with 92 additions and 81 deletions
				
			
		|  | @ -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 | ||||
|   --------------------- | ||||
| 
 | ||||
|  |  | |||
|  | @ -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 | ||||
|  |  | |||
|  | @ -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 *) §ion_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); | ||||
|  |  | |||
		Loading…
	
	Add table
		
		Reference in a new issue
	
	 Takashi Iwai
						Takashi Iwai