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