xref: /netbsd/sys/dev/pci/sv.c (revision bf9ec67e)
1 /*      $NetBSD: sv.c,v 1.15 2001/11/13 07:48:49 lukem Exp $ */
2 /*      $OpenBSD: sv.c,v 1.2 1998/07/13 01:50:15 csapuntz Exp $ */
3 
4 /*
5  * Copyright (c) 1999 The NetBSD Foundation, Inc.
6  * All rights reserved.
7  *
8  * This code is derived from software contributed to The NetBSD Foundation
9  * by Charles M. Hannum.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in the
18  *    documentation and/or other materials provided with the distribution.
19  * 3. All advertising materials mentioning features or use of this software
20  *    must display the following acknowledgement:
21  *        This product includes software developed by the NetBSD
22  *        Foundation, Inc. and its contributors.
23  * 4. Neither the name of The NetBSD Foundation nor the names of its
24  *    contributors may be used to endorse or promote products derived
25  *    from this software without specific prior written permission.
26  *
27  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
28  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
29  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
31  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37  * POSSIBILITY OF SUCH DAMAGE.
38  */
39 
40 /*
41  * Copyright (c) 1998 Constantine Paul Sapuntzakis
42  * All rights reserved
43  *
44  * Author: Constantine Paul Sapuntzakis (csapuntz@cvs.openbsd.org)
45  *
46  * Redistribution and use in source and binary forms, with or without
47  * modification, are permitted provided that the following conditions
48  * are met:
49  * 1. Redistributions of source code must retain the above copyright
50  *    notice, this list of conditions and the following disclaimer.
51  * 2. Redistributions in binary form must reproduce the above copyright
52  *    notice, this list of conditions and the following disclaimer in the
53  *    documentation and/or other materials provided with the distribution.
54  * 3. The author's name or those of the contributors may be used to
55  *    endorse or promote products derived from this software without
56  *    specific prior written permission.
57  *
58  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) AND CONTRIBUTORS
59  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
60  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
61  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
62  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
63  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
64  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
65  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
66  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
67  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
68  * POSSIBILITY OF SUCH DAMAGE.
69  */
70 
71 /*
72  * S3 SonicVibes driver
73  *   Heavily based on the eap driver by Lennart Augustsson
74  */
75 
76 #include <sys/cdefs.h>
77 __KERNEL_RCSID(0, "$NetBSD: sv.c,v 1.15 2001/11/13 07:48:49 lukem Exp $");
78 
79 #include <sys/param.h>
80 #include <sys/systm.h>
81 #include <sys/kernel.h>
82 #include <sys/malloc.h>
83 #include <sys/device.h>
84 
85 #include <dev/pci/pcireg.h>
86 #include <dev/pci/pcivar.h>
87 #include <dev/pci/pcidevs.h>
88 
89 #include <sys/audioio.h>
90 #include <dev/audio_if.h>
91 #include <dev/mulaw.h>
92 #include <dev/auconv.h>
93 
94 #include <dev/ic/i8237reg.h>
95 #include <dev/pci/svreg.h>
96 #include <dev/pci/svvar.h>
97 
98 #include <machine/bus.h>
99 
100 #ifdef AUDIO_DEBUG
101 #define DPRINTF(x)	if (svdebug) printf x
102 #define DPRINTFN(n,x)	if (svdebug>(n)) printf x
103 int	svdebug = 0;
104 #else
105 #define DPRINTF(x)
106 #define DPRINTFN(n,x)
107 #endif
108 
109 int	sv_match __P((struct device *, struct cfdata *, void *));
110 void	sv_attach __P((struct device *, struct device *, void *));
111 int	sv_intr __P((void *));
112 
113 struct sv_dma {
114 	bus_dmamap_t map;
115 	caddr_t addr;
116 	bus_dma_segment_t segs[1];
117 	int nsegs;
118 	size_t size;
119 	struct sv_dma *next;
120 };
121 #define DMAADDR(p) ((p)->map->dm_segs[0].ds_addr)
122 #define KERNADDR(p) ((void *)((p)->addr))
123 
124 struct cfattach sv_ca = {
125 	sizeof(struct sv_softc), sv_match, sv_attach
126 };
127 
128 struct audio_device sv_device = {
129 	"S3 SonicVibes",
130 	"",
131 	"sv"
132 };
133 
134 #define ARRAY_SIZE(foo)  ((sizeof(foo)) / sizeof(foo[0]))
135 
136 int	sv_allocmem __P((struct sv_softc *, size_t, size_t, int, struct sv_dma *));
137 int	sv_freemem __P((struct sv_softc *, struct sv_dma *));
138 
139 int	sv_open __P((void *, int));
140 void	sv_close __P((void *));
141 int	sv_query_encoding __P((void *, struct audio_encoding *));
142 int	sv_set_params __P((void *, int, int, struct audio_params *, struct audio_params *));
143 int	sv_round_blocksize __P((void *, int));
144 int	sv_trigger_output __P((void *, void *, void *, int, void (*)(void *),
145 	    void *, struct audio_params *));
146 int	sv_trigger_input __P((void *, void *, void *, int, void (*)(void *),
147 	    void *, struct audio_params *));
148 int	sv_halt_output __P((void *));
149 int	sv_halt_input __P((void *));
150 int	sv_getdev __P((void *, struct audio_device *));
151 int	sv_mixer_set_port __P((void *, mixer_ctrl_t *));
152 int	sv_mixer_get_port __P((void *, mixer_ctrl_t *));
153 int	sv_query_devinfo __P((void *, mixer_devinfo_t *));
154 void   *sv_malloc __P((void *, int, size_t, int, int));
155 void	sv_free __P((void *, void *, int));
156 size_t	sv_round_buffersize __P((void *, int, size_t));
157 paddr_t	sv_mappage __P((void *, void *, off_t, int));
158 int	sv_get_props __P((void *));
159 
160 #ifdef AUDIO_DEBUG
161 void    sv_dumpregs __P((struct sv_softc *sc));
162 #endif
163 
164 struct audio_hw_if sv_hw_if = {
165 	sv_open,
166 	sv_close,
167 	NULL,
168 	sv_query_encoding,
169 	sv_set_params,
170 	sv_round_blocksize,
171 	NULL,
172 	NULL,
173 	NULL,
174 	NULL,
175 	NULL,
176 	sv_halt_output,
177 	sv_halt_input,
178 	NULL,
179 	sv_getdev,
180 	NULL,
181 	sv_mixer_set_port,
182 	sv_mixer_get_port,
183 	sv_query_devinfo,
184 	sv_malloc,
185 	sv_free,
186 	sv_round_buffersize,
187 	sv_mappage,
188 	sv_get_props,
189 	sv_trigger_output,
190 	sv_trigger_input,
191 	NULL,
192 };
193 
194 
195 static u_int8_t sv_read __P((struct sv_softc *, u_int8_t));
196 static u_int8_t sv_read_indirect __P((struct sv_softc *, u_int8_t));
197 static void sv_write __P((struct sv_softc *, u_int8_t, u_int8_t ));
198 static void sv_write_indirect __P((struct sv_softc *, u_int8_t, u_int8_t ));
199 static void sv_init_mixer __P((struct sv_softc *));
200 
201 static void sv_defer __P((struct device *self));
202 
203 static void
204 sv_write (sc, reg, val)
205 	struct sv_softc *sc;
206 	u_int8_t reg, val;
207 
208 {
209 	DPRINTFN(8,("sv_write(0x%x, 0x%x)\n", reg, val));
210 	bus_space_write_1(sc->sc_iot, sc->sc_ioh, reg, val);
211 }
212 
213 static u_int8_t
214 sv_read(sc, reg)
215 	struct sv_softc *sc;
216 	u_int8_t reg;
217 
218 {
219 	u_int8_t val;
220 
221 	val = bus_space_read_1(sc->sc_iot, sc->sc_ioh, reg);
222 	DPRINTFN(8,("sv_read(0x%x) = 0x%x\n", reg, val));
223 	return val;
224 }
225 
226 static u_int8_t
227 sv_read_indirect(sc, reg)
228 	struct sv_softc *sc;
229 	u_int8_t reg;
230 {
231 	u_int8_t val;
232 	int s = splaudio();
233 
234 	sv_write(sc, SV_CODEC_IADDR, reg & SV_IADDR_MASK);
235 	val = sv_read(sc, SV_CODEC_IDATA);
236 	splx(s);
237 	return (val);
238 }
239 
240 static void
241 sv_write_indirect(sc, reg, val)
242 	struct sv_softc *sc;
243 	u_int8_t reg, val;
244 {
245 	u_int8_t iaddr = reg & SV_IADDR_MASK;
246 	int s = splaudio();
247 
248 	if (reg == SV_DMA_DATA_FORMAT)
249 		iaddr |= SV_IADDR_MCE;
250 
251 	sv_write(sc, SV_CODEC_IADDR, iaddr);
252 	sv_write(sc, SV_CODEC_IDATA, val);
253 	splx(s);
254 }
255 
256 int
257 sv_match(parent, match, aux)
258 	struct device *parent;
259 	struct cfdata *match;
260 	void *aux;
261 {
262 	struct pci_attach_args *pa = aux;
263 
264 	if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_S3 &&
265 	    PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_S3_SONICVIBES)
266 		return (1);
267 
268 	return (0);
269 }
270 
271 int pci_alloc_io __P((pci_chipset_tag_t pc, pcitag_t pt,
272 		      int pcioffs,
273 		      bus_space_tag_t iot, bus_size_t size,
274 		      bus_size_t align, bus_size_t bound, int flags,
275 		      bus_space_handle_t *ioh));
276 
277 #define PCI_IO_ALLOC_LOW 0xa000
278 #define PCI_IO_ALLOC_HIGH 0xb000
279 int
280 pci_alloc_io(pc, pt, pcioffs, iot, size, align, bound, flags, ioh)
281 	pci_chipset_tag_t pc;
282 	pcitag_t pt;
283 	int pcioffs;
284 	bus_space_tag_t iot;
285 	bus_size_t size;
286 	bus_size_t align;
287 	bus_size_t bound;
288 	int flags;
289 	bus_space_handle_t *ioh;
290 {
291 	bus_addr_t addr;
292 	int error;
293 
294 	error = bus_space_alloc(iot, PCI_IO_ALLOC_LOW, PCI_IO_ALLOC_HIGH,
295 				size, align, bound, flags, &addr, ioh);
296 	if (error)
297 		return(error);
298 
299 	pci_conf_write(pc, pt, pcioffs, addr);
300 	return (0);
301 }
302 
303 /*
304  * Allocate IO addresses when all other configuration is done.
305  */
306 void
307 sv_defer(self)
308 	struct device *self;
309 {
310 	struct sv_softc *sc = (struct sv_softc *)self;
311 	pci_chipset_tag_t pc = sc->sc_pa.pa_pc;
312 	pcitag_t pt = sc->sc_pa.pa_tag;
313 	pcireg_t dmaio;
314 
315 	DPRINTF(("sv_defer: %p\n", sc));
316 	if (pci_alloc_io(pc, pt, SV_DMAA_CONFIG_OFF,
317 			  sc->sc_iot, SV_DMAA_SIZE, SV_DMAA_ALIGN, 0,
318 			  0, &sc->sc_dmaa_ioh)) {
319 		printf("sv_attach: cannot allocate DMA A range\n");
320 		return;
321 	}
322 	dmaio = pci_conf_read(pc, pt, SV_DMAA_CONFIG_OFF);
323 	DPRINTF(("sv_attach: addr a dmaio=0x%lx\n", (u_long)dmaio));
324 	pci_conf_write(pc, pt, SV_DMAA_CONFIG_OFF,
325 		       dmaio | SV_DMA_CHANNEL_ENABLE | SV_DMAA_EXTENDED_ADDR);
326 
327 	if (pci_alloc_io(pc, pt, SV_DMAC_CONFIG_OFF,
328 			  sc->sc_iot, SV_DMAC_SIZE, SV_DMAC_ALIGN, 0,
329 			  0, &sc->sc_dmac_ioh)) {
330 		printf("sv_attach: cannot allocate DMA C range\n");
331 		return;
332 	}
333 	dmaio = pci_conf_read(pc, pt, SV_DMAC_CONFIG_OFF);
334 	DPRINTF(("sv_attach: addr c dmaio=0x%lx\n", (u_long)dmaio));
335 	pci_conf_write(pc, pt, SV_DMAC_CONFIG_OFF,
336 		       dmaio | SV_DMA_CHANNEL_ENABLE);
337 
338 	sc->sc_dmaset = 1;
339 }
340 
341 void
342 sv_attach(parent, self, aux)
343 	struct device *parent, *self;
344 	void *aux;
345 {
346 	struct sv_softc *sc = (struct sv_softc *)self;
347 	struct pci_attach_args *pa = aux;
348 	pci_chipset_tag_t pc = pa->pa_pc;
349 	pcitag_t pt = pa->pa_tag;
350 	pci_intr_handle_t ih;
351 	pcireg_t csr;
352 	char const *intrstr;
353 	u_int8_t reg;
354 	struct audio_attach_args arg;
355 
356 	printf ("\n");
357 
358 	/* Map I/O registers */
359 	if (pci_mapreg_map(pa, SV_ENHANCED_PORTBASE_SLOT,
360 			   PCI_MAPREG_TYPE_IO, 0,
361 			   &sc->sc_iot, &sc->sc_ioh, NULL, NULL)) {
362 		printf("%s: can't map enhanced i/o space\n",
363 		       sc->sc_dev.dv_xname);
364 		return;
365 	}
366 	if (pci_mapreg_map(pa, SV_FM_PORTBASE_SLOT,
367 			   PCI_MAPREG_TYPE_IO, 0,
368 			   &sc->sc_opliot, &sc->sc_oplioh, NULL, NULL)) {
369 		printf("%s: can't map FM i/o space\n", sc->sc_dev.dv_xname);
370 		return;
371 	}
372 	if (pci_mapreg_map(pa, SV_MIDI_PORTBASE_SLOT,
373 			   PCI_MAPREG_TYPE_IO, 0,
374 			   &sc->sc_midiiot, &sc->sc_midiioh, NULL, NULL)) {
375 		printf("%s: can't map MIDI i/o space\n", sc->sc_dev.dv_xname);
376 		return;
377 	}
378 	DPRINTF(("sv: IO ports: enhanced=0x%x, OPL=0x%x, MIDI=0x%x\n",
379 		 (int)sc->sc_ioh, (int)sc->sc_oplioh, (int)sc->sc_midiioh));
380 
381 #ifdef alpha
382 	/* XXX Force allocation through the SGMAP. */
383 	sc->sc_dmatag = alphabus_dma_get_tag(pa->pa_dmat, ALPHA_BUS_ISA);
384 #else
385 	sc->sc_dmatag = pa->pa_dmat;
386 #endif
387 
388 	pci_conf_write(pc, pt, SV_DMAA_CONFIG_OFF, SV_DMAA_EXTENDED_ADDR);
389 	pci_conf_write(pc, pt, SV_DMAC_CONFIG_OFF, 0);
390 
391 	/* Enable the device. */
392 	csr = pci_conf_read(pc, pt, PCI_COMMAND_STATUS_REG);
393 	pci_conf_write(pc, pt, PCI_COMMAND_STATUS_REG,
394 		       csr | PCI_COMMAND_MASTER_ENABLE);
395 
396 	sv_write_indirect(sc, SV_ANALOG_POWER_DOWN_CONTROL, 0);
397 	sv_write_indirect(sc, SV_DIGITAL_POWER_DOWN_CONTROL, 0);
398 
399 	/* initialize codec registers */
400 	reg = sv_read(sc, SV_CODEC_CONTROL);
401 	reg |= SV_CTL_RESET;
402 	sv_write(sc, SV_CODEC_CONTROL, reg);
403 	delay(50);
404 
405 	reg = sv_read(sc, SV_CODEC_CONTROL);
406 	reg &= ~SV_CTL_RESET;
407 	reg |= SV_CTL_INTA | SV_CTL_ENHANCED;
408 
409 	/* This write clears the reset */
410 	sv_write(sc, SV_CODEC_CONTROL, reg);
411 	delay(50);
412 
413 	/* This write actually shoves the new values in */
414 	sv_write(sc, SV_CODEC_CONTROL, reg);
415 
416 	DPRINTF(("sv_attach: control=0x%x\n", sv_read(sc, SV_CODEC_CONTROL)));
417 
418 	/* Enable DMA interrupts */
419 	reg = sv_read(sc, SV_CODEC_INTMASK);
420 	reg &= ~(SV_INTMASK_DMAA | SV_INTMASK_DMAC);
421 	reg |= SV_INTMASK_UD | SV_INTMASK_SINT | SV_INTMASK_MIDI;
422 	sv_write(sc, SV_CODEC_INTMASK, reg);
423 
424 	sv_read(sc, SV_CODEC_STATUS);
425 
426 	/* Map and establish the interrupt. */
427 	if (pci_intr_map(pa, &ih)) {
428 		printf("%s: couldn't map interrupt\n", sc->sc_dev.dv_xname);
429 		return;
430 	}
431 	intrstr = pci_intr_string(pc, ih);
432 	sc->sc_ih = pci_intr_establish(pc, ih, IPL_AUDIO, sv_intr, sc);
433 	if (sc->sc_ih == NULL) {
434 		printf("%s: couldn't establish interrupt",
435 		       sc->sc_dev.dv_xname);
436 		if (intrstr != NULL)
437 			printf(" at %s", intrstr);
438 		printf("\n");
439 		return;
440 	}
441 	printf("%s: interrupting at %s\n", sc->sc_dev.dv_xname, intrstr);
442 	printf("%s: rev %d", sc->sc_dev.dv_xname,
443 	       sv_read_indirect(sc, SV_REVISION_LEVEL));
444 	if (sv_read(sc, SV_CODEC_CONTROL) & SV_CTL_MD1)
445 		printf(", reverb SRAM present");
446 	if (!(sv_read_indirect(sc, SV_WAVETABLE_SOURCE_SELECT) & SV_WSS_WT0))
447 		printf(", wavetable ROM present");
448 	printf("\n");
449 
450 	sv_init_mixer(sc);
451 
452 	audio_attach_mi(&sv_hw_if, sc, &sc->sc_dev);
453 
454 	arg.type = AUDIODEV_TYPE_OPL;
455 	arg.hwif = 0;
456 	arg.hdl = 0;
457 	(void)config_found(&sc->sc_dev, &arg, audioprint);
458 
459 	sc->sc_pa = *pa;	/* for deferred setup */
460 	config_defer(self, sv_defer);
461 }
462 
463 #ifdef AUDIO_DEBUG
464 void
465 sv_dumpregs(sc)
466 	struct sv_softc *sc;
467 {
468 	int idx;
469 
470 #if 0
471 	for (idx = 0; idx < 0x50; idx += 4)
472 		printf ("%02x = %x\n", idx,
473 			pci_conf_read(pa->pa_pc, pa->pa_tag, idx));
474 #endif
475 
476 	for (idx = 0; idx < 6; idx++)
477 		printf ("REG %02x = %02x\n", idx, sv_read(sc, idx));
478 
479 	for (idx = 0; idx < 0x32; idx++)
480 		printf ("IREG %02x = %02x\n", idx, sv_read_indirect(sc, idx));
481 
482 	for (idx = 0; idx < 0x10; idx++)
483 		printf ("DMA %02x = %02x\n", idx,
484 			bus_space_read_1(sc->sc_iot, sc->sc_dmaa_ioh, idx));
485 }
486 #endif
487 
488 int
489 sv_intr(p)
490 	void *p;
491 {
492 	struct sv_softc *sc = p;
493 	u_int8_t intr;
494 
495 	intr = sv_read(sc, SV_CODEC_STATUS);
496 	DPRINTFN(5,("sv_intr: intr=0x%x\n", intr));
497 
498 	if (!(intr & (SV_INTSTATUS_DMAA | SV_INTSTATUS_DMAC)))
499 		return (0);
500 
501 	if (intr & SV_INTSTATUS_DMAA) {
502 		if (sc->sc_pintr)
503 			sc->sc_pintr(sc->sc_parg);
504 	}
505 
506 	if (intr & SV_INTSTATUS_DMAC) {
507 		if (sc->sc_rintr)
508 			sc->sc_rintr(sc->sc_rarg);
509 	}
510 
511 	return (1);
512 }
513 
514 int
515 sv_allocmem(sc, size, align, direction, p)
516 	struct sv_softc *sc;
517 	size_t size;
518 	size_t align;
519 	int direction;
520 	struct sv_dma *p;
521 {
522 	int error;
523 
524 	p->size = size;
525 	error = bus_dmamem_alloc(sc->sc_dmatag, p->size, align, 0,
526 				 p->segs, ARRAY_SIZE(p->segs),
527 				 &p->nsegs, BUS_DMA_NOWAIT);
528 	if (error)
529 		return (error);
530 
531 	error = bus_dmamem_map(sc->sc_dmatag, p->segs, p->nsegs, p->size,
532 			       &p->addr, BUS_DMA_NOWAIT|BUS_DMA_COHERENT);
533 	if (error)
534 		goto free;
535 
536 	error = bus_dmamap_create(sc->sc_dmatag, p->size, 1, p->size,
537 				  0, BUS_DMA_NOWAIT, &p->map);
538 	if (error)
539 		goto unmap;
540 
541 	error = bus_dmamap_load(sc->sc_dmatag, p->map, p->addr, p->size, NULL,
542 				BUS_DMA_NOWAIT |
543                                 (direction == AUMODE_RECORD) ? BUS_DMA_READ : BUS_DMA_WRITE);
544 	if (error)
545 		goto destroy;
546 	DPRINTF(("sv_allocmem: pa=%lx va=%lx pba=%lx\n",
547 	    (long)p->segs[0].ds_addr, (long)KERNADDR(p), (long)DMAADDR(p)));
548 	return (0);
549 
550 destroy:
551 	bus_dmamap_destroy(sc->sc_dmatag, p->map);
552 unmap:
553 	bus_dmamem_unmap(sc->sc_dmatag, p->addr, p->size);
554 free:
555 	bus_dmamem_free(sc->sc_dmatag, p->segs, p->nsegs);
556 	return (error);
557 }
558 
559 int
560 sv_freemem(sc, p)
561 	struct sv_softc *sc;
562 	struct sv_dma *p;
563 {
564 	bus_dmamap_unload(sc->sc_dmatag, p->map);
565 	bus_dmamap_destroy(sc->sc_dmatag, p->map);
566 	bus_dmamem_unmap(sc->sc_dmatag, p->addr, p->size);
567 	bus_dmamem_free(sc->sc_dmatag, p->segs, p->nsegs);
568 	return (0);
569 }
570 
571 int
572 sv_open(addr, flags)
573 	void *addr;
574 	int flags;
575 {
576 	struct sv_softc *sc = addr;
577 
578 	DPRINTF(("sv_open\n"));
579 	if (!sc->sc_dmaset)
580 		return (ENXIO);
581 	sc->sc_pintr = 0;
582 	sc->sc_rintr = 0;
583 
584 	return (0);
585 }
586 
587 /*
588  * Close function is called at splaudio().
589  */
590 void
591 sv_close(addr)
592 	void *addr;
593 {
594 	struct sv_softc *sc = addr;
595 
596 	DPRINTF(("sv_close\n"));
597 	sv_halt_output(sc);
598 	sv_halt_input(sc);
599 
600 	sc->sc_pintr = 0;
601 	sc->sc_rintr = 0;
602 }
603 
604 int
605 sv_query_encoding(addr, fp)
606 	void *addr;
607 	struct audio_encoding *fp;
608 {
609 	switch (fp->index) {
610 	case 0:
611 		strcpy(fp->name, AudioEulinear);
612 		fp->encoding = AUDIO_ENCODING_ULINEAR;
613 		fp->precision = 8;
614 		fp->flags = 0;
615 		return (0);
616 	case 1:
617 		strcpy(fp->name, AudioEmulaw);
618 		fp->encoding = AUDIO_ENCODING_ULAW;
619 		fp->precision = 8;
620 		fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
621 		return (0);
622 	case 2:
623 		strcpy(fp->name, AudioEalaw);
624 		fp->encoding = AUDIO_ENCODING_ALAW;
625 		fp->precision = 8;
626 		fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
627 		return (0);
628 	case 3:
629 		strcpy(fp->name, AudioEslinear);
630 		fp->encoding = AUDIO_ENCODING_SLINEAR;
631 		fp->precision = 8;
632 		fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
633 		return (0);
634 	case 4:
635 		strcpy(fp->name, AudioEslinear_le);
636 		fp->encoding = AUDIO_ENCODING_SLINEAR_LE;
637 		fp->precision = 16;
638 		fp->flags = 0;
639 		return (0);
640 	case 5:
641 		strcpy(fp->name, AudioEulinear_le);
642 		fp->encoding = AUDIO_ENCODING_ULINEAR_LE;
643 		fp->precision = 16;
644 		fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
645 		return (0);
646 	case 6:
647 		strcpy(fp->name, AudioEslinear_be);
648 		fp->encoding = AUDIO_ENCODING_SLINEAR_BE;
649 		fp->precision = 16;
650 		fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
651 		return (0);
652 	case 7:
653 		strcpy(fp->name, AudioEulinear_be);
654 		fp->encoding = AUDIO_ENCODING_ULINEAR_BE;
655 		fp->precision = 16;
656 		fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
657 		return (0);
658 	default:
659 		return (EINVAL);
660 	}
661 }
662 
663 int
664 sv_set_params(addr, setmode, usemode, play, rec)
665 	void *addr;
666 	int setmode, usemode;
667 	struct audio_params *play, *rec;
668 {
669 	struct sv_softc *sc = addr;
670 	struct audio_params *p = NULL;
671 	int mode;
672 	u_int32_t val;
673 
674 	/*
675 	 * This device only has one clock, so make the sample rates match.
676 	 */
677 	if (play->sample_rate != rec->sample_rate &&
678 	    usemode == (AUMODE_PLAY | AUMODE_RECORD)) {
679 		if (setmode == AUMODE_PLAY) {
680 			rec->sample_rate = play->sample_rate;
681 			setmode |= AUMODE_RECORD;
682 		} else if (setmode == AUMODE_RECORD) {
683 			play->sample_rate = rec->sample_rate;
684 			setmode |= AUMODE_PLAY;
685 		} else
686 			return (EINVAL);
687 	}
688 
689 	for (mode = AUMODE_RECORD; mode != -1;
690 	     mode = mode == AUMODE_RECORD ? AUMODE_PLAY : -1) {
691 		if ((setmode & mode) == 0)
692 			continue;
693 
694 		p = mode == AUMODE_PLAY ? play : rec;
695 
696 		if (p->sample_rate < 2000 || p->sample_rate > 48000 ||
697 		    (p->precision != 8 && p->precision != 16) ||
698 		    (p->channels != 1 && p->channels != 2))
699 			return (EINVAL);
700 
701 		p->factor = 1;
702 		p->sw_code = 0;
703 		switch (p->encoding) {
704 		case AUDIO_ENCODING_SLINEAR_BE:
705 			if (p->precision == 16)
706 				p->sw_code = swap_bytes;
707 			else
708 				p->sw_code = change_sign8;
709 			break;
710 		case AUDIO_ENCODING_SLINEAR_LE:
711 			if (p->precision != 16)
712 				p->sw_code = change_sign8;
713 			break;
714 		case AUDIO_ENCODING_ULINEAR_BE:
715 			if (p->precision == 16) {
716 				if (mode == AUMODE_PLAY)
717 					p->sw_code = swap_bytes_change_sign16_le;
718 				else
719 					p->sw_code = change_sign16_swap_bytes_le;
720 			}
721 			break;
722 		case AUDIO_ENCODING_ULINEAR_LE:
723 			if (p->precision == 16)
724 				p->sw_code = change_sign16_le;
725 			break;
726 		case AUDIO_ENCODING_ULAW:
727 			if (mode == AUMODE_PLAY) {
728 				p->factor = 2;
729 				p->sw_code = mulaw_to_slinear16_le;
730 			} else
731 				p->sw_code = ulinear8_to_mulaw;
732 			break;
733 		case AUDIO_ENCODING_ALAW:
734 			if (mode == AUMODE_PLAY) {
735 				p->factor = 2;
736 				p->sw_code = alaw_to_slinear16_le;
737 			} else
738 				p->sw_code = ulinear8_to_alaw;
739 			break;
740 		default:
741 			return (EINVAL);
742 		}
743 	}
744 
745 	val = p->sample_rate * 65536 / 48000;
746 	/*
747 	 * If the sample rate is exactly 48KHz, the fraction would overflow the
748 	 * register, so we have to bias it.  This causes a little clock drift.
749 	 * The drift is below normal crystal tolerance (.0001%), so although
750 	 * this seems a little silly, we can pretty much ignore it.
751 	 * (I tested the output speed with values of 1-20, just to be sure this
752 	 * register isn't *supposed* to have a bias.  It isn't.)
753 	 * - mycroft
754 	 */
755 	if (val > 65535)
756 		val = 65535;
757 
758 	sv_write_indirect(sc, SV_PCM_SAMPLE_RATE_0, val & 0xff);
759 	sv_write_indirect(sc, SV_PCM_SAMPLE_RATE_1, val >> 8);
760 
761 #define F_REF 24576000
762 
763 #define ABS(x) (((x) < 0) ? (-x) : (x))
764 
765 	if (setmode & AUMODE_RECORD) {
766 		/* The ADC reference frequency (f_out) is 512 * sample rate */
767 
768 		/* f_out is dervied from the 24.576MHZ crystal by three values:
769 		   M & N & R. The equation is as follows:
770 
771 		   f_out = (m + 2) * f_ref / ((n + 2) * (2 ^ a))
772 
773 		   with the constraint that:
774 
775 		   80 MhZ < (m + 2) / (n + 2) * f_ref <= 150Mhz
776 		   and n, m >= 1
777 		*/
778 
779 		int  goal_f_out = 512 * rec->sample_rate;
780 		int  a, n, m, best_n = 0, best_m = 0, best_error = 10000000;
781 		int  pll_sample;
782 		int  error;
783 
784 		for (a = 0; a < 8; a++) {
785 			if ((goal_f_out * (1 << a)) >= 80000000)
786 				break;
787 		}
788 
789 		/* a != 8 because sample_rate >= 2000 */
790 
791 		for (n = 33; n > 2; n--) {
792 			m = (goal_f_out * n * (1 << a)) / F_REF;
793 			if ((m > 257) || (m < 3))
794 				continue;
795 
796 			pll_sample = (m * F_REF) / (n * (1 << a));
797 			pll_sample /= 512;
798 
799 			/* Threshold might be good here */
800 			error = pll_sample - rec->sample_rate;
801 			error = ABS(error);
802 
803 			if (error < best_error) {
804 				best_error = error;
805 				best_n = n;
806 				best_m = m;
807 				if (error == 0) break;
808 			}
809 		}
810 
811 		best_n -= 2;
812 		best_m -= 2;
813 
814 		sv_write_indirect(sc, SV_ADC_PLL_M, best_m);
815 		sv_write_indirect(sc, SV_ADC_PLL_N,
816 				  best_n | (a << SV_PLL_R_SHIFT));
817 	}
818 
819 	return (0);
820 }
821 
822 int
823 sv_round_blocksize(addr, blk)
824 	void *addr;
825 	int blk;
826 {
827 	return (blk & -32);	/* keep good alignment */
828 }
829 
830 int
831 sv_trigger_output(addr, start, end, blksize, intr, arg, param)
832 	void *addr;
833 	void *start, *end;
834 	int blksize;
835 	void (*intr) __P((void *));
836 	void *arg;
837 	struct audio_params *param;
838 {
839 	struct sv_softc *sc = addr;
840 	struct sv_dma *p;
841 	u_int8_t mode;
842 	int dma_count;
843 
844 	DPRINTFN(1, ("sv_trigger_output: sc=%p start=%p end=%p blksize=%d intr=%p(%p)\n",
845 	    addr, start, end, blksize, intr, arg));
846 	sc->sc_pintr = intr;
847 	sc->sc_parg = arg;
848 
849 	mode = sv_read_indirect(sc, SV_DMA_DATA_FORMAT);
850 	mode &= ~(SV_DMAA_FORMAT16 | SV_DMAA_STEREO);
851 	if (param->precision * param->factor == 16)
852 		mode |= SV_DMAA_FORMAT16;
853 	if (param->channels == 2)
854 		mode |= SV_DMAA_STEREO;
855 	sv_write_indirect(sc, SV_DMA_DATA_FORMAT, mode);
856 
857 	for (p = sc->sc_dmas; p && KERNADDR(p) != start; p = p->next)
858 		;
859 	if (!p) {
860 		printf("sv_trigger_output: bad addr %p\n", start);
861 		return (EINVAL);
862 	}
863 
864 	dma_count = ((char *)end - (char *)start) - 1;
865 	DPRINTF(("sv_trigger_output: dma start loop input addr=%x cc=%d\n",
866 	    (int)DMAADDR(p), dma_count));
867 
868 	bus_space_write_4(sc->sc_iot, sc->sc_dmaa_ioh, SV_DMA_ADDR0,
869 			  DMAADDR(p));
870 	bus_space_write_4(sc->sc_iot, sc->sc_dmaa_ioh, SV_DMA_COUNT0,
871 			  dma_count);
872 	bus_space_write_1(sc->sc_iot, sc->sc_dmaa_ioh, SV_DMA_MODE,
873 			  DMA37MD_READ | DMA37MD_LOOP);
874 
875 	DPRINTF(("sv_trigger_output: current addr=%x\n",
876 	    bus_space_read_4(sc->sc_iot, sc->sc_dmaa_ioh, SV_DMA_ADDR0)));
877 
878 	dma_count = blksize - 1;
879 
880 	sv_write_indirect(sc, SV_DMAA_COUNT1, dma_count >> 8);
881 	sv_write_indirect(sc, SV_DMAA_COUNT0, dma_count & 0xFF);
882 
883 	mode = sv_read_indirect(sc, SV_PLAY_RECORD_ENABLE);
884 	sv_write_indirect(sc, SV_PLAY_RECORD_ENABLE, mode | SV_PLAY_ENABLE);
885 
886 	return (0);
887 }
888 
889 int
890 sv_trigger_input(addr, start, end, blksize, intr, arg, param)
891 	void *addr;
892 	void *start, *end;
893 	int blksize;
894 	void (*intr) __P((void *));
895 	void *arg;
896 	struct audio_params *param;
897 {
898 	struct sv_softc *sc = addr;
899 	struct sv_dma *p;
900 	u_int8_t mode;
901 	int dma_count;
902 
903 	DPRINTFN(1, ("sv_trigger_input: sc=%p start=%p end=%p blksize=%d intr=%p(%p)\n",
904 	    addr, start, end, blksize, intr, arg));
905 	sc->sc_rintr = intr;
906 	sc->sc_rarg = arg;
907 
908 	mode = sv_read_indirect(sc, SV_DMA_DATA_FORMAT);
909 	mode &= ~(SV_DMAC_FORMAT16 | SV_DMAC_STEREO);
910 	if (param->precision * param->factor == 16)
911 		mode |= SV_DMAC_FORMAT16;
912 	if (param->channels == 2)
913 		mode |= SV_DMAC_STEREO;
914 	sv_write_indirect(sc, SV_DMA_DATA_FORMAT, mode);
915 
916 	for (p = sc->sc_dmas; p && KERNADDR(p) != start; p = p->next)
917 		;
918 	if (!p) {
919 		printf("sv_trigger_input: bad addr %p\n", start);
920 		return (EINVAL);
921 	}
922 
923 	dma_count = (((char *)end - (char *)start) >> 1) - 1;
924 	DPRINTF(("sv_trigger_input: dma start loop input addr=%x cc=%d\n",
925 	    (int)DMAADDR(p), dma_count));
926 
927 	bus_space_write_4(sc->sc_iot, sc->sc_dmac_ioh, SV_DMA_ADDR0,
928 			  DMAADDR(p));
929 	bus_space_write_4(sc->sc_iot, sc->sc_dmac_ioh, SV_DMA_COUNT0,
930 			  dma_count);
931 	bus_space_write_1(sc->sc_iot, sc->sc_dmac_ioh, SV_DMA_MODE,
932 			  DMA37MD_WRITE | DMA37MD_LOOP);
933 
934 	DPRINTF(("sv_trigger_input: current addr=%x\n",
935 	    bus_space_read_4(sc->sc_iot, sc->sc_dmac_ioh, SV_DMA_ADDR0)));
936 
937 	dma_count = (blksize >> 1) - 1;
938 
939 	sv_write_indirect(sc, SV_DMAC_COUNT1, dma_count >> 8);
940 	sv_write_indirect(sc, SV_DMAC_COUNT0, dma_count & 0xFF);
941 
942 	mode = sv_read_indirect(sc, SV_PLAY_RECORD_ENABLE);
943 	sv_write_indirect(sc, SV_PLAY_RECORD_ENABLE, mode | SV_RECORD_ENABLE);
944 
945 	return (0);
946 }
947 
948 int
949 sv_halt_output(addr)
950 	void *addr;
951 {
952 	struct sv_softc *sc = addr;
953 	u_int8_t mode;
954 
955 	DPRINTF(("sv: sv_halt_output\n"));
956 	mode = sv_read_indirect(sc, SV_PLAY_RECORD_ENABLE);
957 	sv_write_indirect(sc, SV_PLAY_RECORD_ENABLE, mode & ~SV_PLAY_ENABLE);
958 
959 	return (0);
960 }
961 
962 int
963 sv_halt_input(addr)
964 	void *addr;
965 {
966 	struct sv_softc *sc = addr;
967 	u_int8_t mode;
968 
969 	DPRINTF(("sv: sv_halt_input\n"));
970 	mode = sv_read_indirect(sc, SV_PLAY_RECORD_ENABLE);
971 	sv_write_indirect(sc, SV_PLAY_RECORD_ENABLE, mode & ~SV_RECORD_ENABLE);
972 
973 	return (0);
974 }
975 
976 int
977 sv_getdev(addr, retp)
978 	void *addr;
979 	struct audio_device *retp;
980 {
981 	*retp = sv_device;
982 	return (0);
983 }
984 
985 
986 /*
987  * Mixer related code is here
988  *
989  */
990 
991 #define SV_INPUT_CLASS 0
992 #define SV_OUTPUT_CLASS 1
993 #define SV_RECORD_CLASS 2
994 
995 #define SV_LAST_CLASS 2
996 
997 static const char *mixer_classes[] =
998 	{ AudioCinputs, AudioCoutputs, AudioCrecord };
999 
1000 static const struct {
1001 	u_int8_t   l_port;
1002 	u_int8_t   r_port;
1003 	u_int8_t   mask;
1004 	u_int8_t   class;
1005 	const char *audio;
1006 } ports[] = {
1007   { SV_LEFT_AUX1_INPUT_CONTROL, SV_RIGHT_AUX1_INPUT_CONTROL, SV_AUX1_MASK,
1008     SV_INPUT_CLASS, "aux1" },
1009   { SV_LEFT_CD_INPUT_CONTROL, SV_RIGHT_CD_INPUT_CONTROL, SV_CD_MASK,
1010     SV_INPUT_CLASS, AudioNcd },
1011   { SV_LEFT_LINE_IN_INPUT_CONTROL, SV_RIGHT_LINE_IN_INPUT_CONTROL, SV_LINE_IN_MASK,
1012     SV_INPUT_CLASS, AudioNline },
1013   { SV_MIC_INPUT_CONTROL, 0, SV_MIC_MASK, SV_INPUT_CLASS, AudioNmicrophone },
1014   { SV_LEFT_SYNTH_INPUT_CONTROL, SV_RIGHT_SYNTH_INPUT_CONTROL,
1015     SV_SYNTH_MASK, SV_INPUT_CLASS, AudioNfmsynth },
1016   { SV_LEFT_AUX2_INPUT_CONTROL, SV_RIGHT_AUX2_INPUT_CONTROL, SV_AUX2_MASK,
1017     SV_INPUT_CLASS, "aux2" },
1018   { SV_LEFT_PCM_INPUT_CONTROL, SV_RIGHT_PCM_INPUT_CONTROL, SV_PCM_MASK,
1019     SV_INPUT_CLASS, AudioNdac },
1020   { SV_LEFT_MIXER_OUTPUT_CONTROL, SV_RIGHT_MIXER_OUTPUT_CONTROL,
1021     SV_MIXER_OUT_MASK, SV_OUTPUT_CLASS, AudioNmaster }
1022 };
1023 
1024 
1025 static const struct {
1026 	int idx;
1027 	const char *name;
1028 } record_sources[] = {
1029 	{ SV_REC_CD, AudioNcd },
1030 	{ SV_REC_DAC, AudioNdac },
1031 	{ SV_REC_AUX2, "aux2" },
1032 	{ SV_REC_LINE, AudioNline },
1033 	{ SV_REC_AUX1, "aux1" },
1034 	{ SV_REC_MIC, AudioNmicrophone },
1035 	{ SV_REC_MIXER, AudioNmixerout }
1036 };
1037 
1038 
1039 #define SV_DEVICES_PER_PORT 2
1040 #define SV_FIRST_MIXER (SV_LAST_CLASS + 1)
1041 #define SV_LAST_MIXER (SV_DEVICES_PER_PORT * (ARRAY_SIZE(ports)) + SV_LAST_CLASS)
1042 #define SV_RECORD_SOURCE (SV_LAST_MIXER + 1)
1043 #define SV_MIC_BOOST (SV_LAST_MIXER + 2)
1044 #define SV_RECORD_GAIN (SV_LAST_MIXER + 3)
1045 #define SV_SRS_MODE (SV_LAST_MIXER + 4)
1046 
1047 int
1048 sv_query_devinfo(addr, dip)
1049 	void *addr;
1050 	mixer_devinfo_t *dip;
1051 {
1052 	int i;
1053 
1054 	/* It's a class */
1055 	if (dip->index <= SV_LAST_CLASS) {
1056 		dip->type = AUDIO_MIXER_CLASS;
1057 		dip->mixer_class = dip->index;
1058 		dip->next = dip->prev = AUDIO_MIXER_LAST;
1059 		strcpy(dip->label.name,
1060 		       mixer_classes[dip->index]);
1061 		return (0);
1062 	}
1063 
1064 	if (dip->index >= SV_FIRST_MIXER &&
1065 	    dip->index <= SV_LAST_MIXER) {
1066 		int off = dip->index - SV_FIRST_MIXER;
1067 		int mute = (off % SV_DEVICES_PER_PORT);
1068 		int idx = off / SV_DEVICES_PER_PORT;
1069 
1070 		dip->mixer_class = ports[idx].class;
1071 		strcpy(dip->label.name, ports[idx].audio);
1072 
1073 		if (!mute) {
1074 			dip->type = AUDIO_MIXER_VALUE;
1075 			dip->prev = AUDIO_MIXER_LAST;
1076 			dip->next = dip->index + 1;
1077 
1078 			if (ports[idx].r_port != 0)
1079 				dip->un.v.num_channels = 2;
1080 			else
1081 				dip->un.v.num_channels = 1;
1082 
1083 			strcpy(dip->un.v.units.name, AudioNvolume);
1084 		} else {
1085 			dip->type = AUDIO_MIXER_ENUM;
1086 			dip->prev = dip->index - 1;
1087 			dip->next = AUDIO_MIXER_LAST;
1088 
1089 			strcpy(dip->label.name, AudioNmute);
1090 			dip->un.e.num_mem = 2;
1091 			strcpy(dip->un.e.member[0].label.name, AudioNoff);
1092 			dip->un.e.member[0].ord = 0;
1093 			strcpy(dip->un.e.member[1].label.name, AudioNon);
1094 			dip->un.e.member[1].ord = 1;
1095 		}
1096 
1097 		return (0);
1098 	}
1099 
1100 	switch (dip->index) {
1101 	case SV_RECORD_SOURCE:
1102 		dip->mixer_class = SV_RECORD_CLASS;
1103 		dip->prev = AUDIO_MIXER_LAST;
1104 		dip->next = SV_RECORD_GAIN;
1105 		strcpy(dip->label.name, AudioNsource);
1106 		dip->type = AUDIO_MIXER_ENUM;
1107 
1108 		dip->un.e.num_mem = ARRAY_SIZE(record_sources);
1109 		for (i = 0; i < ARRAY_SIZE(record_sources); i++) {
1110 			strcpy(dip->un.e.member[i].label.name,
1111 			       record_sources[i].name);
1112 			dip->un.e.member[i].ord = record_sources[i].idx;
1113 		}
1114 		return (0);
1115 
1116 	case SV_RECORD_GAIN:
1117 		dip->mixer_class = SV_RECORD_CLASS;
1118 		dip->prev = SV_RECORD_SOURCE;
1119 		dip->next = AUDIO_MIXER_LAST;
1120 		strcpy(dip->label.name, "gain");
1121 		dip->type = AUDIO_MIXER_VALUE;
1122 		dip->un.v.num_channels = 1;
1123 		strcpy(dip->un.v.units.name, AudioNvolume);
1124 		return (0);
1125 
1126 	case SV_MIC_BOOST:
1127 		dip->mixer_class = SV_RECORD_CLASS;
1128 		dip->prev = AUDIO_MIXER_LAST;
1129 		dip->next = AUDIO_MIXER_LAST;
1130 		strcpy(dip->label.name, "micboost");
1131 		goto on_off;
1132 
1133 	case SV_SRS_MODE:
1134 		dip->mixer_class = SV_OUTPUT_CLASS;
1135 		dip->prev = dip->next = AUDIO_MIXER_LAST;
1136 		strcpy(dip->label.name, AudioNspatial);
1137 
1138 	on_off:
1139 		dip->type = AUDIO_MIXER_ENUM;
1140 		dip->un.e.num_mem = 2;
1141 		strcpy(dip->un.e.member[0].label.name, AudioNoff);
1142 		dip->un.e.member[0].ord = 0;
1143 		strcpy(dip->un.e.member[1].label.name, AudioNon);
1144 		dip->un.e.member[1].ord = 1;
1145 		return (0);
1146 	}
1147 
1148 	return (ENXIO);
1149 }
1150 
1151 int
1152 sv_mixer_set_port(addr, cp)
1153 	void *addr;
1154 	mixer_ctrl_t *cp;
1155 {
1156 	struct sv_softc *sc = addr;
1157 	u_int8_t reg;
1158 	int idx;
1159 
1160 	if (cp->dev >= SV_FIRST_MIXER &&
1161 	    cp->dev <= SV_LAST_MIXER) {
1162 		int off = cp->dev - SV_FIRST_MIXER;
1163 		int mute = (off % SV_DEVICES_PER_PORT);
1164 		idx = off / SV_DEVICES_PER_PORT;
1165 
1166 		if (mute) {
1167 			if (cp->type != AUDIO_MIXER_ENUM)
1168 				return (EINVAL);
1169 
1170 			reg = sv_read_indirect(sc, ports[idx].l_port);
1171 			if (cp->un.ord)
1172 				reg |= SV_MUTE_BIT;
1173 			else
1174 				reg &= ~SV_MUTE_BIT;
1175 			sv_write_indirect(sc, ports[idx].l_port, reg);
1176 
1177 			if (ports[idx].r_port) {
1178 				reg = sv_read_indirect(sc, ports[idx].r_port);
1179 				if (cp->un.ord)
1180 					reg |= SV_MUTE_BIT;
1181 				else
1182 					reg &= ~SV_MUTE_BIT;
1183 				sv_write_indirect(sc, ports[idx].r_port, reg);
1184 			}
1185 		} else {
1186 			int  lval, rval;
1187 
1188 			if (cp->type != AUDIO_MIXER_VALUE)
1189 				return (EINVAL);
1190 
1191 			if (cp->un.value.num_channels != 1 &&
1192 			    cp->un.value.num_channels != 2)
1193 				return (EINVAL);
1194 
1195 			if (ports[idx].r_port == 0) {
1196 				if (cp->un.value.num_channels != 1)
1197 					return (EINVAL);
1198 				lval = cp->un.value.level[AUDIO_MIXER_LEVEL_MONO];
1199 				rval = 0; /* shut up GCC */
1200 			} else {
1201 				if (cp->un.value.num_channels != 2)
1202 					return (EINVAL);
1203 
1204 				lval = cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT];
1205 				rval = cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT];
1206       }
1207 
1208 
1209 			reg = sv_read_indirect(sc, ports[idx].l_port);
1210 			reg &= ~(ports[idx].mask);
1211 			lval = (AUDIO_MAX_GAIN - lval) * ports[idx].mask /
1212 				AUDIO_MAX_GAIN;
1213 			reg |= lval;
1214 			sv_write_indirect(sc, ports[idx].l_port, reg);
1215 
1216 			if (ports[idx].r_port != 0) {
1217 				reg = sv_read_indirect(sc, ports[idx].r_port);
1218 				reg &= ~(ports[idx].mask);
1219 
1220 				rval = (AUDIO_MAX_GAIN - rval) * ports[idx].mask /
1221 					AUDIO_MAX_GAIN;
1222 				reg |= rval;
1223 
1224 				sv_write_indirect(sc, ports[idx].r_port, reg);
1225 			}
1226 
1227 			sv_read_indirect(sc, ports[idx].l_port);
1228 		}
1229 
1230 		return (0);
1231 	}
1232 
1233 
1234 	switch (cp->dev) {
1235 	case SV_RECORD_SOURCE:
1236 		if (cp->type != AUDIO_MIXER_ENUM)
1237 			return (EINVAL);
1238 
1239 		for (idx = 0; idx < ARRAY_SIZE(record_sources); idx++) {
1240 			if (record_sources[idx].idx == cp->un.ord)
1241 				goto found;
1242 		}
1243 
1244 		return (EINVAL);
1245 
1246 	found:
1247 		reg = sv_read_indirect(sc, SV_LEFT_ADC_INPUT_CONTROL);
1248 		reg &= ~SV_REC_SOURCE_MASK;
1249 		reg |= (((cp->un.ord) << SV_REC_SOURCE_SHIFT) & SV_REC_SOURCE_MASK);
1250 		sv_write_indirect(sc, SV_LEFT_ADC_INPUT_CONTROL, reg);
1251 
1252 		reg = sv_read_indirect(sc, SV_RIGHT_ADC_INPUT_CONTROL);
1253 		reg &= ~SV_REC_SOURCE_MASK;
1254 		reg |= (((cp->un.ord) << SV_REC_SOURCE_SHIFT) & SV_REC_SOURCE_MASK);
1255 		sv_write_indirect(sc, SV_RIGHT_ADC_INPUT_CONTROL, reg);
1256 		return (0);
1257 
1258 	case SV_RECORD_GAIN:
1259 	{
1260 		int val;
1261 
1262 		if (cp->type != AUDIO_MIXER_VALUE)
1263 			return (EINVAL);
1264 
1265 		if (cp->un.value.num_channels != 1)
1266 			return (EINVAL);
1267 
1268 		val = (cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] * SV_REC_GAIN_MASK)
1269 			/ AUDIO_MAX_GAIN;
1270 
1271 		reg = sv_read_indirect(sc, SV_LEFT_ADC_INPUT_CONTROL);
1272 		reg &= ~SV_REC_GAIN_MASK;
1273 		reg |= val;
1274 		sv_write_indirect(sc, SV_LEFT_ADC_INPUT_CONTROL, reg);
1275 
1276 		reg = sv_read_indirect(sc, SV_RIGHT_ADC_INPUT_CONTROL);
1277 		reg &= ~SV_REC_GAIN_MASK;
1278 		reg |= val;
1279 		sv_write_indirect(sc, SV_RIGHT_ADC_INPUT_CONTROL, reg);
1280 	}
1281 	return (0);
1282 
1283 	case SV_MIC_BOOST:
1284 		if (cp->type != AUDIO_MIXER_ENUM)
1285 			return (EINVAL);
1286 
1287 		reg = sv_read_indirect(sc, SV_LEFT_ADC_INPUT_CONTROL);
1288 		if (cp->un.ord) {
1289 			reg |= SV_MIC_BOOST_BIT;
1290 		} else {
1291 			reg &= ~SV_MIC_BOOST_BIT;
1292 		}
1293 
1294 		sv_write_indirect(sc, SV_LEFT_ADC_INPUT_CONTROL, reg);
1295 		return (0);
1296 
1297 	case SV_SRS_MODE:
1298 		if (cp->type != AUDIO_MIXER_ENUM)
1299 			return (EINVAL);
1300 
1301 		reg = sv_read_indirect(sc, SV_SRS_SPACE_CONTROL);
1302 		if (cp->un.ord) {
1303 			reg &= ~SV_SRS_SPACE_ONOFF;
1304 		} else {
1305 			reg |= SV_SRS_SPACE_ONOFF;
1306 		}
1307 
1308 		sv_write_indirect(sc, SV_SRS_SPACE_CONTROL, reg);
1309 		return (0);
1310 	}
1311 
1312 	return (EINVAL);
1313 }
1314 
1315 int
1316 sv_mixer_get_port(addr, cp)
1317 	void *addr;
1318 	mixer_ctrl_t *cp;
1319 {
1320 	struct sv_softc *sc = addr;
1321 	int val;
1322 	u_int8_t reg;
1323 
1324 	if (cp->dev >= SV_FIRST_MIXER &&
1325 	    cp->dev <= SV_LAST_MIXER) {
1326 		int off = cp->dev - SV_FIRST_MIXER;
1327 		int mute = (off % 2);
1328 		int idx = off / 2;
1329 
1330 		if (mute) {
1331 			if (cp->type != AUDIO_MIXER_ENUM)
1332 				return (EINVAL);
1333 
1334 			reg = sv_read_indirect(sc, ports[idx].l_port);
1335 			cp->un.ord = ((reg & SV_MUTE_BIT) ? 1 : 0);
1336 		} else {
1337 			if (cp->type != AUDIO_MIXER_VALUE)
1338 				return (EINVAL);
1339 
1340 			if (cp->un.value.num_channels != 1 &&
1341 			    cp->un.value.num_channels != 2)
1342 				return (EINVAL);
1343 
1344 			if ((ports[idx].r_port == 0 &&
1345 			     cp->un.value.num_channels != 1) ||
1346 			    (ports[idx].r_port != 0 &&
1347 			     cp->un.value.num_channels != 2))
1348 				return (EINVAL);
1349 
1350 			reg = sv_read_indirect(sc, ports[idx].l_port);
1351 			reg &= ports[idx].mask;
1352 
1353 			val = AUDIO_MAX_GAIN - ((reg * AUDIO_MAX_GAIN) / ports[idx].mask);
1354 
1355 			if (ports[idx].r_port != 0) {
1356 				cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT] = val;
1357 
1358 				reg = sv_read_indirect(sc, ports[idx].r_port);
1359 				reg &= ports[idx].mask;
1360 
1361 				val = AUDIO_MAX_GAIN - ((reg * AUDIO_MAX_GAIN) / ports[idx].mask);
1362 				cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] = val;
1363 			} else
1364 				cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] = val;
1365 		}
1366 
1367 		return (0);
1368   }
1369 
1370 	switch (cp->dev) {
1371 	case SV_RECORD_SOURCE:
1372 		if (cp->type != AUDIO_MIXER_ENUM)
1373 			return (EINVAL);
1374 
1375 		reg = sv_read_indirect(sc, SV_LEFT_ADC_INPUT_CONTROL);
1376 		cp->un.ord = ((reg & SV_REC_SOURCE_MASK) >> SV_REC_SOURCE_SHIFT);
1377 
1378 		return (0);
1379 
1380 	case SV_RECORD_GAIN:
1381 		if (cp->type != AUDIO_MIXER_VALUE)
1382 			return (EINVAL);
1383 		if (cp->un.value.num_channels != 1)
1384 			return (EINVAL);
1385 
1386 		reg = sv_read_indirect(sc, SV_LEFT_ADC_INPUT_CONTROL) & SV_REC_GAIN_MASK;
1387 		cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] =
1388 			(((unsigned int)reg) * AUDIO_MAX_GAIN) / SV_REC_GAIN_MASK;
1389 
1390 		return (0);
1391 
1392 	case SV_MIC_BOOST:
1393 		if (cp->type != AUDIO_MIXER_ENUM)
1394 			return (EINVAL);
1395 		reg = sv_read_indirect(sc, SV_LEFT_ADC_INPUT_CONTROL);
1396 		cp->un.ord = ((reg & SV_MIC_BOOST_BIT) ? 1 : 0);
1397 		return (0);
1398 
1399 
1400 	case SV_SRS_MODE:
1401 		if (cp->type != AUDIO_MIXER_ENUM)
1402 			return (EINVAL);
1403 		reg = sv_read_indirect(sc, SV_SRS_SPACE_CONTROL);
1404 		cp->un.ord = ((reg & SV_SRS_SPACE_ONOFF) ? 0 : 1);
1405 		return (0);
1406 	}
1407 
1408 	return (EINVAL);
1409 }
1410 
1411 
1412 static void
1413 sv_init_mixer(sc)
1414 	struct sv_softc *sc;
1415 {
1416 	mixer_ctrl_t cp;
1417 	int i;
1418 
1419 	cp.type = AUDIO_MIXER_ENUM;
1420 	cp.dev = SV_SRS_MODE;
1421 	cp.un.ord = 0;
1422 
1423 	sv_mixer_set_port(sc, &cp);
1424 
1425 	for (i = 0; i < ARRAY_SIZE(ports); i++) {
1426 		if (ports[i].audio == AudioNdac) {
1427 			cp.type = AUDIO_MIXER_ENUM;
1428 			cp.dev = SV_FIRST_MIXER + i * SV_DEVICES_PER_PORT + 1;
1429 			cp.un.ord = 0;
1430 			sv_mixer_set_port(sc, &cp);
1431 			break;
1432 		}
1433 	}
1434 }
1435 
1436 void *
1437 sv_malloc(addr, direction, size, pool, flags)
1438 	void *addr;
1439 	int direction;
1440 	size_t size;
1441 	int pool, flags;
1442 {
1443 	struct sv_softc *sc = addr;
1444 	struct sv_dma *p;
1445 	int error;
1446 
1447 	p = malloc(sizeof(*p), pool, flags);
1448 	if (!p)
1449 		return (0);
1450 	error = sv_allocmem(sc, size, 16, direction, p);
1451 	if (error) {
1452 		free(p, pool);
1453 		return (0);
1454 	}
1455 	p->next = sc->sc_dmas;
1456 	sc->sc_dmas = p;
1457 	return (KERNADDR(p));
1458 }
1459 
1460 void
1461 sv_free(addr, ptr, pool)
1462 	void *addr;
1463 	void *ptr;
1464 	int pool;
1465 {
1466 	struct sv_softc *sc = addr;
1467 	struct sv_dma **pp, *p;
1468 
1469 	for (pp = &sc->sc_dmas; (p = *pp) != NULL; pp = &p->next) {
1470 		if (KERNADDR(p) == ptr) {
1471 			sv_freemem(sc, p);
1472 			*pp = p->next;
1473 			free(p, pool);
1474 			return;
1475 		}
1476 	}
1477 }
1478 
1479 size_t
1480 sv_round_buffersize(addr, direction, size)
1481 	void *addr;
1482 	int direction;
1483 	size_t size;
1484 {
1485 	return (size);
1486 }
1487 
1488 paddr_t
1489 sv_mappage(addr, mem, off, prot)
1490 	void *addr;
1491 	void *mem;
1492 	off_t off;
1493 	int prot;
1494 {
1495 	struct sv_softc *sc = addr;
1496 	struct sv_dma *p;
1497 
1498 	if (off < 0)
1499 		return (-1);
1500 	for (p = sc->sc_dmas; p && KERNADDR(p) != mem; p = p->next)
1501 		;
1502 	if (!p)
1503 		return (-1);
1504 	return (bus_dmamem_mmap(sc->sc_dmatag, p->segs, p->nsegs,
1505 				off, prot, BUS_DMA_WAITOK));
1506 }
1507 
1508 int
1509 sv_get_props(addr)
1510 	void *addr;
1511 {
1512 	return (AUDIO_PROP_MMAP | AUDIO_PROP_INDEPENDENT | AUDIO_PROP_FULLDUPLEX);
1513 }
1514