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