1/*
2 *  synth callback routines for Emu10k1
3 *
4 *  Copyright (C) 2000 Takashi Iwai <tiwai@suse.de>
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#include "emu10k1_synth_local.h"
22#include <sound/asoundef.h>
23
24/* voice status */
25enum {
26	V_FREE=0, V_OFF, V_RELEASED, V_PLAYING, V_END
27};
28
29/* Keeps track of what we are finding */
30struct best_voice {
31	unsigned int time;
32	int voice;
33};
34
35/*
36 * prototypes
37 */
38static void lookup_voices(struct snd_emux *emu, struct snd_emu10k1 *hw,
39			  struct best_voice *best, int active_only);
40static struct snd_emux_voice *get_voice(struct snd_emux *emu,
41					struct snd_emux_port *port);
42static int start_voice(struct snd_emux_voice *vp);
43static void trigger_voice(struct snd_emux_voice *vp);
44static void release_voice(struct snd_emux_voice *vp);
45static void update_voice(struct snd_emux_voice *vp, int update);
46static void terminate_voice(struct snd_emux_voice *vp);
47static void free_voice(struct snd_emux_voice *vp);
48
49static void set_fmmod(struct snd_emu10k1 *hw, struct snd_emux_voice *vp);
50static void set_fm2frq2(struct snd_emu10k1 *hw, struct snd_emux_voice *vp);
51static void set_filterQ(struct snd_emu10k1 *hw, struct snd_emux_voice *vp);
52
53/*
54 * Ensure a value is between two points
55 * macro evaluates its args more than once, so changed to upper-case.
56 */
57#define LIMITVALUE(x, a, b) do { if ((x) < (a)) (x) = (a); else if ((x) > (b)) (x) = (b); } while (0)
58#define LIMITMAX(x, a) do {if ((x) > (a)) (x) = (a); } while (0)
59
60
61/*
62 * set up operators
63 */
64static struct snd_emux_operators emu10k1_ops = {
65	.owner =	THIS_MODULE,
66	.get_voice =	get_voice,
67	.prepare =	start_voice,
68	.trigger =	trigger_voice,
69	.release =	release_voice,
70	.update =	update_voice,
71	.terminate =	terminate_voice,
72	.free_voice =	free_voice,
73	.sample_new =	snd_emu10k1_sample_new,
74	.sample_free =	snd_emu10k1_sample_free,
75};
76
77void
78snd_emu10k1_ops_setup(struct snd_emux *emu)
79{
80	emu->ops = emu10k1_ops;
81}
82
83
84/*
85 * get more voice for pcm
86 *
87 * terminate most inactive voice and give it as a pcm voice.
88 */
89int
90snd_emu10k1_synth_get_voice(struct snd_emu10k1 *hw)
91{
92	struct snd_emux *emu;
93	struct snd_emux_voice *vp;
94	struct best_voice best[V_END];
95	unsigned long flags;
96	int i;
97
98	emu = hw->synth;
99
100	spin_lock_irqsave(&emu->voice_lock, flags);
101	lookup_voices(emu, hw, best, 1); /* no OFF voices */
102	for (i = 0; i < V_END; i++) {
103		if (best[i].voice >= 0) {
104			int ch;
105			vp = &emu->voices[best[i].voice];
106			if ((ch = vp->ch) < 0) {
107				//printk("synth_get_voice: ch < 0 (%d) ??", i);
108				continue;
109			}
110			vp->emu->num_voices--;
111			vp->ch = -1;
112			vp->state = SNDRV_EMUX_ST_OFF;
113			spin_unlock_irqrestore(&emu->voice_lock, flags);
114			return ch;
115		}
116	}
117	spin_unlock_irqrestore(&emu->voice_lock, flags);
118
119	/* not found */
120	return -ENOMEM;
121}
122
123
124/*
125 * turn off the voice (not terminated)
126 */
127static void
128release_voice(struct snd_emux_voice *vp)
129{
130	int dcysusv;
131	struct snd_emu10k1 *hw;
132
133	hw = vp->hw;
134	dcysusv = 0x8000 | (unsigned char)vp->reg.parm.modrelease;
135	snd_emu10k1_ptr_write(hw, DCYSUSM, vp->ch, dcysusv);
136	dcysusv = 0x8000 | (unsigned char)vp->reg.parm.volrelease | DCYSUSV_CHANNELENABLE_MASK;
137	snd_emu10k1_ptr_write(hw, DCYSUSV, vp->ch, dcysusv);
138}
139
140
141/*
142 * terminate the voice
143 */
144static void
145terminate_voice(struct snd_emux_voice *vp)
146{
147	struct snd_emu10k1 *hw;
148
149	snd_assert(vp, return);
150	hw = vp->hw;
151	snd_emu10k1_ptr_write(hw, DCYSUSV, vp->ch, 0x807f | DCYSUSV_CHANNELENABLE_MASK);
152	if (vp->block) {
153		struct snd_emu10k1_memblk *emem;
154		emem = (struct snd_emu10k1_memblk *)vp->block;
155		if (emem->map_locked > 0)
156			emem->map_locked--;
157	}
158}
159
160/*
161 * release the voice to system
162 */
163static void
164free_voice(struct snd_emux_voice *vp)
165{
166	struct snd_emu10k1 *hw;
167
168	hw = vp->hw;
169	if (vp->ch >= 0) {
170		snd_emu10k1_ptr_write(hw, IFATN, vp->ch, 0xff00);
171		snd_emu10k1_ptr_write(hw, DCYSUSV, vp->ch, 0x807f | DCYSUSV_CHANNELENABLE_MASK);
172		// snd_emu10k1_ptr_write(hw, DCYSUSV, vp->ch, 0);
173		snd_emu10k1_ptr_write(hw, VTFT, vp->ch, 0xffff);
174		snd_emu10k1_ptr_write(hw, CVCF, vp->ch, 0xffff);
175		snd_emu10k1_voice_free(hw, &hw->voices[vp->ch]);
176		vp->emu->num_voices--;
177		vp->ch = -1;
178	}
179}
180
181
182/*
183 * update registers
184 */
185static void
186update_voice(struct snd_emux_voice *vp, int update)
187{
188	struct snd_emu10k1 *hw;
189
190	hw = vp->hw;
191	if (update & SNDRV_EMUX_UPDATE_VOLUME)
192		snd_emu10k1_ptr_write(hw, IFATN_ATTENUATION, vp->ch, vp->avol);
193	if (update & SNDRV_EMUX_UPDATE_PITCH)
194		snd_emu10k1_ptr_write(hw, IP, vp->ch, vp->apitch);
195	if (update & SNDRV_EMUX_UPDATE_PAN) {
196		snd_emu10k1_ptr_write(hw, PTRX_FXSENDAMOUNT_A, vp->ch, vp->apan);
197		snd_emu10k1_ptr_write(hw, PTRX_FXSENDAMOUNT_B, vp->ch, vp->aaux);
198	}
199	if (update & SNDRV_EMUX_UPDATE_FMMOD)
200		set_fmmod(hw, vp);
201	if (update & SNDRV_EMUX_UPDATE_TREMFREQ)
202		snd_emu10k1_ptr_write(hw, TREMFRQ, vp->ch, vp->reg.parm.tremfrq);
203	if (update & SNDRV_EMUX_UPDATE_FM2FRQ2)
204		set_fm2frq2(hw, vp);
205	if (update & SNDRV_EMUX_UPDATE_Q)
206		set_filterQ(hw, vp);
207}
208
209
210/*
211 * look up voice table - get the best voice in order of preference
212 */
213/* spinlock held! */
214static void
215lookup_voices(struct snd_emux *emu, struct snd_emu10k1 *hw,
216	      struct best_voice *best, int active_only)
217{
218	struct snd_emux_voice *vp;
219	struct best_voice *bp;
220	int  i;
221
222	for (i = 0; i < V_END; i++) {
223		best[i].time = (unsigned int)-1;;
224		best[i].voice = -1;
225	}
226
227	/*
228	 * Go through them all and get a best one to use.
229	 * NOTE: could also look at volume and pick the quietest one.
230	 */
231	for (i = 0; i < emu->max_voices; i++) {
232		int state, val;
233
234		vp = &emu->voices[i];
235		state = vp->state;
236		if (state == SNDRV_EMUX_ST_OFF) {
237			if (vp->ch < 0) {
238				if (active_only)
239					continue;
240				bp = best + V_FREE;
241			} else
242				bp = best + V_OFF;
243		}
244		else if (state == SNDRV_EMUX_ST_RELEASED ||
245			 state == SNDRV_EMUX_ST_PENDING) {
246			bp = best + V_RELEASED;
247			val = snd_emu10k1_ptr_read(hw, CVCF_CURRENTVOL, vp->ch);
248			if (! val)
249				bp = best + V_OFF;
250		}
251		else if (state == SNDRV_EMUX_ST_STANDBY)
252			continue;
253		else if (state & SNDRV_EMUX_ST_ON)
254			bp = best + V_PLAYING;
255		else
256			continue;
257
258		/* check if sample is finished playing (non-looping only) */
259		if (bp != best + V_OFF && bp != best + V_FREE &&
260		    (vp->reg.sample_mode & SNDRV_SFNT_SAMPLE_SINGLESHOT)) {
261			val = snd_emu10k1_ptr_read(hw, CCCA_CURRADDR, vp->ch);
262			if (val >= vp->reg.loopstart)
263				bp = best + V_OFF;
264		}
265
266		if (vp->time < bp->time) {
267			bp->time = vp->time;
268			bp->voice = i;
269		}
270	}
271}
272
273/*
274 * get an empty voice
275 *
276 * emu->voice_lock is already held.
277 */
278static struct snd_emux_voice *
279get_voice(struct snd_emux *emu, struct snd_emux_port *port)
280{
281	struct snd_emu10k1 *hw;
282	struct snd_emux_voice *vp;
283	struct best_voice best[V_END];
284	int i;
285
286	hw = emu->hw;
287
288	lookup_voices(emu, hw, best, 0);
289	for (i = 0; i < V_END; i++) {
290		if (best[i].voice >= 0) {
291			vp = &emu->voices[best[i].voice];
292			if (vp->ch < 0) {
293				/* allocate a voice */
294				struct snd_emu10k1_voice *hwvoice;
295				if (snd_emu10k1_voice_alloc(hw, EMU10K1_SYNTH, 1, &hwvoice) < 0 || hwvoice == NULL)
296					continue;
297				vp->ch = hwvoice->number;
298				emu->num_voices++;
299			}
300			return vp;
301		}
302	}
303
304	/* not found */
305	return NULL;
306}
307
308/*
309 * prepare envelopes and LFOs
310 */
311static int
312start_voice(struct snd_emux_voice *vp)
313{
314	unsigned int temp;
315	int ch;
316	unsigned int addr, mapped_offset;
317	struct snd_midi_channel *chan;
318	struct snd_emu10k1 *hw;
319	struct snd_emu10k1_memblk *emem;
320
321	hw = vp->hw;
322	ch = vp->ch;
323	snd_assert(ch >= 0, return -EINVAL);
324	chan = vp->chan;
325
326	emem = (struct snd_emu10k1_memblk *)vp->block;
327	if (emem == NULL)
328		return -EINVAL;
329	emem->map_locked++;
330	if (snd_emu10k1_memblk_map(hw, emem) < 0) {
331		// printk("emu: cannot map!\n");
332		return -ENOMEM;
333	}
334	mapped_offset = snd_emu10k1_memblk_offset(emem) >> 1;
335	vp->reg.start += mapped_offset;
336	vp->reg.end += mapped_offset;
337	vp->reg.loopstart += mapped_offset;
338	vp->reg.loopend += mapped_offset;
339
340	/* set channel routing */
341	/* A = left(0), B = right(1), C = reverb(c), D = chorus(d) */
342	if (hw->audigy) {
343		temp = FXBUS_MIDI_LEFT | (FXBUS_MIDI_RIGHT << 8) |
344			(FXBUS_MIDI_REVERB << 16) | (FXBUS_MIDI_CHORUS << 24);
345		snd_emu10k1_ptr_write(hw, A_FXRT1, ch, temp);
346	} else {
347		temp = (FXBUS_MIDI_LEFT << 16) | (FXBUS_MIDI_RIGHT << 20) |
348			(FXBUS_MIDI_REVERB << 24) | (FXBUS_MIDI_CHORUS << 28);
349		snd_emu10k1_ptr_write(hw, FXRT, ch, temp);
350	}
351
352	/* channel to be silent and idle */
353	snd_emu10k1_ptr_write(hw, DCYSUSV, ch, 0x0000);
354	snd_emu10k1_ptr_write(hw, VTFT, ch, 0x0000FFFF);
355	snd_emu10k1_ptr_write(hw, CVCF, ch, 0x0000FFFF);
356	snd_emu10k1_ptr_write(hw, PTRX, ch, 0);
357	snd_emu10k1_ptr_write(hw, CPF, ch, 0);
358
359	/* set pitch offset */
360	snd_emu10k1_ptr_write(hw, IP, vp->ch, vp->apitch);
361
362	/* set envelope parameters */
363	snd_emu10k1_ptr_write(hw, ENVVAL, ch, vp->reg.parm.moddelay);
364	snd_emu10k1_ptr_write(hw, ATKHLDM, ch, vp->reg.parm.modatkhld);
365	snd_emu10k1_ptr_write(hw, DCYSUSM, ch, vp->reg.parm.moddcysus);
366	snd_emu10k1_ptr_write(hw, ENVVOL, ch, vp->reg.parm.voldelay);
367	snd_emu10k1_ptr_write(hw, ATKHLDV, ch, vp->reg.parm.volatkhld);
368	/* decay/sustain parameter for volume envelope is used
369	   for triggerg the voice */
370
371	/* cutoff and volume */
372	temp = (unsigned int)vp->acutoff << 8 | (unsigned char)vp->avol;
373	snd_emu10k1_ptr_write(hw, IFATN, vp->ch, temp);
374
375	/* modulation envelope heights */
376	snd_emu10k1_ptr_write(hw, PEFE, ch, vp->reg.parm.pefe);
377
378	/* lfo1/2 delay */
379	snd_emu10k1_ptr_write(hw, LFOVAL1, ch, vp->reg.parm.lfo1delay);
380	snd_emu10k1_ptr_write(hw, LFOVAL2, ch, vp->reg.parm.lfo2delay);
381
382	/* lfo1 pitch & cutoff shift */
383	set_fmmod(hw, vp);
384	/* lfo1 volume & freq */
385	snd_emu10k1_ptr_write(hw, TREMFRQ, vp->ch, vp->reg.parm.tremfrq);
386	/* lfo2 pitch & freq */
387	set_fm2frq2(hw, vp);
388
389	/* reverb and loop start (reverb 8bit, MSB) */
390	temp = vp->reg.parm.reverb;
391	temp += (int)vp->chan->control[MIDI_CTL_E1_REVERB_DEPTH] * 9 / 10;
392	LIMITMAX(temp, 255);
393	addr = vp->reg.loopstart;
394	snd_emu10k1_ptr_write(hw, PSST, vp->ch, (temp << 24) | addr);
395
396	/* chorus & loop end (chorus 8bit, MSB) */
397	addr = vp->reg.loopend;
398	temp = vp->reg.parm.chorus;
399	temp += (int)chan->control[MIDI_CTL_E3_CHORUS_DEPTH] * 9 / 10;
400	LIMITMAX(temp, 255);
401	temp = (temp <<24) | addr;
402	snd_emu10k1_ptr_write(hw, DSL, ch, temp);
403
404	/* clear filter delay memory */
405	snd_emu10k1_ptr_write(hw, Z1, ch, 0);
406	snd_emu10k1_ptr_write(hw, Z2, ch, 0);
407
408	/* invalidate maps */
409	temp = (hw->silent_page.addr << 1) | MAP_PTI_MASK;
410	snd_emu10k1_ptr_write(hw, MAPA, ch, temp);
411	snd_emu10k1_ptr_write(hw, MAPB, ch, temp);
412
413	/* Q & current address (Q 4bit value, MSB) */
414	addr = vp->reg.start;
415	temp = vp->reg.parm.filterQ;
416	temp = (temp<<28) | addr;
417	if (vp->apitch < 0xe400)
418		temp |= CCCA_INTERPROM_0;
419	else {
420		unsigned int shift = (vp->apitch - 0xe000) >> 10;
421		temp |= shift << 25;
422	}
423	if (vp->reg.sample_mode & SNDRV_SFNT_SAMPLE_8BITS)
424		temp |= CCCA_8BITSELECT;
425	snd_emu10k1_ptr_write(hw, CCCA, ch, temp);
426
427	/* reset volume */
428	temp = (unsigned int)vp->vtarget << 16;
429	snd_emu10k1_ptr_write(hw, VTFT, ch, temp | vp->ftarget);
430	snd_emu10k1_ptr_write(hw, CVCF, ch, temp | 0xff00);
431	return 0;
432}
433
434/*
435 * Start envelope
436 */
437static void
438trigger_voice(struct snd_emux_voice *vp)
439{
440	unsigned int temp, ptarget;
441	struct snd_emu10k1 *hw;
442	struct snd_emu10k1_memblk *emem;
443
444	hw = vp->hw;
445
446	emem = (struct snd_emu10k1_memblk *)vp->block;
447	if (! emem || emem->mapped_page < 0)
448		return; /* not mapped */
449
450	ptarget = IP_TO_CP(vp->apitch);
451	/* set pitch target and pan (volume) */
452	temp = ptarget | (vp->apan << 8) | vp->aaux;
453	snd_emu10k1_ptr_write(hw, PTRX, vp->ch, temp);
454
455	/* pitch target */
456	snd_emu10k1_ptr_write(hw, CPF, vp->ch, ptarget);
457
458	/* trigger voice */
459	snd_emu10k1_ptr_write(hw, DCYSUSV, vp->ch, vp->reg.parm.voldcysus|DCYSUSV_CHANNELENABLE_MASK);
460}
461
462#define MOD_SENSE 18
463
464/* set lfo1 modulation height and cutoff */
465static void
466set_fmmod(struct snd_emu10k1 *hw, struct snd_emux_voice *vp)
467{
468	unsigned short fmmod;
469	short pitch;
470	unsigned char cutoff;
471	int modulation;
472
473	pitch = (char)(vp->reg.parm.fmmod>>8);
474	cutoff = (vp->reg.parm.fmmod & 0xff);
475	modulation = vp->chan->gm_modulation + vp->chan->midi_pressure;
476	pitch += (MOD_SENSE * modulation) / 1200;
477	LIMITVALUE(pitch, -128, 127);
478	fmmod = ((unsigned char)pitch<<8) | cutoff;
479	snd_emu10k1_ptr_write(hw, FMMOD, vp->ch, fmmod);
480}
481
482/* set lfo2 pitch & frequency */
483static void
484set_fm2frq2(struct snd_emu10k1 *hw, struct snd_emux_voice *vp)
485{
486	unsigned short fm2frq2;
487	short pitch;
488	unsigned char freq;
489	int modulation;
490
491	pitch = (char)(vp->reg.parm.fm2frq2>>8);
492	freq = vp->reg.parm.fm2frq2 & 0xff;
493	modulation = vp->chan->gm_modulation + vp->chan->midi_pressure;
494	pitch += (MOD_SENSE * modulation) / 1200;
495	LIMITVALUE(pitch, -128, 127);
496	fm2frq2 = ((unsigned char)pitch<<8) | freq;
497	snd_emu10k1_ptr_write(hw, FM2FRQ2, vp->ch, fm2frq2);
498}
499
500/* set filterQ */
501static void
502set_filterQ(struct snd_emu10k1 *hw, struct snd_emux_voice *vp)
503{
504	unsigned int val;
505	val = snd_emu10k1_ptr_read(hw, CCCA, vp->ch) & ~CCCA_RESONANCE;
506	val |= (vp->reg.parm.filterQ << 28);
507	snd_emu10k1_ptr_write(hw, CCCA, vp->ch, val);
508}
509