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