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