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