emuxki.c revision 1.77 1 1.77 riastrad /* $NetBSD: emuxki.c,v 1.77 2023/05/10 00:11:41 riastradh Exp $ */
2 1.1 jdolecek
3 1.1 jdolecek /*-
4 1.60 jmcneill * Copyright (c) 2001, 2007 The NetBSD Foundation, Inc.
5 1.1 jdolecek * All rights reserved.
6 1.1 jdolecek *
7 1.1 jdolecek * This code is derived from software contributed to The NetBSD Foundation
8 1.60 jmcneill * by Yannick Montulet, and by Andrew Doran.
9 1.1 jdolecek *
10 1.1 jdolecek * Redistribution and use in source and binary forms, with or without
11 1.1 jdolecek * modification, are permitted provided that the following conditions
12 1.1 jdolecek * are met:
13 1.1 jdolecek * 1. Redistributions of source code must retain the above copyright
14 1.1 jdolecek * notice, this list of conditions and the following disclaimer.
15 1.1 jdolecek * 2. Redistributions in binary form must reproduce the above copyright
16 1.1 jdolecek * notice, this list of conditions and the following disclaimer in the
17 1.1 jdolecek * documentation and/or other materials provided with the distribution.
18 1.1 jdolecek *
19 1.1 jdolecek * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 1.1 jdolecek * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 1.1 jdolecek * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 1.1 jdolecek * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 1.1 jdolecek * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 1.1 jdolecek * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 1.1 jdolecek * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 1.1 jdolecek * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 1.1 jdolecek * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 1.1 jdolecek * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 1.1 jdolecek * POSSIBILITY OF SUCH DAMAGE.
30 1.1 jdolecek */
31 1.1 jdolecek
32 1.1 jdolecek /*
33 1.68 isaki * EMU10K1 single voice driver
34 1.68 isaki * o. only 1 voice playback, 1 recording
35 1.68 isaki * o. only s16le 2ch 48k
36 1.68 isaki * This makes it simple to control buffers and interrupts
37 1.68 isaki * while satisfying playback and recording quality.
38 1.1 jdolecek */
39 1.4 lukem
40 1.4 lukem #include <sys/cdefs.h>
41 1.77 riastrad __KERNEL_RCSID(0, "$NetBSD: emuxki.c,v 1.77 2023/05/10 00:11:41 riastradh Exp $");
42 1.1 jdolecek
43 1.5 lukem #include <sys/param.h>
44 1.1 jdolecek #include <sys/device.h>
45 1.73 khorben #include <sys/module.h>
46 1.1 jdolecek #include <sys/errno.h>
47 1.1 jdolecek #include <sys/systm.h>
48 1.1 jdolecek #include <sys/audioio.h>
49 1.60 jmcneill #include <sys/mutex.h>
50 1.60 jmcneill #include <sys/kmem.h>
51 1.60 jmcneill #include <sys/malloc.h>
52 1.68 isaki #include <sys/fcntl.h>
53 1.60 jmcneill
54 1.68 isaki #include <sys/bus.h>
55 1.68 isaki #include <sys/intr.h>
56 1.68 isaki
57 1.1 jdolecek #include <dev/pci/emuxkireg.h>
58 1.75 khorben #include <dev/pci/emuxkivar.h>
59 1.76 khorben #include <dev/pci/emuxki_boards.h>
60 1.1 jdolecek
61 1.68 isaki /* #define EMUXKI_DEBUG 1 */
62 1.68 isaki #ifdef EMUXKI_DEBUG
63 1.68 isaki #define emudebug EMUXKI_DEBUG
64 1.68 isaki # define DPRINTF(fmt...) do { if (emudebug) printf(fmt); } while (0)
65 1.68 isaki # define DPRINTFN(n,fmt...) do { if (emudebug>=(n)) printf(fmt); } while (0)
66 1.68 isaki #else
67 1.68 isaki # define DPRINTF(fmt...) __nothing
68 1.68 isaki # define DPRINTFN(n,fmt...) __nothing
69 1.68 isaki #endif
70 1.68 isaki
71 1.68 isaki /*
72 1.68 isaki * PCI
73 1.68 isaki * Note: emuxki's page table entry uses only 31bit addressing.
74 1.68 isaki * (Maybe, later chip has 32bit mode, but it isn't used now.)
75 1.68 isaki */
76 1.1 jdolecek
77 1.68 isaki #define EMU_PCI_CBIO (0x10)
78 1.1 jdolecek
79 1.68 isaki /* blackmagic */
80 1.68 isaki #define X1(x) ((sc->sc_type & EMUXKI_AUDIGY) ? EMU_A_##x : EMU_##x)
81 1.68 isaki #define X2(x, y) ((sc->sc_type & EMUXKI_AUDIGY) \
82 1.68 isaki ? EMU_A_##x(EMU_A_##y) : EMU_##x(EMU_##y))
83 1.68 isaki #define EMU_A_DSP_FX EMU_DSP_FX
84 1.68 isaki #define EMU_A_DSP_IN_AC97 EMU_DSP_IN_AC97
85 1.1 jdolecek
86 1.68 isaki /* prototypes */
87 1.68 isaki static struct dmamem *dmamem_alloc(struct emuxki_softc *, size_t);
88 1.68 isaki static void dmamem_free(struct dmamem *);
89 1.68 isaki static void dmamem_sync(struct dmamem *, int);
90 1.68 isaki static uint8_t emuxki_readio_1(struct emuxki_softc *, int) __unused;
91 1.68 isaki static uint16_t emuxki_readio_2(struct emuxki_softc *, int);
92 1.68 isaki static uint32_t emuxki_readio_4(struct emuxki_softc *, int);
93 1.68 isaki static void emuxki_writeio_1(struct emuxki_softc *, int, uint8_t);
94 1.68 isaki static void emuxki_writeio_2(struct emuxki_softc *, int, uint16_t);
95 1.68 isaki static void emuxki_writeio_4(struct emuxki_softc *, int, uint32_t);
96 1.68 isaki static uint32_t emuxki_readptr(struct emuxki_softc *, int, int, int);
97 1.68 isaki static void emuxki_writeptr(struct emuxki_softc *, int, int, int, uint32_t);
98 1.68 isaki static uint32_t emuxki_read(struct emuxki_softc *, int, int);
99 1.68 isaki static void emuxki_write(struct emuxki_softc *, int, int, uint32_t);
100 1.68 isaki static int emuxki_match(device_t, cfdata_t, void *);
101 1.68 isaki static void emuxki_attach(device_t, device_t, void *);
102 1.68 isaki static int emuxki_detach(device_t, int);
103 1.68 isaki static int emuxki_init(struct emuxki_softc *);
104 1.68 isaki static void emuxki_dsp_addop(struct emuxki_softc *, uint16_t *, uint8_t,
105 1.68 isaki uint16_t, uint16_t, uint16_t, uint16_t);
106 1.68 isaki static void emuxki_initfx(struct emuxki_softc *);
107 1.68 isaki static void emuxki_play_start(struct emuxki_softc *, int, uint32_t,
108 1.68 isaki uint32_t);
109 1.68 isaki static void emuxki_play_stop(struct emuxki_softc *, int);
110 1.1 jdolecek
111 1.68 isaki static int emuxki_query_format(void *, audio_format_query_t *);
112 1.68 isaki static int emuxki_set_format(void *, int,
113 1.68 isaki const audio_params_t *, const audio_params_t *,
114 1.68 isaki audio_filter_reg_t *, audio_filter_reg_t *);
115 1.3 jdolecek static int emuxki_halt_output(void *);
116 1.3 jdolecek static int emuxki_halt_input(void *);
117 1.68 isaki static int emuxki_intr(void *);
118 1.3 jdolecek static int emuxki_getdev(void *, struct audio_device *);
119 1.3 jdolecek static int emuxki_set_port(void *, mixer_ctrl_t *);
120 1.3 jdolecek static int emuxki_get_port(void *, mixer_ctrl_t *);
121 1.3 jdolecek static int emuxki_query_devinfo(void *, mixer_devinfo_t *);
122 1.68 isaki static void *emuxki_allocm(void *, int, size_t);
123 1.60 jmcneill static void emuxki_freem(void *, void *, size_t);
124 1.68 isaki static int emuxki_round_blocksize(void *, int, int,
125 1.68 isaki const audio_params_t *);
126 1.68 isaki static size_t emuxki_round_buffersize(void *, int, size_t);
127 1.3 jdolecek static int emuxki_get_props(void *);
128 1.68 isaki static int emuxki_trigger_output(void *, void *, void *, int,
129 1.68 isaki void (*)(void *), void *, const audio_params_t *);
130 1.68 isaki static int emuxki_trigger_input(void *, void *, void *, int,
131 1.68 isaki void (*)(void *), void *, const audio_params_t *);
132 1.60 jmcneill static void emuxki_get_locks(void *, kmutex_t **, kmutex_t **);
133 1.1 jdolecek
134 1.68 isaki static int emuxki_ac97_init(struct emuxki_softc *);
135 1.40 kent static int emuxki_ac97_attach(void *, struct ac97_codec_if *);
136 1.40 kent static int emuxki_ac97_read(void *, uint8_t, uint16_t *);
137 1.40 kent static int emuxki_ac97_write(void *, uint8_t, uint16_t);
138 1.40 kent static int emuxki_ac97_reset(void *);
139 1.68 isaki static enum ac97_host_flags emuxki_ac97_flags(void *);
140 1.68 isaki
141 1.1 jdolecek
142 1.58 tsutsui CFATTACH_DECL_NEW(emuxki, sizeof(struct emuxki_softc),
143 1.12 thorpej emuxki_match, emuxki_attach, emuxki_detach, NULL);
144 1.1 jdolecek
145 1.38 yamt static const struct audio_hw_if emuxki_hw_if = {
146 1.68 isaki .query_format = emuxki_query_format,
147 1.68 isaki .set_format = emuxki_set_format,
148 1.67 isaki .round_blocksize = emuxki_round_blocksize,
149 1.67 isaki .halt_output = emuxki_halt_output,
150 1.67 isaki .halt_input = emuxki_halt_input,
151 1.67 isaki .getdev = emuxki_getdev,
152 1.67 isaki .set_port = emuxki_set_port,
153 1.67 isaki .get_port = emuxki_get_port,
154 1.67 isaki .query_devinfo = emuxki_query_devinfo,
155 1.67 isaki .allocm = emuxki_allocm,
156 1.67 isaki .freem = emuxki_freem,
157 1.67 isaki .round_buffersize = emuxki_round_buffersize,
158 1.67 isaki .get_props = emuxki_get_props,
159 1.67 isaki .trigger_output = emuxki_trigger_output,
160 1.67 isaki .trigger_input = emuxki_trigger_input,
161 1.67 isaki .get_locks = emuxki_get_locks,
162 1.1 jdolecek };
163 1.1 jdolecek
164 1.68 isaki static const struct audio_format emuxki_formats[] = {
165 1.68 isaki {
166 1.68 isaki .mode = AUMODE_PLAY | AUMODE_RECORD,
167 1.68 isaki .encoding = AUDIO_ENCODING_SLINEAR_LE,
168 1.68 isaki .validbits = 16,
169 1.68 isaki .precision = 16,
170 1.68 isaki .channels = 2,
171 1.68 isaki .channel_mask = AUFMT_STEREO,
172 1.68 isaki .frequency_type = 1,
173 1.68 isaki .frequency = { 48000 },
174 1.68 isaki }
175 1.39 kent };
176 1.68 isaki #define EMUXKI_NFORMATS __arraycount(emuxki_formats)
177 1.39 kent
178 1.1 jdolecek /*
179 1.68 isaki * dma memory
180 1.1 jdolecek */
181 1.1 jdolecek
182 1.68 isaki static struct dmamem *
183 1.68 isaki dmamem_alloc(struct emuxki_softc *sc, size_t size)
184 1.1 jdolecek {
185 1.68 isaki struct dmamem *mem;
186 1.40 kent
187 1.68 isaki KASSERT(!mutex_owned(&sc->sc_intr_lock));
188 1.1 jdolecek
189 1.1 jdolecek /* Allocate memory for structure */
190 1.65 chs mem = kmem_alloc(sizeof(*mem), KM_SLEEP);
191 1.68 isaki mem->dmat = sc->sc_dmat;
192 1.1 jdolecek mem->size = size;
193 1.68 isaki mem->align = EMU_DMA_ALIGN;
194 1.68 isaki mem->nsegs = EMU_DMA_NSEGS;
195 1.1 jdolecek mem->bound = 0;
196 1.1 jdolecek
197 1.60 jmcneill mem->segs = kmem_alloc(mem->nsegs * sizeof(*(mem->segs)), KM_SLEEP);
198 1.1 jdolecek
199 1.68 isaki if (bus_dmamem_alloc(mem->dmat, mem->size, mem->align, mem->bound,
200 1.68 isaki mem->segs, mem->nsegs, &mem->rsegs, BUS_DMA_WAITOK)) {
201 1.68 isaki device_printf(sc->sc_dev,
202 1.68 isaki "%s bus_dmamem_alloc failed\n", __func__);
203 1.68 isaki goto memfree;
204 1.68 isaki }
205 1.68 isaki
206 1.68 isaki if (bus_dmamem_map(mem->dmat, mem->segs, mem->nsegs, mem->size,
207 1.68 isaki &mem->kaddr, BUS_DMA_WAITOK | BUS_DMA_COHERENT)) {
208 1.68 isaki device_printf(sc->sc_dev,
209 1.68 isaki "%s bus_dmamem_map failed\n", __func__);
210 1.68 isaki goto free;
211 1.68 isaki }
212 1.68 isaki
213 1.68 isaki if (bus_dmamap_create(mem->dmat, mem->size, mem->nsegs, mem->size,
214 1.68 isaki mem->bound, BUS_DMA_WAITOK, &mem->map)) {
215 1.68 isaki device_printf(sc->sc_dev,
216 1.68 isaki "%s bus_dmamap_create failed\n", __func__);
217 1.68 isaki goto unmap;
218 1.68 isaki }
219 1.68 isaki
220 1.68 isaki if (bus_dmamap_load(mem->dmat, mem->map, mem->kaddr,
221 1.68 isaki mem->size, NULL, BUS_DMA_WAITOK)) {
222 1.68 isaki device_printf(sc->sc_dev,
223 1.68 isaki "%s bus_dmamap_load failed\n", __func__);
224 1.68 isaki goto destroy;
225 1.1 jdolecek }
226 1.1 jdolecek
227 1.40 kent return mem;
228 1.68 isaki
229 1.68 isaki destroy:
230 1.68 isaki bus_dmamap_destroy(mem->dmat, mem->map);
231 1.68 isaki unmap:
232 1.68 isaki bus_dmamem_unmap(mem->dmat, mem->kaddr, mem->size);
233 1.68 isaki free:
234 1.68 isaki bus_dmamem_free(mem->dmat, mem->segs, mem->nsegs);
235 1.68 isaki memfree:
236 1.68 isaki kmem_free(mem->segs, mem->nsegs * sizeof(*(mem->segs)));
237 1.68 isaki kmem_free(mem, sizeof(*mem));
238 1.68 isaki
239 1.68 isaki return NULL;
240 1.1 jdolecek }
241 1.1 jdolecek
242 1.1 jdolecek static void
243 1.60 jmcneill dmamem_free(struct dmamem *mem)
244 1.1 jdolecek {
245 1.40 kent
246 1.1 jdolecek bus_dmamap_unload(mem->dmat, mem->map);
247 1.1 jdolecek bus_dmamap_destroy(mem->dmat, mem->map);
248 1.1 jdolecek bus_dmamem_unmap(mem->dmat, mem->kaddr, mem->size);
249 1.1 jdolecek bus_dmamem_free(mem->dmat, mem->segs, mem->nsegs);
250 1.68 isaki
251 1.68 isaki kmem_free(mem->segs, mem->nsegs * sizeof(*(mem->segs)));
252 1.68 isaki kmem_free(mem, sizeof(*mem));
253 1.68 isaki }
254 1.68 isaki
255 1.68 isaki static void
256 1.68 isaki dmamem_sync(struct dmamem *mem, int ops)
257 1.68 isaki {
258 1.68 isaki
259 1.68 isaki bus_dmamap_sync(mem->dmat, mem->map, 0, mem->size, ops);
260 1.1 jdolecek }
261 1.1 jdolecek
262 1.1 jdolecek
263 1.1 jdolecek /*
264 1.68 isaki * I/O register access
265 1.1 jdolecek */
266 1.1 jdolecek
267 1.68 isaki static uint8_t
268 1.68 isaki emuxki_readio_1(struct emuxki_softc *sc, int addr)
269 1.68 isaki {
270 1.68 isaki
271 1.68 isaki return bus_space_read_1(sc->sc_iot, sc->sc_ioh, addr);
272 1.68 isaki }
273 1.68 isaki
274 1.68 isaki static void
275 1.68 isaki emuxki_writeio_1(struct emuxki_softc *sc, int addr, uint8_t data)
276 1.68 isaki {
277 1.68 isaki
278 1.68 isaki bus_space_write_1(sc->sc_iot, sc->sc_ioh, addr, data);
279 1.68 isaki }
280 1.68 isaki
281 1.68 isaki static uint16_t
282 1.68 isaki emuxki_readio_2(struct emuxki_softc *sc, int addr)
283 1.68 isaki {
284 1.68 isaki
285 1.68 isaki return bus_space_read_2(sc->sc_iot, sc->sc_ioh, addr);
286 1.68 isaki }
287 1.68 isaki
288 1.68 isaki static void
289 1.68 isaki emuxki_writeio_2(struct emuxki_softc *sc, int addr, uint16_t data)
290 1.68 isaki {
291 1.68 isaki
292 1.68 isaki bus_space_write_2(sc->sc_iot, sc->sc_ioh, addr, data);
293 1.68 isaki }
294 1.68 isaki
295 1.68 isaki static uint32_t
296 1.68 isaki emuxki_readio_4(struct emuxki_softc *sc, int addr)
297 1.68 isaki {
298 1.68 isaki
299 1.68 isaki return bus_space_read_4(sc->sc_iot, sc->sc_ioh, addr);
300 1.68 isaki }
301 1.68 isaki
302 1.1 jdolecek static void
303 1.68 isaki emuxki_writeio_4(struct emuxki_softc *sc, int addr, uint32_t data)
304 1.1 jdolecek {
305 1.40 kent
306 1.68 isaki bus_space_write_4(sc->sc_iot, sc->sc_ioh, addr, data);
307 1.1 jdolecek }
308 1.1 jdolecek
309 1.68 isaki static uint32_t
310 1.68 isaki emuxki_readptr(struct emuxki_softc *sc, int aptr, int dptr, int addr)
311 1.1 jdolecek {
312 1.68 isaki uint32_t data;
313 1.68 isaki
314 1.68 isaki mutex_spin_enter(&sc->sc_index_lock);
315 1.68 isaki emuxki_writeio_4(sc, aptr, addr);
316 1.68 isaki data = emuxki_readio_4(sc, dptr);
317 1.68 isaki mutex_spin_exit(&sc->sc_index_lock);
318 1.68 isaki return data;
319 1.68 isaki }
320 1.1 jdolecek
321 1.68 isaki static void
322 1.68 isaki emuxki_writeptr(struct emuxki_softc *sc, int aptr, int dptr, int addr,
323 1.68 isaki uint32_t data)
324 1.68 isaki {
325 1.1 jdolecek
326 1.68 isaki mutex_spin_enter(&sc->sc_index_lock);
327 1.68 isaki emuxki_writeio_4(sc, aptr, addr);
328 1.68 isaki emuxki_writeio_4(sc, dptr, data);
329 1.68 isaki mutex_spin_exit(&sc->sc_index_lock);
330 1.68 isaki }
331 1.1 jdolecek
332 1.68 isaki static uint32_t
333 1.68 isaki emuxki_read(struct emuxki_softc *sc, int ch, int addr)
334 1.68 isaki {
335 1.1 jdolecek
336 1.68 isaki /* Original HENTAI addressing is never supported. */
337 1.68 isaki KASSERT((addr & 0xff000000) == 0);
338 1.1 jdolecek
339 1.68 isaki return emuxki_readptr(sc, EMU_PTR, EMU_DATA, (addr << 16) + ch);
340 1.1 jdolecek }
341 1.1 jdolecek
342 1.68 isaki static void
343 1.68 isaki emuxki_write(struct emuxki_softc *sc, int ch, int addr, uint32_t data)
344 1.1 jdolecek {
345 1.68 isaki
346 1.68 isaki /* Original HENTAI addressing is never supported. */
347 1.68 isaki KASSERT((addr & 0xff000000) == 0);
348 1.68 isaki
349 1.68 isaki emuxki_writeptr(sc, EMU_PTR, EMU_DATA, (addr << 16) + ch, data);
350 1.1 jdolecek }
351 1.1 jdolecek
352 1.68 isaki /*
353 1.68 isaki * MD driver
354 1.68 isaki */
355 1.68 isaki
356 1.1 jdolecek static int
357 1.56 cegger emuxki_match(device_t parent, cfdata_t match, void *aux)
358 1.1 jdolecek {
359 1.40 kent struct pci_attach_args *pa;
360 1.76 khorben pcireg_t reg;
361 1.1 jdolecek
362 1.40 kent pa = aux;
363 1.35 christos
364 1.76 khorben reg = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_SUBSYS_ID_REG);
365 1.76 khorben if (emuxki_board_lookup(PCI_VENDOR(pa->pa_id),
366 1.76 khorben PCI_PRODUCT(pa->pa_id), reg,
367 1.76 khorben PCI_REVISION(pa->pa_class)) != NULL)
368 1.40 kent return 1;
369 1.76 khorben
370 1.76 khorben return 0;
371 1.1 jdolecek }
372 1.1 jdolecek
373 1.1 jdolecek static void
374 1.56 cegger emuxki_attach(device_t parent, device_t self, void *aux)
375 1.1 jdolecek {
376 1.40 kent struct emuxki_softc *sc;
377 1.40 kent struct pci_attach_args *pa;
378 1.76 khorben const struct emuxki_board *sb;
379 1.1 jdolecek pci_intr_handle_t ih;
380 1.40 kent const char *intrstr;
381 1.63 christos char intrbuf[PCI_INTRSTR_LEN];
382 1.68 isaki pcireg_t reg;
383 1.1 jdolecek
384 1.57 cegger sc = device_private(self);
385 1.58 tsutsui sc->sc_dev = self;
386 1.40 kent pa = aux;
387 1.15 thorpej
388 1.76 khorben reg = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_SUBSYS_ID_REG);
389 1.76 khorben sb = emuxki_board_lookup(PCI_VENDOR(pa->pa_id),
390 1.76 khorben PCI_PRODUCT(pa->pa_id), reg,
391 1.76 khorben PCI_REVISION(pa->pa_class));
392 1.76 khorben KASSERT(sb != NULL);
393 1.76 khorben
394 1.68 isaki pci_aprint_devinfo(pa, "Audio controller");
395 1.76 khorben aprint_normal_dev(self, "%s [%s]\n", sb->sb_name, sb->sb_board);
396 1.68 isaki DPRINTF("dmat=%p\n", (char *)pa->pa_dmat);
397 1.68 isaki
398 1.60 jmcneill mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_NONE);
399 1.61 mrg mutex_init(&sc->sc_intr_lock, MUTEX_DEFAULT, IPL_AUDIO);
400 1.61 mrg mutex_init(&sc->sc_index_lock, MUTEX_DEFAULT, IPL_AUDIO);
401 1.68 isaki
402 1.68 isaki sc->sc_pc = pa->pa_pc;
403 1.74 khorben
404 1.74 khorben /* EMU10K1 can only address 31 bits (2GB) */
405 1.74 khorben if (bus_dmatag_subregion(pa->pa_dmat, 0, ((uint32_t)1 << 31) - 1,
406 1.74 khorben &(sc->sc_dmat), BUS_DMA_NOWAIT) != 0) {
407 1.74 khorben aprint_error_dev(self,
408 1.74 khorben "WARNING: failed to restrict dma range,"
409 1.74 khorben " falling back to parent bus dma range\n");
410 1.74 khorben sc->sc_dmat = pa->pa_dmat;
411 1.74 khorben }
412 1.68 isaki
413 1.68 isaki reg = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG);
414 1.68 isaki reg |= PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MASTER_ENABLE |
415 1.68 isaki PCI_COMMAND_MEM_ENABLE;
416 1.68 isaki pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, reg);
417 1.60 jmcneill
418 1.1 jdolecek if (pci_mapreg_map(pa, EMU_PCI_CBIO, PCI_MAPREG_TYPE_IO, 0,
419 1.68 isaki &sc->sc_iot, &sc->sc_ioh, &sc->sc_iob, &sc->sc_ios)) {
420 1.15 thorpej aprint_error(": can't map iospace\n");
421 1.1 jdolecek return;
422 1.1 jdolecek }
423 1.62 drochner
424 1.1 jdolecek if (pci_intr_map(pa, &ih)) {
425 1.58 tsutsui aprint_error_dev(self, "couldn't map interrupt\n");
426 1.68 isaki goto unmap;
427 1.1 jdolecek }
428 1.1 jdolecek
429 1.63 christos intrstr = pci_intr_string(pa->pa_pc, ih, intrbuf, sizeof(intrbuf));
430 1.66 jdolecek sc->sc_ih = pci_intr_establish_xname(pa->pa_pc, ih, IPL_AUDIO,
431 1.66 jdolecek emuxki_intr, sc, device_xname(self));
432 1.1 jdolecek if (sc->sc_ih == NULL) {
433 1.58 tsutsui aprint_error_dev(self, "couldn't establish interrupt");
434 1.1 jdolecek if (intrstr != NULL)
435 1.59 njoly aprint_error(" at %s", intrstr);
436 1.59 njoly aprint_error("\n");
437 1.68 isaki goto unmap;
438 1.1 jdolecek }
439 1.58 tsutsui aprint_normal_dev(self, "interrupting at %s\n", intrstr);
440 1.35 christos
441 1.66 jdolecek /* XXX it's unknown whether APS is made from Audigy as well */
442 1.76 khorben sc->sc_type = sb->sb_flags;
443 1.76 khorben if (sc->sc_type & EMUXKI_AUDIGY2_CA0108) {
444 1.76 khorben strlcpy(sc->sc_audv.name, "Audigy2+CA0108",
445 1.72 khorben sizeof(sc->sc_audv.name));
446 1.76 khorben } else if (sc->sc_type & EMUXKI_AUDIGY2) {
447 1.76 khorben strlcpy(sc->sc_audv.name, "Audigy2", sizeof(sc->sc_audv.name));
448 1.76 khorben } else if (sc->sc_type & EMUXKI_AUDIGY) {
449 1.76 khorben strlcpy(sc->sc_audv.name, "Audigy", sizeof(sc->sc_audv.name));
450 1.76 khorben } else if (sc->sc_type & EMUXKI_APS) {
451 1.68 isaki strlcpy(sc->sc_audv.name, "E-mu APS", sizeof(sc->sc_audv.name));
452 1.40 kent } else {
453 1.68 isaki strlcpy(sc->sc_audv.name, "SB Live!", sizeof(sc->sc_audv.name));
454 1.40 kent }
455 1.68 isaki snprintf(sc->sc_audv.version, sizeof(sc->sc_audv.version), "0x%02x",
456 1.68 isaki PCI_REVISION(pa->pa_class));
457 1.68 isaki strlcpy(sc->sc_audv.config, "emuxki", sizeof(sc->sc_audv.config));
458 1.68 isaki
459 1.68 isaki if (emuxki_init(sc)) {
460 1.68 isaki aprint_error("emuxki_init error\n");
461 1.68 isaki goto intrdis;
462 1.68 isaki }
463 1.68 isaki if (emuxki_ac97_init(sc)) {
464 1.68 isaki aprint_error("emuxki_ac97_init error\n");
465 1.68 isaki goto intrdis;
466 1.68 isaki }
467 1.68 isaki
468 1.68 isaki sc->sc_audev = audio_attach_mi(&emuxki_hw_if, sc, self);
469 1.68 isaki if (sc->sc_audev == NULL) {
470 1.68 isaki aprint_error("audio_attach_mi error\n");
471 1.68 isaki goto intrdis;
472 1.19 toshii }
473 1.68 isaki
474 1.68 isaki return;
475 1.68 isaki
476 1.68 isaki intrdis:
477 1.68 isaki pci_intr_disestablish(sc->sc_pc, sc->sc_ih);
478 1.68 isaki unmap:
479 1.68 isaki bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_ios);
480 1.68 isaki return;
481 1.1 jdolecek }
482 1.1 jdolecek
483 1.1 jdolecek static int
484 1.56 cegger emuxki_detach(device_t self, int flags)
485 1.1 jdolecek {
486 1.77 riastrad struct emuxki_softc *sc = device_private(self);
487 1.77 riastrad int error;
488 1.1 jdolecek
489 1.77 riastrad error = config_detach_children(self, flags);
490 1.77 riastrad if (error)
491 1.77 riastrad return error;
492 1.1 jdolecek
493 1.1 jdolecek /* All voices should be stopped now but add some code here if not */
494 1.68 isaki emuxki_writeio_4(sc, EMU_HCFG,
495 1.68 isaki EMU_HCFG_LOCKSOUNDCACHE |
496 1.68 isaki EMU_HCFG_LOCKTANKCACHE_MASK |
497 1.68 isaki EMU_HCFG_MUTEBUTTONENABLE);
498 1.68 isaki emuxki_writeio_4(sc, EMU_INTE, 0);
499 1.68 isaki
500 1.68 isaki /* Disable any Channels interrupts */
501 1.68 isaki emuxki_write(sc, 0, EMU_CLIEL, 0);
502 1.68 isaki emuxki_write(sc, 0, EMU_CLIEH, 0);
503 1.68 isaki emuxki_write(sc, 0, EMU_SOLEL, 0);
504 1.68 isaki emuxki_write(sc, 0, EMU_SOLEH, 0);
505 1.68 isaki
506 1.68 isaki /* stop DSP */
507 1.68 isaki emuxki_write(sc, 0, X1(DBG), X1(DBG_SINGLE_STEP));
508 1.1 jdolecek
509 1.68 isaki dmamem_free(sc->ptb);
510 1.1 jdolecek
511 1.68 isaki pci_intr_disestablish(sc->sc_pc, sc->sc_ih);
512 1.68 isaki bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_ios);
513 1.1 jdolecek
514 1.60 jmcneill mutex_destroy(&sc->sc_lock);
515 1.60 jmcneill mutex_destroy(&sc->sc_intr_lock);
516 1.60 jmcneill mutex_destroy(&sc->sc_index_lock);
517 1.60 jmcneill
518 1.40 kent return 0;
519 1.1 jdolecek }
520 1.1 jdolecek
521 1.1 jdolecek static int
522 1.1 jdolecek emuxki_init(struct emuxki_softc *sc)
523 1.1 jdolecek {
524 1.68 isaki int i;
525 1.68 isaki uint32_t spcs;
526 1.68 isaki uint32_t hcfg;
527 1.68 isaki
528 1.68 isaki /* clear AUDIO bit */
529 1.68 isaki emuxki_writeio_4(sc, EMU_HCFG,
530 1.68 isaki EMU_HCFG_LOCKSOUNDCACHE |
531 1.68 isaki EMU_HCFG_LOCKTANKCACHE_MASK |
532 1.68 isaki EMU_HCFG_MUTEBUTTONENABLE);
533 1.68 isaki
534 1.68 isaki /* mask interrupt without PCIERR */
535 1.68 isaki emuxki_writeio_4(sc, EMU_INTE,
536 1.68 isaki EMU_INTE_SAMPLERATER | /* always on this bit */
537 1.68 isaki EMU_INTE_PCIERRENABLE);
538 1.1 jdolecek
539 1.68 isaki /* disable all channel interrupt */
540 1.1 jdolecek emuxki_write(sc, 0, EMU_CLIEL, 0);
541 1.1 jdolecek emuxki_write(sc, 0, EMU_CLIEH, 0);
542 1.1 jdolecek emuxki_write(sc, 0, EMU_SOLEL, 0);
543 1.1 jdolecek emuxki_write(sc, 0, EMU_SOLEH, 0);
544 1.1 jdolecek
545 1.1 jdolecek /* Set recording buffers sizes to zero */
546 1.1 jdolecek emuxki_write(sc, 0, EMU_MICBS, EMU_RECBS_BUFSIZE_NONE);
547 1.1 jdolecek emuxki_write(sc, 0, EMU_MICBA, 0);
548 1.1 jdolecek emuxki_write(sc, 0, EMU_FXBS, EMU_RECBS_BUFSIZE_NONE);
549 1.1 jdolecek emuxki_write(sc, 0, EMU_FXBA, 0);
550 1.1 jdolecek emuxki_write(sc, 0, EMU_ADCBS, EMU_RECBS_BUFSIZE_NONE);
551 1.1 jdolecek emuxki_write(sc, 0, EMU_ADCBA, 0);
552 1.1 jdolecek
553 1.40 kent if(sc->sc_type & EMUXKI_AUDIGY) {
554 1.40 kent emuxki_write(sc, 0, EMU_SPBYPASS, EMU_SPBYPASS_24_BITS);
555 1.68 isaki emuxki_write(sc, 0, EMU_AC97SLOT,
556 1.68 isaki EMU_AC97SLOT_CENTER | EMU_AC97SLOT_LFE);
557 1.40 kent }
558 1.35 christos
559 1.1 jdolecek /* Initialize all channels to stopped and no effects */
560 1.1 jdolecek for (i = 0; i < EMU_NUMCHAN; i++) {
561 1.68 isaki emuxki_write(sc, i, EMU_CHAN_DCYSUSV, 0x7f7f);
562 1.68 isaki emuxki_write(sc, i, EMU_CHAN_IP, EMU_CHAN_IP_UNITY);
563 1.1 jdolecek emuxki_write(sc, i, EMU_CHAN_VTFT, 0xffff);
564 1.1 jdolecek emuxki_write(sc, i, EMU_CHAN_CVCF, 0xffff);
565 1.1 jdolecek emuxki_write(sc, i, EMU_CHAN_PTRX, 0);
566 1.1 jdolecek emuxki_write(sc, i, EMU_CHAN_CPF, 0);
567 1.1 jdolecek emuxki_write(sc, i, EMU_CHAN_CCR, 0);
568 1.1 jdolecek emuxki_write(sc, i, EMU_CHAN_PSST, 0);
569 1.68 isaki emuxki_write(sc, i, EMU_CHAN_DSL, 0);
570 1.68 isaki emuxki_write(sc, i, EMU_CHAN_CCCA, EMU_CHAN_CCCA_INTERPROM_1);
571 1.1 jdolecek emuxki_write(sc, i, EMU_CHAN_Z1, 0);
572 1.1 jdolecek emuxki_write(sc, i, EMU_CHAN_Z2, 0);
573 1.68 isaki emuxki_write(sc, i, EMU_CHAN_MAPA, 0xffffffff);
574 1.68 isaki emuxki_write(sc, i, EMU_CHAN_MAPB, 0xffffffff);
575 1.1 jdolecek emuxki_write(sc, i, EMU_CHAN_FXRT, 0x32100000);
576 1.1 jdolecek emuxki_write(sc, i, EMU_CHAN_ATKHLDM, 0);
577 1.1 jdolecek emuxki_write(sc, i, EMU_CHAN_DCYSUSM, 0);
578 1.1 jdolecek emuxki_write(sc, i, EMU_CHAN_IFATN, 0xffff);
579 1.68 isaki emuxki_write(sc, i, EMU_CHAN_PEFE, 0x007f);
580 1.1 jdolecek emuxki_write(sc, i, EMU_CHAN_FMMOD, 0);
581 1.68 isaki emuxki_write(sc, i, EMU_CHAN_TREMFRQ, 0);
582 1.68 isaki emuxki_write(sc, i, EMU_CHAN_FM2FRQ2, 0);
583 1.1 jdolecek emuxki_write(sc, i, EMU_CHAN_TEMPENV, 0);
584 1.1 jdolecek
585 1.1 jdolecek /* these are last so OFF prevents writing */
586 1.68 isaki emuxki_write(sc, i, EMU_CHAN_LFOVAL2, 0x8000);
587 1.68 isaki emuxki_write(sc, i, EMU_CHAN_LFOVAL1, 0x8000);
588 1.68 isaki emuxki_write(sc, i, EMU_CHAN_ATKHLDV, 0x7f7f);
589 1.1 jdolecek emuxki_write(sc, i, EMU_CHAN_ENVVOL, 0);
590 1.68 isaki emuxki_write(sc, i, EMU_CHAN_ENVVAL, 0x8000);
591 1.1 jdolecek }
592 1.1 jdolecek
593 1.1 jdolecek /* set digital outputs format */
594 1.68 isaki spcs = EMU_SPCS_CLKACCY_1000PPM |
595 1.68 isaki EMU_SPCS_SAMPLERATE_48 |
596 1.68 isaki EMU_SPCS_CHANNELNUM_LEFT |
597 1.68 isaki EMU_SPCS_SOURCENUM_UNSPEC |
598 1.68 isaki EMU_SPCS_GENERATIONSTATUS |
599 1.68 isaki 0x00001200 /* Cat code. */ |
600 1.68 isaki 0x00000000 /* IEC-958 Mode */ |
601 1.68 isaki EMU_SPCS_EMPHASIS_NONE |
602 1.68 isaki EMU_SPCS_COPYRIGHT;
603 1.1 jdolecek emuxki_write(sc, 0, EMU_SPCS0, spcs);
604 1.1 jdolecek emuxki_write(sc, 0, EMU_SPCS1, spcs);
605 1.1 jdolecek emuxki_write(sc, 0, EMU_SPCS2, spcs);
606 1.1 jdolecek
607 1.76 khorben if (sc->sc_type & EMUXKI_AUDIGY2_CA0108) {
608 1.72 khorben /* Setup SRCMulti_I2S SamplingRate */
609 1.72 khorben emuxki_write(sc, 0, EMU_A2_SPDIF_SAMPLERATE,
610 1.72 khorben emuxki_read(sc, 0, EMU_A2_SPDIF_SAMPLERATE) & 0xfffff1ff);
611 1.72 khorben
612 1.72 khorben /* Setup SRCSel (Enable SPDIF, I2S SRCMulti) */
613 1.72 khorben emuxki_writeptr(sc, EMU_A2_PTR, EMU_A2_DATA, EMU_A2_SRCSEL,
614 1.72 khorben EMU_A2_SRCSEL_ENABLE_SPDIF | EMU_A2_SRCSEL_ENABLE_SRCMULTI);
615 1.72 khorben
616 1.72 khorben /* Setup SRCMulti Input Audio Enable */
617 1.72 khorben emuxki_writeptr(sc, EMU_A2_PTR, EMU_A2_DATA,
618 1.72 khorben 0x7b0000, 0xff000000);
619 1.72 khorben
620 1.72 khorben /* Setup SPDIF Out Audio Enable
621 1.72 khorben * The Audigy 2 Value has a separate SPDIF out,
622 1.72 khorben * so no need for a mixer switch */
623 1.72 khorben emuxki_writeptr(sc, EMU_A2_PTR, EMU_A2_DATA,
624 1.72 khorben 0x7a0000, 0xff000000);
625 1.72 khorben emuxki_writeio_4(sc, EMU_A_IOCFG,
626 1.72 khorben emuxki_readio_4(sc, EMU_A_IOCFG) & ~0x8); /* clear bit 3 */
627 1.72 khorben } else if (sc->sc_type & EMUXKI_AUDIGY2) {
628 1.68 isaki emuxki_write(sc, 0, EMU_A2_SPDIF_SAMPLERATE,
629 1.68 isaki EMU_A2_SPDIF_UNKNOWN);
630 1.35 christos
631 1.68 isaki emuxki_writeptr(sc, EMU_A2_PTR, EMU_A2_DATA, EMU_A2_SRCSEL,
632 1.68 isaki EMU_A2_SRCSEL_ENABLE_SPDIF | EMU_A2_SRCSEL_ENABLE_SRCMULTI);
633 1.40 kent
634 1.68 isaki emuxki_writeptr(sc, EMU_A2_PTR, EMU_A2_DATA, EMU_A2_SRCMULTI,
635 1.68 isaki EMU_A2_SRCMULTI_ENABLE_INPUT);
636 1.40 kent }
637 1.35 christos
638 1.68 isaki /* page table */
639 1.68 isaki sc->ptb = dmamem_alloc(sc, EMU_MAXPTE * sizeof(uint32_t));
640 1.68 isaki if (sc->ptb == NULL) {
641 1.68 isaki device_printf(sc->sc_dev, "ptb allocation error\n");
642 1.68 isaki return ENOMEM;
643 1.68 isaki }
644 1.68 isaki emuxki_write(sc, 0, EMU_PTB, DMAADDR(sc->ptb));
645 1.68 isaki
646 1.68 isaki emuxki_write(sc, 0, EMU_TCBS, 0); /* This means 16K TCB */
647 1.68 isaki emuxki_write(sc, 0, EMU_TCB, 0); /* No TCB use for now */
648 1.35 christos
649 1.1 jdolecek /* Let's play with sound processor */
650 1.1 jdolecek emuxki_initfx(sc);
651 1.1 jdolecek
652 1.68 isaki /* enable interrupt */
653 1.68 isaki emuxki_writeio_4(sc, EMU_INTE,
654 1.68 isaki emuxki_readio_4(sc, EMU_INTE) |
655 1.68 isaki EMU_INTE_VOLINCRENABLE |
656 1.68 isaki EMU_INTE_VOLDECRENABLE |
657 1.68 isaki EMU_INTE_MUTEENABLE);
658 1.1 jdolecek
659 1.76 khorben if (sc->sc_type & EMUXKI_AUDIGY2_CA0108) {
660 1.72 khorben emuxki_writeio_4(sc, EMU_A_IOCFG,
661 1.72 khorben 0x0060 | emuxki_readio_4(sc, EMU_A_IOCFG));
662 1.72 khorben } else if (sc->sc_type & EMUXKI_AUDIGY2) {
663 1.68 isaki emuxki_writeio_4(sc, EMU_A_IOCFG,
664 1.72 khorben EMU_A_IOCFG_GPOUT0 | emuxki_readio_4(sc, EMU_A_IOCFG));
665 1.1 jdolecek }
666 1.1 jdolecek
667 1.68 isaki /* enable AUDIO bit */
668 1.68 isaki hcfg = EMU_HCFG_AUDIOENABLE | EMU_HCFG_AUTOMUTE;
669 1.1 jdolecek
670 1.68 isaki if (sc->sc_type & EMUXKI_AUDIGY2) {
671 1.68 isaki hcfg |= EMU_HCFG_AC3ENABLE_CDSPDIF |
672 1.68 isaki EMU_HCFG_AC3ENABLE_GPSPDIF;
673 1.68 isaki } else if (sc->sc_type & EMUXKI_AUDIGY) {
674 1.68 isaki } else {
675 1.68 isaki hcfg |= EMU_HCFG_LOCKTANKCACHE_MASK;
676 1.1 jdolecek }
677 1.68 isaki /* joystick not supported now */
678 1.68 isaki emuxki_writeio_4(sc, EMU_HCFG, hcfg);
679 1.1 jdolecek
680 1.40 kent return 0;
681 1.1 jdolecek }
682 1.1 jdolecek
683 1.68 isaki /*
684 1.68 isaki * dsp programming
685 1.68 isaki */
686 1.68 isaki
687 1.1 jdolecek static void
688 1.68 isaki emuxki_dsp_addop(struct emuxki_softc *sc, uint16_t *pc, uint8_t op,
689 1.68 isaki uint16_t r, uint16_t a, uint16_t x, uint16_t y)
690 1.1 jdolecek {
691 1.68 isaki uint32_t loword;
692 1.68 isaki uint32_t hiword;
693 1.68 isaki int reg;
694 1.1 jdolecek
695 1.68 isaki if (sc->sc_type & EMUXKI_AUDIGY) {
696 1.68 isaki reg = EMU_A_MICROCODEBASE;
697 1.68 isaki loword = (x << 12) & EMU_A_DSP_LOWORD_OPX_MASK;
698 1.68 isaki loword |= y & EMU_A_DSP_LOWORD_OPY_MASK;
699 1.68 isaki hiword = (op << 24) & EMU_A_DSP_HIWORD_OPCODE_MASK;
700 1.68 isaki hiword |= (r << 12) & EMU_A_DSP_HIWORD_RESULT_MASK;
701 1.68 isaki hiword |= a & EMU_A_DSP_HIWORD_OPA_MASK;
702 1.40 kent } else {
703 1.68 isaki reg = EMU_MICROCODEBASE;
704 1.68 isaki loword = (x << 10) & EMU_DSP_LOWORD_OPX_MASK;
705 1.68 isaki loword |= y & EMU_DSP_LOWORD_OPY_MASK;
706 1.68 isaki hiword = (op << 20) & EMU_DSP_HIWORD_OPCODE_MASK;
707 1.68 isaki hiword |= (r << 10) & EMU_DSP_HIWORD_RESULT_MASK;
708 1.68 isaki hiword |= a & EMU_DSP_HIWORD_OPA_MASK;
709 1.40 kent }
710 1.1 jdolecek
711 1.68 isaki reg += (*pc) * 2;
712 1.68 isaki /* must ordering; lo, hi */
713 1.68 isaki emuxki_write(sc, 0, reg, loword);
714 1.68 isaki emuxki_write(sc, 0, reg + 1, hiword);
715 1.1 jdolecek
716 1.68 isaki (*pc)++;
717 1.1 jdolecek }
718 1.1 jdolecek
719 1.68 isaki static void
720 1.68 isaki emuxki_initfx(struct emuxki_softc *sc)
721 1.1 jdolecek {
722 1.68 isaki uint16_t pc;
723 1.1 jdolecek
724 1.68 isaki /* Set all GPRs to 0 */
725 1.68 isaki for (pc = 0; pc < 256; pc++)
726 1.68 isaki emuxki_write(sc, 0, EMU_DSP_GPR(pc), 0);
727 1.68 isaki for (pc = 0; pc < 160; pc++) {
728 1.68 isaki emuxki_write(sc, 0, EMU_TANKMEMDATAREGBASE + pc, 0);
729 1.68 isaki emuxki_write(sc, 0, EMU_TANKMEMADDRREGBASE + pc, 0);
730 1.1 jdolecek }
731 1.1 jdolecek
732 1.68 isaki /* stop DSP, single step mode */
733 1.68 isaki emuxki_write(sc, 0, X1(DBG), X1(DBG_SINGLE_STEP));
734 1.40 kent
735 1.68 isaki /* XXX: delay (48kHz equiv. 21us) if needed */
736 1.1 jdolecek
737 1.68 isaki /* start DSP programming */
738 1.68 isaki pc = 0;
739 1.1 jdolecek
740 1.68 isaki /* OUT[L/R] = 0 + FX[L/R] * 1 */
741 1.68 isaki emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_MACINTS,
742 1.68 isaki X2(DSP_OUTL, DSP_OUT_A_FRONT),
743 1.68 isaki X1(DSP_CST(0)),
744 1.68 isaki X1(DSP_FX(0)),
745 1.68 isaki X1(DSP_CST(1)));
746 1.68 isaki emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_MACINTS,
747 1.68 isaki X2(DSP_OUTR, DSP_OUT_A_FRONT),
748 1.68 isaki X1(DSP_CST(0)),
749 1.68 isaki X1(DSP_FX(1)),
750 1.68 isaki X1(DSP_CST(1)));
751 1.68 isaki #if 0
752 1.68 isaki /* XXX: rear feature??? */
753 1.68 isaki /* Rear OUT[L/R] = 0 + FX[L/R] * 1 */
754 1.68 isaki emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_MACINTS,
755 1.68 isaki X2(DSP_OUTL, DSP_OUT_A_REAR),
756 1.68 isaki X1(DSP_CST(0)),
757 1.68 isaki X1(DSP_FX(0)),
758 1.68 isaki X1(DSP_CST(1)));
759 1.68 isaki emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_MACINTS,
760 1.68 isaki X2(DSP_OUTR, DSP_OUT_A_REAR),
761 1.68 isaki X1(DSP_CST(0)),
762 1.68 isaki X1(DSP_FX(1)),
763 1.68 isaki X1(DSP_CST(1)));
764 1.68 isaki #endif
765 1.68 isaki /* ADC recording[L/R] = AC97 In[L/R] */
766 1.68 isaki emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_ACC3,
767 1.68 isaki X2(DSP_OUTL, DSP_OUT_ADC),
768 1.68 isaki X2(DSP_INL, DSP_IN_AC97),
769 1.68 isaki X1(DSP_CST(0)),
770 1.68 isaki X1(DSP_CST(0)));
771 1.68 isaki emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_ACC3,
772 1.68 isaki X2(DSP_OUTR, DSP_OUT_ADC),
773 1.68 isaki X2(DSP_INR, DSP_IN_AC97),
774 1.68 isaki X1(DSP_CST(0)),
775 1.68 isaki X1(DSP_CST(0)));
776 1.1 jdolecek
777 1.68 isaki /* fill NOP the rest of the microcode */
778 1.68 isaki while (pc < 512) {
779 1.68 isaki emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_ACC3,
780 1.68 isaki X1(DSP_CST(0)),
781 1.68 isaki X1(DSP_CST(0)),
782 1.68 isaki X1(DSP_CST(0)),
783 1.68 isaki X1(DSP_CST(0)));
784 1.68 isaki }
785 1.1 jdolecek
786 1.68 isaki /* clear single step flag, run DSP */
787 1.68 isaki emuxki_write(sc, 0, X1(DBG), 0);
788 1.1 jdolecek }
789 1.1 jdolecek
790 1.1 jdolecek /*
791 1.68 isaki * operations
792 1.1 jdolecek */
793 1.1 jdolecek
794 1.1 jdolecek static void
795 1.68 isaki emuxki_play_start(struct emuxki_softc *sc, int ch, uint32_t start, uint32_t end)
796 1.1 jdolecek {
797 1.68 isaki uint32_t pitch;
798 1.68 isaki uint32_t volume;
799 1.40 kent
800 1.68 isaki /* 48kHz:16384 = 128/375 */
801 1.68 isaki pitch = sc->play.sample_rate * 128 / 375;
802 1.68 isaki volume = 32767;
803 1.1 jdolecek
804 1.68 isaki emuxki_write(sc, ch, EMU_CHAN_DSL,
805 1.68 isaki (0 << 24) | /* send amound D = 0 */
806 1.68 isaki end);
807 1.1 jdolecek
808 1.68 isaki emuxki_write(sc, ch, EMU_CHAN_PSST,
809 1.68 isaki (0 << 24) | /* send amount C = 0 */
810 1.68 isaki start);
811 1.1 jdolecek
812 1.68 isaki emuxki_write(sc, ch, EMU_CHAN_VTFT,
813 1.68 isaki (volume << 16) |
814 1.68 isaki (0xffff)); /* cutoff filter = none */
815 1.40 kent
816 1.68 isaki emuxki_write(sc, ch, EMU_CHAN_CVCF,
817 1.68 isaki (volume << 16) |
818 1.68 isaki (0xffff)); /* cutoff filter = none */
819 1.1 jdolecek
820 1.68 isaki emuxki_write(sc, ch, EMU_CHAN_PTRX,
821 1.68 isaki (pitch << 16) |
822 1.68 isaki ((ch == 0 ? 0x7f : 0) << 8) | /* send amount A = 255,0(L) */
823 1.68 isaki ((ch == 0 ? 0 : 0x7f))); /* send amount B = 0,255(R) */
824 1.40 kent
825 1.68 isaki /* set the pitch to start */
826 1.68 isaki emuxki_write(sc, ch, EMU_CHAN_CPF,
827 1.68 isaki (pitch << 16) |
828 1.68 isaki EMU_CHAN_CPF_STEREO_MASK); /* stereo only */
829 1.1 jdolecek }
830 1.1 jdolecek
831 1.1 jdolecek static void
832 1.68 isaki emuxki_play_stop(struct emuxki_softc *sc, int ch)
833 1.35 christos {
834 1.40 kent
835 1.68 isaki /* pitch = 0 to stop playing */
836 1.68 isaki emuxki_write(sc, ch, EMU_CHAN_CPF, EMU_CHAN_CPF_STOP_MASK);
837 1.68 isaki /* volume = 0 */
838 1.68 isaki emuxki_write(sc, ch, EMU_CHAN_CVCF, 0);
839 1.35 christos }
840 1.35 christos
841 1.35 christos static void
842 1.68 isaki emuxki_timer_start(struct emuxki_softc *sc)
843 1.1 jdolecek {
844 1.68 isaki uint32_t timer;
845 1.1 jdolecek
846 1.68 isaki /* frame count of half PTE at 16bit, 2ch, 48kHz */
847 1.68 isaki timer = EMU_PTESIZE / 4 / 2;
848 1.1 jdolecek
849 1.68 isaki /* EMU_TIMER is 16bit register */
850 1.68 isaki emuxki_writeio_2(sc, EMU_TIMER, timer);
851 1.68 isaki emuxki_writeio_4(sc, EMU_INTE,
852 1.68 isaki emuxki_readio_4(sc, EMU_INTE) |
853 1.68 isaki EMU_INTE_INTERTIMERENB);
854 1.68 isaki DPRINTF("timer start\n");
855 1.1 jdolecek }
856 1.1 jdolecek
857 1.1 jdolecek static void
858 1.68 isaki emuxki_timer_stop(struct emuxki_softc *sc)
859 1.1 jdolecek {
860 1.1 jdolecek
861 1.68 isaki emuxki_writeio_4(sc, EMU_INTE,
862 1.68 isaki emuxki_readio_4(sc, EMU_INTE) &
863 1.68 isaki ~EMU_INTE_INTERTIMERENB);
864 1.68 isaki /* EMU_TIMER is 16bit register */
865 1.68 isaki emuxki_writeio_2(sc, EMU_TIMER, 0);
866 1.68 isaki DPRINTF("timer stop\n");
867 1.1 jdolecek }
868 1.1 jdolecek
869 1.1 jdolecek /*
870 1.68 isaki * audio interface
871 1.1 jdolecek */
872 1.1 jdolecek
873 1.1 jdolecek static int
874 1.68 isaki emuxki_query_format(void *hdl, audio_format_query_t *afp)
875 1.1 jdolecek {
876 1.40 kent
877 1.68 isaki return audio_query_format(emuxki_formats, EMUXKI_NFORMATS, afp);
878 1.1 jdolecek }
879 1.1 jdolecek
880 1.1 jdolecek static int
881 1.68 isaki emuxki_set_format(void *hdl, int setmode,
882 1.68 isaki const audio_params_t *play, const audio_params_t *rec,
883 1.68 isaki audio_filter_reg_t *pfil, audio_filter_reg_t *rfil)
884 1.1 jdolecek {
885 1.68 isaki struct emuxki_softc *sc = hdl;
886 1.1 jdolecek
887 1.68 isaki if ((setmode & AUMODE_PLAY))
888 1.68 isaki sc->play = *play;
889 1.68 isaki if ((setmode & AUMODE_RECORD))
890 1.68 isaki sc->rec = *rec;
891 1.40 kent return 0;
892 1.1 jdolecek }
893 1.1 jdolecek
894 1.68 isaki static int
895 1.68 isaki emuxki_halt_output(void *hdl)
896 1.1 jdolecek {
897 1.68 isaki struct emuxki_softc *sc = hdl;
898 1.40 kent
899 1.68 isaki emuxki_timer_stop(sc);
900 1.68 isaki emuxki_play_stop(sc, 0);
901 1.68 isaki emuxki_play_stop(sc, 1);
902 1.68 isaki return 0;
903 1.1 jdolecek }
904 1.1 jdolecek
905 1.68 isaki static int
906 1.68 isaki emuxki_halt_input(void *hdl)
907 1.1 jdolecek {
908 1.68 isaki struct emuxki_softc *sc = hdl;
909 1.1 jdolecek
910 1.68 isaki /* stop ADC */
911 1.68 isaki emuxki_write(sc, 0, EMU_ADCCR, 0);
912 1.1 jdolecek
913 1.68 isaki /* disable interrupt */
914 1.68 isaki emuxki_writeio_4(sc, EMU_INTE,
915 1.68 isaki emuxki_readio_4(sc, EMU_INTE) &
916 1.68 isaki ~EMU_INTE_ADCBUFENABLE);
917 1.40 kent
918 1.40 kent return 0;
919 1.1 jdolecek }
920 1.1 jdolecek
921 1.1 jdolecek static int
922 1.68 isaki emuxki_intr(void *hdl)
923 1.1 jdolecek {
924 1.68 isaki struct emuxki_softc *sc = hdl;
925 1.68 isaki uint32_t ipr;
926 1.68 isaki uint32_t curaddr;
927 1.68 isaki int handled = 0;
928 1.1 jdolecek
929 1.68 isaki mutex_spin_enter(&sc->sc_intr_lock);
930 1.1 jdolecek
931 1.68 isaki ipr = emuxki_readio_4(sc, EMU_IPR);
932 1.68 isaki DPRINTFN(3, "emuxki: ipr=%08x\n", ipr);
933 1.68 isaki if (sc->pintr && (ipr & EMU_IPR_INTERVALTIMER)) {
934 1.68 isaki /* read ch 0 */
935 1.68 isaki curaddr = emuxki_read(sc, 0, EMU_CHAN_CCCA) &
936 1.68 isaki EMU_CHAN_CCCA_CURRADDR_MASK;
937 1.68 isaki DPRINTFN(3, "curaddr=%08x\n", curaddr);
938 1.68 isaki curaddr *= sc->pframesize;
939 1.68 isaki
940 1.68 isaki if (curaddr < sc->poffset)
941 1.68 isaki curaddr += sc->plength;
942 1.68 isaki if (curaddr >= sc->poffset + sc->pblksize) {
943 1.68 isaki dmamem_sync(sc->pmem, BUS_DMASYNC_POSTWRITE);
944 1.68 isaki sc->pintr(sc->pintrarg);
945 1.68 isaki sc->poffset += sc->pblksize;
946 1.68 isaki if (sc->poffset >= sc->plength) {
947 1.68 isaki sc->poffset -= sc->plength;
948 1.19 toshii }
949 1.68 isaki dmamem_sync(sc->pmem, BUS_DMASYNC_PREWRITE);
950 1.1 jdolecek }
951 1.68 isaki handled = 1;
952 1.1 jdolecek }
953 1.1 jdolecek
954 1.68 isaki if (sc->rintr &&
955 1.68 isaki (ipr & (EMU_IPR_ADCBUFHALFFULL | EMU_IPR_ADCBUFFULL))) {
956 1.68 isaki char *src;
957 1.68 isaki char *dst;
958 1.68 isaki
959 1.68 isaki /* Record DMA buffer has just 2 blocks */
960 1.68 isaki src = KERNADDR(sc->rmem);
961 1.68 isaki if (ipr & EMU_IPR_ADCBUFFULL) {
962 1.68 isaki /* 2nd block */
963 1.68 isaki src += EMU_REC_DMABLKSIZE;
964 1.35 christos }
965 1.68 isaki dst = (char *)sc->rptr + sc->rcurrent;
966 1.1 jdolecek
967 1.68 isaki dmamem_sync(sc->rmem, BUS_DMASYNC_POSTREAD);
968 1.68 isaki memcpy(dst, src, EMU_REC_DMABLKSIZE);
969 1.68 isaki /* for next trans */
970 1.68 isaki dmamem_sync(sc->rmem, BUS_DMASYNC_PREREAD);
971 1.68 isaki sc->rcurrent += EMU_REC_DMABLKSIZE;
972 1.68 isaki
973 1.68 isaki if (sc->rcurrent >= sc->roffset + sc->rblksize) {
974 1.68 isaki sc->rintr(sc->rintrarg);
975 1.68 isaki sc->roffset += sc->rblksize;
976 1.68 isaki if (sc->roffset >= sc->rlength) {
977 1.68 isaki sc->roffset = 0;
978 1.68 isaki sc->rcurrent = 0;
979 1.35 christos }
980 1.68 isaki }
981 1.35 christos
982 1.68 isaki handled = 1;
983 1.1 jdolecek }
984 1.1 jdolecek
985 1.68 isaki #if defined(EMUXKI_DEBUG)
986 1.68 isaki if (!handled) {
987 1.68 isaki char buf[1024];
988 1.68 isaki snprintb(buf, sizeof(buf),
989 1.68 isaki "\20"
990 1.68 isaki "\x19""RATETRCHANGE"
991 1.68 isaki "\x18""FXDSP"
992 1.68 isaki "\x17""FORCEINT"
993 1.68 isaki "\x16""PCIERROR"
994 1.68 isaki "\x15""VOLINCR"
995 1.68 isaki "\x14""VOLDECR"
996 1.68 isaki "\x13""MUTE"
997 1.68 isaki "\x12""MICBUFFULL"
998 1.68 isaki "\x11""MICBUFHALFFULL"
999 1.68 isaki "\x10""ADCBUFFULL"
1000 1.68 isaki "\x0f""ADCBUFHALFFULL"
1001 1.68 isaki "\x0e""EFXBUFFULL"
1002 1.68 isaki "\x0d""EFXBUFHALFFULL"
1003 1.68 isaki "\x0c""GPSPDIFSTCHANGE"
1004 1.68 isaki "\x0b""CDROMSTCHANGE"
1005 1.68 isaki /* INTERVALTIMER */
1006 1.68 isaki "\x09""MIDITRANSBUFE"
1007 1.68 isaki "\x08""MIDIRECVBUFE"
1008 1.68 isaki "\x07""CHANNELLOOP"
1009 1.68 isaki , ipr);
1010 1.68 isaki DPRINTF("unexpected intr: %s\n", buf);
1011 1.40 kent
1012 1.68 isaki /* for debugging (must not handle if !DEBUG) */
1013 1.68 isaki handled = 1;
1014 1.1 jdolecek }
1015 1.19 toshii #endif
1016 1.13 jdolecek
1017 1.68 isaki /* Reset interrupt bit */
1018 1.68 isaki emuxki_writeio_4(sc, EMU_IPR, ipr);
1019 1.1 jdolecek
1020 1.60 jmcneill mutex_spin_exit(&sc->sc_intr_lock);
1021 1.60 jmcneill
1022 1.68 isaki /* Interrupt handler must return !=0 if handled */
1023 1.68 isaki return handled;
1024 1.1 jdolecek }
1025 1.1 jdolecek
1026 1.1 jdolecek static int
1027 1.68 isaki emuxki_getdev(void *hdl, struct audio_device *dev)
1028 1.1 jdolecek {
1029 1.68 isaki struct emuxki_softc *sc = hdl;
1030 1.1 jdolecek
1031 1.68 isaki *dev = sc->sc_audv;
1032 1.40 kent return 0;
1033 1.1 jdolecek }
1034 1.1 jdolecek
1035 1.68 isaki static int
1036 1.68 isaki emuxki_set_port(void *hdl, mixer_ctrl_t *mctl)
1037 1.1 jdolecek {
1038 1.68 isaki struct emuxki_softc *sc = hdl;
1039 1.1 jdolecek
1040 1.68 isaki return sc->codecif->vtbl->mixer_set_port(sc->codecif, mctl);
1041 1.1 jdolecek }
1042 1.1 jdolecek
1043 1.1 jdolecek static int
1044 1.68 isaki emuxki_get_port(void *hdl, mixer_ctrl_t *mctl)
1045 1.1 jdolecek {
1046 1.68 isaki struct emuxki_softc *sc = hdl;
1047 1.1 jdolecek
1048 1.68 isaki return sc->codecif->vtbl->mixer_get_port(sc->codecif, mctl);
1049 1.1 jdolecek }
1050 1.1 jdolecek
1051 1.1 jdolecek static int
1052 1.68 isaki emuxki_query_devinfo(void *hdl, mixer_devinfo_t *minfo)
1053 1.1 jdolecek {
1054 1.68 isaki struct emuxki_softc *sc = hdl;
1055 1.1 jdolecek
1056 1.68 isaki return sc->codecif->vtbl->query_devinfo(sc->codecif, minfo);
1057 1.1 jdolecek }
1058 1.1 jdolecek
1059 1.68 isaki static void *
1060 1.68 isaki emuxki_allocm(void *hdl, int direction, size_t size)
1061 1.1 jdolecek {
1062 1.68 isaki struct emuxki_softc *sc = hdl;
1063 1.68 isaki
1064 1.68 isaki if (direction == AUMODE_PLAY) {
1065 1.68 isaki if (sc->pmem) {
1066 1.68 isaki panic("pmem already allocated\n");
1067 1.68 isaki return NULL;
1068 1.8 jdolecek }
1069 1.68 isaki sc->pmem = dmamem_alloc(sc, size);
1070 1.68 isaki return KERNADDR(sc->pmem);
1071 1.68 isaki } else {
1072 1.68 isaki /* rmem is fixed size internal DMA buffer */
1073 1.68 isaki if (sc->rmem) {
1074 1.68 isaki panic("rmem already allocated\n");
1075 1.68 isaki return NULL;
1076 1.8 jdolecek }
1077 1.68 isaki /* rmem fixed size */
1078 1.68 isaki sc->rmem = dmamem_alloc(sc, EMU_REC_DMASIZE);
1079 1.1 jdolecek
1080 1.68 isaki /* recording MI buffer is normal kmem, software trans. */
1081 1.68 isaki sc->rptr = kmem_alloc(size, KM_SLEEP);
1082 1.68 isaki return sc->rptr;
1083 1.1 jdolecek }
1084 1.1 jdolecek }
1085 1.1 jdolecek
1086 1.68 isaki static void
1087 1.68 isaki emuxki_freem(void *hdl, void *ptr, size_t size)
1088 1.1 jdolecek {
1089 1.68 isaki struct emuxki_softc *sc = hdl;
1090 1.1 jdolecek
1091 1.68 isaki if (sc->pmem && ptr == KERNADDR(sc->pmem)) {
1092 1.68 isaki dmamem_free(sc->pmem);
1093 1.68 isaki sc->pmem = NULL;
1094 1.68 isaki }
1095 1.68 isaki if (sc->rmem && ptr == sc->rptr) {
1096 1.68 isaki dmamem_free(sc->rmem);
1097 1.68 isaki sc->rmem = NULL;
1098 1.68 isaki kmem_free(sc->rptr, size);
1099 1.68 isaki sc->rptr = NULL;
1100 1.68 isaki }
1101 1.1 jdolecek }
1102 1.1 jdolecek
1103 1.68 isaki /*
1104 1.68 isaki * blocksize rounding to EMU_PTESIZE. It is for easy to drive.
1105 1.68 isaki */
1106 1.1 jdolecek static int
1107 1.68 isaki emuxki_round_blocksize(void *hdl, int blksize,
1108 1.68 isaki int mode, const audio_params_t* param)
1109 1.1 jdolecek {
1110 1.1 jdolecek
1111 1.68 isaki /*
1112 1.68 isaki * This is not necessary for recording, but symmetric for easy.
1113 1.68 isaki * For recording buffer/block size requirements of hardware,
1114 1.68 isaki * see EMU_RECBS_BUFSIZE_*
1115 1.68 isaki */
1116 1.68 isaki if (blksize < EMU_PTESIZE)
1117 1.68 isaki blksize = EMU_PTESIZE;
1118 1.68 isaki return rounddown(blksize, EMU_PTESIZE);
1119 1.1 jdolecek }
1120 1.1 jdolecek
1121 1.68 isaki static size_t
1122 1.68 isaki emuxki_round_buffersize(void *hdl, int direction, size_t bsize)
1123 1.1 jdolecek {
1124 1.40 kent
1125 1.68 isaki /* This is not necessary for recording, but symmetric for easy */
1126 1.68 isaki if (bsize < EMU_MINPTE * EMU_PTESIZE) {
1127 1.68 isaki bsize = EMU_MINPTE * EMU_PTESIZE;
1128 1.68 isaki } else if (bsize > EMU_MAXPTE * EMU_PTESIZE) {
1129 1.68 isaki bsize = EMU_MAXPTE * EMU_PTESIZE;
1130 1.68 isaki }
1131 1.68 isaki return roundup(bsize, EMU_PTESIZE);
1132 1.1 jdolecek }
1133 1.1 jdolecek
1134 1.1 jdolecek static int
1135 1.68 isaki emuxki_get_props(void *hdl)
1136 1.1 jdolecek {
1137 1.1 jdolecek
1138 1.70 isaki return AUDIO_PROP_PLAYBACK | AUDIO_PROP_CAPTURE |
1139 1.70 isaki AUDIO_PROP_INDEPENDENT | AUDIO_PROP_FULLDUPLEX;
1140 1.1 jdolecek }
1141 1.1 jdolecek
1142 1.1 jdolecek static int
1143 1.68 isaki emuxki_trigger_output(void *hdl, void *start, void *end, int blksize,
1144 1.68 isaki void (*intr)(void *), void *arg, const audio_params_t *params)
1145 1.1 jdolecek {
1146 1.68 isaki struct emuxki_softc *sc = hdl;
1147 1.68 isaki int npage;
1148 1.68 isaki uint32_t *kptb;
1149 1.68 isaki bus_addr_t dpmem;
1150 1.68 isaki int i;
1151 1.68 isaki uint32_t hwstart;
1152 1.68 isaki uint32_t hwend;
1153 1.68 isaki
1154 1.68 isaki if (sc->pmem == NULL)
1155 1.68 isaki panic("pmem == NULL\n");
1156 1.68 isaki if (start != KERNADDR(sc->pmem))
1157 1.68 isaki panic("start != KERNADDR(sc->pmem)\n");
1158 1.68 isaki
1159 1.68 isaki sc->pframesize = 4; /* channels * bit / 8 = 2*16/8=4 */
1160 1.68 isaki sc->pblksize = blksize;
1161 1.68 isaki sc->plength = (char *)end - (char *)start;
1162 1.68 isaki sc->poffset = 0;
1163 1.68 isaki npage = roundup(sc->plength, EMU_PTESIZE);
1164 1.1 jdolecek
1165 1.68 isaki kptb = KERNADDR(sc->ptb);
1166 1.68 isaki dpmem = DMAADDR(sc->pmem);
1167 1.68 isaki for (i = 0; i < npage; i++) {
1168 1.68 isaki kptb[i] = htole32(dpmem << 1);
1169 1.68 isaki dpmem += EMU_PTESIZE;
1170 1.68 isaki }
1171 1.68 isaki dmamem_sync(sc->ptb, BUS_DMASYNC_PREWRITE);
1172 1.1 jdolecek
1173 1.68 isaki hwstart = 0;
1174 1.68 isaki hwend = hwstart + sc->plength / sc->pframesize;
1175 1.1 jdolecek
1176 1.68 isaki sc->pintr = intr;
1177 1.68 isaki sc->pintrarg = arg;
1178 1.1 jdolecek
1179 1.68 isaki dmamem_sync(sc->pmem, BUS_DMASYNC_PREWRITE);
1180 1.1 jdolecek
1181 1.68 isaki emuxki_play_start(sc, 0, hwstart, hwend);
1182 1.68 isaki emuxki_play_start(sc, 1, hwstart, hwend);
1183 1.1 jdolecek
1184 1.68 isaki emuxki_timer_start(sc);
1185 1.1 jdolecek
1186 1.68 isaki return 0;
1187 1.1 jdolecek }
1188 1.1 jdolecek
1189 1.68 isaki /*
1190 1.68 isaki * Recording uses temporary buffer. Because it can use ADC_HALF/FULL
1191 1.68 isaki * interrupts and this method doesn't conflict with playback.
1192 1.68 isaki */
1193 1.68 isaki
1194 1.19 toshii static int
1195 1.68 isaki emuxki_trigger_input(void *hdl, void *start, void *end, int blksize,
1196 1.68 isaki void (*intr)(void *), void *arg, const audio_params_t *params)
1197 1.19 toshii {
1198 1.68 isaki struct emuxki_softc *sc = hdl;
1199 1.19 toshii
1200 1.68 isaki if (sc->rmem == NULL)
1201 1.68 isaki panic("rmem == NULL\n");
1202 1.68 isaki if (start != sc->rptr)
1203 1.68 isaki panic("start != sc->rptr\n");
1204 1.68 isaki
1205 1.68 isaki sc->rframesize = 4; /* channels * bit / 8 = 2*16/8=4 */
1206 1.68 isaki sc->rblksize = blksize;
1207 1.68 isaki sc->rlength = (char *)end - (char *)start;
1208 1.68 isaki sc->roffset = 0;
1209 1.68 isaki sc->rcurrent = 0;
1210 1.19 toshii
1211 1.68 isaki sc->rintr = intr;
1212 1.68 isaki sc->rintrarg = arg;
1213 1.19 toshii
1214 1.68 isaki /*
1215 1.68 isaki * Memo:
1216 1.68 isaki * recording source is selected by AC97
1217 1.68 isaki * AC97 input source routes to ADC by FX(DSP)
1218 1.68 isaki *
1219 1.68 isaki * Must keep following sequence order
1220 1.68 isaki */
1221 1.40 kent
1222 1.68 isaki /* first, stop ADC */
1223 1.68 isaki emuxki_write(sc, 0, EMU_ADCCR, 0);
1224 1.68 isaki emuxki_write(sc, 0, EMU_ADCBA, 0);
1225 1.68 isaki emuxki_write(sc, 0, EMU_ADCBS, 0);
1226 1.1 jdolecek
1227 1.68 isaki dmamem_sync(sc->rmem, BUS_DMASYNC_PREREAD);
1228 1.1 jdolecek
1229 1.68 isaki /* ADC interrupt enable */
1230 1.68 isaki emuxki_writeio_4(sc, EMU_INTE,
1231 1.68 isaki emuxki_readio_4(sc, EMU_INTE) |
1232 1.68 isaki EMU_INTE_ADCBUFENABLE);
1233 1.68 isaki
1234 1.68 isaki /* ADC Enable */
1235 1.68 isaki /* stereo, 48kHz, enable */
1236 1.68 isaki emuxki_write(sc, 0, EMU_ADCCR,
1237 1.68 isaki X1(ADCCR_LCHANENABLE) | X1(ADCCR_RCHANENABLE));
1238 1.68 isaki
1239 1.68 isaki /* ADC buffer address */
1240 1.68 isaki emuxki_write(sc, 0, X1(ADCIDX), 0);
1241 1.68 isaki emuxki_write(sc, 0, EMU_ADCBA, DMAADDR(sc->rmem));
1242 1.1 jdolecek
1243 1.68 isaki /* ADC buffer size, to start */
1244 1.68 isaki emuxki_write(sc, 0, EMU_ADCBS, EMU_REC_BUFSIZE_RECBS);
1245 1.1 jdolecek
1246 1.68 isaki return 0;
1247 1.1 jdolecek }
1248 1.1 jdolecek
1249 1.68 isaki static void
1250 1.68 isaki emuxki_get_locks(void *hdl, kmutex_t **intr, kmutex_t **proc)
1251 1.1 jdolecek {
1252 1.68 isaki struct emuxki_softc *sc = hdl;
1253 1.1 jdolecek
1254 1.68 isaki *intr = &sc->sc_intr_lock;
1255 1.68 isaki *proc = &sc->sc_lock;
1256 1.1 jdolecek }
1257 1.1 jdolecek
1258 1.68 isaki /*
1259 1.68 isaki * AC97
1260 1.68 isaki */
1261 1.1 jdolecek
1262 1.1 jdolecek static int
1263 1.68 isaki emuxki_ac97_init(struct emuxki_softc *sc)
1264 1.1 jdolecek {
1265 1.1 jdolecek
1266 1.68 isaki sc->hostif.arg = sc;
1267 1.68 isaki sc->hostif.attach = emuxki_ac97_attach;
1268 1.68 isaki sc->hostif.read = emuxki_ac97_read;
1269 1.68 isaki sc->hostif.write = emuxki_ac97_write;
1270 1.68 isaki sc->hostif.reset = emuxki_ac97_reset;
1271 1.68 isaki sc->hostif.flags = emuxki_ac97_flags;
1272 1.68 isaki return ac97_attach(&sc->hostif, sc->sc_dev, &sc->sc_lock);
1273 1.1 jdolecek }
1274 1.1 jdolecek
1275 1.1 jdolecek /*
1276 1.1 jdolecek * AC97 callbacks
1277 1.1 jdolecek */
1278 1.1 jdolecek
1279 1.1 jdolecek static int
1280 1.68 isaki emuxki_ac97_attach(void *hdl, struct ac97_codec_if *codecif)
1281 1.1 jdolecek {
1282 1.68 isaki struct emuxki_softc *sc = hdl;
1283 1.1 jdolecek
1284 1.1 jdolecek sc->codecif = codecif;
1285 1.40 kent return 0;
1286 1.1 jdolecek }
1287 1.1 jdolecek
1288 1.1 jdolecek static int
1289 1.68 isaki emuxki_ac97_read(void *hdl, uint8_t reg, uint16_t *val)
1290 1.1 jdolecek {
1291 1.68 isaki struct emuxki_softc *sc = hdl;
1292 1.1 jdolecek
1293 1.68 isaki mutex_spin_enter(&sc->sc_index_lock);
1294 1.68 isaki emuxki_writeio_1(sc, EMU_AC97ADDR, reg);
1295 1.68 isaki *val = emuxki_readio_2(sc, EMU_AC97DATA);
1296 1.68 isaki mutex_spin_exit(&sc->sc_index_lock);
1297 1.1 jdolecek
1298 1.40 kent return 0;
1299 1.1 jdolecek }
1300 1.1 jdolecek
1301 1.1 jdolecek static int
1302 1.68 isaki emuxki_ac97_write(void *hdl, uint8_t reg, uint16_t val)
1303 1.1 jdolecek {
1304 1.68 isaki struct emuxki_softc *sc = hdl;
1305 1.1 jdolecek
1306 1.68 isaki mutex_spin_enter(&sc->sc_index_lock);
1307 1.68 isaki emuxki_writeio_1(sc, EMU_AC97ADDR, reg);
1308 1.68 isaki emuxki_writeio_2(sc, EMU_AC97DATA, val);
1309 1.68 isaki mutex_spin_exit(&sc->sc_index_lock);
1310 1.1 jdolecek
1311 1.40 kent return 0;
1312 1.1 jdolecek }
1313 1.1 jdolecek
1314 1.36 kent static int
1315 1.68 isaki emuxki_ac97_reset(void *hdl)
1316 1.1 jdolecek {
1317 1.40 kent
1318 1.36 kent return 0;
1319 1.6 jdolecek }
1320 1.6 jdolecek
1321 1.68 isaki static enum ac97_host_flags
1322 1.68 isaki emuxki_ac97_flags(void *hdl)
1323 1.6 jdolecek {
1324 1.40 kent
1325 1.40 kent return AC97_HOST_SWAPPED_CHANNELS;
1326 1.1 jdolecek }
1327 1.73 khorben
1328 1.73 khorben MODULE(MODULE_CLASS_DRIVER, emuxki, "pci,audio");
1329 1.73 khorben
1330 1.73 khorben #ifdef _MODULE
1331 1.73 khorben #include "ioconf.c"
1332 1.73 khorben #endif
1333 1.73 khorben
1334 1.73 khorben static int
1335 1.73 khorben emuxki_modcmd(modcmd_t cmd, void *opaque)
1336 1.73 khorben {
1337 1.73 khorben int error = 0;
1338 1.73 khorben
1339 1.73 khorben switch (cmd) {
1340 1.73 khorben case MODULE_CMD_INIT:
1341 1.73 khorben #ifdef _MODULE
1342 1.73 khorben error = config_init_component(cfdriver_ioconf_emuxki,
1343 1.73 khorben cfattach_ioconf_emuxki, cfdata_ioconf_emuxki);
1344 1.73 khorben #endif
1345 1.73 khorben return error;
1346 1.73 khorben case MODULE_CMD_FINI:
1347 1.73 khorben #ifdef _MODULE
1348 1.73 khorben error = config_fini_component(cfdriver_ioconf_emuxki,
1349 1.73 khorben cfattach_ioconf_emuxki, cfdata_ioconf_emuxki);
1350 1.73 khorben #endif
1351 1.73 khorben return error;
1352 1.73 khorben default:
1353 1.73 khorben return ENOTTY;
1354 1.73 khorben }
1355 1.73 khorben }
1356