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