root/sound/pci/emu10k1/emu10k1_callback.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. snd_emu10k1_ops_setup
  2. snd_emu10k1_synth_get_voice
  3. release_voice
  4. terminate_voice
  5. free_voice
  6. update_voice
  7. lookup_voices
  8. get_voice
  9. start_voice
  10. trigger_voice
  11. set_fmmod
  12. set_fm2frq2
  13. set_filterQ

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

/* [<][>][^][v][top][bottom][index][help] */