diff options
author | Jacob Meuser <jakemsr@cvs.openbsd.org> | 2010-07-23 11:47:51 +0000 |
---|---|---|
committer | Jacob Meuser <jakemsr@cvs.openbsd.org> | 2010-07-23 11:47:51 +0000 |
commit | 0b8ac1b85c014f66e56ffbc346f5a8f460af6e4e (patch) | |
tree | 021b64888a7f8cb4fa49c40392d1b39e2138f540 /sys | |
parent | 989db1c3d4476c9dcd0db00e87a2e34715a4a0a9 (diff) |
ANSI/style(9), no binary change
Diffstat (limited to 'sys')
-rw-r--r-- | sys/dev/isa/ad1848.c | 2273 |
1 files changed, 1099 insertions, 1174 deletions
diff --git a/sys/dev/isa/ad1848.c b/sys/dev/isa/ad1848.c index 5d46684d965..cdbc01dd54a 100644 --- a/sys/dev/isa/ad1848.c +++ b/sys/dev/isa/ad1848.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ad1848.c,v 1.35 2010/07/15 03:43:11 jakemsr Exp $ */ +/* $OpenBSD: ad1848.c,v 1.36 2010/07/23 11:47:50 jakemsr Exp $ */ /* $NetBSD: ad1848.c,v 1.45 1998/01/30 02:02:38 augustss Exp $ */ /* @@ -103,46 +103,43 @@ int ad1848debug = 0; * Initial values for the indirect registers of CS4248/AD1848. */ static int ad1848_init_values[] = { - /* Left Input Control */ - GAIN_12|INPUT_MIC_GAIN_ENABLE, - /* Right Input Control */ - GAIN_12|INPUT_MIC_GAIN_ENABLE, - ATTEN_12, /* Left Aux #1 Input Control */ - ATTEN_12, /* Right Aux #1 Input Control */ - ATTEN_12, /* Left Aux #2 Input Control */ - ATTEN_12, /* Right Aux #2 Input Control */ - /* bits 5-0 are attenuation select */ - ATTEN_12, /* Left DAC output Control */ - ATTEN_12, /* Right DAC output Control */ - /* Clock and Data Format */ - CLOCK_XTAL1|FMT_PCM8, - /* Interface Config */ - SINGLE_DMA|AUTO_CAL_ENABLE, - INTERRUPT_ENABLE, /* Pin control */ - 0x00, /* Test and Init */ - MODE2, /* Misc control */ - ATTEN_0<<2, /* Digital Mix Control */ - 0, /* Upper base Count */ - 0, /* Lower base Count */ - - /* These are for CS4231 &c. only (additional registers): */ - 0, /* Alt feature 1 */ - 0, /* Alt feature 2 */ - ATTEN_12, /* Left line in */ - ATTEN_12, /* Right line in */ - 0, /* Timer low */ - 0, /* Timer high */ - 0, /* unused */ - 0, /* unused */ - 0, /* IRQ status */ - 0, /* unused */ - /* Mono input (a.k.a speaker) (mic) Control */ - MONO_INPUT_MUTE|ATTEN_6, /* mute speaker by default */ - 0, /* unused */ - 0, /* record format */ - 0, /* Crystal Clock Select */ - 0, /* upper record count */ - 0 /* lower record count */ + GAIN_12 | INPUT_MIC_GAIN_ENABLE, /* Left Input Control */ + GAIN_12 | INPUT_MIC_GAIN_ENABLE, /* Right Input Control */ + ATTEN_12, /* Left Aux #1 Input Control */ + ATTEN_12, /* Right Aux #1 Input Control */ + ATTEN_12, /* Left Aux #2 Input Control */ + ATTEN_12, /* Right Aux #2 Input Control */ + /* bits 5-0 are attenuation select */ + ATTEN_12, /* Left DAC output Control */ + ATTEN_12, /* Right DAC output Control */ + CLOCK_XTAL1 | FMT_PCM8, /* Clock and Data Format */ + SINGLE_DMA | AUTO_CAL_ENABLE, /* Interface Config */ + INTERRUPT_ENABLE, /* Pin control */ + 0x00, /* Test and Init */ + MODE2, /* Misc control */ + ATTEN_0 << 2, /* Digital Mix Control */ + 0, /* Upper base Count */ + 0, /* Lower base Count */ + + /* These are for CS4231 &c. only (additional registers): */ + 0, /* Alt feature 1 */ + 0, /* Alt feature 2 */ + ATTEN_12, /* Left line in */ + ATTEN_12, /* Right line in */ + 0, /* Timer low */ + 0, /* Timer high */ + 0, /* unused */ + 0, /* unused */ + 0, /* IRQ status */ + 0, /* unused */ + + /* Mono input (a.k.a speaker) (mic) Control */ + MONO_INPUT_MUTE|ATTEN_6, /* mute speaker by default */ + 0, /* unused */ + 0, /* record format */ + 0, /* Crystal Clock Select */ + 0, /* upper record count */ + 0 /* lower record count */ }; void ad1848_reset(struct ad1848_softc *); @@ -160,112 +157,103 @@ static void wait_for_calibration(struct ad1848_softc *); #define ADWRITE(sc, addr, data) bus_space_write_1((sc)->sc_iot, (sc)->sc_ioh, (sc)->sc_iooffs+(addr), (data)) static int -ad_read(sc, reg) - struct ad1848_softc *sc; - int reg; +ad_read(struct ad1848_softc *sc, int reg) { - int x, s; + int x, s; - s = splaudio(); - ADWRITE(sc, AD1848_IADDR, (reg & 0xff) | sc->MCE_bit); - x = ADREAD(sc, AD1848_IDATA); - splx(s); - /* printf("(%02x<-%02x) ", reg|sc->MCE_bit, x); */ + s = splaudio(); + ADWRITE(sc, AD1848_IADDR, (reg & 0xff) | sc->MCE_bit); + x = ADREAD(sc, AD1848_IDATA); + splx(s); + /* printf("(%02x<-%02x) ", reg|sc->MCE_bit, x); */ - return x; + return x; } static void -ad_write(sc, reg, data) - struct ad1848_softc *sc; - int reg; - int data; +ad_write(struct ad1848_softc *sc, int reg, int data) { - int s = splaudio(); - ADWRITE(sc, AD1848_IADDR, (reg & 0xff) | sc->MCE_bit); - ADWRITE(sc, AD1848_IDATA, data & 0xff); - splx(s); - /* printf("(%02x->%02x) ", reg|sc->MCE_bit, data); */ + int s = splaudio(); + ADWRITE(sc, AD1848_IADDR, (reg & 0xff) | sc->MCE_bit); + ADWRITE(sc, AD1848_IDATA, data & 0xff); + splx(s); + /* printf("(%02x->%02x) ", reg|sc->MCE_bit, data); */ } static void -ad_set_MCE(sc, state) - struct ad1848_softc *sc; - int state; +ad_set_MCE(struct ad1848_softc *sc, int state) { - if (state) + if (state) sc->MCE_bit = MODE_CHANGE_ENABLE; - else + else sc->MCE_bit = 0; - ADWRITE(sc, AD1848_IADDR, sc->MCE_bit); + ADWRITE(sc, AD1848_IADDR, sc->MCE_bit); } static void -wait_for_calibration(sc) - struct ad1848_softc *sc; +wait_for_calibration(struct ad1848_softc *sc) { - int timeout; - - DPRINTF(("ad1848: Auto calibration started.\n")); - /* - * Wait until the auto calibration process has finished. - * - * 1) Wait until the chip becomes ready (reads don't return SP_IN_INIT). - * 2) Wait until the ACI bit of I11 goes hi and then lo. - * a) With AD1848 alike, ACI goes hi within 5 sample cycles - * and remains hi for ~384 sample periods. - * b) With CS4231 alike, ACI goes hi immediately and remains - * hi for at least 168 sample periods. - */ - timeout = AD1848_TIMO; - while (timeout > 0 && ADREAD(sc, AD1848_IADDR) == SP_IN_INIT) + int timeout; + + DPRINTF(("ad1848: Auto calibration started.\n")); + /* + * Wait until the auto calibration process has finished. + * + * 1) Wait until the chip becomes ready (reads don't return SP_IN_INIT). + * 2) Wait until the ACI bit of I11 goes hi and then lo. + * a) With AD1848 alike, ACI goes hi within 5 sample cycles + * and remains hi for ~384 sample periods. + * b) With CS4231 alike, ACI goes hi immediately and remains + * hi for at least 168 sample periods. + */ + timeout = AD1848_TIMO; + while (timeout > 0 && ADREAD(sc, AD1848_IADDR) == SP_IN_INIT) timeout--; - if (ADREAD(sc, AD1848_IADDR) == SP_IN_INIT) + if (ADREAD(sc, AD1848_IADDR) == SP_IN_INIT) DPRINTF(("ad1848: Auto calibration timed out(1).\n")); - if (!(sc->sc_flags & AD1848_FLAG_32REGS)) { - timeout = AD1848_TIMO; - while (timeout > 0 && - !(ad_read(sc, SP_TEST_AND_INIT) & AUTO_CAL_IN_PROG)) - timeout--; + if (!(sc->sc_flags & AD1848_FLAG_32REGS)) { + timeout = AD1848_TIMO; + while (timeout > 0 && + !(ad_read(sc, SP_TEST_AND_INIT) & AUTO_CAL_IN_PROG)) + timeout--; - if (!(ad_read(sc, SP_TEST_AND_INIT) & AUTO_CAL_IN_PROG)) { - DPRINTF(("ad1848: Auto calibration timed out(2).\n")); + if (!(ad_read(sc, SP_TEST_AND_INIT) & AUTO_CAL_IN_PROG)) { + DPRINTF(("ad1848: Auto calibration timed out(2).\n")); + } } - } - timeout = AD1848_TIMO; - while (timeout > 0 && ad_read(sc, SP_TEST_AND_INIT) & AUTO_CAL_IN_PROG) - timeout--; - if (ad_read(sc, SP_TEST_AND_INIT) & AUTO_CAL_IN_PROG) - DPRINTF(("ad1848: Auto calibration timed out(3).\n")); + timeout = AD1848_TIMO; + while (timeout > 0 && ad_read(sc, SP_TEST_AND_INIT) & AUTO_CAL_IN_PROG) + timeout--; + if (ad_read(sc, SP_TEST_AND_INIT) & AUTO_CAL_IN_PROG) + DPRINTF(("ad1848: Auto calibration timed out(3).\n")); } #ifdef AUDIO_DEBUG void ad1848_dump_regs(struct ad1848_softc *); void -ad1848_dump_regs(sc) - struct ad1848_softc *sc; +ad1848_dump_regs(ad1848_softc *sc) { - int i; - u_char r; - - printf("ad1848 status=%02x", ADREAD(sc, AD1848_STATUS)); - printf(" regs: "); - for (i = 0; i < 16; i++) { - r = ad_read(sc, i); - printf("%02x ", r); - } - if (sc->mode == 2) { - for (i = 16; i < 32; i++) { - r = ad_read(sc, i); - printf("%02x ", r); - } - } - printf("\n"); + int i; + u_char r; + + printf("ad1848 status=%02x", ADREAD(sc, AD1848_STATUS)); + printf(" regs: "); + for (i = 0; i < 16; i++) { + r = ad_read(sc, i); + printf("%02x ", r); + } + if (sc->mode == 2) { + for (i = 16; i < 32; i++) { + r = ad_read(sc, i); + printf("%02x ", r); + } + } + printf("\n"); } #endif @@ -273,229 +261,229 @@ ad1848_dump_regs(sc) * Map and probe for the ad1848 chip */ int -ad1848_mapprobe(sc, iobase) - struct ad1848_softc *sc; - int iobase; +ad1848_mapprobe(struct ad1848_softc *sc, int iobase) { - if (!AD1848_BASE_VALID(iobase)) { + if (!AD1848_BASE_VALID(iobase)) { #ifdef AUDIO_DEBUG - printf("ad1848: configured iobase %04x invalid\n", iobase); + printf("ad1848: configured iobase %04x invalid\n", iobase); #endif - return 0; - } + return 0; + } - sc->sc_iooffs = 0; - /* Map the AD1848 ports */ - if (bus_space_map(sc->sc_iot, iobase, AD1848_NPORT, 0, &sc->sc_ioh)) - return 0; + sc->sc_iooffs = 0; + /* Map the AD1848 ports */ + if (bus_space_map(sc->sc_iot, iobase, AD1848_NPORT, 0, &sc->sc_ioh)) + return 0; - if (!ad1848_probe(sc)) { - bus_space_unmap(sc->sc_iot, sc->sc_ioh, AD1848_NPORT); - return 0; - } else - return 1; + if (!ad1848_probe(sc)) { + bus_space_unmap(sc->sc_iot, sc->sc_ioh, AD1848_NPORT); + return 0; + } else + return 1; } /* * Probe for the ad1848 chip */ int -ad1848_probe(sc) - struct ad1848_softc *sc; +ad1848_probe(struct ad1848_softc *sc) { - u_char tmp, tmp1 = 0xff, tmp2 = 0xff; + u_char tmp, tmp1 = 0xff, tmp2 = 0xff; #if 0 - int i; + int i; #endif - - /* Is there an ad1848 chip ? */ - sc->MCE_bit = MODE_CHANGE_ENABLE; - sc->mode = 1; /* MODE 1 = original ad1848/ad1846/cs4248 */ - sc->sc_flags = 0; - - /* - * 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 */ + + /* Is there an ad1848 chip ? */ + sc->MCE_bit = MODE_CHANGE_ENABLE; + sc->mode = 1; /* MODE 1 = original ad1848/ad1846/cs4248 */ + sc->sc_flags = 0; + + /* + * 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 */ #if 0 - DPRINTF(("ad_detect_A %x\n", tmp)); + DPRINTF(("ad_detect_A %x\n", tmp)); #endif - goto bad; - } - - /* - * 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; - } - - ad_write(sc, 0, 0x45); - ad_write(sc, 1, 0xaa); - - if ((tmp1 = ad_read(sc, 0)) != 0x45 || - (tmp2 = ad_read(sc, 1)) != 0xaa) { - DPRINTF(("ad_detect_C (%x/%x)\n", tmp1, tmp2)); - goto bad; - } - - /* - * The indirect register I12 has some read only bits. Lets - * try to change them. - */ - tmp = ad_read(sc, SP_MISC_INFO); - ad_write(sc, SP_MISC_INFO, (~tmp) & 0x0f); - - if ((tmp & 0x0f) != ((tmp1 = ad_read(sc, SP_MISC_INFO)) & 0x0f)) { - DPRINTF(("ad_detect_D (%x)\n", tmp1)); - goto bad; - } - - /* - * MSB and 4 LSBs of the reg I12 tell the chip revision. - * - * A preliminary version of the AD1846 data sheet stated that it - * used an ID field of 0x0B. The current version, however, - * states that the AD1846 uses ID 0x0A, just like the AD1848K. - * - * this switch statement will need updating as newer clones arrive.... - */ - switch (tmp1 & 0x8f) { - case 0x09: - sc->chip_name = "AD1848J"; - break; - case 0x0A: - sc->chip_name = "AD1848K"; - break; + goto bad; + } + + /* + * 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; + } + + ad_write(sc, 0, 0x45); + ad_write(sc, 1, 0xaa); + + if ((tmp1 = ad_read(sc, 0)) != 0x45 || + (tmp2 = ad_read(sc, 1)) != 0xaa) { + DPRINTF(("ad_detect_C (%x/%x)\n", tmp1, tmp2)); + goto bad; + } + + /* + * The indirect register I12 has some read only bits. Lets + * try to change them. + */ + tmp = ad_read(sc, SP_MISC_INFO); + ad_write(sc, SP_MISC_INFO, (~tmp) & 0x0f); + + if ((tmp & 0x0f) != ((tmp1 = ad_read(sc, SP_MISC_INFO)) & 0x0f)) { + DPRINTF(("ad_detect_D (%x)\n", tmp1)); + goto bad; + } + + /* + * MSB and 4 LSBs of the reg I12 tell the chip revision. + * + * A preliminary version of the AD1846 data sheet stated that it + * used an ID field of 0x0B. The current version, however, + * states that the AD1846 uses ID 0x0A, just like the AD1848K. + * + * this switch statement will need updating as newer clones arrive.... + */ + switch (tmp1 & 0x8f) { + case 0x09: + sc->chip_name = "AD1848J"; + break; + case 0x0A: + sc->chip_name = "AD1848K"; + break; #if 0 /* See above */ - case 0x0B: - sc->chip_name = "AD1846"; - break; + case 0x0B: + sc->chip_name = "AD1846"; + break; #endif - case 0x81: - sc->chip_name = "CS4248revB"; /* or CS4231 rev B; see below */ - break; - case 0x89: - sc->chip_name = "CS4248"; - break; - case 0x8A: - sc->chip_name = "broken"; /* CS4231/AD1845; see below */ - break; - default: - sc->chip_name = "unknown"; - DPRINTF(("ad1848: unknown codec version %#02X\n", (tmp1 & 0x8f))); - } - + case 0x81: + sc->chip_name = "CS4248revB"; /* or CS4231 rev B; see below */ + break; + case 0x89: + sc->chip_name = "CS4248"; + break; + case 0x8A: + sc->chip_name = "broken"; /* CS4231/AD1845; see below */ + break; + default: + sc->chip_name = "unknown"; + DPRINTF(("ad1848: unknown codec version %#02X\n", (tmp1 & 0x8f))); + } + #if 0 - /* - * XXX I don't know why, but this probe fails on an otherwise well-working - * AW35/pro card, so I'll just take it out for now. [niklas@openbsd.org] - */ - - /* - * The original AD1848/CS4248 has just 16 indirect registers. This means - * that I0 and I16 should return the same value (etc.). - * Ensure that the Mode2 enable bit of I12 is 0. Otherwise this test fails - * with CS4231, AD1845, etc. - */ - ad_write(sc, SP_MISC_INFO, 0); /* Mode2 = disabled */ - - for (i = 0; i < 16; i++) - if ((tmp1 = ad_read(sc, i)) != (tmp2 = ad_read(sc, i + 16))) { - if (i != SP_TEST_AND_INIT) { - DPRINTF(("ad_detect_F(%d/%x/%x)\n", i, tmp1, tmp2)); - goto bad; - } + /* + * XXX I don't know why, but this probe fails on an otherwise + * well-working AW35/pro card, so I'll just take it out for now. + * [niklas@openbsd.org] + */ + + /* + * The original AD1848/CS4248 has just 16 indirect registers. This + * means that I0 and I16 should return the same value (etc.). + * Ensure that the Mode2 enable bit of I12 is 0. Otherwise this test + * fails with CS4231, AD1845, etc. + */ + ad_write(sc, SP_MISC_INFO, 0); /* Mode2 = disabled */ + + for (i = 0; i < 16; i++) { + if ((tmp1 = ad_read(sc, i)) != (tmp2 = ad_read(sc, i + 16))) { + if (i != SP_TEST_AND_INIT) { + DPRINTF(("ad_detect_F(%d/%x/%x)\n", i, tmp1, tmp2)); + goto bad; + } + } } #endif - /* - * Try to switch the chip to mode2 (CS4231) by setting the MODE2 bit - * The bit 0x80 is always 1 in CS4248, CS4231, and AD1845. - */ - ad_write(sc, SP_MISC_INFO, MODE2); /* Set mode2, clear 0x80 */ - - tmp1 = ad_read(sc, SP_MISC_INFO); - if ((tmp1 & 0xc0) == (0x80 | MODE2)) { /* - * CS4231 or AD1845 detected - is it? - * - * Verify that setting I2 doesn't change I18. + * Try to switch the chip to mode2 (CS4231) by setting the MODE2 bit + * The bit 0x80 is always 1 in CS4248, CS4231, and AD1845. */ - ad_write(sc, 18, 0x88); /* Set I18 to known value */ - - ad_write(sc, 2, 0x45); - if ((tmp2 = ad_read(sc, 18)) != 0x45) { /* No change -> CS4231? */ - ad_write(sc, 2, 0xaa); - if ((tmp2 = ad_read(sc, 18)) == 0xaa) { /* Rotten bits? */ - DPRINTF(("ad_detect_H(%x)\n", tmp2)); - goto bad; - } - - /* - * It's a CS4231, or another clone with 32 registers. - * Let's find out which by checking I25. - */ - if ((tmp1 & 0x8f) == 0x8a) { - tmp1 = ad_read(sc, CS_VERSION_ID); - switch (tmp1 & 0xe7) { - case 0xA0: - sc->chip_name = "CS4231A"; - break; - case 0x80: - /* XXX I25 no good, AD1845 same as CS4231 */ - sc->chip_name = "CS4231 or AD1845"; - break; - case 0x82: - sc->chip_name = "CS4232"; - break; - case 0xa2: - sc->chip_name = "CS4232C"; - break; - case 0x03: - sc->chip_name = "CS4236/CS4236B"; - break; + ad_write(sc, SP_MISC_INFO, MODE2); /* Set mode2, clear 0x80 */ + + tmp1 = ad_read(sc, SP_MISC_INFO); + if ((tmp1 & 0xc0) == (0x80 | MODE2)) { + /* + * CS4231 or AD1845 detected - is it? + * + * Verify that setting I2 doesn't change I18. + */ + ad_write(sc, 18, 0x88); /* Set I18 to known value */ + + ad_write(sc, 2, 0x45); + if ((tmp2 = ad_read(sc, 18)) != 0x45) { + /* No change -> CS4231? */ + ad_write(sc, 2, 0xaa); + if ((tmp2 = ad_read(sc, 18)) == 0xaa) { + /* Rotten bits? */ + DPRINTF(("ad_detect_H(%x)\n", tmp2)); + goto bad; + } + + /* + * It's a CS4231, or another clone with 32 registers. + * Let's find out which by checking I25. + */ + if ((tmp1 & 0x8f) == 0x8a) { + tmp1 = ad_read(sc, CS_VERSION_ID); + switch (tmp1 & 0xe7) { + case 0xA0: + sc->chip_name = "CS4231A"; + break; + case 0x80: + /* I25 no good, AD1845 same as CS4231 */ + sc->chip_name = "CS4231 or AD1845"; + break; + case 0x82: + sc->chip_name = "CS4232"; + break; + case 0xa2: + sc->chip_name = "CS4232C"; + break; + case 0x03: + sc->chip_name = "CS4236/CS4236B"; + break; + } + } + sc->mode = 2; + sc->sc_flags |= AD1848_FLAG_32REGS; } - } - sc->mode = 2; - sc->sc_flags |= AD1848_FLAG_32REGS; } - } - /* Wait for 1848 to init */ - while(ADREAD(sc, AD1848_IADDR) & SP_IN_INIT) - ; - - /* Wait for 1848 to autocal */ - ADWRITE(sc, AD1848_IADDR, SP_TEST_AND_INIT); - while(ADREAD(sc, AD1848_IDATA) & AUTO_CAL_IN_PROG) - ; + /* Wait for 1848 to init */ + while(ADREAD(sc, AD1848_IADDR) & SP_IN_INIT) + ; - return 1; + /* Wait for 1848 to autocal */ + ADWRITE(sc, AD1848_IADDR, SP_TEST_AND_INIT); + while(ADREAD(sc, AD1848_IDATA) & AUTO_CAL_IN_PROG) + ; + + return 1; bad: - return 0; + return 0; } /* Unmap the I/O ports */ void -ad1848_unmap(sc) - struct ad1848_softc *sc; +ad1848_unmap(struct ad1848_softc *sc) { - bus_space_unmap(sc->sc_iot, sc->sc_ioh, AD1848_NPORT); + bus_space_unmap(sc->sc_iot, sc->sc_ioh, AD1848_NPORT); } /* @@ -503,106 +491,109 @@ ad1848_unmap(sc) * pseudo-device driver . */ void -ad1848_attach(sc) - struct ad1848_softc *sc; +ad1848_attach(struct ad1848_softc *sc) { - int i; - struct ad1848_volume vol_mid = {220, 220}; - struct ad1848_volume vol_0 = {0, 0}; - struct audio_params pparams, rparams; - int timeout; - - sc->sc_playrun = 0; - sc->sc_recrun = 0; - - if (sc->sc_drq != -1) { - if (isa_dmamap_create(sc->sc_isa, sc->sc_drq, MAX_ISADMA, - BUS_DMA_NOWAIT|BUS_DMA_ALLOCNOW)) { - printf("ad1848_attach: can't create map for drq %d\n", - sc->sc_drq); - return; + int i; + struct ad1848_volume vol_mid = {220, 220}; + struct ad1848_volume vol_0 = {0, 0}; + struct audio_params pparams, rparams; + int timeout; + + sc->sc_playrun = 0; + sc->sc_recrun = 0; + + if (sc->sc_drq != -1) { + if (isa_dmamap_create(sc->sc_isa, sc->sc_drq, MAX_ISADMA, + BUS_DMA_NOWAIT|BUS_DMA_ALLOCNOW)) { + printf("ad1848_attach: can't create map for drq %d\n", + sc->sc_drq); + return; + } } - } - if (sc->sc_recdrq != -1 && sc->sc_recdrq != sc->sc_drq) { - if (isa_dmamap_create(sc->sc_isa, sc->sc_recdrq, MAX_ISADMA, - BUS_DMA_NOWAIT|BUS_DMA_ALLOCNOW)) { - printf("ad1848_attach: can't create map for second drq %d\n", - sc->sc_recdrq); - return; + if (sc->sc_recdrq != -1 && sc->sc_recdrq != sc->sc_drq) { + if (isa_dmamap_create(sc->sc_isa, sc->sc_recdrq, MAX_ISADMA, + BUS_DMA_NOWAIT|BUS_DMA_ALLOCNOW)) { + printf("ad1848_attach: can't create map for second drq %d\n", + sc->sc_recdrq); + return; + } + } + + /* Initialize the ad1848... */ + for (i = 0; i < 0x10; i++) { + ad_write(sc, i, ad1848_init_values[i]); + timeout = AD1848_TIMO; + while (timeout > 0 && ADREAD(sc, AD1848_IADDR) & SP_IN_INIT) + timeout--; + } + /* need 2 separate drqs for mode 2 */ + if ((sc->mode == 2) && + ((sc->sc_recdrq == -1) || (sc->sc_recdrq == sc->sc_drq))) { + ad_write(sc, SP_MISC_INFO, ad_read(sc, SP_MISC_INFO) & ~MODE2); + if (!(ad_read(sc, SP_MISC_INFO) & MODE2)) + sc->mode = 1; + } + /* ...and additional CS4231 stuff too */ + if (sc->mode == 2) { + ad_write(sc, SP_INTERFACE_CONFIG, 0); /* disable SINGLE_DMA */ + for (i = 0x10; i < 0x20; i++) { + if (ad1848_init_values[i] != 0) { + ad_write(sc, i, ad1848_init_values[i]); + timeout = AD1848_TIMO; + while (timeout > 0 && + ADREAD(sc, AD1848_IADDR) & SP_IN_INIT) + timeout--; + } + } } - } - - /* Initialize the ad1848... */ - for (i = 0; i < 0x10; i++) { - ad_write(sc, i, ad1848_init_values[i]); - timeout = AD1848_TIMO; - while (timeout > 0 && ADREAD(sc, AD1848_IADDR) & SP_IN_INIT) - timeout--; - } - /* need 2 separate drqs for mode 2 */ - if ((sc->mode == 2) && - ((sc->sc_recdrq == -1) || (sc->sc_recdrq == sc->sc_drq))) { - ad_write(sc, SP_MISC_INFO, ad_read(sc, SP_MISC_INFO) & ~MODE2); - if (!(ad_read(sc, SP_MISC_INFO) & MODE2)) - sc->mode = 1; - } - /* ...and additional CS4231 stuff too */ - if (sc->mode == 2) { - ad_write(sc, SP_INTERFACE_CONFIG, 0); /* disable SINGLE_DMA */ - for (i = 0x10; i < 0x20; i++) - if (ad1848_init_values[i] != 0) { - ad_write(sc, i, ad1848_init_values[i]); - timeout = AD1848_TIMO; - while (timeout > 0 && - ADREAD(sc, AD1848_IADDR) & SP_IN_INIT) - timeout--; - } - } - ad1848_reset(sc); - - pparams = audio_default; - rparams = audio_default; - (void) ad1848_set_params(sc, AUMODE_RECORD|AUMODE_PLAY, 0, &pparams, &rparams); - - /* Set default gains */ - (void) ad1848_set_rec_gain(sc, &vol_mid); - (void) ad1848_set_channel_gain(sc, AD1848_DAC_CHANNEL, &vol_mid); - (void) ad1848_set_channel_gain(sc, AD1848_MONITOR_CHANNEL, &vol_0); - (void) ad1848_set_channel_gain(sc, AD1848_AUX1_CHANNEL, &vol_mid); /* CD volume */ - if (sc->mode == 2) { - (void) ad1848_set_channel_gain(sc, AD1848_AUX2_CHANNEL, &vol_mid); /* CD volume */ - (void) ad1848_set_channel_gain(sc, AD1848_LINE_CHANNEL, &vol_mid); - (void) ad1848_set_channel_gain(sc, AD1848_MONO_CHANNEL, &vol_0); - sc->mute[AD1848_MONO_CHANNEL] = MUTE_ALL; - } else - (void) ad1848_set_channel_gain(sc, AD1848_AUX2_CHANNEL, &vol_0); - - /* Set default port */ - (void) ad1848_set_rec_port(sc, MIC_IN_PORT); - - if (sc->chip_name) - printf(": %s", sc->chip_name); + ad1848_reset(sc); + + pparams = audio_default; + rparams = audio_default; + (void) ad1848_set_params(sc, AUMODE_RECORD|AUMODE_PLAY, 0, + &pparams, &rparams); + + /* Set default gains */ + (void) ad1848_set_rec_gain(sc, &vol_mid); + (void) ad1848_set_channel_gain(sc, AD1848_DAC_CHANNEL, &vol_mid); + (void) ad1848_set_channel_gain(sc, AD1848_MONITOR_CHANNEL, &vol_0); + /* CD volume */ + (void) ad1848_set_channel_gain(sc, AD1848_AUX1_CHANNEL, &vol_mid); + if (sc->mode == 2) { + /* CD volume */ + (void) ad1848_set_channel_gain(sc, AD1848_AUX2_CHANNEL, &vol_mid); + (void) ad1848_set_channel_gain(sc, AD1848_LINE_CHANNEL, &vol_mid); + (void) ad1848_set_channel_gain(sc, AD1848_MONO_CHANNEL, &vol_0); + sc->mute[AD1848_MONO_CHANNEL] = MUTE_ALL; + } else + (void) ad1848_set_channel_gain(sc, AD1848_AUX2_CHANNEL, &vol_0); + + /* Set default port */ + (void) ad1848_set_rec_port(sc, MIC_IN_PORT); + + if (sc->chip_name) + printf(": %s", sc->chip_name); } /* * Various routines to interface to higher level audio driver */ struct ad1848_mixerinfo { - int left_reg; - int right_reg; - int atten_bits; - int atten_mask; -} mixer_channel_info[] = -{ { SP_LEFT_AUX2_CONTROL, SP_RIGHT_AUX2_CONTROL, AUX_INPUT_ATTEN_BITS, - AUX_INPUT_ATTEN_MASK }, - { SP_LEFT_AUX1_CONTROL, SP_RIGHT_AUX1_CONTROL, AUX_INPUT_ATTEN_BITS, - AUX_INPUT_ATTEN_MASK }, - { SP_LEFT_OUTPUT_CONTROL, SP_RIGHT_OUTPUT_CONTROL, - OUTPUT_ATTEN_BITS, OUTPUT_ATTEN_MASK }, - { CS_LEFT_LINE_CONTROL, CS_RIGHT_LINE_CONTROL, LINE_INPUT_ATTEN_BITS, - LINE_INPUT_ATTEN_MASK }, - { CS_MONO_IO_CONTROL, 0, MONO_INPUT_ATTEN_BITS, MONO_INPUT_ATTEN_MASK }, - { SP_DIGITAL_MIX, 0, OUTPUT_ATTEN_BITS, MIX_ATTEN_MASK } + int left_reg; + int right_reg; + int atten_bits; + int atten_mask; +} mixer_channel_info[] = { + { SP_LEFT_AUX2_CONTROL, SP_RIGHT_AUX2_CONTROL, AUX_INPUT_ATTEN_BITS, + AUX_INPUT_ATTEN_MASK }, + { SP_LEFT_AUX1_CONTROL, SP_RIGHT_AUX1_CONTROL, AUX_INPUT_ATTEN_BITS, + AUX_INPUT_ATTEN_MASK }, + { SP_LEFT_OUTPUT_CONTROL, SP_RIGHT_OUTPUT_CONTROL, OUTPUT_ATTEN_BITS, + OUTPUT_ATTEN_MASK }, + { CS_LEFT_LINE_CONTROL, CS_RIGHT_LINE_CONTROL, LINE_INPUT_ATTEN_BITS, + LINE_INPUT_ATTEN_MASK }, + { CS_MONO_IO_CONTROL, 0, MONO_INPUT_ATTEN_BITS, MONO_INPUT_ATTEN_MASK }, + { SP_DIGITAL_MIX, 0, OUTPUT_ATTEN_BITS, MIX_ATTEN_MASK } }; /* @@ -611,626 +602,585 @@ struct ad1848_mixerinfo { * However, the driver occasionally wants to mute devices (e.g. when chaing * sampling rate). These operations should not affect the mute flags. */ - void -ad1848_mute_channel(sc, device, mute) - struct ad1848_softc *sc; - int device; - int mute; +ad1848_mute_channel(struct ad1848_softc *sc, int device, int mute) { - u_char reg; - - reg = ad_read(sc, mixer_channel_info[device].left_reg); - - if (mute & MUTE_LEFT) { - if (device == AD1848_MONITOR_CHANNEL) - ad_write(sc, mixer_channel_info[device].left_reg, reg & 0xFE); - else - ad_write(sc, mixer_channel_info[device].left_reg, reg | 0x80); - } else if (!(sc->mute[device] & MUTE_LEFT)) { - if (device == AD1848_MONITOR_CHANNEL) - ad_write(sc, mixer_channel_info[device].left_reg, reg | 0x01); - else - ad_write(sc, mixer_channel_info[device].left_reg, reg & ~0x80); - } - - if (!mixer_channel_info[device].right_reg) { - return; - } - - reg = ad_read(sc, mixer_channel_info[device].right_reg); - - if (mute & MUTE_RIGHT) - ad_write(sc, mixer_channel_info[device].right_reg, reg | 0x80); - else if (!(sc->mute[device] & MUTE_RIGHT)) { - ad_write(sc, mixer_channel_info[device].right_reg, reg & ~0x80); - } -} + u_char reg; + + reg = ad_read(sc, mixer_channel_info[device].left_reg); + + if (mute & MUTE_LEFT) { + if (device == AD1848_MONITOR_CHANNEL) { + ad_write(sc, mixer_channel_info[device].left_reg, + reg & 0xFE); + } else { + ad_write(sc, mixer_channel_info[device].left_reg, + reg | 0x80); + } + } else if (!(sc->mute[device] & MUTE_LEFT)) { + if (device == AD1848_MONITOR_CHANNEL) { + ad_write(sc, mixer_channel_info[device].left_reg, + reg | 0x01); + } else { + ad_write(sc, mixer_channel_info[device].left_reg, + reg & ~0x80); + } + } + + if (!mixer_channel_info[device].right_reg) { + return; + } + reg = ad_read(sc, mixer_channel_info[device].right_reg); + + if (mute & MUTE_RIGHT) { + ad_write(sc, mixer_channel_info[device].right_reg, reg | 0x80); + } else if (!(sc->mute[device] & MUTE_RIGHT)) { + ad_write(sc, mixer_channel_info[device].right_reg, reg & ~0x80); + } +} int -ad1848_set_channel_gain(sc, device, gp) - struct ad1848_softc *sc; - int device; - struct ad1848_volume *gp; +ad1848_set_channel_gain(struct ad1848_softc *sc, int device, + struct ad1848_volume *gp) { - struct ad1848_mixerinfo *info = &mixer_channel_info[device]; - u_char reg; - u_int atten; + struct ad1848_mixerinfo *info = &mixer_channel_info[device]; + u_char reg; + u_int atten; - sc->gains[device] = *gp; + sc->gains[device] = *gp; - atten = ((AUDIO_MAX_GAIN - gp->left) * info->atten_bits)/AUDIO_MAX_GAIN; + atten = ((AUDIO_MAX_GAIN - gp->left) * info->atten_bits) / + AUDIO_MAX_GAIN; - reg = ad_read(sc, info->left_reg) & (info->atten_mask); - if (device == AD1848_MONITOR_CHANNEL) - reg |= ((atten & info->atten_bits) << 2); - else - reg |= ((atten & info->atten_bits)); + reg = ad_read(sc, info->left_reg) & (info->atten_mask); + if (device == AD1848_MONITOR_CHANNEL) + reg |= ((atten & info->atten_bits) << 2); + else + reg |= ((atten & info->atten_bits)); - ad_write(sc, info->left_reg, reg); + ad_write(sc, info->left_reg, reg); - if (!info->right_reg) - return (0); + if (!info->right_reg) + return 0; - atten = ((AUDIO_MAX_GAIN - gp->right) * info->atten_bits)/AUDIO_MAX_GAIN; - reg = ad_read(sc, info->right_reg); - reg &= (info->atten_mask); - ad_write(sc, info->right_reg, (atten& info->atten_bits)|reg); + atten = ((AUDIO_MAX_GAIN - gp->right) * info->atten_bits) / + AUDIO_MAX_GAIN; + reg = ad_read(sc, info->right_reg); + reg &= (info->atten_mask); + ad_write(sc, info->right_reg, (atten & info->atten_bits) | reg); - return(0); + return 0; } - int -ad1848_get_device_gain(sc, device, gp) - struct ad1848_softc *sc; - int device; - struct ad1848_volume *gp; +ad1848_get_device_gain(struct ad1848_softc *sc, int device, + struct ad1848_volume *gp) { - *gp = sc->gains[device]; - return(0); + *gp = sc->gains[device]; + return 0; } int -ad1848_get_rec_gain(sc, gp) - struct ad1848_softc *sc; - struct ad1848_volume *gp; +ad1848_get_rec_gain(struct ad1848_softc *sc, struct ad1848_volume *gp) { - *gp = sc->rec_gain; - return(0); + *gp = sc->rec_gain; + return 0; } int -ad1848_set_rec_gain(sc, gp) - struct ad1848_softc *sc; - struct ad1848_volume *gp; +ad1848_set_rec_gain(struct ad1848_softc *sc, struct ad1848_volume *gp) { - u_char reg, gain; - - DPRINTF(("ad1848_set_rec_gain: %d:%d\n", gp->left, gp->right)); + u_char reg, gain; + + DPRINTF(("ad1848_set_rec_gain: %d:%d\n", gp->left, gp->right)); - sc->rec_gain = *gp; + sc->rec_gain = *gp; - gain = (gp->left * GAIN_22_5)/AUDIO_MAX_GAIN; - reg = ad_read(sc, SP_LEFT_INPUT_CONTROL); - reg &= INPUT_GAIN_MASK; - ad_write(sc, SP_LEFT_INPUT_CONTROL, (gain&0x0f)|reg); + gain = (gp->left * GAIN_22_5) / AUDIO_MAX_GAIN; + reg = ad_read(sc, SP_LEFT_INPUT_CONTROL); + reg &= INPUT_GAIN_MASK; + ad_write(sc, SP_LEFT_INPUT_CONTROL, (gain & 0x0f) | reg); - gain = (gp->right * GAIN_22_5)/AUDIO_MAX_GAIN; - reg = ad_read(sc, SP_RIGHT_INPUT_CONTROL); - reg &= INPUT_GAIN_MASK; - ad_write(sc, SP_RIGHT_INPUT_CONTROL, (gain&0x0f)|reg); + gain = (gp->right * GAIN_22_5) / AUDIO_MAX_GAIN; + reg = ad_read(sc, SP_RIGHT_INPUT_CONTROL); + reg &= INPUT_GAIN_MASK; + ad_write(sc, SP_RIGHT_INPUT_CONTROL, (gain & 0x0f) | reg); - return(0); + return 0; } - void -ad1848_mute_monitor(addr, mute) - void *addr; - int mute; +ad1848_mute_monitor(void *addr, int mute) { struct ad1848_softc *sc = addr; DPRINTF(("ad1848_mute_monitor: %smuting\n", mute ? "" : "un")); if (sc->mode == 2) { - ad1848_mute_channel(sc, AD1848_DAC_CHANNEL, mute ? MUTE_ALL : 0); - ad1848_mute_channel(sc, AD1848_MONO_CHANNEL, mute ? MUTE_MONO : 0); - ad1848_mute_channel(sc, AD1848_LINE_CHANNEL, mute ? MUTE_ALL : 0); + ad1848_mute_channel(sc, AD1848_DAC_CHANNEL, + mute ? MUTE_ALL : 0); + ad1848_mute_channel(sc, AD1848_MONO_CHANNEL, + mute ? MUTE_MONO : 0); + ad1848_mute_channel(sc, AD1848_LINE_CHANNEL, + mute ? MUTE_ALL : 0); } - + ad1848_mute_channel(sc, AD1848_AUX2_CHANNEL, mute ? MUTE_ALL : 0); ad1848_mute_channel(sc, AD1848_AUX1_CHANNEL, mute ? MUTE_ALL : 0); } int -ad1848_set_mic_gain(sc, gp) - struct ad1848_softc *sc; - struct ad1848_volume *gp; +ad1848_set_mic_gain(struct ad1848_softc *sc, struct ad1848_volume *gp) { - u_char reg; - - DPRINTF(("cs4231_set_mic_gain: %d\n", gp->left)); - - if (gp->left > AUDIO_MAX_GAIN/2) { - sc->mic_gain_on = 1; - reg = ad_read(sc, SP_LEFT_INPUT_CONTROL); - ad_write(sc, SP_LEFT_INPUT_CONTROL, reg | INPUT_MIC_GAIN_ENABLE); - } else { - sc->mic_gain_on = 0; - reg = ad_read(sc, SP_LEFT_INPUT_CONTROL); - ad_write(sc, SP_LEFT_INPUT_CONTROL, reg & ~INPUT_MIC_GAIN_ENABLE); - } - - return(0); + u_char reg; + + DPRINTF(("cs4231_set_mic_gain: %d\n", gp->left)); + + if (gp->left > AUDIO_MAX_GAIN / 2) { + sc->mic_gain_on = 1; + reg = ad_read(sc, SP_LEFT_INPUT_CONTROL); + ad_write(sc, SP_LEFT_INPUT_CONTROL, + reg | INPUT_MIC_GAIN_ENABLE); + } else { + sc->mic_gain_on = 0; + reg = ad_read(sc, SP_LEFT_INPUT_CONTROL); + ad_write(sc, SP_LEFT_INPUT_CONTROL, + reg & ~INPUT_MIC_GAIN_ENABLE); + } + + return 0; } int -ad1848_get_mic_gain(sc, gp) - struct ad1848_softc *sc; - struct ad1848_volume *gp; +ad1848_get_mic_gain(struct ad1848_softc *sc, struct ad1848_volume *gp) { if (sc->mic_gain_on) gp->left = gp->right = AUDIO_MAX_GAIN; else gp->left = gp->right = AUDIO_MIN_GAIN; - return(0); + + return 0; } static ad1848_devmap_t *ad1848_mixer_find_dev(ad1848_devmap_t *, int, mixer_ctrl_t *); static ad1848_devmap_t * -ad1848_mixer_find_dev(map, cnt, cp) - ad1848_devmap_t *map; - int cnt; - mixer_ctrl_t *cp; - +ad1848_mixer_find_dev(ad1848_devmap_t *map, int cnt, mixer_ctrl_t *cp) { - int idx; - - for (idx = 0; idx < cnt; idx++) { - if (map[idx].id == cp->dev) { - return (&map[idx]); - } - } - return (NULL); + int idx; + + for (idx = 0; idx < cnt; idx++) { + if (map[idx].id == cp->dev) { + return &map[idx]; + } + } + return NULL; } -int -ad1848_mixer_get_port(ac, map, cnt, cp) - struct ad1848_softc *ac; - struct ad1848_devmap *map; - int cnt; - mixer_ctrl_t *cp; +int +ad1848_mixer_get_port(struct ad1848_softc *ac, struct ad1848_devmap *map, + int cnt, mixer_ctrl_t *cp) { - ad1848_devmap_t *entry; - struct ad1848_volume vol; - int error = EINVAL; - int dev; - - if (!(entry = ad1848_mixer_find_dev(map, cnt, cp))) - return (ENXIO); - - dev = entry->dev; - - switch (entry->kind) { - case AD1848_KIND_LVL: - if (cp->type != AUDIO_MIXER_VALUE) - break; - - if (dev < AD1848_AUX2_CHANNEL || - dev > AD1848_MONITOR_CHANNEL) - break; - - if (cp->un.value.num_channels != 1 && - mixer_channel_info[dev].right_reg == 0) - break; - - error = ad1848_get_device_gain(ac, dev, &vol); - if (!error) - ad1848_from_vol(cp, &vol); - - break; - - case AD1848_KIND_MUTE: - if (cp->type != AUDIO_MIXER_ENUM) break; - - cp->un.ord = ac->mute[dev] ? 1 : 0; - error = 0; - break; - - case AD1848_KIND_RECORDGAIN: - if (cp->type != AUDIO_MIXER_VALUE) break; - - error = ad1848_get_rec_gain(ac, &vol); - if (!error) - ad1848_from_vol(cp, &vol); - - break; - - case AD1848_KIND_MICGAIN: - if (cp->type != AUDIO_MIXER_VALUE) break; - - error = ad1848_get_mic_gain(ac, &vol); - if (!error) - ad1848_from_vol(cp, &vol); - - break; - - case AD1848_KIND_RECORDSOURCE: - if (cp->type != AUDIO_MIXER_ENUM) break; - cp->un.ord = ad1848_get_rec_port(ac); - error = 0; - break; - default: - printf ("Invalid kind\n"); - break; - } + ad1848_devmap_t *entry; + struct ad1848_volume vol; + int error = EINVAL; + int dev; + + if (!(entry = ad1848_mixer_find_dev(map, cnt, cp))) + return (ENXIO); + + dev = entry->dev; + + switch (entry->kind) { + case AD1848_KIND_LVL: + if (cp->type != AUDIO_MIXER_VALUE) + break; + if (dev < AD1848_AUX2_CHANNEL || + dev > AD1848_MONITOR_CHANNEL) + break; + if (cp->un.value.num_channels != 1 && + mixer_channel_info[dev].right_reg == 0) + break; + error = ad1848_get_device_gain(ac, dev, &vol); + if (!error) + ad1848_from_vol(cp, &vol); + break; + + case AD1848_KIND_MUTE: + if (cp->type != AUDIO_MIXER_ENUM) + break; + cp->un.ord = ac->mute[dev] ? 1 : 0; + error = 0; + break; + + case AD1848_KIND_RECORDGAIN: + if (cp->type != AUDIO_MIXER_VALUE) + break; + error = ad1848_get_rec_gain(ac, &vol); + if (!error) + ad1848_from_vol(cp, &vol); + break; + + case AD1848_KIND_MICGAIN: + if (cp->type != AUDIO_MIXER_VALUE) + break; + error = ad1848_get_mic_gain(ac, &vol); + if (!error) + ad1848_from_vol(cp, &vol); + break; + + case AD1848_KIND_RECORDSOURCE: + if (cp->type != AUDIO_MIXER_ENUM) + break; + cp->un.ord = ad1848_get_rec_port(ac); + error = 0; + break; + + default: + printf("Invalid kind\n"); + break; + } - return (error); + return error; } -int -ad1848_mixer_set_port(ac, map, cnt, cp) - struct ad1848_softc *ac; - struct ad1848_devmap *map; - int cnt; - mixer_ctrl_t *cp; +int +ad1848_mixer_set_port(struct ad1848_softc *ac, struct ad1848_devmap *map, + int cnt, mixer_ctrl_t *cp) { - ad1848_devmap_t *entry; - struct ad1848_volume vol; - int error = EINVAL; - int dev; - - if (!(entry = ad1848_mixer_find_dev(map, cnt, cp))) - return (ENXIO); - - dev = entry->dev; - - switch (entry->kind) { - case AD1848_KIND_LVL: - if (cp->type != AUDIO_MIXER_VALUE) - break; - - if (dev < AD1848_AUX2_CHANNEL || - dev > AD1848_MONITOR_CHANNEL) - break; - - if (cp->un.value.num_channels != 1 && - mixer_channel_info[dev].right_reg == 0) - break; - - ad1848_to_vol(cp, &vol); - error = ad1848_set_channel_gain(ac, dev, &vol); - break; - - case AD1848_KIND_MUTE: - if (cp->type != AUDIO_MIXER_ENUM) break; - - ac->mute[dev] = (cp->un.ord ? MUTE_ALL : 0); - ad1848_mute_channel(ac, dev, ac->mute[dev]); - error = 0; - break; - - case AD1848_KIND_RECORDGAIN: - if (cp->type != AUDIO_MIXER_VALUE) break; - - ad1848_to_vol(cp, &vol); - error = ad1848_set_rec_gain(ac, &vol); - break; - - case AD1848_KIND_MICGAIN: - if (cp->type != AUDIO_MIXER_VALUE) break; - - ad1848_to_vol(cp, &vol); - error = ad1848_set_mic_gain(ac, &vol); - break; - - case AD1848_KIND_RECORDSOURCE: - if (cp->type != AUDIO_MIXER_ENUM) break; - - error = ad1848_set_rec_port(ac, cp->un.ord); - break; - default: - printf ("Invalid kind\n"); - break; - } - - return (error); -} + ad1848_devmap_t *entry; + struct ad1848_volume vol; + int error = EINVAL; + int dev; + + if (!(entry = ad1848_mixer_find_dev(map, cnt, cp))) + return (ENXIO); + + dev = entry->dev; + + switch (entry->kind) { + case AD1848_KIND_LVL: + if (cp->type != AUDIO_MIXER_VALUE) + break; + if (dev < AD1848_AUX2_CHANNEL || + dev > AD1848_MONITOR_CHANNEL) + break; + if (cp->un.value.num_channels != 1 && + mixer_channel_info[dev].right_reg == 0) + break; + ad1848_to_vol(cp, &vol); + error = ad1848_set_channel_gain(ac, dev, &vol); + break; + + case AD1848_KIND_MUTE: + if (cp->type != AUDIO_MIXER_ENUM) + break; + ac->mute[dev] = (cp->un.ord ? MUTE_ALL : 0); + ad1848_mute_channel(ac, dev, ac->mute[dev]); + error = 0; + break; + + case AD1848_KIND_RECORDGAIN: + if (cp->type != AUDIO_MIXER_VALUE) + break; + ad1848_to_vol(cp, &vol); + error = ad1848_set_rec_gain(ac, &vol); + break; + + case AD1848_KIND_MICGAIN: + if (cp->type != AUDIO_MIXER_VALUE) + break; + ad1848_to_vol(cp, &vol); + error = ad1848_set_mic_gain(ac, &vol); + break; + + case AD1848_KIND_RECORDSOURCE: + if (cp->type != AUDIO_MIXER_ENUM) + break; + error = ad1848_set_rec_port(ac, cp->un.ord); + break; + + default: + printf("Invalid kind\n"); + break; + } + return (error); +} int -ad1848_query_encoding(addr, fp) - void *addr; - struct audio_encoding *fp; +ad1848_query_encoding(void *addr, struct audio_encoding *fp) { - struct ad1848_softc *sc = addr; - - switch (fp->index) { - case 0: - strlcpy(fp->name, AudioEmulaw, sizeof fp->name); - fp->encoding = AUDIO_ENCODING_ULAW; - fp->precision = 8; - fp->flags = 0; - break; - case 1: - strlcpy(fp->name, AudioEalaw, sizeof fp->name); - fp->encoding = AUDIO_ENCODING_ALAW; - fp->precision = 8; - fp->flags = 0; - break; - case 2: - strlcpy(fp->name, AudioEslinear_le, sizeof fp->name); - fp->encoding = AUDIO_ENCODING_SLINEAR_LE; - fp->precision = 16; - fp->flags = 0; - break; - case 3: - strlcpy(fp->name, AudioEulinear, sizeof fp->name); - fp->encoding = AUDIO_ENCODING_ULINEAR; - fp->precision = 8; - fp->flags = 0; - break; - - case 4: /* only on CS4231 */ - strlcpy(fp->name, AudioEslinear_be, sizeof fp->name); - fp->encoding = AUDIO_ENCODING_SLINEAR_BE; - fp->precision = 16; - fp->flags = sc->mode == 1 ? AUDIO_ENCODINGFLAG_EMULATED : 0; - break; - - /* emulate some modes */ - case 5: - strlcpy(fp->name, AudioEslinear, sizeof fp->name); - fp->encoding = AUDIO_ENCODING_SLINEAR; - fp->precision = 8; - fp->flags = AUDIO_ENCODINGFLAG_EMULATED; - break; - case 6: - strlcpy(fp->name, AudioEulinear_le, sizeof fp->name); - fp->encoding = AUDIO_ENCODING_ULINEAR_LE; - fp->precision = 16; - fp->flags = AUDIO_ENCODINGFLAG_EMULATED; - break; - case 7: - strlcpy(fp->name, AudioEulinear_be, sizeof fp->name); - fp->encoding = AUDIO_ENCODING_ULINEAR_BE; - fp->precision = 16; - fp->flags = AUDIO_ENCODINGFLAG_EMULATED; - break; - - case 8: /* only on CS4231 */ - if (sc->mode == 1) - return EINVAL; - strlcpy(fp->name, AudioEadpcm, sizeof fp->name); - fp->encoding = AUDIO_ENCODING_ADPCM; - fp->precision = 8; - fp->flags = 0; - break; - default: - return EINVAL; - /*NOTREACHED*/ - } - fp->bps = AUDIO_BPS(fp->precision); - fp->msb = 1; - - return (0); + struct ad1848_softc *sc = addr; + + switch (fp->index) { + case 0: + strlcpy(fp->name, AudioEmulaw, sizeof fp->name); + fp->encoding = AUDIO_ENCODING_ULAW; + fp->precision = 8; + fp->flags = 0; + break; + case 1: + strlcpy(fp->name, AudioEalaw, sizeof fp->name); + fp->encoding = AUDIO_ENCODING_ALAW; + fp->precision = 8; + fp->flags = 0; + break; + case 2: + strlcpy(fp->name, AudioEslinear_le, sizeof fp->name); + fp->encoding = AUDIO_ENCODING_SLINEAR_LE; + fp->precision = 16; + fp->flags = 0; + break; + case 3: + strlcpy(fp->name, AudioEulinear, sizeof fp->name); + fp->encoding = AUDIO_ENCODING_ULINEAR; + fp->precision = 8; + fp->flags = 0; + break; + case 4: /* only on CS4231 */ + strlcpy(fp->name, AudioEslinear_be, sizeof fp->name); + fp->encoding = AUDIO_ENCODING_SLINEAR_BE; + fp->precision = 16; + fp->flags = sc->mode == 1 ? AUDIO_ENCODINGFLAG_EMULATED : 0; + break; + + /* emulate some modes */ + case 5: + strlcpy(fp->name, AudioEslinear, sizeof fp->name); + fp->encoding = AUDIO_ENCODING_SLINEAR; + fp->precision = 8; + fp->flags = AUDIO_ENCODINGFLAG_EMULATED; + break; + case 6: + strlcpy(fp->name, AudioEulinear_le, sizeof fp->name); + fp->encoding = AUDIO_ENCODING_ULINEAR_LE; + fp->precision = 16; + fp->flags = AUDIO_ENCODINGFLAG_EMULATED; + break; + case 7: + strlcpy(fp->name, AudioEulinear_be, sizeof fp->name); + fp->encoding = AUDIO_ENCODING_ULINEAR_BE; + fp->precision = 16; + fp->flags = AUDIO_ENCODINGFLAG_EMULATED; + break; + case 8: /* only on CS4231 */ + if (sc->mode == 1) + return EINVAL; + strlcpy(fp->name, AudioEadpcm, sizeof fp->name); + fp->encoding = AUDIO_ENCODING_ADPCM; + fp->precision = 8; + fp->flags = 0; + break; + default: + return EINVAL; + /*NOTREACHED*/ + } + fp->bps = AUDIO_BPS(fp->precision); + fp->msb = 1; + + return (0); } int -ad1848_set_params(addr, setmode, usemode, p, r) - void *addr; - int setmode, usemode; - struct audio_params *p, *r; +ad1848_set_params(void *addr, int setmode, int usemode, struct audio_params *p, + struct audio_params *r) { - struct ad1848_softc *sc = addr; - int error, bits, enc; - void (*pswcode)(void *, u_char *buf, int cnt); - void (*rswcode)(void *, u_char *buf, int cnt); + struct ad1848_softc *sc = addr; + int error, bits, enc; + void (*pswcode)(void *, u_char *buf, int cnt); + void (*rswcode)(void *, u_char *buf, int cnt); - DPRINTF(("ad1848_set_params: %d %d %d %ld\n", + DPRINTF(("ad1848_set_params: %d %d %d %ld\n", p->encoding, p->precision, p->channels, p->sample_rate)); - enc = p->encoding; - pswcode = rswcode = 0; - switch (enc) { - case AUDIO_ENCODING_SLINEAR_LE: - if (p->precision == 8) { - enc = AUDIO_ENCODING_ULINEAR_LE; - pswcode = rswcode = change_sign8; - } - break; - case AUDIO_ENCODING_SLINEAR_BE: - if (p->precision == 16 && sc->mode == 1) { - enc = AUDIO_ENCODING_SLINEAR_LE; - pswcode = rswcode = swap_bytes; - } - break; - case AUDIO_ENCODING_ULINEAR_LE: - if (p->precision == 16) { - enc = AUDIO_ENCODING_SLINEAR_LE; - pswcode = rswcode = change_sign16_le; + enc = p->encoding; + pswcode = rswcode = 0; + switch (enc) { + case AUDIO_ENCODING_SLINEAR_LE: + if (p->precision == 8) { + enc = AUDIO_ENCODING_ULINEAR_LE; + pswcode = rswcode = change_sign8; + } + break; + case AUDIO_ENCODING_SLINEAR_BE: + if (p->precision == 16 && sc->mode == 1) { + enc = AUDIO_ENCODING_SLINEAR_LE; + pswcode = rswcode = swap_bytes; + } + break; + case AUDIO_ENCODING_ULINEAR_LE: + if (p->precision == 16) { + enc = AUDIO_ENCODING_SLINEAR_LE; + pswcode = rswcode = change_sign16_le; + } + break; + case AUDIO_ENCODING_ULINEAR_BE: + if (p->precision == 16) { + enc = AUDIO_ENCODING_SLINEAR_LE; + pswcode = swap_bytes_change_sign16_le; + rswcode = change_sign16_swap_bytes_le; + } + break; } - break; - case AUDIO_ENCODING_ULINEAR_BE: - if (p->precision == 16) { - enc = AUDIO_ENCODING_SLINEAR_LE; - pswcode = swap_bytes_change_sign16_le; - rswcode = change_sign16_swap_bytes_le; + switch (enc) { + case AUDIO_ENCODING_ULAW: + bits = FMT_ULAW; + break; + case AUDIO_ENCODING_ALAW: + bits = FMT_ALAW; + break; + case AUDIO_ENCODING_ADPCM: + bits = FMT_ADPCM; + break; + case AUDIO_ENCODING_SLINEAR_LE: + if (p->precision == 16) + bits = FMT_TWOS_COMP; + else + return EINVAL; + break; + case AUDIO_ENCODING_SLINEAR_BE: + if (p->precision == 16) + bits = FMT_TWOS_COMP_BE; + else + return EINVAL; + break; + case AUDIO_ENCODING_ULINEAR_LE: + if (p->precision == 8) + bits = FMT_PCM8; + else + return EINVAL; + break; + default: + return EINVAL; } - break; - } - switch (enc) { - case AUDIO_ENCODING_ULAW: - bits = FMT_ULAW; - break; - case AUDIO_ENCODING_ALAW: - bits = FMT_ALAW; - break; - case AUDIO_ENCODING_ADPCM: - bits = FMT_ADPCM; - break; - case AUDIO_ENCODING_SLINEAR_LE: - if (p->precision == 16) - bits = FMT_TWOS_COMP; - else - return EINVAL; - break; - case AUDIO_ENCODING_SLINEAR_BE: - if (p->precision == 16) - bits = FMT_TWOS_COMP_BE; - else - return EINVAL; - break; - case AUDIO_ENCODING_ULINEAR_LE: - if (p->precision == 8) - bits = FMT_PCM8; - else - return EINVAL; - break; - default: - return EINVAL; - } - if (p->channels < 1 || p->channels > 2) - return EINVAL; + if (p->channels < 1 || p->channels > 2) + return EINVAL; - error = ad1848_set_speed(sc, &p->sample_rate); - if (error) - return error; + error = ad1848_set_speed(sc, &p->sample_rate); + if (error) + return error; - p->sw_code = pswcode; - r->sw_code = rswcode; - p->bps = AUDIO_BPS(p->precision); - r->bps = AUDIO_BPS(r->precision); - p->msb = 1; - r->msb = 1; + p->sw_code = pswcode; + r->sw_code = rswcode; + p->bps = AUDIO_BPS(p->precision); + r->bps = AUDIO_BPS(r->precision); + p->msb = 1; + r->msb = 1; - sc->format_bits = bits; - sc->channels = p->channels; - sc->precision = p->precision; - sc->need_commit = 1; + sc->format_bits = bits; + sc->channels = p->channels; + sc->precision = p->precision; + sc->need_commit = 1; - DPRINTF(("ad1848_set_params succeeded, bits=%x\n", bits)); - return (0); + DPRINTF(("ad1848_set_params succeeded, bits=%x\n", bits)); + return (0); } int -ad1848_set_rec_port(sc, port) - struct ad1848_softc *sc; - int port; +ad1848_set_rec_port(struct ad1848_softc *sc, int port) { - u_char inp, reg; - - DPRINTF(("ad1848_set_rec_port: 0x%x\n", port)); - - if (port == MIC_IN_PORT) { - inp = MIC_INPUT; - } - else if (port == LINE_IN_PORT) { - inp = LINE_INPUT; - } - else if (port == DAC_IN_PORT) { - inp = MIXED_DAC_INPUT; - } - else if (sc->mode == 2 && port == AUX1_IN_PORT) { - inp = AUX_INPUT; - } - else - return(EINVAL); - - reg = ad_read(sc, SP_LEFT_INPUT_CONTROL); - reg &= INPUT_SOURCE_MASK; - ad_write(sc, SP_LEFT_INPUT_CONTROL, (inp|reg)); - - reg = ad_read(sc, SP_RIGHT_INPUT_CONTROL); - reg &= INPUT_SOURCE_MASK; - ad_write(sc, SP_RIGHT_INPUT_CONTROL, (inp|reg)); - - sc->rec_port = port; - - return(0); + u_char inp, reg; + + DPRINTF(("ad1848_set_rec_port: 0x%x\n", port)); + + if (port == MIC_IN_PORT) { + inp = MIC_INPUT; + } else if (port == LINE_IN_PORT) { + inp = LINE_INPUT; + } else if (port == DAC_IN_PORT) { + inp = MIXED_DAC_INPUT; + } else if (sc->mode == 2 && port == AUX1_IN_PORT) { + inp = AUX_INPUT; + } else + return EINVAL; + + reg = ad_read(sc, SP_LEFT_INPUT_CONTROL); + reg &= INPUT_SOURCE_MASK; + ad_write(sc, SP_LEFT_INPUT_CONTROL, (inp | reg)); + + reg = ad_read(sc, SP_RIGHT_INPUT_CONTROL); + reg &= INPUT_SOURCE_MASK; + ad_write(sc, SP_RIGHT_INPUT_CONTROL, (inp | reg)); + + sc->rec_port = port; + + return 0; } int -ad1848_get_rec_port(sc) - struct ad1848_softc *sc; +ad1848_get_rec_port(struct ad1848_softc *sc) { - return(sc->rec_port); + return sc->rec_port; } int -ad1848_round_blocksize(addr, blk) - void *addr; - int blk; +ad1848_round_blocksize(void *addr, int blk) { - /* Round to a multiple of the biggest sample size. */ - blk = (blk + 3) & -4; + /* Round to a multiple of the biggest sample size. */ + blk = (blk + 3) & -4; - return (blk); + return blk; } int -ad1848_open(addr, flags) - void *addr; - int flags; +ad1848_open(void *addr, int flags) { - struct ad1848_softc *sc = addr; + struct ad1848_softc *sc = addr; - DPRINTF(("ad1848_open: sc=%p\n", sc)); + DPRINTF(("ad1848_open: sc=%p\n", sc)); - sc->sc_pintr = sc->sc_parg = NULL; - sc->sc_rintr = sc->sc_rarg = NULL; + sc->sc_pintr = sc->sc_parg = NULL; + sc->sc_rintr = sc->sc_rarg = NULL; - /* Enable interrupts */ - DPRINTF(("ad1848_open: enable intrs\n")); - ad_write(sc, SP_PIN_CONTROL, INTERRUPT_ENABLE|ad_read(sc, SP_PIN_CONTROL)); + /* Enable interrupts */ + DPRINTF(("ad1848_open: enable intrs\n")); + ad_write(sc, SP_PIN_CONTROL, + INTERRUPT_ENABLE | ad_read(sc, SP_PIN_CONTROL)); #ifdef AUDIO_DEBUG - if (ad1848debug > 2) - ad1848_dump_regs(sc); + if (ad1848debug > 2) + ad1848_dump_regs(sc); #endif - return 0; + return 0; } /* * Close function is called at splaudio(). */ void -ad1848_close(addr) - void *addr; +ad1848_close(void *addr) { - struct ad1848_softc *sc = addr; - u_char r; + struct ad1848_softc *sc = addr; + u_char r; - ad1848_halt_output(sc); - ad1848_halt_input(sc); + ad1848_halt_output(sc); + ad1848_halt_input(sc); - sc->sc_pintr = NULL; - sc->sc_rintr = NULL; + sc->sc_pintr = NULL; + sc->sc_rintr = NULL; - DPRINTF(("ad1848_close: stop DMA\n")); + DPRINTF(("ad1848_close: stop DMA\n")); - ad_write(sc, SP_LOWER_BASE_COUNT, (u_char)0); - ad_write(sc, SP_UPPER_BASE_COUNT, (u_char)0); + ad_write(sc, SP_LOWER_BASE_COUNT, (u_char)0); + ad_write(sc, SP_UPPER_BASE_COUNT, (u_char)0); - /* Disable interrupts */ - DPRINTF(("ad1848_close: disable intrs\n")); - ad_write(sc, SP_PIN_CONTROL, - ad_read(sc, SP_PIN_CONTROL) & ~INTERRUPT_ENABLE); + /* Disable interrupts */ + DPRINTF(("ad1848_close: disable intrs\n")); + ad_write(sc, SP_PIN_CONTROL, + ad_read(sc, SP_PIN_CONTROL) & ~INTERRUPT_ENABLE); - DPRINTF(("ad1848_close: disable capture and playback\n")); - r = ad_read(sc, SP_INTERFACE_CONFIG); - r &= ~(CAPTURE_ENABLE|PLAYBACK_ENABLE); - ad_write(sc, SP_INTERFACE_CONFIG, r); + DPRINTF(("ad1848_close: disable capture and playback\n")); + r = ad_read(sc, SP_INTERFACE_CONFIG); + r &= ~(CAPTURE_ENABLE | PLAYBACK_ENABLE); + ad_write(sc, SP_INTERFACE_CONFIG, r); #ifdef AUDIO_DEBUG - if (ad1848debug > 2) - ad1848_dump_regs(sc); + if (ad1848debug > 2) + ad1848_dump_regs(sc); #endif } @@ -1238,356 +1188,342 @@ ad1848_close(addr) * Lower-level routines */ int -ad1848_commit_settings(addr) - void *addr; +ad1848_commit_settings(void *addr) { - struct ad1848_softc *sc = addr; - int timeout; - u_char fs; - int s; + struct ad1848_softc *sc = addr; + int timeout; + u_char fs; + int s; - if (!sc->need_commit) - return 0; + if (!sc->need_commit) + return 0; - s = splaudio(); - - ad1848_mute_monitor(sc, 1); - - ad_set_MCE(sc, 1); /* Enables changes to the format select reg */ + s = splaudio(); - fs = sc->speed_bits | sc->format_bits; + ad1848_mute_monitor(sc, 1); - if (sc->channels == 2) - fs |= FMT_STEREO; + /* Enables changes to the format select reg */ + ad_set_MCE(sc, 1); - ad_write(sc, SP_CLOCK_DATA_FORMAT, fs); + fs = sc->speed_bits | sc->format_bits; - /* - * If mode == 2 (CS4231), set I28 also. It's the capture format register. - */ - if (sc->mode == 2) { - /* Gravis Ultrasound MAX SDK sources says something about errata - * sheets, with the implication that these inb()s are necessary. + if (sc->channels == 2) + fs |= FMT_STEREO; + + ad_write(sc, SP_CLOCK_DATA_FORMAT, fs); + + /* + * If mode == 2 (CS4231), set I28 also. It's the capture format + * register. */ - (void)ADREAD(sc, AD1848_IDATA); - (void)ADREAD(sc, AD1848_IDATA); + if (sc->mode == 2) { + /* Gravis Ultrasound MAX SDK sources says something about + * errata sheets, with the implication that these inb()s + * are necessary. + */ + (void)ADREAD(sc, AD1848_IDATA); + (void)ADREAD(sc, AD1848_IDATA); + + /* + * Write to I8 starts resynchronization. Wait until it + * completes. + */ + timeout = AD1848_TIMO; + while (timeout > 0 && ADREAD(sc, AD1848_IADDR) == SP_IN_INIT) + timeout--; + + ad_write(sc, CS_REC_FORMAT, fs); + /* Gravis Ultrasound MAX SDK sources says something about + * errata sheets, with the implication that these inb()s + * are necessary. + */ + (void)ADREAD(sc, AD1848_IDATA); + (void)ADREAD(sc, AD1848_IDATA); + /* Now wait for resync for capture side of the house */ + } /* * Write to I8 starts resynchronization. Wait until it completes. */ timeout = AD1848_TIMO; while (timeout > 0 && ADREAD(sc, AD1848_IADDR) == SP_IN_INIT) - timeout--; + timeout--; - ad_write(sc, CS_REC_FORMAT, fs); - /* Gravis Ultrasound MAX SDK sources says something about errata - * sheets, with the implication that these inb()s are necessary. - */ - (void)ADREAD(sc, AD1848_IDATA); - (void)ADREAD(sc, AD1848_IDATA); - /* Now wait for resync for capture side of the house */ - } - /* - * Write to I8 starts resynchronization. Wait until it completes. - */ - timeout = AD1848_TIMO; - while (timeout > 0 && ADREAD(sc, AD1848_IADDR) == SP_IN_INIT) - timeout--; + if (ADREAD(sc, AD1848_IADDR) == SP_IN_INIT) + printf("ad1848_commit: Auto calibration timed out\n"); - if (ADREAD(sc, AD1848_IADDR) == SP_IN_INIT) - printf("ad1848_commit: Auto calibration timed out\n"); + /* + * Starts the calibration process and enters playback mode after it. + */ + ad_set_MCE(sc, 0); + wait_for_calibration(sc); - /* - * Starts the calibration process and - * enters playback mode after it. - */ - ad_set_MCE(sc, 0); - wait_for_calibration(sc); + ad1848_mute_monitor(sc, 0); - ad1848_mute_monitor(sc, 0); + splx(s); + + sc->need_commit = 0; - splx(s); - - sc->need_commit = 0; - return 0; + return 0; } void -ad1848_reset(sc) - struct ad1848_softc *sc; +ad1848_reset(struct ad1848_softc *sc) { - u_char r; - - DPRINTF(("ad1848_reset\n")); - - /* Clear the PEN and CEN bits */ - r = ad_read(sc, SP_INTERFACE_CONFIG); - r &= ~(CAPTURE_ENABLE|PLAYBACK_ENABLE); - ad_write(sc, SP_INTERFACE_CONFIG, r); - - /* Clear interrupt status */ - if (sc->mode == 2) + u_char r; + + DPRINTF(("ad1848_reset\n")); + + /* Clear the PEN and CEN bits */ + r = ad_read(sc, SP_INTERFACE_CONFIG); + r &= ~(CAPTURE_ENABLE | PLAYBACK_ENABLE); + ad_write(sc, SP_INTERFACE_CONFIG, r); + + /* Clear interrupt status */ + if (sc->mode == 2) ad_write(sc, CS_IRQ_STATUS, 0); - ADWRITE(sc, AD1848_STATUS, 0); + ADWRITE(sc, AD1848_STATUS, 0); #ifdef AUDIO_DEBUG - if (ad1848debug > 2) - ad1848_dump_regs(sc); + if (ad1848debug > 2) + ad1848_dump_regs(sc); #endif } int -ad1848_set_speed(sc, argp) - struct ad1848_softc *sc; - u_long *argp; +ad1848_set_speed(struct ad1848_softc *sc, u_long *argp) { - /* - * The sampling speed is encoded in the least significant nible of I8. The - * LSB selects the clock source (0=24.576 MHz, 1=16.9344 MHz) and other - * three bits select the divisor (indirectly): - * - * The available speeds are in the following table. Keep the speeds in - * the increasing order. - */ - typedef struct { - int speed; - u_char bits; - } speed_struct; - u_long arg = *argp; - - static speed_struct speed_table[] = { - {5510, (0 << 1) | 1}, - {5510, (0 << 1) | 1}, - {6620, (7 << 1) | 1}, - {8000, (0 << 1) | 0}, - {9600, (7 << 1) | 0}, - {11025, (1 << 1) | 1}, - {16000, (1 << 1) | 0}, - {18900, (2 << 1) | 1}, - {22050, (3 << 1) | 1}, - {27420, (2 << 1) | 0}, - {32000, (3 << 1) | 0}, - {33075, (6 << 1) | 1}, - {37800, (4 << 1) | 1}, - {44100, (5 << 1) | 1}, - {48000, (6 << 1) | 0} - }; - - int i, n, selected = -1; - - n = sizeof(speed_table) / sizeof(speed_struct); - - if (arg < speed_table[0].speed) - selected = 0; - if (arg > speed_table[n - 1].speed) - selected = n - 1; - - for (i = 1 /*really*/ ; selected == -1 && i < n; i++) - if (speed_table[i].speed == arg) - selected = i; - else if (speed_table[i].speed > arg) { - int diff1, diff2; - - diff1 = arg - speed_table[i - 1].speed; - diff2 = speed_table[i].speed - arg; - - if (diff1 < diff2) - selected = i - 1; - else - selected = i; + /* + * The sampling speed is encoded in the least significant nible of I8. + * The LSB selects the clock source (0=24.576 MHz, 1=16.9344 MHz) and + * other three bits select the divisor (indirectly): + * + * The available speeds are in the following table. Keep the speeds in + * the increasing order. + */ + typedef struct { + int speed; + u_char bits; + } speed_struct; + u_long arg = *argp; + + static speed_struct speed_table[] = { + {5510, (0 << 1) | 1}, + {5510, (0 << 1) | 1}, + {6620, (7 << 1) | 1}, + {8000, (0 << 1) | 0}, + {9600, (7 << 1) | 0}, + {11025, (1 << 1) | 1}, + {16000, (1 << 1) | 0}, + {18900, (2 << 1) | 1}, + {22050, (3 << 1) | 1}, + {27420, (2 << 1) | 0}, + {32000, (3 << 1) | 0}, + {33075, (6 << 1) | 1}, + {37800, (4 << 1) | 1}, + {44100, (5 << 1) | 1}, + {48000, (6 << 1) | 0} + }; + + int i, n, selected = -1; + + n = sizeof(speed_table) / sizeof(speed_struct); + + if (arg < speed_table[0].speed) + selected = 0; + if (arg > speed_table[n - 1].speed) + selected = n - 1; + + for (i = 1 /*really*/ ; selected == -1 && i < n; i++) + if (speed_table[i].speed == arg) + selected = i; + else if (speed_table[i].speed > arg) { + int diff1, diff2; + + diff1 = arg - speed_table[i - 1].speed; + diff2 = speed_table[i].speed - arg; + + if (diff1 < diff2) + selected = i - 1; + else + selected = i; } - if (selected == -1) { - printf("ad1848: Can't find speed???\n"); - selected = 3; - } + if (selected == -1) { + printf("ad1848: Can't find speed???\n"); + selected = 3; + } - sc->speed_bits = speed_table[selected].bits; - sc->need_commit = 1; - *argp = speed_table[selected].speed; + sc->speed_bits = speed_table[selected].bits; + sc->need_commit = 1; + *argp = speed_table[selected].speed; - return (0); + return 0; } /* * Halt a DMA in progress. */ int -ad1848_halt_output(addr) - void *addr; +ad1848_halt_output(void *addr) { - struct ad1848_softc *sc = addr; - u_char reg; + struct ad1848_softc *sc = addr; + u_char reg; - DPRINTF(("ad1848: ad1848_halt_output\n")); + DPRINTF(("ad1848: ad1848_halt_output\n")); - reg = ad_read(sc, SP_INTERFACE_CONFIG); - ad_write(sc, SP_INTERFACE_CONFIG, (reg & ~PLAYBACK_ENABLE)); + reg = ad_read(sc, SP_INTERFACE_CONFIG); + ad_write(sc, SP_INTERFACE_CONFIG, (reg & ~PLAYBACK_ENABLE)); - if (sc->sc_playrun == 1) { - isa_dmaabort(sc->sc_isa, sc->sc_drq); - sc->sc_playrun = 0; - } + if (sc->sc_playrun == 1) { + isa_dmaabort(sc->sc_isa, sc->sc_drq); + sc->sc_playrun = 0; + } - return(0); + return 0; } int -ad1848_halt_input(addr) - void *addr; +ad1848_halt_input(void *addr) { - struct ad1848_softc *sc = addr; - u_char reg; - - DPRINTF(("ad1848: ad1848_halt_input\n")); + struct ad1848_softc *sc = addr; + u_char reg; - reg = ad_read(sc, SP_INTERFACE_CONFIG); - ad_write(sc, SP_INTERFACE_CONFIG, (reg & ~CAPTURE_ENABLE)); + DPRINTF(("ad1848: ad1848_halt_input\n")); - if (sc->sc_recrun == 1) { - isa_dmaabort(sc->sc_isa, sc->sc_recdrq); - sc->sc_recrun = 0; - } + reg = ad_read(sc, SP_INTERFACE_CONFIG); + ad_write(sc, SP_INTERFACE_CONFIG, (reg & ~CAPTURE_ENABLE)); + + if (sc->sc_recrun == 1) { + isa_dmaabort(sc->sc_isa, sc->sc_recdrq); + sc->sc_recrun = 0; + } - return(0); + return 0; } int -ad1848_trigger_input(addr, start, end, blksize, intr, arg, param) - void *addr; - void *start, *end; - int blksize; - void (*intr)(void *); - void *arg; - struct audio_params *param; +ad1848_trigger_input(void *addr, void *start, void *end, int blksize, + void (*intr)(void *), void *arg, struct audio_params *param) { - struct ad1848_softc *sc = addr; - u_char reg; - - if (sc->sc_recdrq == -1) { - DPRINTF(("ad1848_trigger_input: invalid recording drq\n")); - return ENXIO; - } - - isa_dmastart(sc->sc_isa, sc->sc_recdrq, start, (char *)end - (char *)start, - NULL, DMAMODE_READ | DMAMODE_LOOP, BUS_DMA_NOWAIT); - - sc->sc_recrun = 1; - sc->sc_rintr = intr; - sc->sc_rarg = arg; - - blksize = (blksize * NBBY) / (param->precision * param->channels) - 1; - - if (sc->mode == 2) { - ad_write(sc, CS_LOWER_REC_CNT, (blksize & 0xff)); - ad_write(sc, CS_UPPER_REC_CNT, ((blksize >> 8) & 0xff)); - } else { - ad_write(sc, SP_LOWER_BASE_COUNT, blksize & 0xff); - ad_write(sc, SP_UPPER_BASE_COUNT, (blksize >> 8) & 0xff); - } - - reg = ad_read(sc, SP_INTERFACE_CONFIG); - ad_write(sc, SP_INTERFACE_CONFIG, (CAPTURE_ENABLE|reg)); + struct ad1848_softc *sc = addr; + u_char reg; + + if (sc->sc_recdrq == -1) { + DPRINTF(("ad1848_trigger_input: invalid recording drq\n")); + return ENXIO; + } + + isa_dmastart(sc->sc_isa, sc->sc_recdrq, start, + (char *)end - (char *)start, NULL, DMAMODE_READ | DMAMODE_LOOP, + BUS_DMA_NOWAIT); + + sc->sc_recrun = 1; + sc->sc_rintr = intr; + sc->sc_rarg = arg; + + blksize = (blksize * NBBY) / (param->precision * param->channels) - 1; + + if (sc->mode == 2) { + ad_write(sc, CS_LOWER_REC_CNT, (blksize & 0xff)); + ad_write(sc, CS_UPPER_REC_CNT, ((blksize >> 8) & 0xff)); + } else { + ad_write(sc, SP_LOWER_BASE_COUNT, blksize & 0xff); + ad_write(sc, SP_UPPER_BASE_COUNT, (blksize >> 8) & 0xff); + } + + reg = ad_read(sc, SP_INTERFACE_CONFIG); + ad_write(sc, SP_INTERFACE_CONFIG, (CAPTURE_ENABLE | reg)); #ifdef AUDIO_DEBUG - if (ad1848debug > 1) - printf("ad1848_trigger_input: started capture\n"); + if (ad1848debug > 1) + printf("ad1848_trigger_input: started capture\n"); #endif - - return 0; + + return 0; } int -ad1848_trigger_output(addr, start, end, blksize, intr, arg, param) - void *addr; - void *start, *end; - int blksize; - void (*intr)(void *); - void *arg; - struct audio_params *param; +ad1848_trigger_output(void *addr, void *start, void *end, int blksize, + void (*intr)(void *), void *arg, struct audio_params *param) { - struct ad1848_softc *sc = addr; - u_char reg; - - isa_dmastart(sc->sc_isa, sc->sc_drq, start, (char *)end - (char *)start, - NULL, DMAMODE_WRITE | DMAMODE_LOOP, BUS_DMA_NOWAIT); + struct ad1848_softc *sc = addr; + u_char reg; - sc->sc_playrun = 1; - sc->sc_pintr = intr; - sc->sc_parg = arg; + isa_dmastart(sc->sc_isa, sc->sc_drq, start, + (char *)end - (char *)start, NULL, + DMAMODE_WRITE | DMAMODE_LOOP, BUS_DMA_NOWAIT); - blksize = (blksize * NBBY) / (param->precision * param->channels) - 1; + sc->sc_playrun = 1; + sc->sc_pintr = intr; + sc->sc_parg = arg; - ad_write(sc, SP_LOWER_BASE_COUNT, blksize & 0xff); - ad_write(sc, SP_UPPER_BASE_COUNT, (blksize >> 8) & 0xff); + blksize = (blksize * NBBY) / (param->precision * param->channels) - 1; - reg = ad_read(sc, SP_INTERFACE_CONFIG); - ad_write(sc, SP_INTERFACE_CONFIG, (PLAYBACK_ENABLE|reg)); + ad_write(sc, SP_LOWER_BASE_COUNT, blksize & 0xff); + ad_write(sc, SP_UPPER_BASE_COUNT, (blksize >> 8) & 0xff); + + reg = ad_read(sc, SP_INTERFACE_CONFIG); + ad_write(sc, SP_INTERFACE_CONFIG, (PLAYBACK_ENABLE | reg)); #ifdef AUDIO_DEBUG - if (ad1848debug > 1) - printf("ad1848_trigger_output: started playback\n"); + if (ad1848debug > 1) + printf("ad1848_trigger_output: started playback\n"); #endif - - return 0; + + return 0; } int -ad1848_intr(arg) - void *arg; +ad1848_intr(void *arg) { - struct ad1848_softc *sc = arg; - int retval = 0; - u_char status; - - /* Get intr status */ - status = ADREAD(sc, AD1848_STATUS); - + struct ad1848_softc *sc = arg; + int retval = 0; + u_char status; + + /* Get intr status */ + status = ADREAD(sc, AD1848_STATUS); + #ifdef AUDIO_DEBUG - if (ad1848debug > 1) - printf("ad1848_intr: mode=%d pintr=%p prun=%d rintr=%p rrun=%d status=0x%x\n", - sc->mode, sc->sc_pintr, sc->sc_playrun, sc->sc_rintr, sc->sc_recrun, status); + if (ad1848debug > 1) + printf("ad1848_intr: mode=%d pintr=%p prun=%d rintr=%p rrun=%d status=0x%x\n", + sc->mode, sc->sc_pintr, sc->sc_playrun, sc->sc_rintr, sc->sc_recrun, status); #endif - - /* Handle interrupt */ - if ((status & INTERRUPT_STATUS) != 0) { - if (sc->mode == 2) { - status = ad_read(sc, CS_IRQ_STATUS); + + /* Handle interrupt */ + if ((status & INTERRUPT_STATUS) != 0) { + if (sc->mode == 2) { + status = ad_read(sc, CS_IRQ_STATUS); #ifdef AUDIO_DEBUG - if (ad1848debug > 2) - printf("ad1848_intr: cs_irq_status=0x%x (play=0x%x rec0x%x)\n", - status, CS_IRQ_PI, CS_IRQ_CI); + if (ad1848debug > 2) + printf("ad1848_intr: cs_irq_status=0x%x (play=0x%x rec0x%x)\n", + status, CS_IRQ_PI, CS_IRQ_CI); #endif - if ((status & CS_IRQ_PI) && sc->sc_playrun) { - (*sc->sc_pintr)(sc->sc_parg); - retval = 1; - } - if ((status & CS_IRQ_CI) && sc->sc_recrun) { - (*sc->sc_rintr)(sc->sc_rarg); - retval = 1; - } - } else { - if (sc->sc_playrun) { - (*sc->sc_pintr)(sc->sc_parg); - retval = 1; - } else if (sc->sc_recrun) { - (*sc->sc_rintr)(sc->sc_rarg); - retval = 1; + if ((status & CS_IRQ_PI) && sc->sc_playrun) { + (*sc->sc_pintr)(sc->sc_parg); + retval = 1; + } + if ((status & CS_IRQ_CI) && sc->sc_recrun) { + (*sc->sc_rintr)(sc->sc_rarg); + retval = 1; + } + } else { + if (sc->sc_playrun) { + (*sc->sc_pintr)(sc->sc_parg); + retval = 1; + } else if (sc->sc_recrun) { + (*sc->sc_rintr)(sc->sc_rarg); + retval = 1; + } } + /* clear interrupt */ + ADWRITE(sc, AD1848_STATUS, 0); } - /* clear interrupt */ - ADWRITE(sc, AD1848_STATUS, 0); - } - return(retval); + return(retval); } void * -ad1848_malloc(addr, direction, size, pool, flags) - void *addr; - int direction; - size_t size; - int pool; - int flags; +ad1848_malloc(void *addr, int direction, size_t size, int pool, int flags) { struct ad1848_softc *sc = addr; int drq; @@ -1601,19 +1537,13 @@ ad1848_malloc(addr, direction, size, pool, flags) } void -ad1848_free(addr, ptr, pool) - void *addr; - void *ptr; - int pool; +ad1848_free(void *addr, void *ptr, int pool) { isa_free(ptr, pool); } size_t -ad1848_round(addr, direction, size) - void *addr; - int direction; - size_t size; +ad1848_round(void *addr, int direction, size_t size) { if (size > MAX_ISADMA) size = MAX_ISADMA; @@ -1621,21 +1551,16 @@ ad1848_round(addr, direction, size) } paddr_t -ad1848_mappage(addr, mem, off, prot) - void *addr; - void *mem; - off_t off; - int prot; +ad1848_mappage(void *addr, void *mem, off_t off, int prot) { return isa_mappage(mem, off, prot); } int -ad1848_get_props(addr) - void *addr; +ad1848_get_props(void *addr) { struct ad1848_softc *sc = addr; return AUDIO_PROP_MMAP | - (sc->mode == 2 ? AUDIO_PROP_FULLDUPLEX : 0); + (sc->mode == 2 ? AUDIO_PROP_FULLDUPLEX : 0); } |