Expand PMF_FN_* macros.
[netbsd-mini2440.git] / sys / dev / pci / azalia.c
blob530c04190999d286560a361ebd482117e38ea306
1 /* $NetBSD: azalia.c,v 1.70 2009/11/12 19:40:19 dyoung Exp $ */
3 /*-
4 * Copyright (c) 2005 The NetBSD Foundation, Inc.
5 * All rights reserved.
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by TAMURA Kent
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.
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 * High Definition Audio Specification
34 * ftp://download.intel.com/standards/hdaudio/pdf/HDAudio_03.pdf
37 * TO DO:
38 * - power hook
39 * - multiple codecs (needed?)
40 * - multiple streams (needed?)
43 #include <sys/cdefs.h>
44 __KERNEL_RCSID(0, "$NetBSD: azalia.c,v 1.70 2009/11/12 19:40:19 dyoung Exp $");
46 #include <sys/param.h>
47 #include <sys/device.h>
48 #include <sys/fcntl.h>
49 #include <sys/malloc.h>
50 #include <sys/systm.h>
51 #include <sys/module.h>
52 #include <dev/audio_if.h>
53 #include <dev/auconv.h>
54 #include <dev/pci/pcidevs.h>
55 #include <dev/pci/pcivar.h>
57 #include <dev/pci/azalia.h>
59 /* ----------------------------------------------------------------
60 * ICH6/ICH7 constant values
61 * ---------------------------------------------------------------- */
63 /* PCI registers */
64 #define ICH_PCI_HDBARL 0x10
65 #define ICH_PCI_HDBARU 0x14
66 #define ICH_PCI_HDCTL 0x40
67 #define ICH_PCI_HDCTL_CLKDETCLR 0x08
68 #define ICH_PCI_HDCTL_CLKDETEN 0x04
69 #define ICH_PCI_HDCTL_CLKDETINV 0x02
70 #define ICH_PCI_HDCTL_SIGNALMODE 0x01
72 /* internal types */
74 typedef struct {
75 bus_dmamap_t map;
76 void *addr; /* kernel virtual address */
77 bus_dma_segment_t segments[1];
78 size_t size;
79 } azalia_dma_t;
81 #define AZALIA_DMA_DMAADDR(p) ((p)->map->dm_segs[0].ds_addr)
83 typedef struct {
84 struct azalia_t *az;
85 int regbase;
86 int number;
87 int dir; /* AUMODE_PLAY or AUMODE_RECORD */
88 uint32_t intr_bit;
89 azalia_dma_t bdlist;
90 azalia_dma_t buffer;
91 void (*intr)(void*);
92 void *intr_arg;
93 bus_addr_t dmaend, dmanext; /* XXX needed? */
94 } stream_t;
96 /* XXXfreza use bus_space_subregion() instead of adding 'regbase' offset */
97 #define STR_READ_1(s, r) \
98 bus_space_read_1((s)->az->iot, (s)->az->ioh, (s)->regbase + HDA_SD_##r)
99 #define STR_READ_2(s, r) \
100 bus_space_read_2((s)->az->iot, (s)->az->ioh, (s)->regbase + HDA_SD_##r)
101 #define STR_READ_4(s, r) \
102 bus_space_read_4((s)->az->iot, (s)->az->ioh, (s)->regbase + HDA_SD_##r)
103 #define STR_WRITE_1(s, r, v) \
104 bus_space_write_1((s)->az->iot, (s)->az->ioh, (s)->regbase + HDA_SD_##r, v)
105 #define STR_WRITE_2(s, r, v) \
106 bus_space_write_2((s)->az->iot, (s)->az->ioh, (s)->regbase + HDA_SD_##r, v)
107 #define STR_WRITE_4(s, r, v) \
108 bus_space_write_4((s)->az->iot, (s)->az->ioh, (s)->regbase + HDA_SD_##r, v)
110 typedef struct azalia_t {
111 device_t dev;
112 device_t audiodev;
114 pci_chipset_tag_t pc;
115 pcitag_t tag;
116 void *ih;
117 bus_space_tag_t iot;
118 bus_space_handle_t ioh;
119 bus_size_t map_size;
120 bus_dma_tag_t dmat;
121 pcireg_t pciid;
122 uint32_t subid;
124 codec_t codecs[15];
125 int ncodecs; /* number of codecs */
126 int codecno; /* index of the using codec */
128 azalia_dma_t corb_dma;
129 int corb_size;
130 azalia_dma_t rirb_dma;
131 int rirb_size;
132 int rirb_rp;
133 #define UNSOLQ_SIZE 256
134 rirb_entry_t *unsolq;
135 int unsolq_wp;
136 int unsolq_rp;
137 bool unsolq_kick;
139 bool ok64;
140 int nistreams, nostreams, nbstreams;
141 stream_t pstream;
142 stream_t rstream;
144 int mode_cap;
145 } azalia_t;
147 #define AZ_READ_1(z, r) bus_space_read_1((z)->iot, (z)->ioh, HDA_##r)
148 #define AZ_READ_2(z, r) bus_space_read_2((z)->iot, (z)->ioh, HDA_##r)
149 #define AZ_READ_4(z, r) bus_space_read_4((z)->iot, (z)->ioh, HDA_##r)
150 #define AZ_WRITE_1(z, r, v) bus_space_write_1((z)->iot, (z)->ioh, HDA_##r, v)
151 #define AZ_WRITE_2(z, r, v) bus_space_write_2((z)->iot, (z)->ioh, HDA_##r, v)
152 #define AZ_WRITE_4(z, r, v) bus_space_write_4((z)->iot, (z)->ioh, HDA_##r, v)
155 /* prototypes */
156 static int azalia_pci_match(device_t, cfdata_t, void *);
157 static void azalia_pci_attach(device_t, device_t, void *);
158 static int azalia_pci_detach(device_t, int);
159 static bool azalia_pci_resume(device_t, pmf_qual_t);
160 static void azalia_childdet(device_t, device_t);
161 static int azalia_intr(void *);
162 static int azalia_attach(azalia_t *);
163 static void azalia_attach_intr(device_t);
164 static int azalia_init_corb(azalia_t *, int);
165 static int azalia_delete_corb(azalia_t *);
166 static int azalia_init_rirb(azalia_t *, int);
167 static int azalia_delete_rirb(azalia_t *);
168 static int azalia_set_command(const azalia_t *, nid_t, int, uint32_t,
169 uint32_t);
170 static int azalia_get_response(azalia_t *, uint32_t *);
171 static void azalia_rirb_kick_unsol_events(azalia_t *);
172 static void azalia_rirb_intr(azalia_t *);
173 static int azalia_alloc_dmamem(azalia_t *, size_t, size_t, azalia_dma_t *);
174 static int azalia_free_dmamem(const azalia_t *, azalia_dma_t*);
176 static int azalia_codec_init(codec_t *, int, uint32_t);
177 static int azalia_codec_delete(codec_t *);
178 static void azalia_codec_add_bits(codec_t *, int, uint32_t, int);
179 static void azalia_codec_add_format(codec_t *, int, int, int, uint32_t,
180 int32_t);
181 static int azalia_codec_comresp(const codec_t *, nid_t, uint32_t,
182 uint32_t, uint32_t *);
183 static int azalia_codec_connect_stream(codec_t *, int, uint16_t, int);
184 static int azalia_codec_disconnect_stream(codec_t *, int);
186 static int azalia_widget_init(widget_t *, const codec_t *, int, const char *);
187 static int azalia_widget_init_audio(widget_t *, const codec_t *, const char *);
188 #ifdef AZALIA_DEBUG
189 static int azalia_widget_print_audio(const widget_t *, const char *, int);
190 #endif
191 static int azalia_widget_init_pin(widget_t *, const codec_t *);
192 static int azalia_widget_print_pin(const widget_t *, const char *);
193 static int azalia_widget_init_connection(widget_t *, const codec_t *, const char *);
195 static int azalia_stream_init(stream_t *, azalia_t *, int, int, int);
196 static int azalia_stream_delete(stream_t *, azalia_t *);
197 static int azalia_stream_reset(stream_t *);
198 static int azalia_stream_start(stream_t *, void *, void *, int,
199 void (*)(void *), void *, uint16_t);
200 static int azalia_stream_halt(stream_t *);
201 static int azalia_stream_intr(stream_t *, uint32_t);
203 static int azalia_open(void *, int);
204 static void azalia_close(void *);
205 static int azalia_query_encoding(void *, audio_encoding_t *);
206 static int azalia_set_params(void *, int, int, audio_params_t *,
207 audio_params_t *, stream_filter_list_t *, stream_filter_list_t *);
208 static int azalia_round_blocksize(void *, int, int, const audio_params_t *);
209 static int azalia_halt_output(void *);
210 static int azalia_halt_input(void *);
211 static int azalia_getdev(void *, struct audio_device *);
212 static int azalia_set_port(void *, mixer_ctrl_t *);
213 static int azalia_get_port(void *, mixer_ctrl_t *);
214 static int azalia_query_devinfo(void *, mixer_devinfo_t *);
215 static void *azalia_allocm(void *, int, size_t, struct malloc_type *, int);
216 static void azalia_freem(void *, void *, struct malloc_type *);
217 static size_t azalia_round_buffersize(void *, int, size_t);
218 static int azalia_get_props(void *);
219 static int azalia_trigger_output(void *, void *, void *, int,
220 void (*)(void *), void *, const audio_params_t *);
221 static int azalia_trigger_input(void *, void *, void *, int,
222 void (*)(void *), void *, const audio_params_t *);
224 static int azalia_params2fmt(const audio_params_t *, uint16_t *);
226 /* variables */
227 CFATTACH_DECL2_NEW(azalia, sizeof(azalia_t),
228 azalia_pci_match, azalia_pci_attach, azalia_pci_detach, NULL,
229 NULL, azalia_childdet);
231 static const struct audio_hw_if azalia_hw_if = {
232 azalia_open,
233 azalia_close,
234 NULL, /* drain */
235 azalia_query_encoding,
236 azalia_set_params,
237 azalia_round_blocksize,
238 NULL, /* commit_settings */
239 NULL, /* init_output */
240 NULL, /* init_input */
241 NULL, /* start_output */
242 NULL, /* satart_inpu */
243 azalia_halt_output,
244 azalia_halt_input,
245 NULL, /* speaker_ctl */
246 azalia_getdev,
247 NULL, /* setfd */
248 azalia_set_port,
249 azalia_get_port,
250 azalia_query_devinfo,
251 azalia_allocm,
252 azalia_freem,
253 azalia_round_buffersize,
254 NULL, /* mappage */
255 azalia_get_props,
256 azalia_trigger_output,
257 azalia_trigger_input,
258 NULL, /* dev_ioctl */
259 NULL, /* powerstate */
262 static const char *pin_colors[16] = {
263 "unknown", "black", "gray", "blue",
264 "green", "red", "orange", "yellow",
265 "purple", "pink", "col0a", "col0b",
266 "col0c", "col0d", "white", "other"
269 #ifdef AZALIA_DEBUG
270 static const char *pin_devices[16] = {
271 "line-out", AudioNspeaker, AudioNheadphone, AudioNcd,
272 "SPDIF-out", "digital-out", "modem-line", "modem-handset",
273 "line-in", AudioNaux, AudioNmicrophone, "telephony",
274 "SPDIF-in", "digital-in", "dev0e", "other"
276 #endif
278 /* ================================================================
279 * PCI functions
280 * ================================================================ */
282 static int
283 azalia_pci_match(device_t parent, cfdata_t match, void *aux)
285 struct pci_attach_args *pa;
287 pa = aux;
288 if (PCI_CLASS(pa->pa_class) == PCI_CLASS_MULTIMEDIA
289 && PCI_SUBCLASS(pa->pa_class) == PCI_SUBCLASS_MULTIMEDIA_HDAUDIO)
290 return 1;
291 return 0;
294 static void
295 azalia_pci_attach(device_t parent, device_t self, void *aux)
297 azalia_t *sc = device_private(self);
298 struct pci_attach_args *pa = aux;
299 pcireg_t v;
300 pci_intr_handle_t ih;
301 const char *intrrupt_str;
302 const char *name;
303 const char *vendor;
305 sc->dev = self;
306 sc->dmat = pa->pa_dmat;
308 aprint_normal(": Generic High Definition Audio Controller\n");
310 v = pci_conf_read(pa->pa_pc, pa->pa_tag, ICH_PCI_HDBARL);
311 v &= PCI_MAPREG_TYPE_MASK | PCI_MAPREG_MEM_TYPE_MASK;
312 if (pci_mapreg_map(pa, ICH_PCI_HDBARL, v, 0,
313 &sc->iot, &sc->ioh, NULL, &sc->map_size)) {
314 aprint_error_dev(self, "can't map device i/o space\n");
315 return;
318 /* enable bus mastering */
319 v = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG);
320 pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG,
321 v | PCI_COMMAND_MASTER_ENABLE | PCI_COMMAND_BACKTOBACK_ENABLE);
323 /* interrupt */
324 if (pci_intr_map(pa, &ih)) {
325 aprint_error_dev(self, "can't map interrupt\n");
326 return;
328 sc->pc = pa->pa_pc;
329 sc->tag = pa->pa_tag;
330 intrrupt_str = pci_intr_string(pa->pa_pc, ih);
331 sc->ih = pci_intr_establish(pa->pa_pc, ih, IPL_AUDIO, azalia_intr, sc);
332 if (sc->ih == NULL) {
333 aprint_error_dev(self, "can't establish interrupt");
334 if (intrrupt_str != NULL)
335 aprint_error(" at %s", intrrupt_str);
336 aprint_error("\n");
337 return;
339 aprint_normal_dev(self, "interrupting at %s\n", intrrupt_str);
341 if (!pmf_device_register(self, NULL, azalia_pci_resume))
342 aprint_error_dev(self, "couldn't establish power handler\n");
344 sc->pciid = pa->pa_id;
345 vendor = pci_findvendor(pa->pa_id);
346 name = pci_findproduct(pa->pa_id);
347 if (vendor != NULL && name != NULL) {
348 aprint_normal_dev(self, "host: %s %s (rev. %d)",
349 vendor, name, PCI_REVISION(pa->pa_class));
350 } else {
351 aprint_normal_dev(self, "host: 0x%4.4x/0x%4.4x (rev. %d)",
352 PCI_VENDOR(pa->pa_id), PCI_PRODUCT(pa->pa_id),
353 PCI_REVISION(pa->pa_class));
356 if (azalia_attach(sc)) {
357 aprint_error_dev(self, "initialization failure\n");
358 azalia_pci_detach(self, 0);
359 return;
361 sc->subid = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_SUBSYS_ID_REG);
363 config_interrupts(self, azalia_attach_intr);
366 static void
367 azalia_childdet(device_t self, device_t child)
369 azalia_t *az = device_private(self);
371 KASSERT(az->audiodev == child);
372 az->audiodev = NULL;
375 static int
376 azalia_pci_detach(device_t self, int flags)
378 azalia_t *az;
379 int i;
381 DPRINTF(("%s\n", __func__));
382 az = device_private(self);
383 if (az->audiodev != NULL)
384 config_detach(az->audiodev, flags);
386 #if notyet
387 DPRINTF(("%s: halt streams\n", __func__));
388 azalia_stream_halt(&az->rstream);
389 azalia_stream_halt(&az->pstream);
390 #endif
392 DPRINTF(("%s: delete streams\n", __func__));
393 azalia_stream_delete(&az->rstream, az);
394 azalia_stream_delete(&az->pstream, az);
396 DPRINTF(("%s: delete codecs\n", __func__));
397 for (i = 0; i < az->ncodecs; i++) {
398 azalia_codec_delete(&az->codecs[i]);
400 az->ncodecs = 0;
402 DPRINTF(("%s: delete CORB and RIRB\n", __func__));
403 azalia_delete_corb(az);
404 azalia_delete_rirb(az);
406 DPRINTF(("%s: delete PCI resources\n", __func__));
407 if (az->ih != NULL) {
408 pci_intr_disestablish(az->pc, az->ih);
409 az->ih = NULL;
411 if (az->map_size != 0) {
412 bus_space_unmap(az->iot, az->ioh, az->map_size);
413 az->map_size = 0;
415 return 0;
418 static bool
419 azalia_pci_resume(device_t dv, pmf_qual_t qual)
421 azalia_t *az = device_private(dv);
422 int s;
424 s = splaudio();
425 azalia_attach(az);
426 splx(s);
428 azalia_attach_intr(az->dev);
430 return true;
433 static int
434 azalia_intr(void *v)
436 azalia_t *az;
437 int ret;
438 uint32_t intsts;
439 uint8_t rirbsts;
441 az = v;
443 if (!device_has_power(az->dev))
444 return 0;
446 if ((intsts = AZ_READ_4(az, INTSTS)) == 0)
447 return 0;
449 ret = azalia_stream_intr(&az->pstream, intsts) +
450 azalia_stream_intr(&az->rstream, intsts);
452 rirbsts = AZ_READ_1(az, RIRBSTS);
453 if (rirbsts & (HDA_RIRBSTS_RIRBOIS | HDA_RIRBSTS_RINTFL)) {
454 if (rirbsts & HDA_RIRBSTS_RINTFL) {
455 azalia_rirb_intr(az);
456 } else {
457 /*printf("[Overflow!]");*/
459 AZ_WRITE_1(az, RIRBSTS,
460 rirbsts | HDA_RIRBSTS_RIRBOIS | HDA_RIRBSTS_RINTFL);
461 ret++;
464 return ret;
467 /* ================================================================
468 * HDA controller functions
469 * ================================================================ */
471 static int
472 azalia_attach(azalia_t *az)
474 int i, n;
475 uint32_t gctl;
476 uint16_t gcap;
477 uint16_t statests;
479 if (az->audiodev == NULL)
480 aprint_normal(", HDA rev. %d.%d\n",
481 AZ_READ_1(az, VMAJ), AZ_READ_1(az, VMIN));
483 gcap = AZ_READ_2(az, GCAP);
484 az->nistreams = HDA_GCAP_ISS(gcap);
485 az->nostreams = HDA_GCAP_OSS(gcap);
486 az->nbstreams = HDA_GCAP_BSS(gcap);
487 az->ok64 = (gcap & HDA_GCAP_64OK) != 0;
488 DPRINTF(("%s: host: %d output, %d input, and %d bidi streams\n",
489 device_xname(az->dev), az->nostreams, az->nistreams, az->nbstreams));
490 if (az->nistreams > 0)
491 az->mode_cap |= AUMODE_RECORD;
492 if (az->nostreams > 0)
493 az->mode_cap |= AUMODE_PLAY;
495 /* 4.2.2 Starting the High Definition Audio Controller */
496 DPRINTF(("%s: resetting\n", __func__));
497 gctl = AZ_READ_4(az, GCTL);
498 AZ_WRITE_4(az, GCTL, gctl & ~HDA_GCTL_CRST);
499 for (i = 5000; i >= 0; i--) {
500 DELAY(10);
501 if ((AZ_READ_4(az, GCTL) & HDA_GCTL_CRST) == 0)
502 break;
504 DPRINTF(("%s: reset counter = %d\n", __func__, i));
505 if (i <= 0) {
506 aprint_error_dev(az->dev, "reset failure\n");
507 return ETIMEDOUT;
509 DELAY(1000);
510 gctl = AZ_READ_4(az, GCTL);
511 AZ_WRITE_4(az, GCTL, gctl | HDA_GCTL_CRST);
512 for (i = 5000; i >= 0; i--) {
513 DELAY(10);
514 if (AZ_READ_4(az, GCTL) & HDA_GCTL_CRST)
515 break;
517 DPRINTF(("%s: reset counter = %d\n", __func__, i));
518 if (i <= 0) {
519 aprint_error_dev(az->dev, "reset-exit failure\n");
520 return ETIMEDOUT;
523 /* enable unsolicited response */
524 gctl = AZ_READ_4(az, GCTL);
525 AZ_WRITE_4(az, GCTL, gctl | HDA_GCTL_UNSOL);
527 /* 4.3 Codec discovery */
528 DELAY(1000);
529 statests = AZ_READ_2(az, STATESTS);
530 for (i = 0, n = 0; i < 15; i++) {
531 if ((statests >> i) & 1) {
532 DPRINTF(("%s: found a codec at #%d\n",
533 device_xname(az->dev), i));
534 az->codecs[n].address = i;
535 az->codecs[n++].dev = az->dev;
538 az->ncodecs = n;
539 if (az->ncodecs < 1) {
540 aprint_error_dev(az->dev, "No HD-Audio codecs\n");
541 return -1;
543 return 0;
546 static void
547 azalia_attach_intr(device_t self)
549 azalia_t *az;
550 int err, i, c, reinit;
552 az = device_private(self);
553 reinit = az->audiodev == NULL ? 0 : 1;
555 AZ_WRITE_2(az, STATESTS, HDA_STATESTS_SDIWAKE);
556 AZ_WRITE_1(az, RIRBSTS, HDA_RIRBSTS_RINTFL | HDA_RIRBSTS_RIRBOIS);
557 AZ_WRITE_4(az, INTSTS, HDA_INTSTS_CIS | HDA_INTSTS_GIS);
558 AZ_WRITE_4(az, DPLBASE, 0);
559 AZ_WRITE_4(az, DPUBASE, 0);
561 /* 4.4.1 Command Outbound Ring Buffer */
562 if (azalia_init_corb(az, reinit))
563 goto err_exit;
564 /* 4.4.2 Response Inbound Ring Buffer */
565 if (azalia_init_rirb(az, reinit))
566 goto err_exit;
568 AZ_WRITE_4(az, INTCTL,
569 AZ_READ_4(az, INTCTL) | HDA_INTCTL_CIE | HDA_INTCTL_GIE);
571 c = -1;
572 for (i = 0; i < az->ncodecs; i++) {
573 err = azalia_codec_init(&az->codecs[i], reinit, az->subid);
574 if (!err && c < 0)
575 c = i;
577 if (c < 0)
578 goto err_exit;
579 /* Use the first audio codec */
580 az->codecno = c;
581 DPRINTF(("%s: using the #%d codec\n",
582 device_xname(az->dev), az->codecno));
583 if (az->codecs[c].dacs.ngroups <= 0)
584 az->mode_cap &= ~AUMODE_PLAY;
585 if (az->codecs[c].adcs.ngroups <= 0)
586 az->mode_cap &= ~AUMODE_RECORD;
588 /* Use stream#1 and #2. Don't use stream#0. */
589 if (reinit == 0) {
590 if (azalia_stream_init(&az->pstream, az, az->nistreams + 0,
591 1, AUMODE_PLAY))
592 goto err_exit;
593 if (azalia_stream_init(&az->rstream, az, 0, 2, AUMODE_RECORD))
594 goto err_exit;
596 az->audiodev = audio_attach_mi(&azalia_hw_if, az, az->dev);
598 return;
599 err_exit:
600 azalia_pci_detach(self, 0);
601 return;
604 static int
605 azalia_init_corb(azalia_t *az, int reinit)
607 int entries, err, i;
608 uint16_t corbrp, corbwp;
609 uint8_t corbsize, cap, corbctl;
611 /* stop the CORB */
612 corbctl = AZ_READ_1(az, CORBCTL);
613 if (corbctl & HDA_CORBCTL_CORBRUN) { /* running? */
614 AZ_WRITE_1(az, CORBCTL, corbctl & ~HDA_CORBCTL_CORBRUN);
615 for (i = 5000; i >= 0; i--) {
616 DELAY(10);
617 corbctl = AZ_READ_1(az, CORBCTL);
618 if ((corbctl & HDA_CORBCTL_CORBRUN) == 0)
619 break;
621 if (i <= 0) {
622 aprint_error_dev(az->dev, "CORB is running\n");
623 return EBUSY;
627 /* determine CORB size */
628 corbsize = AZ_READ_1(az, CORBSIZE);
629 cap = corbsize & HDA_CORBSIZE_CORBSZCAP_MASK;
630 corbsize &= ~HDA_CORBSIZE_CORBSIZE_MASK;
631 if (cap & HDA_CORBSIZE_CORBSZCAP_256) {
632 entries = 256;
633 corbsize |= HDA_CORBSIZE_CORBSIZE_256;
634 } else if (cap & HDA_CORBSIZE_CORBSZCAP_16) {
635 entries = 16;
636 corbsize |= HDA_CORBSIZE_CORBSIZE_16;
637 } else if (cap & HDA_CORBSIZE_CORBSZCAP_2) {
638 entries = 2;
639 corbsize |= HDA_CORBSIZE_CORBSIZE_2;
640 } else {
641 aprint_error_dev(az->dev, "Invalid CORBSZCAP: 0x%2x\n", cap);
642 return -1;
645 if (reinit == 0) {
646 err = azalia_alloc_dmamem(az, entries * sizeof(corb_entry_t),
647 128, &az->corb_dma);
648 if (err) {
649 aprint_error_dev(az->dev, "can't allocate CORB buffer\n");
650 return err;
653 AZ_WRITE_4(az, CORBLBASE, (uint32_t)AZALIA_DMA_DMAADDR(&az->corb_dma));
654 AZ_WRITE_4(az, CORBUBASE, PTR_UPPER32(AZALIA_DMA_DMAADDR(&az->corb_dma)));
655 AZ_WRITE_1(az, CORBSIZE, corbsize);
656 az->corb_size = entries;
658 DPRINTF(("%s: CORB allocation succeeded.\n", __func__));
660 /* reset CORBRP */
661 corbrp = AZ_READ_2(az, CORBRP);
662 AZ_WRITE_2(az, CORBRP, corbrp | HDA_CORBRP_CORBRPRST);
663 AZ_WRITE_2(az, CORBRP, corbrp & ~HDA_CORBRP_CORBRPRST);
664 for (i = 5000; i >= 0; i--) {
665 DELAY(10);
666 corbrp = AZ_READ_2(az, CORBRP);
667 if ((corbrp & HDA_CORBRP_CORBRPRST) == 0)
668 break;
670 if (i <= 0) {
671 aprint_error_dev(az->dev, "CORBRP reset failure\n");
672 return -1;
674 DPRINTF(("%s: CORBWP=%d; size=%d\n", __func__,
675 AZ_READ_2(az, CORBRP) & HDA_CORBRP_CORBRP, az->corb_size));
677 /* clear CORBWP */
678 corbwp = AZ_READ_2(az, CORBWP);
679 AZ_WRITE_2(az, CORBWP, corbwp & ~HDA_CORBWP_CORBWP);
681 /* Run! */
682 corbctl = AZ_READ_1(az, CORBCTL);
683 AZ_WRITE_1(az, CORBCTL, corbctl | HDA_CORBCTL_CORBRUN);
684 return 0;
687 static int
688 azalia_delete_corb(azalia_t *az)
690 int i;
691 uint8_t corbctl;
693 if (az->corb_dma.addr == NULL)
694 return 0;
695 /* stop the CORB */
696 corbctl = AZ_READ_1(az, CORBCTL);
697 AZ_WRITE_1(az, CORBCTL, corbctl & ~HDA_CORBCTL_CORBRUN);
698 for (i = 5000; i >= 0; i--) {
699 DELAY(10);
700 corbctl = AZ_READ_1(az, CORBCTL);
701 if ((corbctl & HDA_CORBCTL_CORBRUN) == 0)
702 break;
704 azalia_free_dmamem(az, &az->corb_dma);
705 return 0;
708 static int
709 azalia_init_rirb(azalia_t *az, int reinit)
711 int entries, err, i;
712 uint16_t rirbwp;
713 uint8_t rirbsize, cap, rirbctl;
715 /* stop the RIRB */
716 rirbctl = AZ_READ_1(az, RIRBCTL);
717 if (rirbctl & HDA_RIRBCTL_RIRBDMAEN) { /* running? */
718 AZ_WRITE_1(az, RIRBCTL, rirbctl & ~HDA_RIRBCTL_RIRBDMAEN);
719 for (i = 5000; i >= 0; i--) {
720 DELAY(10);
721 rirbctl = AZ_READ_1(az, RIRBCTL);
722 if ((rirbctl & HDA_RIRBCTL_RIRBDMAEN) == 0)
723 break;
725 if (i <= 0) {
726 aprint_error_dev(az->dev, "RIRB is running\n");
727 return EBUSY;
731 /* determine RIRB size */
732 rirbsize = AZ_READ_1(az, RIRBSIZE);
733 cap = rirbsize & HDA_RIRBSIZE_RIRBSZCAP_MASK;
734 rirbsize &= ~HDA_RIRBSIZE_RIRBSIZE_MASK;
735 if (cap & HDA_RIRBSIZE_RIRBSZCAP_256) {
736 entries = 256;
737 rirbsize |= HDA_RIRBSIZE_RIRBSIZE_256;
738 } else if (cap & HDA_RIRBSIZE_RIRBSZCAP_16) {
739 entries = 16;
740 rirbsize |= HDA_RIRBSIZE_RIRBSIZE_16;
741 } else if (cap & HDA_RIRBSIZE_RIRBSZCAP_2) {
742 entries = 2;
743 rirbsize |= HDA_RIRBSIZE_RIRBSIZE_2;
744 } else {
745 aprint_error_dev(az->dev, "Invalid RIRBSZCAP: 0x%2x\n", cap);
746 return -1;
749 if (reinit == 0) {
750 err = azalia_alloc_dmamem(az, entries * sizeof(rirb_entry_t),
751 128, &az->rirb_dma);
752 if (err) {
753 aprint_error_dev(az->dev, "can't allocate RIRB buffer\n");
754 return err;
757 AZ_WRITE_4(az, RIRBLBASE, (uint32_t)AZALIA_DMA_DMAADDR(&az->rirb_dma));
758 AZ_WRITE_4(az, RIRBUBASE, PTR_UPPER32(AZALIA_DMA_DMAADDR(&az->rirb_dma)));
759 AZ_WRITE_1(az, RIRBSIZE, rirbsize);
760 az->rirb_size = entries;
762 DPRINTF(("%s: RIRB allocation succeeded.\n", __func__));
764 /* setup the unsolicited response queue */
765 az->unsolq_rp = 0;
766 az->unsolq_wp = 0;
767 az->unsolq_kick = FALSE;
768 if (reinit == 0) {
769 az->unsolq = malloc(sizeof(rirb_entry_t) * UNSOLQ_SIZE,
770 M_DEVBUF, M_ZERO | M_NOWAIT);
771 } else {
772 memset(az->unsolq, 0, sizeof(rirb_entry_t) * UNSOLQ_SIZE);
774 if (az->unsolq == NULL) {
775 aprint_error_dev(az->dev, "can't allocate unsolicited response queue.\n");
776 azalia_free_dmamem(az, &az->rirb_dma);
777 return ENOMEM;
780 #if notyet
781 rirbctl = AZ_READ_1(az, RIRBCTL);
782 AZ_WRITE_1(az, RIRBCTL, rirbctl & ~HDA_RIRBCTL_RINTCTL);
783 #endif
785 /* reset the write pointer */
786 rirbwp = AZ_READ_2(az, RIRBWP);
787 AZ_WRITE_2(az, RIRBWP, rirbwp | HDA_RIRBWP_RIRBWPRST);
789 /* clear the read pointer */
790 az->rirb_rp = AZ_READ_2(az, RIRBWP) & HDA_RIRBWP_RIRBWP;
791 DPRINTF(("%s: RIRBRP=%d, size=%d\n", __func__, az->rirb_rp, az->rirb_size));
793 AZ_WRITE_2(az, RINTCNT, 1);
795 /* Run! */
796 rirbctl = AZ_READ_1(az, RIRBCTL);
797 AZ_WRITE_1(az, RIRBCTL, rirbctl | HDA_RIRBCTL_RIRBDMAEN | HDA_RIRBCTL_RINTCTL);
798 return 0;
801 static int
802 azalia_delete_rirb(azalia_t *az)
804 int i;
805 uint8_t rirbctl;
807 if (az->unsolq != NULL) {
808 free(az->unsolq, M_DEVBUF);
809 az->unsolq = NULL;
811 if (az->rirb_dma.addr == NULL)
812 return 0;
813 /* stop the RIRB */
814 rirbctl = AZ_READ_1(az, RIRBCTL);
815 AZ_WRITE_1(az, RIRBCTL, rirbctl & ~HDA_RIRBCTL_RIRBDMAEN);
816 for (i = 5000; i >= 0; i--) {
817 DELAY(10);
818 rirbctl = AZ_READ_1(az, RIRBCTL);
819 if ((rirbctl & HDA_RIRBCTL_RIRBDMAEN) == 0)
820 break;
822 azalia_free_dmamem(az, &az->rirb_dma);
823 return 0;
826 static int
827 azalia_set_command(const azalia_t *az, int caddr, nid_t nid, uint32_t control,
828 uint32_t param)
830 corb_entry_t *corb;
831 int wp;
832 uint32_t verb;
833 uint16_t corbwp;
835 #ifdef DIAGNOSTIC
836 if ((AZ_READ_1(az, CORBCTL) & HDA_CORBCTL_CORBRUN) == 0) {
837 aprint_error_dev(az->dev, "CORB is not running.\n");
838 return -1;
840 #endif
841 verb = (caddr << 28) | (nid << 20) | (control << 8) | param;
842 corbwp = AZ_READ_2(az, CORBWP);
843 wp = corbwp & HDA_CORBWP_CORBWP;
844 corb = (corb_entry_t*)az->corb_dma.addr;
845 if (++wp >= az->corb_size)
846 wp = 0;
847 corb[wp] = verb;
848 AZ_WRITE_2(az, CORBWP, (corbwp & ~HDA_CORBWP_CORBWP) | wp);
849 #if 0
850 DPRINTF(("%s: caddr=%d nid=%d control=0x%x param=0x%x verb=0x%8.8x wp=%d\n",
851 __func__, caddr, nid, control, param, verb, wp));
852 #endif
853 return 0;
856 static int
857 azalia_get_response(azalia_t *az, uint32_t *result)
859 const rirb_entry_t *rirb;
860 int i;
861 uint16_t wp;
863 #ifdef DIAGNOSTIC
864 if ((AZ_READ_1(az, RIRBCTL) & HDA_RIRBCTL_RIRBDMAEN) == 0) {
865 aprint_error_dev(az->dev, "RIRB is not running.\n");
866 return -1;
868 #endif
869 for (i = 5000; i >= 0; i--) {
870 wp = AZ_READ_2(az, RIRBWP) & HDA_RIRBWP_RIRBWP;
871 if (az->rirb_rp != wp)
872 break;
873 DELAY(10);
875 if (i <= 0) {
876 aprint_error_dev(az->dev, "RIRB time out\n");
877 return ETIMEDOUT;
879 rirb = (rirb_entry_t*)az->rirb_dma.addr;
880 for (;;) {
881 if (++az->rirb_rp >= az->rirb_size)
882 az->rirb_rp = 0;
883 if (rirb[az->rirb_rp].resp_ex & RIRB_RESP_UNSOL) {
884 az->unsolq[az->unsolq_wp].resp = rirb[az->rirb_rp].resp;
885 az->unsolq[az->unsolq_wp++].resp_ex = rirb[az->rirb_rp].resp_ex;
886 az->unsolq_wp %= UNSOLQ_SIZE;
887 } else
888 break;
890 if (result != NULL)
891 *result = rirb[az->rirb_rp].resp;
892 azalia_rirb_kick_unsol_events(az);
893 #if 0
894 DPRINTF(("%s: rirbwp=%d rp=%d resp1=0x%8.8x resp2=0x%8.8x\n",
895 __func__, wp, az->rirb_rp, rirb[az->rirb_rp].resp,
896 rirb[az->rirb_rp].resp_ex));
897 for (i = 0; i < 16 /*az->rirb_size*/; i++) {
898 DPRINTF(("rirb[%d] 0x%8.8x:0x%8.8x ", i, rirb[i].resp, rirb[i].resp_ex));
899 if ((i % 2) == 1)
900 DPRINTF(("\n"));
902 #endif
903 return 0;
906 static void
907 azalia_rirb_kick_unsol_events(azalia_t *az)
909 if (az->unsolq_kick)
910 return;
911 az->unsolq_kick = TRUE;
912 while (az->unsolq_rp != az->unsolq_wp) {
913 int i;
914 int tag;
915 codec_t *codec;
916 i = RIRB_RESP_CODEC(az->unsolq[az->unsolq_rp].resp_ex);
917 tag = RIRB_UNSOL_TAG(az->unsolq[az->unsolq_rp].resp);
918 codec = &az->codecs[i];
919 DPRINTF(("%s: codec#=%d tag=%d\n", __func__, i, tag));
920 az->unsolq_rp++;
921 az->unsolq_rp %= UNSOLQ_SIZE;
922 if (codec->unsol_event != NULL)
923 codec->unsol_event(codec, tag);
925 az->unsolq_kick = FALSE;
928 static void
929 azalia_rirb_intr(azalia_t *az)
931 const rirb_entry_t *rirb;
932 uint16_t wp, newrp;
934 wp = AZ_READ_2(az, RIRBWP) & HDA_RIRBWP_RIRBWP;
935 if (az->rirb_rp == wp)
936 return; /* interrupted but no data in RIRB */
937 /* Copy the first sequence of unsolicited reponses in the RIRB to
938 * unsolq. Don't consume non-unsolicited responses. */
939 rirb = (rirb_entry_t*)az->rirb_dma.addr;
940 while (az->rirb_rp != wp) {
941 newrp = az->rirb_rp + 1;
942 if (newrp >= az->rirb_size)
943 newrp = 0;
944 if (rirb[newrp].resp_ex & RIRB_RESP_UNSOL) {
945 az->unsolq[az->unsolq_wp].resp = rirb[newrp].resp;
946 az->unsolq[az->unsolq_wp++].resp_ex = rirb[newrp].resp_ex;
947 az->unsolq_wp %= UNSOLQ_SIZE;
948 az->rirb_rp = newrp;
949 } else {
950 break;
953 azalia_rirb_kick_unsol_events(az);
956 static int
957 azalia_alloc_dmamem(azalia_t *az, size_t size, size_t align, azalia_dma_t *d)
959 int err;
960 int nsegs;
962 d->size = size;
963 err = bus_dmamem_alloc(az->dmat, size, align, 0, d->segments, 1,
964 &nsegs, BUS_DMA_NOWAIT);
965 if (err)
966 return err;
967 if (nsegs != 1)
968 goto free;
969 err = bus_dmamem_map(az->dmat, d->segments, 1, size,
970 &d->addr, BUS_DMA_NOWAIT | BUS_DMA_COHERENT | BUS_DMA_NOCACHE);
971 if (err)
972 goto free;
973 err = bus_dmamap_create(az->dmat, size, 1, size, 0,
974 BUS_DMA_NOWAIT, &d->map);
975 if (err)
976 goto unmap;
977 err = bus_dmamap_load(az->dmat, d->map, d->addr, size,
978 NULL, BUS_DMA_NOWAIT);
979 if (err)
980 goto destroy;
982 if (!az->ok64 && PTR_UPPER32(AZALIA_DMA_DMAADDR(d)) != 0) {
983 azalia_free_dmamem(az, d);
984 return -1;
986 return 0;
988 destroy:
989 bus_dmamap_destroy(az->dmat, d->map);
990 unmap:
991 bus_dmamem_unmap(az->dmat, d->addr, size);
992 free:
993 bus_dmamem_free(az->dmat, d->segments, 1);
994 d->addr = NULL;
995 return err;
998 static int
999 azalia_free_dmamem(const azalia_t *az, azalia_dma_t* d)
1001 if (d->addr == NULL)
1002 return 0;
1003 bus_dmamap_unload(az->dmat, d->map);
1004 bus_dmamap_destroy(az->dmat, d->map);
1005 bus_dmamem_unmap(az->dmat, d->addr, d->size);
1006 bus_dmamem_free(az->dmat, d->segments, 1);
1007 d->addr = NULL;
1008 return 0;
1011 /* ================================================================
1012 * HDA coodec functions
1013 * ================================================================ */
1015 static int
1016 azalia_codec_init(codec_t *this, int reinit, uint32_t subid)
1018 #define LEAD_LEN 100
1019 char lead[LEAD_LEN];
1020 uint32_t rev, id, result;
1021 int err, addr, n, i;
1023 this->comresp = azalia_codec_comresp;
1024 addr = this->address;
1025 DPRINTF(("%s: information of codec[%d] follows:\n",
1026 device_xname(this->dev), addr));
1027 /* codec vendor/device/revision */
1028 err = this->comresp(this, CORB_NID_ROOT, CORB_GET_PARAMETER,
1029 COP_REVISION_ID, &rev);
1030 if (err)
1031 return err;
1032 err = this->comresp(this, CORB_NID_ROOT, CORB_GET_PARAMETER,
1033 COP_VENDOR_ID, &id);
1034 if (err)
1035 return err;
1036 this->vid = id;
1037 this->subid = subid;
1039 if (!reinit) {
1040 err = azalia_codec_init_vtbl(this);
1041 if (err)
1042 return err;
1045 if (!reinit) {
1046 aprint_normal("%s: codec[%d]: ", device_xname(this->dev), addr);
1047 if (this->name == NULL) {
1048 aprint_normal("0x%4.4x/0x%4.4x (rev. %u.%u)",
1049 id >> 16, id & 0xffff,
1050 COP_RID_REVISION(rev), COP_RID_STEPPING(rev));
1051 } else {
1052 aprint_normal("%s (rev. %u.%u)", this->name,
1053 COP_RID_REVISION(rev), COP_RID_STEPPING(rev));
1055 aprint_normal(", HDA rev. %u.%u\n",
1056 COP_RID_MAJ(rev), COP_RID_MIN(rev));
1059 /* identify function nodes */
1060 err = this->comresp(this, CORB_NID_ROOT, CORB_GET_PARAMETER,
1061 COP_SUBORDINATE_NODE_COUNT, &result);
1062 if (err)
1063 return err;
1064 this->nfunctions = COP_NSUBNODES(result);
1065 if (COP_NSUBNODES(result) <= 0) {
1066 aprint_error("%s: No function groups\n",
1067 device_xname(this->dev));
1068 return -1;
1070 /* iterate function nodes and find an audio function */
1071 n = COP_START_NID(result);
1072 DPRINTF(("%s: nidstart=%d #functions=%d\n",
1073 __func__, n, this->nfunctions));
1074 this->audiofunc = -1;
1075 for (i = 0; i < this->nfunctions; i++) {
1076 err = this->comresp(this, n + i, CORB_GET_PARAMETER,
1077 COP_FUNCTION_GROUP_TYPE, &result);
1078 if (err)
1079 continue;
1080 DPRINTF(("%s: FTYPE result = 0x%8.8x\n", __func__, result));
1081 if (COP_FTYPE(result) == COP_FTYPE_AUDIO) {
1082 this->audiofunc = n + i;
1083 break; /* XXX multiple audio functions? */
1084 } else if (COP_FTYPE(result) == COP_FTYPE_MODEM && !reinit) {
1085 aprint_normal("%s: codec[%d]: No support for modem "
1086 "function groups\n",
1087 device_xname(this->dev), addr);
1090 if (this->audiofunc < 0 && !reinit) {
1091 aprint_verbose("%s: codec[%d] has no audio function groups\n",
1092 device_xname(this->dev), addr);
1093 return -1;
1096 /* power the audio function */
1097 this->comresp(this, this->audiofunc, CORB_SET_POWER_STATE, CORB_PS_D0, &result);
1098 DELAY(100);
1100 /* check widgets in the audio function */
1101 err = this->comresp(this, this->audiofunc,
1102 CORB_GET_PARAMETER, COP_SUBORDINATE_NODE_COUNT, &result);
1103 if (err)
1104 return err;
1105 DPRINTF(("%s: There are %d widgets in the audio function.\n",
1106 __func__, COP_NSUBNODES(result)));
1107 this->wstart = COP_START_NID(result);
1108 if (this->wstart < 2) {
1109 if (!reinit)
1110 aprint_error("%s: invalid node structure\n",
1111 device_xname(this->dev));
1112 return -1;
1114 this->wend = this->wstart + COP_NSUBNODES(result);
1115 if (!reinit) {
1116 this->w = malloc(sizeof(widget_t) * this->wend, M_DEVBUF,
1117 M_ZERO | M_NOWAIT);
1118 if (this->w == NULL) {
1119 aprint_error("%s: out of memory\n",
1120 device_xname(this->dev));
1121 return ENOMEM;
1123 } else
1124 memset(this->w, 0, sizeof(widget_t) * this->wend);
1126 /* query the base parameters */
1127 this->comresp(this, this->audiofunc, CORB_GET_PARAMETER,
1128 COP_STREAM_FORMATS, &result);
1129 this->w[this->audiofunc].d.audio.encodings = result;
1130 this->comresp(this, this->audiofunc, CORB_GET_PARAMETER,
1131 COP_PCM, &result);
1132 this->w[this->audiofunc].d.audio.bits_rates = result;
1133 this->comresp(this, this->audiofunc, CORB_GET_PARAMETER,
1134 COP_INPUT_AMPCAP, &result);
1135 this->w[this->audiofunc].inamp_cap = result;
1136 this->comresp(this, this->audiofunc, CORB_GET_PARAMETER,
1137 COP_OUTPUT_AMPCAP, &result);
1138 this->w[this->audiofunc].outamp_cap = result;
1139 lead[0] = 0;
1140 #ifdef AZALIA_DEBUG
1141 snprintf(lead, LEAD_LEN, "%s: ", device_xname(this->dev));
1142 azalia_widget_print_audio(&this->w[this->audiofunc], lead, -1);
1143 result = this->w[this->audiofunc].inamp_cap;
1144 DPRINTF(("%sinamp: mute=%u size=%u steps=%u offset=%u\n", lead,
1145 (result & COP_AMPCAP_MUTE) != 0, COP_AMPCAP_STEPSIZE(result),
1146 COP_AMPCAP_NUMSTEPS(result), COP_AMPCAP_OFFSET(result)));
1147 result = this->w[this->audiofunc].outamp_cap;
1148 DPRINTF(("%soutamp: mute=%u size=%u steps=%u offset=%u\n", lead,
1149 (result & COP_AMPCAP_MUTE) != 0, COP_AMPCAP_STEPSIZE(result),
1150 COP_AMPCAP_NUMSTEPS(result), COP_AMPCAP_OFFSET(result)));
1151 #endif
1153 strlcpy(this->w[CORB_NID_ROOT].name, "root",
1154 sizeof(this->w[CORB_NID_ROOT].name));
1155 strlcpy(this->w[this->audiofunc].name, "hdaudio",
1156 sizeof(this->w[this->audiofunc].name));
1157 FOR_EACH_WIDGET(this, i) {
1158 err = azalia_widget_init(&this->w[i], this, i, lead);
1159 if (err)
1160 return err;
1162 #if defined(AZALIA_DEBUG) && defined(AZALIA_DEBUG_DOT)
1163 DPRINTF(("-------- Graphviz DOT starts\n"));
1164 if (this->name == NULL) {
1165 DPRINTF(("digraph \"0x%4.4x/0x%4.4x (rev. %u.%u)\" {\n",
1166 id >> 16, id & 0xffff,
1167 COP_RID_REVISION(rev), COP_RID_STEPPING(rev)));
1168 } else {
1169 DPRINTF(("digraph \"%s (rev. %u.%u)\" {\n", this->name,
1170 COP_RID_REVISION(rev), COP_RID_STEPPING(rev)));
1172 FOR_EACH_WIDGET(this, i) {
1173 const widget_t *w;
1174 int j;
1175 w = &this->w[i];
1176 switch (w->type) {
1177 case COP_AWTYPE_AUDIO_OUTPUT:
1178 DPRINTF((" %s [shape=box,style=filled,fillcolor=\""
1179 "#88ff88\"];\n", w->name));
1180 break;
1181 case COP_AWTYPE_AUDIO_INPUT:
1182 DPRINTF((" %s [shape=box,style=filled,fillcolor=\""
1183 "#ff8888\"];\n", w->name));
1184 break;
1185 case COP_AWTYPE_AUDIO_MIXER:
1186 DPRINTF((" %s [shape=invhouse];\n", w->name));
1187 break;
1188 case COP_AWTYPE_AUDIO_SELECTOR:
1189 DPRINTF((" %s [shape=invtrapezium];\n", w->name));
1190 break;
1191 case COP_AWTYPE_PIN_COMPLEX:
1192 DPRINTF((" %s [label=\"%s\\ndevice=%s\",style=filled",
1193 w->name, w->name, pin_devices[w->d.pin.device]));
1194 if (w->d.pin.cap & COP_PINCAP_OUTPUT &&
1195 w->d.pin.cap & COP_PINCAP_INPUT)
1196 DPRINTF((",shape=doublecircle,fillcolor=\""
1197 "#ffff88\"];\n"));
1198 else if (w->d.pin.cap & COP_PINCAP_OUTPUT)
1199 DPRINTF((",shape=circle,fillcolor=\"#88ff88\"];\n"));
1200 else
1201 DPRINTF((",shape=circle,fillcolor=\"#ff8888\"];\n"));
1202 break;
1204 if ((w->widgetcap & COP_AWCAP_CONNLIST) == 0)
1205 continue;
1206 for (j = 0; j < w->nconnections; j++) {
1207 int src = w->connections[j];
1208 if (!VALID_WIDGET_NID(src, this))
1209 continue;
1210 DPRINTF((" %s -> %s [sametail=%s];\n",
1211 this->w[src].name, w->name, this->w[src].name));
1215 DPRINTF((" {rank=min;"));
1216 FOR_EACH_WIDGET(this, i) {
1217 const widget_t *w;
1218 w = &this->w[i];
1219 switch (w->type) {
1220 case COP_AWTYPE_AUDIO_OUTPUT:
1221 case COP_AWTYPE_AUDIO_INPUT:
1222 DPRINTF((" %s;", w->name));
1223 break;
1226 DPRINTF(("}\n"));
1228 DPRINTF((" {rank=max;"));
1229 FOR_EACH_WIDGET(this, i) {
1230 const widget_t *w;
1231 w = &this->w[i];
1232 switch (w->type) {
1233 case COP_AWTYPE_PIN_COMPLEX:
1234 DPRINTF((" %s;", w->name));
1235 break;
1238 DPRINTF(("}\n"));
1240 DPRINTF(("}\n"));
1241 DPRINTF(("-------- Graphviz DOT ends\n"));
1242 #endif /* AZALIA_DEBUG && AZALIA_DEBUG_DOT */
1244 err = this->init_dacgroup(this);
1245 if (err)
1246 return err;
1247 #ifdef AZALIA_DEBUG
1248 for (i = 0; i < this->dacs.ngroups; i++) {
1249 DPRINTF(("%s: dacgroup[%d]:", __func__, i));
1250 for (n = 0; n < this->dacs.groups[i].nconv; n++) {
1251 DPRINTF((" %2.2x", this->dacs.groups[i].conv[n]));
1253 DPRINTF(("\n"));
1255 #endif
1257 /* set invalid values for azalia_codec_construct_format() to work */
1258 this->dacs.cur = -1;
1259 this->adcs.cur = -1;
1260 err = azalia_codec_construct_format(this,
1261 this->dacs.ngroups > 0 ? 0 : -1,
1262 this->adcs.ngroups > 0 ? 0 : -1);
1263 if (err)
1264 return err;
1266 return this->mixer_init(this);
1269 static int
1270 azalia_codec_delete(codec_t *this)
1272 if (this->mixer_delete != NULL)
1273 this->mixer_delete(this);
1274 if (this->formats != NULL) {
1275 free(this->formats, M_DEVBUF);
1276 this->formats = NULL;
1278 auconv_delete_encodings(this->encodings);
1279 this->encodings = NULL;
1280 if (this->extra != NULL) {
1281 free(this->extra, M_DEVBUF);
1282 this->extra = NULL;
1284 return 0;
1288 azalia_codec_construct_format(codec_t *this, int newdac, int newadc)
1290 #ifdef AZALIA_DEBUG
1291 char flagbuf[FLAGBUFLEN];
1292 #endif
1293 const convgroup_t *group;
1294 uint32_t bits_rates;
1295 int prev_dac, prev_adc;
1296 int variation;
1297 int nbits, c, chan, i, err;
1298 nid_t nid;
1300 variation = 0;
1301 chan = 0;
1303 prev_dac = this->dacs.cur;
1304 if (newdac >= 0 && newdac < this->dacs.ngroups) {
1305 this->dacs.cur = newdac;
1306 group = &this->dacs.groups[this->dacs.cur];
1307 bits_rates = this->w[group->conv[0]].d.audio.bits_rates;
1308 nbits = 0;
1309 if (bits_rates & COP_PCM_B8)
1310 nbits++;
1311 if (bits_rates & COP_PCM_B16)
1312 nbits++;
1313 if (bits_rates & COP_PCM_B20)
1314 nbits++;
1315 if (bits_rates & COP_PCM_B24)
1316 nbits++;
1317 if (bits_rates & COP_PCM_B32)
1318 nbits++;
1319 if (nbits == 0) {
1320 aprint_error("%s: invalid PCM format: 0x%8.8x\n",
1321 device_xname(this->dev), bits_rates);
1322 return -1;
1324 variation = group->nconv * nbits;
1327 prev_adc = this->adcs.cur;
1328 if (newadc >= 0 && newadc < this->adcs.ngroups) {
1329 this->adcs.cur = newadc;
1330 group = &this->adcs.groups[this->adcs.cur];
1331 bits_rates = this->w[group->conv[0]].d.audio.bits_rates;
1332 nbits = 0;
1333 if (bits_rates & COP_PCM_B8)
1334 nbits++;
1335 if (bits_rates & COP_PCM_B16)
1336 nbits++;
1337 if (bits_rates & COP_PCM_B20)
1338 nbits++;
1339 if (bits_rates & COP_PCM_B24)
1340 nbits++;
1341 if (bits_rates & COP_PCM_B32)
1342 nbits++;
1343 if (nbits == 0) {
1344 aprint_error("%s: invalid PCM format: 0x%8.8x\n",
1345 device_xname(this->dev), bits_rates);
1346 return -1;
1348 variation += group->nconv * nbits;
1351 if (this->formats != NULL)
1352 free(this->formats, M_DEVBUF);
1353 this->nformats = 0;
1354 this->formats = malloc(sizeof(struct audio_format) * variation,
1355 M_DEVBUF, M_ZERO | M_NOWAIT);
1356 if (this->formats == NULL) {
1357 aprint_error("%s: out of memory in %s\n",
1358 device_xname(this->dev), __func__);
1359 return ENOMEM;
1362 /* register formats for playback */
1363 if (this->dacs.cur >= 0 && this->dacs.cur < this->dacs.ngroups) {
1364 group = &this->dacs.groups[this->dacs.cur];
1365 for (c = 0; c < group->nconv; c++) {
1366 chan = 0;
1367 bits_rates = ~0;
1368 for (i = 0; i <= c; i++) {
1369 nid = group->conv[i];
1370 chan += WIDGET_CHANNELS(&this->w[nid]);
1371 bits_rates &= this->w[nid].d.audio.bits_rates;
1373 azalia_codec_add_bits(this, chan,
1374 bits_rates, AUMODE_PLAY);
1376 #ifdef AZALIA_DEBUG
1377 /* print playback capability */
1378 if (prev_dac != this->dacs.cur) {
1379 snprintf(flagbuf, FLAGBUFLEN, "%s: playback: ",
1380 device_xname(this->dev));
1381 azalia_widget_print_audio(&this->w[group->conv[0]],
1382 flagbuf, chan);
1384 #endif
1387 /* register formats for recording */
1388 if (this->adcs.cur >= 0 && this->adcs.cur < this->adcs.ngroups) {
1389 group = &this->adcs.groups[this->adcs.cur];
1390 for (c = 0; c < group->nconv; c++) {
1391 chan = 0;
1392 bits_rates = ~0;
1393 for (i = 0; i <= c; i++) {
1394 nid = group->conv[i];
1395 chan += WIDGET_CHANNELS(&this->w[nid]);
1396 bits_rates &= this->w[nid].d.audio.bits_rates;
1398 azalia_codec_add_bits(this, chan,
1399 bits_rates, AUMODE_RECORD);
1401 #ifdef AZALIA_DEBUG
1402 /* print recording capability */
1403 if (prev_adc != this->adcs.cur) {
1404 snprintf(flagbuf, FLAGBUFLEN, "%s: recording: ",
1405 device_xname(this->dev));
1406 azalia_widget_print_audio(&this->w[group->conv[0]],
1407 flagbuf, chan);
1409 #endif
1412 #ifdef DIAGNOSTIC
1413 if (this->nformats > variation) {
1414 aprint_error("%s: Internal error: the format buffer is too small: "
1415 "nformats=%d variation=%d\n", device_xname(this->dev),
1416 this->nformats, variation);
1417 return ENOMEM;
1419 #endif
1421 err = auconv_create_encodings(this->formats, this->nformats,
1422 &this->encodings);
1423 if (err)
1424 return err;
1425 return 0;
1428 static void
1429 azalia_codec_add_bits(codec_t *this, int chan, uint32_t bits_rates, int mode)
1431 if (bits_rates & COP_PCM_B8)
1432 azalia_codec_add_format(this, chan, 8, 16, bits_rates, mode);
1433 if (bits_rates & COP_PCM_B16)
1434 azalia_codec_add_format(this, chan, 16, 16, bits_rates, mode);
1435 if (bits_rates & COP_PCM_B20)
1436 azalia_codec_add_format(this, chan, 20, 32, bits_rates, mode);
1437 if (bits_rates & COP_PCM_B24)
1438 azalia_codec_add_format(this, chan, 24, 32, bits_rates, mode);
1439 if (bits_rates & COP_PCM_B32)
1440 azalia_codec_add_format(this, chan, 32, 32, bits_rates, mode);
1443 static void
1444 azalia_codec_add_format(codec_t *this, int chan, int valid, int prec,
1445 uint32_t rates, int32_t mode)
1447 struct audio_format *f;
1449 f = &this->formats[this->nformats++];
1450 f->mode = mode;
1451 f->encoding = AUDIO_ENCODING_SLINEAR_LE;
1452 if (valid == 8 && prec == 8)
1453 f->encoding = AUDIO_ENCODING_ULINEAR_LE;
1454 f->validbits = valid;
1455 f->precision = prec;
1456 f->channels = chan;
1457 switch (chan) {
1458 case 1:
1459 f->channel_mask = AUFMT_MONAURAL;
1460 break;
1461 case 2:
1462 f->channel_mask = AUFMT_STEREO;
1463 break;
1464 case 4:
1465 f->channel_mask = AUFMT_SURROUND4;
1466 break;
1467 case 6:
1468 f->channel_mask = AUFMT_DOLBY_5_1;
1469 break;
1470 case 8:
1471 f->channel_mask = AUFMT_DOLBY_5_1
1472 | AUFMT_SIDE_LEFT | AUFMT_SIDE_RIGHT;
1473 break;
1474 default:
1475 f->channel_mask = 0;
1477 f->frequency_type = 0;
1478 if (rates & COP_PCM_R80)
1479 f->frequency[f->frequency_type++] = 8000;
1480 if (rates & COP_PCM_R110)
1481 f->frequency[f->frequency_type++] = 11025;
1482 if (rates & COP_PCM_R160)
1483 f->frequency[f->frequency_type++] = 16000;
1484 if (rates & COP_PCM_R220)
1485 f->frequency[f->frequency_type++] = 22050;
1486 if (rates & COP_PCM_R320)
1487 f->frequency[f->frequency_type++] = 32000;
1488 if (rates & COP_PCM_R441)
1489 f->frequency[f->frequency_type++] = 44100;
1490 if (rates & COP_PCM_R480)
1491 f->frequency[f->frequency_type++] = 48000;
1492 if (rates & COP_PCM_R882)
1493 f->frequency[f->frequency_type++] = 88200;
1494 if (rates & COP_PCM_R960)
1495 f->frequency[f->frequency_type++] = 96000;
1496 if (rates & COP_PCM_R1764)
1497 f->frequency[f->frequency_type++] = 176400;
1498 if (rates & COP_PCM_R1920)
1499 f->frequency[f->frequency_type++] = 192000;
1500 if (rates & COP_PCM_R3840)
1501 f->frequency[f->frequency_type++] = 384000;
1504 static int
1505 azalia_codec_comresp(const codec_t *codec, nid_t nid, uint32_t control,
1506 uint32_t param, uint32_t* result)
1508 azalia_t *az = device_private(codec->dev);
1509 int err, s;
1511 s = splaudio();
1512 err = azalia_set_command(az, codec->address, nid, control, param);
1513 if (err)
1514 goto EXIT;
1515 err = azalia_get_response(az, result);
1516 EXIT:
1517 splx(s);
1518 return err;
1521 static int
1522 azalia_codec_connect_stream(codec_t *this, int dir, uint16_t fmt, int number)
1524 const convgroup_t *group;
1525 uint32_t v;
1526 int i, err, startchan, nchan;
1527 nid_t nid;
1528 bool flag222;
1530 DPRINTF(("%s: fmt=0x%4.4x number=%d\n", __func__, fmt, number));
1531 err = 0;
1532 if (dir == AUMODE_RECORD)
1533 group = &this->adcs.groups[this->adcs.cur];
1534 else
1535 group = &this->dacs.groups[this->dacs.cur];
1536 flag222 = group->nconv >= 3 &&
1537 (WIDGET_CHANNELS(&this->w[group->conv[0]]) == 2) &&
1538 (WIDGET_CHANNELS(&this->w[group->conv[1]]) == 2) &&
1539 (WIDGET_CHANNELS(&this->w[group->conv[2]]) == 2);
1540 nchan = (fmt & HDA_SD_FMT_CHAN) + 1;
1541 startchan = 0;
1542 for (i = 0; i < group->nconv; i++) {
1543 uint32_t stream_chan;
1544 nid = group->conv[i];
1546 /* surround and c/lfe handling */
1547 if (nchan >= 6 && flag222 && i == 1) {
1548 nid = group->conv[2];
1549 } else if (nchan >= 6 && flag222 && i == 2) {
1550 nid = group->conv[1];
1553 err = this->comresp(this, nid, CORB_SET_CONVERTER_FORMAT, fmt, NULL);
1554 if (err)
1555 goto exit;
1556 stream_chan = (number << 4) | startchan;
1557 if (startchan >= nchan)
1558 stream_chan = 0; /* stream#0 */
1559 err = this->comresp(this, nid, CORB_SET_CONVERTER_STREAM_CHANNEL,
1560 stream_chan, NULL);
1561 if (err)
1562 goto exit;
1563 if (this->w[nid].widgetcap & COP_AWCAP_DIGITAL) {
1564 /* enable S/PDIF */
1565 this->comresp(this, nid, CORB_GET_DIGITAL_CONTROL,
1566 0, &v);
1567 v = (v & 0xff) | CORB_DCC_DIGEN;
1568 this->comresp(this, nid, CORB_SET_DIGITAL_CONTROL_L,
1569 v, NULL);
1571 startchan += WIDGET_CHANNELS(&this->w[nid]);
1574 exit:
1575 DPRINTF(("%s: leave with %d\n", __func__, err));
1576 return err;
1579 static int
1580 azalia_codec_disconnect_stream(codec_t *this, int dir)
1582 const convgroup_t *group;
1583 uint32_t v;
1584 int i;
1585 nid_t nid;
1587 if (dir == AUMODE_RECORD)
1588 group = &this->adcs.groups[this->adcs.cur];
1589 else
1590 group = &this->dacs.groups[this->dacs.cur];
1591 for (i = 0; i < group->nconv; i++) {
1592 nid = group->conv[i];
1593 this->comresp(this, nid, CORB_SET_CONVERTER_STREAM_CHANNEL,
1594 0, NULL); /* stream#0 */
1595 if (this->w[nid].widgetcap & COP_AWCAP_DIGITAL) {
1596 /* disable S/PDIF */
1597 this->comresp(this, nid, CORB_GET_DIGITAL_CONTROL, 0, &v);
1598 v = (v & ~CORB_DCC_DIGEN) & 0xff;
1599 this->comresp(this, nid, CORB_SET_DIGITAL_CONTROL_L, v, NULL);
1602 return 0;
1605 /* ================================================================
1606 * HDA widget functions
1607 * ================================================================ */
1609 static int
1610 azalia_widget_init(widget_t *this, const codec_t *codec,
1611 nid_t nid, const char *lead)
1613 char flagbuf[FLAGBUFLEN];
1614 uint32_t result;
1615 int err;
1617 err = codec->comresp(codec, nid, CORB_GET_PARAMETER,
1618 COP_AUDIO_WIDGET_CAP, &result);
1619 if (err)
1620 return err;
1621 this->nid = nid;
1622 this->widgetcap = result;
1623 this->type = COP_AWCAP_TYPE(result);
1624 snprintb(flagbuf, sizeof(flagbuf),
1625 "\20\014LRSWAP\013POWER\012DIGITAL"
1626 "\011CONNLIST\010UNSOL\07PROC\06STRIPE\05FORMATOV\04AMPOV\03OUTAMP"
1627 "\02INAMP\01STEREO", this->widgetcap);
1628 DPRINTF(("%s: ", device_xname(codec->dev)));
1629 if (this->widgetcap & COP_AWCAP_POWER) {
1630 codec->comresp(codec, nid, CORB_SET_POWER_STATE, CORB_PS_D0, &result);
1631 DELAY(100);
1633 switch (this->type) {
1634 case COP_AWTYPE_AUDIO_OUTPUT:
1635 snprintf(this->name, sizeof(this->name), "dac%2.2x", nid);
1636 DPRINTF(("%s wcap=%s\n", this->name, flagbuf));
1637 azalia_widget_init_audio(this, codec, lead);
1638 break;
1639 case COP_AWTYPE_AUDIO_INPUT:
1640 snprintf(this->name, sizeof(this->name), "adc%2.2x", nid);
1641 DPRINTF(("%s wcap=%s\n", this->name, flagbuf));
1642 azalia_widget_init_audio(this, codec, lead);
1643 break;
1644 case COP_AWTYPE_AUDIO_MIXER:
1645 snprintf(this->name, sizeof(this->name), "mix%2.2x", nid);
1646 DPRINTF(("%s wcap=%s\n", this->name, flagbuf));
1647 break;
1648 case COP_AWTYPE_AUDIO_SELECTOR:
1649 snprintf(this->name, sizeof(this->name), "sel%2.2x", nid);
1650 DPRINTF(("%s wcap=%s\n", this->name, flagbuf));
1651 break;
1652 case COP_AWTYPE_PIN_COMPLEX:
1653 azalia_widget_init_pin(this, codec);
1654 snprintf(this->name, sizeof(this->name), "%s%2.2x",
1655 pin_colors[this->d.pin.color], nid);
1656 DPRINTF(("%s wcap=%s\n", this->name, flagbuf));
1657 azalia_widget_print_pin(this, lead);
1658 break;
1659 case COP_AWTYPE_POWER:
1660 snprintf(this->name, sizeof(this->name), "pow%2.2x", nid);
1661 DPRINTF(("%s wcap=%s\n", this->name, flagbuf));
1662 break;
1663 case COP_AWTYPE_VOLUME_KNOB:
1664 snprintf(this->name, sizeof(this->name), "volume%2.2x", nid);
1665 DPRINTF(("%s wcap=%s\n", this->name, flagbuf));
1666 err = codec->comresp(codec, nid, CORB_GET_PARAMETER,
1667 COP_VOLUME_KNOB_CAPABILITIES, &result);
1668 if (!err) {
1669 this->d.volume.cap = result;
1670 DPRINTF(("%sdelta=%d steps=%d\n", lead,
1671 !!(result & COP_VKCAP_DELTA),
1672 COP_VKCAP_NUMSTEPS(result)));
1674 break;
1675 case COP_AWTYPE_BEEP_GENERATOR:
1676 snprintf(this->name, sizeof(this->name), "beep%2.2x", nid);
1677 DPRINTF(("%s wcap=%s\n", this->name, flagbuf));
1678 break;
1679 default:
1680 snprintf(this->name, sizeof(this->name), "widget%2.2x", nid);
1681 DPRINTF(("%s wcap=%s\n", this->name, flagbuf));
1682 break;
1684 azalia_widget_init_connection(this, codec, lead);
1686 /* amplifier information */
1687 if (this->widgetcap & COP_AWCAP_INAMP) {
1688 if (this->widgetcap & COP_AWCAP_AMPOV)
1689 codec->comresp(codec, nid, CORB_GET_PARAMETER,
1690 COP_INPUT_AMPCAP, &this->inamp_cap);
1691 else
1692 this->inamp_cap = codec->w[codec->audiofunc].inamp_cap;
1693 DPRINTF(("%sinamp: mute=%u size=%u steps=%u offset=%u\n",
1694 lead, (this->inamp_cap & COP_AMPCAP_MUTE) != 0,
1695 COP_AMPCAP_STEPSIZE(this->inamp_cap),
1696 COP_AMPCAP_NUMSTEPS(this->inamp_cap),
1697 COP_AMPCAP_OFFSET(this->inamp_cap)));
1699 if (this->widgetcap & COP_AWCAP_OUTAMP) {
1700 if (this->widgetcap & COP_AWCAP_AMPOV)
1701 codec->comresp(codec, nid, CORB_GET_PARAMETER,
1702 COP_OUTPUT_AMPCAP, &this->outamp_cap);
1703 else
1704 this->outamp_cap = codec->w[codec->audiofunc].outamp_cap;
1705 DPRINTF(("%soutamp: mute=%u size=%u steps=%u offset=%u\n",
1706 lead, (this->outamp_cap & COP_AMPCAP_MUTE) != 0,
1707 COP_AMPCAP_STEPSIZE(this->outamp_cap),
1708 COP_AMPCAP_NUMSTEPS(this->outamp_cap),
1709 COP_AMPCAP_OFFSET(this->outamp_cap)));
1711 if (codec->init_widget != NULL)
1712 codec->init_widget(codec, this, nid);
1713 return 0;
1716 static int
1717 azalia_widget_init_audio(widget_t *this, const codec_t *codec, const char *lead)
1719 uint32_t result;
1720 int err;
1722 /* check audio format */
1723 if (this->widgetcap & COP_AWCAP_FORMATOV) {
1724 err = codec->comresp(codec, this->nid,
1725 CORB_GET_PARAMETER, COP_STREAM_FORMATS, &result);
1726 if (err)
1727 return err;
1728 this->d.audio.encodings = result;
1729 if (result == 0) { /* quirk for CMI9880.
1730 * This must not occuur usually... */
1731 this->d.audio.encodings =
1732 codec->w[codec->audiofunc].d.audio.encodings;
1733 this->d.audio.bits_rates =
1734 codec->w[codec->audiofunc].d.audio.bits_rates;
1735 } else {
1736 if ((result & COP_STREAM_FORMAT_PCM) == 0) {
1737 aprint_error("%s: %s: No PCM support: %x\n",
1738 device_xname(codec->dev), this->name, result);
1739 return -1;
1741 err = codec->comresp(codec, this->nid, CORB_GET_PARAMETER,
1742 COP_PCM, &result);
1743 if (err)
1744 return err;
1745 this->d.audio.bits_rates = result;
1747 } else {
1748 this->d.audio.encodings =
1749 codec->w[codec->audiofunc].d.audio.encodings;
1750 this->d.audio.bits_rates =
1751 codec->w[codec->audiofunc].d.audio.bits_rates;
1753 #ifdef AZALIA_DEBUG
1754 azalia_widget_print_audio(this, lead, -1);
1755 #endif
1756 return 0;
1759 #ifdef AZALIA_DEBUG
1760 static int
1761 azalia_widget_print_audio(const widget_t *this, const char *lead, int channels)
1763 char flagbuf[FLAGBUFLEN];
1765 snprintb(flagbuf, sizeof(flagbuf),
1766 "\20\3AC3\2FLOAT32\1PCM", this->d.audio.encodings);
1767 if (channels < 0) {
1768 aprint_normal("%sencodings=%s\n", lead, flagbuf);
1769 } else if (this->widgetcap & COP_AWCAP_DIGITAL) {
1770 aprint_normal("%smax channels=%d, DIGITAL, encodings=%s\n",
1771 lead, channels, flagbuf);
1772 } else {
1773 aprint_normal("%smax channels=%d, encodings=%s\n",
1774 lead, channels, flagbuf);
1776 snprintb(flagbuf, sizeof(flagbuf),
1777 "\20\x15""32bit\x14""24bit\x13""20bit"
1778 "\x12""16bit\x11""8bit""\x0c""384kHz\x0b""192kHz\x0a""176.4kHz"
1779 "\x09""96kHz\x08""88.2kHz\x07""48kHz\x06""44.1kHz\x05""32kHz\x04"
1780 "22.05kHz\x03""16kHz\x02""11.025kHz\x01""8kHz",
1781 this->d.audio.bits_rates);
1782 aprint_normal("%sPCM formats=%s\n", lead, flagbuf);
1783 return 0;
1785 #endif
1787 static int
1788 azalia_widget_init_pin(widget_t *this, const codec_t *codec)
1790 uint32_t result;
1791 int err;
1793 err = codec->comresp(codec, this->nid, CORB_GET_CONFIGURATION_DEFAULT,
1794 0, &result);
1795 if (err)
1796 return err;
1797 this->d.pin.config = result;
1798 this->d.pin.sequence = CORB_CD_SEQUENCE(result);
1799 this->d.pin.association = CORB_CD_ASSOCIATION(result);
1800 this->d.pin.color = CORB_CD_COLOR(result);
1801 this->d.pin.device = CORB_CD_DEVICE(result);
1803 err = codec->comresp(codec, this->nid, CORB_GET_PARAMETER,
1804 COP_PINCAP, &result);
1805 if (err)
1806 return err;
1807 this->d.pin.cap = result;
1809 /* input pin */
1810 if ((this->d.pin.cap & COP_PINCAP_INPUT) &&
1811 (this->d.pin.cap & COP_PINCAP_OUTPUT) == 0) {
1812 err = codec->comresp(codec, this->nid,
1813 CORB_GET_PIN_WIDGET_CONTROL, 0, &result);
1814 if (err == 0) {
1815 result &= ~CORB_PWC_OUTPUT;
1816 result |= CORB_PWC_INPUT;
1817 codec->comresp(codec, this->nid,
1818 CORB_SET_PIN_WIDGET_CONTROL, result, NULL);
1821 /* output pin, or bidirectional pin */
1822 if (this->d.pin.cap & COP_PINCAP_OUTPUT) {
1823 err = codec->comresp(codec, this->nid,
1824 CORB_GET_PIN_WIDGET_CONTROL, 0, &result);
1825 if (err == 0) {
1826 result &= ~CORB_PWC_INPUT;
1827 result |= CORB_PWC_OUTPUT;
1828 codec->comresp(codec, this->nid,
1829 CORB_SET_PIN_WIDGET_CONTROL, result, NULL);
1832 return 0;
1835 static int
1836 azalia_widget_print_pin(const widget_t *this, const char *lead)
1838 char flagbuf[FLAGBUFLEN];
1840 DPRINTF(("%spin config; device=%s color=%s assoc=%d seq=%d", lead,
1841 pin_devices[this->d.pin.device], pin_colors[this->d.pin.color],
1842 this->d.pin.association, this->d.pin.sequence));
1843 snprintb(flagbuf, sizeof(flagbuf),
1844 "\20\021EAPD\07BALANCE\06INPUT"
1845 "\05OUTPUT\04HEADPHONE\03PRESENCE\02TRIGGER\01IMPEDANCE",
1846 this->d.pin.cap);
1847 DPRINTF((" cap=%s\n", flagbuf));
1848 return 0;
1851 static int
1852 azalia_widget_init_connection(widget_t *this, const codec_t *codec,
1853 const char *lead)
1855 uint32_t result;
1856 int err;
1857 bool longform;
1858 int length, i;
1860 this->selected = -1;
1861 if ((this->widgetcap & COP_AWCAP_CONNLIST) == 0)
1862 return 0;
1864 err = codec->comresp(codec, this->nid, CORB_GET_PARAMETER,
1865 COP_CONNECTION_LIST_LENGTH, &result);
1866 if (err)
1867 return err;
1868 longform = (result & COP_CLL_LONG) != 0;
1869 length = COP_CLL_LENGTH(result);
1870 if (length == 0)
1871 return 0;
1872 this->nconnections = length;
1873 this->connections = malloc(sizeof(nid_t) * (length + 3),
1874 M_DEVBUF, M_NOWAIT);
1875 if (this->connections == NULL) {
1876 aprint_error("%s: out of memory\n", device_xname(codec->dev));
1877 return ENOMEM;
1879 if (longform) {
1880 for (i = 0; i < length;) {
1881 err = codec->comresp(codec, this->nid,
1882 CORB_GET_CONNECTION_LIST_ENTRY, i, &result);
1883 if (err)
1884 return err;
1885 this->connections[i++] = CORB_CLE_LONG_0(result);
1886 this->connections[i++] = CORB_CLE_LONG_1(result);
1888 } else {
1889 for (i = 0; i < length;) {
1890 err = codec->comresp(codec, this->nid,
1891 CORB_GET_CONNECTION_LIST_ENTRY, i, &result);
1892 if (err)
1893 return err;
1894 this->connections[i++] = CORB_CLE_SHORT_0(result);
1895 this->connections[i++] = CORB_CLE_SHORT_1(result);
1896 this->connections[i++] = CORB_CLE_SHORT_2(result);
1897 this->connections[i++] = CORB_CLE_SHORT_3(result);
1900 if (length > 0) {
1901 DPRINTF(("%sconnections=0x%x", lead, this->connections[0]));
1902 for (i = 1; i < length; i++) {
1903 DPRINTF((",0x%x", this->connections[i]));
1906 err = codec->comresp(codec, this->nid,
1907 CORB_GET_CONNECTION_SELECT_CONTROL, 0, &result);
1908 if (err)
1909 return err;
1910 this->selected = CORB_CSC_INDEX(result);
1911 DPRINTF(("; selected=0x%x\n", this->connections[result]));
1913 return 0;
1916 /* ================================================================
1917 * Stream functions
1918 * ================================================================ */
1920 static int
1921 azalia_stream_init(stream_t *this, azalia_t *az, int regindex, int strnum, int dir)
1923 int err;
1925 this->az = az;
1926 this->regbase = HDA_SD_BASE + regindex * HDA_SD_SIZE;
1927 this->intr_bit = 1 << regindex;
1928 this->number = strnum;
1929 this->dir = dir;
1931 /* setup BDL buffers */
1932 err = azalia_alloc_dmamem(az, sizeof(bdlist_entry_t) * HDA_BDL_MAX,
1933 128, &this->bdlist);
1934 if (err) {
1935 aprint_error_dev(az->dev, "can't allocate a BDL buffer\n");
1936 return err;
1938 return 0;
1941 static int
1942 azalia_stream_delete(stream_t *this, azalia_t *az)
1944 if (this->bdlist.addr == NULL)
1945 return 0;
1946 azalia_free_dmamem(az, &this->bdlist);
1947 return 0;
1950 static int
1951 azalia_stream_reset(stream_t *this)
1953 int i;
1954 uint16_t ctl;
1956 if (this->bdlist.addr == NULL)
1957 return EINVAL;
1958 ctl = STR_READ_2(this, CTL);
1959 STR_WRITE_2(this, CTL, ctl | HDA_SD_CTL_SRST);
1960 for (i = 5000; i >= 0; i--) {
1961 DELAY(10);
1962 ctl = STR_READ_2(this, CTL);
1963 if (ctl & HDA_SD_CTL_SRST)
1964 break;
1966 if (i <= 0) {
1967 aprint_error_dev(this->az->dev, "stream reset failure 1\n");
1968 return -1;
1970 STR_WRITE_2(this, CTL, ctl & ~HDA_SD_CTL_SRST);
1971 for (i = 5000; i >= 0; i--) {
1972 DELAY(10);
1973 ctl = STR_READ_2(this, CTL);
1974 if ((ctl & HDA_SD_CTL_SRST) == 0)
1975 break;
1977 if (i <= 0) {
1978 aprint_error_dev(this->az->dev, "stream reset failure 2\n");
1979 return -1;
1981 return 0;
1984 static int
1985 azalia_stream_start(stream_t *this, void *start, void *end, int blk,
1986 void (*intr)(void *), void *arg, uint16_t fmt)
1988 bdlist_entry_t *bdlist;
1989 bus_addr_t dmaaddr;
1990 int err, index;
1991 uint32_t intctl;
1992 uint8_t ctl, ctl2;
1994 DPRINTF(("%s: start=%p end=%p\n", __func__, start, end));
1995 if (this->bdlist.addr == NULL)
1996 return EINVAL;
1997 this->intr = intr;
1998 this->intr_arg = arg;
2000 err = azalia_stream_reset(this);
2001 if (err)
2002 return err;
2004 /* setup BDL */
2005 dmaaddr = AZALIA_DMA_DMAADDR(&this->buffer);
2006 this->dmaend = dmaaddr + ((char *)end - (char *)start);
2007 bdlist = (bdlist_entry_t*)this->bdlist.addr;
2008 for (index = 0; index < HDA_BDL_MAX; index++) {
2009 bdlist[index].low = dmaaddr;
2010 bdlist[index].high = PTR_UPPER32(dmaaddr);
2011 bdlist[index].length = blk;
2012 bdlist[index].flags = BDLIST_ENTRY_IOC;
2013 dmaaddr += blk;
2014 if (dmaaddr >= this->dmaend) {
2015 index++;
2016 break;
2019 /* The BDL covers the whole of the buffer. */
2020 this->dmanext = AZALIA_DMA_DMAADDR(&this->buffer);
2022 dmaaddr = AZALIA_DMA_DMAADDR(&this->bdlist);
2023 STR_WRITE_4(this, BDPL, dmaaddr);
2024 STR_WRITE_4(this, BDPU, PTR_UPPER32(dmaaddr));
2025 STR_WRITE_2(this, LVI, (index - 1) & HDA_SD_LVI_LVI);
2026 ctl2 = STR_READ_1(this, CTL2);
2027 STR_WRITE_1(this, CTL2,
2028 (ctl2 & ~HDA_SD_CTL2_STRM) | (this->number << HDA_SD_CTL2_STRM_SHIFT));
2029 STR_WRITE_4(this, CBL, ((char *)end - (char *)start));
2031 STR_WRITE_2(this, FMT, fmt);
2033 err = azalia_codec_connect_stream(&this->az->codecs[this->az->codecno],
2034 this->dir, fmt, this->number);
2035 if (err)
2036 return EINVAL;
2038 intctl = AZ_READ_4(this->az, INTCTL);
2039 intctl |= this->intr_bit;
2040 AZ_WRITE_4(this->az, INTCTL, intctl);
2042 ctl = STR_READ_1(this, CTL);
2043 ctl |= ctl | HDA_SD_CTL_DEIE | HDA_SD_CTL_FEIE | HDA_SD_CTL_IOCE | HDA_SD_CTL_RUN;
2044 STR_WRITE_1(this, CTL, ctl);
2045 return 0;
2048 static int
2049 azalia_stream_halt(stream_t *this)
2051 uint16_t ctl;
2053 if (this->bdlist.addr == NULL)
2054 return EINVAL;
2055 this->intr = this->intr_arg = NULL;
2056 ctl = STR_READ_2(this, CTL);
2057 ctl &= ~(HDA_SD_CTL_DEIE | HDA_SD_CTL_FEIE | HDA_SD_CTL_IOCE | HDA_SD_CTL_RUN);
2058 STR_WRITE_2(this, CTL, ctl);
2059 AZ_WRITE_4(this->az, INTCTL, AZ_READ_4(this->az, INTCTL) & ~this->intr_bit);
2060 azalia_codec_disconnect_stream
2061 (&this->az->codecs[this->az->codecno], this->dir);
2062 return 0;
2065 static int
2066 azalia_stream_intr(stream_t *this, uint32_t intsts)
2068 if (this->bdlist.addr == NULL)
2069 return 0;
2070 if ((intsts & this->intr_bit) == 0)
2071 return 0;
2072 STR_WRITE_1(this, STS, HDA_SD_STS_DESE
2073 | HDA_SD_STS_FIFOE | HDA_SD_STS_BCIS);
2075 if (this->intr != NULL)
2076 this->intr(this->intr_arg);
2077 return 1;
2080 /* ================================================================
2081 * MI audio entries
2082 * ================================================================ */
2084 static int
2085 azalia_open(void *v, int flags)
2087 azalia_t *az;
2088 codec_t *codec;
2090 DPRINTF(("%s: flags=0x%x\n", __func__, flags));
2091 az = v;
2092 codec = &az->codecs[az->codecno];
2093 if (flags & FWRITE && (az->mode_cap & AUMODE_PLAY) == 0)
2094 return EACCES;
2095 if (flags & FREAD && (az->mode_cap & AUMODE_RECORD) == 0)
2096 return EACCES;
2097 codec->running++;
2098 return 0;
2101 static void
2102 azalia_close(void *v)
2104 azalia_t *az;
2105 codec_t *codec;
2107 DPRINTF(("%s\n", __func__));
2108 az = v;
2109 codec = &az->codecs[az->codecno];
2110 codec->running--;
2113 static int
2114 azalia_query_encoding(void *v, audio_encoding_t *enc)
2116 azalia_t *az;
2117 codec_t *codec;
2119 az = v;
2120 codec = &az->codecs[az->codecno];
2121 return auconv_query_encoding(codec->encodings, enc);
2124 static int
2125 azalia_set_params(void *v, int smode, int umode, audio_params_t *p,
2126 audio_params_t *r, stream_filter_list_t *pfil, stream_filter_list_t *rfil)
2128 azalia_t *az;
2129 codec_t *codec;
2130 int index;
2132 az = v;
2133 codec = &az->codecs[az->codecno];
2134 smode &= az->mode_cap;
2135 if (smode & AUMODE_RECORD && r != NULL) {
2136 index = auconv_set_converter(codec->formats, codec->nformats,
2137 AUMODE_RECORD, r, TRUE, rfil);
2138 if (index < 0)
2139 return EINVAL;
2141 if (smode & AUMODE_PLAY && p != NULL) {
2142 index = auconv_set_converter(codec->formats, codec->nformats,
2143 AUMODE_PLAY, p, TRUE, pfil);
2144 if (index < 0)
2145 return EINVAL;
2147 return 0;
2150 static int
2151 azalia_round_blocksize(void *v, int blk, int mode,
2152 const audio_params_t *param)
2154 azalia_t *az;
2155 size_t size;
2157 blk &= ~0x7f; /* must be multiple of 128 */
2158 if (blk <= 0)
2159 blk = 128;
2160 /* number of blocks must be <= HDA_BDL_MAX */
2161 az = v;
2162 size = mode == AUMODE_PLAY ? az->pstream.buffer.size : az->rstream.buffer.size;
2163 #ifdef DIAGNOSTIC
2164 if (size <= 0) {
2165 aprint_error("%s: size is 0", __func__);
2166 return 256;
2168 #endif
2169 if (size > HDA_BDL_MAX * blk) {
2170 blk = size / HDA_BDL_MAX;
2171 if (blk & 0x7f)
2172 blk = (blk + 0x7f) & ~0x7f;
2174 DPRINTF(("%s: resultant block size = %d\n", __func__, blk));
2175 return blk;
2178 static int
2179 azalia_halt_output(void *v)
2181 azalia_t *az;
2183 DPRINTF(("%s\n", __func__));
2184 az = v;
2185 return azalia_stream_halt(&az->pstream);
2188 static int
2189 azalia_halt_input(void *v)
2191 azalia_t *az;
2193 DPRINTF(("%s\n", __func__));
2194 az = v;
2195 return azalia_stream_halt(&az->rstream);
2198 static int
2199 azalia_getdev(void *v, struct audio_device *dev)
2201 azalia_t *az;
2203 az = v;
2204 strlcpy(dev->name, "HD-Audio", MAX_AUDIO_DEV_LEN);
2205 snprintf(dev->version, MAX_AUDIO_DEV_LEN,
2206 "%d.%d", AZ_READ_1(az, VMAJ), AZ_READ_1(az, VMIN));
2207 strlcpy(dev->config, device_xname(az->dev), MAX_AUDIO_DEV_LEN);
2208 return 0;
2211 static int
2212 azalia_set_port(void *v, mixer_ctrl_t *mc)
2214 azalia_t *az;
2215 codec_t *co;
2217 az = v;
2218 co = &az->codecs[az->codecno];
2219 return co->set_port(co, mc);
2222 static int
2223 azalia_get_port(void *v, mixer_ctrl_t *mc)
2225 azalia_t *az;
2226 codec_t *co;
2228 az = v;
2229 co = &az->codecs[az->codecno];
2230 return co->get_port(co, mc);
2233 static int
2234 azalia_query_devinfo(void *v, mixer_devinfo_t *mdev)
2236 azalia_t *az;
2237 const codec_t *co;
2239 az = v;
2240 co = &az->codecs[az->codecno];
2241 if (mdev->index >= co->nmixers)
2242 return ENXIO;
2243 *mdev = co->mixers[mdev->index].devinfo;
2244 return 0;
2247 static void *
2248 azalia_allocm(void *v, int dir, size_t size, struct malloc_type *pool,
2249 int flags)
2251 azalia_t *az;
2252 stream_t *stream;
2253 int err;
2255 az = v;
2256 stream = dir == AUMODE_PLAY ? &az->pstream : &az->rstream;
2257 err = azalia_alloc_dmamem(az, size, 128, &stream->buffer);
2258 if (err)
2259 return NULL;
2260 return stream->buffer.addr;
2263 static void
2264 azalia_freem(void *v, void *addr, struct malloc_type *pool)
2266 azalia_t *az;
2267 stream_t *stream;
2269 az = v;
2270 if (addr == az->pstream.buffer.addr) {
2271 stream = &az->pstream;
2272 } else if (addr == az->rstream.buffer.addr) {
2273 stream = &az->rstream;
2274 } else {
2275 return;
2277 azalia_free_dmamem(az, &stream->buffer);
2280 static size_t
2281 azalia_round_buffersize(void *v, int dir, size_t size)
2283 size &= ~0x7f; /* must be multiple of 128 */
2284 if (size <= 0)
2285 size = 128;
2286 return size;
2289 static int
2290 azalia_get_props(void *v)
2292 return AUDIO_PROP_INDEPENDENT | AUDIO_PROP_FULLDUPLEX;
2295 static int
2296 azalia_trigger_output(void *v, void *start, void *end, int blk,
2297 void (*intr)(void *), void *arg, const audio_params_t *param)
2299 azalia_t *az;
2300 int err;
2301 uint16_t fmt;
2303 DPRINTF(("%s: this=%p start=%p end=%p blk=%d {enc=%u %uch %u/%ubit %uHz}\n",
2304 __func__, v, start, end, blk, param->encoding, param->channels,
2305 param->validbits, param->precision, param->sample_rate));
2307 err = azalia_params2fmt(param, &fmt);
2308 if (err)
2309 return EINVAL;
2311 az = v;
2312 return azalia_stream_start(&az->pstream, start, end, blk, intr, arg, fmt);
2315 static int
2316 azalia_trigger_input(void *v, void *start, void *end, int blk,
2317 void (*intr)(void *), void *arg, const audio_params_t *param)
2319 azalia_t *az;
2320 int err;
2321 uint16_t fmt;
2323 DPRINTF(("%s: this=%p start=%p end=%p blk=%d {enc=%u %uch %u/%ubit %uHz}\n",
2324 __func__, v, start, end, blk, param->encoding, param->channels,
2325 param->validbits, param->precision, param->sample_rate));
2327 err = azalia_params2fmt(param, &fmt);
2328 if (err)
2329 return EINVAL;
2331 az = v;
2332 return azalia_stream_start(&az->rstream, start, end, blk, intr, arg, fmt);
2335 /* --------------------------------
2336 * helpers for MI audio functions
2337 * -------------------------------- */
2338 static int
2339 azalia_params2fmt(const audio_params_t *param, uint16_t *fmt)
2341 uint16_t ret;
2343 ret = 0;
2344 #ifdef DIAGNOSTIC
2345 if (param->channels > HDA_MAX_CHANNELS) {
2346 aprint_error("%s: too many channels: %u\n", __func__,
2347 param->channels);
2348 return EINVAL;
2350 #endif
2351 ret |= param->channels - 1;
2353 switch (param->validbits) {
2354 case 8:
2355 ret |= HDA_SD_FMT_BITS_8_16;
2356 break;
2357 case 16:
2358 ret |= HDA_SD_FMT_BITS_16_16;
2359 break;
2360 case 20:
2361 ret |= HDA_SD_FMT_BITS_20_32;
2362 break;
2363 case 24:
2364 ret |= HDA_SD_FMT_BITS_24_32;
2365 break;
2366 case 32:
2367 ret |= HDA_SD_FMT_BITS_32_32;
2368 break;
2369 default:
2370 aprint_error("%s: invalid validbits: %u\n", __func__,
2371 param->validbits);
2374 if (param->sample_rate == 384000) {
2375 aprint_error("%s: invalid sample_rate: %u\n", __func__,
2376 param->sample_rate);
2377 return EINVAL;
2378 } else if (param->sample_rate == 192000) {
2379 ret |= HDA_SD_FMT_BASE_48 | HDA_SD_FMT_MULT_X4 | HDA_SD_FMT_DIV_BY1;
2380 } else if (param->sample_rate == 176400) {
2381 ret |= HDA_SD_FMT_BASE_44 | HDA_SD_FMT_MULT_X4 | HDA_SD_FMT_DIV_BY1;
2382 } else if (param->sample_rate == 96000) {
2383 ret |= HDA_SD_FMT_BASE_48 | HDA_SD_FMT_MULT_X2 | HDA_SD_FMT_DIV_BY1;
2384 } else if (param->sample_rate == 88200) {
2385 ret |= HDA_SD_FMT_BASE_44 | HDA_SD_FMT_MULT_X2 | HDA_SD_FMT_DIV_BY1;
2386 } else if (param->sample_rate == 48000) {
2387 ret |= HDA_SD_FMT_BASE_48 | HDA_SD_FMT_MULT_X1 | HDA_SD_FMT_DIV_BY1;
2388 } else if (param->sample_rate == 44100) {
2389 ret |= HDA_SD_FMT_BASE_44 | HDA_SD_FMT_MULT_X1 | HDA_SD_FMT_DIV_BY1;
2390 } else if (param->sample_rate == 32000) {
2391 ret |= HDA_SD_FMT_BASE_48 | HDA_SD_FMT_MULT_X2 | HDA_SD_FMT_DIV_BY3;
2392 } else if (param->sample_rate == 22050) {
2393 ret |= HDA_SD_FMT_BASE_44 | HDA_SD_FMT_MULT_X1 | HDA_SD_FMT_DIV_BY2;
2394 } else if (param->sample_rate == 16000) {
2395 ret |= HDA_SD_FMT_BASE_48 | HDA_SD_FMT_MULT_X1 | HDA_SD_FMT_DIV_BY3;
2396 } else if (param->sample_rate == 11025) {
2397 ret |= HDA_SD_FMT_BASE_44 | HDA_SD_FMT_MULT_X1 | HDA_SD_FMT_DIV_BY4;
2398 } else if (param->sample_rate == 8000) {
2399 ret |= HDA_SD_FMT_BASE_48 | HDA_SD_FMT_MULT_X1 | HDA_SD_FMT_DIV_BY6;
2400 } else {
2401 aprint_error("%s: invalid sample_rate: %u\n", __func__,
2402 param->sample_rate);
2403 return EINVAL;
2405 *fmt = ret;
2406 return 0;
2409 #ifdef _MODULE
2411 MODULE(MODULE_CLASS_DRIVER, azalia, NULL);
2413 static const struct cfiattrdata audiobuscf_iattrdata = {
2414 "audiobus", 0, { { NULL, NULL, 0 }, }
2416 static const struct cfiattrdata * const azalia_attrs[] = {
2417 &audiobuscf_iattrdata, NULL
2419 CFDRIVER_DECL(azalia, DV_DULL, azalia_attrs);
2420 extern struct cfattach azalia_ca;
2421 static int azalialoc[] = { -1, -1 };
2422 static struct cfparent pciparent = {
2423 "pci", "pci", DVUNIT_ANY
2425 static struct cfdata azalia_cfdata[] = {
2427 .cf_name = "azalia",
2428 .cf_atname = "azalia",
2429 .cf_unit = 0,
2430 .cf_fstate = FSTATE_STAR,
2431 .cf_loc = azalialoc,
2432 .cf_flags = 0,
2433 .cf_pspec = &pciparent,
2435 { NULL }
2438 static int
2439 azalia_modcmd(modcmd_t cmd, void *arg)
2441 int err, s;
2443 switch (cmd) {
2444 case MODULE_CMD_INIT:
2445 err = config_cfdriver_attach(&azalia_cd);
2446 if (err)
2447 return err;
2448 err = config_cfattach_attach("azalia", &azalia_ca);
2449 if (err) {
2450 config_cfdriver_detach(&azalia_cd);
2451 return err;
2453 s = splaudio();
2454 err = config_cfdata_attach(azalia_cfdata, 1);
2455 splx(s);
2456 if (err) {
2457 config_cfattach_detach("azalia", &azalia_ca);
2458 config_cfdriver_detach(&azalia_cd);
2459 return err;
2461 return 0;
2462 case MODULE_CMD_FINI:
2463 err = config_cfdata_detach(azalia_cfdata);
2464 if (err)
2465 return err;
2466 config_cfattach_detach("azalia", &azalia_ca);
2467 config_cfdriver_detach(&azalia_cd);
2468 return 0;
2469 default:
2470 return ENOTTY;
2474 #endif