summaryrefslogtreecommitdiff
path: root/sys/dev/pci
diff options
context:
space:
mode:
authorAlexandre Ratchov <ratchov@cvs.openbsd.org>2008-02-21 01:37:56 +0000
committerAlexandre Ratchov <ratchov@cvs.openbsd.org>2008-02-21 01:37:56 +0000
commit8091041d251c8df8725bb2ed2bb29d70555eb729 (patch)
tree357ad916babc674bdf782a8476ad4f78416ca7a3 /sys/dev/pci
parent702b8139e944833f90396dd4de094a09b5dde898 (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.c95
-rw-r--r--sys/dev/pci/envyreg.h9
-rw-r--r--sys/dev/pci/envyvar.h7
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