hdafg.c revision 1.2.2.3 1 1.2.2.3 skrll /* $NetBSD: hdafg.c,v 1.2.2.3 2015/09/22 12:05:57 skrll Exp $ */
2 1.2.2.2 skrll
3 1.2.2.2 skrll /*
4 1.2.2.2 skrll * Copyright (c) 2009 Precedence Technologies Ltd <support (at) precedence.co.uk>
5 1.2.2.2 skrll * Copyright (c) 2009-2011 Jared D. McNeill <jmcneill (at) invisible.ca>
6 1.2.2.2 skrll * All rights reserved.
7 1.2.2.2 skrll *
8 1.2.2.2 skrll * This code is derived from software contributed to The NetBSD Foundation
9 1.2.2.2 skrll * by Precedence Technologies Ltd
10 1.2.2.2 skrll *
11 1.2.2.2 skrll * Redistribution and use in source and binary forms, with or without
12 1.2.2.2 skrll * modification, are permitted provided that the following conditions
13 1.2.2.2 skrll * are met:
14 1.2.2.2 skrll * 1. Redistributions of source code must retain the above copyright
15 1.2.2.2 skrll * notice, this list of conditions and the following disclaimer.
16 1.2.2.2 skrll * 2. The name of the author may not be used to endorse or promote products
17 1.2.2.2 skrll * derived from this software without specific prior written permission.
18 1.2.2.2 skrll *
19 1.2.2.2 skrll * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20 1.2.2.2 skrll * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21 1.2.2.2 skrll * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22 1.2.2.2 skrll * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23 1.2.2.2 skrll * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
24 1.2.2.2 skrll * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 1.2.2.2 skrll * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
26 1.2.2.2 skrll * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27 1.2.2.2 skrll * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 1.2.2.2 skrll * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 1.2.2.2 skrll * SUCH DAMAGE.
30 1.2.2.2 skrll */
31 1.2.2.2 skrll
32 1.2.2.2 skrll /*
33 1.2.2.2 skrll * Widget parsing from FreeBSD hdac.c:
34 1.2.2.2 skrll *
35 1.2.2.2 skrll * Copyright (c) 2006 Stephane E. Potvin <sepotvin (at) videotron.ca>
36 1.2.2.2 skrll * Copyright (c) 2006 Ariff Abdullah <ariff (at) FreeBSD.org>
37 1.2.2.2 skrll * Copyright (c) 2008 Alexander Motin <mav (at) FreeBSD.org>
38 1.2.2.2 skrll * All rights reserved.
39 1.2.2.2 skrll *
40 1.2.2.2 skrll * Redistribution and use in source and binary forms, with or without
41 1.2.2.2 skrll * modification, are permitted provided that the following conditions
42 1.2.2.2 skrll * are met:
43 1.2.2.2 skrll * 1. Redistributions of source code must retain the above copyright
44 1.2.2.2 skrll * notice, this list of conditions and the following disclaimer.
45 1.2.2.2 skrll * 2. Redistributions in binary form must reproduce the above copyright
46 1.2.2.2 skrll * notice, this list of conditions and the following disclaimer in the
47 1.2.2.2 skrll * documentation and/or other materials provided with the distribution.
48 1.2.2.2 skrll *
49 1.2.2.2 skrll * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
50 1.2.2.2 skrll * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
51 1.2.2.2 skrll * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
52 1.2.2.2 skrll * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
53 1.2.2.2 skrll * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
54 1.2.2.2 skrll * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
55 1.2.2.2 skrll * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
56 1.2.2.2 skrll * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
57 1.2.2.2 skrll * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
58 1.2.2.2 skrll * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
59 1.2.2.2 skrll * SUCH DAMAGE.
60 1.2.2.2 skrll */
61 1.2.2.2 skrll
62 1.2.2.2 skrll #include <sys/cdefs.h>
63 1.2.2.3 skrll __KERNEL_RCSID(0, "$NetBSD: hdafg.c,v 1.2.2.3 2015/09/22 12:05:57 skrll Exp $");
64 1.2.2.2 skrll
65 1.2.2.2 skrll #include <sys/types.h>
66 1.2.2.2 skrll #include <sys/param.h>
67 1.2.2.2 skrll #include <sys/systm.h>
68 1.2.2.2 skrll #include <sys/kernel.h>
69 1.2.2.2 skrll #include <sys/device.h>
70 1.2.2.2 skrll #include <sys/conf.h>
71 1.2.2.2 skrll #include <sys/bus.h>
72 1.2.2.2 skrll #include <sys/kmem.h>
73 1.2.2.2 skrll #include <sys/module.h>
74 1.2.2.2 skrll
75 1.2.2.2 skrll #include <sys/audioio.h>
76 1.2.2.2 skrll #include <dev/audio_if.h>
77 1.2.2.2 skrll #include <dev/auconv.h>
78 1.2.2.2 skrll
79 1.2.2.2 skrll #ifdef _KERNEL_OPT
80 1.2.2.2 skrll #include "opt_hdaudio.h"
81 1.2.2.2 skrll #endif
82 1.2.2.2 skrll
83 1.2.2.2 skrll #include "hdaudiovar.h"
84 1.2.2.2 skrll #include "hdaudioreg.h"
85 1.2.2.2 skrll #include "hdaudio_mixer.h"
86 1.2.2.2 skrll #include "hdaudioio.h"
87 1.2.2.2 skrll #include "hdaudio_verbose.h"
88 1.2.2.2 skrll #include "hdaudiodevs.h"
89 1.2.2.2 skrll #include "hdafg_dd.h"
90 1.2.2.2 skrll #include "hdmireg.h"
91 1.2.2.2 skrll
92 1.2.2.2 skrll #ifndef AUFMT_SURROUND_7_1
93 1.2.2.2 skrll #define AUFMT_SURROUND_7_1 (AUFMT_DOLBY_5_1|AUFMT_SIDE_LEFT|AUFMT_SIDE_RIGHT)
94 1.2.2.2 skrll #endif
95 1.2.2.2 skrll
96 1.2.2.2 skrll #if defined(HDAFG_DEBUG)
97 1.2.2.2 skrll static int hdafg_debug = HDAFG_DEBUG;
98 1.2.2.2 skrll #else
99 1.2.2.2 skrll static int hdafg_debug = 0;
100 1.2.2.2 skrll #endif
101 1.2.2.2 skrll
102 1.2.2.2 skrll #define hda_debug(sc, ...) \
103 1.2.2.2 skrll if (hdafg_debug) hda_print(sc, __VA_ARGS__)
104 1.2.2.2 skrll #define hda_debug1(sc, ...) \
105 1.2.2.2 skrll if (hdafg_debug) hda_print1(sc, __VA_ARGS__)
106 1.2.2.2 skrll
107 1.2.2.2 skrll #define HDAUDIO_MIXER_CLASS_OUTPUTS 0
108 1.2.2.2 skrll #define HDAUDIO_MIXER_CLASS_INPUTS 1
109 1.2.2.2 skrll #define HDAUDIO_MIXER_CLASS_RECORD 2
110 1.2.2.2 skrll #define HDAUDIO_MIXER_CLASS_LAST HDAUDIO_MIXER_CLASS_RECORD
111 1.2.2.2 skrll
112 1.2.2.2 skrll #define HDAUDIO_GPIO_MASK 0
113 1.2.2.2 skrll #define HDAUDIO_GPIO_DIR 1
114 1.2.2.2 skrll #define HDAUDIO_GPIO_DATA 2
115 1.2.2.2 skrll
116 1.2.2.2 skrll #define HDAUDIO_UNSOLTAG_EVENT_HP 0x01
117 1.2.2.2 skrll #define HDAUDIO_UNSOLTAG_EVENT_DD 0x02
118 1.2.2.2 skrll
119 1.2.2.2 skrll #define HDAUDIO_HP_SENSE_PERIOD hz
120 1.2.2.2 skrll
121 1.2.2.2 skrll const u_int hdafg_possible_rates[] = {
122 1.2.2.2 skrll 8000, 11025, 16000, 22050, 32000, 44100,
123 1.2.2.2 skrll 48000, 88200, 96000, 176500, 192000, /* 384000, */
124 1.2.2.2 skrll };
125 1.2.2.2 skrll
126 1.2.2.2 skrll static const char *hdafg_mixer_names[] = HDAUDIO_DEVICE_NAMES;
127 1.2.2.2 skrll
128 1.2.2.2 skrll static const char *hdafg_port_connectivity[] = {
129 1.2.2.2 skrll "Jack",
130 1.2.2.2 skrll "Unconnected",
131 1.2.2.2 skrll "Built-In",
132 1.2.2.2 skrll "Jack & Built-In"
133 1.2.2.2 skrll };
134 1.2.2.2 skrll static const char *hdafg_default_device[] = {
135 1.2.2.2 skrll "Line Out",
136 1.2.2.2 skrll "Speaker",
137 1.2.2.2 skrll "HP Out",
138 1.2.2.2 skrll "CD",
139 1.2.2.2 skrll "SPDIF Out",
140 1.2.2.2 skrll "Digital Out",
141 1.2.2.2 skrll "Modem Line Side",
142 1.2.2.2 skrll "Modem Handset Side",
143 1.2.2.2 skrll "Line In",
144 1.2.2.2 skrll "AUX",
145 1.2.2.2 skrll "Mic In",
146 1.2.2.2 skrll "Telephony",
147 1.2.2.2 skrll "SPDIF In",
148 1.2.2.2 skrll "Digital In",
149 1.2.2.2 skrll "Reserved",
150 1.2.2.2 skrll "Other"
151 1.2.2.2 skrll };
152 1.2.2.2 skrll static const char *hdafg_color[] = {
153 1.2.2.2 skrll "Unknown",
154 1.2.2.2 skrll "Black",
155 1.2.2.2 skrll "Grey",
156 1.2.2.2 skrll "Blue",
157 1.2.2.2 skrll "Green",
158 1.2.2.2 skrll "Red",
159 1.2.2.2 skrll "Orange",
160 1.2.2.2 skrll "Yellow",
161 1.2.2.2 skrll "Purple",
162 1.2.2.2 skrll "Pink",
163 1.2.2.2 skrll "ReservedA",
164 1.2.2.2 skrll "ReservedB",
165 1.2.2.2 skrll "ReservedC",
166 1.2.2.2 skrll "ReservedD",
167 1.2.2.2 skrll "White",
168 1.2.2.2 skrll "Other"
169 1.2.2.2 skrll };
170 1.2.2.2 skrll
171 1.2.2.2 skrll #define HDAUDIO_MAXFORMATS 24
172 1.2.2.2 skrll #define HDAUDIO_MAXCONNECTIONS 32
173 1.2.2.2 skrll #define HDAUDIO_MAXPINS 16
174 1.2.2.2 skrll #define HDAUDIO_PARSE_MAXDEPTH 10
175 1.2.2.2 skrll
176 1.2.2.2 skrll #define HDAUDIO_AMP_VOL_DEFAULT (-1)
177 1.2.2.2 skrll #define HDAUDIO_AMP_MUTE_DEFAULT (0xffffffff)
178 1.2.2.2 skrll #define HDAUDIO_AMP_MUTE_NONE 0
179 1.2.2.2 skrll #define HDAUDIO_AMP_MUTE_LEFT (1 << 0)
180 1.2.2.2 skrll #define HDAUDIO_AMP_MUTE_RIGHT (1 << 1)
181 1.2.2.2 skrll #define HDAUDIO_AMP_MUTE_ALL (HDAUDIO_AMP_MUTE_LEFT | HDAUDIO_AMP_MUTE_RIGHT)
182 1.2.2.2 skrll #define HDAUDIO_AMP_LEFT_MUTED(x) ((x) & HDAUDIO_AMP_MUTE_LEFT)
183 1.2.2.2 skrll #define HDAUDIO_AMP_RIGHT_MUTED(x) (((x) & HDAUDIO_AMP_MUTE_RIGHT) >> 1)
184 1.2.2.2 skrll
185 1.2.2.2 skrll #define HDAUDIO_ADC_MONITOR 1
186 1.2.2.2 skrll
187 1.2.2.2 skrll enum hdaudio_pindir {
188 1.2.2.2 skrll HDAUDIO_PINDIR_NONE = 0,
189 1.2.2.2 skrll HDAUDIO_PINDIR_OUT = 1,
190 1.2.2.2 skrll HDAUDIO_PINDIR_IN = 2,
191 1.2.2.2 skrll HDAUDIO_PINDIR_INOUT = 3,
192 1.2.2.2 skrll };
193 1.2.2.2 skrll
194 1.2.2.2 skrll #define hda_get_param(sc, cop) \
195 1.2.2.2 skrll hdaudio_command((sc)->sc_codec, (sc)->sc_nid, \
196 1.2.2.2 skrll CORB_GET_PARAMETER, COP_##cop)
197 1.2.2.2 skrll #define hda_get_wparam(w, cop) \
198 1.2.2.2 skrll hdaudio_command((w)->w_afg->sc_codec, (w)->w_nid, \
199 1.2.2.2 skrll CORB_GET_PARAMETER, COP_##cop)
200 1.2.2.2 skrll
201 1.2.2.2 skrll struct hdaudio_assoc {
202 1.2.2.2 skrll bool as_enable;
203 1.2.2.2 skrll bool as_activated;
204 1.2.2.2 skrll u_char as_index;
205 1.2.2.2 skrll enum hdaudio_pindir as_dir;
206 1.2.2.2 skrll u_char as_pincnt;
207 1.2.2.2 skrll u_char as_fakeredir;
208 1.2.2.2 skrll int as_digital;
209 1.2.2.2 skrll #define HDAFG_AS_ANALOG 0
210 1.2.2.2 skrll #define HDAFG_AS_SPDIF 1
211 1.2.2.2 skrll #define HDAFG_AS_HDMI 2
212 1.2.2.2 skrll #define HDAFG_AS_DISPLAYPORT 3
213 1.2.2.2 skrll bool as_displaydev;
214 1.2.2.2 skrll int as_hpredir;
215 1.2.2.2 skrll int as_pins[HDAUDIO_MAXPINS];
216 1.2.2.2 skrll int as_dacs[HDAUDIO_MAXPINS];
217 1.2.2.2 skrll };
218 1.2.2.2 skrll
219 1.2.2.2 skrll struct hdaudio_widget {
220 1.2.2.2 skrll struct hdafg_softc *w_afg;
221 1.2.2.2 skrll char w_name[32];
222 1.2.2.2 skrll int w_nid;
223 1.2.2.2 skrll bool w_enable;
224 1.2.2.2 skrll bool w_waspin;
225 1.2.2.2 skrll int w_selconn;
226 1.2.2.2 skrll int w_bindas;
227 1.2.2.2 skrll int w_bindseqmask;
228 1.2.2.2 skrll int w_pflags;
229 1.2.2.2 skrll int w_audiodev;
230 1.2.2.2 skrll uint32_t w_audiomask;
231 1.2.2.2 skrll
232 1.2.2.2 skrll int w_nconns;
233 1.2.2.2 skrll int w_conns[HDAUDIO_MAXCONNECTIONS];
234 1.2.2.2 skrll bool w_connsenable[HDAUDIO_MAXCONNECTIONS];
235 1.2.2.2 skrll
236 1.2.2.2 skrll int w_type;
237 1.2.2.2 skrll struct {
238 1.2.2.2 skrll uint32_t aw_cap;
239 1.2.2.2 skrll uint32_t pcm_size_rate;
240 1.2.2.2 skrll uint32_t stream_format;
241 1.2.2.2 skrll uint32_t outamp_cap;
242 1.2.2.2 skrll uint32_t inamp_cap;
243 1.2.2.2 skrll uint32_t eapdbtl;
244 1.2.2.2 skrll } w_p;
245 1.2.2.2 skrll struct {
246 1.2.2.2 skrll uint32_t config;
247 1.2.2.2 skrll uint32_t biosconfig;
248 1.2.2.2 skrll uint32_t cap;
249 1.2.2.2 skrll uint32_t ctrl;
250 1.2.2.2 skrll } w_pin;
251 1.2.2.2 skrll };
252 1.2.2.2 skrll
253 1.2.2.2 skrll struct hdaudio_control {
254 1.2.2.2 skrll struct hdaudio_widget *ctl_widget, *ctl_childwidget;
255 1.2.2.2 skrll bool ctl_enable;
256 1.2.2.2 skrll int ctl_index;
257 1.2.2.2 skrll enum hdaudio_pindir ctl_dir, ctl_ndir;
258 1.2.2.2 skrll int ctl_mute, ctl_step, ctl_size, ctl_offset;
259 1.2.2.2 skrll int ctl_left, ctl_right, ctl_forcemute;
260 1.2.2.2 skrll uint32_t ctl_muted;
261 1.2.2.2 skrll uint32_t ctl_audiomask, ctl_paudiomask;
262 1.2.2.2 skrll };
263 1.2.2.2 skrll
264 1.2.2.2 skrll #define HDAUDIO_CONTROL_GIVE(ctl) ((ctl)->ctl_step ? 1 : 0)
265 1.2.2.2 skrll
266 1.2.2.2 skrll struct hdaudio_mixer {
267 1.2.2.2 skrll struct hdaudio_control *mx_ctl;
268 1.2.2.2 skrll mixer_devinfo_t mx_di;
269 1.2.2.2 skrll };
270 1.2.2.2 skrll
271 1.2.2.2 skrll struct hdaudio_audiodev {
272 1.2.2.2 skrll struct hdafg_softc *ad_sc;
273 1.2.2.2 skrll device_t ad_audiodev;
274 1.2.2.2 skrll struct audio_encoding_set *ad_encodings;
275 1.2.2.2 skrll int ad_nformats;
276 1.2.2.2 skrll struct audio_format ad_formats[HDAUDIO_MAXFORMATS];
277 1.2.2.2 skrll
278 1.2.2.2 skrll struct hdaudio_stream *ad_playback;
279 1.2.2.2 skrll void (*ad_playbackintr)(void *);
280 1.2.2.2 skrll void *ad_playbackintrarg;
281 1.2.2.2 skrll int ad_playbacknid[HDAUDIO_MAXPINS];
282 1.2.2.2 skrll struct hdaudio_assoc *ad_playbackassoc;
283 1.2.2.2 skrll struct hdaudio_stream *ad_capture;
284 1.2.2.2 skrll void (*ad_captureintr)(void *);
285 1.2.2.2 skrll void *ad_captureintrarg;
286 1.2.2.2 skrll int ad_capturenid[HDAUDIO_MAXPINS];
287 1.2.2.2 skrll struct hdaudio_assoc *ad_captureassoc;
288 1.2.2.2 skrll };
289 1.2.2.2 skrll
290 1.2.2.2 skrll struct hdafg_softc {
291 1.2.2.2 skrll device_t sc_dev;
292 1.2.2.2 skrll kmutex_t sc_lock;
293 1.2.2.2 skrll kmutex_t sc_intr_lock;
294 1.2.2.2 skrll struct hdaudio_softc *sc_host;
295 1.2.2.2 skrll struct hdaudio_codec *sc_codec;
296 1.2.2.2 skrll struct hdaudio_function_group *sc_fg;
297 1.2.2.2 skrll int sc_nid;
298 1.2.2.2 skrll uint16_t sc_vendor, sc_product;
299 1.2.2.2 skrll
300 1.2.2.2 skrll prop_array_t sc_config;
301 1.2.2.2 skrll
302 1.2.2.2 skrll int sc_startnode, sc_endnode;
303 1.2.2.2 skrll int sc_nwidgets;
304 1.2.2.2 skrll struct hdaudio_widget *sc_widgets;
305 1.2.2.2 skrll int sc_nassocs;
306 1.2.2.2 skrll struct hdaudio_assoc *sc_assocs;
307 1.2.2.2 skrll int sc_nctls;
308 1.2.2.2 skrll struct hdaudio_control *sc_ctls;
309 1.2.2.2 skrll int sc_nmixers;
310 1.2.2.2 skrll struct hdaudio_mixer *sc_mixers;
311 1.2.2.2 skrll bool sc_has_beepgen;
312 1.2.2.2 skrll
313 1.2.2.2 skrll int sc_pchan, sc_rchan;
314 1.2.2.2 skrll audio_params_t sc_pparam, sc_rparam;
315 1.2.2.2 skrll
316 1.2.2.2 skrll struct callout sc_jack_callout;
317 1.2.2.2 skrll bool sc_jack_polling;
318 1.2.2.2 skrll
319 1.2.2.2 skrll struct {
320 1.2.2.2 skrll uint32_t afg_cap;
321 1.2.2.2 skrll uint32_t pcm_size_rate;
322 1.2.2.2 skrll uint32_t stream_format;
323 1.2.2.2 skrll uint32_t outamp_cap;
324 1.2.2.2 skrll uint32_t inamp_cap;
325 1.2.2.2 skrll uint32_t power_states;
326 1.2.2.2 skrll uint32_t gpio_cnt;
327 1.2.2.2 skrll } sc_p;
328 1.2.2.2 skrll
329 1.2.2.2 skrll struct hdaudio_audiodev sc_audiodev;
330 1.2.2.3 skrll
331 1.2.2.3 skrll uint16_t sc_fixed_rate;
332 1.2.2.2 skrll };
333 1.2.2.2 skrll
334 1.2.2.2 skrll static int hdafg_match(device_t, cfdata_t, void *);
335 1.2.2.2 skrll static void hdafg_attach(device_t, device_t, void *);
336 1.2.2.2 skrll static int hdafg_detach(device_t, int);
337 1.2.2.2 skrll static void hdafg_childdet(device_t, device_t);
338 1.2.2.2 skrll static bool hdafg_suspend(device_t, const pmf_qual_t *);
339 1.2.2.2 skrll static bool hdafg_resume(device_t, const pmf_qual_t *);
340 1.2.2.2 skrll
341 1.2.2.2 skrll static int hdafg_unsol(device_t, uint8_t);
342 1.2.2.2 skrll static int hdafg_widget_info(void *, prop_dictionary_t,
343 1.2.2.2 skrll prop_dictionary_t);
344 1.2.2.2 skrll static int hdafg_codec_info(void *, prop_dictionary_t,
345 1.2.2.2 skrll prop_dictionary_t);
346 1.2.2.2 skrll static void hdafg_enable_analog_beep(struct hdafg_softc *);
347 1.2.2.2 skrll
348 1.2.2.2 skrll CFATTACH_DECL2_NEW(
349 1.2.2.2 skrll hdafg,
350 1.2.2.2 skrll sizeof(struct hdafg_softc),
351 1.2.2.2 skrll hdafg_match,
352 1.2.2.2 skrll hdafg_attach,
353 1.2.2.2 skrll hdafg_detach,
354 1.2.2.2 skrll NULL,
355 1.2.2.2 skrll NULL,
356 1.2.2.2 skrll hdafg_childdet
357 1.2.2.2 skrll );
358 1.2.2.2 skrll
359 1.2.2.2 skrll static int hdafg_query_encoding(void *, struct audio_encoding *);
360 1.2.2.2 skrll static int hdafg_set_params(void *, int, int,
361 1.2.2.2 skrll audio_params_t *,
362 1.2.2.2 skrll audio_params_t *,
363 1.2.2.2 skrll stream_filter_list_t *,
364 1.2.2.2 skrll stream_filter_list_t *);
365 1.2.2.2 skrll static int hdafg_round_blocksize(void *, int, int,
366 1.2.2.2 skrll const audio_params_t *);
367 1.2.2.2 skrll static int hdafg_commit_settings(void *);
368 1.2.2.2 skrll static int hdafg_halt_output(void *);
369 1.2.2.2 skrll static int hdafg_halt_input(void *);
370 1.2.2.2 skrll static int hdafg_set_port(void *, mixer_ctrl_t *);
371 1.2.2.2 skrll static int hdafg_get_port(void *, mixer_ctrl_t *);
372 1.2.2.2 skrll static int hdafg_query_devinfo(void *, mixer_devinfo_t *);
373 1.2.2.2 skrll static void * hdafg_allocm(void *, int, size_t);
374 1.2.2.2 skrll static void hdafg_freem(void *, void *, size_t);
375 1.2.2.2 skrll static int hdafg_getdev(void *, struct audio_device *);
376 1.2.2.2 skrll static size_t hdafg_round_buffersize(void *, int, size_t);
377 1.2.2.2 skrll static paddr_t hdafg_mappage(void *, void *, off_t, int);
378 1.2.2.2 skrll static int hdafg_get_props(void *);
379 1.2.2.2 skrll static int hdafg_trigger_output(void *, void *, void *, int,
380 1.2.2.2 skrll void (*)(void *), void *,
381 1.2.2.2 skrll const audio_params_t *);
382 1.2.2.2 skrll static int hdafg_trigger_input(void *, void *, void *, int,
383 1.2.2.2 skrll void (*)(void *), void *,
384 1.2.2.2 skrll const audio_params_t *);
385 1.2.2.2 skrll static void hdafg_get_locks(void *, kmutex_t **, kmutex_t **);
386 1.2.2.2 skrll
387 1.2.2.2 skrll static const struct audio_hw_if hdafg_hw_if = {
388 1.2.2.2 skrll .query_encoding = hdafg_query_encoding,
389 1.2.2.2 skrll .set_params = hdafg_set_params,
390 1.2.2.2 skrll .round_blocksize = hdafg_round_blocksize,
391 1.2.2.2 skrll .commit_settings = hdafg_commit_settings,
392 1.2.2.2 skrll .halt_output = hdafg_halt_output,
393 1.2.2.2 skrll .halt_input = hdafg_halt_input,
394 1.2.2.2 skrll .getdev = hdafg_getdev,
395 1.2.2.2 skrll .set_port = hdafg_set_port,
396 1.2.2.2 skrll .get_port = hdafg_get_port,
397 1.2.2.2 skrll .query_devinfo = hdafg_query_devinfo,
398 1.2.2.2 skrll .allocm = hdafg_allocm,
399 1.2.2.2 skrll .freem = hdafg_freem,
400 1.2.2.2 skrll .round_buffersize = hdafg_round_buffersize,
401 1.2.2.2 skrll .mappage = hdafg_mappage,
402 1.2.2.2 skrll .get_props = hdafg_get_props,
403 1.2.2.2 skrll .trigger_output = hdafg_trigger_output,
404 1.2.2.2 skrll .trigger_input = hdafg_trigger_input,
405 1.2.2.2 skrll .get_locks = hdafg_get_locks,
406 1.2.2.2 skrll };
407 1.2.2.2 skrll
408 1.2.2.2 skrll static int
409 1.2.2.2 skrll hdafg_append_formats(struct hdaudio_audiodev *ad,
410 1.2.2.2 skrll const struct audio_format *format)
411 1.2.2.2 skrll {
412 1.2.2.2 skrll if (ad->ad_nformats + 1 >= HDAUDIO_MAXFORMATS) {
413 1.2.2.2 skrll hda_print1(ad->ad_sc, "[ENOMEM] ");
414 1.2.2.2 skrll return ENOMEM;
415 1.2.2.2 skrll }
416 1.2.2.2 skrll ad->ad_formats[ad->ad_nformats++] = *format;
417 1.2.2.2 skrll
418 1.2.2.2 skrll return 0;
419 1.2.2.2 skrll }
420 1.2.2.2 skrll
421 1.2.2.2 skrll static struct hdaudio_widget *
422 1.2.2.2 skrll hdafg_widget_lookup(struct hdafg_softc *sc, int nid)
423 1.2.2.2 skrll {
424 1.2.2.2 skrll if (sc->sc_widgets == NULL || sc->sc_nwidgets == 0) {
425 1.2.2.2 skrll hda_error(sc, "lookup failed; widgets %p nwidgets %d\n",
426 1.2.2.2 skrll sc->sc_widgets, sc->sc_nwidgets);
427 1.2.2.2 skrll return NULL;
428 1.2.2.2 skrll }
429 1.2.2.2 skrll if (nid < sc->sc_startnode || nid >= sc->sc_endnode) {
430 1.2.2.2 skrll hda_debug(sc, "nid %02X out of range (%02X-%02X)\n",
431 1.2.2.2 skrll nid, sc->sc_startnode, sc->sc_endnode);
432 1.2.2.2 skrll return NULL;
433 1.2.2.2 skrll }
434 1.2.2.2 skrll return &sc->sc_widgets[nid - sc->sc_startnode];
435 1.2.2.2 skrll }
436 1.2.2.2 skrll
437 1.2.2.2 skrll static struct hdaudio_control *
438 1.2.2.2 skrll hdafg_control_lookup(struct hdafg_softc *sc, int nid,
439 1.2.2.2 skrll enum hdaudio_pindir dir, int index, int cnt)
440 1.2.2.2 skrll {
441 1.2.2.2 skrll struct hdaudio_control *ctl;
442 1.2.2.2 skrll int i, found = 0;
443 1.2.2.2 skrll
444 1.2.2.2 skrll if (sc->sc_ctls == NULL)
445 1.2.2.2 skrll return NULL;
446 1.2.2.2 skrll for (i = 0; i < sc->sc_nctls; i++) {
447 1.2.2.2 skrll ctl = &sc->sc_ctls[i];
448 1.2.2.2 skrll if (ctl->ctl_enable == false)
449 1.2.2.2 skrll continue;
450 1.2.2.2 skrll if (ctl->ctl_widget->w_nid != nid)
451 1.2.2.2 skrll continue;
452 1.2.2.2 skrll if (dir && ctl->ctl_ndir != dir)
453 1.2.2.2 skrll continue;
454 1.2.2.2 skrll if (index >= 0 && ctl->ctl_ndir == HDAUDIO_PINDIR_IN &&
455 1.2.2.2 skrll ctl->ctl_dir == ctl->ctl_ndir && ctl->ctl_index != index)
456 1.2.2.2 skrll continue;
457 1.2.2.2 skrll found++;
458 1.2.2.2 skrll if (found == cnt || cnt <= 0)
459 1.2.2.2 skrll return ctl;
460 1.2.2.2 skrll }
461 1.2.2.2 skrll
462 1.2.2.2 skrll return NULL;
463 1.2.2.2 skrll }
464 1.2.2.2 skrll
465 1.2.2.2 skrll static void
466 1.2.2.2 skrll hdafg_widget_connection_parse(struct hdaudio_widget *w)
467 1.2.2.2 skrll {
468 1.2.2.2 skrll struct hdafg_softc *sc = w->w_afg;
469 1.2.2.2 skrll uint32_t res;
470 1.2.2.2 skrll int i, j, maxconns, ents, entnum;
471 1.2.2.2 skrll int cnid, addcnid, prevcnid;
472 1.2.2.2 skrll
473 1.2.2.2 skrll w->w_nconns = 0;
474 1.2.2.2 skrll
475 1.2.2.2 skrll res = hda_get_wparam(w, CONNECTION_LIST_LENGTH);
476 1.2.2.2 skrll ents = COP_CONNECTION_LIST_LENGTH_LEN(res);
477 1.2.2.2 skrll if (ents < 1)
478 1.2.2.2 skrll return;
479 1.2.2.2 skrll if (res & COP_CONNECTION_LIST_LENGTH_LONG_FORM)
480 1.2.2.2 skrll entnum = 2;
481 1.2.2.2 skrll else
482 1.2.2.2 skrll entnum = 4;
483 1.2.2.2 skrll maxconns = (sizeof(w->w_conns) / sizeof(w->w_conns[0])) - 1;
484 1.2.2.2 skrll prevcnid = 0;
485 1.2.2.2 skrll
486 1.2.2.2 skrll #define CONN_RMASK(e) (1 << ((32 / (e)) - 1))
487 1.2.2.2 skrll #define CONN_NMASK(e) (CONN_RMASK(e) - 1)
488 1.2.2.2 skrll #define CONN_RESVAL(r, e, n) ((r) >> ((32 / (e)) * (n)))
489 1.2.2.2 skrll #define CONN_RANGE(r, e, n) (CONN_RESVAL(r, e, n) & CONN_RMASK(e))
490 1.2.2.2 skrll #define CONN_CNID(r, e, n) (CONN_RESVAL(r, e, n) & CONN_NMASK(e))
491 1.2.2.2 skrll
492 1.2.2.2 skrll for (i = 0; i < ents; i += entnum) {
493 1.2.2.2 skrll res = hdaudio_command(sc->sc_codec, w->w_nid,
494 1.2.2.2 skrll CORB_GET_CONNECTION_LIST_ENTRY, i);
495 1.2.2.2 skrll for (j = 0; j < entnum; j++) {
496 1.2.2.2 skrll cnid = CONN_CNID(res, entnum, j);
497 1.2.2.2 skrll if (cnid == 0) {
498 1.2.2.2 skrll if (w->w_nconns < ents) {
499 1.2.2.2 skrll hda_error(sc, "WARNING: zero cnid\n");
500 1.2.2.2 skrll } else {
501 1.2.2.2 skrll goto getconns_out;
502 1.2.2.2 skrll }
503 1.2.2.2 skrll }
504 1.2.2.2 skrll if (cnid < sc->sc_startnode || cnid >= sc->sc_endnode)
505 1.2.2.2 skrll hda_debug(sc, "ghost nid=%02X\n", cnid);
506 1.2.2.2 skrll if (CONN_RANGE(res, entnum, j) == 0)
507 1.2.2.2 skrll addcnid = cnid;
508 1.2.2.2 skrll else if (prevcnid == 0 || prevcnid >= cnid) {
509 1.2.2.2 skrll hda_error(sc, "invalid child range\n");
510 1.2.2.2 skrll addcnid = cnid;
511 1.2.2.2 skrll } else
512 1.2.2.2 skrll addcnid = prevcnid + 1;
513 1.2.2.2 skrll while (addcnid <= cnid) {
514 1.2.2.2 skrll if (w->w_nconns > maxconns) {
515 1.2.2.2 skrll hda_error(sc,
516 1.2.2.2 skrll "max connections reached\n");
517 1.2.2.2 skrll goto getconns_out;
518 1.2.2.3 skrll }
519 1.2.2.2 skrll w->w_connsenable[w->w_nconns] = true;
520 1.2.2.2 skrll w->w_conns[w->w_nconns++] = addcnid++;
521 1.2.2.2 skrll hda_trace(sc, "add connection %02X->%02X\n",
522 1.2.2.2 skrll w->w_nid, addcnid - 1);
523 1.2.2.2 skrll }
524 1.2.2.2 skrll prevcnid = cnid;
525 1.2.2.2 skrll }
526 1.2.2.2 skrll }
527 1.2.2.2 skrll #undef CONN_RMASK
528 1.2.2.2 skrll #undef CONN_NMASK
529 1.2.2.2 skrll #undef CONN_RESVAL
530 1.2.2.2 skrll #undef CONN_RANGE
531 1.2.2.2 skrll #undef CONN_CNID
532 1.2.2.2 skrll
533 1.2.2.2 skrll getconns_out:
534 1.2.2.2 skrll return;
535 1.2.2.2 skrll }
536 1.2.2.2 skrll
537 1.2.2.2 skrll static void
538 1.2.2.2 skrll hdafg_widget_pin_dump(struct hdafg_softc *sc)
539 1.2.2.2 skrll {
540 1.2.2.2 skrll struct hdaudio_widget *w;
541 1.2.2.2 skrll int i, conn;
542 1.2.2.2 skrll
543 1.2.2.2 skrll for (i = sc->sc_startnode; i < sc->sc_endnode; i++) {
544 1.2.2.2 skrll w = hdafg_widget_lookup(sc, i);
545 1.2.2.2 skrll if (w == NULL || w->w_enable == false)
546 1.2.2.2 skrll continue;
547 1.2.2.2 skrll if (w->w_type != COP_AWCAP_TYPE_PIN_COMPLEX)
548 1.2.2.2 skrll continue;
549 1.2.2.2 skrll conn = COP_CFG_PORT_CONNECTIVITY(w->w_pin.config);
550 1.2.2.2 skrll if (conn != 1) {
551 1.2.2.2 skrll #ifdef HDAUDIO_DEBUG
552 1.2.2.2 skrll int color = COP_CFG_COLOR(w->w_pin.config);
553 1.2.2.2 skrll int defdev = COP_CFG_DEFAULT_DEVICE(w->w_pin.config);
554 1.2.2.2 skrll hda_trace(sc, "io %02X: %s (%s, %s)\n",
555 1.2.2.2 skrll w->w_nid,
556 1.2.2.2 skrll hdafg_default_device[defdev],
557 1.2.2.2 skrll hdafg_color[color],
558 1.2.2.2 skrll hdafg_port_connectivity[conn]);
559 1.2.2.2 skrll #endif
560 1.2.2.2 skrll }
561 1.2.2.2 skrll }
562 1.2.2.2 skrll }
563 1.2.2.2 skrll
564 1.2.2.2 skrll static void
565 1.2.2.2 skrll hdafg_widget_setconfig(struct hdaudio_widget *w, uint32_t cfg)
566 1.2.2.2 skrll {
567 1.2.2.2 skrll struct hdafg_softc *sc = w->w_afg;
568 1.2.2.2 skrll
569 1.2.2.2 skrll hdaudio_command(sc->sc_codec, w->w_nid,
570 1.2.2.2 skrll CORB_SET_CONFIGURATION_DEFAULT_1, (cfg >> 0) & 0xff);
571 1.2.2.2 skrll hdaudio_command(sc->sc_codec, w->w_nid,
572 1.2.2.2 skrll CORB_SET_CONFIGURATION_DEFAULT_2, (cfg >> 8) & 0xff);
573 1.2.2.2 skrll hdaudio_command(sc->sc_codec, w->w_nid,
574 1.2.2.2 skrll CORB_SET_CONFIGURATION_DEFAULT_3, (cfg >> 16) & 0xff);
575 1.2.2.2 skrll hdaudio_command(sc->sc_codec, w->w_nid,
576 1.2.2.2 skrll CORB_SET_CONFIGURATION_DEFAULT_4, (cfg >> 24) & 0xff);
577 1.2.2.2 skrll }
578 1.2.2.2 skrll
579 1.2.2.2 skrll static uint32_t
580 1.2.2.2 skrll hdafg_widget_getconfig(struct hdaudio_widget *w)
581 1.2.2.2 skrll {
582 1.2.2.2 skrll struct hdafg_softc *sc = w->w_afg;
583 1.2.2.2 skrll uint32_t config = 0;
584 1.2.2.2 skrll prop_object_iterator_t iter;
585 1.2.2.2 skrll prop_dictionary_t dict;
586 1.2.2.2 skrll prop_object_t obj;
587 1.2.2.2 skrll int16_t nid;
588 1.2.2.2 skrll
589 1.2.2.2 skrll if (sc->sc_config == NULL)
590 1.2.2.2 skrll goto biosconfig;
591 1.2.2.2 skrll
592 1.2.2.2 skrll iter = prop_array_iterator(sc->sc_config);
593 1.2.2.2 skrll if (iter == NULL)
594 1.2.2.2 skrll goto biosconfig;
595 1.2.2.2 skrll prop_object_iterator_reset(iter);
596 1.2.2.2 skrll while ((obj = prop_object_iterator_next(iter)) != NULL) {
597 1.2.2.2 skrll if (prop_object_type(obj) != PROP_TYPE_DICTIONARY)
598 1.2.2.2 skrll continue;
599 1.2.2.2 skrll dict = (prop_dictionary_t)obj;
600 1.2.2.2 skrll if (!prop_dictionary_get_int16(dict, "nid", &nid) ||
601 1.2.2.2 skrll !prop_dictionary_get_uint32(dict, "config", &config))
602 1.2.2.2 skrll continue;
603 1.2.2.2 skrll if (nid == w->w_nid)
604 1.2.2.2 skrll return config;
605 1.2.2.2 skrll }
606 1.2.2.2 skrll
607 1.2.2.2 skrll biosconfig:
608 1.2.2.2 skrll return hdaudio_command(sc->sc_codec, w->w_nid,
609 1.2.2.2 skrll CORB_GET_CONFIGURATION_DEFAULT, 0);
610 1.2.2.2 skrll }
611 1.2.2.2 skrll
612 1.2.2.2 skrll static void
613 1.2.2.2 skrll hdafg_widget_pin_parse(struct hdaudio_widget *w)
614 1.2.2.2 skrll {
615 1.2.2.2 skrll struct hdafg_softc *sc = w->w_afg;
616 1.2.2.2 skrll int conn, color, defdev;
617 1.2.2.2 skrll
618 1.2.2.2 skrll w->w_pin.cap = hda_get_wparam(w, PIN_CAPABILITIES);
619 1.2.2.2 skrll w->w_pin.config = hdafg_widget_getconfig(w);
620 1.2.2.2 skrll w->w_pin.biosconfig = hdaudio_command(sc->sc_codec, w->w_nid,
621 1.2.2.2 skrll CORB_GET_CONFIGURATION_DEFAULT, 0);
622 1.2.2.2 skrll w->w_pin.ctrl = hdaudio_command(sc->sc_codec, w->w_nid,
623 1.2.2.2 skrll CORB_GET_PIN_WIDGET_CONTROL, 0);
624 1.2.2.2 skrll
625 1.2.2.2 skrll /* treat line-out as speaker, unless connection type is RCA */
626 1.2.2.2 skrll if (COP_CFG_DEFAULT_DEVICE(w->w_pin.config) == COP_DEVICE_LINE_OUT &&
627 1.2.2.2 skrll COP_CFG_CONNECTION_TYPE(w->w_pin.config) != COP_CONN_TYPE_RCA) {
628 1.2.2.2 skrll w->w_pin.config &= ~COP_DEVICE_MASK;
629 1.2.2.2 skrll w->w_pin.config |= (COP_DEVICE_SPEAKER << COP_DEVICE_SHIFT);
630 1.2.2.2 skrll }
631 1.2.2.2 skrll
632 1.2.2.2 skrll if (w->w_pin.cap & COP_PINCAP_EAPD_CAPABLE) {
633 1.2.2.2 skrll w->w_p.eapdbtl = hdaudio_command(sc->sc_codec, w->w_nid,
634 1.2.2.2 skrll CORB_GET_EAPD_BTL_ENABLE, 0);
635 1.2.2.2 skrll w->w_p.eapdbtl &= 0x7;
636 1.2.2.2 skrll w->w_p.eapdbtl |= COP_EAPD_ENABLE_EAPD;
637 1.2.2.2 skrll } else
638 1.2.2.2 skrll w->w_p.eapdbtl = 0xffffffff;
639 1.2.2.2 skrll
640 1.2.2.2 skrll #if 0
641 1.2.2.2 skrll /* XXX VT1708 */
642 1.2.2.2 skrll if (COP_CFG_DEFAULT_DEVICE(w->w_pin.config) == COP_DEVICE_SPEAKER &&
643 1.2.2.2 skrll COP_CFG_DEFAULT_ASSOCIATION(w->w_pin.config) == 15) {
644 1.2.2.2 skrll hda_trace(sc, "forcing speaker nid %02X to assoc=14\n",
645 1.2.2.2 skrll w->w_nid);
646 1.2.2.2 skrll /* set assoc=14 */
647 1.2.2.2 skrll w->w_pin.config &= ~0xf0;
648 1.2.2.2 skrll w->w_pin.config |= 0xe0;
649 1.2.2.2 skrll }
650 1.2.2.2 skrll if (COP_CFG_DEFAULT_DEVICE(w->w_pin.config) == COP_DEVICE_HP_OUT &&
651 1.2.2.2 skrll COP_CFG_PORT_CONNECTIVITY(w->w_pin.config) == COP_PORT_NONE) {
652 1.2.2.2 skrll hda_trace(sc, "forcing hp out nid %02X to assoc=14\n",
653 1.2.2.2 skrll w->w_nid);
654 1.2.2.2 skrll /* set connectivity to 'jack' */
655 1.2.2.2 skrll w->w_pin.config &= ~(COP_PORT_BOTH << 30);
656 1.2.2.2 skrll w->w_pin.config |= (COP_PORT_JACK << 30);
657 1.2.2.2 skrll /* set seq=15 */
658 1.2.2.2 skrll w->w_pin.config &= ~0xf;
659 1.2.2.2 skrll w->w_pin.config |= 15;
660 1.2.2.2 skrll /* set assoc=14 */
661 1.2.2.2 skrll w->w_pin.config &= ~0xf0;
662 1.2.2.2 skrll w->w_pin.config |= 0xe0;
663 1.2.2.2 skrll }
664 1.2.2.2 skrll #endif
665 1.2.2.2 skrll
666 1.2.2.2 skrll conn = COP_CFG_PORT_CONNECTIVITY(w->w_pin.config);
667 1.2.2.2 skrll color = COP_CFG_COLOR(w->w_pin.config);
668 1.2.2.2 skrll defdev = COP_CFG_DEFAULT_DEVICE(w->w_pin.config);
669 1.2.2.2 skrll
670 1.2.2.2 skrll strlcat(w->w_name, ": ", sizeof(w->w_name));
671 1.2.2.2 skrll strlcat(w->w_name, hdafg_default_device[defdev], sizeof(w->w_name));
672 1.2.2.2 skrll strlcat(w->w_name, " (", sizeof(w->w_name));
673 1.2.2.2 skrll if (conn == 0 && color != 0 && color != 15) {
674 1.2.2.2 skrll strlcat(w->w_name, hdafg_color[color], sizeof(w->w_name));
675 1.2.2.2 skrll strlcat(w->w_name, " ", sizeof(w->w_name));
676 1.2.2.2 skrll }
677 1.2.2.2 skrll strlcat(w->w_name, hdafg_port_connectivity[conn], sizeof(w->w_name));
678 1.2.2.2 skrll strlcat(w->w_name, ")", sizeof(w->w_name));
679 1.2.2.2 skrll }
680 1.2.2.2 skrll
681 1.2.2.2 skrll static uint32_t
682 1.2.2.2 skrll hdafg_widget_getcaps(struct hdaudio_widget *w)
683 1.2.2.2 skrll {
684 1.2.2.2 skrll struct hdafg_softc *sc = w->w_afg;
685 1.2.2.2 skrll uint32_t wcap, config;
686 1.2.2.2 skrll bool pcbeep = false;
687 1.2.2.2 skrll
688 1.2.2.2 skrll wcap = hda_get_wparam(w, AUDIO_WIDGET_CAPABILITIES);
689 1.2.2.2 skrll config = hdafg_widget_getconfig(w);
690 1.2.2.2 skrll
691 1.2.2.2 skrll w->w_waspin = false;
692 1.2.2.2 skrll
693 1.2.2.2 skrll switch (sc->sc_vendor) {
694 1.2.2.2 skrll case HDAUDIO_VENDOR_ANALOG:
695 1.2.2.2 skrll /*
696 1.2.2.2 skrll * help the parser by marking the analog
697 1.2.2.2 skrll * beeper as a beep generator
698 1.2.2.2 skrll */
699 1.2.2.2 skrll if (w->w_nid == 0x1a &&
700 1.2.2.2 skrll COP_CFG_SEQUENCE(config) == 0x0 &&
701 1.2.2.2 skrll COP_CFG_DEFAULT_ASSOCIATION(config) == 0xf &&
702 1.2.2.2 skrll COP_CFG_PORT_CONNECTIVITY(config) ==
703 1.2.2.2 skrll COP_PORT_FIXED_FUNCTION &&
704 1.2.2.2 skrll COP_CFG_DEFAULT_DEVICE(config) ==
705 1.2.2.2 skrll COP_DEVICE_OTHER) {
706 1.2.2.2 skrll pcbeep = true;
707 1.2.2.2 skrll }
708 1.2.2.2 skrll break;
709 1.2.2.2 skrll }
710 1.2.2.2 skrll
711 1.2.2.2 skrll if (pcbeep ||
712 1.2.2.2 skrll (sc->sc_has_beepgen == false &&
713 1.2.2.2 skrll COP_CFG_DEFAULT_DEVICE(config) == COP_DEVICE_SPEAKER &&
714 1.2.2.2 skrll (wcap & (COP_AWCAP_INAMP_PRESENT|COP_AWCAP_OUTAMP_PRESENT)) == 0)) {
715 1.2.2.2 skrll wcap &= ~COP_AWCAP_TYPE_MASK;
716 1.2.2.2 skrll wcap |= (COP_AWCAP_TYPE_BEEP_GENERATOR << COP_AWCAP_TYPE_SHIFT);
717 1.2.2.2 skrll w->w_waspin = true;
718 1.2.2.2 skrll }
719 1.2.2.2 skrll
720 1.2.2.2 skrll return wcap;
721 1.2.2.2 skrll }
722 1.2.2.2 skrll
723 1.2.2.2 skrll static void
724 1.2.2.2 skrll hdafg_widget_parse(struct hdaudio_widget *w)
725 1.2.2.2 skrll {
726 1.2.2.2 skrll struct hdafg_softc *sc = w->w_afg;
727 1.2.2.2 skrll const char *tstr;
728 1.2.2.2 skrll
729 1.2.2.2 skrll w->w_p.aw_cap = hdafg_widget_getcaps(w);
730 1.2.2.2 skrll w->w_type = COP_AWCAP_TYPE(w->w_p.aw_cap);
731 1.2.2.2 skrll
732 1.2.2.2 skrll switch (w->w_type) {
733 1.2.2.2 skrll case COP_AWCAP_TYPE_AUDIO_OUTPUT: tstr = "audio output"; break;
734 1.2.2.2 skrll case COP_AWCAP_TYPE_AUDIO_INPUT: tstr = "audio input"; break;
735 1.2.2.2 skrll case COP_AWCAP_TYPE_AUDIO_MIXER: tstr = "audio mixer"; break;
736 1.2.2.2 skrll case COP_AWCAP_TYPE_AUDIO_SELECTOR: tstr = "audio selector"; break;
737 1.2.2.2 skrll case COP_AWCAP_TYPE_PIN_COMPLEX: tstr = "pin"; break;
738 1.2.2.2 skrll case COP_AWCAP_TYPE_POWER_WIDGET: tstr = "power widget"; break;
739 1.2.2.2 skrll case COP_AWCAP_TYPE_VOLUME_KNOB: tstr = "volume knob"; break;
740 1.2.2.2 skrll case COP_AWCAP_TYPE_BEEP_GENERATOR: tstr = "beep generator"; break;
741 1.2.2.2 skrll case COP_AWCAP_TYPE_VENDOR_DEFINED: tstr = "vendor defined"; break;
742 1.2.2.2 skrll default: tstr = "unknown"; break;
743 1.2.2.2 skrll }
744 1.2.2.2 skrll
745 1.2.2.2 skrll strlcpy(w->w_name, tstr, sizeof(w->w_name));
746 1.2.2.2 skrll
747 1.2.2.2 skrll hdafg_widget_connection_parse(w);
748 1.2.2.2 skrll
749 1.2.2.2 skrll if (w->w_p.aw_cap & COP_AWCAP_INAMP_PRESENT) {
750 1.2.2.2 skrll if (w->w_p.aw_cap & COP_AWCAP_AMP_PARAM_OVERRIDE)
751 1.2.2.2 skrll w->w_p.inamp_cap = hda_get_wparam(w,
752 1.2.2.2 skrll AMPLIFIER_CAPABILITIES_INAMP);
753 1.2.2.2 skrll else
754 1.2.2.2 skrll w->w_p.inamp_cap = sc->sc_p.inamp_cap;
755 1.2.2.2 skrll }
756 1.2.2.2 skrll if (w->w_p.aw_cap & COP_AWCAP_OUTAMP_PRESENT) {
757 1.2.2.2 skrll if (w->w_p.aw_cap & COP_AWCAP_AMP_PARAM_OVERRIDE)
758 1.2.2.2 skrll w->w_p.outamp_cap = hda_get_wparam(w,
759 1.2.2.2 skrll AMPLIFIER_CAPABILITIES_OUTAMP);
760 1.2.2.2 skrll else
761 1.2.2.2 skrll w->w_p.outamp_cap = sc->sc_p.outamp_cap;
762 1.2.2.2 skrll }
763 1.2.2.2 skrll
764 1.2.2.2 skrll w->w_p.stream_format = 0;
765 1.2.2.2 skrll w->w_p.pcm_size_rate = 0;
766 1.2.2.2 skrll switch (w->w_type) {
767 1.2.2.2 skrll case COP_AWCAP_TYPE_AUDIO_OUTPUT:
768 1.2.2.2 skrll case COP_AWCAP_TYPE_AUDIO_INPUT:
769 1.2.2.2 skrll if (w->w_p.aw_cap & COP_AWCAP_FORMAT_OVERRIDE) {
770 1.2.2.2 skrll w->w_p.stream_format = hda_get_wparam(w,
771 1.2.2.2 skrll SUPPORTED_STREAM_FORMATS);
772 1.2.2.2 skrll w->w_p.pcm_size_rate = hda_get_wparam(w,
773 1.2.2.2 skrll SUPPORTED_PCM_SIZE_RATES);
774 1.2.2.2 skrll } else {
775 1.2.2.2 skrll w->w_p.stream_format = sc->sc_p.stream_format;
776 1.2.2.2 skrll w->w_p.pcm_size_rate = sc->sc_p.pcm_size_rate;
777 1.2.2.2 skrll }
778 1.2.2.2 skrll break;
779 1.2.2.2 skrll case COP_AWCAP_TYPE_PIN_COMPLEX:
780 1.2.2.2 skrll hdafg_widget_pin_parse(w);
781 1.2.2.2 skrll hdafg_widget_setconfig(w, w->w_pin.config);
782 1.2.2.2 skrll break;
783 1.2.2.2 skrll }
784 1.2.2.2 skrll }
785 1.2.2.2 skrll
786 1.2.2.2 skrll static int
787 1.2.2.2 skrll hdafg_assoc_count_channels(struct hdafg_softc *sc,
788 1.2.2.2 skrll struct hdaudio_assoc *as, enum hdaudio_pindir dir)
789 1.2.2.2 skrll {
790 1.2.2.2 skrll struct hdaudio_widget *w;
791 1.2.2.2 skrll int *dacmap;
792 1.2.2.2 skrll int i, dacmapsz = sizeof(*dacmap) * sc->sc_endnode;
793 1.2.2.2 skrll int nchans = 0;
794 1.2.2.2 skrll
795 1.2.2.2 skrll if (as->as_enable == false || as->as_dir != dir)
796 1.2.2.2 skrll return 0;
797 1.2.2.2 skrll
798 1.2.2.2 skrll dacmap = kmem_zalloc(dacmapsz, KM_SLEEP);
799 1.2.2.2 skrll if (dacmap == NULL)
800 1.2.2.2 skrll return 0;
801 1.2.2.2 skrll
802 1.2.2.2 skrll for (i = 0; i < HDAUDIO_MAXPINS; i++)
803 1.2.2.2 skrll if (as->as_dacs[i])
804 1.2.2.2 skrll dacmap[as->as_dacs[i]] = 1;
805 1.2.2.2 skrll
806 1.2.2.2 skrll for (i = 1; i < sc->sc_endnode; i++) {
807 1.2.2.2 skrll if (!dacmap[i])
808 1.2.2.2 skrll continue;
809 1.2.2.2 skrll w = hdafg_widget_lookup(sc, i);
810 1.2.2.2 skrll if (w == NULL || w->w_enable == false)
811 1.2.2.2 skrll continue;
812 1.2.2.2 skrll nchans += COP_AWCAP_CHANNEL_COUNT(w->w_p.aw_cap);
813 1.2.2.2 skrll }
814 1.2.2.2 skrll
815 1.2.2.2 skrll kmem_free(dacmap, dacmapsz);
816 1.2.2.2 skrll
817 1.2.2.2 skrll return nchans;
818 1.2.2.2 skrll }
819 1.2.2.2 skrll
820 1.2.2.2 skrll static const char *
821 1.2.2.2 skrll hdafg_assoc_type_string(struct hdaudio_assoc *as)
822 1.2.2.2 skrll {
823 1.2.2.2 skrll switch (as->as_digital) {
824 1.2.2.2 skrll case HDAFG_AS_ANALOG:
825 1.2.2.2 skrll return as->as_dir == HDAUDIO_PINDIR_IN ?
826 1.2.2.2 skrll "ADC" : "DAC";
827 1.2.2.2 skrll case HDAFG_AS_SPDIF:
828 1.2.2.2 skrll return as->as_dir == HDAUDIO_PINDIR_IN ?
829 1.2.2.2 skrll "DIG-In" : "DIG";
830 1.2.2.2 skrll case HDAFG_AS_HDMI:
831 1.2.2.2 skrll return as->as_dir == HDAUDIO_PINDIR_IN ?
832 1.2.2.2 skrll "HDMI-In" : "HDMI";
833 1.2.2.2 skrll case HDAFG_AS_DISPLAYPORT:
834 1.2.2.2 skrll return as->as_dir == HDAUDIO_PINDIR_IN ?
835 1.2.2.2 skrll "DP-In" : "DP";
836 1.2.2.2 skrll default:
837 1.2.2.2 skrll return as->as_dir == HDAUDIO_PINDIR_IN ?
838 1.2.2.2 skrll "Unknown-In" : "Unknown-Out";
839 1.2.2.2 skrll }
840 1.2.2.2 skrll }
841 1.2.2.2 skrll
842 1.2.2.2 skrll static void
843 1.2.2.2 skrll hdafg_assoc_dump_dd(struct hdafg_softc *sc, struct hdaudio_assoc *as, int pin,
844 1.2.2.2 skrll int lock)
845 1.2.2.2 skrll {
846 1.2.2.2 skrll struct hdafg_dd_info hdi;
847 1.2.2.2 skrll struct hdaudio_widget *w;
848 1.2.2.2 skrll uint8_t elddata[256];
849 1.2.2.2 skrll unsigned int elddatalen = 0, i;
850 1.2.2.2 skrll uint32_t res;
851 1.2.2.2 skrll uint32_t (*cmd)(struct hdaudio_codec *, int, uint32_t, uint32_t) =
852 1.2.2.2 skrll lock ? hdaudio_command : hdaudio_command_unlocked;
853 1.2.2.2 skrll
854 1.2.2.2 skrll w = hdafg_widget_lookup(sc, as->as_pins[pin]);
855 1.2.2.2 skrll
856 1.2.2.2 skrll if (w->w_pin.cap & COP_PINCAP_TRIGGER_REQD) {
857 1.2.2.2 skrll (*cmd)(sc->sc_codec, as->as_pins[pin],
858 1.2.2.2 skrll CORB_SET_PIN_SENSE, 0);
859 1.2.2.2 skrll }
860 1.2.2.2 skrll res = (*cmd)(sc->sc_codec, as->as_pins[pin],
861 1.2.2.2 skrll CORB_GET_PIN_SENSE, 0);
862 1.2.2.2 skrll
863 1.2.2.2 skrll #ifdef HDAFG_HDMI_DEBUG
864 1.2.2.2 skrll hda_print(sc, "Display Device, pin=%02X\n", as->as_pins[pin]);
865 1.2.2.2 skrll hda_print(sc, " COP_GET_PIN_SENSE_PRESENSE_DETECT=%d\n",
866 1.2.2.2 skrll !!(res & COP_GET_PIN_SENSE_PRESENSE_DETECT));
867 1.2.2.2 skrll hda_print(sc, " COP_GET_PIN_SENSE_ELD_VALID=%d\n",
868 1.2.2.2 skrll !!(res & COP_GET_PIN_SENSE_ELD_VALID));
869 1.2.2.2 skrll #endif
870 1.2.2.2 skrll
871 1.2.2.2 skrll if ((res &
872 1.2.2.2 skrll (COP_GET_PIN_SENSE_PRESENSE_DETECT|COP_GET_PIN_SENSE_ELD_VALID)) ==
873 1.2.2.2 skrll (COP_GET_PIN_SENSE_PRESENSE_DETECT|COP_GET_PIN_SENSE_ELD_VALID)) {
874 1.2.2.2 skrll res = (*cmd)(sc->sc_codec, as->as_pins[pin],
875 1.2.2.2 skrll CORB_GET_HDMI_DIP_SIZE, COP_DIP_ELD_SIZE);
876 1.2.2.2 skrll elddatalen = COP_DIP_BUFFER_SIZE(res);
877 1.2.2.2 skrll if (elddatalen == 0)
878 1.2.2.2 skrll elddatalen = sizeof(elddata); /* paranoid */
879 1.2.2.2 skrll for (i = 0; i < elddatalen; i++) {
880 1.2.2.2 skrll res = (*cmd)(sc->sc_codec, as->as_pins[pin],
881 1.2.2.2 skrll CORB_GET_HDMI_ELD_DATA, i);
882 1.2.2.2 skrll if (!(res & COP_ELD_VALID)) {
883 1.2.2.2 skrll hda_error(sc, "bad ELD size (%u/%u)\n",
884 1.2.2.2 skrll i, elddatalen);
885 1.2.2.2 skrll break;
886 1.2.2.2 skrll }
887 1.2.2.2 skrll elddata[i] = COP_ELD_DATA(res);
888 1.2.2.2 skrll }
889 1.2.2.2 skrll
890 1.2.2.2 skrll if (hdafg_dd_parse_info(elddata, elddatalen, &hdi) != 0) {
891 1.2.2.2 skrll hda_error(sc, "failed to parse ELD data\n");
892 1.2.2.2 skrll return;
893 1.2.2.2 skrll }
894 1.2.2.2 skrll
895 1.2.2.2 skrll hda_print(sc, " ELD version=0x%x", ELD_VER(&hdi.eld));
896 1.2.2.2 skrll hda_print1(sc, ",len=%u", hdi.eld.header.baseline_eld_len * 4);
897 1.2.2.2 skrll hda_print1(sc, ",edid=0x%x", ELD_CEA_EDID_VER(&hdi.eld));
898 1.2.2.2 skrll hda_print1(sc, ",port=0x%" PRIx64, hdi.eld.port_id);
899 1.2.2.2 skrll hda_print1(sc, ",vendor=0x%04x", hdi.eld.vendor);
900 1.2.2.2 skrll hda_print1(sc, ",product=0x%04x", hdi.eld.product);
901 1.2.2.2 skrll hda_print1(sc, "\n");
902 1.2.2.2 skrll hda_print(sc, " Monitor = '%s'\n", hdi.monitor);
903 1.2.2.2 skrll for (i = 0; i < hdi.nsad; i++) {
904 1.2.2.2 skrll hda_print(sc, " SAD id=%u", i);
905 1.2.2.2 skrll hda_print1(sc, ",format=%u",
906 1.2.2.2 skrll CEA_AUDIO_FORMAT(&hdi.sad[i]));
907 1.2.2.2 skrll hda_print1(sc, ",channels=%u",
908 1.2.2.2 skrll CEA_MAX_CHANNELS(&hdi.sad[i]));
909 1.2.2.2 skrll hda_print1(sc, ",rate=0x%02x",
910 1.2.2.2 skrll CEA_SAMPLE_RATE(&hdi.sad[i]));
911 1.2.2.2 skrll if (CEA_AUDIO_FORMAT(&hdi.sad[i]) ==
912 1.2.2.2 skrll CEA_AUDIO_FORMAT_LPCM)
913 1.2.2.2 skrll hda_print1(sc, ",precision=0x%x",
914 1.2.2.2 skrll CEA_PRECISION(&hdi.sad[i]));
915 1.2.2.2 skrll else
916 1.2.2.2 skrll hda_print1(sc, ",maxbitrate=%u",
917 1.2.2.2 skrll CEA_MAX_BITRATE(&hdi.sad[i]));
918 1.2.2.2 skrll hda_print1(sc, "\n");
919 1.2.2.2 skrll }
920 1.2.2.2 skrll }
921 1.2.2.2 skrll }
922 1.2.2.2 skrll
923 1.2.2.2 skrll static char *
924 1.2.2.2 skrll hdafg_mixer_mask2allname(uint32_t mask, char *buf, size_t len)
925 1.2.2.2 skrll {
926 1.2.2.2 skrll static const char *audioname[] = HDAUDIO_DEVICE_NAMES;
927 1.2.2.2 skrll int i, first = 1;
928 1.2.2.2 skrll
929 1.2.2.2 skrll memset(buf, 0, len);
930 1.2.2.2 skrll for (i = 0; i < HDAUDIO_MIXER_NRDEVICES; i++) {
931 1.2.2.2 skrll if (mask & (1 << i)) {
932 1.2.2.2 skrll if (first == 0)
933 1.2.2.2 skrll strlcat(buf, ", ", len);
934 1.2.2.2 skrll strlcat(buf, audioname[i], len);
935 1.2.2.2 skrll first = 0;
936 1.2.2.2 skrll }
937 1.2.2.2 skrll }
938 1.2.2.2 skrll
939 1.2.2.2 skrll return buf;
940 1.2.2.2 skrll }
941 1.2.2.2 skrll
942 1.2.2.2 skrll static void
943 1.2.2.2 skrll hdafg_dump_dst_nid(struct hdafg_softc *sc, int nid, int depth)
944 1.2.2.2 skrll {
945 1.2.2.2 skrll struct hdaudio_widget *w, *cw;
946 1.2.2.2 skrll char buf[64];
947 1.2.2.2 skrll int i;
948 1.2.2.2 skrll
949 1.2.2.2 skrll if (depth > HDAUDIO_PARSE_MAXDEPTH)
950 1.2.2.2 skrll return;
951 1.2.2.2 skrll
952 1.2.2.2 skrll w = hdafg_widget_lookup(sc, nid);
953 1.2.2.2 skrll if (w == NULL || w->w_enable == false)
954 1.2.2.2 skrll return;
955 1.2.2.2 skrll
956 1.2.2.2 skrll aprint_debug("%*s", 4 + depth * 7, "");
957 1.2.2.2 skrll aprint_debug("nid=%02X [%s]", w->w_nid, w->w_name);
958 1.2.2.2 skrll
959 1.2.2.2 skrll if (depth > 0) {
960 1.2.2.2 skrll if (w->w_audiomask == 0) {
961 1.2.2.2 skrll aprint_debug("\n");
962 1.2.2.2 skrll return;
963 1.2.2.2 skrll }
964 1.2.2.2 skrll aprint_debug(" [source: %s]",
965 1.2.2.2 skrll hdafg_mixer_mask2allname(w->w_audiomask, buf, sizeof(buf)));
966 1.2.2.2 skrll if (w->w_audiodev >= 0) {
967 1.2.2.2 skrll aprint_debug("\n");
968 1.2.2.2 skrll return;
969 1.2.2.2 skrll }
970 1.2.2.2 skrll }
971 1.2.2.2 skrll
972 1.2.2.2 skrll aprint_debug("\n");
973 1.2.2.2 skrll
974 1.2.2.2 skrll for (i = 0; i < w->w_nconns; i++) {
975 1.2.2.2 skrll if (w->w_connsenable[i] == 0)
976 1.2.2.2 skrll continue;
977 1.2.2.2 skrll cw = hdafg_widget_lookup(sc, w->w_conns[i]);
978 1.2.2.2 skrll if (cw == NULL || cw->w_enable == false || cw->w_bindas == -1)
979 1.2.2.2 skrll continue;
980 1.2.2.2 skrll hdafg_dump_dst_nid(sc, w->w_conns[i], depth + 1);
981 1.2.2.2 skrll }
982 1.2.2.2 skrll }
983 1.2.2.2 skrll
984 1.2.2.2 skrll static void
985 1.2.2.2 skrll hdafg_assoc_dump(struct hdafg_softc *sc)
986 1.2.2.2 skrll {
987 1.2.2.2 skrll struct hdaudio_assoc *as = sc->sc_assocs;
988 1.2.2.2 skrll struct hdaudio_widget *w;
989 1.2.2.2 skrll uint32_t conn, defdev, curdev, curport;
990 1.2.2.2 skrll int maxassocs = sc->sc_nassocs;
991 1.2.2.2 skrll int i, j;
992 1.2.2.2 skrll
993 1.2.2.2 skrll for (i = 0; i < maxassocs; i++) {
994 1.2.2.2 skrll uint32_t devmask = 0, portmask = 0;
995 1.2.2.2 skrll bool firstdev = true;
996 1.2.2.2 skrll int nchan;
997 1.2.2.2 skrll
998 1.2.2.2 skrll if (as[i].as_enable == false)
999 1.2.2.2 skrll continue;
1000 1.2.2.2 skrll
1001 1.2.2.2 skrll hda_print(sc, "%s%02X",
1002 1.2.2.2 skrll hdafg_assoc_type_string(&as[i]), i);
1003 1.2.2.2 skrll
1004 1.2.2.2 skrll nchan = hdafg_assoc_count_channels(sc, &as[i],
1005 1.2.2.2 skrll as[i].as_dir);
1006 1.2.2.2 skrll hda_print1(sc, " %dch:", nchan);
1007 1.2.2.2 skrll
1008 1.2.2.2 skrll for (j = 0; j < HDAUDIO_MAXPINS; j++) {
1009 1.2.2.2 skrll if (as[i].as_dacs[j] == 0)
1010 1.2.2.2 skrll continue;
1011 1.2.2.2 skrll w = hdafg_widget_lookup(sc, as[i].as_pins[j]);
1012 1.2.2.2 skrll if (w == NULL)
1013 1.2.2.2 skrll continue;
1014 1.2.2.2 skrll conn = COP_CFG_PORT_CONNECTIVITY(w->w_pin.config);
1015 1.2.2.2 skrll defdev = COP_CFG_DEFAULT_DEVICE(w->w_pin.config);
1016 1.2.2.2 skrll if (conn != COP_PORT_NONE) {
1017 1.2.2.2 skrll devmask |= (1 << defdev);
1018 1.2.2.2 skrll portmask |= (1 << conn);
1019 1.2.2.2 skrll }
1020 1.2.2.2 skrll }
1021 1.2.2.2 skrll for (curdev = 0; curdev < 16; curdev++) {
1022 1.2.2.2 skrll bool firstport = true;
1023 1.2.2.2 skrll if ((devmask & (1 << curdev)) == 0)
1024 1.2.2.2 skrll continue;
1025 1.2.2.2 skrll
1026 1.2.2.2 skrll if (firstdev == false)
1027 1.2.2.2 skrll hda_print1(sc, ",");
1028 1.2.2.2 skrll firstdev = false;
1029 1.2.2.2 skrll hda_print1(sc, " %s",
1030 1.2.2.2 skrll hdafg_default_device[curdev]);
1031 1.2.2.2 skrll
1032 1.2.2.2 skrll for (curport = 0; curport < 4; curport++) {
1033 1.2.2.2 skrll bool devonport = false;
1034 1.2.2.2 skrll if ((portmask & (1 << curport)) == 0)
1035 1.2.2.2 skrll continue;
1036 1.2.2.2 skrll
1037 1.2.2.2 skrll for (j = 0; j < HDAUDIO_MAXPINS; j++) {
1038 1.2.2.2 skrll if (as[i].as_dacs[j] == 0)
1039 1.2.2.2 skrll continue;
1040 1.2.2.2 skrll
1041 1.2.2.2 skrll w = hdafg_widget_lookup(sc,
1042 1.2.2.2 skrll as[i].as_pins[j]);
1043 1.2.2.2 skrll if (w == NULL)
1044 1.2.2.2 skrll continue;
1045 1.2.2.2 skrll conn = COP_CFG_PORT_CONNECTIVITY(w->w_pin.config);
1046 1.2.2.2 skrll defdev = COP_CFG_DEFAULT_DEVICE(w->w_pin.config);
1047 1.2.2.2 skrll if (conn != curport || defdev != curdev)
1048 1.2.2.2 skrll continue;
1049 1.2.2.2 skrll
1050 1.2.2.2 skrll devonport = true;
1051 1.2.2.2 skrll }
1052 1.2.2.2 skrll
1053 1.2.2.2 skrll if (devonport == false)
1054 1.2.2.2 skrll continue;
1055 1.2.2.2 skrll
1056 1.2.2.2 skrll hda_print1(sc, " [%s",
1057 1.2.2.2 skrll hdafg_port_connectivity[curport]);
1058 1.2.2.2 skrll for (j = 0; j < HDAUDIO_MAXPINS; j++) {
1059 1.2.2.2 skrll if (as[i].as_dacs[j] == 0)
1060 1.2.2.2 skrll continue;
1061 1.2.2.2 skrll
1062 1.2.2.2 skrll w = hdafg_widget_lookup(sc,
1063 1.2.2.2 skrll as[i].as_pins[j]);
1064 1.2.2.2 skrll if (w == NULL)
1065 1.2.2.2 skrll continue;
1066 1.2.2.2 skrll conn = COP_CFG_PORT_CONNECTIVITY(w->w_pin.config);
1067 1.2.2.2 skrll defdev = COP_CFG_DEFAULT_DEVICE(w->w_pin.config);
1068 1.2.2.2 skrll if (conn != curport || defdev != curdev)
1069 1.2.2.2 skrll continue;
1070 1.2.2.2 skrll
1071 1.2.2.2 skrll if (firstport == false)
1072 1.2.2.2 skrll hda_trace1(sc, ",");
1073 1.2.2.2 skrll else
1074 1.2.2.2 skrll hda_trace1(sc, " ");
1075 1.2.2.2 skrll firstport = false;
1076 1.2.2.2 skrll #ifdef HDAUDIO_DEBUG
1077 1.2.2.2 skrll int color =
1078 1.2.2.2 skrll COP_CFG_COLOR(w->w_pin.config);
1079 1.2.2.2 skrll hda_trace1(sc, "%s",
1080 1.2.2.2 skrll hdafg_color[color]);
1081 1.2.2.2 skrll #endif
1082 1.2.2.2 skrll hda_trace1(sc, "(%02X)", w->w_nid);
1083 1.2.2.2 skrll }
1084 1.2.2.2 skrll hda_print1(sc, "]");
1085 1.2.2.2 skrll }
1086 1.2.2.2 skrll }
1087 1.2.2.2 skrll hda_print1(sc, "\n");
1088 1.2.2.2 skrll
1089 1.2.2.2 skrll for (j = 0; j < HDAUDIO_MAXPINS; j++) {
1090 1.2.2.2 skrll if (as[i].as_pins[j] == 0)
1091 1.2.2.2 skrll continue;
1092 1.2.2.2 skrll hdafg_dump_dst_nid(sc, as[i].as_pins[j], 0);
1093 1.2.2.2 skrll }
1094 1.2.2.2 skrll
1095 1.2.2.2 skrll if (as[i].as_displaydev == true) {
1096 1.2.2.2 skrll for (j = 0; j < HDAUDIO_MAXPINS; j++) {
1097 1.2.2.2 skrll if (as[i].as_pins[j] == 0)
1098 1.2.2.2 skrll continue;
1099 1.2.2.2 skrll hdafg_assoc_dump_dd(sc, &as[i], j, 1);
1100 1.2.2.2 skrll }
1101 1.2.2.2 skrll }
1102 1.2.2.2 skrll }
1103 1.2.2.2 skrll }
1104 1.2.2.2 skrll
1105 1.2.2.2 skrll static void
1106 1.2.2.2 skrll hdafg_assoc_parse(struct hdafg_softc *sc)
1107 1.2.2.2 skrll {
1108 1.2.2.2 skrll struct hdaudio_assoc *as;
1109 1.2.2.2 skrll struct hdaudio_widget *w;
1110 1.2.2.2 skrll int i, j, cnt, maxassocs, type, assoc, seq, first, hpredir;
1111 1.2.2.2 skrll enum hdaudio_pindir dir;
1112 1.2.2.2 skrll
1113 1.2.2.2 skrll hda_debug(sc, " count present associations\n");
1114 1.2.2.2 skrll /* Count present associations */
1115 1.2.2.2 skrll maxassocs = 0;
1116 1.2.2.2 skrll for (j = 1; j < HDAUDIO_MAXPINS; j++) {
1117 1.2.2.2 skrll for (i = sc->sc_startnode; i < sc->sc_endnode; i++) {
1118 1.2.2.2 skrll w = hdafg_widget_lookup(sc, i);
1119 1.2.2.2 skrll if (w == NULL || w->w_enable == false)
1120 1.2.2.2 skrll continue;
1121 1.2.2.2 skrll if (w->w_type != COP_AWCAP_TYPE_PIN_COMPLEX)
1122 1.2.2.2 skrll continue;
1123 1.2.2.2 skrll if (COP_CFG_DEFAULT_ASSOCIATION(w->w_pin.config) != j)
1124 1.2.2.2 skrll continue;
1125 1.2.2.2 skrll maxassocs++;
1126 1.2.2.2 skrll if (j != 15) /* There could be many 1-pin assocs #15 */
1127 1.2.2.2 skrll break;
1128 1.2.2.2 skrll }
1129 1.2.2.2 skrll }
1130 1.2.2.2 skrll
1131 1.2.2.2 skrll hda_debug(sc, " maxassocs %d\n", maxassocs);
1132 1.2.2.2 skrll sc->sc_nassocs = maxassocs;
1133 1.2.2.2 skrll
1134 1.2.2.2 skrll if (maxassocs < 1)
1135 1.2.2.2 skrll return;
1136 1.2.2.2 skrll
1137 1.2.2.2 skrll hda_debug(sc, " allocating memory\n");
1138 1.2.2.2 skrll as = kmem_zalloc(maxassocs * sizeof(*as), KM_SLEEP);
1139 1.2.2.2 skrll for (i = 0; i < maxassocs; i++) {
1140 1.2.2.2 skrll as[i].as_hpredir = -1;
1141 1.2.2.2 skrll /* as[i].as_chan = NULL; */
1142 1.2.2.2 skrll as[i].as_digital = HDAFG_AS_SPDIF;
1143 1.2.2.2 skrll }
1144 1.2.2.2 skrll
1145 1.2.2.2 skrll hda_debug(sc, " scan associations, skipping as=0\n");
1146 1.2.2.2 skrll /* Scan associations skipping as=0 */
1147 1.2.2.2 skrll cnt = 0;
1148 1.2.2.2 skrll for (j = 1; j < HDAUDIO_MAXPINS && cnt < maxassocs; j++) {
1149 1.2.2.2 skrll first = 16;
1150 1.2.2.2 skrll hpredir = 0;
1151 1.2.2.2 skrll for (i = sc->sc_startnode; i < sc->sc_endnode; i++) {
1152 1.2.2.2 skrll w = hdafg_widget_lookup(sc, i);
1153 1.2.2.2 skrll if (w == NULL || w->w_enable == false)
1154 1.2.2.2 skrll continue;
1155 1.2.2.2 skrll if (w->w_type != COP_AWCAP_TYPE_PIN_COMPLEX)
1156 1.2.2.2 skrll continue;
1157 1.2.2.2 skrll assoc = COP_CFG_DEFAULT_ASSOCIATION(w->w_pin.config);
1158 1.2.2.2 skrll seq = COP_CFG_SEQUENCE(w->w_pin.config);
1159 1.2.2.2 skrll if (assoc != j)
1160 1.2.2.2 skrll continue;
1161 1.2.2.2 skrll KASSERT(cnt < maxassocs);
1162 1.2.2.2 skrll type = COP_CFG_DEFAULT_DEVICE(w->w_pin.config);
1163 1.2.2.2 skrll /* Get pin direction */
1164 1.2.2.2 skrll switch (type) {
1165 1.2.2.2 skrll case COP_DEVICE_LINE_OUT:
1166 1.2.2.2 skrll case COP_DEVICE_SPEAKER:
1167 1.2.2.2 skrll case COP_DEVICE_HP_OUT:
1168 1.2.2.2 skrll case COP_DEVICE_SPDIF_OUT:
1169 1.2.2.2 skrll case COP_DEVICE_DIGITAL_OTHER_OUT:
1170 1.2.2.2 skrll dir = HDAUDIO_PINDIR_OUT;
1171 1.2.2.2 skrll break;
1172 1.2.2.2 skrll default:
1173 1.2.2.2 skrll dir = HDAUDIO_PINDIR_IN;
1174 1.2.2.2 skrll break;
1175 1.2.2.2 skrll }
1176 1.2.2.2 skrll /* If this is a first pin, create new association */
1177 1.2.2.2 skrll if (as[cnt].as_pincnt == 0) {
1178 1.2.2.2 skrll as[cnt].as_enable = true;
1179 1.2.2.2 skrll as[cnt].as_activated = true;
1180 1.2.2.2 skrll as[cnt].as_index = j;
1181 1.2.2.2 skrll as[cnt].as_dir = dir;
1182 1.2.2.2 skrll }
1183 1.2.2.2 skrll if (seq < first)
1184 1.2.2.2 skrll first = seq;
1185 1.2.2.2 skrll /* Check association correctness */
1186 1.2.2.2 skrll if (as[cnt].as_pins[seq] != 0) {
1187 1.2.2.2 skrll hda_error(sc, "duplicate pin in association\n");
1188 1.2.2.2 skrll as[cnt].as_enable = false;
1189 1.2.2.2 skrll }
1190 1.2.2.2 skrll if (dir != as[cnt].as_dir) {
1191 1.2.2.2 skrll hda_error(sc,
1192 1.2.2.2 skrll "pin %02X has wrong direction for %02X\n",
1193 1.2.2.2 skrll w->w_nid, j);
1194 1.2.2.2 skrll as[cnt].as_enable = false;
1195 1.2.2.2 skrll }
1196 1.2.2.2 skrll if ((w->w_p.aw_cap & COP_AWCAP_DIGITAL) == 0)
1197 1.2.2.2 skrll as[cnt].as_digital = HDAFG_AS_ANALOG;
1198 1.2.2.2 skrll if (w->w_pin.cap & (COP_PINCAP_HDMI|COP_PINCAP_DP))
1199 1.2.2.2 skrll as[cnt].as_displaydev = true;
1200 1.2.2.2 skrll if (w->w_pin.cap & COP_PINCAP_HDMI)
1201 1.2.2.2 skrll as[cnt].as_digital = HDAFG_AS_HDMI;
1202 1.2.2.2 skrll if (w->w_pin.cap & COP_PINCAP_DP)
1203 1.2.2.2 skrll as[cnt].as_digital = HDAFG_AS_DISPLAYPORT;
1204 1.2.2.2 skrll /* Headphones with seq=15 may mean redirection */
1205 1.2.2.2 skrll if (type == COP_DEVICE_HP_OUT && seq == 15)
1206 1.2.2.2 skrll hpredir = 1;
1207 1.2.2.2 skrll as[cnt].as_pins[seq] = w->w_nid;
1208 1.2.2.2 skrll as[cnt].as_pincnt++;
1209 1.2.2.2 skrll if (j == 15)
1210 1.2.2.2 skrll cnt++;
1211 1.2.2.2 skrll }
1212 1.2.2.2 skrll if (j != 15 && cnt < maxassocs && as[cnt].as_pincnt > 0) {
1213 1.2.2.2 skrll if (hpredir && as[cnt].as_pincnt > 1)
1214 1.2.2.2 skrll as[cnt].as_hpredir = first;
1215 1.2.2.2 skrll cnt++;
1216 1.2.2.2 skrll }
1217 1.2.2.2 skrll }
1218 1.2.2.2 skrll
1219 1.2.2.2 skrll hda_debug(sc, " all done\n");
1220 1.2.2.2 skrll sc->sc_assocs = as;
1221 1.2.2.2 skrll }
1222 1.2.2.2 skrll
1223 1.2.2.2 skrll static void
1224 1.2.2.2 skrll hdafg_control_parse(struct hdafg_softc *sc)
1225 1.2.2.2 skrll {
1226 1.2.2.2 skrll struct hdaudio_control *ctl;
1227 1.2.2.2 skrll struct hdaudio_widget *w, *cw;
1228 1.2.2.2 skrll int i, j, cnt, maxctls, ocap, icap;
1229 1.2.2.2 skrll int mute, offset, step, size;
1230 1.2.2.2 skrll
1231 1.2.2.2 skrll maxctls = 0;
1232 1.2.2.2 skrll for (i = sc->sc_startnode; i < sc->sc_endnode; i++) {
1233 1.2.2.2 skrll w = hdafg_widget_lookup(sc, i);
1234 1.2.2.2 skrll if (w == NULL || w->w_enable == false)
1235 1.2.2.2 skrll continue;
1236 1.2.2.2 skrll if (w->w_p.outamp_cap)
1237 1.2.2.2 skrll maxctls++;
1238 1.2.2.2 skrll if (w->w_p.inamp_cap) {
1239 1.2.2.2 skrll switch (w->w_type) {
1240 1.2.2.2 skrll case COP_AWCAP_TYPE_AUDIO_SELECTOR:
1241 1.2.2.2 skrll case COP_AWCAP_TYPE_AUDIO_MIXER:
1242 1.2.2.2 skrll for (j = 0; j < w->w_nconns; j++) {
1243 1.2.2.2 skrll cw = hdafg_widget_lookup(sc,
1244 1.2.2.2 skrll w->w_conns[j]);
1245 1.2.2.2 skrll if (cw == NULL || cw->w_enable == false)
1246 1.2.2.2 skrll continue;
1247 1.2.2.2 skrll maxctls++;
1248 1.2.2.2 skrll }
1249 1.2.2.2 skrll break;
1250 1.2.2.2 skrll default:
1251 1.2.2.2 skrll maxctls++;
1252 1.2.2.2 skrll break;
1253 1.2.2.2 skrll }
1254 1.2.2.2 skrll }
1255 1.2.2.2 skrll }
1256 1.2.2.2 skrll
1257 1.2.2.2 skrll sc->sc_nctls = maxctls;
1258 1.2.2.2 skrll if (maxctls < 1)
1259 1.2.2.2 skrll return;
1260 1.2.2.2 skrll
1261 1.2.2.2 skrll ctl = kmem_zalloc(sc->sc_nctls * sizeof(*ctl), KM_SLEEP);
1262 1.2.2.2 skrll
1263 1.2.2.2 skrll cnt = 0;
1264 1.2.2.2 skrll for (i = sc->sc_startnode; cnt < maxctls && i < sc->sc_endnode; i++) {
1265 1.2.2.2 skrll if (cnt >= maxctls) {
1266 1.2.2.2 skrll hda_error(sc, "ctl overflow\n");
1267 1.2.2.2 skrll break;
1268 1.2.2.2 skrll }
1269 1.2.2.2 skrll w = hdafg_widget_lookup(sc, i);
1270 1.2.2.2 skrll if (w == NULL || w->w_enable == false)
1271 1.2.2.2 skrll continue;
1272 1.2.2.2 skrll ocap = w->w_p.outamp_cap;
1273 1.2.2.2 skrll icap = w->w_p.inamp_cap;
1274 1.2.2.2 skrll if (ocap) {
1275 1.2.2.2 skrll hda_trace(sc, "add ctrl outamp %d:%02X:FF\n",
1276 1.2.2.2 skrll cnt, w->w_nid);
1277 1.2.2.2 skrll mute = COP_AMPCAP_MUTE_CAPABLE(ocap);
1278 1.2.2.2 skrll step = COP_AMPCAP_NUM_STEPS(ocap);
1279 1.2.2.2 skrll size = COP_AMPCAP_STEP_SIZE(ocap);
1280 1.2.2.2 skrll offset = COP_AMPCAP_OFFSET(ocap);
1281 1.2.2.2 skrll ctl[cnt].ctl_enable = true;
1282 1.2.2.2 skrll ctl[cnt].ctl_widget = w;
1283 1.2.2.2 skrll ctl[cnt].ctl_mute = mute;
1284 1.2.2.2 skrll ctl[cnt].ctl_step = step;
1285 1.2.2.2 skrll ctl[cnt].ctl_size = size;
1286 1.2.2.2 skrll ctl[cnt].ctl_offset = offset;
1287 1.2.2.2 skrll ctl[cnt].ctl_left = offset;
1288 1.2.2.2 skrll ctl[cnt].ctl_right = offset;
1289 1.2.2.2 skrll if (w->w_type == COP_AWCAP_TYPE_PIN_COMPLEX ||
1290 1.2.2.2 skrll w->w_waspin == true)
1291 1.2.2.2 skrll ctl[cnt].ctl_ndir = HDAUDIO_PINDIR_IN;
1292 1.2.2.2 skrll else
1293 1.2.2.2 skrll ctl[cnt].ctl_ndir = HDAUDIO_PINDIR_OUT;
1294 1.2.2.2 skrll ctl[cnt++].ctl_dir = HDAUDIO_PINDIR_OUT;
1295 1.2.2.2 skrll }
1296 1.2.2.2 skrll if (icap) {
1297 1.2.2.2 skrll mute = COP_AMPCAP_MUTE_CAPABLE(icap);
1298 1.2.2.2 skrll step = COP_AMPCAP_NUM_STEPS(icap);
1299 1.2.2.2 skrll size = COP_AMPCAP_STEP_SIZE(icap);
1300 1.2.2.2 skrll offset = COP_AMPCAP_OFFSET(icap);
1301 1.2.2.2 skrll switch (w->w_type) {
1302 1.2.2.2 skrll case COP_AWCAP_TYPE_AUDIO_SELECTOR:
1303 1.2.2.2 skrll case COP_AWCAP_TYPE_AUDIO_MIXER:
1304 1.2.2.2 skrll for (j = 0; j < w->w_nconns; j++) {
1305 1.2.2.2 skrll if (cnt >= maxctls)
1306 1.2.2.2 skrll break;
1307 1.2.2.2 skrll cw = hdafg_widget_lookup(sc,
1308 1.2.2.2 skrll w->w_conns[j]);
1309 1.2.2.2 skrll if (cw == NULL || cw->w_enable == false)
1310 1.2.2.2 skrll continue;
1311 1.2.2.2 skrll hda_trace(sc, "add ctrl inamp selmix "
1312 1.2.2.2 skrll "%d:%02X:%02X\n", cnt, w->w_nid,
1313 1.2.2.2 skrll cw->w_nid);
1314 1.2.2.2 skrll ctl[cnt].ctl_enable = true;
1315 1.2.2.2 skrll ctl[cnt].ctl_widget = w;
1316 1.2.2.2 skrll ctl[cnt].ctl_childwidget = cw;
1317 1.2.2.2 skrll ctl[cnt].ctl_index = j;
1318 1.2.2.2 skrll ctl[cnt].ctl_mute = mute;
1319 1.2.2.2 skrll ctl[cnt].ctl_step = step;
1320 1.2.2.2 skrll ctl[cnt].ctl_size = size;
1321 1.2.2.2 skrll ctl[cnt].ctl_offset = offset;
1322 1.2.2.2 skrll ctl[cnt].ctl_left = offset;
1323 1.2.2.2 skrll ctl[cnt].ctl_right = offset;
1324 1.2.2.2 skrll ctl[cnt].ctl_ndir = HDAUDIO_PINDIR_IN;
1325 1.2.2.2 skrll ctl[cnt++].ctl_dir = HDAUDIO_PINDIR_IN;
1326 1.2.2.2 skrll }
1327 1.2.2.2 skrll break;
1328 1.2.2.2 skrll default:
1329 1.2.2.2 skrll if (cnt >= maxctls)
1330 1.2.2.2 skrll break;
1331 1.2.2.2 skrll hda_trace(sc, "add ctrl inamp "
1332 1.2.2.2 skrll "%d:%02X:FF\n", cnt, w->w_nid);
1333 1.2.2.2 skrll ctl[cnt].ctl_enable = true;
1334 1.2.2.2 skrll ctl[cnt].ctl_widget = w;
1335 1.2.2.2 skrll ctl[cnt].ctl_mute = mute;
1336 1.2.2.2 skrll ctl[cnt].ctl_step = step;
1337 1.2.2.2 skrll ctl[cnt].ctl_size = size;
1338 1.2.2.2 skrll ctl[cnt].ctl_offset = offset;
1339 1.2.2.2 skrll ctl[cnt].ctl_left = offset;
1340 1.2.2.2 skrll ctl[cnt].ctl_right = offset;
1341 1.2.2.2 skrll if (w->w_type == COP_AWCAP_TYPE_PIN_COMPLEX)
1342 1.2.2.2 skrll ctl[cnt].ctl_ndir = HDAUDIO_PINDIR_OUT;
1343 1.2.2.2 skrll else
1344 1.2.2.2 skrll ctl[cnt].ctl_ndir = HDAUDIO_PINDIR_IN;
1345 1.2.2.2 skrll ctl[cnt++].ctl_dir = HDAUDIO_PINDIR_IN;
1346 1.2.2.2 skrll break;
1347 1.2.2.2 skrll }
1348 1.2.2.2 skrll }
1349 1.2.2.2 skrll }
1350 1.2.2.2 skrll
1351 1.2.2.2 skrll sc->sc_ctls = ctl;
1352 1.2.2.2 skrll }
1353 1.2.2.2 skrll
1354 1.2.2.2 skrll static void
1355 1.2.2.2 skrll hdafg_parse(struct hdafg_softc *sc)
1356 1.2.2.2 skrll {
1357 1.2.2.2 skrll struct hdaudio_widget *w;
1358 1.2.2.2 skrll uint32_t nodecnt, wcap;
1359 1.2.2.2 skrll int nid;
1360 1.2.2.2 skrll
1361 1.2.2.2 skrll nodecnt = hda_get_param(sc, SUBORDINATE_NODE_COUNT);
1362 1.2.2.2 skrll sc->sc_startnode = COP_NODECNT_STARTNODE(nodecnt);
1363 1.2.2.2 skrll sc->sc_nwidgets = COP_NODECNT_NUMNODES(nodecnt);
1364 1.2.2.2 skrll sc->sc_endnode = sc->sc_startnode + sc->sc_nwidgets;
1365 1.2.2.2 skrll hda_debug(sc, "afg start %02X end %02X nwidgets %d\n",
1366 1.2.2.2 skrll sc->sc_startnode, sc->sc_endnode, sc->sc_nwidgets);
1367 1.2.2.2 skrll
1368 1.2.2.2 skrll hda_debug(sc, "powering up widgets\n");
1369 1.2.2.2 skrll hdaudio_command(sc->sc_codec, sc->sc_nid,
1370 1.2.2.2 skrll CORB_SET_POWER_STATE, COP_POWER_STATE_D0);
1371 1.2.2.2 skrll hda_delay(100);
1372 1.2.2.2 skrll for (nid = sc->sc_startnode; nid < sc->sc_endnode; nid++)
1373 1.2.2.2 skrll hdaudio_command(sc->sc_codec, nid,
1374 1.2.2.2 skrll CORB_SET_POWER_STATE, COP_POWER_STATE_D0);
1375 1.2.2.2 skrll hda_delay(1000);
1376 1.2.2.2 skrll
1377 1.2.2.2 skrll sc->sc_p.afg_cap = hda_get_param(sc, AUDIO_FUNCTION_GROUP_CAPABILITIES);
1378 1.2.2.2 skrll sc->sc_p.stream_format = hda_get_param(sc, SUPPORTED_STREAM_FORMATS);
1379 1.2.2.2 skrll sc->sc_p.pcm_size_rate = hda_get_param(sc, SUPPORTED_PCM_SIZE_RATES);
1380 1.2.2.2 skrll sc->sc_p.outamp_cap = hda_get_param(sc, AMPLIFIER_CAPABILITIES_OUTAMP);
1381 1.2.2.2 skrll sc->sc_p.inamp_cap = hda_get_param(sc, AMPLIFIER_CAPABILITIES_INAMP);
1382 1.2.2.2 skrll sc->sc_p.power_states = hda_get_param(sc, SUPPORTED_POWER_STATES);
1383 1.2.2.2 skrll sc->sc_p.gpio_cnt = hda_get_param(sc, GPIO_COUNT);
1384 1.2.2.2 skrll
1385 1.2.2.2 skrll sc->sc_widgets = kmem_zalloc(sc->sc_nwidgets * sizeof(*w), KM_SLEEP);
1386 1.2.2.2 skrll hda_debug(sc, "afg widgets %p-%p\n",
1387 1.2.2.2 skrll sc->sc_widgets, sc->sc_widgets + sc->sc_nwidgets);
1388 1.2.2.2 skrll
1389 1.2.2.2 skrll for (nid = sc->sc_startnode; nid < sc->sc_endnode; nid++) {
1390 1.2.2.2 skrll w = hdafg_widget_lookup(sc, nid);
1391 1.2.2.2 skrll if (w == NULL)
1392 1.2.2.2 skrll continue;
1393 1.2.2.2 skrll wcap = hdaudio_command(sc->sc_codec, nid, CORB_GET_PARAMETER,
1394 1.2.2.2 skrll COP_AUDIO_WIDGET_CAPABILITIES);
1395 1.2.2.2 skrll switch (COP_AWCAP_TYPE(wcap)) {
1396 1.2.2.2 skrll case COP_AWCAP_TYPE_BEEP_GENERATOR:
1397 1.2.2.2 skrll sc->sc_has_beepgen = true;
1398 1.2.2.2 skrll break;
1399 1.2.2.2 skrll }
1400 1.2.2.2 skrll }
1401 1.2.2.2 skrll
1402 1.2.2.2 skrll for (nid = sc->sc_startnode; nid < sc->sc_endnode; nid++) {
1403 1.2.2.2 skrll w = hdafg_widget_lookup(sc, nid);
1404 1.2.2.2 skrll if (w == NULL)
1405 1.2.2.2 skrll continue;
1406 1.2.2.2 skrll w->w_afg = sc;
1407 1.2.2.2 skrll w->w_nid = nid;
1408 1.2.2.2 skrll w->w_enable = true;
1409 1.2.2.2 skrll w->w_pflags = 0;
1410 1.2.2.2 skrll w->w_audiodev = -1;
1411 1.2.2.2 skrll w->w_selconn = -1;
1412 1.2.2.2 skrll w->w_bindas = -1;
1413 1.2.2.2 skrll w->w_p.eapdbtl = 0xffffffff;
1414 1.2.2.2 skrll hdafg_widget_parse(w);
1415 1.2.2.2 skrll }
1416 1.2.2.2 skrll }
1417 1.2.2.2 skrll
1418 1.2.2.2 skrll static void
1419 1.2.2.2 skrll hdafg_disable_nonaudio(struct hdafg_softc *sc)
1420 1.2.2.2 skrll {
1421 1.2.2.2 skrll struct hdaudio_widget *w;
1422 1.2.2.2 skrll int i;
1423 1.2.2.2 skrll
1424 1.2.2.2 skrll /* Disable power and volume widgets */
1425 1.2.2.2 skrll for (i = sc->sc_startnode; i < sc->sc_endnode; i++) {
1426 1.2.2.2 skrll w = hdafg_widget_lookup(sc, i);
1427 1.2.2.2 skrll if (w == NULL || w->w_enable == false)
1428 1.2.2.2 skrll continue;
1429 1.2.2.2 skrll if (w->w_type == COP_AWCAP_TYPE_POWER_WIDGET ||
1430 1.2.2.2 skrll w->w_type == COP_AWCAP_TYPE_VOLUME_KNOB) {
1431 1.2.2.2 skrll hda_trace(w->w_afg, "disable %02X [nonaudio]\n",
1432 1.2.2.2 skrll w->w_nid);
1433 1.2.2.2 skrll w->w_enable = false;
1434 1.2.2.2 skrll }
1435 1.2.2.2 skrll }
1436 1.2.2.2 skrll }
1437 1.2.2.2 skrll
1438 1.2.2.2 skrll static void
1439 1.2.2.2 skrll hdafg_disable_useless(struct hdafg_softc *sc)
1440 1.2.2.2 skrll {
1441 1.2.2.2 skrll struct hdaudio_widget *w, *cw;
1442 1.2.2.2 skrll struct hdaudio_control *ctl;
1443 1.2.2.2 skrll int done, found, i, j, k;
1444 1.2.2.2 skrll int conn, assoc;
1445 1.2.2.2 skrll
1446 1.2.2.2 skrll /* Disable useless pins */
1447 1.2.2.2 skrll for (i = sc->sc_startnode; i < sc->sc_endnode; i++) {
1448 1.2.2.2 skrll w = hdafg_widget_lookup(sc, i);
1449 1.2.2.2 skrll if (w == NULL || w->w_enable == false)
1450 1.2.2.2 skrll continue;
1451 1.2.2.2 skrll if (w->w_type != COP_AWCAP_TYPE_PIN_COMPLEX)
1452 1.2.2.2 skrll continue;
1453 1.2.2.2 skrll conn = COP_CFG_PORT_CONNECTIVITY(w->w_pin.config);
1454 1.2.2.2 skrll assoc = COP_CFG_DEFAULT_ASSOCIATION(w->w_pin.config);
1455 1.2.2.2 skrll if (conn == COP_PORT_NONE) {
1456 1.2.2.2 skrll hda_trace(w->w_afg, "disable %02X [no connectivity]\n",
1457 1.2.2.2 skrll w->w_nid);
1458 1.2.2.2 skrll w->w_enable = false;
1459 1.2.2.2 skrll }
1460 1.2.2.2 skrll if (assoc == 0) {
1461 1.2.2.2 skrll hda_trace(w->w_afg, "disable %02X [no association]\n",
1462 1.2.2.2 skrll w->w_nid);
1463 1.2.2.2 skrll w->w_enable = false;
1464 1.2.2.2 skrll }
1465 1.2.2.2 skrll }
1466 1.2.2.2 skrll
1467 1.2.2.2 skrll do {
1468 1.2.2.2 skrll done = 1;
1469 1.2.2.2 skrll /* Disable and mute controls for disabled widgets */
1470 1.2.2.2 skrll i = 0;
1471 1.2.2.2 skrll for (i = 0; i < sc->sc_nctls; i++) {
1472 1.2.2.2 skrll ctl = &sc->sc_ctls[i];
1473 1.2.2.2 skrll if (ctl->ctl_enable == false)
1474 1.2.2.2 skrll continue;
1475 1.2.2.2 skrll if (ctl->ctl_widget->w_enable == false ||
1476 1.2.2.2 skrll (ctl->ctl_childwidget != NULL &&
1477 1.2.2.2 skrll ctl->ctl_childwidget->w_enable == false)) {
1478 1.2.2.2 skrll ctl->ctl_forcemute = 1;
1479 1.2.2.2 skrll ctl->ctl_muted = HDAUDIO_AMP_MUTE_ALL;
1480 1.2.2.2 skrll ctl->ctl_left = ctl->ctl_right = 0;
1481 1.2.2.2 skrll ctl->ctl_enable = false;
1482 1.2.2.2 skrll if (ctl->ctl_ndir == HDAUDIO_PINDIR_IN)
1483 1.2.2.2 skrll ctl->ctl_widget->w_connsenable[
1484 1.2.2.2 skrll ctl->ctl_index] = false;
1485 1.2.2.2 skrll done = 0;
1486 1.2.2.2 skrll hda_trace(ctl->ctl_widget->w_afg,
1487 1.2.2.2 skrll "disable ctl %d:%02X:%02X [widget disabled]\n",
1488 1.2.2.2 skrll i, ctl->ctl_widget->w_nid,
1489 1.2.2.2 skrll ctl->ctl_childwidget ?
1490 1.2.2.2 skrll ctl->ctl_childwidget->w_nid : 0xff);
1491 1.2.2.2 skrll }
1492 1.2.2.2 skrll }
1493 1.2.2.2 skrll /* Disable useless widgets */
1494 1.2.2.2 skrll for (i = sc->sc_startnode; i < sc->sc_endnode; i++) {
1495 1.2.2.2 skrll w = hdafg_widget_lookup(sc, i);
1496 1.2.2.2 skrll if (w == NULL || w->w_enable == false)
1497 1.2.2.2 skrll continue;
1498 1.2.2.2 skrll /* Disable inputs with disabled child widgets */
1499 1.2.2.2 skrll for (j = 0; j < w->w_nconns; j++) {
1500 1.2.2.2 skrll if (!w->w_connsenable[j])
1501 1.2.2.2 skrll continue;
1502 1.2.2.2 skrll cw = hdafg_widget_lookup(sc,
1503 1.2.2.2 skrll w->w_conns[j]);
1504 1.2.2.2 skrll if (cw == NULL || cw->w_enable == false) {
1505 1.2.2.2 skrll w->w_connsenable[j] = false;
1506 1.2.2.2 skrll hda_trace(w->w_afg,
1507 1.2.2.2 skrll "disable conn %02X->%02X "
1508 1.2.2.2 skrll "[disabled child]\n",
1509 1.2.2.2 skrll w->w_nid, w->w_conns[j]);
1510 1.2.2.2 skrll }
1511 1.2.2.2 skrll }
1512 1.2.2.2 skrll if (w->w_type != COP_AWCAP_TYPE_AUDIO_SELECTOR &&
1513 1.2.2.2 skrll w->w_type != COP_AWCAP_TYPE_AUDIO_MIXER)
1514 1.2.2.2 skrll continue;
1515 1.2.2.2 skrll /* Disable mixers and selectors without inputs */
1516 1.2.2.2 skrll found = 0;
1517 1.2.2.2 skrll for (j = 0; j < w->w_nconns; j++)
1518 1.2.2.2 skrll if (w->w_connsenable[j]) {
1519 1.2.2.2 skrll found = 1;
1520 1.2.2.2 skrll break;
1521 1.2.2.2 skrll }
1522 1.2.2.2 skrll if (found == 0) {
1523 1.2.2.2 skrll w->w_enable = false;
1524 1.2.2.2 skrll done = 0;
1525 1.2.2.2 skrll hda_trace(w->w_afg,
1526 1.2.2.2 skrll "disable %02X [inputs disabled]\n",
1527 1.2.2.2 skrll w->w_nid);
1528 1.2.2.2 skrll }
1529 1.2.2.2 skrll /* Disable nodes without consumers */
1530 1.2.2.2 skrll if (w->w_type != COP_AWCAP_TYPE_AUDIO_SELECTOR &&
1531 1.2.2.2 skrll w->w_type != COP_AWCAP_TYPE_AUDIO_MIXER)
1532 1.2.2.2 skrll continue;
1533 1.2.2.2 skrll found = 0;
1534 1.2.2.2 skrll for (k = sc->sc_startnode; k < sc->sc_endnode; k++) {
1535 1.2.2.2 skrll cw = hdafg_widget_lookup(sc, k);
1536 1.2.2.2 skrll if (cw == NULL || cw->w_enable == false)
1537 1.2.2.2 skrll continue;
1538 1.2.2.2 skrll for (j = 0; j < cw->w_nconns; j++) {
1539 1.2.2.2 skrll if (cw->w_connsenable[j] &&
1540 1.2.2.2 skrll cw->w_conns[j] == i) {
1541 1.2.2.2 skrll found = 1;
1542 1.2.2.2 skrll break;
1543 1.2.2.2 skrll }
1544 1.2.2.2 skrll }
1545 1.2.2.2 skrll }
1546 1.2.2.2 skrll if (found == 0) {
1547 1.2.2.2 skrll w->w_enable = false;
1548 1.2.2.2 skrll done = 0;
1549 1.2.2.2 skrll hda_trace(w->w_afg,
1550 1.2.2.2 skrll "disable %02X [consumers disabled]\n",
1551 1.2.2.2 skrll w->w_nid);
1552 1.2.2.2 skrll }
1553 1.2.2.2 skrll }
1554 1.2.2.2 skrll } while (done == 0);
1555 1.2.2.2 skrll }
1556 1.2.2.2 skrll
1557 1.2.2.2 skrll static void
1558 1.2.2.2 skrll hdafg_assoc_trace_undo(struct hdafg_softc *sc, int as, int seq)
1559 1.2.2.2 skrll {
1560 1.2.2.2 skrll struct hdaudio_widget *w;
1561 1.2.2.2 skrll int i;
1562 1.2.2.2 skrll
1563 1.2.2.2 skrll for (i = sc->sc_startnode; i < sc->sc_endnode; i++) {
1564 1.2.2.2 skrll w = hdafg_widget_lookup(sc, i);
1565 1.2.2.2 skrll if (w == NULL || w->w_enable == false)
1566 1.2.2.2 skrll continue;
1567 1.2.2.2 skrll if (w->w_bindas != as)
1568 1.2.2.2 skrll continue;
1569 1.2.2.2 skrll if (seq >= 0) {
1570 1.2.2.2 skrll w->w_bindseqmask &= ~(1 << seq);
1571 1.2.2.2 skrll if (w->w_bindseqmask == 0) {
1572 1.2.2.2 skrll w->w_bindas = -1;
1573 1.2.2.2 skrll w->w_selconn = -1;
1574 1.2.2.2 skrll }
1575 1.2.2.2 skrll } else {
1576 1.2.2.2 skrll w->w_bindas = -1;
1577 1.2.2.2 skrll w->w_bindseqmask = 0;
1578 1.2.2.2 skrll w->w_selconn = -1;
1579 1.2.2.2 skrll }
1580 1.2.2.2 skrll }
1581 1.2.2.2 skrll }
1582 1.2.2.2 skrll
1583 1.2.2.2 skrll static int
1584 1.2.2.2 skrll hdafg_assoc_trace_dac(struct hdafg_softc *sc, int as, int seq,
1585 1.2.2.2 skrll int nid, int dupseq, int minassoc, int only, int depth)
1586 1.2.2.2 skrll {
1587 1.2.2.2 skrll struct hdaudio_widget *w;
1588 1.2.2.2 skrll int i, im = -1;
1589 1.2.2.2 skrll int m = 0, ret;
1590 1.2.2.2 skrll
1591 1.2.2.2 skrll if (depth >= HDAUDIO_PARSE_MAXDEPTH)
1592 1.2.2.2 skrll return 0;
1593 1.2.2.2 skrll w = hdafg_widget_lookup(sc, nid);
1594 1.2.2.2 skrll if (w == NULL || w->w_enable == false)
1595 1.2.2.2 skrll return 0;
1596 1.2.2.2 skrll /* We use only unused widgets */
1597 1.2.2.2 skrll if (w->w_bindas >= 0 && w->w_bindas != as) {
1598 1.2.2.2 skrll if (!only)
1599 1.2.2.2 skrll hda_trace(sc, "depth %d nid %02X busy by assoc %d\n",
1600 1.2.2.2 skrll depth + 1, nid, w->w_bindas);
1601 1.2.2.2 skrll return 0;
1602 1.2.2.2 skrll }
1603 1.2.2.2 skrll if (dupseq < 0) {
1604 1.2.2.2 skrll if (w->w_bindseqmask != 0) {
1605 1.2.2.2 skrll if (!only)
1606 1.2.2.2 skrll hda_trace(sc,
1607 1.2.2.2 skrll "depth %d nid %02X busy by seqmask %x\n",
1608 1.2.2.2 skrll depth + 1, nid, w->w_bindas);
1609 1.2.2.2 skrll return 0;
1610 1.2.2.2 skrll }
1611 1.2.2.2 skrll } else {
1612 1.2.2.2 skrll /* If this is headphones, allow duplicate first pin */
1613 1.2.2.2 skrll if (w->w_bindseqmask != 0 &&
1614 1.2.2.2 skrll (w->w_bindseqmask & (1 << dupseq)) == 0)
1615 1.2.2.2 skrll return 0;
1616 1.2.2.2 skrll }
1617 1.2.2.2 skrll
1618 1.2.2.2 skrll switch (w->w_type) {
1619 1.2.2.2 skrll case COP_AWCAP_TYPE_AUDIO_INPUT:
1620 1.2.2.2 skrll break;
1621 1.2.2.2 skrll case COP_AWCAP_TYPE_AUDIO_OUTPUT:
1622 1.2.2.2 skrll /* If we are tracing HP take only dac of first pin */
1623 1.2.2.2 skrll if ((only == 0 || only == w->w_nid) &&
1624 1.2.2.2 skrll (w->w_nid >= minassoc) && (dupseq < 0 || w->w_nid ==
1625 1.2.2.2 skrll sc->sc_assocs[as].as_dacs[dupseq]))
1626 1.2.2.2 skrll m = w->w_nid;
1627 1.2.2.2 skrll break;
1628 1.2.2.2 skrll case COP_AWCAP_TYPE_PIN_COMPLEX:
1629 1.2.2.2 skrll if (depth > 0)
1630 1.2.2.2 skrll break;
1631 1.2.2.2 skrll /* FALLTHROUGH */
1632 1.2.2.2 skrll default:
1633 1.2.2.2 skrll for (i = 0; i < w->w_nconns; i++) {
1634 1.2.2.2 skrll if (w->w_connsenable[i] == false)
1635 1.2.2.2 skrll continue;
1636 1.2.2.2 skrll if (w->w_selconn != -1 && w->w_selconn != i)
1637 1.2.2.2 skrll continue;
1638 1.2.2.2 skrll ret = hdafg_assoc_trace_dac(sc, as, seq,
1639 1.2.2.2 skrll w->w_conns[i], dupseq, minassoc, only, depth + 1);
1640 1.2.2.2 skrll if (ret) {
1641 1.2.2.2 skrll if (m == 0 || ret < m) {
1642 1.2.2.2 skrll m = ret;
1643 1.2.2.2 skrll im = i;
1644 1.2.2.2 skrll }
1645 1.2.2.2 skrll if (only || dupseq >= 0)
1646 1.2.2.2 skrll break;
1647 1.2.2.2 skrll }
1648 1.2.2.2 skrll }
1649 1.2.2.2 skrll if (m && only && ((w->w_nconns > 1 &&
1650 1.2.2.2 skrll w->w_type != COP_AWCAP_TYPE_AUDIO_MIXER) ||
1651 1.2.2.2 skrll w->w_type == COP_AWCAP_TYPE_AUDIO_SELECTOR))
1652 1.2.2.2 skrll w->w_selconn = im;
1653 1.2.2.2 skrll break;
1654 1.2.2.2 skrll }
1655 1.2.2.2 skrll if (m && only) {
1656 1.2.2.2 skrll w->w_bindas = as;
1657 1.2.2.2 skrll w->w_bindseqmask |= (1 << seq);
1658 1.2.2.2 skrll }
1659 1.2.2.2 skrll if (!only)
1660 1.2.2.2 skrll hda_trace(sc, "depth %d nid %02X dupseq %d returned %02X\n",
1661 1.2.2.2 skrll depth + 1, nid, dupseq, m);
1662 1.2.2.2 skrll
1663 1.2.2.2 skrll return m;
1664 1.2.2.2 skrll }
1665 1.2.2.2 skrll
1666 1.2.2.3 skrll static int
1667 1.2.2.2 skrll hdafg_assoc_trace_out(struct hdafg_softc *sc, int as, int seq)
1668 1.2.2.2 skrll {
1669 1.2.2.2 skrll struct hdaudio_assoc *assocs = sc->sc_assocs;
1670 1.2.2.2 skrll int i, hpredir;
1671 1.2.2.2 skrll int minassoc, res;
1672 1.2.2.2 skrll
1673 1.2.2.2 skrll /* Find next pin */
1674 1.2.2.2 skrll for (i = seq; i < HDAUDIO_MAXPINS && assocs[as].as_pins[i] == 0; i++)
1675 1.2.2.2 skrll ;
1676 1.2.2.2 skrll /* Check if there is any left, if not then we have succeeded */
1677 1.2.2.2 skrll if (i == HDAUDIO_MAXPINS)
1678 1.2.2.2 skrll return 1;
1679 1.2.2.2 skrll
1680 1.2.2.2 skrll hpredir = (i == 15 && assocs[as].as_fakeredir == 0) ?
1681 1.2.2.2 skrll assocs[as].as_hpredir : -1;
1682 1.2.2.2 skrll minassoc = res = 0;
1683 1.2.2.2 skrll do {
1684 1.2.2.2 skrll /* Trace this pin taking min nid into account */
1685 1.2.2.2 skrll res = hdafg_assoc_trace_dac(sc, as, i,
1686 1.2.2.2 skrll assocs[as].as_pins[i], hpredir, minassoc, 0, 0);
1687 1.2.2.2 skrll if (res == 0) {
1688 1.2.2.2 skrll /* If we failed, return to previous and redo it */
1689 1.2.2.2 skrll hda_trace(sc, " trace failed as=%d seq=%d pin=%02X "
1690 1.2.2.2 skrll "hpredir=%d minassoc=%d\n",
1691 1.2.2.2 skrll as, seq, assocs[as].as_pins[i], hpredir, minassoc);
1692 1.2.2.2 skrll return 0;
1693 1.2.2.2 skrll }
1694 1.2.2.2 skrll /* Trace again to mark the path */
1695 1.2.2.2 skrll hdafg_assoc_trace_dac(sc, as, i,
1696 1.2.2.2 skrll assocs[as].as_pins[i], hpredir, minassoc, res, 0);
1697 1.2.2.2 skrll assocs[as].as_dacs[i] = res;
1698 1.2.2.2 skrll /* We succeeded, so call next */
1699 1.2.2.2 skrll if (hdafg_assoc_trace_out(sc, as, i + 1))
1700 1.2.2.2 skrll return 1;
1701 1.2.2.2 skrll /* If next failed, we should retry with next min */
1702 1.2.2.2 skrll hdafg_assoc_trace_undo(sc, as, i);
1703 1.2.2.2 skrll assocs[as].as_dacs[i] = 0;
1704 1.2.2.2 skrll minassoc = res + 1;
1705 1.2.2.2 skrll } while (1);
1706 1.2.2.2 skrll }
1707 1.2.2.2 skrll
1708 1.2.2.2 skrll static int
1709 1.2.2.2 skrll hdafg_assoc_trace_adc(struct hdafg_softc *sc, int assoc, int seq,
1710 1.2.2.2 skrll int nid, int only, int depth)
1711 1.2.2.2 skrll {
1712 1.2.2.2 skrll struct hdaudio_widget *w, *wc;
1713 1.2.2.2 skrll int i, j;
1714 1.2.2.2 skrll int res = 0;
1715 1.2.2.2 skrll
1716 1.2.2.2 skrll if (depth > HDAUDIO_PARSE_MAXDEPTH)
1717 1.2.2.2 skrll return 0;
1718 1.2.2.2 skrll w = hdafg_widget_lookup(sc, nid);
1719 1.2.2.2 skrll if (w == NULL || w->w_enable == false)
1720 1.2.2.2 skrll return 0;
1721 1.2.2.2 skrll /* Use only unused widgets */
1722 1.2.2.2 skrll if (w->w_bindas >= 0 && w->w_bindas != assoc)
1723 1.2.2.2 skrll return 0;
1724 1.2.2.2 skrll
1725 1.2.2.2 skrll switch (w->w_type) {
1726 1.2.2.2 skrll case COP_AWCAP_TYPE_AUDIO_INPUT:
1727 1.2.2.2 skrll if (only == w->w_nid)
1728 1.2.2.2 skrll res = 1;
1729 1.2.2.2 skrll break;
1730 1.2.2.2 skrll case COP_AWCAP_TYPE_PIN_COMPLEX:
1731 1.2.2.2 skrll if (depth > 0)
1732 1.2.2.2 skrll break;
1733 1.2.2.2 skrll /* FALLTHROUGH */
1734 1.2.2.2 skrll default:
1735 1.2.2.2 skrll /* Try to find reachable ADCs with specified nid */
1736 1.2.2.2 skrll for (j = sc->sc_startnode; j < sc->sc_endnode; j++) {
1737 1.2.2.2 skrll wc = hdafg_widget_lookup(sc, j);
1738 1.2.2.2 skrll if (w == NULL || w->w_enable == false)
1739 1.2.2.2 skrll continue;
1740 1.2.2.2 skrll for (i = 0; i < wc->w_nconns; i++) {
1741 1.2.2.2 skrll if (wc->w_connsenable[i] == false)
1742 1.2.2.2 skrll continue;
1743 1.2.2.2 skrll if (wc->w_conns[i] != nid)
1744 1.2.2.2 skrll continue;
1745 1.2.2.2 skrll if (hdafg_assoc_trace_adc(sc, assoc, seq,
1746 1.2.2.2 skrll j, only, depth + 1) != 0) {
1747 1.2.2.2 skrll res = 1;
1748 1.2.2.2 skrll if (((wc->w_nconns > 1 &&
1749 1.2.2.2 skrll wc->w_type != COP_AWCAP_TYPE_AUDIO_MIXER) ||
1750 1.2.2.2 skrll wc->w_type != COP_AWCAP_TYPE_AUDIO_SELECTOR)
1751 1.2.2.2 skrll && wc->w_selconn == -1)
1752 1.2.2.2 skrll wc->w_selconn = i;
1753 1.2.2.2 skrll }
1754 1.2.2.2 skrll }
1755 1.2.2.2 skrll }
1756 1.2.2.2 skrll break;
1757 1.2.2.2 skrll }
1758 1.2.2.2 skrll if (res) {
1759 1.2.2.2 skrll w->w_bindas = assoc;
1760 1.2.2.2 skrll w->w_bindseqmask |= (1 << seq);
1761 1.2.2.2 skrll }
1762 1.2.2.2 skrll return res;
1763 1.2.2.2 skrll }
1764 1.2.2.2 skrll
1765 1.2.2.2 skrll static int
1766 1.2.2.2 skrll hdafg_assoc_trace_in(struct hdafg_softc *sc, int assoc)
1767 1.2.2.2 skrll {
1768 1.2.2.2 skrll struct hdaudio_assoc *as = sc->sc_assocs;
1769 1.2.2.2 skrll struct hdaudio_widget *w;
1770 1.2.2.2 skrll int i, j, k;
1771 1.2.2.2 skrll
1772 1.2.2.2 skrll for (j = sc->sc_startnode; j < sc->sc_endnode; j++) {
1773 1.2.2.2 skrll w = hdafg_widget_lookup(sc, j);
1774 1.2.2.2 skrll if (w == NULL || w->w_enable == false)
1775 1.2.2.2 skrll continue;
1776 1.2.2.2 skrll if (w->w_type != COP_AWCAP_TYPE_AUDIO_INPUT)
1777 1.2.2.2 skrll continue;
1778 1.2.2.2 skrll if (w->w_bindas >= 0 && w->w_bindas != assoc)
1779 1.2.2.2 skrll continue;
1780 1.2.2.2 skrll
1781 1.2.2.2 skrll /* Find next pin */
1782 1.2.2.2 skrll for (i = 0; i < HDAUDIO_MAXPINS; i++) {
1783 1.2.2.2 skrll if (as[assoc].as_pins[i] == 0)
1784 1.2.2.2 skrll continue;
1785 1.2.2.2 skrll /* Trace this pin taking goal into account */
1786 1.2.2.2 skrll if (hdafg_assoc_trace_adc(sc, assoc, i,
1787 1.2.2.2 skrll as[assoc].as_pins[i], j, 0) == 0) {
1788 1.2.2.2 skrll hdafg_assoc_trace_undo(sc, assoc, -1);
1789 1.2.2.2 skrll for (k = 0; k < HDAUDIO_MAXPINS; k++)
1790 1.2.2.2 skrll as[assoc].as_dacs[k] = 0;
1791 1.2.2.2 skrll break;
1792 1.2.2.2 skrll }
1793 1.2.2.2 skrll as[assoc].as_dacs[i] = j;
1794 1.2.2.2 skrll }
1795 1.2.2.2 skrll if (i == HDAUDIO_MAXPINS)
1796 1.2.2.2 skrll return 1;
1797 1.2.2.2 skrll }
1798 1.2.2.2 skrll return 0;
1799 1.2.2.2 skrll }
1800 1.2.2.2 skrll
1801 1.2.2.2 skrll static int
1802 1.2.2.2 skrll hdafg_assoc_trace_to_out(struct hdafg_softc *sc, int nid, int depth)
1803 1.2.2.2 skrll {
1804 1.2.2.2 skrll struct hdaudio_assoc *as = sc->sc_assocs;
1805 1.2.2.2 skrll struct hdaudio_widget *w, *wc;
1806 1.2.2.2 skrll int i, j;
1807 1.2.2.2 skrll int res = 0;
1808 1.2.2.2 skrll
1809 1.2.2.2 skrll if (depth > HDAUDIO_PARSE_MAXDEPTH)
1810 1.2.2.2 skrll return 0;
1811 1.2.2.2 skrll w = hdafg_widget_lookup(sc, nid);
1812 1.2.2.2 skrll if (w == NULL || w->w_enable == false)
1813 1.2.2.2 skrll return 0;
1814 1.2.2.2 skrll
1815 1.2.2.2 skrll /* Use only unused widgets */
1816 1.2.2.2 skrll if (depth > 0 && w->w_bindas != -1) {
1817 1.2.2.2 skrll if (w->w_bindas < 0 ||
1818 1.2.2.2 skrll as[w->w_bindas].as_dir == HDAUDIO_PINDIR_OUT) {
1819 1.2.2.2 skrll return 1;
1820 1.2.2.2 skrll } else {
1821 1.2.2.2 skrll return 0;
1822 1.2.2.2 skrll }
1823 1.2.2.2 skrll }
1824 1.2.2.2 skrll
1825 1.2.2.2 skrll switch (w->w_type) {
1826 1.2.2.2 skrll case COP_AWCAP_TYPE_AUDIO_INPUT:
1827 1.2.2.2 skrll /* Do not traverse input (not yet supported) */
1828 1.2.2.2 skrll break;
1829 1.2.2.2 skrll case COP_AWCAP_TYPE_PIN_COMPLEX:
1830 1.2.2.2 skrll if (depth > 0)
1831 1.2.2.2 skrll break;
1832 1.2.2.2 skrll /* FALLTHROUGH */
1833 1.2.2.2 skrll default:
1834 1.2.2.2 skrll /* Try to find reachable ADCs with specified nid */
1835 1.2.2.2 skrll for (j = sc->sc_startnode; j < sc->sc_endnode; j++) {
1836 1.2.2.2 skrll wc = hdafg_widget_lookup(sc, j);
1837 1.2.2.2 skrll if (wc == NULL || wc->w_enable == false)
1838 1.2.2.2 skrll continue;
1839 1.2.2.2 skrll for (i = 0; i < wc->w_nconns; i++) {
1840 1.2.2.2 skrll if (wc->w_connsenable[i] == false)
1841 1.2.2.2 skrll continue;
1842 1.2.2.2 skrll if (wc->w_conns[i] != nid)
1843 1.2.2.2 skrll continue;
1844 1.2.2.2 skrll if (hdafg_assoc_trace_to_out(sc,
1845 1.2.2.2 skrll j, depth + 1) != 0) {
1846 1.2.2.2 skrll res = 1;
1847 1.2.2.2 skrll if (wc->w_type ==
1848 1.2.2.2 skrll COP_AWCAP_TYPE_AUDIO_SELECTOR &&
1849 1.2.2.2 skrll wc->w_selconn == -1)
1850 1.2.2.2 skrll wc->w_selconn = i;
1851 1.2.2.2 skrll }
1852 1.2.2.2 skrll }
1853 1.2.2.2 skrll }
1854 1.2.2.2 skrll break;
1855 1.2.2.2 skrll }
1856 1.2.2.2 skrll if (res)
1857 1.2.2.2 skrll w->w_bindas = -2;
1858 1.2.2.2 skrll return res;
1859 1.2.2.2 skrll }
1860 1.2.2.2 skrll
1861 1.2.2.2 skrll static void
1862 1.2.2.2 skrll hdafg_assoc_trace_misc(struct hdafg_softc *sc)
1863 1.2.2.2 skrll {
1864 1.2.2.2 skrll struct hdaudio_assoc *as = sc->sc_assocs;
1865 1.2.2.2 skrll struct hdaudio_widget *w;
1866 1.2.2.2 skrll int j;
1867 1.2.2.2 skrll
1868 1.2.2.2 skrll /* Input monitor */
1869 1.2.2.2 skrll /*
1870 1.2.2.2 skrll * Find mixer associated with input, but supplying signal
1871 1.2.2.2 skrll * for output associations. Hope it will be input monitor.
1872 1.2.2.2 skrll */
1873 1.2.2.2 skrll for (j = sc->sc_startnode; j < sc->sc_endnode; j++) {
1874 1.2.2.2 skrll w = hdafg_widget_lookup(sc, j);
1875 1.2.2.2 skrll if (w == NULL || w->w_enable == false)
1876 1.2.2.2 skrll continue;
1877 1.2.2.2 skrll if (w->w_type != COP_AWCAP_TYPE_AUDIO_MIXER)
1878 1.2.2.2 skrll continue;
1879 1.2.2.2 skrll if (w->w_bindas < 0 ||
1880 1.2.2.2 skrll as[w->w_bindas].as_dir != HDAUDIO_PINDIR_IN)
1881 1.2.2.2 skrll continue;
1882 1.2.2.2 skrll if (hdafg_assoc_trace_to_out(sc, w->w_nid, 0)) {
1883 1.2.2.2 skrll w->w_pflags |= HDAUDIO_ADC_MONITOR;
1884 1.2.2.2 skrll w->w_audiodev = HDAUDIO_MIXER_IMIX;
1885 1.2.2.2 skrll }
1886 1.2.2.2 skrll }
1887 1.2.2.2 skrll
1888 1.2.2.2 skrll /* Beeper */
1889 1.2.2.2 skrll for (j = sc->sc_startnode; j < sc->sc_endnode; j++) {
1890 1.2.2.2 skrll w = hdafg_widget_lookup(sc, j);
1891 1.2.2.2 skrll if (w == NULL || w->w_enable == false)
1892 1.2.2.2 skrll continue;
1893 1.2.2.2 skrll if (w->w_type != COP_AWCAP_TYPE_BEEP_GENERATOR)
1894 1.2.2.2 skrll continue;
1895 1.2.2.2 skrll if (hdafg_assoc_trace_to_out(sc, w->w_nid, 0)) {
1896 1.2.2.2 skrll hda_debug(sc, "beeper %02X traced to out\n", w->w_nid);
1897 1.2.2.2 skrll }
1898 1.2.2.2 skrll w->w_bindas = -2;
1899 1.2.2.2 skrll }
1900 1.2.2.2 skrll }
1901 1.2.2.2 skrll
1902 1.2.2.2 skrll static void
1903 1.2.2.2 skrll hdafg_build_tree(struct hdafg_softc *sc)
1904 1.2.2.2 skrll {
1905 1.2.2.2 skrll struct hdaudio_assoc *as = sc->sc_assocs;
1906 1.2.2.2 skrll int i, j, res;
1907 1.2.2.2 skrll
1908 1.2.2.2 skrll /* Trace all associations in order of their numbers */
1909 1.2.2.2 skrll
1910 1.2.2.2 skrll /* Trace DACs first */
1911 1.2.2.2 skrll for (j = 0; j < sc->sc_nassocs; j++) {
1912 1.2.2.2 skrll if (as[j].as_enable == false)
1913 1.2.2.2 skrll continue;
1914 1.2.2.2 skrll if (as[j].as_dir != HDAUDIO_PINDIR_OUT)
1915 1.2.2.2 skrll continue;
1916 1.2.2.2 skrll retry:
1917 1.2.2.2 skrll res = hdafg_assoc_trace_out(sc, j, 0);
1918 1.2.2.2 skrll if (res == 0 && as[j].as_hpredir >= 0 &&
1919 1.2.2.2 skrll as[j].as_fakeredir == 0) {
1920 1.2.2.2 skrll /*
1921 1.2.2.2 skrll * If codec can't do analog HP redirection
1922 1.2.2.2 skrll * try to make it using one more DAC
1923 1.2.2.2 skrll */
1924 1.2.2.2 skrll as[j].as_fakeredir = 1;
1925 1.2.2.2 skrll goto retry;
1926 1.2.2.2 skrll }
1927 1.2.2.2 skrll if (!res) {
1928 1.2.2.2 skrll hda_debug(sc, "disable assoc %d (%d) [trace failed]\n",
1929 1.2.2.2 skrll j, as[j].as_index);
1930 1.2.2.2 skrll for (i = 0; i < HDAUDIO_MAXPINS; i++) {
1931 1.2.2.2 skrll if (as[j].as_pins[i] == 0)
1932 1.2.2.2 skrll continue;
1933 1.2.2.2 skrll hda_debug(sc, " assoc %d pin%d: %02X\n", j, i,
1934 1.2.2.2 skrll as[j].as_pins[i]);
1935 1.2.2.2 skrll }
1936 1.2.2.2 skrll for (i = 0; i < HDAUDIO_MAXPINS; i++) {
1937 1.2.2.2 skrll if (as[j].as_dacs[i] == 0)
1938 1.2.2.2 skrll continue;
1939 1.2.2.2 skrll hda_debug(sc, " assoc %d dac%d: %02X\n", j, i,
1940 1.2.2.2 skrll as[j].as_dacs[i]);
1941 1.2.2.2 skrll }
1942 1.2.2.2 skrll
1943 1.2.2.2 skrll as[j].as_enable = false;
1944 1.2.2.2 skrll }
1945 1.2.2.2 skrll }
1946 1.2.2.2 skrll
1947 1.2.2.2 skrll /* Trace ADCs */
1948 1.2.2.2 skrll for (j = 0; j < sc->sc_nassocs; j++) {
1949 1.2.2.2 skrll if (as[j].as_enable == false)
1950 1.2.2.2 skrll continue;
1951 1.2.2.2 skrll if (as[j].as_dir != HDAUDIO_PINDIR_IN)
1952 1.2.2.2 skrll continue;
1953 1.2.2.2 skrll res = hdafg_assoc_trace_in(sc, j);
1954 1.2.2.2 skrll if (!res) {
1955 1.2.2.2 skrll hda_debug(sc, "disable assoc %d (%d) [trace failed]\n",
1956 1.2.2.2 skrll j, as[j].as_index);
1957 1.2.2.2 skrll for (i = 0; i < HDAUDIO_MAXPINS; i++) {
1958 1.2.2.2 skrll if (as[j].as_pins[i] == 0)
1959 1.2.2.2 skrll continue;
1960 1.2.2.2 skrll hda_debug(sc, " assoc %d pin%d: %02X\n", j, i,
1961 1.2.2.2 skrll as[j].as_pins[i]);
1962 1.2.2.2 skrll }
1963 1.2.2.2 skrll for (i = 0; i < HDAUDIO_MAXPINS; i++) {
1964 1.2.2.2 skrll if (as[j].as_dacs[i] == 0)
1965 1.2.2.2 skrll continue;
1966 1.2.2.2 skrll hda_debug(sc, " assoc %d adc%d: %02X\n", j, i,
1967 1.2.2.2 skrll as[j].as_dacs[i]);
1968 1.2.2.2 skrll }
1969 1.2.2.2 skrll
1970 1.2.2.2 skrll as[j].as_enable = false;
1971 1.2.2.2 skrll }
1972 1.2.2.2 skrll }
1973 1.2.2.2 skrll
1974 1.2.2.2 skrll /* Trace mixer and beeper pseudo associations */
1975 1.2.2.2 skrll hdafg_assoc_trace_misc(sc);
1976 1.2.2.2 skrll }
1977 1.2.2.2 skrll
1978 1.2.2.2 skrll static void
1979 1.2.2.2 skrll hdafg_prepare_pin_controls(struct hdafg_softc *sc)
1980 1.2.2.2 skrll {
1981 1.2.2.2 skrll struct hdaudio_assoc *as = sc->sc_assocs;
1982 1.2.2.2 skrll struct hdaudio_widget *w;
1983 1.2.2.2 skrll uint32_t pincap;
1984 1.2.2.2 skrll int i;
1985 1.2.2.2 skrll
1986 1.2.2.2 skrll hda_debug(sc, "*** prepare pin controls, nwidgets = %d\n",
1987 1.2.2.2 skrll sc->sc_nwidgets);
1988 1.2.2.2 skrll
1989 1.2.2.2 skrll for (i = 0; i < sc->sc_nwidgets; i++) {
1990 1.2.2.2 skrll w = &sc->sc_widgets[i];
1991 1.2.2.2 skrll if (w->w_type != COP_AWCAP_TYPE_PIN_COMPLEX) {
1992 1.2.2.2 skrll hda_debug(sc, " skipping pin %02X type 0x%x\n",
1993 1.2.2.2 skrll w->w_nid, w->w_type);
1994 1.2.2.2 skrll continue;
1995 1.2.2.2 skrll }
1996 1.2.2.2 skrll pincap = w->w_pin.cap;
1997 1.2.2.2 skrll
1998 1.2.2.2 skrll /* Disable everything */
1999 1.2.2.2 skrll w->w_pin.ctrl &= ~(
2000 1.2.2.2 skrll COP_PWC_VREF_ENABLE_MASK |
2001 1.2.2.2 skrll COP_PWC_IN_ENABLE |
2002 1.2.2.2 skrll COP_PWC_OUT_ENABLE |
2003 1.2.2.2 skrll COP_PWC_HPHN_ENABLE);
2004 1.2.2.2 skrll
2005 1.2.2.2 skrll if (w->w_enable == false ||
2006 1.2.2.2 skrll w->w_bindas < 0 || as[w->w_bindas].as_enable == false) {
2007 1.2.2.2 skrll /* Pin is unused so leave it disabled */
2008 1.2.2.2 skrll if ((pincap & (COP_PINCAP_OUTPUT_CAPABLE |
2009 1.2.2.2 skrll COP_PINCAP_INPUT_CAPABLE)) ==
2010 1.2.2.2 skrll (COP_PINCAP_OUTPUT_CAPABLE |
2011 1.2.2.2 skrll COP_PINCAP_INPUT_CAPABLE)) {
2012 1.2.2.2 skrll hda_debug(sc, "pin %02X off, "
2013 1.2.2.2 skrll "in/out capable (bindas=%d "
2014 1.2.2.2 skrll "enable=%d as_enable=%d)\n",
2015 1.2.2.2 skrll w->w_nid, w->w_bindas, w->w_enable,
2016 1.2.2.2 skrll w->w_bindas >= 0 ?
2017 1.2.2.2 skrll as[w->w_bindas].as_enable : -1);
2018 1.2.2.2 skrll w->w_pin.ctrl |= COP_PWC_OUT_ENABLE;
2019 1.2.2.2 skrll } else
2020 1.2.2.2 skrll hda_debug(sc, "pin %02X off\n", w->w_nid);
2021 1.2.2.2 skrll continue;
2022 1.2.2.2 skrll } else if (as[w->w_bindas].as_dir == HDAUDIO_PINDIR_IN) {
2023 1.2.2.2 skrll /* Input pin, configure for input */
2024 1.2.2.2 skrll if (pincap & COP_PINCAP_INPUT_CAPABLE)
2025 1.2.2.2 skrll w->w_pin.ctrl |= COP_PWC_IN_ENABLE;
2026 1.2.2.2 skrll
2027 1.2.2.2 skrll hda_debug(sc, "pin %02X in ctrl 0x%x\n", w->w_nid,
2028 1.2.2.2 skrll w->w_pin.ctrl);
2029 1.2.2.2 skrll
2030 1.2.2.2 skrll if (COP_CFG_DEFAULT_DEVICE(w->w_pin.config) !=
2031 1.2.2.2 skrll COP_DEVICE_MIC_IN)
2032 1.2.2.2 skrll continue;
2033 1.2.2.2 skrll if (COP_PINCAP_VREF_CONTROL(pincap) & COP_VREF_80)
2034 1.2.2.2 skrll w->w_pin.ctrl |= COP_PWC_VREF_80;
2035 1.2.2.2 skrll else if (COP_PINCAP_VREF_CONTROL(pincap) & COP_VREF_50)
2036 1.2.2.2 skrll w->w_pin.ctrl |= COP_PWC_VREF_50;
2037 1.2.2.2 skrll } else {
2038 1.2.2.2 skrll /* Output pin, configure for output */
2039 1.2.2.2 skrll if (pincap & COP_PINCAP_OUTPUT_CAPABLE)
2040 1.2.2.2 skrll w->w_pin.ctrl |= COP_PWC_OUT_ENABLE;
2041 1.2.2.2 skrll if ((pincap & COP_PINCAP_HEADPHONE_DRIVE_CAPABLE) &&
2042 1.2.2.2 skrll (COP_CFG_DEFAULT_DEVICE(w->w_pin.config) ==
2043 1.2.2.2 skrll COP_DEVICE_HP_OUT))
2044 1.2.2.2 skrll w->w_pin.ctrl |= COP_PWC_HPHN_ENABLE;
2045 1.2.2.2 skrll /* XXX VREF */
2046 1.2.2.2 skrll hda_debug(sc, "pin %02X out ctrl 0x%x\n", w->w_nid,
2047 1.2.2.2 skrll w->w_pin.ctrl);
2048 1.2.2.2 skrll }
2049 1.2.2.2 skrll }
2050 1.2.2.2 skrll }
2051 1.2.2.2 skrll
2052 1.2.2.2 skrll static void
2053 1.2.2.2 skrll hdafg_dump(struct hdafg_softc *sc)
2054 1.2.2.2 skrll {
2055 1.2.2.2 skrll #if defined(HDAFG_DEBUG) && HDAFG_DEBUG > 1
2056 1.2.2.2 skrll struct hdaudio_control *ctl;
2057 1.2.2.2 skrll int i, type;
2058 1.2.2.2 skrll
2059 1.2.2.2 skrll for (i = 0; i < sc->sc_nctls; i++) {
2060 1.2.2.2 skrll ctl = &sc->sc_ctls[i];
2061 1.2.2.2 skrll type = (ctl->ctl_widget ? ctl->ctl_widget->w_type : -1);
2062 1.2.2.2 skrll hda_print(sc, "%03X: nid %02X type %d %s (%s) index %d",
2063 1.2.2.2 skrll i, (ctl->ctl_widget ? ctl->ctl_widget->w_nid : -1), type,
2064 1.2.2.2 skrll (ctl->ctl_ndir == HDAUDIO_PINDIR_IN) ? "in " : "out",
2065 1.2.2.2 skrll (ctl->ctl_dir == HDAUDIO_PINDIR_IN) ? "in " : "out",
2066 1.2.2.2 skrll ctl->ctl_index);
2067 1.2.2.2 skrll if (ctl->ctl_childwidget)
2068 1.2.2.2 skrll hda_print1(sc, " cnid %02X",
2069 1.2.2.2 skrll ctl->ctl_childwidget->w_nid);
2070 1.2.2.2 skrll else
2071 1.2.2.2 skrll hda_print1(sc, " ");
2072 1.2.2.2 skrll hda_print1(sc, "\n");
2073 1.2.2.2 skrll hda_print(sc, " mute: %d step: %3d size: %3d off: %3d%s\n",
2074 1.2.2.2 skrll ctl->ctl_mute, ctl->ctl_step, ctl->ctl_size,
2075 1.2.2.2 skrll ctl->ctl_offset,
2076 1.2.2.2 skrll (ctl->ctl_enable == false) ? " [DISABLED]" : "");
2077 1.2.2.2 skrll }
2078 1.2.2.2 skrll #endif
2079 1.2.2.2 skrll }
2080 1.2.2.2 skrll
2081 1.2.2.2 skrll static int
2082 1.2.2.2 skrll hdafg_match(device_t parent, cfdata_t match, void *opaque)
2083 1.2.2.2 skrll {
2084 1.2.2.2 skrll prop_dictionary_t args = opaque;
2085 1.2.2.2 skrll uint8_t fgtype;
2086 1.2.2.2 skrll bool rv;
2087 1.2.2.2 skrll
2088 1.2.2.2 skrll rv = prop_dictionary_get_uint8(args, "function-group-type", &fgtype);
2089 1.2.2.2 skrll if (rv == false || fgtype != HDAUDIO_GROUP_TYPE_AFG)
2090 1.2.2.2 skrll return 0;
2091 1.2.2.2 skrll
2092 1.2.2.2 skrll return 1;
2093 1.2.2.2 skrll }
2094 1.2.2.2 skrll
2095 1.2.2.2 skrll static void
2096 1.2.2.2 skrll hdafg_disable_unassoc(struct hdafg_softc *sc)
2097 1.2.2.2 skrll {
2098 1.2.2.2 skrll struct hdaudio_assoc *as = sc->sc_assocs;
2099 1.2.2.2 skrll struct hdaudio_widget *w, *cw;
2100 1.2.2.2 skrll struct hdaudio_control *ctl;
2101 1.2.2.2 skrll int i, j, k;
2102 1.2.2.2 skrll
2103 1.2.2.2 skrll /* Disable unassociated widgets */
2104 1.2.2.2 skrll for (i = sc->sc_startnode; i < sc->sc_endnode; i++) {
2105 1.2.2.2 skrll w = hdafg_widget_lookup(sc, i);
2106 1.2.2.2 skrll if (w == NULL || w->w_enable == false)
2107 1.2.2.2 skrll continue;
2108 1.2.2.2 skrll if (w->w_bindas == -1) {
2109 1.2.2.2 skrll w->w_enable = 0;
2110 1.2.2.2 skrll hda_trace(sc, "disable %02X [unassociated]\n",
2111 1.2.2.2 skrll w->w_nid);
2112 1.2.2.2 skrll }
2113 1.2.2.2 skrll }
2114 1.2.2.2 skrll
2115 1.2.2.2 skrll /* Disable input connections on input pin and output on output */
2116 1.2.2.2 skrll for (i = sc->sc_startnode; i < sc->sc_endnode; i++) {
2117 1.2.2.2 skrll w = hdafg_widget_lookup(sc, i);
2118 1.2.2.2 skrll if (w == NULL || w->w_enable == false)
2119 1.2.2.2 skrll continue;
2120 1.2.2.2 skrll if (w->w_type != COP_AWCAP_TYPE_PIN_COMPLEX)
2121 1.2.2.2 skrll continue;
2122 1.2.2.2 skrll if (w->w_bindas < 0)
2123 1.2.2.2 skrll continue;
2124 1.2.2.2 skrll if (as[w->w_bindas].as_dir == HDAUDIO_PINDIR_IN) {
2125 1.2.2.2 skrll hda_trace(sc, "disable %02X input connections\n",
2126 1.2.2.2 skrll w->w_nid);
2127 1.2.2.2 skrll for (j = 0; j < w->w_nconns; j++)
2128 1.2.2.2 skrll w->w_connsenable[j] = false;
2129 1.2.2.2 skrll ctl = hdafg_control_lookup(sc, w->w_nid,
2130 1.2.2.2 skrll HDAUDIO_PINDIR_IN, -1, 1);
2131 1.2.2.2 skrll if (ctl && ctl->ctl_enable == true) {
2132 1.2.2.2 skrll ctl->ctl_forcemute = 1;
2133 1.2.2.2 skrll ctl->ctl_muted = HDAUDIO_AMP_MUTE_ALL;
2134 1.2.2.2 skrll ctl->ctl_left = ctl->ctl_right = 0;
2135 1.2.2.2 skrll ctl->ctl_enable = false;
2136 1.2.2.2 skrll }
2137 1.2.2.2 skrll } else {
2138 1.2.2.2 skrll ctl = hdafg_control_lookup(sc, w->w_nid,
2139 1.2.2.2 skrll HDAUDIO_PINDIR_OUT, -1, 1);
2140 1.2.2.2 skrll if (ctl && ctl->ctl_enable == true) {
2141 1.2.2.2 skrll ctl->ctl_forcemute = 1;
2142 1.2.2.2 skrll ctl->ctl_muted = HDAUDIO_AMP_MUTE_ALL;
2143 1.2.2.2 skrll ctl->ctl_left = ctl->ctl_right = 0;
2144 1.2.2.2 skrll ctl->ctl_enable = false;
2145 1.2.2.2 skrll }
2146 1.2.2.2 skrll for (k = sc->sc_startnode; k < sc->sc_endnode; k++) {
2147 1.2.2.2 skrll cw = hdafg_widget_lookup(sc, k);
2148 1.2.2.2 skrll if (cw == NULL || cw->w_enable == false)
2149 1.2.2.2 skrll continue;
2150 1.2.2.2 skrll for (j = 0; j < cw->w_nconns; j++) {
2151 1.2.2.2 skrll if (!cw->w_connsenable[j])
2152 1.2.2.2 skrll continue;
2153 1.2.2.2 skrll if (cw->w_conns[j] != i)
2154 1.2.2.2 skrll continue;
2155 1.2.2.2 skrll hda_trace(sc, "disable %02X -> %02X "
2156 1.2.2.2 skrll "output connection\n",
2157 1.2.2.2 skrll cw->w_nid, cw->w_conns[j]);
2158 1.2.2.2 skrll cw->w_connsenable[j] = false;
2159 1.2.2.2 skrll if (cw->w_type ==
2160 1.2.2.2 skrll COP_AWCAP_TYPE_PIN_COMPLEX &&
2161 1.2.2.2 skrll cw->w_nconns > 1)
2162 1.2.2.2 skrll continue;
2163 1.2.2.2 skrll ctl = hdafg_control_lookup(sc,
2164 1.2.2.2 skrll k, HDAUDIO_PINDIR_IN, j, 1);
2165 1.2.2.2 skrll if (ctl && ctl->ctl_enable == true) {
2166 1.2.2.2 skrll ctl->ctl_forcemute = 1;
2167 1.2.2.2 skrll ctl->ctl_muted =
2168 1.2.2.2 skrll HDAUDIO_AMP_MUTE_ALL;
2169 1.2.2.2 skrll ctl->ctl_left =
2170 1.2.2.2 skrll ctl->ctl_right = 0;
2171 1.2.2.2 skrll ctl->ctl_enable = false;
2172 1.2.2.2 skrll }
2173 1.2.2.2 skrll }
2174 1.2.2.2 skrll }
2175 1.2.2.2 skrll }
2176 1.2.2.2 skrll }
2177 1.2.2.2 skrll }
2178 1.2.2.2 skrll
2179 1.2.2.2 skrll static void
2180 1.2.2.2 skrll hdafg_disable_unsel(struct hdafg_softc *sc)
2181 1.2.2.2 skrll {
2182 1.2.2.2 skrll struct hdaudio_assoc *as = sc->sc_assocs;
2183 1.2.2.2 skrll struct hdaudio_widget *w;
2184 1.2.2.2 skrll int i, j;
2185 1.2.2.2 skrll
2186 1.2.2.2 skrll /* On playback path we can safely disable all unselected inputs */
2187 1.2.2.2 skrll for (i = sc->sc_startnode; i < sc->sc_endnode; i++) {
2188 1.2.2.2 skrll w = hdafg_widget_lookup(sc, i);
2189 1.2.2.2 skrll if (w == NULL || w->w_enable == false)
2190 1.2.2.2 skrll continue;
2191 1.2.2.2 skrll if (w->w_nconns <= 1)
2192 1.2.2.2 skrll continue;
2193 1.2.2.2 skrll if (w->w_type == COP_AWCAP_TYPE_AUDIO_MIXER)
2194 1.2.2.2 skrll continue;
2195 1.2.2.2 skrll if (w->w_bindas < 0 ||
2196 1.2.2.2 skrll as[w->w_bindas].as_dir == HDAUDIO_PINDIR_IN)
2197 1.2.2.2 skrll continue;
2198 1.2.2.2 skrll for (j = 0; j < w->w_nconns; j++) {
2199 1.2.2.2 skrll if (w->w_connsenable[j] == false)
2200 1.2.2.2 skrll continue;
2201 1.2.2.2 skrll if (w->w_selconn < 0 || w->w_selconn == j)
2202 1.2.2.2 skrll continue;
2203 1.2.2.2 skrll hda_trace(sc, "disable %02X->%02X [unselected]\n",
2204 1.2.2.2 skrll w->w_nid, w->w_conns[j]);
2205 1.2.2.2 skrll w->w_connsenable[j] = false;
2206 1.2.2.2 skrll }
2207 1.2.2.2 skrll }
2208 1.2.2.2 skrll }
2209 1.2.2.2 skrll
2210 1.2.2.2 skrll static void
2211 1.2.2.2 skrll hdafg_disable_crossassoc(struct hdafg_softc *sc)
2212 1.2.2.2 skrll {
2213 1.2.2.2 skrll struct hdaudio_widget *w, *cw;
2214 1.2.2.2 skrll struct hdaudio_control *ctl;
2215 1.2.2.2 skrll int i, j;
2216 1.2.2.2 skrll
2217 1.2.2.2 skrll /* Disable cross associated and unwanted cross channel connections */
2218 1.2.2.2 skrll
2219 1.2.2.2 skrll /* ... using selectors */
2220 1.2.2.2 skrll for (i = sc->sc_startnode; i < sc->sc_endnode; i++) {
2221 1.2.2.2 skrll w = hdafg_widget_lookup(sc, i);
2222 1.2.2.2 skrll if (w == NULL || w->w_enable == false)
2223 1.2.2.2 skrll continue;
2224 1.2.2.2 skrll if (w->w_nconns <= 1)
2225 1.2.2.2 skrll continue;
2226 1.2.2.2 skrll if (w->w_type == COP_AWCAP_TYPE_AUDIO_MIXER)
2227 1.2.2.2 skrll continue;
2228 1.2.2.2 skrll if (w->w_bindas == -2)
2229 1.2.2.2 skrll continue;
2230 1.2.2.2 skrll for (j = 0; j < w->w_nconns; j++) {
2231 1.2.2.2 skrll if (w->w_connsenable[j] == false)
2232 1.2.2.2 skrll continue;
2233 1.2.2.2 skrll cw = hdafg_widget_lookup(sc, w->w_conns[j]);
2234 1.2.2.2 skrll if (cw == NULL || cw->w_enable == false)
2235 1.2.2.2 skrll continue;
2236 1.2.2.2 skrll if (cw->w_bindas == -2)
2237 1.2.2.2 skrll continue;
2238 1.2.2.2 skrll if (w->w_bindas == cw->w_bindas &&
2239 1.2.2.2 skrll (w->w_bindseqmask & cw->w_bindseqmask) != 0)
2240 1.2.2.2 skrll continue;
2241 1.2.2.2 skrll hda_trace(sc, "disable %02X->%02X [crossassoc]\n",
2242 1.2.2.2 skrll w->w_nid, w->w_conns[j]);
2243 1.2.2.2 skrll w->w_connsenable[j] = false;
2244 1.2.2.2 skrll }
2245 1.2.2.2 skrll }
2246 1.2.2.2 skrll /* ... using controls */
2247 1.2.2.2 skrll for (i = 0; i < sc->sc_nctls; i++) {
2248 1.2.2.2 skrll ctl = &sc->sc_ctls[i];
2249 1.2.2.2 skrll if (ctl->ctl_enable == false || ctl->ctl_childwidget == NULL)
2250 1.2.2.2 skrll continue;
2251 1.2.2.2 skrll if (ctl->ctl_widget->w_bindas == -2 ||
2252 1.2.2.2 skrll ctl->ctl_childwidget->w_bindas == -2)
2253 1.2.2.2 skrll continue;
2254 1.2.2.2 skrll if (ctl->ctl_widget->w_bindas !=
2255 1.2.2.2 skrll ctl->ctl_childwidget->w_bindas ||
2256 1.2.2.2 skrll (ctl->ctl_widget->w_bindseqmask &
2257 1.2.2.2 skrll ctl->ctl_childwidget->w_bindseqmask) == 0) {
2258 1.2.2.2 skrll ctl->ctl_forcemute = 1;
2259 1.2.2.2 skrll ctl->ctl_muted = HDAUDIO_AMP_MUTE_ALL;
2260 1.2.2.2 skrll ctl->ctl_left = ctl->ctl_right = 0;
2261 1.2.2.2 skrll ctl->ctl_enable = false;
2262 1.2.2.2 skrll if (ctl->ctl_ndir == HDAUDIO_PINDIR_IN) {
2263 1.2.2.2 skrll hda_trace(sc, "disable ctl %d:%02X:%02X "
2264 1.2.2.2 skrll "[crossassoc]\n",
2265 1.2.2.2 skrll i, ctl->ctl_widget->w_nid,
2266 1.2.2.2 skrll ctl->ctl_widget->w_conns[ctl->ctl_index]);
2267 1.2.2.2 skrll ctl->ctl_widget->w_connsenable[
2268 1.2.2.2 skrll ctl->ctl_index] = false;
2269 1.2.2.2 skrll }
2270 1.2.2.2 skrll }
2271 1.2.2.2 skrll }
2272 1.2.2.2 skrll }
2273 1.2.2.2 skrll
2274 1.2.2.2 skrll static struct hdaudio_control *
2275 1.2.2.2 skrll hdafg_control_amp_get(struct hdafg_softc *sc, int nid,
2276 1.2.2.2 skrll enum hdaudio_pindir dir, int index, int cnt)
2277 1.2.2.2 skrll {
2278 1.2.2.2 skrll struct hdaudio_control *ctl;
2279 1.2.2.2 skrll int i, found = 0;
2280 1.2.2.2 skrll
2281 1.2.2.2 skrll for (i = 0; i < sc->sc_nctls; i++) {
2282 1.2.2.2 skrll ctl = &sc->sc_ctls[i];
2283 1.2.2.2 skrll if (ctl->ctl_enable == false)
2284 1.2.2.2 skrll continue;
2285 1.2.2.2 skrll if (ctl->ctl_widget->w_nid != nid)
2286 1.2.2.2 skrll continue;
2287 1.2.2.2 skrll if (dir && ctl->ctl_ndir != dir)
2288 1.2.2.2 skrll continue;
2289 1.2.2.2 skrll if (index >= 0 && ctl->ctl_ndir == HDAUDIO_PINDIR_IN &&
2290 1.2.2.2 skrll ctl->ctl_dir == ctl->ctl_ndir &&
2291 1.2.2.2 skrll ctl->ctl_index != index)
2292 1.2.2.2 skrll continue;
2293 1.2.2.2 skrll ++found;
2294 1.2.2.2 skrll if (found == cnt || cnt <= 0)
2295 1.2.2.2 skrll return ctl;
2296 1.2.2.2 skrll }
2297 1.2.2.2 skrll
2298 1.2.2.2 skrll return NULL;
2299 1.2.2.2 skrll }
2300 1.2.2.2 skrll
2301 1.2.2.2 skrll static void
2302 1.2.2.2 skrll hdafg_control_amp_set1(struct hdaudio_control *ctl, int lmute, int rmute,
2303 1.2.2.2 skrll int left, int right, int dir)
2304 1.2.2.2 skrll {
2305 1.2.2.2 skrll struct hdafg_softc *sc = ctl->ctl_widget->w_afg;
2306 1.2.2.2 skrll int index = ctl->ctl_index;
2307 1.2.2.2 skrll uint16_t v = 0;
2308 1.2.2.2 skrll
2309 1.2.2.2 skrll if (left != right || lmute != rmute) {
2310 1.2.2.2 skrll v = (1 << (15 - dir)) | (1 << 13) | (index << 8) |
2311 1.2.2.2 skrll (lmute << 7) | left;
2312 1.2.2.2 skrll hdaudio_command(sc->sc_codec, ctl->ctl_widget->w_nid,
2313 1.2.2.2 skrll CORB_SET_AMPLIFIER_GAIN_MUTE, v);
2314 1.2.2.2 skrll v = (1 << (15 - dir)) | (1 << 12) | (index << 8) |
2315 1.2.2.2 skrll (rmute << 7) | right;
2316 1.2.2.2 skrll } else
2317 1.2.2.2 skrll v = (1 << (15 - dir)) | (3 << 12) | (index << 8) |
2318 1.2.2.2 skrll (lmute << 7) | left;
2319 1.2.2.2 skrll hdaudio_command(sc->sc_codec, ctl->ctl_widget->w_nid,
2320 1.2.2.2 skrll CORB_SET_AMPLIFIER_GAIN_MUTE, v);
2321 1.2.2.2 skrll }
2322 1.2.2.2 skrll
2323 1.2.2.2 skrll static void
2324 1.2.2.2 skrll hdafg_control_amp_set(struct hdaudio_control *ctl, uint32_t mute,
2325 1.2.2.2 skrll int left, int right)
2326 1.2.2.2 skrll {
2327 1.2.2.2 skrll int lmute, rmute;
2328 1.2.2.2 skrll
2329 1.2.2.2 skrll /* Save new values if valid */
2330 1.2.2.2 skrll if (mute != HDAUDIO_AMP_MUTE_DEFAULT)
2331 1.2.2.2 skrll ctl->ctl_muted = mute;
2332 1.2.2.2 skrll if (left != HDAUDIO_AMP_VOL_DEFAULT)
2333 1.2.2.2 skrll ctl->ctl_left = left;
2334 1.2.2.2 skrll if (right != HDAUDIO_AMP_VOL_DEFAULT)
2335 1.2.2.2 skrll ctl->ctl_right = right;
2336 1.2.2.2 skrll
2337 1.2.2.2 skrll /* Prepare effective values */
2338 1.2.2.2 skrll if (ctl->ctl_forcemute) {
2339 1.2.2.2 skrll lmute = rmute = 1;
2340 1.2.2.2 skrll left = right = 0;
2341 1.2.2.2 skrll } else {
2342 1.2.2.2 skrll lmute = HDAUDIO_AMP_LEFT_MUTED(ctl->ctl_muted);
2343 1.2.2.2 skrll rmute = HDAUDIO_AMP_RIGHT_MUTED(ctl->ctl_muted);
2344 1.2.2.2 skrll left = ctl->ctl_left;
2345 1.2.2.2 skrll right = ctl->ctl_right;
2346 1.2.2.2 skrll }
2347 1.2.2.2 skrll
2348 1.2.2.2 skrll /* Apply effective values */
2349 1.2.2.2 skrll if (ctl->ctl_dir & HDAUDIO_PINDIR_OUT)
2350 1.2.2.2 skrll hdafg_control_amp_set1(ctl, lmute, rmute, left, right, 0);
2351 1.2.2.2 skrll if (ctl->ctl_dir & HDAUDIO_PINDIR_IN)
2352 1.2.2.2 skrll hdafg_control_amp_set1(ctl, lmute, rmute, left, right, 1);
2353 1.2.2.2 skrll }
2354 1.2.2.2 skrll
2355 1.2.2.2 skrll static void
2356 1.2.2.2 skrll hdafg_control_commit(struct hdafg_softc *sc)
2357 1.2.2.2 skrll {
2358 1.2.2.2 skrll struct hdaudio_control *ctl;
2359 1.2.2.2 skrll int i, z;
2360 1.2.2.2 skrll
2361 1.2.2.2 skrll for (i = 0; i < sc->sc_nctls; i++) {
2362 1.2.2.2 skrll ctl = &sc->sc_ctls[i];
2363 1.2.2.2 skrll //if (ctl->ctl_enable == false || ctl->ctl_audiomask != 0)
2364 1.2.2.2 skrll if (ctl->ctl_enable == false)
2365 1.2.2.2 skrll continue;
2366 1.2.2.2 skrll /* Init fixed controls to 0dB amplification */
2367 1.2.2.2 skrll z = ctl->ctl_offset;
2368 1.2.2.2 skrll if (z > ctl->ctl_step)
2369 1.2.2.2 skrll z = ctl->ctl_step;
2370 1.2.2.2 skrll hdafg_control_amp_set(ctl, HDAUDIO_AMP_MUTE_NONE, z, z);
2371 1.2.2.2 skrll }
2372 1.2.2.2 skrll }
2373 1.2.2.2 skrll
2374 1.2.2.2 skrll static void
2375 1.2.2.2 skrll hdafg_widget_connection_select(struct hdaudio_widget *w, uint8_t index)
2376 1.2.2.2 skrll {
2377 1.2.2.2 skrll struct hdafg_softc *sc = w->w_afg;
2378 1.2.2.2 skrll
2379 1.2.2.2 skrll if (w->w_nconns < 1 || index > (w->w_nconns - 1))
2380 1.2.2.2 skrll return;
2381 1.2.2.2 skrll
2382 1.2.2.2 skrll hdaudio_command(sc->sc_codec, w->w_nid,
2383 1.2.2.2 skrll CORB_SET_CONNECTION_SELECT_CONTROL, index);
2384 1.2.2.2 skrll w->w_selconn = index;
2385 1.2.2.2 skrll }
2386 1.2.2.2 skrll
2387 1.2.2.2 skrll static void
2388 1.2.2.2 skrll hdafg_assign_names(struct hdafg_softc *sc)
2389 1.2.2.2 skrll {
2390 1.2.2.2 skrll struct hdaudio_assoc *as = sc->sc_assocs;
2391 1.2.2.2 skrll struct hdaudio_widget *w;
2392 1.2.2.2 skrll int i, j;
2393 1.2.2.2 skrll int type = -1, use, used =0;
2394 1.2.2.2 skrll static const int types[7][13] = {
2395 1.2.2.2 skrll { HDAUDIO_MIXER_LINE, HDAUDIO_MIXER_LINE1, HDAUDIO_MIXER_LINE2,
2396 1.2.2.2 skrll HDAUDIO_MIXER_LINE3, -1 },
2397 1.2.2.2 skrll { HDAUDIO_MIXER_MONITOR, HDAUDIO_MIXER_MIC, -1 }, /* int mic */
2398 1.2.2.2 skrll { HDAUDIO_MIXER_MIC, HDAUDIO_MIXER_MONITOR, -1 }, /* ext mic */
2399 1.2.2.2 skrll { HDAUDIO_MIXER_CD, -1 },
2400 1.2.2.2 skrll { HDAUDIO_MIXER_SPEAKER, -1 },
2401 1.2.2.2 skrll { HDAUDIO_MIXER_DIGITAL1, HDAUDIO_MIXER_DIGITAL2,
2402 1.2.2.2 skrll HDAUDIO_MIXER_DIGITAL3, -1 },
2403 1.2.2.2 skrll { HDAUDIO_MIXER_LINE, HDAUDIO_MIXER_LINE1, HDAUDIO_MIXER_LINE2,
2404 1.2.2.2 skrll HDAUDIO_MIXER_LINE3, HDAUDIO_MIXER_PHONEIN,
2405 1.2.2.2 skrll HDAUDIO_MIXER_PHONEOUT, HDAUDIO_MIXER_VIDEO, HDAUDIO_MIXER_RADIO,
2406 1.2.2.2 skrll HDAUDIO_MIXER_DIGITAL1, HDAUDIO_MIXER_DIGITAL2,
2407 1.2.2.2 skrll HDAUDIO_MIXER_DIGITAL3, HDAUDIO_MIXER_MONITOR, -1 } /* others */
2408 1.2.2.2 skrll };
2409 1.2.2.2 skrll
2410 1.2.2.2 skrll /* Surely known names */
2411 1.2.2.2 skrll for (i = sc->sc_startnode; i < sc->sc_endnode; i++) {
2412 1.2.2.2 skrll w = hdafg_widget_lookup(sc, i);
2413 1.2.2.2 skrll if (w == NULL || w->w_enable == false)
2414 1.2.2.2 skrll continue;
2415 1.2.2.2 skrll if (w->w_bindas == -1)
2416 1.2.2.2 skrll continue;
2417 1.2.2.2 skrll use = -1;
2418 1.2.2.2 skrll switch (w->w_type) {
2419 1.2.2.2 skrll case COP_AWCAP_TYPE_PIN_COMPLEX:
2420 1.2.2.2 skrll if (as[w->w_bindas].as_dir == HDAUDIO_PINDIR_OUT)
2421 1.2.2.2 skrll break;
2422 1.2.2.2 skrll type = -1;
2423 1.2.2.2 skrll switch (COP_CFG_DEFAULT_DEVICE(w->w_pin.config)) {
2424 1.2.2.2 skrll case COP_DEVICE_LINE_IN:
2425 1.2.2.2 skrll type = 0;
2426 1.2.2.2 skrll break;
2427 1.2.2.2 skrll case COP_DEVICE_MIC_IN:
2428 1.2.2.2 skrll if (COP_CFG_PORT_CONNECTIVITY(w->w_pin.config)
2429 1.2.2.2 skrll == COP_PORT_JACK)
2430 1.2.2.2 skrll break;
2431 1.2.2.2 skrll type = 1;
2432 1.2.2.2 skrll break;
2433 1.2.2.2 skrll case COP_DEVICE_CD:
2434 1.2.2.2 skrll type = 3;
2435 1.2.2.2 skrll break;
2436 1.2.2.2 skrll case COP_DEVICE_SPEAKER:
2437 1.2.2.2 skrll type = 4;
2438 1.2.2.2 skrll break;
2439 1.2.2.2 skrll case COP_DEVICE_SPDIF_IN:
2440 1.2.2.2 skrll case COP_DEVICE_DIGITAL_OTHER_IN:
2441 1.2.2.2 skrll type = 5;
2442 1.2.2.2 skrll break;
2443 1.2.2.2 skrll }
2444 1.2.2.2 skrll if (type == -1)
2445 1.2.2.2 skrll break;
2446 1.2.2.2 skrll j = 0;
2447 1.2.2.2 skrll while (types[type][j] >= 0 &&
2448 1.2.2.2 skrll (used & (1 << types[type][j])) != 0) {
2449 1.2.2.2 skrll j++;
2450 1.2.2.2 skrll }
2451 1.2.2.2 skrll if (types[type][j] >= 0)
2452 1.2.2.2 skrll use = types[type][j];
2453 1.2.2.2 skrll break;
2454 1.2.2.2 skrll case COP_AWCAP_TYPE_AUDIO_OUTPUT:
2455 1.2.2.2 skrll use = HDAUDIO_MIXER_PCM;
2456 1.2.2.2 skrll break;
2457 1.2.2.2 skrll case COP_AWCAP_TYPE_BEEP_GENERATOR:
2458 1.2.2.2 skrll use = HDAUDIO_MIXER_SPEAKER;
2459 1.2.2.2 skrll break;
2460 1.2.2.2 skrll default:
2461 1.2.2.2 skrll break;
2462 1.2.2.2 skrll }
2463 1.2.2.2 skrll if (use >= 0) {
2464 1.2.2.2 skrll w->w_audiodev = use;
2465 1.2.2.2 skrll used |= (1 << use);
2466 1.2.2.2 skrll }
2467 1.2.2.2 skrll }
2468 1.2.2.2 skrll /* Semi-known names */
2469 1.2.2.2 skrll for (i = sc->sc_startnode; i < sc->sc_endnode; i++) {
2470 1.2.2.2 skrll w = hdafg_widget_lookup(sc, i);
2471 1.2.2.2 skrll if (w == NULL || w->w_enable == false)
2472 1.2.2.2 skrll continue;
2473 1.2.2.2 skrll if (w->w_audiodev >= 0)
2474 1.2.2.2 skrll continue;
2475 1.2.2.2 skrll if (w->w_bindas == -1)
2476 1.2.2.2 skrll continue;
2477 1.2.2.2 skrll if (w->w_type != COP_AWCAP_TYPE_PIN_COMPLEX)
2478 1.2.2.2 skrll continue;
2479 1.2.2.2 skrll if (as[w->w_bindas].as_dir == HDAUDIO_PINDIR_OUT)
2480 1.2.2.2 skrll continue;
2481 1.2.2.2 skrll type = -1;
2482 1.2.2.2 skrll switch (COP_CFG_DEFAULT_DEVICE(w->w_pin.config)) {
2483 1.2.2.2 skrll case COP_DEVICE_LINE_OUT:
2484 1.2.2.2 skrll case COP_DEVICE_SPEAKER:
2485 1.2.2.2 skrll case COP_DEVICE_HP_OUT:
2486 1.2.2.2 skrll case COP_DEVICE_AUX:
2487 1.2.2.2 skrll type = 0;
2488 1.2.2.2 skrll break;
2489 1.2.2.2 skrll case COP_DEVICE_MIC_IN:
2490 1.2.2.2 skrll type = 2;
2491 1.2.2.2 skrll break;
2492 1.2.2.2 skrll case COP_DEVICE_SPDIF_OUT:
2493 1.2.2.2 skrll case COP_DEVICE_DIGITAL_OTHER_OUT:
2494 1.2.2.2 skrll type = 5;
2495 1.2.2.2 skrll break;
2496 1.2.2.2 skrll }
2497 1.2.2.2 skrll if (type == -1)
2498 1.2.2.2 skrll break;
2499 1.2.2.2 skrll j = 0;
2500 1.2.2.2 skrll while (types[type][j] >= 0 &&
2501 1.2.2.2 skrll (used & (1 << types[type][j])) != 0) {
2502 1.2.2.2 skrll j++;
2503 1.2.2.2 skrll }
2504 1.2.2.2 skrll if (types[type][j] >= 0) {
2505 1.2.2.2 skrll w->w_audiodev = types[type][j];
2506 1.2.2.2 skrll used |= (1 << types[type][j]);
2507 1.2.2.2 skrll }
2508 1.2.2.2 skrll }
2509 1.2.2.2 skrll /* Others */
2510 1.2.2.2 skrll for (i = sc->sc_startnode; i < sc->sc_endnode; i++) {
2511 1.2.2.2 skrll w = hdafg_widget_lookup(sc, i);
2512 1.2.2.2 skrll if (w == NULL || w->w_enable == false)
2513 1.2.2.2 skrll continue;
2514 1.2.2.2 skrll if (w->w_audiodev >= 0)
2515 1.2.2.2 skrll continue;
2516 1.2.2.2 skrll if (w->w_bindas == -1)
2517 1.2.2.2 skrll continue;
2518 1.2.2.2 skrll if (w->w_type != COP_AWCAP_TYPE_PIN_COMPLEX)
2519 1.2.2.2 skrll continue;
2520 1.2.2.2 skrll if (as[w->w_bindas].as_dir == HDAUDIO_PINDIR_OUT)
2521 1.2.2.2 skrll continue;
2522 1.2.2.2 skrll j = 0;
2523 1.2.2.2 skrll while (types[6][j] >= 0 &&
2524 1.2.2.2 skrll (used & (1 << types[6][j])) != 0) {
2525 1.2.2.2 skrll j++;
2526 1.2.2.2 skrll }
2527 1.2.2.2 skrll if (types[6][j] >= 0) {
2528 1.2.2.2 skrll w->w_audiodev = types[6][j];
2529 1.2.2.2 skrll used |= (1 << types[6][j]);
2530 1.2.2.2 skrll }
2531 1.2.2.2 skrll }
2532 1.2.2.2 skrll }
2533 1.2.2.2 skrll
2534 1.2.2.2 skrll static int
2535 1.2.2.2 skrll hdafg_control_source_amp(struct hdafg_softc *sc, int nid, int index,
2536 1.2.2.2 skrll int audiodev, int ctlable, int depth, int need)
2537 1.2.2.2 skrll {
2538 1.2.2.2 skrll struct hdaudio_widget *w, *wc;
2539 1.2.2.2 skrll struct hdaudio_control *ctl;
2540 1.2.2.2 skrll int i, j, conns = 0, rneed;
2541 1.2.2.2 skrll
2542 1.2.2.2 skrll if (depth >= HDAUDIO_PARSE_MAXDEPTH)
2543 1.2.2.2 skrll return need;
2544 1.2.2.2 skrll
2545 1.2.2.2 skrll w = hdafg_widget_lookup(sc, nid);
2546 1.2.2.2 skrll if (w == NULL || w->w_enable == false)
2547 1.2.2.2 skrll return need;
2548 1.2.2.2 skrll
2549 1.2.2.2 skrll /* Count number of active inputs */
2550 1.2.2.2 skrll if (depth > 0) {
2551 1.2.2.2 skrll for (j = 0; j < w->w_nconns; j++) {
2552 1.2.2.2 skrll if (w->w_connsenable[j])
2553 1.2.2.2 skrll ++conns;
2554 1.2.2.2 skrll }
2555 1.2.2.2 skrll }
2556 1.2.2.2 skrll
2557 1.2.2.2 skrll /*
2558 1.2.2.2 skrll * If this is not a first step, use input mixer. Pins have common
2559 1.2.2.2 skrll * input ctl so care must be taken
2560 1.2.2.2 skrll */
2561 1.2.2.2 skrll if (depth > 0 && ctlable && (conns == 1 ||
2562 1.2.2.2 skrll w->w_type != COP_AWCAP_TYPE_PIN_COMPLEX)) {
2563 1.2.2.2 skrll ctl = hdafg_control_amp_get(sc, w->w_nid,
2564 1.2.2.2 skrll HDAUDIO_PINDIR_IN, index, 1);
2565 1.2.2.2 skrll if (ctl) {
2566 1.2.2.2 skrll if (HDAUDIO_CONTROL_GIVE(ctl) & need)
2567 1.2.2.2 skrll ctl->ctl_audiomask |= (1 << audiodev);
2568 1.2.2.2 skrll else
2569 1.2.2.2 skrll ctl->ctl_paudiomask |= (1 << audiodev);
2570 1.2.2.2 skrll need &= ~HDAUDIO_CONTROL_GIVE(ctl);
2571 1.2.2.2 skrll }
2572 1.2.2.2 skrll }
2573 1.2.2.2 skrll
2574 1.2.2.2 skrll /* If widget has own audiodev, don't traverse it. */
2575 1.2.2.2 skrll if (w->w_audiodev >= 0 && depth > 0)
2576 1.2.2.2 skrll return need;
2577 1.2.2.2 skrll
2578 1.2.2.2 skrll /* We must not traverse pins */
2579 1.2.2.2 skrll if ((w->w_type == COP_AWCAP_TYPE_AUDIO_INPUT ||
2580 1.2.2.2 skrll w->w_type == COP_AWCAP_TYPE_PIN_COMPLEX) && depth > 0)
2581 1.2.2.2 skrll return need;
2582 1.2.2.2 skrll
2583 1.2.2.2 skrll /* Record that this widget exports such signal */
2584 1.2.2.2 skrll w->w_audiomask |= (1 << audiodev);
2585 1.2.2.2 skrll
2586 1.2.2.2 skrll /*
2587 1.2.2.2 skrll * If signals mixed, we can't assign controls further. Ignore this
2588 1.2.2.2 skrll * on depth zero. Caller must know why. Ignore this for static
2589 1.2.2.2 skrll * selectors if this input is selected.
2590 1.2.2.2 skrll */
2591 1.2.2.2 skrll if (conns > 1)
2592 1.2.2.2 skrll ctlable = 0;
2593 1.2.2.2 skrll
2594 1.2.2.2 skrll if (ctlable) {
2595 1.2.2.2 skrll ctl = hdafg_control_amp_get(sc, w->w_nid,
2596 1.2.2.2 skrll HDAUDIO_PINDIR_OUT, -1, 1);
2597 1.2.2.2 skrll if (ctl) {
2598 1.2.2.2 skrll if (HDAUDIO_CONTROL_GIVE(ctl) & need)
2599 1.2.2.2 skrll ctl->ctl_audiomask |= (1 << audiodev);
2600 1.2.2.2 skrll else
2601 1.2.2.2 skrll ctl->ctl_paudiomask |= (1 << audiodev);
2602 1.2.2.2 skrll need &= ~HDAUDIO_CONTROL_GIVE(ctl);
2603 1.2.2.2 skrll }
2604 1.2.2.2 skrll }
2605 1.2.2.2 skrll
2606 1.2.2.2 skrll rneed = 0;
2607 1.2.2.2 skrll for (i = sc->sc_startnode; i < sc->sc_endnode; i++) {
2608 1.2.2.2 skrll wc = hdafg_widget_lookup(sc, i);
2609 1.2.2.2 skrll if (wc == NULL || wc->w_enable == false)
2610 1.2.2.2 skrll continue;
2611 1.2.2.2 skrll for (j = 0; j < wc->w_nconns; j++) {
2612 1.2.2.2 skrll if (wc->w_connsenable[j] && wc->w_conns[j] == nid) {
2613 1.2.2.2 skrll rneed |= hdafg_control_source_amp(sc,
2614 1.2.2.2 skrll wc->w_nid, j, audiodev, ctlable, depth + 1,
2615 1.2.2.2 skrll need);
2616 1.2.2.2 skrll }
2617 1.2.2.2 skrll }
2618 1.2.2.2 skrll }
2619 1.2.2.2 skrll rneed &= need;
2620 1.2.2.2 skrll
2621 1.2.2.2 skrll return rneed;
2622 1.2.2.2 skrll }
2623 1.2.2.2 skrll
2624 1.2.2.2 skrll static void
2625 1.2.2.2 skrll hdafg_control_dest_amp(struct hdafg_softc *sc, int nid,
2626 1.2.2.2 skrll int audiodev, int depth, int need)
2627 1.2.2.2 skrll {
2628 1.2.2.2 skrll struct hdaudio_assoc *as = sc->sc_assocs;
2629 1.2.2.2 skrll struct hdaudio_widget *w, *wc;
2630 1.2.2.2 skrll struct hdaudio_control *ctl;
2631 1.2.2.2 skrll int i, j, consumers;
2632 1.2.2.2 skrll
2633 1.2.2.2 skrll if (depth > HDAUDIO_PARSE_MAXDEPTH)
2634 1.2.2.2 skrll return;
2635 1.2.2.2 skrll
2636 1.2.2.2 skrll w = hdafg_widget_lookup(sc, nid);
2637 1.2.2.2 skrll if (w == NULL || w->w_enable == false)
2638 1.2.2.2 skrll return;
2639 1.2.2.2 skrll
2640 1.2.2.2 skrll if (depth > 0) {
2641 1.2.2.2 skrll /*
2642 1.2.2.2 skrll * If this node produces output for several consumers,
2643 1.2.2.2 skrll * we can't touch it
2644 1.2.2.2 skrll */
2645 1.2.2.2 skrll consumers = 0;
2646 1.2.2.2 skrll for (i = sc->sc_startnode; i < sc->sc_endnode; i++) {
2647 1.2.2.2 skrll wc = hdafg_widget_lookup(sc, i);
2648 1.2.2.2 skrll if (wc == NULL || wc->w_enable == false)
2649 1.2.2.2 skrll continue;
2650 1.2.2.2 skrll for (j = 0; j < wc->w_nconns; j++) {
2651 1.2.2.2 skrll if (wc->w_connsenable[j] &&
2652 1.2.2.2 skrll wc->w_conns[j] == nid)
2653 1.2.2.2 skrll ++consumers;
2654 1.2.2.2 skrll }
2655 1.2.2.2 skrll }
2656 1.2.2.2 skrll /*
2657 1.2.2.2 skrll * The only exception is if real HP redirection is configured
2658 1.2.2.2 skrll * and this is a duplication point.
2659 1.2.2.2 skrll * XXX: Not completely correct.
2660 1.2.2.2 skrll */
2661 1.2.2.2 skrll if ((consumers == 2 && (w->w_bindas < 0 ||
2662 1.2.2.2 skrll as[w->w_bindas].as_hpredir < 0 ||
2663 1.2.2.2 skrll as[w->w_bindas].as_fakeredir ||
2664 1.2.2.2 skrll (w->w_bindseqmask & (1 << 15)) == 0)) ||
2665 1.2.2.2 skrll consumers > 2)
2666 1.2.2.2 skrll return;
2667 1.2.2.2 skrll
2668 1.2.2.2 skrll /* Else use its output mixer */
2669 1.2.2.2 skrll ctl = hdafg_control_amp_get(sc, w->w_nid,
2670 1.2.2.2 skrll HDAUDIO_PINDIR_OUT, -1, 1);
2671 1.2.2.2 skrll if (ctl) {
2672 1.2.2.2 skrll if (HDAUDIO_CONTROL_GIVE(ctl) & need)
2673 1.2.2.2 skrll ctl->ctl_audiomask |= (1 << audiodev);
2674 1.2.2.2 skrll else
2675 1.2.2.2 skrll ctl->ctl_paudiomask |= (1 << audiodev);
2676 1.2.2.2 skrll need &= ~HDAUDIO_CONTROL_GIVE(ctl);
2677 1.2.2.2 skrll }
2678 1.2.2.2 skrll }
2679 1.2.2.2 skrll
2680 1.2.2.2 skrll /* We must not traverse pin */
2681 1.2.2.2 skrll if (w->w_type == COP_AWCAP_TYPE_PIN_COMPLEX && depth > 0)
2682 1.2.2.2 skrll return;
2683 1.2.2.2 skrll
2684 1.2.2.2 skrll for (i = 0; i < w->w_nconns; i++) {
2685 1.2.2.2 skrll int tneed = need;
2686 1.2.2.2 skrll if (w->w_connsenable[i] == false)
2687 1.2.2.2 skrll continue;
2688 1.2.2.2 skrll ctl = hdafg_control_amp_get(sc, w->w_nid,
2689 1.2.2.2 skrll HDAUDIO_PINDIR_IN, i, 1);
2690 1.2.2.2 skrll if (ctl) {
2691 1.2.2.2 skrll if (HDAUDIO_CONTROL_GIVE(ctl) & tneed)
2692 1.2.2.2 skrll ctl->ctl_audiomask |= (1 << audiodev);
2693 1.2.2.2 skrll else
2694 1.2.2.2 skrll ctl->ctl_paudiomask |= (1 << audiodev);
2695 1.2.2.2 skrll tneed &= ~HDAUDIO_CONTROL_GIVE(ctl);
2696 1.2.2.2 skrll }
2697 1.2.2.2 skrll hdafg_control_dest_amp(sc, w->w_conns[i], audiodev,
2698 1.2.2.2 skrll depth + 1, tneed);
2699 1.2.2.2 skrll }
2700 1.2.2.2 skrll }
2701 1.2.2.2 skrll
2702 1.2.2.2 skrll static void
2703 1.2.2.2 skrll hdafg_assign_mixers(struct hdafg_softc *sc)
2704 1.2.2.2 skrll {
2705 1.2.2.2 skrll struct hdaudio_assoc *as = sc->sc_assocs;
2706 1.2.2.2 skrll struct hdaudio_control *ctl;
2707 1.2.2.2 skrll struct hdaudio_widget *w;
2708 1.2.2.2 skrll int i;
2709 1.2.2.2 skrll
2710 1.2.2.2 skrll /* Assign mixers to the tree */
2711 1.2.2.2 skrll for (i = sc->sc_startnode; i < sc->sc_endnode; i++) {
2712 1.2.2.2 skrll w = hdafg_widget_lookup(sc, i);
2713 1.2.2.2 skrll if (w == NULL || w->w_enable == FALSE)
2714 1.2.2.2 skrll continue;
2715 1.2.2.2 skrll if (w->w_type == COP_AWCAP_TYPE_AUDIO_OUTPUT ||
2716 1.2.2.2 skrll w->w_type == COP_AWCAP_TYPE_BEEP_GENERATOR ||
2717 1.2.2.2 skrll (w->w_type == COP_AWCAP_TYPE_PIN_COMPLEX &&
2718 1.2.2.2 skrll as[w->w_bindas].as_dir == HDAUDIO_PINDIR_IN)) {
2719 1.2.2.2 skrll if (w->w_audiodev < 0)
2720 1.2.2.2 skrll continue;
2721 1.2.2.2 skrll hdafg_control_source_amp(sc, w->w_nid, -1,
2722 1.2.2.2 skrll w->w_audiodev, 1, 0, 1);
2723 1.2.2.2 skrll } else if (w->w_pflags & HDAUDIO_ADC_MONITOR) {
2724 1.2.2.2 skrll if (w->w_audiodev < 0)
2725 1.2.2.2 skrll continue;
2726 1.2.2.2 skrll if (hdafg_control_source_amp(sc, w->w_nid, -1,
2727 1.2.2.2 skrll w->w_audiodev, 1, 0, 1)) {
2728 1.2.2.2 skrll /* If we are unable to control input monitor
2729 1.2.2.2 skrll as source, try to control it as dest */
2730 1.2.2.2 skrll hdafg_control_dest_amp(sc, w->w_nid,
2731 1.2.2.2 skrll w->w_audiodev, 0, 1);
2732 1.2.2.2 skrll }
2733 1.2.2.2 skrll } else if (w->w_type == COP_AWCAP_TYPE_AUDIO_INPUT) {
2734 1.2.2.2 skrll hdafg_control_dest_amp(sc, w->w_nid,
2735 1.2.2.2 skrll HDAUDIO_MIXER_RECLEV, 0, 1);
2736 1.2.2.2 skrll } else if (w->w_type == COP_AWCAP_TYPE_PIN_COMPLEX &&
2737 1.2.2.2 skrll as[w->w_bindas].as_dir == HDAUDIO_PINDIR_OUT) {
2738 1.2.2.2 skrll hdafg_control_dest_amp(sc, w->w_nid,
2739 1.2.2.2 skrll HDAUDIO_MIXER_VOLUME, 0, 1);
2740 1.2.2.2 skrll }
2741 1.2.2.2 skrll }
2742 1.2.2.2 skrll /* Treat unrequired as possible */
2743 1.2.2.2 skrll i = 0;
2744 1.2.2.2 skrll for (i = 0; i < sc->sc_nctls; i++) {
2745 1.2.2.2 skrll ctl = &sc->sc_ctls[i];
2746 1.2.2.2 skrll if (ctl->ctl_audiomask == 0)
2747 1.2.2.2 skrll ctl->ctl_audiomask = ctl->ctl_paudiomask;
2748 1.2.2.2 skrll }
2749 1.2.2.2 skrll }
2750 1.2.2.2 skrll
2751 1.2.2.2 skrll static void
2752 1.2.2.2 skrll hdafg_build_mixers(struct hdafg_softc *sc)
2753 1.2.2.2 skrll {
2754 1.2.2.2 skrll struct hdaudio_mixer *mx;
2755 1.2.2.2 skrll struct hdaudio_control *ctl, *masterctl = NULL;
2756 1.2.2.2 skrll uint32_t audiomask = 0;
2757 1.2.2.2 skrll int nmixers = 0;
2758 1.2.2.2 skrll int i, j, index = 0;
2759 1.2.2.2 skrll int ndac, nadc;
2760 1.2.2.2 skrll int ctrlcnt[HDAUDIO_MIXER_NRDEVICES];
2761 1.2.2.2 skrll
2762 1.2.2.2 skrll memset(ctrlcnt, 0, sizeof(ctrlcnt));
2763 1.2.2.2 skrll
2764 1.2.2.2 skrll /* Count the number of required mixers */
2765 1.2.2.2 skrll for (i = 0; i < sc->sc_nctls; i++) {
2766 1.2.2.2 skrll ctl = &sc->sc_ctls[i];
2767 1.2.2.2 skrll if (ctl->ctl_enable == false ||
2768 1.2.2.2 skrll ctl->ctl_audiomask == 0)
2769 1.2.2.2 skrll continue;
2770 1.2.2.2 skrll audiomask |= ctl->ctl_audiomask;
2771 1.2.2.2 skrll ++nmixers;
2772 1.2.2.2 skrll if (ctl->ctl_mute)
2773 1.2.2.2 skrll ++nmixers;
2774 1.2.2.2 skrll }
2775 1.2.2.2 skrll
2776 1.2.2.2 skrll /* XXXJDM TODO: softvol */
2777 1.2.2.2 skrll /* Declare master volume if needed */
2778 1.2.2.2 skrll if ((audiomask & (HDAUDIO_MASK(VOLUME) | HDAUDIO_MASK(PCM))) ==
2779 1.2.2.2 skrll HDAUDIO_MASK(PCM)) {
2780 1.2.2.2 skrll audiomask |= HDAUDIO_MASK(VOLUME);
2781 1.2.2.2 skrll for (i = 0; i < sc->sc_nctls; i++) {
2782 1.2.2.2 skrll if (sc->sc_ctls[i].ctl_audiomask == HDAUDIO_MASK(PCM)) {
2783 1.2.2.2 skrll masterctl = &sc->sc_ctls[i];
2784 1.2.2.2 skrll ++nmixers;
2785 1.2.2.2 skrll if (masterctl->ctl_mute)
2786 1.2.2.2 skrll ++nmixers;
2787 1.2.2.2 skrll break;
2788 1.2.2.2 skrll }
2789 1.2.2.2 skrll }
2790 1.2.2.2 skrll }
2791 1.2.2.2 skrll
2792 1.2.2.2 skrll /* Make room for mixer classes */
2793 1.2.2.2 skrll nmixers += (HDAUDIO_MIXER_CLASS_LAST + 1);
2794 1.2.2.2 skrll
2795 1.2.2.2 skrll /* count DACs and ADCs for selectors */
2796 1.2.2.2 skrll ndac = nadc = 0;
2797 1.2.2.2 skrll for (i = 0; i < sc->sc_nassocs; i++) {
2798 1.2.2.2 skrll if (sc->sc_assocs[i].as_enable == false)
2799 1.2.2.2 skrll continue;
2800 1.2.2.2 skrll if (sc->sc_assocs[i].as_dir == HDAUDIO_PINDIR_OUT)
2801 1.2.2.2 skrll ++ndac;
2802 1.2.2.2 skrll else if (sc->sc_assocs[i].as_dir == HDAUDIO_PINDIR_IN)
2803 1.2.2.2 skrll ++nadc;
2804 1.2.2.2 skrll }
2805 1.2.2.2 skrll
2806 1.2.2.2 skrll /* Make room for selectors */
2807 1.2.2.2 skrll if (ndac > 0)
2808 1.2.2.2 skrll ++nmixers;
2809 1.2.2.2 skrll if (nadc > 0)
2810 1.2.2.2 skrll ++nmixers;
2811 1.2.2.2 skrll
2812 1.2.2.2 skrll hda_trace(sc, " need %d mixers (3 classes%s)\n",
2813 1.2.2.2 skrll nmixers, masterctl ? " + fake master" : "");
2814 1.2.2.2 skrll
2815 1.2.2.2 skrll /* Allocate memory for the mixers */
2816 1.2.2.2 skrll mx = kmem_zalloc(nmixers * sizeof(*mx), KM_SLEEP);
2817 1.2.2.2 skrll sc->sc_nmixers = nmixers;
2818 1.2.2.2 skrll
2819 1.2.2.2 skrll /* Build class mixers */
2820 1.2.2.2 skrll for (i = 0; i <= HDAUDIO_MIXER_CLASS_LAST; i++) {
2821 1.2.2.2 skrll mx[index].mx_ctl = NULL;
2822 1.2.2.2 skrll mx[index].mx_di.index = index;
2823 1.2.2.2 skrll mx[index].mx_di.type = AUDIO_MIXER_CLASS;
2824 1.2.2.2 skrll mx[index].mx_di.mixer_class = i;
2825 1.2.2.2 skrll mx[index].mx_di.next = mx[index].mx_di.prev = AUDIO_MIXER_LAST;
2826 1.2.2.2 skrll switch (i) {
2827 1.2.2.2 skrll case HDAUDIO_MIXER_CLASS_OUTPUTS:
2828 1.2.2.2 skrll strcpy(mx[index].mx_di.label.name, AudioCoutputs);
2829 1.2.2.2 skrll break;
2830 1.2.2.2 skrll case HDAUDIO_MIXER_CLASS_INPUTS:
2831 1.2.2.2 skrll strcpy(mx[index].mx_di.label.name, AudioCinputs);
2832 1.2.2.2 skrll break;
2833 1.2.2.2 skrll case HDAUDIO_MIXER_CLASS_RECORD:
2834 1.2.2.2 skrll strcpy(mx[index].mx_di.label.name, AudioCrecord);
2835 1.2.2.2 skrll break;
2836 1.2.2.2 skrll }
2837 1.2.2.2 skrll ++index;
2838 1.2.2.2 skrll }
2839 1.2.2.2 skrll
2840 1.2.2.2 skrll /* Shadow master control */
2841 1.2.2.2 skrll if (masterctl != NULL) {
2842 1.2.2.2 skrll mx[index].mx_ctl = masterctl;
2843 1.2.2.2 skrll mx[index].mx_di.index = index;
2844 1.2.2.2 skrll mx[index].mx_di.type = AUDIO_MIXER_VALUE;
2845 1.2.2.2 skrll mx[index].mx_di.prev = mx[index].mx_di.next = AUDIO_MIXER_LAST;
2846 1.2.2.2 skrll mx[index].mx_di.un.v.num_channels = 2; /* XXX */
2847 1.2.2.2 skrll mx[index].mx_di.mixer_class = HDAUDIO_MIXER_CLASS_OUTPUTS;
2848 1.2.2.2 skrll mx[index].mx_di.un.v.delta = 256 / (masterctl->ctl_step + 1);
2849 1.2.2.2 skrll strcpy(mx[index].mx_di.label.name, AudioNmaster);
2850 1.2.2.2 skrll strcpy(mx[index].mx_di.un.v.units.name, AudioNvolume);
2851 1.2.2.2 skrll hda_trace(sc, " adding outputs.%s\n",
2852 1.2.2.2 skrll mx[index].mx_di.label.name);
2853 1.2.2.2 skrll ++index;
2854 1.2.2.2 skrll if (masterctl->ctl_mute) {
2855 1.2.2.2 skrll mx[index] = mx[index - 1];
2856 1.2.2.2 skrll mx[index].mx_di.index = index;
2857 1.2.2.2 skrll mx[index].mx_di.type = AUDIO_MIXER_ENUM;
2858 1.2.2.2 skrll mx[index].mx_di.prev = mx[index].mx_di.next = AUDIO_MIXER_LAST;
2859 1.2.2.2 skrll strcpy(mx[index].mx_di.label.name, AudioNmaster "." AudioNmute);
2860 1.2.2.2 skrll mx[index].mx_di.un.e.num_mem = 2;
2861 1.2.2.2 skrll strcpy(mx[index].mx_di.un.e.member[0].label.name, AudioNoff);
2862 1.2.2.2 skrll mx[index].mx_di.un.e.member[0].ord = 0;
2863 1.2.2.2 skrll strcpy(mx[index].mx_di.un.e.member[1].label.name, AudioNon);
2864 1.2.2.2 skrll mx[index].mx_di.un.e.member[1].ord = 1;
2865 1.2.2.2 skrll ++index;
2866 1.2.2.2 skrll }
2867 1.2.2.2 skrll }
2868 1.2.2.2 skrll
2869 1.2.2.2 skrll /* Build volume mixers */
2870 1.2.2.2 skrll for (i = 0; i < sc->sc_nctls; i++) {
2871 1.2.2.2 skrll uint32_t audiodev;
2872 1.2.2.2 skrll
2873 1.2.2.2 skrll ctl = &sc->sc_ctls[i];
2874 1.2.2.2 skrll if (ctl->ctl_enable == false ||
2875 1.2.2.2 skrll ctl->ctl_audiomask == 0)
2876 1.2.2.2 skrll continue;
2877 1.2.2.2 skrll audiodev = ffs(ctl->ctl_audiomask) - 1;
2878 1.2.2.2 skrll mx[index].mx_ctl = ctl;
2879 1.2.2.2 skrll mx[index].mx_di.index = index;
2880 1.2.2.2 skrll mx[index].mx_di.type = AUDIO_MIXER_VALUE;
2881 1.2.2.2 skrll mx[index].mx_di.prev = mx[index].mx_di.next = AUDIO_MIXER_LAST;
2882 1.2.2.2 skrll mx[index].mx_di.un.v.num_channels = 2; /* XXX */
2883 1.2.2.2 skrll mx[index].mx_di.un.v.delta = 256 / (ctl->ctl_step + 1);
2884 1.2.2.2 skrll if (ctrlcnt[audiodev] > 0)
2885 1.2.2.2 skrll snprintf(mx[index].mx_di.label.name,
2886 1.2.2.2 skrll sizeof(mx[index].mx_di.label.name),
2887 1.2.2.2 skrll "%s%d",
2888 1.2.2.2 skrll hdafg_mixer_names[audiodev],
2889 1.2.2.2 skrll ctrlcnt[audiodev] + 1);
2890 1.2.2.2 skrll else
2891 1.2.2.2 skrll strcpy(mx[index].mx_di.label.name,
2892 1.2.2.2 skrll hdafg_mixer_names[audiodev]);
2893 1.2.2.2 skrll ctrlcnt[audiodev]++;
2894 1.2.2.2 skrll
2895 1.2.2.2 skrll switch (audiodev) {
2896 1.2.2.2 skrll case HDAUDIO_MIXER_VOLUME:
2897 1.2.2.2 skrll case HDAUDIO_MIXER_BASS:
2898 1.2.2.2 skrll case HDAUDIO_MIXER_TREBLE:
2899 1.2.2.2 skrll case HDAUDIO_MIXER_OGAIN:
2900 1.2.2.2 skrll mx[index].mx_di.mixer_class =
2901 1.2.2.2 skrll HDAUDIO_MIXER_CLASS_OUTPUTS;
2902 1.2.2.2 skrll hda_trace(sc, " adding outputs.%s\n",
2903 1.2.2.2 skrll mx[index].mx_di.label.name);
2904 1.2.2.2 skrll break;
2905 1.2.2.2 skrll case HDAUDIO_MIXER_MIC:
2906 1.2.2.2 skrll case HDAUDIO_MIXER_MONITOR:
2907 1.2.2.2 skrll mx[index].mx_di.mixer_class =
2908 1.2.2.2 skrll HDAUDIO_MIXER_CLASS_RECORD;
2909 1.2.2.2 skrll hda_trace(sc, " adding record.%s\n",
2910 1.2.2.2 skrll mx[index].mx_di.label.name);
2911 1.2.2.2 skrll break;
2912 1.2.2.2 skrll default:
2913 1.2.2.2 skrll mx[index].mx_di.mixer_class =
2914 1.2.2.2 skrll HDAUDIO_MIXER_CLASS_INPUTS;
2915 1.2.2.2 skrll hda_trace(sc, " adding inputs.%s\n",
2916 1.2.2.2 skrll mx[index].mx_di.label.name);
2917 1.2.2.2 skrll break;
2918 1.2.2.2 skrll }
2919 1.2.2.2 skrll strcpy(mx[index].mx_di.un.v.units.name, AudioNvolume);
2920 1.2.2.3 skrll
2921 1.2.2.2 skrll ++index;
2922 1.2.2.2 skrll
2923 1.2.2.2 skrll if (ctl->ctl_mute) {
2924 1.2.2.2 skrll mx[index] = mx[index - 1];
2925 1.2.2.2 skrll mx[index].mx_di.index = index;
2926 1.2.2.2 skrll mx[index].mx_di.type = AUDIO_MIXER_ENUM;
2927 1.2.2.2 skrll mx[index].mx_di.prev = mx[index].mx_di.next = AUDIO_MIXER_LAST;
2928 1.2.2.2 skrll snprintf(mx[index].mx_di.label.name,
2929 1.2.2.2 skrll sizeof(mx[index].mx_di.label.name),
2930 1.2.2.2 skrll "%s." AudioNmute,
2931 1.2.2.2 skrll mx[index - 1].mx_di.label.name);
2932 1.2.2.2 skrll mx[index].mx_di.un.e.num_mem = 2;
2933 1.2.2.2 skrll strcpy(mx[index].mx_di.un.e.member[0].label.name, AudioNoff);
2934 1.2.2.2 skrll mx[index].mx_di.un.e.member[0].ord = 0;
2935 1.2.2.2 skrll strcpy(mx[index].mx_di.un.e.member[1].label.name, AudioNon);
2936 1.2.2.2 skrll mx[index].mx_di.un.e.member[1].ord = 1;
2937 1.2.2.2 skrll ++index;
2938 1.2.2.2 skrll }
2939 1.2.2.2 skrll }
2940 1.2.2.2 skrll
2941 1.2.2.2 skrll /* DAC selector */
2942 1.2.2.2 skrll if (ndac > 0) {
2943 1.2.2.2 skrll mx[index].mx_ctl = NULL;
2944 1.2.2.2 skrll mx[index].mx_di.index = index;
2945 1.2.2.2 skrll mx[index].mx_di.type = AUDIO_MIXER_SET;
2946 1.2.2.2 skrll mx[index].mx_di.mixer_class = HDAUDIO_MIXER_CLASS_OUTPUTS;
2947 1.2.2.2 skrll mx[index].mx_di.prev = mx[index].mx_di.next = AUDIO_MIXER_LAST;
2948 1.2.2.2 skrll strcpy(mx[index].mx_di.label.name, "dacsel"); /* AudioNselect */
2949 1.2.2.2 skrll mx[index].mx_di.un.s.num_mem = ndac;
2950 1.2.2.2 skrll for (i = 0, j = 0; i < sc->sc_nassocs; i++) {
2951 1.2.2.2 skrll if (sc->sc_assocs[i].as_enable == false)
2952 1.2.2.2 skrll continue;
2953 1.2.2.2 skrll if (sc->sc_assocs[i].as_dir != HDAUDIO_PINDIR_OUT)
2954 1.2.2.2 skrll continue;
2955 1.2.2.2 skrll mx[index].mx_di.un.s.member[j].mask = 1 << i;
2956 1.2.2.2 skrll snprintf(mx[index].mx_di.un.s.member[j].label.name,
2957 1.2.2.2 skrll sizeof(mx[index].mx_di.un.s.member[j].label.name),
2958 1.2.2.2 skrll "%s%02X",
2959 1.2.2.2 skrll hdafg_assoc_type_string(&sc->sc_assocs[i]), i);
2960 1.2.2.2 skrll ++j;
2961 1.2.2.2 skrll }
2962 1.2.2.2 skrll ++index;
2963 1.2.2.2 skrll }
2964 1.2.2.2 skrll
2965 1.2.2.2 skrll /* ADC selector */
2966 1.2.2.2 skrll if (nadc > 0) {
2967 1.2.2.2 skrll mx[index].mx_ctl = NULL;
2968 1.2.2.2 skrll mx[index].mx_di.index = index;
2969 1.2.2.2 skrll mx[index].mx_di.type = AUDIO_MIXER_SET;
2970 1.2.2.2 skrll mx[index].mx_di.mixer_class = HDAUDIO_MIXER_CLASS_RECORD;
2971 1.2.2.2 skrll mx[index].mx_di.prev = mx[index].mx_di.next = AUDIO_MIXER_LAST;
2972 1.2.2.2 skrll strcpy(mx[index].mx_di.label.name, AudioNsource);
2973 1.2.2.2 skrll mx[index].mx_di.un.s.num_mem = nadc;
2974 1.2.2.2 skrll for (i = 0, j = 0; i < sc->sc_nassocs; i++) {
2975 1.2.2.2 skrll if (sc->sc_assocs[i].as_enable == false)
2976 1.2.2.2 skrll continue;
2977 1.2.2.2 skrll if (sc->sc_assocs[i].as_dir != HDAUDIO_PINDIR_IN)
2978 1.2.2.2 skrll continue;
2979 1.2.2.2 skrll mx[index].mx_di.un.s.member[j].mask = 1 << i;
2980 1.2.2.2 skrll snprintf(mx[index].mx_di.un.s.member[j].label.name,
2981 1.2.2.2 skrll sizeof(mx[index].mx_di.un.s.member[j].label.name),
2982 1.2.2.2 skrll "%s%02X",
2983 1.2.2.2 skrll hdafg_assoc_type_string(&sc->sc_assocs[i]), i);
2984 1.2.2.2 skrll ++j;
2985 1.2.2.2 skrll }
2986 1.2.2.2 skrll ++index;
2987 1.2.2.2 skrll }
2988 1.2.2.2 skrll
2989 1.2.2.2 skrll sc->sc_mixers = mx;
2990 1.2.2.2 skrll }
2991 1.2.2.2 skrll
2992 1.2.2.2 skrll static void
2993 1.2.2.2 skrll hdafg_commit(struct hdafg_softc *sc)
2994 1.2.2.2 skrll {
2995 1.2.2.2 skrll struct hdaudio_widget *w;
2996 1.2.2.2 skrll uint32_t gdata, gmask, gdir;
2997 1.2.2.2 skrll int commitgpio;
2998 1.2.2.2 skrll int i;
2999 1.2.2.2 skrll
3000 1.2.2.2 skrll /* Commit controls */
3001 1.2.2.2 skrll hdafg_control_commit(sc);
3002 1.2.2.2 skrll
3003 1.2.2.2 skrll /* Commit selectors, pins, and EAPD */
3004 1.2.2.2 skrll for (i = 0; i < sc->sc_nwidgets; i++) {
3005 1.2.2.2 skrll w = &sc->sc_widgets[i];
3006 1.2.2.2 skrll if (w->w_selconn == -1)
3007 1.2.2.2 skrll w->w_selconn = 0;
3008 1.2.2.2 skrll if (w->w_nconns > 0)
3009 1.2.2.2 skrll hdafg_widget_connection_select(w, w->w_selconn);
3010 1.2.2.2 skrll if (w->w_type == COP_AWCAP_TYPE_PIN_COMPLEX)
3011 1.2.2.2 skrll hdaudio_command(sc->sc_codec, w->w_nid,
3012 1.2.2.2 skrll CORB_SET_PIN_WIDGET_CONTROL, w->w_pin.ctrl);
3013 1.2.2.2 skrll if (w->w_p.eapdbtl != 0xffffffff)
3014 1.2.2.2 skrll hdaudio_command(sc->sc_codec, w->w_nid,
3015 1.2.2.2 skrll CORB_SET_EAPD_BTL_ENABLE, w->w_p.eapdbtl);
3016 1.2.2.2 skrll }
3017 1.2.2.2 skrll
3018 1.2.2.2 skrll gdata = gmask = gdir = commitgpio = 0;
3019 1.2.2.2 skrll #ifdef notyet
3020 1.2.2.2 skrll int numgpio = COP_GPIO_COUNT_NUM_GPIO(sc->sc_p.gpio_cnt);
3021 1.2.2.2 skrll
3022 1.2.2.2 skrll hda_trace(sc, "found %d GPIOs\n", numgpio);
3023 1.2.2.2 skrll for (i = 0; i < numgpio && i < 8; i++) {
3024 1.2.2.2 skrll if (commitgpio == 0)
3025 1.2.2.2 skrll commitgpio = 1;
3026 1.2.2.2 skrll gdata |= 1 << i;
3027 1.2.2.2 skrll gmask |= 1 << i;
3028 1.2.2.2 skrll gdir |= 1 << i;
3029 1.2.2.2 skrll }
3030 1.2.2.2 skrll #endif
3031 1.2.2.2 skrll
3032 1.2.2.2 skrll if (commitgpio) {
3033 1.2.2.2 skrll hda_trace(sc, "GPIO commit: data=%08X mask=%08X dir=%08X\n",
3034 1.2.2.2 skrll gdata, gmask, gdir);
3035 1.2.2.2 skrll hdaudio_command(sc->sc_codec, sc->sc_nid,
3036 1.2.2.2 skrll CORB_SET_GPIO_ENABLE_MASK, gmask);
3037 1.2.2.2 skrll hdaudio_command(sc->sc_codec, sc->sc_nid,
3038 1.2.2.2 skrll CORB_SET_GPIO_DIRECTION, gdir);
3039 1.2.2.2 skrll hdaudio_command(sc->sc_codec, sc->sc_nid,
3040 1.2.2.2 skrll CORB_SET_GPIO_DATA, gdata);
3041 1.2.2.2 skrll }
3042 1.2.2.2 skrll }
3043 1.2.2.2 skrll
3044 1.2.2.2 skrll static void
3045 1.2.2.2 skrll hdafg_stream_connect_hdmi(struct hdafg_softc *sc, struct hdaudio_assoc *as,
3046 1.2.2.3 skrll struct hdaudio_widget *w, const audio_params_t *params)
3047 1.2.2.2 skrll {
3048 1.2.2.2 skrll struct hdmi_audio_infoframe hdmi;
3049 1.2.2.2 skrll /* TODO struct displayport_audio_infoframe dp; */
3050 1.2.2.2 skrll uint8_t *dip = NULL;
3051 1.2.2.2 skrll size_t diplen = 0;
3052 1.2.2.2 skrll int i;
3053 1.2.2.2 skrll
3054 1.2.2.2 skrll #ifdef HDAFG_HDMI_DEBUG
3055 1.2.2.2 skrll uint32_t res;
3056 1.2.2.2 skrll res = hdaudio_command(sc->sc_codec, w->w_nid,
3057 1.2.2.2 skrll CORB_GET_HDMI_DIP_XMIT_CTRL, 0);
3058 1.2.2.2 skrll hda_print(sc, "connect HDMI nid %02X, xmitctrl = 0x%08X\n",
3059 1.2.2.2 skrll w->w_nid, res);
3060 1.2.2.2 skrll #endif
3061 1.2.2.2 skrll
3062 1.2.2.2 skrll /* disable infoframe transmission */
3063 1.2.2.2 skrll hdaudio_command(sc->sc_codec, w->w_nid,
3064 1.2.2.2 skrll CORB_SET_HDMI_DIP_XMIT_CTRL, COP_DIP_XMIT_CTRL_DISABLE);
3065 1.2.2.2 skrll
3066 1.2.2.2 skrll /* build new infoframe */
3067 1.2.2.2 skrll if (as->as_digital == HDAFG_AS_HDMI) {
3068 1.2.2.2 skrll dip = (uint8_t *)&hdmi;
3069 1.2.2.2 skrll diplen = sizeof(hdmi);
3070 1.2.2.2 skrll memset(&hdmi, 0, sizeof(hdmi));
3071 1.2.2.2 skrll hdmi.header.packet_type = HDMI_AI_PACKET_TYPE;
3072 1.2.2.2 skrll hdmi.header.version = HDMI_AI_VERSION;
3073 1.2.2.2 skrll hdmi.header.length = HDMI_AI_LENGTH;
3074 1.2.2.3 skrll hdmi.ct_cc = params->channels - 1;
3075 1.2.2.3 skrll if (params->channels > 2) {
3076 1.2.2.3 skrll hdmi.ca = 0x1f;
3077 1.2.2.3 skrll } else {
3078 1.2.2.3 skrll hdmi.ca = 0x00;
3079 1.2.2.3 skrll }
3080 1.2.2.2 skrll hdafg_dd_hdmi_ai_cksum(&hdmi);
3081 1.2.2.2 skrll }
3082 1.2.2.2 skrll /* update data island with new audio infoframe */
3083 1.2.2.2 skrll if (dip) {
3084 1.2.2.2 skrll hdaudio_command(sc->sc_codec, w->w_nid,
3085 1.2.2.2 skrll CORB_SET_HDMI_DIP_INDEX, 0);
3086 1.2.2.2 skrll for (i = 0; i < diplen; i++) {
3087 1.2.2.2 skrll hdaudio_command(sc->sc_codec, w->w_nid,
3088 1.2.2.2 skrll CORB_SET_HDMI_DIP_DATA, dip[i]);
3089 1.2.2.2 skrll }
3090 1.2.2.2 skrll }
3091 1.2.2.2 skrll
3092 1.2.2.2 skrll /* enable infoframe transmission */
3093 1.2.2.2 skrll hdaudio_command(sc->sc_codec, w->w_nid,
3094 1.2.2.2 skrll CORB_SET_HDMI_DIP_XMIT_CTRL, COP_DIP_XMIT_CTRL_BEST_EFFORT);
3095 1.2.2.2 skrll }
3096 1.2.2.2 skrll
3097 1.2.2.2 skrll static void
3098 1.2.2.2 skrll hdafg_stream_connect(struct hdafg_softc *sc, int mode)
3099 1.2.2.2 skrll {
3100 1.2.2.2 skrll struct hdaudio_assoc *as = sc->sc_assocs;
3101 1.2.2.2 skrll struct hdaudio_widget *w;
3102 1.2.2.3 skrll const audio_params_t *params;
3103 1.2.2.2 skrll uint16_t fmt, dfmt;
3104 1.2.2.2 skrll int tag, chn, maxchan, c;
3105 1.2.2.2 skrll int i, j, k;
3106 1.2.2.2 skrll
3107 1.2.2.2 skrll KASSERT(mode == AUMODE_PLAY || mode == AUMODE_RECORD);
3108 1.2.2.2 skrll
3109 1.2.2.3 skrll if (mode == AUMODE_PLAY) {
3110 1.2.2.2 skrll fmt = hdaudio_stream_param(sc->sc_audiodev.ad_playback,
3111 1.2.2.2 skrll &sc->sc_pparam);
3112 1.2.2.3 skrll params = &sc->sc_pparam;
3113 1.2.2.3 skrll } else {
3114 1.2.2.2 skrll fmt = hdaudio_stream_param(sc->sc_audiodev.ad_capture,
3115 1.2.2.2 skrll &sc->sc_rparam);
3116 1.2.2.3 skrll params = &sc->sc_rparam;
3117 1.2.2.3 skrll }
3118 1.2.2.2 skrll
3119 1.2.2.2 skrll for (i = 0; i < sc->sc_nassocs; i++) {
3120 1.2.2.2 skrll if (as[i].as_enable == false)
3121 1.2.2.2 skrll continue;
3122 1.2.2.2 skrll
3123 1.2.2.2 skrll if (mode == AUMODE_PLAY && as[i].as_dir != HDAUDIO_PINDIR_OUT)
3124 1.2.2.2 skrll continue;
3125 1.2.2.2 skrll if (mode == AUMODE_RECORD && as[i].as_dir != HDAUDIO_PINDIR_IN)
3126 1.2.2.2 skrll continue;
3127 1.2.2.2 skrll
3128 1.2.2.2 skrll fmt &= ~HDAUDIO_FMT_CHAN_MASK;
3129 1.2.2.2 skrll if (as[i].as_dir == HDAUDIO_PINDIR_OUT &&
3130 1.2.2.2 skrll sc->sc_audiodev.ad_playback != NULL) {
3131 1.2.2.2 skrll tag = hdaudio_stream_tag(sc->sc_audiodev.ad_playback);
3132 1.2.2.2 skrll fmt |= HDAUDIO_FMT_CHAN(sc->sc_pparam.channels);
3133 1.2.2.2 skrll maxchan = sc->sc_pparam.channels;
3134 1.2.2.2 skrll } else if (as[i].as_dir == HDAUDIO_PINDIR_IN &&
3135 1.2.2.2 skrll sc->sc_audiodev.ad_capture != NULL) {
3136 1.2.2.2 skrll tag = hdaudio_stream_tag(sc->sc_audiodev.ad_capture);
3137 1.2.2.2 skrll fmt |= HDAUDIO_FMT_CHAN(sc->sc_rparam.channels);
3138 1.2.2.2 skrll maxchan = sc->sc_rparam.channels;
3139 1.2.2.2 skrll } else {
3140 1.2.2.2 skrll tag = 0;
3141 1.2.2.2 skrll if (as[i].as_dir == HDAUDIO_PINDIR_OUT) {
3142 1.2.2.2 skrll fmt |= HDAUDIO_FMT_CHAN(sc->sc_pchan);
3143 1.2.2.2 skrll maxchan = sc->sc_pchan;
3144 1.2.2.2 skrll } else {
3145 1.2.2.2 skrll fmt |= HDAUDIO_FMT_CHAN(sc->sc_rchan);
3146 1.2.2.2 skrll maxchan = sc->sc_rchan;
3147 1.2.2.2 skrll }
3148 1.2.2.2 skrll }
3149 1.2.2.2 skrll
3150 1.2.2.2 skrll chn = 0;
3151 1.2.2.2 skrll for (j = 0; j < HDAUDIO_MAXPINS; j++) {
3152 1.2.2.2 skrll if (as[i].as_dacs[j] == 0)
3153 1.2.2.2 skrll continue;
3154 1.2.2.2 skrll w = hdafg_widget_lookup(sc, as[i].as_dacs[j]);
3155 1.2.2.2 skrll if (w == NULL || w->w_enable == FALSE)
3156 1.2.2.2 skrll continue;
3157 1.2.2.2 skrll if (as[i].as_hpredir >= 0 && i == as[i].as_pincnt)
3158 1.2.2.2 skrll chn = 0;
3159 1.2.2.2 skrll if (chn >= maxchan)
3160 1.2.2.2 skrll chn = 0; /* XXX */
3161 1.2.2.2 skrll c = (tag << 4) | chn;
3162 1.2.2.2 skrll
3163 1.2.2.2 skrll if (as[i].as_activated == false)
3164 1.2.2.2 skrll c = 0;
3165 1.2.2.2 skrll
3166 1.2.2.2 skrll /*
3167 1.2.2.2 skrll * If a non-PCM stream is being connected, and the
3168 1.2.2.2 skrll * analog converter doesn't support non-PCM streams,
3169 1.2.2.2 skrll * then don't decode it
3170 1.2.2.2 skrll */
3171 1.2.2.2 skrll if (!(w->w_p.aw_cap & COP_AWCAP_DIGITAL) &&
3172 1.2.2.2 skrll !(w->w_p.stream_format & COP_STREAM_FORMAT_AC3) &&
3173 1.2.2.2 skrll (fmt & HDAUDIO_FMT_TYPE_NONPCM)) {
3174 1.2.2.2 skrll hdaudio_command(sc->sc_codec, w->w_nid,
3175 1.2.2.2 skrll CORB_SET_CONVERTER_STREAM_CHANNEL, 0);
3176 1.2.2.2 skrll continue;
3177 1.2.2.2 skrll }
3178 1.2.2.2 skrll
3179 1.2.2.2 skrll hdaudio_command(sc->sc_codec, w->w_nid,
3180 1.2.2.2 skrll CORB_SET_CONVERTER_FORMAT, fmt);
3181 1.2.2.2 skrll if (w->w_p.aw_cap & COP_AWCAP_DIGITAL) {
3182 1.2.2.2 skrll dfmt = hdaudio_command(sc->sc_codec, w->w_nid,
3183 1.2.2.2 skrll CORB_GET_DIGITAL_CONVERTER_CONTROL, 0) &
3184 1.2.2.2 skrll 0xff;
3185 1.2.2.2 skrll dfmt |= COP_DIGITAL_CONVCTRL1_DIGEN;
3186 1.2.2.2 skrll if (fmt & HDAUDIO_FMT_TYPE_NONPCM)
3187 1.2.2.2 skrll dfmt |= COP_DIGITAL_CONVCTRL1_NAUDIO;
3188 1.2.2.2 skrll else
3189 1.2.2.2 skrll dfmt &= ~COP_DIGITAL_CONVCTRL1_NAUDIO;
3190 1.2.2.3 skrll if (sc->sc_vendor == HDAUDIO_VENDOR_NVIDIA)
3191 1.2.2.3 skrll dfmt |= COP_DIGITAL_CONVCTRL1_COPY;
3192 1.2.2.2 skrll hdaudio_command(sc->sc_codec, w->w_nid,
3193 1.2.2.2 skrll CORB_SET_DIGITAL_CONVERTER_CONTROL_1, dfmt);
3194 1.2.2.2 skrll }
3195 1.2.2.2 skrll if (w->w_pin.cap & (COP_PINCAP_HDMI|COP_PINCAP_DP)) {
3196 1.2.2.2 skrll hdaudio_command(sc->sc_codec, w->w_nid,
3197 1.2.2.2 skrll CORB_SET_CONVERTER_CHANNEL_COUNT,
3198 1.2.2.2 skrll maxchan - 1);
3199 1.2.2.2 skrll for (k = 0; k < maxchan; k++) {
3200 1.2.2.2 skrll hdaudio_command(sc->sc_codec, w->w_nid,
3201 1.2.2.2 skrll CORB_ASP_SET_CHANNEL_MAPPING,
3202 1.2.2.2 skrll (k << 4) | k);
3203 1.2.2.2 skrll }
3204 1.2.2.2 skrll }
3205 1.2.2.2 skrll hdaudio_command(sc->sc_codec, w->w_nid,
3206 1.2.2.2 skrll CORB_SET_CONVERTER_STREAM_CHANNEL, c);
3207 1.2.2.2 skrll chn += COP_AWCAP_CHANNEL_COUNT(w->w_p.aw_cap);
3208 1.2.2.2 skrll }
3209 1.2.2.2 skrll
3210 1.2.2.2 skrll for (j = 0; j < HDAUDIO_MAXPINS; j++) {
3211 1.2.2.2 skrll if (as[i].as_pins[j] == 0)
3212 1.2.2.2 skrll continue;
3213 1.2.2.2 skrll w = hdafg_widget_lookup(sc, as[i].as_pins[j]);
3214 1.2.2.2 skrll if (w == NULL || w->w_enable == FALSE)
3215 1.2.2.2 skrll continue;
3216 1.2.2.2 skrll if (w->w_pin.cap & (COP_PINCAP_HDMI|COP_PINCAP_DP))
3217 1.2.2.2 skrll hdafg_stream_connect_hdmi(sc, &as[i],
3218 1.2.2.3 skrll w, params);
3219 1.2.2.2 skrll }
3220 1.2.2.2 skrll }
3221 1.2.2.2 skrll }
3222 1.2.2.2 skrll
3223 1.2.2.2 skrll static int
3224 1.2.2.2 skrll hdafg_stream_intr(struct hdaudio_stream *st)
3225 1.2.2.2 skrll {
3226 1.2.2.2 skrll struct hdaudio_audiodev *ad = st->st_cookie;
3227 1.2.2.2 skrll int handled = 0;
3228 1.2.2.2 skrll
3229 1.2.2.2 skrll (void)hda_read1(ad->ad_sc->sc_host, HDAUDIO_SD_STS(st->st_shift));
3230 1.2.2.2 skrll hda_write1(ad->ad_sc->sc_host, HDAUDIO_SD_STS(st->st_shift),
3231 1.2.2.2 skrll HDAUDIO_STS_DESE | HDAUDIO_STS_FIFOE | HDAUDIO_STS_BCIS);
3232 1.2.2.2 skrll
3233 1.2.2.2 skrll mutex_spin_enter(&ad->ad_sc->sc_intr_lock);
3234 1.2.2.2 skrll /* XXX test (sts & HDAUDIO_STS_BCIS)? */
3235 1.2.2.2 skrll if (st == ad->ad_playback && ad->ad_playbackintr) {
3236 1.2.2.2 skrll ad->ad_playbackintr(ad->ad_playbackintrarg);
3237 1.2.2.2 skrll handled = 1;
3238 1.2.2.2 skrll } else if (st == ad->ad_capture && ad->ad_captureintr) {
3239 1.2.2.2 skrll ad->ad_captureintr(ad->ad_captureintrarg);
3240 1.2.2.2 skrll handled = 1;
3241 1.2.2.2 skrll }
3242 1.2.2.2 skrll mutex_spin_exit(&ad->ad_sc->sc_intr_lock);
3243 1.2.2.2 skrll
3244 1.2.2.2 skrll return handled;
3245 1.2.2.2 skrll }
3246 1.2.2.2 skrll
3247 1.2.2.2 skrll static bool
3248 1.2.2.2 skrll hdafg_rate_supported(struct hdafg_softc *sc, u_int frequency)
3249 1.2.2.2 skrll {
3250 1.2.2.2 skrll uint32_t caps = sc->sc_p.pcm_size_rate;
3251 1.2.2.2 skrll
3252 1.2.2.3 skrll if (sc->sc_fixed_rate)
3253 1.2.2.3 skrll return frequency == sc->sc_fixed_rate;
3254 1.2.2.3 skrll
3255 1.2.2.2 skrll #define ISFREQOK(shift) ((caps & (1 << (shift))) ? true : false)
3256 1.2.2.2 skrll switch (frequency) {
3257 1.2.2.2 skrll case 8000:
3258 1.2.2.2 skrll return ISFREQOK(0);
3259 1.2.2.2 skrll case 11025:
3260 1.2.2.2 skrll return ISFREQOK(1);
3261 1.2.2.2 skrll case 16000:
3262 1.2.2.2 skrll return ISFREQOK(2);
3263 1.2.2.2 skrll case 22050:
3264 1.2.2.2 skrll return ISFREQOK(3);
3265 1.2.2.2 skrll case 32000:
3266 1.2.2.2 skrll return ISFREQOK(4);
3267 1.2.2.2 skrll case 44100:
3268 1.2.2.2 skrll return ISFREQOK(5);
3269 1.2.2.3 skrll return true;
3270 1.2.2.2 skrll case 48000:
3271 1.2.2.2 skrll return true; /* Must be supported by all codecs */
3272 1.2.2.2 skrll case 88200:
3273 1.2.2.2 skrll return ISFREQOK(7);
3274 1.2.2.2 skrll case 96000:
3275 1.2.2.2 skrll return ISFREQOK(8);
3276 1.2.2.2 skrll case 176400:
3277 1.2.2.2 skrll return ISFREQOK(9);
3278 1.2.2.2 skrll case 192000:
3279 1.2.2.2 skrll return ISFREQOK(10);
3280 1.2.2.2 skrll case 384000:
3281 1.2.2.2 skrll return ISFREQOK(11);
3282 1.2.2.2 skrll default:
3283 1.2.2.2 skrll return false;
3284 1.2.2.2 skrll }
3285 1.2.2.2 skrll #undef ISFREQOK
3286 1.2.2.2 skrll }
3287 1.2.2.2 skrll
3288 1.2.2.2 skrll static bool
3289 1.2.2.2 skrll hdafg_bits_supported(struct hdafg_softc *sc, u_int bits)
3290 1.2.2.2 skrll {
3291 1.2.2.2 skrll uint32_t caps = sc->sc_p.pcm_size_rate;
3292 1.2.2.2 skrll #define ISBITSOK(shift) ((caps & (1 << (shift))) ? true : false)
3293 1.2.2.2 skrll switch (bits) {
3294 1.2.2.2 skrll case 8:
3295 1.2.2.2 skrll return ISBITSOK(16);
3296 1.2.2.2 skrll case 16:
3297 1.2.2.2 skrll return ISBITSOK(17);
3298 1.2.2.2 skrll case 20:
3299 1.2.2.2 skrll return ISBITSOK(18);
3300 1.2.2.2 skrll case 24:
3301 1.2.2.2 skrll return ISBITSOK(19);
3302 1.2.2.2 skrll case 32:
3303 1.2.2.2 skrll return ISBITSOK(20);
3304 1.2.2.2 skrll default:
3305 1.2.2.2 skrll return false;
3306 1.2.2.2 skrll }
3307 1.2.2.2 skrll #undef ISBITSOK
3308 1.2.2.2 skrll }
3309 1.2.2.2 skrll
3310 1.2.2.2 skrll static bool
3311 1.2.2.2 skrll hdafg_probe_encoding(struct hdafg_softc *sc,
3312 1.2.2.2 skrll u_int validbits, u_int precision, int encoding, bool force)
3313 1.2.2.2 skrll {
3314 1.2.2.2 skrll struct audio_format f;
3315 1.2.2.2 skrll int i;
3316 1.2.2.2 skrll
3317 1.2.2.2 skrll if (!force && hdafg_bits_supported(sc, validbits) == false)
3318 1.2.2.2 skrll return false;
3319 1.2.2.2 skrll
3320 1.2.2.2 skrll memset(&f, 0, sizeof(f));
3321 1.2.2.2 skrll f.driver_data = NULL;
3322 1.2.2.2 skrll f.mode = 0;
3323 1.2.2.2 skrll f.encoding = encoding;
3324 1.2.2.2 skrll f.validbits = validbits;
3325 1.2.2.2 skrll f.precision = precision;
3326 1.2.2.2 skrll f.channels = 0;
3327 1.2.2.2 skrll f.channel_mask = 0;
3328 1.2.2.2 skrll f.frequency_type = 0;
3329 1.2.2.2 skrll for (i = 0; i < __arraycount(hdafg_possible_rates); i++) {
3330 1.2.2.2 skrll u_int rate = hdafg_possible_rates[i];
3331 1.2.2.2 skrll if (hdafg_rate_supported(sc, rate))
3332 1.2.2.2 skrll f.frequency[f.frequency_type++] = rate;
3333 1.2.2.2 skrll }
3334 1.2.2.2 skrll
3335 1.2.2.2 skrll #define HDAUDIO_INITFMT(ch, chmask) \
3336 1.2.2.2 skrll do { \
3337 1.2.2.2 skrll f.channels = (ch); \
3338 1.2.2.2 skrll f.channel_mask = (chmask); \
3339 1.2.2.2 skrll f.mode = 0; \
3340 1.2.2.2 skrll if (sc->sc_pchan >= (ch)) \
3341 1.2.2.2 skrll f.mode |= AUMODE_PLAY; \
3342 1.2.2.2 skrll if (sc->sc_rchan >= (ch)) \
3343 1.2.2.2 skrll f.mode |= AUMODE_RECORD; \
3344 1.2.2.2 skrll if (f.mode != 0) \
3345 1.2.2.2 skrll hdafg_append_formats(&sc->sc_audiodev, &f); \
3346 1.2.2.2 skrll } while (0)
3347 1.2.2.2 skrll
3348 1.2.2.2 skrll /* Commented out, otherwise monaural samples play through left
3349 1.2.2.2 skrll * channel only
3350 1.2.2.2 skrll */
3351 1.2.2.2 skrll /* HDAUDIO_INITFMT(1, AUFMT_MONAURAL); */
3352 1.2.2.2 skrll HDAUDIO_INITFMT(2, AUFMT_STEREO);
3353 1.2.2.2 skrll HDAUDIO_INITFMT(4, AUFMT_SURROUND4);
3354 1.2.2.2 skrll HDAUDIO_INITFMT(6, AUFMT_DOLBY_5_1);
3355 1.2.2.2 skrll HDAUDIO_INITFMT(8, AUFMT_SURROUND_7_1);
3356 1.2.2.2 skrll
3357 1.2.2.2 skrll #undef HDAUDIO_INITFMT
3358 1.2.2.2 skrll
3359 1.2.2.2 skrll return true;
3360 1.2.2.2 skrll }
3361 1.2.2.2 skrll
3362 1.2.2.2 skrll
3363 1.2.2.2 skrll static void
3364 1.2.2.2 skrll hdafg_configure_encodings(struct hdafg_softc *sc)
3365 1.2.2.2 skrll {
3366 1.2.2.2 skrll struct hdaudio_assoc *as = sc->sc_assocs;
3367 1.2.2.2 skrll struct hdaudio_widget *w;
3368 1.2.2.2 skrll struct audio_format f;
3369 1.2.2.2 skrll uint32_t stream_format, caps;
3370 1.2.2.2 skrll int nchan, i, nid;
3371 1.2.2.2 skrll
3372 1.2.2.2 skrll sc->sc_pchan = sc->sc_rchan = 0;
3373 1.2.2.2 skrll
3374 1.2.2.2 skrll for (nchan = 0, i = 0; i < sc->sc_nassocs; i++) {
3375 1.2.2.2 skrll nchan = hdafg_assoc_count_channels(sc, &as[i],
3376 1.2.2.2 skrll HDAUDIO_PINDIR_OUT);
3377 1.2.2.2 skrll if (nchan > sc->sc_pchan)
3378 1.2.2.2 skrll sc->sc_pchan = nchan;
3379 1.2.2.2 skrll }
3380 1.2.2.2 skrll for (nchan = 0, i = 0; i < sc->sc_nassocs; i++) {
3381 1.2.2.2 skrll nchan = hdafg_assoc_count_channels(sc, &as[i],
3382 1.2.2.2 skrll HDAUDIO_PINDIR_IN);
3383 1.2.2.2 skrll if (nchan > sc->sc_rchan)
3384 1.2.2.2 skrll sc->sc_rchan = nchan;
3385 1.2.2.2 skrll }
3386 1.2.2.2 skrll hda_print(sc, "%dch/%dch", sc->sc_pchan, sc->sc_rchan);
3387 1.2.2.2 skrll
3388 1.2.2.2 skrll for (i = 0; i < __arraycount(hdafg_possible_rates); i++)
3389 1.2.2.2 skrll if (hdafg_rate_supported(sc,
3390 1.2.2.2 skrll hdafg_possible_rates[i]))
3391 1.2.2.2 skrll hda_print1(sc, " %uHz", hdafg_possible_rates[i]);
3392 1.2.2.2 skrll
3393 1.2.2.2 skrll stream_format = sc->sc_p.stream_format;
3394 1.2.2.2 skrll caps = 0;
3395 1.2.2.2 skrll for (nid = sc->sc_startnode; nid < sc->sc_endnode; nid++) {
3396 1.2.2.2 skrll w = hdafg_widget_lookup(sc, nid);
3397 1.2.2.2 skrll if (w == NULL)
3398 1.2.2.2 skrll continue;
3399 1.2.2.2 skrll stream_format |= w->w_p.stream_format;
3400 1.2.2.2 skrll caps |= w->w_p.aw_cap;
3401 1.2.2.2 skrll }
3402 1.2.2.2 skrll if (stream_format == 0) {
3403 1.2.2.2 skrll hda_print(sc,
3404 1.2.2.2 skrll "WARNING: unsupported stream format mask 0x%X, assuming PCM\n",
3405 1.2.2.2 skrll stream_format);
3406 1.2.2.2 skrll stream_format |= COP_STREAM_FORMAT_PCM;
3407 1.2.2.2 skrll }
3408 1.2.2.2 skrll
3409 1.2.2.2 skrll if (stream_format & COP_STREAM_FORMAT_PCM) {
3410 1.2.2.2 skrll int e = AUDIO_ENCODING_SLINEAR_LE;
3411 1.2.2.2 skrll if (hdafg_probe_encoding(sc, 8, 16, e, false))
3412 1.2.2.2 skrll hda_print1(sc, " PCM8");
3413 1.2.2.2 skrll if (hdafg_probe_encoding(sc, 16, 16, e, false))
3414 1.2.2.2 skrll hda_print1(sc, " PCM16");
3415 1.2.2.2 skrll if (hdafg_probe_encoding(sc, 20, 32, e, false))
3416 1.2.2.2 skrll hda_print1(sc, " PCM20");
3417 1.2.2.2 skrll if (hdafg_probe_encoding(sc, 24, 32, e, false))
3418 1.2.2.2 skrll hda_print1(sc, " PCM24");
3419 1.2.2.2 skrll if (hdafg_probe_encoding(sc, 32, 32, e, false))
3420 1.2.2.2 skrll hda_print1(sc, " PCM32");
3421 1.2.2.2 skrll }
3422 1.2.2.2 skrll
3423 1.2.2.2 skrll if ((stream_format & COP_STREAM_FORMAT_AC3) ||
3424 1.2.2.2 skrll (caps & COP_AWCAP_DIGITAL)) {
3425 1.2.2.2 skrll int e = AUDIO_ENCODING_AC3;
3426 1.2.2.2 skrll if (hdafg_probe_encoding(sc, 16, 16, e, false))
3427 1.2.2.2 skrll hda_print1(sc, " AC3");
3428 1.2.2.2 skrll }
3429 1.2.2.2 skrll
3430 1.2.2.2 skrll if (sc->sc_audiodev.ad_nformats == 0) {
3431 1.2.2.2 skrll hdafg_probe_encoding(sc, 16, 16, AUDIO_ENCODING_SLINEAR_LE, true);
3432 1.2.2.2 skrll hda_print1(sc, " PCM16*");
3433 1.2.2.2 skrll }
3434 1.2.2.2 skrll
3435 1.2.2.2 skrll /*
3436 1.2.2.2 skrll * XXX JDM 20090614
3437 1.2.2.2 skrll * MI audio assumes that at least one playback and one capture format
3438 1.2.2.2 skrll * is reported by the hw driver; until this bug is resolved just
3439 1.2.2.2 skrll * report 2ch capabilities if the function group does not support
3440 1.2.2.2 skrll * the direction.
3441 1.2.2.2 skrll */
3442 1.2.2.2 skrll if (sc->sc_rchan == 0 || sc->sc_pchan == 0) {
3443 1.2.2.2 skrll memset(&f, 0, sizeof(f));
3444 1.2.2.2 skrll f.driver_data = NULL;
3445 1.2.2.2 skrll f.mode = 0;
3446 1.2.2.2 skrll f.encoding = AUDIO_ENCODING_SLINEAR_LE;
3447 1.2.2.2 skrll f.validbits = 16;
3448 1.2.2.2 skrll f.precision = 16;
3449 1.2.2.2 skrll f.channels = 2;
3450 1.2.2.2 skrll f.channel_mask = AUFMT_STEREO;
3451 1.2.2.2 skrll f.frequency_type = 0;
3452 1.2.2.3 skrll f.frequency[0] = f.frequency[1] = sc->sc_fixed_rate ?
3453 1.2.2.3 skrll sc->sc_fixed_rate : 48000;
3454 1.2.2.2 skrll f.mode = AUMODE_PLAY|AUMODE_RECORD;
3455 1.2.2.2 skrll hdafg_append_formats(&sc->sc_audiodev, &f);
3456 1.2.2.2 skrll }
3457 1.2.2.2 skrll
3458 1.2.2.2 skrll hda_print1(sc, "\n");
3459 1.2.2.2 skrll }
3460 1.2.2.2 skrll
3461 1.2.2.2 skrll static void
3462 1.2.2.2 skrll hdafg_hp_switch_handler(void *opaque)
3463 1.2.2.2 skrll {
3464 1.2.2.2 skrll struct hdafg_softc *sc = opaque;
3465 1.2.2.2 skrll struct hdaudio_assoc *as = sc->sc_assocs;
3466 1.2.2.2 skrll struct hdaudio_widget *w;
3467 1.2.2.2 skrll uint32_t res = 0;
3468 1.2.2.2 skrll int i, j;
3469 1.2.2.2 skrll
3470 1.2.2.2 skrll if (!device_is_active(sc->sc_dev))
3471 1.2.2.2 skrll goto resched;
3472 1.2.2.2 skrll
3473 1.2.2.2 skrll for (i = 0; i < sc->sc_nassocs; i++) {
3474 1.2.2.2 skrll if (as[i].as_digital != HDAFG_AS_ANALOG &&
3475 1.2.2.2 skrll as[i].as_digital != HDAFG_AS_SPDIF)
3476 1.2.2.2 skrll continue;
3477 1.2.2.2 skrll for (j = 0; j < HDAUDIO_MAXPINS; j++) {
3478 1.2.2.2 skrll if (as[i].as_pins[j] == 0)
3479 1.2.2.2 skrll continue;
3480 1.2.2.2 skrll w = hdafg_widget_lookup(sc, as[i].as_pins[j]);
3481 1.2.2.2 skrll if (w == NULL || w->w_enable == false)
3482 1.2.2.2 skrll continue;
3483 1.2.2.2 skrll if (w->w_type != COP_AWCAP_TYPE_PIN_COMPLEX)
3484 1.2.2.2 skrll continue;
3485 1.2.2.2 skrll if (COP_CFG_DEFAULT_DEVICE(w->w_pin.config) !=
3486 1.2.2.2 skrll COP_DEVICE_HP_OUT)
3487 1.2.2.2 skrll continue;
3488 1.2.2.2 skrll res |= hdaudio_command(sc->sc_codec, as[i].as_pins[j],
3489 1.2.2.2 skrll CORB_GET_PIN_SENSE, 0) &
3490 1.2.2.2 skrll COP_GET_PIN_SENSE_PRESENSE_DETECT;
3491 1.2.2.2 skrll }
3492 1.2.2.2 skrll }
3493 1.2.2.2 skrll
3494 1.2.2.2 skrll for (i = 0; i < sc->sc_nassocs; i++) {
3495 1.2.2.2 skrll if (as[i].as_digital != HDAFG_AS_ANALOG &&
3496 1.2.2.2 skrll as[i].as_digital != HDAFG_AS_SPDIF)
3497 1.2.2.2 skrll continue;
3498 1.2.2.2 skrll for (j = 0; j < HDAUDIO_MAXPINS; j++) {
3499 1.2.2.2 skrll if (as[i].as_pins[j] == 0)
3500 1.2.2.2 skrll continue;
3501 1.2.2.2 skrll w = hdafg_widget_lookup(sc, as[i].as_pins[j]);
3502 1.2.2.2 skrll if (w == NULL || w->w_enable == false)
3503 1.2.2.2 skrll continue;
3504 1.2.2.2 skrll if (w->w_type != COP_AWCAP_TYPE_PIN_COMPLEX)
3505 1.2.2.2 skrll continue;
3506 1.2.2.2 skrll switch (COP_CFG_DEFAULT_DEVICE(w->w_pin.config)) {
3507 1.2.2.2 skrll case COP_DEVICE_HP_OUT:
3508 1.2.2.2 skrll if (res & COP_GET_PIN_SENSE_PRESENSE_DETECT)
3509 1.2.2.2 skrll w->w_pin.ctrl |= COP_PWC_OUT_ENABLE;
3510 1.2.2.2 skrll else
3511 1.2.2.2 skrll w->w_pin.ctrl &= ~COP_PWC_OUT_ENABLE;
3512 1.2.2.2 skrll hdaudio_command(sc->sc_codec, w->w_nid,
3513 1.2.2.2 skrll CORB_SET_PIN_WIDGET_CONTROL, w->w_pin.ctrl);
3514 1.2.2.2 skrll break;
3515 1.2.2.2 skrll case COP_DEVICE_LINE_OUT:
3516 1.2.2.2 skrll case COP_DEVICE_SPEAKER:
3517 1.2.2.2 skrll case COP_DEVICE_AUX:
3518 1.2.2.2 skrll if (res & COP_GET_PIN_SENSE_PRESENSE_DETECT)
3519 1.2.2.2 skrll w->w_pin.ctrl &= ~COP_PWC_OUT_ENABLE;
3520 1.2.2.2 skrll else
3521 1.2.2.2 skrll w->w_pin.ctrl |= COP_PWC_OUT_ENABLE;
3522 1.2.2.2 skrll hdaudio_command(sc->sc_codec, w->w_nid,
3523 1.2.2.2 skrll CORB_SET_PIN_WIDGET_CONTROL, w->w_pin.ctrl);
3524 1.2.2.2 skrll break;
3525 1.2.2.2 skrll default:
3526 1.2.2.2 skrll break;
3527 1.2.2.2 skrll }
3528 1.2.2.2 skrll }
3529 1.2.2.2 skrll }
3530 1.2.2.2 skrll
3531 1.2.2.2 skrll resched:
3532 1.2.2.2 skrll callout_schedule(&sc->sc_jack_callout, HDAUDIO_HP_SENSE_PERIOD);
3533 1.2.2.2 skrll }
3534 1.2.2.2 skrll
3535 1.2.2.2 skrll static void
3536 1.2.2.2 skrll hdafg_hp_switch_init(struct hdafg_softc *sc)
3537 1.2.2.2 skrll {
3538 1.2.2.2 skrll struct hdaudio_assoc *as = sc->sc_assocs;
3539 1.2.2.2 skrll struct hdaudio_widget *w;
3540 1.2.2.2 skrll bool enable = false;
3541 1.2.2.2 skrll int i, j;
3542 1.2.2.2 skrll
3543 1.2.2.2 skrll for (i = 0; i < sc->sc_nassocs; i++) {
3544 1.2.2.2 skrll if (as[i].as_hpredir < 0 && as[i].as_displaydev == false)
3545 1.2.2.2 skrll continue;
3546 1.2.2.2 skrll if (as[i].as_displaydev == false)
3547 1.2.2.2 skrll w = hdafg_widget_lookup(sc, as[i].as_pins[15]);
3548 1.2.2.2 skrll else {
3549 1.2.2.2 skrll w = NULL;
3550 1.2.2.2 skrll for (j = 0; j < HDAUDIO_MAXPINS; j++) {
3551 1.2.2.2 skrll if (as[i].as_pins[j] == 0)
3552 1.2.2.2 skrll continue;
3553 1.2.2.2 skrll w = hdafg_widget_lookup(sc, as[i].as_pins[j]);
3554 1.2.2.2 skrll if (w && w->w_enable &&
3555 1.2.2.2 skrll w->w_type == COP_AWCAP_TYPE_PIN_COMPLEX)
3556 1.2.2.2 skrll break;
3557 1.2.2.2 skrll w = NULL;
3558 1.2.2.2 skrll }
3559 1.2.2.2 skrll }
3560 1.2.2.2 skrll if (w == NULL || w->w_enable == false)
3561 1.2.2.2 skrll continue;
3562 1.2.2.2 skrll if (w->w_type != COP_AWCAP_TYPE_PIN_COMPLEX)
3563 1.2.2.2 skrll continue;
3564 1.2.2.2 skrll if (!(w->w_pin.cap & COP_PINCAP_PRESENSE_DETECT_CAPABLE)) {
3565 1.2.2.2 skrll continue;
3566 1.2.2.2 skrll }
3567 1.2.2.2 skrll if (COP_CFG_MISC(w->w_pin.config) & 1) {
3568 1.2.2.2 skrll hda_trace(sc, "no presence detect on pin %02X\n",
3569 1.2.2.2 skrll w->w_nid);
3570 1.2.2.2 skrll continue;
3571 1.2.2.2 skrll }
3572 1.2.2.2 skrll if ((w->w_pin.cap & (COP_PINCAP_HDMI|COP_PINCAP_DP)) == 0)
3573 1.2.2.2 skrll enable = true;
3574 1.2.2.2 skrll
3575 1.2.2.2 skrll if (w->w_p.aw_cap & COP_AWCAP_UNSOL_CAPABLE) {
3576 1.2.2.2 skrll uint8_t val = COP_SET_UNSOLICITED_RESPONSE_ENABLE;
3577 1.2.2.2 skrll if (w->w_pin.cap & (COP_PINCAP_HDMI|COP_PINCAP_DP))
3578 1.2.2.2 skrll val |= HDAUDIO_UNSOLTAG_EVENT_DD;
3579 1.2.2.2 skrll else
3580 1.2.2.2 skrll val |= HDAUDIO_UNSOLTAG_EVENT_HP;
3581 1.2.2.2 skrll
3582 1.2.2.2 skrll hdaudio_command(sc->sc_codec, w->w_nid,
3583 1.2.2.2 skrll CORB_SET_UNSOLICITED_RESPONSE, val);
3584 1.2.2.2 skrll
3585 1.2.2.2 skrll hdaudio_command(sc->sc_codec, w->w_nid,
3586 1.2.2.2 skrll CORB_SET_AMPLIFIER_GAIN_MUTE, 0xb000);
3587 1.2.2.2 skrll }
3588 1.2.2.2 skrll
3589 1.2.2.2 skrll hda_trace(sc, "presence detect [pin=%02X,%s",
3590 1.2.2.2 skrll w->w_nid,
3591 1.2.2.2 skrll (w->w_p.aw_cap & COP_AWCAP_UNSOL_CAPABLE) ?
3592 1.2.2.2 skrll "unsol" : "poll"
3593 1.2.2.2 skrll );
3594 1.2.2.2 skrll if (w->w_pin.cap & COP_PINCAP_HDMI)
3595 1.2.2.2 skrll hda_trace1(sc, ",hdmi");
3596 1.2.2.2 skrll if (w->w_pin.cap & COP_PINCAP_DP)
3597 1.2.2.2 skrll hda_trace1(sc, ",displayport");
3598 1.2.2.2 skrll hda_trace1(sc, "]\n");
3599 1.2.2.2 skrll }
3600 1.2.2.2 skrll if (enable) {
3601 1.2.2.2 skrll sc->sc_jack_polling = true;
3602 1.2.2.2 skrll hdafg_hp_switch_handler(sc);
3603 1.2.2.2 skrll } else
3604 1.2.2.2 skrll hda_trace(sc, "jack detect not enabled\n");
3605 1.2.2.2 skrll }
3606 1.2.2.2 skrll
3607 1.2.2.2 skrll static void
3608 1.2.2.2 skrll hdafg_attach(device_t parent, device_t self, void *opaque)
3609 1.2.2.2 skrll {
3610 1.2.2.2 skrll struct hdafg_softc *sc = device_private(self);
3611 1.2.2.2 skrll audio_params_t defparams;
3612 1.2.2.2 skrll prop_dictionary_t args = opaque;
3613 1.2.2.2 skrll char vendor[16], product[16];
3614 1.2.2.2 skrll uint64_t fgptr = 0;
3615 1.2.2.2 skrll uint32_t astype = 0;
3616 1.2.2.2 skrll uint8_t nid = 0;
3617 1.2.2.2 skrll int err, i;
3618 1.2.2.2 skrll bool rv;
3619 1.2.2.2 skrll
3620 1.2.2.2 skrll aprint_naive("\n");
3621 1.2.2.2 skrll sc->sc_dev = self;
3622 1.2.2.2 skrll
3623 1.2.2.2 skrll mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_NONE);
3624 1.2.2.2 skrll mutex_init(&sc->sc_intr_lock, MUTEX_DEFAULT, IPL_SCHED);
3625 1.2.2.2 skrll
3626 1.2.2.2 skrll callout_init(&sc->sc_jack_callout, 0);
3627 1.2.2.2 skrll callout_setfunc(&sc->sc_jack_callout,
3628 1.2.2.2 skrll hdafg_hp_switch_handler, sc);
3629 1.2.2.2 skrll
3630 1.2.2.2 skrll if (!pmf_device_register(self, hdafg_suspend, hdafg_resume))
3631 1.2.2.2 skrll aprint_error_dev(self, "couldn't establish power handler\n");
3632 1.2.2.2 skrll
3633 1.2.2.2 skrll sc->sc_config = prop_dictionary_get(args, "pin-config");
3634 1.2.2.2 skrll if (sc->sc_config && prop_object_type(sc->sc_config) != PROP_TYPE_ARRAY)
3635 1.2.2.2 skrll sc->sc_config = NULL;
3636 1.2.2.2 skrll
3637 1.2.2.2 skrll prop_dictionary_get_uint16(args, "vendor-id", &sc->sc_vendor);
3638 1.2.2.2 skrll prop_dictionary_get_uint16(args, "product-id", &sc->sc_product);
3639 1.2.2.2 skrll hdaudio_findvendor(vendor, sizeof(vendor), sc->sc_vendor);
3640 1.2.2.2 skrll hdaudio_findproduct(product, sizeof(product), sc->sc_vendor,
3641 1.2.2.2 skrll sc->sc_product);
3642 1.2.2.2 skrll hda_print1(sc, ": %s %s%s\n", vendor, product,
3643 1.2.2.2 skrll sc->sc_config ? " (custom configuration)" : "");
3644 1.2.2.2 skrll
3645 1.2.2.3 skrll switch (sc->sc_vendor) {
3646 1.2.2.3 skrll case HDAUDIO_VENDOR_NVIDIA:
3647 1.2.2.3 skrll switch (sc->sc_product) {
3648 1.2.2.3 skrll case HDAUDIO_PRODUCT_NVIDIA_TEGRA124_HDMI:
3649 1.2.2.3 skrll sc->sc_fixed_rate = 44100;
3650 1.2.2.3 skrll break;
3651 1.2.2.3 skrll }
3652 1.2.2.3 skrll break;
3653 1.2.2.3 skrll }
3654 1.2.2.3 skrll
3655 1.2.2.2 skrll rv = prop_dictionary_get_uint64(args, "function-group", &fgptr);
3656 1.2.2.2 skrll if (rv == false || fgptr == 0) {
3657 1.2.2.2 skrll hda_error(sc, "missing function-group property\n");
3658 1.2.2.2 skrll return;
3659 1.2.2.2 skrll }
3660 1.2.2.2 skrll rv = prop_dictionary_get_uint8(args, "node-id", &nid);
3661 1.2.2.2 skrll if (rv == false || nid == 0) {
3662 1.2.2.2 skrll hda_error(sc, "missing node-id property\n");
3663 1.2.2.2 skrll return;
3664 1.2.2.2 skrll }
3665 1.2.2.2 skrll
3666 1.2.2.2 skrll prop_dictionary_set_uint64(device_properties(self),
3667 1.2.2.2 skrll "codecinfo-callback",
3668 1.2.2.2 skrll (uint64_t)(uintptr_t)hdafg_codec_info);
3669 1.2.2.2 skrll prop_dictionary_set_uint64(device_properties(self),
3670 1.2.2.2 skrll "widgetinfo-callback",
3671 1.2.2.2 skrll (uint64_t)(uintptr_t)hdafg_widget_info);
3672 1.2.2.2 skrll
3673 1.2.2.2 skrll sc->sc_nid = nid;
3674 1.2.2.2 skrll sc->sc_fg = (struct hdaudio_function_group *)(vaddr_t)fgptr;
3675 1.2.2.2 skrll sc->sc_fg->fg_unsol = hdafg_unsol;
3676 1.2.2.2 skrll sc->sc_codec = sc->sc_fg->fg_codec;
3677 1.2.2.2 skrll KASSERT(sc->sc_codec != NULL);
3678 1.2.2.2 skrll sc->sc_host = sc->sc_codec->co_host;
3679 1.2.2.2 skrll KASSERT(sc->sc_host != NULL);
3680 1.2.2.2 skrll
3681 1.2.2.2 skrll hda_debug(sc, "parsing widgets\n");
3682 1.2.2.2 skrll hdafg_parse(sc);
3683 1.2.2.2 skrll hda_debug(sc, "parsing controls\n");
3684 1.2.2.2 skrll hdafg_control_parse(sc);
3685 1.2.2.2 skrll hda_debug(sc, "disabling non-audio devices\n");
3686 1.2.2.2 skrll hdafg_disable_nonaudio(sc);
3687 1.2.2.2 skrll hda_debug(sc, "disabling useless devices\n");
3688 1.2.2.2 skrll hdafg_disable_useless(sc);
3689 1.2.2.2 skrll hda_debug(sc, "parsing associations\n");
3690 1.2.2.2 skrll hdafg_assoc_parse(sc);
3691 1.2.2.2 skrll hda_debug(sc, "building tree\n");
3692 1.2.2.2 skrll hdafg_build_tree(sc);
3693 1.2.2.2 skrll hda_debug(sc, "disabling unassociated pins\n");
3694 1.2.2.2 skrll hdafg_disable_unassoc(sc);
3695 1.2.2.2 skrll hda_debug(sc, "disabling unselected pins\n");
3696 1.2.2.2 skrll hdafg_disable_unsel(sc);
3697 1.2.2.2 skrll hda_debug(sc, "disabling useless devices\n");
3698 1.2.2.2 skrll hdafg_disable_useless(sc);
3699 1.2.2.2 skrll hda_debug(sc, "disabling cross-associated pins\n");
3700 1.2.2.2 skrll hdafg_disable_crossassoc(sc);
3701 1.2.2.2 skrll hda_debug(sc, "disabling useless devices\n");
3702 1.2.2.2 skrll hdafg_disable_useless(sc);
3703 1.2.2.2 skrll
3704 1.2.2.2 skrll hda_debug(sc, "assigning mixer names to sound sources\n");
3705 1.2.2.2 skrll hdafg_assign_names(sc);
3706 1.2.2.2 skrll hda_debug(sc, "assigning mixers to device tree\n");
3707 1.2.2.2 skrll hdafg_assign_mixers(sc);
3708 1.2.2.2 skrll
3709 1.2.2.2 skrll hda_debug(sc, "preparing pin controls\n");
3710 1.2.2.2 skrll hdafg_prepare_pin_controls(sc);
3711 1.2.2.2 skrll hda_debug(sc, "commiting settings\n");
3712 1.2.2.2 skrll hdafg_commit(sc);
3713 1.2.2.2 skrll
3714 1.2.2.2 skrll hda_debug(sc, "setup jack sensing\n");
3715 1.2.2.2 skrll hdafg_hp_switch_init(sc);
3716 1.2.2.2 skrll
3717 1.2.2.2 skrll hda_debug(sc, "building mixer controls\n");
3718 1.2.2.2 skrll hdafg_build_mixers(sc);
3719 1.2.2.2 skrll
3720 1.2.2.2 skrll hdafg_dump(sc);
3721 1.2.2.2 skrll if (1) hdafg_widget_pin_dump(sc);
3722 1.2.2.2 skrll hdafg_assoc_dump(sc);
3723 1.2.2.2 skrll
3724 1.2.2.2 skrll hda_debug(sc, "enabling analog beep\n");
3725 1.2.2.2 skrll hdafg_enable_analog_beep(sc);
3726 1.2.2.2 skrll
3727 1.2.2.2 skrll hda_debug(sc, "configuring encodings\n");
3728 1.2.2.2 skrll sc->sc_audiodev.ad_sc = sc;
3729 1.2.2.2 skrll hdafg_configure_encodings(sc);
3730 1.2.2.2 skrll err = auconv_create_encodings(sc->sc_audiodev.ad_formats,
3731 1.2.2.2 skrll sc->sc_audiodev.ad_nformats, &sc->sc_audiodev.ad_encodings);
3732 1.2.2.2 skrll if (err) {
3733 1.2.2.2 skrll hda_error(sc, "couldn't create encodings\n");
3734 1.2.2.2 skrll return;
3735 1.2.2.2 skrll }
3736 1.2.2.2 skrll
3737 1.2.2.2 skrll hda_debug(sc, "reserving streams\n");
3738 1.2.2.2 skrll sc->sc_audiodev.ad_capture = hdaudio_stream_establish(sc->sc_host,
3739 1.2.2.2 skrll HDAUDIO_STREAM_ISS, hdafg_stream_intr, &sc->sc_audiodev);
3740 1.2.2.2 skrll sc->sc_audiodev.ad_playback = hdaudio_stream_establish(sc->sc_host,
3741 1.2.2.2 skrll HDAUDIO_STREAM_OSS, hdafg_stream_intr, &sc->sc_audiodev);
3742 1.2.2.2 skrll
3743 1.2.2.2 skrll hda_debug(sc, "connecting streams\n");
3744 1.2.2.2 skrll defparams.channels = 2;
3745 1.2.2.3 skrll defparams.sample_rate = sc->sc_fixed_rate ? sc->sc_fixed_rate : 48000;
3746 1.2.2.2 skrll defparams.precision = defparams.validbits = 16;
3747 1.2.2.2 skrll defparams.encoding = AUDIO_ENCODING_SLINEAR_LE;
3748 1.2.2.2 skrll sc->sc_pparam = sc->sc_rparam = defparams;
3749 1.2.2.2 skrll hdafg_stream_connect(sc, AUMODE_PLAY);
3750 1.2.2.2 skrll hdafg_stream_connect(sc, AUMODE_RECORD);
3751 1.2.2.2 skrll
3752 1.2.2.2 skrll for (i = 0; i < sc->sc_nassocs; i++) {
3753 1.2.2.2 skrll astype |= (1 << sc->sc_assocs[i].as_digital);
3754 1.2.2.2 skrll }
3755 1.2.2.2 skrll hda_debug(sc, "assoc type mask: %x\n", astype);
3756 1.2.2.2 skrll
3757 1.2.2.2 skrll #ifndef HDAUDIO_ENABLE_HDMI
3758 1.2.2.2 skrll astype &= ~(1 << HDAFG_AS_HDMI);
3759 1.2.2.2 skrll #endif
3760 1.2.2.2 skrll #ifndef HDAUDIO_ENABLE_DISPLAYPORT
3761 1.2.2.2 skrll astype &= ~(1 << HDAFG_AS_DISPLAYPORT);
3762 1.2.2.2 skrll #endif
3763 1.2.2.2 skrll
3764 1.2.2.2 skrll if (astype == 0)
3765 1.2.2.2 skrll return;
3766 1.2.2.2 skrll
3767 1.2.2.2 skrll hda_debug(sc, "attaching audio device\n");
3768 1.2.2.2 skrll sc->sc_audiodev.ad_audiodev = audio_attach_mi(&hdafg_hw_if,
3769 1.2.2.2 skrll &sc->sc_audiodev, self);
3770 1.2.2.2 skrll }
3771 1.2.2.2 skrll
3772 1.2.2.2 skrll static int
3773 1.2.2.2 skrll hdafg_detach(device_t self, int flags)
3774 1.2.2.2 skrll {
3775 1.2.2.2 skrll struct hdafg_softc *sc = device_private(self);
3776 1.2.2.2 skrll struct hdaudio_widget *wl, *w = sc->sc_widgets;
3777 1.2.2.2 skrll struct hdaudio_assoc *as = sc->sc_assocs;
3778 1.2.2.2 skrll struct hdaudio_control *ctl = sc->sc_ctls;
3779 1.2.2.2 skrll struct hdaudio_mixer *mx = sc->sc_mixers;
3780 1.2.2.2 skrll int nid;
3781 1.2.2.2 skrll
3782 1.2.2.2 skrll callout_halt(&sc->sc_jack_callout, NULL);
3783 1.2.2.2 skrll callout_destroy(&sc->sc_jack_callout);
3784 1.2.2.2 skrll
3785 1.2.2.2 skrll if (sc->sc_config)
3786 1.2.2.2 skrll prop_object_release(sc->sc_config);
3787 1.2.2.2 skrll if (sc->sc_audiodev.ad_audiodev)
3788 1.2.2.2 skrll config_detach(sc->sc_audiodev.ad_audiodev, flags);
3789 1.2.2.2 skrll if (sc->sc_audiodev.ad_encodings)
3790 1.2.2.2 skrll auconv_delete_encodings(sc->sc_audiodev.ad_encodings);
3791 1.2.2.2 skrll if (sc->sc_audiodev.ad_playback)
3792 1.2.2.2 skrll hdaudio_stream_disestablish(sc->sc_audiodev.ad_playback);
3793 1.2.2.2 skrll if (sc->sc_audiodev.ad_capture)
3794 1.2.2.2 skrll hdaudio_stream_disestablish(sc->sc_audiodev.ad_capture);
3795 1.2.2.2 skrll
3796 1.2.2.2 skrll /* restore bios pin widget configuration */
3797 1.2.2.2 skrll for (nid = sc->sc_startnode; nid < sc->sc_endnode; nid++) {
3798 1.2.2.3 skrll wl = hdafg_widget_lookup(sc, nid);
3799 1.2.2.2 skrll if (wl == NULL || wl->w_type != COP_AWCAP_TYPE_PIN_COMPLEX)
3800 1.2.2.2 skrll continue;
3801 1.2.2.2 skrll hdafg_widget_setconfig(wl, wl->w_pin.biosconfig);
3802 1.2.2.2 skrll }
3803 1.2.2.2 skrll
3804 1.2.2.2 skrll if (w)
3805 1.2.2.2 skrll kmem_free(w, sc->sc_nwidgets * sizeof(*w));
3806 1.2.2.2 skrll if (as)
3807 1.2.2.2 skrll kmem_free(as, sc->sc_nassocs * sizeof(*as));
3808 1.2.2.2 skrll if (ctl)
3809 1.2.2.2 skrll kmem_free(ctl, sc->sc_nctls * sizeof(*ctl));
3810 1.2.2.2 skrll if (mx)
3811 1.2.2.2 skrll kmem_free(mx, sc->sc_nmixers * sizeof(*mx));
3812 1.2.2.2 skrll
3813 1.2.2.2 skrll mutex_destroy(&sc->sc_lock);
3814 1.2.2.2 skrll mutex_destroy(&sc->sc_intr_lock);
3815 1.2.2.2 skrll
3816 1.2.2.2 skrll pmf_device_deregister(self);
3817 1.2.2.2 skrll
3818 1.2.2.2 skrll return 0;
3819 1.2.2.2 skrll }
3820 1.2.2.2 skrll
3821 1.2.2.2 skrll static void
3822 1.2.2.2 skrll hdafg_childdet(device_t self, device_t child)
3823 1.2.2.2 skrll {
3824 1.2.2.2 skrll struct hdafg_softc *sc = device_private(self);
3825 1.2.2.2 skrll
3826 1.2.2.2 skrll if (child == sc->sc_audiodev.ad_audiodev)
3827 1.2.2.2 skrll sc->sc_audiodev.ad_audiodev = NULL;
3828 1.2.2.2 skrll }
3829 1.2.2.2 skrll
3830 1.2.2.2 skrll static bool
3831 1.2.2.2 skrll hdafg_suspend(device_t self, const pmf_qual_t *qual)
3832 1.2.2.2 skrll {
3833 1.2.2.2 skrll struct hdafg_softc *sc = device_private(self);
3834 1.2.2.2 skrll
3835 1.2.2.2 skrll callout_halt(&sc->sc_jack_callout, NULL);
3836 1.2.2.2 skrll
3837 1.2.2.2 skrll return true;
3838 1.2.2.2 skrll }
3839 1.2.2.2 skrll
3840 1.2.2.2 skrll static bool
3841 1.2.2.2 skrll hdafg_resume(device_t self, const pmf_qual_t *qual)
3842 1.2.2.2 skrll {
3843 1.2.2.2 skrll struct hdafg_softc *sc = device_private(self);
3844 1.2.2.2 skrll struct hdaudio_widget *w;
3845 1.2.2.2 skrll int nid;
3846 1.2.2.2 skrll
3847 1.2.2.2 skrll hdaudio_command(sc->sc_codec, sc->sc_nid,
3848 1.2.2.2 skrll CORB_SET_POWER_STATE, COP_POWER_STATE_D0);
3849 1.2.2.2 skrll hda_delay(100);
3850 1.2.2.2 skrll for (nid = sc->sc_startnode; nid < sc->sc_endnode; nid++) {
3851 1.2.2.2 skrll hdaudio_command(sc->sc_codec, nid,
3852 1.2.2.2 skrll CORB_SET_POWER_STATE, COP_POWER_STATE_D0);
3853 1.2.2.3 skrll w = hdafg_widget_lookup(sc, nid);
3854 1.2.2.2 skrll
3855 1.2.2.2 skrll /* restore pin widget configuration */
3856 1.2.2.2 skrll if (w == NULL || w->w_type != COP_AWCAP_TYPE_PIN_COMPLEX)
3857 1.2.2.2 skrll continue;
3858 1.2.2.2 skrll hdafg_widget_setconfig(w, w->w_pin.config);
3859 1.2.2.2 skrll }
3860 1.2.2.2 skrll hda_delay(1000);
3861 1.2.2.2 skrll
3862 1.2.2.2 skrll hdafg_commit(sc);
3863 1.2.2.2 skrll hdafg_stream_connect(sc, AUMODE_PLAY);
3864 1.2.2.2 skrll hdafg_stream_connect(sc, AUMODE_RECORD);
3865 1.2.2.2 skrll
3866 1.2.2.2 skrll if (sc->sc_jack_polling)
3867 1.2.2.2 skrll hdafg_hp_switch_handler(sc);
3868 1.2.2.2 skrll
3869 1.2.2.2 skrll return true;
3870 1.2.2.2 skrll }
3871 1.2.2.2 skrll
3872 1.2.2.2 skrll static int
3873 1.2.2.2 skrll hdafg_query_encoding(void *opaque, struct audio_encoding *ae)
3874 1.2.2.2 skrll {
3875 1.2.2.2 skrll struct hdaudio_audiodev *ad = opaque;
3876 1.2.2.2 skrll return auconv_query_encoding(ad->ad_encodings, ae);
3877 1.2.2.2 skrll }
3878 1.2.2.2 skrll
3879 1.2.2.2 skrll static int
3880 1.2.2.2 skrll hdafg_set_params(void *opaque, int setmode, int usemode,
3881 1.2.2.2 skrll audio_params_t *play, audio_params_t *rec,
3882 1.2.2.2 skrll stream_filter_list_t *pfil, stream_filter_list_t *rfil)
3883 1.2.2.2 skrll {
3884 1.2.2.2 skrll struct hdaudio_audiodev *ad = opaque;
3885 1.2.2.2 skrll int index;
3886 1.2.2.2 skrll
3887 1.2.2.2 skrll if (play && (setmode & AUMODE_PLAY)) {
3888 1.2.2.2 skrll index = auconv_set_converter(ad->ad_formats, ad->ad_nformats,
3889 1.2.2.2 skrll AUMODE_PLAY, play, TRUE, pfil);
3890 1.2.2.2 skrll if (index < 0)
3891 1.2.2.2 skrll return EINVAL;
3892 1.2.2.3 skrll ad->ad_sc->sc_pparam = pfil->req_size > 0 ?
3893 1.2.2.3 skrll pfil->filters[0].param : *play;
3894 1.2.2.2 skrll hdafg_stream_connect(ad->ad_sc, AUMODE_PLAY);
3895 1.2.2.2 skrll }
3896 1.2.2.2 skrll if (rec && (setmode & AUMODE_RECORD)) {
3897 1.2.2.2 skrll index = auconv_set_converter(ad->ad_formats, ad->ad_nformats,
3898 1.2.2.2 skrll AUMODE_RECORD, rec, TRUE, rfil);
3899 1.2.2.2 skrll if (index < 0)
3900 1.2.2.2 skrll return EINVAL;
3901 1.2.2.3 skrll ad->ad_sc->sc_rparam = rfil->req_size > 0 ?
3902 1.2.2.3 skrll rfil->filters[0].param : *rec;
3903 1.2.2.2 skrll hdafg_stream_connect(ad->ad_sc, AUMODE_RECORD);
3904 1.2.2.2 skrll }
3905 1.2.2.2 skrll return 0;
3906 1.2.2.2 skrll }
3907 1.2.2.2 skrll
3908 1.2.2.2 skrll static int
3909 1.2.2.2 skrll hdafg_round_blocksize(void *opaque, int blksize, int mode,
3910 1.2.2.2 skrll const audio_params_t *param)
3911 1.2.2.2 skrll {
3912 1.2.2.2 skrll struct hdaudio_audiodev *ad = opaque;
3913 1.2.2.2 skrll struct hdaudio_stream *st;
3914 1.2.2.2 skrll int bufsize, nblksize;
3915 1.2.2.2 skrll
3916 1.2.2.2 skrll st = (mode == AUMODE_PLAY) ? ad->ad_playback : ad->ad_capture;
3917 1.2.2.2 skrll if (st == NULL) {
3918 1.2.2.2 skrll hda_trace(ad->ad_sc,
3919 1.2.2.2 skrll "round_blocksize called for invalid stream\n");
3920 1.2.2.2 skrll return 128;
3921 1.2.2.2 skrll }
3922 1.2.2.2 skrll
3923 1.2.2.2 skrll if (blksize > 8192)
3924 1.2.2.2 skrll blksize = 8192;
3925 1.2.2.2 skrll else if (blksize < 0)
3926 1.2.2.2 skrll blksize = 128;
3927 1.2.2.2 skrll
3928 1.2.2.2 skrll /* HD audio wants a multiple of 128, and OSS wants a power of 2 */
3929 1.2.2.2 skrll for (nblksize = 128; nblksize < blksize; nblksize <<= 1)
3930 1.2.2.2 skrll ;
3931 1.2.2.2 skrll
3932 1.2.2.2 skrll /* Make sure there are enough BDL descriptors */
3933 1.2.2.2 skrll bufsize = st->st_data.dma_size;
3934 1.2.2.2 skrll if (bufsize > HDAUDIO_BDL_MAX * nblksize) {
3935 1.2.2.2 skrll blksize = bufsize / HDAUDIO_BDL_MAX;
3936 1.2.2.2 skrll for (nblksize = 128; nblksize < blksize; nblksize <<= 1)
3937 1.2.2.2 skrll ;
3938 1.2.2.2 skrll }
3939 1.2.2.2 skrll
3940 1.2.2.2 skrll return nblksize;
3941 1.2.2.2 skrll }
3942 1.2.2.2 skrll
3943 1.2.2.2 skrll static int
3944 1.2.2.2 skrll hdafg_commit_settings(void *opaque)
3945 1.2.2.2 skrll {
3946 1.2.2.2 skrll return 0;
3947 1.2.2.2 skrll }
3948 1.2.2.2 skrll
3949 1.2.2.2 skrll static int
3950 1.2.2.2 skrll hdafg_halt_output(void *opaque)
3951 1.2.2.2 skrll {
3952 1.2.2.2 skrll struct hdaudio_audiodev *ad = opaque;
3953 1.2.2.2 skrll struct hdafg_softc *sc = ad->ad_sc;
3954 1.2.2.2 skrll struct hdaudio_assoc *as = ad->ad_sc->sc_assocs;
3955 1.2.2.2 skrll struct hdaudio_widget *w;
3956 1.2.2.2 skrll uint16_t dfmt;
3957 1.2.2.2 skrll int i, j;
3958 1.2.2.2 skrll
3959 1.2.2.2 skrll /* Disable digital outputs */
3960 1.2.2.2 skrll for (i = 0; i < sc->sc_nassocs; i++) {
3961 1.2.2.2 skrll if (as[i].as_enable == false)
3962 1.2.2.2 skrll continue;
3963 1.2.2.2 skrll if (as[i].as_dir != HDAUDIO_PINDIR_OUT)
3964 1.2.2.2 skrll continue;
3965 1.2.2.2 skrll for (j = 0; j < HDAUDIO_MAXPINS; j++) {
3966 1.2.2.2 skrll if (as[i].as_dacs[j] == 0)
3967 1.2.2.2 skrll continue;
3968 1.2.2.2 skrll w = hdafg_widget_lookup(sc, as[i].as_dacs[j]);
3969 1.2.2.2 skrll if (w == NULL || w->w_enable == false)
3970 1.2.2.2 skrll continue;
3971 1.2.2.2 skrll if (w->w_p.aw_cap & COP_AWCAP_DIGITAL) {
3972 1.2.2.2 skrll dfmt = hdaudio_command(sc->sc_codec, w->w_nid,
3973 1.2.2.2 skrll CORB_GET_DIGITAL_CONVERTER_CONTROL, 0) &
3974 1.2.2.2 skrll 0xff;
3975 1.2.2.2 skrll dfmt &= ~COP_DIGITAL_CONVCTRL1_DIGEN;
3976 1.2.2.2 skrll hdaudio_command(sc->sc_codec, w->w_nid,
3977 1.2.2.2 skrll CORB_SET_DIGITAL_CONVERTER_CONTROL_1, dfmt);
3978 1.2.2.2 skrll }
3979 1.2.2.2 skrll }
3980 1.2.2.2 skrll }
3981 1.2.2.2 skrll
3982 1.2.2.2 skrll hdaudio_stream_stop(ad->ad_playback);
3983 1.2.2.2 skrll
3984 1.2.2.2 skrll return 0;
3985 1.2.2.2 skrll }
3986 1.2.2.2 skrll
3987 1.2.2.2 skrll static int
3988 1.2.2.2 skrll hdafg_halt_input(void *opaque)
3989 1.2.2.2 skrll {
3990 1.2.2.2 skrll struct hdaudio_audiodev *ad = opaque;
3991 1.2.2.2 skrll
3992 1.2.2.2 skrll hdaudio_stream_stop(ad->ad_capture);
3993 1.2.2.2 skrll
3994 1.2.2.2 skrll return 0;
3995 1.2.2.2 skrll }
3996 1.2.2.2 skrll
3997 1.2.2.2 skrll static int
3998 1.2.2.2 skrll hdafg_getdev(void *opaque, struct audio_device *audiodev)
3999 1.2.2.2 skrll {
4000 1.2.2.2 skrll struct hdaudio_audiodev *ad = opaque;
4001 1.2.2.2 skrll struct hdafg_softc *sc = ad->ad_sc;
4002 1.2.2.2 skrll
4003 1.2.2.2 skrll hdaudio_findvendor(audiodev->name, sizeof(audiodev->name),
4004 1.2.2.2 skrll sc->sc_vendor);
4005 1.2.2.2 skrll hdaudio_findproduct(audiodev->version, sizeof(audiodev->version),
4006 1.2.2.2 skrll sc->sc_vendor, sc->sc_product);
4007 1.2.2.2 skrll snprintf(audiodev->config, sizeof(audiodev->config) - 1,
4008 1.2.2.2 skrll "%02Xh", sc->sc_nid);
4009 1.2.2.2 skrll
4010 1.2.2.2 skrll return 0;
4011 1.2.2.2 skrll }
4012 1.2.2.2 skrll
4013 1.2.2.2 skrll static int
4014 1.2.2.2 skrll hdafg_set_port(void *opaque, mixer_ctrl_t *mc)
4015 1.2.2.2 skrll {
4016 1.2.2.2 skrll struct hdaudio_audiodev *ad = opaque;
4017 1.2.2.2 skrll struct hdafg_softc *sc = ad->ad_sc;
4018 1.2.2.2 skrll struct hdaudio_mixer *mx;
4019 1.2.2.2 skrll struct hdaudio_control *ctl;
4020 1.2.2.2 skrll int i, divisor;
4021 1.2.2.2 skrll
4022 1.2.2.2 skrll if (mc->dev < 0 || mc->dev >= sc->sc_nmixers)
4023 1.2.2.2 skrll return EINVAL;
4024 1.2.2.2 skrll mx = &sc->sc_mixers[mc->dev];
4025 1.2.2.2 skrll ctl = mx->mx_ctl;
4026 1.2.2.2 skrll if (ctl == NULL) {
4027 1.2.2.2 skrll if (mx->mx_di.type != AUDIO_MIXER_SET)
4028 1.2.2.2 skrll return ENXIO;
4029 1.2.2.2 skrll if (mx->mx_di.mixer_class != HDAUDIO_MIXER_CLASS_OUTPUTS &&
4030 1.2.2.2 skrll mx->mx_di.mixer_class != HDAUDIO_MIXER_CLASS_RECORD)
4031 1.2.2.2 skrll return ENXIO;
4032 1.2.2.2 skrll for (i = 0; i < sc->sc_nassocs; i++) {
4033 1.2.2.2 skrll if (sc->sc_assocs[i].as_dir != HDAUDIO_PINDIR_OUT &&
4034 1.2.2.2 skrll mx->mx_di.mixer_class ==
4035 1.2.2.2 skrll HDAUDIO_MIXER_CLASS_OUTPUTS)
4036 1.2.2.2 skrll continue;
4037 1.2.2.2 skrll if (sc->sc_assocs[i].as_dir != HDAUDIO_PINDIR_IN &&
4038 1.2.2.2 skrll mx->mx_di.mixer_class ==
4039 1.2.2.2 skrll HDAUDIO_MIXER_CLASS_RECORD)
4040 1.2.2.2 skrll continue;
4041 1.2.2.2 skrll sc->sc_assocs[i].as_activated =
4042 1.2.2.2 skrll (mc->un.mask & (1 << i)) ? true : false;
4043 1.2.2.2 skrll }
4044 1.2.2.2 skrll hdafg_stream_connect(ad->ad_sc,
4045 1.2.2.2 skrll mx->mx_di.mixer_class == HDAUDIO_MIXER_CLASS_OUTPUTS ?
4046 1.2.2.2 skrll AUMODE_PLAY : AUMODE_RECORD);
4047 1.2.2.2 skrll return 0;
4048 1.2.2.2 skrll }
4049 1.2.2.2 skrll
4050 1.2.2.2 skrll switch (mx->mx_di.type) {
4051 1.2.2.2 skrll case AUDIO_MIXER_VALUE:
4052 1.2.2.2 skrll if (ctl->ctl_step == 0)
4053 1.2.2.2 skrll divisor = 128; /* ??? - just avoid div by 0 */
4054 1.2.2.2 skrll else
4055 1.2.2.2 skrll divisor = 255 / ctl->ctl_step;
4056 1.2.2.2 skrll
4057 1.2.2.2 skrll hdafg_control_amp_set(ctl, HDAUDIO_AMP_MUTE_NONE,
4058 1.2.2.2 skrll mc->un.value.level[AUDIO_MIXER_LEVEL_LEFT] / divisor,
4059 1.2.2.2 skrll mc->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] / divisor);
4060 1.2.2.2 skrll break;
4061 1.2.2.2 skrll case AUDIO_MIXER_ENUM:
4062 1.2.2.2 skrll hdafg_control_amp_set(ctl,
4063 1.2.2.2 skrll mc->un.ord ? HDAUDIO_AMP_MUTE_ALL : HDAUDIO_AMP_MUTE_NONE,
4064 1.2.2.2 skrll ctl->ctl_left, ctl->ctl_right);
4065 1.2.2.2 skrll break;
4066 1.2.2.2 skrll default:
4067 1.2.2.2 skrll return ENXIO;
4068 1.2.2.2 skrll }
4069 1.2.2.3 skrll
4070 1.2.2.2 skrll return 0;
4071 1.2.2.2 skrll }
4072 1.2.2.2 skrll
4073 1.2.2.2 skrll static int
4074 1.2.2.2 skrll hdafg_get_port(void *opaque, mixer_ctrl_t *mc)
4075 1.2.2.2 skrll {
4076 1.2.2.2 skrll struct hdaudio_audiodev *ad = opaque;
4077 1.2.2.2 skrll struct hdafg_softc *sc = ad->ad_sc;
4078 1.2.2.2 skrll struct hdaudio_mixer *mx;
4079 1.2.2.2 skrll struct hdaudio_control *ctl;
4080 1.2.2.2 skrll u_int mask = 0;
4081 1.2.2.2 skrll int i, factor;
4082 1.2.2.2 skrll
4083 1.2.2.2 skrll if (mc->dev < 0 || mc->dev >= sc->sc_nmixers)
4084 1.2.2.2 skrll return EINVAL;
4085 1.2.2.2 skrll mx = &sc->sc_mixers[mc->dev];
4086 1.2.2.2 skrll ctl = mx->mx_ctl;
4087 1.2.2.2 skrll if (ctl == NULL) {
4088 1.2.2.2 skrll if (mx->mx_di.type != AUDIO_MIXER_SET)
4089 1.2.2.2 skrll return ENXIO;
4090 1.2.2.2 skrll if (mx->mx_di.mixer_class != HDAUDIO_MIXER_CLASS_OUTPUTS &&
4091 1.2.2.2 skrll mx->mx_di.mixer_class != HDAUDIO_MIXER_CLASS_RECORD)
4092 1.2.2.2 skrll return ENXIO;
4093 1.2.2.2 skrll for (i = 0; i < sc->sc_nassocs; i++) {
4094 1.2.2.2 skrll if (sc->sc_assocs[i].as_enable == false)
4095 1.2.2.2 skrll continue;
4096 1.2.2.2 skrll if (sc->sc_assocs[i].as_activated == false)
4097 1.2.2.2 skrll continue;
4098 1.2.2.2 skrll if (sc->sc_assocs[i].as_dir == HDAUDIO_PINDIR_OUT &&
4099 1.2.2.2 skrll mx->mx_di.mixer_class ==
4100 1.2.2.2 skrll HDAUDIO_MIXER_CLASS_OUTPUTS)
4101 1.2.2.2 skrll mask |= (1 << i);
4102 1.2.2.2 skrll if (sc->sc_assocs[i].as_dir == HDAUDIO_PINDIR_IN &&
4103 1.2.2.2 skrll mx->mx_di.mixer_class ==
4104 1.2.2.2 skrll HDAUDIO_MIXER_CLASS_RECORD)
4105 1.2.2.2 skrll mask |= (1 << i);
4106 1.2.2.2 skrll }
4107 1.2.2.2 skrll mc->un.mask = mask;
4108 1.2.2.2 skrll return 0;
4109 1.2.2.2 skrll }
4110 1.2.2.2 skrll
4111 1.2.2.2 skrll switch (mx->mx_di.type) {
4112 1.2.2.2 skrll case AUDIO_MIXER_VALUE:
4113 1.2.2.2 skrll if (ctl->ctl_step == 0)
4114 1.2.2.2 skrll factor = 128; /* ??? - just avoid div by 0 */
4115 1.2.2.2 skrll else
4116 1.2.2.2 skrll factor = 255 / ctl->ctl_step;
4117 1.2.2.2 skrll
4118 1.2.2.2 skrll mc->un.value.level[AUDIO_MIXER_LEVEL_LEFT] = ctl->ctl_left * factor;
4119 1.2.2.2 skrll mc->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] = ctl->ctl_right * factor;
4120 1.2.2.2 skrll break;
4121 1.2.2.2 skrll case AUDIO_MIXER_ENUM:
4122 1.2.2.2 skrll mc->un.ord = (ctl->ctl_muted || ctl->ctl_forcemute) ? 1 : 0;
4123 1.2.2.2 skrll break;
4124 1.2.2.2 skrll default:
4125 1.2.2.2 skrll return ENXIO;
4126 1.2.2.2 skrll }
4127 1.2.2.2 skrll return 0;
4128 1.2.2.2 skrll }
4129 1.2.2.2 skrll
4130 1.2.2.2 skrll static int
4131 1.2.2.2 skrll hdafg_query_devinfo(void *opaque, mixer_devinfo_t *di)
4132 1.2.2.2 skrll {
4133 1.2.2.2 skrll struct hdaudio_audiodev *ad = opaque;
4134 1.2.2.2 skrll struct hdafg_softc *sc = ad->ad_sc;
4135 1.2.2.2 skrll
4136 1.2.2.2 skrll if (di->index < 0 || di->index >= sc->sc_nmixers)
4137 1.2.2.2 skrll return ENXIO;
4138 1.2.2.2 skrll
4139 1.2.2.2 skrll *di = sc->sc_mixers[di->index].mx_di;
4140 1.2.2.2 skrll
4141 1.2.2.2 skrll return 0;
4142 1.2.2.2 skrll }
4143 1.2.2.2 skrll
4144 1.2.2.2 skrll static void *
4145 1.2.2.2 skrll hdafg_allocm(void *opaque, int direction, size_t size)
4146 1.2.2.2 skrll {
4147 1.2.2.2 skrll struct hdaudio_audiodev *ad = opaque;
4148 1.2.2.2 skrll struct hdaudio_stream *st;
4149 1.2.2.2 skrll int err;
4150 1.2.2.2 skrll
4151 1.2.2.2 skrll st = (direction == AUMODE_PLAY) ? ad->ad_playback : ad->ad_capture;
4152 1.2.2.2 skrll if (st == NULL)
4153 1.2.2.2 skrll return NULL;
4154 1.2.2.2 skrll
4155 1.2.2.2 skrll if (st->st_data.dma_valid == true)
4156 1.2.2.2 skrll hda_error(ad->ad_sc, "WARNING: allocm leak\n");
4157 1.2.2.3 skrll
4158 1.2.2.2 skrll st->st_data.dma_size = size;
4159 1.2.2.2 skrll err = hdaudio_dma_alloc(st->st_host, &st->st_data,
4160 1.2.2.2 skrll BUS_DMA_COHERENT | BUS_DMA_NOCACHE);
4161 1.2.2.2 skrll if (err || st->st_data.dma_valid == false)
4162 1.2.2.2 skrll return NULL;
4163 1.2.2.2 skrll
4164 1.2.2.2 skrll return DMA_KERNADDR(&st->st_data);
4165 1.2.2.2 skrll }
4166 1.2.2.2 skrll
4167 1.2.2.2 skrll static void
4168 1.2.2.2 skrll hdafg_freem(void *opaque, void *addr, size_t size)
4169 1.2.2.2 skrll {
4170 1.2.2.2 skrll struct hdaudio_audiodev *ad = opaque;
4171 1.2.2.2 skrll struct hdaudio_stream *st;
4172 1.2.2.2 skrll
4173 1.2.2.2 skrll if (addr == DMA_KERNADDR(&ad->ad_playback->st_data))
4174 1.2.2.2 skrll st = ad->ad_playback;
4175 1.2.2.2 skrll else if (addr == DMA_KERNADDR(&ad->ad_capture->st_data))
4176 1.2.2.2 skrll st = ad->ad_capture;
4177 1.2.2.2 skrll else
4178 1.2.2.2 skrll return;
4179 1.2.2.2 skrll
4180 1.2.2.2 skrll hdaudio_dma_free(st->st_host, &st->st_data);
4181 1.2.2.2 skrll }
4182 1.2.2.2 skrll
4183 1.2.2.2 skrll static size_t
4184 1.2.2.2 skrll hdafg_round_buffersize(void *opaque, int direction, size_t bufsize)
4185 1.2.2.2 skrll {
4186 1.2.2.2 skrll /* Multiple of 128 */
4187 1.2.2.2 skrll bufsize &= ~127;
4188 1.2.2.2 skrll if (bufsize <= 0)
4189 1.2.2.2 skrll bufsize = 128;
4190 1.2.2.2 skrll return bufsize;
4191 1.2.2.2 skrll }
4192 1.2.2.2 skrll
4193 1.2.2.2 skrll static paddr_t
4194 1.2.2.2 skrll hdafg_mappage(void *opaque, void *addr, off_t off, int prot)
4195 1.2.2.2 skrll {
4196 1.2.2.2 skrll struct hdaudio_audiodev *ad = opaque;
4197 1.2.2.2 skrll struct hdaudio_stream *st;
4198 1.2.2.2 skrll
4199 1.2.2.2 skrll if (addr == DMA_KERNADDR(&ad->ad_playback->st_data))
4200 1.2.2.2 skrll st = ad->ad_playback;
4201 1.2.2.2 skrll else if (addr == DMA_KERNADDR(&ad->ad_capture->st_data))
4202 1.2.2.2 skrll st = ad->ad_capture;
4203 1.2.2.2 skrll else
4204 1.2.2.2 skrll return -1;
4205 1.2.2.2 skrll
4206 1.2.2.2 skrll if (st->st_data.dma_valid == false)
4207 1.2.2.2 skrll return -1;
4208 1.2.2.2 skrll
4209 1.2.2.2 skrll return bus_dmamem_mmap(st->st_host->sc_dmat, st->st_data.dma_segs,
4210 1.2.2.2 skrll st->st_data.dma_nsegs, off, prot, BUS_DMA_WAITOK);
4211 1.2.2.2 skrll }
4212 1.2.2.2 skrll
4213 1.2.2.2 skrll static int
4214 1.2.2.2 skrll hdafg_get_props(void *opaque)
4215 1.2.2.2 skrll {
4216 1.2.2.2 skrll struct hdaudio_audiodev *ad = opaque;
4217 1.2.2.2 skrll int props = AUDIO_PROP_MMAP;
4218 1.2.2.2 skrll
4219 1.2.2.2 skrll if (ad->ad_playback)
4220 1.2.2.2 skrll props |= AUDIO_PROP_PLAYBACK;
4221 1.2.2.2 skrll if (ad->ad_capture)
4222 1.2.2.2 skrll props |= AUDIO_PROP_CAPTURE;
4223 1.2.2.2 skrll if (ad->ad_playback && ad->ad_capture) {
4224 1.2.2.2 skrll props |= AUDIO_PROP_FULLDUPLEX;
4225 1.2.2.2 skrll props |= AUDIO_PROP_INDEPENDENT;
4226 1.2.2.2 skrll }
4227 1.2.2.2 skrll
4228 1.2.2.2 skrll return props;
4229 1.2.2.2 skrll }
4230 1.2.2.2 skrll
4231 1.2.2.2 skrll static int
4232 1.2.2.2 skrll hdafg_trigger_output(void *opaque, void *start, void *end, int blksize,
4233 1.2.2.2 skrll void (*intr)(void *), void *intrarg, const audio_params_t *param)
4234 1.2.2.2 skrll {
4235 1.2.2.2 skrll struct hdaudio_audiodev *ad = opaque;
4236 1.2.2.2 skrll bus_size_t dmasize;
4237 1.2.2.2 skrll
4238 1.2.2.2 skrll if (ad->ad_playback == NULL)
4239 1.2.2.2 skrll return ENXIO;
4240 1.2.2.2 skrll if (ad->ad_playback->st_data.dma_valid == false)
4241 1.2.2.2 skrll return ENOMEM;
4242 1.2.2.2 skrll
4243 1.2.2.2 skrll ad->ad_playbackintr = intr;
4244 1.2.2.2 skrll ad->ad_playbackintrarg = intrarg;
4245 1.2.2.2 skrll
4246 1.2.2.2 skrll dmasize = (char *)end - (char *)start;
4247 1.2.2.2 skrll hdafg_stream_connect(ad->ad_sc, AUMODE_PLAY);
4248 1.2.2.3 skrll hdaudio_stream_start(ad->ad_playback, blksize, dmasize,
4249 1.2.2.3 skrll &ad->ad_sc->sc_pparam);
4250 1.2.2.2 skrll
4251 1.2.2.2 skrll return 0;
4252 1.2.2.2 skrll }
4253 1.2.2.2 skrll
4254 1.2.2.2 skrll static int
4255 1.2.2.2 skrll hdafg_trigger_input(void *opaque, void *start, void *end, int blksize,
4256 1.2.2.2 skrll void (*intr)(void *), void *intrarg, const audio_params_t *param)
4257 1.2.2.2 skrll {
4258 1.2.2.2 skrll struct hdaudio_audiodev *ad = opaque;
4259 1.2.2.2 skrll bus_size_t dmasize;
4260 1.2.2.2 skrll
4261 1.2.2.2 skrll if (ad->ad_capture == NULL)
4262 1.2.2.2 skrll return ENXIO;
4263 1.2.2.2 skrll if (ad->ad_capture->st_data.dma_valid == false)
4264 1.2.2.2 skrll return ENOMEM;
4265 1.2.2.2 skrll
4266 1.2.2.2 skrll ad->ad_captureintr = intr;
4267 1.2.2.2 skrll ad->ad_captureintrarg = intrarg;
4268 1.2.2.2 skrll
4269 1.2.2.2 skrll dmasize = (char *)end - (char *)start;
4270 1.2.2.2 skrll hdafg_stream_connect(ad->ad_sc, AUMODE_RECORD);
4271 1.2.2.3 skrll hdaudio_stream_start(ad->ad_capture, blksize, dmasize,
4272 1.2.2.3 skrll &ad->ad_sc->sc_rparam);
4273 1.2.2.2 skrll
4274 1.2.2.2 skrll return 0;
4275 1.2.2.2 skrll }
4276 1.2.2.2 skrll
4277 1.2.2.2 skrll static void
4278 1.2.2.2 skrll hdafg_get_locks(void *opaque, kmutex_t **intr, kmutex_t **thread)
4279 1.2.2.2 skrll {
4280 1.2.2.2 skrll struct hdaudio_audiodev *ad = opaque;
4281 1.2.2.2 skrll
4282 1.2.2.2 skrll *intr = &ad->ad_sc->sc_intr_lock;
4283 1.2.2.2 skrll *thread = &ad->ad_sc->sc_lock;
4284 1.2.2.2 skrll }
4285 1.2.2.2 skrll
4286 1.2.2.2 skrll static int
4287 1.2.2.2 skrll hdafg_unsol(device_t self, uint8_t tag)
4288 1.2.2.2 skrll {
4289 1.2.2.2 skrll struct hdafg_softc *sc = device_private(self);
4290 1.2.2.2 skrll struct hdaudio_assoc *as = sc->sc_assocs;
4291 1.2.2.2 skrll int i, j;
4292 1.2.2.2 skrll
4293 1.2.2.2 skrll switch (tag) {
4294 1.2.2.2 skrll case HDAUDIO_UNSOLTAG_EVENT_DD:
4295 1.2.2.2 skrll hda_print(sc, "unsol: display device hotplug\n");
4296 1.2.2.2 skrll for (i = 0; i < sc->sc_nassocs; i++) {
4297 1.2.2.2 skrll if (as[i].as_displaydev == false)
4298 1.2.2.2 skrll continue;
4299 1.2.2.2 skrll for (j = 0; j < HDAUDIO_MAXPINS; j++) {
4300 1.2.2.2 skrll if (as[i].as_pins[j] == 0)
4301 1.2.2.2 skrll continue;
4302 1.2.2.2 skrll hdafg_assoc_dump_dd(sc, &as[i], j, 0);
4303 1.2.2.2 skrll }
4304 1.2.2.2 skrll }
4305 1.2.2.2 skrll break;
4306 1.2.2.2 skrll default:
4307 1.2.2.2 skrll hda_print(sc, "unsol: tag=%u\n", tag);
4308 1.2.2.2 skrll break;
4309 1.2.2.2 skrll }
4310 1.2.2.2 skrll
4311 1.2.2.2 skrll return 0;
4312 1.2.2.2 skrll }
4313 1.2.2.2 skrll
4314 1.2.2.2 skrll static int
4315 1.2.2.2 skrll hdafg_widget_info(void *opaque, prop_dictionary_t request,
4316 1.2.2.2 skrll prop_dictionary_t response)
4317 1.2.2.2 skrll {
4318 1.2.2.2 skrll struct hdafg_softc *sc = opaque;
4319 1.2.2.2 skrll struct hdaudio_widget *w;
4320 1.2.2.2 skrll prop_array_t connlist;
4321 1.2.2.2 skrll uint32_t config, wcap;
4322 1.2.2.2 skrll uint16_t index;
4323 1.2.2.2 skrll int nid;
4324 1.2.2.2 skrll int i;
4325 1.2.2.2 skrll
4326 1.2.2.2 skrll if (prop_dictionary_get_uint16(request, "index", &index) == false)
4327 1.2.2.2 skrll return EINVAL;
4328 1.2.2.2 skrll
4329 1.2.2.2 skrll nid = sc->sc_startnode + index;
4330 1.2.2.2 skrll if (nid >= sc->sc_endnode)
4331 1.2.2.2 skrll return EINVAL;
4332 1.2.2.2 skrll
4333 1.2.2.2 skrll w = hdafg_widget_lookup(sc, nid);
4334 1.2.2.2 skrll if (w == NULL)
4335 1.2.2.2 skrll return ENXIO;
4336 1.2.2.2 skrll wcap = hda_get_wparam(w, PIN_CAPABILITIES);
4337 1.2.2.2 skrll config = hdaudio_command(sc->sc_codec, w->w_nid,
4338 1.2.2.2 skrll CORB_GET_CONFIGURATION_DEFAULT, 0);
4339 1.2.2.2 skrll prop_dictionary_set_cstring_nocopy(response, "name", w->w_name);
4340 1.2.2.2 skrll prop_dictionary_set_bool(response, "enable", w->w_enable);
4341 1.2.2.2 skrll prop_dictionary_set_uint8(response, "nid", w->w_nid);
4342 1.2.2.2 skrll prop_dictionary_set_uint8(response, "type", w->w_type);
4343 1.2.2.2 skrll prop_dictionary_set_uint32(response, "config", config);
4344 1.2.2.2 skrll prop_dictionary_set_uint32(response, "cap", wcap);
4345 1.2.2.2 skrll if (w->w_nconns == 0)
4346 1.2.2.2 skrll return 0;
4347 1.2.2.2 skrll connlist = prop_array_create();
4348 1.2.2.2 skrll for (i = 0; i < w->w_nconns; i++) {
4349 1.2.2.2 skrll if (w->w_conns[i] == 0)
4350 1.2.2.2 skrll continue;
4351 1.2.2.2 skrll prop_array_add(connlist,
4352 1.2.2.2 skrll prop_number_create_unsigned_integer(w->w_conns[i]));
4353 1.2.2.2 skrll }
4354 1.2.2.2 skrll prop_dictionary_set(response, "connlist", connlist);
4355 1.2.2.2 skrll prop_object_release(connlist);
4356 1.2.2.2 skrll return 0;
4357 1.2.2.2 skrll }
4358 1.2.2.2 skrll
4359 1.2.2.2 skrll static int
4360 1.2.2.2 skrll hdafg_codec_info(void *opaque, prop_dictionary_t request,
4361 1.2.2.2 skrll prop_dictionary_t response)
4362 1.2.2.2 skrll {
4363 1.2.2.2 skrll struct hdafg_softc *sc = opaque;
4364 1.2.2.2 skrll prop_dictionary_set_uint16(response, "vendor-id",
4365 1.2.2.2 skrll sc->sc_vendor);
4366 1.2.2.2 skrll prop_dictionary_set_uint16(response, "product-id",
4367 1.2.2.2 skrll sc->sc_product);
4368 1.2.2.2 skrll return 0;
4369 1.2.2.2 skrll }
4370 1.2.2.2 skrll
4371 1.2.2.2 skrll MODULE(MODULE_CLASS_DRIVER, hdafg, "hdaudio");
4372 1.2.2.2 skrll
4373 1.2.2.2 skrll #ifdef _MODULE
4374 1.2.2.2 skrll #include "ioconf.c"
4375 1.2.2.2 skrll #endif
4376 1.2.2.2 skrll
4377 1.2.2.2 skrll static int
4378 1.2.2.2 skrll hdafg_modcmd(modcmd_t cmd, void *opaque)
4379 1.2.2.2 skrll {
4380 1.2.2.2 skrll int error = 0;
4381 1.2.2.2 skrll
4382 1.2.2.2 skrll switch (cmd) {
4383 1.2.2.2 skrll case MODULE_CMD_INIT:
4384 1.2.2.2 skrll #ifdef _MODULE
4385 1.2.2.2 skrll error = config_init_component(cfdriver_ioconf_hdafg,
4386 1.2.2.2 skrll cfattach_ioconf_hdafg, cfdata_ioconf_hdafg);
4387 1.2.2.2 skrll #endif
4388 1.2.2.2 skrll return error;
4389 1.2.2.2 skrll case MODULE_CMD_FINI:
4390 1.2.2.2 skrll #ifdef _MODULE
4391 1.2.2.2 skrll error = config_fini_component(cfdriver_ioconf_hdafg,
4392 1.2.2.2 skrll cfattach_ioconf_hdafg, cfdata_ioconf_hdafg);
4393 1.2.2.2 skrll #endif
4394 1.2.2.2 skrll return error;
4395 1.2.2.2 skrll default:
4396 1.2.2.2 skrll return ENOTTY;
4397 1.2.2.2 skrll }
4398 1.2.2.2 skrll }
4399 1.2.2.2 skrll
4400 1.2.2.2 skrll #define HDAFG_GET_ANACTRL 0xfe0
4401 1.2.2.2 skrll #define HDAFG_SET_ANACTRL 0x7e0
4402 1.2.2.2 skrll #define HDAFG_ANALOG_BEEP_EN __BIT(5)
4403 1.2.2.2 skrll #define HDAFG_ALC231_MONO_OUT_MIXER 0xf
4404 1.2.2.2 skrll #define HDAFG_STAC9200_AFG 0x1
4405 1.2.2.2 skrll #define HDAFG_STAC9200_GET_ANACTRL_PAYLOAD 0x0
4406 1.2.2.2 skrll #define HDAFG_ALC231_INPUT_BOTH_CHANNELS_UNMUTE 0x7100
4407 1.2.2.2 skrll
4408 1.2.2.2 skrll static void
4409 1.2.2.2 skrll hdafg_enable_analog_beep(struct hdafg_softc *sc)
4410 1.2.2.2 skrll {
4411 1.2.2.2 skrll int nid;
4412 1.2.2.2 skrll uint32_t response;
4413 1.2.2.3 skrll
4414 1.2.2.2 skrll switch (sc->sc_vendor) {
4415 1.2.2.2 skrll case HDAUDIO_VENDOR_SIGMATEL:
4416 1.2.2.2 skrll switch (sc->sc_product) {
4417 1.2.2.2 skrll case HDAUDIO_PRODUCT_SIGMATEL_STAC9200:
4418 1.2.2.2 skrll case HDAUDIO_PRODUCT_SIGMATEL_STAC9200D:
4419 1.2.2.2 skrll case HDAUDIO_PRODUCT_SIGMATEL_STAC9202:
4420 1.2.2.2 skrll case HDAUDIO_PRODUCT_SIGMATEL_STAC9202D:
4421 1.2.2.2 skrll case HDAUDIO_PRODUCT_SIGMATEL_STAC9204:
4422 1.2.2.2 skrll case HDAUDIO_PRODUCT_SIGMATEL_STAC9204D:
4423 1.2.2.2 skrll case HDAUDIO_PRODUCT_SIGMATEL_STAC9205:
4424 1.2.2.2 skrll case HDAUDIO_PRODUCT_SIGMATEL_STAC9205_1:
4425 1.2.2.2 skrll case HDAUDIO_PRODUCT_SIGMATEL_STAC9205D:
4426 1.2.2.2 skrll nid = HDAFG_STAC9200_AFG;
4427 1.2.2.2 skrll
4428 1.2.2.2 skrll response = hdaudio_command(sc->sc_codec, nid,
4429 1.2.2.2 skrll HDAFG_GET_ANACTRL,
4430 1.2.2.2 skrll HDAFG_STAC9200_GET_ANACTRL_PAYLOAD);
4431 1.2.2.2 skrll hda_delay(100);
4432 1.2.2.2 skrll
4433 1.2.2.2 skrll response |= HDAFG_ANALOG_BEEP_EN;
4434 1.2.2.2 skrll
4435 1.2.2.2 skrll hdaudio_command(sc->sc_codec, nid, HDAFG_SET_ANACTRL,
4436 1.2.2.2 skrll response);
4437 1.2.2.2 skrll hda_delay(100);
4438 1.2.2.2 skrll break;
4439 1.2.2.2 skrll default:
4440 1.2.2.2 skrll break;
4441 1.2.2.2 skrll }
4442 1.2.2.2 skrll break;
4443 1.2.2.2 skrll case HDAUDIO_VENDOR_REALTEK:
4444 1.2.2.2 skrll switch (sc->sc_product) {
4445 1.2.2.2 skrll case HDAUDIO_PRODUCT_REALTEK_ALC269:
4446 1.2.2.2 skrll /* The Panasonic Toughbook CF19 - Mk 5 uses a Realtek
4447 1.2.2.2 skrll * ALC231 that identifies as an ALC269.
4448 1.2.2.2 skrll * This unmutes the PCBEEP on the speaker.
4449 1.2.2.2 skrll */
4450 1.2.2.2 skrll nid = HDAFG_ALC231_MONO_OUT_MIXER;
4451 1.2.2.2 skrll response = hdaudio_command(sc->sc_codec, nid,
4452 1.2.2.2 skrll CORB_SET_AMPLIFIER_GAIN_MUTE,
4453 1.2.2.2 skrll HDAFG_ALC231_INPUT_BOTH_CHANNELS_UNMUTE);
4454 1.2.2.2 skrll hda_delay(100);
4455 1.2.2.2 skrll break;
4456 1.2.2.2 skrll default:
4457 1.2.2.2 skrll break;
4458 1.2.2.2 skrll }
4459 1.2.2.2 skrll default:
4460 1.2.2.2 skrll break;
4461 1.2.2.2 skrll }
4462 1.2.2.2 skrll }
4463