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