changeset 4093:0cffd8004e71

6472118 add alias to audio810 for NVIDIA MCP51 6501535 add alise to audio810 for AMD 762-768 6518857 audio810.conf should be packaged as an editable file 6521109 Need support for nVidia MCP51 High Definition Audio 6543816 audiohd should not set PCI 0x44 register to 0 for all hardware 6543817 audiohd should not combine two 32-bit write into a 64-bit write 6543819 audiohd mis-defined the offset for stream synchronization register 6544595 audiohd driver is not PAE safe 6546221 changes for a failure symptom in audiohd driver
author cg149915
date Mon, 23 Apr 2007 19:21:35 -0700
parents c859d126a342
children 3ade97212088
files usr/src/pkgdefs/SUNWad810/Makefile usr/src/pkgdefs/SUNWad810/pkginfo.tmpl usr/src/pkgdefs/SUNWad810/postinstall usr/src/pkgdefs/SUNWad810/prototype_com usr/src/pkgdefs/SUNWad810/prototype_i386 usr/src/pkgdefs/SUNWaudiohd/postinstall usr/src/uts/common/io/audio/sada/drv/audiohd/audiohd.c usr/src/uts/common/sys/audio/impl/audiohd_impl.h
diffstat 8 files changed, 146 insertions(+), 49 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/pkgdefs/SUNWad810/Makefile	Mon Apr 23 18:54:07 2007 -0700
+++ b/usr/src/pkgdefs/SUNWad810/Makefile	Mon Apr 23 19:21:35 2007 -0700
@@ -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 2007 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
 # ident	"%Z%%M%	%I%	%E% SMI"
@@ -28,6 +27,7 @@
 
 include ../Makefile.com
 
+DATAFILES += i.preserve
 
 .KEEP_STATE:
 
--- a/usr/src/pkgdefs/SUNWad810/pkginfo.tmpl	Mon Apr 23 18:54:07 2007 -0700
+++ b/usr/src/pkgdefs/SUNWad810/pkginfo.tmpl	Mon Apr 23 19:21:35 2007 -0700
@@ -20,7 +20,7 @@
 #
 
 #
-# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
 # ident	"%Z%%M%	%I%	%E% SMI"
@@ -44,7 +44,7 @@
 VENDOR="Sun Microsystems, Inc."
 HOTLINE="Please contact your local service provider"
 EMAIL=""
-CLASSES="none"
+CLASSES="none preserve"
 BASEDIR=/
 SUNW_PKGVERS="1.0"
 SUNW_PKG_ALLZONES="true"
--- a/usr/src/pkgdefs/SUNWad810/postinstall	Mon Apr 23 18:54:07 2007 -0700
+++ b/usr/src/pkgdefs/SUNWad810/postinstall	Mon Apr 23 19:21:35 2007 -0700
@@ -20,7 +20,7 @@
 # CDDL HEADER END
 #
 #
-# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
 # ident	"%Z%%M%	%I%	%E% SMI"
@@ -36,9 +36,29 @@
 	return $?
 }
 
+
+#
+# Audio810(7d) driver had been released before solaris had
+# update_drv(1M) command so that we have to manually add
+# aliases via echo(1).
+#
+update_driver() {
+	driver=$1
+	aliases=$2
+	for alias in ${aliases}
+	do
+		egrep "^${driver}[ 	]+${alias}" ${BASEDIR}/etc/driver_aliases>/dev/null 2>&1
+		if [ $? -ne 0 ]
+		then
+			 echo "${driver} ${alias}" >> ${BASEDIR}/etc/driver_aliases
+		fi
+	done
+}
+
 EXIT=0
 
 I810_ALIASES="\
+	\"pci1022,7445\" \
 	\"pci1022,746d\" \
 	\"pci8086,2485\" \
 	\"pci8086,24c5\" \
@@ -50,14 +70,18 @@
 	\"pci10de,ea\" \
 	\"pci10de,59\" \
 	\"pci10de,3a\" \
+	\"pci10de,26b\" \
 	"
 	
 case "${ARCH}" in
 	i386)
