2 * IWFFFF - AMD InterWave (tm) - Instrument routines
3 * Copyright (c) 1999 by Jaroslav Kysela <perex@perex.cz>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #include <sound/driver.h>
22 #include <linux/init.h>
23 #include <linux/slab.h>
24 #include <sound/core.h>
25 #include <sound/ainstr_iw.h>
26 #include <sound/initval.h>
27 #include <asm/uaccess.h>
29 MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
30 MODULE_DESCRIPTION("Advanced Linux Sound Architecture IWFFFF support.");
31 MODULE_LICENSE("GPL");
33 static unsigned int snd_seq_iwffff_size(unsigned int size
, unsigned int format
)
35 unsigned int result
= size
;
37 if (format
& IWFFFF_WAVE_16BIT
)
39 if (format
& IWFFFF_WAVE_STEREO
)
44 static void snd_seq_iwffff_copy_lfo_from_stream(struct iwffff_lfo
*fp
,
45 struct iwffff_xlfo
*fx
)
47 fp
->freq
= le16_to_cpu(fx
->freq
);
48 fp
->depth
= le16_to_cpu(fx
->depth
);
49 fp
->sweep
= le16_to_cpu(fx
->sweep
);
50 fp
->shape
= fx
->shape
;
51 fp
->delay
= fx
->delay
;
54 static int snd_seq_iwffff_copy_env_from_stream(__u32 req_stype
,
55 struct iwffff_layer
*lp
,
56 struct iwffff_env
*ep
,
57 struct iwffff_xenv
*ex
,
63 struct iwffff_env_record
*rp
, *rp_last
;
64 struct iwffff_xenv_record rx
;
65 struct iwffff_env_point
*pp
;
66 struct iwffff_xenv_point px
;
69 ep
->flags
= ex
->flags
;
71 ep
->index
= ex
->index
;
74 if (*len
< (long)sizeof(__u32
))
76 if (copy_from_user(&stype
, *data
, sizeof(stype
)))
78 if (stype
== IWFFFF_STRU_WAVE
)
80 if (req_stype
!= stype
) {
81 if (stype
== IWFFFF_STRU_ENV_RECP
||
82 stype
== IWFFFF_STRU_ENV_RECV
)
85 if (*len
< (long)sizeof(rx
))
87 if (copy_from_user(&rx
, *data
, sizeof(rx
)))
91 points_size
= (le16_to_cpu(rx
.nattack
) + le16_to_cpu(rx
.nrelease
)) * 2 * sizeof(__u16
);
92 if (points_size
> *len
)
94 rp
= kzalloc(sizeof(*rp
) + points_size
, gfp_mask
);
97 rp
->nattack
= le16_to_cpu(rx
.nattack
);
98 rp
->nrelease
= le16_to_cpu(rx
.nrelease
);
99 rp
->sustain_offset
= le16_to_cpu(rx
.sustain_offset
);
100 rp
->sustain_rate
= le16_to_cpu(rx
.sustain_rate
);
101 rp
->release_rate
= le16_to_cpu(rx
.release_rate
);
102 rp
->hirange
= rx
.hirange
;
103 pp
= (struct iwffff_env_point
*)(rp
+ 1);
104 for (idx
= 0; idx
< rp
->nattack
+ rp
->nrelease
; idx
++) {
105 if (copy_from_user(&px
, *data
, sizeof(px
)))
109 pp
->offset
= le16_to_cpu(px
.offset
);
110 pp
->rate
= le16_to_cpu(px
.rate
);
112 if (ep
->record
== NULL
) {
122 static int snd_seq_iwffff_copy_wave_from_stream(struct snd_iwffff_ops
*ops
,
123 struct iwffff_layer
*lp
,
128 struct iwffff_wave
*wp
, *prev
;
129 struct iwffff_xwave xp
;
132 unsigned int real_size
;
134 gfp_mask
= atomic
? GFP_ATOMIC
: GFP_KERNEL
;
135 if (*len
< (long)sizeof(xp
))
137 if (copy_from_user(&xp
, *data
, sizeof(xp
)))
141 wp
= kzalloc(sizeof(*wp
), gfp_mask
);
144 wp
->share_id
[0] = le32_to_cpu(xp
.share_id
[0]);
145 wp
->share_id
[1] = le32_to_cpu(xp
.share_id
[1]);
146 wp
->share_id
[2] = le32_to_cpu(xp
.share_id
[2]);
147 wp
->share_id
[3] = le32_to_cpu(xp
.share_id
[3]);
148 wp
->format
= le32_to_cpu(xp
.format
);
149 wp
->address
.memory
= le32_to_cpu(xp
.offset
);
150 wp
->size
= le32_to_cpu(xp
.size
);
151 wp
->start
= le32_to_cpu(xp
.start
);
152 wp
->loop_start
= le32_to_cpu(xp
.loop_start
);
153 wp
->loop_end
= le32_to_cpu(xp
.loop_end
);
154 wp
->loop_repeat
= le16_to_cpu(xp
.loop_repeat
);
155 wp
->sample_ratio
= le32_to_cpu(xp
.sample_ratio
);
156 wp
->attenuation
= xp
.attenuation
;
157 wp
->low_note
= xp
.low_note
;
158 wp
->high_note
= xp
.high_note
;
159 real_size
= snd_seq_iwffff_size(wp
->size
, wp
->format
);
160 if (!(wp
->format
& IWFFFF_WAVE_ROM
)) {
161 if ((long)real_size
> *len
) {
166 if (ops
->put_sample
) {
167 err
= ops
->put_sample(ops
->private_data
, wp
,
168 *data
, real_size
, atomic
);
174 if (!(wp
->format
& IWFFFF_WAVE_ROM
)) {
180 while (prev
->next
) prev
= prev
->next
;
188 static void snd_seq_iwffff_env_free(struct snd_iwffff_ops
*ops
,
189 struct iwffff_env
*env
,
192 struct iwffff_env_record
*rec
;
194 while ((rec
= env
->record
) != NULL
) {
195 env
->record
= rec
->next
;
200 static void snd_seq_iwffff_wave_free(struct snd_iwffff_ops
*ops
,
201 struct iwffff_wave
*wave
,
204 if (ops
->remove_sample
)
205 ops
->remove_sample(ops
->private_data
, wave
, atomic
);
209 static void snd_seq_iwffff_instr_free(struct snd_iwffff_ops
*ops
,
210 struct iwffff_instrument
*ip
,
213 struct iwffff_layer
*layer
;
214 struct iwffff_wave
*wave
;
216 while ((layer
= ip
->layer
) != NULL
) {
217 ip
->layer
= layer
->next
;
218 snd_seq_iwffff_env_free(ops
, &layer
->penv
, atomic
);
219 snd_seq_iwffff_env_free(ops
, &layer
->venv
, atomic
);
220 while ((wave
= layer
->wave
) != NULL
) {
221 layer
->wave
= wave
->next
;
222 snd_seq_iwffff_wave_free(ops
, wave
, atomic
);
228 static int snd_seq_iwffff_put(void *private_data
, struct snd_seq_kinstr
*instr
,
229 char __user
*instr_data
, long len
, int atomic
,
232 struct snd_iwffff_ops
*ops
= private_data
;
233 struct iwffff_instrument
*ip
;
234 struct iwffff_xinstrument ix
;
235 struct iwffff_layer
*lp
, *prev_lp
;
236 struct iwffff_xlayer lx
;
240 if (cmd
!= SNDRV_SEQ_INSTR_PUT_CMD_CREATE
)
242 gfp_mask
= atomic
? GFP_ATOMIC
: GFP_KERNEL
;
243 /* copy instrument data */
244 if (len
< (long)sizeof(ix
))
246 if (copy_from_user(&ix
, instr_data
, sizeof(ix
)))
248 if (ix
.stype
!= IWFFFF_STRU_INSTR
)
250 instr_data
+= sizeof(ix
);
252 ip
= (struct iwffff_instrument
*)KINSTR_DATA(instr
);
253 ip
->exclusion
= le16_to_cpu(ix
.exclusion
);
254 ip
->layer_type
= le16_to_cpu(ix
.layer_type
);
255 ip
->exclusion_group
= le16_to_cpu(ix
.exclusion_group
);
256 ip
->effect1
= ix
.effect1
;
257 ip
->effect1_depth
= ix
.effect1_depth
;
258 ip
->effect2
= ix
.effect2
;
259 ip
->effect2_depth
= ix
.effect2_depth
;
263 if (len
< (long)sizeof(struct iwffff_xlayer
)) {
264 snd_seq_iwffff_instr_free(ops
, ip
, atomic
);
267 if (copy_from_user(&lx
, instr_data
, sizeof(lx
)))
269 instr_data
+= sizeof(lx
);
271 if (lx
.stype
!= IWFFFF_STRU_LAYER
) {
272 snd_seq_iwffff_instr_free(ops
, ip
, atomic
);
275 lp
= kzalloc(sizeof(*lp
), gfp_mask
);
277 snd_seq_iwffff_instr_free(ops
, ip
, atomic
);
286 lp
->flags
= lx
.flags
;
287 lp
->velocity_mode
= lx
.velocity_mode
;
288 lp
->layer_event
= lx
.layer_event
;
289 lp
->low_range
= lx
.low_range
;
290 lp
->high_range
= lx
.high_range
;
292 lp
->pan_freq_scale
= lx
.pan_freq_scale
;
293 lp
->attenuation
= lx
.attenuation
;
294 snd_seq_iwffff_copy_lfo_from_stream(&lp
->tremolo
, &lx
.tremolo
);
295 snd_seq_iwffff_copy_lfo_from_stream(&lp
->vibrato
, &lx
.vibrato
);
296 lp
->freq_scale
= le16_to_cpu(lx
.freq_scale
);
297 lp
->freq_center
= lx
.freq_center
;
298 err
= snd_seq_iwffff_copy_env_from_stream(IWFFFF_STRU_ENV_RECP
,
304 snd_seq_iwffff_instr_free(ops
, ip
, atomic
);
307 err
= snd_seq_iwffff_copy_env_from_stream(IWFFFF_STRU_ENV_RECV
,
313 snd_seq_iwffff_instr_free(ops
, ip
, atomic
);
316 while (len
> (long)sizeof(__u32
)) {
319 if (copy_from_user(&stype
, instr_data
, sizeof(stype
)))
321 if (stype
!= IWFFFF_STRU_WAVE
)
323 err
= snd_seq_iwffff_copy_wave_from_stream(ops
,
329 snd_seq_iwffff_instr_free(ops
, ip
, atomic
);
337 static void snd_seq_iwffff_copy_lfo_to_stream(struct iwffff_xlfo
*fx
,
338 struct iwffff_lfo
*fp
)
340 fx
->freq
= cpu_to_le16(fp
->freq
);
341 fx
->depth
= cpu_to_le16(fp
->depth
);
342 fx
->sweep
= cpu_to_le16(fp
->sweep
);
343 fp
->shape
= fx
->shape
;
344 fp
->delay
= fx
->delay
;
347 static int snd_seq_iwffff_copy_env_to_stream(__u32 req_stype
,
348 struct iwffff_layer
*lp
,
349 struct iwffff_xenv
*ex
,
350 struct iwffff_env
*ep
,
354 struct iwffff_env_record
*rp
;
355 struct iwffff_xenv_record rx
;
356 struct iwffff_env_point
*pp
;
357 struct iwffff_xenv_point px
;
358 int points_size
, idx
;
360 ex
->flags
= ep
->flags
;
362 ex
->index
= ep
->index
;
363 for (rp
= ep
->record
; rp
; rp
= rp
->next
) {
364 if (*len
< (long)sizeof(rx
))
366 memset(&rx
, 0, sizeof(rx
));
367 rx
.stype
= req_stype
;
368 rx
.nattack
= cpu_to_le16(rp
->nattack
);
369 rx
.nrelease
= cpu_to_le16(rp
->nrelease
);
370 rx
.sustain_offset
= cpu_to_le16(rp
->sustain_offset
);
371 rx
.sustain_rate
= cpu_to_le16(rp
->sustain_rate
);
372 rx
.release_rate
= cpu_to_le16(rp
->release_rate
);
373 rx
.hirange
= cpu_to_le16(rp
->hirange
);
374 if (copy_to_user(*data
, &rx
, sizeof(rx
)))
378 points_size
= (rp
->nattack
+ rp
->nrelease
) * 2 * sizeof(__u16
);
379 if (*len
< points_size
)
381 pp
= (struct iwffff_env_point
*)(rp
+ 1);
382 for (idx
= 0; idx
< rp
->nattack
+ rp
->nrelease
; idx
++) {
383 px
.offset
= cpu_to_le16(pp
->offset
);
384 px
.rate
= cpu_to_le16(pp
->rate
);
385 if (copy_to_user(*data
, &px
, sizeof(px
)))
394 static int snd_seq_iwffff_copy_wave_to_stream(struct snd_iwffff_ops
*ops
,
395 struct iwffff_layer
*lp
,
400 struct iwffff_wave
*wp
;
401 struct iwffff_xwave xp
;
403 unsigned int real_size
;
405 for (wp
= lp
->wave
; wp
; wp
= wp
->next
) {
406 if (*len
< (long)sizeof(xp
))
408 memset(&xp
, 0, sizeof(xp
));
409 xp
.stype
= IWFFFF_STRU_WAVE
;
410 xp
.share_id
[0] = cpu_to_le32(wp
->share_id
[0]);
411 xp
.share_id
[1] = cpu_to_le32(wp
->share_id
[1]);
412 xp
.share_id
[2] = cpu_to_le32(wp
->share_id
[2]);
413 xp
.share_id
[3] = cpu_to_le32(wp
->share_id
[3]);
414 xp
.format
= cpu_to_le32(wp
->format
);
415 if (wp
->format
& IWFFFF_WAVE_ROM
)
416 xp
.offset
= cpu_to_le32(wp
->address
.memory
);
417 xp
.size
= cpu_to_le32(wp
->size
);
418 xp
.start
= cpu_to_le32(wp
->start
);
419 xp
.loop_start
= cpu_to_le32(wp
->loop_start
);
420 xp
.loop_end
= cpu_to_le32(wp
->loop_end
);
421 xp
.loop_repeat
= cpu_to_le32(wp
->loop_repeat
);
422 xp
.sample_ratio
= cpu_to_le32(wp
->sample_ratio
);
423 xp
.attenuation
= wp
->attenuation
;
424 xp
.low_note
= wp
->low_note
;
425 xp
.high_note
= wp
->high_note
;
426 if (copy_to_user(*data
, &xp
, sizeof(xp
)))
430 real_size
= snd_seq_iwffff_size(wp
->size
, wp
->format
);
431 if (!(wp
->format
& IWFFFF_WAVE_ROM
)) {
432 if (*len
< (long)real_size
)
435 if (ops
->get_sample
) {
436 err
= ops
->get_sample(ops
->private_data
, wp
,
437 *data
, real_size
, atomic
);
441 if (!(wp
->format
& IWFFFF_WAVE_ROM
)) {
449 static int snd_seq_iwffff_get(void *private_data
, struct snd_seq_kinstr
*instr
,
450 char __user
*instr_data
, long len
, int atomic
, int cmd
)
452 struct snd_iwffff_ops
*ops
= private_data
;
453 struct iwffff_instrument
*ip
;
454 struct iwffff_xinstrument ix
;
455 struct iwffff_layer
*lp
;
456 struct iwffff_xlayer lx
;
457 char __user
*layer_instr_data
;
460 if (cmd
!= SNDRV_SEQ_INSTR_GET_CMD_FULL
)
462 if (len
< (long)sizeof(ix
))
464 memset(&ix
, 0, sizeof(ix
));
465 ip
= (struct iwffff_instrument
*)KINSTR_DATA(instr
);
466 ix
.stype
= IWFFFF_STRU_INSTR
;
467 ix
.exclusion
= cpu_to_le16(ip
->exclusion
);
468 ix
.layer_type
= cpu_to_le16(ip
->layer_type
);
469 ix
.exclusion_group
= cpu_to_le16(ip
->exclusion_group
);
470 ix
.effect1
= cpu_to_le16(ip
->effect1
);
471 ix
.effect1_depth
= cpu_to_le16(ip
->effect1_depth
);
472 ix
.effect2
= ip
->effect2
;
473 ix
.effect2_depth
= ip
->effect2_depth
;
474 if (copy_to_user(instr_data
, &ix
, sizeof(ix
)))
476 instr_data
+= sizeof(ix
);
478 for (lp
= ip
->layer
; lp
; lp
= lp
->next
) {
479 if (len
< (long)sizeof(lx
))
481 memset(&lx
, 0, sizeof(lx
));
482 lx
.stype
= IWFFFF_STRU_LAYER
;
483 lx
.flags
= lp
->flags
;
484 lx
.velocity_mode
= lp
->velocity_mode
;
485 lx
.layer_event
= lp
->layer_event
;
486 lx
.low_range
= lp
->low_range
;
487 lx
.high_range
= lp
->high_range
;
489 lx
.pan_freq_scale
= lp
->pan_freq_scale
;
490 lx
.attenuation
= lp
->attenuation
;
491 snd_seq_iwffff_copy_lfo_to_stream(&lx
.tremolo
, &lp
->tremolo
);
492 snd_seq_iwffff_copy_lfo_to_stream(&lx
.vibrato
, &lp
->vibrato
);
493 layer_instr_data
= instr_data
;
494 instr_data
+= sizeof(lx
);
496 err
= snd_seq_iwffff_copy_env_to_stream(IWFFFF_STRU_ENV_RECP
,
502 err
= snd_seq_iwffff_copy_env_to_stream(IWFFFF_STRU_ENV_RECV
,
508 /* layer structure updating is now finished */
509 if (copy_to_user(layer_instr_data
, &lx
, sizeof(lx
)))
511 err
= snd_seq_iwffff_copy_wave_to_stream(ops
,
522 static long snd_seq_iwffff_env_size_in_stream(struct iwffff_env
*ep
)
525 struct iwffff_env_record
*rp
;
527 for (rp
= ep
->record
; rp
; rp
= rp
->next
) {
528 result
+= sizeof(struct iwffff_xenv_record
);
529 result
+= (rp
->nattack
+ rp
->nrelease
) * 2 * sizeof(__u16
);
534 static long snd_seq_iwffff_wave_size_in_stream(struct iwffff_layer
*lp
)
537 struct iwffff_wave
*wp
;
539 for (wp
= lp
->wave
; wp
; wp
= wp
->next
) {
540 result
+= sizeof(struct iwffff_xwave
);
541 if (!(wp
->format
& IWFFFF_WAVE_ROM
))
547 static int snd_seq_iwffff_get_size(void *private_data
, struct snd_seq_kinstr
*instr
,
551 struct iwffff_instrument
*ip
;
552 struct iwffff_layer
*lp
;
555 ip
= (struct iwffff_instrument
*)KINSTR_DATA(instr
);
556 result
= sizeof(struct iwffff_xinstrument
);
557 for (lp
= ip
->layer
; lp
; lp
= lp
->next
) {
558 result
+= sizeof(struct iwffff_xlayer
);
559 result
+= snd_seq_iwffff_env_size_in_stream(&lp
->penv
);
560 result
+= snd_seq_iwffff_env_size_in_stream(&lp
->venv
);
561 result
+= snd_seq_iwffff_wave_size_in_stream(lp
);
567 static int snd_seq_iwffff_remove(void *private_data
,
568 struct snd_seq_kinstr
*instr
,
571 struct snd_iwffff_ops
*ops
= private_data
;
572 struct iwffff_instrument
*ip
;
574 ip
= (struct iwffff_instrument
*)KINSTR_DATA(instr
);
575 snd_seq_iwffff_instr_free(ops
, ip
, atomic
);
579 static void snd_seq_iwffff_notify(void *private_data
,
580 struct snd_seq_kinstr
*instr
,
583 struct snd_iwffff_ops
*ops
= private_data
;
586 ops
->notify(ops
->private_data
, instr
, what
);
589 int snd_seq_iwffff_init(struct snd_iwffff_ops
*ops
,
591 struct snd_seq_kinstr_ops
*next
)
593 memset(ops
, 0, sizeof(*ops
));
594 ops
->private_data
= private_data
;
595 ops
->kops
.private_data
= ops
;
596 ops
->kops
.add_len
= sizeof(struct iwffff_instrument
);
597 ops
->kops
.instr_type
= SNDRV_SEQ_INSTR_ID_INTERWAVE
;
598 ops
->kops
.put
= snd_seq_iwffff_put
;
599 ops
->kops
.get
= snd_seq_iwffff_get
;
600 ops
->kops
.get_size
= snd_seq_iwffff_get_size
;
601 ops
->kops
.remove
= snd_seq_iwffff_remove
;
602 ops
->kops
.notify
= snd_seq_iwffff_notify
;
603 ops
->kops
.next
= next
;
611 static int __init
alsa_ainstr_iw_init(void)
616 static void __exit
alsa_ainstr_iw_exit(void)
620 module_init(alsa_ainstr_iw_init
)
621 module_exit(alsa_ainstr_iw_exit
)
623 EXPORT_SYMBOL(snd_seq_iwffff_init
);