emuxki.c revision 1.60 1 1.60 jmcneill /* $NetBSD: emuxki.c,v 1.60 2011/11/23 23:07:35 jmcneill Exp $ */
2 1.1 jdolecek
3 1.1 jdolecek /*-
4 1.60 jmcneill * Copyright (c) 2001, 2007 The NetBSD Foundation, Inc.
5 1.1 jdolecek * All rights reserved.
6 1.1 jdolecek *
7 1.1 jdolecek * This code is derived from software contributed to The NetBSD Foundation
8 1.60 jmcneill * by Yannick Montulet, and by Andrew Doran.
9 1.1 jdolecek *
10 1.1 jdolecek * Redistribution and use in source and binary forms, with or without
11 1.1 jdolecek * modification, are permitted provided that the following conditions
12 1.1 jdolecek * are met:
13 1.1 jdolecek * 1. Redistributions of source code must retain the above copyright
14 1.1 jdolecek * notice, this list of conditions and the following disclaimer.
15 1.1 jdolecek * 2. Redistributions in binary form must reproduce the above copyright
16 1.1 jdolecek * notice, this list of conditions and the following disclaimer in the
17 1.1 jdolecek * documentation and/or other materials provided with the distribution.
18 1.1 jdolecek *
19 1.1 jdolecek * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 1.1 jdolecek * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 1.1 jdolecek * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 1.1 jdolecek * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 1.1 jdolecek * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 1.1 jdolecek * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 1.1 jdolecek * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 1.1 jdolecek * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 1.1 jdolecek * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 1.1 jdolecek * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 1.1 jdolecek * POSSIBILITY OF SUCH DAMAGE.
30 1.1 jdolecek */
31 1.1 jdolecek
32 1.1 jdolecek /*
33 1.1 jdolecek * Driver for Creative Labs SBLive! series and probably PCI512.
34 1.40 kent *
35 1.1 jdolecek * Known bugs:
36 1.1 jdolecek * - inversed stereo at ac97 codec level
37 1.1 jdolecek * (XXX jdolecek - don't see the problem? maybe because auvia(4) has
38 1.1 jdolecek * it swapped too?)
39 1.37 dsainty * - bass disappear when you plug rear jack-in on Cambridge FPS2000 speakers
40 1.1 jdolecek * (and presumably all speakers that support front and rear jack-in)
41 1.1 jdolecek *
42 1.1 jdolecek * TODO:
43 1.1 jdolecek * - Digital Outputs
44 1.1 jdolecek * - (midi/mpu),joystick support
45 1.1 jdolecek * - Multiple voices play (problem with /dev/audio architecture)
46 1.1 jdolecek * - Multiple sources recording (Pb with audio(4))
47 1.37 dsainty * - Independent modification of each channel's parameters (via mixer ?)
48 1.1 jdolecek * - DSP FX patches (to make fx like chipmunk)
49 1.1 jdolecek */
50 1.4 lukem
51 1.4 lukem #include <sys/cdefs.h>
52 1.60 jmcneill __KERNEL_RCSID(0, "$NetBSD: emuxki.c,v 1.60 2011/11/23 23:07:35 jmcneill Exp $");
53 1.1 jdolecek
54 1.5 lukem #include <sys/param.h>
55 1.1 jdolecek #include <sys/device.h>
56 1.1 jdolecek #include <sys/errno.h>
57 1.1 jdolecek #include <sys/systm.h>
58 1.1 jdolecek #include <sys/audioio.h>
59 1.1 jdolecek #include <sys/select.h>
60 1.60 jmcneill #include <sys/mutex.h>
61 1.60 jmcneill #include <sys/kmem.h>
62 1.60 jmcneill #include <sys/malloc.h>
63 1.60 jmcneill
64 1.1 jdolecek #include <dev/audio_if.h>
65 1.1 jdolecek #include <dev/audiovar.h>
66 1.1 jdolecek #include <dev/auconv.h>
67 1.1 jdolecek #include <dev/mulaw.h>
68 1.60 jmcneill
69 1.1 jdolecek #include <dev/ic/ac97reg.h>
70 1.1 jdolecek #include <dev/ic/ac97var.h>
71 1.1 jdolecek
72 1.60 jmcneill #include <dev/pci/pcireg.h>
73 1.60 jmcneill #include <dev/pci/pcivar.h>
74 1.60 jmcneill #include <dev/pci/pcidevs.h>
75 1.1 jdolecek #include <dev/pci/emuxkireg.h>
76 1.1 jdolecek #include <dev/pci/emuxkivar.h>
77 1.1 jdolecek
78 1.26 wiz /* autoconf goo */
79 1.56 cegger static int emuxki_match(device_t, cfdata_t, void *);
80 1.56 cegger static void emuxki_attach(device_t, device_t, void *);
81 1.56 cegger static int emuxki_detach(device_t, int);
82 1.1 jdolecek
83 1.26 wiz /* DMA mem mgmt */
84 1.3 jdolecek static struct dmamem *dmamem_alloc(bus_dma_tag_t, size_t, bus_size_t,
85 1.60 jmcneill int);
86 1.60 jmcneill static void dmamem_free(struct dmamem *);
87 1.1 jdolecek
88 1.1 jdolecek /* Emu10k1 init & shutdown */
89 1.40 kent static int emuxki_init(struct emuxki_softc *);
90 1.40 kent static void emuxki_shutdown(struct emuxki_softc *);
91 1.1 jdolecek
92 1.1 jdolecek /* Emu10k1 mem mgmt */
93 1.60 jmcneill static void *emuxki_pmem_alloc(struct emuxki_softc *, size_t);
94 1.60 jmcneill static void *emuxki_rmem_alloc(struct emuxki_softc *, size_t);
95 1.1 jdolecek
96 1.1 jdolecek /*
97 1.1 jdolecek * Emu10k1 channels funcs : There is no direct access to channels, everything
98 1.1 jdolecek * is done through voices I will at least provide channel based fx params
99 1.1 jdolecek * modification, later...
100 1.1 jdolecek */
101 1.1 jdolecek
102 1.1 jdolecek /* Emu10k1 voice mgmt */
103 1.3 jdolecek static struct emuxki_voice *emuxki_voice_new(struct emuxki_softc *,
104 1.40 kent uint8_t);
105 1.40 kent static void emuxki_voice_delete(struct emuxki_voice *);
106 1.60 jmcneill static int emuxki_voice_set_audioparms(struct emuxki_softc *,
107 1.60 jmcneill struct emuxki_voice *, uint8_t,
108 1.60 jmcneill uint8_t, uint32_t);
109 1.1 jdolecek /* emuxki_voice_set_fxparms will come later, it'll need channel distinction */
110 1.40 kent static int emuxki_voice_set_bufparms(struct emuxki_voice *,
111 1.40 kent void *, uint32_t, uint16_t);
112 1.40 kent static void emuxki_voice_commit_parms(struct emuxki_voice *);
113 1.40 kent static int emuxki_voice_adc_rate(struct emuxki_voice *);
114 1.40 kent static uint32_t emuxki_voice_curaddr(struct emuxki_voice *);
115 1.40 kent static void emuxki_voice_start(struct emuxki_voice *,
116 1.40 kent void (*) (void *), void *);
117 1.40 kent static void emuxki_voice_halt(struct emuxki_voice *);
118 1.1 jdolecek
119 1.1 jdolecek /*
120 1.1 jdolecek * Emu10k1 stream mgmt : not done yet
121 1.1 jdolecek */
122 1.1 jdolecek #if 0
123 1.3 jdolecek static struct emuxki_stream *emuxki_stream_new(struct emu10k1 *);
124 1.40 kent static void emuxki_stream_delete(struct emuxki_stream *);
125 1.40 kent static int emuxki_stream_set_audio_params(struct emuxki_stream *,
126 1.40 kent uint8_t, uint8_t, uint8_t, uint16_t);
127 1.40 kent static void emuxki_stream_start(struct emuxki_stream *);
128 1.40 kent static void emuxki_stream_halt(struct emuxki_stream *);
129 1.1 jdolecek #endif
130 1.1 jdolecek
131 1.1 jdolecek /* audio interface callbacks */
132 1.1 jdolecek
133 1.3 jdolecek static int emuxki_open(void *, int);
134 1.3 jdolecek static void emuxki_close(void *);
135 1.1 jdolecek
136 1.3 jdolecek static int emuxki_query_encoding(void *, struct audio_encoding *);
137 1.39 kent static int emuxki_set_params(void *, int, int, audio_params_t *,
138 1.40 kent audio_params_t *, stream_filter_list_t *,
139 1.40 kent stream_filter_list_t *);
140 1.1 jdolecek
141 1.39 kent static int emuxki_round_blocksize(void *, int, int, const audio_params_t *);
142 1.3 jdolecek static size_t emuxki_round_buffersize(void *, int, size_t);
143 1.1 jdolecek
144 1.3 jdolecek static int emuxki_trigger_output(void *, void *, void *, int,
145 1.40 kent void (*)(void *), void *, const audio_params_t *);
146 1.3 jdolecek static int emuxki_trigger_input(void *, void *, void *, int,
147 1.40 kent void (*) (void *), void *, const audio_params_t *);
148 1.3 jdolecek static int emuxki_halt_output(void *);
149 1.3 jdolecek static int emuxki_halt_input(void *);
150 1.3 jdolecek
151 1.3 jdolecek static int emuxki_getdev(void *, struct audio_device *);
152 1.3 jdolecek static int emuxki_set_port(void *, mixer_ctrl_t *);
153 1.3 jdolecek static int emuxki_get_port(void *, mixer_ctrl_t *);
154 1.3 jdolecek static int emuxki_query_devinfo(void *, mixer_devinfo_t *);
155 1.1 jdolecek
156 1.60 jmcneill static void *emuxki_allocm(void *, int, size_t);
157 1.60 jmcneill static void emuxki_freem(void *, void *, size_t);
158 1.1 jdolecek
159 1.3 jdolecek static paddr_t emuxki_mappage(void *, void *, off_t, int);
160 1.3 jdolecek static int emuxki_get_props(void *);
161 1.60 jmcneill static void emuxki_get_locks(void *, kmutex_t **, kmutex_t **);
162 1.1 jdolecek
163 1.1 jdolecek /* Interrupt handler */
164 1.40 kent static int emuxki_intr(void *);
165 1.1 jdolecek
166 1.1 jdolecek /* Emu10k1 AC97 interface callbacks */
167 1.40 kent static int emuxki_ac97_attach(void *, struct ac97_codec_if *);
168 1.40 kent static int emuxki_ac97_read(void *, uint8_t, uint16_t *);
169 1.40 kent static int emuxki_ac97_write(void *, uint8_t, uint16_t);
170 1.40 kent static int emuxki_ac97_reset(void *);
171 1.6 jdolecek static enum ac97_host_flags emuxki_ac97_flags(void *);
172 1.1 jdolecek
173 1.1 jdolecek /*
174 1.1 jdolecek * Autoconfig goo.
175 1.1 jdolecek */
176 1.58 tsutsui CFATTACH_DECL_NEW(emuxki, sizeof(struct emuxki_softc),
177 1.12 thorpej emuxki_match, emuxki_attach, emuxki_detach, NULL);
178 1.1 jdolecek
179 1.38 yamt static const struct audio_hw_if emuxki_hw_if = {
180 1.1 jdolecek emuxki_open,
181 1.1 jdolecek emuxki_close,
182 1.1 jdolecek NULL, /* drain */
183 1.1 jdolecek emuxki_query_encoding,
184 1.1 jdolecek emuxki_set_params,
185 1.19 toshii emuxki_round_blocksize,
186 1.1 jdolecek NULL, /* commit settings */
187 1.1 jdolecek NULL, /* init_output */
188 1.1 jdolecek NULL, /* init_input */
189 1.1 jdolecek NULL, /* start_output */
190 1.1 jdolecek NULL, /* start_input */
191 1.1 jdolecek emuxki_halt_output,
192 1.1 jdolecek emuxki_halt_input,
193 1.1 jdolecek NULL, /* speaker_ctl */
194 1.1 jdolecek emuxki_getdev,
195 1.1 jdolecek NULL, /* setfd */
196 1.1 jdolecek emuxki_set_port,
197 1.1 jdolecek emuxki_get_port,
198 1.1 jdolecek emuxki_query_devinfo,
199 1.1 jdolecek emuxki_allocm,
200 1.1 jdolecek emuxki_freem,
201 1.1 jdolecek emuxki_round_buffersize,
202 1.1 jdolecek emuxki_mappage,
203 1.1 jdolecek emuxki_get_props,
204 1.1 jdolecek emuxki_trigger_output,
205 1.1 jdolecek emuxki_trigger_input,
206 1.1 jdolecek NULL, /* dev_ioctl */
207 1.60 jmcneill emuxki_get_locks,
208 1.1 jdolecek };
209 1.1 jdolecek
210 1.20 fvdl #if 0
211 1.19 toshii static const int emuxki_recsrc_intrmasks[EMU_NUMRECSRCS] =
212 1.19 toshii { EMU_INTE_MICBUFENABLE, EMU_INTE_ADCBUFENABLE, EMU_INTE_EFXBUFENABLE };
213 1.20 fvdl #endif
214 1.40 kent static const uint32_t emuxki_recsrc_bufaddrreg[EMU_NUMRECSRCS] =
215 1.19 toshii { EMU_MICBA, EMU_ADCBA, EMU_FXBA };
216 1.40 kent static const uint32_t emuxki_recsrc_szreg[EMU_NUMRECSRCS] =
217 1.19 toshii { EMU_MICBS, EMU_ADCBS, EMU_FXBS };
218 1.19 toshii static const int emuxki_recbuf_sz[] = {
219 1.19 toshii 0, 384, 448, 512, 640, 768, 896, 1024, 1280, 1536, 1792,
220 1.19 toshii 2048, 2560, 3072, 3584, 4096, 5120, 6144, 7168, 8192, 10240,
221 1.19 toshii 12288, 14366, 16384, 20480, 24576, 28672, 32768, 40960, 49152,
222 1.19 toshii 57344, 65536
223 1.19 toshii };
224 1.19 toshii
225 1.39 kent #define EMUXKI_NFORMATS 4
226 1.39 kent static const struct audio_format emuxki_formats[EMUXKI_NFORMATS] = {
227 1.39 kent {NULL, AUMODE_PLAY | AUMODE_RECORD, AUDIO_ENCODING_SLINEAR_LE, 16, 16,
228 1.39 kent 2, AUFMT_STEREO, 0, {4000, 48000}},
229 1.39 kent {NULL, AUMODE_PLAY | AUMODE_RECORD, AUDIO_ENCODING_SLINEAR_LE, 16, 16,
230 1.39 kent 1, AUFMT_MONAURAL, 0, {4000, 48000}},
231 1.39 kent {NULL, AUMODE_PLAY, AUDIO_ENCODING_ULINEAR_LE, 8, 8,
232 1.39 kent 2, AUFMT_STEREO, 0, {4000, 48000}},
233 1.39 kent {NULL, AUMODE_PLAY, AUDIO_ENCODING_ULINEAR_LE, 8, 8,
234 1.39 kent 1, AUFMT_MONAURAL, 0, {4000, 48000}},
235 1.39 kent };
236 1.39 kent
237 1.1 jdolecek /*
238 1.26 wiz * DMA memory mgmt
239 1.1 jdolecek */
240 1.1 jdolecek
241 1.1 jdolecek static void
242 1.60 jmcneill dmamem_delete(struct dmamem *mem)
243 1.1 jdolecek {
244 1.40 kent
245 1.60 jmcneill kmem_free(mem->segs, mem->nsegs * sizeof(*(mem->segs)));
246 1.60 jmcneill kmem_free(mem, sizeof(*mem));
247 1.1 jdolecek }
248 1.1 jdolecek
249 1.1 jdolecek static struct dmamem *
250 1.60 jmcneill dmamem_alloc(bus_dma_tag_t dmat, size_t size, bus_size_t align, int nsegs)
251 1.1 jdolecek {
252 1.1 jdolecek struct dmamem *mem;
253 1.1 jdolecek
254 1.1 jdolecek /* Allocate memory for structure */
255 1.60 jmcneill if ((mem = kmem_alloc(sizeof(*mem), KM_SLEEP)) == NULL)
256 1.40 kent return NULL;
257 1.1 jdolecek mem->dmat = dmat;
258 1.1 jdolecek mem->size = size;
259 1.1 jdolecek mem->align = align;
260 1.1 jdolecek mem->nsegs = nsegs;
261 1.1 jdolecek mem->bound = 0;
262 1.1 jdolecek
263 1.60 jmcneill mem->segs = kmem_alloc(mem->nsegs * sizeof(*(mem->segs)), KM_SLEEP);
264 1.1 jdolecek if (mem->segs == NULL) {
265 1.60 jmcneill kmem_free(mem, sizeof(*mem));
266 1.40 kent return NULL;
267 1.1 jdolecek }
268 1.1 jdolecek
269 1.1 jdolecek if (bus_dmamem_alloc(dmat, mem->size, mem->align, mem->bound,
270 1.1 jdolecek mem->segs, mem->nsegs, &(mem->rsegs),
271 1.60 jmcneill BUS_DMA_WAITOK)) {
272 1.60 jmcneill dmamem_delete(mem);
273 1.40 kent return NULL;
274 1.1 jdolecek }
275 1.1 jdolecek
276 1.1 jdolecek if (bus_dmamem_map(dmat, mem->segs, mem->nsegs, mem->size,
277 1.60 jmcneill &(mem->kaddr), BUS_DMA_WAITOK | BUS_DMA_COHERENT)) {
278 1.1 jdolecek bus_dmamem_free(dmat, mem->segs, mem->nsegs);
279 1.60 jmcneill dmamem_delete(mem);
280 1.40 kent return NULL;
281 1.1 jdolecek }
282 1.1 jdolecek
283 1.1 jdolecek if (bus_dmamap_create(dmat, mem->size, mem->nsegs, mem->size,
284 1.60 jmcneill mem->bound, BUS_DMA_WAITOK, &(mem->map))) {
285 1.1 jdolecek bus_dmamem_unmap(dmat, mem->kaddr, mem->size);
286 1.1 jdolecek bus_dmamem_free(dmat, mem->segs, mem->nsegs);
287 1.60 jmcneill dmamem_delete(mem);
288 1.40 kent return NULL;
289 1.1 jdolecek }
290 1.1 jdolecek
291 1.40 kent if (bus_dmamap_load(dmat, mem->map, mem->kaddr,
292 1.60 jmcneill mem->size, NULL, BUS_DMA_WAITOK)) {
293 1.1 jdolecek bus_dmamap_destroy(dmat, mem->map);
294 1.1 jdolecek bus_dmamem_unmap(dmat, mem->kaddr, mem->size);
295 1.1 jdolecek bus_dmamem_free(dmat, mem->segs, mem->nsegs);
296 1.60 jmcneill dmamem_delete(mem);
297 1.40 kent return NULL;
298 1.1 jdolecek }
299 1.1 jdolecek
300 1.40 kent return mem;
301 1.1 jdolecek }
302 1.1 jdolecek
303 1.1 jdolecek static void
304 1.60 jmcneill dmamem_free(struct dmamem *mem)
305 1.1 jdolecek {
306 1.40 kent
307 1.1 jdolecek bus_dmamap_unload(mem->dmat, mem->map);
308 1.1 jdolecek bus_dmamap_destroy(mem->dmat, mem->map);
309 1.1 jdolecek bus_dmamem_unmap(mem->dmat, mem->kaddr, mem->size);
310 1.1 jdolecek bus_dmamem_free(mem->dmat, mem->segs, mem->nsegs);
311 1.60 jmcneill dmamem_delete(mem);
312 1.1 jdolecek }
313 1.1 jdolecek
314 1.1 jdolecek
315 1.1 jdolecek /*
316 1.1 jdolecek * Autoconf device callbacks : attach and detach
317 1.1 jdolecek */
318 1.1 jdolecek
319 1.1 jdolecek static void
320 1.1 jdolecek emuxki_pci_shutdown(struct emuxki_softc *sc)
321 1.1 jdolecek {
322 1.40 kent
323 1.1 jdolecek if (sc->sc_ih != NULL)
324 1.1 jdolecek pci_intr_disestablish(sc->sc_pc, sc->sc_ih);
325 1.1 jdolecek if (sc->sc_ios)
326 1.1 jdolecek bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_ios);
327 1.1 jdolecek }
328 1.1 jdolecek
329 1.1 jdolecek static int
330 1.1 jdolecek emuxki_scinit(struct emuxki_softc *sc)
331 1.1 jdolecek {
332 1.40 kent int err;
333 1.1 jdolecek
334 1.1 jdolecek bus_space_write_4(sc->sc_iot, sc->sc_ioh, EMU_HCFG,
335 1.1 jdolecek EMU_HCFG_LOCKSOUNDCACHE | EMU_HCFG_LOCKTANKCACHE_MASK |
336 1.1 jdolecek EMU_HCFG_MUTEBUTTONENABLE);
337 1.1 jdolecek bus_space_write_4(sc->sc_iot, sc->sc_ioh, EMU_INTE,
338 1.1 jdolecek EMU_INTE_SAMPLERATER | EMU_INTE_PCIERRENABLE);
339 1.1 jdolecek
340 1.1 jdolecek if ((err = emuxki_init(sc)))
341 1.40 kent return err;
342 1.1 jdolecek
343 1.35 christos if (sc->sc_type & EMUXKI_AUDIGY2) {
344 1.35 christos bus_space_write_4(sc->sc_iot, sc->sc_ioh, EMU_HCFG,
345 1.35 christos EMU_HCFG_AUDIOENABLE | EMU_HCFG_AC3ENABLE_CDSPDIF |
346 1.35 christos EMU_HCFG_AC3ENABLE_GPSPDIF | EMU_HCFG_AUTOMUTE);
347 1.35 christos } else if (sc->sc_type & EMUXKI_AUDIGY) {
348 1.35 christos bus_space_write_4(sc->sc_iot, sc->sc_ioh, EMU_HCFG,
349 1.35 christos EMU_HCFG_AUDIOENABLE | EMU_HCFG_AUTOMUTE);
350 1.35 christos } else {
351 1.35 christos bus_space_write_4(sc->sc_iot, sc->sc_ioh, EMU_HCFG,
352 1.42 jdolecek EMU_HCFG_AUDIOENABLE | EMU_HCFG_JOYENABLE |
353 1.35 christos EMU_HCFG_LOCKTANKCACHE_MASK | EMU_HCFG_AUTOMUTE);
354 1.35 christos }
355 1.1 jdolecek bus_space_write_4(sc->sc_iot, sc->sc_ioh, EMU_INTE,
356 1.1 jdolecek bus_space_read_4(sc->sc_iot, sc->sc_ioh, EMU_INTE) |
357 1.1 jdolecek EMU_INTE_VOLINCRENABLE | EMU_INTE_VOLDECRENABLE |
358 1.1 jdolecek EMU_INTE_MUTEENABLE);
359 1.35 christos if (sc->sc_type & EMUXKI_AUDIGY2) {
360 1.35 christos bus_space_write_4(sc->sc_iot, sc->sc_ioh, EMU_A_IOCFG,
361 1.35 christos EMU_A_IOCFG_GPOUT0 |
362 1.35 christos bus_space_read_4(sc->sc_iot, sc->sc_ioh, EMU_A_IOCFG));
363 1.35 christos }
364 1.1 jdolecek
365 1.1 jdolecek /* No multiple voice support for now */
366 1.54 gmcgarry sc->pvoice = sc->rvoice = NULL;
367 1.1 jdolecek
368 1.40 kent return 0;
369 1.1 jdolecek }
370 1.1 jdolecek
371 1.1 jdolecek static int
372 1.1 jdolecek emuxki_ac97_init(struct emuxki_softc *sc)
373 1.1 jdolecek {
374 1.1 jdolecek sc->hostif.arg = sc;
375 1.1 jdolecek sc->hostif.attach = emuxki_ac97_attach;
376 1.1 jdolecek sc->hostif.read = emuxki_ac97_read;
377 1.1 jdolecek sc->hostif.write = emuxki_ac97_write;
378 1.1 jdolecek sc->hostif.reset = emuxki_ac97_reset;
379 1.6 jdolecek sc->hostif.flags = emuxki_ac97_flags;
380 1.60 jmcneill return ac97_attach(&sc->hostif, sc->sc_dev, &sc->sc_lock);
381 1.1 jdolecek }
382 1.1 jdolecek
383 1.1 jdolecek static int
384 1.56 cegger emuxki_match(device_t parent, cfdata_t match, void *aux)
385 1.1 jdolecek {
386 1.40 kent struct pci_attach_args *pa;
387 1.1 jdolecek
388 1.40 kent pa = aux;
389 1.35 christos if (PCI_VENDOR(pa->pa_id) != PCI_VENDOR_CREATIVELABS)
390 1.35 christos return 0;
391 1.35 christos
392 1.35 christos switch (PCI_PRODUCT(pa->pa_id)) {
393 1.35 christos case PCI_PRODUCT_CREATIVELABS_SBLIVE:
394 1.35 christos case PCI_PRODUCT_CREATIVELABS_SBLIVE2:
395 1.40 kent case PCI_PRODUCT_CREATIVELABS_AUDIGY:
396 1.40 kent return 1;
397 1.35 christos default:
398 1.35 christos return 0;
399 1.32 martti }
400 1.1 jdolecek }
401 1.1 jdolecek
402 1.1 jdolecek static void
403 1.56 cegger emuxki_attach(device_t parent, device_t self, void *aux)
404 1.1 jdolecek {
405 1.40 kent struct emuxki_softc *sc;
406 1.40 kent struct pci_attach_args *pa;
407 1.40 kent char devinfo[256];
408 1.1 jdolecek pci_intr_handle_t ih;
409 1.40 kent const char *intrstr;
410 1.1 jdolecek
411 1.57 cegger sc = device_private(self);
412 1.58 tsutsui sc->sc_dev = self;
413 1.40 kent pa = aux;
414 1.15 thorpej aprint_naive(": Audio controller\n");
415 1.15 thorpej
416 1.60 jmcneill mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_NONE);
417 1.60 jmcneill mutex_init(&sc->sc_intr_lock, MUTEX_DEFAULT, IPL_SCHED);
418 1.60 jmcneill mutex_init(&sc->sc_index_lock, MUTEX_DEFAULT, IPL_SCHED);
419 1.60 jmcneill mutex_init(&sc->sc_ac97_index_lock, MUTEX_DEFAULT, IPL_SCHED);
420 1.60 jmcneill
421 1.1 jdolecek if (pci_mapreg_map(pa, EMU_PCI_CBIO, PCI_MAPREG_TYPE_IO, 0,
422 1.1 jdolecek &(sc->sc_iot), &(sc->sc_ioh), &(sc->sc_iob),
423 1.1 jdolecek &(sc->sc_ios))) {
424 1.15 thorpej aprint_error(": can't map iospace\n");
425 1.1 jdolecek return;
426 1.1 jdolecek }
427 1.33 itojun pci_devinfo(pa->pa_id, pa->pa_class, 1, devinfo, sizeof(devinfo));
428 1.15 thorpej aprint_normal(": %s\n", devinfo);
429 1.1 jdolecek
430 1.1 jdolecek sc->sc_pc = pa->pa_pc;
431 1.1 jdolecek sc->sc_dmat = pa->pa_dmat;
432 1.1 jdolecek pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG,
433 1.1 jdolecek pci_conf_read(pa->pa_pc, pa->pa_tag,
434 1.1 jdolecek (PCI_COMMAND_STATUS_REG) | PCI_COMMAND_MASTER_ENABLE));
435 1.1 jdolecek
436 1.1 jdolecek if (pci_intr_map(pa, &ih)) {
437 1.58 tsutsui aprint_error_dev(self, "couldn't map interrupt\n");
438 1.1 jdolecek bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_ios);
439 1.1 jdolecek return;
440 1.1 jdolecek }
441 1.1 jdolecek
442 1.1 jdolecek intrstr = pci_intr_string(pa->pa_pc, ih);
443 1.60 jmcneill sc->sc_ih = pci_intr_establish(pa->pa_pc, ih, IPL_SCHED, emuxki_intr,
444 1.1 jdolecek sc);
445 1.1 jdolecek if (sc->sc_ih == NULL) {
446 1.58 tsutsui aprint_error_dev(self, "couldn't establish interrupt");
447 1.1 jdolecek if (intrstr != NULL)
448 1.59 njoly aprint_error(" at %s", intrstr);
449 1.59 njoly aprint_error("\n");
450 1.1 jdolecek bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_ios);
451 1.1 jdolecek return;
452 1.1 jdolecek }
453 1.58 tsutsui aprint_normal_dev(self, "interrupting at %s\n", intrstr);
454 1.35 christos
455 1.37 dsainty /* XXX it's unknown whether APS is made from Audigy as well */
456 1.40 kent if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_CREATIVELABS_AUDIGY) {
457 1.40 kent sc->sc_type = EMUXKI_AUDIGY;
458 1.40 kent if (PCI_REVISION(pa->pa_class) == 0x04) {
459 1.40 kent sc->sc_type |= EMUXKI_AUDIGY2;
460 1.40 kent strlcpy(sc->sc_audv.name, "Audigy2", sizeof sc->sc_audv.name);
461 1.40 kent } else {
462 1.40 kent strlcpy(sc->sc_audv.name, "Audigy", sizeof sc->sc_audv.name);
463 1.40 kent }
464 1.40 kent } else if (pci_conf_read(pa->pa_pc, pa->pa_tag,
465 1.40 kent PCI_SUBSYS_ID_REG) == EMU_SUBSYS_APS) {
466 1.40 kent sc->sc_type = EMUXKI_APS;
467 1.40 kent strlcpy(sc->sc_audv.name, "E-mu APS", sizeof sc->sc_audv.name);
468 1.40 kent } else {
469 1.40 kent sc->sc_type = EMUXKI_SBLIVE;
470 1.40 kent strlcpy(sc->sc_audv.name, "SB Live!", sizeof sc->sc_audv.name);
471 1.40 kent }
472 1.40 kent snprintf(sc->sc_audv.version, sizeof sc->sc_audv.version, "0x%02x",
473 1.40 kent PCI_REVISION(pa->pa_class));
474 1.40 kent strlcpy(sc->sc_audv.config, "emuxki", sizeof sc->sc_audv.config);
475 1.1 jdolecek
476 1.1 jdolecek if (emuxki_scinit(sc) || emuxki_ac97_init(sc) ||
477 1.19 toshii (sc->sc_audev = audio_attach_mi(&emuxki_hw_if, sc, self)) == NULL) {
478 1.1 jdolecek emuxki_pci_shutdown(sc);
479 1.19 toshii return;
480 1.19 toshii }
481 1.19 toshii #if 0
482 1.60 jmcneill mutex_enter(&sc->lock);
483 1.19 toshii sc->rsourcectl.dev =
484 1.19 toshii sc->codecif->vtbl->get_portnum_by_name(sc->codec_if, AudioCrecord,
485 1.19 toshii AudioNsource, NULL);
486 1.19 toshii sc->rsourcectl.cp = AUDIO_MIXER_ENUM;
487 1.60 jmcneill mutex_exit(&sc->lock);
488 1.19 toshii #endif
489 1.1 jdolecek }
490 1.1 jdolecek
491 1.1 jdolecek static int
492 1.56 cegger emuxki_detach(device_t self, int flags)
493 1.1 jdolecek {
494 1.40 kent struct emuxki_softc *sc;
495 1.1 jdolecek
496 1.57 cegger sc = device_private(self);
497 1.40 kent if (sc->sc_audev != NULL) /* Test in case audio didn't attach */
498 1.40 kent config_detach(sc->sc_audev, 0);
499 1.1 jdolecek
500 1.1 jdolecek /* All voices should be stopped now but add some code here if not */
501 1.1 jdolecek
502 1.1 jdolecek bus_space_write_4(sc->sc_iot, sc->sc_ioh, EMU_HCFG,
503 1.1 jdolecek EMU_HCFG_LOCKSOUNDCACHE | EMU_HCFG_LOCKTANKCACHE_MASK |
504 1.1 jdolecek EMU_HCFG_MUTEBUTTONENABLE);
505 1.1 jdolecek bus_space_write_4(sc->sc_iot, sc->sc_ioh, EMU_INTE, 0);
506 1.1 jdolecek
507 1.60 jmcneill mutex_enter(&sc->sc_lock);
508 1.1 jdolecek emuxki_shutdown(sc);
509 1.60 jmcneill mutex_exit(&sc->sc_lock);
510 1.1 jdolecek
511 1.1 jdolecek emuxki_pci_shutdown(sc);
512 1.1 jdolecek
513 1.60 jmcneill mutex_destroy(&sc->sc_lock);
514 1.60 jmcneill mutex_destroy(&sc->sc_intr_lock);
515 1.60 jmcneill mutex_destroy(&sc->sc_index_lock);
516 1.60 jmcneill mutex_destroy(&sc->sc_ac97_index_lock);
517 1.60 jmcneill
518 1.40 kent return 0;
519 1.1 jdolecek }
520 1.1 jdolecek
521 1.1 jdolecek
522 1.1 jdolecek /* Misc stuff relative to emu10k1 */
523 1.1 jdolecek
524 1.40 kent static uint32_t
525 1.40 kent emuxki_rate_to_pitch(uint32_t rate)
526 1.1 jdolecek {
527 1.40 kent static const uint32_t logMagTable[128] = {
528 1.1 jdolecek 0x00000, 0x02dfc, 0x05b9e, 0x088e6, 0x0b5d6, 0x0e26f, 0x10eb3,
529 1.1 jdolecek 0x13aa2, 0x1663f, 0x1918a, 0x1bc84, 0x1e72e, 0x2118b, 0x23b9a,
530 1.1 jdolecek 0x2655d, 0x28ed5, 0x2b803, 0x2e0e8, 0x30985, 0x331db, 0x359eb,
531 1.1 jdolecek 0x381b6, 0x3a93d, 0x3d081, 0x3f782, 0x41e42, 0x444c1, 0x46b01,
532 1.1 jdolecek 0x49101, 0x4b6c4, 0x4dc49, 0x50191, 0x5269e, 0x54b6f, 0x57006,
533 1.1 jdolecek 0x59463, 0x5b888, 0x5dc74, 0x60029, 0x623a7, 0x646ee, 0x66a00,
534 1.1 jdolecek 0x68cdd, 0x6af86, 0x6d1fa, 0x6f43c, 0x7164b, 0x73829, 0x759d4,
535 1.1 jdolecek 0x77b4f, 0x79c9a, 0x7bdb5, 0x7dea1, 0x7ff5e, 0x81fed, 0x8404e,
536 1.1 jdolecek 0x86082, 0x88089, 0x8a064, 0x8c014, 0x8df98, 0x8fef1, 0x91e20,
537 1.1 jdolecek 0x93d26, 0x95c01, 0x97ab4, 0x9993e, 0x9b79f, 0x9d5d9, 0x9f3ec,
538 1.1 jdolecek 0xa11d8, 0xa2f9d, 0xa4d3c, 0xa6ab5, 0xa8808, 0xaa537, 0xac241,
539 1.1 jdolecek 0xadf26, 0xafbe7, 0xb1885, 0xb3500, 0xb5157, 0xb6d8c, 0xb899f,
540 1.1 jdolecek 0xba58f, 0xbc15e, 0xbdd0c, 0xbf899, 0xc1404, 0xc2f50, 0xc4a7b,
541 1.1 jdolecek 0xc6587, 0xc8073, 0xc9b3f, 0xcb5ed, 0xcd07c, 0xceaec, 0xd053f,
542 1.1 jdolecek 0xd1f73, 0xd398a, 0xd5384, 0xd6d60, 0xd8720, 0xda0c3, 0xdba4a,
543 1.1 jdolecek 0xdd3b4, 0xded03, 0xe0636, 0xe1f4e, 0xe384a, 0xe512c, 0xe69f3,
544 1.1 jdolecek 0xe829f, 0xe9b31, 0xeb3a9, 0xecc08, 0xee44c, 0xefc78, 0xf148a,
545 1.1 jdolecek 0xf2c83, 0xf4463, 0xf5c2a, 0xf73da, 0xf8b71, 0xfa2f0, 0xfba57,
546 1.1 jdolecek 0xfd1a7, 0xfe8df
547 1.1 jdolecek };
548 1.40 kent static const uint8_t logSlopeTable[128] = {
549 1.1 jdolecek 0x5c, 0x5c, 0x5b, 0x5a, 0x5a, 0x59, 0x58, 0x58,
550 1.1 jdolecek 0x57, 0x56, 0x56, 0x55, 0x55, 0x54, 0x53, 0x53,
551 1.1 jdolecek 0x52, 0x52, 0x51, 0x51, 0x50, 0x50, 0x4f, 0x4f,
552 1.1 jdolecek 0x4e, 0x4d, 0x4d, 0x4d, 0x4c, 0x4c, 0x4b, 0x4b,
553 1.1 jdolecek 0x4a, 0x4a, 0x49, 0x49, 0x48, 0x48, 0x47, 0x47,
554 1.1 jdolecek 0x47, 0x46, 0x46, 0x45, 0x45, 0x45, 0x44, 0x44,
555 1.1 jdolecek 0x43, 0x43, 0x43, 0x42, 0x42, 0x42, 0x41, 0x41,
556 1.1 jdolecek 0x41, 0x40, 0x40, 0x40, 0x3f, 0x3f, 0x3f, 0x3e,
557 1.1 jdolecek 0x3e, 0x3e, 0x3d, 0x3d, 0x3d, 0x3c, 0x3c, 0x3c,
558 1.1 jdolecek 0x3b, 0x3b, 0x3b, 0x3b, 0x3a, 0x3a, 0x3a, 0x39,
559 1.1 jdolecek 0x39, 0x39, 0x39, 0x38, 0x38, 0x38, 0x38, 0x37,
560 1.1 jdolecek 0x37, 0x37, 0x37, 0x36, 0x36, 0x36, 0x36, 0x35,
561 1.1 jdolecek 0x35, 0x35, 0x35, 0x34, 0x34, 0x34, 0x34, 0x34,
562 1.1 jdolecek 0x33, 0x33, 0x33, 0x33, 0x32, 0x32, 0x32, 0x32,
563 1.1 jdolecek 0x32, 0x31, 0x31, 0x31, 0x31, 0x31, 0x30, 0x30,
564 1.1 jdolecek 0x30, 0x30, 0x30, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f
565 1.1 jdolecek };
566 1.40 kent int8_t i;
567 1.1 jdolecek
568 1.1 jdolecek if (rate == 0)
569 1.1 jdolecek return 0; /* Bail out if no leading "1" */
570 1.1 jdolecek rate *= 11185; /* Scale 48000 to 0x20002380 */
571 1.1 jdolecek for (i = 31; i > 0; i--) {
572 1.1 jdolecek if (rate & 0x80000000) { /* Detect leading "1" */
573 1.40 kent return (((uint32_t) (i - 15) << 20) +
574 1.1 jdolecek logMagTable[0x7f & (rate >> 24)] +
575 1.1 jdolecek (0x7f & (rate >> 17)) *
576 1.1 jdolecek logSlopeTable[0x7f & (rate >> 24)]);
577 1.1 jdolecek }
578 1.1 jdolecek rate <<= 1;
579 1.1 jdolecek }
580 1.1 jdolecek
581 1.1 jdolecek return 0; /* Should never reach this point */
582 1.1 jdolecek }
583 1.1 jdolecek
584 1.1 jdolecek /* Emu10k1 Low level */
585 1.1 jdolecek
586 1.40 kent static uint32_t
587 1.40 kent emuxki_read(struct emuxki_softc *sc, uint16_t chano, uint32_t reg)
588 1.1 jdolecek {
589 1.40 kent uint32_t ptr, mask;
590 1.40 kent uint8_t size, offset;
591 1.1 jdolecek
592 1.40 kent mask = 0xffffffff;
593 1.40 kent offset = 0;
594 1.35 christos ptr = ((((u_int32_t) reg) << 16) &
595 1.35 christos (sc->sc_type & EMUXKI_AUDIGY ?
596 1.35 christos EMU_A_PTR_ADDR_MASK : EMU_PTR_ADDR_MASK)) |
597 1.1 jdolecek (chano & EMU_PTR_CHNO_MASK);
598 1.1 jdolecek if (reg & 0xff000000) {
599 1.1 jdolecek size = (reg >> 24) & 0x3f;
600 1.1 jdolecek offset = (reg >> 16) & 0x1f;
601 1.1 jdolecek mask = ((1 << size) - 1) << offset;
602 1.1 jdolecek }
603 1.1 jdolecek
604 1.60 jmcneill mutex_spin_enter(&sc->sc_index_lock);
605 1.1 jdolecek bus_space_write_4(sc->sc_iot, sc->sc_ioh, EMU_PTR, ptr);
606 1.1 jdolecek ptr = (bus_space_read_4(sc->sc_iot, sc->sc_ioh, EMU_DATA) & mask)
607 1.1 jdolecek >> offset;
608 1.60 jmcneill mutex_spin_exit(&sc->sc_index_lock);
609 1.1 jdolecek
610 1.40 kent return ptr;
611 1.1 jdolecek }
612 1.1 jdolecek
613 1.1 jdolecek static void
614 1.40 kent emuxki_write(struct emuxki_softc *sc, uint16_t chano,
615 1.40 kent uint32_t reg, uint32_t data)
616 1.1 jdolecek {
617 1.40 kent uint32_t ptr, mask;
618 1.40 kent uint8_t size, offset;
619 1.1 jdolecek
620 1.35 christos ptr = ((((u_int32_t) reg) << 16) &
621 1.35 christos (sc->sc_type & EMUXKI_AUDIGY ?
622 1.35 christos EMU_A_PTR_ADDR_MASK : EMU_PTR_ADDR_MASK)) |
623 1.1 jdolecek (chano & EMU_PTR_CHNO_MASK);
624 1.1 jdolecek if (reg & 0xff000000) {
625 1.1 jdolecek size = (reg >> 24) & 0x3f;
626 1.1 jdolecek offset = (reg >> 16) & 0x1f;
627 1.1 jdolecek mask = ((1 << size) - 1) << offset;
628 1.1 jdolecek data = ((data << offset) & mask) |
629 1.1 jdolecek (emuxki_read(sc, chano, reg & 0xffff) & ~mask);
630 1.1 jdolecek }
631 1.1 jdolecek
632 1.60 jmcneill mutex_spin_enter(&sc->sc_index_lock);
633 1.1 jdolecek bus_space_write_4(sc->sc_iot, sc->sc_ioh, EMU_PTR, ptr);
634 1.1 jdolecek bus_space_write_4(sc->sc_iot, sc->sc_ioh, EMU_DATA, data);
635 1.60 jmcneill mutex_spin_exit(&sc->sc_index_lock);
636 1.1 jdolecek }
637 1.1 jdolecek
638 1.1 jdolecek /* Microcode should this go in /sys/dev/microcode ? */
639 1.1 jdolecek
640 1.1 jdolecek static void
641 1.40 kent emuxki_write_micro(struct emuxki_softc *sc, uint32_t pc, uint32_t data)
642 1.1 jdolecek {
643 1.40 kent
644 1.35 christos emuxki_write(sc, 0,
645 1.35 christos (sc->sc_type & EMUXKI_AUDIGY ?
646 1.35 christos EMU_A_MICROCODEBASE : EMU_MICROCODEBASE) + pc,
647 1.35 christos data);
648 1.1 jdolecek }
649 1.1 jdolecek
650 1.1 jdolecek static void
651 1.40 kent emuxki_dsp_addop(struct emuxki_softc *sc, uint16_t *pc, uint8_t op,
652 1.40 kent uint16_t r, uint16_t a, uint16_t x, uint16_t y)
653 1.1 jdolecek {
654 1.40 kent
655 1.35 christos if (sc->sc_type & EMUXKI_AUDIGY) {
656 1.35 christos emuxki_write_micro(sc, *pc << 1,
657 1.35 christos ((x << 12) & EMU_A_DSP_LOWORD_OPX_MASK) |
658 1.35 christos (y & EMU_A_DSP_LOWORD_OPY_MASK));
659 1.35 christos emuxki_write_micro(sc, (*pc << 1) + 1,
660 1.35 christos ((op << 24) & EMU_A_DSP_HIWORD_OPCODE_MASK) |
661 1.35 christos ((r << 12) & EMU_A_DSP_HIWORD_RESULT_MASK) |
662 1.35 christos (a & EMU_A_DSP_HIWORD_OPA_MASK));
663 1.35 christos } else {
664 1.35 christos emuxki_write_micro(sc, *pc << 1,
665 1.35 christos ((x << 10) & EMU_DSP_LOWORD_OPX_MASK) |
666 1.35 christos (y & EMU_DSP_LOWORD_OPY_MASK));
667 1.35 christos emuxki_write_micro(sc, (*pc << 1) + 1,
668 1.35 christos ((op << 20) & EMU_DSP_HIWORD_OPCODE_MASK) |
669 1.35 christos ((r << 10) & EMU_DSP_HIWORD_RESULT_MASK) |
670 1.35 christos (a & EMU_DSP_HIWORD_OPA_MASK));
671 1.35 christos }
672 1.40 kent (*pc)++;
673 1.1 jdolecek }
674 1.1 jdolecek
675 1.1 jdolecek /* init and shutdown */
676 1.1 jdolecek
677 1.1 jdolecek static void
678 1.1 jdolecek emuxki_initfx(struct emuxki_softc *sc)
679 1.1 jdolecek {
680 1.40 kent uint16_t pc;
681 1.1 jdolecek
682 1.1 jdolecek /* Set all GPRs to 0 */
683 1.1 jdolecek for (pc = 0; pc < 256; pc++)
684 1.1 jdolecek emuxki_write(sc, 0, EMU_DSP_GPR(pc), 0);
685 1.1 jdolecek for (pc = 0; pc < 160; pc++) {
686 1.1 jdolecek emuxki_write(sc, 0, EMU_TANKMEMDATAREGBASE + pc, 0);
687 1.1 jdolecek emuxki_write(sc, 0, EMU_TANKMEMADDRREGBASE + pc, 0);
688 1.1 jdolecek }
689 1.1 jdolecek pc = 0;
690 1.1 jdolecek
691 1.35 christos if (sc->sc_type & EMUXKI_AUDIGY) {
692 1.35 christos /* AC97 Out (l/r) = AC97 In (l/r) + FX[0/1] * 4 */
693 1.35 christos emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_MACINTS,
694 1.35 christos EMU_A_DSP_OUTL(EMU_A_DSP_OUT_A_FRONT),
695 1.35 christos EMU_A_DSP_CST(0),
696 1.35 christos EMU_DSP_FX(0), EMU_A_DSP_CST(4));
697 1.35 christos emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_MACINTS,
698 1.35 christos EMU_A_DSP_OUTR(EMU_A_DSP_OUT_A_FRONT),
699 1.35 christos EMU_A_DSP_CST(0),
700 1.35 christos EMU_DSP_FX(1), EMU_A_DSP_CST(4));
701 1.35 christos
702 1.35 christos /* Rear channel OUT (l/r) = FX[2/3] * 4 */
703 1.1 jdolecek #if 0
704 1.35 christos emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_MACINTS,
705 1.35 christos EMU_A_DSP_OUTL(EMU_A_DSP_OUT_A_REAR),
706 1.35 christos EMU_A_DSP_OUTL(EMU_A_DSP_OUT_A_FRONT),
707 1.35 christos EMU_DSP_FX(0), EMU_A_DSP_CST(4));
708 1.35 christos emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_MACINTS,
709 1.35 christos EMU_A_DSP_OUTR(EMU_A_DSP_OUT_A_REAR),
710 1.35 christos EMU_A_DSP_OUTR(EMU_A_DSP_OUT_A_FRONT),
711 1.35 christos EMU_DSP_FX(1), EMU_A_DSP_CST(4));
712 1.35 christos #endif
713 1.35 christos /* ADC recording (l/r) = AC97 In (l/r) */
714 1.35 christos emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_ACC3,
715 1.35 christos EMU_A_DSP_OUTL(EMU_A_DSP_OUT_ADC),
716 1.35 christos EMU_A_DSP_INL(EMU_DSP_IN_AC97),
717 1.35 christos EMU_A_DSP_CST(0), EMU_A_DSP_CST(0));
718 1.35 christos emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_ACC3,
719 1.35 christos EMU_A_DSP_OUTR(EMU_A_DSP_OUT_ADC),
720 1.35 christos EMU_A_DSP_INR(EMU_DSP_IN_AC97),
721 1.35 christos EMU_A_DSP_CST(0), EMU_A_DSP_CST(0));
722 1.35 christos
723 1.35 christos /* zero out the rest of the microcode */
724 1.35 christos while (pc < 512)
725 1.35 christos emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_ACC3,
726 1.35 christos EMU_A_DSP_CST(0), EMU_A_DSP_CST(0),
727 1.35 christos EMU_A_DSP_CST(0), EMU_A_DSP_CST(0));
728 1.35 christos
729 1.35 christos emuxki_write(sc, 0, EMU_A_DBG, 0); /* Is it really necessary ? */
730 1.35 christos } else {
731 1.35 christos /* AC97 Out (l/r) = AC97 In (l/r) + FX[0/1] * 4 */
732 1.35 christos emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_MACINTS,
733 1.35 christos EMU_DSP_OUTL(EMU_DSP_OUT_A_FRONT),
734 1.35 christos EMU_DSP_CST(0),
735 1.35 christos EMU_DSP_FX(0), EMU_DSP_CST(4));
736 1.35 christos emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_MACINTS,
737 1.35 christos EMU_DSP_OUTR(EMU_DSP_OUT_A_FRONT),
738 1.35 christos EMU_DSP_CST(0),
739 1.35 christos EMU_DSP_FX(1), EMU_DSP_CST(4));
740 1.35 christos
741 1.35 christos /* Rear channel OUT (l/r) = FX[2/3] * 4 */
742 1.35 christos #if 0
743 1.35 christos emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_MACINTS,
744 1.35 christos EMU_DSP_OUTL(EMU_DSP_OUT_AD_REAR),
745 1.35 christos EMU_DSP_OUTL(EMU_DSP_OUT_A_FRONT),
746 1.35 christos EMU_DSP_FX(0), EMU_DSP_CST(4));
747 1.35 christos emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_MACINTS,
748 1.35 christos EMU_DSP_OUTR(EMU_DSP_OUT_AD_REAR),
749 1.35 christos EMU_DSP_OUTR(EMU_DSP_OUT_A_FRONT),
750 1.35 christos EMU_DSP_FX(1), EMU_DSP_CST(4));
751 1.35 christos #endif
752 1.35 christos /* ADC recording (l/r) = AC97 In (l/r) */
753 1.1 jdolecek emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_ACC3,
754 1.35 christos EMU_DSP_OUTL(EMU_DSP_OUT_ADC),
755 1.35 christos EMU_DSP_INL(EMU_DSP_IN_AC97),
756 1.1 jdolecek EMU_DSP_CST(0), EMU_DSP_CST(0));
757 1.35 christos emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_ACC3,
758 1.35 christos EMU_DSP_OUTR(EMU_DSP_OUT_ADC),
759 1.35 christos EMU_DSP_INR(EMU_DSP_IN_AC97),
760 1.35 christos EMU_DSP_CST(0), EMU_DSP_CST(0));
761 1.35 christos
762 1.35 christos /* zero out the rest of the microcode */
763 1.35 christos while (pc < 512)
764 1.35 christos emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_ACC3,
765 1.35 christos EMU_DSP_CST(0), EMU_DSP_CST(0),
766 1.35 christos EMU_DSP_CST(0), EMU_DSP_CST(0));
767 1.1 jdolecek
768 1.35 christos emuxki_write(sc, 0, EMU_DBG, 0); /* Is it really necessary ? */
769 1.35 christos }
770 1.1 jdolecek }
771 1.1 jdolecek
772 1.1 jdolecek static int
773 1.1 jdolecek emuxki_init(struct emuxki_softc *sc)
774 1.1 jdolecek {
775 1.40 kent uint16_t i;
776 1.40 kent uint32_t spcs, *ptb;
777 1.40 kent bus_addr_t silentpage;
778 1.1 jdolecek
779 1.1 jdolecek /* disable any channel interrupt */
780 1.1 jdolecek emuxki_write(sc, 0, EMU_CLIEL, 0);
781 1.1 jdolecek emuxki_write(sc, 0, EMU_CLIEH, 0);
782 1.1 jdolecek emuxki_write(sc, 0, EMU_SOLEL, 0);
783 1.1 jdolecek emuxki_write(sc, 0, EMU_SOLEH, 0);
784 1.1 jdolecek
785 1.1 jdolecek /* Set recording buffers sizes to zero */
786 1.1 jdolecek emuxki_write(sc, 0, EMU_MICBS, EMU_RECBS_BUFSIZE_NONE);
787 1.1 jdolecek emuxki_write(sc, 0, EMU_MICBA, 0);
788 1.1 jdolecek emuxki_write(sc, 0, EMU_FXBS, EMU_RECBS_BUFSIZE_NONE);
789 1.1 jdolecek emuxki_write(sc, 0, EMU_FXBA, 0);
790 1.1 jdolecek emuxki_write(sc, 0, EMU_ADCBS, EMU_RECBS_BUFSIZE_NONE);
791 1.1 jdolecek emuxki_write(sc, 0, EMU_ADCBA, 0);
792 1.1 jdolecek
793 1.40 kent if(sc->sc_type & EMUXKI_AUDIGY) {
794 1.40 kent emuxki_write(sc, 0, EMU_SPBYPASS, EMU_SPBYPASS_24_BITS);
795 1.40 kent emuxki_write(sc, 0, EMU_AC97SLOT, EMU_AC97SLOT_CENTER | EMU_AC97SLOT_LFE);
796 1.40 kent }
797 1.35 christos
798 1.1 jdolecek /* Initialize all channels to stopped and no effects */
799 1.1 jdolecek for (i = 0; i < EMU_NUMCHAN; i++) {
800 1.1 jdolecek emuxki_write(sc, i, EMU_CHAN_DCYSUSV, 0);
801 1.1 jdolecek emuxki_write(sc, i, EMU_CHAN_IP, 0);
802 1.1 jdolecek emuxki_write(sc, i, EMU_CHAN_VTFT, 0xffff);
803 1.1 jdolecek emuxki_write(sc, i, EMU_CHAN_CVCF, 0xffff);
804 1.1 jdolecek emuxki_write(sc, i, EMU_CHAN_PTRX, 0);
805 1.1 jdolecek emuxki_write(sc, i, EMU_CHAN_CPF, 0);
806 1.1 jdolecek emuxki_write(sc, i, EMU_CHAN_CCR, 0);
807 1.1 jdolecek emuxki_write(sc, i, EMU_CHAN_PSST, 0);
808 1.1 jdolecek emuxki_write(sc, i, EMU_CHAN_DSL, 0x10); /* Why 16 ? */
809 1.1 jdolecek emuxki_write(sc, i, EMU_CHAN_CCCA, 0);
810 1.1 jdolecek emuxki_write(sc, i, EMU_CHAN_Z1, 0);
811 1.1 jdolecek emuxki_write(sc, i, EMU_CHAN_Z2, 0);
812 1.1 jdolecek emuxki_write(sc, i, EMU_CHAN_FXRT, 0x32100000);
813 1.1 jdolecek emuxki_write(sc, i, EMU_CHAN_ATKHLDM, 0);
814 1.1 jdolecek emuxki_write(sc, i, EMU_CHAN_DCYSUSM, 0);
815 1.1 jdolecek emuxki_write(sc, i, EMU_CHAN_IFATN, 0xffff);
816 1.1 jdolecek emuxki_write(sc, i, EMU_CHAN_PEFE, 0);
817 1.1 jdolecek emuxki_write(sc, i, EMU_CHAN_FMMOD, 0);
818 1.1 jdolecek emuxki_write(sc, i, EMU_CHAN_TREMFRQ, 24);
819 1.1 jdolecek emuxki_write(sc, i, EMU_CHAN_FM2FRQ2, 24);
820 1.1 jdolecek emuxki_write(sc, i, EMU_CHAN_TEMPENV, 0);
821 1.1 jdolecek
822 1.1 jdolecek /* these are last so OFF prevents writing */
823 1.1 jdolecek emuxki_write(sc, i, EMU_CHAN_LFOVAL2, 0);
824 1.1 jdolecek emuxki_write(sc, i, EMU_CHAN_LFOVAL1, 0);
825 1.1 jdolecek emuxki_write(sc, i, EMU_CHAN_ATKHLDV, 0);
826 1.1 jdolecek emuxki_write(sc, i, EMU_CHAN_ENVVOL, 0);
827 1.1 jdolecek emuxki_write(sc, i, EMU_CHAN_ENVVAL, 0);
828 1.1 jdolecek }
829 1.1 jdolecek
830 1.1 jdolecek /* set digital outputs format */
831 1.1 jdolecek spcs = (EMU_SPCS_CLKACCY_1000PPM | EMU_SPCS_SAMPLERATE_48 |
832 1.1 jdolecek EMU_SPCS_CHANNELNUM_LEFT | EMU_SPCS_SOURCENUM_UNSPEC |
833 1.1 jdolecek EMU_SPCS_GENERATIONSTATUS | 0x00001200 /* Cat code. */ |
834 1.1 jdolecek 0x00000000 /* IEC-958 Mode */ | EMU_SPCS_EMPHASIS_NONE |
835 1.1 jdolecek EMU_SPCS_COPYRIGHT);
836 1.1 jdolecek emuxki_write(sc, 0, EMU_SPCS0, spcs);
837 1.1 jdolecek emuxki_write(sc, 0, EMU_SPCS1, spcs);
838 1.1 jdolecek emuxki_write(sc, 0, EMU_SPCS2, spcs);
839 1.1 jdolecek
840 1.40 kent if(sc->sc_type & EMUXKI_AUDIGY2) {
841 1.40 kent emuxki_write(sc, 0, EMU_A2_SPDIF_SAMPLERATE, EMU_A2_SPDIF_UNKNOWN);
842 1.35 christos
843 1.40 kent bus_space_write_4(sc->sc_iot, sc->sc_ioh, EMU_A2_PTR, EMU_A2_SRCSEL);
844 1.41 perry bus_space_write_4(sc->sc_iot, sc->sc_ioh, EMU_A2_DATA,
845 1.40 kent EMU_A2_SRCSEL_ENABLE_SPDIF | EMU_A2_SRCSEL_ENABLE_SRCMULTI);
846 1.40 kent
847 1.40 kent bus_space_write_4(sc->sc_iot, sc->sc_ioh, EMU_A2_PTR, EMU_A2_SRCMULTI);
848 1.40 kent bus_space_write_4(sc->sc_iot, sc->sc_ioh, EMU_A2_DATA, EMU_A2_SRCMULTI_ENABLE_INPUT);
849 1.40 kent }
850 1.35 christos
851 1.35 christos
852 1.1 jdolecek /* Let's play with sound processor */
853 1.1 jdolecek emuxki_initfx(sc);
854 1.1 jdolecek
855 1.1 jdolecek /* Here is our Page Table */
856 1.1 jdolecek if ((sc->ptb = dmamem_alloc(sc->sc_dmat,
857 1.1 jdolecek EMU_MAXPTE * sizeof(u_int32_t),
858 1.60 jmcneill EMU_DMA_ALIGN, EMU_DMAMEM_NSEG)) == NULL)
859 1.40 kent return ENOMEM;
860 1.1 jdolecek
861 1.1 jdolecek /* This is necessary unless you like Metallic noise... */
862 1.1 jdolecek if ((sc->silentpage = dmamem_alloc(sc->sc_dmat, EMU_PTESIZE,
863 1.60 jmcneill EMU_DMA_ALIGN, EMU_DMAMEM_NSEG))==NULL){
864 1.60 jmcneill dmamem_free(sc->ptb);
865 1.40 kent return ENOMEM;
866 1.1 jdolecek }
867 1.1 jdolecek
868 1.1 jdolecek /* Zero out the silent page */
869 1.1 jdolecek /* This might not be always true, it might be 128 for 8bit channels */
870 1.1 jdolecek memset(KERNADDR(sc->silentpage), 0, DMASIZE(sc->silentpage));
871 1.1 jdolecek
872 1.1 jdolecek /*
873 1.1 jdolecek * Set all the PTB Entries to the silent page We shift the physical
874 1.1 jdolecek * address by one and OR it with the page number. I don't know what
875 1.1 jdolecek * the ORed index is for, might be a very useful unused feature...
876 1.1 jdolecek */
877 1.1 jdolecek silentpage = DMAADDR(sc->silentpage) << 1;
878 1.1 jdolecek ptb = KERNADDR(sc->ptb);
879 1.1 jdolecek for (i = 0; i < EMU_MAXPTE; i++)
880 1.34 tsutsui ptb[i] = htole32(silentpage | i);
881 1.1 jdolecek
882 1.1 jdolecek /* Write PTB address and set TCB to none */
883 1.1 jdolecek emuxki_write(sc, 0, EMU_PTB, DMAADDR(sc->ptb));
884 1.1 jdolecek emuxki_write(sc, 0, EMU_TCBS, 0); /* This means 16K TCB */
885 1.1 jdolecek emuxki_write(sc, 0, EMU_TCB, 0); /* No TCB use for now */
886 1.1 jdolecek
887 1.1 jdolecek /*
888 1.1 jdolecek * Set channels MAPs to the silent page.
889 1.1 jdolecek * I don't know what MAPs are for.
890 1.1 jdolecek */
891 1.1 jdolecek silentpage |= EMU_CHAN_MAP_PTI_MASK;
892 1.1 jdolecek for (i = 0; i < EMU_NUMCHAN; i++) {
893 1.1 jdolecek emuxki_write(sc, i, EMU_CHAN_MAPA, silentpage);
894 1.1 jdolecek emuxki_write(sc, i, EMU_CHAN_MAPB, silentpage);
895 1.1 jdolecek sc->channel[i] = NULL;
896 1.1 jdolecek }
897 1.1 jdolecek
898 1.1 jdolecek /* Init voices list */
899 1.1 jdolecek LIST_INIT(&(sc->voices));
900 1.1 jdolecek
901 1.1 jdolecek /* Timer is stopped */
902 1.1 jdolecek sc->timerstate &= ~EMU_TIMER_STATE_ENABLED;
903 1.40 kent return 0;
904 1.1 jdolecek }
905 1.1 jdolecek
906 1.1 jdolecek static void
907 1.1 jdolecek emuxki_shutdown(struct emuxki_softc *sc)
908 1.1 jdolecek {
909 1.40 kent uint32_t i;
910 1.1 jdolecek
911 1.1 jdolecek /* Disable any Channels interrupts */
912 1.1 jdolecek emuxki_write(sc, 0, EMU_CLIEL, 0);
913 1.1 jdolecek emuxki_write(sc, 0, EMU_CLIEH, 0);
914 1.1 jdolecek emuxki_write(sc, 0, EMU_SOLEL, 0);
915 1.1 jdolecek emuxki_write(sc, 0, EMU_SOLEH, 0);
916 1.1 jdolecek
917 1.1 jdolecek /*
918 1.1 jdolecek * Should do some voice(stream) stopping stuff here, that's what will
919 1.1 jdolecek * stop and deallocate all channels.
920 1.1 jdolecek */
921 1.1 jdolecek
922 1.1 jdolecek /* Stop all channels */
923 1.1 jdolecek /* XXX This shouldn't be necessary, I'll remove once everything works */
924 1.1 jdolecek for (i = 0; i < EMU_NUMCHAN; i++)
925 1.1 jdolecek emuxki_write(sc, i, EMU_CHAN_DCYSUSV, 0);
926 1.1 jdolecek for (i = 0; i < EMU_NUMCHAN; i++) {
927 1.1 jdolecek emuxki_write(sc, i, EMU_CHAN_VTFT, 0);
928 1.1 jdolecek emuxki_write(sc, i, EMU_CHAN_CVCF, 0);
929 1.1 jdolecek emuxki_write(sc, i, EMU_CHAN_PTRX, 0);
930 1.1 jdolecek emuxki_write(sc, i, EMU_CHAN_CPF, 0);
931 1.1 jdolecek }
932 1.1 jdolecek
933 1.1 jdolecek /*
934 1.1 jdolecek * Deallocate Emu10k1 caches and recording buffers. Again it will be
935 1.1 jdolecek * removed because it will be done in voice shutdown.
936 1.1 jdolecek */
937 1.1 jdolecek emuxki_write(sc, 0, EMU_MICBS, EMU_RECBS_BUFSIZE_NONE);
938 1.1 jdolecek emuxki_write(sc, 0, EMU_MICBA, 0);
939 1.1 jdolecek emuxki_write(sc, 0, EMU_FXBS, EMU_RECBS_BUFSIZE_NONE);
940 1.1 jdolecek emuxki_write(sc, 0, EMU_FXBA, 0);
941 1.40 kent if(sc->sc_type & EMUXKI_AUDIGY) {
942 1.40 kent emuxki_write(sc, 0, EMU_A_FXWC1, 0);
943 1.40 kent emuxki_write(sc, 0, EMU_A_FXWC2, 0);
944 1.40 kent } else {
945 1.40 kent emuxki_write(sc, 0, EMU_FXWC, 0);
946 1.40 kent }
947 1.1 jdolecek emuxki_write(sc, 0, EMU_ADCBS, EMU_RECBS_BUFSIZE_NONE);
948 1.1 jdolecek emuxki_write(sc, 0, EMU_ADCBA, 0);
949 1.1 jdolecek
950 1.1 jdolecek /*
951 1.1 jdolecek * XXX I don't know yet how I will handle tank cache buffer,
952 1.1 jdolecek * I don't even clearly know what it is for.
953 1.1 jdolecek */
954 1.1 jdolecek emuxki_write(sc, 0, EMU_TCB, 0); /* 16K again */
955 1.1 jdolecek emuxki_write(sc, 0, EMU_TCBS, 0);
956 1.1 jdolecek
957 1.1 jdolecek emuxki_write(sc, 0, EMU_DBG, 0x8000); /* necessary ? */
958 1.1 jdolecek
959 1.60 jmcneill dmamem_free(sc->silentpage);
960 1.60 jmcneill dmamem_free(sc->ptb);
961 1.1 jdolecek }
962 1.1 jdolecek
963 1.25 wiz /* Emu10k1 Memory management */
964 1.1 jdolecek
965 1.1 jdolecek static struct emuxki_mem *
966 1.60 jmcneill emuxki_mem_new(struct emuxki_softc *sc, int ptbidx, size_t size)
967 1.1 jdolecek {
968 1.1 jdolecek struct emuxki_mem *mem;
969 1.1 jdolecek
970 1.60 jmcneill if ((mem = kmem_alloc(sizeof(*mem), KM_SLEEP)) == NULL)
971 1.40 kent return NULL;
972 1.1 jdolecek
973 1.1 jdolecek mem->ptbidx = ptbidx;
974 1.1 jdolecek if ((mem->dmamem = dmamem_alloc(sc->sc_dmat, size, EMU_DMA_ALIGN,
975 1.60 jmcneill EMU_DMAMEM_NSEG)) == NULL) {
976 1.60 jmcneill kmem_free(mem, sizeof(*mem));
977 1.40 kent return NULL;
978 1.1 jdolecek }
979 1.40 kent return mem;
980 1.1 jdolecek }
981 1.1 jdolecek
982 1.1 jdolecek static void
983 1.60 jmcneill emuxki_mem_delete(struct emuxki_mem *mem, size_t size)
984 1.1 jdolecek {
985 1.40 kent
986 1.60 jmcneill dmamem_free(mem->dmamem);
987 1.60 jmcneill kmem_free(mem, sizeof(*mem));
988 1.1 jdolecek }
989 1.1 jdolecek
990 1.1 jdolecek static void *
991 1.60 jmcneill emuxki_pmem_alloc(struct emuxki_softc *sc, size_t size)
992 1.1 jdolecek {
993 1.60 jmcneill int i, j;
994 1.40 kent size_t numblocks;
995 1.1 jdolecek struct emuxki_mem *mem;
996 1.40 kent uint32_t *ptb, silentpage;
997 1.1 jdolecek
998 1.1 jdolecek ptb = KERNADDR(sc->ptb);
999 1.1 jdolecek silentpage = DMAADDR(sc->silentpage) << 1;
1000 1.1 jdolecek numblocks = size / EMU_PTESIZE;
1001 1.1 jdolecek if (size % EMU_PTESIZE)
1002 1.1 jdolecek numblocks++;
1003 1.1 jdolecek
1004 1.60 jmcneill for (i = 0; i < EMU_MAXPTE; i++) {
1005 1.60 jmcneill mutex_spin_enter(&sc->sc_intr_lock);
1006 1.34 tsutsui if ((le32toh(ptb[i]) & EMU_CHAN_MAP_PTE_MASK) == silentpage) {
1007 1.1 jdolecek /* We look for a free PTE */
1008 1.1 jdolecek for (j = 0; j < numblocks; j++)
1009 1.34 tsutsui if ((le32toh(ptb[i + j])
1010 1.34 tsutsui & EMU_CHAN_MAP_PTE_MASK) != silentpage)
1011 1.1 jdolecek break;
1012 1.1 jdolecek if (j == numblocks) {
1013 1.60 jmcneill mutex_spin_exit(&sc->sc_intr_lock);
1014 1.1 jdolecek if ((mem = emuxki_mem_new(sc, i,
1015 1.60 jmcneill size)) == NULL) {
1016 1.40 kent return NULL;
1017 1.1 jdolecek }
1018 1.60 jmcneill mutex_spin_enter(&sc->sc_intr_lock);
1019 1.1 jdolecek for (j = 0; j < numblocks; j++)
1020 1.1 jdolecek ptb[i + j] =
1021 1.34 tsutsui htole32((((DMAADDR(mem->dmamem) +
1022 1.34 tsutsui j * EMU_PTESIZE)) << 1) | (i + j));
1023 1.1 jdolecek LIST_INSERT_HEAD(&(sc->mem), mem, next);
1024 1.60 jmcneill mutex_spin_exit(&sc->sc_intr_lock);
1025 1.1 jdolecek return (KERNADDR(mem->dmamem));
1026 1.1 jdolecek } else
1027 1.1 jdolecek i += j;
1028 1.1 jdolecek }
1029 1.60 jmcneill mutex_spin_exit(&sc->sc_intr_lock);
1030 1.60 jmcneill }
1031 1.40 kent return NULL;
1032 1.1 jdolecek }
1033 1.1 jdolecek
1034 1.1 jdolecek static void *
1035 1.60 jmcneill emuxki_rmem_alloc(struct emuxki_softc *sc, size_t size)
1036 1.1 jdolecek {
1037 1.1 jdolecek struct emuxki_mem *mem;
1038 1.1 jdolecek
1039 1.60 jmcneill mem = emuxki_mem_new(sc, EMU_RMEM, size);
1040 1.1 jdolecek if (mem == NULL)
1041 1.40 kent return NULL;
1042 1.1 jdolecek
1043 1.60 jmcneill mutex_spin_enter(&sc->sc_intr_lock);
1044 1.1 jdolecek LIST_INSERT_HEAD(&(sc->mem), mem, next);
1045 1.60 jmcneill mutex_spin_exit(&sc->sc_intr_lock);
1046 1.1 jdolecek
1047 1.40 kent return KERNADDR(mem->dmamem);
1048 1.1 jdolecek }
1049 1.1 jdolecek
1050 1.1 jdolecek /*
1051 1.25 wiz * emuxki_channel_* : Channel management functions
1052 1.1 jdolecek * emuxki_chanparms_* : Channel parameters modification functions
1053 1.1 jdolecek */
1054 1.1 jdolecek
1055 1.1 jdolecek /*
1056 1.1 jdolecek * is splaudio necessary here, can the same voice be manipulated by two
1057 1.1 jdolecek * different threads at a time ?
1058 1.1 jdolecek */
1059 1.1 jdolecek static void
1060 1.1 jdolecek emuxki_chanparms_set_defaults(struct emuxki_channel *chan)
1061 1.1 jdolecek {
1062 1.40 kent
1063 1.1 jdolecek chan->fxsend.a.level = chan->fxsend.b.level =
1064 1.35 christos chan->fxsend.c.level = chan->fxsend.d.level =
1065 1.35 christos /* for audigy */
1066 1.35 christos chan->fxsend.e.level = chan->fxsend.f.level =
1067 1.35 christos chan->fxsend.g.level = chan->fxsend.h.level =
1068 1.35 christos chan->voice->sc->sc_type & EMUXKI_AUDIGY ?
1069 1.35 christos 0xc0 : 0xff; /* not max */
1070 1.35 christos
1071 1.1 jdolecek chan->fxsend.a.dest = 0x0;
1072 1.1 jdolecek chan->fxsend.b.dest = 0x1;
1073 1.1 jdolecek chan->fxsend.c.dest = 0x2;
1074 1.1 jdolecek chan->fxsend.d.dest = 0x3;
1075 1.35 christos /* for audigy */
1076 1.35 christos chan->fxsend.e.dest = 0x4;
1077 1.35 christos chan->fxsend.f.dest = 0x5;
1078 1.35 christos chan->fxsend.g.dest = 0x6;
1079 1.35 christos chan->fxsend.h.dest = 0x7;
1080 1.1 jdolecek
1081 1.17 wiz chan->pitch.initial = 0x0000; /* shouldn't it be 0xE000 ? */
1082 1.1 jdolecek chan->pitch.current = 0x0000; /* should it be 0x0400 */
1083 1.1 jdolecek chan->pitch.target = 0x0000; /* the unity pitch shift ? */
1084 1.1 jdolecek chan->pitch.envelope_amount = 0x00; /* none */
1085 1.1 jdolecek
1086 1.1 jdolecek chan->initial_attenuation = 0x00; /* no attenuation */
1087 1.1 jdolecek chan->volume.current = 0x0000; /* no volume */
1088 1.1 jdolecek chan->volume.target = 0xffff;
1089 1.1 jdolecek chan->volume.envelope.current_state = 0x8000; /* 0 msec delay */
1090 1.1 jdolecek chan->volume.envelope.hold_time = 0x7f; /* 0 msec */
1091 1.1 jdolecek chan->volume.envelope.attack_time = 0x7F; /* 5.5msec */
1092 1.1 jdolecek chan->volume.envelope.sustain_level = 0x7F; /* full */
1093 1.1 jdolecek chan->volume.envelope.decay_time = 0x7F; /* 22msec */
1094 1.1 jdolecek
1095 1.1 jdolecek chan->filter.initial_cutoff_frequency = 0xff; /* no filter */
1096 1.1 jdolecek chan->filter.current_cutoff_frequency = 0xffff; /* no filtering */
1097 1.1 jdolecek chan->filter.target_cutoff_frequency = 0xffff; /* no filtering */
1098 1.1 jdolecek chan->filter.lowpass_resonance_height = 0x0;
1099 1.1 jdolecek chan->filter.interpolation_ROM = 0x1; /* full band */
1100 1.1 jdolecek chan->filter.envelope_amount = 0x7f; /* none */
1101 1.1 jdolecek chan->filter.LFO_modulation_depth = 0x00; /* none */
1102 1.1 jdolecek
1103 1.1 jdolecek chan->loop.start = 0x000000;
1104 1.1 jdolecek chan->loop.end = 0x000010; /* Why ? */
1105 1.1 jdolecek
1106 1.1 jdolecek chan->modulation.envelope.current_state = 0x8000;
1107 1.1 jdolecek chan->modulation.envelope.hold_time = 0x00; /* 127 better ? */
1108 1.1 jdolecek chan->modulation.envelope.attack_time = 0x00; /* infinite */
1109 1.1 jdolecek chan->modulation.envelope.sustain_level = 0x00; /* off */
1110 1.1 jdolecek chan->modulation.envelope.decay_time = 0x7f; /* 22 msec */
1111 1.1 jdolecek chan->modulation.LFO_state = 0x8000;
1112 1.1 jdolecek
1113 1.1 jdolecek chan->vibrato_LFO.state = 0x8000;
1114 1.1 jdolecek chan->vibrato_LFO.modulation_depth = 0x00; /* none */
1115 1.1 jdolecek chan->vibrato_LFO.vibrato_depth = 0x00;
1116 1.1 jdolecek chan->vibrato_LFO.frequency = 0x00; /* Why set to 24 when
1117 1.1 jdolecek * initialized ? */
1118 1.1 jdolecek
1119 1.1 jdolecek chan->tremolo_depth = 0x00;
1120 1.1 jdolecek }
1121 1.1 jdolecek
1122 1.1 jdolecek /* only call it at splaudio */
1123 1.1 jdolecek static struct emuxki_channel *
1124 1.1 jdolecek emuxki_channel_new(struct emuxki_voice *voice, u_int8_t num)
1125 1.1 jdolecek {
1126 1.1 jdolecek struct emuxki_channel *chan;
1127 1.1 jdolecek
1128 1.1 jdolecek chan = malloc(sizeof(struct emuxki_channel), M_DEVBUF, M_WAITOK);
1129 1.1 jdolecek if (chan == NULL)
1130 1.40 kent return NULL;
1131 1.1 jdolecek
1132 1.1 jdolecek chan->voice = voice;
1133 1.1 jdolecek chan->num = num;
1134 1.1 jdolecek emuxki_chanparms_set_defaults(chan);
1135 1.1 jdolecek chan->voice->sc->channel[num] = chan;
1136 1.40 kent return chan;
1137 1.1 jdolecek }
1138 1.1 jdolecek
1139 1.1 jdolecek /* only call it at splaudio */
1140 1.1 jdolecek static void
1141 1.1 jdolecek emuxki_channel_delete(struct emuxki_channel *chan)
1142 1.1 jdolecek {
1143 1.40 kent
1144 1.1 jdolecek chan->voice->sc->channel[chan->num] = NULL;
1145 1.1 jdolecek free(chan, M_DEVBUF);
1146 1.1 jdolecek }
1147 1.1 jdolecek
1148 1.1 jdolecek static void
1149 1.1 jdolecek emuxki_channel_set_fxsend(struct emuxki_channel *chan,
1150 1.40 kent struct emuxki_chanparms_fxsend *fxsend)
1151 1.1 jdolecek {
1152 1.1 jdolecek /* Could do a memcpy ...*/
1153 1.1 jdolecek chan->fxsend.a.level = fxsend->a.level;
1154 1.1 jdolecek chan->fxsend.b.level = fxsend->b.level;
1155 1.1 jdolecek chan->fxsend.c.level = fxsend->c.level;
1156 1.1 jdolecek chan->fxsend.d.level = fxsend->d.level;
1157 1.1 jdolecek chan->fxsend.a.dest = fxsend->a.dest;
1158 1.1 jdolecek chan->fxsend.b.dest = fxsend->b.dest;
1159 1.1 jdolecek chan->fxsend.c.dest = fxsend->c.dest;
1160 1.1 jdolecek chan->fxsend.d.dest = fxsend->d.dest;
1161 1.35 christos
1162 1.35 christos /* for audigy */
1163 1.35 christos chan->fxsend.e.level = fxsend->e.level;
1164 1.35 christos chan->fxsend.f.level = fxsend->f.level;
1165 1.35 christos chan->fxsend.g.level = fxsend->g.level;
1166 1.35 christos chan->fxsend.h.level = fxsend->h.level;
1167 1.35 christos chan->fxsend.e.dest = fxsend->e.dest;
1168 1.35 christos chan->fxsend.f.dest = fxsend->f.dest;
1169 1.35 christos chan->fxsend.g.dest = fxsend->g.dest;
1170 1.35 christos chan->fxsend.h.dest = fxsend->h.dest;
1171 1.1 jdolecek }
1172 1.1 jdolecek
1173 1.1 jdolecek static void
1174 1.40 kent emuxki_channel_set_srate(struct emuxki_channel *chan, uint32_t srate)
1175 1.1 jdolecek {
1176 1.40 kent
1177 1.1 jdolecek chan->pitch.target = (srate << 8) / 375;
1178 1.1 jdolecek chan->pitch.target = (chan->pitch.target >> 1) +
1179 1.1 jdolecek (chan->pitch.target & 1);
1180 1.1 jdolecek chan->pitch.target &= 0xffff;
1181 1.1 jdolecek chan->pitch.current = chan->pitch.target;
1182 1.17 wiz chan->pitch.initial =
1183 1.1 jdolecek (emuxki_rate_to_pitch(srate) >> 8) & EMU_CHAN_IP_MASK;
1184 1.1 jdolecek }
1185 1.1 jdolecek
1186 1.1 jdolecek /* voice params must be set before calling this */
1187 1.1 jdolecek static void
1188 1.1 jdolecek emuxki_channel_set_bufparms(struct emuxki_channel *chan,
1189 1.40 kent uint32_t start, uint32_t end)
1190 1.1 jdolecek {
1191 1.40 kent
1192 1.1 jdolecek chan->loop.start = start & EMU_CHAN_PSST_LOOPSTARTADDR_MASK;
1193 1.1 jdolecek chan->loop.end = end & EMU_CHAN_DSL_LOOPENDADDR_MASK;
1194 1.1 jdolecek }
1195 1.1 jdolecek
1196 1.1 jdolecek static void
1197 1.35 christos emuxki_channel_commit_fx(struct emuxki_channel *chan)
1198 1.35 christos {
1199 1.40 kent struct emuxki_softc *sc;
1200 1.40 kent u_int8_t chano;
1201 1.40 kent
1202 1.40 kent sc = chan->voice->sc;
1203 1.40 kent chano = chan->num;
1204 1.40 kent if(sc->sc_type & EMUXKI_AUDIGY) {
1205 1.40 kent emuxki_write(sc, chano, EMU_A_CHAN_FXRT1,
1206 1.40 kent (chan->fxsend.d.dest << 24) |
1207 1.40 kent (chan->fxsend.c.dest << 16) |
1208 1.40 kent (chan->fxsend.b.dest << 8) |
1209 1.40 kent (chan->fxsend.a.dest));
1210 1.40 kent emuxki_write(sc, chano, EMU_A_CHAN_FXRT2,
1211 1.40 kent (chan->fxsend.h.dest << 24) |
1212 1.40 kent (chan->fxsend.g.dest << 16) |
1213 1.40 kent (chan->fxsend.f.dest << 8) |
1214 1.40 kent (chan->fxsend.e.dest));
1215 1.40 kent emuxki_write(sc, chano, EMU_A_CHAN_SENDAMOUNTS,
1216 1.40 kent (chan->fxsend.e.level << 24) |
1217 1.40 kent (chan->fxsend.f.level << 16) |
1218 1.40 kent (chan->fxsend.g.level << 8) |
1219 1.40 kent (chan->fxsend.h.level));
1220 1.40 kent } else {
1221 1.40 kent emuxki_write(sc, chano, EMU_CHAN_FXRT,
1222 1.40 kent (chan->fxsend.d.dest << 28) |
1223 1.40 kent (chan->fxsend.c.dest << 24) |
1224 1.40 kent (chan->fxsend.b.dest << 20) |
1225 1.40 kent (chan->fxsend.a.dest << 16));
1226 1.40 kent }
1227 1.40 kent
1228 1.40 kent emuxki_write(sc, chano, 0x10000000 | EMU_CHAN_PTRX,
1229 1.40 kent (chan->fxsend.a.level << 8) | chan->fxsend.b.level);
1230 1.40 kent emuxki_write(sc, chano, EMU_CHAN_DSL,
1231 1.40 kent (chan->fxsend.d.level << 24) | chan->loop.end);
1232 1.40 kent emuxki_write(sc, chano, EMU_CHAN_PSST,
1233 1.40 kent (chan->fxsend.c.level << 24) | chan->loop.start);
1234 1.35 christos }
1235 1.35 christos
1236 1.35 christos static void
1237 1.1 jdolecek emuxki_channel_commit_parms(struct emuxki_channel *chan)
1238 1.1 jdolecek {
1239 1.40 kent struct emuxki_voice *voice;
1240 1.40 kent struct emuxki_softc *sc;
1241 1.40 kent uint32_t start, mapval;
1242 1.40 kent uint8_t chano;
1243 1.1 jdolecek
1244 1.40 kent voice = chan->voice;
1245 1.40 kent sc = voice->sc;
1246 1.40 kent chano = chan->num;
1247 1.1 jdolecek start = chan->loop.start +
1248 1.1 jdolecek (voice->stereo ? 28 : 30) * (voice->b16 + 1);
1249 1.1 jdolecek mapval = DMAADDR(sc->silentpage) << 1 | EMU_CHAN_MAP_PTI_MASK;
1250 1.1 jdolecek
1251 1.60 jmcneill KASSERT(mutex_owned(&sc->sc_intr_lock));
1252 1.1 jdolecek emuxki_write(sc, chano, EMU_CHAN_CPF_STEREO, voice->stereo);
1253 1.35 christos
1254 1.35 christos emuxki_channel_commit_fx(chan);
1255 1.35 christos
1256 1.1 jdolecek emuxki_write(sc, chano, EMU_CHAN_CCCA,
1257 1.1 jdolecek (chan->filter.lowpass_resonance_height << 28) |
1258 1.1 jdolecek (chan->filter.interpolation_ROM << 25) |
1259 1.1 jdolecek (voice->b16 ? 0 : EMU_CHAN_CCCA_8BITSELECT) | start);
1260 1.1 jdolecek emuxki_write(sc, chano, EMU_CHAN_Z1, 0);
1261 1.1 jdolecek emuxki_write(sc, chano, EMU_CHAN_Z2, 0);
1262 1.1 jdolecek emuxki_write(sc, chano, EMU_CHAN_MAPA, mapval);
1263 1.1 jdolecek emuxki_write(sc, chano, EMU_CHAN_MAPB, mapval);
1264 1.1 jdolecek emuxki_write(sc, chano, EMU_CHAN_CVCF_CURRFILTER,
1265 1.1 jdolecek chan->filter.current_cutoff_frequency);
1266 1.1 jdolecek emuxki_write(sc, chano, EMU_CHAN_VTFT_FILTERTARGET,
1267 1.1 jdolecek chan->filter.target_cutoff_frequency);
1268 1.1 jdolecek emuxki_write(sc, chano, EMU_CHAN_ATKHLDM,
1269 1.1 jdolecek (chan->modulation.envelope.hold_time << 8) |
1270 1.1 jdolecek chan->modulation.envelope.attack_time);
1271 1.1 jdolecek emuxki_write(sc, chano, EMU_CHAN_DCYSUSM,
1272 1.1 jdolecek (chan->modulation.envelope.sustain_level << 8) |
1273 1.1 jdolecek chan->modulation.envelope.decay_time);
1274 1.1 jdolecek emuxki_write(sc, chano, EMU_CHAN_LFOVAL1,
1275 1.1 jdolecek chan->modulation.LFO_state);
1276 1.1 jdolecek emuxki_write(sc, chano, EMU_CHAN_LFOVAL2,
1277 1.1 jdolecek chan->vibrato_LFO.state);
1278 1.1 jdolecek emuxki_write(sc, chano, EMU_CHAN_FMMOD,
1279 1.1 jdolecek (chan->vibrato_LFO.modulation_depth << 8) |
1280 1.1 jdolecek chan->filter.LFO_modulation_depth);
1281 1.1 jdolecek emuxki_write(sc, chano, EMU_CHAN_TREMFRQ,
1282 1.1 jdolecek (chan->tremolo_depth << 8));
1283 1.1 jdolecek emuxki_write(sc, chano, EMU_CHAN_FM2FRQ2,
1284 1.1 jdolecek (chan->vibrato_LFO.vibrato_depth << 8) |
1285 1.1 jdolecek chan->vibrato_LFO.frequency);
1286 1.1 jdolecek emuxki_write(sc, chano, EMU_CHAN_ENVVAL,
1287 1.1 jdolecek chan->modulation.envelope.current_state);
1288 1.1 jdolecek emuxki_write(sc, chano, EMU_CHAN_ATKHLDV,
1289 1.1 jdolecek (chan->volume.envelope.hold_time << 8) |
1290 1.1 jdolecek chan->volume.envelope.attack_time);
1291 1.1 jdolecek emuxki_write(sc, chano, EMU_CHAN_ENVVOL,
1292 1.1 jdolecek chan->volume.envelope.current_state);
1293 1.1 jdolecek emuxki_write(sc, chano, EMU_CHAN_PEFE,
1294 1.1 jdolecek (chan->pitch.envelope_amount << 8) |
1295 1.1 jdolecek chan->filter.envelope_amount);
1296 1.1 jdolecek }
1297 1.1 jdolecek
1298 1.1 jdolecek static void
1299 1.1 jdolecek emuxki_channel_start(struct emuxki_channel *chan)
1300 1.1 jdolecek {
1301 1.40 kent struct emuxki_voice *voice;
1302 1.40 kent struct emuxki_softc *sc;
1303 1.40 kent u_int8_t cache_sample, cache_invalid_size, chano;
1304 1.40 kent u_int32_t sample;
1305 1.1 jdolecek
1306 1.40 kent voice = chan->voice;
1307 1.40 kent sc = voice->sc;
1308 1.40 kent chano = chan->num;
1309 1.1 jdolecek cache_sample = voice->stereo ? 4 : 2;
1310 1.1 jdolecek sample = voice->b16 ? 0x00000000 : 0x80808080;
1311 1.1 jdolecek cache_invalid_size = (voice->stereo ? 28 : 30) * (voice->b16 + 1);
1312 1.1 jdolecek
1313 1.60 jmcneill KASSERT(mutex_owned(&sc->sc_intr_lock));
1314 1.1 jdolecek while (cache_sample--) {
1315 1.1 jdolecek emuxki_write(sc, chano, EMU_CHAN_CD0 + cache_sample,
1316 1.1 jdolecek sample);
1317 1.1 jdolecek }
1318 1.1 jdolecek emuxki_write(sc, chano, EMU_CHAN_CCR_CACHEINVALIDSIZE, 0);
1319 1.1 jdolecek emuxki_write(sc, chano, EMU_CHAN_CCR_READADDRESS, 64);
1320 1.1 jdolecek emuxki_write(sc, chano, EMU_CHAN_CCR_CACHEINVALIDSIZE,
1321 1.1 jdolecek cache_invalid_size);
1322 1.1 jdolecek emuxki_write(sc, chano, EMU_CHAN_IFATN,
1323 1.1 jdolecek (chan->filter.target_cutoff_frequency << 8) |
1324 1.1 jdolecek chan->initial_attenuation);
1325 1.1 jdolecek emuxki_write(sc, chano, EMU_CHAN_VTFT_VOLUMETARGET,
1326 1.1 jdolecek chan->volume.target);
1327 1.1 jdolecek emuxki_write(sc, chano, EMU_CHAN_CVCF_CURRVOL,
1328 1.1 jdolecek chan->volume.current);
1329 1.1 jdolecek emuxki_write(sc, 0,
1330 1.1 jdolecek EMU_MKSUBREG(1, chano, EMU_SOLEL + (chano >> 5)),
1331 1.1 jdolecek 0); /* Clear stop on loop */
1332 1.1 jdolecek emuxki_write(sc, 0,
1333 1.1 jdolecek EMU_MKSUBREG(1, chano, EMU_CLIEL + (chano >> 5)),
1334 1.1 jdolecek 0); /* Clear loop interrupt */
1335 1.1 jdolecek emuxki_write(sc, chano, EMU_CHAN_DCYSUSV,
1336 1.1 jdolecek (chan->volume.envelope.sustain_level << 8) |
1337 1.1 jdolecek chan->volume.envelope.decay_time);
1338 1.1 jdolecek emuxki_write(sc, chano, EMU_CHAN_PTRX_PITCHTARGET,
1339 1.1 jdolecek chan->pitch.target);
1340 1.1 jdolecek emuxki_write(sc, chano, EMU_CHAN_CPF_PITCH,
1341 1.1 jdolecek chan->pitch.current);
1342 1.17 wiz emuxki_write(sc, chano, EMU_CHAN_IP, chan->pitch.initial);
1343 1.1 jdolecek }
1344 1.1 jdolecek
1345 1.1 jdolecek static void
1346 1.1 jdolecek emuxki_channel_stop(struct emuxki_channel *chan)
1347 1.1 jdolecek {
1348 1.40 kent struct emuxki_softc *sc;
1349 1.40 kent u_int8_t chano;
1350 1.1 jdolecek
1351 1.40 kent sc = chan->voice->sc;
1352 1.40 kent chano = chan->num;
1353 1.60 jmcneill KASSERT(mutex_owned(&sc->sc_intr_lock));
1354 1.1 jdolecek emuxki_write(sc, chano, EMU_CHAN_PTRX_PITCHTARGET, 0);
1355 1.1 jdolecek emuxki_write(sc, chano, EMU_CHAN_CPF_PITCH, 0);
1356 1.1 jdolecek emuxki_write(sc, chano, EMU_CHAN_IFATN_ATTENUATION, 0xff);
1357 1.1 jdolecek emuxki_write(sc, chano, EMU_CHAN_VTFT_VOLUMETARGET, 0);
1358 1.1 jdolecek emuxki_write(sc, chano, EMU_CHAN_CVCF_CURRVOL, 0);
1359 1.1 jdolecek emuxki_write(sc, chano, EMU_CHAN_IP, 0);
1360 1.1 jdolecek }
1361 1.1 jdolecek
1362 1.1 jdolecek /*
1363 1.25 wiz * Voices management
1364 1.37 dsainty * emuxki_voice_dataloc : use(play or rec) independent dataloc union helpers
1365 1.1 jdolecek * emuxki_voice_channel_* : play part of dataloc union helpers
1366 1.1 jdolecek * emuxki_voice_recsrc_* : rec part of dataloc union helpers
1367 1.1 jdolecek */
1368 1.1 jdolecek
1369 1.1 jdolecek /* Allocate channels for voice in case of play voice */
1370 1.1 jdolecek static int
1371 1.1 jdolecek emuxki_voice_channel_create(struct emuxki_voice *voice)
1372 1.1 jdolecek {
1373 1.40 kent struct emuxki_channel **channel;
1374 1.40 kent uint8_t i, stereo;
1375 1.1 jdolecek
1376 1.40 kent channel = voice->sc->channel;
1377 1.40 kent stereo = voice->stereo;
1378 1.45 christos for (i = 0; i < EMU_NUMCHAN - stereo; i += stereo + 1) {
1379 1.1 jdolecek if ((stereo && (channel[i + 1] != NULL)) ||
1380 1.1 jdolecek (channel[i] != NULL)) /* Looking for free channels */
1381 1.1 jdolecek continue;
1382 1.60 jmcneill
1383 1.1 jdolecek if (stereo) {
1384 1.1 jdolecek voice->dataloc.chan[1] =
1385 1.1 jdolecek emuxki_channel_new(voice, i + 1);
1386 1.60 jmcneill if (voice->dataloc.chan[1] == NULL)
1387 1.40 kent return ENOMEM;
1388 1.1 jdolecek }
1389 1.1 jdolecek voice->dataloc.chan[0] = emuxki_channel_new(voice, i);
1390 1.1 jdolecek if (voice->dataloc.chan[0] == NULL) {
1391 1.1 jdolecek if (stereo) {
1392 1.1 jdolecek emuxki_channel_delete(voice->dataloc.chan[1]);
1393 1.1 jdolecek voice->dataloc.chan[1] = NULL;
1394 1.1 jdolecek }
1395 1.40 kent return ENOMEM;
1396 1.1 jdolecek }
1397 1.40 kent return 0;
1398 1.1 jdolecek }
1399 1.40 kent return EAGAIN;
1400 1.1 jdolecek }
1401 1.1 jdolecek
1402 1.1 jdolecek /* When calling this function we assume no one can access the voice */
1403 1.1 jdolecek static void
1404 1.1 jdolecek emuxki_voice_channel_destroy(struct emuxki_voice *voice)
1405 1.1 jdolecek {
1406 1.40 kent
1407 1.1 jdolecek emuxki_channel_delete(voice->dataloc.chan[0]);
1408 1.1 jdolecek voice->dataloc.chan[0] = NULL;
1409 1.1 jdolecek if (voice->stereo)
1410 1.1 jdolecek emuxki_channel_delete(voice->dataloc.chan[1]);
1411 1.1 jdolecek voice->dataloc.chan[1] = NULL;
1412 1.1 jdolecek }
1413 1.1 jdolecek
1414 1.1 jdolecek /*
1415 1.1 jdolecek * Will come back when used in voice_dataloc_create
1416 1.1 jdolecek */
1417 1.1 jdolecek static int
1418 1.1 jdolecek emuxki_recsrc_reserve(struct emuxki_voice *voice, emuxki_recsrc_t source)
1419 1.1 jdolecek {
1420 1.40 kent
1421 1.46 christos if (source >= EMU_NUMRECSRCS) {
1422 1.19 toshii #ifdef EMUXKI_DEBUG
1423 1.37 dsainty printf("Tried to reserve invalid source: %d\n", source);
1424 1.19 toshii #endif
1425 1.40 kent return EINVAL;
1426 1.19 toshii }
1427 1.19 toshii if (voice->sc->recsrc[source] == voice)
1428 1.40 kent return 0; /* XXX */
1429 1.19 toshii if (voice->sc->recsrc[source] != NULL)
1430 1.40 kent return EBUSY;
1431 1.19 toshii voice->sc->recsrc[source] = voice;
1432 1.40 kent return 0;
1433 1.1 jdolecek }
1434 1.19 toshii
1435 1.1 jdolecek /* When calling this function we assume the voice is stopped */
1436 1.1 jdolecek static void
1437 1.1 jdolecek emuxki_voice_recsrc_release(struct emuxki_softc *sc, emuxki_recsrc_t source)
1438 1.1 jdolecek {
1439 1.40 kent
1440 1.1 jdolecek sc->recsrc[source] = NULL;
1441 1.1 jdolecek }
1442 1.1 jdolecek
1443 1.1 jdolecek static int
1444 1.1 jdolecek emuxki_voice_dataloc_create(struct emuxki_voice *voice)
1445 1.1 jdolecek {
1446 1.40 kent int error;
1447 1.1 jdolecek
1448 1.1 jdolecek if (voice->use & EMU_VOICE_USE_PLAY) {
1449 1.1 jdolecek if ((error = emuxki_voice_channel_create(voice)))
1450 1.40 kent return error;
1451 1.1 jdolecek } else {
1452 1.19 toshii if ((error =
1453 1.19 toshii emuxki_recsrc_reserve(voice, voice->dataloc.source)))
1454 1.40 kent return error;
1455 1.1 jdolecek }
1456 1.40 kent return 0;
1457 1.1 jdolecek }
1458 1.1 jdolecek
1459 1.1 jdolecek static void
1460 1.1 jdolecek emuxki_voice_dataloc_destroy(struct emuxki_voice *voice)
1461 1.1 jdolecek {
1462 1.40 kent
1463 1.1 jdolecek if (voice->use & EMU_VOICE_USE_PLAY) {
1464 1.1 jdolecek if (voice->dataloc.chan[0] != NULL)
1465 1.1 jdolecek emuxki_voice_channel_destroy(voice);
1466 1.1 jdolecek } else {
1467 1.1 jdolecek if (voice->dataloc.source != EMU_RECSRC_NOTSET) {
1468 1.1 jdolecek emuxki_voice_recsrc_release(voice->sc,
1469 1.1 jdolecek voice->dataloc.source);
1470 1.1 jdolecek voice->dataloc.source = EMU_RECSRC_NOTSET;
1471 1.1 jdolecek }
1472 1.1 jdolecek }
1473 1.1 jdolecek }
1474 1.1 jdolecek
1475 1.1 jdolecek static struct emuxki_voice *
1476 1.40 kent emuxki_voice_new(struct emuxki_softc *sc, uint8_t use)
1477 1.1 jdolecek {
1478 1.1 jdolecek struct emuxki_voice *voice;
1479 1.1 jdolecek
1480 1.60 jmcneill KASSERT(mutex_owned(&sc->sc_intr_lock));
1481 1.60 jmcneill
1482 1.7 jdolecek voice = sc->lvoice;
1483 1.7 jdolecek sc->lvoice = NULL;
1484 1.7 jdolecek
1485 1.24 toshii if (!voice) {
1486 1.60 jmcneill mutex_exit(&sc->sc_intr_lock);
1487 1.60 jmcneill voice = kmem_alloc(sizeof(*voice), KM_SLEEP);
1488 1.60 jmcneill mutex_enter(&sc->sc_intr_lock);
1489 1.60 jmcneill if (!voice)
1490 1.40 kent return NULL;
1491 1.60 jmcneill } else if (voice->use != use) {
1492 1.60 jmcneill mutex_exit(&sc->sc_intr_lock);
1493 1.24 toshii emuxki_voice_dataloc_destroy(voice);
1494 1.60 jmcneill mutex_enter(&sc->sc_intr_lock);
1495 1.60 jmcneill } else
1496 1.24 toshii goto skip_initialize;
1497 1.19 toshii
1498 1.19 toshii voice->sc = sc;
1499 1.19 toshii voice->state = !EMU_VOICE_STATE_STARTED;
1500 1.19 toshii voice->stereo = EMU_VOICE_STEREO_NOTSET;
1501 1.19 toshii voice->b16 = 0;
1502 1.19 toshii voice->sample_rate = 0;
1503 1.19 toshii if (use & EMU_VOICE_USE_PLAY)
1504 1.19 toshii voice->dataloc.chan[0] = voice->dataloc.chan[1] = NULL;
1505 1.19 toshii else
1506 1.19 toshii voice->dataloc.source = EMU_RECSRC_NOTSET;
1507 1.19 toshii voice->buffer = NULL;
1508 1.19 toshii voice->blksize = 0;
1509 1.19 toshii voice->trigblk = 0;
1510 1.19 toshii voice->blkmod = 0;
1511 1.19 toshii voice->inth = NULL;
1512 1.19 toshii voice->inthparam = NULL;
1513 1.1 jdolecek voice->use = use;
1514 1.1 jdolecek
1515 1.24 toshii skip_initialize:
1516 1.1 jdolecek LIST_INSERT_HEAD((&sc->voices), voice, next);
1517 1.1 jdolecek
1518 1.40 kent return voice;
1519 1.1 jdolecek }
1520 1.1 jdolecek
1521 1.1 jdolecek static void
1522 1.1 jdolecek emuxki_voice_delete(struct emuxki_voice *voice)
1523 1.1 jdolecek {
1524 1.40 kent struct emuxki_softc *sc;
1525 1.7 jdolecek struct emuxki_voice *lvoice;
1526 1.1 jdolecek
1527 1.40 kent sc = voice->sc;
1528 1.1 jdolecek if (voice->state & EMU_VOICE_STATE_STARTED)
1529 1.1 jdolecek emuxki_voice_halt(voice);
1530 1.1 jdolecek
1531 1.1 jdolecek LIST_REMOVE(voice, next);
1532 1.7 jdolecek lvoice = sc->lvoice;
1533 1.7 jdolecek sc->lvoice = voice;
1534 1.1 jdolecek
1535 1.7 jdolecek if (lvoice) {
1536 1.60 jmcneill mutex_exit(&sc->sc_lock);
1537 1.7 jdolecek emuxki_voice_dataloc_destroy(lvoice);
1538 1.60 jmcneill kmem_free(lvoice, sizeof(*lvoice));
1539 1.60 jmcneill mutex_enter(&sc->sc_lock);
1540 1.7 jdolecek }
1541 1.1 jdolecek }
1542 1.1 jdolecek
1543 1.1 jdolecek static int
1544 1.60 jmcneill emuxki_voice_set_stereo(struct emuxki_softc *sc,
1545 1.60 jmcneill struct emuxki_voice *voice, uint8_t stereo)
1546 1.1 jdolecek {
1547 1.40 kent int error;
1548 1.40 kent emuxki_recsrc_t source;
1549 1.1 jdolecek struct emuxki_chanparms_fxsend fxsend;
1550 1.1 jdolecek
1551 1.40 kent source = 0; /* XXX: gcc */
1552 1.19 toshii if (! (voice->use & EMU_VOICE_USE_PLAY))
1553 1.19 toshii source = voice->dataloc.source;
1554 1.60 jmcneill mutex_exit(&sc->sc_lock);
1555 1.1 jdolecek emuxki_voice_dataloc_destroy(voice);
1556 1.19 toshii if (! (voice->use & EMU_VOICE_USE_PLAY))
1557 1.19 toshii voice->dataloc.source = source;
1558 1.1 jdolecek voice->stereo = stereo;
1559 1.60 jmcneill error = emuxki_voice_dataloc_create(voice);
1560 1.60 jmcneill mutex_enter(&sc->sc_lock);
1561 1.60 jmcneill if (error)
1562 1.40 kent return error;
1563 1.1 jdolecek if (voice->use & EMU_VOICE_USE_PLAY) {
1564 1.1 jdolecek fxsend.a.dest = 0x0;
1565 1.1 jdolecek fxsend.b.dest = 0x1;
1566 1.1 jdolecek fxsend.c.dest = 0x2;
1567 1.1 jdolecek fxsend.d.dest = 0x3;
1568 1.35 christos /* for audigy */
1569 1.35 christos fxsend.e.dest = 0x4;
1570 1.35 christos fxsend.f.dest = 0x5;
1571 1.35 christos fxsend.g.dest = 0x6;
1572 1.35 christos fxsend.h.dest = 0x7;
1573 1.1 jdolecek if (voice->stereo) {
1574 1.7 jdolecek fxsend.a.level = fxsend.c.level = 0xc0;
1575 1.1 jdolecek fxsend.b.level = fxsend.d.level = 0x00;
1576 1.35 christos fxsend.e.level = fxsend.g.level = 0xc0;
1577 1.35 christos fxsend.f.level = fxsend.h.level = 0x00;
1578 1.1 jdolecek emuxki_channel_set_fxsend(voice->dataloc.chan[0],
1579 1.1 jdolecek &fxsend);
1580 1.1 jdolecek fxsend.a.level = fxsend.c.level = 0x00;
1581 1.7 jdolecek fxsend.b.level = fxsend.d.level = 0xc0;
1582 1.35 christos fxsend.e.level = fxsend.g.level = 0x00;
1583 1.35 christos fxsend.f.level = fxsend.h.level = 0xc0;
1584 1.1 jdolecek emuxki_channel_set_fxsend(voice->dataloc.chan[1],
1585 1.1 jdolecek &fxsend);
1586 1.40 kent } /* No else : default is good for mono */
1587 1.1 jdolecek }
1588 1.40 kent return 0;
1589 1.1 jdolecek }
1590 1.1 jdolecek
1591 1.1 jdolecek static int
1592 1.40 kent emuxki_voice_set_srate(struct emuxki_voice *voice, uint32_t srate)
1593 1.1 jdolecek {
1594 1.40 kent
1595 1.1 jdolecek if (voice->use & EMU_VOICE_USE_PLAY) {
1596 1.1 jdolecek if ((srate < 4000) || (srate > 48000))
1597 1.40 kent return EINVAL;
1598 1.1 jdolecek voice->sample_rate = srate;
1599 1.1 jdolecek emuxki_channel_set_srate(voice->dataloc.chan[0], srate);
1600 1.1 jdolecek if (voice->stereo)
1601 1.1 jdolecek emuxki_channel_set_srate(voice->dataloc.chan[1],
1602 1.1 jdolecek srate);
1603 1.1 jdolecek } else {
1604 1.35 christos if ((srate < 8000) || (srate > 48000))
1605 1.40 kent return EINVAL;
1606 1.19 toshii voice->sample_rate = srate;
1607 1.35 christos if (emuxki_voice_adc_rate(voice) < 0) {
1608 1.35 christos voice->sample_rate = 0;
1609 1.40 kent return EINVAL;
1610 1.35 christos }
1611 1.1 jdolecek }
1612 1.40 kent return 0;
1613 1.1 jdolecek }
1614 1.1 jdolecek
1615 1.1 jdolecek static int
1616 1.60 jmcneill emuxki_voice_set_audioparms(struct emuxki_softc *sc,
1617 1.60 jmcneill struct emuxki_voice *voice, uint8_t stereo, uint8_t b16, uint32_t srate)
1618 1.1 jdolecek {
1619 1.40 kent int error;
1620 1.1 jdolecek
1621 1.1 jdolecek if (voice->stereo == stereo && voice->b16 == b16 &&
1622 1.1 jdolecek voice->sample_rate == srate)
1623 1.40 kent return 0;
1624 1.1 jdolecek
1625 1.1 jdolecek #ifdef EMUXKI_DEBUG
1626 1.18 tsutsui printf("Setting %s voice params : %s, %u bits, %u Hz\n",
1627 1.1 jdolecek (voice->use & EMU_VOICE_USE_PLAY) ? "play" : "record",
1628 1.1 jdolecek stereo ? "stereo" : "mono", (b16 + 1) * 8, srate);
1629 1.1 jdolecek #endif
1630 1.40 kent error = 0;
1631 1.1 jdolecek if (voice->stereo != stereo) {
1632 1.60 jmcneill if ((error = emuxki_voice_set_stereo(sc, voice, stereo)))
1633 1.40 kent return error;
1634 1.1 jdolecek }
1635 1.1 jdolecek voice->b16 = b16;
1636 1.1 jdolecek if (voice->sample_rate != srate)
1637 1.23 toshii error = emuxki_voice_set_srate(voice, srate);
1638 1.23 toshii return error;
1639 1.1 jdolecek }
1640 1.1 jdolecek
1641 1.1 jdolecek /* voice audio parms (see just before) must be set prior to this */
1642 1.1 jdolecek static int
1643 1.1 jdolecek emuxki_voice_set_bufparms(struct emuxki_voice *voice, void *ptr,
1644 1.40 kent uint32_t bufsize, uint16_t blksize)
1645 1.1 jdolecek {
1646 1.1 jdolecek struct emuxki_mem *mem;
1647 1.1 jdolecek struct emuxki_channel **chan;
1648 1.40 kent uint32_t start, end;
1649 1.40 kent uint8_t sample_size;
1650 1.19 toshii int idx;
1651 1.40 kent int error;
1652 1.1 jdolecek
1653 1.40 kent error = EFAULT;
1654 1.1 jdolecek LIST_FOREACH(mem, &voice->sc->mem, next) {
1655 1.1 jdolecek if (KERNADDR(mem->dmamem) != ptr)
1656 1.1 jdolecek continue;
1657 1.1 jdolecek
1658 1.1 jdolecek voice->buffer = mem;
1659 1.1 jdolecek sample_size = (voice->b16 + 1) * (voice->stereo + 1);
1660 1.1 jdolecek voice->trigblk = 0; /* This shouldn't be needed */
1661 1.1 jdolecek voice->blkmod = bufsize / blksize;
1662 1.40 kent if (bufsize % blksize) /* This should not happen */
1663 1.1 jdolecek voice->blkmod++;
1664 1.1 jdolecek error = 0;
1665 1.1 jdolecek
1666 1.1 jdolecek if (voice->use & EMU_VOICE_USE_PLAY) {
1667 1.19 toshii voice->blksize = blksize / sample_size;
1668 1.1 jdolecek chan = voice->dataloc.chan;
1669 1.1 jdolecek start = mem->ptbidx << 12;
1670 1.1 jdolecek end = start + bufsize / sample_size;
1671 1.1 jdolecek emuxki_channel_set_bufparms(chan[0],
1672 1.1 jdolecek start, end);
1673 1.1 jdolecek if (voice->stereo)
1674 1.1 jdolecek emuxki_channel_set_bufparms(chan[1],
1675 1.1 jdolecek start, end);
1676 1.40 kent voice->timerate = (uint32_t) 48000 *
1677 1.40 kent voice->blksize / voice->sample_rate;
1678 1.1 jdolecek if (voice->timerate < 5)
1679 1.1 jdolecek error = EINVAL;
1680 1.1 jdolecek } else {
1681 1.19 toshii voice->blksize = blksize;
1682 1.19 toshii for(idx = sizeof(emuxki_recbuf_sz) /
1683 1.19 toshii sizeof(emuxki_recbuf_sz[0]); --idx >= 0;)
1684 1.19 toshii if (emuxki_recbuf_sz[idx] == bufsize)
1685 1.19 toshii break;
1686 1.19 toshii if (idx < 0) {
1687 1.19 toshii #ifdef EMUXKI_DEBUG
1688 1.19 toshii printf("Invalid bufsize: %d\n", bufsize);
1689 1.19 toshii #endif
1690 1.40 kent return EINVAL;
1691 1.19 toshii }
1692 1.19 toshii emuxki_write(voice->sc, 0,
1693 1.19 toshii emuxki_recsrc_szreg[voice->dataloc.source], idx);
1694 1.19 toshii emuxki_write(voice->sc, 0,
1695 1.19 toshii emuxki_recsrc_bufaddrreg[voice->dataloc.source],
1696 1.19 toshii DMAADDR(mem->dmamem));
1697 1.19 toshii
1698 1.19 toshii /* Use timer to emulate DMA completion interrupt */
1699 1.19 toshii voice->timerate = (u_int32_t) 48000 * blksize /
1700 1.19 toshii (voice->sample_rate * sample_size);
1701 1.19 toshii if (voice->timerate < 5) {
1702 1.1 jdolecek #ifdef EMUXKI_DEBUG
1703 1.19 toshii printf("Invalid timerate: %d, blksize %d\n",
1704 1.19 toshii voice->timerate, blksize);
1705 1.1 jdolecek #endif
1706 1.19 toshii error = EINVAL;
1707 1.19 toshii }
1708 1.1 jdolecek }
1709 1.1 jdolecek
1710 1.1 jdolecek break;
1711 1.1 jdolecek }
1712 1.1 jdolecek
1713 1.40 kent return error;
1714 1.1 jdolecek }
1715 1.1 jdolecek
1716 1.1 jdolecek static void
1717 1.1 jdolecek emuxki_voice_commit_parms(struct emuxki_voice *voice)
1718 1.1 jdolecek {
1719 1.1 jdolecek if (voice->use & EMU_VOICE_USE_PLAY) {
1720 1.1 jdolecek emuxki_channel_commit_parms(voice->dataloc.chan[0]);
1721 1.1 jdolecek if (voice->stereo)
1722 1.1 jdolecek emuxki_channel_commit_parms(voice->dataloc.chan[1]);
1723 1.1 jdolecek }
1724 1.1 jdolecek }
1725 1.1 jdolecek
1726 1.40 kent static uint32_t
1727 1.1 jdolecek emuxki_voice_curaddr(struct emuxki_voice *voice)
1728 1.1 jdolecek {
1729 1.40 kent int idxreg;
1730 1.53 gmcgarry int rv;
1731 1.19 toshii
1732 1.19 toshii /* XXX different semantics in these cases */
1733 1.35 christos if (voice->use & EMU_VOICE_USE_PLAY) {
1734 1.19 toshii /* returns number of samples (an l/r pair counts 1) */
1735 1.53 gmcgarry rv = emuxki_read(voice->sc,
1736 1.40 kent voice->dataloc.chan[0]->num, EMU_CHAN_CCCA_CURRADDR) -
1737 1.40 kent voice->dataloc.chan[0]->loop.start;
1738 1.35 christos } else {
1739 1.40 kent idxreg = 0;
1740 1.19 toshii /* returns number of bytes */
1741 1.35 christos switch (voice->dataloc.source) {
1742 1.35 christos case EMU_RECSRC_MIC:
1743 1.35 christos idxreg = (voice->sc->sc_type & EMUXKI_AUDIGY) ?
1744 1.35 christos EMU_A_MICIDX : EMU_MICIDX;
1745 1.35 christos break;
1746 1.35 christos case EMU_RECSRC_ADC:
1747 1.35 christos idxreg = (voice->sc->sc_type & EMUXKI_AUDIGY) ?
1748 1.35 christos EMU_A_ADCIDX : EMU_ADCIDX;
1749 1.35 christos break;
1750 1.35 christos case EMU_RECSRC_FX:
1751 1.35 christos idxreg = EMU_FXIDX;
1752 1.35 christos break;
1753 1.35 christos default:
1754 1.35 christos #ifdef EMUXKI_DEBUG
1755 1.35 christos printf("emu: bad recording source!\n");
1756 1.35 christos #endif
1757 1.35 christos break;
1758 1.35 christos }
1759 1.53 gmcgarry rv = emuxki_read(voice->sc, 0, EMU_RECIDX(idxreg)
1760 1.35 christos & EMU_RECIDX_MASK);
1761 1.35 christos }
1762 1.53 gmcgarry return rv;
1763 1.1 jdolecek }
1764 1.1 jdolecek
1765 1.1 jdolecek static void
1766 1.1 jdolecek emuxki_resched_timer(struct emuxki_softc *sc)
1767 1.1 jdolecek {
1768 1.1 jdolecek struct emuxki_voice *voice;
1769 1.40 kent uint16_t timerate;
1770 1.40 kent uint8_t active;
1771 1.1 jdolecek
1772 1.40 kent timerate = 1024;
1773 1.40 kent active = 0;
1774 1.60 jmcneill KASSERT(mutex_owned(&sc->sc_intr_lock));
1775 1.1 jdolecek LIST_FOREACH(voice, &sc->voices, next) {
1776 1.19 toshii if ((voice->state & EMU_VOICE_STATE_STARTED) == 0)
1777 1.1 jdolecek continue;
1778 1.1 jdolecek active = 1;
1779 1.1 jdolecek if (voice->timerate < timerate)
1780 1.1 jdolecek timerate = voice->timerate;
1781 1.1 jdolecek }
1782 1.1 jdolecek
1783 1.1 jdolecek if (timerate & ~EMU_TIMER_RATE_MASK)
1784 1.1 jdolecek timerate = 0;
1785 1.14 tron bus_space_write_2(sc->sc_iot, sc->sc_ioh, EMU_TIMER, timerate);
1786 1.1 jdolecek if (!active && (sc->timerstate & EMU_TIMER_STATE_ENABLED)) {
1787 1.1 jdolecek bus_space_write_4(sc->sc_iot, sc->sc_ioh, EMU_INTE,
1788 1.1 jdolecek bus_space_read_4(sc->sc_iot, sc->sc_ioh, EMU_INTE) &
1789 1.1 jdolecek ~EMU_INTE_INTERTIMERENB);
1790 1.1 jdolecek sc->timerstate &= ~EMU_TIMER_STATE_ENABLED;
1791 1.1 jdolecek } else if (active && !(sc->timerstate & EMU_TIMER_STATE_ENABLED)) {
1792 1.1 jdolecek bus_space_write_4(sc->sc_iot, sc->sc_ioh, EMU_INTE,
1793 1.1 jdolecek bus_space_read_4(sc->sc_iot, sc->sc_ioh, EMU_INTE) |
1794 1.1 jdolecek EMU_INTE_INTERTIMERENB);
1795 1.1 jdolecek sc->timerstate |= EMU_TIMER_STATE_ENABLED;
1796 1.1 jdolecek }
1797 1.1 jdolecek }
1798 1.1 jdolecek
1799 1.35 christos static int
1800 1.35 christos emuxki_voice_adc_rate(struct emuxki_voice *voice)
1801 1.35 christos {
1802 1.40 kent
1803 1.35 christos switch(voice->sample_rate) {
1804 1.35 christos case 48000:
1805 1.35 christos return EMU_ADCCR_SAMPLERATE_48;
1806 1.35 christos break;
1807 1.35 christos case 44100:
1808 1.35 christos return EMU_ADCCR_SAMPLERATE_44;
1809 1.35 christos break;
1810 1.35 christos case 32000:
1811 1.35 christos return EMU_ADCCR_SAMPLERATE_32;
1812 1.35 christos break;
1813 1.35 christos case 24000:
1814 1.35 christos return EMU_ADCCR_SAMPLERATE_24;
1815 1.35 christos break;
1816 1.35 christos case 22050:
1817 1.35 christos return EMU_ADCCR_SAMPLERATE_22;
1818 1.35 christos break;
1819 1.35 christos case 16000:
1820 1.35 christos return EMU_ADCCR_SAMPLERATE_16;
1821 1.35 christos break;
1822 1.35 christos case 12000:
1823 1.35 christos if(voice->sc->sc_type & EMUXKI_AUDIGY)
1824 1.35 christos return EMU_A_ADCCR_SAMPLERATE_12;
1825 1.35 christos else {
1826 1.35 christos #ifdef EMUXKI_DEBUG
1827 1.35 christos printf("recording sample_rate not supported : %u\n", voice->sample_rate);
1828 1.35 christos #endif
1829 1.40 kent return -1;
1830 1.35 christos }
1831 1.35 christos break;
1832 1.35 christos case 11000:
1833 1.35 christos if(voice->sc->sc_type & EMUXKI_AUDIGY)
1834 1.35 christos return EMU_A_ADCCR_SAMPLERATE_11;
1835 1.35 christos else
1836 1.35 christos return EMU_ADCCR_SAMPLERATE_11;
1837 1.35 christos break;
1838 1.35 christos case 8000:
1839 1.35 christos if(voice->sc->sc_type & EMUXKI_AUDIGY)
1840 1.35 christos return EMU_A_ADCCR_SAMPLERATE_8;
1841 1.35 christos else
1842 1.35 christos return EMU_ADCCR_SAMPLERATE_8;
1843 1.35 christos break;
1844 1.35 christos default:
1845 1.35 christos #ifdef EMUXKI_DEBUG
1846 1.35 christos printf("recording sample_rate not supported : %u\n", voice->sample_rate);
1847 1.35 christos #endif
1848 1.40 kent return -1;
1849 1.35 christos }
1850 1.40 kent return -1; /* shouldn't get here */
1851 1.35 christos }
1852 1.35 christos
1853 1.35 christos
1854 1.1 jdolecek static void
1855 1.1 jdolecek emuxki_voice_start(struct emuxki_voice *voice,
1856 1.40 kent void (*inth) (void *), void *inthparam)
1857 1.1 jdolecek {
1858 1.40 kent uint32_t val;
1859 1.19 toshii
1860 1.1 jdolecek voice->inth = inth;
1861 1.1 jdolecek voice->inthparam = inthparam;
1862 1.1 jdolecek if (voice->use & EMU_VOICE_USE_PLAY) {
1863 1.1 jdolecek voice->trigblk = 1;
1864 1.1 jdolecek emuxki_channel_start(voice->dataloc.chan[0]);
1865 1.1 jdolecek if (voice->stereo)
1866 1.1 jdolecek emuxki_channel_start(voice->dataloc.chan[1]);
1867 1.19 toshii } else {
1868 1.19 toshii voice->trigblk = 1;
1869 1.35 christos switch (voice->dataloc.source) {
1870 1.19 toshii case EMU_RECSRC_ADC:
1871 1.19 toshii /* XXX need to program DSP to output L+R
1872 1.19 toshii * XXX in monaural case? */
1873 1.35 christos if (voice->sc->sc_type & EMUXKI_AUDIGY) {
1874 1.35 christos val = EMU_A_ADCCR_LCHANENABLE;
1875 1.35 christos if (voice->stereo)
1876 1.35 christos val |= EMU_A_ADCCR_RCHANENABLE;
1877 1.35 christos } else {
1878 1.35 christos val = EMU_ADCCR_LCHANENABLE;
1879 1.35 christos if (voice->stereo)
1880 1.35 christos val |= EMU_ADCCR_RCHANENABLE;
1881 1.35 christos }
1882 1.35 christos val |= emuxki_voice_adc_rate(voice);
1883 1.35 christos emuxki_write(voice->sc, 0, EMU_ADCCR, 0);
1884 1.35 christos emuxki_write(voice->sc, 0, EMU_ADCCR, val);
1885 1.19 toshii break;
1886 1.19 toshii case EMU_RECSRC_MIC:
1887 1.19 toshii case EMU_RECSRC_FX:
1888 1.19 toshii printf("unimplemented\n");
1889 1.19 toshii break;
1890 1.35 christos case EMU_RECSRC_NOTSET:
1891 1.35 christos default:
1892 1.44 christos printf("Bad dataloc.source %d\n",
1893 1.44 christos voice->dataloc.source);
1894 1.40 kent break;
1895 1.19 toshii }
1896 1.19 toshii #if 0
1897 1.44 christos switch (voice->dataloc.source) {
1898 1.44 christos case EMU_RECSRC_ADC:
1899 1.44 christos case EMU_RECSRC_FX:
1900 1.44 christos case EMU_RECSRC_MIC:
1901 1.44 christos /* DMA completion interrupt is useless; use timer */
1902 1.60 jmcneill KASSERT(mutex_owned(&sc->sc_intr_lock));
1903 1.44 christos val = emu_rd(sc, INTE, 4);
1904 1.44 christos val |= emuxki_recsrc_intrmasks[voice->dataloc.source];
1905 1.44 christos emu_wr(sc, INTE, val, 4);
1906 1.44 christos break;
1907 1.44 christos default:
1908 1.44 christos break;
1909 1.44 christos }
1910 1.19 toshii #endif
1911 1.1 jdolecek }
1912 1.1 jdolecek voice->state |= EMU_VOICE_STATE_STARTED;
1913 1.19 toshii emuxki_resched_timer(voice->sc);
1914 1.1 jdolecek }
1915 1.1 jdolecek
1916 1.1 jdolecek static void
1917 1.1 jdolecek emuxki_voice_halt(struct emuxki_voice *voice)
1918 1.1 jdolecek {
1919 1.40 kent
1920 1.1 jdolecek if (voice->use & EMU_VOICE_USE_PLAY) {
1921 1.1 jdolecek emuxki_channel_stop(voice->dataloc.chan[0]);
1922 1.1 jdolecek if (voice->stereo)
1923 1.1 jdolecek emuxki_channel_stop(voice->dataloc.chan[1]);
1924 1.19 toshii } else {
1925 1.19 toshii switch (voice->dataloc.source) {
1926 1.19 toshii case EMU_RECSRC_ADC:
1927 1.35 christos emuxki_write(voice->sc, 0, EMU_ADCCR, 0);
1928 1.19 toshii break;
1929 1.19 toshii case EMU_RECSRC_FX:
1930 1.19 toshii case EMU_RECSRC_MIC:
1931 1.19 toshii printf("unimplemented\n");
1932 1.19 toshii break;
1933 1.44 christos default:
1934 1.19 toshii case EMU_RECSRC_NOTSET:
1935 1.44 christos printf("Bad dataloc.source %d\n",
1936 1.44 christos voice->dataloc.source);
1937 1.44 christos break;
1938 1.19 toshii }
1939 1.44 christos
1940 1.44 christos switch (voice->dataloc.source) {
1941 1.44 christos case EMU_RECSRC_ADC:
1942 1.44 christos case EMU_RECSRC_FX:
1943 1.44 christos case EMU_RECSRC_MIC:
1944 1.44 christos /* This should reset buffer pointer */
1945 1.44 christos emuxki_write(voice->sc, 0,
1946 1.44 christos emuxki_recsrc_szreg[voice->dataloc.source],
1947 1.44 christos EMU_RECBS_BUFSIZE_NONE);
1948 1.19 toshii #if 0
1949 1.60 jmcneill KASSERT(mutex_owned(&sc->sc_intr_lock));
1950 1.44 christos val = emu_rd(sc, INTE, 4);
1951 1.44 christos val &= ~emuxki_recsrc_intrmasks[voice->dataloc.source];
1952 1.44 christos emu_wr(sc, INTE, val, 4);
1953 1.19 toshii #endif
1954 1.44 christos break;
1955 1.44 christos default:
1956 1.44 christos break;
1957 1.44 christos }
1958 1.1 jdolecek }
1959 1.1 jdolecek voice->state &= ~EMU_VOICE_STATE_STARTED;
1960 1.19 toshii emuxki_resched_timer(voice->sc);
1961 1.1 jdolecek }
1962 1.1 jdolecek
1963 1.1 jdolecek /*
1964 1.1 jdolecek * The interrupt handler
1965 1.1 jdolecek */
1966 1.1 jdolecek static int
1967 1.1 jdolecek emuxki_intr(void *arg)
1968 1.1 jdolecek {
1969 1.40 kent struct emuxki_softc *sc;
1970 1.1 jdolecek struct emuxki_voice *voice;
1971 1.40 kent uint32_t ipr, curblk;
1972 1.40 kent int claim;
1973 1.1 jdolecek
1974 1.40 kent sc = arg;
1975 1.40 kent claim = 0;
1976 1.60 jmcneill
1977 1.60 jmcneill mutex_spin_enter(&sc->sc_intr_lock);
1978 1.60 jmcneill
1979 1.1 jdolecek while ((ipr = bus_space_read_4(sc->sc_iot, sc->sc_ioh, EMU_IPR))) {
1980 1.1 jdolecek if (ipr & EMU_IPR_INTERVALTIMER) {
1981 1.1 jdolecek LIST_FOREACH(voice, &sc->voices, next) {
1982 1.19 toshii if ((voice->state &
1983 1.1 jdolecek EMU_VOICE_STATE_STARTED) == 0)
1984 1.1 jdolecek continue;
1985 1.1 jdolecek
1986 1.1 jdolecek curblk = emuxki_voice_curaddr(voice) /
1987 1.1 jdolecek voice->blksize;
1988 1.19 toshii #if 0
1989 1.1 jdolecek if (curblk == voice->trigblk) {
1990 1.1 jdolecek voice->inth(voice->inthparam);
1991 1.1 jdolecek voice->trigblk++;
1992 1.1 jdolecek voice->trigblk %= voice->blkmod;
1993 1.1 jdolecek }
1994 1.19 toshii #else
1995 1.19 toshii while ((curblk >= voice->trigblk &&
1996 1.19 toshii curblk < (voice->trigblk + voice->blkmod / 2)) ||
1997 1.19 toshii ((int)voice->trigblk - (int)curblk) >
1998 1.19 toshii (voice->blkmod / 2 + 1)) {
1999 1.19 toshii voice->inth(voice->inthparam);
2000 1.19 toshii voice->trigblk++;
2001 1.19 toshii voice->trigblk %= voice->blkmod;
2002 1.19 toshii }
2003 1.19 toshii #endif
2004 1.1 jdolecek }
2005 1.1 jdolecek }
2006 1.1 jdolecek
2007 1.1 jdolecek /* Got interrupt */
2008 1.1 jdolecek bus_space_write_4(sc->sc_iot, sc->sc_ioh, EMU_IPR, ipr);
2009 1.13 jdolecek
2010 1.13 jdolecek claim = 1;
2011 1.1 jdolecek }
2012 1.1 jdolecek
2013 1.60 jmcneill mutex_spin_exit(&sc->sc_intr_lock);
2014 1.60 jmcneill
2015 1.40 kent return claim;
2016 1.1 jdolecek }
2017 1.1 jdolecek
2018 1.1 jdolecek
2019 1.1 jdolecek /*
2020 1.1 jdolecek * Audio Architecture callbacks
2021 1.1 jdolecek */
2022 1.1 jdolecek
2023 1.1 jdolecek static int
2024 1.1 jdolecek emuxki_open(void *addr, int flags)
2025 1.1 jdolecek {
2026 1.40 kent struct emuxki_softc *sc;
2027 1.1 jdolecek
2028 1.40 kent sc = addr;
2029 1.1 jdolecek #ifdef EMUXKI_DEBUG
2030 1.58 tsutsui printf("%s: emuxki_open called\n", device_xname(sc->sc_dev));
2031 1.1 jdolecek #endif
2032 1.1 jdolecek
2033 1.1 jdolecek /*
2034 1.1 jdolecek * Multiple voice support would be added as soon as I find a way to
2035 1.1 jdolecek * trick the audio arch into supporting multiple voices.
2036 1.1 jdolecek * Or I might integrate a modified audio arch supporting
2037 1.1 jdolecek * multiple voices.
2038 1.1 jdolecek */
2039 1.1 jdolecek
2040 1.1 jdolecek /*
2041 1.1 jdolecek * I did this because i have problems identifying the selected
2042 1.1 jdolecek * recording source(s) which is necessary when setting recording
2043 1.31 wiz * params This will be addressed very soon
2044 1.1 jdolecek */
2045 1.19 toshii if (flags & AUOPEN_READ) {
2046 1.19 toshii sc->rvoice = emuxki_voice_new(sc, 0 /* EMU_VOICE_USE_RECORD */);
2047 1.19 toshii if (sc->rvoice == NULL)
2048 1.40 kent return EBUSY;
2049 1.19 toshii
2050 1.19 toshii /* XXX Hardcode RECSRC_ADC for now */
2051 1.19 toshii sc->rvoice->dataloc.source = EMU_RECSRC_ADC;
2052 1.19 toshii }
2053 1.1 jdolecek
2054 1.1 jdolecek if (flags & AUOPEN_WRITE) {
2055 1.1 jdolecek sc->pvoice = emuxki_voice_new(sc, EMU_VOICE_USE_PLAY);
2056 1.1 jdolecek if (sc->pvoice == NULL) {
2057 1.8 jdolecek if (sc->rvoice) {
2058 1.1 jdolecek emuxki_voice_delete(sc->rvoice);
2059 1.8 jdolecek sc->rvoice = NULL;
2060 1.8 jdolecek }
2061 1.40 kent return EBUSY;
2062 1.1 jdolecek }
2063 1.1 jdolecek }
2064 1.1 jdolecek
2065 1.40 kent return 0;
2066 1.1 jdolecek }
2067 1.1 jdolecek
2068 1.1 jdolecek static void
2069 1.1 jdolecek emuxki_close(void *addr)
2070 1.1 jdolecek {
2071 1.40 kent struct emuxki_softc *sc;
2072 1.1 jdolecek
2073 1.40 kent sc = addr;
2074 1.1 jdolecek #ifdef EMUXKI_DEBUG
2075 1.58 tsutsui printf("%s: emu10K1_close called\n", device_xname(sc->sc_dev));
2076 1.1 jdolecek #endif
2077 1.1 jdolecek
2078 1.1 jdolecek /* No multiple voice support for now */
2079 1.8 jdolecek if (sc->rvoice != NULL) {
2080 1.1 jdolecek emuxki_voice_delete(sc->rvoice);
2081 1.8 jdolecek sc->rvoice = NULL;
2082 1.8 jdolecek }
2083 1.8 jdolecek if (sc->pvoice != NULL) {
2084 1.1 jdolecek emuxki_voice_delete(sc->pvoice);
2085 1.8 jdolecek sc->pvoice = NULL;
2086 1.8 jdolecek }
2087 1.1 jdolecek }
2088 1.1 jdolecek
2089 1.1 jdolecek static int
2090 1.49 christos emuxki_query_encoding(void *addr, struct audio_encoding *fp)
2091 1.1 jdolecek {
2092 1.1 jdolecek #ifdef EMUXKI_DEBUG
2093 1.40 kent struct emuxki_softc *sc;
2094 1.1 jdolecek
2095 1.40 kent sc = addr;
2096 1.58 tsutsui printf("%s: emuxki_query_encoding called\n", device_xname(sc->sc_dev));
2097 1.1 jdolecek #endif
2098 1.1 jdolecek
2099 1.1 jdolecek switch (fp->index) {
2100 1.1 jdolecek case 0:
2101 1.1 jdolecek strcpy(fp->name, AudioEulinear);
2102 1.1 jdolecek fp->encoding = AUDIO_ENCODING_ULINEAR;
2103 1.1 jdolecek fp->precision = 8;
2104 1.1 jdolecek fp->flags = 0;
2105 1.1 jdolecek break;
2106 1.1 jdolecek case 1:
2107 1.1 jdolecek strcpy(fp->name, AudioEmulaw);
2108 1.1 jdolecek fp->encoding = AUDIO_ENCODING_ULAW;
2109 1.1 jdolecek fp->precision = 8;
2110 1.1 jdolecek fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
2111 1.1 jdolecek break;
2112 1.1 jdolecek case 2:
2113 1.1 jdolecek strcpy(fp->name, AudioEalaw);
2114 1.1 jdolecek fp->encoding = AUDIO_ENCODING_ALAW;
2115 1.1 jdolecek fp->precision = 8;
2116 1.1 jdolecek fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
2117 1.1 jdolecek break;
2118 1.1 jdolecek case 3:
2119 1.1 jdolecek strcpy(fp->name, AudioEslinear);
2120 1.1 jdolecek fp->encoding = AUDIO_ENCODING_SLINEAR;
2121 1.1 jdolecek fp->precision = 8;
2122 1.1 jdolecek fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
2123 1.1 jdolecek break;
2124 1.1 jdolecek case 4:
2125 1.1 jdolecek strcpy(fp->name, AudioEslinear_le);
2126 1.1 jdolecek fp->encoding = AUDIO_ENCODING_SLINEAR_LE;
2127 1.1 jdolecek fp->precision = 16;
2128 1.1 jdolecek fp->flags = 0;
2129 1.1 jdolecek break;
2130 1.1 jdolecek case 5:
2131 1.1 jdolecek strcpy(fp->name, AudioEulinear_le);
2132 1.1 jdolecek fp->encoding = AUDIO_ENCODING_ULINEAR_LE;
2133 1.1 jdolecek fp->precision = 16;
2134 1.1 jdolecek fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
2135 1.1 jdolecek break;
2136 1.1 jdolecek case 6:
2137 1.1 jdolecek strcpy(fp->name, AudioEslinear_be);
2138 1.1 jdolecek fp->encoding = AUDIO_ENCODING_SLINEAR_BE;
2139 1.1 jdolecek fp->precision = 16;
2140 1.1 jdolecek fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
2141 1.1 jdolecek break;
2142 1.1 jdolecek case 7:
2143 1.1 jdolecek strcpy(fp->name, AudioEulinear_be);
2144 1.1 jdolecek fp->encoding = AUDIO_ENCODING_ULINEAR_BE;
2145 1.1 jdolecek fp->precision = 16;
2146 1.1 jdolecek fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
2147 1.1 jdolecek break;
2148 1.1 jdolecek default:
2149 1.40 kent return EINVAL;
2150 1.1 jdolecek }
2151 1.40 kent return 0;
2152 1.1 jdolecek }
2153 1.1 jdolecek
2154 1.1 jdolecek static int
2155 1.60 jmcneill emuxki_set_vparms(struct emuxki_softc *sc, struct emuxki_voice *voice,
2156 1.60 jmcneill const audio_params_t *p, stream_filter_list_t *fil)
2157 1.1 jdolecek {
2158 1.39 kent int mode, i;
2159 1.1 jdolecek
2160 1.1 jdolecek mode = (voice->use & EMU_VOICE_USE_PLAY) ?
2161 1.1 jdolecek AUMODE_PLAY : AUMODE_RECORD;
2162 1.39 kent i = auconv_set_converter(emuxki_formats, EMUXKI_NFORMATS,
2163 1.39 kent mode, p, FALSE, fil);
2164 1.39 kent if (i < 0)
2165 1.39 kent return EINVAL;
2166 1.39 kent if (fil->req_size > 0)
2167 1.39 kent p = &fil->filters[0].param;
2168 1.60 jmcneill return emuxki_voice_set_audioparms(sc, voice, p->channels == 2,
2169 1.60 jmcneill p->precision == 16, p->sample_rate);
2170 1.1 jdolecek }
2171 1.1 jdolecek
2172 1.1 jdolecek static int
2173 1.40 kent emuxki_set_params(void *addr, int setmode, int usemode, audio_params_t *play,
2174 1.40 kent audio_params_t *rec, stream_filter_list_t *pfil, stream_filter_list_t *rfil)
2175 1.1 jdolecek {
2176 1.40 kent struct emuxki_softc *sc;
2177 1.1 jdolecek struct audio_params *p;
2178 1.8 jdolecek struct emuxki_voice *v;
2179 1.39 kent stream_filter_list_t *fil;
2180 1.40 kent int mode, error;
2181 1.1 jdolecek
2182 1.40 kent sc = addr;
2183 1.1 jdolecek for (mode = AUMODE_RECORD; mode != -1;
2184 1.1 jdolecek mode = mode == AUMODE_RECORD ? AUMODE_PLAY : -1) {
2185 1.1 jdolecek if ((usemode & setmode & mode) == 0)
2186 1.1 jdolecek continue;
2187 1.1 jdolecek
2188 1.8 jdolecek if (mode == AUMODE_PLAY) {
2189 1.8 jdolecek p = play;
2190 1.39 kent fil = pfil;
2191 1.8 jdolecek v = sc->pvoice;
2192 1.8 jdolecek } else {
2193 1.8 jdolecek p = rec;
2194 1.39 kent fil = rfil;
2195 1.8 jdolecek v = sc->rvoice;
2196 1.8 jdolecek }
2197 1.8 jdolecek
2198 1.8 jdolecek if (v == NULL) {
2199 1.8 jdolecek continue;
2200 1.8 jdolecek }
2201 1.1 jdolecek
2202 1.1 jdolecek /* No multiple voice support for now */
2203 1.60 jmcneill if ((error = emuxki_set_vparms(sc, v, p, fil)))
2204 1.40 kent return error;
2205 1.1 jdolecek }
2206 1.1 jdolecek
2207 1.40 kent return 0;
2208 1.1 jdolecek }
2209 1.1 jdolecek
2210 1.1 jdolecek static int
2211 1.1 jdolecek emuxki_halt_output(void *addr)
2212 1.1 jdolecek {
2213 1.40 kent struct emuxki_softc *sc;
2214 1.1 jdolecek
2215 1.40 kent sc = addr;
2216 1.1 jdolecek /* No multiple voice support for now */
2217 1.1 jdolecek if (sc->pvoice == NULL)
2218 1.40 kent return ENXIO;
2219 1.1 jdolecek
2220 1.1 jdolecek emuxki_voice_halt(sc->pvoice);
2221 1.40 kent return 0;
2222 1.1 jdolecek }
2223 1.1 jdolecek
2224 1.1 jdolecek static int
2225 1.1 jdolecek emuxki_halt_input(void *addr)
2226 1.1 jdolecek {
2227 1.40 kent struct emuxki_softc *sc;
2228 1.1 jdolecek
2229 1.40 kent sc = addr;
2230 1.1 jdolecek #ifdef EMUXKI_DEBUG
2231 1.58 tsutsui printf("%s: emuxki_halt_input called\n", device_xname(sc->sc_dev));
2232 1.1 jdolecek #endif
2233 1.1 jdolecek
2234 1.1 jdolecek /* No multiple voice support for now */
2235 1.1 jdolecek if (sc->rvoice == NULL)
2236 1.40 kent return ENXIO;
2237 1.1 jdolecek emuxki_voice_halt(sc->rvoice);
2238 1.40 kent return 0;
2239 1.1 jdolecek }
2240 1.1 jdolecek
2241 1.1 jdolecek static int
2242 1.1 jdolecek emuxki_getdev(void *addr, struct audio_device *dev)
2243 1.1 jdolecek {
2244 1.40 kent struct emuxki_softc *sc;
2245 1.40 kent
2246 1.40 kent sc = addr;
2247 1.35 christos *dev = sc->sc_audv;
2248 1.40 kent return 0;
2249 1.1 jdolecek }
2250 1.1 jdolecek
2251 1.1 jdolecek static int
2252 1.1 jdolecek emuxki_set_port(void *addr, mixer_ctrl_t *mctl)
2253 1.1 jdolecek {
2254 1.40 kent struct emuxki_softc *sc;
2255 1.1 jdolecek
2256 1.40 kent sc = addr;
2257 1.1 jdolecek return sc->codecif->vtbl->mixer_set_port(sc->codecif, mctl);
2258 1.1 jdolecek }
2259 1.1 jdolecek
2260 1.1 jdolecek static int
2261 1.1 jdolecek emuxki_get_port(void *addr, mixer_ctrl_t *mctl)
2262 1.1 jdolecek {
2263 1.40 kent struct emuxki_softc *sc;
2264 1.1 jdolecek
2265 1.40 kent sc = addr;
2266 1.1 jdolecek return sc->codecif->vtbl->mixer_get_port(sc->codecif, mctl);
2267 1.1 jdolecek }
2268 1.1 jdolecek
2269 1.1 jdolecek static int
2270 1.1 jdolecek emuxki_query_devinfo(void *addr, mixer_devinfo_t *minfo)
2271 1.1 jdolecek {
2272 1.40 kent struct emuxki_softc *sc;
2273 1.1 jdolecek
2274 1.40 kent sc = addr;
2275 1.1 jdolecek return sc->codecif->vtbl->query_devinfo(sc->codecif, minfo);
2276 1.1 jdolecek }
2277 1.1 jdolecek
2278 1.1 jdolecek static void *
2279 1.60 jmcneill emuxki_allocm(void *addr, int direction, size_t size)
2280 1.1 jdolecek {
2281 1.1 jdolecek if (direction == AUMODE_PLAY)
2282 1.60 jmcneill return emuxki_pmem_alloc(addr, size);
2283 1.1 jdolecek else
2284 1.60 jmcneill return emuxki_rmem_alloc(addr, size);
2285 1.1 jdolecek }
2286 1.1 jdolecek
2287 1.1 jdolecek static void
2288 1.60 jmcneill emuxki_freem(void *addr, void *ptr, size_t size)
2289 1.1 jdolecek {
2290 1.40 kent struct emuxki_softc *sc;
2291 1.1 jdolecek struct emuxki_mem *mem;
2292 1.40 kent uint32_t *ptb, silentpage;
2293 1.40 kent size_t numblocks;
2294 1.60 jmcneill int i;
2295 1.1 jdolecek
2296 1.40 kent sc = addr;
2297 1.1 jdolecek ptb = KERNADDR(sc->ptb);
2298 1.1 jdolecek silentpage = DMAADDR(sc->silentpage) << 1;
2299 1.1 jdolecek LIST_FOREACH(mem, &sc->mem, next) {
2300 1.1 jdolecek if (KERNADDR(mem->dmamem) != ptr)
2301 1.1 jdolecek continue;
2302 1.1 jdolecek
2303 1.60 jmcneill mutex_spin_enter(&sc->sc_intr_lock);
2304 1.1 jdolecek if (mem->ptbidx != EMU_RMEM) {
2305 1.1 jdolecek numblocks = DMASIZE(mem->dmamem) / EMU_PTESIZE;
2306 1.1 jdolecek if (DMASIZE(mem->dmamem) % EMU_PTESIZE)
2307 1.1 jdolecek numblocks++;
2308 1.1 jdolecek for (i = 0; i < numblocks; i++)
2309 1.1 jdolecek ptb[mem->ptbidx + i] =
2310 1.34 tsutsui htole32(silentpage | (mem->ptbidx + i));
2311 1.1 jdolecek }
2312 1.1 jdolecek LIST_REMOVE(mem, next);
2313 1.60 jmcneill mutex_spin_exit(&sc->sc_intr_lock);
2314 1.1 jdolecek
2315 1.60 jmcneill emuxki_mem_delete(mem, size);
2316 1.1 jdolecek break;
2317 1.1 jdolecek }
2318 1.1 jdolecek }
2319 1.1 jdolecek
2320 1.19 toshii /* blocksize should be a divisor of allowable buffersize */
2321 1.19 toshii /* XXX probably this could be done better */
2322 1.19 toshii static int
2323 1.49 christos emuxki_round_blocksize(void *addr, int blksize,
2324 1.49 christos int mode, const audio_params_t* param)
2325 1.19 toshii {
2326 1.19 toshii #if 0
2327 1.40 kent struct emuxki_softc *sc;
2328 1.19 toshii struct audio_softc *au;
2329 1.19 toshii #endif
2330 1.19 toshii int bufsize;
2331 1.19 toshii #if 0
2332 1.40 kent sc = addr;
2333 1.19 toshii if (sc == NULL)
2334 1.19 toshii return blksize;
2335 1.19 toshii
2336 1.57 cegger au = device_private(sc->sc_audev);
2337 1.19 toshii if (au == NULL)
2338 1.19 toshii return blksize;
2339 1.19 toshii
2340 1.19 toshii bufsize = emuxki_round_buffersize(sc, AUMODE_RECORD,
2341 1.19 toshii au->sc_rr.bufsize);
2342 1.19 toshii #else
2343 1.19 toshii bufsize = 65536;
2344 1.19 toshii #endif
2345 1.19 toshii
2346 1.19 toshii while (bufsize > blksize)
2347 1.19 toshii bufsize /= 2;
2348 1.19 toshii
2349 1.19 toshii return bufsize;
2350 1.19 toshii }
2351 1.40 kent
2352 1.1 jdolecek static size_t
2353 1.49 christos emuxki_round_buffersize(void *addr, int direction, size_t bsize)
2354 1.1 jdolecek {
2355 1.1 jdolecek
2356 1.1 jdolecek if (direction == AUMODE_PLAY) {
2357 1.1 jdolecek if (bsize < EMU_PTESIZE)
2358 1.1 jdolecek bsize = EMU_PTESIZE;
2359 1.1 jdolecek else if (bsize > (EMU_PTESIZE * EMU_MAXPTE))
2360 1.1 jdolecek bsize = EMU_PTESIZE * EMU_MAXPTE;
2361 1.1 jdolecek /* Would be better if set to max available */
2362 1.1 jdolecek else if (bsize % EMU_PTESIZE)
2363 1.1 jdolecek bsize = bsize -
2364 1.1 jdolecek (bsize % EMU_PTESIZE) +
2365 1.1 jdolecek EMU_PTESIZE;
2366 1.1 jdolecek } else {
2367 1.1 jdolecek int idx;
2368 1.1 jdolecek
2369 1.1 jdolecek /* find nearest lower recbuf size */
2370 1.19 toshii for(idx = sizeof(emuxki_recbuf_sz) /
2371 1.19 toshii sizeof(emuxki_recbuf_sz[0]); --idx >= 0; ) {
2372 1.19 toshii if (bsize >= emuxki_recbuf_sz[idx]) {
2373 1.19 toshii bsize = emuxki_recbuf_sz[idx];
2374 1.1 jdolecek break;
2375 1.1 jdolecek }
2376 1.1 jdolecek }
2377 1.1 jdolecek
2378 1.1 jdolecek if (bsize == 0)
2379 1.1 jdolecek bsize = 384;
2380 1.1 jdolecek }
2381 1.1 jdolecek
2382 1.40 kent return bsize;
2383 1.1 jdolecek }
2384 1.1 jdolecek
2385 1.1 jdolecek static paddr_t
2386 1.1 jdolecek emuxki_mappage(void *addr, void *ptr, off_t off, int prot)
2387 1.1 jdolecek {
2388 1.40 kent struct emuxki_softc *sc;
2389 1.1 jdolecek struct emuxki_mem *mem;
2390 1.1 jdolecek
2391 1.40 kent sc = addr;
2392 1.60 jmcneill
2393 1.60 jmcneill mutex_exit(&sc->sc_lock);
2394 1.1 jdolecek LIST_FOREACH(mem, &sc->mem, next) {
2395 1.1 jdolecek if (KERNADDR(mem->dmamem) == ptr) {
2396 1.1 jdolecek struct dmamem *dm = mem->dmamem;
2397 1.1 jdolecek
2398 1.1 jdolecek return bus_dmamem_mmap(dm->dmat, dm->segs, dm->nsegs,
2399 1.1 jdolecek off, prot, BUS_DMA_WAITOK);
2400 1.1 jdolecek }
2401 1.1 jdolecek }
2402 1.60 jmcneill mutex_enter(&sc->sc_lock);
2403 1.1 jdolecek
2404 1.40 kent return -1;
2405 1.1 jdolecek }
2406 1.1 jdolecek
2407 1.1 jdolecek static int
2408 1.49 christos emuxki_get_props(void *addr)
2409 1.1 jdolecek {
2410 1.40 kent return AUDIO_PROP_MMAP | AUDIO_PROP_INDEPENDENT |
2411 1.40 kent AUDIO_PROP_FULLDUPLEX;
2412 1.1 jdolecek }
2413 1.1 jdolecek
2414 1.1 jdolecek static int
2415 1.1 jdolecek emuxki_trigger_output(void *addr, void *start, void *end, int blksize,
2416 1.40 kent void (*inth) (void *), void *inthparam, const audio_params_t *params)
2417 1.1 jdolecek {
2418 1.40 kent struct emuxki_softc *sc;
2419 1.1 jdolecek /* No multiple voice support for now */
2420 1.40 kent struct emuxki_voice *voice;
2421 1.40 kent int error;
2422 1.1 jdolecek
2423 1.40 kent sc = addr;
2424 1.40 kent voice = sc->pvoice;
2425 1.1 jdolecek if (voice == NULL)
2426 1.40 kent return ENXIO;
2427 1.60 jmcneill if ((error = emuxki_voice_set_audioparms(sc, voice, params->channels == 2,
2428 1.40 kent params->precision == 16, params->sample_rate)))
2429 1.40 kent return error;
2430 1.1 jdolecek if ((error = emuxki_voice_set_bufparms(voice, start,
2431 1.50 christos (char *)end - (char *)start, blksize)))
2432 1.40 kent return error;
2433 1.1 jdolecek emuxki_voice_commit_parms(voice);
2434 1.1 jdolecek emuxki_voice_start(voice, inth, inthparam);
2435 1.1 jdolecek
2436 1.40 kent return 0;
2437 1.1 jdolecek }
2438 1.1 jdolecek
2439 1.1 jdolecek static int
2440 1.1 jdolecek emuxki_trigger_input(void *addr, void *start, void *end, int blksize,
2441 1.40 kent void (*inth) (void *), void *inthparam, const audio_params_t *params)
2442 1.1 jdolecek {
2443 1.40 kent struct emuxki_softc *sc;
2444 1.1 jdolecek /* No multiple voice support for now */
2445 1.40 kent struct emuxki_voice *voice;
2446 1.35 christos int error;
2447 1.1 jdolecek
2448 1.40 kent sc = addr;
2449 1.40 kent voice = sc->rvoice;
2450 1.1 jdolecek if (voice == NULL)
2451 1.40 kent return ENXIO;
2452 1.60 jmcneill if ((error = emuxki_voice_set_audioparms(sc, voice,
2453 1.60 jmcneill params->channels == 2, params->precision == 16,
2454 1.60 jmcneill params->sample_rate)))
2455 1.40 kent return error;
2456 1.1 jdolecek if ((error = emuxki_voice_set_bufparms(voice, start,
2457 1.50 christos (char *)end - (char *)start, blksize)))
2458 1.40 kent return error;
2459 1.1 jdolecek emuxki_voice_start(voice, inth, inthparam);
2460 1.1 jdolecek
2461 1.40 kent return 0;
2462 1.1 jdolecek }
2463 1.1 jdolecek
2464 1.1 jdolecek /*
2465 1.1 jdolecek * AC97 callbacks
2466 1.1 jdolecek */
2467 1.1 jdolecek
2468 1.1 jdolecek static int
2469 1.1 jdolecek emuxki_ac97_attach(void *arg, struct ac97_codec_if *codecif)
2470 1.1 jdolecek {
2471 1.40 kent struct emuxki_softc *sc;
2472 1.1 jdolecek
2473 1.40 kent sc = arg;
2474 1.1 jdolecek sc->codecif = codecif;
2475 1.40 kent return 0;
2476 1.1 jdolecek }
2477 1.1 jdolecek
2478 1.1 jdolecek static int
2479 1.40 kent emuxki_ac97_read(void *arg, uint8_t reg, uint16_t *val)
2480 1.1 jdolecek {
2481 1.40 kent struct emuxki_softc *sc;
2482 1.1 jdolecek
2483 1.40 kent sc = arg;
2484 1.60 jmcneill mutex_spin_enter(&sc->sc_ac97_index_lock);
2485 1.1 jdolecek bus_space_write_1(sc->sc_iot, sc->sc_ioh, EMU_AC97ADDR, reg);
2486 1.1 jdolecek *val = bus_space_read_2(sc->sc_iot, sc->sc_ioh, EMU_AC97DATA);
2487 1.60 jmcneill mutex_spin_exit(&sc->sc_ac97_index_lock);
2488 1.1 jdolecek
2489 1.40 kent return 0;
2490 1.1 jdolecek }
2491 1.1 jdolecek
2492 1.1 jdolecek static int
2493 1.40 kent emuxki_ac97_write(void *arg, uint8_t reg, uint16_t val)
2494 1.1 jdolecek {
2495 1.40 kent struct emuxki_softc *sc;
2496 1.1 jdolecek
2497 1.40 kent sc = arg;
2498 1.60 jmcneill mutex_spin_enter(&sc->sc_ac97_index_lock);
2499 1.1 jdolecek bus_space_write_1(sc->sc_iot, sc->sc_ioh, EMU_AC97ADDR, reg);
2500 1.1 jdolecek bus_space_write_2(sc->sc_iot, sc->sc_ioh, EMU_AC97DATA, val);
2501 1.60 jmcneill mutex_spin_exit(&sc->sc_ac97_index_lock);
2502 1.1 jdolecek
2503 1.40 kent return 0;
2504 1.1 jdolecek }
2505 1.1 jdolecek
2506 1.36 kent static int
2507 1.49 christos emuxki_ac97_reset(void *arg)
2508 1.1 jdolecek {
2509 1.40 kent
2510 1.36 kent return 0;
2511 1.6 jdolecek }
2512 1.6 jdolecek
2513 1.6 jdolecek enum ac97_host_flags
2514 1.49 christos emuxki_ac97_flags(void *arg)
2515 1.6 jdolecek {
2516 1.40 kent
2517 1.40 kent return AC97_HOST_SWAPPED_CHANNELS;
2518 1.1 jdolecek }
2519 1.60 jmcneill
2520 1.60 jmcneill static void
2521 1.60 jmcneill emuxki_get_locks(void *arg, kmutex_t **intr, kmutex_t **proc)
2522 1.60 jmcneill {
2523 1.60 jmcneill struct emuxki_softc *sc;
2524 1.60 jmcneill
2525 1.60 jmcneill sc = arg;
2526 1.60 jmcneill *intr = &sc->sc_intr_lock;
2527 1.60 jmcneill *proc = &sc->sc_lock;
2528 1.60 jmcneill }
2529