Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  *  synth callback routines for Emu10k1
0004  *
0005  *  Copyright (C) 2000 Takashi Iwai <tiwai@suse.de>
0006  */
0007 
0008 #include <linux/export.h>
0009 #include "emu10k1_synth_local.h"
0010 #include <sound/asoundef.h>
0011 
0012 /* voice status */
0013 enum {
0014     V_FREE=0, V_OFF, V_RELEASED, V_PLAYING, V_END
0015 };
0016 
0017 /* Keeps track of what we are finding */
0018 struct best_voice {
0019     unsigned int time;
0020     int voice;
0021 };
0022 
0023 /*
0024  * prototypes
0025  */
0026 static void lookup_voices(struct snd_emux *emux, struct snd_emu10k1 *hw,
0027               struct best_voice *best, int active_only);
0028 static struct snd_emux_voice *get_voice(struct snd_emux *emux,
0029                     struct snd_emux_port *port);
0030 static int start_voice(struct snd_emux_voice *vp);
0031 static void trigger_voice(struct snd_emux_voice *vp);
0032 static void release_voice(struct snd_emux_voice *vp);
0033 static void update_voice(struct snd_emux_voice *vp, int update);
0034 static void terminate_voice(struct snd_emux_voice *vp);
0035 static void free_voice(struct snd_emux_voice *vp);
0036 static void set_fmmod(struct snd_emu10k1 *hw, struct snd_emux_voice *vp);
0037 static void set_fm2frq2(struct snd_emu10k1 *hw, struct snd_emux_voice *vp);
0038 static void set_filterQ(struct snd_emu10k1 *hw, struct snd_emux_voice *vp);
0039 
0040 /*
0041  * Ensure a value is between two points
0042  * macro evaluates its args more than once, so changed to upper-case.
0043  */
0044 #define LIMITVALUE(x, a, b) do { if ((x) < (a)) (x) = (a); else if ((x) > (b)) (x) = (b); } while (0)
0045 #define LIMITMAX(x, a) do {if ((x) > (a)) (x) = (a); } while (0)
0046 
0047 
0048 /*
0049  * set up operators
0050  */
0051 static const struct snd_emux_operators emu10k1_ops = {
0052     .owner =    THIS_MODULE,
0053     .get_voice =    get_voice,
0054     .prepare =  start_voice,
0055     .trigger =  trigger_voice,
0056     .release =  release_voice,
0057     .update =   update_voice,
0058     .terminate =    terminate_voice,
0059     .free_voice =   free_voice,
0060     .sample_new =   snd_emu10k1_sample_new,
0061     .sample_free =  snd_emu10k1_sample_free,
0062 };
0063 
0064 void
0065 snd_emu10k1_ops_setup(struct snd_emux *emux)
0066 {
0067     emux->ops = emu10k1_ops;
0068 }
0069 
0070 
0071 /*
0072  * get more voice for pcm
0073  *
0074  * terminate most inactive voice and give it as a pcm voice.
0075  *
0076  * voice_lock is already held.
0077  */
0078 int
0079 snd_emu10k1_synth_get_voice(struct snd_emu10k1 *hw)
0080 {
0081     struct snd_emux *emu;
0082     struct snd_emux_voice *vp;
0083     struct best_voice best[V_END];
0084     int i;
0085 
0086     emu = hw->synth;
0087 
0088     lookup_voices(emu, hw, best, 1); /* no OFF voices */
0089     for (i = 0; i < V_END; i++) {
0090         if (best[i].voice >= 0) {
0091             int ch;
0092             vp = &emu->voices[best[i].voice];
0093             ch = vp->ch;
0094             if (ch < 0) {
0095                 /*
0096                 dev_warn(emu->card->dev,
0097                        "synth_get_voice: ch < 0 (%d) ??", i);
0098                 */
0099                 continue;
0100             }
0101             vp->emu->num_voices--;
0102             vp->ch = -1;
0103             vp->state = SNDRV_EMUX_ST_OFF;
0104             return ch;
0105         }
0106     }
0107 
0108     /* not found */
0109     return -ENOMEM;
0110 }
0111 
0112 
0113 /*
0114  * turn off the voice (not terminated)
0115  */
0116 static void
0117 release_voice(struct snd_emux_voice *vp)
0118 {
0119     int dcysusv;
0120     struct snd_emu10k1 *hw;
0121     
0122     hw = vp->hw;
0123     dcysusv = 0x8000 | (unsigned char)vp->reg.parm.modrelease;
0124     snd_emu10k1_ptr_write(hw, DCYSUSM, vp->ch, dcysusv);
0125     dcysusv = 0x8000 | (unsigned char)vp->reg.parm.volrelease | DCYSUSV_CHANNELENABLE_MASK;
0126     snd_emu10k1_ptr_write(hw, DCYSUSV, vp->ch, dcysusv);
0127 }
0128 
0129 
0130 /*
0131  * terminate the voice
0132  */
0133 static void
0134 terminate_voice(struct snd_emux_voice *vp)
0135 {
0136     struct snd_emu10k1 *hw;
0137     
0138     if (snd_BUG_ON(!vp))
0139         return;
0140     hw = vp->hw;
0141     snd_emu10k1_ptr_write(hw, DCYSUSV, vp->ch, 0x807f | DCYSUSV_CHANNELENABLE_MASK);
0142     if (vp->block) {
0143         struct snd_emu10k1_memblk *emem;
0144         emem = (struct snd_emu10k1_memblk *)vp->block;
0145         if (emem->map_locked > 0)
0146             emem->map_locked--;
0147     }
0148 }
0149 
0150 /*
0151  * release the voice to system
0152  */
0153 static void
0154 free_voice(struct snd_emux_voice *vp)
0155 {
0156     struct snd_emu10k1 *hw;
0157     
0158     hw = vp->hw;
0159     /* FIXME: emu10k1_synth is broken. */
0160     /* This can get called with hw == 0 */
0161     /* Problem apparent on plug, unplug then plug */
0162     /* on the Audigy 2 ZS Notebook. */
0163     if (hw && (vp->ch >= 0)) {
0164         snd_emu10k1_ptr_write(hw, IFATN, vp->ch, 0xff00);
0165         snd_emu10k1_ptr_write(hw, DCYSUSV, vp->ch, 0x807f | DCYSUSV_CHANNELENABLE_MASK);
0166         // snd_emu10k1_ptr_write(hw, DCYSUSV, vp->ch, 0);
0167         snd_emu10k1_ptr_write(hw, VTFT, vp->ch, 0xffff);
0168         snd_emu10k1_ptr_write(hw, CVCF, vp->ch, 0xffff);
0169         snd_emu10k1_voice_free(hw, &hw->voices[vp->ch]);
0170         vp->emu->num_voices--;
0171         vp->ch = -1;
0172     }
0173 }
0174 
0175 
0176 /*
0177  * update registers
0178  */
0179 static void
0180 update_voice(struct snd_emux_voice *vp, int update)
0181 {
0182     struct snd_emu10k1 *hw;
0183     
0184     hw = vp->hw;
0185     if (update & SNDRV_EMUX_UPDATE_VOLUME)
0186         snd_emu10k1_ptr_write(hw, IFATN_ATTENUATION, vp->ch, vp->avol);
0187     if (update & SNDRV_EMUX_UPDATE_PITCH)
0188         snd_emu10k1_ptr_write(hw, IP, vp->ch, vp->apitch);
0189     if (update & SNDRV_EMUX_UPDATE_PAN) {
0190         snd_emu10k1_ptr_write(hw, PTRX_FXSENDAMOUNT_A, vp->ch, vp->apan);
0191         snd_emu10k1_ptr_write(hw, PTRX_FXSENDAMOUNT_B, vp->ch, vp->aaux);
0192     }
0193     if (update & SNDRV_EMUX_UPDATE_FMMOD)
0194         set_fmmod(hw, vp);
0195     if (update & SNDRV_EMUX_UPDATE_TREMFREQ)
0196         snd_emu10k1_ptr_write(hw, TREMFRQ, vp->ch, vp->reg.parm.tremfrq);
0197     if (update & SNDRV_EMUX_UPDATE_FM2FRQ2)
0198         set_fm2frq2(hw, vp);
0199     if (update & SNDRV_EMUX_UPDATE_Q)
0200         set_filterQ(hw, vp);
0201 }
0202 
0203 
0204 /*
0205  * look up voice table - get the best voice in order of preference
0206  */
0207 /* spinlock held! */
0208 static void
0209 lookup_voices(struct snd_emux *emu, struct snd_emu10k1 *hw,
0210           struct best_voice *best, int active_only)
0211 {
0212     struct snd_emux_voice *vp;
0213     struct best_voice *bp;
0214     int  i;
0215 
0216     for (i = 0; i < V_END; i++) {
0217         best[i].time = (unsigned int)-1; /* XXX MAX_?INT really */
0218         best[i].voice = -1;
0219     }
0220 
0221     /*
0222      * Go through them all and get a best one to use.
0223      * NOTE: could also look at volume and pick the quietest one.
0224      */
0225     for (i = 0; i < emu->max_voices; i++) {
0226         int state, val;
0227 
0228         vp = &emu->voices[i];
0229         state = vp->state;
0230         if (state == SNDRV_EMUX_ST_OFF) {
0231             if (vp->ch < 0) {
0232                 if (active_only)
0233                     continue;
0234                 bp = best + V_FREE;
0235             } else
0236                 bp = best + V_OFF;
0237         }
0238         else if (state == SNDRV_EMUX_ST_RELEASED ||
0239              state == SNDRV_EMUX_ST_PENDING) {
0240             bp = best + V_RELEASED;
0241 #if 1
0242             val = snd_emu10k1_ptr_read(hw, CVCF_CURRENTVOL, vp->ch);
0243             if (! val)
0244                 bp = best + V_OFF;
0245 #endif
0246         }
0247         else if (state == SNDRV_EMUX_ST_STANDBY)
0248             continue;
0249         else if (state & SNDRV_EMUX_ST_ON)
0250             bp = best + V_PLAYING;
0251         else
0252             continue;
0253 
0254         /* check if sample is finished playing (non-looping only) */
0255         if (bp != best + V_OFF && bp != best + V_FREE &&
0256             (vp->reg.sample_mode & SNDRV_SFNT_SAMPLE_SINGLESHOT)) {
0257             val = snd_emu10k1_ptr_read(hw, CCCA_CURRADDR, vp->ch);
0258             if (val >= vp->reg.loopstart)
0259                 bp = best + V_OFF;
0260         }
0261 
0262         if (vp->time < bp->time) {
0263             bp->time = vp->time;
0264             bp->voice = i;
0265         }
0266     }
0267 }
0268 
0269 /*
0270  * get an empty voice
0271  *
0272  * emu->voice_lock is already held.
0273  */
0274 static struct snd_emux_voice *
0275 get_voice(struct snd_emux *emu, struct snd_emux_port *port)
0276 {
0277     struct snd_emu10k1 *hw;
0278     struct snd_emux_voice *vp;
0279     struct best_voice best[V_END];
0280     int i;
0281 
0282     hw = emu->hw;
0283 
0284     lookup_voices(emu, hw, best, 0);
0285     for (i = 0; i < V_END; i++) {
0286         if (best[i].voice >= 0) {
0287             vp = &emu->voices[best[i].voice];
0288             if (vp->ch < 0) {
0289                 /* allocate a voice */
0290                 struct snd_emu10k1_voice *hwvoice;
0291                 if (snd_emu10k1_voice_alloc(hw, EMU10K1_SYNTH, 1, &hwvoice) < 0 || hwvoice == NULL)
0292                     continue;
0293                 vp->ch = hwvoice->number;
0294                 emu->num_voices++;
0295             }
0296             return vp;
0297         }
0298     }
0299 
0300     /* not found */
0301     return NULL;
0302 }
0303 
0304 /*
0305  * prepare envelopes and LFOs
0306  */
0307 static int
0308 start_voice(struct snd_emux_voice *vp)
0309 {
0310     unsigned int temp;
0311     int ch;
0312     unsigned int addr, mapped_offset;
0313     struct snd_midi_channel *chan;
0314     struct snd_emu10k1 *hw;
0315     struct snd_emu10k1_memblk *emem;
0316     
0317     hw = vp->hw;
0318     ch = vp->ch;
0319     if (snd_BUG_ON(ch < 0))
0320         return -EINVAL;
0321     chan = vp->chan;
0322 
0323     emem = (struct snd_emu10k1_memblk *)vp->block;
0324     if (emem == NULL)
0325         return -EINVAL;
0326     emem->map_locked++;
0327     if (snd_emu10k1_memblk_map(hw, emem) < 0) {
0328         /* dev_err(hw->card->devK, "emu: cannot map!\n"); */
0329         return -ENOMEM;
0330     }
0331     mapped_offset = snd_emu10k1_memblk_offset(emem) >> 1;
0332     vp->reg.start += mapped_offset;
0333     vp->reg.end += mapped_offset;
0334     vp->reg.loopstart += mapped_offset;
0335     vp->reg.loopend += mapped_offset;
0336 
0337     /* set channel routing */
0338     /* A = left(0), B = right(1), C = reverb(c), D = chorus(d) */
0339     if (hw->audigy) {
0340         temp = FXBUS_MIDI_LEFT | (FXBUS_MIDI_RIGHT << 8) | 
0341             (FXBUS_MIDI_REVERB << 16) | (FXBUS_MIDI_CHORUS << 24);
0342         snd_emu10k1_ptr_write(hw, A_FXRT1, ch, temp);
0343     } else {
0344         temp = (FXBUS_MIDI_LEFT << 16) | (FXBUS_MIDI_RIGHT << 20) | 
0345             (FXBUS_MIDI_REVERB << 24) | (FXBUS_MIDI_CHORUS << 28);
0346         snd_emu10k1_ptr_write(hw, FXRT, ch, temp);
0347     }
0348 
0349     /* channel to be silent and idle */
0350     snd_emu10k1_ptr_write(hw, DCYSUSV, ch, 0x0000);
0351     snd_emu10k1_ptr_write(hw, VTFT, ch, 0x0000FFFF);
0352     snd_emu10k1_ptr_write(hw, CVCF, ch, 0x0000FFFF);
0353     snd_emu10k1_ptr_write(hw, PTRX, ch, 0);
0354     snd_emu10k1_ptr_write(hw, CPF, ch, 0);
0355 
0356     /* set pitch offset */
0357     snd_emu10k1_ptr_write(hw, IP, vp->ch, vp->apitch);
0358 
0359     /* set envelope parameters */
0360     snd_emu10k1_ptr_write(hw, ENVVAL, ch, vp->reg.parm.moddelay);
0361     snd_emu10k1_ptr_write(hw, ATKHLDM, ch, vp->reg.parm.modatkhld);
0362     snd_emu10k1_ptr_write(hw, DCYSUSM, ch, vp->reg.parm.moddcysus);
0363     snd_emu10k1_ptr_write(hw, ENVVOL, ch, vp->reg.parm.voldelay);
0364     snd_emu10k1_ptr_write(hw, ATKHLDV, ch, vp->reg.parm.volatkhld);
0365     /* decay/sustain parameter for volume envelope is used
0366        for triggerg the voice */
0367 
0368     /* cutoff and volume */
0369     temp = (unsigned int)vp->acutoff << 8 | (unsigned char)vp->avol;
0370     snd_emu10k1_ptr_write(hw, IFATN, vp->ch, temp);
0371 
0372     /* modulation envelope heights */
0373     snd_emu10k1_ptr_write(hw, PEFE, ch, vp->reg.parm.pefe);
0374 
0375     /* lfo1/2 delay */
0376     snd_emu10k1_ptr_write(hw, LFOVAL1, ch, vp->reg.parm.lfo1delay);
0377     snd_emu10k1_ptr_write(hw, LFOVAL2, ch, vp->reg.parm.lfo2delay);
0378 
0379     /* lfo1 pitch & cutoff shift */
0380     set_fmmod(hw, vp);
0381     /* lfo1 volume & freq */
0382     snd_emu10k1_ptr_write(hw, TREMFRQ, vp->ch, vp->reg.parm.tremfrq);
0383     /* lfo2 pitch & freq */
0384     set_fm2frq2(hw, vp);
0385 
0386     /* reverb and loop start (reverb 8bit, MSB) */
0387     temp = vp->reg.parm.reverb;
0388     temp += (int)vp->chan->control[MIDI_CTL_E1_REVERB_DEPTH] * 9 / 10;
0389     LIMITMAX(temp, 255);
0390     addr = vp->reg.loopstart;
0391     snd_emu10k1_ptr_write(hw, PSST, vp->ch, (temp << 24) | addr);
0392 
0393     /* chorus & loop end (chorus 8bit, MSB) */
0394     addr = vp->reg.loopend;
0395     temp = vp->reg.parm.chorus;
0396     temp += (int)chan->control[MIDI_CTL_E3_CHORUS_DEPTH] * 9 / 10;
0397     LIMITMAX(temp, 255);
0398     temp = (temp <<24) | addr;
0399     snd_emu10k1_ptr_write(hw, DSL, ch, temp);
0400 
0401     /* clear filter delay memory */
0402     snd_emu10k1_ptr_write(hw, Z1, ch, 0);
0403     snd_emu10k1_ptr_write(hw, Z2, ch, 0);
0404 
0405     /* invalidate maps */
0406     temp = (hw->silent_page.addr << hw->address_mode) | (hw->address_mode ? MAP_PTI_MASK1 : MAP_PTI_MASK0);
0407     snd_emu10k1_ptr_write(hw, MAPA, ch, temp);
0408     snd_emu10k1_ptr_write(hw, MAPB, ch, temp);
0409 #if 0
0410     /* cache */
0411     {
0412         unsigned int val, sample;
0413         val = 32;
0414         if (vp->reg.sample_mode & SNDRV_SFNT_SAMPLE_8BITS)
0415             sample = 0x80808080;
0416         else {
0417             sample = 0;
0418             val *= 2;
0419         }
0420 
0421         /* cache */
0422         snd_emu10k1_ptr_write(hw, CCR, ch, 0x1c << 16);
0423         snd_emu10k1_ptr_write(hw, CDE, ch, sample);
0424         snd_emu10k1_ptr_write(hw, CDF, ch, sample);
0425 
0426         /* invalidate maps */
0427         temp = ((unsigned int)hw->silent_page.addr << hw_address_mode) | (hw->address_mode ? MAP_PTI_MASK1 : MAP_PTI_MASK0);
0428         snd_emu10k1_ptr_write(hw, MAPA, ch, temp);
0429         snd_emu10k1_ptr_write(hw, MAPB, ch, temp);
0430         
0431         /* fill cache */
0432         val -= 4;
0433         val <<= 25;
0434         val |= 0x1c << 16;
0435         snd_emu10k1_ptr_write(hw, CCR, ch, val);
0436     }
0437 #endif
0438 
0439     /* Q & current address (Q 4bit value, MSB) */
0440     addr = vp->reg.start;
0441     temp = vp->reg.parm.filterQ;
0442     temp = (temp<<28) | addr;
0443     if (vp->apitch < 0xe400)
0444         temp |= CCCA_INTERPROM_0;
0445     else {
0446         unsigned int shift = (vp->apitch - 0xe000) >> 10;
0447         temp |= shift << 25;
0448     }
0449     if (vp->reg.sample_mode & SNDRV_SFNT_SAMPLE_8BITS)
0450         temp |= CCCA_8BITSELECT;
0451     snd_emu10k1_ptr_write(hw, CCCA, ch, temp);
0452 
0453     /* reset volume */
0454     temp = (unsigned int)vp->vtarget << 16;
0455     snd_emu10k1_ptr_write(hw, VTFT, ch, temp | vp->ftarget);
0456     snd_emu10k1_ptr_write(hw, CVCF, ch, temp | 0xff00);
0457     return 0;
0458 }
0459 
0460 /*
0461  * Start envelope
0462  */
0463 static void
0464 trigger_voice(struct snd_emux_voice *vp)
0465 {
0466     unsigned int temp, ptarget;
0467     struct snd_emu10k1 *hw;
0468     struct snd_emu10k1_memblk *emem;
0469     
0470     hw = vp->hw;
0471 
0472     emem = (struct snd_emu10k1_memblk *)vp->block;
0473     if (! emem || emem->mapped_page < 0)
0474         return; /* not mapped */
0475 
0476 #if 0
0477     ptarget = (unsigned int)vp->ptarget << 16;
0478 #else
0479     ptarget = IP_TO_CP(vp->apitch);
0480 #endif
0481     /* set pitch target and pan (volume) */
0482     temp = ptarget | (vp->apan << 8) | vp->aaux;
0483     snd_emu10k1_ptr_write(hw, PTRX, vp->ch, temp);
0484 
0485     /* pitch target */
0486     snd_emu10k1_ptr_write(hw, CPF, vp->ch, ptarget);
0487 
0488     /* trigger voice */
0489     snd_emu10k1_ptr_write(hw, DCYSUSV, vp->ch, vp->reg.parm.voldcysus|DCYSUSV_CHANNELENABLE_MASK);
0490 }
0491 
0492 #define MOD_SENSE 18
0493 
0494 /* set lfo1 modulation height and cutoff */
0495 static void
0496 set_fmmod(struct snd_emu10k1 *hw, struct snd_emux_voice *vp)
0497 {
0498     unsigned short fmmod;
0499     short pitch;
0500     unsigned char cutoff;
0501     int modulation;
0502 
0503     pitch = (char)(vp->reg.parm.fmmod>>8);
0504     cutoff = (vp->reg.parm.fmmod & 0xff);
0505     modulation = vp->chan->gm_modulation + vp->chan->midi_pressure;
0506     pitch += (MOD_SENSE * modulation) / 1200;
0507     LIMITVALUE(pitch, -128, 127);
0508     fmmod = ((unsigned char)pitch<<8) | cutoff;
0509     snd_emu10k1_ptr_write(hw, FMMOD, vp->ch, fmmod);
0510 }
0511 
0512 /* set lfo2 pitch & frequency */
0513 static void
0514 set_fm2frq2(struct snd_emu10k1 *hw, struct snd_emux_voice *vp)
0515 {
0516     unsigned short fm2frq2;
0517     short pitch;
0518     unsigned char freq;
0519     int modulation;
0520 
0521     pitch = (char)(vp->reg.parm.fm2frq2>>8);
0522     freq = vp->reg.parm.fm2frq2 & 0xff;
0523     modulation = vp->chan->gm_modulation + vp->chan->midi_pressure;
0524     pitch += (MOD_SENSE * modulation) / 1200;
0525     LIMITVALUE(pitch, -128, 127);
0526     fm2frq2 = ((unsigned char)pitch<<8) | freq;
0527     snd_emu10k1_ptr_write(hw, FM2FRQ2, vp->ch, fm2frq2);
0528 }
0529 
0530 /* set filterQ */
0531 static void
0532 set_filterQ(struct snd_emu10k1 *hw, struct snd_emux_voice *vp)
0533 {
0534     unsigned int val;
0535     val = snd_emu10k1_ptr_read(hw, CCCA, vp->ch) & ~CCCA_RESONANCE;
0536     val |= (vp->reg.parm.filterQ << 28);
0537     snd_emu10k1_ptr_write(hw, CCCA, vp->ch, val);
0538 }