1 /* $NetBSD: auvia.c,v 1.70 2009/11/26 15:17:08 njoly Exp $ */
4 * Copyright (c) 2000 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
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.
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
33 * VIA Technologies VT82C686A / VT8233 / VT8235 Southbridge Audio Driver
35 * Documentation links:
37 * ftp://ftp.alsa-project.org/pub/manuals/via/686a.pdf
38 * ftp://ftp.alsa-project.org/pub/manuals/general/ac97r21.pdf
39 * ftp://ftp.alsa-project.org/pub/manuals/ad/AD1881_0.pdf (example AC'97 codec)
42 #include <sys/cdefs.h>
43 __KERNEL_RCSID(0, "$NetBSD: auvia.c,v 1.70 2009/11/26 15:17:08 njoly Exp $");
45 #include <sys/param.h>
46 #include <sys/systm.h>
47 #include <sys/malloc.h>
48 #include <sys/device.h>
49 #include <sys/audioio.h>
51 #include <uvm/uvm_extern.h>
53 #include <dev/pci/pcidevs.h>
54 #include <dev/pci/pcivar.h>
56 #include <dev/audio_if.h>
57 #include <dev/mulaw.h>
58 #include <dev/auconv.h>
60 #include <dev/ic/ac97reg.h>
61 #include <dev/ic/ac97var.h>
63 #include <dev/pci/auviavar.h>
66 struct auvia_dma
*next
;
70 bus_dma_segment_t seg
;
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)
82 static int auvia_match(device_t
, cfdata_t
, void *);
83 static void auvia_attach(device_t
, device_t
, void *);
84 static int auvia_detach(device_t
, int);
85 static void auvia_childdet(device_t
, device_t
);
86 static int auvia_open(void *, int);
87 static void auvia_close(void *);
88 static int auvia_query_encoding(void *, struct audio_encoding
*);
89 static void auvia_set_params_sub(struct auvia_softc
*,
90 struct auvia_softc_chan
*,
91 const audio_params_t
*);
92 static int auvia_set_params(void *, int, int, audio_params_t
*,
93 audio_params_t
*, stream_filter_list_t
*,
94 stream_filter_list_t
*);
95 static int auvia_round_blocksize(void *, int, int, const audio_params_t
*);
96 static int auvia_halt_output(void *);
97 static int auvia_halt_input(void *);
98 static int auvia_getdev(void *, struct audio_device
*);
99 static int auvia_set_port(void *, mixer_ctrl_t
*);
100 static int auvia_get_port(void *, mixer_ctrl_t
*);
101 static int auvia_query_devinfo(void *, mixer_devinfo_t
*);
102 static void * auvia_malloc(void *, int, size_t, struct malloc_type
*, int);
103 static void auvia_free(void *, void *, struct malloc_type
*);
104 static size_t auvia_round_buffersize(void *, int, size_t);
105 static paddr_t
auvia_mappage(void *, void *, off_t
, int);
106 static int auvia_get_props(void *);
107 static int auvia_build_dma_ops(struct auvia_softc
*,
108 struct auvia_softc_chan
*,
109 struct auvia_dma
*, void *, void *, int);
110 static int auvia_trigger_output(void *, void *, void *, int,
111 void (*)(void *), void *,
112 const audio_params_t
*);
113 static int auvia_trigger_input(void *, void *, void *, int,
114 void (*)(void *), void *,
115 const audio_params_t
*);
116 static bool auvia_resume(device_t
, pmf_qual_t
);
117 static int auvia_intr(void *);
119 static int auvia_attach_codec(void *, struct ac97_codec_if
*);
120 static int auvia_write_codec(void *, uint8_t, uint16_t);
121 static int auvia_read_codec(void *, uint8_t, uint16_t *);
122 static int auvia_reset_codec(void *);
123 static int auvia_waitready_codec(struct auvia_softc
*);
124 static int auvia_waitvalid_codec(struct auvia_softc
*);
125 static void auvia_spdif_event(void *, bool);
127 CFATTACH_DECL2_NEW(auvia
, sizeof (struct auvia_softc
),
128 auvia_match
, auvia_attach
, auvia_detach
, NULL
, NULL
, auvia_childdet
);
130 /* VIA VT823xx revision number */
131 #define VIA_REV_8233PRE 0x10
132 #define VIA_REV_8233C 0x20
133 #define VIA_REV_8233 0x30
134 #define VIA_REV_8233A 0x40
135 #define VIA_REV_8235 0x50
136 #define VIA_REV_8237 0x60
138 #define AUVIA_PCICONF_JUNK 0x40
139 #define AUVIA_PCICONF_ENABLES 0x00FF0000 /* reg 42 mask */
140 #define AUVIA_PCICONF_ACLINKENAB 0x00008000 /* ac link enab */
141 #define AUVIA_PCICONF_ACNOTRST 0x00004000 /* ~(ac reset) */
142 #define AUVIA_PCICONF_ACSYNC 0x00002000 /* ac sync */
143 #define AUVIA_PCICONF_ACVSR 0x00000800 /* var. samp. rate */
144 #define AUVIA_PCICONF_ACSGD 0x00000400 /* SGD enab */
145 #define AUVIA_PCICONF_ACFM 0x00000200 /* FM enab */
146 #define AUVIA_PCICONF_ACSB 0x00000100 /* SB enab */
147 #define AUVIA_PCICONF_PRIVALID 0x00000001 /* primary codec rdy */
149 #define AUVIA_PLAY_BASE 0x00
150 #define AUVIA_RECORD_BASE 0x10
152 /* *_RP_* are offsets from AUVIA_PLAY_BASE or AUVIA_RECORD_BASE */
153 #define AUVIA_RP_STAT 0x00
154 #define AUVIA_RPSTAT_INTR 0x03
155 #define AUVIA_RP_CONTROL 0x01
156 #define AUVIA_RPCTRL_START 0x80
157 #define AUVIA_RPCTRL_TERMINATE 0x40
158 #define AUVIA_RPCTRL_AUTOSTART 0x20
159 /* The following are 8233 specific */
160 #define AUVIA_RPCTRL_STOP 0x04
161 #define AUVIA_RPCTRL_EOL 0x02
162 #define AUVIA_RPCTRL_FLAG 0x01
163 #define AUVIA_RP_MODE 0x02 /* 82c686 specific */
164 #define AUVIA_RPMODE_INTR_FLAG 0x01
165 #define AUVIA_RPMODE_INTR_EOL 0x02
166 #define AUVIA_RPMODE_STEREO 0x10
167 #define AUVIA_RPMODE_16BIT 0x20
168 #define AUVIA_RPMODE_AUTOSTART 0x80
169 #define AUVIA_RP_DMAOPS_BASE 0x04
171 #define VIA8233_RP_DXS_LVOL 0x02
172 #define VIA8233_RP_DXS_RVOL 0x03
173 #define VIA8233_RP_RATEFMT 0x08
174 #define VIA8233_RATEFMT_48K 0xfffff
175 #define VIA8233_RATEFMT_STEREO 0x00100000
176 #define VIA8233_RATEFMT_16BIT 0x00200000
178 #define VIA_RP_DMAOPS_COUNT 0x0c
180 #define VIA8233_MP_BASE 0x40
181 /* STAT, CONTROL, DMAOPS_BASE, DMAOPS_COUNT are valid */
182 #define VIA8233_OFF_MP_FORMAT 0x02
183 #define VIA8233_MP_FORMAT_8BIT 0x00
184 #define VIA8233_MP_FORMAT_16BIT 0x80
185 #define VIA8233_MP_FORMAT_CHANNLE_MASK 0x70 /* 1, 2, 4, 6 */
186 #define VIA8233_OFF_MP_SCRATCH 0x03
187 #define VIA8233_OFF_MP_STOP 0x08
189 #define VIA8233_WR_BASE 0x60
191 #define AUVIA_CODEC_CTL 0x80
192 #define AUVIA_CODEC_READ 0x00800000
193 #define AUVIA_CODEC_BUSY 0x01000000
194 #define AUVIA_CODEC_PRIVALID 0x02000000
195 #define AUVIA_CODEC_INDEX(x) ((x)<<16)
197 #define CH_WRITE1(sc, ch, off, v) \
198 bus_space_write_1((sc)->sc_iot, (sc)->sc_ioh, (ch)->sc_base + (off), v)
199 #define CH_WRITE4(sc, ch, off, v) \
200 bus_space_write_4((sc)->sc_iot, (sc)->sc_ioh, (ch)->sc_base + (off), v)
201 #define CH_READ1(sc, ch, off) \
202 bus_space_read_1((sc)->sc_iot, (sc)->sc_ioh, (ch)->sc_base + (off))
203 #define CH_READ4(sc, ch, off) \
204 bus_space_read_4((sc)->sc_iot, (sc)->sc_ioh, (ch)->sc_base + (off))
208 static const struct audio_hw_if auvia_hw_if
= {
212 auvia_query_encoding
,
214 auvia_round_blocksize
,
215 NULL
, /* commit_settings */
216 NULL
, /* init_output */
217 NULL
, /* init_input */
218 NULL
, /* start_output */
219 NULL
, /* start_input */
222 NULL
, /* speaker_ctl */
230 auvia_round_buffersize
,
233 auvia_trigger_output
,
235 NULL
, /* dev_ioctl */
236 NULL
, /* powerstate */
239 #define AUVIA_FORMATS_4CH_16 2
240 #define AUVIA_FORMATS_6CH_16 3
241 #define AUVIA_FORMATS_4CH_8 6
242 #define AUVIA_FORMATS_6CH_8 7
243 static const struct audio_format auvia_formats
[AUVIA_NFORMATS
] = {
244 {NULL
, AUMODE_PLAY
| AUMODE_RECORD
, AUDIO_ENCODING_SLINEAR_LE
, 16, 16,
245 1, AUFMT_MONAURAL
, 0, {8000, 48000}},
246 {NULL
, AUMODE_PLAY
| AUMODE_RECORD
, AUDIO_ENCODING_SLINEAR_LE
, 16, 16,
247 2, AUFMT_STEREO
, 0, {8000, 48000}},
248 {NULL
, AUMODE_PLAY
, AUDIO_ENCODING_SLINEAR_LE
, 16, 16,
249 4, AUFMT_SURROUND4
, 0, {8000, 48000}},
250 {NULL
, AUMODE_PLAY
, AUDIO_ENCODING_SLINEAR_LE
, 16, 16,
251 6, AUFMT_DOLBY_5_1
, 0, {8000, 48000}},
252 {NULL
, AUMODE_PLAY
| AUMODE_RECORD
, AUDIO_ENCODING_ULINEAR_LE
, 8, 8,
253 1, AUFMT_MONAURAL
, 0, {8000, 48000}},
254 {NULL
, AUMODE_PLAY
| AUMODE_RECORD
, AUDIO_ENCODING_ULINEAR_LE
, 8, 8,
255 2, AUFMT_STEREO
, 0, {8000, 48000}},
256 {NULL
, AUMODE_PLAY
, AUDIO_ENCODING_ULINEAR_LE
, 8, 8,
257 4, AUFMT_SURROUND4
, 0, {8000, 48000}},
258 {NULL
, AUMODE_PLAY
, AUDIO_ENCODING_SLINEAR_LE
, 8, 8,
259 6, AUFMT_DOLBY_5_1
, 0, {8000, 48000}},
262 #define AUVIA_SPDIF_NFORMATS 1
263 static const struct audio_format auvia_spdif_formats
[AUVIA_SPDIF_NFORMATS
] = {
264 {NULL
, AUMODE_PLAY
| AUMODE_RECORD
, AUDIO_ENCODING_SLINEAR_LE
, 16, 16,
265 2, AUFMT_STEREO
, 1, {48000}},
270 auvia_match(device_t parent
, cfdata_t match
, void *aux
)
272 struct pci_attach_args
*pa
;
274 pa
= (struct pci_attach_args
*) aux
;
275 if (PCI_VENDOR(pa
->pa_id
) != PCI_VENDOR_VIATECH
)
277 switch (PCI_PRODUCT(pa
->pa_id
)) {
278 case PCI_PRODUCT_VIATECH_VT82C686A_AC97
:
279 case PCI_PRODUCT_VIATECH_VT8233_AC97
:
289 auvia_childdet(device_t self
, device_t child
)
291 /* we hold no child references, so do nothing */
295 auvia_detach(device_t self
, int flags
)
298 struct auvia_softc
*sc
= device_private(self
);
300 if ((rc
= config_detach_children(self
, flags
)) != 0)
303 pmf_device_deregister(self
);
305 auconv_delete_encodings(sc
->sc_encodings
);
306 auconv_delete_encodings(sc
->sc_spdif_encodings
);
308 if (sc
->codec_if
!= NULL
)
309 sc
->codec_if
->vtbl
->detach(sc
->codec_if
);
311 /* XXX restore compatibility? */
313 if (sc
->sc_ih
!= NULL
)
314 pci_intr_disestablish(sc
->sc_pc
, sc
->sc_ih
);
316 bus_space_unmap(sc
->sc_iot
, sc
->sc_ioh
, sc
->sc_iosize
);
322 auvia_attach(device_t parent
, device_t self
, void *aux
)
324 struct pci_attach_args
*pa
;
325 struct auvia_softc
*sc
;
327 pci_chipset_tag_t pc
;
329 pci_intr_handle_t ih
;
332 const char *revnum
; /* VT823xx revision number */
335 sc
= device_private(self
);
342 aprint_naive(": Audio controller\n");
344 sc
->sc_play
.sc_base
= AUVIA_PLAY_BASE
;
345 sc
->sc_record
.sc_base
= AUVIA_RECORD_BASE
;
346 if (PCI_PRODUCT(pa
->pa_id
) == PCI_PRODUCT_VIATECH_VT8233_AC97
) {
347 sc
->sc_flags
|= AUVIA_FLAGS_VT8233
;
348 sc
->sc_play
.sc_base
= VIA8233_MP_BASE
;
349 sc
->sc_record
.sc_base
= VIA8233_WR_BASE
;
352 if (pci_mapreg_map(pa
, 0x10, PCI_MAPREG_TYPE_IO
, 0, &sc
->sc_iot
,
353 &sc
->sc_ioh
, NULL
, &sc
->sc_iosize
)) {
354 aprint_error(": can't map i/o space\n");
358 sc
->sc_dmat
= pa
->pa_dmat
;
362 r
= PCI_REVISION(pa
->pa_class
);
363 if (sc
->sc_flags
& AUVIA_FLAGS_VT8233
) {
364 snprintf(sc
->sc_revision
, sizeof(sc
->sc_revision
), "0x%02X", r
);
366 case VIA_REV_8233PRE
:
367 /* same as 8233, but should not be in the market */
371 /* 2 rec, 4 pb, 1 multi-pb */
375 /* 2 rec, 4 pb, 1 multi-pb, spdif */
379 /* 1 rec, 1 multi-pb, spdif */
385 if (r
>= VIA_REV_8237
)
387 else if (r
>= VIA_REV_8235
) /* 2 rec, 4 pb, 1 multi-pb, spdif */
389 aprint_normal(": VIA Technologies VT823%s AC'97 Audio "
390 "(rev %s)\n", revnum
, sc
->sc_revision
);
392 sc
->sc_revision
[1] = '\0';
394 sc
->sc_revision
[0] = 'H';
395 } else if ((r
>= 0x10) && (r
<= 0x14)) {
396 sc
->sc_revision
[0] = 'A' + (r
- 0x10);
398 snprintf(sc
->sc_revision
, sizeof(sc
->sc_revision
),
402 aprint_normal(": VIA Technologies VT82C686A AC'97 Audio "
403 "(rev %s)\n", sc
->sc_revision
);
406 if (pci_intr_map(pa
, &ih
)) {
407 aprint_error(": couldn't map interrupt\n");
408 bus_space_unmap(sc
->sc_iot
, sc
->sc_ioh
, sc
->sc_iosize
);
411 intrstr
= pci_intr_string(pc
, ih
);
413 sc
->sc_ih
= pci_intr_establish(pc
, ih
, IPL_AUDIO
, auvia_intr
, sc
);
414 if (sc
->sc_ih
== NULL
) {
415 aprint_error_dev(sc
->sc_dev
, "couldn't establish interrupt");
417 aprint_error(" at %s", intrstr
);
419 bus_space_unmap(sc
->sc_iot
, sc
->sc_ioh
, sc
->sc_iosize
);
423 aprint_normal_dev(sc
->sc_dev
, "interrupting at %s\n", intrstr
);
425 /* disable SBPro compat & others */
426 pr
= pci_conf_read(pc
, pt
, AUVIA_PCICONF_JUNK
);
428 pr
&= ~AUVIA_PCICONF_ENABLES
; /* clear compat function enables */
429 /* XXX what to do about MIDI, FM, joystick? */
431 pr
|= (AUVIA_PCICONF_ACLINKENAB
| AUVIA_PCICONF_ACNOTRST
432 | AUVIA_PCICONF_ACVSR
| AUVIA_PCICONF_ACSGD
);
434 pr
&= ~(AUVIA_PCICONF_ACFM
| AUVIA_PCICONF_ACSB
);
436 pci_conf_write(pc
, pt
, AUVIA_PCICONF_JUNK
, pr
);
438 sc
->host_if
.arg
= sc
;
439 sc
->host_if
.attach
= auvia_attach_codec
;
440 sc
->host_if
.read
= auvia_read_codec
;
441 sc
->host_if
.write
= auvia_write_codec
;
442 sc
->host_if
.reset
= auvia_reset_codec
;
443 sc
->host_if
.spdif_event
= auvia_spdif_event
;
445 if ((r
= ac97_attach(&sc
->host_if
, self
)) != 0) {
446 aprint_error_dev(sc
->sc_dev
, "can't attach codec (error 0x%X)\n", r
);
447 pci_intr_disestablish(pc
, sc
->sc_ih
);
448 bus_space_unmap(sc
->sc_iot
, sc
->sc_ioh
, sc
->sc_iosize
);
452 /* setup audio_format */
453 memcpy(sc
->sc_formats
, auvia_formats
, sizeof(auvia_formats
));
454 if (sc
->sc_play
.sc_base
!= VIA8233_MP_BASE
|| !AC97_IS_4CH(sc
->codec_if
)) {
455 AUFMT_INVALIDATE(&sc
->sc_formats
[AUVIA_FORMATS_4CH_8
]);
456 AUFMT_INVALIDATE(&sc
->sc_formats
[AUVIA_FORMATS_4CH_16
]);
458 if (sc
->sc_play
.sc_base
!= VIA8233_MP_BASE
|| !AC97_IS_6CH(sc
->codec_if
)) {
459 AUFMT_INVALIDATE(&sc
->sc_formats
[AUVIA_FORMATS_6CH_8
]);
460 AUFMT_INVALIDATE(&sc
->sc_formats
[AUVIA_FORMATS_6CH_16
]);
462 if (AC97_IS_FIXED_RATE(sc
->codec_if
)) {
463 for (r
= 0; r
< AUVIA_NFORMATS
; r
++) {
464 sc
->sc_formats
[r
].frequency_type
= 1;
465 sc
->sc_formats
[r
].frequency
[0] = 48000;
469 if (0 != auconv_create_encodings(sc
->sc_formats
, AUVIA_NFORMATS
,
470 &sc
->sc_encodings
)) {
471 sc
->codec_if
->vtbl
->detach(sc
->codec_if
);
472 pci_intr_disestablish(pc
, sc
->sc_ih
);
473 bus_space_unmap(sc
->sc_iot
, sc
->sc_ioh
, sc
->sc_iosize
);
474 aprint_error_dev(sc
->sc_dev
, "can't create encodings\n");
477 if (0 != auconv_create_encodings(auvia_spdif_formats
,
478 AUVIA_SPDIF_NFORMATS
, &sc
->sc_spdif_encodings
)) {
479 sc
->codec_if
->vtbl
->detach(sc
->codec_if
);
480 pci_intr_disestablish(pc
, sc
->sc_ih
);
481 bus_space_unmap(sc
->sc_iot
, sc
->sc_ioh
, sc
->sc_iosize
);
482 aprint_error_dev(sc
->sc_dev
, "can't create spdif encodings\n");
486 if (!pmf_device_register(self
, NULL
, auvia_resume
))
487 aprint_error_dev(self
, "couldn't establish power handler\n");
489 audio_attach_mi(&auvia_hw_if
, sc
, sc
->sc_dev
);
490 sc
->codec_if
->vtbl
->unlock(sc
->codec_if
);
495 auvia_attach_codec(void *addr
, struct ac97_codec_if
*cif
)
497 struct auvia_softc
*sc
;
505 auvia_reset_codec(void *addr
)
507 struct auvia_softc
*sc
;
511 /* perform a codec cold reset */
513 r
= pci_conf_read(sc
->sc_pc
, sc
->sc_pt
, AUVIA_PCICONF_JUNK
);
515 r
&= ~AUVIA_PCICONF_ACNOTRST
; /* enable RESET (active low) */
516 pci_conf_write(sc
->sc_pc
, sc
->sc_pt
, AUVIA_PCICONF_JUNK
, r
);
519 r
|= AUVIA_PCICONF_ACNOTRST
; /* disable RESET (inactive high) */
520 pci_conf_write(sc
->sc_pc
, sc
->sc_pt
, AUVIA_PCICONF_JUNK
, r
);
523 for (i
= 500000; i
!= 0 && !(pci_conf_read(sc
->sc_pc
, sc
->sc_pt
,
524 AUVIA_PCICONF_JUNK
) & AUVIA_PCICONF_PRIVALID
); i
--)
527 printf("%s: codec reset timed out\n", device_xname(sc
->sc_dev
));
534 auvia_waitready_codec(struct auvia_softc
*sc
)
538 /* poll until codec not busy */
539 for (i
= 0; (i
< TIMEOUT
) && (bus_space_read_4(sc
->sc_iot
, sc
->sc_ioh
,
540 AUVIA_CODEC_CTL
) & AUVIA_CODEC_BUSY
); i
++)
543 printf("%s: codec busy\n", device_xname(sc
->sc_dev
));
551 auvia_waitvalid_codec(struct auvia_softc
*sc
)
555 /* poll until codec valid */
556 for (i
= 0; (i
< TIMEOUT
) && !(bus_space_read_4(sc
->sc_iot
, sc
->sc_ioh
,
557 AUVIA_CODEC_CTL
) & AUVIA_CODEC_PRIVALID
); i
++)
560 printf("%s: codec invalid\n", device_xname(sc
->sc_dev
));
568 auvia_write_codec(void *addr
, u_int8_t reg
, u_int16_t val
)
570 struct auvia_softc
*sc
;
573 if (auvia_waitready_codec(sc
))
576 bus_space_write_4(sc
->sc_iot
, sc
->sc_ioh
, AUVIA_CODEC_CTL
,
577 AUVIA_CODEC_PRIVALID
| AUVIA_CODEC_INDEX(reg
) | val
);
583 auvia_read_codec(void *addr
, u_int8_t reg
, u_int16_t
*val
)
585 struct auvia_softc
*sc
;
588 if (auvia_waitready_codec(sc
))
591 bus_space_write_4(sc
->sc_iot
, sc
->sc_ioh
, AUVIA_CODEC_CTL
,
592 AUVIA_CODEC_PRIVALID
| AUVIA_CODEC_READ
| AUVIA_CODEC_INDEX(reg
));
594 if (auvia_waitready_codec(sc
))
597 if (auvia_waitvalid_codec(sc
))
600 *val
= bus_space_read_2(sc
->sc_iot
, sc
->sc_ioh
, AUVIA_CODEC_CTL
);
606 auvia_spdif_event(void *addr
, bool flag
)
608 struct auvia_softc
*sc
;
615 auvia_open(void *addr
, int flags
)
617 struct auvia_softc
*sc
;
619 sc
= (struct auvia_softc
*)addr
;
620 sc
->codec_if
->vtbl
->lock(sc
->codec_if
);
625 auvia_close(void *addr
)
627 struct auvia_softc
*sc
;
629 sc
= (struct auvia_softc
*)addr
;
630 sc
->codec_if
->vtbl
->unlock(sc
->codec_if
);
634 auvia_query_encoding(void *addr
, struct audio_encoding
*fp
)
636 struct auvia_softc
*sc
;
638 sc
= (struct auvia_softc
*)addr
;
639 return auconv_query_encoding(
640 sc
->sc_spdif
? sc
->sc_spdif_encodings
: sc
->sc_encodings
, fp
);
644 auvia_set_params_sub(struct auvia_softc
*sc
, struct auvia_softc_chan
*ch
,
645 const audio_params_t
*p
)
650 if (!(sc
->sc_flags
& AUVIA_FLAGS_VT8233
)) {
651 regval
= (p
->channels
== 2 ? AUVIA_RPMODE_STEREO
: 0)
652 | (p
->precision
== 16 ?
653 AUVIA_RPMODE_16BIT
: 0)
654 | AUVIA_RPMODE_INTR_FLAG
| AUVIA_RPMODE_INTR_EOL
655 | AUVIA_RPMODE_AUTOSTART
;
657 } else if (ch
->sc_base
!= VIA8233_MP_BASE
) {
658 v
= CH_READ4(sc
, ch
, VIA8233_RP_RATEFMT
);
659 v
&= ~(VIA8233_RATEFMT_48K
| VIA8233_RATEFMT_STEREO
660 | VIA8233_RATEFMT_16BIT
);
662 v
|= VIA8233_RATEFMT_48K
* (p
->sample_rate
/ 20)
664 if (p
->channels
== 2)
665 v
|= VIA8233_RATEFMT_STEREO
;
666 if (p
->precision
== 16)
667 v
|= VIA8233_RATEFMT_16BIT
;
669 CH_WRITE4(sc
, ch
, VIA8233_RP_RATEFMT
, v
);
671 static const u_int32_t slottab
[7] =
672 { 0, 0xff000011, 0xff000021, 0,
673 0xff004321, 0, 0xff436521};
675 regval
= (p
->precision
== 16
676 ? VIA8233_MP_FORMAT_16BIT
: VIA8233_MP_FORMAT_8BIT
)
677 | (p
->channels
<< 4);
678 CH_WRITE1(sc
, ch
, VIA8233_OFF_MP_FORMAT
, regval
);
679 CH_WRITE4(sc
, ch
, VIA8233_OFF_MP_STOP
, slottab
[p
->channels
]);
684 auvia_set_params(void *addr
, int setmode
, int usemode
,
685 audio_params_t
*play
, audio_params_t
*rec
, stream_filter_list_t
*pfil
,
686 stream_filter_list_t
*rfil
)
688 struct auvia_softc
*sc
;
689 struct auvia_softc_chan
*ch
;
690 struct audio_params
*p
;
691 struct ac97_codec_if
* codec
;
692 stream_filter_list_t
*fil
;
697 codec
= sc
->codec_if
;
698 /* for mode in (RECORD, PLAY) */
699 for (mode
= AUMODE_RECORD
; mode
!= -1;
700 mode
= mode
== AUMODE_RECORD
? AUMODE_PLAY
: -1) {
701 if ((setmode
& mode
) == 0)
704 if (mode
== AUMODE_PLAY
) {
707 reg
= AC97_REG_PCM_FRONT_DAC_RATE
;
712 reg
= AC97_REG_PCM_LR_ADC_RATE
;
716 if (p
->sample_rate
< 4000 || p
->sample_rate
> 48000 ||
717 (p
->precision
!= 8 && p
->precision
!= 16))
720 index
= auconv_set_converter(auvia_spdif_formats
,
721 AUVIA_SPDIF_NFORMATS
, mode
, p
, TRUE
, fil
);
723 index
= auconv_set_converter(sc
->sc_formats
,
724 AUVIA_NFORMATS
, mode
, p
, TRUE
, fil
);
727 if (fil
->req_size
> 0)
728 p
= &fil
->filters
[0].param
;
729 if (!AC97_IS_FIXED_RATE(codec
)) {
730 if (codec
->vtbl
->set_rate(codec
, reg
, &p
->sample_rate
))
732 reg
= AC97_REG_PCM_SURR_DAC_RATE
;
734 && codec
->vtbl
->set_rate(codec
, reg
,
737 reg
= AC97_REG_PCM_LFE_DAC_RATE
;
739 && codec
->vtbl
->set_rate(codec
, reg
,
743 auvia_set_params_sub(sc
, ch
, p
);
750 auvia_round_blocksize(void *addr
, int blk
,
751 int mode
, const audio_params_t
*param
)
753 struct auvia_softc
*sc
;
756 /* XXX VT823x might have the limitation of dma_ops size */
757 if (sc
->sc_flags
& AUVIA_FLAGS_VT8233
&& blk
< 288)
764 auvia_halt_output(void *addr
)
766 struct auvia_softc
*sc
;
767 struct auvia_softc_chan
*ch
;
771 CH_WRITE1(sc
, ch
, AUVIA_RP_CONTROL
, AUVIA_RPCTRL_TERMINATE
);
777 auvia_halt_input(void *addr
)
779 struct auvia_softc
*sc
;
780 struct auvia_softc_chan
*ch
;
783 ch
= &(sc
->sc_record
);
784 CH_WRITE1(sc
, ch
, AUVIA_RP_CONTROL
, AUVIA_RPCTRL_TERMINATE
);
790 auvia_getdev(void *addr
, struct audio_device
*retp
)
792 struct auvia_softc
*sc
;
796 if (sc
->sc_flags
& AUVIA_FLAGS_VT8233
) {
797 strncpy(retp
->name
, "VIA VT823x",
800 strncpy(retp
->name
, "VIA VT82C686A",
803 strncpy(retp
->version
, sc
->sc_revision
, sizeof(retp
->version
));
804 strncpy(retp
->config
, "auvia", sizeof(retp
->config
));
811 auvia_set_port(void *addr
, mixer_ctrl_t
*cp
)
813 struct auvia_softc
*sc
;
816 return sc
->codec_if
->vtbl
->mixer_set_port(sc
->codec_if
, cp
);
820 auvia_get_port(void *addr
, mixer_ctrl_t
*cp
)
822 struct auvia_softc
*sc
;
825 return sc
->codec_if
->vtbl
->mixer_get_port(sc
->codec_if
, cp
);
829 auvia_query_devinfo(void *addr
, mixer_devinfo_t
*dip
)
831 struct auvia_softc
*sc
;
834 return sc
->codec_if
->vtbl
->query_devinfo(sc
->codec_if
, dip
);
838 auvia_malloc(void *addr
, int direction
, size_t size
,
839 struct malloc_type
* pool
, int flags
)
841 struct auvia_softc
*sc
;
846 p
= malloc(sizeof(*p
), pool
, flags
);
851 if ((error
= bus_dmamem_alloc(sc
->sc_dmat
, size
, PAGE_SIZE
, 0, &p
->seg
,
852 1, &rseg
, BUS_DMA_NOWAIT
)) != 0) {
853 aprint_error_dev(sc
->sc_dev
, "unable to allocate DMA, error = %d\n", error
);
857 if ((error
= bus_dmamem_map(sc
->sc_dmat
, &p
->seg
, rseg
, size
, &p
->addr
,
858 BUS_DMA_NOWAIT
| BUS_DMA_COHERENT
)) != 0) {
859 aprint_error_dev(sc
->sc_dev
, "unable to map DMA, error = %d\n",
864 if ((error
= bus_dmamap_create(sc
->sc_dmat
, size
, 1, size
, 0,
865 BUS_DMA_NOWAIT
, &p
->map
)) != 0) {
866 aprint_error_dev(sc
->sc_dev
, "unable to create DMA map, error = %d\n",
871 if ((error
= bus_dmamap_load(sc
->sc_dmat
, p
->map
, p
->addr
, size
, NULL
,
872 BUS_DMA_NOWAIT
)) != 0) {
873 aprint_error_dev(sc
->sc_dev
, "unable to load DMA map, error = %d\n",
878 p
->next
= sc
->sc_dmas
;
885 bus_dmamap_destroy(sc
->sc_dmat
, p
->map
);
887 bus_dmamem_unmap(sc
->sc_dmat
, p
->addr
, size
);
889 bus_dmamem_free(sc
->sc_dmat
, &p
->seg
, 1);
896 auvia_free(void *addr
, void *ptr
, struct malloc_type
*pool
)
898 struct auvia_softc
*sc
;
899 struct auvia_dma
**pp
, *p
;
902 for (pp
= &(sc
->sc_dmas
); (p
= *pp
) != NULL
; pp
= &p
->next
)
903 if (p
->addr
== ptr
) {
904 bus_dmamap_unload(sc
->sc_dmat
, p
->map
);
905 bus_dmamap_destroy(sc
->sc_dmat
, p
->map
);
906 bus_dmamem_unmap(sc
->sc_dmat
, p
->addr
, p
->size
);
907 bus_dmamem_free(sc
->sc_dmat
, &p
->seg
, 1);
914 panic("auvia_free: trying to free unallocated memory");
918 auvia_round_buffersize(void *addr
, int direction
, size_t size
)
925 auvia_mappage(void *addr
, void *mem
, off_t off
, int prot
)
927 struct auvia_softc
*sc
;
933 for (p
= sc
->sc_dmas
; p
&& p
->addr
!= mem
; p
= p
->next
)
939 return bus_dmamem_mmap(sc
->sc_dmat
, &p
->seg
, 1, off
, prot
,
944 auvia_get_props(void *addr
)
946 struct auvia_softc
*sc
;
949 props
= AUDIO_PROP_INDEPENDENT
| AUDIO_PROP_FULLDUPLEX
;
952 * Even if the codec is fixed-rate, set_param() succeeds for any sample
953 * rate because of aurateconv. Applications can't know what rate the
954 * device can process in the case of mmap().
956 if (!AC97_IS_FIXED_RATE(sc
->codec_if
))
957 props
|= AUDIO_PROP_MMAP
;
962 auvia_build_dma_ops(struct auvia_softc
*sc
, struct auvia_softc_chan
*ch
,
963 struct auvia_dma
*p
, void *start
, void *end
, int blksize
)
965 struct auvia_dma_op
*op
;
966 struct auvia_dma
*dp
;
971 s
= p
->map
->dm_segs
[0].ds_addr
;
972 l
= ((char *)end
- (char *)start
);
973 segs
= (l
+ blksize
- 1) / blksize
;
975 if (segs
> (ch
->sc_dma_op_count
)) {
976 /* if old list was too small, free it */
977 if (ch
->sc_dma_ops
) {
978 auvia_free(sc
, ch
->sc_dma_ops
, M_DEVBUF
);
981 ch
->sc_dma_ops
= auvia_malloc(sc
, 0,
982 sizeof(struct auvia_dma_op
) * segs
, M_DEVBUF
, M_WAITOK
);
984 if (ch
->sc_dma_ops
== NULL
) {
985 aprint_error_dev(sc
->sc_dev
, "couldn't build dmaops\n");
989 for (dp
= sc
->sc_dmas
;
990 dp
&& dp
->addr
!= (void *)(ch
->sc_dma_ops
);
995 panic("%s: build_dma_ops: where'd my memory go??? "
996 "address (%p)\n", device_xname(sc
->sc_dev
),
999 ch
->sc_dma_op_count
= segs
;
1000 ch
->sc_dma_ops_dma
= dp
;
1003 dp
= ch
->sc_dma_ops_dma
;
1004 op
= ch
->sc_dma_ops
;
1007 op
->ptr
= htole32(s
);
1011 op
->flags
= htole32(AUVIA_DMAOP_EOL
| blksize
);
1013 op
->flags
= htole32(AUVIA_DMAOP_FLAG
| blksize
);
1024 auvia_trigger_output(void *addr
, void *start
, void *end
, int blksize
,
1025 void (*intr
)(void *), void *arg
, const audio_params_t
*param
)
1027 struct auvia_softc
*sc
;
1028 struct auvia_softc_chan
*ch
;
1029 struct auvia_dma
*p
;
1032 ch
= &(sc
->sc_play
);
1033 for (p
= sc
->sc_dmas
; p
&& p
->addr
!= start
; p
= p
->next
)
1037 panic("auvia_trigger_output: request with bad start "
1038 "address (%p)", start
);
1040 if (auvia_build_dma_ops(sc
, ch
, p
, start
, end
, blksize
)) {
1047 CH_WRITE4(sc
, ch
, AUVIA_RP_DMAOPS_BASE
,
1048 ch
->sc_dma_ops_dma
->map
->dm_segs
[0].ds_addr
);
1050 if (sc
->sc_flags
& AUVIA_FLAGS_VT8233
) {
1051 if (ch
->sc_base
!= VIA8233_MP_BASE
) {
1052 CH_WRITE1(sc
, ch
, VIA8233_RP_DXS_LVOL
, 0);
1053 CH_WRITE1(sc
, ch
, VIA8233_RP_DXS_RVOL
, 0);
1055 CH_WRITE1(sc
, ch
, AUVIA_RP_CONTROL
,
1056 AUVIA_RPCTRL_START
| AUVIA_RPCTRL_AUTOSTART
|
1057 AUVIA_RPCTRL_STOP
| AUVIA_RPCTRL_EOL
| AUVIA_RPCTRL_FLAG
);
1059 CH_WRITE1(sc
, ch
, AUVIA_RP_MODE
, ch
->sc_reg
);
1060 CH_WRITE1(sc
, ch
, AUVIA_RP_CONTROL
, AUVIA_RPCTRL_START
);
1067 auvia_trigger_input(void *addr
, void *start
, void *end
, int blksize
,
1068 void (*intr
)(void *), void *arg
, const audio_params_t
*param
)
1070 struct auvia_softc
*sc
;
1071 struct auvia_softc_chan
*ch
;
1072 struct auvia_dma
*p
;
1075 ch
= &(sc
->sc_record
);
1076 for (p
= sc
->sc_dmas
; p
&& p
->addr
!= start
; p
= p
->next
)
1080 panic("auvia_trigger_input: request with bad start "
1081 "address (%p)", start
);
1083 if (auvia_build_dma_ops(sc
, ch
, p
, start
, end
, blksize
)) {
1090 CH_WRITE4(sc
, ch
, AUVIA_RP_DMAOPS_BASE
,
1091 ch
->sc_dma_ops_dma
->map
->dm_segs
[0].ds_addr
);
1093 if (sc
->sc_flags
& AUVIA_FLAGS_VT8233
) {
1094 CH_WRITE1(sc
, ch
, VIA8233_RP_DXS_LVOL
, 0);
1095 CH_WRITE1(sc
, ch
, VIA8233_RP_DXS_RVOL
, 0);
1096 CH_WRITE1(sc
, ch
, AUVIA_RP_CONTROL
,
1097 AUVIA_RPCTRL_START
| AUVIA_RPCTRL_AUTOSTART
|
1098 AUVIA_RPCTRL_STOP
| AUVIA_RPCTRL_EOL
| AUVIA_RPCTRL_FLAG
);
1100 CH_WRITE1(sc
, ch
, AUVIA_RP_MODE
, ch
->sc_reg
);
1101 CH_WRITE1(sc
, ch
, AUVIA_RP_CONTROL
, AUVIA_RPCTRL_START
);
1108 auvia_intr(void *arg
)
1110 struct auvia_softc
*sc
;
1111 struct auvia_softc_chan
*ch
;
1118 ch
= &sc
->sc_record
;
1119 r
= CH_READ1(sc
, ch
, AUVIA_RP_STAT
);
1120 if (r
& AUVIA_RPSTAT_INTR
) {
1121 if (sc
->sc_record
.sc_intr
)
1122 sc
->sc_record
.sc_intr(sc
->sc_record
.sc_arg
);
1124 /* clear interrupts */
1125 CH_WRITE1(sc
, ch
, AUVIA_RP_STAT
, AUVIA_RPSTAT_INTR
);
1130 r
= CH_READ1(sc
, ch
, AUVIA_RP_STAT
);
1131 if (r
& AUVIA_RPSTAT_INTR
) {
1132 if (sc
->sc_play
.sc_intr
)
1133 sc
->sc_play
.sc_intr(sc
->sc_play
.sc_arg
);
1135 /* clear interrupts */
1136 CH_WRITE1(sc
, ch
, AUVIA_RP_STAT
, AUVIA_RPSTAT_INTR
);
1144 auvia_resume(device_t dv
, pmf_qual_t qual
)
1146 struct auvia_softc
*sc
= device_private(dv
);
1148 auvia_reset_codec(sc
);
1150 (sc
->codec_if
->vtbl
->restore_ports
)(sc
->codec_if
);