diff options
author | 2011-09-03 20:03:27 +0000 | |
---|---|---|
committer | 2011-09-03 20:03:27 +0000 | |
commit | d98f46d72cda82c9e3983a12b45a6d4050ace6f3 (patch) | |
tree | b8bd3752633cfeca9185a6cf42846ab6c18b52f4 | |
parent | zap trailing whitespace; (diff) | |
download | wireguard-openbsd-d98f46d72cda82c9e3983a12b45a6d4050ace6f3.tar.xz wireguard-openbsd-d98f46d72cda82c9e3983a12b45a6d4050ace6f3.zip |
MI driver for AMD79C30 audio chip; from NetBSD
-rw-r--r-- | sys/conf/files | 6 | ||||
-rw-r--r-- | sys/dev/ic/am7930.c | 571 | ||||
-rw-r--r-- | sys/dev/ic/am7930reg.h | 273 | ||||
-rw-r--r-- | sys/dev/ic/am7930var.h | 121 |
4 files changed, 860 insertions, 111 deletions
diff --git a/sys/conf/files b/sys/conf/files index f14890ffec9..14d9c44ec11 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -1,4 +1,4 @@ -# $OpenBSD: files,v 1.526 2011/08/18 20:02:58 miod Exp $ +# $OpenBSD: files,v 1.527 2011/09/03 20:03:27 miod Exp $ # $NetBSD: files,v 1.87 1996/05/19 17:17:50 jonathan Exp $ # @(#)files.newconf 7.5 (Berkeley) 5/10/93 @@ -450,6 +450,10 @@ device wbsd: sdmmcbus file dev/ic/w83l518d.c wbsd file dev/ic/w83l518d_sdmmc.c wbsd +# AMD 7930 audio/ISDN codec +define am7930 +file dev/ic/am7930.c am7930 + # radio devices, attaches to radio hardware driver device radio attach radio at radiobus diff --git a/sys/dev/ic/am7930.c b/sys/dev/ic/am7930.c new file mode 100644 index 00000000000..a18089f3817 --- /dev/null +++ b/sys/dev/ic/am7930.c @@ -0,0 +1,571 @@ +/* $OpenBSD: am7930.c,v 1.1 2011/09/03 20:03:29 miod Exp $ */ +/* $NetBSD: am7930.c,v 1.44 2001/11/13 13:14:34 lukem Exp $ */ + +/* + * Copyright (c) 1995 Rolf Grossmann + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Rolf Grossmann. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Front-end attachment independent layer for AMD 79c30 + * audio driver. No ISDN support. + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/errno.h> +#include <sys/ioctl.h> +#include <sys/device.h> +#include <sys/proc.h> + +#include <sys/audioio.h> +#include <dev/audio_if.h> + +#include <dev/ic/am7930reg.h> +#include <dev/ic/am7930var.h> + +#ifdef AUDIO_DEBUG +int am7930debug = 0; +#define DPRINTF(x) if (am7930debug) printf x +#else +#define DPRINTF(x) +#endif + + +/* The following tables stolen from former (4.4Lite's) sys/sparc/bsd_audio.c */ + +/* + * gx, gr & stg gains. this table must contain 256 elements with + * the 0th being "infinity" (the magic value 9008). The remaining + * elements match sun's gain curve (but with higher resolution): + * -18 to 0dB in .16dB steps then 0 to 12dB in .08dB steps. + */ +static const uint16_t gx_coeff[256] = { + 0x9008, 0x8e7c, 0x8e51, 0x8e45, 0x8d42, 0x8d3b, 0x8c36, 0x8c33, + 0x8b32, 0x8b2a, 0x8b2b, 0x8b2c, 0x8b25, 0x8b23, 0x8b22, 0x8b22, + 0x9122, 0x8b1a, 0x8aa3, 0x8aa3, 0x8b1c, 0x8aa6, 0x912d, 0x912b, + 0x8aab, 0x8b12, 0x8aaa, 0x8ab2, 0x9132, 0x8ab4, 0x913c, 0x8abb, + 0x9142, 0x9144, 0x9151, 0x8ad5, 0x8aeb, 0x8a79, 0x8a5a, 0x8a4a, + 0x8b03, 0x91c2, 0x91bb, 0x8a3f, 0x8a33, 0x91b2, 0x9212, 0x9213, + 0x8a2c, 0x921d, 0x8a23, 0x921a, 0x9222, 0x9223, 0x922d, 0x9231, + 0x9234, 0x9242, 0x925b, 0x92dd, 0x92c1, 0x92b3, 0x92ab, 0x92a4, + 0x92a2, 0x932b, 0x9341, 0x93d3, 0x93b2, 0x93a2, 0x943c, 0x94b2, + 0x953a, 0x9653, 0x9782, 0x9e21, 0x9d23, 0x9cd2, 0x9c23, 0x9baa, + 0x9bde, 0x9b33, 0x9b22, 0x9b1d, 0x9ab2, 0xa142, 0xa1e5, 0x9a3b, + 0xa213, 0xa1a2, 0xa231, 0xa2eb, 0xa313, 0xa334, 0xa421, 0xa54b, + 0xada4, 0xac23, 0xab3b, 0xaaab, 0xaa5c, 0xb1a3, 0xb2ca, 0xb3bd, + 0xbe24, 0xbb2b, 0xba33, 0xc32b, 0xcb5a, 0xd2a2, 0xe31d, 0x0808, + 0x72ba, 0x62c2, 0x5c32, 0x52db, 0x513e, 0x4cce, 0x43b2, 0x4243, + 0x41b4, 0x3b12, 0x3bc3, 0x3df2, 0x34bd, 0x3334, 0x32c2, 0x3224, + 0x31aa, 0x2a7b, 0x2aaa, 0x2b23, 0x2bba, 0x2c42, 0x2e23, 0x25bb, + 0x242b, 0x240f, 0x231a, 0x22bb, 0x2241, 0x2223, 0x221f, 0x1a33, + 0x1a4a, 0x1acd, 0x2132, 0x1b1b, 0x1b2c, 0x1b62, 0x1c12, 0x1c32, + 0x1d1b, 0x1e71, 0x16b1, 0x1522, 0x1434, 0x1412, 0x1352, 0x1323, + 0x1315, 0x12bc, 0x127a, 0x1235, 0x1226, 0x11a2, 0x1216, 0x0a2a, + 0x11bc, 0x11d1, 0x1163, 0x0ac2, 0x0ab2, 0x0aab, 0x0b1b, 0x0b23, + 0x0b33, 0x0c0f, 0x0bb3, 0x0c1b, 0x0c3e, 0x0cb1, 0x0d4c, 0x0ec1, + 0x079a, 0x0614, 0x0521, 0x047c, 0x0422, 0x03b1, 0x03e3, 0x0333, + 0x0322, 0x031c, 0x02aa, 0x02ba, 0x02f2, 0x0242, 0x0232, 0x0227, + 0x0222, 0x021b, 0x01ad, 0x0212, 0x01b2, 0x01bb, 0x01cb, 0x01f6, + 0x0152, 0x013a, 0x0133, 0x0131, 0x012c, 0x0123, 0x0122, 0x00a2, + 0x011b, 0x011e, 0x0114, 0x00b1, 0x00aa, 0x00b3, 0x00bd, 0x00ba, + 0x00c5, 0x00d3, 0x00f3, 0x0062, 0x0051, 0x0042, 0x003b, 0x0033, + 0x0032, 0x002a, 0x002c, 0x0025, 0x0023, 0x0022, 0x001a, 0x0021, + 0x001b, 0x001b, 0x001d, 0x0015, 0x0013, 0x0013, 0x0012, 0x0012, + 0x000a, 0x000a, 0x0011, 0x0011, 0x000b, 0x000b, 0x000c, 0x000e, +}; + +/* + * second stage play gain. + */ +static const uint16_t ger_coeff[] = { + 0x431f, /* 5. dB */ + 0x331f, /* 5.5 dB */ + 0x40dd, /* 6. dB */ + 0x11dd, /* 6.5 dB */ + 0x440f, /* 7. dB */ + 0x411f, /* 7.5 dB */ + 0x311f, /* 8. dB */ + 0x5520, /* 8.5 dB */ + 0x10dd, /* 9. dB */ + 0x4211, /* 9.5 dB */ + 0x410f, /* 10. dB */ + 0x111f, /* 10.5 dB */ + 0x600b, /* 11. dB */ + 0x00dd, /* 11.5 dB */ + 0x4210, /* 12. dB */ + 0x110f, /* 13. dB */ + 0x7200, /* 14. dB */ + 0x2110, /* 15. dB */ + 0x2200, /* 15.9 dB */ + 0x000b, /* 16.9 dB */ + 0x000f /* 18. dB */ +#define NGER (sizeof(ger_coeff) / sizeof(ger_coeff[0])) +}; + + +/* + * Reset chip and set boot-time softc defaults. + */ +void +am7930_init(struct am7930_softc *sc, int flag) +{ + DPRINTF(("am7930_init()\n")); + + /* set boot defaults */ + sc->sc_rlevel = 128; + sc->sc_plevel = 128; + sc->sc_mlevel = 0; + sc->sc_out_port = AUDIOAMD_SPEAKER_VOL; + sc->sc_mic_mute = 0; + + /* disable sample interrupts */ + AM7930_IWRITE(sc, AM7930_IREG_MUX_MCR4, 0); + + /* initialise voice and data, and disable interrupts */ + AM7930_IWRITE(sc, AM7930_IREG_INIT, + AM7930_INIT_PMS_ACTIVE | AM7930_INIT_INT_DISABLE); + + if (flag == AUDIOAMD_DMA_MODE) { + /* configure PP for serial (SBP) mode */ + AM7930_IWRITE(sc, AM7930_IREG_PP_PPCR1, AM7930_PPCR1_SBP); + + /* + * Initialise the MUX unit - route the MAP to the PP + */ + AM7930_IWRITE(sc, AM7930_IREG_MUX_MCR1, + (AM7930_MCRCHAN_BA << 4) | AM7930_MCRCHAN_BD); + AM7930_IWRITE(sc, AM7930_IREG_MUX_MCR2, AM7930_MCRCHAN_NC); + AM7930_IWRITE(sc, AM7930_IREG_MUX_MCR3, AM7930_MCRCHAN_NC); + } else { + /* + * Initialize the MUX unit. We use MCR3 to route the MAP + * through channel Bb. MCR1 and MCR2 are unused. + * Setting the INT enable bit in MCR4 will generate an + * interrupt on each converted audio sample. + */ + AM7930_IWRITE(sc, AM7930_IREG_MUX_MCR1, 0); + AM7930_IWRITE(sc, AM7930_IREG_MUX_MCR2, 0); + AM7930_IWRITE(sc, AM7930_IREG_MUX_MCR3, + (AM7930_MCRCHAN_BB << 4) | AM7930_MCRCHAN_BA); + AM7930_IWRITE(sc, AM7930_IREG_MUX_MCR4, + AM7930_MCR4_INT_ENABLE); + } +} + +int +am7930_open(void *addr, int flags) +{ + struct am7930_softc *sc = addr; + + DPRINTF(("sa_open: unit %p\n", sc)); + if (sc->sc_open) + return EBUSY; + sc->sc_open = 1; + sc->sc_locked = 0; + + sc->sc_glue->onopen(sc); + DPRINTF(("saopen: ok -> sc=%p\n",sc)); + return 0; +} + +void +am7930_close(void *addr) +{ + struct am7930_softc *sc = addr; + + DPRINTF(("sa_close: sc=%p\n", sc)); + sc->sc_glue->onclose(sc); + sc->sc_open = 0; + DPRINTF(("sa_close: closed.\n")); +} + +/* + * XXX should be extended to handle a few of the more common formats. + */ +int +am7930_set_params(void *addr, int setmode, int usemode, struct audio_params *p, + struct audio_params *r) +{ +#if 0 + struct am7930_softc *sc = addr; +#endif + + if ((usemode & AUMODE_PLAY) == AUMODE_PLAY) { + p->encoding = AUDIO_ENCODING_ULAW; + p->precision = 8; + p->bps = 1; + p->msb = 1; + p->channels = 1; + /* no other rates supported by amd chip */ + p->sample_rate = 8000; + } + if ((usemode & AUMODE_RECORD) == AUMODE_RECORD) { + r->encoding = AUDIO_ENCODING_ULAW; + r->precision = 8; + r->bps = 1; + r->msb = 1; + r->channels = 1; + /* no other rates supported by amd chip */ + r->sample_rate = 8000; + } + + return 0; +} + +int +am7930_query_encoding(void *addr, struct audio_encoding *fp) +{ + switch (fp->index) { + case 0: + strlcpy(fp->name, AudioEmulaw, sizeof fp->name); + fp->encoding = AUDIO_ENCODING_ULAW; + fp->precision = 8; + fp->bps = 1; + fp->msb = 1; + fp->flags = 0; + break; + default: + return EINVAL; + /*NOTREACHED*/ + } + return 0; +} + +int +am7930_round_blocksize(void *addr, int blk) +{ + return blk; +} + +int +am7930_commit_settings(void *addr) +{ + struct am7930_softc *sc = addr; + uint16_t ger, gr, gx, stgr; + uint8_t mmr2, mmr3; + int s, level; + + DPRINTF(("sa_commit.\n")); + gx = gx_coeff[sc->sc_rlevel]; + stgr = gx_coeff[sc->sc_mlevel]; + + level = (sc->sc_plevel * (256 + NGER)) >> 8; + if (level >= 256) { + ger = ger_coeff[level - 256]; + gr = gx_coeff[255]; + } else { + ger = ger_coeff[0]; + gr = gx_coeff[level]; + } + + s = splaudio(); + + mmr2 = AM7930_IREAD(sc, AM7930_IREG_MAP_MMR2); + if (sc->sc_out_port == AUDIOAMD_SPEAKER_VOL) + mmr2 |= AM7930_MMR2_LS; + else + mmr2 &= ~AM7930_MMR2_LS; + AM7930_IWRITE(sc, AM7930_IREG_MAP_MMR2, mmr2); + + mmr3 = AM7930_IREAD(sc, AM7930_IREG_MAP_MMR3); + if (sc->sc_mic_mute) + mmr3 |= AM7930_MMR3_MUTE; + else + mmr3 &= ~AM7930_MMR3_MUTE; + AM7930_IWRITE(sc, AM7930_IREG_MAP_MMR3, mmr3); + + AM7930_IWRITE(sc, AM7930_IREG_MAP_MMR1, + AM7930_MMR1_GX | AM7930_MMR1_GER | + AM7930_MMR1_GR | AM7930_MMR1_STG); + + AM7930_IWRITE16(sc, AM7930_IREG_MAP_GX, gx); + AM7930_IWRITE16(sc, AM7930_IREG_MAP_STG, stgr); + AM7930_IWRITE16(sc, AM7930_IREG_MAP_GR, gr); + AM7930_IWRITE16(sc, AM7930_IREG_MAP_GER, ger); + + splx(s); + + return 0; +} + +int +am7930_halt_output(void *addr) +{ + struct am7930_softc *sc = addr; + + /* XXX only halt, if input is also halted ?? */ + AM7930_IWRITE(sc, AM7930_IREG_INIT, + AM7930_INIT_PMS_ACTIVE | AM7930_INIT_INT_DISABLE); + sc->sc_locked = 0; + return 0; +} + +int +am7930_halt_input(void *addr) +{ + struct am7930_softc *sc = addr; + + /* XXX only halt, if output is also halted ?? */ + AM7930_IWRITE(sc, AM7930_IREG_INIT, + AM7930_INIT_PMS_ACTIVE | AM7930_INIT_INT_DISABLE); + sc->sc_locked = 0; + return 0; +} + +/* + * XXX chip is full-duplex, but really attach-dependent. + * For now we know of no half-duplex attachments. + */ +int +am7930_get_props(void *addr) +{ + return AUDIO_PROP_FULLDUPLEX; +} + +/* + * Attach-dependent channel set/query + */ +int +am7930_set_port(void *addr, mixer_ctrl_t *cp) +{ + struct am7930_softc *sc = addr; + + DPRINTF(("am7930_set_port: port=%d", cp->dev)); + if (cp->dev == AUDIOAMD_RECORD_SOURCE || + cp->dev == AUDIOAMD_MONITOR_OUTPUT || + cp->dev == AUDIOAMD_MIC_MUTE) { + if (cp->type != AUDIO_MIXER_ENUM) + return EINVAL; + } else if (cp->type != AUDIO_MIXER_VALUE || + cp->un.value.num_channels != 1) { + return EINVAL; + } + + switch(cp->dev) { + case AUDIOAMD_MIC_VOL: + sc->sc_rlevel = cp->un.value.level[AUDIO_MIXER_LEVEL_MONO]; + break; + case AUDIOAMD_SPEAKER_VOL: + case AUDIOAMD_HEADPHONES_VOL: + sc->sc_plevel = cp->un.value.level[AUDIO_MIXER_LEVEL_MONO]; + break; + case AUDIOAMD_MONITOR_VOL: + sc->sc_mlevel = cp->un.value.level[AUDIO_MIXER_LEVEL_MONO]; + break; + case AUDIOAMD_RECORD_SOURCE: + if (cp->un.ord != AUDIOAMD_MIC_VOL) + return EINVAL; + break; + case AUDIOAMD_MIC_MUTE: + sc->sc_mic_mute = cp->un.ord; + break; + case AUDIOAMD_MONITOR_OUTPUT: + if (cp->un.ord != AUDIOAMD_SPEAKER_VOL && + cp->un.ord != AUDIOAMD_HEADPHONES_VOL) + return EINVAL; + sc->sc_out_port = cp->un.ord; + break; + default: + return EINVAL; + /* NOTREACHED */ + } + return 0; +} + +int +am7930_get_port(void *addr, mixer_ctrl_t *cp) +{ + struct am7930_softc *sc = addr; + + DPRINTF(("am7930_get_port: port=%d\n", cp->dev)); + if (cp->dev == AUDIOAMD_RECORD_SOURCE || + cp->dev == AUDIOAMD_MONITOR_OUTPUT || + cp->dev == AUDIOAMD_MIC_MUTE) { + if (cp->type != AUDIO_MIXER_ENUM) + return EINVAL; + } else if (cp->type != AUDIO_MIXER_VALUE || + cp->un.value.num_channels != 1) { + return EINVAL; + } + + switch(cp->dev) { + case AUDIOAMD_MIC_VOL: + cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] = sc->sc_rlevel; + break; + case AUDIOAMD_SPEAKER_VOL: + case AUDIOAMD_HEADPHONES_VOL: + cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] = sc->sc_plevel; + break; + case AUDIOAMD_MONITOR_VOL: + cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] = sc->sc_mlevel; + break; + case AUDIOAMD_RECORD_SOURCE: + cp->un.ord = AUDIOAMD_MIC_VOL; + break; + case AUDIOAMD_MIC_MUTE: + cp->un.ord = sc->sc_mic_mute; + break; + case AUDIOAMD_MONITOR_OUTPUT: + cp->un.ord = sc->sc_out_port; + break; + default: + return EINVAL; + /* NOTREACHED */ + } + return 0; +} + + +/* + * Define mixer control facilities. + */ +int +am7930_query_devinfo(void *addr, mixer_devinfo_t *dip) +{ + DPRINTF(("am7930_query_devinfo()\n")); + + switch(dip->index) { + case AUDIOAMD_MIC_VOL: + dip->type = AUDIO_MIXER_VALUE; + dip->mixer_class = AUDIOAMD_INPUT_CLASS; + dip->prev = AUDIO_MIXER_LAST; + dip->next = AUDIOAMD_MIC_MUTE; + strlcpy(dip->label.name, AudioNmicrophone, + sizeof dip->label.name); + dip->un.v.num_channels = 1; + strlcpy(dip->un.v.units.name, AudioNvolume, + sizeof dip->un.v.units.name); + break; + case AUDIOAMD_SPEAKER_VOL: + dip->type = AUDIO_MIXER_VALUE; + dip->mixer_class = AUDIOAMD_OUTPUT_CLASS; + dip->prev = dip->next = AUDIO_MIXER_LAST; + strlcpy(dip->label.name, AudioNspeaker, + sizeof dip->label.name); + dip->un.v.num_channels = 1; + strlcpy(dip->un.v.units.name, AudioNvolume, + sizeof dip->un.v.units.name); + break; + case AUDIOAMD_HEADPHONES_VOL: + dip->type = AUDIO_MIXER_VALUE; + dip->mixer_class = AUDIOAMD_OUTPUT_CLASS; + dip->prev = dip->next = AUDIO_MIXER_LAST; + strlcpy(dip->label.name, AudioNheadphone, + sizeof dip->label.name); + dip->un.v.num_channels = 1; + strlcpy(dip->un.v.units.name, AudioNvolume, + sizeof dip->un.v.units.name); + break; + case AUDIOAMD_MONITOR_VOL: + dip->type = AUDIO_MIXER_VALUE; + dip->mixer_class = AUDIOAMD_MONITOR_CLASS; + dip->prev = dip->next = AUDIO_MIXER_LAST; + strlcpy(dip->label.name, AudioNmonitor, + sizeof dip->label.name); + dip->un.v.num_channels = 1; + strlcpy(dip->un.v.units.name, AudioNvolume, + sizeof dip->un.v.units.name); + break; + case AUDIOAMD_RECORD_SOURCE: + dip->type = AUDIO_MIXER_ENUM; + dip->mixer_class = AUDIOAMD_RECORD_CLASS; + dip->prev = dip->next = AUDIO_MIXER_LAST; + strlcpy(dip->label.name, AudioNsource, + sizeof dip->label.name); + dip->un.e.num_mem = 1; + strlcpy(dip->un.e.member[0].label.name, AudioNmicrophone, + sizeof dip->un.e.member[0].label.name); + dip->un.e.member[0].ord = AUDIOAMD_MIC_VOL; + break; + case AUDIOAMD_MONITOR_OUTPUT: + dip->type = AUDIO_MIXER_ENUM; + dip->mixer_class = AUDIOAMD_MONITOR_CLASS; + dip->prev = dip->next = AUDIO_MIXER_LAST; + strlcpy(dip->label.name, AudioNoutput, + sizeof dip->label.name); + dip->un.e.num_mem = 2; + strlcpy(dip->un.e.member[0].label.name, AudioNspeaker, + sizeof dip->un.e.member[0].label.name); + dip->un.e.member[0].ord = AUDIOAMD_SPEAKER_VOL; + strlcpy(dip->un.e.member[1].label.name, AudioNheadphone, + sizeof dip->un.e.member[1].label.name); + dip->un.e.member[1].ord = AUDIOAMD_HEADPHONES_VOL; + break; + case AUDIOAMD_MIC_MUTE: + dip->type = AUDIO_MIXER_ENUM; + dip->mixer_class = AUDIOAMD_INPUT_CLASS; + dip->prev = AUDIOAMD_MIC_VOL; + dip->next = AUDIO_MIXER_LAST; + strlcpy(dip->label.name, AudioNmute, + sizeof dip->label.name); + dip->un.e.num_mem = 2; + strlcpy(dip->un.e.member[0].label.name, AudioNoff, + sizeof dip->un.e.member[0].label.name); + dip->un.e.member[0].ord = 0; + strlcpy(dip->un.e.member[1].label.name, AudioNon, + sizeof dip->un.e.member[1].label.name); + dip->un.e.member[1].ord = 1; + break; + case AUDIOAMD_INPUT_CLASS: + dip->type = AUDIO_MIXER_CLASS; + dip->mixer_class = AUDIOAMD_INPUT_CLASS; + dip->prev = dip->next = AUDIO_MIXER_LAST; + strlcpy(dip->label.name, AudioCinputs, + sizeof dip->label.name); + break; + case AUDIOAMD_OUTPUT_CLASS: + dip->type = AUDIO_MIXER_CLASS; + dip->mixer_class = AUDIOAMD_OUTPUT_CLASS; + dip->prev = dip->next = AUDIO_MIXER_LAST; + strlcpy(dip->label.name, AudioCoutputs, + sizeof dip->label.name); + break; + case AUDIOAMD_RECORD_CLASS: + dip->type = AUDIO_MIXER_CLASS; + dip->mixer_class = AUDIOAMD_RECORD_CLASS; + dip->prev = dip->next = AUDIO_MIXER_LAST; + strlcpy(dip->label.name, AudioCrecord, + sizeof dip->label.name); + break; + case AUDIOAMD_MONITOR_CLASS: + dip->type = AUDIO_MIXER_CLASS; + dip->mixer_class = AUDIOAMD_MONITOR_CLASS; + dip->prev = dip->next = AUDIO_MIXER_LAST; + strlcpy(dip->label.name, AudioCmonitor, + sizeof dip->label.name); + break; + default: + return ENXIO; + /*NOTREACHED*/ + } + + DPRINTF(("AUDIO_MIXER_DEVINFO: name=%s\n", dip->label.name)); + + return 0; +} diff --git a/sys/dev/ic/am7930reg.h b/sys/dev/ic/am7930reg.h index 058f0c03893..96a223082f9 100644 --- a/sys/dev/ic/am7930reg.h +++ b/sys/dev/ic/am7930reg.h @@ -1,5 +1,5 @@ -/* $OpenBSD: am7930reg.h,v 1.5 2007/05/23 09:00:17 jmc Exp $ */ -/* $NetBSD: am7930reg.h,v 1.1 1995/04/24 19:17:17 pk Exp $ */ +/* $OpenBSD: am7930reg.h,v 1.6 2011/09/03 20:03:29 miod Exp $ */ +/* $NetBSD: am7930reg.h,v 1.7 2005/12/11 12:21:25 christos Exp $ */ /* * Copyright (c) 1992, 1993 @@ -42,116 +42,169 @@ */ /* - * Bit encodings for chip commands from "Microprocessor Access Guide for - * Indirect Registers", p.19 Am79C30A/32A Advanced Micro Devices spec - * sheet (preliminary). - * - * Indirect register numbers (the value written into cr to select a given - * chip registers) have the form AMDR_*. Register fields look like AMD_*. - * + * Am79C30A direct registers */ +#define AM7930_DREG_CR 0 /* command register (wo) */ +#define AM7930_DREG_IR 0 /* interrupt register (ro) */ +#define AM7930_IR_DTTHRSH 0x01 /* D-channel TX empty */ +#define AM7930_IR_DRTHRSH 0x02 /* D-channel RX avail */ +#define AM7930_IR_DSRI 0x04 /* D-channel packet status */ +#define AM7930_IR_DERI 0x08 /* D-channel error */ +#define AM7930_IR_BBUFF 0x10 /* Bb or Bc byte avail/empty */ +#define AM7930_IR_LSRI 0x20 /* LIU status */ +#define AM7930_IR_DSR2I 0x40 /* D-channel buffer status */ +#define AM7930_IR_PPMF 0x80 /* Multiframe or PP */ +#define AM7930_DREG_DR 1 /* data register (rw) */ +#define AM7930_DREG_DSR1 2 /* D-channel status register 1 (ro) */ +#define AM7930_DREG_DER 3 /* D-channel error register (ro) */ +#define AM7930_DREG_DCTB 4 /* D-channel transmit register (wo) */ +#define AM7930_DREG_DCRB 4 /* D-channel receive register (ro) */ +#define AM7930_DREG_BBTB 5 /* Bb-channel transmit register (wo) */ +#define AM7930_DREG_BBRB 5 /* Bb-channel receive register (ro) */ +#define AM7930_DREG_BCTB 6 /* Bc-channel transmit register (wo) */ +#define AM7930_DREG_BCRB 6 /* Bc-channel receive register (ro) */ +#define AM7930_DREG_DSR2 7 /* D-channel status register 2 (ro) */ + +#define AM7930_DREG_SIZE 8 + /* - * Documentation for this chip: - * PCnet-Mobile Single Chip Wireless LAN Media Access Controller - * AMD Publication #: 20183, Rev B, Jan 1997 + * Am79C30A indirect registers */ -struct amd7930 { - u_char cr; /* command register (wo) */ -#define ir cr /* interrupt register (ro) */ - u_char dr; /* data register (rw) */ - u_char dsr1; /* D-channel status register 1 (ro) */ - u_char der; /* D-channel error register (ro) */ - u_char dctb; /* D-channel transmit register (wo) */ -#define dcrb dctb /* D-channel receive register (ro) */ - u_char bbtb; /* Bb-channel transmit register (wo) */ -#define bbrb bbtb /* Bb-channel receive register (ro) */ - u_char bctb; /* Bc-channel transmit register (wo) */ -#define bcrb bctb /* Bc-channel receive register (ro) */ - u_char dsr2; /* D-channel status register 2 (ro) */ -}; - -#define AMDR_INIT 0x21 -#define AMD_INIT_PMS_IDLE 0x00 -#define AMD_INIT_PMS_ACTIVE 0x01 -#define AMD_INIT_PMS_ACTIVE_DATA 0x02 -#define AMD_INIT_INT_DISABLE (0x01 << 2) -#define AMD_INIT_CDS_DIV2 (0x00 << 3) -#define AMD_INIT_CDS_DIV1 (0x01 << 3) -#define AMD_INIT_CDS_DIV4 (0x02 << 3) -#define AMD_INIT_AS_RX (0x01 << 6) -#define AMD_INIT_AS_TX (0x01 << 7) - -#define AMDR_LIU_LSR 0xa1 -#define AMDR_LIU_LPR 0xa2 -#define AMDR_LIU_LMR1 0xa3 -#define AMDR_LIU_LMR2 0xa4 -#define AMDR_LIU_2_4 0xa5 -#define AMDR_LIU_MF 0xa6 -#define AMDR_LIU_MFSB 0xa7 -#define AMDR_LIU_MFQB 0xa8 - -#define AMDR_MUX_MCR1 0x41 -#define AMDR_MUX_MCR2 0x42 -#define AMDR_MUX_MCR3 0x43 -#define AMD_MCRCHAN_NC 0x00 -#define AMD_MCRCHAN_B1 0x01 -#define AMD_MCRCHAN_B2 0x02 -#define AMD_MCRCHAN_BA 0x03 -#define AMD_MCRCHAN_BB 0x04 -#define AMD_MCRCHAN_BC 0x05 -#define AMD_MCRCHAN_BD 0x06 -#define AMD_MCRCHAN_BE 0x07 -#define AMD_MCRCHAN_BF 0x08 -#define AMDR_MUX_MCR4 0x44 -#define AMD_MCR4_INT_ENABLE (1 << 3) -#define AMD_MCR4_SWAPBB (1 << 4) -#define AMD_MCR4_SWAPBC (1 << 5) - -#define AMDR_MUX_1_4 0x45 - -#define AMDR_MAP_X 0x61 -#define AMDR_MAP_R 0x62 -#define AMDR_MAP_GX 0x63 -#define AMDR_MAP_GR 0x64 -#define AMDR_MAP_GER 0x65 -#define AMDR_MAP_STG 0x66 -#define AMDR_MAP_FTGR 0x67 -#define AMDR_MAP_ATGR 0x68 -#define AMDR_MAP_MMR1 0x69 -#define AMD_MMR1_ALAW 0x01 -#define AMD_MMR1_GX 0x02 -#define AMD_MMR1_GR 0x04 -#define AMD_MMR1_GER 0x08 -#define AMD_MMR1_X 0x10 -#define AMD_MMR1_R 0x20 -#define AMD_MMR1_STG 0x40 -#define AMD_MMR1_LOOP 0x80 -#define AMDR_MAP_MMR2 0x6a -#define AMD_MMR2_AINB 0x01 -#define AMD_MMR2_LS 0x02 -#define AMD_MMR2_DTMF 0x04 -#define AMD_MMR2_GEN 0x08 -#define AMD_MMR2_RNG 0x10 -#define AMD_MMR2_DIS_HPF 0x20 -#define AMD_MMR2_DIS_AZ 0x40 -#define AMDR_MAP_1_10 0x6b - -#define AMDR_DLC_FRAR123 0x81 -#define AMDR_DLC_SRAR123 0x82 -#define AMDR_DLC_TAR 0x83 -#define AMDR_DLC_DRLR 0x84 -#define AMDR_DLC_DTCR 0x85 -#define AMDR_DLC_DMR1 0x86 -#define AMDR_DLC_DMR2 0x87 -#define AMDR_DLC_1_7 0x88 -#define AMDR_DLC_DRCR 0x89 -#define AMDR_DLC_RNGR1 0x8a -#define AMDR_DLC_RNGR2 0x8b -#define AMDR_DLC_FRAR4 0x8c -#define AMDR_DLC_SRAR4 0x8d -#define AMDR_DLC_DMR3 0x8e -#define AMDR_DLC_DMR4 0x8f -#define AMDR_DLC_12_15 0x90 -#define AMDR_DLC_ASR 0x91 +/* Initialisation registers */ + +#define AM7930_IREG_INIT 0x21 +#define AM7930_IREG_INIT2 0x20 +/* power mode selection */ +#define AM7930_INIT_PMS_IDLE 0x00 +#define AM7930_INIT_PMS_ACTIVE 0x01 +#define AM7930_INIT_PMS_ACTIVE_DATA 0x02 +#define AM7930_INIT_PMS_MASK 0x03 +/* interrupt selection */ +#define AM7930_INIT_INT_ENABLE 0x00 +#define AM7930_INIT_INT_DISABLE 0x04 +#define AM7930_INIT_INT_MASK 0x04 +/* clock divider selection */ +#define AM7930_INIT_CDS_DIV2 0x00 +#define AM7930_INIT_CDS_DIV1 0x08 +#define AM7930_INIT_CDS_DIV4 0x10 +#define AM7930_INIT_CDS_DIV3 0x20 +#define AM7930_INIT_CDS_MASK 0x38 +/* abort selection */ +#define AM7930_INIT_AS_RX 0x40 +#define AM7930_INIT_AS_NRX 0x00 +#define AM7930_INIT_AS_TX 0x80 +#define AM7930_INIT_AS_NTX 0x00 +#define AM7930_INIT_AS_MASK 0xc0 + +/* Line Interface Unit registers */ + +#define AM7930_IREG_LIU_LSR 0xa1 /* LIU status (ro) */ +#define AM7930_IREG_LIU_LPR 0xa2 /* LIU priority (rw) */ +#define AM7930_IREG_LIU_LMR1 0xa3 /* LIU mode register 1 (rw) */ +#define AM7930_IREG_LIU_LMR2 0xa4 /* LIU mode register 2 (rw) */ +#define AM7930_IREG_LIU_2_4 0xa5 +#define AM7930_IREG_LIU_MF 0xa6 /* Multiframe (rw) */ +#define AM7930_IREG_LIU_MFSB 0xa7 /* Multiframe S-bit/status (ro) */ +#define AM7930_IREG_LIU_MFQB 0xa8 /* Multiframe Q-bit buffer (wo) */ + +/* Multiplexer registers */ + +#define AM7930_IREG_MUX_MCR1 0x41 /* MUX command register 1 (rw) */ +#define AM7930_IREG_MUX_MCR2 0x42 /* MUX command register 2 (rw) */ +#define AM7930_IREG_MUX_MCR3 0x43 /* MUX command register 3 (rw) */ +#define AM7930_MCRCHAN_NC 0x00 +#define AM7930_MCRCHAN_B1 0x01 +#define AM7930_MCRCHAN_B2 0x02 +#define AM7930_MCRCHAN_BA 0x03 +#define AM7930_MCRCHAN_BB 0x04 +#define AM7930_MCRCHAN_BC 0x05 +#define AM7930_MCRCHAN_BD 0x06 +#define AM7930_MCRCHAN_BE 0x07 +#define AM7930_MCRCHAN_BF 0x08 +#define AM7930_IREG_MUX_MCR4 0x44 /* MUX command register 4 (rw) */ +#define AM7930_MCR4_INT_ENABLE (1 << 3) +#define AM7930_MCR4_SWAPBB (1 << 4) +#define AM7930_MCR4_SWAPBC (1 << 5) +#define AM7930_IREG_MUX_1_4 0x45 + +/* Main Audio Processor registers */ + +#define AM7930_IREG_MAP_X 0x61 /* X filter coefficient (rw) */ +#define AM7930_IREG_MAP_R 0x62 /* R filter coefficient (rw) */ +#define AM7930_IREG_MAP_GX 0x63 /* GX gain coefficient (rw) */ +#define AM7930_IREG_MAP_GR 0x64 /* GR gain coefficient (rw) */ +#define AM7930_IREG_MAP_GER 0x65 /* GER gain coefficient (rw) */ +#define AM7930_IREG_MAP_STG 0x66 /* Sidetone gain coefficient (rw) */ +#define AM7930_IREG_MAP_FTGR 0x67 /* Frequency tone generator 1,2 (rw) */ +#define AM7930_IREG_MAP_ATGR 0x68 /* Amplitude tone generator 1,2 (rw) */ +#define AM7930_IREG_MAP_MMR1 0x69 /* MAP mode register 1 (rw) */ +#define AM7930_MMR1_ALAW 0x01 +#define AM7930_MMR1_GX 0x02 +#define AM7930_MMR1_GR 0x04 +#define AM7930_MMR1_GER 0x08 +#define AM7930_MMR1_X 0x10 +#define AM7930_MMR1_R 0x20 +#define AM7930_MMR1_STG 0x40 +#define AM7930_MMR1_LOOP 0x80 +#define AM7930_IREG_MAP_MMR2 0x6a /* MAP mode register 2 (rw) */ +#define AM7930_MMR2_AINB 0x01 +#define AM7930_MMR2_LS 0x02 +#define AM7930_MMR2_DTMF 0x04 +#define AM7930_MMR2_GEN 0x08 +#define AM7930_MMR2_RNG 0x10 +#define AM7930_MMR2_DIS_HPF 0x20 +#define AM7930_MMR2_DIS_AZ 0x40 +#define AM7930_IREG_MAP_1_10 0x6b +#define AM7930_IREG_MAP_MMR3 0x6c /* MAP mode register 3 (rw) */ +#define AM7930_MMR3_BOTH 0x02 +#define AM7930_MMR3_MBZ 0x01 +#define AM7930_MMR3_GA 0x70 +#define AM7930_MMR3_GA0 0x00 +#define AM7930_MMR3_GA6 0x10 +#define AM7930_MMR3_GA12 0x20 +#define AM7930_MMR3_GA18 0x30 +#define AM7930_MMR3_GA24 0x40 +#define AM7930_MMR3_MUTE 0x08 +#define AM7930_MMR3_STR 0x01 +#define AM7930_IREG_MAP_STRA 0x6d /* Second tone ringer amplitude (rw) */ +#define AM7930_IREG_MAP_STRF 0x6e /* Second tone ringer frequency (rw) */ + +/* Data Link Controller registers */ + +#define AM7930_IREG_DLC_FRAR123 0x81 /* First rcvd byte address 123 (rw) */ +#define AM7930_IREG_DLC_SRAR123 0x82 /* Second rcvd byte address 123 (rw) */ +#define AM7930_IREG_DLC_TAR 0x83 /* Transmit address (rw) */ +#define AM7930_IREG_DLC_DRLR 0x84 /* D-channel receive byte limit (rw) */ +#define AM7930_IREG_DLC_DTCR 0x85 /* D-channel transmit byte count (rw)*/ +#define AM7930_IREG_DLC_DMR1 0x86 /* D-channel mode register 1 (rw) */ +#define AM7930_IREG_DLC_DMR2 0x87 /* D-channel mode register 2 (rw) */ +#define AM7930_IREG_DLC_1_7 0x88 +#define AM7930_IREG_DLC_DRCR 0x89 /* D-channel receive byte count (ro) */ +#define AM7930_IREG_DLC_RNGR1 0x8a /* Random number generator LSB (rw) */ +#define AM7930_IREG_DLC_RNGR2 0x8b /* Random number generator MSB (rw) */ +#define AM7930_IREG_DLC_FRAR4 0x8c /* First rcvd byte address 4 (rw) */ +#define AM7930_IREG_DLC_SRAR4 0x8d /* Second rcvd byte address 4 (rw) */ +#define AM7930_IREG_DLC_DMR3 0x8e /* D-channel mode register 3 (rw) */ +#define AM7930_IREG_DLC_DMR4 0x8f /* D-channel mode register 4 (rw) */ +#define AM7930_IREG_DLC_12_15 0x90 +#define AM7930_IREG_DLC_ASR 0x91 /* Address status register (ro) */ +#define AM7930_IREG_DLC_EFCR 0x92 /* Extended FIFO control (rw) */ + +/* Peripheral Port registers */ + +#define AM7930_IREG_PP_PPCR1 0xc0 /* Peripheral port control 1 (rw) */ +#define AM7930_PPCR1_DISABLE 0x00 +#define AM7930_PPCR1_SBP 0x01 +#define AM7930_PPCR1_IOM2SL 0x10 +#define AM7930_PPCR1_IOM2MA 0x11 +#define AM7930_IREG_PP_PPSR 0xc1 /* Peripheral port control 2 (ro) */ +#define AM7930_IREG_PP_PPIER 0xc2 /* Peripheral port intr enable (rw) */ +#define AM7930_IREG_PP_MTDR 0xc3 /* monitor transmit data (wo) */ +#define AM7930_IREG_PP_MRDR 0xc3 /* monitor receive data (ro) */ +#define AM7930_IREG_PP_CITDR0 0xc4 /* C/I transmit data register 0 (wo) */ +#define AM7930_IREG_PP_CIRDR0 0xc4 /* C/I receive data register 0 (ro) */ +#define AM7930_IREG_PP_CITDR1 0xc5 /* C/I transmit data register 1 (wo) */ +#define AM7930_IREG_PP_CIRDR1 0xc5 /* C/I receive data register 1 (ro) */ +#define AM7930_IREG_PP_PPCR2 0xc8 /* Peripheral port control 2 (rw) */ diff --git a/sys/dev/ic/am7930var.h b/sys/dev/ic/am7930var.h new file mode 100644 index 00000000000..e7242cc2bb3 --- /dev/null +++ b/sys/dev/ic/am7930var.h @@ -0,0 +1,121 @@ +/* $OpenBSD: am7930var.h,v 1.1 2011/09/03 20:03:29 miod Exp $ */ +/* $NetBSD: am7930var.h,v 1.10 2005/01/15 15:19:52 kent Exp $ */ + +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratory. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)bsd_audiovar.h 8.1 (Berkeley) 6/11/93 + */ + +struct am7930_softc; + +struct am7930_glue { + uint8_t (*codec_iread)(struct am7930_softc *sc, int); + void (*codec_iwrite)(struct am7930_softc *sc, int, uint8_t); + uint16_t (*codec_iread16)(struct am7930_softc *sc, int); + void (*codec_iwrite16)(struct am7930_softc *sc, int, uint16_t); + void (*onopen)(struct am7930_softc *sc); + void (*onclose)(struct am7930_softc *sc); +}; + +struct am7930_softc { + struct device sc_dev; /* base device */ + int sc_open; + int sc_locked; + + uint8_t sc_rlevel; /* record level */ + uint8_t sc_plevel; /* play level */ + uint8_t sc_mlevel; /* monitor level */ + uint8_t sc_out_port; /* output port */ + uint8_t sc_mic_mute; + + struct am7930_glue *sc_glue; +}; + +extern int am7930debug; + +void am7930_init(struct am7930_softc *, int); + +#define AM7930_IWRITE(x,y,z) (*(x)->sc_glue->codec_iwrite)((x),(y),(z)) +#define AM7930_IREAD(x,y) (*(x)->sc_glue->codec_iread)((x),(y)) +#define AM7930_IWRITE16(x,y,z) (*(x)->sc_glue->codec_iwrite16)((x),(y),(z)) +#define AM7930_IREAD16(x,y) (*(x)->sc_glue->codec_iread16)((x),(y)) + +#define AUDIOAMD_POLL_MODE 0 +#define AUDIOAMD_DMA_MODE 1 + +/* + * audio channel definitions. + */ + +#define AUDIOAMD_SPEAKER_VOL 0 /* speaker volume */ +#define AUDIOAMD_HEADPHONES_VOL 1 /* headphones volume */ +#define AUDIOAMD_OUTPUT_CLASS 2 + +#define AUDIOAMD_MONITOR_VOL 3 /* monitor input volume */ +#define AUDIOAMD_MONITOR_OUTPUT 4 /* output selector */ +#define AUDIOAMD_MONITOR_CLASS 5 + +#define AUDIOAMD_MIC_VOL 6 /* microphone volume */ +#define AUDIOAMD_MIC_MUTE 7 +#define AUDIOAMD_INPUT_CLASS 8 + +#define AUDIOAMD_RECORD_SOURCE 9 /* source selector */ +#define AUDIOAMD_RECORD_CLASS 10 + +/* + * audio(9) MI callbacks from upper-level audio layer. + */ + +struct audio_device; +struct audio_encoding; +struct audio_params; + +int am7930_open(void *, int); +void am7930_close(void *); +int am7930_query_encoding(void *, struct audio_encoding *); +int am7930_set_params(void *, int, int, struct audio_params *, + struct audio_params *); +int am7930_commit_settings(void *); +int am7930_round_blocksize(void *, int); +int am7930_halt_output(void *); +int am7930_halt_input(void *); +int am7930_getdev(void *, struct audio_device *); +int am7930_get_props(void *); +int am7930_set_port(void *, mixer_ctrl_t *); +int am7930_get_port(void *, mixer_ctrl_t *); +int am7930_query_devinfo(void *, mixer_devinfo_t *); |