emuxki.c revision 1.1 1 1.1 jdolecek /* $NetBSD: emuxki.c,v 1.1 2001/10/17 18:39:41 jdolecek Exp $ */
2 1.1 jdolecek
3 1.1 jdolecek /*-
4 1.1 jdolecek * Copyright (c) 2001 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.1 jdolecek * by Yannick Montulet.
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 * 3. All advertising materials mentioning features or use of this software
19 1.1 jdolecek * must display the following acknowledgement:
20 1.1 jdolecek * This product includes software developed by the NetBSD
21 1.1 jdolecek * Foundation, Inc. and its contributors.
22 1.1 jdolecek * 4. Neither the name of The NetBSD Foundation nor the names of its
23 1.1 jdolecek * contributors may be used to endorse or promote products derived
24 1.1 jdolecek * from this software without specific prior written permission.
25 1.1 jdolecek *
26 1.1 jdolecek * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27 1.1 jdolecek * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28 1.1 jdolecek * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 1.1 jdolecek * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30 1.1 jdolecek * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 1.1 jdolecek * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 1.1 jdolecek * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 1.1 jdolecek * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 1.1 jdolecek * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 1.1 jdolecek * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 1.1 jdolecek * POSSIBILITY OF SUCH DAMAGE.
37 1.1 jdolecek */
38 1.1 jdolecek
39 1.1 jdolecek /*
40 1.1 jdolecek * Driver for Creative Labs SBLive! series and probably PCI512.
41 1.1 jdolecek *
42 1.1 jdolecek * Known bugs:
43 1.1 jdolecek * - inversed stereo at ac97 codec level
44 1.1 jdolecek * (XXX jdolecek - don't see the problem? maybe because auvia(4) has
45 1.1 jdolecek * it swapped too?)
46 1.1 jdolecek * - bass disapear when you plug rear jack-in on Cambridge FPS2000 speakers
47 1.1 jdolecek * (and presumably all speakers that support front and rear jack-in)
48 1.1 jdolecek *
49 1.1 jdolecek * TODO:
50 1.1 jdolecek * - Digital Outputs
51 1.1 jdolecek * - (midi/mpu),joystick support
52 1.1 jdolecek * - Single source recording
53 1.1 jdolecek * - Multiple voices play (problem with /dev/audio architecture)
54 1.1 jdolecek * - Multiple sources recording (Pb with audio(4))
55 1.1 jdolecek * - Independant modification of each channel's parameters (via mixer ?)
56 1.1 jdolecek * - DSP FX patches (to make fx like chipmunk)
57 1.1 jdolecek */
58 1.1 jdolecek
59 1.1 jdolecek #include <sys/types.h>
60 1.1 jdolecek #include <sys/device.h>
61 1.1 jdolecek #include <sys/errno.h>
62 1.1 jdolecek #include <sys/malloc.h>
63 1.1 jdolecek #include <sys/systm.h>
64 1.1 jdolecek #include <sys/param.h>
65 1.1 jdolecek #include <sys/audioio.h>
66 1.1 jdolecek #include <sys/select.h>
67 1.1 jdolecek #include <dev/pci/pcireg.h>
68 1.1 jdolecek #include <dev/pci/pcivar.h>
69 1.1 jdolecek #include <dev/pci/pcidevs.h>
70 1.1 jdolecek #include <dev/audio_if.h>
71 1.1 jdolecek #include <dev/audiovar.h>
72 1.1 jdolecek #include <dev/auconv.h>
73 1.1 jdolecek #include <dev/mulaw.h>
74 1.1 jdolecek #include <dev/ic/ac97reg.h>
75 1.1 jdolecek #include <dev/ic/ac97var.h>
76 1.1 jdolecek
77 1.1 jdolecek #include <dev/pci/emuxkireg.h>
78 1.1 jdolecek #include <dev/pci/emuxkivar.h>
79 1.1 jdolecek
80 1.1 jdolecek /* autconf goo */
81 1.1 jdolecek static int emuxki_match __P((struct device *, struct cfdata *, void *));
82 1.1 jdolecek static void emuxki_attach __P((struct device *, struct device *, void *));
83 1.1 jdolecek static int emuxki_detach __P((struct device *, int));
84 1.1 jdolecek
85 1.1 jdolecek /* dma mem mgmt */
86 1.1 jdolecek static struct dmamem *dmamem_alloc __P((bus_dma_tag_t, size_t, bus_size_t,
87 1.1 jdolecek int, int, int));
88 1.1 jdolecek static void dmamem_free __P((struct dmamem *, int));
89 1.1 jdolecek
90 1.1 jdolecek /* Emu10k1 init & shutdown */
91 1.1 jdolecek static int emuxki_init __P((struct emuxki_softc *));
92 1.1 jdolecek static void emuxki_shutdown __P((struct emuxki_softc *));
93 1.1 jdolecek
94 1.1 jdolecek /* Emu10k1 mem mgmt */
95 1.1 jdolecek static void *emuxki_pmem_alloc __P((struct emuxki_softc *, size_t,int,int));
96 1.1 jdolecek static void *emuxki_rmem_alloc __P((struct emuxki_softc *, size_t,int,int));
97 1.1 jdolecek
98 1.1 jdolecek /*
99 1.1 jdolecek * Emu10k1 channels funcs : There is no direct access to channels, everything
100 1.1 jdolecek * is done through voices I will at least provide channel based fx params
101 1.1 jdolecek * modification, later...
102 1.1 jdolecek */
103 1.1 jdolecek
104 1.1 jdolecek /* Emu10k1 voice mgmt */
105 1.1 jdolecek static struct emuxki_voice *emuxki_voice_new __P((struct emuxki_softc *,
106 1.1 jdolecek u_int8_t));
107 1.1 jdolecek static void emuxki_voice_delete __P((struct emuxki_voice *));
108 1.1 jdolecek static int emuxki_voice_set_audioparms __P((struct emuxki_voice *, u_int8_t,
109 1.1 jdolecek u_int8_t, u_int32_t));
110 1.1 jdolecek /* emuxki_voice_set_fxparms will come later, it'll need channel distinction */
111 1.1 jdolecek static int emuxki_voice_set_bufparms __P((struct emuxki_voice *,
112 1.1 jdolecek void *, u_int32_t, u_int16_t));
113 1.1 jdolecek static void emuxki_voice_commit_parms __P((struct emuxki_voice *));
114 1.1 jdolecek static u_int32_t emuxki_voice_curaddr __P((struct emuxki_voice *));
115 1.1 jdolecek static void emuxki_voice_start __P((struct emuxki_voice *,
116 1.1 jdolecek void (*) (void *), void *));
117 1.1 jdolecek static void emuxki_voice_halt __P((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.1 jdolecek static struct emuxki_stream *emuxki_stream_new __P((struct emu10k1 *));
124 1.1 jdolecek static void emuxki_stream_delete __P((struct emuxki_stream *));
125 1.1 jdolecek static int emuxki_stream_set_audio_params __P((struct emuxki_stream *, u_int8_t,
126 1.1 jdolecek u_int8_t, u_int8_t, u_int16_t));
127 1.1 jdolecek static void emuxki_stream_start __P((struct emuxki_stream *));
128 1.1 jdolecek static void emuxki_stream_halt __P((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.1 jdolecek static int emuxki_open __P((void *, int));
134 1.1 jdolecek static void emuxki_close __P((void *));
135 1.1 jdolecek
136 1.1 jdolecek static int emuxki_query_encoding __P((void *, struct audio_encoding *));
137 1.1 jdolecek static int emuxki_set_params __P((void *, int, int,
138 1.1 jdolecek struct audio_params *,
139 1.1 jdolecek struct audio_params *));
140 1.1 jdolecek
141 1.1 jdolecek static size_t emuxki_round_buffersize __P((void *, int, size_t));
142 1.1 jdolecek
143 1.1 jdolecek static int emuxki_trigger_output __P((void *, void *, void *, int,
144 1.1 jdolecek void (*)(void *), void *,
145 1.1 jdolecek struct audio_params *));
146 1.1 jdolecek static int emuxki_trigger_input __P((void *, void *, void *, int,
147 1.1 jdolecek void (*) (void *), void *,
148 1.1 jdolecek struct audio_params *));
149 1.1 jdolecek static int emuxki_halt_output __P((void *));
150 1.1 jdolecek static int emuxki_halt_input __P((void *));
151 1.1 jdolecek
152 1.1 jdolecek static int emuxki_getdev __P((void *, struct audio_device *));
153 1.1 jdolecek static int emuxki_set_port __P((void *, mixer_ctrl_t *));
154 1.1 jdolecek static int emuxki_get_port __P((void *, mixer_ctrl_t *));
155 1.1 jdolecek static int emuxki_query_devinfo __P((void *, mixer_devinfo_t *));
156 1.1 jdolecek
157 1.1 jdolecek static void *emuxki_allocm __P((void *, int, size_t, int, int));
158 1.1 jdolecek static void emuxki_freem __P((void *, void *, int));
159 1.1 jdolecek
160 1.1 jdolecek static paddr_t emuxki_mappage __P((void *, void *, off_t, int));
161 1.1 jdolecek static int emuxki_get_props __P((void *));
162 1.1 jdolecek
163 1.1 jdolecek /* Interrupt handler */
164 1.1 jdolecek static int emuxki_intr __P((void *));
165 1.1 jdolecek
166 1.1 jdolecek /* Emu10k1 AC97 interface callbacks */
167 1.1 jdolecek static int emuxki_ac97_attach __P((void *, struct ac97_codec_if *));
168 1.1 jdolecek static int emuxki_ac97_read __P((void *, u_int8_t, u_int16_t *));
169 1.1 jdolecek static int emuxki_ac97_write __P((void *, u_int8_t, u_int16_t));
170 1.1 jdolecek static void emuxki_ac97_reset __P((void *));
171 1.1 jdolecek
172 1.1 jdolecek /*
173 1.1 jdolecek * Autoconfig goo.
174 1.1 jdolecek */
175 1.1 jdolecek struct cfattach emuxki_ca = {
176 1.1 jdolecek sizeof(struct emuxki_softc),
177 1.1 jdolecek emuxki_match,
178 1.1 jdolecek emuxki_attach,
179 1.1 jdolecek emuxki_detach,
180 1.1 jdolecek NULL /* config activate */
181 1.1 jdolecek };
182 1.1 jdolecek
183 1.1 jdolecek static struct audio_hw_if emuxki_hw_if = {
184 1.1 jdolecek emuxki_open,
185 1.1 jdolecek emuxki_close,
186 1.1 jdolecek NULL, /* drain */
187 1.1 jdolecek emuxki_query_encoding,
188 1.1 jdolecek emuxki_set_params,
189 1.1 jdolecek NULL, /* round blocksize */
190 1.1 jdolecek NULL, /* commit settings */
191 1.1 jdolecek NULL, /* init_output */
192 1.1 jdolecek NULL, /* init_input */
193 1.1 jdolecek NULL, /* start_output */
194 1.1 jdolecek NULL, /* start_input */
195 1.1 jdolecek emuxki_halt_output,
196 1.1 jdolecek emuxki_halt_input,
197 1.1 jdolecek NULL, /* speaker_ctl */
198 1.1 jdolecek emuxki_getdev,
199 1.1 jdolecek NULL, /* setfd */
200 1.1 jdolecek emuxki_set_port,
201 1.1 jdolecek emuxki_get_port,
202 1.1 jdolecek emuxki_query_devinfo,
203 1.1 jdolecek emuxki_allocm,
204 1.1 jdolecek emuxki_freem,
205 1.1 jdolecek emuxki_round_buffersize,
206 1.1 jdolecek emuxki_mappage,
207 1.1 jdolecek emuxki_get_props,
208 1.1 jdolecek emuxki_trigger_output,
209 1.1 jdolecek emuxki_trigger_input,
210 1.1 jdolecek NULL, /* dev_ioctl */
211 1.1 jdolecek };
212 1.1 jdolecek
213 1.1 jdolecek /*
214 1.1 jdolecek * Dma memory mgmt
215 1.1 jdolecek */
216 1.1 jdolecek
217 1.1 jdolecek static void
218 1.1 jdolecek dmamem_delete(struct dmamem *mem, int type)
219 1.1 jdolecek {
220 1.1 jdolecek free(mem->segs, type);
221 1.1 jdolecek free(mem, type);
222 1.1 jdolecek }
223 1.1 jdolecek
224 1.1 jdolecek static struct dmamem *
225 1.1 jdolecek dmamem_alloc(bus_dma_tag_t dmat, size_t size, bus_size_t align,
226 1.1 jdolecek int nsegs, int type, int flags)
227 1.1 jdolecek {
228 1.1 jdolecek struct dmamem *mem;
229 1.1 jdolecek int bus_dma_flags;
230 1.1 jdolecek
231 1.1 jdolecek /* Allocate memory for structure */
232 1.1 jdolecek if ((mem = malloc(sizeof(*mem), type, flags)) == NULL)
233 1.1 jdolecek return (NULL);
234 1.1 jdolecek mem->dmat = dmat;
235 1.1 jdolecek mem->size = size;
236 1.1 jdolecek mem->align = align;
237 1.1 jdolecek mem->nsegs = nsegs;
238 1.1 jdolecek mem->bound = 0;
239 1.1 jdolecek
240 1.1 jdolecek mem->segs = malloc(mem->nsegs * sizeof(*(mem->segs)), type, flags);
241 1.1 jdolecek if (mem->segs == NULL) {
242 1.1 jdolecek free(mem, type);
243 1.1 jdolecek return (NULL);
244 1.1 jdolecek }
245 1.1 jdolecek
246 1.1 jdolecek bus_dma_flags = (flags & M_NOWAIT) ? BUS_DMA_NOWAIT : BUS_DMA_WAITOK;
247 1.1 jdolecek if (bus_dmamem_alloc(dmat, mem->size, mem->align, mem->bound,
248 1.1 jdolecek mem->segs, mem->nsegs, &(mem->rsegs),
249 1.1 jdolecek bus_dma_flags)) {
250 1.1 jdolecek dmamem_delete(mem, type);
251 1.1 jdolecek return (NULL);
252 1.1 jdolecek }
253 1.1 jdolecek
254 1.1 jdolecek if (bus_dmamem_map(dmat, mem->segs, mem->nsegs, mem->size,
255 1.1 jdolecek &(mem->kaddr), bus_dma_flags | BUS_DMA_COHERENT)) {
256 1.1 jdolecek bus_dmamem_free(dmat, mem->segs, mem->nsegs);
257 1.1 jdolecek dmamem_delete(mem, type);
258 1.1 jdolecek return (NULL);
259 1.1 jdolecek }
260 1.1 jdolecek
261 1.1 jdolecek if (bus_dmamap_create(dmat, mem->size, mem->nsegs, mem->size,
262 1.1 jdolecek mem->bound, bus_dma_flags, &(mem->map))) {
263 1.1 jdolecek bus_dmamem_unmap(dmat, mem->kaddr, mem->size);
264 1.1 jdolecek bus_dmamem_free(dmat, mem->segs, mem->nsegs);
265 1.1 jdolecek dmamem_delete(mem, type);
266 1.1 jdolecek return (NULL);
267 1.1 jdolecek }
268 1.1 jdolecek
269 1.1 jdolecek if (bus_dmamap_load(dmat, mem->map, mem->kaddr,
270 1.1 jdolecek mem->size, NULL, bus_dma_flags)) {
271 1.1 jdolecek bus_dmamap_destroy(dmat, mem->map);
272 1.1 jdolecek bus_dmamem_unmap(dmat, mem->kaddr, mem->size);
273 1.1 jdolecek bus_dmamem_free(dmat, mem->segs, mem->nsegs);
274 1.1 jdolecek dmamem_delete(mem, type);
275 1.1 jdolecek return (NULL);
276 1.1 jdolecek }
277 1.1 jdolecek
278 1.1 jdolecek return (mem);
279 1.1 jdolecek }
280 1.1 jdolecek
281 1.1 jdolecek static void
282 1.1 jdolecek dmamem_free(struct dmamem *mem, int type)
283 1.1 jdolecek {
284 1.1 jdolecek bus_dmamap_unload(mem->dmat, mem->map);
285 1.1 jdolecek bus_dmamap_destroy(mem->dmat, mem->map);
286 1.1 jdolecek bus_dmamem_unmap(mem->dmat, mem->kaddr, mem->size);
287 1.1 jdolecek bus_dmamem_free(mem->dmat, mem->segs, mem->nsegs);
288 1.1 jdolecek dmamem_delete(mem, type);
289 1.1 jdolecek }
290 1.1 jdolecek
291 1.1 jdolecek
292 1.1 jdolecek /*
293 1.1 jdolecek * Autoconf device callbacks : attach and detach
294 1.1 jdolecek */
295 1.1 jdolecek
296 1.1 jdolecek static void
297 1.1 jdolecek emuxki_pci_shutdown(struct emuxki_softc *sc)
298 1.1 jdolecek {
299 1.1 jdolecek if (sc->sc_ih != NULL)
300 1.1 jdolecek pci_intr_disestablish(sc->sc_pc, sc->sc_ih);
301 1.1 jdolecek if (sc->sc_ios)
302 1.1 jdolecek bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_ios);
303 1.1 jdolecek }
304 1.1 jdolecek
305 1.1 jdolecek static int
306 1.1 jdolecek emuxki_scinit(struct emuxki_softc *sc)
307 1.1 jdolecek {
308 1.1 jdolecek int err;
309 1.1 jdolecek
310 1.1 jdolecek bus_space_write_4(sc->sc_iot, sc->sc_ioh, EMU_HCFG,
311 1.1 jdolecek EMU_HCFG_LOCKSOUNDCACHE | EMU_HCFG_LOCKTANKCACHE_MASK |
312 1.1 jdolecek EMU_HCFG_MUTEBUTTONENABLE);
313 1.1 jdolecek bus_space_write_4(sc->sc_iot, sc->sc_ioh, EMU_INTE,
314 1.1 jdolecek EMU_INTE_SAMPLERATER | EMU_INTE_PCIERRENABLE);
315 1.1 jdolecek
316 1.1 jdolecek if ((err = emuxki_init(sc)))
317 1.1 jdolecek return (err);
318 1.1 jdolecek
319 1.1 jdolecek bus_space_write_4(sc->sc_iot, sc->sc_ioh, EMU_HCFG,
320 1.1 jdolecek EMU_HCFG_AUDIOENABLE |
321 1.1 jdolecek EMU_HCFG_LOCKTANKCACHE_MASK | EMU_HCFG_AUTOMUTE);
322 1.1 jdolecek bus_space_write_4(sc->sc_iot, sc->sc_ioh, EMU_INTE,
323 1.1 jdolecek bus_space_read_4(sc->sc_iot, sc->sc_ioh, EMU_INTE) |
324 1.1 jdolecek EMU_INTE_VOLINCRENABLE | EMU_INTE_VOLDECRENABLE |
325 1.1 jdolecek EMU_INTE_MUTEENABLE);
326 1.1 jdolecek
327 1.1 jdolecek /* No multiple voice support for now */
328 1.1 jdolecek sc->pvoice = sc->rvoice = NULL;
329 1.1 jdolecek
330 1.1 jdolecek return (0);
331 1.1 jdolecek }
332 1.1 jdolecek
333 1.1 jdolecek static int
334 1.1 jdolecek emuxki_ac97_init(struct emuxki_softc *sc)
335 1.1 jdolecek {
336 1.1 jdolecek sc->hostif.arg = sc;
337 1.1 jdolecek sc->hostif.attach = emuxki_ac97_attach;
338 1.1 jdolecek sc->hostif.read = emuxki_ac97_read;
339 1.1 jdolecek sc->hostif.write = emuxki_ac97_write;
340 1.1 jdolecek sc->hostif.reset = emuxki_ac97_reset;
341 1.1 jdolecek sc->hostif.flags = NULL;
342 1.1 jdolecek return (ac97_attach(&(sc->hostif)));
343 1.1 jdolecek }
344 1.1 jdolecek
345 1.1 jdolecek static int
346 1.1 jdolecek emuxki_match(struct device *parent, struct cfdata *match, void *aux)
347 1.1 jdolecek {
348 1.1 jdolecek struct pci_attach_args *pa = aux;
349 1.1 jdolecek
350 1.1 jdolecek if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_CREATIVELABS &&
351 1.1 jdolecek PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_CREATIVELABS_SBLIVE)
352 1.1 jdolecek return (1);
353 1.1 jdolecek
354 1.1 jdolecek return (0);
355 1.1 jdolecek }
356 1.1 jdolecek
357 1.1 jdolecek static void
358 1.1 jdolecek emuxki_attach(struct device *parent, struct device *self, void *aux)
359 1.1 jdolecek {
360 1.1 jdolecek struct emuxki_softc *sc = (struct emuxki_softc *) self;
361 1.1 jdolecek struct pci_attach_args *pa = aux;
362 1.1 jdolecek char devinfo[256];
363 1.1 jdolecek pci_intr_handle_t ih;
364 1.1 jdolecek const char *intrstr;
365 1.1 jdolecek
366 1.1 jdolecek if (pci_mapreg_map(pa, EMU_PCI_CBIO, PCI_MAPREG_TYPE_IO, 0,
367 1.1 jdolecek &(sc->sc_iot), &(sc->sc_ioh), &(sc->sc_iob),
368 1.1 jdolecek &(sc->sc_ios))) {
369 1.1 jdolecek printf(": can't map iospace\n");
370 1.1 jdolecek return;
371 1.1 jdolecek }
372 1.1 jdolecek pci_devinfo(pa->pa_id, pa->pa_class, 1, devinfo);
373 1.1 jdolecek printf(": %s\n", devinfo);
374 1.1 jdolecek
375 1.1 jdolecek sc->sc_pc = pa->pa_pc;
376 1.1 jdolecek sc->sc_dmat = pa->pa_dmat;
377 1.1 jdolecek pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG,
378 1.1 jdolecek pci_conf_read(pa->pa_pc, pa->pa_tag,
379 1.1 jdolecek (PCI_COMMAND_STATUS_REG) | PCI_COMMAND_MASTER_ENABLE));
380 1.1 jdolecek
381 1.1 jdolecek if (pci_intr_map(pa, &ih)) {
382 1.1 jdolecek printf(", couldn't map interrupt\n");
383 1.1 jdolecek bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_ios);
384 1.1 jdolecek return;
385 1.1 jdolecek }
386 1.1 jdolecek
387 1.1 jdolecek intrstr = pci_intr_string(pa->pa_pc, ih);
388 1.1 jdolecek sc->sc_ih = pci_intr_establish(pa->pa_pc, ih, IPL_AUDIO, emuxki_intr,
389 1.1 jdolecek sc);
390 1.1 jdolecek if (sc->sc_ih == NULL) {
391 1.1 jdolecek printf(", couldn't establish interrupt", sc->sc_dev.dv_xname);
392 1.1 jdolecek if (intrstr != NULL)
393 1.1 jdolecek printf(" at %s", intrstr);
394 1.1 jdolecek printf("\n");
395 1.1 jdolecek bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_ios);
396 1.1 jdolecek return;
397 1.1 jdolecek }
398 1.1 jdolecek printf("%s: interrupting at %s\n", sc->sc_dev.dv_xname, intrstr);
399 1.1 jdolecek
400 1.1 jdolecek if (emuxki_scinit(sc) || emuxki_ac97_init(sc) ||
401 1.1 jdolecek (sc->sc_audev = audio_attach_mi(&emuxki_hw_if, sc, self)) == NULL)
402 1.1 jdolecek emuxki_pci_shutdown(sc);
403 1.1 jdolecek }
404 1.1 jdolecek
405 1.1 jdolecek static int
406 1.1 jdolecek emuxki_detach(struct device *self, int flags)
407 1.1 jdolecek {
408 1.1 jdolecek struct emuxki_softc *sc = (struct emuxki_softc *) self;
409 1.1 jdolecek int err = 0;
410 1.1 jdolecek
411 1.1 jdolecek if (sc->sc_audev != NULL) /* Test in case audio didn't attach */
412 1.1 jdolecek err = config_detach(sc->sc_audev, 0);
413 1.1 jdolecek
414 1.1 jdolecek /* All voices should be stopped now but add some code here if not */
415 1.1 jdolecek
416 1.1 jdolecek bus_space_write_4(sc->sc_iot, sc->sc_ioh, EMU_HCFG,
417 1.1 jdolecek EMU_HCFG_LOCKSOUNDCACHE | EMU_HCFG_LOCKTANKCACHE_MASK |
418 1.1 jdolecek EMU_HCFG_MUTEBUTTONENABLE);
419 1.1 jdolecek bus_space_write_4(sc->sc_iot, sc->sc_ioh, EMU_INTE, 0);
420 1.1 jdolecek
421 1.1 jdolecek emuxki_shutdown(sc);
422 1.1 jdolecek
423 1.1 jdolecek emuxki_pci_shutdown(sc);
424 1.1 jdolecek
425 1.1 jdolecek return (0);
426 1.1 jdolecek }
427 1.1 jdolecek
428 1.1 jdolecek
429 1.1 jdolecek /* Misc stuff relative to emu10k1 */
430 1.1 jdolecek
431 1.1 jdolecek static u_int32_t
432 1.1 jdolecek emuxki_rate_to_pitch(u_int32_t rate)
433 1.1 jdolecek {
434 1.1 jdolecek static const u_int32_t logMagTable[128] = {
435 1.1 jdolecek 0x00000, 0x02dfc, 0x05b9e, 0x088e6, 0x0b5d6, 0x0e26f, 0x10eb3,
436 1.1 jdolecek 0x13aa2, 0x1663f, 0x1918a, 0x1bc84, 0x1e72e, 0x2118b, 0x23b9a,
437 1.1 jdolecek 0x2655d, 0x28ed5, 0x2b803, 0x2e0e8, 0x30985, 0x331db, 0x359eb,
438 1.1 jdolecek 0x381b6, 0x3a93d, 0x3d081, 0x3f782, 0x41e42, 0x444c1, 0x46b01,
439 1.1 jdolecek 0x49101, 0x4b6c4, 0x4dc49, 0x50191, 0x5269e, 0x54b6f, 0x57006,
440 1.1 jdolecek 0x59463, 0x5b888, 0x5dc74, 0x60029, 0x623a7, 0x646ee, 0x66a00,
441 1.1 jdolecek 0x68cdd, 0x6af86, 0x6d1fa, 0x6f43c, 0x7164b, 0x73829, 0x759d4,
442 1.1 jdolecek 0x77b4f, 0x79c9a, 0x7bdb5, 0x7dea1, 0x7ff5e, 0x81fed, 0x8404e,
443 1.1 jdolecek 0x86082, 0x88089, 0x8a064, 0x8c014, 0x8df98, 0x8fef1, 0x91e20,
444 1.1 jdolecek 0x93d26, 0x95c01, 0x97ab4, 0x9993e, 0x9b79f, 0x9d5d9, 0x9f3ec,
445 1.1 jdolecek 0xa11d8, 0xa2f9d, 0xa4d3c, 0xa6ab5, 0xa8808, 0xaa537, 0xac241,
446 1.1 jdolecek 0xadf26, 0xafbe7, 0xb1885, 0xb3500, 0xb5157, 0xb6d8c, 0xb899f,
447 1.1 jdolecek 0xba58f, 0xbc15e, 0xbdd0c, 0xbf899, 0xc1404, 0xc2f50, 0xc4a7b,
448 1.1 jdolecek 0xc6587, 0xc8073, 0xc9b3f, 0xcb5ed, 0xcd07c, 0xceaec, 0xd053f,
449 1.1 jdolecek 0xd1f73, 0xd398a, 0xd5384, 0xd6d60, 0xd8720, 0xda0c3, 0xdba4a,
450 1.1 jdolecek 0xdd3b4, 0xded03, 0xe0636, 0xe1f4e, 0xe384a, 0xe512c, 0xe69f3,
451 1.1 jdolecek 0xe829f, 0xe9b31, 0xeb3a9, 0xecc08, 0xee44c, 0xefc78, 0xf148a,
452 1.1 jdolecek 0xf2c83, 0xf4463, 0xf5c2a, 0xf73da, 0xf8b71, 0xfa2f0, 0xfba57,
453 1.1 jdolecek 0xfd1a7, 0xfe8df
454 1.1 jdolecek };
455 1.1 jdolecek static const u_int8_t logSlopeTable[128] = {
456 1.1 jdolecek 0x5c, 0x5c, 0x5b, 0x5a, 0x5a, 0x59, 0x58, 0x58,
457 1.1 jdolecek 0x57, 0x56, 0x56, 0x55, 0x55, 0x54, 0x53, 0x53,
458 1.1 jdolecek 0x52, 0x52, 0x51, 0x51, 0x50, 0x50, 0x4f, 0x4f,
459 1.1 jdolecek 0x4e, 0x4d, 0x4d, 0x4d, 0x4c, 0x4c, 0x4b, 0x4b,
460 1.1 jdolecek 0x4a, 0x4a, 0x49, 0x49, 0x48, 0x48, 0x47, 0x47,
461 1.1 jdolecek 0x47, 0x46, 0x46, 0x45, 0x45, 0x45, 0x44, 0x44,
462 1.1 jdolecek 0x43, 0x43, 0x43, 0x42, 0x42, 0x42, 0x41, 0x41,
463 1.1 jdolecek 0x41, 0x40, 0x40, 0x40, 0x3f, 0x3f, 0x3f, 0x3e,
464 1.1 jdolecek 0x3e, 0x3e, 0x3d, 0x3d, 0x3d, 0x3c, 0x3c, 0x3c,
465 1.1 jdolecek 0x3b, 0x3b, 0x3b, 0x3b, 0x3a, 0x3a, 0x3a, 0x39,
466 1.1 jdolecek 0x39, 0x39, 0x39, 0x38, 0x38, 0x38, 0x38, 0x37,
467 1.1 jdolecek 0x37, 0x37, 0x37, 0x36, 0x36, 0x36, 0x36, 0x35,
468 1.1 jdolecek 0x35, 0x35, 0x35, 0x34, 0x34, 0x34, 0x34, 0x34,
469 1.1 jdolecek 0x33, 0x33, 0x33, 0x33, 0x32, 0x32, 0x32, 0x32,
470 1.1 jdolecek 0x32, 0x31, 0x31, 0x31, 0x31, 0x31, 0x30, 0x30,
471 1.1 jdolecek 0x30, 0x30, 0x30, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f
472 1.1 jdolecek };
473 1.1 jdolecek int8_t i;
474 1.1 jdolecek
475 1.1 jdolecek if (rate == 0)
476 1.1 jdolecek return 0; /* Bail out if no leading "1" */
477 1.1 jdolecek rate *= 11185; /* Scale 48000 to 0x20002380 */
478 1.1 jdolecek for (i = 31; i > 0; i--) {
479 1.1 jdolecek if (rate & 0x80000000) { /* Detect leading "1" */
480 1.1 jdolecek return (((u_int32_t) (i - 15) << 20) +
481 1.1 jdolecek logMagTable[0x7f & (rate >> 24)] +
482 1.1 jdolecek (0x7f & (rate >> 17)) *
483 1.1 jdolecek logSlopeTable[0x7f & (rate >> 24)]);
484 1.1 jdolecek }
485 1.1 jdolecek rate <<= 1;
486 1.1 jdolecek }
487 1.1 jdolecek
488 1.1 jdolecek return 0; /* Should never reach this point */
489 1.1 jdolecek }
490 1.1 jdolecek
491 1.1 jdolecek /* Emu10k1 Low level */
492 1.1 jdolecek
493 1.1 jdolecek static u_int32_t
494 1.1 jdolecek emuxki_read(struct emuxki_softc *sc, u_int16_t chano, u_int32_t reg)
495 1.1 jdolecek {
496 1.1 jdolecek u_int32_t ptr, mask = 0xffffffff;
497 1.1 jdolecek u_int8_t size, offset = 0;
498 1.1 jdolecek int s;
499 1.1 jdolecek
500 1.1 jdolecek ptr = ((((u_int32_t) reg) << 16) & EMU_PTR_ADDR_MASK) |
501 1.1 jdolecek (chano & EMU_PTR_CHNO_MASK);
502 1.1 jdolecek if (reg & 0xff000000) {
503 1.1 jdolecek size = (reg >> 24) & 0x3f;
504 1.1 jdolecek offset = (reg >> 16) & 0x1f;
505 1.1 jdolecek mask = ((1 << size) - 1) << offset;
506 1.1 jdolecek }
507 1.1 jdolecek
508 1.1 jdolecek s = splaudio();
509 1.1 jdolecek bus_space_write_4(sc->sc_iot, sc->sc_ioh, EMU_PTR, ptr);
510 1.1 jdolecek ptr = (bus_space_read_4(sc->sc_iot, sc->sc_ioh, EMU_DATA) & mask)
511 1.1 jdolecek >> offset;
512 1.1 jdolecek splx(s);
513 1.1 jdolecek
514 1.1 jdolecek return (ptr);
515 1.1 jdolecek }
516 1.1 jdolecek
517 1.1 jdolecek static void
518 1.1 jdolecek emuxki_write(struct emuxki_softc *sc, u_int16_t chano,
519 1.1 jdolecek u_int32_t reg, u_int32_t data)
520 1.1 jdolecek {
521 1.1 jdolecek u_int32_t ptr, mask;
522 1.1 jdolecek u_int8_t size, offset;
523 1.1 jdolecek int s;
524 1.1 jdolecek
525 1.1 jdolecek ptr = ((((u_int32_t) reg) << 16) & EMU_PTR_ADDR_MASK) |
526 1.1 jdolecek (chano & EMU_PTR_CHNO_MASK);
527 1.1 jdolecek if (reg & 0xff000000) {
528 1.1 jdolecek size = (reg >> 24) & 0x3f;
529 1.1 jdolecek offset = (reg >> 16) & 0x1f;
530 1.1 jdolecek mask = ((1 << size) - 1) << offset;
531 1.1 jdolecek data = ((data << offset) & mask) |
532 1.1 jdolecek (emuxki_read(sc, chano, reg & 0xffff) & ~mask);
533 1.1 jdolecek }
534 1.1 jdolecek
535 1.1 jdolecek s = splaudio();
536 1.1 jdolecek bus_space_write_4(sc->sc_iot, sc->sc_ioh, EMU_PTR, ptr);
537 1.1 jdolecek bus_space_write_4(sc->sc_iot, sc->sc_ioh, EMU_DATA, data);
538 1.1 jdolecek splx(s);
539 1.1 jdolecek }
540 1.1 jdolecek
541 1.1 jdolecek /* Microcode should this go in /sys/dev/microcode ? */
542 1.1 jdolecek
543 1.1 jdolecek static void
544 1.1 jdolecek emuxki_write_micro(struct emuxki_softc *sc, u_int32_t pc, u_int32_t data)
545 1.1 jdolecek {
546 1.1 jdolecek emuxki_write(sc, 0, EMU_MICROCODEBASE + pc, data);
547 1.1 jdolecek }
548 1.1 jdolecek
549 1.1 jdolecek static void
550 1.1 jdolecek emuxki_dsp_addop(struct emuxki_softc *sc, u_int16_t *pc, u_int8_t op,
551 1.1 jdolecek u_int16_t r, u_int16_t a, u_int16_t x, u_int16_t y)
552 1.1 jdolecek {
553 1.1 jdolecek emuxki_write_micro(sc, *pc << 1,
554 1.1 jdolecek ((x << 10) & EMU_DSP_LOWORD_OPX_MASK) |
555 1.1 jdolecek (y & EMU_DSP_LOWORD_OPY_MASK));
556 1.1 jdolecek emuxki_write_micro(sc, (*pc << 1) + 1,
557 1.1 jdolecek ((op << 20) & EMU_DSP_HIWORD_OPCODE_MASK) |
558 1.1 jdolecek ((r << 10) & EMU_DSP_HIWORD_RESULT_MASK) |
559 1.1 jdolecek (a & EMU_DSP_HIWORD_OPA_MASK));
560 1.1 jdolecek (*pc)++;
561 1.1 jdolecek }
562 1.1 jdolecek
563 1.1 jdolecek /* init and shutdown */
564 1.1 jdolecek
565 1.1 jdolecek static void
566 1.1 jdolecek emuxki_initfx(struct emuxki_softc *sc)
567 1.1 jdolecek {
568 1.1 jdolecek u_int16_t pc;
569 1.1 jdolecek
570 1.1 jdolecek /* Set all GPRs to 0 */
571 1.1 jdolecek for (pc = 0; pc < 256; pc++)
572 1.1 jdolecek emuxki_write(sc, 0, EMU_DSP_GPR(pc), 0);
573 1.1 jdolecek for (pc = 0; pc < 160; pc++) {
574 1.1 jdolecek emuxki_write(sc, 0, EMU_TANKMEMDATAREGBASE + pc, 0);
575 1.1 jdolecek emuxki_write(sc, 0, EMU_TANKMEMADDRREGBASE + pc, 0);
576 1.1 jdolecek }
577 1.1 jdolecek pc = 0;
578 1.1 jdolecek /* AC97 Out (l/r) = AC97 In (l/r) + FX[0/1] * 4 */
579 1.1 jdolecek emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_MACINTS,
580 1.1 jdolecek EMU_DSP_OUTL(EMU_DSP_OUT_AC97),
581 1.1 jdolecek EMU_DSP_CST(0),
582 1.1 jdolecek EMU_DSP_FX(0), EMU_DSP_CST(4));
583 1.1 jdolecek emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_MACINTS,
584 1.1 jdolecek EMU_DSP_OUTR(EMU_DSP_OUT_AC97),
585 1.1 jdolecek EMU_DSP_CST(0),
586 1.1 jdolecek EMU_DSP_FX(1), EMU_DSP_CST(4));
587 1.1 jdolecek
588 1.1 jdolecek /* Rear channel OUT (l/r) = FX[2/3] * 4 */
589 1.1 jdolecek #if 0
590 1.1 jdolecek emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_MACINTS,
591 1.1 jdolecek EMU_DSP_OUTL(EMU_DSP_OUT_RCHAN),
592 1.1 jdolecek EMU_DSP_OUTL(EMU_DSP_OUT_AC97),
593 1.1 jdolecek EMU_DSP_FX(0), EMU_DSP_CST(4));
594 1.1 jdolecek emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_MACINTS,
595 1.1 jdolecek EMU_DSP_OUTR(EMU_DSP_OUT_RCHAN),
596 1.1 jdolecek EMU_DSP_OUTR(EMU_DSP_OUT_AC97),
597 1.1 jdolecek EMU_DSP_FX(1), EMU_DSP_CST(4));
598 1.1 jdolecek #endif
599 1.1 jdolecek /* zero out the rest of the microcode */
600 1.1 jdolecek while (pc < 512)
601 1.1 jdolecek emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_ACC3,
602 1.1 jdolecek EMU_DSP_CST(0), EMU_DSP_CST(0),
603 1.1 jdolecek EMU_DSP_CST(0), EMU_DSP_CST(0));
604 1.1 jdolecek
605 1.1 jdolecek emuxki_write(sc, 0, EMU_DBG, 0); /* Is it really necessary ? */
606 1.1 jdolecek }
607 1.1 jdolecek
608 1.1 jdolecek static int
609 1.1 jdolecek emuxki_init(struct emuxki_softc *sc)
610 1.1 jdolecek {
611 1.1 jdolecek u_int16_t i;
612 1.1 jdolecek u_int32_t spcs, *ptb;
613 1.1 jdolecek bus_addr_t silentpage;
614 1.1 jdolecek
615 1.1 jdolecek /* disable any channel interrupt */
616 1.1 jdolecek emuxki_write(sc, 0, EMU_CLIEL, 0);
617 1.1 jdolecek emuxki_write(sc, 0, EMU_CLIEH, 0);
618 1.1 jdolecek emuxki_write(sc, 0, EMU_SOLEL, 0);
619 1.1 jdolecek emuxki_write(sc, 0, EMU_SOLEH, 0);
620 1.1 jdolecek
621 1.1 jdolecek /* Set recording buffers sizes to zero */
622 1.1 jdolecek emuxki_write(sc, 0, EMU_MICBS, EMU_RECBS_BUFSIZE_NONE);
623 1.1 jdolecek emuxki_write(sc, 0, EMU_MICBA, 0);
624 1.1 jdolecek emuxki_write(sc, 0, EMU_FXBS, EMU_RECBS_BUFSIZE_NONE);
625 1.1 jdolecek emuxki_write(sc, 0, EMU_FXBA, 0);
626 1.1 jdolecek emuxki_write(sc, 0, EMU_ADCBS, EMU_RECBS_BUFSIZE_NONE);
627 1.1 jdolecek emuxki_write(sc, 0, EMU_ADCBA, 0);
628 1.1 jdolecek
629 1.1 jdolecek /* Initialize all channels to stopped and no effects */
630 1.1 jdolecek for (i = 0; i < EMU_NUMCHAN; i++) {
631 1.1 jdolecek emuxki_write(sc, i, EMU_CHAN_DCYSUSV, 0);
632 1.1 jdolecek emuxki_write(sc, i, EMU_CHAN_IP, 0);
633 1.1 jdolecek emuxki_write(sc, i, EMU_CHAN_VTFT, 0xffff);
634 1.1 jdolecek emuxki_write(sc, i, EMU_CHAN_CVCF, 0xffff);
635 1.1 jdolecek emuxki_write(sc, i, EMU_CHAN_PTRX, 0);
636 1.1 jdolecek emuxki_write(sc, i, EMU_CHAN_CPF, 0);
637 1.1 jdolecek emuxki_write(sc, i, EMU_CHAN_CCR, 0);
638 1.1 jdolecek emuxki_write(sc, i, EMU_CHAN_PSST, 0);
639 1.1 jdolecek emuxki_write(sc, i, EMU_CHAN_DSL, 0x10); /* Why 16 ? */
640 1.1 jdolecek emuxki_write(sc, i, EMU_CHAN_CCCA, 0);
641 1.1 jdolecek emuxki_write(sc, i, EMU_CHAN_Z1, 0);
642 1.1 jdolecek emuxki_write(sc, i, EMU_CHAN_Z2, 0);
643 1.1 jdolecek emuxki_write(sc, i, EMU_CHAN_FXRT, 0x32100000);
644 1.1 jdolecek emuxki_write(sc, i, EMU_CHAN_ATKHLDM, 0);
645 1.1 jdolecek emuxki_write(sc, i, EMU_CHAN_DCYSUSM, 0);
646 1.1 jdolecek emuxki_write(sc, i, EMU_CHAN_IFATN, 0xffff);
647 1.1 jdolecek emuxki_write(sc, i, EMU_CHAN_PEFE, 0);
648 1.1 jdolecek emuxki_write(sc, i, EMU_CHAN_FMMOD, 0);
649 1.1 jdolecek emuxki_write(sc, i, EMU_CHAN_TREMFRQ, 24);
650 1.1 jdolecek emuxki_write(sc, i, EMU_CHAN_FM2FRQ2, 24);
651 1.1 jdolecek emuxki_write(sc, i, EMU_CHAN_TEMPENV, 0);
652 1.1 jdolecek
653 1.1 jdolecek /* these are last so OFF prevents writing */
654 1.1 jdolecek emuxki_write(sc, i, EMU_CHAN_LFOVAL2, 0);
655 1.1 jdolecek emuxki_write(sc, i, EMU_CHAN_LFOVAL1, 0);
656 1.1 jdolecek emuxki_write(sc, i, EMU_CHAN_ATKHLDV, 0);
657 1.1 jdolecek emuxki_write(sc, i, EMU_CHAN_ENVVOL, 0);
658 1.1 jdolecek emuxki_write(sc, i, EMU_CHAN_ENVVAL, 0);
659 1.1 jdolecek }
660 1.1 jdolecek
661 1.1 jdolecek /* set digital outputs format */
662 1.1 jdolecek spcs = (EMU_SPCS_CLKACCY_1000PPM | EMU_SPCS_SAMPLERATE_48 |
663 1.1 jdolecek EMU_SPCS_CHANNELNUM_LEFT | EMU_SPCS_SOURCENUM_UNSPEC |
664 1.1 jdolecek EMU_SPCS_GENERATIONSTATUS | 0x00001200 /* Cat code. */ |
665 1.1 jdolecek 0x00000000 /* IEC-958 Mode */ | EMU_SPCS_EMPHASIS_NONE |
666 1.1 jdolecek EMU_SPCS_COPYRIGHT);
667 1.1 jdolecek emuxki_write(sc, 0, EMU_SPCS0, spcs);
668 1.1 jdolecek emuxki_write(sc, 0, EMU_SPCS1, spcs);
669 1.1 jdolecek emuxki_write(sc, 0, EMU_SPCS2, spcs);
670 1.1 jdolecek
671 1.1 jdolecek /* Let's play with sound processor */
672 1.1 jdolecek emuxki_initfx(sc);
673 1.1 jdolecek
674 1.1 jdolecek /* Here is our Page Table */
675 1.1 jdolecek if ((sc->ptb = dmamem_alloc(sc->sc_dmat,
676 1.1 jdolecek EMU_MAXPTE * sizeof(u_int32_t),
677 1.1 jdolecek EMU_DMA_ALIGN, EMU_DMAMEM_NSEG,
678 1.1 jdolecek M_DEVBUF, M_WAITOK)) == NULL)
679 1.1 jdolecek return (ENOMEM);
680 1.1 jdolecek
681 1.1 jdolecek /* This is necessary unless you like Metallic noise... */
682 1.1 jdolecek if ((sc->silentpage = dmamem_alloc(sc->sc_dmat, EMU_PTESIZE,
683 1.1 jdolecek EMU_DMA_ALIGN, EMU_DMAMEM_NSEG, M_DEVBUF, M_WAITOK))==NULL){
684 1.1 jdolecek dmamem_free(sc->ptb, M_DEVBUF);
685 1.1 jdolecek return (ENOMEM);
686 1.1 jdolecek }
687 1.1 jdolecek
688 1.1 jdolecek /* Zero out the silent page */
689 1.1 jdolecek /* This might not be always true, it might be 128 for 8bit channels */
690 1.1 jdolecek memset(KERNADDR(sc->silentpage), 0, DMASIZE(sc->silentpage));
691 1.1 jdolecek
692 1.1 jdolecek /*
693 1.1 jdolecek * Set all the PTB Entries to the silent page We shift the physical
694 1.1 jdolecek * address by one and OR it with the page number. I don't know what
695 1.1 jdolecek * the ORed index is for, might be a very useful unused feature...
696 1.1 jdolecek */
697 1.1 jdolecek silentpage = DMAADDR(sc->silentpage) << 1;
698 1.1 jdolecek ptb = KERNADDR(sc->ptb);
699 1.1 jdolecek for (i = 0; i < EMU_MAXPTE; i++)
700 1.1 jdolecek ptb[i] = silentpage | i;
701 1.1 jdolecek
702 1.1 jdolecek /* Write PTB address and set TCB to none */
703 1.1 jdolecek emuxki_write(sc, 0, EMU_PTB, DMAADDR(sc->ptb));
704 1.1 jdolecek emuxki_write(sc, 0, EMU_TCBS, 0); /* This means 16K TCB */
705 1.1 jdolecek emuxki_write(sc, 0, EMU_TCB, 0); /* No TCB use for now */
706 1.1 jdolecek
707 1.1 jdolecek /*
708 1.1 jdolecek * Set channels MAPs to the silent page.
709 1.1 jdolecek * I don't know what MAPs are for.
710 1.1 jdolecek */
711 1.1 jdolecek silentpage |= EMU_CHAN_MAP_PTI_MASK;
712 1.1 jdolecek for (i = 0; i < EMU_NUMCHAN; i++) {
713 1.1 jdolecek emuxki_write(sc, i, EMU_CHAN_MAPA, silentpage);
714 1.1 jdolecek emuxki_write(sc, i, EMU_CHAN_MAPB, silentpage);
715 1.1 jdolecek sc->channel[i] = NULL;
716 1.1 jdolecek }
717 1.1 jdolecek
718 1.1 jdolecek /* Init voices list */
719 1.1 jdolecek LIST_INIT(&(sc->voices));
720 1.1 jdolecek
721 1.1 jdolecek /* Timer is stopped */
722 1.1 jdolecek sc->timerstate &= ~EMU_TIMER_STATE_ENABLED;
723 1.1 jdolecek return (0);
724 1.1 jdolecek }
725 1.1 jdolecek
726 1.1 jdolecek static void
727 1.1 jdolecek emuxki_shutdown(struct emuxki_softc *sc)
728 1.1 jdolecek {
729 1.1 jdolecek u_int32_t i;
730 1.1 jdolecek
731 1.1 jdolecek /* Disable any Channels interrupts */
732 1.1 jdolecek emuxki_write(sc, 0, EMU_CLIEL, 0);
733 1.1 jdolecek emuxki_write(sc, 0, EMU_CLIEH, 0);
734 1.1 jdolecek emuxki_write(sc, 0, EMU_SOLEL, 0);
735 1.1 jdolecek emuxki_write(sc, 0, EMU_SOLEH, 0);
736 1.1 jdolecek
737 1.1 jdolecek /*
738 1.1 jdolecek * Should do some voice(stream) stopping stuff here, that's what will
739 1.1 jdolecek * stop and deallocate all channels.
740 1.1 jdolecek */
741 1.1 jdolecek
742 1.1 jdolecek /* Stop all channels */
743 1.1 jdolecek /* XXX This shouldn't be necessary, I'll remove once everything works */
744 1.1 jdolecek for (i = 0; i < EMU_NUMCHAN; i++)
745 1.1 jdolecek emuxki_write(sc, i, EMU_CHAN_DCYSUSV, 0);
746 1.1 jdolecek for (i = 0; i < EMU_NUMCHAN; i++) {
747 1.1 jdolecek emuxki_write(sc, i, EMU_CHAN_VTFT, 0);
748 1.1 jdolecek emuxki_write(sc, i, EMU_CHAN_CVCF, 0);
749 1.1 jdolecek emuxki_write(sc, i, EMU_CHAN_PTRX, 0);
750 1.1 jdolecek emuxki_write(sc, i, EMU_CHAN_CPF, 0);
751 1.1 jdolecek }
752 1.1 jdolecek
753 1.1 jdolecek /*
754 1.1 jdolecek * Deallocate Emu10k1 caches and recording buffers. Again it will be
755 1.1 jdolecek * removed because it will be done in voice shutdown.
756 1.1 jdolecek */
757 1.1 jdolecek emuxki_write(sc, 0, EMU_MICBS, EMU_RECBS_BUFSIZE_NONE);
758 1.1 jdolecek emuxki_write(sc, 0, EMU_MICBA, 0);
759 1.1 jdolecek emuxki_write(sc, 0, EMU_FXBS, EMU_RECBS_BUFSIZE_NONE);
760 1.1 jdolecek emuxki_write(sc, 0, EMU_FXBA, 0);
761 1.1 jdolecek emuxki_write(sc, 0, EMU_FXWC, 0);
762 1.1 jdolecek emuxki_write(sc, 0, EMU_ADCBS, EMU_RECBS_BUFSIZE_NONE);
763 1.1 jdolecek emuxki_write(sc, 0, EMU_ADCBA, 0);
764 1.1 jdolecek
765 1.1 jdolecek /*
766 1.1 jdolecek * XXX I don't know yet how I will handle tank cache buffer,
767 1.1 jdolecek * I don't even clearly know what it is for.
768 1.1 jdolecek */
769 1.1 jdolecek emuxki_write(sc, 0, EMU_TCB, 0); /* 16K again */
770 1.1 jdolecek emuxki_write(sc, 0, EMU_TCBS, 0);
771 1.1 jdolecek
772 1.1 jdolecek emuxki_write(sc, 0, EMU_DBG, 0x8000); /* necessary ? */
773 1.1 jdolecek
774 1.1 jdolecek dmamem_free(sc->silentpage, M_DEVBUF);
775 1.1 jdolecek dmamem_free(sc->ptb, M_DEVBUF);
776 1.1 jdolecek }
777 1.1 jdolecek
778 1.1 jdolecek /* Emu10k1 Memory managment */
779 1.1 jdolecek
780 1.1 jdolecek static struct emuxki_mem *
781 1.1 jdolecek emuxki_mem_new(struct emuxki_softc *sc, int ptbidx,
782 1.1 jdolecek size_t size, int type, int flags)
783 1.1 jdolecek {
784 1.1 jdolecek struct emuxki_mem *mem;
785 1.1 jdolecek
786 1.1 jdolecek if ((mem = malloc(sizeof(*mem), type, flags)) == NULL)
787 1.1 jdolecek return (NULL);
788 1.1 jdolecek
789 1.1 jdolecek mem->ptbidx = ptbidx;
790 1.1 jdolecek if ((mem->dmamem = dmamem_alloc(sc->sc_dmat, size, EMU_DMA_ALIGN,
791 1.1 jdolecek EMU_DMAMEM_NSEG, type, flags)) == NULL) {
792 1.1 jdolecek free(mem, type);
793 1.1 jdolecek return (NULL);
794 1.1 jdolecek }
795 1.1 jdolecek return (mem);
796 1.1 jdolecek }
797 1.1 jdolecek
798 1.1 jdolecek static void
799 1.1 jdolecek emuxki_mem_delete(struct emuxki_mem *mem, int type)
800 1.1 jdolecek {
801 1.1 jdolecek dmamem_free(mem->dmamem, type);
802 1.1 jdolecek free(mem, type);
803 1.1 jdolecek }
804 1.1 jdolecek
805 1.1 jdolecek static void *
806 1.1 jdolecek emuxki_pmem_alloc(struct emuxki_softc *sc, size_t size, int type, int flags)
807 1.1 jdolecek {
808 1.1 jdolecek int i, j, s;
809 1.1 jdolecek size_t numblocks;
810 1.1 jdolecek struct emuxki_mem *mem;
811 1.1 jdolecek u_int32_t *ptb, silentpage;
812 1.1 jdolecek
813 1.1 jdolecek ptb = KERNADDR(sc->ptb);
814 1.1 jdolecek silentpage = DMAADDR(sc->silentpage) << 1;
815 1.1 jdolecek numblocks = size / EMU_PTESIZE;
816 1.1 jdolecek if (size % EMU_PTESIZE)
817 1.1 jdolecek numblocks++;
818 1.1 jdolecek
819 1.1 jdolecek for (i = 0; i < EMU_MAXPTE; i++)
820 1.1 jdolecek if ((ptb[i] & EMU_CHAN_MAP_PTE_MASK) == silentpage) {
821 1.1 jdolecek /* We look for a free PTE */
822 1.1 jdolecek s = splaudio();
823 1.1 jdolecek for (j = 0; j < numblocks; j++)
824 1.1 jdolecek if ((ptb[i + j] & EMU_CHAN_MAP_PTE_MASK)
825 1.1 jdolecek != silentpage)
826 1.1 jdolecek break;
827 1.1 jdolecek if (j == numblocks) {
828 1.1 jdolecek if ((mem = emuxki_mem_new(sc, i,
829 1.1 jdolecek size, type, flags)) == NULL) {
830 1.1 jdolecek splx(s);
831 1.1 jdolecek return (NULL);
832 1.1 jdolecek }
833 1.1 jdolecek for (j = 0; j < numblocks; j++)
834 1.1 jdolecek ptb[i + j] =
835 1.1 jdolecek (((DMAADDR(mem->dmamem) +
836 1.1 jdolecek j * EMU_PTESIZE)) << 1)
837 1.1 jdolecek | (i + j);
838 1.1 jdolecek LIST_INSERT_HEAD(&(sc->mem), mem, next);
839 1.1 jdolecek splx(s);
840 1.1 jdolecek return (KERNADDR(mem->dmamem));
841 1.1 jdolecek } else
842 1.1 jdolecek i += j;
843 1.1 jdolecek splx(s);
844 1.1 jdolecek }
845 1.1 jdolecek return (NULL);
846 1.1 jdolecek }
847 1.1 jdolecek
848 1.1 jdolecek static void *
849 1.1 jdolecek emuxki_rmem_alloc(struct emuxki_softc *sc, size_t size, int type, int flags)
850 1.1 jdolecek {
851 1.1 jdolecek struct emuxki_mem *mem;
852 1.1 jdolecek int s;
853 1.1 jdolecek
854 1.1 jdolecek mem = emuxki_mem_new(sc, EMU_RMEM, size, type, flags);
855 1.1 jdolecek if (mem == NULL)
856 1.1 jdolecek return (NULL);
857 1.1 jdolecek
858 1.1 jdolecek s = splaudio();
859 1.1 jdolecek LIST_INSERT_HEAD(&(sc->mem), mem, next);
860 1.1 jdolecek splx(s);
861 1.1 jdolecek
862 1.1 jdolecek return (KERNADDR(mem->dmamem));
863 1.1 jdolecek }
864 1.1 jdolecek
865 1.1 jdolecek /*
866 1.1 jdolecek * emuxki_channel_* : Channel managment functions
867 1.1 jdolecek * emuxki_chanparms_* : Channel parameters modification functions
868 1.1 jdolecek */
869 1.1 jdolecek
870 1.1 jdolecek /*
871 1.1 jdolecek * is splaudio necessary here, can the same voice be manipulated by two
872 1.1 jdolecek * different threads at a time ?
873 1.1 jdolecek */
874 1.1 jdolecek static void
875 1.1 jdolecek emuxki_chanparms_set_defaults(struct emuxki_channel *chan)
876 1.1 jdolecek {
877 1.1 jdolecek chan->fxsend.a.level = chan->fxsend.b.level =
878 1.1 jdolecek chan->fxsend.c.level = chan->fxsend.d.level = 0xff; /* max */
879 1.1 jdolecek chan->fxsend.a.dest = 0x0;
880 1.1 jdolecek chan->fxsend.b.dest = 0x1;
881 1.1 jdolecek chan->fxsend.c.dest = 0x2;
882 1.1 jdolecek chan->fxsend.d.dest = 0x3;
883 1.1 jdolecek
884 1.1 jdolecek chan->pitch.intial = 0x0000; /* shouldn't it be 0xE000 ? */
885 1.1 jdolecek chan->pitch.current = 0x0000; /* should it be 0x0400 */
886 1.1 jdolecek chan->pitch.target = 0x0000; /* the unity pitch shift ? */
887 1.1 jdolecek chan->pitch.envelope_amount = 0x00; /* none */
888 1.1 jdolecek
889 1.1 jdolecek chan->initial_attenuation = 0x00; /* no attenuation */
890 1.1 jdolecek chan->volume.current = 0x0000; /* no volume */
891 1.1 jdolecek chan->volume.target = 0xffff;
892 1.1 jdolecek chan->volume.envelope.current_state = 0x8000; /* 0 msec delay */
893 1.1 jdolecek chan->volume.envelope.hold_time = 0x7f; /* 0 msec */
894 1.1 jdolecek chan->volume.envelope.attack_time = 0x7F; /* 5.5msec */
895 1.1 jdolecek chan->volume.envelope.sustain_level = 0x7F; /* full */
896 1.1 jdolecek chan->volume.envelope.decay_time = 0x7F; /* 22msec */
897 1.1 jdolecek
898 1.1 jdolecek chan->filter.initial_cutoff_frequency = 0xff; /* no filter */
899 1.1 jdolecek chan->filter.current_cutoff_frequency = 0xffff; /* no filtering */
900 1.1 jdolecek chan->filter.target_cutoff_frequency = 0xffff; /* no filtering */
901 1.1 jdolecek chan->filter.lowpass_resonance_height = 0x0;
902 1.1 jdolecek chan->filter.interpolation_ROM = 0x1; /* full band */
903 1.1 jdolecek chan->filter.envelope_amount = 0x7f; /* none */
904 1.1 jdolecek chan->filter.LFO_modulation_depth = 0x00; /* none */
905 1.1 jdolecek
906 1.1 jdolecek chan->loop.start = 0x000000;
907 1.1 jdolecek chan->loop.end = 0x000010; /* Why ? */
908 1.1 jdolecek
909 1.1 jdolecek chan->modulation.envelope.current_state = 0x8000;
910 1.1 jdolecek chan->modulation.envelope.hold_time = 0x00; /* 127 better ? */
911 1.1 jdolecek chan->modulation.envelope.attack_time = 0x00; /* infinite */
912 1.1 jdolecek chan->modulation.envelope.sustain_level = 0x00; /* off */
913 1.1 jdolecek chan->modulation.envelope.decay_time = 0x7f; /* 22 msec */
914 1.1 jdolecek chan->modulation.LFO_state = 0x8000;
915 1.1 jdolecek
916 1.1 jdolecek chan->vibrato_LFO.state = 0x8000;
917 1.1 jdolecek chan->vibrato_LFO.modulation_depth = 0x00; /* none */
918 1.1 jdolecek chan->vibrato_LFO.vibrato_depth = 0x00;
919 1.1 jdolecek chan->vibrato_LFO.frequency = 0x00; /* Why set to 24 when
920 1.1 jdolecek * initialized ? */
921 1.1 jdolecek
922 1.1 jdolecek chan->tremolo_depth = 0x00;
923 1.1 jdolecek }
924 1.1 jdolecek
925 1.1 jdolecek /* only call it at splaudio */
926 1.1 jdolecek static struct emuxki_channel *
927 1.1 jdolecek emuxki_channel_new(struct emuxki_voice *voice, u_int8_t num)
928 1.1 jdolecek {
929 1.1 jdolecek struct emuxki_channel *chan;
930 1.1 jdolecek
931 1.1 jdolecek chan = malloc(sizeof(struct emuxki_channel), M_DEVBUF, M_WAITOK);
932 1.1 jdolecek if (chan == NULL)
933 1.1 jdolecek return (NULL);
934 1.1 jdolecek
935 1.1 jdolecek chan->voice = voice;
936 1.1 jdolecek chan->num = num;
937 1.1 jdolecek emuxki_chanparms_set_defaults(chan);
938 1.1 jdolecek chan->voice->sc->channel[num] = chan;
939 1.1 jdolecek return (chan);
940 1.1 jdolecek }
941 1.1 jdolecek
942 1.1 jdolecek /* only call it at splaudio */
943 1.1 jdolecek static void
944 1.1 jdolecek emuxki_channel_delete(struct emuxki_channel *chan)
945 1.1 jdolecek {
946 1.1 jdolecek chan->voice->sc->channel[chan->num] = NULL;
947 1.1 jdolecek free(chan, M_DEVBUF);
948 1.1 jdolecek }
949 1.1 jdolecek
950 1.1 jdolecek static void
951 1.1 jdolecek emuxki_channel_set_fxsend(struct emuxki_channel *chan,
952 1.1 jdolecek struct emuxki_chanparms_fxsend *fxsend)
953 1.1 jdolecek {
954 1.1 jdolecek /* Could do a memcpy ...*/
955 1.1 jdolecek chan->fxsend.a.level = fxsend->a.level;
956 1.1 jdolecek chan->fxsend.b.level = fxsend->b.level;
957 1.1 jdolecek chan->fxsend.c.level = fxsend->c.level;
958 1.1 jdolecek chan->fxsend.d.level = fxsend->d.level;
959 1.1 jdolecek chan->fxsend.a.dest = fxsend->a.dest;
960 1.1 jdolecek chan->fxsend.b.dest = fxsend->b.dest;
961 1.1 jdolecek chan->fxsend.c.dest = fxsend->c.dest;
962 1.1 jdolecek chan->fxsend.d.dest = fxsend->d.dest;
963 1.1 jdolecek }
964 1.1 jdolecek
965 1.1 jdolecek static void
966 1.1 jdolecek emuxki_channel_set_srate(struct emuxki_channel *chan, u_int32_t srate)
967 1.1 jdolecek {
968 1.1 jdolecek chan->pitch.target = (srate << 8) / 375;
969 1.1 jdolecek chan->pitch.target = (chan->pitch.target >> 1) +
970 1.1 jdolecek (chan->pitch.target & 1);
971 1.1 jdolecek chan->pitch.target &= 0xffff;
972 1.1 jdolecek chan->pitch.current = chan->pitch.target;
973 1.1 jdolecek chan->pitch.intial =
974 1.1 jdolecek (emuxki_rate_to_pitch(srate) >> 8) & EMU_CHAN_IP_MASK;
975 1.1 jdolecek }
976 1.1 jdolecek
977 1.1 jdolecek /* voice params must be set before calling this */
978 1.1 jdolecek static void
979 1.1 jdolecek emuxki_channel_set_bufparms(struct emuxki_channel *chan,
980 1.1 jdolecek u_int32_t start, u_int32_t end)
981 1.1 jdolecek {
982 1.1 jdolecek u_int8_t shift;
983 1.1 jdolecek struct emuxki_voice *voice = chan->voice;
984 1.1 jdolecek
985 1.1 jdolecek shift = voice->stereo + voice->b16;
986 1.1 jdolecek chan->loop.start = start & EMU_CHAN_PSST_LOOPSTARTADDR_MASK;
987 1.1 jdolecek chan->loop.end = end & EMU_CHAN_DSL_LOOPENDADDR_MASK;
988 1.1 jdolecek }
989 1.1 jdolecek
990 1.1 jdolecek static void
991 1.1 jdolecek emuxki_channel_commit_parms(struct emuxki_channel *chan)
992 1.1 jdolecek {
993 1.1 jdolecek struct emuxki_voice *voice = chan->voice;
994 1.1 jdolecek struct emuxki_softc *sc = voice->sc;
995 1.1 jdolecek u_int32_t start, mapval;
996 1.1 jdolecek u_int8_t chano = chan->num;
997 1.1 jdolecek int s;
998 1.1 jdolecek
999 1.1 jdolecek start = chan->loop.start +
1000 1.1 jdolecek (voice->stereo ? 28 : 30) * (voice->b16 + 1);
1001 1.1 jdolecek mapval = DMAADDR(sc->silentpage) << 1 | EMU_CHAN_MAP_PTI_MASK;
1002 1.1 jdolecek
1003 1.1 jdolecek s = splaudio();
1004 1.1 jdolecek emuxki_write(sc, chano, EMU_CHAN_CPF_STEREO, voice->stereo);
1005 1.1 jdolecek emuxki_write(sc, chano, EMU_CHAN_FXRT,
1006 1.1 jdolecek (chan->fxsend.d.dest << 28) | (chan->fxsend.c.dest << 24) |
1007 1.1 jdolecek (chan->fxsend.b.dest << 20) | (chan->fxsend.a.dest << 16));
1008 1.1 jdolecek emuxki_write(sc, chano, 0x10000000 | EMU_CHAN_PTRX,
1009 1.1 jdolecek (chan->fxsend.a.level << 8) | chan->fxsend.b.level);
1010 1.1 jdolecek emuxki_write(sc, chano, EMU_CHAN_DSL,
1011 1.1 jdolecek (chan->fxsend.d.level << 24) | chan->loop.end);
1012 1.1 jdolecek emuxki_write(sc, chano, EMU_CHAN_PSST,
1013 1.1 jdolecek (chan->fxsend.c.level << 24) | chan->loop.start);
1014 1.1 jdolecek emuxki_write(sc, chano, EMU_CHAN_CCCA,
1015 1.1 jdolecek (chan->filter.lowpass_resonance_height << 28) |
1016 1.1 jdolecek (chan->filter.interpolation_ROM << 25) |
1017 1.1 jdolecek (voice->b16 ? 0 : EMU_CHAN_CCCA_8BITSELECT) | start);
1018 1.1 jdolecek emuxki_write(sc, chano, EMU_CHAN_Z1, 0);
1019 1.1 jdolecek emuxki_write(sc, chano, EMU_CHAN_Z2, 0);
1020 1.1 jdolecek emuxki_write(sc, chano, EMU_CHAN_MAPA, mapval);
1021 1.1 jdolecek emuxki_write(sc, chano, EMU_CHAN_MAPB, mapval);
1022 1.1 jdolecek emuxki_write(sc, chano, EMU_CHAN_CVCF_CURRFILTER,
1023 1.1 jdolecek chan->filter.current_cutoff_frequency);
1024 1.1 jdolecek emuxki_write(sc, chano, EMU_CHAN_VTFT_FILTERTARGET,
1025 1.1 jdolecek chan->filter.target_cutoff_frequency);
1026 1.1 jdolecek emuxki_write(sc, chano, EMU_CHAN_ATKHLDM,
1027 1.1 jdolecek (chan->modulation.envelope.hold_time << 8) |
1028 1.1 jdolecek chan->modulation.envelope.attack_time);
1029 1.1 jdolecek emuxki_write(sc, chano, EMU_CHAN_DCYSUSM,
1030 1.1 jdolecek (chan->modulation.envelope.sustain_level << 8) |
1031 1.1 jdolecek chan->modulation.envelope.decay_time);
1032 1.1 jdolecek emuxki_write(sc, chano, EMU_CHAN_LFOVAL1,
1033 1.1 jdolecek chan->modulation.LFO_state);
1034 1.1 jdolecek emuxki_write(sc, chano, EMU_CHAN_LFOVAL2,
1035 1.1 jdolecek chan->vibrato_LFO.state);
1036 1.1 jdolecek emuxki_write(sc, chano, EMU_CHAN_FMMOD,
1037 1.1 jdolecek (chan->vibrato_LFO.modulation_depth << 8) |
1038 1.1 jdolecek chan->filter.LFO_modulation_depth);
1039 1.1 jdolecek emuxki_write(sc, chano, EMU_CHAN_TREMFRQ,
1040 1.1 jdolecek (chan->tremolo_depth << 8));
1041 1.1 jdolecek emuxki_write(sc, chano, EMU_CHAN_FM2FRQ2,
1042 1.1 jdolecek (chan->vibrato_LFO.vibrato_depth << 8) |
1043 1.1 jdolecek chan->vibrato_LFO.frequency);
1044 1.1 jdolecek emuxki_write(sc, chano, EMU_CHAN_ENVVAL,
1045 1.1 jdolecek chan->modulation.envelope.current_state);
1046 1.1 jdolecek emuxki_write(sc, chano, EMU_CHAN_ATKHLDV,
1047 1.1 jdolecek (chan->volume.envelope.hold_time << 8) |
1048 1.1 jdolecek chan->volume.envelope.attack_time);
1049 1.1 jdolecek emuxki_write(sc, chano, EMU_CHAN_ENVVOL,
1050 1.1 jdolecek chan->volume.envelope.current_state);
1051 1.1 jdolecek emuxki_write(sc, chano, EMU_CHAN_PEFE,
1052 1.1 jdolecek (chan->pitch.envelope_amount << 8) |
1053 1.1 jdolecek chan->filter.envelope_amount);
1054 1.1 jdolecek splx(s);
1055 1.1 jdolecek }
1056 1.1 jdolecek
1057 1.1 jdolecek static void
1058 1.1 jdolecek emuxki_channel_start(struct emuxki_channel *chan)
1059 1.1 jdolecek {
1060 1.1 jdolecek struct emuxki_voice *voice = chan->voice;
1061 1.1 jdolecek struct emuxki_softc *sc = voice->sc;
1062 1.1 jdolecek u_int8_t cache_sample, cache_invalid_size, chano = chan->num;
1063 1.1 jdolecek u_int32_t sample;
1064 1.1 jdolecek int s;
1065 1.1 jdolecek
1066 1.1 jdolecek cache_sample = voice->stereo ? 4 : 2;
1067 1.1 jdolecek sample = voice->b16 ? 0x00000000 : 0x80808080;
1068 1.1 jdolecek cache_invalid_size = (voice->stereo ? 28 : 30) * (voice->b16 + 1);
1069 1.1 jdolecek
1070 1.1 jdolecek s = splaudio();
1071 1.1 jdolecek while (cache_sample--) {
1072 1.1 jdolecek emuxki_write(sc, chano, EMU_CHAN_CD0 + cache_sample,
1073 1.1 jdolecek sample);
1074 1.1 jdolecek }
1075 1.1 jdolecek emuxki_write(sc, chano, EMU_CHAN_CCR_CACHEINVALIDSIZE, 0);
1076 1.1 jdolecek emuxki_write(sc, chano, EMU_CHAN_CCR_READADDRESS, 64);
1077 1.1 jdolecek emuxki_write(sc, chano, EMU_CHAN_CCR_CACHEINVALIDSIZE,
1078 1.1 jdolecek cache_invalid_size);
1079 1.1 jdolecek emuxki_write(sc, chano, EMU_CHAN_IFATN,
1080 1.1 jdolecek (chan->filter.target_cutoff_frequency << 8) |
1081 1.1 jdolecek chan->initial_attenuation);
1082 1.1 jdolecek emuxki_write(sc, chano, EMU_CHAN_VTFT_VOLUMETARGET,
1083 1.1 jdolecek chan->volume.target);
1084 1.1 jdolecek emuxki_write(sc, chano, EMU_CHAN_CVCF_CURRVOL,
1085 1.1 jdolecek chan->volume.current);
1086 1.1 jdolecek emuxki_write(sc, 0,
1087 1.1 jdolecek EMU_MKSUBREG(1, chano, EMU_SOLEL + (chano >> 5)),
1088 1.1 jdolecek 0); /* Clear stop on loop */
1089 1.1 jdolecek emuxki_write(sc, 0,
1090 1.1 jdolecek EMU_MKSUBREG(1, chano, EMU_CLIEL + (chano >> 5)),
1091 1.1 jdolecek 0); /* Clear loop interrupt */
1092 1.1 jdolecek emuxki_write(sc, chano, EMU_CHAN_DCYSUSV,
1093 1.1 jdolecek (chan->volume.envelope.sustain_level << 8) |
1094 1.1 jdolecek chan->volume.envelope.decay_time);
1095 1.1 jdolecek emuxki_write(sc, chano, EMU_CHAN_PTRX_PITCHTARGET,
1096 1.1 jdolecek chan->pitch.target);
1097 1.1 jdolecek emuxki_write(sc, chano, EMU_CHAN_CPF_PITCH,
1098 1.1 jdolecek chan->pitch.current);
1099 1.1 jdolecek emuxki_write(sc, chano, EMU_CHAN_IP, chan->pitch.intial);
1100 1.1 jdolecek
1101 1.1 jdolecek splx(s);
1102 1.1 jdolecek }
1103 1.1 jdolecek
1104 1.1 jdolecek static void
1105 1.1 jdolecek emuxki_channel_stop(struct emuxki_channel *chan)
1106 1.1 jdolecek {
1107 1.1 jdolecek int s;
1108 1.1 jdolecek u_int8_t chano = chan->num;
1109 1.1 jdolecek struct emuxki_softc *sc = chan->voice->sc;
1110 1.1 jdolecek
1111 1.1 jdolecek s = splaudio();
1112 1.1 jdolecek emuxki_write(sc, chano, EMU_CHAN_PTRX_PITCHTARGET, 0);
1113 1.1 jdolecek emuxki_write(sc, chano, EMU_CHAN_CPF_PITCH, 0);
1114 1.1 jdolecek emuxki_write(sc, chano, EMU_CHAN_IFATN_ATTENUATION, 0xff);
1115 1.1 jdolecek emuxki_write(sc, chano, EMU_CHAN_VTFT_VOLUMETARGET, 0);
1116 1.1 jdolecek emuxki_write(sc, chano, EMU_CHAN_CVCF_CURRVOL, 0);
1117 1.1 jdolecek emuxki_write(sc, chano, EMU_CHAN_IP, 0);
1118 1.1 jdolecek splx(s);
1119 1.1 jdolecek }
1120 1.1 jdolecek
1121 1.1 jdolecek /*
1122 1.1 jdolecek * Voices managment
1123 1.1 jdolecek * emuxki_voice_dataloc : use(play or rec) independant dataloc union helpers
1124 1.1 jdolecek * emuxki_voice_channel_* : play part of dataloc union helpers
1125 1.1 jdolecek * emuxki_voice_recsrc_* : rec part of dataloc union helpers
1126 1.1 jdolecek */
1127 1.1 jdolecek
1128 1.1 jdolecek /* Allocate channels for voice in case of play voice */
1129 1.1 jdolecek static int
1130 1.1 jdolecek emuxki_voice_channel_create(struct emuxki_voice *voice)
1131 1.1 jdolecek {
1132 1.1 jdolecek struct emuxki_channel **channel = voice->sc->channel;
1133 1.1 jdolecek u_int8_t i, stereo = voice->stereo;
1134 1.1 jdolecek int s;
1135 1.1 jdolecek
1136 1.1 jdolecek for (i = 0; i < EMU_NUMCHAN; i += stereo + 1) {
1137 1.1 jdolecek if ((stereo && (channel[i + 1] != NULL)) ||
1138 1.1 jdolecek (channel[i] != NULL)) /* Looking for free channels */
1139 1.1 jdolecek continue;
1140 1.1 jdolecek s = splaudio();
1141 1.1 jdolecek if (stereo) {
1142 1.1 jdolecek voice->dataloc.chan[1] =
1143 1.1 jdolecek emuxki_channel_new(voice, i + 1);
1144 1.1 jdolecek if (voice->dataloc.chan[1] == NULL) {
1145 1.1 jdolecek splx(s);
1146 1.1 jdolecek return (ENOMEM);
1147 1.1 jdolecek }
1148 1.1 jdolecek }
1149 1.1 jdolecek voice->dataloc.chan[0] = emuxki_channel_new(voice, i);
1150 1.1 jdolecek if (voice->dataloc.chan[0] == NULL) {
1151 1.1 jdolecek if (stereo) {
1152 1.1 jdolecek emuxki_channel_delete(voice->dataloc.chan[1]);
1153 1.1 jdolecek voice->dataloc.chan[1] = NULL;
1154 1.1 jdolecek }
1155 1.1 jdolecek splx(s);
1156 1.1 jdolecek return (ENOMEM);
1157 1.1 jdolecek }
1158 1.1 jdolecek splx(s);
1159 1.1 jdolecek return (0);
1160 1.1 jdolecek }
1161 1.1 jdolecek return (EAGAIN);
1162 1.1 jdolecek }
1163 1.1 jdolecek
1164 1.1 jdolecek /* When calling this function we assume no one can access the voice */
1165 1.1 jdolecek static void
1166 1.1 jdolecek emuxki_voice_channel_destroy(struct emuxki_voice *voice)
1167 1.1 jdolecek {
1168 1.1 jdolecek emuxki_channel_delete(voice->dataloc.chan[0]);
1169 1.1 jdolecek voice->dataloc.chan[0] = NULL;
1170 1.1 jdolecek if (voice->stereo)
1171 1.1 jdolecek emuxki_channel_delete(voice->dataloc.chan[1]);
1172 1.1 jdolecek voice->dataloc.chan[1] = NULL;
1173 1.1 jdolecek }
1174 1.1 jdolecek
1175 1.1 jdolecek /*
1176 1.1 jdolecek * Will come back when used in voice_dataloc_create
1177 1.1 jdolecek */
1178 1.1 jdolecek #if 0
1179 1.1 jdolecek static int
1180 1.1 jdolecek emuxki_recsrc_reserve(struct emuxki_voice *voice, emuxki_recsrc_t source)
1181 1.1 jdolecek {
1182 1.1 jdolecek if (voice->emu->recsrc[source] != NULL)
1183 1.1 jdolecek return (EBUSY);
1184 1.1 jdolecek voice->emu->recsrc[source] = voice;
1185 1.1 jdolecek return (0);
1186 1.1 jdolecek }
1187 1.1 jdolecek #endif
1188 1.1 jdolecek
1189 1.1 jdolecek /* When calling this function we assume the voice is stopped */
1190 1.1 jdolecek static void
1191 1.1 jdolecek emuxki_voice_recsrc_release(struct emuxki_softc *sc, emuxki_recsrc_t source)
1192 1.1 jdolecek {
1193 1.1 jdolecek sc->recsrc[source] = NULL;
1194 1.1 jdolecek }
1195 1.1 jdolecek
1196 1.1 jdolecek static int
1197 1.1 jdolecek emuxki_voice_dataloc_create(struct emuxki_voice *voice)
1198 1.1 jdolecek {
1199 1.1 jdolecek int error;
1200 1.1 jdolecek
1201 1.1 jdolecek if (voice->use & EMU_VOICE_USE_PLAY) {
1202 1.1 jdolecek if ((error = emuxki_voice_channel_create(voice)))
1203 1.1 jdolecek return (error);
1204 1.1 jdolecek } else {
1205 1.1 jdolecek /*
1206 1.1 jdolecek * Commented out because i don't know how to get the selected
1207 1.1 jdolecek * recording source
1208 1.1 jdolecek */
1209 1.1 jdolecek #if 0
1210 1.1 jdolecek if (emuxki_recsrc_reserve(voice, recsrc))
1211 1.1 jdolecek return (EBUSY);
1212 1.1 jdolecek printf("Which rec src do i have to create!!!\n");
1213 1.1 jdolecek #endif
1214 1.1 jdolecek return (EBUSY); /* just return an error, no real meaning */
1215 1.1 jdolecek }
1216 1.1 jdolecek return (0);
1217 1.1 jdolecek }
1218 1.1 jdolecek
1219 1.1 jdolecek static void
1220 1.1 jdolecek emuxki_voice_dataloc_destroy(struct emuxki_voice *voice)
1221 1.1 jdolecek {
1222 1.1 jdolecek if (voice->use & EMU_VOICE_USE_PLAY) {
1223 1.1 jdolecek if (voice->dataloc.chan[0] != NULL)
1224 1.1 jdolecek emuxki_voice_channel_destroy(voice);
1225 1.1 jdolecek } else {
1226 1.1 jdolecek if (voice->dataloc.source != EMU_RECSRC_NOTSET) {
1227 1.1 jdolecek emuxki_voice_recsrc_release(voice->sc,
1228 1.1 jdolecek voice->dataloc.source);
1229 1.1 jdolecek voice->dataloc.source = EMU_RECSRC_NOTSET;
1230 1.1 jdolecek }
1231 1.1 jdolecek }
1232 1.1 jdolecek }
1233 1.1 jdolecek
1234 1.1 jdolecek static struct emuxki_voice *
1235 1.1 jdolecek emuxki_voice_new(struct emuxki_softc *sc, u_int8_t use)
1236 1.1 jdolecek {
1237 1.1 jdolecek struct emuxki_voice *voice;
1238 1.1 jdolecek int s;
1239 1.1 jdolecek
1240 1.1 jdolecek if ((voice = malloc(sizeof(*voice), M_DEVBUF, M_WAITOK)) == NULL)
1241 1.1 jdolecek return (NULL);
1242 1.1 jdolecek voice->sc = sc;
1243 1.1 jdolecek voice->use = use;
1244 1.1 jdolecek voice->state = !EMU_VOICE_STATE_STARTED;
1245 1.1 jdolecek voice->stereo = EMU_VOICE_STEREO_NOTSET;
1246 1.1 jdolecek voice->b16 = 0;
1247 1.1 jdolecek voice->sample_rate = 0;
1248 1.1 jdolecek if (use & EMU_VOICE_USE_PLAY)
1249 1.1 jdolecek voice->dataloc.chan[0] = voice->dataloc.chan[0] = NULL;
1250 1.1 jdolecek else
1251 1.1 jdolecek voice->dataloc.source = EMU_RECSRC_NOTSET;
1252 1.1 jdolecek voice->buffer = NULL;
1253 1.1 jdolecek voice->blksize = 0;
1254 1.1 jdolecek voice->trigblk = 0;
1255 1.1 jdolecek voice->blkmod = 0;
1256 1.1 jdolecek voice->inth = NULL;
1257 1.1 jdolecek voice->inthparam = NULL;
1258 1.1 jdolecek
1259 1.1 jdolecek s = splaudio();
1260 1.1 jdolecek LIST_INSERT_HEAD((&sc->voices), voice, next);
1261 1.1 jdolecek splx(s);
1262 1.1 jdolecek
1263 1.1 jdolecek return (voice);
1264 1.1 jdolecek }
1265 1.1 jdolecek
1266 1.1 jdolecek static void
1267 1.1 jdolecek emuxki_voice_delete(struct emuxki_voice *voice)
1268 1.1 jdolecek {
1269 1.1 jdolecek int s;
1270 1.1 jdolecek
1271 1.1 jdolecek if (voice->state & EMU_VOICE_STATE_STARTED)
1272 1.1 jdolecek emuxki_voice_halt(voice);
1273 1.1 jdolecek
1274 1.1 jdolecek s = splaudio();
1275 1.1 jdolecek LIST_REMOVE(voice, next);
1276 1.1 jdolecek splx(s);
1277 1.1 jdolecek
1278 1.1 jdolecek emuxki_voice_dataloc_destroy(voice);
1279 1.1 jdolecek free(voice, M_DEVBUF);
1280 1.1 jdolecek }
1281 1.1 jdolecek
1282 1.1 jdolecek static int
1283 1.1 jdolecek emuxki_voice_set_stereo(struct emuxki_voice *voice, u_int8_t stereo)
1284 1.1 jdolecek {
1285 1.1 jdolecek int error;
1286 1.1 jdolecek struct emuxki_chanparms_fxsend fxsend;
1287 1.1 jdolecek
1288 1.1 jdolecek emuxki_voice_dataloc_destroy(voice);
1289 1.1 jdolecek voice->stereo = stereo;
1290 1.1 jdolecek if ((error = emuxki_voice_dataloc_create(voice)))
1291 1.1 jdolecek return (error);
1292 1.1 jdolecek if (voice->use & EMU_VOICE_USE_PLAY) {
1293 1.1 jdolecek fxsend.a.dest = 0x0;
1294 1.1 jdolecek fxsend.b.dest = 0x1;
1295 1.1 jdolecek fxsend.c.dest = 0x2;
1296 1.1 jdolecek fxsend.d.dest = 0x3;
1297 1.1 jdolecek if (voice->stereo) {
1298 1.1 jdolecek fxsend.a.level = fxsend.c.level = 0xff;
1299 1.1 jdolecek fxsend.b.level = fxsend.d.level = 0x00;
1300 1.1 jdolecek emuxki_channel_set_fxsend(voice->dataloc.chan[0],
1301 1.1 jdolecek &fxsend);
1302 1.1 jdolecek fxsend.a.level = fxsend.c.level = 0x00;
1303 1.1 jdolecek fxsend.b.level = fxsend.d.level = 0xff;
1304 1.1 jdolecek emuxki_channel_set_fxsend(voice->dataloc.chan[1],
1305 1.1 jdolecek &fxsend);
1306 1.1 jdolecek } /* No else : default is good for mono */
1307 1.1 jdolecek }
1308 1.1 jdolecek return (0);
1309 1.1 jdolecek }
1310 1.1 jdolecek
1311 1.1 jdolecek static int
1312 1.1 jdolecek emuxki_voice_set_srate(struct emuxki_voice *voice, u_int32_t srate)
1313 1.1 jdolecek {
1314 1.1 jdolecek if (voice->use & EMU_VOICE_USE_PLAY) {
1315 1.1 jdolecek if ((srate < 4000) || (srate > 48000))
1316 1.1 jdolecek return (EINVAL);
1317 1.1 jdolecek voice->sample_rate = srate;
1318 1.1 jdolecek emuxki_channel_set_srate(voice->dataloc.chan[0], srate);
1319 1.1 jdolecek if (voice->stereo)
1320 1.1 jdolecek emuxki_channel_set_srate(voice->dataloc.chan[1],
1321 1.1 jdolecek srate);
1322 1.1 jdolecek } else {
1323 1.1 jdolecek #ifdef EMUXKI_DEBUG
1324 1.1 jdolecek printf("Recording voice set_srate not implemented\n");
1325 1.1 jdolecek #endif
1326 1.1 jdolecek return (EINVAL);
1327 1.1 jdolecek }
1328 1.1 jdolecek return (0);
1329 1.1 jdolecek }
1330 1.1 jdolecek
1331 1.1 jdolecek static int
1332 1.1 jdolecek emuxki_voice_set_audioparms(struct emuxki_voice *voice, u_int8_t stereo,
1333 1.1 jdolecek u_int8_t b16, u_int32_t srate)
1334 1.1 jdolecek {
1335 1.1 jdolecek int error;
1336 1.1 jdolecek
1337 1.1 jdolecek /*
1338 1.1 jdolecek * Audio driver tried to set recording AND playing params even if
1339 1.1 jdolecek * device opened in play or record only mode ==>
1340 1.1 jdolecek * modified emuxki_set_params.
1341 1.1 jdolecek * Stays here for now just in case ...
1342 1.1 jdolecek */
1343 1.1 jdolecek if (voice == NULL) {
1344 1.1 jdolecek #ifdef EMUXKI_DEBUG
1345 1.1 jdolecek printf("warning: tried to set unallocated voice params !!\n");
1346 1.1 jdolecek #endif
1347 1.1 jdolecek return (0);
1348 1.1 jdolecek }
1349 1.1 jdolecek
1350 1.1 jdolecek if (voice->stereo == stereo && voice->b16 == b16 &&
1351 1.1 jdolecek voice->sample_rate == srate)
1352 1.1 jdolecek return (0);
1353 1.1 jdolecek
1354 1.1 jdolecek #ifdef EMUXKI_DEBUG
1355 1.1 jdolecek printf("Setting %s voice params : %s, %u bits, %u hz\n",
1356 1.1 jdolecek (voice->use & EMU_VOICE_USE_PLAY) ? "play" : "record",
1357 1.1 jdolecek stereo ? "stereo" : "mono", (b16 + 1) * 8, srate);
1358 1.1 jdolecek #endif
1359 1.1 jdolecek
1360 1.1 jdolecek if (voice->stereo != stereo) {
1361 1.1 jdolecek if ((error = emuxki_voice_set_stereo(voice, stereo)))
1362 1.1 jdolecek return (error);
1363 1.1 jdolecek }
1364 1.1 jdolecek voice->b16 = b16;
1365 1.1 jdolecek if (voice->sample_rate != srate)
1366 1.1 jdolecek emuxki_voice_set_srate(voice, srate);
1367 1.1 jdolecek return (0);
1368 1.1 jdolecek }
1369 1.1 jdolecek
1370 1.1 jdolecek /* voice audio parms (see just before) must be set prior to this */
1371 1.1 jdolecek static int
1372 1.1 jdolecek emuxki_voice_set_bufparms(struct emuxki_voice *voice, void *ptr,
1373 1.1 jdolecek u_int32_t bufsize, u_int16_t blksize)
1374 1.1 jdolecek {
1375 1.1 jdolecek struct emuxki_mem *mem;
1376 1.1 jdolecek struct emuxki_channel **chan;
1377 1.1 jdolecek u_int32_t start, end;
1378 1.1 jdolecek u_int8_t sample_size;
1379 1.1 jdolecek int error = EFAULT;
1380 1.1 jdolecek
1381 1.1 jdolecek LIST_FOREACH(mem, &voice->sc->mem, next) {
1382 1.1 jdolecek if (KERNADDR(mem->dmamem) != ptr)
1383 1.1 jdolecek continue;
1384 1.1 jdolecek
1385 1.1 jdolecek voice->buffer = mem;
1386 1.1 jdolecek sample_size = (voice->b16 + 1) * (voice->stereo + 1);
1387 1.1 jdolecek voice->blksize = blksize / sample_size;
1388 1.1 jdolecek voice->trigblk = 0; /* This shouldn't be needed */
1389 1.1 jdolecek voice->blkmod = bufsize / blksize;
1390 1.1 jdolecek if (bufsize % blksize) /* This should not happen */
1391 1.1 jdolecek voice->blkmod++;
1392 1.1 jdolecek error = 0;
1393 1.1 jdolecek
1394 1.1 jdolecek if (voice->use & EMU_VOICE_USE_PLAY) {
1395 1.1 jdolecek chan = voice->dataloc.chan;
1396 1.1 jdolecek start = mem->ptbidx << 12;
1397 1.1 jdolecek end = start + bufsize / sample_size;
1398 1.1 jdolecek emuxki_channel_set_bufparms(chan[0],
1399 1.1 jdolecek start, end);
1400 1.1 jdolecek if (voice->stereo)
1401 1.1 jdolecek emuxki_channel_set_bufparms(chan[1],
1402 1.1 jdolecek start, end);
1403 1.1 jdolecek voice->timerate = (u_int32_t) 48000 *
1404 1.1 jdolecek voice->blksize / voice->sample_rate;
1405 1.1 jdolecek if (voice->timerate < 5)
1406 1.1 jdolecek error = EINVAL;
1407 1.1 jdolecek } else {
1408 1.1 jdolecek #ifdef EMUXKI_DEBUG
1409 1.1 jdolecek printf("Rec voice set bufparms not implemented\n");
1410 1.1 jdolecek #endif
1411 1.1 jdolecek error = ENODEV;
1412 1.1 jdolecek }
1413 1.1 jdolecek
1414 1.1 jdolecek break;
1415 1.1 jdolecek }
1416 1.1 jdolecek
1417 1.1 jdolecek return (error);
1418 1.1 jdolecek }
1419 1.1 jdolecek
1420 1.1 jdolecek static void
1421 1.1 jdolecek emuxki_voice_commit_parms(struct emuxki_voice *voice)
1422 1.1 jdolecek {
1423 1.1 jdolecek if (voice->use & EMU_VOICE_USE_PLAY) {
1424 1.1 jdolecek emuxki_channel_commit_parms(voice->dataloc.chan[0]);
1425 1.1 jdolecek if (voice->stereo)
1426 1.1 jdolecek emuxki_channel_commit_parms(voice->dataloc.chan[1]);
1427 1.1 jdolecek }
1428 1.1 jdolecek }
1429 1.1 jdolecek
1430 1.1 jdolecek static u_int32_t
1431 1.1 jdolecek emuxki_voice_curaddr(struct emuxki_voice *voice)
1432 1.1 jdolecek {
1433 1.1 jdolecek if (voice->use & EMU_VOICE_USE_PLAY)
1434 1.1 jdolecek return (emuxki_read(voice->sc,
1435 1.1 jdolecek voice->dataloc.chan[0]->num,
1436 1.1 jdolecek EMU_CHAN_CCCA_CURRADDR) -
1437 1.1 jdolecek voice->dataloc.chan[0]->loop.start);
1438 1.1 jdolecek return (0);
1439 1.1 jdolecek }
1440 1.1 jdolecek
1441 1.1 jdolecek static void
1442 1.1 jdolecek emuxki_resched_timer(struct emuxki_softc *sc)
1443 1.1 jdolecek {
1444 1.1 jdolecek struct emuxki_voice *voice;
1445 1.1 jdolecek u_int16_t timerate = 1024;
1446 1.1 jdolecek u_int8_t active = 0;
1447 1.1 jdolecek int s;
1448 1.1 jdolecek
1449 1.1 jdolecek s = splaudio();
1450 1.1 jdolecek LIST_FOREACH(voice, &sc->voices, next) {
1451 1.1 jdolecek if ((voice->use & EMU_VOICE_USE_PLAY) == 0 ||
1452 1.1 jdolecek (voice->state & EMU_VOICE_STATE_STARTED) == 0)
1453 1.1 jdolecek continue;
1454 1.1 jdolecek active = 1;
1455 1.1 jdolecek if (voice->timerate < timerate)
1456 1.1 jdolecek timerate = voice->timerate;
1457 1.1 jdolecek }
1458 1.1 jdolecek
1459 1.1 jdolecek if (timerate & ~EMU_TIMER_RATE_MASK)
1460 1.1 jdolecek timerate = 0;
1461 1.1 jdolecek bus_space_write_4(sc->sc_iot, sc->sc_ioh, EMU_TIMER, timerate);
1462 1.1 jdolecek if (!active && (sc->timerstate & EMU_TIMER_STATE_ENABLED)) {
1463 1.1 jdolecek bus_space_write_4(sc->sc_iot, sc->sc_ioh, EMU_INTE,
1464 1.1 jdolecek bus_space_read_4(sc->sc_iot, sc->sc_ioh, EMU_INTE) &
1465 1.1 jdolecek ~EMU_INTE_INTERTIMERENB);
1466 1.1 jdolecek sc->timerstate &= ~EMU_TIMER_STATE_ENABLED;
1467 1.1 jdolecek } else if (active && !(sc->timerstate & EMU_TIMER_STATE_ENABLED)) {
1468 1.1 jdolecek bus_space_write_4(sc->sc_iot, sc->sc_ioh, EMU_INTE,
1469 1.1 jdolecek bus_space_read_4(sc->sc_iot, sc->sc_ioh, EMU_INTE) |
1470 1.1 jdolecek EMU_INTE_INTERTIMERENB);
1471 1.1 jdolecek sc->timerstate |= EMU_TIMER_STATE_ENABLED;
1472 1.1 jdolecek }
1473 1.1 jdolecek splx(s);
1474 1.1 jdolecek }
1475 1.1 jdolecek
1476 1.1 jdolecek static void
1477 1.1 jdolecek emuxki_voice_start(struct emuxki_voice *voice,
1478 1.1 jdolecek void (*inth) (void *), void *inthparam)
1479 1.1 jdolecek {
1480 1.1 jdolecek voice->inth = inth;
1481 1.1 jdolecek voice->inthparam = inthparam;
1482 1.1 jdolecek if (voice->use & EMU_VOICE_USE_PLAY) {
1483 1.1 jdolecek voice->trigblk = 1;
1484 1.1 jdolecek emuxki_channel_start(voice->dataloc.chan[0]);
1485 1.1 jdolecek if (voice->stereo)
1486 1.1 jdolecek emuxki_channel_start(voice->dataloc.chan[1]);
1487 1.1 jdolecek }
1488 1.1 jdolecek #ifdef EMUXKI_DEBUG
1489 1.1 jdolecek else
1490 1.1 jdolecek printf("Recording voice start not implemented\n");
1491 1.1 jdolecek #endif
1492 1.1 jdolecek voice->state |= EMU_VOICE_STATE_STARTED;
1493 1.1 jdolecek if (voice->use & EMU_VOICE_USE_PLAY)
1494 1.1 jdolecek emuxki_resched_timer(voice->sc);
1495 1.1 jdolecek }
1496 1.1 jdolecek
1497 1.1 jdolecek static void
1498 1.1 jdolecek emuxki_voice_halt(struct emuxki_voice *voice)
1499 1.1 jdolecek {
1500 1.1 jdolecek if (voice->use & EMU_VOICE_USE_PLAY) {
1501 1.1 jdolecek emuxki_channel_stop(voice->dataloc.chan[0]);
1502 1.1 jdolecek if (voice->stereo)
1503 1.1 jdolecek emuxki_channel_stop(voice->dataloc.chan[1]);
1504 1.1 jdolecek }
1505 1.1 jdolecek #ifdef EMUXKI_DEBUG
1506 1.1 jdolecek else
1507 1.1 jdolecek printf("Recording voice halt not implemented\n");
1508 1.1 jdolecek #endif
1509 1.1 jdolecek voice->state &= ~EMU_VOICE_STATE_STARTED;
1510 1.1 jdolecek if (voice->use & EMU_VOICE_USE_PLAY)
1511 1.1 jdolecek emuxki_resched_timer(voice->sc);
1512 1.1 jdolecek }
1513 1.1 jdolecek
1514 1.1 jdolecek /*
1515 1.1 jdolecek * The interrupt handler
1516 1.1 jdolecek */
1517 1.1 jdolecek static int
1518 1.1 jdolecek emuxki_intr(void *arg)
1519 1.1 jdolecek {
1520 1.1 jdolecek struct emuxki_softc *sc = arg;
1521 1.1 jdolecek u_int32_t ipr, curblk;
1522 1.1 jdolecek struct emuxki_voice *voice;
1523 1.1 jdolecek
1524 1.1 jdolecek while ((ipr = bus_space_read_4(sc->sc_iot, sc->sc_ioh, EMU_IPR))) {
1525 1.1 jdolecek if (ipr & EMU_IPR_INTERVALTIMER) {
1526 1.1 jdolecek LIST_FOREACH(voice, &sc->voices, next) {
1527 1.1 jdolecek if ((voice->use & EMU_VOICE_USE_PLAY)==0 ||
1528 1.1 jdolecek (voice->state &
1529 1.1 jdolecek EMU_VOICE_STATE_STARTED) == 0)
1530 1.1 jdolecek continue;
1531 1.1 jdolecek
1532 1.1 jdolecek curblk = emuxki_voice_curaddr(voice) /
1533 1.1 jdolecek voice->blksize;
1534 1.1 jdolecek if (curblk == voice->trigblk) {
1535 1.1 jdolecek voice->inth(voice->inthparam);
1536 1.1 jdolecek voice->trigblk++;
1537 1.1 jdolecek voice->trigblk %= voice->blkmod;
1538 1.1 jdolecek }
1539 1.1 jdolecek }
1540 1.1 jdolecek }
1541 1.1 jdolecek
1542 1.1 jdolecek /* Got interrupt */
1543 1.1 jdolecek bus_space_write_4(sc->sc_iot, sc->sc_ioh, EMU_IPR, ipr);
1544 1.1 jdolecek }
1545 1.1 jdolecek
1546 1.1 jdolecek return (0);
1547 1.1 jdolecek }
1548 1.1 jdolecek
1549 1.1 jdolecek
1550 1.1 jdolecek /*
1551 1.1 jdolecek * Audio Architecture callbacks
1552 1.1 jdolecek */
1553 1.1 jdolecek
1554 1.1 jdolecek static int
1555 1.1 jdolecek emuxki_open(void *addr, int flags)
1556 1.1 jdolecek {
1557 1.1 jdolecek struct emuxki_softc *sc = addr;
1558 1.1 jdolecek
1559 1.1 jdolecek #ifdef EMUXKI_DEBUG
1560 1.1 jdolecek printf("%s: emuxki_open called\n", sc->sc_dev.dv_xname);
1561 1.1 jdolecek #endif
1562 1.1 jdolecek
1563 1.1 jdolecek /*
1564 1.1 jdolecek * Multiple voice support would be added as soon as I find a way to
1565 1.1 jdolecek * trick the audio arch into supporting multiple voices.
1566 1.1 jdolecek * Or I might integrate a modified audio arch supporting
1567 1.1 jdolecek * multiple voices.
1568 1.1 jdolecek */
1569 1.1 jdolecek
1570 1.1 jdolecek /*
1571 1.1 jdolecek * I did this because i have problems identifying the selected
1572 1.1 jdolecek * recording source(s) which is necessary when setting recording
1573 1.1 jdolecek * params This will be adressed very soon
1574 1.1 jdolecek */
1575 1.1 jdolecek if (flags & AUOPEN_READ)
1576 1.1 jdolecek return (EOPNOTSUPP);
1577 1.1 jdolecek
1578 1.1 jdolecek if (flags & AUOPEN_WRITE) {
1579 1.1 jdolecek sc->pvoice = emuxki_voice_new(sc, EMU_VOICE_USE_PLAY);
1580 1.1 jdolecek if (sc->pvoice == NULL) {
1581 1.1 jdolecek if (flags & AUOPEN_READ)
1582 1.1 jdolecek emuxki_voice_delete(sc->rvoice);
1583 1.1 jdolecek return (EBUSY);
1584 1.1 jdolecek }
1585 1.1 jdolecek }
1586 1.1 jdolecek
1587 1.1 jdolecek return (0);
1588 1.1 jdolecek }
1589 1.1 jdolecek
1590 1.1 jdolecek static void
1591 1.1 jdolecek emuxki_close(void *addr)
1592 1.1 jdolecek {
1593 1.1 jdolecek struct emuxki_softc *sc = addr;
1594 1.1 jdolecek
1595 1.1 jdolecek #ifdef EMUXKI_DEBUG
1596 1.1 jdolecek printf("%s: emu10K1_close called\n", sc->sc_dev.dv_xname);
1597 1.1 jdolecek #endif
1598 1.1 jdolecek
1599 1.1 jdolecek /* No multiple voice support for now */
1600 1.1 jdolecek if (sc->rvoice != NULL)
1601 1.1 jdolecek emuxki_voice_delete(sc->rvoice);
1602 1.1 jdolecek sc->rvoice = NULL;
1603 1.1 jdolecek if (sc->pvoice != NULL)
1604 1.1 jdolecek emuxki_voice_delete(sc->pvoice);
1605 1.1 jdolecek sc->pvoice = NULL;
1606 1.1 jdolecek }
1607 1.1 jdolecek
1608 1.1 jdolecek static int
1609 1.1 jdolecek emuxki_query_encoding(void *addr, struct audio_encoding *fp)
1610 1.1 jdolecek {
1611 1.1 jdolecek #ifdef EMUXKI_DEBUG
1612 1.1 jdolecek struct emuxki_softc *sc = addr;
1613 1.1 jdolecek
1614 1.1 jdolecek printf("%s: emuxki_query_encoding called\n", sc->sc_dev.dv_xname);
1615 1.1 jdolecek #endif
1616 1.1 jdolecek
1617 1.1 jdolecek switch (fp->index) {
1618 1.1 jdolecek case 0:
1619 1.1 jdolecek strcpy(fp->name, AudioEulinear);
1620 1.1 jdolecek fp->encoding = AUDIO_ENCODING_ULINEAR;
1621 1.1 jdolecek fp->precision = 8;
1622 1.1 jdolecek fp->flags = 0;
1623 1.1 jdolecek break;
1624 1.1 jdolecek case 1:
1625 1.1 jdolecek strcpy(fp->name, AudioEmulaw);
1626 1.1 jdolecek fp->encoding = AUDIO_ENCODING_ULAW;
1627 1.1 jdolecek fp->precision = 8;
1628 1.1 jdolecek fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
1629 1.1 jdolecek break;
1630 1.1 jdolecek case 2:
1631 1.1 jdolecek strcpy(fp->name, AudioEalaw);
1632 1.1 jdolecek fp->encoding = AUDIO_ENCODING_ALAW;
1633 1.1 jdolecek fp->precision = 8;
1634 1.1 jdolecek fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
1635 1.1 jdolecek break;
1636 1.1 jdolecek case 3:
1637 1.1 jdolecek strcpy(fp->name, AudioEslinear);
1638 1.1 jdolecek fp->encoding = AUDIO_ENCODING_SLINEAR;
1639 1.1 jdolecek fp->precision = 8;
1640 1.1 jdolecek fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
1641 1.1 jdolecek break;
1642 1.1 jdolecek case 4:
1643 1.1 jdolecek strcpy(fp->name, AudioEslinear_le);
1644 1.1 jdolecek fp->encoding = AUDIO_ENCODING_SLINEAR_LE;
1645 1.1 jdolecek fp->precision = 16;
1646 1.1 jdolecek fp->flags = 0;
1647 1.1 jdolecek break;
1648 1.1 jdolecek case 5:
1649 1.1 jdolecek strcpy(fp->name, AudioEulinear_le);
1650 1.1 jdolecek fp->encoding = AUDIO_ENCODING_ULINEAR_LE;
1651 1.1 jdolecek fp->precision = 16;
1652 1.1 jdolecek fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
1653 1.1 jdolecek break;
1654 1.1 jdolecek case 6:
1655 1.1 jdolecek strcpy(fp->name, AudioEslinear_be);
1656 1.1 jdolecek fp->encoding = AUDIO_ENCODING_SLINEAR_BE;
1657 1.1 jdolecek fp->precision = 16;
1658 1.1 jdolecek fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
1659 1.1 jdolecek break;
1660 1.1 jdolecek case 7:
1661 1.1 jdolecek strcpy(fp->name, AudioEulinear_be);
1662 1.1 jdolecek fp->encoding = AUDIO_ENCODING_ULINEAR_BE;
1663 1.1 jdolecek fp->precision = 16;
1664 1.1 jdolecek fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
1665 1.1 jdolecek break;
1666 1.1 jdolecek default:
1667 1.1 jdolecek return (EINVAL);
1668 1.1 jdolecek }
1669 1.1 jdolecek return (0);
1670 1.1 jdolecek }
1671 1.1 jdolecek
1672 1.1 jdolecek static int
1673 1.1 jdolecek emuxki_set_vparms(struct emuxki_voice *voice, struct audio_params *p)
1674 1.1 jdolecek {
1675 1.1 jdolecek u_int8_t b16, mode;
1676 1.1 jdolecek
1677 1.1 jdolecek mode = (voice->use & EMU_VOICE_USE_PLAY) ?
1678 1.1 jdolecek AUMODE_PLAY : AUMODE_RECORD;
1679 1.1 jdolecek p->factor = 1;
1680 1.1 jdolecek p->sw_code = NULL;
1681 1.1 jdolecek if (p->channels != 1 && p->channels != 2)
1682 1.1 jdolecek return (EINVAL);/* Will change when streams come in use */
1683 1.1 jdolecek
1684 1.1 jdolecek switch (p->encoding) {
1685 1.1 jdolecek case AUDIO_ENCODING_ULAW:
1686 1.1 jdolecek if (mode == AUMODE_PLAY) {
1687 1.1 jdolecek p->factor = 2;
1688 1.1 jdolecek p->sw_code = mulaw_to_slinear16_le;
1689 1.1 jdolecek b16 = 1;
1690 1.1 jdolecek } else {
1691 1.1 jdolecek p->sw_code = ulinear8_to_mulaw;
1692 1.1 jdolecek b16 = 0;
1693 1.1 jdolecek }
1694 1.1 jdolecek break;
1695 1.1 jdolecek
1696 1.1 jdolecek case AUDIO_ENCODING_ALAW:
1697 1.1 jdolecek if (mode == AUMODE_PLAY) {
1698 1.1 jdolecek p->factor = 2;
1699 1.1 jdolecek p->sw_code = alaw_to_slinear16_le;
1700 1.1 jdolecek b16 = 1;
1701 1.1 jdolecek } else {
1702 1.1 jdolecek p->sw_code = ulinear8_to_alaw;
1703 1.1 jdolecek b16 = 0;
1704 1.1 jdolecek }
1705 1.1 jdolecek break;
1706 1.1 jdolecek
1707 1.1 jdolecek case AUDIO_ENCODING_SLINEAR_LE:
1708 1.1 jdolecek if (p->precision == 8)
1709 1.1 jdolecek p->sw_code = change_sign8;
1710 1.1 jdolecek b16 = (p->precision == 16);
1711 1.1 jdolecek break;
1712 1.1 jdolecek
1713 1.1 jdolecek case AUDIO_ENCODING_ULINEAR_LE:
1714 1.1 jdolecek if (p->precision == 16)
1715 1.1 jdolecek p->sw_code = change_sign16_le;
1716 1.1 jdolecek b16 = (p->precision == 16);
1717 1.1 jdolecek break;
1718 1.1 jdolecek
1719 1.1 jdolecek case AUDIO_ENCODING_SLINEAR_BE:
1720 1.1 jdolecek if (p->precision == 16)
1721 1.1 jdolecek p->sw_code = swap_bytes;
1722 1.1 jdolecek else
1723 1.1 jdolecek p->sw_code = change_sign8;
1724 1.1 jdolecek b16 = (p->precision == 16);
1725 1.1 jdolecek break;
1726 1.1 jdolecek
1727 1.1 jdolecek case AUDIO_ENCODING_ULINEAR_BE:
1728 1.1 jdolecek if (p->precision == 16) {
1729 1.1 jdolecek if (mode == AUMODE_PLAY)
1730 1.1 jdolecek p->sw_code = swap_bytes_change_sign16_le;
1731 1.1 jdolecek else
1732 1.1 jdolecek p->sw_code = change_sign16_swap_bytes_le;
1733 1.1 jdolecek }
1734 1.1 jdolecek b16 = (p->precision == 16);
1735 1.1 jdolecek break;
1736 1.1 jdolecek
1737 1.1 jdolecek default:
1738 1.1 jdolecek return (EINVAL);
1739 1.1 jdolecek }
1740 1.1 jdolecek
1741 1.1 jdolecek return (emuxki_voice_set_audioparms(voice, p->channels == 2,
1742 1.1 jdolecek b16, p->sample_rate));
1743 1.1 jdolecek }
1744 1.1 jdolecek
1745 1.1 jdolecek static int
1746 1.1 jdolecek emuxki_set_params(void *addr, int setmode, int usemode,
1747 1.1 jdolecek struct audio_params *play, struct audio_params *rec)
1748 1.1 jdolecek {
1749 1.1 jdolecek struct emuxki_softc *sc = addr;
1750 1.1 jdolecek int mode, error;
1751 1.1 jdolecek struct audio_params *p;
1752 1.1 jdolecek
1753 1.1 jdolecek for (mode = AUMODE_RECORD; mode != -1;
1754 1.1 jdolecek mode = mode == AUMODE_RECORD ? AUMODE_PLAY : -1) {
1755 1.1 jdolecek if ((usemode & setmode & mode) == 0)
1756 1.1 jdolecek continue;
1757 1.1 jdolecek
1758 1.1 jdolecek p = (mode == AUMODE_PLAY) ? play : rec;
1759 1.1 jdolecek
1760 1.1 jdolecek /* No multiple voice support for now */
1761 1.1 jdolecek if ((error = emuxki_set_vparms((mode == AUMODE_PLAY) ?
1762 1.1 jdolecek sc->pvoice : sc->rvoice, p)))
1763 1.1 jdolecek return (error);
1764 1.1 jdolecek }
1765 1.1 jdolecek
1766 1.1 jdolecek return (0);
1767 1.1 jdolecek }
1768 1.1 jdolecek
1769 1.1 jdolecek static int
1770 1.1 jdolecek emuxki_halt_output(void *addr)
1771 1.1 jdolecek {
1772 1.1 jdolecek struct emuxki_softc *sc = addr;
1773 1.1 jdolecek
1774 1.1 jdolecek /* No multiple voice support for now */
1775 1.1 jdolecek if (sc->pvoice == NULL)
1776 1.1 jdolecek return (ENXIO);
1777 1.1 jdolecek
1778 1.1 jdolecek emuxki_voice_halt(sc->pvoice);
1779 1.1 jdolecek return (0);
1780 1.1 jdolecek }
1781 1.1 jdolecek
1782 1.1 jdolecek static int
1783 1.1 jdolecek emuxki_halt_input(void *addr)
1784 1.1 jdolecek {
1785 1.1 jdolecek struct emuxki_softc *sc = addr;
1786 1.1 jdolecek
1787 1.1 jdolecek #ifdef EMUXKI_DEBUG
1788 1.1 jdolecek printf("%s: emuxki_halt_input called\n", sc->sc_dev.dv_xname);
1789 1.1 jdolecek #endif
1790 1.1 jdolecek
1791 1.1 jdolecek /* No multiple voice support for now */
1792 1.1 jdolecek if (sc->rvoice == NULL)
1793 1.1 jdolecek return (ENXIO);
1794 1.1 jdolecek emuxki_voice_halt(sc->rvoice);
1795 1.1 jdolecek return (0);
1796 1.1 jdolecek }
1797 1.1 jdolecek
1798 1.1 jdolecek static int
1799 1.1 jdolecek emuxki_getdev(void *addr, struct audio_device *dev)
1800 1.1 jdolecek {
1801 1.1 jdolecek strncpy(dev->name, "Creative EMU10k1", sizeof(dev->name));
1802 1.1 jdolecek strcpy(dev->version, "");
1803 1.1 jdolecek strncpy(dev->config, "emuxki", sizeof(dev->config));
1804 1.1 jdolecek
1805 1.1 jdolecek return (0);
1806 1.1 jdolecek }
1807 1.1 jdolecek
1808 1.1 jdolecek static int
1809 1.1 jdolecek emuxki_set_port(void *addr, mixer_ctrl_t *mctl)
1810 1.1 jdolecek {
1811 1.1 jdolecek struct emuxki_softc *sc = addr;
1812 1.1 jdolecek
1813 1.1 jdolecek return sc->codecif->vtbl->mixer_set_port(sc->codecif, mctl);
1814 1.1 jdolecek }
1815 1.1 jdolecek
1816 1.1 jdolecek static int
1817 1.1 jdolecek emuxki_get_port(void *addr, mixer_ctrl_t *mctl)
1818 1.1 jdolecek {
1819 1.1 jdolecek struct emuxki_softc *sc = addr;
1820 1.1 jdolecek
1821 1.1 jdolecek return sc->codecif->vtbl->mixer_get_port(sc->codecif, mctl);
1822 1.1 jdolecek }
1823 1.1 jdolecek
1824 1.1 jdolecek static int
1825 1.1 jdolecek emuxki_query_devinfo(void *addr, mixer_devinfo_t *minfo)
1826 1.1 jdolecek {
1827 1.1 jdolecek struct emuxki_softc *sc = addr;
1828 1.1 jdolecek
1829 1.1 jdolecek return sc->codecif->vtbl->query_devinfo(sc->codecif, minfo);
1830 1.1 jdolecek }
1831 1.1 jdolecek
1832 1.1 jdolecek static void *
1833 1.1 jdolecek emuxki_allocm(void *addr, int direction, size_t size, int type, int flags)
1834 1.1 jdolecek {
1835 1.1 jdolecek struct emuxki_softc *sc = addr;
1836 1.1 jdolecek
1837 1.1 jdolecek if (direction == AUMODE_PLAY)
1838 1.1 jdolecek return emuxki_pmem_alloc(sc, size, type, flags);
1839 1.1 jdolecek else
1840 1.1 jdolecek return emuxki_rmem_alloc(sc, size, type, flags);
1841 1.1 jdolecek }
1842 1.1 jdolecek
1843 1.1 jdolecek static void
1844 1.1 jdolecek emuxki_freem(void *addr, void *ptr, int type)
1845 1.1 jdolecek {
1846 1.1 jdolecek struct emuxki_softc *sc = addr;
1847 1.1 jdolecek int i, s;
1848 1.1 jdolecek struct emuxki_mem *mem;
1849 1.1 jdolecek size_t numblocks;
1850 1.1 jdolecek u_int32_t *ptb, silentpage;
1851 1.1 jdolecek
1852 1.1 jdolecek ptb = KERNADDR(sc->ptb);
1853 1.1 jdolecek silentpage = DMAADDR(sc->silentpage) << 1;
1854 1.1 jdolecek LIST_FOREACH(mem, &sc->mem, next) {
1855 1.1 jdolecek if (KERNADDR(mem->dmamem) != ptr)
1856 1.1 jdolecek continue;
1857 1.1 jdolecek
1858 1.1 jdolecek s = splaudio();
1859 1.1 jdolecek if (mem->ptbidx != EMU_RMEM) {
1860 1.1 jdolecek numblocks = DMASIZE(mem->dmamem) / EMU_PTESIZE;
1861 1.1 jdolecek if (DMASIZE(mem->dmamem) % EMU_PTESIZE)
1862 1.1 jdolecek numblocks++;
1863 1.1 jdolecek for (i = 0; i < numblocks; i++)
1864 1.1 jdolecek ptb[mem->ptbidx + i] =
1865 1.1 jdolecek silentpage | (mem->ptbidx + i);
1866 1.1 jdolecek }
1867 1.1 jdolecek LIST_REMOVE(mem, next);
1868 1.1 jdolecek splx(s);
1869 1.1 jdolecek
1870 1.1 jdolecek emuxki_mem_delete(mem, type);
1871 1.1 jdolecek break;
1872 1.1 jdolecek }
1873 1.1 jdolecek }
1874 1.1 jdolecek
1875 1.1 jdolecek static size_t
1876 1.1 jdolecek emuxki_round_buffersize(void *addr, int direction, size_t bsize)
1877 1.1 jdolecek {
1878 1.1 jdolecek static const int recbuf_sz[] = {
1879 1.1 jdolecek 0, 384, 448, 512, 640, 768, 896, 1024, 1280, 1536, 1792,
1880 1.1 jdolecek 2048, 2560, 3072, 3584, 4096, 5120, 6144, 7168, 8192, 10240,
1881 1.1 jdolecek 12288, 14366, 16384, 20480, 24576, 28672, 32768, 40960, 49152,
1882 1.1 jdolecek 57344, 65536
1883 1.1 jdolecek };
1884 1.1 jdolecek
1885 1.1 jdolecek if (direction == AUMODE_PLAY) {
1886 1.1 jdolecek if (bsize < EMU_PTESIZE)
1887 1.1 jdolecek bsize = EMU_PTESIZE;
1888 1.1 jdolecek else if (bsize > (EMU_PTESIZE * EMU_MAXPTE))
1889 1.1 jdolecek bsize = EMU_PTESIZE * EMU_MAXPTE;
1890 1.1 jdolecek /* Would be better if set to max available */
1891 1.1 jdolecek else if (bsize % EMU_PTESIZE)
1892 1.1 jdolecek bsize = bsize -
1893 1.1 jdolecek (bsize % EMU_PTESIZE) +
1894 1.1 jdolecek EMU_PTESIZE;
1895 1.1 jdolecek } else {
1896 1.1 jdolecek int idx;
1897 1.1 jdolecek
1898 1.1 jdolecek /* find nearest lower recbuf size */
1899 1.1 jdolecek for(idx=32; --idx >= 0; ) {
1900 1.1 jdolecek if (bsize >= recbuf_sz[idx]) {
1901 1.1 jdolecek bsize = recbuf_sz[idx];
1902 1.1 jdolecek break;
1903 1.1 jdolecek }
1904 1.1 jdolecek }
1905 1.1 jdolecek
1906 1.1 jdolecek if (bsize == 0)
1907 1.1 jdolecek bsize = 384;
1908 1.1 jdolecek }
1909 1.1 jdolecek
1910 1.1 jdolecek return (bsize);
1911 1.1 jdolecek }
1912 1.1 jdolecek
1913 1.1 jdolecek static paddr_t
1914 1.1 jdolecek emuxki_mappage(void *addr, void *ptr, off_t off, int prot)
1915 1.1 jdolecek {
1916 1.1 jdolecek struct emuxki_softc *sc = addr;
1917 1.1 jdolecek struct emuxki_mem *mem;
1918 1.1 jdolecek u_int32_t *ptb;
1919 1.1 jdolecek
1920 1.1 jdolecek ptb = KERNADDR(sc->ptb);
1921 1.1 jdolecek LIST_FOREACH(mem, &sc->mem, next) {
1922 1.1 jdolecek if (KERNADDR(mem->dmamem) == ptr) {
1923 1.1 jdolecek struct dmamem *dm = mem->dmamem;
1924 1.1 jdolecek
1925 1.1 jdolecek return bus_dmamem_mmap(dm->dmat, dm->segs, dm->nsegs,
1926 1.1 jdolecek off, prot, BUS_DMA_WAITOK);
1927 1.1 jdolecek }
1928 1.1 jdolecek }
1929 1.1 jdolecek
1930 1.1 jdolecek return (-1);
1931 1.1 jdolecek }
1932 1.1 jdolecek
1933 1.1 jdolecek static int
1934 1.1 jdolecek emuxki_get_props(void *addr)
1935 1.1 jdolecek {
1936 1.1 jdolecek return (AUDIO_PROP_MMAP | AUDIO_PROP_INDEPENDENT |
1937 1.1 jdolecek AUDIO_PROP_FULLDUPLEX);
1938 1.1 jdolecek }
1939 1.1 jdolecek
1940 1.1 jdolecek static int
1941 1.1 jdolecek emuxki_trigger_output(void *addr, void *start, void *end, int blksize,
1942 1.1 jdolecek void (*inth) (void *), void *inthparam,
1943 1.1 jdolecek struct audio_params *params)
1944 1.1 jdolecek {
1945 1.1 jdolecek struct emuxki_softc *sc = addr;
1946 1.1 jdolecek /* No multiple voice support for now */
1947 1.1 jdolecek struct emuxki_voice *voice = sc->pvoice;
1948 1.1 jdolecek int error;
1949 1.1 jdolecek
1950 1.1 jdolecek if (voice == NULL)
1951 1.1 jdolecek return (ENXIO);
1952 1.1 jdolecek if ((error = emuxki_set_vparms(voice, params)))
1953 1.1 jdolecek return (error);
1954 1.1 jdolecek if ((error = emuxki_voice_set_bufparms(voice, start,
1955 1.1 jdolecek (caddr_t)end - (caddr_t)start, blksize)))
1956 1.1 jdolecek return (error);
1957 1.1 jdolecek emuxki_voice_commit_parms(voice);
1958 1.1 jdolecek emuxki_voice_start(voice, inth, inthparam);
1959 1.1 jdolecek
1960 1.1 jdolecek return (0);
1961 1.1 jdolecek }
1962 1.1 jdolecek
1963 1.1 jdolecek static int
1964 1.1 jdolecek emuxki_trigger_input(void *addr, void *start, void *end, int blksize,
1965 1.1 jdolecek void (*inth) (void *), void *inthparam,
1966 1.1 jdolecek struct audio_params *params)
1967 1.1 jdolecek {
1968 1.1 jdolecek struct emuxki_softc *sc = addr;
1969 1.1 jdolecek /* No multiple voice support for now */
1970 1.1 jdolecek struct emuxki_voice *voice = sc->rvoice;
1971 1.1 jdolecek int error;
1972 1.1 jdolecek
1973 1.1 jdolecek if (voice == NULL)
1974 1.1 jdolecek return (ENXIO);
1975 1.1 jdolecek if ((error = emuxki_set_vparms(voice, params)))
1976 1.1 jdolecek return (error);
1977 1.1 jdolecek if ((error = emuxki_voice_set_bufparms(voice, start,
1978 1.1 jdolecek (caddr_t)end - (caddr_t)start,
1979 1.1 jdolecek blksize)))
1980 1.1 jdolecek return (error);
1981 1.1 jdolecek emuxki_voice_commit_parms(voice); /* Useless for record ? */
1982 1.1 jdolecek emuxki_voice_start(voice, inth, inthparam);
1983 1.1 jdolecek
1984 1.1 jdolecek return (0);
1985 1.1 jdolecek }
1986 1.1 jdolecek
1987 1.1 jdolecek
1988 1.1 jdolecek /*
1989 1.1 jdolecek * AC97 callbacks
1990 1.1 jdolecek */
1991 1.1 jdolecek
1992 1.1 jdolecek static int
1993 1.1 jdolecek emuxki_ac97_attach(void *arg, struct ac97_codec_if *codecif)
1994 1.1 jdolecek {
1995 1.1 jdolecek struct emuxki_softc *sc = arg;
1996 1.1 jdolecek
1997 1.1 jdolecek sc->codecif = codecif;
1998 1.1 jdolecek return (0);
1999 1.1 jdolecek }
2000 1.1 jdolecek
2001 1.1 jdolecek static int
2002 1.1 jdolecek emuxki_ac97_read(void *arg, u_int8_t reg, u_int16_t *val)
2003 1.1 jdolecek {
2004 1.1 jdolecek struct emuxki_softc *sc = arg;
2005 1.1 jdolecek int s;
2006 1.1 jdolecek
2007 1.1 jdolecek s = splaudio();
2008 1.1 jdolecek bus_space_write_1(sc->sc_iot, sc->sc_ioh, EMU_AC97ADDR, reg);
2009 1.1 jdolecek *val = bus_space_read_2(sc->sc_iot, sc->sc_ioh, EMU_AC97DATA);
2010 1.1 jdolecek splx(s);
2011 1.1 jdolecek
2012 1.1 jdolecek return (0);
2013 1.1 jdolecek }
2014 1.1 jdolecek
2015 1.1 jdolecek static int
2016 1.1 jdolecek emuxki_ac97_write(void *arg, u_int8_t reg, u_int16_t val)
2017 1.1 jdolecek {
2018 1.1 jdolecek struct emuxki_softc *sc = arg;
2019 1.1 jdolecek int s;
2020 1.1 jdolecek
2021 1.1 jdolecek s = splaudio();
2022 1.1 jdolecek bus_space_write_1(sc->sc_iot, sc->sc_ioh, EMU_AC97ADDR, reg);
2023 1.1 jdolecek bus_space_write_2(sc->sc_iot, sc->sc_ioh, EMU_AC97DATA, val);
2024 1.1 jdolecek splx(s);
2025 1.1 jdolecek
2026 1.1 jdolecek return (0);
2027 1.1 jdolecek }
2028 1.1 jdolecek
2029 1.1 jdolecek static void
2030 1.1 jdolecek emuxki_ac97_reset(void *arg)
2031 1.1 jdolecek {
2032 1.1 jdolecek }
2033