-		not_installed audio810 || \
-		add_drv -b "${BASEDIR}" -i "${I810_ALIASES}" -n audio810 || \
-		EXIT=1
-
+		not_installed audio810
+		if [ $? -ne 0 ] 
+		then 
+			add_drv -b "${BASEDIR}" -i "${I810_ALIASES}" -n audio810 || EXIT=1
+		else
+			update_driver  audio810 "${I810_ALIASES}" || EXIT=1
+		fi
 	;;
 esac
 
--- a/usr/src/pkgdefs/SUNWad810/prototype_com	Mon Apr 23 18:54:07 2007 -0700
+++ b/usr/src/pkgdefs/SUNWad810/prototype_com	Mon Apr 23 19:21:35 2007 -0700
@@ -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 2007 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
 # ident	"%Z%%M%	%I%	%E% SMI"
@@ -41,6 +40,7 @@
 i depend
 i postinstall
 i preremove
+i i.preserve
 #
 # source locations relative to the prototype file
 #
--- a/usr/src/pkgdefs/SUNWad810/prototype_i386	Mon Apr 23 18:54:07 2007 -0700
+++ b/usr/src/pkgdefs/SUNWad810/prototype_i386	Mon Apr 23 19:21:35 2007 -0700
@@ -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 2007 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
 # ident	"%Z%%M%	%I%	%E% SMI"
@@ -49,6 +48,6 @@
 d none kernel 755 root sys
 d none kernel/drv 755 root sys
 f none kernel/drv/audio810 755 root sys
-f none kernel/drv/audio810.conf 644 root sys
+e preserve kernel/drv/audio810.conf 644 root sys
 d none kernel/drv/amd64 755 root sys
 f none kernel/drv/amd64/audio810 755 root sys
--- a/usr/src/pkgdefs/SUNWaudiohd/postinstall	Mon Apr 23 18:54:07 2007 -0700
+++ b/usr/src/pkgdefs/SUNWaudiohd/postinstall	Mon Apr 23 19:21:35 2007 -0700
@@ -20,7 +20,7 @@
 # CDDL HEADER END
 #
 #
-# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
 # ident	"%Z%%M%	%I%	%E% SMI"
@@ -36,19 +36,36 @@
 	return $?
 }
 
+update_driver() {
+	driver=$1
+	aliases=$2
+	for alias in ${aliases}
+	do
+		egrep "^${driver}[  ]+${alias}" ${BASEDIR}/etc/driver_aliases>/dev/null 2>&1
+		if [ $? -ne 0 ]
+		then
+			update_drv -b "${BASEDIR}" -a -i "${alias}" ${driver}
+		fi
+	done
+}
+
 EXIT=0
 
 AUDIOHD_ALIASES="\
 	\"pci8086,2668\" \
 	\"pci10de,371\" \
+	\"pciclass,0403\" \
 	"
 	
 case "${ARCH}" in
 	i386)
-		not_installed audiohd || \
-		add_drv -b "${BASEDIR}" -i "${AUDIOHD_ALIASES}" -n audiohd || \
-		EXIT=1
-
+		not_installed audiohd
+		if [ $? -ne 0 ]
+		then
+			add_drv -b "${BASEDIR}" -i "${AUDIOHD_ALIASES}" -n audiohd || EXIT=1
+		else
+			update_driver audiohd "${AUDIOHD_ALIASES}" || EXIT=1
+		fi
 	;;
 esac
 
