diff options
26 files changed, 5 insertions, 5603 deletions
diff --git a/include/sound/ainstr_fm.h b/include/sound/ainstr_fm.h deleted file mode 100644 index c4afb1f121fe..000000000000 --- a/include/sound/ainstr_fm.h +++ /dev/null | |||
| @@ -1,134 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Advanced Linux Sound Architecture | ||
| 3 | * | ||
| 4 | * FM (OPL2/3) Instrument Format | ||
| 5 | * Copyright (c) 2000 Uros Bizjak <uros@kss-loka.si> | ||
| 6 | * | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify | ||
| 9 | * it under the terms of the GNU General Public License as published by | ||
| 10 | * the Free Software Foundation; either version 2 of the License, or | ||
| 11 | * (at your option) any later version. | ||
| 12 | * | ||
| 13 | * This program is distributed in the hope that it will be useful, | ||
| 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 16 | * GNU General Public License for more details. | ||
| 17 | * | ||
| 18 | * You should have received a copy of the GNU General Public License | ||
| 19 | * along with this program; if not, write to the Free Software | ||
| 20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 21 | * | ||
| 22 | */ | ||
| 23 | |||
| 24 | #ifndef __SOUND_AINSTR_FM_H | ||
| 25 | #define __SOUND_AINSTR_FM_H | ||
| 26 | |||
| 27 | #ifndef __KERNEL__ | ||
| 28 | #include <asm/types.h> | ||
| 29 | #include <asm/byteorder.h> | ||
| 30 | #endif | ||
| 31 | |||
| 32 | /* | ||
| 33 | * share types (share ID 1) | ||
| 34 | */ | ||
| 35 | |||
| 36 | #define FM_SHARE_FILE 0 | ||
| 37 | |||
| 38 | /* | ||
| 39 | * FM operator | ||
| 40 | */ | ||
| 41 | |||
| 42 | struct fm_operator { | ||
| 43 | unsigned char am_vib; | ||
| 44 | unsigned char ksl_level; | ||
| 45 | unsigned char attack_decay; | ||
| 46 | unsigned char sustain_release; | ||
| 47 | unsigned char wave_select; | ||
| 48 | }; | ||
| 49 | |||
| 50 | /* | ||
| 51 | * Instrument | ||
| 52 | */ | ||
| 53 | |||
| 54 | #define FM_PATCH_OPL2 0x01 /* OPL2 2 operators FM instrument */ | ||
| 55 | #define FM_PATCH_OPL3 0x02 /* OPL3 4 operators FM instrument */ | ||
| 56 | |||
| 57 | struct fm_instrument { | ||
| 58 | unsigned int share_id[4]; /* share id - zero = no sharing */ | ||
| 59 | unsigned char type; /* instrument type */ | ||
| 60 | |||
| 61 | struct fm_operator op[4]; | ||
| 62 | unsigned char feedback_connection[2]; | ||
| 63 | |||
| 64 | unsigned char echo_delay; | ||
| 65 | unsigned char echo_atten; | ||
| 66 | unsigned char chorus_spread; | ||
| 67 | unsigned char trnsps; | ||
| 68 | unsigned char fix_dur; | ||
| 69 | unsigned char modes; | ||
| 70 | unsigned char fix_key; | ||
| 71 | }; | ||
| 72 | |||
| 73 | /* | ||
| 74 | * | ||
| 75 | * Kernel <-> user space | ||
| 76 | * Hardware (CPU) independent section | ||
| 77 | * | ||
| 78 | * * = zero or more | ||
| 79 | * + = one or more | ||
| 80 | * | ||
| 81 | * fm_xinstrument FM_STRU_INSTR | ||
| 82 | * | ||
| 83 | */ | ||
| 84 | |||
| 85 | #define FM_STRU_INSTR __cpu_to_be32(('I'<<24)|('N'<<16)|('S'<<8)|'T') | ||
| 86 | |||
| 87 | /* | ||
| 88 | * FM operator | ||
| 89 | */ | ||
| 90 | |||
| 91 | struct fm_xoperator { | ||
| 92 | __u8 am_vib; | ||
| 93 | __u8 ksl_level; | ||
| 94 | __u8 attack_decay; | ||
| 95 | __u8 sustain_release; | ||
| 96 | __u8 wave_select; | ||
| 97 | }; | ||
| 98 | |||
| 99 | /* | ||
| 100 | * Instrument | ||
| 101 | */ | ||
| 102 | |||
| 103 | struct fm_xinstrument { | ||
| 104 | __u32 stype; /* structure type */ | ||
| 105 | |||
| 106 | __u32 share_id[4]; /* share id - zero = no sharing */ | ||
| 107 | __u8 type; /* instrument type */ | ||
| 108 | |||
| 109 | struct fm_xoperator op[4]; /* fm operators */ | ||
| 110 | __u8 feedback_connection[2]; | ||
| 111 | |||
| 112 | __u8 echo_delay; | ||
| 113 | __u8 echo_atten; | ||
| 114 | __u8 chorus_spread; | ||
| 115 | __u8 trnsps; | ||
| 116 | __u8 fix_dur; | ||
| 117 | __u8 modes; | ||
| 118 | __u8 fix_key; | ||
| 119 | }; | ||
| 120 | |||
| 121 | #ifdef __KERNEL__ | ||
| 122 | |||
| 123 | #include "seq_instr.h" | ||
| 124 | |||
| 125 | int snd_seq_fm_init(struct snd_seq_kinstr_ops * ops, | ||
| 126 | struct snd_seq_kinstr_ops * next); | ||
| 127 | |||
| 128 | #endif | ||
| 129 | |||
| 130 | /* typedefs for compatibility to user-space */ | ||
| 131 | typedef struct fm_xoperator fm_xoperator_t; | ||
| 132 | typedef struct fm_xinstrument fm_xinstrument_t; | ||
| 133 | |||
| 134 | #endif /* __SOUND_AINSTR_FM_H */ | ||
diff --git a/include/sound/ainstr_gf1.h b/include/sound/ainstr_gf1.h deleted file mode 100644 index b62b665c69c6..000000000000 --- a/include/sound/ainstr_gf1.h +++ /dev/null | |||
| @@ -1,229 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Advanced Linux Sound Architecture | ||
| 3 | * | ||
| 4 | * GF1 (GUS) Patch Instrument Format | ||
| 5 | * Copyright (c) 1994-99 by Jaroslav Kysela <perex@perex.cz> | ||
| 6 | * | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify | ||
| 9 | * it under the terms of the GNU General Public License as published by | ||
| 10 | * the Free Software Foundation; either version 2 of the License, or | ||
| 11 | * (at your option) any later version. | ||
| 12 | * | ||
| 13 | * This program is distributed in the hope that it will be useful, | ||
| 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 16 | * GNU General Public License for more details. | ||
| 17 | * | ||
| 18 | * You should have received a copy of the GNU General Public License | ||
| 19 | * along with this program; if not, write to the Free Software | ||
| 20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 21 | * | ||
| 22 | */ | ||
| 23 | |||
| 24 | #ifndef __SOUND_AINSTR_GF1_H | ||
| 25 | #define __SOUND_AINSTR_GF1_H | ||
| 26 | |||
| 27 | #ifndef __KERNEL__ | ||
| 28 | #include <asm/types.h> | ||
| 29 | #include <asm/byteorder.h> | ||
| 30 | #endif | ||
| 31 | |||
| 32 | /* | ||
| 33 | * share types (share ID 1) | ||
| 34 | */ | ||
| 35 | |||
| 36 | #define GF1_SHARE_FILE 0 | ||
| 37 | |||
| 38 | /* | ||
| 39 | * wave formats | ||
| 40 | */ | ||
| 41 | |||
| 42 | #define GF1_WAVE_16BIT 0x0001 /* 16-bit wave */ | ||
| 43 | #define GF1_WAVE_UNSIGNED 0x0002 /* unsigned wave */ | ||
| 44 | #define GF1_WAVE_INVERT 0x0002 /* same as unsigned wave */ | ||
| 45 | #define GF1_WAVE_BACKWARD 0x0004 /* backward mode (maybe used for reverb or ping-ping loop) */ | ||
| 46 | #define GF1_WAVE_LOOP 0x0008 /* loop mode */ | ||
| 47 | #define GF1_WAVE_BIDIR 0x0010 /* bidirectional mode */ | ||
| 48 | #define GF1_WAVE_STEREO 0x0100 /* stereo mode */ | ||
| 49 | #define GF1_WAVE_ULAW 0x0200 /* uLaw compression mode */ | ||
| 50 | |||
| 51 | /* | ||
| 52 | * Wavetable definitions | ||
| 53 | */ | ||
| 54 | |||
| 55 | struct gf1_wave { | ||
| 56 | unsigned int share_id[4]; /* share id - zero = no sharing */ | ||
| 57 | unsigned int format; /* wave format */ | ||
| 58 | |||
| 59 | struct { | ||
| 60 | unsigned int number; /* some other ID for this instrument */ | ||
| 61 | unsigned int memory; /* begin of waveform in onboard memory */ | ||
| 62 | unsigned char *ptr; /* pointer to waveform in system memory */ | ||
| 63 | } address; | ||
| 64 | |||
| 65 | unsigned int size; /* size of waveform in samples */ | ||
| 66 | unsigned int start; /* start offset in samples * 16 (lowest 4 bits - fraction) */ | ||
| 67 | unsigned int loop_start; /* bits loop start offset in samples * 16 (lowest 4 bits - fraction) */ | ||
| 68 | unsigned int loop_end; /* loop start offset in samples * 16 (lowest 4 bits - fraction) */ | ||
| 69 | unsigned short loop_repeat; /* loop repeat - 0 = forever */ | ||
| 70 | |||
| 71 | unsigned char flags; /* GF1 patch flags */ | ||
| 72 | unsigned char pad; | ||
| 73 | unsigned int sample_rate; /* sample rate in Hz */ | ||
| 74 | unsigned int low_frequency; /* low frequency range */ | ||
| 75 | unsigned int high_frequency; /* high frequency range */ | ||
| 76 | unsigned int root_frequency; /* root frequency range */ | ||
| 77 | signed short tune; | ||
| 78 | unsigned char balance; | ||
| 79 | unsigned char envelope_rate[6]; | ||
| 80 | unsigned char envelope_offset[6]; | ||
| 81 | unsigned char tremolo_sweep; | ||
| 82 | unsigned char tremolo_rate; | ||
| 83 | unsigned char tremolo_depth; | ||
| 84 | unsigned char vibrato_sweep; | ||
| 85 | unsigned char vibrato_rate; | ||
| 86 | unsigned char vibrato_depth; | ||
| 87 | unsigned short scale_frequency; | ||
| 88 | unsigned short scale_factor; /* 0-2048 or 0-2 */ | ||
| 89 | |||
| 90 | struct gf1_wave *next; | ||
| 91 | }; | ||
| 92 | |||
| 93 | /* | ||
| 94 | * Instrument | ||
| 95 | */ | ||
| 96 | |||
| 97 | #define IWFFFF_EXCLUDE_NONE 0x0000 /* exclusion mode - none */ | ||
| 98 | #define IWFFFF_EXCLUDE_SINGLE 0x0001 /* exclude single - single note from the instrument group */ | ||
| 99 | #define IWFFFF_EXCLUDE_MULTIPLE 0x0002 /* exclude multiple - stop only same note from this instrument */ | ||
| 100 | |||
| 101 | #define IWFFFF_EFFECT_NONE 0 | ||
| 102 | #define IWFFFF_EFFECT_REVERB 1 | ||
| 103 | #define IWFFFF_EFFECT_CHORUS 2 | ||
| 104 | #define IWFFFF_EFFECT_ECHO 3 | ||
| 105 | |||
| 106 | struct gf1_instrument { | ||
| 107 | unsigned short exclusion; | ||
| 108 | unsigned short exclusion_group; /* 0 - none, 1-65535 */ | ||
| 109 | |||
| 110 | unsigned char effect1; /* effect 1 */ | ||
| 111 | unsigned char effect1_depth; /* 0-127 */ | ||
| 112 | unsigned char effect2; /* effect 2 */ | ||
| 113 | unsigned char effect2_depth; /* 0-127 */ | ||
| 114 | |||
| 115 | struct gf1_wave *wave; /* first waveform */ | ||
| 116 | }; | ||
| 117 | |||
| 118 | /* | ||
| 119 | * | ||
| 120 | * Kernel <-> user space | ||
| 121 | * Hardware (CPU) independent section | ||
| 122 | * | ||
| 123 | * * = zero or more | ||
| 124 | * + = one or more | ||
| 125 | * | ||
| 126 | * gf1_xinstrument IWFFFF_STRU_INSTR | ||
| 127 | * +gf1_xwave IWFFFF_STRU_WAVE | ||
| 128 | * | ||
| 129 | */ | ||
| 130 | |||
| 131 | #define GF1_STRU_WAVE __cpu_to_be32(('W'<<24)|('A'<<16)|('V'<<8)|'E') | ||
| 132 | #define GF1_STRU_INSTR __cpu_to_be32(('I'<<24)|('N'<<16)|('S'<<8)|'T') | ||
| 133 | |||
| 134 | /* | ||
| 135 | * Wavetable definitions | ||
| 136 | */ | ||
| 137 | |||
| 138 | struct gf1_xwave { | ||
| 139 | __u32 stype; /* structure type */ | ||
| 140 | |||
| 141 | __u32 share_id[4]; /* share id - zero = no sharing */ | ||
| 142 | __u32 format; /* wave format */ | ||
| 143 | |||
| 144 | __u32 size; /* size of waveform in samples */ | ||
| 145 | __u32 start; /* start offset in samples * 16 (lowest 4 bits - fraction) */ | ||
| 146 | __u32 loop_start; /* bits loop start offset in samples * 16 (lowest 4 bits - fraction) */ | ||
| 147 | __u32 loop_end; /* loop start offset in samples * 16 (lowest 4 bits - fraction) */ | ||
| 148 | __u16 loop_repeat; /* loop repeat - 0 = forever */ | ||
| 149 | |||
| 150 | __u8 flags; /* GF1 patch flags */ | ||
| 151 | __u8 pad; | ||
| 152 | __u32 sample_rate; /* sample rate in Hz */ | ||
| 153 | __u32 low_frequency; /* low frequency range */ | ||
| 154 | __u32 high_frequency; /* high frequency range */ | ||
| 155 | __u32 root_frequency; /* root frequency range */ | ||
| 156 | __s16 tune; | ||
| 157 | __u8 balance; | ||
| 158 | __u8 envelope_rate[6]; | ||
| 159 | __u8 envelope_offset[6]; | ||
| 160 | __u8 tremolo_sweep; | ||
| 161 | __u8 tremolo_rate; | ||
| 162 | __u8 tremolo_depth; | ||
| 163 | __u8 vibrato_sweep; | ||
| 164 | __u8 vibrato_rate; | ||
| 165 | __u8 vibrato_depth; | ||
| 166 | __u16 scale_frequency; | ||
| 167 | __u16 scale_factor; /* 0-2048 or 0-2 */ | ||
| 168 | }; | ||
| 169 | |||
| 170 | /* | ||
| 171 | * Instrument | ||
| 172 | */ | ||
| 173 | |||
| 174 | struct gf1_xinstrument { | ||
| 175 | __u32 stype; | ||
| 176 | |||
| 177 | __u16 exclusion; | ||
| 178 | __u16 exclusion_group; /* 0 - none, 1-65535 */ | ||
| 179 | |||
| 180 | __u8 effect1; /* effect 1 */ | ||
| 181 | __u8 effect1_depth; /* 0-127 */ | ||
| 182 | __u8 effect2; /* effect 2 */ | ||
| 183 | __u8 effect2_depth; /* 0-127 */ | ||
| 184 | }; | ||
| 185 | |||
| 186 | /* | ||
| 187 | * Instrument info | ||
| 188 | */ | ||
| 189 | |||
| 190 | #define GF1_INFO_ENVELOPE (1<<0) | ||
| 191 | #define GF1_INFO_TREMOLO (1<<1) | ||
| 192 | #define GF1_INFO_VIBRATO (1<<2) | ||
| 193 | |||
| 194 | struct gf1_info { | ||
| 195 | unsigned char flags; /* supported wave flags */ | ||
| 196 | unsigned char pad[3]; | ||
| 197 | unsigned int features; /* supported features */ | ||
| 198 | unsigned int max8_len; /* maximum 8-bit wave length */ | ||
| 199 | unsigned int max16_len; /* maximum 16-bit wave length */ | ||
| 200 | }; | ||
| 201 | |||
| 202 | #ifdef __KERNEL__ | ||
| 203 | |||
| 204 | #include "seq_instr.h" | ||
| 205 | |||
| 206 | struct snd_gf1_ops { | ||
| 207 | void *private_data; | ||
| 208 | int (*info)(void *private_data, struct gf1_info *info); | ||
| 209 | int (*put_sample)(void *private_data, struct gf1_wave *wave, | ||
| 210 | char __user *data, long len, int atomic); | ||
| 211 | int (*get_sample)(void *private_data, struct gf1_wave *wave, | ||
| 212 | char __user *data, long len, int atomic); | ||
| 213 | int (*remove_sample)(void *private_data, struct gf1_wave *wave, | ||
| 214 | int atomic); | ||
| 215 | void (*notify)(void *private_data, struct snd_seq_kinstr *instr, int what); | ||
| 216 | struct snd_seq_kinstr_ops kops; | ||
| 217 | }; | ||
| 218 | |||
| 219 | int snd_seq_gf1_init(struct snd_gf1_ops *ops, | ||
| 220 | void *private_data, | ||
| 221 | struct snd_seq_kinstr_ops *next); | ||
| 222 | |||
| 223 | #endif | ||
| 224 | |||
| 225 | /* typedefs for compatibility to user-space */ | ||
| 226 | typedef struct gf1_xwave gf1_xwave_t; | ||
| 227 | typedef struct gf1_xinstrument gf1_xinstrument_t; | ||
| 228 | |||
| 229 | #endif /* __SOUND_AINSTR_GF1_H */ | ||
diff --git a/include/sound/ainstr_iw.h b/include/sound/ainstr_iw.h deleted file mode 100644 index 11bd25082600..000000000000 --- a/include/sound/ainstr_iw.h +++ /dev/null | |||
| @@ -1,384 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Advanced Linux Sound Architecture | ||
| 3 | * | ||
| 4 | * InterWave FFFF Instrument Format | ||
| 5 | * Copyright (c) 1994-99 by Jaroslav Kysela <perex@perex.cz> | ||
| 6 | * | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify | ||
| 9 | * it under the terms of the GNU General Public License as published by | ||
| 10 | * the Free Software Foundation; either version 2 of the License, or | ||
| 11 | * (at your option) any later version. | ||
| 12 | * | ||
| 13 | * This program is distributed in the hope that it will be useful, | ||
| 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 16 | * GNU General Public License for more details. | ||
| 17 | * | ||
| 18 | * You should have received a copy of the GNU General Public License | ||
| 19 | * along with this program; if not, write to the Free Software | ||
| 20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 21 | * | ||
| 22 | */ | ||
| 23 | |||
| 24 | #ifndef __SOUND_AINSTR_IW_H | ||
| 25 | #define __SOUND_AINSTR_IW_H | ||
| 26 | |||
| 27 | #ifndef __KERNEL__ | ||
| 28 | #include <asm/types.h> | ||
| 29 | #include <asm/byteorder.h> | ||
| 30 | #endif | ||
| 31 | |||
| 32 | /* | ||
| 33 | * share types (share ID 1) | ||
| 34 | */ | ||
| 35 | |||
| 36 | #define IWFFFF_SHARE_FILE 0 | ||
| 37 | |||
| 38 | /* | ||
| 39 | * wave formats | ||
| 40 | */ | ||
| 41 | |||
| 42 | #define IWFFFF_WAVE_16BIT 0x0001 /* 16-bit wave */ | ||
| 43 | #define IWFFFF_WAVE_UNSIGNED 0x0002 /* unsigned wave */ | ||
| 44 | #define IWFFFF_WAVE_INVERT 0x0002 /* same as unsigned wave */ | ||
| 45 | #define IWFFFF_WAVE_BACKWARD 0x0004 /* backward mode (maybe used for reverb or ping-ping loop) */ | ||
| 46 | #define IWFFFF_WAVE_LOOP 0x0008 /* loop mode */ | ||
| 47 | #define IWFFFF_WAVE_BIDIR 0x0010 /* bidirectional mode */ | ||
| 48 | #define IWFFFF_WAVE_ULAW 0x0020 /* uLaw compressed wave */ | ||
| 49 | #define IWFFFF_WAVE_RAM 0x0040 /* wave is _preloaded_ in RAM (it is used for ROM simulation) */ | ||
| 50 | #define IWFFFF_WAVE_ROM 0x0080 /* wave is in ROM */ | ||
| 51 | #define IWFFFF_WAVE_STEREO 0x0100 /* wave is stereo */ | ||
| 52 | |||
| 53 | /* | ||
| 54 | * Wavetable definitions | ||
| 55 | */ | ||
| 56 | |||
| 57 | struct iwffff_wave { | ||
| 58 | unsigned int share_id[4]; /* share id - zero = no sharing */ | ||
| 59 | unsigned int format; /* wave format */ | ||
| 60 | |||
| 61 | struct { | ||
| 62 | unsigned int number; /* some other ID for this wave */ | ||
| 63 | unsigned int memory; /* begin of waveform in onboard memory */ | ||
| 64 | unsigned char *ptr; /* pointer to waveform in system memory */ | ||
| 65 | } address; | ||
| 66 | |||
| 67 | unsigned int size; /* size of waveform in samples */ | ||
| 68 | unsigned int start; /* start offset in samples * 16 (lowest 4 bits - fraction) */ | ||
| 69 | unsigned int loop_start; /* bits loop start offset in samples * 16 (lowest 4 bits - fraction) */ | ||
| 70 | unsigned int loop_end; /* loop start offset in samples * 16 (lowest 4 bits - fraction) */ | ||
| 71 | unsigned short loop_repeat; /* loop repeat - 0 = forever */ | ||
| 72 | unsigned int sample_ratio; /* sample ratio (44100 * 1024 / rate) */ | ||
| 73 | unsigned char attenuation; /* 0 - 127 (no corresponding midi controller) */ | ||
| 74 | unsigned char low_note; /* lower frequency range for this waveform */ | ||
| 75 | unsigned char high_note; /* higher frequency range for this waveform */ | ||
| 76 | unsigned char pad; | ||
| 77 | |||
| 78 | struct iwffff_wave *next; | ||
| 79 | }; | ||
| 80 | |||
| 81 | /* | ||
| 82 | * Layer | ||
| 83 | */ | ||
| 84 | |||
| 85 | #define IWFFFF_LFO_SHAPE_TRIANGLE 0 | ||
| 86 | #define IWFFFF_LFO_SHAPE_POSTRIANGLE 1 | ||
| 87 | |||
| 88 | struct iwffff_lfo { | ||
| 89 | unsigned short freq; /* (0-2047) 0.01Hz - 21.5Hz */ | ||
| 90 | signed short depth; /* volume +- (0-255) 0.48675dB/step */ | ||
| 91 | signed short sweep; /* 0 - 950 deciseconds */ | ||
| 92 | unsigned char shape; /* see to IWFFFF_LFO_SHAPE_XXXX */ | ||
| 93 | unsigned char delay; /* 0 - 255 deciseconds */ | ||
| 94 | }; | ||
| 95 | |||
| 96 | #define IWFFFF_ENV_FLAG_RETRIGGER 0x0001 /* flag - retrigger */ | ||
| 97 | |||
| 98 | #define IWFFFF_ENV_MODE_ONE_SHOT 0x0001 /* mode - one shot */ | ||
| 99 | #define IWFFFF_ENV_MODE_SUSTAIN 0x0002 /* mode - sustain */ | ||
| 100 | #define IWFFFF_ENV_MODE_NO_SUSTAIN 0x0003 /* mode - no sustain */ | ||
| 101 | |||
| 102 | #define IWFFFF_ENV_INDEX_VELOCITY 0x0001 /* index - velocity */ | ||
| 103 | #define IWFFFF_ENV_INDEX_FREQUENCY 0x0002 /* index - frequency */ | ||
| 104 | |||
| 105 | struct iwffff_env_point { | ||
| 106 | unsigned short offset; | ||
| 107 | unsigned short rate; | ||
| 108 | }; | ||
| 109 | |||
| 110 | struct iwffff_env_record { | ||
| 111 | unsigned short nattack; | ||
| 112 | unsigned short nrelease; | ||
| 113 | unsigned short sustain_offset; | ||
| 114 | unsigned short sustain_rate; | ||
| 115 | unsigned short release_rate; | ||
| 116 | unsigned char hirange; | ||
| 117 | unsigned char pad; | ||
| 118 | struct iwffff_env_record *next; | ||
| 119 | /* points are stored here */ | ||
| 120 | /* count of points = nattack + nrelease */ | ||
| 121 | }; | ||
| 122 | |||
| 123 | struct iwffff_env { | ||
| 124 | unsigned char flags; | ||
| 125 | unsigned char mode; | ||
| 126 | unsigned char index; | ||
| 127 | unsigned char pad; | ||
| 128 | struct iwffff_env_record *record; | ||
| 129 | }; | ||
| 130 | |||
| 131 | #define IWFFFF_LAYER_FLAG_RETRIGGER 0x0001 /* retrigger */ | ||
| 132 | |||
| 133 | #define IWFFFF_LAYER_VELOCITY_TIME 0x0000 /* velocity mode = time */ | ||
| 134 | #define IWFFFF_LAYER_VELOCITY_RATE 0x0001 /* velocity mode = rate */ | ||
| 135 | |||
| 136 | #define IWFFFF_LAYER_EVENT_KUP 0x0000 /* layer event - key up */ | ||
| 137 | #define IWFFFF_LAYER_EVENT_KDOWN 0x0001 /* layer event - key down */ | ||
| 138 | #define IWFFFF_LAYER_EVENT_RETRIG 0x0002 /* layer event - retrigger */ | ||
| 139 | #define IWFFFF_LAYER_EVENT_LEGATO 0x0003 /* layer event - legato */ | ||
| 140 | |||
| 141 | struct iwffff_layer { | ||
| 142 | unsigned char flags; | ||
| 143 | unsigned char velocity_mode; | ||
| 144 | unsigned char layer_event; | ||
| 145 | unsigned char low_range; /* range for layer based */ | ||
| 146 | unsigned char high_range; /* on either velocity or frequency */ | ||
| 147 | unsigned char pan; /* pan offset from CC1 (0 left - 127 right) */ | ||
| 148 | unsigned char pan_freq_scale; /* position based on frequency (0-127) */ | ||
| 149 | unsigned char attenuation; /* 0-127 (no corresponding midi controller) */ | ||
| 150 | struct iwffff_lfo tremolo; /* tremolo effect */ | ||
| 151 | struct iwffff_lfo vibrato; /* vibrato effect */ | ||
| 152 | unsigned short freq_scale; /* 0-2048, 1024 is equal to semitone scaling */ | ||
| 153 | unsigned char freq_center; /* center for keyboard frequency scaling */ | ||
| 154 | unsigned char pad; | ||
| 155 | struct iwffff_env penv; /* pitch envelope */ | ||
| 156 | struct iwffff_env venv; /* volume envelope */ | ||
| 157 | |||
| 158 | struct iwffff_wave *wave; | ||
| 159 | struct iwffff_layer *next; | ||
| 160 | }; | ||
| 161 | |||
| 162 | /* | ||
| 163 | * Instrument | ||
| 164 | */ | ||
| 165 | |||
| 166 | #define IWFFFF_EXCLUDE_NONE 0x0000 /* exclusion mode - none */ | ||
| 167 | #define IWFFFF_EXCLUDE_SINGLE 0x0001 /* exclude single - single note from the instrument group */ | ||
| 168 | #define IWFFFF_EXCLUDE_MULTIPLE 0x0002 /* exclude multiple - stop only same note from this instrument */ | ||
| 169 | |||
| 170 | #define IWFFFF_LAYER_NONE 0x0000 /* not layered */ | ||
| 171 | #define IWFFFF_LAYER_ON 0x0001 /* layered */ | ||
| 172 | #define IWFFFF_LAYER_VELOCITY 0x0002 /* layered by velocity */ | ||
| 173 | #define IWFFFF_LAYER_FREQUENCY 0x0003 /* layered by frequency */ | ||
| 174 | |||
| 175 | #define IWFFFF_EFFECT_NONE 0 | ||
| 176 | #define IWFFFF_EFFECT_REVERB 1 | ||
| 177 | #define IWFFFF_EFFECT_CHORUS 2 | ||
| 178 | #define IWFFFF_EFFECT_ECHO 3 | ||
| 179 | |||
| 180 | struct iwffff_instrument { | ||
| 181 | unsigned short exclusion; | ||
| 182 | unsigned short layer_type; | ||
| 183 | unsigned short exclusion_group; /* 0 - none, 1-65535 */ | ||
| 184 | |||
| 185 | unsigned char effect1; /* effect 1 */ | ||
| 186 | unsigned char effect1_depth; /* 0-127 */ | ||
| 187 | unsigned char effect2; /* effect 2 */ | ||
| 188 | unsigned char effect2_depth; /* 0-127 */ | ||
| 189 | |||
| 190 | struct iwffff_layer *layer; /* first layer */ | ||
| 191 | }; | ||
| 192 | |||
| 193 | /* | ||
| 194 | * | ||
| 195 | * Kernel <-> user space | ||
| 196 | * Hardware (CPU) independent section | ||
| 197 | * | ||
| 198 | * * = zero or more | ||
| 199 | * + = one or more | ||
| 200 | * | ||
| 201 | * iwffff_xinstrument IWFFFF_STRU_INSTR | ||
| 202 | * +iwffff_xlayer IWFFFF_STRU_LAYER | ||
| 203 | * *iwffff_xenv_record IWFFFF_STRU_ENV_RECT (tremolo) | ||
| 204 | * *iwffff_xenv_record IWFFFF_STRU_EVN_RECT (vibrato) | ||
| 205 | * +iwffff_xwave IWFFFF_STRU_WAVE | ||
| 206 | * | ||
| 207 | */ | ||
| 208 | |||
| 209 | #define IWFFFF_STRU_WAVE __cpu_to_be32(('W'<<24)|('A'<<16)|('V'<<8)|'E') | ||
| 210 | #define IWFFFF_STRU_ENV_RECP __cpu_to_be32(('E'<<24)|('N'<<16)|('R'<<8)|'P') | ||
| 211 | #define IWFFFF_STRU_ENV_RECV __cpu_to_be32(('E'<<24)|('N'<<16)|('R'<<8)|'V') | ||
| 212 | #define IWFFFF_STRU_LAYER __cpu_to_be32(('L'<<24)|('A'<<16)|('Y'<<8)|'R') | ||
| 213 | #define IWFFFF_STRU_INSTR __cpu_to_be32(('I'<<24)|('N'<<16)|('S'<<8)|'T') | ||
| 214 | |||
| 215 | /* | ||
| 216 | * Wavetable definitions | ||
| 217 | */ | ||
| 218 | |||
| 219 | struct iwffff_xwave { | ||
| 220 | __u32 stype; /* structure type */ | ||
| 221 | |||
| 222 | __u32 share_id[4]; /* share id - zero = no sharing */ | ||
| 223 | |||
| 224 | __u32 format; /* wave format */ | ||
| 225 | __u32 offset; /* offset to ROM (address) */ | ||
| 226 | |||
| 227 | __u32 size; /* size of waveform in samples */ | ||
| 228 | __u32 start; /* start offset in samples * 16 (lowest 4 bits - fraction) */ | ||
| 229 | __u32 loop_start; /* bits loop start offset in samples * 16 (lowest 4 bits - fraction) */ | ||
| 230 | __u32 loop_end; /* loop start offset in samples * 16 (lowest 4 bits - fraction) */ | ||
| 231 | __u16 loop_repeat; /* loop repeat - 0 = forever */ | ||
| 232 | __u32 sample_ratio; /* sample ratio (44100 * 1024 / rate) */ | ||
| 233 | __u8 attenuation; /* 0 - 127 (no corresponding midi controller) */ | ||
| 234 | __u8 low_note; /* lower frequency range for this waveform */ | ||
| 235 | __u8 high_note; /* higher frequency range for this waveform */ | ||
| 236 | __u8 pad; | ||
| 237 | }; | ||
| 238 | |||
| 239 | /* | ||
| 240 | * Layer | ||
| 241 | */ | ||
| 242 | |||
| 243 | struct iwffff_xlfo { | ||
| 244 | __u16 freq; /* (0-2047) 0.01Hz - 21.5Hz */ | ||
| 245 | __s16 depth; /* volume +- (0-255) 0.48675dB/step */ | ||
| 246 | __s16 sweep; /* 0 - 950 deciseconds */ | ||
| 247 | __u8 shape; /* see to ULTRA_IW_LFO_SHAPE_XXXX */ | ||
| 248 | __u8 delay; /* 0 - 255 deciseconds */ | ||
| 249 | }; | ||
| 250 | |||
| 251 | struct iwffff_xenv_point { | ||
| 252 | __u16 offset; | ||
| 253 | __u16 rate; | ||
| 254 | }; | ||
| 255 | |||
| 256 | struct iwffff_xenv_record { | ||
| 257 | __u32 stype; | ||
| 258 | __u16 nattack; | ||
| 259 | __u16 nrelease; | ||
| 260 | __u16 sustain_offset; | ||
| 261 | __u16 sustain_rate; | ||
| 262 | __u16 release_rate; | ||
| 263 | __u8 hirange; | ||
| 264 | __u8 pad; | ||
| 265 | /* points are stored here.. */ | ||
| 266 | /* count of points = nattack + nrelease */ | ||
| 267 | }; | ||
| 268 | |||
| 269 | struct iwffff_xenv { | ||
| 270 | __u8 flags; | ||
| 271 | __u8 mode; | ||
| 272 | __u8 index; | ||
| 273 | __u8 pad; | ||
| 274 | }; | ||
| 275 | |||
| 276 | struct iwffff_xlayer { | ||
| 277 | __u32 stype; | ||
| 278 | __u8 flags; | ||
| 279 | __u8 velocity_mode; | ||
| 280 | __u8 layer_event; | ||
| 281 | __u8 low_range; /* range for layer based */ | ||
| 282 | __u8 high_range; /* on either velocity or frequency */ | ||
| 283 | __u8 pan; /* pan offset from CC1 (0 left - 127 right) */ | ||
| 284 | __u8 pan_freq_scale; /* position based on frequency (0-127) */ | ||
| 285 | __u8 attenuation; /* 0-127 (no corresponding midi controller) */ | ||
| 286 | struct iwffff_xlfo tremolo; /* tremolo effect */ | ||
| 287 | struct iwffff_xlfo vibrato; /* vibrato effect */ | ||
| 288 | __u16 freq_scale; /* 0-2048, 1024 is equal to semitone scaling */ | ||
| 289 | __u8 freq_center; /* center for keyboard frequency scaling */ | ||
| 290 | __u8 pad; | ||
| 291 | struct iwffff_xenv penv; /* pitch envelope */ | ||
| 292 | struct iwffff_xenv venv; /* volume envelope */ | ||
| 293 | }; | ||
| 294 | |||
| 295 | /* | ||
| 296 | * Instrument | ||
| 297 | */ | ||
| 298 | |||
| 299 | struct iwffff_xinstrument { | ||
| 300 | __u32 stype; | ||
| 301 | |||
| 302 | __u16 exclusion; | ||
| 303 | __u16 layer_type; | ||
| 304 | __u16 exclusion_group; /* 0 - none, 1-65535 */ | ||
| 305 | |||
| 306 | __u8 effect1; /* effect 1 */ | ||
| 307 | __u8 effect1_depth; /* 0-127 */ | ||
| 308 | __u8 effect2; /* effect 2 */ | ||
| 309 | __u8 effect2_depth; /* 0-127 */ | ||
| 310 | }; | ||
| 311 | |||
| 312 | /* | ||
| 313 | * ROM support | ||
| 314 | * InterWave ROMs are Little-Endian (x86) | ||
| 315 | */ | ||
| 316 | |||
| 317 | #define IWFFFF_ROM_HDR_SIZE 512 | ||
| 318 | |||
| 319 | struct iwffff_rom_header { | ||
| 320 | __u8 iwave[8]; | ||
| 321 | __u8 revision; | ||
| 322 | __u8 series_number; | ||
| 323 | __u8 series_name[16]; | ||
| 324 | __u8 date[10]; | ||
| 325 | __u16 vendor_revision_major; | ||
| 326 | __u16 vendor_revision_minor; | ||
| 327 | __u32 rom_size; | ||
| 328 | __u8 copyright[128]; | ||
| 329 | __u8 vendor_name[64]; | ||
| 330 | __u8 description[128]; | ||
| 331 | }; | ||
| 332 | |||
| 333 | /* | ||
| 334 | * Instrument info | ||
| 335 | */ | ||
| 336 | |||
| 337 | #define IWFFFF_INFO_LFO_VIBRATO (1<<0) | ||
| 338 | #define IWFFFF_INFO_LFO_VIBRATO_SHAPE (1<<1) | ||
| 339 | #define IWFFFF_INFO_LFO_TREMOLO (1<<2) | ||
| 340 | #define IWFFFF_INFO_LFO_TREMOLO_SHAPE (1<<3) | ||
| 341 | |||
| 342 | struct iwffff_info { | ||
| 343 | unsigned int format; /* supported format bits */ | ||
| 344 | unsigned int effects; /* supported effects (1 << IWFFFF_EFFECT*) */ | ||
| 345 | unsigned int lfos; /* LFO effects */ | ||
| 346 | unsigned int max8_len; /* maximum 8-bit wave length */ | ||
| 347 | unsigned int max16_len; /* maximum 16-bit wave length */ | ||
| 348 | }; | ||
| 349 | |||
| 350 | #ifdef __KERNEL__ | ||
| 351 | |||
| 352 | #include "seq_instr.h" | ||
| 353 | |||
| 354 | struct snd_iwffff_ops { | ||
| 355 | void *private_data; | ||
| 356 | int (*info)(void *private_data, struct iwffff_info *info); | ||
| 357 | int (*put_sample)(void *private_data, struct iwffff_wave *wave, | ||
| 358 | char __user *data, long len, int atomic); | ||
| 359 | int (*get_sample)(void *private_data, struct iwffff_wave *wave, | ||
| 360 | char __user *data, long len, int atomic); | ||
| 361 | int (*remove_sample)(void *private_data, struct iwffff_wave *wave, | ||
| 362 | int atomic); | ||
| 363 | void (*notify)(void *private_data, struct snd_seq_kinstr *instr, int what); | ||
| 364 | struct snd_seq_kinstr_ops kops; | ||
| 365 | }; | ||
| 366 | |||
| 367 | int snd_seq_iwffff_init(struct snd_iwffff_ops *ops, | ||
| 368 | void *private_data, | ||
| 369 | struct snd_seq_kinstr_ops *next); | ||
| 370 | |||
| 371 | #endif | ||
| 372 | |||
| 373 | /* typedefs for compatibility to user-space */ | ||
| 374 | typedef struct iwffff_xwave iwffff_xwave_t; | ||
| 375 | typedef struct iwffff_xlfo iwffff_xlfo_t; | ||
| 376 | typedef struct iwffff_xenv_point iwffff_xenv_point_t; | ||
| 377 | typedef struct iwffff_xenv_record iwffff_xenv_record_t; | ||
| 378 | typedef struct iwffff_xenv iwffff_xenv_t; | ||
| 379 | typedef struct iwffff_xlayer iwffff_xlayer_t; | ||
| 380 | typedef struct iwffff_xinstrument iwffff_xinstrument_t; | ||
| 381 | typedef struct iwffff_rom_header iwffff_rom_header_t; | ||
| 382 | typedef struct iwffff_info iwffff_info_t; | ||
| 383 | |||
| 384 | #endif /* __SOUND_AINSTR_IW_H */ | ||
diff --git a/include/sound/ainstr_simple.h b/include/sound/ainstr_simple.h deleted file mode 100644 index da08e7287557..000000000000 --- a/include/sound/ainstr_simple.h +++ /dev/null | |||
| @@ -1,159 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Advanced Linux Sound Architecture | ||
| 3 | * | ||
| 4 | * Simple (MOD player) Instrument Format | ||
| 5 | * Copyright (c) 1994-99 by Jaroslav Kysela <perex@perex.cz> | ||
| 6 | * | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify | ||
| 9 | * it under the terms of the GNU General Public License as published by | ||
| 10 | * the Free Software Foundation; either version 2 of the License, or | ||
| 11 | * (at your option) any later version. | ||
| 12 | * | ||
| 13 | * This program is distributed in the hope that it will be useful, | ||
| 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 16 | * GNU General Public License for more details. | ||
| 17 | * | ||
| 18 | * You should have received a copy of the GNU General Public License | ||
| 19 | * along with this program; if not, write to the Free Software | ||
| 20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 21 | * | ||
| 22 | */ | ||
| 23 | |||
| 24 | #ifndef __SOUND_AINSTR_SIMPLE_H | ||
| 25 | #define __SOUND_AINSTR_SIMPLE_H | ||
| 26 | |||
| 27 | #ifndef __KERNEL__ | ||
| 28 | #include <asm/types.h> | ||
| 29 | #include <asm/byteorder.h> | ||
| 30 | #endif | ||
| 31 | |||
| 32 | /* | ||
| 33 | * share types (share ID 1) | ||
| 34 | */ | ||
| 35 | |||
| 36 | #define SIMPLE_SHARE_FILE 0 | ||
| 37 | |||
| 38 | /* | ||
| 39 | * wave formats | ||
| 40 | */ | ||
| 41 | |||
| 42 | #define SIMPLE_WAVE_16BIT 0x0001 /* 16-bit wave */ | ||
| 43 | #define SIMPLE_WAVE_UNSIGNED 0x0002 /* unsigned wave */ | ||
| 44 | #define SIMPLE_WAVE_INVERT 0x0002 /* same as unsigned wave */ | ||
| 45 | #define SIMPLE_WAVE_BACKWARD 0x0004 /* backward mode (maybe used for reverb or ping-ping loop) */ | ||
| 46 | #define SIMPLE_WAVE_LOOP 0x0008 /* loop mode */ | ||
| 47 | #define SIMPLE_WAVE_BIDIR 0x0010 /* bidirectional mode */ | ||
| 48 | #define SIMPLE_WAVE_STEREO 0x0100 /* stereo wave */ | ||
| 49 | #define SIMPLE_WAVE_ULAW 0x0200 /* uLaw compression mode */ | ||
| 50 | |||
| 51 | /* | ||
| 52 | * instrument effects | ||
| 53 | */ | ||
| 54 | |||
| 55 | #define SIMPLE_EFFECT_NONE 0 | ||
| 56 | #define SIMPLE_EFFECT_REVERB 1 | ||
| 57 | #define SIMPLE_EFFECT_CHORUS 2 | ||
| 58 | #define SIMPLE_EFFECT_ECHO 3 | ||
| 59 | |||
| 60 | /* | ||
| 61 | * instrument info | ||
| 62 | */ | ||
| 63 | |||
| 64 | struct simple_instrument_info { | ||
| 65 | unsigned int format; /* supported format bits */ | ||
| 66 | unsigned int effects; /* supported effects (1 << SIMPLE_EFFECT_*) */ | ||
| 67 | unsigned int max8_len; /* maximum 8-bit wave length */ | ||
| 68 | unsigned int max16_len; /* maximum 16-bit wave length */ | ||
| 69 | }; | ||
| 70 | |||
| 71 | /* | ||
| 72 | * Instrument | ||
| 73 | */ | ||
| 74 | |||
| 75 | struct simple_instrument { | ||
| 76 | unsigned int share_id[4]; /* share id - zero = no sharing */ | ||
| 77 | unsigned int format; /* wave format */ | ||
| 78 | |||
| 79 | struct { | ||
| 80 | unsigned int number; /* some other ID for this instrument */ | ||
| 81 | unsigned int memory; /* begin of waveform in onboard memory */ | ||
| 82 | unsigned char *ptr; /* pointer to waveform in system memory */ | ||
| 83 | } address; | ||
| 84 | |||
| 85 | unsigned int size; /* size of waveform in samples */ | ||
| 86 | unsigned int start; /* start offset in samples * 16 (lowest 4 bits - fraction) */ | ||
| 87 | unsigned int loop_start; /* loop start offset in samples * 16 (lowest 4 bits - fraction) */ | ||
| 88 | unsigned int loop_end; /* loop end offset in samples * 16 (lowest 4 bits - fraction) */ | ||
| 89 | unsigned short loop_repeat; /* loop repeat - 0 = forever */ | ||
| 90 | |||
| 91 | unsigned char effect1; /* effect 1 */ | ||
| 92 | unsigned char effect1_depth; /* 0-127 */ | ||
| 93 | unsigned char effect2; /* effect 2 */ | ||
| 94 | unsigned char effect2_depth; /* 0-127 */ | ||
| 95 | }; | ||
| 96 | |||
| 97 | /* | ||
| 98 | * | ||
| 99 | * Kernel <-> user space | ||
| 100 | * Hardware (CPU) independent section | ||
| 101 | * | ||
| 102 | * * = zero or more | ||
| 103 | * + = one or more | ||
| 104 | * | ||
| 105 | * simple_xinstrument SIMPLE_STRU_INSTR | ||
| 106 | * | ||
| 107 | */ | ||
| 108 | |||
| 109 | #define SIMPLE_STRU_INSTR __cpu_to_be32(('I'<<24)|('N'<<16)|('S'<<8)|'T') | ||
| 110 | |||
| 111 | /* | ||
| 112 | * Instrument | ||
| 113 | */ | ||
| 114 | |||
| 115 | struct simple_xinstrument { | ||
| 116 | __u32 stype; | ||
| 117 | |||
| 118 | __u32 share_id[4]; /* share id - zero = no sharing */ | ||
| 119 | __u32 format; /* wave format */ | ||
| 120 | |||
| 121 | __u32 size; /* size of waveform in samples */ | ||
| 122 | __u32 start; /* start offset in samples * 16 (lowest 4 bits - fraction) */ | ||
| 123 | __u32 loop_start; /* bits loop start offset in samples * 16 (lowest 4 bits - fraction) */ | ||
| 124 | __u32 loop_end; /* loop start offset in samples * 16 (lowest 4 bits - fraction) */ | ||
| 125 | __u16 loop_repeat; /* loop repeat - 0 = forever */ | ||
| 126 | |||
| 127 | __u8 effect1; /* effect 1 */ | ||
| 128 | __u8 effect1_depth; /* 0-127 */ | ||
| 129 | __u8 effect2; /* effect 2 */ | ||
| 130 | __u8 effect2_depth; /* 0-127 */ | ||
| 131 | }; | ||
| 132 | |||
| 133 | #ifdef __KERNEL__ | ||
| 134 | |||
| 135 | #include "seq_instr.h" | ||
| 136 | |||
| 137 | struct snd_simple_ops { | ||
| 138 | void *private_data; | ||
| 139 | int (*info)(void *private_data, struct simple_instrument_info *info); | ||
| 140 | int (*put_sample)(void *private_data, struct simple_instrument *instr, | ||
| 141 | char __user *data, long len, int atomic); | ||
| 142 | int (*get_sample)(void *private_data, struct simple_instrument *instr, | ||
| 143 | char __user *data, long len, int atomic); | ||
| 144 | int (*remove_sample)(void *private_data, struct simple_instrument *instr, | ||
| 145 | int atomic); | ||
| 146 | void (*notify)(void *private_data, struct snd_seq_kinstr *instr, int what); | ||
| 147 | struct snd_seq_kinstr_ops kops; | ||
| 148 | }; | ||
| 149 | |||
| 150 | int snd_seq_simple_init(struct snd_simple_ops *ops, | ||
| 151 | void *private_data, | ||
| 152 | struct snd_seq_kinstr_ops *next); | ||
| 153 | |||
| 154 | #endif | ||
| 155 | |||
| 156 | /* typedefs for compatibility to user-space */ | ||
| 157 | typedef struct simple_xinstrument simple_xinstrument_t; | ||
| 158 | |||
| 159 | #endif /* __SOUND_AINSTR_SIMPLE_H */ | ||
diff --git a/include/sound/asequencer.h b/include/sound/asequencer.h index 64daccbe8b29..1505e6d5ef82 100644 --- a/include/sound/asequencer.h +++ b/include/sound/asequencer.h | |||
| @@ -110,18 +110,7 @@ | |||
| 110 | #define SNDRV_SEQ_EVENT_PORT_SUBSCRIBED 66 /* ports connected */ | 110 | #define SNDRV_SEQ_EVENT_PORT_SUBSCRIBED 66 /* ports connected */ |
| 111 | #define SNDRV_SEQ_EVENT_PORT_UNSUBSCRIBED 67 /* ports disconnected */ | 111 | #define SNDRV_SEQ_EVENT_PORT_UNSUBSCRIBED 67 /* ports disconnected */ |
| 112 | 112 | ||
| 113 | /** synthesizer events | 113 | /* 70-89: synthesizer events - obsoleted */ |
| 114 | * event data type = snd_seq_eve_sample_control | ||
| 115 | */ | ||
| 116 | #define SNDRV_SEQ_EVENT_SAMPLE 70 /* sample select */ | ||
| 117 | #define SNDRV_SEQ_EVENT_SAMPLE_CLUSTER 71 /* sample cluster select */ | ||
| 118 | #define SNDRV_SEQ_EVENT_SAMPLE_START 72 /* voice start */ | ||
| 119 | #define SNDRV_SEQ_EVENT_SAMPLE_STOP 73 /* voice stop */ | ||
| 120 | #define SNDRV_SEQ_EVENT_SAMPLE_FREQ 74 /* playback frequency */ | ||
| 121 | #define SNDRV_SEQ_EVENT_SAMPLE_VOLUME 75 /* volume and balance */ | ||
| 122 | #define SNDRV_SEQ_EVENT_SAMPLE_LOOP 76 /* sample loop */ | ||
| 123 | #define SNDRV_SEQ_EVENT_SAMPLE_POSITION 77 /* sample position */ | ||
| 124 | #define SNDRV_SEQ_EVENT_SAMPLE_PRIVATE1 78 /* private (hardware dependent) event */ | ||
| 125 | 114 | ||
| 126 | /** user-defined events with fixed length | 115 | /** user-defined events with fixed length |
| 127 | * event data type = any | 116 | * event data type = any |
| @@ -137,28 +126,7 @@ | |||
| 137 | #define SNDRV_SEQ_EVENT_USR8 98 | 126 | #define SNDRV_SEQ_EVENT_USR8 98 |
| 138 | #define SNDRV_SEQ_EVENT_USR9 99 | 127 | #define SNDRV_SEQ_EVENT_USR9 99 |
| 139 | 128 | ||
| 140 | /** instrument layer | 129 | /* 100-118: instrument layer - obsoleted */ |
| 141 | * variable length data can be passed directly to the driver | ||
| 142 | */ | ||
| 143 | #define SNDRV_SEQ_EVENT_INSTR_BEGIN 100 /* begin of instrument management */ | ||
| 144 | #define SNDRV_SEQ_EVENT_INSTR_END 101 /* end of instrument management */ | ||
| 145 | #define SNDRV_SEQ_EVENT_INSTR_INFO 102 /* instrument interface info */ | ||
| 146 | #define SNDRV_SEQ_EVENT_INSTR_INFO_RESULT 103 /* result */ | ||
| 147 | #define SNDRV_SEQ_EVENT_INSTR_FINFO 104 /* get format info */ | ||
| 148 | #define SNDRV_SEQ_EVENT_INSTR_FINFO_RESULT 105 /* get format info */ | ||
| 149 | #define SNDRV_SEQ_EVENT_INSTR_RESET 106 /* reset instrument memory */ | ||
| 150 | #define SNDRV_SEQ_EVENT_INSTR_STATUS 107 /* instrument interface status */ | ||
| 151 | #define SNDRV_SEQ_EVENT_INSTR_STATUS_RESULT 108 /* result */ | ||
| 152 | #define SNDRV_SEQ_EVENT_INSTR_PUT 109 /* put instrument to port */ | ||
| 153 | #define SNDRV_SEQ_EVENT_INSTR_GET 110 /* get instrument from port */ | ||
| 154 | #define SNDRV_SEQ_EVENT_INSTR_GET_RESULT 111 /* result */ | ||
| 155 | #define SNDRV_SEQ_EVENT_INSTR_FREE 112 /* free instrument(s) */ | ||
| 156 | #define SNDRV_SEQ_EVENT_INSTR_LIST 113 /* instrument list */ | ||
| 157 | #define SNDRV_SEQ_EVENT_INSTR_LIST_RESULT 114 /* result */ | ||
| 158 | #define SNDRV_SEQ_EVENT_INSTR_CLUSTER 115 /* cluster parameters */ | ||
| 159 | #define SNDRV_SEQ_EVENT_INSTR_CLUSTER_GET 116 /* get cluster parameters */ | ||
| 160 | #define SNDRV_SEQ_EVENT_INSTR_CLUSTER_RESULT 117 /* result */ | ||
| 161 | #define SNDRV_SEQ_EVENT_INSTR_CHANGE 118 /* instrument change */ | ||
| 162 | /* 119-129: reserved */ | 130 | /* 119-129: reserved */ |
| 163 | 131 | ||
| 164 | /* 130-139: variable length events | 132 | /* 130-139: variable length events |
| @@ -258,78 +226,6 @@ struct snd_seq_ev_ext { | |||
| 258 | void *ptr; /* pointer to data (note: maybe 64-bit) */ | 226 | void *ptr; /* pointer to data (note: maybe 64-bit) */ |
| 259 | } __attribute__((packed)); | 227 | } __attribute__((packed)); |
| 260 | 228 | ||
| 261 | /* Instrument cluster type */ | ||
| 262 | typedef unsigned int snd_seq_instr_cluster_t; | ||
| 263 | |||
| 264 | /* Instrument type */ | ||
| 265 | struct snd_seq_instr { | ||
| 266 | snd_seq_instr_cluster_t cluster; | ||
| 267 | unsigned int std; /* the upper byte means a private instrument (owner - client #) */ | ||
| 268 | unsigned short bank; | ||
| 269 | unsigned short prg; | ||
| 270 | }; | ||
| 271 | |||
| 272 | /* sample number */ | ||
| 273 | struct snd_seq_ev_sample { | ||
| 274 | unsigned int std; | ||
| 275 | unsigned short bank; | ||
| 276 | unsigned short prg; | ||
| 277 | }; | ||
| 278 | |||
| 279 | /* sample cluster */ | ||
| 280 | struct snd_seq_ev_cluster { | ||
| 281 | snd_seq_instr_cluster_t cluster; | ||
| 282 | }; | ||
| 283 | |||
| 284 | /* sample position */ | ||
| 285 | typedef unsigned int snd_seq_position_t; /* playback position (in samples) * 16 */ | ||
| 286 | |||
| 287 | /* sample stop mode */ | ||
| 288 | enum { | ||
| 289 | SAMPLE_STOP_IMMEDIATELY = 0, /* terminate playing immediately */ | ||
| 290 | SAMPLE_STOP_VENVELOPE = 1, /* finish volume envelope */ | ||
| 291 | SAMPLE_STOP_LOOP = 2 /* terminate loop and finish wave */ | ||
| 292 | }; | ||
| 293 | |||
| 294 | /* sample frequency */ | ||
| 295 | typedef int snd_seq_frequency_t; /* playback frequency in HZ * 16 */ | ||
| 296 | |||
| 297 | /* sample volume control; if any value is set to -1 == do not change */ | ||
| 298 | struct snd_seq_ev_volume { | ||
| 299 | signed short volume; /* range: 0-16383 */ | ||
| 300 | signed short lr; /* left-right balance; range: 0-16383 */ | ||
| 301 | signed short fr; /* front-rear balance; range: 0-16383 */ | ||
| 302 | signed short du; /* down-up balance; range: 0-16383 */ | ||
| 303 | }; | ||
| 304 | |||
| 305 | /* simple loop redefinition */ | ||
| 306 | struct snd_seq_ev_loop { | ||
| 307 | unsigned int start; /* loop start (in samples) * 16 */ | ||
| 308 | unsigned int end; /* loop end (in samples) * 16 */ | ||
| 309 | }; | ||
| 310 | |||
| 311 | struct snd_seq_ev_sample_control { | ||
| 312 | unsigned char channel; | ||
| 313 | unsigned char unused1, unused2, unused3; /* pad */ | ||
| 314 | union { | ||
| 315 | struct snd_seq_ev_sample sample; | ||
| 316 | struct snd_seq_ev_cluster cluster; | ||
| 317 | snd_seq_position_t position; | ||
| 318 | int stop_mode; | ||
| 319 | snd_seq_frequency_t frequency; | ||
| 320 | struct snd_seq_ev_volume volume; | ||
| 321 | struct snd_seq_ev_loop loop; | ||
| 322 | unsigned char raw8[8]; | ||
| 323 | } param; | ||
| 324 | }; | ||
| 325 | |||
| 326 | |||
| 327 | |||
| 328 | /* INSTR_BEGIN event */ | ||
| 329 | struct snd_seq_ev_instr_begin { | ||
| 330 | int timeout; /* zero = forever, otherwise timeout in ms */ | ||
| 331 | }; | ||
| 332 | |||
| 333 | struct snd_seq_result { | 229 | struct snd_seq_result { |
| 334 | int event; /* processed event type */ | 230 | int event; /* processed event type */ |
| 335 | int result; | 231 | int result; |
| @@ -399,8 +295,6 @@ struct snd_seq_event { | |||
| 399 | struct snd_seq_addr addr; | 295 | struct snd_seq_addr addr; |
| 400 | struct snd_seq_connect connect; | 296 | struct snd_seq_connect connect; |
| 401 | struct snd_seq_result result; | 297 | struct snd_seq_result result; |
| 402 | struct snd_seq_ev_instr_begin instr_begin; | ||
| 403 | struct snd_seq_ev_sample_control sample; | ||
| 404 | struct snd_seq_ev_quote quote; | 298 | struct snd_seq_ev_quote quote; |
| 405 | } data; | 299 | } data; |
| 406 | }; | 300 | }; |
| @@ -441,8 +335,6 @@ struct snd_seq_event_bounce { | |||
| 441 | #define snd_seq_ev_is_user_type(ev) ((ev)->type >= 90 && (ev)->type < 99) | 335 | #define snd_seq_ev_is_user_type(ev) ((ev)->type >= 90 && (ev)->type < 99) |
| 442 | /* fixed length events: 0-99 */ | 336 | /* fixed length events: 0-99 */ |
| 443 | #define snd_seq_ev_is_fixed_type(ev) ((ev)->type < 100) | 337 | #define snd_seq_ev_is_fixed_type(ev) ((ev)->type < 100) |
| 444 | /* instrument layer events: 100-129 */ | ||
| 445 | #define snd_seq_ev_is_instr_type(ev) ((ev)->type >= 100 && (ev)->type < 130) | ||
| 446 | /* variable length events: 130-139 */ | 338 | /* variable length events: 130-139 */ |
| 447 | #define snd_seq_ev_is_variable_type(ev) ((ev)->type >= 130 && (ev)->type < 140) | 339 | #define snd_seq_ev_is_variable_type(ev) ((ev)->type >= 130 && (ev)->type < 140) |
| 448 | /* reserved for kernel */ | 340 | /* reserved for kernel */ |
| @@ -738,136 +630,6 @@ struct snd_seq_query_subs { | |||
| 738 | 630 | ||
| 739 | 631 | ||
| 740 | /* | 632 | /* |
| 741 | * Instrument abstraction layer | ||
| 742 | * - based on events | ||
| 743 | */ | ||
| 744 | |||
| 745 | /* instrument types */ | ||
| 746 | #define SNDRV_SEQ_INSTR_ATYPE_DATA 0 /* instrument data */ | ||
| 747 | #define SNDRV_SEQ_INSTR_ATYPE_ALIAS 1 /* instrument alias */ | ||
| 748 | |||
| 749 | /* instrument ASCII identifiers */ | ||
| 750 | #define SNDRV_SEQ_INSTR_ID_DLS1 "DLS1" | ||
| 751 | #define SNDRV_SEQ_INSTR_ID_DLS2 "DLS2" | ||
| 752 | #define SNDRV_SEQ_INSTR_ID_SIMPLE "Simple Wave" | ||
| 753 | #define SNDRV_SEQ_INSTR_ID_SOUNDFONT "SoundFont" | ||
| 754 | #define SNDRV_SEQ_INSTR_ID_GUS_PATCH "GUS Patch" | ||
| 755 | #define SNDRV_SEQ_INSTR_ID_INTERWAVE "InterWave FFFF" | ||
| 756 | #define SNDRV_SEQ_INSTR_ID_OPL2_3 "OPL2/3 FM" | ||
| 757 | #define SNDRV_SEQ_INSTR_ID_OPL4 "OPL4" | ||
| 758 | |||
| 759 | /* instrument types */ | ||
| 760 | #define SNDRV_SEQ_INSTR_TYPE0_DLS1 (1<<0) /* MIDI DLS v1 */ | ||
| 761 | #define SNDRV_SEQ_INSTR_TYPE0_DLS2 (1<<1) /* MIDI DLS v2 */ | ||
| 762 | #define SNDRV_SEQ_INSTR_TYPE1_SIMPLE (1<<0) /* Simple Wave */ | ||
| 763 | #define SNDRV_SEQ_INSTR_TYPE1_SOUNDFONT (1<<1) /* EMU SoundFont */ | ||
| 764 | #define SNDRV_SEQ_INSTR_TYPE1_GUS_PATCH (1<<2) /* Gravis UltraSound Patch */ | ||
| 765 | #define SNDRV_SEQ_INSTR_TYPE1_INTERWAVE (1<<3) /* InterWave FFFF */ | ||
| 766 | #define SNDRV_SEQ_INSTR_TYPE2_OPL2_3 (1<<0) /* Yamaha OPL2/3 FM */ | ||
| 767 | #define SNDRV_SEQ_INSTR_TYPE2_OPL4 (1<<1) /* Yamaha OPL4 */ | ||
| 768 | |||
| 769 | /* put commands */ | ||
| 770 | #define SNDRV_SEQ_INSTR_PUT_CMD_CREATE 0 | ||
| 771 | #define SNDRV_SEQ_INSTR_PUT_CMD_REPLACE 1 | ||
| 772 | #define SNDRV_SEQ_INSTR_PUT_CMD_MODIFY 2 | ||
| 773 | #define SNDRV_SEQ_INSTR_PUT_CMD_ADD 3 | ||
| 774 | #define SNDRV_SEQ_INSTR_PUT_CMD_REMOVE 4 | ||
| 775 | |||
| 776 | /* get commands */ | ||
| 777 | #define SNDRV_SEQ_INSTR_GET_CMD_FULL 0 | ||
| 778 | #define SNDRV_SEQ_INSTR_GET_CMD_PARTIAL 1 | ||
| 779 | |||
| 780 | /* query flags */ | ||
| 781 | #define SNDRV_SEQ_INSTR_QUERY_FOLLOW_ALIAS (1<<0) | ||
| 782 | |||
| 783 | /* free commands */ | ||
| 784 | #define SNDRV_SEQ_INSTR_FREE_CMD_ALL 0 | ||
| 785 | #define SNDRV_SEQ_INSTR_FREE_CMD_PRIVATE 1 | ||
| 786 | #define SNDRV_SEQ_INSTR_FREE_CMD_CLUSTER 2 | ||
| 787 | #define SNDRV_SEQ_INSTR_FREE_CMD_SINGLE 3 | ||
| 788 | |||
| 789 | /* size of ROM/RAM */ | ||
| 790 | typedef unsigned int snd_seq_instr_size_t; | ||
| 791 | |||
| 792 | /* INSTR_INFO */ | ||
| 793 | |||
| 794 | struct snd_seq_instr_info { | ||
| 795 | int result; /* operation result */ | ||
| 796 | unsigned int formats[8]; /* bitmap of supported formats */ | ||
| 797 | int ram_count; /* count of RAM banks */ | ||
| 798 | snd_seq_instr_size_t ram_sizes[16]; /* size of RAM banks */ | ||
| 799 | int rom_count; /* count of ROM banks */ | ||
| 800 | snd_seq_instr_size_t rom_sizes[8]; /* size of ROM banks */ | ||
| 801 | char reserved[128]; | ||
| 802 | }; | ||
| 803 | |||
| 804 | /* INSTR_STATUS */ | ||
| 805 | |||
| 806 | struct snd_seq_instr_status { | ||
| 807 | int result; /* operation result */ | ||
| 808 | snd_seq_instr_size_t free_ram[16]; /* free RAM in banks */ | ||
| 809 | int instrument_count; /* count of downloaded instruments */ | ||
| 810 | char reserved[128]; | ||
| 811 | }; | ||
| 812 | |||
| 813 | /* INSTR_FORMAT_INFO */ | ||
| 814 | |||
| 815 | struct snd_seq_instr_format_info { | ||
| 816 | char format[16]; /* format identifier - SNDRV_SEQ_INSTR_ID_* */ | ||
| 817 | unsigned int len; /* max data length (without this structure) */ | ||
| 818 | }; | ||
| 819 | |||
| 820 | struct snd_seq_instr_format_info_result { | ||
| 821 | int result; /* operation result */ | ||
| 822 | char format[16]; /* format identifier */ | ||
| 823 | unsigned int len; /* filled data length (without this structure) */ | ||
| 824 | }; | ||
| 825 | |||
| 826 | /* instrument data */ | ||
| 827 | struct snd_seq_instr_data { | ||
| 828 | char name[32]; /* instrument name */ | ||
| 829 | char reserved[16]; /* for the future use */ | ||
| 830 | int type; /* instrument type */ | ||
| 831 | union { | ||
| 832 | char format[16]; /* format identifier */ | ||
| 833 | struct snd_seq_instr alias; | ||
| 834 | } data; | ||
| 835 | }; | ||
| 836 | |||
| 837 | /* INSTR_PUT/GET, data are stored in one block (extended), header + data */ | ||
| 838 | |||
| 839 | struct snd_seq_instr_header { | ||
| 840 | union { | ||
| 841 | struct snd_seq_instr instr; | ||
| 842 | snd_seq_instr_cluster_t cluster; | ||
| 843 | } id; /* instrument identifier */ | ||
| 844 | unsigned int cmd; /* get/put/free command */ | ||
| 845 | unsigned int flags; /* query flags (only for get) */ | ||
| 846 | unsigned int len; /* real instrument data length (without header) */ | ||
| 847 | int result; /* operation result */ | ||
| 848 | char reserved[16]; /* for the future */ | ||
| 849 | struct snd_seq_instr_data data; /* instrument data (for put/get result) */ | ||
| 850 | }; | ||
| 851 | |||
| 852 | /* INSTR_CLUSTER_SET */ | ||
| 853 | |||
| 854 | struct snd_seq_instr_cluster_set { | ||
| 855 | snd_seq_instr_cluster_t cluster; /* cluster identifier */ | ||
| 856 | char name[32]; /* cluster name */ | ||
| 857 | int priority; /* cluster priority */ | ||
| 858 | char reserved[64]; /* for the future use */ | ||
| 859 | }; | ||
| 860 | |||
| 861 | /* INSTR_CLUSTER_GET */ | ||
| 862 | |||
| 863 | struct snd_seq_instr_cluster_get { | ||
| 864 | snd_seq_instr_cluster_t cluster; /* cluster identifier */ | ||
| 865 | char name[32]; /* cluster name */ | ||
| 866 | int priority; /* cluster priority */ | ||
| 867 | char reserved[64]; /* for the future use */ | ||
| 868 | }; | ||
| 869 | |||
| 870 | /* | ||
| 871 | * IOCTL commands | 633 | * IOCTL commands |
| 872 | */ | 634 | */ |
| 873 | 635 | ||
diff --git a/include/sound/gus.h b/include/sound/gus.h index e5433d8b78bc..841bb8df38c1 100644 --- a/include/sound/gus.h +++ b/include/sound/gus.h | |||
| @@ -27,13 +27,8 @@ | |||
| 27 | #include "timer.h" | 27 | #include "timer.h" |
| 28 | #include "seq_midi_emul.h" | 28 | #include "seq_midi_emul.h" |
| 29 | #include "seq_device.h" | 29 | #include "seq_device.h" |
| 30 | #include "ainstr_iw.h" | ||
| 31 | #include "ainstr_gf1.h" | ||
| 32 | #include "ainstr_simple.h" | ||
| 33 | #include <asm/io.h> | 30 | #include <asm/io.h> |
| 34 | 31 | ||
| 35 | #define SNDRV_SEQ_DEV_ID_GUS "gus-synth" | ||
| 36 | |||
| 37 | /* IO ports */ | 32 | /* IO ports */ |
| 38 | 33 | ||
| 39 | #define GUSP(gus, x) ((gus)->gf1.port + SNDRV_g_u_s_##x) | 34 | #define GUSP(gus, x) ((gus)->gf1.port + SNDRV_g_u_s_##x) |
| @@ -234,16 +229,6 @@ struct snd_gus_port { | |||
| 234 | 229 | ||
| 235 | struct snd_gus_voice; | 230 | struct snd_gus_voice; |
| 236 | 231 | ||
| 237 | struct snd_gus_sample_ops { | ||
| 238 | void (*sample_start)(struct snd_gus_card *gus, struct snd_gus_voice *voice, snd_seq_position_t position); | ||
| 239 | void (*sample_stop)(struct snd_gus_card *gus, struct snd_gus_voice *voice, int mode); | ||
| 240 | void (*sample_freq)(struct snd_gus_card *gus, struct snd_gus_voice *voice, snd_seq_frequency_t freq); | ||
| 241 | void (*sample_volume)(struct snd_gus_card *gus, struct snd_gus_voice *voice, struct snd_seq_ev_volume *volume); | ||
| 242 | void (*sample_loop)(struct snd_gus_card *card, struct snd_gus_voice *voice, struct snd_seq_ev_loop *loop); | ||
| 243 | void (*sample_pos)(struct snd_gus_card *card, struct snd_gus_voice *voice, snd_seq_position_t position); | ||
| 244 | void (*sample_private1)(struct snd_gus_card *card, struct snd_gus_voice *voice, unsigned char *data); | ||
| 245 | }; | ||
| 246 | |||
| 247 | #define SNDRV_GF1_VOICE_TYPE_PCM 0 | 232 | #define SNDRV_GF1_VOICE_TYPE_PCM 0 |
| 248 | #define SNDRV_GF1_VOICE_TYPE_SYNTH 1 | 233 | #define SNDRV_GF1_VOICE_TYPE_SYNTH 1 |
| 249 | #define SNDRV_GF1_VOICE_TYPE_MIDI 2 | 234 | #define SNDRV_GF1_VOICE_TYPE_MIDI 2 |
| @@ -284,12 +269,8 @@ struct snd_gus_voice { | |||
| 284 | 269 | ||
| 285 | struct snd_gus_sample_ops *sample_ops; | 270 | struct snd_gus_sample_ops *sample_ops; |
| 286 | 271 | ||
| 287 | struct snd_seq_instr instr; | ||
| 288 | |||
| 289 | /* running status / registers */ | 272 | /* running status / registers */ |
| 290 | 273 | ||
| 291 | struct snd_seq_ev_volume sample_volume; | ||
| 292 | |||
| 293 | unsigned short fc_register; | 274 | unsigned short fc_register; |
| 294 | unsigned short fc_lfo; | 275 | unsigned short fc_lfo; |
| 295 | unsigned short gf1_volume; | 276 | unsigned short gf1_volume; |
| @@ -382,10 +363,6 @@ struct snd_gf1 { | |||
| 382 | 363 | ||
| 383 | int seq_client; | 364 | int seq_client; |
| 384 | struct snd_gus_port seq_ports[4]; | 365 | struct snd_gus_port seq_ports[4]; |
| 385 | struct snd_seq_kinstr_list *ilist; | ||
| 386 | struct snd_iwffff_ops iwffff_ops; | ||
| 387 | struct snd_gf1_ops gf1_ops; | ||
| 388 | struct snd_simple_ops simple_ops; | ||
| 389 | 366 | ||
| 390 | /* timer */ | 367 | /* timer */ |
| 391 | 368 | ||
| @@ -458,8 +435,6 @@ struct snd_gus_card { | |||
| 458 | struct snd_rawmidi_substream *midi_substream_output; | 435 | struct snd_rawmidi_substream *midi_substream_output; |
| 459 | struct snd_rawmidi_substream *midi_substream_input; | 436 | struct snd_rawmidi_substream *midi_substream_input; |
| 460 | 437 | ||
| 461 | struct snd_seq_device *seq_dev; | ||
| 462 | |||
| 463 | spinlock_t reg_lock; | 438 | spinlock_t reg_lock; |
| 464 | spinlock_t voice_alloc; | 439 | spinlock_t voice_alloc; |
| 465 | spinlock_t active_voice_lock; | 440 | spinlock_t active_voice_lock; |
| @@ -647,48 +622,10 @@ void snd_gus_irq_profile_init(struct snd_gus_card *gus); | |||
| 647 | 622 | ||
| 648 | int snd_gf1_rawmidi_new(struct snd_gus_card * gus, int device, struct snd_rawmidi **rrawmidi); | 623 | int snd_gf1_rawmidi_new(struct snd_gus_card * gus, int device, struct snd_rawmidi **rrawmidi); |
| 649 | 624 | ||
| 650 | #if 0 | ||
| 651 | extern void snd_engine_instrument_register(unsigned short mode, | ||
| 652 | struct _SND_INSTRUMENT_VOICE_COMMANDS *voice_cmds, | ||
| 653 | struct _SND_INSTRUMENT_NOTE_COMMANDS *note_cmds, | ||
| 654 | struct _SND_INSTRUMENT_CHANNEL_COMMANDS *channel_cmds); | ||
| 655 | extern int snd_engine_instrument_register_ask(unsigned short mode); | ||
| 656 | #endif | ||
| 657 | |||
| 658 | /* gus_dram.c */ | 625 | /* gus_dram.c */ |
| 659 | int snd_gus_dram_write(struct snd_gus_card *gus, char __user *ptr, | 626 | int snd_gus_dram_write(struct snd_gus_card *gus, char __user *ptr, |
| 660 | unsigned int addr, unsigned int size); | 627 | unsigned int addr, unsigned int size); |
| 661 | int snd_gus_dram_read(struct snd_gus_card *gus, char __user *ptr, | 628 | int snd_gus_dram_read(struct snd_gus_card *gus, char __user *ptr, |
| 662 | unsigned int addr, unsigned int size, int rom); | 629 | unsigned int addr, unsigned int size, int rom); |
| 663 | 630 | ||
| 664 | #if defined(CONFIG_SND_SEQUENCER) || defined(CONFIG_SND_SEQUENCER_MODULE) | ||
| 665 | |||
| 666 | /* gus_sample.c */ | ||
| 667 | void snd_gus_sample_event(struct snd_seq_event *ev, struct snd_gus_port *p); | ||
| 668 | |||
| 669 | /* gus_simple.c */ | ||
| 670 | void snd_gf1_simple_init(struct snd_gus_voice *voice); | ||
| 671 | |||
| 672 | /* gus_instr.c */ | ||
| 673 | int snd_gus_iwffff_put_sample(void *private_data, struct iwffff_wave *wave, | ||
| 674 | char __user *data, long len, int atomic); | ||
| 675 | int snd_gus_iwffff_get_sample(void *private_data, struct iwffff_wave *wave, | ||
| 676 | char __user *data, long len, int atomic); | ||
| 677 | int snd_gus_iwffff_remove_sample(void *private_data, struct iwffff_wave *wave, | ||
| 678 | int atomic); | ||
| 679 | int snd_gus_gf1_put_sample(void *private_data, struct gf1_wave *wave, | ||
| 680 | char __user *data, long len, int atomic); | ||
| 681 | int snd_gus_gf1_get_sample(void *private_data, struct gf1_wave *wave, | ||
| 682 | char __user *data, long len, int atomic); | ||
| 683 | int snd_gus_gf1_remove_sample(void *private_data, struct gf1_wave *wave, | ||
| 684 | int atomic); | ||
| 685 | int snd_gus_simple_put_sample(void *private_data, struct simple_instrument *instr, | ||
| 686 | char __user *data, long len, int atomic); | ||
| 687 | int snd_gus_simple_get_sample(void *private_data, struct simple_instrument *instr, | ||
| 688 | char __user *data, long len, int atomic); | ||
| 689 | int snd_gus_simple_remove_sample(void *private_data, struct simple_instrument *instr, | ||
| 690 | int atomic); | ||
| 691 | |||
| 692 | #endif /* CONFIG_SND_SEQUENCER */ | ||
| 693 | |||
| 694 | #endif /* __SOUND_GUS_H */ | 631 | #endif /* __SOUND_GUS_H */ |
diff --git a/include/sound/seq_instr.h b/include/sound/seq_instr.h deleted file mode 100644 index 93b0c51df5b0..000000000000 --- a/include/sound/seq_instr.h +++ /dev/null | |||
| @@ -1,110 +0,0 @@ | |||
| 1 | #ifndef __SOUND_SEQ_INSTR_H | ||
| 2 | #define __SOUND_SEQ_INSTR_H | ||
| 3 | |||
| 4 | /* | ||
| 5 | * Main kernel header file for the ALSA sequencer | ||
| 6 | * Copyright (c) 1999 by Jaroslav Kysela <perex@perex.cz> | ||
| 7 | * | ||
| 8 | * | ||
| 9 | * This program is free software; you can redistribute it and/or modify | ||
| 10 | * it under the terms of the GNU General Public License as published by | ||
| 11 | * the Free Software Foundation; either version 2 of the License, or | ||
| 12 | * (at your option) any later version. | ||
| 13 | * | ||
| 14 | * This program is distributed in the hope that it will be useful, | ||
| 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 17 | * GNU General Public License for more details. | ||
| 18 | * | ||
| 19 | * You should have received a copy of the GNU General Public License | ||
| 20 | * along with this program; if not, write to the Free Software | ||
| 21 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 22 | * | ||
| 23 | */ | ||
| 24 | #include "seq_kernel.h" | ||
| 25 | |||
| 26 | /* Instrument cluster */ | ||
| 27 | struct snd_seq_kcluster { | ||
| 28 | snd_seq_instr_cluster_t cluster; | ||
| 29 | char name[32]; | ||
| 30 | int priority; | ||
| 31 | struct snd_seq_kcluster *next; | ||
| 32 | }; | ||
| 33 | |||
| 34 | /* return pointer to private data */ | ||
| 35 | #define KINSTR_DATA(kinstr) (void *)(((char *)kinstr) + sizeof(struct snd_seq_kinstr)) | ||
| 36 | |||
| 37 | /* Instrument structure */ | ||
| 38 | struct snd_seq_kinstr { | ||
| 39 | struct snd_seq_instr instr; | ||
| 40 | char name[32]; | ||
| 41 | int type; /* instrument type */ | ||
| 42 | int use; /* use count */ | ||
| 43 | int busy; /* not useable */ | ||
| 44 | int add_len; /* additional length */ | ||
| 45 | struct snd_seq_kinstr_ops *ops; /* operations */ | ||
| 46 | struct snd_seq_kinstr *next; | ||
| 47 | }; | ||
| 48 | |||
| 49 | #define SNDRV_SEQ_INSTR_HASH_SIZE 32 | ||
| 50 | |||
| 51 | /* Instrument flags */ | ||
| 52 | #define SNDRV_SEQ_INSTR_FLG_DIRECT (1<<0) /* accept only direct events */ | ||
| 53 | |||
| 54 | /* List of all instruments */ | ||
| 55 | struct snd_seq_kinstr_list { | ||
| 56 | struct snd_seq_kinstr *hash[SNDRV_SEQ_INSTR_HASH_SIZE]; | ||
| 57 | int count; /* count of all instruments */ | ||
| 58 | |||
| 59 | struct snd_seq_kcluster *chash[SNDRV_SEQ_INSTR_HASH_SIZE]; | ||
| 60 | int ccount; /* count of all clusters */ | ||
| 61 | |||
| 62 | int owner; /* current owner of the instrument list */ | ||
| 63 | unsigned int flags; | ||
| 64 | |||
| 65 | spinlock_t lock; | ||
| 66 | spinlock_t ops_lock; | ||
| 67 | struct mutex ops_mutex; | ||
| 68 | unsigned long ops_flags; | ||
| 69 | }; | ||
| 70 | |||
| 71 | #define SNDRV_SEQ_INSTR_NOTIFY_REMOVE 0 | ||
| 72 | #define SNDRV_SEQ_INSTR_NOTIFY_CHANGE 1 | ||
| 73 | |||
| 74 | struct snd_seq_kinstr_ops { | ||
| 75 | void *private_data; | ||
| 76 | long add_len; /* additional length */ | ||
| 77 | char *instr_type; | ||
| 78 | int (*info)(void *private_data, char *info_data, long len); | ||
| 79 | int (*put)(void *private_data, struct snd_seq_kinstr *kinstr, | ||
| 80 | char __user *instr_data, long len, int atomic, int cmd); | ||
| 81 | int (*get)(void *private_data, struct snd_seq_kinstr *kinstr, | ||
| 82 | char __user *instr_data, long len, int atomic, int cmd); | ||
| 83 | int (*get_size)(void *private_data, struct snd_seq_kinstr *kinstr, long *size); | ||
| 84 | int (*remove)(void *private_data, struct snd_seq_kinstr *kinstr, int atomic); | ||
| 85 | void (*notify)(void *private_data, struct snd_seq_kinstr *kinstr, int what); | ||
| 86 | struct snd_seq_kinstr_ops *next; | ||
| 87 | }; | ||
| 88 | |||
| 89 | |||
| 90 | /* instrument operations */ | ||
| 91 | struct snd_seq_kinstr_list *snd_seq_instr_list_new(void); | ||
| 92 | void snd_seq_instr_list_free(struct snd_seq_kinstr_list **list); | ||
| 93 | int snd_seq_instr_list_free_cond(struct snd_seq_kinstr_list *list, | ||
| 94 | struct snd_seq_instr_header *ifree, | ||
| 95 | int client, | ||
| 96 | int atomic); | ||
| 97 | struct snd_seq_kinstr *snd_seq_instr_find(struct snd_seq_kinstr_list *list, | ||
| 98 | struct snd_seq_instr *instr, | ||
| 99 | int exact, | ||
| 100 | int follow_alias); | ||
| 101 | void snd_seq_instr_free_use(struct snd_seq_kinstr_list *list, | ||
| 102 | struct snd_seq_kinstr *instr); | ||
| 103 | int snd_seq_instr_event(struct snd_seq_kinstr_ops *ops, | ||
| 104 | struct snd_seq_kinstr_list *list, | ||
| 105 | struct snd_seq_event *ev, | ||
| 106 | int client, | ||
| 107 | int atomic, | ||
| 108 | int hop); | ||
| 109 | |||
| 110 | #endif /* __SOUND_SEQ_INSTR_H */ | ||
diff --git a/include/sound/trident.h b/include/sound/trident.h index 9752243241e5..9f191a0a1e19 100644 --- a/include/sound/trident.h +++ b/include/sound/trident.h | |||
| @@ -26,19 +26,12 @@ | |||
| 26 | #include "pcm.h" | 26 | #include "pcm.h" |
| 27 | #include "mpu401.h" | 27 | #include "mpu401.h" |
| 28 | #include "ac97_codec.h" | 28 | #include "ac97_codec.h" |
| 29 | #include "seq_midi_emul.h" | ||
| 30 | #include "seq_device.h" | ||
| 31 | #include "util_mem.h" | 29 | #include "util_mem.h" |
| 32 | //#include "ainstr_iw.h" | ||
| 33 | //#include "ainstr_gf1.h" | ||
| 34 | #include "ainstr_simple.h" | ||
| 35 | 30 | ||
| 36 | #define TRIDENT_DEVICE_ID_DX ((PCI_VENDOR_ID_TRIDENT<<16)|PCI_DEVICE_ID_TRIDENT_4DWAVE_DX) | 31 | #define TRIDENT_DEVICE_ID_DX ((PCI_VENDOR_ID_TRIDENT<<16)|PCI_DEVICE_ID_TRIDENT_4DWAVE_DX) |
| 37 | #define TRIDENT_DEVICE_ID_NX ((PCI_VENDOR_ID_TRIDENT<<16)|PCI_DEVICE_ID_TRIDENT_4DWAVE_NX) | 32 | #define TRIDENT_DEVICE_ID_NX ((PCI_VENDOR_ID_TRIDENT<<16)|PCI_DEVICE_ID_TRIDENT_4DWAVE_NX) |
| 38 | #define TRIDENT_DEVICE_ID_SI7018 ((PCI_VENDOR_ID_SI<<16)|PCI_DEVICE_ID_SI_7018) | 33 | #define TRIDENT_DEVICE_ID_SI7018 ((PCI_VENDOR_ID_SI<<16)|PCI_DEVICE_ID_SI_7018) |
| 39 | 34 | ||
| 40 | #define SNDRV_SEQ_DEV_ID_TRIDENT "trident-synth" | ||
| 41 | |||
| 42 | #define SNDRV_TRIDENT_VOICE_TYPE_PCM 0 | 35 | #define SNDRV_TRIDENT_VOICE_TYPE_PCM 0 |
| 43 | #define SNDRV_TRIDENT_VOICE_TYPE_SYNTH 1 | 36 | #define SNDRV_TRIDENT_VOICE_TYPE_SYNTH 1 |
| 44 | #define SNDRV_TRIDENT_VOICE_TYPE_MIDI 2 | 37 | #define SNDRV_TRIDENT_VOICE_TYPE_MIDI 2 |
| @@ -257,16 +250,6 @@ struct snd_trident; | |||
| 257 | struct snd_trident_voice; | 250 | struct snd_trident_voice; |
| 258 | struct snd_trident_pcm_mixer; | 251 | struct snd_trident_pcm_mixer; |
| 259 | 252 | ||
| 260 | struct snd_trident_sample_ops { | ||
| 261 | void (*sample_start)(struct snd_trident *gus, struct snd_trident_voice *voice, snd_seq_position_t position); | ||
| 262 | void (*sample_stop)(struct snd_trident *gus, struct snd_trident_voice *voice, int mode); | ||
| 263 | void (*sample_freq)(struct snd_trident *gus, struct snd_trident_voice *voice, snd_seq_frequency_t freq); | ||
| 264 | void (*sample_volume)(struct snd_trident *gus, struct snd_trident_voice *voice, struct snd_seq_ev_volume *volume); | ||
| 265 | void (*sample_loop)(struct snd_trident *card, struct snd_trident_voice *voice, struct snd_seq_ev_loop *loop); | ||
| 266 | void (*sample_pos)(struct snd_trident *card, struct snd_trident_voice *voice, snd_seq_position_t position); | ||
| 267 | void (*sample_private1)(struct snd_trident *card, struct snd_trident_voice *voice, unsigned char *data); | ||
| 268 | }; | ||
| 269 | |||
| 270 | struct snd_trident_port { | 253 | struct snd_trident_port { |
| 271 | struct snd_midi_channel_set * chset; | 254 | struct snd_midi_channel_set * chset; |
| 272 | struct snd_trident * trident; | 255 | struct snd_trident * trident; |
| @@ -300,7 +283,6 @@ struct snd_trident_voice { | |||
| 300 | unsigned char port; | 283 | unsigned char port; |
| 301 | unsigned char index; | 284 | unsigned char index; |
| 302 | 285 | ||
| 303 | struct snd_seq_instr instr; | ||
| 304 | struct snd_trident_sample_ops *sample_ops; | 286 | struct snd_trident_sample_ops *sample_ops; |
| 305 | 287 | ||
| 306 | /* channel parameters */ | 288 | /* channel parameters */ |
| @@ -354,9 +336,6 @@ struct snd_4dwave { | |||
| 354 | int seq_client; | 336 | int seq_client; |
| 355 | 337 | ||
| 356 | struct snd_trident_port seq_ports[4]; | 338 | struct snd_trident_port seq_ports[4]; |
| 357 | struct snd_simple_ops simple_ops; | ||
| 358 | struct snd_seq_kinstr_list *ilist; | ||
| 359 | |||
| 360 | struct snd_trident_voice voices[64]; | 339 | struct snd_trident_voice voices[64]; |
| 361 | 340 | ||
| 362 | int ChanSynthCount; /* number of allocated synth channels */ | 341 | int ChanSynthCount; /* number of allocated synth channels */ |
| @@ -416,7 +395,6 @@ struct snd_trident { | |||
| 416 | struct snd_pcm *foldback; /* Foldback PCM */ | 395 | struct snd_pcm *foldback; /* Foldback PCM */ |
| 417 | struct snd_pcm *spdif; /* SPDIF PCM */ | 396 | struct snd_pcm *spdif; /* SPDIF PCM */ |
| 418 | struct snd_rawmidi *rmidi; | 397 | struct snd_rawmidi *rmidi; |
| 419 | struct snd_seq_device *seq_dev; | ||
| 420 | 398 | ||
| 421 | struct snd_ac97_bus *ac97_bus; | 399 | struct snd_ac97_bus *ac97_bus; |
| 422 | struct snd_ac97 *ac97; | 400 | struct snd_ac97 *ac97; |
diff --git a/sound/core/seq/Makefile b/sound/core/seq/Makefile index ceef14afee30..069593717fba 100644 --- a/sound/core/seq/Makefile +++ b/sound/core/seq/Makefile | |||
| @@ -3,7 +3,6 @@ | |||
| 3 | # Copyright (c) 1999 by Jaroslav Kysela <perex@perex.cz> | 3 | # Copyright (c) 1999 by Jaroslav Kysela <perex@perex.cz> |
| 4 | # | 4 | # |
| 5 | 5 | ||
| 6 | obj-$(CONFIG_SND) += instr/ | ||
| 7 | ifeq ($(CONFIG_SND_SEQUENCER_OSS),y) | 6 | ifeq ($(CONFIG_SND_SEQUENCER_OSS),y) |
| 8 | obj-$(CONFIG_SND_SEQUENCER) += oss/ | 7 | obj-$(CONFIG_SND_SEQUENCER) += oss/ |
| 9 | endif | 8 | endif |
| @@ -15,7 +14,6 @@ snd-seq-objs := seq.o seq_lock.o seq_clientmgr.o seq_memory.o seq_queue.o \ | |||
| 15 | snd-seq-midi-objs := seq_midi.o | 14 | snd-seq-midi-objs := seq_midi.o |
| 16 | snd-seq-midi-emul-objs := seq_midi_emul.o | 15 | snd-seq-midi-emul-objs := seq_midi_emul.o |
| 17 | snd-seq-midi-event-objs := seq_midi_event.o | 16 | snd-seq-midi-event-objs := seq_midi_event.o |
| 18 | snd-seq-instr-objs := seq_instr.o | ||
| 19 | snd-seq-dummy-objs := seq_dummy.o | 17 | snd-seq-dummy-objs := seq_dummy.o |
| 20 | snd-seq-virmidi-objs := seq_virmidi.o | 18 | snd-seq-virmidi-objs := seq_virmidi.o |
| 21 | 19 | ||
| @@ -36,9 +34,7 @@ obj-$(CONFIG_SND_SEQ_DUMMY) += snd-seq-dummy.o | |||
| 36 | # Toplevel Module Dependency | 34 | # Toplevel Module Dependency |
| 37 | obj-$(CONFIG_SND_VIRMIDI) += snd-seq-virmidi.o snd-seq-midi-event.o | 35 | obj-$(CONFIG_SND_VIRMIDI) += snd-seq-virmidi.o snd-seq-midi-event.o |
| 38 | obj-$(call sequencer,$(CONFIG_SND_RAWMIDI)) += snd-seq-midi.o snd-seq-midi-event.o | 36 | obj-$(call sequencer,$(CONFIG_SND_RAWMIDI)) += snd-seq-midi.o snd-seq-midi-event.o |
| 39 | obj-$(call sequencer,$(CONFIG_SND_OPL3_LIB)) += snd-seq-midi-event.o snd-seq-midi-emul.o snd-seq-instr.o | 37 | obj-$(call sequencer,$(CONFIG_SND_OPL3_LIB)) += snd-seq-midi-event.o snd-seq-midi-emul.o |
| 40 | obj-$(call sequencer,$(CONFIG_SND_OPL4_LIB)) += snd-seq-midi-event.o snd-seq-midi-emul.o snd-seq-instr.o | 38 | obj-$(call sequencer,$(CONFIG_SND_OPL4_LIB)) += snd-seq-midi-event.o snd-seq-midi-emul.o |
| 41 | obj-$(call sequencer,$(CONFIG_SND_GUS_SYNTH)) += snd-seq-midi-emul.o snd-seq-instr.o | ||
| 42 | obj-$(call sequencer,$(CONFIG_SND_SBAWE)) += snd-seq-midi-emul.o snd-seq-virmidi.o | 39 | obj-$(call sequencer,$(CONFIG_SND_SBAWE)) += snd-seq-midi-emul.o snd-seq-virmidi.o |
| 43 | obj-$(call sequencer,$(CONFIG_SND_EMU10K1)) += snd-seq-midi-emul.o snd-seq-virmidi.o | 40 | obj-$(call sequencer,$(CONFIG_SND_EMU10K1)) += snd-seq-midi-emul.o snd-seq-virmidi.o |
| 44 | obj-$(call sequencer,$(CONFIG_SND_TRIDENT)) += snd-seq-midi-emul.o snd-seq-instr.o | ||
diff --git a/sound/core/seq/instr/Makefile b/sound/core/seq/instr/Makefile deleted file mode 100644 index 608960364813..000000000000 --- a/sound/core/seq/instr/Makefile +++ /dev/null | |||
| @@ -1,23 +0,0 @@ | |||
| 1 | # | ||
| 2 | # Makefile for ALSA | ||
| 3 | # Copyright (c) 1999 by Jaroslav Kysela <perex@perex.cz> | ||
| 4 | # | ||
| 5 | |||
| 6 | snd-ainstr-fm-objs := ainstr_fm.o | ||
| 7 | snd-ainstr-simple-objs := ainstr_simple.o | ||
| 8 | snd-ainstr-gf1-objs := ainstr_gf1.o | ||
| 9 | snd-ainstr-iw-objs := ainstr_iw.o | ||
| 10 | |||
| 11 | # | ||
| 12 | # this function returns: | ||
| 13 | # "m" - CONFIG_SND_SEQUENCER is m | ||
| 14 | # <empty string> - CONFIG_SND_SEQUENCER is undefined | ||
| 15 | # otherwise parameter #1 value | ||
| 16 | # | ||
| 17 | sequencer = $(if $(subst y,,$(CONFIG_SND_SEQUENCER)),$(if $(1),m),$(if $(CONFIG_SND_SEQUENCER),$(1))) | ||
| 18 | |||
| 19 | # Toplevel Module Dependency | ||
| 20 | obj-$(call sequencer,$(CONFIG_SND_OPL3_LIB)) += snd-ainstr-fm.o | ||
| 21 | obj-$(call sequencer,$(CONFIG_SND_OPL4_LIB)) += snd-ainstr-fm.o | ||
| 22 | obj-$(call sequencer,$(CONFIG_SND_GUS_SYNTH)) += snd-ainstr-gf1.o snd-ainstr-simple.o snd-ainstr-iw.o | ||
| 23 | obj-$(call sequencer,$(CONFIG_SND_TRIDENT)) += snd-ainstr-simple.o | ||
diff --git a/sound/core/seq/instr/ainstr_fm.c b/sound/core/seq/instr/ainstr_fm.c deleted file mode 100644 index f80fab8f2ed1..000000000000 --- a/sound/core/seq/instr/ainstr_fm.c +++ /dev/null | |||
| @@ -1,155 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * FM (OPL2/3) Instrument routines | ||
| 3 | * Copyright (c) 2000 Uros Bizjak <uros@kss-loka.si> | ||
| 4 | * | ||
| 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. | ||
| 9 | * | ||
| 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. | ||
| 14 | * | ||
| 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 | ||
| 18 | * | ||
| 19 | */ | ||
| 20 | |||
| 21 | #include <sound/driver.h> | ||
| 22 | #include <linux/init.h> | ||
| 23 | #include <sound/core.h> | ||
| 24 | #include <sound/ainstr_fm.h> | ||
| 25 | #include <sound/initval.h> | ||
| 26 | #include <asm/uaccess.h> | ||
| 27 | |||
| 28 | MODULE_AUTHOR("Uros Bizjak <uros@kss-loka.si>"); | ||
| 29 | MODULE_DESCRIPTION("Advanced Linux Sound Architecture FM Instrument support."); | ||
| 30 | MODULE_LICENSE("GPL"); | ||
| 31 | |||
| 32 | static int snd_seq_fm_put(void *private_data, struct snd_seq_kinstr *instr, | ||
| 33 | char __user *instr_data, long len, int atomic, int cmd) | ||
| 34 | { | ||
| 35 | struct fm_instrument *ip; | ||
| 36 | struct fm_xinstrument ix; | ||
| 37 | int idx; | ||
| 38 | |||
| 39 | if (cmd != SNDRV_SEQ_INSTR_PUT_CMD_CREATE) | ||
| 40 | return -EINVAL; | ||
| 41 | /* copy instrument data */ | ||
| 42 | if (len < (long)sizeof(ix)) | ||
| 43 | return -EINVAL; | ||
| 44 | if (copy_from_user(&ix, instr_data, sizeof(ix))) | ||
| 45 | return -EFAULT; | ||
| 46 | if (ix.stype != FM_STRU_INSTR) | ||
| 47 | return -EINVAL; | ||
| 48 | ip = (struct fm_instrument *)KINSTR_DATA(instr); | ||
| 49 | ip->share_id[0] = le32_to_cpu(ix.share_id[0]); | ||
| 50 | ip->share_id[1] = le32_to_cpu(ix.share_id[1]); | ||
| 51 | ip->share_id[2] = le32_to_cpu(ix.share_id[2]); | ||
| 52 | ip->share_id[3] = le32_to_cpu(ix.share_id[3]); | ||
| 53 | ip->type = ix.type; | ||
| 54 | for (idx = 0; idx < 4; idx++) { | ||
| 55 | ip->op[idx].am_vib = ix.op[idx].am_vib; | ||
| 56 | ip->op[idx].ksl_level = ix.op[idx].ksl_level; | ||
| 57 | ip->op[idx].attack_decay = ix.op[idx].attack_decay; | ||
| 58 | ip->op[idx].sustain_release = ix.op[idx].sustain_release; | ||
| 59 | ip->op[idx].wave_select = ix.op[idx].wave_select; | ||
| 60 | } | ||
| 61 | for (idx = 0; idx < 2; idx++) { | ||
| 62 | ip->feedback_connection[idx] = ix.feedback_connection[idx]; | ||
| 63 | } | ||
| 64 | ip->echo_delay = ix.echo_delay; | ||
| 65 | ip->echo_atten = ix.echo_atten; | ||
| 66 | ip->chorus_spread = ix.chorus_spread; | ||
| 67 | ip->trnsps = ix.trnsps; | ||
| 68 | ip->fix_dur = ix.fix_dur; | ||
| 69 | ip->modes = ix.modes; | ||
| 70 | ip->fix_key = ix.fix_key; | ||
| 71 | return 0; | ||
| 72 | } | ||
| 73 | |||
| 74 | static int snd_seq_fm_get(void *private_data, struct snd_seq_kinstr *instr, | ||
| 75 | char __user *instr_data, long len, int atomic, | ||
| 76 | int cmd) | ||
| 77 | { | ||
| 78 | struct fm_instrument *ip; | ||
| 79 | struct fm_xinstrument ix; | ||
| 80 | int idx; | ||
| 81 | |||
| 82 | if (cmd != SNDRV_SEQ_INSTR_GET_CMD_FULL) | ||
| 83 | return -EINVAL; | ||
| 84 | if (len < (long)sizeof(ix)) | ||
| 85 | return -ENOMEM; | ||
| 86 | memset(&ix, 0, sizeof(ix)); | ||
| 87 | ip = (struct fm_instrument *)KINSTR_DATA(instr); | ||
| 88 | ix.stype = FM_STRU_INSTR; | ||
| 89 | ix.share_id[0] = cpu_to_le32(ip->share_id[0]); | ||
| 90 | ix.share_id[1] = cpu_to_le32(ip->share_id[1]); | ||
| 91 | ix.share_id[2] = cpu_to_le32(ip->share_id[2]); | ||
| 92 | ix.share_id[3] = cpu_to_le32(ip->share_id[3]); | ||
| 93 | ix.type = ip->type; | ||
| 94 | for (idx = 0; idx < 4; idx++) { | ||
| 95 | ix.op[idx].am_vib = ip->op[idx].am_vib; | ||
| 96 | ix.op[idx].ksl_level = ip->op[idx].ksl_level; | ||
| 97 | ix.op[idx].attack_decay = ip->op[idx].attack_decay; | ||
| 98 | ix.op[idx].sustain_release = ip->op[idx].sustain_release; | ||
| 99 | ix.op[idx].wave_select = ip->op[idx].wave_select; | ||
| 100 | } | ||
| 101 | for (idx = 0; idx < 2; idx++) { | ||
| 102 | ix.feedback_connection[idx] = ip->feedback_connection[idx]; | ||
| 103 | } | ||
| 104 | if (copy_to_user(instr_data, &ix, sizeof(ix))) | ||
| 105 | return -EFAULT; | ||
| 106 | ix.echo_delay = ip->echo_delay; | ||
| 107 | ix.echo_atten = ip->echo_atten; | ||
| 108 | ix.chorus_spread = ip->chorus_spread; | ||
| 109 | ix.trnsps = ip->trnsps; | ||
| 110 | ix.fix_dur = ip->fix_dur; | ||
| 111 | ix.modes = ip->modes; | ||
| 112 | ix.fix_key = ip->fix_key; | ||
| 113 | return 0; | ||
| 114 | } | ||
| 115 | |||
| 116 | static int snd_seq_fm_get_size(void *private_data, struct snd_seq_kinstr *instr, | ||
| 117 | long *size) | ||
| 118 | { | ||
| 119 | *size = sizeof(struct fm_xinstrument); | ||
| 120 | return 0; | ||
| 121 | } | ||
| 122 | |||
| 123 | int snd_seq_fm_init(struct snd_seq_kinstr_ops *ops, | ||
| 124 | struct snd_seq_kinstr_ops *next) | ||
| 125 | { | ||
| 126 | memset(ops, 0, sizeof(*ops)); | ||
| 127 | // ops->private_data = private_data; | ||
| 128 | ops->add_len = sizeof(struct fm_instrument); | ||
| 129 | ops->instr_type = SNDRV_SEQ_INSTR_ID_OPL2_3; | ||
| 130 | ops->put = snd_seq_fm_put; | ||
| 131 | ops->get = snd_seq_fm_get; | ||
| 132 | ops->get_size = snd_seq_fm_get_size; | ||
| 133 | // ops->remove = snd_seq_fm_remove; | ||
| 134 | // ops->notify = snd_seq_fm_notify; | ||
| 135 | ops->next = next; | ||
| 136 | return 0; | ||
| 137 | } | ||
| 138 | |||
| 139 | /* | ||
| 140 | * Init part | ||
| 141 | */ | ||
| 142 | |||
| 143 | static int __init alsa_ainstr_fm_init(void) | ||
| 144 | { | ||
| 145 | return 0; | ||
| 146 | } | ||
| 147 | |||
| 148 | static void __exit alsa_ainstr_fm_exit(void) | ||
| 149 | { | ||
| 150 | } | ||
| 151 | |||
| 152 | module_init(alsa_ainstr_fm_init) | ||
| 153 | module_exit(alsa_ainstr_fm_exit) | ||
| 154 | |||
| 155 | EXPORT_SYMBOL(snd_seq_fm_init); | ||
diff --git a/sound/core/seq/instr/ainstr_gf1.c b/sound/core/seq/instr/ainstr_gf1.c deleted file mode 100644 index 49400262b1eb..000000000000 --- a/sound/core/seq/instr/ainstr_gf1.c +++ /dev/null | |||
| @@ -1,359 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * GF1 (GUS) Patch - Instrument routines | ||
| 3 | * Copyright (c) 1999 by Jaroslav Kysela <perex@perex.cz> | ||
| 4 | * | ||
| 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. | ||
| 9 | * | ||
| 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. | ||
| 14 | * | ||
| 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 | ||
| 18 | * | ||
| 19 | */ | ||
| 20 | |||
| 21 | #include <sound/driver.h> | ||
| 22 | #include <linux/init.h> | ||
| 23 | #include <linux/slab.h> | ||
| 24 | #include <sound/core.h> | ||
| 25 | #include <sound/ainstr_gf1.h> | ||
| 26 | #include <sound/initval.h> | ||
| 27 | #include <asm/uaccess.h> | ||
| 28 | |||
| 29 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); | ||
| 30 | MODULE_DESCRIPTION("Advanced Linux Sound Architecture GF1 (GUS) Patch support."); | ||
| 31 | MODULE_LICENSE("GPL"); | ||
| 32 | |||
| 33 | static unsigned int snd_seq_gf1_size(unsigned int size, unsigned int format) | ||
| 34 | { | ||
| 35 | unsigned int result = size; | ||
| 36 | |||
| 37 | if (format & GF1_WAVE_16BIT) | ||
| 38 | result <<= 1; | ||
| 39 | if (format & GF1_WAVE_STEREO) | ||
| 40 | result <<= 1; | ||
| 41 | return format; | ||
| 42 | } | ||
| 43 | |||
| 44 | static int snd_seq_gf1_copy_wave_from_stream(struct snd_gf1_ops *ops, | ||
| 45 | struct gf1_instrument *ip, | ||
| 46 | char __user **data, | ||
| 47 | long *len, | ||
| 48 | int atomic) | ||
| 49 | { | ||
| 50 | struct gf1_wave *wp, *prev; | ||
| 51 | struct gf1_xwave xp; | ||
| 52 | int err; | ||
| 53 | gfp_t gfp_mask; | ||
| 54 | unsigned int real_size; | ||
| 55 | |||
| 56 | gfp_mask = atomic ? GFP_ATOMIC : GFP_KERNEL; | ||
| 57 | if (*len < (long)sizeof(xp)) | ||
| 58 | return -EINVAL; | ||
| 59 | if (copy_from_user(&xp, *data, sizeof(xp))) | ||
| 60 | return -EFAULT; | ||
| 61 | *data += sizeof(xp); | ||
| 62 | *len -= sizeof(xp); | ||
| 63 | wp = kzalloc(sizeof(*wp), gfp_mask); | ||
| 64 | if (wp == NULL) | ||
| 65 | return -ENOMEM; | ||
| 66 | wp->share_id[0] = le32_to_cpu(xp.share_id[0]); | ||
| 67 | wp->share_id[1] = le32_to_cpu(xp.share_id[1]); | ||
| 68 | wp->share_id[2] = le32_to_cpu(xp.share_id[2]); | ||
| 69 | wp->share_id[3] = le32_to_cpu(xp.share_id[3]); | ||
| 70 | wp->format = le32_to_cpu(xp.format); | ||
| 71 | wp->size = le32_to_cpu(xp.size); | ||
| 72 | wp->start = le32_to_cpu(xp.start); | ||
| 73 | wp->loop_start = le32_to_cpu(xp.loop_start); | ||
| 74 | wp->loop_end = le32_to_cpu(xp.loop_end); | ||
| 75 | wp->loop_repeat = le16_to_cpu(xp.loop_repeat); | ||
| 76 | wp->flags = xp.flags; | ||
| 77 | wp->sample_rate = le32_to_cpu(xp.sample_rate); | ||
| 78 | wp->low_frequency = le32_to_cpu(xp.low_frequency); | ||
| 79 | wp->high_frequency = le32_to_cpu(xp.high_frequency); | ||
| 80 | wp->root_frequency = le32_to_cpu(xp.root_frequency); | ||
| 81 | wp->tune = le16_to_cpu(xp.tune); | ||
| 82 | wp->balance = xp.balance; | ||
| 83 | memcpy(wp->envelope_rate, xp.envelope_rate, 6); | ||
| 84 | memcpy(wp->envelope_offset, xp.envelope_offset, 6); | ||
| 85 | wp->tremolo_sweep = xp.tremolo_sweep; | ||
| 86 | wp->tremolo_rate = xp.tremolo_rate; | ||
| 87 | wp->tremolo_depth = xp.tremolo_depth; | ||
| 88 | wp->vibrato_sweep = xp.vibrato_sweep; | ||
| 89 | wp->vibrato_rate = xp.vibrato_rate; | ||
| 90 | wp->vibrato_depth = xp.vibrato_depth; | ||
| 91 | wp->scale_frequency = le16_to_cpu(xp.scale_frequency); | ||
| 92 | wp->scale_factor = le16_to_cpu(xp.scale_factor); | ||
| 93 | real_size = snd_seq_gf1_size(wp->size, wp->format); | ||
| 94 | if ((long)real_size > *len) { | ||
| 95 | kfree(wp); | ||
| 96 | return -ENOMEM; | ||
| 97 | } | ||
| 98 | if (ops->put_sample) { | ||
| 99 | err = ops->put_sample(ops->private_data, wp, | ||
| 100 | *data, real_size, atomic); | ||
| 101 | if (err < 0) { | ||
| 102 | kfree(wp); | ||
| 103 | return err; | ||
| 104 | } | ||
| 105 | } | ||
| 106 | *data += real_size; | ||
| 107 | *len -= real_size; | ||
| 108 | prev = ip->wave; | ||
| 109 | if (prev) { | ||
| 110 | while (prev->next) prev = prev->next; | ||
| 111 | prev->next = wp; | ||
| 112 | } else { | ||
| 113 | ip->wave = wp; | ||
| 114 | } | ||
| 115 | return 0; | ||
| 116 | } | ||
| 117 | |||
| 118 | static void snd_seq_gf1_wave_free(struct snd_gf1_ops *ops, | ||
| 119 | struct gf1_wave *wave, | ||
| 120 | int atomic) | ||
| 121 | { | ||
| 122 | if (ops->remove_sample) | ||
| 123 | ops->remove_sample(ops->private_data, wave, atomic); | ||
| 124 | kfree(wave); | ||
| 125 | } | ||
| 126 | |||
| 127 | static void snd_seq_gf1_instr_free(struct snd_gf1_ops *ops, | ||
| 128 | struct gf1_instrument *ip, | ||
| 129 | int atomic) | ||
| 130 | { | ||
| 131 | struct gf1_wave *wave; | ||
| 132 | |||
| 133 | while ((wave = ip->wave) != NULL) { | ||
| 134 | ip->wave = wave->next; | ||
| 135 | snd_seq_gf1_wave_free(ops, wave, atomic); | ||
| 136 | } | ||
| 137 | } | ||
| 138 | |||
| 139 | static int snd_seq_gf1_put(void *private_data, struct snd_seq_kinstr *instr, | ||
| 140 | char __user *instr_data, long len, int atomic, | ||
| 141 | int cmd) | ||
| 142 | { | ||
| 143 | struct snd_gf1_ops *ops = private_data; | ||
| 144 | struct gf1_instrument *ip; | ||
| 145 | struct gf1_xinstrument ix; | ||
| 146 | int err; | ||
| 147 | gfp_t gfp_mask; | ||
| 148 | |||
| 149 | if (cmd != SNDRV_SEQ_INSTR_PUT_CMD_CREATE) | ||
| 150 | return -EINVAL; | ||
| 151 | gfp_mask = atomic ? GFP_ATOMIC : GFP_KERNEL; | ||
| 152 | /* copy instrument data */ | ||
| 153 | if (len < (long)sizeof(ix)) | ||
| 154 | return -EINVAL; | ||
| 155 | if (copy_from_user(&ix, instr_data, sizeof(ix))) | ||
| 156 | return -EFAULT; | ||
| 157 | if (ix.stype != GF1_STRU_INSTR) | ||
| 158 | return -EINVAL; | ||
| 159 | instr_data += sizeof(ix); | ||
| 160 | len -= sizeof(ix); | ||
| 161 | ip = (struct gf1_instrument *)KINSTR_DATA(instr); | ||
| 162 | ip->exclusion = le16_to_cpu(ix.exclusion); | ||
| 163 | ip->exclusion_group = le16_to_cpu(ix.exclusion_group); | ||
| 164 | ip->effect1 = ix.effect1; | ||
| 165 | ip->effect1_depth = ix.effect1_depth; | ||
| 166 | ip->effect2 = ix.effect2; | ||
| 167 | ip->effect2_depth = ix.effect2_depth; | ||
| 168 | /* copy layers */ | ||
| 169 | while (len > (long)sizeof(__u32)) { | ||
| 170 | __u32 stype; | ||
| 171 | |||
| 172 | if (copy_from_user(&stype, instr_data, sizeof(stype))) | ||
| 173 | return -EFAULT; | ||
| 174 | if (stype != GF1_STRU_WAVE) { | ||
| 175 | snd_seq_gf1_instr_free(ops, ip, atomic); | ||
| 176 | return -EINVAL; | ||
| 177 | } | ||
| 178 | err = snd_seq_gf1_copy_wave_from_stream(ops, | ||
| 179 | ip, | ||
| 180 | &instr_data, | ||
| 181 | &len, | ||
| 182 | atomic); | ||
| 183 | if (err < 0) { | ||
| 184 | snd_seq_gf1_instr_free(ops, ip, atomic); | ||
| 185 | return err; | ||
| 186 | } | ||
| 187 | } | ||
| 188 | return 0; | ||
| 189 | } | ||
| 190 | |||
| 191 | static int snd_seq_gf1_copy_wave_to_stream(struct snd_gf1_ops *ops, | ||
| 192 | struct gf1_instrument *ip, | ||
| 193 | char __user **data, | ||
| 194 | long *len, | ||
| 195 | int atomic) | ||
| 196 | { | ||
| 197 | struct gf1_wave *wp; | ||
| 198 | struct gf1_xwave xp; | ||
| 199 | int err; | ||
| 200 | unsigned int real_size; | ||
| 201 | |||
| 202 | for (wp = ip->wave; wp; wp = wp->next) { | ||
| 203 | if (*len < (long)sizeof(xp)) | ||
| 204 | return -ENOMEM; | ||
| 205 | memset(&xp, 0, sizeof(xp)); | ||
| 206 | xp.stype = GF1_STRU_WAVE; | ||
| 207 | xp.share_id[0] = cpu_to_le32(wp->share_id[0]); | ||
| 208 | xp.share_id[1] = cpu_to_le32(wp->share_id[1]); | ||
| 209 | xp.share_id[2] = cpu_to_le32(wp->share_id[2]); | ||
| 210 | xp.share_id[3] = cpu_to_le32(wp->share_id[3]); | ||
| 211 | xp.format = cpu_to_le32(wp->format); | ||
| 212 | xp.size = cpu_to_le32(wp->size); | ||
| 213 | xp.start = cpu_to_le32(wp->start); | ||
| 214 | xp.loop_start = cpu_to_le32(wp->loop_start); | ||
| 215 | xp.loop_end = cpu_to_le32(wp->loop_end); | ||
| 216 | xp.loop_repeat = cpu_to_le32(wp->loop_repeat); | ||
| 217 | xp.flags = wp->flags; | ||
| 218 | xp.sample_rate = cpu_to_le32(wp->sample_rate); | ||
| 219 | xp.low_frequency = cpu_to_le32(wp->low_frequency); | ||
| 220 | xp.high_frequency = cpu_to_le32(wp->high_frequency); | ||
| 221 | xp.root_frequency = cpu_to_le32(wp->root_frequency); | ||
| 222 | xp.tune = cpu_to_le16(wp->tune); | ||
| 223 | xp.balance = wp->balance; | ||
| 224 | memcpy(xp.envelope_rate, wp->envelope_rate, 6); | ||
| 225 | memcpy(xp.envelope_offset, wp->envelope_offset, 6); | ||
| 226 | xp.tremolo_sweep = wp->tremolo_sweep; | ||
| 227 | xp.tremolo_rate = wp->tremolo_rate; | ||
| 228 | xp.tremolo_depth = wp->tremolo_depth; | ||
| 229 | xp.vibrato_sweep = wp->vibrato_sweep; | ||
| 230 | xp.vibrato_rate = wp->vibrato_rate; | ||
| 231 | xp.vibrato_depth = wp->vibrato_depth; | ||
| 232 | xp.scale_frequency = cpu_to_le16(wp->scale_frequency); | ||
| 233 | xp.scale_factor = cpu_to_le16(wp->scale_factor); | ||
| 234 | if (copy_to_user(*data, &xp, sizeof(xp))) | ||
| 235 | return -EFAULT; | ||
| 236 | *data += sizeof(xp); | ||
| 237 | *len -= sizeof(xp); | ||
| 238 | real_size = snd_seq_gf1_size(wp->size, wp->format); | ||
| 239 | if (*len < (long)real_size) | ||
| 240 | return -ENOMEM; | ||
| 241 | if (ops->get_sample) { | ||
| 242 | err = ops->get_sample(ops->private_data, wp, | ||
| 243 | *data, real_size, atomic); | ||
| 244 | if (err < 0) | ||
| 245 | return err; | ||
| 246 | } | ||
| 247 | *data += wp->size; | ||
| 248 | *len -= wp->size; | ||
| 249 | } | ||
| 250 | return 0; | ||
| 251 | } | ||
| 252 | |||
| 253 | static int snd_seq_gf1_get(void *private_data, struct snd_seq_kinstr *instr, | ||
| 254 | char __user *instr_data, long len, int atomic, | ||
| 255 | int cmd) | ||
| 256 | { | ||
| 257 | struct snd_gf1_ops *ops = private_data; | ||
| 258 | struct gf1_instrument *ip; | ||
| 259 | struct gf1_xinstrument ix; | ||
| 260 | |||
| 261 | if (cmd != SNDRV_SEQ_INSTR_GET_CMD_FULL) | ||
| 262 | return -EINVAL; | ||
| 263 | if (len < (long)sizeof(ix)) | ||
| 264 | return -ENOMEM; | ||
| 265 | memset(&ix, 0, sizeof(ix)); | ||
| 266 | ip = (struct gf1_instrument *)KINSTR_DATA(instr); | ||
| 267 | ix.stype = GF1_STRU_INSTR; | ||
| 268 | ix.exclusion = cpu_to_le16(ip->exclusion); | ||
| 269 | ix.exclusion_group = cpu_to_le16(ip->exclusion_group); | ||
| 270 | ix.effect1 = cpu_to_le16(ip->effect1); | ||
| 271 | ix.effect1_depth = cpu_to_le16(ip->effect1_depth); | ||
| 272 | ix.effect2 = ip->effect2; | ||
| 273 | ix.effect2_depth = ip->effect2_depth; | ||
| 274 | if (copy_to_user(instr_data, &ix, sizeof(ix))) | ||
| 275 | return -EFAULT; | ||
| 276 | instr_data += sizeof(ix); | ||
| 277 | len -= sizeof(ix); | ||
| 278 | return snd_seq_gf1_copy_wave_to_stream(ops, | ||
| 279 | ip, | ||
| 280 | &instr_data, | ||
| 281 | &len, | ||
| 282 | atomic); | ||
| 283 | } | ||
| 284 | |||
| 285 | static int snd_seq_gf1_get_size(void *private_data, struct snd_seq_kinstr *instr, | ||
| 286 | long *size) | ||
| 287 | { | ||
| 288 | long result; | ||
| 289 | struct gf1_instrument *ip; | ||
| 290 | struct gf1_wave *wp; | ||
| 291 | |||
| 292 | *size = 0; | ||
| 293 | ip = (struct gf1_instrument *)KINSTR_DATA(instr); | ||
| 294 | result = sizeof(struct gf1_xinstrument); | ||
| 295 | for (wp = ip->wave; wp; wp = wp->next) { | ||
| 296 | result += sizeof(struct gf1_xwave); | ||
| 297 | result += wp->size; | ||
| 298 | } | ||
| 299 | *size = result; | ||
| 300 | return 0; | ||
| 301 | } | ||
| 302 | |||
| 303 | static int snd_seq_gf1_remove(void *private_data, | ||
| 304 | struct snd_seq_kinstr *instr, | ||
| 305 | int atomic) | ||
| 306 | { | ||
| 307 | struct snd_gf1_ops *ops = private_data; | ||
| 308 | struct gf1_instrument *ip; | ||
| 309 | |||
| 310 | ip = (struct gf1_instrument *)KINSTR_DATA(instr); | ||
| 311 | snd_seq_gf1_instr_free(ops, ip, atomic); | ||
| 312 | return 0; | ||
| 313 | } | ||
| 314 | |||
| 315 | static void snd_seq_gf1_notify(void *private_data, | ||
| 316 | struct snd_seq_kinstr *instr, | ||
| 317 | int what) | ||
| 318 | { | ||
| 319 | struct snd_gf1_ops *ops = private_data; | ||
| 320 | |||
| 321 | if (ops->notify) | ||
| 322 | ops->notify(ops->private_data, instr, what); | ||
| 323 | } | ||
| 324 | |||
| 325 | int snd_seq_gf1_init(struct snd_gf1_ops *ops, | ||
| 326 | void *private_data, | ||
| 327 | struct snd_seq_kinstr_ops *next) | ||
| 328 | { | ||
| 329 | memset(ops, 0, sizeof(*ops)); | ||
| 330 | ops->private_data = private_data; | ||
| 331 | ops->kops.private_data = ops; | ||
| 332 | ops->kops.add_len = sizeof(struct gf1_instrument); | ||
| 333 | ops->kops.instr_type = SNDRV_SEQ_INSTR_ID_GUS_PATCH; | ||
| 334 | ops->kops.put = snd_seq_gf1_put; | ||
| 335 | ops->kops.get = snd_seq_gf1_get; | ||
| 336 | ops->kops.get_size = snd_seq_gf1_get_size; | ||
| 337 | ops->kops.remove = snd_seq_gf1_remove; | ||
| 338 | ops->kops.notify = snd_seq_gf1_notify; | ||
| 339 | ops->kops.next = next; | ||
| 340 | return 0; | ||
| 341 | } | ||
| 342 | |||
| 343 | /* | ||
| 344 | * Init part | ||
| 345 | */ | ||
| 346 | |||
| 347 | static int __init alsa_ainstr_gf1_init(void) | ||
| 348 | { | ||
| 349 | return 0; | ||
| 350 | } | ||
| 351 | |||
| 352 | static void __exit alsa_ainstr_gf1_exit(void) | ||
| 353 | { | ||
| 354 | } | ||
| 355 | |||
| 356 | module_init(alsa_ainstr_gf1_init) | ||
| 357 | module_exit(alsa_ainstr_gf1_exit) | ||
| 358 | |||
| 359 | EXPORT_SYMBOL(snd_seq_gf1_init); | ||
diff --git a/sound/core/seq/instr/ainstr_iw.c b/sound/core/seq/instr/ainstr_iw.c deleted file mode 100644 index 6c40eb73fa9f..000000000000 --- a/sound/core/seq/instr/ainstr_iw.c +++ /dev/null | |||
| @@ -1,623 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * IWFFFF - AMD InterWave (tm) - Instrument routines | ||
| 3 | * Copyright (c) 1999 by Jaroslav Kysela <perex@perex.cz> | ||
| 4 | * | ||
| 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. | ||
| 9 | * | ||
| 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. | ||
| 14 | * | ||
| 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 | ||
| 18 | * | ||
| 19 | */ | ||
| 20 | |||
| 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> | ||
| 28 | |||
| 29 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); | ||
| 30 | MODULE_DESCRIPTION("Advanced Linux Sound Architecture IWFFFF support."); | ||
| 31 | MODULE_LICENSE("GPL"); | ||
| 32 | |||
| 33 | static unsigned int snd_seq_iwffff_size(unsigned int size, unsigned int format) | ||
| 34 | { | ||
| 35 | unsigned int result = size; | ||
| 36 | |||
| 37 | if (format & IWFFFF_WAVE_16BIT) | ||
| 38 | result <<= 1; | ||
| 39 | if (format & IWFFFF_WAVE_STEREO) | ||
| 40 | result <<= 1; | ||
| 41 | return result; | ||
| 42 | } | ||
| 43 | |||
| 44 | static void snd_seq_iwffff_copy_lfo_from_stream(struct iwffff_lfo *fp, | ||
| 45 | struct iwffff_xlfo *fx) | ||
| 46 | { | ||
| 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; | ||
| 52 | } | ||
| 53 | |||
| 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, | ||
| 58 | char __user **data, | ||
| 59 | long *len, | ||
| 60 | gfp_t gfp_mask) | ||
| 61 | { | ||
| 62 | __u32 stype; | ||
| 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; | ||
| 67 | int points_size, idx; | ||
| 68 | |||
| 69 | ep->flags = ex->flags; | ||
| 70 | ep->mode = ex->mode; | ||
| 71 | ep->index = ex->index; | ||
| 72 | rp_last = NULL; | ||
| 73 | while (1) { | ||
| 74 | if (*len < (long)sizeof(__u32)) | ||
| 75 | return -EINVAL; | ||
| 76 | if (copy_from_user(&stype, *data, sizeof(stype))) | ||
| 77 | return -EFAULT; | ||
| 78 | if (stype == IWFFFF_STRU_WAVE) | ||
| 79 | return 0; | ||
| 80 | if (req_stype != stype) { | ||
| 81 | if (stype == IWFFFF_STRU_ENV_RECP || | ||
| 82 | stype == IWFFFF_STRU_ENV_RECV) | ||
| 83 | return 0; | ||
| 84 | } | ||
| 85 | if (*len < (long)sizeof(rx)) | ||
| 86 | return -EINVAL; | ||
| 87 | if (copy_from_user(&rx, *data, sizeof(rx))) | ||
| 88 | return -EFAULT; | ||
| 89 | *data += sizeof(rx); | ||
| 90 | *len -= sizeof(rx); | ||
| 91 | points_size = (le16_to_cpu(rx.nattack) + le16_to_cpu(rx.nrelease)) * 2 * sizeof(__u16); | ||
| 92 | if (points_size > *len) | ||
| 93 | return -EINVAL; | ||
| 94 | rp = kzalloc(sizeof(*rp) + points_size, gfp_mask); | ||
| 95 | if (rp == NULL) | ||
| 96 | return -ENOMEM; | ||
| 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))) | ||
| 106 | return -EFAULT; | ||
| 107 | *data += sizeof(px); | ||
| 108 | *len -= sizeof(px); | ||
| 109 | pp->offset = le16_to_cpu(px.offset); | ||
| 110 | pp->rate = le16_to_cpu(px.rate); | ||
| 111 | } | ||
| 112 | if (ep->record == NULL) { | ||
| 113 | ep->record = rp; | ||
| 114 | } else { | ||
| 115 | rp_last = rp; | ||
| 116 | } | ||
| 117 | rp_last = rp; | ||
| 118 | } | ||
| 119 | return 0; | ||
| 120 | } | ||
| 121 | |||
| 122 | static int snd_seq_iwffff_copy_wave_from_stream(struct snd_iwffff_ops *ops, | ||
| 123 | struct iwffff_layer *lp, | ||
| 124 | char __user **data, | ||
| 125 | long *len, | ||
| 126 | int atomic) | ||
| 127 | { | ||
| 128 | struct iwffff_wave *wp, *prev; | ||
| 129 | struct iwffff_xwave xp; | ||
| 130 | int err; | ||
| 131 | gfp_t gfp_mask; | ||
| 132 | unsigned int real_size; | ||
| 133 | |||
| 134 | gfp_mask = atomic ? GFP_ATOMIC : GFP_KERNEL; | ||
| 135 | if (*len < (long)sizeof(xp)) | ||
| 136 | return -EINVAL; | ||
| 137 | if (copy_from_user(&xp, *data, sizeof(xp))) | ||
| 138 | return -EFAULT; | ||
| 139 | *data += sizeof(xp); | ||
| 140 | *len -= sizeof(xp); | ||
| 141 | wp = kzalloc(sizeof(*wp), gfp_mask); | ||
| 142 | if (wp == NULL) | ||
| 143 | return -ENOMEM; | ||
| 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) { | ||
| 162 | kfree(wp); | ||
| 163 | return -ENOMEM; | ||
| 164 | } | ||
| 165 | } | ||
| 166 | if (ops->put_sample) { | ||
| 167 | err = ops->put_sample(ops->private_data, wp, | ||
| 168 | *data, real_size, atomic); | ||
| 169 | if (err < 0) { | ||
| 170 | kfree(wp); | ||
| 171 | return err; | ||
| 172 | } | ||
| 173 | } | ||
| 174 | if (!(wp->format & IWFFFF_WAVE_ROM)) { | ||
| 175 | *data += real_size; | ||
| 176 | *len -= real_size; | ||
| 177 | } | ||
| 178 | prev = lp->wave; | ||
| 179 | if (prev) { | ||
| 180 | while (prev->next) prev = prev->next; | ||
| 181 | prev->next = wp; | ||
| 182 | } else { | ||
| 183 | lp->wave = wp; | ||
| 184 | } | ||
| 185 | return 0; | ||
| 186 | } | ||
| 187 | |||
| 188 | static void snd_seq_iwffff_env_free(struct snd_iwffff_ops *ops, | ||
| 189 | struct iwffff_env *env, | ||
| 190 | int atomic) | ||
| 191 | { | ||
| 192 | struct iwffff_env_record *rec; | ||
| 193 | |||
| 194 | while ((rec = env->record) != NULL) { | ||
| 195 | env->record = rec->next; | ||
| 196 | kfree(rec); | ||
| 197 | } | ||
| 198 | } | ||
| 199 | |||
| 200 | static void snd_seq_iwffff_wave_free(struct snd_iwffff_ops *ops, | ||
| 201 | struct iwffff_wave *wave, | ||
| 202 | int atomic) | ||
| 203 | { | ||
| 204 | if (ops->remove_sample) | ||
| 205 | ops->remove_sample(ops->private_data, wave, atomic); | ||
| 206 | kfree(wave); | ||
| 207 | } | ||
| 208 | |||
| 209 | static void snd_seq_iwffff_instr_free(struct snd_iwffff_ops *ops, | ||
| 210 | struct iwffff_instrument *ip, | ||
| 211 | int atomic) | ||
| 212 | { | ||
| 213 | struct iwffff_layer *layer; | ||
| 214 | struct iwffff_wave *wave; | ||
| 215 | |||
| 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); | ||
| 223 | } | ||
| 224 | kfree(layer); | ||
| 225 | } | ||
| 226 | } | ||
| 227 | |||
| 228 | static int snd_seq_iwffff_put(void *private_data, struct snd_seq_kinstr *instr, | ||
| 229 | char __user *instr_data, long len, int atomic, | ||
| 230 | int cmd) | ||
| 231 | { | ||
| 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; | ||
| 237 | int err; | ||
| 238 | gfp_t gfp_mask; | ||
| 239 | |||
| 240 | if (cmd != SNDRV_SEQ_INSTR_PUT_CMD_CREATE) | ||
| 241 | return -EINVAL; | ||
| 242 | gfp_mask = atomic ? GFP_ATOMIC : GFP_KERNEL; | ||
| 243 | /* copy instrument data */ | ||
| 244 | if (len < (long)sizeof(ix)) | ||
| 245 | return -EINVAL; | ||
| 246 | if (copy_from_user(&ix, instr_data, sizeof(ix))) | ||
| 247 | return -EFAULT; | ||
| 248 | if (ix.stype != IWFFFF_STRU_INSTR) | ||
| 249 | return -EINVAL; | ||
| 250 | instr_data += sizeof(ix); | ||
| 251 | len -= 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; | ||
| 260 | /* copy layers */ | ||
| 261 | prev_lp = NULL; | ||
| 262 | while (len > 0) { | ||
| 263 | if (len < (long)sizeof(struct iwffff_xlayer)) { | ||
| 264 | snd_seq_iwffff_instr_free(ops, ip, atomic); | ||
| 265 | return -EINVAL; | ||
| 266 | } | ||
| 267 | if (copy_from_user(&lx, instr_data, sizeof(lx))) | ||
| 268 | return -EFAULT; | ||
| 269 | instr_data += sizeof(lx); | ||
| 270 | len -= sizeof(lx); | ||
| 271 | if (lx.stype != IWFFFF_STRU_LAYER) { | ||
| 272 | snd_seq_iwffff_instr_free(ops, ip, atomic); | ||
| 273 | return -EINVAL; | ||
| 274 | } | ||
| 275 | lp = kzalloc(sizeof(*lp), gfp_mask); | ||
| 276 | if (lp == NULL) { | ||
| 277 | snd_seq_iwffff_instr_free(ops, ip, atomic); | ||
| 278 | return -ENOMEM; | ||
| 279 | } | ||
| 280 | if (prev_lp) { | ||
| 281 | prev_lp->next = lp; | ||
| 282 | } else { | ||
| 283 | ip->layer = lp; | ||
| 284 | } | ||
| 285 | prev_lp = lp; | ||
| 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; | ||
| 291 | lp->pan = lx.pan; | ||
| 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, | ||
| 299 | lp, | ||
| 300 | &lp->penv, &lx.penv, | ||
| 301 | &instr_data, &len, | ||
| 302 | gfp_mask); | ||
| 303 | if (err < 0) { | ||
| 304 | snd_seq_iwffff_instr_free(ops, ip, atomic); | ||
| 305 | return err; | ||
| 306 | } | ||
| 307 | err = snd_seq_iwffff_copy_env_from_stream(IWFFFF_STRU_ENV_RECV, | ||
| 308 | lp, | ||
| 309 | &lp->venv, &lx.venv, | ||
| 310 | &instr_data, &len, | ||
| 311 | gfp_mask); | ||
| 312 | if (err < 0) { | ||
| 313 | snd_seq_iwffff_instr_free(ops, ip, atomic); | ||
| 314 | return err; | ||
| 315 | } | ||
| 316 | while (len > (long)sizeof(__u32)) { | ||
| 317 | __u32 stype; | ||
| 318 | |||
| 319 | if (copy_from_user(&stype, instr_data, sizeof(stype))) | ||
| 320 | return -EFAULT; | ||
| 321 | if (stype != IWFFFF_STRU_WAVE) | ||
| 322 | break; | ||
| 323 | err = snd_seq_iwffff_copy_wave_from_stream(ops, | ||
| 324 | lp, | ||
| 325 | &instr_data, | ||
| 326 | &len, | ||
| 327 | atomic); | ||
| 328 | if (err < 0) { | ||
| 329 | snd_seq_iwffff_instr_free(ops, ip, atomic); | ||
| 330 | return err; | ||
| 331 | } | ||
| 332 | } | ||
| 333 | } | ||
| 334 | return 0; | ||
| 335 | } | ||
| 336 | |||
| 337 | static void snd_seq_iwffff_copy_lfo_to_stream(struct iwffff_xlfo *fx, | ||
| 338 | struct iwffff_lfo *fp) | ||
| 339 | { | ||
| 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; | ||
| 345 | } | ||
| 346 | |||
| 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, | ||
| 351 | char __user **data, | ||
| 352 | long *len) | ||
| 353 | { | ||
| 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; | ||
| 359 | |||
| 360 | ex->flags = ep->flags; | ||
| 361 | ex->mode = ep->mode; | ||
| 362 | ex->index = ep->index; | ||
| 363 | for (rp = ep->record; rp; rp = rp->next) { | ||
| 364 | if (*len < (long)sizeof(rx)) | ||
| 365 | return -ENOMEM; | ||
| 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))) | ||
| 375 | return -EFAULT; | ||
| 376 | *data += sizeof(rx); | ||
| 377 | *len -= sizeof(rx); | ||
| 378 | points_size = (rp->nattack + rp->nrelease) * 2 * sizeof(__u16); | ||
| 379 | if (*len < points_size) | ||
| 380 | return -ENOMEM; | ||
| 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))) | ||
| 386 | return -EFAULT; | ||
| 387 | *data += sizeof(px); | ||
| 388 | *len -= sizeof(px); | ||
| 389 | } | ||
| 390 | } | ||
| 391 | return 0; | ||
| 392 | } | ||
| 393 | |||
| 394 | static int snd_seq_iwffff_copy_wave_to_stream(struct snd_iwffff_ops *ops, | ||
| 395 | struct iwffff_layer *lp, | ||
| 396 | char __user **data, | ||
| 397 | long *len, | ||
| 398 | int atomic) | ||
| 399 | { | ||
| 400 | struct iwffff_wave *wp; | ||
| 401 | struct iwffff_xwave xp; | ||
| 402 | int err; | ||
| 403 | unsigned int real_size; | ||
| 404 | |||
| 405 | for (wp = lp->wave; wp; wp = wp->next) { | ||
| 406 | if (*len < (long)sizeof(xp)) | ||
| 407 | return -ENOMEM; | ||
| 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))) | ||
| 427 | return -EFAULT; | ||
| 428 | *data += sizeof(xp); | ||
| 429 | *len -= 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) | ||
| 433 | return -ENOMEM; | ||
| 434 | } | ||
| 435 | if (ops->get_sample) { | ||
| 436 | err = ops->get_sample(ops->private_data, wp, | ||
| 437 | *data, real_size, atomic); | ||
| 438 | if (err < 0) | ||
| 439 | return err; | ||
| 440 | } | ||
| 441 | if (!(wp->format & IWFFFF_WAVE_ROM)) { | ||
| 442 | *data += real_size; | ||
| 443 | *len -= real_size; | ||
| 444 | } | ||
| 445 | } | ||
| 446 | return 0; | ||
| 447 | } | ||
| 448 | |||
| 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) | ||
| 451 | { | ||
| 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; | ||
| 458 | int err; | ||
| 459 | |||
| 460 | if (cmd != SNDRV_SEQ_INSTR_GET_CMD_FULL) | ||
| 461 | return -EINVAL; | ||
| 462 | if (len < (long)sizeof(ix)) | ||
| 463 | return -ENOMEM; | ||
| 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))) | ||
| 475 | return -EFAULT; | ||
| 476 | instr_data += sizeof(ix); | ||
| 477 | len -= sizeof(ix); | ||
| 478 | for (lp = ip->layer; lp; lp = lp->next) { | ||
| 479 | if (len < (long)sizeof(lx)) | ||
| 480 | return -ENOMEM; | ||
| 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; | ||
| 488 | lx.pan = lp->pan; | ||
| 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); | ||
| 495 | len -= sizeof(lx); | ||
| 496 | err = snd_seq_iwffff_copy_env_to_stream(IWFFFF_STRU_ENV_RECP, | ||
| 497 | lp, | ||
| 498 | &lx.penv, &lp->penv, | ||
| 499 | &instr_data, &len); | ||
| 500 | if (err < 0) | ||
| 501 | return err; | ||
| 502 | err = snd_seq_iwffff_copy_env_to_stream(IWFFFF_STRU_ENV_RECV, | ||
| 503 | lp, | ||
| 504 | &lx.venv, &lp->venv, | ||
| 505 | &instr_data, &len); | ||
| 506 | if (err < 0) | ||
| 507 | return err; | ||
| 508 | /* layer structure updating is now finished */ | ||
| 509 | if (copy_to_user(layer_instr_data, &lx, sizeof(lx))) | ||
| 510 | return -EFAULT; | ||
| 511 | err = snd_seq_iwffff_copy_wave_to_stream(ops, | ||
| 512 | lp, | ||
| 513 | &instr_data, | ||
| 514 | &len, | ||
| 515 | atomic); | ||
| 516 | if (err < 0) | ||
| 517 | return err; | ||
| 518 | } | ||
| 519 | return 0; | ||
| 520 | } | ||
| 521 | |||
| 522 | static long snd_seq_iwffff_env_size_in_stream(struct iwffff_env *ep) | ||
| 523 | { | ||
| 524 | long result = 0; | ||
| 525 | struct iwffff_env_record *rp; | ||
| 526 | |||
| 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); | ||
| 530 | } | ||
| 531 | return 0; | ||
| 532 | } | ||
| 533 | |||
| 534 | static long snd_seq_iwffff_wave_size_in_stream(struct iwffff_layer *lp) | ||
| 535 | { | ||
| 536 | long result = 0; | ||
| 537 | struct iwffff_wave *wp; | ||
| 538 | |||
| 539 | for (wp = lp->wave; wp; wp = wp->next) { | ||
| 540 | result += sizeof(struct iwffff_xwave); | ||
| 541 | if (!(wp->format & IWFFFF_WAVE_ROM)) | ||
| 542 | result += wp->size; | ||
| 543 | } | ||
| 544 | return result; | ||
| 545 | } | ||
| 546 | |||
| 547 | static int snd_seq_iwffff_get_size(void *private_data, struct snd_seq_kinstr *instr, | ||
| 548 | long *size) | ||
| 549 | { | ||
| 550 | long result; | ||
| 551 | struct iwffff_instrument *ip; | ||
| 552 | struct iwffff_layer *lp; | ||
| 553 | |||
| 554 | *size = 0; | ||
| 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); | ||
| 562 | } | ||
| 563 | *size = result; | ||
| 564 | return 0; | ||
| 565 | } | ||
| 566 | |||
| 567 | static int snd_seq_iwffff_remove(void *private_data, | ||
| 568 | struct snd_seq_kinstr *instr, | ||
| 569 | int atomic) | ||
| 570 | { | ||
| 571 | struct snd_iwffff_ops *ops = private_data; | ||
| 572 | struct iwffff_instrument *ip; | ||
| 573 | |||
| 574 | ip = (struct iwffff_instrument *)KINSTR_DATA(instr); | ||
| 575 | snd_seq_iwffff_instr_free(ops, ip, atomic); | ||
| 576 | return 0; | ||
| 577 | } | ||
| 578 | |||
| 579 | static void snd_seq_iwffff_notify(void *private_data, | ||
| 580 | struct snd_seq_kinstr *instr, | ||
| 581 | int what) | ||
| 582 | { | ||
| 583 | struct snd_iwffff_ops *ops = private_data; | ||
| 584 | |||
| 585 | if (ops->notify) | ||
| 586 | ops->notify(ops->private_data, instr, what); | ||
| 587 | } | ||
| 588 | |||
| 589 | int snd_seq_iwffff_init(struct snd_iwffff_ops *ops, | ||
| 590 | void *private_data, | ||
| 591 | struct snd_seq_kinstr_ops *next) | ||
| 592 | { | ||
| 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; | ||
| 604 | return 0; | ||
| 605 | } | ||
| 606 | |||
| 607 | /* | ||
| 608 | * Init part | ||
| 609 | */ | ||
| 610 | |||
| 611 | static int __init alsa_ainstr_iw_init(void) | ||
| 612 | { | ||
| 613 | return 0; | ||
| 614 | } | ||
| 615 | |||
| 616 | static void __exit alsa_ainstr_iw_exit(void) | ||
| 617 | { | ||
| 618 | } | ||
| 619 | |||
| 620 | module_init(alsa_ainstr_iw_init) | ||
| 621 | module_exit(alsa_ainstr_iw_exit) | ||
| 622 | |||
| 623 | EXPORT_SYMBOL(snd_seq_iwffff_init); | ||
diff --git a/sound/core/seq/instr/ainstr_simple.c b/sound/core/seq/instr/ainstr_simple.c deleted file mode 100644 index 78f68bee24fe..000000000000 --- a/sound/core/seq/instr/ainstr_simple.c +++ /dev/null | |||
| @@ -1,215 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Simple (MOD player) - Instrument routines | ||
| 3 | * Copyright (c) 1999 by Jaroslav Kysela <perex@perex.cz> | ||
| 4 | * | ||
| 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. | ||
| 9 | * | ||
| 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. | ||
| 14 | * | ||
| 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 | ||
| 18 | * | ||
| 19 | */ | ||
| 20 | |||
| 21 | #include <sound/driver.h> | ||
| 22 | #include <linux/init.h> | ||
| 23 | #include <linux/slab.h> | ||
| 24 | #include <sound/core.h> | ||
| 25 | #include <sound/ainstr_simple.h> | ||
| 26 | #include <sound/initval.h> | ||
| 27 | #include <asm/uaccess.h> | ||
| 28 | |||
| 29 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); | ||
| 30 | MODULE_DESCRIPTION("Advanced Linux Sound Architecture Simple Instrument support."); | ||
| 31 | MODULE_LICENSE("GPL"); | ||
| 32 | |||
| 33 | static unsigned int snd_seq_simple_size(unsigned int size, unsigned int format) | ||
| 34 | { | ||
| 35 | unsigned int result = size; | ||
| 36 | |||
| 37 | if (format & SIMPLE_WAVE_16BIT) | ||
| 38 | result <<= 1; | ||
| 39 | if (format & SIMPLE_WAVE_STEREO) | ||
| 40 | result <<= 1; | ||
| 41 | return result; | ||
| 42 | } | ||
| 43 | |||
| 44 | static void snd_seq_simple_instr_free(struct snd_simple_ops *ops, | ||
| 45 | struct simple_instrument *ip, | ||
| 46 | int atomic) | ||
| 47 | { | ||
| 48 | if (ops->remove_sample) | ||
| 49 | ops->remove_sample(ops->private_data, ip, atomic); | ||
| 50 | } | ||
| 51 | |||
| 52 | static int snd_seq_simple_put(void *private_data, struct snd_seq_kinstr *instr, | ||
| 53 | char __user *instr_data, long len, | ||
| 54 | int atomic, int cmd) | ||
| 55 | { | ||
| 56 | struct snd_simple_ops *ops = private_data; | ||
| 57 | struct simple_instrument *ip; | ||
| 58 | struct simple_xinstrument ix; | ||
| 59 | int err; | ||
| 60 | gfp_t gfp_mask; | ||
| 61 | unsigned int real_size; | ||
| 62 | |||
| 63 | if (cmd != SNDRV_SEQ_INSTR_PUT_CMD_CREATE) | ||
| 64 | return -EINVAL; | ||
| 65 | gfp_mask = atomic ? GFP_ATOMIC : GFP_KERNEL; | ||
| 66 | /* copy instrument data */ | ||
| 67 | if (len < (long)sizeof(ix)) | ||
| 68 | return -EINVAL; | ||
| 69 | if (copy_from_user(&ix, instr_data, sizeof(ix))) | ||
| 70 | return -EFAULT; | ||
| 71 | if (ix.stype != SIMPLE_STRU_INSTR) | ||
| 72 | return -EINVAL; | ||
| 73 | instr_data += sizeof(ix); | ||
| 74 | len -= sizeof(ix); | ||
| 75 | ip = (struct simple_instrument *)KINSTR_DATA(instr); | ||
| 76 | ip->share_id[0] = le32_to_cpu(ix.share_id[0]); | ||
| 77 | ip->share_id[1] = le32_to_cpu(ix.share_id[1]); | ||
| 78 | ip->share_id[2] = le32_to_cpu(ix.share_id[2]); | ||
| 79 | ip->share_id[3] = le32_to_cpu(ix.share_id[3]); | ||
| 80 | ip->format = le32_to_cpu(ix.format); | ||
| 81 | ip->size = le32_to_cpu(ix.size); | ||
| 82 | ip->start = le32_to_cpu(ix.start); | ||
| 83 | ip->loop_start = le32_to_cpu(ix.loop_start); | ||
| 84 | ip->loop_end = le32_to_cpu(ix.loop_end); | ||
| 85 | ip->loop_repeat = le16_to_cpu(ix.loop_repeat); | ||
| 86 | ip->effect1 = ix.effect1; | ||
| 87 | ip->effect1_depth = ix.effect1_depth; | ||
| 88 | ip->effect2 = ix.effect2; | ||
| 89 | ip->effect2_depth = ix.effect2_depth; | ||
| 90 | real_size = snd_seq_simple_size(ip->size, ip->format); | ||
| 91 | if (len < (long)real_size) | ||
| 92 | return -EINVAL; | ||
| 93 | if (ops->put_sample) { | ||
| 94 | err = ops->put_sample(ops->private_data, ip, | ||
| 95 | instr_data, real_size, atomic); | ||
| 96 | if (err < 0) | ||
| 97 | return err; | ||
| 98 | } | ||
| 99 | return 0; | ||
| 100 | } | ||
| 101 | |||
| 102 | static int snd_seq_simple_get(void *private_data, struct snd_seq_kinstr *instr, | ||
| 103 | char __user *instr_data, long len, | ||
| 104 | int atomic, int cmd) | ||
| 105 | { | ||
| 106 | struct snd_simple_ops *ops = private_data; | ||
| 107 | struct simple_instrument *ip; | ||
| 108 | struct simple_xinstrument ix; | ||
| 109 | int err; | ||
| 110 | unsigned int real_size; | ||
| 111 | |||
| 112 | if (cmd != SNDRV_SEQ_INSTR_GET_CMD_FULL) | ||
| 113 | return -EINVAL; | ||
| 114 | if (len < (long)sizeof(ix)) | ||
| 115 | return -ENOMEM; | ||
| 116 | memset(&ix, 0, sizeof(ix)); | ||
| 117 | ip = (struct simple_instrument *)KINSTR_DATA(instr); | ||
| 118 | ix.stype = SIMPLE_STRU_INSTR; | ||
| 119 | ix.share_id[0] = cpu_to_le32(ip->share_id[0]); | ||
| 120 | ix.share_id[1] = cpu_to_le32(ip->share_id[1]); | ||
| 121 | ix.share_id[2] = cpu_to_le32(ip->share_id[2]); | ||
| 122 | ix.share_id[3] = cpu_to_le32(ip->share_id[3]); | ||
| 123 | ix.format = cpu_to_le32(ip->format); | ||
| 124 | ix.size = cpu_to_le32(ip->size); | ||
| 125 | ix.start = cpu_to_le32(ip->start); | ||
| 126 | ix.loop_start = cpu_to_le32(ip->loop_start); | ||
| 127 | ix.loop_end = cpu_to_le32(ip->loop_end); | ||
| 128 | ix.loop_repeat = cpu_to_le32(ip->loop_repeat); | ||
| 129 | ix.effect1 = cpu_to_le16(ip->effect1); | ||
| 130 | ix.effect1_depth = cpu_to_le16(ip->effect1_depth); | ||
| 131 | ix.effect2 = ip->effect2; | ||
| 132 | ix.effect2_depth = ip->effect2_depth; | ||
| 133 | if (copy_to_user(instr_data, &ix, sizeof(ix))) | ||
| 134 | return -EFAULT; | ||
| 135 | instr_data += sizeof(ix); | ||
| 136 | len -= sizeof(ix); | ||
| 137 | real_size = snd_seq_simple_size(ip->size, ip->format); | ||
| 138 | if (len < (long)real_size) | ||
| 139 | return -ENOMEM; | ||
| 140 | if (ops->get_sample) { | ||
| 141 | err = ops->get_sample(ops->private_data, ip, | ||
| 142 | instr_data, real_size, atomic); | ||
| 143 | if (err < 0) | ||
| 144 | return err; | ||
| 145 | } | ||
| 146 | return 0; | ||
| 147 | } | ||
| 148 | |||
| 149 | static int snd_seq_simple_get_size(void *private_data, struct snd_seq_kinstr *instr, | ||
| 150 | long *size) | ||
| 151 | { | ||
| 152 | struct simple_instrument *ip; | ||
| 153 | |||
| 154 | ip = (struct simple_instrument *)KINSTR_DATA(instr); | ||
| 155 | *size = sizeof(struct simple_xinstrument) + snd_seq_simple_size(ip->size, ip->format); | ||
| 156 | return 0; | ||
| 157 | } | ||
| 158 | |||
| 159 | static int snd_seq_simple_remove(void *private_data, | ||
| 160 | struct snd_seq_kinstr *instr, | ||
| 161 | int atomic) | ||
| 162 | { | ||
| 163 | struct snd_simple_ops *ops = private_data; | ||
| 164 | struct simple_instrument *ip; | ||
| 165 | |||
| 166 | ip = (struct simple_instrument *)KINSTR_DATA(instr); | ||
| 167 | snd_seq_simple_instr_free(ops, ip, atomic); | ||
| 168 | return 0; | ||
| 169 | } | ||
| 170 | |||
| 171 | static void snd_seq_simple_notify(void *private_data, | ||
| 172 | struct snd_seq_kinstr *instr, | ||
| 173 | int what) | ||
| 174 | { | ||
| 175 | struct snd_simple_ops *ops = private_data; | ||
| 176 | |||
| 177 | if (ops->notify) | ||
| 178 | ops->notify(ops->private_data, instr, what); | ||
| 179 | } | ||
| 180 | |||
| 181 | int snd_seq_simple_init(struct snd_simple_ops *ops, | ||
| 182 | void *private_data, | ||
| 183 | struct snd_seq_kinstr_ops *next) | ||
| 184 | { | ||
| 185 | memset(ops, 0, sizeof(*ops)); | ||
| 186 | ops->private_data = private_data; | ||
| 187 | ops->kops.private_data = ops; | ||
| 188 | ops->kops.add_len = sizeof(struct simple_instrument); | ||
| 189 | ops->kops.instr_type = SNDRV_SEQ_INSTR_ID_SIMPLE; | ||
| 190 | ops->kops.put = snd_seq_simple_put; | ||
| 191 | ops->kops.get = snd_seq_simple_get; | ||
| 192 | ops->kops.get_size = snd_seq_simple_get_size; | ||
| 193 | ops->kops.remove = snd_seq_simple_remove; | ||
| 194 | ops->kops.notify = snd_seq_simple_notify; | ||
| 195 | ops->kops.next = next; | ||
| 196 | return 0; | ||
| 197 | } | ||
| 198 | |||
| 199 | /* | ||
| 200 | * Init part | ||
| 201 | */ | ||
| 202 | |||
| 203 | static int __init alsa_ainstr_simple_init(void) | ||
| 204 | { | ||
| 205 | return 0; | ||
| 206 | } | ||
| 207 | |||
| 208 | static void __exit alsa_ainstr_simple_exit(void) | ||
| 209 | { | ||
| 210 | } | ||
| 211 | |||
| 212 | module_init(alsa_ainstr_simple_init) | ||
| 213 | module_exit(alsa_ainstr_simple_exit) | ||
| 214 | |||
| 215 | EXPORT_SYMBOL(snd_seq_simple_init); | ||
diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c index 2e3fa25ab19f..69421ca68167 100644 --- a/sound/core/seq/seq_clientmgr.c +++ b/sound/core/seq/seq_clientmgr.c | |||
| @@ -966,8 +966,7 @@ static int check_event_type_and_length(struct snd_seq_event *ev) | |||
| 966 | return -EINVAL; | 966 | return -EINVAL; |
| 967 | break; | 967 | break; |
| 968 | case SNDRV_SEQ_EVENT_LENGTH_VARUSR: | 968 | case SNDRV_SEQ_EVENT_LENGTH_VARUSR: |
| 969 | if (! snd_seq_ev_is_instr_type(ev) || | 969 | if (! snd_seq_ev_is_direct(ev)) |
| 970 | ! snd_seq_ev_is_direct(ev)) | ||
| 971 | return -EINVAL; | 970 | return -EINVAL; |
| 972 | break; | 971 | break; |
| 973 | } | 972 | } |
diff --git a/sound/core/seq/seq_instr.c b/sound/core/seq/seq_instr.c deleted file mode 100644 index 9a6fd56c9109..000000000000 --- a/sound/core/seq/seq_instr.c +++ /dev/null | |||
| @@ -1,655 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Generic Instrument routines for ALSA sequencer | ||
| 3 | * Copyright (c) 1999 by Jaroslav Kysela <perex@perex.cz> | ||
| 4 | * | ||
| 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. | ||
| 9 | * | ||
| 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. | ||
| 14 | * | ||
| 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 | ||
| 18 | * | ||
| 19 | */ | ||
| 20 | |||
| 21 | #include <sound/driver.h> | ||
| 22 | #include <linux/init.h> | ||
| 23 | #include <linux/slab.h> | ||
| 24 | #include <sound/core.h> | ||
| 25 | #include "seq_clientmgr.h" | ||
| 26 | #include <sound/seq_instr.h> | ||
| 27 | #include <sound/initval.h> | ||
| 28 | |||
| 29 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); | ||
| 30 | MODULE_DESCRIPTION("Advanced Linux Sound Architecture sequencer instrument library."); | ||
| 31 | MODULE_LICENSE("GPL"); | ||
| 32 | |||
| 33 | |||
| 34 | static void snd_instr_lock_ops(struct snd_seq_kinstr_list *list) | ||
| 35 | { | ||
| 36 | if (!(list->flags & SNDRV_SEQ_INSTR_FLG_DIRECT)) { | ||
| 37 | spin_lock_irqsave(&list->ops_lock, list->ops_flags); | ||
| 38 | } else { | ||
| 39 | mutex_lock(&list->ops_mutex); | ||
| 40 | } | ||
| 41 | } | ||
| 42 | |||
| 43 | static void snd_instr_unlock_ops(struct snd_seq_kinstr_list *list) | ||
| 44 | { | ||
| 45 | if (!(list->flags & SNDRV_SEQ_INSTR_FLG_DIRECT)) { | ||
| 46 | spin_unlock_irqrestore(&list->ops_lock, list->ops_flags); | ||
| 47 | } else { | ||
| 48 | mutex_unlock(&list->ops_mutex); | ||
| 49 | } | ||
| 50 | } | ||
| 51 | |||
| 52 | static struct snd_seq_kinstr *snd_seq_instr_new(int add_len, int atomic) | ||
| 53 | { | ||
| 54 | struct snd_seq_kinstr *instr; | ||
| 55 | |||
| 56 | instr = kzalloc(sizeof(struct snd_seq_kinstr) + add_len, atomic ? GFP_ATOMIC : GFP_KERNEL); | ||
| 57 | if (instr == NULL) | ||
| 58 | return NULL; | ||
| 59 | instr->add_len = add_len; | ||
| 60 | return instr; | ||
| 61 | } | ||
| 62 | |||
| 63 | static int snd_seq_instr_free(struct snd_seq_kinstr *instr, int atomic) | ||
| 64 | { | ||
| 65 | int result = 0; | ||
| 66 | |||
| 67 | if (instr == NULL) | ||
| 68 | return -EINVAL; | ||
| 69 | if (instr->ops && instr->ops->remove) | ||
| 70 | result = instr->ops->remove(instr->ops->private_data, instr, 1); | ||
| 71 | if (!result) | ||
| 72 | kfree(instr); | ||
| 73 | return result; | ||
| 74 | } | ||
| 75 | |||
| 76 | struct snd_seq_kinstr_list *snd_seq_instr_list_new(void) | ||
| 77 | { | ||
| 78 | struct snd_seq_kinstr_list *list; | ||
| 79 | |||
| 80 | list = kzalloc(sizeof(struct snd_seq_kinstr_list), GFP_KERNEL); | ||
| 81 | if (list == NULL) | ||
| 82 | return NULL; | ||
| 83 | spin_lock_init(&list->lock); | ||
| 84 | spin_lock_init(&list->ops_lock); | ||
| 85 | mutex_init(&list->ops_mutex); | ||
| 86 | list->owner = -1; | ||
| 87 | return list; | ||
| 88 | } | ||
| 89 | |||
| 90 | void snd_seq_instr_list_free(struct snd_seq_kinstr_list **list_ptr) | ||
| 91 | { | ||
| 92 | struct snd_seq_kinstr_list *list; | ||
| 93 | struct snd_seq_kinstr *instr; | ||
| 94 | struct snd_seq_kcluster *cluster; | ||
| 95 | int idx; | ||
| 96 | unsigned long flags; | ||
| 97 | |||
| 98 | if (list_ptr == NULL) | ||
| 99 | return; | ||
| 100 | list = *list_ptr; | ||
| 101 | *list_ptr = NULL; | ||
| 102 | if (list == NULL) | ||
| 103 | return; | ||
| 104 | |||
| 105 | for (idx = 0; idx < SNDRV_SEQ_INSTR_HASH_SIZE; idx++) { | ||
| 106 | while ((instr = list->hash[idx]) != NULL) { | ||
| 107 | list->hash[idx] = instr->next; | ||
| 108 | list->count--; | ||
| 109 | spin_lock_irqsave(&list->lock, flags); | ||
| 110 | while (instr->use) { | ||
| 111 | spin_unlock_irqrestore(&list->lock, flags); | ||
| 112 | schedule_timeout_uninterruptible(1); | ||
| 113 | spin_lock_irqsave(&list->lock, flags); | ||
| 114 | } | ||
| 115 | spin_unlock_irqrestore(&list->lock, flags); | ||
| 116 | if (snd_seq_instr_free(instr, 0)<0) | ||
| 117 | snd_printk(KERN_WARNING "instrument free problem\n"); | ||
| 118 | } | ||
| 119 | while ((cluster = list->chash[idx]) != NULL) { | ||
| 120 | list->chash[idx] = cluster->next; | ||
| 121 | list->ccount--; | ||
| 122 | kfree(cluster); | ||
| 123 | } | ||
| 124 | } | ||
| 125 | kfree(list); | ||
| 126 | } | ||
| 127 | |||
| 128 | static int instr_free_compare(struct snd_seq_kinstr *instr, | ||
| 129 | struct snd_seq_instr_header *ifree, | ||
| 130 | unsigned int client) | ||
| 131 | { | ||
| 132 | switch (ifree->cmd) { | ||
| 133 | case SNDRV_SEQ_INSTR_FREE_CMD_ALL: | ||
| 134 | /* all, except private for other clients */ | ||
| 135 | if ((instr->instr.std & 0xff000000) == 0) | ||
| 136 | return 0; | ||
| 137 | if (((instr->instr.std >> 24) & 0xff) == client) | ||
| 138 | return 0; | ||
| 139 | return 1; | ||
| 140 | case SNDRV_SEQ_INSTR_FREE_CMD_PRIVATE: | ||
| 141 | /* all my private instruments */ | ||
| 142 | if ((instr->instr.std & 0xff000000) == 0) | ||
| 143 | return 1; | ||
| 144 | if (((instr->instr.std >> 24) & 0xff) == client) | ||
| 145 | return 0; | ||
| 146 | return 1; | ||
| 147 | case SNDRV_SEQ_INSTR_FREE_CMD_CLUSTER: | ||
| 148 | /* all my private instruments */ | ||
| 149 | if ((instr->instr.std & 0xff000000) == 0) { | ||
| 150 | if (instr->instr.cluster == ifree->id.cluster) | ||
| 151 | return 0; | ||
| 152 | return 1; | ||
| 153 | } | ||
| 154 | if (((instr->instr.std >> 24) & 0xff) == client) { | ||
| 155 | if (instr->instr.cluster == ifree->id.cluster) | ||
| 156 | return 0; | ||
| 157 | } | ||
| 158 | return 1; | ||
| 159 | } | ||
| 160 | return 1; | ||
| 161 | } | ||
| 162 | |||
| 163 | int snd_seq_instr_list_free_cond(struct snd_seq_kinstr_list *list, | ||
| 164 | struct snd_seq_instr_header *ifree, | ||
| 165 | int client, | ||
| 166 | int atomic) | ||
| 167 | { | ||
| 168 | struct snd_seq_kinstr *instr, *prev, *next, *flist; | ||
| 169 | int idx; | ||
| 170 | unsigned long flags; | ||
| 171 | |||
| 172 | snd_instr_lock_ops(list); | ||
| 173 | for (idx = 0; idx < SNDRV_SEQ_INSTR_HASH_SIZE; idx++) { | ||
| 174 | spin_lock_irqsave(&list->lock, flags); | ||
| 175 | instr = list->hash[idx]; | ||
| 176 | prev = flist = NULL; | ||
| 177 | while (instr) { | ||
| 178 | while (instr && instr_free_compare(instr, ifree, (unsigned int)client)) { | ||
| 179 | prev = instr; | ||
| 180 | instr = instr->next; | ||
| 181 | } | ||
| 182 | if (instr == NULL) | ||
| 183 | continue; | ||
| 184 | if (instr->ops && instr->ops->notify) | ||
| 185 | instr->ops->notify(instr->ops->private_data, instr, SNDRV_SEQ_INSTR_NOTIFY_REMOVE); | ||
| 186 | next = instr->next; | ||
| 187 | if (prev == NULL) { | ||
| 188 | list->hash[idx] = next; | ||
| 189 | } else { | ||
| 190 | prev->next = next; | ||
| 191 | } | ||
| 192 | list->count--; | ||
| 193 | instr->next = flist; | ||
| 194 | flist = instr; | ||
| 195 | instr = next; | ||
| 196 | } | ||
| 197 | spin_unlock_irqrestore(&list->lock, flags); | ||
| 198 | while (flist) { | ||
| 199 | instr = flist; | ||
| 200 | flist = instr->next; | ||
| 201 | while (instr->use) { | ||
| 202 | schedule_timeout_uninterruptible(1); | ||
| 203 | barrier(); | ||
| 204 | } | ||
| 205 | if (snd_seq_instr_free(instr, atomic)<0) | ||
| 206 | snd_printk(KERN_WARNING "instrument free problem\n"); | ||
| 207 | instr = next; | ||
| 208 | } | ||
| 209 | } | ||
| 210 | snd_instr_unlock_ops(list); | ||
| 211 | return 0; | ||
| 212 | } | ||
| 213 | |||
| 214 | static int compute_hash_instr_key(struct snd_seq_instr *instr) | ||
| 215 | { | ||
| 216 | int result; | ||
| 217 | |||
| 218 | result = instr->bank | (instr->prg << 16); | ||
| 219 | result += result >> 24; | ||
| 220 | result += result >> 16; | ||
| 221 | result += result >> 8; | ||
| 222 | return result & (SNDRV_SEQ_INSTR_HASH_SIZE-1); | ||
| 223 | } | ||
| 224 | |||
| 225 | #if 0 | ||
| 226 | static int compute_hash_cluster_key(snd_seq_instr_cluster_t cluster) | ||
| 227 | { | ||
| 228 | int result; | ||
| 229 | |||
| 230 | result = cluster; | ||
| 231 | result += result >> 24; | ||
| 232 | result += result >> 16; | ||
| 233 | result += result >> 8; | ||
| 234 | return result & (SNDRV_SEQ_INSTR_HASH_SIZE-1); | ||
| 235 | } | ||
| 236 | #endif | ||
| 237 | |||
| 238 | static int compare_instr(struct snd_seq_instr *i1, struct snd_seq_instr *i2, int exact) | ||
| 239 | { | ||
| 240 | if (exact) { | ||
| 241 | if (i1->cluster != i2->cluster || | ||
| 242 | i1->bank != i2->bank || | ||
| 243 | i1->prg != i2->prg) | ||
| 244 | return 1; | ||
| 245 | if ((i1->std & 0xff000000) != (i2->std & 0xff000000)) | ||
| 246 | return 1; | ||
| 247 | if (!(i1->std & i2->std)) | ||
| 248 | return 1; | ||
| 249 | return 0; | ||
| 250 | } else { | ||
| 251 | unsigned int client_check; | ||
| 252 | |||
| 253 | if (i2->cluster && i1->cluster != i2->cluster) | ||
| 254 | return 1; | ||
| 255 | client_check = i2->std & 0xff000000; | ||
| 256 | if (client_check) { | ||
| 257 | if ((i1->std & 0xff000000) != client_check) | ||
| 258 | return 1; | ||
| 259 | } else { | ||
| 260 | if ((i1->std & i2->std) != i2->std) | ||
| 261 | return 1; | ||
| 262 | } | ||
| 263 | return i1->bank != i2->bank || i1->prg != i2->prg; | ||
| 264 | } | ||
| 265 | } | ||
| 266 | |||
| 267 | struct snd_seq_kinstr *snd_seq_instr_find(struct snd_seq_kinstr_list *list, | ||
| 268 | struct snd_seq_instr *instr, | ||
| 269 | int exact, | ||
| 270 | int follow_alias) | ||
| 271 | { | ||
| 272 | unsigned long flags; | ||
| 273 | int depth = 0; | ||
| 274 | struct snd_seq_kinstr *result; | ||
| 275 | |||
| 276 | if (list == NULL || instr == NULL) | ||
| 277 | return NULL; | ||
| 278 | spin_lock_irqsave(&list->lock, flags); | ||
| 279 | __again: | ||
| 280 | result = list->hash[compute_hash_instr_key(instr)]; | ||
| 281 | while (result) { | ||
| 282 | if (!compare_instr(&result->instr, instr, exact)) { | ||
| 283 | if (follow_alias && (result->type == SNDRV_SEQ_INSTR_ATYPE_ALIAS)) { | ||
| 284 | instr = (struct snd_seq_instr *)KINSTR_DATA(result); | ||
| 285 | if (++depth > 10) | ||
| 286 | goto __not_found; | ||
| 287 | goto __again; | ||
| 288 | } | ||
| 289 | result->use++; | ||
| 290 | spin_unlock_irqrestore(&list->lock, flags); | ||
| 291 | return result; | ||
| 292 | } | ||
| 293 | result = result->next; | ||
| 294 | } | ||
| 295 | __not_found: | ||
| 296 | spin_unlock_irqrestore(&list->lock, flags); | ||
| 297 | return NULL; | ||
| 298 | } | ||
| 299 | |||
| 300 | void snd_seq_instr_free_use(struct snd_seq_kinstr_list *list, | ||
| 301 | struct snd_seq_kinstr *instr) | ||
| 302 | { | ||
| 303 | unsigned long flags; | ||
| 304 | |||
| 305 | if (list == NULL || instr == NULL) | ||
| 306 | return; | ||
| 307 | spin_lock_irqsave(&list->lock, flags); | ||
| 308 | if (instr->use <= 0) { | ||
| 309 | snd_printk(KERN_ERR "free_use: fatal!!! use = %i, name = '%s'\n", instr->use, instr->name); | ||
| 310 | } else { | ||
| 311 | instr->use--; | ||
| 312 | } | ||
| 313 | spin_unlock_irqrestore(&list->lock, flags); | ||
| 314 | } | ||
| 315 | |||
| 316 | static struct snd_seq_kinstr_ops *instr_ops(struct snd_seq_kinstr_ops *ops, | ||
| 317 | char *instr_type) | ||
| 318 | { | ||
| 319 | while (ops) { | ||
| 320 | if (!strcmp(ops->instr_type, instr_type)) | ||
| 321 | return ops; | ||
| 322 | ops = ops->next; | ||
| 323 | } | ||
| 324 | return NULL; | ||
| 325 | } | ||
| 326 | |||
| 327 | static int instr_result(struct snd_seq_event *ev, | ||
| 328 | int type, int result, | ||
| 329 | int atomic) | ||
| 330 | { | ||
| 331 | struct snd_seq_event sev; | ||
| 332 | |||
| 333 | memset(&sev, 0, sizeof(sev)); | ||
| 334 | sev.type = SNDRV_SEQ_EVENT_RESULT; | ||
| 335 | sev.flags = SNDRV_SEQ_TIME_STAMP_REAL | SNDRV_SEQ_EVENT_LENGTH_FIXED | | ||
| 336 | SNDRV_SEQ_PRIORITY_NORMAL; | ||
| 337 | sev.source = ev->dest; | ||
| 338 | sev.dest = ev->source; | ||
| 339 | sev.data.result.event = type; | ||
| 340 | sev.data.result.result = result; | ||
| 341 | #if 0 | ||
| 342 | printk("instr result - type = %i, result = %i, queue = %i, source.client:port = %i:%i, dest.client:port = %i:%i\n", | ||
| 343 | type, result, | ||
| 344 | sev.queue, | ||
| 345 | sev.source.client, sev.source.port, | ||
| 346 | sev.dest.client, sev.dest.port); | ||
| 347 | #endif | ||
| 348 | return snd_seq_kernel_client_dispatch(sev.source.client, &sev, atomic, 0); | ||
| 349 | } | ||
| 350 | |||
| 351 | static int instr_begin(struct snd_seq_kinstr_ops *ops, | ||
| 352 | struct snd_seq_kinstr_list *list, | ||
| 353 | struct snd_seq_event *ev, | ||
| 354 | int atomic, int hop) | ||
| 355 | { | ||
| 356 | unsigned long flags; | ||
| 357 | |||
| 358 | spin_lock_irqsave(&list->lock, flags); | ||
| 359 | if (list->owner >= 0 && list->owner != ev->source.client) { | ||
| 360 | spin_unlock_irqrestore(&list->lock, flags); | ||
| 361 | return instr_result(ev, SNDRV_SEQ_EVENT_INSTR_BEGIN, -EBUSY, atomic); | ||
| 362 | } | ||
| 363 | list->owner = ev->source.client; | ||
| 364 | spin_unlock_irqrestore(&list->lock, flags); | ||
| 365 | return instr_result(ev, SNDRV_SEQ_EVENT_INSTR_BEGIN, 0, atomic); | ||
| 366 | } | ||
| 367 | |||
| 368 | static int instr_end(struct snd_seq_kinstr_ops *ops, | ||
| 369 | struct snd_seq_kinstr_list *list, | ||
| 370 | struct snd_seq_event *ev, | ||
| 371 | int atomic, int hop) | ||
| 372 | { | ||
| 373 | unsigned long flags; | ||
| 374 | |||
| 375 | /* TODO: timeout handling */ | ||
| 376 | spin_lock_irqsave(&list->lock, flags); | ||
| 377 | if (list->owner == ev->source.client) { | ||
| 378 | list->owner = -1; | ||
| 379 | spin_unlock_irqrestore(&list->lock, flags); | ||
| 380 | return instr_result(ev, SNDRV_SEQ_EVENT_INSTR_END, 0, atomic); | ||
| 381 | } | ||
| 382 | spin_unlock_irqrestore(&list->lock, flags); | ||
| 383 | return instr_result(ev, SNDRV_SEQ_EVENT_INSTR_END, -EINVAL, atomic); | ||
| 384 | } | ||
| 385 | |||
| 386 | static int instr_info(struct snd_seq_kinstr_ops *ops, | ||
| 387 | struct snd_seq_kinstr_list *list, | ||
| 388 | struct snd_seq_event *ev, | ||
| 389 | int atomic, int hop) | ||
| 390 | { | ||
| 391 | return -ENXIO; | ||
| 392 | } | ||
| 393 | |||
| 394 | static int instr_format_info(struct snd_seq_kinstr_ops *ops, | ||
| 395 | struct snd_seq_kinstr_list *list, | ||
| 396 | struct snd_seq_event *ev, | ||
| 397 | int atomic, int hop) | ||
| 398 | { | ||
| 399 | return -ENXIO; | ||
| 400 | } | ||
| 401 | |||
| 402 | static int instr_reset(struct snd_seq_kinstr_ops *ops, | ||
| 403 | struct snd_seq_kinstr_list *list, | ||
| 404 | struct snd_seq_event *ev, | ||
| 405 | int atomic, int hop) | ||
| 406 | { | ||
| 407 | return -ENXIO; | ||
| 408 | } | ||
| 409 | |||
| 410 | static int instr_status(struct snd_seq_kinstr_ops *ops, | ||
| 411 | struct snd_seq_kinstr_list *list, | ||
| 412 | struct snd_seq_event *ev, | ||
| 413 | int atomic, int hop) | ||
| 414 | { | ||
| 415 | return -ENXIO; | ||
| 416 | } | ||
| 417 | |||
| 418 | static int instr_put(struct snd_seq_kinstr_ops *ops, | ||
| 419 | struct snd_seq_kinstr_list *list, | ||
| 420 | struct snd_seq_event *ev, | ||
| 421 | int atomic, int hop) | ||
| 422 | { | ||
| 423 | unsigned long flags; | ||
| 424 | struct snd_seq_instr_header put; | ||
| 425 | struct snd_seq_kinstr *instr; | ||
| 426 | int result = -EINVAL, len, key; | ||
| 427 | |||
| 428 | if ((ev->flags & SNDRV_SEQ_EVENT_LENGTH_MASK) != SNDRV_SEQ_EVENT_LENGTH_VARUSR) | ||
| 429 | goto __return; | ||
| 430 | |||
| 431 | if (ev->data.ext.len < sizeof(struct snd_seq_instr_header)) | ||
| 432 | goto __return; | ||
| 433 | if (copy_from_user(&put, (void __user *)ev->data.ext.ptr, | ||
| 434 | sizeof(struct snd_seq_instr_header))) { | ||
| 435 | result = -EFAULT; | ||
| 436 | goto __return; | ||
| 437 | } | ||
| 438 | snd_instr_lock_ops(list); | ||
| 439 | if (put.id.instr.std & 0xff000000) { /* private instrument */ | ||
| 440 | put.id.instr.std &= 0x00ffffff; | ||
| 441 | put.id.instr.std |= (unsigned int)ev->source.client << 24; | ||
| 442 | } | ||
| 443 | if ((instr = snd_seq_instr_find(list, &put.id.instr, 1, 0))) { | ||
| 444 | snd_seq_instr_free_use(list, instr); | ||
| 445 | snd_instr_unlock_ops(list); | ||
| 446 | result = -EBUSY; | ||
| 447 | goto __return; | ||
| 448 | } | ||
| 449 | ops = instr_ops(ops, put.data.data.format); | ||
| 450 | if (ops == NULL) { | ||
| 451 | snd_instr_unlock_ops(list); | ||
| 452 | goto __return; | ||
| 453 | } | ||
| 454 | len = ops->add_len; | ||
| 455 | if (put.data.type == SNDRV_SEQ_INSTR_ATYPE_ALIAS) | ||
| 456 | len = sizeof(struct snd_seq_instr); | ||
| 457 | instr = snd_seq_instr_new(len, atomic); | ||
| 458 | if (instr == NULL) { | ||
| 459 | snd_instr_unlock_ops(list); | ||
| 460 | result = -ENOMEM; | ||
| 461 | goto __return; | ||
| 462 | } | ||
| 463 | instr->ops = ops; | ||
| 464 | instr->instr = put.id.instr; | ||
| 465 | strlcpy(instr->name, put.data.name, sizeof(instr->name)); | ||
| 466 | instr->type = put.data.type; | ||
| 467 | if (instr->type == SNDRV_SEQ_INSTR_ATYPE_DATA) { | ||
| 468 | result = ops->put(ops->private_data, | ||
| 469 | instr, | ||
| 470 | (void __user *)ev->data.ext.ptr + sizeof(struct snd_seq_instr_header), | ||
| 471 | ev->data.ext.len - sizeof(struct snd_seq_instr_header), | ||
| 472 | atomic, | ||
| 473 | put.cmd); | ||
| 474 | if (result < 0) { | ||
| 475 | snd_seq_instr_free(instr, atomic); | ||
| 476 | snd_instr_unlock_ops(list); | ||
| 477 | goto __return; | ||
| 478 | } | ||
| 479 | } | ||
| 480 | key = compute_hash_instr_key(&instr->instr); | ||
| 481 | spin_lock_irqsave(&list->lock, flags); | ||
| 482 | instr->next = list->hash[key]; | ||
| 483 | list->hash[key] = instr; | ||
| 484 | list->count++; | ||
| 485 | spin_unlock_irqrestore(&list->lock, flags); | ||
| 486 | snd_instr_unlock_ops(list); | ||
| 487 | result = 0; | ||
| 488 | __return: | ||
| 489 | instr_result(ev, SNDRV_SEQ_EVENT_INSTR_PUT, result, atomic); | ||
| 490 | return result; | ||
| 491 | } | ||
| 492 | |||
| 493 | static int instr_get(struct snd_seq_kinstr_ops *ops, | ||
| 494 | struct snd_seq_kinstr_list *list, | ||
| 495 | struct snd_seq_event *ev, | ||
| 496 | int atomic, int hop) | ||
| 497 | { | ||
| 498 | return -ENXIO; | ||
| 499 | } | ||
| 500 | |||
| 501 | static int instr_free(struct snd_seq_kinstr_ops *ops, | ||
| 502 | struct snd_seq_kinstr_list *list, | ||
| 503 | struct snd_seq_event *ev, | ||
| 504 | int atomic, int hop) | ||
| 505 | { | ||
| 506 | struct snd_seq_instr_header ifree; | ||
| 507 | struct snd_seq_kinstr *instr, *prev; | ||
| 508 | int result = -EINVAL; | ||
| 509 | unsigned long flags; | ||
| 510 | unsigned int hash; | ||
| 511 | |||
| 512 | if ((ev->flags & SNDRV_SEQ_EVENT_LENGTH_MASK) != SNDRV_SEQ_EVENT_LENGTH_VARUSR) | ||
| 513 | goto __return; | ||
| 514 | |||
| 515 | if (ev->data.ext.len < sizeof(struct snd_seq_instr_header)) | ||
| 516 | goto __return; | ||
| 517 | if (copy_from_user(&ifree, (void __user *)ev->data.ext.ptr, | ||
| 518 | sizeof(struct snd_seq_instr_header))) { | ||
| 519 | result = -EFAULT; | ||
| 520 | goto __return; | ||
| 521 | } | ||
| 522 | if (ifree.cmd == SNDRV_SEQ_INSTR_FREE_CMD_ALL || | ||
| 523 | ifree.cmd == SNDRV_SEQ_INSTR_FREE_CMD_PRIVATE || | ||
| 524 | ifree.cmd == SNDRV_SEQ_INSTR_FREE_CMD_CLUSTER) { | ||
| 525 | result = snd_seq_instr_list_free_cond(list, &ifree, ev->dest.client, atomic); | ||
| 526 | goto __return; | ||
| 527 | } | ||
| 528 | if (ifree.cmd == SNDRV_SEQ_INSTR_FREE_CMD_SINGLE) { | ||
| 529 | if (ifree.id.instr.std & 0xff000000) { | ||
| 530 | ifree.id.instr.std &= 0x00ffffff; | ||
| 531 | ifree.id.instr.std |= (unsigned int)ev->source.client << 24; | ||
| 532 | } | ||
| 533 | hash = compute_hash_instr_key(&ifree.id.instr); | ||
| 534 | snd_instr_lock_ops(list); | ||
| 535 | spin_lock_irqsave(&list->lock, flags); | ||
| 536 | instr = list->hash[hash]; | ||
| 537 | prev = NULL; | ||
| 538 | while (instr) { | ||
| 539 | if (!compare_instr(&instr->instr, &ifree.id.instr, 1)) | ||
| 540 | goto __free_single; | ||
| 541 | prev = instr; | ||
| 542 | instr = instr->next; | ||
| 543 | } | ||
| 544 | result = -ENOENT; | ||
| 545 | spin_unlock_irqrestore(&list->lock, flags); | ||
| 546 | snd_instr_unlock_ops(list); | ||
| 547 | goto __return; | ||
| 548 | |||
| 549 | __free_single: | ||
| 550 | if (prev) { | ||
| 551 | prev->next = instr->next; | ||
| 552 | } else { | ||
| 553 | list->hash[hash] = instr->next; | ||
| 554 | } | ||
| 555 | if (instr->ops && instr->ops->notify) | ||
| 556 | instr->ops->notify(instr->ops->private_data, instr, | ||
| 557 | SNDRV_SEQ_INSTR_NOTIFY_REMOVE); | ||
| 558 | while (instr->use) { | ||
| 559 | spin_unlock_irqrestore(&list->lock, flags); | ||
| 560 | schedule_timeout_uninterruptible(1); | ||
| 561 | spin_lock_irqsave(&list->lock, flags); | ||
| 562 | } | ||
| 563 | spin_unlock_irqrestore(&list->lock, flags); | ||
| 564 | result = snd_seq_instr_free(instr, atomic); | ||
| 565 | snd_instr_unlock_ops(list); | ||
| 566 | goto __return; | ||
| 567 | } | ||
| 568 | |||
| 569 | __return: | ||
| 570 | instr_result(ev, SNDRV_SEQ_EVENT_INSTR_FREE, result, atomic); | ||
| 571 | return result; | ||
| 572 | } | ||
| 573 | |||
| 574 | static int instr_list(struct snd_seq_kinstr_ops *ops, | ||
| 575 | struct snd_seq_kinstr_list *list, | ||
| 576 | struct snd_seq_event *ev, | ||
| 577 | int atomic, int hop) | ||
| 578 | { | ||
| 579 | return -ENXIO; | ||
| 580 | } | ||
| 581 | |||
| 582 | static int instr_cluster(struct snd_seq_kinstr_ops *ops, | ||
| 583 | struct snd_seq_kinstr_list *list, | ||
| 584 | struct snd_seq_event *ev, | ||
| 585 | int atomic, int hop) | ||
| 586 | { | ||
| 587 | return -ENXIO; | ||
| 588 | } | ||
| 589 | |||
| 590 | int snd_seq_instr_event(struct snd_seq_kinstr_ops *ops, | ||
| 591 | struct snd_seq_kinstr_list *list, | ||
| 592 | struct snd_seq_event *ev, | ||
| 593 | int client, | ||
| 594 | int atomic, | ||
| 595 | int hop) | ||
| 596 | { | ||
| 597 | int direct = 0; | ||
| 598 | |||
| 599 | snd_assert(ops != NULL && list != NULL && ev != NULL, return -EINVAL); | ||
| 600 | if (snd_seq_ev_is_direct(ev)) { | ||
| 601 | direct = 1; | ||
| 602 | switch (ev->type) { | ||
| 603 | case SNDRV_SEQ_EVENT_INSTR_BEGIN: | ||
| 604 | return instr_begin(ops, list, ev, atomic, hop); | ||
| 605 | case SNDRV_SEQ_EVENT_INSTR_END: | ||
| 606 | return instr_end(ops, list, ev, atomic, hop); | ||
| 607 | } | ||
| 608 | } | ||
| 609 | if ((list->flags & SNDRV_SEQ_INSTR_FLG_DIRECT) && !direct) | ||
| 610 | return -EINVAL; | ||
| 611 | switch (ev->type) { | ||
| 612 | case SNDRV_SEQ_EVENT_INSTR_INFO: | ||
| 613 | return instr_info(ops, list, ev, atomic, hop); | ||
| 614 | case SNDRV_SEQ_EVENT_INSTR_FINFO: | ||
| 615 | return instr_format_info(ops, list, ev, atomic, hop); | ||
| 616 | case SNDRV_SEQ_EVENT_INSTR_RESET: | ||
| 617 | return instr_reset(ops, list, ev, atomic, hop); | ||
| 618 | case SNDRV_SEQ_EVENT_INSTR_STATUS: | ||
| 619 | return instr_status(ops, list, ev, atomic, hop); | ||
| 620 | case SNDRV_SEQ_EVENT_INSTR_PUT: | ||
| 621 | return instr_put(ops, list, ev, atomic, hop); | ||
| 622 | case SNDRV_SEQ_EVENT_INSTR_GET: | ||
| 623 | return instr_get(ops, list, ev, atomic, hop); | ||
| 624 | case SNDRV_SEQ_EVENT_INSTR_FREE: | ||
| 625 | return instr_free(ops, list, ev, atomic, hop); | ||
| 626 | case SNDRV_SEQ_EVENT_INSTR_LIST: | ||
| 627 | return instr_list(ops, list, ev, atomic, hop); | ||
| 628 | case SNDRV_SEQ_EVENT_INSTR_CLUSTER: | ||
| 629 | return instr_cluster(ops, list, ev, atomic, hop); | ||
| 630 | } | ||
| 631 | return -EINVAL; | ||
| 632 | } | ||
| 633 | |||
| 634 | /* | ||
| 635 | * Init part | ||
| 636 | */ | ||
| 637 | |||
| 638 | static int __init alsa_seq_instr_init(void) | ||
| 639 | { | ||
| 640 | return 0; | ||
| 641 | } | ||
| 642 | |||
| 643 | static void __exit alsa_seq_instr_exit(void) | ||
| 644 | { | ||
| 645 | } | ||
| 646 | |||
| 647 | module_init(alsa_seq_instr_init) | ||
| 648 | module_exit(alsa_seq_instr_exit) | ||
| 649 | |||
| 650 | EXPORT_SYMBOL(snd_seq_instr_list_new); | ||
| 651 | EXPORT_SYMBOL(snd_seq_instr_list_free); | ||
| 652 | EXPORT_SYMBOL(snd_seq_instr_list_free_cond); | ||
| 653 | EXPORT_SYMBOL(snd_seq_instr_find); | ||
| 654 | EXPORT_SYMBOL(snd_seq_instr_free_use); | ||
| 655 | EXPORT_SYMBOL(snd_seq_instr_event); | ||
diff --git a/sound/core/seq/seq_midi_emul.c b/sound/core/seq/seq_midi_emul.c index 17b3e6f13ca3..6645fc544621 100644 --- a/sound/core/seq/seq_midi_emul.c +++ b/sound/core/seq/seq_midi_emul.c | |||
| @@ -229,13 +229,6 @@ snd_midi_process_event(struct snd_midi_op *ops, | |||
| 229 | case SNDRV_SEQ_EVENT_PORT_START: | 229 | case SNDRV_SEQ_EVENT_PORT_START: |
| 230 | case SNDRV_SEQ_EVENT_PORT_EXIT: | 230 | case SNDRV_SEQ_EVENT_PORT_EXIT: |
| 231 | case SNDRV_SEQ_EVENT_PORT_CHANGE: | 231 | case SNDRV_SEQ_EVENT_PORT_CHANGE: |
| 232 | case SNDRV_SEQ_EVENT_SAMPLE: | ||
| 233 | case SNDRV_SEQ_EVENT_SAMPLE_START: | ||
| 234 | case SNDRV_SEQ_EVENT_SAMPLE_STOP: | ||
| 235 | case SNDRV_SEQ_EVENT_SAMPLE_FREQ: | ||
| 236 | case SNDRV_SEQ_EVENT_SAMPLE_VOLUME: | ||
| 237 | case SNDRV_SEQ_EVENT_SAMPLE_LOOP: | ||
| 238 | case SNDRV_SEQ_EVENT_SAMPLE_POSITION: | ||
| 239 | case SNDRV_SEQ_EVENT_ECHO: | 232 | case SNDRV_SEQ_EVENT_ECHO: |
| 240 | not_yet: | 233 | not_yet: |
| 241 | default: | 234 | default: |
diff --git a/sound/isa/gus/Makefile b/sound/isa/gus/Makefile index df3d59f25f5e..6cd4ee03754a 100644 --- a/sound/isa/gus/Makefile +++ b/sound/isa/gus/Makefile | |||
| @@ -9,7 +9,6 @@ snd-gus-lib-objs := gus_main.o \ | |||
| 9 | gus_pcm.o gus_mixer.o \ | 9 | gus_pcm.o gus_mixer.o \ |
| 10 | gus_uart.o \ | 10 | gus_uart.o \ |
| 11 | gus_reset.o | 11 | gus_reset.o |
| 12 | snd-gus-synth-objs := gus_synth.o gus_sample.o gus_simple.o gus_instr.o | ||
| 13 | 12 | ||
| 14 | snd-gusclassic-objs := gusclassic.o | 13 | snd-gusclassic-objs := gusclassic.o |
| 15 | snd-gusextreme-objs := gusextreme.o | 14 | snd-gusextreme-objs := gusextreme.o |
| @@ -17,20 +16,9 @@ snd-gusmax-objs := gusmax.o | |||
| 17 | snd-interwave-objs := interwave.o | 16 | snd-interwave-objs := interwave.o |
| 18 | snd-interwave-stb-objs := interwave-stb.o | 17 | snd-interwave-stb-objs := interwave-stb.o |
| 19 | 18 | ||
| 20 | # | ||
| 21 | # this function returns: | ||
| 22 | # "m" - CONFIG_SND_SEQUENCER is m | ||
| 23 | # <empty string> - CONFIG_SND_SEQUENCER is undefined | ||
| 24 | # otherwise parameter #1 value | ||
| 25 | # | ||
| 26 | sequencer = $(if $(subst y,,$(CONFIG_SND_SEQUENCER)),$(if $(1),m),$(if $(CONFIG_SND_SEQUENCER),$(1))) | ||
| 27 | |||
| 28 | # Toplevel Module Dependency | 19 | # Toplevel Module Dependency |
| 29 | obj-$(CONFIG_SND_GUSCLASSIC) += snd-gusclassic.o snd-gus-lib.o | 20 | obj-$(CONFIG_SND_GUSCLASSIC) += snd-gusclassic.o snd-gus-lib.o |
| 30 | obj-$(CONFIG_SND_GUSMAX) += snd-gusmax.o snd-gus-lib.o | 21 | obj-$(CONFIG_SND_GUSMAX) += snd-gusmax.o snd-gus-lib.o |
| 31 | obj-$(CONFIG_SND_GUSEXTREME) += snd-gusextreme.o snd-gus-lib.o | 22 | obj-$(CONFIG_SND_GUSEXTREME) += snd-gusextreme.o snd-gus-lib.o |
| 32 | obj-$(CONFIG_SND_INTERWAVE) += snd-interwave.o snd-gus-lib.o | 23 | obj-$(CONFIG_SND_INTERWAVE) += snd-interwave.o snd-gus-lib.o |
| 33 | obj-$(CONFIG_SND_INTERWAVE_STB) += snd-interwave-stb.o snd-gus-lib.o | 24 | obj-$(CONFIG_SND_INTERWAVE_STB) += snd-interwave-stb.o snd-gus-lib.o |
| 34 | obj-$(call sequencer,$(CONFIG_SND_GUS_SYNTH)) += snd-gus-synth.o | ||
| 35 | |||
| 36 | obj-m := $(sort $(obj-m)) | ||
diff --git a/sound/isa/gus/gus_main.c b/sound/isa/gus/gus_main.c index b14d5d6d9a32..e4453e5e5c23 100644 --- a/sound/isa/gus/gus_main.c +++ b/sound/isa/gus/gus_main.c | |||
| @@ -104,12 +104,6 @@ static int snd_gus_free(struct snd_gus_card *gus) | |||
| 104 | { | 104 | { |
| 105 | if (gus->gf1.res_port2 == NULL) | 105 | if (gus->gf1.res_port2 == NULL) |
| 106 | goto __hw_end; | 106 | goto __hw_end; |
| 107 | #if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE)) | ||
| 108 | if (gus->seq_dev) { | ||
| 109 | snd_device_free(gus->card, gus->seq_dev); | ||
| 110 | gus->seq_dev = NULL; | ||
| 111 | } | ||
| 112 | #endif | ||
| 113 | snd_gf1_stop(gus); | 107 | snd_gf1_stop(gus); |
| 114 | snd_gus_init_dma_irq(gus, 0); | 108 | snd_gus_init_dma_irq(gus, 0); |
| 115 | __hw_end: | 109 | __hw_end: |
| @@ -408,14 +402,6 @@ static int snd_gus_check_version(struct snd_gus_card * gus) | |||
| 408 | return 0; | 402 | return 0; |
| 409 | } | 403 | } |
| 410 | 404 | ||
| 411 | #if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE)) | ||
| 412 | static void snd_gus_seq_dev_free(struct snd_seq_device *seq_dev) | ||
| 413 | { | ||
| 414 | struct snd_gus_card *gus = seq_dev->private_data; | ||
| 415 | gus->seq_dev = NULL; | ||
| 416 | } | ||
| 417 | #endif | ||
| 418 | |||
| 419 | int snd_gus_initialize(struct snd_gus_card *gus) | 405 | int snd_gus_initialize(struct snd_gus_card *gus) |
| 420 | { | 406 | { |
| 421 | int err; | 407 | int err; |
| @@ -430,15 +416,6 @@ int snd_gus_initialize(struct snd_gus_card *gus) | |||
| 430 | } | 416 | } |
| 431 | if ((err = snd_gus_init_dma_irq(gus, 1)) < 0) | 417 | if ((err = snd_gus_init_dma_irq(gus, 1)) < 0) |
| 432 | return err; | 418 | return err; |
| 433 | #if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE)) | ||
| 434 | if (snd_seq_device_new(gus->card, 1, SNDRV_SEQ_DEV_ID_GUS, | ||
| 435 | sizeof(struct snd_gus_card *), &gus->seq_dev) >= 0) { | ||
| 436 | strcpy(gus->seq_dev->name, "GUS"); | ||
| 437 | *(struct snd_gus_card **)SNDRV_SEQ_DEVICE_ARGPTR(gus->seq_dev) = gus; | ||
| 438 | gus->seq_dev->private_data = gus; | ||
| 439 | gus->seq_dev->private_free = snd_gus_seq_dev_free; | ||
| 440 | } | ||
| 441 | #endif | ||
| 442 | snd_gf1_start(gus); | 419 | snd_gf1_start(gus); |
| 443 | gus->initialized = 1; | 420 | gus->initialized = 1; |
| 444 | return 0; | 421 | return 0; |
diff --git a/sound/isa/gus/gus_sample.c b/sound/isa/gus/gus_sample.c deleted file mode 100644 index cba0829a7106..000000000000 --- a/sound/isa/gus/gus_sample.c +++ /dev/null | |||
| @@ -1,165 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Routines for Gravis UltraSound soundcards - Sample support | ||
| 3 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> | ||
| 4 | * | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify | ||
| 7 | * it under the terms of the GNU General Public License as published by | ||
| 8 | * the Free Software Foundation; either version 2 of the License, or | ||
| 9 | * (at your option) any later version. | ||
| 10 | * | ||
| 11 | * This program is distributed in the hope that it will be useful, | ||
| 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 14 | * GNU General Public License for more details. | ||
| 15 | * | ||
| 16 | * You should have received a copy of the GNU General Public License | ||
| 17 | * along with this program; if not, write to the Free Software | ||
| 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 19 | * | ||
| 20 | */ | ||
| 21 | |||
| 22 | #include <sound/driver.h> | ||
| 23 | #include <linux/time.h> | ||
| 24 | #include <sound/core.h> | ||
| 25 | #include <sound/gus.h> | ||
| 26 | |||
| 27 | /* | ||
| 28 | * | ||
| 29 | */ | ||
| 30 | |||
| 31 | static void select_instrument(struct snd_gus_card * gus, struct snd_gus_voice * v) | ||
| 32 | { | ||
| 33 | struct snd_seq_kinstr *instr; | ||
| 34 | |||
| 35 | #if 0 | ||
| 36 | printk("select instrument: cluster = %li, std = 0x%x, bank = %i, prg = %i\n", | ||
| 37 | v->instr.cluster, | ||
| 38 | v->instr.std, | ||
| 39 | v->instr.bank, | ||
| 40 | v->instr.prg); | ||
| 41 | #endif | ||
| 42 | instr = snd_seq_instr_find(gus->gf1.ilist, &v->instr, 0, 1); | ||
| 43 | if (instr != NULL) { | ||
| 44 | if (instr->ops) { | ||
| 45 | if (!strcmp(instr->ops->instr_type, SNDRV_SEQ_INSTR_ID_SIMPLE)) | ||
| 46 | snd_gf1_simple_init(v); | ||
| 47 | } | ||
| 48 | snd_seq_instr_free_use(gus->gf1.ilist, instr); | ||
| 49 | } | ||
| 50 | } | ||
| 51 | |||
| 52 | /* | ||
| 53 | * | ||
| 54 | */ | ||
| 55 | |||
| 56 | static void event_sample(struct snd_seq_event *ev, struct snd_gus_port *p, | ||
| 57 | struct snd_gus_voice *v) | ||
| 58 | { | ||
| 59 | if (v->sample_ops && v->sample_ops->sample_stop) | ||
| 60 | v->sample_ops->sample_stop(p->gus, v, SAMPLE_STOP_IMMEDIATELY); | ||
| 61 | v->instr.std = ev->data.sample.param.sample.std; | ||
| 62 | if (v->instr.std & 0xff000000) { /* private instrument */ | ||
| 63 | v->instr.std &= 0x00ffffff; | ||
| 64 | v->instr.std |= (unsigned int)ev->source.client << 24; | ||
| 65 | } | ||
| 66 | v->instr.bank = ev->data.sample.param.sample.bank; | ||
| 67 | v->instr.prg = ev->data.sample.param.sample.prg; | ||
| 68 | select_instrument(p->gus, v); | ||
| 69 | } | ||
| 70 | |||
| 71 | static void event_cluster(struct snd_seq_event *ev, struct snd_gus_port *p, | ||
| 72 | struct snd_gus_voice *v) | ||
| 73 | { | ||
| 74 | if (v->sample_ops && v->sample_ops->sample_stop) | ||
| 75 | v->sample_ops->sample_stop(p->gus, v, SAMPLE_STOP_IMMEDIATELY); | ||
| 76 | v->instr.cluster = ev->data.sample.param.cluster.cluster; | ||
| 77 | select_instrument(p->gus, v); | ||
| 78 | } | ||
| 79 | |||
| 80 | static void event_start(struct snd_seq_event *ev, struct snd_gus_port *p, | ||
| 81 | struct snd_gus_voice *v) | ||
| 82 | { | ||
| 83 | if (v->sample_ops && v->sample_ops->sample_start) | ||
| 84 | v->sample_ops->sample_start(p->gus, v, ev->data.sample.param.position); | ||
| 85 | } | ||
| 86 | |||
| 87 | static void event_stop(struct snd_seq_event *ev, struct snd_gus_port *p, | ||
| 88 | struct snd_gus_voice *v) | ||
| 89 | { | ||
| 90 | if (v->sample_ops && v->sample_ops->sample_stop) | ||
| 91 | v->sample_ops->sample_stop(p->gus, v, ev->data.sample.param.stop_mode); | ||
| 92 | } | ||
| 93 | |||
| 94 | static void event_freq(struct snd_seq_event *ev, struct snd_gus_port *p, | ||
| 95 | struct snd_gus_voice *v) | ||
| 96 | { | ||
| 97 | if (v->sample_ops && v->sample_ops->sample_freq) | ||
| 98 | v->sample_ops->sample_freq(p->gus, v, ev->data.sample.param.frequency); | ||
| 99 | } | ||
| 100 | |||
| 101 | static void event_volume(struct snd_seq_event *ev, struct snd_gus_port *p, | ||
| 102 | struct snd_gus_voice *v) | ||
| 103 | { | ||
| 104 | if (v->sample_ops && v->sample_ops->sample_volume) | ||
| 105 | v->sample_ops->sample_volume(p->gus, v, &ev->data.sample.param.volume); | ||
| 106 | } | ||
| 107 | |||
| 108 | static void event_loop(struct snd_seq_event *ev, struct snd_gus_port *p, | ||
| 109 | struct snd_gus_voice *v) | ||
| 110 | { | ||
| 111 | if (v->sample_ops && v->sample_ops->sample_loop) | ||
| 112 | v->sample_ops->sample_loop(p->gus, v, &ev->data.sample.param.loop); | ||
| 113 | } | ||
| 114 | |||
| 115 | static void event_position(struct snd_seq_event *ev, struct snd_gus_port *p, | ||
| 116 | struct snd_gus_voice *v) | ||
| 117 | { | ||
| 118 | if (v->sample_ops && v->sample_ops->sample_pos) | ||
| 119 | v->sample_ops->sample_pos(p->gus, v, ev->data.sample.param.position); | ||
| 120 | } | ||
| 121 | |||
| 122 | static void event_private1(struct snd_seq_event *ev, struct snd_gus_port *p, | ||
| 123 | struct snd_gus_voice *v) | ||
| 124 | { | ||
| 125 | if (v->sample_ops && v->sample_ops->sample_private1) | ||
| 126 | v->sample_ops->sample_private1(p->gus, v, (unsigned char *)&ev->data.sample.param.raw8); | ||
| 127 | } | ||
| 128 | |||
| 129 | typedef void (gus_sample_event_handler_t)(struct snd_seq_event *ev, | ||
| 130 | struct snd_gus_port *p, | ||
| 131 | struct snd_gus_voice *v); | ||
| 132 | static gus_sample_event_handler_t *gus_sample_event_handlers[9] = { | ||
| 133 | event_sample, | ||
| 134 | event_cluster, | ||
| 135 | event_start, | ||
| 136 | event_stop, | ||
| 137 | event_freq, | ||
| 138 | event_volume, | ||
| 139 | event_loop, | ||
| 140 | event_position, | ||
| 141 | event_private1 | ||
| 142 | }; | ||
| 143 | |||
| 144 | void snd_gus_sample_event(struct snd_seq_event *ev, struct snd_gus_port *p) | ||
| 145 | { | ||
| 146 | int idx, voice; | ||
| 147 | struct snd_gus_card *gus = p->gus; | ||
| 148 | struct snd_gus_voice *v; | ||
| 149 | unsigned long flags; | ||
| 150 | |||
| 151 | idx = ev->type - SNDRV_SEQ_EVENT_SAMPLE; | ||
| 152 | if (idx < 0 || idx > 8) | ||
| 153 | return; | ||
| 154 | for (voice = 0; voice < 32; voice++) { | ||
| 155 | v = &gus->gf1.voices[voice]; | ||
| 156 | if (v->use && v->client == ev->source.client && | ||
| 157 | v->port == ev->source.port && | ||
| 158 | v->index == ev->data.sample.channel) { | ||
| 159 | spin_lock_irqsave(&gus->event_lock, flags); | ||
| 160 | gus_sample_event_handlers[idx](ev, p, v); | ||
| 161 | spin_unlock_irqrestore(&gus->event_lock, flags); | ||
| 162 | return; | ||
| 163 | } | ||
| 164 | } | ||
| 165 | } | ||
diff --git a/sound/isa/gus/gus_simple.c b/sound/isa/gus/gus_simple.c deleted file mode 100644 index 39d121e2c8c4..000000000000 --- a/sound/isa/gus/gus_simple.c +++ /dev/null | |||
| @@ -1,634 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Routines for Gravis UltraSound soundcards - Simple instrument handlers | ||
| 3 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> | ||
| 4 | * | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify | ||
| 7 | * it under the terms of the GNU General Public License as published by | ||
| 8 | * the Free Software Foundation; either version 2 of the License, or | ||
| 9 | * (at your option) any later version. | ||
| 10 | * | ||
| 11 | * This program is distributed in the hope that it will be useful, | ||
| 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 14 | * GNU General Public License for more details. | ||
| 15 | * | ||
| 16 | * You should have received a copy of the GNU General Public License | ||
| 17 | * along with this program; if not, write to the Free Software | ||
| 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 19 | * | ||
| 20 | */ | ||
| 21 | |||
| 22 | #include <sound/driver.h> | ||
| 23 | #include <linux/time.h> | ||
| 24 | #include <sound/core.h> | ||
| 25 | #include <sound/gus.h> | ||
| 26 | #include "gus_tables.h" | ||
| 27 | |||
| 28 | /* | ||
| 29 | * | ||
| 30 | */ | ||
| 31 | |||
| 32 | static void interrupt_wave(struct snd_gus_card *gus, struct snd_gus_voice *voice); | ||
| 33 | static void interrupt_volume(struct snd_gus_card *gus, struct snd_gus_voice *voice); | ||
| 34 | static void interrupt_effect(struct snd_gus_card *gus, struct snd_gus_voice *voice); | ||
| 35 | |||
| 36 | static void sample_start(struct snd_gus_card *gus, struct snd_gus_voice *voice, snd_seq_position_t position); | ||
| 37 | static void sample_stop(struct snd_gus_card *gus, struct snd_gus_voice *voice, int mode); | ||
| 38 | static void sample_freq(struct snd_gus_card *gus, struct snd_gus_voice *voice, snd_seq_frequency_t freq); | ||
| 39 | static void sample_volume(struct snd_gus_card *card, struct snd_gus_voice *voice, struct snd_seq_ev_volume *volume); | ||
| 40 | static void sample_loop(struct snd_gus_card *card, struct snd_gus_voice *voice, struct snd_seq_ev_loop *loop); | ||
| 41 | static void sample_pos(struct snd_gus_card *card, struct snd_gus_voice *voice, snd_seq_position_t position); | ||
| 42 | static void sample_private1(struct snd_gus_card *card, struct snd_gus_voice *voice, unsigned char *data); | ||
| 43 | |||
| 44 | static struct snd_gus_sample_ops sample_ops = { | ||
| 45 | sample_start, | ||
| 46 | sample_stop, | ||
| 47 | sample_freq, | ||
| 48 | sample_volume, | ||
| 49 | sample_loop, | ||
| 50 | sample_pos, | ||
| 51 | sample_private1 | ||
| 52 | }; | ||
| 53 | |||
| 54 | #if 0 | ||
| 55 | |||
| 56 | static void note_stop(struct snd_gus_card *gus, struct snd_gus_voice *voice, int wait); | ||
| 57 | static void note_wait(struct snd_gus_card *gus, struct snd_gus_voice *voice); | ||
| 58 | static void note_off(struct snd_gus_card *gus, struct snd_gus_voice *voice); | ||
| 59 | static void note_volume(struct snd_gus_card *card, struct snd_gus_voice *voice); | ||
| 60 | static void note_pitchbend(struct snd_gus_card *card, struct snd_gus_voice *voice); | ||
| 61 | static void note_vibrato(struct snd_gus_card *card, struct snd_gus_voice *voice); | ||
| 62 | static void note_tremolo(struct snd_gus_card *card, struct snd_gus_voice *voice); | ||
| 63 | |||
| 64 | static struct snd_gus_note_handlers note_commands = { | ||
| 65 | note_stop, | ||
| 66 | note_wait, | ||
| 67 | note_off, | ||
| 68 | note_volume, | ||
| 69 | note_pitchbend, | ||
| 70 | note_vibrato, | ||
| 71 | note_tremolo | ||
| 72 | }; | ||
| 73 | |||
| 74 | static void chn_trigger_down(struct snd_gus_card *card, ultra_channel_t *channel, ultra_instrument_t *instrument, unsigned char note, unsigned char velocity, unsigned char priority ); | ||
| 75 | static void chn_trigger_up( ultra_card_t *card, ultra_note_t *note ); | ||
| 76 | static void chn_control( ultra_card_t *card, ultra_channel_t *channel, unsigned short p1, unsigned short p2 ); | ||
| 77 | |||
| 78 | static struct ULTRA_STRU_INSTRUMENT_CHANNEL_COMMANDS channel_commands = { | ||
| 79 | chn_trigger_down, | ||
| 80 | chn_trigger_up, | ||
| 81 | chn_control | ||
| 82 | }; | ||
| 83 | |||
| 84 | #endif | ||
| 85 | |||
| 86 | static void do_volume_envelope(struct snd_gus_card *card, struct snd_gus_voice *voice); | ||
| 87 | static void do_pan_envelope(struct snd_gus_card *card, struct snd_gus_voice *voice); | ||
| 88 | |||
| 89 | /* | ||
| 90 | * | ||
| 91 | */ | ||
| 92 | |||
| 93 | static void interrupt_wave(struct snd_gus_card *gus, struct snd_gus_voice *voice) | ||
| 94 | { | ||
| 95 | spin_lock(&gus->event_lock); | ||
| 96 | snd_gf1_stop_voice(gus, voice->number); | ||
| 97 | spin_lock(&gus->reg_lock); | ||
| 98 | snd_gf1_select_voice(gus, voice->number); | ||
| 99 | snd_gf1_write16(gus, SNDRV_GF1_VW_VOLUME, 0); | ||
| 100 | spin_unlock(&gus->reg_lock); | ||
| 101 | voice->flags &= ~SNDRV_GF1_VFLG_RUNNING; | ||
| 102 | spin_unlock(&gus->event_lock); | ||
| 103 | } | ||
| 104 | |||
| 105 | static void interrupt_volume(struct snd_gus_card *gus, struct snd_gus_voice *voice) | ||
| 106 | { | ||
| 107 | spin_lock(&gus->event_lock); | ||
| 108 | if (voice->flags & SNDRV_GF1_VFLG_RUNNING) | ||
| 109 | do_volume_envelope(gus, voice); | ||
| 110 | else | ||
| 111 | snd_gf1_stop_voice(gus, voice->number); | ||
| 112 | spin_unlock(&gus->event_lock); | ||
| 113 | } | ||
| 114 | |||
| 115 | static void interrupt_effect(struct snd_gus_card *gus, struct snd_gus_voice *voice) | ||
| 116 | { | ||
| 117 | spin_lock(&gus->event_lock); | ||
| 118 | if ((voice->flags & (SNDRV_GF1_VFLG_RUNNING|SNDRV_GF1_VFLG_EFFECT_TIMER1)) == | ||
| 119 | (SNDRV_GF1_VFLG_RUNNING|SNDRV_GF1_VFLG_EFFECT_TIMER1)) | ||
| 120 | do_pan_envelope(gus, voice); | ||
| 121 | spin_unlock(&gus->event_lock); | ||
| 122 | } | ||
| 123 | |||
| 124 | /* | ||
| 125 | * | ||
| 126 | */ | ||
| 127 | |||
| 128 | static void do_volume_envelope(struct snd_gus_card *gus, struct snd_gus_voice *voice) | ||
| 129 | { | ||
| 130 | unsigned short next, rate, old_volume; | ||
| 131 | int program_next_ramp; | ||
| 132 | unsigned long flags; | ||
| 133 | |||
| 134 | if (!gus->gf1.volume_ramp) { | ||
| 135 | spin_lock_irqsave(&gus->reg_lock, flags); | ||
| 136 | snd_gf1_select_voice(gus, voice->number); | ||
| 137 | snd_gf1_ctrl_stop(gus, SNDRV_GF1_VB_VOLUME_CONTROL); | ||
| 138 | snd_gf1_write16(gus, SNDRV_GF1_VW_VOLUME, voice->gf1_volume); | ||
| 139 | /* printk("gf1_volume = 0x%x\n", voice->gf1_volume); */ | ||
| 140 | spin_unlock_irqrestore(&gus->reg_lock, flags); | ||
| 141 | return; | ||
| 142 | } | ||
| 143 | program_next_ramp = 0; | ||
| 144 | rate = next = 0; | ||
| 145 | while (1) { | ||
| 146 | program_next_ramp = 0; | ||
| 147 | rate = next = 0; | ||
| 148 | switch (voice->venv_state) { | ||
| 149 | case VENV_BEFORE: | ||
| 150 | voice->venv_state = VENV_ATTACK; | ||
| 151 | voice->venv_value_next = 0; | ||
| 152 | spin_lock_irqsave(&gus->reg_lock, flags); | ||
| 153 | snd_gf1_select_voice(gus, voice->number); | ||
| 154 | snd_gf1_ctrl_stop(gus, SNDRV_GF1_VB_VOLUME_CONTROL); | ||
| 155 | snd_gf1_write16(gus, SNDRV_GF1_VW_VOLUME, SNDRV_GF1_MIN_VOLUME); | ||
| 156 | spin_unlock_irqrestore(&gus->reg_lock, flags); | ||
| 157 | break; | ||
| 158 | case VENV_ATTACK: | ||
| 159 | voice->venv_state = VENV_SUSTAIN; | ||
| 160 | program_next_ramp++; | ||
| 161 | next = 255; | ||
| 162 | rate = gus->gf1.volume_ramp; | ||
| 163 | break; | ||
| 164 | case VENV_SUSTAIN: | ||
| 165 | voice->venv_state = VENV_RELEASE; | ||
| 166 | spin_lock_irqsave(&gus->reg_lock, flags); | ||
| 167 | snd_gf1_select_voice(gus, voice->number); | ||
| 168 | snd_gf1_ctrl_stop(gus, SNDRV_GF1_VB_VOLUME_CONTROL); | ||
| 169 | snd_gf1_write16(gus, SNDRV_GF1_VW_VOLUME, ((int)voice->gf1_volume * (int)voice->venv_value_next) / 255); | ||
| 170 | spin_unlock_irqrestore(&gus->reg_lock, flags); | ||
| 171 | return; | ||
| 172 | case VENV_RELEASE: | ||
| 173 | voice->venv_state = VENV_DONE; | ||
| 174 | program_next_ramp++; | ||
| 175 | next = 0; | ||
| 176 | rate = gus->gf1.volume_ramp; | ||
| 177 | break; | ||
| 178 | case VENV_DONE: | ||
| 179 | snd_gf1_stop_voice(gus, voice->number); | ||
| 180 | voice->flags &= ~SNDRV_GF1_VFLG_RUNNING; | ||
| 181 | return; | ||
| 182 | case VENV_VOLUME: | ||
| 183 | program_next_ramp++; | ||
| 184 | next = voice->venv_value_next; | ||
| 185 | rate = gus->gf1.volume_ramp; | ||
| 186 | voice->venv_state = voice->venv_state_prev; | ||
| 187 | break; | ||
| 188 | } | ||
| 189 | voice->venv_value_next = next; | ||
| 190 | if (!program_next_ramp) | ||
| 191 | continue; | ||
| 192 | spin_lock_irqsave(&gus->reg_lock, flags); | ||
| 193 | snd_gf1_select_voice(gus, voice->number); | ||
| 194 | snd_gf1_ctrl_stop(gus, SNDRV_GF1_VB_VOLUME_CONTROL); | ||
| 195 | old_volume = snd_gf1_read16(gus, SNDRV_GF1_VW_VOLUME) >> 8; | ||
| 196 | if (!rate) { | ||
| 197 | spin_unlock_irqrestore(&gus->reg_lock, flags); | ||
| 198 | continue; | ||
| 199 | } | ||
| 200 | next = (((int)voice->gf1_volume * (int)next) / 255) >> 8; | ||
| 201 | if (old_volume < SNDRV_GF1_MIN_OFFSET) | ||
| 202 | old_volume = SNDRV_GF1_MIN_OFFSET; | ||
| 203 | if (next < SNDRV_GF1_MIN_OFFSET) | ||
| 204 | next = SNDRV_GF1_MIN_OFFSET; | ||
| 205 | if (next > SNDRV_GF1_MAX_OFFSET) | ||
| 206 | next = SNDRV_GF1_MAX_OFFSET; | ||
| 207 | if (old_volume == next) { | ||
| 208 | spin_unlock_irqrestore(&gus->reg_lock, flags); | ||
| 209 | continue; | ||
| 210 | } | ||
| 211 | voice->volume_control &= ~0xc3; | ||
| 212 | voice->volume_control |= 0x20; | ||
| 213 | if (old_volume > next) { | ||
| 214 | snd_gf1_write8(gus, SNDRV_GF1_VB_VOLUME_START, next); | ||
| 215 | snd_gf1_write8(gus, SNDRV_GF1_VB_VOLUME_END, old_volume); | ||
| 216 | voice->volume_control |= 0x40; | ||
| 217 | } else { | ||
| 218 | snd_gf1_write8(gus, SNDRV_GF1_VB_VOLUME_START, old_volume); | ||
| 219 | snd_gf1_write8(gus, SNDRV_GF1_VB_VOLUME_END, next); | ||
| 220 | } | ||
| 221 | snd_gf1_write8(gus, SNDRV_GF1_VB_VOLUME_RATE, rate); | ||
| 222 | snd_gf1_write8(gus, SNDRV_GF1_VB_VOLUME_CONTROL, voice->volume_control); | ||
| 223 | if (!gus->gf1.enh_mode) { | ||
| 224 | snd_gf1_delay(gus); | ||
| 225 | snd_gf1_write8(gus, SNDRV_GF1_VB_VOLUME_CONTROL, voice->volume_control); | ||
| 226 | } | ||
| 227 | spin_unlock_irqrestore(&gus->reg_lock, flags); | ||
| 228 | return; | ||
| 229 | } | ||
| 230 | } | ||
| 231 | |||
| 232 | static void do_pan_envelope(struct snd_gus_card *gus, struct snd_gus_voice *voice) | ||
| 233 | { | ||
| 234 | unsigned long flags; | ||
| 235 | unsigned char old_pan; | ||
| 236 | |||
| 237 | #if 0 | ||
| 238 | snd_gf1_select_voice(gus, voice->number); | ||
| 239 | printk(" -%i- do_pan_envelope - flags = 0x%x (0x%x -> 0x%x)\n", | ||
| 240 | voice->number, | ||
| 241 | voice->flags, | ||
| 242 | voice->gf1_pan, | ||
| 243 | snd_gf1_i_read8(gus, SNDRV_GF1_VB_PAN) & 0x0f); | ||
| 244 | #endif | ||
| 245 | if (gus->gf1.enh_mode) { | ||
| 246 | voice->flags &= ~(SNDRV_GF1_VFLG_EFFECT_TIMER1|SNDRV_GF1_VFLG_PAN); | ||
| 247 | return; | ||
| 248 | } | ||
| 249 | if (!gus->gf1.smooth_pan) { | ||
| 250 | spin_lock_irqsave(&gus->reg_lock, flags); | ||
| 251 | snd_gf1_select_voice(gus, voice->number); | ||
| 252 | snd_gf1_write8(gus, SNDRV_GF1_VB_PAN, voice->gf1_pan); | ||
| 253 | spin_unlock_irqrestore(&gus->reg_lock, flags); | ||
| 254 | return; | ||
| 255 | } | ||
| 256 | if (!(voice->flags & SNDRV_GF1_VFLG_PAN)) /* before */ | ||
| 257 | voice->flags |= SNDRV_GF1_VFLG_EFFECT_TIMER1|SNDRV_GF1_VFLG_PAN; | ||
| 258 | spin_lock_irqsave(&gus->reg_lock, flags); | ||
| 259 | snd_gf1_select_voice(gus, voice->number); | ||
| 260 | old_pan = snd_gf1_read8(gus, SNDRV_GF1_VB_PAN) & 0x0f; | ||
| 261 | if (old_pan > voice->gf1_pan ) | ||
| 262 | old_pan--; | ||
| 263 | if (old_pan < voice->gf1_pan) | ||
| 264 | old_pan++; | ||
| 265 | snd_gf1_write8(gus, SNDRV_GF1_VB_PAN, old_pan); | ||
| 266 | spin_unlock_irqrestore(&gus->reg_lock, flags); | ||
| 267 | if (old_pan == voice->gf1_pan) /* the goal was reached */ | ||
| 268 | voice->flags &= ~(SNDRV_GF1_VFLG_EFFECT_TIMER1|SNDRV_GF1_VFLG_PAN); | ||
| 269 | #if 0 | ||
| 270 | snd_gf1_select_voice(gus, voice->number); | ||
| 271 | printk(" -%i- (1) do_pan_envelope - flags = 0x%x (0x%x -> 0x%x)\n", | ||
| 272 | voice->number, | ||
| 273 | voice->flags, | ||
| 274 | voice->gf1_pan, | ||
| 275 | snd_gf1_i_read8(gus, GF1_VB_PAN) & 0x0f); | ||
| 276 | #endif | ||
| 277 | } | ||
| 278 | |||
| 279 | static void set_enhanced_pan(struct snd_gus_card *gus, struct snd_gus_voice *voice, unsigned short pan) | ||
| 280 | { | ||
| 281 | unsigned long flags; | ||
| 282 | unsigned short vlo, vro; | ||
| 283 | |||
| 284 | vlo = SNDRV_GF1_ATTEN((SNDRV_GF1_ATTEN_TABLE_SIZE-1) - pan); | ||
| 285 | vro = SNDRV_GF1_ATTEN(pan); | ||
| 286 | if (pan != SNDRV_GF1_ATTEN_TABLE_SIZE - 1 && pan != 0) { | ||
| 287 | vlo >>= 1; | ||
| 288 | vro >>= 1; | ||
| 289 | } | ||
| 290 | vlo <<= 4; | ||
| 291 | vro <<= 4; | ||
| 292 | #if 0 | ||
| 293 | printk("vlo = 0x%x (0x%x), vro = 0x%x (0x%x)\n", | ||
| 294 | vlo, snd_gf1_i_read16(gus, GF1_VW_OFFSET_LEFT), | ||
| 295 | vro, snd_gf1_i_read16(gus, GF1_VW_OFFSET_RIGHT)); | ||
| 296 | #endif | ||
| 297 | spin_lock_irqsave(&gus->reg_lock, flags); | ||
| 298 | snd_gf1_select_voice(gus, voice->number); | ||
| 299 | snd_gf1_write16(gus, SNDRV_GF1_VW_OFFSET_LEFT_FINAL, vlo); | ||
| 300 | snd_gf1_write16(gus, SNDRV_GF1_VW_OFFSET_RIGHT_FINAL, vro); | ||
| 301 | spin_unlock_irqrestore(&gus->reg_lock, flags); | ||
| 302 | voice->vlo = vlo; | ||
| 303 | voice->vro = vro; | ||
| 304 | } | ||
| 305 | |||
| 306 | /* | ||
| 307 | * | ||
| 308 | */ | ||
| 309 | |||
| 310 | static void sample_start(struct snd_gus_card *gus, struct snd_gus_voice *voice, snd_seq_position_t position) | ||
| 311 | { | ||
| 312 | unsigned long flags; | ||
| 313 | unsigned int begin, addr, addr_end, addr_start; | ||
| 314 | int w_16; | ||
| 315 | struct simple_instrument *simple; | ||
| 316 | struct snd_seq_kinstr *instr; | ||
| 317 | |||
| 318 | instr = snd_seq_instr_find(gus->gf1.ilist, &voice->instr, 0, 1); | ||
| 319 | if (instr == NULL) | ||
| 320 | return; | ||
| 321 | voice->instr = instr->instr; /* copy ID to speedup aliases */ | ||
| 322 | simple = KINSTR_DATA(instr); | ||
| 323 | begin = simple->address.memory << 4; | ||
| 324 | w_16 = simple->format & SIMPLE_WAVE_16BIT ? 0x04 : 0; | ||
| 325 | addr_start = simple->loop_start; | ||
| 326 | if (simple->format & SIMPLE_WAVE_LOOP) { | ||
| 327 | addr_end = simple->loop_end; | ||
| 328 | } else { | ||
| 329 | addr_end = (simple->size << 4) - (w_16 ? 40 : 24); | ||
| 330 | } | ||
| 331 | if (simple->format & SIMPLE_WAVE_BACKWARD) { | ||
| 332 | addr = simple->loop_end; | ||
| 333 | if (position < simple->loop_end) | ||
| 334 | addr -= position; | ||
| 335 | } else { | ||
| 336 | addr = position; | ||
| 337 | } | ||
| 338 | voice->control = 0x00; | ||
| 339 | voice->mode = 0x20; /* enable offset registers */ | ||
| 340 | if (simple->format & SIMPLE_WAVE_16BIT) | ||
| 341 | voice->control |= 0x04; | ||
| 342 | if (simple->format & SIMPLE_WAVE_BACKWARD) | ||
| 343 | voice->control |= 0x40; | ||
| 344 | if (simple->format & SIMPLE_WAVE_LOOP) { | ||
| 345 | voice->control |= 0x08; | ||
| 346 | } else { | ||
| 347 | voice->control |= 0x20; | ||
| 348 | } | ||
| 349 | if (simple->format & SIMPLE_WAVE_BIDIR) | ||
| 350 | voice->control |= 0x10; | ||
| 351 | if (simple->format & SIMPLE_WAVE_ULAW) | ||
| 352 | voice->mode |= 0x40; | ||
| 353 | if (w_16) { | ||
| 354 | addr = ((addr << 1) & ~0x1f) | (addr & 0x0f); | ||
| 355 | addr_start = ((addr_start << 1) & ~0x1f) | (addr_start & 0x0f); | ||
| 356 | addr_end = ((addr_end << 1) & ~0x1f) | (addr_end & 0x0f); | ||
| 357 | } | ||
| 358 | addr += begin; | ||
| 359 | addr_start += begin; | ||
| 360 | addr_end += begin; | ||
| 361 | snd_gf1_stop_voice(gus, voice->number); | ||
| 362 | spin_lock_irqsave(&gus->reg_lock, flags); | ||
| 363 | snd_gf1_select_voice(gus, voice->number); | ||
| 364 | snd_gf1_write16(gus, SNDRV_GF1_VW_FREQUENCY, voice->fc_register + voice->fc_lfo); | ||
| 365 | voice->venv_state = VENV_BEFORE; | ||
| 366 | voice->volume_control = 0x03; | ||
| 367 | snd_gf1_write_addr(gus, SNDRV_GF1_VA_START, addr_start, w_16); | ||
| 368 | snd_gf1_write_addr(gus, SNDRV_GF1_VA_END, addr_end, w_16); | ||
| 369 | snd_gf1_write_addr(gus, SNDRV_GF1_VA_CURRENT, addr, w_16); | ||
| 370 | if (!gus->gf1.enh_mode) { | ||
| 371 | snd_gf1_write8(gus, SNDRV_GF1_VB_PAN, voice->gf1_pan); | ||
| 372 | } else { | ||
| 373 | snd_gf1_write16(gus, SNDRV_GF1_VW_OFFSET_LEFT, voice->vlo); | ||
| 374 | snd_gf1_write16(gus, SNDRV_GF1_VW_OFFSET_LEFT_FINAL, voice->vlo); | ||
| 375 | snd_gf1_write16(gus, SNDRV_GF1_VW_OFFSET_RIGHT, voice->vro); | ||
| 376 | snd_gf1_write16(gus, SNDRV_GF1_VW_OFFSET_RIGHT_FINAL, voice->vro); | ||
| 377 | snd_gf1_write8(gus, SNDRV_GF1_VB_ACCUMULATOR, voice->effect_accumulator); | ||
| 378 | snd_gf1_write16(gus, SNDRV_GF1_VW_EFFECT_VOLUME, voice->gf1_effect_volume); | ||
| 379 | snd_gf1_write16(gus, SNDRV_GF1_VW_EFFECT_VOLUME_FINAL, voice->gf1_effect_volume); | ||
| 380 | } | ||
| 381 | spin_unlock_irqrestore(&gus->reg_lock, flags); | ||
| 382 | do_volume_envelope(gus, voice); | ||
| 383 | spin_lock_irqsave(&gus->reg_lock, flags); | ||
| 384 | snd_gf1_select_voice(gus, voice->number); | ||
| 385 | if (gus->gf1.enh_mode) | ||
| 386 | snd_gf1_write8(gus, SNDRV_GF1_VB_MODE, voice->mode); | ||
| 387 | snd_gf1_write8(gus, SNDRV_GF1_VB_ADDRESS_CONTROL, voice->control); | ||
| 388 | if (!gus->gf1.enh_mode) { | ||
| 389 | snd_gf1_delay(gus); | ||
| 390 | snd_gf1_write8(gus, SNDRV_GF1_VB_ADDRESS_CONTROL, voice->control ); | ||
| 391 | } | ||
| 392 | spin_unlock_irqrestore(&gus->reg_lock, flags); | ||
| 393 | #if 0 | ||
| 394 | snd_gf1_print_voice_registers(gus); | ||
| 395 | #endif | ||
| 396 | voice->flags |= SNDRV_GF1_VFLG_RUNNING; | ||
| 397 | snd_seq_instr_free_use(gus->gf1.ilist, instr); | ||
| 398 | } | ||
| 399 | |||
| 400 | static void sample_stop(struct snd_gus_card *gus, struct snd_gus_voice *voice, int mode) | ||
| 401 | { | ||
| 402 | unsigned char control; | ||
| 403 | unsigned long flags; | ||
| 404 | |||
| 405 | if (!(voice->flags & SNDRV_GF1_VFLG_RUNNING)) | ||
| 406 | return; | ||
| 407 | switch (mode) { | ||
| 408 | default: | ||
| 409 | if (gus->gf1.volume_ramp > 0) { | ||
| 410 | if (voice->venv_state < VENV_RELEASE) { | ||
| 411 | voice->venv_state = VENV_RELEASE; | ||
| 412 | do_volume_envelope(gus, voice); | ||
| 413 | } | ||
| 414 | } | ||
| 415 | if (mode != SAMPLE_STOP_VENVELOPE) { | ||
| 416 | snd_gf1_stop_voice(gus, voice->number); | ||
| 417 | spin_lock_irqsave(&gus->reg_lock, flags); | ||
| 418 | snd_gf1_select_voice(gus, voice->number); | ||
| 419 | snd_gf1_write16(gus, SNDRV_GF1_VW_VOLUME, SNDRV_GF1_MIN_VOLUME); | ||
| 420 | spin_unlock_irqrestore(&gus->reg_lock, flags); | ||
| 421 | voice->flags &= ~SNDRV_GF1_VFLG_RUNNING; | ||
| 422 | } | ||
| 423 | break; | ||
| 424 | case SAMPLE_STOP_LOOP: /* disable loop only */ | ||
| 425 | spin_lock_irqsave(&gus->reg_lock, flags); | ||
| 426 | snd_gf1_select_voice(gus, voice->number); | ||
| 427 | control = snd_gf1_read8(gus, SNDRV_GF1_VB_ADDRESS_CONTROL); | ||
| 428 | control &= ~(0x83 | 0x04); | ||
| 429 | control |= 0x20; | ||
| 430 | snd_gf1_write8(gus, SNDRV_GF1_VB_ADDRESS_CONTROL, control); | ||
| 431 | spin_unlock_irqrestore(&gus->reg_lock, flags); | ||
| 432 | break; | ||
| 433 | } | ||
| 434 | } | ||
| 435 | |||
| 436 | static void sample_freq(struct snd_gus_card *gus, struct snd_gus_voice *voice, snd_seq_frequency_t freq) | ||
| 437 | { | ||
| 438 | unsigned long flags; | ||
| 439 | |||
| 440 | spin_lock_irqsave(&gus->reg_lock, flags); | ||
| 441 | voice->fc_register = snd_gf1_translate_freq(gus, freq); | ||
| 442 | snd_gf1_select_voice(gus, voice->number); | ||
| 443 | snd_gf1_write16(gus, SNDRV_GF1_VW_FREQUENCY, voice->fc_register + voice->fc_lfo); | ||
| 444 | spin_unlock_irqrestore(&gus->reg_lock, flags); | ||
| 445 | } | ||
| 446 | |||
| 447 | static void sample_volume(struct snd_gus_card *gus, struct snd_gus_voice *voice, struct snd_seq_ev_volume *volume) | ||
| 448 | { | ||
| 449 | if (volume->volume >= 0) { | ||
| 450 | volume->volume &= 0x3fff; | ||
| 451 | voice->gf1_volume = snd_gf1_lvol_to_gvol_raw(volume->volume << 2) << 4; | ||
| 452 | voice->venv_state_prev = VENV_SUSTAIN; | ||
| 453 | voice->venv_state = VENV_VOLUME; | ||
| 454 | do_volume_envelope(gus, voice); | ||
| 455 | } | ||
| 456 | if (volume->lr >= 0) { | ||
| 457 | volume->lr &= 0x3fff; | ||
| 458 | if (!gus->gf1.enh_mode) { | ||
| 459 | voice->gf1_pan = (volume->lr >> 10) & 15; | ||
| 460 | if (!gus->gf1.full_range_pan) { | ||
| 461 | if (voice->gf1_pan == 0) | ||
| 462 | voice->gf1_pan++; | ||
| 463 | if (voice->gf1_pan == 15) | ||
| 464 | voice->gf1_pan--; | ||
| 465 | } | ||
| 466 | voice->flags &= ~SNDRV_GF1_VFLG_PAN; /* before */ | ||
| 467 | do_pan_envelope(gus, voice); | ||
| 468 | } else { | ||
| 469 | set_enhanced_pan(gus, voice, volume->lr >> 7); | ||
| 470 | } | ||
| 471 | } | ||
| 472 | } | ||
| 473 | |||
| 474 | static void sample_loop(struct snd_gus_card *gus, struct snd_gus_voice *voice, struct snd_seq_ev_loop *loop) | ||
| 475 | { | ||
| 476 | unsigned long flags; | ||
| 477 | int w_16 = voice->control & 0x04; | ||
| 478 | unsigned int begin, addr_start, addr_end; | ||
| 479 | struct simple_instrument *simple; | ||
| 480 | struct snd_seq_kinstr *instr; | ||
| 481 | |||
| 482 | #if 0 | ||
| 483 | printk("voice_loop: start = 0x%x, end = 0x%x\n", loop->start, loop->end); | ||
| 484 | #endif | ||
| 485 | instr = snd_seq_instr_find(gus->gf1.ilist, &voice->instr, 0, 1); | ||
| 486 | if (instr == NULL) | ||
| 487 | return; | ||
| 488 | voice->instr = instr->instr; /* copy ID to speedup aliases */ | ||
| 489 | simple = KINSTR_DATA(instr); | ||
| 490 | begin = simple->address.memory; | ||
| 491 | addr_start = loop->start; | ||
| 492 | addr_end = loop->end; | ||
| 493 | addr_start = (((addr_start << 1) & ~0x1f) | (addr_start & 0x0f)) + begin; | ||
| 494 | addr_end = (((addr_end << 1) & ~0x1f) | (addr_end & 0x0f)) + begin; | ||
| 495 | spin_lock_irqsave(&gus->reg_lock, flags); | ||
| 496 | snd_gf1_select_voice(gus, voice->number); | ||
| 497 | snd_gf1_write_addr(gus, SNDRV_GF1_VA_START, addr_start, w_16); | ||
| 498 | snd_gf1_write_addr(gus, SNDRV_GF1_VA_END, addr_end, w_16); | ||
| 499 | spin_unlock_irqrestore(&gus->reg_lock, flags); | ||
| 500 | snd_seq_instr_free_use(gus->gf1.ilist, instr); | ||
| 501 | } | ||
| 502 | |||
| 503 | static void sample_pos(struct snd_gus_card *gus, struct snd_gus_voice *voice, snd_seq_position_t position) | ||
| 504 | { | ||
| 505 | unsigned long flags; | ||
| 506 | int w_16 = voice->control & 0x04; | ||
| 507 | unsigned int begin, addr; | ||
| 508 | struct simple_instrument *simple; | ||
| 509 | struct snd_seq_kinstr *instr; | ||
| 510 | |||
| 511 | #if 0 | ||
| 512 | printk("voice_loop: start = 0x%x, end = 0x%x\n", loop->start, loop->end); | ||
| 513 | #endif | ||
| 514 | instr = snd_seq_instr_find(gus->gf1.ilist, &voice->instr, 0, 1); | ||
| 515 | if (instr == NULL) | ||
| 516 | return; | ||
| 517 | voice->instr = instr->instr; /* copy ID to speedup aliases */ | ||
| 518 | simple = KINSTR_DATA(instr); | ||
| 519 | begin = simple->address.memory; | ||
| 520 | addr = (((position << 1) & ~0x1f) | (position & 0x0f)) + begin; | ||
| 521 | spin_lock_irqsave(&gus->reg_lock, flags); | ||
| 522 | snd_gf1_select_voice(gus, voice->number); | ||
| 523 | snd_gf1_write_addr(gus, SNDRV_GF1_VA_CURRENT, addr, w_16); | ||
| 524 | spin_unlock_irqrestore(&gus->reg_lock, flags); | ||
| 525 | snd_seq_instr_free_use(gus->gf1.ilist, instr); | ||
| 526 | } | ||
| 527 | |||
| 528 | #if 0 | ||
| 529 | |||
| 530 | static unsigned char get_effects_mask( ultra_card_t *card, int value ) | ||
| 531 | { | ||
| 532 | if ( value > 7 ) return 0; | ||
| 533 | if ( card -> gf1.effects && card -> gf1.effects -> chip_type == ULTRA_EFFECT_CHIP_INTERWAVE ) | ||
| 534 | return card -> gf1.effects -> chip.interwave.voice_output[ value ]; | ||
| 535 | return 0; | ||
| 536 | } | ||
| 537 | |||
| 538 | #endif | ||
| 539 | |||
| 540 | static void sample_private1(struct snd_gus_card *card, struct snd_gus_voice *voice, unsigned char *data) | ||
| 541 | { | ||
| 542 | #if 0 | ||
| 543 | unsigned long flags; | ||
| 544 | unsigned char uc; | ||
| 545 | |||
| 546 | switch ( *data ) { | ||
| 547 | case ULTRA_PRIV1_IW_EFFECT: | ||
| 548 | uc = get_effects_mask( card, ultra_get_byte( data, 4 ) ); | ||
| 549 | uc |= get_effects_mask( card, ultra_get_byte( data, 4 ) >> 4 ); | ||
| 550 | uc |= get_effects_mask( card, ultra_get_byte( data, 5 ) ); | ||
| 551 | uc |= get_effects_mask( card, ultra_get_byte( data, 5 ) >> 4 ); | ||
| 552 | voice -> data.simple.effect_accumulator = uc; | ||
| 553 | voice -> data.simple.effect_volume = ultra_translate_voice_volume( card, ultra_get_word( data, 2 ) ) << 4; | ||
| 554 | if ( !card -> gf1.enh_mode ) return; | ||
| 555 | if ( voice -> flags & VFLG_WAIT_FOR_START ) return; | ||
| 556 | if ( voice -> flags & VFLG_RUNNING ) | ||
| 557 | { | ||
| 558 | CLI( &flags ); | ||
| 559 | gf1_select_voice( card, voice -> number ); | ||
| 560 | ultra_write8( card, GF1_VB_ACCUMULATOR, voice -> data.simple.effect_accumulator ); | ||
| 561 | ultra_write16( card, GF1_VW_EFFECT_VOLUME_FINAL, voice -> data.simple.effect_volume ); | ||
| 562 | STI( &flags ); | ||
| 563 | } | ||
| 564 | break; | ||
| 565 | case ULTRA_PRIV1_IW_LFO: | ||
| 566 | ultra_lfo_command( card, voice -> number, data ); | ||
| 567 | } | ||
| 568 | #endif | ||
| 569 | } | ||
| 570 | |||
| 571 | #if 0 | ||
| 572 | |||
| 573 | /* | ||
| 574 | * | ||
| 575 | */ | ||
| 576 | |||
| 577 | static void note_stop( ultra_card_t *card, ultra_voice_t *voice, int wait ) | ||
| 578 | { | ||
| 579 | } | ||
| 580 | |||
| 581 | static void note_wait( ultra_card_t *card, ultra_voice_t *voice ) | ||
| 582 | { | ||
| 583 | } | ||
| 584 | |||
| 585 | static void note_off( ultra_card_t *card, ultra_voice_t *voice ) | ||
| 586 | { | ||
| 587 | } | ||
| 588 | |||
| 589 | static void note_volume( ultra_card_t *card, ultra_voice_t *voice ) | ||
| 590 | { | ||
| 591 | } | ||
| 592 | |||
| 593 | static void note_pitchbend( ultra_card_t *card, ultra_voice_t *voice ) | ||
| 594 | { | ||
| 595 | } | ||
| 596 | |||
| 597 | static void note_vibrato( ultra_card_t *card, ultra_voice_t *voice ) | ||
| 598 | { | ||
| 599 | } | ||
| 600 | |||
| 601 | static void note_tremolo( ultra_card_t *card, ultra_voice_t *voice ) | ||
| 602 | { | ||
| 603 | } | ||
| 604 | |||
| 605 | /* | ||
| 606 | * | ||
| 607 | */ | ||
| 608 | |||
| 609 | static void chn_trigger_down( ultra_card_t *card, ultra_channel_t *channel, ultra_instrument_t *instrument, unsigned char note, unsigned char velocity, unsigned char priority ) | ||
| 610 | { | ||
| 611 | } | ||
| 612 | |||
| 613 | static void chn_trigger_up( ultra_card_t *card, ultra_note_t *note ) | ||
| 614 | { | ||
| 615 | } | ||
| 616 | |||
| 617 | static void chn_control( ultra_card_t *card, ultra_channel_t *channel, unsigned short p1, unsigned short p2 ) | ||
| 618 | { | ||
| 619 | } | ||
| 620 | |||
| 621 | /* | ||
| 622 | * | ||
| 623 | */ | ||
| 624 | |||
| 625 | #endif | ||
| 626 | |||
| 627 | void snd_gf1_simple_init(struct snd_gus_voice *voice) | ||
| 628 | { | ||
| 629 | voice->handler_wave = interrupt_wave; | ||
| 630 | voice->handler_volume = interrupt_volume; | ||
| 631 | voice->handler_effect = interrupt_effect; | ||
| 632 | voice->volume_change = NULL; | ||
| 633 | voice->sample_ops = &sample_ops; | ||
| 634 | } | ||
diff --git a/sound/isa/gus/gus_synth.c b/sound/isa/gus/gus_synth.c deleted file mode 100644 index 2c2051782aa2..000000000000 --- a/sound/isa/gus/gus_synth.c +++ /dev/null | |||
| @@ -1,314 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Routines for Gravis UltraSound soundcards - Synthesizer | ||
| 3 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> | ||
| 4 | * | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify | ||
| 7 | * it under the terms of the GNU General Public License as published by | ||
| 8 | * the Free Software Foundation; either version 2 of the License, or | ||
| 9 | * (at your option) any later version. | ||
| 10 | * | ||
| 11 | * This program is distributed in the hope that it will be useful, | ||
| 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 14 | * GNU General Public License for more details. | ||
| 15 | * | ||
| 16 | * You should have received a copy of the GNU General Public License | ||
| 17 | * along with this program; if not, write to the Free Software | ||
| 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 19 | * | ||
| 20 | */ | ||
| 21 | |||
| 22 | #include <sound/driver.h> | ||
| 23 | #include <linux/init.h> | ||
| 24 | #include <linux/time.h> | ||
| 25 | #include <sound/core.h> | ||
| 26 | #include <sound/gus.h> | ||
| 27 | #include <sound/seq_device.h> | ||
| 28 | |||
| 29 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); | ||
| 30 | MODULE_DESCRIPTION("Routines for Gravis UltraSound soundcards - Synthesizer"); | ||
| 31 | MODULE_LICENSE("GPL"); | ||
| 32 | |||
| 33 | /* | ||
| 34 | * | ||
| 35 | */ | ||
| 36 | |||
| 37 | static void snd_gus_synth_free_voices(struct snd_gus_card * gus, int client, int port) | ||
| 38 | { | ||
| 39 | int idx; | ||
| 40 | struct snd_gus_voice * voice; | ||
| 41 | |||
| 42 | for (idx = 0; idx < 32; idx++) { | ||
| 43 | voice = &gus->gf1.voices[idx]; | ||
| 44 | if (voice->use && voice->client == client && voice->port == port) | ||
| 45 | snd_gf1_free_voice(gus, voice); | ||
| 46 | } | ||
| 47 | } | ||
| 48 | |||
| 49 | static int snd_gus_synth_use(void *private_data, struct snd_seq_port_subscribe *info) | ||
| 50 | { | ||
| 51 | struct snd_gus_port * port = private_data; | ||
| 52 | struct snd_gus_card * gus = port->gus; | ||
| 53 | struct snd_gus_voice * voice; | ||
| 54 | unsigned int idx; | ||
| 55 | |||
| 56 | if (info->voices > 32) | ||
| 57 | return -EINVAL; | ||
| 58 | mutex_lock(&gus->register_mutex); | ||
| 59 | if (!snd_gus_use_inc(gus)) { | ||
| 60 | mutex_unlock(&gus->register_mutex); | ||
| 61 | return -EFAULT; | ||
| 62 | } | ||
| 63 | for (idx = 0; idx < info->voices; idx++) { | ||
| 64 | voice = snd_gf1_alloc_voice(gus, SNDRV_GF1_VOICE_TYPE_SYNTH, info->sender.client, info->sender.port); | ||
| 65 | if (voice == NULL) { | ||
| 66 | snd_gus_synth_free_voices(gus, info->sender.client, info->sender.port); | ||
| 67 | snd_gus_use_dec(gus); | ||
| 68 | mutex_unlock(&gus->register_mutex); | ||
| 69 | return -EBUSY; | ||
| 70 | } | ||
| 71 | voice->index = idx; | ||
| 72 | } | ||
| 73 | mutex_unlock(&gus->register_mutex); | ||
| 74 | return 0; | ||
| 75 | } | ||
| 76 | |||
| 77 | static int snd_gus_synth_unuse(void *private_data, struct snd_seq_port_subscribe *info) | ||
| 78 | { | ||
| 79 | struct snd_gus_port * port = private_data; | ||
| 80 | struct snd_gus_card * gus = port->gus; | ||
| 81 | |||
| 82 | mutex_lock(&gus->register_mutex); | ||
| 83 | snd_gus_synth_free_voices(gus, info->sender.client, info->sender.port); | ||
| 84 | snd_gus_use_dec(gus); | ||
| 85 | mutex_unlock(&gus->register_mutex); | ||
| 86 | return 0; | ||
| 87 | } | ||
| 88 | |||
| 89 | /* | ||
| 90 | * | ||
| 91 | */ | ||
| 92 | |||
| 93 | static void snd_gus_synth_free_private_instruments(struct snd_gus_port *p, int client) | ||
| 94 | { | ||
| 95 | struct snd_seq_instr_header ifree; | ||
| 96 | |||
| 97 | memset(&ifree, 0, sizeof(ifree)); | ||
| 98 | ifree.cmd = SNDRV_SEQ_INSTR_FREE_CMD_PRIVATE; | ||
| 99 | snd_seq_instr_list_free_cond(p->gus->gf1.ilist, &ifree, client, 0); | ||
| 100 | } | ||
| 101 | |||
| 102 | static int snd_gus_synth_event_input(struct snd_seq_event *ev, int direct, | ||
| 103 | void *private_data, int atomic, int hop) | ||
| 104 | { | ||
| 105 | struct snd_gus_port * p = private_data; | ||
| 106 | |||
| 107 | snd_assert(p != NULL, return -EINVAL); | ||
| 108 | if (ev->type >= SNDRV_SEQ_EVENT_SAMPLE && | ||
| 109 | ev->type <= SNDRV_SEQ_EVENT_SAMPLE_PRIVATE1) { | ||
| 110 | snd_gus_sample_event(ev, p); | ||
| 111 | return 0; | ||
| 112 | } | ||
| 113 | if (ev->source.client == SNDRV_SEQ_CLIENT_SYSTEM && | ||
| 114 | ev->source.port == SNDRV_SEQ_PORT_SYSTEM_ANNOUNCE) { | ||
| 115 | if (ev->type == SNDRV_SEQ_EVENT_CLIENT_EXIT) { | ||
| 116 | snd_gus_synth_free_private_instruments(p, ev->data.addr.client); | ||
| 117 | return 0; | ||
| 118 | } | ||
| 119 | } | ||
| 120 | if (direct) { | ||
| 121 | if (ev->type >= SNDRV_SEQ_EVENT_INSTR_BEGIN) { | ||
| 122 | snd_seq_instr_event(&p->gus->gf1.iwffff_ops.kops, | ||
| 123 | p->gus->gf1.ilist, | ||
| 124 | ev, | ||
| 125 | p->gus->gf1.seq_client, | ||
| 126 | atomic, hop); | ||
| 127 | return 0; | ||
| 128 | } | ||
| 129 | } | ||
| 130 | return 0; | ||
| 131 | } | ||
| 132 | |||
| 133 | static void snd_gus_synth_instr_notify(void *private_data, | ||
| 134 | struct snd_seq_kinstr *instr, | ||
| 135 | int what) | ||
| 136 | { | ||
| 137 | unsigned int idx; | ||
| 138 | struct snd_gus_card *gus = private_data; | ||
| 139 | struct snd_gus_voice *pvoice; | ||
| 140 | unsigned long flags; | ||
| 141 | |||
| 142 | spin_lock_irqsave(&gus->event_lock, flags); | ||
| 143 | for (idx = 0; idx < 32; idx++) { | ||
| 144 | pvoice = &gus->gf1.voices[idx]; | ||
| 145 | if (pvoice->use && !memcmp(&pvoice->instr, &instr->instr, sizeof(pvoice->instr))) { | ||
| 146 | if (pvoice->sample_ops && pvoice->sample_ops->sample_stop) { | ||
| 147 | pvoice->sample_ops->sample_stop(gus, pvoice, SAMPLE_STOP_IMMEDIATELY); | ||
| 148 | } else { | ||
| 149 | snd_gf1_stop_voice(gus, pvoice->number); | ||
| 150 | pvoice->flags &= ~SNDRV_GF1_VFLG_RUNNING; | ||
| 151 | } | ||
| 152 | } | ||
| 153 | } | ||
| 154 | spin_unlock_irqrestore(&gus->event_lock, flags); | ||
| 155 | } | ||
| 156 | |||
| 157 | /* | ||
| 158 | * | ||
| 159 | */ | ||
| 160 | |||
| 161 | static void snd_gus_synth_free_port(void *private_data) | ||
| 162 | { | ||
| 163 | struct snd_gus_port * p = private_data; | ||
| 164 | |||
| 165 | if (p) | ||
| 166 | snd_midi_channel_free_set(p->chset); | ||
| 167 | } | ||
| 168 | |||
| 169 | static int snd_gus_synth_create_port(struct snd_gus_card * gus, int idx) | ||
| 170 | { | ||
| 171 | struct snd_gus_port * p; | ||
| 172 | struct snd_seq_port_callback callbacks; | ||
| 173 | char name[32]; | ||
| 174 | int result; | ||
| 175 | |||
| 176 | p = &gus->gf1.seq_ports[idx]; | ||
| 177 | p->chset = snd_midi_channel_alloc_set(16); | ||
| 178 | if (p->chset == NULL) | ||
| 179 | return -ENOMEM; | ||
| 180 | p->chset->private_data = p; | ||
| 181 | p->gus = gus; | ||
| 182 | p->client = gus->gf1.seq_client; | ||
| 183 | |||
| 184 | memset(&callbacks, 0, sizeof(callbacks)); | ||
| 185 | callbacks.owner = THIS_MODULE; | ||
| 186 | callbacks.use = snd_gus_synth_use; | ||
| 187 | callbacks.unuse = snd_gus_synth_unuse; | ||
| 188 | callbacks.event_input = snd_gus_synth_event_input; | ||
| 189 | callbacks.private_free = snd_gus_synth_free_port; | ||
| 190 | callbacks.private_data = p; | ||
| 191 | |||
| 192 | sprintf(name, "%s port %i", gus->interwave ? "AMD InterWave" : "GF1", idx); | ||
| 193 | p->chset->port = snd_seq_event_port_attach(gus->gf1.seq_client, | ||
| 194 | &callbacks, | ||
| 195 | SNDRV_SEQ_PORT_CAP_WRITE | SNDRV_SEQ_PORT_CAP_SUBS_WRITE, | ||
| 196 | SNDRV_SEQ_PORT_TYPE_DIRECT_SAMPLE | | ||
| 197 | SNDRV_SEQ_PORT_TYPE_SYNTH | | ||
| 198 | SNDRV_SEQ_PORT_TYPE_HARDWARE | | ||
| 199 | SNDRV_SEQ_PORT_TYPE_SYNTHESIZER, | ||
| 200 | 16, 0, | ||
| 201 | name); | ||
| 202 | if (p->chset->port < 0) { | ||
| 203 | result = p->chset->port; | ||
| 204 | snd_gus_synth_free_port(p); | ||
| 205 | return result; | ||
| 206 | } | ||
| 207 | p->port = p->chset->port; | ||
| 208 | return 0; | ||
| 209 | } | ||
| 210 | |||
| 211 | /* | ||
| 212 | * | ||
| 213 | */ | ||
| 214 | |||
| 215 | static int snd_gus_synth_new_device(struct snd_seq_device *dev) | ||
| 216 | { | ||
| 217 | struct snd_gus_card *gus; | ||
| 218 | int client, i; | ||
| 219 | struct snd_seq_port_subscribe sub; | ||
| 220 | struct snd_iwffff_ops *iwops; | ||
| 221 | struct snd_gf1_ops *gf1ops; | ||
| 222 | struct snd_simple_ops *simpleops; | ||
| 223 | |||
| 224 | gus = *(struct snd_gus_card **)SNDRV_SEQ_DEVICE_ARGPTR(dev); | ||
| 225 | if (gus == NULL) | ||
| 226 | return -EINVAL; | ||
| 227 | |||
| 228 | mutex_init(&gus->register_mutex); | ||
| 229 | gus->gf1.seq_client = -1; | ||
| 230 | |||
| 231 | /* allocate new client */ | ||
| 232 | client = gus->gf1.seq_client = | ||
| 233 | snd_seq_create_kernel_client(gus->card, 1, gus->interwave ? | ||
| 234 | "AMD InterWave" : "GF1"); | ||
| 235 | if (client < 0) | ||
| 236 | return client; | ||
| 237 | |||
| 238 | for (i = 0; i < 4; i++) | ||
| 239 | snd_gus_synth_create_port(gus, i); | ||
| 240 | |||
| 241 | gus->gf1.ilist = snd_seq_instr_list_new(); | ||
| 242 | if (gus->gf1.ilist == NULL) { | ||
| 243 | snd_seq_delete_kernel_client(client); | ||
| 244 | gus->gf1.seq_client = -1; | ||
| 245 | return -ENOMEM; | ||
| 246 | } | ||
| 247 | gus->gf1.ilist->flags = SNDRV_SEQ_INSTR_FLG_DIRECT; | ||
| 248 | |||
| 249 | simpleops = &gus->gf1.simple_ops; | ||
| 250 | snd_seq_simple_init(simpleops, gus, NULL); | ||
| 251 | simpleops->put_sample = snd_gus_simple_put_sample; | ||
| 252 | simpleops->get_sample = snd_gus_simple_get_sample; | ||
| 253 | simpleops->remove_sample = snd_gus_simple_remove_sample; | ||
| 254 | simpleops->notify = snd_gus_synth_instr_notify; | ||
| 255 | |||
| 256 | gf1ops = &gus->gf1.gf1_ops; | ||
| 257 | snd_seq_gf1_init(gf1ops, gus, &simpleops->kops); | ||
| 258 | gf1ops->put_sample = snd_gus_gf1_put_sample; | ||
| 259 | gf1ops->get_sample = snd_gus_gf1_get_sample; | ||
| 260 | gf1ops->remove_sample = snd_gus_gf1_remove_sample; | ||
| 261 | gf1ops->notify = snd_gus_synth_instr_notify; | ||
| 262 | |||
| 263 | iwops = &gus->gf1.iwffff_ops; | ||
| 264 | snd_seq_iwffff_init(iwops, gus, &gf1ops->kops); | ||
| 265 | iwops->put_sample = snd_gus_iwffff_put_sample; | ||
| 266 | iwops->get_sample = snd_gus_iwffff_get_sample; | ||
| 267 | iwops->remove_sample = snd_gus_iwffff_remove_sample; | ||
| 268 | iwops->notify = snd_gus_synth_instr_notify; | ||
| 269 | |||
| 270 | memset(&sub, 0, sizeof(sub)); | ||
| 271 | sub.sender.client = SNDRV_SEQ_CLIENT_SYSTEM; | ||
| 272 | sub.sender.port = SNDRV_SEQ_PORT_SYSTEM_ANNOUNCE; | ||
| 273 | sub.dest.client = client; | ||
| 274 | sub.dest.port = 0; | ||
| 275 | snd_seq_kernel_client_ctl(client, SNDRV_SEQ_IOCTL_SUBSCRIBE_PORT, &sub); | ||
| 276 | |||
| 277 | return 0; | ||
| 278 | } | ||
| 279 | |||
| 280 | static int snd_gus_synth_delete_device(struct snd_seq_device *dev) | ||
| 281 | { | ||
| 282 | struct snd_gus_card *gus; | ||
| 283 | |||
| 284 | gus = *(struct snd_gus_card **)SNDRV_SEQ_DEVICE_ARGPTR(dev); | ||
| 285 | if (gus == NULL) | ||
| 286 | return -EINVAL; | ||
| 287 | |||
| 288 | if (gus->gf1.seq_client >= 0) { | ||
| 289 | snd_seq_delete_kernel_client(gus->gf1.seq_client); | ||
| 290 | gus->gf1.seq_client = -1; | ||
| 291 | } | ||
| 292 | if (gus->gf1.ilist) | ||
| 293 | snd_seq_instr_list_free(&gus->gf1.ilist); | ||
| 294 | return 0; | ||
| 295 | } | ||
| 296 | |||
| 297 | static int __init alsa_gus_synth_init(void) | ||
| 298 | { | ||
| 299 | static struct snd_seq_dev_ops ops = { | ||
| 300 | snd_gus_synth_new_device, | ||
| 301 | snd_gus_synth_delete_device | ||
| 302 | }; | ||
| 303 | |||
| 304 | return snd_seq_device_register_driver(SNDRV_SEQ_DEV_ID_GUS, &ops, | ||
| 305 | sizeof(struct snd_gus_card *)); | ||
| 306 | } | ||
| 307 | |||
| 308 | static void __exit alsa_gus_synth_exit(void) | ||
| 309 | { | ||
| 310 | snd_seq_device_unregister_driver(SNDRV_SEQ_DEV_ID_GUS); | ||
| 311 | } | ||
| 312 | |||
| 313 | module_init(alsa_gus_synth_init) | ||
| 314 | module_exit(alsa_gus_synth_exit) | ||
diff --git a/sound/pci/trident/Makefile b/sound/pci/trident/Makefile index 65f2c218324c..88676b50f385 100644 --- a/sound/pci/trident/Makefile +++ b/sound/pci/trident/Makefile | |||
| @@ -4,16 +4,6 @@ | |||
| 4 | # | 4 | # |
| 5 | 5 | ||
| 6 | snd-trident-objs := trident.o trident_main.o trident_memory.o | 6 | snd-trident-objs := trident.o trident_main.o trident_memory.o |
| 7 | snd-trident-synth-objs := trident_synth.o | ||
| 8 | |||
| 9 | # | ||
| 10 | # this function returns: | ||
| 11 | # "m" - CONFIG_SND_SEQUENCER is m | ||
| 12 | # <empty string> - CONFIG_SND_SEQUENCER is undefined | ||
| 13 | # otherwise parameter #1 value | ||
| 14 | # | ||
| 15 | sequencer = $(if $(subst y,,$(CONFIG_SND_SEQUENCER)),$(if $(1),m),$(if $(CONFIG_SND_SEQUENCER),$(1))) | ||
| 16 | 7 | ||
| 17 | # Toplevel Module Dependency | 8 | # Toplevel Module Dependency |
| 18 | obj-$(CONFIG_SND_TRIDENT) += snd-trident.o | 9 | obj-$(CONFIG_SND_TRIDENT) += snd-trident.o |
| 19 | obj-$(call sequencer,$(CONFIG_SND_TRIDENT)) += snd-trident-synth.o | ||
diff --git a/sound/pci/trident/trident.c b/sound/pci/trident/trident.c index 84884567df6a..6193c7e4d798 100644 --- a/sound/pci/trident/trident.c +++ b/sound/pci/trident/trident.c | |||
| @@ -155,13 +155,6 @@ static int __devinit snd_trident_probe(struct pci_dev *pci, | |||
| 155 | return err; | 155 | return err; |
| 156 | } | 156 | } |
| 157 | 157 | ||
| 158 | #if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE)) | ||
| 159 | if ((err = snd_trident_attach_synthesizer(trident)) < 0) { | ||
| 160 | snd_card_free(card); | ||
| 161 | return err; | ||
| 162 | } | ||
| 163 | #endif | ||
| 164 | |||
| 165 | snd_trident_create_gameport(trident); | 158 | snd_trident_create_gameport(trident); |
| 166 | 159 | ||
| 167 | if ((err = snd_card_register(card)) < 0) { | 160 | if ((err = snd_card_register(card)) < 0) { |
diff --git a/sound/pci/trident/trident_main.c b/sound/pci/trident/trident_main.c index a235e034a690..59a319568ae5 100644 --- a/sound/pci/trident/trident_main.c +++ b/sound/pci/trident/trident_main.c | |||
| @@ -3313,12 +3313,6 @@ static void snd_trident_proc_read(struct snd_info_entry *entry, | |||
| 3313 | snd_iprintf(buffer, "Memory Free : %d\n", snd_util_mem_avail(trident->tlb.memhdr)); | 3313 | snd_iprintf(buffer, "Memory Free : %d\n", snd_util_mem_avail(trident->tlb.memhdr)); |
| 3314 | } | 3314 | } |
| 3315 | } | 3315 | } |
| 3316 | #if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE)) | ||
| 3317 | snd_iprintf(buffer,"\nWavetable Synth\n"); | ||
| 3318 | snd_iprintf(buffer, "Memory Maximum : %d\n", trident->synth.max_size); | ||
| 3319 | snd_iprintf(buffer, "Memory Used : %d\n", trident->synth.current_size); | ||
| 3320 | snd_iprintf(buffer, "Memory Free : %d\n", (trident->synth.max_size-trident->synth.current_size)); | ||
| 3321 | #endif | ||
| 3322 | } | 3316 | } |
| 3323 | 3317 | ||
| 3324 | static void __devinit snd_trident_proc_init(struct snd_trident * trident) | 3318 | static void __devinit snd_trident_proc_init(struct snd_trident * trident) |
| @@ -3815,28 +3809,6 @@ static irqreturn_t snd_trident_interrupt(int irq, void *dev_id) | |||
| 3815 | return IRQ_HANDLED; | 3809 | return IRQ_HANDLED; |
| 3816 | } | 3810 | } |
| 3817 | 3811 | ||
| 3818 | /*--------------------------------------------------------------------------- | ||
| 3819 | snd_trident_attach_synthesizer | ||
| 3820 | |||
| 3821 | Description: Attach synthesizer hooks | ||
| 3822 | |||
| 3823 | Paramters: trident - device specific private data for 4DWave card | ||
| 3824 | |||
| 3825 | Returns: None. | ||
| 3826 | |||
| 3827 | ---------------------------------------------------------------------------*/ | ||
| 3828 | int snd_trident_attach_synthesizer(struct snd_trident *trident) | ||
| 3829 | { | ||
| 3830 | #if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE)) | ||
| 3831 | if (snd_seq_device_new(trident->card, 1, SNDRV_SEQ_DEV_ID_TRIDENT, | ||
| 3832 | sizeof(struct snd_trident *), &trident->seq_dev) >= 0) { | ||
| 3833 | strcpy(trident->seq_dev->name, "4DWave"); | ||
| 3834 | *(struct snd_trident **)SNDRV_SEQ_DEVICE_ARGPTR(trident->seq_dev) = trident; | ||
| 3835 | } | ||
| 3836 | #endif | ||
| 3837 | return 0; | ||
| 3838 | } | ||
| 3839 | |||
| 3840 | struct snd_trident_voice *snd_trident_alloc_voice(struct snd_trident * trident, int type, int client, int port) | 3812 | struct snd_trident_voice *snd_trident_alloc_voice(struct snd_trident * trident, int type, int client, int port) |
| 3841 | { | 3813 | { |
| 3842 | struct snd_trident_voice *pvoice; | 3814 | struct snd_trident_voice *pvoice; |
diff --git a/sound/pci/trident/trident_synth.c b/sound/pci/trident/trident_synth.c deleted file mode 100644 index 9b7dee84743b..000000000000 --- a/sound/pci/trident/trident_synth.c +++ /dev/null | |||
| @@ -1,1024 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Routines for Trident 4DWave NX/DX soundcards - Synthesizer | ||
| 3 | * Copyright (c) by Scott McNab <jedi@tartarus.uwa.edu.au> | ||
| 4 | * | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify | ||
| 7 | * it under the terms of the GNU General Public License as published by | ||
| 8 | * the Free Software Foundation; either version 2 of the License, or | ||
| 9 | * (at your option) any later version. | ||
| 10 | * | ||
| 11 | * This program is distributed in the hope that it will be useful, | ||
| 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 14 | * GNU General Public License for more details. | ||
| 15 | * | ||
| 16 | * You should have received a copy of the GNU General Public License | ||
| 17 | * along with this program; if not, write to the Free Software | ||
| 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 19 | * | ||
| 20 | */ | ||
| 21 | |||
| 22 | #include <sound/driver.h> | ||
| 23 | #include <asm/io.h> | ||
| 24 | #include <linux/init.h> | ||
| 25 | #include <linux/slab.h> | ||
| 26 | #include <linux/pci.h> | ||
| 27 | #include <sound/core.h> | ||
| 28 | #include <sound/trident.h> | ||
| 29 | #include <sound/seq_device.h> | ||
| 30 | |||
| 31 | MODULE_AUTHOR("Scott McNab <jedi@tartarus.uwa.edu.au>"); | ||
| 32 | MODULE_DESCRIPTION("Routines for Trident 4DWave NX/DX soundcards - Synthesizer"); | ||
| 33 | MODULE_LICENSE("GPL"); | ||
| 34 | |||
| 35 | /* linear to log pan conversion table (4.2 channel attenuation format) */ | ||
| 36 | static unsigned int pan_table[63] = { | ||
| 37 | 7959, 7733, 7514, 7301, 7093, 6892, 6697, 6507, | ||
| 38 | 6322, 6143, 5968, 5799, 5634, 5475, 5319, 5168, | ||
| 39 | 5022, 4879, 4741, 4606, 4475, 4349, 4225, 4105, | ||
| 40 | 3989, 3876, 3766, 3659, 3555, 3454, 3356, 3261, | ||
| 41 | 3168, 3078, 2991, 2906, 2824, 2744, 2666, 2590, | ||
| 42 | 2517, 2445, 2376, 2308, 2243, 2179, 2117, 2057, | ||
| 43 | 1999, 1942, 1887, 1833, 1781, 1731, 1682, 1634, | ||
| 44 | 1588, 1543, 1499, 1456, 1415, 1375, 1336 | ||
| 45 | }; | ||
| 46 | |||
| 47 | #define LOG_TABLE_SIZE 386 | ||
| 48 | |||
| 49 | /* Linear half-attenuation to log conversion table in the format: | ||
| 50 | * {linear volume, logarithmic attenuation equivalent}, ... | ||
| 51 | * | ||
| 52 | * Provides conversion from a linear half-volume value in the range | ||
| 53 | * [0,8192] to a logarithmic attenuation value in the range 0 to 6.02dB. | ||
| 54 | * Halving the linear volume is equivalent to an additional 6dB of | ||
| 55 | * logarithmic attenuation. The algorithm used in log_from_linear() | ||
| 56 | * therefore uses this table as follows: | ||
| 57 | * | ||
| 58 | * - loop and for every time the volume is less than half the maximum | ||
| 59 | * volume (16384), add another 6dB and halve the maximum value used | ||
| 60 | * for this comparison. | ||
| 61 | * - when the volume is greater than half the maximum volume, take | ||
| 62 | * the difference of the volume to half volume (in the range [0,8192]) | ||
| 63 | * and look up the log_table[] to find the nearest entry. | ||
| 64 | * - take the logarithic component of this entry and add it to the | ||
| 65 | * resulting attenuation. | ||
| 66 | * | ||
| 67 | * Thus this routine provides a linear->log conversion for a range of | ||
| 68 | * [0,16384] using only 386 table entries | ||
| 69 | * | ||
| 70 | * Note: although this table stores log attenuation in 8.8 format, values | ||
| 71 | * were only calculated for 6 bits fractional precision, since that is | ||
| 72 | * the most precision offered by the trident hardware. | ||
| 73 | */ | ||
| 74 | |||
| 75 | static unsigned short log_table[LOG_TABLE_SIZE*2] = | ||
| 76 | { | ||
| 77 | 4, 0x0604, 19, 0x0600, 34, 0x05fc, | ||
| 78 | 49, 0x05f8, 63, 0x05f4, 78, 0x05f0, 93, 0x05ec, 108, 0x05e8, | ||
| 79 | 123, 0x05e4, 138, 0x05e0, 153, 0x05dc, 168, 0x05d8, 183, 0x05d4, | ||
| 80 | 198, 0x05d0, 213, 0x05cc, 228, 0x05c8, 244, 0x05c4, 259, 0x05c0, | ||
| 81 | 274, 0x05bc, 289, 0x05b8, 304, 0x05b4, 320, 0x05b0, 335, 0x05ac, | ||
| 82 | 350, 0x05a8, 366, 0x05a4, 381, 0x05a0, 397, 0x059c, 412, 0x0598, | ||
| 83 | 428, 0x0594, 443, 0x0590, 459, 0x058c, 474, 0x0588, 490, 0x0584, | ||
| 84 | 506, 0x0580, 521, 0x057c, 537, 0x0578, 553, 0x0574, 568, 0x0570, | ||
| 85 | 584, 0x056c, 600, 0x0568, 616, 0x0564, 632, 0x0560, 647, 0x055c, | ||
| 86 | 663, 0x0558, 679, 0x0554, 695, 0x0550, 711, 0x054c, 727, 0x0548, | ||
| 87 | 743, 0x0544, 759, 0x0540, 776, 0x053c, 792, 0x0538, 808, 0x0534, | ||
| 88 | 824, 0x0530, 840, 0x052c, 857, 0x0528, 873, 0x0524, 889, 0x0520, | ||
| 89 | 906, 0x051c, 922, 0x0518, 938, 0x0514, 955, 0x0510, 971, 0x050c, | ||
| 90 | 988, 0x0508, 1004, 0x0504, 1021, 0x0500, 1037, 0x04fc, 1054, 0x04f8, | ||
| 91 | 1071, 0x04f4, 1087, 0x04f0, 1104, 0x04ec, 1121, 0x04e8, 1138, 0x04e4, | ||
| 92 | 1154, 0x04e0, 1171, 0x04dc, 1188, 0x04d8, 1205, 0x04d4, 1222, 0x04d0, | ||
| 93 | 1239, 0x04cc, 1256, 0x04c8, 1273, 0x04c4, 1290, 0x04c0, 1307, 0x04bc, | ||
| 94 | 1324, 0x04b8, 1341, 0x04b4, 1358, 0x04b0, 1376, 0x04ac, 1393, 0x04a8, | ||
| 95 | 1410, 0x04a4, 1427, 0x04a0, 1445, 0x049c, 1462, 0x0498, 1479, 0x0494, | ||
| 96 | 1497, 0x0490, 1514, 0x048c, 1532, 0x0488, 1549, 0x0484, 1567, 0x0480, | ||
| 97 | 1584, 0x047c, 1602, 0x0478, 1620, 0x0474, 1637, 0x0470, 1655, 0x046c, | ||
| 98 | 1673, 0x0468, 1690, 0x0464, 1708, 0x0460, 1726, 0x045c, 1744, 0x0458, | ||
| 99 | 1762, 0x0454, 1780, 0x0450, 1798, 0x044c, 1816, 0x0448, 1834, 0x0444, | ||
| 100 | 1852, 0x0440, 1870, 0x043c, 1888, 0x0438, 1906, 0x0434, 1924, 0x0430, | ||
| 101 | 1943, 0x042c, 1961, 0x0428, 1979, 0x0424, 1997, 0x0420, 2016, 0x041c, | ||
| 102 | 2034, 0x0418, 2053, 0x0414, 2071, 0x0410, 2089, 0x040c, 2108, 0x0408, | ||
| 103 | 2127, 0x0404, 2145, 0x0400, 2164, 0x03fc, 2182, 0x03f8, 2201, 0x03f4, | ||
| 104 | 2220, 0x03f0, 2239, 0x03ec, 2257, 0x03e8, 2276, 0x03e4, 2295, 0x03e0, | ||
| 105 | 2314, 0x03dc, 2333, 0x03d8, 2352, 0x03d4, 2371, 0x03d0, 2390, 0x03cc, | ||
| 106 | 2409, 0x03c8, 2428, 0x03c4, 2447, 0x03c0, 2466, 0x03bc, 2485, 0x03b8, | ||
| 107 | 2505, 0x03b4, 2524, 0x03b0, 2543, 0x03ac, 2562, 0x03a8, 2582, 0x03a4, | ||
| 108 | 2601, 0x03a0, 2621, 0x039c, 2640, 0x0398, 2660, 0x0394, 2679, 0x0390, | ||
| 109 | 2699, 0x038c, 2718, 0x0388, 2738, 0x0384, 2758, 0x0380, 2777, 0x037c, | ||
| 110 | 2797, 0x0378, 2817, 0x0374, 2837, 0x0370, 2857, 0x036c, 2876, 0x0368, | ||
| 111 | 2896, 0x0364, 2916, 0x0360, 2936, 0x035c, 2956, 0x0358, 2976, 0x0354, | ||
| 112 | 2997, 0x0350, 3017, 0x034c, 3037, 0x0348, 3057, 0x0344, 3077, 0x0340, | ||
| 113 | 3098, 0x033c, 3118, 0x0338, 3138, 0x0334, 3159, 0x0330, 3179, 0x032c, | ||
| 114 | 3200, 0x0328, 3220, 0x0324, 3241, 0x0320, 3261, 0x031c, 3282, 0x0318, | ||
| 115 | 3303, 0x0314, 3323, 0x0310, 3344, 0x030c, 3365, 0x0308, 3386, 0x0304, | ||
| 116 | 3406, 0x0300, 3427, 0x02fc, 3448, 0x02f8, 3469, 0x02f4, 3490, 0x02f0, | ||
| 117 | 3511, 0x02ec, 3532, 0x02e8, 3553, 0x02e4, 3575, 0x02e0, 3596, 0x02dc, | ||
| 118 | 3617, 0x02d8, 3638, 0x02d4, 3660, 0x02d0, 3681, 0x02cc, 3702, 0x02c8, | ||
| 119 | 3724, 0x02c4, 3745, 0x02c0, 3767, 0x02bc, 3788, 0x02b8, 3810, 0x02b4, | ||
| 120 | 3831, 0x02b0, 3853, 0x02ac, 3875, 0x02a8, 3896, 0x02a4, 3918, 0x02a0, | ||
| 121 | 3940, 0x029c, 3962, 0x0298, 3984, 0x0294, 4006, 0x0290, 4028, 0x028c, | ||
| 122 | 4050, 0x0288, 4072, 0x0284, 4094, 0x0280, 4116, 0x027c, 4138, 0x0278, | ||
| 123 | 4160, 0x0274, 4182, 0x0270, 4205, 0x026c, 4227, 0x0268, 4249, 0x0264, | ||
| 124 | 4272, 0x0260, 4294, 0x025c, 4317, 0x0258, 4339, 0x0254, 4362, 0x0250, | ||
| 125 | 4384, 0x024c, 4407, 0x0248, 4430, 0x0244, 4453, 0x0240, 4475, 0x023c, | ||
| 126 | 4498, 0x0238, 4521, 0x0234, 4544, 0x0230, 4567, 0x022c, 4590, 0x0228, | ||
| 127 | 4613, 0x0224, 4636, 0x0220, 4659, 0x021c, 4682, 0x0218, 4705, 0x0214, | ||
| 128 | 4728, 0x0210, 4752, 0x020c, 4775, 0x0208, 4798, 0x0204, 4822, 0x0200, | ||
| 129 | 4845, 0x01fc, 4869, 0x01f8, 4892, 0x01f4, 4916, 0x01f0, 4939, 0x01ec, | ||
| 130 | 4963, 0x01e8, 4987, 0x01e4, 5010, 0x01e0, 5034, 0x01dc, 5058, 0x01d8, | ||
| 131 | 5082, 0x01d4, 5106, 0x01d0, 5130, 0x01cc, 5154, 0x01c8, 5178, 0x01c4, | ||
| 132 | 5202, 0x01c0, 5226, 0x01bc, 5250, 0x01b8, 5274, 0x01b4, 5299, 0x01b0, | ||
| 133 | 5323, 0x01ac, 5347, 0x01a8, 5372, 0x01a4, 5396, 0x01a0, 5420, 0x019c, | ||
| 134 | 5445, 0x0198, 5469, 0x0194, 5494, 0x0190, 5519, 0x018c, 5543, 0x0188, | ||
| 135 | 5568, 0x0184, 5593, 0x0180, 5618, 0x017c, 5643, 0x0178, 5668, 0x0174, | ||
| 136 | 5692, 0x0170, 5717, 0x016c, 5743, 0x0168, 5768, 0x0164, 5793, 0x0160, | ||
| 137 | 5818, 0x015c, 5843, 0x0158, 5868, 0x0154, 5894, 0x0150, 5919, 0x014c, | ||
| 138 | 5945, 0x0148, 5970, 0x0144, 5995, 0x0140, 6021, 0x013c, 6047, 0x0138, | ||
| 139 | 6072, 0x0134, 6098, 0x0130, 6124, 0x012c, 6149, 0x0128, 6175, 0x0124, | ||
| 140 | 6201, 0x0120, 6227, 0x011c, 6253, 0x0118, 6279, 0x0114, 6305, 0x0110, | ||
| 141 | 6331, 0x010c, 6357, 0x0108, 6384, 0x0104, 6410, 0x0100, 6436, 0x00fc, | ||
| 142 | 6462, 0x00f8, 6489, 0x00f4, 6515, 0x00f0, 6542, 0x00ec, 6568, 0x00e8, | ||
| 143 | 6595, 0x00e4, 6621, 0x00e0, 6648, 0x00dc, 6675, 0x00d8, 6702, 0x00d4, | ||
| 144 | 6728, 0x00d0, 6755, 0x00cc, 6782, 0x00c8, 6809, 0x00c4, 6836, 0x00c0, | ||
| 145 | 6863, 0x00bc, 6890, 0x00b8, 6917, 0x00b4, 6945, 0x00b0, 6972, 0x00ac, | ||
| 146 | 6999, 0x00a8, 7027, 0x00a4, 7054, 0x00a0, 7081, 0x009c, 7109, 0x0098, | ||
| 147 | 7136, 0x0094, 7164, 0x0090, 7192, 0x008c, 7219, 0x0088, 7247, 0x0084, | ||
| 148 | 7275, 0x0080, 7303, 0x007c, 7331, 0x0078, 7359, 0x0074, 7387, 0x0070, | ||
| 149 | 7415, 0x006c, 7443, 0x0068, 7471, 0x0064, 7499, 0x0060, 7527, 0x005c, | ||
| 150 | 7556, 0x0058, 7584, 0x0054, 7613, 0x0050, 7641, 0x004c, 7669, 0x0048, | ||
| 151 | 7698, 0x0044, 7727, 0x0040, 7755, 0x003c, 7784, 0x0038, 7813, 0x0034, | ||
| 152 | 7842, 0x0030, 7870, 0x002c, 7899, 0x0028, 7928, 0x0024, 7957, 0x0020, | ||
| 153 | 7986, 0x001c, 8016, 0x0018, 8045, 0x0014, 8074, 0x0010, 8103, 0x000c, | ||
| 154 | 8133, 0x0008, 8162, 0x0004, 8192, 0x0000 | ||
| 155 | }; | ||
| 156 | |||
| 157 | static unsigned short lookup_volume_table( unsigned short value ) | ||
| 158 | { | ||
| 159 | /* This code is an optimised version of: | ||
| 160 | * int i = 0; | ||
| 161 | * while( volume_table[i*2] < value ) | ||
| 162 | * i++; | ||
| 163 | * return volume_table[i*2+1]; | ||
| 164 | */ | ||
| 165 | unsigned short *ptr = log_table; | ||
| 166 | while( *ptr < value ) | ||
| 167 | ptr += 2; | ||
| 168 | return *(ptr+1); | ||
| 169 | } | ||
| 170 | |||
| 171 | /* this function calculates a 8.8 fixed point logarithmic attenuation | ||
| 172 | * value from a linear volume value in the range 0 to 16384 */ | ||
| 173 | static unsigned short log_from_linear( unsigned short value ) | ||
| 174 | { | ||
| 175 | if (value >= 16384) | ||
| 176 | return 0x0000; | ||
| 177 | if (value) { | ||
| 178 | unsigned short result = 0; | ||
| 179 | int v, c; | ||
| 180 | for( c = 0, v = 8192; c < 14; c++, v >>= 1 ) { | ||
| 181 | if( value >= v ) { | ||
| 182 | result += lookup_volume_table( (value - v) << c ); | ||
| 183 | return result; | ||
| 184 | } | ||
| 185 | result += 0x0605; /* 6.0205 (result of -20*log10(0.5)) */ | ||
| 186 | } | ||
| 187 | } | ||
| 188 | return 0xffff; | ||
| 189 | } | ||
| 190 | |||
| 191 | /* | ||
| 192 | * Sample handling operations | ||
| 193 | */ | ||
| 194 | |||
| 195 | static void sample_start(struct snd_trident * trident, struct snd_trident_voice * voice, snd_seq_position_t position); | ||
| 196 | static void sample_stop(struct snd_trident * trident, struct snd_trident_voice * voice, int mode); | ||
| 197 | static void sample_freq(struct snd_trident * trident, struct snd_trident_voice * voice, snd_seq_frequency_t freq); | ||
| 198 | static void sample_volume(struct snd_trident * trident, struct snd_trident_voice * voice, struct snd_seq_ev_volume * volume); | ||
| 199 | static void sample_loop(struct snd_trident * trident, struct snd_trident_voice * voice, struct snd_seq_ev_loop * loop); | ||
| 200 | static void sample_pos(struct snd_trident * trident, struct snd_trident_voice * voice, snd_seq_position_t position); | ||
| 201 | static void sample_private1(struct snd_trident * trident, struct snd_trident_voice * voice, unsigned char *data); | ||
| 202 | |||
| 203 | static struct snd_trident_sample_ops sample_ops = | ||
| 204 | { | ||
| 205 | sample_start, | ||
| 206 | sample_stop, | ||
| 207 | sample_freq, | ||
| 208 | sample_volume, | ||
| 209 | sample_loop, | ||
| 210 | sample_pos, | ||
| 211 | sample_private1 | ||
| 212 | }; | ||
| 213 | |||
| 214 | static void snd_trident_simple_init(struct snd_trident_voice * voice) | ||
| 215 | { | ||
| 216 | //voice->handler_wave = interrupt_wave; | ||
| 217 | //voice->handler_volume = interrupt_volume; | ||
| 218 | //voice->handler_effect = interrupt_effect; | ||
| 219 | //voice->volume_change = NULL; | ||
| 220 | voice->sample_ops = &sample_ops; | ||
| 221 | } | ||
| 222 | |||
| 223 | static void sample_start(struct snd_trident * trident, struct snd_trident_voice * voice, snd_seq_position_t position) | ||
| 224 | { | ||
| 225 | struct simple_instrument *simple; | ||
| 226 | struct snd_seq_kinstr *instr; | ||
| 227 | unsigned long flags; | ||
| 228 | unsigned int loop_start, loop_end, sample_start, sample_end, start_offset; | ||
| 229 | unsigned int value; | ||
| 230 | unsigned int shift = 0; | ||
| 231 | |||
| 232 | instr = snd_seq_instr_find(trident->synth.ilist, &voice->instr, 0, 1); | ||
| 233 | if (instr == NULL) | ||
| 234 | return; | ||
| 235 | voice->instr = instr->instr; /* copy ID to speedup aliases */ | ||
| 236 | simple = KINSTR_DATA(instr); | ||
| 237 | |||
| 238 | spin_lock_irqsave(&trident->reg_lock, flags); | ||
| 239 | |||
| 240 | if (trident->device == TRIDENT_DEVICE_ID_SI7018) | ||
| 241 | voice->GVSel = 1; /* route to Wave volume */ | ||
| 242 | |||
| 243 | voice->CTRL = 0; | ||
| 244 | voice->Alpha = 0; | ||
| 245 | voice->FMS = 0; | ||
| 246 | |||
| 247 | loop_start = simple->loop_start >> 4; | ||
| 248 | loop_end = simple->loop_end >> 4; | ||
| 249 | sample_start = (simple->start + position) >> 4; | ||
| 250 | if( sample_start >= simple->size ) | ||
| 251 | sample_start = simple->start >> 4; | ||
| 252 | sample_end = simple->size; | ||
| 253 | start_offset = position >> 4; | ||
| 254 | |||
| 255 | if (simple->format & SIMPLE_WAVE_16BIT) { | ||
| 256 | voice->CTRL |= 8; | ||
| 257 | shift++; | ||
| 258 | } | ||
| 259 | if (simple->format & SIMPLE_WAVE_STEREO) { | ||
| 260 | voice->CTRL |= 4; | ||
| 261 | shift++; | ||
| 262 | } | ||
| 263 | if (!(simple->format & SIMPLE_WAVE_UNSIGNED)) | ||
| 264 | voice->CTRL |= 2; | ||
| 265 | |||
| 266 | voice->LBA = simple->address.memory; | ||
| 267 | |||
| 268 | if (simple->format & SIMPLE_WAVE_LOOP) { | ||
| 269 | voice->CTRL |= 1; | ||
| 270 | voice->LBA += loop_start << shift; | ||
| 271 | if( start_offset >= loop_start ) { | ||
| 272 | voice->CSO = start_offset - loop_start; | ||
| 273 | voice->negCSO = 0; | ||
| 274 | } else { | ||
| 275 | voice->CSO = loop_start - start_offset; | ||
| 276 | voice->negCSO = 1; | ||
| 277 | } | ||
| 278 | voice->ESO = loop_end - loop_start - 1; | ||
| 279 | } else { | ||
| 280 | voice->LBA += start_offset << shift; | ||
| 281 | voice->CSO = sample_start; | ||
| 282 | voice->ESO = sample_end - 1; | ||
| 283 | voice->negCSO = 0; | ||
| 284 | } | ||
| 285 | |||
| 286 | if (voice->flags & SNDRV_TRIDENT_VFLG_RUNNING) { | ||
| 287 | snd_trident_stop_voice(trident, voice->number); | ||
| 288 | voice->flags &= ~SNDRV_TRIDENT_VFLG_RUNNING; | ||
| 289 | } | ||
| 290 | |||
| 291 | /* set CSO sign */ | ||
| 292 | value = inl(TRID_REG(trident, T4D_SIGN_CSO_A)); | ||
| 293 | if( voice->negCSO ) { | ||
| 294 | value |= 1 << (voice->number&31); | ||
| 295 | } else { | ||
| 296 | value &= ~(1 << (voice->number&31)); | ||
| 297 | } | ||
| 298 | outl(value,TRID_REG(trident, T4D_SIGN_CSO_A)); | ||
| 299 | |||
| 300 | voice->Attribute = 0; | ||
| 301 | snd_trident_write_voice_regs(trident, voice); | ||
| 302 | snd_trident_start_voice(trident, voice->number); | ||
| 303 | voice->flags |= SNDRV_TRIDENT_VFLG_RUNNING; | ||
| 304 | spin_unlock_irqrestore(&trident->reg_lock, flags); | ||
| 305 | snd_seq_instr_free_use(trident->synth.ilist, instr); | ||
| 306 | } | ||
| 307 | |||
| 308 | static void sample_stop(struct snd_trident * trident, struct snd_trident_voice * voice, int mode) | ||
| 309 | { | ||
| 310 | unsigned long flags; | ||
| 311 | |||
| 312 | if (!(voice->flags & SNDRV_TRIDENT_VFLG_RUNNING)) | ||
| 313 | return; | ||
| 314 | |||
| 315 | switch (mode) { | ||
| 316 | default: | ||
| 317 | spin_lock_irqsave(&trident->reg_lock, flags); | ||
| 318 | snd_trident_stop_voice(trident, voice->number); | ||
| 319 | voice->flags &= ~SNDRV_TRIDENT_VFLG_RUNNING; | ||
| 320 | spin_unlock_irqrestore(&trident->reg_lock, flags); | ||
| 321 | break; | ||
| 322 | case SAMPLE_STOP_LOOP: /* disable loop only */ | ||
| 323 | voice->CTRL &= ~1; | ||
| 324 | spin_lock_irqsave(&trident->reg_lock, flags); | ||
| 325 | outb((unsigned char) voice->number, TRID_REG(trident, T4D_LFO_GC_CIR)); | ||
| 326 | outw((((voice->CTRL << 12) | (voice->EC & 0x0fff)) & 0xffff), CH_GVSEL_PAN_VOL_CTRL_EC); | ||
| 327 | spin_unlock_irqrestore(&trident->reg_lock, flags); | ||
| 328 | break; | ||
| 329 | } | ||
| 330 | } | ||
| 331 | |||
| 332 | static void sample_freq(struct snd_trident * trident, struct snd_trident_voice * voice, snd_seq_frequency_t freq) | ||
| 333 | { | ||
| 334 | unsigned long flags; | ||
| 335 | freq >>= 4; | ||
| 336 | |||
| 337 | spin_lock_irqsave(&trident->reg_lock, flags); | ||
| 338 | if (freq == 44100) | ||
| 339 | voice->Delta = 0xeb3; | ||
| 340 | else if (freq == 8000) | ||
| 341 | voice->Delta = 0x2ab; | ||
| 342 | else if (freq == 48000) | ||
| 343 | voice->Delta = 0x1000; | ||
| 344 | else | ||
| 345 | voice->Delta = (((freq << 12) + freq) / 48000) & 0x0000ffff; | ||
| 346 | |||
| 347 | outb((unsigned char) voice->number, TRID_REG(trident, T4D_LFO_GC_CIR)); | ||
| 348 | if (trident->device == TRIDENT_DEVICE_ID_NX) { | ||
| 349 | outb((unsigned char) voice->Delta, TRID_REG(trident, CH_NX_DELTA_CSO + 3)); | ||
| 350 | outb((unsigned char) (voice->Delta >> 8), TRID_REG(trident, CH_NX_DELTA_ESO + 3)); | ||
| 351 | } else { | ||
| 352 | outw((unsigned short) voice->Delta, TRID_REG(trident, CH_DX_ESO_DELTA)); | ||
| 353 | } | ||
| 354 | |||
| 355 | spin_unlock_irqrestore(&trident->reg_lock, flags); | ||
| 356 | } | ||
| 357 | |||
| 358 | static void sample_volume(struct snd_trident * trident, struct snd_trident_voice * voice, struct snd_seq_ev_volume * volume) | ||
| 359 | { | ||
| 360 | unsigned long flags; | ||
| 361 | unsigned short value; | ||
| 362 | |||
| 363 | spin_lock_irqsave(&trident->reg_lock, flags); | ||
| 364 | voice->GVSel = 0; /* use global music volume */ | ||
| 365 | voice->FMC = 0x03; /* fixme: can we do something useful with FMC? */ | ||
| 366 | if (volume->volume >= 0) { | ||
| 367 | volume->volume &= 0x3fff; | ||
| 368 | /* linear volume -> logarithmic attenuation conversion | ||
| 369 | * uses EC register for greater resolution (6.6 bits) than Vol register (5.3 bits) | ||
| 370 | * Vol register used when additional attenuation is required */ | ||
| 371 | voice->RVol = 0; | ||
| 372 | voice->CVol = 0; | ||
| 373 | value = log_from_linear( volume->volume ); | ||
| 374 | voice->Vol = 0; | ||
| 375 | voice->EC = (value & 0x3fff) >> 2; | ||
| 376 | if (value > 0x3fff) { | ||
| 377 | voice->EC |= 0xfc0; | ||
| 378 | if (value < 0x5f00 ) | ||
| 379 | voice->Vol = ((value >> 8) - 0x3f) << 5; | ||
| 380 | else { | ||
| 381 | voice->Vol = 0x3ff; | ||
| 382 | voice->EC = 0xfff; | ||
| 383 | } | ||
| 384 | } | ||
| 385 | } | ||
| 386 | if (volume->lr >= 0) { | ||
| 387 | volume->lr &= 0x3fff; | ||
| 388 | /* approximate linear pan by attenuating channels */ | ||
| 389 | if (volume->lr >= 0x2000) { /* attenuate left (pan right) */ | ||
| 390 | value = 0x3fff - volume->lr; | ||
| 391 | for (voice->Pan = 0; voice->Pan < 63; voice->Pan++ ) | ||
| 392 | if (value >= pan_table[voice->Pan] ) | ||
| 393 | break; | ||
| 394 | } else { /* attenuate right (pan left) */ | ||
| 395 | for (voice->Pan = 0; voice->Pan < 63; voice->Pan++ ) | ||
| 396 | if ((unsigned int)volume->lr >= pan_table[voice->Pan] ) | ||
| 397 | break; | ||
| 398 | voice->Pan |= 0x40; | ||
| 399 | } | ||
| 400 | } | ||
| 401 | outb((unsigned char) voice->number, TRID_REG(trident, T4D_LFO_GC_CIR)); | ||
| 402 | outl((voice->GVSel << 31) | ((voice->Pan & 0x0000007f) << 24) | | ||
| 403 | ((voice->Vol & 0x000000ff) << 16) | ((voice->CTRL & 0x0000000f) << 12) | | ||
| 404 | (voice->EC & 0x00000fff), TRID_REG(trident, CH_GVSEL_PAN_VOL_CTRL_EC)); | ||
| 405 | value = ((voice->FMC & 0x03) << 14) | ((voice->RVol & 0x7f) << 7) | (voice->CVol & 0x7f); | ||
| 406 | outw(value, TRID_REG(trident, CH_DX_FMC_RVOL_CVOL)); | ||
| 407 | spin_unlock_irqrestore(&trident->reg_lock, flags); | ||
| 408 | } | ||
| 409 | |||
| 410 | static void sample_loop(struct snd_trident * trident, struct snd_trident_voice * voice, struct snd_seq_ev_loop * loop) | ||
| 411 | { | ||
| 412 | unsigned long flags; | ||
| 413 | struct simple_instrument *simple; | ||
| 414 | struct snd_seq_kinstr *instr; | ||
| 415 | unsigned int loop_start, loop_end; | ||
| 416 | |||
| 417 | instr = snd_seq_instr_find(trident->synth.ilist, &voice->instr, 0, 1); | ||
| 418 | if (instr == NULL) | ||
| 419 | return; | ||
| 420 | voice->instr = instr->instr; /* copy ID to speedup aliases */ | ||
| 421 | simple = KINSTR_DATA(instr); | ||
| 422 | |||
| 423 | loop_start = loop->start >> 4; | ||
| 424 | loop_end = loop->end >> 4; | ||
| 425 | |||
| 426 | spin_lock_irqsave(&trident->reg_lock, flags); | ||
| 427 | |||
| 428 | voice->LBA = simple->address.memory + loop_start; | ||
| 429 | voice->CSO = 0; | ||
| 430 | voice->ESO = loop_end - loop_start - 1; | ||
| 431 | |||
| 432 | outb((unsigned char) voice->number, TRID_REG(trident, T4D_LFO_GC_CIR)); | ||
| 433 | outb((voice->LBA >> 16), TRID_REG(trident, CH_LBA + 2)); | ||
| 434 | outw((voice->LBA & 0xffff), TRID_REG(trident, CH_LBA)); | ||
| 435 | if (trident->device == TRIDENT_DEVICE_ID_NX) { | ||
| 436 | outb((voice->ESO >> 16), TRID_REG(trident, CH_NX_DELTA_ESO + 2)); | ||
| 437 | outw((voice->ESO & 0xffff), TRID_REG(trident, CH_NX_DELTA_ESO)); | ||
| 438 | outb((voice->CSO >> 16), TRID_REG(trident, CH_NX_DELTA_CSO + 2)); | ||
| 439 | outw((voice->CSO & 0xffff), TRID_REG(trident, CH_NX_DELTA_CSO)); | ||
| 440 | } else { | ||
| 441 | outw((voice->ESO & 0xffff), TRID_REG(trident, CH_DX_ESO_DELTA + 2)); | ||
| 442 | outw((voice->CSO & 0xffff), TRID_REG(trident, CH_DX_CSO_ALPHA_FMS + 2)); | ||
| 443 | } | ||
| 444 | |||
| 445 | spin_unlock_irqrestore(&trident->reg_lock, flags); | ||
| 446 | snd_seq_instr_free_use(trident->synth.ilist, instr); | ||
| 447 | } | ||
| 448 | |||
| 449 | static void sample_pos(struct snd_trident * trident, struct snd_trident_voice * voice, snd_seq_position_t position) | ||
| 450 | { | ||
| 451 | unsigned long flags; | ||
| 452 | struct simple_instrument *simple; | ||
| 453 | struct snd_seq_kinstr *instr; | ||
| 454 | unsigned int value; | ||
| 455 | |||
| 456 | instr = snd_seq_instr_find(trident->synth.ilist, &voice->instr, 0, 1); | ||
| 457 | if (instr == NULL) | ||
| 458 | return; | ||
| 459 | voice->instr = instr->instr; /* copy ID to speedup aliases */ | ||
| 460 | simple = KINSTR_DATA(instr); | ||
| 461 | |||
| 462 | spin_lock_irqsave(&trident->reg_lock, flags); | ||
| 463 | |||
| 464 | if (simple->format & SIMPLE_WAVE_LOOP) { | ||
| 465 | if( position >= simple->loop_start ) { | ||
| 466 | voice->CSO = (position - simple->loop_start) >> 4; | ||
| 467 | voice->negCSO = 0; | ||
| 468 | } else { | ||
| 469 | voice->CSO = (simple->loop_start - position) >> 4; | ||
| 470 | voice->negCSO = 1; | ||
| 471 | } | ||
| 472 | } else { | ||
| 473 | voice->CSO = position >> 4; | ||
| 474 | voice->negCSO = 0; | ||
| 475 | } | ||
| 476 | |||
| 477 | /* set CSO sign */ | ||
| 478 | value = inl(TRID_REG(trident, T4D_SIGN_CSO_A)); | ||
| 479 | if( voice->negCSO ) { | ||
| 480 | value |= 1 << (voice->number&31); | ||
| 481 | } else { | ||
| 482 | value &= ~(1 << (voice->number&31)); | ||
| 483 | } | ||
| 484 | outl(value,TRID_REG(trident, T4D_SIGN_CSO_A)); | ||
| 485 | |||
| 486 | |||
| 487 | outb((unsigned char) voice->number, TRID_REG(trident, T4D_LFO_GC_CIR)); | ||
| 488 | if (trident->device == TRIDENT_DEVICE_ID_NX) { | ||
| 489 | outw((voice->CSO & 0xffff), TRID_REG(trident, CH_NX_DELTA_CSO)); | ||
| 490 | outb((voice->CSO >> 16), TRID_REG(trident, CH_NX_DELTA_CSO + 2)); | ||
| 491 | } else { | ||
| 492 | outw((voice->CSO & 0xffff), TRID_REG(trident, CH_DX_CSO_ALPHA_FMS) + 2); | ||
| 493 | } | ||
| 494 | |||
| 495 | spin_unlock_irqrestore(&trident->reg_lock, flags); | ||
| 496 | snd_seq_instr_free_use(trident->synth.ilist, instr); | ||
| 497 | } | ||
| 498 | |||
| 499 | static void sample_private1(struct snd_trident * trident, struct snd_trident_voice * voice, unsigned char *data) | ||
| 500 | { | ||
| 501 | } | ||
| 502 | |||
| 503 | /* | ||
| 504 | * Memory management / sample loading | ||
| 505 | */ | ||
| 506 | |||
| 507 | static int snd_trident_simple_put_sample(void *private_data, | ||
| 508 | struct simple_instrument * instr, | ||
| 509 | char __user *data, long len, int atomic) | ||
| 510 | { | ||
| 511 | struct snd_trident *trident = private_data; | ||
| 512 | int size = instr->size; | ||
| 513 | int shift = 0; | ||
| 514 | |||
| 515 | if (instr->format & SIMPLE_WAVE_BACKWARD || | ||
| 516 | instr->format & SIMPLE_WAVE_BIDIR || | ||
| 517 | instr->format & SIMPLE_WAVE_ULAW) | ||
| 518 | return -EINVAL; /* not supported */ | ||
| 519 | |||
| 520 | if (instr->format & SIMPLE_WAVE_16BIT) | ||
| 521 | shift++; | ||
| 522 | if (instr->format & SIMPLE_WAVE_STEREO) | ||
| 523 | shift++; | ||
| 524 | size <<= shift; | ||
| 525 | |||
| 526 | if (trident->synth.current_size + size > trident->synth.max_size) | ||
| 527 | return -ENOMEM; | ||
| 528 | |||
| 529 | if (!access_ok(VERIFY_READ, data, size)) | ||
| 530 | return -EFAULT; | ||
| 531 | |||
| 532 | if (trident->tlb.entries) { | ||
| 533 | struct snd_util_memblk *memblk; | ||
| 534 | memblk = snd_trident_synth_alloc(trident, size); | ||
| 535 | if (memblk == NULL) | ||
| 536 | return -ENOMEM; | ||
| 537 | if (snd_trident_synth_copy_from_user(trident, memblk, 0, data, size) ) { | ||
| 538 | snd_trident_synth_free(trident, memblk); | ||
| 539 | return -EFAULT; | ||
| 540 | } | ||
| 541 | instr->address.ptr = (unsigned char*)memblk; | ||
| 542 | instr->address.memory = memblk->offset; | ||
| 543 | } else { | ||
| 544 | struct snd_dma_buffer dmab; | ||
| 545 | if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(trident->pci), | ||
| 546 | size, &dmab) < 0) | ||
| 547 | return -ENOMEM; | ||
| 548 | |||
| 549 | if (copy_from_user(dmab.area, data, size)) { | ||
| 550 | snd_dma_free_pages(&dmab); | ||
| 551 | return -EFAULT; | ||
| 552 | } | ||
| 553 | instr->address.ptr = dmab.area; | ||
| 554 | instr->address.memory = dmab.addr; | ||
| 555 | } | ||
| 556 | |||
| 557 | trident->synth.current_size += size; | ||
| 558 | return 0; | ||
| 559 | } | ||
| 560 | |||
| 561 | static int snd_trident_simple_get_sample(void *private_data, | ||
| 562 | struct simple_instrument * instr, | ||
| 563 | char __user *data, long len, int atomic) | ||
| 564 | { | ||
| 565 | //struct snd_trident *trident = private_data; | ||
| 566 | int size = instr->size; | ||
| 567 | int shift = 0; | ||
| 568 | |||
| 569 | if (instr->format & SIMPLE_WAVE_16BIT) | ||
| 570 | shift++; | ||
| 571 | if (instr->format & SIMPLE_WAVE_STEREO) | ||
| 572 | shift++; | ||
| 573 | size <<= shift; | ||
| 574 | |||
| 575 | if (!access_ok(VERIFY_WRITE, data, size)) | ||
| 576 | return -EFAULT; | ||
| 577 | |||
| 578 | /* FIXME: not implemented yet */ | ||
| 579 | |||
| 580 | return -EBUSY; | ||
| 581 | } | ||
| 582 | |||
| 583 | static int snd_trident_simple_remove_sample(void *private_data, | ||
| 584 | struct simple_instrument * instr, | ||
| 585 | int atomic) | ||
| 586 | { | ||
| 587 | struct snd_trident *trident = private_data; | ||
| 588 | int size = instr->size; | ||
| 589 | |||
| 590 | if (instr->format & SIMPLE_WAVE_16BIT) | ||
| 591 | size <<= 1; | ||
| 592 | if (instr->format & SIMPLE_WAVE_STEREO) | ||
| 593 | size <<= 1; | ||
| 594 | |||
| 595 | if (trident->tlb.entries) { | ||
| 596 | struct snd_util_memblk *memblk = (struct snd_util_memblk *)instr->address.ptr; | ||
| 597 | if (memblk) | ||
| 598 | snd_trident_synth_free(trident, memblk); | ||
| 599 | else | ||
| 600 | return -EFAULT; | ||
| 601 | } else { | ||
| 602 | struct snd_dma_buffer dmab; | ||
| 603 | dmab.dev.type = SNDRV_DMA_TYPE_DEV; | ||
| 604 | dmab.dev.dev = snd_dma_pci_data(trident->pci); | ||
| 605 | dmab.area = instr->address.ptr; | ||
| 606 | dmab.addr = instr->address.memory; | ||
| 607 | dmab.bytes = size; | ||
| 608 | snd_dma_free_pages(&dmab); | ||
| 609 | } | ||
| 610 | |||
| 611 | trident->synth.current_size -= size; | ||
| 612 | if (trident->synth.current_size < 0) /* shouldn't need this check... */ | ||
| 613 | trident->synth.current_size = 0; | ||
| 614 | |||
| 615 | return 0; | ||
| 616 | } | ||
| 617 | |||
| 618 | static void select_instrument(struct snd_trident * trident, struct snd_trident_voice * v) | ||
| 619 | { | ||
| 620 | struct snd_seq_kinstr *instr; | ||
| 621 | instr = snd_seq_instr_find(trident->synth.ilist, &v->instr, 0, 1); | ||
| 622 | if (instr != NULL) { | ||
| 623 | if (instr->ops) { | ||
| 624 | if (!strcmp(instr->ops->instr_type, SNDRV_SEQ_INSTR_ID_SIMPLE)) | ||
| 625 | snd_trident_simple_init(v); | ||
| 626 | } | ||
| 627 | snd_seq_instr_free_use(trident->synth.ilist, instr); | ||
| 628 | } | ||
| 629 | } | ||
| 630 | |||
| 631 | /* | ||
| 632 | |||
| 633 | */ | ||
| 634 | |||
| 635 | static void event_sample(struct snd_seq_event * ev, struct snd_trident_port * p, struct snd_trident_voice * v) | ||
| 636 | { | ||
| 637 | if (v->sample_ops && v->sample_ops->sample_stop) | ||
| 638 | v->sample_ops->sample_stop(p->trident, v, SAMPLE_STOP_IMMEDIATELY); | ||
| 639 | v->instr.std = ev->data.sample.param.sample.std; | ||
| 640 | if (v->instr.std & 0xff000000) { /* private instrument */ | ||
| 641 | v->instr.std &= 0x00ffffff; | ||
| 642 | v->instr.std |= (unsigned int)ev->source.client << 24; | ||
| 643 | } | ||
| 644 | v->instr.bank = ev->data.sample.param.sample.bank; | ||
| 645 | v->instr.prg = ev->data.sample.param.sample.prg; | ||
| 646 | select_instrument(p->trident, v); | ||
| 647 | } | ||
| 648 | |||
| 649 | static void event_cluster(struct snd_seq_event * ev, struct snd_trident_port * p, struct snd_trident_voice * v) | ||
| 650 | { | ||
| 651 | if (v->sample_ops && v->sample_ops->sample_stop) | ||
| 652 | v->sample_ops->sample_stop(p->trident, v, SAMPLE_STOP_IMMEDIATELY); | ||
| 653 | v->instr.cluster = ev->data.sample.param.cluster.cluster; | ||
| 654 | select_instrument(p->trident, v); | ||
| 655 | } | ||
| 656 | |||
| 657 | static void event_start(struct snd_seq_event * ev, struct snd_trident_port * p, struct snd_trident_voice * v) | ||
| 658 | { | ||
| 659 | if (v->sample_ops && v->sample_ops->sample_start) | ||
| 660 | v->sample_ops->sample_start(p->trident, v, ev->data.sample.param.position); | ||
| 661 | } | ||
| 662 | |||
| 663 | static void event_stop(struct snd_seq_event * ev, struct snd_trident_port * p, struct snd_trident_voice * v) | ||
| 664 | { | ||
| 665 | if (v->sample_ops && v->sample_ops->sample_stop) | ||
| 666 | v->sample_ops->sample_stop(p->trident, v, ev->data.sample.param.stop_mode); | ||
| 667 | } | ||
| 668 | |||
| 669 | static void event_freq(struct snd_seq_event * ev, struct snd_trident_port * p, struct snd_trident_voice * v) | ||
| 670 | { | ||
| 671 | if (v->sample_ops && v->sample_ops->sample_freq) | ||
| 672 | v->sample_ops->sample_freq(p->trident, v, ev->data.sample.param.frequency); | ||
| 673 | } | ||
| 674 | |||
| 675 | static void event_volume(struct snd_seq_event * ev, struct snd_trident_port * p, struct snd_trident_voice * v) | ||
| 676 | { | ||
| 677 | if (v->sample_ops && v->sample_ops->sample_volume) | ||
| 678 | v->sample_ops->sample_volume(p->trident, v, &ev->data.sample.param.volume); | ||
| 679 | } | ||
| 680 | |||
| 681 | static void event_loop(struct snd_seq_event * ev, struct snd_trident_port * p, struct snd_trident_voice * v) | ||
| 682 | { | ||
| 683 | if (v->sample_ops && v->sample_ops->sample_loop) | ||
| 684 | v->sample_ops->sample_loop(p->trident, v, &ev->data.sample.param.loop); | ||
| 685 | } | ||
| 686 | |||
| 687 | static void event_position(struct snd_seq_event * ev, struct snd_trident_port * p, struct snd_trident_voice * v) | ||
| 688 | { | ||
| 689 | if (v->sample_ops && v->sample_ops->sample_pos) | ||
| 690 | v->sample_ops->sample_pos(p->trident, v, ev->data.sample.param.position); | ||
| 691 | } | ||
| 692 | |||
| 693 | static void event_private1(struct snd_seq_event * ev, struct snd_trident_port * p, struct snd_trident_voice * v) | ||
| 694 | { | ||
| 695 | if (v->sample_ops && v->sample_ops->sample_private1) | ||
| 696 | v->sample_ops->sample_private1(p->trident, v, (unsigned char *) &ev->data.sample.param.raw8); | ||
| 697 | } | ||
| 698 | |||
| 699 | typedef void (trident_sample_event_handler_t) (struct snd_seq_event * ev, struct snd_trident_port * p, struct snd_trident_voice * v); | ||
| 700 | |||
| 701 | static trident_sample_event_handler_t *trident_sample_event_handlers[9] = | ||
| 702 | { | ||
| 703 | event_sample, | ||
| 704 | event_cluster, | ||
| 705 | event_start, | ||
| 706 | event_stop, | ||
| 707 | event_freq, | ||
| 708 | event_volume, | ||
| 709 | event_loop, | ||
| 710 | event_position, | ||
| 711 | event_private1 | ||
| 712 | }; | ||
| 713 | |||
| 714 | static void snd_trident_sample_event(struct snd_seq_event * ev, struct snd_trident_port * p) | ||
| 715 | { | ||
| 716 | int idx, voice; | ||
| 717 | struct snd_trident *trident = p->trident; | ||
| 718 | struct snd_trident_voice *v; | ||
| 719 | unsigned long flags; | ||
| 720 | |||
| 721 | idx = ev->type - SNDRV_SEQ_EVENT_SAMPLE; | ||
| 722 | if (idx < 0 || idx > 8) | ||
| 723 | return; | ||
| 724 | for (voice = 0; voice < 64; voice++) { | ||
| 725 | v = &trident->synth.voices[voice]; | ||
| 726 | if (v->use && v->client == ev->source.client && | ||
| 727 | v->port == ev->source.port && | ||
| 728 | v->index == ev->data.sample.channel) { | ||
| 729 | spin_lock_irqsave(&trident->event_lock, flags); | ||
| 730 | trident_sample_event_handlers[idx] (ev, p, v); | ||
| 731 | spin_unlock_irqrestore(&trident->event_lock, flags); | ||
| 732 | return; | ||
| 733 | } | ||
| 734 | } | ||
| 735 | } | ||
| 736 | |||
| 737 | /* | ||
| 738 | |||
| 739 | */ | ||
| 740 | |||
| 741 | static void snd_trident_synth_free_voices(struct snd_trident * trident, int client, int port) | ||
| 742 | { | ||
| 743 | int idx; | ||
| 744 | struct snd_trident_voice *voice; | ||
| 745 | |||
| 746 | for (idx = 0; idx < 32; idx++) { | ||
| 747 | voice = &trident->synth.voices[idx]; | ||
| 748 | if (voice->use && voice->client == client && voice->port == port) | ||
| 749 | snd_trident_free_voice(trident, voice); | ||
| 750 | } | ||
| 751 | } | ||
| 752 | |||
| 753 | static int snd_trident_synth_use(void *private_data, struct snd_seq_port_subscribe * info) | ||
| 754 | { | ||
| 755 | struct snd_trident_port *port = private_data; | ||
| 756 | struct snd_trident *trident = port->trident; | ||
| 757 | struct snd_trident_voice *voice; | ||
| 758 | unsigned int idx; | ||
| 759 | unsigned long flags; | ||
| 760 | |||
| 761 | if (info->voices > 32) | ||
| 762 | return -EINVAL; | ||
| 763 | spin_lock_irqsave(&trident->reg_lock, flags); | ||
| 764 | for (idx = 0; idx < info->voices; idx++) { | ||
| 765 | voice = snd_trident_alloc_voice(trident, SNDRV_TRIDENT_VOICE_TYPE_SYNTH, info->sender.client, info->sender.port); | ||
| 766 | if (voice == NULL) { | ||
| 767 | snd_trident_synth_free_voices(trident, info->sender.client, info->sender.port); | ||
| 768 | spin_unlock_irqrestore(&trident->reg_lock, flags); | ||
| 769 | return -EBUSY; | ||
| 770 | } | ||
| 771 | voice->index = idx; | ||
| 772 | voice->Vol = 0x3ff; | ||
| 773 | voice->EC = 0x0fff; | ||
| 774 | } | ||
| 775 | #if 0 | ||
| 776 | for (idx = 0; idx < info->midi_voices; idx++) { | ||
| 777 | port->midi_has_voices = 1; | ||
| 778 | voice = snd_trident_alloc_voice(trident, SNDRV_TRIDENT_VOICE_TYPE_MIDI, info->sender.client, info->sender.port); | ||
| 779 | if (voice == NULL) { | ||
| 780 | snd_trident_synth_free_voices(trident, info->sender.client, info->sender.port); | ||
| 781 | spin_unlock_irqrestore(&trident->reg_lock, flags); | ||
| 782 | return -EBUSY; | ||
| 783 | } | ||
| 784 | voice->Vol = 0x3ff; | ||
| 785 | voice->EC = 0x0fff; | ||
| 786 | } | ||
| 787 | #endif | ||
| 788 | spin_unlock_irqrestore(&trident->reg_lock, flags); | ||
| 789 | return 0; | ||
| 790 | } | ||
| 791 | |||
| 792 | static int snd_trident_synth_unuse(void *private_data, struct snd_seq_port_subscribe * info) | ||
| 793 | { | ||
| 794 | struct snd_trident_port *port = private_data; | ||
| 795 | struct snd_trident *trident = port->trident; | ||
| 796 | unsigned long flags; | ||
| 797 | |||
| 798 | spin_lock_irqsave(&trident->reg_lock, flags); | ||
| 799 | snd_trident_synth_free_voices(trident, info->sender.client, info->sender.port); | ||
| 800 | spin_unlock_irqrestore(&trident->reg_lock, flags); | ||
| 801 | return 0; | ||
| 802 | } | ||
| 803 | |||
| 804 | /* | ||
| 805 | |||
| 806 | */ | ||
| 807 | |||
| 808 | static void snd_trident_synth_free_private_instruments(struct snd_trident_port * p, int client) | ||
| 809 | { | ||
| 810 | struct snd_seq_instr_header ifree; | ||
| 811 | |||
| 812 | memset(&ifree, 0, sizeof(ifree)); | ||
| 813 | ifree.cmd = SNDRV_SEQ_INSTR_FREE_CMD_PRIVATE; | ||
| 814 | snd_seq_instr_list_free_cond(p->trident->synth.ilist, &ifree, client, 0); | ||
| 815 | } | ||
| 816 | |||
| 817 | static int snd_trident_synth_event_input(struct snd_seq_event * ev, int direct, void *private_data, int atomic, int hop) | ||
| 818 | { | ||
| 819 | struct snd_trident_port *p = (struct snd_trident_port *) private_data; | ||
| 820 | |||
| 821 | if (p == NULL) | ||
| 822 | return -EINVAL; | ||
| 823 | if (ev->type >= SNDRV_SEQ_EVENT_SAMPLE && | ||
| 824 | ev->type <= SNDRV_SEQ_EVENT_SAMPLE_PRIVATE1) { | ||
| 825 | snd_trident_sample_event(ev, p); | ||
| 826 | return 0; | ||
| 827 | } | ||
| 828 | if (ev->source.client == SNDRV_SEQ_CLIENT_SYSTEM && | ||
| 829 | ev->source.port == SNDRV_SEQ_PORT_SYSTEM_ANNOUNCE) { | ||
| 830 | if (ev->type == SNDRV_SEQ_EVENT_CLIENT_EXIT) { | ||
| 831 | snd_trident_synth_free_private_instruments(p, ev->data.addr.client); | ||
| 832 | return 0; | ||
| 833 | } | ||
| 834 | } | ||
| 835 | if (direct) { | ||
| 836 | if (ev->type >= SNDRV_SEQ_EVENT_INSTR_BEGIN) { | ||
| 837 | snd_seq_instr_event(&p->trident->synth.simple_ops.kops, | ||
| 838 | p->trident->synth.ilist, ev, | ||
| 839 | p->trident->synth.seq_client, atomic, hop); | ||
| 840 | return 0; | ||
| 841 | } | ||
| 842 | } | ||
| 843 | return 0; | ||
| 844 | } | ||
| 845 | |||
| 846 | static void snd_trident_synth_instr_notify(void *private_data, | ||
| 847 | struct snd_seq_kinstr * instr, | ||
| 848 | int what) | ||
| 849 | { | ||
| 850 | int idx; | ||
| 851 | struct snd_trident *trident = private_data; | ||
| 852 | struct snd_trident_voice *pvoice; | ||
| 853 | unsigned long flags; | ||
| 854 | |||
| 855 | spin_lock_irqsave(&trident->event_lock, flags); | ||
| 856 | for (idx = 0; idx < 64; idx++) { | ||
| 857 | pvoice = &trident->synth.voices[idx]; | ||
| 858 | if (pvoice->use && !memcmp(&pvoice->instr, &instr->instr, sizeof(pvoice->instr))) { | ||
| 859 | if (pvoice->sample_ops && pvoice->sample_ops->sample_stop) { | ||
| 860 | pvoice->sample_ops->sample_stop(trident, pvoice, SAMPLE_STOP_IMMEDIATELY); | ||
| 861 | } else { | ||
| 862 | snd_trident_stop_voice(trident, pvoice->number); | ||
| 863 | pvoice->flags &= ~SNDRV_TRIDENT_VFLG_RUNNING; | ||
| 864 | } | ||
| 865 | } | ||
| 866 | } | ||
| 867 | spin_unlock_irqrestore(&trident->event_lock, flags); | ||
| 868 | } | ||
| 869 | |||
| 870 | /* | ||
| 871 | |||
| 872 | */ | ||
| 873 | |||
| 874 | static void snd_trident_synth_free_port(void *private_data) | ||
| 875 | { | ||
| 876 | struct snd_trident_port *p = (struct snd_trident_port *) private_data; | ||
| 877 | |||
| 878 | if (p) | ||
| 879 | snd_midi_channel_free_set(p->chset); | ||
| 880 | } | ||
| 881 | |||
| 882 | static int snd_trident_synth_create_port(struct snd_trident * trident, int idx) | ||
| 883 | { | ||
| 884 | struct snd_trident_port *p; | ||
| 885 | struct snd_seq_port_callback callbacks; | ||
| 886 | char name[32]; | ||
| 887 | char *str; | ||
| 888 | int result; | ||
| 889 | |||
| 890 | p = &trident->synth.seq_ports[idx]; | ||
| 891 | p->chset = snd_midi_channel_alloc_set(16); | ||
| 892 | if (p->chset == NULL) | ||
| 893 | return -ENOMEM; | ||
| 894 | p->chset->private_data = p; | ||
| 895 | p->trident = trident; | ||
| 896 | p->client = trident->synth.seq_client; | ||
| 897 | |||
| 898 | memset(&callbacks, 0, sizeof(callbacks)); | ||
| 899 | callbacks.owner = THIS_MODULE; | ||
| 900 | callbacks.use = snd_trident_synth_use; | ||
| 901 | callbacks.unuse = snd_trident_synth_unuse; | ||
| 902 | callbacks.event_input = snd_trident_synth_event_input; | ||
| 903 | callbacks.private_free = snd_trident_synth_free_port; | ||
| 904 | callbacks.private_data = p; | ||
| 905 | |||
| 906 | str = "???"; | ||
| 907 | switch (trident->device) { | ||
| 908 | case TRIDENT_DEVICE_ID_DX: str = "Trident 4DWave-DX"; break; | ||
| 909 | case TRIDENT_DEVICE_ID_NX: str = "Trident 4DWave-NX"; break; | ||
| 910 | case TRIDENT_DEVICE_ID_SI7018: str = "SiS 7018"; break; | ||
| 911 | } | ||
| 912 | sprintf(name, "%s port %i", str, idx); | ||
| 913 | p->chset->port = snd_seq_event_port_attach(trident->synth.seq_client, | ||
| 914 | &callbacks, | ||
| 915 | SNDRV_SEQ_PORT_CAP_WRITE | SNDRV_SEQ_PORT_CAP_SUBS_WRITE, | ||
| 916 | SNDRV_SEQ_PORT_TYPE_DIRECT_SAMPLE | | ||
| 917 | SNDRV_SEQ_PORT_TYPE_SYNTH | | ||
| 918 | SNDRV_SEQ_PORT_TYPE_HARDWARE | | ||
| 919 | SNDRV_SEQ_PORT_TYPE_SYNTHESIZER, | ||
| 920 | 16, 0, | ||
| 921 | name); | ||
| 922 | if (p->chset->port < 0) { | ||
| 923 | result = p->chset->port; | ||
| 924 | snd_trident_synth_free_port(p); | ||
| 925 | return result; | ||
| 926 | } | ||
| 927 | p->port = p->chset->port; | ||
| 928 | return 0; | ||
| 929 | } | ||
| 930 | |||
| 931 | /* | ||
| 932 | |||
| 933 | */ | ||
| 934 | |||
| 935 | static int snd_trident_synth_new_device(struct snd_seq_device *dev) | ||
| 936 | { | ||
| 937 | struct snd_trident *trident; | ||
| 938 | int client, i; | ||
| 939 | struct snd_seq_port_subscribe sub; | ||
| 940 | struct snd_simple_ops *simpleops; | ||
| 941 | char *str; | ||
| 942 | |||
| 943 | trident = *(struct snd_trident **)SNDRV_SEQ_DEVICE_ARGPTR(dev); | ||
| 944 | if (trident == NULL) | ||
| 945 | return -EINVAL; | ||
| 946 | |||
| 947 | trident->synth.seq_client = -1; | ||
| 948 | |||
| 949 | /* allocate new client */ | ||
| 950 | str = "???"; | ||
| 951 | switch (trident->device) { | ||
| 952 | case TRIDENT_DEVICE_ID_DX: str = "Trident 4DWave-DX"; break; | ||
| 953 | case TRIDENT_DEVICE_ID_NX: str = "Trident 4DWave-NX"; break; | ||
| 954 | case TRIDENT_DEVICE_ID_SI7018: str = "SiS 7018"; break; | ||
| 955 | } | ||
| 956 | client = trident->synth.seq_client = | ||
| 957 | snd_seq_create_kernel_client(trident->card, 1, str); | ||
| 958 | if (client < 0) | ||
| 959 | return client; | ||
| 960 | |||
| 961 | for (i = 0; i < 4; i++) | ||
| 962 | snd_trident_synth_create_port(trident, i); | ||
| 963 | |||
| 964 | trident->synth.ilist = snd_seq_instr_list_new(); | ||
| 965 | if (trident->synth.ilist == NULL) { | ||
| 966 | snd_seq_delete_kernel_client(client); | ||
| 967 | trident->synth.seq_client = -1; | ||
| 968 | return -ENOMEM; | ||
| 969 | } | ||
| 970 | trident->synth.ilist->flags = SNDRV_SEQ_INSTR_FLG_DIRECT; | ||
| 971 | |||
| 972 | simpleops = &trident->synth.simple_ops; | ||
| 973 | snd_seq_simple_init(simpleops, trident, NULL); | ||
| 974 | simpleops->put_sample = snd_trident_simple_put_sample; | ||
| 975 | simpleops->get_sample = snd_trident_simple_get_sample; | ||
| 976 | simpleops->remove_sample = snd_trident_simple_remove_sample; | ||
| 977 | simpleops->notify = snd_trident_synth_instr_notify; | ||
| 978 | |||
| 979 | memset(&sub, 0, sizeof(sub)); | ||
| 980 | sub.sender.client = SNDRV_SEQ_CLIENT_SYSTEM; | ||
| 981 | sub.sender.port = SNDRV_SEQ_PORT_SYSTEM_ANNOUNCE; | ||
| 982 | sub.dest.client = client; | ||
| 983 | sub.dest.port = 0; | ||
| 984 | snd_seq_kernel_client_ctl(client, SNDRV_SEQ_IOCTL_SUBSCRIBE_PORT, &sub); | ||
| 985 | |||
| 986 | return 0; | ||
| 987 | } | ||
| 988 | |||
| 989 | static int snd_trident_synth_delete_device(struct snd_seq_device *dev) | ||
| 990 | { | ||
| 991 | struct snd_trident *trident; | ||
| 992 | |||
| 993 | trident = *(struct snd_trident **)SNDRV_SEQ_DEVICE_ARGPTR(dev); | ||
| 994 | if (trident == NULL) | ||
| 995 | return -EINVAL; | ||
| 996 | |||
| 997 | if (trident->synth.seq_client >= 0) { | ||
| 998 | snd_seq_delete_kernel_client(trident->synth.seq_client); | ||
| 999 | trident->synth.seq_client = -1; | ||
| 1000 | } | ||
| 1001 | if (trident->synth.ilist) | ||
| 1002 | snd_seq_instr_list_free(&trident->synth.ilist); | ||
| 1003 | return 0; | ||
| 1004 | } | ||
| 1005 | |||
| 1006 | static int __init alsa_trident_synth_init(void) | ||
| 1007 | { | ||
| 1008 | static struct snd_seq_dev_ops ops = | ||
| 1009 | { | ||
| 1010 | snd_trident_synth_new_device, | ||
| 1011 | snd_trident_synth_delete_device | ||
| 1012 | }; | ||
| 1013 | |||
| 1014 | return snd_seq_device_register_driver(SNDRV_SEQ_DEV_ID_TRIDENT, &ops, | ||
| 1015 | sizeof(struct snd_trident *)); | ||
| 1016 | } | ||
| 1017 | |||
| 1018 | static void __exit alsa_trident_synth_exit(void) | ||
| 1019 | { | ||
| 1020 | snd_seq_device_unregister_driver(SNDRV_SEQ_DEV_ID_TRIDENT); | ||
| 1021 | } | ||
| 1022 | |||
| 1023 | module_init(alsa_trident_synth_init) | ||
| 1024 | module_exit(alsa_trident_synth_exit) | ||
