[TG3]: Set minimal hw interrupt mitigation.
[linux-2.6/verdex.git] / sound / synth / emux / soundfont.c
blob901a7db05bdef5ed70724886f3e60ff8d57424c4
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.
6 * Copyright (C) 1999 Steve Ratcliffe
7 * Copyright (c) 1999-2000 Takashi Iwai <tiwai@suse.de>
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.
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.
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
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.
28 #include <sound/driver.h>
29 #include <asm/uaccess.h>
30 #include <linux/slab.h>
31 #include <sound/core.h>
32 #include <sound/soundfont.h>
33 #include <sound/seq_oss_legacy.h>
35 /* Prototypes for static functions */
37 static int open_patch(snd_sf_list_t *sflist, const char __user *data, int count, int client);
38 static snd_soundfont_t *newsf(snd_sf_list_t *sflist, int type, char *name);
39 static int is_identical_font(snd_soundfont_t *sf, int type, unsigned char *name);
40 static int close_patch(snd_sf_list_t *sflist);
41 static int probe_data(snd_sf_list_t *sflist, int sample_id);
42 static void set_zone_counter(snd_sf_list_t *sflist, snd_soundfont_t *sf, snd_sf_zone_t *zp);
43 static snd_sf_zone_t *sf_zone_new(snd_sf_list_t *sflist, snd_soundfont_t *sf);
44 static void set_sample_counter(snd_sf_list_t *sflist, snd_soundfont_t *sf, snd_sf_sample_t *sp);
45 static snd_sf_sample_t *sf_sample_new(snd_sf_list_t *sflist, snd_soundfont_t *sf);
46 static void sf_sample_delete(snd_sf_list_t *sflist, snd_soundfont_t *sf, snd_sf_sample_t *sp);
47 static int load_map(snd_sf_list_t *sflist, const void __user *data, int count);
48 static int load_info(snd_sf_list_t *sflist, const void __user *data, long count);
49 static int remove_info(snd_sf_list_t *sflist, snd_soundfont_t *sf, int bank, int instr);
50 static void init_voice_info(soundfont_voice_info_t *avp);
51 static void init_voice_parm(soundfont_voice_parm_t *pp);
52 static snd_sf_sample_t *set_sample(snd_soundfont_t *sf, soundfont_voice_info_t *avp);
53 static snd_sf_sample_t *find_sample(snd_soundfont_t *sf, int sample_id);
54 static int load_data(snd_sf_list_t *sflist, const void __user *data, long count);
55 static void rebuild_presets(snd_sf_list_t *sflist);
56 static void add_preset(snd_sf_list_t *sflist, snd_sf_zone_t *cur);
57 static void delete_preset(snd_sf_list_t *sflist, snd_sf_zone_t *zp);
58 static snd_sf_zone_t *search_first_zone(snd_sf_list_t *sflist, int bank, int preset, int key);
59 static int search_zones(snd_sf_list_t *sflist, int *notep, int vel, int preset, int bank, snd_sf_zone_t **table, int max_layers, int level);
60 static int get_index(int bank, int instr, int key);
61 static void snd_sf_init(snd_sf_list_t *sflist);
62 static void snd_sf_clear(snd_sf_list_t *sflist);
65 * lock access to sflist
67 static void
68 lock_preset(snd_sf_list_t *sflist)
70 unsigned long flags;
71 down(&sflist->presets_mutex);
72 spin_lock_irqsave(&sflist->lock, flags);
73 sflist->presets_locked = 1;
74 spin_unlock_irqrestore(&sflist->lock, flags);
79 * remove lock
81 static void
82 unlock_preset(snd_sf_list_t *sflist)
84 unsigned long flags;
85 spin_lock_irqsave(&sflist->lock, flags);
86 sflist->presets_locked = 0;
87 spin_unlock_irqrestore(&sflist->lock, flags);
88 up(&sflist->presets_mutex);
93 * close the patch if the patch was opened by this client.
95 int
96 snd_soundfont_close_check(snd_sf_list_t *sflist, int client)
98 unsigned long flags;
99 spin_lock_irqsave(&sflist->lock, flags);
100 if (sflist->open_client == client) {
101 spin_unlock_irqrestore(&sflist->lock, flags);
102 return close_patch(sflist);
104 spin_unlock_irqrestore(&sflist->lock, flags);
105 return 0;
110 * Deal with a soundfont patch. Any driver could use these routines
111 * although it was designed for the AWE64.
113 * The sample_write and callargs pararameters allow a callback into
114 * the actual driver to write sample data to the board or whatever
115 * it wants to do with it.
118 snd_soundfont_load(snd_sf_list_t *sflist, const void __user *data, long count, int client)
120 soundfont_patch_info_t patch;
121 unsigned long flags;
122 int rc;
124 if (count < (long)sizeof(patch)) {
125 snd_printk("patch record too small %ld\n", count);
126 return -EINVAL;
128 if (copy_from_user(&patch, data, sizeof(patch)))
129 return -EFAULT;
131 count -= sizeof(patch);
132 data += sizeof(patch);
134 if (patch.key != SNDRV_OSS_SOUNDFONT_PATCH) {
135 snd_printk("'The wrong kind of patch' %x\n", patch.key);
136 return -EINVAL;
138 if (count < patch.len) {
139 snd_printk("Patch too short %ld, need %d\n", count, patch.len);
140 return -EINVAL;
142 if (patch.len < 0) {
143 snd_printk("poor length %d\n", patch.len);
144 return -EINVAL;
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;
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;
161 spin_unlock_irqrestore(&sflist->lock, flags);
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("soundfont: remove_info: patch not opened\n");
188 rc = -EINVAL;
189 } else {
190 int bank, instr;
191 bank = ((unsigned short)patch.optarg >> 8) & 0xff;
192 instr = (unsigned short)patch.optarg & 0xff;
193 if (! remove_info(sflist, sflist->currsf, bank, instr))
194 rc = -EINVAL;
195 else
196 rc = 0;
198 break;
200 unlock_preset(sflist);
202 return rc;
206 /* check if specified type is special font (GUS or preset-alias) */
207 static inline int
208 is_special_type(int type)
210 type &= 0x0f;
211 return (type == SNDRV_SFNT_PAT_TYPE_GUS ||
212 type == SNDRV_SFNT_PAT_TYPE_MAP);
216 /* open patch; create sf list */
217 static int
218 open_patch(snd_sf_list_t *sflist, const char __user *data, int count, int client)
220 soundfont_open_parm_t parm;
221 snd_soundfont_t *sf;
222 unsigned long flags;
224 spin_lock_irqsave(&sflist->lock, flags);
225 if (sflist->open_client >= 0 || sflist->currsf) {
226 spin_unlock_irqrestore(&sflist->lock, flags);
227 return -EBUSY;
229 spin_unlock_irqrestore(&sflist->lock, flags);
231 if (copy_from_user(&parm, data, sizeof(parm)))
232 return -EFAULT;
234 if (is_special_type(parm.type)) {
235 parm.type |= SNDRV_SFNT_PAT_SHARED;
236 sf = newsf(sflist, parm.type, NULL);
237 } else
238 sf = newsf(sflist, parm.type, parm.name);
239 if (sf == NULL) {
240 return -ENOMEM;
243 spin_lock_irqsave(&sflist->lock, flags);
244 sflist->open_client = client;
245 sflist->currsf = sf;
246 spin_unlock_irqrestore(&sflist->lock, flags);
248 return 0;
252 * Allocate a new soundfont structure.
254 static snd_soundfont_t *
255 newsf(snd_sf_list_t *sflist, int type, char *name)
257 snd_soundfont_t *sf;
259 /* check the shared fonts */
260 if (type & SNDRV_SFNT_PAT_SHARED) {
261 for (sf = sflist->fonts; sf; sf = sf->next) {
262 if (is_identical_font(sf, type, name)) {
263 return sf;
268 /* not found -- create a new one */
269 sf = kcalloc(1, sizeof(*sf), GFP_KERNEL);
270 if (sf == NULL)
271 return NULL;
272 sf->id = sflist->fonts_size;
273 sflist->fonts_size++;
275 /* prepend this record */
276 sf->next = sflist->fonts;
277 sflist->fonts = sf;
279 sf->type = type;
280 sf->zones = NULL;
281 sf->samples = NULL;
282 if (name)
283 memcpy(sf->name, name, SNDRV_SFNT_PATCH_NAME_LEN);
285 return sf;
288 /* check if the given name matches to the existing list */
289 static int
290 is_identical_font(snd_soundfont_t *sf, int type, unsigned char *name)
292 return ((sf->type & SNDRV_SFNT_PAT_SHARED) &&
293 (sf->type & 0x0f) == (type & 0x0f) &&
294 (name == NULL ||
295 memcmp(sf->name, name, SNDRV_SFNT_PATCH_NAME_LEN) == 0));
299 * Close the current patch.
301 static int
302 close_patch(snd_sf_list_t *sflist)
304 unsigned long flags;
306 spin_lock_irqsave(&sflist->lock, flags);
307 sflist->currsf = NULL;
308 sflist->open_client = -1;
309 spin_unlock_irqrestore(&sflist->lock, flags);
311 rebuild_presets(sflist);
313 return 0;
317 /* probe sample in the current list -- nothing to be loaded */
318 static int
319 probe_data(snd_sf_list_t *sflist, int sample_id)
321 /* patch must be opened */
322 if (sflist->currsf) {
323 /* search the specified sample by optarg */
324 if (find_sample(sflist->currsf, sample_id))
325 return 0;
327 return -EINVAL;
331 * increment zone counter
333 static void
334 set_zone_counter(snd_sf_list_t *sflist, snd_soundfont_t *sf, snd_sf_zone_t *zp)
336 zp->counter = sflist->zone_counter++;
337 if (sf->type & SNDRV_SFNT_PAT_LOCKED)
338 sflist->zone_locked = sflist->zone_counter;
342 * allocate a new zone record
344 static snd_sf_zone_t *
345 sf_zone_new(snd_sf_list_t *sflist, snd_soundfont_t *sf)
347 snd_sf_zone_t *zp;
349 if ((zp = kcalloc(1, sizeof(*zp), GFP_KERNEL)) == NULL)
350 return NULL;
351 zp->next = sf->zones;
352 sf->zones = zp;
354 init_voice_info(&zp->v);
356 set_zone_counter(sflist, sf, zp);
357 return zp;
362 * increment sample couter
364 static void
365 set_sample_counter(snd_sf_list_t *sflist, snd_soundfont_t *sf, snd_sf_sample_t *sp)
367 sp->counter = sflist->sample_counter++;
368 if (sf->type & SNDRV_SFNT_PAT_LOCKED)
369 sflist->sample_locked = sflist->sample_counter;
373 * allocate a new sample list record
375 static snd_sf_sample_t *
376 sf_sample_new(snd_sf_list_t *sflist, snd_soundfont_t *sf)
378 snd_sf_sample_t *sp;
380 if ((sp = kcalloc(1, sizeof(*sp), GFP_KERNEL)) == NULL)
381 return NULL;
383 sp->next = sf->samples;
384 sf->samples = sp;
386 set_sample_counter(sflist, sf, sp);
387 return sp;
391 * delete sample list -- this is an exceptional job.
392 * only the last allocated sample can be deleted.
394 static void
395 sf_sample_delete(snd_sf_list_t *sflist, snd_soundfont_t *sf, snd_sf_sample_t *sp)
397 /* only last sample is accepted */
398 if (sp == sf->samples) {
399 sf->samples = sp->next;
400 kfree(sp);
405 /* load voice map */
406 static int
407 load_map(snd_sf_list_t *sflist, const void __user *data, int count)
409 snd_sf_zone_t *zp, *prevp;
410 snd_soundfont_t *sf;
411 soundfont_voice_map_t map;
413 /* get the link info */
414 if (count < (int)sizeof(map))
415 return -EINVAL;
416 if (copy_from_user(&map, data, sizeof(map)))
417 return -EFAULT;
419 if (map.map_instr < 0 || map.map_instr >= SF_MAX_INSTRUMENTS)
420 return -EINVAL;
422 sf = newsf(sflist, SNDRV_SFNT_PAT_TYPE_MAP|SNDRV_SFNT_PAT_SHARED, NULL);
423 if (sf == NULL)
424 return -ENOMEM;
426 prevp = NULL;
427 for (zp = sf->zones; zp; prevp = zp, zp = zp->next) {
428 if (zp->mapped &&
429 zp->instr == map.map_instr &&
430 zp->bank == map.map_bank &&
431 zp->v.low == map.map_key &&
432 zp->v.start == map.src_instr &&
433 zp->v.end == map.src_bank &&
434 zp->v.fixkey == map.src_key) {
435 /* the same mapping is already present */
436 /* relink this record to the link head */
437 if (prevp) {
438 prevp->next = zp->next;
439 zp->next = sf->zones;
440 sf->zones = zp;
442 /* update the counter */
443 set_zone_counter(sflist, sf, zp);
444 return 0;
448 /* create a new zone */
449 if ((zp = sf_zone_new(sflist, sf)) == NULL)
450 return -ENOMEM;
452 zp->bank = map.map_bank;
453 zp->instr = map.map_instr;
454 zp->mapped = 1;
455 if (map.map_key >= 0) {
456 zp->v.low = map.map_key;
457 zp->v.high = map.map_key;
459 zp->v.start = map.src_instr;
460 zp->v.end = map.src_bank;
461 zp->v.fixkey = map.src_key;
462 zp->v.sf_id = sf->id;
464 add_preset(sflist, zp);
466 return 0;
470 /* remove the present instrument layers */
471 static int
472 remove_info(snd_sf_list_t *sflist, snd_soundfont_t *sf, int bank, int instr)
474 snd_sf_zone_t *prev, *next, *p;
475 int removed = 0;
477 prev = NULL;
478 for (p = sf->zones; p; p = next) {
479 next = p->next;
480 if (! p->mapped &&
481 p->bank == bank && p->instr == instr) {
482 /* remove this layer */
483 if (prev)
484 prev->next = next;
485 else
486 sf->zones = next;
487 removed++;
488 kfree(p);
489 } else
490 prev = p;
492 if (removed)
493 rebuild_presets(sflist);
494 return removed;
499 * Read an info record from the user buffer and save it on the current
500 * open soundfont.
502 static int
503 load_info(snd_sf_list_t *sflist, const void __user *data, long count)
505 snd_soundfont_t *sf;
506 snd_sf_zone_t *zone;
507 soundfont_voice_rec_hdr_t hdr;
508 int i;
510 /* patch must be opened */
511 if ((sf = sflist->currsf) == NULL)
512 return -EINVAL;
514 if (is_special_type(sf->type))
515 return -EINVAL;
517 if (count < (long)sizeof(hdr)) {
518 printk("Soundfont error: invalid patch zone length\n");
519 return -EINVAL;
521 if (copy_from_user((char*)&hdr, data, sizeof(hdr)))
522 return -EFAULT;
524 data += sizeof(hdr);
525 count -= sizeof(hdr);
527 if (hdr.nvoices <= 0 || hdr.nvoices >= 100) {
528 printk("Soundfont error: Illegal voice number %d\n", hdr.nvoices);
529 return -EINVAL;
532 if (count < (long)sizeof(soundfont_voice_info_t)*hdr.nvoices) {
533 printk("Soundfont Error: patch length(%ld) is smaller than nvoices(%d)\n",
534 count, hdr.nvoices);
535 return -EINVAL;
538 switch (hdr.write_mode) {
539 case SNDRV_SFNT_WR_EXCLUSIVE:
540 /* exclusive mode - if the instrument already exists,
541 return error */
542 for (zone = sf->zones; zone; zone = zone->next) {
543 if (!zone->mapped &&
544 zone->bank == hdr.bank &&
545 zone->instr == hdr.instr)
546 return -EINVAL;
548 break;
549 case SNDRV_SFNT_WR_REPLACE:
550 /* replace mode - remove the instrument if it already exists */
551 remove_info(sflist, sf, hdr.bank, hdr.instr);
552 break;
555 for (i = 0; i < hdr.nvoices; i++) {
556 snd_sf_zone_t tmpzone;
558 /* copy awe_voice_info parameters */
559 if (copy_from_user(&tmpzone.v, data, sizeof(tmpzone.v))) {
560 return -EFAULT;
563 data += sizeof(tmpzone.v);
564 count -= sizeof(tmpzone.v);
566 tmpzone.bank = hdr.bank;
567 tmpzone.instr = hdr.instr;
568 tmpzone.mapped = 0;
569 tmpzone.v.sf_id = sf->id;
570 if (tmpzone.v.mode & SNDRV_SFNT_MODE_INIT_PARM)
571 init_voice_parm(&tmpzone.v.parm);
573 /* create a new zone */
574 if ((zone = sf_zone_new(sflist, sf)) == NULL) {
575 return -ENOMEM;
578 /* copy the temporary data */
579 zone->bank = tmpzone.bank;
580 zone->instr = tmpzone.instr;
581 zone->v = tmpzone.v;
583 /* look up the sample */
584 zone->sample = set_sample(sf, &zone->v);
587 return 0;
591 /* initialize voice_info record */
592 static void
593 init_voice_info(soundfont_voice_info_t *avp)
595 memset(avp, 0, sizeof(*avp));
597 avp->root = 60;
598 avp->high = 127;
599 avp->velhigh = 127;
600 avp->fixkey = -1;
601 avp->fixvel = -1;
602 avp->fixpan = -1;
603 avp->pan = -1;
604 avp->amplitude = 127;
605 avp->scaleTuning = 100;
607 init_voice_parm(&avp->parm);
610 /* initialize voice_parm record:
611 * Env1/2: delay=0, attack=0, hold=0, sustain=0, decay=0, release=0.
612 * Vibrato and Tremolo effects are zero.
613 * Cutoff is maximum.
614 * Chorus and Reverb effects are zero.
616 static void
617 init_voice_parm(soundfont_voice_parm_t *pp)
619 memset(pp, 0, sizeof(*pp));
621 pp->moddelay = 0x8000;
622 pp->modatkhld = 0x7f7f;
623 pp->moddcysus = 0x7f7f;
624 pp->modrelease = 0x807f;
626 pp->voldelay = 0x8000;
627 pp->volatkhld = 0x7f7f;
628 pp->voldcysus = 0x7f7f;
629 pp->volrelease = 0x807f;
631 pp->lfo1delay = 0x8000;
632 pp->lfo2delay = 0x8000;
634 pp->cutoff = 0xff;
637 /* search the specified sample */
638 static snd_sf_sample_t *
639 set_sample(snd_soundfont_t *sf, soundfont_voice_info_t *avp)
641 snd_sf_sample_t *sample;
643 sample = find_sample(sf, avp->sample);
644 if (sample == NULL)
645 return NULL;
647 /* add in the actual sample offsets:
648 * The voice_info addresses define only the relative offset
649 * from sample pointers. Here we calculate the actual DRAM
650 * offset from sample pointers.
652 avp->start += sample->v.start;
653 avp->end += sample->v.end;
654 avp->loopstart += sample->v.loopstart;
655 avp->loopend += sample->v.loopend;
657 /* copy mode flags */
658 avp->sample_mode = sample->v.mode_flags;
660 return sample;
663 /* find the sample pointer with the given id in the soundfont */
664 static snd_sf_sample_t *
665 find_sample(snd_soundfont_t *sf, int sample_id)
667 snd_sf_sample_t *p;
669 if (sf == NULL)
670 return NULL;
672 for (p = sf->samples; p; p = p->next) {
673 if (p->v.sample == sample_id)
674 return p;
676 return NULL;
681 * Load sample information, this can include data to be loaded onto
682 * the soundcard. It can also just be a pointer into soundcard ROM.
683 * If there is data it will be written to the soundcard via the callback
684 * routine.
686 static int
687 load_data(snd_sf_list_t *sflist, const void __user *data, long count)
689 snd_soundfont_t *sf;
690 soundfont_sample_info_t sample_info;
691 snd_sf_sample_t *sp;
692 long off;
694 /* patch must be opened */
695 if ((sf = sflist->currsf) == NULL)
696 return -EINVAL;
698 if (is_special_type(sf->type))
699 return -EINVAL;
701 if (copy_from_user(&sample_info, data, sizeof(sample_info)))
702 return -EFAULT;
704 off = sizeof(sample_info);
706 if (sample_info.size != (count-off)/2)
707 return -EINVAL;
709 /* Check for dup */
710 if (find_sample(sf, sample_info.sample)) {
711 /* if shared sample, skip this data */
712 if (sf->type & SNDRV_SFNT_PAT_SHARED)
713 return 0;
714 return -EINVAL;
717 /* Allocate a new sample structure */
718 if ((sp = sf_sample_new(sflist, sf)) == NULL)
719 return -ENOMEM;
721 sp->v = sample_info;
722 sp->v.sf_id = sf->id;
723 sp->v.dummy = 0;
724 sp->v.truesize = sp->v.size;
727 * If there is wave data then load it.
729 if (sp->v.size > 0) {
730 int rc;
731 rc = sflist->callback.sample_new
732 (sflist->callback.private_data, sp, sflist->memhdr,
733 data + off, count - off);
734 if (rc < 0) {
735 sf_sample_delete(sflist, sf, sp);
736 return rc;
738 sflist->mem_used += sp->v.truesize;
741 return count;
745 /* log2_tbl[i] = log2(i+128) * 0x10000 */
746 static int log_tbl[129] = {
747 0x70000, 0x702df, 0x705b9, 0x7088e, 0x70b5d, 0x70e26, 0x710eb, 0x713aa,
748 0x71663, 0x71918, 0x71bc8, 0x71e72, 0x72118, 0x723b9, 0x72655, 0x728ed,
749 0x72b80, 0x72e0e, 0x73098, 0x7331d, 0x7359e, 0x7381b, 0x73a93, 0x73d08,
750 0x73f78, 0x741e4, 0x7444c, 0x746b0, 0x74910, 0x74b6c, 0x74dc4, 0x75019,
751 0x75269, 0x754b6, 0x75700, 0x75946, 0x75b88, 0x75dc7, 0x76002, 0x7623a,
752 0x7646e, 0x766a0, 0x768cd, 0x76af8, 0x76d1f, 0x76f43, 0x77164, 0x77382,
753 0x7759d, 0x777b4, 0x779c9, 0x77bdb, 0x77dea, 0x77ff5, 0x781fe, 0x78404,
754 0x78608, 0x78808, 0x78a06, 0x78c01, 0x78df9, 0x78fef, 0x791e2, 0x793d2,
755 0x795c0, 0x797ab, 0x79993, 0x79b79, 0x79d5d, 0x79f3e, 0x7a11d, 0x7a2f9,
756 0x7a4d3, 0x7a6ab, 0x7a880, 0x7aa53, 0x7ac24, 0x7adf2, 0x7afbe, 0x7b188,
757 0x7b350, 0x7b515, 0x7b6d8, 0x7b899, 0x7ba58, 0x7bc15, 0x7bdd0, 0x7bf89,
758 0x7c140, 0x7c2f5, 0x7c4a7, 0x7c658, 0x7c807, 0x7c9b3, 0x7cb5e, 0x7cd07,
759 0x7ceae, 0x7d053, 0x7d1f7, 0x7d398, 0x7d538, 0x7d6d6, 0x7d872, 0x7da0c,
760 0x7dba4, 0x7dd3b, 0x7ded0, 0x7e063, 0x7e1f4, 0x7e384, 0x7e512, 0x7e69f,
761 0x7e829, 0x7e9b3, 0x7eb3a, 0x7ecc0, 0x7ee44, 0x7efc7, 0x7f148, 0x7f2c8,
762 0x7f446, 0x7f5c2, 0x7f73d, 0x7f8b7, 0x7fa2f, 0x7fba5, 0x7fd1a, 0x7fe8d,
763 0x80000,
766 /* convert from linear to log value
768 * conversion: value = log2(amount / base) * ratio
770 * argument:
771 * amount = linear value (unsigned, 32bit max)
772 * offset = base offset (:= log2(base) * 0x10000)
773 * ratio = division ratio
777 snd_sf_linear_to_log(unsigned int amount, int offset, int ratio)
779 int v;
780 int s, low, bit;
782 if (amount < 2)
783 return 0;
784 for (bit = 0; ! (amount & 0x80000000L); bit++)
785 amount <<= 1;
786 s = (amount >> 24) & 0x7f;
787 low = (amount >> 16) & 0xff;
788 /* linear approxmimation by lower 8 bit */
789 v = (log_tbl[s + 1] * low + log_tbl[s] * (0x100 - low)) >> 8;
790 v -= offset;
791 v = (v * ratio) >> 16;
792 v += (24 - bit) * ratio;
793 return v;
796 #define OFFSET_MSEC 653117 /* base = 1000 */
797 #define OFFSET_ABSCENT 851781 /* base = 8176 */
798 #define OFFSET_SAMPLERATE 1011119 /* base = 44100 */
800 #define ABSCENT_RATIO 1200
801 #define TIMECENT_RATIO 1200
802 #define SAMPLERATE_RATIO 4096
805 * mHz to abscent
806 * conversion: abscent = log2(MHz / 8176) * 1200
808 static int
809 freq_to_note(int mhz)
811 return snd_sf_linear_to_log(mhz, OFFSET_ABSCENT, ABSCENT_RATIO);
814 /* convert Hz to AWE32 rate offset:
815 * sample pitch offset for the specified sample rate
816 * rate=44100 is no offset, each 4096 is 1 octave (twice).
817 * eg, when rate is 22050, this offset becomes -4096.
819 * conversion: offset = log2(Hz / 44100) * 4096
821 static int
822 calc_rate_offset(int hz)
824 return snd_sf_linear_to_log(hz, OFFSET_SAMPLERATE, SAMPLERATE_RATIO);
828 /* calculate GUS envelope time */
829 static int
830 calc_gus_envelope_time(int rate, int start, int end)
832 int r, p, t;
833 r = (3 - ((rate >> 6) & 3)) * 3;
834 p = rate & 0x3f;
835 t = end - start;
836 if (t < 0) t = -t;
837 if (13 > r)
838 t = t << (13 - r);
839 else
840 t = t >> (r - 13);
841 return (t * 10) / (p * 441);
844 /* convert envelope time parameter to soundfont parameters */
846 /* attack & decay/release time table (msec) */
847 static short attack_time_tbl[128] = {
848 32767, 32767, 5989, 4235, 2994, 2518, 2117, 1780, 1497, 1373, 1259, 1154, 1058, 970, 890, 816,
849 707, 691, 662, 634, 607, 581, 557, 533, 510, 489, 468, 448, 429, 411, 393, 377,
850 361, 345, 331, 317, 303, 290, 278, 266, 255, 244, 234, 224, 214, 205, 196, 188,
851 180, 172, 165, 158, 151, 145, 139, 133, 127, 122, 117, 112, 107, 102, 98, 94,
852 90, 86, 82, 79, 75, 72, 69, 66, 63, 61, 58, 56, 53, 51, 49, 47,
853 45, 43, 41, 39, 37, 36, 34, 33, 31, 30, 29, 28, 26, 25, 24, 23,
854 22, 21, 20, 19, 19, 18, 17, 16, 16, 15, 15, 14, 13, 13, 12, 12,
855 11, 11, 10, 10, 10, 9, 9, 8, 8, 8, 8, 7, 7, 7, 6, 0,
858 static short decay_time_tbl[128] = {
859 32767, 32767, 22614, 15990, 11307, 9508, 7995, 6723, 5653, 5184, 4754, 4359, 3997, 3665, 3361, 3082,
860 2828, 2765, 2648, 2535, 2428, 2325, 2226, 2132, 2042, 1955, 1872, 1793, 1717, 1644, 1574, 1507,
861 1443, 1382, 1324, 1267, 1214, 1162, 1113, 1066, 978, 936, 897, 859, 822, 787, 754, 722,
862 691, 662, 634, 607, 581, 557, 533, 510, 489, 468, 448, 429, 411, 393, 377, 361,
863 345, 331, 317, 303, 290, 278, 266, 255, 244, 234, 224, 214, 205, 196, 188, 180,
864 172, 165, 158, 151, 145, 139, 133, 127, 122, 117, 112, 107, 102, 98, 94, 90,
865 86, 82, 79, 75, 72, 69, 66, 63, 61, 58, 56, 53, 51, 49, 47, 45,
866 43, 41, 39, 37, 36, 34, 33, 31, 30, 29, 28, 26, 25, 24, 23, 22,
869 /* delay time = 0x8000 - msec/92 */
871 snd_sf_calc_parm_hold(int msec)
873 int val = (0x7f * 92 - msec) / 92;
874 if (val < 1) val = 1;
875 if (val >= 126) val = 126;
876 return val;
879 /* search an index for specified time from given time table */
880 static int
881 calc_parm_search(int msec, short *table)
883 int left = 1, right = 127, mid;
884 while (left < right) {
885 mid = (left + right) / 2;
886 if (msec < (int)table[mid])
887 left = mid + 1;
888 else
889 right = mid;
891 return left;
894 /* attack time: search from time table */
896 snd_sf_calc_parm_attack(int msec)
898 return calc_parm_search(msec, attack_time_tbl);
901 /* decay/release time: search from time table */
903 snd_sf_calc_parm_decay(int msec)
905 return calc_parm_search(msec, decay_time_tbl);
908 int snd_sf_vol_table[128] = {
909 255,111,95,86,79,74,70,66,63,61,58,56,54,52,50,49,
910 47,46,45,43,42,41,40,39,38,37,36,35,34,34,33,32,
911 31,31,30,29,29,28,27,27,26,26,25,24,24,23,23,22,
912 22,21,21,21,20,20,19,19,18,18,18,17,17,16,16,16,
913 15,15,15,14,14,14,13,13,13,12,12,12,11,11,11,10,
914 10,10,10,9,9,9,8,8,8,8,7,7,7,7,6,6,
915 6,6,5,5,5,5,5,4,4,4,4,3,3,3,3,3,
916 2,2,2,2,2,1,1,1,1,1,0,0,0,0,0,0,
920 #define calc_gus_sustain(val) (0x7f - snd_sf_vol_table[(val)/2])
921 #define calc_gus_attenuation(val) snd_sf_vol_table[(val)/2]
923 /* load GUS patch */
924 static int
925 load_guspatch(snd_sf_list_t *sflist, const char __user *data, long count, int client)
927 struct patch_info patch;
928 snd_soundfont_t *sf;
929 snd_sf_zone_t *zone;
930 snd_sf_sample_t *smp;
931 int note, sample_id;
932 int rc;
934 if (count < (long)sizeof(patch)) {
935 snd_printk("patch record too small %ld\n", count);
936 return -EINVAL;
938 if (copy_from_user(&patch, data, sizeof(patch)))
939 return -EFAULT;
941 count -= sizeof(patch);
942 data += sizeof(patch);
944 sf = newsf(sflist, SNDRV_SFNT_PAT_TYPE_GUS|SNDRV_SFNT_PAT_SHARED, NULL);
945 if (sf == NULL)
946 return -ENOMEM;
947 if ((smp = sf_sample_new(sflist, sf)) == NULL)
948 return -ENOMEM;
949 sample_id = sflist->sample_counter;
950 smp->v.sample = sample_id;
951 smp->v.start = 0;
952 smp->v.end = patch.len;
953 smp->v.loopstart = patch.loop_start;
954 smp->v.loopend = patch.loop_end;
955 smp->v.size = patch.len;
957 /* set up mode flags */
958 smp->v.mode_flags = 0;
959 if (!(patch.mode & WAVE_16_BITS))
960 smp->v.mode_flags |= SNDRV_SFNT_SAMPLE_8BITS;
961 if (patch.mode & WAVE_UNSIGNED)
962 smp->v.mode_flags |= SNDRV_SFNT_SAMPLE_UNSIGNED;
963 smp->v.mode_flags |= SNDRV_SFNT_SAMPLE_NO_BLANK;
964 if (!(patch.mode & (WAVE_LOOPING|WAVE_BIDIR_LOOP|WAVE_LOOP_BACK)))
965 smp->v.mode_flags |= SNDRV_SFNT_SAMPLE_SINGLESHOT;
966 if (patch.mode & WAVE_BIDIR_LOOP)
967 smp->v.mode_flags |= SNDRV_SFNT_SAMPLE_BIDIR_LOOP;
968 if (patch.mode & WAVE_LOOP_BACK)
969 smp->v.mode_flags |= SNDRV_SFNT_SAMPLE_REVERSE_LOOP;
971 if (patch.mode & WAVE_16_BITS) {
972 /* convert to word offsets */
973 smp->v.size /= 2;
974 smp->v.end /= 2;
975 smp->v.loopstart /= 2;
976 smp->v.loopend /= 2;
978 /*smp->v.loopend++;*/
980 smp->v.dummy = 0;
981 smp->v.truesize = 0;
982 smp->v.sf_id = sf->id;
984 /* set up voice info */
985 if ((zone = sf_zone_new(sflist, sf)) == NULL) {
986 sf_sample_delete(sflist, sf, smp);
987 return -ENOMEM;
991 * load wave data
993 if (sflist->callback.sample_new) {
994 rc = sflist->callback.sample_new
995 (sflist->callback.private_data, smp, sflist->memhdr, data, count);
996 if (rc < 0) {
997 sf_sample_delete(sflist, sf, smp);
998 return rc;
1000 /* memory offset is updated after */
1003 /* update the memory offset here */
1004 sflist->mem_used += smp->v.truesize;
1006 zone->v.sample = sample_id; /* the last sample */
1007 zone->v.rate_offset = calc_rate_offset(patch.base_freq);
1008 note = freq_to_note(patch.base_note);
1009 zone->v.root = note / 100;
1010 zone->v.tune = -(note % 100);
1011 zone->v.low = (freq_to_note(patch.low_note) + 99) / 100;
1012 zone->v.high = freq_to_note(patch.high_note) / 100;
1013 /* panning position; -128 - 127 => 0-127 */
1014 zone->v.pan = (patch.panning + 128) / 2;
1015 #if 0
1016 snd_printk("gus: basefrq=%d (ofs=%d) root=%d,tune=%d, range:%d-%d\n",
1017 (int)patch.base_freq, zone->v.rate_offset,
1018 zone->v.root, zone->v.tune, zone->v.low, zone->v.high);
1019 #endif
1021 /* detuning is ignored */
1022 /* 6points volume envelope */
1023 if (patch.mode & WAVE_ENVELOPES) {
1024 int attack, hold, decay, release;
1025 attack = calc_gus_envelope_time
1026 (patch.env_rate[0], 0, patch.env_offset[0]);
1027 hold = calc_gus_envelope_time
1028 (patch.env_rate[1], patch.env_offset[0],
1029 patch.env_offset[1]);
1030 decay = calc_gus_envelope_time
1031 (patch.env_rate[2], patch.env_offset[1],
1032 patch.env_offset[2]);
1033 release = calc_gus_envelope_time
1034 (patch.env_rate[3], patch.env_offset[1],
1035 patch.env_offset[4]);
1036 release += calc_gus_envelope_time
1037 (patch.env_rate[4], patch.env_offset[3],
1038 patch.env_offset[4]);
1039 release += calc_gus_envelope_time
1040 (patch.env_rate[5], patch.env_offset[4],
1041 patch.env_offset[5]);
1042 zone->v.parm.volatkhld =
1043 (snd_sf_calc_parm_hold(hold) << 8) |
1044 snd_sf_calc_parm_attack(attack);
1045 zone->v.parm.voldcysus = (calc_gus_sustain(patch.env_offset[2]) << 8) |
1046 snd_sf_calc_parm_decay(decay);
1047 zone->v.parm.volrelease = 0x8000 | snd_sf_calc_parm_decay(release);
1048 zone->v.attenuation = calc_gus_attenuation(patch.env_offset[0]);
1049 #if 0
1050 snd_printk("gus: atkhld=%x, dcysus=%x, volrel=%x, att=%d\n",
1051 zone->v.parm.volatkhld,
1052 zone->v.parm.voldcysus,
1053 zone->v.parm.volrelease,
1054 zone->v.attenuation);
1055 #endif
1058 /* fast release */
1059 if (patch.mode & WAVE_FAST_RELEASE) {
1060 zone->v.parm.volrelease = 0x807f;
1063 /* tremolo effect */
1064 if (patch.mode & WAVE_TREMOLO) {
1065 int rate = (patch.tremolo_rate * 1000 / 38) / 42;
1066 zone->v.parm.tremfrq = ((patch.tremolo_depth / 2) << 8) | rate;
1068 /* vibrato effect */
1069 if (patch.mode & WAVE_VIBRATO) {
1070 int rate = (patch.vibrato_rate * 1000 / 38) / 42;
1071 zone->v.parm.fm2frq2 = ((patch.vibrato_depth / 6) << 8) | rate;
1074 /* scale_freq, scale_factor, volume, and fractions not implemented */
1076 if (!(smp->v.mode_flags & SNDRV_SFNT_SAMPLE_SINGLESHOT))
1077 zone->v.mode = SNDRV_SFNT_MODE_LOOPING;
1078 else
1079 zone->v.mode = 0;
1081 /* append to the tail of the list */
1082 /*zone->bank = ctrls[AWE_MD_GUS_BANK];*/
1083 zone->bank = 0;
1084 zone->instr = patch.instr_no;
1085 zone->mapped = 0;
1086 zone->v.sf_id = sf->id;
1088 zone->sample = set_sample(sf, &zone->v);
1090 /* rebuild preset now */
1091 add_preset(sflist, zone);
1093 return 0;
1096 /* load GUS patch */
1098 snd_soundfont_load_guspatch(snd_sf_list_t *sflist, const char __user *data,
1099 long count, int client)
1101 int rc;
1102 lock_preset(sflist);
1103 rc = load_guspatch(sflist, data, count, client);
1104 unlock_preset(sflist);
1105 return rc;
1110 * Rebuild the preset table. This is like a hash table in that it allows
1111 * quick access to the zone information. For each preset there are zone
1112 * structures linked by next_instr and by next_zone. Former is the whole
1113 * link for this preset, and latter is the link for zone (i.e. instrument/
1114 * bank/key combination).
1116 static void
1117 rebuild_presets(snd_sf_list_t *sflist)
1119 snd_soundfont_t *sf;
1120 snd_sf_zone_t *cur;
1122 /* clear preset table */
1123 memset(sflist->presets, 0, sizeof(sflist->presets));
1125 /* search all fonts and insert each font */
1126 for (sf = sflist->fonts; sf; sf = sf->next) {
1127 for (cur = sf->zones; cur; cur = cur->next) {
1128 if (! cur->mapped && cur->sample == NULL) {
1129 /* try again to search the corresponding sample */
1130 cur->sample = set_sample(sf, &cur->v);
1131 if (cur->sample == NULL)
1132 continue;
1135 add_preset(sflist, cur);
1142 * add the given zone to preset table
1144 static void
1145 add_preset(snd_sf_list_t *sflist, snd_sf_zone_t *cur)
1147 snd_sf_zone_t *zone;
1148 int index;
1150 zone = search_first_zone(sflist, cur->bank, cur->instr, cur->v.low);
1151 if (zone && zone->v.sf_id != cur->v.sf_id) {
1152 /* different instrument was already defined */
1153 snd_sf_zone_t *p;
1154 /* compare the allocated time */
1155 for (p = zone; p; p = p->next_zone) {
1156 if (p->counter > cur->counter)
1157 /* the current is older.. skipped */
1158 return;
1160 /* remove old zones */
1161 delete_preset(sflist, zone);
1162 zone = NULL; /* do not forget to clear this! */
1165 /* prepend this zone */
1166 if ((index = get_index(cur->bank, cur->instr, cur->v.low)) < 0)
1167 return;
1168 cur->next_zone = zone; /* zone link */
1169 cur->next_instr = sflist->presets[index]; /* preset table link */
1170 sflist->presets[index] = cur;
1174 * delete the given zones from preset_table
1176 static void
1177 delete_preset(snd_sf_list_t *sflist, snd_sf_zone_t *zp)
1179 int index;
1180 snd_sf_zone_t *p;
1182 if ((index = get_index(zp->bank, zp->instr, zp->v.low)) < 0)
1183 return;
1184 for (p = sflist->presets[index]; p; p = p->next_instr) {
1185 while (p->next_instr == zp) {
1186 p->next_instr = zp->next_instr;
1187 zp = zp->next_zone;
1188 if (zp == NULL)
1189 return;
1196 * Search matching zones from preset table.
1197 * The note can be rewritten by preset mapping (alias).
1198 * The found zones are stored on 'table' array. max_layers defines
1199 * the maximum number of elements in this array.
1200 * This function returns the number of found zones. 0 if not found.
1203 snd_soundfont_search_zone(snd_sf_list_t *sflist, int *notep, int vel,
1204 int preset, int bank,
1205 int def_preset, int def_bank,
1206 snd_sf_zone_t **table, int max_layers)
1208 int nvoices;
1209 unsigned long flags;
1211 /* this function is supposed to be called atomically,
1212 * so we check the lock. if it's busy, just returns 0 to
1213 * tell the caller the busy state
1215 spin_lock_irqsave(&sflist->lock, flags);
1216 if (sflist->presets_locked) {
1217 spin_unlock_irqrestore(&sflist->lock, flags);
1218 return 0;
1220 nvoices = search_zones(sflist, notep, vel, preset, bank, table, max_layers, 0);
1221 if (! nvoices) {
1222 if (preset != def_preset || bank != def_bank)
1223 nvoices = search_zones(sflist, notep, vel, def_preset, def_bank, table, max_layers, 0);
1225 spin_unlock_irqrestore(&sflist->lock, flags);
1226 return nvoices;
1231 * search the first matching zone
1233 static snd_sf_zone_t *
1234 search_first_zone(snd_sf_list_t *sflist, int bank, int preset, int key)
1236 int index;
1237 snd_sf_zone_t *zp;
1239 if ((index = get_index(bank, preset, key)) < 0)
1240 return NULL;
1241 for (zp = sflist->presets[index]; zp; zp = zp->next_instr) {
1242 if (zp->instr == preset && zp->bank == bank)
1243 return zp;
1245 return NULL;
1250 * search matching zones from sflist. can be called recursively.
1252 static int
1253 search_zones(snd_sf_list_t *sflist, int *notep, int vel, int preset, int bank, snd_sf_zone_t **table, int max_layers, int level)
1255 snd_sf_zone_t *zp;
1256 int nvoices;
1258 zp = search_first_zone(sflist, bank, preset, *notep);
1259 nvoices = 0;
1260 for (; zp; zp = zp->next_zone) {
1261 if (*notep >= zp->v.low && *notep <= zp->v.high &&
1262 vel >= zp->v.vellow && vel <= zp->v.velhigh) {
1263 if (zp->mapped) {
1264 /* search preset mapping (aliasing) */
1265 int key = zp->v.fixkey;
1266 preset = zp->v.start;
1267 bank = zp->v.end;
1269 if (level > 5) /* too deep alias level */
1270 return 0;
1271 if (key < 0)
1272 key = *notep;
1273 nvoices = search_zones(sflist, &key, vel,
1274 preset, bank, table,
1275 max_layers, level + 1);
1276 if (nvoices > 0)
1277 *notep = key;
1278 break;
1280 table[nvoices++] = zp;
1281 if (nvoices >= max_layers)
1282 break;
1286 return nvoices;
1290 /* calculate the index of preset table:
1291 * drums are mapped from 128 to 255 according to its note key.
1292 * other instruments are mapped from 0 to 127.
1293 * if the index is out of range, return -1.
1295 static int
1296 get_index(int bank, int instr, int key)
1298 int index;
1299 if (SF_IS_DRUM_BANK(bank))
1300 index = key + SF_MAX_INSTRUMENTS;
1301 else
1302 index = instr;
1303 index = index % SF_MAX_PRESETS;
1304 if (index < 0)
1305 return -1;
1306 return index;
1310 * Initialise the sflist structure.
1312 static void
1313 snd_sf_init(snd_sf_list_t *sflist)
1315 memset(sflist->presets, 0, sizeof(sflist->presets));
1317 sflist->mem_used = 0;
1318 sflist->currsf = NULL;
1319 sflist->open_client = -1;
1320 sflist->fonts = NULL;
1321 sflist->fonts_size = 0;
1322 sflist->zone_counter = 0;
1323 sflist->sample_counter = 0;
1324 sflist->zone_locked = 0;
1325 sflist->sample_locked = 0;
1329 * Release all list records
1331 static void
1332 snd_sf_clear(snd_sf_list_t *sflist)
1334 snd_soundfont_t *sf, *nextsf;
1335 snd_sf_zone_t *zp, *nextzp;
1336 snd_sf_sample_t *sp, *nextsp;
1338 for (sf = sflist->fonts; sf; sf = nextsf) {
1339 nextsf = sf->next;
1340 for (zp = sf->zones; zp; zp = nextzp) {
1341 nextzp = zp->next;
1342 kfree(zp);
1344 for (sp = sf->samples; sp; sp = nextsp) {
1345 nextsp = sp->next;
1346 if (sflist->callback.sample_free)
1347 sflist->callback.sample_free(sflist->callback.private_data, sp, sflist->memhdr);
1348 kfree(sp);
1350 kfree(sf);
1353 snd_sf_init(sflist);
1358 * Create a new sflist structure
1360 snd_sf_list_t *
1361 snd_sf_new(snd_sf_callback_t *callback, snd_util_memhdr_t *hdr)
1363 snd_sf_list_t *sflist;
1365 if ((sflist = kcalloc(1, sizeof(*sflist), GFP_KERNEL)) == NULL)
1366 return NULL;
1368 init_MUTEX(&sflist->presets_mutex);
1369 spin_lock_init(&sflist->lock);
1370 sflist->memhdr = hdr;
1372 if (callback)
1373 sflist->callback = *callback;
1375 snd_sf_init(sflist);
1376 return sflist;
1381 * Free everything allocated off the sflist structure.
1383 void
1384 snd_sf_free(snd_sf_list_t *sflist)
1386 if (sflist == NULL)
1387 return;
1389 lock_preset(sflist);
1390 if (sflist->callback.sample_reset)
1391 sflist->callback.sample_reset(sflist->callback.private_data);
1392 snd_sf_clear(sflist);
1393 unlock_preset(sflist);
1395 kfree(sflist);
1399 * Remove all samples
1400 * The soundcard should be silet before calling this function.
1403 snd_soundfont_remove_samples(snd_sf_list_t *sflist)
1405 lock_preset(sflist);
1406 if (sflist->callback.sample_reset)
1407 sflist->callback.sample_reset(sflist->callback.private_data);
1408 snd_sf_clear(sflist);
1409 unlock_preset(sflist);
1411 return 0;
1415 * Remove unlocked samples.
1416 * The soundcard should be silent before calling this function.
1419 snd_soundfont_remove_unlocked(snd_sf_list_t *sflist)
1421 snd_soundfont_t *sf;
1422 snd_sf_zone_t *zp, *nextzp;
1423 snd_sf_sample_t *sp, *nextsp;
1425 lock_preset(sflist);
1427 if (sflist->callback.sample_reset)
1428 sflist->callback.sample_reset(sflist->callback.private_data);
1430 /* to be sure */
1431 memset(sflist->presets, 0, sizeof(sflist->presets));
1433 for (sf = sflist->fonts; sf; sf = sf->next) {
1434 for (zp = sf->zones; zp; zp = nextzp) {
1435 if (zp->counter < sflist->zone_locked)
1436 break;
1437 nextzp = zp->next;
1438 sf->zones = nextzp;
1439 kfree(zp);
1442 for (sp = sf->samples; sp; sp = nextsp) {
1443 if (sp->counter < sflist->sample_locked)
1444 break;
1445 nextsp = sp->next;
1446 sf->samples = nextsp;
1447 sflist->mem_used -= sp->v.truesize;
1448 if (sflist->callback.sample_free)
1449 sflist->callback.sample_free(sflist->callback.private_data, sp, sflist->memhdr);
1450 kfree(sp);
1454 sflist->zone_counter = sflist->zone_locked;
1455 sflist->sample_counter = sflist->sample_locked;
1457 rebuild_presets(sflist);
1459 unlock_preset(sflist);
1460 return 0;