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