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