1 /*	$OpenBSD: opl.c,v 1.6 2003/10/21 18:58:49 jmc Exp $	*/
2 /*	$NetBSD: opl.c,v 1.7 1998/12/08 14:26:56 augustss Exp $	*/
3 
4 /*
5  * Copyright (c) 1998 The NetBSD Foundation, Inc.
6  * All rights reserved.
7  *
8  * This code is derived from software contributed to The NetBSD Foundation
9  * by Lennart Augustsson (augustss@netbsd.org).
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in the
18  *    documentation and/or other materials provided with the distribution.
19  * 3. All advertising materials mentioning features or use of this software
20  *    must display the following acknowledgement:
21  *        This product includes software developed by the NetBSD
22  *        Foundation, Inc. and its contributors.
23  * 4. Neither the name of The NetBSD Foundation nor the names of its
24  *    contributors may be used to endorse or promote products derived
25  *    from this software without specific prior written permission.
26  *
27  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
28  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
29  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
31  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37  * POSSIBILITY OF SUCH DAMAGE.
38  */
39 
40 /*
41  * The OPL3 (YMF262) manual can be found at
42  * ftp://ftp.yamahayst.com/pub/Fax_Back_Doc/Sound/YMF262.PDF
43  */
44 
45 #include <sys/param.h>
46 #include <sys/systm.h>
47 #include <sys/errno.h>
48 #include <sys/ioctl.h>
49 #include <sys/syslog.h>
50 #include <sys/device.h>
51 #include <sys/select.h>
52 
53 #include <machine/cpu.h>
54 #include <machine/bus.h>
55 
56 #include <sys/audioio.h>
57 #include <sys/midiio.h>
58 #include <dev/audio_if.h>
59 
60 #include <dev/midi_if.h>
61 #include <dev/midivar.h>
62 #include <dev/midisynvar.h>
63 
64 #include <dev/ic/oplreg.h>
65 #include <dev/ic/oplvar.h>
66 
67 #ifdef AUDIO_DEBUG
68 #define DPRINTF(x)	if (opldebug) printf x
69 #define DPRINTFN(n,x)	if (opldebug >= (n)) printf x
70 int	opldebug = 0;
71 #else
72 #define DPRINTF(x)
73 #define DPRINTFN(n,x)
74 #endif
75 
76 struct real_voice {
77 	u_int8_t voice_num;
78 	u_int8_t voice_mode; /* 0=unavailable, 2=2 OP, 4=4 OP */
79 	u_int8_t iooffs; /* I/O port (left or right side) */
80 	u_int8_t op[4]; /* Operator offsets */
81 };
82 
83 const struct opl_voice voicetab[] = {
84 /*       No    I/O offs		OP1	OP2	OP3   OP4	*/
85 /*	---------------------------------------------------	*/
86 	{ 0,   OPL_L,	{0x00,	0x03,	0x08, 0x0b}},
87 	{ 1,   OPL_L,	{0x01,	0x04,	0x09, 0x0c}},
88 	{ 2,   OPL_L,	{0x02,	0x05,	0x0a, 0x0d}},
89 
90 	{ 3,   OPL_L,	{0x08,	0x0b,	0x00, 0x00}},
91 	{ 4,   OPL_L,	{0x09,	0x0c,	0x00, 0x00}},
92 	{ 5,   OPL_L,	{0x0a,	0x0d,	0x00, 0x00}},
93 
94 	{ 6,   OPL_L,	{0x10,	0x13,	0x00, 0x00}},
95 	{ 7,   OPL_L,	{0x11,	0x14,	0x00, 0x00}},
96 	{ 8,   OPL_L,	{0x12,	0x15,	0x00, 0x00}},
97 
98 	{ 0,   OPL_R,	{0x00,	0x03,	0x08, 0x0b}},
99 	{ 1,   OPL_R,	{0x01,	0x04,	0x09, 0x0c}},
100 	{ 2,   OPL_R,	{0x02,	0x05,	0x0a, 0x0d}},
101 	{ 3,   OPL_R,	{0x08,	0x0b,	0x00, 0x00}},
102 	{ 4,   OPL_R,	{0x09,	0x0c,	0x00, 0x00}},
103 	{ 5,   OPL_R,	{0x0a,	0x0d,	0x00, 0x00}},
104 
105 	{ 6,   OPL_R,	{0x10,	0x13,	0x00, 0x00}},
106 	{ 7,   OPL_R,	{0x11,	0x14,	0x00, 0x00}},
107 	{ 8,   OPL_R,	{0x12,	0x15,	0x00, 0x00}}
108 };
109 
110 static void opl_command(struct opl_softc *, int, int, int);
111 void opl_reset(struct opl_softc *);
112 void opl_freq_to_fnum (int freq, int *block, int *fnum);
113 
114 int oplsyn_open(midisyn *ms, int);
115 void oplsyn_close(midisyn *);
116 void oplsyn_reset(void *);
117 void oplsyn_noteon(midisyn *, u_int32_t, u_int32_t, u_int32_t);
118 void oplsyn_noteoff(midisyn *, u_int32_t, u_int32_t, u_int32_t);
119 void oplsyn_keypressure(midisyn *, u_int32_t, u_int32_t, u_int32_t);
120 void oplsyn_ctlchange(midisyn *, u_int32_t, u_int32_t, u_int32_t);
121 void oplsyn_pitchbend(midisyn *, u_int32_t, u_int32_t, u_int32_t);
122 void oplsyn_loadpatch(midisyn *, struct sysex_info *, struct uio *);
123 
124 
125 void opl_set_op_reg(struct opl_softc *, int, int, int, u_char);
126 void opl_set_ch_reg(struct opl_softc *, int, int, u_char);
127 void opl_load_patch(struct opl_softc *, int);
128 u_int32_t opl_get_block_fnum(int freq);
129 int opl_calc_vol(int regbyte, int volume, int main_vol);
130 
131 struct cfdriver opl_cd = {
132 	NULL, "opl", DV_DULL
133 };
134 
135 struct midisyn_methods opl3_midi = {
136 	oplsyn_open,
137 	oplsyn_close,
138 	0,
139 	0,
140 	oplsyn_noteon,
141 	oplsyn_noteoff,
142 	oplsyn_keypressure,
143 	oplsyn_ctlchange,
144 	0,
145 	0,
146 	oplsyn_pitchbend,
147 	0
148 };
149 
150 void
opl_attach(sc)151 opl_attach(sc)
152 	struct opl_softc *sc;
153 {
154 	int i;
155 
156 	if (!opl_find(sc)) {
157 		printf("\nopl: find failed\n");
158 		return;
159 	}
160 
161 	sc->syn.mets = &opl3_midi;
162 	snprintf(sc->syn.name, sizeof sc->syn.name, "%sYamaha OPL%d",
163 	    sc->syn.name, sc->model);
164 	sc->syn.data = sc;
165 	sc->syn.nvoice = sc->model == OPL_2 ? OPL2_NVOICE : OPL3_NVOICE;
166 	sc->syn.flags =  MS_DOALLOC | MS_FREQXLATE;
167 	midisyn_attach(&sc->mididev, &sc->syn);
168 
169 	/* Set up voice table */
170 	for (i = 0; i < OPL3_NVOICE; i++)
171 		sc->voices[i] = voicetab[i];
172 
173 	opl_reset(sc);
174 
175 	printf(": model OPL%d\n", sc->model);
176 
177 	midi_attach_mi(&midisyn_hw_if, &sc->syn, &sc->mididev.dev);
178 }
179 
180 static void
opl_command(sc,offs,addr,data)181 opl_command(sc, offs, addr, data)
182 	struct opl_softc *sc;
183 	int offs;
184 	int addr, data;
185 {
186 	DPRINTFN(4, ("opl_command: sc=%p, offs=%d addr=0x%02x data=0x%02x\n",
187 		     sc, offs, addr, data));
188 	offs += sc->offs;
189 	bus_space_write_1(sc->iot, sc->ioh, OPL_ADDR+offs, addr);
190 	if (sc->model == OPL_2)
191 		delay(10);
192 	else
193 		delay(6);
194 	bus_space_write_1(sc->iot, sc->ioh, OPL_DATA+offs, data);
195 	if (sc->model == OPL_2)
196 		delay(30);
197 	else
198 		delay(6);
199 }
200 
201 int
opl_find(sc)202 opl_find(sc)
203 	struct opl_softc *sc;
204 {
205 	u_int8_t status1, status2;
206 
207 	DPRINTFN(2,("opl_find: ioh=0x%x\n", (int)sc->ioh));
208 	sc->model = OPL_2;	/* worst case assumption */
209 
210 	/* Reset timers 1 and 2 */
211 	opl_command(sc, OPL_L, OPL_TIMER_CONTROL,
212 		    OPL_TIMER1_MASK | OPL_TIMER2_MASK);
213 	/* Reset the IRQ of the FM chip */
214 	opl_command(sc, OPL_L, OPL_TIMER_CONTROL, OPL_IRQ_RESET);
215 
216 	/* get status bits */
217 	status1 = bus_space_read_1(sc->iot,sc->ioh,OPL_STATUS+OPL_L+sc->offs);
218 
219 	opl_command(sc, OPL_L, OPL_TIMER1, -2); /* wait 2 ticks */
220 	opl_command(sc, OPL_L, OPL_TIMER_CONTROL, /* start timer1 */
221 		    OPL_TIMER1_START | OPL_TIMER2_MASK);
222 	delay(1000);		/* wait for timer to expire */
223 
224 	/* get status bits again */
225 	status2 = bus_space_read_1(sc->iot,sc->ioh,OPL_STATUS+OPL_L+sc->offs);
226 
227 	opl_command(sc, OPL_L, OPL_TIMER_CONTROL,
228 		    OPL_TIMER1_MASK | OPL_TIMER2_MASK);
229 	opl_command(sc, OPL_L, OPL_TIMER_CONTROL, OPL_IRQ_RESET);
230 
231 	DPRINTFN(2,("opl_find: %02x %02x\n", status1, status2));
232 
233 	if ((status1 & OPL_STATUS_MASK) != 0 ||
234 	    (status2 & OPL_STATUS_MASK) != (OPL_STATUS_IRQ | OPL_STATUS_FT1))
235 		return (0);
236 
237 	switch(status1) {
238 	case 0x00:
239 	case 0x0f:
240 		sc->model = OPL_3;
241 		break;
242 	case 0x06:
243 		sc->model = OPL_2;
244 		break;
245 	default:
246 		return 0;
247 	}
248 
249 	DPRINTFN(2,("opl_find: OPL%d at 0x%x detected\n",
250 		    sc->model, (int)sc->ioh));
251 	return (1);
252 }
253 
254 void
opl_set_op_reg(sc,base,voice,op,value)255 opl_set_op_reg(sc, base, voice, op, value)
256 	struct opl_softc *sc;
257 	int base;
258 	int voice;
259 	int op;
260 	u_char value;
261 {
262 	struct opl_voice *v = &sc->voices[voice];
263 	opl_command(sc, v->iooffs, base + v->op[op], value);
264 }
265 
266 void
opl_set_ch_reg(sc,base,voice,value)267 opl_set_ch_reg(sc, base, voice, value)
268 	struct opl_softc *sc;
269 	int base;
270 	int voice;
271 	u_char value;
272 {
273 	struct opl_voice *v = &sc->voices[voice];
274 	opl_command(sc, v->iooffs, base + v->voiceno, value);
275 }
276 
277 
278 void
opl_load_patch(sc,v)279 opl_load_patch(sc, v)
280 	struct opl_softc *sc;
281 	int v;
282 {
283 	const struct opl_operators *p = sc->voices[v].patch;
284 
285 	opl_set_op_reg(sc, OPL_AM_VIB,          v, 0, p->ops[OO_CHARS+0]);
286 	opl_set_op_reg(sc, OPL_AM_VIB,          v, 1, p->ops[OO_CHARS+1]);
287 	opl_set_op_reg(sc, OPL_KSL_LEVEL,       v, 0, p->ops[OO_KSL_LEV+0]);
288 	opl_set_op_reg(sc, OPL_KSL_LEVEL,       v, 1, p->ops[OO_KSL_LEV+1]);
289 	opl_set_op_reg(sc, OPL_ATTACK_DECAY,    v, 0, p->ops[OO_ATT_DEC+0]);
290 	opl_set_op_reg(sc, OPL_ATTACK_DECAY,    v, 1, p->ops[OO_ATT_DEC+1]);
291 	opl_set_op_reg(sc, OPL_SUSTAIN_RELEASE, v, 0, p->ops[OO_SUS_REL+0]);
292 	opl_set_op_reg(sc, OPL_SUSTAIN_RELEASE, v, 1, p->ops[OO_SUS_REL+1]);
293 	opl_set_op_reg(sc, OPL_WAVE_SELECT,     v, 0, p->ops[OO_WAV_SEL+0]);
294 	opl_set_op_reg(sc, OPL_WAVE_SELECT,     v, 1, p->ops[OO_WAV_SEL+1]);
295 	opl_set_ch_reg(sc, OPL_FEEDBACK_CONNECTION, v, p->ops[OO_FB_CONN]);
296 }
297 
298 #define OPL_FNUM_FAIL 0xffff
299 u_int32_t
opl_get_block_fnum(freq)300 opl_get_block_fnum(freq)
301 	int freq;
302 {
303 	u_int32_t f_num = freq / 3125;
304 	u_int32_t  block = 0;
305 
306 	while (f_num > 0x3FF && block < 8) {
307 		block++;
308 		f_num >>= 1;
309 	}
310 
311 	if (block > 7)
312 		return (OPL_FNUM_FAIL);
313 	else
314 		return ((block << 10) | f_num);
315   }
316 
317 
318 void
opl_reset(sc)319 opl_reset(sc)
320 	struct opl_softc *sc;
321 {
322 	int i;
323 
324 	for (i = 1; i <= OPL_MAXREG; i++)
325 		opl_command(sc, OPL_L, OPL_KEYON_BLOCK + i, 0);
326 
327 	opl_command(sc, OPL_L, OPL_TEST, OPL_ENABLE_WAVE_SELECT);
328 	opl_command(sc, OPL_L, OPL_PERCUSSION, 0);
329 	if (sc->model == OPL_3) {
330 		opl_command(sc, OPL_R, OPL_MODE, OPL3_ENABLE);
331 		opl_command(sc, OPL_R,OPL_CONNECTION_SELECT,OPL_NOCONNECTION);
332 	}
333 
334 	sc->volume = 64;
335 }
336 
337 int
oplsyn_open(ms,flags)338 oplsyn_open(ms, flags)
339 	midisyn *ms;
340 	int flags;
341 {
342 	struct opl_softc *sc = ms->data;
343 
344 	DPRINTFN(2, ("oplsyn_open: %d\n", flags));
345 
346 	opl_reset(ms->data);
347 	if (sc->spkrctl)
348 		sc->spkrctl(sc->spkrarg, 1);
349 	return (0);
350 }
351 
352 void
oplsyn_close(ms)353 oplsyn_close(ms)
354 	midisyn *ms;
355 {
356 	struct opl_softc *sc = ms->data;
357 
358 	DPRINTFN(2, ("oplsyn_close:\n"));
359 
360 	/*opl_reset(ms->data);*/
361 	if (sc->spkrctl)
362 		sc->spkrctl(sc->spkrarg, 0);
363 }
364 
365 #if 0
366 void
367 oplsyn_getinfo(addr, sd)
368 	void *addr;
369 	struct synth_dev *sd;
370 {
371 	struct opl_softc *sc = addr;
372 
373 	sd->name = sc->model == OPL_2 ? "Yamaha OPL2" : "Yamaha OPL3";
374 	sd->type = SYNTH_TYPE_FM;
375 	sd->subtype = sc->model == OPL_2 ? SYNTH_SUB_FM_TYPE_ADLIB
376 		: SYNTH_SUB_FM_TYPE_OPL3;
377 	sd->capabilities = 0;
378 }
379 #endif
380 
381 void
oplsyn_reset(addr)382 oplsyn_reset(addr)
383 	void *addr;
384 {
385 	struct opl_softc *sc = addr;
386 	DPRINTFN(3, ("oplsyn_reset:\n"));
387 	opl_reset(sc);
388 }
389 
390 int8_t opl_volume_table[128] =
391     {-64, -48, -40, -35, -32, -29, -27, -26,
392      -24, -23, -21, -20, -19, -18, -18, -17,
393      -16, -15, -15, -14, -13, -13, -12, -12,
394      -11, -11, -10, -10, -10, -9, -9, -8,
395      -8, -8, -7, -7, -7, -6, -6, -6,
396      -5, -5, -5, -5, -4, -4, -4, -4,
397      -3, -3, -3, -3, -2, -2, -2, -2,
398      -2, -1, -1, -1, -1, 0, 0, 0,
399      0, 0, 0, 1, 1, 1, 1, 1,
400      1, 2, 2, 2, 2, 2, 2, 2,
401      3, 3, 3, 3, 3, 3, 3, 4,
402      4, 4, 4, 4, 4, 4, 4, 5,
403      5, 5, 5, 5, 5, 5, 5, 5,
404      6, 6, 6, 6, 6, 6, 6, 6,
405      6, 7, 7, 7, 7, 7, 7, 7,
406      7, 7, 7, 8, 8, 8, 8, 8};
407 
408 int
opl_calc_vol(regbyte,volume,mainvol)409 opl_calc_vol(regbyte, volume, mainvol)
410 	int regbyte;
411 	int volume;
412 	int mainvol;
413 {
414 	int level = ~regbyte & OPL_TOTAL_LEVEL_MASK;
415 
416 	if (mainvol > 127)
417 		mainvol = 127;
418 
419 	volume = (volume * mainvol) / 127;
420 
421 	if (level)
422 		level += opl_volume_table[volume];
423 
424 	if (level > OPL_TOTAL_LEVEL_MASK)
425 		level = OPL_TOTAL_LEVEL_MASK;
426 	if (level < 0)
427 		level = 0;
428 
429 	return (~level & OPL_TOTAL_LEVEL_MASK);
430 }
431 
432 void
oplsyn_noteon(ms,voice,freq,vel)433 oplsyn_noteon(ms, voice, freq, vel)
434 	midisyn *ms;
435 	u_int32_t voice, freq, vel;
436 {
437 	struct opl_softc *sc = ms->data;
438 	struct opl_voice *v;
439 	const struct opl_operators *p;
440 	u_int32_t block_fnum;
441 	int mult;
442 	int c_mult, m_mult;
443 	u_int8_t chars0, chars1, ksl0, ksl1, fbc;
444 	u_int8_t r20m, r20c, r40m, r40c, rA0, rB0;
445 	u_int8_t vol0, vol1;
446 
447 	DPRINTFN(3, ("oplsyn_noteon: %p %d %d\n", sc, voice,
448 		     MIDISYN_FREQ_TO_HZ(freq)));
449 
450 #ifdef DIAGNOSTIC
451 	if (voice < 0 || voice >= sc->syn.nvoice) {
452 		printf("oplsyn_noteon: bad voice %d\n", voice);
453 		return;
454 	}
455 #endif
456 	/* Turn off old note */
457 	opl_set_op_reg(sc, OPL_KSL_LEVEL,   voice, 0, 0xff);
458 	opl_set_op_reg(sc, OPL_KSL_LEVEL,   voice, 1, 0xff);
459 	opl_set_ch_reg(sc, OPL_KEYON_BLOCK, voice,    0);
460 
461 	v = &sc->voices[voice];
462 
463 	p = &opl2_instrs[MS_GETPGM(ms, voice)];
464 	v->patch = p;
465 	opl_load_patch(sc, voice);
466 
467 	mult = 1;
468 	for (;;) {
469 		block_fnum = opl_get_block_fnum(freq / mult);
470 		if (block_fnum != OPL_FNUM_FAIL)
471 			break;
472 		mult *= 2;
473 		if (mult == 16)
474 			mult = 15;
475 	}
476 
477 	chars0 = p->ops[OO_CHARS+0];
478 	chars1 = p->ops[OO_CHARS+1];
479 	m_mult = (chars0 & OPL_MULTIPLE_MASK) * mult;
480 	c_mult = (chars1 & OPL_MULTIPLE_MASK) * mult;
481 	if ((block_fnum == OPL_FNUM_FAIL) || (m_mult > 15) || (c_mult > 15)) {
482 		printf("oplsyn_noteon: frequence out of range %d\n",
483 		       MIDISYN_FREQ_TO_HZ(freq));
484 		return;
485 	}
486 	r20m = (chars0 &~ OPL_MULTIPLE_MASK) | m_mult;
487 	r20c = (chars1 &~ OPL_MULTIPLE_MASK) | c_mult;
488 
489 	/* 2 voice */
490 	ksl0 = p->ops[OO_KSL_LEV+0];
491 	ksl1 = p->ops[OO_KSL_LEV+1];
492 	if (p->ops[OO_FB_CONN] & 0x01) {
493 		vol0 = opl_calc_vol(ksl0, vel, sc->volume);
494 		vol1 = opl_calc_vol(ksl1, vel, sc->volume);
495 	} else {
496 		vol0 = ksl0;
497 		vol1 = opl_calc_vol(ksl1, vel, sc->volume);
498 	}
499 	r40m = (ksl0 & OPL_KSL_MASK) | vol0;
500 	r40c = (ksl1 & OPL_KSL_MASK) | vol1;
501 
502 	rA0  = block_fnum & 0xFF;
503 	rB0  = (block_fnum >> 8) | OPL_KEYON_BIT;
504 
505 	v->rB0 = rB0;
506 
507 	fbc = p->ops[OO_FB_CONN];
508 	if (sc->model == OPL_3) {
509 		fbc &= ~OPL_STEREO_BITS;
510 		/* XXX use pan */
511 		fbc |= OPL_VOICE_TO_LEFT | OPL_VOICE_TO_RIGHT;
512 	}
513 	opl_set_ch_reg(sc, OPL_FEEDBACK_CONNECTION, voice, fbc);
514 
515 	opl_set_op_reg(sc, OPL_AM_VIB,      voice, 0, r20m);
516 	opl_set_op_reg(sc, OPL_AM_VIB,      voice, 1, r20c);
517 	opl_set_op_reg(sc, OPL_KSL_LEVEL,   voice, 0, r40m);
518 	opl_set_op_reg(sc, OPL_KSL_LEVEL,   voice, 1, r40c);
519 	opl_set_ch_reg(sc, OPL_FNUM_LOW,    voice,    rA0);
520 	opl_set_ch_reg(sc, OPL_KEYON_BLOCK, voice,    rB0);
521 }
522 
523 void
oplsyn_noteoff(ms,voice,note,vel)524 oplsyn_noteoff(ms, voice, note, vel)
525 	midisyn *ms;
526 	u_int32_t voice, note, vel;
527 {
528 	struct opl_softc *sc = ms->data;
529 	struct opl_voice *v;
530 
531 	DPRINTFN(3, ("oplsyn_noteoff: %p %d %d\n", sc, voice,
532 		     MIDISYN_FREQ_TO_HZ(note)));
533 
534 #ifdef DIAGNOSTIC
535 	if (voice < 0 || voice >= sc->syn.nvoice) {
536 		printf("oplsyn_noteoff: bad voice %d\n", voice);
537 		return;
538 	}
539 #endif
540 	v = &sc->voices[voice];
541 	opl_set_ch_reg(sc, 0xB0, voice, v->rB0 & ~OPL_KEYON_BIT);
542 }
543 
544 void
oplsyn_keypressure(ms,voice,note,vel)545 oplsyn_keypressure(ms, voice, note, vel)
546 	midisyn *ms;
547 	u_int32_t voice, note, vel;
548 {
549 #ifdef AUDIO_DEBUG
550 	struct opl_softc *sc = ms->data;
551 	DPRINTFN(1, ("oplsyn_keypressure: %p %d\n", sc, note));
552 #endif
553 }
554 
555 void
oplsyn_ctlchange(ms,voice,parm,w14)556 oplsyn_ctlchange(ms, voice, parm, w14)
557 	midisyn *ms;
558 	u_int32_t voice, parm, w14;
559 {
560 #ifdef AUDIO_DEBUG
561 	struct opl_softc *sc = ms->data;
562 	DPRINTFN(1, ("oplsyn_ctlchange: %p %d\n", sc, voice));
563 #endif
564 }
565 
566 void
oplsyn_pitchbend(ms,voice,parm,x)567 oplsyn_pitchbend(ms, voice, parm, x)
568 	midisyn *ms;
569 	u_int32_t voice, parm, x;
570 {
571 #ifdef AUDIO_DEBUG
572 	struct opl_softc *sc = ms->data;
573 	DPRINTFN(1, ("oplsyn_pitchbend: %p %d\n", sc, voice));
574 #endif
575 }
576 
577 void
oplsyn_loadpatch(ms,sysex,uio)578 oplsyn_loadpatch(ms, sysex, uio)
579 	midisyn *ms;
580 	struct sysex_info *sysex;
581 	struct uio *uio;
582 {
583 #if 0
584 	struct opl_softc *sc = ms->data;
585 	struct sbi_instrument ins;
586 
587 	DPRINTFN(1, ("oplsyn_loadpatch: %p\n", sc));
588 
589 	memcpy(&ins, sysex, sizeof *sysex);
590 	if (uio->uio_resid >= sizeof ins - sizeof *sysex)
591 		return EINVAL;
592 	uiomove((char *)&ins + sizeof *sysex, sizeof ins - sizeof *sysex, uio);
593 	/* XXX */
594 #endif
595 }
596