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