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