--- a/usr/src/uts/common/io/audio/sada/drv/audiohd/audiohd.c	Mon Apr 23 18:54:07 2007 -0700
+++ b/usr/src/uts/common/io/audio/sada/drv/audiohd/audiohd.c	Mon Apr 23 19:21:35 2007 -0700
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 #pragma ident	"%Z%%M%	%I%	%E% SMI"
@@ -770,7 +770,7 @@
 audiohd_ad_start_play(audiohdl_t ahandle, int stream)
 {
 	audiohd_state_t	*statep;
-	uintptr_t	sbd_phys_addr;
+	uint64_t	sbd_phys_addr;
 	uint8_t		cTmp;
 	uint_t	regbase;
 
@@ -806,16 +806,16 @@
 	statep->hda_flags |= AUDIOHD_PLAY_STARTED;
 
 	if (audiohd_fill_pbuf(statep) != AUDIO_SUCCESS) {
-		audio_sup_log(statep->hda_ahandle, CE_WARN,
-		    "!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);
 	}
 
 	sbd_phys_addr = statep->hda_dma_play_bd.ad_paddr;
-	AUDIOHD_REG_SET64(regbase + AUDIOHD_SDREG_OFFSET_BDLPL, sbd_phys_addr);
+	AUDIOHD_REG_SET32(regbase + AUDIOHD_SDREG_OFFSET_BDLPL,
+	    (uint32_t)sbd_phys_addr);
+	AUDIOHD_REG_SET32(regbase + AUDIOHD_SDREG_OFFSET_BDLPU,
+	    (uint32_t)(sbd_phys_addr >> 32));
 	AUDIOHD_REG_SET16(regbase + AUDIOHD_SDREG_OFFSET_LVI,
 	    AUDIOHD_BDLE_NUMS - 1);
 	AUDIOHD_REG_SET32(regbase + AUDIOHD_SDREG_OFFSET_CBL,
@@ -1072,7 +1072,10 @@
 
 	regbase = statep->hda_record_regbase;
 	sbd_phys_addr = statep->hda_dma_record_bd.ad_paddr;
-	AUDIOHD_REG_SET64(regbase + AUDIOHD_SDREG_OFFSET_BDLPL, sbd_phys_addr);
+	AUDIOHD_REG_SET32(regbase + AUDIOHD_SDREG_OFFSET_BDLPL,
+	    (uint32_t)sbd_phys_addr);
+	AUDIOHD_REG_SET32(regbase + AUDIOHD_SDREG_OFFSET_BDLPU,
+	    (uint32_t)(sbd_phys_addr >> 32));
 	AUDIOHD_REG_SET16(regbase + AUDIOHD_SDREG_OFFSET_FORMAT,
 	    statep->hda_record_format);
 	AUDIOHD_REG_SET16(regbase + AUDIOHD_SDREG_OFFSET_LVI,
@@ -1298,6 +1301,8 @@
 audiohd_init_pci(audiohd_state_t *statep, ddi_device_acc_attr_t *acc_attr)
 {
 	uint16_t	cmdreg;
+	uint16_t	vid;
+	uint8_t		cTmp;
 	dev_info_t	*dip = statep->hda_dip;
 	audiohdl_t	ahandle = statep->hda_ahandle;
 
@@ -1322,8 +1327,26 @@
 	pci_config_put16(statep->hda_pci_handle, PCI_CONF_COMM,
 	    cmdreg | PCI_COMM_MAE | PCI_COMM_ME);
 
-	/* set TCSEL to TC0 */
-	pci_config_put8(statep->hda_pci_handle, 0x44, 0);
+	/*
+	 * Currently, Intel (G)MCH and ICHx chipsets support PCI Express
+	 * QoS. It implemenets two VCs(virtual channels) and allows OS
+	 * software to map 8 traffic classes to the two VCs. Some BIOSes
+	 * initialize HD audio hardware to use TC7 (traffic class 7) and
+	 * map TC7 to VC1 as Intel recommended. However, solaris doesn't
+	 * PCI express QoS yet. As a result, this driver can not work for
+	 * those hardware without touching PCI express control registers.
+	 * So, here, we set TCSEL to 0 so as to use TC0/VC0 (VC0 is always
+	 * enabled and TC0 is always mapped to VC0) for All Intel Hd audio
+	 * controllers.
+	 */
+	vid = pci_config_get16(statep->hda_pci_handle, PCI_CONF_VENID);
+	if (vid == AUDIOHD_VID_INTEL) {
+		cTmp = pci_config_get8(statep->hda_pci_handle,
+		    AUDIOHD_INTEL_PCI_TCSEL);
+		pci_config_put8(statep->hda_pci_handle,
+		    AUDIOHD_INTEL_PCI_TCSEL, (cTmp & 0xf8));
+	}
+
 
 	return (AUDIO_SUCCESS);
 
@@ -1499,7 +1522,7 @@
 		    "!map_regs() addr_bind_handle failed, cookies > 1");
 		goto error_alloc_dma_exit3;
 	}
-	pdma->ad_paddr = (uintptr_t)(cookie.dmac_laddress);
+	pdma->ad_paddr = (uint64_t)(cookie.dmac_laddress);
 	pdma->ad_req_sz = memsize;
 
 	return (AUDIO_SUCCESS);
@@ -1554,15 +1577,15 @@
 static int
 audiohd_init_controller(audiohd_state_t *statep)
 {
-	uintptr_t	addr;
+	uint64_t	addr;
 	uint16_t	gcap;
 	int		retval;
 
 	ddi_dma_attr_t	dma_attr = {
 		DMA_ATTR_V0,		/* version */
 		0,			/* addr_lo */
-		0xffffffffffffffff,	/* addr_hi */
-		0x00000000ffffffff,	/* count_max */
+		0xffffffffffffffffULL,	/* addr_hi */
+		0x00000000ffffffffULL,	/* count_max */
 		128,			/* 128-byte alignment as HD spec */
 		0xfff,			/* burstsize */
 		1,			/* minxfer */
@@ -1574,6 +1597,14 @@
 	};
 
 	gcap = AUDIOHD_REG_GET16(AUDIOHD_REG_GCAP);
+
+	/*
+	 * If the device doesn't support 64-bit DMA, we should not
+	 * allocate DMA memory from 4G above
+	 */
+	if ((gcap & AUDIOHDR_GCAP_64OK) == 0)
+		dma_attr.dma_attr_addr_hi = 0xffffffffUL;
+
 	statep->hda_input_streams = (gcap & AUDIOHDR_GCAP_INSTREAMS) >> 8;
 	statep->hda_output_streams = (gcap & AUDIOHDR_GCAP_OUTSTREAMS) >> 12;
 	statep->hda_streams_nums = statep->hda_input_streams +
@@ -1663,7 +1694,9 @@
 
 	/* Initialize RIRB */
 	addr = statep->hda_dma_rirb.ad_paddr;
-	AUDIOHD_REG_SET64(AUDIOHD_REG_RIRBLBASE, addr);
+	AUDIOHD_REG_SET32(AUDIOHD_REG_RIRBLBASE, (uint32_t)addr);
+	AUDIOHD_REG_SET32(AUDIOHD_REG_RIRBUBASE,
+	    (uint32_t)(addr >> 32));
 	AUDIOHD_REG_SET16(AUDIOHD_REG_RIRBWP, AUDIOHDR_RIRBWP_RESET);
 	AUDIOHD_REG_SET8(AUDIOHD_REG_RIRBSIZE, AUDIOHDR_RIRBSZ_256);
 	AUDIOHD_REG_SET8(AUDIOHD_REG_RIRBCTL, AUDIOHDR_RIRBCTL_DMARUN);
@@ -1671,7 +1704,9 @@
 	/* initialize CORB */
 	addr = statep->hda_dma_corb.ad_paddr;
 	AUDIOHD_REG_SET16(AUDIOHD_REG_CORBRP, AUDIOHDR_CORBRP_RESET);
-	AUDIOHD_REG_SET64(AUDIOHD_REG_CORBLBASE, addr);
+	AUDIOHD_REG_SET32(AUDIOHD_REG_CORBLBASE, (uint32_t)addr);
+	AUDIOHD_REG_SET32(AUDIOHD_REG_CORBUBASE,
+	    (uint32_t)(addr >> 32));
 	AUDIOHD_REG_SET8(AUDIOHD_REG_CORBSIZE, AUDIOHDR_CORBSZ_256);
 	AUDIOHD_REG_SET16(AUDIOHD_REG_CORBWP, 0);
 	AUDIOHD_REG_SET16(AUDIOHD_REG_CORBRP, 0);
@@ -1984,8 +2019,11 @@
  * audiohd_fill_pbuf()
  *
  * Description:
- *	Get pending audio data, and fill out entries of stream
- *	descriptor list for playback.
+ *	Get pending audio data, and fill out entries of stream	descriptor
+ *	list for playback. This routine returns	AUDIO_FAILURE if it doesn't
+ *	fill any audio samples to DMA buffers. This can happen:
+ *		1) when mixer cannot provide any samples;
+ *		2) playback has been stopped during fetching samples;
  */
 static int
 audiohd_fill_pbuf(audiohd_state_t *statep)
@@ -2008,12 +2046,23 @@
 	rs = am_get_audio(statep->hda_ahandle, buf, AUDIO_NO_CHANNEL, samples);
 	mutex_enter(&statep->hda_mutex);
 
+	/* If we cannot get sample */
+	if (rs <= 0) {
+		audio_sup_log(statep->hda_ahandle, CE_WARN,
+		    "!fill_pbuf() failed to get play sample");
+		statep->hda_flags &= ~AUDIOHD_PLAY_STARTED;
+		return (AUDIO_FAILURE);
+	}
+
 	/*
-	 * If we cannot get sample or playback already stopped before
-	 * we re-grab mutex
+	 * Because users can quickly start and stop audio streams, it
+	 * is possible that playback already stopped before we re-grab
+	 * mutex. In this case, we dispose fetched samples, and return
+	 * AUDIO_FAILURE as we didn't get samples.
 	 */
-	if ((rs <= 0) || ((statep->hda_flags & AUDIOHD_PLAY_STARTED) == 0))
+	if ((statep->hda_flags & AUDIOHD_PLAY_STARTED) == 0) {
 		return (AUDIO_FAILURE);
+	}
 
 	for (i = 0; i < AUDIOHD_BDLE_NUMS; i++) {
 		entry->sbde_addr = buf_phys_addr;
--- a/usr/src/uts/common/sys/audio/impl/audiohd_impl.h	Mon Apr 23 18:54:07 2007 -0700
+++ b/usr/src/uts/common/sys/audio/impl/audiohd_impl.h	Mon Apr 23 19:21:35 2007 -0700
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 #ifndef _SYS_AUDIOHD_IMPL_H_
@@ -59,6 +59,14 @@
 #define	AUDIOHD_VID_AD1988A	0x11d41988
 #define	AUDIOHD_VID_AD1988B	0x11d4198b
 
+#define	AUDIOHD_VID_INTEL	0x8086
+
+/*
+ * Only for Intel hardware:
+ * PCI Express traffic class select register in PCI configure space
+ */
+#define	AUDIOHD_INTEL_PCI_TCSEL 0x44
+
 /* vendor-id and device-id for ATI SB450 */
 #define	AUDIOHD_ATI_SB450	0x437d1002
 
@@ -123,7 +131,7 @@
 #define	AUDIOHD_INTSTS_BIT_SINTS	(0x3fffffff)
 
 #define	AUDIOHD_REG_WALCLK		0x30
-#define	AUDIOHD_REG_SYNC		0x34
+#define	AUDIOHD_REG_SYNC		0x38
 
 #define	AUDIOHD_REG_CORBLBASE		0x40
 #define	AUDIOHD_REG_CORBUBASE		0x44
@@ -387,8 +395,8 @@
 typedef struct {
 	ddi_dma_handle_t	ad_dmahdl;
 	ddi_acc_handle_t	ad_acchdl;
-	uintptr_t	ad_vaddr;	/* virtual addr */
-	uintptr_t	ad_paddr;	/* physical addr */
+	caddr_t		ad_vaddr;	/* virtual addr */
+	uint64_t	ad_paddr;	/* physical addr */
 	size_t		ad_req_sz;	/* required size of memory */
 	size_t		ad_real_sz;	/* real size of memory */
 } audiohd_dma_t;