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