Annotation of sys/dev/pci/azalia.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: azalia.c,v 1.29 2007/08/02 17:13:31 reyk Exp $ */
2: /* $NetBSD: azalia.c,v 1.20 2006/05/07 08:31:44 kent Exp $ */
3:
4: /*-
5: * Copyright (c) 2005 The NetBSD Foundation, Inc.
6: * All rights reserved.
7: *
8: * This code is derived from software contributed to The NetBSD Foundation
9: * by TAMURA Kent
10: *
11: * Redistribution and use in source and binary forms, with or without
12: * modification, are permitted provided that the following conditions
13: * are met:
14: * 1. Redistributions of source code must retain the above copyright
15: * notice, this list of conditions and the following disclaimer.
16: * 2. Redistributions in binary form must reproduce the above copyright
17: * notice, this list of conditions and the following disclaimer in the
18: * documentation and/or other materials provided with the distribution.
19: * 3. All advertising materials mentioning features or use of this software
20: * must display the following acknowledgement:
21: * This product includes software developed by the NetBSD
22: * Foundation, Inc. and its contributors.
23: * 4. Neither the name of The NetBSD Foundation nor the names of its
24: * contributors may be used to endorse or promote products derived
25: * from this software without specific prior written permission.
26: *
27: * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
28: * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
29: * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
31: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37: * POSSIBILITY OF SUCH DAMAGE.
38: */
39:
40: /*
41: * High Definition Audio Specification
42: * ftp://download.intel.com/standards/hdaudio/pdf/HDAudio_03.pdf
43: *
44: *
45: * TO DO:
46: * - S/PDIF
47: * - power hook
48: * - multiple codecs (needed?)
49: * - multiple streams (needed?)
50: */
51:
52: #include <sys/cdefs.h>
53: #ifdef NETBSD_GOOP
54: __KERNEL_RCSID(0, "$NetBSD: azalia.c,v 1.15 2005/09/29 04:14:03 kent Exp $");
55: #endif
56:
57: #include <sys/param.h>
58: #include <sys/device.h>
59: #include <sys/malloc.h>
60: #include <sys/systm.h>
61: #include <uvm/uvm_param.h>
62: #include <dev/audio_if.h>
63: #include <dev/auconv.h>
64: #include <dev/pci/pcidevs.h>
65: #include <dev/pci/pcivar.h>
66:
67: #include <dev/pci/azalia.h>
68:
69: typedef struct audio_params audio_params_t;
70: #ifndef BUS_DMA_NOCACHE
71: #define BUS_DMA_NOCACHE 0
72: #endif
73: #define auconv_delete_encodings(x...)
74: #define auconv_query_encoding(x...) (EINVAL)
75: #define auconv_create_encodings(x...) (0)
76:
77: struct audio_format {
78: void *driver_data;
79: int32_t mode;
80: u_int encoding;
81: u_int validbits;
82: u_int precision;
83: u_int channels;
84: u_int channel_mask;
85: #define AUFMT_UNKNOWN_POSITION 0U
86: #define AUFMT_FRONT_LEFT 0x00001U /* USB audio compatible */
87: #define AUFMT_FRONT_RIGHT 0x00002U /* USB audio compatible */
88: #define AUFMT_FRONT_CENTER 0x00004U /* USB audio compatible */
89: #define AUFMT_LOW_FREQUENCY 0x00008U /* USB audio compatible */
90: #define AUFMT_BACK_LEFT 0x00010U /* USB audio compatible */
91: #define AUFMT_BACK_RIGHT 0x00020U /* USB audio compatible */
92: #define AUFMT_FRONT_LEFT_OF_CENTER 0x00040U /* USB audio compatible */
93: #define AUFMT_FRONT_RIGHT_OF_CENTER 0x00080U /* USB audio compatible */
94: #define AUFMT_BACK_CENTER 0x00100U /* USB audio compatible */
95: #define AUFMT_SIDE_LEFT 0x00200U /* USB audio compatible */
96: #define AUFMT_SIDE_RIGHT 0x00400U /* USB audio compatible */
97: #define AUFMT_TOP_CENTER 0x00800U /* USB audio compatible */
98: #define AUFMT_TOP_FRONT_LEFT 0x01000U
99: #define AUFMT_TOP_FRONT_CENTER 0x02000U
100: #define AUFMT_TOP_FRONT_RIGHT 0x04000U
101: #define AUFMT_TOP_BACK_LEFT 0x08000U
102: #define AUFMT_TOP_BACK_CENTER 0x10000U
103: #define AUFMT_TOP_BACK_RIGHT 0x20000U
104:
105: #define AUFMT_MONAURAL AUFMT_FRONT_CENTER
106: #define AUFMT_STEREO (AUFMT_FRONT_LEFT | AUFMT_FRONT_RIGHT)
107: #define AUFMT_SURROUND4 (AUFMT_STEREO | AUFMT_BACK_LEFT \
108: | AUFMT_BACK_RIGHT)
109: #define AUFMT_DOLBY_5_1 (AUFMT_SURROUND4 | AUFMT_FRONT_CENTER \
110: | AUFMT_LOW_FREQUENCY)
111:
112: /**
113: * 0: frequency[0] is lower limit, and frequency[1] is higher limit.
114: * 1-16: frequency[0] to frequency[frequency_type-1] are valid.
115: */
116: u_int frequency_type;
117:
118: #define AUFMT_MAX_FREQUENCIES 16
119: /**
120: * sampling rates
121: */
122: u_int frequency[AUFMT_MAX_FREQUENCIES];
123: };
124:
125: #define AUFMT_INVALIDATE(fmt) (fmt)->mode |= 0x80000000
126: #define AUFMT_VALIDATE(fmt) (fmt)->mode &= 0x7fffffff
127: #define AUFMT_IS_VALID(fmt) (((fmt)->mode & 0x80000000) == 0)
128:
129: /* ----------------------------------------------------------------
130: * ICH6/ICH7 constant values
131: * ---------------------------------------------------------------- */
132:
133: /* PCI registers */
134: #define ICH_PCI_HDBARL 0x10
135: #define ICH_PCI_HDBARU 0x14
136: #define ICH_PCI_HDCTL 0x40
137: #define ICH_PCI_HDCTL_CLKDETCLR 0x08
138: #define ICH_PCI_HDCTL_CLKDETEN 0x04
139: #define ICH_PCI_HDCTL_CLKDETINV 0x02
140: #define ICH_PCI_HDCTL_SIGNALMODE 0x01
141:
142: /* internal types */
143:
144: typedef struct {
145: bus_dmamap_t map;
146: caddr_t addr; /* kernel virtual address */
147: bus_dma_segment_t segments[1];
148: size_t size;
149: } azalia_dma_t;
150: #define AZALIA_DMA_DMAADDR(p) ((p)->map->dm_segs[0].ds_addr)
151:
152: typedef struct {
153: struct azalia_t *az;
154: int regbase;
155: int number;
156: int dir; /* AUMODE_PLAY or AUMODE_RECORD */
157: uint32_t intr_bit;
158: azalia_dma_t bdlist;
159: azalia_dma_t buffer;
160: void (*intr)(void*);
161: void *intr_arg;
162: } stream_t;
163: #define STR_READ_1(s, r) \
164: bus_space_read_1((s)->az->iot, (s)->az->ioh, (s)->regbase + HDA_SD_##r)
165: #define STR_READ_2(s, r) \
166: bus_space_read_2((s)->az->iot, (s)->az->ioh, (s)->regbase + HDA_SD_##r)
167: #define STR_READ_4(s, r) \
168: bus_space_read_4((s)->az->iot, (s)->az->ioh, (s)->regbase + HDA_SD_##r)
169: #define STR_WRITE_1(s, r, v) \
170: bus_space_write_1((s)->az->iot, (s)->az->ioh, (s)->regbase + HDA_SD_##r, v)
171: #define STR_WRITE_2(s, r, v) \
172: bus_space_write_2((s)->az->iot, (s)->az->ioh, (s)->regbase + HDA_SD_##r, v)
173: #define STR_WRITE_4(s, r, v) \
174: bus_space_write_4((s)->az->iot, (s)->az->ioh, (s)->regbase + HDA_SD_##r, v)
175:
176: typedef struct azalia_t {
177: struct device dev;
178: struct device *audiodev;
179:
180: pci_chipset_tag_t pc;
181: void *ih;
182: bus_space_tag_t iot;
183: bus_space_handle_t ioh;
184: bus_size_t map_size;
185: bus_dma_tag_t dmat;
186: pcireg_t pciid;
187: uint32_t subid;
188:
189: codec_t codecs[15];
190: int ncodecs; /* number of codecs */
191: int codecno; /* index of the using codec */
192:
193: azalia_dma_t corb_dma;
194: int corb_size;
195: azalia_dma_t rirb_dma;
196: int rirb_size;
197: int rirb_rp;
198: #define UNSOLQ_SIZE 256
199: rirb_entry_t *unsolq;
200: int unsolq_wp;
201: int unsolq_rp;
202: boolean_t unsolq_kick;
203:
204: boolean_t ok64;
205: int nistreams, nostreams, nbstreams;
206: stream_t pstream;
207: stream_t rstream;
208: } azalia_t;
209: #define XNAME(sc) ((sc)->dev.dv_xname)
210: #define AZ_READ_1(z, r) bus_space_read_1((z)->iot, (z)->ioh, HDA_##r)
211: #define AZ_READ_2(z, r) bus_space_read_2((z)->iot, (z)->ioh, HDA_##r)
212: #define AZ_READ_4(z, r) bus_space_read_4((z)->iot, (z)->ioh, HDA_##r)
213: #define AZ_WRITE_1(z, r, v) bus_space_write_1((z)->iot, (z)->ioh, HDA_##r, v)
214: #define AZ_WRITE_2(z, r, v) bus_space_write_2((z)->iot, (z)->ioh, HDA_##r, v)
215: #define AZ_WRITE_4(z, r, v) bus_space_write_4((z)->iot, (z)->ioh, HDA_##r, v)
216:
217:
218: /* prototypes */
219: int azalia_pci_match(struct device *, void *, void *);
220: void azalia_pci_attach(struct device *, struct device *, void *);
221: int azalia_pci_activate(struct device *, enum devact);
222: int azalia_pci_detach(struct device *, int);
223: int azalia_intr(void *);
224: int azalia_attach(azalia_t *);
225: void azalia_attach_intr(struct device *);
226: int azalia_init_corb(azalia_t *);
227: int azalia_delete_corb(azalia_t *);
228: int azalia_init_rirb(azalia_t *);
229: int azalia_delete_rirb(azalia_t *);
230: int azalia_set_command(azalia_t *, nid_t, int, uint32_t,
231: uint32_t);
232: int azalia_get_response(azalia_t *, uint32_t *);
233: void azalia_rirb_kick_unsol_events(azalia_t *);
234: void azalia_rirb_intr(azalia_t *);
235: int azalia_alloc_dmamem(azalia_t *, size_t, size_t, azalia_dma_t *);
236: int azalia_free_dmamem(const azalia_t *, azalia_dma_t*);
237:
238: int azalia_codec_init(codec_t *);
239: int azalia_codec_delete(codec_t *);
240: void azalia_codec_add_bits(codec_t *, int, uint32_t, int);
241: void azalia_codec_add_format(codec_t *, int, int, int, uint32_t,
242: int32_t);
243: int azalia_codec_comresp(const codec_t *, nid_t, uint32_t,
244: uint32_t, uint32_t *);
245: int azalia_codec_connect_stream(codec_t *, int, uint16_t, int);
246:
247: int azalia_widget_init(widget_t *, const codec_t *, int);
248: int azalia_widget_init_audio(widget_t *, const codec_t *);
249: int azalia_widget_print_audio(const widget_t *, const char *);
250: int azalia_widget_init_pin(widget_t *, const codec_t *);
251: int azalia_widget_print_pin(const widget_t *);
252: int azalia_widget_init_connection(widget_t *, const codec_t *);
253:
254: int azalia_stream_init(stream_t *, azalia_t *, int, int, int);
255: int azalia_stream_delete(stream_t *, azalia_t *);
256: int azalia_stream_reset(stream_t *);
257: int azalia_stream_start(stream_t *, void *, void *, int,
258: void (*)(void *), void *, uint16_t);
259: int azalia_stream_halt(stream_t *);
260: int azalia_stream_intr(stream_t *, uint32_t);
261:
262: int azalia_open(void *, int);
263: void azalia_close(void *);
264: int azalia_query_encoding(void *, audio_encoding_t *);
265: int azalia_set_params(void *, int, int, audio_params_t *,
266: audio_params_t *);
267: int azalia_round_blocksize(void *, int);
268: int azalia_halt_output(void *);
269: int azalia_halt_input(void *);
270: int azalia_getdev(void *, struct audio_device *);
271: int azalia_set_port(void *, mixer_ctrl_t *);
272: int azalia_get_port(void *, mixer_ctrl_t *);
273: int azalia_query_devinfo(void *, mixer_devinfo_t *);
274: void *azalia_allocm(void *, int, size_t, int, int);
275: void azalia_freem(void *, void *, int);
276: size_t azalia_round_buffersize(void *, int, size_t);
277: int azalia_get_props(void *);
278: int azalia_trigger_output(void *, void *, void *, int,
279: void (*)(void *), void *, audio_params_t *);
280: int azalia_trigger_input(void *, void *, void *, int,
281: void (*)(void *), void *, audio_params_t *);
282:
283: int azalia_params2fmt(const audio_params_t *, uint16_t *);
284: int azalia_create_encodings(struct audio_format *, int,
285: struct audio_encoding_set **);
286:
287: /* variables */
288: struct cfattach azalia_ca = {
289: sizeof(azalia_t), azalia_pci_match, azalia_pci_attach,
290: azalia_pci_detach, azalia_pci_activate
291: };
292:
293: struct cfdriver azalia_cd = {
294: NULL, "azalia", DV_DULL
295: };
296:
297: struct audio_hw_if azalia_hw_if = {
298: azalia_open,
299: azalia_close,
300: NULL, /* drain */
301: azalia_query_encoding,
302: azalia_set_params,
303: azalia_round_blocksize,
304: NULL, /* commit_settings */
305: NULL, /* init_output */
306: NULL, /* init_input */
307: NULL, /* start_output */
308: NULL, /* start_input */
309: azalia_halt_output,
310: azalia_halt_input,
311: NULL, /* speaker_ctl */
312: azalia_getdev,
313: NULL, /* setfd */
314: azalia_set_port,
315: azalia_get_port,
316: azalia_query_devinfo,
317: azalia_allocm,
318: azalia_freem,
319: azalia_round_buffersize,
320: NULL, /* mappage */
321: azalia_get_props,
322: azalia_trigger_output,
323: azalia_trigger_input,
324: };
325:
326: static const char *pin_colors[16] = {
327: "unknown", "black", "gray", "blue",
328: "green", "red", "orange", "yellow",
329: "purple", "pink", "col0a", "col0b",
330: "col0c", "col0d", "white", "other"};
331: #ifdef AZALIA_DEBUG
332: static const char *pin_devices[16] = {
333: "line-out", AudioNspeaker, AudioNheadphone, AudioNcd,
334: "SPDIF-out", "digital-out", "modem-line", "modem-handset",
335: "line-in", AudioNaux, AudioNmicrophone, "telephony",
336: "SPDIF-in", "digital-in", "dev0e", "other"};
337: #endif
338:
339: /* ================================================================
340: * PCI functions
341: * ================================================================ */
342:
343: #define PCI_ID_CODE0(v, p) PCI_ID_CODE(PCI_VENDOR_##v, PCI_PRODUCT_##v##_##p)
344: #define PCIID_NVIDIA_MCP51 PCI_ID_CODE0(NVIDIA, MCP51_HDA)
345: #define PCIID_NVIDIA_MCP55 PCI_ID_CODE0(NVIDIA, MCP55_HDA)
346: #define PCIID_ALI_M5461 PCI_ID_CODE0(ALI, M5461)
347: #define PCIID_VIATECH_HDA PCI_ID_CODE0(VIATECH, HDA)
348:
349: int
350: azalia_pci_match(struct device *parent, void *match, void *aux)
351: {
352: struct pci_attach_args *pa;
353:
354: pa = aux;
355: if (PCI_CLASS(pa->pa_class) == PCI_CLASS_MULTIMEDIA
356: && PCI_SUBCLASS(pa->pa_class) == PCI_SUBCLASS_MULTIMEDIA_HDAUDIO)
357: return 1;
358: return 0;
359: }
360:
361: void
362: azalia_pci_attach(struct device *parent, struct device *self, void *aux)
363: {
364: azalia_t *sc;
365: struct pci_attach_args *pa;
366: pcireg_t v;
367: pci_intr_handle_t ih;
368: const char *intrrupt_str;
369:
370: sc = (azalia_t*)self;
371: pa = aux;
372:
373: sc->dmat = pa->pa_dmat;
374:
375: v = pci_conf_read(pa->pa_pc, pa->pa_tag, ICH_PCI_HDBARL);
376: v &= PCI_MAPREG_TYPE_MASK | PCI_MAPREG_MEM_TYPE_MASK;
377: if (pci_mapreg_map(pa, ICH_PCI_HDBARL, v, 0,
378: &sc->iot, &sc->ioh, NULL, &sc->map_size, 0)) {
379: printf(": can't map device i/o space\n");
380: return;
381: }
382:
383: /* enable back-to-back */
384: v = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG);
385: pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG,
386: v | PCI_COMMAND_BACKTOBACK_ENABLE);
387:
388: v = pci_conf_read(pa->pa_pc, pa->pa_tag, 0x44);
389: pci_conf_write(pa->pa_pc, pa->pa_tag, 0x44, v & (~0x7));
390:
391: /* interrupt */
392: if (pci_intr_map(pa, &ih)) {
393: printf(": can't map interrupt\n");
394: return;
395: }
396: sc->pc = pa->pa_pc;
397: intrrupt_str = pci_intr_string(pa->pa_pc, ih);
398: sc->ih = pci_intr_establish(pa->pa_pc, ih, IPL_AUDIO, azalia_intr,
399: sc, sc->dev.dv_xname);
400: if (sc->ih == NULL) {
401: printf(": can't establish interrupt");
402: if (intrrupt_str != NULL)
403: printf(" at %s", intrrupt_str);
404: printf("\n");
405: return;
406: }
407: printf(": %s\n", intrrupt_str);
408:
409: sc->pciid = pa->pa_id;
410:
411: if (azalia_attach(sc)) {
412: printf("%s: initialization failure\n", XNAME(sc));
413: azalia_pci_detach(self, 0);
414: return;
415: }
416: sc->subid = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_SUBSYS_ID_REG);
417:
418: azalia_attach_intr(self);
419: }
420:
421: int
422: azalia_pci_activate(struct device *self, enum devact act)
423: {
424: azalia_t *sc;
425: int ret;
426:
427: sc = (azalia_t*)self;
428: ret = 0;
429: switch (act) {
430: case DVACT_ACTIVATE:
431: return ret;
432: case DVACT_DEACTIVATE:
433: if (sc->audiodev != NULL)
434: ret = config_deactivate(sc->audiodev);
435: return ret;
436: }
437: return EOPNOTSUPP;
438: }
439:
440: int
441: azalia_pci_detach(struct device *self, int flags)
442: {
443: azalia_t *az;
444: int i;
445:
446: DPRINTF(("%s\n", __func__));
447: az = (azalia_t*)self;
448: if (az->audiodev != NULL) {
449: config_detach(az->audiodev, flags);
450: az->audiodev = NULL;
451: }
452:
453: DPRINTF(("%s: delete streams\n", __func__));
454: azalia_stream_delete(&az->rstream, az);
455: azalia_stream_delete(&az->pstream, az);
456:
457: DPRINTF(("%s: delete codecs\n", __func__));
458: for (i = 0; i < az->ncodecs; i++) {
459: azalia_codec_delete(&az->codecs[i]);
460: }
461: az->ncodecs = 0;
462:
463: DPRINTF(("%s: delete CORB and RIRB\n", __func__));
464: azalia_delete_corb(az);
465: azalia_delete_rirb(az);
466:
467: DPRINTF(("%s: delete PCI resources\n", __func__));
468: if (az->ih != NULL) {
469: pci_intr_disestablish(az->pc, az->ih);
470: az->ih = NULL;
471: }
472: if (az->map_size != 0) {
473: bus_space_unmap(az->iot, az->ioh, az->map_size);
474: az->map_size = 0;
475: }
476: return 0;
477: }
478:
479: int
480: azalia_intr(void *v)
481: {
482: azalia_t *az = v;
483: int ret = 0;
484: uint32_t intsts;
485: uint8_t rirbsts, rirbctl;
486:
487: intsts = AZ_READ_4(az, INTSTS);
488: if (intsts == 0)
489: return (0);
490:
491: AZ_WRITE_4(az, INTSTS, intsts);
492:
493: ret += azalia_stream_intr(&az->pstream, intsts);
494: ret += azalia_stream_intr(&az->rstream, intsts);
495:
496: rirbctl = AZ_READ_1(az, RIRBCTL);
497: rirbsts = AZ_READ_1(az, RIRBSTS);
498:
499: if (intsts & HDA_INTCTL_CIE) {
500: if (rirbctl & HDA_RIRBCTL_RINTCTL) {
501: if (rirbsts & HDA_RIRBSTS_RINTFL)
502: azalia_rirb_intr(az);
503: }
504: }
505:
506: return (1);
507: }
508:
509: /* ================================================================
510: * HDA controller functions
511: * ================================================================ */
512:
513: int
514: azalia_attach(azalia_t *az)
515: {
516: int i, n;
517: uint32_t gctl;
518: uint16_t gcap;
519: uint16_t statests;
520:
521: printf("%s: host: High Definition Audio rev. %d.%d\n",
522: XNAME(az), AZ_READ_1(az, VMAJ), AZ_READ_1(az, VMIN));
523: gcap = AZ_READ_2(az, GCAP);
524: az->nistreams = HDA_GCAP_ISS(gcap);
525: az->nostreams = HDA_GCAP_OSS(gcap);
526: az->nbstreams = HDA_GCAP_BSS(gcap);
527: az->ok64 = (gcap & HDA_GCAP_64OK) != 0;
528: DPRINTF(("%s: host: %d output, %d input, and %d bidi streams\n",
529: XNAME(az), az->nostreams, az->nistreams, az->nbstreams));
530:
531: /* 4.2.2 Starting the High Definition Audio Controller */
532: DPRINTF(("%s: resetting\n", __func__));
533: gctl = AZ_READ_4(az, GCTL);
534: AZ_WRITE_4(az, GCTL, gctl & ~HDA_GCTL_CRST);
535: for (i = 5000; i >= 0; i--) {
536: DELAY(10);
537: if ((AZ_READ_4(az, GCTL) & HDA_GCTL_CRST) == 0)
538: break;
539: }
540: DPRINTF(("%s: reset counter = %d\n", __func__, i));
541: if (i <= 0) {
542: printf("%s: reset failure\n", XNAME(az));
543: return ETIMEDOUT;
544: }
545: DELAY(1000);
546: gctl = AZ_READ_4(az, GCTL);
547: AZ_WRITE_4(az, GCTL, gctl | HDA_GCTL_CRST);
548: for (i = 5000; i >= 0; i--) {
549: DELAY(10);
550: if (AZ_READ_4(az, GCTL) & HDA_GCTL_CRST)
551: break;
552: }
553: DPRINTF(("%s: reset counter = %d\n", __func__, i));
554: if (i <= 0) {
555: printf("%s: reset-exit failure\n", XNAME(az));
556: return ETIMEDOUT;
557: }
558:
559: /* enable unsolicited response */
560: gctl = AZ_READ_4(az, GCTL);
561: AZ_WRITE_4(az, GCTL, gctl | HDA_GCTL_UNSOL);
562:
563: /* 4.3 Codec discovery */
564: DELAY(1000);
565: statests = AZ_READ_2(az, STATESTS);
566: for (i = 0, n = 0; i < 15; i++) {
567: if ((statests >> i) & 1) {
568: DPRINTF(("%s: found a codec at #%d\n", XNAME(az), i));
569: az->codecs[n].address = i;
570: az->codecs[n++].az = az;
571: }
572: }
573: az->ncodecs = n;
574: if (az->ncodecs < 1) {
575: printf("%s: No HD-Audio codecs\n", XNAME(az));
576: return -1;
577: }
578: return 0;
579: }
580:
581: void
582: azalia_attach_intr(struct device *self)
583: {
584: azalia_t *az;
585: int err, i, c;
586:
587: az = (azalia_t*)self;
588:
589: AZ_WRITE_2(az, STATESTS, HDA_STATESTS_SDIWAKE);
590: AZ_WRITE_1(az, RIRBSTS, HDA_RIRBSTS_RINTFL | HDA_RIRBSTS_RIRBOIS);
591: AZ_WRITE_4(az, INTSTS, HDA_INTSTS_CIS | HDA_INTSTS_GIS);
592: AZ_WRITE_4(az, DPLBASE, 0);
593: AZ_WRITE_4(az, DPUBASE, 0);
594:
595: /* 4.4.1 Command Outbound Ring Buffer */
596: if (azalia_init_corb(az))
597: goto err_exit;
598: /* 4.4.2 Response Inbound Ring Buffer */
599: if (azalia_init_rirb(az))
600: goto err_exit;
601:
602: AZ_WRITE_4(az, INTCTL,
603: AZ_READ_4(az, INTCTL) | HDA_INTCTL_CIE | HDA_INTCTL_GIE);
604:
605: c = -1;
606: for (i = 0; i < az->ncodecs; i++) {
607: err = azalia_codec_init(&az->codecs[i]);
608: if (!err && c < 0)
609: c = i;
610: }
611: if (c < 0)
612: goto err_exit;
613: /* Use the first audio codec */
614: az->codecno = c;
615: DPRINTF(("%s: using the #%d codec\n", XNAME(az), az->codecno));
616:
617: if (azalia_stream_init(&az->pstream, az, az->nistreams + 0,
618: 1, AUMODE_PLAY))
619: goto err_exit;
620: if (azalia_stream_init(&az->rstream, az, 0, 2, AUMODE_RECORD))
621: goto err_exit;
622:
623: az->audiodev = audio_attach_mi(&azalia_hw_if, az, &az->dev);
624: return;
625: err_exit:
626: azalia_pci_detach(self, 0);
627: return;
628: }
629:
630: int
631: azalia_init_corb(azalia_t *az)
632: {
633: int entries, err, i;
634: uint16_t corbrp, corbwp;
635: uint8_t corbsize, cap, corbctl;
636:
637: /* stop the CORB */
638: corbctl = AZ_READ_1(az, CORBCTL);
639: if (corbctl & HDA_CORBCTL_CORBRUN) { /* running? */
640: AZ_WRITE_1(az, CORBCTL, corbctl & ~HDA_CORBCTL_CORBRUN);
641: for (i = 5000; i >= 0; i--) {
642: DELAY(10);
643: corbctl = AZ_READ_1(az, CORBCTL);
644: if ((corbctl & HDA_CORBCTL_CORBRUN) == 0)
645: break;
646: }
647: if (i <= 0) {
648: printf("%s: CORB is running\n", XNAME(az));
649: return EBUSY;
650: }
651: }
652:
653: /* determine CORB size */
654: corbsize = AZ_READ_1(az, CORBSIZE);
655: cap = corbsize & HDA_CORBSIZE_CORBSZCAP_MASK;
656: corbsize &= ~HDA_CORBSIZE_CORBSIZE_MASK;
657: if (cap & HDA_CORBSIZE_CORBSZCAP_256) {
658: entries = 256;
659: corbsize |= HDA_CORBSIZE_CORBSIZE_256;
660: } else if (cap & HDA_CORBSIZE_CORBSZCAP_16) {
661: entries = 16;
662: corbsize |= HDA_CORBSIZE_CORBSIZE_16;
663: } else if (cap & HDA_CORBSIZE_CORBSZCAP_2) {
664: entries = 2;
665: corbsize |= HDA_CORBSIZE_CORBSIZE_2;
666: } else {
667: printf("%s: Invalid CORBSZCAP: 0x%2x\n", XNAME(az), cap);
668: return -1;
669: }
670:
671: err = azalia_alloc_dmamem(az, entries * sizeof(corb_entry_t),
672: 128, &az->corb_dma);
673: if (err) {
674: printf("%s: can't allocate CORB buffer\n", XNAME(az));
675: return err;
676: }
677: AZ_WRITE_4(az, CORBLBASE, (uint32_t)AZALIA_DMA_DMAADDR(&az->corb_dma));
678: AZ_WRITE_4(az, CORBUBASE, PTR_UPPER32(AZALIA_DMA_DMAADDR(&az->corb_dma)));
679: AZ_WRITE_1(az, CORBSIZE, corbsize);
680: az->corb_size = entries;
681:
682: DPRINTF(("%s: CORB allocation succeeded.\n", __func__));
683:
684: /* reset CORBRP */
685: corbrp = AZ_READ_2(az, CORBRP);
686: AZ_WRITE_2(az, CORBRP, corbrp | HDA_CORBRP_CORBRPRST);
687: AZ_WRITE_2(az, CORBRP, corbrp & ~HDA_CORBRP_CORBRPRST);
688: for (i = 5000; i >= 0; i--) {
689: DELAY(10);
690: corbrp = AZ_READ_2(az, CORBRP);
691: if ((corbrp & HDA_CORBRP_CORBRPRST) == 0)
692: break;
693: }
694: if (i <= 0) {
695: printf("%s: CORBRP reset failure\n", XNAME(az));
696: return -1;
697: }
698: DPRINTF(("%s: CORBWP=%d; size=%d\n", __func__,
699: AZ_READ_2(az, CORBRP) & HDA_CORBRP_CORBRP, az->corb_size));
700:
701: /* clear CORBWP */
702: corbwp = AZ_READ_2(az, CORBWP);
703: AZ_WRITE_2(az, CORBWP, corbwp & ~HDA_CORBWP_CORBWP);
704:
705: /* Run! */
706: corbctl = AZ_READ_1(az, CORBCTL);
707: AZ_WRITE_1(az, CORBCTL, corbctl | HDA_CORBCTL_CORBRUN);
708: return 0;
709: }
710:
711: int
712: azalia_delete_corb(azalia_t *az)
713: {
714: int i;
715: uint8_t corbctl;
716:
717: if (az->corb_dma.addr == NULL)
718: return 0;
719: /* stop the CORB */
720: corbctl = AZ_READ_1(az, CORBCTL);
721: AZ_WRITE_1(az, CORBCTL, corbctl & ~HDA_CORBCTL_CORBRUN);
722: for (i = 5000; i >= 0; i--) {
723: DELAY(10);
724: corbctl = AZ_READ_1(az, CORBCTL);
725: if ((corbctl & HDA_CORBCTL_CORBRUN) == 0)
726: break;
727: }
728: azalia_free_dmamem(az, &az->corb_dma);
729: return 0;
730: }
731:
732: int
733: azalia_init_rirb(azalia_t *az)
734: {
735: int entries, err, i;
736: uint16_t rirbwp;
737: uint8_t rirbsize, cap, rirbctl;
738:
739: /* stop the RIRB */
740: rirbctl = AZ_READ_1(az, RIRBCTL);
741: if (rirbctl & HDA_RIRBCTL_RIRBDMAEN) { /* running? */
742: AZ_WRITE_1(az, RIRBCTL, rirbctl & ~HDA_RIRBCTL_RIRBDMAEN);
743: for (i = 5000; i >= 0; i--) {
744: DELAY(10);
745: rirbctl = AZ_READ_1(az, RIRBCTL);
746: if ((rirbctl & HDA_RIRBCTL_RIRBDMAEN) == 0)
747: break;
748: }
749: if (i <= 0) {
750: printf("%s: RIRB is running\n", XNAME(az));
751: return EBUSY;
752: }
753: }
754:
755: /* determine RIRB size */
756: rirbsize = AZ_READ_1(az, RIRBSIZE);
757: cap = rirbsize & HDA_RIRBSIZE_RIRBSZCAP_MASK;
758: rirbsize &= ~HDA_RIRBSIZE_RIRBSIZE_MASK;
759: if (cap & HDA_RIRBSIZE_RIRBSZCAP_256) {
760: entries = 256;
761: rirbsize |= HDA_RIRBSIZE_RIRBSIZE_256;
762: } else if (cap & HDA_RIRBSIZE_RIRBSZCAP_16) {
763: entries = 16;
764: rirbsize |= HDA_RIRBSIZE_RIRBSIZE_16;
765: } else if (cap & HDA_RIRBSIZE_RIRBSZCAP_2) {
766: entries = 2;
767: rirbsize |= HDA_RIRBSIZE_RIRBSIZE_2;
768: } else {
769: printf("%s: Invalid RIRBSZCAP: 0x%2x\n", XNAME(az), cap);
770: return -1;
771: }
772:
773: err = azalia_alloc_dmamem(az, entries * sizeof(rirb_entry_t),
774: 128, &az->rirb_dma);
775: if (err) {
776: printf("%s: can't allocate RIRB buffer\n", XNAME(az));
777: return err;
778: }
779: AZ_WRITE_4(az, RIRBLBASE, (uint32_t)AZALIA_DMA_DMAADDR(&az->rirb_dma));
780: AZ_WRITE_4(az, RIRBUBASE, PTR_UPPER32(AZALIA_DMA_DMAADDR(&az->rirb_dma)));
781: AZ_WRITE_1(az, RIRBSIZE, rirbsize);
782: az->rirb_size = entries;
783:
784: DPRINTF(("%s: RIRB allocation succeeded.\n", __func__));
785:
786: /* setup the unsolicited response queue */
787: az->unsolq_rp = 0;
788: az->unsolq_wp = 0;
789: az->unsolq_kick = FALSE;
790: az->unsolq = malloc(sizeof(rirb_entry_t) * UNSOLQ_SIZE,
791: M_DEVBUF, M_NOWAIT);
792: if (az->unsolq == NULL) {
793: DPRINTF(("%s: can't allocate unsolicited response queue.\n",
794: XNAME(az)));
795: azalia_free_dmamem(az, &az->rirb_dma);
796: return ENOMEM;
797: }
798: bzero(az->unsolq, sizeof(rirb_entry_t) * UNSOLQ_SIZE);
799:
800: /* reset the write pointer */
801: rirbwp = AZ_READ_2(az, RIRBWP);
802: AZ_WRITE_2(az, RIRBWP, rirbwp | HDA_RIRBWP_RIRBWPRST);
803:
804: /* clear the read pointer */
805: az->rirb_rp = AZ_READ_2(az, RIRBWP) & HDA_RIRBWP_RIRBWP;
806: DPRINTF(("%s: RIRBRP=%d, size=%d\n", __func__, az->rirb_rp, az->rirb_size));
807:
808: AZ_WRITE_2(az, RINTCNT, 1);
809:
810: /* Run! */
811: rirbctl = AZ_READ_1(az, RIRBCTL);
812: AZ_WRITE_1(az, RIRBCTL, rirbctl |
813: HDA_RIRBCTL_RIRBDMAEN | HDA_RIRBCTL_RINTCTL);
814:
815: return (0);
816: }
817:
818: int
819: azalia_delete_rirb(azalia_t *az)
820: {
821: int i;
822: uint8_t rirbctl;
823:
824: if (az->unsolq != NULL) {
825: free(az->unsolq, M_DEVBUF);
826: az->unsolq = NULL;
827: }
828: if (az->rirb_dma.addr == NULL)
829: return 0;
830: /* stop the RIRB */
831: rirbctl = AZ_READ_1(az, RIRBCTL);
832: AZ_WRITE_1(az, RIRBCTL, rirbctl & ~HDA_RIRBCTL_RIRBDMAEN);
833: for (i = 5000; i >= 0; i--) {
834: DELAY(10);
835: rirbctl = AZ_READ_1(az, RIRBCTL);
836: if ((rirbctl & HDA_RIRBCTL_RIRBDMAEN) == 0)
837: break;
838: }
839: azalia_free_dmamem(az, &az->rirb_dma);
840: return 0;
841: }
842:
843: int
844: azalia_set_command(azalia_t *az, int caddr, nid_t nid, uint32_t control,
845: uint32_t param)
846: {
847: corb_entry_t *corb;
848: int wp;
849: uint32_t verb;
850: uint16_t corbwp;
851: uint8_t rirbctl;
852:
853: #ifdef DIAGNOSTIC
854: if ((AZ_READ_1(az, CORBCTL) & HDA_CORBCTL_CORBRUN) == 0) {
855: printf("%s: CORB is not running.\n", XNAME(az));
856: return -1;
857: }
858: #endif
859: verb = (caddr << 28) | (nid << 20) | (control << 8) | param;
860: corbwp = AZ_READ_2(az, CORBWP);
861: wp = corbwp & HDA_CORBWP_CORBWP;
862: corb = (corb_entry_t*)az->corb_dma.addr;
863: if (++wp >= az->corb_size)
864: wp = 0;
865: corb[wp] = verb;
866:
867: /* disable RIRB interrupts */
868: rirbctl = AZ_READ_1(az, RIRBCTL);
869: if (rirbctl & HDA_RIRBCTL_RINTCTL) {
870: AZ_WRITE_1(az, RIRBCTL, rirbctl & ~HDA_RIRBCTL_RINTCTL);
871: azalia_rirb_intr(az);
872: }
873:
874: AZ_WRITE_2(az, CORBWP, (corbwp & ~HDA_CORBWP_CORBWP) | wp);
875: #if 0
876: DPRINTF(("%s: caddr=%d nid=%d control=0x%x param=0x%x verb=0x%8.8x wp=%d\n",
877: __func__, caddr, nid, control, param, verb, wp));
878: #endif
879: return 0;
880: }
881:
882: int
883: azalia_get_response(azalia_t *az, uint32_t *result)
884: {
885: const rirb_entry_t *rirb;
886: int i;
887: uint16_t wp;
888: uint8_t rirbctl;
889:
890: #ifdef DIAGNOSTIC
891: if ((AZ_READ_1(az, RIRBCTL) & HDA_RIRBCTL_RIRBDMAEN) == 0) {
892: printf("%s: RIRB is not running.\n", XNAME(az));
893: return -1;
894: }
895: #endif
896: for (i = 5000; i >= 0; i--) {
897: wp = AZ_READ_2(az, RIRBWP) & HDA_RIRBWP_RIRBWP;
898: if (az->rirb_rp != wp)
899: break;
900: DELAY(10);
901: }
902: if (i <= 0) {
903: printf("%s: RIRB time out\n", XNAME(az));
904: return ETIMEDOUT;
905: }
906: rirb = (rirb_entry_t*)az->rirb_dma.addr;
907: for (;;) {
908: if (++az->rirb_rp >= az->rirb_size)
909: az->rirb_rp = 0;
910: if (rirb[az->rirb_rp].resp_ex & RIRB_RESP_UNSOL) {
911: az->unsolq[az->unsolq_wp].resp = rirb[az->rirb_rp].resp;
912: az->unsolq[az->unsolq_wp++].resp_ex = rirb[az->rirb_rp].resp_ex;
913: az->unsolq_wp %= UNSOLQ_SIZE;
914: } else
915: break;
916: }
917: if (result != NULL)
918: *result = rirb[az->rirb_rp].resp;
919:
920: azalia_rirb_kick_unsol_events(az);
921: #if 0
922: for (i = 0; i < 16 /*az->rirb_size*/; i++) {
923: DPRINTF(("rirb[%d] 0x%8.8x:0x%8.8x ", i, rirb[i].resp, rirb[i].resp_ex));
924: if ((i % 2) == 1)
925: DPRINTF(("\n"));
926: }
927: #endif
928:
929: /* re-enable RIRB interrupts */
930: rirbctl = AZ_READ_1(az, RIRBCTL);
931: AZ_WRITE_1(az, RIRBCTL, rirbctl | HDA_RIRBCTL_RINTCTL);
932:
933: return 0;
934: }
935:
936: void
937: azalia_rirb_kick_unsol_events(azalia_t *az)
938: {
939: if (az->unsolq_kick)
940: return;
941: az->unsolq_kick = TRUE;
942: while (az->unsolq_rp != az->unsolq_wp) {
943: int i;
944: int tag;
945: codec_t *codec;
946: i = RIRB_RESP_CODEC(az->unsolq[az->unsolq_rp].resp_ex);
947: tag = RIRB_UNSOL_TAG(az->unsolq[az->unsolq_rp].resp);
948: codec = &az->codecs[i];
949: DPRINTF(("%s: codec#=%d tag=%d\n", __func__, i, tag));
950: az->unsolq_rp++;
951: az->unsolq_rp %= UNSOLQ_SIZE;
952: if (codec->unsol_event != NULL)
953: codec->unsol_event(codec, tag);
954: }
955: az->unsolq_kick = FALSE;
956: }
957:
958: void
959: azalia_rirb_intr(azalia_t *az)
960: {
961: const rirb_entry_t *rirb;
962: uint16_t wp, rp;
963: uint8_t rirbsts;
964:
965: rirbsts = AZ_READ_1(az, RIRBSTS);
966:
967: wp = AZ_READ_2(az, RIRBWP) & HDA_RIRBWP_RIRBWP;
968: if (rp == wp)
969: return; /* interrupted but no data in RIRB */
970: rirb = (rirb_entry_t*)az->rirb_dma.addr;
971: while (az->rirb_rp != wp) {
972: if (++az->rirb_rp >= az->rirb_size)
973: az->rirb_rp = 0;
974: if (rirb[az->rirb_rp].resp_ex & RIRB_RESP_UNSOL) {
975: az->unsolq[az->unsolq_wp].resp = rirb[az->rirb_rp].resp;
976: az->unsolq[az->unsolq_wp++].resp_ex = rirb[az->rirb_rp].resp_ex;
977: az->unsolq_wp %= UNSOLQ_SIZE;
978: } else {
979: break;
980: }
981: }
982:
983: azalia_rirb_kick_unsol_events(az);
984:
985: AZ_WRITE_1(az, RIRBSTS,
986: rirbsts | HDA_RIRBSTS_RIRBOIS | HDA_RIRBSTS_RINTFL);
987: }
988:
989: int
990: azalia_alloc_dmamem(azalia_t *az, size_t size, size_t align, azalia_dma_t *d)
991: {
992: int err;
993: int nsegs;
994:
995: d->size = size;
996: err = bus_dmamem_alloc(az->dmat, size, align, 0, d->segments, 1,
997: &nsegs, BUS_DMA_NOWAIT);
998: if (err)
999: return err;
1000: if (nsegs != 1)
1001: goto free;
1002: err = bus_dmamem_map(az->dmat, d->segments, 1, size,
1003: &d->addr, BUS_DMA_NOWAIT | BUS_DMA_COHERENT | BUS_DMA_NOCACHE);
1004: if (err)
1005: goto free;
1006: err = bus_dmamap_create(az->dmat, size, 1, size, 0,
1007: BUS_DMA_NOWAIT, &d->map);
1008: if (err)
1009: goto unmap;
1010: err = bus_dmamap_load(az->dmat, d->map, d->addr, size,
1011: NULL, BUS_DMA_NOWAIT);
1012: if (err)
1013: goto destroy;
1014:
1015: if (!az->ok64 && PTR_UPPER32(AZALIA_DMA_DMAADDR(d)) != 0) {
1016: azalia_free_dmamem(az, d);
1017: return -1;
1018: }
1019: return 0;
1020:
1021: destroy:
1022: bus_dmamap_destroy(az->dmat, d->map);
1023: unmap:
1024: bus_dmamem_unmap(az->dmat, d->addr, size);
1025: free:
1026: bus_dmamem_free(az->dmat, d->segments, 1);
1027: d->addr = NULL;
1028: return err;
1029: }
1030:
1031: int
1032: azalia_free_dmamem(const azalia_t *az, azalia_dma_t* d)
1033: {
1034: if (d->addr == NULL)
1035: return 0;
1036: bus_dmamap_unload(az->dmat, d->map);
1037: bus_dmamap_destroy(az->dmat, d->map);
1038: bus_dmamem_unmap(az->dmat, d->addr, d->size);
1039: bus_dmamem_free(az->dmat, d->segments, 1);
1040: d->addr = NULL;
1041: return 0;
1042: }
1043:
1044: /* ================================================================
1045: * HDA codec functions
1046: * ================================================================ */
1047:
1048: int
1049: azalia_codec_init(codec_t *this)
1050: {
1051: uint32_t rev, id, result;
1052: int err, addr, n, i;
1053: const char *vendor;
1054:
1055: this->comresp = azalia_codec_comresp;
1056: addr = this->address;
1057: DPRINTF(("%s: information of codec[%d] follows:\n",
1058: XNAME(this->az), addr));
1059: /* codec vendor/device/revision */
1060: err = this->comresp(this, CORB_NID_ROOT, CORB_GET_PARAMETER,
1061: COP_REVISION_ID, &rev);
1062: if (err)
1063: return err;
1064: err = this->comresp(this, CORB_NID_ROOT, CORB_GET_PARAMETER,
1065: COP_VENDOR_ID, &id);
1066: if (err)
1067: return err;
1068: this->vid = id;
1069: this->subid = this->az->subid;
1070: azalia_codec_init_vtbl(this);
1071:
1072: printf("%s: codec:", XNAME(this->az));
1073: if (this->name == NULL) {
1074: vendor = pci_findvendor(id >> 16);
1075: if (vendor == NULL)
1076: printf(" 0x%04x/0x%04x", id >> 16, id & 0xffff);
1077: else
1078: printf(" %s/0x%04x", vendor, id & 0xffff);
1079: } else
1080: printf(" %s", this->name);
1081: printf(" (rev. %u.%u), HDA version %u.%u\n",
1082: COP_RID_REVISION(rev), COP_RID_STEPPING(rev),
1083: COP_RID_MAJ(rev), COP_RID_MIN(rev));
1084:
1085: /* identify function nodes */
1086: err = this->comresp(this, CORB_NID_ROOT, CORB_GET_PARAMETER,
1087: COP_SUBORDINATE_NODE_COUNT, &result);
1088: if (err)
1089: return err;
1090: this->nfunctions = COP_NSUBNODES(result);
1091: if (COP_NSUBNODES(result) <= 0) {
1092: printf("%s: No function groups\n", XNAME(this->az));
1093: return -1;
1094: }
1095: /* iterate function nodes and find an audio function */
1096: n = COP_START_NID(result);
1097: DPRINTF(("%s: nidstart=%d #functions=%d\n",
1098: __func__, n, this->nfunctions));
1099: this->audiofunc = -1;
1100: for (i = 0; i < this->nfunctions; i++) {
1101: err = this->comresp(this, n + i, CORB_GET_PARAMETER,
1102: COP_FUNCTION_GROUP_TYPE, &result);
1103: if (err)
1104: continue;
1105: DPRINTF(("%s: FTYPE result = 0x%8.8x\n", __func__, result));
1106: if (COP_FTYPE(result) == COP_FTYPE_AUDIO) {
1107: this->audiofunc = n + i;
1108: break; /* XXX multiple audio functions? */
1109: } else if (COP_FTYPE(result) == COP_FTYPE_MODEM) {
1110: printf("%s: codec[%d]: No support for modem function groups\n",
1111: XNAME(this->az), addr);
1112: }
1113: }
1114: if (this->audiofunc < 0) {
1115: printf("%s: codec[%d]: No audio function groups\n",
1116: XNAME(this->az), addr);
1117: return -1;
1118: }
1119:
1120: /* power the audio function */
1121: this->comresp(this, this->audiofunc, CORB_SET_POWER_STATE, CORB_PS_D0, &result);
1122: DELAY(100);
1123:
1124: /* check widgets in the audio function */
1125: err = this->comresp(this, this->audiofunc,
1126: CORB_GET_PARAMETER, COP_SUBORDINATE_NODE_COUNT, &result);
1127: if (err)
1128: return err;
1129: DPRINTF(("%s: There are %d widgets in the audio function.\n",
1130: __func__, COP_NSUBNODES(result)));
1131: this->wstart = COP_START_NID(result);
1132: if (this->wstart < 2) {
1133: printf("%s: invalid node structure\n", XNAME(this->az));
1134: return -1;
1135: }
1136: this->wend = this->wstart + COP_NSUBNODES(result);
1137: this->w = malloc(sizeof(widget_t) * this->wend, M_DEVBUF, M_NOWAIT);
1138: if (this->w == NULL) {
1139: printf("%s: out of memory\n", XNAME(this->az));
1140: return ENOMEM;
1141: }
1142: bzero(this->w, sizeof(widget_t) * this->wend);
1143:
1144: /* query the base parameters */
1145: this->comresp(this, this->audiofunc, CORB_GET_PARAMETER,
1146: COP_STREAM_FORMATS, &result);
1147: this->w[this->audiofunc].d.audio.encodings = result;
1148: this->comresp(this, this->audiofunc, CORB_GET_PARAMETER,
1149: COP_PCM, &result);
1150: this->w[this->audiofunc].d.audio.bits_rates = result;
1151: this->comresp(this, this->audiofunc, CORB_GET_PARAMETER,
1152: COP_INPUT_AMPCAP, &result);
1153: this->w[this->audiofunc].inamp_cap = result;
1154: this->comresp(this, this->audiofunc, CORB_GET_PARAMETER,
1155: COP_OUTPUT_AMPCAP, &result);
1156: this->w[this->audiofunc].outamp_cap = result;
1157: #ifdef AZALIA_DEBUG
1158: azalia_widget_print_audio(&this->w[this->audiofunc], "\t");
1159: result = this->w[this->audiofunc].inamp_cap;
1160: DPRINTF(("\tinamp: mute=%u size=%u steps=%u offset=%u\n",
1161: (result & COP_AMPCAP_MUTE) != 0, COP_AMPCAP_STEPSIZE(result),
1162: COP_AMPCAP_NUMSTEPS(result), COP_AMPCAP_OFFSET(result)));
1163: result = this->w[this->audiofunc].outamp_cap;
1164: DPRINTF(("\toutamp: mute=%u size=%u steps=%u offset=%u\n",
1165: (result & COP_AMPCAP_MUTE) != 0, COP_AMPCAP_STEPSIZE(result),
1166: COP_AMPCAP_NUMSTEPS(result), COP_AMPCAP_OFFSET(result)));
1167: #endif
1168:
1169: strlcpy(this->w[CORB_NID_ROOT].name, "root",
1170: sizeof(this->w[CORB_NID_ROOT].name));
1171: strlcpy(this->w[this->audiofunc].name, "hdaudio",
1172: sizeof(this->w[this->audiofunc].name));
1173: FOR_EACH_WIDGET(this, i) {
1174: err = azalia_widget_init(&this->w[i], this, i);
1175: if (err)
1176: return err;
1177: }
1178:
1179: err = this->init_dacgroup(this);
1180: if (err)
1181: return err;
1182: #ifdef AZALIA_DEBUG
1183: for (i = 0; i < this->dacs.ngroups; i++) {
1184: DPRINTF(("%s: dacgroup[%d]:", __func__, i));
1185: for (n = 0; n < this->dacs.groups[i].nconv; n++) {
1186: DPRINTF((" %2.2x", this->dacs.groups[i].conv[n]));
1187: }
1188: DPRINTF(("\n"));
1189: }
1190: #endif
1191:
1192: /* set invalid values for azalia_codec_construct_format() to work */
1193: this->dacs.cur = -1;
1194: this->adcs.cur = -1;
1195: err = azalia_codec_construct_format(this, 0, 0);
1196: if (err)
1197: return err;
1198:
1199: return this->mixer_init(this);
1200: }
1201:
1202: int
1203: azalia_codec_delete(codec_t *this)
1204: {
1205: if (this->mixer_delete != NULL)
1206: this->mixer_delete(this);
1207: if (this->formats != NULL) {
1208: free(this->formats, M_DEVBUF);
1209: this->formats = NULL;
1210: }
1211: printf("delete_encodings...\n");
1212: auconv_delete_encodings(this->encodings);
1213: this->encodings = NULL;
1214: return 0;
1215: }
1216:
1217: int
1218: azalia_codec_construct_format(codec_t *this, int newdac, int newadc)
1219: {
1220: const convgroup_t *group;
1221: uint32_t bits_rates;
1222: int prev_dac, prev_adc;
1223: int pvariation, rvariation;
1224: int nbits, c, chan, i, err;
1225: nid_t nid;
1226:
1227: prev_dac = this->dacs.cur;
1228: this->dacs.cur = newdac;
1229: group = &this->dacs.groups[this->dacs.cur];
1230: bits_rates = this->w[group->conv[0]].d.audio.bits_rates;
1231: nbits = 0;
1232: if (bits_rates & COP_PCM_B8)
1233: nbits++;
1234: if (bits_rates & COP_PCM_B16)
1235: nbits++;
1236: if (bits_rates & COP_PCM_B20)
1237: nbits++;
1238: if (bits_rates & COP_PCM_B24)
1239: nbits++;
1240: if (bits_rates & COP_PCM_B32)
1241: nbits++;
1242: if (nbits == 0) {
1243: printf("%s: %s/%d invalid PCM format: 0x%8.8x\n",
1244: XNAME(this->az), __FILE__, __LINE__, bits_rates);
1245: return -1;
1246: }
1247: pvariation = group->nconv * nbits;
1248:
1249: prev_adc = this->adcs.cur;
1250: this->adcs.cur = newadc;
1251: group = &this->adcs.groups[this->adcs.cur];
1252: bits_rates = this->w[group->conv[0]].d.audio.bits_rates;
1253: nbits = 0;
1254: if (bits_rates & COP_PCM_B8)
1255: nbits++;
1256: if (bits_rates & COP_PCM_B16)
1257: nbits++;
1258: if (bits_rates & COP_PCM_B20)
1259: nbits++;
1260: if (bits_rates & COP_PCM_B24)
1261: nbits++;
1262: if (bits_rates & COP_PCM_B32)
1263: nbits++;
1264: if (nbits == 0) {
1265: printf("%s: %s/%d invalid PCM format: 0x%8.8x\n",
1266: XNAME(this->az), __FILE__, __LINE__, bits_rates);
1267: return -1;
1268: }
1269: rvariation = group->nconv * nbits;
1270:
1271: if (this->formats != NULL)
1272: free(this->formats, M_DEVBUF);
1273: this->nformats = 0;
1274: this->formats = malloc(sizeof(struct audio_format) *
1275: (pvariation + rvariation), M_DEVBUF, M_NOWAIT);
1276: if (this->formats == NULL) {
1277: printf("%s: out of memory in %s\n",
1278: XNAME(this->az), __func__);
1279: return ENOMEM;
1280: }
1281: bzero(this->formats, sizeof(struct audio_format) *
1282: (pvariation + rvariation));
1283:
1284: /* register formats for playback */
1285: group = &this->dacs.groups[this->dacs.cur];
1286: nid = group->conv[0];
1287: chan = 0;
1288: bits_rates = this->w[nid].d.audio.bits_rates;
1289: for (c = 0; c < group->nconv; c++) {
1290: for (chan = 0, i = 0; i <= c; i++)
1291: chan += WIDGET_CHANNELS(&this->w[group->conv[c]]);
1292: azalia_codec_add_bits(this, chan, bits_rates, AUMODE_PLAY);
1293: }
1294:
1295: /* register formats for recording */
1296: group = &this->adcs.groups[this->adcs.cur];
1297: nid = group->conv[0];
1298: chan = 0;
1299: bits_rates = this->w[nid].d.audio.bits_rates;
1300: for (c = 0; c < group->nconv; c++) {
1301: for (chan = 0, i = 0; i <= c; i++)
1302: chan += WIDGET_CHANNELS(&this->w[group->conv[c]]);
1303: azalia_codec_add_bits(this, chan, bits_rates, AUMODE_RECORD);
1304: }
1305:
1306: err = azalia_create_encodings(this->formats, this->nformats,
1307: &this->encodings);
1308: if (err)
1309: return err;
1310: return 0;
1311: }
1312:
1313: void
1314: azalia_codec_add_bits(codec_t *this, int chan, uint32_t bits_rates, int mode)
1315: {
1316: if (bits_rates & COP_PCM_B8)
1317: azalia_codec_add_format(this, chan, 8, 16, bits_rates, mode);
1318: if (bits_rates & COP_PCM_B16)
1319: azalia_codec_add_format(this, chan, 16, 16, bits_rates, mode);
1320: if (bits_rates & COP_PCM_B20)
1321: azalia_codec_add_format(this, chan, 20, 32, bits_rates, mode);
1322: if (bits_rates & COP_PCM_B24)
1323: azalia_codec_add_format(this, chan, 24, 32, bits_rates, mode);
1324: if (bits_rates & COP_PCM_B32)
1325: azalia_codec_add_format(this, chan, 32, 32, bits_rates, mode);
1326: }
1327:
1328: void
1329: azalia_codec_add_format(codec_t *this, int chan, int valid, int prec,
1330: uint32_t rates, int32_t mode)
1331: {
1332: struct audio_format *f;
1333:
1334: f = &this->formats[this->nformats++];
1335: f->mode = mode;
1336: f->encoding = AUDIO_ENCODING_SLINEAR_LE;
1337: if (valid == 8 && prec == 8)
1338: f->encoding = AUDIO_ENCODING_ULINEAR_LE;
1339: f->validbits = valid;
1340: f->precision = prec;
1341: f->channels = chan;
1342: switch (chan) {
1343: case 1:
1344: f->channel_mask = AUFMT_MONAURAL;
1345: break;
1346: case 2:
1347: f->channel_mask = AUFMT_STEREO;
1348: break;
1349: case 4:
1350: f->channel_mask = AUFMT_SURROUND4;
1351: break;
1352: case 6:
1353: f->channel_mask = AUFMT_DOLBY_5_1;
1354: break;
1355: case 8:
1356: f->channel_mask = AUFMT_DOLBY_5_1
1357: | AUFMT_SIDE_LEFT | AUFMT_SIDE_RIGHT;
1358: break;
1359: default:
1360: f->channel_mask = 0;
1361: }
1362: if (rates & COP_PCM_R80)
1363: f->frequency[f->frequency_type++] = 8000;
1364: if (rates & COP_PCM_R110)
1365: f->frequency[f->frequency_type++] = 11025;
1366: if (rates & COP_PCM_R160)
1367: f->frequency[f->frequency_type++] = 16000;
1368: if (rates & COP_PCM_R220)
1369: f->frequency[f->frequency_type++] = 22050;
1370: if (rates & COP_PCM_R320)
1371: f->frequency[f->frequency_type++] = 32000;
1372: if (rates & COP_PCM_R441)
1373: f->frequency[f->frequency_type++] = 44100;
1374: if (rates & COP_PCM_R480)
1375: f->frequency[f->frequency_type++] = 48000;
1376: if (rates & COP_PCM_R882)
1377: f->frequency[f->frequency_type++] = 88200;
1378: if (rates & COP_PCM_R960)
1379: f->frequency[f->frequency_type++] = 96000;
1380: if (rates & COP_PCM_R1764)
1381: f->frequency[f->frequency_type++] = 176400;
1382: if (rates & COP_PCM_R1920)
1383: f->frequency[f->frequency_type++] = 192000;
1384: if (rates & COP_PCM_R3840)
1385: f->frequency[f->frequency_type++] = 384000;
1386: }
1387:
1388: int
1389: azalia_codec_comresp(const codec_t *codec, nid_t nid, uint32_t control,
1390: uint32_t param, uint32_t* result)
1391: {
1392: int err;
1393:
1394: err = azalia_set_command(codec->az, codec->address, nid, control, param);
1395: if (err)
1396: return err;
1397: return azalia_get_response(codec->az, result);
1398: }
1399:
1400: int
1401: azalia_codec_connect_stream(codec_t *this, int dir, uint16_t fmt, int number)
1402: {
1403: const convgroup_t *group;
1404: int i, err, startchan, nchan;
1405: nid_t nid;
1406: boolean_t flag222;
1407:
1408: DPRINTF(("%s: fmt=0x%4.4x number=%d\n", __func__, fmt, number));
1409: err = 0;
1410: if (dir == AUMODE_RECORD)
1411: group = &this->adcs.groups[this->adcs.cur];
1412: else
1413: group = &this->dacs.groups[this->dacs.cur];
1414: flag222 = group->nconv >= 3 &&
1415: (WIDGET_CHANNELS(&this->w[group->conv[0]]) == 2) &&
1416: (WIDGET_CHANNELS(&this->w[group->conv[1]]) == 2) &&
1417: (WIDGET_CHANNELS(&this->w[group->conv[2]]) == 2);
1418: nchan = (fmt & HDA_SD_FMT_CHAN) + 1;
1419: startchan = 0;
1420: for (i = 0; i < group->nconv; i++) {
1421: nid = group->conv[i];
1422:
1423: /* surround and c/lfe handling */
1424: if (nchan >= 6 && flag222 && i == 1) {
1425: nid = group->conv[2];
1426: } else if (nchan >= 6 && flag222 && i == 2) {
1427: nid = group->conv[1];
1428: }
1429:
1430: err = this->comresp(this, nid, CORB_SET_CONVERTER_FORMAT, fmt, NULL);
1431: if (err)
1432: goto exit;
1433: err = this->comresp(this, nid, CORB_SET_CONVERTER_STREAM_CHANNEL,
1434: (number << 4) | startchan, NULL);
1435: if (err)
1436: goto exit;
1437: if (nchan > 2)
1438: startchan += WIDGET_CHANNELS(&this->w[nid]);
1439: }
1440:
1441: exit:
1442: DPRINTF(("%s: leave with %d\n", __func__, err));
1443: return err;
1444: }
1445:
1446: /* ================================================================
1447: * HDA widget functions
1448: * ================================================================ */
1449:
1450: #define WIDGETCAP_BITS \
1451: "\20\014LRSWAP\013POWER\012DIGITAL" \
1452: "\011CONNLIST\010UNSOL\07PROC\06STRIPE\05FORMATOV\04AMPOV\03OUTAMP" \
1453: "\02INAMP\01STEREO"
1454:
1455: int
1456: azalia_widget_init(widget_t *this, const codec_t *codec, nid_t nid)
1457: {
1458: uint32_t result;
1459: int err;
1460:
1461: err = codec->comresp(codec, nid, CORB_GET_PARAMETER,
1462: COP_AUDIO_WIDGET_CAP, &result);
1463: if (err)
1464: return err;
1465: this->nid = nid;
1466: this->widgetcap = result;
1467: this->type = COP_AWCAP_TYPE(result);
1468: DPRINTF(("%s: ", XNAME(codec->az)));
1469: if (this->widgetcap & COP_AWCAP_POWER) {
1470: codec->comresp(codec, nid, CORB_SET_POWER_STATE, CORB_PS_D0, &result);
1471: DELAY(100);
1472: }
1473: switch (this->type) {
1474: case COP_AWTYPE_AUDIO_OUTPUT:
1475: snprintf(this->name, sizeof(this->name), "dac%2.2x", nid);
1476: DPRINTF(("%s wcap=%b\n", this->name,
1477: this->widgetcap, WIDGETCAP_BITS));
1478: azalia_widget_init_audio(this, codec);
1479: break;
1480: case COP_AWTYPE_AUDIO_INPUT:
1481: snprintf(this->name, sizeof(this->name), "adc%2.2x", nid);
1482: DPRINTF(("%s wcap=%b\n", this->name,
1483: this->widgetcap, WIDGETCAP_BITS));
1484: azalia_widget_init_audio(this, codec);
1485: break;
1486: case COP_AWTYPE_AUDIO_MIXER:
1487: snprintf(this->name, sizeof(this->name), "mix%2.2x", nid);
1488: DPRINTF(("%s wcap=%b\n", this->name,
1489: this->widgetcap, WIDGETCAP_BITS));
1490: break;
1491: case COP_AWTYPE_AUDIO_SELECTOR:
1492: snprintf(this->name, sizeof(this->name), "sel%2.2x", nid);
1493: DPRINTF(("%s wcap=%b\n", this->name,
1494: this->widgetcap, WIDGETCAP_BITS));
1495: break;
1496: case COP_AWTYPE_PIN_COMPLEX:
1497: azalia_widget_init_pin(this, codec);
1498: snprintf(this->name, sizeof(this->name), "%s%2.2x",
1499: pin_colors[this->d.pin.color], nid);
1500: DPRINTF(("%s wcap=%b\n", this->name,
1501: this->widgetcap, WIDGETCAP_BITS));
1502: azalia_widget_print_pin(this);
1503: break;
1504: case COP_AWTYPE_POWER:
1505: snprintf(this->name, sizeof(this->name), "pow%2.2x", nid);
1506: DPRINTF(("%s wcap=%b\n", this->name,
1507: this->widgetcap, WIDGETCAP_BITS));
1508: break;
1509: case COP_AWTYPE_VOLUME_KNOB:
1510: snprintf(this->name, sizeof(this->name), "volume%2.2x", nid);
1511: DPRINTF(("%s wcap=%b\n", this->name,
1512: this->widgetcap, WIDGETCAP_BITS));
1513: err = codec->comresp(codec, nid, CORB_GET_PARAMETER,
1514: COP_VOLUME_KNOB_CAPABILITIES, &result);
1515: if (!err) {
1516: this->d.volume.cap = result;
1517: DPRINTF(("\tdelta=%d steps=%d\n",
1518: !!(result & COP_VKCAP_DELTA),
1519: COP_VKCAP_NUMSTEPS(result)));
1520: }
1521: break;
1522: case COP_AWTYPE_BEEP_GENERATOR:
1523: snprintf(this->name, sizeof(this->name), "beep%2.2x", nid);
1524: DPRINTF(("%s wcap=%b\n", this->name,
1525: this->widgetcap, WIDGETCAP_BITS));
1526: break;
1527: default:
1528: snprintf(this->name, sizeof(this->name), "widget%2.2x", nid);
1529: DPRINTF(("%s wcap=%b\n", this->name,
1530: this->widgetcap, WIDGETCAP_BITS));
1531: break;
1532: }
1533: azalia_widget_init_connection(this, codec);
1534:
1535: /* amplifier information */
1536: if (this->widgetcap & COP_AWCAP_INAMP) {
1537: if (this->widgetcap & COP_AWCAP_AMPOV)
1538: codec->comresp(codec, nid, CORB_GET_PARAMETER,
1539: COP_INPUT_AMPCAP, &this->inamp_cap);
1540: else
1541: this->inamp_cap = codec->w[codec->audiofunc].inamp_cap;
1542: DPRINTF(("\tinamp: mute=%u size=%u steps=%u offset=%u\n",
1543: (this->inamp_cap & COP_AMPCAP_MUTE) != 0,
1544: COP_AMPCAP_STEPSIZE(this->inamp_cap),
1545: COP_AMPCAP_NUMSTEPS(this->inamp_cap),
1546: COP_AMPCAP_OFFSET(this->inamp_cap)));
1547: }
1548: if (this->widgetcap & COP_AWCAP_OUTAMP) {
1549: if (this->widgetcap & COP_AWCAP_AMPOV)
1550: codec->comresp(codec, nid, CORB_GET_PARAMETER,
1551: COP_OUTPUT_AMPCAP, &this->outamp_cap);
1552: else
1553: this->outamp_cap = codec->w[codec->audiofunc].outamp_cap;
1554: DPRINTF(("\toutamp: mute=%u size=%u steps=%u offset=%u\n",
1555: (this->outamp_cap & COP_AMPCAP_MUTE) != 0,
1556: COP_AMPCAP_STEPSIZE(this->outamp_cap),
1557: COP_AMPCAP_NUMSTEPS(this->outamp_cap),
1558: COP_AMPCAP_OFFSET(this->outamp_cap)));
1559: }
1560: if (codec->init_widget != NULL)
1561: codec->init_widget(codec, this, nid);
1562: return 0;
1563: }
1564:
1565: int
1566: azalia_widget_init_audio(widget_t *this, const codec_t *codec)
1567: {
1568: uint32_t result;
1569: int err;
1570:
1571: /* check audio format */
1572: if (this->widgetcap & COP_AWCAP_FORMATOV) {
1573: err = codec->comresp(codec, this->nid,
1574: CORB_GET_PARAMETER, COP_STREAM_FORMATS, &result);
1575: if (err)
1576: return err;
1577: this->d.audio.encodings = result;
1578: if (result == 0) { /* quirk for CMI9880.
1579: * This must not occuur usually... */
1580: this->d.audio.encodings =
1581: codec->w[codec->audiofunc].d.audio.encodings;
1582: this->d.audio.bits_rates =
1583: codec->w[codec->audiofunc].d.audio.bits_rates;
1584: } else {
1585: if ((result & COP_STREAM_FORMAT_PCM) == 0) {
1586: printf("%s: %s: No PCM support: %x\n",
1587: XNAME(codec->az), this->name, result);
1588: return -1;
1589: }
1590: err = codec->comresp(codec, this->nid, CORB_GET_PARAMETER,
1591: COP_PCM, &result);
1592: if (err)
1593: return err;
1594: this->d.audio.bits_rates = result;
1595: }
1596: this->d.audio.bits_rates = result;
1597: } else {
1598: this->d.audio.encodings =
1599: codec->w[codec->audiofunc].d.audio.encodings;
1600: this->d.audio.bits_rates =
1601: codec->w[codec->audiofunc].d.audio.bits_rates;
1602: }
1603: #ifdef AZALIA_DEBUG
1604: azalia_widget_print_audio(this, "\t");
1605: #endif
1606: return 0;
1607: }
1608:
1609: #define ENCODING_BITS "\20\3AC3\2FLOAT32\1PCM"
1610: #define BITSRATES_BITS "\20\x15""32bit\x14""24bit\x13""20bit" \
1611: "\x12""16bit\x11""8bit""\x0c""384kHz\x0b""192kHz\x0a""176.4kHz" \
1612: "\x09""96kHz\x08""88.2kHz\x07""48kHz\x06""44.1kHz\x05""32kHz\x04" \
1613: "22.05kHz\x03""16kHz\x02""11.025kHz\x01""8kHz"
1614:
1615: int
1616: azalia_widget_print_audio(const widget_t *this, const char *lead)
1617: {
1618: printf("%sencodings=%b\n", lead, this->d.audio.encodings,
1619: ENCODING_BITS);
1620: printf("%sPCM formats=%b\n", lead, this->d.audio.bits_rates,
1621: BITSRATES_BITS);
1622: return 0;
1623: }
1624:
1625: int
1626: azalia_widget_init_pin(widget_t *this, const codec_t *codec)
1627: {
1628: uint32_t result;
1629: int err;
1630:
1631: err = codec->comresp(codec, this->nid, CORB_GET_CONFIGURATION_DEFAULT,
1632: 0, &result);
1633: if (err)
1634: return err;
1635: this->d.pin.config = result;
1636: this->d.pin.sequence = CORB_CD_SEQUENCE(result);
1637: this->d.pin.association = CORB_CD_ASSOCIATION(result);
1638: this->d.pin.color = CORB_CD_COLOR(result);
1639: this->d.pin.device = CORB_CD_DEVICE(result);
1640:
1641: err = codec->comresp(codec, this->nid, CORB_GET_PARAMETER,
1642: COP_PINCAP, &result);
1643: if (err)
1644: return err;
1645: this->d.pin.cap = result;
1646: return 0;
1647: }
1648:
1649: #define PINCAP_BITS "\20\021EAPD\07BALANCE\06INPUT" \
1650: "\05OUTPUT\04HEADPHONE\03PRESENCE\02TRIGGER\01IMPEDANCE"
1651:
1652: int
1653: azalia_widget_print_pin(const widget_t *this)
1654: {
1655: DPRINTF(("\tpin config; device=%s color=%s assoc=%d seq=%d",
1656: pin_devices[this->d.pin.device], pin_colors[this->d.pin.color],
1657: this->d.pin.association, this->d.pin.sequence));
1658: DPRINTF((" cap=%b\n", this->d.pin.cap, PINCAP_BITS));
1659: return 0;
1660: }
1661:
1662: int
1663: azalia_widget_init_connection(widget_t *this, const codec_t *codec)
1664: {
1665: uint32_t result;
1666: int err;
1667: boolean_t longform;
1668: int length, i;
1669:
1670: this->selected = -1;
1671: if ((this->widgetcap & COP_AWCAP_CONNLIST) == 0)
1672: return 0;
1673:
1674: err = codec->comresp(codec, this->nid, CORB_GET_PARAMETER,
1675: COP_CONNECTION_LIST_LENGTH, &result);
1676: if (err)
1677: return err;
1678: longform = (result & COP_CLL_LONG) != 0;
1679: length = COP_CLL_LENGTH(result);
1680: if (length == 0)
1681: return 0;
1682: this->nconnections = length;
1683: this->connections = malloc(sizeof(nid_t) * (length + 3),
1684: M_DEVBUF, M_NOWAIT);
1685: if (this->connections == NULL) {
1686: printf("%s: out of memory\n", XNAME(codec->az));
1687: return ENOMEM;
1688: }
1689: if (longform) {
1690: for (i = 0; i < length;) {
1691: err = codec->comresp(codec, this->nid,
1692: CORB_GET_CONNECTION_LIST_ENTRY, i, &result);
1693: if (err)
1694: return err;
1695: this->connections[i++] = CORB_CLE_LONG_0(result);
1696: this->connections[i++] = CORB_CLE_LONG_1(result);
1697: }
1698: } else {
1699: for (i = 0; i < length;) {
1700: err = codec->comresp(codec, this->nid,
1701: CORB_GET_CONNECTION_LIST_ENTRY, i, &result);
1702: if (err)
1703: return err;
1704: this->connections[i++] = CORB_CLE_SHORT_0(result);
1705: this->connections[i++] = CORB_CLE_SHORT_1(result);
1706: this->connections[i++] = CORB_CLE_SHORT_2(result);
1707: this->connections[i++] = CORB_CLE_SHORT_3(result);
1708: }
1709: }
1710: if (length > 0) {
1711: DPRINTF(("\tconnections=0x%x", this->connections[0]));
1712: for (i = 1; i < length; i++) {
1713: DPRINTF((",0x%x", this->connections[i]));
1714: }
1715:
1716: err = codec->comresp(codec, this->nid,
1717: CORB_GET_CONNECTION_SELECT_CONTROL, 0, &result);
1718: if (err)
1719: return err;
1720: this->selected = CORB_CSC_INDEX(result);
1721: DPRINTF(("; selected=0x%x\n", this->connections[result]));
1722: }
1723: return 0;
1724: }
1725:
1726: /* ================================================================
1727: * Stream functions
1728: * ================================================================ */
1729:
1730: int
1731: azalia_stream_init(stream_t *this, azalia_t *az, int regindex, int strnum, int dir)
1732: {
1733: int err;
1734:
1735: this->az = az;
1736: this->regbase = HDA_SD_BASE + regindex * HDA_SD_SIZE;
1737: this->intr_bit = 1 << regindex;
1738: this->number = strnum;
1739: this->dir = dir;
1740:
1741: /* setup BDL buffers */
1742: err = azalia_alloc_dmamem(az, sizeof(bdlist_entry_t) * HDA_BDL_MAX,
1743: 128, &this->bdlist);
1744: if (err) {
1745: printf("%s: can't allocate a BDL buffer\n", XNAME(az));
1746: return err;
1747: }
1748: return 0;
1749: }
1750:
1751: int
1752: azalia_stream_delete(stream_t *this, azalia_t *az)
1753: {
1754: if (this->bdlist.addr == NULL)
1755: return 0;
1756: azalia_free_dmamem(az, &this->bdlist);
1757: return 0;
1758: }
1759:
1760: int
1761: azalia_stream_reset(stream_t *this)
1762: {
1763: int i;
1764: uint16_t ctl;
1765: uint8_t sts;
1766:
1767: /* Make sure RUN bit is zero before resetting */
1768: ctl = STR_READ_2(this, CTL);
1769: ctl &= ~HDA_SD_CTL_RUN;
1770: STR_WRITE_2(this, CTL, ctl);
1771:
1772: /* Start reset and wait for chip to enter. */
1773: ctl = STR_READ_2(this, CTL);
1774: STR_WRITE_2(this, CTL, ctl | HDA_SD_CTL_SRST);
1775: for (i = 5000; i >= 0; i--) {
1776: DELAY(10);
1777: ctl = STR_READ_2(this, CTL);
1778: if (ctl & HDA_SD_CTL_SRST)
1779: break;
1780: }
1781: if (i <= 0) {
1782: printf("%s: stream reset failure 1\n", XNAME(this->az));
1783: return -1;
1784: }
1785:
1786: /* Clear reset and wait for chip to finish */
1787: STR_WRITE_2(this, CTL, ctl & ~HDA_SD_CTL_SRST);
1788: for (i = 5000; i >= 0; i--) {
1789: DELAY(10);
1790: ctl = STR_READ_2(this, CTL);
1791: if ((ctl & HDA_SD_CTL_SRST) == 0)
1792: break;
1793: }
1794: if (i <= 0) {
1795: printf("%s: stream reset failure 2\n", XNAME(this->az));
1796: return -1;
1797: }
1798:
1799: sts = STR_READ_1(this, STS);
1800: sts |= HDA_SD_STS_DESE | HDA_SD_STS_FIFOE | HDA_SD_STS_BCIS;
1801: STR_WRITE_1(this, STS, sts);
1802:
1803: return (0);
1804: }
1805:
1806: int
1807: azalia_stream_start(stream_t *this, void *start, void *end, int blk,
1808: void (*intr)(void *), void *arg, uint16_t fmt)
1809: {
1810: bdlist_entry_t *bdlist;
1811: bus_addr_t dmaaddr, dmaend;
1812: int err, index;
1813: uint32_t intctl;
1814: uint8_t ctl2;
1815:
1816: this->intr = intr;
1817: this->intr_arg = arg;
1818:
1819: err = azalia_stream_reset(this);
1820: if (err) {
1821: printf("%s: stream reset failed\n", "azalia");
1822: return err;
1823: }
1824:
1825: STR_WRITE_4(this, BDPL, 0);
1826: STR_WRITE_4(this, BDPU, 0);
1827:
1828: /* setup BDL */
1829: dmaaddr = AZALIA_DMA_DMAADDR(&this->buffer);
1830: dmaend = dmaaddr + ((caddr_t)end - (caddr_t)start);
1831: bdlist = (bdlist_entry_t*)this->bdlist.addr;
1832: for (index = 0; index < HDA_BDL_MAX; index++) {
1833: bdlist[index].low = htole32(dmaaddr);
1834: bdlist[index].high = htole32(PTR_UPPER32(dmaaddr));
1835: bdlist[index].length = htole32(blk);
1836: bdlist[index].flags = htole32(BDLIST_ENTRY_IOC);
1837: dmaaddr += blk;
1838: if (dmaaddr >= dmaend) {
1839: index++;
1840: break;
1841: }
1842: }
1843:
1844: dmaaddr = AZALIA_DMA_DMAADDR(&this->bdlist);
1845: STR_WRITE_4(this, BDPL, dmaaddr);
1846: STR_WRITE_4(this, BDPU, PTR_UPPER32(dmaaddr));
1847: STR_WRITE_2(this, LVI, (index - 1) & HDA_SD_LVI_LVI);
1848: ctl2 = STR_READ_1(this, CTL2);
1849: STR_WRITE_1(this, CTL2,
1850: (ctl2 & ~HDA_SD_CTL2_STRM) | (this->number << HDA_SD_CTL2_STRM_SHIFT));
1851: STR_WRITE_4(this, CBL, ((caddr_t)end - (caddr_t)start));
1852: STR_WRITE_2(this, FMT, fmt);
1853:
1854: err = azalia_codec_connect_stream(&this->az->codecs[this->az->codecno],
1855: this->dir, fmt, this->number);
1856: if (err)
1857: return EINVAL;
1858:
1859: intctl = AZ_READ_4(this->az, INTCTL);
1860: intctl |= this->intr_bit;
1861: AZ_WRITE_4(this->az, INTCTL, intctl);
1862:
1863: STR_WRITE_1(this, CTL, STR_READ_1(this, CTL) |
1864: HDA_SD_CTL_DEIE | HDA_SD_CTL_FEIE | HDA_SD_CTL_IOCE |
1865: HDA_SD_CTL_RUN);
1866:
1867: return (0);
1868: }
1869:
1870: int
1871: azalia_stream_halt(stream_t *this)
1872: {
1873: uint16_t ctl;
1874:
1875: ctl = STR_READ_2(this, CTL);
1876: ctl &= ~(HDA_SD_CTL_DEIE | HDA_SD_CTL_FEIE | HDA_SD_CTL_IOCE | HDA_SD_CTL_RUN);
1877: STR_WRITE_2(this, CTL, ctl);
1878: AZ_WRITE_4(this->az, INTCTL,
1879: AZ_READ_4(this->az, INTCTL) & ~this->intr_bit);
1880: return (0);
1881: }
1882:
1883: #define HDA_SD_STS_BITS "\20\3BCIS\4FIFOE\5DESE\6FIFORDY"
1884:
1885: int
1886: azalia_stream_intr(stream_t *this, uint32_t intsts)
1887: {
1888: u_int8_t sts;
1889:
1890: if ((intsts & this->intr_bit) == 0)
1891: return (0);
1892:
1893: sts = STR_READ_1(this, STS);
1894: STR_WRITE_1(this, STS, sts |
1895: HDA_SD_STS_DESE | HDA_SD_STS_FIFOE | HDA_SD_STS_BCIS);
1896:
1897: if (sts & (HDA_SD_STS_DESE | HDA_SD_STS_FIFOE))
1898: printf("%s: stream %d: sts=%b\n", XNAME(this->az),
1899: this->number, sts, HDA_SD_STS_BITS);
1900: if (sts & HDA_SD_STS_BCIS)
1901: this->intr(this->intr_arg);
1902: return (1);
1903: }
1904:
1905: /* ================================================================
1906: * MI audio entries
1907: * ================================================================ */
1908:
1909: int
1910: azalia_open(void *v, int flags)
1911: {
1912: azalia_t *az;
1913: codec_t *codec;
1914:
1915: DPRINTF(("%s: flags=0x%x\n", __func__, flags));
1916: az = v;
1917: codec = &az->codecs[az->codecno];
1918: codec->running++;
1919: return 0;
1920: }
1921:
1922: void
1923: azalia_close(void *v)
1924: {
1925: azalia_t *az;
1926: codec_t *codec;
1927:
1928: DPRINTF(("%s\n", __func__));
1929: az = v;
1930: codec = &az->codecs[az->codecno];
1931: codec->running--;
1932: }
1933:
1934: int
1935: azalia_query_encoding(void *v, audio_encoding_t *enc)
1936: {
1937: azalia_t *az;
1938: codec_t *codec;
1939: int i, j;
1940:
1941: az = v;
1942: codec = &az->codecs[az->codecno];
1943: for (j = 0, i = 0; j < codec->nformats; j++) {
1944: if (codec->formats[j].validbits !=
1945: codec->formats[j].precision)
1946: continue;
1947: if (i == enc->index) {
1948: enc->encoding = codec->formats[j].encoding;
1949: enc->precision = codec->formats[j].precision;
1950: switch (enc->encoding) {
1951: case AUDIO_ENCODING_SLINEAR_LE:
1952: strlcpy(enc->name, enc->precision == 8 ?
1953: AudioEslinear : AudioEslinear_le,
1954: sizeof enc->name);
1955: break;
1956: case AUDIO_ENCODING_ULINEAR_LE:
1957: strlcpy(enc->name, enc->precision == 8 ?
1958: AudioEulinear : AudioEulinear_le,
1959: sizeof enc->name);
1960: break;
1961: default:
1962: strlcpy(enc->name, "unknown", sizeof enc->name);
1963: break;
1964: }
1965: return (0);
1966: }
1967: i++;
1968: }
1969: return (EINVAL);
1970: }
1971:
1972: int
1973: azalia_set_params(void *v, int smode, int umode, audio_params_t *p,
1974: audio_params_t *r)
1975: {
1976: azalia_t *az;
1977: codec_t *codec;
1978: void (*pswcode)(void *, u_char *, int) = NULL;
1979: void (*rswcode)(void *, u_char *, int) = NULL;
1980: int i, j;
1981:
1982: az = v;
1983: codec = &az->codecs[az->codecno];
1984: if (smode & AUMODE_RECORD && r != NULL) {
1985: if (r->encoding == AUDIO_ENCODING_ULAW) { /*XXX*/
1986: r->encoding = AUDIO_ENCODING_SLINEAR_LE;
1987: r->precision = 16;
1988: r->channels = 2;
1989: r->sample_rate = 44100;
1990: }
1991: for (i = 0; i < codec->nformats; i++) {
1992: if (r->encoding != codec->formats[i].encoding)
1993: continue;
1994: if (r->precision != codec->formats[i].precision)
1995: continue;
1996: if (r->channels != codec->formats[i].channels)
1997: continue;
1998: break;
1999: }
2000: if (i == codec->nformats) {
2001: printf("didn't find Record format %u/%u/%u\n",
2002: r->encoding, r->precision, r->channels);
2003: return (EINVAL);
2004: }
2005: for (j = 0; j < codec->formats[i].frequency_type; j++) {
2006: if (r->sample_rate != codec->formats[i].frequency[j])
2007: continue;
2008: break;
2009: }
2010: if (j == codec->formats[i].frequency_type) {
2011: printf("didn't find Record rate %u\n",
2012: r->sample_rate);
2013: return (EINVAL);
2014: }
2015: r->sw_code = rswcode;
2016: }
2017: if (smode & AUMODE_PLAY && p != NULL) {
2018: if (p->encoding == AUDIO_ENCODING_ULAW) { /*XXX*/
2019: p->encoding = AUDIO_ENCODING_SLINEAR_LE;
2020: p->precision = 16;
2021: p->channels = 2;
2022: p->sample_rate = 44100;
2023: }
2024: for (i = 0; i < codec->nformats; i++) {
2025: if (p->encoding != codec->formats[i].encoding)
2026: continue;
2027: if (p->precision != codec->formats[i].precision)
2028: continue;
2029: if (p->channels != codec->formats[i].channels)
2030: continue;
2031: break;
2032: }
2033: if (i == codec->nformats) {
2034: printf("can't find playback format %u/%u/%u\n",
2035: r->encoding, r->precision, r->channels);
2036: return (EINVAL);
2037: }
2038: for (j = 0; j < codec->formats[i].frequency_type; j++) {
2039: if (p->sample_rate != codec->formats[i].frequency[j])
2040: continue;
2041: break;
2042: }
2043: if (j == codec->formats[i].frequency_type) {
2044: printf("can't find playback rate %u\n",
2045: p->sample_rate);
2046: return (EINVAL);
2047: }
2048: p->sw_code = pswcode;
2049: }
2050:
2051: return (0);
2052: }
2053:
2054: int
2055: azalia_round_blocksize(void *v, int blk)
2056: {
2057: azalia_t *az;
2058: size_t size;
2059:
2060: blk &= ~0x7f; /* must be multiple of 128 */
2061: if (blk <= 0)
2062: blk = 128;
2063: /* number of blocks must be <= HDA_BDL_MAX */
2064: az = v;
2065: size = az->pstream.buffer.size;
2066: #ifdef DIAGNOSTIC
2067: if (size <= 0) {
2068: printf("%s: size is 0", __func__);
2069: return 256;
2070: }
2071: #endif
2072: if (size > HDA_BDL_MAX * blk) {
2073: blk = size / HDA_BDL_MAX;
2074: if (blk & 0x7f)
2075: blk = (blk + 0x7f) & ~0x7f;
2076: }
2077: DPRINTF(("%s: resultant block size = %d\n", __func__, blk));
2078: return blk;
2079: }
2080:
2081: int
2082: azalia_halt_output(void *v)
2083: {
2084: azalia_t *az;
2085:
2086: DPRINTF(("%s\n", __func__));
2087: az = v;
2088: return azalia_stream_halt(&az->pstream);
2089: }
2090:
2091: int
2092: azalia_halt_input(void *v)
2093: {
2094: azalia_t *az;
2095:
2096: DPRINTF(("%s\n", __func__));
2097: az = v;
2098: return azalia_stream_halt(&az->rstream);
2099: }
2100:
2101: int
2102: azalia_getdev(void *v, struct audio_device *dev)
2103: {
2104: azalia_t *az;
2105:
2106: az = v;
2107: strlcpy(dev->name, "HD-Audio", MAX_AUDIO_DEV_LEN);
2108: snprintf(dev->version, MAX_AUDIO_DEV_LEN,
2109: "%d.%d", AZ_READ_1(az, VMAJ), AZ_READ_1(az, VMIN));
2110: strlcpy(dev->config, XNAME(az), MAX_AUDIO_DEV_LEN);
2111: return 0;
2112: }
2113:
2114: int
2115: azalia_set_port(void *v, mixer_ctrl_t *mc)
2116: {
2117: azalia_t *az;
2118: codec_t *co;
2119:
2120: az = v;
2121: co = &az->codecs[az->codecno];
2122: return co->set_port(co, mc);
2123: }
2124:
2125: int
2126: azalia_get_port(void *v, mixer_ctrl_t *mc)
2127: {
2128: azalia_t *az;
2129: codec_t *co;
2130:
2131: az = v;
2132: co = &az->codecs[az->codecno];
2133: return co->get_port(co, mc);
2134: }
2135:
2136: int
2137: azalia_query_devinfo(void *v, mixer_devinfo_t *mdev)
2138: {
2139: azalia_t *az;
2140: const codec_t *co;
2141:
2142: az = v;
2143: co = &az->codecs[az->codecno];
2144: if (mdev->index >= co->nmixers)
2145: return ENXIO;
2146: *mdev = co->mixers[mdev->index].devinfo;
2147: return 0;
2148: }
2149:
2150: void *
2151: azalia_allocm(void *v, int dir, size_t size, int pool, int flags)
2152: {
2153: azalia_t *az;
2154: stream_t *stream;
2155: int err;
2156:
2157: az = v;
2158: stream = dir == AUMODE_PLAY ? &az->pstream : &az->rstream;
2159: err = azalia_alloc_dmamem(az, size, 128, &stream->buffer);
2160: if (err) {
2161: printf("%s: allocm failed\n", az->dev.dv_xname);
2162: return NULL;
2163: }
2164: return stream->buffer.addr;
2165: }
2166:
2167: void
2168: azalia_freem(void *v, void *addr, int pool)
2169: {
2170: azalia_t *az;
2171: stream_t *stream;
2172:
2173: az = v;
2174: if (addr == az->pstream.buffer.addr) {
2175: stream = &az->pstream;
2176: } else if (addr == az->rstream.buffer.addr) {
2177: stream = &az->rstream;
2178: } else {
2179: return;
2180: }
2181: azalia_free_dmamem(az, &stream->buffer);
2182: }
2183:
2184: size_t
2185: azalia_round_buffersize(void *v, int dir, size_t size)
2186: {
2187: size &= ~0x7f; /* must be multiple of 128 */
2188: if (size <= 0)
2189: size = 128;
2190: return size;
2191: }
2192:
2193: int
2194: azalia_get_props(void *v)
2195: {
2196: return AUDIO_PROP_INDEPENDENT | AUDIO_PROP_FULLDUPLEX;
2197: }
2198:
2199: int
2200: azalia_trigger_output(void *v, void *start, void *end, int blk,
2201: void (*intr)(void *), void *arg, audio_params_t *param)
2202: {
2203: azalia_t *az;
2204: int err;
2205: uint16_t fmt;
2206:
2207: err = azalia_params2fmt(param, &fmt);
2208: if (err)
2209: return EINVAL;
2210:
2211: az = v;
2212: return azalia_stream_start(&az->pstream, start, end, blk, intr, arg, fmt);
2213: }
2214:
2215: int
2216: azalia_trigger_input(void *v, void *start, void *end, int blk,
2217: void (*intr)(void *), void *arg, audio_params_t *param)
2218: {
2219: azalia_t *az;
2220: int err;
2221: uint16_t fmt;
2222:
2223: DPRINTF(("%s: this=%p start=%p end=%p blk=%d {enc=%u %uch %u/%ubit %uHz}\n",
2224: __func__, v, start, end, blk, param->encoding, param->channels,
2225: param->precision, param->precision, param->sample_rate));
2226:
2227: err = azalia_params2fmt(param, &fmt);
2228: if (err)
2229: return EINVAL;
2230:
2231: az = v;
2232: return azalia_stream_start(&az->rstream, start, end, blk, intr, arg, fmt);
2233: }
2234:
2235: /* --------------------------------
2236: * helpers for MI audio functions
2237: * -------------------------------- */
2238: int
2239: azalia_params2fmt(const audio_params_t *param, uint16_t *fmt)
2240: {
2241: uint16_t ret;
2242:
2243: ret = 0;
2244: #ifdef DIAGNOSTIC
2245: if (param->channels > HDA_MAX_CHANNELS) {
2246: printf("%s: too many channels: %u\n", __func__,
2247: param->channels);
2248: return EINVAL;
2249: }
2250: #endif
2251: ret |= param->channels - 1;
2252:
2253: switch (param->precision) {
2254: case 8:
2255: ret |= HDA_SD_FMT_BITS_8_16;
2256: break;
2257: case 16:
2258: ret |= HDA_SD_FMT_BITS_16_16;
2259: break;
2260: case 32:
2261: ret |= HDA_SD_FMT_BITS_32_32;
2262: break;
2263: }
2264:
2265: #if 0
2266: switch (param->validbits) {
2267: case 8:
2268: ret |= HDA_SD_FMT_BITS_8_16;
2269: break;
2270: case 16:
2271: ret |= HDA_SD_FMT_BITS_16_16;
2272: break;
2273: case 20:
2274: ret |= HDA_SD_FMT_BITS_20_32;
2275: break;
2276: case 24:
2277: ret |= HDA_SD_FMT_BITS_24_32;
2278: break;
2279: case 32:
2280: ret |= HDA_SD_FMT_BITS_32_32;
2281: break;
2282: default:
2283: printf("%s: invalid validbits: %u\n", __func__,
2284: param->validbits);
2285: }
2286: #endif
2287:
2288: if (param->sample_rate == 384000) {
2289: printf("%s: invalid sample_rate: %u\n", __func__,
2290: param->sample_rate);
2291: return EINVAL;
2292: } else if (param->sample_rate == 192000) {
2293: ret |= HDA_SD_FMT_BASE_48 | HDA_SD_FMT_MULT_X4 | HDA_SD_FMT_DIV_BY1;
2294: } else if (param->sample_rate == 176400) {
2295: ret |= HDA_SD_FMT_BASE_44 | HDA_SD_FMT_MULT_X4 | HDA_SD_FMT_DIV_BY1;
2296: } else if (param->sample_rate == 96000) {
2297: ret |= HDA_SD_FMT_BASE_48 | HDA_SD_FMT_MULT_X2 | HDA_SD_FMT_DIV_BY1;
2298: } else if (param->sample_rate == 88200) {
2299: ret |= HDA_SD_FMT_BASE_44 | HDA_SD_FMT_MULT_X2 | HDA_SD_FMT_DIV_BY1;
2300: } else if (param->sample_rate == 48000) {
2301: ret |= HDA_SD_FMT_BASE_48 | HDA_SD_FMT_MULT_X1 | HDA_SD_FMT_DIV_BY1;
2302: } else if (param->sample_rate == 44100) {
2303: ret |= HDA_SD_FMT_BASE_44 | HDA_SD_FMT_MULT_X1 | HDA_SD_FMT_DIV_BY1;
2304: } else if (param->sample_rate == 32000) {
2305: ret |= HDA_SD_FMT_BASE_48 | HDA_SD_FMT_MULT_X2 | HDA_SD_FMT_DIV_BY3;
2306: } else if (param->sample_rate == 22050) {
2307: ret |= HDA_SD_FMT_BASE_44 | HDA_SD_FMT_MULT_X1 | HDA_SD_FMT_DIV_BY2;
2308: } else if (param->sample_rate == 16000) {
2309: ret |= HDA_SD_FMT_BASE_48 | HDA_SD_FMT_MULT_X1 | HDA_SD_FMT_DIV_BY3;
2310: } else if (param->sample_rate == 11025) {
2311: ret |= HDA_SD_FMT_BASE_44 | HDA_SD_FMT_MULT_X1 | HDA_SD_FMT_DIV_BY4;
2312: } else if (param->sample_rate == 8000) {
2313: ret |= HDA_SD_FMT_BASE_48 | HDA_SD_FMT_MULT_X1 | HDA_SD_FMT_DIV_BY6;
2314: } else {
2315: printf("%s: invalid sample_rate: %u\n", __func__,
2316: param->sample_rate);
2317: return EINVAL;
2318: }
2319: *fmt = ret;
2320: return 0;
2321: }
2322:
2323: int
2324: azalia_create_encodings(struct audio_format *formats, int nformats,
2325: struct audio_encoding_set **encodings)
2326: {
2327: #if 0
2328: int i;
2329: u_int j;
2330:
2331: for (i = 0; i < nformats; i++) {
2332: printf("format(%d): encoding %u vbits %u prec %u chans %u cmask 0x%x\n",
2333: i, formats[i].encoding, formats[i].validbits,
2334: formats[i].precision, formats[i].channels,
2335: formats[i].channel_mask);
2336: printf("format(%d) rates:", i);
2337: for (j = 0; j < formats[i].frequency_type; j++) {
2338: printf(" %u", formats[i].frequency[j]);
2339: }
2340: printf("\n");
2341: }
2342: #endif
2343: return (0);
2344: }
CVSweb