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