This source file includes following definitions.
- auvia_match
- auvia_attach
- auvia_attach_codec
- auvia_reset_codec
- auvia_waitready_codec
- auvia_waitvalid_codec
- auvia_write_codec
- auvia_read_codec
- auvia_open
- auvia_close
- auvia_query_encoding
- auvia_set_params
- auvia_round_blocksize
- auvia_halt_output
- auvia_halt_input
- auvia_getdev
- auvia_set_port
- auvia_get_port
- auvia_query_devinfo
- auvia_malloc
- auvia_free
- auvia_mappage
- auvia_get_props
- auvia_build_dma_ops
- auvia_trigger_output
- auvia_trigger_input
- auvia_intr
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
40
41
42
43
44
45
46
47
48 #include <sys/param.h>
49 #include <sys/systm.h>
50 #include <sys/malloc.h>
51 #include <sys/device.h>
52 #include <sys/audioio.h>
53
54 #include <dev/pci/pcidevs.h>
55 #include <dev/pci/pcivar.h>
56
57 #include <dev/audio_if.h>
58 #include <dev/mulaw.h>
59 #include <dev/auconv.h>
60
61 #include <dev/ic/ac97.h>
62
63 #include <dev/pci/auviavar.h>
64
65 struct auvia_dma {
66 struct auvia_dma *next;
67 caddr_t addr;
68 size_t size;
69 bus_dmamap_t map;
70 bus_dma_segment_t seg;
71 };
72
73 struct auvia_dma_op {
74 u_int32_t ptr;
75 u_int32_t flags;
76 #define AUVIA_DMAOP_EOL 0x80000000
77 #define AUVIA_DMAOP_FLAG 0x40000000
78 #define AUVIA_DMAOP_STOP 0x20000000
79 #define AUVIA_DMAOP_COUNT(x) ((x)&0x00FFFFFF)
80 };
81
82
83 #define AUVIA_FIXED_RATE 44100
84
85 int auvia_match(struct device *, void *, void *);
86 void auvia_attach(struct device *, struct device *, void *);
87 int auvia_open(void *, int);
88 void auvia_close(void *);
89 int auvia_query_encoding(void *addr, struct audio_encoding *fp);
90 int auvia_set_params(void *, int, int, struct audio_params *,
91 struct audio_params *);
92 int auvia_round_blocksize(void *, int);
93 int auvia_halt_output(void *);
94 int auvia_halt_input(void *);
95 int auvia_getdev(void *, struct audio_device *);
96 int auvia_set_port(void *, mixer_ctrl_t *);
97 int auvia_get_port(void *, mixer_ctrl_t *);
98 int auvia_query_devinfo(void *, mixer_devinfo_t *);
99 void * auvia_malloc(void *, int, size_t, int, int);
100 void auvia_free(void *, void *, int);
101 paddr_t auvia_mappage(void *, void *, off_t, int);
102 int auvia_get_props(void *);
103 int auvia_build_dma_ops(struct auvia_softc *, struct auvia_softc_chan *,
104 struct auvia_dma *, void *, void *, int);
105 int auvia_trigger_output(void *, void *, void *, int, void (*)(void *),
106 void *, struct audio_params *);
107 int auvia_trigger_input(void *, void *, void *, int, void (*)(void *),
108 void *, struct audio_params *);
109
110 int auvia_intr(void *);
111
112 struct cfdriver auvia_cd = {
113 NULL, "auvia", DV_DULL
114 };
115
116 struct cfattach auvia_ca = {
117 sizeof (struct auvia_softc), auvia_match, auvia_attach
118 };
119
120 #define AUVIA_PCICONF_JUNK 0x40
121 #define AUVIA_PCICONF_ENABLES 0x00FF0000
122 #define AUVIA_PCICONF_ACLINKENAB 0x00008000
123 #define AUVIA_PCICONF_ACNOTRST 0x00004000
124 #define AUVIA_PCICONF_ACSYNC 0x00002000
125 #define AUVIA_PCICONF_ACVSR 0x00000800
126 #define AUVIA_PCICONF_ACSGD 0x00000400
127 #define AUVIA_PCICONF_ACFM 0x00000200
128 #define AUVIA_PCICONF_ACSB 0x00000100
129 #define AUVIA_PCICONF_PRIVALID 0x00000001
130
131 #define AUVIA_PLAY_BASE 0x00
132 #define AUVIA_RECORD_BASE 0x10
133
134 #define AUVIA_RP_STAT 0x00
135 #define AUVIA_RPSTAT_INTR 0x03
136 #define AUVIA_RP_CONTROL 0x01
137 #define AUVIA_RPCTRL_START 0x80
138 #define AUVIA_RPCTRL_TERMINATE 0x40
139 #define AUVIA_RPCTRL_AUTOSTART 0x20
140
141 #define AUVIA_RPCTRL_STOP 0x04
142 #define AUVIA_RPCTRL_EOL 0x02
143 #define AUVIA_RPCTRL_FLAG 0x01
144 #define AUVIA_RP_MODE 0x02
145 #define AUVIA_RPMODE_INTR_FLAG 0x01
146 #define AUVIA_RPMODE_INTR_EOL 0x02
147 #define AUVIA_RPMODE_STEREO 0x10
148 #define AUVIA_RPMODE_16BIT 0x20
149 #define AUVIA_RPMODE_AUTOSTART 0x80
150 #define AUVIA_RP_DMAOPS_BASE 0x04
151
152 #define VIA8233_RP_DXS_LVOL 0x02
153 #define VIA8233_RP_DXS_RVOL 0x03
154 #define VIA8233_RP_RATEFMT 0x08
155 #define VIA8233_RATEFMT_48K 0xfffff
156 #define VIA8233_RATEFMT_STEREO 0x00100000
157 #define VIA8233_RATEFMT_16BIT 0x00200000
158
159 #define VIA_RP_DMAOPS_COUNT 0x0C
160
161 #define AUVIA_CODEC_CTL 0x80
162 #define AUVIA_CODEC_READ 0x00800000
163 #define AUVIA_CODEC_BUSY 0x01000000
164 #define AUVIA_CODEC_PRIVALID 0x02000000
165 #define AUVIA_CODEC_INDEX(x) ((x)<<16)
166
167 #define TIMEOUT 50
168
169 struct audio_hw_if auvia_hw_if = {
170 auvia_open,
171 auvia_close,
172 NULL,
173 auvia_query_encoding,
174 auvia_set_params,
175 auvia_round_blocksize,
176 NULL,
177 NULL,
178 NULL,
179 NULL,
180 NULL,
181 auvia_halt_output,
182 auvia_halt_input,
183 NULL,
184 auvia_getdev,
185 NULL,
186 auvia_set_port,
187 auvia_get_port,
188 auvia_query_devinfo,
189 auvia_malloc,
190 auvia_free,
191 NULL,
192 auvia_mappage,
193 auvia_get_props,
194 auvia_trigger_output,
195 auvia_trigger_input
196 };
197
198 int auvia_attach_codec(void *, struct ac97_codec_if *);
199 int auvia_write_codec(void *, u_int8_t, u_int16_t);
200 int auvia_read_codec(void *, u_int8_t, u_int16_t *);
201 void auvia_reset_codec(void *);
202 int auvia_waitready_codec(struct auvia_softc *sc);
203 int auvia_waitvalid_codec(struct auvia_softc *sc);
204
205 const struct pci_matchid auvia_devices[] = {
206 { PCI_VENDOR_VIATECH, PCI_PRODUCT_VIATECH_VT82C686A_AC97 },
207 { PCI_VENDOR_VIATECH, PCI_PRODUCT_VIATECH_VT8233_AC97 },
208 };
209
210 int
211 auvia_match(struct device *parent, void *match, void *aux)
212 {
213 return (pci_matchbyid((struct pci_attach_args *)aux, auvia_devices,
214 sizeof(auvia_devices)/sizeof(auvia_devices[0])));
215 }
216
217
218 void
219 auvia_attach(struct device *parent, struct device *self, void *aux)
220 {
221 struct pci_attach_args *pa = aux;
222 struct auvia_softc *sc = (struct auvia_softc *) self;
223 const char *intrstr = NULL;
224 struct mixer_ctrl ctl;
225 pci_chipset_tag_t pc = pa->pa_pc;
226 pcitag_t pt = pa->pa_tag;
227 pci_intr_handle_t ih;
228 bus_size_t iosize;
229 pcireg_t pr;
230 int r, i;
231
232 if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_VIATECH_VT8233_AC97)
233 sc->sc_flags |= AUVIA_FLAGS_VT8233;
234
235 if (pci_mapreg_map(pa, 0x10, PCI_MAPREG_TYPE_IO, 0, &sc->sc_iot,
236 &sc->sc_ioh, NULL, &iosize, 0)) {
237 printf(": can't map i/o space\n");
238 return;
239 }
240
241 sc->sc_dmat = pa->pa_dmat;
242 sc->sc_pc = pc;
243 sc->sc_pt = pt;
244
245 if (pci_intr_map(pa, &ih)) {
246 printf(": couldn't map interrupt\n");
247 bus_space_unmap(sc->sc_iot, sc->sc_ioh, iosize);
248 return;
249 }
250 intrstr = pci_intr_string(pc, ih);
251
252 sc->sc_ih = pci_intr_establish(pc, ih, IPL_AUDIO, auvia_intr, sc,
253 sc->sc_dev.dv_xname);
254 if (sc->sc_ih == NULL) {
255 printf(": couldn't establish interrupt");
256 if (intrstr != NULL)
257 printf(" at %s", intrstr);
258 printf("\n");
259 bus_space_unmap(sc->sc_iot, sc->sc_ioh, iosize);
260 return;
261 }
262
263 printf(": %s\n", intrstr);
264
265
266 pr = pci_conf_read(pc, pt, AUVIA_PCICONF_JUNK);
267
268 pr &= ~AUVIA_PCICONF_ENABLES;
269
270
271 pr |= (AUVIA_PCICONF_ACLINKENAB | AUVIA_PCICONF_ACNOTRST |
272 AUVIA_PCICONF_ACVSR | AUVIA_PCICONF_ACSGD);
273
274 pr &= ~(AUVIA_PCICONF_ACFM | AUVIA_PCICONF_ACSB);
275
276 pci_conf_write(pc, pt, AUVIA_PCICONF_JUNK, pr);
277
278 sc->host_if.arg = sc;
279 sc->host_if.attach = auvia_attach_codec;
280 sc->host_if.read = auvia_read_codec;
281 sc->host_if.write = auvia_write_codec;
282 sc->host_if.reset = auvia_reset_codec;
283
284 if ((r = ac97_attach(&sc->host_if)) != 0) {
285 printf("%s: can't attach codec (error 0x%X)\n",
286 sc->sc_dev.dv_xname, r);
287 pci_intr_disestablish(pc, sc->sc_ih);
288 bus_space_unmap(sc->sc_iot, sc->sc_ioh, iosize);
289 return;
290 }
291
292
293 for (i = 0; i < 4; i++) {
294 static struct {
295 char *class, *device;
296 } d[] = {
297 { AudioCoutputs, AudioNmaster},
298 { AudioCinputs, AudioNdac},
299 { AudioCinputs, AudioNcd},
300 { AudioCrecord, AudioNvolume},
301 };
302
303 ctl.type = AUDIO_MIXER_ENUM;
304 ctl.un.ord = 0;
305
306 ctl.dev = sc->codec_if->vtbl->get_portnum_by_name(sc->codec_if,
307 d[i].class, d[i].device, AudioNmute);
308 auvia_set_port(sc, &ctl);
309 }
310
311
312
313 ctl.type = AUDIO_MIXER_VALUE;
314 ctl.un.value.num_channels = 2;
315 ctl.un.value.level[AUDIO_MIXER_LEVEL_LEFT] = \
316 ctl.un.value.level[AUDIO_MIXER_LEVEL_RIGHT] = 199;
317
318 ctl.dev = sc->codec_if->vtbl->get_portnum_by_name(sc->codec_if,
319 AudioCoutputs, AudioNmaster, NULL);
320 auvia_set_port(sc, &ctl);
321
322 audio_attach_mi(&auvia_hw_if, sc, &sc->sc_dev);
323 }
324
325
326 int
327 auvia_attach_codec(void *addr, struct ac97_codec_if *cif)
328 {
329 struct auvia_softc *sc = addr;
330
331 sc->codec_if = cif;
332
333 return 0;
334 }
335
336
337 void
338 auvia_reset_codec(void *addr)
339 {
340 int i;
341 struct auvia_softc *sc = addr;
342 pcireg_t r;
343
344
345
346 r = pci_conf_read(sc->sc_pc, sc->sc_pt, AUVIA_PCICONF_JUNK);
347
348 r &= ~AUVIA_PCICONF_ACNOTRST;
349 pci_conf_write(sc->sc_pc, sc->sc_pt, AUVIA_PCICONF_JUNK, r);
350 delay(2);
351
352 r |= AUVIA_PCICONF_ACNOTRST;
353 pci_conf_write(sc->sc_pc, sc->sc_pt, AUVIA_PCICONF_JUNK, r);
354 delay(200);
355
356 for (i = 500000; i != 0 && !(pci_conf_read(sc->sc_pc, sc->sc_pt,
357 AUVIA_PCICONF_JUNK) & AUVIA_PCICONF_PRIVALID); i--)
358 DELAY(1);
359 if (i == 0)
360 printf("%s: codec reset timed out\n", sc->sc_dev.dv_xname);
361 }
362
363
364 int
365 auvia_waitready_codec(struct auvia_softc *sc)
366 {
367 int i;
368
369
370 for (i = 0; (i < TIMEOUT) && (bus_space_read_4(sc->sc_iot, sc->sc_ioh,
371 AUVIA_CODEC_CTL) & AUVIA_CODEC_BUSY); i++)
372 delay(1);
373
374 if (i >= TIMEOUT) {
375 printf("%s: codec busy\n", sc->sc_dev.dv_xname);
376 return 1;
377 }
378
379 return 0;
380 }
381
382
383 int
384 auvia_waitvalid_codec(struct auvia_softc *sc)
385 {
386 int i;
387
388
389 for (i = 0; (i < TIMEOUT) && !(bus_space_read_4(sc->sc_iot, sc->sc_ioh,
390 AUVIA_CODEC_CTL) & AUVIA_CODEC_PRIVALID); i++)
391 delay(1);
392
393 if (i >= TIMEOUT) {
394 printf("%s: codec invalid\n", sc->sc_dev.dv_xname);
395 return 1;
396 }
397
398 return 0;
399 }
400
401
402 int
403 auvia_write_codec(void *addr, u_int8_t reg, u_int16_t val)
404 {
405 struct auvia_softc *sc = addr;
406
407 if (auvia_waitready_codec(sc))
408 return 1;
409
410 bus_space_write_4(sc->sc_iot, sc->sc_ioh, AUVIA_CODEC_CTL,
411 AUVIA_CODEC_PRIVALID | AUVIA_CODEC_INDEX(reg) | val);
412
413 return 0;
414 }
415
416
417 int
418 auvia_read_codec(void *addr, u_int8_t reg, u_int16_t *val)
419 {
420 struct auvia_softc *sc = addr;
421
422 if (auvia_waitready_codec(sc))
423 return 1;
424
425 bus_space_write_4(sc->sc_iot, sc->sc_ioh, AUVIA_CODEC_CTL,
426 AUVIA_CODEC_PRIVALID | AUVIA_CODEC_READ | AUVIA_CODEC_INDEX(reg));
427
428 if (auvia_waitready_codec(sc))
429 return 1;
430
431 if (auvia_waitvalid_codec(sc))
432 return 1;
433
434 *val = bus_space_read_2(sc->sc_iot, sc->sc_ioh, AUVIA_CODEC_CTL);
435
436 return 0;
437 }
438
439
440 int
441 auvia_open(void *addr, int flags)
442 {
443 return 0;
444 }
445
446
447 void
448 auvia_close(void *addr)
449 {
450 struct auvia_softc *sc = addr;
451
452 auvia_halt_output(sc);
453 auvia_halt_input(sc);
454
455 sc->sc_play.sc_intr = NULL;
456 sc->sc_record.sc_intr = NULL;
457 }
458
459
460 int
461 auvia_query_encoding(void *addr, struct audio_encoding *fp)
462 {
463 switch (fp->index) {
464 case 0:
465 strlcpy(fp->name, AudioEulinear, sizeof fp->name);
466 fp->encoding = AUDIO_ENCODING_ULINEAR;
467 fp->precision = 8;
468 fp->flags = 0;
469 return (0);
470 case 1:
471 strlcpy(fp->name, AudioEmulaw, sizeof fp->name);
472 fp->encoding = AUDIO_ENCODING_ULAW;
473 fp->precision = 8;
474 fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
475 return (0);
476 case 2:
477 strlcpy(fp->name, AudioEalaw, sizeof fp->name);
478 fp->encoding = AUDIO_ENCODING_ALAW;
479 fp->precision = 8;
480 fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
481 return (0);
482 case 3:
483 strlcpy(fp->name, AudioEslinear, sizeof fp->name);
484 fp->encoding = AUDIO_ENCODING_SLINEAR;
485 fp->precision = 8;
486 fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
487 return (0);
488 case 4:
489 strlcpy(fp->name, AudioEslinear_le, sizeof fp->name);
490 fp->encoding = AUDIO_ENCODING_SLINEAR_LE;
491 fp->precision = 16;
492 fp->flags = 0;
493 return (0);
494 case 5:
495 strlcpy(fp->name, AudioEulinear_le, sizeof fp->name);
496 fp->encoding = AUDIO_ENCODING_ULINEAR_LE;
497 fp->precision = 16;
498 fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
499 return (0);
500 case 6:
501 strlcpy(fp->name, AudioEslinear_be, sizeof fp->name);
502 fp->encoding = AUDIO_ENCODING_SLINEAR_BE;
503 fp->precision = 16;
504 fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
505 return (0);
506 case 7:
507 strlcpy(fp->name, AudioEulinear_be, sizeof fp->name);
508 fp->encoding = AUDIO_ENCODING_ULINEAR_BE;
509 fp->precision = 16;
510 fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
511 return (0);
512 default:
513 return (EINVAL);
514 }
515 }
516
517
518 int
519 auvia_set_params(void *addr, int setmode, int usemode,
520 struct audio_params *play, struct audio_params *rec)
521 {
522 struct auvia_softc *sc = addr;
523 struct audio_params *p;
524 u_int16_t regval;
525 int mode, base;
526
527
528 for (mode = AUMODE_RECORD; mode != -1;
529 mode = mode == AUMODE_RECORD ? AUMODE_PLAY : -1) {
530 if ((setmode & mode) == 0)
531 continue;
532
533 if (mode == AUMODE_PLAY) {
534 p = play;
535 base = AUVIA_PLAY_BASE;
536 } else {
537 p = rec;
538 base = AUVIA_RECORD_BASE;
539 }
540
541 if (sc->sc_flags & AUVIA_FLAGS_VT8233) {
542 u_int32_t v = bus_space_read_4(sc->sc_iot, sc->sc_ioh,
543 base + VIA8233_RP_RATEFMT) & ~(VIA8233_RATEFMT_48K
544 | VIA8233_RATEFMT_STEREO | VIA8233_RATEFMT_16BIT);
545
546 v |= VIA8233_RATEFMT_48K *
547 (p->sample_rate / 20) / (48000 / 20);
548
549 if (p->channels == 2)
550 v |= VIA8233_RATEFMT_STEREO;
551 if (p->precision == 16)
552 v |= VIA8233_RATEFMT_16BIT;
553
554 bus_space_write_4(sc->sc_iot, sc->sc_ioh,
555 base + VIA8233_RP_RATEFMT, v);
556 }
557
558 if (ac97_set_rate(sc->codec_if, p, mode))
559 return (EINVAL);
560
561 if ((p->precision != 8 && p->precision != 16) ||
562 (p->channels != 1 && p->channels != 2))
563 return (EINVAL);
564
565 p->factor = 1;
566 p->sw_code = 0;
567 switch (p->encoding) {
568 case AUDIO_ENCODING_SLINEAR_BE:
569 if (p->precision == 16)
570 p->sw_code = swap_bytes;
571 else
572 p->sw_code = change_sign8;
573 break;
574 case AUDIO_ENCODING_SLINEAR_LE:
575 if (p->precision != 16)
576 p->sw_code = change_sign8;
577 break;
578 case AUDIO_ENCODING_ULINEAR_BE:
579 if (p->precision == 16)
580 p->sw_code = mode == AUMODE_PLAY?
581 swap_bytes_change_sign16_le :
582 change_sign16_swap_bytes_le;
583 break;
584 case AUDIO_ENCODING_ULINEAR_LE:
585 if (p->precision == 16)
586 p->sw_code = change_sign16_le;
587 break;
588 case AUDIO_ENCODING_ULAW:
589 if (mode == AUMODE_PLAY) {
590 p->factor = 2;
591 p->sw_code = mulaw_to_slinear16_le;
592 } else
593 p->sw_code = ulinear8_to_mulaw;
594 break;
595 case AUDIO_ENCODING_ALAW:
596 if (mode == AUMODE_PLAY) {
597 p->factor = 2;
598 p->sw_code = alaw_to_slinear16_le;
599 } else
600 p->sw_code = ulinear8_to_alaw;
601 break;
602 case AUDIO_ENCODING_SLINEAR:
603 case AUDIO_ENCODING_ULINEAR:
604 break;
605 default:
606 return (EINVAL);
607 }
608
609 regval = (p->channels == 2 ? AUVIA_RPMODE_STEREO : 0)
610 | (p->precision * p->factor == 16 ?
611 AUVIA_RPMODE_16BIT : 0)
612 | AUVIA_RPMODE_INTR_FLAG | AUVIA_RPMODE_INTR_EOL
613 | AUVIA_RPMODE_AUTOSTART;
614
615 if (mode == AUMODE_PLAY)
616 sc->sc_play.sc_reg = regval;
617 else
618 sc->sc_record.sc_reg = regval;
619 }
620
621 return 0;
622 }
623
624
625 int
626 auvia_round_blocksize(void *addr, int blk)
627 {
628 return ((blk + 31) & -32);
629 }
630
631
632 int
633 auvia_halt_output(void *addr)
634 {
635 struct auvia_softc *sc = addr;
636
637 bus_space_write_1(sc->sc_iot, sc->sc_ioh,
638 AUVIA_PLAY_BASE + AUVIA_RP_CONTROL, AUVIA_RPCTRL_TERMINATE);
639
640 return 0;
641 }
642
643
644 int
645 auvia_halt_input(void *addr)
646 {
647 struct auvia_softc *sc = addr;
648
649 bus_space_write_1(sc->sc_iot, sc->sc_ioh,
650 AUVIA_RECORD_BASE + AUVIA_RP_CONTROL, AUVIA_RPCTRL_TERMINATE);
651
652 return 0;
653 }
654
655
656 int
657 auvia_getdev(void *addr, struct audio_device *retp)
658 {
659 struct auvia_softc *sc = addr;
660
661 if (retp) {
662 strncpy(retp->name,
663 sc->sc_flags & AUVIA_FLAGS_VT8233? "VIA VT8233" :
664 "VIA VT82C686A", sizeof(retp->name));
665 strncpy(retp->version, sc->sc_revision, sizeof(retp->version));
666 strncpy(retp->config, "auvia", sizeof(retp->config));
667 }
668
669 return 0;
670 }
671
672
673 int
674 auvia_set_port(void *addr, mixer_ctrl_t *cp)
675 {
676 struct auvia_softc *sc = addr;
677
678 return (sc->codec_if->vtbl->mixer_set_port(sc->codec_if, cp));
679 }
680
681
682 int
683 auvia_get_port(void *addr, mixer_ctrl_t *cp)
684 {
685 struct auvia_softc *sc = addr;
686
687 return (sc->codec_if->vtbl->mixer_get_port(sc->codec_if, cp));
688 }
689
690
691 int
692 auvia_query_devinfo(void *addr, mixer_devinfo_t *dip)
693 {
694 struct auvia_softc *sc = addr;
695
696 return (sc->codec_if->vtbl->query_devinfo(sc->codec_if, dip));
697 }
698
699
700 void *
701 auvia_malloc(void *addr, int direction, size_t size, int pool, int flags)
702 {
703 struct auvia_softc *sc = addr;
704 struct auvia_dma *p;
705 int error;
706 int rseg;
707
708 p = malloc(sizeof(*p), pool, flags);
709 if (!p)
710 return 0;
711
712 p->size = size;
713 if ((error = bus_dmamem_alloc(sc->sc_dmat, size, PAGE_SIZE, 0, &p->seg,
714 1, &rseg, BUS_DMA_NOWAIT)) != 0) {
715 printf("%s: unable to allocate dma, error = %d\n",
716 sc->sc_dev.dv_xname, error);
717 goto fail_alloc;
718 }
719
720 if ((error = bus_dmamem_map(sc->sc_dmat, &p->seg, rseg, size, &p->addr,
721 BUS_DMA_NOWAIT | BUS_DMA_COHERENT)) != 0) {
722 printf("%s: unable to map dma, error = %d\n",
723 sc->sc_dev.dv_xname, error);
724 goto fail_map;
725 }
726
727 if ((error = bus_dmamap_create(sc->sc_dmat, size, 1, size, 0,
728 BUS_DMA_NOWAIT, &p->map)) != 0) {
729 printf("%s: unable to create dma map, error = %d\n",
730 sc->sc_dev.dv_xname, error);
731 goto fail_create;
732 }
733
734 if ((error = bus_dmamap_load(sc->sc_dmat, p->map, p->addr, size, NULL,
735 BUS_DMA_NOWAIT)) != 0) {
736 printf("%s: unable to load dma map, error = %d\n",
737 sc->sc_dev.dv_xname, error);
738 goto fail_load;
739 }
740
741 p->next = sc->sc_dmas;
742 sc->sc_dmas = p;
743
744 return p->addr;
745
746
747 fail_load:
748 bus_dmamap_destroy(sc->sc_dmat, p->map);
749 fail_create:
750 bus_dmamem_unmap(sc->sc_dmat, p->addr, size);
751 fail_map:
752 bus_dmamem_free(sc->sc_dmat, &p->seg, 1);
753 fail_alloc:
754 free(p, pool);
755 return 0;
756 }
757
758
759 void
760 auvia_free(void *addr, void *ptr, int pool)
761 {
762 struct auvia_softc *sc = addr;
763 struct auvia_dma **pp, *p;
764
765 for (pp = &(sc->sc_dmas); (p = *pp) != NULL; pp = &p->next)
766 if (p->addr == ptr) {
767 bus_dmamap_unload(sc->sc_dmat, p->map);
768 bus_dmamap_destroy(sc->sc_dmat, p->map);
769 bus_dmamem_unmap(sc->sc_dmat, p->addr, p->size);
770 bus_dmamem_free(sc->sc_dmat, &p->seg, 1);
771
772 *pp = p->next;
773 free(p, pool);
774 return;
775 }
776
777 panic("auvia_free: trying to free unallocated memory");
778 }
779
780 paddr_t
781 auvia_mappage(void *addr, void *mem, off_t off, int prot)
782 {
783 struct auvia_softc *sc = addr;
784 struct auvia_dma *p;
785
786 if (off < 0)
787 return -1;
788
789 for (p = sc->sc_dmas; p && p->addr != mem; p = p->next)
790 ;
791
792 if (!p)
793 return -1;
794
795 return bus_dmamem_mmap(sc->sc_dmat, &p->seg, 1, off, prot,
796 BUS_DMA_WAITOK);
797 }
798
799
800 int
801 auvia_get_props(void *addr)
802 {
803 return (AUDIO_PROP_MMAP | AUDIO_PROP_INDEPENDENT |
804 AUDIO_PROP_FULLDUPLEX);
805 }
806
807
808 int
809 auvia_build_dma_ops(struct auvia_softc *sc, struct auvia_softc_chan *ch,
810 struct auvia_dma *p, void *start, void *end, int blksize)
811 {
812 struct auvia_dma_op *op;
813 struct auvia_dma *dp;
814 bus_addr_t s;
815 size_t l;
816 int segs;
817
818 s = p->map->dm_segs[0].ds_addr;
819 l = (vaddr_t)end - (vaddr_t)start;
820 segs = howmany(l, blksize);
821
822 if (segs > ch->sc_dma_op_count) {
823
824 if (ch->sc_dma_ops)
825 auvia_free(sc, ch->sc_dma_ops, M_DEVBUF);
826
827 ch->sc_dma_ops = auvia_malloc(sc, 0,
828 sizeof(struct auvia_dma_op) * segs, M_DEVBUF, M_WAITOK);
829
830 for (dp = sc->sc_dmas; dp &&
831 dp->addr != (void *)(ch->sc_dma_ops); dp = dp->next)
832 ;
833
834 if (!dp)
835 panic("%s: build_dma_ops: where'd my memory go??? "
836 "address (%p)", sc->sc_dev.dv_xname,
837 ch->sc_dma_ops);
838
839 ch->sc_dma_op_count = segs;
840 ch->sc_dma_ops_dma = dp;
841 }
842
843 dp = ch->sc_dma_ops_dma;
844 op = ch->sc_dma_ops;
845
846 while (l) {
847 op->ptr = htole32(s);
848 l = l - min(l, blksize);
849
850 op->flags = htole32((l? AUVIA_DMAOP_FLAG : AUVIA_DMAOP_EOL) | blksize);
851 s += blksize;
852 op++;
853 }
854
855 return 0;
856 }
857
858
859 int
860 auvia_trigger_output(void *addr, void *start, void *end, int blksize,
861 void (*intr)(void *), void *arg, struct audio_params *param)
862 {
863 struct auvia_softc *sc = addr;
864 struct auvia_softc_chan *ch = &(sc->sc_play);
865 struct auvia_dma *p;
866
867 for (p = sc->sc_dmas; p && p->addr != start; p = p->next)
868 ;
869
870 if (!p)
871 panic("auvia_trigger_output: request with bad start "
872 "address (%p)", start);
873
874 if (auvia_build_dma_ops(sc, ch, p, start, end, blksize)) {
875 return 1;
876 }
877
878 ch->sc_intr = intr;
879 ch->sc_arg = arg;
880
881 bus_space_write_4(sc->sc_iot, sc->sc_ioh,
882 AUVIA_PLAY_BASE + AUVIA_RP_DMAOPS_BASE,
883 ch->sc_dma_ops_dma->map->dm_segs[0].ds_addr);
884
885 bus_space_write_1(sc->sc_iot, sc->sc_ioh,
886 AUVIA_PLAY_BASE + AUVIA_RP_MODE, ch->sc_reg);
887
888 if (sc->sc_flags & AUVIA_FLAGS_VT8233) {
889 bus_space_write_1(sc->sc_iot, sc->sc_ioh,
890 AUVIA_PLAY_BASE + VIA8233_RP_DXS_LVOL, 0);
891 bus_space_write_1(sc->sc_iot, sc->sc_ioh,
892 AUVIA_PLAY_BASE + VIA8233_RP_DXS_RVOL, 0);
893 bus_space_write_1(sc->sc_iot, sc->sc_ioh,
894 AUVIA_PLAY_BASE + AUVIA_RP_CONTROL,
895 AUVIA_RPCTRL_START | AUVIA_RPCTRL_AUTOSTART |
896 AUVIA_RPCTRL_STOP | AUVIA_RPCTRL_EOL | AUVIA_RPCTRL_FLAG);
897 } else
898 bus_space_write_1(sc->sc_iot, sc->sc_ioh,
899 AUVIA_PLAY_BASE + AUVIA_RP_CONTROL, AUVIA_RPCTRL_START);
900
901 return 0;
902 }
903
904
905 int
906 auvia_trigger_input(void *addr, void *start, void *end, int blksize,
907 void (*intr)(void *), void *arg, struct audio_params *param)
908 {
909 struct auvia_softc *sc = addr;
910 struct auvia_softc_chan *ch = &(sc->sc_record);
911 struct auvia_dma *p;
912
913 for (p = sc->sc_dmas; p && p->addr != start; p = p->next)
914 ;
915
916 if (!p)
917 panic("auvia_trigger_input: request with bad start "
918 "address (%p)", start);
919
920 if (auvia_build_dma_ops(sc, ch, p, start, end, blksize))
921 return 1;
922
923 ch->sc_intr = intr;
924 ch->sc_arg = arg;
925
926 bus_space_write_4(sc->sc_iot, sc->sc_ioh,
927 AUVIA_RECORD_BASE + AUVIA_RP_DMAOPS_BASE,
928 ch->sc_dma_ops_dma->map->dm_segs[0].ds_addr);
929 bus_space_write_1(sc->sc_iot, sc->sc_ioh,
930 AUVIA_RECORD_BASE + AUVIA_RP_MODE, ch->sc_reg);
931
932 if (sc->sc_flags & AUVIA_FLAGS_VT8233) {
933 bus_space_write_1(sc->sc_iot, sc->sc_ioh,
934 AUVIA_RECORD_BASE + VIA8233_RP_DXS_LVOL, 0);
935 bus_space_write_1(sc->sc_iot, sc->sc_ioh,
936 AUVIA_RECORD_BASE + VIA8233_RP_DXS_RVOL, 0);
937 bus_space_write_1(sc->sc_iot, sc->sc_ioh,
938 AUVIA_RECORD_BASE + AUVIA_RP_CONTROL,
939 AUVIA_RPCTRL_START | AUVIA_RPCTRL_AUTOSTART |
940 AUVIA_RPCTRL_STOP | AUVIA_RPCTRL_EOL | AUVIA_RPCTRL_FLAG);
941 } else
942 bus_space_write_1(sc->sc_iot, sc->sc_ioh,
943 AUVIA_RECORD_BASE + AUVIA_RP_CONTROL, AUVIA_RPCTRL_START);
944
945 return 0;
946 }
947
948
949 int
950 auvia_intr(void *arg)
951 {
952 struct auvia_softc *sc = arg;
953 u_int8_t r;
954 int i = 0;
955
956 r = bus_space_read_1(sc->sc_iot, sc->sc_ioh,
957 AUVIA_RECORD_BASE + AUVIA_RP_STAT);
958 if (r & AUVIA_RPSTAT_INTR) {
959 if (sc->sc_record.sc_intr)
960 sc->sc_record.sc_intr(sc->sc_record.sc_arg);
961
962
963 bus_space_write_1(sc->sc_iot, sc->sc_ioh,
964 AUVIA_RECORD_BASE + AUVIA_RP_STAT, AUVIA_RPSTAT_INTR);
965
966 i++;
967 }
968 r = bus_space_read_1(sc->sc_iot, sc->sc_ioh,
969 AUVIA_PLAY_BASE + AUVIA_RP_STAT);
970 if (r & AUVIA_RPSTAT_INTR) {
971 if (sc->sc_play.sc_intr)
972 sc->sc_play.sc_intr(sc->sc_play.sc_arg);
973
974
975 bus_space_write_1(sc->sc_iot, sc->sc_ioh,
976 AUVIA_PLAY_BASE + AUVIA_RP_STAT, AUVIA_RPSTAT_INTR);
977
978 i++;
979 }
980
981 return (i? 1 : 0);
982 }