Home | History | Annotate | Line # | Download | only in hdaudio
      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