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