xref: /netbsd-src/sys/dev/ic/opl.c (revision dc306354b0b29af51801a7632f1e95265a68cd81)
1 /*	$NetBSD: opl.c,v 1.7 1998/12/08 14:26:56 augustss 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/pub/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 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_pitchbend __P((midisyn *, u_int32_t, u_int32_t, u_int32_t));
121 void oplsyn_loadpatch __P((midisyn *, struct sysex_info *, struct uio *));
122 
123 
124 void opl_set_op_reg __P((struct opl_softc *, int, int, int, u_char));
125 void opl_set_ch_reg __P((struct opl_softc *, int, int, u_char));
126 void opl_load_patch __P((struct opl_softc *, int));
127 u_int32_t opl_get_block_fnum __P((int freq));
128 int opl_calc_vol __P((int regbyte, int volume, int main_vol));
129 
130 struct midisyn_methods opl3_midi = {
131 	oplsyn_open,
132 	oplsyn_close,
133 	0,
134 	0,
135 	oplsyn_noteon,
136 	oplsyn_noteoff,
137 	oplsyn_keypressure,
138 	oplsyn_ctlchange,
139 	0,
140 	0,
141 	oplsyn_pitchbend,
142 	0
143 };
144 
145 void
146 opl_attach(sc)
147 	struct opl_softc *sc;
148 {
149 	int i;
150 
151 	if (!opl_find(sc)) {
152 		printf("\nopl: find failed\n");
153 		return;
154 	}
155 
156 	sc->syn.mets = &opl3_midi;
157 	sprintf(sc->syn.name, "%sYamaha OPL%d", sc->syn.name, sc->model);
158 	sc->syn.data = sc;
159 	sc->syn.nvoice = sc->model == OPL_2 ? OPL2_NVOICE : OPL3_NVOICE;
160 	sc->syn.flags =  MS_DOALLOC | MS_FREQXLATE;
161 	midisyn_attach(&sc->mididev, &sc->syn);
162 
163 	/* Set up voice table */
164 	for (i = 0; i < OPL3_NVOICE; i++)
165 		sc->voices[i] = voicetab[i];
166 
167 	opl_reset(sc);
168 
169 	printf(": model OPL%d\n", sc->model);
170 
171 	midi_attach_mi(&midisyn_hw_if, &sc->syn, &sc->mididev.dev);
172 }
173 
174 static void
175 opl_command(sc, offs, addr, data)
176 	struct opl_softc *sc;
177 	int offs;
178 	int addr, data;
179 {
180 	DPRINTFN(4, ("opl_command: sc=%p, offs=%d addr=0x%02x data=0x%02x\n",
181 		     sc, offs, addr, data));
182 	offs += sc->offs;
183 	bus_space_write_1(sc->iot, sc->ioh, OPL_ADDR+offs, addr);
184 	if (sc->model == OPL_2)
185 		delay(10);
186 	else
187 		delay(6);
188 	bus_space_write_1(sc->iot, sc->ioh, OPL_DATA+offs, data);
189 	if (sc->model == OPL_2)
190 		delay(30);
191 	else
192 		delay(6);
193 }
194 
195 int
196 opl_find(sc)
197 	struct opl_softc *sc;
198 {
199 	u_int8_t status1, status2;
200 
201 	DPRINTFN(2,("opl_find: ioh=0x%x\n", (int)sc->ioh));
202 	sc->model = OPL_2;	/* worst case assumtion */
203 
204 	/* Reset timers 1 and 2 */
205 	opl_command(sc, OPL_L, OPL_TIMER_CONTROL,
206 		    OPL_TIMER1_MASK | OPL_TIMER2_MASK);
207 	/* Reset the IRQ of the FM chip */
208 	opl_command(sc, OPL_L, OPL_TIMER_CONTROL, OPL_IRQ_RESET);
209 
210 	/* get status bits */
211 	status1 = bus_space_read_1(sc->iot,sc->ioh,OPL_STATUS+OPL_L+sc->offs);
212 
213 	opl_command(sc, OPL_L, OPL_TIMER1, -2); /* wait 2 ticks */
214 	opl_command(sc, OPL_L, OPL_TIMER_CONTROL, /* start timer1 */
215 		    OPL_TIMER1_START | OPL_TIMER2_MASK);
216 	delay(1000);		/* wait for timer to expire */
217 
218 	/* get status bits again */
219 	status2 = bus_space_read_1(sc->iot,sc->ioh,OPL_STATUS+OPL_L+sc->offs);
220 
221 	opl_command(sc, OPL_L, OPL_TIMER_CONTROL,
222 		    OPL_TIMER1_MASK | OPL_TIMER2_MASK);
223 	opl_command(sc, OPL_L, OPL_TIMER_CONTROL, OPL_IRQ_RESET);
224 
225 	DPRINTFN(2,("opl_find: %02x %02x\n", status1, status2));
226 
227 	if ((status1 & OPL_STATUS_MASK) != 0 ||
228 	    (status2 & OPL_STATUS_MASK) != (OPL_STATUS_IRQ | OPL_STATUS_FT1))
229 		return (0);
230 
231 	switch(status1) {
232 	case 0x00:
233 	case 0x0f:
234 		sc->model = OPL_3;
235 		break;
236 	case 0x06:
237 		sc->model = OPL_2;
238 		break;
239 	default:
240 		return 0;
241 	}
242 
243 	DPRINTFN(2,("opl_find: OPL%d at 0x%x detected\n",
244 		    sc->model, (int)sc->ioh));
245 	return (1);
246 }
247 
248 void
249 opl_set_op_reg(sc, base, voice, op, value)
250 	struct opl_softc *sc;
251 	int base;
252 	int voice;
253 	int op;
254 	u_char value;
255 {
256 	struct opl_voice *v = &sc->voices[voice];
257 	opl_command(sc, v->iooffs, base + v->op[op], value);
258 }
259 
260 void
261 opl_set_ch_reg(sc, base, voice, value)
262 	struct opl_softc *sc;
263 	int base;
264 	int voice;
265 	u_char value;
266 {
267 	struct opl_voice *v = &sc->voices[voice];
268 	opl_command(sc, v->iooffs, base + v->voiceno, value);
269 }
270 
271 
272 void
273 opl_load_patch(sc, v)
274 	struct opl_softc *sc;
275 	int v;
276 {
277 	struct opl_operators *p = sc->voices[v].patch;
278 
279 	opl_set_op_reg(sc, OPL_AM_VIB,          v, 0, p->ops[OO_CHARS+0]);
280 	opl_set_op_reg(sc, OPL_AM_VIB,          v, 1, p->ops[OO_CHARS+1]);
281 	opl_set_op_reg(sc, OPL_KSL_LEVEL,       v, 0, p->ops[OO_KSL_LEV+0]);
282 	opl_set_op_reg(sc, OPL_KSL_LEVEL,       v, 1, p->ops[OO_KSL_LEV+1]);
283 	opl_set_op_reg(sc, OPL_ATTACK_DECAY,    v, 0, p->ops[OO_ATT_DEC+0]);
284 	opl_set_op_reg(sc, OPL_ATTACK_DECAY,    v, 1, p->ops[OO_ATT_DEC+1]);
285 	opl_set_op_reg(sc, OPL_SUSTAIN_RELEASE, v, 0, p->ops[OO_SUS_REL+0]);
286 	opl_set_op_reg(sc, OPL_SUSTAIN_RELEASE, v, 1, p->ops[OO_SUS_REL+1]);
287 	opl_set_op_reg(sc, OPL_WAVE_SELECT,     v, 0, p->ops[OO_WAV_SEL+0]);
288 	opl_set_op_reg(sc, OPL_WAVE_SELECT,     v, 1, p->ops[OO_WAV_SEL+1]);
289 	opl_set_ch_reg(sc, OPL_FEEDBACK_CONNECTION, v, p->ops[OO_FB_CONN]);
290 }
291 
292 #define OPL_FNUM_FAIL 0xffff
293 u_int32_t
294 opl_get_block_fnum(freq)
295 	int freq;
296 {
297 	u_int32_t f_num = freq / 3125;
298 	u_int32_t  block = 0;
299 
300 	while (f_num > 0x3FF && block < 8) {
301 		block++;
302 		f_num >>= 1;
303 	}
304 
305 	if (block > 7)
306 		return (OPL_FNUM_FAIL);
307 	else
308 		return ((block << 10) | f_num);
309   }
310 
311 
312 void
313 opl_reset(sc)
314 	struct opl_softc *sc;
315 {
316 	int i;
317 
318 	for (i = 1; i <= OPL_MAXREG; i++)
319 		opl_command(sc, OPL_L, OPL_KEYON_BLOCK + i, 0);
320 
321 	opl_command(sc, OPL_L, OPL_TEST, OPL_ENABLE_WAVE_SELECT);
322 	opl_command(sc, OPL_L, OPL_PERCUSSION, 0);
323 	if (sc->model == OPL_3) {
324 		opl_command(sc, OPL_R, OPL_MODE, OPL3_ENABLE);
325 		opl_command(sc, OPL_R,OPL_CONNECTION_SELECT,OPL_NOCONNECTION);
326 	}
327 
328 	sc->volume = 64;
329 }
330 
331 int
332 oplsyn_open(ms, flags)
333 	midisyn *ms;
334 	int flags;
335 {
336 	struct opl_softc *sc = ms->data;
337 
338 	DPRINTFN(2, ("oplsyn_open: %d\n", flags));
339 
340 	opl_reset(ms->data);
341 	if (sc->spkrctl)
342 		sc->spkrctl(sc->spkrarg, 1);
343 	return (0);
344 }
345 
346 void
347 oplsyn_close(ms)
348 	midisyn *ms;
349 {
350 	struct opl_softc *sc = ms->data;
351 
352 	DPRINTFN(2, ("oplsyn_close:\n"));
353 
354 	/*opl_reset(ms->data);*/
355 	if (sc->spkrctl)
356 		sc->spkrctl(sc->spkrarg, 0);
357 }
358 
359 #if 0
360 void
361 oplsyn_getinfo(addr, sd)
362 	void *addr;
363 	struct synth_dev *sd;
364 {
365 	struct opl_softc *sc = addr;
366 
367 	sd->name = sc->model == OPL_2 ? "Yamaha OPL2" : "Yamaha OPL3";
368 	sd->type = SYNTH_TYPE_FM;
369 	sd->subtype = sc->model == OPL_2 ? SYNTH_SUB_FM_TYPE_ADLIB
370 		: SYNTH_SUB_FM_TYPE_OPL3;
371 	sd->capabilities = 0;
372 }
373 #endif
374 
375 void
376 oplsyn_reset(addr)
377 	void *addr;
378 {
379 	struct opl_softc *sc = addr;
380 	DPRINTFN(3, ("oplsyn_reset:\n"));
381 	opl_reset(sc);
382 }
383 
384 int8_t opl_volume_table[128] =
385     {-64, -48, -40, -35, -32, -29, -27, -26,
386      -24, -23, -21, -20, -19, -18, -18, -17,
387      -16, -15, -15, -14, -13, -13, -12, -12,
388      -11, -11, -10, -10, -10, -9, -9, -8,
389      -8, -8, -7, -7, -7, -6, -6, -6,
390      -5, -5, -5, -5, -4, -4, -4, -4,
391      -3, -3, -3, -3, -2, -2, -2, -2,
392      -2, -1, -1, -1, -1, 0, 0, 0,
393      0, 0, 0, 1, 1, 1, 1, 1,
394      1, 2, 2, 2, 2, 2, 2, 2,
395      3, 3, 3, 3, 3, 3, 3, 4,
396      4, 4, 4, 4, 4, 4, 4, 5,
397      5, 5, 5, 5, 5, 5, 5, 5,
398      6, 6, 6, 6, 6, 6, 6, 6,
399      6, 7, 7, 7, 7, 7, 7, 7,
400      7, 7, 7, 8, 8, 8, 8, 8};
401 
402 int
403 opl_calc_vol(regbyte, volume, mainvol)
404 	int regbyte;
405 	int volume;
406 	int mainvol;
407 {
408 	int level = ~regbyte & OPL_TOTAL_LEVEL_MASK;
409 
410 	if (mainvol > 127)
411 		mainvol = 127;
412 
413 	volume = (volume * mainvol) / 127;
414 
415 	if (level)
416 		level += opl_volume_table[volume];
417 
418 	if (level > OPL_TOTAL_LEVEL_MASK)
419 		level = OPL_TOTAL_LEVEL_MASK;
420 	if (level < 0)
421 		level = 0;
422 
423 	return (~level & OPL_TOTAL_LEVEL_MASK);
424 }
425 
426 void
427 oplsyn_noteon(ms, voice, freq, vel)
428 	midisyn *ms;
429 	u_int32_t voice, freq, vel;
430 {
431 	struct opl_softc *sc = ms->data;
432 	struct opl_voice *v;
433 	struct opl_operators *p;
434 	u_int32_t block_fnum;
435 	int mult;
436 	int c_mult, m_mult;
437 	u_int8_t chars0, chars1, ksl0, ksl1, fbc;
438 	u_int8_t r20m, r20c, r40m, r40c, rA0, rB0;
439 	u_int8_t vol0, vol1;
440 
441 	DPRINTFN(3, ("oplsyn_noteon: %p %d %d\n", sc, voice,
442 		     MIDISYN_FREQ_TO_HZ(freq)));
443 
444 #ifdef DIAGNOSTIC
445 	if (voice < 0 || voice >= sc->syn.nvoice) {
446 		printf("oplsyn_noteon: bad voice %d\n", voice);
447 		return;
448 	}
449 #endif
450 	/* Turn off old note */
451 	opl_set_op_reg(sc, OPL_KSL_LEVEL,   voice, 0, 0xff);
452 	opl_set_op_reg(sc, OPL_KSL_LEVEL,   voice, 1, 0xff);
453 	opl_set_ch_reg(sc, OPL_KEYON_BLOCK, voice,    0);
454 
455 	v = &sc->voices[voice];
456 
457 	p = &opl2_instrs[MS_GETPGM(ms, voice)];
458 	v->patch = p;
459 	opl_load_patch(sc, voice);
460 
461 	mult = 1;
462 	for (;;) {
463 		block_fnum = opl_get_block_fnum(freq / mult);
464 		if (block_fnum != OPL_FNUM_FAIL)
465 			break;
466 		mult *= 2;
467 		if (mult == 16)
468 			mult = 15;
469 	}
470 
471 	chars0 = p->ops[OO_CHARS+0];
472 	chars1 = p->ops[OO_CHARS+1];
473 	m_mult = (chars0 & OPL_MULTIPLE_MASK) * mult;
474 	c_mult = (chars1 & OPL_MULTIPLE_MASK) * mult;
475 	if ((block_fnum == OPL_FNUM_FAIL) || (m_mult > 15) || (c_mult > 15)) {
476 		printf("oplsyn_noteon: frequence out of range %d\n",
477 		       MIDISYN_FREQ_TO_HZ(freq));
478 		return;
479 	}
480 	r20m = (chars0 &~ OPL_MULTIPLE_MASK) | m_mult;
481 	r20c = (chars1 &~ OPL_MULTIPLE_MASK) | c_mult;
482 
483 	/* 2 voice */
484 	ksl0 = p->ops[OO_KSL_LEV+0];
485 	ksl1 = p->ops[OO_KSL_LEV+1];
486 	if (p->ops[OO_FB_CONN] & 0x01) {
487 		vol0 = opl_calc_vol(ksl0, vel, sc->volume);
488 		vol1 = opl_calc_vol(ksl1, vel, sc->volume);
489 	} else {
490 		vol0 = ksl0;
491 		vol1 = opl_calc_vol(ksl1, vel, sc->volume);
492 	}
493 	r40m = (ksl0 & OPL_KSL_MASK) | vol0;
494 	r40c = (ksl1 & OPL_KSL_MASK) | vol1;
495 
496 	rA0  = block_fnum & 0xFF;
497 	rB0  = (block_fnum >> 8) | OPL_KEYON_BIT;
498 
499 	v->rB0 = rB0;
500 
501 	fbc = p->ops[OO_FB_CONN];
502 	if (sc->model == OPL_3) {
503 		fbc &= ~OPL_STEREO_BITS;
504 		/* XXX use pan */
505 		fbc |= OPL_VOICE_TO_LEFT | OPL_VOICE_TO_RIGHT;
506 	}
507 	opl_set_ch_reg(sc, OPL_FEEDBACK_CONNECTION, voice, fbc);
508 
509 	opl_set_op_reg(sc, OPL_AM_VIB,      voice, 0, r20m);
510 	opl_set_op_reg(sc, OPL_AM_VIB,      voice, 1, r20c);
511 	opl_set_op_reg(sc, OPL_KSL_LEVEL,   voice, 0, r40m);
512 	opl_set_op_reg(sc, OPL_KSL_LEVEL,   voice, 1, r40c);
513 	opl_set_ch_reg(sc, OPL_FNUM_LOW,    voice,    rA0);
514 	opl_set_ch_reg(sc, OPL_KEYON_BLOCK, voice,    rB0);
515 }
516 
517 void
518 oplsyn_noteoff(ms, voice, note, vel)
519 	midisyn *ms;
520 	u_int32_t voice, note, vel;
521 {
522 	struct opl_softc *sc = ms->data;
523 	struct opl_voice *v;
524 
525 	DPRINTFN(3, ("oplsyn_noteoff: %p %d %d\n", sc, voice,
526 		     MIDISYN_FREQ_TO_HZ(note)));
527 
528 #ifdef DIAGNOSTIC
529 	if (voice < 0 || voice >= sc->syn.nvoice) {
530 		printf("oplsyn_noteoff: bad voice %d\n", voice);
531 		return;
532 	}
533 #endif
534 	v = &sc->voices[voice];
535 	opl_set_ch_reg(sc, 0xB0, voice, v->rB0 & ~OPL_KEYON_BIT);
536 }
537 
538 void
539 oplsyn_keypressure(ms, voice, note, vel)
540 	midisyn *ms;
541 	u_int32_t voice, note, vel;
542 {
543 #ifdef AUDIO_DEBUG
544 	struct opl_softc *sc = ms->data;
545 	DPRINTFN(1, ("oplsyn_keypressure: %p %d\n", sc, note));
546 #endif
547 }
548 
549 void
550 oplsyn_ctlchange(ms, voice, parm, w14)
551 	midisyn *ms;
552 	u_int32_t voice, parm, w14;
553 {
554 #ifdef AUDIO_DEBUG
555 	struct opl_softc *sc = ms->data;
556 	DPRINTFN(1, ("oplsyn_ctlchange: %p %d\n", sc, voice));
557 #endif
558 }
559 
560 void
561 oplsyn_pitchbend(ms, voice, parm, x)
562 	midisyn *ms;
563 	u_int32_t voice, parm, x;
564 {
565 #ifdef AUDIO_DEBUG
566 	struct opl_softc *sc = ms->data;
567 	DPRINTFN(1, ("oplsyn_pitchbend: %p %d\n", sc, voice));
568 #endif
569 }
570 
571 void
572 oplsyn_loadpatch(ms, sysex, uio)
573 	midisyn *ms;
574 	struct sysex_info *sysex;
575 	struct uio *uio;
576 {
577 #if 0
578 	struct opl_softc *sc = ms->data;
579 	struct sbi_instrument ins;
580 
581 	DPRINTFN(1, ("oplsyn_loadpatch: %p\n", sc));
582 
583 	memcpy(&ins, sysex, sizeof *sysex);
584 	if (uio->uio_resid >= sizeof ins - sizeof *sysex)
585 		return EINVAL;
586 	uiomove((char *)&ins + sizeof *sysex, sizeof ins - sizeof *sysex, uio);
587 	/* XXX */
588 #endif
589 }
590