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