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                        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 */
 115static void
 116release_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 */
 132static void
 133terminate_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 */
 152static void
 153free_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 */
 178static void
 179update_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! */
 207static void
 208lookup_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 */
 273static struct snd_emux_voice *
 274get_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 */
 306static int
 307start_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 */
 462static void
 463trigger_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 */
 494static void
 495set_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 */
 512static void
 513set_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 */
 530static void
 531set_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}
 538