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