1 /* $NetBSD: cms.c,v 1.17 2008/03/16 22:30:31 cube Exp $ */
4 * Copyright (c) 2000 The NetBSD Foundation, Inc.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
29 #include <sys/cdefs.h>
30 __KERNEL_RCSID(0, "$NetBSD: cms.c,v 1.17 2008/03/16 22:30:31 cube Exp $");
32 #include <sys/param.h>
33 #include <sys/systm.h>
34 #include <sys/kernel.h>
35 #include <sys/device.h>
36 #include <sys/select.h>
40 #include <sys/audioio.h>
41 #include <dev/audio_if.h>
42 #include <dev/audiovar.h>
44 #include <sys/midiio.h>
45 #include <dev/midi_if.h>
46 #include <dev/midivar.h>
47 #include <dev/midisynvar.h>
49 #include <dev/isa/isareg.h>
50 #include <dev/isa/isavar.h>
51 #include <dev/isa/cmsreg.h>
54 #define DPRINTF(x) if (cmsdebug) printf x
61 struct midi_softc sc_mididev
;
63 bus_space_tag_t sc_iot
;
64 bus_space_handle_t sc_ioh
;
66 /* shadow registers for each chip */
67 u_int8_t sc_shadowregs
[32*2];
71 int cms_probe(device_t
, cfdata_t
, void *);
72 void cms_attach(device_t
, device_t
, void *);
74 CFATTACH_DECL_NEW(cms
, sizeof(struct cms_softc
),
75 cms_probe
, cms_attach
, NULL
, NULL
);
77 int cms_open(midisyn
*, int);
78 void cms_close(midisyn
*);
79 void cms_on(midisyn
*, uint_fast16_t, midipitch_t
, int16_t);
80 void cms_off(midisyn
*, uint_fast16_t, uint_fast8_t);
82 struct midisyn_methods midi_cms_hw
= {
89 static void cms_reset(struct cms_softc
*);
91 static char cms_note_table
[] = {
106 #define NOTE_TO_OCTAVE(note) (((note)-CMS_FIRST_NOTE)/12)
107 #define NOTE_TO_COUNT(note) cms_note_table[(((note)-CMS_FIRST_NOTE)%12)]
110 cms_probe(device_t parent
, cfdata_t match
, void *aux
)
112 struct isa_attach_args
*ia
= aux
;
114 bus_space_handle_t ioh
;
118 DPRINTF(("cms_probe():\n"));
125 if (ISA_DIRECT_CONFIG(ia
))
128 if (ia
->ia_io
[0].ir_addr
== ISA_UNKNOWN_PORT
)
131 if (bus_space_map(iot
, ia
->ia_io
[0].ir_addr
, CMS_IOSIZE
, 0, &ioh
))
134 bus_space_write_1(iot
, ioh
, CMS_WREG
, 0xaa);
135 if (bus_space_read_1(iot
, ioh
, CMS_RREG
) != 0xaa)
138 for (i
= 0; i
< 8; i
++) {
139 if (bus_space_read_1(iot
, ioh
, CMS_MREG
) != 0x7f)
145 ia
->ia_io
[0].ir_size
= CMS_IOSIZE
;
152 bus_space_unmap(iot
, ioh
, CMS_IOSIZE
);
159 cms_attach(device_t parent
, device_t self
, void *aux
)
161 struct cms_softc
*sc
= device_private(self
);
162 struct isa_attach_args
*ia
= aux
;
164 bus_space_handle_t ioh
;
166 struct audio_attach_args arg
;
168 sc
->sc_mididev
.dev
= self
;
172 DPRINTF(("cms_attach():\n"));
176 if (bus_space_map(iot
, ia
->ia_io
[0].ir_addr
, CMS_IOSIZE
, 0, &ioh
)) {
177 aprint_error_dev(self
, "can't map i/o space\n");
184 /* now let's reset the chips */
187 ms
= &sc
->sc_midisyn
;
188 ms
->mets
= &midi_cms_hw
;
189 strcpy(ms
->name
, "Creative Music System");
190 ms
->nvoice
= CMS_NVOICES
;
193 /* use the synthesiser */
194 midisyn_attach(&sc
->sc_mididev
, ms
);
196 /* now attach the midi device to the synthesiser */
197 arg
.type
= AUDIODEV_TYPE_MIDI
;
198 arg
.hwif
= sc
->sc_mididev
.hw_if
;
199 arg
.hdl
= sc
->sc_mididev
.hw_hdl
;
200 config_found(self
, &arg
, 0);
205 cms_open(midisyn
*ms
, int flag
)
207 struct cms_softc
*sc
= (struct cms_softc
*)ms
->data
;
215 cms_close(midisyn
*ms
)
217 struct cms_softc
*sc
= (struct cms_softc
*)ms
->data
;
223 cms_on(midisyn
*ms
, uint_fast16_t vidx
, midipitch_t mp
, int16_t level_cB
)
225 struct cms_softc
*sc
= (struct cms_softc
*)ms
->data
;
226 int chip
= CHAN_TO_CHIP(vidx
);
227 int voice
= CHAN_TO_VOICE(vidx
);
235 * The next line is a regrettable hack, because it drops all pitch
236 * adjustment midisyn has supplied in miditune, so this synth will
237 * not respond to tuning, pitchbend, etc. It seems it ought to be
238 * possible to DTRT if the formula that generated the cms_note_table
239 * can be found, but I've had no luck, and a plot of the numbers in
240 * the table clearly curves the wrong way to be derived any obvious
241 * way from the equal tempered scale. (Or maybe the table's wrong?
242 * Has this device been playing flat up the scale? I don't have
243 * access to one to try.)
245 note
= MIDIPITCH_TO_KEY(mp
);
247 if (note
< CMS_FIRST_NOTE
)
250 octave
= NOTE_TO_OCTAVE(note
);
251 count
= NOTE_TO_COUNT(note
);
253 DPRINTF(("chip=%d voice=%d octave=%d count=%d offset=%d shift=%d\n",
254 chip
, voice
, octave
, count
, OCTAVE_OFFSET(voice
),
255 OCTAVE_SHIFT(voice
)));
257 /* write the count */
258 CMS_WRITE(sc
, chip
, CMS_IREG_FREQ0
+ voice
, count
);
260 /* select the octave */
261 reg
= CMS_READ(sc
, chip
, CMS_IREG_OCTAVE_1_0
+ OCTAVE_OFFSET(voice
));
262 reg
&= ~(0x0f<<OCTAVE_SHIFT(voice
));
263 reg
|= ((octave
&0x7)<<OCTAVE_SHIFT(voice
));
264 CMS_WRITE(sc
, chip
, CMS_IREG_OCTAVE_1_0
+ OCTAVE_OFFSET(voice
), reg
);
267 /* this may be the wrong curve but will do something. no docs! */
268 vol
= 15 + (level_cB
> -75) ? level_cB
/5 : -15;
269 CMS_WRITE(sc
, chip
, CMS_IREG_VOL0
+ voice
, ((vol
<<4)|vol
));
271 /* enable the voice */
272 reg
= CMS_READ(sc
, chip
, CMS_IREG_FREQ_CTL
);
274 CMS_WRITE(sc
, chip
, CMS_IREG_FREQ_CTL
, reg
);
278 cms_off(midisyn
*ms
, uint_fast16_t vidx
, uint_fast8_t vel
)
280 struct cms_softc
*sc
= (struct cms_softc
*)ms
->data
;
281 int chip
= CHAN_TO_CHIP(vidx
);
282 int voice
= CHAN_TO_VOICE(vidx
);
285 /* disable the channel */
286 reg
= CMS_READ(sc
, chip
, CMS_IREG_FREQ_CTL
);
288 CMS_WRITE(sc
, chip
, CMS_IREG_FREQ_CTL
, reg
);
292 cms_reset(struct cms_softc
*sc
)
296 DPRINTF(("cms_reset():\n"));
298 for (i
= 0; i
< 6; i
++) {
299 CMS_WRITE(sc
, 0, CMS_IREG_VOL0
+i
, 0x00);
300 CMS_WRITE(sc
, 1, CMS_IREG_VOL0
+i
, 0x00);
302 CMS_WRITE(sc
, 0, CMS_IREG_FREQ0
+i
, 0x00);
303 CMS_WRITE(sc
, 1, CMS_IREG_FREQ0
+i
, 0x00);
306 for (i
= 0; i
< 3; i
++) {
307 CMS_WRITE(sc
, 0, CMS_IREG_OCTAVE_1_0
+i
, 0x00);
308 CMS_WRITE(sc
, 1, CMS_IREG_OCTAVE_1_0
+i
, 0x00);
311 CMS_WRITE(sc
, 0, CMS_IREG_FREQ_CTL
, 0x00);
312 CMS_WRITE(sc
, 1, CMS_IREG_FREQ_CTL
, 0x00);
314 CMS_WRITE(sc
, 0, CMS_IREG_NOISE_CTL
, 0x00);
315 CMS_WRITE(sc
, 1, CMS_IREG_NOISE_CTL
, 0x00);
317 CMS_WRITE(sc
, 0, CMS_IREG_NOISE_BW
, 0x00);
318 CMS_WRITE(sc
, 1, CMS_IREG_NOISE_BW
, 0x00);
321 * These registers don't appear to be useful, but must be
322 * cleared otherwise certain voices don't work properly
324 CMS_WRITE(sc
, 0, 0x18, 0x00);
325 CMS_WRITE(sc
, 1, 0x18, 0x00);
326 CMS_WRITE(sc
, 0, 0x19, 0x00);
327 CMS_WRITE(sc
, 1, 0x19, 0x00);
329 CMS_WRITE(sc
, 0, CMS_IREG_SYS_CTL
, CMS_IREG_SYS_RESET
);
330 CMS_WRITE(sc
, 1, CMS_IREG_SYS_CTL
, CMS_IREG_SYS_RESET
);
332 CMS_WRITE(sc
, 0, CMS_IREG_SYS_CTL
, CMS_IREG_SYS_ENBL
);
333 CMS_WRITE(sc
, 1, CMS_IREG_SYS_CTL
, CMS_IREG_SYS_ENBL
);