xref: /haiku/src/add-ons/kernel/drivers/audio/hda/hda_codec.cpp (revision b617a7b410c05275effb95f4b2f5608359d9b7b9)
1 /*
2  * Copyright 2007-2012, Haiku, Inc. All Rights Reserved.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *		Ithamar Adema, ithamar AT unet DOT nl
7  *		Axel Dörfler, axeld@pinc-software.de
8  *		Jérôme Duval, korli@users.berlios.de
9  */
10 
11 
12 #include "driver.h"
13 #include "hda_codec_defs.h"
14 
15 
16 #undef TRACE
17 #define TRACE_CODEC
18 #ifdef TRACE_CODEC
19 #	define TRACE(a...) dprintf(a)
20 #else
21 #	define TRACE(a...)
22 #endif
23 #define ERROR(a...) dprintf(a)
24 
25 
26 #define HDA_ALL 0xffffffff
27 #define HDA_QUIRK_GPIO_COUNT	8
28 #define HDA_QUIRK_GPIO0		(1 << 0)
29 #define HDA_QUIRK_GPIO1		(1 << 1)
30 #define HDA_QUIRK_GPIO2		(1 << 2)
31 #define HDA_QUIRK_GPIO3		(1 << 3)
32 #define HDA_QUIRK_GPIO4		(1 << 4)
33 #define HDA_QUIRK_GPIO5		(1 << 5)
34 #define HDA_QUIRK_GPIO6		(1 << 6)
35 #define HDA_QUIRK_GPIO7		(1 << 7)
36 #define HDA_QUIRK_IVREF50	(1 << 8)
37 #define HDA_QUIRK_IVREF80	(1 << 9)
38 #define HDA_QUIRK_IVREF100	(1 << 10)
39 #define HDA_QUIRK_OVREF50	(1 << 11)
40 #define HDA_QUIRK_OVREF80	(1 << 12)
41 #define HDA_QUIRK_OVREF100	(1 << 13)
42 #define HDA_QUIRK_IVREF (HDA_QUIRK_IVREF50 | HDA_QUIRK_IVREF80 \
43 	| HDA_QUIRK_IVREF100)
44 #define HDA_QUIRK_OVREF (HDA_QUIRK_OVREF50 | HDA_QUIRK_OVREF80 \
45 	| HDA_QUIRK_OVREF100)
46 
47 
48 #define ANALOGDEVICES_VENDORID		0x11d4
49 #define CIRRUSLOGIC_VENDORID		0x1013
50 #define CONEXANT_VENDORID			0x14f1
51 #define IDT_VENDORID				0x111d
52 #define REALTEK_VENDORID			0x10ec
53 #define SIGMATEL_VENDORID			0x8384
54 
55 
56 static const char* kPortConnector[] = {
57 	"Jack", "None", "Fixed", "Dual"
58 };
59 
60 static const char* kDefaultDevice[] = {
61 	"Line out", "Speaker", "HP out", "CD", "SPDIF out", "Digital other out",
62 	"Modem line side", "Modem hand side", "Line in", "AUX", "Mic in",
63 	"Telephony", "SPDIF in", "Digital other in", "Reserved", "Other"
64 };
65 
66 static const char* kConnectionType[] = {
67 	"N/A", "1/8\"", "1/4\"", "ATAPI internal", "RCA", "Optical",
68 	"Other digital", "Other analog", "Multichannel analog (DIN)",
69 	"XLR/Professional", "RJ-11 (modem)", "Combination", "-", "-", "-", "Other"
70 };
71 
72 static const char* kJackColor[] = {
73 	"N/A", "Black", "Grey", "Blue", "Green", "Red", "Orange", "Yellow",
74 	"Purple", "Pink", "-", "-", "-", "-", "White", "Other"
75 };
76 
77 static const struct {
78 	uint32 subsystem_vendor_id, subsystem_id;
79 	uint32 codec_vendor_id, codec_id;
80 	uint32 quirks, nonquirks;
81 } kCodecQuirks[] = {
82 	{ HDA_ALL, HDA_ALL, HDA_ALL, HDA_ALL, HDA_QUIRK_IVREF, 0 },
83 	{ HDA_ALL, HDA_ALL, HDA_ALL, HDA_ALL, HDA_QUIRK_IVREF, 0 },
84 	{ 0x10de, 0xcb79, CIRRUSLOGIC_VENDORID, 0x4206,
85 		HDA_QUIRK_GPIO1 | HDA_QUIRK_GPIO3, 0 },		// MacBook Pro 5.5
86 	{ 0x8384, 0x7680, SIGMATEL_VENDORID, 0x7680,
87 		HDA_QUIRK_GPIO0 | HDA_QUIRK_GPIO1, 0},		// Apple Intel Mac
88 	{ 0x106b, 0x00a1, REALTEK_VENDORID, 0x0885,
89 		HDA_QUIRK_GPIO0 | HDA_QUIRK_OVREF50, 0},	// MacBook
90 	{ 0x106b, 0x00a3, REALTEK_VENDORID, 0x0885,
91 		HDA_QUIRK_GPIO0, 0},						// MacBook
92 	{ HDA_ALL, HDA_ALL, IDT_VENDORID, 0x76b2, HDA_QUIRK_GPIO0, 0},
93 };
94 
95 
96 static const char*
97 get_widget_type_name(hda_widget_type type)
98 {
99 	switch (type) {
100 		case WT_AUDIO_OUTPUT:
101 			return "Audio output";
102 		case WT_AUDIO_INPUT:
103 			return "Audio input";
104 		case WT_AUDIO_MIXER:
105 			return "Audio mixer";
106 		case WT_AUDIO_SELECTOR:
107 			return "Audio selector";
108 		case WT_PIN_COMPLEX:
109 			return "Pin complex";
110 		case WT_POWER:
111 			return "Power";
112 		case WT_VOLUME_KNOB:
113 			return "Volume knob";
114 		case WT_BEEP_GENERATOR:
115 			return "Beep generator";
116 		case WT_VENDOR_DEFINED:
117 			return "Vendor defined";
118 		default:
119 			return "Unknown";
120 	}
121 }
122 
123 
124 const char*
125 get_widget_location(uint32 location)
126 {
127 	switch (location >> 4) {
128 		case 0:
129 		case 2:
130 			switch (location & 0xf) {
131 				case 2:
132 					return "Front";
133 				case 3:
134 					return "Left";
135 				case 4:
136 					return "Right";
137 				case 5:
138 					return "Top";
139 				case 6:
140 					return "Bottom";
141 				case 7:
142 					return "Rear panel";
143 				case 8:
144 					return "Drive bay";
145 				case 0:
146 				case 1:
147 				default:
148 					return NULL;
149 			}
150 		case 1:
151 			switch (location & 0xf) {
152 				case 7:
153 					return "Riser";
154 				case 8:
155 					return "HDMI";
156 				default:
157 					return NULL;
158 			}
159 		case 3:
160 			switch (location & 0xf) {
161 				case 6:
162 					return "Bottom";
163 				case 7:
164 					return "Inside lid";
165 				case 8:
166 					return "Outside lid";
167 				default:
168 					return NULL;
169 			}
170 	}
171 	return NULL;
172 }
173 
174 
175 static void
176 dump_widget_audio_capabilities(uint32 capabilities)
177 {
178 	static const struct {
179 		uint32		flag;
180 		const char*	name;
181 	} kFlags[] = {
182 		{AUDIO_CAP_CP_CAPS, "CP caps"},
183 		{AUDIO_CAP_LEFT_RIGHT_SWAP, "L-R swap"},
184 		{AUDIO_CAP_POWER_CONTROL, "Power"},
185 		{AUDIO_CAP_DIGITAL, "Digital"},
186 		{AUDIO_CAP_CONNECTION_LIST, "Conn. list"},
187 		{AUDIO_CAP_UNSOLICITED_RESPONSES, "Unsol. responses"},
188 		{AUDIO_CAP_PROCESSING_CONTROLS, "Proc widget"},
189 		{AUDIO_CAP_STRIPE, "Stripe"},
190 		{AUDIO_CAP_FORMAT_OVERRIDE, "Format override"},
191 		{AUDIO_CAP_AMPLIFIER_OVERRIDE, "Amplifier override"},
192 		{AUDIO_CAP_OUTPUT_AMPLIFIER, "Out amplifier"},
193 		{AUDIO_CAP_INPUT_AMPLIFIER, "In amplifier"},
194 		{AUDIO_CAP_STEREO, "Stereo"},
195 	};
196 
197 	char buffer[256];
198 	int offset = 0;
199 
200 	for (uint32 j = 0; j < sizeof(kFlags) / sizeof(kFlags[0]); j++) {
201 		if ((capabilities & kFlags[j].flag) != 0)
202 			offset += sprintf(buffer + offset, "[%s] ", kFlags[j].name);
203 	}
204 
205 	if (offset != 0)
206 		TRACE("\t%s\n", buffer);
207 }
208 
209 
210 static void
211 dump_widget_inputs(hda_widget& widget)
212 {
213 	// dump connections
214 
215 	char buffer[256];
216 	int offset = 0;
217 
218 	for (uint32 i = 0; i < widget.num_inputs; i++) {
219 		int32 input = widget.inputs[i];
220 
221 		if ((int32)i != widget.active_input)
222 			offset += sprintf(buffer + offset, "%ld ", input);
223 		else
224 			offset += sprintf(buffer + offset, "<%ld> ", input);
225 	}
226 
227 	if (offset != 0)
228 		TRACE("\tInputs: %s\n", buffer);
229 }
230 
231 
232 static void
233 dump_widget_amplifier_capabilities(hda_widget& widget, bool input)
234 {
235 	uint32 capabilities;
236 	if (input)
237 		capabilities = widget.capabilities.input_amplifier;
238 	else
239 		capabilities = widget.capabilities.output_amplifier;
240 
241 	if (capabilities == 0)
242 		return;
243 
244 	TRACE("\t%s Amp: %sstep size: %f dB, # steps: %ld, offset to 0 dB: "
245 		"%ld\n", input ? "In" : "Out",
246 		(capabilities & AMP_CAP_MUTE) != 0 ? "supports mute, " : "",
247 		AMP_CAP_STEP_SIZE(capabilities),
248 		AMP_CAP_NUM_STEPS(capabilities),
249 		AMP_CAP_OFFSET(capabilities));
250 }
251 
252 
253 static void
254 dump_widget_pm_support(hda_widget& widget)
255 {
256 	TRACE("\tSupported power states: %s%s%s%s%s%s%s%s\n",
257 		widget.pm & POWER_STATE_D0 ? "D0 " : "",
258 		widget.pm & POWER_STATE_D1 ? "D1 " : "",
259 		widget.pm & POWER_STATE_D2 ? "D2 " : "",
260 		widget.pm & POWER_STATE_D3 ? "D3 " : "",
261 		widget.pm & POWER_STATE_D3COLD ? "D3COLD " : "",
262 		widget.pm & POWER_STATE_S3D3COLD ? "S3D3COLD " : "",
263 		widget.pm & POWER_STATE_CLKSTOP ? "CLKSTOP " : "",
264 		widget.pm & POWER_STATE_EPSS ? "EPSS " : "");
265 }
266 
267 
268 static void
269 dump_widget_stream_support(hda_widget& widget)
270 {
271 	TRACE("\tSupported formats: %s%s%s%s%s%s%s%s%s\n",
272 		widget.d.io.formats & B_FMT_8BIT_S ? "8bits " : "",
273 		widget.d.io.formats & B_FMT_16BIT ? "16bits " : "",
274 		widget.d.io.formats & B_FMT_20BIT ? "20bits " : "",
275 		widget.d.io.formats & B_FMT_24BIT ? "24bits " : "",
276 		widget.d.io.formats & B_FMT_32BIT ? "32bits " : "",
277 		widget.d.io.formats & B_FMT_FLOAT ? "float " : "",
278 		widget.d.io.formats & B_FMT_DOUBLE ? "double " : "",
279 		widget.d.io.formats & B_FMT_EXTENDED ? "extended " : "",
280 		widget.d.io.formats & B_FMT_BITSTREAM ? "bitstream " : "");
281 	TRACE("\tSupported rates: %s%s%s%s%s%s%s%s%s%s%s%s\n",
282 		widget.d.io.rates & B_SR_8000 ? "8khz " : "",
283 		widget.d.io.rates & B_SR_11025 ? "11khz " : "",
284 		widget.d.io.rates & B_SR_16000 ? "16khz " : "",
285 		widget.d.io.rates & B_SR_22050 ? "22khz " : "",
286 		widget.d.io.rates & B_SR_32000 ? "32khz " : "",
287 		widget.d.io.rates & B_SR_44100 ? "44khz " : "",
288 		widget.d.io.rates & B_SR_48000 ? "48khz " : "",
289 		widget.d.io.rates & B_SR_88200 ? "88khz " : "",
290 		widget.d.io.rates & B_SR_96000 ? "96khz " : "",
291 		widget.d.io.rates & B_SR_176400 ? "176khz " : "",
292 		widget.d.io.rates & B_SR_192000 ? "192khz " : "",
293 		widget.d.io.rates & B_SR_384000 ? "384khz " : "");
294 
295 }
296 
297 
298 static void
299 dump_pin_complex_capabilities(hda_widget& widget)
300 {
301 	TRACE("\t%s%s%s%s%s%s%s%s%s%s%s%s%s\n",
302 		widget.d.pin.capabilities & PIN_CAP_IMP_SENSE ? "[Imp Sense] " : "",
303 		widget.d.pin.capabilities & PIN_CAP_TRIGGER_REQ ? "[Trigger Req]" : "",
304 		widget.d.pin.capabilities & PIN_CAP_PRES_DETECT ? "[Pres Detect]" : "",
305 		widget.d.pin.capabilities & PIN_CAP_HP_DRIVE ? "[HP Drive]" : "",
306 		widget.d.pin.capabilities & PIN_CAP_OUTPUT ? "[Output]" : "",
307 		widget.d.pin.capabilities & PIN_CAP_INPUT ? "[Input]" : "",
308 		widget.d.pin.capabilities & PIN_CAP_BALANCE ? "[Balance]" : "",
309 		widget.d.pin.capabilities & PIN_CAP_VREF_CTRL_HIZ ? "[VRef HIZ]" : "",
310 		widget.d.pin.capabilities & PIN_CAP_VREF_CTRL_50 ? "[VRef 50]" : "",
311 		widget.d.pin.capabilities & PIN_CAP_VREF_CTRL_GROUND ? "[VRef Gr]" : "",
312 		widget.d.pin.capabilities & PIN_CAP_VREF_CTRL_80 ? "[VRef 80]" : "",
313 		widget.d.pin.capabilities & PIN_CAP_VREF_CTRL_100 ? "[VRef 100]" : "",
314 		widget.d.pin.capabilities & PIN_CAP_EAPD_CAP ? "[EAPD]" : "");
315 }
316 
317 
318 static void
319 dump_audiogroup_widgets(hda_audio_group* audioGroup)
320 {
321 	TRACE("\tAudiogroup:\n");
322 	// Iterate over all widgets and collect info
323 	for (uint32 i = 0; i < audioGroup->widget_count; i++) {
324 		hda_widget& widget = audioGroup->widgets[i];
325 		uint32 nodeID = audioGroup->widget_start + i;
326 
327 		TRACE("%ld: %s\n", nodeID, get_widget_type_name(widget.type));
328 
329 		switch (widget.type) {
330 			case WT_AUDIO_OUTPUT:
331 			case WT_AUDIO_INPUT:
332 				break;
333 
334 			case WT_PIN_COMPLEX:
335 				dump_pin_complex_capabilities(widget);
336 				break;
337 
338 			default:
339 				break;
340 		}
341 
342 		dump_widget_pm_support(widget);
343 		dump_widget_audio_capabilities(widget.capabilities.audio);
344 		dump_widget_amplifier_capabilities(widget, true);
345 		dump_widget_amplifier_capabilities(widget, false);
346 		dump_widget_inputs(widget);
347 	}
348 }
349 
350 
351 //	#pragma mark -
352 
353 
354 static void
355 hda_codec_get_quirks(hda_codec* codec)
356 {
357 	codec->quirks = 0;
358 
359 	uint32 subSystemID = codec->controller->pci_info.u.h0.subsystem_id;
360 	uint32 subSystemVendorID
361 		= codec->controller->pci_info.u.h0.subsystem_vendor_id;
362 
363 	for (uint32 i = 0;
364 			i < (sizeof(kCodecQuirks) / sizeof(kCodecQuirks[0])); i++) {
365 		if (kCodecQuirks[i].subsystem_id != HDA_ALL
366 			&& kCodecQuirks[i].subsystem_id != subSystemID)
367 			continue;
368 		if (kCodecQuirks[i].subsystem_vendor_id != HDA_ALL
369 			&& kCodecQuirks[i].subsystem_vendor_id != subSystemVendorID)
370 			continue;
371 		if (kCodecQuirks[i].codec_vendor_id != HDA_ALL
372 			&& kCodecQuirks[i].codec_vendor_id != codec->vendor_id)
373 			continue;
374 		if (kCodecQuirks[i].codec_id != HDA_ALL
375 			&& kCodecQuirks[i].codec_id != codec->product_id)
376 			continue;
377 
378 		codec->quirks |= kCodecQuirks[i].quirks;
379 		codec->quirks &= ~kCodecQuirks[i].nonquirks;
380 	}
381 }
382 
383 
384 static status_t
385 hda_get_pm_support(hda_codec* codec, uint32 nodeID, uint32* pm)
386 {
387 	corb_t verb = MAKE_VERB(codec->addr, nodeID, VID_GET_PARAMETER,
388 		PID_POWERSTATE_SUPPORT);
389 
390 	uint32 response;
391 	status_t status = hda_send_verbs(codec, &verb, &response, 1);
392 	if (status == B_OK)
393 		*pm = response & 0xf;
394 
395 	return status;
396 }
397 
398 
399 static status_t
400 hda_get_stream_support(hda_codec* codec, uint32 nodeID, uint32* formats,
401 	uint32* rates)
402 {
403 	corb_t verbs[2];
404 	uint32 resp[2];
405 	status_t status;
406 
407 	verbs[0] = MAKE_VERB(codec->addr, nodeID, VID_GET_PARAMETER,
408 		PID_STREAM_SUPPORT);
409 	verbs[1] = MAKE_VERB(codec->addr, nodeID, VID_GET_PARAMETER,
410 		PID_PCM_SUPPORT);
411 
412 	status = hda_send_verbs(codec, verbs, resp, 2);
413 	if (status != B_OK)
414 		return status;
415 
416 	*formats = 0;
417 	*rates = 0;
418 
419 	if ((resp[0] & (STREAM_FLOAT | STREAM_PCM)) != 0) {
420 		if (resp[1] & (1 << 0))
421 			*rates |= B_SR_8000;
422 		if (resp[1] & (1 << 1))
423 			*rates |= B_SR_11025;
424 		if (resp[1] & (1 << 2))
425 			*rates |= B_SR_16000;
426 		if (resp[1] & (1 << 3))
427 			*rates |= B_SR_22050;
428 		if (resp[1] & (1 << 4))
429 			*rates |= B_SR_32000;
430 		if (resp[1] & (1 << 5))
431 			*rates |= B_SR_44100;
432 		if (resp[1] & (1 << 6))
433 			*rates |= B_SR_48000;
434 		if (resp[1] & (1 << 7))
435 			*rates |= B_SR_88200;
436 		if (resp[1] & (1 << 8))
437 			*rates |= B_SR_96000;
438 		if (resp[1] & (1 << 9))
439 			*rates |= B_SR_176400;
440 		if (resp[1] & (1 << 10))
441 			*rates |= B_SR_192000;
442 		if (resp[1] & (1 << 11))
443 			*rates |= B_SR_384000;
444 
445 		if (resp[1] & PCM_8_BIT)
446 			*formats |= B_FMT_8BIT_S;
447 		if (resp[1] & PCM_16_BIT)
448 			*formats |= B_FMT_16BIT;
449 		if (resp[1] & PCM_20_BIT)
450 			*formats |= B_FMT_20BIT;
451 		if (resp[1] & PCM_24_BIT)
452 			*formats |= B_FMT_24BIT;
453 		if (resp[1] & PCM_32_BIT)
454 			*formats |= B_FMT_32BIT;
455 	}
456 	if ((resp[0] & STREAM_FLOAT) != 0)
457 		*formats |= B_FMT_FLOAT;
458 	if ((resp[0] & STREAM_AC3) != 0) {
459 		*formats |= B_FMT_BITSTREAM;
460 	}
461 
462 	return B_OK;
463 }
464 
465 
466 //	#pragma mark - widget functions
467 
468 
469 static status_t
470 hda_widget_get_pm_support(hda_audio_group* audioGroup, hda_widget* widget)
471 {
472 	return hda_get_pm_support(audioGroup->codec, widget->node_id, &widget->pm);
473 }
474 
475 
476 static status_t
477 hda_widget_get_stream_support(hda_audio_group* audioGroup, hda_widget* widget)
478 {
479 	if (audioGroup->widget.node_id != widget->node_id
480 		&& (widget->capabilities.audio & AUDIO_CAP_FORMAT_OVERRIDE) == 0) {
481 		// adopt capabilities of the audio group
482 		widget->d.io.formats = audioGroup->widget.d.io.formats;
483 		widget->d.io.rates = audioGroup->widget.d.io.rates;
484 		return B_OK;
485 	}
486 
487 	return hda_get_stream_support(audioGroup->codec, widget->node_id,
488 		&widget->d.io.formats, &widget->d.io.rates);
489 }
490 
491 
492 static status_t
493 hda_widget_get_amplifier_capabilities(hda_audio_group* audioGroup,
494 	hda_widget* widget)
495 {
496 	uint32 response;
497 	corb_t verb;
498 
499 	if ((widget->capabilities.audio & AUDIO_CAP_OUTPUT_AMPLIFIER) != 0
500 		|| audioGroup->widget.node_id == widget->node_id) {
501 		if ((widget->capabilities.audio & AUDIO_CAP_AMPLIFIER_OVERRIDE) != 0
502 			|| audioGroup->widget.node_id == widget->node_id) {
503 			verb = MAKE_VERB(audioGroup->codec->addr, widget->node_id,
504 				VID_GET_PARAMETER, PID_OUTPUT_AMPLIFIER_CAP);
505 			status_t status = hda_send_verbs(audioGroup->codec, &verb,
506 				&response, 1);
507 			if (status != B_OK)
508 				return status;
509 
510 			widget->capabilities.output_amplifier = response;
511 		} else {
512 			// adopt capabilities from the audio function group
513 			widget->capabilities.output_amplifier
514 				= audioGroup->widget.capabilities.output_amplifier;
515 		}
516 	}
517 
518 	if ((widget->capabilities.audio & AUDIO_CAP_INPUT_AMPLIFIER) != 0
519 		|| audioGroup->widget.node_id == widget->node_id) {
520 		if ((widget->capabilities.audio & AUDIO_CAP_AMPLIFIER_OVERRIDE
521 			|| audioGroup->widget.node_id == widget->node_id) != 0) {
522 			verb = MAKE_VERB(audioGroup->codec->addr, widget->node_id,
523 				VID_GET_PARAMETER, PID_INPUT_AMPLIFIER_CAP);
524 			status_t status = hda_send_verbs(audioGroup->codec, &verb,
525 				&response, 1);
526 			if (status != B_OK)
527 				return status;
528 
529 			widget->capabilities.input_amplifier = response;
530 		} else {
531 			// adopt capabilities from the audio function group
532 			widget->capabilities.input_amplifier
533 				= audioGroup->widget.capabilities.input_amplifier;
534 		}
535 	}
536 
537 	return B_OK;
538 }
539 
540 
541 hda_widget*
542 hda_audio_group_get_widget(hda_audio_group* audioGroup, uint32 nodeID)
543 {
544 	if (audioGroup->widget_start > nodeID
545 		|| audioGroup->widget_start + audioGroup->widget_count < nodeID)
546 		return NULL;
547 
548 	return &audioGroup->widgets[nodeID - audioGroup->widget_start];
549 }
550 
551 
552 static status_t
553 hda_widget_get_connections(hda_audio_group* audioGroup, hda_widget* widget)
554 {
555 	corb_t verb = MAKE_VERB(audioGroup->codec->addr, widget->node_id,
556 		VID_GET_PARAMETER, PID_CONNECTION_LIST_LENGTH);
557 	uint32 response;
558 
559 	if (hda_send_verbs(audioGroup->codec, &verb, &response, 1) != B_OK)
560 		return B_ERROR;
561 
562 	uint32 listEntries = response & 0x7f;
563 	bool longForm = (response & 0xf0) != 0;
564 
565 	if (listEntries == 0)
566 		return B_OK;
567 
568 #if 1
569 	if (widget->num_inputs > 1) {
570 		// Get currently active connection
571 		verb = MAKE_VERB(audioGroup->codec->addr, widget->node_id,
572 			VID_GET_CONNECTION_SELECT, 0);
573 		if (hda_send_verbs(audioGroup->codec, &verb, &response, 1) == B_OK)
574 			widget->active_input = response & 0xff;
575 	}
576 #endif
577 
578 	uint32 valuesPerEntry = longForm ? 2 : 4;
579 	uint32 shift = 32 / valuesPerEntry;
580 	uint32 rangeMask = (1 << (shift - 1));
581 	int32 previousInput = -1;
582 	uint32 numInputs = 0;
583 
584 	for (uint32 i = 0; i < listEntries; i++) {
585 		if ((i % valuesPerEntry) == 0) {
586 			// We get 2 or 4 answers per call depending on if we're
587 			// in short or long list mode
588 			verb = MAKE_VERB(audioGroup->codec->addr, widget->node_id,
589 				VID_GET_CONNECTION_LIST_ENTRY, i);
590 			if (hda_send_verbs(audioGroup->codec, &verb, &response, 1)
591 					!= B_OK) {
592 				ERROR("hda: Error parsing inputs for widget %ld!\n",
593 					widget->node_id);
594 				break;
595 			}
596 		}
597 
598 		int32 input = (response >> (shift * (i % valuesPerEntry)))
599 			& ((1 << shift) - 1);
600 
601 		if (input & rangeMask) {
602 			// found range
603 			input &= ~rangeMask;
604 
605 			if (input < previousInput || previousInput == -1) {
606 				ERROR("hda: invalid range from %ld to %ld\n", previousInput,
607 					input);
608 				continue;
609 			}
610 
611 			for (int32 rangeInput = previousInput + 1; rangeInput <= input
612 					&& numInputs < MAX_INPUTS; rangeInput++) {
613 				widget->inputs[numInputs++] = rangeInput;
614 			}
615 
616 			previousInput = -1;
617 		} else if (numInputs < MAX_INPUTS) {
618 			// standard value
619 			widget->inputs[numInputs++] = input;
620 			previousInput = input;
621 		}
622 	}
623 
624 	widget->num_inputs = numInputs;
625 
626 	if (widget->num_inputs == 1)
627 		widget->active_input = 0;
628 
629 	return B_OK;
630 }
631 
632 
633 static status_t
634 hda_widget_get_associations(hda_audio_group* audioGroup)
635 {
636 	uint32 index = 0;
637 	for (uint32 i = 0; i < MAX_ASSOCIATIONS; i++) {
638 		for (uint32 j = 0; j < audioGroup->widget_count; j++) {
639 			hda_widget& widget = audioGroup->widgets[j];
640 
641 			if (widget.type != WT_PIN_COMPLEX)
642 				continue;
643 			if (CONF_DEFAULT_ASSOCIATION(widget.d.pin.config) != i)
644 				continue;
645 			if (audioGroup->associations[index].pin_count == 0) {
646 				audioGroup->associations[index].index = index;
647 				audioGroup->associations[index].enabled = true;
648 			}
649 			uint32 sequence = CONF_DEFAULT_SEQUENCE(widget.d.pin.config);
650 			if (audioGroup->associations[index].pins[sequence] != 0) {
651 				audioGroup->associations[index].enabled = false;
652 			}
653 			audioGroup->associations[index].pins[sequence] = widget.node_id;
654 			audioGroup->associations[index].pin_count++;
655 			if (i == 15)
656 				index++;
657 		}
658 		if (i != 15 && audioGroup->associations[index].pin_count != 0)
659 			index++;
660 	}
661 	audioGroup->association_count = index;
662 
663 	return B_OK;
664 }
665 
666 
667 static uint32
668 hda_widget_prepare_pin_ctrl(hda_audio_group* audioGroup, hda_widget* widget,
669 	bool isOutput)
670 {
671 	uint32 ctrl = 0;
672 	if (isOutput)
673 		ctrl = PIN_ENABLE_HEAD_PHONE | PIN_ENABLE_OUTPUT;
674 	else
675 		ctrl = PIN_ENABLE_INPUT;
676 
677 	if (PIN_CAP_IS_VREF_CTRL_50_CAP(widget->d.pin.capabilities)
678 		&& (audioGroup->codec->quirks & (isOutput ? HDA_QUIRK_OVREF50
679 			: HDA_QUIRK_IVREF50))) {
680 		ctrl |= PIN_ENABLE_VREF_50;
681 		TRACE("%s vref 50 enabled\n", isOutput ? "output" : "input");
682 	}
683 	if (PIN_CAP_IS_VREF_CTRL_80_CAP(widget->d.pin.capabilities)
684 		&& (audioGroup->codec->quirks & (isOutput ? HDA_QUIRK_OVREF80
685 			: HDA_QUIRK_IVREF80))) {
686 		ctrl |= PIN_ENABLE_VREF_80;
687 		TRACE("%s vref 80 enabled\n", isOutput ? "output" : "input");
688 	}
689 	if (PIN_CAP_IS_VREF_CTRL_100_CAP(widget->d.pin.capabilities)
690 		&& (audioGroup->codec->quirks & (isOutput ? HDA_QUIRK_OVREF100
691 			: HDA_QUIRK_IVREF100))) {
692 		ctrl |= PIN_ENABLE_VREF_100;
693 		TRACE("%s vref 100 enabled\n", isOutput ? "output" : "input");
694 	}
695 
696 	return ctrl;
697 }
698 
699 
700 //	#pragma mark - audio group functions
701 
702 
703 static status_t
704 hda_codec_parse_audio_group(hda_audio_group* audioGroup)
705 {
706 	corb_t verbs[3];
707 	uint32 resp[3];
708 
709 	hda_codec* codec = audioGroup->codec;
710 	uint32 codec_id = (codec->vendor_id << 16) | codec->product_id;
711 	hda_widget_get_stream_support(audioGroup, &audioGroup->widget);
712 	hda_widget_get_pm_support(audioGroup, &audioGroup->widget);
713 	hda_widget_get_amplifier_capabilities(audioGroup, &audioGroup->widget);
714 
715 	verbs[0] = MAKE_VERB(audioGroup->codec->addr, audioGroup->widget.node_id,
716 		VID_GET_PARAMETER, PID_AUDIO_GROUP_CAP);
717 	verbs[1] = MAKE_VERB(audioGroup->codec->addr, audioGroup->widget.node_id,
718 		VID_GET_PARAMETER, PID_GPIO_COUNT);
719 	verbs[2] = MAKE_VERB(audioGroup->codec->addr, audioGroup->widget.node_id,
720 		VID_GET_PARAMETER, PID_SUB_NODE_COUNT);
721 
722 	if (hda_send_verbs(audioGroup->codec, verbs, resp, 3) != B_OK)
723 		return B_ERROR;
724 
725 	TRACE("hda: Audio Group: Output delay: %ld samples, Input delay: %ld "
726 		"samples, Beep Generator: %s\n", AUDIO_GROUP_CAP_OUTPUT_DELAY(resp[0]),
727 		AUDIO_GROUP_CAP_INPUT_DELAY(resp[0]),
728 		AUDIO_GROUP_CAP_BEEPGEN(resp[0]) ? "yes" : "no");
729 
730 	TRACE("hda:   #GPIO: %ld, #GPO: %ld, #GPI: %ld, unsol: %s, wake: %s\n",
731 		GPIO_COUNT_NUM_GPIO(resp[1]), GPIO_COUNT_NUM_GPO(resp[1]),
732 		GPIO_COUNT_NUM_GPI(resp[1]), GPIO_COUNT_GPIUNSOL(resp[1]) ? "yes" : "no",
733 		GPIO_COUNT_GPIWAKE(resp[1]) ? "yes" : "no");
734 	dump_widget_stream_support(audioGroup->widget);
735 
736 	audioGroup->gpio = resp[1];
737 	audioGroup->widget_start = SUB_NODE_COUNT_START(resp[2]);
738 	audioGroup->widget_count = SUB_NODE_COUNT_TOTAL(resp[2]);
739 
740 	TRACE("hda:   widget start %lu, count %lu\n", audioGroup->widget_start,
741 		audioGroup->widget_count);
742 
743 	audioGroup->widgets = (hda_widget*)calloc(audioGroup->widget_count,
744 		sizeof(*audioGroup->widgets));
745 	if (audioGroup->widgets == NULL) {
746 		ERROR("ERROR: Not enough memory!\n");
747 		return B_NO_MEMORY;
748 	}
749 
750 	// Iterate over all Widgets and collect info
751 	for (uint32 i = 0; i < audioGroup->widget_count; i++) {
752 		hda_widget& widget = audioGroup->widgets[i];
753 		uint32 nodeID = audioGroup->widget_start + i;
754 		uint32 capabilities;
755 
756 		verbs[0] = MAKE_VERB(audioGroup->codec->addr, nodeID, VID_GET_PARAMETER,
757 			PID_AUDIO_WIDGET_CAP);
758 		if (hda_send_verbs(audioGroup->codec, verbs, &capabilities, 1) != B_OK)
759 			return B_ERROR;
760 
761 		widget.type = (hda_widget_type)((capabilities & AUDIO_CAP_TYPE_MASK)
762 			>> AUDIO_CAP_TYPE_SHIFT);
763 
764 		// Check specific node ids declared as inputs as beepers
765 		switch (codec_id) {
766 			case 0x11d41882:
767 			case 0x11d41883:
768 			case 0x11d41884:
769 			case 0x11d4194a:
770 			case 0x11d4194b:
771 			case 0x11d41987:
772 			case 0x11d41988:
773 			case 0x11d4198b:
774 			case 0x11d4989b:
775 				if (nodeID == 26)
776 					widget.type = WT_BEEP_GENERATOR;
777 				break;
778 			case 0x10ec0260:
779 				if (nodeID == 23)
780 					widget.type = WT_BEEP_GENERATOR;
781 				break;
782 			case 0x10ec0262:
783 			case 0x10ec0268:
784 			case 0x10ec0880:
785 			case 0x10ec0882:
786 			case 0x10ec0883:
787 			case 0x10ec0885:
788 			case 0x10ec0888:
789 			case 0x10ec0889:
790 				if (nodeID == 29)
791 					widget.type = WT_BEEP_GENERATOR;
792 				break;
793 		}
794 		widget.active_input = -1;
795 		widget.capabilities.audio = capabilities;
796 		widget.node_id = nodeID;
797 
798 		if ((capabilities & AUDIO_CAP_POWER_CONTROL) != 0) {
799 			// We support power; switch us on!
800 			verbs[0] = MAKE_VERB(audioGroup->codec->addr, nodeID,
801 				VID_SET_POWER_STATE, 0);
802 			hda_send_verbs(audioGroup->codec, verbs, NULL, 1);
803 
804 			snooze(1000);
805 		}
806 		if ((capabilities & (AUDIO_CAP_INPUT_AMPLIFIER
807 				| AUDIO_CAP_OUTPUT_AMPLIFIER)) != 0) {
808 			hda_widget_get_amplifier_capabilities(audioGroup, &widget);
809 		}
810 
811 		TRACE("%ld: %s\n", nodeID, get_widget_type_name(widget.type));
812 
813 		switch (widget.type) {
814 			case WT_AUDIO_OUTPUT:
815 			case WT_AUDIO_INPUT:
816 				hda_widget_get_stream_support(audioGroup, &widget);
817 				dump_widget_stream_support(widget);
818 				break;
819 
820 			case WT_PIN_COMPLEX:
821 				verbs[0] = MAKE_VERB(audioGroup->codec->addr, nodeID,
822 					VID_GET_PARAMETER, PID_PIN_CAP);
823 				if (hda_send_verbs(audioGroup->codec, verbs, resp, 1) == B_OK) {
824 					widget.d.pin.capabilities = resp[0];
825 
826 					TRACE("\t%s%s\n", PIN_CAP_IS_INPUT(resp[0]) ? "[Input] " : "",
827 						PIN_CAP_IS_OUTPUT(resp[0]) ? "[Output]" : "");
828 				} else {
829 					ERROR("%s: Error getting Pin Complex IO\n", __func__);
830 				}
831 
832 				verbs[0] = MAKE_VERB(audioGroup->codec->addr, nodeID,
833 					VID_GET_CONFIGURATION_DEFAULT, 0);
834 				if (hda_send_verbs(audioGroup->codec, verbs, resp, 1) == B_OK) {
835 					widget.d.pin.config = resp[0];
836 					const char* location =
837 						get_widget_location(CONF_DEFAULT_LOCATION(resp[0]));
838 					TRACE("\t%s, %s%s%s, %s, %s, Association:%ld\n",
839 						kPortConnector[CONF_DEFAULT_CONNECTIVITY(resp[0])],
840 						location ? location : "",
841 						location ? " " : "",
842 						kDefaultDevice[CONF_DEFAULT_DEVICE(resp[0])],
843 						kConnectionType[CONF_DEFAULT_CONNTYPE(resp[0])],
844 						kJackColor[CONF_DEFAULT_COLOR(resp[0])],
845 						CONF_DEFAULT_ASSOCIATION(resp[0]));
846 				}
847 				break;
848 
849 			case WT_VOLUME_KNOB:
850 				verbs[0] = MAKE_VERB(audioGroup->codec->addr, nodeID,
851 					VID_SET_VOLUME_KNOB_CONTROL, 0x0);
852 				hda_send_verbs(audioGroup->codec, verbs, NULL, 1);
853 				break;
854 			default:
855 				break;
856 		}
857 
858 		hda_widget_get_pm_support(audioGroup, &widget);
859 		hda_widget_get_connections(audioGroup, &widget);
860 
861 		dump_widget_pm_support(widget);
862 		dump_widget_audio_capabilities(capabilities);
863 		dump_widget_amplifier_capabilities(widget, true);
864 		dump_widget_amplifier_capabilities(widget, false);
865 		dump_widget_inputs(widget);
866 	}
867 
868 	hda_widget_get_associations(audioGroup);
869 
870 	// init the codecs
871 	switch (codec_id) {
872 		case 0x10ec0888: {
873 			hda_verb_write(codec, 0x20, VID_SET_COEFFICIENT_INDEX, 0x0);
874 			uint32 tmp;
875 			hda_verb_read(codec, 0x20, VID_GET_PROCESSING_COEFFICIENT, &tmp);
876 			hda_verb_write(codec, 0x20, VID_SET_COEFFICIENT_INDEX, 0x7);
877 			hda_verb_write(codec, 0x20, VID_SET_PROCESSING_COEFFICIENT,
878 				(tmp & 0xf0) == 0x20 ? 0x830 : 0x3030);
879 			break;
880 		}
881 	}
882 
883 	return B_OK;
884 }
885 
886 
887 /*! Find output path for widget */
888 static bool
889 hda_widget_find_output_path(hda_audio_group* audioGroup, hda_widget* widget,
890 	uint32 depth, bool &alreadyUsed)
891 {
892 	alreadyUsed = false;
893 
894 	if (widget == NULL || depth > 16)
895 		return false;
896 
897 	switch (widget->type) {
898 		case WT_AUDIO_OUTPUT:
899 			widget->flags |= WIDGET_FLAG_OUTPUT_PATH;
900 TRACE("      %*soutput: added output widget %ld\n", (int)depth * 2, "", widget->node_id);
901 			return true;
902 
903 		case WT_AUDIO_MIXER:
904 		case WT_AUDIO_SELECTOR:
905 		{
906 			// already used
907 			if ((widget->flags & WIDGET_FLAG_OUTPUT_PATH) != 0) {
908 				alreadyUsed = true;
909 				return false;
910 			}
911 
912 			// search for output in this path
913 			bool found = false;
914 			for (uint32 i = 0; i < widget->num_inputs; i++) {
915 				hda_widget* inputWidget = hda_audio_group_get_widget(audioGroup,
916 					widget->inputs[i]);
917 
918 				if (hda_widget_find_output_path(audioGroup, inputWidget,
919 						depth + 1, alreadyUsed)) {
920 					if (widget->active_input == -1)
921 						widget->active_input = i;
922 
923 					widget->flags |= WIDGET_FLAG_OUTPUT_PATH;
924 TRACE("      %*soutput: added mixer/selector widget %ld\n", (int)depth * 2, "", widget->node_id);
925 					found = true;
926 				}
927 			}
928 if (!found) TRACE("      %*soutput: not added mixer/selector widget %ld\n", (int)depth * 2, "", widget->node_id);
929 			return found;
930 		}
931 
932 		default:
933 			return false;
934 	}
935 }
936 
937 
938 /*! Find input path for widget */
939 static bool
940 hda_widget_find_input_path(hda_audio_group* audioGroup, hda_widget* widget,
941 	uint32 depth)
942 {
943 	if (widget == NULL || depth > 16)
944 		return false;
945 
946 	switch (widget->type) {
947 		case WT_PIN_COMPLEX:
948 			// already used
949 			if ((widget->flags
950 					& (WIDGET_FLAG_INPUT_PATH | WIDGET_FLAG_OUTPUT_PATH)) != 0)
951 				return false;
952 
953 			if (PIN_CAP_IS_INPUT(widget->d.pin.capabilities)) {
954 				switch (CONF_DEFAULT_DEVICE(widget->d.pin.config)) {
955 					case PIN_DEV_CD:
956 					case PIN_DEV_LINE_IN:
957 					case PIN_DEV_MIC_IN:
958 						widget->flags |= WIDGET_FLAG_INPUT_PATH;
959 TRACE("      %*sinput: added input widget %ld\n", (int)depth * 2, "", widget->node_id);
960 						return true;
961 					break;
962 				}
963 			}
964 			return false;
965 		case WT_AUDIO_INPUT:
966 		case WT_AUDIO_MIXER:
967 		case WT_AUDIO_SELECTOR:
968 		{
969 			// already used
970 			if ((widget->flags
971 					& (WIDGET_FLAG_INPUT_PATH | WIDGET_FLAG_OUTPUT_PATH)) != 0)
972 				return false;
973 
974 			// search for pin complex in this path
975 			bool found = false;
976 			for (uint32 i = 0; i < widget->num_inputs; i++) {
977 				hda_widget* inputWidget = hda_audio_group_get_widget(audioGroup,
978 					widget->inputs[i]);
979 
980 				if (hda_widget_find_input_path(audioGroup, inputWidget,
981 						depth + 1)) {
982 					if (widget->active_input == -1)
983 						widget->active_input = i;
984 
985 					widget->flags |= WIDGET_FLAG_INPUT_PATH;
986 TRACE("      %*sinput: added mixer/selector widget %ld\n", (int)depth * 2, "", widget->node_id);
987 					found = true;
988 				}
989 			}
990 if (!found) TRACE("      %*sinput: not added mixer/selector widget %ld\n", (int)depth * 2, "", widget->node_id);
991 			return found;
992 		}
993 
994 		default:
995 			return false;
996 	}
997 }
998 
999 static bool
1000 hda_audio_group_build_output_tree(hda_audio_group* audioGroup, bool useMixer)
1001 {
1002 	bool found = false;
1003 
1004 TRACE("build output tree: %suse mixer\n", useMixer ? "" : "don't ");
1005 	for (uint32 i = 0; i < audioGroup->widget_count; i++) {
1006 		hda_widget& widget = audioGroup->widgets[i];
1007 
1008 		if (widget.type != WT_PIN_COMPLEX
1009 			|| !PIN_CAP_IS_OUTPUT(widget.d.pin.capabilities))
1010 			continue;
1011 
1012 		int device = CONF_DEFAULT_DEVICE(widget.d.pin.config);
1013 		if (device != PIN_DEV_HEAD_PHONE_OUT
1014 			&& device != PIN_DEV_DIGITAL_OTHER_OUT
1015 			&& device != PIN_DEV_SPEAKER
1016 			&& device != PIN_DEV_LINE_OUT)
1017 			continue;
1018 
1019 TRACE("  look at pin widget %ld (%ld inputs)\n", widget.node_id, widget.num_inputs);
1020 		for (uint32 j = 0; j < widget.num_inputs; j++) {
1021 			hda_widget* inputWidget = hda_audio_group_get_widget(audioGroup,
1022 				widget.inputs[j]);
1023 TRACE("    try widget %ld: %p\n", widget.inputs[j], inputWidget);
1024 			if (inputWidget == NULL)
1025 				continue;
1026 
1027 			if (useMixer && inputWidget->type != WT_AUDIO_MIXER
1028 				&& inputWidget->type != WT_AUDIO_SELECTOR)
1029 				continue;
1030 TRACE("    widget %ld is candidate\n", inputWidget->node_id);
1031 
1032 			bool alreadyUsed = false;
1033 			if (hda_widget_find_output_path(audioGroup, inputWidget, 0,
1034 				alreadyUsed)
1035 				|| (device == PIN_DEV_HEAD_PHONE_OUT && alreadyUsed)) {
1036 				// find the output path to an audio output widget
1037 				// or for headphones, an already used widget
1038 TRACE("    add pin widget %ld\n", widget.node_id);
1039 				if (widget.active_input == -1)
1040 					widget.active_input = j;
1041 				widget.flags |= WIDGET_FLAG_OUTPUT_PATH;
1042 				found = true;
1043 				break;
1044 			}
1045 		}
1046 	}
1047 
1048 	return found;
1049 }
1050 
1051 
1052 static bool
1053 hda_audio_group_build_input_tree(hda_audio_group* audioGroup)
1054 {
1055 	bool found = false;
1056 
1057 TRACE("build input tree\n");
1058 	for (uint32 i = 0; i < audioGroup->widget_count; i++) {
1059 		hda_widget& widget = audioGroup->widgets[i];
1060 
1061 		if (widget.type != WT_AUDIO_INPUT)
1062 			continue;
1063 
1064 TRACE("  look at input widget %ld (%ld inputs)\n", widget.node_id, widget.num_inputs);
1065 		for (uint32 j = 0; j < widget.num_inputs; j++) {
1066 			hda_widget* inputWidget = hda_audio_group_get_widget(audioGroup,
1067 				widget.inputs[j]);
1068 TRACE("    try widget %ld: %p\n", widget.inputs[j], inputWidget);
1069 			if (inputWidget == NULL)
1070 				continue;
1071 
1072 TRACE("    widget %ld is candidate\n", inputWidget->node_id);
1073 
1074 			if (hda_widget_find_input_path(audioGroup, inputWidget, 0)) {
1075 TRACE("    add pin widget %ld\n", widget.node_id);
1076 				if (widget.active_input == -1)
1077 					widget.active_input = j;
1078 				widget.flags |= WIDGET_FLAG_INPUT_PATH;
1079 				found = true;
1080 				break;
1081 			}
1082 		}
1083 	}
1084 
1085 	return found;
1086 }
1087 
1088 
1089 static status_t
1090 hda_audio_group_build_tree(hda_audio_group* audioGroup)
1091 {
1092 	if (!hda_audio_group_build_output_tree(audioGroup, true)) {
1093 		// didn't find a mixer path, try again without
1094 TRACE("try without mixer!\n");
1095 		if (!hda_audio_group_build_output_tree(audioGroup, false))
1096 			return ENODEV;
1097 	}
1098 
1099 	if (!hda_audio_group_build_input_tree(audioGroup)) {
1100 		ERROR("hda: build input tree failed\n");
1101 	}
1102 
1103 TRACE("build tree!\n");
1104 
1105 	// select active connections
1106 
1107 	for (uint32 i = 0; i < audioGroup->widget_count; i++) {
1108 		hda_widget& widget = audioGroup->widgets[i];
1109 
1110 		if (widget.active_input == -1)
1111 			widget.active_input = 0;
1112 		if (widget.num_inputs < 2)
1113 			continue;
1114 
1115 		if (widget.type != WT_AUDIO_INPUT
1116 			&& widget.type != WT_AUDIO_SELECTOR
1117 			&& widget.type != WT_PIN_COMPLEX)
1118 			continue;
1119 
1120 		corb_t verb = MAKE_VERB(audioGroup->codec->addr,
1121 			widget.node_id, VID_SET_CONNECTION_SELECT, widget.active_input);
1122 		if (hda_send_verbs(audioGroup->codec, &verb, NULL, 1) != B_OK)
1123 			ERROR("hda: Setting output selector %ld failed on widget %ld!\n",
1124 				widget.active_input, widget.node_id);
1125 	}
1126 
1127 	// GPIO
1128 	uint32 gpio = 0;
1129 	for (uint32 i = 0; i < GPIO_COUNT_NUM_GPIO(audioGroup->gpio)
1130 		&& i < HDA_QUIRK_GPIO_COUNT; i++) {
1131 		if (audioGroup->codec->quirks & (1 << i)) {
1132 			gpio |= (1 << i);
1133 		}
1134 	}
1135 
1136 	if (gpio != 0) {
1137 		corb_t verb[] = {
1138 			MAKE_VERB(audioGroup->codec->addr,
1139 				audioGroup->widget.node_id, VID_SET_GPIO_DATA, gpio),
1140 			MAKE_VERB(audioGroup->codec->addr,
1141 				audioGroup->widget.node_id, VID_SET_GPIO_EN, gpio),
1142 			MAKE_VERB(audioGroup->codec->addr,
1143 				audioGroup->widget.node_id, VID_SET_GPIO_DIR, gpio)
1144 		};
1145 		TRACE("hda: Setting gpio 0x%lx\n", gpio);
1146 		if (hda_send_verbs(audioGroup->codec, verb, NULL, 3) != B_OK)
1147 			ERROR("hda: Setting gpio failed!\n");
1148 	}
1149 
1150 	dump_audiogroup_widgets(audioGroup);
1151 
1152 	return B_OK;
1153 }
1154 
1155 
1156 static void
1157 hda_audio_group_switch_init(hda_audio_group* audioGroup)
1158 {
1159 	for (uint32 i = 0; i < audioGroup->widget_count; i++) {
1160 		hda_widget& widget = audioGroup->widgets[i];
1161 		if (widget.type != WT_PIN_COMPLEX)
1162 			continue;
1163 
1164 		if ((widget.capabilities.audio & AUDIO_CAP_UNSOLICITED_RESPONSES) != 0
1165 			&& (widget.d.pin.capabilities & PIN_CAP_PRES_DETECT) != 0
1166 			&& (CONF_DEFAULT_MISC(widget.d.pin.config) & 1) == 0) {
1167 			corb_t verb = MAKE_VERB(audioGroup->codec->addr, widget.node_id,
1168 				VID_SET_UNSOLRESP, UNSOLRESP_ENABLE);
1169 			hda_send_verbs(audioGroup->codec, &verb, NULL, 1);
1170 			TRACE("hda: Enabled unsolicited responses on widget %ld\n",
1171 				widget.node_id);
1172 		}
1173 	}
1174 }
1175 
1176 
1177 static void
1178 hda_audio_group_check_sense(hda_audio_group* audioGroup, bool disable)
1179 {
1180 	for (uint32 i = 0; i < audioGroup->widget_count; i++) {
1181 		hda_widget& widget = audioGroup->widgets[i];
1182 
1183 		if (widget.type != WT_PIN_COMPLEX
1184 			|| !PIN_CAP_IS_OUTPUT(widget.d.pin.capabilities)
1185 			|| CONF_DEFAULT_DEVICE(widget.d.pin.config)
1186 				!= PIN_DEV_HEAD_PHONE_OUT)
1187 			continue;
1188 
1189 		corb_t verb = MAKE_VERB(audioGroup->codec->addr, widget.node_id,
1190 			VID_GET_PINSENSE, 0);
1191 		uint32 response;
1192 		hda_send_verbs(audioGroup->codec, &verb, &response, 1);
1193 		disable = response & PIN_SENSE_PRESENCE_DETECT;
1194 		TRACE("hda: sensed pin widget %ld, %d\n", widget.node_id, disable);
1195 
1196 		uint32 ctrl = hda_widget_prepare_pin_ctrl(audioGroup, &widget,
1197 				true);
1198 		verb = MAKE_VERB(audioGroup->codec->addr, widget.node_id,
1199 			VID_SET_PIN_WIDGET_CONTROL, disable ? ctrl : 0);
1200 		hda_send_verbs(audioGroup->codec, &verb, NULL, 1);
1201 		break;
1202 	}
1203 
1204 	for (uint32 i = 0; i < audioGroup->widget_count; i++) {
1205 		hda_widget& widget = audioGroup->widgets[i];
1206 
1207 		if (widget.type != WT_PIN_COMPLEX
1208 			|| !PIN_CAP_IS_OUTPUT(widget.d.pin.capabilities))
1209 			continue;
1210 
1211 		int device = CONF_DEFAULT_DEVICE(widget.d.pin.config);
1212 		if (device != PIN_DEV_AUX
1213 			&& device != PIN_DEV_SPEAKER
1214 			&& device != PIN_DEV_LINE_OUT)
1215 			continue;
1216 
1217 		uint32 ctrl = hda_widget_prepare_pin_ctrl(audioGroup, &widget,
1218 				true);
1219 		corb_t verb = MAKE_VERB(audioGroup->codec->addr, widget.node_id,
1220 			VID_SET_PIN_WIDGET_CONTROL, disable ? 0 : ctrl);
1221 		hda_send_verbs(audioGroup->codec, &verb, NULL, 1);
1222 	}
1223 }
1224 
1225 
1226 static status_t
1227 hda_codec_switch_handler(hda_codec* codec)
1228 {
1229 	while (acquire_sem(codec->unsol_response_sem) == B_OK) {
1230 		uint32 response = codec->unsol_responses[codec->unsol_response_read++];
1231 		codec->unsol_response_read %= MAX_CODEC_UNSOL_RESPONSES;
1232 
1233 		bool disable = response & 1;
1234 		hda_audio_group* audioGroup = codec->audio_groups[0];
1235 		hda_audio_group_check_sense(audioGroup, disable);
1236 	}
1237 	return B_OK;
1238 }
1239 
1240 
1241 static void
1242 hda_codec_delete_audio_group(hda_audio_group* audioGroup)
1243 {
1244 	if (audioGroup == NULL)
1245 		return;
1246 
1247 	if (audioGroup->playback_stream != NULL)
1248 		hda_stream_delete(audioGroup->playback_stream);
1249 
1250 	if (audioGroup->record_stream != NULL)
1251 		hda_stream_delete(audioGroup->record_stream);
1252 	free(audioGroup->multi);
1253 	free(audioGroup->widgets);
1254 	free(audioGroup);
1255 }
1256 
1257 
1258 static status_t
1259 hda_codec_new_audio_group(hda_codec* codec, uint32 audioGroupNodeID)
1260 {
1261 	hda_audio_group* audioGroup = (hda_audio_group*)calloc(1,
1262 		sizeof(hda_audio_group));
1263 	if (audioGroup == NULL)
1264 		return B_NO_MEMORY;
1265 
1266 	// Setup minimal info needed by hda_codec_parse_afg
1267 	audioGroup->widget.node_id = audioGroupNodeID;
1268 	audioGroup->codec = codec;
1269 	audioGroup->multi = (hda_multi*)calloc(1,
1270 		sizeof(hda_multi));
1271 	if (audioGroup->multi == NULL) {
1272 		free(audioGroup);
1273 		return B_NO_MEMORY;
1274 	}
1275 	audioGroup->multi->group = audioGroup;
1276 
1277 	// Parse all widgets in Audio Function Group
1278 	status_t status = hda_codec_parse_audio_group(audioGroup);
1279 	if (status != B_OK)
1280 		goto err;
1281 
1282 	// Setup for worst-case scenario; we cannot find any output Pin Widgets
1283 	status = ENODEV;
1284 
1285 	if (hda_audio_group_build_tree(audioGroup) != B_OK)
1286 		goto err;
1287 	hda_audio_group_switch_init(audioGroup);
1288 
1289 	audioGroup->playback_stream = hda_stream_new(audioGroup, STREAM_PLAYBACK);
1290 	audioGroup->record_stream = hda_stream_new(audioGroup, STREAM_RECORD);
1291 	TRACE("hda: streams playback %p, record %p\n", audioGroup->playback_stream,
1292 		audioGroup->record_stream);
1293 
1294 	if (audioGroup->playback_stream != NULL
1295 		|| audioGroup->record_stream != NULL) {
1296 		codec->audio_groups[codec->num_audio_groups++] = audioGroup;
1297 		hda_audio_group_check_sense(audioGroup, false);
1298 		return B_OK;
1299 	}
1300 
1301 err:
1302 	free(audioGroup->widgets);
1303 	free(audioGroup);
1304 	return status;
1305 }
1306 
1307 
1308 //	#pragma mark -
1309 
1310 
1311 status_t
1312 hda_audio_group_get_widgets(hda_audio_group* audioGroup, hda_stream* stream)
1313 {
1314 	hda_widget_type type;
1315 	uint32 flags;
1316 
1317 	if (stream->type == STREAM_PLAYBACK) {
1318 		type = WT_AUDIO_OUTPUT;
1319 		flags = WIDGET_FLAG_OUTPUT_PATH;
1320 	} else {
1321 		// record
1322 		type = WT_AUDIO_INPUT;
1323 		flags = WIDGET_FLAG_INPUT_PATH;
1324 	}
1325 
1326 	uint32 count = 0;
1327 
1328 	for (uint32 i = 0; i < audioGroup->widget_count && count < MAX_IO_WIDGETS;
1329 			i++) {
1330 		hda_widget& widget = audioGroup->widgets[i];
1331 
1332 		if ((widget.flags & flags) != 0) {
1333 			if (widget.type == WT_PIN_COMPLEX) {
1334 				stream->pin_widget = widget.node_id;
1335 
1336 				uint32 ctrl = hda_widget_prepare_pin_ctrl(audioGroup, &widget,
1337 					flags == WIDGET_FLAG_OUTPUT_PATH);
1338 
1339 TRACE("ENABLE pin widget %ld\n", widget.node_id);
1340 				// FIXME: Force Pin Widget to unmute; enable hp/output
1341 				corb_t verb = MAKE_VERB(audioGroup->codec->addr,
1342 					widget.node_id,
1343 					VID_SET_PIN_WIDGET_CONTROL, ctrl);
1344 				hda_send_verbs(audioGroup->codec, &verb, NULL, 1);
1345 
1346 				if (PIN_CAP_IS_EAPD_CAP(widget.d.pin.capabilities)) {
1347 					uint32 result;
1348 					verb = MAKE_VERB(audioGroup->codec->addr,
1349 						widget.node_id, VID_GET_EAPDBTL_EN, 0);
1350 					if (hda_send_verbs(audioGroup->codec, &verb,
1351 						&result, 1) == B_OK) {
1352 						result &= 0xff;
1353 						verb = MAKE_VERB(audioGroup->codec->addr,
1354 							widget.node_id, VID_SET_EAPDBTL_EN,
1355 							result | EAPDBTL_ENABLE_EAPD);
1356 						hda_send_verbs(audioGroup->codec,
1357 							&verb, NULL, 1);
1358 TRACE("ENABLE EAPD pin widget %ld\n", widget.node_id);
1359 					}
1360 				}
1361 			}
1362 
1363 			if (widget.capabilities.output_amplifier != 0) {
1364 TRACE("UNMUTE/SET OUTPUT GAIN widget %ld (offset %ld)\n", widget.node_id,
1365 	AMP_CAP_OFFSET(widget.capabilities.output_amplifier));
1366 				corb_t verb = MAKE_VERB(audioGroup->codec->addr,
1367 					widget.node_id,
1368 					VID_SET_AMPLIFIER_GAIN_MUTE,
1369 					AMP_SET_OUTPUT | AMP_SET_LEFT_CHANNEL
1370 						| AMP_SET_RIGHT_CHANNEL
1371 						| AMP_CAP_OFFSET(widget.capabilities.output_amplifier));
1372 				hda_send_verbs(audioGroup->codec, &verb, NULL, 1);
1373 			}
1374 			if (widget.capabilities.input_amplifier != 0) {
1375 TRACE("UNMUTE/SET INPUT GAIN widget %ld (offset %ld)\n", widget.node_id,
1376 	AMP_CAP_OFFSET(widget.capabilities.input_amplifier));
1377 				for (uint32 i = 0; i < widget.num_inputs; i++) {
1378 					corb_t verb = MAKE_VERB(audioGroup->codec->addr,
1379 						widget.node_id,
1380 						VID_SET_AMPLIFIER_GAIN_MUTE,
1381 						AMP_SET_INPUT | AMP_SET_LEFT_CHANNEL
1382 							| AMP_SET_RIGHT_CHANNEL
1383 							| AMP_SET_INPUT_INDEX(i)
1384 							| ((widget.active_input == (int32)i) ? 0 : AMP_MUTE)
1385 							| AMP_CAP_OFFSET(widget.capabilities.input_amplifier));
1386 					hda_send_verbs(audioGroup->codec, &verb, NULL, 1);
1387 				}
1388 			}
1389 		}
1390 
1391 		if (widget.type != type || (widget.flags & flags) == 0
1392 			|| (widget.capabilities.audio
1393 				& (AUDIO_CAP_STEREO | AUDIO_CAP_DIGITAL)) != AUDIO_CAP_STEREO
1394 			|| widget.d.io.formats == 0)
1395 			continue;
1396 
1397 		if (count == 0) {
1398 			stream->sample_format = widget.d.io.formats;
1399 			stream->sample_rate = widget.d.io.rates;
1400 		} else {
1401 			stream->sample_format &= widget.d.io.formats;
1402 			stream->sample_rate &= widget.d.io.rates;
1403 		}
1404 
1405 		stream->io_widgets[count++] = widget.node_id;
1406 	}
1407 
1408 	if (count == 0)
1409 		return B_ENTRY_NOT_FOUND;
1410 
1411 	stream->num_io_widgets = count;
1412 	return B_OK;
1413 }
1414 
1415 
1416 void
1417 hda_codec_delete(hda_codec* codec)
1418 {
1419 	if (codec == NULL)
1420 		return;
1421 
1422 	delete_sem(codec->response_sem);
1423 	delete_sem(codec->unsol_response_sem);
1424 
1425 	int32 result;
1426 	wait_for_thread(codec->unsol_response_thread, &result);
1427 
1428 	for (uint32 i = 0; i < codec->num_audio_groups; i++) {
1429 		hda_codec_delete_audio_group(codec->audio_groups[i]);
1430 		codec->audio_groups[i] = NULL;
1431 	}
1432 
1433 	free(codec);
1434 }
1435 
1436 
1437 hda_codec*
1438 hda_codec_new(hda_controller* controller, uint32 codecAddress)
1439 {
1440 	if (codecAddress > HDA_MAX_CODECS)
1441 		return NULL;
1442 
1443 	hda_codec* codec = (hda_codec*)calloc(1, sizeof(hda_codec));
1444 	if (codec == NULL) {
1445 		ERROR("hda: Failed to alloc a codec\n");
1446 		return NULL;
1447 	}
1448 
1449 	status_t status;
1450 
1451 	codec->controller = controller;
1452 	codec->addr = codecAddress;
1453 	codec->response_sem = create_sem(0, "hda_codec_response_sem");
1454 	if (codec->response_sem < B_OK) {
1455 		ERROR("hda: Failed to create semaphore\n");
1456 		goto err;
1457 	}
1458 	controller->codecs[codecAddress] = codec;
1459 
1460 	codec->unsol_response_sem = create_sem(0, "hda_codec_unsol_response_sem");
1461 	if (codec->unsol_response_sem < B_OK) {
1462 		ERROR("hda: Failed to create semaphore\n");
1463 		goto err;
1464 	}
1465 	codec->unsol_response_read = 0;
1466 	codec->unsol_response_write = 0;
1467 
1468 	struct {
1469 		uint32 device : 16;
1470 		uint32 vendor : 16;
1471 		uint32 stepping : 8;
1472 		uint32 revision : 8;
1473 		uint32 minor : 4;
1474 		uint32 major : 4;
1475 		uint32 _reserved0 : 8;
1476 		uint32 count : 8;
1477 		uint32 _reserved1 : 8;
1478 		uint32 start : 8;
1479 		uint32 _reserved2 : 8;
1480 	} response;
1481 
1482 	corb_t verbs[3];
1483 	verbs[0] = MAKE_VERB(codecAddress, 0, VID_GET_PARAMETER, PID_VENDOR_ID);
1484 	verbs[1] = MAKE_VERB(codecAddress, 0, VID_GET_PARAMETER, PID_REVISION_ID);
1485 	verbs[2] = MAKE_VERB(codecAddress, 0, VID_GET_PARAMETER,
1486 		PID_SUB_NODE_COUNT);
1487 
1488 	status = hda_send_verbs(codec, verbs, (uint32*)&response, 3);
1489 	if (status != B_OK) {
1490 		ERROR("hda: Failed to get vendor and revision parameters: %s\n",
1491 			strerror(status));
1492 		goto err;
1493 	}
1494 
1495 	codec->vendor_id = response.vendor;
1496 	codec->product_id = response.device;
1497 	codec->stepping = response.stepping;
1498 	codec->revision = response.revision;
1499 	codec->minor = response.minor;
1500 	codec->major = response.major;
1501 	hda_codec_get_quirks(codec);
1502 
1503 	TRACE("Codec %ld Vendor: %04lx Product: %04lx, Revision: "
1504 		"%lu.%lu.%lu.%lu\n", codecAddress, response.vendor, response.device,
1505 		response.major, response.minor, response.revision, response.stepping);
1506 
1507 	for (uint32 nodeID = response.start;
1508 			nodeID < response.start + response.count; nodeID++) {
1509 		uint32 groupType;
1510 		verbs[0] = MAKE_VERB(codecAddress, nodeID, VID_GET_PARAMETER,
1511 			PID_FUNCTION_GROUP_TYPE);
1512 
1513 		if (hda_send_verbs(codec, verbs, &groupType, 1) != B_OK) {
1514 			ERROR("hda: Failed to get function group type\n");
1515 			goto err;
1516 		}
1517 
1518 		if ((groupType & FUNCTION_GROUP_NODETYPE_MASK)
1519 				== FUNCTION_GROUP_NODETYPE_AUDIO) {
1520 			// Found an Audio Function Group!
1521 			status_t status = hda_codec_new_audio_group(codec, nodeID);
1522 			if (status != B_OK) {
1523 				ERROR("hda: Failed to setup new audio function group (%s)!\n",
1524 					strerror(status));
1525 				goto err;
1526 			}
1527 		}
1528 	}
1529 
1530 	codec->unsol_response_thread = spawn_kernel_thread(
1531 		(status_t(*)(void*))hda_codec_switch_handler,
1532 		"hda_codec_unsol_thread", B_LOW_PRIORITY, codec);
1533 	if (codec->unsol_response_thread < B_OK) {
1534 		ERROR("hda: Failed to spawn thread\n");
1535 		goto err;
1536 	}
1537 	resume_thread(codec->unsol_response_thread);
1538 
1539 	return codec;
1540 
1541 err:
1542 	controller->codecs[codecAddress] = NULL;
1543 	hda_codec_delete(codec);
1544 	return NULL;
1545 }
1546