2 * Routines for Trident 4DWave NX/DX soundcards - Synthesizer
3 * Copyright (c) by Scott McNab <jedi@tartarus.uwa.edu.au>
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.
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.
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
22 #include <sound/driver.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>
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");
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
47 #define LOG_TABLE_SIZE 386
49 /* Linear half-attenuation to log conversion table in the format:
50 * {linear volume, logarithmic attenuation equivalent}, ...
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:
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.
67 * Thus this routine provides a linear->log conversion for a range of
68 * [0,16384] using only 386 table entries
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.
75 static unsigned short log_table[LOG_TABLE_SIZE*2] =
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
157 static unsigned short lookup_volume_table( unsigned short value )
159 /* This code is an optimised version of:
161 * while( volume_table[i*2] < value )
163 * return volume_table[i*2+1];
165 unsigned short *ptr = log_table;
166 while( *ptr < value )
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 )
178 unsigned short result = 0;
180 for( c = 0, v = 8192; c < 14; c++, v >>= 1 ) {
182 result += lookup_volume_table( (value - v) << c );
185 result += 0x0605; /* 6.0205 (result of -20*log10(0.5)) */
192 * Sample handling operations
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);
203 static struct snd_trident_sample_ops sample_ops =
214 static void snd_trident_simple_init(struct snd_trident_voice * voice)
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;
223 static void sample_start(struct snd_trident * trident, struct snd_trident_voice * voice, snd_seq_position_t position)
225 struct simple_instrument *simple;
226 struct snd_seq_kinstr *instr;
228 unsigned int loop_start, loop_end, sample_start, sample_end, start_offset;
230 unsigned int shift = 0;
232 instr = snd_seq_instr_find(trident->synth.ilist, &voice->instr, 0, 1);
235 voice->instr = instr->instr; /* copy ID to speedup aliases */
236 simple = KINSTR_DATA(instr);
238 spin_lock_irqsave(&trident->reg_lock, flags);
240 if (trident->device == TRIDENT_DEVICE_ID_SI7018)
241 voice->GVSel = 1; /* route to Wave volume */
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;
255 if (simple->format & SIMPLE_WAVE_16BIT) {
259 if (simple->format & SIMPLE_WAVE_STEREO) {
263 if (!(simple->format & SIMPLE_WAVE_UNSIGNED))
266 voice->LBA = simple->address.memory;
268 if (simple->format & SIMPLE_WAVE_LOOP) {
270 voice->LBA += loop_start << shift;
271 if( start_offset >= loop_start ) {
272 voice->CSO = start_offset - loop_start;
275 voice->CSO = loop_start - start_offset;
278 voice->ESO = loop_end - loop_start - 1;
280 voice->LBA += start_offset << shift;
281 voice->CSO = sample_start;
282 voice->ESO = sample_end - 1;
286 if (voice->flags & SNDRV_TRIDENT_VFLG_RUNNING) {
287 snd_trident_stop_voice(trident, voice->number);
288 voice->flags &= ~SNDRV_TRIDENT_VFLG_RUNNING;
292 value = inl(TRID_REG(trident, T4D_SIGN_CSO_A));
293 if( voice->negCSO ) {
294 value |= 1 << (voice->number&31);
296 value &= ~(1 << (voice->number&31));
298 outl(value,TRID_REG(trident, T4D_SIGN_CSO_A));
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);
308 static void sample_stop(struct snd_trident * trident, struct snd_trident_voice * voice, int mode)
312 if (!(voice->flags & SNDRV_TRIDENT_VFLG_RUNNING))
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);
322 case SAMPLE_STOP_LOOP: /* disable loop only */
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);
332 static void sample_freq(struct snd_trident * trident, struct snd_trident_voice * voice, snd_seq_frequency_t freq)
337 spin_lock_irqsave(&trident->reg_lock, flags);
339 voice->Delta = 0xeb3;
340 else if (freq == 8000)
341 voice->Delta = 0x2ab;
342 else if (freq == 48000)
343 voice->Delta = 0x1000;
345 voice->Delta = (((freq << 12) + freq) / 48000) & 0x0000ffff;
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));
352 outw((unsigned short) voice->Delta, TRID_REG(trident, CH_DX_ESO_DELTA));
355 spin_unlock_irqrestore(&trident->reg_lock, flags);
358 static void sample_volume(struct snd_trident * trident, struct snd_trident_voice * voice, struct snd_seq_ev_volume * volume)
361 unsigned short value;
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 */
373 value = log_from_linear( volume->volume );
375 voice->EC = (value & 0x3fff) >> 2;
376 if (value > 0x3fff) {
379 voice->Vol = ((value >> 8) - 0x3f) << 5;
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] )
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] )
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);
410 static void sample_loop(struct snd_trident * trident, struct snd_trident_voice * voice, struct snd_seq_ev_loop * loop)
413 struct simple_instrument *simple;
414 struct snd_seq_kinstr *instr;
415 unsigned int loop_start, loop_end;
417 instr = snd_seq_instr_find(trident->synth.ilist, &voice->instr, 0, 1);
420 voice->instr = instr->instr; /* copy ID to speedup aliases */
421 simple = KINSTR_DATA(instr);
423 loop_start = loop->start >> 4;
424 loop_end = loop->end >> 4;
426 spin_lock_irqsave(&trident->reg_lock, flags);
428 voice->LBA = simple->address.memory + loop_start;
430 voice->ESO = loop_end - loop_start - 1;
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));
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));
445 spin_unlock_irqrestore(&trident->reg_lock, flags);
446 snd_seq_instr_free_use(trident->synth.ilist, instr);
449 static void sample_pos(struct snd_trident * trident, struct snd_trident_voice * voice, snd_seq_position_t position)
452 struct simple_instrument *simple;
453 struct snd_seq_kinstr *instr;
456 instr = snd_seq_instr_find(trident->synth.ilist, &voice->instr, 0, 1);
459 voice->instr = instr->instr; /* copy ID to speedup aliases */
460 simple = KINSTR_DATA(instr);
462 spin_lock_irqsave(&trident->reg_lock, flags);
464 if (simple->format & SIMPLE_WAVE_LOOP) {
465 if( position >= simple->loop_start ) {
466 voice->CSO = (position - simple->loop_start) >> 4;
469 voice->CSO = (simple->loop_start - position) >> 4;
473 voice->CSO = position >> 4;
478 value = inl(TRID_REG(trident, T4D_SIGN_CSO_A));
479 if( voice->negCSO ) {
480 value |= 1 << (voice->number&31);
482 value &= ~(1 << (voice->number&31));
484 outl(value,TRID_REG(trident, T4D_SIGN_CSO_A));
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));
492 outw((voice->CSO & 0xffff), TRID_REG(trident, CH_DX_CSO_ALPHA_FMS) + 2);
495 spin_unlock_irqrestore(&trident->reg_lock, flags);
496 snd_seq_instr_free_use(trident->synth.ilist, instr);
499 static void sample_private1(struct snd_trident * trident, struct snd_trident_voice * voice, unsigned char *data)
504 * Memory management / sample loading
507 static int snd_trident_simple_put_sample(void *private_data,
508 struct simple_instrument * instr,
509 char __user *data, long len, int atomic)
511 struct snd_trident *trident = private_data;
512 int size = instr->size;
515 if (instr->format & SIMPLE_WAVE_BACKWARD ||
516 instr->format & SIMPLE_WAVE_BIDIR ||
517 instr->format & SIMPLE_WAVE_ULAW)
518 return -EINVAL; /* not supported */
520 if (instr->format & SIMPLE_WAVE_16BIT)
522 if (instr->format & SIMPLE_WAVE_STEREO)
526 if (trident->synth.current_size + size > trident->synth.max_size)
529 if (!access_ok(VERIFY_READ, data, size))
532 if (trident->tlb.entries) {
533 struct snd_util_memblk *memblk;
534 memblk = snd_trident_synth_alloc(trident, size);
537 if (snd_trident_synth_copy_from_user(trident, memblk, 0, data, size) ) {
538 snd_trident_synth_free(trident, memblk);
541 instr->address.ptr = (unsigned char*)memblk;
542 instr->address.memory = memblk->offset;
544 struct snd_dma_buffer dmab;
545 if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(trident->pci),
549 if (copy_from_user(dmab.area, data, size)) {
550 snd_dma_free_pages(&dmab);
553 instr->address.ptr = dmab.area;
554 instr->address.memory = dmab.addr;
557 trident->synth.current_size += size;
561 static int snd_trident_simple_get_sample(void *private_data,
562 struct simple_instrument * instr,
563 char __user *data, long len, int atomic)
565 //struct snd_trident *trident = private_data;
566 int size = instr->size;
569 if (instr->format & SIMPLE_WAVE_16BIT)
571 if (instr->format & SIMPLE_WAVE_STEREO)
575 if (!access_ok(VERIFY_WRITE, data, size))
578 /* FIXME: not implemented yet */
583 static int snd_trident_simple_remove_sample(void *private_data,
584 struct simple_instrument * instr,
587 struct snd_trident *trident = private_data;
588 int size = instr->size;
590 if (instr->format & SIMPLE_WAVE_16BIT)
592 if (instr->format & SIMPLE_WAVE_STEREO)
595 if (trident->tlb.entries) {
596 struct snd_util_memblk *memblk = (struct snd_util_memblk *)instr->address.ptr;
598 snd_trident_synth_free(trident, memblk);
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;
608 snd_dma_free_pages(&dmab);
611 trident->synth.current_size -= size;
612 if (trident->synth.current_size < 0) /* shouldn't need this check... */
613 trident->synth.current_size = 0;
618 static void select_instrument(struct snd_trident * trident, struct snd_trident_voice * v)
620 struct snd_seq_kinstr *instr;
621 instr = snd_seq_instr_find(trident->synth.ilist, &v->instr, 0, 1);
624 if (!strcmp(instr->ops->instr_type, SNDRV_SEQ_INSTR_ID_SIMPLE))
625 snd_trident_simple_init(v);
627 snd_seq_instr_free_use(trident->synth.ilist, instr);
635 static void event_sample(struct snd_seq_event * ev, struct snd_trident_port * p, struct snd_trident_voice * v)
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;
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);
649 static void event_cluster(struct snd_seq_event * ev, struct snd_trident_port * p, struct snd_trident_voice * v)
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);
657 static void event_start(struct snd_seq_event * ev, struct snd_trident_port * p, struct snd_trident_voice * v)
659 if (v->sample_ops && v->sample_ops->sample_start)
660 v->sample_ops->sample_start(p->trident, v, ev->data.sample.param.position);
663 static void event_stop(struct snd_seq_event * ev, struct snd_trident_port * p, struct snd_trident_voice * v)
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);
669 static void event_freq(struct snd_seq_event * ev, struct snd_trident_port * p, struct snd_trident_voice * v)
671 if (v->sample_ops && v->sample_ops->sample_freq)
672 v->sample_ops->sample_freq(p->trident, v, ev->data.sample.param.frequency);
675 static void event_volume(struct snd_seq_event * ev, struct snd_trident_port * p, struct snd_trident_voice * v)
677 if (v->sample_ops && v->sample_ops->sample_volume)
678 v->sample_ops->sample_volume(p->trident, v, &ev->data.sample.param.volume);
681 static void event_loop(struct snd_seq_event * ev, struct snd_trident_port * p, struct snd_trident_voice * v)
683 if (v->sample_ops && v->sample_ops->sample_loop)
684 v->sample_ops->sample_loop(p->trident, v, &ev->data.sample.param.loop);
687 static void event_position(struct snd_seq_event * ev, struct snd_trident_port * p, struct snd_trident_voice * v)
689 if (v->sample_ops && v->sample_ops->sample_pos)
690 v->sample_ops->sample_pos(p->trident, v, ev->data.sample.param.position);
693 static void event_private1(struct snd_seq_event * ev, struct snd_trident_port * p, struct snd_trident_voice * v)
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);
699 typedef void (trident_sample_event_handler_t) (struct snd_seq_event * ev, struct snd_trident_port * p, struct snd_trident_voice * v);
701 static trident_sample_event_handler_t *trident_sample_event_handlers[9] =
714 static void snd_trident_sample_event(struct snd_seq_event * ev, struct snd_trident_port * p)
717 struct snd_trident *trident = p->trident;
718 struct snd_trident_voice *v;
721 idx = ev->type - SNDRV_SEQ_EVENT_SAMPLE;
722 if (idx < 0 || idx > 8)
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);
741 static void snd_trident_synth_free_voices(struct snd_trident * trident, int client, int port)
744 struct snd_trident_voice *voice;
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);
753 static int snd_trident_synth_use(void *private_data, struct snd_seq_port_subscribe * info)
755 struct snd_trident_port *port = private_data;
756 struct snd_trident *trident = port->trident;
757 struct snd_trident_voice *voice;
761 if (info->voices > 32)
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);
767 snd_trident_synth_free_voices(trident, info->sender.client, info->sender.port);
768 spin_unlock_irqrestore(&trident->reg_lock, flags);
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);
780 snd_trident_synth_free_voices(trident, info->sender.client, info->sender.port);
781 spin_unlock_irqrestore(&trident->reg_lock, flags);
788 spin_unlock_irqrestore(&trident->reg_lock, flags);
792 static int snd_trident_synth_unuse(void *private_data, struct snd_seq_port_subscribe * info)
794 struct snd_trident_port *port = private_data;
795 struct snd_trident *trident = port->trident;
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);
808 static void snd_trident_synth_free_private_instruments(struct snd_trident_port * p, int client)
810 struct snd_seq_instr_header ifree;
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);
817 static int snd_trident_synth_event_input(struct snd_seq_event * ev, int direct, void *private_data, int atomic, int hop)
819 struct snd_trident_port *p = (struct snd_trident_port *) private_data;
823 if (ev->type >= SNDRV_SEQ_EVENT_SAMPLE &&
824 ev->type <= SNDRV_SEQ_EVENT_SAMPLE_PRIVATE1) {
825 snd_trident_sample_event(ev, p);
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);
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);
846 static void snd_trident_synth_instr_notify(void *private_data,
847 struct snd_seq_kinstr * instr,
851 struct snd_trident *trident = private_data;
852 struct snd_trident_voice *pvoice;
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);
862 snd_trident_stop_voice(trident, pvoice->number);
863 pvoice->flags &= ~SNDRV_TRIDENT_VFLG_RUNNING;
867 spin_unlock_irqrestore(&trident->event_lock, flags);
874 static void snd_trident_synth_free_port(void *private_data)
876 struct snd_trident_port *p = (struct snd_trident_port *) private_data;
879 snd_midi_channel_free_set(p->chset);
882 static int snd_trident_synth_create_port(struct snd_trident * trident, int idx)
884 struct snd_trident_port *p;
885 struct snd_seq_port_callback callbacks;
890 p = &trident->synth.seq_ports[idx];
891 p->chset = snd_midi_channel_alloc_set(16);
892 if (p->chset == NULL)
894 p->chset->private_data = p;
895 p->trident = trident;
896 p->client = trident->synth.seq_client;
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;
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;
912 sprintf(name, "%s port %i", str, idx);
913 p->chset->port = snd_seq_event_port_attach(trident->synth.seq_client,
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,
920 if (p->chset->port < 0) {
921 result = p->chset->port;
922 snd_trident_synth_free_port(p);
925 p->port = p->chset->port;
933 static int snd_trident_synth_new_device(struct snd_seq_device *dev)
935 struct snd_trident *trident;
937 struct snd_seq_client_callback callbacks;
938 struct snd_seq_client_info cinfo;
939 struct snd_seq_port_subscribe sub;
940 struct snd_simple_ops *simpleops;
943 trident = *(struct snd_trident **)SNDRV_SEQ_DEVICE_ARGPTR(dev);
947 trident->synth.seq_client = -1;
949 /* allocate new client */
950 memset(&callbacks, 0, sizeof(callbacks));
951 callbacks.private_data = trident;
952 callbacks.allow_output = callbacks.allow_input = 1;
953 client = trident->synth.seq_client =
954 snd_seq_create_kernel_client(trident->card, 1, &callbacks);
958 /* change name of client */
959 memset(&cinfo, 0, sizeof(cinfo));
960 cinfo.client = client;
961 cinfo.type = KERNEL_CLIENT;
963 switch (trident->device) {
964 case TRIDENT_DEVICE_ID_DX: str = "Trident 4DWave-DX"; break;
965 case TRIDENT_DEVICE_ID_NX: str = "Trident 4DWave-NX"; break;
966 case TRIDENT_DEVICE_ID_SI7018: str = "SiS 7018"; break;
968 sprintf(cinfo.name, str);
969 snd_seq_kernel_client_ctl(client, SNDRV_SEQ_IOCTL_SET_CLIENT_INFO, &cinfo);
971 for (i = 0; i < 4; i++)
972 snd_trident_synth_create_port(trident, i);
974 trident->synth.ilist = snd_seq_instr_list_new();
975 if (trident->synth.ilist == NULL) {
976 snd_seq_delete_kernel_client(client);
977 trident->synth.seq_client = -1;
980 trident->synth.ilist->flags = SNDRV_SEQ_INSTR_FLG_DIRECT;
982 simpleops = &trident->synth.simple_ops;
983 snd_seq_simple_init(simpleops, trident, NULL);
984 simpleops->put_sample = snd_trident_simple_put_sample;
985 simpleops->get_sample = snd_trident_simple_get_sample;
986 simpleops->remove_sample = snd_trident_simple_remove_sample;
987 simpleops->notify = snd_trident_synth_instr_notify;
989 memset(&sub, 0, sizeof(sub));
990 sub.sender.client = SNDRV_SEQ_CLIENT_SYSTEM;
991 sub.sender.port = SNDRV_SEQ_PORT_SYSTEM_ANNOUNCE;
992 sub.dest.client = client;
994 snd_seq_kernel_client_ctl(client, SNDRV_SEQ_IOCTL_SUBSCRIBE_PORT, &sub);
999 static int snd_trident_synth_delete_device(struct snd_seq_device *dev)
1001 struct snd_trident *trident;
1003 trident = *(struct snd_trident **)SNDRV_SEQ_DEVICE_ARGPTR(dev);
1004 if (trident == NULL)
1007 if (trident->synth.seq_client >= 0) {
1008 snd_seq_delete_kernel_client(trident->synth.seq_client);
1009 trident->synth.seq_client = -1;
1011 if (trident->synth.ilist)
1012 snd_seq_instr_list_free(&trident->synth.ilist);
1016 static int __init alsa_trident_synth_init(void)
1018 static struct snd_seq_dev_ops ops =
1020 snd_trident_synth_new_device,
1021 snd_trident_synth_delete_device
1024 return snd_seq_device_register_driver(SNDRV_SEQ_DEV_ID_TRIDENT, &ops,
1025 sizeof(struct snd_trident *));
1028 static void __exit alsa_trident_synth_exit(void)
1030 snd_seq_device_unregister_driver(SNDRV_SEQ_DEV_ID_TRIDENT);
1033 module_init(alsa_trident_synth_init)
1034 module_exit(alsa_trident_synth_exit)