Subject: kern/24488: Voyotra Santa Cruz sound driver will not function
To: None <gnats-bugs@gnats.NetBSD.org>
From: None <nir.mor@lintronics.com>
List: netbsd-bugs
Date: 02/19/2004 07:38:43
>Number:         24488
>Category:       kern
>Synopsis:       Voyotra Santa Cruz sound driver will not function
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    kern-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Thu Feb 19 07:39:01 UTC 2004
>Closed-Date:
>Last-Modified:
>Originator:     Nir Mor
>Release:        NetBSD 1.6ZK
>Organization:
>Environment:
NetBSD  1.6ZK NetBSD 1.6ZK (GENERIC) #0: Thu Feb 19 08:52:13 GMT 2004   :/usr/src/sys/arch/i386/compile/GENERIC i386
>Description:
Voyotra Santa Cruz sound driver based on clcs does not enable external amplifiler on the ac97 codec.
>How-To-Repeat:

>Fix:
*** sys/dev/ic/ac97.c.orig	Thu Jan  1 18:47:49 2004
--- sys/dev/ic/ac97.c	Thu Jan  1 19:34:07 2004
*************** ac97_attach(struct ac97_host_if *host_if
*** 857,863 ****
  	int error, i, j;
  	u_int32_t id;
  	u_int16_t id1, id2;
! 	u_int16_t extstat, rate;
  	mixer_ctrl_t ctl;
  	void (*initfunc)(struct ac97_softc *);
  #define FLAGBUFLEN	140
--- 857,863 ----
  	int error, i, j;
  	u_int32_t id;
  	u_int16_t id1, id2;
! 	u_int16_t extstat, rate,power;
  	mixer_ctrl_t ctl;
  	void (*initfunc)(struct ac97_softc *);
  #define FLAGBUFLEN	140
*************** ac97_attach(struct ac97_host_if *host_if
*** 992,997 ****
--- 992,1002 ----
  		}
  	}
  
+ 	if (as->host_flags & AC97_HOST_POWER_EAMP) {
+ 		ac97_read(as, AC97_REG_POWER, &power);
+ 		ac97_write(as, AC97_REG_POWER, power|AC97_POWER_EAMP );
+ 	}
+ 
  	ac97_setup_source_info(as);
  
  	DELAY(900 * 1000);*** sys/dev/ic/ac97var.h.orig	Wed Jul  9 03:07:45 2003
