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