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: