Subject: kern/18880: clcs driver unable to produce sound with Turtle Beach Santa Cruz soundcard
To: None <gnats-bugs@gnats.netbsd.org>
From: None <b@barkenfelt.com>
List: netbsd-bugs
Date: 11/01/2002 03:50:37
>Number:         18880
>Category:       kern
>Synopsis:       clcs driver unable to produce sound with Turtle Beach Santa Cruz soundcard
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    kern-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Fri Nov 01 03:51:00 PST 2002
>Closed-Date:
>Last-Modified:
>Originator:     Björn Barkenfelt
>Release:        -current
>Organization:
>Environment:
NetBSD phobos 1.6J NetBSD 1.6J (PHOBOS) #17: Thu Oct 31 19:49:06 CET 2002     barken@phobos:/usr/src/sys/arch/i386/compile/PHOBOS i386
>Description:
The clcs driver will attach properly, but is unable to produce any sound output. No errors on playback, just silence.
>How-To-Repeat:

>Fix:
Looking at the FreeBSD driver, it seems that the soundcard in question has the ac97 EAPD (External Amplifier Powerdown) bit inverted. So these cards need to be recognized and the eapd bit set.
The following set of patches fixes the problem:

--- cs4280.c	Wed Oct 30 21:58:30 2002
+++ /usr/src/sys/dev/pci/cs4280.c	Thu Oct 31 19:39:51 2002
@@ -88,6 +88,20 @@
 #define BA1READ4(sc, r) bus_space_read_4((sc)->ba1t, (sc)->ba1h, (r))
 #define BA1WRITE4(sc, r, x) bus_space_write_4((sc)->ba1t, (sc)->ba1h, (r), (x))
 
+struct csSubcard_t
+{
+	u_int16_t subVendorID;
+	u_int16_t subProductID;
+	char * name;
+	u_int16_t inv_eapd;
+};
+
+struct csSubcard_t specialSubcards[] = {
+	{0x5053, 0x3357, "Turtle Beach Santa Cruz", 1}
+	};
+
+#define SPECIAL_SUBCARDS_SIZE (sizeof(specialSubcards)/sizeof(specialSubcards[0]))
+
 /* IF functions for audio driver */
 int  cs4280_match(struct device *, struct cfdata *, void *);
 void cs4280_attach(struct device *, struct device *, void *);
@@ -117,6 +131,8 @@
 int  cs4280_init(struct cs428x_softc *, int);
 void cs4280_clear_fifos(struct cs428x_softc *);
 
+struct csSubcard_t * cs4280_find_subcard( struct pci_attach_args * pa );
+
 #if CS4280_DEBUG > 10
 /* Thease two function is only for checking image loading is succeeded or not. */
 int  cs4280_check_images(struct cs428x_softc *);
@@ -199,6 +215,19 @@
 	return 0;
 }
 
+struct csSubcard_t * cs4280_find_subcard( struct pci_attach_args * pa )
+{
+	pcireg_t reg;
+	int i;
+	reg = pci_conf_read( pa->pa_pc, pa->pa_tag, PCI_SUBSYS_ID_REG );
+	for( i = 0 ; i < SPECIAL_SUBCARDS_SIZE != NULL ;++i ) {
+		if( ( PCI_VENDOR(reg) == specialSubcards[i].subVendorID ) &&
+			( PCI_PRODUCT(reg) == specialSubcards[i].subProductID ) )
+			return &specialSubcards[i];
+	}
+	return NULL;
+}
+
 void
 cs4280_attach(parent, self, aux)
 	struct device *parent;
@@ -215,9 +244,20 @@
 	mixer_ctrl_t ctl;
 	u_int32_t mem;
 	int pci_pwrmgmt_cap_reg, pci_pwrmgmt_csr_reg;
+	struct csSubcard_t * pSubcard;
 
 	pci_devinfo(pa->pa_id, pa->pa_class, 0, devinfo);
 	printf(": %s (rev. 0x%02x)\n", devinfo, PCI_REVISION(pa->pa_class));
+
+	pSubcard = cs4280_find_subcard( pa );
+	if( pSubcard != NULL ) {
+		if( pSubcard->name != NULL )
+			printf("%s: %s\n",sc->sc_dev.dv_xname,pSubcard->name );
+			
+		sc->host_if.inv_eapd = pSubcard->inv_eapd;
+	}
+	else
+		sc->host_if.inv_eapd = 0;
 
 	/* Map I/O register */
 	if (pci_mapreg_map(pa, PCI_BA0, 



--- ac97.c	Wed Oct 30 18:19:58 2002
+++ /usr/src/sys/dev/ic/ac97.c	Thu Oct 31 19:30:49 2002
@@ -974,6 +974,12 @@
 		}
 	}
 
+	if( host_if->inv_eapd == 1 ) {
+		/* Enable inverted EAPD bit. */
+		ac97_read( as, AC97_REG_POWER, &id1 );
+		ac97_write( as, AC97_REG_POWER, id1|0x8000 );
+	}
+
 	ac97_setup_source_info(as);
 
 	DELAY(900 * 1000);

--- ac97var.h	Thu Oct 31 17:30:30 2002
+++ /usr/src/sys/dev/ic/ac97var.h	Thu Oct 31 12:45:36 2002
@@ -47,6 +47,7 @@
 	void (*reset)(void *arg);
 
 	enum ac97_host_flags (*flags)(void *arg);
+	u_int16_t inv_eapd;
 };
 
 /*

>Release-Note:
>Audit-Trail:
>Unformatted: