emu10k1_callback.c (13965B)
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}