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