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