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