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