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