• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-R7000-V1.0.7.12_1.2.5/components/opensource/linux/linux-2.6.36/sound/synth/emux/
1/*
2 *  Soundfont generic routines.
3 *	It is intended that these should be used by any driver that is willing
4 *	to accept soundfont patches.
5 *
6 *  Copyright (C) 1999 Steve Ratcliffe
7 *  Copyright (c) 1999-2000 Takashi Iwai <tiwai@suse.de>
8 *
9 *   This program is free software; you can redistribute it and/or modify
10 *   it under the terms of the GNU General Public License as published by
11 *   the Free Software Foundation; either version 2 of the License, or
12 *   (at your option) any later version.
13 *
14 *   This program is distributed in the hope that it will be useful,
15 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
16 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 *   GNU General Public License for more details.
18 *
19 *   You should have received a copy of the GNU General Public License
20 *   along with this program; if not, write to the Free Software
21 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
22 */
23/*
24 * Deal with reading in of a soundfont.  Code follows the OSS way
25 * of doing things so that the old sfxload utility can be used.
26 * Everything may change when there is an alsa way of doing things.
27 */
28#include <asm/uaccess.h>
29#include <linux/slab.h>
30#include <sound/core.h>
31#include <sound/soundfont.h>
32#include <sound/seq_oss_legacy.h>
33
34/* Prototypes for static functions */
35
36static int open_patch(struct snd_sf_list *sflist, const char __user *data,
37		      int count, int client);
38static struct snd_soundfont *newsf(struct snd_sf_list *sflist, int type, char *name);
39static int is_identical_font(struct snd_soundfont *sf, int type, unsigned char *name);
40static int close_patch(struct snd_sf_list *sflist);
41static int probe_data(struct snd_sf_list *sflist, int sample_id);
42static void set_zone_counter(struct snd_sf_list *sflist,
43			     struct snd_soundfont *sf, struct snd_sf_zone *zp);
44static struct snd_sf_zone *sf_zone_new(struct snd_sf_list *sflist,
45				       struct snd_soundfont *sf);
46static void set_sample_counter(struct snd_sf_list *sflist,
47			       struct snd_soundfont *sf, struct snd_sf_sample *sp);
48static struct snd_sf_sample *sf_sample_new(struct snd_sf_list *sflist,
49					   struct snd_soundfont *sf);
50static void sf_sample_delete(struct snd_sf_list *sflist,
51			     struct snd_soundfont *sf, struct snd_sf_sample *sp);
52static int load_map(struct snd_sf_list *sflist, const void __user *data, int count);
53static int load_info(struct snd_sf_list *sflist, const void __user *data, long count);
54static int remove_info(struct snd_sf_list *sflist, struct snd_soundfont *sf,
55		       int bank, int instr);
56static void init_voice_info(struct soundfont_voice_info *avp);
57static void init_voice_parm(struct soundfont_voice_parm *pp);
58static struct snd_sf_sample *set_sample(struct snd_soundfont *sf,
59					struct soundfont_voice_info *avp);
60static struct snd_sf_sample *find_sample(struct snd_soundfont *sf, int sample_id);
61static int load_data(struct snd_sf_list *sflist, const void __user *data, long count);
62static void rebuild_presets(struct snd_sf_list *sflist);
63static void add_preset(struct snd_sf_list *sflist, struct snd_sf_zone *cur);
64static void delete_preset(struct snd_sf_list *sflist, struct snd_sf_zone *zp);
65static struct snd_sf_zone *search_first_zone(struct snd_sf_list *sflist,
66					     int bank, int preset, int key);
67static int search_zones(struct snd_sf_list *sflist, int *notep, int vel,
68			int preset, int bank, struct snd_sf_zone **table,
69			int max_layers, int level);
70static int get_index(int bank, int instr, int key);
71static void snd_sf_init(struct snd_sf_list *sflist);
72static void snd_sf_clear(struct snd_sf_list *sflist);
73
74/*
75 * lock access to sflist
76 */
77static void
78lock_preset(struct snd_sf_list *sflist)
79{
80	unsigned long flags;
81	mutex_lock(&sflist->presets_mutex);
82	spin_lock_irqsave(&sflist->lock, flags);
83	sflist->presets_locked = 1;
84	spin_unlock_irqrestore(&sflist->lock, flags);
85}
86
87
88/*
89 * remove lock
90 */
91static void
92unlock_preset(struct snd_sf_list *sflist)
93{
94	unsigned long flags;
95	spin_lock_irqsave(&sflist->lock, flags);
96	sflist->presets_locked = 0;
97	spin_unlock_irqrestore(&sflist->lock, flags);
98	mutex_unlock(&sflist->presets_mutex);
99}
100
101
102/*
103 * close the patch if the patch was opened by this client.
104 */
105int
106snd_soundfont_close_check(struct snd_sf_list *sflist, int client)
107{
108	unsigned long flags;
109	spin_lock_irqsave(&sflist->lock, flags);
110	if (sflist->open_client == client)  {
111		spin_unlock_irqrestore(&sflist->lock, flags);
112		return close_patch(sflist);
113	}
114	spin_unlock_irqrestore(&sflist->lock, flags);
115	return 0;
116}
117
118
119/*
120 * Deal with a soundfont patch.  Any driver could use these routines
121 * although it was designed for the AWE64.
122 *
123 * The sample_write and callargs pararameters allow a callback into
124 * the actual driver to write sample data to the board or whatever
125 * it wants to do with it.
126 */
127int
128snd_soundfont_load(struct snd_sf_list *sflist, const void __user *data,
129		   long count, int client)
130{
131	struct soundfont_patch_info patch;
132	unsigned long flags;
133	int  rc;
134
135	if (count < (long)sizeof(patch)) {
136		snd_printk(KERN_ERR "patch record too small %ld\n", count);
137		return -EINVAL;
138	}
139	if (copy_from_user(&patch, data, sizeof(patch)))
140		return -EFAULT;
141
142	count -= sizeof(patch);
143	data += sizeof(patch);
144
145	if (patch.key != SNDRV_OSS_SOUNDFONT_PATCH) {
146		snd_printk(KERN_ERR "The wrong kind of patch %x\n", patch.key);
147		return -EINVAL;
148	}
149	if (count < patch.len) {
150		snd_printk(KERN_ERR "Patch too short %ld, need %d\n",
151			   count, patch.len);
152		return -EINVAL;
153	}
154	if (patch.len < 0) {
155		snd_printk(KERN_ERR "poor length %d\n", patch.len);
156		return -EINVAL;
157	}
158
159	if (patch.type == SNDRV_SFNT_OPEN_PATCH) {
160		/* grab sflist to open */
161		lock_preset(sflist);
162		rc = open_patch(sflist, data, count, client);
163		unlock_preset(sflist);
164		return rc;
165	}
166
167	/* check if other client already opened patch */
168	spin_lock_irqsave(&sflist->lock, flags);
169	if (sflist->open_client != client) {
170		spin_unlock_irqrestore(&sflist->lock, flags);
171		return -EBUSY;
172	}
173	spin_unlock_irqrestore(&sflist->lock, flags);
174
175	lock_preset(sflist);
176	rc = -EINVAL;
177	switch (patch.type) {
178	case SNDRV_SFNT_LOAD_INFO:
179		rc = load_info(sflist, data, count);
180		break;
181	case SNDRV_SFNT_LOAD_DATA:
182		rc = load_data(sflist, data, count);
183		break;
184	case SNDRV_SFNT_CLOSE_PATCH:
185		rc = close_patch(sflist);
186		break;
187	case SNDRV_SFNT_REPLACE_DATA:
188		/*rc = replace_data(&patch, data, count);*/
189		break;
190	case SNDRV_SFNT_MAP_PRESET:
191		rc = load_map(sflist, data, count);
192		break;
193	case SNDRV_SFNT_PROBE_DATA:
194		rc = probe_data(sflist, patch.optarg);
195		break;
196	case SNDRV_SFNT_REMOVE_INFO:
197		/* patch must be opened */
198		if (!sflist->currsf) {
199			snd_printk(KERN_ERR "soundfont: remove_info: "
200				   "patch not opened\n");
201			rc = -EINVAL;
202		} else {
203			int bank, instr;
204			bank = ((unsigned short)patch.optarg >> 8) & 0xff;
205			instr = (unsigned short)patch.optarg & 0xff;
206			if (! remove_info(sflist, sflist->currsf, bank, instr))
207				rc = -EINVAL;
208			else
209				rc = 0;
210		}
211		break;
212	}
213	unlock_preset(sflist);
214
215	return rc;
216}
217
218
219/* check if specified type is special font (GUS or preset-alias) */
220static inline int
221is_special_type(int type)
222{
223	type &= 0x0f;
224	return (type == SNDRV_SFNT_PAT_TYPE_GUS ||
225		type == SNDRV_SFNT_PAT_TYPE_MAP);
226}
227
228
229/* open patch; create sf list */
230static int
231open_patch(struct snd_sf_list *sflist, const char __user *data,
232	   int count, int client)
233{
234	struct soundfont_open_parm parm;
235	struct snd_soundfont *sf;
236	unsigned long flags;
237
238	spin_lock_irqsave(&sflist->lock, flags);
239	if (sflist->open_client >= 0 || sflist->currsf) {
240		spin_unlock_irqrestore(&sflist->lock, flags);
241		return -EBUSY;
242	}
243	spin_unlock_irqrestore(&sflist->lock, flags);
244
245	if (copy_from_user(&parm, data, sizeof(parm)))
246		return -EFAULT;
247
248	if (is_special_type(parm.type)) {
249		parm.type |= SNDRV_SFNT_PAT_SHARED;
250		sf = newsf(sflist, parm.type, NULL);
251	} else
252		sf = newsf(sflist, parm.type, parm.name);
253	if (sf == NULL) {
254		return -ENOMEM;
255	}
256
257	spin_lock_irqsave(&sflist->lock, flags);
258	sflist->open_client = client;
259	sflist->currsf = sf;
260	spin_unlock_irqrestore(&sflist->lock, flags);
261
262	return 0;
263}
264
265/*
266 * Allocate a new soundfont structure.
267 */
268static struct snd_soundfont *
269newsf(struct snd_sf_list *sflist, int type, char *name)
270{
271	struct snd_soundfont *sf;
272
273	/* check the shared fonts */
274	if (type & SNDRV_SFNT_PAT_SHARED) {
275		for (sf = sflist->fonts; sf; sf = sf->next) {
276			if (is_identical_font(sf, type, name)) {
277				return sf;
278			}
279		}
280	}
281
282	/* not found -- create a new one */
283	sf = kzalloc(sizeof(*sf), GFP_KERNEL);
284	if (sf == NULL)
285		return NULL;
286	sf->id = sflist->fonts_size;
287	sflist->fonts_size++;
288
289	/* prepend this record */
290	sf->next = sflist->fonts;
291	sflist->fonts = sf;
292
293	sf->type = type;
294	sf->zones = NULL;
295	sf->samples = NULL;
296	if (name)
297		memcpy(sf->name, name, SNDRV_SFNT_PATCH_NAME_LEN);
298
299	return sf;
300}
301
302/* check if the given name matches to the existing list */
303static int
304is_identical_font(struct snd_soundfont *sf, int type, unsigned char *name)
305{
306	return ((sf->type & SNDRV_SFNT_PAT_SHARED) &&
307		(sf->type & 0x0f) == (type & 0x0f) &&
308		(name == NULL ||
309		 memcmp(sf->name, name, SNDRV_SFNT_PATCH_NAME_LEN) == 0));
310}
311
312/*
313 * Close the current patch.
314 */
315static int
316close_patch(struct snd_sf_list *sflist)
317{
318	unsigned long flags;
319
320	spin_lock_irqsave(&sflist->lock, flags);
321	sflist->currsf = NULL;
322	sflist->open_client = -1;
323	spin_unlock_irqrestore(&sflist->lock, flags);
324
325	rebuild_presets(sflist);
326
327	return 0;
328
329}
330
331/* probe sample in the current list -- nothing to be loaded */
332static int
333probe_data(struct snd_sf_list *sflist, int sample_id)
334{
335	/* patch must be opened */
336	if (sflist->currsf) {
337		/* search the specified sample by optarg */
338		if (find_sample(sflist->currsf, sample_id))
339			return 0;
340	}
341	return -EINVAL;
342}
343
344/*
345 * increment zone counter
346 */
347static void
348set_zone_counter(struct snd_sf_list *sflist, struct snd_soundfont *sf,
349		 struct snd_sf_zone *zp)
350{
351	zp->counter = sflist->zone_counter++;
352	if (sf->type & SNDRV_SFNT_PAT_LOCKED)
353		sflist->zone_locked = sflist->zone_counter;
354}
355
356/*
357 * allocate a new zone record
358 */
359static struct snd_sf_zone *
360sf_zone_new(struct snd_sf_list *sflist, struct snd_soundfont *sf)
361{
362	struct snd_sf_zone *zp;
363
364	if ((zp = kzalloc(sizeof(*zp), GFP_KERNEL)) == NULL)
365		return NULL;
366	zp->next = sf->zones;
367	sf->zones = zp;
368
369	init_voice_info(&zp->v);
370
371	set_zone_counter(sflist, sf, zp);
372	return zp;
373}
374
375
376/*
377 * increment sample counter
378 */
379static void
380set_sample_counter(struct snd_sf_list *sflist, struct snd_soundfont *sf,
381		   struct snd_sf_sample *sp)
382{
383	sp->counter = sflist->sample_counter++;
384	if (sf->type & SNDRV_SFNT_PAT_LOCKED)
385		sflist->sample_locked = sflist->sample_counter;
386}
387
388/*
389 * allocate a new sample list record
390 */
391static struct snd_sf_sample *
392sf_sample_new(struct snd_sf_list *sflist, struct snd_soundfont *sf)
393{
394	struct snd_sf_sample *sp;
395
396	if ((sp = kzalloc(sizeof(*sp), GFP_KERNEL)) == NULL)
397		return NULL;
398
399	sp->next = sf->samples;
400	sf->samples = sp;
401
402	set_sample_counter(sflist, sf, sp);
403	return sp;
404}
405
406/*
407 * delete sample list -- this is an exceptional job.
408 * only the last allocated sample can be deleted.
409 */
410static void
411sf_sample_delete(struct snd_sf_list *sflist, struct snd_soundfont *sf,
412		 struct snd_sf_sample *sp)
413{
414	/* only last sample is accepted */
415	if (sp == sf->samples) {
416		sf->samples = sp->next;
417		kfree(sp);
418	}
419}
420
421
422/* load voice map */
423static int
424load_map(struct snd_sf_list *sflist, const void __user *data, int count)
425{
426	struct snd_sf_zone *zp, *prevp;
427	struct snd_soundfont *sf;
428	struct soundfont_voice_map map;
429
430	/* get the link info */
431	if (count < (int)sizeof(map))
432		return -EINVAL;
433	if (copy_from_user(&map, data, sizeof(map)))
434		return -EFAULT;
435
436	if (map.map_instr < 0 || map.map_instr >= SF_MAX_INSTRUMENTS)
437		return -EINVAL;
438
439	sf = newsf(sflist, SNDRV_SFNT_PAT_TYPE_MAP|SNDRV_SFNT_PAT_SHARED, NULL);
440	if (sf == NULL)
441		return -ENOMEM;
442
443	prevp = NULL;
444	for (zp = sf->zones; zp; prevp = zp, zp = zp->next) {
445		if (zp->mapped &&
446		    zp->instr == map.map_instr &&
447		    zp->bank == map.map_bank &&
448		    zp->v.low == map.map_key &&
449		    zp->v.start == map.src_instr &&
450		    zp->v.end == map.src_bank &&
451		    zp->v.fixkey == map.src_key) {
452			/* the same mapping is already present */
453			/* relink this record to the link head */
454			if (prevp) {
455				prevp->next = zp->next;
456				zp->next = sf->zones;
457				sf->zones = zp;
458			}
459			/* update the counter */
460			set_zone_counter(sflist, sf, zp);
461			return 0;
462		}
463	}
464
465	/* create a new zone */
466	if ((zp = sf_zone_new(sflist, sf)) == NULL)
467		return -ENOMEM;
468
469	zp->bank = map.map_bank;
470	zp->instr = map.map_instr;
471	zp->mapped = 1;
472	if (map.map_key >= 0) {
473		zp->v.low = map.map_key;
474		zp->v.high = map.map_key;
475	}
476	zp->v.start = map.src_instr;
477	zp->v.end = map.src_bank;
478	zp->v.fixkey = map.src_key;
479	zp->v.sf_id = sf->id;
480
481	add_preset(sflist, zp);
482
483	return 0;
484}
485
486
487/* remove the present instrument layers */
488static int
489remove_info(struct snd_sf_list *sflist, struct snd_soundfont *sf,
490	    int bank, int instr)
491{
492	struct snd_sf_zone *prev, *next, *p;
493	int removed = 0;
494
495	prev = NULL;
496	for (p = sf->zones; p; p = next) {
497		next = p->next;
498		if (! p->mapped &&
499		    p->bank == bank && p->instr == instr) {
500			/* remove this layer */
501			if (prev)
502				prev->next = next;
503			else
504				sf->zones = next;
505			removed++;
506			kfree(p);
507		} else
508			prev = p;
509	}
510	if (removed)
511		rebuild_presets(sflist);
512	return removed;
513}
514
515
516/*
517 * Read an info record from the user buffer and save it on the current
518 * open soundfont.
519 */
520static int
521load_info(struct snd_sf_list *sflist, const void __user *data, long count)
522{
523	struct snd_soundfont *sf;
524	struct snd_sf_zone *zone;
525	struct soundfont_voice_rec_hdr hdr;
526	int i;
527
528	/* patch must be opened */
529	if ((sf = sflist->currsf) == NULL)
530		return -EINVAL;
531
532	if (is_special_type(sf->type))
533		return -EINVAL;
534
535	if (count < (long)sizeof(hdr)) {
536		printk(KERN_ERR "Soundfont error: invalid patch zone length\n");
537		return -EINVAL;
538	}
539	if (copy_from_user((char*)&hdr, data, sizeof(hdr)))
540		return -EFAULT;
541
542	data += sizeof(hdr);
543	count -= sizeof(hdr);
544
545	if (hdr.nvoices <= 0 || hdr.nvoices >= 100) {
546		printk(KERN_ERR "Soundfont error: Illegal voice number %d\n",
547		       hdr.nvoices);
548		return -EINVAL;
549	}
550
551	if (count < (long)sizeof(struct soundfont_voice_info) * hdr.nvoices) {
552		printk(KERN_ERR "Soundfont Error: "
553		       "patch length(%ld) is smaller than nvoices(%d)\n",
554		       count, hdr.nvoices);
555		return -EINVAL;
556	}
557
558	switch (hdr.write_mode) {
559	case SNDRV_SFNT_WR_EXCLUSIVE:
560		/* exclusive mode - if the instrument already exists,
561		   return error */
562		for (zone = sf->zones; zone; zone = zone->next) {
563			if (!zone->mapped &&
564			    zone->bank == hdr.bank &&
565			    zone->instr == hdr.instr)
566				return -EINVAL;
567		}
568		break;
569	case SNDRV_SFNT_WR_REPLACE:
570		/* replace mode - remove the instrument if it already exists */
571		remove_info(sflist, sf, hdr.bank, hdr.instr);
572		break;
573	}
574
575	for (i = 0; i < hdr.nvoices; i++) {
576		struct snd_sf_zone tmpzone;
577
578		/* copy awe_voice_info parameters */
579		if (copy_from_user(&tmpzone.v, data, sizeof(tmpzone.v))) {
580			return -EFAULT;
581		}
582
583		data += sizeof(tmpzone.v);
584		count -= sizeof(tmpzone.v);
585
586		tmpzone.bank = hdr.bank;
587		tmpzone.instr = hdr.instr;
588		tmpzone.mapped = 0;
589		tmpzone.v.sf_id = sf->id;
590		if (tmpzone.v.mode & SNDRV_SFNT_MODE_INIT_PARM)
591			init_voice_parm(&tmpzone.v.parm);
592
593		/* create a new zone */
594		if ((zone = sf_zone_new(sflist, sf)) == NULL) {
595			return -ENOMEM;
596		}
597
598		/* copy the temporary data */
599		zone->bank = tmpzone.bank;
600		zone->instr = tmpzone.instr;
601		zone->v = tmpzone.v;
602
603		/* look up the sample */
604		zone->sample = set_sample(sf, &zone->v);
605	}
606
607	return 0;
608}
609
610
611/* initialize voice_info record */
612static void
613init_voice_info(struct soundfont_voice_info *avp)
614{
615	memset(avp, 0, sizeof(*avp));
616
617	avp->root = 60;
618	avp->high = 127;
619	avp->velhigh = 127;
620	avp->fixkey = -1;
621	avp->fixvel = -1;
622	avp->fixpan = -1;
623	avp->pan = -1;
624	avp->amplitude = 127;
625	avp->scaleTuning = 100;
626
627	init_voice_parm(&avp->parm);
628}
629
630/* initialize voice_parm record:
631 * Env1/2: delay=0, attack=0, hold=0, sustain=0, decay=0, release=0.
632 * Vibrato and Tremolo effects are zero.
633 * Cutoff is maximum.
634 * Chorus and Reverb effects are zero.
635 */
636static void
637init_voice_parm(struct soundfont_voice_parm *pp)
638{
639	memset(pp, 0, sizeof(*pp));
640
641	pp->moddelay = 0x8000;
642	pp->modatkhld = 0x7f7f;
643	pp->moddcysus = 0x7f7f;
644	pp->modrelease = 0x807f;
645
646	pp->voldelay = 0x8000;
647	pp->volatkhld = 0x7f7f;
648	pp->voldcysus = 0x7f7f;
649	pp->volrelease = 0x807f;
650
651	pp->lfo1delay = 0x8000;
652	pp->lfo2delay = 0x8000;
653
654	pp->cutoff = 0xff;
655}
656
657/* search the specified sample */
658static struct snd_sf_sample *
659set_sample(struct snd_soundfont *sf, struct soundfont_voice_info *avp)
660{
661	struct snd_sf_sample *sample;
662
663	sample = find_sample(sf, avp->sample);
664	if (sample == NULL)
665		return NULL;
666
667	/* add in the actual sample offsets:
668	 * The voice_info addresses define only the relative offset
669	 * from sample pointers.  Here we calculate the actual DRAM
670	 * offset from sample pointers.
671	 */
672	avp->start += sample->v.start;
673	avp->end += sample->v.end;
674	avp->loopstart += sample->v.loopstart;
675	avp->loopend += sample->v.loopend;
676
677	/* copy mode flags */
678	avp->sample_mode = sample->v.mode_flags;
679
680	return sample;
681}
682
683/* find the sample pointer with the given id in the soundfont */
684static struct snd_sf_sample *
685find_sample(struct snd_soundfont *sf, int sample_id)
686{
687	struct snd_sf_sample *p;
688
689	if (sf == NULL)
690		return NULL;
691
692	for (p = sf->samples; p; p = p->next) {
693		if (p->v.sample == sample_id)
694			return p;
695	}
696	return NULL;
697}
698
699
700/*
701 * Load sample information, this can include data to be loaded onto
702 * the soundcard.  It can also just be a pointer into soundcard ROM.
703 * If there is data it will be written to the soundcard via the callback
704 * routine.
705 */
706static int
707load_data(struct snd_sf_list *sflist, const void __user *data, long count)
708{
709	struct snd_soundfont *sf;
710	struct soundfont_sample_info sample_info;
711	struct snd_sf_sample *sp;
712	long off;
713
714	/* patch must be opened */
715	if ((sf = sflist->currsf) == NULL)
716		return -EINVAL;
717
718	if (is_special_type(sf->type))
719		return -EINVAL;
720
721	if (copy_from_user(&sample_info, data, sizeof(sample_info)))
722		return -EFAULT;
723
724	off = sizeof(sample_info);
725
726	if (sample_info.size != (count-off)/2)
727		return -EINVAL;
728
729	/* Check for dup */
730	if (find_sample(sf, sample_info.sample)) {
731		/* if shared sample, skip this data */
732		if (sf->type & SNDRV_SFNT_PAT_SHARED)
733			return 0;
734		return -EINVAL;
735	}
736
737	/* Allocate a new sample structure */
738	if ((sp = sf_sample_new(sflist, sf)) == NULL)
739		return -ENOMEM;
740
741	sp->v = sample_info;
742	sp->v.sf_id = sf->id;
743	sp->v.dummy = 0;
744	sp->v.truesize = sp->v.size;
745
746	/*
747	 * If there is wave data then load it.
748	 */
749	if (sp->v.size > 0) {
750		int  rc;
751		rc = sflist->callback.sample_new
752			(sflist->callback.private_data, sp, sflist->memhdr,
753			 data + off, count - off);
754		if (rc < 0) {
755			sf_sample_delete(sflist, sf, sp);
756			return rc;
757		}
758		sflist->mem_used += sp->v.truesize;
759	}
760
761	return count;
762}
763
764
765/* log2_tbl[i] = log2(i+128) * 0x10000 */
766static int log_tbl[129] = {
767	0x70000, 0x702df, 0x705b9, 0x7088e, 0x70b5d, 0x70e26, 0x710eb, 0x713aa,
768	0x71663, 0x71918, 0x71bc8, 0x71e72, 0x72118, 0x723b9, 0x72655, 0x728ed,
769	0x72b80, 0x72e0e, 0x73098, 0x7331d, 0x7359e, 0x7381b, 0x73a93, 0x73d08,
770	0x73f78, 0x741e4, 0x7444c, 0x746b0, 0x74910, 0x74b6c, 0x74dc4, 0x75019,
771	0x75269, 0x754b6, 0x75700, 0x75946, 0x75b88, 0x75dc7, 0x76002, 0x7623a,
772	0x7646e, 0x766a0, 0x768cd, 0x76af8, 0x76d1f, 0x76f43, 0x77164, 0x77382,
773	0x7759d, 0x777b4, 0x779c9, 0x77bdb, 0x77dea, 0x77ff5, 0x781fe, 0x78404,
774	0x78608, 0x78808, 0x78a06, 0x78c01, 0x78df9, 0x78fef, 0x791e2, 0x793d2,
775	0x795c0, 0x797ab, 0x79993, 0x79b79, 0x79d5d, 0x79f3e, 0x7a11d, 0x7a2f9,
776	0x7a4d3, 0x7a6ab, 0x7a880, 0x7aa53, 0x7ac24, 0x7adf2, 0x7afbe, 0x7b188,
777	0x7b350, 0x7b515, 0x7b6d8, 0x7b899, 0x7ba58, 0x7bc15, 0x7bdd0, 0x7bf89,
778	0x7c140, 0x7c2f5, 0x7c4a7, 0x7c658, 0x7c807, 0x7c9b3, 0x7cb5e, 0x7cd07,
779	0x7ceae, 0x7d053, 0x7d1f7, 0x7d398, 0x7d538, 0x7d6d6, 0x7d872, 0x7da0c,
780	0x7dba4, 0x7dd3b, 0x7ded0, 0x7e063, 0x7e1f4, 0x7e384, 0x7e512, 0x7e69f,
781	0x7e829, 0x7e9b3, 0x7eb3a, 0x7ecc0, 0x7ee44, 0x7efc7, 0x7f148, 0x7f2c8,
782	0x7f446, 0x7f5c2, 0x7f73d, 0x7f8b7, 0x7fa2f, 0x7fba5, 0x7fd1a, 0x7fe8d,
783	0x80000,
784};
785
786/* convert from linear to log value
787 *
788 * conversion: value = log2(amount / base) * ratio
789 *
790 * argument:
791 *   amount = linear value (unsigned, 32bit max)
792 *   offset = base offset (:= log2(base) * 0x10000)
793 *   ratio = division ratio
794 *
795 */
796int
797snd_sf_linear_to_log(unsigned int amount, int offset, int ratio)
798{
799	int v;
800	int s, low, bit;
801
802	if (amount < 2)
803		return 0;
804	for (bit = 0; ! (amount & 0x80000000L); bit++)
805		amount <<= 1;
806	s = (amount >> 24) & 0x7f;
807	low = (amount >> 16) & 0xff;
808	/* linear approxmimation by lower 8 bit */
809	v = (log_tbl[s + 1] * low + log_tbl[s] * (0x100 - low)) >> 8;
810	v -= offset;
811	v = (v * ratio) >> 16;
812	v += (24 - bit) * ratio;
813	return v;
814}
815
816EXPORT_SYMBOL(snd_sf_linear_to_log);
817
818
819#define OFFSET_MSEC		653117		/* base = 1000 */
820#define OFFSET_ABSCENT		851781		/* base = 8176 */
821#define OFFSET_SAMPLERATE	1011119		/* base = 44100 */
822
823#define ABSCENT_RATIO		1200
824#define TIMECENT_RATIO		1200
825#define SAMPLERATE_RATIO	4096
826
827/*
828 * mHz to abscent
829 * conversion: abscent = log2(MHz / 8176) * 1200
830 */
831static int
832freq_to_note(int mhz)
833{
834	return snd_sf_linear_to_log(mhz, OFFSET_ABSCENT, ABSCENT_RATIO);
835}
836
837/* convert Hz to AWE32 rate offset:
838 * sample pitch offset for the specified sample rate
839 * rate=44100 is no offset, each 4096 is 1 octave (twice).
840 * eg, when rate is 22050, this offset becomes -4096.
841 *
842 * conversion: offset = log2(Hz / 44100) * 4096
843 */
844static int
845calc_rate_offset(int hz)
846{
847	return snd_sf_linear_to_log(hz, OFFSET_SAMPLERATE, SAMPLERATE_RATIO);
848}
849
850
851/* calculate GUS envelope time */
852static int
853calc_gus_envelope_time(int rate, int start, int end)
854{
855	int r, p, t;
856	r = (3 - ((rate >> 6) & 3)) * 3;
857	p = rate & 0x3f;
858	t = end - start;
859	if (t < 0) t = -t;
860	if (13 > r)
861		t = t << (13 - r);
862	else
863		t = t >> (r - 13);
864	return (t * 10) / (p * 441);
865}
866
867/* convert envelope time parameter to soundfont parameters */
868
869/* attack & decay/release time table (msec) */
870static short attack_time_tbl[128] = {
87132767, 32767, 5989, 4235, 2994, 2518, 2117, 1780, 1497, 1373, 1259, 1154, 1058, 970, 890, 816,
872707, 691, 662, 634, 607, 581, 557, 533, 510, 489, 468, 448, 429, 411, 393, 377,
873361, 345, 331, 317, 303, 290, 278, 266, 255, 244, 234, 224, 214, 205, 196, 188,
874180, 172, 165, 158, 151, 145, 139, 133, 127, 122, 117, 112, 107, 102, 98, 94,
87590, 86, 82, 79, 75, 72, 69, 66, 63, 61, 58, 56, 53, 51, 49, 47,
87645, 43, 41, 39, 37, 36, 34, 33, 31, 30, 29, 28, 26, 25, 24, 23,
87722, 21, 20, 19, 19, 18, 17, 16, 16, 15, 15, 14, 13, 13, 12, 12,
87811, 11, 10, 10, 10, 9, 9, 8, 8, 8, 8, 7, 7, 7, 6, 0,
879};
880
881static short decay_time_tbl[128] = {
88232767, 32767, 22614, 15990, 11307, 9508, 7995, 6723, 5653, 5184, 4754, 4359, 3997, 3665, 3361, 3082,
8832828, 2765, 2648, 2535, 2428, 2325, 2226, 2132, 2042, 1955, 1872, 1793, 1717, 1644, 1574, 1507,
8841443, 1382, 1324, 1267, 1214, 1162, 1113, 1066, 978, 936, 897, 859, 822, 787, 754, 722,
885691, 662, 634, 607, 581, 557, 533, 510, 489, 468, 448, 429, 411, 393, 377, 361,
886345, 331, 317, 303, 290, 278, 266, 255, 244, 234, 224, 214, 205, 196, 188, 180,
887172, 165, 158, 151, 145, 139, 133, 127, 122, 117, 112, 107, 102, 98, 94, 90,
88886, 82, 79, 75, 72, 69, 66, 63, 61, 58, 56, 53, 51, 49, 47, 45,
88943, 41, 39, 37, 36, 34, 33, 31, 30, 29, 28, 26, 25, 24, 23, 22,
890};
891
892/* delay time = 0x8000 - msec/92 */
893int
894snd_sf_calc_parm_hold(int msec)
895{
896	int val = (0x7f * 92 - msec) / 92;
897	if (val < 1) val = 1;
898	if (val >= 126) val = 126;
899	return val;
900}
901
902/* search an index for specified time from given time table */
903static int
904calc_parm_search(int msec, short *table)
905{
906	int left = 1, right = 127, mid;
907	while (left < right) {
908		mid = (left + right) / 2;
909		if (msec < (int)table[mid])
910			left = mid + 1;
911		else
912			right = mid;
913	}
914	return left;
915}
916
917/* attack time: search from time table */
918int
919snd_sf_calc_parm_attack(int msec)
920{
921	return calc_parm_search(msec, attack_time_tbl);
922}
923
924/* decay/release time: search from time table */
925int
926snd_sf_calc_parm_decay(int msec)
927{
928	return calc_parm_search(msec, decay_time_tbl);
929}
930
931int snd_sf_vol_table[128] = {
932	255,111,95,86,79,74,70,66,63,61,58,56,54,52,50,49,
933	47,46,45,43,42,41,40,39,38,37,36,35,34,34,33,32,
934	31,31,30,29,29,28,27,27,26,26,25,24,24,23,23,22,
935	22,21,21,21,20,20,19,19,18,18,18,17,17,16,16,16,
936	15,15,15,14,14,14,13,13,13,12,12,12,11,11,11,10,
937	10,10,10,9,9,9,8,8,8,8,7,7,7,7,6,6,
938	6,6,5,5,5,5,5,4,4,4,4,3,3,3,3,3,
939	2,2,2,2,2,1,1,1,1,1,0,0,0,0,0,0,
940};
941
942
943#define calc_gus_sustain(val)  (0x7f - snd_sf_vol_table[(val)/2])
944#define calc_gus_attenuation(val)	snd_sf_vol_table[(val)/2]
945
946/* load GUS patch */
947static int
948load_guspatch(struct snd_sf_list *sflist, const char __user *data,
949	      long count, int client)
950{
951	struct patch_info patch;
952	struct snd_soundfont *sf;
953	struct snd_sf_zone *zone;
954	struct snd_sf_sample *smp;
955	int note, sample_id;
956	int rc;
957
958	if (count < (long)sizeof(patch)) {
959		snd_printk(KERN_ERR "patch record too small %ld\n", count);
960		return -EINVAL;
961	}
962	if (copy_from_user(&patch, data, sizeof(patch)))
963		return -EFAULT;
964
965	count -= sizeof(patch);
966	data += sizeof(patch);
967
968	sf = newsf(sflist, SNDRV_SFNT_PAT_TYPE_GUS|SNDRV_SFNT_PAT_SHARED, NULL);
969	if (sf == NULL)
970		return -ENOMEM;
971	if ((smp = sf_sample_new(sflist, sf)) == NULL)
972		return -ENOMEM;
973	sample_id = sflist->sample_counter;
974	smp->v.sample = sample_id;
975	smp->v.start = 0;
976	smp->v.end = patch.len;
977	smp->v.loopstart = patch.loop_start;
978	smp->v.loopend = patch.loop_end;
979	smp->v.size = patch.len;
980
981	/* set up mode flags */
982	smp->v.mode_flags = 0;
983	if (!(patch.mode & WAVE_16_BITS))
984		smp->v.mode_flags |= SNDRV_SFNT_SAMPLE_8BITS;
985	if (patch.mode & WAVE_UNSIGNED)
986		smp->v.mode_flags |= SNDRV_SFNT_SAMPLE_UNSIGNED;
987	smp->v.mode_flags |= SNDRV_SFNT_SAMPLE_NO_BLANK;
988	if (!(patch.mode & (WAVE_LOOPING|WAVE_BIDIR_LOOP|WAVE_LOOP_BACK)))
989		smp->v.mode_flags |= SNDRV_SFNT_SAMPLE_SINGLESHOT;
990	if (patch.mode & WAVE_BIDIR_LOOP)
991		smp->v.mode_flags |= SNDRV_SFNT_SAMPLE_BIDIR_LOOP;
992	if (patch.mode & WAVE_LOOP_BACK)
993		smp->v.mode_flags |= SNDRV_SFNT_SAMPLE_REVERSE_LOOP;
994
995	if (patch.mode & WAVE_16_BITS) {
996		/* convert to word offsets */
997		smp->v.size /= 2;
998		smp->v.end /= 2;
999		smp->v.loopstart /= 2;
1000		smp->v.loopend /= 2;
1001	}
1002	/*smp->v.loopend++;*/
1003
1004	smp->v.dummy = 0;
1005	smp->v.truesize = 0;
1006	smp->v.sf_id = sf->id;
1007
1008	/* set up voice info */
1009	if ((zone = sf_zone_new(sflist, sf)) == NULL) {
1010		sf_sample_delete(sflist, sf, smp);
1011		return -ENOMEM;
1012	}
1013
1014	/*
1015	 * load wave data
1016	 */
1017	if (sflist->callback.sample_new) {
1018		rc = sflist->callback.sample_new
1019			(sflist->callback.private_data, smp, sflist->memhdr,
1020			 data, count);
1021		if (rc < 0) {
1022			sf_sample_delete(sflist, sf, smp);
1023			return rc;
1024		}
1025		/* memory offset is updated after */
1026	}
1027
1028	/* update the memory offset here */
1029	sflist->mem_used += smp->v.truesize;
1030
1031	zone->v.sample = sample_id; /* the last sample */
1032	zone->v.rate_offset = calc_rate_offset(patch.base_freq);
1033	note = freq_to_note(patch.base_note);
1034	zone->v.root = note / 100;
1035	zone->v.tune = -(note % 100);
1036	zone->v.low = (freq_to_note(patch.low_note) + 99) / 100;
1037	zone->v.high = freq_to_note(patch.high_note) / 100;
1038	/* panning position; -128 - 127 => 0-127 */
1039	zone->v.pan = (patch.panning + 128) / 2;
1040
1041	/* detuning is ignored */
1042	/* 6points volume envelope */
1043	if (patch.mode & WAVE_ENVELOPES) {
1044		int attack, hold, decay, release;
1045		attack = calc_gus_envelope_time
1046			(patch.env_rate[0], 0, patch.env_offset[0]);
1047		hold = calc_gus_envelope_time
1048			(patch.env_rate[1], patch.env_offset[0],
1049			 patch.env_offset[1]);
1050		decay = calc_gus_envelope_time
1051			(patch.env_rate[2], patch.env_offset[1],
1052			 patch.env_offset[2]);
1053		release = calc_gus_envelope_time
1054			(patch.env_rate[3], patch.env_offset[1],
1055			 patch.env_offset[4]);
1056		release += calc_gus_envelope_time
1057			(patch.env_rate[4], patch.env_offset[3],
1058			 patch.env_offset[4]);
1059		release += calc_gus_envelope_time
1060			(patch.env_rate[5], patch.env_offset[4],
1061			 patch.env_offset[5]);
1062		zone->v.parm.volatkhld =
1063			(snd_sf_calc_parm_hold(hold) << 8) |
1064			snd_sf_calc_parm_attack(attack);
1065		zone->v.parm.voldcysus = (calc_gus_sustain(patch.env_offset[2]) << 8) |
1066			snd_sf_calc_parm_decay(decay);
1067		zone->v.parm.volrelease = 0x8000 | snd_sf_calc_parm_decay(release);
1068		zone->v.attenuation = calc_gus_attenuation(patch.env_offset[0]);
1069	}
1070
1071	/* fast release */
1072	if (patch.mode & WAVE_FAST_RELEASE) {
1073		zone->v.parm.volrelease = 0x807f;
1074	}
1075
1076	/* tremolo effect */
1077	if (patch.mode & WAVE_TREMOLO) {
1078		int rate = (patch.tremolo_rate * 1000 / 38) / 42;
1079		zone->v.parm.tremfrq = ((patch.tremolo_depth / 2) << 8) | rate;
1080	}
1081	/* vibrato effect */
1082	if (patch.mode & WAVE_VIBRATO) {
1083		int rate = (patch.vibrato_rate * 1000 / 38) / 42;
1084		zone->v.parm.fm2frq2 = ((patch.vibrato_depth / 6) << 8) | rate;
1085	}
1086
1087	/* scale_freq, scale_factor, volume, and fractions not implemented */
1088
1089	if (!(smp->v.mode_flags & SNDRV_SFNT_SAMPLE_SINGLESHOT))
1090		zone->v.mode = SNDRV_SFNT_MODE_LOOPING;
1091	else
1092		zone->v.mode = 0;
1093
1094	/* append to the tail of the list */
1095	/*zone->bank = ctrls[AWE_MD_GUS_BANK];*/
1096	zone->bank = 0;
1097	zone->instr = patch.instr_no;
1098	zone->mapped = 0;
1099	zone->v.sf_id = sf->id;
1100
1101	zone->sample = set_sample(sf, &zone->v);
1102
1103	/* rebuild preset now */
1104	add_preset(sflist, zone);
1105
1106	return 0;
1107}
1108
1109/* load GUS patch */
1110int
1111snd_soundfont_load_guspatch(struct snd_sf_list *sflist, const char __user *data,
1112			    long count, int client)
1113{
1114	int rc;
1115	lock_preset(sflist);
1116	rc = load_guspatch(sflist, data, count, client);
1117	unlock_preset(sflist);
1118	return rc;
1119}
1120
1121
1122/*
1123 * Rebuild the preset table.  This is like a hash table in that it allows
1124 * quick access to the zone information.  For each preset there are zone
1125 * structures linked by next_instr and by next_zone.  Former is the whole
1126 * link for this preset, and latter is the link for zone (i.e. instrument/
1127 * bank/key combination).
1128 */
1129static void
1130rebuild_presets(struct snd_sf_list *sflist)
1131{
1132	struct snd_soundfont *sf;
1133	struct snd_sf_zone *cur;
1134
1135	/* clear preset table */
1136	memset(sflist->presets, 0, sizeof(sflist->presets));
1137
1138	/* search all fonts and insert each font */
1139	for (sf = sflist->fonts; sf; sf = sf->next) {
1140		for (cur = sf->zones; cur; cur = cur->next) {
1141			if (! cur->mapped && cur->sample == NULL) {
1142				/* try again to search the corresponding sample */
1143				cur->sample = set_sample(sf, &cur->v);
1144				if (cur->sample == NULL)
1145					continue;
1146			}
1147
1148			add_preset(sflist, cur);
1149		}
1150	}
1151}
1152
1153
1154/*
1155 * add the given zone to preset table
1156 */
1157static void
1158add_preset(struct snd_sf_list *sflist, struct snd_sf_zone *cur)
1159{
1160	struct snd_sf_zone *zone;
1161	int index;
1162
1163	zone = search_first_zone(sflist, cur->bank, cur->instr, cur->v.low);
1164	if (zone && zone->v.sf_id != cur->v.sf_id) {
1165		/* different instrument was already defined */
1166		struct snd_sf_zone *p;
1167		/* compare the allocated time */
1168		for (p = zone; p; p = p->next_zone) {
1169			if (p->counter > cur->counter)
1170				/* the current is older.. skipped */
1171				return;
1172		}
1173		/* remove old zones */
1174		delete_preset(sflist, zone);
1175		zone = NULL; /* do not forget to clear this! */
1176	}
1177
1178	/* prepend this zone */
1179	if ((index = get_index(cur->bank, cur->instr, cur->v.low)) < 0)
1180		return;
1181	cur->next_zone = zone; /* zone link */
1182	cur->next_instr = sflist->presets[index]; /* preset table link */
1183	sflist->presets[index] = cur;
1184}
1185
1186/*
1187 * delete the given zones from preset_table
1188 */
1189static void
1190delete_preset(struct snd_sf_list *sflist, struct snd_sf_zone *zp)
1191{
1192	int index;
1193	struct snd_sf_zone *p;
1194
1195	if ((index = get_index(zp->bank, zp->instr, zp->v.low)) < 0)
1196		return;
1197	for (p = sflist->presets[index]; p; p = p->next_instr) {
1198		while (p->next_instr == zp) {
1199			p->next_instr = zp->next_instr;
1200			zp = zp->next_zone;
1201			if (zp == NULL)
1202				return;
1203		}
1204	}
1205}
1206
1207
1208/*
1209 * Search matching zones from preset table.
1210 * The note can be rewritten by preset mapping (alias).
1211 * The found zones are stored on 'table' array.  max_layers defines
1212 * the maximum number of elements in this array.
1213 * This function returns the number of found zones.  0 if not found.
1214 */
1215int
1216snd_soundfont_search_zone(struct snd_sf_list *sflist, int *notep, int vel,
1217			  int preset, int bank,
1218			  int def_preset, int def_bank,
1219			  struct snd_sf_zone **table, int max_layers)
1220{
1221	int nvoices;
1222	unsigned long flags;
1223
1224	/* this function is supposed to be called atomically,
1225	 * so we check the lock.  if it's busy, just returns 0 to
1226	 * tell the caller the busy state
1227	 */
1228	spin_lock_irqsave(&sflist->lock, flags);
1229	if (sflist->presets_locked) {
1230		spin_unlock_irqrestore(&sflist->lock, flags);
1231		return 0;
1232	}
1233	nvoices = search_zones(sflist, notep, vel, preset, bank,
1234			       table, max_layers, 0);
1235	if (! nvoices) {
1236		if (preset != def_preset || bank != def_bank)
1237			nvoices = search_zones(sflist, notep, vel,
1238					       def_preset, def_bank,
1239					       table, max_layers, 0);
1240	}
1241	spin_unlock_irqrestore(&sflist->lock, flags);
1242	return nvoices;
1243}
1244
1245
1246/*
1247 * search the first matching zone
1248 */
1249static struct snd_sf_zone *
1250search_first_zone(struct snd_sf_list *sflist, int bank, int preset, int key)
1251{
1252	int index;
1253	struct snd_sf_zone *zp;
1254
1255	if ((index = get_index(bank, preset, key)) < 0)
1256		return NULL;
1257	for (zp = sflist->presets[index]; zp; zp = zp->next_instr) {
1258		if (zp->instr == preset && zp->bank == bank)
1259			return zp;
1260	}
1261	return NULL;
1262}
1263
1264
1265/*
1266 * search matching zones from sflist.  can be called recursively.
1267 */
1268static int
1269search_zones(struct snd_sf_list *sflist, int *notep, int vel,
1270	     int preset, int bank, struct snd_sf_zone **table,
1271	     int max_layers, int level)
1272{
1273	struct snd_sf_zone *zp;
1274	int nvoices;
1275
1276	zp = search_first_zone(sflist, bank, preset, *notep);
1277	nvoices = 0;
1278	for (; zp; zp = zp->next_zone) {
1279		if (*notep >= zp->v.low && *notep <= zp->v.high &&
1280		    vel >= zp->v.vellow && vel <= zp->v.velhigh) {
1281			if (zp->mapped) {
1282				/* search preset mapping (aliasing) */
1283				int key = zp->v.fixkey;
1284				preset = zp->v.start;
1285				bank = zp->v.end;
1286
1287				if (level > 5) /* too deep alias level */
1288					return 0;
1289				if (key < 0)
1290					key = *notep;
1291				nvoices = search_zones(sflist, &key, vel,
1292						       preset, bank, table,
1293						       max_layers, level + 1);
1294				if (nvoices > 0)
1295					*notep = key;
1296				break;
1297			}
1298			table[nvoices++] = zp;
1299			if (nvoices >= max_layers)
1300				break;
1301		}
1302	}
1303
1304	return nvoices;
1305}
1306
1307
1308/* calculate the index of preset table:
1309 * drums are mapped from 128 to 255 according to its note key.
1310 * other instruments are mapped from 0 to 127.
1311 * if the index is out of range, return -1.
1312 */
1313static int
1314get_index(int bank, int instr, int key)
1315{
1316	int index;
1317	if (SF_IS_DRUM_BANK(bank))
1318		index = key + SF_MAX_INSTRUMENTS;
1319	else
1320		index = instr;
1321	index = index % SF_MAX_PRESETS;
1322	if (index < 0)
1323		return -1;
1324	return index;
1325}
1326
1327/*
1328 * Initialise the sflist structure.
1329 */
1330static void
1331snd_sf_init(struct snd_sf_list *sflist)
1332{
1333	memset(sflist->presets, 0, sizeof(sflist->presets));
1334
1335	sflist->mem_used = 0;
1336	sflist->currsf = NULL;
1337	sflist->open_client = -1;
1338	sflist->fonts = NULL;
1339	sflist->fonts_size = 0;
1340	sflist->zone_counter = 0;
1341	sflist->sample_counter = 0;
1342	sflist->zone_locked = 0;
1343	sflist->sample_locked = 0;
1344}
1345
1346/*
1347 * Release all list records
1348 */
1349static void
1350snd_sf_clear(struct snd_sf_list *sflist)
1351{
1352	struct snd_soundfont *sf, *nextsf;
1353	struct snd_sf_zone *zp, *nextzp;
1354	struct snd_sf_sample *sp, *nextsp;
1355
1356	for (sf = sflist->fonts; sf; sf = nextsf) {
1357		nextsf = sf->next;
1358		for (zp = sf->zones; zp; zp = nextzp) {
1359			nextzp = zp->next;
1360			kfree(zp);
1361		}
1362		for (sp = sf->samples; sp; sp = nextsp) {
1363			nextsp = sp->next;
1364			if (sflist->callback.sample_free)
1365				sflist->callback.sample_free(sflist->callback.private_data,
1366							     sp, sflist->memhdr);
1367			kfree(sp);
1368		}
1369		kfree(sf);
1370	}
1371
1372	snd_sf_init(sflist);
1373}
1374
1375
1376/*
1377 * Create a new sflist structure
1378 */
1379struct snd_sf_list *
1380snd_sf_new(struct snd_sf_callback *callback, struct snd_util_memhdr *hdr)
1381{
1382	struct snd_sf_list *sflist;
1383
1384	if ((sflist = kzalloc(sizeof(*sflist), GFP_KERNEL)) == NULL)
1385		return NULL;
1386
1387	mutex_init(&sflist->presets_mutex);
1388	spin_lock_init(&sflist->lock);
1389	sflist->memhdr = hdr;
1390
1391	if (callback)
1392		sflist->callback = *callback;
1393
1394	snd_sf_init(sflist);
1395	return sflist;
1396}
1397
1398
1399/*
1400 * Free everything allocated off the sflist structure.
1401 */
1402void
1403snd_sf_free(struct snd_sf_list *sflist)
1404{
1405	if (sflist == NULL)
1406		return;
1407
1408	lock_preset(sflist);
1409	if (sflist->callback.sample_reset)
1410		sflist->callback.sample_reset(sflist->callback.private_data);
1411	snd_sf_clear(sflist);
1412	unlock_preset(sflist);
1413
1414	kfree(sflist);
1415}
1416
1417/*
1418 * Remove all samples
1419 * The soundcard should be silet before calling this function.
1420 */
1421int
1422snd_soundfont_remove_samples(struct snd_sf_list *sflist)
1423{
1424	lock_preset(sflist);
1425	if (sflist->callback.sample_reset)
1426		sflist->callback.sample_reset(sflist->callback.private_data);
1427	snd_sf_clear(sflist);
1428	unlock_preset(sflist);
1429
1430	return 0;
1431}
1432
1433/*
1434 * Remove unlocked samples.
1435 * The soundcard should be silent before calling this function.
1436 */
1437int
1438snd_soundfont_remove_unlocked(struct snd_sf_list *sflist)
1439{
1440	struct snd_soundfont *sf;
1441	struct snd_sf_zone *zp, *nextzp;
1442	struct snd_sf_sample *sp, *nextsp;
1443
1444	lock_preset(sflist);
1445
1446	if (sflist->callback.sample_reset)
1447		sflist->callback.sample_reset(sflist->callback.private_data);
1448
1449	/* to be sure */
1450	memset(sflist->presets, 0, sizeof(sflist->presets));
1451
1452	for (sf = sflist->fonts; sf; sf = sf->next) {
1453		for (zp = sf->zones; zp; zp = nextzp) {
1454			if (zp->counter < sflist->zone_locked)
1455				break;
1456			nextzp = zp->next;
1457			sf->zones = nextzp;
1458			kfree(zp);
1459		}
1460
1461		for (sp = sf->samples; sp; sp = nextsp) {
1462			if (sp->counter < sflist->sample_locked)
1463				break;
1464			nextsp = sp->next;
1465			sf->samples = nextsp;
1466			sflist->mem_used -= sp->v.truesize;
1467			if (sflist->callback.sample_free)
1468				sflist->callback.sample_free(sflist->callback.private_data,
1469							     sp, sflist->memhdr);
1470			kfree(sp);
1471		}
1472	}
1473
1474	sflist->zone_counter = sflist->zone_locked;
1475	sflist->sample_counter = sflist->sample_locked;
1476
1477	rebuild_presets(sflist);
1478
1479	unlock_preset(sflist);
1480	return 0;
1481}
1482