Bug Summary

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

Annotated Source Code

Press '?' to see keyboard shortcuts

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