1 /* $OpenBSD: auvia.c,v 1.67 2024/04/13 23:44:11 jsg Exp $ */
2 /* $NetBSD: auvia.c,v 1.28 2002/11/04 16:38:49 kent Exp $ */
3
4 /*-
5 * Copyright (c) 2000 The NetBSD Foundation, Inc.
6 * All rights reserved.
7 *
8 * This code is derived from software contributed to The NetBSD Foundation
9 * by Tyler C. Sarna
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 *
20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 * POSSIBILITY OF SUCH DAMAGE.
31 */
32
33 /*
34 * VIA Technologies VT82C686A Southbridge Audio Driver
35 *
36 * Documentation links:
37 *
38 * ftp://ftp.alsa-project.org/pub/manuals/via/686a.pdf
39 */
40
41 #include <sys/param.h>
42 #include <sys/systm.h>
43 #include <sys/malloc.h>
44 #include <sys/device.h>
45 #include <sys/audioio.h>
46
47 #include <dev/pci/pcidevs.h>
48 #include <dev/pci/pcivar.h>
49
50 #include <dev/audio_if.h>
51
52 #include <dev/ic/ac97.h>
53
54 #include <dev/pci/auviavar.h>
55
56 struct auvia_dma {
57 struct auvia_dma *next;
58 caddr_t addr;
59 size_t size;
60 bus_dmamap_t map;
61 bus_dma_segment_t seg;
62 };
63
64 struct auvia_dma_op {
65 u_int32_t ptr;
66 u_int32_t flags;
67 #define AUVIA_DMAOP_EOL 0x80000000
68 #define AUVIA_DMAOP_FLAG 0x40000000
69 #define AUVIA_DMAOP_STOP 0x20000000
70 #define AUVIA_DMAOP_COUNT(x) ((x)&0x00FFFFFF)
71 };
72
73 int auvia_match(struct device *, void *, void *);
74 void auvia_attach(struct device *, struct device *, void *);
75 int auvia_open(void *, int);
76 void auvia_close(void *);
77 void auvia_set_params_sub(struct auvia_softc *, struct auvia_softc_chan *,
78 struct audio_params *);
79 int auvia_set_params(void *, int, int, struct audio_params *,
80 struct audio_params *);
81 int auvia_round_blocksize(void *, int);
82 int auvia_halt_output(void *);
83 int auvia_halt_input(void *);
84 int auvia_set_port(void *, mixer_ctrl_t *);
85 int auvia_get_port(void *, mixer_ctrl_t *);
86 int auvia_query_devinfo(void *, mixer_devinfo_t *);
87 void * auvia_malloc(void *, int, size_t, int, int);
88 void auvia_free(void *, void *, int);
89 size_t auvia_round_buffersize(void *, int, size_t);
90 int auvia_build_dma_ops(struct auvia_softc *, struct auvia_softc_chan *,
91 struct auvia_dma *, void *, void *, int);
92 int auvia_trigger_output(void *, void *, void *, int, void (*)(void *),
93 void *, struct audio_params *);
94 int auvia_trigger_input(void *, void *, void *, int, void (*)(void *),
95 void *, struct audio_params *);
96
97 int auvia_intr(void *);
98
99 int auvia_activate(struct device *, int);
100
101 struct cfdriver auvia_cd = {
102 NULL, "auvia", DV_DULL
103 };
104
105 const struct cfattach auvia_ca = {
106 sizeof (struct auvia_softc), auvia_match, auvia_attach,
107 NULL, auvia_activate
108 };
109
110 #define AUVIA_PCICONF_JUNK 0x40
111 #define AUVIA_PCICONF_ENABLES 0x00FF0000 /* reg 42 mask */
112 #define AUVIA_PCICONF_ACLINKENAB 0x00008000 /* ac link enab */
113 #define AUVIA_PCICONF_ACNOTRST 0x00004000 /* ~(ac reset) */
114 #define AUVIA_PCICONF_ACSYNC 0x00002000 /* ac sync */
115 #define AUVIA_PCICONF_ACVSR 0x00000800 /* var. samp. rate */
116 #define AUVIA_PCICONF_ACSGD 0x00000400 /* SGD enab */
117 #define AUVIA_PCICONF_ACFM 0x00000200 /* FM enab */
118 #define AUVIA_PCICONF_ACSB 0x00000100 /* SB enab */
119 #define AUVIA_PCICONF_PRIVALID 0x00000001 /* primary codec rdy */
120
121 #define AUVIA_PLAY_BASE 0x00
122 #define AUVIA_RECORD_BASE 0x10
123
124 /* *_RP_* are offsets from AUVIA_PLAY_BASE or AUVIA_RECORD_BASE */
125 #define AUVIA_RP_STAT 0x00
126 #define AUVIA_RPSTAT_INTR 0x03
127 #define AUVIA_RP_CONTROL 0x01
128 #define AUVIA_RPCTRL_START 0x80
129 #define AUVIA_RPCTRL_TERMINATE 0x40
130 #define AUVIA_RPCTRL_AUTOSTART 0x20
131 /* The following are 8233 specific */
132 #define AUVIA_RPCTRL_STOP 0x04
133 #define AUVIA_RPCTRL_EOL 0x02
134 #define AUVIA_RPCTRL_FLAG 0x01
135 #define AUVIA_RP_MODE 0x02 /* 82c686 specific */
136 #define AUVIA_RPMODE_INTR_FLAG 0x01
137 #define AUVIA_RPMODE_INTR_EOL 0x02
138 #define AUVIA_RPMODE_STEREO 0x10
139 #define AUVIA_RPMODE_16BIT 0x20
140 #define AUVIA_RPMODE_AUTOSTART 0x80
141 #define AUVIA_RP_DMAOPS_BASE 0x04
142
143 #define VIA8233_RP_DXS_LVOL 0x02
144 #define VIA8233_RP_DXS_RVOL 0x03
145 #define VIA8233_RP_RATEFMT 0x08
146 #define VIA8233_RATEFMT_48K 0xfffff
147 #define VIA8233_RATEFMT_STEREO 0x00100000
148 #define VIA8233_RATEFMT_16BIT 0x00200000
149
150 #define VIA_RP_DMAOPS_COUNT 0x0c
151
152 #define VIA8233_MP_BASE 0x40
153 /* STAT, CONTROL, DMAOPS_BASE, DMAOPS_COUNT are valid */
154 #define VIA8233_OFF_MP_FORMAT 0x02
155 #define VIA8233_MP_FORMAT_8BIT 0x00
156 #define VIA8233_MP_FORMAT_16BIT 0x80
157 #define VIA8233_MP_FORMAT_CHANNLE_MASK 0x70 /* 1, 2, 4, 6 */
158 #define VIA8233_OFF_MP_SCRATCH 0x03
159 #define VIA8233_OFF_MP_STOP 0x08
160
161 #define VIA8233_WR_BASE 0x60
162
163 #define AUVIA_CODEC_CTL 0x80
164 #define AUVIA_CODEC_READ 0x00800000
165 #define AUVIA_CODEC_BUSY 0x01000000
166 #define AUVIA_CODEC_PRIVALID 0x02000000
167 #define AUVIA_CODEC_INDEX(x) ((x)<<16)
168
169 #define CH_WRITE1(sc, ch, off, v) \
170 bus_space_write_1((sc)->sc_iot, (sc)->sc_ioh, (ch)->sc_base + (off), v)
171 #define CH_WRITE4(sc, ch, off, v) \
172 bus_space_write_4((sc)->sc_iot, (sc)->sc_ioh, (ch)->sc_base + (off), v)
173 #define CH_READ1(sc, ch, off) \
174 bus_space_read_1((sc)->sc_iot, (sc)->sc_ioh, (ch)->sc_base + (off))
175 #define CH_READ4(sc, ch, off) \
176 bus_space_read_4((sc)->sc_iot, (sc)->sc_ioh, (ch)->sc_base + (off))
177
178 #define TIMEOUT 50
179
180 const struct audio_hw_if auvia_hw_if = {
181 .open = auvia_open,
182 .close = auvia_close,
183 .set_params = auvia_set_params,
184 .round_blocksize = auvia_round_blocksize,
185 .halt_output = auvia_halt_output,
186 .halt_input = auvia_halt_input,
187 .set_port = auvia_set_port,
188 .get_port = auvia_get_port,
189 .query_devinfo = auvia_query_devinfo,
190 .allocm = auvia_malloc,
191 .freem = auvia_free,
192 .round_buffersize = auvia_round_buffersize,
193 .trigger_output = auvia_trigger_output,
194 .trigger_input = auvia_trigger_input,
195 };
196
197 int auvia_attach_codec(void *, struct ac97_codec_if *);
198 int auvia_write_codec(void *, u_int8_t, u_int16_t);
199 int auvia_read_codec(void *, u_int8_t, u_int16_t *);
200 void auvia_reset_codec(void *);
201 int auvia_waitready_codec(struct auvia_softc *sc);
202 int auvia_waitvalid_codec(struct auvia_softc *sc);
203 void auvia_spdif_event(void *, int);
204
205 void auvia_resume(struct auvia_softc *);
206
207 const struct pci_matchid auvia_devices[] = {
208 { PCI_VENDOR_VIATECH, PCI_PRODUCT_VIATECH_VT82C686A_AC97 },
209 { PCI_VENDOR_VIATECH, PCI_PRODUCT_VIATECH_VT8233_AC97 },
210 };
211
212 int
auvia_match(struct device * parent,void * match,void * aux)213 auvia_match(struct device *parent, void *match, void *aux)
214 {
215 return (pci_matchbyid((struct pci_attach_args *)aux, auvia_devices,
216 nitems(auvia_devices)));
217 }
218
219 int
auvia_activate(struct device * self,int act)220 auvia_activate(struct device *self, int act)
221 {
222 struct auvia_softc *sc = (struct auvia_softc *)self;
223
224 if (act == DVACT_RESUME)
225 auvia_resume(sc);
226 return (config_activate_children(self, act));
227 }
228
229 void
auvia_attach(struct device * parent,struct device * self,void * aux)230 auvia_attach(struct device *parent, struct device *self, void *aux)
231 {
232 struct pci_attach_args *pa = aux;
233 struct auvia_softc *sc = (struct auvia_softc *) self;
234 const char *intrstr = NULL;
235 struct mixer_ctrl ctl;
236 pci_chipset_tag_t pc = pa->pa_pc;
237 pcitag_t pt = pa->pa_tag;
238 pci_intr_handle_t ih;
239 bus_size_t iosize;
240 pcireg_t pr;
241 int r, i;
242
243 sc->sc_play.sc_base = AUVIA_PLAY_BASE;
244 sc->sc_record.sc_base = AUVIA_RECORD_BASE;
245 if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_VIATECH_VT8233_AC97) {
246 sc->sc_flags |= AUVIA_FLAGS_VT8233;
247 sc->sc_play.sc_base = VIA8233_MP_BASE;
248 sc->sc_record.sc_base = VIA8233_WR_BASE;
249 }
250
251 if (pci_mapreg_map(pa, 0x10, PCI_MAPREG_TYPE_IO, 0, &sc->sc_iot,
252 &sc->sc_ioh, NULL, &iosize, 0)) {
253 printf(": can't map i/o space\n");
254 return;
255 }
256
257 sc->sc_dmat = pa->pa_dmat;
258 sc->sc_pc = pc;
259 sc->sc_pt = pt;
260
261 if (pci_intr_map(pa, &ih)) {
262 printf(": couldn't map interrupt\n");
263 bus_space_unmap(sc->sc_iot, sc->sc_ioh, iosize);
264 return;
265 }
266 intrstr = pci_intr_string(pc, ih);
267
268 sc->sc_ih = pci_intr_establish(pc, ih, IPL_AUDIO | IPL_MPSAFE,
269 auvia_intr, sc, sc->sc_dev.dv_xname);
270 if (sc->sc_ih == NULL) {
271 printf(": couldn't establish interrupt");
272 if (intrstr != NULL)
273 printf(" at %s", intrstr);
274 printf("\n");
275 bus_space_unmap(sc->sc_iot, sc->sc_ioh, iosize);
276 return;
277 }
278
279 printf(": %s\n", intrstr);
280
281 /* disable SBPro compat & others */
282 pr = pci_conf_read(pc, pt, AUVIA_PCICONF_JUNK);
283
284 pr &= ~AUVIA_PCICONF_ENABLES; /* clear compat function enables */
285 /* XXX what to do about MIDI, FM, joystick? */
286
287 pr |= (AUVIA_PCICONF_ACLINKENAB | AUVIA_PCICONF_ACNOTRST |
288 AUVIA_PCICONF_ACVSR | AUVIA_PCICONF_ACSGD);
289
290 pr &= ~(AUVIA_PCICONF_ACFM | AUVIA_PCICONF_ACSB);
291
292 pci_conf_write(pc, pt, AUVIA_PCICONF_JUNK, pr);
293 sc->sc_pci_junk = pr;
294
295 sc->host_if.arg = sc;
296 sc->host_if.attach = auvia_attach_codec;
297 sc->host_if.read = auvia_read_codec;
298 sc->host_if.write = auvia_write_codec;
299 sc->host_if.reset = auvia_reset_codec;
300 sc->host_if.spdif_event = auvia_spdif_event;
301
302 if ((r = ac97_attach(&sc->host_if)) != 0) {
303 printf("%s: can't attach codec (error 0x%X)\n",
304 sc->sc_dev.dv_xname, r);
305 pci_intr_disestablish(pc, sc->sc_ih);
306 bus_space_unmap(sc->sc_iot, sc->sc_ioh, iosize);
307 return;
308 }
309
310 /* disable mutes */
311 for (i = 0; i < 4; i++) {
312 static struct {
313 char *class, *device;
314 } d[] = {
315 { AudioCoutputs, AudioNmaster},
316 { AudioCinputs, AudioNdac},
317 { AudioCinputs, AudioNcd},
318 { AudioCrecord, AudioNvolume},
319 };
320
321 ctl.type = AUDIO_MIXER_ENUM;
322 ctl.un.ord = 0;
323
324 ctl.dev = sc->codec_if->vtbl->get_portnum_by_name(sc->codec_if,
325 d[i].class, d[i].device, AudioNmute);
326 auvia_set_port(sc, &ctl);
327 }
328
329 /* set a reasonable default volume */
330
331 ctl.type = AUDIO_MIXER_VALUE;
332 ctl.un.value.num_channels = 2;
333 ctl.un.value.level[AUDIO_MIXER_LEVEL_LEFT] = \
334 ctl.un.value.level[AUDIO_MIXER_LEVEL_RIGHT] = 199;
335
336 ctl.dev = sc->codec_if->vtbl->get_portnum_by_name(sc->codec_if,
337 AudioCoutputs, AudioNmaster, NULL);
338 auvia_set_port(sc, &ctl);
339
340 audio_attach_mi(&auvia_hw_if, sc, NULL, &sc->sc_dev);
341 sc->codec_if->vtbl->unlock(sc->codec_if);
342 }
343
344
345 int
auvia_attach_codec(void * addr,struct ac97_codec_if * cif)346 auvia_attach_codec(void *addr, struct ac97_codec_if *cif)
347 {
348 struct auvia_softc *sc = addr;
349
350 sc->codec_if = cif;
351
352 return 0;
353 }
354
355
356 void
auvia_reset_codec(void * addr)357 auvia_reset_codec(void *addr)
358 {
359 int i;
360 struct auvia_softc *sc = addr;
361 pcireg_t r;
362
363 /* perform a codec cold reset */
364
365 r = pci_conf_read(sc->sc_pc, sc->sc_pt, AUVIA_PCICONF_JUNK);
366
367 r &= ~AUVIA_PCICONF_ACNOTRST; /* enable RESET (active low) */
368 pci_conf_write(sc->sc_pc, sc->sc_pt, AUVIA_PCICONF_JUNK, r);
369 delay(2);
370
371 r |= AUVIA_PCICONF_ACNOTRST; /* disable RESET (inactive high) */
372 pci_conf_write(sc->sc_pc, sc->sc_pt, AUVIA_PCICONF_JUNK, r);
373 delay(200);
374
375 for (i = 500000; i != 0 && !(pci_conf_read(sc->sc_pc, sc->sc_pt,
376 AUVIA_PCICONF_JUNK) & AUVIA_PCICONF_PRIVALID); i--)
377 DELAY(1);
378 if (i == 0)
379 printf("%s: codec reset timed out\n", sc->sc_dev.dv_xname);
380 }
381
382
383 int
auvia_waitready_codec(struct auvia_softc * sc)384 auvia_waitready_codec(struct auvia_softc *sc)
385 {
386 int i;
387
388 /* poll until codec not busy */
389 for (i = 0; (i < TIMEOUT) && (bus_space_read_4(sc->sc_iot, sc->sc_ioh,
390 AUVIA_CODEC_CTL) & AUVIA_CODEC_BUSY); i++)
391 delay(1);
392
393 if (i >= TIMEOUT) {
394 printf("%s: codec busy\n", sc->sc_dev.dv_xname);
395 return 1;
396 }
397
398 return 0;
399 }
400
401
402 int
auvia_waitvalid_codec(struct auvia_softc * sc)403 auvia_waitvalid_codec(struct auvia_softc *sc)
404 {
405 int i;
406
407 /* poll until codec valid */
408 for (i = 0; (i < TIMEOUT) && !(bus_space_read_4(sc->sc_iot, sc->sc_ioh,
409 AUVIA_CODEC_CTL) & AUVIA_CODEC_PRIVALID); i++)
410 delay(1);
411
412 if (i >= TIMEOUT) {
413 printf("%s: codec invalid\n", sc->sc_dev.dv_xname);
414 return 1;
415 }
416
417 return 0;
418 }
419
420
421 int
auvia_write_codec(void * addr,u_int8_t reg,u_int16_t val)422 auvia_write_codec(void *addr, u_int8_t reg, u_int16_t val)
423 {
424 struct auvia_softc *sc = addr;
425
426 if (auvia_waitready_codec(sc))
427 return 1;
428
429 bus_space_write_4(sc->sc_iot, sc->sc_ioh, AUVIA_CODEC_CTL,
430 AUVIA_CODEC_PRIVALID | AUVIA_CODEC_INDEX(reg) | val);
431
432 return 0;
433 }
434
435
436 int
auvia_read_codec(void * addr,u_int8_t reg,u_int16_t * val)437 auvia_read_codec(void *addr, u_int8_t reg, u_int16_t *val)
438 {
439 struct auvia_softc *sc = addr;
440
441 if (auvia_waitready_codec(sc))
442 return 1;
443
444 bus_space_write_4(sc->sc_iot, sc->sc_ioh, AUVIA_CODEC_CTL,
445 AUVIA_CODEC_PRIVALID | AUVIA_CODEC_READ | AUVIA_CODEC_INDEX(reg));
446
447 if (auvia_waitready_codec(sc))
448 return 1;
449
450 if (auvia_waitvalid_codec(sc))
451 return 1;
452
453 *val = bus_space_read_2(sc->sc_iot, sc->sc_ioh, AUVIA_CODEC_CTL);
454
455 return 0;
456 }
457
458
459 void
auvia_spdif_event(void * addr,int flag)460 auvia_spdif_event(void *addr, int flag)
461 {
462 struct auvia_softc *sc = addr;
463 sc->sc_spdif = flag;
464 }
465
466 int
auvia_open(void * addr,int flags)467 auvia_open(void *addr, int flags)
468 {
469 struct auvia_softc *sc = addr;
470 sc->codec_if->vtbl->lock(sc->codec_if);
471 return 0;
472 }
473
474
475 void
auvia_close(void * addr)476 auvia_close(void *addr)
477 {
478 struct auvia_softc *sc = addr;
479 sc->codec_if->vtbl->unlock(sc->codec_if);
480
481 /* XXX: already called by audio_close() */
482 auvia_halt_output(sc);
483 auvia_halt_input(sc);
484
485 sc->sc_play.sc_intr = NULL;
486 sc->sc_record.sc_intr = NULL;
487 }
488
489
490 void
auvia_set_params_sub(struct auvia_softc * sc,struct auvia_softc_chan * ch,struct audio_params * p)491 auvia_set_params_sub(struct auvia_softc *sc, struct auvia_softc_chan *ch,
492 struct audio_params *p)
493 {
494 u_int32_t v;
495 u_int16_t regval;
496
497 if (!(sc->sc_flags & AUVIA_FLAGS_VT8233)) {
498 regval = (p->channels == 2 ? AUVIA_RPMODE_STEREO : 0)
499 | (p->precision == 16 ?
500 AUVIA_RPMODE_16BIT : 0)
501 | AUVIA_RPMODE_INTR_FLAG | AUVIA_RPMODE_INTR_EOL
502 | AUVIA_RPMODE_AUTOSTART;
503 ch->sc_reg = regval;
504 } else if (ch->sc_base != VIA8233_MP_BASE) {
505 v = CH_READ4(sc, ch, VIA8233_RP_RATEFMT);
506 v &= ~(VIA8233_RATEFMT_48K | VIA8233_RATEFMT_STEREO
507 | VIA8233_RATEFMT_16BIT);
508
509 v |= VIA8233_RATEFMT_48K * (p->sample_rate / 20)
510 / (48000 / 20);
511 if (p->channels == 2)
512 v |= VIA8233_RATEFMT_STEREO;
513 if (p->precision == 16)
514 v |= VIA8233_RATEFMT_16BIT;
515
516 CH_WRITE4(sc, ch, VIA8233_RP_RATEFMT, v);
517 } else {
518 static const u_int32_t slottab[7] =
519 { 0, 0xff000011, 0xff000021, 0,
520 0xff004321, 0, 0xff436521};
521
522 regval = (p->precision == 16
523 ? VIA8233_MP_FORMAT_16BIT : VIA8233_MP_FORMAT_8BIT)
524 | (p->channels << 4);
525 CH_WRITE1(sc, ch, VIA8233_OFF_MP_FORMAT, regval);
526 CH_WRITE4(sc, ch, VIA8233_OFF_MP_STOP, slottab[p->channels]);
527 }
528 }
529
530 int
auvia_set_params(void * addr,int setmode,int usemode,struct audio_params * play,struct audio_params * rec)531 auvia_set_params(void *addr, int setmode, int usemode,
532 struct audio_params *play, struct audio_params *rec)
533 {
534 struct auvia_softc *sc = addr;
535 struct auvia_softc_chan *ch;
536 struct audio_params *p;
537 struct ac97_codec_if* codec = sc->codec_if;
538 int reg, mode;
539 u_int16_t ext_id;
540
541 /* for mode in (RECORD, PLAY) */
542 for (mode = AUMODE_RECORD; mode != -1;
543 mode = mode == AUMODE_RECORD ? AUMODE_PLAY : -1) {
544 if ((setmode & mode) == 0)
545 continue;
546
547 if (mode == AUMODE_PLAY) {
548 p = play;
549 ch = &sc->sc_play;
550 reg = AC97_REG_PCM_FRONT_DAC_RATE;
551 } else {
552 p = rec;
553 ch = &sc->sc_record;
554 reg = AC97_REG_PCM_LR_ADC_RATE;
555 }
556
557 if (ch->sc_base == VIA8233_MP_BASE && mode == AUMODE_PLAY) {
558 ext_id = codec->vtbl->get_caps(codec);
559 if (p->channels == 1) {
560 /* ok */
561 } else if (p->channels == 2) {
562 /* ok */
563 } else if (p->channels == 4
564 && ext_id & AC97_EXT_AUDIO_SDAC) {
565 /* ok */
566 } else if (p->channels == 6
567 && (ext_id & AC97_BITS_6CH) == AC97_BITS_6CH) {
568 /* ok */
569 } else {
570 p->channels = 2;
571 }
572 } else {
573 if (p->channels > 2)
574 p->channels = 2;
575 }
576
577 if (p->sample_rate < 4000)
578 p->sample_rate = 4000;
579 if (p->sample_rate > 48000)
580 p->sample_rate = 48000;
581 if (p->precision > 16)
582 p->precision = 16;
583
584 /* XXX only 16-bit 48kHz slinear_le if s/pdif enabled ? */
585 if (sc->sc_spdif) {
586 p->sample_rate = 48000;
587 p->precision = 16;
588 p->encoding = AUDIO_ENCODING_SLINEAR_LE;
589 }
590
591 /* XXX only 16-bit 48kHz slinear_le if s/pdif enabled ? */
592 if (sc->sc_spdif &&
593 ((p->sample_rate != 48000) || (p->precision != 16) ||
594 (p->encoding != AUDIO_ENCODING_SLINEAR_LE)))
595 return (EINVAL);
596
597 if (AC97_IS_FIXED_RATE(codec)) {
598 p->sample_rate = AC97_SINGLE_RATE;
599 } else {
600 if (codec->vtbl->set_rate(codec, reg, &p->sample_rate))
601 return (EINVAL);
602
603 if (ch->sc_base == VIA8233_MP_BASE &&
604 mode == AUMODE_PLAY) {
605 reg = AC97_REG_PCM_SURR_DAC_RATE;
606 if (p->channels >= 4
607 && codec->vtbl->set_rate(codec, reg,
608 &p->sample_rate))
609 return (EINVAL);
610 reg = AC97_REG_PCM_LFE_DAC_RATE;
611 if (p->channels == 6
612 && codec->vtbl->set_rate(codec, reg,
613 &p->sample_rate))
614 return (EINVAL);
615 }
616 }
617
618 switch (p->encoding) {
619 case AUDIO_ENCODING_SLINEAR_LE:
620 if (p->precision != 16)
621 return EINVAL;
622 break;
623 case AUDIO_ENCODING_ULINEAR_LE:
624 case AUDIO_ENCODING_ULINEAR_BE:
625 if (p->precision != 8)
626 return EINVAL;
627 break;
628 default:
629 return (EINVAL);
630 }
631 auvia_set_params_sub(sc, ch, p);
632
633 p->bps = AUDIO_BPS(p->precision);
634 p->msb = 1;
635 }
636
637 return 0;
638 }
639
640
641 int
auvia_round_blocksize(void * addr,int blk)642 auvia_round_blocksize(void *addr, int blk)
643 {
644 struct auvia_softc *sc = addr;
645
646 if (sc->bufsize / blk > AUVIA_DMALIST_MAX)
647 blk = sc->bufsize / AUVIA_DMALIST_MAX + 1;
648 return ((blk + 31) & -32);
649 }
650
651
652 int
auvia_halt_output(void * addr)653 auvia_halt_output(void *addr)
654 {
655 struct auvia_softc *sc = addr;
656 struct auvia_softc_chan *ch = &(sc->sc_play);
657
658 CH_WRITE1(sc, ch, AUVIA_RP_CONTROL, AUVIA_RPCTRL_TERMINATE);
659 ch->sc_intr = NULL;
660 return 0;
661 }
662
663
664 int
auvia_halt_input(void * addr)665 auvia_halt_input(void *addr)
666 {
667 struct auvia_softc *sc = addr;
668 struct auvia_softc_chan *ch = &(sc->sc_record);
669
670 CH_WRITE1(sc, ch, AUVIA_RP_CONTROL, AUVIA_RPCTRL_TERMINATE);
671 ch->sc_intr = NULL;
672 return 0;
673 }
674
675
676 int
auvia_set_port(void * addr,mixer_ctrl_t * cp)677 auvia_set_port(void *addr, mixer_ctrl_t *cp)
678 {
679 struct auvia_softc *sc = addr;
680
681 return (sc->codec_if->vtbl->mixer_set_port(sc->codec_if, cp));
682 }
683
684
685 int
auvia_get_port(void * addr,mixer_ctrl_t * cp)686 auvia_get_port(void *addr, mixer_ctrl_t *cp)
687 {
688 struct auvia_softc *sc = addr;
689
690 return (sc->codec_if->vtbl->mixer_get_port(sc->codec_if, cp));
691 }
692
693
694 int
auvia_query_devinfo(void * addr,mixer_devinfo_t * dip)695 auvia_query_devinfo(void *addr, mixer_devinfo_t *dip)
696 {
697 struct auvia_softc *sc = addr;
698
699 return (sc->codec_if->vtbl->query_devinfo(sc->codec_if, dip));
700 }
701
702
703 void *
auvia_malloc(void * addr,int direction,size_t size,int pool,int flags)704 auvia_malloc(void *addr, int direction, size_t size, int pool, int flags)
705 {
706 struct auvia_softc *sc = addr;
707 struct auvia_dma *p;
708 int error;
709 int rseg;
710
711 p = malloc(sizeof(*p), pool, flags);
712 if (!p)
713 return 0;
714
715 p->size = size;
716 if ((error = bus_dmamem_alloc(sc->sc_dmat, size, PAGE_SIZE, 0, &p->seg,
717 1, &rseg, BUS_DMA_NOWAIT)) != 0) {
718 printf("%s: unable to allocate dma, error = %d\n",
719 sc->sc_dev.dv_xname, error);
720 goto fail_alloc;
721 }
722
723 if ((error = bus_dmamem_map(sc->sc_dmat, &p->seg, rseg, size, &p->addr,
724 BUS_DMA_NOWAIT | BUS_DMA_COHERENT)) != 0) {
725 printf("%s: unable to map dma, error = %d\n",
726 sc->sc_dev.dv_xname, error);
727 goto fail_map;
728 }
729
730 if ((error = bus_dmamap_create(sc->sc_dmat, size, 1, size, 0,
731 BUS_DMA_NOWAIT, &p->map)) != 0) {
732 printf("%s: unable to create dma map, error = %d\n",
733 sc->sc_dev.dv_xname, error);
734 goto fail_create;
735 }
736
737 if ((error = bus_dmamap_load(sc->sc_dmat, p->map, p->addr, size, NULL,
738 BUS_DMA_NOWAIT)) != 0) {
739 printf("%s: unable to load dma map, error = %d\n",
740 sc->sc_dev.dv_xname, error);
741 goto fail_load;
742 }
743
744 p->next = sc->sc_dmas;
745 sc->sc_dmas = p;
746
747 return p->addr;
748
749
750 fail_load:
751 bus_dmamap_destroy(sc->sc_dmat, p->map);
752 fail_create:
753 bus_dmamem_unmap(sc->sc_dmat, p->addr, size);
754 fail_map:
755 bus_dmamem_free(sc->sc_dmat, &p->seg, 1);
756 fail_alloc:
757 free(p, pool, sizeof(*p));
758 return 0;
759 }
760
761
762 void
auvia_free(void * addr,void * ptr,int pool)763 auvia_free(void *addr, void *ptr, int pool)
764 {
765 struct auvia_softc *sc = addr;
766 struct auvia_dma **pp, *p;
767
768 for (pp = &(sc->sc_dmas); (p = *pp) != NULL; pp = &p->next)
769 if (p->addr == ptr) {
770 bus_dmamap_unload(sc->sc_dmat, p->map);
771 bus_dmamap_destroy(sc->sc_dmat, p->map);
772 bus_dmamem_unmap(sc->sc_dmat, p->addr, p->size);
773 bus_dmamem_free(sc->sc_dmat, &p->seg, 1);
774
775 *pp = p->next;
776 free(p, pool, sizeof(*p));
777 return;
778 }
779
780 panic("auvia_free: trying to free unallocated memory");
781 }
782
783 size_t
auvia_round_buffersize(void * addr,int direction,size_t bufsize)784 auvia_round_buffersize(void *addr, int direction, size_t bufsize)
785 {
786 struct auvia_softc *sc = addr;
787
788 sc->bufsize = bufsize;
789 return bufsize;
790 }
791
792
793 int
auvia_build_dma_ops(struct auvia_softc * sc,struct auvia_softc_chan * ch,struct auvia_dma * p,void * start,void * end,int blksize)794 auvia_build_dma_ops(struct auvia_softc *sc, struct auvia_softc_chan *ch,
795 struct auvia_dma *p, void *start, void *end, int blksize)
796 {
797 struct auvia_dma_op *op;
798 struct auvia_dma *dp;
799 bus_addr_t s;
800 size_t l;
801 int segs;
802
803 s = p->map->dm_segs[0].ds_addr;
804 l = (vaddr_t)end - (vaddr_t)start;
805 segs = howmany(l, blksize);
806 if (segs > AUVIA_DMALIST_MAX) {
807 panic("%s: build_dma_ops: too many DMA segments",
808 sc->sc_dev.dv_xname);
809 }
810
811 if (segs > ch->sc_dma_op_count) {
812 /* if old list was too small, free it */
813 if (ch->sc_dma_ops)
814 auvia_free(sc, ch->sc_dma_ops, M_DEVBUF);
815
816 ch->sc_dma_ops = auvia_malloc(sc, 0,
817 sizeof(struct auvia_dma_op) * segs, M_DEVBUF, M_WAITOK);
818
819 for (dp = sc->sc_dmas; dp &&
820 dp->addr != (void *)(ch->sc_dma_ops); dp = dp->next)
821 ;
822
823 if (!dp)
824 panic("%s: build_dma_ops: where'd my memory go??? "
825 "address (%p)", sc->sc_dev.dv_xname,
826 ch->sc_dma_ops);
827
828 ch->sc_dma_op_count = segs;
829 ch->sc_dma_ops_dma = dp;
830 }
831
832 op = ch->sc_dma_ops;
833
834 while (l) {
835 op->ptr = htole32(s);
836 l = l - min(l, blksize);
837 /* if last block */
838 op->flags = htole32((l? AUVIA_DMAOP_FLAG : AUVIA_DMAOP_EOL) | blksize);
839 s += blksize;
840 op++;
841 }
842
843 return 0;
844 }
845
846
847 int
auvia_trigger_output(void * addr,void * start,void * end,int blksize,void (* intr)(void *),void * arg,struct audio_params * param)848 auvia_trigger_output(void *addr, void *start, void *end, int blksize,
849 void (*intr)(void *), void *arg, struct audio_params *param)
850 {
851 struct auvia_softc *sc = addr;
852 struct auvia_softc_chan *ch = &(sc->sc_play);
853 struct auvia_dma *p;
854
855 for (p = sc->sc_dmas; p && p->addr != start; p = p->next)
856 ;
857
858 if (!p)
859 panic("auvia_trigger_output: request with bad start "
860 "address (%p)", start);
861
862 if (auvia_build_dma_ops(sc, ch, p, start, end, blksize)) {
863 return 1;
864 }
865
866 ch->sc_intr = intr;
867 ch->sc_arg = arg;
868
869 CH_WRITE4(sc, ch, AUVIA_RP_DMAOPS_BASE,
870 ch->sc_dma_ops_dma->map->dm_segs[0].ds_addr);
871 mtx_enter(&audio_lock);
872 if (sc->sc_flags & AUVIA_FLAGS_VT8233) {
873 if (ch->sc_base != VIA8233_MP_BASE) {
874 CH_WRITE1(sc, ch, VIA8233_RP_DXS_LVOL, 0);
875 CH_WRITE1(sc, ch, VIA8233_RP_DXS_RVOL, 0);
876 }
877 CH_WRITE1(sc, ch, AUVIA_RP_CONTROL,
878 AUVIA_RPCTRL_START | AUVIA_RPCTRL_AUTOSTART |
879 AUVIA_RPCTRL_STOP | AUVIA_RPCTRL_EOL | AUVIA_RPCTRL_FLAG);
880 } else {
881 CH_WRITE1(sc, ch, AUVIA_RP_MODE, ch->sc_reg);
882 CH_WRITE1(sc, ch, AUVIA_RP_CONTROL, AUVIA_RPCTRL_START);
883 }
884 mtx_leave(&audio_lock);
885 return 0;
886 }
887
888
889 int
auvia_trigger_input(void * addr,void * start,void * end,int blksize,void (* intr)(void *),void * arg,struct audio_params * param)890 auvia_trigger_input(void *addr, void *start, void *end, int blksize,
891 void (*intr)(void *), void *arg, struct audio_params *param)
892 {
893 struct auvia_softc *sc = addr;
894 struct auvia_softc_chan *ch = &(sc->sc_record);
895 struct auvia_dma *p;
896
897 for (p = sc->sc_dmas; p && p->addr != start; p = p->next)
898 ;
899
900 if (!p)
901 panic("auvia_trigger_input: request with bad start "
902 "address (%p)", start);
903
904 if (auvia_build_dma_ops(sc, ch, p, start, end, blksize))
905 return 1;
906
907 ch->sc_intr = intr;
908 ch->sc_arg = arg;
909
910 CH_WRITE4(sc, ch, AUVIA_RP_DMAOPS_BASE,
911 ch->sc_dma_ops_dma->map->dm_segs[0].ds_addr);
912
913 mtx_enter(&audio_lock);
914 if (sc->sc_flags & AUVIA_FLAGS_VT8233) {
915 if (ch->sc_base != VIA8233_MP_BASE) {
916 CH_WRITE1(sc, ch, VIA8233_RP_DXS_LVOL, 0);
917 CH_WRITE1(sc, ch, VIA8233_RP_DXS_RVOL, 0);
918 }
919 CH_WRITE1(sc, ch, AUVIA_RP_CONTROL,
920 AUVIA_RPCTRL_START | AUVIA_RPCTRL_AUTOSTART |
921 AUVIA_RPCTRL_STOP | AUVIA_RPCTRL_EOL | AUVIA_RPCTRL_FLAG);
922 } else {
923 CH_WRITE1(sc, ch, AUVIA_RP_MODE, ch->sc_reg);
924 CH_WRITE1(sc, ch, AUVIA_RP_CONTROL, AUVIA_RPCTRL_START);
925 }
926 mtx_leave(&audio_lock);
927 return 0;
928 }
929
930
931 int
auvia_intr(void * arg)932 auvia_intr(void *arg)
933 {
934 struct auvia_softc *sc = arg;
935 struct auvia_softc_chan *ch;
936 u_int8_t r;
937 int i = 0;
938
939 mtx_enter(&audio_lock);
940 ch = &sc->sc_record;
941 r = CH_READ1(sc, ch, AUVIA_RP_STAT);
942 if (r & AUVIA_RPSTAT_INTR) {
943 if (sc->sc_record.sc_intr)
944 sc->sc_record.sc_intr(sc->sc_record.sc_arg);
945
946 /* clear interrupts */
947 CH_WRITE1(sc, ch, AUVIA_RP_STAT, AUVIA_RPSTAT_INTR);
948
949 i++;
950 }
951 ch = &sc->sc_play;
952 r = CH_READ1(sc, ch, AUVIA_RP_STAT);
953 if (r & AUVIA_RPSTAT_INTR) {
954 if (sc->sc_play.sc_intr)
955 sc->sc_play.sc_intr(sc->sc_play.sc_arg);
956
957 /* clear interrupts */
958 CH_WRITE1(sc, ch, AUVIA_RP_STAT, AUVIA_RPSTAT_INTR);
959
960 i++;
961 }
962 mtx_leave(&audio_lock);
963 return (i? 1 : 0);
964 }
965
966 void
auvia_resume(struct auvia_softc * sc)967 auvia_resume(struct auvia_softc *sc)
968 {
969 pci_conf_read(sc->sc_pc, sc->sc_pt, AUVIA_PCICONF_JUNK);
970 pci_conf_write(sc->sc_pc, sc->sc_pt, AUVIA_PCICONF_JUNK,
971 sc->sc_pci_junk);
972
973 ac97_resume(&sc->host_if, sc->codec_if);
974 }
975
976