Bug Summary

File:dev/pci/azalia.c
Warning:line 1914, column 3
Value stored to 'conv' is never read

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