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