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