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