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