Bug Summary

File:dev/pci/azalia.c
Warning:line 2570, column 5
Value stored to 'cap' is never read

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;
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;
Value stored to 'cap' is never read
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}