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