0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/export.h>
0009 #include "emu10k1_synth_local.h"
0010 #include <sound/asoundef.h>
0011
0012
0013 enum {
0014 V_FREE=0, V_OFF, V_RELEASED, V_PLAYING, V_END
0015 };
0016
0017
0018 struct best_voice {
0019 unsigned int time;
0020 int voice;
0021 };
0022
0023
0024
0025
0026 static void lookup_voices(struct snd_emux *emux, struct snd_emu10k1 *hw,
0027 struct best_voice *best, int active_only);
0028 static struct snd_emux_voice *get_voice(struct snd_emux *emux,
0029 struct snd_emux_port *port);
0030 static int start_voice(struct snd_emux_voice *vp);
0031 static void trigger_voice(struct snd_emux_voice *vp);
0032 static void release_voice(struct snd_emux_voice *vp);
0033 static void update_voice(struct snd_emux_voice *vp, int update);
0034 static void terminate_voice(struct snd_emux_voice *vp);
0035 static void free_voice(struct snd_emux_voice *vp);
0036 static void set_fmmod(struct snd_emu10k1 *hw, struct snd_emux_voice *vp);
0037 static void set_fm2frq2(struct snd_emu10k1 *hw, struct snd_emux_voice *vp);
0038 static void set_filterQ(struct snd_emu10k1 *hw, struct snd_emux_voice *vp);
0039
0040
0041
0042
0043
0044 #define LIMITVALUE(x, a, b) do { if ((x) < (a)) (x) = (a); else if ((x) > (b)) (x) = (b); } while (0)
0045 #define LIMITMAX(x, a) do {if ((x) > (a)) (x) = (a); } while (0)
0046
0047
0048
0049
0050
0051 static const struct snd_emux_operators emu10k1_ops = {
0052 .owner = THIS_MODULE,
0053 .get_voice = get_voice,
0054 .prepare = start_voice,
0055 .trigger = trigger_voice,
0056 .release = release_voice,
0057 .update = update_voice,
0058 .terminate = terminate_voice,
0059 .free_voice = free_voice,
0060 .sample_new = snd_emu10k1_sample_new,
0061 .sample_free = snd_emu10k1_sample_free,
0062 };
0063
0064 void
0065 snd_emu10k1_ops_setup(struct snd_emux *emux)
0066 {
0067 emux->ops = emu10k1_ops;
0068 }
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078 int
0079 snd_emu10k1_synth_get_voice(struct snd_emu10k1 *hw)
0080 {
0081 struct snd_emux *emu;
0082 struct snd_emux_voice *vp;
0083 struct best_voice best[V_END];
0084 int i;
0085
0086 emu = hw->synth;
0087
0088 lookup_voices(emu, hw, best, 1);
0089 for (i = 0; i < V_END; i++) {
0090 if (best[i].voice >= 0) {
0091 int ch;
0092 vp = &emu->voices[best[i].voice];
0093 ch = vp->ch;
0094 if (ch < 0) {
0095
0096
0097
0098
0099 continue;
0100 }
0101 vp->emu->num_voices--;
0102 vp->ch = -1;
0103 vp->state = SNDRV_EMUX_ST_OFF;
0104 return ch;
0105 }
0106 }
0107
0108
0109 return -ENOMEM;
0110 }
0111
0112
0113
0114
0115
0116 static void
0117 release_voice(struct snd_emux_voice *vp)
0118 {
0119 int dcysusv;
0120 struct snd_emu10k1 *hw;
0121
0122 hw = vp->hw;
0123 dcysusv = 0x8000 | (unsigned char)vp->reg.parm.modrelease;
0124 snd_emu10k1_ptr_write(hw, DCYSUSM, vp->ch, dcysusv);
0125 dcysusv = 0x8000 | (unsigned char)vp->reg.parm.volrelease | DCYSUSV_CHANNELENABLE_MASK;
0126 snd_emu10k1_ptr_write(hw, DCYSUSV, vp->ch, dcysusv);
0127 }
0128
0129
0130
0131
0132
0133 static void
0134 terminate_voice(struct snd_emux_voice *vp)
0135 {
0136 struct snd_emu10k1 *hw;
0137
0138 if (snd_BUG_ON(!vp))
0139 return;
0140 hw = vp->hw;
0141 snd_emu10k1_ptr_write(hw, DCYSUSV, vp->ch, 0x807f | DCYSUSV_CHANNELENABLE_MASK);
0142 if (vp->block) {
0143 struct snd_emu10k1_memblk *emem;
0144 emem = (struct snd_emu10k1_memblk *)vp->block;
0145 if (emem->map_locked > 0)
0146 emem->map_locked--;
0147 }
0148 }
0149
0150
0151
0152
0153 static void
0154 free_voice(struct snd_emux_voice *vp)
0155 {
0156 struct snd_emu10k1 *hw;
0157
0158 hw = vp->hw;
0159
0160
0161
0162
0163 if (hw && (vp->ch >= 0)) {
0164 snd_emu10k1_ptr_write(hw, IFATN, vp->ch, 0xff00);
0165 snd_emu10k1_ptr_write(hw, DCYSUSV, vp->ch, 0x807f | DCYSUSV_CHANNELENABLE_MASK);
0166
0167 snd_emu10k1_ptr_write(hw, VTFT, vp->ch, 0xffff);
0168 snd_emu10k1_ptr_write(hw, CVCF, vp->ch, 0xffff);
0169 snd_emu10k1_voice_free(hw, &hw->voices[vp->ch]);
0170 vp->emu->num_voices--;
0171 vp->ch = -1;
0172 }
0173 }
0174
0175
0176
0177
0178
0179 static void
0180 update_voice(struct snd_emux_voice *vp, int update)
0181 {
0182 struct snd_emu10k1 *hw;
0183
0184 hw = vp->hw;
0185 if (update & SNDRV_EMUX_UPDATE_VOLUME)
0186 snd_emu10k1_ptr_write(hw, IFATN_ATTENUATION, vp->ch, vp->avol);
0187 if (update & SNDRV_EMUX_UPDATE_PITCH)
0188 snd_emu10k1_ptr_write(hw, IP, vp->ch, vp->apitch);
0189 if (update & SNDRV_EMUX_UPDATE_PAN) {
0190 snd_emu10k1_ptr_write(hw, PTRX_FXSENDAMOUNT_A, vp->ch, vp->apan);
0191 snd_emu10k1_ptr_write(hw, PTRX_FXSENDAMOUNT_B, vp->ch, vp->aaux);
0192 }
0193 if (update & SNDRV_EMUX_UPDATE_FMMOD)
0194 set_fmmod(hw, vp);
0195 if (update & SNDRV_EMUX_UPDATE_TREMFREQ)
0196 snd_emu10k1_ptr_write(hw, TREMFRQ, vp->ch, vp->reg.parm.tremfrq);
0197 if (update & SNDRV_EMUX_UPDATE_FM2FRQ2)
0198 set_fm2frq2(hw, vp);
0199 if (update & SNDRV_EMUX_UPDATE_Q)
0200 set_filterQ(hw, vp);
0201 }
0202
0203
0204
0205
0206
0207
0208 static void
0209 lookup_voices(struct snd_emux *emu, struct snd_emu10k1 *hw,
0210 struct best_voice *best, int active_only)
0211 {
0212 struct snd_emux_voice *vp;
0213 struct best_voice *bp;
0214 int i;
0215
0216 for (i = 0; i < V_END; i++) {
0217 best[i].time = (unsigned int)-1;
0218 best[i].voice = -1;
0219 }
0220
0221
0222
0223
0224
0225 for (i = 0; i < emu->max_voices; i++) {
0226 int state, val;
0227
0228 vp = &emu->voices[i];
0229 state = vp->state;
0230 if (state == SNDRV_EMUX_ST_OFF) {
0231 if (vp->ch < 0) {
0232 if (active_only)
0233 continue;
0234 bp = best + V_FREE;
0235 } else
0236 bp = best + V_OFF;
0237 }
0238 else if (state == SNDRV_EMUX_ST_RELEASED ||
0239 state == SNDRV_EMUX_ST_PENDING) {
0240 bp = best + V_RELEASED;
0241 #if 1
0242 val = snd_emu10k1_ptr_read(hw, CVCF_CURRENTVOL, vp->ch);
0243 if (! val)
0244 bp = best + V_OFF;
0245 #endif
0246 }
0247 else if (state == SNDRV_EMUX_ST_STANDBY)
0248 continue;
0249 else if (state & SNDRV_EMUX_ST_ON)
0250 bp = best + V_PLAYING;
0251 else
0252 continue;
0253
0254
0255 if (bp != best + V_OFF && bp != best + V_FREE &&
0256 (vp->reg.sample_mode & SNDRV_SFNT_SAMPLE_SINGLESHOT)) {
0257 val = snd_emu10k1_ptr_read(hw, CCCA_CURRADDR, vp->ch);
0258 if (val >= vp->reg.loopstart)
0259 bp = best + V_OFF;
0260 }
0261
0262 if (vp->time < bp->time) {
0263 bp->time = vp->time;
0264 bp->voice = i;
0265 }
0266 }
0267 }
0268
0269
0270
0271
0272
0273
0274 static struct snd_emux_voice *
0275 get_voice(struct snd_emux *emu, struct snd_emux_port *port)
0276 {
0277 struct snd_emu10k1 *hw;
0278 struct snd_emux_voice *vp;
0279 struct best_voice best[V_END];
0280 int i;
0281
0282 hw = emu->hw;
0283
0284 lookup_voices(emu, hw, best, 0);
0285 for (i = 0; i < V_END; i++) {
0286 if (best[i].voice >= 0) {
0287 vp = &emu->voices[best[i].voice];
0288 if (vp->ch < 0) {
0289
0290 struct snd_emu10k1_voice *hwvoice;
0291 if (snd_emu10k1_voice_alloc(hw, EMU10K1_SYNTH, 1, &hwvoice) < 0 || hwvoice == NULL)
0292 continue;
0293 vp->ch = hwvoice->number;
0294 emu->num_voices++;
0295 }
0296 return vp;
0297 }
0298 }
0299
0300
0301 return NULL;
0302 }
0303
0304
0305
0306
0307 static int
0308 start_voice(struct snd_emux_voice *vp)
0309 {
0310 unsigned int temp;
0311 int ch;
0312 unsigned int addr, mapped_offset;
0313 struct snd_midi_channel *chan;
0314 struct snd_emu10k1 *hw;
0315 struct snd_emu10k1_memblk *emem;
0316
0317 hw = vp->hw;
0318 ch = vp->ch;
0319 if (snd_BUG_ON(ch < 0))
0320 return -EINVAL;
0321 chan = vp->chan;
0322
0323 emem = (struct snd_emu10k1_memblk *)vp->block;
0324 if (emem == NULL)
0325 return -EINVAL;
0326 emem->map_locked++;
0327 if (snd_emu10k1_memblk_map(hw, emem) < 0) {
0328
0329 return -ENOMEM;
0330 }
0331 mapped_offset = snd_emu10k1_memblk_offset(emem) >> 1;
0332 vp->reg.start += mapped_offset;
0333 vp->reg.end += mapped_offset;
0334 vp->reg.loopstart += mapped_offset;
0335 vp->reg.loopend += mapped_offset;
0336
0337
0338
0339 if (hw->audigy) {
0340 temp = FXBUS_MIDI_LEFT | (FXBUS_MIDI_RIGHT << 8) |
0341 (FXBUS_MIDI_REVERB << 16) | (FXBUS_MIDI_CHORUS << 24);
0342 snd_emu10k1_ptr_write(hw, A_FXRT1, ch, temp);
0343 } else {
0344 temp = (FXBUS_MIDI_LEFT << 16) | (FXBUS_MIDI_RIGHT << 20) |
0345 (FXBUS_MIDI_REVERB << 24) | (FXBUS_MIDI_CHORUS << 28);
0346 snd_emu10k1_ptr_write(hw, FXRT, ch, temp);
0347 }
0348
0349
0350 snd_emu10k1_ptr_write(hw, DCYSUSV, ch, 0x0000);
0351 snd_emu10k1_ptr_write(hw, VTFT, ch, 0x0000FFFF);
0352 snd_emu10k1_ptr_write(hw, CVCF, ch, 0x0000FFFF);
0353 snd_emu10k1_ptr_write(hw, PTRX, ch, 0);
0354 snd_emu10k1_ptr_write(hw, CPF, ch, 0);
0355
0356
0357 snd_emu10k1_ptr_write(hw, IP, vp->ch, vp->apitch);
0358
0359
0360 snd_emu10k1_ptr_write(hw, ENVVAL, ch, vp->reg.parm.moddelay);
0361 snd_emu10k1_ptr_write(hw, ATKHLDM, ch, vp->reg.parm.modatkhld);
0362 snd_emu10k1_ptr_write(hw, DCYSUSM, ch, vp->reg.parm.moddcysus);
0363 snd_emu10k1_ptr_write(hw, ENVVOL, ch, vp->reg.parm.voldelay);
0364 snd_emu10k1_ptr_write(hw, ATKHLDV, ch, vp->reg.parm.volatkhld);
0365
0366
0367
0368
0369 temp = (unsigned int)vp->acutoff << 8 | (unsigned char)vp->avol;
0370 snd_emu10k1_ptr_write(hw, IFATN, vp->ch, temp);
0371
0372
0373 snd_emu10k1_ptr_write(hw, PEFE, ch, vp->reg.parm.pefe);
0374
0375
0376 snd_emu10k1_ptr_write(hw, LFOVAL1, ch, vp->reg.parm.lfo1delay);
0377 snd_emu10k1_ptr_write(hw, LFOVAL2, ch, vp->reg.parm.lfo2delay);
0378
0379
0380 set_fmmod(hw, vp);
0381
0382 snd_emu10k1_ptr_write(hw, TREMFRQ, vp->ch, vp->reg.parm.tremfrq);
0383
0384 set_fm2frq2(hw, vp);
0385
0386
0387 temp = vp->reg.parm.reverb;
0388 temp += (int)vp->chan->control[MIDI_CTL_E1_REVERB_DEPTH] * 9 / 10;
0389 LIMITMAX(temp, 255);
0390 addr = vp->reg.loopstart;
0391 snd_emu10k1_ptr_write(hw, PSST, vp->ch, (temp << 24) | addr);
0392
0393
0394 addr = vp->reg.loopend;
0395 temp = vp->reg.parm.chorus;
0396 temp += (int)chan->control[MIDI_CTL_E3_CHORUS_DEPTH] * 9 / 10;
0397 LIMITMAX(temp, 255);
0398 temp = (temp <<24) | addr;
0399 snd_emu10k1_ptr_write(hw, DSL, ch, temp);
0400
0401
0402 snd_emu10k1_ptr_write(hw, Z1, ch, 0);
0403 snd_emu10k1_ptr_write(hw, Z2, ch, 0);
0404
0405
0406 temp = (hw->silent_page.addr << hw->address_mode) | (hw->address_mode ? MAP_PTI_MASK1 : MAP_PTI_MASK0);
0407 snd_emu10k1_ptr_write(hw, MAPA, ch, temp);
0408 snd_emu10k1_ptr_write(hw, MAPB, ch, temp);
0409 #if 0
0410
0411 {
0412 unsigned int val, sample;
0413 val = 32;
0414 if (vp->reg.sample_mode & SNDRV_SFNT_SAMPLE_8BITS)
0415 sample = 0x80808080;
0416 else {
0417 sample = 0;
0418 val *= 2;
0419 }
0420
0421
0422 snd_emu10k1_ptr_write(hw, CCR, ch, 0x1c << 16);
0423 snd_emu10k1_ptr_write(hw, CDE, ch, sample);
0424 snd_emu10k1_ptr_write(hw, CDF, ch, sample);
0425
0426
0427 temp = ((unsigned int)hw->silent_page.addr << hw_address_mode) | (hw->address_mode ? MAP_PTI_MASK1 : MAP_PTI_MASK0);
0428 snd_emu10k1_ptr_write(hw, MAPA, ch, temp);
0429 snd_emu10k1_ptr_write(hw, MAPB, ch, temp);
0430
0431
0432 val -= 4;
0433 val <<= 25;
0434 val |= 0x1c << 16;
0435 snd_emu10k1_ptr_write(hw, CCR, ch, val);
0436 }
0437 #endif
0438
0439
0440 addr = vp->reg.start;
0441 temp = vp->reg.parm.filterQ;
0442 temp = (temp<<28) | addr;
0443 if (vp->apitch < 0xe400)
0444 temp |= CCCA_INTERPROM_0;
0445 else {
0446 unsigned int shift = (vp->apitch - 0xe000) >> 10;
0447 temp |= shift << 25;
0448 }
0449 if (vp->reg.sample_mode & SNDRV_SFNT_SAMPLE_8BITS)
0450 temp |= CCCA_8BITSELECT;
0451 snd_emu10k1_ptr_write(hw, CCCA, ch, temp);
0452
0453
0454 temp = (unsigned int)vp->vtarget << 16;
0455 snd_emu10k1_ptr_write(hw, VTFT, ch, temp | vp->ftarget);
0456 snd_emu10k1_ptr_write(hw, CVCF, ch, temp | 0xff00);
0457 return 0;
0458 }
0459
0460
0461
0462
0463 static void
0464 trigger_voice(struct snd_emux_voice *vp)
0465 {
0466 unsigned int temp, ptarget;
0467 struct snd_emu10k1 *hw;
0468 struct snd_emu10k1_memblk *emem;
0469
0470 hw = vp->hw;
0471
0472 emem = (struct snd_emu10k1_memblk *)vp->block;
0473 if (! emem || emem->mapped_page < 0)
0474 return;
0475
0476 #if 0
0477 ptarget = (unsigned int)vp->ptarget << 16;
0478 #else
0479 ptarget = IP_TO_CP(vp->apitch);
0480 #endif
0481
0482 temp = ptarget | (vp->apan << 8) | vp->aaux;
0483 snd_emu10k1_ptr_write(hw, PTRX, vp->ch, temp);
0484
0485
0486 snd_emu10k1_ptr_write(hw, CPF, vp->ch, ptarget);
0487
0488
0489 snd_emu10k1_ptr_write(hw, DCYSUSV, vp->ch, vp->reg.parm.voldcysus|DCYSUSV_CHANNELENABLE_MASK);
0490 }
0491
0492 #define MOD_SENSE 18
0493
0494
0495 static void
0496 set_fmmod(struct snd_emu10k1 *hw, struct snd_emux_voice *vp)
0497 {
0498 unsigned short fmmod;
0499 short pitch;
0500 unsigned char cutoff;
0501 int modulation;
0502
0503 pitch = (char)(vp->reg.parm.fmmod>>8);
0504 cutoff = (vp->reg.parm.fmmod & 0xff);
0505 modulation = vp->chan->gm_modulation + vp->chan->midi_pressure;
0506 pitch += (MOD_SENSE * modulation) / 1200;
0507 LIMITVALUE(pitch, -128, 127);
0508 fmmod = ((unsigned char)pitch<<8) | cutoff;
0509 snd_emu10k1_ptr_write(hw, FMMOD, vp->ch, fmmod);
0510 }
0511
0512
0513 static void
0514 set_fm2frq2(struct snd_emu10k1 *hw, struct snd_emux_voice *vp)
0515 {
0516 unsigned short fm2frq2;
0517 short pitch;
0518 unsigned char freq;
0519 int modulation;
0520
0521 pitch = (char)(vp->reg.parm.fm2frq2>>8);
0522 freq = vp->reg.parm.fm2frq2 & 0xff;
0523 modulation = vp->chan->gm_modulation + vp->chan->midi_pressure;
0524 pitch += (MOD_SENSE * modulation) / 1200;
0525 LIMITVALUE(pitch, -128, 127);
0526 fm2frq2 = ((unsigned char)pitch<<8) | freq;
0527 snd_emu10k1_ptr_write(hw, FM2FRQ2, vp->ch, fm2frq2);
0528 }
0529
0530
0531 static void
0532 set_filterQ(struct snd_emu10k1 *hw, struct snd_emux_voice *vp)
0533 {
0534 unsigned int val;
0535 val = snd_emu10k1_ptr_read(hw, CCCA, vp->ch) & ~CCCA_RESONANCE;
0536 val |= (vp->reg.parm.filterQ << 28);
0537 snd_emu10k1_ptr_write(hw, CCCA, vp->ch, val);
0538 }