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