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