Say hello to a sound system update from FreeBSD. This includes the long
[dragonfly.git] / sys / dev / sound / pci / ds1.c
CommitLineData
558a398b 1/*-
984263bc
MD
2 * Copyright (c) 2000 Cameron Grant <cg@freebsd.org>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHERIN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THEPOSSIBILITY OF
24 * SUCH DAMAGE.
1de703da 25 *
558a398b
SS
26 * $FreeBSD: src/sys/dev/sound/pci/ds1.c,v 1.43.2.1 2006/01/18 01:05:34 ariff Exp $
27 * $DragonFly: src/sys/dev/sound/pci/ds1.c,v 1.8 2007/01/04 21:47:02 corecode Exp $
984263bc
MD
28 */
29
30#include <dev/sound/pcm/sound.h>
31#include <dev/sound/pcm/ac97.h>
32
1f2de5d4
MD
33#include <bus/pci/pcireg.h>
34#include <bus/pci/pcivar.h>
984263bc
MD
35
36#include <dev/sound/pci/ds1.h>
37#include <dev/sound/pci/ds1-fw.h>
38
558a398b 39SND_DECLARE_FILE("$DragonFly: src/sys/dev/sound/pci/ds1.c,v 1.8 2007/01/04 21:47:02 corecode Exp $");
984263bc
MD
40
41/* -------------------------------------------------------------------- */
42
43#define DS1_CHANS 4
44#define DS1_RECPRIMARY 0
45#define DS1_IRQHZ ((48000 << 8) / 256)
46#define DS1_BUFFSIZE 4096
47
48struct pbank {
49 volatile u_int32_t Format;
50 volatile u_int32_t LoopDefault;
51 volatile u_int32_t PgBase;
52 volatile u_int32_t PgLoop;
53 volatile u_int32_t PgLoopEnd;
54 volatile u_int32_t PgLoopFrac;
55 volatile u_int32_t PgDeltaEnd;
56 volatile u_int32_t LpfKEnd;
57 volatile u_int32_t EgGainEnd;
58 volatile u_int32_t LchGainEnd;
59 volatile u_int32_t RchGainEnd;
60 volatile u_int32_t Effect1GainEnd;
61 volatile u_int32_t Effect2GainEnd;
62 volatile u_int32_t Effect3GainEnd;
63 volatile u_int32_t LpfQ;
64 volatile u_int32_t Status;
65 volatile u_int32_t NumOfFrames;
66 volatile u_int32_t LoopCount;
67 volatile u_int32_t PgStart;
68 volatile u_int32_t PgStartFrac;
69 volatile u_int32_t PgDelta;
70 volatile u_int32_t LpfK;
71 volatile u_int32_t EgGain;
72 volatile u_int32_t LchGain;
73 volatile u_int32_t RchGain;
74 volatile u_int32_t Effect1Gain;
75 volatile u_int32_t Effect2Gain;
76 volatile u_int32_t Effect3Gain;
77 volatile u_int32_t LpfD1;
78 volatile u_int32_t LpfD2;
79};
80
81struct rbank {
82 volatile u_int32_t PgBase;
83 volatile u_int32_t PgLoopEnd;
84 volatile u_int32_t PgStart;
85 volatile u_int32_t NumOfLoops;
86};
87
88struct sc_info;
89
90/* channel registers */
91struct sc_pchinfo {
92 int run, spd, dir, fmt;
93 struct snd_dbuf *buffer;
94 struct pcm_channel *channel;
95 volatile struct pbank *lslot, *rslot;
96 int lsnum, rsnum;
97 struct sc_info *parent;
98};
99
100struct sc_rchinfo {
101 int run, spd, dir, fmt, num;
102 struct snd_dbuf *buffer;
103 struct pcm_channel *channel;
104 volatile struct rbank *slot;
105 struct sc_info *parent;
106};
107
108/* device private data */
109struct sc_info {
110 device_t dev;
111 u_int32_t type, rev;
112 u_int32_t cd2id, ctrlbase;
113
114 bus_space_tag_t st;
115 bus_space_handle_t sh;
116 bus_dma_tag_t buffer_dmat, control_dmat;
117 bus_dmamap_t map;
118
119 struct resource *reg, *irq;
120 int regid, irqid;
121 void *ih;
558a398b 122 struct spinlock *lock;
984263bc
MD
123
124 void *regbase;
125 u_int32_t *pbase, pbankbase, pbanksize;
126 volatile struct pbank *pbank[2 * 64];
127 volatile struct rbank *rbank;
128 int pslotfree, currbank, pchn, rchn;
129 unsigned int bufsz;
130
131 struct sc_pchinfo pch[DS1_CHANS];
132 struct sc_rchinfo rch[2];
133};
134
135struct {
136 u_int32_t dev, subdev;
137 char *name;
138 u_int32_t *mcode;
139} ds_devs[] = {
140 {0x00041073, 0, "Yamaha DS-1 (YMF724)", CntrlInst},
141 {0x000d1073, 0, "Yamaha DS-1E (YMF724F)", CntrlInst1E},
142 {0x00051073, 0, "Yamaha DS-1? (YMF734)", CntrlInst},
143 {0x00081073, 0, "Yamaha DS-1? (YMF737)", CntrlInst},
144 {0x00201073, 0, "Yamaha DS-1? (YMF738)", CntrlInst},
145 {0x00061073, 0, "Yamaha DS-1? (YMF738_TEG)", CntrlInst},
146 {0x000a1073, 0x00041073, "Yamaha DS-1 (YMF740)", CntrlInst},
147 {0x000a1073, 0x000a1073, "Yamaha DS-1 (YMF740B)", CntrlInst},
148 {0x000a1073, 0x53328086, "Yamaha DS-1 (YMF740I)", CntrlInst},
149 {0x000a1073, 0, "Yamaha DS-1 (YMF740?)", CntrlInst},
150 {0x000c1073, 0, "Yamaha DS-1E (YMF740C)", CntrlInst1E},
151 {0x00101073, 0, "Yamaha DS-1E (YMF744)", CntrlInst1E},
152 {0x00121073, 0, "Yamaha DS-1E (YMF754)", CntrlInst1E},
153 {0, 0, NULL, NULL}
154};
155
156/* -------------------------------------------------------------------- */
157
158/*
159 * prototypes
160 */
161
162/* stuff */
163static int ds_init(struct sc_info *);
164static void ds_intr(void *);
165
166/* talk to the card */
167static u_int32_t ds_rd(struct sc_info *, int, int);
168static void ds_wr(struct sc_info *, int, u_int32_t, int);
169
170/* -------------------------------------------------------------------- */
171
172static u_int32_t ds_recfmt[] = {
173 AFMT_U8,
174 AFMT_STEREO | AFMT_U8,
175 AFMT_S8,
176 AFMT_STEREO | AFMT_S8,
177 AFMT_S16_LE,
178 AFMT_STEREO | AFMT_S16_LE,
179 AFMT_U16_LE,
180 AFMT_STEREO | AFMT_U16_LE,
181 0
182};
183static struct pcmchan_caps ds_reccaps = {4000, 48000, ds_recfmt, 0};
184
185static u_int32_t ds_playfmt[] = {
186 AFMT_U8,
187 AFMT_STEREO | AFMT_U8,
188 /* AFMT_S16_LE, */
189 AFMT_STEREO | AFMT_S16_LE,
190 0
191};
192static struct pcmchan_caps ds_playcaps = {4000, 96000, ds_playfmt, 0};
193
194/* -------------------------------------------------------------------- */
195/* Hardware */
196static u_int32_t
197ds_rd(struct sc_info *sc, int regno, int size)
198{
199 switch (size) {
200 case 1:
201 return bus_space_read_1(sc->st, sc->sh, regno);
202 case 2:
203 return bus_space_read_2(sc->st, sc->sh, regno);
204 case 4:
205 return bus_space_read_4(sc->st, sc->sh, regno);
206 default:
207 return 0xffffffff;
208 }
209}
210
211static void
212ds_wr(struct sc_info *sc, int regno, u_int32_t data, int size)
213{
214 switch (size) {
215 case 1:
216 bus_space_write_1(sc->st, sc->sh, regno, data);
217 break;
218 case 2:
219 bus_space_write_2(sc->st, sc->sh, regno, data);
220 break;
221 case 4:
222 bus_space_write_4(sc->st, sc->sh, regno, data);
223 break;
224 }
225}
226
227static void
228wrl(struct sc_info *sc, u_int32_t *ptr, u_int32_t val)
229{
230 *(volatile u_int32_t *)ptr = val;
231 bus_space_barrier(sc->st, sc->sh, 0, 0, BUS_SPACE_BARRIER_WRITE);
232}
233
234/* -------------------------------------------------------------------- */
235/* ac97 codec */
236static int
237ds_cdbusy(struct sc_info *sc, int sec)
238{
239 int i, reg;
240
241 reg = sec? YDSXGR_SECSTATUSADR : YDSXGR_PRISTATUSADR;
242 i = YDSXG_AC97TIMEOUT;
243 while (i > 0) {
244 if (!(ds_rd(sc, reg, 2) & 0x8000))
245 return 0;
246 i--;
247 }
248 return ETIMEDOUT;
249}
250
251static u_int32_t
252ds_initcd(kobj_t obj, void *devinfo)
253{
254 struct sc_info *sc = (struct sc_info *)devinfo;
255 u_int32_t x;
256
257 x = pci_read_config(sc->dev, PCIR_DSXGCTRL, 1);
258 if (x & 0x03) {
259 pci_write_config(sc->dev, PCIR_DSXGCTRL, x & ~0x03, 1);
260 pci_write_config(sc->dev, PCIR_DSXGCTRL, x | 0x03, 1);
261 pci_write_config(sc->dev, PCIR_DSXGCTRL, x & ~0x03, 1);
262 /*
263 * The YMF740 on some Intel motherboards requires a pretty
264 * hefty delay after this reset for some reason... Otherwise:
265 * "pcm0: ac97 codec init failed"
266 * Maybe this is needed for all YMF740's?
267 * 400ms and 500ms here seem to work, 300ms does not.
268 *
269 * do it for all chips -cg
270 */
271 DELAY(500000);
272 }
273
274 return ds_cdbusy(sc, 0)? 0 : 1;
275}
276
277static int
278ds_rdcd(kobj_t obj, void *devinfo, int regno)
279{
280 struct sc_info *sc = (struct sc_info *)devinfo;
281 int sec, cid, i;
282 u_int32_t cmd, reg;
283
284 sec = regno & 0x100;
285 regno &= 0xff;
286 cid = sec? (sc->cd2id << 8) : 0;
287 reg = sec? YDSXGR_SECSTATUSDATA : YDSXGR_PRISTATUSDATA;
288 if (sec && cid == 0)
289 return 0xffffffff;
290
291 cmd = YDSXG_AC97READCMD | cid | regno;
292 ds_wr(sc, YDSXGR_AC97CMDADR, cmd, 2);
293
294 if (ds_cdbusy(sc, sec))
295 return 0xffffffff;
296
297 if (sc->type == 11 && sc->rev < 2)
298 for (i = 0; i < 600; i++)
299 ds_rd(sc, reg, 2);
300
301 return ds_rd(sc, reg, 2);
302}
303
304static int
305ds_wrcd(kobj_t obj, void *devinfo, int regno, u_int32_t data)
306{
307 struct sc_info *sc = (struct sc_info *)devinfo;
308 int sec, cid;
309 u_int32_t cmd;
310
311 sec = regno & 0x100;
312 regno &= 0xff;
313 cid = sec? (sc->cd2id << 8) : 0;
314 if (sec && cid == 0)
315 return ENXIO;
316
317 cmd = YDSXG_AC97WRITECMD | cid | regno;
318 cmd <<= 16;
319 cmd |= data;
320 ds_wr(sc, YDSXGR_AC97CMDDATA, cmd, 4);
321
322 return ds_cdbusy(sc, sec);
323}
324
325static kobj_method_t ds_ac97_methods[] = {
326 KOBJMETHOD(ac97_init, ds_initcd),
327 KOBJMETHOD(ac97_read, ds_rdcd),
328 KOBJMETHOD(ac97_write, ds_wrcd),
329 { 0, 0 }
330};
331AC97_DECLARE(ds_ac97);
332
333/* -------------------------------------------------------------------- */
334
335static void
336ds_enadsp(struct sc_info *sc, int on)
337{
338 u_int32_t v, i;
339
340 v = on? 1 : 0;
341 if (on) {
342 ds_wr(sc, YDSXGR_CONFIG, 0x00000001, 4);
343 } else {
344 if (ds_rd(sc, YDSXGR_CONFIG, 4))
345 ds_wr(sc, YDSXGR_CONFIG, 0x00000000, 4);
346 i = YDSXG_WORKBITTIMEOUT;
347 while (i > 0) {
348 if (!(ds_rd(sc, YDSXGR_CONFIG, 4) & 0x00000002))
349 break;
350 i--;
351 }
352 }
353}
354
355static volatile struct pbank *
356ds_allocpslot(struct sc_info *sc)
357{
358 int slot;
359
360 if (sc->pslotfree > 63)
361 return NULL;
362 slot = sc->pslotfree++;
363 return sc->pbank[slot * 2];
364}
365
366static int
558a398b 367ds_initpbank(volatile struct pbank *pb, int ch, int b16, int stereo, u_int32_t rate, bus_addr_t base, u_int32_t len)
984263bc
MD
368{
369 u_int32_t lv[] = {1, 1, 0, 0, 0};
370 u_int32_t rv[] = {1, 0, 1, 0, 0};
371 u_int32_t e1[] = {0, 0, 0, 0, 0};
372 u_int32_t e2[] = {1, 0, 0, 1, 0};
373 u_int32_t e3[] = {1, 0, 0, 0, 1};
374 int ss, i;
375 u_int32_t delta;
376
377 struct {
378 int rate, fK, fQ;
379 } speedinfo[] = {
380 { 100, 0x00570000, 0x35280000},
381 { 2000, 0x06aa0000, 0x34a70000},
382 { 8000, 0x18b20000, 0x32020000},
383 {11025, 0x20930000, 0x31770000},
384 {16000, 0x2b9a0000, 0x31390000},
385 {22050, 0x35a10000, 0x31c90000},
386 {32000, 0x3eaa0000, 0x33d00000},
387/* {44100, 0x04646000, 0x370a0000},
388*/ {48000, 0x40000000, 0x40000000},
389 };
390
391 ss = b16? 1 : 0;
392 ss += stereo? 1 : 0;
393 delta = (65536 * rate) / 48000;
394 i = 0;
395 while (i < 7 && speedinfo[i].rate < rate)
396 i++;
397
398 pb->Format = stereo? 0x00010000 : 0;
399 pb->Format |= b16? 0 : 0x80000000;
400 pb->Format |= (stereo && (ch == 2 || ch == 4))? 0x00000001 : 0;
401 pb->LoopDefault = 0;
558a398b 402 pb->PgBase = base? base : 0;
984263bc
MD
403 pb->PgLoop = 0;
404 pb->PgLoopEnd = len >> ss;
405 pb->PgLoopFrac = 0;
406 pb->Status = 0;
407 pb->NumOfFrames = 0;
408 pb->LoopCount = 0;
409 pb->PgStart = 0;
410 pb->PgStartFrac = 0;
411 pb->PgDelta = pb->PgDeltaEnd = delta << 12;
412 pb->LpfQ = speedinfo[i].fQ;
413 pb->LpfK = pb->LpfKEnd = speedinfo[i].fK;
414 pb->LpfD1 = pb->LpfD2 = 0;
415 pb->EgGain = pb->EgGainEnd = 0x40000000;
416 pb->LchGain = pb->LchGainEnd = lv[ch] * 0x40000000;
417 pb->RchGain = pb->RchGainEnd = rv[ch] * 0x40000000;
418 pb->Effect1Gain = pb->Effect1GainEnd = e1[ch] * 0x40000000;
419 pb->Effect2Gain = pb->Effect2GainEnd = e2[ch] * 0x40000000;
420 pb->Effect3Gain = pb->Effect3GainEnd = e3[ch] * 0x40000000;
421
422 return 0;
423}
424
425static void
426ds_enapslot(struct sc_info *sc, int slot, int go)
427{
428 wrl(sc, &sc->pbase[slot + 1], go? (sc->pbankbase + 2 * slot * sc->pbanksize) : 0);
e3869ec7 429 /* kprintf("pbase[%d] = 0x%x\n", slot + 1, go? (sc->pbankbase + 2 * slot * sc->pbanksize) : 0); */
984263bc
MD
430}
431
432static void
433ds_setuppch(struct sc_pchinfo *ch)
434{
435 int stereo, b16, c, sz;
558a398b 436 bus_addr_t addr;
984263bc
MD
437
438 stereo = (ch->fmt & AFMT_STEREO)? 1 : 0;
439 b16 = (ch->fmt & AFMT_16BIT)? 1 : 0;
440 c = stereo? 1 : 0;
558a398b 441 addr = sndbuf_getbufaddr(ch->buffer);
984263bc
MD
442 sz = sndbuf_getsize(ch->buffer);
443
558a398b
SS
444 ds_initpbank(ch->lslot, c, stereo, b16, ch->spd, addr, sz);
445 ds_initpbank(ch->lslot + 1, c, stereo, b16, ch->spd, addr, sz);
446 ds_initpbank(ch->rslot, 2, stereo, b16, ch->spd, addr, sz);
447 ds_initpbank(ch->rslot + 1, 2, stereo, b16, ch->spd, addr, sz);
984263bc
MD
448}
449
450static void
451ds_setuprch(struct sc_rchinfo *ch)
452{
453 struct sc_info *sc = ch->parent;
454 int stereo, b16, i, sz, pri;
455 u_int32_t x, y;
558a398b 456 bus_addr_t addr;
984263bc
MD
457
458 stereo = (ch->fmt & AFMT_STEREO)? 1 : 0;
459 b16 = (ch->fmt & AFMT_16BIT)? 1 : 0;
558a398b 460 addr = sndbuf_getbufaddr(ch->buffer);
984263bc
MD
461 sz = sndbuf_getsize(ch->buffer);
462 pri = (ch->num == DS1_RECPRIMARY)? 1 : 0;
463
464 for (i = 0; i < 2; i++) {
558a398b 465 ch->slot[i].PgBase = addr;
984263bc
MD
466 ch->slot[i].PgLoopEnd = sz;
467 ch->slot[i].PgStart = 0;
468 ch->slot[i].NumOfLoops = 0;
469 }
470 x = (b16? 0x00 : 0x01) | (stereo? 0x02 : 0x00);
471 y = (48000 * 4096) / ch->spd;
472 y--;
e3869ec7 473 /* kprintf("pri = %d, x = %d, y = %d\n", pri, x, y); */
984263bc
MD
474 ds_wr(sc, pri? YDSXGR_ADCFORMAT : YDSXGR_RECFORMAT, x, 4);
475 ds_wr(sc, pri? YDSXGR_ADCSLOTSR : YDSXGR_RECSLOTSR, y, 4);
476}
477
478/* -------------------------------------------------------------------- */
479/* play channel interface */
480static void *
481ds1pchan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, struct pcm_channel *c, int dir)
482{
483 struct sc_info *sc = devinfo;
484 struct sc_pchinfo *ch;
485
486 KASSERT(dir == PCMDIR_PLAY, ("ds1pchan_init: bad direction"));
487
488 ch = &sc->pch[sc->pchn++];
489 ch->buffer = b;
490 ch->parent = sc;
491 ch->channel = c;
492 ch->dir = dir;
493 ch->fmt = AFMT_U8;
494 ch->spd = 8000;
495 ch->run = 0;
558a398b 496 if (sndbuf_alloc(ch->buffer, sc->buffer_dmat, sc->bufsz) != 0)
984263bc
MD
497 return NULL;
498 else {
499 ch->lsnum = sc->pslotfree;
500 ch->lslot = ds_allocpslot(sc);
501 ch->rsnum = sc->pslotfree;
502 ch->rslot = ds_allocpslot(sc);
503 ds_setuppch(ch);
504 return ch;
505 }
506}
507
508static int
509ds1pchan_setformat(kobj_t obj, void *data, u_int32_t format)
510{
511 struct sc_pchinfo *ch = data;
512
513 ch->fmt = format;
514
515 return 0;
516}
517
518static int
519ds1pchan_setspeed(kobj_t obj, void *data, u_int32_t speed)
520{
521 struct sc_pchinfo *ch = data;
522
523 ch->spd = speed;
524
525 return speed;
526}
527
528static int
529ds1pchan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize)
530{
531 struct sc_pchinfo *ch = data;
558a398b 532 struct sc_info *sc = ch->parent;
984263bc
MD
533 int drate;
534
535 /* irq rate is fixed at 187.5hz */
536 drate = ch->spd * sndbuf_getbps(ch->buffer);
558a398b
SS
537 blocksize = roundup2((drate << 8) / DS1_IRQHZ, 4);
538 sndbuf_resize(ch->buffer, sc->bufsz / blocksize, blocksize);
984263bc
MD
539
540 return blocksize;
541}
542
543/* semantic note: must start at beginning of buffer */
544static int
545ds1pchan_trigger(kobj_t obj, void *data, int go)
546{
547 struct sc_pchinfo *ch = data;
548 struct sc_info *sc = ch->parent;
549 int stereo;
550
551 if (go == PCMTRIG_EMLDMAWR || go == PCMTRIG_EMLDMARD)
552 return 0;
553 stereo = (ch->fmt & AFMT_STEREO)? 1 : 0;
554 if (go == PCMTRIG_START) {
555 ch->run = 1;
556 ds_setuppch(ch);
557 ds_enapslot(sc, ch->lsnum, 1);
558 ds_enapslot(sc, ch->rsnum, stereo);
559 snd_mtxlock(sc->lock);
560 ds_wr(sc, YDSXGR_MODE, 0x00000003, 4);
561 snd_mtxunlock(sc->lock);
562 } else {
563 ch->run = 0;
564 /* ds_setuppch(ch); */
565 ds_enapslot(sc, ch->lsnum, 0);
566 ds_enapslot(sc, ch->rsnum, 0);
567 }
568
569 return 0;
570}
571
572static int
573ds1pchan_getptr(kobj_t obj, void *data)
574{
575 struct sc_pchinfo *ch = data;
576 struct sc_info *sc = ch->parent;
577 volatile struct pbank *bank;
578 int ss;
579 u_int32_t ptr;
580
581 ss = (ch->fmt & AFMT_STEREO)? 1 : 0;
582 ss += (ch->fmt & AFMT_16BIT)? 1 : 0;
583
584 bank = ch->lslot + sc->currbank;
e3869ec7 585 /* kprintf("getptr: %d\n", bank->PgStart << ss); */
984263bc
MD
586 ptr = bank->PgStart;
587 ptr <<= ss;
588 return ptr;
589}
590
591static struct pcmchan_caps *
592ds1pchan_getcaps(kobj_t obj, void *data)
593{
594 return &ds_playcaps;
595}
596
597static kobj_method_t ds1pchan_methods[] = {
598 KOBJMETHOD(channel_init, ds1pchan_init),
599 KOBJMETHOD(channel_setformat, ds1pchan_setformat),
600 KOBJMETHOD(channel_setspeed, ds1pchan_setspeed),
601 KOBJMETHOD(channel_setblocksize, ds1pchan_setblocksize),
602 KOBJMETHOD(channel_trigger, ds1pchan_trigger),
603 KOBJMETHOD(channel_getptr, ds1pchan_getptr),
604 KOBJMETHOD(channel_getcaps, ds1pchan_getcaps),
605 { 0, 0 }
606};
607CHANNEL_DECLARE(ds1pchan);
608
609/* -------------------------------------------------------------------- */
610/* record channel interface */
611static void *
612ds1rchan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, struct pcm_channel *c, int dir)
613{
614 struct sc_info *sc = devinfo;
615 struct sc_rchinfo *ch;
616
617 KASSERT(dir == PCMDIR_REC, ("ds1rchan_init: bad direction"));
618
619 ch = &sc->rch[sc->rchn];
620 ch->num = sc->rchn++;
621 ch->buffer = b;
622 ch->parent = sc;
623 ch->channel = c;
624 ch->dir = dir;
625 ch->fmt = AFMT_U8;
626 ch->spd = 8000;
558a398b 627 if (sndbuf_alloc(ch->buffer, sc->buffer_dmat, sc->bufsz) != 0)
984263bc
MD
628 return NULL;
629 else {
630 ch->slot = (ch->num == DS1_RECPRIMARY)? sc->rbank + 2: sc->rbank;
631 ds_setuprch(ch);
632 return ch;
633 }
634}
635
636static int
637ds1rchan_setformat(kobj_t obj, void *data, u_int32_t format)
638{
639 struct sc_rchinfo *ch = data;
640
641 ch->fmt = format;
642
643 return 0;
644}
645
646static int
647ds1rchan_setspeed(kobj_t obj, void *data, u_int32_t speed)
648{
649 struct sc_rchinfo *ch = data;
650
651 ch->spd = speed;
652
653 return speed;
654}
655
656static int
657ds1rchan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize)
658{
659 struct sc_rchinfo *ch = data;
558a398b 660 struct sc_info *sc = ch->parent;
984263bc
MD
661 int drate;
662
663 /* irq rate is fixed at 187.5hz */
664 drate = ch->spd * sndbuf_getbps(ch->buffer);
558a398b
SS
665 blocksize = roundup2((drate << 8) / DS1_IRQHZ, 4);
666 sndbuf_resize(ch->buffer, sc->bufsz / blocksize, blocksize);
984263bc
MD
667
668 return blocksize;
669}
670
671/* semantic note: must start at beginning of buffer */
672static int
673ds1rchan_trigger(kobj_t obj, void *data, int go)
674{
675 struct sc_rchinfo *ch = data;
676 struct sc_info *sc = ch->parent;
677 u_int32_t x;
678
679 if (go == PCMTRIG_EMLDMAWR || go == PCMTRIG_EMLDMARD)
680 return 0;
681 if (go == PCMTRIG_START) {
682 ch->run = 1;
683 ds_setuprch(ch);
684 snd_mtxlock(sc->lock);
685 x = ds_rd(sc, YDSXGR_MAPOFREC, 4);
686 x |= (ch->num == DS1_RECPRIMARY)? 0x02 : 0x01;
687 ds_wr(sc, YDSXGR_MAPOFREC, x, 4);
688 ds_wr(sc, YDSXGR_MODE, 0x00000003, 4);
689 snd_mtxunlock(sc->lock);
690 } else {
691 ch->run = 0;
692 snd_mtxlock(sc->lock);
693 x = ds_rd(sc, YDSXGR_MAPOFREC, 4);
694 x &= ~((ch->num == DS1_RECPRIMARY)? 0x02 : 0x01);
695 ds_wr(sc, YDSXGR_MAPOFREC, x, 4);
696 snd_mtxunlock(sc->lock);
697 }
698
699 return 0;
700}
701
702static int
703ds1rchan_getptr(kobj_t obj, void *data)
704{
705 struct sc_rchinfo *ch = data;
706 struct sc_info *sc = ch->parent;
707
708 return ch->slot[sc->currbank].PgStart;
709}
710
711static struct pcmchan_caps *
712ds1rchan_getcaps(kobj_t obj, void *data)
713{
714 return &ds_reccaps;
715}
716
717static kobj_method_t ds1rchan_methods[] = {
718 KOBJMETHOD(channel_init, ds1rchan_init),
719 KOBJMETHOD(channel_setformat, ds1rchan_setformat),
720 KOBJMETHOD(channel_setspeed, ds1rchan_setspeed),
721 KOBJMETHOD(channel_setblocksize, ds1rchan_setblocksize),
722 KOBJMETHOD(channel_trigger, ds1rchan_trigger),
723 KOBJMETHOD(channel_getptr, ds1rchan_getptr),
724 KOBJMETHOD(channel_getcaps, ds1rchan_getcaps),
725 { 0, 0 }
726};
727CHANNEL_DECLARE(ds1rchan);
728
729/* -------------------------------------------------------------------- */
730/* The interrupt handler */
731static void
732ds_intr(void *p)
733{
734 struct sc_info *sc = (struct sc_info *)p;
735 u_int32_t i, x;
736
737 snd_mtxlock(sc->lock);
738 i = ds_rd(sc, YDSXGR_STATUS, 4);
739 if (i & 0x00008000)
740 device_printf(sc->dev, "timeout irq\n");
741 if (i & 0x80008000) {
742 ds_wr(sc, YDSXGR_STATUS, i & 0x80008000, 4);
743 sc->currbank = ds_rd(sc, YDSXGR_CTRLSELECT, 4) & 0x00000001;
744
745 x = 0;
746 for (i = 0; i < DS1_CHANS; i++) {
747 if (sc->pch[i].run) {
748 x = 1;
558a398b 749 snd_mtxunlock(sc->lock);
984263bc 750 chn_intr(sc->pch[i].channel);
558a398b 751 snd_mtxlock(sc->lock);
984263bc
MD
752 }
753 }
754 for (i = 0; i < 2; i++) {
755 if (sc->rch[i].run) {
756 x = 1;
558a398b 757 snd_mtxunlock(sc->lock);
984263bc 758 chn_intr(sc->rch[i].channel);
558a398b 759 snd_mtxlock(sc->lock);
984263bc
MD
760 }
761 }
762 i = ds_rd(sc, YDSXGR_MODE, 4);
763 if (x)
764 ds_wr(sc, YDSXGR_MODE, i | 0x00000002, 4);
765
766 }
767 snd_mtxunlock(sc->lock);
768}
769
770/* -------------------------------------------------------------------- */
771
772/*
773 * Probe and attach the card
774 */
775
776static void
777ds_setmap(void *arg, bus_dma_segment_t *segs, int nseg, int error)
778{
779 struct sc_info *sc = arg;
780
781 sc->ctrlbase = error? 0 : (u_int32_t)segs->ds_addr;
782
783 if (bootverbose) {
e3869ec7 784 kprintf("ds1: setmap (%lx, %lx), nseg=%d, error=%d\n",
984263bc
MD
785 (unsigned long)segs->ds_addr, (unsigned long)segs->ds_len,
786 nseg, error);
787 }
788}
789
790static int
791ds_init(struct sc_info *sc)
792{
793 int i;
794 u_int32_t *ci, r, pcs, rcs, ecs, ws, memsz, cb;
795 u_int8_t *t;
796 void *buf;
797
798 ci = ds_devs[sc->type].mcode;
799
800 ds_wr(sc, YDSXGR_NATIVEDACOUTVOL, 0x00000000, 4);
801 ds_enadsp(sc, 0);
802 ds_wr(sc, YDSXGR_MODE, 0x00010000, 4);
803 ds_wr(sc, YDSXGR_MODE, 0x00000000, 4);
804 ds_wr(sc, YDSXGR_MAPOFREC, 0x00000000, 4);
805 ds_wr(sc, YDSXGR_MAPOFEFFECT, 0x00000000, 4);
806 ds_wr(sc, YDSXGR_PLAYCTRLBASE, 0x00000000, 4);
807 ds_wr(sc, YDSXGR_RECCTRLBASE, 0x00000000, 4);
808 ds_wr(sc, YDSXGR_EFFCTRLBASE, 0x00000000, 4);
809 r = ds_rd(sc, YDSXGR_GLOBALCTRL, 2);
810 ds_wr(sc, YDSXGR_GLOBALCTRL, r & ~0x0007, 2);
811
812 for (i = 0; i < YDSXG_DSPLENGTH; i += 4)
813 ds_wr(sc, YDSXGR_DSPINSTRAM + i, DspInst[i >> 2], 4);
814
815 for (i = 0; i < YDSXG_CTRLLENGTH; i += 4)
816 ds_wr(sc, YDSXGR_CTRLINSTRAM + i, ci[i >> 2], 4);
817
818 ds_enadsp(sc, 1);
819
820 pcs = 0;
821 for (i = 100; i > 0; i--) {
822 pcs = ds_rd(sc, YDSXGR_PLAYCTRLSIZE, 4) << 2;
823 if (pcs == sizeof(struct pbank))
824 break;
825 DELAY(1000);
826 }
827 if (pcs != sizeof(struct pbank)) {
828 device_printf(sc->dev, "preposterous playctrlsize (%d)\n", pcs);
829 return -1;
830 }
831 rcs = ds_rd(sc, YDSXGR_RECCTRLSIZE, 4) << 2;
832 ecs = ds_rd(sc, YDSXGR_EFFCTRLSIZE, 4) << 2;
833 ws = ds_rd(sc, YDSXGR_WORKSIZE, 4) << 2;
834
835 memsz = 64 * 2 * pcs + 2 * 2 * rcs + 5 * 2 * ecs + ws;
836 memsz += (64 + 1) * 4;
837
838 if (sc->regbase == NULL) {
839 if (bus_dma_tag_create(NULL, 2, 0, BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR,
558a398b
SS
840 NULL, NULL, memsz, 1, memsz, 0,
841 &sc->control_dmat))
984263bc
MD
842 return -1;
843 if (bus_dmamem_alloc(sc->control_dmat, &buf, BUS_DMA_NOWAIT, &sc->map))
844 return -1;
845 if (bus_dmamap_load(sc->control_dmat, sc->map, buf, memsz, ds_setmap, sc, 0) || !sc->ctrlbase) {
846 device_printf(sc->dev, "pcs=%d, rcs=%d, ecs=%d, ws=%d, memsz=%d\n",
847 pcs, rcs, ecs, ws, memsz);
848 return -1;
849 }
850 sc->regbase = buf;
851 } else
852 buf = sc->regbase;
853
854 cb = 0;
855 t = buf;
856 ds_wr(sc, YDSXGR_WORKBASE, sc->ctrlbase + cb, 4);
857 cb += ws;
858 sc->pbase = (u_int32_t *)(t + cb);
e3869ec7 859 /* kprintf("pbase = %p -> 0x%x\n", sc->pbase, sc->ctrlbase + cb); */
984263bc
MD
860 ds_wr(sc, YDSXGR_PLAYCTRLBASE, sc->ctrlbase + cb, 4);
861 cb += (64 + 1) * 4;
862 sc->rbank = (struct rbank *)(t + cb);
863 ds_wr(sc, YDSXGR_RECCTRLBASE, sc->ctrlbase + cb, 4);
864 cb += 2 * 2 * rcs;
865 ds_wr(sc, YDSXGR_EFFCTRLBASE, sc->ctrlbase + cb, 4);
866 cb += 5 * 2 * ecs;
867
868 sc->pbankbase = sc->ctrlbase + cb;
869 sc->pbanksize = pcs;
870 for (i = 0; i < 64; i++) {
871 wrl(sc, &sc->pbase[i + 1], 0);
872 sc->pbank[i * 2] = (struct pbank *)(t + cb);
e3869ec7 873 /* kprintf("pbank[%d] = %p -> 0x%x; ", i * 2, (struct pbank *)(t + cb), sc->ctrlbase + cb - vtophys(t + cb)); */
984263bc
MD
874 cb += pcs;
875 sc->pbank[i * 2 + 1] = (struct pbank *)(t + cb);
e3869ec7 876 /* kprintf("pbank[%d] = %p -> 0x%x\n", i * 2 + 1, (struct pbank *)(t + cb), sc->ctrlbase + cb - vtophys(t + cb)); */
984263bc
MD
877 cb += pcs;
878 }
879 wrl(sc, &sc->pbase[0], DS1_CHANS * 2);
880
881 sc->pchn = sc->rchn = 0;
882 ds_wr(sc, YDSXGR_NATIVEDACOUTVOL, 0x3fff3fff, 4);
883 ds_wr(sc, YDSXGR_NATIVEADCINVOL, 0x3fff3fff, 4);
884 ds_wr(sc, YDSXGR_NATIVEDACINVOL, 0x3fff3fff, 4);
885
886 return 0;
887}
888
889static int
890ds_uninit(struct sc_info *sc)
891{
892 ds_wr(sc, YDSXGR_NATIVEDACOUTVOL, 0x00000000, 4);
893 ds_wr(sc, YDSXGR_NATIVEADCINVOL, 0, 4);
894 ds_wr(sc, YDSXGR_NATIVEDACINVOL, 0, 4);
895 ds_enadsp(sc, 0);
896 ds_wr(sc, YDSXGR_MODE, 0x00010000, 4);
897 ds_wr(sc, YDSXGR_MAPOFREC, 0x00000000, 4);
898 ds_wr(sc, YDSXGR_MAPOFEFFECT, 0x00000000, 4);
899 ds_wr(sc, YDSXGR_PLAYCTRLBASE, 0x00000000, 4);
900 ds_wr(sc, YDSXGR_RECCTRLBASE, 0x00000000, 4);
901 ds_wr(sc, YDSXGR_EFFCTRLBASE, 0x00000000, 4);
902 ds_wr(sc, YDSXGR_GLOBALCTRL, 0, 2);
903
904 bus_dmamap_unload(sc->control_dmat, sc->map);
905 bus_dmamem_free(sc->control_dmat, sc->regbase, sc->map);
906
907 return 0;
908}
909
910static int
911ds_finddev(u_int32_t dev, u_int32_t subdev)
912{
913 int i;
914
915 for (i = 0; ds_devs[i].dev; i++) {
916 if (ds_devs[i].dev == dev &&
917 (ds_devs[i].subdev == subdev || ds_devs[i].subdev == 0))
918 return i;
919 }
920 return -1;
921}
922
923static int
924ds_pci_probe(device_t dev)
925{
926 int i;
927 u_int32_t subdev;
928
929 subdev = (pci_get_subdevice(dev) << 16) | pci_get_subvendor(dev);
930 i = ds_finddev(pci_get_devid(dev), subdev);
931 if (i >= 0) {
932 device_set_desc(dev, ds_devs[i].name);
558a398b 933 return BUS_PROBE_DEFAULT;
984263bc
MD
934 } else
935 return ENXIO;
936}
937
938static int
939ds_pci_attach(device_t dev)
940{
941 u_int32_t data;
942 u_int32_t subdev, i;
943 struct sc_info *sc;
944 struct ac97_info *codec = NULL;
945 char status[SND_STATUSLEN];
946
efda3bd0 947 if ((sc = kmalloc(sizeof(*sc), M_DEVBUF, M_WAITOK | M_ZERO)) == NULL) {
984263bc
MD
948 device_printf(dev, "cannot allocate softc\n");
949 return ENXIO;
950 }
951
952 sc->lock = snd_mtxcreate(device_get_nameunit(dev), "sound softc");
953 sc->dev = dev;
954 subdev = (pci_get_subdevice(dev) << 16) | pci_get_subvendor(dev);
955 sc->type = ds_finddev(pci_get_devid(dev), subdev);
956 sc->rev = pci_get_revid(dev);
957
958 data = pci_read_config(dev, PCIR_COMMAND, 2);
959 data |= (PCIM_CMD_PORTEN|PCIM_CMD_MEMEN|PCIM_CMD_BUSMASTEREN);
960 pci_write_config(dev, PCIR_COMMAND, data, 2);
961 data = pci_read_config(dev, PCIR_COMMAND, 2);
962
558a398b
SS
963 sc->regid = PCIR_BAR(0);
964 sc->reg = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->regid,
965 RF_ACTIVE);
984263bc
MD
966 if (!sc->reg) {
967 device_printf(dev, "unable to map register space\n");
968 goto bad;
969 }
970
971 sc->st = rman_get_bustag(sc->reg);
972 sc->sh = rman_get_bushandle(sc->reg);
973
974 sc->bufsz = pcm_getbuffersize(dev, 4096, DS1_BUFFSIZE, 65536);
975
976 if (bus_dma_tag_create(/*parent*/NULL, /*alignment*/2, /*boundary*/0,
977 /*lowaddr*/BUS_SPACE_MAXADDR_32BIT,
978 /*highaddr*/BUS_SPACE_MAXADDR,
979 /*filter*/NULL, /*filterarg*/NULL,
980 /*maxsize*/sc->bufsz, /*nsegments*/1, /*maxsegz*/0x3ffff,
558a398b
SS
981 /*flags*/0,
982 &sc->buffer_dmat) != 0) {
984263bc
MD
983 device_printf(dev, "unable to create dma tag\n");
984 goto bad;
985 }
986
987 sc->regbase = NULL;
988 if (ds_init(sc) == -1) {
989 device_printf(dev, "unable to initialize the card\n");
990 goto bad;
991 }
992
993 codec = AC97_CREATE(dev, sc, ds_ac97);
994 if (codec == NULL)
995 goto bad;
558a398b
SS
996 /*
997 * Turn on inverted external amplifier sense flags for few
998 * 'special' boards.
999 */
1000 switch (subdev) {
1001 case 0x81171033: /* NEC ValueStar (VT550/0) */
1002 ac97_setflags(codec, ac97_getflags(codec) | AC97_F_EAPD_INV);
1003 break;
1004 default:
1005 break;
1006 }
984263bc
MD
1007 mixer_init(dev, ac97_getmixerclass(), codec);
1008
1009 sc->irqid = 0;
558a398b
SS
1010 sc->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->irqid,
1011 RF_ACTIVE | RF_SHAREABLE);
1012 if (!sc->irq || snd_setup_intr(dev, sc->irq, INTR_MPSAFE, ds_intr, sc, &sc->ih)) {
984263bc
MD
1013 device_printf(dev, "unable to map interrupt\n");
1014 goto bad;
1015 }
1016
558a398b
SS
1017 ksnprintf(status, SND_STATUSLEN, "at memory 0x%lx irq %ld %s",
1018 rman_get_start(sc->reg), rman_get_start(sc->irq),PCM_KLDSTRING(snd_ds1));
984263bc
MD
1019
1020 if (pcm_register(dev, sc, DS1_CHANS, 2))
1021 goto bad;
1022 for (i = 0; i < DS1_CHANS; i++)
1023 pcm_addchan(dev, PCMDIR_PLAY, &ds1pchan_class, sc);
1024 for (i = 0; i < 2; i++)
1025 pcm_addchan(dev, PCMDIR_REC, &ds1rchan_class, sc);
1026 pcm_setstatus(dev, status);
1027
1028 return 0;
1029
1030bad:
1031 if (codec)
1032 ac97_destroy(codec);
1033 if (sc->reg)
1034 bus_release_resource(dev, SYS_RES_MEMORY, sc->regid, sc->reg);
1035 if (sc->ih)
1036 bus_teardown_intr(dev, sc->irq, sc->ih);
1037 if (sc->irq)
1038 bus_release_resource(dev, SYS_RES_IRQ, sc->irqid, sc->irq);
1039 if (sc->buffer_dmat)
1040 bus_dma_tag_destroy(sc->buffer_dmat);
1041 if (sc->control_dmat)
1042 bus_dma_tag_destroy(sc->control_dmat);
1043 if (sc->lock)
1044 snd_mtxfree(sc->lock);
efda3bd0 1045 kfree(sc, M_DEVBUF);
984263bc
MD
1046 return ENXIO;
1047}
1048
1049static int
1050ds_pci_resume(device_t dev)
1051{
1052 struct sc_info *sc;
1053
1054 sc = pcm_getdevinfo(dev);
1055
1056 if (ds_init(sc) == -1) {
1057 device_printf(dev, "unable to reinitialize the card\n");
1058 return ENXIO;
1059 }
1060 if (mixer_reinit(dev) == -1) {
1061 device_printf(dev, "unable to reinitialize the mixer\n");
1062 return ENXIO;
1063 }
1064 return 0;
1065}
1066
1067static int
1068ds_pci_detach(device_t dev)
1069{
1070 int r;
1071 struct sc_info *sc;
1072
1073 r = pcm_unregister(dev);
1074 if (r)
1075 return r;
1076
1077 sc = pcm_getdevinfo(dev);
1078 ds_uninit(sc);
1079 bus_release_resource(dev, SYS_RES_MEMORY, sc->regid, sc->reg);
1080 bus_teardown_intr(dev, sc->irq, sc->ih);
1081 bus_release_resource(dev, SYS_RES_IRQ, sc->irqid, sc->irq);
1082 bus_dma_tag_destroy(sc->buffer_dmat);
1083 bus_dma_tag_destroy(sc->control_dmat);
1084 snd_mtxfree(sc->lock);
efda3bd0 1085 kfree(sc, M_DEVBUF);
984263bc
MD
1086 return 0;
1087}
1088
1089static device_method_t ds1_methods[] = {
1090 /* Device interface */
1091 DEVMETHOD(device_probe, ds_pci_probe),
1092 DEVMETHOD(device_attach, ds_pci_attach),
1093 DEVMETHOD(device_detach, ds_pci_detach),
1094 DEVMETHOD(device_resume, ds_pci_resume),
1095 { 0, 0 }
1096};
1097
1098static driver_t ds1_driver = {
1099 "pcm",
1100 ds1_methods,
1101 PCM_SOFTC_SIZE,
1102};
1103
1104DRIVER_MODULE(snd_ds1, pci, ds1_driver, pcm_devclass, 0, 0);
558a398b 1105MODULE_DEPEND(snd_ds1, sound, SOUND_MINVER, SOUND_PREFVER, SOUND_MAXVER);
984263bc 1106MODULE_VERSION(snd_ds1, 1);