changeset 3160:8234795d0b5f

PSARC 2006/648 Sony VAIO Audio Amp Invert 6365200 audio810 attaches on VAIO laptops, but hardware stays silent 6433485 audiohd should support stac9200 codec for Toshiba Tecra M5 6450140 audiohd should support ALC260/262 codecs 6494395 audiohd should support ALC88x codec
author cg149915
date Wed, 22 Nov 2006 18:59:14 -0800
parents 2750b6a8d8c0
children 187c511fc2bf
files usr/src/uts/common/io/audio/sada/drv/audio810/audio810.c usr/src/uts/common/io/audio/sada/drv/audio810/audio810.conf usr/src/uts/common/io/audio/sada/drv/audiohd/audiohd.c usr/src/uts/common/sys/audio/impl/audiohd_impl.h
diffstat 4 files changed, 1068 insertions(+), 226 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/uts/common/io/audio/sada/drv/audio810/audio810.c	Wed Nov 22 13:57:56 2006 -0800
+++ b/usr/src/uts/common/io/audio/sada/drv/audio810/audio810.c	Wed Nov 22 18:59:14 2006 -0800
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -2220,6 +2219,49 @@
 		    TDCR_NULL;
 
 		/*
+		 * 26h - set EAPD to 1 for devices with ac97-invert-amp
+		 * property.
+		 *
+		 * According to AC'97 spec, EAPD (PR7) independently controls
+		 * an output pin that manages an optional external audio
+		 * amplifier. AC'97 compliance requires the implementation of
+		 * a dedicated output pin for external audio amplifier control.
+		 * The pin is controlled via the ¡°EAPD¡±(External Amplifier
+		 * Powerdown) bit in Powerdown Ctrl/Stat Register, bit 15
+		 * (formerly PR7). EAPD = 0 places a 0 on the output pin,
+		 * enabling an external audio amplifier, EAPD = 1 shuts it
+		 * down. Audio amplifier devices that operate with reverse
+		 * polarity may require an external inverter. By default,
+		 * EAPD = 0 is to enable external audio amplifier, but for
+		 * some Sony Vaio laptops, we need to revert polarity to
+		 * enable external amplifier.
+		 */
+		switch (ddi_prop_get_int(DDI_DEV_T_ANY, statep->dip,
+		    DDI_PROP_DONTPASS, "ac97-invert-amp", -1)) {
+		case -1:
+			/* not attempt to flip EAPD */
+			break;
+
+		case 0:
+			/* set EAPD to 0 */
+			shadow[I810_CODEC_REG(
+			    AC97_POWERDOWN_CTRL_STAT_REGISTER)] &= ~PCSR_EAPD;
+			break;
+
+		case 1:
+			/* set EAPD to 1 */
+			shadow[I810_CODEC_REG(
+			    AC97_POWERDOWN_CTRL_STAT_REGISTER)] |= PCSR_EAPD;
+			break;
+
+		default:
+			/* invalid */
+			audio_sup_log(statep->audio_handle, CE_WARN,
+			    "!Invalid value for ac97-invert-amp property");
+			break;
+		}
+
+		/*
 		 * The rest we ignore, most are reserved.
 		 */
 
--- a/usr/src/uts/common/io/audio/sada/drv/audio810/audio810.conf	Wed Nov 22 13:57:56 2006 -0800
+++ b/usr/src/uts/common/io/audio/sada/drv/audio810/audio810.conf	Wed Nov 22 18:59:14 2006 -0800
@@ -2,9 +2,8 @@
 # CDDL HEADER START
 #
 # The contents of this file are subject to the terms of the
-# Common Development and Distribution License, Version 1.0 only
-# (the "License").  You may not use this file except in compliance
-# with the License.
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
 #
 # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 # or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
 # CDDL HEADER END
 #
 #
-# Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
 # ident	"%Z%%M%	%I%	%E% SMI"
@@ -62,6 +61,14 @@
 #reset-configuration=1;
 
 #
-# We need change the priority so that we aren't high level interrupt.
+# We need change the priority so that we aren't a high level interrupt.
 #
 interrupt-priorities=9;
+
+#
+# Uncomment ac97-invert-amp to power down/up external amplifier. Most
+# hardware does't need this property. But some devices, such as some
+# Sony Vaio laptops need to set this property to 1 to correct the
+# inverted polarity of the external amplifier device.
+#
+# ac97-invert-amp=1;
--- a/usr/src/uts/common/io/audio/sada/drv/audiohd/audiohd.c	Wed Nov 22 13:57:56 2006 -0800
+++ b/usr/src/uts/common/io/audio/sada/drv/audiohd/audiohd.c	Wed Nov 22 18:59:14 2006 -0800
@@ -42,6 +42,9 @@
  * for playback. And because ALC880 doesn't support sample rates
  * below 48K (except 44.1K), this driver just supports 48K sample
  * rate in compatible mode.
+ *
+ * Currently, this driver only supports limit CODECs, such as Realtek
+ * ALC880/882/883/885/888, ALC260/262 and Sigmatel STAC9200(D).
  */
 #include <sys/types.h>
 #include <sys/modctl.h>
@@ -95,6 +98,7 @@
 static void audiohd_stop_dma(audiohd_state_t *);
 static void audiohd_disable_intr(audiohd_state_t *);
 static int audiohd_create_codec(audiohd_state_t *);
+static int audiohd_init_codec(audiohd_state_t *);
 static void audiohd_destroy_codec(audiohd_state_t *);
 static int audiohd_reset_stream(audiohd_state_t	*, int);
 static int audiohd_fill_pbuf(audiohd_state_t *);
@@ -114,10 +118,9 @@
     uint8_t, uint16_t, uint16_t);
 
 /*
- * operation routines for ALC88x codec
+ * operation routines for ALC260, ALC262 and ALC88x
  */
-static int audiohd_alc880_enable_play(audiohd_state_t *);
-static int audiohd_alc880_enable_record(audiohd_state_t *);
+static int audiohd_alc880_init_codec(audiohd_state_t *);
 static int audiohd_alc880_set_pcm_fmt(audiohd_state_t *, int, uint_t);
 static int audiohd_alc880_set_gain(audiohd_state_t *, int, int, int);
 static int audiohd_alc880_set_port(audiohd_state_t *, int, int);
@@ -126,16 +129,39 @@
 static void audiohd_alc880_max_gain(audiohd_state_t *, uint_t *,
     uint_t *, uint_t *);
 
-/* ops for ALC880 */
+/* ops for ALC260, ALC262 and ALC88x */
 static struct audiohd_codec_ops audiohd_alc880_ops = {
-	audiohd_alc880_enable_play,		/* ac_enable_play */
-	audiohd_alc880_enable_record,		/* ac_enable_record */
+	audiohd_alc880_init_codec,		/* ac_init_codec */
 	audiohd_alc880_set_pcm_fmt,		/* ac_set_pcm_fmt */
 	audiohd_alc880_set_gain,		/* ac_set_out_gain */
 	audiohd_alc880_set_port,		/* ac_set_port */
 	audiohd_alc880_mute_outputs,		/* ac_mute_outputs */
 	audiohd_alc880_set_monitor_gain,	/* ac_set_monitor_gain */
-	audiohd_alc880_max_gain		/* ac_get_max_gain */
+	audiohd_alc880_max_gain			/* ac_get_max_gain */
+};
+
+
+/*
+ * operation routines for STAC9200 codec
+ */
+static int audiohd_stac_init_codec(audiohd_state_t *);
+static int audiohd_stac_set_pcm_fmt(audiohd_state_t *, int, uint_t);
+static int audiohd_stac_set_gain(audiohd_state_t *, int, int, int);
+static int audiohd_stac_set_port(audiohd_state_t *, int, int);
+static int audiohd_stac_mute_outputs(audiohd_state_t *, boolean_t);
+static int audiohd_stac_set_monitor_gain(audiohd_state_t *, int);
+static void audiohd_stac_max_gain(audiohd_state_t *, uint_t *,
+    uint_t *, uint_t *);
+
+/* ops for STAC9200, STAC9200D */
+static struct audiohd_codec_ops audiohd_stac9200_ops = {
+	audiohd_stac_init_codec,		/* ac_init_codec */
+	audiohd_stac_set_pcm_fmt,		/* ac_set_pcm_fmt */
+	audiohd_stac_set_gain,			/* ac_set_out_gain */
+	audiohd_stac_set_port,			/* ac_set_port */
+	audiohd_stac_mute_outputs,		/* ac_mute_outputs */
+	audiohd_stac_set_monitor_gain,	/* ac_set_monitor_gain */
+	audiohd_stac_max_gain			/* ac_get_max_gain */
 };
 
 /* anchor for soft state structures */
@@ -464,6 +490,12 @@
 	AUDIOHD_CODEC_MAX_GAIN(statep, &statep->hda_pgain_max,
 	    &statep->hda_rgain_max, &statep->hda_mgain_max);
 
+	if (audiohd_init_codec(statep) != AUDIO_SUCCESS) {
+		audio_sup_log(statep->hda_ahandle, CE_WARN,
+		    "!audiohd_attach() counldn't init codec");
+		goto err_attach_exit7;
+	}
+
 	/*
 	 * This is a workaround. ALC880 doesn't support 8k sample rate,
 	 * but solaris requires hardware to be set to 8K by default. This
@@ -695,7 +727,7 @@
 	uint8_t		cTmp;
 	uint_t	regbase;
 
-	ATRACE_32("i810_ad_start_play() stream", stream);
+	ATRACE_32("audiohd_ad_start_play() stream", stream);
 	statep = audio_sup_get_private(ahandle);
 	ASSERT(statep);
 
@@ -731,6 +763,7 @@
 		    "!start_play() failed to get play sample");
 		statep->hda_flags &= ~AUDIOHD_PLAY_STARTED;
 		mutex_exit(&statep->hda_mutex);
+		am_play_shutdown(statep->hda_ahandle, NULL);
 		return (AUDIO_FAILURE);
 	}
 
@@ -751,8 +784,6 @@
 	    AUDIOHDR_SD_STS_BCIS | AUDIOHDR_SD_STS_FIFOE |
 	    AUDIOHDR_SD_STS_DESE);
 
-	AUDIOHD_CODEC_ENABLE_PLAY(statep);
-
 	/* set playback stream tag */
 	AUDIOHD_REG_SET8(regbase + AUDIOHD_SDREG_OFFSET_CTL + 2,
 	    (statep->hda_play_stag) << 4 | 4);
@@ -1008,7 +1039,6 @@
 
 	AUDIOHD_CODEC_SET_PCM_FORMAT(statep, AUDIO_RECORD,
 	    statep->hda_record_format);