--- sys/dev/ic/ac97var.h	Thu Jan  1 18:51:27 2004
*************** struct ac97_codec_if;
*** 35,41 ****
   */
  enum ac97_host_flags {
  	AC97_HOST_DONT_READ = 0x1,
! 	AC97_HOST_SWAPPED_CHANNELS = 0x2	/* l/r is reversed */
  };
  
  struct ac97_host_if {
--- 35,42 ----
   */
  enum ac97_host_flags {
  	AC97_HOST_DONT_READ = 0x1,
! 	AC97_HOST_SWAPPED_CHANNELS = 0x2,	/* l/r is reversed */
! 	AC97_HOST_POWER_EAMP = 0x4		/* need external amp*/
  };
  
  struct ac97_host_if {
*** sys/dev/pci/cs4280.c.orig	Thu Jan  1 18:54:17 2004
--- sys/dev/pci/cs4280.c	Thu Jan  1 19:51:24 2004
*************** __KERNEL_RCSID(0, "$NetBSD: cs4280.c,v 1
*** 88,93 ****
--- 88,107 ----
  #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 external_amp;
+ };
+ 
+ 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 *);
*************** int  cs4280_trigger_input(void *, void *
*** 103,108 ****
--- 117,124 ----
                            void *, struct audio_params *);
  
  void cs4280_reset_codec(void *);
+ enum ac97_host_flags cs4280_flags(void *);
+ 
  
  /* For PowerHook */
  void cs4280_power(int, void *);
*************** int  cs4280_get_portnum_by_name(struct c
*** 117,122 ****
--- 133,140 ----
  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 *);
*************** struct audio_device cs4280_device = {
*** 181,193 ****
  
  
  int
! cs4280_match(parent, match, aux) 
  	struct device *parent;
  	struct cfdata *match;
  	void *aux;
  {
  	struct pci_attach_args *pa = (struct pci_attach_args *)aux;
! 	
  	if (PCI_VENDOR(pa->pa_id) != PCI_VENDOR_CIRRUS)
  		return 0;
  	if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_CIRRUS_CS4280
--- 199,211 ----
  
  
  int
! cs4280_match(parent, match, aux)
  	struct device *parent;
  	struct cfdata *match;
  	void *aux;
  {
  	struct pci_attach_args *pa = (struct pci_attach_args *)aux;
! 
  	if (PCI_VENDOR(pa->pa_id) != PCI_VENDOR_CIRRUS)
  		return 0;
  	if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_CIRRUS_CS4280
*************** cs4280_match(parent, match, aux) 
*** 199,204 ****
--- 217,235 ----
  	return 0;
  }
  
+ struct csSubcard_t * cs4280_find_subcard( struct pci_attach_args * pa )
+ {
+ 	pcireg_t reg;
+ 	u_int32_t i;
+ 	reg = pci_conf_read( pa->pa_pc, pa->pa_tag, PCI_SUBSYS_ID_REG );
+ 	for( i = 0 ; i < SPECIAL_SUBCARDS_SIZE ;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;
*************** cs4280_attach(parent, self, aux)
*** 215,220 ****
--- 246,252 ----
  	mixer_ctrl_t ctl;
  	u_int32_t mem;
  	int pci_pwrmgmt_cap_reg, pci_pwrmgmt_csr_reg;
+ 	struct csSubcard_t * pSubcard;
  
  	aprint_naive(": Audio controller\n");
  *************** cs4280_attach(parent, self, aux)
*** 222,229 ****
  	aprint_normal(": %s (rev. 0x%02x)\n", devinfo,
  	    PCI_REVISION(pa->pa_class));
  
  	/* Map I/O register */
! 	if (pci_mapreg_map(pa, PCI_BA0, 
  	    PCI_MAPREG_TYPE_MEM|PCI_MAPREG_MEM_TYPE_32BIT, 0,
  	    &sc->ba0t, &sc->ba0h, NULL, NULL)) {
  		aprint_error("%s: can't map BA0 space\n", sc->sc_dev.dv_xname);
--- 254,271 ----
  	aprint_normal(": %s (rev. 0x%02x)\n", devinfo,
  	    PCI_REVISION(pa->pa_class));
  
+ 	sc->host_flags=0;
+ 	pSubcard = cs4280_find_subcard( pa );
+ 	if( pSubcard != NULL ) {
+ 		aprint_normal("%s: %s\n",sc->sc_dev.dv_xname,pSubcard->name );
+ 		/* need external amp for Voyotra Santa Cruz*/
+ 		if (pSubcard->external_amp){
+ 			sc->host_flags=AC97_HOST_POWER_EAMP;
+ 		}
+ 	}
+ 
  	/* Map I/O register */
! 	if (pci_mapreg_map(pa, PCI_BA0,
  	    PCI_MAPREG_TYPE_MEM|PCI_MAPREG_MEM_TYPE_32BIT, 0,
  	    &sc->ba0t, &sc->ba0h, NULL, NULL)) {
  		aprint_error("%s: can't map BA0 space\n", sc->sc_dev.dv_xname);
*************** cs4280_attach(parent, self, aux)
*** 244,250 ****
  		pci_pwrmgmt_csr_reg = pci_pwrmgmt_cap_reg + PCI_PMCSR;
  		reg = pci_conf_read(pa->pa_pc, pa->pa_tag,
  		    pci_pwrmgmt_csr_reg);
! 		DPRINTF(("%s: Power State is %d\n", 
  		    sc->sc_dev.dv_xname, reg & PCI_PMCSR_STATE_MASK));
  		if ((reg & PCI_PMCSR_STATE_MASK) != PCI_PMCSR_STATE_D0) {
  			pci_conf_write(pc, pa->pa_tag, pci_pwrmgmt_csr_reg,
--- 286,292 ----
  		pci_pwrmgmt_csr_reg = pci_pwrmgmt_cap_reg + PCI_PMCSR;
  		reg = pci_conf_read(pa->pa_pc, pa->pa_tag,
  		    pci_pwrmgmt_csr_reg);
! 		DPRINTF(("%s: Power State is %d\n",
  		    sc->sc_dev.dv_xname, reg & PCI_PMCSR_STATE_MASK));
  		if ((reg & PCI_PMCSR_STATE_MASK) != PCI_PMCSR_STATE_D0) {
  			pci_conf_write(pc, pa->pa_tag, pci_pwrmgmt_csr_reg,
*************** cs4280_attach(parent, self, aux)
*** 304,309 ****
--- 346,352 ----
  	sc->host_if.read   = cs428x_read_codec;
  	sc->host_if.write  = cs428x_write_codec;
  	sc->host_if.reset  = cs4280_reset_codec;
+ 	sc->host_if.flags  = cs4280_flags;
  	if (ac97_attach(&sc->host_if) != 0) {
  		aprint_error("%s: ac97_attach failed\n", sc->sc_dev.dv_xname);
  		return;
*************** cs4280_reset_codec(void *addr)
*** 977,982 ****
--- 1020,1033 ----
  	}
  }
  
+ enum ac97_host_flags cs4280_flags(void * addr)
+ {
+ 	struct cs428x_softc *sc;
+ 
+ 	sc = addr;
+ 
+ 	return sc->host_flags;
+ }
  
  /* Internal functions */
  
*** sys/dev/pci/cs428x.h.orig	Thu Jan  1 18:58:51 2004
--- sys/dev/pci/cs428x.h	Thu Jan  1 19:01:32 2004
*************** struct cs428x_softc {
*** 126,132 ****
  	/* AC97 CODEC */
  	struct ac97_codec_if *codec_if;
  	struct ac97_host_if host_if;	
! 
  	/* Power Management */
  	char	sc_suspend;
  	void   *sc_powerhook;		/* Power Hook */
--- 126,133 ----
  	/* AC97 CODEC */
  	struct ac97_codec_if *codec_if;
  	struct ac97_host_if host_if;	
! 	enum ac97_host_flags host_flags;
! 	
  	/* Power Management */
  	char	sc_suspend;
  	void   *sc_powerhook;		/* Power Hook */




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