Bug Summary

File:dev/pci/azalia.c
Warning:line 2259, column 10
Although the value stored to 'conv' is used in the enclosing expression, the value is never actually read from 'conv'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.4 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name azalia.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model static -mframe-pointer=all -relaxed-aliasing -ffp-contract=on -fno-rounding-math -mconstructor-aliases -ffreestanding -mcmodel=kernel -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -target-feature -sse2 -target-feature -sse -target-feature -3dnow -target-feature -mmx -target-feature +save-args -target-feature +retpoline-external-thunk -disable-red-zone -no-implicit-float -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -nostdsysteminc -nobuiltininc -resource-dir /usr/local/llvm16/lib/clang/16 -I /usr/src/sys -I /usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -I /usr/src/sys/arch -I /usr/src/sys/dev/pci/drm/include -I /usr/src/sys/dev/pci/drm/include/uapi -I /usr/src/sys/dev/pci/drm/amd/include/asic_reg -I /usr/src/sys/dev/pci/drm/amd/include -I /usr/src/sys/dev/pci/drm/amd/amdgpu -I /usr/src/sys/dev/pci/drm/amd/display -I /usr/src/sys/dev/pci/drm/amd/display/include -I /usr/src/sys/dev/pci/drm/amd/display/dc -I /usr/src/sys/dev/pci/drm/amd/display/amdgpu_dm -I /usr/src/sys/dev/pci/drm/amd/pm/inc -I /usr/src/sys/dev/pci/drm/amd/pm/legacy-dpm -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/inc -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu11 -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu12 -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu13 -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/inc -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/hwmgr -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/smumgr -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/inc -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/inc/pmfw_if -I /usr/src/sys/dev/pci/drm/amd/display/dc/inc -I /usr/src/sys/dev/pci/drm/amd/display/dc/inc/hw -I /usr/src/sys/dev/pci/drm/amd/display/dc/clk_mgr -I /usr/src/sys/dev/pci/drm/amd/display/modules/inc -I /usr/src/sys/dev/pci/drm/amd/display/modules/hdcp -I /usr/src/sys/dev/pci/drm/amd/display/dmub/inc -I /usr/src/sys/dev/pci/drm/i915 -D DDB -D DIAGNOSTIC -D KTRACE -D ACCOUNTING -D KMEMSTATS -D PTRACE -D POOL_DEBUG -D CRYPTO -D SYSVMSG -D SYSVSEM -D SYSVSHM -D UVM_SWAP_ENCRYPT -D FFS -D FFS2 -D FFS_SOFTUPDATES -D UFS_DIRHASH -D QUOTA -D EXT2FS -D MFS -D NFSCLIENT -D NFSSERVER -D CD9660 -D UDF -D MSDOSFS -D FIFO -D FUSE -D SOCKET_SPLICE -D TCP_ECN -D TCP_SIGNATURE -D INET6 -D IPSEC -D PPP_BSDCOMP -D PPP_DEFLATE -D PIPEX -D MROUTING -D MPLS -D BOOT_CONFIG -D USER_PCICONF -D APERTURE -D MTRR -D NTFS -D SUSPEND -D HIBERNATE -D PCIVERBOSE -D USBVERBOSE -D WSDISPLAY_COMPAT_USL -D WSDISPLAY_COMPAT_RAWKBD -D WSDISPLAY_DEFAULTSCREENS=6 -D X86EMU -D ONEWIREVERBOSE -D MULTIPROCESSOR -D MAXUSERS=80 -D _KERNEL -O2 -Wno-pointer-sign -Wno-address-of-packed-member -Wno-constant-conversion -Wno-unused-but-set-variable -Wno-gnu-folding-constant -fdebug-compilation-dir=/usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fcf-protection=branch -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -o /home/ben/Projects/scan/2024-01-11-110808-61670-1 -x c /usr/src/sys/dev/pci/azalia.c
1/* $OpenBSD: azalia.c,v 1.285 2023/11/23 14:24:06 jsg 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 *
20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 * POSSIBILITY OF SUCH DAMAGE.
31 */
32
33/*
34 * High Definition Audio Specification
35 *
36 * http://www.intel.com/content/dam/www/public/us/en/documents/product-specifications/high-definition-audio-specification.pdf
37 *
38 *
39 * TO DO:
40 * - multiple codecs (needed?)
41 * - multiple streams (needed?)
42 */
43
44#include <sys/param.h>
45#include <sys/fcntl.h>
46#include <sys/device.h>
47#include <sys/malloc.h>
48#include <sys/systm.h>
49#include <sys/timeout.h>
50#include <dev/audio_if.h>
51#include <dev/pci/pcidevs.h>
52#include <dev/pci/pcivar.h>
53
54#include <dev/pci/azalia.h>
55
56typedef struct audio_params audio_params_t;
57
58struct audio_format {
59 void *driver_data;
60 int32_t mode;
61 u_int encoding;
62 u_int precision;
63 u_int channels;
64
65 /**
66 * 0: frequency[0] is lower limit, and frequency[1] is higher limit.
67 * 1-16: frequency[0] to frequency[frequency_type-1] are valid.
68 */
69 u_int frequency_type;
70
71#define AUFMT_MAX_FREQUENCIES16 16
72 /**
73 * sampling rates
74 */
75 u_int frequency[AUFMT_MAX_FREQUENCIES16];
76};
77
78
79#ifdef AZALIA_DEBUG
80# define DPRINTFN(n,x)do {} while (0 ) do { if (az_debug > (n)) printf x; } while (0/*CONSTCOND*/)
81int az_debug = 0;
82#else
83# define DPRINTFN(n,x)do {} while (0 ) do {} while (0/*CONSTCOND*/)
84#endif
85
86
87/* ----------------------------------------------------------------
88 * ICH6/ICH7 constant values
89 * ---------------------------------------------------------------- */
90
91/* PCI registers */
92#define ICH_PCI_HDBARL0x10 0x10
93#define ICH_PCI_HDBARU0x14 0x14
94#define ICH_PCI_HDCTL0x40 0x40
95#define ICH_PCI_HDCTL_CLKDETCLR0x08 0x08
96#define ICH_PCI_HDCTL_CLKDETEN0x04 0x04
97#define ICH_PCI_HDCTL_CLKDETINV0x02 0x02
98#define ICH_PCI_HDCTL_SIGNALMODE0x01 0x01
99#define ICH_PCI_HDTCSEL0x44 0x44
100#define ICH_PCI_HDTCSEL_MASK0x7 0x7
101#define ICH_PCI_MMC0x62 0x62
102#define ICH_PCI_MMC_ME0x1 0x1
103
104/* internal types */
105
106typedef struct {
107 bus_dmamap_t map;
108 caddr_t addr; /* kernel virtual address */
109 bus_dma_segment_t segments[1];
110 size_t size;
111} azalia_dma_t;
112#define AZALIA_DMA_DMAADDR(p)((p)->map->dm_segs[0].ds_addr) ((p)->map->dm_segs[0].ds_addr)
113
114typedef struct {
115 struct azalia_t *az;
116 int regbase;
117 int number;
118 int dir; /* AUMODE_PLAY or AUMODE_RECORD */
119 uint32_t intr_bit;
120 azalia_dma_t bdlist;
121 azalia_dma_t buffer;
122 void (*intr)(void*);
123 void *intr_arg;
124 int bufsize;
125 uint16_t fmt;
126 int blk;
127 unsigned int swpos; /* position in the audio(4) layer */
128} stream_t;
129#define STR_READ_1(s, r)(((s)->az->iot)->read_1(((s)->az->ioh), ((s)->
regbase + HDA_SD_r)))
\
130 bus_space_read_1((s)->az->iot, (s)->az->ioh, (s)->regbase + HDA_SD_##r)(((s)->az->iot)->read_1(((s)->az->ioh), ((s)->
regbase + HDA_SD_##r)))
131#define STR_READ_2(s, r)(((s)->az->iot)->read_2(((s)->az->ioh), ((s)->
regbase + HDA_SD_r)))
\
132 bus_space_read_2((s)->az->iot, (s)->az->ioh, (s)->regbase + HDA_SD_##r)(((s)->az->iot)->read_2(((s)->az->ioh), ((s)->
regbase + HDA_SD_##r)))
133#define STR_READ_4(s, r)(((s)->az->iot)->read_4(((s)->az->ioh), ((s)->
regbase + HDA_SD_r)))
\
134 bus_space_read_4((s)->az->iot, (s)->az->ioh, (s)->regbase + HDA_SD_##r)(((s)->az->iot)->read_4(((s)->az->ioh), ((s)->
regbase + HDA_SD_##r)))
135#define STR_WRITE_1(s, r, v)(((s)->az->iot)->write_1(((s)->az->ioh), ((s)->
regbase + HDA_SD_r), (v)))
\
136 bus_space_write_1((s)->az->iot, (s)->az->ioh, (s)->regbase + HDA_SD_##r, v)(((s)->az->iot)->write_1(((s)->az->ioh), ((s)->
regbase + HDA_SD_##r), (v)))
137#define STR_WRITE_2(s, r, v)(((s)->az->iot)->write_2(((s)->az->ioh), ((s)->
regbase + HDA_SD_r), (v)))
\
138 bus_space_write_2((s)->az->iot, (s)->az->ioh, (s)->regbase + HDA_SD_##r, v)(((s)->az->iot)->write_2(((s)->az->ioh), ((s)->
regbase + HDA_SD_##r), (v)))
139#define STR_WRITE_4(s, r, v)(((s)->az->iot)->write_4(((s)->az->ioh), ((s)->
regbase + HDA_SD_r), (v)))
\
140 bus_space_write_4((s)->az->iot, (s)->az->ioh, (s)->regbase + HDA_SD_##r, v)(((s)->az->iot)->write_4(((s)->az->ioh), ((s)->
regbase + HDA_SD_##r), (v)))
141
142typedef struct azalia_t {
143 struct device dev;
144
145 pci_chipset_tag_t pc;
146 pcitag_t tag;
147 void *ih;
148 bus_space_tag_t iot;
149 bus_space_handle_t ioh;
150 bus_size_t map_size;
151 bus_dma_tag_t dmat;
152 pcireg_t pciid;
153 uint32_t subid;
154
155 codec_t *codecs;
156 int ncodecs; /* number of codecs */
157 int codecno; /* index of the using codec */
158 int detached; /* 1 if failed to initialize, 2 if
159 * azalia_pci_detach has run
160 */
161 azalia_dma_t corb_dma;
162 int corb_entries;
163 uint8_t corbsize;
164 azalia_dma_t rirb_dma;
165 int rirb_entries;
166 uint8_t rirbsize;
167 int rirb_rp;
168#define UNSOLQ_SIZE256 256
169 rirb_entry_t *unsolq;
170 int unsolq_wp;
171 int unsolq_rp;
172 int unsolq_kick;
173 struct timeout unsol_to;
174
175 int ok64;
176 int nistreams, nostreams, nbstreams;
177 stream_t pstream;
178 stream_t rstream;
179} azalia_t;
180#define XNAME(sc)((sc)->dev.dv_xname) ((sc)->dev.dv_xname)
181#define AZ_READ_1(z, r)(((z)->iot)->read_1(((z)->ioh), (HDA_r))) bus_space_read_1((z)->iot, (z)->ioh, HDA_##r)(((z)->iot)->read_1(((z)->ioh), (HDA_##r)))
182#define AZ_READ_2(z, r)(((z)->iot)->read_2(((z)->ioh), (HDA_r))) bus_space_read_2((z)->iot, (z)->ioh, HDA_##r)(((z)->iot)->read_2(((z)->ioh), (HDA_##r)))
183#define AZ_READ_4(z, r)(((z)->iot)->read_4(((z)->ioh), (HDA_r))) bus_space_read_4((z)->iot, (z)->ioh, HDA_##r)(((z)->iot)->read_4(((z)->ioh), (HDA_##r)))
184#define AZ_WRITE_1(z, r, v)(((z)->iot)->write_1(((z)->ioh), (HDA_r), (v))) bus_space_write_1((z)->iot, (z)->ioh, HDA_##r, v)(((z)->iot)->write_1(((z)->ioh), (HDA_##r), (v)))
185#define AZ_WRITE_2(z, r, v)(((z)->iot)->write_2(((z)->ioh), (HDA_r), (v))) bus_space_write_2((z)->iot, (z)->ioh, HDA_##r, v)(((z)->iot)->write_2(((z)->ioh), (HDA_##r), (v)))
186#define AZ_WRITE_4(z, r, v)(((z)->iot)->write_4(((z)->ioh), (HDA_r), (v))) bus_space_write_4((z)->iot, (z)->ioh, HDA_##r, v)(((z)->iot)->write_4(((z)->ioh), (HDA_##r), (v)))
187
188
189/* prototypes */
190uint8_t azalia_pci_read(pci_chipset_tag_t, pcitag_t, int);
191void azalia_pci_write(pci_chipset_tag_t, pcitag_t, int, uint8_t);
192int azalia_pci_match(struct device *, void *, void *);
193void azalia_pci_attach(struct device *, struct device *, void *);
194int azalia_pci_activate(struct device *, int);
195int azalia_pci_detach(struct device *, int);
196void azalia_configure_pci(azalia_t *);
197int azalia_intr(void *);
198void azalia_print_codec(codec_t *);
199int azalia_reset(azalia_t *);
200int azalia_get_ctrlr_caps(azalia_t *);
201int azalia_init(azalia_t *, int);
202int azalia_init_codecs(azalia_t *);
203int azalia_init_streams(azalia_t *);
204void azalia_shutdown(void *);
205int azalia_halt_corb(azalia_t *);
206int azalia_init_corb(azalia_t *, int);
207int azalia_halt_rirb(azalia_t *);
208int azalia_init_rirb(azalia_t *, int);
209int azalia_set_command(azalia_t *, nid_t, int, uint32_t, uint32_t);
210int azalia_get_response(azalia_t *, uint32_t *);
211void azalia_rirb_kick_unsol_events(void *);
212void azalia_rirb_intr(azalia_t *);
213int azalia_alloc_dmamem(azalia_t *, size_t, size_t, azalia_dma_t *);
214void azalia_free_dmamem(const azalia_t *, azalia_dma_t*);
215
216int azalia_codec_init(codec_t *);
217int azalia_codec_delete(codec_t *);
218void azalia_codec_add_bits(codec_t *, int, uint32_t, int);
219void azalia_codec_add_format(codec_t *, int, int, uint32_t, int32_t);
220int azalia_codec_connect_stream(stream_t *);
221int azalia_codec_disconnect_stream(stream_t *);
222void azalia_codec_print_audiofunc(const codec_t *);
223void azalia_codec_print_groups(const codec_t *);
224int azalia_codec_find_defdac(codec_t *, int, int);
225int azalia_codec_find_defadc(codec_t *, int, int);
226int azalia_codec_find_defadc_sub(codec_t *, nid_t, int, int);
227int azalia_codec_init_volgroups(codec_t *);
228int azalia_codec_sort_pins(codec_t *);
229int azalia_codec_select_micadc(codec_t *);
230int azalia_codec_select_dacs(codec_t *);
231int azalia_codec_select_spkrdac(codec_t *);
232int azalia_codec_find_inputmixer(codec_t *);
233
234int azalia_widget_init(widget_t *, const codec_t *, int);
235int azalia_widget_label_widgets(codec_t *);
236int azalia_widget_init_audio(widget_t *, const codec_t *);
237int azalia_widget_init_pin(widget_t *, const codec_t *);
238int azalia_widget_init_connection(widget_t *, const codec_t *);
239int azalia_widget_check_conn(codec_t *, int, int);
240int azalia_widget_sole_conn(codec_t *, nid_t);
241void azalia_widget_print_widget(const widget_t *, const codec_t *);
242void azalia_widget_print_audio(const widget_t *, const char *);
243void azalia_widget_print_pin(const widget_t *);
244
245int azalia_stream_init(stream_t *, azalia_t *, int, int, int);
246int azalia_stream_reset(stream_t *);
247int azalia_stream_start(stream_t *);
248int azalia_stream_halt(stream_t *);
249int azalia_stream_intr(stream_t *);
250
251int azalia_open(void *, int);
252void azalia_close(void *);
253int azalia_set_params(void *, int, int, audio_params_t *,
254 audio_params_t *);
255unsigned int azalia_set_blksz(void *, int,
256 struct audio_params *, struct audio_params *, unsigned int);
257unsigned int azalia_set_nblks(void *, int,
258 struct audio_params *, unsigned int, unsigned int);
259int azalia_halt_output(void *);
260int azalia_halt_input(void *);
261int azalia_set_port(void *, mixer_ctrl_t *);
262int azalia_get_port(void *, mixer_ctrl_t *);
263int azalia_query_devinfo(void *, mixer_devinfo_t *);
264void *azalia_allocm(void *, int, size_t, int, int);
265void azalia_freem(void *, void *, int);
266size_t azalia_round_buffersize(void *, int, size_t);
267int azalia_trigger_output(void *, void *, void *, int,
268 void (*)(void *), void *, audio_params_t *);
269int azalia_trigger_input(void *, void *, void *, int,
270 void (*)(void *), void *, audio_params_t *);
271
272int azalia_params2fmt(const audio_params_t *, uint16_t *);
273
274int azalia_match_format(codec_t *, int, audio_params_t *);
275int azalia_set_params_sub(codec_t *, int, audio_params_t *);
276
277int azalia_suspend(azalia_t *);
278int azalia_resume(azalia_t *);
279int azalia_resume_codec(codec_t *);
280
281/* variables */
282const struct cfattach azalia_ca = {
283 sizeof(azalia_t), azalia_pci_match, azalia_pci_attach,
284 azalia_pci_detach, azalia_pci_activate
285};
286
287struct cfdriver azalia_cd = {
288 NULL((void *)0), "azalia", DV_DULL, CD_SKIPHIBERNATE2
289};
290
291const struct audio_hw_if azalia_hw_if = {
292 .open = azalia_open,
293 .close = azalia_close,
294 .set_params = azalia_set_params,
295 .halt_output = azalia_halt_output,
296 .halt_input = azalia_halt_input,
297 .set_port = azalia_set_port,
298 .get_port = azalia_get_port,
299 .query_devinfo = azalia_query_devinfo,
300 .allocm = azalia_allocm,
301 .freem = azalia_freem,
302 .round_buffersize = azalia_round_buffersize,
303 .trigger_output = azalia_trigger_output,
304 .trigger_input = azalia_trigger_input,
305 .set_blksz = azalia_set_blksz,
306 .set_nblks = azalia_set_nblks,
307};
308
309static const char *pin_devices[16] = {
310 AudioNline"line", AudioNspeaker"spkr", AudioNheadphone"hp", AudioNcd"cd",
311 "SPDIF", "digital-out", "modem-line", "modem-handset",
312 "line-in", AudioNaux"aux", AudioNmicrophone"mic", "telephony",
313 "SPDIF-in", "digital-in", "beep", "other"};
314static const char *wtypes[16] = {
315 "dac", "adc", "mix", "sel", "pin", "pow", "volume",
316 "beep", "wid08", "wid09", "wid0a", "wid0b", "wid0c",
317 "wid0d", "wid0e", "vendor"};
318static const char *line_colors[16] = {
319 "unk", "blk", "gry", "blu", "grn", "red", "org", "yel",
320 "pur", "pnk", "0xa", "0xb", "0xc", "0xd", "wht", "oth"};
321
322/* ================================================================
323 * PCI functions
324 * ================================================================ */
325
326#define ATI_PCIE_SNOOP_REG0x42 0x42
327#define ATI_PCIE_SNOOP_MASK0xf8 0xf8
328#define ATI_PCIE_SNOOP_ENABLE0x02 0x02
329#define NVIDIA_PCIE_SNOOP_REG0x4e 0x4e
330#define NVIDIA_PCIE_SNOOP_MASK0xf0 0xf0
331#define NVIDIA_PCIE_SNOOP_ENABLE0x0f 0x0f
332#define NVIDIA_HDA_ISTR_COH_REG0x4d 0x4d
333#define NVIDIA_HDA_OSTR_COH_REG0x4c 0x4c
334#define NVIDIA_HDA_STR_COH_ENABLE0x01 0x01
335#define INTEL_PCIE_NOSNOOP_REG0x79 0x79
336#define INTEL_PCIE_NOSNOOP_MASK0xf7 0xf7
337#define INTEL_PCIE_NOSNOOP_ENABLE0x08 0x08
338
339uint8_t
340azalia_pci_read(pci_chipset_tag_t pc, pcitag_t pa, int reg)
341{
342 return (pci_conf_read(pc, pa, (reg & ~0x03)) >>
343 ((reg & 0x03) * 8) & 0xff);
344}
345
346void
347azalia_pci_write(pci_chipset_tag_t pc, pcitag_t pa, int reg, uint8_t val)
348{
349 pcireg_t pcival;
350
351 pcival = pci_conf_read(pc, pa, (reg & ~0x03));
352 pcival &= ~(0xff << ((reg & 0x03) * 8));
353 pcival |= (val << ((reg & 0x03) * 8));
354 pci_conf_write(pc, pa, (reg & ~0x03), pcival);
355}
356
357void
358azalia_configure_pci(azalia_t *az)
359{
360 pcireg_t v;
361 uint8_t reg;
362
363 /* enable back-to-back */
364 v = pci_conf_read(az->pc, az->tag, PCI_COMMAND_STATUS_REG0x04);
365 pci_conf_write(az->pc, az->tag, PCI_COMMAND_STATUS_REG0x04,
366 v | PCI_COMMAND_BACKTOBACK_ENABLE0x00000200);
367
368 /* traffic class select */
369 v = pci_conf_read(az->pc, az->tag, ICH_PCI_HDTCSEL0x44);
370 pci_conf_write(az->pc, az->tag, ICH_PCI_HDTCSEL0x44,
371 v & ~(ICH_PCI_HDTCSEL_MASK0x7));
372
373 /* enable PCIe snoop */
374 switch (PCI_PRODUCT(az->pciid)(((az->pciid) >> 16) & 0xffff)) {
375 case PCI_PRODUCT_ATI_SB450_HDA0x437b:
376 case PCI_PRODUCT_ATI_SBX00_HDA0x4383:
377 case PCI_PRODUCT_AMD_15_6X_AUDIO0x157a:
378 case PCI_PRODUCT_AMD_17_HDA0x1457:
379 case PCI_PRODUCT_AMD_17_1X_HDA0x15e3:
380 case PCI_PRODUCT_AMD_17_3X_HDA0x1487:
381 case PCI_PRODUCT_AMD_HUDSON2_HDA0x780d:
382 reg = azalia_pci_read(az->pc, az->tag, ATI_PCIE_SNOOP_REG0x42);
383 reg &= ATI_PCIE_SNOOP_MASK0xf8;
384 reg |= ATI_PCIE_SNOOP_ENABLE0x02;
385 azalia_pci_write(az->pc, az->tag, ATI_PCIE_SNOOP_REG0x42, reg);
386 break;
387 case PCI_PRODUCT_NVIDIA_MCP51_HDA0x026c:
388 case PCI_PRODUCT_NVIDIA_MCP55_HDA0x0371:
389 case PCI_PRODUCT_NVIDIA_MCP61_HDA_10x03e4:
390 case PCI_PRODUCT_NVIDIA_MCP61_HDA_20x03f0:
391 case PCI_PRODUCT_NVIDIA_MCP65_HDA_10x044a:
392 case PCI_PRODUCT_NVIDIA_MCP65_HDA_20x044b:
393 case PCI_PRODUCT_NVIDIA_MCP67_HDA_10x055c:
394 case PCI_PRODUCT_NVIDIA_MCP67_HDA_20x055d:
395 case PCI_PRODUCT_NVIDIA_MCP73_HDA_10x07fc:
396 case PCI_PRODUCT_NVIDIA_MCP73_HDA_20x07fd:
397 case PCI_PRODUCT_NVIDIA_MCP77_HDA_10x0774:
398 case PCI_PRODUCT_NVIDIA_MCP77_HDA_20x0775:
399 case PCI_PRODUCT_NVIDIA_MCP77_HDA_30x0776:
400 case PCI_PRODUCT_NVIDIA_MCP77_HDA_40x0777:
401 case PCI_PRODUCT_NVIDIA_MCP79_HDA_10x0ac0:
402 case PCI_PRODUCT_NVIDIA_MCP79_HDA_20x0ac1:
403 case PCI_PRODUCT_NVIDIA_MCP79_HDA_30x0ac2:
404 case PCI_PRODUCT_NVIDIA_MCP79_HDA_40x0ac3:
405 case PCI_PRODUCT_NVIDIA_MCP89_HDA_10x0d94:
406 case PCI_PRODUCT_NVIDIA_MCP89_HDA_20x0d95:
407 case PCI_PRODUCT_NVIDIA_MCP89_HDA_30x0d96:
408 case PCI_PRODUCT_NVIDIA_MCP89_HDA_40x0d97:
409 reg = azalia_pci_read(az->pc, az->tag,
410 NVIDIA_HDA_OSTR_COH_REG0x4c);
411 reg |= NVIDIA_HDA_STR_COH_ENABLE0x01;
412 azalia_pci_write(az->pc, az->tag,
413 NVIDIA_HDA_OSTR_COH_REG0x4c, reg);
414
415 reg = azalia_pci_read(az->pc, az->tag,
416 NVIDIA_HDA_ISTR_COH_REG0x4d);
417 reg |= NVIDIA_HDA_STR_COH_ENABLE0x01;
418 azalia_pci_write(az->pc, az->tag,
419 NVIDIA_HDA_ISTR_COH_REG0x4d, reg);
420
421 reg = azalia_pci_read(az->pc, az->tag,
422 NVIDIA_PCIE_SNOOP_REG0x4e);
423 reg &= NVIDIA_PCIE_SNOOP_MASK0xf0;
424 reg |= NVIDIA_PCIE_SNOOP_ENABLE0x0f;
425 azalia_pci_write(az->pc, az->tag,
426 NVIDIA_PCIE_SNOOP_REG0x4e, reg);
427
428 reg = azalia_pci_read(az->pc, az->tag,
429 NVIDIA_PCIE_SNOOP_REG0x4e);
430 if ((reg & NVIDIA_PCIE_SNOOP_ENABLE0x0f) !=
431 NVIDIA_PCIE_SNOOP_ENABLE0x0f) {
432 printf(": could not enable PCIe cache snooping!\n");
433 }
434 break;
435 case PCI_PRODUCT_INTEL_82801FB_HDA0x2668:
436 case PCI_PRODUCT_INTEL_82801GB_HDA0x27d8:
437 case PCI_PRODUCT_INTEL_82801H_HDA0x284b:
438 case PCI_PRODUCT_INTEL_82801I_HDA0x293e:
439 case PCI_PRODUCT_INTEL_82801JI_HDA0x3a3e:
440 case PCI_PRODUCT_INTEL_82801JD_HDA0x3a6e:
441 case PCI_PRODUCT_INTEL_6321ESB_HDA0x269a:
442 case PCI_PRODUCT_INTEL_3400_HDA0x3b56:
443 case PCI_PRODUCT_INTEL_QS57_HDA0x3b57:
444 case PCI_PRODUCT_INTEL_6SERIES_HDA0x1c20:
445 case PCI_PRODUCT_INTEL_7SERIES_HDA0x1e20:
446 case PCI_PRODUCT_INTEL_8SERIES_HDA0x8c20:
447 case PCI_PRODUCT_INTEL_8SERIES_LP_HDA0x9c20:
448 case PCI_PRODUCT_INTEL_9SERIES_HDA0x8ca0:
449 case PCI_PRODUCT_INTEL_9SERIES_LP_HDA0x9ca0:
450 case PCI_PRODUCT_INTEL_100SERIES_HDA0xa170:
451 case PCI_PRODUCT_INTEL_100SERIES_H_HDA0xa171:
452 case PCI_PRODUCT_INTEL_100SERIES_LP_HDA0x9d70:
453 case PCI_PRODUCT_INTEL_200SERIES_HDA0xa2f0:
454 case PCI_PRODUCT_INTEL_200SERIES_U_HDA0x9d71:
455 case PCI_PRODUCT_INTEL_300SERIES_CAVS0xa348:
456 case PCI_PRODUCT_INTEL_300SERIES_U_HDA0x9dc8:
457 case PCI_PRODUCT_INTEL_400SERIES_CAVS0x06c8:
458 case PCI_PRODUCT_INTEL_400SERIES_LP_HDA0x02c8:
459 case PCI_PRODUCT_INTEL_495SERIES_LP_HDA0x34c8:
460 case PCI_PRODUCT_INTEL_500SERIES_HDA0x43c8:
461 case PCI_PRODUCT_INTEL_500SERIES_HDA_20xf0c8:
462 case PCI_PRODUCT_INTEL_500SERIES_LP_HDA0xa0c8:
463 case PCI_PRODUCT_INTEL_600SERIES_HDA0x7ad0:
464 case PCI_PRODUCT_INTEL_600SERIES_LP_HDA0x51c8:
465 case PCI_PRODUCT_INTEL_700SERIES_HDA0x7a50:
466 case PCI_PRODUCT_INTEL_700SERIES_LP_HDA0x51ca:
467 case PCI_PRODUCT_INTEL_C600_HDA0x1d20:
468 case PCI_PRODUCT_INTEL_C610_HDA_10x8d20:
469 case PCI_PRODUCT_INTEL_C610_HDA_20x8d21:
470 case PCI_PRODUCT_INTEL_C620_HDA_10xa1f0:
471 case PCI_PRODUCT_INTEL_C620_HDA_20xa270:
472 case PCI_PRODUCT_INTEL_APOLLOLAKE_HDA0x5a98:
473 case PCI_PRODUCT_INTEL_BAYTRAIL_HDA0x0f04:
474 case PCI_PRODUCT_INTEL_BSW_HDA0x2284:
475 case PCI_PRODUCT_INTEL_GLK_HDA0x3198:
476 case PCI_PRODUCT_INTEL_JSL_HDA0x4dc8:
477 case PCI_PRODUCT_INTEL_EHL_HDA0x4b58:
478 case PCI_PRODUCT_INTEL_ADL_N_HDA0x54c8:
479 reg = azalia_pci_read(az->pc, az->tag,
480 INTEL_PCIE_NOSNOOP_REG0x79);
481 reg &= INTEL_PCIE_NOSNOOP_MASK0xf7;
482 azalia_pci_write(az->pc, az->tag,
483 INTEL_PCIE_NOSNOOP_REG0x79, reg);
484 break;
485 }
486}
487
488const struct pci_matchid azalia_pci_devices[] = {
489 { PCI_VENDOR_INTEL0x8086, PCI_PRODUCT_INTEL_200SERIES_U_HDA0x9d71 },
490 { PCI_VENDOR_INTEL0x8086, PCI_PRODUCT_INTEL_300SERIES_CAVS0xa348 },
491 { PCI_VENDOR_INTEL0x8086, PCI_PRODUCT_INTEL_300SERIES_U_HDA0x9dc8 },
492 { PCI_VENDOR_INTEL0x8086, PCI_PRODUCT_INTEL_400SERIES_CAVS0x06c8 },
493 { PCI_VENDOR_INTEL0x8086, PCI_PRODUCT_INTEL_400SERIES_LP_HDA0x02c8 },
494 { PCI_VENDOR_INTEL0x8086, PCI_PRODUCT_INTEL_500SERIES_HDA0x43c8 },
495 { PCI_VENDOR_INTEL0x8086, PCI_PRODUCT_INTEL_500SERIES_LP_HDA0xa0c8 },
496 { PCI_VENDOR_INTEL0x8086, PCI_PRODUCT_INTEL_600SERIES_LP_HDA0x51c8 },
497 { PCI_VENDOR_INTEL0x8086, PCI_PRODUCT_INTEL_700SERIES_LP_HDA0x51ca },
498 { PCI_VENDOR_INTEL0x8086, PCI_PRODUCT_INTEL_APOLLOLAKE_HDA0x5a98 },
499 { PCI_VENDOR_INTEL0x8086, PCI_PRODUCT_INTEL_GLK_HDA0x3198 },
500 { PCI_VENDOR_INTEL0x8086, PCI_PRODUCT_INTEL_JSL_HDA0x4dc8 },
501 { PCI_VENDOR_INTEL0x8086, PCI_PRODUCT_INTEL_EHL_HDA0x4b58 },
502 { PCI_VENDOR_INTEL0x8086, PCI_PRODUCT_INTEL_ADL_N_HDA0x54c8 },
503};
504
505int
506azalia_pci_match(struct device *parent, void *match, void *aux)
507{
508 struct pci_attach_args *pa;
509
510 pa = aux;
511 if (PCI_CLASS(pa->pa_class)(((pa->pa_class) >> 24) & 0xff) == PCI_CLASS_MULTIMEDIA0x04
512 && PCI_SUBCLASS(pa->pa_class)(((pa->pa_class) >> 16) & 0xff) == PCI_SUBCLASS_MULTIMEDIA_HDAUDIO0x03)
513 return 1;
514 return pci_matchbyid((struct pci_attach_args *)aux, azalia_pci_devices,
515 nitems(azalia_pci_devices)(sizeof((azalia_pci_devices)) / sizeof((azalia_pci_devices)[0
]))
);
516}
517
518void
519azalia_pci_attach(struct device *parent, struct device *self, void *aux)
520{
521 azalia_t *sc;
522 struct pci_attach_args *pa;
523 pcireg_t v;
524 uint8_t reg;
525 pci_intr_handle_t ih;
526 const char *interrupt_str;
527
528 sc = (azalia_t*)self;
529 pa = aux;
530
531 sc->dmat = pa->pa_dmat;
532
533 pci_set_powerstate(pa->pa_pc, pa->pa_tag, PCI_PMCSR_STATE_D00x0000);
534
535 v = pci_conf_read(pa->pa_pc, pa->pa_tag, ICH_PCI_HDBARL0x10);
536 v &= PCI_MAPREG_TYPE_MASK0x00000001 | PCI_MAPREG_MEM_TYPE_MASK0x00000006;
537 if (pci_mapreg_map(pa, ICH_PCI_HDBARL0x10, v, 0,
538 &sc->iot, &sc->ioh, NULL((void *)0), &sc->map_size, 0)) {
539 printf(": can't map device i/o space\n");
540 return;
541 }
542
543 sc->pc = pa->pa_pc;
544 sc->tag = pa->pa_tag;
545 sc->pciid = pa->pa_id;
546 sc->subid = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_SUBSYS_ID_REG0x2c);
547
548 azalia_configure_pci(sc);
549
550 /* disable MSI, use INTx instead */
551 if (PCI_VENDOR(sc->pciid)(((sc->pciid) >> 0) & 0xffff) == PCI_VENDOR_INTEL0x8086) {
552 reg = azalia_pci_read(sc->pc, sc->tag, ICH_PCI_MMC0x62);
553 reg &= ~(ICH_PCI_MMC_ME0x1);
554 azalia_pci_write(sc->pc, sc->tag, ICH_PCI_MMC0x62, reg);
555 }
556
557 /* disable MSI for AMD Summit Ridge/Raven Ridge HD Audio */
558 if (PCI_VENDOR(sc->pciid)(((sc->pciid) >> 0) & 0xffff) == PCI_VENDOR_AMD0x1022) {
559 switch (PCI_PRODUCT(sc->pciid)(((sc->pciid) >> 16) & 0xffff)) {
560 case PCI_PRODUCT_AMD_17_HDA0x1457:
561 case PCI_PRODUCT_AMD_17_1X_HDA0x15e3:
562 case PCI_PRODUCT_AMD_HUDSON2_HDA0x780d:
563 pa->pa_flags &= ~PCI_FLAGS_MSI_ENABLED0x20;
564 }
565 }
566
567 /* interrupt */
568 if (pci_intr_map_msi(pa, &ih) && pci_intr_map(pa, &ih)) {
569 printf(": can't map interrupt\n");
570 return;
571 }
572 interrupt_str = pci_intr_string(pa->pa_pc, ih);
573 sc->ih = pci_intr_establish(pa->pa_pc, ih, IPL_AUDIO0xb | IPL_MPSAFE0x100,
574 azalia_intr, sc, sc->dev.dv_xname);
575 if (sc->ih == NULL((void *)0)) {
576 printf(": can't establish interrupt");
577 if (interrupt_str != NULL((void *)0))
578 printf(" at %s", interrupt_str);
579 printf("\n");
580 return;
581 }
582 printf(": %s\n", interrupt_str);
583
584 if (azalia_init(sc, 0))
585 goto err_exit;
586
587 if (azalia_init_codecs(sc))
588 goto err_exit;
589
590 if (azalia_init_streams(sc))
591 goto err_exit;
592
593 audio_attach_mi(&azalia_hw_if, sc, NULL((void *)0), &sc->dev);
594
595 return;
596
597err_exit:
598 sc->detached = 1;
599 azalia_pci_detach(self, 0);
600}
601
602int
603azalia_pci_activate(struct device *self, int act)
604{
605 azalia_t *sc = (azalia_t*)self;
606 int rv = 0;
607
608 switch (act) {
609 case DVACT_SUSPEND3:
610 azalia_suspend(sc);
611 break;
612 case DVACT_POWERDOWN6:
613 azalia_shutdown(sc);
614 break;
615 case DVACT_RESUME4:
616 azalia_resume(sc);
617 rv = config_activate_children(self, act);
618 break;
619 default:
620 rv = config_activate_children(self, act);
621 break;
622 }
623 return (rv);
624}
625
626int
627azalia_pci_detach(struct device *self, int flags)
628{
629 azalia_t *az = (azalia_t*)self;
630 uint32_t gctl;
631 int i;
632
633 DPRINTF(("%s\n", __func__))do {} while (0 );
634
635 /*
636 * this function is called if the device could not be supported,
637 * in which case az->detached == 1. check if this function has
638 * already cleaned up.
639 */
640 if (az->detached > 1)
641 return 0;
642
643 config_detach_children(self, flags);
644
645 /* disable unsolicited responses if soft detaching */
646 if (az->detached == 1) {
647 gctl = AZ_READ_4(az, GCTL)(((az)->iot)->read_4(((az)->ioh), (0x008)));
648 AZ_WRITE_4(az, GCTL, gctl &~(HDA_GCTL_UNSOL))(((az)->iot)->write_4(((az)->ioh), (0x008), (gctl &
~(0x00000100))))
;
649 }
650
651 timeout_del(&az->unsol_to);
652
653 DPRINTF(("%s: delete streams\n", __func__))do {} while (0 );
654 if (az->rstream.bdlist.addr != NULL((void *)0))
655 azalia_free_dmamem(az, &az->rstream.bdlist);
656 if (az->pstream.bdlist.addr != NULL((void *)0))
657 azalia_free_dmamem(az, &az->pstream.bdlist);
658
659 DPRINTF(("%s: delete codecs\n", __func__))do {} while (0 );
660 for (i = 0; i < az->ncodecs; i++) {
661 azalia_codec_delete(&az->codecs[i]);
662 }
663 az->ncodecs = 0;
664 if (az->codecs != NULL((void *)0)) {
665 free(az->codecs, M_DEVBUF2, 0);
666 az->codecs = NULL((void *)0);
667 }
668
669 DPRINTF(("%s: delete CORB and RIRB\n", __func__))do {} while (0 );
670 if (az->corb_dma.addr != NULL((void *)0))
671 azalia_free_dmamem(az, &az->corb_dma);
672 if (az->rirb_dma.addr != NULL((void *)0))
673 azalia_free_dmamem(az, &az->rirb_dma);
674 if (az->unsolq != NULL((void *)0)) {
675 free(az->unsolq, M_DEVBUF2, 0);
676 az->unsolq = NULL((void *)0);
677 }
678
679 /* disable interrupts if soft detaching */
680 if (az->detached == 1) {
681 DPRINTF(("%s: disable interrupts\n", __func__))do {} while (0 );
682 AZ_WRITE_4(az, INTCTL, 0)(((az)->iot)->write_4(((az)->ioh), (0x020), (0)));
683
684 DPRINTF(("%s: clear interrupts\n", __func__))do {} while (0 );
685 AZ_WRITE_4(az, INTSTS, HDA_INTSTS_CIS | HDA_INTSTS_GIS)(((az)->iot)->write_4(((az)->ioh), (0x024), (0x40000000
| 0x80000000)))
;
686 AZ_WRITE_2(az, STATESTS, HDA_STATESTS_SDIWAKE)(((az)->iot)->write_2(((az)->ioh), (0x00e), (0x7fff)
))
;
687 AZ_WRITE_1(az, RIRBSTS, HDA_RIRBSTS_RINTFL | HDA_RIRBSTS_RIRBOIS)(((az)->iot)->write_1(((az)->ioh), (0x05d), (0x01 | 0x04
)))
;
688 }
689
690 DPRINTF(("%s: delete PCI resources\n", __func__))do {} while (0 );
691 if (az->ih != NULL((void *)0)) {
692 pci_intr_disestablish(az->pc, az->ih);
693 az->ih = NULL((void *)0);
694 }
695 if (az->map_size != 0) {
696 bus_space_unmap(az->iot, az->ioh, az->map_size);
697 az->map_size = 0;
698 }
699
700 az->detached = 2;
701 return 0;
702}
703
704int
705azalia_intr(void *v)
706{
707 azalia_t *az = v;
708 uint32_t intsts;
709 int ret = 0;
710
711 mtx_enter(&audio_lock);
712 intsts = AZ_READ_4(az, INTSTS)(((az)->iot)->read_4(((az)->ioh), (0x024)));
713 if (intsts == 0 || intsts == 0xffffffff) {
714 mtx_leave(&audio_lock);
715 return (ret);
716 }
717
718 AZ_WRITE_4(az, INTSTS, intsts)(((az)->iot)->write_4(((az)->ioh), (0x024), (intsts)
))
;
719
720 if (intsts & az->pstream.intr_bit) {
721 azalia_stream_intr(&az->pstream);
722 ret = 1;
723 }
724
725 if (intsts & az->rstream.intr_bit) {
726 azalia_stream_intr(&az->rstream);
727 ret = 1;
728 }
729
730 if ((intsts & HDA_INTSTS_CIS0x40000000) &&
731 (AZ_READ_1(az, RIRBCTL)(((az)->iot)->read_1(((az)->ioh), (0x05c))) & HDA_RIRBCTL_RINTCTL0x01) &&
732 (AZ_READ_1(az, RIRBSTS)(((az)->iot)->read_1(((az)->ioh), (0x05d))) & HDA_RIRBSTS_RINTFL0x01)) {
733 azalia_rirb_intr(az);
734 ret = 1;
735 }
736 mtx_leave(&audio_lock);
737 return (ret);
738}
739
740void
741azalia_shutdown(void *v)
742{
743 azalia_t *az = (azalia_t *)v;
744 uint32_t gctl;
745
746 if (az->detached)
747 return;
748
749 /* disable unsolicited response */
750 gctl = AZ_READ_4(az, GCTL)(((az)->iot)->read_4(((az)->ioh), (0x008)));
751 AZ_WRITE_4(az, GCTL, gctl & ~(HDA_GCTL_UNSOL))(((az)->iot)->write_4(((az)->ioh), (0x008), (gctl &
~(0x00000100))))
;
752
753 timeout_del(&az->unsol_to);
754
755 /* halt CORB/RIRB */
756 azalia_halt_corb(az);
757 azalia_halt_rirb(az);
758}
759
760/* ================================================================
761 * HDA controller functions
762 * ================================================================ */
763
764void
765azalia_print_codec(codec_t *codec)
766{
767 const char *vendor;
768
769 if (codec->name == NULL((void *)0)) {
770 vendor = pci_findvendor(codec->vid >> 16);
771 if (vendor == NULL((void *)0))
772 printf("0x%04x/0x%04x",
773 codec->vid >> 16, codec->vid & 0xffff);
774 else
775 printf("%s/0x%04x", vendor, codec->vid & 0xffff);
776 } else
777 printf("%s", codec->name);
778}
779
780int
781azalia_reset(azalia_t *az)
782{
783 uint32_t gctl;
784 int i;
785
786 /* 4.2.2 Starting the High Definition Audio Controller */
787 DPRINTF(("%s: resetting\n", __func__))do {} while (0 );
788 gctl = AZ_READ_4(az, GCTL)(((az)->iot)->read_4(((az)->ioh), (0x008)));
789 AZ_WRITE_4(az, GCTL, gctl & ~HDA_GCTL_CRST)(((az)->iot)->write_4(((az)->ioh), (0x008), (gctl &
~0x00000001)))
;
790 for (i = 5000; i > 0; i--) {
791 DELAY(10)(*delay_func)(10);
792 if ((AZ_READ_4(az, GCTL)(((az)->iot)->read_4(((az)->ioh), (0x008))) & HDA_GCTL_CRST0x00000001) == 0)
793 break;
794 }
795 DPRINTF(("%s: reset counter = %d\n", __func__, i))do {} while (0 );
796 if (i == 0) {
797 DPRINTF(("%s: reset failure\n", XNAME(az)))do {} while (0 );
798 return(ETIMEDOUT60);
799 }
800 DELAY(1000)(*delay_func)(1000);
801 gctl = AZ_READ_4(az, GCTL)(((az)->iot)->read_4(((az)->ioh), (0x008)));
802 AZ_WRITE_4(az, GCTL, gctl | HDA_GCTL_CRST)(((az)->iot)->write_4(((az)->ioh), (0x008), (gctl | 0x00000001
)))
;
803 for (i = 5000; i > 0; i--) {
804 DELAY(10)(*delay_func)(10);
805 if (AZ_READ_4(az, GCTL)(((az)->iot)->read_4(((az)->ioh), (0x008))) & HDA_GCTL_CRST0x00000001)
806 break;
807 }
808 DPRINTF(("%s: reset counter = %d\n", __func__, i))do {} while (0 );
809 if (i == 0) {
810 DPRINTF(("%s: reset-exit failure\n", XNAME(az)))do {} while (0 );
811 return(ETIMEDOUT60);
812 }
813 DELAY(1000)(*delay_func)(1000);
814
815 return(0);
816}
817
818int
819azalia_get_ctrlr_caps(azalia_t *az)
820{
821 int i, n;
822 uint16_t gcap;
823 uint16_t statests;
824 uint8_t cap;
825
826 DPRINTF(("%s: host: High Definition Audio rev. %d.%d\n",do {} while (0 )
827 XNAME(az), AZ_READ_1(az, VMAJ), AZ_READ_1(az, VMIN)))do {} while (0 );
828 gcap = AZ_READ_2(az, GCAP)(((az)->iot)->read_2(((az)->ioh), (0x000)));
829 az->nistreams = HDA_GCAP_ISS(gcap)((gcap & 0x0f00) >> 8);
830 az->nostreams = HDA_GCAP_OSS(gcap)((gcap & 0xf000) >> 12);
831 az->nbstreams = HDA_GCAP_BSS(gcap)((gcap & 0x00f8) >> 3);
832 az->ok64 = (gcap & HDA_GCAP_64OK0x0001) != 0;
833 DPRINTF(("%s: host: %d output, %d input, and %d bidi streams\n",do {} while (0 )
834 XNAME(az), az->nostreams, az->nistreams, az->nbstreams))do {} while (0 );
835
836 /* 4.3 Codec discovery */
837 statests = AZ_READ_2(az, STATESTS)(((az)->iot)->read_2(((az)->ioh), (0x00e)));
838 for (i = 0, n = 0; i < HDA_MAX_CODECS15; i++) {
839 if ((statests >> i) & 1) {
840 DPRINTF(("%s: found a codec at #%d\n", XNAME(az), i))do {} while (0 );
841 n++;
842 }
843 }
844 az->ncodecs = n;
845 if (az->ncodecs < 1) {
846 printf("%s: no HD-Audio codecs\n", XNAME(az)((az)->dev.dv_xname));
847 return -1;
848 }
849 az->codecs = mallocarray(az->ncodecs, sizeof(codec_t), M_DEVBUF2,
850 M_NOWAIT0x0002 | M_ZERO0x0008);
851 if (az->codecs == NULL((void *)0)) {
852 printf("%s: can't allocate memory for codecs\n", XNAME(az)((az)->dev.dv_xname));
853 return ENOMEM12;
854 }
855 for (i = 0, n = 0; n < az->ncodecs; i++) {
856 if ((statests >> i) & 1) {
857 az->codecs[n].address = i;
858 az->codecs[n++].az = az;
859 }
860 }
861
862 /* determine CORB size */
863 az->corbsize = AZ_READ_1(az, CORBSIZE)(((az)->iot)->read_1(((az)->ioh), (0x04e)));
864 cap = az->corbsize & HDA_CORBSIZE_CORBSZCAP_MASK0xf0;
865 az->corbsize &= ~HDA_CORBSIZE_CORBSIZE_MASK0x03;
866 if (cap & HDA_CORBSIZE_CORBSZCAP_2560x40) {
867 az->corb_entries = 256;
868 az->corbsize |= HDA_CORBSIZE_CORBSIZE_2560x02;
869 } else if (cap & HDA_CORBSIZE_CORBSZCAP_160x20) {
870 az->corb_entries = 16;
871 az->corbsize |= HDA_CORBSIZE_CORBSIZE_160x01;
872 } else if (cap & HDA_CORBSIZE_CORBSZCAP_20x10) {
873 az->corb_entries = 2;
874 az->corbsize |= HDA_CORBSIZE_CORBSIZE_20x00;
875 } else {
876 printf("%s: invalid CORBSZCAP: 0x%2x\n", XNAME(az)((az)->dev.dv_xname), cap);
877 return(-1);
878 }
879
880 /* determine RIRB size */
881 az->rirbsize = AZ_READ_1(az, RIRBSIZE)(((az)->iot)->read_1(((az)->ioh), (0x05e)));
882 cap = az->rirbsize & HDA_RIRBSIZE_RIRBSZCAP_MASK0xf0;
883 az->rirbsize &= ~HDA_RIRBSIZE_RIRBSIZE_MASK0x03;
884 if (cap & HDA_RIRBSIZE_RIRBSZCAP_2560x40) {
885 az->rirb_entries = 256;
886 az->rirbsize |= HDA_RIRBSIZE_RIRBSIZE_2560x02;
887 } else if (cap & HDA_RIRBSIZE_RIRBSZCAP_160x20) {
888 az->rirb_entries = 16;
889 az->rirbsize |= HDA_RIRBSIZE_RIRBSIZE_160x01;
890 } else if (cap & HDA_RIRBSIZE_RIRBSZCAP_20x10) {
891 az->rirb_entries = 2;
892 az->rirbsize |= HDA_RIRBSIZE_RIRBSIZE_20x00;
893 } else {
894 printf("%s: invalid RIRBSZCAP: 0x%2x\n", XNAME(az)((az)->dev.dv_xname), cap);
895 return(-1);
896 }
897
898 return(0);
899}
900
901int
902azalia_init(azalia_t *az, int resuming)
903{
904 int err;
905
906 err = azalia_reset(az);
907 if (err)
908 return(err);
909
910 if (!resuming) {
911 err = azalia_get_ctrlr_caps(az);
912 if (err)
913 return(err);
914 }
915
916 /* clear interrupt status */
917 AZ_WRITE_2(az, STATESTS, HDA_STATESTS_SDIWAKE)(((az)->iot)->write_2(((az)->ioh), (0x00e), (0x7fff)
))
;
918 AZ_WRITE_1(az, RIRBSTS, HDA_RIRBSTS_RINTFL | HDA_RIRBSTS_RIRBOIS)(((az)->iot)->write_1(((az)->ioh), (0x05d), (0x01 | 0x04
)))
;
919 AZ_WRITE_4(az, INTSTS, HDA_INTSTS_CIS | HDA_INTSTS_GIS)(((az)->iot)->write_4(((az)->ioh), (0x024), (0x40000000
| 0x80000000)))
;
920 AZ_WRITE_4(az, DPLBASE, 0)(((az)->iot)->write_4(((az)->ioh), (0x070), (0)));
921 AZ_WRITE_4(az, DPUBASE, 0)(((az)->iot)->write_4(((az)->ioh), (0x074), (0)));
922
923 /* 4.4.1 Command Outbound Ring Buffer */
924 err = azalia_init_corb(az, resuming);
925 if (err)
926 return(err);
927
928 /* 4.4.2 Response Inbound Ring Buffer */
929 err = azalia_init_rirb(az, resuming);
930 if (err)
931 return(err);
932
933 AZ_WRITE_4(az, INTCTL,(((az)->iot)->write_4(((az)->ioh), (0x020), ((((az)->
iot)->read_4(((az)->ioh), (0x020))) | 0x40000000 | 0x80000000
)))
934 AZ_READ_4(az, INTCTL) | HDA_INTCTL_CIE | HDA_INTCTL_GIE)(((az)->iot)->write_4(((az)->ioh), (0x020), ((((az)->
iot)->read_4(((az)->ioh), (0x020))) | 0x40000000 | 0x80000000
)))
;
935
936 return(0);
937}
938
939int
940azalia_init_codecs(azalia_t *az)
941{
942 codec_t *codec;
943 int c, i;
944
945 c = 0;
946 for (i = 0; i < az->ncodecs; i++) {
947 if (!azalia_codec_init(&az->codecs[i]))
948 c++;
949 }
950 if (c == 0) {
951 printf("%s: No codecs found\n", XNAME(az)((az)->dev.dv_xname));
952 return(1);
953 }
954
955 /* Use the first codec capable of analog I/O. If there are none,
956 * use the first codec capable of digital I/O. Skip HDMI codecs.
957 */
958 c = -1;
959 for (i = 0; i < az->ncodecs; i++) {
960 codec = &az->codecs[i];
961 if ((codec->audiofunc < 0) ||
962 (codec->codec_type == AZ_CODEC_TYPE_HDMI2))
963 continue;
964 if (codec->codec_type == AZ_CODEC_TYPE_DIGITAL1) {
965 if (c < 0)
966 c = i;
967 } else {
968 c = i;
969 break;
970 }
971 }
972 az->codecno = c;
973 if (az->codecno < 0) {
974 printf("%s: no supported codecs\n", XNAME(az)((az)->dev.dv_xname));
975 return(1);
976 }
977
978 printf("%s: codecs: ", XNAME(az)((az)->dev.dv_xname));
979 for (i = 0; i < az->ncodecs; i++) {
980 azalia_print_codec(&az->codecs[i]);
981 if (i < az->ncodecs - 1)
982 printf(", ");
983 }
984 if (az->ncodecs > 1) {
985 printf(", using ");
986 azalia_print_codec(&az->codecs[az->codecno]);
987 }
988 printf("\n");
989
990 /* All codecs with audio are enabled, but only one will be used. */
991 for (i = 0; i < az->ncodecs; i++) {
992 codec = &az->codecs[i];
993 if (i != az->codecno) {
994 if (codec->audiofunc < 0)
995 continue;
996 azalia_comresp(codec, codec->audiofunc,
997 CORB_SET_POWER_STATE0x705, CORB_PS_D30x3, NULL((void *)0));
998 DELAY(100)(*delay_func)(100);
999 azalia_codec_delete(codec);
1000 }
1001 }
1002
1003 /* Enable unsolicited responses now that az->codecno is set. */
1004 AZ_WRITE_4(az, GCTL, AZ_READ_4(az, GCTL) | HDA_GCTL_UNSOL)(((az)->iot)->write_4(((az)->ioh), (0x008), ((((az)->
iot)->read_4(((az)->ioh), (0x008))) | 0x00000100)))
;
1005
1006 return(0);
1007}
1008
1009int
1010azalia_init_streams(azalia_t *az)
1011{
1012 int err;
1013
1014 /* Use stream#1 and #2. Don't use stream#0. */
1015 err = azalia_stream_init(&az->pstream, az, az->nistreams + 0,
1016 1, AUMODE_PLAY0x01);
1017 if (err)
1018 return(err);
1019 err = azalia_stream_init(&az->rstream, az, 0, 2, AUMODE_RECORD0x02);
1020 if (err)
1021 return(err);
1022
1023 return(0);
1024}
1025
1026int
1027azalia_halt_corb(azalia_t *az)
1028{
1029 uint8_t corbctl;
1030 codec_t *codec;
1031 int i;
1032
1033 corbctl = AZ_READ_1(az, CORBCTL)(((az)->iot)->read_1(((az)->ioh), (0x04c)));
1034 if (corbctl & HDA_CORBCTL_CORBRUN0x02) { /* running? */
1035 /* power off all codecs */
1036 for (i = 0; i < az->ncodecs; i++) {
1037 codec = &az->codecs[i];
1038 if (codec->audiofunc < 0)
1039 continue;
1040 azalia_comresp(codec, codec->audiofunc,
1041 CORB_SET_POWER_STATE0x705, CORB_PS_D30x3, NULL((void *)0));
1042 }
1043
1044 AZ_WRITE_1(az, CORBCTL, corbctl & ~HDA_CORBCTL_CORBRUN)(((az)->iot)->write_1(((az)->ioh), (0x04c), (corbctl
& ~0x02)))
;
1045 for (i = 5000; i > 0; i--) {
1046 DELAY(10)(*delay_func)(10);
1047 corbctl = AZ_READ_1(az, CORBCTL)(((az)->iot)->read_1(((az)->ioh), (0x04c)));
1048 if ((corbctl & HDA_CORBCTL_CORBRUN0x02) == 0)
1049 break;
1050 }
1051 if (i == 0) {
1052 DPRINTF(("%s: CORB is running\n", XNAME(az)))do {} while (0 );
1053 return EBUSY16;
1054 }
1055 }
1056 return(0);
1057}
1058
1059int
1060azalia_init_corb(azalia_t *az, int resuming)
1061{
1062 int err, i;
1063 uint16_t corbrp, corbwp;
1064 uint8_t corbctl;
1065
1066 err = azalia_halt_corb(az);
1067 if (err)
1068 return(err);
1069
1070 if (!resuming) {
1071 err = azalia_alloc_dmamem(az,
1072 az->corb_entries * sizeof(corb_entry_t), 128,
1073 &az->corb_dma);
1074 if (err) {
1075 printf("%s: can't allocate CORB buffer\n", XNAME(az)((az)->dev.dv_xname));
1076 return(err);
1077 }
1078 DPRINTF(("%s: CORB allocation succeeded.\n", __func__))do {} while (0 );
1079 }
1080 timeout_set(&az->unsol_to, azalia_rirb_kick_unsol_events, az);
1081
1082 AZ_WRITE_4(az, CORBLBASE, (uint32_t)AZALIA_DMA_DMAADDR(&az->corb_dma))(((az)->iot)->write_4(((az)->ioh), (0x040), ((uint32_t
)((&az->corb_dma)->map->dm_segs[0].ds_addr))))
;
1083 AZ_WRITE_4(az, CORBUBASE, PTR_UPPER32(AZALIA_DMA_DMAADDR(&az->corb_dma)))(((az)->iot)->write_4(((az)->ioh), (0x044), (((uint64_t
)(((&az->corb_dma)->map->dm_segs[0].ds_addr)) >>
32))))
;
1084 AZ_WRITE_1(az, CORBSIZE, az->corbsize)(((az)->iot)->write_1(((az)->ioh), (0x04e), (az->
corbsize)))
;
1085
1086 /* reset CORBRP */
1087 corbrp = AZ_READ_2(az, CORBRP)(((az)->iot)->read_2(((az)->ioh), (0x04a)));
1088 AZ_WRITE_2(az, CORBRP, corbrp | HDA_CORBRP_CORBRPRST)(((az)->iot)->write_2(((az)->ioh), (0x04a), (corbrp |
0x8000)))
;
1089 AZ_WRITE_2(az, CORBRP, corbrp & ~HDA_CORBRP_CORBRPRST)(((az)->iot)->write_2(((az)->ioh), (0x04a), (corbrp &
~0x8000)))
;
1090 for (i = 5000; i > 0; i--) {
1091 DELAY(10)(*delay_func)(10);
1092 corbrp = AZ_READ_2(az, CORBRP)(((az)->iot)->read_2(((az)->ioh), (0x04a)));
1093 if ((corbrp & HDA_CORBRP_CORBRPRST0x8000) == 0)
1094 break;
1095 }
1096 if (i == 0) {
1097 DPRINTF(("%s: CORBRP reset failure\n", XNAME(az)))do {} while (0 );
1098 return -1;
1099 }
1100 DPRINTF(("%s: CORBWP=%d; size=%d\n", __func__,do {} while (0 )
1101 AZ_READ_2(az, CORBRP) & HDA_CORBRP_CORBRP, az->corb_entries))do {} while (0 );
1102
1103 /* clear CORBWP */
1104 corbwp = AZ_READ_2(az, CORBWP)(((az)->iot)->read_2(((az)->ioh), (0x048)));
1105 AZ_WRITE_2(az, CORBWP, corbwp & ~HDA_CORBWP_CORBWP)(((az)->iot)->write_2(((az)->ioh), (0x048), (corbwp &
~0x00ff)))
;
1106
1107 /* Run! */
1108 corbctl = AZ_READ_1(az, CORBCTL)(((az)->iot)->read_1(((az)->ioh), (0x04c)));
1109 AZ_WRITE_1(az, CORBCTL, corbctl | HDA_CORBCTL_CORBRUN)(((az)->iot)->write_1(((az)->ioh), (0x04c), (corbctl
| 0x02)))
;
1110 return 0;
1111}
1112
1113int
1114azalia_halt_rirb(azalia_t *az)
1115{
1116 int i;
1117 uint8_t rirbctl;
1118
1119 rirbctl = AZ_READ_1(az, RIRBCTL)(((az)->iot)->read_1(((az)->ioh), (0x05c)));
1120 if (rirbctl & HDA_RIRBCTL_RIRBDMAEN0x02) { /* running? */
1121 AZ_WRITE_1(az, RIRBCTL, rirbctl & ~HDA_RIRBCTL_RIRBDMAEN)(((az)->iot)->write_1(((az)->ioh), (0x05c), (rirbctl
& ~0x02)))
;
1122 for (i = 5000; i > 0; i--) {
1123 DELAY(10)(*delay_func)(10);
1124 rirbctl = AZ_READ_1(az, RIRBCTL)(((az)->iot)->read_1(((az)->ioh), (0x05c)));
1125 if ((rirbctl & HDA_RIRBCTL_RIRBDMAEN0x02) == 0)
1126 break;
1127 }
1128 if (i == 0) {
1129 DPRINTF(("%s: RIRB is running\n", XNAME(az)))do {} while (0 );
1130 return(EBUSY16);
1131 }
1132 }
1133 return(0);
1134}
1135
1136int
1137azalia_init_rirb(azalia_t *az, int resuming)
1138{
1139 int err, i;
1140 uint16_t rirbwp;
1141 uint8_t rirbctl;
1142
1143 err = azalia_halt_rirb(az);
1144 if (err)
1145 return(err);
1146
1147 if (!resuming) {
1148 err = azalia_alloc_dmamem(az,
1149 az->rirb_entries * sizeof(rirb_entry_t), 128,
1150 &az->rirb_dma);
1151 if (err) {
1152 printf("%s: can't allocate RIRB buffer\n", XNAME(az)((az)->dev.dv_xname));
1153 return err;
1154 }
1155 DPRINTF(("%s: RIRB allocation succeeded.\n", __func__))do {} while (0 );
1156
1157 /* setup the unsolicited response queue */
1158 az->unsolq = malloc(sizeof(rirb_entry_t) * UNSOLQ_SIZE256,
1159 M_DEVBUF2, M_NOWAIT0x0002 | M_ZERO0x0008);
1160 if (az->unsolq == NULL((void *)0)) {
1161 DPRINTF(("%s: can't allocate unsolicited response queue.\n",do {} while (0 )
1162 XNAME(az)))do {} while (0 );
1163 azalia_free_dmamem(az, &az->rirb_dma);
1164 return ENOMEM12;
1165 }
1166 }
1167 AZ_WRITE_4(az, RIRBLBASE, (uint32_t)AZALIA_DMA_DMAADDR(&az->rirb_dma))(((az)->iot)->write_4(((az)->ioh), (0x050), ((uint32_t
)((&az->rirb_dma)->map->dm_segs[0].ds_addr))))
;
1168 AZ_WRITE_4(az, RIRBUBASE, PTR_UPPER32(AZALIA_DMA_DMAADDR(&az->rirb_dma)))(((az)->iot)->write_4(((az)->ioh), (0x054), (((uint64_t
)(((&az->rirb_dma)->map->dm_segs[0].ds_addr)) >>
32))))
;
1169 AZ_WRITE_1(az, RIRBSIZE, az->rirbsize)(((az)->iot)->write_1(((az)->ioh), (0x05e), (az->
rirbsize)))
;
1170
1171 /* reset the write pointer */
1172 rirbwp = AZ_READ_2(az, RIRBWP)(((az)->iot)->read_2(((az)->ioh), (0x058)));
1173 AZ_WRITE_2(az, RIRBWP, rirbwp | HDA_RIRBWP_RIRBWPRST)(((az)->iot)->write_2(((az)->ioh), (0x058), (rirbwp |
0x8000)))
;
1174
1175 /* clear the read pointer */
1176 az->rirb_rp = AZ_READ_2(az, RIRBWP)(((az)->iot)->read_2(((az)->ioh), (0x058))) & HDA_RIRBWP_RIRBWP0x00ff;
1177 DPRINTF(("%s: RIRBRP=%d, size=%d\n", __func__, az->rirb_rp,do {} while (0 )
1178 az->rirb_entries))do {} while (0 );
1179
1180 az->unsolq_rp = 0;
1181 az->unsolq_wp = 0;
1182 az->unsolq_kick = 0;
1183
1184 AZ_WRITE_2(az, RINTCNT, 1)(((az)->iot)->write_2(((az)->ioh), (0x05a), (1)));
1185
1186 /* Run! */
1187 rirbctl = AZ_READ_1(az, RIRBCTL)(((az)->iot)->read_1(((az)->ioh), (0x05c)));
1188 AZ_WRITE_1(az, RIRBCTL, rirbctl |(((az)->iot)->write_1(((az)->ioh), (0x05c), (rirbctl
| 0x02 | 0x01)))
1189 HDA_RIRBCTL_RIRBDMAEN | HDA_RIRBCTL_RINTCTL)(((az)->iot)->write_1(((az)->ioh), (0x05c), (rirbctl
| 0x02 | 0x01)))
;
1190 for (i = 5000; i > 0; i--) {
1191 DELAY(10)(*delay_func)(10);
1192 rirbctl = AZ_READ_1(az, RIRBCTL)(((az)->iot)->read_1(((az)->ioh), (0x05c)));
1193 if (rirbctl & HDA_RIRBCTL_RIRBDMAEN0x02)
1194 break;
1195 }
1196 if (i == 0) {
1197 DPRINTF(("%s: RIRB is not running\n", XNAME(az)))do {} while (0 );
1198 return(EBUSY16);
1199 }
1200
1201 return (0);
1202}
1203
1204int
1205azalia_comresp(const codec_t *codec, nid_t nid, uint32_t control,
1206 uint32_t param, uint32_t* result)
1207{
1208 int err;
1209
1210 mtx_enter(&audio_lock);
1211 err = azalia_set_command(codec->az, codec->address, nid, control,
1212 param);
1213 if (err)
1214 goto exit;
1215 err = azalia_get_response(codec->az, result);
1216exit:
1217 mtx_leave(&audio_lock);
1218 return(err);
1219}
1220
1221int
1222azalia_set_command(azalia_t *az, int caddr, nid_t nid, uint32_t control,
1223 uint32_t param)
1224{
1225 corb_entry_t *corb;
1226 int wp;
1227 uint32_t verb;
1228 uint16_t corbwp;
1229
1230 if ((AZ_READ_1(az, CORBCTL)(((az)->iot)->read_1(((az)->ioh), (0x04c))) & HDA_CORBCTL_CORBRUN0x02) == 0) {
1231 printf("%s: CORB is not running.\n", XNAME(az)((az)->dev.dv_xname));
1232 return(-1);
1233 }
1234 verb = (caddr << 28) | (nid << 20) | (control << 8) | param;
1235 corbwp = AZ_READ_2(az, CORBWP)(((az)->iot)->read_2(((az)->ioh), (0x048)));
1236 wp = corbwp & HDA_CORBWP_CORBWP0x00ff;
1237 corb = (corb_entry_t*)az->corb_dma.addr;
1238 if (++wp >= az->corb_entries)
1239 wp = 0;
1240 corb[wp] = verb;
1241
1242 AZ_WRITE_2(az, CORBWP, (corbwp & ~HDA_CORBWP_CORBWP) | wp)(((az)->iot)->write_2(((az)->ioh), (0x048), ((corbwp
& ~0x00ff) | wp)))
;
1243
1244 return(0);
1245}
1246
1247int
1248azalia_get_response(azalia_t *az, uint32_t *result)
1249{
1250 const rirb_entry_t *rirb;
1251 int i;
1252 uint16_t wp;
1253
1254 if ((AZ_READ_1(az, RIRBCTL)(((az)->iot)->read_1(((az)->ioh), (0x05c))) & HDA_RIRBCTL_RIRBDMAEN0x02) == 0) {
1255 printf("%s: RIRB is not running.\n", XNAME(az)((az)->dev.dv_xname));
1256 return(-1);
1257 }
1258
1259 rirb = (rirb_entry_t*)az->rirb_dma.addr;
1260 i = 5000;
1261 for (;;) {
1262 while (i > 0) {
1263 wp = AZ_READ_2(az, RIRBWP)(((az)->iot)->read_2(((az)->ioh), (0x058))) & HDA_RIRBWP_RIRBWP0x00ff;
1264 if (az->rirb_rp != wp)
1265 break;
1266 DELAY(10)(*delay_func)(10);
1267 i--;
1268 }
1269 if (i == 0) {
1270 DPRINTF(("%s: RIRB time out\n", XNAME(az)))do {} while (0 );
1271 return(ETIMEDOUT60);
1272 }
1273 if (++az->rirb_rp >= az->rirb_entries)
1274 az->rirb_rp = 0;
1275 if (rirb[az->rirb_rp].resp_ex & RIRB_RESP_UNSOL(1 << 4)) {
1276 az->unsolq[az->unsolq_wp].resp = rirb[az->rirb_rp].resp;
1277 az->unsolq[az->unsolq_wp++].resp_ex = rirb[az->rirb_rp].resp_ex;
1278 az->unsolq_wp %= UNSOLQ_SIZE256;
1279 } else
1280 break;
1281 }
1282 if (result != NULL((void *)0))
1283 *result = rirb[az->rirb_rp].resp;
1284
1285 return(0);
1286}
1287
1288void
1289azalia_rirb_kick_unsol_events(void *v)
1290{
1291 azalia_t *az = v;
1292 int addr, tag;
1293
1294 if (az->unsolq_kick)
1295 return;
1296 az->unsolq_kick = 1;
1297 while (az->unsolq_rp != az->unsolq_wp) {
1298 addr = RIRB_RESP_CODEC(az->unsolq[az->unsolq_rp].resp_ex)((az->unsolq[az->unsolq_rp].resp_ex) & 0xf);
1299 tag = RIRB_UNSOL_TAG(az->unsolq[az->unsolq_rp].resp)((az->unsolq[az->unsolq_rp].resp) >> 26);
1300 DPRINTF(("%s: codec address=%d tag=%d\n", __func__, addr, tag))do {} while (0 );
1301
1302 az->unsolq_rp++;
1303 az->unsolq_rp %= UNSOLQ_SIZE256;
1304
1305 /* We only care about events on the using codec. */
1306 if (az->codecs[az->codecno].address == addr)
1307 azalia_unsol_event(&az->codecs[az->codecno], tag);
1308 }
1309 az->unsolq_kick = 0;
1310}
1311
1312void
1313azalia_rirb_intr(azalia_t *az)
1314{
1315 const rirb_entry_t *rirb;
1316 uint16_t wp;
1317 uint8_t rirbsts;
1318
1319 rirbsts = AZ_READ_1(az, RIRBSTS)(((az)->iot)->read_1(((az)->ioh), (0x05d)));
1320
1321 wp = AZ_READ_2(az, RIRBWP)(((az)->iot)->read_2(((az)->ioh), (0x058))) & HDA_RIRBWP_RIRBWP0x00ff;
1322 rirb = (rirb_entry_t*)az->rirb_dma.addr;
1323 while (az->rirb_rp != wp) {
1324 if (++az->rirb_rp >= az->rirb_entries)
1325 az->rirb_rp = 0;
1326 if (rirb[az->rirb_rp].resp_ex & RIRB_RESP_UNSOL(1 << 4)) {
1327 az->unsolq[az->unsolq_wp].resp = rirb[az->rirb_rp].resp;
1328 az->unsolq[az->unsolq_wp++].resp_ex = rirb[az->rirb_rp].resp_ex;
1329 az->unsolq_wp %= UNSOLQ_SIZE256;
1330 } else {
1331 DPRINTF(("%s: dropped solicited response\n", __func__))do {} while (0 );
1332 }
1333 }
1334 timeout_add_msec(&az->unsol_to, 1);
1335
1336 AZ_WRITE_1(az, RIRBSTS,(((az)->iot)->write_1(((az)->ioh), (0x05d), (rirbsts
| 0x04 | 0x01)))
1337 rirbsts | HDA_RIRBSTS_RIRBOIS | HDA_RIRBSTS_RINTFL)(((az)->iot)->write_1(((az)->ioh), (0x05d), (rirbsts
| 0x04 | 0x01)))
;
1338}
1339
1340int
1341azalia_alloc_dmamem(azalia_t *az, size_t size, size_t align, azalia_dma_t *d)
1342{
1343 int err;
1344 int nsegs;
1345
1346 d->size = size;
1347 err = bus_dmamem_alloc(az->dmat, size, align, 0, d->segments, 1,(*(az->dmat)->_dmamem_alloc)((az->dmat), (size), (align
), (0), (d->segments), (1), (&nsegs), (0x0001))
1348 &nsegs, BUS_DMA_NOWAIT)(*(az->dmat)->_dmamem_alloc)((az->dmat), (size), (align
), (0), (d->segments), (1), (&nsegs), (0x0001))
;
1349 if (err)
1350 return err;
1351 if (nsegs != 1)
1352 goto free;
1353 err = bus_dmamem_map(az->dmat, d->segments, 1, size,(*(az->dmat)->_dmamem_map)((az->dmat), (d->segments
), (1), (size), (&d->addr), (0x0001 | 0x0004))
1354 &d->addr, BUS_DMA_NOWAIT | BUS_DMA_COHERENT)(*(az->dmat)->_dmamem_map)((az->dmat), (d->segments
), (1), (size), (&d->addr), (0x0001 | 0x0004))
;
1355 if (err)
1356 goto free;
1357 err = bus_dmamap_create(az->dmat, size, 1, size, 0,(*(az->dmat)->_dmamap_create)((az->dmat), (size), (1
), (size), (0), (0x0001), (&d->map))
1358 BUS_DMA_NOWAIT, &d->map)(*(az->dmat)->_dmamap_create)((az->dmat), (size), (1
), (size), (0), (0x0001), (&d->map))
;
1359 if (err)
1360 goto unmap;
1361 err = bus_dmamap_load(az->dmat, d->map, d->addr, size,(*(az->dmat)->_dmamap_load)((az->dmat), (d->map),
(d->addr), (size), (((void *)0)), (0x0001))
1362 NULL, BUS_DMA_NOWAIT)(*(az->dmat)->_dmamap_load)((az->dmat), (d->map),
(d->addr), (size), (((void *)0)), (0x0001))
;
1363 if (err)
1364 goto destroy;
1365
1366 if (!az->ok64 && PTR_UPPER32(AZALIA_DMA_DMAADDR(d))((uint64_t)(((d)->map->dm_segs[0].ds_addr)) >> 32
)
!= 0) {
1367 azalia_free_dmamem(az, d);
1368 return -1;
1369 }
1370 return 0;
1371
1372destroy:
1373 bus_dmamap_destroy(az->dmat, d->map)(*(az->dmat)->_dmamap_destroy)((az->dmat), (d->map
))
;
1374unmap:
1375 bus_dmamem_unmap(az->dmat, d->addr, size)(*(az->dmat)->_dmamem_unmap)((az->dmat), (d->addr
), (size))
;
1376free:
1377 bus_dmamem_free(az->dmat, d->segments, 1)(*(az->dmat)->_dmamem_free)((az->dmat), (d->segments
), (1))
;
1378 d->addr = NULL((void *)0);
1379 return err;
1380}
1381
1382void
1383azalia_free_dmamem(const azalia_t *az, azalia_dma_t* d)
1384{
1385 if (d->addr == NULL((void *)0))
1386 return;
1387 bus_dmamap_unload(az->dmat, d->map)(*(az->dmat)->_dmamap_unload)((az->dmat), (d->map
))
;
1388 bus_dmamap_destroy(az->dmat, d->map)(*(az->dmat)->_dmamap_destroy)((az->dmat), (d->map
))
;
1389 bus_dmamem_unmap(az->dmat, d->addr, d->size)(*(az->dmat)->_dmamem_unmap)((az->dmat), (d->addr
), (d->size))
;
1390 bus_dmamem_free(az->dmat, d->segments, 1)(*(az->dmat)->_dmamem_free)((az->dmat), (d->segments
), (1))
;
1391 d->addr = NULL((void *)0);
1392}
1393
1394int
1395azalia_suspend(azalia_t *az)
1396{
1397 int err;
1398
1399 if (az->detached)
1400 return 0;
1401
1402 /* disable unsolicited responses */
1403 AZ_WRITE_4(az, GCTL, AZ_READ_4(az, GCTL) & ~HDA_GCTL_UNSOL)(((az)->iot)->write_4(((az)->ioh), (0x008), ((((az)->
iot)->read_4(((az)->ioh), (0x008))) & ~0x00000100))
)
;
1404
1405 timeout_del(&az->unsol_to);
1406
1407 /* azalia_halt_{corb,rirb}() only fail if the {CORB,RIRB} can't
1408 * be stopped and azalia_init_{corb,rirb}(), which starts the
1409 * {CORB,RIRB}, first calls azalia_halt_{corb,rirb}(). If halt
1410 * fails, don't try to restart.
1411 */
1412 err = azalia_halt_corb(az);
1413 if (err)
1414 goto corb_fail;
1415
1416 err = azalia_halt_rirb(az);
1417 if (err)
1418 goto rirb_fail;
1419
1420 /* stop interrupts and clear status registers */
1421 AZ_WRITE_4(az, INTCTL, 0)(((az)->iot)->write_4(((az)->ioh), (0x020), (0)));
1422 AZ_WRITE_4(az, INTSTS, HDA_INTSTS_CIS | HDA_INTSTS_GIS)(((az)->iot)->write_4(((az)->ioh), (0x024), (0x40000000
| 0x80000000)))
;
1423 AZ_WRITE_2(az, STATESTS, HDA_STATESTS_SDIWAKE)(((az)->iot)->write_2(((az)->ioh), (0x00e), (0x7fff)
))
;
1424 AZ_WRITE_1(az, RIRBSTS, HDA_RIRBSTS_RINTFL | HDA_RIRBSTS_RIRBOIS)(((az)->iot)->write_1(((az)->ioh), (0x05d), (0x01 | 0x04
)))
;
1425
1426 return 0;
1427
1428rirb_fail:
1429 azalia_init_corb(az, 1);
1430corb_fail:
1431 AZ_WRITE_4(az, GCTL, AZ_READ_4(az, GCTL) | HDA_GCTL_UNSOL)(((az)->iot)->write_4(((az)->ioh), (0x008), ((((az)->
iot)->read_4(((az)->ioh), (0x008))) | 0x00000100)))
;
1432
1433 return err;
1434}
1435
1436int
1437azalia_resume_codec(codec_t *this)
1438{
1439 widget_t *w;
1440 uint32_t result;
1441 int i, err;
1442
1443 err = azalia_comresp(this, this->audiofunc, CORB_SET_POWER_STATE0x705,
1444 CORB_PS_D00x0, &result);
1445 if (err) {
1446 DPRINTF(("%s: power audio func error: result=0x%8.8x\n",do {} while (0 )
1447 __func__, result))do {} while (0 );
1448 }
1449 DELAY(100)(*delay_func)(100);
1450
1451 if (this->qrks & AZ_QRK_DOLBY_ATMOS0x02000000)
1452 azalia_codec_init_dolby_atmos(this);
1453
1454 FOR_EACH_WIDGET(this, i)for (i = (this)->wstart; i < (this)->wend; i++) {
1455 w = &this->w[i];
1456 if (w->widgetcap & COP_AWCAP_POWER0x400) {
1457 azalia_comresp(this, w->nid, CORB_SET_POWER_STATE0x705,
1458 CORB_PS_D00x0, &result);
1459 DELAY(100)(*delay_func)(100);
1460 }
1461 if (w->type == COP_AWTYPE_PIN_COMPLEX0x4)
1462 azalia_widget_init_pin(w, this);
1463 if (this->qrks & AZ_QRK_WID_MASK0x00fff000)
1464 azalia_codec_widget_quirks(this, w->nid);
1465 }
1466
1467 if (this->qrks & AZ_QRK_GPIO_MASK0x00000fff) {
1468 err = azalia_codec_gpio_quirks(this);
1469 if (err)
1470 return err;
1471 }
1472
1473 return(0);
1474}
1475
1476int
1477azalia_resume(azalia_t *az)
1478{
1479 int err;
1480
1481 if (az->detached)
1482 return 0;
1483
1484 azalia_configure_pci(az);
1485
1486 /* is this necessary? */
1487 pci_conf_write(az->pc, az->tag, PCI_SUBSYS_ID_REG0x2c, az->subid);
1488
1489 err = azalia_init(az, 1);
1490 if (err)
1491 return err;
1492
1493 /* enable unsolicited responses on the controller */
1494 AZ_WRITE_4(az, GCTL, AZ_READ_4(az, GCTL) | HDA_GCTL_UNSOL)(((az)->iot)->write_4(((az)->ioh), (0x008), ((((az)->
iot)->read_4(((az)->ioh), (0x008))) | 0x00000100)))
;
1495
1496 err = azalia_resume_codec(&az->codecs[az->codecno]);
1497 if (err)
1498 return err;
1499
1500 err = azalia_codec_enable_unsol(&az->codecs[az->codecno]);
1501 if (err)
1502 return err;
1503
1504 return 0;
1505}
1506
1507/* ================================================================
1508 * HDA codec functions
1509 * ================================================================ */
1510
1511int
1512azalia_codec_init(codec_t *this)
1513{
1514 widget_t *w;
1515 uint32_t rev, id, result;
1516 int err, addr, n, i, nspdif, nhdmi;
1517
1518 addr = this->address;
1519 /* codec vendor/device/revision */
1520 err = azalia_comresp(this, CORB_NID_ROOT0, CORB_GET_PARAMETER0xf00,
1521 COP_REVISION_ID0x02, &rev);
1522 if (err)
1523 return err;
1524 err = azalia_comresp(this, CORB_NID_ROOT0, CORB_GET_PARAMETER0xf00,
1525 COP_VENDOR_ID0x00, &id);
1526 if (err)
1527 return err;
1528 this->vid = id;
1529 this->subid = this->az->subid;
1530 azalia_codec_init_vtbl(this);
1531 DPRINTF(("%s: codec[%d] vid 0x%8.8x, subid 0x%8.8x, rev. %u.%u,",do {} while (0 )
1532 XNAME(this->az), addr, this->vid, this->subid,do {} while (0 )
1533 COP_RID_REVISION(rev), COP_RID_STEPPING(rev)))do {} while (0 );
1534 DPRINTF((" HDA version %u.%u\n",do {} while (0 )
1535 COP_RID_MAJ(rev), COP_RID_MIN(rev)))do {} while (0 );
1536
1537 /* identify function nodes */
1538 err = azalia_comresp(this, CORB_NID_ROOT0, CORB_GET_PARAMETER0xf00,
1539 COP_SUBORDINATE_NODE_COUNT0x04, &result);
1540 if (err)
1541 return err;
1542 this->nfunctions = COP_NSUBNODES(result)(result & 0x000000ff);
1543 if (COP_NSUBNODES(result)(result & 0x000000ff) <= 0) {
1544 DPRINTF(("%s: codec[%d]: No function groups\n",do {} while (0 )
1545 XNAME(this->az), addr))do {} while (0 );
1546 return -1;
1547 }
1548 /* iterate function nodes and find an audio function */
1549 n = COP_START_NID(result)((result & 0x00ff0000) >> 16);
1550 DPRINTF(("%s: nidstart=%d #functions=%d\n",do {} while (0 )
1551 XNAME(this->az), n, this->nfunctions))do {} while (0 );
1552 this->audiofunc = -1;
1553 for (i = 0; i < this->nfunctions; i++) {
1554 err = azalia_comresp(this, n + i, CORB_GET_PARAMETER0xf00,
1555 COP_FUNCTION_GROUP_TYPE0x05, &result);
1556 if (err)
1557 continue;
1558 DPRINTF(("%s: FTYPE result = 0x%8.8x\n", __func__, result))do {} while (0 );
1559 if (COP_FTYPE(result)(result & 0x000000ff) == COP_FTYPE_AUDIO0x01) {
1560 this->audiofunc = n + i;
1561 break; /* XXX multiple audio functions? */
1562 }
1563 }
1564 if (this->audiofunc < 0) {
1565 DPRINTF(("%s: codec[%d]: No audio function groups\n",do {} while (0 )
1566 XNAME(this->az), addr))do {} while (0 );
1567 return -1;
1568 }
1569
1570 /* power the audio function */
1571 azalia_comresp(this, this->audiofunc, CORB_SET_POWER_STATE0x705,
1572 CORB_PS_D00x0, &result);
1573 DELAY(100)(*delay_func)(100);
1574
1575 /* check widgets in the audio function */
1576 err = azalia_comresp(this, this->audiofunc, CORB_GET_PARAMETER0xf00,
1577 COP_SUBORDINATE_NODE_COUNT0x04, &result);
1578 if (err)
1579 return err;
1580 DPRINTF(("%s: There are %d widgets in the audio function.\n",do {} while (0 )
1581 __func__, COP_NSUBNODES(result)))do {} while (0 );
1582 this->wstart = COP_START_NID(result)((result & 0x00ff0000) >> 16);
1583 if (this->wstart < 2) {
1584 printf("%s: invalid node structure\n", XNAME(this->az)((this->az)->dev.dv_xname));
1585 return -1;
1586 }
1587 this->wend = this->wstart + COP_NSUBNODES(result)(result & 0x000000ff);
1588 this->w = mallocarray(this->wend, sizeof(widget_t), M_DEVBUF2,
1589 M_NOWAIT0x0002 | M_ZERO0x0008);
1590 if (this->w == NULL((void *)0)) {
1591 printf("%s: out of memory\n", XNAME(this->az)((this->az)->dev.dv_xname));
1592 return ENOMEM12;
1593 }
1594
1595 if (this->qrks & AZ_QRK_DOLBY_ATMOS0x02000000)
1596 azalia_codec_init_dolby_atmos(this);
1597
1598 /* query the base parameters */
1599 azalia_comresp(this, this->audiofunc, CORB_GET_PARAMETER0xf00,
1600 COP_STREAM_FORMATS0x0b, &result);
1601 this->w[this->audiofunc].d.audio.encodings = result;
1602 azalia_comresp(this, this->audiofunc, CORB_GET_PARAMETER0xf00,
1603 COP_PCM0x0a, &result);
1604 this->w[this->audiofunc].d.audio.bits_rates = result;
1605 azalia_comresp(this, this->audiofunc, CORB_GET_PARAMETER0xf00,
1606 COP_INPUT_AMPCAP0x0d, &result);
1607 this->w[this->audiofunc].inamp_cap = result;
1608 azalia_comresp(this, this->audiofunc, CORB_GET_PARAMETER0xf00,
1609 COP_OUTPUT_AMPCAP0x12, &result);
1610 this->w[this->audiofunc].outamp_cap = result;
1611
1612 azalia_codec_print_audiofunc(this);
1613
1614 strlcpy(this->w[CORB_NID_ROOT0].name, "root",
1615 sizeof(this->w[CORB_NID_ROOT0].name));
1616 strlcpy(this->w[this->audiofunc].name, "hdaudio",
1617 sizeof(this->w[this->audiofunc].name));
1618 this->w[this->audiofunc].enable = 1;
1619
1620 FOR_EACH_WIDGET(this, i)for (i = (this)->wstart; i < (this)->wend; i++) {
1621 w = &this->w[i];
1622 err = azalia_widget_init(w, this, i);
1623 if (err)
1624 return err;
1625 err = azalia_widget_init_connection(w, this);
1626 if (err)
1627 return err;
1628
1629 azalia_widget_print_widget(w, this);
1630
1631 if (this->qrks & AZ_QRK_WID_MASK0x00fff000) {
1632 azalia_codec_widget_quirks(this, i);
1633 }
1634 }
1635
1636 this->na_dacs = this->na_dacs_d = 0;
1637 this->na_adcs = this->na_adcs_d = 0;
1638 this->speaker = this->speaker2 = this->spkr_dac =
1639 this->fhp = this->fhp_dac =
1640 this->mic = this->mic_adc = -1;
1641 this->nsense_pins = 0;
1642 this->nout_jacks = 0;
1643 nspdif = nhdmi = 0;
1644 FOR_EACH_WIDGET(this, i)for (i = (this)->wstart; i < (this)->wend; i++) {
1645 w = &this->w[i];
1646
1647 if (!w->enable)
1648 continue;
1649
1650 switch (w->type) {
1651
1652 case COP_AWTYPE_AUDIO_MIXER0x2:
1653 case COP_AWTYPE_AUDIO_SELECTOR0x3:
1654 if (!azalia_widget_check_conn(this, i, 0))
1655 w->enable = 0;
1656 break;
1657
1658 case COP_AWTYPE_AUDIO_OUTPUT0x0:
1659 if ((w->widgetcap & COP_AWCAP_DIGITAL0x200) == 0) {
1660 if (this->na_dacs < HDA_MAX_CHANNELS16)
1661 this->a_dacs[this->na_dacs++] = i;
1662 } else {
1663 if (this->na_dacs_d < HDA_MAX_CHANNELS16)
1664 this->a_dacs_d[this->na_dacs_d++] = i;
1665 }
1666 break;
1667
1668 case COP_AWTYPE_AUDIO_INPUT0x1:
1669 if ((w->widgetcap & COP_AWCAP_DIGITAL0x200) == 0) {
1670 if (this->na_adcs < HDA_MAX_CHANNELS16)
1671 this->a_adcs[this->na_adcs++] = i;
1672 } else {
1673 if (this->na_adcs_d < HDA_MAX_CHANNELS16)
1674 this->a_adcs_d[this->na_adcs_d++] = i;
1675 }
1676 break;
1677
1678 case COP_AWTYPE_PIN_COMPLEX0x4:
1679 switch (CORB_CD_PORT(w->d.pin.config)((w->d.pin.config >> 30) & 0x3)) {
1680 case CORB_CD_FIXED0x2:
1681 switch (w->d.pin.device) {
1682 case CORB_CD_SPEAKER0x1:
1683 if (this->speaker == -1) {
1684 this->speaker = i;
1685 } else if (w->d.pin.association <
1686 this->w[this->speaker].d.pin.association ||
1687 (w->d.pin.association ==
1688 this->w[this->speaker].d.pin.association &&
1689 w->d.pin.sequence <
1690 this->w[this->speaker].d.pin.sequence)) {
1691 this->speaker2 = this->speaker;
1692 this->speaker = i;
1693 } else {
1694 this->speaker2 = i;
1695 }
1696 if (this->speaker == i)
1697 this->spkr_dac =
1698 azalia_codec_find_defdac(this, i, 0);
1699 break;
1700 case CORB_CD_MICIN0xa:
1701 this->mic = i;
1702 this->mic_adc =
1703 azalia_codec_find_defadc(this, i, 0);
1704 break;
1705 }
1706 break;
1707 case CORB_CD_JACK0x0:
1708 if (w->d.pin.device == CORB_CD_LINEOUT0x0)
1709 this->nout_jacks++;
1710 else if (w->d.pin.device == CORB_CD_HEADPHONE0x2 &&
1711 CORB_CD_LOC_GEO(w->d.pin.config)((w->d.pin.config >> 24) & 0xf) ==
1712 CORB_CD_FRONT0x2) {
1713 this->fhp = i;
1714 this->fhp_dac =
1715 azalia_codec_find_defdac(this, i, 0);
1716 }
1717 if (this->nsense_pins >= HDA_MAX_SENSE_PINS16 ||
1718 !(w->d.pin.cap & COP_PINCAP_PRESENCE0x00000004))
1719 break;
1720 /* check override bit */
1721 err = azalia_comresp(this, i,
1722 CORB_GET_CONFIGURATION_DEFAULT0xf1c, 0, &result);
1723 if (err)
1724 break;
1725 if (!(CORB_CD_MISC(result)((result >> 8) & 0xf) & CORB_CD_PRESENCEOV0x1)) {
1726 this->sense_pins[this->nsense_pins++] = i;
1727 }
1728 break;
1729 }
1730 if ((w->d.pin.device == CORB_CD_DIGITALOUT0x5) &&
1731 (w->d.pin.cap & COP_PINCAP_HDMI0x00000080))
1732 nhdmi++;
1733 else if (w->d.pin.device == CORB_CD_SPDIFOUT0x4 ||
1734 w->d.pin.device == CORB_CD_SPDIFIN0xc)
1735 nspdif++;
1736 break;
1737 }
1738 }
1739 this->codec_type = AZ_CODEC_TYPE_ANALOG0;
1740 if ((this->na_dacs == 0) && (this->na_adcs == 0)) {
1741 this->codec_type = AZ_CODEC_TYPE_DIGITAL1;
1742 if (nspdif == 0 && nhdmi > 0)
1743 this->codec_type = AZ_CODEC_TYPE_HDMI2;
1744 }
1745
1746 /* make sure built-in mic is connected to an adc */
1747 if (this->mic != -1 && this->mic_adc == -1) {
1748 if (azalia_codec_select_micadc(this)) {
1749 DPRINTF(("%s: could not select mic adc\n", __func__))do {} while (0 );
1750 }
1751 }
1752
1753 err = azalia_codec_sort_pins(this);
1754 if (err)
1755 return err;
1756
1757 err = azalia_codec_find_inputmixer(this);
1758 if (err)
1759 return err;
1760
1761 /* If the codec can do multichannel, select different DACs for
1762 * the multichannel jack group. Also be sure to keep track of
1763 * which DAC the front headphone is connected to.
1764 */
1765 if (this->na_dacs >= 3 && this->nopins >= 3) {
1766 err = azalia_codec_select_dacs(this);
1767 if (err)
1768 return err;
1769 }
1770
1771 err = azalia_codec_select_spkrdac(this);
1772 if (err)
1773 return err;
1774
1775 err = azalia_init_dacgroup(this);
1776 if (err)
1777 return err;
1778
1779 azalia_codec_print_groups(this);
1780
1781 err = azalia_widget_label_widgets(this);
1782 if (err)
1783 return err;
1784
1785 err = azalia_codec_construct_format(this, 0, 0);
1786 if (err)
1787 return err;
1788
1789 err = azalia_codec_init_volgroups(this);
1790 if (err)
1791 return err;
1792
1793 if (this->qrks & AZ_QRK_GPIO_MASK0x00000fff) {
1794 err = azalia_codec_gpio_quirks(this);
1795 if (err)
1796 return err;
1797 }
1798
1799 err = azalia_mixer_init(this);
1800 if (err)
1801 return err;
1802
1803 return 0;
1804}
1805
1806int
1807azalia_codec_find_inputmixer(codec_t *this)
1808{
1809 widget_t *w;
1810 int i, j;
1811
1812 this->input_mixer = -1;
1813
1814 FOR_EACH_WIDGET(this, i)for (i = (this)->wstart; i < (this)->wend; i++) {
1815 w = &this->w[i];
1816 if (w->type != COP_AWTYPE_AUDIO_MIXER0x2)
1817 continue;
1818
1819 /* can input from a pin */
1820 for (j = 0; j < this->nipins; j++) {
1821 if (azalia_codec_fnode(this, this->ipins[j].nid,
1822 w->nid, 0) != -1)
1823 break;
1824 }
1825 if (j == this->nipins)
1826 continue;
1827
1828 /* can output to a pin */
1829 for (j = 0; j < this->nopins; j++) {
1830 if (azalia_codec_fnode(this, w->nid,
1831 this->opins[j].nid, 0) != -1)
1832 break;
1833 }
1834 if (j == this->nopins)
1835 continue;
1836
1837 /* can output to an ADC */
1838 for (j = 0; j < this->na_adcs; j++) {
1839 if (azalia_codec_fnode(this, w->nid,
1840 this->a_adcs[j], 0) != -1)
1841 break;
1842 }
1843 if (j == this->na_adcs)
1844 continue;
1845
1846 this->input_mixer = i;
1847 break;
1848 }
1849 return(0);
1850}
1851
1852int
1853azalia_codec_select_micadc(codec_t *this)
1854{
1855 widget_t *w;
1856 int i, j, conv, err;
1857
1858 for (i = 0; i < this->na_adcs; i++) {
1859 if (azalia_codec_fnode(this, this->mic,
1860 this->a_adcs[i], 0) >= 0)
1861 break;
1862 }
1863 if (i >= this->na_adcs)
1864 return(-1);
1865 conv = this->a_adcs[i];
1866
1867 w = &this->w[conv];
1868 for (j = 0; j < 10; j++) {
1869 for (i = 0; i < w->nconnections; i++) {
1870 if (!azalia_widget_enabled(this, w->connections[i]))
1871 continue;
1872 if (azalia_codec_fnode(this, this->mic,
1873 w->connections[i], j + 1) >= 0) {
1874 break;
1875 }
1876 }
1877 if (i >= w->nconnections)
1878 return(-1);
1879 err = azalia_comresp(this, w->nid,
1880 CORB_SET_CONNECTION_SELECT_CONTROL0x701, i, 0);
1881 if (err)
1882 return(err);
1883 w->selected = i;
1884 if (w->connections[i] == this->mic) {
1885 this->mic_adc = conv;
1886 return(0);
1887 }
1888 w = &this->w[w->connections[i]];
1889 }
1890 return(-1);
1891}
1892
1893int
1894azalia_codec_sort_pins(codec_t *this)
1895{
1896#define MAX_PINS 16
1897 const widget_t *w;
1898 struct io_pin opins[MAX_PINS], opins_d[MAX_PINS];
1899 struct io_pin ipins[MAX_PINS], ipins_d[MAX_PINS];
1900 int nopins, nopins_d, nipins, nipins_d;
1901 int prio, loc, add, nd, conv;
1902 int i, j, k;
1903
1904 nopins = nopins_d = nipins = nipins_d = 0;
1905
1906 FOR_EACH_WIDGET(this, i)for (i = (this)->wstart; i < (this)->wend; i++) {
1907 w = &this->w[i];
1908 if (!w->enable || w->type != COP_AWTYPE_PIN_COMPLEX0x4)
1909 continue;
1910
1911 loc = 0;
1912 if (this->na_dacs >= 3 && this->nout_jacks < 3)
1913 loc = CORB_CD_LOC_GEO(w->d.pin.config)((w->d.pin.config >> 24) & 0xf);
1914
1915 prio = w->d.pin.association << 4 | w->d.pin.sequence;
1916 conv = -1;
1917
1918 /* analog out */
1919 if ((w->d.pin.cap & COP_PINCAP_OUTPUT0x00000010) &&
1920 !(w->widgetcap & COP_AWCAP_DIGITAL0x200)) {
1921 add = nd = 0;
1922 conv = azalia_codec_find_defdac(this, w->nid, 0);
1923 switch(w->d.pin.device) {
1924 /* primary - output by default */
1925 case CORB_CD_SPEAKER0x1:
1926 if (w->nid == this->speaker ||
1927 w->nid == this->speaker2)
1928 break;
1929 /* FALLTHROUGH */
1930 case CORB_CD_HEADPHONE0x2:
1931 case CORB_CD_LINEOUT0x0:
1932 add = 1;
1933 break;
1934 /* secondary - input by default */
1935 case CORB_CD_MICIN0xa:
1936 if (w->nid == this->mic)
1937 break;
1938 /* FALLTHROUGH */
1939 case CORB_CD_LINEIN0x8:
1940 add = nd = 1;
1941 break;
1942 }
1943 if (add && nopins < MAX_PINS) {
1944 opins[nopins].nid = w->nid;
1945 opins[nopins].conv = conv;
1946 prio |= (nd << 8) | (loc << 9);
1947 opins[nopins].prio = prio;
1948 nopins++;
1949 }
1950 }
1951 /* digital out */
1952 if ((w->d.pin.cap & COP_PINCAP_OUTPUT0x00000010) &&
1953 (w->widgetcap & COP_AWCAP_DIGITAL0x200)) {
1954 conv = azalia_codec_find_defdac(this, w->nid, 0);
1955 switch(w->d.pin.device) {
1956 case CORB_CD_SPDIFOUT0x4:
1957 case CORB_CD_DIGITALOUT0x5:
1958 if (nopins_d < MAX_PINS) {
1959 opins_d[nopins_d].nid = w->nid;
1960 opins_d[nopins_d].conv = conv;
1961 opins_d[nopins_d].prio = prio;
1962 nopins_d++;
1963 }
1964 break;
1965 }
1966 }
1967 /* analog in */
1968 if ((w->d.pin.cap & COP_PINCAP_INPUT0x00000020) &&
1969 !(w->widgetcap & COP_AWCAP_DIGITAL0x200)) {
1970 add = nd = 0;
1971 conv = azalia_codec_find_defadc(this, w->nid, 0);
1972 switch(w->d.pin.device) {
1973 /* primary - input by default */
1974 case CORB_CD_MICIN0xa:
1975 case CORB_CD_LINEIN0x8:
1976 add = 1;
1977 break;
1978 /* secondary - output by default */
1979 case CORB_CD_SPEAKER0x1:
1980 if (w->nid == this->speaker ||
1981 w->nid == this->speaker2)
1982 break;
1983 /* FALLTHROUGH */
1984 case CORB_CD_HEADPHONE0x2:
1985 case CORB_CD_LINEOUT0x0:
1986 add = nd = 1;
1987 break;
1988 }
1989 if (add && nipins < MAX_PINS) {
1990 ipins[nipins].nid = w->nid;
1991 ipins[nipins].prio = prio | (nd << 8);
1992 ipins[nipins].conv = conv;
1993 nipins++;
1994 }
1995 }
1996 /* digital in */
1997 if ((w->d.pin.cap & COP_PINCAP_INPUT0x00000020) &&
1998 (w->widgetcap & COP_AWCAP_DIGITAL0x200)) {
1999 conv = azalia_codec_find_defadc(this, w->nid, 0);
2000 switch(w->d.pin.device) {
2001 case CORB_CD_SPDIFIN0xc:
2002 case CORB_CD_DIGITALIN0xd:
2003 case CORB_CD_MICIN0xa:
2004 if (nipins_d < MAX_PINS) {
2005 ipins_d[nipins_d].nid = w->nid;
2006 ipins_d[nipins_d].prio = prio;
2007 ipins_d[nipins_d].conv = conv;
2008 nipins_d++;
2009 }
2010 break;
2011 }
2012 }
2013 }
2014
2015 this->opins = mallocarray(nopins, sizeof(struct io_pin), M_DEVBUF2,
2016 M_NOWAIT0x0002 | M_ZERO0x0008);
2017 if (this->opins == NULL((void *)0))
2018 return(ENOMEM12);
2019 this->nopins = 0;
2020 for (i = 0; i < nopins; i++) {
2021 for (j = 0; j < this->nopins; j++)
2022 if (this->opins[j].prio > opins[i].prio)
2023 break;
2024 for (k = this->nopins; k > j; k--)
2025 this->opins[k] = this->opins[k - 1];
2026 if (j < nopins)
2027 this->opins[j] = opins[i];
2028 this->nopins++;
2029 if (this->nopins == nopins)
2030 break;
2031 }
2032
2033 this->opins_d = mallocarray(nopins_d, sizeof(struct io_pin), M_DEVBUF2,
2034 M_NOWAIT0x0002 | M_ZERO0x0008);
2035 if (this->opins_d == NULL((void *)0))
2036 return(ENOMEM12);
2037 this->nopins_d = 0;
2038 for (i = 0; i < nopins_d; i++) {
2039 for (j = 0; j < this->nopins_d; j++)
2040 if (this->opins_d[j].prio > opins_d[i].prio)
2041 break;
2042 for (k = this->nopins_d; k > j; k--)
2043 this->opins_d[k] = this->opins_d[k - 1];
2044 if (j < nopins_d)
2045 this->opins_d[j] = opins_d[i];
2046 this->nopins_d++;
2047 if (this->nopins_d == nopins_d)
2048 break;
2049 }
2050
2051 this->ipins = mallocarray(nipins, sizeof(struct io_pin), M_DEVBUF2,
2052 M_NOWAIT0x0002 | M_ZERO0x0008);
2053 if (this->ipins == NULL((void *)0))
2054 return(ENOMEM12);
2055 this->nipins = 0;
2056 for (i = 0; i < nipins; i++) {
2057 for (j = 0; j < this->nipins; j++)
2058 if (this->ipins[j].prio > ipins[i].prio)
2059 break;
2060 for (k = this->nipins; k > j; k--)
2061 this->ipins[k] = this->ipins[k - 1];
2062 if (j < nipins)
2063 this->ipins[j] = ipins[i];
2064 this->nipins++;
2065 if (this->nipins == nipins)
2066 break;
2067 }
2068
2069 this->ipins_d = mallocarray(nipins_d, sizeof(struct io_pin), M_DEVBUF2,
2070 M_NOWAIT0x0002 | M_ZERO0x0008);
2071 if (this->ipins_d == NULL((void *)0))
2072 return(ENOMEM12);
2073 this->nipins_d = 0;
2074 for (i = 0; i < nipins_d; i++) {
2075 for (j = 0; j < this->nipins_d; j++)
2076 if (this->ipins_d[j].prio > ipins_d[i].prio)
2077 break;
2078 for (k = this->nipins_d; k > j; k--)
2079 this->ipins_d[k] = this->ipins_d[k - 1];
2080 if (j < nipins_d)
2081 this->ipins_d[j] = ipins_d[i];
2082 this->nipins_d++;
2083 if (this->nipins_d == nipins_d)
2084 break;
2085 }
2086
2087#ifdef AZALIA_DEBUG
2088 printf("%s: analog out pins:", __func__);
2089 for (i = 0; i < this->nopins; i++)
2090 printf(" 0x%2.2x->0x%2.2x", this->opins[i].nid,
2091 this->opins[i].conv);
2092 printf("\n");
2093 printf("%s: digital out pins:", __func__);
2094 for (i = 0; i < this->nopins_d; i++)
2095 printf(" 0x%2.2x->0x%2.2x", this->opins_d[i].nid,
2096 this->opins_d[i].conv);
2097 printf("\n");
2098 printf("%s: analog in pins:", __func__);
2099 for (i = 0; i < this->nipins; i++)
2100 printf(" 0x%2.2x->0x%2.2x", this->ipins[i].nid,
2101 this->ipins[i].conv);
2102 printf("\n");
2103 printf("%s: digital in pins:", __func__);
2104 for (i = 0; i < this->nipins_d; i++)
2105 printf(" 0x%2.2x->0x%2.2x", this->ipins_d[i].nid,
2106 this->ipins_d[i].conv);
2107 printf("\n");
2108#endif
2109
2110 return 0;
2111#undef MAX_PINS
2112}
2113
2114int
2115azalia_codec_select_dacs(codec_t *this)
2116{
2117 widget_t *w;
2118 nid_t *convs;
2119 int nconv, conv;
2120 int i, j, k, err;
2121
2122 convs = mallocarray(this->na_dacs, sizeof(nid_t), M_DEVBUF2,
2123 M_NOWAIT0x0002 | M_ZERO0x0008);
2124 if (convs == NULL((void *)0))
2125 return(ENOMEM12);
2126
2127 err = 0;
2128 nconv = 0;
2129 for (i = 0; i < this->nopins; i++) {
2130 w = &this->w[this->opins[i].nid];
2131
2132 conv = this->opins[i].conv;
2133 for (j = 0; j < nconv; j++) {
2134 if (conv == convs[j])
2135 break;
2136 }
2137 if (j == nconv) {
2138 convs[nconv++] = conv;
2139 if (w->nid == this->fhp)
2140 this->fhp_dac = conv;
2141 if (nconv >= this->na_dacs) {
2142 break;
2143 }
2144 } else {
2145 /* find a different dac */
2146 conv = -1;
2147 for (j = 0; j < w->nconnections; j++) {
2148 if (!azalia_widget_enabled(this,
2149 w->connections[j]))
2150 continue;
2151 conv = azalia_codec_find_defdac(this,
2152 w->connections[j], 1);
2153 if (conv == -1)
2154 continue;
2155 for (k = 0; k < nconv; k++) {
2156 if (conv == convs[k])
2157 break;
2158 }
2159 if (k == nconv)
2160 break;
2161 }
2162 if (j < w->nconnections && conv != -1) {
2163 err = azalia_comresp(this, w->nid,
2164 CORB_SET_CONNECTION_SELECT_CONTROL0x701, j, 0);
2165 if (err)
2166 break;
2167 w->selected = j;
2168 this->opins[i].conv = conv;
2169 if (w->nid == this->fhp)
2170 this->fhp_dac = conv;
2171 convs[nconv++] = conv;
2172 if (nconv >= this->na_dacs)
2173 break;
2174 }
2175 }
2176 }
2177
2178 free(convs, M_DEVBUF2, this->na_dacs * sizeof(nid_t));
2179 return(err);
2180}
2181
2182/* Connect the speaker to a DAC that no other output pin is connected
2183 * to by default. If that is not possible, connect to a DAC other
2184 * than the one the first output pin is connected to.
2185 */
2186int
2187azalia_codec_select_spkrdac(codec_t *this)
2188{
2189 widget_t *w;
2190 nid_t convs[HDA_MAX_CHANNELS16];
2191 int nconv, conv;
2192 int i, j, err, fspkr, conn;
2193
2194 nconv = fspkr = 0;
2195 for (i = 0; i < this->nopins; i++) {
2196 conv = this->opins[i].conv;
2197 for (j = 0; j < nconv; j++) {
2198 if (conv == convs[j])
2199 break;
2200 }
2201 if (j == nconv) {
2202 if (conv == this->spkr_dac)
2203 fspkr = 1;
2204 convs[nconv++] = conv;
2205 if (nconv == this->na_dacs)
2206 break;
2207 }
2208 }
2209
2210 if (fspkr) {
2211 conn = conv = -1;
2212 w = &this->w[this->speaker];
2213 for (i = 0; i < w->nconnections; i++) {
2214 conv = azalia_codec_find_defdac(this,
2215 w->connections[i], 1);
2216 for (j = 0; j < nconv; j++)
2217 if (conv == convs[j])
2218 break;
2219 if (j == nconv)
2220 break;
2221 }
2222 if (i < w->nconnections) {
2223 conn = i;
2224 } else {
2225 /* Couldn't get a unique DAC. Try to get a different
2226 * DAC than the first pin's DAC.
2227 */
2228 if (this->spkr_dac == this->opins[0].conv) {
2229 /* If the speaker connection can't be changed,
2230 * change the first pin's connection.
2231 */
2232 if (w->nconnections == 1)
2233 w = &this->w[this->opins[0].nid];
2234 for (j = 0; j < w->nconnections; j++) {
2235 conv = azalia_codec_find_defdac(this,
2236 w->connections[j], 1);
2237 if (conv != this->opins[0].conv) {
2238 conn = j;
2239 break;
2240 }
2241 }
2242 }
2243 }
2244 if (conn != -1 && conv != -1) {
2245 err = azalia_comresp(this, w->nid,
2246 CORB_SET_CONNECTION_SELECT_CONTROL0x701, conn, 0);
2247 if (err)
2248 return(err);
2249 w->selected = conn;
2250 if (w->nid == this->speaker)
2251 this->spkr_dac = conv;
2252 else
2253 this->opins[0].conv = conv;
2254 }
2255 }
2256
2257 /* If there is a speaker2, try to connect it to spkr_dac. */
2258 if (this->speaker2 != -1) {
2259 conn = conv = -1;
Although the value stored to 'conv' is used in the enclosing expression, the value is never actually read from 'conv'
2260 w = &this->w[this->speaker2];
2261 for (i = 0; i < w->nconnections; i++) {
2262 conv = azalia_codec_find_defdac(this,
2263 w->connections[i], 1);
2264 if (this->qrks & AZ_QRK_ROUTE_SPKR2_DAC0x01000000) {
2265 if (conv != this->spkr_dac) {
2266 conn = i;
2267 break;
2268 }
2269 } else if (conv == this->spkr_dac) {
2270 conn = i;
2271 break;
2272 }
2273 }
2274 if (conn != -1) {
2275 err = azalia_comresp(this, w->nid,
2276 CORB_SET_CONNECTION_SELECT_CONTROL0x701, conn, 0);
2277 if (err)
2278 return(err);
2279 w->selected = conn;
2280 }
2281 }
2282
2283 return(0);
2284}
2285
2286int
2287azalia_codec_find_defdac(codec_t *this, int index, int depth)
2288{
2289 const widget_t *w;
2290 int i, ret;
2291
2292 w = &this->w[index];
2293 if (w->enable == 0)
2294 return -1;
2295
2296 if (w->type == COP_AWTYPE_AUDIO_OUTPUT0x0)
2297 return index;
2298
2299 if (depth > 0 &&
2300 (w->type == COP_AWTYPE_PIN_COMPLEX0x4 ||
2301 w->type == COP_AWTYPE_BEEP_GENERATOR0x7 ||
2302 w->type == COP_AWTYPE_AUDIO_INPUT0x1))
2303 return -1;
2304 if (++depth >= 10)
2305 return -1;
2306
2307 if (w->nconnections > 0) {
2308 /* by default, all mixer connections are active */
2309 if (w->type == COP_AWTYPE_AUDIO_MIXER0x2) {
2310 for (i = 0; i < w->nconnections; i++) {
2311 index = w->connections[i];
2312 if (!azalia_widget_enabled(this, index))
2313 continue;
2314 ret = azalia_codec_find_defdac(this, index,
2315 depth);
2316 if (ret >= 0)
2317 return ret;
2318 }
2319 /* 7.3.3.2 Connection Select Control
2320 * If an attempt is made to Set an index value greater than
2321 * the number of list entries (index is equal to or greater
2322 * than the Connection List Length property for the widget)
2323 * the behavior is not predictable.
2324 */
2325
2326 /* negative index values are wrong too */
2327 } else if (w->selected >= 0 &&
2328 w->selected < sizeof(w->connections)) {
2329 index = w->connections[w->selected];
2330 if (VALID_WIDGET_NID(index, this)(index == (this)->audiofunc || (index >= (this)->wstart
&& index < (this)->wend))
) {
2331 ret = azalia_codec_find_defdac(this,
2332 index, depth);
2333 if (ret >= 0)
2334 return ret;
2335 }
2336 }
2337 }
2338
2339 return -1;
2340}
2341
2342int
2343azalia_codec_find_defadc_sub(codec_t *this, nid_t node, int index, int depth)
2344{
2345 const widget_t *w;
2346 int i, ret;
2347
2348 w = &this->w[index];
2349 if (w->nid == node) {
2350 return index;
2351 }
2352 /* back at the beginning or a bad end */
2353 if (depth > 0 &&
2354 (w->type == COP_AWTYPE_PIN_COMPLEX0x4 ||
2355 w->type == COP_AWTYPE_BEEP_GENERATOR0x7 ||
2356 w->type == COP_AWTYPE_AUDIO_OUTPUT0x0 ||
2357 w->type == COP_AWTYPE_AUDIO_INPUT0x1))
2358 return -1;
2359 if (++depth >= 10)
2360 return -1;
2361
2362 if (w->nconnections > 0) {
2363 /* by default, all mixer connections are active */
2364 if (w->type == COP_AWTYPE_AUDIO_MIXER0x2) {
2365 for (i = 0; i < w->nconnections; i++) {
2366 if (!azalia_widget_enabled(this, w->connections[i]))
2367 continue;
2368 ret = azalia_codec_find_defadc_sub(this, node,
2369 w->connections[i], depth);
2370 if (ret >= 0)
2371 return ret;
2372 }
2373 /* 7.3.3.2 Connection Select Control
2374 * If an attempt is made to Set an index value greater than
2375 * the number of list entries (index is equal to or greater
2376 * than the Connection List Length property for the widget)
2377 * the behavior is not predictable.
2378 */
2379
2380 /* negative index values are wrong too */
2381 } else if (w->selected >= 0 &&
2382 w->selected < sizeof(w->connections)) {
2383 index = w->connections[w->selected];
2384 if (VALID_WIDGET_NID(index, this)(index == (this)->audiofunc || (index >= (this)->wstart
&& index < (this)->wend))
) {
2385 ret = azalia_codec_find_defadc_sub(this,
2386 node, index, depth);
2387 if (ret >= 0)
2388 return ret;
2389 }
2390 }
2391 }
2392 return -1;
2393}
2394
2395int
2396azalia_codec_find_defadc(codec_t *this, int index, int depth)
2397{
2398 int i, j, conv;
2399
2400 conv = -1;
2401 for (i = 0; i < this->na_adcs; i++) {
2402 j = azalia_codec_find_defadc_sub(this, index,
2403 this->a_adcs[i], 0);
2404 if (j >= 0) {
2405 conv = this->a_adcs[i];
2406 break;
2407 }
2408 }
2409 return(conv);
2410}
2411
2412int
2413azalia_codec_init_volgroups(codec_t *this)
2414{
2415 const widget_t *w;
2416 uint32_t cap, result;
2417 int i, j, dac, err;
2418
2419 j = 0;
2420 this->playvols.mask = 0;
2421 FOR_EACH_WIDGET(this, i)for (i = (this)->wstart; i < (this)->wend; i++) {
2422 w = &this->w[i];
2423 if (w->enable == 0)
2424 continue;
2425 if (w->mixer_class == AZ_CLASS_RECORD2)
2426 continue;
2427 if (!(w->widgetcap & COP_AWCAP_OUTAMP0x004))
2428 continue;
2429 if ((COP_AMPCAP_NUMSTEPS(w->outamp_cap)((w->outamp_cap >> 8) & 0x7f) == 0) &&
2430 !(w->outamp_cap & COP_AMPCAP_MUTE0x80000000))
2431 continue;
2432 this->playvols.mask |= (1 << j);
2433 this->playvols.slaves[j++] = w->nid;
2434 if (j >= AZ_MAX_VOL_SLAVES16)
2435 break;
2436 }
2437 this->playvols.nslaves = j;
2438
2439 this->playvols.cur = 0;
2440 for (i = 0; i < this->playvols.nslaves; i++) {
2441 w = &this->w[this->playvols.slaves[i]];
2442 if (w->nid == this->input_mixer ||
2443 w->parent == this->input_mixer ||
2444 WIDGET_CHANNELS(w)((w)->widgetcap & 0x001 ? 2 : 1) < 2)
2445 continue;
2446 j = 0;
2447 /* azalia_codec_find_defdac only goes 10 connections deep.
2448 * Start the connection depth at 7 so it doesn't go more
2449 * than 3 connections deep.
2450 */
2451 if (w->type == COP_AWTYPE_AUDIO_MIXER0x2 ||
2452 w->type == COP_AWTYPE_AUDIO_SELECTOR0x3)
2453 j = 7;
2454 dac = azalia_codec_find_defdac(this, w->nid, j);
2455 if (dac == -1)
2456 continue;
2457 if (dac != this->dacs.groups[this->dacs.cur].conv[0] &&
2458 dac != this->spkr_dac && dac != this->fhp_dac)
2459 continue;
2460 cap = w->outamp_cap;
2461 if ((cap & COP_AMPCAP_MUTE0x80000000) && COP_AMPCAP_NUMSTEPS(cap)((cap >> 8) & 0x7f)) {
2462 if (w->type == COP_AWTYPE_BEEP_GENERATOR0x7) {
2463 continue;
2464 } else if (w->type == COP_AWTYPE_PIN_COMPLEX0x4) {
2465 err = azalia_comresp(this, w->nid,
2466 CORB_GET_PIN_WIDGET_CONTROL0xf07, 0, &result);
2467 if (!err && (result & CORB_PWC_OUTPUT0x40))
2468 this->playvols.cur |= (1 << i);
2469 } else
2470 this->playvols.cur |= (1 << i);
2471 }
2472 }
2473 if (this->playvols.cur == 0) {
2474 for (i = 0; i < this->playvols.nslaves; i++) {
2475 w = &this->w[this->playvols.slaves[i]];
2476 j = 0;
2477 if (w->type == COP_AWTYPE_AUDIO_MIXER0x2 ||
2478 w->type == COP_AWTYPE_AUDIO_SELECTOR0x3)
2479 j = 7;
2480 dac = azalia_codec_find_defdac(this, w->nid, j);
2481 if (dac == -1)
2482 continue;
2483 if (dac != this->dacs.groups[this->dacs.cur].conv[0] &&
2484 dac != this->spkr_dac && dac != this->fhp_dac)
2485 continue;
2486 if (w->type == COP_AWTYPE_BEEP_GENERATOR0x7)
2487 continue;
2488 if (w->type == COP_AWTYPE_PIN_COMPLEX0x4) {
2489 err = azalia_comresp(this, w->nid,
2490 CORB_GET_PIN_WIDGET_CONTROL0xf07, 0, &result);
2491 if (!err && (result & CORB_PWC_OUTPUT0x40))
2492 this->playvols.cur |= (1 << i);
2493 } else {
2494 this->playvols.cur |= (1 << i);
2495 }
2496 }
2497 }
2498
2499 this->playvols.master = this->audiofunc;
2500 if (this->playvols.nslaves > 0) {
2501 FOR_EACH_WIDGET(this, i)for (i = (this)->wstart; i < (this)->wend; i++) {
2502 w = &this->w[i];
2503 if (w->type != COP_AWTYPE_VOLUME_KNOB0x6)
2504 continue;
2505 if (!COP_VKCAP_NUMSTEPS(w->d.volume.cap)(w->d.volume.cap & 0x7f))
2506 continue;
2507 this->playvols.master = w->nid;
2508 break;
2509 }
2510 }
2511
2512 j = 0;
2513 this->recvols.mask = 0;
2514 FOR_EACH_WIDGET(this, i)for (i = (this)->wstart; i < (this)->wend; i++) {
2515 w = &this->w[i];
2516 if (w->enable == 0)
2517 continue;
2518 if (w->type == COP_AWTYPE_AUDIO_INPUT0x1 ||
2519 w->type == COP_AWTYPE_PIN_COMPLEX0x4) {
2520 if (!(w->widgetcap & COP_AWCAP_INAMP0x002))
2521 continue;
2522 if ((COP_AMPCAP_NUMSTEPS(w->inamp_cap)((w->inamp_cap >> 8) & 0x7f) == 0) &&
2523 !(w->inamp_cap & COP_AMPCAP_MUTE0x80000000))
2524 continue;
2525 } else if (w->type == COP_AWTYPE_AUDIO_MIXER0x2 ||
2526 w->type == COP_AWTYPE_AUDIO_SELECTOR0x3) {
2527 if (w->mixer_class != AZ_CLASS_RECORD2)
2528 continue;
2529 if (!(w->widgetcap & COP_AWCAP_OUTAMP0x004))
2530 continue;
2531 if ((COP_AMPCAP_NUMSTEPS(w->outamp_cap)((w->outamp_cap >> 8) & 0x7f) == 0) &&
2532 !(w->outamp_cap & COP_AMPCAP_MUTE0x80000000))
2533 continue;
2534 } else {
2535 continue;
2536 }
2537 this->recvols.mask |= (1 << j);
2538 this->recvols.slaves[j++] = w->nid;
2539 if (j >= AZ_MAX_VOL_SLAVES16)
2540 break;
2541 }
2542 this->recvols.nslaves = j;
2543
2544 this->recvols.cur = 0;
2545 for (i = 0; i < this->recvols.nslaves; i++) {
2546 w = &this->w[this->recvols.slaves[i]];
2547 cap = w->outamp_cap;
2548 if (w->type == COP_AWTYPE_AUDIO_INPUT0x1 ||
2549 w->type != COP_AWTYPE_PIN_COMPLEX0x4)
2550 cap = w->inamp_cap;
2551 else
2552 if (w->mixer_class != AZ_CLASS_RECORD2)
2553 continue;
2554 if ((cap & COP_AMPCAP_MUTE0x80000000) && COP_AMPCAP_NUMSTEPS(cap)((cap >> 8) & 0x7f)) {
2555 if (w->type == COP_AWTYPE_PIN_COMPLEX0x4) {
2556 err = azalia_comresp(this, w->nid,
2557 CORB_GET_PIN_WIDGET_CONTROL0xf07, 0, &result);
2558 if (!err && !(result & CORB_PWC_OUTPUT0x40))
2559 this->recvols.cur |= (1 << i);
2560 } else
2561 this->recvols.cur |= (1 << i);
2562 }
2563 }
2564 if (this->recvols.cur == 0) {
2565 for (i = 0; i < this->recvols.nslaves; i++) {
2566 w = &this->w[this->recvols.slaves[i]];
2567 cap = w->outamp_cap;
2568 if (w->type == COP_AWTYPE_AUDIO_INPUT0x1 ||
2569 w->type != COP_AWTYPE_PIN_COMPLEX0x4)
2570 cap = w->inamp_cap;
2571 else
2572 if (w->mixer_class != AZ_CLASS_RECORD2)
2573 continue;
2574 if (w->type == COP_AWTYPE_PIN_COMPLEX0x4) {
2575 err = azalia_comresp(this, w->nid,
2576 CORB_GET_PIN_WIDGET_CONTROL0xf07, 0, &result);
2577 if (!err && !(result & CORB_PWC_OUTPUT0x40))
2578 this->recvols.cur |= (1 << i);
2579 } else {
2580 this->recvols.cur |= (1 << i);
2581 }
2582 }
2583 }
2584
2585 this->recvols.master = this->audiofunc;
2586
2587 return 0;
2588}
2589
2590int
2591azalia_codec_delete(codec_t *this)
2592{
2593 azalia_mixer_delete(this);
2594
2595 if (this->formats != NULL((void *)0)) {
2596 free(this->formats, M_DEVBUF2,
2597 this->nformats * sizeof(struct audio_format));
2598 this->formats = NULL((void *)0);
2599 }
2600 this->nformats = 0;
2601
2602 if (this->opins != NULL((void *)0)) {
2603 free(this->opins, M_DEVBUF2,
2604 this->nopins * sizeof(struct io_pin));
2605 this->opins = NULL((void *)0);
2606 }
2607 this->nopins = 0;
2608
2609 if (this->opins_d != NULL((void *)0)) {
2610 free(this->opins_d, M_DEVBUF2,
2611 this->nopins_d * sizeof(struct io_pin));
2612 this->opins_d = NULL((void *)0);
2613 }
2614 this->nopins_d = 0;
2615
2616 if (this->ipins != NULL((void *)0)) {
2617 free(this->ipins, M_DEVBUF2,
2618 this->nipins * sizeof(struct io_pin));
2619 this->ipins = NULL((void *)0);
2620 }
2621 this->nipins = 0;
2622
2623 if (this->ipins_d != NULL((void *)0)) {
2624 free(this->ipins_d, M_DEVBUF2,
2625 this->nipins_d * sizeof(struct io_pin));
2626 this->ipins_d = NULL((void *)0);
2627 }
2628 this->nipins_d = 0;
2629
2630 if (this->w != NULL((void *)0)) {
2631 free(this->w, M_DEVBUF2,
2632 this->wend * sizeof(widget_t));
2633 this->w = NULL((void *)0);
2634 }
2635
2636 return 0;
2637}
2638
2639int
2640azalia_codec_construct_format(codec_t *this, int newdac, int newadc)
2641{
2642 const convgroup_t *group;
2643 uint32_t bits_rates;
2644 int variation;
2645 int nbits, c, chan, i;
2646 nid_t nid;
2647
2648 variation = 0;
2649
2650 if (this->dacs.ngroups > 0 && newdac < this->dacs.ngroups &&
2651 newdac >= 0) {
2652 this->dacs.cur = newdac;
2653 group = &this->dacs.groups[this->dacs.cur];
2654 bits_rates = this->w[group->conv[0]].d.audio.bits_rates;
2655 nbits = 0;
2656 if (bits_rates & COP_PCM_B80x00010000)
2657 nbits++;
2658 if (bits_rates & COP_PCM_B160x00020000)
2659 nbits++;
2660 if (bits_rates & COP_PCM_B200x00040000)
2661 nbits++;
2662 if (bits_rates & COP_PCM_B240x00080000)
2663 nbits++;
2664 if ((bits_rates & COP_PCM_B320x00100000) &&
2665 !(this->w[group->conv[0]].widgetcap & COP_AWCAP_DIGITAL0x200))
2666 nbits++;
2667 if (nbits == 0) {
2668 printf("%s: invalid DAC PCM format: 0x%8.8x\n",
2669 XNAME(this->az)((this->az)->dev.dv_xname), bits_rates);
2670 return -1;
2671 }
2672 variation += group->nconv * nbits;
2673 }
2674
2675 if (this->adcs.ngroups > 0 && newadc < this->adcs.ngroups &&
2676 newadc >= 0) {
2677 this->adcs.cur = newadc;
2678 group = &this->adcs.groups[this->adcs.cur];
2679 bits_rates = this->w[group->conv[0]].d.audio.bits_rates;
2680 nbits = 0;
2681 if (bits_rates & COP_PCM_B80x00010000)
2682 nbits++;
2683 if (bits_rates & COP_PCM_B160x00020000)
2684 nbits++;
2685 if (bits_rates & COP_PCM_B200x00040000)
2686 nbits++;
2687 if (bits_rates & COP_PCM_B240x00080000)
2688 nbits++;
2689 if ((bits_rates & COP_PCM_B320x00100000) &&
2690 !(this->w[group->conv[0]].widgetcap & COP_AWCAP_DIGITAL0x200))
2691 nbits++;
2692 if (nbits == 0) {
2693 printf("%s: invalid ADC PCM format: 0x%8.8x\n",
2694 XNAME(this->az)((this->az)->dev.dv_xname), bits_rates);
2695 return -1;
2696 }
2697 variation += group->nconv * nbits;
2698 }
2699
2700 if (variation == 0) {
2701 DPRINTF(("%s: no converter groups\n", XNAME(this->az)))do {} while (0 );
2702 return -1;
2703 }
2704
2705 if (this->formats != NULL((void *)0))
2706 free(this->formats, M_DEVBUF2, 0);
2707 this->nformats = 0;
2708 this->formats = mallocarray(variation, sizeof(struct audio_format),
2709 M_DEVBUF2, M_NOWAIT0x0002 | M_ZERO0x0008);
2710 if (this->formats == NULL((void *)0)) {
2711 printf("%s: out of memory in %s\n",
2712 XNAME(this->az)((this->az)->dev.dv_xname), __func__);
2713 return ENOMEM12;
2714 }
2715
2716 /* register formats for playback */
2717 if (this->dacs.ngroups > 0) {
2718 group = &this->dacs.groups[this->dacs.cur];
2719 for (c = 0; c < group->nconv; c++) {
2720 chan = 0;
2721 bits_rates = ~0;
2722 if (this->w[group->conv[0]].widgetcap &
2723 COP_AWCAP_DIGITAL0x200)
2724 bits_rates &= ~(COP_PCM_B320x00100000);
2725 for (i = 0; i <= c; i++) {
2726 nid = group->conv[i];
2727 chan += WIDGET_CHANNELS(&this->w[nid])((&this->w[nid])->widgetcap & 0x001 ? 2 : 1);
2728 bits_rates &= this->w[nid].d.audio.bits_rates;
2729 }
2730 azalia_codec_add_bits(this, chan, bits_rates,
2731 AUMODE_PLAY0x01);
2732 }
2733 }
2734
2735 /* register formats for recording */
2736 if (this->adcs.ngroups > 0) {
2737 group = &this->adcs.groups[this->adcs.cur];
2738 for (c = 0; c < group->nconv; c++) {
2739 chan = 0;
2740 bits_rates = ~0;
2741 if (this->w[group->conv[0]].widgetcap &
2742 COP_AWCAP_DIGITAL0x200)
2743 bits_rates &= ~(COP_PCM_B320x00100000);
2744 for (i = 0; i <= c; i++) {
2745 nid = group->conv[i];
2746 chan += WIDGET_CHANNELS(&this->w[nid])((&this->w[nid])->widgetcap & 0x001 ? 2 : 1);
2747 bits_rates &= this->w[nid].d.audio.bits_rates;
2748 }
2749 azalia_codec_add_bits(this, chan, bits_rates,
2750 AUMODE_RECORD0x02);
2751 }
2752 }
2753
2754 return 0;
2755}
2756
2757void
2758azalia_codec_add_bits(codec_t *this, int chan, uint32_t bits_rates, int mode)
2759{
2760 if (bits_rates & COP_PCM_B80x00010000)
2761 azalia_codec_add_format(this, chan, 8, bits_rates, mode);
2762 if (bits_rates & COP_PCM_B160x00020000)
2763 azalia_codec_add_format(this, chan, 16, bits_rates, mode);
2764 if (bits_rates & COP_PCM_B200x00040000)
2765 azalia_codec_add_format(this, chan, 20, bits_rates, mode);
2766 if (bits_rates & COP_PCM_B240x00080000)
2767 azalia_codec_add_format(this, chan, 24, bits_rates, mode);
2768 if (bits_rates & COP_PCM_B320x00100000)
2769 azalia_codec_add_format(this, chan, 32, bits_rates, mode);
2770}
2771
2772void
2773azalia_codec_add_format(codec_t *this, int chan, int prec, uint32_t rates,
2774 int32_t mode)
2775{
2776 struct audio_format *f;
2777
2778 f = &this->formats[this->nformats++];
2779 f->mode = mode;
2780 f->encoding = AUDIO_ENCODING_SLINEAR_LE6;
2781 if (prec == 8)
2782 f->encoding = AUDIO_ENCODING_ULINEAR_LE8;
2783 f->precision = prec;
2784 f->channels = chan;
2785 f->frequency_type = 0;
2786 if (rates & COP_PCM_R800x00000001)
2787 f->frequency[f->frequency_type++] = 8000;
2788 if (rates & COP_PCM_R1100x00000002)
2789 f->frequency[f->frequency_type++] = 11025;
2790 if (rates & COP_PCM_R1600x00000004)
2791 f->frequency[f->frequency_type++] = 16000;
2792 if (rates & COP_PCM_R2200x00000008)
2793 f->frequency[f->frequency_type++] = 22050;
2794 if (rates & COP_PCM_R3200x00000010)
2795 f->frequency[f->frequency_type++] = 32000;
2796 if (rates & COP_PCM_R4410x00000020)
2797 f->frequency[f->frequency_type++] = 44100;
2798 if (rates & COP_PCM_R4800x00000040)
2799 f->frequency[f->frequency_type++] = 48000;
2800 if (rates & COP_PCM_R8820x00000080)
2801 f->frequency[f->frequency_type++] = 88200;
2802 if (rates & COP_PCM_R9600x00000100)
2803 f->frequency[f->frequency_type++] = 96000;
2804 if (rates & COP_PCM_R17640x00000200)
2805 f->frequency[f->frequency_type++] = 176400;
2806 if (rates & COP_PCM_R19200x00000400)
2807 f->frequency[f->frequency_type++] = 192000;
2808 if (rates & COP_PCM_R38400x00000800)
2809 f->frequency[f->frequency_type++] = 384000;
2810}
2811
2812int
2813azalia_codec_connect_stream(stream_t *this)
2814{
2815 const codec_t *codec = &this->az->codecs[this->az->codecno];
2816 const convgroup_t *group;
2817 widget_t *w;
2818 uint32_t digital, stream_chan;
2819 int i, err, curchan, nchan, widchan;
2820
2821 err = 0;
2822 nchan = (this->fmt & HDA_SD_FMT_CHAN0x000f) + 1;
2823
2824 if (this->dir == AUMODE_RECORD0x02)
2825 group = &codec->adcs.groups[codec->adcs.cur];
2826 else
2827 group = &codec->dacs.groups[codec->dacs.cur];
2828
2829 curchan = 0;
2830 for (i = 0; i < group->nconv; i++) {
2831 w = &codec->w[group->conv[i]];
2832 widchan = WIDGET_CHANNELS(w)((w)->widgetcap & 0x001 ? 2 : 1);
2833
2834 stream_chan = (this->number << 4);
2835 if (curchan < nchan) {
2836 stream_chan |= curchan;
2837 } else if (w->nid == codec->spkr_dac ||
2838 w->nid == codec->fhp_dac) {
2839 stream_chan |= 0; /* first channel(s) */
2840 } else
2841 stream_chan = 0; /* idle stream */
2842
2843 if (stream_chan == 0) {
2844 DPRINTFN(0, ("%s: %2.2x is idle\n", __func__, w->nid))do {} while (0 );
2845 } else {
2846 DPRINTFN(0, ("%s: %2.2x on stream chan %d\n", __func__,do {} while (0 )
2847 w->nid, stream_chan & ~(this->number << 4)))do {} while (0 );
2848 }
2849
2850 err = azalia_comresp(codec, w->nid, CORB_SET_CONVERTER_FORMAT0x200,
2851 this->fmt, NULL((void *)0));
2852 if (err) {
2853 DPRINTF(("%s: nid %2.2x fmt %2.2x: %d\n",do {} while (0 )
2854 __func__, w->nid, this->fmt, err))do {} while (0 );
2855 break;
2856 }
2857 err = azalia_comresp(codec, w->nid,
2858 CORB_SET_CONVERTER_STREAM_CHANNEL0x706, stream_chan, NULL((void *)0));
2859 if (err) {
2860 DPRINTF(("%s: nid %2.2x chan %d: %d\n",do {} while (0 )
2861 __func__, w->nid, stream_chan, err))do {} while (0 );
2862 break;
2863 }
2864
2865 if (w->widgetcap & COP_AWCAP_DIGITAL0x200) {
2866 err = azalia_comresp(codec, w->nid,
2867 CORB_GET_DIGITAL_CONTROL0xf0d, 0, &digital);
2868 if (err) {
2869 DPRINTF(("%s: nid %2.2x get digital: %d\n",do {} while (0 )
2870 __func__, w->nid, err))do {} while (0 );
2871 break;
2872 }
2873 digital = (digital & 0xff) | CORB_DCC_DIGEN0x01;
2874 err = azalia_comresp(codec, w->nid,
2875 CORB_SET_DIGITAL_CONTROL_L0x70d, digital, NULL((void *)0));
2876 if (err) {
2877 DPRINTF(("%s: nid %2.2x set digital: %d\n",do {} while (0 )
2878 __func__, w->nid, err))do {} while (0 );
2879 break;
2880 }
2881 }
2882 curchan += widchan;
2883 }
2884
2885 return err;
2886}
2887
2888int
2889azalia_codec_disconnect_stream(stream_t *this)
2890{
2891 const codec_t *codec = &this->az->codecs[this->az->codecno];
2892 const convgroup_t *group;
2893 uint32_t v;
2894 int i;
2895 nid_t nid;
2896
2897 if (this->dir == AUMODE_RECORD0x02)
2898 group = &codec->adcs.groups[codec->adcs.cur];
2899 else
2900 group = &codec->dacs.groups[codec->dacs.cur];
2901 for (i = 0; i < group->nconv; i++) {
2902 nid = group->conv[i];
2903 azalia_comresp(codec, nid, CORB_SET_CONVERTER_STREAM_CHANNEL0x706,
2904 0, NULL((void *)0)); /* stream#0 */
2905 if (codec->w[nid].widgetcap & COP_AWCAP_DIGITAL0x200) {
2906 /* disable S/PDIF */
2907 azalia_comresp(codec, nid, CORB_GET_DIGITAL_CONTROL0xf0d,
2908 0, &v);
2909 v = (v & ~CORB_DCC_DIGEN0x01) & 0xff;
2910 azalia_comresp(codec, nid, CORB_SET_DIGITAL_CONTROL_L0x70d,
2911 v, NULL((void *)0));
2912 }
2913 }
2914 return 0;
2915}
2916
2917/* ================================================================
2918 * HDA widget functions
2919 * ================================================================ */
2920
2921int
2922azalia_widget_init(widget_t *this, const codec_t *codec, nid_t nid)
2923{
2924 uint32_t result;
2925 int err;
2926
2927 err = azalia_comresp(codec, nid, CORB_GET_PARAMETER0xf00,
2928 COP_AUDIO_WIDGET_CAP0x09, &result);
2929 if (err)
2930 return err;
2931 this->nid = nid;
2932 this->widgetcap = result;
2933 this->type = COP_AWCAP_TYPE(result)((result >> 20) & 0xf);
2934 if (this->widgetcap & COP_AWCAP_POWER0x400) {
2935 azalia_comresp(codec, nid, CORB_SET_POWER_STATE0x705, CORB_PS_D00x0,
2936 &result);
2937 DELAY(100)(*delay_func)(100);
2938 }
2939
2940 this->enable = 1;
2941 this->mixer_class = -1;
2942 this->parent = codec->audiofunc;
2943
2944 switch (this->type) {
2945 case COP_AWTYPE_AUDIO_OUTPUT0x0:
2946 /* FALLTHROUGH */
2947 case COP_AWTYPE_AUDIO_INPUT0x1:
2948 azalia_widget_init_audio(this, codec);
2949 break;
2950 case COP_AWTYPE_PIN_COMPLEX0x4:
2951 azalia_widget_init_pin(this, codec);
2952 break;
2953 case COP_AWTYPE_VOLUME_KNOB0x6:
2954 err = azalia_comresp(codec, this->nid, CORB_GET_PARAMETER0xf00,
2955 COP_VOLUME_KNOB_CAPABILITIES0x13, &result);
2956 if (err)
2957 return err;
2958 this->d.volume.cap = result;
2959 break;
2960 case COP_AWTYPE_POWER0x5:
2961 /* FALLTHROUGH */
2962 case COP_AWTYPE_VENDOR_DEFINED0xf:
2963 this->enable = 0;
2964 break;
2965 }
2966
2967 /* amplifier information */
2968 /* XXX (ab)use bits 24-30 to store the "control offset", which is
2969 * the number of steps, starting at 0, that have no effect. these
2970 * bits are reserved in HDA 1.0.
2971 */
2972 if (this->widgetcap & COP_AWCAP_INAMP0x002) {
2973 if (this->widgetcap & COP_AWCAP_AMPOV0x008)
2974 azalia_comresp(codec, nid, CORB_GET_PARAMETER0xf00,
2975 COP_INPUT_AMPCAP0x0d, &this->inamp_cap);
2976 else
2977 this->inamp_cap = codec->w[codec->audiofunc].inamp_cap;
2978 this->inamp_cap &= ~(0x7f << 24);
2979 }
2980 if (this->widgetcap & COP_AWCAP_OUTAMP0x004) {
2981 if (this->widgetcap & COP_AWCAP_AMPOV0x008)
2982 azalia_comresp(codec, nid, CORB_GET_PARAMETER0xf00,
2983 COP_OUTPUT_AMPCAP0x12, &this->outamp_cap);
2984 else
2985 this->outamp_cap = codec->w[codec->audiofunc].outamp_cap;
2986 this->outamp_cap &= ~(0x7f << 24);
2987 }
2988 return 0;
2989}
2990
2991int
2992azalia_widget_sole_conn(codec_t *this, nid_t nid)
2993{
2994 int i, j, target, nconn, has_target;
2995
2996 /* connected to ADC */
2997 for (i = 0; i < this->adcs.ngroups; i++) {
2998 for (j = 0; j < this->adcs.groups[i].nconv; j++) {
2999 target = this->adcs.groups[i].conv[j];
3000 if (this->w[target].nconnections == 1 &&
3001 this->w[target].connections[0] == nid) {
3002 return target;
3003 }
3004 }
3005 }
3006 /* connected to DAC */
3007 for (i = 0; i < this->dacs.ngroups; i++) {
3008 for (j = 0; j < this->dacs.groups[i].nconv; j++) {
3009 target = this->dacs.groups[i].conv[j];
3010 if (this->w[target].nconnections == 1 &&
3011 this->w[target].connections[0] == nid) {
3012 return target;
3013 }
3014 }
3015 }
3016 /* connected to pin complex */
3017 target = -1;
3018 FOR_EACH_WIDGET(this, i)for (i = (this)->wstart; i < (this)->wend; i++) {
3019 if (this->w[i].type != COP_AWTYPE_PIN_COMPLEX0x4)
3020 continue;
3021 if (this->w[i].nconnections == 1 &&
3022 this->w[i].connections[0] == nid) {
3023 if (target != -1)
3024 return -1;
3025 target = i;
3026 } else {
3027 nconn = 0;
3028 has_target = 0;
3029 for (j = 0; j < this->w[i].nconnections; j++) {
3030 if (!this->w[this->w[i].connections[j]].enable)
3031 continue;
3032 nconn++;
3033 if (this->w[i].connections[j] == nid)
3034 has_target = 1;
3035 }
3036 if (has_target == 1) {
3037 if (nconn == 1) {
3038 if (target != -1)
3039 return -1;
3040 target = i;
3041 } else {
3042 /* not sole connection at least once */
3043 return -1;
3044 }
3045 }
3046 }
3047 }
3048 if (target != -1)
3049 return target;
3050
3051 return -1;
3052}
3053
3054int
3055azalia_widget_label_widgets(codec_t *codec)
3056{
3057 widget_t *w;
3058 convgroup_t *group;
3059 int types[16];
3060 int pins[16];
3061 int colors_used, use_colors, schan;
3062 int i, j;
3063
3064 bzero(&pins, sizeof(pins))__builtin_bzero((&pins), (sizeof(pins)));
3065 bzero(&types, sizeof(types))__builtin_bzero((&types), (sizeof(types)));
3066
3067 /* If codec has more than one line-out jack, check if the jacks
3068 * have unique colors. If so, use the colors in the mixer names.
3069 */
3070 use_colors = 1;
3071 colors_used = 0;
3072 if (codec->nout_jacks < 2)
3073 use_colors = 0;
3074 for (i = 0; use_colors && i < codec->nopins; i++) {
3075 w = &codec->w[codec->opins[i].nid];
3076 if (w->d.pin.device != CORB_CD_LINEOUT0x0)
3077 continue;
3078 if (colors_used & (1 << w->d.pin.color))
3079 use_colors = 0;
3080 else
3081 colors_used |= (1 << w->d.pin.color);
3082 }
3083
3084 FOR_EACH_WIDGET(codec, i)for (i = (codec)->wstart; i < (codec)->wend; i++) {
3085 w = &codec->w[i];
3086 /* default for disabled/unused widgets */
3087 snprintf(w->name, sizeof(w->name), "u-wid%2.2x", w->nid);
3088 if (w->enable == 0)
3089 continue;
3090 switch (w->type) {
3091 case COP_AWTYPE_PIN_COMPLEX0x4:
3092 pins[w->d.pin.device]++;
3093 if (use_colors && w->d.pin.device == CORB_CD_LINEOUT0x0) {
3094 snprintf(w->name, sizeof(w->name), "%s-%s",
3095 pin_devices[w->d.pin.device],
3096 line_colors[w->d.pin.color]);
3097 } else if (pins[w->d.pin.device] > 1) {
3098 snprintf(w->name, sizeof(w->name), "%s%d",
3099 pin_devices[w->d.pin.device],
3100 pins[w->d.pin.device]);
3101 } else {
3102 snprintf(w->name, sizeof(w->name), "%s",
3103 pin_devices[w->d.pin.device]);
3104 }
3105 break;
3106 case COP_AWTYPE_AUDIO_OUTPUT0x0:
3107 if (codec->dacs.ngroups < 1)
3108 break;
3109 group = &codec->dacs.groups[0];
3110 schan = 0;
3111 for (j = 0; j < group->nconv; j++) {
3112 if (w->nid == group->conv[j]) {
3113 snprintf(w->name, sizeof(w->name),
3114 "%s-%d:%d", wtypes[w->type], schan,
3115 schan + WIDGET_CHANNELS(w)((w)->widgetcap & 0x001 ? 2 : 1) - 1);
3116 }
3117 schan += WIDGET_CHANNELS(w)((w)->widgetcap & 0x001 ? 2 : 1);
3118 }
3119 if (codec->dacs.ngroups < 2)
3120 break;
3121 group = &codec->dacs.groups[1];
3122 schan = 0;
3123 for (j = 0; j < group->nconv; j++) {
3124 if (w->nid == group->conv[j]) {
3125 snprintf(w->name, sizeof(w->name),
3126 "dig-%s-%d:%d", wtypes[w->type],
3127 schan,
3128 schan + WIDGET_CHANNELS(w)((w)->widgetcap & 0x001 ? 2 : 1) - 1);
3129 }
3130 schan += WIDGET_CHANNELS(w)((w)->widgetcap & 0x001 ? 2 : 1);
3131 }
3132 break;
3133 case COP_AWTYPE_AUDIO_INPUT0x1:
3134 w->mixer_class = AZ_CLASS_RECORD2;
3135 if (codec->adcs.ngroups < 1)
3136 break;
3137 group = &codec->adcs.groups[0];
3138 schan = 0;
3139 for (j = 0; j < group->nconv; j++) {
3140 if (w->nid == group->conv[j]) {
3141 snprintf(w->name, sizeof(w->name),
3142 "%s-%d:%d", wtypes[w->type], schan,
3143 schan + WIDGET_CHANNELS(w)((w)->widgetcap & 0x001 ? 2 : 1) - 1);
3144 }
3145 schan += WIDGET_CHANNELS(w)((w)->widgetcap & 0x001 ? 2 : 1);
3146 }
3147 if (codec->adcs.ngroups < 2)
3148 break;
3149 group = &codec->adcs.groups[1];
3150 schan = 0;
3151 for (j = 0; j < group->nconv; j++) {
3152 if (w->nid == group->conv[j]) {
3153 snprintf(w->name, sizeof(w->name),
3154 "dig-%s-%d:%d", wtypes[w->type],
3155 schan,
3156 schan + WIDGET_CHANNELS(w)((w)->widgetcap & 0x001 ? 2 : 1) - 1);
3157 }
3158 schan += WIDGET_CHANNELS(w)((w)->widgetcap & 0x001 ? 2 : 1);
3159 }
3160 break;
3161 default:
3162 types[w->type]++;
3163 if (types[w->type] > 1)
3164 snprintf(w->name, sizeof(w->name), "%s%d",
3165 wtypes[w->type], types[w->type]);
3166 else
3167 snprintf(w->name, sizeof(w->name), "%s",
3168 wtypes[w->type]);
3169 break;
3170 }
3171 }
3172
3173 /* Mixers and selectors that connect to only one other widget are
3174 * functionally part of the widget they are connected to. Show that
3175 * relationship in the name.
3176 */
3177 FOR_EACH_WIDGET(codec, i)for (i = (codec)->wstart; i < (codec)->wend; i++) {
3178 if (codec->w[i].type != COP_AWTYPE_AUDIO_MIXER0x2 &&
3179 codec->w[i].type != COP_AWTYPE_AUDIO_SELECTOR0x3)
3180 continue;
3181 if (codec->w[i].enable == 0)
3182 continue;
3183 j = azalia_widget_sole_conn(codec, i);
3184 if (j == -1) {
3185 /* Special case. A selector with outamp capabilities
3186 * and is connected to a single widget that has either
3187 * no input or no output capabilities. This widget
3188 * serves as the input or output amp for the widget
3189 * it is connected to.
3190 */
3191 if (codec->w[i].type == COP_AWTYPE_AUDIO_SELECTOR0x3 &&
3192 (codec->w[i].widgetcap & COP_AWCAP_OUTAMP0x004) &&
3193 codec->w[i].nconnections == 1) {
3194 j = codec->w[i].connections[0];
3195 if (!azalia_widget_enabled(codec, j))
3196 continue;
3197 if (!(codec->w[j].widgetcap & COP_AWCAP_INAMP0x002))
3198 codec->w[i].mixer_class =
3199 AZ_CLASS_INPUT0;
3200 else if (!(codec->w[j].widgetcap & COP_AWCAP_OUTAMP0x004))
3201 codec->w[i].mixer_class =
3202 AZ_CLASS_OUTPUT1;
3203 else
3204 continue;
3205 }
3206 }
3207 if (j >= 0) {
3208 /* As part of a disabled widget, this widget
3209 * should be disabled as well.
3210 */
3211 if (codec->w[j].enable == 0) {
3212 codec->w[i].enable = 0;
3213 snprintf(codec->w[i].name,
3214 sizeof(codec->w[i].name),
3215 "u-wid%2.2x", i);
3216 continue;
3217 }
3218 snprintf(codec->w[i].name, sizeof(codec->w[i].name),
3219 "%s", codec->w[j].name);
3220 if (codec->w[j].mixer_class == AZ_CLASS_RECORD2)
3221 codec->w[i].mixer_class = AZ_CLASS_RECORD2;
3222 codec->w[i].parent = j;
3223 }
3224 }
3225
3226 return 0;
3227}
3228
3229int
3230azalia_widget_init_audio(widget_t *this, const codec_t *codec)
3231{
3232 uint32_t result;
3233 int err;
3234
3235 /* check audio format */
3236 if (this->widgetcap & COP_AWCAP_FORMATOV0x010) {
3237 err = azalia_comresp(codec, this->nid, CORB_GET_PARAMETER0xf00,
3238 COP_STREAM_FORMATS0x0b, &result);
3239 if (err)
3240 return err;
3241 this->d.audio.encodings = result;
3242 if (result == 0) { /* quirk for CMI9880.
3243 * This must not occur usually... */
3244 this->d.audio.encodings =
3245 codec->w[codec->audiofunc].d.audio.encodings;
3246 this->d.audio.bits_rates =
3247 codec->w[codec->audiofunc].d.audio.bits_rates;
3248 } else {
3249 if ((result & COP_STREAM_FORMAT_PCM0x00000001) == 0) {
3250 printf("%s: %s: No PCM support: %x\n",
3251 XNAME(codec->az)((codec->az)->dev.dv_xname), this->name, result);
3252 return -1;
3253 }
3254 err = azalia_comresp(codec, this->nid,
3255 CORB_GET_PARAMETER0xf00, COP_PCM0x0a, &result);
3256 if (err)
3257 return err;
3258 this->d.audio.bits_rates = result;
3259 }
3260 } else {
3261 this->d.audio.encodings =
3262 codec->w[codec->audiofunc].d.audio.encodings;
3263 this->d.audio.bits_rates =
3264 codec->w[codec->audiofunc].d.audio.bits_rates;
3265 }
3266 return 0;
3267}
3268
3269int
3270azalia_widget_init_pin(widget_t *this, const codec_t *codec)
3271{
3272 uint32_t result, dir;
3273 int err;
3274
3275 err = azalia_comresp(codec, this->nid, CORB_GET_CONFIGURATION_DEFAULT0xf1c,
3276 0, &result);
3277 if (err)
3278 return err;
3279 this->d.pin.config = result;
3280 this->d.pin.sequence = CORB_CD_SEQUENCE(result)(result & 0x0000000f);
3281 this->d.pin.association = CORB_CD_ASSOCIATION(result)((result >> 4) & 0xf);
3282 this->d.pin.color = CORB_CD_COLOR(result)((result >> 12) & 0xf);
3283 this->d.pin.device = CORB_CD_DEVICE(result)((result >> 20) & 0xf);
3284
3285 err = azalia_comresp(codec, this->nid, CORB_GET_PARAMETER0xf00,
3286 COP_PINCAP0x0c, &result);
3287 if (err)
3288 return err;
3289 this->d.pin.cap = result;
3290
3291 dir = CORB_PWC_INPUT0x20;
3292 switch (this->d.pin.device) {
3293 case CORB_CD_LINEOUT0x0:
3294 case CORB_CD_SPEAKER0x1:
3295 case CORB_CD_HEADPHONE0x2:
3296 case CORB_CD_SPDIFOUT0x4:
3297 case CORB_CD_DIGITALOUT0x5:
3298 dir = CORB_PWC_OUTPUT0x40;
3299 break;
3300 }
3301
3302 if (dir == CORB_PWC_INPUT0x20 && !(this->d.pin.cap & COP_PINCAP_INPUT0x00000020))
3303 dir = CORB_PWC_OUTPUT0x40;
3304 if (dir == CORB_PWC_OUTPUT0x40 && !(this->d.pin.cap & COP_PINCAP_OUTPUT0x00000010))
3305 dir = CORB_PWC_INPUT0x20;
3306
3307 if (dir == CORB_PWC_INPUT0x20 && this->d.pin.device == CORB_CD_MICIN0xa) {
3308 if (COP_PINCAP_VREF(this->d.pin.cap)((this->d.pin.cap >> 8) & 0xff) & (1 << CORB_PWC_VREF_800x04))
3309 dir |= CORB_PWC_VREF_800x04;
3310 else if (COP_PINCAP_VREF(this->d.pin.cap)((this->d.pin.cap >> 8) & 0xff) &
3311 (1 << CORB_PWC_VREF_500x01))
3312 dir |= CORB_PWC_VREF_500x01;
3313 }
3314
3315 if ((codec->qrks & AZ_QRK_WID_OVREF500x00004000) && (dir == CORB_PWC_OUTPUT0x40))
3316 dir |= CORB_PWC_VREF_500x01;
3317
3318 azalia_comresp(codec, this->nid, CORB_SET_PIN_WIDGET_CONTROL0x707,
3319 dir, NULL((void *)0));
3320
3321 if (this->d.pin.cap & COP_PINCAP_EAPD0x00010000) {
3322 err = azalia_comresp(codec, this->nid,
3323 CORB_GET_EAPD_BTL_ENABLE0xf0c, 0, &result);
3324 if (err)
3325 return err;
3326 result &= 0xff;
3327 result |= CORB_EAPD_EAPD0x02;
3328 err = azalia_comresp(codec, this->nid,
3329 CORB_SET_EAPD_BTL_ENABLE0x70c, result, &result);
3330 if (err)
3331 return err;
3332 }
3333
3334 /* Disable unconnected pins */
3335 if (CORB_CD_PORT(this->d.pin.config)((this->d.pin.config >> 30) & 0x3) == CORB_CD_NONE0x1)
3336 this->enable = 0;
3337
3338 return 0;
3339}
3340
3341int
3342azalia_widget_init_connection(widget_t *this, const codec_t *codec)
3343{
3344 uint32_t result;
3345 int err;
3346 int i, j, k;
3347 int length, nconn, bits, conn, last;
3348
3349 this->selected = -1;
3350 if ((this->widgetcap & COP_AWCAP_CONNLIST0x100) == 0)
3351 return 0;
3352
3353 err = azalia_comresp(codec, this->nid, CORB_GET_PARAMETER0xf00,
3354 COP_CONNECTION_LIST_LENGTH0x0e, &result);
3355 if (err)
3356 return err;
3357
3358 bits = 8;
3359 if (result & COP_CLL_LONG0x00000080)
3360 bits = 16;
3361
3362 length = COP_CLL_LENGTH(result)(result & 0x0000007f);
3363 if (length == 0)
3364 return 0;
3365
3366 /*
3367 * 'length' is the number of entries, not the number of
3368 * connections. Find the number of connections, 'nconn', so
3369 * enough space can be allocated for the list of connected
3370 * nids.
3371 */
3372 nconn = last = 0;
3373 for (i = 0; i < length;) {
3374 err = azalia_comresp(codec, this->nid,
3375 CORB_GET_CONNECTION_LIST_ENTRY0xf02, i, &result);
3376 if (err)
3377 return err;
3378 for (k = 0; i < length && (k < 32 / bits); k++) {
3379 conn = (result >> (k * bits)) & ((1 << bits) - 1);
3380 /* If high bit is set, this is the end of a continuous
3381 * list that started with the last connection.
3382 */
3383 if ((nconn > 0) && (conn & (1 << (bits - 1))))
3384 nconn += (conn & ~(1 << (bits - 1))) - last;
3385 else
3386 nconn++;
3387 last = conn;
3388 i++;
3389 }
3390 }
3391
3392 this->connections = mallocarray(nconn, sizeof(nid_t), M_DEVBUF2, M_NOWAIT0x0002);
3393 if (this->connections == NULL((void *)0)) {
3394 printf("%s: out of memory\n", XNAME(codec->az)((codec->az)->dev.dv_xname));
3395 return ENOMEM12;
3396 }
3397 for (i = 0; i < nconn;) {
3398 err = azalia_comresp(codec, this->nid,
3399 CORB_GET_CONNECTION_LIST_ENTRY0xf02, i, &result);
3400 if (err)
3401 return err;
3402 for (k = 0; i < nconn && (k < 32 / bits); k++) {
3403 conn = (result >> (k * bits)) & ((1 << bits) - 1);
3404 /* If high bit is set, this is the end of a continuous
3405 * list that started with the last connection.
3406 */
3407 if ((i > 0) && (conn & (1 << (bits - 1)))) {
3408 for (j = 1; i < nconn && j <= conn - last; j++)
3409 this->connections[i++] = last + j;
3410 } else {
3411 this->connections[i++] = conn;
3412 }
3413 last = conn;
3414 }
3415 }
3416 this->nconnections = nconn;
3417
3418 if (nconn > 0) {
3419 err = azalia_comresp(codec, this->nid,
3420 CORB_GET_CONNECTION_SELECT_CONTROL0xf01, 0, &result);
3421 if (err)
3422 return err;
3423 this->selected = CORB_CSC_INDEX(result)(result & 0xff);
3424 }
3425 return 0;
3426}
3427
3428int
3429azalia_widget_check_conn(codec_t *codec, int index, int depth)
3430{
3431 const widget_t *w;
3432 int i;
3433
3434 w = &codec->w[index];
3435
3436 if (w->type == COP_AWTYPE_BEEP_GENERATOR0x7)
3437 return 0;
3438
3439 if (depth > 0 &&
3440 (w->type == COP_AWTYPE_PIN_COMPLEX0x4 ||
3441 w->type == COP_AWTYPE_AUDIO_OUTPUT0x0 ||
3442 w->type == COP_AWTYPE_AUDIO_INPUT0x1)) {
3443 if (w->enable)
3444 return 1;
3445 else
3446 return 0;
3447 }
3448 if (++depth >= 10)
3449 return 0;
3450 for (i = 0; i < w->nconnections; i++) {
3451 if (!azalia_widget_enabled(codec, w->connections[i]))
3452 continue;
3453 if (azalia_widget_check_conn(codec, w->connections[i], depth))
3454 return 1;
3455 }
3456 return 0;
3457}
3458
3459#ifdef AZALIA_DEBUG
3460
3461#define WIDGETCAP_BITS \
3462 "\20\014LRSWAP\013POWER\012DIGITAL" \
3463 "\011CONNLIST\010UNSOL\07PROC\06STRIPE\05FORMATOV\04AMPOV\03OUTAMP" \
3464 "\02INAMP\01STEREO"
3465
3466#define PINCAP_BITS "\20\021EAPD\16VREF100\15VREF80" \
3467 "\13VREFGND\12VREF50\11VREFHIZ\07BALANCE\06INPUT" \
3468 "\05OUTPUT\04HEADPHONE\03PRESENCE\02TRIGGER\01IMPEDANCE"
3469
3470#define ENCODING_BITS "\20\3AC3\2FLOAT32\1PCM"
3471
3472#define BITSRATES_BITS "\20\x15""32bit\x14""24bit\x13""20bit" \
3473 "\x12""16bit\x11""8bit""\x0c""384kHz\x0b""192kHz\x0a""176.4kHz" \
3474 "\x09""96kHz\x08""88.2kHz\x07""48kHz\x06""44.1kHz\x05""32kHz\x04" \
3475 "22.05kHz\x03""16kHz\x02""11.025kHz\x01""8kHz"
3476
3477static const char *pin_colors[16] = {
3478 "unknown", "black", "gray", "blue",
3479 "green", "red", "orange", "yellow",
3480 "purple", "pink", "col0a", "col0b",
3481 "col0c", "col0d", "white", "other"};
3482static const char *pin_conn[4] = {
3483 "jack", "none", "fixed", "combined"};
3484static const char *pin_conntype[16] = {
3485 "unknown", "1/8", "1/4", "atapi", "rca", "optical",
3486 "digital", "analog", "din", "xlr", "rj-11", "combination",
3487 "con0c", "con0d", "con0e", "other"};
3488static const char *pin_geo[15] = {
3489 "n/a", "rear", "front", "left",
3490 "right", "top", "bottom", "spec0", "spec1", "spec2",
3491 "loc0a", "loc0b", "loc0c", "loc0d", "loc0f"};
3492static const char *pin_chass[4] = {
3493 "external", "internal", "separate", "other"};
3494
3495void
3496azalia_codec_print_audiofunc(const codec_t *this)
3497{
3498 uint32_t result;
3499
3500 azalia_widget_print_audio(&this->w[this->audiofunc], "\t");
3501
3502 result = this->w[this->audiofunc].inamp_cap;
3503 DPRINTF(("\tinamp: mute=%u size=%u steps=%u offset=%u\n",do {} while (0 )
3504 (result & COP_AMPCAP_MUTE) != 0, COP_AMPCAP_STEPSIZE(result),do {} while (0 )
3505 COP_AMPCAP_NUMSTEPS(result), COP_AMPCAP_OFFSET(result)))do {} while (0 );
3506 result = this->w[this->audiofunc].outamp_cap;
3507 DPRINTF(("\toutamp: mute=%u size=%u steps=%u offset=%u\n",do {} while (0 )
3508 (result & COP_AMPCAP_MUTE) != 0, COP_AMPCAP_STEPSIZE(result),do {} while (0 )
3509 COP_AMPCAP_NUMSTEPS(result), COP_AMPCAP_OFFSET(result)))do {} while (0 );
3510 azalia_comresp(this, this->audiofunc, CORB_GET_PARAMETER0xf00,
3511 COP_GPIO_COUNT0x11, &result);
3512 DPRINTF(("\tgpio: wake=%u unsol=%u gpis=%u gpos=%u gpios=%u\n",do {} while (0 )
3513 (result & COP_GPIO_WAKE) != 0, (result & COP_GPIO_UNSOL) != 0,do {} while (0 )
3514 COP_GPIO_GPIS(result), COP_GPIO_GPOS(result),do {} while (0 )
3515 COP_GPIO_GPIOS(result)))do {} while (0 );
3516}
3517
3518void
3519azalia_codec_print_groups(const codec_t *this)
3520{
3521 int i, n;
3522
3523 for (i = 0; i < this->dacs.ngroups; i++) {
3524 printf("%s: dacgroup[%d]:", XNAME(this->az)((this->az)->dev.dv_xname), i);
3525 for (n = 0; n < this->dacs.groups[i].nconv; n++) {
3526 printf(" %2.2x", this->dacs.groups[i].conv[n]);
3527 }
3528 printf("\n");
3529 }
3530 for (i = 0; i < this->adcs.ngroups; i++) {
3531 printf("%s: adcgroup[%d]:", XNAME(this->az)((this->az)->dev.dv_xname), i);
3532 for (n = 0; n < this->adcs.groups[i].nconv; n++) {
3533 printf(" %2.2x", this->adcs.groups[i].conv[n]);
3534 }
3535 printf("\n");
3536 }
3537}
3538
3539void
3540azalia_widget_print_audio(const widget_t *this, const char *lead)
3541{
3542 printf("%sencodings=%b\n", lead, this->d.audio.encodings,
3543 ENCODING_BITS);
3544 printf("%sPCM formats=%b\n", lead, this->d.audio.bits_rates,
3545 BITSRATES_BITS);
3546}
3547
3548void
3549azalia_widget_print_widget(const widget_t *w, const codec_t *codec)
3550{
3551 int i;
3552
3553 printf("%s: ", XNAME(codec->az)((codec->az)->dev.dv_xname));
3554 printf("%s%2.2x wcap=%b\n", w->type == COP_AWTYPE_PIN_COMPLEX0x4 ?
3555 pin_colors[w->d.pin.color] : wtypes[w->type],
3556 w->nid, w->widgetcap, WIDGETCAP_BITS);
3557 if (w->widgetcap & COP_AWCAP_FORMATOV0x010)
3558 azalia_widget_print_audio(w, "\t");
3559 if (w->type == COP_AWTYPE_PIN_COMPLEX0x4)
3560 azalia_widget_print_pin(w);
3561
3562 if (w->type == COP_AWTYPE_VOLUME_KNOB0x6)
3563 printf("\tdelta=%d steps=%d\n",
3564 !!(w->d.volume.cap & COP_VKCAP_DELTA0x00000080),
3565 COP_VKCAP_NUMSTEPS(w->d.volume.cap)(w->d.volume.cap & 0x7f));
3566
3567 if ((w->widgetcap & COP_AWCAP_INAMP0x002) &&
3568 (w->widgetcap & COP_AWCAP_AMPOV0x008))
3569 printf("\tinamp: mute=%u size=%u steps=%u offset=%u\n",
3570 (w->inamp_cap & COP_AMPCAP_MUTE0x80000000) != 0,
3571 COP_AMPCAP_STEPSIZE(w->inamp_cap)((w->inamp_cap >> 16) & 0x7f),
3572 COP_AMPCAP_NUMSTEPS(w->inamp_cap)((w->inamp_cap >> 8) & 0x7f),
3573 COP_AMPCAP_OFFSET(w->inamp_cap)(w->inamp_cap & 0x0000007f));
3574
3575 if ((w->widgetcap & COP_AWCAP_OUTAMP0x004) &&
3576 (w->widgetcap & COP_AWCAP_AMPOV0x008))
3577 printf("\toutamp: mute=%u size=%u steps=%u offset=%u\n",
3578 (w->outamp_cap & COP_AMPCAP_MUTE0x80000000) != 0,
3579 COP_AMPCAP_STEPSIZE(w->outamp_cap)((w->outamp_cap >> 16) & 0x7f),
3580 COP_AMPCAP_NUMSTEPS(w->outamp_cap)((w->outamp_cap >> 8) & 0x7f),
3581 COP_AMPCAP_OFFSET(w->outamp_cap)(w->outamp_cap & 0x0000007f));
3582
3583 if (w->nconnections > 0) {
3584 printf("\tconnections=0x%x", w->connections[0]);
3585 for (i = 1; i < w->nconnections; i++)
3586 printf(",0x%x", w->connections[i]);
3587 printf("; selected=0x%x\n", w->connections[w->selected]);
3588 }
3589}
3590
3591void
3592azalia_widget_print_pin(const widget_t *this)
3593{
3594 printf("\tcap=%b\n", this->d.pin.cap, PINCAP_BITS);
3595 printf("\t[%2.2d/%2.2d] ", CORB_CD_ASSOCIATION(this->d.pin.config)((this->d.pin.config >> 4) & 0xf),
3596 CORB_CD_SEQUENCE(this->d.pin.config)(this->d.pin.config & 0x0000000f));
3597 printf("color=%s ", pin_colors[CORB_CD_COLOR(this->d.pin.config)((this->d.pin.config >> 12) & 0xf)]);
3598 printf("device=%s ", pin_devices[CORB_CD_DEVICE(this->d.pin.config)((this->d.pin.config >> 20) & 0xf)]);
3599 printf("conn=%s ", pin_conn[CORB_CD_PORT(this->d.pin.config)((this->d.pin.config >> 30) & 0x3)]);
3600 printf("conntype=%s\n", pin_conntype[CORB_CD_CONNECTION(this->d.pin.config)((this->d.pin.config >> 16) & 0xf)]);
3601 printf("\tlocation=%s ", pin_geo[CORB_CD_LOC_GEO(this->d.pin.config)((this->d.pin.config >> 24) & 0xf)]);
3602 printf("chassis=%s ", pin_chass[CORB_CD_LOC_CHASS(this->d.pin.config)((this->d.pin.config >> 28) & 0x3)]);
3603 printf("special=");
3604 if (CORB_CD_LOC_GEO(this->d.pin.config)((this->d.pin.config >> 24) & 0xf) == CORB_CD_LOC_SPEC00x7) {
3605 if (CORB_CD_LOC_CHASS(this->d.pin.config)((this->d.pin.config >> 28) & 0x3) == CORB_CD_EXTERNAL0x0)
3606 printf("rear-panel");
3607 else if (CORB_CD_LOC_CHASS(this->d.pin.config)((this->d.pin.config >> 28) & 0x3) == CORB_CD_INTERNAL0x1)
3608 printf("riser");
3609 else if (CORB_CD_LOC_CHASS(this->d.pin.config)((this->d.pin.config >> 28) & 0x3) == CORB_CD_LOC_OTHER0x3)
3610 printf("mobile-lid-internal");
3611 } else if (CORB_CD_LOC_GEO(this->d.pin.config)((this->d.pin.config >> 24) & 0xf) == CORB_CD_LOC_SPEC10x8) {
3612 if (CORB_CD_LOC_CHASS(this->d.pin.config)((this->d.pin.config >> 28) & 0x3) == CORB_CD_EXTERNAL0x0)
3613 printf("drive-bay");
3614 else if (CORB_CD_LOC_CHASS(this->d.pin.config)((this->d.pin.config >> 28) & 0x3) == CORB_CD_INTERNAL0x1)
3615 printf("hdmi");
3616 else if (CORB_CD_LOC_CHASS(this->d.pin.config)((this->d.pin.config >> 28) & 0x3) == CORB_CD_LOC_OTHER0x3)
3617 printf("mobile-lid-external");
3618 } else if (CORB_CD_LOC_GEO(this->d.pin.config)((this->d.pin.config >> 24) & 0xf) == CORB_CD_LOC_SPEC20x9) {
3619 if (CORB_CD_LOC_CHASS(this->d.pin.config)((this->d.pin.config >> 28) & 0x3) == CORB_CD_INTERNAL0x1)
3620 printf("atapi");
3621 } else
3622 printf("none");
3623 printf("\n");
3624}
3625
3626#else /* AZALIA_DEBUG */
3627
3628void
3629azalia_codec_print_audiofunc(const codec_t *this) {}
3630
3631void
3632azalia_codec_print_groups(const codec_t *this) {}
3633
3634void
3635azalia_widget_print_audio(const widget_t *this, const char *lead) {}
3636
3637void
3638azalia_widget_print_widget(const widget_t *w, const codec_t *codec) {}
3639
3640void
3641azalia_widget_print_pin(const widget_t *this) {}
3642
3643#endif /* AZALIA_DEBUG */
3644
3645/* ================================================================
3646 * Stream functions
3647 * ================================================================ */
3648
3649int
3650azalia_stream_init(stream_t *this, azalia_t *az, int regindex, int strnum,
3651 int dir)
3652{
3653 int err;
3654
3655 this->az = az;
3656 this->regbase = HDA_SD_BASE0x080 + regindex * HDA_SD_SIZE0x20;
3657 this->intr_bit = 1 << regindex;
3658 this->number = strnum;
3659 this->dir = dir;
3660
3661 /* setup BDL buffers */
3662 err = azalia_alloc_dmamem(az, sizeof(bdlist_entry_t) * HDA_BDL_MAX256,
3663 128, &this->bdlist);
3664 if (err) {
3665 printf("%s: can't allocate a BDL buffer\n", XNAME(az)((az)->dev.dv_xname));
3666 return err;
3667 }
3668 return 0;
3669}
3670
3671int
3672azalia_stream_reset(stream_t *this)
3673{
3674 int i;
3675 uint16_t ctl;
3676 uint8_t sts;
3677
3678 /* Make sure RUN bit is zero before resetting */
3679 ctl = STR_READ_2(this, CTL)(((this)->az->iot)->read_2(((this)->az->ioh), (
(this)->regbase + 0x00)))
;
3680 ctl &= ~HDA_SD_CTL_RUN0x0002;
3681 STR_WRITE_2(this, CTL, ctl)(((this)->az->iot)->write_2(((this)->az->ioh),
((this)->regbase + 0x00), (ctl)))
;
3682 DELAY(40)(*delay_func)(40);
3683
3684 /* Start reset and wait for chip to enter. */
3685 ctl = STR_READ_2(this, CTL)(((this)->az->iot)->read_2(((this)->az->ioh), (
(this)->regbase + 0x00)))
;
3686 STR_WRITE_2(this, CTL, ctl | HDA_SD_CTL_SRST)(((this)->az->iot)->write_2(((this)->az->ioh),
((this)->regbase + 0x00), (ctl | 0x0001)))
;
3687 for (i = 5000; i > 0; i--) {
3688 DELAY(10)(*delay_func)(10);
3689 ctl = STR_READ_2(this, CTL)(((this)->az->iot)->read_2(((this)->az->ioh), (
(this)->regbase + 0x00)))
;
3690 if (ctl & HDA_SD_CTL_SRST0x0001)
3691 break;
3692 }
3693 if (i == 0) {
3694 DPRINTF(("%s: stream reset failure 1\n", XNAME(this->az)))do {} while (0 );
3695 return -1;
3696 }
3697
3698 /* Clear reset and wait for chip to finish */
3699 STR_WRITE_2(this, CTL, ctl & ~HDA_SD_CTL_SRST)(((this)->az->iot)->write_2(((this)->az->ioh),
((this)->regbase + 0x00), (ctl & ~0x0001)))
;
3700 for (i = 5000; i > 0; i--) {
3701 DELAY(10)(*delay_func)(10);
3702 ctl = STR_READ_2(this, CTL)(((this)->az->iot)->read_2(((this)->az->ioh), (
(this)->regbase + 0x00)))
;
3703 if ((ctl & HDA_SD_CTL_SRST0x0001) == 0)
3704 break;
3705 }
3706 if (i == 0) {
3707 DPRINTF(("%s: stream reset failure 2\n", XNAME(this->az)))do {} while (0 );
3708 return -1;
3709 }
3710
3711 sts = STR_READ_1(this, STS)(((this)->az->iot)->read_1(((this)->az->ioh), (
(this)->regbase + 0x03)))
;
3712 sts |= HDA_SD_STS_DESE0x10 | HDA_SD_STS_FIFOE0x08 | HDA_SD_STS_BCIS0x04;
3713 STR_WRITE_1(this, STS, sts)(((this)->az->iot)->write_1(((this)->az->ioh),
((this)->regbase + 0x03), (sts)))
;
3714
3715 return (0);
3716}
3717
3718int
3719azalia_stream_start(stream_t *this)
3720{
3721 bdlist_entry_t *bdlist;
3722 bus_addr_t dmaaddr, dmaend;
3723 int err, index;
3724 uint32_t intctl;
3725 uint8_t ctl2;
3726
3727 err = azalia_stream_reset(this);
3728 if (err) {
3729 DPRINTF(("%s: stream reset failed\n", "azalia"))do {} while (0 );
3730 return err;
3731 }
3732
3733 STR_WRITE_4(this, BDPL, 0)(((this)->az->iot)->write_4(((this)->az->ioh),
((this)->regbase + 0x18), (0)))
;
3734 STR_WRITE_4(this, BDPU, 0)(((this)->az->iot)->write_4(((this)->az->ioh),
((this)->regbase + 0x1c), (0)))
;
3735
3736 /* setup BDL */
3737 dmaaddr = AZALIA_DMA_DMAADDR(&this->buffer)((&this->buffer)->map->dm_segs[0].ds_addr);
3738 dmaend = dmaaddr + this->bufsize;
3739 bdlist = (bdlist_entry_t*)this->bdlist.addr;
3740 for (index = 0; index < HDA_BDL_MAX256; index++) {
3741 bdlist[index].low = htole32(dmaaddr)((__uint32_t)(dmaaddr));
3742 bdlist[index].high = htole32(PTR_UPPER32(dmaaddr))((__uint32_t)(((uint64_t)(dmaaddr) >> 32)));
3743 bdlist[index].length = htole32(this->blk)((__uint32_t)(this->blk));
3744 bdlist[index].flags = htole32(BDLIST_ENTRY_IOC)((__uint32_t)(0x00000001));
3745 dmaaddr += this->blk;
3746 if (dmaaddr >= dmaend) {
3747 index++;
3748 break;
3749 }
3750 }
3751
3752 DPRINTFN(1, ("%s: size=%d fmt=0x%4.4x index=%d\n",do {} while (0 )
3753 __func__, this->bufsize, this->fmt, index))do {} while (0 );
3754
3755 dmaaddr = AZALIA_DMA_DMAADDR(&this->bdlist)((&this->bdlist)->map->dm_segs[0].ds_addr);
3756 STR_WRITE_4(this, BDPL, dmaaddr)(((this)->az->iot)->write_4(((this)->az->ioh),
((this)->regbase + 0x18), (dmaaddr)))
;
3757 STR_WRITE_4(this, BDPU, PTR_UPPER32(dmaaddr))(((this)->az->iot)->write_4(((this)->az->ioh),
((this)->regbase + 0x1c), (((uint64_t)(dmaaddr) >> 32
))))
;
3758 STR_WRITE_2(this, LVI, (index - 1) & HDA_SD_LVI_LVI)(((this)->az->iot)->write_2(((this)->az->ioh),
((this)->regbase + 0x0c), ((index - 1) & 0x00ff)))
;
3759 ctl2 = STR_READ_1(this, CTL2)(((this)->az->iot)->read_1(((this)->az->ioh), (
(this)->regbase + 0x02)))
;
3760 STR_WRITE_1(this, CTL2,(((this)->az->iot)->write_1(((this)->az->ioh),
((this)->regbase + 0x02), ((ctl2 & ~0xf0) | (this->
number << 4))))
3761 (ctl2 & ~HDA_SD_CTL2_STRM) | (this->number << HDA_SD_CTL2_STRM_SHIFT))(((this)->az->iot)->write_1(((this)->az->ioh),
((this)->regbase + 0x02), ((ctl2 & ~0xf0) | (this->
number << 4))))
;
3762 STR_WRITE_4(this, CBL, this->bufsize)(((this)->az->iot)->write_4(((this)->az->ioh),
((this)->regbase + 0x08), (this->bufsize)))
;
3763 STR_WRITE_2(this, FMT, this->fmt)(((this)->az->iot)->write_2(((this)->az->ioh),
((this)->regbase + 0x12), (this->fmt)))
;
3764
3765 err = azalia_codec_connect_stream(this);
3766 if (err)
3767 return EINVAL22;
3768
3769 intctl = AZ_READ_4(this->az, INTCTL)(((this->az)->iot)->read_4(((this->az)->ioh), (
0x020)))
;
3770 intctl |= this->intr_bit;
3771 AZ_WRITE_4(this->az, INTCTL, intctl)(((this->az)->iot)->write_4(((this->az)->ioh),
(0x020), (intctl)))
;
3772
3773 STR_WRITE_1(this, CTL, STR_READ_1(this, CTL) |(((this)->az->iot)->write_1(((this)->az->ioh),
((this)->regbase + 0x00), ((((this)->az->iot)->read_1
(((this)->az->ioh), ((this)->regbase + 0x00))) | 0x0010
| 0x0008 | 0x0004 | 0x0002)))
3774 HDA_SD_CTL_DEIE | HDA_SD_CTL_FEIE | HDA_SD_CTL_IOCE |(((this)->az->iot)->write_1(((this)->az->ioh),
((this)->regbase + 0x00), ((((this)->az->iot)->read_1
(((this)->az->ioh), ((this)->regbase + 0x00))) | 0x0010
| 0x0008 | 0x0004 | 0x0002)))
3775 HDA_SD_CTL_RUN)(((this)->az->iot)->write_1(((this)->az->ioh),
((this)->regbase + 0x00), ((((this)->az->iot)->read_1
(((this)->az->ioh), ((this)->regbase + 0x00))) | 0x0010
| 0x0008 | 0x0004 | 0x0002)))
;
3776 return (0);
3777}
3778
3779int
3780azalia_stream_halt(stream_t *this)
3781{
3782 uint16_t ctl;
3783
3784 ctl = STR_READ_2(this, CTL)(((this)->az->iot)->read_2(((this)->az->ioh), (
(this)->regbase + 0x00)))
;
3785 ctl &= ~(HDA_SD_CTL_DEIE0x0010 | HDA_SD_CTL_FEIE0x0008 | HDA_SD_CTL_IOCE0x0004 | HDA_SD_CTL_RUN0x0002);
3786 STR_WRITE_2(this, CTL, ctl)(((this)->az->iot)->write_2(((this)->az->ioh),
((this)->regbase + 0x00), (ctl)))
;
3787 AZ_WRITE_4(this->az, INTCTL,(((this->az)->iot)->write_4(((this->az)->ioh),
(0x020), ((((this->az)->iot)->read_4(((this->az)
->ioh), (0x020))) & ~this->intr_bit)))
3788 AZ_READ_4(this->az, INTCTL) & ~this->intr_bit)(((this->az)->iot)->write_4(((this->az)->ioh),
(0x020), ((((this->az)->iot)->read_4(((this->az)
->ioh), (0x020))) & ~this->intr_bit)))
;
3789 azalia_codec_disconnect_stream(this);
3790
3791 return (0);
3792}
3793
3794#define HDA_SD_STS_BITS"\20\3BCIS\4FIFOE\5DESE\6FIFORDY" "\20\3BCIS\4FIFOE\5DESE\6FIFORDY"
3795
3796int
3797azalia_stream_intr(stream_t *this)
3798{
3799 unsigned int lpib, fifos, hwpos, cnt;
3800 u_int8_t sts;
3801
3802 sts = STR_READ_1(this, STS)(((this)->az->iot)->read_1(((this)->az->ioh), (
(this)->regbase + 0x03)))
;
3803 STR_WRITE_1(this, STS, sts |(((this)->az->iot)->write_1(((this)->az->ioh),
((this)->regbase + 0x03), (sts | 0x10 | 0x08 | 0x04)))
3804 HDA_SD_STS_DESE | HDA_SD_STS_FIFOE | HDA_SD_STS_BCIS)(((this)->az->iot)->write_1(((this)->az->ioh),
((this)->regbase + 0x03), (sts | 0x10 | 0x08 | 0x04)))
;
3805
3806 if (sts & (HDA_SD_STS_DESE0x10 | HDA_SD_STS_FIFOE0x08))
3807 DPRINTF(("%s: stream %d: sts=%b\n", XNAME(this->az),do {} while (0 )
3808 this->number, sts, HDA_SD_STS_BITS))do {} while (0 );
3809
3810 if (sts & HDA_SD_STS_BCIS0x04) {
3811 lpib = STR_READ_4(this, LPIB)(((this)->az->iot)->read_4(((this)->az->ioh), (
(this)->regbase + 0x04)))
;
3812 fifos = STR_READ_2(this, FIFOS)(((this)->az->iot)->read_2(((this)->az->ioh), (
(this)->regbase + 0x10)))
;
3813 if (fifos & 1)
3814 fifos++;
3815 hwpos = lpib;
3816 if (this->dir == AUMODE_PLAY0x01)
3817 hwpos += fifos + 1;
3818 if (hwpos >= this->bufsize)
3819 hwpos -= this->bufsize;
3820 DPRINTFN(2, ("%s: stream %d, pos = %d -> %d, "do {} while (0 )
3821 "lpib = %u, fifos = %u\n", __func__,do {} while (0 )
3822 this->number, this->swpos, hwpos, lpib, fifos))do {} while (0 );
3823 cnt = 0;
3824 while (hwpos - this->swpos >= this->blk) {
3825 this->intr(this->intr_arg);
3826 this->swpos += this->blk;
3827 if (this->swpos == this->bufsize)
3828 this->swpos = 0;
3829 cnt++;
3830 }
3831 if (cnt != 1) {
3832 DPRINTF(("%s: stream %d: hwpos %u, %u intrs\n",do {} while (0 )
3833 __func__, this->number, this->swpos, cnt))do {} while (0 );
3834 }
3835 }
3836 return (1);
3837}
3838
3839/* ================================================================
3840 * MI audio entries
3841 * ================================================================ */
3842
3843int
3844azalia_open(void *v, int flags)
3845{
3846 azalia_t *az;
3847 codec_t *codec;
3848
3849 DPRINTFN(1, ("%s: flags=0x%x\n", __func__, flags))do {} while (0 );
3850 az = v;
3851 codec = &az->codecs[az->codecno];
3852 if ((flags & FWRITE0x0002) && codec->dacs.ngroups == 0)
3853 return ENODEV19;
3854 if ((flags & FREAD0x0001) && codec->adcs.ngroups == 0)
3855 return ENODEV19;
3856 codec->running++;
3857 return 0;
3858}
3859
3860void
3861azalia_close(void *v)
3862{
3863 azalia_t *az;
3864 codec_t *codec;
3865
3866 DPRINTFN(1, ("%s\n", __func__))do {} while (0 );
3867 az = v;
3868 codec = &az->codecs[az->codecno];
3869 codec->running--;
3870}
3871
3872int
3873azalia_match_format(codec_t *codec, int mode, audio_params_t *par)
3874{
3875 int i;
3876
3877 DPRINTFN(1, ("%s: mode=%d, want: enc=%d, prec=%d, chans=%d\n", __func__,do {} while (0 )
3878 mode, par->encoding, par->precision, par->channels))do {} while (0 );
3879
3880 for (i = 0; i < codec->nformats; i++) {
3881 if (mode != codec->formats[i].mode)
3882 continue;
3883 if (par->encoding != codec->formats[i].encoding)
3884 continue;
3885 if (par->precision != codec->formats[i].precision)
3886 continue;
3887 if (par->channels != codec->formats[i].channels)
3888 continue;
3889 break;
3890 }
3891
3892 DPRINTFN(1, ("%s: return: enc=%d, prec=%d, chans=%d\n", __func__,do {} while (0 )
3893 codec->formats[i].encoding, codec->formats[i].precision,do {} while (0 )
3894 codec->formats[i].channels))do {} while (0 );
3895
3896 return (i);
3897}
3898
3899int
3900azalia_set_params_sub(codec_t *codec, int mode, audio_params_t *par)
3901{
3902 int i, j;
3903 uint ochan, oenc, opre;
3904#ifdef AZALIA_DEBUG
3905 char *cmode = (mode == AUMODE_PLAY0x01) ? "play" : "record";
3906#endif
3907
3908 ochan = par->channels;
3909 oenc = par->encoding;
3910 opre = par->precision;
3911
3912 if ((mode == AUMODE_PLAY0x01 && codec->dacs.ngroups == 0) ||
3913 (mode == AUMODE_RECORD0x02 && codec->adcs.ngroups == 0))
3914 return 0;
3915
3916 i = azalia_match_format(codec, mode, par);
3917 if (i == codec->nformats && (par->precision != 16 || par->encoding !=
3918 AUDIO_ENCODING_SLINEAR_LE6)) {
3919 /* try with default encoding/precision */
3920 par->encoding = AUDIO_ENCODING_SLINEAR_LE6;
3921 par->precision = 16;
3922 i = azalia_match_format(codec, mode, par);
3923 }
3924 if (i == codec->nformats && par->channels != 2) {
3925 /* try with default channels */
3926 par->encoding = oenc;
3927 par->precision = opre;
3928 par->channels = 2;
3929 i = azalia_match_format(codec, mode, par);
3930 }
3931 /* try with default everything */
3932 if (i == codec->nformats) {
3933 par->encoding = AUDIO_ENCODING_SLINEAR_LE6;
3934 par->precision = 16;
3935 par->channels = 2;
3936 i = azalia_match_format(codec, mode, par);
3937 if (i == codec->nformats) {
3938 DPRINTF(("%s: can't find %s format %u/%u/%u\n",do {} while (0 )
3939 __func__, cmode, par->encoding,do {} while (0 )
3940 par->precision, par->channels))do {} while (0 );
3941 return EINVAL22;
3942 }
3943 }
3944 if (codec->formats[i].frequency_type == 0) {
3945 DPRINTF(("%s: matched %s format %d has 0 frequencies\n",do {} while (0 )
3946 __func__, cmode, i))do {} while (0 );
3947 return EINVAL22;
3948 }
3949
3950 for (j = 0; j < codec->formats[i].frequency_type; j++) {
3951 if (par->sample_rate != codec->formats[i].frequency[j])
3952 continue;
3953 break;
3954 }
3955 if (j == codec->formats[i].frequency_type) {
3956 /* try again with default */
3957 par->sample_rate = 48000;
3958 for (j = 0; j < codec->formats[i].frequency_type; j++) {
3959 if (par->sample_rate != codec->formats[i].frequency[j])
3960 continue;
3961 break;
3962 }
3963 if (j == codec->formats[i].frequency_type) {
3964 DPRINTF(("%s: can't find %s rate %lu\n",do {} while (0 )
3965 __func__, cmode, par->sample_rate))do {} while (0 );
3966 return EINVAL22;
3967 }
3968 }
3969 par->bps = AUDIO_BPS(par->precision)(par->precision) <= 8 ? 1 : ((par->precision) <= 16
? 2 : 4)
;
3970 par->msb = 1;
3971
3972 return (0);
3973}
3974
3975int
3976azalia_set_params(void *v, int smode, int umode, audio_params_t *p,
3977 audio_params_t *r)
3978{
3979 azalia_t *az;
3980 codec_t *codec;
3981 int ret;
3982
3983 az = v;
3984 codec = &az->codecs[az->codecno];
3985 if (codec->nformats == 0) {
3986 DPRINTF(("%s: codec has no formats\n", __func__))do {} while (0 );
3987 return EINVAL22;
3988 }
3989
3990 if (smode & AUMODE_RECORD0x02 && r != NULL((void *)0)) {
3991 ret = azalia_set_params_sub(codec, AUMODE_RECORD0x02, r);
3992 if (ret)
3993 return (ret);
3994 }
3995
3996 if (smode & AUMODE_PLAY0x01 && p != NULL((void *)0)) {
3997 ret = azalia_set_params_sub(codec, AUMODE_PLAY0x01, p);
3998 if (ret)
3999 return (ret);
4000 }
4001
4002 return (0);
4003}
4004
4005unsigned int
4006azalia_set_blksz(void *v, int mode,
4007 struct audio_params *p, struct audio_params *r, unsigned int blksz)
4008{
4009 int mult;
4010
4011 /* must be multiple of 128 bytes */
4012 mult = audio_blksz_bytes(mode, p, r, 128);
4013
4014 blksz -= blksz % mult;
4015 if (blksz == 0)
4016 blksz = mult;
4017
4018 return blksz;
4019}
4020
4021unsigned int
4022azalia_set_nblks(void *v, int mode,
4023 struct audio_params *params, unsigned int blksz, unsigned int nblks)
4024{
4025 /* number of blocks must be <= HDA_BDL_MAX */
4026 if (nblks > HDA_BDL_MAX256)
4027 nblks = HDA_BDL_MAX256;
4028
4029 return nblks;
4030}
4031
4032int
4033azalia_halt_output(void *v)
4034{
4035 azalia_t *az;
4036
4037 DPRINTFN(1, ("%s\n", __func__))do {} while (0 );
4038 az = v;
4039 return azalia_stream_halt(&az->pstream);
4040}
4041
4042int
4043azalia_halt_input(void *v)
4044{
4045 azalia_t *az;
4046
4047 DPRINTFN(1, ("%s\n", __func__))do {} while (0 );
4048 az = v;
4049 return azalia_stream_halt(&az->rstream);
4050}
4051
4052int
4053azalia_set_port(void *v, mixer_ctrl_t *mc)
4054{
4055 azalia_t *az;
4056 codec_t *co;
4057 const mixer_item_t *m;
4058
4059 az = v;
4060 co = &az->codecs[az->codecno];
4061 if (mc->dev < 0 || mc->dev >= co->nmixers)
4062 return EINVAL22;
4063
4064 m = &co->mixers[mc->dev];
4065 if (mc->type != m->devinfo.type)
4066 return EINVAL22;
4067
4068 return azalia_mixer_set(co, m->nid, m->target, mc);
4069}
4070
4071int
4072azalia_get_port(void *v, mixer_ctrl_t *mc)
4073{
4074 azalia_t *az;
4075 codec_t *co;
4076 const mixer_item_t *m;
4077
4078 az = v;
4079 co = &az->codecs[az->codecno];
4080 if (mc->dev < 0 || mc->dev >= co->nmixers)
4081 return EINVAL22;
4082
4083 m = &co->mixers[mc->dev];
4084 mc->type = m->devinfo.type;
4085
4086 return azalia_mixer_get(co, m->nid, m->target, mc);
4087}
4088
4089int
4090azalia_query_devinfo(void *v, mixer_devinfo_t *mdev)
4091{
4092 azalia_t *az;
4093 const codec_t *co;
4094
4095 az = v;
4096 co = &az->codecs[az->codecno];
4097 if (mdev->index < 0 || mdev->index >= co->nmixers)
4098 return ENXIO6;
4099 *mdev = co->mixers[mdev->index].devinfo;
4100 return 0;
4101}
4102
4103void *
4104azalia_allocm(void *v, int dir, size_t size, int pool, int flags)
4105{
4106 azalia_t *az;
4107 stream_t *stream;
4108 int err;
4109
4110 az = v;
4111 stream = dir == AUMODE_PLAY0x01 ? &az->pstream : &az->rstream;
4112 err = azalia_alloc_dmamem(az, size, 128, &stream->buffer);
4113 if (err) {
4114 printf("%s: allocm failed\n", az->dev.dv_xname);
4115 return NULL((void *)0);
4116 }
4117 return stream->buffer.addr;
4118}
4119
4120void
4121azalia_freem(void *v, void *addr, int pool)
4122{
4123 azalia_t *az;
4124 stream_t *stream;
4125
4126 az = v;
4127 if (addr == az->pstream.buffer.addr) {
4128 stream = &az->pstream;
4129 } else if (addr == az->rstream.buffer.addr) {
4130 stream = &az->rstream;
4131 } else {
4132 return;
4133 }
4134 azalia_free_dmamem(az, &stream->buffer);
4135}
4136
4137size_t
4138azalia_round_buffersize(void *v, int dir, size_t size)
4139{
4140 size &= ~0x7f; /* must be multiple of 128 */
4141 if (size <= 0)
4142 size = 128;
4143 return size;
4144}
4145
4146int
4147azalia_trigger_output(void *v, void *start, void *end, int blk,
4148 void (*intr)(void *), void *arg, audio_params_t *param)
4149{
4150 azalia_t *az;
4151 int err;
4152 uint16_t fmt;
4153
4154 az = v;
4155
4156 if (az->codecs[az->codecno].dacs.ngroups == 0) {
4157 DPRINTF(("%s: can't play without a DAC\n", __func__))do {} while (0 );
4158 return ENXIO6;
4159 }
4160
4161 err = azalia_params2fmt(param, &fmt);
4162 if (err)
4163 return(EINVAL22);
4164
4165 az->pstream.bufsize = (caddr_t)end - (caddr_t)start;
4166 az->pstream.blk = blk;
4167 az->pstream.fmt = fmt;
4168 az->pstream.intr = intr;
4169 az->pstream.intr_arg = arg;
4170 az->pstream.swpos = 0;
4171
4172 return azalia_stream_start(&az->pstream);
4173}
4174
4175int
4176azalia_trigger_input(void *v, void *start, void *end, int blk,
4177 void (*intr)(void *), void *arg, audio_params_t *param)
4178{
4179 azalia_t *az;
4180 int err;
4181 uint16_t fmt;
4182
4183 DPRINTFN(1, ("%s: this=%p start=%p end=%p blk=%d {enc=%u %uch %ubit %luHz}\n",do {} while (0 )
4184 __func__, v, start, end, blk, param->encoding, param->channels,do {} while (0 )
4185 param->precision, param->sample_rate))do {} while (0 );
4186
4187 az = v;
4188
4189 if (az->codecs[az->codecno].adcs.ngroups == 0) {
4190 DPRINTF(("%s: can't record without an ADC\n", __func__))do {} while (0 );
4191 return ENXIO6;
4192 }
4193
4194 err = azalia_params2fmt(param, &fmt);
4195 if (err)
4196 return(EINVAL22);
4197
4198 az->rstream.bufsize = (caddr_t)end - (caddr_t)start;
4199 az->rstream.blk = blk;
4200 az->rstream.fmt = fmt;
4201 az->rstream.intr = intr;
4202 az->rstream.intr_arg = arg;
4203 az->rstream.swpos = 0;
4204
4205 return azalia_stream_start(&az->rstream);
4206}
4207
4208/* --------------------------------
4209 * helpers for MI audio functions
4210 * -------------------------------- */
4211int
4212azalia_params2fmt(const audio_params_t *param, uint16_t *fmt)
4213{
4214 uint16_t ret;
4215
4216 ret = 0;
4217 if (param->channels > HDA_MAX_CHANNELS16) {
4218 printf("%s: too many channels: %u\n", __func__,
4219 param->channels);
4220 return EINVAL22;
4221 }
4222
4223 DPRINTFN(1, ("%s: prec=%d, chan=%d, rate=%ld\n", __func__,do {} while (0 )
4224 param->precision, param->channels, param->sample_rate))do {} while (0 );
4225
4226 /* XXX: can channels be >2 ? */
4227 ret |= param->channels - 1;
4228
4229 switch (param->precision) {
4230 case 8:
4231 ret |= HDA_SD_FMT_BITS_8_160x0000;
4232 break;
4233 case 16:
4234 ret |= HDA_SD_FMT_BITS_16_160x0010;
4235 break;
4236 case 20:
4237 ret |= HDA_SD_FMT_BITS_20_320x0020;
4238 break;
4239 case 24:
4240 ret |= HDA_SD_FMT_BITS_24_320x0030;
4241 break;
4242 case 32:
4243 ret |= HDA_SD_FMT_BITS_32_320x0040;
4244 break;
4245 }
4246
4247 switch (param->sample_rate) {
4248 default:
4249 case 384000:
4250 printf("%s: invalid sample_rate: %lu\n", __func__,
4251 param->sample_rate);
4252 return EINVAL22;
4253 case 192000:
4254 ret |= HDA_SD_FMT_BASE_480x0000 | HDA_SD_FMT_MULT_X40x1800 | HDA_SD_FMT_DIV_BY10x0000;
4255 break;
4256 case 176400:
4257 ret |= HDA_SD_FMT_BASE_440x4000 | HDA_SD_FMT_MULT_X40x1800 | HDA_SD_FMT_DIV_BY10x0000;
4258 break;
4259 case 96000:
4260 ret |= HDA_SD_FMT_BASE_480x0000 | HDA_SD_FMT_MULT_X20x0800 | HDA_SD_FMT_DIV_BY10x0000;
4261 break;
4262 case 88200:
4263 ret |= HDA_SD_FMT_BASE_440x4000 | HDA_SD_FMT_MULT_X20x0800 | HDA_SD_FMT_DIV_BY10x0000;
4264 break;
4265 case 48000:
4266 ret |= HDA_SD_FMT_BASE_480x0000 | HDA_SD_FMT_MULT_X10x0000 | HDA_SD_FMT_DIV_BY10x0000;
4267 break;
4268 case 44100:
4269 ret |= HDA_SD_FMT_BASE_440x4000 | HDA_SD_FMT_MULT_X10x0000 | HDA_SD_FMT_DIV_BY10x0000;
4270 break;
4271 case 32000:
4272 ret |= HDA_SD_FMT_BASE_480x0000 | HDA_SD_FMT_MULT_X20x0800 | HDA_SD_FMT_DIV_BY30x0200;
4273 break;
4274 case 22050:
4275 ret |= HDA_SD_FMT_BASE_440x4000 | HDA_SD_FMT_MULT_X10x0000 | HDA_SD_FMT_DIV_BY20x0100;
4276 break;
4277 case 16000:
4278 ret |= HDA_SD_FMT_BASE_480x0000 | HDA_SD_FMT_MULT_X10x0000 | HDA_SD_FMT_DIV_BY30x0200;
4279 break;
4280 case 11025:
4281 ret |= HDA_SD_FMT_BASE_440x4000 | HDA_SD_FMT_MULT_X10x0000 | HDA_SD_FMT_DIV_BY40x0300;
4282 break;
4283 case 8000:
4284 ret |= HDA_SD_FMT_BASE_480x0000 | HDA_SD_FMT_MULT_X10x0000 | HDA_SD_FMT_DIV_BY60x0500;
4285 break;
4286 }
4287 *fmt = ret;
4288 return 0;
4289}