-	AUDIOHD_CODEC_ENABLE_RECORD(statep);
 
 	/* set stream tag to 1 */
 	AUDIOHD_REG_SET8(regbase + AUDIOHD_SDREG_OFFSET_CTL + 2,
@@ -1114,12 +1144,6 @@
 	statep->hda_info_defaults.play.precision = AUDIOHD_DEFAULT_PREC;
 	statep->hda_info_defaults.play.encoding = AUDIOHD_DEFAULT_ENC;
 	statep->hda_info_defaults.play.gain = AUDIOHD_DEFAULT_PGAIN;
-	statep->hda_info_defaults.play.port =
-	    AUDIO_HEADPHONE | AUDIO_LINE_OUT;
-	statep->hda_info_defaults.play.avail_ports =
-	    AUDIO_HEADPHONE | AUDIO_LINE_OUT;
-	statep->hda_info_defaults.play.mod_ports =
-	    AUDIO_HEADPHONE | AUDIO_LINE_OUT;
 	statep->hda_info_defaults.play.buffer_size = AUDIOHD_BSIZE;
 	statep->hda_info_defaults.play.balance = AUDIOHD_DEFAULT_BAL;
 
@@ -1128,11 +1152,6 @@
 	statep->hda_info_defaults.record.precision = AUDIOHD_DEFAULT_PREC;
 	statep->hda_info_defaults.record.encoding = AUDIOHD_DEFAULT_ENC;
 	statep->hda_info_defaults.record.gain = AUDIOHD_DEFAULT_RGAIN;
-	statep->hda_info_defaults.record.port = AUDIO_MICROPHONE;
-	statep->hda_info_defaults.record.avail_ports =
-	    AUDIO_MICROPHONE | AUDIO_LINE_IN;
-	statep->hda_info_defaults.record.mod_ports =
-	    AUDIO_MICROPHONE | AUDIO_LINE_IN;
 	statep->hda_info_defaults.record.buffer_size = AUDIOHD_BSIZE;
 	statep->hda_info_defaults.record.balance = AUDIOHD_DEFAULT_BAL;
 
@@ -1160,8 +1179,6 @@
 	    statep->hda_info_defaults.record.precision;
 	statep->hda_record_format = AUDIOHD_FMT_PCMIN;
 
-	statep->hda_out_ports = AUDIO_HEADPHONE;
-	statep->hda_in_ports = AUDIO_MICROPHONE;
 
 	/*
 	 * fill in the ad_info structure
@@ -1258,7 +1275,7 @@
 	pci_config_put16(statep->hda_pci_handle, PCI_CONF_COMM,
 	    cmdreg | PCI_COMM_MAE | PCI_COMM_ME);
 
-	/* set TCSEL to TC1 */
+	/* set TCSEL to TC0 */
 	pci_config_put8(statep->hda_pci_handle, 0x44, 0);
 
 	return (AUDIO_SUCCESS);
@@ -1690,13 +1707,27 @@
 
 		switch (codec->hc_vid) {
 
+		case AUDIOHD_VID_ALC260:
+		case AUDIOHD_VID_ALC262:
 		case AUDIOHD_VID_ALC880:
+		case AUDIOHD_VID_ALC882:
 		case AUDIOHD_VID_ALC883:
 		case AUDIOHD_VID_ALC885:
+		case AUDIOHD_VID_ALC888:
 			codec->hc_ops = &audiohd_alc880_ops;
 			found = B_TRUE;
 			break;
 
+		case AUDIOHD_VID_STAC9200:
+		case AUDIOHD_VID_STAC9200D:
+			codec->hc_ops = &audiohd_stac9200_ops;
+			found = B_TRUE;
+			break;
+
+		case AUDIOHD_CODEC_FAILURE:
+			ATRACE_32("failed to get VID of codec", NULL);
+			break;
+
 		default:
 			audio_sup_log(statep->hda_ahandle, CE_WARN,
 			    "!unsupported HD codec: vid=0x%08x, rev=0x%08x",
@@ -1758,6 +1789,18 @@
 
 }	/* audiohd_destroy_codec() */
 
+/*
+ * audiohd_init_codec()
+ */
+static int
+audiohd_init_codec(audiohd_state_t *statep)
+{
+	int		ret;
+
+	ret = AUDIOHD_CODEC_INIT_CODEC(statep)
+
+	return (ret);
+}
 
 /*
  * audiohd_disable_intr()
@@ -2317,147 +2360,151 @@
 
 }	/* audioha_codec_4bit_verb_get() */
 
-
 /*
- * audiohd_alc880_enable_play()
+ * audiohd_alc880_init_codec()
+ *
+ * common routines for Realtek ALC260, ALC262, ALC88x
  */
 static int
-audiohd_alc880_enable_play(audiohd_state_t *statep)
+audiohd_alc880_init_codec(audiohd_state_t *statep)
 {
-	uint32_t	lTmp;
-	uint_t		output_val;
-	uint_t		input_val;
+	uint_t		val;
+	uint_t		inputs, outputs;
 	uint_t		caddr = statep->hda_codec->hc_addr;
 
-	lTmp = audioha_codec_verb_get(statep, caddr, AUDIOHDC_NID(0x02),
-	    AUDIOHDC_VERB_SET_STREAM_CHANN, statep->hda_play_stag << 4);
-	if (lTmp == AUDIOHD_CODEC_FAILURE)
-		return (AUDIO_FAILURE);
-
-	output_val = AUDIOHDC_AMP_SET_LR_OUTPUT | AUDIOHDC_GAIN_MAX;
-	input_val = AUDIOHDC_AMP_SET_LR_INPUT | AUDIOHDC_GAIN_MAX;
-
-	/* output amp of DAC */
-	lTmp = audioha_codec_4bit_verb_get(statep, caddr, AUDIOHDC_NID(0x02),
-	    AUDIOHDC_VERB_SET_AMP_MUTE, output_val);
-
-	if (lTmp == AUDIOHD_CODEC_FAILURE)
-		return (AUDIO_FAILURE);
-
-	/* unmute input for DAC2 of mixer */
-	lTmp = audioha_codec_4bit_verb_get(statep, caddr, AUDIOHDC_NID(0xc),
-	    AUDIOHDC_VERB_SET_AMP_MUTE, input_val);
-
-	if (lTmp == AUDIOHD_CODEC_FAILURE)
-		return (AUDIO_FAILURE);
-
-	/* output amp of mixer */
-	(void) audioha_codec_4bit_verb_get(statep, caddr, AUDIOHDC_NID(0xc),
-	    AUDIOHDC_VERB_SET_AMP_MUTE, AUDIOHDC_AMP_SET_OUTPUT |
-	    AUDIOHDC_AMP_SET_LEFT | statep->hda_play_lgain);
-
-	(void) audioha_codec_4bit_verb_get(statep, caddr, AUDIOHDC_NID(0xc),
-	    AUDIOHDC_VERB_SET_AMP_MUTE, AUDIOHDC_AMP_SET_OUTPUT |
-	    AUDIOHDC_AMP_SET_RIGHT | statep->hda_play_rgain);
-
-	/* Unmute pin */
-	if (!statep->hda_outputs_muted) {
-		lTmp = audioha_codec_4bit_verb_get(statep, caddr,
-		    AUDIOHDC_NID(0x14), AUDIOHDC_VERB_SET_AMP_MUTE, output_val);
-		if (lTmp == AUDIOHD_CODEC_FAILURE)
-			return (AUDIO_FAILURE);
-
-		lTmp = audioha_codec_4bit_verb_get(statep, caddr,
-		    AUDIOHDC_NID(0x1b), AUDIOHDC_VERB_SET_AMP_MUTE,
-			output_val);
-		if (lTmp == AUDIOHD_CODEC_FAILURE)
-			return (AUDIO_FAILURE);
-	}
-
-	/* enable output for pin node 0x14 */
-	lTmp = audioha_codec_verb_get(statep, caddr, AUDIOHDC_NID(0x14),
-	    AUDIOHDC_VERB_GET_PIN_CTRL, 0);
-	if (lTmp == AUDIOHD_CODEC_FAILURE)
+	ASSERT((statep->hda_codec->hc_vid == AUDIOHD_VID_ALC260) ||
+	    (statep->hda_codec->hc_vid == AUDIOHD_VID_ALC262) ||
+	    (statep->hda_codec->hc_vid == AUDIOHD_VID_ALC880) ||
+	    (statep->hda_codec->hc_vid == AUDIOHD_VID_ALC882) ||
+	    (statep->hda_codec->hc_vid == AUDIOHD_VID_ALC883) ||
+	    (statep->hda_codec->hc_vid == AUDIOHD_VID_ALC885) ||
+	    (statep->hda_codec->hc_vid == AUDIOHD_VID_ALC888));
+
+	outputs = 0;
+	switch (statep->hda_codec->hc_vid) {
+	case AUDIOHD_VID_ALC880:
+		AUDIOHD_NODE_INIT_DAC(statep, caddr, 4);
+		AUDIOHD_NODE_INIT_MIXER(statep, caddr, 0x0E, 0);
+		AUDIOHD_NODE_INIT_DAC(statep, caddr, 3);
+		AUDIOHD_NODE_INIT_MIXER(statep, caddr, 0x0D, 0);
+		/*FALLTHRU*/
+
+	case AUDIOHD_VID_ALC882:
+	case AUDIOHD_VID_ALC883:
+	case AUDIOHD_VID_ALC885:
+	case AUDIOHD_VID_ALC888:
+		/* AUDIO_AUX2_OUT */
+		outputs |= AUDIO_AUX2_OUT;
+		AUDIOHD_NODE_ENABLE_PIN_OUT(statep, caddr, 0x16);
+		if (!statep->hda_outputs_muted)
+			AUDIOHD_NODE_UNMUTE_OUT(statep, caddr, 0x16);
+		/*FALLTHRU*/
+
+	case AUDIOHD_VID_ALC262:
+		AUDIOHD_NODE_INIT_DAC(statep, caddr, 2);
+		AUDIOHD_NODE_INIT_MIXER(statep, caddr, 0x0C, 0);
+
+		/* AUDIO_HEADPHONE */
+		AUDIOHD_NODE_ENABLE_PIN_OUT(statep, caddr, 0x14);
+
+		/* AUDIO_AUX1_OUT */
+		AUDIOHD_NODE_ENABLE_PIN_OUT(statep, caddr, 0x15);
+
+		/* AUDIO_LINE_OUT */
+		AUDIOHD_NODE_ENABLE_PIN_OUT(statep, caddr, 0x1B);
+
+		if (!statep->hda_outputs_muted) {
+			AUDIOHD_NODE_UNMUTE_OUT(statep, caddr, 0x14);
+			AUDIOHD_NODE_UNMUTE_OUT(statep, caddr, 0x15);
+			AUDIOHD_NODE_UNMUTE_OUT(statep, caddr, 0x1B);
+		}
+
+		outputs |= AUDIO_HEADPHONE | AUDIO_LINE_OUT | AUDIO_AUX1_OUT;
+		break;
+
+	case AUDIOHD_VID_ALC260:
+		AUDIOHD_NODE_INIT_DAC(statep, caddr, 2);
+		AUDIOHD_NODE_INIT_MIXER(statep, caddr, 0x8, 0);
+		AUDIOHD_NODE_INIT_MIXER(statep, caddr, 0x9, 0);
+
+		if (!statep->hda_outputs_muted) {
+			AUDIOHD_NODE_UNMUTE_OUT(statep, caddr, 0x10);
+			AUDIOHD_NODE_UNMUTE_OUT(statep, caddr, 0x0f);
+		}
+
+		/* AUDIO_HEADPHONE */
+		AUDIOHD_NODE_ENABLE_PIN_OUT(statep, caddr, 0x10);
+
+		/* AUDIO_LINE_OUT */
+		AUDIOHD_NODE_ENABLE_PIN_OUT(statep, caddr, 0x0F);
+
+		outputs = AUDIO_HEADPHONE | AUDIO_LINE_OUT;
+		break;
+
+	default:
 		return (AUDIO_FAILURE);
-	lTmp = audioha_codec_verb_get(statep, caddr, AUDIOHDC_NID(0x14),
-	    AUDIOHDC_VERB_SET_PIN_CTRL, (lTmp |
-	    AUDIOHDC_PIN_CONTROL_OUT_ENABLE));
-	if (lTmp == AUDIOHD_CODEC_FAILURE)
-		return (AUDIO_FAILURE);
-
-	/* enable output for pin node 0x1b */
-	lTmp = audioha_codec_verb_get(statep, caddr, AUDIOHDC_NID(0x1b),
-	    AUDIOHDC_VERB_GET_PIN_CTRL, 0);
-	if (lTmp == AUDIOHD_CODEC_FAILURE)
-		return (AUDIO_FAILURE);
-	lTmp = audioha_codec_verb_get(statep, caddr, AUDIOHDC_NID(0x1b),
-	    AUDIOHDC_VERB_SET_PIN_CTRL, (lTmp |
-	    AUDIOHDC_PIN_CONTROL_OUT_ENABLE));
-	if (lTmp == AUDIOHD_CODEC_FAILURE)
-		return (AUDIO_FAILURE);
-
-	return (AUDIO_SUCCESS);
-
-}	/* audiohd_alc880_enable_play() */
-
-/*
- * audiohd_alc880_enable_record()
- */
-static int
-audiohd_alc880_enable_record(audiohd_state_t *statep)
-{
-	uint32_t	lTmp;
-	uint_t		val;
-	uint_t		caddr = statep->hda_codec->hc_addr;
-
-	/* for ADC node 0x9, set channel and stream tag */
-	lTmp = audioha_codec_verb_get(statep, caddr, AUDIOHDC_NID(0x09),
-	    AUDIOHDC_VERB_SET_STREAM_CHANN, statep->hda_record_stag << 4);
-	if (lTmp == AUDIOHD_CODEC_FAILURE)
-		return (AUDIO_FAILURE);
-
-	/* input amp of ADC node 0x9 */
-	val = AUDIOHDC_AMP_SET_LR_INPUT | AUDIOHDC_GAIN_MAX;
-	lTmp = audioha_codec_4bit_verb_get(statep, caddr, AUDIOHDC_NID(0x09),
-	    AUDIOHDC_VERB_SET_AMP_MUTE, val);
-	if (lTmp == AUDIOHD_CODEC_FAILURE)
-		return (AUDIO_FAILURE);
-
-	/* MIC1 */
-	(void) audioha_codec_verb_get(statep, caddr, AUDIOHDC_NID(0x18),
-	    AUDIOHDC_VERB_SET_PIN_CTRL, AUDIOHDC_PIN_CONTROL_IN_ENABLE | 4);
-
-	/* MIC 2 */
-	(void) audioha_codec_verb_get(statep, caddr, AUDIOHDC_NID(0x19),
-	    AUDIOHDC_VERB_SET_PIN_CTRL, AUDIOHDC_PIN_CONTROL_IN_ENABLE | 4);
-
-	/* line-in1 */
-	(void) audioha_codec_verb_get(statep, caddr, AUDIOHDC_NID(0x1a),
-	    AUDIOHDC_VERB_SET_PIN_CTRL, AUDIOHDC_PIN_CONTROL_IN_ENABLE | 4);
-
-	/* cd-in */
-	(void) audioha_codec_verb_get(statep, caddr, AUDIOHDC_NID(0x1c),
-	    AUDIOHDC_VERB_SET_PIN_CTRL, AUDIOHDC_PIN_CONTROL_IN_ENABLE | 4);
+	}
+
+	statep->hda_info_defaults.play.port = outputs;
+	statep->hda_info_defaults.play.avail_ports = outputs;
+	statep->hda_info_defaults.play.mod_ports = outputs;
+	statep->hda_out_ports = 0;
 
 	/*
-	 * enable gain for monitor path, from node 0x0B to node 0x0C,
-	 * In the input list of 0x0c, 0x0b node has index 1
+	 * Up to now, we initialized playback paths. we begin
+	 * to initialize record paths.
 	 */
+	inputs = AUDIO_MICROPHONE | AUDIO_LINE_IN | AUDIO_CD;
+	statep->hda_info_defaults.record.port = AUDIO_MICROPHONE;
+	statep->hda_info_defaults.record.avail_ports = inputs;
+	statep->hda_info_defaults.record.mod_ports = inputs;
+	statep->hda_in_ports = 0;
+
 	val = AUDIOHDC_AMP_SET_LR_INPUT | AUDIOHDC_GAIN_MAX;
 	val |= (1 << AUDIOHDC_AMP_SET_INDEX_OFFSET);
-	lTmp = audioha_codec_4bit_verb_get(statep, caddr, AUDIOHDC_NID(0x0C),
-	    AUDIOHDC_VERB_SET_AMP_MUTE, val);
-	if (lTmp == AUDIOHD_CODEC_FAILURE) {
-		audio_sup_log(statep->hda_ahandle, CE_WARN,
-		    "!alc880_enable_record() failed to set monitor");
+	if (statep->hda_codec->hc_vid == AUDIOHD_VID_ALC260) {
+		/*
+		 * enable gain for monitor path, from node 0x07 to node 0x08,
+		 * and 0x09. In the input list of 0x08 & 0x09, 0x0b node has
+		 * index 1
+		 */
+		if (audioha_codec_4bit_verb_get(statep, caddr,
+		    AUDIOHDC_NID(0x0C), AUDIOHDC_VERB_SET_AMP_MUTE, val) ==
+		    AUDIOHD_CODEC_FAILURE)
+			audio_sup_log(statep->hda_ahandle, CE_WARN,
+			    "!alc880_init_codec() failed to set monitor");
+
+		AUDIOHD_NODE_INIT_ADC(statep, caddr, 0x04);
+		AUDIOHD_NODE_ENABLE_PIN_IN(statep, caddr, 0x12); /* MIC1 */
+		AUDIOHD_NODE_ENABLE_PIN_IN(statep, caddr, 0x13); /* MIC2 */
+		AUDIOHD_NODE_ENABLE_PIN_IN(statep, caddr, 0x14); /* line-in1 */
+		AUDIOHD_NODE_ENABLE_PIN_IN(statep, caddr, 0x16); /* cd-in */
+	} else {
+		/*
+		 * enable gain for monitor path, from node 0x0B to node 0x0C,
+		 * In the input list of 0x0c, 0x0b node has index 1
+		 */
+		if (audioha_codec_4bit_verb_get(statep, caddr,
+		    AUDIOHDC_NID(0x0C), AUDIOHDC_VERB_SET_AMP_MUTE, val) ==
+		    AUDIOHD_CODEC_FAILURE)
+			audio_sup_log(statep->hda_ahandle, CE_WARN,
+			    "!alc880_init_codec() failed to set monitor");
+
+		AUDIOHD_NODE_INIT_ADC(statep, caddr, 0x08);
+		AUDIOHD_NODE_ENABLE_PIN_IN(statep, caddr, 0x18); /* MIC1 */
+		AUDIOHD_NODE_ENABLE_PIN_IN(statep, caddr, 0x19); /* MIC2 */
+		AUDIOHD_NODE_ENABLE_PIN_IN(statep, caddr, 0x1a); /* line-in1 */
+		AUDIOHD_NODE_ENABLE_PIN_IN(statep, caddr, 0x1c); /* cd-in */
 	}
 
 	return (AUDIO_SUCCESS);
 
-}	/* audiohd_alc880_enable_record */
+}	/* audiohd_alc880_init_codec() */
 
 /*
  * audiohd_alc880_set_pcm_fmt()
+ *
+ * common routines for Realtek ALC260, ALC262, ALC88x
  */
 static int
 audiohd_alc880_set_pcm_fmt(audiohd_state_t *statep, int dir, uint_t format)
@@ -2465,12 +2512,40 @@
 	uint32_t	lTmp;
 	uint_t		caddr = statep->hda_codec->hc_addr;
 
+	ASSERT((statep->hda_codec->hc_vid == AUDIOHD_VID_ALC260) ||
+	    (statep->hda_codec->hc_vid == AUDIOHD_VID_ALC262) ||
+	    (statep->hda_codec->hc_vid == AUDIOHD_VID_ALC880) ||
+	    (statep->hda_codec->hc_vid == AUDIOHD_VID_ALC882) ||
+	    (statep->hda_codec->hc_vid == AUDIOHD_VID_ALC883) ||
+	    (statep->hda_codec->hc_vid == AUDIOHD_VID_ALC885) ||
+	    (statep->hda_codec->hc_vid == AUDIOHD_VID_ALC888));
+
 	if (dir == AUDIO_PLAY) {
 		lTmp = audioha_codec_4bit_verb_get(statep, caddr,
 		    AUDIOHDC_NID(0x2), AUDIOHDC_VERB_SET_CONVERTER_FMT, format);
 	} else {
-		lTmp = audioha_codec_4bit_verb_get(statep, caddr,
-		    AUDIOHDC_NID(0x9), AUDIOHDC_VERB_SET_CONVERTER_FMT, format);
+		switch (statep->hda_codec->hc_vid) {
+		case AUDIOHD_VID_ALC262:
+		case AUDIOHD_VID_ALC880:
+		case AUDIOHD_VID_ALC882:
+		case AUDIOHD_VID_ALC883:
+		case AUDIOHD_VID_ALC885:
+		case AUDIOHD_VID_ALC888:
+			/*
+			 * We choose node 8 as active ADC
+			 */
+			lTmp = audioha_codec_4bit_verb_get(
+			    statep, caddr, AUDIOHDC_NID(0x8),
+			    AUDIOHDC_VERB_SET_CONVERTER_FMT, format);
+			break;
+		case AUDIOHD_VID_ALC260:
+			lTmp = audioha_codec_4bit_verb_get(
+			    statep, caddr, AUDIOHDC_NID(0x4),
+			    AUDIOHDC_VERB_SET_CONVERTER_FMT, format);
+			break;
+		default:
+			break;
+		}
 	}
 
 	if (lTmp == AUDIOHD_CODEC_FAILURE)
@@ -2482,6 +2557,8 @@
 
 /*
  * audiohd_alc880_set_gain()
+ *
+ * common routines for Realtek ALC260, ALC262, ALC88x
  */
 static int
 audiohd_alc880_set_gain(audiohd_state_t *statep, int dir, int gain, int channel)
@@ -2490,6 +2567,14 @@
 	uint_t		val;
 	uint_t		caddr = statep->hda_codec->hc_addr;
 
+	ASSERT((statep->hda_codec->hc_vid == AUDIOHD_VID_ALC260) ||
+	    (statep->hda_codec->hc_vid == AUDIOHD_VID_ALC262) ||
+	    (statep->hda_codec->hc_vid == AUDIOHD_VID_ALC880) ||
+	    (statep->hda_codec->hc_vid == AUDIOHD_VID_ALC882) ||
+	    (statep->hda_codec->hc_vid == AUDIOHD_VID_ALC883) ||
+	    (statep->hda_codec->hc_vid == AUDIOHD_VID_ALC885) ||
+	    (statep->hda_codec->hc_vid == AUDIOHD_VID_ALC888));
+
 	if (dir == AUDIO_PLAY) {
 		val = AUDIOHDC_AMP_SET_OUTPUT | gain;
 		if (channel == 0) {
@@ -2501,8 +2586,33 @@
 			val |= AUDIOHDC_AMP_SET_RIGHT;
 			statep->hda_play_rgain = gain;
 		}
-		lTmp = audioha_codec_4bit_verb_get(statep, caddr,
-		    AUDIOHDC_NID(0xC), AUDIOHDC_VERB_SET_AMP_MUTE, val);
+
+		switch (statep->hda_codec->hc_vid) {
+		case AUDIOHD_VID_ALC880:
+			lTmp = audioha_codec_4bit_verb_get(statep, caddr,
+			    AUDIOHDC_NID(0xE), AUDIOHDC_VERB_SET_AMP_MUTE, val);
+			/*FALLTHRU*/
+
+		case AUDIOHD_VID_ALC262:
+			lTmp = audioha_codec_4bit_verb_get(statep, caddr,
+			    AUDIOHDC_NID(0xD), AUDIOHDC_VERB_SET_AMP_MUTE, val);
+			/*FALLTHRU*/
+
+		case AUDIOHD_VID_ALC882:
+		case AUDIOHD_VID_ALC883:
+		case AUDIOHD_VID_ALC885:
+		case AUDIOHD_VID_ALC888:
+			lTmp = audioha_codec_4bit_verb_get(statep, caddr,
+			    AUDIOHDC_NID(0xC), AUDIOHDC_VERB_SET_AMP_MUTE, val);
+			break;
+
+		case AUDIOHD_VID_ALC260:
+			lTmp = audioha_codec_4bit_verb_get(statep, caddr,
+			    AUDIOHDC_NID(0x8), AUDIOHDC_VERB_SET_AMP_MUTE, val);
+			lTmp = audioha_codec_4bit_verb_get(statep, caddr,
+			    AUDIOHDC_NID(0x9), AUDIOHDC_VERB_SET_AMP_MUTE, val);
+			break;
+		}
 	} else {
 		ASSERT(dir == AUDIO_RECORD);
 		val = AUDIOHDC_AMP_SET_INPUT | gain;
@@ -2515,8 +2625,24 @@
 			val |= AUDIOHDC_AMP_SET_RIGHT;
 			statep->hda_record_rgain = gain;
 		}
-		lTmp = audioha_codec_4bit_verb_get(statep, caddr,
-		    AUDIOHDC_NID(0x9), AUDIOHDC_VERB_SET_AMP_MUTE, val);
+
+		switch (statep->hda_codec->hc_vid) {
+		case AUDIOHD_VID_ALC262:
+		case AUDIOHD_VID_ALC880:
+		case AUDIOHD_VID_ALC882:
+		case AUDIOHD_VID_ALC883:
+		case AUDIOHD_VID_ALC885:
+		case AUDIOHD_VID_ALC888:
+			lTmp = audioha_codec_4bit_verb_get(statep, caddr,
+			    AUDIOHDC_NID(0x8), AUDIOHDC_VERB_SET_AMP_MUTE, val);
+			break;
+		case AUDIOHD_VID_ALC260:
+			lTmp = audioha_codec_4bit_verb_get(statep, caddr,
+			    AUDIOHDC_NID(0x4), AUDIOHDC_VERB_SET_AMP_MUTE, val);
+			break;
+		default:
+			break;
+		}
 	}
 
 	if (lTmp == AUDIOHD_CODEC_FAILURE)
@@ -2528,6 +2654,8 @@
 
 /*
  * audiohd_alc880_set_port()
+ *
+ * common routines for Realtek ALC260, ALC262, ALC88x
  */
 static int
 audiohd_alc880_set_port(audiohd_state_t *statep, int dir, int port)
@@ -2536,39 +2664,104 @@
 	uint_t	tmp_port = 0;
 	uint_t	caddr = statep->hda_codec->hc_addr;
 
+	ASSERT((statep->hda_codec->hc_vid == AUDIOHD_VID_ALC260) ||
+	    (statep->hda_codec->hc_vid == AUDIOHD_VID_ALC262) ||
+	    (statep->hda_codec->hc_vid == AUDIOHD_VID_ALC880) ||
+	    (statep->hda_codec->hc_vid == AUDIOHD_VID_ALC882) ||
+	    (statep->hda_codec->hc_vid == AUDIOHD_VID_ALC883) ||
+	    (statep->hda_codec->hc_vid == AUDIOHD_VID_ALC885) ||
+	    (statep->hda_codec->hc_vid == AUDIOHD_VID_ALC888));
+
 	if (dir == AUDIO_PLAY) {
-
-		if (port == AUDIOHD_PORT_UNMUTE) {
+		if (port == AUDIOHD_PORT_UNMUTE)
 			port = statep->hda_out_ports;
-		}
-
-		val = AUDIOHDC_AMP_SET_LR_OUTPUT;
-		if (port & AUDIO_HEADPHONE) {
-			tmp_port |= AUDIO_HEADPHONE;
-		} else { /* mute */
-			val |= AUDIOHDC_AMP_SET_MUTE;
+
+		switch (statep->hda_codec->hc_vid) {
+		case AUDIOHD_VID_ALC880:
+		case AUDIOHD_VID_ALC882:
+		case AUDIOHD_VID_ALC883:
+		case AUDIOHD_VID_ALC885:
+		case AUDIOHD_VID_ALC888:
+			val = AUDIOHDC_AMP_SET_LR_OUTPUT;
+			if (port & AUDIO_AUX2_OUT)
+				tmp_port |= AUDIO_AUX2_OUT;
+			else
+				val |= AUDIOHDC_AMP_SET_MUTE;
+
+			if (audioha_codec_4bit_verb_get(statep, caddr,
+			    AUDIOHDC_NID(0x16), AUDIOHDC_VERB_SET_AMP_MUTE,
+			    val) == AUDIOHD_CODEC_FAILURE)
+				return (AUDIO_FAILURE);
+			/*FALLTHRU*/
+
+		case AUDIOHD_VID_ALC262:
+			val = AUDIOHDC_AMP_SET_LR_OUTPUT;
+			if (port & AUDIO_HEADPHONE)
+				tmp_port |= AUDIO_HEADPHONE;
+			else
+				val |= AUDIOHDC_AMP_SET_MUTE;
+			if (audioha_codec_4bit_verb_get(statep, caddr,
+			    AUDIOHDC_NID(0x14), AUDIOHDC_VERB_SET_AMP_MUTE,
+			    val) == AUDIOHD_CODEC_FAILURE)
+				return (AUDIO_FAILURE);
+
+			/*
+			 * Munich workstation uses 0x1B of ALC885 as Line-out
+			 * pin. so we consider this pin as line-out for all
+			 * codec of alc88x series.
+			 */
+			val = AUDIOHDC_AMP_SET_LR_OUTPUT;
+			if (port & AUDIO_LINE_OUT)
+				tmp_port |= AUDIO_LINE_OUT;
+			else
+				val |= AUDIOHDC_AMP_SET_MUTE;
+			if (audioha_codec_4bit_verb_get(statep, caddr,
+			    AUDIOHDC_NID(0x1B), AUDIOHDC_VERB_SET_AMP_MUTE,
+			    val) == AUDIOHD_CODEC_FAILURE)
+				return (AUDIO_FAILURE);
+
+			val = AUDIOHDC_AMP_SET_LR_OUTPUT;
+			if (port & AUDIO_AUX1_OUT)
+				tmp_port |= AUDIO_AUX1_OUT;
+			else
+				val |= AUDIOHDC_AMP_SET_MUTE;
+
+			if (audioha_codec_4bit_verb_get(statep, caddr,
+			    AUDIOHDC_NID(0x15), AUDIOHDC_VERB_SET_AMP_MUTE,
+			    val) == AUDIOHD_CODEC_FAILURE)
+				return (AUDIO_FAILURE);
+			break;
+
+		case AUDIOHD_VID_ALC260:
+			val = AUDIOHDC_AMP_SET_LR_OUTPUT;
+			if (port & AUDIO_HEADPHONE)
+				tmp_port |= AUDIO_HEADPHONE;
+			else
+				val |= AUDIOHDC_AMP_SET_MUTE;
+			if (audioha_codec_4bit_verb_get(statep, caddr,
+			    AUDIOHDC_NID(0x10), AUDIOHDC_VERB_SET_AMP_MUTE,
+			    val) == AUDIOHD_CODEC_FAILURE)
+				return (AUDIO_FAILURE);
+
+			val = AUDIOHDC_AMP_SET_LR_OUTPUT;
+			if (port & AUDIO_LINE_OUT)
+				tmp_port |= AUDIO_LINE_OUT;
+			else
+				val |= AUDIOHDC_AMP_SET_MUTE;
+			if (audioha_codec_4bit_verb_get(statep, caddr,
+			    AUDIOHDC_NID(0x0F), AUDIOHDC_VERB_SET_AMP_MUTE,
+			    val) == AUDIOHD_CODEC_FAILURE)
+				return (AUDIO_FAILURE);
+			break;
+
+		default:	/* unknown CODEC */
+			return (AUDIO_FAILURE);
 		}
 
-		if (audioha_codec_4bit_verb_get(statep, caddr,
-		    AUDIOHDC_NID(0x14), AUDIOHDC_VERB_SET_AMP_MUTE, val) ==
-		    AUDIOHD_CODEC_FAILURE)
-			return (AUDIO_FAILURE);
-
-		val = AUDIOHDC_AMP_SET_LR_OUTPUT;
-		if (port & AUDIO_LINE_OUT) {
-			tmp_port |= AUDIO_LINE_OUT;
-		} else { /* mute */
-			val |= AUDIOHDC_AMP_SET_MUTE;
-		}
-
-		if (audioha_codec_4bit_verb_get(statep, caddr,
-		    AUDIOHDC_NID(0x1B), AUDIOHDC_VERB_SET_AMP_MUTE,
-		    val) == AUDIOHD_CODEC_FAILURE)
-			return (AUDIO_FAILURE);
+		statep->hda_out_ports = tmp_port;
 
 		if (tmp_port != port)
 			return (AUDIO_FAILURE);
-		statep->hda_out_ports = tmp_port;
 
 		return (AUDIO_SUCCESS);
 	}
@@ -2580,10 +2773,16 @@
 
 	switch (port) {
 	case AUDIO_NONE:
-		/* mute ADC node 0x09 */
+		/*
+		 * Mute ADC node: node 0x04 for ALC260, 0x08 for others.
+		 */
 		val = AUDIOHDC_AMP_SET_LR_INPUT | AUDIOHDC_AMP_SET_MUTE;
-		(void) audioha_codec_4bit_verb_get(statep, caddr,
-		    AUDIOHDC_NID(0x9), AUDIOHDC_VERB_SET_AMP_MUTE, val);
+		if (statep->hda_codec->hc_vid == AUDIOHD_VID_ALC260)
+			(void) audioha_codec_4bit_verb_get(statep, caddr,
+			    AUDIOHDC_NID(0x4), AUDIOHDC_VERB_SET_AMP_MUTE, val);
+		else
+			(void) audioha_codec_4bit_verb_get(statep, caddr,
+			    AUDIOHDC_NID(0x8), AUDIOHDC_VERB_SET_AMP_MUTE, val);
 		statep->hda_in_ports = port;
 		return (AUDIO_SUCCESS);
 
@@ -2600,35 +2799,60 @@
 		return (AUDIO_FAILURE);
 	}
 
-	/* if ADC 0x09 is muted, we resume its gains */
+	/* if ADC 0x08 is muted, we resume its gains */
 	if (statep->hda_in_ports == AUDIO_NONE) {
-		(void) audioha_codec_4bit_verb_get(statep, caddr,
-		    AUDIOHDC_NID(0x9), AUDIOHDC_VERB_SET_AMP_MUTE,
-		    (AUDIOHDC_AMP_SET_INPUT | AUDIOHDC_AMP_SET_LEFT |
-		    statep->hda_record_lgain));
-		(void) audioha_codec_4bit_verb_get(statep, caddr,
-		    AUDIOHDC_NID(0x9), AUDIOHDC_VERB_SET_AMP_MUTE,
-		    (AUDIOHDC_AMP_SET_INPUT | AUDIOHDC_AMP_SET_RIGHT |
-		    statep->hda_record_rgain));
+		if (statep->hda_codec->hc_vid == AUDIOHD_VID_ALC260) {
+			(void) audioha_codec_4bit_verb_get(statep, caddr,
+			    AUDIOHDC_NID(0x8), AUDIOHDC_VERB_SET_AMP_MUTE,
+			    (AUDIOHDC_AMP_SET_INPUT | AUDIOHDC_AMP_SET_LEFT |
+			    statep->hda_record_lgain));
+			(void) audioha_codec_4bit_verb_get(statep, caddr,
+			    AUDIOHDC_NID(0x8), AUDIOHDC_VERB_SET_AMP_MUTE,
+			    (AUDIOHDC_AMP_SET_INPUT | AUDIOHDC_AMP_SET_RIGHT |
+			    statep->hda_record_rgain));
+		} else {
+			(void) audioha_codec_4bit_verb_get(statep, caddr,
+			    AUDIOHDC_NID(0x4), AUDIOHDC_VERB_SET_AMP_MUTE,
+			    (AUDIOHDC_AMP_SET_INPUT | AUDIOHDC_AMP_SET_LEFT |
+			    statep->hda_record_lgain));
+			(void) audioha_codec_4bit_verb_get(statep, caddr,
+			    AUDIOHDC_NID(0x4), AUDIOHDC_VERB_SET_AMP_MUTE,
+			    (AUDIOHDC_AMP_SET_INPUT | AUDIOHDC_AMP_SET_RIGHT |
+			    statep->hda_record_rgain));
+		}
 	}
 
 	switch (statep->hda_codec->hc_vid) {
-	case AUDIOHD_VID_ALC880:
+	case AUDIOHD_VID_ALC260:
 		/*
-		 * For ALC880, node 9 has multiple inputs,
+		 * For ALC260, node 4 has multiple inputs,
 		 * we need to select the right one among
 		 * those inputs
 		 */
 		(void) audioha_codec_verb_get(statep, caddr,
-		    AUDIOHDC_NID(0x9), AUDIOHDC_VERB_SET_CONN_SEL,
+		    AUDIOHDC_NID(0x4), AUDIOHDC_VERB_SET_CONN_SEL,
 		    tmp_port);
 		break;
 
+	case AUDIOHD_VID_ALC880:
+		/*
+		 * For ALC880, node 8 has multiple inputs,
+		 * we need to select the right one among
+		 * those inputs
+		 */
+		(void) audioha_codec_verb_get(statep, caddr,
+		    AUDIOHDC_NID(0x8), AUDIOHDC_VERB_SET_CONN_SEL,
+		    tmp_port);
+		break;
+
+	case AUDIOHD_VID_ALC262:
+	case AUDIOHD_VID_ALC882:
 	case AUDIOHD_VID_ALC883:
 	case AUDIOHD_VID_ALC885:
+	case AUDIOHD_VID_ALC888:
 		/*
-		 * For ALC883/885, node 9 has only one input,
-		 * which is a mixer with node number 0x22. So,
+		 * For ALC883/885, node 8 has only one input,
+		 * which is a mixer with node number 0x23. So,
 		 * we mute all inputs except the one selected
 		 * by users. Note that all inputs are muted by
 		 * default, it is needed to mute the one being
@@ -2656,7 +2880,7 @@
 			val = AUDIOHDC_AMP_SET_LR_INPUT | AUDIOHDC_AMP_SET_MUTE;
 			val |= (old_index << AUDIOHDC_AMP_SET_INDEX_OFFSET);
 			(void) audioha_codec_4bit_verb_get(statep, caddr,
-			    AUDIOHDC_NID(0x22), AUDIOHDC_VERB_SET_AMP_MUTE,
+			    AUDIOHDC_NID(0x23), AUDIOHDC_VERB_SET_AMP_MUTE,
 			    val);
 
 			if (statep->hda_in_ports == AUDIO_MICROPHONE) {
@@ -2667,7 +2891,7 @@
 				val |=
 				    old_index << AUDIOHDC_AMP_SET_INDEX_OFFSET;
 				(void) audioha_codec_4bit_verb_get(statep,
-				    caddr, AUDIOHDC_NID(0x22),
+				    caddr, AUDIOHDC_NID(0x23),
 					AUDIOHDC_VERB_SET_AMP_MUTE, val);
 			}
 		}
@@ -2676,7 +2900,7 @@
 		val = AUDIOHDC_AMP_SET_LR_INPUT;
 		val |= tmp_port << AUDIOHDC_AMP_SET_INDEX_OFFSET;
 		(void) audioha_codec_4bit_verb_get(statep, caddr,
-		    AUDIOHDC_NID(0x22), AUDIOHDC_VERB_SET_AMP_MUTE, val);
+		    AUDIOHDC_NID(0x23), AUDIOHDC_VERB_SET_AMP_MUTE, val);
 
 		if (port == AUDIO_MICROPHONE) {
 			/*
@@ -2687,7 +2911,7 @@
 			val = AUDIOHDC_AMP_SET_LR_INPUT;
 			val |= tmp_port << AUDIOHDC_AMP_SET_INDEX_OFFSET;
 			(void) audioha_codec_4bit_verb_get(statep, caddr,
-			    AUDIOHDC_NID(0x22), AUDIOHDC_VERB_SET_AMP_MUTE,
+			    AUDIOHDC_NID(0x23), AUDIOHDC_VERB_SET_AMP_MUTE,
 			    val);
 		}
 
@@ -2706,6 +2930,8 @@
 
 /*
  * audiohd_alc880_mute_outputs()
+ *
+ * common routines for Realtek ALC260, ALC262, ALC88x
  */
 static int
 audiohd_alc880_mute_outputs(audiohd_state_t *statep, boolean_t mute)
@@ -2713,6 +2939,14 @@
 	uint_t	val;
 	uint_t	caddr = statep->hda_codec->hc_addr;
 
+	ASSERT((statep->hda_codec->hc_vid == AUDIOHD_VID_ALC260) ||
+	    (statep->hda_codec->hc_vid == AUDIOHD_VID_ALC262) ||
+	    (statep->hda_codec->hc_vid == AUDIOHD_VID_ALC880) ||
+	    (statep->hda_codec->hc_vid == AUDIOHD_VID_ALC882) ||
+	    (statep->hda_codec->hc_vid == AUDIOHD_VID_ALC883) ||
+	    (statep->hda_codec->hc_vid == AUDIOHD_VID_ALC885) ||
+	    (statep->hda_codec->hc_vid == AUDIOHD_VID_ALC888));
+
 	if (statep->hda_outputs_muted == mute)
 		return (AUDIO_SUCCESS);
 
@@ -2722,11 +2956,31 @@
 		val |= AUDIOHDC_AMP_SET_MUTE;
 	}
 
-	(void) audioha_codec_4bit_verb_get(statep, caddr,
-	    AUDIOHDC_NID(0x14), AUDIOHDC_VERB_SET_AMP_MUTE, val);
-
-	(void) audioha_codec_4bit_verb_get(statep, caddr,
-	    AUDIOHDC_NID(0x1b), AUDIOHDC_VERB_SET_AMP_MUTE, val);
+	switch (statep->hda_codec->hc_vid) {
+	case AUDIOHD_VID_ALC262:
+	case AUDIOHD_VID_ALC880:
+	case AUDIOHD_VID_ALC882:
+	case AUDIOHD_VID_ALC883:
+	case AUDIOHD_VID_ALC885:
+	case AUDIOHD_VID_ALC888:
+		(void) audioha_codec_4bit_verb_get(statep, caddr,
+		    AUDIOHDC_NID(0x1b), AUDIOHDC_VERB_SET_AMP_MUTE, val);
+		(void) audioha_codec_4bit_verb_get(statep, caddr,
+		    AUDIOHDC_NID(0x16), AUDIOHDC_VERB_SET_AMP_MUTE, val);
+		(void) audioha_codec_4bit_verb_get(statep, caddr,
+		    AUDIOHDC_NID(0x15), AUDIOHDC_VERB_SET_AMP_MUTE, val);
+		(void) audioha_codec_4bit_verb_get(statep, caddr,
+		    AUDIOHDC_NID(0x14), AUDIOHDC_VERB_SET_AMP_MUTE, val);
+		break;
+	case AUDIOHD_VID_ALC260:
+		(void) audioha_codec_4bit_verb_get(statep, caddr,
+		    AUDIOHDC_NID(0x10), AUDIOHDC_VERB_SET_AMP_MUTE, val);
+		(void) audioha_codec_4bit_verb_get(statep, caddr,
+		    AUDIOHDC_NID(0x0f), AUDIOHDC_VERB_SET_AMP_MUTE, val);
+		break;
+	default:
+		break;
+	}
 
 	return (AUDIO_SUCCESS);
 
@@ -2735,6 +2989,8 @@
 /*
  * audiohd_alc880_set_monitor_gain()
  *
+ * common routines for Realtek ALC260, ALC262, ALC88x
+ *
  * Description:
  *	Set the gain for input-to-ouput path
  */
@@ -2744,6 +3000,15 @@
 	uint_t	val;
 	uint_t	index;
 	uint_t	caddr = statep->hda_codec->hc_addr;
+	uint_t	mix_nid;
+
+	ASSERT((statep->hda_codec->hc_vid == AUDIOHD_VID_ALC260) ||
+	    (statep->hda_codec->hc_vid == AUDIOHD_VID_ALC262) ||
+	    (statep->hda_codec->hc_vid == AUDIOHD_VID_ALC880) ||
+	    (statep->hda_codec->hc_vid == AUDIOHD_VID_ALC882) ||
+	    (statep->hda_codec->hc_vid == AUDIOHD_VID_ALC883) ||
+	    (statep->hda_codec->hc_vid == AUDIOHD_VID_ALC885) ||
+	    (statep->hda_codec->hc_vid == AUDIOHD_VID_ALC888));
 
 	switch (statep->hda_in_ports) {
 	case AUDIO_MICROPHONE:
@@ -2757,10 +3022,14 @@
 		break;
 	}
 
+	if (statep->hda_codec->hc_vid == AUDIOHD_VID_ALC260)
+		mix_nid = 0x7;
+	else
+		mix_nid = 0xB;
 	val = AUDIOHDC_AMP_SET_LR_INPUT | gain;
 	val |= (index << AUDIOHDC_AMP_SET_INDEX_OFFSET);
 	(void) audioha_codec_4bit_verb_get(statep, caddr,
-	    AUDIOHDC_NID(0xB), AUDIOHDC_VERB_SET_AMP_MUTE, val);
+	    mix_nid, AUDIOHDC_VERB_SET_AMP_MUTE, val);
 
 	/* set MIC1 and MIC2 if MIC is requested */
 	if (statep->hda_in_ports == AUDIO_MICROPHONE) {
@@ -2768,15 +3037,19 @@
 		val = AUDIOHDC_AMP_SET_LR_INPUT | gain;
 		val |= (index << AUDIOHDC_AMP_SET_INDEX_OFFSET);
 		(void) audioha_codec_4bit_verb_get(statep, caddr,
-		    AUDIOHDC_NID(0xB), AUDIOHDC_VERB_SET_AMP_MUTE, val);
+		    mix_nid, AUDIOHDC_VERB_SET_AMP_MUTE, val);
 	}
 	return (AUDIO_SUCCESS);
 
 }	/* audiohd_alc880_set_monitor_gain() */
 
