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