sb16.c revision 67652
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 67652 2000-10-26 20:46:58Z cg $
32 */
33
34#include <dev/sound/pcm/sound.h>
35
36#define __SB_MIXER_C__	/* XXX warning... */
37#include  <dev/sound/isa/sb.h>
38#include  <dev/sound/chip.h>
39
40#define PLAIN_SB16(x) ((((x)->bd_flags) & (BD_F_SB16|BD_F_SB16X)) == BD_F_SB16)
41
42/* channel interface */
43static void *sbchan_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir);
44static int sbchan_setdir(void *data, int dir);
45static int sbchan_setformat(void *data, u_int32_t format);
46static int sbchan_setspeed(void *data, u_int32_t speed);
47static int sbchan_setblocksize(void *data, u_int32_t blocksize);
48static int sbchan_trigger(void *data, int go);
49static int sbchan_getptr(void *data);
50static pcmchan_caps *sbchan_getcaps(void *data);
51
52static u_int32_t sb_playfmt[] = {
53	AFMT_U8,
54	0
55};
56static pcmchan_caps sb_playcaps = {4000, 22050, sb_playfmt, 0};
57
58static u_int32_t sb_recfmt[] = {
59	AFMT_U8,
60	0
61};
62static pcmchan_caps sb_reccaps = {4000, 13000, sb_recfmt, 0};
63
64static u_int32_t sbpro_playfmt[] = {
65	AFMT_U8,
66	AFMT_STEREO | AFMT_U8,
67	0
68};
69static pcmchan_caps sbpro_playcaps = {4000, 45000, sbpro_playfmt, 0};
70
71static u_int32_t sbpro_recfmt[] = {
72	AFMT_U8,
73	AFMT_STEREO | AFMT_U8,
74	0
75};
76static pcmchan_caps sbpro_reccaps = {4000, 15000, sbpro_recfmt, 0};
77
78static u_int32_t sb16_hfmt[] = {
79	AFMT_S16_LE,
80	AFMT_STEREO | AFMT_S16_LE,
81	0
82};
83static pcmchan_caps sb16_hcaps = {5000, 45000, sb16_hfmt, 0};
84
85static u_int32_t sb16_lfmt[] = {
86	AFMT_U8,
87	AFMT_STEREO | AFMT_U8,
88	0
89};
90static pcmchan_caps sb16_lcaps = {5000, 45000, sb16_lfmt, 0};
91
92static u_int32_t sb16x_fmt[] = {
93	AFMT_U8,
94	AFMT_STEREO | AFMT_U8,
95	AFMT_S16_LE,
96	AFMT_STEREO | AFMT_S16_LE,
97	0
98};
99static pcmchan_caps sb16x_caps = {5000, 49000, sb16x_fmt, 0};
100
101static pcm_channel sb_chantemplate = {
102	sbchan_init,
103	sbchan_setdir,
104	sbchan_setformat,
105	sbchan_setspeed,
106	sbchan_setblocksize,
107	sbchan_trigger,
108	sbchan_getptr,
109	sbchan_getcaps,
110	NULL, 			/* free */
111	NULL, 			/* nop1 */
112	NULL, 			/* nop2 */
113	NULL, 			/* nop3 */
114	NULL, 			/* nop4 */
115	NULL, 			/* nop5 */
116	NULL, 			/* nop6 */
117	NULL, 			/* nop7 */
118};
119
120struct sb_info;
121
122struct sb_chinfo {
123	struct sb_info *parent;
124	pcm_channel *channel;
125	snd_dbuf *buffer;
126	int dir;
127	u_int32_t fmt, spd;
128};
129
130struct sb_info {
131    	struct resource *io_base;	/* I/O address for the board */
132    	struct resource *irq;
133   	struct resource *drq1;
134    	struct resource *drq2;
135    	void *ih;
136    	bus_dma_tag_t parent_dmat;
137
138    	int bd_id;
139    	u_long bd_flags;       /* board-specific flags */
140    	struct sb_chinfo pch, rch;
141};
142
143static int sb_rd(struct sb_info *sb, int reg);
144static void sb_wr(struct sb_info *sb, int reg, u_int8_t val);
145static int sb_dspready(struct sb_info *sb);
146static int sb_cmd(struct sb_info *sb, u_char val);
147static int sb_cmd1(struct sb_info *sb, u_char cmd, int val);
148static int sb_cmd2(struct sb_info *sb, u_char cmd, int val);
149static u_int sb_get_byte(struct sb_info *sb);
150static void sb_setmixer(struct sb_info *sb, u_int port, u_int value);
151static int sb_getmixer(struct sb_info *sb, u_int port);
152static int sb_reset_dsp(struct sb_info *sb);
153
154static void sb_intr(void *arg);
155static int sb_speed(struct sb_chinfo *ch);
156static int sb_start(struct sb_chinfo *ch);
157static int sb_stop(struct sb_chinfo *ch);
158
159static int sbmix_init(snd_mixer *m);
160static int sbmix_set(snd_mixer *m, unsigned dev, unsigned left, unsigned right);
161static int sbmix_setrecsrc(snd_mixer *m, u_int32_t src);
162
163static snd_mixer sb_mixer = {
164    	"SoundBlaster mixer",
165    	sbmix_init,
166	NULL,
167	NULL,
168    	sbmix_set,
169    	sbmix_setrecsrc,
170};
171
172static devclass_t pcm_devclass;
173
174/*
175 * Common code for the midi and pcm functions
176 *
177 * sb_cmd write a single byte to the CMD port.
178 * sb_cmd1 write a CMD + 1 byte arg
179 * sb_cmd2 write a CMD + 2 byte arg
180 * sb_get_byte returns a single byte from the DSP data port
181 *
182 * ess_write is actually sb_cmd1
183 * ess_read access ext. regs via sb_cmd(0xc0, reg) followed by sb_get_byte
184 */
185
186static int
187port_rd(struct resource *port, int off)
188{
189	return bus_space_read_1(rman_get_bustag(port),
190				rman_get_bushandle(port),
191				off);
192}
193
194static void
195port_wr(struct resource *port, int off, u_int8_t data)
196{
197	return bus_space_write_1(rman_get_bustag(port),
198				 rman_get_bushandle(port),
199				 off, data);
200}
201
202static int
203sb_rd(struct sb_info *sb, int reg)
204{
205	return port_rd(sb->io_base, reg);
206}
207
208static void
209sb_wr(struct sb_info *sb, int reg, u_int8_t val)
210{
211	port_wr(sb->io_base, reg, val);
212}
213
214static int
215sb_dspready(struct sb_info *sb)
216{
217	return ((sb_rd(sb, SBDSP_STATUS) & 0x80) == 0);
218}
219
220static int
221sb_dspwr(struct sb_info *sb, u_char val)
222{
223    	int  i;
224
225    	for (i = 0; i < 1000; i++) {
226		if (sb_dspready(sb)) {
227	    		sb_wr(sb, SBDSP_CMD, val);
228	    		return 1;
229		}
230		if (i > 10) DELAY((i > 100)? 1000 : 10);
231    	}
232    	printf("sb_dspwr(0x%02x) timed out.\n", val);
233    	return 0;
234}
235
236static int
237sb_cmd(struct sb_info *sb, u_char val)
238{
239#if 0
240	printf("sb_cmd: %x\n", val);
241#endif
242    	return sb_dspwr(sb, val);
243}
244
245static int
246sb_cmd1(struct sb_info *sb, u_char cmd, int val)
247{
248#if 0
249    	printf("sb_cmd1: %x, %x\n", cmd, val);
250#endif
251    	if (sb_dspwr(sb, cmd)) {
252		return sb_dspwr(sb, val & 0xff);
253    	} else return 0;
254}
255
256static int
257sb_cmd2(struct sb_info *sb, u_char cmd, int val)
258{
259#if 0
260    	printf("sb_cmd2: %x, %x\n", cmd, val);
261#endif
262    	if (sb_dspwr(sb, cmd)) {
263		return sb_dspwr(sb, val & 0xff) &&
264		       sb_dspwr(sb, (val >> 8) & 0xff);
265    	} else return 0;
266}
267
268/*
269 * in the SB, there is a set of indirect "mixer" registers with
270 * address at offset 4, data at offset 5
271 */
272static void
273sb_setmixer(struct sb_info *sb, u_int port, u_int value)
274{
275    	u_long   flags;
276
277    	flags = spltty();
278    	sb_wr(sb, SB_MIX_ADDR, (u_char) (port & 0xff)); /* Select register */
279    	DELAY(10);
280    	sb_wr(sb, SB_MIX_DATA, (u_char) (value & 0xff));
281    	DELAY(10);
282    	splx(flags);
283}
284
285static int
286sb_getmixer(struct sb_info *sb, u_int port)
287{
288    	int val;
289    	u_long flags;
290
291    	flags = spltty();
292    	sb_wr(sb, SB_MIX_ADDR, (u_char) (port & 0xff)); /* Select register */
293    	DELAY(10);
294    	val = sb_rd(sb, SB_MIX_DATA);
295    	DELAY(10);
296    	splx(flags);
297
298    	return val;
299}
300
301static u_int
302sb_get_byte(struct sb_info *sb)
303{
304    	int i;
305
306    	for (i = 1000; i > 0; i--) {
307		if (sb_rd(sb, DSP_DATA_AVAIL) & 0x80)
308			return sb_rd(sb, DSP_READ);
309		else
310			DELAY(20);
311    	}
312    	return 0xffff;
313}
314
315static int
316sb_reset_dsp(struct sb_info *sb)
317{
318    	sb_wr(sb, SBDSP_RST, 3);
319    	DELAY(100);
320    	sb_wr(sb, SBDSP_RST, 0);
321    	if (sb_get_byte(sb) != 0xAA) {
322        	DEB(printf("sb_reset_dsp 0x%lx failed\n",
323			   rman_get_start(d->io_base)));
324		return ENXIO;	/* Sorry */
325    	}
326    	if (sb->bd_flags & BD_F_ESS)
327		sb_cmd(sb, 0xc6);
328    	return 0;
329}
330
331static void
332sb_release_resources(struct sb_info *sb, device_t dev)
333{
334    	if (sb->irq) {
335    		if (sb->ih)
336			bus_teardown_intr(dev, sb->irq, sb->ih);
337 		bus_release_resource(dev, SYS_RES_IRQ, 0, sb->irq);
338		sb->irq = 0;
339    	}
340    	if (sb->drq1) {
341		bus_release_resource(dev, SYS_RES_DRQ, 0, sb->drq1);
342		sb->drq1 = 0;
343    	}
344    	if (sb->drq2) {
345		bus_release_resource(dev, SYS_RES_DRQ, 1, sb->drq2);
346		sb->drq2 = 0;
347    	}
348    	if (sb->io_base) {
349		bus_release_resource(dev, SYS_RES_IOPORT, 0, sb->io_base);
350		sb->io_base = 0;
351    	}
352    	if (sb->parent_dmat) {
353		bus_dma_tag_destroy(sb->parent_dmat);
354		sb->parent_dmat = 0;
355    	}
356     	free(sb, M_DEVBUF);
357}
358
359static int
360sb_alloc_resources(struct sb_info *sb, device_t dev)
361{
362	int rid;
363
364	rid = 0;
365	if (!sb->io_base)
366    		sb->io_base = bus_alloc_resource(dev, SYS_RES_IOPORT,
367						 &rid, 0, ~0, 1,
368						 RF_ACTIVE);
369	rid = 0;
370	if (!sb->irq)
371    		sb->irq = bus_alloc_resource(dev, SYS_RES_IRQ,
372					     &rid, 0, ~0, 1,
373					     RF_ACTIVE);
374	rid = 0;
375	if (!sb->drq1)
376    		sb->drq1 = bus_alloc_resource(dev, SYS_RES_DRQ,
377					      &rid, 0, ~0, 1,
378					      RF_ACTIVE);
379	rid = 1;
380	if (!sb->drq2)
381        	sb->drq2 = bus_alloc_resource(dev, SYS_RES_DRQ,
382					      &rid, 0, ~0, 1,
383					      RF_ACTIVE);
384
385    	if (sb->io_base && sb->drq1 && sb->irq) {
386		int bs = DSP_BUFFSIZE;
387
388		isa_dma_acquire(rman_get_start(sb->drq1));
389		isa_dmainit(rman_get_start(sb->drq1), bs);
390
391		if (sb->drq2) {
392			isa_dma_acquire(rman_get_start(sb->drq2));
393			isa_dmainit(rman_get_start(sb->drq2), bs);
394		}
395
396		return 0;
397	} else return ENXIO;
398}
399
400static void
401sb16_swap(void *v, int dir)
402{
403	struct sb_info *sb = v;
404	int pb = sb->pch.buffer->dl;
405	int rb = sb->rch.buffer->dl;
406	int pc = sb->pch.buffer->chan;
407	int rc = sb->rch.buffer->chan;
408	int swp = 0;
409
410	if (!pb && !rb) {
411		if (dir == PCMDIR_PLAY && pc < 4)
412			swp = 1;
413		else
414			if (dir == PCMDIR_REC && rc < 4)
415				swp = 1;
416	if (swp) {
417			int t;
418
419			t = sb->pch.buffer->chan;
420			sb->pch.buffer->chan = sb->rch.buffer->chan;
421			sb->rch.buffer->chan = t;
422			sb->pch.buffer->dir = ISADMA_WRITE;
423			sb->rch.buffer->dir = ISADMA_READ;
424		}
425	}
426}
427
428static int
429sb_doattach(device_t dev, struct sb_info *sb)
430{
431    	char status[SND_STATUSLEN];
432	int bs = DSP_BUFFSIZE;
433
434    	if (sb_alloc_resources(sb, dev))
435		goto no;
436    	if (sb_reset_dsp(sb))
437		goto no;
438    	mixer_init(dev, &sb_mixer, sb);
439
440	bus_setup_intr(dev, sb->irq, INTR_TYPE_TTY, sb_intr, sb, &sb->ih);
441    	if ((sb->bd_flags & BD_F_SB16) && !(sb->bd_flags & BD_F_SB16X))
442		pcm_setswap(dev, sb16_swap);
443    	if (!sb->drq2)
444		pcm_setflags(dev, pcm_getflags(dev) | SD_F_SIMPLEX);
445
446    	if (bus_dma_tag_create(/*parent*/NULL, /*alignment*/2, /*boundary*/0,
447			/*lowaddr*/BUS_SPACE_MAXADDR_24BIT,
448			/*highaddr*/BUS_SPACE_MAXADDR,
449			/*filter*/NULL, /*filterarg*/NULL,
450			/*maxsize*/bs, /*nsegments*/1,
451			/*maxsegz*/0x3ffff,
452			/*flags*/0, &sb->parent_dmat) != 0) {
453		device_printf(dev, "unable to create dma tag\n");
454		goto no;
455    	}
456
457    	snprintf(status, SND_STATUSLEN, "at io 0x%lx irq %ld drq %ld",
458    	     	rman_get_start(sb->io_base), rman_get_start(sb->irq),
459		rman_get_start(sb->drq1));
460    	if (sb->drq2)
461		snprintf(status + strlen(status), SND_STATUSLEN - strlen(status),
462			":%ld", rman_get_start(sb->drq2));
463
464    	if (pcm_register(dev, sb, 1, 1))
465		goto no;
466	pcm_addchan(dev, PCMDIR_REC, &sb_chantemplate, sb);
467	pcm_addchan(dev, PCMDIR_PLAY, &sb_chantemplate, sb);
468    	pcm_setstatus(dev, status);
469
470    	return 0;
471
472no:
473    	sb_release_resources(sb, dev);
474    	return ENXIO;
475}
476
477static int
478sb_detach(device_t dev)
479{
480	int r;
481	struct sb_info *sb;
482
483	r = pcm_unregister(dev);
484	if (r)
485		return r;
486
487	sb = pcm_getdevinfo(dev);
488    	sb_release_resources(sb, dev);
489	return 0;
490}
491
492static void
493sb_intr(void *arg)
494{
495    	struct sb_info *sb = (struct sb_info *)arg;
496    	int reason = 3, c;
497
498    	/*
499     	* SB < 4.0 is half duplex and has only 1 bit for int source,
500     	* so we fake it. SB 4.x (SB16) has the int source in a separate
501     	* register.
502     	* The Vibra16X has separate flags for 8 and 16 bit transfers, but
503     	* I have no idea how to tell capture from playback interrupts...
504     	*/
505    	if (sb->bd_flags & BD_F_SB16) {
506    		c = sb_getmixer(sb, IRQ_STAT);
507    		/* this tells us if the source is 8-bit or 16-bit dma. We
508     		* have to check the io channel to map it to read or write...
509     		*/
510    		reason = 0;
511    		if (c & 1) { /* 8-bit dma */
512			if (sb->pch.fmt & AFMT_U8)
513				reason |= 1;
514			if (sb->rch.fmt & AFMT_U8)
515				reason |= 2;
516    		}
517    		if (c & 2) { /* 16-bit dma */
518			if (sb->pch.fmt & AFMT_S16_LE)
519				reason |= 1;
520			if (sb->rch.fmt & AFMT_S16_LE)
521				reason |= 2;
522    		}
523    	} else c = 1;
524#if 0
525    	printf("sb_intr: reason=%d c=0x%x\n", reason, c);
526#endif
527    	if ((reason & 1) && (sb->pch.buffer->dl > 0))
528		chn_intr(sb->pch.channel);
529    	if ((reason & 2) && (sb->rch.buffer->dl > 0))
530		chn_intr(sb->rch.channel);
531    	if (c & 1)
532		sb_rd(sb, DSP_DATA_AVAIL); /* 8-bit int ack */
533    	if (c & 2)
534		sb_rd(sb, DSP_DATA_AVL16); /* 16-bit int ack */
535}
536
537static int
538sb_speed(struct sb_chinfo *ch)
539{
540    	struct sb_info *sb = ch->parent;
541    	int play = (ch->dir == PCMDIR_PLAY)? 1 : 0;
542    	int stereo = (ch->fmt & AFMT_STEREO)? 1 : 0;
543	int speed = ch->spd;
544
545    	if (sb->bd_flags & BD_F_SB16) {
546		RANGE(speed, 5000, 45000);
547		sb_cmd(sb, 0x42 - play);
548    		sb_cmd(sb, speed >> 8);
549		sb_cmd(sb, speed & 0xff);
550    	} else {
551		u_char tconst;
552		int max_speed = 45000, tmp;
553        	u_long flags;
554
555    		/* here enforce speed limitations - max 22050 on sb 1.x*/
556    		if (sb->bd_id <= 0x200)
557			max_speed = 22050;
558
559    		/*
560     	 	* SB models earlier than SB Pro have low limit for the
561     	 	* input rate. Note that this is only for input, but since
562     	 	* we do not support separate values for rec & play....
563     	 	*/
564		if (!play) {
565    			if (sb->bd_id <= 0x200)
566				max_speed = 13000;
567    			else
568				if (sb->bd_id < 0x300)
569					max_speed = 15000;
570		}
571    		RANGE(speed, 4000, max_speed);
572    		if (stereo)
573			speed <<= 1;
574
575    		/*
576     	 	* Now the speed should be valid. Compute the value to be
577     	 	* programmed into the board.
578     	 	*/
579    		if (speed > 22050) { /* High speed mode on 2.01/3.xx */
580			tconst = (u_char)
581				((65536 - ((256000000 + speed / 2) / speed))
582				>> 8);
583			sb->bd_flags |= BD_F_HISPEED;
584			tmp = 65536 - (tconst << 8);
585			speed = (256000000 + tmp / 2) / tmp;
586    		} else {
587			sb->bd_flags &= ~BD_F_HISPEED;
588			tconst = (256 - ((1000000 + speed / 2) / speed)) & 0xff;
589			tmp = 256 - tconst;
590			speed = (1000000 + tmp / 2) / tmp;
591    		}
592		flags = spltty();
593		sb_cmd1(sb, 0x40, tconst); /* set time constant */
594		splx(flags);
595    		if (stereo)
596			speed >>= 1;
597    	}
598	ch->spd = speed;
599    	return speed;
600}
601
602static int
603sb_start(struct sb_chinfo *ch)
604{
605	struct sb_info *sb = ch->parent;
606    	int play = (ch->dir == PCMDIR_PLAY)? 1 : 0;
607    	int b16 = (ch->fmt & AFMT_S16_LE)? 1 : 0;
608    	int stereo = (ch->fmt & AFMT_STEREO)? 1 : 0;
609	int l = ch->buffer->dl;
610	int dh = ch->buffer->chan > 3;
611	u_char i1, i2;
612
613	if (b16 || dh)
614		l >>= 1;
615	l--;
616
617	if (play)
618		sb_cmd(sb, DSP_CMD_SPKON);
619
620	if (sb->bd_flags & BD_F_SB16) {
621	    	i1 = DSP_F16_AUTO | DSP_F16_FIFO_ON;
622	        i1 |= play? DSP_F16_DAC : DSP_F16_ADC;
623	    	i1 |= (b16 || dh)? DSP_DMA16 : DSP_DMA8;
624	    	i2 = (stereo? DSP_F16_STEREO : 0) | (b16? DSP_F16_SIGNED : 0);
625	    	sb_cmd(sb, i1);
626	    	sb_cmd2(sb, i2, l);
627	} else {
628	    	if (sb->bd_flags & BD_F_HISPEED)
629			i1 = play? 0x90 : 0x98;
630	    	else
631			i1 = play? 0x1c : 0x2c;
632	    	sb_setmixer(sb, 0x0e, stereo? 2 : 0);
633	    	sb_cmd2(sb, 0x48, l);
634       	    	sb_cmd(sb, i1);
635	}
636	sb->bd_flags |= BD_F_DMARUN << b16;
637	return 0;
638}
639
640static int
641sb_stop(struct sb_chinfo *ch)
642{
643	struct sb_info *sb = ch->parent;
644    	int play = (ch->dir == PCMDIR_PLAY)? 1 : 0;
645    	int b16 = (ch->fmt & AFMT_S16_LE)? 1 : 0;
646
647    	if (sb->bd_flags & BD_F_HISPEED)
648		sb_reset_dsp(sb);
649	else {
650		sb_cmd(sb, b16? DSP_CMD_DMAPAUSE_16 : DSP_CMD_DMAPAUSE_8);
651	       /*
652		* The above seems to have the undocumented side effect of
653		* blocking the other side as well. If the other
654		* channel was active (SB16) I have to re-enable it :(
655		*/
656		if (sb->bd_flags & (BD_F_DMARUN << (1 - b16)))
657			sb_cmd(sb, b16? 0xd4 : 0xd6 );
658	}
659	if (play)
660		sb_cmd(sb, DSP_CMD_SPKOFF); /* speaker off */
661	sb->bd_flags &= ~(BD_F_DMARUN << b16);
662	return 0;
663}
664
665/* channel interface */
666static void *
667sbchan_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir)
668{
669	struct sb_info *sb = devinfo;
670	struct sb_chinfo *ch = (dir == PCMDIR_PLAY)? &sb->pch : &sb->rch;
671	int dch, dl, dh;
672
673	ch->parent = sb;
674	ch->channel = c;
675	ch->buffer = b;
676	ch->buffer->bufsize = DSP_BUFFSIZE;
677	if (chn_allocbuf(ch->buffer, sb->parent_dmat) == -1)
678		return NULL;
679	dch = (dir == PCMDIR_PLAY)? 1 : 0;
680	if (sb->bd_flags & BD_F_SB16X)
681		dch = !dch;
682	dl = rman_get_start(sb->drq1);
683	dh = sb->drq2? rman_get_start(sb->drq2) : dl;
684	ch->buffer->chan = dch? dh : dl;
685	return ch;
686}
687
688static int
689sbchan_setdir(void *data, int dir)
690{
691	struct sb_chinfo *ch = data;
692
693	ch->dir = dir;
694	return 0;
695}
696
697static int
698sbchan_setformat(void *data, u_int32_t format)
699{
700	struct sb_chinfo *ch = data;
701
702	ch->fmt = format;
703	return 0;
704}
705
706static int
707sbchan_setspeed(void *data, u_int32_t speed)
708{
709	struct sb_chinfo *ch = data;
710
711	ch->spd = speed;
712	return sb_speed(ch);
713}
714
715static int
716sbchan_setblocksize(void *data, u_int32_t blocksize)
717{
718	return blocksize;
719}
720
721static int
722sbchan_trigger(void *data, int go)
723{
724	struct sb_chinfo *ch = data;
725
726	if (go == PCMTRIG_EMLDMAWR || go == PCMTRIG_EMLDMARD)
727		return 0;
728
729	buf_isadma(ch->buffer, go);
730	if (go == PCMTRIG_START)
731		sb_start(ch);
732	else
733		sb_stop(ch);
734	return 0;
735}
736
737static int
738sbchan_getptr(void *data)
739{
740	struct sb_chinfo *ch = data;
741
742	return buf_isadmaptr(ch->buffer);
743}
744
745static pcmchan_caps *
746sbchan_getcaps(void *data)
747{
748	struct sb_chinfo *ch = data;
749	int p = (ch->dir == PCMDIR_PLAY)? 1 : 0;
750
751	if (ch->parent->bd_id < 0x300)
752		return p? &sb_playcaps : &sb_reccaps;
753	else if (ch->parent->bd_id < 0x400)
754		return p? &sbpro_playcaps : &sbpro_reccaps;
755	else if (ch->parent->bd_flags & BD_F_SB16X)
756		return &sb16x_caps;
757	else
758		return (ch->buffer->chan >= 4)? &sb16_hcaps : &sb16_lcaps;
759}
760
761/************************************************************/
762
763static int
764sbmix_init(snd_mixer *m)
765{
766    	struct sb_info *sb = mix_getdevinfo(m);
767
768    	switch (sb->bd_flags & BD_F_MIX_MASK) {
769    	case BD_F_MIX_CT1345: /* SB 3.0 has 1345 mixer */
770		mix_setdevs(m, SBPRO_MIXER_DEVICES);
771		mix_setrecdevs(m, SBPRO_RECORDING_DEVICES);
772		sb_setmixer(sb, 0, 1); /* reset mixer */
773		sb_setmixer(sb, MIC_VOL, 0x6); /* mic volume max */
774		sb_setmixer(sb, RECORD_SRC, 0x0); /* mic source */
775		sb_setmixer(sb, FM_VOL, 0x0); /* no midi */
776		break;
777
778    	case BD_F_MIX_CT1745: /* SB16 mixer ... */
779		mix_setdevs(m, SB16_MIXER_DEVICES);
780		mix_setrecdevs(m, SB16_RECORDING_DEVICES);
781		sb_setmixer(sb, 0x3c, 0x1f); /* make all output active */
782		sb_setmixer(sb, 0x3d, 0); /* make all inputs-l off */
783		sb_setmixer(sb, 0x3e, 0); /* make all inputs-r off */
784    	}
785    	return 0;
786}
787
788static int
789sbmix_set(snd_mixer *m, unsigned dev, unsigned left, unsigned right)
790{
791    	struct sb_info *sb = mix_getdevinfo(m);
792    	int regoffs;
793    	u_char   val;
794    	mixer_tab *iomap;
795
796    	switch (sb->bd_flags & BD_F_MIX_MASK) {
797    	case BD_F_MIX_CT1345:
798		iomap = &sbpro_mix;
799		break;
800
801    	case BD_F_MIX_CT1745:
802		iomap = &sb16_mix;
803		break;
804
805    	default:
806        	return -1;
807    	}
808
809	/* Change left channel */
810    	regoffs = (*iomap)[dev][LEFT_CHN].regno;
811    	if (regoffs != 0) {
812		val = sb_getmixer(sb, regoffs);
813		change_bits(iomap, &val, dev, LEFT_CHN, left);
814		sb_setmixer(sb, regoffs, val);
815	}
816
817	/* Change right channel */
818	regoffs = (*iomap)[dev][RIGHT_CHN].regno;
819	if (regoffs != 0) {
820		val = sb_getmixer(sb, regoffs); /* Read the new one */
821		change_bits(iomap, &val, dev, RIGHT_CHN, right);
822		sb_setmixer(sb, regoffs, val);
823	} else
824		right = left;
825
826    	return left | (right << 8);
827}
828
829static int
830sbmix_setrecsrc(snd_mixer *m, u_int32_t src)
831{
832    	struct sb_info *sb = mix_getdevinfo(m);
833    	u_char recdev;
834
835    	switch (sb->bd_flags & BD_F_MIX_MASK) {
836    	case BD_F_MIX_CT1345:
837		if      (src == SOUND_MASK_LINE)
838			recdev = 0x06;
839		else if (src == SOUND_MASK_CD)
840			recdev = 0x02;
841		else { /* default: mic */
842	    		src = SOUND_MASK_MIC;
843	    		recdev = 0;
844		}
845		sb_setmixer(sb, RECORD_SRC, recdev |
846			    (sb_getmixer(sb, RECORD_SRC) & ~0x07));
847		break;
848
849    	case BD_F_MIX_CT1745: /* sb16 */
850		recdev = 0;
851		if (src & SOUND_MASK_MIC)
852			recdev |= 0x01; /* mono mic */
853		if (src & SOUND_MASK_CD)
854			recdev |= 0x06; /* l+r cd */
855		if (src & SOUND_MASK_LINE)
856			recdev |= 0x18; /* l+r line */
857		if (src & SOUND_MASK_SYNTH)
858			recdev |= 0x60; /* l+r midi */
859		sb_setmixer(sb, SB16_IMASK_L, recdev);
860		sb_setmixer(sb, SB16_IMASK_R, recdev);
861		/*
862	 	* since the same volume controls apply to the input and
863	 	* output sections, the best approach to have a consistent
864	 	* behaviour among cards would be to disable the output path
865	 	* on devices which are used to record.
866	 	* However, since users like to have feedback, we only disable
867	 	* the mic -- permanently.
868	 	*/
869        	sb_setmixer(sb, SB16_OMASK, 0x1f & ~1);
870		break;
871       	}
872    	return src;
873}
874
875static int
876sbsbc_probe(device_t dev)
877{
878    	char buf[64];
879	uintptr_t func, ver, r, f;
880
881	/* The parent device has already been probed. */
882	r = BUS_READ_IVAR(device_get_parent(dev), dev, 0, &func);
883	if (func != SCF_PCM)
884		return (ENXIO);
885
886	r = BUS_READ_IVAR(device_get_parent(dev), dev, 1, &ver);
887	f = (ver & 0xffff0000) >> 16;
888	ver &= 0x0000ffff;
889	if (f & BD_F_ESS)
890		return (ENXIO);
891
892	snprintf(buf, sizeof buf, "SB DSP %d.%02d%s", (int) ver >> 8, (int) ver & 0xff,
893		(f & BD_F_SB16X)? " (ViBRA16X)" : "");
894    	device_set_desc_copy(dev, buf);
895
896	return 0;
897}
898
899static int
900sbsbc_attach(device_t dev)
901{
902    	struct sb_info *sb;
903	uintptr_t ver;
904
905    	sb = (struct sb_info *)malloc(sizeof *sb, M_DEVBUF, M_NOWAIT);
906    	if (!sb)
907		return ENXIO;
908    	bzero(sb, sizeof *sb);
909
910	BUS_READ_IVAR(device_get_parent(dev), dev, 1, &ver);
911	sb->bd_id = ver & 0x0000ffff;
912	sb->bd_flags = (ver & 0xffff0000) >> 16;
913
914    	return sb_doattach(dev, sb);
915}
916
917static device_method_t sbsbc_methods[] = {
918	/* Device interface */
919	DEVMETHOD(device_probe,		sbsbc_probe),
920	DEVMETHOD(device_attach,	sbsbc_attach),
921	DEVMETHOD(device_detach,	sb_detach),
922
923	{ 0, 0 }
924};
925
926static driver_t sbsbc_driver = {
927	"pcm",
928	sbsbc_methods,
929	sizeof(snddev_info),
930};
931
932DRIVER_MODULE(snd_sb, sbc, sbsbc_driver, pcm_devclass, 0, 0);
933MODULE_DEPEND(snd_sb, snd_pcm, PCM_MINVER, PCM_PREFVER, PCM_MAXVER);
934MODULE_VERSION(snd_sb, 1);
935
936
937
938
939