Subject: Re: CS4236B usage, anyone?
To: None <port-i386@NetBSD.ORG>
From: None <Havard.Eidnes@runit.sintef.no>
List: port-i386
Date: 07/19/1998 00:13:16
----Next_Part(Sat_Jul_18_23:54:09_1998)--
Content-Type: Text/Plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

Hm,

I've now (as shown in the "isapnp confusion (?)" thread) tried to
whack the wss_isapnp to work with my CS4236B.  So far I've not
had much luck.  Here's what I've done:

in wss_isapnp_attach() I've rearranged the setting of the I/O
handle so that in the CS4236 case it picks the (presumably)
correct I/O address base/range entry for the WSS codec:

        if (strcmp(ipa->ipa_devident, "CS4236") == 0) {
                sc->sc_ioh = ipa->ipa_io[0].h;
                sc->sc_ad1848.sc_iooffs = 0;
        } else {
                sc->sc_ioh = ipa->ipa_io[1].h;
                sc->sc_ad1848.sc_iooffs = WSS_CODEC;
        }

The rest is as before.

Next, I've tried to make ad1848_probe() recognize the CS4236B,
and that also appears to have its problems.  Basically, it fails
the second test, where it tries to set two ADC volume registers
(indexed register 0 and 1) and read the result back to verify
they're the same as written.

I added a call to ad1848_dump_regs() before test B, and much to
my surprise it reads back the same value from the indexed data
register as was written in the index address register (!).  A
section of the output from the probe looks something like this
(with DEBUG_ISAPNP turned on):

isapnp0: configuring <CS4236, CSC0000, , WSS/SB>
wss0 at isapnp0 port 0x534/4,0x388/4,0x220/16 irq 5 drq 1,0
Found <CS4236, CSC0000, , WSS/SB> config: preferred
4 IO Ports: 16 address bits, alignment 212 min 0x534, max 0x608
4 IO Ports: 16 address bits, alignment 8 min 0x388, max 0x388
16 IO Ports: 16 address bits, alignment 32 min 0x220, max 0x240
IRQ's supported: 5 7 9 E+
DRQ's supported: 1 3 Width: 8-bit Speed: compat Attributes: incr 8 
DRQ's supported: 0 1 3 Width: 8-bit Speed: compat Attributes: incr 8 
ad1848 status=01 regs: (40<-40) 40 (41<-41) 41 (42<-42) 42 (43<-43) 43 (44<-44) 44 (45<-45) 45 (46<-46) 46 (47<-47) 47 (48<-48) 48 (49<-49) 49 (4a<-4a) 4a (4b<-4b) 4b (4c<-4c) 4c (4d<-4d) 4d (4e<-4e) 4e (4f<-4f) 4f (40->aa) (41->45) (40<-40) ad_detect_B (40/ff)
wss0: ad1848_probe failed

First, I don't understand why the index address register reads as
0x1 -- if I read the documentation correctly it should return
0x40 after a recent reset of the chip.  Second, I don't
understand what is going on with the indexed registeres and why I
read back the value put in the index address register when I read
the indexed data register (I've cross-checked that the ISA ports
being referenced by these two are 0x534 and 0x535 respectively).

Hints are welcome.


Regards,

- Havard

PS. The parts of my modified ad1848_probe() which gets executed
follows below.  (Yes, I've enabled the printf()s inside ad_read()
and ad_write().)

----Next_Part(Sat_Jul_18_23:54:09_1998)--
Content-Type: Text/Plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

/*
 * Probe for the ad1848 chip
 */
int
ad1848_probe(sc)
    struct ad1848_softc *sc;
{
    u_char tmp, tmp1 = 0xff, tmp2 = 0xff;
    int i;
    
    /* Is there an ad1848 chip ? */
    sc->MCE_bit = MODE_CHANGE_ENABLE;
    sc->mode = 1;       /* MODE 1 = original ad1848/ad1846/cs4248 */
    
    /*
     * Check that the I/O address is in use.
     *
     * The SP_IN_INIT bit of the base I/O port is known to be 0 after the
     * chip has performed its power-on initialization. Just assume
     * this has happened before the OS is starting.
     *
     * If the I/O address is unused, inb() typically returns 0xff.
     */
    tmp = ADREAD(sc, AD1848_IADDR);
    if (tmp & SP_IN_INIT) { /* Not a AD1848 */
        DPRINTF(("ad_detect_A %x\n", tmp));
        goto bad;
    }

#ifdef AUDIO_DEBUG
    ad1848_dump_regs(sc);
#endif

    /*
     * Test if it's possible to change contents of the indirect registers.
     * Registers 0 and 1 are ADC volume registers. The bit 0x10 is read only
     * so try to avoid using it.
     */
    ad_write(sc, 0, 0xaa);
    ad_write(sc, 1, 0x45);      /* 0x55 with bit 0x10 clear */

    if ((tmp1 = ad_read(sc, 0)) != 0xaa ||
        (tmp2 = ad_read(sc, 1)) != 0x45) {
        DPRINTF(("ad_detect_B (%x/%x)\n", tmp1, tmp2));
        goto bad;
    }

----Next_Part(Sat_Jul_18_23:54:09_1998)----