1 /* $NetBSD: hdaudio_afg.c,v 1.17 2009/10/11 08:50:11 sborrill Exp $ */
4 * Copyright (c) 2009 Precedence Technologies Ltd <support@precedence.co.uk>
5 * Copyright (c) 2009 Jared D. McNeill <jmcneill@invisible.ca>
8 * This code is derived from software contributed to The NetBSD Foundation
9 * by Precedence Technologies Ltd
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. The name of the author may not be used to endorse or promote products
17 * derived from this software without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
24 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
26 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * Widget parsing from FreeBSD hdac.c:
35 * Copyright (c) 2006 Stephane E. Potvin <sepotvin@videotron.ca>
36 * Copyright (c) 2006 Ariff Abdullah <ariff@FreeBSD.org>
37 * Copyright (c) 2008 Alexander Motin <mav@FreeBSD.org>
38 * All rights reserved.
40 * Redistribution and use in source and binary forms, with or without
41 * modification, are permitted provided that the following conditions
43 * 1. Redistributions of source code must retain the above copyright
44 * notice, this list of conditions and the following disclaimer.
45 * 2. Redistributions in binary form must reproduce the above copyright
46 * notice, this list of conditions and the following disclaimer in the
47 * documentation and/or other materials provided with the distribution.
49 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
50 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
51 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
52 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
53 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
54 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
55 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
56 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
57 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
58 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
62 #include <sys/cdefs.h>
63 __KERNEL_RCSID(0, "$NetBSD: hdaudio_afg.c,v 1.17 2009/10/11 08:50:11 sborrill Exp $");
65 #include <sys/types.h>
66 #include <sys/param.h>
67 #include <sys/systm.h>
68 #include <sys/kernel.h>
69 #include <sys/device.h>
74 #include <sys/audioio.h>
75 #include <dev/audio_if.h>
76 #include <dev/auconv.h>
78 #include <dev/pci/hdaudio/hdaudiovar.h>
79 #include <dev/pci/hdaudio/hdaudioreg.h>
80 #include <dev/pci/hdaudio/hdaudio_mixer.h>
81 #include <dev/pci/hdaudio/hdaudioio.h>
83 #ifndef AUFMT_SURROUND_7_1
84 #define AUFMT_SURROUND_7_1 (AUFMT_DOLBY_5_1|AUFMT_SIDE_LEFT|AUFMT_SIDE_RIGHT)
87 /* #define HDAUDIO_AFG_DEBUG 1 */
89 #if defined(HDAUDIO_AFG_DEBUG)
90 static int hdaudio_afg_debug
= HDAUDIO_AFG_DEBUG
;
92 static int hdaudio_afg_debug
= 0;
95 #define hda_debug(sc, ...) \
96 if (hdaudio_afg_debug) hda_print(sc, __VA_ARGS__)
98 #define HDAUDIO_MIXER_CLASS_OUTPUTS 0
99 #define HDAUDIO_MIXER_CLASS_INPUTS 1
100 #define HDAUDIO_MIXER_CLASS_RECORD 2
101 #define HDAUDIO_MIXER_CLASS_LAST HDAUDIO_MIXER_CLASS_RECORD
103 #define HDAUDIO_GPIO_MASK 0
104 #define HDAUDIO_GPIO_DIR 1
105 #define HDAUDIO_GPIO_DATA 2
107 #define HDAUDIO_UNSOLTAG_EVENT_HP 0x00
109 #define HDAUDIO_HP_SENSE_PERIOD hz
111 static const char *hdaudio_afg_mixer_names
[] = HDAUDIO_DEVICE_NAMES
;
113 static const char *hdaudio_afg_port_connectivity
[] = {
117 "Jack & Fixed Function"
119 static const char *hdaudio_afg_default_device
[] = {
127 "Modem Handset Side",
137 static const char *hdaudio_afg_color
[] = {
156 #define HDAUDIO_MAXFORMATS 24
157 #define HDAUDIO_MAXCONNECTIONS 32
158 #define HDAUDIO_MAXPINS 16
159 #define HDAUDIO_PARSE_MAXDEPTH 10
161 #define HDAUDIO_AMP_VOL_DEFAULT (-1)
162 #define HDAUDIO_AMP_MUTE_DEFAULT (0xffffffff)
163 #define HDAUDIO_AMP_MUTE_NONE 0
164 #define HDAUDIO_AMP_MUTE_LEFT (1 << 0)
165 #define HDAUDIO_AMP_MUTE_RIGHT (1 << 1)
166 #define HDAUDIO_AMP_MUTE_ALL (HDAUDIO_AMP_MUTE_LEFT | HDAUDIO_AMP_MUTE_RIGHT)
167 #define HDAUDIO_AMP_LEFT_MUTED(x) ((x) & HDAUDIO_AMP_MUTE_LEFT)
168 #define HDAUDIO_AMP_RIGHT_MUTED(x) (((x) & HDAUDIO_AMP_MUTE_RIGHT) >> 1)
170 #define HDAUDIO_ADC_MONITOR 1
172 enum hdaudio_pindir
{
173 HDAUDIO_PINDIR_NONE
= 0,
174 HDAUDIO_PINDIR_OUT
= 1,
175 HDAUDIO_PINDIR_IN
= 2,
176 HDAUDIO_PINDIR_INOUT
= 3,
179 #define hda_get_param(sc, cop) \
180 hdaudio_command((sc)->sc_codec, (sc)->sc_nid, \
181 CORB_GET_PARAMETER, COP_##cop)
182 #define hda_get_wparam(w, cop) \
183 hdaudio_command((w)->w_afg->sc_codec, (w)->w_nid, \
184 CORB_GET_PARAMETER, COP_##cop)
186 struct hdaudio_assoc
{
190 enum hdaudio_pindir as_dir
;
195 int as_pins
[HDAUDIO_MAXPINS
];
196 int as_dacs
[HDAUDIO_MAXPINS
];
199 struct hdaudio_widget
{
200 struct hdaudio_afg_softc
*w_afg
;
210 uint32_t w_audiomask
;
213 int w_conns
[HDAUDIO_MAXCONNECTIONS
];
214 bool w_connsenable
[HDAUDIO_MAXCONNECTIONS
];
219 uint32_t pcm_size_rate
;
220 uint32_t stream_format
;
232 struct hdaudio_control
{
233 struct hdaudio_widget
*ctl_widget
, *ctl_childwidget
;
236 enum hdaudio_pindir ctl_dir
, ctl_ndir
;
237 int ctl_mute
, ctl_step
, ctl_size
, ctl_offset
;
238 int ctl_left
, ctl_right
, ctl_forcemute
;
240 uint32_t ctl_audiomask
, ctl_paudiomask
;
243 #define HDAUDIO_CONTROL_GIVE(ctl) ((ctl)->ctl_step ? 1 : 0)
245 struct hdaudio_mixer
{
246 struct hdaudio_control
*mx_ctl
;
247 mixer_devinfo_t mx_di
;
250 struct hdaudio_audiodev
{
251 struct hdaudio_afg_softc
*ad_sc
;
252 device_t ad_audiodev
;
253 struct audio_encoding_set
*ad_encodings
;
255 struct audio_format ad_formats
[HDAUDIO_MAXFORMATS
];
257 struct hdaudio_stream
*ad_playback
;
258 void (*ad_playbackintr
)(void *);
259 void *ad_playbackintrarg
;
260 int ad_playbacknid
[HDAUDIO_MAXPINS
];
261 struct hdaudio_assoc
*ad_playbackassoc
;
262 struct hdaudio_stream
*ad_capture
;
263 void (*ad_captureintr
)(void *);
264 void *ad_captureintrarg
;
265 int ad_capturenid
[HDAUDIO_MAXPINS
];
266 struct hdaudio_assoc
*ad_captureassoc
;
269 struct hdaudio_afg_softc
{
271 struct hdaudio_softc
*sc_host
;
272 struct hdaudio_codec
*sc_codec
;
273 struct hdaudio_function_group
*sc_fg
;
275 uint16_t sc_vendor
, sc_product
;
277 prop_array_t sc_config
;
279 int sc_startnode
, sc_endnode
;
281 struct hdaudio_widget
*sc_widgets
;
283 struct hdaudio_assoc
*sc_assocs
;
285 struct hdaudio_control
*sc_ctls
;
287 struct hdaudio_mixer
*sc_mixers
;
289 int sc_pchan
, sc_rchan
;
290 audio_params_t sc_pparam
, sc_rparam
;
292 struct callout sc_jack_callout
;
293 bool sc_jack_polling
;
297 uint32_t pcm_size_rate
;
298 uint32_t stream_format
;
301 uint32_t power_states
;
305 struct hdaudio_audiodev sc_audiodev
;
308 static int hdaudio_afg_match(device_t
, cfdata_t
, void *);
309 static void hdaudio_afg_attach(device_t
, device_t
, void *);
310 static int hdaudio_afg_detach(device_t
, int);
311 static void hdaudio_afg_childdet(device_t
, device_t
);
312 static bool hdaudio_afg_suspend(device_t
, pmf_qual_t
);
313 static bool hdaudio_afg_resume(device_t
, pmf_qual_t
);
317 sizeof(struct hdaudio_afg_softc
),
326 static const struct audio_device hdaudio_afg_audio_device
= {
332 static int hdaudio_afg_query_encoding(void *, struct audio_encoding
*);
333 static int hdaudio_afg_set_params(void *, int, int,
336 stream_filter_list_t
*,
337 stream_filter_list_t
*);
338 static int hdaudio_afg_round_blocksize(void *, int, int,
339 const audio_params_t
*);
340 static int hdaudio_afg_commit_settings(void *);
341 static int hdaudio_afg_halt_output(void *);
342 static int hdaudio_afg_halt_input(void *);
343 static int hdaudio_afg_set_port(void *, mixer_ctrl_t
*);
344 static int hdaudio_afg_get_port(void *, mixer_ctrl_t
*);
345 static int hdaudio_afg_query_devinfo(void *, mixer_devinfo_t
*);
346 static void * hdaudio_afg_allocm(void *, int, size_t, struct malloc_type
*, int);
347 static void hdaudio_afg_freem(void *, void *, struct malloc_type
*);
348 static int hdaudio_afg_getdev(void *, struct audio_device
*);
349 static size_t hdaudio_afg_round_buffersize(void *, int, size_t);
350 static paddr_t
hdaudio_afg_mappage(void *, void *, off_t
, int);
351 static int hdaudio_afg_get_props(void *);
352 static int hdaudio_afg_trigger_output(void *, void *, void *, int,
353 void (*)(void *), void *,
354 const audio_params_t
*);
355 static int hdaudio_afg_trigger_input(void *, void *, void *, int,
356 void (*)(void *), void *,
357 const audio_params_t
*);
358 static int hdaudio_afg_dev_ioctl(void *, u_long
, void *, int, lwp_t
*);
360 static const struct audio_hw_if hdaudio_afg_hw_if
= {
361 .query_encoding
= hdaudio_afg_query_encoding
,
362 .set_params
= hdaudio_afg_set_params
,
363 .round_blocksize
= hdaudio_afg_round_blocksize
,
364 .commit_settings
= hdaudio_afg_commit_settings
,
365 .halt_output
= hdaudio_afg_halt_output
,
366 .halt_input
= hdaudio_afg_halt_input
,
367 .getdev
= hdaudio_afg_getdev
,
368 .set_port
= hdaudio_afg_set_port
,
369 .get_port
= hdaudio_afg_get_port
,
370 .query_devinfo
= hdaudio_afg_query_devinfo
,
371 .allocm
= hdaudio_afg_allocm
,
372 .freem
= hdaudio_afg_freem
,
373 .round_buffersize
= hdaudio_afg_round_buffersize
,
374 .mappage
= hdaudio_afg_mappage
,
375 .get_props
= hdaudio_afg_get_props
,
376 .trigger_output
= hdaudio_afg_trigger_output
,
377 .trigger_input
= hdaudio_afg_trigger_input
,
378 .dev_ioctl
= hdaudio_afg_dev_ioctl
382 hdaudio_afg_append_formats(struct hdaudio_audiodev
*ad
,
383 const struct audio_format
*format
)
385 if (ad
->ad_nformats
+ 1 >= HDAUDIO_MAXFORMATS
) {
386 hda_print1(ad
->ad_sc
, "[ENOMEM] ");
389 ad
->ad_formats
[ad
->ad_nformats
++] = *format
;
394 static struct hdaudio_widget
*
395 hdaudio_afg_widget_lookup(struct hdaudio_afg_softc
*sc
, int nid
)
397 if (sc
->sc_widgets
== NULL
|| sc
->sc_nwidgets
== 0) {
398 hda_error(sc
, "lookup failed; widgets %p nwidgets %d\n",
399 sc
->sc_widgets
, sc
->sc_nwidgets
);
402 if (nid
< sc
->sc_startnode
|| nid
>= sc
->sc_endnode
) {
403 hda_debug(sc
, "nid %02X out of range (%02X-%02X)\n",
404 nid
, sc
->sc_startnode
, sc
->sc_endnode
);
407 return &sc
->sc_widgets
[nid
- sc
->sc_startnode
];
410 static struct hdaudio_control
*
411 hdaudio_afg_control_lookup(struct hdaudio_afg_softc
*sc
, int nid
,
412 enum hdaudio_pindir dir
, int index
, int cnt
)
414 struct hdaudio_control
*ctl
;
417 if (sc
->sc_ctls
== NULL
)
419 for (i
= 0; i
< sc
->sc_nctls
; i
++) {
420 ctl
= &sc
->sc_ctls
[i
];
421 if (ctl
->ctl_enable
== false)
423 if (ctl
->ctl_widget
->w_nid
!= nid
)
425 if (dir
&& ctl
->ctl_ndir
!= dir
)
427 if (index
>= 0 && ctl
->ctl_ndir
== HDAUDIO_PINDIR_IN
&&
428 ctl
->ctl_dir
== ctl
->ctl_ndir
&& ctl
->ctl_index
!= index
)
431 if (found
== cnt
|| cnt
<= 0)
439 hdaudio_afg_widget_connection_parse(struct hdaudio_widget
*w
)
441 struct hdaudio_afg_softc
*sc
= w
->w_afg
;
443 int i
, j
, maxconns
, ents
, entnum
;
444 int cnid
, addcnid
, prevcnid
;
448 res
= hda_get_wparam(w
, CONNECTION_LIST_LENGTH
);
449 ents
= COP_CONNECTION_LIST_LENGTH_LEN(res
);
452 if (res
& COP_CONNECTION_LIST_LENGTH_LONG_FORM
)
456 maxconns
= (sizeof(w
->w_conns
) / sizeof(w
->w_conns
[0])) - 1;
459 #define CONN_RMASK(e) (1 << ((32 / (e)) - 1))
460 #define CONN_NMASK(e) (CONN_RMASK(e) - 1)
461 #define CONN_RESVAL(r, e, n) ((r) >> ((32 / (e)) * (n)))
462 #define CONN_RANGE(r, e, n) (CONN_RESVAL(r, e, n) & CONN_RMASK(e))
463 #define CONN_CNID(r, e, n) (CONN_RESVAL(r, e, n) & CONN_NMASK(e))
465 for (i
= 0; i
< ents
; i
+= entnum
) {
466 res
= hdaudio_command(sc
->sc_codec
, w
->w_nid
,
467 CORB_GET_CONNECTION_LIST_ENTRY
, i
);
468 for (j
= 0; j
< entnum
; j
++) {
469 cnid
= CONN_CNID(res
, entnum
, j
);
471 if (w
->w_nconns
< ents
) {
472 hda_error(sc
, "WARNING: zero cnid\n");
477 if (cnid
< sc
->sc_startnode
|| cnid
>= sc
->sc_endnode
)
478 hda_debug(sc
, "ghost nid=%02X\n", cnid
);
479 if (CONN_RANGE(res
, entnum
, j
) == 0)
481 else if (prevcnid
== 0 || prevcnid
>= cnid
) {
482 hda_error(sc
, "invalid child range\n");
485 addcnid
= prevcnid
+ 1;
486 while (addcnid
<= cnid
) {
487 if (w
->w_nconns
> maxconns
) {
489 "max connections reached\n");
492 w
->w_connsenable
[w
->w_nconns
] = true;
493 w
->w_conns
[w
->w_nconns
++] = addcnid
++;
494 hda_trace(sc
, "add connection %02X->%02X\n",
495 w
->w_nid
, addcnid
- 1);
511 hdaudio_afg_widget_pin_dump(struct hdaudio_afg_softc
*sc
)
513 struct hdaudio_widget
*w
;
514 int i
, conn
, color
, defdev
;
516 for (i
= sc
->sc_startnode
; i
< sc
->sc_endnode
; i
++) {
517 w
= hdaudio_afg_widget_lookup(sc
, i
);
518 if (w
== NULL
|| w
->w_enable
== false)
520 if (w
->w_type
!= COP_AWCAP_TYPE_PIN_COMPLEX
)
522 conn
= COP_CFG_PORT_CONNECTIVITY(w
->w_pin
.config
);
523 color
= COP_CFG_COLOR(w
->w_pin
.config
);
524 defdev
= COP_CFG_DEFAULT_DEVICE(w
->w_pin
.config
);
526 hda_print(sc
, "io %02X: %s (%s, %s)\n",
528 hdaudio_afg_default_device
[defdev
],
529 hdaudio_afg_color
[color
],
530 hdaudio_afg_port_connectivity
[conn
]);
536 hdaudio_afg_widget_getconfig(struct hdaudio_widget
*w
)
538 struct hdaudio_afg_softc
*sc
= w
->w_afg
;
540 prop_object_iterator_t iter
;
541 prop_dictionary_t dict
;
545 if (sc
->sc_config
== NULL
)
548 iter
= prop_array_iterator(sc
->sc_config
);
551 prop_object_iterator_reset(iter
);
552 while ((obj
= prop_object_iterator_next(iter
)) != NULL
) {
553 if (prop_object_type(obj
) != PROP_TYPE_DICTIONARY
)
555 dict
= (prop_dictionary_t
)obj
;
556 if (!prop_dictionary_get_int16(dict
, "nid", &nid
) ||
557 !prop_dictionary_get_uint32(dict
, "config", &config
))
564 return hdaudio_command(sc
->sc_codec
, w
->w_nid
,
565 CORB_GET_CONFIGURATION_DEFAULT
, 0);
569 hdaudio_afg_widget_pin_parse(struct hdaudio_widget
*w
)
571 struct hdaudio_afg_softc
*sc
= w
->w_afg
;
573 int conn
, color
, defdev
;
576 w
->w_pin
.cap
= hda_get_wparam(w
, PIN_CAPABILITIES
);
577 w
->w_pin
.config
= hdaudio_afg_widget_getconfig(w
);
578 w
->w_pin
.ctrl
= hdaudio_command(sc
->sc_codec
, w
->w_nid
,
579 CORB_GET_PIN_WIDGET_CONTROL
, 0);
581 /* treat line-out as speaker, unless connection type is RCA */
582 if (COP_CFG_DEFAULT_DEVICE(w
->w_pin
.config
) == COP_DEVICE_LINE_OUT
&&
583 COP_CFG_CONNECTION_TYPE(w
->w_pin
.config
) != COP_CONN_TYPE_RCA
) {
584 w
->w_pin
.config
&= ~COP_DEVICE_MASK
;
585 w
->w_pin
.config
|= (COP_DEVICE_SPEAKER
<< COP_DEVICE_SHIFT
);
588 if (w
->w_pin
.cap
& COP_PINCAP_EAPD_CAPABLE
) {
589 w
->w_p
.eapdbtl
= hdaudio_command(sc
->sc_codec
, w
->w_nid
,
590 CORB_GET_EAPD_BTL_ENABLE
, 0);
591 w
->w_p
.eapdbtl
&= 0x7;
592 w
->w_p
.eapdbtl
|= COP_EAPD_ENABLE_EAPD
;
594 w
->w_p
.eapdbtl
= 0xffffffff;
598 if (COP_CFG_DEFAULT_DEVICE(w
->w_pin
.config
) == COP_DEVICE_SPEAKER
&&
599 COP_CFG_DEFAULT_ASSOCIATION(w
->w_pin
.config
) == 15) {
600 hda_trace(sc
, "forcing speaker nid %02X to assoc=14\n",
603 w
->w_pin
.config
&= ~0xf0;
604 w
->w_pin
.config
|= 0xe0;
606 if (COP_CFG_DEFAULT_DEVICE(w
->w_pin
.config
) == COP_DEVICE_HP_OUT
&&
607 COP_CFG_PORT_CONNECTIVITY(w
->w_pin
.config
) == COP_PORT_NONE
) {
608 hda_trace(sc
, "forcing hp out nid %02X to assoc=14\n",
610 /* set connectivity to 'jack' */
611 w
->w_pin
.config
&= ~(COP_PORT_BOTH
<< 30);
612 w
->w_pin
.config
|= (COP_PORT_JACK
<< 30);
614 w
->w_pin
.config
&= ~0xf;
615 w
->w_pin
.config
|= 15;
617 w
->w_pin
.config
&= ~0xf0;
618 w
->w_pin
.config
|= 0xe0;
623 conn
= COP_CFG_PORT_CONNECTIVITY(w
->w_pin
.config
);
624 color
= COP_CFG_COLOR(w
->w_pin
.config
);
625 defdev
= COP_CFG_DEFAULT_DEVICE(w
->w_pin
.config
);
627 /* TODO: set w->w_name */
630 sprintf(w
->w_name
, "%02Xh", w
->w_nid
);
635 hdaudio_afg_widget_getcaps(struct hdaudio_widget
*w
)
637 uint32_t wcap
, config
;
639 wcap
= hda_get_wparam(w
, AUDIO_WIDGET_CAPABILITIES
);
640 config
= hdaudio_afg_widget_getconfig(w
);
644 if (COP_CFG_DEFAULT_DEVICE(config
) == COP_DEVICE_SPEAKER
&&
645 (wcap
& (COP_AWCAP_INAMP_PRESENT
|COP_AWCAP_OUTAMP_PRESENT
)) == 0) {
646 wcap
&= ~COP_AWCAP_TYPE_MASK
;
647 wcap
|= (COP_AWCAP_TYPE_BEEP_GENERATOR
<< COP_AWCAP_TYPE_SHIFT
);
655 hdaudio_afg_widget_parse(struct hdaudio_widget
*w
)
657 struct hdaudio_afg_softc
*sc
= w
->w_afg
;
659 w
->w_p
.aw_cap
= hdaudio_afg_widget_getcaps(w
);
660 w
->w_type
= COP_AWCAP_TYPE(w
->w_p
.aw_cap
);
662 hdaudio_afg_widget_connection_parse(w
);
664 if (w
->w_p
.aw_cap
& COP_AWCAP_INAMP_PRESENT
) {
665 if (w
->w_p
.aw_cap
& COP_AWCAP_AMP_PARAM_OVERRIDE
)
666 w
->w_p
.inamp_cap
= hda_get_wparam(w
,
667 AMPLIFIER_CAPABILITIES_INAMP
);
669 w
->w_p
.inamp_cap
= sc
->sc_p
.inamp_cap
;
671 if (w
->w_p
.aw_cap
& COP_AWCAP_OUTAMP_PRESENT
) {
672 if (w
->w_p
.aw_cap
& COP_AWCAP_AMP_PARAM_OVERRIDE
)
673 w
->w_p
.outamp_cap
= hda_get_wparam(w
,
674 AMPLIFIER_CAPABILITIES_OUTAMP
);
676 w
->w_p
.outamp_cap
= sc
->sc_p
.outamp_cap
;
679 w
->w_p
.stream_format
= 0;
680 w
->w_p
.pcm_size_rate
= 0;
682 case COP_AWCAP_TYPE_AUDIO_OUTPUT
:
683 case COP_AWCAP_TYPE_AUDIO_INPUT
:
684 if (w
->w_p
.aw_cap
& COP_AWCAP_FORMAT_OVERRIDE
) {
685 w
->w_p
.stream_format
= hda_get_wparam(w
,
686 SUPPORTED_STREAM_FORMATS
);
687 w
->w_p
.pcm_size_rate
= hda_get_wparam(w
,
688 SUPPORTED_PCM_SIZE_RATES
);
690 w
->w_p
.stream_format
= sc
->sc_p
.stream_format
;
691 w
->w_p
.pcm_size_rate
= sc
->sc_p
.pcm_size_rate
;
694 case COP_AWCAP_TYPE_PIN_COMPLEX
:
695 hdaudio_afg_widget_pin_parse(w
);
701 hdaudio_afg_assoc_dump(struct hdaudio_afg_softc
*sc
)
703 struct hdaudio_assoc
*as
= sc
->sc_assocs
;
704 struct hdaudio_widget
*w
;
705 uint32_t conn
, color
, defdev
;
706 int maxassocs
= sc
->sc_nassocs
;
709 for (i
= 0; i
< maxassocs
; i
++) {
712 if (as
[i
].as_enable
== false)
715 for (j
= 0; j
< HDAUDIO_MAXPINS
; j
++) {
716 if (as
[i
].as_dacs
[j
] == 0)
719 hda_print(sc
, "%s%d:%02X, %s ",
720 as
[i
].as_dir
== HDAUDIO_PINDIR_IN
? "ADC" : "DAC",
722 as
[i
].as_digital
? "Digital" : "Analog");
724 w
= hdaudio_afg_widget_lookup(sc
, as
[i
].as_pins
[j
]);
726 hda_print1(sc
, "<none>\n");
729 conn
= COP_CFG_PORT_CONNECTIVITY(w
->w_pin
.config
);
730 color
= COP_CFG_COLOR(w
->w_pin
.config
);
731 defdev
= COP_CFG_DEFAULT_DEVICE(w
->w_pin
.config
);
733 hda_print1(sc
, "%s: %s (%s, %02X)\n",
734 hdaudio_afg_default_device
[defdev
],
735 hdaudio_afg_port_connectivity
[conn
],
736 hdaudio_afg_color
[color
], w
->w_nid
);
738 hda_print1(sc
, "<unknown>\n");
742 hda_print1(sc
, "<none>\n");
747 hdaudio_afg_assoc_parse(struct hdaudio_afg_softc
*sc
)
749 struct hdaudio_assoc
*as
;
750 struct hdaudio_widget
*w
;
751 int i
, j
, cnt
, maxassocs
, type
, assoc
, seq
, first
, hpredir
;
752 enum hdaudio_pindir dir
;
754 hda_debug(sc
, " count present associations\n");
755 /* Count present associations */
757 for (j
= 1; j
< HDAUDIO_MAXPINS
; j
++) {
758 for (i
= sc
->sc_startnode
; i
< sc
->sc_endnode
; i
++) {
759 w
= hdaudio_afg_widget_lookup(sc
, i
);
760 if (w
== NULL
|| w
->w_enable
== false)
762 if (w
->w_type
!= COP_AWCAP_TYPE_PIN_COMPLEX
)
764 if (COP_CFG_DEFAULT_ASSOCIATION(w
->w_pin
.config
) != j
)
767 if (j
!= 15) /* There could be many 1-pin assocs #15 */
772 hda_debug(sc
, " maxassocs %d\n", maxassocs
);
773 sc
->sc_nassocs
= maxassocs
;
778 hda_debug(sc
, " allocating memory\n");
779 as
= kmem_zalloc(maxassocs
* sizeof(*as
), KM_SLEEP
);
780 for (i
= 0; i
< maxassocs
; i
++) {
781 as
[i
].as_hpredir
= -1;
782 /* as[i].as_chan = NULL; */
783 as
[i
].as_digital
= true;
786 hda_debug(sc
, " scan associations, skipping as=0\n");
787 /* Scan associations skipping as=0 */
789 for (j
= 1; j
< HDAUDIO_MAXPINS
&& cnt
< maxassocs
; j
++) {
792 for (i
= sc
->sc_startnode
; i
< sc
->sc_endnode
; i
++) {
793 w
= hdaudio_afg_widget_lookup(sc
, i
);
794 if (w
== NULL
|| w
->w_enable
== false)
796 if (w
->w_type
!= COP_AWCAP_TYPE_PIN_COMPLEX
)
798 assoc
= COP_CFG_DEFAULT_ASSOCIATION(w
->w_pin
.config
);
799 seq
= COP_CFG_SEQUENCE(w
->w_pin
.config
);
802 KASSERT(cnt
< maxassocs
);
803 type
= COP_CFG_DEFAULT_DEVICE(w
->w_pin
.config
);
804 /* Get pin direction */
806 case COP_DEVICE_LINE_OUT
:
807 case COP_DEVICE_SPEAKER
:
808 case COP_DEVICE_HP_OUT
:
809 case COP_DEVICE_SPDIF_OUT
:
810 case COP_DEVICE_DIGITAL_OTHER_OUT
:
811 dir
= HDAUDIO_PINDIR_OUT
;
814 dir
= HDAUDIO_PINDIR_IN
;
817 /* If this is a first pin, create new association */
818 if (as
[cnt
].as_pincnt
== 0) {
819 as
[cnt
].as_enable
= true;
820 as
[cnt
].as_activated
= true;
821 as
[cnt
].as_index
= j
;
822 as
[cnt
].as_dir
= dir
;
826 /* Check association correctness */
827 if (as
[cnt
].as_pins
[seq
] != 0) {
828 hda_error(sc
, "duplicate pin in association\n");
829 as
[cnt
].as_enable
= false;
831 if (dir
!= as
[cnt
].as_dir
) {
833 "pin %02X has wrong direction for %02X\n",
835 as
[cnt
].as_enable
= false;
837 if ((w
->w_p
.aw_cap
& COP_AWCAP_DIGITAL
) == 0)
838 as
[cnt
].as_digital
= false;
839 /* Headphones with seq=15 may mean redirection */
840 if (type
== COP_DEVICE_HP_OUT
&& seq
== 15)
842 as
[cnt
].as_pins
[seq
] = w
->w_nid
;
847 if (j
!= 15 && cnt
< maxassocs
&& as
[cnt
].as_pincnt
> 0) {
848 if (hpredir
&& as
[cnt
].as_pincnt
> 1)
849 as
[cnt
].as_hpredir
= first
;
854 hda_debug(sc
, " all done\n");
859 hdaudio_afg_control_parse(struct hdaudio_afg_softc
*sc
)
861 struct hdaudio_control
*ctl
;
862 struct hdaudio_widget
*w
, *cw
;
863 int i
, j
, cnt
, maxctls
, ocap
, icap
;
864 int mute
, offset
, step
, size
;
867 for (i
= sc
->sc_startnode
; i
< sc
->sc_endnode
; i
++) {
868 w
= hdaudio_afg_widget_lookup(sc
, i
);
869 if (w
== NULL
|| w
->w_enable
== false)
871 if (w
->w_p
.outamp_cap
)
873 if (w
->w_p
.inamp_cap
) {
875 case COP_AWCAP_TYPE_AUDIO_SELECTOR
:
876 case COP_AWCAP_TYPE_AUDIO_MIXER
:
877 for (j
= 0; j
< w
->w_nconns
; j
++) {
878 cw
= hdaudio_afg_widget_lookup(sc
,
880 if (cw
== NULL
|| cw
->w_enable
== false)
892 sc
->sc_nctls
= maxctls
;
896 ctl
= kmem_zalloc(sc
->sc_nctls
* sizeof(*ctl
), KM_SLEEP
);
899 for (i
= sc
->sc_startnode
; cnt
< maxctls
&& i
< sc
->sc_endnode
; i
++) {
900 if (cnt
>= maxctls
) {
901 hda_error(sc
, "ctl overflow\n");
904 w
= hdaudio_afg_widget_lookup(sc
, i
);
905 if (w
== NULL
|| w
->w_enable
== false)
907 ocap
= w
->w_p
.outamp_cap
;
908 icap
= w
->w_p
.inamp_cap
;
910 hda_trace(sc
, "add ctrl outamp %d:%02X:FF\n",
912 mute
= COP_AMPCAP_MUTE_CAPABLE(ocap
);
913 step
= COP_AMPCAP_NUM_STEPS(ocap
);
914 size
= COP_AMPCAP_STEP_SIZE(ocap
);
915 offset
= COP_AMPCAP_OFFSET(ocap
);
916 ctl
[cnt
].ctl_enable
= true;
917 ctl
[cnt
].ctl_widget
= w
;
918 ctl
[cnt
].ctl_mute
= mute
;
919 ctl
[cnt
].ctl_step
= step
;
920 ctl
[cnt
].ctl_size
= size
;
921 ctl
[cnt
].ctl_offset
= offset
;
922 ctl
[cnt
].ctl_left
= offset
;
923 ctl
[cnt
].ctl_right
= offset
;
924 if (w
->w_type
== COP_AWCAP_TYPE_PIN_COMPLEX
||
926 ctl
[cnt
].ctl_ndir
= HDAUDIO_PINDIR_IN
;
928 ctl
[cnt
].ctl_ndir
= HDAUDIO_PINDIR_OUT
;
929 ctl
[cnt
++].ctl_dir
= HDAUDIO_PINDIR_OUT
;
932 mute
= COP_AMPCAP_MUTE_CAPABLE(icap
);
933 step
= COP_AMPCAP_NUM_STEPS(icap
);
934 size
= COP_AMPCAP_STEP_SIZE(icap
);
935 offset
= COP_AMPCAP_OFFSET(icap
);
937 case COP_AWCAP_TYPE_AUDIO_SELECTOR
:
938 case COP_AWCAP_TYPE_AUDIO_MIXER
:
939 for (j
= 0; j
< w
->w_nconns
; j
++) {
942 cw
= hdaudio_afg_widget_lookup(sc
,
944 if (cw
== NULL
|| cw
->w_enable
== false)
946 hda_trace(sc
, "add ctrl inamp selmix "
947 "%d:%02X:%02X\n", cnt
, w
->w_nid
,
949 ctl
[cnt
].ctl_enable
= true;
950 ctl
[cnt
].ctl_widget
= w
;
951 ctl
[cnt
].ctl_childwidget
= cw
;
952 ctl
[cnt
].ctl_index
= j
;
953 ctl
[cnt
].ctl_mute
= mute
;
954 ctl
[cnt
].ctl_step
= step
;
955 ctl
[cnt
].ctl_size
= size
;
956 ctl
[cnt
].ctl_offset
= offset
;
957 ctl
[cnt
].ctl_left
= offset
;
958 ctl
[cnt
].ctl_right
= offset
;
959 ctl
[cnt
].ctl_ndir
= HDAUDIO_PINDIR_IN
;
960 ctl
[cnt
++].ctl_dir
= HDAUDIO_PINDIR_IN
;
966 hda_trace(sc
, "add ctrl inamp "
967 "%d:%02X:FF\n", cnt
, w
->w_nid
);
968 ctl
[cnt
].ctl_enable
= true;
969 ctl
[cnt
].ctl_widget
= w
;
970 ctl
[cnt
].ctl_mute
= mute
;
971 ctl
[cnt
].ctl_step
= step
;
972 ctl
[cnt
].ctl_size
= size
;
973 ctl
[cnt
].ctl_offset
= offset
;
974 ctl
[cnt
].ctl_left
= offset
;
975 ctl
[cnt
].ctl_right
= offset
;
976 if (w
->w_type
== COP_AWCAP_TYPE_PIN_COMPLEX
)
977 ctl
[cnt
].ctl_ndir
= HDAUDIO_PINDIR_OUT
;
979 ctl
[cnt
].ctl_ndir
= HDAUDIO_PINDIR_IN
;
980 ctl
[cnt
++].ctl_dir
= HDAUDIO_PINDIR_IN
;
990 hdaudio_afg_parse(struct hdaudio_afg_softc
*sc
)
992 struct hdaudio_widget
*w
;
996 nodecnt
= hda_get_param(sc
, SUBORDINATE_NODE_COUNT
);
997 sc
->sc_startnode
= COP_NODECNT_STARTNODE(nodecnt
);
998 sc
->sc_nwidgets
= COP_NODECNT_NUMNODES(nodecnt
);
999 sc
->sc_endnode
= sc
->sc_startnode
+ sc
->sc_nwidgets
;
1000 hda_debug(sc
, "afg start %02X end %02X nwidgets %d\n",
1001 sc
->sc_startnode
, sc
->sc_endnode
, sc
->sc_nwidgets
);
1003 hda_debug(sc
, "powering up widgets\n");
1004 hdaudio_command(sc
->sc_codec
, sc
->sc_nid
,
1005 CORB_SET_POWER_STATE
, COP_POWER_STATE_D0
);
1007 for (nid
= sc
->sc_startnode
; nid
< sc
->sc_endnode
; nid
++)
1008 hdaudio_command(sc
->sc_codec
, nid
,
1009 CORB_SET_POWER_STATE
, COP_POWER_STATE_D0
);
1012 sc
->sc_p
.afg_cap
= hda_get_param(sc
, AUDIO_FUNCTION_GROUP_CAPABILITIES
);
1013 sc
->sc_p
.stream_format
= hda_get_param(sc
, SUPPORTED_STREAM_FORMATS
);
1014 sc
->sc_p
.pcm_size_rate
= hda_get_param(sc
, SUPPORTED_PCM_SIZE_RATES
);
1015 sc
->sc_p
.outamp_cap
= hda_get_param(sc
, AMPLIFIER_CAPABILITIES_OUTAMP
);
1016 sc
->sc_p
.inamp_cap
= hda_get_param(sc
, AMPLIFIER_CAPABILITIES_INAMP
);
1017 sc
->sc_p
.power_states
= hda_get_param(sc
, SUPPORTED_POWER_STATES
);
1018 sc
->sc_p
.gpio_cnt
= hda_get_param(sc
, GPIO_COUNT
);
1020 sc
->sc_widgets
= kmem_zalloc(sc
->sc_nwidgets
* sizeof(*w
), KM_SLEEP
);
1021 hda_debug(sc
, "afg widgets %p-%p\n",
1022 sc
->sc_widgets
, sc
->sc_widgets
+ sc
->sc_nwidgets
);
1024 for (nid
= sc
->sc_startnode
; nid
< sc
->sc_endnode
; nid
++) {
1025 w
= hdaudio_afg_widget_lookup(sc
, nid
);
1035 w
->w_p
.eapdbtl
= 0xffffffff;
1036 hdaudio_afg_widget_parse(w
);
1041 hdaudio_afg_disable_nonaudio(struct hdaudio_afg_softc
*sc
)
1043 struct hdaudio_widget
*w
;
1046 /* Disable power and volume widgets */
1047 for (i
= sc
->sc_startnode
; i
< sc
->sc_endnode
; i
++) {
1048 w
= hdaudio_afg_widget_lookup(sc
, i
);
1049 if (w
== NULL
|| w
->w_enable
== false)
1051 if (w
->w_type
== COP_AWCAP_TYPE_POWER_WIDGET
||
1052 w
->w_type
== COP_AWCAP_TYPE_VOLUME_KNOB
) {
1053 hda_trace(w
->w_afg
, "disable %02X [nonaudio]\n",
1055 w
->w_enable
= false;
1061 hdaudio_afg_disable_useless(struct hdaudio_afg_softc
*sc
)
1063 struct hdaudio_widget
*w
, *cw
;
1064 struct hdaudio_control
*ctl
;
1065 int done
, found
, i
, j
, k
;
1068 /* Disable useless pins */
1069 for (i
= sc
->sc_startnode
; i
< sc
->sc_endnode
; i
++) {
1070 w
= hdaudio_afg_widget_lookup(sc
, i
);
1071 if (w
== NULL
|| w
->w_enable
== false)
1073 if (w
->w_type
!= COP_AWCAP_TYPE_PIN_COMPLEX
)
1075 conn
= COP_CFG_PORT_CONNECTIVITY(w
->w_pin
.config
);
1076 assoc
= COP_CFG_DEFAULT_ASSOCIATION(w
->w_pin
.config
);
1077 if (conn
== COP_PORT_NONE
) {
1078 hda_trace(w
->w_afg
, "disable %02X [no connectivity]\n",
1080 w
->w_enable
= false;
1083 hda_trace(w
->w_afg
, "disable %02X [no association]\n",
1085 w
->w_enable
= false;
1091 /* Disable and mute controls for disabled widgets */
1093 for (i
= 0; i
< sc
->sc_nctls
; i
++) {
1094 ctl
= &sc
->sc_ctls
[i
];
1095 if (ctl
->ctl_enable
== false)
1097 if (ctl
->ctl_widget
->w_enable
== false ||
1098 (ctl
->ctl_childwidget
!= NULL
&&
1099 ctl
->ctl_childwidget
->w_enable
== false)) {
1100 ctl
->ctl_forcemute
= 1;
1101 ctl
->ctl_muted
= HDAUDIO_AMP_MUTE_ALL
;
1102 ctl
->ctl_left
= ctl
->ctl_right
= 0;
1103 ctl
->ctl_enable
= false;
1104 if (ctl
->ctl_ndir
== HDAUDIO_PINDIR_IN
)
1105 ctl
->ctl_widget
->w_connsenable
[
1106 ctl
->ctl_index
] = false;
1108 hda_trace(ctl
->ctl_widget
->w_afg
,
1109 "disable ctl %d:%02X:%02X [widget disabled]\n",
1110 i
, ctl
->ctl_widget
->w_nid
,
1111 ctl
->ctl_childwidget
?
1112 ctl
->ctl_childwidget
->w_nid
: 0xff);
1115 /* Disable useless widgets */
1116 for (i
= sc
->sc_startnode
; i
< sc
->sc_endnode
; i
++) {
1117 w
= hdaudio_afg_widget_lookup(sc
, i
);
1118 if (w
== NULL
|| w
->w_enable
== false)
1120 /* Disable inputs with disabled child widgets */
1121 for (j
= 0; j
< w
->w_nconns
; j
++) {
1122 if (!w
->w_connsenable
[j
])
1124 cw
= hdaudio_afg_widget_lookup(sc
,
1126 if (cw
== NULL
|| cw
->w_enable
== false) {
1127 w
->w_connsenable
[j
] = false;
1129 "disable conn %02X->%02X "
1130 "[disabled child]\n",
1131 w
->w_nid
, w
->w_conns
[j
]);
1134 if (w
->w_type
!= COP_AWCAP_TYPE_AUDIO_SELECTOR
&&
1135 w
->w_type
!= COP_AWCAP_TYPE_AUDIO_MIXER
)
1137 /* Disable mixers and selectors without inputs */
1139 for (j
= 0; j
< w
->w_nconns
; j
++)
1140 if (w
->w_connsenable
[j
]) {
1145 w
->w_enable
= false;
1148 "disable %02X [inputs disabled]\n",
1151 /* Disable nodes without consumers */
1152 if (w
->w_type
!= COP_AWCAP_TYPE_AUDIO_SELECTOR
&&
1153 w
->w_type
!= COP_AWCAP_TYPE_AUDIO_MIXER
)
1156 for (k
= sc
->sc_startnode
; k
< sc
->sc_endnode
; k
++) {
1157 cw
= hdaudio_afg_widget_lookup(sc
, k
);
1158 if (cw
== NULL
|| cw
->w_enable
== false)
1160 for (j
= 0; j
< cw
->w_nconns
; j
++) {
1161 if (cw
->w_connsenable
[j
] &&
1162 cw
->w_conns
[j
] == i
) {
1169 w
->w_enable
= false;
1172 "disable %02X [consumers disabled]\n",
1176 } while (done
== 0);
1180 hdaudio_afg_assoc_trace_undo(struct hdaudio_afg_softc
*sc
, int as
, int seq
)
1182 struct hdaudio_widget
*w
;
1185 for (i
= sc
->sc_startnode
; i
< sc
->sc_endnode
; i
++) {
1186 w
= hdaudio_afg_widget_lookup(sc
, i
);
1187 if (w
== NULL
|| w
->w_enable
== false)
1189 if (w
->w_bindas
!= as
)
1192 w
->w_bindseqmask
&= ~(1 << seq
);
1193 if (w
->w_bindseqmask
== 0) {
1199 w
->w_bindseqmask
= 0;
1206 hdaudio_afg_assoc_trace_dac(struct hdaudio_afg_softc
*sc
, int as
, int seq
,
1207 int nid
, int dupseq
, int minassoc
, int only
, int depth
)
1209 struct hdaudio_widget
*w
;
1213 if (depth
>= HDAUDIO_PARSE_MAXDEPTH
)
1215 w
= hdaudio_afg_widget_lookup(sc
, nid
);
1216 if (w
== NULL
|| w
->w_enable
== false)
1218 /* We use only unused widgets */
1219 if (w
->w_bindas
>= 0 && w
->w_bindas
!= as
) {
1221 hda_trace(sc
, "depth %d nid %02X busy by assoc %d\n",
1222 depth
+ 1, nid
, w
->w_bindas
);
1226 if (w
->w_bindseqmask
!= 0) {
1229 "depth %d nid %02X busy by seqmask %x\n",
1230 depth
+ 1, nid
, w
->w_bindas
);
1234 /* If this is headphones, allow duplicate first pin */
1235 if (w
->w_bindseqmask
!= 0 &&
1236 (w
->w_bindseqmask
& (1 << dupseq
)) == 0)
1240 switch (w
->w_type
) {
1241 case COP_AWCAP_TYPE_AUDIO_INPUT
:
1243 case COP_AWCAP_TYPE_AUDIO_OUTPUT
:
1244 /* If we are tracing HP take only dac of first pin */
1245 if ((only
== 0 || only
== w
->w_nid
) &&
1246 (w
->w_nid
>= minassoc
) && (dupseq
< 0 || w
->w_nid
==
1247 sc
->sc_assocs
[as
].as_dacs
[dupseq
]))
1250 case COP_AWCAP_TYPE_PIN_COMPLEX
:
1255 for (i
= 0; i
< w
->w_nconns
; i
++) {
1256 if (w
->w_connsenable
[i
] == false)
1258 if (w
->w_selconn
!= -1 && w
->w_selconn
!= i
)
1260 ret
= hdaudio_afg_assoc_trace_dac(sc
, as
, seq
,
1261 w
->w_conns
[i
], dupseq
, minassoc
, only
, depth
+ 1);
1263 if (m
== 0 || ret
< m
) {
1267 if (only
|| dupseq
>= 0)
1271 if (m
&& only
&& ((w
->w_nconns
> 1 &&
1272 w
->w_type
!= COP_AWCAP_TYPE_AUDIO_MIXER
) ||
1273 w
->w_type
== COP_AWCAP_TYPE_AUDIO_SELECTOR
))
1279 w
->w_bindseqmask
|= (1 << seq
);
1282 hda_trace(sc
, "depth %d nid %02X dupseq %d returned %02X\n",
1283 depth
+ 1, nid
, dupseq
, m
);
1289 hdaudio_afg_assoc_trace_out(struct hdaudio_afg_softc
*sc
, int as
, int seq
)
1291 struct hdaudio_assoc
*assocs
= sc
->sc_assocs
;
1296 for (i
= seq
; i
< HDAUDIO_MAXPINS
&& assocs
[as
].as_pins
[i
] == 0; i
++)
1298 /* Check if there is any left, if not then we have succeeded */
1299 if (i
== HDAUDIO_MAXPINS
)
1302 hpredir
= (i
== 15 && assocs
[as
].as_fakeredir
== 0) ?
1303 assocs
[as
].as_hpredir
: -1;
1306 /* Trace this pin taking min nid into account */
1307 res
= hdaudio_afg_assoc_trace_dac(sc
, as
, i
,
1308 assocs
[as
].as_pins
[i
], hpredir
, minassoc
, 0, 0);
1310 /* If we failed, return to previous and redo it */
1311 hda_trace(sc
, " trace failed as=%d seq=%d pin=%02X "
1312 "hpredir=%d minassoc=%d\n",
1313 as
, seq
, assocs
[as
].as_pins
[i
], hpredir
, minassoc
);
1316 /* Trace again to mark the path */
1317 hdaudio_afg_assoc_trace_dac(sc
, as
, i
,
1318 assocs
[as
].as_pins
[i
], hpredir
, minassoc
, res
, 0);
1319 assocs
[as
].as_dacs
[i
] = res
;
1320 /* We succeeded, so call next */
1321 if (hdaudio_afg_assoc_trace_out(sc
, as
, i
+ 1))
1323 /* If next failed, we should retry with next min */
1324 hdaudio_afg_assoc_trace_undo(sc
, as
, i
);
1325 assocs
[as
].as_dacs
[i
] = 0;
1331 hdaudio_afg_assoc_trace_adc(struct hdaudio_afg_softc
*sc
, int assoc
, int seq
,
1332 int nid
, int only
, int depth
)
1334 struct hdaudio_widget
*w
, *wc
;
1338 if (depth
> HDAUDIO_PARSE_MAXDEPTH
)
1340 w
= hdaudio_afg_widget_lookup(sc
, nid
);
1341 if (w
== NULL
|| w
->w_enable
== false)
1343 /* Use only unused widgets */
1344 if (w
->w_bindas
>= 0 && w
->w_bindas
!= assoc
)
1347 switch (w
->w_type
) {
1348 case COP_AWCAP_TYPE_AUDIO_INPUT
:
1349 if (only
== w
->w_nid
)
1352 case COP_AWCAP_TYPE_PIN_COMPLEX
:
1357 /* Try to find reachable ADCs with specified nid */
1358 for (j
= sc
->sc_startnode
; j
< sc
->sc_endnode
; j
++) {
1359 wc
= hdaudio_afg_widget_lookup(sc
, j
);
1360 if (w
== NULL
|| w
->w_enable
== false)
1362 for (i
= 0; i
< wc
->w_nconns
; i
++) {
1363 if (wc
->w_connsenable
[i
] == false)
1365 if (wc
->w_conns
[i
] != nid
)
1367 if (hdaudio_afg_assoc_trace_adc(sc
, assoc
, seq
,
1368 j
, only
, depth
+ 1) != 0) {
1370 if (((wc
->w_nconns
> 1 &&
1371 wc
->w_type
!= COP_AWCAP_TYPE_AUDIO_MIXER
) ||
1372 wc
->w_type
!= COP_AWCAP_TYPE_AUDIO_SELECTOR
)
1373 && wc
->w_selconn
== -1)
1381 w
->w_bindas
= assoc
;
1382 w
->w_bindseqmask
|= (1 << seq
);
1388 hdaudio_afg_assoc_trace_in(struct hdaudio_afg_softc
*sc
, int assoc
)
1390 struct hdaudio_assoc
*as
= sc
->sc_assocs
;
1391 struct hdaudio_widget
*w
;
1394 for (j
= sc
->sc_startnode
; j
< sc
->sc_endnode
; j
++) {
1395 w
= hdaudio_afg_widget_lookup(sc
, j
);
1396 if (w
== NULL
|| w
->w_enable
== false)
1398 if (w
->w_type
!= COP_AWCAP_TYPE_AUDIO_INPUT
)
1400 if (w
->w_bindas
>= 0 && w
->w_bindas
!= assoc
)
1404 for (i
= 0; i
< HDAUDIO_MAXPINS
; i
++) {
1405 if (as
[assoc
].as_pins
[i
] == 0)
1407 /* Trace this pin taking goal into account */
1408 if (hdaudio_afg_assoc_trace_adc(sc
, assoc
, i
,
1409 as
[assoc
].as_pins
[i
], j
, 0) == 0) {
1410 hdaudio_afg_assoc_trace_undo(sc
, assoc
, -1);
1411 for (k
= 0; k
< HDAUDIO_MAXPINS
; k
++)
1412 as
[assoc
].as_dacs
[k
] = 0;
1415 as
[assoc
].as_dacs
[i
] = j
;
1417 if (i
== HDAUDIO_MAXPINS
)
1424 hdaudio_afg_assoc_trace_to_out(struct hdaudio_afg_softc
*sc
, int nid
, int depth
)
1426 struct hdaudio_assoc
*as
= sc
->sc_assocs
;
1427 struct hdaudio_widget
*w
, *wc
;
1431 if (depth
> HDAUDIO_PARSE_MAXDEPTH
)
1433 w
= hdaudio_afg_widget_lookup(sc
, nid
);
1434 if (w
== NULL
|| w
->w_enable
== false)
1437 /* Use only unused widgets */
1438 if (depth
> 0 && w
->w_bindas
!= -1) {
1439 if (w
->w_bindas
< 0 ||
1440 as
[w
->w_bindas
].as_dir
== HDAUDIO_PINDIR_OUT
) {
1447 switch (w
->w_type
) {
1448 case COP_AWCAP_TYPE_AUDIO_INPUT
:
1449 /* Do not traverse input (not yet supported) */
1451 case COP_AWCAP_TYPE_PIN_COMPLEX
:
1456 /* Try to find reachable ADCs with specified nid */
1457 for (j
= sc
->sc_startnode
; j
< sc
->sc_endnode
; j
++) {
1458 wc
= hdaudio_afg_widget_lookup(sc
, j
);
1459 if (wc
== NULL
|| wc
->w_enable
== false)
1461 for (i
= 0; i
< wc
->w_nconns
; i
++) {
1462 if (wc
->w_connsenable
[i
] == false)
1464 if (wc
->w_conns
[i
] != nid
)
1466 if (hdaudio_afg_assoc_trace_to_out(sc
,
1467 j
, depth
+ 1) != 0) {
1470 COP_AWCAP_TYPE_AUDIO_SELECTOR
&&
1471 wc
->w_selconn
== -1)
1484 hdaudio_afg_assoc_trace_misc(struct hdaudio_afg_softc
*sc
)
1486 struct hdaudio_assoc
*as
= sc
->sc_assocs
;
1487 struct hdaudio_widget
*w
;
1492 * Find mixer associated with input, but supplying signal
1493 * for output associations. Hope it will be input monitor.
1495 for (j
= sc
->sc_startnode
; j
< sc
->sc_endnode
; j
++) {
1496 w
= hdaudio_afg_widget_lookup(sc
, j
);
1497 if (w
== NULL
|| w
->w_enable
== false)
1499 if (w
->w_type
!= COP_AWCAP_TYPE_AUDIO_MIXER
)
1501 if (w
->w_bindas
< 0 ||
1502 as
[w
->w_bindas
].as_dir
!= HDAUDIO_PINDIR_IN
)
1504 if (hdaudio_afg_assoc_trace_to_out(sc
, w
->w_nid
, 0)) {
1505 w
->w_pflags
|= HDAUDIO_ADC_MONITOR
;
1506 w
->w_audiodev
= HDAUDIO_MIXER_IMIX
;
1511 for (j
= sc
->sc_startnode
; j
< sc
->sc_endnode
; j
++) {
1512 w
= hdaudio_afg_widget_lookup(sc
, j
);
1513 if (w
== NULL
|| w
->w_enable
== false)
1515 if (w
->w_type
!= COP_AWCAP_TYPE_BEEP_GENERATOR
)
1517 if (hdaudio_afg_assoc_trace_to_out(sc
, w
->w_nid
, 0)) {
1518 hda_debug(sc
, "beeper %02X traced to out\n", w
->w_nid
);
1525 hdaudio_afg_build_tree(struct hdaudio_afg_softc
*sc
)
1527 struct hdaudio_assoc
*as
= sc
->sc_assocs
;
1530 /* Trace all associations in order of their numbers */
1532 /* Trace DACs first */
1533 for (j
= 0; j
< sc
->sc_nassocs
; j
++) {
1534 if (as
[j
].as_enable
== false)
1536 if (as
[j
].as_dir
!= HDAUDIO_PINDIR_OUT
)
1539 res
= hdaudio_afg_assoc_trace_out(sc
, j
, 0);
1540 if (res
== 0 && as
[j
].as_hpredir
>= 0 &&
1541 as
[j
].as_fakeredir
== 0) {
1543 * If codec can't do analog HP redirection
1544 * try to make it using one more DAC
1546 as
[j
].as_fakeredir
= 1;
1550 hda_debug(sc
, "disable assoc %d (%d) [trace failed]\n",
1552 for (i
= 0; i
< HDAUDIO_MAXPINS
; i
++) {
1553 if (as
[j
].as_pins
[i
] == 0)
1555 hda_debug(sc
, " assoc %d pin%d: %02X\n", j
, i
,
1558 for (i
= 0; i
< HDAUDIO_MAXPINS
; i
++) {
1559 if (as
[j
].as_dacs
[i
] == 0)
1561 hda_debug(sc
, " assoc %d dac%d: %02X\n", j
, i
,
1565 as
[j
].as_enable
= false;
1570 for (j
= 0; j
< sc
->sc_nassocs
; j
++) {
1571 if (as
[j
].as_enable
== false)
1573 if (as
[j
].as_dir
!= HDAUDIO_PINDIR_IN
)
1575 res
= hdaudio_afg_assoc_trace_in(sc
, j
);
1577 hda_error(sc
, "disable assoc %d (%d) [trace failed]\n",
1579 for (i
= 0; i
< HDAUDIO_MAXPINS
; i
++) {
1580 if (as
[j
].as_pins
[i
] == 0)
1582 hda_error(sc
, " assoc %d pin%d: %02X\n", j
, i
,
1585 for (i
= 0; i
< HDAUDIO_MAXPINS
; i
++) {
1586 if (as
[j
].as_dacs
[i
] == 0)
1588 hda_error(sc
, " assoc %d adc%d: %02X\n", j
, i
,
1592 as
[j
].as_enable
= false;
1596 /* Trace mixer and beeper pseudo associations */
1597 hdaudio_afg_assoc_trace_misc(sc
);
1601 hdaudio_afg_prepare_pin_controls(struct hdaudio_afg_softc
*sc
)
1603 struct hdaudio_assoc
*as
= sc
->sc_assocs
;
1604 struct hdaudio_widget
*w
;
1608 for (i
= 0; i
< sc
->sc_nwidgets
; i
++) {
1609 w
= &sc
->sc_widgets
[i
];
1610 if (w
->w_type
!= COP_AWCAP_TYPE_PIN_COMPLEX
)
1612 pincap
= w
->w_pin
.cap
;
1614 /* Disable everything */
1616 COP_PWC_VREF_ENABLE_MASK
|
1618 COP_PWC_OUT_ENABLE
|
1619 COP_PWC_HPHN_ENABLE
);
1621 if (w
->w_enable
== false ||
1622 w
->w_bindas
< 0 || as
[w
->w_bindas
].as_enable
== false) {
1623 /* Pin is unused so leave it disabled */
1624 if ((pincap
& (COP_PINCAP_OUTPUT_CAPABLE
|
1625 COP_PINCAP_INPUT_CAPABLE
)) ==
1626 (COP_PINCAP_OUTPUT_CAPABLE
|
1627 COP_PINCAP_INPUT_CAPABLE
)) {
1628 hda_trace(sc
, "pin %02X off, "
1629 "in/out capable (bindas=%d "
1630 "enable=%d as_enable=%d)\n",
1631 w
->w_nid
, w
->w_bindas
, w
->w_enable
,
1633 as
[w
->w_bindas
].as_enable
: -1);
1634 w
->w_pin
.ctrl
|= COP_PWC_OUT_ENABLE
;
1637 } else if (as
[w
->w_bindas
].as_dir
== HDAUDIO_PINDIR_IN
) {
1638 /* Input pin, configure for input */
1639 if (pincap
& COP_PINCAP_INPUT_CAPABLE
)
1640 w
->w_pin
.ctrl
|= COP_PWC_IN_ENABLE
;
1642 if (COP_CFG_DEFAULT_DEVICE(w
->w_pin
.config
) !=
1645 if (COP_PINCAP_VREF_CONTROL(pincap
) & COP_VREF_80
)
1646 w
->w_pin
.ctrl
|= COP_PWC_VREF_80
;
1647 else if (COP_PINCAP_VREF_CONTROL(pincap
) & COP_VREF_50
)
1648 w
->w_pin
.ctrl
|= COP_PWC_VREF_50
;
1650 /* Output pin, configure for output */
1651 if (pincap
& COP_PINCAP_OUTPUT_CAPABLE
)
1652 w
->w_pin
.ctrl
|= COP_PWC_OUT_ENABLE
;
1653 if ((pincap
& COP_PINCAP_HEADPHONE_DRIVE_CAPABLE
) &&
1654 (COP_CFG_DEFAULT_DEVICE(w
->w_pin
.config
) ==
1656 w
->w_pin
.ctrl
|= COP_PWC_HPHN_ENABLE
;
1663 hdaudio_afg_dump(struct hdaudio_afg_softc
*sc
)
1665 #if defined(HDAUDIO_AFG_DEBUG) && HDAUDIO_AFG_DEBUG > 1
1666 struct hdaudio_control
*ctl
;
1669 for (i
= 0; i
< sc
->sc_nctls
; i
++) {
1670 ctl
= &sc
->sc_ctls
[i
];
1671 type
= (ctl
->ctl_widget
? ctl
->ctl_widget
->w_type
: -1);
1672 hda_print(sc
, "%03X: nid %02X type %d %s (%s) index %d",
1673 i
, (ctl
->ctl_widget
? ctl
->ctl_widget
->w_nid
: -1), type
,
1674 (ctl
->ctl_ndir
== HDAUDIO_PINDIR_IN
) ? "in " : "out",
1675 (ctl
->ctl_dir
== HDAUDIO_PINDIR_IN
) ? "in " : "out",
1677 if (ctl
->ctl_childwidget
)
1678 hda_print1(sc
, " cnid %02X",
1679 ctl
->ctl_childwidget
->w_nid
);
1681 hda_print1(sc
, " ");
1682 hda_print1(sc
, "\n");
1683 hda_print(sc
, " mute: %d step: %3d size: %3d off: %3d%s\n",
1684 ctl
->ctl_mute
, ctl
->ctl_step
, ctl
->ctl_size
,
1686 (ctl
->ctl_enable
== false) ? " [DISABLED]" : "");
1692 hdaudio_afg_match(device_t parent
, cfdata_t match
, void *opaque
)
1694 prop_dictionary_t args
= opaque
;
1698 rv
= prop_dictionary_get_uint8(args
, "function-group-type", &fgtype
);
1699 if (rv
== false || fgtype
!= HDAUDIO_GROUP_TYPE_AFG
)
1706 hdaudio_afg_disable_unassoc(struct hdaudio_afg_softc
*sc
)
1708 struct hdaudio_assoc
*as
= sc
->sc_assocs
;
1709 struct hdaudio_widget
*w
, *cw
;
1710 struct hdaudio_control
*ctl
;
1713 /* Disable unassociated widgets */
1714 for (i
= sc
->sc_startnode
; i
< sc
->sc_endnode
; i
++) {
1715 w
= hdaudio_afg_widget_lookup(sc
, i
);
1716 if (w
== NULL
|| w
->w_enable
== false)
1718 if (w
->w_bindas
== -1) {
1720 hda_trace(sc
, "disable %02X [unassociated]\n",
1725 /* Disable input connections on input pin and output on output */
1726 for (i
= sc
->sc_startnode
; i
< sc
->sc_endnode
; i
++) {
1727 w
= hdaudio_afg_widget_lookup(sc
, i
);
1728 if (w
== NULL
|| w
->w_enable
== false)
1730 if (w
->w_type
!= COP_AWCAP_TYPE_PIN_COMPLEX
)
1732 if (w
->w_bindas
< 0)
1734 if (as
[w
->w_bindas
].as_dir
== HDAUDIO_PINDIR_IN
) {
1735 hda_trace(sc
, "disable %02X input connections\n",
1737 for (j
= 0; j
< w
->w_nconns
; j
++)
1738 w
->w_connsenable
[j
] = false;
1739 ctl
= hdaudio_afg_control_lookup(sc
, w
->w_nid
,
1740 HDAUDIO_PINDIR_IN
, -1, 1);
1741 if (ctl
&& ctl
->ctl_enable
== true) {
1742 ctl
->ctl_forcemute
= 1;
1743 ctl
->ctl_muted
= HDAUDIO_AMP_MUTE_ALL
;
1744 ctl
->ctl_left
= ctl
->ctl_right
= 0;
1745 ctl
->ctl_enable
= false;
1748 ctl
= hdaudio_afg_control_lookup(sc
, w
->w_nid
,
1749 HDAUDIO_PINDIR_OUT
, -1, 1);
1750 if (ctl
&& ctl
->ctl_enable
== true) {
1751 ctl
->ctl_forcemute
= 1;
1752 ctl
->ctl_muted
= HDAUDIO_AMP_MUTE_ALL
;
1753 ctl
->ctl_left
= ctl
->ctl_right
= 0;
1754 ctl
->ctl_enable
= false;
1756 for (k
= sc
->sc_startnode
; k
< sc
->sc_endnode
; k
++) {
1757 cw
= hdaudio_afg_widget_lookup(sc
, k
);
1758 if (cw
== NULL
|| cw
->w_enable
== false)
1760 for (j
= 0; j
< cw
->w_nconns
; j
++) {
1761 if (!cw
->w_connsenable
[j
])
1763 if (cw
->w_conns
[j
] != i
)
1765 hda_trace(sc
, "disable %02X -> %02X "
1766 "output connection\n",
1767 cw
->w_nid
, cw
->w_conns
[j
]);
1768 cw
->w_connsenable
[j
] = false;
1770 COP_AWCAP_TYPE_PIN_COMPLEX
&&
1773 ctl
= hdaudio_afg_control_lookup(sc
,
1774 k
, HDAUDIO_PINDIR_IN
, j
, 1);
1775 if (ctl
&& ctl
->ctl_enable
== true) {
1776 ctl
->ctl_forcemute
= 1;
1778 HDAUDIO_AMP_MUTE_ALL
;
1781 ctl
->ctl_enable
= false;
1790 hdaudio_afg_disable_unsel(struct hdaudio_afg_softc
*sc
)
1792 struct hdaudio_assoc
*as
= sc
->sc_assocs
;
1793 struct hdaudio_widget
*w
;
1796 /* On playback path we can safely disable all unselected inputs */
1797 for (i
= sc
->sc_startnode
; i
< sc
->sc_endnode
; i
++) {
1798 w
= hdaudio_afg_widget_lookup(sc
, i
);
1799 if (w
== NULL
|| w
->w_enable
== false)
1801 if (w
->w_nconns
<= 1)
1803 if (w
->w_type
== COP_AWCAP_TYPE_AUDIO_MIXER
)
1805 if (w
->w_bindas
< 0 ||
1806 as
[w
->w_bindas
].as_dir
== HDAUDIO_PINDIR_IN
)
1808 for (j
= 0; j
< w
->w_nconns
; j
++) {
1809 if (w
->w_connsenable
[j
] == false)
1811 if (w
->w_selconn
< 0 || w
->w_selconn
== j
)
1813 hda_trace(sc
, "disable %02X->%02X [unselected]\n",
1814 w
->w_nid
, w
->w_conns
[j
]);
1815 w
->w_connsenable
[j
] = false;
1821 hdaudio_afg_disable_crossassoc(struct hdaudio_afg_softc
*sc
)
1823 struct hdaudio_widget
*w
, *cw
;
1824 struct hdaudio_control
*ctl
;
1827 /* Disable cross associated and unwanted cross channel connections */
1829 /* ... using selectors */
1830 for (i
= sc
->sc_startnode
; i
< sc
->sc_endnode
; i
++) {
1831 w
= hdaudio_afg_widget_lookup(sc
, i
);
1832 if (w
== NULL
|| w
->w_enable
== false)
1834 if (w
->w_nconns
<= 1)
1836 if (w
->w_type
== COP_AWCAP_TYPE_AUDIO_MIXER
)
1838 if (w
->w_bindas
== -2)
1840 for (j
= 0; j
< w
->w_nconns
; j
++) {
1841 if (w
->w_connsenable
[j
] == false)
1843 cw
= hdaudio_afg_widget_lookup(sc
, w
->w_conns
[j
]);
1844 if (cw
== NULL
|| cw
->w_enable
== false)
1846 if (cw
->w_bindas
== -2)
1848 if (w
->w_bindas
== cw
->w_bindas
&&
1849 (w
->w_bindseqmask
& cw
->w_bindseqmask
) != 0)
1851 hda_trace(sc
, "disable %02X->%02X [crossassoc]\n",
1852 w
->w_nid
, w
->w_conns
[j
]);
1853 w
->w_connsenable
[j
] = false;
1856 /* ... using controls */
1857 for (i
= 0; i
< sc
->sc_nctls
; i
++) {
1858 ctl
= &sc
->sc_ctls
[i
];
1859 if (ctl
->ctl_enable
== false || ctl
->ctl_childwidget
== NULL
)
1861 if (ctl
->ctl_widget
->w_bindas
== -2 ||
1862 ctl
->ctl_childwidget
->w_bindas
== -2)
1864 if (ctl
->ctl_widget
->w_bindas
!=
1865 ctl
->ctl_childwidget
->w_bindas
||
1866 (ctl
->ctl_widget
->w_bindseqmask
&
1867 ctl
->ctl_childwidget
->w_bindseqmask
) == 0) {
1868 ctl
->ctl_forcemute
= 1;
1869 ctl
->ctl_muted
= HDAUDIO_AMP_MUTE_ALL
;
1870 ctl
->ctl_left
= ctl
->ctl_right
= 0;
1871 ctl
->ctl_enable
= false;
1872 if (ctl
->ctl_ndir
== HDAUDIO_PINDIR_IN
) {
1873 hda_trace(sc
, "disable ctl %d:%02X:%02X "
1875 i
, ctl
->ctl_widget
->w_nid
,
1876 ctl
->ctl_widget
->w_conns
[ctl
->ctl_index
]);
1877 ctl
->ctl_widget
->w_connsenable
[
1878 ctl
->ctl_index
] = false;
1884 static struct hdaudio_control
*
1885 hdaudio_afg_control_amp_get(struct hdaudio_afg_softc
*sc
, int nid
,
1886 enum hdaudio_pindir dir
, int index
, int cnt
)
1888 struct hdaudio_control
*ctl
;
1891 for (i
= 0; i
< sc
->sc_nctls
; i
++) {
1892 ctl
= &sc
->sc_ctls
[i
];
1893 if (ctl
->ctl_enable
== false)
1895 if (ctl
->ctl_widget
->w_nid
!= nid
)
1897 if (dir
&& ctl
->ctl_ndir
!= dir
)
1899 if (index
>= 0 && ctl
->ctl_ndir
== HDAUDIO_PINDIR_IN
&&
1900 ctl
->ctl_dir
== ctl
->ctl_ndir
&&
1901 ctl
->ctl_index
!= index
)
1904 if (found
== cnt
|| cnt
<= 0)
1912 hdaudio_afg_control_amp_set1(struct hdaudio_control
*ctl
, int lmute
, int rmute
,
1913 int left
, int right
, int dir
)
1915 struct hdaudio_afg_softc
*sc
= ctl
->ctl_widget
->w_afg
;
1916 int index
= ctl
->ctl_index
;
1919 if (left
!= right
|| lmute
!= rmute
) {
1920 v
= (1 << (15 - dir
)) | (1 << 13) | (index
<< 8) |
1921 (lmute
<< 7) | left
;
1922 hdaudio_command(sc
->sc_codec
, ctl
->ctl_widget
->w_nid
,
1923 CORB_SET_AMPLIFIER_GAIN_MUTE
, v
);
1924 v
= (1 << (15 - dir
)) | (1 << 12) | (index
<< 8) |
1925 (rmute
<< 7) | right
;
1927 v
= (1 << (15 - dir
)) | (3 << 12) | (index
<< 8) |
1928 (lmute
<< 7) | left
;
1929 hdaudio_command(sc
->sc_codec
, ctl
->ctl_widget
->w_nid
,
1930 CORB_SET_AMPLIFIER_GAIN_MUTE
, v
);
1934 hdaudio_afg_control_amp_set(struct hdaudio_control
*ctl
, uint32_t mute
,
1935 int left
, int right
)
1939 /* Save new values if valid */
1940 if (mute
!= HDAUDIO_AMP_MUTE_DEFAULT
)
1941 ctl
->ctl_muted
= mute
;
1942 if (left
!= HDAUDIO_AMP_VOL_DEFAULT
)
1943 ctl
->ctl_left
= left
;
1944 if (right
!= HDAUDIO_AMP_VOL_DEFAULT
)
1945 ctl
->ctl_right
= right
;
1947 /* Prepare effective values */
1948 if (ctl
->ctl_forcemute
) {
1952 lmute
= HDAUDIO_AMP_LEFT_MUTED(ctl
->ctl_muted
);
1953 rmute
= HDAUDIO_AMP_RIGHT_MUTED(ctl
->ctl_muted
);
1954 left
= ctl
->ctl_left
;
1955 right
= ctl
->ctl_right
;
1958 /* Apply effective values */
1959 if (ctl
->ctl_dir
& HDAUDIO_PINDIR_OUT
)
1960 hdaudio_afg_control_amp_set1(ctl
, lmute
, rmute
, left
, right
, 0);
1961 if (ctl
->ctl_dir
& HDAUDIO_PINDIR_IN
)
1962 hdaudio_afg_control_amp_set1(ctl
, lmute
, rmute
, left
, right
, 1);
1966 hdaudio_afg_control_commit(struct hdaudio_afg_softc
*sc
)
1968 struct hdaudio_control
*ctl
;
1971 for (i
= 0; i
< sc
->sc_nctls
; i
++) {
1972 ctl
= &sc
->sc_ctls
[i
];
1973 //if (ctl->ctl_enable == false || ctl->ctl_audiomask != 0)
1974 if (ctl
->ctl_enable
== false)
1976 /* Init fixed controls to 0dB amplification */
1977 z
= ctl
->ctl_offset
;
1978 if (z
> ctl
->ctl_step
)
1980 hdaudio_afg_control_amp_set(ctl
, HDAUDIO_AMP_MUTE_NONE
, z
, z
);
1985 hdaudio_afg_widget_connection_select(struct hdaudio_widget
*w
, uint8_t index
)
1987 struct hdaudio_afg_softc
*sc
= w
->w_afg
;
1989 if (w
->w_nconns
< 1 || index
> (w
->w_nconns
- 1))
1992 hdaudio_command(sc
->sc_codec
, w
->w_nid
,
1993 CORB_SET_CONNECTION_SELECT_CONTROL
, index
);
1994 w
->w_selconn
= index
;
1998 hdaudio_afg_assign_names(struct hdaudio_afg_softc
*sc
)
2000 struct hdaudio_assoc
*as
= sc
->sc_assocs
;
2001 struct hdaudio_widget
*w
;
2003 int type
= -1, use
, used
=0;
2004 static const int types
[7][13] = {
2005 { HDAUDIO_MIXER_LINE
, HDAUDIO_MIXER_LINE1
, HDAUDIO_MIXER_LINE2
,
2006 HDAUDIO_MIXER_LINE3
, -1 },
2007 { HDAUDIO_MIXER_MONITOR
, HDAUDIO_MIXER_MIC
, -1 }, /* int mic */
2008 { HDAUDIO_MIXER_MIC
, HDAUDIO_MIXER_MONITOR
, -1 }, /* ext mic */
2009 { HDAUDIO_MIXER_CD
, -1 },
2010 { HDAUDIO_MIXER_SPEAKER
, -1 },
2011 { HDAUDIO_MIXER_DIGITAL1
, HDAUDIO_MIXER_DIGITAL2
,
2012 HDAUDIO_MIXER_DIGITAL3
, -1 },
2013 { HDAUDIO_MIXER_LINE
, HDAUDIO_MIXER_LINE1
, HDAUDIO_MIXER_LINE2
,
2014 HDAUDIO_MIXER_LINE3
, HDAUDIO_MIXER_PHONEIN
,
2015 HDAUDIO_MIXER_PHONEOUT
, HDAUDIO_MIXER_VIDEO
, HDAUDIO_MIXER_RADIO
,
2016 HDAUDIO_MIXER_DIGITAL1
, HDAUDIO_MIXER_DIGITAL2
,
2017 HDAUDIO_MIXER_DIGITAL3
, HDAUDIO_MIXER_MONITOR
, -1 } /* others */
2020 /* Surely known names */
2021 for (i
= sc
->sc_startnode
; i
< sc
->sc_endnode
; i
++) {
2022 w
= hdaudio_afg_widget_lookup(sc
, i
);
2023 if (w
== NULL
|| w
->w_enable
== false)
2025 if (w
->w_bindas
== -1)
2028 switch (w
->w_type
) {
2029 case COP_AWCAP_TYPE_PIN_COMPLEX
:
2030 if (as
[w
->w_bindas
].as_dir
== HDAUDIO_PINDIR_OUT
)
2033 switch (COP_CFG_DEFAULT_DEVICE(w
->w_pin
.config
)) {
2034 case COP_DEVICE_LINE_IN
:
2037 case COP_DEVICE_MIC_IN
:
2038 if (COP_CFG_PORT_CONNECTIVITY(w
->w_pin
.config
)
2046 case COP_DEVICE_SPEAKER
:
2049 case COP_DEVICE_SPDIF_IN
:
2050 case COP_DEVICE_DIGITAL_OTHER_IN
:
2057 while (types
[type
][j
] >= 0 &&
2058 (used
& (1 << types
[type
][j
])) != 0) {
2061 if (types
[type
][j
] >= 0)
2062 use
= types
[type
][j
];
2064 case COP_AWCAP_TYPE_AUDIO_OUTPUT
:
2065 use
= HDAUDIO_MIXER_PCM
;
2067 case COP_AWCAP_TYPE_BEEP_GENERATOR
:
2068 use
= HDAUDIO_MIXER_SPEAKER
;
2074 w
->w_audiodev
= use
;
2078 /* Semi-known names */
2079 for (i
= sc
->sc_startnode
; i
< sc
->sc_endnode
; i
++) {
2080 w
= hdaudio_afg_widget_lookup(sc
, i
);
2081 if (w
== NULL
|| w
->w_enable
== false)
2083 if (w
->w_audiodev
>= 0)
2085 if (w
->w_bindas
== -1)
2087 if (w
->w_type
!= COP_AWCAP_TYPE_PIN_COMPLEX
)
2089 if (as
[w
->w_bindas
].as_dir
== HDAUDIO_PINDIR_OUT
)
2092 switch (COP_CFG_DEFAULT_DEVICE(w
->w_pin
.config
)) {
2093 case COP_DEVICE_LINE_OUT
:
2094 case COP_DEVICE_SPEAKER
:
2095 case COP_DEVICE_HP_OUT
:
2096 case COP_DEVICE_AUX
:
2099 case COP_DEVICE_MIC_IN
:
2102 case COP_DEVICE_SPDIF_OUT
:
2103 case COP_DEVICE_DIGITAL_OTHER_OUT
:
2110 while (types
[type
][j
] >= 0 &&
2111 (used
& (1 << types
[type
][j
])) != 0) {
2114 if (types
[type
][j
] >= 0) {
2115 w
->w_audiodev
= types
[type
][j
];
2116 used
|= (1 << types
[type
][j
]);
2120 for (i
= sc
->sc_startnode
; i
< sc
->sc_endnode
; i
++) {
2121 w
= hdaudio_afg_widget_lookup(sc
, i
);
2122 if (w
== NULL
|| w
->w_enable
== false)
2124 if (w
->w_audiodev
>= 0)
2126 if (w
->w_bindas
== -1)
2128 if (w
->w_type
!= COP_AWCAP_TYPE_PIN_COMPLEX
)
2130 if (as
[w
->w_bindas
].as_dir
== HDAUDIO_PINDIR_OUT
)
2133 while (types
[6][j
] >= 0 &&
2134 (used
& (1 << types
[6][j
])) != 0) {
2137 if (types
[6][j
] >= 0) {
2138 w
->w_audiodev
= types
[6][j
];
2139 used
|= (1 << types
[6][j
]);
2145 hdaudio_afg_control_source_amp(struct hdaudio_afg_softc
*sc
, int nid
, int index
,
2146 int audiodev
, int ctlable
, int depth
, int need
)
2148 struct hdaudio_widget
*w
, *wc
;
2149 struct hdaudio_control
*ctl
;
2150 int i
, j
, conns
= 0, rneed
;
2152 if (depth
>= HDAUDIO_PARSE_MAXDEPTH
)
2155 w
= hdaudio_afg_widget_lookup(sc
, nid
);
2156 if (w
== NULL
|| w
->w_enable
== false)
2159 /* Count number of active inputs */
2161 for (j
= 0; j
< w
->w_nconns
; j
++) {
2162 if (w
->w_connsenable
[j
])
2168 * If this is not a first step, use input mixer. Pins have common
2169 * input ctl so care must be taken
2171 if (depth
> 0 && ctlable
&& (conns
== 1 ||
2172 w
->w_type
!= COP_AWCAP_TYPE_PIN_COMPLEX
)) {
2173 ctl
= hdaudio_afg_control_amp_get(sc
, w
->w_nid
,
2174 HDAUDIO_PINDIR_IN
, index
, 1);
2176 if (HDAUDIO_CONTROL_GIVE(ctl
) & need
)
2177 ctl
->ctl_audiomask
|= (1 << audiodev
);
2179 ctl
->ctl_paudiomask
|= (1 << audiodev
);
2180 need
&= ~HDAUDIO_CONTROL_GIVE(ctl
);
2184 /* If widget has own audiodev, don't traverse it. */
2185 if (w
->w_audiodev
>= 0 && depth
> 0)
2188 /* We must not traverse pins */
2189 if ((w
->w_type
== COP_AWCAP_TYPE_AUDIO_INPUT
||
2190 w
->w_type
== COP_AWCAP_TYPE_PIN_COMPLEX
) && depth
> 0)
2193 /* Record that this widget exports such signal */
2194 w
->w_audiomask
|= (1 << audiodev
);
2197 * If signals mixed, we can't assign controls further. Ignore this
2198 * on depth zero. Caller must know why. Ignore this for static
2199 * selectors if this input is selected.
2205 ctl
= hdaudio_afg_control_amp_get(sc
, w
->w_nid
,
2206 HDAUDIO_PINDIR_OUT
, -1, 1);
2208 if (HDAUDIO_CONTROL_GIVE(ctl
) & need
)
2209 ctl
->ctl_audiomask
|= (1 << audiodev
);
2211 ctl
->ctl_paudiomask
|= (1 << audiodev
);
2212 need
&= ~HDAUDIO_CONTROL_GIVE(ctl
);
2217 for (i
= sc
->sc_startnode
; i
< sc
->sc_endnode
; i
++) {
2218 wc
= hdaudio_afg_widget_lookup(sc
, i
);
2219 if (wc
== NULL
|| wc
->w_enable
== false)
2221 for (j
= 0; j
< wc
->w_nconns
; j
++) {
2222 if (wc
->w_connsenable
[j
] && wc
->w_conns
[j
] == nid
) {
2223 rneed
|= hdaudio_afg_control_source_amp(sc
,
2224 wc
->w_nid
, j
, audiodev
, ctlable
, depth
+ 1,
2235 hdaudio_afg_control_dest_amp(struct hdaudio_afg_softc
*sc
, int nid
,
2236 int audiodev
, int depth
, int need
)
2238 struct hdaudio_assoc
*as
= sc
->sc_assocs
;
2239 struct hdaudio_widget
*w
, *wc
;
2240 struct hdaudio_control
*ctl
;
2241 int i
, j
, consumers
;
2243 if (depth
> HDAUDIO_PARSE_MAXDEPTH
)
2246 w
= hdaudio_afg_widget_lookup(sc
, nid
);
2247 if (w
== NULL
|| w
->w_enable
== false)
2252 * If this node produces output for several consumers,
2256 for (i
= sc
->sc_startnode
; i
< sc
->sc_endnode
; i
++) {
2257 wc
= hdaudio_afg_widget_lookup(sc
, i
);
2258 if (wc
== NULL
|| wc
->w_enable
== false)
2260 for (j
= 0; j
< wc
->w_nconns
; j
++) {
2261 if (wc
->w_connsenable
[j
] &&
2262 wc
->w_conns
[j
] == nid
)
2267 * The only exception is if real HP redirection is configured
2268 * and this is a duplication point.
2269 * XXX: Not completely correct.
2271 if ((consumers
== 2 && (w
->w_bindas
< 0 ||
2272 as
[w
->w_bindas
].as_hpredir
< 0 ||
2273 as
[w
->w_bindas
].as_fakeredir
||
2274 (w
->w_bindseqmask
& (1 << 15)) == 0)) ||
2278 /* Else use its output mixer */
2279 ctl
= hdaudio_afg_control_amp_get(sc
, w
->w_nid
,
2280 HDAUDIO_PINDIR_OUT
, -1, 1);
2282 if (HDAUDIO_CONTROL_GIVE(ctl
) & need
)
2283 ctl
->ctl_audiomask
|= (1 << audiodev
);
2285 ctl
->ctl_paudiomask
|= (1 << audiodev
);
2286 need
&= ~HDAUDIO_CONTROL_GIVE(ctl
);
2290 /* We must not traverse pin */
2291 if (w
->w_type
== COP_AWCAP_TYPE_PIN_COMPLEX
&& depth
> 0)
2294 for (i
= 0; i
< w
->w_nconns
; i
++) {
2296 if (w
->w_connsenable
[i
] == false)
2298 ctl
= hdaudio_afg_control_amp_get(sc
, w
->w_nid
,
2299 HDAUDIO_PINDIR_IN
, i
, 1);
2301 if (HDAUDIO_CONTROL_GIVE(ctl
) & tneed
)
2302 ctl
->ctl_audiomask
|= (1 << audiodev
);
2304 ctl
->ctl_paudiomask
|= (1 << audiodev
);
2305 tneed
&= ~HDAUDIO_CONTROL_GIVE(ctl
);
2307 hdaudio_afg_control_dest_amp(sc
, w
->w_conns
[i
], audiodev
,
2313 hdaudio_afg_assign_mixers(struct hdaudio_afg_softc
*sc
)
2315 struct hdaudio_assoc
*as
= sc
->sc_assocs
;
2316 struct hdaudio_control
*ctl
;
2317 struct hdaudio_widget
*w
;
2320 /* Assign mixers to the tree */
2321 for (i
= sc
->sc_startnode
; i
< sc
->sc_endnode
; i
++) {
2322 w
= hdaudio_afg_widget_lookup(sc
, i
);
2323 if (w
== NULL
|| w
->w_enable
== FALSE
)
2325 if (w
->w_type
== COP_AWCAP_TYPE_AUDIO_OUTPUT
||
2326 w
->w_type
== COP_AWCAP_TYPE_BEEP_GENERATOR
||
2327 (w
->w_type
== COP_AWCAP_TYPE_PIN_COMPLEX
&&
2328 as
[w
->w_bindas
].as_dir
== HDAUDIO_PINDIR_IN
)) {
2329 if (w
->w_audiodev
< 0)
2331 hdaudio_afg_control_source_amp(sc
, w
->w_nid
, -1,
2332 w
->w_audiodev
, 1, 0, 1);
2333 } else if (w
->w_pflags
& HDAUDIO_ADC_MONITOR
) {
2334 if (w
->w_audiodev
< 0)
2336 if (hdaudio_afg_control_source_amp(sc
, w
->w_nid
, -1,
2337 w
->w_audiodev
, 1, 0, 1)) {
2338 /* If we are unable to control input monitor
2339 as source, try to control it as dest */
2340 hdaudio_afg_control_dest_amp(sc
, w
->w_nid
,
2341 w
->w_audiodev
, 0, 1);
2343 } else if (w
->w_type
== COP_AWCAP_TYPE_AUDIO_INPUT
) {
2344 hdaudio_afg_control_dest_amp(sc
, w
->w_nid
,
2345 HDAUDIO_MIXER_RECLEV
, 0, 1);
2346 } else if (w
->w_type
== COP_AWCAP_TYPE_PIN_COMPLEX
&&
2347 as
[w
->w_bindas
].as_dir
== HDAUDIO_PINDIR_OUT
) {
2348 hdaudio_afg_control_dest_amp(sc
, w
->w_nid
,
2349 HDAUDIO_MIXER_VOLUME
, 0, 1);
2352 /* Treat unrequired as possible */
2354 for (i
= 0; i
< sc
->sc_nctls
; i
++) {
2355 ctl
= &sc
->sc_ctls
[i
];
2356 if (ctl
->ctl_audiomask
== 0)
2357 ctl
->ctl_audiomask
= ctl
->ctl_paudiomask
;
2362 hdaudio_afg_build_mixers(struct hdaudio_afg_softc
*sc
)
2364 struct hdaudio_mixer
*mx
;
2365 struct hdaudio_control
*ctl
, *masterctl
= NULL
;
2366 uint32_t audiomask
= 0;
2368 int i
, j
, index
= 0;
2370 int ctrlcnt
[HDAUDIO_MIXER_NRDEVICES
];
2372 memset(ctrlcnt
, 0, sizeof(ctrlcnt
));
2374 /* Count the number of required mixers */
2375 for (i
= 0; i
< sc
->sc_nctls
; i
++) {
2376 ctl
= &sc
->sc_ctls
[i
];
2377 if (ctl
->ctl_enable
== false ||
2378 ctl
->ctl_audiomask
== 0)
2380 audiomask
|= ctl
->ctl_audiomask
;
2386 /* XXXJDM TODO: softvol */
2387 /* Declare master volume if needed */
2388 if ((audiomask
& (HDAUDIO_MASK(VOLUME
) | HDAUDIO_MASK(PCM
))) ==
2389 HDAUDIO_MASK(PCM
)) {
2390 audiomask
|= HDAUDIO_MASK(VOLUME
);
2391 for (i
= 0; i
< sc
->sc_nctls
; i
++) {
2392 if (sc
->sc_ctls
[i
].ctl_audiomask
== HDAUDIO_MASK(PCM
)) {
2393 masterctl
= &sc
->sc_ctls
[i
];
2395 if (masterctl
->ctl_mute
)
2402 /* Make room for mixer classes */
2403 nmixers
+= (HDAUDIO_MIXER_CLASS_LAST
+ 1);
2405 /* count DACs and ADCs for selectors */
2407 for (i
= 0; i
< sc
->sc_nassocs
; i
++) {
2408 if (sc
->sc_assocs
[i
].as_enable
== false)
2410 if (sc
->sc_assocs
[i
].as_dir
== HDAUDIO_PINDIR_OUT
)
2412 else if (sc
->sc_assocs
[i
].as_dir
== HDAUDIO_PINDIR_IN
)
2416 /* Make room for selectors */
2422 hda_trace(sc
, " need %d mixers (3 classes%s)\n",
2423 nmixers
, masterctl
? " + fake master" : "");
2425 /* Allocate memory for the mixers */
2426 mx
= kmem_zalloc(nmixers
* sizeof(*mx
), KM_SLEEP
);
2427 sc
->sc_nmixers
= nmixers
;
2429 /* Build class mixers */
2430 for (i
= 0; i
<= HDAUDIO_MIXER_CLASS_LAST
; i
++) {
2431 mx
[index
].mx_ctl
= NULL
;
2432 mx
[index
].mx_di
.index
= index
;
2433 mx
[index
].mx_di
.type
= AUDIO_MIXER_CLASS
;
2434 mx
[index
].mx_di
.mixer_class
= i
;
2435 mx
[index
].mx_di
.next
= mx
[index
].mx_di
.prev
= AUDIO_MIXER_LAST
;
2437 case HDAUDIO_MIXER_CLASS_OUTPUTS
:
2438 strcpy(mx
[index
].mx_di
.label
.name
, AudioCoutputs
);
2440 case HDAUDIO_MIXER_CLASS_INPUTS
:
2441 strcpy(mx
[index
].mx_di
.label
.name
, AudioCinputs
);
2443 case HDAUDIO_MIXER_CLASS_RECORD
:
2444 strcpy(mx
[index
].mx_di
.label
.name
, AudioCrecord
);
2450 /* Shadow master control */
2451 if (masterctl
!= NULL
) {
2452 mx
[index
].mx_ctl
= masterctl
;
2453 mx
[index
].mx_di
.index
= index
;
2454 mx
[index
].mx_di
.type
= AUDIO_MIXER_VALUE
;
2455 mx
[index
].mx_di
.prev
= mx
[index
].mx_di
.next
= AUDIO_MIXER_LAST
;
2456 mx
[index
].mx_di
.un
.v
.num_channels
= 2; /* XXX */
2457 mx
[index
].mx_di
.mixer_class
= HDAUDIO_MIXER_CLASS_OUTPUTS
;
2458 mx
[index
].mx_di
.un
.v
.delta
= 256 / (masterctl
->ctl_step
+ 1);
2459 strcpy(mx
[index
].mx_di
.label
.name
, AudioNmaster
);
2460 strcpy(mx
[index
].mx_di
.un
.v
.units
.name
, AudioNvolume
);
2461 hda_trace(sc
, " adding outputs.%s\n",
2462 mx
[index
].mx_di
.label
.name
);
2464 if (masterctl
->ctl_mute
) {
2465 mx
[index
] = mx
[index
- 1];
2466 mx
[index
].mx_di
.index
= index
;
2467 mx
[index
].mx_di
.type
= AUDIO_MIXER_ENUM
;
2468 mx
[index
].mx_di
.prev
= mx
[index
].mx_di
.next
= AUDIO_MIXER_LAST
;
2469 strcpy(mx
[index
].mx_di
.label
.name
, AudioNmaster
"." AudioNmute
);
2470 mx
[index
].mx_di
.un
.e
.num_mem
= 2;
2471 strcpy(mx
[index
].mx_di
.un
.e
.member
[0].label
.name
, AudioNoff
);
2472 mx
[index
].mx_di
.un
.e
.member
[0].ord
= 0;
2473 strcpy(mx
[index
].mx_di
.un
.e
.member
[1].label
.name
, AudioNon
);
2474 mx
[index
].mx_di
.un
.e
.member
[1].ord
= 1;
2479 /* Build volume mixers */
2480 for (i
= 0; i
< sc
->sc_nctls
; i
++) {
2483 ctl
= &sc
->sc_ctls
[i
];
2484 if (ctl
->ctl_enable
== false ||
2485 ctl
->ctl_audiomask
== 0)
2487 audiodev
= ffs(ctl
->ctl_audiomask
) - 1;
2488 mx
[index
].mx_ctl
= ctl
;
2489 mx
[index
].mx_di
.index
= index
;
2490 mx
[index
].mx_di
.type
= AUDIO_MIXER_VALUE
;
2491 mx
[index
].mx_di
.prev
= mx
[index
].mx_di
.next
= AUDIO_MIXER_LAST
;
2492 mx
[index
].mx_di
.un
.v
.num_channels
= 2; /* XXX */
2493 mx
[index
].mx_di
.un
.v
.delta
= 256 / (ctl
->ctl_step
+ 1);
2494 if (ctrlcnt
[audiodev
] > 0)
2495 snprintf(mx
[index
].mx_di
.label
.name
,
2496 sizeof(mx
[index
].mx_di
.label
.name
),
2498 hdaudio_afg_mixer_names
[audiodev
],
2499 ctrlcnt
[audiodev
] + 1);
2501 strcpy(mx
[index
].mx_di
.label
.name
,
2502 hdaudio_afg_mixer_names
[audiodev
]);
2503 ctrlcnt
[audiodev
]++;
2506 case HDAUDIO_MIXER_VOLUME
:
2507 case HDAUDIO_MIXER_BASS
:
2508 case HDAUDIO_MIXER_TREBLE
:
2509 case HDAUDIO_MIXER_OGAIN
:
2510 mx
[index
].mx_di
.mixer_class
=
2511 HDAUDIO_MIXER_CLASS_OUTPUTS
;
2512 hda_trace(sc
, " adding outputs.%s\n",
2513 mx
[index
].mx_di
.label
.name
);
2515 case HDAUDIO_MIXER_MIC
:
2516 case HDAUDIO_MIXER_MONITOR
:
2517 mx
[index
].mx_di
.mixer_class
=
2518 HDAUDIO_MIXER_CLASS_RECORD
;
2519 hda_trace(sc
, " adding record.%s\n",
2520 mx
[index
].mx_di
.label
.name
);
2523 mx
[index
].mx_di
.mixer_class
=
2524 HDAUDIO_MIXER_CLASS_INPUTS
;
2525 hda_trace(sc
, " adding inputs.%s\n",
2526 mx
[index
].mx_di
.label
.name
);
2529 strcpy(mx
[index
].mx_di
.un
.v
.units
.name
, AudioNvolume
);
2533 if (ctl
->ctl_mute
) {
2534 mx
[index
] = mx
[index
- 1];
2535 mx
[index
].mx_di
.index
= index
;
2536 mx
[index
].mx_di
.type
= AUDIO_MIXER_ENUM
;
2537 mx
[index
].mx_di
.prev
= mx
[index
].mx_di
.next
= AUDIO_MIXER_LAST
;
2538 snprintf(mx
[index
].mx_di
.label
.name
,
2539 sizeof(mx
[index
].mx_di
.label
.name
),
2541 mx
[index
- 1].mx_di
.label
.name
);
2542 mx
[index
].mx_di
.un
.e
.num_mem
= 2;
2543 strcpy(mx
[index
].mx_di
.un
.e
.member
[0].label
.name
, AudioNoff
);
2544 mx
[index
].mx_di
.un
.e
.member
[0].ord
= 0;
2545 strcpy(mx
[index
].mx_di
.un
.e
.member
[1].label
.name
, AudioNon
);
2546 mx
[index
].mx_di
.un
.e
.member
[1].ord
= 1;
2553 mx
[index
].mx_ctl
= NULL
;
2554 mx
[index
].mx_di
.index
= index
;
2555 mx
[index
].mx_di
.type
= AUDIO_MIXER_SET
;
2556 mx
[index
].mx_di
.mixer_class
= HDAUDIO_MIXER_CLASS_OUTPUTS
;
2557 mx
[index
].mx_di
.prev
= mx
[index
].mx_di
.next
= AUDIO_MIXER_LAST
;
2558 strcpy(mx
[index
].mx_di
.label
.name
, "dacsel"); /* AudioNselect */
2559 mx
[index
].mx_di
.un
.s
.num_mem
= ndac
;
2560 for (i
= 0, j
= 0; i
< sc
->sc_nassocs
; i
++) {
2561 if (sc
->sc_assocs
[i
].as_enable
== false)
2563 if (sc
->sc_assocs
[i
].as_dir
!= HDAUDIO_PINDIR_OUT
)
2565 mx
[index
].mx_di
.un
.s
.member
[j
].mask
= 1 << i
;
2566 sprintf(mx
[index
].mx_di
.un
.s
.member
[j
].label
.name
,
2575 mx
[index
].mx_ctl
= NULL
;
2576 mx
[index
].mx_di
.index
= index
;
2577 mx
[index
].mx_di
.type
= AUDIO_MIXER_SET
;
2578 mx
[index
].mx_di
.mixer_class
= HDAUDIO_MIXER_CLASS_RECORD
;
2579 mx
[index
].mx_di
.prev
= mx
[index
].mx_di
.next
= AUDIO_MIXER_LAST
;
2580 strcpy(mx
[index
].mx_di
.label
.name
, AudioNsource
);
2581 mx
[index
].mx_di
.un
.s
.num_mem
= nadc
;
2582 for (i
= 0, j
= 0; i
< sc
->sc_nassocs
; i
++) {
2583 if (sc
->sc_assocs
[i
].as_enable
== false)
2585 if (sc
->sc_assocs
[i
].as_dir
!= HDAUDIO_PINDIR_IN
)
2587 mx
[index
].mx_di
.un
.s
.member
[j
].mask
= 1 << i
;
2588 sprintf(mx
[index
].mx_di
.un
.s
.member
[j
].label
.name
,
2599 hdaudio_afg_commit(struct hdaudio_afg_softc
*sc
)
2601 struct hdaudio_widget
*w
;
2602 uint32_t gdata
, gmask
, gdir
;
2603 int commitgpio
, numgpio
;
2606 /* Commit controls */
2607 hdaudio_afg_control_commit(sc
);
2609 /* Commit selectors, pins, and EAPD */
2610 for (i
= 0; i
< sc
->sc_nwidgets
; i
++) {
2611 w
= &sc
->sc_widgets
[i
];
2612 if (w
->w_selconn
== -1)
2614 if (w
->w_nconns
> 0)
2615 hdaudio_afg_widget_connection_select(w
, w
->w_selconn
);
2616 if (w
->w_type
== COP_AWCAP_TYPE_PIN_COMPLEX
)
2617 hdaudio_command(sc
->sc_codec
, w
->w_nid
,
2618 CORB_SET_PIN_WIDGET_CONTROL
, w
->w_pin
.ctrl
);
2619 if (w
->w_p
.eapdbtl
!= 0xffffffff)
2620 hdaudio_command(sc
->sc_codec
, w
->w_nid
,
2621 CORB_SET_EAPD_BTL_ENABLE
, w
->w_p
.eapdbtl
);
2624 gdata
= gmask
= gdir
= commitgpio
= 0;
2625 numgpio
= COP_GPIO_COUNT_NUM_GPIO(sc
->sc_p
.gpio_cnt
);
2627 hda_trace(sc
, "found %d GPIOs\n", numgpio
);
2629 for (i
= 0; i
< numgpio
&& i
< 8; i
++) {
2630 if (commitgpio
== 0)
2639 hda_trace(sc
, "GPIO commit: data=%08X mask=%08X dir=%08X\n",
2640 gdata
, gmask
, gdir
);
2641 hdaudio_command(sc
->sc_codec
, sc
->sc_nid
,
2642 CORB_SET_GPIO_ENABLE_MASK
, gmask
);
2643 hdaudio_command(sc
->sc_codec
, sc
->sc_nid
,
2644 CORB_SET_GPIO_DIRECTION
, gdir
);
2645 hdaudio_command(sc
->sc_codec
, sc
->sc_nid
,
2646 CORB_SET_GPIO_DATA
, gdata
);
2651 hdaudio_afg_stream_connect(struct hdaudio_afg_softc
*sc
, int mode
)
2653 struct hdaudio_assoc
*as
= sc
->sc_assocs
;
2654 struct hdaudio_widget
*w
;
2656 int tag
, chn
, maxchan
, c
;
2659 KASSERT(mode
== AUMODE_PLAY
|| mode
== AUMODE_RECORD
);
2661 dfmt
= COP_DIGITAL_CONVCTRL1_DIGEN
; /* TODO: AC3 */
2663 if (mode
== AUMODE_PLAY
)
2664 fmt
= hdaudio_stream_param(sc
->sc_audiodev
.ad_playback
,
2667 fmt
= hdaudio_stream_param(sc
->sc_audiodev
.ad_capture
,
2670 for (i
= 0; i
< sc
->sc_nassocs
; i
++) {
2671 if (as
[i
].as_enable
== false)
2674 if (mode
== AUMODE_PLAY
&& as
[i
].as_dir
!= HDAUDIO_PINDIR_OUT
)
2676 if (mode
== AUMODE_RECORD
&& as
[i
].as_dir
!= HDAUDIO_PINDIR_IN
)
2679 fmt
&= ~HDAUDIO_FMT_CHAN_MASK
;
2680 if (as
[i
].as_dir
== HDAUDIO_PINDIR_OUT
&&
2681 sc
->sc_audiodev
.ad_playback
!= NULL
) {
2682 tag
= hdaudio_stream_tag(sc
->sc_audiodev
.ad_playback
);
2683 fmt
|= HDAUDIO_FMT_CHAN(sc
->sc_pparam
.channels
);
2684 maxchan
= sc
->sc_pparam
.channels
;
2685 } else if (as
[i
].as_dir
== HDAUDIO_PINDIR_IN
&&
2686 sc
->sc_audiodev
.ad_capture
!= NULL
) {
2687 tag
= hdaudio_stream_tag(sc
->sc_audiodev
.ad_capture
);
2688 fmt
|= HDAUDIO_FMT_CHAN(sc
->sc_rparam
.channels
);
2689 maxchan
= sc
->sc_rparam
.channels
;
2692 if (as
[i
].as_dir
== HDAUDIO_PINDIR_OUT
) {
2693 fmt
|= HDAUDIO_FMT_CHAN(sc
->sc_pchan
);
2694 maxchan
= sc
->sc_pchan
;
2696 fmt
|= HDAUDIO_FMT_CHAN(sc
->sc_rchan
);
2697 maxchan
= sc
->sc_rchan
;
2702 for (j
= 0; j
< HDAUDIO_MAXPINS
; j
++) {
2703 if (as
[i
].as_dacs
[j
] == 0)
2705 w
= hdaudio_afg_widget_lookup(sc
, as
[i
].as_dacs
[j
]);
2706 if (w
== NULL
|| w
->w_enable
== FALSE
)
2708 if (as
[i
].as_hpredir
>= 0 && i
== as
[i
].as_pincnt
)
2712 c
= (tag
<< 4) | chn
;
2714 if (as
[i
].as_activated
== false)
2717 hdaudio_command(sc
->sc_codec
, w
->w_nid
,
2718 CORB_SET_CONVERTER_FORMAT
, fmt
);
2719 if (w
->w_p
.aw_cap
& COP_AWCAP_DIGITAL
)
2720 hdaudio_command(sc
->sc_codec
, w
->w_nid
,
2721 CORB_SET_DIGITAL_CONVERTER_CONTROL_1
, dfmt
);
2722 hdaudio_command(sc
->sc_codec
, w
->w_nid
,
2723 CORB_SET_CONVERTER_STREAM_CHANNEL
, c
);
2724 chn
+= (w
->w_p
.aw_cap
& COP_AWCAP_STEREO
) ? 2 : 1;
2730 hdaudio_afg_stream_intr(struct hdaudio_stream
*st
)
2732 struct hdaudio_audiodev
*ad
= st
->st_cookie
;
2736 sts
= hda_read1(ad
->ad_sc
->sc_host
, HDAUDIO_SD_STS(st
->st_shift
));
2737 hda_write1(ad
->ad_sc
->sc_host
, HDAUDIO_SD_STS(st
->st_shift
),
2738 HDAUDIO_STS_DESE
| HDAUDIO_STS_FIFOE
| HDAUDIO_STS_BCIS
);
2740 //if (sts & HDAUDIO_STS_BCIS) {
2741 if (st
== ad
->ad_playback
&& ad
->ad_playbackintr
) {
2742 ad
->ad_playbackintr(ad
->ad_playbackintrarg
);
2744 } else if (st
== ad
->ad_capture
&& ad
->ad_captureintr
) {
2745 ad
->ad_captureintr(ad
->ad_captureintrarg
);
2754 hdaudio_afg_assoc_count_channels(struct hdaudio_afg_softc
*sc
,
2755 struct hdaudio_assoc
*as
, enum hdaudio_pindir dir
)
2757 struct hdaudio_widget
*w
;
2759 int i
, dacmapsz
= sizeof(*dacmap
) * sc
->sc_endnode
;
2762 if (as
->as_enable
== false || as
->as_dir
!= dir
)
2765 dacmap
= kmem_zalloc(dacmapsz
, KM_SLEEP
);
2769 for (i
= 0; i
< HDAUDIO_MAXPINS
; i
++)
2771 dacmap
[as
->as_dacs
[i
]] = 1;
2773 for (i
= 1; i
< sc
->sc_endnode
; i
++) {
2776 w
= hdaudio_afg_widget_lookup(sc
, i
);
2777 if (w
== NULL
|| w
->w_enable
== false)
2779 nchans
+= (w
->w_p
.aw_cap
& COP_AWCAP_STEREO
) ? 2 : 1;
2782 kmem_free(dacmap
, dacmapsz
);
2788 hdaudio_afg_rate_supported(struct hdaudio_afg_softc
*sc
, u_int frequency
)
2790 uint32_t caps
= sc
->sc_p
.pcm_size_rate
;
2792 #define ISFREQOK(shift) ((caps & (1 << (shift))) ? true : false)
2793 switch (frequency
) {
2807 return true; /* Must be supported by all codecs */
2815 return ISFREQOK(10);
2817 return ISFREQOK(11);
2825 hdaudio_afg_bits_supported(struct hdaudio_afg_softc
*sc
, u_int bits
)
2827 uint32_t caps
= sc
->sc_p
.pcm_size_rate
;
2828 #define ISBITSOK(shift) ((caps & (1 << (shift))) ? true : false)
2831 return ISBITSOK(16);
2833 return ISBITSOK(17);
2835 return ISBITSOK(18);
2837 return ISBITSOK(19);
2839 return ISBITSOK(20);
2847 hdaudio_afg_probe_encoding(struct hdaudio_afg_softc
*sc
,
2848 u_int minrate
, u_int maxrate
, u_int validbits
, u_int precision
, bool force
)
2850 struct audio_format f
;
2852 if (!force
&& hdaudio_afg_bits_supported(sc
, validbits
) == false)
2855 memset(&f
, 0, sizeof(f
));
2856 f
.driver_data
= NULL
;
2858 f
.encoding
= AUDIO_ENCODING_SLINEAR_LE
;
2859 f
.validbits
= validbits
;
2860 f
.precision
= precision
;
2863 f
.frequency_type
= 0;
2864 f
.frequency
[0] = minrate
;
2865 f
.frequency
[1] = maxrate
;
2867 #define HDAUDIO_INITFMT(ch, chmask) \
2869 f.channels = (ch); \
2870 f.channel_mask = (chmask); \
2872 if (sc->sc_pchan >= (ch)) \
2873 f.mode |= AUMODE_PLAY; \
2874 if (sc->sc_rchan >= (ch)) \
2875 f.mode |= AUMODE_RECORD; \
2877 hdaudio_afg_append_formats(&sc->sc_audiodev, &f); \
2880 /* Commented out, otherwise monaural samples play through left
2883 /* HDAUDIO_INITFMT(1, AUFMT_MONAURAL); */
2884 HDAUDIO_INITFMT(2, AUFMT_STEREO
);
2885 HDAUDIO_INITFMT(4, AUFMT_SURROUND4
);
2886 HDAUDIO_INITFMT(6, AUFMT_DOLBY_5_1
);
2887 HDAUDIO_INITFMT(8, AUFMT_SURROUND_7_1
);
2889 #undef HDAUDIO_INITFMT
2896 hdaudio_afg_configure_encodings(struct hdaudio_afg_softc
*sc
)
2898 const u_int possible_rates
[] = {
2899 8000, 11025, 16000, 22050, 32000, 44100,
2900 48000, 88200, 96000, 176500, 192000, /* 384000, */
2902 struct hdaudio_assoc
*as
= sc
->sc_assocs
;
2903 struct audio_format f
;
2904 u_int minrate
, maxrate
;
2907 sc
->sc_pchan
= sc
->sc_rchan
= 0;
2908 minrate
= maxrate
= 0;
2910 for (nchan
= 0, i
= 0; i
< sc
->sc_nassocs
; i
++) {
2911 nchan
= hdaudio_afg_assoc_count_channels(sc
, &as
[i
],
2912 HDAUDIO_PINDIR_OUT
);
2913 if (nchan
> sc
->sc_pchan
)
2914 sc
->sc_pchan
= nchan
;
2916 for (nchan
= 0, i
= 0; i
< sc
->sc_nassocs
; i
++) {
2917 nchan
= hdaudio_afg_assoc_count_channels(sc
, &as
[i
],
2919 if (nchan
> sc
->sc_rchan
)
2920 sc
->sc_rchan
= nchan
;
2922 hda_print(sc
, "%dch/%dch", sc
->sc_pchan
, sc
->sc_rchan
);
2924 for (i
= 0; __arraycount(possible_rates
); i
++)
2925 if (hdaudio_afg_rate_supported(sc
, possible_rates
[i
])) {
2926 minrate
= possible_rates
[i
];
2929 for (i
= __arraycount(possible_rates
) - 1; i
>= 0; i
--)
2930 if (hdaudio_afg_rate_supported(sc
, possible_rates
[i
])) {
2931 maxrate
= possible_rates
[i
];
2934 KASSERT(minrate
> 0 && maxrate
> 0); /* impossible */
2935 hda_print1(sc
, " %uHz", minrate
);
2936 if (minrate
!= maxrate
)
2937 hda_print1(sc
, "-%uHz", maxrate
);
2939 if (hdaudio_afg_probe_encoding(sc
, minrate
, maxrate
, 8, 16, false))
2940 hda_print1(sc
, " 8/16");
2941 if (hdaudio_afg_probe_encoding(sc
, minrate
, maxrate
, 16, 16, false))
2942 hda_print1(sc
, " 16/16");
2943 if (hdaudio_afg_probe_encoding(sc
, minrate
, maxrate
, 20, 32, false))
2944 hda_print1(sc
, " 20/32");
2945 if (hdaudio_afg_probe_encoding(sc
, minrate
, maxrate
, 24, 32, false))
2946 hda_print1(sc
, " 24/32");
2947 if (hdaudio_afg_probe_encoding(sc
, minrate
, maxrate
, 32, 32, false))
2948 hda_print1(sc
, " 32/32");
2950 if (sc
->sc_audiodev
.ad_nformats
== 0) {
2951 hdaudio_afg_probe_encoding(sc
, minrate
, maxrate
, 16, 16, true);
2952 hda_print1(sc
, " 16/16*");
2957 * MI audio assumes that at least one playback and one capture format
2958 * is reported by the hw driver; until this bug is resolved just
2959 * report 2ch capabilities if the function group does not support
2962 if (sc
->sc_rchan
== 0 || sc
->sc_pchan
== 0) {
2963 memset(&f
, 0, sizeof(f
));
2964 f
.driver_data
= NULL
;
2966 f
.encoding
= AUDIO_ENCODING_SLINEAR_LE
;
2970 f
.channel_mask
= AUFMT_STEREO
;
2971 f
.frequency_type
= 0;
2972 f
.frequency
[0] = f
.frequency
[1] = 48000;
2973 f
.mode
= AUMODE_PLAY
|AUMODE_RECORD
;
2974 hdaudio_afg_append_formats(&sc
->sc_audiodev
, &f
);
2977 hda_print1(sc
, "\n");
2981 hdaudio_afg_hp_switch_handler(void *opaque
)
2983 struct hdaudio_afg_softc
*sc
= opaque
;
2984 struct hdaudio_assoc
*as
= sc
->sc_assocs
;
2985 struct hdaudio_widget
*w
;
2989 if (!device_is_active(sc
->sc_dev
))
2992 for (i
= 0; i
< sc
->sc_nassocs
; i
++)
2993 for (j
= 0; j
< HDAUDIO_MAXPINS
; j
++) {
2994 w
= hdaudio_afg_widget_lookup(sc
, as
[i
].as_pins
[j
]);
2995 if (w
== NULL
|| w
->w_enable
== false)
2997 if (w
->w_type
!= COP_AWCAP_TYPE_PIN_COMPLEX
)
2999 if (COP_CFG_DEFAULT_DEVICE(w
->w_pin
.config
) !=
3002 res
|= hdaudio_command(sc
->sc_codec
, as
[i
].as_pins
[j
],
3003 CORB_GET_PIN_SENSE
, 0) &
3004 COP_GET_PIN_SENSE_PRESENSE_DETECT
;
3007 for (i
= 0; i
< sc
->sc_nassocs
; i
++)
3008 for (j
= 0; j
< HDAUDIO_MAXPINS
; j
++) {
3009 w
= hdaudio_afg_widget_lookup(sc
, as
[i
].as_pins
[j
]);
3010 if (w
== NULL
|| w
->w_enable
== false)
3012 if (w
->w_type
!= COP_AWCAP_TYPE_PIN_COMPLEX
)
3014 switch (COP_CFG_DEFAULT_DEVICE(w
->w_pin
.config
)) {
3015 case COP_DEVICE_HP_OUT
:
3016 if (res
& COP_GET_PIN_SENSE_PRESENSE_DETECT
)
3017 w
->w_pin
.ctrl
|= COP_PWC_OUT_ENABLE
;
3019 w
->w_pin
.ctrl
&= ~COP_PWC_OUT_ENABLE
;
3020 hdaudio_command(sc
->sc_codec
, w
->w_nid
,
3021 CORB_SET_PIN_WIDGET_CONTROL
, w
->w_pin
.ctrl
);
3023 case COP_DEVICE_LINE_OUT
:
3024 case COP_DEVICE_SPEAKER
:
3025 case COP_DEVICE_AUX
:
3026 if (res
& COP_GET_PIN_SENSE_PRESENSE_DETECT
)
3027 w
->w_pin
.ctrl
&= ~COP_PWC_OUT_ENABLE
;
3029 w
->w_pin
.ctrl
|= COP_PWC_OUT_ENABLE
;
3030 hdaudio_command(sc
->sc_codec
, w
->w_nid
,
3031 CORB_SET_PIN_WIDGET_CONTROL
, w
->w_pin
.ctrl
);
3039 callout_schedule(&sc
->sc_jack_callout
, HDAUDIO_HP_SENSE_PERIOD
);
3043 hdaudio_afg_hp_switch_init(struct hdaudio_afg_softc
*sc
)
3045 struct hdaudio_assoc
*as
= sc
->sc_assocs
;
3046 struct hdaudio_widget
*w
;
3047 bool enable
= false;
3050 for (i
= 0; i
< sc
->sc_nassocs
; i
++) {
3051 if (as
[i
].as_hpredir
< 0)
3053 w
= hdaudio_afg_widget_lookup(sc
, as
[i
].as_pins
[15]);
3054 if (w
== NULL
|| w
->w_enable
== false)
3056 if (w
->w_type
!= COP_AWCAP_TYPE_PIN_COMPLEX
)
3058 if (!(w
->w_pin
.cap
& COP_PINCAP_PRESENSE_DETECT_CAPABLE
))
3060 if (COP_CFG_MISC(w
->w_pin
.config
) & 1) {
3061 hda_trace(sc
, "no jack detection on pin %02X\n",
3067 if (w
->w_p
.aw_cap
& COP_AWCAP_UNSOL_CAPABLE
)
3068 hdaudio_command(sc
->sc_codec
, w
->w_nid
,
3069 CORB_SET_UNSOLICITED_RESPONSE
,
3070 COP_SET_UNSOLICITED_RESPONSE_ENABLE
|
3071 HDAUDIO_UNSOLTAG_EVENT_HP
);
3073 hda_trace(sc
, "jack detect supported on pin %02X [%s]\n",
3075 (w
->w_p
.aw_cap
& COP_AWCAP_UNSOL_CAPABLE
) ?
3079 sc
->sc_jack_polling
= true;
3080 hdaudio_afg_hp_switch_handler(sc
);
3082 hda_trace(sc
, "jack detect not enabled\n");
3086 hdaudio_afg_attach(device_t parent
, device_t self
, void *opaque
)
3088 struct hdaudio_afg_softc
*sc
= device_private(self
);
3089 audio_params_t defparams
;
3090 prop_dictionary_t args
= opaque
;
3098 callout_init(&sc
->sc_jack_callout
, 0);
3099 callout_setfunc(&sc
->sc_jack_callout
,
3100 hdaudio_afg_hp_switch_handler
, sc
);
3102 if (!pmf_device_register(self
, hdaudio_afg_suspend
, hdaudio_afg_resume
))
3103 aprint_error_dev(self
, "couldn't establish power handler\n");
3105 sc
->sc_config
= prop_dictionary_get(args
, "pin-config");
3106 if (sc
->sc_config
&& prop_object_type(sc
->sc_config
) != PROP_TYPE_ARRAY
)
3107 sc
->sc_config
= NULL
;
3108 hda_print1(sc
, " (%s configuration)\n", sc
->sc_config
?
3109 "custom" : "firmware");
3111 rv
= prop_dictionary_get_uint64(args
, "function-group", &fgptr
);
3112 if (rv
== false || fgptr
== 0) {
3113 hda_error(sc
, "missing function-group property\n");
3116 rv
= prop_dictionary_get_uint8(args
, "node-id", &nid
);
3117 if (rv
== false || nid
== 0) {
3118 hda_error(sc
, "missing node-id property\n");
3121 prop_dictionary_get_uint16(args
, "vendor-id", &sc
->sc_vendor
);
3122 prop_dictionary_get_uint16(args
, "product-id", &sc
->sc_product
);
3125 sc
->sc_fg
= (struct hdaudio_function_group
*)(vaddr_t
)fgptr
;
3126 sc
->sc_codec
= sc
->sc_fg
->fg_codec
;
3127 KASSERT(sc
->sc_codec
!= NULL
);
3128 sc
->sc_host
= sc
->sc_codec
->co_host
;
3129 KASSERT(sc
->sc_host
!= NULL
);
3131 hda_debug(sc
, "parsing widgets\n");
3132 hdaudio_afg_parse(sc
);
3133 hda_debug(sc
, "parsing controls\n");
3134 hdaudio_afg_control_parse(sc
);
3135 hda_debug(sc
, "disabling non-audio devices\n");
3136 hdaudio_afg_disable_nonaudio(sc
);
3137 hda_debug(sc
, "disabling useless devices\n");
3138 hdaudio_afg_disable_useless(sc
);
3139 hda_debug(sc
, "parsing associations\n");
3140 hdaudio_afg_assoc_parse(sc
);
3141 hda_debug(sc
, "building tree\n");
3142 hdaudio_afg_build_tree(sc
);
3143 hda_debug(sc
, "disabling unassociated pins\n");
3144 hdaudio_afg_disable_unassoc(sc
);
3145 hda_debug(sc
, "disabling unselected pins\n");
3146 hdaudio_afg_disable_unsel(sc
);
3147 hda_debug(sc
, "disabling useless devices\n");
3148 hdaudio_afg_disable_useless(sc
);
3149 hda_debug(sc
, "disabling cross-associated pins\n");
3150 hdaudio_afg_disable_crossassoc(sc
);
3151 hda_debug(sc
, "disabling useless devices\n");
3152 hdaudio_afg_disable_useless(sc
);
3154 hda_debug(sc
, "assigning mixer names to sound sources\n");
3155 hdaudio_afg_assign_names(sc
);
3156 hda_debug(sc
, "assigning mixers to device tree\n");
3157 hdaudio_afg_assign_mixers(sc
);
3159 hda_debug(sc
, "preparing pin controls\n");
3160 hdaudio_afg_prepare_pin_controls(sc
);
3161 hda_debug(sc
, "commiting settings\n");
3162 hdaudio_afg_commit(sc
);
3164 hda_debug(sc
, "setup jack sensing\n");
3165 hdaudio_afg_hp_switch_init(sc
);
3167 hda_debug(sc
, "building mixer controls\n");
3168 hdaudio_afg_build_mixers(sc
);
3170 hdaudio_afg_dump(sc
);
3171 if (0) hdaudio_afg_widget_pin_dump(sc
);
3172 hdaudio_afg_assoc_dump(sc
);
3174 hda_debug(sc
, "configuring encodings\n");
3175 sc
->sc_audiodev
.ad_sc
= sc
;
3176 hdaudio_afg_configure_encodings(sc
);
3177 err
= auconv_create_encodings(sc
->sc_audiodev
.ad_formats
,
3178 sc
->sc_audiodev
.ad_nformats
, &sc
->sc_audiodev
.ad_encodings
);
3180 hda_error(sc
, "couldn't create encodings\n");
3184 hda_debug(sc
, "reserving streams\n");
3185 sc
->sc_audiodev
.ad_capture
= hdaudio_stream_establish(sc
->sc_host
,
3186 HDAUDIO_STREAM_ISS
, hdaudio_afg_stream_intr
, &sc
->sc_audiodev
);
3187 sc
->sc_audiodev
.ad_playback
= hdaudio_stream_establish(sc
->sc_host
,
3188 HDAUDIO_STREAM_OSS
, hdaudio_afg_stream_intr
, &sc
->sc_audiodev
);
3190 hda_debug(sc
, "connecting streams\n");
3191 defparams
.channels
= 2;
3192 defparams
.sample_rate
= 48000;
3193 defparams
.precision
= defparams
.validbits
= 16;
3194 defparams
.encoding
= AUDIO_ENCODING_SLINEAR_LE
;
3195 sc
->sc_pparam
= sc
->sc_rparam
= defparams
;
3196 hdaudio_afg_stream_connect(sc
, AUMODE_PLAY
);
3197 hdaudio_afg_stream_connect(sc
, AUMODE_RECORD
);
3199 hda_debug(sc
, "attaching audio device\n");
3200 sc
->sc_audiodev
.ad_audiodev
= audio_attach_mi(&hdaudio_afg_hw_if
,
3201 &sc
->sc_audiodev
, self
);
3205 hdaudio_afg_detach(device_t self
, int flags
)
3207 struct hdaudio_afg_softc
*sc
= device_private(self
);
3208 struct hdaudio_widget
*w
= sc
->sc_widgets
;
3209 struct hdaudio_assoc
*as
= sc
->sc_assocs
;
3210 struct hdaudio_control
*ctl
= sc
->sc_ctls
;
3211 struct hdaudio_mixer
*mx
= sc
->sc_mixers
;
3213 callout_halt(&sc
->sc_jack_callout
, NULL
);
3214 callout_destroy(&sc
->sc_jack_callout
);
3217 prop_object_release(sc
->sc_config
);
3218 if (sc
->sc_audiodev
.ad_audiodev
)
3219 config_detach(sc
->sc_audiodev
.ad_audiodev
, flags
);
3220 if (sc
->sc_audiodev
.ad_encodings
)
3221 auconv_delete_encodings(sc
->sc_audiodev
.ad_encodings
);
3222 if (sc
->sc_audiodev
.ad_playback
)
3223 hdaudio_stream_disestablish(sc
->sc_audiodev
.ad_playback
);
3224 if (sc
->sc_audiodev
.ad_capture
)
3225 hdaudio_stream_disestablish(sc
->sc_audiodev
.ad_capture
);
3227 kmem_free(w
, sc
->sc_nwidgets
* sizeof(*w
));
3229 kmem_free(as
, sc
->sc_nassocs
* sizeof(*as
));
3231 kmem_free(ctl
, sc
->sc_nctls
* sizeof(*ctl
));
3233 kmem_free(mx
, sc
->sc_nmixers
* sizeof(*mx
));
3235 pmf_device_deregister(self
);
3241 hdaudio_afg_childdet(device_t self
, device_t child
)
3243 struct hdaudio_afg_softc
*sc
= device_private(self
);
3245 if (child
== sc
->sc_audiodev
.ad_audiodev
)
3246 sc
->sc_audiodev
.ad_audiodev
= NULL
;
3250 hdaudio_afg_suspend(device_t self
, pmf_qual_t qual
)
3252 struct hdaudio_afg_softc
*sc
= device_private(self
);
3254 callout_halt(&sc
->sc_jack_callout
, NULL
);
3260 hdaudio_afg_resume(device_t self
, pmf_qual_t qual
)
3262 struct hdaudio_afg_softc
*sc
= device_private(self
);
3265 hdaudio_command(sc
->sc_codec
, sc
->sc_nid
,
3266 CORB_SET_POWER_STATE
, COP_POWER_STATE_D0
);
3268 for (nid
= sc
->sc_startnode
; nid
< sc
->sc_endnode
; nid
++)
3269 hdaudio_command(sc
->sc_codec
, nid
,
3270 CORB_SET_POWER_STATE
, COP_POWER_STATE_D0
);
3273 hdaudio_afg_commit(sc
);
3274 hdaudio_afg_stream_connect(sc
, AUMODE_PLAY
);
3275 hdaudio_afg_stream_connect(sc
, AUMODE_RECORD
);
3277 if (sc
->sc_jack_polling
)
3278 hdaudio_afg_hp_switch_handler(sc
);
3284 hdaudio_afg_query_encoding(void *opaque
, struct audio_encoding
*ae
)
3286 struct hdaudio_audiodev
*ad
= opaque
;
3287 return auconv_query_encoding(ad
->ad_encodings
, ae
);
3291 hdaudio_afg_set_params(void *opaque
, int setmode
, int usemode
,
3292 audio_params_t
*play
, audio_params_t
*rec
,
3293 stream_filter_list_t
*pfil
, stream_filter_list_t
*rfil
)
3295 struct hdaudio_audiodev
*ad
= opaque
;
3298 if (play
&& (setmode
& AUMODE_PLAY
)) {
3299 index
= auconv_set_converter(ad
->ad_formats
, ad
->ad_nformats
,
3300 AUMODE_PLAY
, play
, TRUE
, pfil
);
3303 ad
->ad_sc
->sc_pparam
= *play
;
3304 hdaudio_afg_stream_connect(ad
->ad_sc
, AUMODE_PLAY
);
3306 if (rec
&& (setmode
& AUMODE_RECORD
)) {
3307 index
= auconv_set_converter(ad
->ad_formats
, ad
->ad_nformats
,
3308 AUMODE_RECORD
, rec
, TRUE
, rfil
);
3311 ad
->ad_sc
->sc_rparam
= *rec
;
3312 hdaudio_afg_stream_connect(ad
->ad_sc
, AUMODE_RECORD
);
3318 hdaudio_afg_round_blocksize(void *opaque
, int blksize
, int mode
,
3319 const audio_params_t
*param
)
3321 struct hdaudio_audiodev
*ad
= opaque
;
3322 struct hdaudio_stream
*st
;
3325 st
= (mode
== AUMODE_PLAY
) ? ad
->ad_playback
: ad
->ad_capture
;
3327 hda_trace(ad
->ad_sc
,
3328 "round_blocksize called for invalid stream\n");
3332 /* Multiple of 128 */
3337 bufsize
= st
->st_data
.dma_size
;
3338 if (bufsize
> HDAUDIO_BDL_MAX
* blksize
) {
3339 blksize
= bufsize
/ HDAUDIO_BDL_MAX
;
3341 blksize
= (blksize
+ 128) & ~128;
3348 hdaudio_afg_commit_settings(void *opaque
)
3354 hdaudio_afg_halt_output(void *opaque
)
3356 struct hdaudio_audiodev
*ad
= opaque
;
3358 hdaudio_stream_stop(ad
->ad_playback
);
3364 hdaudio_afg_halt_input(void *opaque
)
3366 struct hdaudio_audiodev
*ad
= opaque
;
3368 hdaudio_stream_stop(ad
->ad_capture
);
3374 hdaudio_afg_getdev(void *opaque
, struct audio_device
*audiodev
)
3376 *audiodev
= hdaudio_afg_audio_device
;
3381 hdaudio_afg_set_port(void *opaque
, mixer_ctrl_t
*mc
)
3383 struct hdaudio_audiodev
*ad
= opaque
;
3384 struct hdaudio_afg_softc
*sc
= ad
->ad_sc
;
3385 struct hdaudio_mixer
*mx
;
3386 struct hdaudio_control
*ctl
;
3389 if (mc
->dev
< 0 || mc
->dev
>= sc
->sc_nmixers
)
3391 mx
= &sc
->sc_mixers
[mc
->dev
];
3394 if (mx
->mx_di
.type
!= AUDIO_MIXER_SET
)
3396 if (mx
->mx_di
.mixer_class
!= HDAUDIO_MIXER_CLASS_OUTPUTS
&&
3397 mx
->mx_di
.mixer_class
!= HDAUDIO_MIXER_CLASS_RECORD
)
3399 for (i
= 0; i
< sc
->sc_nassocs
; i
++) {
3400 if (sc
->sc_assocs
[i
].as_dir
!= HDAUDIO_PINDIR_OUT
&&
3401 mx
->mx_di
.mixer_class
==
3402 HDAUDIO_MIXER_CLASS_OUTPUTS
)
3404 if (sc
->sc_assocs
[i
].as_dir
!= HDAUDIO_PINDIR_IN
&&
3405 mx
->mx_di
.mixer_class
==
3406 HDAUDIO_MIXER_CLASS_RECORD
)
3408 sc
->sc_assocs
[i
].as_activated
=
3409 (mc
->un
.mask
& (1 << i
)) ? true : false;
3411 hdaudio_afg_stream_connect(ad
->ad_sc
,
3412 mx
->mx_di
.mixer_class
== HDAUDIO_MIXER_CLASS_OUTPUTS
?
3413 AUMODE_PLAY
: AUMODE_RECORD
);
3417 switch (mx
->mx_di
.type
) {
3418 case AUDIO_MIXER_VALUE
:
3419 if (ctl
->ctl_step
== 0)
3420 divisor
= 128; /* ??? - just avoid div by 0 */
3422 divisor
= 255 / ctl
->ctl_step
;
3424 hdaudio_afg_control_amp_set(ctl
, HDAUDIO_AMP_MUTE_NONE
,
3425 mc
->un
.value
.level
[AUDIO_MIXER_LEVEL_LEFT
] / divisor
,
3426 mc
->un
.value
.level
[AUDIO_MIXER_LEVEL_RIGHT
] / divisor
);
3428 case AUDIO_MIXER_ENUM
:
3429 hdaudio_afg_control_amp_set(ctl
,
3430 mc
->un
.ord
? HDAUDIO_AMP_MUTE_ALL
: HDAUDIO_AMP_MUTE_NONE
,
3431 ctl
->ctl_left
, ctl
->ctl_right
);
3441 hdaudio_afg_get_port(void *opaque
, mixer_ctrl_t
*mc
)
3443 struct hdaudio_audiodev
*ad
= opaque
;
3444 struct hdaudio_afg_softc
*sc
= ad
->ad_sc
;
3445 struct hdaudio_mixer
*mx
;
3446 struct hdaudio_control
*ctl
;
3450 if (mc
->dev
< 0 || mc
->dev
>= sc
->sc_nmixers
)
3452 mx
= &sc
->sc_mixers
[mc
->dev
];
3455 if (mx
->mx_di
.type
!= AUDIO_MIXER_SET
)
3457 if (mx
->mx_di
.mixer_class
!= HDAUDIO_MIXER_CLASS_OUTPUTS
&&
3458 mx
->mx_di
.mixer_class
!= HDAUDIO_MIXER_CLASS_RECORD
)
3460 for (i
= 0; i
< sc
->sc_nassocs
; i
++) {
3461 if (sc
->sc_assocs
[i
].as_enable
== false)
3463 if (sc
->sc_assocs
[i
].as_activated
== false)
3465 if (sc
->sc_assocs
[i
].as_dir
== HDAUDIO_PINDIR_OUT
&&
3466 mx
->mx_di
.mixer_class
==
3467 HDAUDIO_MIXER_CLASS_OUTPUTS
)
3469 if (sc
->sc_assocs
[i
].as_dir
== HDAUDIO_PINDIR_IN
&&
3470 mx
->mx_di
.mixer_class
==
3471 HDAUDIO_MIXER_CLASS_RECORD
)
3478 switch (mx
->mx_di
.type
) {
3479 case AUDIO_MIXER_VALUE
:
3480 if (ctl
->ctl_step
== 0)
3481 factor
= 128; /* ??? - just avoid div by 0 */
3483 factor
= 255 / ctl
->ctl_step
;
3485 mc
->un
.value
.level
[AUDIO_MIXER_LEVEL_LEFT
] = ctl
->ctl_left
* factor
;
3486 mc
->un
.value
.level
[AUDIO_MIXER_LEVEL_RIGHT
] = ctl
->ctl_right
* factor
;
3488 case AUDIO_MIXER_ENUM
:
3489 mc
->un
.ord
= (ctl
->ctl_muted
|| ctl
->ctl_forcemute
) ? 1 : 0;
3498 hdaudio_afg_query_devinfo(void *opaque
, mixer_devinfo_t
*di
)
3500 struct hdaudio_audiodev
*ad
= opaque
;
3501 struct hdaudio_afg_softc
*sc
= ad
->ad_sc
;
3503 if (di
->index
>= sc
->sc_nmixers
)
3506 *di
= sc
->sc_mixers
[di
->index
].mx_di
;
3512 hdaudio_afg_allocm(void *opaque
, int direction
, size_t size
,
3513 struct malloc_type
*type
, int flags
)
3515 struct hdaudio_audiodev
*ad
= opaque
;
3516 struct hdaudio_stream
*st
;
3519 st
= (direction
== AUMODE_PLAY
) ? ad
->ad_playback
: ad
->ad_capture
;
3523 if (st
->st_data
.dma_valid
== true)
3524 hda_error(ad
->ad_sc
, "WARNING: allocm leak\n");
3526 st
->st_data
.dma_size
= size
;
3527 err
= hdaudio_dma_alloc(st
->st_host
, &st
->st_data
,
3528 BUS_DMA_COHERENT
| BUS_DMA_NOCACHE
);
3529 if (err
|| st
->st_data
.dma_valid
== false)
3532 return DMA_KERNADDR(&st
->st_data
);
3536 hdaudio_afg_freem(void *opaque
, void *addr
, struct malloc_type
*type
)
3538 struct hdaudio_audiodev
*ad
= opaque
;
3539 struct hdaudio_stream
*st
;
3541 if (addr
== DMA_KERNADDR(&ad
->ad_playback
->st_data
))
3542 st
= ad
->ad_playback
;
3543 else if (addr
== DMA_KERNADDR(&ad
->ad_capture
->st_data
))
3544 st
= ad
->ad_capture
;
3548 hdaudio_dma_free(st
->st_host
, &st
->st_data
);
3552 hdaudio_afg_round_buffersize(void *opaque
, int direction
, size_t bufsize
)
3554 /* Multiple of 128 */
3562 hdaudio_afg_mappage(void *opaque
, void *addr
, off_t off
, int prot
)
3564 struct hdaudio_audiodev
*ad
= opaque
;
3565 struct hdaudio_stream
*st
;
3567 if (addr
== DMA_KERNADDR(&ad
->ad_playback
->st_data
))
3568 st
= ad
->ad_playback
;
3569 else if (addr
== DMA_KERNADDR(&ad
->ad_capture
->st_data
))
3570 st
= ad
->ad_capture
;
3574 if (st
->st_data
.dma_valid
== false)
3577 return bus_dmamem_mmap(st
->st_host
->sc_dmat
, st
->st_data
.dma_segs
,
3578 st
->st_data
.dma_nsegs
, off
, prot
, BUS_DMA_WAITOK
);
3582 hdaudio_afg_get_props(void *opaque
)
3584 struct hdaudio_audiodev
*ad
= opaque
;
3587 if (ad
->ad_playback
)
3588 props
|= AUDIO_PROP_PLAYBACK
;
3590 props
|= AUDIO_PROP_CAPTURE
;
3591 if (ad
->ad_playback
&& ad
->ad_capture
) {
3592 props
|= AUDIO_PROP_FULLDUPLEX
;
3593 props
|= AUDIO_PROP_INDEPENDENT
;
3596 /* TODO: AUDIO_PROP_MMAP */
3602 hdaudio_afg_trigger_output(void *opaque
, void *start
, void *end
, int blksize
,
3603 void (*intr
)(void *), void *intrarg
, const audio_params_t
*param
)
3605 struct hdaudio_audiodev
*ad
= opaque
;
3608 if (ad
->ad_playback
== NULL
)
3610 if (ad
->ad_playback
->st_data
.dma_valid
== false)
3613 ad
->ad_playbackintr
= intr
;
3614 ad
->ad_playbackintrarg
= intrarg
;
3616 dmasize
= (char *)end
- (char *)start
;
3617 ad
->ad_sc
->sc_pparam
= *param
;
3618 hdaudio_afg_stream_connect(ad
->ad_sc
, AUMODE_PLAY
);
3619 hdaudio_stream_start(ad
->ad_playback
, blksize
, dmasize
, param
);
3625 hdaudio_afg_trigger_input(void *opaque
, void *start
, void *end
, int blksize
,
3626 void (*intr
)(void *), void *intrarg
, const audio_params_t
*param
)
3628 struct hdaudio_audiodev
*ad
= opaque
;
3631 if (ad
->ad_capture
== NULL
)
3633 if (ad
->ad_capture
->st_data
.dma_valid
== false)
3636 ad
->ad_captureintr
= intr
;
3637 ad
->ad_captureintrarg
= intrarg
;
3639 dmasize
= (char *)end
- (char *)start
;
3640 ad
->ad_sc
->sc_rparam
= *param
;
3641 hdaudio_afg_stream_connect(ad
->ad_sc
, AUMODE_RECORD
);
3642 hdaudio_stream_start(ad
->ad_capture
, blksize
, dmasize
, param
);
3648 hdaudio_afg_widget_info(void *opaque
, prop_dictionary_t request
,
3649 prop_dictionary_t response
)
3651 struct hdaudio_afg_softc
*sc
= opaque
;
3652 struct hdaudio_widget
*w
;
3653 prop_array_t connlist
;
3654 uint32_t config
, wcap
;
3659 if (prop_dictionary_get_uint16(request
, "index", &index
) == false)
3662 nid
= sc
->sc_startnode
+ index
;
3663 if (nid
>= sc
->sc_endnode
)
3666 w
= hdaudio_afg_widget_lookup(sc
, nid
);
3669 wcap
= hda_get_wparam(w
, PIN_CAPABILITIES
);
3670 config
= hdaudio_command(sc
->sc_codec
, w
->w_nid
,
3671 CORB_GET_CONFIGURATION_DEFAULT
, 0);
3672 prop_dictionary_set_cstring_nocopy(response
, "name", w
->w_name
);
3673 prop_dictionary_set_bool(response
, "enable", w
->w_enable
);
3674 prop_dictionary_set_uint8(response
, "nid", w
->w_nid
);
3675 prop_dictionary_set_uint8(response
, "type", w
->w_type
);
3676 prop_dictionary_set_uint32(response
, "config", config
);
3677 prop_dictionary_set_uint32(response
, "cap", wcap
);
3678 if (w
->w_nconns
== 0)
3680 connlist
= prop_array_create();
3681 for (i
= 0; i
< w
->w_nconns
; i
++) {
3682 if (w
->w_conns
[i
] == 0)
3684 prop_array_add(connlist
,
3685 prop_number_create_unsigned_integer(w
->w_conns
[i
]));
3687 prop_dictionary_set(response
, "connlist", connlist
);
3688 prop_object_release(connlist
);
3693 hdaudio_afg_codec_info(void *opaque
, prop_dictionary_t request
,
3694 prop_dictionary_t response
)
3696 struct hdaudio_afg_softc
*sc
= opaque
;
3697 prop_dictionary_set_uint16(response
, "vendor-id",
3699 prop_dictionary_set_uint16(response
, "product-id",
3705 hdaudio_afg_dev_ioctl(void *opaque
, u_long cmd
, void *addr
, int flag
, lwp_t
*l
)
3707 struct hdaudio_audiodev
*ad
= opaque
;
3708 struct hdaudio_afg_softc
*sc
= ad
->ad_sc
;
3709 struct plistref
*pref
= addr
;
3710 prop_dictionary_t request
, response
;
3713 response
= prop_dictionary_create();
3714 if (response
== NULL
)
3717 err
= prop_dictionary_copyin_ioctl(pref
, cmd
, &request
);
3719 prop_object_release(response
);
3724 case HDAUDIO_AFG_WIDGET_INFO
:
3725 err
= hdaudio_afg_widget_info(sc
, request
, response
);
3727 case HDAUDIO_AFG_CODEC_INFO
:
3728 err
= hdaudio_afg_codec_info(sc
, request
, response
);
3736 err
= prop_dictionary_copyout_ioctl(pref
, cmd
, response
);
3739 prop_object_release(response
);
3740 prop_object_release(request
);