auvia.c revision 1.52 1 /* $NetBSD: auvia.c,v 1.52 2005/06/28 00:28:41 thorpej Exp $ */
2
3 /*-
4 * Copyright (c) 2000 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Tyler C. Sarna
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by the NetBSD
21 * Foundation, Inc. and its contributors.
22 * 4. Neither the name of The NetBSD Foundation nor the names of its
23 * contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 * POSSIBILITY OF SUCH DAMAGE.
37 */
38
39 /*
40 * VIA Technologies VT82C686A / VT8233 / VT8235 Southbridge Audio Driver
41 *
42 * Documentation links:
43 *
44 * ftp://ftp.alsa-project.org/pub/manuals/via/686a.pdf
45 * ftp://ftp.alsa-project.org/pub/manuals/general/ac97r21.pdf
46 * ftp://ftp.alsa-project.org/pub/manuals/ad/AD1881_0.pdf (example AC'97 codec)
47 */
48
49 #include <sys/cdefs.h>
50 __KERNEL_RCSID(0, "$NetBSD: auvia.c,v 1.52 2005/06/28 00:28:41 thorpej Exp $");
51
52 #include <sys/param.h>
53 #include <sys/systm.h>
54 #include <sys/malloc.h>
55 #include <sys/device.h>
56 #include <sys/audioio.h>
57
58 #include <uvm/uvm_extern.h>
59
60 #include <dev/pci/pcidevs.h>
61 #include <dev/pci/pcivar.h>
62
63 #include <dev/audio_if.h>
64 #include <dev/mulaw.h>
65 #include <dev/auconv.h>
66
67 #include <dev/ic/ac97reg.h>
68 #include <dev/ic/ac97var.h>
69
70 #include <dev/pci/auviavar.h>
71
72 struct auvia_dma {
73 struct auvia_dma *next;
74 caddr_t addr;
75 size_t size;
76 bus_dmamap_t map;
77 bus_dma_segment_t seg;
78 };
79
80 struct auvia_dma_op {
81 uint32_t ptr;
82 uint32_t flags;
83 #define AUVIA_DMAOP_EOL 0x80000000
84 #define AUVIA_DMAOP_FLAG 0x40000000
85 #define AUVIA_DMAOP_STOP 0x20000000
86 #define AUVIA_DMAOP_COUNT(x) ((x)&0x00FFFFFF)
87 };
88
89 static int auvia_match(struct device *, struct cfdata *, void *);
90 static void auvia_attach(struct device *, struct device *, void *);
91 static int auvia_query_encoding(void *, struct audio_encoding *);
92 static void auvia_set_params_sub(struct auvia_softc *,
93 struct auvia_softc_chan *,
94 const audio_params_t *);
95 static int auvia_set_params(void *, int, int, audio_params_t *,
96 audio_params_t *, stream_filter_list_t *,
97 stream_filter_list_t *);
98 static int auvia_round_blocksize(void *, int, int, const audio_params_t *);
99 static int auvia_halt_output(void *);
100 static int auvia_halt_input(void *);
101 static int auvia_getdev(void *, struct audio_device *);
102 static int auvia_set_port(void *, mixer_ctrl_t *);
103 static int auvia_get_port(void *, mixer_ctrl_t *);
104 static int auvia_query_devinfo(void *, mixer_devinfo_t *);
105 static void * auvia_malloc(void *, int, size_t, struct malloc_type *, int);
106 static void auvia_free(void *, void *, struct malloc_type *);
107 static size_t auvia_round_buffersize(void *, int, size_t);
108 static paddr_t auvia_mappage(void *, void *, off_t, int);
109 static int auvia_get_props(void *);
110 static int auvia_build_dma_ops(struct auvia_softc *,
111 struct auvia_softc_chan *,
112 struct auvia_dma *, void *, void *, int);
113 static int auvia_trigger_output(void *, void *, void *, int,
114 void (*)(void *), void *,
115 const audio_params_t *);
116 static int auvia_trigger_input(void *, void *, void *, int,
117 void (*)(void *), void *,
118 const audio_params_t *);
119 static void auvia_powerhook(int, void *);
120 static int auvia_intr(void *);
121
122 CFATTACH_DECL(auvia, sizeof (struct auvia_softc),
123 auvia_match, auvia_attach, NULL, NULL);
124
125 /* VIA VT823xx revision number */
126 #define VIA_REV_8233C 0x20
127 #define VIA_REV_8233 0x30
128 #define VIA_REV_8233A 0x40
129 #define VIA_REV_8235 0x50
130 #define VIA_REV_8237 0x60
131
132 #define AUVIA_PCICONF_JUNK 0x40
133 #define AUVIA_PCICONF_ENABLES 0x00FF0000 /* reg 42 mask */
134 #define AUVIA_PCICONF_ACLINKENAB 0x00008000 /* ac link enab */
135 #define AUVIA_PCICONF_ACNOTRST 0x00004000 /* ~(ac reset) */
136 #define AUVIA_PCICONF_ACSYNC 0x00002000 /* ac sync */
137 #define AUVIA_PCICONF_ACVSR 0x00000800 /* var. samp. rate */
138 #define AUVIA_PCICONF_ACSGD 0x00000400 /* SGD enab */
139 #define AUVIA_PCICONF_ACFM 0x00000200 /* FM enab */
140 #define AUVIA_PCICONF_ACSB 0x00000100 /* SB enab */
141 #define AUVIA_PCICONF_PRIVALID 0x00000001 /* primary codec rdy */
142
143 #define AUVIA_PLAY_BASE 0x00
144 #define AUVIA_RECORD_BASE 0x10
145
146 /* *_RP_* are offsets from AUVIA_PLAY_BASE or AUVIA_RECORD_BASE */
147 #define AUVIA_RP_STAT 0x00
148 #define AUVIA_RPSTAT_INTR 0x03
149 #define AUVIA_RP_CONTROL 0x01
150 #define AUVIA_RPCTRL_START 0x80
151 #define AUVIA_RPCTRL_TERMINATE 0x40
152 #define AUVIA_RPCTRL_AUTOSTART 0x20
153 /* The following are 8233 specific */
154 #define AUVIA_RPCTRL_STOP 0x04
155 #define AUVIA_RPCTRL_EOL 0x02
156 #define AUVIA_RPCTRL_FLAG 0x01
157 #define AUVIA_RP_MODE 0x02 /* 82c686 specific */
158 #define AUVIA_RPMODE_INTR_FLAG 0x01
159 #define AUVIA_RPMODE_INTR_EOL 0x02
160 #define AUVIA_RPMODE_STEREO 0x10
161 #define AUVIA_RPMODE_16BIT 0x20
162 #define AUVIA_RPMODE_AUTOSTART 0x80
163 #define AUVIA_RP_DMAOPS_BASE 0x04
164
165 #define VIA8233_RP_DXS_LVOL 0x02
166 #define VIA8233_RP_DXS_RVOL 0x03
167 #define VIA8233_RP_RATEFMT 0x08
168 #define VIA8233_RATEFMT_48K 0xfffff
169 #define VIA8233_RATEFMT_STEREO 0x00100000
170 #define VIA8233_RATEFMT_16BIT 0x00200000
171
172 #define VIA_RP_DMAOPS_COUNT 0x0c
173
174 #define VIA8233_MP_BASE 0x40
175 /* STAT, CONTROL, DMAOPS_BASE, DMAOPS_COUNT are valid */
176 #define VIA8233_OFF_MP_FORMAT 0x02
177 #define VIA8233_MP_FORMAT_8BIT 0x00
178 #define VIA8233_MP_FORMAT_16BIT 0x80
179 #define VIA8233_MP_FORMAT_CHANNLE_MASK 0x70 /* 1, 2, 4, 6 */
180 #define VIA8233_OFF_MP_SCRATCH 0x03
181 #define VIA8233_OFF_MP_STOP 0x08
182
183 #define AUVIA_CODEC_CTL 0x80
184 #define AUVIA_CODEC_READ 0x00800000
185 #define AUVIA_CODEC_BUSY 0x01000000
186 #define AUVIA_CODEC_PRIVALID 0x02000000
187 #define AUVIA_CODEC_INDEX(x) ((x)<<16)
188
189 #define CH_WRITE1(sc, ch, off, v) \
190 bus_space_write_1((sc)->sc_iot, (sc)->sc_ioh, (ch)->sc_base + (off), v)
191 #define CH_WRITE4(sc, ch, off, v) \
192 bus_space_write_4((sc)->sc_iot, (sc)->sc_ioh, (ch)->sc_base + (off), v)
193 #define CH_READ1(sc, ch, off) \
194 bus_space_read_1((sc)->sc_iot, (sc)->sc_ioh, (ch)->sc_base + (off))
195 #define CH_READ4(sc, ch, off) \
196 bus_space_read_4((sc)->sc_iot, (sc)->sc_ioh, (ch)->sc_base + (off))
197
198 #define TIMEOUT 50
199
200 static const struct audio_hw_if auvia_hw_if = {
201 NULL, /* open */
202 NULL, /* close */
203 NULL, /* drain */
204 auvia_query_encoding,
205 auvia_set_params,
206 auvia_round_blocksize,
207 NULL, /* commit_settings */
208 NULL, /* init_output */
209 NULL, /* init_input */
210 NULL, /* start_output */
211 NULL, /* start_input */
212 auvia_halt_output,
213 auvia_halt_input,
214 NULL, /* speaker_ctl */
215 auvia_getdev,
216 NULL, /* setfd */
217 auvia_set_port,
218 auvia_get_port,
219 auvia_query_devinfo,
220 auvia_malloc,
221 auvia_free,
222 auvia_round_buffersize,
223 auvia_mappage,
224 auvia_get_props,
225 auvia_trigger_output,
226 auvia_trigger_input,
227 NULL, /* dev_ioctl */
228 };
229
230 #define AUVIA_FORMATS_4CH_16 2
231 #define AUVIA_FORMATS_6CH_16 3
232 #define AUVIA_FORMATS_4CH_8 6
233 #define AUVIA_FORMATS_6CH_8 7
234 static const struct audio_format auvia_formats[AUVIA_NFORMATS] = {
235 {NULL, AUMODE_PLAY | AUMODE_RECORD, AUDIO_ENCODING_SLINEAR_LE, 16, 16,
236 1, AUFMT_MONAURAL, 0, {8000, 48000}},
237 {NULL, AUMODE_PLAY | AUMODE_RECORD, AUDIO_ENCODING_SLINEAR_LE, 16, 16,
238 2, AUFMT_STEREO, 0, {8000, 48000}},
239 {NULL, AUMODE_PLAY, AUDIO_ENCODING_SLINEAR_LE, 16, 16,
240 4, AUFMT_SURROUND4, 0, {8000, 48000}},
241 {NULL, AUMODE_PLAY, AUDIO_ENCODING_SLINEAR_LE, 16, 16,
242 6, AUFMT_DOLBY_5_1, 0, {8000, 48000}},
243 {NULL, AUMODE_PLAY | AUMODE_RECORD, AUDIO_ENCODING_ULINEAR_LE, 8, 8,
244 1, AUFMT_MONAURAL, 0, {8000, 48000}},
245 {NULL, AUMODE_PLAY | AUMODE_RECORD, AUDIO_ENCODING_ULINEAR_LE, 8, 8,
246 2, AUFMT_STEREO, 0, {8000, 48000}},
247 {NULL, AUMODE_PLAY, AUDIO_ENCODING_ULINEAR_LE, 8, 8,
248 4, AUFMT_SURROUND4, 0, {8000, 48000}},
249 {NULL, AUMODE_PLAY, AUDIO_ENCODING_SLINEAR_LE, 8, 8,
250 6, AUFMT_DOLBY_5_1, 0, {8000, 48000}},
251 };
252
253 static int auvia_attach_codec(void *, struct ac97_codec_if *);
254 static int auvia_write_codec(void *, uint8_t, uint16_t);
255 static int auvia_read_codec(void *, uint8_t, uint16_t *);
256 static int auvia_reset_codec(void *);
257 static int auvia_waitready_codec(struct auvia_softc *sc);
258 static int auvia_waitvalid_codec(struct auvia_softc *sc);
259
260
261 static int
262 auvia_match(struct device *parent, struct cfdata *match, void *aux)
263 {
264 struct pci_attach_args *pa;
265
266 pa = (struct pci_attach_args *) aux;
267 if (PCI_VENDOR(pa->pa_id) != PCI_VENDOR_VIATECH)
268 return 0;
269 switch (PCI_PRODUCT(pa->pa_id)) {
270 case PCI_PRODUCT_VIATECH_VT82C686A_AC97:
271 case PCI_PRODUCT_VIATECH_VT8233_AC97:
272 break;
273 default:
274 return 0;
275 }
276
277 return 1;
278 }
279
280 static void
281 auvia_attach(struct device *parent, struct device *self, void *aux)
282 {
283 struct pci_attach_args *pa;
284 struct auvia_softc *sc;
285 const char *intrstr;
286 pci_chipset_tag_t pc;
287 pcitag_t pt;
288 pci_intr_handle_t ih;
289 bus_size_t iosize;
290 pcireg_t pr;
291 int r;
292 const char *revnum; /* VT823xx revision number */
293
294 pa = aux;
295 sc = (struct auvia_softc *)self;
296 intrstr = NULL;
297 pc = pa->pa_pc;
298 pt = pa->pa_tag;
299 revnum = NULL;
300
301 aprint_naive(": Audio controller\n");
302
303 sc->sc_play.sc_base = AUVIA_PLAY_BASE;
304 sc->sc_record.sc_base = AUVIA_RECORD_BASE;
305 if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_VIATECH_VT8233_AC97) {
306 sc->sc_flags |= AUVIA_FLAGS_VT8233;
307 sc->sc_play.sc_base = VIA8233_MP_BASE;
308 }
309
310 if (pci_mapreg_map(pa, 0x10, PCI_MAPREG_TYPE_IO, 0, &sc->sc_iot,
311 &sc->sc_ioh, NULL, &iosize)) {
312 aprint_error(": can't map i/o space\n");
313 return;
314 }
315
316 sc->sc_dmat = pa->pa_dmat;
317 sc->sc_pc = pc;
318 sc->sc_pt = pt;
319
320 r = PCI_REVISION(pa->pa_class);
321 if (sc->sc_flags & AUVIA_FLAGS_VT8233) {
322 snprintf(sc->sc_revision, sizeof(sc->sc_revision), "0x%02X", r);
323 switch(r) {
324 case VIA_REV_8233C:
325 /* 2 rec, 4 pb, 1 multi-pb */
326 revnum = "3C";
327 break;
328 case VIA_REV_8233:
329 /* 2 rec, 4 pb, 1 multi-pb, spdif */
330 revnum = "3";
331 break;
332 case VIA_REV_8233A:
333 /* 1 rec, 1 multi-pb, spdif */
334 revnum = "3A";
335 break;
336 default:
337 break;
338 }
339 if (r >= VIA_REV_8237)
340 revnum = "7";
341 else if (r >= VIA_REV_8235) /* 2 rec, 4 pb, 1 multi-pb, spdif */
342 revnum = "5";
343 aprint_normal(": VIA Technologies VT823%s AC'97 Audio "
344 "(rev %s)\n", revnum, sc->sc_revision);
345 } else {
346 sc->sc_revision[1] = '\0';
347 if (r == 0x20) {
348 sc->sc_revision[0] = 'H';
349 } else if ((r >= 0x10) && (r <= 0x14)) {
350 sc->sc_revision[0] = 'A' + (r - 0x10);
351 } else {
352 snprintf(sc->sc_revision, sizeof(sc->sc_revision),
353 "0x%02X", r);
354 }
355
356 aprint_normal(": VIA Technologies VT82C686A AC'97 Audio "
357 "(rev %s)\n", sc->sc_revision);
358 }
359
360 if (pci_intr_map(pa, &ih)) {
361 aprint_error(": couldn't map interrupt\n");
362 bus_space_unmap(sc->sc_iot, sc->sc_ioh, iosize);
363 return;
364 }
365 intrstr = pci_intr_string(pc, ih);
366
367 sc->sc_ih = pci_intr_establish(pc, ih, IPL_AUDIO, auvia_intr, sc);
368 if (sc->sc_ih == NULL) {
369 aprint_error("%s: couldn't establish interrupt",
370 sc->sc_dev.dv_xname);
371 if (intrstr != NULL)
372 aprint_normal(" at %s", intrstr);
373 aprint_normal("\n");
374 bus_space_unmap(sc->sc_iot, sc->sc_ioh, iosize);
375 return;
376 }
377
378 aprint_normal("%s: interrupting at %s\n", sc->sc_dev.dv_xname, intrstr);
379
380 /* disable SBPro compat & others */
381 pr = pci_conf_read(pc, pt, AUVIA_PCICONF_JUNK);
382
383 pr &= ~AUVIA_PCICONF_ENABLES; /* clear compat function enables */
384 /* XXX what to do about MIDI, FM, joystick? */
385
386 pr |= (AUVIA_PCICONF_ACLINKENAB | AUVIA_PCICONF_ACNOTRST
387 | AUVIA_PCICONF_ACVSR | AUVIA_PCICONF_ACSGD);
388
389 pr &= ~(AUVIA_PCICONF_ACFM | AUVIA_PCICONF_ACSB);
390
391 pci_conf_write(pc, pt, AUVIA_PCICONF_JUNK, pr);
392
393 sc->host_if.arg = sc;
394 sc->host_if.attach = auvia_attach_codec;
395 sc->host_if.read = auvia_read_codec;
396 sc->host_if.write = auvia_write_codec;
397 sc->host_if.reset = auvia_reset_codec;
398
399 if ((r = ac97_attach(&sc->host_if, self)) != 0) {
400 aprint_error("%s: can't attach codec (error 0x%X)\n",
401 sc->sc_dev.dv_xname, r);
402 pci_intr_disestablish(pc, sc->sc_ih);
403 bus_space_unmap(sc->sc_iot, sc->sc_ioh, iosize);
404 return;
405 }
406
407 /* setup audio_format */
408 memcpy(sc->sc_formats, auvia_formats, sizeof(auvia_formats));
409 if (sc->sc_play.sc_base != VIA8233_MP_BASE || !AC97_IS_4CH(sc->codec_if)) {
410 AUFMT_INVALIDATE(&sc->sc_formats[AUVIA_FORMATS_4CH_8]);
411 AUFMT_INVALIDATE(&sc->sc_formats[AUVIA_FORMATS_4CH_16]);
412 }
413 if (sc->sc_play.sc_base != VIA8233_MP_BASE || !AC97_IS_6CH(sc->codec_if)) {
414 AUFMT_INVALIDATE(&sc->sc_formats[AUVIA_FORMATS_6CH_8]);
415 AUFMT_INVALIDATE(&sc->sc_formats[AUVIA_FORMATS_6CH_16]);
416 }
417 if (AC97_IS_FIXED_RATE(sc->codec_if)) {
418 for (r = 0; r < AUVIA_NFORMATS; r++) {
419 sc->sc_formats[r].frequency_type = 1;
420 sc->sc_formats[r].frequency[0] = 48000;
421 }
422 }
423
424 if (0 != auconv_create_encodings(sc->sc_formats, AUVIA_NFORMATS,
425 &sc->sc_encodings)) {
426 sc->codec_if->vtbl->detach(sc->codec_if);
427 pci_intr_disestablish(pc, sc->sc_ih);
428 bus_space_unmap(sc->sc_iot, sc->sc_ioh, iosize);
429 return;
430 }
431
432 /* Watch for power change */
433 sc->sc_suspend = PWR_RESUME;
434 sc->sc_powerhook = powerhook_establish(auvia_powerhook, sc);
435
436 audio_attach_mi(&auvia_hw_if, sc, &sc->sc_dev);
437 return;
438 }
439
440 static int
441 auvia_attach_codec(void *addr, struct ac97_codec_if *cif)
442 {
443 struct auvia_softc *sc;
444
445 sc = addr;
446 sc->codec_if = cif;
447 return 0;
448 }
449
450 static int
451 auvia_reset_codec(void *addr)
452 {
453 struct auvia_softc *sc;
454 pcireg_t r;
455 int i;
456
457 /* perform a codec cold reset */
458 sc = addr;
459 r = pci_conf_read(sc->sc_pc, sc->sc_pt, AUVIA_PCICONF_JUNK);
460
461 r &= ~AUVIA_PCICONF_ACNOTRST; /* enable RESET (active low) */
462 pci_conf_write(sc->sc_pc, sc->sc_pt, AUVIA_PCICONF_JUNK, r);
463 delay(2);
464
465 r |= AUVIA_PCICONF_ACNOTRST; /* disable RESET (inactive high) */
466 pci_conf_write(sc->sc_pc, sc->sc_pt, AUVIA_PCICONF_JUNK, r);
467 delay(200);
468
469 for (i = 500000; i != 0 && !(pci_conf_read(sc->sc_pc, sc->sc_pt,
470 AUVIA_PCICONF_JUNK) & AUVIA_PCICONF_PRIVALID); i--)
471 DELAY(1);
472 if (i == 0) {
473 printf("%s: codec reset timed out\n", sc->sc_dev.dv_xname);
474 return ETIMEDOUT;
475 }
476 return 0;
477 }
478
479 static int
480 auvia_waitready_codec(struct auvia_softc *sc)
481 {
482 int i;
483
484 /* poll until codec not busy */
485 for (i = 0; (i < TIMEOUT) && (bus_space_read_4(sc->sc_iot, sc->sc_ioh,
486 AUVIA_CODEC_CTL) & AUVIA_CODEC_BUSY); i++)
487 delay(1);
488 if (i >= TIMEOUT) {
489 printf("%s: codec busy\n", sc->sc_dev.dv_xname);
490 return 1;
491 }
492
493 return 0;
494 }
495
496 static int
497 auvia_waitvalid_codec(struct auvia_softc *sc)
498 {
499 int i;
500
501 /* poll until codec valid */
502 for (i = 0; (i < TIMEOUT) && !(bus_space_read_4(sc->sc_iot, sc->sc_ioh,
503 AUVIA_CODEC_CTL) & AUVIA_CODEC_PRIVALID); i++)
504 delay(1);
505 if (i >= TIMEOUT) {
506 printf("%s: codec invalid\n", sc->sc_dev.dv_xname);
507 return 1;
508 }
509
510 return 0;
511 }
512
513 static int
514 auvia_write_codec(void *addr, u_int8_t reg, u_int16_t val)
515 {
516 struct auvia_softc *sc;
517
518 sc = addr;
519 if (auvia_waitready_codec(sc))
520 return 1;
521
522 bus_space_write_4(sc->sc_iot, sc->sc_ioh, AUVIA_CODEC_CTL,
523 AUVIA_CODEC_PRIVALID | AUVIA_CODEC_INDEX(reg) | val);
524
525 return 0;
526 }
527
528 static int
529 auvia_read_codec(void *addr, u_int8_t reg, u_int16_t *val)
530 {
531 struct auvia_softc *sc;
532
533 sc = addr;
534 if (auvia_waitready_codec(sc))
535 return 1;
536
537 bus_space_write_4(sc->sc_iot, sc->sc_ioh, AUVIA_CODEC_CTL,
538 AUVIA_CODEC_PRIVALID | AUVIA_CODEC_READ | AUVIA_CODEC_INDEX(reg));
539
540 if (auvia_waitready_codec(sc))
541 return 1;
542
543 if (auvia_waitvalid_codec(sc))
544 return 1;
545
546 *val = bus_space_read_2(sc->sc_iot, sc->sc_ioh, AUVIA_CODEC_CTL);
547
548 return 0;
549 }
550
551 static int
552 auvia_query_encoding(void *addr, struct audio_encoding *fp)
553 {
554 struct auvia_softc *sc;
555
556 sc = (struct auvia_softc *)addr;
557 return auconv_query_encoding(sc->sc_encodings, fp);
558 }
559
560 static void
561 auvia_set_params_sub(struct auvia_softc *sc, struct auvia_softc_chan *ch,
562 const audio_params_t *p)
563 {
564 uint32_t v;
565 uint16_t regval;
566
567 if (!(sc->sc_flags & AUVIA_FLAGS_VT8233)) {
568 regval = (p->channels == 2 ? AUVIA_RPMODE_STEREO : 0)
569 | (p->precision == 16 ?
570 AUVIA_RPMODE_16BIT : 0)
571 | AUVIA_RPMODE_INTR_FLAG | AUVIA_RPMODE_INTR_EOL
572 | AUVIA_RPMODE_AUTOSTART;
573 ch->sc_reg = regval;
574 } else if (ch->sc_base != VIA8233_MP_BASE) {
575 v = CH_READ4(sc, ch, VIA8233_RP_RATEFMT);
576 v &= ~(VIA8233_RATEFMT_48K | VIA8233_RATEFMT_STEREO
577 | VIA8233_RATEFMT_16BIT);
578
579 v |= VIA8233_RATEFMT_48K * (p->sample_rate / 20)
580 / (48000 / 20);
581 if (p->channels == 2)
582 v |= VIA8233_RATEFMT_STEREO;
583 if (p->precision == 16)
584 v |= VIA8233_RATEFMT_16BIT;
585
586 CH_WRITE4(sc, ch, VIA8233_RP_RATEFMT, v);
587 } else {
588 static const u_int32_t slottab[7] =
589 { 0, 0xff000011, 0xff000021, 0,
590 0xff004321, 0, 0xff436521};
591
592 regval = (p->precision == 16
593 ? VIA8233_MP_FORMAT_16BIT : VIA8233_MP_FORMAT_8BIT)
594 | (p->channels << 4);
595 CH_WRITE1(sc, ch, VIA8233_OFF_MP_FORMAT, regval);
596 CH_WRITE4(sc, ch, VIA8233_OFF_MP_STOP, slottab[p->channels]);
597 }
598 }
599
600 static int
601 auvia_set_params(void *addr, int setmode, int usemode,
602 audio_params_t *play, audio_params_t *rec,
603 stream_filter_list_t *pfil, stream_filter_list_t *rfil)
604 {
605 struct auvia_softc *sc;
606 struct auvia_softc_chan *ch;
607 struct audio_params *p;
608 struct ac97_codec_if* codec;
609 stream_filter_list_t *fil;
610 int reg, mode;
611 int index;
612
613 sc = addr;
614 codec = sc->codec_if;
615 /* for mode in (RECORD, PLAY) */
616 for (mode = AUMODE_RECORD; mode != -1;
617 mode = mode == AUMODE_RECORD ? AUMODE_PLAY : -1) {
618 if ((setmode & mode) == 0)
619 continue;
620
621 if (mode == AUMODE_PLAY ) {
622 p = play;
623 ch = &sc->sc_play;
624 reg = AC97_REG_PCM_FRONT_DAC_RATE;
625 fil = pfil;
626 } else {
627 p = rec;
628 ch = &sc->sc_record;
629 reg = AC97_REG_PCM_LR_ADC_RATE;
630 fil = rfil;
631 }
632
633 if (p->sample_rate < 4000 || p->sample_rate > 48000 ||
634 (p->precision != 8 && p->precision != 16))
635 return (EINVAL);
636 index = auconv_set_converter(sc->sc_formats, AUVIA_NFORMATS,
637 mode, p, TRUE, fil);
638 if (index < 0)
639 return EINVAL;
640 if (fil->req_size > 0)
641 p = &fil->filters[0].param;
642 if (!AC97_IS_FIXED_RATE(codec)) {
643 if (codec->vtbl->set_rate(codec, reg, &p->sample_rate))
644 return EINVAL;
645 reg = AC97_REG_PCM_SURR_DAC_RATE;
646 if (p->channels >= 4
647 && codec->vtbl->set_rate(codec, reg,
648 &p->sample_rate))
649 return EINVAL;
650 reg = AC97_REG_PCM_LFE_DAC_RATE;
651 if (p->channels == 6
652 && codec->vtbl->set_rate(codec, reg,
653 &p->sample_rate))
654 return EINVAL;
655 }
656 auvia_set_params_sub(sc, ch, p);
657 }
658
659 return 0;
660 }
661
662 static int
663 auvia_round_blocksize(void *addr, int blk,
664 int mode, const audio_params_t *param)
665 {
666 struct auvia_softc *sc;
667
668 sc = addr;
669 /* XXX VT823x might have the limitation of dma_ops size */
670 if (sc->sc_flags & AUVIA_FLAGS_VT8233 && blk < 288)
671 blk = 288;
672
673 return (blk & -32);
674 }
675
676 static int
677 auvia_halt_output(void *addr)
678 {
679 struct auvia_softc *sc;
680 struct auvia_softc_chan *ch;
681
682 sc = addr;
683 ch = &(sc->sc_play);
684 CH_WRITE1(sc, ch, AUVIA_RP_CONTROL, AUVIA_RPCTRL_TERMINATE);
685 ch->sc_intr = NULL;
686 return 0;
687 }
688
689 static int
690 auvia_halt_input(void *addr)
691 {
692 struct auvia_softc *sc;
693 struct auvia_softc_chan *ch;
694
695 sc = addr;
696 ch = &(sc->sc_record);
697 CH_WRITE1(sc, ch, AUVIA_RP_CONTROL, AUVIA_RPCTRL_TERMINATE);
698 ch->sc_intr = NULL;
699 return 0;
700 }
701
702 static int
703 auvia_getdev(void *addr, struct audio_device *retp)
704 {
705 struct auvia_softc *sc;
706
707 if (retp) {
708 sc = addr;
709 if (sc->sc_flags & AUVIA_FLAGS_VT8233) {
710 strncpy(retp->name, "VIA VT823x",
711 sizeof(retp->name));
712 } else {
713 strncpy(retp->name, "VIA VT82C686A",
714 sizeof(retp->name));
715 }
716 strncpy(retp->version, sc->sc_revision, sizeof(retp->version));
717 strncpy(retp->config, "auvia", sizeof(retp->config));
718 }
719
720 return 0;
721 }
722
723 static int
724 auvia_set_port(void *addr, mixer_ctrl_t *cp)
725 {
726 struct auvia_softc *sc;
727
728 sc = addr;
729 return sc->codec_if->vtbl->mixer_set_port(sc->codec_if, cp);
730 }
731
732 static int
733 auvia_get_port(void *addr, mixer_ctrl_t *cp)
734 {
735 struct auvia_softc *sc;
736
737 sc = addr;
738 return sc->codec_if->vtbl->mixer_get_port(sc->codec_if, cp);
739 }
740
741 static int
742 auvia_query_devinfo(void *addr, mixer_devinfo_t *dip)
743 {
744 struct auvia_softc *sc;
745
746 sc = addr;
747 return sc->codec_if->vtbl->query_devinfo(sc->codec_if, dip);
748 }
749
750 static void *
751 auvia_malloc(void *addr, int direction, size_t size, struct malloc_type * pool,
752 int flags)
753 {
754 struct auvia_softc *sc;
755 struct auvia_dma *p;
756 int error;
757 int rseg;
758
759 p = malloc(sizeof(*p), pool, flags);
760 if (!p)
761 return 0;
762 sc = addr;
763 p->size = size;
764 if ((error = bus_dmamem_alloc(sc->sc_dmat, size, PAGE_SIZE, 0, &p->seg,
765 1, &rseg, BUS_DMA_NOWAIT)) != 0) {
766 printf("%s: unable to allocate DMA, error = %d\n",
767 sc->sc_dev.dv_xname, error);
768 goto fail_alloc;
769 }
770
771 if ((error = bus_dmamem_map(sc->sc_dmat, &p->seg, rseg, size, &p->addr,
772 BUS_DMA_NOWAIT | BUS_DMA_COHERENT)) != 0) {
773 printf("%s: unable to map DMA, error = %d\n",
774 sc->sc_dev.dv_xname, error);
775 goto fail_map;
776 }
777
778 if ((error = bus_dmamap_create(sc->sc_dmat, size, 1, size, 0,
779 BUS_DMA_NOWAIT, &p->map)) != 0) {
780 printf("%s: unable to create DMA map, error = %d\n",
781 sc->sc_dev.dv_xname, error);
782 goto fail_create;
783 }
784
785 if ((error = bus_dmamap_load(sc->sc_dmat, p->map, p->addr, size, NULL,
786 BUS_DMA_NOWAIT)) != 0) {
787 printf("%s: unable to load DMA map, error = %d\n",
788 sc->sc_dev.dv_xname, error);
789 goto fail_load;
790 }
791
792 p->next = sc->sc_dmas;
793 sc->sc_dmas = p;
794
795 return p->addr;
796
797
798 fail_load:
799 bus_dmamap_destroy(sc->sc_dmat, p->map);
800 fail_create:
801 bus_dmamem_unmap(sc->sc_dmat, p->addr, size);
802 fail_map:
803 bus_dmamem_free(sc->sc_dmat, &p->seg, 1);
804 fail_alloc:
805 free(p, pool);
806 return NULL;
807 }
808
809 static void
810 auvia_free(void *addr, void *ptr, struct malloc_type *pool)
811 {
812 struct auvia_softc *sc;
813 struct auvia_dma **pp, *p;
814
815 sc = addr;
816 for (pp = &(sc->sc_dmas); (p = *pp) != NULL; pp = &p->next)
817 if (p->addr == ptr) {
818 bus_dmamap_unload(sc->sc_dmat, p->map);
819 bus_dmamap_destroy(sc->sc_dmat, p->map);
820 bus_dmamem_unmap(sc->sc_dmat, p->addr, p->size);
821 bus_dmamem_free(sc->sc_dmat, &p->seg, 1);
822
823 *pp = p->next;
824 free(p, pool);
825 return;
826 }
827
828 panic("auvia_free: trying to free unallocated memory");
829 }
830
831 static size_t
832 auvia_round_buffersize(void *addr, int direction, size_t size)
833 {
834
835 return size;
836 }
837
838 static paddr_t
839 auvia_mappage(void *addr, void *mem, off_t off, int prot)
840 {
841 struct auvia_softc *sc;
842 struct auvia_dma *p;
843
844 if (off < 0)
845 return -1;
846 sc = addr;
847 for (p = sc->sc_dmas; p && p->addr != mem; p = p->next)
848 continue;
849
850 if (!p)
851 return -1;
852
853 return bus_dmamem_mmap(sc->sc_dmat, &p->seg, 1, off, prot,
854 BUS_DMA_WAITOK);
855 }
856
857 static int
858 auvia_get_props(void *addr)
859 {
860 struct auvia_softc *sc;
861 int props;
862
863 props = AUDIO_PROP_INDEPENDENT | AUDIO_PROP_FULLDUPLEX;
864 sc = addr;
865 /*
866 * Even if the codec is fixed-rate, set_param() succeeds for any sample
867 * rate because of aurateconv. Applications can't know what rate the
868 * device can process in the case of mmap().
869 */
870 if (!AC97_IS_FIXED_RATE(sc->codec_if))
871 props |= AUDIO_PROP_MMAP;
872 return props;
873 }
874
875 static int
876 auvia_build_dma_ops(struct auvia_softc *sc, struct auvia_softc_chan *ch,
877 struct auvia_dma *p, void *start, void *end, int blksize)
878 {
879 struct auvia_dma_op *op;
880 struct auvia_dma *dp;
881 bus_addr_t s;
882 size_t l;
883 int segs;
884
885 s = p->map->dm_segs[0].ds_addr;
886 l = ((char *)end - (char *)start);
887 segs = (l + blksize - 1) / blksize;
888
889 if (segs > (ch->sc_dma_op_count)) {
890 /* if old list was too small, free it */
891 if (ch->sc_dma_ops) {
892 auvia_free(sc, ch->sc_dma_ops, M_DEVBUF);
893 }
894
895 ch->sc_dma_ops = auvia_malloc(sc, 0,
896 sizeof(struct auvia_dma_op) * segs, M_DEVBUF, M_WAITOK);
897
898 if (ch->sc_dma_ops == NULL) {
899 printf("%s: couldn't build dmaops\n", sc->sc_dev.dv_xname);
900 return 1;
901 }
902
903 for (dp = sc->sc_dmas;
904 dp && dp->addr != (void *)(ch->sc_dma_ops);
905 dp = dp->next)
906 continue;
907
908 if (!dp)
909 panic("%s: build_dma_ops: where'd my memory go??? "
910 "address (%p)\n", sc->sc_dev.dv_xname,
911 ch->sc_dma_ops);
912
913 ch->sc_dma_op_count = segs;
914 ch->sc_dma_ops_dma = dp;
915 }
916
917 dp = ch->sc_dma_ops_dma;
918 op = ch->sc_dma_ops;
919
920 while (l) {
921 op->ptr = s;
922 l = l - blksize;
923 if (!l) {
924 /* if last block */
925 op->flags = AUVIA_DMAOP_EOL | blksize;
926 } else {
927 op->flags = AUVIA_DMAOP_FLAG | blksize;
928 }
929 s += blksize;
930 op++;
931 }
932
933 return 0;
934 }
935
936
937 static int
938 auvia_trigger_output(void *addr, void *start, void *end,
939 int blksize, void (*intr)(void *), void *arg,
940 const audio_params_t *param)
941 {
942 struct auvia_softc *sc;
943 struct auvia_softc_chan *ch;
944 struct auvia_dma *p;
945
946 sc = addr;
947 ch = &(sc->sc_play);
948 for (p = sc->sc_dmas; p && p->addr != start; p = p->next)
949 continue;
950
951 if (!p)
952 panic("auvia_trigger_output: request with bad start "
953 "address (%p)", start);
954
955 if (auvia_build_dma_ops(sc, ch, p, start, end, blksize)) {
956 return 1;
957 }
958
959 ch->sc_intr = intr;
960 ch->sc_arg = arg;
961
962 CH_WRITE4(sc, ch, AUVIA_RP_DMAOPS_BASE,
963 ch->sc_dma_ops_dma->map->dm_segs[0].ds_addr);
964
965 if (sc->sc_flags & AUVIA_FLAGS_VT8233) {
966 if (ch->sc_base != VIA8233_MP_BASE) {
967 CH_WRITE1(sc, ch, VIA8233_RP_DXS_LVOL, 0);
968 CH_WRITE1(sc, ch, VIA8233_RP_DXS_RVOL, 0);
969 }
970 CH_WRITE1(sc, ch, AUVIA_RP_CONTROL,
971 AUVIA_RPCTRL_START | AUVIA_RPCTRL_AUTOSTART |
972 AUVIA_RPCTRL_STOP | AUVIA_RPCTRL_EOL | AUVIA_RPCTRL_FLAG);
973 } else {
974 CH_WRITE1(sc, ch, AUVIA_RP_MODE, ch->sc_reg);
975 CH_WRITE1(sc, ch, AUVIA_RP_CONTROL, AUVIA_RPCTRL_START);
976 }
977
978 return 0;
979 }
980
981 static int
982 auvia_trigger_input(void *addr, void *start, void *end,
983 int blksize, void (*intr)(void *), void *arg,
984 const audio_params_t *param)
985 {
986 struct auvia_softc *sc;
987 struct auvia_softc_chan *ch;
988 struct auvia_dma *p;
989
990 sc = addr;
991 ch = &(sc->sc_record);
992 for (p = sc->sc_dmas; p && p->addr != start; p = p->next)
993 continue;
994
995 if (!p)
996 panic("auvia_trigger_input: request with bad start "
997 "address (%p)", start);
998
999 if (auvia_build_dma_ops(sc, ch, p, start, end, blksize)) {
1000 return 1;
1001 }
1002
1003 ch->sc_intr = intr;
1004 ch->sc_arg = arg;
1005
1006 CH_WRITE4(sc, ch, AUVIA_RP_DMAOPS_BASE,
1007 ch->sc_dma_ops_dma->map->dm_segs[0].ds_addr);
1008
1009 if (sc->sc_flags & AUVIA_FLAGS_VT8233) {
1010 CH_WRITE1(sc, ch, VIA8233_RP_DXS_LVOL, 0);
1011 CH_WRITE1(sc, ch, VIA8233_RP_DXS_RVOL, 0);
1012 CH_WRITE1(sc, ch, AUVIA_RP_CONTROL,
1013 AUVIA_RPCTRL_START | AUVIA_RPCTRL_AUTOSTART |
1014 AUVIA_RPCTRL_STOP | AUVIA_RPCTRL_EOL | AUVIA_RPCTRL_FLAG);
1015 } else {
1016 CH_WRITE1(sc, ch, AUVIA_RP_MODE, ch->sc_reg);
1017 CH_WRITE1(sc, ch, AUVIA_RP_CONTROL, AUVIA_RPCTRL_START);
1018 }
1019
1020 return 0;
1021 }
1022
1023 static int
1024 auvia_intr(void *arg)
1025 {
1026 struct auvia_softc *sc;
1027 struct auvia_softc_chan *ch;
1028 u_int8_t r;
1029 int rval;
1030
1031 sc = arg;
1032 rval = 0;
1033
1034 ch = &sc->sc_record;
1035 r = CH_READ1(sc, ch, AUVIA_RP_STAT);
1036 if (r & AUVIA_RPSTAT_INTR) {
1037 if (sc->sc_record.sc_intr)
1038 sc->sc_record.sc_intr(sc->sc_record.sc_arg);
1039
1040 /* clear interrupts */
1041 CH_WRITE1(sc, ch, AUVIA_RP_STAT, AUVIA_RPSTAT_INTR);
1042 rval = 1;
1043 }
1044
1045 ch = &sc->sc_play;
1046 r = CH_READ1(sc, ch, AUVIA_RP_STAT);
1047 if (r & AUVIA_RPSTAT_INTR) {
1048 if (sc->sc_play.sc_intr)
1049 sc->sc_play.sc_intr(sc->sc_play.sc_arg);
1050
1051 /* clear interrupts */
1052 CH_WRITE1(sc, ch, AUVIA_RP_STAT, AUVIA_RPSTAT_INTR);
1053 rval = 1;
1054 }
1055
1056 return rval;
1057 }
1058
1059 static void
1060 auvia_powerhook(int why, void *addr)
1061 {
1062 struct auvia_softc *sc;
1063
1064 sc = addr;
1065 switch (why) {
1066 case PWR_SUSPEND:
1067 case PWR_STANDBY:
1068 /* Power down */
1069 sc->sc_suspend = why;
1070 break;
1071
1072 case PWR_RESUME:
1073 /* Wake up */
1074 if (sc->sc_suspend == PWR_RESUME) {
1075 printf("%s: resume without suspend.\n",
1076 sc->sc_dev.dv_xname);
1077 sc->sc_suspend = why;
1078 return;
1079 }
1080 sc->sc_suspend = why;
1081 auvia_reset_codec(sc);
1082 DELAY(1000);
1083 (sc->codec_if->vtbl->restore_ports)(sc->codec_if);
1084 break;
1085
1086 case PWR_SOFTSUSPEND:
1087 case PWR_SOFTSTANDBY:
1088 case PWR_SOFTRESUME:
1089 break;
1090 }
1091 }
1092