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