cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

opl3_midi.c (21930B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 *  Copyright (c) by Uros Bizjak <uros@kss-loka.si>
      4 *
      5 *  Midi synth routines for OPL2/OPL3/OPL4 FM
      6 */
      7
      8#undef DEBUG_ALLOC
      9#undef DEBUG_MIDI
     10
     11#include "opl3_voice.h"
     12#include <sound/asoundef.h>
     13
     14static void snd_opl3_note_off_unsafe(void *p, int note, int vel,
     15				     struct snd_midi_channel *chan);
     16/*
     17 * The next table looks magical, but it certainly is not. Its values have
     18 * been calculated as table[i]=8*log(i/64)/log(2) with an obvious exception
     19 * for i=0. This log-table converts a linear volume-scaling (0..127) to a
     20 * logarithmic scaling as present in the FM-synthesizer chips. so :    Volume
     21 * 64 =  0 db = relative volume  0 and:    Volume 32 = -6 db = relative
     22 * volume -8 it was implemented as a table because it is only 128 bytes and
     23 * it saves a lot of log() calculations. (Rob Hooft <hooft@chem.ruu.nl>)
     24 */
     25
     26static const char opl3_volume_table[128] =
     27{
     28	-63, -48, -40, -35, -32, -29, -27, -26,
     29	-24, -23, -21, -20, -19, -18, -18, -17,
     30	-16, -15, -15, -14, -13, -13, -12, -12,
     31	-11, -11, -10, -10, -10, -9, -9, -8,
     32	-8, -8, -7, -7, -7, -6, -6, -6,
     33	-5, -5, -5, -5, -4, -4, -4, -4,
     34	-3, -3, -3, -3, -2, -2, -2, -2,
     35	-2, -1, -1, -1, -1, 0, 0, 0,
     36	0, 0, 0, 1, 1, 1, 1, 1,
     37	1, 2, 2, 2, 2, 2, 2, 2,
     38	3, 3, 3, 3, 3, 3, 3, 4,
     39	4, 4, 4, 4, 4, 4, 4, 5,
     40	5, 5, 5, 5, 5, 5, 5, 5,
     41	6, 6, 6, 6, 6, 6, 6, 6,
     42	6, 7, 7, 7, 7, 7, 7, 7,
     43	7, 7, 7, 8, 8, 8, 8, 8
     44};
     45
     46void snd_opl3_calc_volume(unsigned char *volbyte, int vel,
     47			  struct snd_midi_channel *chan)
     48{
     49	int oldvol, newvol, n;
     50	int volume;
     51
     52	volume = (vel * chan->gm_volume * chan->gm_expression) / (127*127);
     53	if (volume > 127)
     54		volume = 127;
     55
     56	oldvol = OPL3_TOTAL_LEVEL_MASK - (*volbyte & OPL3_TOTAL_LEVEL_MASK);
     57
     58	newvol = opl3_volume_table[volume] + oldvol;
     59	if (newvol > OPL3_TOTAL_LEVEL_MASK)
     60		newvol = OPL3_TOTAL_LEVEL_MASK;
     61	else if (newvol < 0)
     62		newvol = 0;
     63
     64	n = OPL3_TOTAL_LEVEL_MASK - (newvol & OPL3_TOTAL_LEVEL_MASK);
     65
     66	*volbyte = (*volbyte & OPL3_KSL_MASK) | (n & OPL3_TOTAL_LEVEL_MASK);
     67}
     68
     69/*
     70 * Converts the note frequency to block and fnum values for the FM chip
     71 */
     72static const short opl3_note_table[16] =
     73{
     74	305, 323,	/* for pitch bending, -2 semitones */
     75	343, 363, 385, 408, 432, 458, 485, 514, 544, 577, 611, 647,
     76	686, 726	/* for pitch bending, +2 semitones */
     77};
     78
     79static void snd_opl3_calc_pitch(unsigned char *fnum, unsigned char *blocknum,
     80				int note, struct snd_midi_channel *chan)
     81{
     82	int block = ((note / 12) & 0x07) - 1;
     83	int idx = (note % 12) + 2;
     84	int freq;
     85
     86	if (chan->midi_pitchbend) {
     87		int pitchbend = chan->midi_pitchbend;
     88		int segment;
     89
     90		if (pitchbend < -0x2000)
     91			pitchbend = -0x2000;
     92		if (pitchbend > 0x1FFF)
     93			pitchbend = 0x1FFF;
     94
     95		segment = pitchbend / 0x1000;
     96		freq = opl3_note_table[idx+segment];
     97		freq += ((opl3_note_table[idx+segment+1] - freq) *
     98			 (pitchbend % 0x1000)) / 0x1000;
     99	} else {
    100		freq = opl3_note_table[idx];
    101	}
    102
    103	*fnum = (unsigned char) freq;
    104	*blocknum = ((freq >> 8) & OPL3_FNUM_HIGH_MASK) |
    105		((block << 2) & OPL3_BLOCKNUM_MASK);
    106}
    107
    108
    109#ifdef DEBUG_ALLOC
    110static void debug_alloc(struct snd_opl3 *opl3, char *s, int voice) {
    111	int i;
    112	char *str = "x.24";
    113
    114	printk(KERN_DEBUG "time %.5i: %s [%.2i]: ", opl3->use_time, s, voice);
    115	for (i = 0; i < opl3->max_voices; i++)
    116		printk(KERN_CONT "%c", *(str + opl3->voices[i].state + 1));
    117	printk(KERN_CONT "\n");
    118}
    119#endif
    120
    121/*
    122 * Get a FM voice (channel) to play a note on.
    123 */
    124static int opl3_get_voice(struct snd_opl3 *opl3, int instr_4op,
    125			  struct snd_midi_channel *chan) {
    126	int chan_4op_1;		/* first voice for 4op instrument */
    127	int chan_4op_2;		/* second voice for 4op instrument */
    128
    129	struct snd_opl3_voice *vp, *vp2;
    130	unsigned int voice_time;
    131	int i;
    132
    133#ifdef DEBUG_ALLOC
    134	char *alloc_type[3] = { "FREE     ", "CHEAP    ", "EXPENSIVE" };
    135#endif
    136
    137	/* This is our "allocation cost" table */
    138	enum {
    139		FREE = 0, CHEAP, EXPENSIVE, END
    140	};
    141
    142	/* Keeps track of what we are finding */
    143	struct best {
    144		unsigned int time;
    145		int voice;
    146	} best[END];
    147	struct best *bp;
    148
    149	for (i = 0; i < END; i++) {
    150		best[i].time = (unsigned int)(-1); /* XXX MAX_?INT really */
    151		best[i].voice = -1;
    152	}
    153
    154	/* Look through all the channels for the most suitable. */
    155	for (i = 0; i < opl3->max_voices; i++) {
    156		vp = &opl3->voices[i];
    157
    158		if (vp->state == SNDRV_OPL3_ST_NOT_AVAIL)
    159		  /* skip unavailable channels, allocated by
    160		     drum voices or by bounded 4op voices) */
    161			continue;
    162
    163		voice_time = vp->time;
    164		bp = best;
    165
    166		chan_4op_1 = ((i < 3) || (i > 8 && i < 12));
    167		chan_4op_2 = ((i > 2 && i < 6) || (i > 11 && i < 15));
    168		if (instr_4op) {
    169			/* allocate 4op voice */
    170			/* skip channels unavailable to 4op instrument */
    171			if (!chan_4op_1)
    172				continue;
    173
    174			if (vp->state)
    175				/* kill one voice, CHEAP */
    176				bp++;
    177			/* get state of bounded 2op channel
    178			   to be allocated for 4op instrument */
    179			vp2 = &opl3->voices[i + 3];
    180			if (vp2->state == SNDRV_OPL3_ST_ON_2OP) {
    181				/* kill two voices, EXPENSIVE */
    182				bp++;
    183				voice_time = max(voice_time, vp2->time);
    184			}
    185		} else {
    186			/* allocate 2op voice */
    187			if ((chan_4op_1) || (chan_4op_2))
    188				/* use bounded channels for 2op, CHEAP */
    189				bp++;
    190			else if (vp->state)
    191				/* kill one voice on 2op channel, CHEAP */
    192				bp++;
    193			/* raise kill cost to EXPENSIVE for all channels */
    194			if (vp->state)
    195				bp++;
    196		}
    197		if (voice_time < bp->time) {
    198			bp->time = voice_time;
    199			bp->voice = i;
    200		}
    201	}
    202
    203	for (i = 0; i < END; i++) {
    204		if (best[i].voice >= 0) {
    205#ifdef DEBUG_ALLOC
    206			printk(KERN_DEBUG "%s %iop allocation on voice %i\n",
    207			       alloc_type[i], instr_4op ? 4 : 2,
    208			       best[i].voice);
    209#endif
    210			return best[i].voice;
    211		}
    212	}
    213	/* not found */
    214	return -1;
    215}
    216
    217/* ------------------------------ */
    218
    219/*
    220 * System timer interrupt function
    221 */
    222void snd_opl3_timer_func(struct timer_list *t)
    223{
    224
    225	struct snd_opl3 *opl3 = from_timer(opl3, t, tlist);
    226	unsigned long flags;
    227	int again = 0;
    228	int i;
    229
    230	spin_lock_irqsave(&opl3->voice_lock, flags);
    231	for (i = 0; i < opl3->max_voices; i++) {
    232		struct snd_opl3_voice *vp = &opl3->voices[i];
    233		if (vp->state > 0 && vp->note_off_check) {
    234			if (vp->note_off == jiffies)
    235				snd_opl3_note_off_unsafe(opl3, vp->note, 0,
    236							 vp->chan);
    237			else
    238				again++;
    239		}
    240	}
    241	spin_unlock_irqrestore(&opl3->voice_lock, flags);
    242
    243	spin_lock_irqsave(&opl3->sys_timer_lock, flags);
    244	if (again)
    245		mod_timer(&opl3->tlist, jiffies + 1);	/* invoke again */
    246	else
    247		opl3->sys_timer_status = 0;
    248	spin_unlock_irqrestore(&opl3->sys_timer_lock, flags);
    249}
    250
    251/*
    252 * Start system timer
    253 */
    254static void snd_opl3_start_timer(struct snd_opl3 *opl3)
    255{
    256	unsigned long flags;
    257	spin_lock_irqsave(&opl3->sys_timer_lock, flags);
    258	if (! opl3->sys_timer_status) {
    259		mod_timer(&opl3->tlist, jiffies + 1);
    260		opl3->sys_timer_status = 1;
    261	}
    262	spin_unlock_irqrestore(&opl3->sys_timer_lock, flags);
    263}
    264
    265/* ------------------------------ */
    266
    267
    268static const int snd_opl3_oss_map[MAX_OPL3_VOICES] = {
    269	0, 1, 2, 9, 10, 11, 6, 7, 8, 15, 16, 17, 3, 4 ,5, 12, 13, 14
    270};
    271
    272/*
    273 * Start a note.
    274 */
    275void snd_opl3_note_on(void *p, int note, int vel, struct snd_midi_channel *chan)
    276{
    277	struct snd_opl3 *opl3;
    278	int instr_4op;
    279
    280	int voice;
    281	struct snd_opl3_voice *vp, *vp2;
    282	unsigned short connect_mask;
    283	unsigned char connection;
    284	unsigned char vol_op[4];
    285
    286	int extra_prg = 0;
    287
    288	unsigned short reg_side;
    289	unsigned char op_offset;
    290	unsigned char voice_offset;
    291	unsigned short opl3_reg;
    292	unsigned char reg_val;
    293	unsigned char prg, bank;
    294
    295	int key = note;
    296	unsigned char fnum, blocknum;
    297	int i;
    298
    299	struct fm_patch *patch;
    300	struct fm_instrument *fm;
    301	unsigned long flags;
    302
    303	opl3 = p;
    304
    305#ifdef DEBUG_MIDI
    306	snd_printk(KERN_DEBUG "Note on, ch %i, inst %i, note %i, vel %i\n",
    307		   chan->number, chan->midi_program, note, vel);
    308#endif
    309
    310	/* in SYNTH mode, application takes care of voices */
    311	/* in SEQ mode, drum voice numbers are notes on drum channel */
    312	if (opl3->synth_mode == SNDRV_OPL3_MODE_SEQ) {
    313		if (chan->drum_channel) {
    314			/* percussion instruments are located in bank 128 */
    315			bank = 128;
    316			prg = note;
    317		} else {
    318			bank = chan->gm_bank_select;
    319			prg = chan->midi_program;
    320		}
    321	} else {
    322		/* Prepare for OSS mode */
    323		if (chan->number >= MAX_OPL3_VOICES)
    324			return;
    325
    326		/* OSS instruments are located in bank 127 */
    327		bank = 127;
    328		prg = chan->midi_program;
    329	}
    330
    331	spin_lock_irqsave(&opl3->voice_lock, flags);
    332
    333	if (use_internal_drums) {
    334		snd_opl3_drum_switch(opl3, note, vel, 1, chan);
    335		spin_unlock_irqrestore(&opl3->voice_lock, flags);
    336		return;
    337	}
    338
    339 __extra_prg:
    340	patch = snd_opl3_find_patch(opl3, prg, bank, 0);
    341	if (!patch) {
    342		spin_unlock_irqrestore(&opl3->voice_lock, flags);
    343		return;
    344	}
    345
    346	fm = &patch->inst;
    347	switch (patch->type) {
    348	case FM_PATCH_OPL2:
    349		instr_4op = 0;
    350		break;
    351	case FM_PATCH_OPL3:
    352		if (opl3->hardware >= OPL3_HW_OPL3) {
    353			instr_4op = 1;
    354			break;
    355		}
    356		fallthrough;
    357	default:
    358		spin_unlock_irqrestore(&opl3->voice_lock, flags);
    359		return;
    360	}
    361#ifdef DEBUG_MIDI
    362	snd_printk(KERN_DEBUG "  --> OPL%i instrument: %s\n",
    363		   instr_4op ? 3 : 2, patch->name);
    364#endif
    365	/* in SYNTH mode, application takes care of voices */
    366	/* in SEQ mode, allocate voice on free OPL3 channel */
    367	if (opl3->synth_mode == SNDRV_OPL3_MODE_SEQ) {
    368		voice = opl3_get_voice(opl3, instr_4op, chan);
    369	} else {
    370		/* remap OSS voice */
    371		voice = snd_opl3_oss_map[chan->number];		
    372	}
    373
    374	if (voice < 0) {
    375		spin_unlock_irqrestore(&opl3->voice_lock, flags);
    376		return;
    377	}
    378
    379	if (voice < MAX_OPL2_VOICES) {
    380		/* Left register block for voices 0 .. 8 */
    381		reg_side = OPL3_LEFT;
    382		voice_offset = voice;
    383		connect_mask = (OPL3_LEFT_4OP_0 << voice_offset) & 0x07;
    384	} else {
    385		/* Right register block for voices 9 .. 17 */
    386		reg_side = OPL3_RIGHT;
    387		voice_offset = voice - MAX_OPL2_VOICES;
    388		connect_mask = (OPL3_RIGHT_4OP_0 << voice_offset) & 0x38;
    389	}
    390
    391	/* kill voice on channel */
    392	vp = &opl3->voices[voice];
    393	if (vp->state > 0) {
    394		opl3_reg = reg_side | (OPL3_REG_KEYON_BLOCK + voice_offset);
    395		reg_val = vp->keyon_reg & ~OPL3_KEYON_BIT;
    396		opl3->command(opl3, opl3_reg, reg_val);
    397	}
    398	if (instr_4op) {
    399		vp2 = &opl3->voices[voice + 3];
    400		if (vp2->state > 0) {
    401			opl3_reg = reg_side | (OPL3_REG_KEYON_BLOCK +
    402					       voice_offset + 3);
    403			reg_val = vp->keyon_reg & ~OPL3_KEYON_BIT;
    404			opl3->command(opl3, opl3_reg, reg_val);
    405		}
    406	}
    407
    408	/* set connection register */
    409	if (instr_4op) {
    410		if ((opl3->connection_reg ^ connect_mask) & connect_mask) {
    411			opl3->connection_reg |= connect_mask;
    412			/* set connection bit */
    413			opl3_reg = OPL3_RIGHT | OPL3_REG_CONNECTION_SELECT;
    414			opl3->command(opl3, opl3_reg, opl3->connection_reg);
    415		}
    416	} else {
    417		if ((opl3->connection_reg ^ ~connect_mask) & connect_mask) {
    418			opl3->connection_reg &= ~connect_mask;
    419			/* clear connection bit */
    420			opl3_reg = OPL3_RIGHT | OPL3_REG_CONNECTION_SELECT;
    421			opl3->command(opl3, opl3_reg, opl3->connection_reg);
    422		}
    423	}
    424
    425#ifdef DEBUG_MIDI
    426	snd_printk(KERN_DEBUG "  --> setting OPL3 connection: 0x%x\n",
    427		   opl3->connection_reg);
    428#endif
    429	/*
    430	 * calculate volume depending on connection
    431	 * between FM operators (see include/opl3.h)
    432	 */
    433	for (i = 0; i < (instr_4op ? 4 : 2); i++)
    434		vol_op[i] = fm->op[i].ksl_level;
    435
    436	connection = fm->feedback_connection[0] & 0x01;
    437	if (instr_4op) {
    438		connection <<= 1;
    439		connection |= fm->feedback_connection[1] & 0x01;
    440
    441		snd_opl3_calc_volume(&vol_op[3], vel, chan);
    442		switch (connection) {
    443		case 0x03:
    444			snd_opl3_calc_volume(&vol_op[2], vel, chan);
    445			fallthrough;
    446		case 0x02:
    447			snd_opl3_calc_volume(&vol_op[0], vel, chan);
    448			break;
    449		case 0x01:
    450			snd_opl3_calc_volume(&vol_op[1], vel, chan);
    451		}
    452	} else {
    453		snd_opl3_calc_volume(&vol_op[1], vel, chan);
    454		if (connection)
    455			snd_opl3_calc_volume(&vol_op[0], vel, chan);
    456	}
    457
    458	/* Program the FM voice characteristics */
    459	for (i = 0; i < (instr_4op ? 4 : 2); i++) {
    460#ifdef DEBUG_MIDI
    461		snd_printk(KERN_DEBUG "  --> programming operator %i\n", i);
    462#endif
    463		op_offset = snd_opl3_regmap[voice_offset][i];
    464
    465		/* Set OPL3 AM_VIB register of requested voice/operator */ 
    466		reg_val = fm->op[i].am_vib;
    467		opl3_reg = reg_side | (OPL3_REG_AM_VIB + op_offset);
    468		opl3->command(opl3, opl3_reg, reg_val);
    469
    470		/* Set OPL3 KSL_LEVEL register of requested voice/operator */ 
    471		reg_val = vol_op[i];
    472		opl3_reg = reg_side | (OPL3_REG_KSL_LEVEL + op_offset);
    473		opl3->command(opl3, opl3_reg, reg_val);
    474
    475		/* Set OPL3 ATTACK_DECAY register of requested voice/operator */ 
    476		reg_val = fm->op[i].attack_decay;
    477		opl3_reg = reg_side | (OPL3_REG_ATTACK_DECAY + op_offset);
    478		opl3->command(opl3, opl3_reg, reg_val);
    479
    480		/* Set OPL3 SUSTAIN_RELEASE register of requested voice/operator */ 
    481		reg_val = fm->op[i].sustain_release;
    482		opl3_reg = reg_side | (OPL3_REG_SUSTAIN_RELEASE + op_offset);
    483		opl3->command(opl3, opl3_reg, reg_val);
    484
    485		/* Select waveform */
    486		reg_val = fm->op[i].wave_select;
    487		opl3_reg = reg_side | (OPL3_REG_WAVE_SELECT + op_offset);
    488		opl3->command(opl3, opl3_reg, reg_val);
    489	}
    490
    491	/* Set operator feedback and 2op inter-operator connection */
    492	reg_val = fm->feedback_connection[0];
    493	/* Set output voice connection */
    494	reg_val |= OPL3_STEREO_BITS;
    495	if (chan->gm_pan < 43)
    496		reg_val &= ~OPL3_VOICE_TO_RIGHT;
    497	if (chan->gm_pan > 85)
    498		reg_val &= ~OPL3_VOICE_TO_LEFT;
    499	opl3_reg = reg_side | (OPL3_REG_FEEDBACK_CONNECTION + voice_offset);
    500	opl3->command(opl3, opl3_reg, reg_val);
    501
    502	if (instr_4op) {
    503		/* Set 4op inter-operator connection */
    504		reg_val = fm->feedback_connection[1] & OPL3_CONNECTION_BIT;
    505		/* Set output voice connection */
    506		reg_val |= OPL3_STEREO_BITS;
    507		if (chan->gm_pan < 43)
    508			reg_val &= ~OPL3_VOICE_TO_RIGHT;
    509		if (chan->gm_pan > 85)
    510			reg_val &= ~OPL3_VOICE_TO_LEFT;
    511		opl3_reg = reg_side | (OPL3_REG_FEEDBACK_CONNECTION +
    512				       voice_offset + 3);
    513		opl3->command(opl3, opl3_reg, reg_val);
    514	}
    515
    516	/*
    517	 * Special treatment of percussion notes for fm:
    518	 * Requested pitch is really program, and pitch for
    519	 * device is whatever was specified in the patch library.
    520	 */
    521	if (fm->fix_key)
    522		note = fm->fix_key;
    523	/*
    524	 * use transpose if defined in patch library
    525	 */
    526	if (fm->trnsps)
    527		note += (fm->trnsps - 64);
    528
    529	snd_opl3_calc_pitch(&fnum, &blocknum, note, chan);
    530
    531	/* Set OPL3 FNUM_LOW register of requested voice */
    532	opl3_reg = reg_side | (OPL3_REG_FNUM_LOW + voice_offset);
    533	opl3->command(opl3, opl3_reg, fnum);
    534
    535	opl3->voices[voice].keyon_reg = blocknum;
    536
    537	/* Set output sound flag */
    538	blocknum |= OPL3_KEYON_BIT;
    539
    540#ifdef DEBUG_MIDI
    541	snd_printk(KERN_DEBUG "  --> trigger voice %i\n", voice);
    542#endif
    543	/* Set OPL3 KEYON_BLOCK register of requested voice */ 
    544	opl3_reg = reg_side | (OPL3_REG_KEYON_BLOCK + voice_offset);
    545	opl3->command(opl3, opl3_reg, blocknum);
    546
    547	/* kill note after fixed duration (in centiseconds) */
    548	if (fm->fix_dur) {
    549		opl3->voices[voice].note_off = jiffies +
    550			(fm->fix_dur * HZ) / 100;
    551		snd_opl3_start_timer(opl3);
    552		opl3->voices[voice].note_off_check = 1;
    553	} else
    554		opl3->voices[voice].note_off_check = 0;
    555
    556	/* get extra pgm, but avoid possible loops */
    557	extra_prg = (extra_prg) ? 0 : fm->modes;
    558
    559	/* do the bookkeeping */
    560	vp->time = opl3->use_time++;
    561	vp->note = key;
    562	vp->chan = chan;
    563
    564	if (instr_4op) {
    565		vp->state = SNDRV_OPL3_ST_ON_4OP;
    566
    567		vp2 = &opl3->voices[voice + 3];
    568		vp2->time = opl3->use_time++;
    569		vp2->note = key;
    570		vp2->chan = chan;
    571		vp2->state = SNDRV_OPL3_ST_NOT_AVAIL;
    572	} else {
    573		if (vp->state == SNDRV_OPL3_ST_ON_4OP) {
    574			/* 4op killed by 2op, release bounded voice */
    575			vp2 = &opl3->voices[voice + 3];
    576			vp2->time = opl3->use_time++;
    577			vp2->state = SNDRV_OPL3_ST_OFF;
    578		}
    579		vp->state = SNDRV_OPL3_ST_ON_2OP;
    580	}
    581
    582#ifdef DEBUG_ALLOC
    583	debug_alloc(opl3, "note on ", voice);
    584#endif
    585
    586	/* allocate extra program if specified in patch library */
    587	if (extra_prg) {
    588		if (extra_prg > 128) {
    589			bank = 128;
    590			/* percussions start at 35 */
    591			prg = extra_prg - 128 + 35 - 1;
    592		} else {
    593			bank = 0;
    594			prg = extra_prg - 1;
    595		}
    596#ifdef DEBUG_MIDI
    597		snd_printk(KERN_DEBUG " *** allocating extra program\n");
    598#endif
    599		goto __extra_prg;
    600	}
    601	spin_unlock_irqrestore(&opl3->voice_lock, flags);
    602}
    603
    604static void snd_opl3_kill_voice(struct snd_opl3 *opl3, int voice)
    605{
    606	unsigned short reg_side;
    607	unsigned char voice_offset;
    608	unsigned short opl3_reg;
    609
    610	struct snd_opl3_voice *vp, *vp2;
    611
    612	if (snd_BUG_ON(voice >= MAX_OPL3_VOICES))
    613		return;
    614
    615	vp = &opl3->voices[voice];
    616	if (voice < MAX_OPL2_VOICES) {
    617		/* Left register block for voices 0 .. 8 */
    618		reg_side = OPL3_LEFT;
    619		voice_offset = voice;
    620	} else {
    621		/* Right register block for voices 9 .. 17 */
    622		reg_side = OPL3_RIGHT;
    623		voice_offset = voice - MAX_OPL2_VOICES;
    624	}
    625
    626	/* kill voice */
    627#ifdef DEBUG_MIDI
    628	snd_printk(KERN_DEBUG "  --> kill voice %i\n", voice);
    629#endif
    630	opl3_reg = reg_side | (OPL3_REG_KEYON_BLOCK + voice_offset);
    631	/* clear Key ON bit */
    632	opl3->command(opl3, opl3_reg, vp->keyon_reg);
    633
    634	/* do the bookkeeping */
    635	vp->time = opl3->use_time++;
    636
    637	if (vp->state == SNDRV_OPL3_ST_ON_4OP) {
    638		vp2 = &opl3->voices[voice + 3];
    639
    640		vp2->time = opl3->use_time++;
    641		vp2->state = SNDRV_OPL3_ST_OFF;
    642	}
    643	vp->state = SNDRV_OPL3_ST_OFF;
    644#ifdef DEBUG_ALLOC
    645	debug_alloc(opl3, "note off", voice);
    646#endif
    647
    648}
    649
    650/*
    651 * Release a note in response to a midi note off.
    652 */
    653static void snd_opl3_note_off_unsafe(void *p, int note, int vel,
    654				     struct snd_midi_channel *chan)
    655{
    656  	struct snd_opl3 *opl3;
    657
    658	int voice;
    659	struct snd_opl3_voice *vp;
    660
    661	opl3 = p;
    662
    663#ifdef DEBUG_MIDI
    664	snd_printk(KERN_DEBUG "Note off, ch %i, inst %i, note %i\n",
    665		   chan->number, chan->midi_program, note);
    666#endif
    667
    668	if (opl3->synth_mode == SNDRV_OPL3_MODE_SEQ) {
    669		if (chan->drum_channel && use_internal_drums) {
    670			snd_opl3_drum_switch(opl3, note, vel, 0, chan);
    671			return;
    672		}
    673		/* this loop will hopefully kill all extra voices, because
    674		   they are grouped by the same channel and note values */
    675		for (voice = 0; voice < opl3->max_voices; voice++) {
    676			vp = &opl3->voices[voice];
    677			if (vp->state > 0 && vp->chan == chan && vp->note == note) {
    678				snd_opl3_kill_voice(opl3, voice);
    679			}
    680		}
    681	} else {
    682		/* remap OSS voices */
    683		if (chan->number < MAX_OPL3_VOICES) {
    684			voice = snd_opl3_oss_map[chan->number];		
    685			snd_opl3_kill_voice(opl3, voice);
    686		}
    687	}
    688}
    689
    690void snd_opl3_note_off(void *p, int note, int vel,
    691		       struct snd_midi_channel *chan)
    692{
    693	struct snd_opl3 *opl3 = p;
    694	unsigned long flags;
    695
    696	spin_lock_irqsave(&opl3->voice_lock, flags);
    697	snd_opl3_note_off_unsafe(p, note, vel, chan);
    698	spin_unlock_irqrestore(&opl3->voice_lock, flags);
    699}
    700
    701/*
    702 * key pressure change
    703 */
    704void snd_opl3_key_press(void *p, int note, int vel, struct snd_midi_channel *chan)
    705{
    706#ifdef DEBUG_MIDI
    707	snd_printk(KERN_DEBUG "Key pressure, ch#: %i, inst#: %i\n",
    708		   chan->number, chan->midi_program);
    709#endif
    710}
    711
    712/*
    713 * terminate note
    714 */
    715void snd_opl3_terminate_note(void *p, int note, struct snd_midi_channel *chan)
    716{
    717#ifdef DEBUG_MIDI
    718	snd_printk(KERN_DEBUG "Terminate note, ch#: %i, inst#: %i\n",
    719		   chan->number, chan->midi_program);
    720#endif
    721}
    722
    723static void snd_opl3_update_pitch(struct snd_opl3 *opl3, int voice)
    724{
    725	unsigned short reg_side;
    726	unsigned char voice_offset;
    727	unsigned short opl3_reg;
    728
    729	unsigned char fnum, blocknum;
    730
    731	struct snd_opl3_voice *vp;
    732
    733	if (snd_BUG_ON(voice >= MAX_OPL3_VOICES))
    734		return;
    735
    736	vp = &opl3->voices[voice];
    737	if (vp->chan == NULL)
    738		return; /* not allocated? */
    739
    740	if (voice < MAX_OPL2_VOICES) {
    741		/* Left register block for voices 0 .. 8 */
    742		reg_side = OPL3_LEFT;
    743		voice_offset = voice;
    744	} else {
    745		/* Right register block for voices 9 .. 17 */
    746		reg_side = OPL3_RIGHT;
    747		voice_offset = voice - MAX_OPL2_VOICES;
    748	}
    749
    750	snd_opl3_calc_pitch(&fnum, &blocknum, vp->note, vp->chan);
    751
    752	/* Set OPL3 FNUM_LOW register of requested voice */
    753	opl3_reg = reg_side | (OPL3_REG_FNUM_LOW + voice_offset);
    754	opl3->command(opl3, opl3_reg, fnum);
    755
    756	vp->keyon_reg = blocknum;
    757
    758	/* Set output sound flag */
    759	blocknum |= OPL3_KEYON_BIT;
    760
    761	/* Set OPL3 KEYON_BLOCK register of requested voice */ 
    762	opl3_reg = reg_side | (OPL3_REG_KEYON_BLOCK + voice_offset);
    763	opl3->command(opl3, opl3_reg, blocknum);
    764
    765	vp->time = opl3->use_time++;
    766}
    767
    768/*
    769 * Update voice pitch controller
    770 */
    771static void snd_opl3_pitch_ctrl(struct snd_opl3 *opl3, struct snd_midi_channel *chan)
    772{
    773	int voice;
    774	struct snd_opl3_voice *vp;
    775
    776	unsigned long flags;
    777
    778	spin_lock_irqsave(&opl3->voice_lock, flags);
    779
    780	if (opl3->synth_mode == SNDRV_OPL3_MODE_SEQ) {
    781		for (voice = 0; voice < opl3->max_voices; voice++) {
    782			vp = &opl3->voices[voice];
    783			if (vp->state > 0 && vp->chan == chan) {
    784				snd_opl3_update_pitch(opl3, voice);
    785			}
    786		}
    787	} else {
    788		/* remap OSS voices */
    789		if (chan->number < MAX_OPL3_VOICES) {
    790			voice = snd_opl3_oss_map[chan->number];		
    791			snd_opl3_update_pitch(opl3, voice);
    792		}
    793	}
    794	spin_unlock_irqrestore(&opl3->voice_lock, flags);
    795}
    796
    797/*
    798 * Deal with a controller type event.  This includes all types of
    799 * control events, not just the midi controllers
    800 */
    801void snd_opl3_control(void *p, int type, struct snd_midi_channel *chan)
    802{
    803  	struct snd_opl3 *opl3;
    804
    805	opl3 = p;
    806#ifdef DEBUG_MIDI
    807	snd_printk(KERN_DEBUG "Controller, TYPE = %i, ch#: %i, inst#: %i\n",
    808		   type, chan->number, chan->midi_program);
    809#endif
    810
    811	switch (type) {
    812	case MIDI_CTL_MSB_MODWHEEL:
    813		if (chan->control[MIDI_CTL_MSB_MODWHEEL] > 63)
    814			opl3->drum_reg |= OPL3_VIBRATO_DEPTH;
    815		else 
    816			opl3->drum_reg &= ~OPL3_VIBRATO_DEPTH;
    817		opl3->command(opl3, OPL3_LEFT | OPL3_REG_PERCUSSION,
    818				 opl3->drum_reg);
    819		break;
    820	case MIDI_CTL_E2_TREMOLO_DEPTH:
    821		if (chan->control[MIDI_CTL_E2_TREMOLO_DEPTH] > 63)
    822			opl3->drum_reg |= OPL3_TREMOLO_DEPTH;
    823		else 
    824			opl3->drum_reg &= ~OPL3_TREMOLO_DEPTH;
    825		opl3->command(opl3, OPL3_LEFT | OPL3_REG_PERCUSSION,
    826				 opl3->drum_reg);
    827		break;
    828	case MIDI_CTL_PITCHBEND:
    829		snd_opl3_pitch_ctrl(opl3, chan);
    830		break;
    831	}
    832}
    833
    834/*
    835 * NRPN events
    836 */
    837void snd_opl3_nrpn(void *p, struct snd_midi_channel *chan,
    838		   struct snd_midi_channel_set *chset)
    839{
    840#ifdef DEBUG_MIDI
    841	snd_printk(KERN_DEBUG "NRPN, ch#: %i, inst#: %i\n",
    842		   chan->number, chan->midi_program);
    843#endif
    844}
    845
    846/*
    847 * receive sysex
    848 */
    849void snd_opl3_sysex(void *p, unsigned char *buf, int len,
    850		    int parsed, struct snd_midi_channel_set *chset)
    851{
    852#ifdef DEBUG_MIDI
    853	snd_printk(KERN_DEBUG "SYSEX\n");
    854#endif
    855}