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