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 31MODULE_AUTHOR("Scott McNab <jedi@tartarus.uwa.edu.au>"); 32MODULE_DESCRIPTION("Routines for Trident 4DWave NX/DX soundcards - Synthesizer"); 33MODULE_LICENSE("GPL"); 34 35/* linear to log pan conversion table (4.2 channel attenuation format) */ 36static 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 75static 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 157static 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 */ 173static 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 195static void sample_start(struct snd_trident * trident, struct snd_trident_voice * voice, snd_seq_position_t position); 196static void sample_stop(struct snd_trident * trident, struct snd_trident_voice * voice, int mode); 197static void sample_freq(struct snd_trident * trident, struct snd_trident_voice * voice, snd_seq_frequency_t freq); 198static void sample_volume(struct snd_trident * trident, struct snd_trident_voice * voice, struct snd_seq_ev_volume * volume); 199static void sample_loop(struct snd_trident * trident, struct snd_trident_voice * voice, struct snd_seq_ev_loop * loop); 200static void sample_pos(struct snd_trident * trident, struct snd_trident_voice * voice, snd_seq_position_t position); 201static void sample_private1(struct snd_trident * trident, struct snd_trident_voice * voice, unsigned char *data); 202 203static 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 214static 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 223static 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 308static 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 332static 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 358static 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; 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 410static 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 449static 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 499static 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 507static 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 561static 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 579 return -EBUSY; 580} 581 582static int snd_trident_simple_remove_sample(void *private_data, 583 struct simple_instrument * instr, 584 int atomic) 585{ 586 struct snd_trident *trident = private_data; 587 int size = instr->size; 588 589 if (instr->format & SIMPLE_WAVE_16BIT) 590 size <<= 1; 591 if (instr->format & SIMPLE_WAVE_STEREO) 592 size <<= 1; 593 594 if (trident->tlb.entries) { 595 struct snd_util_memblk *memblk = (struct snd_util_memblk *)instr->address.ptr; 596 if (memblk) 597 snd_trident_synth_free(trident, memblk); 598 else 599 return -EFAULT; 600 } else { 601 struct snd_dma_buffer dmab; 602 dmab.dev.type = SNDRV_DMA_TYPE_DEV; 603 dmab.dev.dev = snd_dma_pci_data(trident->pci); 604 dmab.area = instr->address.ptr; 605 dmab.addr = instr->address.memory; 606 dmab.bytes = size; 607 snd_dma_free_pages(&dmab); 608 } 609 610 trident->synth.current_size -= size; 611 if (trident->synth.current_size < 0) /* shouldn't need this check... */ 612 trident->synth.current_size = 0; 613 614 return 0; 615} 616 617static void select_instrument(struct snd_trident * trident, struct snd_trident_voice * v) 618{ 619 struct snd_seq_kinstr *instr; 620 instr = snd_seq_instr_find(trident->synth.ilist, &v->instr, 0, 1); 621 if (instr != NULL) { 622 if (instr->ops) { 623 if (!strcmp(instr->ops->instr_type, SNDRV_SEQ_INSTR_ID_SIMPLE)) 624 snd_trident_simple_init(v); 625 } 626 snd_seq_instr_free_use(trident->synth.ilist, instr); 627 } 628} 629 630/* 631 632 */ 633 634static void event_sample(struct snd_seq_event * ev, struct snd_trident_port * p, struct snd_trident_voice * v) 635{ 636 if (v->sample_ops && v->sample_ops->sample_stop) 637 v->sample_ops->sample_stop(p->trident, v, SAMPLE_STOP_IMMEDIATELY); 638 v->instr.std = ev->data.sample.param.sample.std; 639 if (v->instr.std & 0xff000000) { /* private instrument */ 640 v->instr.std &= 0x00ffffff; 641 v->instr.std |= (unsigned int)ev->source.client << 24; 642 } 643 v->instr.bank = ev->data.sample.param.sample.bank; 644 v->instr.prg = ev->data.sample.param.sample.prg; 645 select_instrument(p->trident, v); 646} 647 648static void event_cluster(struct snd_seq_event * ev, struct snd_trident_port * p, struct snd_trident_voice * v) 649{ 650 if (v->sample_ops && v->sample_ops->sample_stop) 651 v->sample_ops->sample_stop(p->trident, v, SAMPLE_STOP_IMMEDIATELY); 652 v->instr.cluster = ev->data.sample.param.cluster.cluster; 653 select_instrument(p->trident, v); 654} 655 656static void event_start(struct snd_seq_event * ev, struct snd_trident_port * p, struct snd_trident_voice * v) 657{ 658 if (v->sample_ops && v->sample_ops->sample_start) 659 v->sample_ops->sample_start(p->trident, v, ev->data.sample.param.position); 660} 661 662static void event_stop(struct snd_seq_event * ev, struct snd_trident_port * p, struct snd_trident_voice * v) 663{ 664 if (v->sample_ops && v->sample_ops->sample_stop) 665 v->sample_ops->sample_stop(p->trident, v, ev->data.sample.param.stop_mode); 666} 667 668static void event_freq(struct snd_seq_event * ev, struct snd_trident_port * p, struct snd_trident_voice * v) 669{ 670 if (v->sample_ops && v->sample_ops->sample_freq) 671 v->sample_ops->sample_freq(p->trident, v, ev->data.sample.param.frequency); 672} 673 674static void event_volume(struct snd_seq_event * ev, struct snd_trident_port * p, struct snd_trident_voice * v) 675{ 676 if (v->sample_ops && v->sample_ops->sample_volume) 677 v->sample_ops->sample_volume(p->trident, v, &ev->data.sample.param.volume); 678} 679 680static void event_loop(struct snd_seq_event * ev, struct snd_trident_port * p, struct snd_trident_voice * v) 681{ 682 if (v->sample_ops && v->sample_ops->sample_loop) 683 v->sample_ops->sample_loop(p->trident, v, &ev->data.sample.param.loop); 684} 685 686static void event_position(struct snd_seq_event * ev, struct snd_trident_port * p, struct snd_trident_voice * v) 687{ 688 if (v->sample_ops && v->sample_ops->sample_pos) 689 v->sample_ops->sample_pos(p->trident, v, ev->data.sample.param.position); 690} 691 692static void event_private1(struct snd_seq_event * ev, struct snd_trident_port * p, struct snd_trident_voice * v) 693{ 694 if (v->sample_ops && v->sample_ops->sample_private1) 695 v->sample_ops->sample_private1(p->trident, v, (unsigned char *) &ev->data.sample.param.raw8); 696} 697 698typedef void (trident_sample_event_handler_t) (struct snd_seq_event * ev, struct snd_trident_port * p, struct snd_trident_voice * v); 699 700static trident_sample_event_handler_t *trident_sample_event_handlers[9] = 701{ 702 event_sample, 703 event_cluster, 704 event_start, 705 event_stop, 706 event_freq, 707 event_volume, 708 event_loop, 709 event_position, 710 event_private1 711}; 712 713static void snd_trident_sample_event(struct snd_seq_event * ev, struct snd_trident_port * p) 714{ 715 int idx, voice; 716 struct snd_trident *trident = p->trident; 717 struct snd_trident_voice *v; 718 unsigned long flags; 719 720 idx = ev->type - SNDRV_SEQ_EVENT_SAMPLE; 721 if (idx < 0 || idx > 8) 722 return; 723 for (voice = 0; voice < 64; voice++) { 724 v = &trident->synth.voices[voice]; 725 if (v->use && v->client == ev->source.client && 726 v->port == ev->source.port && 727 v->index == ev->data.sample.channel) { 728 spin_lock_irqsave(&trident->event_lock, flags); 729 trident_sample_event_handlers[idx] (ev, p, v); 730 spin_unlock_irqrestore(&trident->event_lock, flags); 731 return; 732 } 733 } 734} 735 736/* 737 738 */ 739 740static void snd_trident_synth_free_voices(struct snd_trident * trident, int client, int port) 741{ 742 int idx; 743 struct snd_trident_voice *voice; 744 745 for (idx = 0; idx < 32; idx++) { 746 voice = &trident->synth.voices[idx]; 747 if (voice->use && voice->client == client && voice->port == port) 748 snd_trident_free_voice(trident, voice); 749 } 750} 751 752static int snd_trident_synth_use(void *private_data, struct snd_seq_port_subscribe * info) 753{ 754 struct snd_trident_port *port = private_data; 755 struct snd_trident *trident = port->trident; 756 struct snd_trident_voice *voice; 757 unsigned int idx; 758 unsigned long flags; 759 760 if (info->voices > 32) 761 return -EINVAL; 762 spin_lock_irqsave(&trident->reg_lock, flags); 763 for (idx = 0; idx < info->voices; idx++) { 764 voice = snd_trident_alloc_voice(trident, SNDRV_TRIDENT_VOICE_TYPE_SYNTH, info->sender.client, info->sender.port); 765 if (voice == NULL) { 766 snd_trident_synth_free_voices(trident, info->sender.client, info->sender.port); 767 spin_unlock_irqrestore(&trident->reg_lock, flags); 768 return -EBUSY; 769 } 770 voice->index = idx; 771 voice->Vol = 0x3ff; 772 voice->EC = 0x0fff; 773 } 774 spin_unlock_irqrestore(&trident->reg_lock, flags); 775 return 0; 776} 777 778static int snd_trident_synth_unuse(void *private_data, struct snd_seq_port_subscribe * info) 779{ 780 struct snd_trident_port *port = private_data; 781 struct snd_trident *trident = port->trident; 782 unsigned long flags; 783 784 spin_lock_irqsave(&trident->reg_lock, flags); 785 snd_trident_synth_free_voices(trident, info->sender.client, info->sender.port); 786 spin_unlock_irqrestore(&trident->reg_lock, flags); 787 return 0; 788} 789 790/* 791 792 */ 793 794static void snd_trident_synth_free_private_instruments(struct snd_trident_port * p, int client) 795{ 796 struct snd_seq_instr_header ifree; 797 798 memset(&ifree, 0, sizeof(ifree)); 799 ifree.cmd = SNDRV_SEQ_INSTR_FREE_CMD_PRIVATE; 800 snd_seq_instr_list_free_cond(p->trident->synth.ilist, &ifree, client, 0); 801} 802 803static int snd_trident_synth_event_input(struct snd_seq_event * ev, int direct, void *private_data, int atomic, int hop) 804{ 805 struct snd_trident_port *p = (struct snd_trident_port *) private_data; 806 807 if (p == NULL) 808 return -EINVAL; 809 if (ev->type >= SNDRV_SEQ_EVENT_SAMPLE && 810 ev->type <= SNDRV_SEQ_EVENT_SAMPLE_PRIVATE1) { 811 snd_trident_sample_event(ev, p); 812 return 0; 813 } 814 if (ev->source.client == SNDRV_SEQ_CLIENT_SYSTEM && 815 ev->source.port == SNDRV_SEQ_PORT_SYSTEM_ANNOUNCE) { 816 if (ev->type == SNDRV_SEQ_EVENT_CLIENT_EXIT) { 817 snd_trident_synth_free_private_instruments(p, ev->data.addr.client); 818 return 0; 819 } 820 } 821 if (direct) { 822 if (ev->type >= SNDRV_SEQ_EVENT_INSTR_BEGIN) { 823 snd_seq_instr_event(&p->trident->synth.simple_ops.kops, 824 p->trident->synth.ilist, ev, 825 p->trident->synth.seq_client, atomic, hop); 826 return 0; 827 } 828 } 829 return 0; 830} 831 832static void snd_trident_synth_instr_notify(void *private_data, 833 struct snd_seq_kinstr * instr, 834 int what) 835{ 836 int idx; 837 struct snd_trident *trident = private_data; 838 struct snd_trident_voice *pvoice; 839 unsigned long flags; 840 841 spin_lock_irqsave(&trident->event_lock, flags); 842 for (idx = 0; idx < 64; idx++) { 843 pvoice = &trident->synth.voices[idx]; 844 if (pvoice->use && !memcmp(&pvoice->instr, &instr->instr, sizeof(pvoice->instr))) { 845 if (pvoice->sample_ops && pvoice->sample_ops->sample_stop) { 846 pvoice->sample_ops->sample_stop(trident, pvoice, SAMPLE_STOP_IMMEDIATELY); 847 } else { 848 snd_trident_stop_voice(trident, pvoice->number); 849 pvoice->flags &= ~SNDRV_TRIDENT_VFLG_RUNNING; 850 } 851 } 852 } 853 spin_unlock_irqrestore(&trident->event_lock, flags); 854} 855 856/* 857 858 */ 859 860static void snd_trident_synth_free_port(void *private_data) 861{ 862 struct snd_trident_port *p = (struct snd_trident_port *) private_data; 863 864 if (p) 865 snd_midi_channel_free_set(p->chset); 866} 867 868static int snd_trident_synth_create_port(struct snd_trident * trident, int idx) 869{ 870 struct snd_trident_port *p; 871 struct snd_seq_port_callback callbacks; 872 char name[32]; 873 char *str; 874 int result; 875 876 p = &trident->synth.seq_ports[idx]; 877 p->chset = snd_midi_channel_alloc_set(16); 878 if (p->chset == NULL) 879 return -ENOMEM; 880 p->chset->private_data = p; 881 p->trident = trident; 882 p->client = trident->synth.seq_client; 883 884 memset(&callbacks, 0, sizeof(callbacks)); 885 callbacks.owner = THIS_MODULE; 886 callbacks.use = snd_trident_synth_use; 887 callbacks.unuse = snd_trident_synth_unuse; 888 callbacks.event_input = snd_trident_synth_event_input; 889 callbacks.private_free = snd_trident_synth_free_port; 890 callbacks.private_data = p; 891 892 str = "???"; 893 switch (trident->device) { 894 case TRIDENT_DEVICE_ID_DX: str = "Trident 4DWave-DX"; break; 895 case TRIDENT_DEVICE_ID_NX: str = "Trident 4DWave-NX"; break; 896 case TRIDENT_DEVICE_ID_SI7018: str = "SiS 7018"; break; 897 } 898 sprintf(name, "%s port %i", str, idx); 899 p->chset->port = snd_seq_event_port_attach(trident->synth.seq_client, 900 &callbacks, 901 SNDRV_SEQ_PORT_CAP_WRITE | SNDRV_SEQ_PORT_CAP_SUBS_WRITE, 902 SNDRV_SEQ_PORT_TYPE_DIRECT_SAMPLE | 903 SNDRV_SEQ_PORT_TYPE_SYNTH | 904 SNDRV_SEQ_PORT_TYPE_HARDWARE | 905 SNDRV_SEQ_PORT_TYPE_SYNTHESIZER, 906 16, 0, 907 name); 908 if (p->chset->port < 0) { 909 result = p->chset->port; 910 snd_trident_synth_free_port(p); 911 return result; 912 } 913 p->port = p->chset->port; 914 return 0; 915} 916 917/* 918 919 */ 920 921static int snd_trident_synth_new_device(struct snd_seq_device *dev) 922{ 923 struct snd_trident *trident; 924 int client, i; 925 struct snd_seq_port_subscribe sub; 926 struct snd_simple_ops *simpleops; 927 char *str; 928 929 trident = *(struct snd_trident **)SNDRV_SEQ_DEVICE_ARGPTR(dev); 930 if (trident == NULL) 931 return -EINVAL; 932 933 trident->synth.seq_client = -1; 934 935 /* allocate new client */ 936 str = "???"; 937 switch (trident->device) { 938 case TRIDENT_DEVICE_ID_DX: str = "Trident 4DWave-DX"; break; 939 case TRIDENT_DEVICE_ID_NX: str = "Trident 4DWave-NX"; break; 940 case TRIDENT_DEVICE_ID_SI7018: str = "SiS 7018"; break; 941 } 942 client = trident->synth.seq_client = 943 snd_seq_create_kernel_client(trident->card, 1, str); 944 if (client < 0) 945 return client; 946 947 for (i = 0; i < 4; i++) 948 snd_trident_synth_create_port(trident, i); 949 950 trident->synth.ilist = snd_seq_instr_list_new(); 951 if (trident->synth.ilist == NULL) { 952 snd_seq_delete_kernel_client(client); 953 trident->synth.seq_client = -1; 954 return -ENOMEM; 955 } 956 trident->synth.ilist->flags = SNDRV_SEQ_INSTR_FLG_DIRECT; 957 958 simpleops = &trident->synth.simple_ops; 959 snd_seq_simple_init(simpleops, trident, NULL); 960 simpleops->put_sample = snd_trident_simple_put_sample; 961 simpleops->get_sample = snd_trident_simple_get_sample; 962 simpleops->remove_sample = snd_trident_simple_remove_sample; 963 simpleops->notify = snd_trident_synth_instr_notify; 964 965 memset(&sub, 0, sizeof(sub)); 966 sub.sender.client = SNDRV_SEQ_CLIENT_SYSTEM; 967 sub.sender.port = SNDRV_SEQ_PORT_SYSTEM_ANNOUNCE; 968 sub.dest.client = client; 969 sub.dest.port = 0; 970 snd_seq_kernel_client_ctl(client, SNDRV_SEQ_IOCTL_SUBSCRIBE_PORT, &sub); 971 972 return 0; 973} 974 975static int snd_trident_synth_delete_device(struct snd_seq_device *dev) 976{ 977 struct snd_trident *trident; 978 979 trident = *(struct snd_trident **)SNDRV_SEQ_DEVICE_ARGPTR(dev); 980 if (trident == NULL) 981 return -EINVAL; 982 983 if (trident->synth.seq_client >= 0) { 984 snd_seq_delete_kernel_client(trident->synth.seq_client); 985 trident->synth.seq_client = -1; 986 } 987 if (trident->synth.ilist) 988 snd_seq_instr_list_free(&trident->synth.ilist); 989 return 0; 990} 991 992static int __init alsa_trident_synth_init(void) 993{ 994 static struct snd_seq_dev_ops ops = 995 { 996 snd_trident_synth_new_device, 997 snd_trident_synth_delete_device 998 }; 999 1000 return snd_seq_device_register_driver(SNDRV_SEQ_DEV_ID_TRIDENT, &ops, 1001 sizeof(struct snd_trident *)); 1002} 1003 1004static void __exit alsa_trident_synth_exit(void) 1005{ 1006 snd_seq_device_unregister_driver(SNDRV_SEQ_DEV_ID_TRIDENT); 1007} 1008 1009module_init(alsa_trident_synth_init) 1010module_exit(alsa_trident_synth_exit) 1011