+
+
 /*
  * audiohd_alc880_max_gain()
  *
+ * common routines for Realtek ALC260, ALC262, ALC88x
+ *
  * Description:
  *	Get max gains for packplay and recording
  */
@@ -2785,18 +3058,375 @@
 	*rgain, uint_t *mgain)
 {
 	uint_t	caddr = statep->hda_codec->hc_addr;
+	uint_t	nid_p, nid_r, nid_m;
 	uint_t	lTmp;
 
-	lTmp = audioha_codec_verb_get(statep, caddr, AUDIOHDC_NID(0xC),
+	ASSERT((statep->hda_codec->hc_vid == AUDIOHD_VID_ALC260) ||
+	    (statep->hda_codec->hc_vid == AUDIOHD_VID_ALC262) ||
+	    (statep->hda_codec->hc_vid == AUDIOHD_VID_ALC880) ||
+	    (statep->hda_codec->hc_vid == AUDIOHD_VID_ALC882) ||
+	    (statep->hda_codec->hc_vid == AUDIOHD_VID_ALC883) ||
+	    (statep->hda_codec->hc_vid == AUDIOHD_VID_ALC885) ||
+	    (statep->hda_codec->hc_vid == AUDIOHD_VID_ALC888));
+
+	if (statep->hda_codec->hc_vid == AUDIOHD_VID_ALC260) {
+		nid_p = 0x08;
+		nid_r = 0x04;
+		nid_m = 0x07;
+	} else {
+		nid_p = 0x0c;
+		nid_r = 0x08;
+		nid_m = 0x0b;
+	}
+	lTmp = audioha_codec_verb_get(statep, caddr, nid_p,
 	    AUDIOHDC_VERB_GET_PARAM, AUDIOHDC_PAR_AMP_OUT_CAP);
 	*pgain = (lTmp & AUDIOHDC_AMP_CAP_STEP_NUMS) >> 8;
 
-	lTmp = audioha_codec_verb_get(statep, caddr, AUDIOHDC_NID(0x9),
+	lTmp = audioha_codec_verb_get(statep, caddr, nid_r,
 	    AUDIOHDC_VERB_GET_PARAM, AUDIOHDC_PAR_AMP_IN_CAP);
 	*rgain = (lTmp & AUDIOHDC_AMP_CAP_STEP_NUMS) >> 8;
 
-	lTmp = audioha_codec_verb_get(statep, caddr, AUDIOHDC_NID(0xb),
+	lTmp = audioha_codec_verb_get(statep, caddr, nid_m,
 	    AUDIOHDC_VERB_GET_PARAM, AUDIOHDC_PAR_AMP_IN_CAP);
 	*mgain = (lTmp & AUDIOHDC_AMP_CAP_STEP_NUMS) >> 8;
 
 }	/* audiohd_alc880_max_gain() */
+
+
+/*
+ * audiohd_stac_init_codec()
+ */
+static int
+audiohd_stac_init_codec(audiohd_state_t *statep)
+{
+	uint_t		inputs, outputs;
+	uint_t		caddr = statep->hda_codec->hc_addr;
+
+	ASSERT((statep->hda_codec->hc_vid == AUDIOHD_VID_STAC9200) ||
+	    (statep->hda_codec->hc_vid == AUDIOHD_VID_STAC9200D));
+
+	/* power-up AFG node */
+	(void) audioha_codec_verb_get(statep, caddr,
+	    AUDIOHDC_NID(0x1), AUDIOHDC_VERB_SET_POWER_STATE, 0);
+
+	/* power-up DAC node */
+	(void) audioha_codec_verb_get(statep, caddr,
+	    AUDIOHDC_NID(0x2), AUDIOHDC_VERB_SET_POWER_STATE, 0);
+
+	AUDIOHD_NODE_INIT_DAC(statep, caddr, AUDIOHDC_NID(0x2));
+
+	(void) audioha_codec_verb_get(statep, caddr,
+	    AUDIOHDC_NID(0x7), AUDIOHDC_VERB_SET_CONN_SEL, 0);
+
+	/* HEADPHONE_OUT */
+	AUDIOHD_NODE_ENABLE_PIN_OUT(statep, caddr, AUDIOHDC_NID(0x0D));
+
+	/* AUDIO_LINE_OUT */
+	AUDIOHD_NODE_ENABLE_PIN_OUT(statep, caddr, AUDIOHDC_NID(0x0E));
+
+	outputs = AUDIO_HEADPHONE | AUDIO_LINE_OUT;
+
+	statep->hda_info_defaults.play.port = outputs;
+	statep->hda_info_defaults.play.avail_ports = outputs;
+	statep->hda_info_defaults.play.mod_ports = outputs;
+	statep->hda_out_ports = 0;
+
+	/* set master volume to max */
+	(void) audioha_codec_4bit_verb_get(statep, caddr,
+	    AUDIOHDC_NID(0x0B), AUDIOHDC_VERB_SET_AMP_MUTE,
+		AUDIOHDC_AMP_ROUT_MAX);
+	(void) audioha_codec_4bit_verb_get(statep, caddr,
+	    AUDIOHDC_NID(0x0B), AUDIOHDC_VERB_SET_AMP_MUTE,
+		AUDIOHDC_AMP_LOUT_MAX);
+
+	/*
+	 * Up to now, we initialized playback paths. we begin
+	 * to initialize record paths.
+	 */
+	inputs = AUDIO_MICROPHONE | AUDIO_LINE_IN | AUDIO_CD;
+	statep->hda_info_defaults.record.port = AUDIO_MICROPHONE;
+	statep->hda_info_defaults.record.avail_ports = inputs;
+	statep->hda_info_defaults.record.mod_ports = inputs;
+	statep->hda_in_ports = 0;
+
+	/* power-up ADC node */
+	(void) audioha_codec_verb_get(statep, caddr,
+	    AUDIOHDC_NID(0x3), AUDIOHDC_VERB_SET_POWER_STATE, 0);
+
+	AUDIOHD_NODE_INIT_ADC(statep, caddr, AUDIOHDC_NID(0x3));
+
+	/* set MUX volume to max */
+	(void) audioha_codec_4bit_verb_get(statep, caddr,
+	    AUDIOHDC_NID(0x0C), AUDIOHDC_VERB_SET_AMP_MUTE,
+		AUDIOHDC_AMP_ROUT_MAX);
+	(void) audioha_codec_4bit_verb_get(statep, caddr,
+	    AUDIOHDC_NID(0x0C), AUDIOHDC_VERB_SET_AMP_MUTE,
+		AUDIOHDC_AMP_LOUT_MAX);
+
+	/* MIC */
+	AUDIOHD_NODE_ENABLE_PIN_IN(statep, caddr, AUDIOHDC_NID(0x10));
+	(void) audioha_codec_verb_get(statep, caddr, AUDIOHDC_NID(0xC),
+	    AUDIOHDC_VERB_SET_CONN_SEL, 0);
+
+	return (AUDIO_SUCCESS);
+
+}	/* audiohd_stac_init_codec() */
+
+
+/*
+ * audiohd_stac_set_pcm_fmt()
+ */
+static int
+audiohd_stac_set_pcm_fmt(audiohd_state_t *statep, int dir, uint_t format)
+{
+	uint_t		lTmp;
+	uint_t		caddr = statep->hda_codec->hc_addr;
+
+	ASSERT((statep->hda_codec->hc_vid == AUDIOHD_VID_STAC9200) ||
+	    (statep->hda_codec->hc_vid == AUDIOHD_VID_STAC9200D));
+
+	if (dir == AUDIO_PLAY) {
+		lTmp = audioha_codec_4bit_verb_get(statep, caddr,
+		    AUDIOHDC_NID(0x2), AUDIOHDC_VERB_SET_CONVERTER_FMT, format);
+	} else {
+		lTmp = audioha_codec_4bit_verb_get(statep, caddr,
+		    AUDIOHDC_NID(0x3), AUDIOHDC_VERB_SET_CONVERTER_FMT, format);
+	}
+
+	if (lTmp == AUDIOHD_CODEC_FAILURE)
+		return (AUDIO_FAILURE);
+
+	return (AUDIO_SUCCESS);
+
+}	/* audiohd_stac_set_pcm_fmt() */
+
+
+/*
+ * audiohd_stac_set_gain()
+ */
+static int
+audiohd_stac_set_gain(audiohd_state_t *statep, int dir, int gain, int channel)
+{
+	uint_t		val, lTmp;
+	uint_t		caddr = statep->hda_codec->hc_addr;
+
+	ASSERT((statep->hda_codec->hc_vid == AUDIOHD_VID_STAC9200) ||
+	    (statep->hda_codec->hc_vid == AUDIOHD_VID_STAC9200D));
+
+	if (dir == AUDIO_PLAY) {
+
+		val = AUDIOHDC_AMP_SET_OUTPUT | gain;
+		if (channel == 0) {
+			/* left channel */
+			val |= AUDIOHDC_AMP_SET_LEFT;
+			statep->hda_play_lgain = gain;
+		} else {
+			/* right channel */
+			val |= AUDIOHDC_AMP_SET_RIGHT;
+			statep->hda_play_rgain = gain;
+		}
+
+		lTmp = audioha_codec_4bit_verb_get(statep, caddr,
+		    AUDIOHDC_NID(0xB), AUDIOHDC_VERB_SET_AMP_MUTE, val);
+	} else {
+		ASSERT(dir == AUDIO_RECORD);
+		val = AUDIOHDC_AMP_SET_OUTPUT | gain;
+		if (channel == 0) {
+			/* left channel */
+			val |= AUDIOHDC_AMP_SET_LEFT;
+			statep->hda_record_lgain = gain;
+		} else {
+			/* right channel */
+			val |= AUDIOHDC_AMP_SET_RIGHT;
+			statep->hda_record_rgain = gain;
+		}
+
+		lTmp = audioha_codec_4bit_verb_get(statep, caddr,
+		    AUDIOHDC_NID(0xA), AUDIOHDC_VERB_SET_AMP_MUTE, val);
+	}
+
+	if (lTmp == AUDIOHD_CODEC_FAILURE)
+		return (AUDIO_FAILURE);
+
+	return (AUDIO_SUCCESS);
+
+}	/* audiohd_stac_set_gain() */
+
+/*
+ * audiohd_stac_set_port()
+ */
+static int
+audiohd_stac_set_port(audiohd_state_t *statep, int dir, int port)
+{
+	uint_t		nid;
+	uint_t		tmp_port = 0;
+	uint_t		index_port;
+	uint_t		caddr = statep->hda_codec->hc_addr;
+
+	ASSERT((statep->hda_codec->hc_vid == AUDIOHD_VID_STAC9200) ||
+	    (statep->hda_codec->hc_vid == AUDIOHD_VID_STAC9200D));
+
+	if (dir == AUDIO_PLAY) {
+		if (port == AUDIOHD_PORT_UNMUTE)
+			port = statep->hda_out_ports;
+
+		if (port & AUDIO_HEADPHONE) {
+			tmp_port |= AUDIO_HEADPHONE;
+			AUDIOHD_NODE_ENABLE_PIN_OUT(statep, caddr, 0x0D);
+		} else {
+			AUDIOHD_NODE_DISABLE_PIN_OUT(statep, caddr, 0x0D);
+		}
+
+		if (port & AUDIO_LINE_OUT) {
+			tmp_port |= AUDIO_LINE_OUT;
+			AUDIOHD_NODE_ENABLE_PIN_OUT(statep, caddr, 0x0E);
+		} else {
+			AUDIOHD_NODE_DISABLE_PIN_OUT(statep, caddr, 0x0E);
+		}
+
+		statep->hda_out_ports = tmp_port;
+		if (tmp_port != port)
+			return (AUDIO_FAILURE);
+
+		return (AUDIO_SUCCESS);
+	}
+
+	ASSERT(dir == AUDIO_RECORD);
+
+	nid = 0;
+	switch (port) {
+	case AUDIO_NONE:
+		nid = statep->hda_in_ports;
+		if (nid != 0) {
+			AUDIOHD_NODE_DISABLE_PIN_IN(statep, caddr, nid);
+			statep->hda_in_ports = 0;
+		}
+		return (AUDIO_SUCCESS);
+
+	case AUDIO_MICROPHONE:
+		index_port = 0;
+		nid = 0x10;
+		break;
+
+	case AUDIO_LINE_IN:
+		index_port = 1;
+		nid = 0x0F;
+		break;
+
+	case AUDIO_CD:
+		index_port = 4;
+		nid = 0x12;
+		break;
+
+	default:
+		return (AUDIO_FAILURE);
+	}
+
+	if (nid != statep->hda_in_ports) {
+		statep->hda_in_ports = nid;
+
+		/* disable last selected input */
+		AUDIOHD_NODE_DISABLE_PIN_IN(statep, caddr,
+		    statep->hda_in_ports);
+
+		/* enable currently selected input */
+		AUDIOHD_NODE_ENABLE_PIN_IN(statep, caddr, nid);
+		(void) audioha_codec_verb_get(statep, caddr,
+		    AUDIOHDC_NID(0xC), AUDIOHDC_VERB_SET_CONN_SEL,
+		    index_port);
+	}
+
+	return (AUDIO_SUCCESS);
+
+}	/* audiohd_stac_set_port() */
+
+/*
+ * audiohd_stac_mute_outputs()
+ */
+static int
+audiohd_stac_mute_outputs(audiohd_state_t *statep, boolean_t mute)
+{
+	uint_t		caddr = statep->hda_codec->hc_addr;
+	uint32_t		lTmp;
+
+	ASSERT((statep->hda_codec->hc_vid == AUDIOHD_VID_STAC9200) ||
+	    (statep->hda_codec->hc_vid == AUDIOHD_VID_STAC9200D));
+
+	if (statep->hda_outputs_muted == mute)
+		return (AUDIO_SUCCESS);
+
+	statep->hda_outputs_muted = mute;
+
+	if (mute) {
+		/* mute master volume */
+		lTmp = audioha_codec_4bit_verb_get(statep, caddr,
+		    AUDIOHDC_NID(0xB), AUDIOHDC_VERB_SET_AMP_MUTE,
+		    AUDIOHDC_AMP_SET_MUTE | AUDIOHDC_AMP_SET_LR_OUTPUT);
+	} else {
+		/* resume left volume */
+		lTmp = audioha_codec_4bit_verb_get(statep, caddr,
+		    AUDIOHDC_NID(0xB), AUDIOHDC_VERB_SET_AMP_MUTE,
+		    AUDIOHDC_AMP_SET_OUTPUT | AUDIOHDC_AMP_SET_LEFT |
+		    statep->hda_play_lgain);
+
+		if (lTmp == AUDIOHD_CODEC_FAILURE)
+			return (AUDIO_FAILURE);
+
+		/* resume right volume */
+		lTmp = audioha_codec_4bit_verb_get(statep, caddr,
+		    AUDIOHDC_NID(0xB), AUDIOHDC_VERB_SET_AMP_MUTE,
+		    AUDIOHDC_AMP_SET_OUTPUT | AUDIOHDC_AMP_SET_RIGHT |
+		    statep->hda_play_rgain);
+	}
+
+	if (lTmp == AUDIOHD_CODEC_FAILURE)
+		return (AUDIO_FAILURE);
+
+	return (AUDIO_SUCCESS);
+
+}	/* audiohd_stac_mute_outputs() */
+
+/*
+ * audiohd_stac_set_monitor_gain()
+ */
+static int
+audiohd_stac_set_monitor_gain(audiohd_state_t *statep, int gain)
+{
+	uint_t		caddr = statep->hda_codec->hc_addr;
+	uint_t		val;
+
+	ASSERT((statep->hda_codec->hc_vid == AUDIOHD_VID_STAC9200) ||
+	    (statep->hda_codec->hc_vid == AUDIOHD_VID_STAC9200D));
+
+	/*
+	 * STAC9200(D) has no specific hardware/node to control
+	 * monitor gain, so we just adjust output volume
+	 */
+	val = AUDIOHDC_AMP_SET_OUTPUT | AUDIOHDC_AMP_SET_LEFT | gain;
+	(void) audioha_codec_4bit_verb_get(statep, caddr,
+	    AUDIOHDC_NID(0xB), AUDIOHDC_VERB_SET_AMP_MUTE, val);
+
+	val = AUDIOHDC_AMP_SET_OUTPUT | AUDIOHDC_AMP_SET_RIGHT | gain;
+	(void) audioha_codec_4bit_verb_get(statep, caddr,
+	    AUDIOHDC_NID(0xB), AUDIOHDC_VERB_SET_AMP_MUTE, val);
+
+	statep->hda_monitor_gain = gain;
+
+	return (AUDIO_SUCCESS);
+
+}	/* audiohd_stac_set_monitor_gain() */
+
+/*
+ * audiohd_stac_max_gain()
+ */
+static void audiohd_stac_max_gain(audiohd_state_t *statep, uint_t *pgain,
+    uint_t *rgain, uint_t *mgain)
+{
+	ASSERT((statep->hda_codec->hc_vid == AUDIOHD_VID_STAC9200) ||
+	    (statep->hda_codec->hc_vid == AUDIOHD_VID_STAC9200D));
+
+	*pgain = 0x1f;
+	*rgain = 0x1f;
+	*mgain = 0x1f;
+
+}	/* audiohd_stac_max_gain() */
--- a/usr/src/uts/common/sys/audio/impl/audiohd_impl.h	Wed Nov 22 13:57:56 2006 -0800
+++ b/usr/src/uts/common/sys/audio/impl/audiohd_impl.h	Wed Nov 22 18:59:14 2006 -0800
@@ -43,9 +43,21 @@
 extern "C" {
 #endif
 
+/*
+ * vendor IDs and device IDs of supported devices
+ */
+#define	AUDIOHD_VID_ALC260	0x10ec0260
+#define	AUDIOHD_VID_ALC262	0x10ec0262
 #define	AUDIOHD_VID_ALC880	0x10ec0880
+#define	AUDIOHD_VID_ALC882	0x10ec0882
 #define	AUDIOHD_VID_ALC883	0x10ec0883
 #define	AUDIOHD_VID_ALC885	0x10ec0885
+#define	AUDIOHD_VID_ALC888	0x10ec0888
+#define	AUDIOHD_VID_STAC9200	0x83847690
+#define	AUDIOHD_VID_STAC9200D	0x83847691
+
+/* vendor-id and device-id for ATI SB450 */
+#define	AUDIOHD_ATI_SB450	0x437d1002
 
 #define	AUDIOHDC_NID(x)		x
 /*
@@ -228,7 +240,9 @@
 #define	AUDIOHDC_VERB_GET_CONN_LIST_ENT		0xf02
 #define	AUDIOHDC_VERB_GET_PROCESS_STATE		0xf03
 #define	AUDIOHDC_VERB_GET_SDI_SEL		0xf04
+
 #define	AUDIOHDC_VERB_GET_POWER_STATE		0xf05
+#define	AUDIOHDC_VERB_SET_POWER_STATE		0x705
 
 #define	AUDIOHDC_VERB_GET_STREAM_CHANN		0xf06
 #define	AUDIOHDC_VERB_SET_STREAM_CHANN		0x706
@@ -286,6 +300,19 @@
 #define	AUDIOHDC_GAIN_BITS			7
 #define	AUDIOHDC_GAIN_DEFAULT			0x0f
 
+/* value used to set max volume for left output */
+#define	AUDIOHDC_AMP_LOUT_MAX	\
+	(AUDIOHDC_AMP_SET_OUTPUT | \
+	AUDIOHDC_AMP_SET_LEFT | \
+	AUDIOHDC_GAIN_MAX)
+
+/* value used to set max volume for right output */
+#define	AUDIOHDC_AMP_ROUT_MAX	\
+	(AUDIOHDC_AMP_SET_OUTPUT | \
+	AUDIOHDC_AMP_SET_RIGHT | \
+	AUDIOHDC_GAIN_MAX)
+
+
 /*
  * Bits for pin widget control verb
  */
@@ -418,8 +445,7 @@
 typedef struct audiohd_state audiohd_state_t;
 
 struct audiohd_codec_ops {
-	int (*ac_enable_play)(audiohd_state_t *);
-	int (*ac_enable_record)(audiohd_state_t *);
+	int (*ac_init_codec)(audiohd_state_t *);
 	int (*ac_set_pcm_fmt)(audiohd_state_t *, int, uint_t);
 	int (*ac_set_gain)(audiohd_state_t *, int, int, int);
 	int (*ac_set_port)(audiohd_state_t *, int, int);
@@ -429,11 +455,8 @@
 		(audiohd_state_t *, uint_t *, uint_t *, uint_t *);
 };
 
-#define	AUDIOHD_CODEC_ENABLE_PLAY(x) \
-	x->hda_codec->hc_ops->ac_enable_play(x)
-
-#define	AUDIOHD_CODEC_ENABLE_RECORD(x) \
-	x->hda_codec->hc_ops->ac_enable_record(x)
+#define	AUDIOHD_CODEC_INIT_CODEC(x) \
+	x->hda_codec->hc_ops->ac_init_codec(x);
 
 #define	AUDIOHD_CODEC_SET_PCM_FORMAT(x, y, z) \
 	x->hda_codec->hc_ops->ac_set_pcm_fmt(x, y, z);
@@ -453,7 +476,6 @@
 #define	AUDIOHD_CODEC_MAX_GAIN(x, y, z, w) \
 	x->hda_codec->hc_ops->ac_get_max_gain(x, y, z, w)
 
-
 /*
  * Operation for high definition audio control system bus
  * interface registers
@@ -491,6 +513,147 @@
 	(void *)((char *)statep->hda_reg_base + (reg)), (val))
 
 
+/*
+ * This is used to initialize ADC node of CODEC
+ */
+#define	AUDIOHD_NODE_INIT_ADC(statep, caddr, nid) \
+{	\
+	/* for ADC node, set channel and stream tag */ \
+	if (audioha_codec_verb_get(statep, \
+	    caddr, nid, AUDIOHDC_VERB_SET_STREAM_CHANN, \
+	    statep->hda_record_stag << 4) == AUDIOHD_CODEC_FAILURE) \
+		return (AUDIO_FAILURE); \
+	\
+	/* set input amp of ADC node to max */ \
+	if (audioha_codec_4bit_verb_get(statep, \
+	    caddr, nid, AUDIOHDC_VERB_SET_AMP_MUTE, \
+	    AUDIOHDC_AMP_SET_LR_INPUT | AUDIOHDC_GAIN_MAX) == \
+	    AUDIOHD_CODEC_FAILURE) \
+		return (AUDIO_FAILURE); \
+}
+
+/*
+ * This is used to initialize DAC node of CODEC
+ */
+#define	AUDIOHD_NODE_INIT_DAC(statep, caddr, nid) \
+{	\
+	if (audioha_codec_verb_get(statep, \
+	    caddr, nid, AUDIOHDC_VERB_SET_STREAM_CHANN, \
+	    statep->hda_play_stag << 4) == AUDIOHD_CODEC_FAILURE) \
+		return (AUDIO_FAILURE); \
+	\
+	/* set output amp of DAC to max */ \
+	if (audioha_codec_4bit_verb_get(statep, \
+	    caddr, nid, AUDIOHDC_VERB_SET_AMP_MUTE, \
+	    AUDIOHDC_AMP_SET_LR_OUTPUT | AUDIOHDC_GAIN_MAX) == \
+	    AUDIOHD_CODEC_FAILURE) \
+		return (AUDIO_FAILURE); \
+}
+
+
+/*
+ * unmute specified one of a mixer's inputs, and set the
+ * left & right output volume of mixer to specified value
+ */
+#define	AUDIOHD_NODE_INIT_MIXER(statep, caddr, nid_m, in_num) \
+{ \
+	/* unmute input of mixer */ \
+	if (audioha_codec_4bit_verb_get(statep, caddr, nid_m, \
+	    AUDIOHDC_VERB_SET_AMP_MUTE, \
+	    AUDIOHDC_AMP_SET_LR_INPUT | AUDIOHDC_GAIN_MAX | \
+		(in_num << AUDIOHDC_AMP_SET_INDEX_OFFSET)) == \
+	    AUDIOHD_CODEC_FAILURE) \
+		return (AUDIO_FAILURE); \
+	\
+	/* output left amp of mixer */ \
+	(void) audioha_codec_4bit_verb_get(statep, caddr, nid_m, \
+	    AUDIOHDC_VERB_SET_AMP_MUTE, AUDIOHDC_AMP_SET_OUTPUT | \
+	    AUDIOHDC_AMP_SET_LEFT | statep->hda_play_lgain); \
+	\
+	/* output right amp of mixer */ \
+	(void) audioha_codec_4bit_verb_get(statep, caddr, nid_m, \
+	    AUDIOHDC_VERB_SET_AMP_MUTE, AUDIOHDC_AMP_SET_OUTPUT | \
+	    AUDIOHDC_AMP_SET_RIGHT | statep->hda_play_rgain); \
+}
+
+
+/*
+ * enable a pin widget to output
+ */
+#define	AUDIOHD_NODE_ENABLE_PIN_OUT(statep, caddr, nid) \
+{ \
+	uint32_t	lTmp; \
+\
+	lTmp = audioha_codec_verb_get(statep, caddr, nid, \
+	    AUDIOHDC_VERB_GET_PIN_CTRL, 0); \
+	if (lTmp == AUDIOHD_CODEC_FAILURE) \
+		return (AUDIO_FAILURE); \
+	lTmp = audioha_codec_verb_get(statep, caddr, nid, \
+	    AUDIOHDC_VERB_SET_PIN_CTRL, \
+	    (lTmp | AUDIOHDC_PIN_CONTROL_OUT_ENABLE | \
+	    AUDIOHDC_PIN_CONTROL_HP_ENABLE)); \
+	if (lTmp == AUDIOHD_CODEC_FAILURE) \
+		return (AUDIO_FAILURE); \
+}
+
+/*
+ * disable output pin
+ */
+#define	AUDIOHD_NODE_DISABLE_PIN_OUT(statep, caddr, nid) \
+{ \
+	uint32_t	lTmp; \
+\
+	lTmp = audioha_codec_verb_get(statep, caddr, nid, \
+	    AUDIOHDC_VERB_GET_PIN_CTRL, 0); \
+	if (lTmp == AUDIOHD_CODEC_FAILURE) \
+		return (AUDIO_FAILURE); \
+	lTmp = audioha_codec_verb_get(statep, caddr, nid, \
+	    AUDIOHDC_VERB_SET_PIN_CTRL, \
+	    (lTmp & ~AUDIOHDC_PIN_CONTROL_OUT_ENABLE)); \
+	if (lTmp == AUDIOHD_CODEC_FAILURE) \
+		return (AUDIO_FAILURE); \
+}
+
+/*
+ * enable a pin widget to input
+ */
+#define	AUDIOHD_NODE_ENABLE_PIN_IN(statep, caddr, nid) \
+{ \
+	(void) audioha_codec_verb_get(statep, caddr, nid, \
+	    AUDIOHDC_VERB_SET_PIN_CTRL, AUDIOHDC_PIN_CONTROL_IN_ENABLE | 4); \
+}
+
+
+/*
+ * disable input pin
+ */
+#define	AUDIOHD_NODE_DISABLE_PIN_IN(statep, caddr, nid) \
+{ \
+	uint32_t	lTmp; \
+\
+	lTmp = audioha_codec_verb_get(statep, caddr, nid, \
+	    AUDIOHDC_VERB_GET_PIN_CTRL, 0); \
+	if (lTmp == AUDIOHD_CODEC_FAILURE) \
+		return (AUDIO_FAILURE); \
+	lTmp = audioha_codec_verb_get(statep, caddr, nid, \
+	    AUDIOHDC_VERB_SET_PIN_CTRL, \
+	    (lTmp & ~AUDIOHDC_PIN_CONTROL_IN_ENABLE)); \
+	if (lTmp == AUDIOHD_CODEC_FAILURE) \
+		return (AUDIO_FAILURE); \
+}
+
+/*
+ * unmute an output pin
+ */
+#define	AUDIOHD_NODE_UNMUTE_OUT(statep, caddr, nid) \
+{ \
+	if (audioha_codec_4bit_verb_get(statep, \
+	    caddr, nid, AUDIOHDC_VERB_SET_AMP_MUTE, \
+	    AUDIOHDC_AMP_SET_LR_OUTPUT | AUDIOHDC_GAIN_MAX) == \
+	    AUDIOHD_CODEC_FAILURE) \
+		return (AUDIO_FAILURE); \
+}
+
 #ifdef __cplusplus
 }
 #endif