Deleted Added
full compact
neomagic.c (55700) neomagic.c (55713)
1/*
2 * Copyright (c) 1999 Cameron Grant <gandalf@vilnya.demon.co.uk>
3 * All rights reserved.
4 *
5 * Derived from the public domain Linux driver
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHERIN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THEPOSSIBILITY OF
26 * SUCH DAMAGE.
27 *
1/*
2 * Copyright (c) 1999 Cameron Grant <gandalf@vilnya.demon.co.uk>
3 * All rights reserved.
4 *
5 * Derived from the public domain Linux driver
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHERIN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THEPOSSIBILITY OF
26 * SUCH DAMAGE.
27 *
28 * $FreeBSD: head/sys/dev/sound/pci/neomagic.c 55700 2000-01-10 01:59:12Z cg $
28 * $FreeBSD: head/sys/dev/sound/pci/neomagic.c 55713 2000-01-10 06:19:20Z cg $
29 */
30
31#include "pci.h"
32#include "pcm.h"
33
34#include <dev/sound/pcm/sound.h>
35#include <dev/sound/pcm/ac97.h>
36#include <dev/sound/pci/neomagic.h>
37#include <dev/sound/pci/neomagic-coeff.h>
38
39#include <pci/pcireg.h>
40#include <pci/pcivar.h>
41
42/* -------------------------------------------------------------------- */
43
44#define NM_BUFFSIZE 16384
45
46#define NM256AV_PCI_ID 0x800510c8
47#define NM256ZX_PCI_ID 0x800610c8
48
49struct sc_info;
50
51/* channel registers */
52struct sc_chinfo {
53 int spd, dir, fmt;
54 snd_dbuf *buffer;
55 pcm_channel *channel;
56 struct sc_info *parent;
57};
58
59/* device private data */
60struct sc_info {
61 device_t dev;
62 u_int32_t type;
63
64 struct resource *reg, *irq, *buf;
65 int regid, irqid, bufid;
66 void *ih;
67
68 u_int32_t ac97_base, ac97_status, ac97_busy;
69 u_int32_t buftop, pbuf, rbuf, cbuf, acbuf;
70 u_int32_t playint, recint, misc1int, misc2int;
71 u_int32_t irsz, badintr;
72
73 struct sc_chinfo pch, rch;
74};
75
76/* -------------------------------------------------------------------- */
77
78/*
79 * prototypes
80 */
81
82/* channel interface */
83static void *nmchan_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir);
84static int nmchan_setdir(void *data, int dir);
85static int nmchan_setformat(void *data, u_int32_t format);
86static int nmchan_setspeed(void *data, u_int32_t speed);
87static int nmchan_setblocksize(void *data, u_int32_t blocksize);
88static int nmchan_trigger(void *data, int go);
89static int nmchan_getptr(void *data);
90static pcmchan_caps *nmchan_getcaps(void *data);
91
92static int nm_waitcd(struct sc_info *sc);
93/* talk to the codec - called from ac97.c */
94static u_int32_t nm_rdcd(void *, int);
95static void nm_wrcd(void *, int, u_int32_t);
96
97/* stuff */
98static int nm_loadcoeff(struct sc_info *sc, int dir, int num);
99static int nm_setch(struct sc_chinfo *ch);
100static int nm_init(struct sc_info *);
101static void nm_intr(void *);
102
103/* talk to the card */
104static u_int32_t nm_rd(struct sc_info *, int, int);
105static void nm_wr(struct sc_info *, int, u_int32_t, int);
106static u_int32_t nm_rdbuf(struct sc_info *, int, int);
107static void nm_wrbuf(struct sc_info *, int, u_int32_t, int);
108
109/* The actual rates supported by the card. */
110static int samplerates[9] = {
111 8000, 11025, 16000, 22050, 24000, 32000, 44100, 48000, 99999999
112};
113
114/* -------------------------------------------------------------------- */
115
116static pcmchan_caps nm_caps = {
117 4000, 48000,
118 AFMT_STEREO | AFMT_U8 | AFMT_S16_LE,
119 AFMT_STEREO | AFMT_S16_LE
120};
121
122static pcm_channel nm_chantemplate = {
123 nmchan_init,
124 nmchan_setdir,
125 nmchan_setformat,
126 nmchan_setspeed,
127 nmchan_setblocksize,
128 nmchan_trigger,
129 nmchan_getptr,
130 nmchan_getcaps,
131};
132
133/* -------------------------------------------------------------------- */
134
135/* Hardware */
136static u_int32_t
137nm_rd(struct sc_info *sc, int regno, int size)
138{
139 bus_space_tag_t st = rman_get_bustag(sc->reg);
140 bus_space_handle_t sh = rman_get_bushandle(sc->reg);
141
142 switch (size) {
143 case 1:
144 return bus_space_read_1(st, sh, regno);
145 case 2:
146 return bus_space_read_2(st, sh, regno);
147 case 4:
148 return bus_space_read_4(st, sh, regno);
149 default:
150 return 0xffffffff;
151 }
152}
153
154static void
155nm_wr(struct sc_info *sc, int regno, u_int32_t data, int size)
156{
157 bus_space_tag_t st = rman_get_bustag(sc->reg);
158 bus_space_handle_t sh = rman_get_bushandle(sc->reg);
159
160 switch (size) {
161 case 1:
162 bus_space_write_1(st, sh, regno, data);
163 break;
164 case 2:
165 bus_space_write_2(st, sh, regno, data);
166 break;
167 case 4:
168 bus_space_write_4(st, sh, regno, data);
169 break;
170 }
171}
172
173static u_int32_t
174nm_rdbuf(struct sc_info *sc, int regno, int size)
175{
176 bus_space_tag_t st = rman_get_bustag(sc->buf);
177 bus_space_handle_t sh = rman_get_bushandle(sc->buf);
178
179 switch (size) {
180 case 1:
181 return bus_space_read_1(st, sh, regno);
182 case 2:
183 return bus_space_read_2(st, sh, regno);
184 case 4:
185 return bus_space_read_4(st, sh, regno);
186 default:
187 return 0xffffffff;
188 }
189}
190
191static void
192nm_wrbuf(struct sc_info *sc, int regno, u_int32_t data, int size)
193{
194 bus_space_tag_t st = rman_get_bustag(sc->buf);
195 bus_space_handle_t sh = rman_get_bushandle(sc->buf);
196
197 switch (size) {
198 case 1:
199 bus_space_write_1(st, sh, regno, data);
200 break;
201 case 2:
202 bus_space_write_2(st, sh, regno, data);
203 break;
204 case 4:
205 bus_space_write_4(st, sh, regno, data);
206 break;
207 }
208}
209
210/* ac97 codec */
211static int
212nm_waitcd(struct sc_info *sc)
213{
214 int cnt = 10;
215
216 while (cnt-- > 0) {
217 if (nm_rd(sc, sc->ac97_status, 2) & sc->ac97_busy)
218 DELAY(100);
219 else
220 break;
221 }
222 return (nm_rd(sc, sc->ac97_status, 2) & sc->ac97_busy);
223}
224
225static u_int32_t
226nm_rdcd(void *devinfo, int regno)
227{
228 struct sc_info *sc = (struct sc_info *)devinfo;
229 u_int32_t x;
230
231 if (!nm_waitcd(sc)) {
232 x = nm_rd(sc, sc->ac97_base + regno, 2);
233 DELAY(1000);
234 return x;
235 } else {
236 device_printf(sc->dev, "ac97 codec not ready\n");
237 return 0xffffffff;
238 }
239}
240
241static void
242nm_wrcd(void *devinfo, int regno, u_int32_t data)
243{
244 struct sc_info *sc = (struct sc_info *)devinfo;
245 int cnt = 3;
246
247 if (!nm_waitcd(sc)) {
248 while (cnt-- > 0) {
249 nm_wr(sc, sc->ac97_base + regno, data, 2);
250 if (!nm_waitcd(sc)) {
251 DELAY(1000);
252 return;
253 }
254 }
255 }
256 device_printf(sc->dev, "ac97 codec not ready\n");
257}
258
259static void
260nm_ackint(struct sc_info *sc, u_int32_t num)
261{
262 if (sc->type == NM256AV_PCI_ID) {
263 nm_wr(sc, NM_INT_REG, num << 1, 2);
264 } else if (sc->type == NM256ZX_PCI_ID) {
265 nm_wr(sc, NM_INT_REG, num, 4);
266 }
267}
268
269static int
270nm_loadcoeff(struct sc_info *sc, int dir, int num)
271{
272 int ofs, sz, i;
273 u_int32_t addr;
274
275 addr = (dir == PCMDIR_PLAY)? 0x01c : 0x21c;
276 if (dir == PCMDIR_REC)
277 num += 8;
278 sz = coefficientSizes[num];
279 ofs = 0;
280 while (num-- > 0)
281 ofs+= coefficientSizes[num];
282 for (i = 0; i < sz; i++)
283 nm_wrbuf(sc, sc->cbuf + i, coefficients[ofs + i], 1);
284 nm_wr(sc, addr, sc->cbuf, 4);
285 if (dir == PCMDIR_PLAY)
286 sz--;
287 nm_wr(sc, addr + 4, sc->cbuf + sz, 4);
288 return 0;
289}
290
291static int
292nm_setch(struct sc_chinfo *ch)
293{
294 struct sc_info *sc = ch->parent;
295 u_int32_t base;
296 u_int8_t x;
297
298 for (x = 0; x < 8; x++)
299 if (ch->spd < (samplerates[x] + samplerates[x + 1]) / 2)
300 break;
301
302 if (x == 8) return 1;
303
304 ch->spd = samplerates[x];
305 nm_loadcoeff(sc, ch->dir, x);
306
307 x <<= 4;
308 x &= NM_RATE_MASK;
309 if (ch->fmt & AFMT_16BIT) x |= NM_RATE_BITS_16;
310 if (ch->fmt & AFMT_STEREO) x |= NM_RATE_STEREO;
311
312 base = (ch->dir == PCMDIR_PLAY)? NM_PLAYBACK_REG_OFFSET : NM_RECORD_REG_OFFSET;
313 nm_wr(sc, base + NM_RATE_REG_OFFSET, x, 1);
314 return 0;
315}
316
317/* channel interface */
318static void *
319nmchan_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir)
320{
321 struct sc_info *sc = devinfo;
322 struct sc_chinfo *ch;
323 u_int32_t chnbuf;
324
325 chnbuf = (dir == PCMDIR_PLAY)? sc->pbuf : sc->rbuf;
326 ch = (dir == PCMDIR_PLAY)? &sc->pch : &sc->rch;
327 ch->buffer = b;
328 ch->buffer->bufsize = NM_BUFFSIZE;
329 ch->buffer->buf = (u_int8_t *)(rman_get_bushandle(sc->buf) + chnbuf);
330 device_printf(sc->dev, "%s buf %p\n", (dir == PCMDIR_PLAY)? "play" : "rec", ch->buffer->buf);
331 ch->parent = sc;
332 ch->channel = c;
333 ch->dir = dir;
334 return ch;
335}
336
337static int
338nmchan_setdir(void *data, int dir)
339{
340 return 0;
341}
342
343static int
344nmchan_setformat(void *data, u_int32_t format)
345{
346 struct sc_chinfo *ch = data;
347
348 ch->fmt = format;
349 return nm_setch(ch);
350}
351
352static int
353nmchan_setspeed(void *data, u_int32_t speed)
354{
355 struct sc_chinfo *ch = data;
356
357 ch->spd = speed;
358 return nm_setch(ch)? 0 : ch->spd;
359}
360
361static int
362nmchan_setblocksize(void *data, u_int32_t blocksize)
363{
364 return blocksize;
365}
366
367static int
368nmchan_trigger(void *data, int go)
369{
370 struct sc_chinfo *ch = data;
371 struct sc_info *sc = ch->parent;
372 int ssz;
373
374 if (go == PCMTRIG_EMLDMAWR) return 0;
375
376 ssz = (ch->fmt & AFMT_16BIT)? 2 : 1;
377 if (ch->fmt & AFMT_STEREO)
378 ssz <<= 1;
379
380 if (ch->dir == PCMDIR_PLAY) {
381 if (go == PCMTRIG_START) {
382 nm_wr(sc, NM_PBUFFER_START, sc->pbuf, 4);
383 nm_wr(sc, NM_PBUFFER_END, sc->pbuf + NM_BUFFSIZE - ssz, 4);
384 nm_wr(sc, NM_PBUFFER_CURRP, sc->pbuf, 4);
385 nm_wr(sc, NM_PBUFFER_WMARK, sc->pbuf + NM_BUFFSIZE / 2, 4);
386 nm_wr(sc, NM_PLAYBACK_ENABLE_REG, NM_PLAYBACK_FREERUN |
387 NM_PLAYBACK_ENABLE_FLAG, 1);
388 nm_wr(sc, NM_AUDIO_MUTE_REG, 0, 2);
389 } else {
390 nm_wr(sc, NM_PLAYBACK_ENABLE_REG, 0, 1);
391 nm_wr(sc, NM_AUDIO_MUTE_REG, NM_AUDIO_MUTE_BOTH, 2);
392 }
393 } else {
394 if (go == PCMTRIG_START) {
395 nm_wr(sc, NM_RECORD_ENABLE_REG, NM_RECORD_FREERUN |
396 NM_RECORD_ENABLE_FLAG, 1);
397 nm_wr(sc, NM_RBUFFER_START, sc->rbuf, 4);
398 nm_wr(sc, NM_RBUFFER_END, sc->rbuf + NM_BUFFSIZE, 4);
399 nm_wr(sc, NM_RBUFFER_CURRP, sc->rbuf, 4);
400 nm_wr(sc, NM_RBUFFER_WMARK, sc->rbuf + NM_BUFFSIZE / 2, 4);
401 } else {
402 nm_wr(sc, NM_RECORD_ENABLE_REG, 0, 1);
403 }
404 }
405 return 0;
406}
407
408static int
409nmchan_getptr(void *data)
410{
411 struct sc_chinfo *ch = data;
412 struct sc_info *sc = ch->parent;
413
414 if (ch->dir == PCMDIR_PLAY)
415 return nm_rd(sc, NM_PBUFFER_CURRP, 4) - sc->pbuf;
416 else
417 return nm_rd(sc, NM_RBUFFER_CURRP, 4) - sc->rbuf;
418}
419
420static pcmchan_caps *
421nmchan_getcaps(void *data)
422{
423 return &nm_caps;
424}
425
426/* The interrupt handler */
427static void
428nm_intr(void *p)
429{
430 struct sc_info *sc = (struct sc_info *)p;
29 */
30
31#include "pci.h"
32#include "pcm.h"
33
34#include <dev/sound/pcm/sound.h>
35#include <dev/sound/pcm/ac97.h>
36#include <dev/sound/pci/neomagic.h>
37#include <dev/sound/pci/neomagic-coeff.h>
38
39#include <pci/pcireg.h>
40#include <pci/pcivar.h>
41
42/* -------------------------------------------------------------------- */
43
44#define NM_BUFFSIZE 16384
45
46#define NM256AV_PCI_ID 0x800510c8
47#define NM256ZX_PCI_ID 0x800610c8
48
49struct sc_info;
50
51/* channel registers */
52struct sc_chinfo {
53 int spd, dir, fmt;
54 snd_dbuf *buffer;
55 pcm_channel *channel;
56 struct sc_info *parent;
57};
58
59/* device private data */
60struct sc_info {
61 device_t dev;
62 u_int32_t type;
63
64 struct resource *reg, *irq, *buf;
65 int regid, irqid, bufid;
66 void *ih;
67
68 u_int32_t ac97_base, ac97_status, ac97_busy;
69 u_int32_t buftop, pbuf, rbuf, cbuf, acbuf;
70 u_int32_t playint, recint, misc1int, misc2int;
71 u_int32_t irsz, badintr;
72
73 struct sc_chinfo pch, rch;
74};
75
76/* -------------------------------------------------------------------- */
77
78/*
79 * prototypes
80 */
81
82/* channel interface */
83static void *nmchan_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir);
84static int nmchan_setdir(void *data, int dir);
85static int nmchan_setformat(void *data, u_int32_t format);
86static int nmchan_setspeed(void *data, u_int32_t speed);
87static int nmchan_setblocksize(void *data, u_int32_t blocksize);
88static int nmchan_trigger(void *data, int go);
89static int nmchan_getptr(void *data);
90static pcmchan_caps *nmchan_getcaps(void *data);
91
92static int nm_waitcd(struct sc_info *sc);
93/* talk to the codec - called from ac97.c */
94static u_int32_t nm_rdcd(void *, int);
95static void nm_wrcd(void *, int, u_int32_t);
96
97/* stuff */
98static int nm_loadcoeff(struct sc_info *sc, int dir, int num);
99static int nm_setch(struct sc_chinfo *ch);
100static int nm_init(struct sc_info *);
101static void nm_intr(void *);
102
103/* talk to the card */
104static u_int32_t nm_rd(struct sc_info *, int, int);
105static void nm_wr(struct sc_info *, int, u_int32_t, int);
106static u_int32_t nm_rdbuf(struct sc_info *, int, int);
107static void nm_wrbuf(struct sc_info *, int, u_int32_t, int);
108
109/* The actual rates supported by the card. */
110static int samplerates[9] = {
111 8000, 11025, 16000, 22050, 24000, 32000, 44100, 48000, 99999999
112};
113
114/* -------------------------------------------------------------------- */
115
116static pcmchan_caps nm_caps = {
117 4000, 48000,
118 AFMT_STEREO | AFMT_U8 | AFMT_S16_LE,
119 AFMT_STEREO | AFMT_S16_LE
120};
121
122static pcm_channel nm_chantemplate = {
123 nmchan_init,
124 nmchan_setdir,
125 nmchan_setformat,
126 nmchan_setspeed,
127 nmchan_setblocksize,
128 nmchan_trigger,
129 nmchan_getptr,
130 nmchan_getcaps,
131};
132
133/* -------------------------------------------------------------------- */
134
135/* Hardware */
136static u_int32_t
137nm_rd(struct sc_info *sc, int regno, int size)
138{
139 bus_space_tag_t st = rman_get_bustag(sc->reg);
140 bus_space_handle_t sh = rman_get_bushandle(sc->reg);
141
142 switch (size) {
143 case 1:
144 return bus_space_read_1(st, sh, regno);
145 case 2:
146 return bus_space_read_2(st, sh, regno);
147 case 4:
148 return bus_space_read_4(st, sh, regno);
149 default:
150 return 0xffffffff;
151 }
152}
153
154static void
155nm_wr(struct sc_info *sc, int regno, u_int32_t data, int size)
156{
157 bus_space_tag_t st = rman_get_bustag(sc->reg);
158 bus_space_handle_t sh = rman_get_bushandle(sc->reg);
159
160 switch (size) {
161 case 1:
162 bus_space_write_1(st, sh, regno, data);
163 break;
164 case 2:
165 bus_space_write_2(st, sh, regno, data);
166 break;
167 case 4:
168 bus_space_write_4(st, sh, regno, data);
169 break;
170 }
171}
172
173static u_int32_t
174nm_rdbuf(struct sc_info *sc, int regno, int size)
175{
176 bus_space_tag_t st = rman_get_bustag(sc->buf);
177 bus_space_handle_t sh = rman_get_bushandle(sc->buf);
178
179 switch (size) {
180 case 1:
181 return bus_space_read_1(st, sh, regno);
182 case 2:
183 return bus_space_read_2(st, sh, regno);
184 case 4:
185 return bus_space_read_4(st, sh, regno);
186 default:
187 return 0xffffffff;
188 }
189}
190
191static void
192nm_wrbuf(struct sc_info *sc, int regno, u_int32_t data, int size)
193{
194 bus_space_tag_t st = rman_get_bustag(sc->buf);
195 bus_space_handle_t sh = rman_get_bushandle(sc->buf);
196
197 switch (size) {
198 case 1:
199 bus_space_write_1(st, sh, regno, data);
200 break;
201 case 2:
202 bus_space_write_2(st, sh, regno, data);
203 break;
204 case 4:
205 bus_space_write_4(st, sh, regno, data);
206 break;
207 }
208}
209
210/* ac97 codec */
211static int
212nm_waitcd(struct sc_info *sc)
213{
214 int cnt = 10;
215
216 while (cnt-- > 0) {
217 if (nm_rd(sc, sc->ac97_status, 2) & sc->ac97_busy)
218 DELAY(100);
219 else
220 break;
221 }
222 return (nm_rd(sc, sc->ac97_status, 2) & sc->ac97_busy);
223}
224
225static u_int32_t
226nm_rdcd(void *devinfo, int regno)
227{
228 struct sc_info *sc = (struct sc_info *)devinfo;
229 u_int32_t x;
230
231 if (!nm_waitcd(sc)) {
232 x = nm_rd(sc, sc->ac97_base + regno, 2);
233 DELAY(1000);
234 return x;
235 } else {
236 device_printf(sc->dev, "ac97 codec not ready\n");
237 return 0xffffffff;
238 }
239}
240
241static void
242nm_wrcd(void *devinfo, int regno, u_int32_t data)
243{
244 struct sc_info *sc = (struct sc_info *)devinfo;
245 int cnt = 3;
246
247 if (!nm_waitcd(sc)) {
248 while (cnt-- > 0) {
249 nm_wr(sc, sc->ac97_base + regno, data, 2);
250 if (!nm_waitcd(sc)) {
251 DELAY(1000);
252 return;
253 }
254 }
255 }
256 device_printf(sc->dev, "ac97 codec not ready\n");
257}
258
259static void
260nm_ackint(struct sc_info *sc, u_int32_t num)
261{
262 if (sc->type == NM256AV_PCI_ID) {
263 nm_wr(sc, NM_INT_REG, num << 1, 2);
264 } else if (sc->type == NM256ZX_PCI_ID) {
265 nm_wr(sc, NM_INT_REG, num, 4);
266 }
267}
268
269static int
270nm_loadcoeff(struct sc_info *sc, int dir, int num)
271{
272 int ofs, sz, i;
273 u_int32_t addr;
274
275 addr = (dir == PCMDIR_PLAY)? 0x01c : 0x21c;
276 if (dir == PCMDIR_REC)
277 num += 8;
278 sz = coefficientSizes[num];
279 ofs = 0;
280 while (num-- > 0)
281 ofs+= coefficientSizes[num];
282 for (i = 0; i < sz; i++)
283 nm_wrbuf(sc, sc->cbuf + i, coefficients[ofs + i], 1);
284 nm_wr(sc, addr, sc->cbuf, 4);
285 if (dir == PCMDIR_PLAY)
286 sz--;
287 nm_wr(sc, addr + 4, sc->cbuf + sz, 4);
288 return 0;
289}
290
291static int
292nm_setch(struct sc_chinfo *ch)
293{
294 struct sc_info *sc = ch->parent;
295 u_int32_t base;
296 u_int8_t x;
297
298 for (x = 0; x < 8; x++)
299 if (ch->spd < (samplerates[x] + samplerates[x + 1]) / 2)
300 break;
301
302 if (x == 8) return 1;
303
304 ch->spd = samplerates[x];
305 nm_loadcoeff(sc, ch->dir, x);
306
307 x <<= 4;
308 x &= NM_RATE_MASK;
309 if (ch->fmt & AFMT_16BIT) x |= NM_RATE_BITS_16;
310 if (ch->fmt & AFMT_STEREO) x |= NM_RATE_STEREO;
311
312 base = (ch->dir == PCMDIR_PLAY)? NM_PLAYBACK_REG_OFFSET : NM_RECORD_REG_OFFSET;
313 nm_wr(sc, base + NM_RATE_REG_OFFSET, x, 1);
314 return 0;
315}
316
317/* channel interface */
318static void *
319nmchan_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir)
320{
321 struct sc_info *sc = devinfo;
322 struct sc_chinfo *ch;
323 u_int32_t chnbuf;
324
325 chnbuf = (dir == PCMDIR_PLAY)? sc->pbuf : sc->rbuf;
326 ch = (dir == PCMDIR_PLAY)? &sc->pch : &sc->rch;
327 ch->buffer = b;
328 ch->buffer->bufsize = NM_BUFFSIZE;
329 ch->buffer->buf = (u_int8_t *)(rman_get_bushandle(sc->buf) + chnbuf);
330 device_printf(sc->dev, "%s buf %p\n", (dir == PCMDIR_PLAY)? "play" : "rec", ch->buffer->buf);
331 ch->parent = sc;
332 ch->channel = c;
333 ch->dir = dir;
334 return ch;
335}
336
337static int
338nmchan_setdir(void *data, int dir)
339{
340 return 0;
341}
342
343static int
344nmchan_setformat(void *data, u_int32_t format)
345{
346 struct sc_chinfo *ch = data;
347
348 ch->fmt = format;
349 return nm_setch(ch);
350}
351
352static int
353nmchan_setspeed(void *data, u_int32_t speed)
354{
355 struct sc_chinfo *ch = data;
356
357 ch->spd = speed;
358 return nm_setch(ch)? 0 : ch->spd;
359}
360
361static int
362nmchan_setblocksize(void *data, u_int32_t blocksize)
363{
364 return blocksize;
365}
366
367static int
368nmchan_trigger(void *data, int go)
369{
370 struct sc_chinfo *ch = data;
371 struct sc_info *sc = ch->parent;
372 int ssz;
373
374 if (go == PCMTRIG_EMLDMAWR) return 0;
375
376 ssz = (ch->fmt & AFMT_16BIT)? 2 : 1;
377 if (ch->fmt & AFMT_STEREO)
378 ssz <<= 1;
379
380 if (ch->dir == PCMDIR_PLAY) {
381 if (go == PCMTRIG_START) {
382 nm_wr(sc, NM_PBUFFER_START, sc->pbuf, 4);
383 nm_wr(sc, NM_PBUFFER_END, sc->pbuf + NM_BUFFSIZE - ssz, 4);
384 nm_wr(sc, NM_PBUFFER_CURRP, sc->pbuf, 4);
385 nm_wr(sc, NM_PBUFFER_WMARK, sc->pbuf + NM_BUFFSIZE / 2, 4);
386 nm_wr(sc, NM_PLAYBACK_ENABLE_REG, NM_PLAYBACK_FREERUN |
387 NM_PLAYBACK_ENABLE_FLAG, 1);
388 nm_wr(sc, NM_AUDIO_MUTE_REG, 0, 2);
389 } else {
390 nm_wr(sc, NM_PLAYBACK_ENABLE_REG, 0, 1);
391 nm_wr(sc, NM_AUDIO_MUTE_REG, NM_AUDIO_MUTE_BOTH, 2);
392 }
393 } else {
394 if (go == PCMTRIG_START) {
395 nm_wr(sc, NM_RECORD_ENABLE_REG, NM_RECORD_FREERUN |
396 NM_RECORD_ENABLE_FLAG, 1);
397 nm_wr(sc, NM_RBUFFER_START, sc->rbuf, 4);
398 nm_wr(sc, NM_RBUFFER_END, sc->rbuf + NM_BUFFSIZE, 4);
399 nm_wr(sc, NM_RBUFFER_CURRP, sc->rbuf, 4);
400 nm_wr(sc, NM_RBUFFER_WMARK, sc->rbuf + NM_BUFFSIZE / 2, 4);
401 } else {
402 nm_wr(sc, NM_RECORD_ENABLE_REG, 0, 1);
403 }
404 }
405 return 0;
406}
407
408static int
409nmchan_getptr(void *data)
410{
411 struct sc_chinfo *ch = data;
412 struct sc_info *sc = ch->parent;
413
414 if (ch->dir == PCMDIR_PLAY)
415 return nm_rd(sc, NM_PBUFFER_CURRP, 4) - sc->pbuf;
416 else
417 return nm_rd(sc, NM_RBUFFER_CURRP, 4) - sc->rbuf;
418}
419
420static pcmchan_caps *
421nmchan_getcaps(void *data)
422{
423 return &nm_caps;
424}
425
426/* The interrupt handler */
427static void
428nm_intr(void *p)
429{
430 struct sc_info *sc = (struct sc_info *)p;
431 int status, x;
431 int status, x, active;
432
432
433 active = (sc->pch.channel->buffer.dl || sc->rch.channel->buffer.dl);
433 status = nm_rd(sc, NM_INT_REG, sc->irsz);
434 status = nm_rd(sc, NM_INT_REG, sc->irsz);
434 if (status == 0) {
435 if (status == 0 && active) {
435 if (sc->badintr++ > 1000) {
436 device_printf(sc->dev, "1000 bad intrs\n");
437 sc->badintr = 0;
438 }
439 return;
440 }
441 sc->badintr = 0;
442
443 if (status & sc->playint) {
444 status &= ~sc->playint;
445 nm_ackint(sc, sc->playint);
446 chn_intr(sc->pch.channel);
447 }
448 if (status & sc->recint) {
449 status &= ~sc->recint;
450 nm_ackint(sc, sc->recint);
451 chn_intr(sc->rch.channel);
452 }
453 if (status & sc->misc1int) {
454 status &= ~sc->misc1int;
455 nm_ackint(sc, sc->misc1int);
456 x = nm_rd(sc, 0x400, 1);
457 nm_wr(sc, 0x400, x | 2, 1);
458 device_printf(sc->dev, "misc int 1\n");
459 }
460 if (status & sc->misc2int) {
461 status &= ~sc->misc2int;
462 nm_ackint(sc, sc->misc2int);
463 x = nm_rd(sc, 0x400, 1);
464 nm_wr(sc, 0x400, x & ~2, 1);
465 device_printf(sc->dev, "misc int 2\n");
466 }
467 if (status) {
468 status &= ~sc->misc2int;
469 nm_ackint(sc, sc->misc2int);
470 device_printf(sc->dev, "unknown int\n");
471 }
472}
473
474/* -------------------------------------------------------------------- */
475
476/*
477 * Probe and attach the card
478 */
479
480static int
481nm_init(struct sc_info *sc)
482{
483 u_int32_t ofs, i;
484
485 if (sc->type == NM256AV_PCI_ID) {
486 sc->ac97_base = NM_MIXER_OFFSET;
487 sc->ac97_status = NM_MIXER_STATUS_OFFSET;
488 sc->ac97_busy = NM_MIXER_READY_MASK;
489
490 sc->buftop = 2560 * 1024;
491
492 sc->irsz = 2;
493 sc->playint = NM_PLAYBACK_INT;
494 sc->recint = NM_RECORD_INT;
495 sc->misc1int = NM_MISC_INT_1;
496 sc->misc2int = NM_MISC_INT_2;
497 } else if (sc->type == NM256ZX_PCI_ID) {
498 sc->ac97_base = NM_MIXER_OFFSET;
499 sc->ac97_status = NM2_MIXER_STATUS_OFFSET;
500 sc->ac97_busy = NM2_MIXER_READY_MASK;
501
502 sc->buftop = (nm_rd(sc, 0xa0b, 2)? 6144 : 4096) * 1024;
503
504 sc->irsz = 4;
505 sc->playint = NM2_PLAYBACK_INT;
506 sc->recint = NM2_RECORD_INT;
507 sc->misc1int = NM2_MISC_INT_1;
508 sc->misc2int = NM2_MISC_INT_2;
436 if (sc->badintr++ > 1000) {
437 device_printf(sc->dev, "1000 bad intrs\n");
438 sc->badintr = 0;
439 }
440 return;
441 }
442 sc->badintr = 0;
443
444 if (status & sc->playint) {
445 status &= ~sc->playint;
446 nm_ackint(sc, sc->playint);
447 chn_intr(sc->pch.channel);
448 }
449 if (status & sc->recint) {
450 status &= ~sc->recint;
451 nm_ackint(sc, sc->recint);
452 chn_intr(sc->rch.channel);
453 }
454 if (status & sc->misc1int) {
455 status &= ~sc->misc1int;
456 nm_ackint(sc, sc->misc1int);
457 x = nm_rd(sc, 0x400, 1);
458 nm_wr(sc, 0x400, x | 2, 1);
459 device_printf(sc->dev, "misc int 1\n");
460 }
461 if (status & sc->misc2int) {
462 status &= ~sc->misc2int;
463 nm_ackint(sc, sc->misc2int);
464 x = nm_rd(sc, 0x400, 1);
465 nm_wr(sc, 0x400, x & ~2, 1);
466 device_printf(sc->dev, "misc int 2\n");
467 }
468 if (status) {
469 status &= ~sc->misc2int;
470 nm_ackint(sc, sc->misc2int);
471 device_printf(sc->dev, "unknown int\n");
472 }
473}
474
475/* -------------------------------------------------------------------- */
476
477/*
478 * Probe and attach the card
479 */
480
481static int
482nm_init(struct sc_info *sc)
483{
484 u_int32_t ofs, i;
485
486 if (sc->type == NM256AV_PCI_ID) {
487 sc->ac97_base = NM_MIXER_OFFSET;
488 sc->ac97_status = NM_MIXER_STATUS_OFFSET;
489 sc->ac97_busy = NM_MIXER_READY_MASK;
490
491 sc->buftop = 2560 * 1024;
492
493 sc->irsz = 2;
494 sc->playint = NM_PLAYBACK_INT;
495 sc->recint = NM_RECORD_INT;
496 sc->misc1int = NM_MISC_INT_1;
497 sc->misc2int = NM_MISC_INT_2;
498 } else if (sc->type == NM256ZX_PCI_ID) {
499 sc->ac97_base = NM_MIXER_OFFSET;
500 sc->ac97_status = NM2_MIXER_STATUS_OFFSET;
501 sc->ac97_busy = NM2_MIXER_READY_MASK;
502
503 sc->buftop = (nm_rd(sc, 0xa0b, 2)? 6144 : 4096) * 1024;
504
505 sc->irsz = 4;
506 sc->playint = NM2_PLAYBACK_INT;
507 sc->recint = NM2_RECORD_INT;
508 sc->misc1int = NM2_MISC_INT_1;
509 sc->misc2int = NM2_MISC_INT_2;
509 }
510 } else return -1;
510 sc->badintr = 0;
511 ofs = sc->buftop - 0x0400;
512 sc->buftop -= 0x1400;
513
514 if ((nm_rdbuf(sc, ofs, 4) & NM_SIG_MASK) == NM_SIGNATURE) {
515 i = nm_rdbuf(sc, ofs + 4, 4);
516 if (i != 0 && i != 0xffffffff)
517 sc->buftop = i;
518 }
519
520 sc->cbuf = sc->buftop - NM_MAX_COEFFICIENT;
521 sc->rbuf = sc->cbuf - NM_BUFFSIZE;
522 sc->pbuf = sc->rbuf - NM_BUFFSIZE;
523 sc->acbuf = sc->pbuf - (NM_TOTAL_COEFF_COUNT * 4);
524
525 nm_wr(sc, 0, 0x11, 1);
526 nm_wr(sc, NM_RECORD_ENABLE_REG, 0, 1);
527 nm_wr(sc, 0x214, 0, 2);
528
529 return 0;
530}
531
532static int
533nm_pci_probe(device_t dev)
534{
535 char *s = NULL;
536
537 switch (pci_get_devid(dev)) {
538 case NM256AV_PCI_ID:
539 s = "NeoMagic 256AV";
540 break;
541
542 case NM256ZX_PCI_ID:
543 s = "NeoMagic 256ZX";
544 break;
545 }
546
547 if (s) device_set_desc(dev, s);
548 return s? 0 : ENXIO;
549}
550
551static int
552nm_pci_attach(device_t dev)
553{
554 snddev_info *d;
555 u_int32_t data;
556 struct sc_info *sc;
557 struct ac97_info *codec;
558 char status[SND_STATUSLEN];
559
560 d = device_get_softc(dev);
561 if ((sc = malloc(sizeof(*sc), M_DEVBUF, M_NOWAIT)) == NULL) {
562 device_printf(dev, "cannot allocate softc\n");
563 return ENXIO;
564 }
565
566 bzero(sc, sizeof(*sc));
567 sc->dev = dev;
568 sc->type = pci_get_devid(dev);
569
570 data = pci_read_config(dev, PCIR_COMMAND, 2);
571 data |= (PCIM_CMD_PORTEN|PCIM_CMD_MEMEN|PCIM_CMD_BUSMASTEREN);
572 pci_write_config(dev, PCIR_COMMAND, data, 2);
573 data = pci_read_config(dev, PCIR_COMMAND, 2);
574
575 sc->bufid = PCIR_MAPS;
576 sc->buf = bus_alloc_resource(dev, SYS_RES_MEMORY, &sc->bufid,
577 0, ~0, 1, RF_ACTIVE);
578 sc->regid = PCIR_MAPS + 4;
579 sc->reg = bus_alloc_resource(dev, SYS_RES_MEMORY, &sc->regid,
580 0, ~0, 1, RF_ACTIVE);
581
582 if (!sc->buf || !sc->reg) {
583 device_printf(dev, "unable to map register space\n");
584 goto bad;
585 }
586
587 if (nm_init(sc) == -1) {
588 device_printf(dev, "unable to initialize the card\n");
589 goto bad;
590 }
591
592 codec = ac97_create(sc, nm_rdcd, nm_wrcd);
593 if (codec == NULL) goto bad;
594 mixer_init(d, &ac97_mixer, codec);
595
596 sc->irqid = 0;
597 sc->irq = bus_alloc_resource(dev, SYS_RES_IRQ, &sc->irqid,
598 0, ~0, 1, RF_ACTIVE | RF_SHAREABLE);
599 if (!sc->irq ||
600 bus_setup_intr(dev, sc->irq, INTR_TYPE_TTY, nm_intr, sc, &sc->ih)) {
601 device_printf(dev, "unable to map interrupt\n");
602 goto bad;
603 }
604
605 snprintf(status, SND_STATUSLEN, "at memory 0x%lx, 0x%lx irq %ld",
606 rman_get_start(sc->buf), rman_get_start(sc->reg),
607 rman_get_start(sc->irq));
608
609 if (pcm_register(dev, sc, 1, 1)) goto bad;
610 pcm_addchan(dev, PCMDIR_REC, &nm_chantemplate, sc);
611 pcm_addchan(dev, PCMDIR_PLAY, &nm_chantemplate, sc);
612 pcm_setstatus(dev, status);
613
614 return 0;
615
616bad:
617 if (sc->buf) bus_release_resource(dev, SYS_RES_MEMORY, sc->bufid, sc->buf);
618 if (sc->reg) bus_release_resource(dev, SYS_RES_MEMORY, sc->regid, sc->reg);
619 if (sc->ih) bus_teardown_intr(dev, sc->irq, sc->ih);
620 if (sc->irq) bus_release_resource(dev, SYS_RES_IRQ, sc->irqid, sc->irq);
621 free(sc, M_DEVBUF);
622 return ENXIO;
623}
624
625static device_method_t nm_methods[] = {
626 /* Device interface */
627 DEVMETHOD(device_probe, nm_pci_probe),
628 DEVMETHOD(device_attach, nm_pci_attach),
629
630 { 0, 0 }
631};
632
633static driver_t nm_driver = {
634 "pcm",
635 nm_methods,
636 sizeof(snddev_info),
637};
638
639static devclass_t pcm_devclass;
640
641DRIVER_MODULE(nm, pci, nm_driver, pcm_devclass, 0, 0);
511 sc->badintr = 0;
512 ofs = sc->buftop - 0x0400;
513 sc->buftop -= 0x1400;
514
515 if ((nm_rdbuf(sc, ofs, 4) & NM_SIG_MASK) == NM_SIGNATURE) {
516 i = nm_rdbuf(sc, ofs + 4, 4);
517 if (i != 0 && i != 0xffffffff)
518 sc->buftop = i;
519 }
520
521 sc->cbuf = sc->buftop - NM_MAX_COEFFICIENT;
522 sc->rbuf = sc->cbuf - NM_BUFFSIZE;
523 sc->pbuf = sc->rbuf - NM_BUFFSIZE;
524 sc->acbuf = sc->pbuf - (NM_TOTAL_COEFF_COUNT * 4);
525
526 nm_wr(sc, 0, 0x11, 1);
527 nm_wr(sc, NM_RECORD_ENABLE_REG, 0, 1);
528 nm_wr(sc, 0x214, 0, 2);
529
530 return 0;
531}
532
533static int
534nm_pci_probe(device_t dev)
535{
536 char *s = NULL;
537
538 switch (pci_get_devid(dev)) {
539 case NM256AV_PCI_ID:
540 s = "NeoMagic 256AV";
541 break;
542
543 case NM256ZX_PCI_ID:
544 s = "NeoMagic 256ZX";
545 break;
546 }
547
548 if (s) device_set_desc(dev, s);
549 return s? 0 : ENXIO;
550}
551
552static int
553nm_pci_attach(device_t dev)
554{
555 snddev_info *d;
556 u_int32_t data;
557 struct sc_info *sc;
558 struct ac97_info *codec;
559 char status[SND_STATUSLEN];
560
561 d = device_get_softc(dev);
562 if ((sc = malloc(sizeof(*sc), M_DEVBUF, M_NOWAIT)) == NULL) {
563 device_printf(dev, "cannot allocate softc\n");
564 return ENXIO;
565 }
566
567 bzero(sc, sizeof(*sc));
568 sc->dev = dev;
569 sc->type = pci_get_devid(dev);
570
571 data = pci_read_config(dev, PCIR_COMMAND, 2);
572 data |= (PCIM_CMD_PORTEN|PCIM_CMD_MEMEN|PCIM_CMD_BUSMASTEREN);
573 pci_write_config(dev, PCIR_COMMAND, data, 2);
574 data = pci_read_config(dev, PCIR_COMMAND, 2);
575
576 sc->bufid = PCIR_MAPS;
577 sc->buf = bus_alloc_resource(dev, SYS_RES_MEMORY, &sc->bufid,
578 0, ~0, 1, RF_ACTIVE);
579 sc->regid = PCIR_MAPS + 4;
580 sc->reg = bus_alloc_resource(dev, SYS_RES_MEMORY, &sc->regid,
581 0, ~0, 1, RF_ACTIVE);
582
583 if (!sc->buf || !sc->reg) {
584 device_printf(dev, "unable to map register space\n");
585 goto bad;
586 }
587
588 if (nm_init(sc) == -1) {
589 device_printf(dev, "unable to initialize the card\n");
590 goto bad;
591 }
592
593 codec = ac97_create(sc, nm_rdcd, nm_wrcd);
594 if (codec == NULL) goto bad;
595 mixer_init(d, &ac97_mixer, codec);
596
597 sc->irqid = 0;
598 sc->irq = bus_alloc_resource(dev, SYS_RES_IRQ, &sc->irqid,
599 0, ~0, 1, RF_ACTIVE | RF_SHAREABLE);
600 if (!sc->irq ||
601 bus_setup_intr(dev, sc->irq, INTR_TYPE_TTY, nm_intr, sc, &sc->ih)) {
602 device_printf(dev, "unable to map interrupt\n");
603 goto bad;
604 }
605
606 snprintf(status, SND_STATUSLEN, "at memory 0x%lx, 0x%lx irq %ld",
607 rman_get_start(sc->buf), rman_get_start(sc->reg),
608 rman_get_start(sc->irq));
609
610 if (pcm_register(dev, sc, 1, 1)) goto bad;
611 pcm_addchan(dev, PCMDIR_REC, &nm_chantemplate, sc);
612 pcm_addchan(dev, PCMDIR_PLAY, &nm_chantemplate, sc);
613 pcm_setstatus(dev, status);
614
615 return 0;
616
617bad:
618 if (sc->buf) bus_release_resource(dev, SYS_RES_MEMORY, sc->bufid, sc->buf);
619 if (sc->reg) bus_release_resource(dev, SYS_RES_MEMORY, sc->regid, sc->reg);
620 if (sc->ih) bus_teardown_intr(dev, sc->irq, sc->ih);
621 if (sc->irq) bus_release_resource(dev, SYS_RES_IRQ, sc->irqid, sc->irq);
622 free(sc, M_DEVBUF);
623 return ENXIO;
624}
625
626static device_method_t nm_methods[] = {
627 /* Device interface */
628 DEVMETHOD(device_probe, nm_pci_probe),
629 DEVMETHOD(device_attach, nm_pci_attach),
630
631 { 0, 0 }
632};
633
634static driver_t nm_driver = {
635 "pcm",
636 nm_methods,
637 sizeof(snddev_info),
638};
639
640static devclass_t pcm_devclass;
641
642DRIVER_MODULE(nm, pci, nm_driver, pcm_devclass, 0, 0);