diff options
author | Alexandre Ratchov <ratchov@cvs.openbsd.org> | 2008-02-21 01:37:56 +0000 |
---|---|---|
committer | Alexandre Ratchov <ratchov@cvs.openbsd.org> | 2008-02-21 01:37:56 +0000 |
commit | 8091041d251c8df8725bb2ed2bb29d70555eb729 (patch) | |
tree | 357ad916babc674bdf782a8476ad4f78416ca7a3 /sys/dev/pci | |
parent | 702b8139e944833f90396dd4de094a09b5dde898 (diff) |
implement AK4524 input and output volume knobs and output mute switches.
There are 8 gain knobs but only 4 mute switches because each codec has two
channels but only one mute switch.
ok jakemsr@
Diffstat (limited to 'sys/dev/pci')
-rw-r--r-- | sys/dev/pci/envy.c | 95 | ||||
-rw-r--r-- | sys/dev/pci/envyreg.h | 9 | ||||
-rw-r--r-- | sys/dev/pci/envyvar.h | 7 |
3 files changed, 102 insertions, 9 deletions
diff --git a/sys/dev/pci/envy.c b/sys/dev/pci/envy.c index 7b56074de4d..57c07f00072 100644 --- a/sys/dev/pci/envy.c +++ b/sys/dev/pci/envy.c @@ -1,4 +1,4 @@ -/* $OpenBSD: envy.c,v 1.5 2008/01/14 01:23:53 jakemsr Exp $ */ +/* $OpenBSD: envy.c,v 1.6 2008/02/21 01:37:55 ratchov Exp $ */ /* * Copyright (c) 2007 Alexandre Ratchov <alex@caoua.org> * @@ -233,6 +233,7 @@ envy_ak_write(struct envy_softc *sc, int dev, int addr, int data) { int bits, i, reg; + DPRINTFN(2, "envy_ak_write: %d, %d, 0x%x\n", dev, addr, data); sc->ak[dev].reg[addr] = data; reg = envy_cci_read(sc, ENVY_GPIO_DATA); @@ -301,6 +302,11 @@ envy_reset(struct envy_softc *sc) delay(300); envy_ak_write(sc, dev, AK_RST, AK_RST_AD | AK_RST_DA); envy_ak_write(sc, dev, AK_FMT, AK_FMT_IIS24); + sc->ak[dev].reg[AK_DEEMVOL] = AK_DEEM_OFF; + sc->ak[dev].reg[AK_ADC_GAIN0] = 0x7f; + sc->ak[dev].reg[AK_ADC_GAIN1] = 0x7f; + sc->ak[dev].reg[AK_DAC_GAIN0] = 0x7f; + sc->ak[dev].reg[AK_DAC_GAIN1] = 0x7f; } /* @@ -465,7 +471,7 @@ envy_mon_getvol(struct envy_softc *sc, int idx, int ch, int *val) { bus_space_write_2(sc->mt_iot, sc->mt_ioh, ENVY_MT_MONIDX, idx); reg = bus_space_read_1(sc->mt_iot, sc->mt_ioh, ENVY_MT_MONDATA + ch); - *val = 0x7f - ((reg) & 0x7f); + *val = 0x7f - (reg & 0x7f); } void @@ -873,7 +879,7 @@ envy_query_devinfo(void *self, struct mixer_devinfo *dev) dev->un.s.num_mem = n; return 0; } - if (dev->index < ENVY_MIX_INVAL) { + if (dev->index < ENVY_MIX_ILVL(4)) { out = dev->index - ENVY_MIX_MONITOR; dev->type = AUDIO_MIXER_VALUE; dev->mixer_class = ENVY_MIX_CLASSMON; @@ -884,6 +890,41 @@ envy_query_devinfo(void *self, struct mixer_devinfo *dev) strlcpy(dev->un.v.units.name, AudioNvolume, MAX_AUDIO_DEV_LEN); return 0; } + if (dev->index < ENVY_MIX_OLVL(4)) { /* inputs.line */ + out = dev->index - ENVY_MIX_ILVL(4); + dev->type = AUDIO_MIXER_VALUE; + dev->mixer_class = ENVY_MIX_CLASSIN; + dev->un.v.delta = 2; + dev->un.v.num_channels = 1; + snprintf(dev->label.name, MAX_AUDIO_DEV_LEN, "line%d", out); + strlcpy(dev->un.v.units.name, AudioNvolume, MAX_AUDIO_DEV_LEN); + return 0; + } + if (dev->index < ENVY_MIX_OMUTE(4)) { /* outputs.line */ + out = dev->index - ENVY_MIX_OLVL(4); + dev->type = AUDIO_MIXER_VALUE; + dev->mixer_class = ENVY_MIX_CLASSOUT; + dev->un.v.delta = 2; + dev->un.v.num_channels = 1; + snprintf(dev->label.name, MAX_AUDIO_DEV_LEN, "line%d", out); + strlcpy(dev->un.v.units.name, AudioNvolume, MAX_AUDIO_DEV_LEN); + return 0; + } + if (dev->index < ENVY_MIX_INVAL(4)) { /* outputs.mute */ + out = dev->index - ENVY_MIX_OMUTE(4); + dev->type = AUDIO_MIXER_ENUM; + dev->mixer_class = ENVY_MIX_CLASSOUT; + dev->un.e.member[0].ord = 0; + strlcpy(dev->un.e.member[0].label.name, "off", + MAX_AUDIO_DEV_LEN); + dev->un.e.member[1].ord = 1; + strlcpy(dev->un.e.member[1].label.name, "on", + MAX_AUDIO_DEV_LEN); + dev->un.s.num_mem = 2; + snprintf(dev->label.name, MAX_AUDIO_DEV_LEN, + "mute%u-%u", 2 * out, 2 * out + 1); + return 0; + } return ENXIO; } @@ -906,13 +947,33 @@ envy_get_port(void *self, struct mixer_ctrl *ctl) ctl->un.ord = envy_spdout_getsrc(sc, out); return 0; } - if (ctl->dev < ENVY_MIX_INVAL) { + if (ctl->dev < ENVY_MIX_ILVL(4)) { out = ctl->dev - ENVY_MIX_MONITOR; envy_mon_getvol(sc, out / 2, out % 2, &val); ctl->un.value.num_channels = 1; ctl->un.value.level[0] = 2 * val; return 0; } + if (ctl->dev < ENVY_MIX_OLVL(4)) { + out = ctl->dev - ENVY_MIX_ILVL(4); + val = envy_ak_read(sc, out / 2, (out % 2) + AK_ADC_GAIN0); + ctl->un.value.num_channels = 1; + ctl->un.value.level[0] = 2 * val; + return 0; + } + if (ctl->dev < ENVY_MIX_OMUTE(4)) { + out = ctl->dev - ENVY_MIX_OLVL(4); + val = envy_ak_read(sc, out / 2, (out % 2) + AK_DAC_GAIN0); + ctl->un.value.num_channels = 1; + ctl->un.value.level[0] = 2 * val; + return 0; + } + if (ctl->dev < ENVY_MIX_INVAL(4)) { + out = ctl->dev - ENVY_MIX_OMUTE(4); + val = envy_ak_read(sc, out, AK_DEEMVOL); + ctl->un.ord = (val & AK_MUTE) ? 1 : 0; + return 0; + } return ENXIO; } @@ -940,7 +1001,7 @@ envy_set_port(void *self, struct mixer_ctrl *ctl) envy_spdout_setsrc(sc, out, ctl->un.ord); return 0; } - if (ctl->dev < ENVY_MIX_INVAL) { + if (ctl->dev < ENVY_MIX_ILVL(4)) { out = ctl->dev - ENVY_MIX_MONITOR; if (ctl->un.value.num_channels != 1) { return EINVAL; @@ -949,6 +1010,30 @@ envy_set_port(void *self, struct mixer_ctrl *ctl) envy_mon_setvol(sc, out / 2, out % 2, val); return 0; } + if (ctl->dev < ENVY_MIX_OLVL(4)) { + if (ctl->un.value.num_channels != 1) + return EINVAL; + out = ctl->dev - ENVY_MIX_ILVL(4); + val = ctl->un.value.level[0] / 2; + envy_ak_write(sc, out / 2, (out % 2) + AK_ADC_GAIN0, val); + return 0; + } + if (ctl->dev < ENVY_MIX_OMUTE(4)) { + if (ctl->un.value.num_channels != 1) + return EINVAL; + out = ctl->dev - ENVY_MIX_OLVL(4); + val = ctl->un.value.level[0] / 2; + envy_ak_write(sc, out / 2, (out % 2) + AK_DAC_GAIN0, val); + return 0; + } + if (ctl->dev < ENVY_MIX_INVAL(4)) { + if (ctl->un.ord >= 2) + return EINVAL; + out = ctl->dev - ENVY_MIX_OMUTE(4); + val = AK_DEEM_OFF | (ctl->un.ord ? AK_MUTE : 0); + envy_ak_write(sc, out, AK_DEEMVOL, val); + return 0; + } return ENXIO; } diff --git a/sys/dev/pci/envyreg.h b/sys/dev/pci/envyreg.h index f46521680da..a4bdb0bdacb 100644 --- a/sys/dev/pci/envyreg.h +++ b/sys/dev/pci/envyreg.h @@ -1,4 +1,4 @@ -/* $OpenBSD: envyreg.h,v 1.2 2007/10/28 18:25:21 fgsch Exp $ */ +/* $OpenBSD: envyreg.h,v 1.3 2008/02/21 01:37:55 ratchov Exp $ */ /* * Copyright (c) 2007 Alexandre Ratchov <alex@caoua.org> * @@ -127,7 +127,8 @@ #define ENVY_MT_SPDSRC_MON 0x01 #define ENVY_MT_SPDSRC_LINE 0x02 #define ENVY_MT_SPDSRC_SPD 0x03 -#define ENVY_MT_SPDSRC_MASK 0x04 +#define ENVY_MT_SPDSRC_BITS 0x02 +#define ENVY_MT_SPDSRC_MASK ((1 << ENVY_MT_SPDSRC_BITS) - 1) #define ENVY_MT_SPDSEL_BITS 0x4 #define ENVY_MT_SPDSEL_MASK ((1 << ENVY_MT_SPDSEL_BITS) - 1) #define ENVY_MT_INSEL 0x34 @@ -160,6 +161,10 @@ #define AK_FMT_IIS24 0x60 #define AK_FMT_LSB24 0x80 #define AK_DEEMVOL 0x03 +#define AK_DEEM_44K1 0x00 +#define AK_DEEM_OFF 0x01 +#define AK_DEEM_48K 0x02 +#define AK_DEEM_32K 0x03 #define AK_MUTE 0x80 #define AK_ADC_GAIN0 0x04 #define AK_ADC_GAIN1 0x05 diff --git a/sys/dev/pci/envyvar.h b/sys/dev/pci/envyvar.h index ee40f6599b4..143349aaaad 100644 --- a/sys/dev/pci/envyvar.h +++ b/sys/dev/pci/envyvar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: envyvar.h,v 1.2 2007/10/28 18:25:21 fgsch Exp $ */ +/* $OpenBSD: envyvar.h,v 1.3 2008/02/21 01:37:55 ratchov Exp $ */ /* * Copyright (c) 2007 Alexandre Ratchov <alex@caoua.org> * @@ -79,7 +79,10 @@ struct envy_softc { #define ENVY_MIX_CLASSMON 3 #define ENVY_MIX_OUTSRC 4 #define ENVY_MIX_MONITOR 14 -#define ENVY_MIX_INVAL 34 +#define ENVY_MIX_ILVL(nak) 34 +#define ENVY_MIX_OLVL(nak) (ENVY_MIX_ILVL(nak) + 2 * (nak)) +#define ENVY_MIX_OMUTE(nak) (ENVY_MIX_OLVL(nak) + 2 * (nak)) +#define ENVY_MIX_INVAL(nak) (ENVY_MIX_OMUTE(nak) + (nak)) #define ENVY_MIX_OUTSRC_LINEIN 0 #define ENVY_MIX_OUTSRC_SPDIN 8 |