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