neo.c revision 1.25 1 1.25 kent /* $NetBSD: neo.c,v 1.25 2005/01/10 22:01:37 kent Exp $ */
2 1.1 thorpej
3 1.1 thorpej /*
4 1.1 thorpej * Copyright (c) 1999 Cameron Grant <gandalf (at) vilnya.demon.co.uk>
5 1.1 thorpej * All rights reserved.
6 1.1 thorpej *
7 1.1 thorpej * Derived from the public domain Linux driver
8 1.1 thorpej *
9 1.1 thorpej * Redistribution and use in source and binary forms, with or without
10 1.1 thorpej * modification, are permitted provided that the following conditions
11 1.1 thorpej * are met:
12 1.1 thorpej * 1. Redistributions of source code must retain the above copyright
13 1.1 thorpej * notice, this list of conditions and the following disclaimer.
14 1.1 thorpej * 2. Redistributions in binary form must reproduce the above copyright
15 1.1 thorpej * notice, this list of conditions and the following disclaimer in the
16 1.1 thorpej * documentation and/or other materials provided with the distribution.
17 1.1 thorpej *
18 1.1 thorpej * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19 1.1 thorpej * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 1.1 thorpej * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 1.1 thorpej * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22 1.1 thorpej * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 1.1 thorpej * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 1.1 thorpej * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 1.1 thorpej * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHERIN CONTRACT, STRICT
26 1.1 thorpej * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 1.1 thorpej * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THEPOSSIBILITY OF
28 1.1 thorpej * SUCH DAMAGE.
29 1.1 thorpej *
30 1.1 thorpej * FreeBSD: src/sys/dev/sound/pci/neomagic.c,v 1.8 2000/03/20 15:30:50 cg Exp
31 1.1 thorpej * OpenBSD: neo.c,v 1.4 2000/07/19 09:04:37 csapuntz Exp
32 1.1 thorpej */
33 1.11 lukem
34 1.11 lukem #include <sys/cdefs.h>
35 1.25 kent __KERNEL_RCSID(0, "$NetBSD: neo.c,v 1.25 2005/01/10 22:01:37 kent Exp $");
36 1.1 thorpej
37 1.1 thorpej #include <sys/param.h>
38 1.1 thorpej #include <sys/systm.h>
39 1.1 thorpej #include <sys/kernel.h>
40 1.1 thorpej #include <sys/malloc.h>
41 1.1 thorpej #include <sys/device.h>
42 1.1 thorpej
43 1.1 thorpej #include <machine/bus.h>
44 1.1 thorpej
45 1.1 thorpej #include <dev/pci/pcidevs.h>
46 1.1 thorpej #include <dev/pci/pcivar.h>
47 1.1 thorpej
48 1.1 thorpej #include <dev/pci/neoreg.h>
49 1.1 thorpej #include <dev/pci/neo-coeff.h>
50 1.1 thorpej
51 1.1 thorpej #include <sys/audioio.h>
52 1.1 thorpej #include <dev/audio_if.h>
53 1.1 thorpej #include <dev/mulaw.h>
54 1.1 thorpej #include <dev/auconv.h>
55 1.1 thorpej
56 1.1 thorpej #include <dev/ic/ac97var.h>
57 1.1 thorpej
58 1.1 thorpej
59 1.1 thorpej /* -------------------------------------------------------------------- */
60 1.1 thorpej /*
61 1.1 thorpej * As of 04/13/00, public documentation on the Neomagic 256 is not available.
62 1.1 thorpej * These comments were gleaned by looking at the driver carefully.
63 1.1 thorpej *
64 1.1 thorpej * The Neomagic 256 AV/ZX chips provide both video and audio capabilities
65 1.1 thorpej * on one chip. About 2-6 megabytes of memory are associated with
66 1.1 thorpej * the chip. Most of this goes to video frame buffers, but some is used for
67 1.1 thorpej * audio buffering
68 1.1 thorpej *
69 1.1 thorpej * Unlike most PCI audio chips, the Neomagic chip does not rely on DMA.
70 1.1 thorpej * Instead, the chip allows you to carve out two ring buffers out of its
71 1.1 thorpej * memory. However you carve this and how much you can carve seems to be
72 1.1 thorpej * voodoo. The algorithm is in nm_init.
73 1.1 thorpej *
74 1.1 thorpej * Most Neomagic audio chips use the AC-97 codec interface. However, there
75 1.1 thorpej * seem to be a select few chips 256AV chips that do not support AC-97.
76 1.1 thorpej * This driver does not support them but there are rumors that it
77 1.12 simonb * might work with wss isa drivers. This might require some playing around
78 1.1 thorpej * with your BIOS.
79 1.1 thorpej *
80 1.1 thorpej * The Neomagic 256 AV/ZX have 2 PCI I/O region descriptors. Both of
81 1.1 thorpej * them describe a memory region. The frame buffer is the first region
82 1.1 thorpej * and the register set is the secodn region.
83 1.1 thorpej *
84 1.1 thorpej * The register manipulation logic is taken from the Linux driver,
85 1.1 thorpej * which is in the public domain.
86 1.1 thorpej *
87 1.1 thorpej * The Neomagic is even nice enough to map the AC-97 codec registers into
88 1.1 thorpej * the register space to allow direct manipulation. Watch out, accessing
89 1.1 thorpej * AC-97 registers on the Neomagic requires great delicateness, otherwise
90 1.1 thorpej * the thing will hang the PCI bus, rendering your system frozen.
91 1.1 thorpej *
92 1.1 thorpej * For one, it seems the Neomagic status register that reports AC-97
93 1.1 thorpej * readiness should NOT be polled more often than once each 1ms.
94 1.1 thorpej *
95 1.1 thorpej * Also, writes to the AC-97 register space may take order 40us to
96 1.1 thorpej * complete.
97 1.1 thorpej *
98 1.12 simonb * Unlike many sound engines, the Neomagic does not support (as far as
99 1.1 thorpej * we know :) the notion of interrupting every n bytes transferred,
100 1.1 thorpej * unlike many DMA engines. Instead, it allows you to specify one
101 1.1 thorpej * location in each ring buffer (called the watermark). When the chip
102 1.1 thorpej * passes that location while playing, it signals an interrupt.
103 1.1 thorpej *
104 1.1 thorpej * The ring buffer size is currently 16k. That is about 100ms of audio
105 1.18 tsutsui * at 44.1kHz/stero/16 bit. However, to keep the buffer full, interrupts
106 1.1 thorpej * are generated more often than that, so 20-40 interrupts per second
107 1.1 thorpej * should not be unexpected. Increasing BUFFSIZE should help minimize
108 1.1 thorpej * of glitches due to drivers that spend to much time looping at high
109 1.1 thorpej * privelege levels as well as the impact of badly written audio
110 1.1 thorpej * interface clients.
111 1.1 thorpej *
112 1.1 thorpej * TO-DO list:
113 1.1 thorpej * Figure out interaction with video stuff (look at Xfree86 driver?)
114 1.1 thorpej *
115 1.1 thorpej * Figure out how to shrink that huge table neo-coeff.h
116 1.1 thorpej */
117 1.1 thorpej
118 1.1 thorpej #define NM_BUFFSIZE 16384
119 1.1 thorpej
120 1.1 thorpej /* device private data */
121 1.1 thorpej struct neo_softc {
122 1.1 thorpej struct device dev;
123 1.1 thorpej
124 1.1 thorpej bus_space_tag_t bufiot;
125 1.1 thorpej bus_space_handle_t bufioh;
126 1.1 thorpej
127 1.1 thorpej bus_space_tag_t regiot;
128 1.1 thorpej bus_space_handle_t regioh;
129 1.1 thorpej
130 1.1 thorpej u_int32_t type;
131 1.1 thorpej void *ih;
132 1.1 thorpej
133 1.19 wiz void (*pintr)(void *); /* DMA completion intr handler */
134 1.1 thorpej void *parg; /* arg for intr() */
135 1.1 thorpej
136 1.19 wiz void (*rintr)(void *); /* DMA completion intr handler */
137 1.1 thorpej void *rarg; /* arg for intr() */
138 1.1 thorpej
139 1.1 thorpej vaddr_t buf_vaddr;
140 1.1 thorpej vaddr_t rbuf_vaddr;
141 1.1 thorpej vaddr_t pbuf_vaddr;
142 1.1 thorpej int pbuf_allocated;
143 1.1 thorpej int rbuf_allocated;
144 1.1 thorpej
145 1.3 thorpej bus_addr_t buf_pciaddr;
146 1.3 thorpej bus_addr_t rbuf_pciaddr;
147 1.3 thorpej bus_addr_t pbuf_pciaddr;
148 1.3 thorpej
149 1.1 thorpej u_int32_t ac97_base, ac97_status, ac97_busy;
150 1.1 thorpej u_int32_t buftop, pbuf, rbuf, cbuf, acbuf;
151 1.1 thorpej u_int32_t playint, recint, misc1int, misc2int;
152 1.1 thorpej u_int32_t irsz, badintr;
153 1.1 thorpej
154 1.1 thorpej u_int32_t pbufsize;
155 1.1 thorpej u_int32_t rbufsize;
156 1.1 thorpej
157 1.1 thorpej u_int32_t pblksize;
158 1.1 thorpej u_int32_t rblksize;
159 1.1 thorpej
160 1.1 thorpej u_int32_t pwmark;
161 1.1 thorpej u_int32_t rwmark;
162 1.1 thorpej
163 1.1 thorpej struct ac97_codec_if *codec_if;
164 1.5 sommerfe struct ac97_host_if host_if;
165 1.5 sommerfe
166 1.5 sommerfe void *powerhook;
167 1.1 thorpej };
168 1.1 thorpej
169 1.1 thorpej /* -------------------------------------------------------------------- */
170 1.1 thorpej
171 1.1 thorpej /*
172 1.1 thorpej * prototypes
173 1.1 thorpej */
174 1.1 thorpej
175 1.1 thorpej static int nm_waitcd(struct neo_softc *sc);
176 1.1 thorpej static int nm_loadcoeff(struct neo_softc *sc, int dir, int num);
177 1.1 thorpej static int nm_init(struct neo_softc *);
178 1.1 thorpej
179 1.1 thorpej int neo_match(struct device *, struct cfdata *, void *);
180 1.1 thorpej void neo_attach(struct device *, struct device *, void *);
181 1.1 thorpej int neo_intr(void *);
182 1.1 thorpej
183 1.1 thorpej int neo_query_encoding(void *, struct audio_encoding *);
184 1.25 kent int neo_set_params(void *, int, int, audio_params_t *, audio_params_t *,
185 1.25 kent stream_filter_list_t *, stream_filter_list_t *);
186 1.25 kent int neo_round_blocksize(void *, int, int, const audio_params_t *);
187 1.1 thorpej int neo_trigger_output(void *, void *, void *, int, void (*)(void *),
188 1.25 kent void *, const audio_params_t *);
189 1.1 thorpej int neo_trigger_input(void *, void *, void *, int, void (*)(void *),
190 1.25 kent void *, const audio_params_t *);
191 1.1 thorpej int neo_halt_output(void *);
192 1.1 thorpej int neo_halt_input(void *);
193 1.1 thorpej int neo_getdev(void *, struct audio_device *);
194 1.1 thorpej int neo_mixer_set_port(void *, mixer_ctrl_t *);
195 1.1 thorpej int neo_mixer_get_port(void *, mixer_ctrl_t *);
196 1.1 thorpej int neo_attach_codec(void *sc, struct ac97_codec_if *);
197 1.1 thorpej int neo_read_codec(void *sc, u_int8_t a, u_int16_t *d);
198 1.1 thorpej int neo_write_codec(void *sc, u_int8_t a, u_int16_t d);
199 1.23 kent int neo_reset_codec(void *sc);
200 1.1 thorpej enum ac97_host_flags neo_flags_codec(void *sc);
201 1.1 thorpej int neo_query_devinfo(void *, mixer_devinfo_t *);
202 1.17 thorpej void *neo_malloc(void *, int, size_t, struct malloc_type *, int);
203 1.17 thorpej void neo_free(void *, void *, struct malloc_type *);
204 1.1 thorpej size_t neo_round_buffersize(void *, int, size_t);
205 1.3 thorpej paddr_t neo_mappage(void *, void *, off_t, int);
206 1.1 thorpej int neo_get_props(void *);
207 1.1 thorpej void neo_set_mixer(struct neo_softc *sc, int a, int d);
208 1.5 sommerfe void neo_power(int why, void *arg);
209 1.1 thorpej
210 1.15 thorpej CFATTACH_DECL(neo, sizeof(struct neo_softc),
211 1.16 thorpej neo_match, neo_attach, NULL, NULL);
212 1.1 thorpej
213 1.1 thorpej struct audio_device neo_device = {
214 1.1 thorpej "NeoMagic 256",
215 1.1 thorpej "",
216 1.1 thorpej "neo"
217 1.1 thorpej };
218 1.1 thorpej
219 1.1 thorpej /* The actual rates supported by the card. */
220 1.1 thorpej static const int samplerates[9] = {
221 1.1 thorpej 8000,
222 1.1 thorpej 11025,
223 1.1 thorpej 16000,
224 1.1 thorpej 22050,
225 1.1 thorpej 24000,
226 1.1 thorpej 32000,
227 1.1 thorpej 44100,
228 1.1 thorpej 48000,
229 1.1 thorpej 99999999
230 1.1 thorpej };
231 1.1 thorpej
232 1.25 kent #define NEO_NFORMATS 4
233 1.25 kent static const struct audio_format neo_formats[NEO_NFORMATS] = {
234 1.25 kent {NULL, AUMODE_PLAY | AUMODE_RECORD, AUDIO_ENCODING_SLINEAR_LE, 16, 16,
235 1.25 kent 2, AUFMT_STEREO, 8, {8000, 11025, 16000, 22050, 24000, 32000, 44100, 48000}},
236 1.25 kent {NULL, AUMODE_PLAY | AUMODE_RECORD, AUDIO_ENCODING_SLINEAR_LE, 16, 16,
237 1.25 kent 1, AUFMT_MONAURAL, 8, {8000, 11025, 16000, 22050, 24000, 32000, 44100, 48000}},
238 1.25 kent {NULL, AUMODE_PLAY | AUMODE_RECORD, AUDIO_ENCODING_ULINEAR_LE, 8, 8,
239 1.25 kent 2, AUFMT_STEREO, 8, {8000, 11025, 16000, 22050, 24000, 32000, 44100, 48000}},
240 1.25 kent {NULL, AUMODE_PLAY | AUMODE_RECORD, AUDIO_ENCODING_ULINEAR_LE, 8, 8,
241 1.25 kent 1, AUFMT_MONAURAL, 8, {8000, 11025, 16000, 22050, 24000, 32000, 44100, 48000}},
242 1.25 kent };
243 1.25 kent
244 1.1 thorpej /* -------------------------------------------------------------------- */
245 1.1 thorpej
246 1.24 yamt const struct audio_hw_if neo_hw_if = {
247 1.25 kent NULL, /* open */
248 1.25 kent NULL, /* close */
249 1.1 thorpej NULL, /* drain */
250 1.1 thorpej neo_query_encoding,
251 1.1 thorpej neo_set_params,
252 1.1 thorpej neo_round_blocksize,
253 1.1 thorpej NULL, /* commit_setting */
254 1.1 thorpej NULL, /* init_output */
255 1.1 thorpej NULL, /* init_input */
256 1.1 thorpej NULL, /* start_output */
257 1.1 thorpej NULL, /* start_input */
258 1.1 thorpej neo_halt_output,
259 1.1 thorpej neo_halt_input,
260 1.1 thorpej NULL, /* speaker_ctl */
261 1.1 thorpej neo_getdev,
262 1.1 thorpej NULL, /* getfd */
263 1.1 thorpej neo_mixer_set_port,
264 1.1 thorpej neo_mixer_get_port,
265 1.1 thorpej neo_query_devinfo,
266 1.1 thorpej neo_malloc,
267 1.1 thorpej neo_free,
268 1.1 thorpej neo_round_buffersize,
269 1.3 thorpej neo_mappage,
270 1.1 thorpej neo_get_props,
271 1.1 thorpej neo_trigger_output,
272 1.1 thorpej neo_trigger_input,
273 1.10 augustss NULL,
274 1.1 thorpej };
275 1.1 thorpej
276 1.1 thorpej /* -------------------------------------------------------------------- */
277 1.1 thorpej
278 1.1 thorpej #define nm_rd_1(sc, regno) \
279 1.1 thorpej bus_space_read_1((sc)->regiot, (sc)->regioh, (regno))
280 1.1 thorpej
281 1.1 thorpej #define nm_rd_2(sc, regno) \
282 1.1 thorpej bus_space_read_2((sc)->regiot, (sc)->regioh, (regno))
283 1.1 thorpej
284 1.1 thorpej #define nm_rd_4(sc, regno) \
285 1.1 thorpej bus_space_read_4((sc)->regiot, (sc)->regioh, (regno))
286 1.1 thorpej
287 1.1 thorpej #define nm_wr_1(sc, regno, val) \
288 1.1 thorpej bus_space_write_1((sc)->regiot, (sc)->regioh, (regno), (val))
289 1.1 thorpej
290 1.1 thorpej #define nm_wr_2(sc, regno, val) \
291 1.1 thorpej bus_space_write_2((sc)->regiot, (sc)->regioh, (regno), (val))
292 1.1 thorpej
293 1.1 thorpej #define nm_wr_4(sc, regno, val) \
294 1.1 thorpej bus_space_write_4((sc)->regiot, (sc)->regioh, (regno), (val))
295 1.1 thorpej
296 1.1 thorpej #define nm_rdbuf_4(sc, regno) \
297 1.1 thorpej bus_space_read_4((sc)->bufiot, (sc)->bufioh, (regno))
298 1.1 thorpej
299 1.1 thorpej #define nm_wrbuf_1(sc, regno, val) \
300 1.1 thorpej bus_space_write_1((sc)->bufiot, (sc)->bufioh, (regno), (val))
301 1.1 thorpej
302 1.1 thorpej /* ac97 codec */
303 1.1 thorpej static int
304 1.1 thorpej nm_waitcd(struct neo_softc *sc)
305 1.1 thorpej {
306 1.1 thorpej int cnt = 10;
307 1.1 thorpej int fail = 1;
308 1.1 thorpej
309 1.1 thorpej while (cnt-- > 0) {
310 1.1 thorpej if (nm_rd_2(sc, sc->ac97_status) & sc->ac97_busy)
311 1.1 thorpej DELAY(100);
312 1.1 thorpej else {
313 1.1 thorpej fail = 0;
314 1.1 thorpej break;
315 1.1 thorpej }
316 1.1 thorpej }
317 1.1 thorpej return (fail);
318 1.1 thorpej }
319 1.1 thorpej
320 1.1 thorpej
321 1.1 thorpej static void
322 1.1 thorpej nm_ackint(struct neo_softc *sc, u_int32_t num)
323 1.1 thorpej {
324 1.1 thorpej
325 1.1 thorpej switch (sc->type) {
326 1.1 thorpej case PCI_PRODUCT_NEOMAGIC_NMMM256AV_AU:
327 1.1 thorpej nm_wr_2(sc, NM_INT_REG, num << 1);
328 1.1 thorpej break;
329 1.1 thorpej
330 1.1 thorpej case PCI_PRODUCT_NEOMAGIC_NMMM256ZX_AU:
331 1.1 thorpej nm_wr_4(sc, NM_INT_REG, num);
332 1.1 thorpej break;
333 1.1 thorpej }
334 1.1 thorpej }
335 1.1 thorpej
336 1.1 thorpej static int
337 1.1 thorpej nm_loadcoeff(struct neo_softc *sc, int dir, int num)
338 1.1 thorpej {
339 1.1 thorpej int ofs, sz, i;
340 1.1 thorpej u_int32_t addr;
341 1.1 thorpej
342 1.1 thorpej addr = (dir == AUMODE_PLAY)? 0x01c : 0x21c;
343 1.1 thorpej if (dir == AUMODE_RECORD)
344 1.1 thorpej num += 8;
345 1.1 thorpej sz = coefficientSizes[num];
346 1.1 thorpej ofs = 0;
347 1.1 thorpej while (num-- > 0)
348 1.1 thorpej ofs+= coefficientSizes[num];
349 1.1 thorpej for (i = 0; i < sz; i++)
350 1.1 thorpej nm_wrbuf_1(sc, sc->cbuf + i, coefficients[ofs + i]);
351 1.1 thorpej nm_wr_4(sc, addr, sc->cbuf);
352 1.1 thorpej if (dir == AUMODE_PLAY)
353 1.1 thorpej sz--;
354 1.1 thorpej nm_wr_4(sc, addr + 4, sc->cbuf + sz);
355 1.1 thorpej return 0;
356 1.1 thorpej }
357 1.1 thorpej
358 1.1 thorpej /* The interrupt handler */
359 1.1 thorpej int
360 1.1 thorpej neo_intr(void *p)
361 1.1 thorpej {
362 1.1 thorpej struct neo_softc *sc = (struct neo_softc *)p;
363 1.20 simonb int status, x;
364 1.1 thorpej int rv = 0;
365 1.1 thorpej
366 1.1 thorpej status = (sc->irsz == 2) ?
367 1.1 thorpej nm_rd_2(sc, NM_INT_REG) :
368 1.1 thorpej nm_rd_4(sc, NM_INT_REG);
369 1.1 thorpej
370 1.1 thorpej if (status & sc->playint) {
371 1.1 thorpej status &= ~sc->playint;
372 1.1 thorpej
373 1.1 thorpej sc->pwmark += sc->pblksize;
374 1.1 thorpej sc->pwmark %= sc->pbufsize;
375 1.1 thorpej
376 1.1 thorpej nm_wr_4(sc, NM_PBUFFER_WMARK, sc->pbuf + sc->pwmark);
377 1.1 thorpej
378 1.1 thorpej nm_ackint(sc, sc->playint);
379 1.1 thorpej
380 1.1 thorpej if (sc->pintr)
381 1.1 thorpej (*sc->pintr)(sc->parg);
382 1.1 thorpej
383 1.1 thorpej rv = 1;
384 1.1 thorpej }
385 1.1 thorpej if (status & sc->recint) {
386 1.1 thorpej status &= ~sc->recint;
387 1.1 thorpej
388 1.1 thorpej sc->rwmark += sc->rblksize;
389 1.1 thorpej sc->rwmark %= sc->rbufsize;
390 1.1 thorpej
391 1.1 thorpej nm_ackint(sc, sc->recint);
392 1.1 thorpej if (sc->rintr)
393 1.1 thorpej (*sc->rintr)(sc->rarg);
394 1.1 thorpej
395 1.1 thorpej rv = 1;
396 1.1 thorpej }
397 1.1 thorpej if (status & sc->misc1int) {
398 1.1 thorpej status &= ~sc->misc1int;
399 1.1 thorpej nm_ackint(sc, sc->misc1int);
400 1.1 thorpej x = nm_rd_1(sc, 0x400);
401 1.1 thorpej nm_wr_1(sc, 0x400, x | 2);
402 1.1 thorpej printf("%s: misc int 1\n", sc->dev.dv_xname);
403 1.1 thorpej rv = 1;
404 1.1 thorpej }
405 1.1 thorpej if (status & sc->misc2int) {
406 1.1 thorpej status &= ~sc->misc2int;
407 1.1 thorpej nm_ackint(sc, sc->misc2int);
408 1.1 thorpej x = nm_rd_1(sc, 0x400);
409 1.1 thorpej nm_wr_1(sc, 0x400, x & ~2);
410 1.1 thorpej printf("%s: misc int 2\n", sc->dev.dv_xname);
411 1.1 thorpej rv = 1;
412 1.1 thorpej }
413 1.1 thorpej if (status) {
414 1.1 thorpej status &= ~sc->misc2int;
415 1.1 thorpej nm_ackint(sc, sc->misc2int);
416 1.1 thorpej printf("%s: unknown int\n", sc->dev.dv_xname);
417 1.1 thorpej rv = 1;
418 1.1 thorpej }
419 1.1 thorpej
420 1.1 thorpej return (rv);
421 1.1 thorpej }
422 1.1 thorpej
423 1.1 thorpej /* -------------------------------------------------------------------- */
424 1.1 thorpej
425 1.1 thorpej /*
426 1.1 thorpej * Probe and attach the card
427 1.1 thorpej */
428 1.1 thorpej
429 1.1 thorpej static int
430 1.1 thorpej nm_init(struct neo_softc *sc)
431 1.1 thorpej {
432 1.1 thorpej u_int32_t ofs, i;
433 1.1 thorpej
434 1.1 thorpej switch (sc->type) {
435 1.1 thorpej case PCI_PRODUCT_NEOMAGIC_NMMM256AV_AU:
436 1.1 thorpej sc->ac97_base = NM_MIXER_OFFSET;
437 1.1 thorpej sc->ac97_status = NM_MIXER_STATUS_OFFSET;
438 1.1 thorpej sc->ac97_busy = NM_MIXER_READY_MASK;
439 1.1 thorpej
440 1.1 thorpej sc->buftop = 2560 * 1024;
441 1.1 thorpej
442 1.1 thorpej sc->irsz = 2;
443 1.1 thorpej sc->playint = NM_PLAYBACK_INT;
444 1.1 thorpej sc->recint = NM_RECORD_INT;
445 1.1 thorpej sc->misc1int = NM_MISC_INT_1;
446 1.1 thorpej sc->misc2int = NM_MISC_INT_2;
447 1.1 thorpej break;
448 1.1 thorpej
449 1.1 thorpej case PCI_PRODUCT_NEOMAGIC_NMMM256ZX_AU:
450 1.1 thorpej sc->ac97_base = NM_MIXER_OFFSET;
451 1.1 thorpej sc->ac97_status = NM2_MIXER_STATUS_OFFSET;
452 1.1 thorpej sc->ac97_busy = NM2_MIXER_READY_MASK;
453 1.1 thorpej
454 1.1 thorpej sc->buftop = (nm_rd_2(sc, 0xa0b) ? 6144 : 4096) * 1024;
455 1.1 thorpej
456 1.1 thorpej sc->irsz = 4;
457 1.1 thorpej sc->playint = NM2_PLAYBACK_INT;
458 1.1 thorpej sc->recint = NM2_RECORD_INT;
459 1.1 thorpej sc->misc1int = NM2_MISC_INT_1;
460 1.1 thorpej sc->misc2int = NM2_MISC_INT_2;
461 1.1 thorpej break;
462 1.1 thorpej #ifdef DIAGNOSTIC
463 1.1 thorpej default:
464 1.1 thorpej panic("nm_init: impossible");
465 1.1 thorpej #endif
466 1.1 thorpej }
467 1.1 thorpej
468 1.1 thorpej sc->badintr = 0;
469 1.1 thorpej ofs = sc->buftop - 0x0400;
470 1.1 thorpej sc->buftop -= 0x1400;
471 1.1 thorpej
472 1.1 thorpej if ((nm_rdbuf_4(sc, ofs) & NM_SIG_MASK) == NM_SIGNATURE) {
473 1.1 thorpej i = nm_rdbuf_4(sc, ofs + 4);
474 1.1 thorpej if (i != 0 && i != 0xffffffff)
475 1.1 thorpej sc->buftop = i;
476 1.1 thorpej }
477 1.1 thorpej
478 1.1 thorpej sc->cbuf = sc->buftop - NM_MAX_COEFFICIENT;
479 1.1 thorpej sc->rbuf = sc->cbuf - NM_BUFFSIZE;
480 1.1 thorpej sc->pbuf = sc->rbuf - NM_BUFFSIZE;
481 1.1 thorpej sc->acbuf = sc->pbuf - (NM_TOTAL_COEFF_COUNT * 4);
482 1.1 thorpej
483 1.1 thorpej sc->buf_vaddr = (vaddr_t) bus_space_vaddr(sc->bufiot, sc->bufioh);
484 1.1 thorpej sc->rbuf_vaddr = sc->buf_vaddr + sc->rbuf;
485 1.1 thorpej sc->pbuf_vaddr = sc->buf_vaddr + sc->pbuf;
486 1.1 thorpej
487 1.3 thorpej sc->rbuf_pciaddr = sc->buf_pciaddr + sc->rbuf;
488 1.3 thorpej sc->pbuf_pciaddr = sc->buf_pciaddr + sc->pbuf;
489 1.3 thorpej
490 1.1 thorpej nm_wr_1(sc, 0, 0x11);
491 1.1 thorpej nm_wr_1(sc, NM_RECORD_ENABLE_REG, 0);
492 1.1 thorpej nm_wr_2(sc, 0x214, 0);
493 1.1 thorpej
494 1.1 thorpej return 0;
495 1.1 thorpej }
496 1.1 thorpej
497 1.2 thorpej int
498 1.2 thorpej neo_match(struct device *parent, struct cfdata *match, void *aux)
499 1.2 thorpej {
500 1.2 thorpej struct pci_attach_args *pa = aux;
501 1.2 thorpej pcireg_t subdev;
502 1.2 thorpej
503 1.2 thorpej if (PCI_VENDOR(pa->pa_id) != PCI_VENDOR_NEOMAGIC)
504 1.2 thorpej return (0);
505 1.2 thorpej
506 1.2 thorpej subdev = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_SUBSYS_ID_REG);
507 1.2 thorpej
508 1.2 thorpej switch (PCI_PRODUCT(pa->pa_id)) {
509 1.2 thorpej case PCI_PRODUCT_NEOMAGIC_NMMM256AV_AU:
510 1.2 thorpej /*
511 1.2 thorpej * We have to weed-out the non-AC'97 versions of
512 1.2 thorpej * the chip (i.e. the ones that are known to work
513 1.2 thorpej * in WSS emulation mode), as they won't work with
514 1.2 thorpej * this driver.
515 1.2 thorpej */
516 1.2 thorpej switch (PCI_VENDOR(subdev)) {
517 1.2 thorpej case PCI_VENDOR_DELL:
518 1.2 thorpej switch (PCI_PRODUCT(subdev)) {
519 1.2 thorpej case 0x008f:
520 1.2 thorpej return (0);
521 1.2 thorpej }
522 1.2 thorpej break;
523 1.2 thorpej
524 1.2 thorpej case PCI_VENDOR_HP:
525 1.2 thorpej switch (PCI_PRODUCT(subdev)) {
526 1.2 thorpej case 0x0007:
527 1.2 thorpej return (0);
528 1.2 thorpej }
529 1.8 drochner break;
530 1.8 drochner
531 1.8 drochner case PCI_VENDOR_IBM:
532 1.8 drochner switch (PCI_PRODUCT(subdev)) {
533 1.8 drochner case 0x00dd:
534 1.8 drochner return (0);
535 1.8 drochner }
536 1.8 drochner break;
537 1.2 thorpej }
538 1.2 thorpej return (1);
539 1.2 thorpej
540 1.2 thorpej case PCI_PRODUCT_NEOMAGIC_NMMM256ZX_AU:
541 1.2 thorpej return (1);
542 1.2 thorpej }
543 1.2 thorpej
544 1.2 thorpej return (0);
545 1.2 thorpej }
546 1.2 thorpej
547 1.1 thorpej void
548 1.5 sommerfe neo_power(int why, void *addr)
549 1.5 sommerfe {
550 1.5 sommerfe struct neo_softc *sc = (struct neo_softc *)addr;
551 1.5 sommerfe
552 1.5 sommerfe if (why == PWR_RESUME) {
553 1.5 sommerfe nm_init(sc);
554 1.5 sommerfe (sc->codec_if->vtbl->restore_ports)(sc->codec_if);
555 1.5 sommerfe }
556 1.5 sommerfe }
557 1.5 sommerfe
558 1.5 sommerfe void
559 1.1 thorpej neo_attach(struct device *parent, struct device *self, void *aux)
560 1.1 thorpej {
561 1.1 thorpej struct neo_softc *sc = (struct neo_softc *)self;
562 1.1 thorpej struct pci_attach_args *pa = (struct pci_attach_args *)aux;
563 1.1 thorpej pci_chipset_tag_t pc = pa->pa_pc;
564 1.1 thorpej char const *intrstr;
565 1.1 thorpej pci_intr_handle_t ih;
566 1.1 thorpej pcireg_t csr;
567 1.1 thorpej
568 1.1 thorpej sc->type = PCI_PRODUCT(pa->pa_id);
569 1.1 thorpej
570 1.1 thorpej printf(": NeoMagic 256%s audio\n",
571 1.1 thorpej sc->type == PCI_PRODUCT_NEOMAGIC_NMMM256AV_AU ? "AV" : "ZX");
572 1.1 thorpej
573 1.1 thorpej /* Map I/O register */
574 1.1 thorpej if (pci_mapreg_map(pa, PCI_MAPREG_START, PCI_MAPREG_TYPE_MEM, 0,
575 1.3 thorpej &sc->bufiot, &sc->bufioh, &sc->buf_pciaddr, NULL)) {
576 1.1 thorpej printf("%s: can't map buffer\n", sc->dev.dv_xname);
577 1.1 thorpej return;
578 1.1 thorpej }
579 1.1 thorpej
580 1.13 thorpej if (pci_mapreg_map(pa, PCI_MAPREG_START + 4, PCI_MAPREG_TYPE_MEM,
581 1.13 thorpej BUS_SPACE_MAP_LINEAR, &sc->regiot, &sc->regioh, NULL, NULL)) {
582 1.1 thorpej printf("%s: can't map registers\n", sc->dev.dv_xname);
583 1.1 thorpej return;
584 1.1 thorpej }
585 1.1 thorpej
586 1.1 thorpej /* Map and establish the interrupt. */
587 1.7 sommerfe if (pci_intr_map(pa, &ih)) {
588 1.1 thorpej printf("%s: couldn't map interrupt\n", sc->dev.dv_xname);
589 1.1 thorpej return;
590 1.1 thorpej }
591 1.1 thorpej
592 1.1 thorpej intrstr = pci_intr_string(pc, ih);
593 1.1 thorpej sc->ih = pci_intr_establish(pc, ih, IPL_AUDIO, neo_intr, sc);
594 1.1 thorpej
595 1.1 thorpej if (sc->ih == NULL) {
596 1.1 thorpej printf("%s: couldn't establish interrupt",
597 1.1 thorpej sc->dev.dv_xname);
598 1.1 thorpej if (intrstr != NULL)
599 1.1 thorpej printf(" at %s", intrstr);
600 1.1 thorpej printf("\n");
601 1.1 thorpej return;
602 1.1 thorpej }
603 1.1 thorpej printf("%s: interruping at %s\n", sc->dev.dv_xname, intrstr);
604 1.1 thorpej
605 1.20 simonb if (nm_init(sc) != 0)
606 1.1 thorpej return;
607 1.1 thorpej
608 1.1 thorpej /* Enable the device. */
609 1.1 thorpej csr = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG);
610 1.1 thorpej pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG,
611 1.1 thorpej csr | PCI_COMMAND_MASTER_ENABLE);
612 1.1 thorpej
613 1.1 thorpej sc->host_if.arg = sc;
614 1.1 thorpej
615 1.1 thorpej sc->host_if.attach = neo_attach_codec;
616 1.1 thorpej sc->host_if.read = neo_read_codec;
617 1.1 thorpej sc->host_if.write = neo_write_codec;
618 1.1 thorpej sc->host_if.reset = neo_reset_codec;
619 1.1 thorpej sc->host_if.flags = neo_flags_codec;
620 1.1 thorpej
621 1.25 kent if (ac97_attach(&sc->host_if, self) != 0)
622 1.1 thorpej return;
623 1.5 sommerfe
624 1.5 sommerfe sc->powerhook = powerhook_establish(neo_power, sc);
625 1.1 thorpej
626 1.1 thorpej audio_attach_mi(&neo_hw_if, sc, &sc->dev);
627 1.1 thorpej }
628 1.1 thorpej
629 1.1 thorpej int
630 1.1 thorpej neo_read_codec(void *v, u_int8_t a, u_int16_t *d)
631 1.1 thorpej {
632 1.1 thorpej struct neo_softc *sc = v;
633 1.1 thorpej
634 1.1 thorpej if (!nm_waitcd(sc)) {
635 1.1 thorpej *d = nm_rd_2(sc, sc->ac97_base + a);
636 1.1 thorpej DELAY(1000);
637 1.1 thorpej return 0;
638 1.1 thorpej }
639 1.1 thorpej
640 1.1 thorpej return (ENXIO);
641 1.1 thorpej }
642 1.1 thorpej
643 1.1 thorpej
644 1.1 thorpej int
645 1.1 thorpej neo_write_codec(void *v, u_int8_t a, u_int16_t d)
646 1.1 thorpej {
647 1.1 thorpej struct neo_softc *sc = v;
648 1.1 thorpej int cnt = 3;
649 1.1 thorpej
650 1.1 thorpej if (!nm_waitcd(sc)) {
651 1.1 thorpej while (cnt-- > 0) {
652 1.1 thorpej nm_wr_2(sc, sc->ac97_base + a, d);
653 1.1 thorpej if (!nm_waitcd(sc)) {
654 1.1 thorpej DELAY(1000);
655 1.1 thorpej return (0);
656 1.1 thorpej }
657 1.1 thorpej }
658 1.1 thorpej }
659 1.1 thorpej
660 1.1 thorpej return (ENXIO);
661 1.1 thorpej }
662 1.1 thorpej
663 1.1 thorpej int
664 1.1 thorpej neo_attach_codec(void *v, struct ac97_codec_if *codec_if)
665 1.1 thorpej {
666 1.1 thorpej struct neo_softc *sc = v;
667 1.1 thorpej
668 1.1 thorpej sc->codec_if = codec_if;
669 1.1 thorpej return (0);
670 1.1 thorpej }
671 1.1 thorpej
672 1.23 kent int
673 1.1 thorpej neo_reset_codec(void *v)
674 1.1 thorpej {
675 1.1 thorpej struct neo_softc *sc = v;
676 1.1 thorpej
677 1.1 thorpej nm_wr_1(sc, 0x6c0, 0x01);
678 1.1 thorpej nm_wr_1(sc, 0x6cc, 0x87);
679 1.1 thorpej nm_wr_1(sc, 0x6cc, 0x80);
680 1.1 thorpej nm_wr_1(sc, 0x6cc, 0x00);
681 1.23 kent return 0;
682 1.1 thorpej }
683 1.1 thorpej
684 1.1 thorpej enum ac97_host_flags
685 1.1 thorpej neo_flags_codec(void *v)
686 1.1 thorpej {
687 1.1 thorpej
688 1.1 thorpej return (AC97_HOST_DONT_READ);
689 1.1 thorpej }
690 1.1 thorpej
691 1.1 thorpej int
692 1.1 thorpej neo_query_encoding(void *addr, struct audio_encoding *fp)
693 1.1 thorpej {
694 1.1 thorpej
695 1.1 thorpej switch (fp->index) {
696 1.1 thorpej case 0:
697 1.1 thorpej strcpy(fp->name, AudioEulinear);
698 1.1 thorpej fp->encoding = AUDIO_ENCODING_ULINEAR;
699 1.1 thorpej fp->precision = 8;
700 1.1 thorpej fp->flags = 0;
701 1.1 thorpej return (0);
702 1.1 thorpej case 1:
703 1.1 thorpej strcpy(fp->name, AudioEmulaw);
704 1.1 thorpej fp->encoding = AUDIO_ENCODING_ULAW;
705 1.1 thorpej fp->precision = 8;
706 1.1 thorpej fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
707 1.1 thorpej return (0);
708 1.1 thorpej case 2:
709 1.1 thorpej strcpy(fp->name, AudioEalaw);
710 1.1 thorpej fp->encoding = AUDIO_ENCODING_ALAW;
711 1.1 thorpej fp->precision = 8;
712 1.1 thorpej fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
713 1.1 thorpej return (0);
714 1.1 thorpej case 3:
715 1.1 thorpej strcpy(fp->name, AudioEslinear);
716 1.1 thorpej fp->encoding = AUDIO_ENCODING_SLINEAR;
717 1.1 thorpej fp->precision = 8;
718 1.1 thorpej fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
719 1.1 thorpej return (0);
720 1.1 thorpej case 4:
721 1.1 thorpej strcpy(fp->name, AudioEslinear_le);
722 1.1 thorpej fp->encoding = AUDIO_ENCODING_SLINEAR_LE;
723 1.1 thorpej fp->precision = 16;
724 1.1 thorpej fp->flags = 0;
725 1.1 thorpej return (0);
726 1.1 thorpej case 5:
727 1.1 thorpej strcpy(fp->name, AudioEulinear_le);
728 1.1 thorpej fp->encoding = AUDIO_ENCODING_ULINEAR_LE;
729 1.1 thorpej fp->precision = 16;
730 1.1 thorpej fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
731 1.1 thorpej return (0);
732 1.1 thorpej case 6:
733 1.1 thorpej strcpy(fp->name, AudioEslinear_be);
734 1.1 thorpej fp->encoding = AUDIO_ENCODING_SLINEAR_BE;
735 1.1 thorpej fp->precision = 16;
736 1.1 thorpej fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
737 1.1 thorpej return (0);
738 1.1 thorpej case 7:
739 1.1 thorpej strcpy(fp->name, AudioEulinear_be);
740 1.1 thorpej fp->encoding = AUDIO_ENCODING_ULINEAR_BE;
741 1.1 thorpej fp->precision = 16;
742 1.1 thorpej fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
743 1.1 thorpej return (0);
744 1.1 thorpej default:
745 1.1 thorpej return (EINVAL);
746 1.1 thorpej }
747 1.1 thorpej }
748 1.1 thorpej
749 1.1 thorpej /* Todo: don't commit settings to card until we've verified all parameters */
750 1.1 thorpej int
751 1.25 kent neo_set_params(void *addr, int setmode, int usemode, audio_params_t *play,
752 1.25 kent audio_params_t *rec, stream_filter_list_t *pfil, stream_filter_list_t *rfil)
753 1.1 thorpej {
754 1.1 thorpej struct neo_softc *sc = addr;
755 1.25 kent audio_params_t *p;
756 1.25 kent stream_filter_list_t *fil;
757 1.1 thorpej u_int32_t base;
758 1.1 thorpej u_int8_t x;
759 1.25 kent int mode, i;
760 1.1 thorpej
761 1.1 thorpej for (mode = AUMODE_RECORD; mode != -1;
762 1.1 thorpej mode = mode == AUMODE_RECORD ? AUMODE_PLAY : -1) {
763 1.1 thorpej if ((setmode & mode) == 0)
764 1.1 thorpej continue;
765 1.1 thorpej
766 1.1 thorpej p = mode == AUMODE_PLAY ? play : rec;
767 1.1 thorpej
768 1.1 thorpej if (p == NULL) continue;
769 1.1 thorpej
770 1.1 thorpej for (x = 0; x < 8; x++) {
771 1.1 thorpej if (p->sample_rate <
772 1.1 thorpej (samplerates[x] + samplerates[x + 1]) / 2)
773 1.1 thorpej break;
774 1.1 thorpej }
775 1.1 thorpej if (x == 8)
776 1.1 thorpej return (EINVAL);
777 1.1 thorpej
778 1.1 thorpej p->sample_rate = samplerates[x];
779 1.1 thorpej nm_loadcoeff(sc, mode, x);
780 1.1 thorpej
781 1.1 thorpej x <<= 4;
782 1.1 thorpej x &= NM_RATE_MASK;
783 1.1 thorpej if (p->precision == 16)
784 1.1 thorpej x |= NM_RATE_BITS_16;
785 1.1 thorpej if (p->channels == 2)
786 1.1 thorpej x |= NM_RATE_STEREO;
787 1.1 thorpej
788 1.1 thorpej base = (mode == AUMODE_PLAY)?
789 1.1 thorpej NM_PLAYBACK_REG_OFFSET : NM_RECORD_REG_OFFSET;
790 1.1 thorpej nm_wr_1(sc, base + NM_RATE_REG_OFFSET, x);
791 1.25 kent
792 1.25 kent fil = mode == AUMODE_PLAY ? pfil : rfil;
793 1.25 kent i = auconv_set_converter(neo_formats, NEO_NFORMATS,
794 1.25 kent mode, p, FALSE, fil);
795 1.25 kent if (i < 0)
796 1.25 kent return EINVAL;
797 1.1 thorpej }
798 1.1 thorpej
799 1.1 thorpej
800 1.1 thorpej return (0);
801 1.1 thorpej }
802 1.1 thorpej
803 1.1 thorpej int
804 1.25 kent neo_round_blocksize(void *addr, int blk, int mode, const audio_params_t *param)
805 1.1 thorpej {
806 1.1 thorpej
807 1.25 kent return (NM_BUFFSIZE / 2);
808 1.1 thorpej }
809 1.1 thorpej
810 1.1 thorpej int
811 1.1 thorpej neo_trigger_output(void *addr, void *start, void *end, int blksize,
812 1.25 kent void (*intr)(void *), void *arg, const audio_params_t *param)
813 1.1 thorpej {
814 1.1 thorpej struct neo_softc *sc = addr;
815 1.1 thorpej int ssz;
816 1.1 thorpej
817 1.1 thorpej sc->pintr = intr;
818 1.1 thorpej sc->parg = arg;
819 1.1 thorpej
820 1.25 kent ssz = (param->precision == 16) ? 2 : 1;
821 1.1 thorpej if (param->channels == 2)
822 1.1 thorpej ssz <<= 1;
823 1.1 thorpej
824 1.1 thorpej sc->pbufsize = ((char*)end - (char *)start);
825 1.1 thorpej sc->pblksize = blksize;
826 1.1 thorpej sc->pwmark = blksize;
827 1.1 thorpej
828 1.1 thorpej nm_wr_4(sc, NM_PBUFFER_START, sc->pbuf);
829 1.1 thorpej nm_wr_4(sc, NM_PBUFFER_END, sc->pbuf + sc->pbufsize - ssz);
830 1.1 thorpej nm_wr_4(sc, NM_PBUFFER_CURRP, sc->pbuf);
831 1.1 thorpej nm_wr_4(sc, NM_PBUFFER_WMARK, sc->pbuf + sc->pwmark);
832 1.1 thorpej nm_wr_1(sc, NM_PLAYBACK_ENABLE_REG, NM_PLAYBACK_FREERUN |
833 1.1 thorpej NM_PLAYBACK_ENABLE_FLAG);
834 1.1 thorpej nm_wr_2(sc, NM_AUDIO_MUTE_REG, 0);
835 1.1 thorpej
836 1.1 thorpej return (0);
837 1.1 thorpej }
838 1.1 thorpej
839 1.1 thorpej int
840 1.1 thorpej neo_trigger_input(void *addr, void *start, void *end, int blksize,
841 1.25 kent void (*intr)(void *), void *arg, const audio_params_t *param)
842 1.1 thorpej {
843 1.25 kent struct neo_softc *sc = addr;
844 1.1 thorpej int ssz;
845 1.1 thorpej
846 1.1 thorpej sc->rintr = intr;
847 1.1 thorpej sc->rarg = arg;
848 1.1 thorpej
849 1.25 kent ssz = (param->precision == 16) ? 2 : 1;
850 1.1 thorpej if (param->channels == 2)
851 1.1 thorpej ssz <<= 1;
852 1.1 thorpej
853 1.1 thorpej sc->rbufsize = ((char*)end - (char *)start);
854 1.1 thorpej sc->rblksize = blksize;
855 1.1 thorpej sc->rwmark = blksize;
856 1.1 thorpej
857 1.1 thorpej nm_wr_4(sc, NM_RBUFFER_START, sc->rbuf);
858 1.1 thorpej nm_wr_4(sc, NM_RBUFFER_END, sc->rbuf + sc->rbufsize);
859 1.1 thorpej nm_wr_4(sc, NM_RBUFFER_CURRP, sc->rbuf);
860 1.1 thorpej nm_wr_4(sc, NM_RBUFFER_WMARK, sc->rbuf + sc->rwmark);
861 1.1 thorpej nm_wr_1(sc, NM_RECORD_ENABLE_REG, NM_RECORD_FREERUN |
862 1.1 thorpej NM_RECORD_ENABLE_FLAG);
863 1.1 thorpej
864 1.1 thorpej return (0);
865 1.1 thorpej }
866 1.1 thorpej
867 1.1 thorpej int
868 1.1 thorpej neo_halt_output(void *addr)
869 1.1 thorpej {
870 1.1 thorpej struct neo_softc *sc = (struct neo_softc *)addr;
871 1.1 thorpej
872 1.1 thorpej nm_wr_1(sc, NM_PLAYBACK_ENABLE_REG, 0);
873 1.1 thorpej nm_wr_2(sc, NM_AUDIO_MUTE_REG, NM_AUDIO_MUTE_BOTH);
874 1.22 mycroft sc->pintr = 0;
875 1.1 thorpej
876 1.1 thorpej return (0);
877 1.1 thorpej }
878 1.1 thorpej
879 1.1 thorpej int
880 1.1 thorpej neo_halt_input(void *addr)
881 1.1 thorpej {
882 1.1 thorpej struct neo_softc *sc = (struct neo_softc *)addr;
883 1.1 thorpej
884 1.1 thorpej nm_wr_1(sc, NM_RECORD_ENABLE_REG, 0);
885 1.22 mycroft sc->rintr = 0;
886 1.1 thorpej
887 1.1 thorpej return (0);
888 1.1 thorpej }
889 1.1 thorpej
890 1.1 thorpej int
891 1.1 thorpej neo_getdev(void *addr, struct audio_device *retp)
892 1.1 thorpej {
893 1.1 thorpej
894 1.1 thorpej *retp = neo_device;
895 1.1 thorpej return (0);
896 1.1 thorpej }
897 1.1 thorpej
898 1.1 thorpej int
899 1.1 thorpej neo_mixer_set_port(void *addr, mixer_ctrl_t *cp)
900 1.1 thorpej {
901 1.1 thorpej struct neo_softc *sc = addr;
902 1.1 thorpej
903 1.1 thorpej return ((sc->codec_if->vtbl->mixer_set_port)(sc->codec_if, cp));
904 1.1 thorpej }
905 1.1 thorpej
906 1.1 thorpej int
907 1.1 thorpej neo_mixer_get_port(void *addr, mixer_ctrl_t *cp)
908 1.1 thorpej {
909 1.1 thorpej struct neo_softc *sc = addr;
910 1.1 thorpej
911 1.1 thorpej return ((sc->codec_if->vtbl->mixer_get_port)(sc->codec_if, cp));
912 1.1 thorpej }
913 1.1 thorpej
914 1.1 thorpej int
915 1.1 thorpej neo_query_devinfo(void *addr, mixer_devinfo_t *dip)
916 1.1 thorpej {
917 1.1 thorpej struct neo_softc *sc = addr;
918 1.1 thorpej
919 1.1 thorpej return ((sc->codec_if->vtbl->query_devinfo)(sc->codec_if, dip));
920 1.1 thorpej }
921 1.1 thorpej
922 1.1 thorpej void *
923 1.17 thorpej neo_malloc(void *addr, int direction, size_t size, struct malloc_type *pool,
924 1.17 thorpej int flags)
925 1.1 thorpej {
926 1.1 thorpej struct neo_softc *sc = addr;
927 1.1 thorpej void *rv = NULL;
928 1.1 thorpej
929 1.1 thorpej switch (direction) {
930 1.1 thorpej case AUMODE_PLAY:
931 1.1 thorpej if (sc->pbuf_allocated == 0) {
932 1.1 thorpej rv = (void *) sc->pbuf_vaddr;
933 1.1 thorpej sc->pbuf_allocated = 1;
934 1.1 thorpej }
935 1.1 thorpej break;
936 1.1 thorpej
937 1.1 thorpej case AUMODE_RECORD:
938 1.1 thorpej if (sc->rbuf_allocated == 0) {
939 1.1 thorpej rv = (void *) sc->rbuf_vaddr;
940 1.1 thorpej sc->rbuf_allocated = 1;
941 1.1 thorpej }
942 1.1 thorpej break;
943 1.1 thorpej }
944 1.1 thorpej
945 1.1 thorpej return (rv);
946 1.1 thorpej }
947 1.1 thorpej
948 1.1 thorpej void
949 1.17 thorpej neo_free(void *addr, void *ptr, struct malloc_type *pool)
950 1.1 thorpej {
951 1.1 thorpej struct neo_softc *sc = addr;
952 1.1 thorpej vaddr_t v = (vaddr_t) ptr;
953 1.1 thorpej
954 1.1 thorpej if (v == sc->pbuf_vaddr)
955 1.1 thorpej sc->pbuf_allocated = 0;
956 1.1 thorpej else if (v == sc->rbuf_vaddr)
957 1.1 thorpej sc->rbuf_allocated = 0;
958 1.1 thorpej else
959 1.1 thorpej printf("neo_free: bad address %p\n", ptr);
960 1.1 thorpej }
961 1.1 thorpej
962 1.1 thorpej size_t
963 1.1 thorpej neo_round_buffersize(void *addr, int direction, size_t size)
964 1.1 thorpej {
965 1.1 thorpej
966 1.1 thorpej return (NM_BUFFSIZE);
967 1.1 thorpej }
968 1.1 thorpej
969 1.3 thorpej paddr_t
970 1.3 thorpej neo_mappage(void *addr, void *mem, off_t off, int prot)
971 1.3 thorpej {
972 1.3 thorpej struct neo_softc *sc = addr;
973 1.3 thorpej vaddr_t v = (vaddr_t) mem;
974 1.3 thorpej bus_addr_t pciaddr;
975 1.3 thorpej
976 1.3 thorpej if (v == sc->pbuf_vaddr)
977 1.3 thorpej pciaddr = sc->pbuf_pciaddr;
978 1.3 thorpej else if (v == sc->rbuf_vaddr)
979 1.3 thorpej pciaddr = sc->rbuf_pciaddr;
980 1.3 thorpej else
981 1.3 thorpej return (-1);
982 1.3 thorpej
983 1.9 thorpej return (bus_space_mmap(sc->bufiot, pciaddr, off, prot,
984 1.9 thorpej BUS_SPACE_MAP_LINEAR));
985 1.3 thorpej }
986 1.1 thorpej
987 1.1 thorpej int
988 1.1 thorpej neo_get_props(void *addr)
989 1.1 thorpej {
990 1.1 thorpej
991 1.3 thorpej return (AUDIO_PROP_INDEPENDENT | AUDIO_PROP_MMAP |
992 1.1 thorpej AUDIO_PROP_FULLDUPLEX);
993 1.1 thorpej }
994