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