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