]> CyberLeo.Net >> Repos - FreeBSD/stable/8.git/blob - sys/dev/sound/pci/t4dwave.c
Copy head to stable/8 as part of 8.0 Release cycle.
[FreeBSD/stable/8.git] / sys / dev / sound / pci / t4dwave.c
1 /*-
2  * Copyright (c) 1999 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 #ifdef HAVE_KERNEL_OPTION_HEADERS
28 #include "opt_snd.h"
29 #endif
30
31 #include <dev/sound/pcm/sound.h>
32 #include <dev/sound/pcm/ac97.h>
33 #include <dev/sound/pci/t4dwave.h>
34
35 #include <dev/pci/pcireg.h>
36 #include <dev/pci/pcivar.h>
37
38 SND_DECLARE_FILE("$FreeBSD$");
39
40 /* -------------------------------------------------------------------- */
41
42 #define TDX_PCI_ID      0x20001023
43 #define TNX_PCI_ID      0x20011023
44 #define ALI_PCI_ID      0x545110b9
45 #define SPA_PCI_ID      0x70181039
46
47 #define TR_DEFAULT_BUFSZ        0x1000
48 #define TR_TIMEOUT_CDC  0xffff
49 #define TR_MAXPLAYCH    4
50 /*
51  * Though, it's not clearly documented in trident datasheet, trident
52  * audio cards can't handle DMA addresses located above 1GB. The LBA
53  * (loop begin address) register which holds DMA base address is 32bits
54  * register.
55  * But the MSB 2bits are used for other purposes(I guess it is really
56  * bad idea). This effectivly limits the DMA address space up to 1GB.
57  */
58 #define TR_MAXADDR      ((1 << 30) - 1)
59
60
61 struct tr_info;
62
63 /* channel registers */
64 struct tr_chinfo {
65         u_int32_t cso, alpha, fms, fmc, ec;
66         u_int32_t lba;
67         u_int32_t eso, delta;
68         u_int32_t rvol, cvol;
69         u_int32_t gvsel, pan, vol, ctrl;
70         u_int32_t active:1, was_active:1;
71         int index, bufhalf;
72         struct snd_dbuf *buffer;
73         struct pcm_channel *channel;
74         struct tr_info *parent;
75 };
76
77 struct tr_rchinfo {
78         u_int32_t delta;
79         u_int32_t active:1, was_active:1;
80         struct snd_dbuf *buffer;
81         struct pcm_channel *channel;
82         struct tr_info *parent;
83 };
84
85 /* device private data */
86 struct tr_info {
87         u_int32_t type;
88         u_int32_t rev;
89
90         bus_space_tag_t st;
91         bus_space_handle_t sh;
92         bus_dma_tag_t parent_dmat;
93
94         struct resource *reg, *irq;
95         int regtype, regid, irqid;
96         void *ih;
97
98         struct mtx *lock;
99
100         u_int32_t playchns;
101         unsigned int bufsz;
102
103         struct tr_chinfo chinfo[TR_MAXPLAYCH];
104         struct tr_rchinfo recchinfo;
105 };
106
107 /* -------------------------------------------------------------------- */
108
109 static u_int32_t tr_recfmt[] = {
110         SND_FORMAT(AFMT_U8, 1, 0),
111         SND_FORMAT(AFMT_U8, 2, 0),
112         SND_FORMAT(AFMT_S8, 1, 0),
113         SND_FORMAT(AFMT_S8, 2, 0),
114         SND_FORMAT(AFMT_S16_LE, 1, 0),
115         SND_FORMAT(AFMT_S16_LE, 2, 0),
116         SND_FORMAT(AFMT_U16_LE, 1, 0),
117         SND_FORMAT(AFMT_U16_LE, 2, 0),
118         0
119 };
120 static struct pcmchan_caps tr_reccaps = {4000, 48000, tr_recfmt, 0};
121
122 static u_int32_t tr_playfmt[] = {
123         SND_FORMAT(AFMT_U8, 1, 0),
124         SND_FORMAT(AFMT_U8, 2, 0),
125         SND_FORMAT(AFMT_S8, 1, 0),
126         SND_FORMAT(AFMT_S8, 2, 0),
127         SND_FORMAT(AFMT_S16_LE, 1, 0),
128         SND_FORMAT(AFMT_S16_LE, 2, 0),
129         SND_FORMAT(AFMT_U16_LE, 1, 0),
130         SND_FORMAT(AFMT_U16_LE, 2, 0),
131         0
132 };
133 static struct pcmchan_caps tr_playcaps = {4000, 48000, tr_playfmt, 0};
134
135 /* -------------------------------------------------------------------- */
136
137 /* Hardware */
138
139 static u_int32_t
140 tr_rd(struct tr_info *tr, int regno, int size)
141 {
142         switch(size) {
143         case 1:
144                 return bus_space_read_1(tr->st, tr->sh, regno);
145         case 2:
146                 return bus_space_read_2(tr->st, tr->sh, regno);
147         case 4:
148                 return bus_space_read_4(tr->st, tr->sh, regno);
149         default:
150                 return 0xffffffff;
151         }
152 }
153
154 static void
155 tr_wr(struct tr_info *tr, int regno, u_int32_t data, int size)
156 {
157         switch(size) {
158         case 1:
159                 bus_space_write_1(tr->st, tr->sh, regno, data);
160                 break;
161         case 2:
162                 bus_space_write_2(tr->st, tr->sh, regno, data);
163                 break;
164         case 4:
165                 bus_space_write_4(tr->st, tr->sh, regno, data);
166                 break;
167         }
168 }
169
170 /* -------------------------------------------------------------------- */
171 /* ac97 codec */
172
173 static int
174 tr_rdcd(kobj_t obj, void *devinfo, int regno)
175 {
176         struct tr_info *tr = (struct tr_info *)devinfo;
177         int i, j, treg, trw;
178
179         switch (tr->type) {
180         case SPA_PCI_ID:
181                 treg=SPA_REG_CODECRD;
182                 trw=SPA_CDC_RWSTAT;
183                 break;
184         case ALI_PCI_ID:
185                 if (tr->rev > 0x01)
186                   treg=TDX_REG_CODECWR;
187                 else
188                   treg=TDX_REG_CODECRD;
189                 trw=TDX_CDC_RWSTAT;
190                 break;
191         case TDX_PCI_ID:
192                 treg=TDX_REG_CODECRD;
193                 trw=TDX_CDC_RWSTAT;
194                 break;
195         case TNX_PCI_ID:
196                 treg=(regno & 0x100)? TNX_REG_CODEC2RD : TNX_REG_CODEC1RD;
197                 trw=TNX_CDC_RWSTAT;
198                 break;
199         default:
200                 printf("!!! tr_rdcd defaulted !!!\n");
201                 return -1;
202         }
203
204         i = j = 0;
205
206         regno &= 0x7f;
207         snd_mtxlock(tr->lock);
208         if (tr->type == ALI_PCI_ID) {
209                 u_int32_t chk1, chk2;
210                 j = trw;
211                 for (i = TR_TIMEOUT_CDC; (i > 0) && (j & trw); i--)
212                         j = tr_rd(tr, treg, 4);
213                 if (i > 0) {
214                         chk1 = tr_rd(tr, 0xc8, 4);
215                         chk2 = tr_rd(tr, 0xc8, 4);
216                         for (i = TR_TIMEOUT_CDC; (i > 0) && (chk1 == chk2);
217                                         i--)
218                                 chk2 = tr_rd(tr, 0xc8, 4);
219                 }
220         }
221         if (tr->type != ALI_PCI_ID || i > 0) {
222                 tr_wr(tr, treg, regno | trw, 4);
223                 j=trw;
224                 for (i=TR_TIMEOUT_CDC; (i > 0) && (j & trw); i--)
225                         j=tr_rd(tr, treg, 4);
226         }
227         snd_mtxunlock(tr->lock);
228         if (i == 0) printf("codec timeout during read of register %x\n", regno);
229         return (j >> TR_CDC_DATA) & 0xffff;
230 }
231
232 static int
233 tr_wrcd(kobj_t obj, void *devinfo, int regno, u_int32_t data)
234 {
235         struct tr_info *tr = (struct tr_info *)devinfo;
236         int i, j, treg, trw;
237
238         switch (tr->type) {
239         case SPA_PCI_ID:
240                 treg=SPA_REG_CODECWR;
241                 trw=SPA_CDC_RWSTAT;
242                 break;
243         case ALI_PCI_ID:
244         case TDX_PCI_ID:
245                 treg=TDX_REG_CODECWR;
246                 trw=TDX_CDC_RWSTAT;
247                 break;
248         case TNX_PCI_ID:
249                 treg=TNX_REG_CODECWR;
250                 trw=TNX_CDC_RWSTAT | ((regno & 0x100)? TNX_CDC_SEC : 0);
251                 break;
252         default:
253                 printf("!!! tr_wrcd defaulted !!!");
254                 return -1;
255         }
256
257         i = 0;
258
259         regno &= 0x7f;
260 #if 0
261         printf("tr_wrcd: reg %x was %x", regno, tr_rdcd(devinfo, regno));
262 #endif
263         j=trw;
264         snd_mtxlock(tr->lock);
265         if (tr->type == ALI_PCI_ID) {
266                 j = trw;
267                 for (i = TR_TIMEOUT_CDC; (i > 0) && (j & trw); i--)
268                         j = tr_rd(tr, treg, 4);
269                 if (i > 0) {
270                         u_int32_t chk1, chk2;
271                         chk1 = tr_rd(tr, 0xc8, 4);
272                         chk2 = tr_rd(tr, 0xc8, 4);
273                         for (i = TR_TIMEOUT_CDC; (i > 0) && (chk1 == chk2);
274                                         i--)
275                                 chk2 = tr_rd(tr, 0xc8, 4);
276                 }
277         }
278         if (tr->type != ALI_PCI_ID || i > 0) {
279                 for (i=TR_TIMEOUT_CDC; (i>0) && (j & trw); i--)
280                         j=tr_rd(tr, treg, 4);
281                 if (tr->type == ALI_PCI_ID && tr->rev > 0x01)
282                         trw |= 0x0100;
283                 tr_wr(tr, treg, (data << TR_CDC_DATA) | regno | trw, 4);
284         }
285 #if 0
286         printf(" - wrote %x, now %x\n", data, tr_rdcd(devinfo, regno));
287 #endif
288         snd_mtxunlock(tr->lock);
289         if (i==0) printf("codec timeout writing %x, data %x\n", regno, data);
290         return (i > 0)? 0 : -1;
291 }
292
293 static kobj_method_t tr_ac97_methods[] = {
294         KOBJMETHOD(ac97_read,           tr_rdcd),
295         KOBJMETHOD(ac97_write,          tr_wrcd),
296         KOBJMETHOD_END
297 };
298 AC97_DECLARE(tr_ac97);
299
300 /* -------------------------------------------------------------------- */
301 /* playback channel interrupts */
302
303 #if 0
304 static u_int32_t
305 tr_testint(struct tr_chinfo *ch)
306 {
307         struct tr_info *tr = ch->parent;
308         int bank, chan;
309
310         bank = (ch->index & 0x20) ? 1 : 0;
311         chan = ch->index & 0x1f;
312         return tr_rd(tr, bank? TR_REG_ADDRINTB : TR_REG_ADDRINTA, 4) & (1 << chan);
313 }
314 #endif
315
316 static void
317 tr_clrint(struct tr_chinfo *ch)
318 {
319         struct tr_info *tr = ch->parent;
320         int bank, chan;
321
322         bank = (ch->index & 0x20) ? 1 : 0;
323         chan = ch->index & 0x1f;
324         tr_wr(tr, bank? TR_REG_ADDRINTB : TR_REG_ADDRINTA, 1 << chan, 4);
325 }
326
327 static void
328 tr_enaint(struct tr_chinfo *ch, int enable)
329 {
330         struct tr_info *tr = ch->parent;
331         u_int32_t i, reg;
332         int bank, chan;
333
334         snd_mtxlock(tr->lock);
335         bank = (ch->index & 0x20) ? 1 : 0;
336         chan = ch->index & 0x1f;
337         reg = bank? TR_REG_INTENB : TR_REG_INTENA;
338
339         i = tr_rd(tr, reg, 4);
340         i &= ~(1 << chan);
341         i |= (enable? 1 : 0) << chan;
342
343         tr_clrint(ch);
344         tr_wr(tr, reg, i, 4);
345         snd_mtxunlock(tr->lock);
346 }
347
348 /* playback channels */
349
350 static void
351 tr_selch(struct tr_chinfo *ch)
352 {
353         struct tr_info *tr = ch->parent;
354         int i;
355
356         i = tr_rd(tr, TR_REG_CIR, 4);
357         i &= ~TR_CIR_MASK;
358         i |= ch->index & 0x3f;
359         tr_wr(tr, TR_REG_CIR, i, 4);
360 }
361
362 static void
363 tr_startch(struct tr_chinfo *ch)
364 {
365         struct tr_info *tr = ch->parent;
366         int bank, chan;
367
368         bank = (ch->index & 0x20) ? 1 : 0;
369         chan = ch->index & 0x1f;
370         tr_wr(tr, bank? TR_REG_STARTB : TR_REG_STARTA, 1 << chan, 4);
371 }
372
373 static void
374 tr_stopch(struct tr_chinfo *ch)
375 {
376         struct tr_info *tr = ch->parent;
377         int bank, chan;
378
379         bank = (ch->index & 0x20) ? 1 : 0;
380         chan = ch->index & 0x1f;
381         tr_wr(tr, bank? TR_REG_STOPB : TR_REG_STOPA, 1 << chan, 4);
382 }
383
384 static void
385 tr_wrch(struct tr_chinfo *ch)
386 {
387         struct tr_info *tr = ch->parent;
388         u_int32_t cr[TR_CHN_REGS], i;
389
390         ch->gvsel       &= 0x00000001;
391         ch->fmc         &= 0x00000003;
392         ch->fms         &= 0x0000000f;
393         ch->ctrl        &= 0x0000000f;
394         ch->pan         &= 0x0000007f;
395         ch->rvol        &= 0x0000007f;
396         ch->cvol        &= 0x0000007f;
397         ch->vol         &= 0x000000ff;
398         ch->ec          &= 0x00000fff;
399         ch->alpha       &= 0x00000fff;
400         ch->delta       &= 0x0000ffff;
401         ch->lba         &= 0x3fffffff;
402
403         cr[1]=ch->lba;
404         cr[3]=(ch->fmc<<14) | (ch->rvol<<7) | (ch->cvol);
405         cr[4]=(ch->gvsel<<31) | (ch->pan<<24) | (ch->vol<<16) | (ch->ctrl<<12) | (ch->ec);
406
407         switch (tr->type) {
408         case SPA_PCI_ID:
409         case ALI_PCI_ID:
410         case TDX_PCI_ID:
411                 ch->cso &= 0x0000ffff;
412                 ch->eso &= 0x0000ffff;
413                 cr[0]=(ch->cso<<16) | (ch->alpha<<4) | (ch->fms);
414                 cr[2]=(ch->eso<<16) | (ch->delta);
415                 break;
416         case TNX_PCI_ID:
417                 ch->cso &= 0x00ffffff;
418                 ch->eso &= 0x00ffffff;
419                 cr[0]=((ch->delta & 0xff)<<24) | (ch->cso);
420                 cr[2]=((ch->delta>>8)<<24) | (ch->eso);
421                 cr[3]|=(ch->alpha<<20) | (ch->fms<<16) | (ch->fmc<<14);
422                 break;
423         }
424         snd_mtxlock(tr->lock);
425         tr_selch(ch);
426         for (i=0; i<TR_CHN_REGS; i++)
427                 tr_wr(tr, TR_REG_CHNBASE+(i<<2), cr[i], 4);
428         snd_mtxunlock(tr->lock);
429 }
430
431 static void
432 tr_rdch(struct tr_chinfo *ch)
433 {
434         struct tr_info *tr = ch->parent;
435         u_int32_t cr[5], i;
436
437         snd_mtxlock(tr->lock);
438         tr_selch(ch);
439         for (i=0; i<5; i++)
440                 cr[i]=tr_rd(tr, TR_REG_CHNBASE+(i<<2), 4);
441         snd_mtxunlock(tr->lock);
442
443
444         ch->lba=        (cr[1] & 0x3fffffff);
445         ch->fmc=        (cr[3] & 0x0000c000) >> 14;
446         ch->rvol=       (cr[3] & 0x00003f80) >> 7;
447         ch->cvol=       (cr[3] & 0x0000007f);
448         ch->gvsel=      (cr[4] & 0x80000000) >> 31;
449         ch->pan=        (cr[4] & 0x7f000000) >> 24;
450         ch->vol=        (cr[4] & 0x00ff0000) >> 16;
451         ch->ctrl=       (cr[4] & 0x0000f000) >> 12;
452         ch->ec=         (cr[4] & 0x00000fff);
453         switch(tr->type) {
454         case SPA_PCI_ID:
455         case ALI_PCI_ID:
456         case TDX_PCI_ID:
457                 ch->cso=        (cr[0] & 0xffff0000) >> 16;
458                 ch->alpha=      (cr[0] & 0x0000fff0) >> 4;
459                 ch->fms=        (cr[0] & 0x0000000f);
460                 ch->eso=        (cr[2] & 0xffff0000) >> 16;
461                 ch->delta=      (cr[2] & 0x0000ffff);
462                 break;
463         case TNX_PCI_ID:
464                 ch->cso=        (cr[0] & 0x00ffffff);
465                 ch->eso=        (cr[2] & 0x00ffffff);
466                 ch->delta=      ((cr[2] & 0xff000000) >> 16) | ((cr[0] & 0xff000000) >> 24);
467                 ch->alpha=      (cr[3] & 0xfff00000) >> 20;
468                 ch->fms=        (cr[3] & 0x000f0000) >> 16;
469                 break;
470         }
471 }
472
473 static u_int32_t
474 tr_fmttobits(u_int32_t fmt)
475 {
476         u_int32_t bits;
477
478         bits = 0;
479         bits |= (fmt & AFMT_SIGNED)? 0x2 : 0;
480         bits |= (AFMT_CHANNEL(fmt) > 1)? 0x4 : 0;
481         bits |= (fmt & AFMT_16BIT)? 0x8 : 0;
482
483         return bits;
484 }
485
486 /* -------------------------------------------------------------------- */
487 /* channel interface */
488
489 static void *
490 trpchan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, struct pcm_channel *c, int dir)
491 {
492         struct tr_info *tr = devinfo;
493         struct tr_chinfo *ch;
494
495         KASSERT(dir == PCMDIR_PLAY, ("trpchan_init: bad direction"));
496         ch = &tr->chinfo[tr->playchns];
497         ch->index = tr->playchns++;
498         ch->buffer = b;
499         ch->parent = tr;
500         ch->channel = c;
501         if (sndbuf_alloc(ch->buffer, tr->parent_dmat, 0, tr->bufsz) != 0)
502                 return NULL;
503
504         return ch;
505 }
506
507 static int
508 trpchan_setformat(kobj_t obj, void *data, u_int32_t format)
509 {
510         struct tr_chinfo *ch = data;
511
512         ch->ctrl = tr_fmttobits(format) | 0x01;
513
514         return 0;
515 }
516
517 static u_int32_t
518 trpchan_setspeed(kobj_t obj, void *data, u_int32_t speed)
519 {
520         struct tr_chinfo *ch = data;
521
522         ch->delta = (speed << 12) / 48000;
523         return (ch->delta * 48000) >> 12;
524 }
525
526 static u_int32_t
527 trpchan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize)
528 {
529         struct tr_chinfo *ch = data;
530
531         sndbuf_resize(ch->buffer, 2, blocksize);
532         return blocksize;
533 }
534
535 static int
536 trpchan_trigger(kobj_t obj, void *data, int go)
537 {
538         struct tr_chinfo *ch = data;
539
540         if (!PCMTRIG_COMMON(go))
541                 return 0;
542
543         if (go == PCMTRIG_START) {
544                 ch->fmc = 3;
545                 ch->fms = 0;
546                 ch->ec = 0;
547                 ch->alpha = 0;
548                 ch->lba = sndbuf_getbufaddr(ch->buffer);
549                 ch->cso = 0;
550                 ch->eso = (sndbuf_getsize(ch->buffer) / sndbuf_getalign(ch->buffer)) - 1;
551                 ch->rvol = ch->cvol = 0x7f;
552                 ch->gvsel = 0;
553                 ch->pan = 0;
554                 ch->vol = 0;
555                 ch->bufhalf = 0;
556                 tr_wrch(ch);
557                 tr_enaint(ch, 1);
558                 tr_startch(ch);
559                 ch->active = 1;
560         } else {
561                 tr_stopch(ch);
562                 ch->active = 0;
563         }
564
565         return 0;
566 }
567
568 static u_int32_t
569 trpchan_getptr(kobj_t obj, void *data)
570 {
571         struct tr_chinfo *ch = data;
572
573         tr_rdch(ch);
574         return ch->cso * sndbuf_getalign(ch->buffer);
575 }
576
577 static struct pcmchan_caps *
578 trpchan_getcaps(kobj_t obj, void *data)
579 {
580         return &tr_playcaps;
581 }
582
583 static kobj_method_t trpchan_methods[] = {
584         KOBJMETHOD(channel_init,                trpchan_init),
585         KOBJMETHOD(channel_setformat,           trpchan_setformat),
586         KOBJMETHOD(channel_setspeed,            trpchan_setspeed),
587         KOBJMETHOD(channel_setblocksize,        trpchan_setblocksize),
588         KOBJMETHOD(channel_trigger,             trpchan_trigger),
589         KOBJMETHOD(channel_getptr,              trpchan_getptr),
590         KOBJMETHOD(channel_getcaps,             trpchan_getcaps),
591         KOBJMETHOD_END
592 };
593 CHANNEL_DECLARE(trpchan);
594
595 /* -------------------------------------------------------------------- */
596 /* rec channel interface */
597
598 static void *
599 trrchan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, struct pcm_channel *c, int dir)
600 {
601         struct tr_info *tr = devinfo;
602         struct tr_rchinfo *ch;
603
604         KASSERT(dir == PCMDIR_REC, ("trrchan_init: bad direction"));
605         ch = &tr->recchinfo;
606         ch->buffer = b;
607         ch->parent = tr;
608         ch->channel = c;
609         if (sndbuf_alloc(ch->buffer, tr->parent_dmat, 0, tr->bufsz) != 0)
610                 return NULL;
611
612         return ch;
613 }
614
615 static int
616 trrchan_setformat(kobj_t obj, void *data, u_int32_t format)
617 {
618         struct tr_rchinfo *ch = data;
619         struct tr_info *tr = ch->parent;
620         u_int32_t i, bits;
621
622         bits = tr_fmttobits(format);
623         /* set # of samples between interrupts */
624         i = (sndbuf_runsz(ch->buffer) >> ((bits & 0x08)? 1 : 0)) - 1;
625         tr_wr(tr, TR_REG_SBBL, i | (i << 16), 4);
626         /* set sample format */
627         i = 0x18 | (bits << 4);
628         tr_wr(tr, TR_REG_SBCTRL, i, 1);
629
630         return 0;
631
632 }
633
634 static u_int32_t
635 trrchan_setspeed(kobj_t obj, void *data, u_int32_t speed)
636 {
637         struct tr_rchinfo *ch = data;
638         struct tr_info *tr = ch->parent;
639
640         /* setup speed */
641         ch->delta = (48000 << 12) / speed;
642         tr_wr(tr, TR_REG_SBDELTA, ch->delta, 2);
643
644         /* return closest possible speed */
645         return (48000 << 12) / ch->delta;
646 }
647
648 static u_int32_t
649 trrchan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize)
650 {
651         struct tr_rchinfo *ch = data;
652
653         sndbuf_resize(ch->buffer, 2, blocksize);
654
655         return blocksize;
656 }
657
658 static int
659 trrchan_trigger(kobj_t obj, void *data, int go)
660 {
661         struct tr_rchinfo *ch = data;
662         struct tr_info *tr = ch->parent;
663         u_int32_t i;
664
665         if (!PCMTRIG_COMMON(go))
666                 return 0;
667
668         if (go == PCMTRIG_START) {
669                 /* set up dma mode regs */
670                 tr_wr(tr, TR_REG_DMAR15, 0, 1);
671                 i = tr_rd(tr, TR_REG_DMAR11, 1) & 0x03;
672                 tr_wr(tr, TR_REG_DMAR11, i | 0x54, 1);
673                 /* set up base address */
674                 tr_wr(tr, TR_REG_DMAR0, sndbuf_getbufaddr(ch->buffer), 4);
675                 /* set up buffer size */
676                 i = tr_rd(tr, TR_REG_DMAR4, 4) & ~0x00ffffff;
677                 tr_wr(tr, TR_REG_DMAR4, i | (sndbuf_runsz(ch->buffer) - 1), 4);
678                 /* start */
679                 tr_wr(tr, TR_REG_SBCTRL, tr_rd(tr, TR_REG_SBCTRL, 1) | 1, 1);
680                 ch->active = 1;
681         } else {
682                 tr_wr(tr, TR_REG_SBCTRL, tr_rd(tr, TR_REG_SBCTRL, 1) & ~7, 1);
683                 ch->active = 0;
684         }
685
686         /* return 0 if ok */
687         return 0;
688 }
689
690 static u_int32_t
691 trrchan_getptr(kobj_t obj, void *data)
692 {
693         struct tr_rchinfo *ch = data;
694         struct tr_info *tr = ch->parent;
695
696         /* return current byte offset of channel */
697         return tr_rd(tr, TR_REG_DMAR0, 4) - sndbuf_getbufaddr(ch->buffer);
698 }
699
700 static struct pcmchan_caps *
701 trrchan_getcaps(kobj_t obj, void *data)
702 {
703         return &tr_reccaps;
704 }
705
706 static kobj_method_t trrchan_methods[] = {
707         KOBJMETHOD(channel_init,                trrchan_init),
708         KOBJMETHOD(channel_setformat,           trrchan_setformat),
709         KOBJMETHOD(channel_setspeed,            trrchan_setspeed),
710         KOBJMETHOD(channel_setblocksize,        trrchan_setblocksize),
711         KOBJMETHOD(channel_trigger,             trrchan_trigger),
712         KOBJMETHOD(channel_getptr,              trrchan_getptr),
713         KOBJMETHOD(channel_getcaps,             trrchan_getcaps),
714         KOBJMETHOD_END
715 };
716 CHANNEL_DECLARE(trrchan);
717
718 /* -------------------------------------------------------------------- */
719 /* The interrupt handler */
720
721 static void
722 tr_intr(void *p)
723 {
724         struct tr_info *tr = (struct tr_info *)p;
725         struct tr_chinfo *ch;
726         u_int32_t active, mask, bufhalf, chnum, intsrc;
727         int tmp;
728
729         intsrc = tr_rd(tr, TR_REG_MISCINT, 4);
730         if (intsrc & TR_INT_ADDR) {
731                 chnum = 0;
732                 while (chnum < 64) {
733                         mask = 0x00000001;
734                         active = tr_rd(tr, (chnum < 32)? TR_REG_ADDRINTA : TR_REG_ADDRINTB, 4);
735                         bufhalf = tr_rd(tr, (chnum < 32)? TR_REG_CSPF_A : TR_REG_CSPF_B, 4);
736                         if (active) {
737                                 do {
738                                         if (active & mask) {
739                                                 tmp = (bufhalf & mask)? 1 : 0;
740                                                 if (chnum < tr->playchns) {
741                                                         ch = &tr->chinfo[chnum];
742                                                         /* printf("%d @ %d, ", chnum, trpchan_getptr(NULL, ch)); */
743                                                         if (ch->bufhalf != tmp) {
744                                                                 chn_intr(ch->channel);
745                                                                 ch->bufhalf = tmp;
746                                                         }
747                                                 }
748                                         }
749                                         chnum++;
750                                         mask <<= 1;
751                                 } while (chnum & 31);
752                         } else
753                                 chnum += 32;
754
755                         tr_wr(tr, (chnum <= 32)? TR_REG_ADDRINTA : TR_REG_ADDRINTB, active, 4);
756                 }
757         }
758         if (intsrc & TR_INT_SB) {
759                 chn_intr(tr->recchinfo.channel);
760                 tr_rd(tr, TR_REG_SBR9, 1);
761                 tr_rd(tr, TR_REG_SBR10, 1);
762         }
763 }
764
765 /* -------------------------------------------------------------------- */
766
767 /*
768  * Probe and attach the card
769  */
770
771 static int
772 tr_init(struct tr_info *tr)
773 {
774         switch (tr->type) {
775         case SPA_PCI_ID:
776                 tr_wr(tr, SPA_REG_GPIO, 0, 4);
777                 tr_wr(tr, SPA_REG_CODECST, SPA_RST_OFF, 4);
778                 break;
779         case TDX_PCI_ID:
780                 tr_wr(tr, TDX_REG_CODECST, TDX_CDC_ON, 4);
781                 break;
782         case TNX_PCI_ID:
783                 tr_wr(tr, TNX_REG_CODECST, TNX_CDC_ON, 4);
784                 break;
785         }
786
787         tr_wr(tr, TR_REG_CIR, TR_CIR_MIDENA | TR_CIR_ADDRENA, 4);
788         return 0;
789 }
790
791 static int
792 tr_pci_probe(device_t dev)
793 {
794         switch (pci_get_devid(dev)) {
795                 case SPA_PCI_ID:
796                         device_set_desc(dev, "SiS 7018");
797                         return BUS_PROBE_DEFAULT;
798                 case ALI_PCI_ID:
799                         device_set_desc(dev, "Acer Labs M5451");
800                         return BUS_PROBE_DEFAULT;
801                 case TDX_PCI_ID:
802                         device_set_desc(dev, "Trident 4DWave DX");
803                         return BUS_PROBE_DEFAULT;
804                 case TNX_PCI_ID:
805                         device_set_desc(dev, "Trident 4DWave NX");
806                         return BUS_PROBE_DEFAULT;
807         }
808
809         return ENXIO;
810 }
811
812 static int
813 tr_pci_attach(device_t dev)
814 {
815         u_int32_t       data;
816         struct tr_info *tr;
817         struct ac97_info *codec = 0;
818         int             i, dacn;
819         char            status[SND_STATUSLEN];
820
821         tr = malloc(sizeof(*tr), M_DEVBUF, M_WAITOK | M_ZERO);
822         tr->type = pci_get_devid(dev);
823         tr->rev = pci_get_revid(dev);
824         tr->lock = snd_mtxcreate(device_get_nameunit(dev), "snd_t4dwave softc");
825
826         if (resource_int_value(device_get_name(dev), device_get_unit(dev),
827             "dac", &i) == 0) {
828                 if (i < 1)
829                         dacn = 1;
830                 else if (i > TR_MAXPLAYCH)
831                         dacn = TR_MAXPLAYCH;
832                 else
833                         dacn = i;
834         } else {
835                 switch (tr->type) {
836                 case ALI_PCI_ID:
837                         dacn = 1;
838                         break;
839                 default:
840                         dacn = TR_MAXPLAYCH;
841                         break;
842                 }
843         }
844
845         data = pci_read_config(dev, PCIR_COMMAND, 2);
846         data |= (PCIM_CMD_PORTEN|PCIM_CMD_MEMEN|PCIM_CMD_BUSMASTEREN);
847         pci_write_config(dev, PCIR_COMMAND, data, 2);
848         data = pci_read_config(dev, PCIR_COMMAND, 2);
849
850         tr->regid = PCIR_BAR(0);
851         tr->regtype = SYS_RES_IOPORT;
852         tr->reg = bus_alloc_resource_any(dev, tr->regtype, &tr->regid,
853                 RF_ACTIVE);
854         if (tr->reg) {
855                 tr->st = rman_get_bustag(tr->reg);
856                 tr->sh = rman_get_bushandle(tr->reg);
857         } else {
858                 device_printf(dev, "unable to map register space\n");
859                 goto bad;
860         }
861
862         tr->bufsz = pcm_getbuffersize(dev, 4096, TR_DEFAULT_BUFSZ, 65536);
863
864         if (tr_init(tr) == -1) {
865                 device_printf(dev, "unable to initialize the card\n");
866                 goto bad;
867         }
868         tr->playchns = 0;
869
870         codec = AC97_CREATE(dev, tr, tr_ac97);
871         if (codec == NULL) goto bad;
872         if (mixer_init(dev, ac97_getmixerclass(), codec) == -1) goto bad;
873
874         tr->irqid = 0;
875         tr->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &tr->irqid,
876                                  RF_ACTIVE | RF_SHAREABLE);
877         if (!tr->irq || snd_setup_intr(dev, tr->irq, 0, tr_intr, tr, &tr->ih)) {
878                 device_printf(dev, "unable to map interrupt\n");
879                 goto bad;
880         }
881
882         if (bus_dma_tag_create(/*parent*/bus_get_dma_tag(dev), /*alignment*/2,
883                 /*boundary*/0,
884                 /*lowaddr*/TR_MAXADDR,
885                 /*highaddr*/BUS_SPACE_MAXADDR,
886                 /*filter*/NULL, /*filterarg*/NULL,
887                 /*maxsize*/tr->bufsz, /*nsegments*/1, /*maxsegz*/0x3ffff,
888                 /*flags*/0, /*lockfunc*/busdma_lock_mutex,
889                 /*lockarg*/&Giant, &tr->parent_dmat) != 0) {
890                 device_printf(dev, "unable to create dma tag\n");
891                 goto bad;
892         }
893
894         snprintf(status, 64, "at io 0x%lx irq %ld %s",
895                  rman_get_start(tr->reg), rman_get_start(tr->irq),PCM_KLDSTRING(snd_t4dwave));
896
897         if (pcm_register(dev, tr, dacn, 1))
898                 goto bad;
899         pcm_addchan(dev, PCMDIR_REC, &trrchan_class, tr);
900         for (i = 0; i < dacn; i++)
901                 pcm_addchan(dev, PCMDIR_PLAY, &trpchan_class, tr);
902         pcm_setstatus(dev, status);
903
904         return 0;
905
906 bad:
907         if (codec) ac97_destroy(codec);
908         if (tr->reg) bus_release_resource(dev, tr->regtype, tr->regid, tr->reg);
909         if (tr->ih) bus_teardown_intr(dev, tr->irq, tr->ih);
910         if (tr->irq) bus_release_resource(dev, SYS_RES_IRQ, tr->irqid, tr->irq);
911         if (tr->parent_dmat) bus_dma_tag_destroy(tr->parent_dmat);
912         if (tr->lock) snd_mtxfree(tr->lock);
913         free(tr, M_DEVBUF);
914         return ENXIO;
915 }
916
917 static int
918 tr_pci_detach(device_t dev)
919 {
920         int r;
921         struct tr_info *tr;
922
923         r = pcm_unregister(dev);
924         if (r)
925                 return r;
926
927         tr = pcm_getdevinfo(dev);
928         bus_release_resource(dev, tr->regtype, tr->regid, tr->reg);
929         bus_teardown_intr(dev, tr->irq, tr->ih);
930         bus_release_resource(dev, SYS_RES_IRQ, tr->irqid, tr->irq);
931         bus_dma_tag_destroy(tr->parent_dmat);
932         snd_mtxfree(tr->lock);
933         free(tr, M_DEVBUF);
934
935         return 0;
936 }
937
938 static int
939 tr_pci_suspend(device_t dev)
940 {
941         int i;
942         struct tr_info *tr;
943
944         tr = pcm_getdevinfo(dev);
945
946         for (i = 0; i < tr->playchns; i++) {
947                 tr->chinfo[i].was_active = tr->chinfo[i].active;
948                 if (tr->chinfo[i].active) {
949                         trpchan_trigger(NULL, &tr->chinfo[i], PCMTRIG_STOP);
950                 }
951         }
952
953         tr->recchinfo.was_active = tr->recchinfo.active;
954         if (tr->recchinfo.active) {
955                 trrchan_trigger(NULL, &tr->recchinfo, PCMTRIG_STOP);
956         }
957
958         return 0;
959 }
960
961 static int
962 tr_pci_resume(device_t dev)
963 {
964         int i;
965         struct tr_info *tr;
966
967         tr = pcm_getdevinfo(dev);
968
969         if (tr_init(tr) == -1) {
970                 device_printf(dev, "unable to initialize the card\n");
971                 return ENXIO;
972         }
973
974         if (mixer_reinit(dev) == -1) {
975                 device_printf(dev, "unable to initialize the mixer\n");
976                 return ENXIO;
977         }
978
979         for (i = 0; i < tr->playchns; i++) {
980                 if (tr->chinfo[i].was_active) {
981                         trpchan_trigger(NULL, &tr->chinfo[i], PCMTRIG_START);
982                 }
983         }
984
985         if (tr->recchinfo.was_active) {
986                 trrchan_trigger(NULL, &tr->recchinfo, PCMTRIG_START);
987         }
988
989         return 0;
990 }
991
992 static device_method_t tr_methods[] = {
993         /* Device interface */
994         DEVMETHOD(device_probe,         tr_pci_probe),
995         DEVMETHOD(device_attach,        tr_pci_attach),
996         DEVMETHOD(device_detach,        tr_pci_detach),
997         DEVMETHOD(device_suspend,       tr_pci_suspend),
998         DEVMETHOD(device_resume,        tr_pci_resume),
999         { 0, 0 }
1000 };
1001
1002 static driver_t tr_driver = {
1003         "pcm",
1004         tr_methods,
1005         PCM_SOFTC_SIZE,
1006 };
1007
1008 DRIVER_MODULE(snd_t4dwave, pci, tr_driver, pcm_devclass, 0, 0);
1009 MODULE_DEPEND(snd_t4dwave, sound, SOUND_MINVER, SOUND_PREFVER, SOUND_MAXVER);
1010 MODULE_VERSION(snd_t4dwave, 1);