audiohd.c revision 12242:acee048dccc7
1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21/*
22 * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
23 */
24
25#include <sys/audio/audio_driver.h>
26#include <sys/note.h>
27#include <sys/beep.h>
28#include <sys/pci.h>
29#include "audiohd.h"
30
31#define	DRVNAME			"audiohd"
32
33/*
34 * Module linkage routines for the kernel
35 */
36
37static int audiohd_attach(dev_info_t *, ddi_attach_cmd_t);
38static int audiohd_detach(dev_info_t *, ddi_detach_cmd_t);
39static int audiohd_quiesce(dev_info_t *);
40static int audiohd_resume(audiohd_state_t *);
41static int audiohd_suspend(audiohd_state_t *);
42
43/*
44 * Local routines
45 */
46static int audiohd_init_state(audiohd_state_t *, dev_info_t *);
47static int audiohd_init_pci(audiohd_state_t *, ddi_device_acc_attr_t *);
48static void audiohd_fini_pci(audiohd_state_t *);
49static int audiohd_reset_controller(audiohd_state_t *);
50static int audiohd_init_controller(audiohd_state_t *);
51static void audiohd_fini_controller(audiohd_state_t *);
52static void audiohd_stop_dma(audiohd_state_t *);
53static void audiohd_disable_intr(audiohd_state_t *);
54static int audiohd_create_codec(audiohd_state_t *);
55static void audiohd_build_path(audiohd_state_t *);
56static void audiohd_destroy_codec(audiohd_state_t *);
57static int audiohd_alloc_dma_mem(audiohd_state_t *, audiohd_dma_t *,
58    size_t, ddi_dma_attr_t *, uint_t);
59static void audiohd_finish_output_path(hda_codec_t *);
60static uint32_t audioha_codec_verb_get(void *, uint8_t,
61    uint8_t, uint16_t, uint8_t);
62static uint32_t audioha_codec_4bit_verb_get(void *, uint8_t,
63    uint8_t, uint16_t, uint16_t);
64static int audiohd_reinit_hda(audiohd_state_t *);
65static int audiohd_response_from_codec(audiohd_state_t *,
66    uint32_t *, uint32_t *);
67static void audiohd_restore_codec_gpio(audiohd_state_t *);
68static void audiohd_change_speaker_state(audiohd_state_t *, int);
69static int audiohd_allocate_port(audiohd_state_t *);
70static void audiohd_free_port(audiohd_state_t *);
71static void audiohd_restore_path(audiohd_state_t *);
72static void audiohd_create_controls(audiohd_state_t *);
73static void audiohd_get_channels(audiohd_state_t *);
74static void audiohd_init_path(audiohd_state_t *);
75static void audiohd_del_controls(audiohd_state_t *);
76static void audiohd_destroy(audiohd_state_t *);
77static void audiohd_beep_on(void *);
78static void audiohd_beep_off(void *);
79static void audiohd_beep_freq(void *, int);
80static wid_t audiohd_find_beep(hda_codec_t *, wid_t, int);
81static void audiohd_build_beep_path(hda_codec_t *);
82static void audiohd_build_beep_amp(hda_codec_t *);
83static void  audiohd_finish_beep_path(hda_codec_t *);
84static void audiohd_do_set_beep_volume(audiohd_state_t *,
85    audiohd_path_t *, uint64_t);
86static void audiohd_set_beep_volume(audiohd_state_t *);
87static int audiohd_set_beep(void *, uint64_t);
88static void audiohd_pin_sense(audiohd_state_t *, uint32_t, uint32_t);
89
90static	int	audiohd_beep;
91static	int	audiohd_beep_divider;
92static	int	audiohd_beep_vol = 1;
93
94static ddi_device_acc_attr_t hda_dev_accattr = {
95	DDI_DEVICE_ATTR_V0,
96	DDI_STRUCTURE_LE_ACC,
97	DDI_STRICTORDER_ACC
98};
99
100static const char *audiohd_dtypes[] = {
101	AUDIO_PORT_LINEOUT,
102	AUDIO_PORT_SPEAKER,
103	AUDIO_PORT_HEADPHONES,
104	AUDIO_PORT_CD,
105	AUDIO_PORT_SPDIFOUT,
106	AUDIO_PORT_DIGOUT,
107	AUDIO_PORT_MODEM,
108	AUDIO_PORT_HANDSET,
109	AUDIO_PORT_LINEIN,
110	AUDIO_PORT_AUX1IN,
111	AUDIO_PORT_MIC,
112	AUDIO_PORT_PHONE,
113	AUDIO_PORT_SPDIFIN,
114	AUDIO_PORT_DIGIN,
115	AUDIO_PORT_STEREOMIX,
116	AUDIO_PORT_NONE,	/* reserved port, don't use */
117	AUDIO_PORT_OTHER,
118	NULL,
119};
120
121static audiohd_codec_info_t audiohd_codecs[] = {
122	{0x1002aa01, "ATI R600 HDMI", 0x0},
123	{0x10134206, "Cirrus CS4206", 0x0},
124	{0x10de0002, "nVidia MCP78 HDMI", 0x0},
125	{0x10de0003, "nVidia MCP78 HDMI", 0x0},
126	{0x10de0006, "nVidia MCP78 HDMI", 0x0},
127	{0x10de0007, "nVidia MCP7A HDMI", 0x0},
128	{0x10ec0260, "Realtek ALC260", (NO_GPIO)},
129	{0x10ec0262, "Realtek ALC262", (NO_GPIO | EN_PIN_BEEP)},
130	{0x10ec0268, "Realtek ALC268", 0x0},
131	{0x10ec0272, "Realtek ALC272", 0x0},
132	{0x10ec0662, "Realtek ALC662", 0x0},
133	{0x10ec0663, "Realtek ALC663", 0x0},
134	{0x10ec0861, "Realtek ALC861", 0x0},
135	{0x10ec0862, "Realtek ALC862", 0x0},
136	{0x10ec0880, "Realtek ALC880", 0x0},
137	{0x10ec0882, "Realtek ALC882", 0x0},
138	{0x10ec0883, "Realtek ALC883", 0x0},
139	{0x10ec0885, "Realtek ALC885", 0x0},
140	{0x10ec0888, "Realtek ALC888", (NO_SPDIF)},
141	{0x111d7603, "Integrated Devices 92HD75B3X5", 0x0},
142	{0x111d7608, "Integrated Devices 92HD75B2X5", (NO_MIXER)},
143	{0x111d76b2, "Integrated Devices 92HD71B7X", (NO_MIXER)},
144	{0x11d4194a, "Analog Devices AD1984A", 0x0},
145	{0x11d41981, "Analog Devices AD1981", (NO_MIXER)},
146	{0x11d41983, "Analog Devices AD1983", 0x0},
147	{0x11d41984, "Analog Devices AD1984", 0x0},
148	{0x11d41986, "Analog Devices AD1986A", 0x0},
149	{0x11d41988, "Analog Devices AD1988A", 0x0},
150	{0x11d4198b, "Analog Devices AD1988B", 0x0},
151	{0x13f69880, "CMedia CMI19880", 0x0},
152	{0x14f15045, "Conexant CX20549", (NO_MIXER)},
153	{0x14f15051, "Conexant CX20561", 0x0},
154	{0x434d4980, "CMedia CMI19880", 0x0},
155	{0x80862802, "Intel HDMI", 0x0},
156	{0x83847610, "Sigmatel STAC9230XN", 0x0},
157	{0x83847611, "Sigmatel STAC9230DN", 0x0},
158	{0x83847612, "Sigmatel STAC9230XT", 0x0},
159	{0x83847613, "Sigmatel STAC9230DT", 0x0},
160	{0x83847614, "Sigmatel STAC9229X", 0x0},
161	{0x83847615, "Sigmatel STAC9229D", 0x0},
162	{0x83847616, "Sigmatel STAC9228X", 0x0},
163	{0x83847617, "Sigmatel STAC9228D", 0x0},
164	{0x83847618, "Sigmatel STAC9227X", 0x0},
165	{0x83847619, "Sigmatel STAC9227D", 0x0},
166	{0x83847620, "Sigmatel STAC9274", 0x0},
167	{0x83847621, "Sigmatel STAC9274D", 0x0},
168	{0x83847622, "Sigmatel STAC9273X", 0x0},
169	{0x83847623, "Sigmatel STAC9273D", 0x0},
170	{0x83847624, "Sigmatel STAC9272X", 0x0},
171	{0x83847625, "Sigmatel STAC9272D", 0x0},
172	{0x83847626, "Sigmatel STAC9271X", 0x0},
173	{0x83847627, "Sigmatel STAC9271D", 0x0},
174	{0x83847628, "Sigmatel STAC9274X5NH", 0x0},
175	{0x83847629, "Sigmatel STAC9274D5NH", 0x0},
176	{0x83847662, "Sigmatel STAC9872AK", 0x0},
177	{0x83847664, "Sigmatel STAC9872K", 0x0},
178	{0x83847680, "Sigmatel STAC9221A1", 0x0},
179	{0x83847680, "Sigmatel STAC9221A1", 0x0},
180	{0x83847681, "Sigmatel STAC9220D", 0x0},
181	{0x83847682, "Sigmatel STAC9221", 0x0},
182	{0x83847683, "Sigmatel STAC9221D", 0x0},
183	{0x83847690, "Sigmatel STAC9200", 0x0},
184	{0x838476a0, "Sigmatel STAC9205", 0x0},
185	{0x838476a1, "Sigmatel STAC9205D", 0x0},
186	{0x838476a2, "Sigmatel STAC9204", 0x0},
187	{0x838476a3, "Sigmatel STAC9204D", 0x0},
188	{0x838476a4, "Sigmatel STAC9255", 0x0},
189	{0x838476a5, "Sigmatel STAC9255D", 0x0},
190	{0x838476a6, "Sigmatel STAC9254", 0x0},
191	{0x838476a7, "Sigmatel STAC9254D", 0x0},
192	{0x83847880, "Sigmatel STAC9220A1", 0x0},
193	{0x83847882, "Sigmatel STAC9220A2", 0x0},
194	{0x0, "Unknown 0x00000000", 0x0},
195};
196
197static void
198audiohd_set_chipset_info(audiohd_state_t *statep)
199{
200	uint32_t		devid;
201	const char		*name;
202	const char		*vers;
203
204	devid = pci_config_get16(statep->hda_pci_handle, PCI_CONF_VENID);
205	devid <<= 16;
206	devid |= pci_config_get16(statep->hda_pci_handle, PCI_CONF_DEVID);
207	statep->devid = devid;
208
209	name = AUDIOHD_DEV_CONFIG;
210	vers = AUDIOHD_DEV_VERSION;
211
212	switch (devid) {
213	case 0x1002437b:
214		name = "ATI HD Audio";
215		vers = "SB450";
216		break;
217	case 0x10024383:
218		name = "ATI HD Audio";
219		vers = "SB600";
220		break;
221	case 0x10029442:
222		name = "ATI HD Audio";
223		vers = "Radeon HD 4850";
224		break;
225	case 0x1002aa30:
226		name = "ATI HD Audio";
227		vers = "HD 48x0";
228		break;
229	case 0x1002aa38:
230		name = "ATI HD Audio";
231		vers = "Radeon HD 4670";
232		break;
233	case 0x10de026c:
234		name = "NVIDIA HD Audio";
235		vers = "MCP51";
236		break;
237	case 0x10de0371:
238		name = "NVIDIA HD Audio";
239		vers = "MCP55";
240		break;
241	case 0x10de03e4:
242		name = "NVIDIA HD Audio";
243		vers = "MCP61";
244		break;
245	case 0x10de03f0:
246		name = "NVIDIA HD Audio";
247		vers = "MCP61A";
248		break;
249	case 0x10de044a:
250		name = "NVIDIA HD Audio";
251		vers = "MCP65";
252		break;
253	case 0x10de055c:
254		name = "NVIDIA HD Audio";
255		vers = "MCP67";
256		break;
257	case 0x10de0774:
258		name = "NVIDIA HD Audio";
259		vers = "MCP78S";
260		break;
261	case 0x10de0ac0:
262		name = "NVIDIA HD Audio";
263		vers = "MCP79";
264		break;
265	case 0x11063288:
266		name = "VIA HD Audio";
267		vers = "HDA";
268		break;
269	case 0x80862668:
270		name = "Intel HD Audio";
271		vers = "ICH6";
272		break;
273	case 0x808627d8:
274		name = "Intel HD Audio";
275		vers = "ICH7";
276		break;
277	case 0x8086284b:
278		name = "Intel HD Audio";
279		vers = "ICH8";
280		break;
281	case 0x8086293e:
282		name = "Intel HD Audio";
283		vers = "ICH9";
284		break;
285	case 0x80863a3e:
286		name = "Intel HD Audio";
287		vers = "ICH10";
288		break;
289	}
290	/* set device information */
291	audio_dev_set_description(statep->adev, name);
292	audio_dev_set_version(statep->adev, vers);
293}
294
295static int
296audiohd_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
297{
298	audiohd_state_t		*statep;
299	int			instance;
300
301	instance = ddi_get_instance(dip);
302	switch (cmd) {
303	case DDI_ATTACH:
304		break;
305
306	case DDI_RESUME:
307		statep = ddi_get_driver_private(dip);
308		ASSERT(statep != NULL);
309		return (audiohd_resume(statep));
310
311	default:
312		return (DDI_FAILURE);
313	}
314
315	/* allocate the soft state structure */
316	statep = kmem_zalloc(sizeof (*statep), KM_SLEEP);
317	ddi_set_driver_private(dip, statep);
318
319	/* interrupt cookie and initialize mutex */
320	if (audiohd_init_state(statep, dip) != DDI_SUCCESS) {
321		cmn_err(CE_WARN,
322		    "audiohd_init_state failed");
323		goto error;
324	}
325
326	/* Set PCI command register to enable bus master and memeory I/O */
327	if (audiohd_init_pci(statep, &hda_dev_accattr) != DDI_SUCCESS) {
328		audio_dev_warn(statep->adev,
329		    "couldn't init pci regs");
330		goto error;
331	}
332
333	audiohd_set_chipset_info(statep);
334
335	if (audiohd_init_controller(statep) != DDI_SUCCESS) {
336		audio_dev_warn(statep->adev,
337		    "couldn't init controller");
338		goto error;
339	}
340
341	if (audiohd_create_codec(statep) != DDI_SUCCESS) {
342		audio_dev_warn(statep->adev,
343		    "couldn't create codec");
344		goto error;
345	}
346
347	audiohd_build_path(statep);
348
349	audiohd_get_channels(statep);
350	if (audiohd_allocate_port(statep) != DDI_SUCCESS) {
351		audio_dev_warn(statep->adev, "allocate port failure");
352		goto error;
353	}
354	audiohd_init_path(statep);
355	/* set up kernel statistics */
356	if ((statep->hda_ksp = kstat_create(DRVNAME, instance,
357	    DRVNAME, "controller", KSTAT_TYPE_INTR, 1,
358	    KSTAT_FLAG_PERSISTENT)) != NULL) {
359		kstat_install(statep->hda_ksp);
360	}
361
362	/* disable interrupts and clear interrupt status */
363	audiohd_disable_intr(statep);
364
365	mutex_init(&statep->hda_mutex, NULL, MUTEX_DRIVER, 0);
366
367	/*
368	 * Register audio controls.
369	 */
370	audiohd_create_controls(statep);
371
372	if (audio_dev_register(statep->adev) != DDI_SUCCESS) {
373		audio_dev_warn(statep->adev,
374		    "unable to register with framework");
375		goto error;
376	}
377	ddi_report_dev(dip);
378
379	return (DDI_SUCCESS);
380error:
381	audiohd_destroy(statep);
382	return (DDI_FAILURE);
383}
384
385static int
386audiohd_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
387{
388	audiohd_state_t		*statep;
389
390	statep = ddi_get_driver_private(dip);
391	ASSERT(statep != NULL);
392
393	switch (cmd) {
394	case DDI_DETACH:
395		break;
396
397	case DDI_SUSPEND:
398		return (audiohd_suspend(statep));
399
400	default:
401		return (DDI_FAILURE);
402	}
403	if (audio_dev_unregister(statep->adev) != DDI_SUCCESS)
404		return (DDI_FAILURE);
405
406	if (audiohd_beep)
407		(void) beep_fini();
408	audiohd_destroy(statep);
409	return (DDI_SUCCESS);
410}
411
412static struct dev_ops audiohd_dev_ops = {
413	DEVO_REV,		/* rev */
414	0,			/* refcnt */
415	NULL,			/* getinfo */
416	nulldev,		/* identify */
417	nulldev,		/* probe */
418	audiohd_attach,		/* attach */
419	audiohd_detach,		/* detach */
420	nodev,			/* reset */
421	NULL,			/* cb_ops */
422	NULL,			/* bus_ops */
423	NULL,			/* power */
424	audiohd_quiesce,	/* quiesce */
425};
426
427static struct modldrv audiohd_modldrv = {
428	&mod_driverops,			/* drv_modops */
429	"AudioHD",			/* linkinfo */
430	&audiohd_dev_ops,		/* dev_ops */
431};
432
433static struct modlinkage modlinkage = {
434	MODREV_1,
435	{ &audiohd_modldrv, NULL }
436};
437
438int
439_init(void)
440{
441	int	rv;
442
443	audio_init_ops(&audiohd_dev_ops, DRVNAME);
444	if ((rv = mod_install(&modlinkage)) != 0) {
445		audio_fini_ops(&audiohd_dev_ops);
446	}
447	return (rv);
448}
449
450int
451_fini(void)
452{
453	int	rv;
454
455	if ((rv = mod_remove(&modlinkage)) == 0) {
456		audio_fini_ops(&audiohd_dev_ops);
457	}
458	return (rv);
459}
460
461int
462_info(struct modinfo *modinfop)
463{
464	return (mod_info(&modlinkage, modinfop));
465}
466
467/*
468 * Audio routines
469 */
470
471static int
472audiohd_engine_format(void *arg)
473{
474	_NOTE(ARGUNUSED(arg));
475
476	return (AUDIO_FORMAT_S16_LE);
477}
478
479static int
480audiohd_engine_channels(void *arg)
481{
482	audiohd_port_t *port = arg;
483
484	return (port->nchan);
485}
486
487static int
488audiohd_engine_rate(void *arg)
489{
490	_NOTE(ARGUNUSED(arg));
491
492	return (48000);
493}
494static void
495audiohd_free_path(audiohd_state_t *statep)
496{
497	audiohd_path_t		*path;
498	int			i;
499
500	for (i = 0; i < statep->pathnum; i++) {
501		if (statep->path[i]) {
502			path = statep->path[i];
503			kmem_free(path, sizeof (audiohd_path_t));
504		}
505	}
506}
507static void
508audiohd_destroy(audiohd_state_t *statep)
509{
510	audiohd_stop_dma(statep);
511	if (statep->hda_ksp)
512		kstat_delete(statep->hda_ksp);
513	audiohd_free_port(statep);
514	audiohd_free_path(statep);
515	audiohd_destroy_codec(statep);
516	audiohd_del_controls(statep);
517	audiohd_fini_controller(statep);
518	audiohd_fini_pci(statep);
519	mutex_destroy(&statep->hda_mutex);
520	if (statep->adev)
521		audio_dev_free(statep->adev);
522	kmem_free(statep, sizeof (*statep));
523}
524/*
525 * get the max channels the hardware supported
526 */
527static void
528audiohd_get_channels(audiohd_state_t *statep)
529{
530	int		i;
531	uint8_t		maxp, assoc;
532
533	maxp = 2;
534	for (i = 0; i < AUDIOHD_MAX_ASSOC; i++) {
535		if (maxp < statep->chann[i]) {
536			maxp = statep->chann[i];
537			assoc = i;
538		}
539	}
540	statep->pchan = maxp;
541	statep->assoc = assoc;
542	/* for record, support stereo so far */
543	statep->rchan = 2;
544}
545static void
546audiohd_init_play_path(audiohd_path_t *path)
547{
548	int				i;
549	uint32_t			ctrl;
550	uint8_t				ctrl8;
551	uint8_t				nchann;
552	audiohd_widget_t		*widget;
553	audiohd_pin_t			*pin;
554	wid_t				wid;
555	audiohd_pin_color_t		color;
556
557	audiohd_state_t		*statep = path->statep;
558	hda_codec_t		*codec = path->codec;
559
560	/* enable SPDIF output */
561	for (i = 0; i < path->pin_nums; i++) {
562		wid = path->pin_wid[i];
563		widget = codec->widget[wid];
564		pin = (audiohd_pin_t *)widget->priv;
565		if (pin->device == DTYPE_SPDIF_OUT) {
566			ctrl = audioha_codec_verb_get(
567			    statep,
568			    codec->index,
569			    path->adda_wid,
570			    AUDIOHDC_VERB_GET_SPDIF_CTL,
571			    0);
572			ctrl |= AUDIOHD_SPDIF_ON;
573			ctrl8 = ctrl &
574			    AUDIOHD_SPDIF_MASK;
575			(void) audioha_codec_verb_get(
576			    statep,
577			    codec->index,
578			    path->adda_wid,
579			    AUDIOHDC_VERB_SET_SPDIF_LCL,
580			    ctrl8);
581			/*
582			 * We find that on intel ICH10 chipset with codec
583			 * ALC888, audio is scratchy if we set the tag on the
584			 * SPDIF path. So we just return here without setting
585			 * the tag for the path as a workaround.
586			 */
587			if (codec->codec_info->flags & NO_SPDIF)
588				return;
589		}
590	}
591	wid = path->pin_wid[0];
592	widget = codec->widget[wid];
593	pin = (audiohd_pin_t *)widget->priv;
594
595	/* two channels supported */
596	if (pin->device == DTYPE_SPEAKER ||
597	    pin->device == DTYPE_HP_OUT ||
598	    pin->assoc != statep->assoc) {
599		(void) audioha_codec_verb_get(
600		    statep,
601		    codec->index,
602		    path->adda_wid,
603		    AUDIOHDC_VERB_SET_STREAM_CHANN,
604		    statep->port[PORT_DAC]->index <<
605		    AUDIOHD_PLAY_TAG_OFF);
606		(void) audioha_codec_4bit_verb_get(
607		    statep,
608		    codec->index,
609		    path->adda_wid,
610		    AUDIOHDC_VERB_SET_CONV_FMT,
611		    AUDIOHD_FMT_PCM << 4 |
612		    statep->pchan - 1);
613	/* multichannel supported */
614	} else {
615		color = (pin->config >> AUDIOHD_PIN_CLR_OFF) &
616		    AUDIOHD_PIN_CLR_MASK;
617		switch (color) {
618		case AUDIOHD_PIN_BLACK:
619			nchann = statep->pchan - 2;
620			break;
621		case AUDIOHD_PIN_ORANGE:
622			nchann = 2;
623			break;
624		case AUDIOHD_PIN_GREY:
625			nchann = 4;
626			break;
627		case AUDIOHD_PIN_GREEN:
628			nchann = 0;
629			break;
630		default:
631			nchann = 0;
632			break;
633		}
634		(void) audioha_codec_verb_get(statep,
635		    codec->index,
636		    path->adda_wid,
637		    AUDIOHDC_VERB_SET_STREAM_CHANN,
638		    statep->port[PORT_DAC]->index <<
639		    AUDIOHD_PLAY_TAG_OFF |
640		    nchann);
641		(void) audioha_codec_4bit_verb_get(
642		    statep,
643		    codec->index,
644		    path->adda_wid,
645		    AUDIOHDC_VERB_SET_CONV_FMT,
646		    AUDIOHD_FMT_PCM << 4 |
647		    statep->pchan - 1);
648	}
649}
650static void
651audiohd_init_record_path(audiohd_path_t *path)
652{
653	audiohd_state_t		*statep = path->statep;
654	hda_codec_t		*codec = path->codec;
655	int			i;
656	wid_t			wid;
657	audiohd_pin_t		*pin;
658	audiohd_widget_t	*widget;
659
660	for (i = 0; i < path->pin_nums; i++) {
661		wid = path->pin_wid[i];
662		widget = codec->widget[wid];
663		pin = (audiohd_pin_t *)widget->priv;
664	/*
665	 * Since there is no SPDIF input device available for test,
666	 * we will use this code in the future to support SPDIF input
667	 */
668#if 0
669		if (pin->device == DTYPE_SPDIF_IN) {
670			ctrl = audioha_codec_verb_get(
671			    statep,
672			    codec->index,
673			    path->adda_wid,
674			    AUDIOHDC_VERB_GET_SPDIF_CTL,
675			    0);
676			ctrl |= AUDIOHD_SPDIF_ON;
677			ctrl8 = ctrl &
678			    AUDIOHD_SPDIF_MASK;
679			(void) audioha_codec_verb_get(
680			    statep,
681			    codec->index,
682			    path->adda_wid,
683			    AUDIOHDC_VERB_SET_SPDIF_LCL,
684			    ctrl8);
685			statep->inmask |= (1U << DTYPE_SPDIF_IN);
686		}
687#endif
688		if (pin->device == DTYPE_MIC_IN) {
689			if (((pin->config >>
690			    AUDIOHD_PIN_CONTP_OFF) &
691			    AUDIOHD_PIN_CONTP_MASK) ==
692			    AUDIOHD_PIN_CON_FIXED)
693				statep->port[PORT_ADC]->index = path->tag;
694		}
695		if ((pin->device == DTYPE_LINE_IN) ||
696		    (pin->device == DTYPE_CD) ||
697		    (pin->device == DTYPE_MIC_IN)) {
698			statep->inmask |= (1U << pin->device);
699		}
700	}
701	(void) audioha_codec_verb_get(statep,
702	    codec->index,
703	    path->adda_wid,
704	    AUDIOHDC_VERB_SET_STREAM_CHANN,
705	    path->tag <<
706	    AUDIOHD_REC_TAG_OFF);
707	(void) audioha_codec_4bit_verb_get(statep,
708	    codec->index,
709	    path->adda_wid,
710	    AUDIOHDC_VERB_SET_CONV_FMT,
711	    AUDIOHD_FMT_PCM << 4 | statep->rchan - 1);
712}
713
714static void
715audiohd_init_path(audiohd_state_t *statep)
716{
717	int				i;
718	audiohd_path_t			*path;
719
720	for (i = 0; i < statep->pathnum; i++) {
721		path = statep->path[i];
722		if (!path)
723			continue;
724		switch (path->path_type) {
725		case PLAY:
726			audiohd_init_play_path(path);
727			break;
728		case RECORD:
729			audiohd_init_record_path(path);
730			break;
731		default:
732			break;
733		}
734	}
735	statep->in_port = 0;
736}
737
738static int
739audiohd_reset_port(audiohd_port_t *port)
740{
741	uint16_t		regbase;
742	audiohd_state_t		*statep;
743	uint8_t			bTmp;
744	int			i;
745
746	regbase = port->regoff;
747	statep = port->statep;
748
749	bTmp = AUDIOHD_REG_GET8(regbase + AUDIOHD_SDREG_OFFSET_CTL);
750	/* stop stream */
751	bTmp &= ~AUDIOHD_REG_RIRBSIZE;
752	AUDIOHD_REG_SET8(regbase + AUDIOHD_SDREG_OFFSET_CTL, bTmp);
753
754	/* wait 40us for stream to stop as HD spec */
755	drv_usecwait(40);
756
757	/* reset stream */
758	bTmp |= AUDIOHDR_SD_CTL_SRST;
759	AUDIOHD_REG_SET8(regbase + AUDIOHD_SDREG_OFFSET_CTL, bTmp);
760
761	for (i = 0; i < AUDIOHD_RETRY_TIMES; i++) {
762		/* Empirical testing time, which works well */
763		drv_usecwait(50);
764		bTmp = AUDIOHD_REG_GET8(regbase + AUDIOHD_SDREG_OFFSET_CTL);
765		bTmp &= AUDIOHDR_SD_CTL_SRST;
766		if (bTmp)
767			break;
768	}
769
770	if (!bTmp) {
771		audio_dev_warn(statep->adev, "Failed to reset stream %d",
772		    port->index);
773		return (EIO);
774	}
775
776	/* Empirical testing time, which works well */
777	drv_usecwait(300);
778
779	/* exit reset stream */
780	bTmp &= ~AUDIOHDR_SD_CTL_SRST;
781	AUDIOHD_REG_SET8(regbase + AUDIOHD_SDREG_OFFSET_CTL, bTmp);
782
783	for (i = 0; i < AUDIOHD_RETRY_TIMES; i++) {
784		/* Empircal testing time */
785		drv_usecwait(50);
786		bTmp = AUDIOHD_REG_GET8(regbase + AUDIOHD_SDREG_OFFSET_CTL);
787		bTmp &= AUDIOHDR_SD_CTL_SRST;
788		if (!bTmp)
789			break;
790	}
791
792	if (bTmp) {
793		audio_dev_warn(statep->adev,
794		    "Failed to exit reset state for"
795		    " stream %d, bTmp=0x%02x", port->index, bTmp);
796		return (EIO);
797	}
798
799	AUDIOHD_REG_SET32(regbase + AUDIOHD_SDREG_OFFSET_BDLPL,
800	    (uint32_t)port->bdl_paddr);
801	AUDIOHD_REG_SET32(regbase + AUDIOHD_SDREG_OFFSET_BDLPU,
802	    (uint32_t)(port->bdl_paddr >> 32));
803	AUDIOHD_REG_SET16(regbase + AUDIOHD_SDREG_OFFSET_LVI,
804	    AUDIOHD_BDLE_NUMS - 1);
805	AUDIOHD_REG_SET32(regbase + AUDIOHD_SDREG_OFFSET_CBL, port->bufsize);
806
807	AUDIOHD_REG_SET16(regbase + AUDIOHD_SDREG_OFFSET_FORMAT,
808	    port->format << 4 | port->nchan - 1);
809
810	/* clear status */
811	AUDIOHD_REG_SET8(regbase + AUDIOHD_SDREG_OFFSET_STS,
812	    AUDIOHDR_SD_STS_BCIS | AUDIOHDR_SD_STS_FIFOE |
813	    AUDIOHDR_SD_STS_DESE);
814
815	/* set stream tag */
816	AUDIOHD_REG_SET8(regbase + AUDIOHD_SDREG_OFFSET_CTL +
817	    AUDIOHD_PLAY_CTL_OFF,
818	    (port->index) << AUDIOHD_PLAY_TAG_OFF);
819
820	return (0);
821}
822
823static int
824audiohd_engine_open(void *arg, int flag, unsigned *nframes, caddr_t *bufp)
825{
826	audiohd_port_t	*port = arg;
827
828	_NOTE(ARGUNUSED(flag));
829
830	port->count = 0;
831	port->curpos = 0;
832	*nframes = port->nframes;
833	*bufp = port->samp_kaddr;
834
835	return (0);
836}
837
838static int
839audiohd_engine_start(void *arg)
840{
841	audiohd_port_t		*port = arg;
842	audiohd_state_t		*statep = port->statep;
843	int			rv;
844
845	mutex_enter(&statep->hda_mutex);
846
847	if ((rv = audiohd_reset_port(port)) != 0) {
848		return (rv);
849	}
850	/* Start DMA */
851	AUDIOHD_REG_SET8(port->regoff + AUDIOHD_SDREG_OFFSET_CTL,
852	    AUDIOHDR_SD_CTL_SRUN);
853
854	mutex_exit(&statep->hda_mutex);
855	return (0);
856}
857
858static void
859audiohd_engine_stop(void *arg)
860{
861	audiohd_port_t		*port = arg;
862	audiohd_state_t		*statep = port->statep;
863
864	mutex_enter(&statep->hda_mutex);
865	AUDIOHD_REG_SET8(port->regoff + AUDIOHD_SDREG_OFFSET_CTL, 0);
866	mutex_exit(&statep->hda_mutex);
867}
868
869static void
870audiohd_update_port(audiohd_port_t *port)
871{
872	uint32_t		pos, len;
873	audiohd_state_t		*statep = port->statep;
874	int			i, ret;
875	uint32_t		status, resp = 0, respex = 0;
876	uint8_t			rirbsts;
877
878	pos = AUDIOHD_REG_GET32(port->regoff + AUDIOHD_SDREG_OFFSET_LPIB);
879	/* Convert the position into a frame count */
880	pos /= (port->nchan * 2);
881
882	ASSERT(pos <= port->nframes);
883	if (pos >= port->curpos) {
884		len = (pos - port->curpos);
885	} else {
886		len = pos + port->nframes - port->curpos;
887	}
888
889	ASSERT(len <= port->nframes);
890	port->curpos = pos;
891	port->count += len;
892
893	/*
894	 * Check unsolicited response from pins, maybe something plugged in or
895	 * out of the jack.
896	 */
897	status = AUDIOHD_REG_GET32(AUDIOHD_REG_INTSTS);
898	if (status == 0) {
899		/* No pending interrupt we should take care */
900		return;
901	}
902
903	if (status & AUDIOHD_CIS_MASK) {
904		/* Clear the unsolicited response interrupt */
905		rirbsts = AUDIOHD_REG_GET8(AUDIOHD_REG_RIRBSTS);
906		AUDIOHD_REG_SET8(AUDIOHD_REG_RIRBSTS, rirbsts);
907
908		/*
909		 * We have to wait and try several times to make sure the
910		 * unsolicited response is generated by our pins.
911		 * we need to make it work for audiohd spec 0.9, which is
912		 * just a draft version and requires more time to wait.
913		 */
914		for (i = 0; i < AUDIOHD_TEST_TIMES; i++) {
915			ret = audiohd_response_from_codec(statep, &resp,
916			    &respex);
917			if ((ret == DDI_SUCCESS) &&
918			    (respex & AUDIOHD_RIRB_UR_MASK)) {
919				/*
920				 * A pin may generate more than one ur rirb,
921				 * we only need handle one of them, and clear
922				 * the other ones
923				 */
924				statep->hda_rirb_rp =
925				    AUDIOHD_REG_GET16(AUDIOHD_REG_RIRBWP) &
926				    AUDIOHD_RIRB_WPMASK;
927				audiohd_pin_sense(statep, resp, respex);
928				break;
929			}
930		}
931	}
932}
933
934static uint64_t
935audiohd_engine_count(void *arg)
936{
937	audiohd_port_t	*port = arg;
938	audiohd_state_t	*statep = port->statep;
939	uint64_t	val;
940
941	mutex_enter(&statep->hda_mutex);
942	audiohd_update_port(port);
943	val = port->count;
944	mutex_exit(&statep->hda_mutex);
945	return (val);
946}
947
948static void
949audiohd_engine_close(void *arg)
950{
951	_NOTE(ARGUNUSED(arg));
952}
953
954static void
955audiohd_engine_sync(void *arg, unsigned nframes)
956{
957	audiohd_port_t *port = arg;
958
959	_NOTE(ARGUNUSED(nframes));
960
961	(void) ddi_dma_sync(port->samp_dmah, 0, 0, port->sync_dir);
962
963}
964
965audio_engine_ops_t audiohd_engine_ops = {
966	AUDIO_ENGINE_VERSION,		/* version number */
967	audiohd_engine_open,
968	audiohd_engine_close,
969	audiohd_engine_start,
970	audiohd_engine_stop,
971	audiohd_engine_count,
972	audiohd_engine_format,
973	audiohd_engine_channels,
974	audiohd_engine_rate,
975	audiohd_engine_sync,
976	NULL,
977	NULL,
978	NULL
979};
980
981static int
982audiohd_get_control(void *arg, uint64_t *val)
983{
984	audiohd_ctrl_t	*ac = arg;
985
986	*val = ac->val;
987	return (0);
988}
989
990static void
991audiohd_do_set_pin_volume(audiohd_state_t *statep, audiohd_path_t *path,
992    uint64_t val)
993{
994	uint8_t				l, r;
995	uint_t				tmp;
996	int				gain;
997
998	if (path->mute_wid && val == 0) {
999		(void) audioha_codec_4bit_verb_get(
1000		    statep,
1001		    path->codec->index,
1002		    path->mute_wid,
1003		    AUDIOHDC_VERB_SET_AMP_MUTE,
1004		    path->mute_dir |
1005		    AUDIOHDC_AMP_SET_LNR |
1006		    AUDIOHDC_AMP_SET_MUTE);
1007		return;
1008	}
1009
1010	l = (val & 0xff00) >> 8;
1011	r = (val & 0xff);
1012	tmp = l * path->gain_bits / 100;
1013	(void) audioha_codec_4bit_verb_get(statep,
1014	    path->codec->index,
1015	    path->gain_wid,
1016	    AUDIOHDC_VERB_SET_AMP_MUTE,
1017	    AUDIOHDC_AMP_SET_LEFT | path->gain_dir |
1018	    tmp);
1019	tmp = r * path->gain_bits / 100;
1020	(void) audioha_codec_4bit_verb_get(statep,
1021	    path->codec->index,
1022	    path->gain_wid,
1023	    AUDIOHDC_VERB_SET_AMP_MUTE,
1024	    AUDIOHDC_AMP_SET_RIGHT | path->gain_dir |
1025	    tmp);
1026
1027	if (path->mute_wid && path->mute_wid != path->gain_wid) {
1028		gain = AUDIOHDC_GAIN_MAX;
1029		(void) audioha_codec_4bit_verb_get(
1030		    statep,
1031		    path->codec->index,
1032		    path->mute_wid,
1033		    AUDIOHDC_VERB_SET_AMP_MUTE,
1034		    path->mute_dir |
1035		    AUDIOHDC_AMP_SET_LEFT |
1036		    gain);
1037		(void) audioha_codec_4bit_verb_get(
1038		    statep,
1039		    path->codec->index,
1040		    path->mute_wid,
1041		    AUDIOHDC_VERB_SET_AMP_MUTE,
1042		    path->mute_dir |
1043		    AUDIOHDC_AMP_SET_RIGHT |
1044		    gain);
1045	}
1046}
1047
1048static void
1049audiohd_set_pin_volume(audiohd_state_t *statep, audiohda_device_type_t type)
1050{
1051	int				i, j;
1052	audiohd_path_t			*path;
1053	audiohd_widget_t		*widget;
1054	wid_t				wid;
1055	audiohd_pin_t			*pin;
1056	hda_codec_t			*codec;
1057	uint64_t			val;
1058	audiohd_ctrl_t			control;
1059
1060	switch (type) {
1061		case DTYPE_SPEAKER:
1062			control = statep->ctrls[CTL_SPEAKER];
1063			if (control.ctrl == NULL)
1064				return;
1065			val = control.val;
1066			break;
1067		case DTYPE_HP_OUT:
1068			control = statep->ctrls[CTL_HEADPHONE];
1069			if (control.ctrl == NULL)
1070				return;
1071			val = control.val;
1072			break;
1073		case DTYPE_LINEOUT:
1074			control = statep->ctrls[CTL_FRONT];
1075			if (control.ctrl == NULL)
1076				return;
1077			val = control.val;
1078			break;
1079		case DTYPE_CD:
1080			control = statep->ctrls[CTL_CD];
1081			if (control.ctrl == NULL)
1082				return;
1083			val = control.val;
1084			break;
1085		case DTYPE_LINE_IN:
1086			control = statep->ctrls[CTL_LINEIN];
1087			if (control.ctrl == NULL)
1088				return;
1089			val = control.val;
1090			break;
1091		case DTYPE_MIC_IN:
1092			control = statep->ctrls[CTL_MIC];
1093			if (control.ctrl == NULL)
1094				return;
1095			val = control.val;
1096			break;
1097	}
1098
1099	for (i = 0; i < statep->pathnum; i++) {
1100		path = statep->path[i];
1101		if (!path)
1102			continue;
1103		codec = path->codec;
1104		for (j = 0; j < path->pin_nums; j++) {
1105			wid = path->pin_wid[j];
1106			widget = codec->widget[wid];
1107			pin = (audiohd_pin_t *)widget->priv;
1108			if ((pin->device == type) && path->gain_wid) {
1109				audiohd_do_set_pin_volume(statep, path, val);
1110			}
1111		}
1112	}
1113}
1114
1115
1116static void
1117audiohd_set_pin_volume_by_color(audiohd_state_t *statep,
1118    audiohd_pin_color_t color)
1119{
1120	int			i, j;
1121	audiohd_path_t		*path;
1122	audiohd_widget_t	*widget;
1123	wid_t			wid;
1124	audiohd_pin_t		*pin;
1125	hda_codec_t		*codec;
1126	uint8_t			l, r;
1127	uint64_t		val;
1128	audiohd_pin_color_t	clr;
1129	audiohd_ctrl_t		control;
1130
1131	switch (color) {
1132		case AUDIOHD_PIN_GREEN:
1133			control = statep->ctrls[CTL_FRONT];
1134			if (control.ctrl == NULL)
1135				return;
1136			val = control.val;
1137			break;
1138		case AUDIOHD_PIN_BLACK:
1139			control = statep->ctrls[CTL_REAR];
1140			if (control.ctrl == NULL)
1141				return;
1142			val = control.val;
1143			break;
1144		case AUDIOHD_PIN_ORANGE:
1145			control = statep->ctrls[CTL_CENTER];
1146			if (control.ctrl == NULL)
1147				return;
1148			l = control.val;
1149			control = statep->ctrls[CTL_LFE];
1150			if (control.ctrl == NULL)
1151				return;
1152			r = control.val;
1153			val = (l << 8) | r;
1154			break;
1155		case AUDIOHD_PIN_GREY:
1156			control = statep->ctrls[CTL_SURROUND];
1157			if (control.ctrl == NULL)
1158				return;
1159			val = control.val;
1160			break;
1161	}
1162
1163	for (i = 0; i < statep->pathnum; i++) {
1164		path = statep->path[i];
1165		if (!path)
1166			continue;
1167		codec = path->codec;
1168		for (j = 0; j < path->pin_nums; j++) {
1169			wid = path->pin_wid[j];
1170			widget = codec->widget[wid];
1171			pin = (audiohd_pin_t *)widget->priv;
1172			clr = (pin->config >> AUDIOHD_PIN_CLR_OFF) &
1173			    AUDIOHD_PIN_CLR_MASK;
1174			if ((clr == color) && path->gain_wid) {
1175				audiohd_do_set_pin_volume(statep, path, val);
1176			}
1177		}
1178	}
1179}
1180
1181static int
1182audiohd_set_input_pin(audiohd_state_t *statep)
1183{
1184	uint64_t		val;
1185	hda_codec_t		*codec;
1186	audiohd_pin_t		*pin;
1187	audiohd_path_t		*path;
1188	audiohd_widget_t	*widget, *w;
1189	int			i, j;
1190	wid_t			wid, pin_wid = 0;
1191	uint32_t		set_val;
1192
1193	val = statep->ctrls[CTL_RECSRC].val;
1194	set_val = ddi_ffs(val & 0xffff) - 1;
1195	for (i = 0; i < statep->pathnum; i++) {
1196		path = statep->path[i];
1197		if (path == NULL || path->path_type != RECORD)
1198			continue;
1199
1200		switch (set_val) {
1201		case DTYPE_LINE_IN:
1202		case DTYPE_MIC_IN:
1203		case DTYPE_CD:
1204			for (j = 0; j < path->pin_nums; j++) {
1205				wid = path->pin_wid[j];
1206				widget = path->codec->widget[wid];
1207				pin = (audiohd_pin_t *)widget->priv;
1208				if ((1U << pin->device) == val) {
1209					AUDIOHD_ENABLE_PIN_IN(statep,
1210					    path->codec->index,
1211					    pin->wid);
1212					pin_wid = pin->wid;
1213					codec = path->codec;
1214					statep->in_port = pin->device;
1215				} else if (statep->in_port == pin->device) {
1216					AUDIOHD_DISABLE_PIN_IN(statep,
1217					    path->codec->index,
1218					    pin->wid);
1219				}
1220			}
1221			break;
1222		default:
1223			break;
1224		}
1225		break;
1226	}
1227	if (pin_wid == 0)
1228		return (DDI_SUCCESS);
1229	w = codec->widget[pin_wid];
1230	pin = (audiohd_pin_t *)w->priv;
1231	w = codec->widget[pin->adc_dac_wid];
1232	path = (audiohd_path_t *)w->priv;
1233	/*
1234	 * If there is a real selector in this input path,
1235	 * we select the right one input for the selector.
1236	 */
1237	if (path->sum_wid) {
1238		w = codec->widget[path->sum_wid];
1239		if (w->type == WTYPE_AUDIO_SEL) {
1240			for (i = 0; i < path->pin_nums; i++)
1241				if (path->pin_wid[i] == pin_wid)
1242					break;
1243			(void) audioha_codec_verb_get(
1244			    statep, codec->index, path->sum_wid,
1245			    AUDIOHDC_VERB_SET_CONN_SEL,
1246			    path->sum_selconn[i]);
1247		}
1248	}
1249	return (DDI_SUCCESS);
1250}
1251
1252static void
1253audiohd_set_pin_monitor_gain(hda_codec_t *codec, audiohd_state_t *statep,
1254    uint_t caddr, audiohd_pin_t *pin, uint64_t gain)
1255{
1256	int 			i, k;
1257	uint_t			ltmp, rtmp;
1258	audiohd_widget_t	*widget;
1259	uint8_t		l, r;
1260
1261	l = (gain & 0xff00) >> 8;
1262	r = (gain & 0xff);
1263
1264	for (k = 0; k < pin->num; k++) {
1265		ltmp = l * pin->mg_gain[k] / 100;
1266		rtmp = r * pin->mg_gain[k] / 100;
1267		widget = codec->widget[pin->mg_wid[k]];
1268		if (pin->mg_dir[k] == AUDIOHDC_AMP_SET_OUTPUT) {
1269			(void) audioha_codec_4bit_verb_get(
1270			    statep,
1271			    caddr,
1272			    pin->mg_wid[k],
1273			    AUDIOHDC_VERB_SET_AMP_MUTE,
1274			    AUDIOHDC_AMP_SET_LEFT|
1275			    pin->mg_dir[k] | ltmp);
1276			(void) audioha_codec_4bit_verb_get(
1277			    statep,
1278			    caddr,
1279			    pin->mg_wid[k],
1280			    AUDIOHDC_VERB_SET_AMP_MUTE,
1281			    AUDIOHDC_AMP_SET_RIGHT|
1282			    pin->mg_dir[k] | rtmp);
1283		} else if (pin->mg_dir[k] == AUDIOHDC_AMP_SET_INPUT) {
1284			for (i = 0; i < widget->used; i++) {
1285				(void) audioha_codec_4bit_verb_get(
1286				    statep,
1287				    caddr,
1288				    pin->mg_wid[k],
1289				    AUDIOHDC_VERB_SET_AMP_MUTE,
1290				    AUDIOHDC_AMP_SET_RIGHT|
1291				    widget->monitor_path_next[i]<<
1292				    AUDIOHDC_AMP_SET_INDEX_OFFSET |
1293				    pin->mg_dir[k] | rtmp);
1294				(void) audioha_codec_4bit_verb_get(
1295				    statep,
1296				    caddr,
1297				    pin->mg_wid[k],
1298				    AUDIOHDC_VERB_SET_AMP_MUTE,
1299				    AUDIOHDC_AMP_SET_LEFT|
1300				    widget->monitor_path_next[i]<<
1301				    AUDIOHDC_AMP_SET_INDEX_OFFSET |
1302				    pin->mg_dir[k] | ltmp);
1303			}
1304		}
1305	}
1306}
1307
1308static void
1309audiohd_set_monitor_gain(audiohd_state_t *statep)
1310{
1311	int			i, j;
1312	audiohd_path_t		*path;
1313	uint_t			caddr;
1314	audiohd_widget_t	*w;
1315	wid_t			wid;
1316	audiohd_pin_t		*pin;
1317	audiohd_ctrl_t		ctrl;
1318	uint64_t		val;
1319
1320	ctrl = statep->ctrls[CTL_MONGAIN];
1321	val = ctrl.val;
1322
1323	for (i = 0; i < statep->pathnum; i++) {
1324		path = statep->path[i];
1325		if (path == NULL || path->path_type != PLAY)
1326			continue;
1327		caddr = path->codec->index;
1328		for (j = 0; j < path->pin_nums; j++) {
1329			wid = path->pin_wid[j];
1330			w = path->codec->widget[wid];
1331			pin = (audiohd_pin_t *)w->priv;
1332			audiohd_set_pin_monitor_gain(path->codec, statep,
1333			    caddr, pin, val);
1334		}
1335	}
1336
1337}
1338
1339static void
1340audiohd_set_beep_volume(audiohd_state_t *statep)
1341{
1342	int			i;
1343	audiohd_path_t		*path;
1344	hda_codec_t		*codec;
1345	uint64_t		val;
1346	uint_t			tmp;
1347	audiohd_ctrl_t		control;
1348	uint32_t		vid;
1349
1350	control = statep->ctrls[CTL_BEEP];
1351	val = control.val;
1352	for (i = 0; i < statep->pathnum; i++) {
1353		path = statep->path[i];
1354		if (!path || path->path_type != BEEP)
1355			continue;
1356		codec = path->codec;
1357		vid = codec->vid;
1358		vid = vid >> 16;
1359
1360		switch (vid) {
1361		case  AUDIOHD_VID_SIGMATEL:
1362			/*
1363			 * Sigmatel HD codec specific operation.
1364			 * There is a workaround,
1365			 * Due to Sigmatel HD codec hardware problem,
1366			 * which it can't mute beep when volume is 0.
1367			 * So add global value audiohd_beep_vol,
1368			 * Set freq to 0 when volume is 0.
1369			 */
1370			tmp = val * path->gain_bits / 100;
1371			if (tmp == 0) {
1372				audiohd_beep_vol = 0;
1373			} else {
1374				audiohd_beep_vol = tmp;
1375				(void) audioha_codec_verb_get(
1376				    statep,
1377				    codec->index,
1378				    path->beep_wid,
1379				    AUDIOHDC_VERB_SET_BEEP_VOL,
1380				    tmp);
1381			}
1382			break;
1383
1384		default:
1385			/* Common operation based on audiohd spec */
1386			audiohd_do_set_beep_volume(statep, path, val);
1387			break;
1388		}
1389	}
1390}
1391
1392static void
1393audiohd_do_set_beep_volume(audiohd_state_t *statep, audiohd_path_t *path,
1394    uint64_t val)
1395{
1396	uint8_t		l, r;
1397	uint_t		tmp;
1398	int		gain;
1399
1400	if (val == 0) {
1401		(void) audioha_codec_4bit_verb_get(
1402		    statep,
1403		    path->codec->index,
1404		    path->mute_wid,
1405		    AUDIOHDC_VERB_SET_AMP_MUTE,
1406		    path->mute_dir |
1407		    AUDIOHDC_AMP_SET_LNR |
1408		    AUDIOHDC_AMP_SET_MUTE);
1409		return;
1410	}
1411
1412	r = (val & 0xff);
1413	l = r;
1414
1415	tmp = l * path->gain_bits / 100;
1416	(void) audioha_codec_4bit_verb_get(statep,
1417	    path->codec->index,
1418	    path->gain_wid,
1419	    AUDIOHDC_VERB_SET_AMP_MUTE,
1420	    AUDIOHDC_AMP_SET_LEFT | path->gain_dir |
1421	    tmp);
1422	tmp = r * path->gain_bits / 100;
1423	(void) audioha_codec_4bit_verb_get(statep,
1424	    path->codec->index,
1425	    path->gain_wid,
1426	    AUDIOHDC_VERB_SET_AMP_MUTE,
1427	    AUDIOHDC_AMP_SET_RIGHT | path->gain_dir |
1428	    tmp);
1429	if (path->mute_wid != path->gain_wid) {
1430		gain = AUDIOHDC_GAIN_MAX;
1431		(void) audioha_codec_4bit_verb_get(
1432		    statep,
1433		    path->codec->index,
1434		    path->mute_wid,
1435		    AUDIOHDC_VERB_SET_AMP_MUTE,
1436		    path->mute_dir |
1437		    AUDIOHDC_AMP_SET_LEFT |
1438		    gain);
1439		(void) audioha_codec_4bit_verb_get(
1440		    statep,
1441		    path->codec->index,
1442		    path->mute_wid,
1443		    AUDIOHDC_VERB_SET_AMP_MUTE,
1444		    path->mute_dir |
1445		    AUDIOHDC_AMP_SET_RIGHT |
1446		    gain);
1447	}
1448}
1449
1450static void
1451audiohd_configure_output(audiohd_state_t *statep)
1452{
1453	audiohd_set_pin_volume(statep, DTYPE_LINEOUT);
1454	audiohd_set_pin_volume(statep, DTYPE_SPEAKER);
1455	audiohd_set_pin_volume(statep, DTYPE_HP_OUT);
1456
1457	audiohd_set_pin_volume_by_color(statep, AUDIOHD_PIN_GREEN);
1458	audiohd_set_pin_volume_by_color(statep, AUDIOHD_PIN_BLACK);
1459	audiohd_set_pin_volume_by_color(statep, AUDIOHD_PIN_GREY);
1460	audiohd_set_pin_volume_by_color(statep, AUDIOHD_PIN_ORANGE);
1461}
1462
1463static void
1464audiohd_configure_input(audiohd_state_t *statep)
1465{
1466	(void) audiohd_set_input_pin(statep);
1467	audiohd_set_monitor_gain(statep);
1468	audiohd_set_pin_volume(statep, DTYPE_LINE_IN);
1469	audiohd_set_pin_volume(statep, DTYPE_CD);
1470	audiohd_set_pin_volume(statep, DTYPE_MIC_IN);
1471}
1472
1473static int
1474audiohd_set_recsrc(void *arg, uint64_t val)
1475{
1476	audiohd_ctrl_t	*pc = arg;
1477	audiohd_state_t *statep = pc->statep;
1478
1479	if (val & ~(statep->inmask))
1480		return (EINVAL);
1481
1482	mutex_enter(&statep->hda_mutex);
1483	pc->val = val;
1484	audiohd_configure_input(statep);
1485	mutex_exit(&statep->hda_mutex);
1486	return (0);
1487}
1488
1489static int
1490audiohd_set_rear(void *arg, uint64_t val)
1491{
1492	audiohd_ctrl_t	*pc = arg;
1493	audiohd_state_t	*statep = pc->statep;
1494	AUDIOHD_CHECK_2CHANNELS_VOLUME(val);
1495
1496	mutex_enter(&statep->hda_mutex);
1497	pc->val = val;
1498	audiohd_set_pin_volume_by_color(statep, AUDIOHD_PIN_BLACK);
1499	mutex_exit(&statep->hda_mutex);
1500
1501	return (0);
1502}
1503
1504static int
1505audiohd_set_center(void *arg, uint64_t val)
1506{
1507	audiohd_ctrl_t	*pc = arg;
1508	audiohd_state_t	*statep = pc->statep;
1509	AUDIOHD_CHECK_CHANNEL_VOLUME(val);
1510
1511	mutex_enter(&statep->hda_mutex);
1512	pc->val = val;
1513	audiohd_set_pin_volume_by_color(statep, AUDIOHD_PIN_ORANGE);
1514	mutex_exit(&statep->hda_mutex);
1515
1516	return (0);
1517}
1518
1519static int
1520audiohd_set_surround(void *arg, uint64_t val)
1521{
1522	audiohd_ctrl_t	*pc = arg;
1523	audiohd_state_t	*statep = pc->statep;
1524	AUDIOHD_CHECK_2CHANNELS_VOLUME(val);
1525
1526	mutex_enter(&statep->hda_mutex);
1527	pc->val = val;
1528	audiohd_set_pin_volume_by_color(statep, AUDIOHD_PIN_GREY);
1529	mutex_exit(&statep->hda_mutex);
1530
1531	return (0);
1532}
1533
1534static int
1535audiohd_set_lfe(void *arg, uint64_t val)
1536{
1537	audiohd_ctrl_t	*pc = arg;
1538	audiohd_state_t	*statep = pc->statep;
1539	AUDIOHD_CHECK_CHANNEL_VOLUME(val);
1540
1541	mutex_enter(&statep->hda_mutex);
1542	pc->val = val;
1543	audiohd_set_pin_volume_by_color(statep, AUDIOHD_PIN_ORANGE);
1544	mutex_exit(&statep->hda_mutex);
1545
1546	return (0);
1547}
1548static int
1549audiohd_set_speaker(void *arg, uint64_t val)
1550{
1551	audiohd_ctrl_t	*pc = arg;
1552	audiohd_state_t	*statep = pc->statep;
1553	AUDIOHD_CHECK_2CHANNELS_VOLUME(val);
1554
1555	mutex_enter(&statep->hda_mutex);
1556	pc->val = val;
1557	audiohd_set_pin_volume(statep, DTYPE_SPEAKER);
1558	mutex_exit(&statep->hda_mutex);
1559
1560	return (0);
1561}
1562static int
1563audiohd_set_front(void *arg, uint64_t val)
1564{
1565	audiohd_ctrl_t	*pc = arg;
1566	audiohd_state_t	*statep = pc->statep;
1567	AUDIOHD_CHECK_2CHANNELS_VOLUME(val);
1568
1569	mutex_enter(&statep->hda_mutex);
1570	pc->val = val;
1571	audiohd_set_pin_volume_by_color(statep, AUDIOHD_PIN_GREEN);
1572	mutex_exit(&statep->hda_mutex);
1573
1574	return (0);
1575}
1576static int
1577audiohd_set_headphone(void *arg, uint64_t val)
1578{
1579	audiohd_ctrl_t	*pc = arg;
1580	audiohd_state_t	*statep = pc->statep;
1581	AUDIOHD_CHECK_2CHANNELS_VOLUME(val);
1582
1583	mutex_enter(&statep->hda_mutex);
1584	pc->val = val;
1585	audiohd_set_pin_volume(statep, DTYPE_HP_OUT);
1586	mutex_exit(&statep->hda_mutex);
1587
1588	return (0);
1589}
1590static int
1591audiohd_set_linein(void *arg, uint64_t val)
1592{
1593	audiohd_ctrl_t	*pc = arg;
1594	audiohd_state_t	*statep = pc->statep;
1595	AUDIOHD_CHECK_2CHANNELS_VOLUME(val);
1596
1597	mutex_enter(&statep->hda_mutex);
1598	pc->val = val;
1599	audiohd_set_pin_volume(statep, DTYPE_LINE_IN);
1600	mutex_exit(&statep->hda_mutex);
1601
1602	return (0);
1603}
1604
1605static int
1606audiohd_set_mic(void *arg, uint64_t val)
1607{
1608	audiohd_ctrl_t	*pc = arg;
1609	audiohd_state_t	*statep = pc->statep;
1610	AUDIOHD_CHECK_2CHANNELS_VOLUME(val);
1611
1612	mutex_enter(&statep->hda_mutex);
1613	pc->val = val;
1614	audiohd_set_pin_volume(statep, DTYPE_MIC_IN);
1615	mutex_exit(&statep->hda_mutex);
1616
1617	return (0);
1618}
1619
1620static int
1621audiohd_set_cd(void *arg, uint64_t val)
1622{
1623	audiohd_ctrl_t	*pc = arg;
1624	audiohd_state_t	*statep = pc->statep;
1625	AUDIOHD_CHECK_2CHANNELS_VOLUME(val);
1626
1627	mutex_enter(&statep->hda_mutex);
1628	pc->val = val;
1629	audiohd_set_pin_volume(statep, DTYPE_CD);
1630	mutex_exit(&statep->hda_mutex);
1631
1632	return (0);
1633}
1634
1635static int
1636audiohd_set_mongain(void *arg, uint64_t val)
1637{
1638	audiohd_ctrl_t	*pc = arg;
1639	audiohd_state_t	*statep = pc->statep;
1640	AUDIOHD_CHECK_2CHANNELS_VOLUME(val);
1641
1642	mutex_enter(&statep->hda_mutex);
1643	pc->val = val;
1644	audiohd_set_monitor_gain(statep);
1645	mutex_exit(&statep->hda_mutex);
1646
1647	return (0);
1648}
1649
1650static int
1651audiohd_set_beep(void *arg, uint64_t val)
1652{
1653	audiohd_ctrl_t  *pc = arg;
1654	audiohd_state_t *statep = pc->statep;
1655	AUDIOHD_CHECK_CHANNEL_VOLUME(val);
1656
1657	mutex_enter(&statep->hda_mutex);
1658	pc->val = val;
1659	audiohd_set_beep_volume(statep);
1660	mutex_exit(&statep->hda_mutex);
1661
1662	return (0);
1663}
1664
1665#define	PLAYCTL	(AUDIO_CTRL_FLAG_RW | AUDIO_CTRL_FLAG_PLAY)
1666#define	RECCTL	(AUDIO_CTRL_FLAG_RW | AUDIO_CTRL_FLAG_REC)
1667#define	MONCTL	(AUDIO_CTRL_FLAG_RW | AUDIO_CTRL_FLAG_MONITOR)
1668#define	PCMVOL	(PLAYCTL | AUDIO_CTRL_FLAG_PCMVOL)
1669#define	MONVOL	(MONCTL | AUDIO_CTRL_FLAG_MONVOL)
1670#define	MAINVOL	(PLAYCTL | AUDIO_CTRL_FLAG_MAINVOL)
1671#define	RECVOL	(RECCTL | AUDIO_CTRL_FLAG_RECVOL)
1672#define	RWCTL	AUDIO_CTRL_FLAG_RW
1673
1674static void
1675audiohd_del_controls(audiohd_state_t *statep)
1676{
1677	int		i;
1678	for (i = 0; i < CTL_MAX; i++) {
1679		audiohd_ctrl_t *ac = &statep->ctrls[i];
1680		if (ac->ctrl != NULL) {
1681			audio_dev_del_control(ac->ctrl);
1682			ac->ctrl = NULL;
1683		}
1684	}
1685}
1686
1687static void
1688audiohd_create_mono(audiohd_state_t *statep, int ctl,
1689    const char *id, int flags, int defval, audio_ctrl_wr_t fn)
1690{
1691	audiohd_ctrl_t		*ac;
1692	audio_ctrl_desc_t	desc;
1693
1694	bzero(&desc, sizeof (desc));
1695
1696	ac = &statep->ctrls[ctl];
1697	ac->statep = statep;
1698	ac->num = ctl;
1699
1700	desc.acd_name = id;
1701	desc.acd_type = AUDIO_CTRL_TYPE_MONO;
1702	desc.acd_minvalue = 0;
1703	desc.acd_maxvalue = 100;
1704	desc.acd_flags = flags;
1705
1706	ac->val = defval;
1707	ac->ctrl = audio_dev_add_control(statep->adev, &desc,
1708	    audiohd_get_control, fn, ac);
1709}
1710
1711static void
1712audiohd_create_stereo(audiohd_state_t *statep, int ctl,
1713    const char *id, int flags, int defval, audio_ctrl_wr_t fn)
1714{
1715	audiohd_ctrl_t		*ac;
1716	audio_ctrl_desc_t	desc;
1717
1718	bzero(&desc, sizeof (desc));
1719
1720	ac = &statep->ctrls[ctl];
1721	ac->statep = statep;
1722	ac->num = ctl;
1723
1724	desc.acd_name = id;
1725	desc.acd_type = AUDIO_CTRL_TYPE_STEREO;
1726	desc.acd_minvalue = 0;
1727	desc.acd_maxvalue = 100;
1728	desc.acd_flags = flags;
1729
1730	ac->val = (defval << 8) | defval;
1731	ac->ctrl = audio_dev_add_control(statep->adev, &desc,
1732	    audiohd_get_control, fn, ac);
1733}
1734
1735static void
1736audiohd_create_recsrc(audiohd_state_t *statep)
1737{
1738	audiohd_ctrl_t *ac;
1739	audio_ctrl_desc_t desc;
1740
1741	bzero(&desc, sizeof (desc));
1742
1743	ac = &statep->ctrls[CTL_RECSRC];
1744	ac->statep = statep;
1745	ac->num = CTL_RECSRC;
1746
1747	desc.acd_name = AUDIO_CTRL_ID_RECSRC;
1748	desc.acd_type = AUDIO_CTRL_TYPE_ENUM;
1749	desc.acd_flags = RECCTL;
1750	desc.acd_minvalue = statep->inmask;
1751	desc.acd_maxvalue = statep->inmask;
1752	for (int i = 0; audiohd_dtypes[i]; i++) {
1753		desc.acd_enum[i] = audiohd_dtypes[i];
1754	}
1755
1756	ac->val = (1U << DTYPE_MIC_IN);
1757	ac->ctrl = audio_dev_add_control(statep->adev, &desc,
1758	    audiohd_get_control, audiohd_set_recsrc, ac);
1759}
1760
1761static void
1762audiohd_create_controls(audiohd_state_t *statep)
1763{
1764	wid_t			wid;
1765	audiohd_widget_t	*widget;
1766	audiohd_path_t		*path;
1767	hda_codec_t		*codec;
1768	audiohd_pin_t		*pin;
1769	audiohd_pin_color_t	color;
1770	int			i, j;
1771
1772	/*
1773	 * We always use soft volume control to adjust PCM volume.
1774	 */
1775	audio_dev_add_soft_volume(statep->adev);
1776
1777	/* Allocate other controls */
1778	for (i = 0; i < statep->pathnum; i++) {
1779		path = statep->path[i];
1780		if (path == NULL)
1781			continue;
1782		codec = path->codec;
1783
1784		for (j = 0; j < path->pin_nums; j++) {
1785			wid = path->pin_wid[j];
1786			widget = codec->widget[wid];
1787			pin = (audiohd_pin_t *)widget->priv;
1788			color = (pin->config >> AUDIOHD_PIN_CLR_OFF) &
1789			    AUDIOHD_PIN_CLR_MASK;
1790			if (color == AUDIOHD_PIN_GREEN) {
1791				audiohd_create_stereo(statep, CTL_FRONT,
1792				    AUDIO_CTRL_ID_FRONT, MAINVOL, 75,
1793				    audiohd_set_front);
1794			} else if (color == AUDIOHD_PIN_BLACK &&
1795			    pin->device != DTYPE_HP_OUT &&
1796			    pin->device != DTYPE_MIC_IN) {
1797				audiohd_create_stereo(statep, CTL_REAR,
1798				    AUDIO_CTRL_ID_REAR, MAINVOL, 75,
1799				    audiohd_set_rear);
1800			} else if (color == AUDIOHD_PIN_ORANGE) {
1801				audiohd_create_mono(statep, CTL_CENTER,
1802				    AUDIO_CTRL_ID_CENTER, MAINVOL, 75,
1803				    audiohd_set_center);
1804				audiohd_create_mono(statep, CTL_LFE,
1805				    AUDIO_CTRL_ID_LFE, MAINVOL, 75,
1806				    audiohd_set_lfe);
1807			} else if (color == AUDIOHD_PIN_GREY) {
1808				audiohd_create_stereo(statep, CTL_SURROUND,
1809				    AUDIO_CTRL_ID_SURROUND, MAINVOL, 75,
1810				    audiohd_set_surround);
1811			}
1812			if (pin->device == DTYPE_SPEAKER) {
1813				audiohd_create_stereo(statep, CTL_SPEAKER,
1814				    AUDIO_CTRL_ID_SPEAKER, MAINVOL, 75,
1815				    audiohd_set_speaker);
1816			} else if (pin->device == DTYPE_HP_OUT) {
1817				audiohd_create_stereo(statep, CTL_HEADPHONE,
1818				    AUDIO_CTRL_ID_HEADPHONE, MAINVOL, 75,
1819				    audiohd_set_headphone);
1820			} else if (pin->device == DTYPE_LINE_IN) {
1821				audiohd_create_stereo(statep, CTL_LINEIN,
1822				    AUDIO_CTRL_ID_LINEIN, RECVOL, 50,
1823				    audiohd_set_linein);
1824			} else if (pin->device == DTYPE_MIC_IN) {
1825				audiohd_create_stereo(statep, CTL_MIC,
1826				    AUDIO_CTRL_ID_MIC, RECVOL, 50,
1827				    audiohd_set_mic);
1828			} else if (pin->device == DTYPE_CD) {
1829				audiohd_create_stereo(statep, CTL_CD,
1830				    AUDIO_CTRL_ID_CD, RECVOL, 50,
1831				    audiohd_set_cd);
1832			}
1833		}
1834
1835		if (path->path_type == BEEP) {
1836			widget = codec->widget[path->beep_wid];
1837			if (widget->type == WTYPE_BEEP &&
1838			    path->gain_wid != 0) {
1839				audiohd_create_mono(statep, CTL_BEEP,
1840				    AUDIO_CTRL_ID_BEEP, RWCTL, 75,
1841				    audiohd_set_beep);
1842				continue;
1843			}
1844		}
1845	}
1846
1847	if (!statep->monitor_unsupported) {
1848		audiohd_create_stereo(statep, CTL_MONGAIN,
1849		    AUDIO_CTRL_ID_MONGAIN, MONVOL, 0,
1850		    audiohd_set_mongain);
1851	}
1852
1853	audiohd_create_recsrc(statep);
1854	audiohd_configure_output(statep);
1855	audiohd_configure_input(statep);
1856}
1857
1858/*
1859 * quiesce(9E) entry point.
1860 *
1861 * This function is called when the system is single-threaded at high
1862 * PIL with preemption disabled. Therefore, this function must not be
1863 * blocked.
1864 *
1865 * This function returns DDI_SUCCESS on success, or DDI_FAILURE on failure.
1866 * DDI_FAILURE indicates an error condition and should almost never happen.
1867 */
1868static int
1869audiohd_quiesce(dev_info_t *dip)
1870{
1871	audiohd_state_t		*statep;
1872
1873	statep = ddi_get_driver_private(dip);
1874
1875	audiohd_stop_dma(statep);
1876
1877	return (DDI_SUCCESS);
1878}
1879
1880static void
1881audiohd_beep_on(void *arg)
1882{
1883	hda_codec_t *codec = ((audiohd_widget_t *)arg)->codec;
1884	audiohd_state_t *statep = codec->soft_statep;
1885	int caddr = codec->index;
1886	wid_t wid = ((audiohd_widget_t *)arg)->wid_wid;
1887
1888	(void) audioha_codec_verb_get(statep, caddr, wid,
1889	    AUDIOHDC_VERB_SET_BEEP_GEN, audiohd_beep_divider);
1890}
1891
1892static void
1893audiohd_beep_off(void *arg)
1894{
1895	hda_codec_t *codec = ((audiohd_widget_t *)arg)->codec;
1896	audiohd_state_t *statep = codec->soft_statep;
1897	int caddr = codec->index;
1898	wid_t wid = ((audiohd_widget_t *)arg)->wid_wid;
1899
1900	(void) audioha_codec_verb_get(statep, caddr, wid,
1901	    AUDIOHDC_VERB_SET_BEEP_GEN, AUDIOHDC_MUTE_BEEP_GEN);
1902}
1903
1904static void
1905audiohd_beep_freq(void *arg, int freq)
1906{
1907	hda_codec_t 	*codec = ((audiohd_widget_t *)arg)->codec;
1908	uint32_t	vid = codec->vid >> 16;
1909
1910	_NOTE(ARGUNUSED(arg));
1911	if (freq == 0) {
1912		audiohd_beep_divider = 0;
1913	} else {
1914		if (freq > AUDIOHDC_MAX_BEEP_GEN)
1915			freq = AUDIOHDC_MAX_BEEP_GEN;
1916		else if (freq < AUDIOHDC_MIX_BEEP_GEN)
1917			freq = AUDIOHDC_MIX_BEEP_GEN;
1918
1919		switch (vid) {
1920		case AUDIOHD_VID_SIGMATEL:
1921			/*
1922			 * Sigmatel HD codec specification:
1923			 * frequency = 48000 * (257 - Divider) / 1024
1924			 */
1925			audiohd_beep_divider = 257 - freq * 1024 /
1926			    AUDIOHDC_SAMPR48000;
1927			break;
1928		default:
1929			audiohd_beep_divider = AUDIOHDC_SAMPR48000 / freq;
1930			break;
1931		}
1932	}
1933
1934	if (audiohd_beep_vol == 0)
1935		audiohd_beep_divider = 0;
1936}
1937
1938/*
1939 * audiohd_init_state()
1940 *
1941 * Description
1942 *	This routine initailizes soft state of driver instance,
1943 *	also, it requests an interrupt cookie and initializes
1944 *	mutex for soft state.
1945 */
1946/*ARGSUSED*/
1947static int
1948audiohd_init_state(audiohd_state_t *statep, dev_info_t *dip)
1949{
1950	audio_dev_t	*adev;
1951
1952	statep->hda_dip = dip;
1953	statep->hda_rirb_rp = 0;
1954
1955	if ((adev = audio_dev_alloc(dip, 0)) == NULL) {
1956		cmn_err(CE_WARN,
1957		    "unable to allocate audio dev");
1958		return (DDI_FAILURE);
1959	}
1960	statep->adev = adev;
1961
1962	/* set device information */
1963	audio_dev_set_description(adev, AUDIOHD_DEV_CONFIG);
1964	audio_dev_set_version(adev, AUDIOHD_DEV_VERSION);
1965
1966	return (DDI_SUCCESS);
1967}	/* audiohd_init_state() */
1968
1969/*
1970 * audiohd_init_pci()
1971 *
1972 * Description
1973 *	enable driver to access PCI configure space and memory
1974 *	I/O space.
1975 */
1976static int
1977audiohd_init_pci(audiohd_state_t *statep, ddi_device_acc_attr_t *acc_attr)
1978{
1979	uint16_t	cmdreg;
1980	uint16_t	vid;
1981	uint8_t		cTmp;
1982	dev_info_t	*dip = statep->hda_dip;
1983	audio_dev_t	*adev = statep->adev;
1984
1985	if (pci_config_setup(dip, &statep->hda_pci_handle) == DDI_FAILURE) {
1986		audio_dev_warn(adev,
1987		    "pci config mapping failed");
1988		return (DDI_FAILURE);
1989	}
1990
1991	if (ddi_regs_map_setup(dip, 1, &statep->hda_reg_base, 0,
1992	    0, acc_attr, &statep->hda_reg_handle) != DDI_SUCCESS) {
1993		audio_dev_warn(adev,
1994		    "memory I/O mapping failed");
1995		return (DDI_FAILURE);
1996	}
1997
1998	/*
1999	 * HD audio control uses memory I/O only, enable it here.
2000	 */
2001	cmdreg = pci_config_get16(statep->hda_pci_handle, PCI_CONF_COMM);
2002	pci_config_put16(statep->hda_pci_handle, PCI_CONF_COMM,
2003	    cmdreg | PCI_COMM_MAE | PCI_COMM_ME);
2004
2005	vid = pci_config_get16(statep->hda_pci_handle, PCI_CONF_VENID);
2006	switch (vid) {
2007	case AUDIOHD_VID_INTEL:
2008		/*
2009		 * Currently, Intel (G)MCH and ICHx chipsets support PCI
2010		 * Express QoS. It implemenets two VCs(virtual channels)
2011		 * and allows OS software to map 8 traffic classes to the
2012		 * two VCs. Some BIOSes initialize HD audio hardware to
2013		 * use TC7 (traffic class 7) and to map TC7 to VC1 as Intel
2014		 * recommended. However, solaris doesn't support PCI express
2015		 * QoS yet. As a result, this driver can not work for those
2016		 * hardware without touching PCI express control registers.
2017		 * Here, we set TCSEL to 0 so as to use TC0/VC0 (VC0 is
2018		 * always enabled and TC0 is always mapped to VC0) for all
2019		 * Intel HD audio controllers.
2020		 */
2021		cTmp = pci_config_get8(statep->hda_pci_handle,
2022		    AUDIOHD_INTEL_PCI_TCSEL);
2023		pci_config_put8(statep->hda_pci_handle,
2024		    AUDIOHD_INTEL_PCI_TCSEL, (cTmp & AUDIOHD_INTEL_TCS_MASK));
2025		break;
2026	case AUDIOHD_VID_ATI:
2027		/*
2028		 * Refer to ATI SB450 datesheet. We set snoop for SB450
2029		 * like hardware.
2030		 */
2031		cTmp = pci_config_get8(statep->hda_pci_handle,
2032		    AUDIOHD_ATI_PCI_MISC2);
2033		pci_config_put8(statep->hda_pci_handle, AUDIOHD_ATI_PCI_MISC2,
2034		    (cTmp & AUDIOHD_ATI_MISC2_MASK) | AUDIOHD_ATI_MISC2_SNOOP);
2035		break;
2036	case AUDIOHD_VID_NVIDIA:
2037		/*
2038		 * Refer to the datasheet, we set snoop for NVIDIA
2039		 * like hardware
2040		 */
2041		cTmp = pci_config_get8(statep->hda_pci_handle,
2042		    AUDIOHD_CORB_SIZE_OFF);
2043		pci_config_put8(statep->hda_pci_handle, AUDIOHD_CORB_SIZE_OFF,
2044		    cTmp | AUDIOHD_NVIDIA_SNOOP);
2045		break;
2046	default:
2047		break;
2048	}
2049
2050	return (DDI_SUCCESS);
2051}	/* audiohd_init_pci() */
2052
2053
2054/*
2055 * audiohd_fini_pci()
2056 *
2057 * Description
2058 *	Release mapping for PCI configure space.
2059 */
2060static void
2061audiohd_fini_pci(audiohd_state_t *statep)
2062{
2063	if (statep->hda_reg_handle != NULL) {
2064		ddi_regs_map_free(&statep->hda_reg_handle);
2065		statep->hda_reg_handle = NULL;
2066	}
2067
2068	if (statep->hda_pci_handle != NULL) {
2069		pci_config_teardown(&statep->hda_pci_handle);
2070		statep->hda_pci_handle = NULL;
2071	}
2072
2073}	/* audiohd_fini_pci() */
2074
2075/*
2076 * audiohd_stop_dma()
2077 *
2078 * Description
2079 *	Stop all DMA behaviors of controllers, for command I/O
2080 *	and each audio stream.
2081 */
2082static void
2083audiohd_stop_dma(audiohd_state_t *statep)
2084{
2085	int	i;
2086	uint_t	base;
2087	uint8_t	bTmp;
2088
2089	AUDIOHD_REG_SET8(AUDIOHD_REG_CORBCTL, 0);
2090	AUDIOHD_REG_SET8(AUDIOHD_REG_RIRBCTL, 0);
2091
2092	base = AUDIOHD_REG_SD_BASE;
2093	for (i = 0; i < statep->hda_streams_nums; i++) {
2094		bTmp = AUDIOHD_REG_GET8(base + AUDIOHD_SDREG_OFFSET_CTL);
2095
2096		/* for input/output stream, it is the same */
2097		bTmp &= ~AUDIOHDR_RIRBCTL_DMARUN;
2098
2099		AUDIOHD_REG_SET8(base + AUDIOHD_SDREG_OFFSET_CTL, bTmp);
2100		base += AUDIOHD_REG_SD_LEN;
2101	}
2102
2103	/* wait 40us for stream DMA to stop */
2104	drv_usecwait(40);
2105
2106}	/* audiohd_stop_dma() */
2107
2108/*
2109 * audiohd_reset_controller()
2110 *
2111 * Description:
2112 *	This routine is just used to reset controller and
2113 *	CODEC as well by HW reset bit in global control
2114 *	register of HD controller.
2115 */
2116static int
2117audiohd_reset_controller(audiohd_state_t *statep)
2118{
2119	int		i;
2120	uint16_t	sTmp;
2121	uint32_t	gctl;
2122
2123	/* Reset Status register but preserve the first bit */
2124	sTmp = AUDIOHD_REG_GET16(AUDIOHD_REG_STATESTS);
2125	AUDIOHD_REG_SET16(AUDIOHD_REG_STATESTS, sTmp & 0x8000);
2126
2127	/* reset controller */
2128	gctl = AUDIOHD_REG_GET32(AUDIOHD_REG_GCTL);
2129	gctl &= ~AUDIOHDR_GCTL_CRST;
2130	AUDIOHD_REG_SET32(AUDIOHD_REG_GCTL, gctl);  /* entering reset state */
2131	for (i = 0; i < AUDIOHD_RETRY_TIMES; i++) {
2132		/* Empirical testing time: 150 */
2133		drv_usecwait(150);
2134		gctl = AUDIOHD_REG_GET32(AUDIOHD_REG_GCTL);
2135		if ((gctl & AUDIOHDR_GCTL_CRST) == 0)
2136			break;
2137	}
2138
2139	if ((gctl & AUDIOHDR_GCTL_CRST) != 0) {
2140		audio_dev_warn(statep->adev,
2141		    "failed to enter reset state");
2142		return (DDI_FAILURE);
2143	}
2144
2145	/* Empirical testing time:300 */
2146	drv_usecwait(300);
2147
2148	/* exit reset state */
2149	AUDIOHD_REG_SET32(AUDIOHD_REG_GCTL, gctl | AUDIOHDR_GCTL_CRST);
2150
2151	for (i = 0; i < AUDIOHD_RETRY_TIMES; i++) {
2152		/* Empirical testing time: 150, which works well */
2153		drv_usecwait(150);
2154		gctl = AUDIOHD_REG_GET32(AUDIOHD_REG_GCTL);
2155		if (gctl & AUDIOHDR_GCTL_CRST)
2156			break;
2157	}
2158
2159	if ((gctl & AUDIOHDR_GCTL_CRST) == 0) {
2160		audio_dev_warn(statep->adev,
2161		    "failed to exit reset state");
2162		return (DDI_FAILURE);
2163	}
2164
2165	/* HD spec requires to wait 250us at least. we use 500us */
2166	drv_usecwait(500);
2167
2168	/* enable unsolicited response */
2169	AUDIOHD_REG_SET32(AUDIOHD_REG_GCTL,
2170	    gctl |  AUDIOHDR_GCTL_URESPE);
2171
2172	return (DDI_SUCCESS);
2173
2174}	/* audiohd_reset_controller() */
2175
2176/*
2177 * audiohd_alloc_dma_mem()
2178 *
2179 * Description:
2180 *	This is an utility routine. It is used to allocate DMA
2181 *	memory.
2182 */
2183static int
2184audiohd_alloc_dma_mem(audiohd_state_t *statep, audiohd_dma_t *pdma,
2185    size_t memsize, ddi_dma_attr_t *dma_attr_p, uint_t dma_flags)
2186{
2187	ddi_dma_cookie_t	cookie;
2188	uint_t			count;
2189	dev_info_t		*dip = statep->hda_dip;
2190	audio_dev_t		*ahandle = statep->adev;
2191
2192	if (ddi_dma_alloc_handle(dip, dma_attr_p, DDI_DMA_SLEEP,
2193	    NULL, &pdma->ad_dmahdl) != DDI_SUCCESS) {
2194		audio_dev_warn(ahandle,
2195		    "ddi_dma_alloc_handle failed");
2196		return (DDI_FAILURE);
2197	}
2198
2199	if (ddi_dma_mem_alloc(pdma->ad_dmahdl, memsize, &hda_dev_accattr,
2200	    dma_flags & (DDI_DMA_CONSISTENT | DDI_DMA_STREAMING),
2201	    DDI_DMA_SLEEP, NULL,
2202	    (caddr_t *)&pdma->ad_vaddr, &pdma->ad_real_sz,
2203	    &pdma->ad_acchdl) != DDI_SUCCESS) {
2204		audio_dev_warn(ahandle,
2205		    "ddi_dma_mem_alloc failed");
2206		return (DDI_FAILURE);
2207	}
2208
2209	if (ddi_dma_addr_bind_handle(pdma->ad_dmahdl, NULL,
2210	    (caddr_t)pdma->ad_vaddr, pdma->ad_real_sz, dma_flags,
2211	    DDI_DMA_SLEEP, NULL, &cookie, &count) != DDI_DMA_MAPPED) {
2212		audio_dev_warn(ahandle,
2213		    "ddi_dma_addr_bind_handle failed");
2214		return (DDI_FAILURE);
2215	}
2216
2217	pdma->ad_paddr = (uint64_t)(cookie.dmac_laddress);
2218	pdma->ad_req_sz = memsize;
2219
2220	return (DDI_SUCCESS);
2221}	/* audiohd_alloc_dma_mem() */
2222
2223/*
2224 * audiohd_release_dma_mem()
2225 *
2226 * Description:
2227 *	Release DMA memory.
2228 */
2229
2230static void
2231audiohd_release_dma_mem(audiohd_dma_t *pdma)
2232{
2233	if (pdma->ad_dmahdl != NULL) {
2234		(void) ddi_dma_unbind_handle(pdma->ad_dmahdl);
2235	}
2236
2237	if (pdma->ad_acchdl != NULL) {
2238		ddi_dma_mem_free(&pdma->ad_acchdl);
2239		pdma->ad_acchdl = NULL;
2240	}
2241
2242	if (pdma->ad_dmahdl != NULL) {
2243		ddi_dma_free_handle(&pdma->ad_dmahdl);
2244		pdma->ad_dmahdl = NULL;
2245	}
2246
2247}	/* audiohd_release_dma_mem() */
2248
2249/*
2250 * audiohd_reinit_hda()
2251 *
2252 * Description:
2253 *	This routine is used to re-initialize HD controller and codec.
2254 */
2255static int
2256audiohd_reinit_hda(audiohd_state_t *statep)
2257{
2258	uint64_t	addr;
2259
2260	/* set PCI configure space in case it's not restored OK */
2261	(void) audiohd_init_pci(statep, &hda_dev_accattr);
2262
2263	/* reset controller */
2264	if (audiohd_reset_controller(statep) != DDI_SUCCESS)
2265		return (DDI_FAILURE);
2266	AUDIOHD_REG_SET32(AUDIOHD_REG_SYNC, 0); /* needn't sync stream */
2267
2268	/* Initialize controller RIRB */
2269	addr = statep->hda_dma_rirb.ad_paddr;
2270	AUDIOHD_REG_SET32(AUDIOHD_REG_RIRBLBASE, (uint32_t)addr);
2271	AUDIOHD_REG_SET32(AUDIOHD_REG_RIRBUBASE,
2272	    (uint32_t)(addr >> 32));
2273	AUDIOHD_REG_SET16(AUDIOHD_REG_RIRBWP, AUDIOHDR_RIRBWP_RESET);
2274	AUDIOHD_REG_SET8(AUDIOHD_REG_RIRBSIZE, AUDIOHDR_RIRBSZ_256);
2275	AUDIOHD_REG_SET8(AUDIOHD_REG_RIRBCTL, AUDIOHDR_RIRBCTL_DMARUN |
2276	    AUDIOHDR_RIRBCTL_RINTCTL);
2277
2278	/* Initialize controller CORB */
2279	addr = statep->hda_dma_corb.ad_paddr;
2280	AUDIOHD_REG_SET16(AUDIOHD_REG_CORBRP, AUDIOHDR_CORBRP_RESET);
2281	AUDIOHD_REG_SET32(AUDIOHD_REG_CORBLBASE, (uint32_t)addr);
2282	AUDIOHD_REG_SET32(AUDIOHD_REG_CORBUBASE,
2283	    (uint32_t)(addr >> 32));
2284	AUDIOHD_REG_SET8(AUDIOHD_REG_CORBSIZE, AUDIOHDR_CORBSZ_256);
2285	AUDIOHD_REG_SET16(AUDIOHD_REG_CORBWP, 0);
2286	AUDIOHD_REG_SET16(AUDIOHD_REG_CORBRP, 0);
2287	AUDIOHD_REG_SET8(AUDIOHD_REG_CORBCTL, AUDIOHDR_CORBCTL_DMARUN);
2288
2289	audiohd_restore_codec_gpio(statep);
2290	audiohd_restore_path(statep);
2291	audiohd_init_path(statep);
2292
2293	return (DDI_SUCCESS);
2294}	/* audiohd_reinit_hda */
2295
2296/*
2297 * audiohd_init_controller()
2298 *
2299 * Description:
2300 *	This routine is used to initialize HD controller. It
2301 *	allocates DMA memory for CORB/RIRB, buffer descriptor
2302 *	list and cylic data buffer for both play and record
2303 *	stream.
2304 */
2305static int
2306audiohd_init_controller(audiohd_state_t *statep)
2307{
2308	uint64_t	addr;
2309	uint16_t	gcap;
2310	int		retval;
2311
2312	ddi_dma_attr_t	dma_attr = {
2313		DMA_ATTR_V0,		/* version */
2314		0,			/* addr_lo */
2315		0xffffffffffffffffULL,	/* addr_hi */
2316		0x00000000ffffffffULL,	/* count_max */
2317		128,			/* 128-byte alignment as HD spec */
2318		0xfff,			/* burstsize */
2319		1,			/* minxfer */
2320		0xffffffff,		/* maxxfer */
2321		0xffffffff,		/* seg */
2322		1,			/* sgllen */
2323		1,			/* granular */
2324		0			/* flags */
2325	};
2326
2327	gcap = AUDIOHD_REG_GET16(AUDIOHD_REG_GCAP);
2328
2329	/*
2330	 * If the device doesn't support 64-bit DMA, we should not
2331	 * allocate DMA memory from 4G above
2332	 */
2333	if ((gcap & AUDIOHDR_GCAP_64OK) == 0)
2334		dma_attr.dma_attr_addr_hi = 0xffffffffUL;
2335
2336	statep->hda_input_streams = (gcap & AUDIOHDR_GCAP_INSTREAMS) >>
2337	    AUDIOHD_INSTR_NUM_OFF;
2338	statep->hda_output_streams = (gcap & AUDIOHDR_GCAP_OUTSTREAMS) >>
2339	    AUDIOHD_OUTSTR_NUM_OFF;
2340	statep->hda_streams_nums = statep->hda_input_streams +
2341	    statep->hda_output_streams;
2342
2343	statep->hda_record_regbase = AUDIOHD_REG_SD_BASE;
2344	statep->hda_play_regbase = AUDIOHD_REG_SD_BASE + AUDIOHD_REG_SD_LEN *
2345	    statep->hda_input_streams;
2346
2347	/* stop all dma before starting to reset controller */
2348	audiohd_stop_dma(statep);
2349
2350	if (audiohd_reset_controller(statep) != DDI_SUCCESS)
2351		return (DDI_FAILURE);
2352
2353	/* check codec */
2354	statep->hda_codec_mask = AUDIOHD_REG_GET16(AUDIOHD_REG_STATESTS);
2355	if (!statep->hda_codec_mask) {
2356		audio_dev_warn(statep->adev,
2357		    "no codec exists");
2358		return (DDI_FAILURE);
2359	}
2360
2361	/* allocate DMA for CORB */
2362	retval = audiohd_alloc_dma_mem(statep, &statep->hda_dma_corb,
2363	    AUDIOHD_CDBIO_CORB_LEN, &dma_attr,
2364	    DDI_DMA_WRITE | DDI_DMA_STREAMING);
2365	if (retval != DDI_SUCCESS) {
2366		audio_dev_warn(statep->adev,
2367		    "failed to alloc DMA for CORB");
2368		return (DDI_FAILURE);
2369	}
2370
2371	/* allocate DMA for RIRB */
2372	retval = audiohd_alloc_dma_mem(statep, &statep->hda_dma_rirb,
2373	    AUDIOHD_CDBIO_RIRB_LEN, &dma_attr,
2374	    DDI_DMA_READ | DDI_DMA_STREAMING);
2375	if (retval != DDI_SUCCESS) {
2376		audio_dev_warn(statep->adev,
2377		    "failed to alloc DMA for RIRB");
2378		return (DDI_FAILURE);
2379	}
2380
2381	AUDIOHD_REG_SET32(AUDIOHD_REG_SYNC, 0); /* needn't sync stream */
2382
2383	/* Initialize RIRB */
2384	addr = statep->hda_dma_rirb.ad_paddr;
2385	AUDIOHD_REG_SET32(AUDIOHD_REG_RIRBLBASE, (uint32_t)addr);
2386	AUDIOHD_REG_SET32(AUDIOHD_REG_RIRBUBASE, (uint32_t)(addr >> 32));
2387	AUDIOHD_REG_SET16(AUDIOHD_REG_RIRBWP, AUDIOHDR_RIRBWP_RESET);
2388	AUDIOHD_REG_SET8(AUDIOHD_REG_RIRBSIZE, AUDIOHDR_RIRBSZ_256);
2389	AUDIOHD_REG_SET8(AUDIOHD_REG_RIRBCTL, AUDIOHDR_RIRBCTL_DMARUN |
2390	    AUDIOHDR_RIRBCTL_RINTCTL);
2391
2392	/* initialize CORB */
2393	addr = statep->hda_dma_corb.ad_paddr;
2394	AUDIOHD_REG_SET16(AUDIOHD_REG_CORBRP, AUDIOHDR_CORBRP_RESET);
2395	AUDIOHD_REG_SET32(AUDIOHD_REG_CORBLBASE, (uint32_t)addr);
2396	AUDIOHD_REG_SET32(AUDIOHD_REG_CORBUBASE, (uint32_t)(addr >> 32));
2397	AUDIOHD_REG_SET8(AUDIOHD_REG_CORBSIZE, AUDIOHDR_CORBSZ_256);
2398	AUDIOHD_REG_SET16(AUDIOHD_REG_CORBWP, 0);
2399	AUDIOHD_REG_SET16(AUDIOHD_REG_CORBRP, 0);
2400	AUDIOHD_REG_SET8(AUDIOHD_REG_CORBCTL, AUDIOHDR_CORBCTL_DMARUN);
2401
2402	return (DDI_SUCCESS);
2403}	/* audiohd_init_controller() */
2404
2405/*
2406 * audiohd_fini_controller()
2407 *
2408 * Description:
2409 *	Releases DMA memory allocated in audiohd_init_controller()
2410 */
2411static void
2412audiohd_fini_controller(audiohd_state_t *statep)
2413{
2414	audiohd_release_dma_mem(&statep->hda_dma_rirb);
2415	audiohd_release_dma_mem(&statep->hda_dma_corb);
2416
2417}	/* audiohd_fini_controller() */
2418
2419/*
2420 * audiohd_get_conns_from_entry()
2421 *
2422 * Description:
2423 *	Get connection list from every entry for a widget
2424 */
2425static void
2426audiohd_get_conns_from_entry(hda_codec_t *codec, audiohd_widget_t *widget,
2427    uint32_t entry, audiohd_entry_prop_t *prop)
2428{
2429	int	i, k, num;
2430	wid_t	input_wid;
2431
2432	for (i = 0; i < prop->conns_per_entry &&
2433	    widget->nconns < prop->conn_len;
2434	    i++, entry >>= prop->bits_per_conn) {
2435		ASSERT(widget->nconns < AUDIOHD_MAX_CONN);
2436		input_wid = entry & prop->mask_wid;
2437		if (entry & prop->mask_range) {
2438			if (widget->nconns == 0) {
2439				if (input_wid < codec->first_wid ||
2440				    (input_wid > codec->last_wid)) {
2441					break;
2442				}
2443				widget->avail_conn[widget->nconns++] =
2444				    input_wid;
2445			} else {
2446				for (k = widget->avail_conn[widget->nconns-1] +
2447				    1; k <= input_wid; k++) {
2448					ASSERT(widget->nconns <
2449					    AUDIOHD_MAX_CONN);
2450					if (k < codec->first_wid ||
2451					    (k > codec->last_wid)) {
2452						break;
2453					} else {
2454						num = widget->nconns;
2455						widget->avail_conn[num] = k;
2456						widget->nconns++;
2457					}
2458				}
2459			}
2460		} else {
2461			if ((codec->first_wid <= input_wid) && (input_wid <=
2462			    codec->last_wid))
2463				widget->avail_conn[widget->nconns++] =
2464				    input_wid;
2465		}
2466	}
2467}
2468
2469/*
2470 * audiohd_get_conns()
2471 *
2472 * Description:
2473 *	Get all connection list for a widget. The connection list is used for
2474 *	build output path, input path, and monitor path
2475 */
2476static void
2477audiohd_get_conns(hda_codec_t *codec, wid_t wid)
2478{
2479	audiohd_state_t		*statep = codec->soft_statep;
2480	audiohd_widget_t	*widget = codec->widget[wid];
2481	uint8_t	caddr = codec->index;
2482	uint32_t	entry;
2483	audiohd_entry_prop_t	prop;
2484	wid_t	input_wid;
2485	int	i;
2486
2487	prop.conn_len = audioha_codec_verb_get(statep, caddr, wid,
2488	    AUDIOHDC_VERB_GET_PARAM, AUDIOHDC_PAR_CONNLIST_LEN);
2489
2490	if (prop.conn_len & AUDIOHD_FORM_MASK) {
2491		prop.conns_per_entry = 2;
2492		prop.bits_per_conn = 16;
2493		prop.mask_range = 0x00008000;
2494		prop.mask_wid = 0x00007fff;
2495	} else {
2496		prop.conns_per_entry = 4;
2497		prop.bits_per_conn = 8;
2498		prop.mask_range = 0x00000080;
2499		prop.mask_wid = 0x0000007f;
2500	}
2501	prop.conn_len &= AUDIOHD_LEN_MASK;
2502
2503	/*
2504	 * This should not happen since the ConnectionList bit of
2505	 * widget capabilities already told us that this widget
2506	 * has a connection list
2507	 */
2508	if (prop.conn_len == 0) {
2509		widget->nconns = 0;
2510		audio_dev_warn(statep->adev,
2511		    "node %d has 0 connections", wid);
2512		return;
2513	}
2514
2515	if (prop.conn_len == 1) {
2516		entry = audioha_codec_verb_get(statep, caddr,
2517		    wid, AUDIOHDC_VERB_GET_CONN_LIST_ENT, 0);
2518		input_wid = entry & prop.mask_wid;
2519		if ((input_wid < codec->first_wid) ||
2520		    (input_wid > codec->last_wid)) {
2521			return;
2522		}
2523		widget->avail_conn[0] = input_wid;
2524		widget->nconns = 1;
2525		return;
2526	}
2527	widget->nconns = 0;
2528	for (i = 0; i < prop.conn_len; i += prop.conns_per_entry) {
2529		entry = audioha_codec_verb_get(statep, caddr, wid,
2530		    AUDIOHDC_VERB_GET_CONN_LIST_ENT, i);
2531		audiohd_get_conns_from_entry(codec, widget, entry, &prop);
2532	}
2533}
2534
2535/*
2536 * Read PinCapabilities & default configuration
2537 */
2538static void
2539audiohd_get_pin_config(audiohd_widget_t *widget)
2540{
2541	hda_codec_t		*codec = widget->codec;
2542	audiohd_state_t		*statep = codec->soft_statep;
2543	audiohd_pin_t		*pin, *prev, *p;
2544
2545	int		caddr = codec->index;
2546	wid_t		wid = widget->wid_wid;
2547	uint32_t	cap, config, pinctrl;
2548	uint8_t		urctrl, vrefbits;
2549
2550	cap = audioha_codec_verb_get(statep, caddr, wid,
2551	    AUDIOHDC_VERB_GET_PARAM, AUDIOHDC_PAR_PIN_CAP);
2552	config = audioha_codec_verb_get(statep, caddr,
2553	    wid, AUDIOHDC_VERB_GET_DEFAULT_CONF, 0);
2554	pinctrl = audioha_codec_verb_get(statep, caddr,
2555	    wid, AUDIOHDC_VERB_GET_PIN_CTRL, 0);
2556
2557	pin = (audiohd_pin_t *)kmem_zalloc(sizeof (audiohd_pin_t), KM_SLEEP);
2558	widget->priv = pin;
2559
2560	/*
2561	 * If the pin has no physical connection for port,
2562	 * we won't link it to pin linkage list ???
2563	 */
2564	if (((config >> AUDIOHD_PIN_CON_STEP) & AUDIOHD_PIN_CON_MASK) == 0x1) {
2565		pin->no_phys_conn = 1;
2566	}
2567
2568	/* bit 4:3 are reserved, read-modify-write is needed */
2569	pin->ctrl = pinctrl & AUDIOHD_PIN_IO_MASK;
2570	pin->wid = wid;
2571	pin->cap = cap;
2572	pin->config = config;
2573	pin->num = 0;
2574	pin->finish = 0;
2575
2576	vrefbits = (cap >> AUDIOHD_PIN_VREF_OFF) & AUDIOHD_PIN_VREF_MASK;
2577	if (vrefbits & AUDIOHD_PIN_VREF_L1)
2578		pin->vrefvalue = 0x5;
2579	else if (vrefbits & AUDIOHD_PIN_VREF_L2)
2580		pin->vrefvalue = 0x4;
2581	else if (vrefbits & AUDIOHD_PIN_VREF_L3)
2582		pin->vrefvalue = 0x2;
2583	else
2584		pin->vrefvalue = 0x1;
2585
2586	pin->seq = config & AUDIOHD_PIN_SEQ_MASK;
2587	pin->assoc = (config & AUDIOHD_PIN_ASO_MASK) >> AUDIOHD_PIN_ASO_OFF;
2588	pin->device = (config & AUDIOHD_PIN_DEV_MASK) >> AUDIOHD_PIN_DEV_OFF;
2589
2590	/* enable the unsolicited response of the pin */
2591	if ((widget->widget_cap & AUDIOHD_URCAP_MASK) &&
2592	    (pin->cap & AUDIOHD_DTCCAP_MASK) &&
2593	    ((pin->device == DTYPE_LINEOUT) ||
2594	    (pin->device == DTYPE_SPDIF_OUT) ||
2595	    (pin->device == DTYPE_HP_OUT) ||
2596	    (pin->device == DTYPE_MIC_IN))) {
2597			urctrl = (uint8_t)(1 << (AUDIOHD_UR_ENABLE_OFF - 1));
2598			urctrl |= (wid & AUDIOHD_UR_TAG_MASK);
2599			(void) audioha_codec_verb_get(statep, caddr,
2600			    wid, AUDIOHDC_VERB_SET_UNS_ENABLE, urctrl);
2601	}
2602	/* accommodate all the pins in a link list sorted by assoc and seq */
2603	if (codec->first_pin == NULL) {
2604		codec->first_pin = pin;
2605	} else {
2606		prev = NULL;
2607		p = codec->first_pin;
2608		while (p) {
2609			if (p->assoc > pin->assoc)
2610				break;
2611			if ((p->assoc == pin->assoc) &&
2612			    (p->seq > pin->seq))
2613				break;
2614			prev = p;
2615			p = p->next;
2616		}
2617		if (prev) {
2618			pin->next = prev->next;
2619			prev->next = pin;
2620		} else {
2621			pin->next = codec->first_pin;
2622			codec->first_pin = pin;
2623		}
2624	}
2625
2626}	/* audiohd_get_pin_config() */
2627
2628/*
2629 * audiohd_create_widgets()
2630 *
2631 * Description:
2632 *	All widgets are created and stored in an array of codec
2633 */
2634static int
2635audiohd_create_widgets(hda_codec_t *codec)
2636{
2637	audiohd_widget_t	*widget;
2638	audiohd_state_t		*statep = codec->soft_statep;
2639	wid_t	wid;
2640	uint32_t	type, widcap;
2641	int		caddr = codec->index;
2642
2643	for (wid = codec->first_wid;
2644	    wid <= codec->last_wid; wid++) {
2645		widget = (audiohd_widget_t *)
2646		    kmem_zalloc(sizeof (audiohd_widget_t), KM_SLEEP);
2647		codec->widget[wid] = widget;
2648		widget->codec = codec;
2649		widget->output_path_next = AUDIOHD_NULL_CONN;
2650		widget->input_path_next = AUDIOHD_NULL_CONN;
2651		widget->beep_path_next = AUDIOHD_NULL_CONN;
2652
2653		widcap = audioha_codec_verb_get(statep, caddr, wid,
2654		    AUDIOHDC_VERB_GET_PARAM, AUDIOHDC_PAR_AUDIO_WID_CAP);
2655		type = AUDIOHD_WIDCAP_TO_WIDTYPE(widcap);
2656		widget->wid_wid = wid;
2657		widget->type = type;
2658		widget->widget_cap = widcap;
2659		widget->finish = 0;
2660		widget->used = 0;
2661
2662		/* if there's connection list */
2663		if (widcap & AUDIOHD_WIDCAP_CONNLIST) {
2664			audiohd_get_conns(codec, wid);
2665		}
2666
2667		/* if power control, power it up to D0 state */
2668		if (widcap & AUDIOHD_WIDCAP_PWRCTRL) {
2669			(void) audioha_codec_verb_get(statep, caddr, wid,
2670			    AUDIOHDC_VERB_SET_POWER_STATE, 0);
2671		}
2672
2673		/*
2674		 * if this widget has format override, we read it.
2675		 * Otherwise, it uses the format of audio function.
2676		 */
2677		if (widcap & AUDIOHD_WIDCAP_FMT_OVRIDE) {
2678			widget->pcm_format =
2679			    audioha_codec_verb_get(statep, caddr, wid,
2680			    AUDIOHDC_VERB_GET_PARAM, AUDIOHDC_PAR_PCM);
2681		} else {
2682			widget->pcm_format = codec->pcm_format;
2683		}
2684
2685		/*
2686		 * Input amplifier. Has the widget input amplifier ?
2687		 */
2688		if (widcap & AUDIOHD_WIDCAP_INAMP) {
2689			/*
2690			 * if overrided bit is 0, use the default
2691			 * amplifier of audio function as HD spec.
2692			 * Otherwise, we read it.
2693			 */
2694			if ((widcap & AUDIOHD_WIDCAP_AMP_OVRIDE) == 0)
2695				widget->inamp_cap = codec->inamp_cap;
2696			else
2697				widget->inamp_cap =
2698				    audioha_codec_verb_get(statep, caddr, wid,
2699				    AUDIOHDC_VERB_GET_PARAM,
2700				    AUDIOHDC_PAR_INAMP_CAP);
2701		} else {
2702			widget->inamp_cap = 0;
2703		}
2704
2705		/*
2706		 * output amplifier. Has this widget output amplifier ?
2707		 */
2708		if (widcap & AUDIOHD_WIDCAP_OUTAMP) {
2709			if ((widcap & AUDIOHD_WIDCAP_AMP_OVRIDE) == 0)
2710				widget->outamp_cap = codec->outamp_cap;
2711			else
2712				widget->outamp_cap =
2713				    audioha_codec_verb_get(statep, caddr, wid,
2714				    AUDIOHDC_VERB_GET_PARAM,
2715				    AUDIOHDC_PAR_OUTAMP_CAP);
2716		} else {
2717			widget->outamp_cap = 0;
2718		}
2719
2720		switch (type) {
2721		case WTYPE_AUDIO_OUT:
2722		case WTYPE_AUDIO_IN:
2723		case WTYPE_AUDIO_MIX:
2724		case WTYPE_AUDIO_SEL:
2725		case WTYPE_VENDOR:
2726		case WTYPE_POWER:
2727		case WTYPE_VOL_KNOB:
2728			break;
2729		case WTYPE_PIN:
2730			/*
2731			 * Some codec(like ALC262) don't provide beep widget,
2732			 * it only has input Pin to connect an external beep
2733			 * (maybe in motherboard or elsewhere). So we open
2734			 * all PINs here in order to enable external beep
2735			 * source.
2736			 */
2737			if ((codec->codec_info->flags & EN_PIN_BEEP) == 0) {
2738				(void) audioha_codec_4bit_verb_get(statep,
2739				    caddr, widget->wid_wid,
2740				    AUDIOHDC_VERB_SET_AMP_MUTE,
2741				    AUDIOHDC_AMP_SET_LR_OUTPUT |
2742				    AUDIOHDC_GAIN_MAX);
2743			}
2744
2745			audiohd_get_pin_config(widget);
2746			break;
2747		case WTYPE_BEEP:
2748			/*
2749			 * Get the audiohd_beep_switch value from audiohd.conf,
2750			 * which is for turning on/off widget beep.
2751			 */
2752			audiohd_beep = ddi_prop_get_int(DDI_DEV_T_ANY,
2753			    statep->hda_dip,
2754			    DDI_PROP_DONTPASS, "audiohd_beep", 1);
2755
2756			if (audiohd_beep) {
2757				(void) beep_fini();
2758				(void) beep_init((void *) widget,
2759				    audiohd_beep_on,
2760				    audiohd_beep_off,
2761				    audiohd_beep_freq);
2762			}
2763			break;
2764		default:
2765			break;
2766		}
2767	}
2768
2769	return (DDI_SUCCESS);
2770
2771}	/* audiohd_create_widgets() */
2772
2773/*
2774 * audiohd_destroy_widgets()
2775 */
2776static void
2777audiohd_destroy_widgets(hda_codec_t *codec)
2778{
2779	for (int i = 0; i < AUDIOHD_MAX_WIDGET; i++) {
2780		if (codec->widget[i]) {
2781			kmem_free(codec->widget[i], sizeof (audiohd_widget_t));
2782			codec->widget[i] = NULL;
2783		}
2784	}
2785
2786}	/* audiohd_destroy_widgets() */
2787
2788/*
2789 * audiohd_create_codec()
2790 *
2791 * Description:
2792 *	Searching for supported CODEC. If find, allocate memory
2793 *	to hold codec structure.
2794 */
2795static int
2796audiohd_create_codec(audiohd_state_t *statep)
2797{
2798	hda_codec_t	*codec;
2799	uint32_t	mask, type;
2800	uint32_t	nums;
2801	uint32_t	i, j, len;
2802	wid_t		wid;
2803	char		buf[128];
2804
2805	mask = statep->hda_codec_mask;
2806	ASSERT(mask != 0);
2807
2808	for (i = 0; i < AUDIOHD_CODEC_MAX; i++) {
2809		if ((mask & (1 << i)) == 0)
2810			continue;
2811		codec = (hda_codec_t *)kmem_zalloc(
2812		    sizeof (hda_codec_t), KM_SLEEP);
2813		codec->index = i;
2814		codec->vid = audioha_codec_verb_get(statep, i,
2815		    AUDIOHDC_NODE_ROOT, AUDIOHDC_VERB_GET_PARAM,
2816		    AUDIOHDC_PAR_VENDOR_ID);
2817		if (codec->vid == (uint32_t)(-1)) {
2818			kmem_free(codec, sizeof (hda_codec_t));
2819			continue;
2820		}
2821
2822		codec->revid =
2823		    audioha_codec_verb_get(statep, i,
2824		    AUDIOHDC_NODE_ROOT, AUDIOHDC_VERB_GET_PARAM,
2825		    AUDIOHDC_PAR_REV_ID);
2826
2827		nums = audioha_codec_verb_get(statep,
2828		    i, AUDIOHDC_NODE_ROOT,
2829		    AUDIOHDC_VERB_GET_PARAM, AUDIOHDC_PAR_NODE_COUNT);
2830		if (nums == (uint32_t)(-1)) {
2831			kmem_free(codec, sizeof (hda_codec_t));
2832			continue;
2833		}
2834		wid = (nums >> AUDIOHD_CODEC_STR_OFF) & AUDIOHD_CODEC_STR_MASK;
2835		nums = nums & AUDIOHD_CODEC_NUM_MASK;
2836
2837		/*
2838		 * Assume that each codec has just one audio function group
2839		 */
2840		for (j = 0; j < nums; j++, wid++) {
2841			type = audioha_codec_verb_get(statep, i, wid,
2842			    AUDIOHDC_VERB_GET_PARAM,
2843			    AUDIOHDC_PAR_FUNCTION_TYPE);
2844			if ((type & AUDIOHD_CODEC_TYPE_MASK) ==
2845			    AUDIOHDC_AUDIO_FUNC_GROUP) {
2846				codec->wid_afg = wid;
2847				break;
2848			}
2849		}
2850
2851		if (codec->wid_afg == 0) {
2852			kmem_free(codec, sizeof (hda_codec_t));
2853			continue;
2854		}
2855
2856		ASSERT(codec->wid_afg == wid);
2857
2858		len = sizeof (audiohd_codecs) / sizeof (audiohd_codec_info_t);
2859		for (j = 0; j < len-1; j++) {
2860			if (audiohd_codecs[j].devid == codec->vid) {
2861				codec->codec_info = &(audiohd_codecs[j]);
2862				break;
2863			}
2864		}
2865
2866		if (codec->codec_info == NULL) {
2867			codec->codec_info = &(audiohd_codecs[len-1]);
2868			(void) snprintf(buf, sizeof (buf),
2869			    "Unknown HD codec: 0x%x", codec->vid);
2870		} else {
2871			(void) snprintf(buf, sizeof (buf), "HD codec: %s",
2872			    codec->codec_info->buf);
2873		}
2874		audio_dev_add_info(statep->adev, buf);
2875
2876		/* work around for Sony VAIO laptop with specific codec */
2877		if ((codec->codec_info->flags & NO_GPIO) == 0) {
2878			/*
2879			 * GPIO controls which are laptop specific workarounds
2880			 * and might be changed. Some laptops use GPIO,
2881			 * so we need to enable and set the GPIO correctly.
2882			 */
2883			(void) audioha_codec_verb_get(statep, i, wid,
2884			    AUDIOHDC_VERB_SET_GPIO_MASK, AUDIOHDC_GPIO_ENABLE);
2885			(void) audioha_codec_verb_get(statep, i, wid,
2886			    AUDIOHDC_VERB_SET_UNSOL_ENABLE_MASK,
2887			    AUDIOHDC_GPIO_ENABLE);
2888			(void) audioha_codec_verb_get(statep, i, wid,
2889			    AUDIOHDC_VERB_SET_GPIO_DIREC, AUDIOHDC_GPIO_DIRECT);
2890			(void) audioha_codec_verb_get(statep, i, wid,
2891			    AUDIOHDC_VERB_SET_GPIO_STCK,
2892			    AUDIOHDC_GPIO_DATA_CTRL);
2893			(void) audioha_codec_verb_get(statep, i, wid,
2894			    AUDIOHDC_VERB_SET_GPIO_DATA,
2895			    AUDIOHDC_GPIO_STCK_CTRL);
2896		}
2897
2898		/* power-up audio function group */
2899		(void) audioha_codec_verb_get(statep, i, wid,
2900		    AUDIOHDC_VERB_SET_POWER_STATE, AUDIOHD_PW_D0);
2901
2902		/* subsystem id is attached to funtion group */
2903		codec->outamp_cap = audioha_codec_verb_get(statep, i, wid,
2904		    AUDIOHDC_VERB_GET_PARAM, AUDIOHDC_PAR_OUTAMP_CAP);
2905		codec->inamp_cap = audioha_codec_verb_get(statep, i, wid,
2906		    AUDIOHDC_VERB_GET_PARAM, AUDIOHDC_PAR_INAMP_CAP);
2907		codec->stream_format = audioha_codec_verb_get(statep, i, wid,
2908		    AUDIOHDC_VERB_GET_PARAM, AUDIOHDC_PAR_STREAM);
2909		codec->pcm_format = audioha_codec_verb_get(statep, i, wid,
2910		    AUDIOHDC_VERB_GET_PARAM, AUDIOHDC_PAR_PCM);
2911
2912		nums = audioha_codec_verb_get(statep, i, wid,
2913		    AUDIOHDC_VERB_GET_PARAM,
2914		    AUDIOHDC_PAR_NODE_COUNT);
2915		wid = (nums >> AUDIOHD_CODEC_STR_OFF) & AUDIOHD_CODEC_STR_MASK;
2916		nums = nums & AUDIOHD_CODEC_NUM_MASK;
2917		codec->first_wid = wid;
2918		codec->last_wid = wid + nums;
2919		codec->nnodes = nums;
2920
2921		/*
2922		 * We output the codec information to syslog
2923		 */
2924		statep->codec[i] = codec;
2925		codec->soft_statep = statep;
2926		(void) audiohd_create_widgets(codec);
2927	}
2928
2929	return (DDI_SUCCESS);
2930
2931}	/* audiohd_create_codec() */
2932
2933/*
2934 * audiohd_destroy_codec()
2935 *
2936 * Description:
2937 *	destroy codec structure, and release its memory
2938 */
2939static void
2940audiohd_destroy_codec(audiohd_state_t *statep)
2941{
2942	int			i;
2943	audiohd_pin_t		*pin, *npin;
2944
2945	for (i = 0; i < AUDIOHD_CODEC_MAX; i++) {
2946		if (statep->codec[i]) {
2947			audiohd_destroy_widgets(statep->codec[i]);
2948			/*
2949			 * free pins
2950			 */
2951			pin = statep->codec[i]->first_pin;
2952			while (pin) {
2953				npin = pin;
2954				pin = pin->next;
2955				kmem_free(npin, sizeof (audiohd_pin_t));
2956			}
2957
2958			kmem_free(statep->codec[i], sizeof (hda_codec_t));
2959			statep->codec[i] = NULL;
2960		}
2961	}
2962}	/* audiohd_destroy_codec() */
2963
2964/*
2965 * audiohd_find_dac()
2966 * Description:
2967 *	Find a dac for a output path. Then the play data can be sent to the out
2968 *	put pin through the output path.
2969 *
2970 * Arguments:
2971 *	hda_codec_t	*codec		where the dac widget exists
2972 *	wid_t		wid		the no. of a widget
2973 *	int		mixer		whether the path need mixer or not
2974 *	int		*mixernum	the total of mixer in the output path
2975 *	int		exclusive	an exclusive path or share path
2976 *	int		depth		the depth of search
2977 *
2978 * Return:
2979 *	1) wid of the first shared widget in the path from
2980 *	   pin to DAC if exclusive is 0;
2981 *	2) wid of DAC widget;
2982 *	3) 0 if no path
2983 */
2984static wid_t
2985audiohd_find_dac(hda_codec_t *codec, wid_t wid,
2986    int mixer, int *mixernum,
2987    int exclusive, int depth)
2988{
2989	audiohd_widget_t	*widget = codec->widget[wid];
2990	wid_t	wdac = (uint32_t)(DDI_FAILURE);
2991	wid_t	retval;
2992
2993	if (depth > AUDIOHD_MAX_DEPTH)
2994		return (uint32_t)(DDI_FAILURE);
2995
2996	if (widget == NULL)
2997		return (uint32_t)(DDI_FAILURE);
2998
2999	/*
3000	 * If exclusive is true, we try to find a path which doesn't
3001	 * share any widget with other paths.
3002	 */
3003	if (exclusive) {
3004		if (widget->path_flags & AUDIOHD_PATH_DAC)
3005			return (uint32_t)(DDI_FAILURE);
3006	} else {
3007		if (widget->path_flags & AUDIOHD_PATH_DAC)
3008			return (wid);
3009	}
3010
3011	switch (widget->type) {
3012	case WTYPE_AUDIO_OUT:
3013		/* We need mixer widget, but the the mixer num is 0, failed  */
3014		if (mixer && !*mixernum)
3015			return (uint32_t)(DDI_FAILURE);
3016		widget->path_flags |= AUDIOHD_PATH_DAC;
3017		widget->out_weight++;
3018		wdac = widget->wid_wid;
3019		break;
3020
3021	case WTYPE_AUDIO_MIX:
3022		(*mixernum)++;
3023		/* FALLTHRU */
3024	case WTYPE_AUDIO_SEL:
3025		for (int i = 0; i < widget->nconns; i++) {
3026			retval = audiohd_find_dac(codec,
3027			    widget->avail_conn[i],
3028			    mixer, mixernum,
3029			    exclusive, depth + 1);
3030			if (retval != (uint32_t)DDI_FAILURE) {
3031				if (widget->output_path_next ==
3032				    AUDIOHD_NULL_CONN) {
3033					widget->output_path_next = i;
3034					wdac = retval;
3035				}
3036				widget->path_flags |= AUDIOHD_PATH_DAC;
3037				widget->out_weight++;
3038
3039				/* return when found a path */
3040				return (wdac);
3041			}
3042		}
3043	default:
3044		break;
3045	}
3046
3047	return (wdac);
3048}	/* audiohd_find_dac() */
3049
3050/*
3051 * audiohd_do_build_output_path()
3052 *
3053 * Description:
3054 *	Search an output path for each pin in the codec.
3055 * Arguments:
3056 *	hda_codec_t	*codec		where the output path exists
3057 *	int		mixer		whether the path needs mixer widget
3058 *	int		*mnum		total of mixer widget in the path
3059 *	int		exclusive	an exclusive path or shared path
3060 *	int		depth		search depth
3061 */
3062static void
3063audiohd_do_build_output_path(hda_codec_t *codec, int mixer, int *mnum,
3064    int exclusive, int depth)
3065{
3066	audiohd_pin_t		*pin;
3067	audiohd_widget_t	*widget, *wdac;
3068	audiohd_path_t		*path;
3069	wid_t			wid;
3070	audiohd_state_t		*statep;
3071	int			i;
3072
3073	statep = codec->soft_statep;
3074
3075	for (pin = codec->first_pin; pin; pin = pin->next) {
3076		if ((pin->cap & AUDIOHD_PIN_CAP_MASK) == 0)
3077			continue;
3078		if ((pin->config & AUDIOHD_PIN_CONF_MASK) ==
3079		    AUDIOHD_PIN_NO_CONN)
3080			continue;
3081		if ((pin->device != DTYPE_LINEOUT) &&
3082		    (pin->device != DTYPE_SPEAKER) &&
3083		    (pin->device != DTYPE_SPDIF_OUT) &&
3084		    (pin->device != DTYPE_HP_OUT))
3085			continue;
3086		if (pin->finish)
3087			continue;
3088		widget = codec->widget[pin->wid];
3089
3090		widget->inamp_cap = 0;
3091		for (i = 0; i < widget->nconns; i++) {
3092			/*
3093			 * If a dac found, the return value is the wid of the
3094			 * widget on the path, or the return value is
3095			 * DDI_FAILURE
3096			 */
3097			wid = audiohd_find_dac(codec,
3098			    widget->avail_conn[i], mixer, mnum, exclusive,
3099			    depth);
3100			/*
3101			 * A dac was not found
3102			 */
3103			if (wid == (wid_t)DDI_FAILURE)
3104				continue;
3105			if (pin->device != DTYPE_SPEAKER &&
3106			    pin->device != DTYPE_HP_OUT)
3107				statep->chann[pin->assoc] += 2;
3108			path = (audiohd_path_t *)
3109			    kmem_zalloc(sizeof (audiohd_path_t),
3110			    KM_SLEEP);
3111			path->adda_wid = wid;
3112			path->pin_wid[0] = widget->wid_wid;
3113			path->pin_nums = 1;
3114			path->path_type = PLAY;
3115			path->codec = codec;
3116			path->statep = statep;
3117			wdac = codec->widget[wid];
3118			wdac->priv = path;
3119			pin->adc_dac_wid = wid;
3120			pin->finish = 1;
3121			widget->path_flags |= AUDIOHD_PATH_DAC;
3122			widget->out_weight++;
3123			widget->output_path_next = i;
3124			statep->path[statep->pathnum++] = path;
3125			break;
3126		}
3127	}
3128
3129}	/* audiohd_do_build_output_path() */
3130
3131/*
3132 * audiohd_build_output_path()
3133 *
3134 * Description:
3135 *	Build the output path in the codec for every pin.
3136 *	First we try to search output path with mixer widget exclusively
3137 *	Then we try to search shared output path with mixer widget.
3138 *	Then we try to search output path without mixer widget exclusively.
3139 *	At last we try to search shared ouput path for the remained pins
3140 */
3141static void
3142audiohd_build_output_path(hda_codec_t *codec)
3143{
3144	int 			mnum = 0;
3145	uint8_t			mixer_allow = 1;
3146
3147	/*
3148	 * Work around for laptops which have IDT or AD audio chipset, such as
3149	 * HP mini 1000 laptop, Dell Lattitude 6400, Lenovo T60, Lenove R61e.
3150	 * We don't allow mixer widget on such path, which leads to speaker
3151	 * loud hiss noise.
3152	 */
3153	if (codec->codec_info->flags & NO_MIXER)
3154		mixer_allow = 0;
3155
3156	/* search an exclusive mixer widget path. This is preferred */
3157	audiohd_do_build_output_path(codec, mixer_allow, &mnum, 1, 0);
3158
3159	/* search a shared mixer widget path for the remained pins */
3160	audiohd_do_build_output_path(codec, mixer_allow, &mnum, 0, 0);
3161
3162	/* search an exclusive widget path without mixer for the remained pin */
3163	audiohd_do_build_output_path(codec, 0, &mnum, 1, 0);
3164
3165	/* search a shared widget path without mixer for the remained pin */
3166	audiohd_do_build_output_path(codec, 0, &mnum, 0, 0);
3167
3168}	/* audiohd_build_output_path */
3169
3170/*
3171 * audiohd_build_output_amp
3172 *
3173 * Description:
3174 *	Find the gain control and mute control widget
3175 */
3176static void
3177audiohd_build_output_amp(hda_codec_t *codec)
3178{
3179	audiohd_path_t		*path;
3180	audiohd_widget_t	*w, *widget, *wpin, *wdac;
3181	audiohd_pin_t		*pin;
3182	wid_t		wid, next;
3183	int		weight;
3184	int		i, j;
3185	uint32_t	gain;
3186
3187	for (i = 0; i < codec->soft_statep->pathnum; i++) {
3188		path = codec->soft_statep->path[i];
3189		if (path == NULL || path->path_type != PLAY ||
3190		    path->codec != codec)
3191			continue;
3192		for (j = 0; j < path->pin_nums; j++) {
3193			wid = path->pin_wid[j];
3194			wpin = codec->widget[wid];
3195			pin = (audiohd_pin_t *)wpin->priv;
3196			weight = wpin->out_weight;
3197
3198			/*
3199			 * search a node which can mute this pin while
3200			 * the mute functionality doesn't effect other
3201			 * pins.
3202			 */
3203			widget = wpin;
3204			while (widget) {
3205				if (widget->outamp_cap &
3206				    AUDIOHDC_AMP_CAP_MUTE_CAP) {
3207					pin->mute_wid = widget->wid_wid;
3208					pin->mute_dir = AUDIOHDC_AMP_SET_OUTPUT;
3209					break;
3210				}
3211				if (widget->inamp_cap &
3212				    AUDIOHDC_AMP_CAP_MUTE_CAP) {
3213					pin->mute_wid = widget->wid_wid;
3214					pin->mute_dir = AUDIOHDC_AMP_SET_INPUT;
3215					break;
3216				}
3217				next = widget->output_path_next;
3218				if (next == AUDIOHD_NULL_CONN)
3219					break;
3220				wid = widget->avail_conn[next];
3221				widget = codec->widget[wid];
3222				if (widget && widget->out_weight != weight)
3223					break;
3224			}
3225
3226			/*
3227			 * We select the wid which has maxium gain range in
3228			 * the output path. Meanwhile, the gain controlling
3229			 * of this node doesn't effect other pins if this
3230			 * output stream has multiple pins.
3231			 */
3232			gain = 0;
3233			widget = wpin;
3234			while (widget) {
3235				gain = (widget->outamp_cap &
3236				    AUDIOHDC_AMP_CAP_STEP_NUMS);
3237				if (gain && gain > pin->gain_bits) {
3238					pin->gain_dir = AUDIOHDC_AMP_SET_OUTPUT;
3239					pin->gain_bits = gain;
3240					pin->gain_wid = widget->wid_wid;
3241				}
3242				gain = widget->inamp_cap &
3243				    AUDIOHDC_AMP_CAP_STEP_NUMS;
3244				if (gain && gain > pin->gain_bits) {
3245					pin->gain_dir = AUDIOHDC_AMP_SET_INPUT;
3246					pin->gain_bits = gain;
3247					pin->gain_wid = widget->wid_wid;
3248				}
3249				next = widget->output_path_next;
3250				if (next == AUDIOHD_NULL_CONN)
3251					break;
3252				wid = widget->avail_conn[next];
3253				widget = codec->widget[wid];
3254				if (widget && widget->out_weight != weight)
3255					break;
3256			}
3257			pin->gain_bits >>= AUDIOHD_GAIN_OFF;
3258		}
3259
3260		/*
3261		 * if this stream has multiple pins, we try to find
3262		 * a mute & gain-controlling nodes which can effect
3263		 * all output pins of this stream to be used for the
3264		 * whole stream
3265		 */
3266		if (path->pin_nums == 1) {
3267			path->mute_wid = pin->mute_wid;
3268			path->mute_dir = pin->mute_dir;
3269			path->gain_wid = pin->gain_wid;
3270			path->gain_dir = pin->gain_dir;
3271			path->gain_bits = pin->gain_bits;
3272		} else {
3273			wdac = codec->widget[path->adda_wid];
3274			weight = wdac->out_weight;
3275			wid = path->pin_wid[0];
3276			w = codec->widget[wid];
3277			while (w && w->out_weight != weight) {
3278				wid = w->avail_conn[w->output_path_next];
3279				w = codec->widget[wid];
3280			}
3281
3282			/* find mute controlling node for this stream */
3283			widget = w;
3284			while (widget) {
3285				if (widget->outamp_cap &
3286				    AUDIOHDC_AMP_CAP_MUTE_CAP) {
3287					path->mute_wid = widget->wid_wid;
3288					path->mute_dir =
3289					    AUDIOHDC_AMP_SET_OUTPUT;
3290					break;
3291				}
3292				if (widget->inamp_cap &
3293				    AUDIOHDC_AMP_CAP_MUTE_CAP) {
3294					path->mute_wid = widget->wid_wid;
3295					path->mute_dir =
3296					    AUDIOHDC_AMP_SET_INPUT;
3297					break;
3298				}
3299				next = widget->output_path_next;
3300				if (next == AUDIOHD_NULL_CONN)
3301					break;
3302				wid = widget->avail_conn[next];
3303				widget = codec->widget[wid];
3304			}
3305
3306			/* find volume controlling node for this stream */
3307			gain = 0;
3308			widget = w;
3309			while (widget) {
3310				gain = (widget->outamp_cap &
3311				    AUDIOHDC_AMP_CAP_STEP_NUMS);
3312				if (gain && gain > pin->gain_bits) {
3313					path->gain_dir =
3314					    AUDIOHDC_AMP_SET_OUTPUT;
3315					path->gain_bits = gain;
3316					path->gain_wid = widget->wid_wid;
3317				}
3318				gain = widget->inamp_cap &
3319				    AUDIOHDC_AMP_CAP_STEP_NUMS;
3320				if (gain && (gain > pin->gain_bits) &&
3321				    (widget->type != WTYPE_AUDIO_MIX)) {
3322					path->gain_dir =
3323					    AUDIOHDC_AMP_SET_INPUT;
3324					path->gain_bits = gain;
3325					path->gain_wid = widget->wid_wid;
3326				}
3327				next = widget->output_path_next;
3328				if (next == AUDIOHD_NULL_CONN)
3329					break;
3330				wid = widget->avail_conn[next];
3331				widget = codec->widget[wid];
3332			}
3333			path->gain_bits >>= AUDIOHD_GAIN_OFF;
3334		}
3335
3336	}
3337
3338}	/* audiohd_build_output_amp */
3339
3340/*
3341 * audiohd_finish_output_path()
3342 *
3343 * Description:
3344 *	Enable the widgets on the output path
3345 */
3346static void
3347audiohd_finish_output_path(hda_codec_t *codec)
3348{
3349	audiohd_state_t		*statep = codec->soft_statep;
3350	audiohd_path_t		*path;
3351	audiohd_widget_t	*widget;
3352	audiohd_pin_t		*pin;
3353	uint_t			caddr = codec->index;
3354	wid_t			wid, next;
3355	int			i, j;
3356
3357	for (i = 0; i < codec->soft_statep->pathnum; i++) {
3358		path = codec->soft_statep->path[i];
3359		if (!path || path->path_type != PLAY || path->codec != codec)
3360			continue;
3361		for (j = 0; j < path->pin_nums; j++) {
3362			wid = path->pin_wid[j];
3363			widget = codec->widget[wid];
3364			pin = (audiohd_pin_t *)widget->priv;
3365			{
3366			uint32_t    lTmp;
3367
3368			lTmp = audioha_codec_verb_get(statep, caddr, wid,
3369			    AUDIOHDC_VERB_GET_PIN_CTRL, 0);
3370			(void) audioha_codec_verb_get(statep, caddr, wid,
3371			    AUDIOHDC_VERB_SET_PIN_CTRL, (lTmp |
3372			    pin->vrefvalue |
3373			    AUDIOHDC_PIN_CONTROL_OUT_ENABLE |
3374			    AUDIOHDC_PIN_CONTROL_HP_ENABLE) &
3375			    ~ AUDIOHDC_PIN_CONTROL_IN_ENABLE);
3376			}
3377			/* If this pin has external amplifier, enable it */
3378			if (pin->cap & AUDIOHD_EXT_AMP_MASK)
3379				(void) audioha_codec_verb_get(statep, caddr,
3380				    wid, AUDIOHDC_VERB_SET_EAPD,
3381				    AUDIOHD_EXT_AMP_ENABLE);
3382
3383			if (widget->outamp_cap) {
3384				(void) audioha_codec_4bit_verb_get(statep,
3385				    caddr, wid, AUDIOHDC_VERB_SET_AMP_MUTE,
3386				    AUDIOHDC_AMP_SET_LR_OUTPUT |
3387				    AUDIOHDC_GAIN_MAX);
3388			}
3389
3390			(void) audioha_codec_verb_get(statep, caddr, wid,
3391			    AUDIOHDC_VERB_SET_CONN_SEL,
3392			    widget->output_path_next);
3393
3394			wid = widget->avail_conn[widget->output_path_next];
3395			widget = codec->widget[wid];
3396
3397			while (widget) {
3398				/*
3399				 * Set all amplifiers in this path to
3400				 * the maximum volume and unmute them.
3401				 */
3402				if (widget->outamp_cap) {
3403					(void) audioha_codec_4bit_verb_get(
3404					    statep, caddr,
3405					    wid, AUDIOHDC_VERB_SET_AMP_MUTE,
3406					    AUDIOHDC_AMP_SET_LR_OUTPUT |
3407					    AUDIOHDC_GAIN_MAX);
3408				}
3409				if (widget->inamp_cap) {
3410					(void) audioha_codec_4bit_verb_get(
3411					    statep, caddr,
3412					    wid, AUDIOHDC_VERB_SET_AMP_MUTE,
3413					    AUDIOHDC_AMP_SET_LR_INPUT |
3414					    AUDIOHDC_GAIN_MAX |
3415					    (widget->output_path_next <<
3416					    AUDIOHDC_AMP_SET_INDEX_OFFSET));
3417				}
3418
3419				next = widget->output_path_next;
3420				if (next == AUDIOHD_NULL_CONN)
3421					break;
3422				/*
3423				 * Accoding to HD spec, mixer doesn't support
3424				 * "select connection"
3425				 */
3426				if ((widget->type == WTYPE_AUDIO_SEL) &&
3427				    (widget->nconns > 1))
3428					(void) audioha_codec_verb_get(statep,
3429					    caddr, wid,
3430					    AUDIOHDC_VERB_SET_CONN_SEL,
3431					    widget->output_path_next);
3432
3433				wid = widget->avail_conn[next];
3434				widget = codec->widget[wid];
3435			}
3436		}
3437	}
3438}	/* audiohd_finish_output_path() */
3439
3440/*
3441 * audiohd_find_input_pins()
3442 *
3443 * Description:
3444 * 	Here we consider a mixer/selector with multi-input as a real sum
3445 * 	widget. Only the first real mixer/selector widget is permitted in
3446 * 	an input path(recording path). If there are more mixers/selectors
3447 * 	execept the first one, only the first input/connection of those
3448 * 	widgets will be used by our driver, that means, we ignore other
3449 * 	inputs of those mixers/selectors.
3450 */
3451static int
3452audiohd_find_input_pins(hda_codec_t *codec, wid_t wid, int allowmixer,
3453    int depth, audiohd_path_t *path)
3454{
3455	audiohd_widget_t	*widget = codec->widget[wid];
3456	audiohd_pin_t		*pin;
3457	audiohd_state_t		*statep = codec->soft_statep;
3458	uint_t			caddr = codec->index;
3459	int			retval = -1;
3460	int			num, i;
3461	uint32_t		pinctrl;
3462
3463	if (depth > AUDIOHD_MAX_DEPTH)
3464		return (uint32_t)(DDI_FAILURE);
3465	if (widget == NULL)
3466		return (uint32_t)(DDI_FAILURE);
3467
3468	/* we don't share widgets */
3469	if (widget->path_flags & AUDIOHD_PATH_ADC ||
3470	    widget->path_flags & AUDIOHD_PATH_DAC)
3471		return (uint32_t)(DDI_FAILURE);
3472
3473	switch (widget->type) {
3474	case WTYPE_PIN:
3475		pin = (audiohd_pin_t *)widget->priv;
3476		if (pin->no_phys_conn)
3477			return (uint32_t)(DDI_FAILURE);
3478		/* enable the pins' input capability */
3479		pinctrl = audioha_codec_verb_get(statep, caddr, wid,
3480		    AUDIOHDC_VERB_GET_PIN_CTRL, 0);
3481		(void) audioha_codec_verb_get(statep, caddr, wid,
3482		    AUDIOHDC_VERB_SET_PIN_CTRL,
3483		    pinctrl | AUDIOHD_PIN_IN_ENABLE);
3484		if (pin->cap & AUDIOHD_EXT_AMP_MASK) {
3485			(void) audioha_codec_verb_get(statep, caddr,
3486			    wid, AUDIOHDC_VERB_SET_EAPD,
3487			    AUDIOHD_EXT_AMP_ENABLE);
3488		}
3489		switch (pin->device) {
3490		case DTYPE_CD:
3491		case DTYPE_LINE_IN:
3492		case DTYPE_MIC_IN:
3493		case DTYPE_AUX:
3494			widget->path_flags |= AUDIOHD_PATH_ADC;
3495			widget->in_weight++;
3496			path->pin_wid[path->pin_nums++] = wid;
3497			pin->adc_dac_wid = path->adda_wid;
3498			return (DDI_SUCCESS);
3499		}
3500		break;
3501	case WTYPE_AUDIO_MIX:
3502	case WTYPE_AUDIO_SEL:
3503		/*
3504		 * If the sum widget has only one input, we don't
3505		 * consider it as a real sum widget.
3506		 */
3507		if (widget->nconns == 1) {
3508			widget->input_path_next = 0;
3509			retval = audiohd_find_input_pins(codec,
3510			    widget->avail_conn[0],
3511			    allowmixer, depth + 1, path);
3512			if (retval == DDI_SUCCESS) {
3513				widget->path_flags |= AUDIOHD_PATH_ADC;
3514				widget->in_weight++;
3515			}
3516			break;
3517		}
3518
3519		if (allowmixer) {
3520			/*
3521			 * This is a real sum widget, we will reject
3522			 * other real sum widget when we find more in
3523			 * the following path-searching.
3524			 */
3525			for (int i = 0; i < widget->nconns; i++) {
3526				retval = audiohd_find_input_pins(codec,
3527				    widget->avail_conn[i], 0, depth + 1,
3528				    path);
3529				if (retval == DDI_SUCCESS) {
3530					widget->input_path_next = i;
3531					widget->in_weight++;
3532					num = path->pin_nums - 1;
3533					path->sum_selconn[num] = i;
3534					path->sum_wid = wid;
3535					widget->path_flags |=
3536					    AUDIOHD_PATH_ADC;
3537				}
3538			}
3539
3540			/* return SUCCESS if we found at least one input path */
3541			if (path->pin_nums > 0)
3542				retval = DDI_SUCCESS;
3543		} else {
3544			/*
3545			 * We had already found a real sum before this one since
3546			 * allowmixer is 0.
3547			 */
3548			for (i = 0; i < widget->nconns; i++) {
3549				retval = audiohd_find_input_pins(codec,
3550				    widget->avail_conn[i], 0, depth + 1,
3551				    path);
3552				if (retval == DDI_SUCCESS) {
3553					widget->input_path_next = i;
3554					widget->path_flags |= AUDIOHD_PATH_ADC;
3555					widget->in_weight++;
3556					break;
3557				}
3558			}
3559		}
3560		break;
3561	default:
3562		break;
3563	}
3564
3565	return (retval);
3566}	/* audiohd_find_input_pins */
3567
3568/*
3569 * audiohd_build_input_path()
3570 *
3571 * Description:
3572 *	Find input path for the codec
3573 */
3574static void
3575audiohd_build_input_path(hda_codec_t *codec)
3576{
3577	audiohd_widget_t	*widget;
3578	audiohd_path_t		*path = NULL;
3579	wid_t			wid;
3580	int			i;
3581	int			retval;
3582	uint8_t			rtag = 0;
3583	audiohd_state_t		*statep = codec->soft_statep;
3584
3585	for (wid = codec->first_wid; wid <= codec->last_wid; wid++) {
3586
3587		widget = codec->widget[wid];
3588
3589		/* check if it is an ADC widget */
3590		if (widget == NULL || widget->type != WTYPE_AUDIO_IN)
3591			continue;
3592
3593		if (path == NULL)
3594			path = kmem_zalloc(sizeof (audiohd_path_t),
3595			    KM_SLEEP);
3596		else
3597			bzero(path, sizeof (audiohd_port_t));
3598
3599		path->adda_wid = wid;
3600
3601		/*
3602		 * Is there any ADC widget which has more than one input ??
3603		 * I don't believe. Anyway, we carefully deal with this. But
3604		 * if hardware vendors embed a selector in a ADC, we just use
3605		 * the first available input, which has connection to input pin
3606		 * widget. Because selector cannot perform mixer functionality,
3607		 * and we just permit one selector or mixer in a recording path,
3608		 * if we use the selector embedded in ADC,we cannot use possible
3609		 * mixer during path searching.
3610		 */
3611		for (i = 0; i < widget->nconns; i++) {
3612			retval = audiohd_find_input_pins(codec,
3613			    widget->avail_conn[i], 1, 0, path);
3614			if (retval == DDI_SUCCESS) {
3615				path->codec = codec;
3616				path->statep = statep;
3617				path->path_type = RECORD;
3618				path->tag = ++rtag;
3619				codec->nistream++;
3620				statep->path[statep->pathnum++] = path;
3621				widget->input_path_next = i;
3622				widget->priv = path;
3623				path = NULL;
3624				break;
3625			}
3626		}
3627	}
3628	if (path)
3629		kmem_free(path, sizeof (audiohd_path_t));
3630}	/* audiohd_build_input_path */
3631
3632/*
3633 * audiohd_build_input_amp()
3634 *
3635 * Description:
3636 *	Find gain and mute control widgets on the input path
3637 */
3638static void
3639audiohd_build_input_amp(hda_codec_t *codec)
3640{
3641	audiohd_path_t		*path;
3642	audiohd_widget_t	*wsum, *wadc, *w;
3643	audiohd_pin_t		*pin;
3644	uint_t			gain;
3645	wid_t			wid, next;
3646	int			i, j;
3647	int			weight;
3648
3649	for (i = 0; i < codec->soft_statep->pathnum; i++) {
3650		path = codec->soft_statep->path[i];
3651		if (path == NULL || path->path_type != RECORD ||
3652		    path->codec != codec)
3653			continue;
3654
3655		wid = path->adda_wid;
3656		wadc = path->codec->widget[wid];
3657		weight = wadc->in_weight;
3658
3659		/*
3660		 * Search node which has mute functionality for
3661		 * the whole input path
3662		 */
3663		w = wadc;
3664		while (w) {
3665			if (w->outamp_cap & AUDIOHDC_AMP_CAP_MUTE_CAP) {
3666				path->mute_wid = w->wid_wid;
3667				path->mute_dir = AUDIOHDC_AMP_SET_OUTPUT;
3668				break;
3669			}
3670			if ((w->inamp_cap & AUDIOHDC_AMP_CAP_MUTE_CAP) &&
3671			    (w->wid_wid != path->sum_wid)) {
3672				path->mute_wid = w->wid_wid;
3673				path->mute_dir = AUDIOHDC_AMP_SET_INPUT;
3674				break;
3675			}
3676
3677			next = w->input_path_next;
3678			if (next == AUDIOHD_NULL_CONN)
3679				break;
3680			wid = w->avail_conn[next];
3681			w = path->codec->widget[wid];
3682			if (w && w->in_weight != weight)
3683				break;
3684		}
3685
3686		/*
3687		 * Search a node for amplifier adjusting for the whole
3688		 * input path
3689		 */
3690		w = wadc;
3691		gain = 0;
3692		while (w) {
3693			gain = (w->outamp_cap & AUDIOHDC_AMP_CAP_STEP_NUMS);
3694			if (gain && gain > path->gain_bits) {
3695				path->gain_dir = AUDIOHDC_AMP_SET_OUTPUT;
3696				path->gain_bits = gain;
3697				path->gain_wid = w->wid_wid;
3698			}
3699			gain = w->inamp_cap & AUDIOHDC_AMP_CAP_STEP_NUMS;
3700			if (gain && (gain > path->gain_bits) &&
3701			    (w->wid_wid != path->sum_wid)) {
3702				path->gain_dir = AUDIOHDC_AMP_SET_INPUT;
3703				path->gain_bits = gain;
3704				path->gain_wid = w->wid_wid;
3705			}
3706
3707			next = w->input_path_next;
3708			if (next == AUDIOHD_NULL_CONN)
3709				break;
3710			wid = w->avail_conn[next];
3711			w = path->codec->widget[wid];
3712		}
3713		path->gain_bits >>= AUDIOHD_GAIN_OFF;
3714
3715		/*
3716		 * If the input path has one pin only, the mute/amp
3717		 * controlling is shared by the whole path and pin
3718		 */
3719		if (path->pin_nums == 1) {
3720			wid = path->pin_wid[0];
3721			w = path->codec->widget[wid];
3722			pin = (audiohd_pin_t *)w->priv;
3723			pin->gain_dir = path->gain_dir;
3724			pin->gain_bits = path->gain_bits;
3725			pin->gain_wid = path->gain_wid;
3726			pin->mute_wid = path->mute_wid;
3727			pin->mute_dir = path->mute_dir;
3728			continue;
3729		}
3730
3731		/*
3732		 * For multi-pin device, there must be a selector
3733		 * or mixer along the input path, and the sum_wid
3734		 * is the widget's node id.
3735		 */
3736		wid = path->sum_wid;
3737		wsum = path->codec->widget[wid]; /* sum widget */
3738
3739		for (j = 0; j < path->pin_nums; j++) {
3740			wid = path->pin_wid[j];
3741			w = path->codec->widget[wid];
3742			pin = (audiohd_pin_t *)w->priv;
3743
3744			/* find node for mute */
3745			if (wsum->inamp_cap & AUDIOHDC_AMP_CAP_MUTE_CAP) {
3746				pin->mute_wid = wsum->wid_wid;
3747				pin->mute_dir = AUDIOHDC_AMP_SET_INPUT;
3748			} else {
3749				wid = wsum->avail_conn[path->sum_selconn[i]];
3750				w = path->codec->widget[wid];
3751				while (w) {
3752					if (w->outamp_cap &
3753					    AUDIOHDC_AMP_CAP_MUTE_CAP) {
3754						pin->mute_wid = w->wid_wid;
3755						pin->mute_dir =
3756						    AUDIOHDC_AMP_SET_OUTPUT;
3757						break;
3758					}
3759					if (w->inamp_cap &
3760					    AUDIOHDC_AMP_CAP_MUTE_CAP) {
3761						pin->mute_wid = w->wid_wid;
3762						pin->mute_dir =
3763						    AUDIOHDC_AMP_SET_INPUT;
3764						break;
3765					}
3766
3767					next = w->input_path_next;
3768					if (next == AUDIOHD_NULL_CONN)
3769						break;
3770					wid = w->avail_conn[next];
3771					w = path->codec->widget[wid];
3772				}
3773			}
3774
3775			/* find node for amp controlling */
3776			gain = (wsum->inamp_cap & AUDIOHDC_AMP_CAP_STEP_NUMS);
3777			wid = wsum->avail_conn[path->sum_selconn[i]];
3778			w = path->codec->widget[wid];
3779			while (w) {
3780				gain = (w->outamp_cap &
3781				    AUDIOHDC_AMP_CAP_STEP_NUMS);
3782				if (gain && gain > pin->gain_bits) {
3783					pin->gain_dir = AUDIOHDC_AMP_SET_OUTPUT;
3784					pin->gain_bits = gain;
3785					pin->gain_wid = w->wid_wid;
3786				}
3787				gain = w->inamp_cap &
3788				    AUDIOHDC_AMP_CAP_STEP_NUMS;
3789				if (gain && (gain > pin->gain_bits)) {
3790					pin->gain_dir = AUDIOHDC_AMP_SET_INPUT;
3791					pin->gain_bits = gain;
3792					pin->gain_wid = w->wid_wid;
3793				}
3794
3795				next = w->input_path_next;
3796				if (next == AUDIOHD_NULL_CONN)
3797					break;
3798				wid = w->avail_conn[next];
3799				w = path->codec->widget[wid];
3800			}
3801			pin->gain_bits >>= AUDIOHD_GAIN_OFF;
3802		}
3803	}
3804}	/* audiohd_build_input_amp() */
3805
3806/*
3807 * audiohd_finish_input_path()
3808 *
3809 * Description:
3810 *	Enable the widgets on the input path
3811 */
3812static void
3813audiohd_finish_input_path(hda_codec_t *codec)
3814{
3815	audiohd_state_t		*statep = codec->soft_statep;
3816	audiohd_path_t		*path;
3817	audiohd_widget_t	*w, *wsum;
3818	uint_t			caddr = codec->index;
3819	wid_t			wid;
3820	int			i, j;
3821
3822	for (i = 0; i < codec->soft_statep->pathnum; i++) {
3823		path = codec->soft_statep->path[i];
3824		if (path == NULL || path->path_type != RECORD ||
3825		    path->codec != codec)
3826			continue;
3827		wid = path->adda_wid;
3828		w = path->codec->widget[wid];
3829		while (w && (w->wid_wid != path->sum_wid) &&
3830		    (w->type != WTYPE_PIN)) {
3831			if ((w->type == WTYPE_AUDIO_SEL) && (w->nconns > 1))
3832				(void) audioha_codec_verb_get(statep, caddr,
3833				    w->wid_wid, AUDIOHDC_VERB_SET_CONN_SEL,
3834				    w->input_path_next);
3835
3836			if (w->outamp_cap) {
3837				(void) audioha_codec_4bit_verb_get(statep,
3838				    caddr,
3839				    w->wid_wid, AUDIOHDC_VERB_SET_AMP_MUTE,
3840				    AUDIOHDC_AMP_SET_LR_OUTPUT |
3841				    AUDIOHDC_GAIN_MAX);
3842			}
3843
3844			if (w->inamp_cap) {
3845				(void) audioha_codec_4bit_verb_get(statep,
3846				    caddr,
3847				    w->wid_wid, AUDIOHDC_VERB_SET_AMP_MUTE,
3848				    AUDIOHDC_AMP_SET_LR_INPUT |
3849				    AUDIOHDC_GAIN_MAX |
3850				    (w->input_path_next <<
3851				    AUDIOHDC_AMP_SET_INDEX_OFFSET));
3852			}
3853
3854			wid = w->avail_conn[w->input_path_next];
3855			w = path->codec->widget[wid];
3856		}
3857
3858		/*
3859		 * After exiting from the above loop, the widget pointed
3860		 * by w can be a pin widget or select/mixer widget. If it
3861		 * is a pin widget, we already finish "select connection"
3862		 * operation for the whole path.
3863		 */
3864		if (w && w->type == WTYPE_PIN)
3865			continue;
3866
3867		/*
3868		 * deal with multi-pin input devices.
3869		 */
3870		wid = path->sum_wid;
3871		wsum = path->codec->widget[wid];
3872		if (wsum == NULL)
3873			continue;
3874		if (wsum->outamp_cap) {
3875			(void) audioha_codec_4bit_verb_get(statep,
3876			    caddr,
3877			    wsum->wid_wid, AUDIOHDC_VERB_SET_AMP_MUTE,
3878			    AUDIOHDC_AMP_SET_LR_OUTPUT |
3879			    AUDIOHDC_GAIN_MAX);
3880		}
3881
3882		for (j = 0; j < path->pin_nums; j++) {
3883			if (wsum->inamp_cap) {
3884				(void) audioha_codec_4bit_verb_get(statep,
3885				    caddr,
3886				    wsum->wid_wid, AUDIOHDC_VERB_SET_AMP_MUTE,
3887				    AUDIOHDC_AMP_SET_LR_INPUT |
3888				    AUDIOHDC_GAIN_MAX |
3889				    (path->sum_selconn[j] <<
3890				    AUDIOHDC_AMP_SET_INDEX_OFFSET));
3891			}
3892			if (wsum->type == WTYPE_AUDIO_SEL) {
3893				(void) audioha_codec_verb_get(statep, caddr,
3894				    wsum->wid_wid,
3895				    AUDIOHDC_VERB_SET_CONN_SEL,
3896				    path->sum_selconn[j]);
3897			}
3898
3899			wid = wsum->avail_conn[path->sum_selconn[j]];
3900			w = path->codec->widget[wid];
3901			while (w && w->type != WTYPE_PIN) {
3902				if ((w->type != WTYPE_AUDIO_MIX) &&
3903				    (w->nconns > 1))
3904					(void) audioha_codec_verb_get(statep,
3905					    caddr, w->wid_wid,
3906					    AUDIOHDC_VERB_SET_CONN_SEL,
3907					    w->input_path_next);
3908
3909				if (w->outamp_cap) {
3910					(void) audioha_codec_4bit_verb_get(
3911					    statep,
3912					    caddr,
3913					    w->wid_wid,
3914					    AUDIOHDC_VERB_SET_AMP_MUTE,
3915					    AUDIOHDC_AMP_SET_LR_OUTPUT |
3916					    AUDIOHDC_GAIN_MAX);
3917				}
3918
3919				if (w->inamp_cap) {
3920					(void) audioha_codec_4bit_verb_get(
3921					    statep,
3922					    caddr,
3923					    w->wid_wid,
3924					    AUDIOHDC_VERB_SET_AMP_MUTE,
3925					    AUDIOHDC_AMP_SET_LR_INPUT |
3926					    AUDIOHDC_GAIN_MAX |
3927					    (w->input_path_next <<
3928					    AUDIOHDC_AMP_SET_INDEX_OFFSET));
3929				}
3930				wid = w->avail_conn[w->input_path_next];
3931				w = path->codec->widget[wid];
3932			}
3933		}
3934	}	/* end of istream loop */
3935}	/* audiohd_finish_input_path */
3936
3937/*
3938 * audiohd_find_inpin_for_monitor()
3939 *
3940 * Description:
3941 *	Find input pin for monitor path.
3942 *
3943 * Arguments:
3944 *	hda_codec_t		*codec		where the monitor path exists
3945 *	wid_t			id		no. of widget being searched
3946 *	int			mixer		share or not
3947 */
3948static int
3949audiohd_find_inpin_for_monitor(hda_codec_t *codec, wid_t id, int mixer)
3950{
3951	wid_t 			wid;
3952	audiohd_widget_t	*widget, *w;
3953	audiohd_pin_t		*pin;
3954	int 			i, find = 0;
3955
3956	wid = id;
3957	widget = codec->widget[wid];
3958	if (widget == NULL)
3959		return (uint32_t)(DDI_FAILURE);
3960
3961	if (widget->type == WTYPE_PIN) {
3962		pin = (audiohd_pin_t *)widget->priv;
3963		if (pin->no_phys_conn)
3964			return (uint32_t)(DDI_FAILURE);
3965		switch (pin->device) {
3966			case DTYPE_SPDIF_IN:
3967			case DTYPE_CD:
3968			case DTYPE_LINE_IN:
3969			case DTYPE_MIC_IN:
3970			case DTYPE_AUX:
3971				widget->path_flags |= AUDIOHD_PATH_MON;
3972				return (DDI_SUCCESS);
3973			default:
3974				return (uint32_t)(DDI_FAILURE);
3975		}
3976	}
3977	/* the widget has been visited and can't be directed to input pin */
3978	if (widget->path_flags & AUDIOHD_PATH_NOMON) {
3979		return (uint32_t)(DDI_FAILURE);
3980	}
3981	/* the widget has been used by the monitor path, and we can share it */
3982	if (widget->path_flags & AUDIOHD_PATH_MON) {
3983		if (mixer)
3984			return (DDI_SUCCESS);
3985		else
3986			return (uint32_t)(DDI_FAILURE);
3987	}
3988	switch (widget->type) {
3989		case WTYPE_AUDIO_MIX:
3990			for (i = 0; i < widget->nconns; i++) {
3991				if (widget->output_path_next == i)
3992					continue;
3993				if (audiohd_find_inpin_for_monitor(codec,
3994				    widget->avail_conn[i], mixer) ==
3995				    DDI_SUCCESS) {
3996					w = widget;
3997					w->monitor_path_next[w->used++] = i;
3998					w->path_flags |= AUDIOHD_PATH_MON;
3999					find = 1;
4000				}
4001			}
4002			break;
4003		case WTYPE_AUDIO_SEL:
4004			for (i = 0; i < widget->nconns; i++) {
4005				if (widget->output_path_next == i)
4006					continue;
4007				if (audiohd_find_inpin_for_monitor(codec,
4008				    widget->avail_conn[i], mixer) ==
4009				    DDI_SUCCESS) {
4010					widget->monitor_path_next[0] = i;
4011					widget->path_flags |= AUDIOHD_PATH_MON;
4012					find = 1;
4013					break;
4014				}
4015			}
4016			break;
4017		default:
4018			break;
4019	}
4020	if (!find) {
4021		widget->path_flags |= AUDIOHD_PATH_NOMON;
4022		return (uint32_t)(DDI_FAILURE);
4023	}
4024	else
4025		return (DDI_SUCCESS);
4026}	/* audiohd_find_inpin_for_monitor */
4027
4028/*
4029 * audiohd_build_monitor_path()
4030 *
4031 * Description:
4032 * 	The functionality of mixer is to mix inputs, such as CD-IN, MIC,
4033 * 	Line-in, etc, with DAC outputs, so as to minitor what is being
4034 * 	recorded and implement "What you hear is what you get". However,
4035 * 	this functionality are really hardware-dependent: the inputs
4036 * 	must be directed to MIXER if they can be directed to ADC as
4037 * 	recording sources.
4038 */
4039static void
4040audiohd_build_monitor_path(hda_codec_t *codec)
4041{
4042	audiohd_path_t		*path;
4043	audiohd_widget_t	*widget, *w;
4044	audiohd_state_t		*statep = codec->soft_statep;
4045	wid_t			wid, next;
4046	int			i, j, k, l, find;
4047	int			mixernum = 0;
4048
4049	for (i = 0; i < statep->pathnum; i++) {
4050		path = statep->path[i];
4051		if (path == NULL || path->codec != codec ||
4052		    path->path_type != PLAY)
4053			continue;
4054		for (j = 0; j < path->pin_nums; j++) {
4055			wid = path->pin_wid[j];
4056			widget = codec->widget[wid];
4057			l = 0;
4058			while (widget) {
4059				while (widget &&
4060				    ((widget->type != WTYPE_AUDIO_MIX) ||
4061				    (widget->nconns < 2))) {
4062					next = widget->output_path_next;
4063					if (next == AUDIOHD_NULL_CONN)
4064						break;
4065					wid = widget->avail_conn[next];
4066					widget = codec->widget[wid];
4067				}
4068
4069				/*
4070				 * No mixer in this output path, we cannot build
4071				 * mixer path for this path, skip it,
4072				 * and continue for next output path.
4073				 */
4074				if (widget == NULL ||
4075				    widget->output_path_next ==
4076				    AUDIOHD_NULL_CONN) {
4077					break;
4078				}
4079				mixernum++;
4080				for (k = 0; k < widget->nconns; k++) {
4081
4082					/*
4083					 * this connection must be routined
4084					 * to DAC instead of an input pin
4085					 * widget, we needn't waste time for
4086					 * it
4087					 */
4088					if (widget->output_path_next == k)
4089						continue;
4090					find = 0;
4091					if (audiohd_find_inpin_for_monitor(
4092					    codec,
4093					    widget->avail_conn[k], 0) ==
4094					    DDI_SUCCESS) {
4095						path->mon_wid[j][l] = wid;
4096						w = widget;
4097						w->monitor_path_next[w->used++]
4098						    = k;
4099						w->path_flags |=
4100						    AUDIOHD_PATH_MON;
4101						find = 1;
4102					} else if (
4103					    audiohd_find_inpin_for_monitor(
4104					    codec,
4105					    widget->avail_conn[k], 1) ==
4106					    DDI_SUCCESS) {
4107						path->mon_wid[j][l] = wid;
4108						w = widget;
4109						w->monitor_path_next[w->used++]
4110						    = k;
4111						w->path_flags |=
4112						    AUDIOHD_PATH_MON;
4113						find = 1;
4114					}
4115
4116				}
4117
4118				/*
4119				 * we needn't check widget->output_path_next
4120				 * here since this widget is a selector or
4121				 * mixer, it cannot be NULL connection.
4122				 */
4123				if (!find) {
4124					path->mon_wid[j][l] = 0;
4125					widget->path_flags |=
4126					    AUDIOHD_PATH_NOMON;
4127				}
4128				next = widget->output_path_next;
4129				wid = widget->avail_conn[next];
4130				widget = codec->widget[wid];
4131				l++;
4132			}
4133			path->maxmixer[j] = l;
4134		}
4135
4136	}
4137	if (mixernum == 0)
4138		statep->monitor_unsupported = B_TRUE;
4139	else
4140		statep->monitor_unsupported = B_FALSE;
4141}	/* audiohd_build_monitor_path */
4142
4143/*
4144 * audiohd_do_finish_monitor_path
4145 *
4146 * Description:
4147 *	Enable the widgets on the monitor path
4148 */
4149static void
4150audiohd_do_finish_monitor_path(hda_codec_t *codec, audiohd_widget_t *wgt)
4151{
4152	uint_t			caddr = codec->index;
4153	audiohd_widget_t 	*widget = wgt;
4154	audiohd_widget_t	*w;
4155	audiohd_state_t		*statep = codec->soft_statep;
4156	wid_t			wid;
4157	int			i;
4158	int			share = 0;
4159
4160	if (!widget || widget->finish)
4161		return;
4162	if (widget->path_flags & AUDIOHD_PATH_ADC)
4163		share = 1;
4164	if ((widget->outamp_cap) && !share)
4165		(void) audioha_codec_4bit_verb_get(statep, caddr,
4166		    widget->wid_wid, AUDIOHDC_VERB_SET_AMP_MUTE,
4167		    AUDIOHDC_AMP_SET_LR_OUTPUT | AUDIOHDC_GAIN_MAX);
4168	if ((widget->inamp_cap) && !share) {
4169		for (i = 0; i < widget->used; i++) {
4170		(void) audioha_codec_4bit_verb_get(statep, caddr,
4171		    widget->wid_wid, AUDIOHDC_VERB_SET_AMP_MUTE,
4172		    AUDIOHDC_AMP_SET_LR_INPUT | AUDIOHDC_GAIN_MAX |
4173		    (widget->monitor_path_next[i]
4174		    << AUDIOHDC_AMP_SET_INDEX_OFFSET));
4175		}
4176	}
4177	if ((widget->type == WTYPE_AUDIO_SEL) && (widget->nconns > 1) &&
4178	    !share) {
4179		(void) audioha_codec_verb_get(statep, caddr, widget->wid_wid,
4180		    AUDIOHDC_VERB_SET_CONN_SEL, widget->monitor_path_next[0]);
4181	}
4182	widget->finish = 1;
4183	if (widget->used == 0)
4184		return;
4185	if (widget->used > 0) {
4186		for (i = 0; i < widget->used; i++) {
4187			wid = widget->avail_conn[widget->monitor_path_next[i]];
4188			w = codec->widget[wid];
4189			audiohd_do_finish_monitor_path(codec, w);
4190		}
4191	}
4192}	/* audiohd_do_finish_monitor_path */
4193
4194/*
4195 * audiohd_finish_monitor_path
4196 *
4197 * Description:
4198 *	Enable the monitor path for every ostream path
4199 */
4200static void
4201audiohd_finish_monitor_path(hda_codec_t *codec)
4202{
4203	audiohd_path_t		*path;
4204	audiohd_widget_t	*widget;
4205	audiohd_state_t		*statep = codec->soft_statep;
4206	wid_t			wid;
4207	int 			i, j, k;
4208
4209	for (i = 0; i < statep->pathnum; i++) {
4210		path = statep->path[i];
4211		if (!path || path->codec != codec || path->path_type != PLAY)
4212			continue;
4213		for (j = 0; j < path->pin_nums; j++) {
4214			for (k = 0; k < path->maxmixer[j]; k++) {
4215				wid = path->mon_wid[j][k];
4216				if (wid == 0) {
4217					continue;
4218				}
4219				widget = codec->widget[wid];
4220				audiohd_do_finish_monitor_path(codec, widget);
4221			}
4222		}
4223	}
4224}	/* audiohd_finish_monitor_path */
4225
4226/*
4227 * audiohd_do_build_monit_amp()
4228 *
4229 * Description:
4230 *	Search for the gain control widget for the monitor path
4231 */
4232static void
4233audiohd_do_build_monitor_amp(hda_codec_t *codec, audiohd_pin_t *pin,
4234    audiohd_widget_t *widget)
4235{
4236	audiohd_widget_t	*w = widget;
4237	uint32_t		gain;
4238	int			i;
4239	wid_t			wid;
4240
4241	if (!w ||
4242	    (w->type == WTYPE_PIN) ||
4243	    !w->used ||
4244	    (pin->num == AUDIOHD_MAX_CONN) ||
4245	    (w->path_flags & AUDIOHD_PATH_ADC))
4246		return;
4247	if (!(w->path_flags & AUDIOHD_PATH_DAC)) {
4248		gain = w->outamp_cap & AUDIOHDC_AMP_CAP_STEP_NUMS;
4249		if (gain) {
4250			pin->mg_dir[pin->num] = AUDIOHDC_AMP_SET_OUTPUT;
4251			pin->mg_gain[pin->num] = gain;
4252			pin->mg_wid[pin->num] = w->wid_wid;
4253			pin->mg_gain[pin->num] >>= AUDIOHD_GAIN_OFF;
4254			pin->num++;
4255			return;
4256		}
4257		gain = w->inamp_cap & AUDIOHDC_AMP_CAP_STEP_NUMS;
4258		if (gain) {
4259			pin->mg_dir[pin->num] = AUDIOHDC_AMP_SET_INPUT;
4260			pin->mg_gain[pin->num] = gain;
4261			pin->mg_wid[pin->num] = w->wid_wid;
4262			pin->mg_gain[pin->num] >>= AUDIOHD_GAIN_OFF;
4263			pin->num++;
4264			return;
4265		}
4266	}
4267	for (i = 0; i < w->used; i++) {
4268		wid = w->avail_conn[w->monitor_path_next[i]];
4269		audiohd_do_build_monitor_amp(codec, pin, codec->widget[wid]);
4270	}
4271
4272
4273}	/* audiohd_do_build_monitor_amp() */
4274
4275/*
4276 * audiohd_build_monitor_amp()
4277 *
4278 * Description:
4279 *	Search gain control widget for every ostream monitor
4280 */
4281static void
4282audiohd_build_monitor_amp(hda_codec_t *codec)
4283{
4284	audiohd_path_t		*path;
4285	audiohd_widget_t	*widget, *w;
4286	audiohd_state_t		*statep = codec->soft_statep;
4287	audiohd_pin_t		*pin;
4288	wid_t			wid, id;
4289	int			i, j, k;
4290
4291	for (i = 0; i < statep->pathnum; i++) {
4292		path = statep->path[i];
4293		if (!path || path->codec != codec || path->path_type != PLAY)
4294			continue;
4295		for (j = 0; j < path->pin_nums; j++) {
4296			id = path->pin_wid[j];
4297			w = codec->widget[id];
4298			pin = (audiohd_pin_t *)(w->priv);
4299			for (k = 0; k < path->maxmixer[j]; k++) {
4300				wid = path->mon_wid[j][k];
4301				if (!wid)
4302					continue;
4303				widget = codec->widget[wid];
4304				audiohd_do_build_monitor_amp(codec, pin,
4305				    widget);
4306			}
4307		}
4308	}
4309}
4310
4311/*
4312 * audiohd_find_beep()
4313 * Description:
4314 *      Find a beep for a beep path. Then the play data can be sent to the out
4315 *      put pin through the beep path.
4316 *
4317 * Arguments:
4318 *      hda_codec_t     *codec          where the beep widget exists
4319 *      wid_t           wid             the no. of a widget
4320 *      int             depth           the depth of search
4321 *
4322 * Return:
4323 *      1) wid of Beep widget;
4324 *      2) 0 if no path
4325 */
4326static wid_t
4327audiohd_find_beep(hda_codec_t *codec, wid_t wid, int depth)
4328{
4329	audiohd_widget_t	*widget = codec->widget[wid];
4330	wid_t   		wbeep = (uint32_t)(DDI_FAILURE);
4331	wid_t   		retval;
4332
4333	if (depth > AUDIOHD_MAX_DEPTH)
4334		return (uint32_t)(DDI_FAILURE);
4335
4336	if (widget == NULL)
4337		return (uint32_t)(DDI_FAILURE);
4338
4339	switch (widget->type) {
4340	case WTYPE_BEEP:
4341		widget->path_flags |= AUDIOHD_PATH_BEEP;
4342		wbeep = widget->wid_wid;
4343		break;
4344	case WTYPE_AUDIO_MIX:
4345	case WTYPE_AUDIO_SEL:
4346		for (int i = 0; i < widget->nconns; i++) {
4347			retval = audiohd_find_beep(codec,
4348			    widget->avail_conn[i], depth + 1);
4349			if (retval == DDI_SUCCESS) {
4350				if (widget->output_path_next !=
4351				    AUDIOHD_NULL_CONN)
4352					continue;
4353				widget->beep_path_next = i;
4354				wbeep = retval;
4355				widget->path_flags |= AUDIOHD_PATH_BEEP;
4356				return (wbeep);
4357			}
4358		}
4359		break;
4360	default:
4361		break;
4362	}
4363
4364	return (wbeep);
4365}       /* audiohd_find_beep() */
4366
4367/*
4368 * audiohd_build_beep_path()
4369 *
4370 * Description:
4371 *      Search an beep path for each pin in the codec.
4372 * Arguments:
4373 *      hda_codec_t     *codec          where the beep path exists
4374 */
4375static void
4376audiohd_build_beep_path(hda_codec_t *codec)
4377{
4378	audiohd_pin_t		*pin;
4379	audiohd_widget_t	*widget;
4380	audiohd_path_t		*path;
4381	wid_t			wid;
4382	audiohd_state_t		*statep;
4383	int			i;
4384	boolean_t		beeppath = B_FALSE;
4385
4386	statep = codec->soft_statep;
4387
4388	for (pin = codec->first_pin; pin; pin = pin->next) {
4389		if ((pin->cap & AUDIOHD_PIN_CAP_MASK) == 0)
4390			continue;
4391		if ((pin->config & AUDIOHD_PIN_CONF_MASK) ==
4392		    AUDIOHD_PIN_NO_CONN)
4393			continue;
4394		if ((pin->device != DTYPE_LINEOUT) &&
4395		    (pin->device != DTYPE_SPEAKER) &&
4396		    (pin->device != DTYPE_SPDIF_OUT) &&
4397		    (pin->device != DTYPE_HP_OUT))
4398			continue;
4399		widget = codec->widget[pin->wid];
4400
4401		widget->inamp_cap = 0;
4402		for (i = 0; i < widget->nconns; i++) {
4403			/*
4404			 * If a beep found, the return value is the wid of the
4405			 * widget on the path, or the return value is
4406			 * DDI_FAILURE
4407			 */
4408			wid = audiohd_find_beep(codec,
4409			    widget->avail_conn[i], 0);
4410			/*
4411			 * A beep was not found
4412			 */
4413			if (wid == (wid_t)DDI_FAILURE)
4414				continue;
4415			if (widget->output_path_next != AUDIOHD_NULL_CONN)
4416				continue;
4417			path = (audiohd_path_t *)
4418			    kmem_zalloc(sizeof (audiohd_path_t),
4419			    KM_SLEEP);
4420			path->beep_wid = wid;
4421			path->pin_wid[0] = widget->wid_wid;
4422			path->pin_nums = 1;
4423			path->path_type = BEEP;
4424			beeppath = 1;
4425			path->codec = codec;
4426			path->statep = statep;
4427			widget->path_flags |= AUDIOHD_PATH_BEEP;
4428			widget->beep_path_next = i;
4429			statep->path[statep->pathnum++] = path;
4430			break;
4431		}
4432	}
4433
4434	if (!beeppath) {
4435		for (int i = 0; i < AUDIOHD_CODEC_MAX; i++) {
4436			codec = statep->codec[i];
4437			if (codec == NULL)
4438				continue;
4439			for (wid = codec->first_wid; wid <= codec->last_wid;
4440			    wid++) {
4441				widget = codec->widget[wid];
4442
4443				if (widget->type == WTYPE_BEEP) {
4444					path = (audiohd_path_t *)
4445					    kmem_zalloc(sizeof (audiohd_path_t),
4446					    KM_SLEEP);
4447					path->beep_wid = wid;
4448					path->pin_nums = 0;
4449					path->path_type = BEEP;
4450					beeppath = 1;
4451					path->codec = codec;
4452					path->statep = statep;
4453					widget->path_flags |= AUDIOHD_PATH_BEEP;
4454					statep->path[statep->pathnum++] = path;
4455					break;
4456				}
4457			}
4458		}
4459	}
4460}       /* audiohd_build_beep_path() */
4461
4462/*
4463 * audiohd_build_beep_amp
4464 *
4465 * Description:
4466 *      Find the gain control and mute control widget
4467 */
4468static void
4469audiohd_build_beep_amp(hda_codec_t *codec)
4470{
4471	audiohd_path_t		*path;
4472	audiohd_widget_t	*widget, *wpin, *wbeep;
4473	wid_t			wid, next;
4474	int			i, j;
4475	uint32_t		gain;
4476
4477	for (i = 0; i < codec->soft_statep->pathnum; i++) {
4478		path = codec->soft_statep->path[i];
4479		if (path == NULL || path->path_type != BEEP ||
4480		    path->codec != codec)
4481			continue;
4482		if (path->pin_nums == 0) {
4483			path->mute_wid = path->beep_wid;
4484			path->mute_dir = AUDIOHDC_AMP_SET_OUTPUT;
4485			wbeep = codec->widget[path->beep_wid];
4486			gain = (wbeep->outamp_cap &
4487			    AUDIOHDC_AMP_CAP_STEP_NUMS);
4488			if (gain) {
4489				path->gain_dir = AUDIOHDC_AMP_SET_OUTPUT;
4490				path->gain_bits = gain;
4491				path->gain_wid = path->beep_wid;
4492			}
4493			path->gain_bits >>= AUDIOHD_GAIN_OFF;
4494			break;
4495		}
4496		for (j = 0; j < path->pin_nums; j++) {
4497			wid = path->pin_wid[j];
4498			wpin = codec->widget[wid];
4499			wbeep = codec->widget[path->beep_wid];
4500
4501			widget = wpin;
4502			while (widget) {
4503				if (widget->out_weight == 0 &&
4504				    widget->outamp_cap &
4505				    AUDIOHDC_AMP_CAP_MUTE_CAP) {
4506					path->mute_wid = widget->wid_wid;
4507					path->mute_dir =
4508					    AUDIOHDC_AMP_SET_OUTPUT;
4509					break;
4510				}
4511				next = widget->beep_path_next;
4512				if (next == AUDIOHD_NULL_CONN)
4513					break;
4514				wid = widget->avail_conn[next];
4515				widget = codec->widget[wid];
4516			}
4517
4518			gain = 0;
4519			widget = wpin;
4520			while (widget) {
4521				if (widget->out_weight == 0 &&
4522				    widget->outamp_cap &
4523				    AUDIOHDC_AMP_CAP_STEP_NUMS) {
4524					gain = (widget->outamp_cap &
4525					    AUDIOHDC_AMP_CAP_STEP_NUMS);
4526					if (gain && gain > path->gain_bits) {
4527						path->gain_dir =
4528						    AUDIOHDC_AMP_SET_OUTPUT;
4529						path->gain_bits = gain;
4530						path->gain_wid =
4531						    widget->wid_wid;
4532					}
4533				}
4534				next = widget->beep_path_next;
4535				if (next == AUDIOHD_NULL_CONN)
4536					break;
4537				wid = widget->avail_conn[next];
4538				widget = codec->widget[wid];
4539			}
4540			path->gain_bits >>= AUDIOHD_GAIN_OFF;
4541		}
4542	}
4543}       /* audiohd_build_beep_amp */
4544
4545/*
4546 * audiohd_finish_beep_path()
4547 *
4548 * Description:
4549 *      Enable the widgets on the beep path
4550 */
4551static void
4552audiohd_finish_beep_path(hda_codec_t *codec)
4553{
4554	audiohd_state_t		*statep = codec->soft_statep;
4555	audiohd_path_t		*path;
4556	audiohd_widget_t	*widget;
4557	uint_t			caddr = codec->index;
4558	wid_t			wid, next;
4559	int			i, j;
4560
4561	for (i = 0; i < codec->soft_statep->pathnum; i++) {
4562		path = codec->soft_statep->path[i];
4563		if (!path || path->path_type != BEEP || path->codec != codec)
4564			continue;
4565		if (path->pin_nums == 0) {
4566			widget = codec->widget[path->beep_wid];
4567			if (widget->outamp_cap) {
4568				(void) audioha_codec_4bit_verb_get(
4569				    statep, caddr,
4570				    path->beep_wid, AUDIOHDC_VERB_SET_AMP_MUTE,
4571				    AUDIOHDC_AMP_SET_LR_OUTPUT |
4572				    AUDIOHDC_GAIN_MAX);
4573			}
4574			if (widget->inamp_cap) {
4575				(void) audioha_codec_4bit_verb_get(
4576				    statep, caddr,
4577				    path->beep_wid, AUDIOHDC_VERB_SET_AMP_MUTE,
4578				    AUDIOHDC_AMP_SET_LR_INPUT |
4579				    AUDIOHDC_GAIN_MAX |
4580				    (widget->beep_path_next <<
4581				    AUDIOHDC_AMP_SET_INDEX_OFFSET));
4582			}
4583			continue;
4584		}
4585
4586		for (j = 0; j < path->pin_nums; j++) {
4587			wid = path->pin_wid[j];
4588			widget = codec->widget[wid];
4589
4590			(void) audioha_codec_verb_get(statep, caddr, wid,
4591			    AUDIOHDC_VERB_SET_CONN_SEL, widget->beep_path_next);
4592
4593			wid = widget->avail_conn[widget->beep_path_next];
4594			widget = codec->widget[wid];
4595
4596			while (widget) {
4597				/*
4598				 * Set all amplifiers in this path to
4599				 * the maximum volume and unmute them.
4600				 */
4601				if (widget->out_weight != 0)
4602					continue;
4603				if (widget->outamp_cap) {
4604					(void) audioha_codec_4bit_verb_get(
4605					    statep, caddr,
4606					    wid, AUDIOHDC_VERB_SET_AMP_MUTE,
4607					    AUDIOHDC_AMP_SET_LR_OUTPUT |
4608					    AUDIOHDC_GAIN_MAX);
4609				}
4610				if (widget->inamp_cap) {
4611					(void) audioha_codec_4bit_verb_get(
4612					    statep, caddr,
4613					    wid, AUDIOHDC_VERB_SET_AMP_MUTE,
4614					    AUDIOHDC_AMP_SET_LR_INPUT |
4615					    AUDIOHDC_GAIN_MAX |
4616					    (widget->beep_path_next <<
4617					    AUDIOHDC_AMP_SET_INDEX_OFFSET));
4618				}
4619
4620				next = widget->beep_path_next;
4621				if (next == AUDIOHD_NULL_CONN)
4622					break;
4623				/*
4624				 * Accoding to HD spec, mixer doesn't support
4625				 * "select connection"
4626				 */
4627				if ((widget->type != WTYPE_AUDIO_MIX) &&
4628				    (widget->nconns > 1))
4629					(void) audioha_codec_verb_get(statep,
4630					    caddr, wid,
4631					    AUDIOHDC_VERB_SET_CONN_SEL,
4632					    widget->beep_path_next);
4633
4634				wid = widget->avail_conn[next];
4635				widget = codec->widget[wid];
4636			}
4637		}
4638	}
4639}       /* audiohd_finish_beep_path */
4640
4641/*
4642 * audiohd_build_path()
4643 *
4644 * Description:
4645 *	Here we build the output, input, monitor path.
4646 *	And also enable the path in default.
4647 *	Search for the gain and mute control for the path
4648 */
4649static void
4650audiohd_build_path(audiohd_state_t *statep)
4651{
4652	int		i;
4653
4654	for (i = 0; i < AUDIOHD_CODEC_MAX; i++) {
4655		if (statep->codec[i]) {
4656			audiohd_build_output_path(statep->codec[i]);
4657			audiohd_build_output_amp(statep->codec[i]);
4658			audiohd_finish_output_path(statep->codec[i]);
4659
4660			audiohd_build_input_path(statep->codec[i]);
4661			audiohd_build_input_amp(statep->codec[i]);
4662			audiohd_finish_input_path(statep->codec[i]);
4663
4664			audiohd_build_monitor_path(statep->codec[i]);
4665			audiohd_build_monitor_amp(statep->codec[i]);
4666			audiohd_finish_monitor_path(statep->codec[i]);
4667
4668			audiohd_build_beep_path(statep->codec[i]);
4669			audiohd_build_beep_amp(statep->codec[i]);
4670			audiohd_finish_beep_path(statep->codec[i]);
4671		}
4672	}
4673}	/* audiohd_build_path */
4674
4675/*
4676 * audiohd_allocate_port()
4677 */
4678static int
4679audiohd_allocate_port(audiohd_state_t *statep)
4680{
4681	int			i, j;
4682	audiohd_port_t		*port;
4683	int			dir;
4684	unsigned		caps;
4685	int			rc;
4686	audio_dev_t		*adev;
4687	dev_info_t		*dip;
4688	ddi_dma_cookie_t	cookie;
4689	uint_t			count;
4690	uint64_t		buf_phys_addr;
4691	sd_bdle_t		*entry;
4692	uint16_t		gcap;
4693	size_t			real_size;
4694
4695	adev = statep->adev;
4696	dip = statep->hda_dip;
4697
4698	ddi_dma_attr_t	dma_attr = {
4699		DMA_ATTR_V0,		/* version */
4700		0,			/* addr_lo */
4701		0xffffffffffffffffULL,	/* addr_hi */
4702		0x00000000ffffffffULL,	/* count_max */
4703		128,			/* 128-byte alignment as HD spec */
4704		0xfff,			/* burstsize */
4705		1,			/* minxfer */
4706		0xffffffff,		/* maxxfer */
4707		0xffffffff,		/* seg */
4708		1,			/* sgllen */
4709		1,			/* granular */
4710		0			/* flags */
4711	};
4712
4713	gcap = AUDIOHD_REG_GET16(AUDIOHD_REG_GCAP);
4714	if ((gcap & AUDIOHDR_GCAP_64OK) == 0)
4715		dma_attr.dma_attr_addr_hi = 0xffffffffUL;
4716
4717	for (i = 0; i < PORT_MAX; i++) {
4718		port = kmem_zalloc(sizeof (*port), KM_SLEEP);
4719		statep->port[i] = port;
4720		port->statep = statep;
4721		switch (i) {
4722		case PORT_ADC:
4723			dir = DDI_DMA_READ | DDI_DMA_CONSISTENT;
4724			caps = ENGINE_INPUT_CAP;
4725			port->sync_dir = DDI_DMA_SYNC_FORKERNEL;
4726			port->nchan = statep->rchan;
4727			port->index = 1;
4728			port->regoff = AUDIOHD_REG_SD_BASE;
4729			break;
4730		case PORT_DAC:
4731			dir = DDI_DMA_WRITE | DDI_DMA_CONSISTENT;
4732			caps = ENGINE_OUTPUT_CAP;
4733			port->sync_dir = DDI_DMA_SYNC_FORDEV;
4734			port->nchan = statep->pchan;
4735			port->index = statep->hda_input_streams + 1;
4736			port->regoff = AUDIOHD_REG_SD_BASE +
4737			    AUDIOHD_REG_SD_LEN *
4738			    statep->hda_input_streams;
4739			break;
4740		default:
4741			return (DDI_FAILURE);
4742		}
4743
4744		port->format = AUDIOHD_FMT_PCM;
4745		port->nframes = 1024 * AUDIOHD_BDLE_NUMS;
4746		port->fragsize = 1024 * port->nchan * 2;
4747		port->bufsize = port->nframes * port->nchan * 2;
4748
4749		/* allocate dma handle */
4750		rc = ddi_dma_alloc_handle(dip, &dma_attr, DDI_DMA_SLEEP,
4751		    NULL, &port->samp_dmah);
4752		if (rc != DDI_SUCCESS) {
4753			audio_dev_warn(adev, "ddi_dma_alloc_handle failed: %d",
4754			    rc);
4755			return (DDI_FAILURE);
4756		}
4757
4758		/*
4759		 * Warning: please be noted that allocating the dma memory
4760		 * with the flag IOMEM_DATA_UNCACHED is a hack due
4761		 * to an incorrect cache synchronization on NVidia MCP79
4762		 * chipset which causes the audio distortion problem,
4763		 * and that it should be fixed later. There should be
4764		 * no reason you have to allocate UNCACHED memory. In
4765		 * complex architectures with nested IO caches,
4766		 * reliance on this flag might lead to failure.
4767		 */
4768		rc = ddi_dma_mem_alloc(port->samp_dmah, port->bufsize,
4769		    &hda_dev_accattr, DDI_DMA_CONSISTENT | IOMEM_DATA_UNCACHED,
4770		    DDI_DMA_SLEEP, NULL, &port->samp_kaddr,
4771		    &real_size, &port->samp_acch);
4772		if (rc == DDI_FAILURE) {
4773			if (ddi_dma_mem_alloc(port->samp_dmah, port->bufsize,
4774			    &hda_dev_accattr, DDI_DMA_CONSISTENT,
4775			    DDI_DMA_SLEEP, NULL,
4776			    &port->samp_kaddr, &real_size,
4777			    &port->samp_acch) != DDI_SUCCESS) {
4778				audio_dev_warn(adev,
4779				    "ddi_dma_mem_alloc failed");
4780				return (DDI_FAILURE);
4781			}
4782		}
4783
4784		/* bind DMA buffer */
4785		rc = ddi_dma_addr_bind_handle(port->samp_dmah, NULL,
4786		    port->samp_kaddr, real_size, dir,
4787		    DDI_DMA_SLEEP, NULL, &cookie, &count);
4788		if ((rc != DDI_DMA_MAPPED) || (count != 1)) {
4789			audio_dev_warn(adev,
4790			    "ddi_dma_addr_bind_handle failed: %d", rc);
4791			return (DDI_FAILURE);
4792		}
4793		port->samp_paddr = (uint64_t)cookie.dmac_laddress;
4794
4795		/*
4796		 * now, from here we allocate DMA
4797		 * memory for buffer descriptor list.
4798		 * we allocate adjacent DMA memory for all DMA engines.
4799		 */
4800		rc = ddi_dma_alloc_handle(dip, &dma_attr, DDI_DMA_SLEEP,
4801		    NULL, &port->bdl_dmah);
4802		if (rc != DDI_SUCCESS) {
4803			audio_dev_warn(adev,
4804			    "ddi_dma_alloc_handle(bdlist) failed");
4805			return (DDI_FAILURE);
4806		}
4807
4808		/*
4809		 * we allocate all buffer descriptors lists in continuous
4810		 * dma memory.
4811		 */
4812		port->bdl_size = sizeof (sd_bdle_t) * AUDIOHD_BDLE_NUMS;
4813		rc = ddi_dma_mem_alloc(port->bdl_dmah, port->bdl_size,
4814		    &hda_dev_accattr, DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, NULL,
4815		    &port->bdl_kaddr, &real_size, &port->bdl_acch);
4816		if (rc != DDI_SUCCESS) {
4817			audio_dev_warn(adev,
4818			    "ddi_dma_mem_alloc(bdlist) failed");
4819			return (DDI_FAILURE);
4820		}
4821
4822		rc = ddi_dma_addr_bind_handle(port->bdl_dmah, NULL,
4823		    port->bdl_kaddr,
4824		    real_size, DDI_DMA_WRITE | DDI_DMA_CONSISTENT,
4825		    DDI_DMA_SLEEP,
4826		    NULL, &cookie, &count);
4827		if ((rc != DDI_DMA_MAPPED) || (count != 1)) {
4828			audio_dev_warn(adev, "addr_bind_handle failed");
4829			return (DDI_FAILURE);
4830		}
4831		port->bdl_paddr = (uint64_t)cookie.dmac_laddress;
4832
4833		entry = (sd_bdle_t *)port->bdl_kaddr;
4834		buf_phys_addr = port->samp_paddr;
4835
4836		for (j = 0; j < AUDIOHD_BDLE_NUMS; j++) {
4837			entry->sbde_addr = buf_phys_addr;
4838			entry->sbde_len = port->fragsize;
4839			entry->sbde_ioc = 1;
4840			buf_phys_addr += port->fragsize;
4841			entry++;
4842		}
4843		(void) ddi_dma_sync(port->bdl_dmah, 0, sizeof (sd_bdle_t) *
4844		    AUDIOHD_BDLE_NUMS, DDI_DMA_SYNC_FORDEV);
4845		port->curpos = 0;
4846
4847		port->engine = audio_engine_alloc(&audiohd_engine_ops, caps);
4848		if (port->engine == NULL) {
4849			return (DDI_FAILURE);
4850		}
4851
4852		audio_engine_set_private(port->engine, port);
4853		audio_dev_add_engine(adev, port->engine);
4854	}
4855
4856	return (DDI_SUCCESS);
4857}
4858
4859static void
4860audiohd_free_port(audiohd_state_t *statep)
4861{
4862	int			i;
4863	audiohd_port_t		*port;
4864
4865	for (i = 0; i < PORT_MAX; i++) {
4866		port = statep->port[i];
4867		if (port == NULL)
4868			continue;
4869		if (port->engine) {
4870			audio_dev_remove_engine(statep->adev,
4871			    port->engine);
4872			audio_engine_free(port->engine);
4873		}
4874		if (port->samp_dmah) {
4875			(void) ddi_dma_unbind_handle(port->samp_dmah);
4876		}
4877		if (port->samp_acch) {
4878			ddi_dma_mem_free(&port->samp_acch);
4879		}
4880		if (port->samp_dmah) {
4881			ddi_dma_free_handle(&port->samp_dmah);
4882		}
4883		if (port->bdl_dmah) {
4884			(void) ddi_dma_unbind_handle(port->bdl_dmah);
4885		}
4886		if (port->bdl_acch) {
4887			ddi_dma_mem_free(&port->bdl_acch);
4888		}
4889		if (port->bdl_dmah) {
4890			ddi_dma_free_handle(&port->bdl_dmah);
4891		}
4892
4893		kmem_free(port, sizeof (audiohd_port_t));
4894	}
4895}
4896
4897/*
4898 * audiohd_change_widget_power_state(audiohd_state_t *statep, int state)
4899 * Description:
4900 * 	This routine is used to change the widget power betwen D0 and D2.
4901 * 	D0 is fully on; D2 allows the lowest possible power consuming state
4902 * 	from which it can return to the fully on state: D0.
4903 */
4904static void
4905audiohd_change_widget_power_state(audiohd_state_t *statep, int state)
4906{
4907	int			i;
4908	wid_t			wid;
4909	hda_codec_t		*codec;
4910	audiohd_widget_t	*widget;
4911
4912	for (i = 0; i < AUDIOHD_CODEC_MAX; i++) {
4913		codec = statep->codec[i];
4914		if (codec == NULL)
4915			continue;
4916		for (wid = codec->first_wid; wid <= codec->last_wid;
4917		    wid++) {
4918			widget = codec->widget[wid];
4919			if (widget->widget_cap &
4920			    AUDIOHD_WIDCAP_PWRCTRL) {
4921				(void) audioha_codec_verb_get(statep,
4922				    codec->index, wid,
4923				    AUDIOHDC_VERB_SET_POWER_STATE,
4924				    state);
4925			}
4926		}
4927	}
4928}
4929/*
4930 * audiohd_restore_path()
4931 * Description:
4932 * 	This routine is used to restore the path on the codec.
4933 */
4934static void
4935audiohd_restore_path(audiohd_state_t *statep)
4936{
4937	int			i;
4938	hda_codec_t		*codec;
4939
4940	for (i = 0; i < AUDIOHD_CODEC_MAX; i++) {
4941		codec = statep->codec[i];
4942		if (codec == NULL)
4943			continue;
4944		audiohd_finish_output_path(statep->codec[i]);
4945		audiohd_finish_input_path(statep->codec[i]);
4946		audiohd_finish_monitor_path(statep->codec[i]);
4947	}
4948}
4949
4950/*
4951 * audiohd_reset_pins_ur_cap()
4952 * Description:
4953 * 	Enable the unsolicited response of the pins which have the unsolicited
4954 * 	response capability
4955 */
4956static void
4957audiohd_reset_pins_ur_cap(audiohd_state_t *statep)
4958{
4959	hda_codec_t		*codec;
4960	audiohd_pin_t		*pin;
4961	audiohd_widget_t	*widget;
4962	uint32_t		urctrl;
4963	int			i;
4964
4965	for (i = 0; i < AUDIOHD_CODEC_MAX; i++) {
4966		codec = statep->codec[i];
4967		if (codec == NULL)
4968			continue;
4969		pin = codec->first_pin;
4970		while (pin) {
4971			/* enable the unsolicited response of the pin */
4972			widget = codec->widget[pin->wid];
4973			if ((widget->widget_cap &
4974			    (AUDIOHD_URCAP_MASK) &&
4975			    (pin->cap & AUDIOHD_DTCCAP_MASK)) &&
4976			    ((pin->device == DTYPE_LINEOUT) ||
4977			    (pin->device == DTYPE_SPDIF_OUT) ||
4978			    (pin->device == DTYPE_HP_OUT) ||
4979			    (pin->device == DTYPE_MIC_IN))) {
4980				urctrl = (uint8_t)(1 <<
4981				    (AUDIOHD_UR_ENABLE_OFF - 1));
4982				urctrl |= (pin->wid & AUDIOHD_UR_TAG_MASK);
4983				(void) audioha_codec_verb_get(statep,
4984				    codec->index,
4985				    pin->wid,
4986				    AUDIOHDC_VERB_SET_UNS_ENABLE, urctrl);
4987			}
4988			pin = pin->next;
4989		}
4990	}
4991}
4992static void
4993audiohd_restore_codec_gpio(audiohd_state_t *statep)
4994{
4995	int		i;
4996	wid_t		wid;
4997	hda_codec_t	*codec;
4998
4999	for (i = 0; i < AUDIOHD_CODEC_MAX; i++) {
5000		codec = statep->codec[i];
5001		if (codec == NULL)
5002			continue;
5003		wid = codec->wid_afg;
5004
5005		/* power-up audio function group */
5006		(void) audioha_codec_verb_get(statep, i, wid,
5007		    AUDIOHDC_VERB_SET_POWER_STATE, AUDIOHD_PW_D0);
5008
5009		/* work around for Sony VAIO laptop with specific codec */
5010		if ((codec->codec_info->flags & NO_GPIO) == 0) {
5011			/*
5012			 * GPIO controls which are laptop specific workarounds
5013			 * and might be changed. Some laptops use GPIO,
5014			 * so we need to enable and set the GPIO correctly.
5015			 */
5016			(void) audioha_codec_verb_get(statep, i, wid,
5017			    AUDIOHDC_VERB_SET_GPIO_MASK, AUDIOHDC_GPIO_ENABLE);
5018			(void) audioha_codec_verb_get(statep, i, wid,
5019			    AUDIOHDC_VERB_SET_GPIO_DIREC, AUDIOHDC_GPIO_DIRECT);
5020			(void) audioha_codec_verb_get(statep, i, wid,
5021			    AUDIOHDC_VERB_SET_GPIO_STCK,
5022			    AUDIOHDC_GPIO_DATA_CTRL);
5023			(void) audioha_codec_verb_get(statep, i, wid,
5024			    AUDIOHDC_VERB_SET_GPIO_DATA,
5025			    AUDIOHDC_GPIO_STCK_CTRL);
5026		}
5027	}
5028}
5029/*
5030 * audiohd_resume()
5031 */
5032static int
5033audiohd_resume(audiohd_state_t *statep)
5034{
5035	uint8_t		rirbsts;
5036
5037	mutex_enter(&statep->hda_mutex);
5038	statep->suspended = B_FALSE;
5039	/* Restore the hda state */
5040	if (audiohd_reinit_hda(statep) == DDI_FAILURE) {
5041		audio_dev_warn(statep->adev,
5042		    "hda reinit failed");
5043		mutex_exit(&statep->hda_mutex);
5044		return (DDI_FAILURE);
5045	}
5046	/* reset to enable the capability of unsolicited response for pin */
5047	audiohd_reset_pins_ur_cap(statep);
5048	/* clear the unsolicited response interrupt */
5049	rirbsts = AUDIOHD_REG_GET8(AUDIOHD_REG_RIRBSTS);
5050	AUDIOHD_REG_SET8(AUDIOHD_REG_RIRBSTS, rirbsts);
5051	/* set widget power to D0 */
5052	audiohd_change_widget_power_state(statep, AUDIOHD_PW_D0);
5053
5054	audiohd_configure_output(statep);
5055	audiohd_configure_input(statep);
5056	mutex_exit(&statep->hda_mutex);
5057
5058	audio_dev_resume(statep->adev);
5059
5060	return (DDI_SUCCESS);
5061}	/* audiohd_resume */
5062
5063/*
5064 * audiohd_suspend()
5065 */
5066static int
5067audiohd_suspend(audiohd_state_t *statep)
5068{
5069	audio_dev_suspend(statep->adev);
5070
5071	mutex_enter(&statep->hda_mutex);
5072	statep->suspended = B_TRUE;
5073
5074	/* set widget power to D2 */
5075	audiohd_change_widget_power_state(statep, AUDIOHD_PW_D2);
5076	/* Disable h/w */
5077	audiohd_stop_dma(statep);
5078	audiohd_fini_pci(statep);
5079	mutex_exit(&statep->hda_mutex);
5080
5081	return (DDI_SUCCESS);
5082}	/* audiohd_suspend */
5083
5084/*
5085 * audiohd_disable_pin()
5086 */
5087static void
5088audiohd_disable_pin(audiohd_state_t *statep, int caddr, wid_t wid)
5089{
5090	uint32_t	tmp;
5091
5092	tmp = audioha_codec_verb_get(statep, caddr, wid,
5093	    AUDIOHDC_VERB_GET_PIN_CTRL, 0);
5094	if (tmp == AUDIOHD_CODEC_FAILURE)
5095		return;
5096	tmp = audioha_codec_verb_get(statep, caddr, wid,
5097	    AUDIOHDC_VERB_SET_PIN_CTRL,
5098	    (tmp & ~AUDIOHDC_PIN_CONTROL_OUT_ENABLE));
5099}
5100
5101/*
5102 * audiohd_enable_pin()
5103 */
5104static void
5105audiohd_enable_pin(audiohd_state_t *statep, int caddr, wid_t wid)
5106{
5107	uint32_t	tmp;
5108
5109	tmp = audioha_codec_verb_get(statep, caddr, wid,
5110	    AUDIOHDC_VERB_GET_PIN_CTRL, 0);
5111	if (tmp == AUDIOHD_CODEC_FAILURE)
5112		return;
5113	tmp = audioha_codec_verb_get(statep, caddr, wid,
5114	    AUDIOHDC_VERB_SET_PIN_CTRL,
5115	    tmp | AUDIOHDC_PIN_CONTROL_OUT_ENABLE |
5116	    AUDIOHDC_PIN_CONTROL_HP_ENABLE);
5117}
5118
5119/*
5120 * audiohd_change_speaker_state()
5121 */
5122static void
5123audiohd_change_speaker_state(audiohd_state_t *statep, int on)
5124{
5125	audiohd_path_t		*path;
5126	audiohd_widget_t	*widget;
5127	audiohd_pin_t		*pin;
5128	int			i, j;
5129	wid_t			wid;
5130
5131	for (i = 0; i < statep->pathnum; i++) {
5132		path = statep->path[i];
5133		if (!path || path->path_type != PLAY)
5134			continue;
5135		if (on) {
5136			for (j = 0; j < path->pin_nums; j++) {
5137				wid = path->pin_wid[j];
5138				widget = path->codec->widget[wid];
5139				pin = (audiohd_pin_t *)widget->priv;
5140				if (pin->device == DTYPE_SPEAKER) {
5141					audiohd_enable_pin(statep,
5142					    path->codec->index,
5143					    pin->wid);
5144				}
5145			}
5146
5147		} else {
5148			for (j = 0; j < path->pin_nums; j++) {
5149				wid = path->pin_wid[j];
5150				widget = path->codec->widget[wid];
5151				pin = (audiohd_pin_t *)widget->priv;
5152				if (pin->device == DTYPE_SPEAKER) {
5153					audiohd_disable_pin(statep,
5154					    path->codec->index,
5155					    pin->wid);
5156				}
5157			}
5158		}
5159	}
5160}
5161/*
5162 * audiohd_select_mic()
5163 *
5164 * Description:
5165 *	This function is used for the recording path which has a selector
5166 *	as the sumwidget. We select the external MIC if it is plugged into the
5167 *	MIC jack, otherwise the internal integrated MIC is selected.
5168 */
5169static void
5170audiohd_select_mic(audiohd_state_t *statep, uint8_t index,
5171uint8_t id, int select)
5172{
5173	hda_codec_t		*codec;
5174	audiohd_path_t		*path;
5175	audiohd_widget_t	*widget, *sumwgt;
5176	audiohd_pin_t		*pin;
5177	int			i, j;
5178	wid_t			wid;
5179
5180	codec = statep->codec[index];
5181	if (codec == NULL)
5182		return;
5183	for (i = 0; i < statep->pathnum; i++) {
5184		path = statep->path[i];
5185		if (path->codec != codec || path->path_type != RECORD)
5186			continue;
5187		sumwgt = codec->widget[path->sum_wid];
5188		if (path && sumwgt &&
5189		    (sumwgt->type == WTYPE_AUDIO_SEL)) {
5190			for (j = 0; j < path->pin_nums; j++) {
5191				wid = path->pin_wid[j];
5192				widget = codec->widget[wid];
5193				if (widget == NULL)
5194					return;
5195				pin = (audiohd_pin_t *)widget->priv;
5196				if (select &&
5197				    pin->device == DTYPE_MIC_IN &&
5198				    pin->wid == id &&
5199				    (((pin->config >>
5200				    AUDIOHD_PIN_CONTP_OFF) &
5201				    AUDIOHD_PIN_CONTP_MASK) ==
5202				    AUDIOHD_PIN_CON_JACK)) {
5203					(void) audioha_codec_verb_get(
5204					    statep,
5205					    index,
5206					    path->sum_wid,
5207					    AUDIOHDC_VERB_SET_CONN_SEL,
5208					    path->sum_selconn[j]);
5209					statep->port[PORT_ADC]->index =
5210					    path->tag;
5211					return;
5212				} else if (!select &&
5213				    pin->device == DTYPE_MIC_IN &&
5214				    pin->wid == id &&
5215				    (((pin->config >>
5216				    AUDIOHD_PIN_CONTP_OFF) &
5217				    AUDIOHD_PIN_CONTP_MASK) ==
5218				    AUDIOHD_PIN_CON_JACK)) {
5219					(void) audioha_codec_verb_get(
5220					    statep,
5221					    index,
5222					    path->sum_wid,
5223					    AUDIOHDC_VERB_SET_CONN_SEL,
5224					    path->sum_selconn[j]);
5225					statep->port[PORT_ADC]->index =
5226					    path->tag;
5227					return;
5228				}
5229			}
5230			if (path == NULL)
5231				break;
5232			sumwgt = codec->widget[path->sum_wid];
5233		}
5234	}
5235	/*
5236	 * If the input istream > 1, we should set the record stream tag
5237	 * respectively. All the input streams sharing one tag may make the
5238	 * record sound distorted.
5239	 */
5240	if (codec->nistream > 1) {
5241		for (i = 0; i < statep->pathnum; i++) {
5242			path = statep->path[i];
5243			if (!path || path->path_type != RECORD)
5244				continue;
5245			for (j = 0; j < path->pin_nums; j++) {
5246				wid = path->pin_wid[j];
5247				widget = codec->widget[wid];
5248				if (widget == NULL)
5249					return;
5250				pin = (audiohd_pin_t *)widget->priv;
5251				if (select &&
5252				    pin->device == DTYPE_MIC_IN &&
5253				    pin->wid == id &&
5254				    (((pin->config >>
5255				    AUDIOHD_PIN_CONTP_OFF) &
5256				    AUDIOHD_PIN_CONTP_MASK) ==
5257				    AUDIOHD_PIN_CON_JACK)) {
5258					statep->port[PORT_ADC]->index =
5259					    path->tag;
5260					return;
5261				} else if (!select &&
5262				    pin->device == DTYPE_MIC_IN &&
5263				    (((pin->config >>
5264				    AUDIOHD_PIN_CONTP_OFF) &
5265				    AUDIOHD_PIN_CONTP_MASK) ==
5266				    AUDIOHD_PIN_CON_FIXED)) {
5267					statep->port[PORT_ADC]->index =
5268					    path->tag;
5269					return;
5270				}
5271			}
5272		}
5273	}
5274}
5275/*
5276 * audiohd_pin_sense()
5277 *
5278 * Description
5279 *
5280 * 	When the earphone is plugged into the jack associtated with the pin
5281 * 	complex, we disable the built in speaker. When the earphone is plugged
5282 * 	out of the jack, we enable the built in speaker.
5283 */
5284static void
5285audiohd_pin_sense(audiohd_state_t *statep, uint32_t resp, uint32_t respex)
5286{
5287	uint8_t			index;
5288	uint8_t			id;
5289	uint32_t		rs;
5290	audiohd_widget_t	*widget;
5291	audiohd_pin_t		*pin;
5292	hda_codec_t		*codec;
5293
5294	index = respex & AUDIOHD_RIRB_CODEC_MASK;
5295	id = resp >> (AUDIOHD_RIRB_WID_OFF - 1);
5296
5297	codec = statep->codec[index];
5298	if (codec == NULL)
5299		return;
5300	widget = codec->widget[id];
5301	if (widget == NULL)
5302		return;
5303
5304	rs = audioha_codec_verb_get(statep, index, id,
5305	    AUDIOHDC_VERB_GET_PIN_SENSE, 0);
5306	if (rs & AUDIOHD_PIN_PRES_MASK) {
5307		/* A MIC is plugged in, we select the MIC as input */
5308		if ((widget->type == WTYPE_PIN) &&
5309		    (pin = (audiohd_pin_t *)widget->priv) &&
5310		    (pin->device == DTYPE_MIC_IN)) {
5311			audiohd_select_mic(statep, index, id, 1);
5312			return;
5313		}
5314		/* output pin is plugged */
5315		audiohd_change_speaker_state(statep, AUDIOHD_SP_OFF);
5316	} else {
5317		/*
5318		 * A MIC is unplugged, we select the built in MIC
5319		 * as input.
5320		 */
5321		if ((widget->type == WTYPE_PIN) &&
5322		    (pin = (audiohd_pin_t *)widget->priv) &&
5323		    (pin->device == DTYPE_MIC_IN)) {
5324			audiohd_select_mic(statep, index, id, 0);
5325			return;
5326		}
5327		/* output pin is unplugged */
5328		audiohd_change_speaker_state(statep, AUDIOHD_SP_ON);
5329	}
5330
5331}
5332
5333/*
5334 * audiohd_disable_intr()
5335 *
5336 * Description:
5337 *	Disable all possible interrupts.
5338 */
5339static void
5340audiohd_disable_intr(audiohd_state_t *statep)
5341{
5342	int		i;
5343	uint32_t	base;
5344
5345	AUDIOHD_REG_SET32(AUDIOHD_REG_INTCTL, 0);
5346	base = AUDIOHD_REG_SD_BASE;
5347	for (i = 0; i < statep->hda_streams_nums; i++) {
5348		AUDIOHD_REG_SET8(base + AUDIOHD_SDREG_OFFSET_STS,
5349		    AUDIOHDR_SD_STS_INTRS);
5350		base += AUDIOHD_REG_SD_LEN;
5351	}
5352	AUDIOHD_REG_SET32(AUDIOHD_REG_INTSTS, (uint32_t)(-1));
5353
5354}	/* audiohd_disable_intr() */
5355
5356
5357/*
5358 * audiohd_12bit_verb_to_codec()
5359 *
5360 * Description:
5361 *
5362 */
5363static int
5364audiohd_12bit_verb_to_codec(audiohd_state_t *statep, uint8_t caddr,
5365    uint8_t wid,
5366    uint16_t cmd, uint8_t param)
5367{
5368	uint32_t	verb;
5369	uint16_t	wptr;
5370	uint16_t	rptr;
5371
5372	ASSERT((cmd & AUDIOHDC_12BIT_VERB_MASK) == 0);
5373
5374	wptr = AUDIOHD_REG_GET16(AUDIOHD_REG_CORBWP) & AUDIOHD_CMDIO_ENT_MASK;
5375	rptr = AUDIOHD_REG_GET16(AUDIOHD_REG_CORBRP) & AUDIOHD_CMDIO_ENT_MASK;
5376
5377	wptr++;
5378	wptr &= AUDIOHD_CMDIO_ENT_MASK;
5379
5380	/* overflow */
5381	if (wptr == rptr) {
5382		return (DDI_FAILURE);
5383	}
5384
5385	verb = (caddr & 0x0f) << AUDIOHD_VERB_ADDR_OFF;
5386	verb |= wid << AUDIOHD_VERB_NID_OFF;
5387	verb |= cmd << AUDIOHD_VERB_CMD_OFF;
5388	verb |= param;
5389
5390	*((uint32_t *)(statep->hda_dma_corb.ad_vaddr) + wptr) = verb;
5391	(void) ddi_dma_sync(statep->hda_dma_corb.ad_dmahdl, 0,
5392	    sizeof (sd_bdle_t) * AUDIOHD_BDLE_NUMS, DDI_DMA_SYNC_FORDEV);
5393	AUDIOHD_REG_SET16(AUDIOHD_REG_CORBWP, wptr);
5394
5395	return (DDI_SUCCESS);
5396
5397}	/* audiohd_12bit_verb_to_codec() */
5398
5399/*
5400 * audiohd_4bit_verb_to_codec()
5401 *
5402 * Description:
5403 *
5404 */
5405static int
5406audiohd_4bit_verb_to_codec(audiohd_state_t *statep, uint8_t caddr,
5407    uint8_t wid,
5408    uint32_t cmd, uint16_t param)
5409{
5410	uint32_t	verb;
5411	uint16_t	wptr;
5412	uint16_t	rptr;
5413
5414	ASSERT((cmd & AUDIOHDC_4BIT_VERB_MASK) == 0);
5415
5416	wptr = AUDIOHD_REG_GET16(AUDIOHD_REG_CORBWP) & AUDIOHD_CMDIO_ENT_MASK;
5417	rptr = AUDIOHD_REG_GET16(AUDIOHD_REG_CORBRP) & AUDIOHD_CMDIO_ENT_MASK;
5418
5419	wptr++;
5420	wptr &= AUDIOHD_CMDIO_ENT_MASK;
5421
5422	/* overflow */
5423	if (wptr == rptr) {
5424		return (DDI_FAILURE);
5425	}
5426
5427	verb = (caddr & 0x0f) << AUDIOHD_VERB_ADDR_OFF;
5428	verb |= wid << AUDIOHD_VERB_NID_OFF;
5429	verb |= cmd << AUDIOHD_VERB_CMD16_OFF;
5430	verb |= param;
5431
5432	*((uint32_t *)(statep->hda_dma_corb.ad_vaddr) + wptr) = verb;
5433	AUDIOHD_REG_SET16(AUDIOHD_REG_CORBWP, wptr);
5434
5435	return (DDI_SUCCESS);
5436
5437}	/* audiohd_4bit_verb_to_codec() */
5438
5439/*
5440 * audiohd_response_from_codec()
5441 *
5442 * Description:
5443 *
5444 */
5445static int
5446audiohd_response_from_codec(audiohd_state_t *statep, uint32_t *resp,
5447    uint32_t *respex)
5448{
5449	uint16_t	wptr;
5450	uint16_t	rptr;
5451	uint32_t	*lp;
5452
5453	wptr = AUDIOHD_REG_GET16(AUDIOHD_REG_RIRBWP) & 0x00ff;
5454	rptr = statep->hda_rirb_rp;
5455
5456	if (rptr == wptr) {
5457		return (DDI_FAILURE);
5458	}
5459
5460	rptr++;
5461	rptr &= AUDIOHD_RING_MAX_SIZE;
5462
5463	lp = (uint32_t *)(statep->hda_dma_rirb.ad_vaddr) + (rptr << 1);
5464	*resp = *(lp);
5465	*respex = *(lp + 1);
5466
5467	statep->hda_rirb_rp = rptr;
5468
5469	return (DDI_SUCCESS);
5470
5471}	/* audiohd_response_from_codec() */
5472
5473
5474/*
5475 * audioha_codec_verb_get()
5476 */
5477static uint32_t
5478audioha_codec_verb_get(void *arg, uint8_t caddr, uint8_t wid,
5479    uint16_t verb,
5480    uint8_t param)
5481{
5482	audiohd_state_t	*statep = (audiohd_state_t *)arg;
5483	uint32_t	resp;
5484	uint32_t	respex;
5485	int		ret;
5486	int		i;
5487
5488	ret = audiohd_12bit_verb_to_codec(statep, caddr, wid, verb, param);
5489	if (ret != DDI_SUCCESS) {
5490		return (uint32_t)(-1);
5491	}
5492
5493	/*
5494	 * Empirical testing times. 50 times is enough for audiohd spec 1.0.
5495	 * But we need to make it work for audiohd spec 0.9, which is just a
5496	 * draft version and requires more time to wait.
5497	 */
5498	for (i = 0; i < 500; i++) {
5499		ret = audiohd_response_from_codec(statep, &resp, &respex);
5500		if (((respex & AUDIOHD_BDLE_RIRB_SDI) == caddr) &&
5501		    ((respex & AUDIOHD_BDLE_RIRB_UNSOLICIT) == 0) &&
5502		    (ret == DDI_SUCCESS))
5503			break;
5504		/* Empirical testing time, which works well */
5505		drv_usecwait(30);
5506	}
5507
5508	if (ret == DDI_SUCCESS) {
5509		return (resp);
5510	}
5511
5512	if (wid != AUDIOHDC_NODE_ROOT && param != AUDIOHDC_PAR_VENDOR_ID) {
5513		audio_dev_warn(statep->adev,  "timeout when get "
5514		    "response from codec: wid=%d, verb=0x%04x, param=0x%04x",
5515		    wid, verb, param);
5516	}
5517
5518	return ((uint32_t)(-1));
5519
5520}	/* audioha_codec_verb_get() */
5521
5522
5523/*
5524 * audioha_codec_4bit_verb_get()
5525 */
5526static uint32_t
5527audioha_codec_4bit_verb_get(void *arg, uint8_t caddr, uint8_t wid,
5528    uint16_t verb, uint16_t param)
5529{
5530	audiohd_state_t	*statep = (audiohd_state_t *)arg;
5531	uint32_t	resp;
5532	uint32_t	respex;
5533	int		ret;
5534	int		i;
5535
5536	ret = audiohd_4bit_verb_to_codec(statep, caddr, wid, verb, param);
5537	if (ret != DDI_SUCCESS) {
5538		return (uint32_t)(-1);
5539	}
5540
5541	for (i = 0; i < 500; i++) {
5542		ret = audiohd_response_from_codec(statep, &resp, &respex);
5543		if (((respex & AUDIOHD_BDLE_RIRB_SDI) == caddr) &&
5544		    ((respex & AUDIOHD_BDLE_RIRB_UNSOLICIT) == 0) &&
5545		    (ret == DDI_SUCCESS))
5546			break;
5547		/* Empirical testing time, which works well */
5548		drv_usecwait(30);
5549	}
5550
5551	if (ret == DDI_SUCCESS) {
5552		return (resp);
5553	}
5554
5555	audio_dev_warn(statep->adev,  "timeout when get "
5556	    "response from codec: wid=%d, verb=0x%04x, param=0x%04x",
5557	    wid, verb, param);
5558
5559	return ((uint32_t)(-1));
5560
5561}	/* audioha_codec_4bit_verb_get() */
5562