73031a22c2f292070490c1466cd56d9e589ce373
[dragonfly.git] / sys / dev / sound / isa / sb16.c
1 /*
2  * Copyright (c) 1999 Cameron Grant <gandalf@vilnya.demon.co.uk>
3  * Copyright 1997,1998 Luigi Rizzo.
4  *
5  * Derived from files in the Voxware 3.5 distribution,
6  * Copyright by Hannu Savolainen 1994, under the same copyright
7  * conditions.
8  * All rights reserved.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29  * SUCH DAMAGE.
30  *
31  * $FreeBSD: src/sys/dev/sound/isa/sb16.c,v 1.64.2.7 2002/12/24 21:17:42 semenu Exp $
32  * $DragonFly: src/sys/dev/sound/isa/sb16.c,v 1.7 2006/12/22 23:26:25 swildner Exp $
33  */
34
35 #include <dev/sound/pcm/sound.h>
36
37 #include  <dev/sound/isa/sb.h>
38 #include  <dev/sound/chip.h>
39
40 #include "mixer_if.h"
41
42 SND_DECLARE_FILE("$DragonFly: src/sys/dev/sound/isa/sb16.c,v 1.7 2006/12/22 23:26:25 swildner Exp $");
43
44 #define SB16_BUFFSIZE   4096
45 #define PLAIN_SB16(x) ((((x)->bd_flags) & (BD_F_SB16|BD_F_SB16X)) == BD_F_SB16)
46
47 static u_int32_t sb16_fmt8[] = {
48         AFMT_U8,
49         AFMT_STEREO | AFMT_U8,
50         0
51 };
52 static struct pcmchan_caps sb16_caps8 = {5000, 45000, sb16_fmt8, 0};
53
54 static u_int32_t sb16_fmt16[] = {
55         AFMT_S16_LE,
56         AFMT_STEREO | AFMT_S16_LE,
57         0
58 };
59 static struct pcmchan_caps sb16_caps16 = {5000, 45000, sb16_fmt16, 0};
60
61 static u_int32_t sb16x_fmt[] = {
62         AFMT_U8,
63         AFMT_STEREO | AFMT_U8,
64         AFMT_S16_LE,
65         AFMT_STEREO | AFMT_S16_LE,
66         0
67 };
68 static struct pcmchan_caps sb16x_caps = {5000, 49000, sb16x_fmt, 0};
69
70 struct sb_info;
71
72 struct sb_chinfo {
73         struct sb_info *parent;
74         struct pcm_channel *channel;
75         struct snd_dbuf *buffer;
76         int dir, run, dch;
77         u_int32_t fmt, spd, blksz;
78 };
79
80 struct sb_info {
81         struct resource *io_base;       /* I/O address for the board */
82         struct resource *irq;
83         struct resource *drq1;
84         struct resource *drq2;
85         void *ih;
86         bus_dma_tag_t parent_dmat;
87
88         unsigned int bufsize;
89         int bd_id;
90         u_long bd_flags;       /* board-specific flags */
91         int prio, prio16;
92         struct sb_chinfo pch, rch;
93         device_t parent_dev;
94 };
95
96 #if 0
97 static void sb_lock(struct sb_info *sb);
98 static void sb_unlock(struct sb_info *sb);
99 static int sb_rd(struct sb_info *sb, int reg);
100 static void sb_wr(struct sb_info *sb, int reg, u_int8_t val);
101 static int sb_cmd(struct sb_info *sb, u_char val);
102 /* static int sb_cmd1(struct sb_info *sb, u_char cmd, int val); */
103 static int sb_cmd2(struct sb_info *sb, u_char cmd, int val);
104 static u_int sb_get_byte(struct sb_info *sb);
105 static void sb_setmixer(struct sb_info *sb, u_int port, u_int value);
106 static int sb_getmixer(struct sb_info *sb, u_int port);
107 static int sb_reset_dsp(struct sb_info *sb);
108
109 static void sb_intr(void *arg);
110 #endif
111
112 /*
113  * Common code for the midi and pcm functions
114  *
115  * sb_cmd write a single byte to the CMD port.
116  * sb_cmd1 write a CMD + 1 byte arg
117  * sb_cmd2 write a CMD + 2 byte arg
118  * sb_get_byte returns a single byte from the DSP data port
119  */
120
121 static void
122 sb_lock(struct sb_info *sb) {
123
124         sbc_lock(device_get_softc(sb->parent_dev));
125 }
126
127 static void
128 sb_unlock(struct sb_info *sb) {
129
130         sbc_unlock(device_get_softc(sb->parent_dev));
131 }
132
133 static int
134 port_rd(struct resource *port, int off)
135 {
136         return bus_space_read_1(rman_get_bustag(port), rman_get_bushandle(port), off);
137 }
138
139 static void
140 port_wr(struct resource *port, int off, u_int8_t data)
141 {
142         bus_space_write_1(rman_get_bustag(port), rman_get_bushandle(port), off, data);
143 }
144
145 static int
146 sb_rd(struct sb_info *sb, int reg)
147 {
148         return port_rd(sb->io_base, reg);
149 }
150
151 static void
152 sb_wr(struct sb_info *sb, int reg, u_int8_t val)
153 {
154         port_wr(sb->io_base, reg, val);
155 }
156
157 static int
158 sb_dspwr(struct sb_info *sb, u_char val)
159 {
160         int  i;
161
162         for (i = 0; i < 1000; i++) {
163                 if ((sb_rd(sb, SBDSP_STATUS) & 0x80))
164                         DELAY((i > 100)? 1000 : 10);
165                 else {
166                         sb_wr(sb, SBDSP_CMD, val);
167                         return 1;
168                 }
169         }
170 #if defined(__FreeBSD__) && __FreeBSD_version > 500000
171         if (curthread->td_intr_nesting_level == 0)
172                 kprintf("sb_dspwr(0x%02x) timed out.\n", val);
173 #endif
174         return 0;
175 }
176
177 static int
178 sb_cmd(struct sb_info *sb, u_char val)
179 {
180 #if 0
181         kprintf("sb_cmd: %x\n", val);
182 #endif
183         return sb_dspwr(sb, val);
184 }
185
186 /*
187 static int
188 sb_cmd1(struct sb_info *sb, u_char cmd, int val)
189 {
190 #if 0
191         kprintf("sb_cmd1: %x, %x\n", cmd, val);
192 #endif
193         if (sb_dspwr(sb, cmd)) {
194                 return sb_dspwr(sb, val & 0xff);
195         } else return 0;
196 }
197 */
198
199 static int
200 sb_cmd2(struct sb_info *sb, u_char cmd, int val)
201 {
202         int r;
203
204 #if 0
205         kprintf("sb_cmd2: %x, %x\n", cmd, val);
206 #endif
207         sb_lock(sb);
208         r = 0;
209         if (sb_dspwr(sb, cmd)) {
210                 if (sb_dspwr(sb, val & 0xff)) {
211                         if (sb_dspwr(sb, (val >> 8) & 0xff)) {
212                                 r = 1;
213                         }
214                 }
215         }
216         sb_unlock(sb);
217
218         return r;
219 }
220
221 /*
222  * in the SB, there is a set of indirect "mixer" registers with
223  * address at offset 4, data at offset 5
224  */
225 static void
226 sb_setmixer(struct sb_info *sb, u_int port, u_int value)
227 {
228         sb_lock(sb);
229         sb_wr(sb, SB_MIX_ADDR, (u_char) (port & 0xff)); /* Select register */
230         DELAY(10);
231         sb_wr(sb, SB_MIX_DATA, (u_char) (value & 0xff));
232         DELAY(10);
233         sb_unlock(sb);
234 }
235
236 static int
237 sb_getmixer(struct sb_info *sb, u_int port)
238 {
239         int val;
240
241         sb_lock(sb);
242         sb_wr(sb, SB_MIX_ADDR, (u_char) (port & 0xff)); /* Select register */
243         DELAY(10);
244         val = sb_rd(sb, SB_MIX_DATA);
245         DELAY(10);
246         sb_unlock(sb);
247
248         return val;
249 }
250
251 static u_int
252 sb_get_byte(struct sb_info *sb)
253 {
254         int i;
255
256         for (i = 1000; i > 0; i--) {
257                 if (sb_rd(sb, DSP_DATA_AVAIL) & 0x80)
258                         return sb_rd(sb, DSP_READ);
259                 else
260                         DELAY(20);
261         }
262         return 0xffff;
263 }
264
265 static int
266 sb_reset_dsp(struct sb_info *sb)
267 {
268         u_char b;
269
270         sb_lock(sb);
271         sb_wr(sb, SBDSP_RST, 3);
272         DELAY(100);
273         sb_wr(sb, SBDSP_RST, 0);
274         b = sb_get_byte(sb);
275         sb_unlock(sb);
276         if (b != 0xAA) {
277                 DEB(kprintf("sb_reset_dsp 0x%lx failed\n",
278                            rman_get_start(sb->io_base)));
279                 return ENXIO;   /* Sorry */
280         }
281         return 0;
282 }
283
284 /************************************************************/
285
286 struct sb16_mixent {
287         int reg;
288         int bits;
289         int ofs;
290         int stereo;
291 };
292
293 static const struct sb16_mixent sb16_mixtab[32] = {
294         [SOUND_MIXER_VOLUME]    = { 0x30, 5, 3, 1 },
295         [SOUND_MIXER_PCM]       = { 0x32, 5, 3, 1 },
296         [SOUND_MIXER_SYNTH]     = { 0x34, 5, 3, 1 },
297         [SOUND_MIXER_CD]        = { 0x36, 5, 3, 1 },
298         [SOUND_MIXER_LINE]      = { 0x38, 5, 3, 1 },
299         [SOUND_MIXER_MIC]       = { 0x3a, 5, 3, 0 },
300         [SOUND_MIXER_SPEAKER]   = { 0x3b, 5, 3, 0 },
301         [SOUND_MIXER_IGAIN]     = { 0x3f, 2, 6, 1 },
302         [SOUND_MIXER_OGAIN]     = { 0x41, 2, 6, 1 },
303         [SOUND_MIXER_TREBLE]    = { 0x44, 4, 4, 1 },
304         [SOUND_MIXER_BASS]      = { 0x46, 4, 4, 1 },
305         [SOUND_MIXER_LINE1]     = { 0x52, 5, 3, 1 }
306 };
307
308 static int
309 sb16mix_init(struct snd_mixer *m)
310 {
311         struct sb_info *sb = mix_getdevinfo(m);
312
313         mix_setdevs(m, SOUND_MASK_SYNTH | SOUND_MASK_PCM | SOUND_MASK_SPEAKER |
314                        SOUND_MASK_LINE | SOUND_MASK_MIC | SOUND_MASK_CD |
315                        SOUND_MASK_IGAIN | SOUND_MASK_OGAIN | SOUND_MASK_LINE1 |
316                        SOUND_MASK_VOLUME | SOUND_MASK_BASS | SOUND_MASK_TREBLE);
317
318         mix_setrecdevs(m, SOUND_MASK_SYNTH | SOUND_MASK_LINE |
319                           SOUND_MASK_LINE1 | SOUND_MASK_MIC | SOUND_MASK_CD);
320
321         sb_setmixer(sb, 0x3c, 0x1f); /* make all output active */
322
323         sb_setmixer(sb, 0x3d, 0); /* make all inputs-l off */
324         sb_setmixer(sb, 0x3e, 0); /* make all inputs-r off */
325
326         return 0;
327 }
328
329 static int
330 sb16mix_set(struct snd_mixer *m, unsigned dev, unsigned left, unsigned right)
331 {
332         struct sb_info *sb = mix_getdevinfo(m);
333         const struct sb16_mixent *e;
334         int max;
335
336         e = &sb16_mixtab[dev];
337         max = (1 << e->bits) - 1;
338
339         left = (left * max) / 100;
340         right = (right * max) / 100;
341
342         sb_setmixer(sb, e->reg, left << e->ofs);
343         if (e->stereo)
344                 sb_setmixer(sb, e->reg + 1, right << e->ofs);
345         else
346                 right = left;
347
348         left = (left * 100) / max;
349         right = (right * 100) / max;
350
351         return left | (right << 8);
352 }
353
354 static int
355 sb16mix_setrecsrc(struct snd_mixer *m, u_int32_t src)
356 {
357         struct sb_info *sb = mix_getdevinfo(m);
358         u_char recdev;
359
360         recdev = 0;
361         if (src & SOUND_MASK_MIC)
362                 recdev |= 0x01; /* mono mic */
363
364         if (src & SOUND_MASK_CD)
365                 recdev |= 0x06; /* l+r cd */
366
367         if (src & SOUND_MASK_LINE)
368                 recdev |= 0x18; /* l+r line */
369
370         if (src & SOUND_MASK_SYNTH)
371                 recdev |= 0x60; /* l+r midi */
372
373         sb_setmixer(sb, SB16_IMASK_L, recdev);
374         sb_setmixer(sb, SB16_IMASK_R, recdev);
375
376         /* Switch on/off FM tuner source */
377         if (src & SOUND_MASK_LINE1)
378                 sb_setmixer(sb, 0x4a, 0x0c);
379         else
380                 sb_setmixer(sb, 0x4a, 0x00);
381
382         /*
383          * since the same volume controls apply to the input and
384          * output sections, the best approach to have a consistent
385          * behaviour among cards would be to disable the output path
386          * on devices which are used to record.
387          * However, since users like to have feedback, we only disable
388          * the mic -- permanently.
389          */
390         sb_setmixer(sb, SB16_OMASK, 0x1f & ~1);
391
392         return src;
393 }
394
395 static kobj_method_t sb16mix_mixer_methods[] = {
396         KOBJMETHOD(mixer_init,          sb16mix_init),
397         KOBJMETHOD(mixer_set,           sb16mix_set),
398         KOBJMETHOD(mixer_setrecsrc,     sb16mix_setrecsrc),
399         { 0, 0 }
400 };
401 MIXER_DECLARE(sb16mix_mixer);
402
403 /************************************************************/
404
405 static void
406 sb16_release_resources(struct sb_info *sb, device_t dev)
407 {
408         if (sb->irq) {
409                 if (sb->ih)
410                         bus_teardown_intr(dev, sb->irq, sb->ih);
411                 bus_release_resource(dev, SYS_RES_IRQ, 0, sb->irq);
412                 sb->irq = 0;
413         }
414         if (sb->drq2) {
415                 if (sb->drq2 != sb->drq1) {
416                         isa_dma_release(rman_get_start(sb->drq2));
417                         bus_release_resource(dev, SYS_RES_DRQ, 1, sb->drq2);
418                 }
419                 sb->drq2 = 0;
420         }
421         if (sb->drq1) {
422                 isa_dma_release(rman_get_start(sb->drq1));
423                 bus_release_resource(dev, SYS_RES_DRQ, 0, sb->drq1);
424                 sb->drq1 = 0;
425         }
426         if (sb->io_base) {
427                 bus_release_resource(dev, SYS_RES_IOPORT, 0, sb->io_base);
428                 sb->io_base = 0;
429         }
430         if (sb->parent_dmat) {
431                 bus_dma_tag_destroy(sb->parent_dmat);
432                 sb->parent_dmat = 0;
433         }
434         kfree(sb, M_DEVBUF);
435 }
436
437 static int
438 sb16_alloc_resources(struct sb_info *sb, device_t dev)
439 {
440         int rid;
441
442         rid = 0;
443         if (!sb->io_base)
444                 sb->io_base = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 0, ~0, 1, RF_ACTIVE);
445
446         rid = 0;
447         if (!sb->irq)
448                 sb->irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0, ~0, 1, RF_ACTIVE);
449
450         rid = 0;
451         if (!sb->drq1)
452                 sb->drq1 = bus_alloc_resource(dev, SYS_RES_DRQ, &rid, 0, ~0, 1, RF_ACTIVE);
453
454         rid = 1;
455         if (!sb->drq2)
456                 sb->drq2 = bus_alloc_resource(dev, SYS_RES_DRQ, &rid, 0, ~0, 1, RF_ACTIVE);
457
458         if (sb->io_base && sb->drq1 && sb->irq) {
459                 isa_dma_acquire(rman_get_start(sb->drq1));
460                 isa_dmainit(rman_get_start(sb->drq1), sb->bufsize);
461
462                 if (sb->drq2) {
463                         isa_dma_acquire(rman_get_start(sb->drq2));
464                         isa_dmainit(rman_get_start(sb->drq2), sb->bufsize);
465                 } else {
466                         sb->drq2 = sb->drq1;
467                         pcm_setflags(dev, pcm_getflags(dev) | SD_F_SIMPLEX);
468                 }
469                 return 0;
470         } else return ENXIO;
471 }
472
473 /* sbc does locking for us */
474 static void
475 sb_intr(void *arg)
476 {
477         struct sb_info *sb = (struct sb_info *)arg;
478         int reason = 3, c;
479
480         /*
481          * The Vibra16X has separate flags for 8 and 16 bit transfers, but
482          * I have no idea how to tell capture from playback interrupts...
483          */
484
485         reason = 0;
486         sb_lock(sb);
487         c = sb_getmixer(sb, IRQ_STAT);
488         if (c & 1)
489                 sb_rd(sb, DSP_DATA_AVAIL); /* 8-bit int ack */
490
491         if (c & 2)
492                 sb_rd(sb, DSP_DATA_AVL16); /* 16-bit int ack */
493         sb_unlock(sb);
494
495         /*
496          * this tells us if the source is 8-bit or 16-bit dma. We
497          * have to check the io channel to map it to read or write...
498          */
499
500         if (sb->bd_flags & BD_F_SB16X) {
501                 if (c & 1) { /* 8-bit format */
502                         if (sb->pch.fmt & AFMT_8BIT)
503                                 reason |= 1;
504                         if (sb->rch.fmt & AFMT_8BIT)
505                                 reason |= 2;
506                 }
507                 if (c & 2) { /* 16-bit format */
508                         if (sb->pch.fmt & AFMT_16BIT)
509                                 reason |= 1;
510                         if (sb->rch.fmt & AFMT_16BIT)
511                                 reason |= 2;
512                 }
513         } else {
514                 if (c & 1) { /* 8-bit dma */
515                         if (sb->pch.dch == 1)
516                                 reason |= 1;
517                         if (sb->rch.dch == 1)
518                                 reason |= 2;
519                 }
520                 if (c & 2) { /* 16-bit dma */
521                         if (sb->pch.dch == 2)
522                                 reason |= 1;
523                         if (sb->rch.dch == 2)
524                                 reason |= 2;
525                 }
526         }
527 #if 0
528         kprintf("sb_intr: reason=%d c=0x%x\n", reason, c);
529 #endif
530         if ((reason & 1) && (sb->pch.run))
531                 chn_intr(sb->pch.channel);
532
533         if ((reason & 2) && (sb->rch.run))
534                 chn_intr(sb->rch.channel);
535 }
536
537 static int
538 sb_setup(struct sb_info *sb)
539 {
540         struct sb_chinfo *ch;
541         u_int8_t v;
542         int l, pprio;
543
544         sb_lock(sb);
545         if (sb->bd_flags & BD_F_DMARUN)
546                 sndbuf_isadma(sb->pch.buffer, PCMTRIG_STOP);
547         if (sb->bd_flags & BD_F_DMARUN2)
548                 sndbuf_isadma(sb->rch.buffer, PCMTRIG_STOP);
549         sb->bd_flags &= ~(BD_F_DMARUN | BD_F_DMARUN2);
550
551         sb_reset_dsp(sb);
552
553         if (sb->bd_flags & BD_F_SB16X) {
554                 pprio = sb->pch.run? 1 : 0;
555                 sndbuf_isadmasetup(sb->pch.buffer, pprio? sb->drq1 : NULL);
556                 sb->pch.dch = pprio? 1 : 0;
557                 sndbuf_isadmasetup(sb->rch.buffer, pprio? sb->drq2 : sb->drq1);
558                 sb->rch.dch = pprio? 2 : 1;
559         } else {
560                 if (sb->pch.run && sb->rch.run) {
561                         pprio = (sb->rch.fmt & AFMT_16BIT)? 0 : 1;
562                         sndbuf_isadmasetup(sb->pch.buffer, pprio? sb->drq2 : sb->drq1);
563                         sb->pch.dch = pprio? 2 : 1;
564                         sndbuf_isadmasetup(sb->rch.buffer, pprio? sb->drq1 : sb->drq2);
565                         sb->rch.dch = pprio? 1 : 2;
566                 } else {
567                         if (sb->pch.run) {
568                                 sndbuf_isadmasetup(sb->pch.buffer, (sb->pch.fmt & AFMT_16BIT)? sb->drq2 : sb->drq1);
569                                 sb->pch.dch = (sb->pch.fmt & AFMT_16BIT)? 2 : 1;
570                                 sndbuf_isadmasetup(sb->rch.buffer, (sb->pch.fmt & AFMT_16BIT)? sb->drq1 : sb->drq2);
571                                 sb->rch.dch = (sb->pch.fmt & AFMT_16BIT)? 1 : 2;
572                         } else if (sb->rch.run) {
573                                 sndbuf_isadmasetup(sb->pch.buffer, (sb->rch.fmt & AFMT_16BIT)? sb->drq1 : sb->drq2);
574                                 sb->pch.dch = (sb->rch.fmt & AFMT_16BIT)? 1 : 2;
575                                 sndbuf_isadmasetup(sb->rch.buffer, (sb->rch.fmt & AFMT_16BIT)? sb->drq2 : sb->drq1);
576                                 sb->rch.dch = (sb->rch.fmt & AFMT_16BIT)? 2 : 1;
577                         }
578                 }
579         }
580
581         sndbuf_isadmasetdir(sb->pch.buffer, PCMDIR_PLAY);
582         sndbuf_isadmasetdir(sb->rch.buffer, PCMDIR_REC);
583
584         /*
585         kprintf("setup: [pch = %d, pfmt = %d, pgo = %d] [rch = %d, rfmt = %d, rgo = %d]\n",
586                sb->pch.dch, sb->pch.fmt, sb->pch.run, sb->rch.dch, sb->rch.fmt, sb->rch.run);
587         */
588
589         ch = &sb->pch;
590         if (ch->run) {
591                 l = ch->blksz;
592                 if (ch->fmt & AFMT_16BIT)
593                         l >>= 1;
594                 l--;
595
596                 /* play speed */
597                 RANGE(ch->spd, 5000, 45000);
598                 sb_cmd(sb, DSP_CMD_OUT16);
599                 sb_cmd(sb, ch->spd >> 8);
600                 sb_cmd(sb, ch->spd & 0xff);
601
602                 /* play format, length */
603                 v = DSP_F16_AUTO | DSP_F16_FIFO_ON | DSP_F16_DAC;
604                 v |= (ch->fmt & AFMT_16BIT)? DSP_DMA16 : DSP_DMA8;
605                 sb_cmd(sb, v);
606
607                 v = (ch->fmt & AFMT_STEREO)? DSP_F16_STEREO : 0;
608                 v |= (ch->fmt & AFMT_SIGNED)? DSP_F16_SIGNED : 0;
609                 sb_cmd2(sb, v, l);
610                 sndbuf_isadma(ch->buffer, PCMTRIG_START);
611                 sb->bd_flags |= BD_F_DMARUN;
612         }
613
614         ch = &sb->rch;
615         if (ch->run) {
616                 l = ch->blksz;
617                 if (ch->fmt & AFMT_16BIT)
618                         l >>= 1;
619                 l--;
620
621                 /* record speed */
622                 RANGE(ch->spd, 5000, 45000);
623                 sb_cmd(sb, DSP_CMD_IN16);
624                 sb_cmd(sb, ch->spd >> 8);
625                 sb_cmd(sb, ch->spd & 0xff);
626
627                 /* record format, length */
628                 v = DSP_F16_AUTO | DSP_F16_FIFO_ON | DSP_F16_ADC;
629                 v |= (ch->fmt & AFMT_16BIT)? DSP_DMA16 : DSP_DMA8;
630                 sb_cmd(sb, v);
631
632                 v = (ch->fmt & AFMT_STEREO)? DSP_F16_STEREO : 0;
633                 v |= (ch->fmt & AFMT_SIGNED)? DSP_F16_SIGNED : 0;
634                 sb_cmd2(sb, v, l);
635                 sndbuf_isadma(ch->buffer, PCMTRIG_START);
636                 sb->bd_flags |= BD_F_DMARUN2;
637         }
638         sb_unlock(sb);
639
640         return 0;
641 }
642
643 /* channel interface */
644 static void *
645 sb16chan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, struct pcm_channel *c, int dir)
646 {
647         struct sb_info *sb = devinfo;
648         struct sb_chinfo *ch = (dir == PCMDIR_PLAY)? &sb->pch : &sb->rch;
649
650         ch->parent = sb;
651         ch->channel = c;
652         ch->buffer = b;
653         ch->dir = dir;
654
655         if (sndbuf_alloc(ch->buffer, sb->parent_dmat, sb->bufsize) == -1)
656                 return NULL;
657
658         return ch;
659 }
660
661 static int
662 sb16chan_setformat(kobj_t obj, void *data, u_int32_t format)
663 {
664         struct sb_chinfo *ch = data;
665         struct sb_info *sb = ch->parent;
666
667         ch->fmt = format;
668         sb->prio = ch->dir;
669         sb->prio16 = (ch->fmt & AFMT_16BIT)? 1 : 0;
670
671         return 0;
672 }
673
674 static int
675 sb16chan_setspeed(kobj_t obj, void *data, u_int32_t speed)
676 {
677         struct sb_chinfo *ch = data;
678
679         ch->spd = speed;
680         return speed;
681 }
682
683 static int
684 sb16chan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize)
685 {
686         struct sb_chinfo *ch = data;
687
688         ch->blksz = blocksize;
689         return ch->blksz;
690 }
691
692 static int
693 sb16chan_trigger(kobj_t obj, void *data, int go)
694 {
695         struct sb_chinfo *ch = data;
696         struct sb_info *sb = ch->parent;
697
698         if (go == PCMTRIG_EMLDMAWR || go == PCMTRIG_EMLDMARD)
699                 return 0;
700
701         if (go == PCMTRIG_START)
702                 ch->run = 1;
703         else
704                 ch->run = 0;
705
706         sb_setup(sb);
707
708         return 0;
709 }
710
711 static int
712 sb16chan_getptr(kobj_t obj, void *data)
713 {
714         struct sb_chinfo *ch = data;
715
716         return sndbuf_isadmaptr(ch->buffer);
717 }
718
719 static struct pcmchan_caps *
720 sb16chan_getcaps(kobj_t obj, void *data)
721 {
722         struct sb_chinfo *ch = data;
723         struct sb_info *sb = ch->parent;
724
725         if ((sb->prio == 0) || (sb->prio == ch->dir))
726                 return &sb16x_caps;
727         else
728                 return sb->prio16? &sb16_caps8 : &sb16_caps16;
729 }
730
731 static int
732 sb16chan_resetdone(kobj_t obj, void *data)
733 {
734         struct sb_chinfo *ch = data;
735         struct sb_info *sb = ch->parent;
736
737         sb->prio = 0;
738
739         return 0;
740 }
741
742 static kobj_method_t sb16chan_methods[] = {
743         KOBJMETHOD(channel_init,                sb16chan_init),
744         KOBJMETHOD(channel_resetdone,           sb16chan_resetdone),
745         KOBJMETHOD(channel_setformat,           sb16chan_setformat),
746         KOBJMETHOD(channel_setspeed,            sb16chan_setspeed),
747         KOBJMETHOD(channel_setblocksize,        sb16chan_setblocksize),
748         KOBJMETHOD(channel_trigger,             sb16chan_trigger),
749         KOBJMETHOD(channel_getptr,              sb16chan_getptr),
750         KOBJMETHOD(channel_getcaps,             sb16chan_getcaps),
751         { 0, 0 }
752 };
753 CHANNEL_DECLARE(sb16chan);
754
755 /************************************************************/
756
757 static int
758 sb16_probe(device_t dev)
759 {
760         char buf[64];
761         uintptr_t func, ver, r, f;
762
763         /* The parent device has already been probed. */
764         r = BUS_READ_IVAR(device_get_parent(dev), dev, 0, &func);
765         if (func != SCF_PCM)
766                 return (ENXIO);
767
768         r = BUS_READ_IVAR(device_get_parent(dev), dev, 1, &ver);
769         f = (ver & 0xffff0000) >> 16;
770         ver &= 0x0000ffff;
771         if (f & BD_F_SB16) {
772                 ksnprintf(buf, sizeof buf, "SB16 DSP %d.%02d%s", (int) ver >> 8, (int) ver & 0xff,
773                          (f & BD_F_SB16X)? " (ViBRA16X)" : "");
774                 device_set_desc_copy(dev, buf);
775                 return 0;
776         } else
777                 return (ENXIO);
778 }
779
780 static int
781 sb16_attach(device_t dev)
782 {
783         struct sb_info *sb;
784         uintptr_t ver;
785         char status[SND_STATUSLEN], status2[SND_STATUSLEN];
786
787         sb = (struct sb_info *)kmalloc(sizeof *sb, M_DEVBUF, M_NOWAIT | M_ZERO);
788         if (!sb)
789                 return ENXIO;
790
791         sb->parent_dev = device_get_parent(dev);
792         BUS_READ_IVAR(sb->parent_dev, dev, 1, &ver);
793         sb->bd_id = ver & 0x0000ffff;
794         sb->bd_flags = (ver & 0xffff0000) >> 16;
795         sb->bufsize = pcm_getbuffersize(dev, 4096, SB16_BUFFSIZE, 65536);
796
797         if (sb16_alloc_resources(sb, dev))
798                 goto no;
799         if (sb_reset_dsp(sb))
800                 goto no;
801         if (mixer_init(dev, &sb16mix_mixer_class, sb))
802                 goto no;
803         if (snd_setup_intr(dev, sb->irq, INTR_MPSAFE, sb_intr, sb, &sb->ih, NULL))
804                 goto no;
805
806         if (sb->bd_flags & BD_F_SB16X)
807                 pcm_setflags(dev, pcm_getflags(dev) | SD_F_SIMPLEX);
808
809         sb->prio = 0;
810
811         if (bus_dma_tag_create(/*parent*/NULL, /*alignment*/2, /*boundary*/0,
812                         /*lowaddr*/BUS_SPACE_MAXADDR_24BIT,
813                         /*highaddr*/BUS_SPACE_MAXADDR,
814                         /*filter*/NULL, /*filterarg*/NULL,
815                         /*maxsize*/sb->bufsize, /*nsegments*/1,
816                         /*maxsegz*/0x3ffff,
817                         /*flags*/0, &sb->parent_dmat) != 0) {
818                 device_printf(dev, "unable to create dma tag\n");
819                 goto no;
820         }
821
822         if (!(pcm_getflags(dev) & SD_F_SIMPLEX))
823                 ksnprintf(status2, SND_STATUSLEN, ":%ld", rman_get_start(sb->drq2));
824         else
825                 status2[0] = '\0';
826
827         ksnprintf(status, SND_STATUSLEN, "at io 0x%lx irq %ld drq %ld%s bufsz %ud",
828                 rman_get_start(sb->io_base), rman_get_start(sb->irq),
829                 rman_get_start(sb->drq1), status2, sb->bufsize);
830
831         if (pcm_register(dev, sb, 1, 1))
832                 goto no;
833         pcm_addchan(dev, PCMDIR_REC, &sb16chan_class, sb);
834         pcm_addchan(dev, PCMDIR_PLAY, &sb16chan_class, sb);
835
836         pcm_setstatus(dev, status);
837
838         return 0;
839
840 no:
841         sb16_release_resources(sb, dev);
842         return ENXIO;
843 }
844
845 static int
846 sb16_detach(device_t dev)
847 {
848         int r;
849         struct sb_info *sb;
850
851         r = pcm_unregister(dev);
852         if (r)
853                 return r;
854
855         sb = pcm_getdevinfo(dev);
856         sb16_release_resources(sb, dev);
857         return 0;
858 }
859
860 static device_method_t sb16_methods[] = {
861         /* Device interface */
862         DEVMETHOD(device_probe,         sb16_probe),
863         DEVMETHOD(device_attach,        sb16_attach),
864         DEVMETHOD(device_detach,        sb16_detach),
865
866         { 0, 0 }
867 };
868
869 static driver_t sb16_driver = {
870         "pcm",
871         sb16_methods,
872         PCM_SOFTC_SIZE,
873 };
874
875 DRIVER_MODULE(snd_sb16, sbc, sb16_driver, pcm_devclass, 0, 0);
876 MODULE_DEPEND(snd_sb16, snd_pcm, PCM_MINVER, PCM_PREFVER, PCM_MAXVER);
877 MODULE_DEPEND(snd_sb16, snd_sbc, 1, 1, 1);
878 MODULE_VERSION(snd_sb16, 1);