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