summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormiod <miod@openbsd.org>2011-12-25 00:07:27 +0000
committermiod <miod@openbsd.org>2011-12-25 00:07:27 +0000
commit1129e4725923572ddc42502297059ce44c96e48b (patch)
treeb06117b3d961df4167d406fb90b540d04f5c2c54
parentSupport leading, trailing and double colons in MANPATH (diff)
downloadwireguard-openbsd-1129e4725923572ddc42502297059ce44c96e48b.tar.xz
wireguard-openbsd-1129e4725923572ddc42502297059ce44c96e48b.zip
Fix the documented CAVEAT by forcing the TX gain to minus infinity when
the user asks to only keep the input source enabled, and remember this to keep reporting the previously configured volume values in mixerctl. While there, document the supported encodings and the supported mixer items in the manual page, and the fact that all output sources share the same volume (GX gain) setting.
-rw-r--r--share/man/man4/arcofi.458
-rw-r--r--sys/dev/ic/arcofi.c80
-rw-r--r--sys/dev/ic/arcofivar.h4
3 files changed, 89 insertions, 53 deletions
diff --git a/share/man/man4/arcofi.4 b/share/man/man4/arcofi.4
index 56dabadf511..397f3fdfae7 100644
--- a/share/man/man4/arcofi.4
+++ b/share/man/man4/arcofi.4
@@ -1,4 +1,4 @@
-.\" $OpenBSD: arcofi.4,v 1.2 2011/12/23 09:12:33 jmc Exp $
+.\" $OpenBSD: arcofi.4,v 1.3 2011/12/25 00:07:27 miod Exp $
.\"
.\"
.\" Copyright (c) 2011 Miodrag Vallat.
@@ -15,7 +15,7 @@
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
-.Dd $Mdocdate: December 23 2011 $
+.Dd $Mdocdate: December 25 2011 $
.Dt ARCOFI 4
.Os
.Sh NAME
@@ -39,8 +39,51 @@ This device is found onboard HP 9000 workstations models 425e, 705 and 710.
.Pp
The
.Nm
-is limited to a phone-quality mono, 8-bit, 8000 KHz sound.
+is limited to a phone-quality mono, 8000 KHz sound.
+.Ss AUDIOCTL SETTINGS
+The following encodings are supported:
+.Bl -tag -width AUDIO_ENCODING_SLINEAR_BE, -compact
+.It Li AUDIO_ENCODING_ULAW,
+.It Li AUDIO_ENCODING_ALAW,
+.It Li AUDIO_ENCODING_SLINEAR_BE
+Natively supported.
+.It Li AUDIO_ENCODING_SLINEAR
+Software converted to
+.Li AUDIO_ENCODING_ULAW
+encoding.
+.It Li AUDIO_ENCODING_SLINEAR_LE,
+.It Li AUDIO_ENCODING_ULINEAR_LE,
+.It Li AUDIO_ENCODING_ULINEAR_BE
+Software converted to
+.Li AUDIO_ENCODING_SLINEAR_BE
+encoding.
+.El
+.Ss MIXERCTL SETTINGS
+The
+.Nm
+has three audio ports:
+.Bl -tag -compact
+.It Cm inputs.line
+The
+.Sq line in
+jack connector.
+.It Cm outputs.line
+The
+.Sq line out
+jack connector.
+.It Cm outputs.spkr
+The built-in speaker.
+.El
+Each port has a volume control, and can be muted.
+.Pp
+The
+.Cm outputs.line
+and
+.Cm outputs.spkr
+volume settings are tied to the same hardware setting.
.Sh SEE ALSO
+.Xr audioctl 1 ,
+.Xr mixerctl 1 ,
.Xr ioctl 2 ,
.Xr audio 4 ,
.Xr dio 4 ,
@@ -52,12 +95,3 @@ support for
.Nm
first appeared in
.Ox 5.1 .
-.Sh CAVEATS
-Due to the
-.Dq ARCOFI
-chip being designed for phones, it is not possible to unmute the
-.Sq line in
-channel while muting
-.Em all
-output channels.
-Attempting to do this will cause all channels (input and output) to be unmuted.
diff --git a/sys/dev/ic/arcofi.c b/sys/dev/ic/arcofi.c
index 2341e099dda..435535b8eec 100644
--- a/sys/dev/ic/arcofi.c
+++ b/sys/dev/ic/arcofi.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: arcofi.c,v 1.3 2011/12/24 16:53:40 miod Exp $ */
+/* $OpenBSD: arcofi.c,v 1.4 2011/12/25 00:07:27 miod Exp $ */
/*
* Copyright (c) 2011 Miodrag Vallat.
@@ -187,10 +187,8 @@ struct cfdriver arcofi_cd = {
#define arcofi_write(sc, r, v) \
bus_space_write_1((sc)->sc_iot, (sc)->sc_ioh, (sc)->sc_reg[r], v)
-#define AUDIO_MIDDLE_GAIN ((AUDIO_MAX_GAIN + 1 - AUDIO_MIN_GAIN) / 2)
-
int arcofi_cmd(struct arcofi_softc *, uint8_t, const uint8_t *);
-int arcofi_cr3_to_portmask(uint);
+int arcofi_cr3_to_portmask(uint, int);
int arcofi_gain_to_mi(uint);
uint arcofi_mi_to_gain(int);
uint arcofi_portmask_to_cr3(int);
@@ -534,10 +532,11 @@ arcofi_commit_settings(void *v)
uint8_t cmd[2], csr, ocsr;
#ifdef ARCOFI_DEBUG
- printf("%s: commit_settings, gr %04x gx %04x cr3 %02x cr4 %02x\n",
+ printf("%s: commit_settings, gr %04x gx %04x cr3 %02x cr4 %02x mute %d\n",
sc->sc_dev.dv_xname,
- arcofi_gains[sc->sc_shadow.gr_idx], arcofi_gains[sc->sc_shadow.gx_idx],
- sc->sc_shadow.cr3, sc->sc_shadow.cr4);
+ arcofi_gains[sc->sc_shadow.gr_idx],
+ arcofi_gains[sc->sc_shadow.gx_idx],
+ sc->sc_shadow.cr3, sc->sc_shadow.cr4, sc->sc_shadow.output_mute);
#endif
if (bcmp(&sc->sc_active, &sc->sc_shadow, sizeof(sc->sc_active)) == 0)
@@ -553,12 +552,19 @@ arcofi_commit_settings(void *v)
sc->sc_active.gr_idx = sc->sc_shadow.gr_idx;
}
- if (sc->sc_active.gx_idx != sc->sc_shadow.gx_idx) {
- cmd[0] = arcofi_gains[sc->sc_shadow.gx_idx] >> 8;
- cmd[1] = arcofi_gains[sc->sc_shadow.gx_idx];
+ if (sc->sc_active.gx_idx != sc->sc_shadow.gx_idx ||
+ sc->sc_active.output_mute != sc->sc_shadow.output_mute) {
+ if (sc->sc_shadow.output_mute) {
+ cmd[0] = arcofi_gains[0] >> 8;
+ cmd[1] = arcofi_gains[0];
+ } else {
+ cmd[0] = arcofi_gains[sc->sc_shadow.gx_idx] >> 8;
+ cmd[1] = arcofi_gains[sc->sc_shadow.gx_idx];
+ }
if ((rc = arcofi_cmd(sc, COP_B, cmd)) != 0)
goto error;
sc->sc_active.gx_idx = sc->sc_shadow.gx_idx;
+ sc->sc_active.output_mute = sc->sc_shadow.output_mute;
}
if (sc->sc_active.cr3 != sc->sc_shadow.cr3) {
@@ -696,10 +702,6 @@ arcofi_getdev(void *v, struct audio_device *ad)
/*
* Convert gain table index to AUDIO_MIN_GAIN..AUDIO_MAX_GAIN scale.
- * minus infinity -> 0
- * < 0dB -> up to 127
- * 0dB -> 128
- * > 0dB -> up to 255
*/
int
arcofi_gain_to_mi(uint idx)
@@ -709,13 +711,8 @@ arcofi_gain_to_mi(uint idx)
if (idx == nitems(arcofi_gains) - 1)
return AUDIO_MAX_GAIN;
- if (idx <= NEGATIVE_GAINS + 1)
- return AUDIO_MIN_GAIN +
- (idx * AUDIO_MIDDLE_GAIN) / (NEGATIVE_GAINS + 1);
-
- return AUDIO_MIDDLE_GAIN +
- ((idx - NEGATIVE_GAINS - 1) * AUDIO_MIDDLE_GAIN) /
- (POSITIVE_GAINS + 1);
+ return ((idx - 1) * (AUDIO_MAX_GAIN - AUDIO_MIN_GAIN)) /
+ (nitems(arcofi_gains) - 1) + AUDIO_MIN_GAIN + 1;
}
/*
@@ -729,12 +726,8 @@ arcofi_mi_to_gain(int lvl)
if (lvl >= AUDIO_MAX_GAIN)
return nitems(arcofi_gains) - 1;
- if (lvl <= AUDIO_MIDDLE_GAIN)
- return 1 + ((lvl - AUDIO_MIN_GAIN) * NEGATIVE_GAINS) /
- AUDIO_MIDDLE_GAIN;
-
- return NEGATIVE_GAINS + 1 +
- ((lvl - AUDIO_MIDDLE_GAIN) * POSITIVE_GAINS) / AUDIO_MIDDLE_GAIN;
+ return ((lvl - AUDIO_MIN_GAIN - 1) * (nitems(arcofi_gains) - 1)) /
+ (AUDIO_MAX_GAIN - AUDIO_MIN_GAIN);
}
/*
@@ -755,7 +748,9 @@ arcofi_mi_to_gain(int lvl)
* Each of these can be enabled or disabled indepently, except for
* MIC enabled with H out and LS out disabled, which is not allowed
* by the chip (and makes no sense for a chip which was intended to
- * be used in phones, not voice recorders).
+ * be used in phones, not voice recorders); we cheat by keeping one
+ * output source enabled, but with the output gain forced to minus
+ * infinity to mute it.
*
* The truth table is thus:
*
@@ -764,7 +759,7 @@ arcofi_mi_to_gain(int lvl)
* off off on MUTE
* off on off LH1
* off on on LH3, X input enabled
- * on off off not available
+ * on off off RDY, GX forced to minus infinity
* on off on RDY
* on on off LH2
* on on on LH3
@@ -786,13 +781,13 @@ arcofi_portmask_to_cr3(int mask)
return CR3_MIC_G_17 | CR3_AFEC_LH1;
case AUDIO_SPEAKER | AUDIO_LINE_OUT:
return CR3_MIC_X_INPUT | CR3_AFEC_LH3;
+ case AUDIO_LINE_IN:
+ /* since we can't do this, just... */
+ /* FALLTHROUGH */
case AUDIO_LINE_IN | AUDIO_LINE_OUT:
return CR3_MIC_G_17 | CR3_AFEC_RDY;
case AUDIO_LINE_IN | AUDIO_SPEAKER:
return CR3_MIC_G_17 | CR3_AFEC_LH2;
- case AUDIO_LINE_IN:
- /* since we can't do this, just... */
- /* FALLTHROUGH */
case AUDIO_LINE_IN | AUDIO_SPEAKER | AUDIO_LINE_OUT:
return CR3_MIC_G_17 | CR3_AFEC_LH3;
}
@@ -802,14 +797,15 @@ arcofi_portmask_to_cr3(int mask)
* Convert CR3 to an enabled ports mask.
*/
int
-arcofi_cr3_to_portmask(uint cr3)
+arcofi_cr3_to_portmask(uint cr3, int output_mute)
{
switch (cr3 & CR3_AFEC_MASK) {
default:
case CR3_AFEC_POR:
return 0;
case CR3_AFEC_RDY:
- return AUDIO_LINE_IN | AUDIO_LINE_OUT;
+ return output_mute ?
+ AUDIO_LINE_IN : AUDIO_LINE_IN | AUDIO_LINE_OUT;
case CR3_AFEC_HFS:
case CR3_AFEC_LH1:
return AUDIO_SPEAKER;
@@ -846,7 +842,8 @@ arcofi_set_port(void *v, mixer_ctrl_t *mc)
case ARCOFI_PORT_AUDIO_SPKR_MUTE:
if (mc->type != AUDIO_MIXER_ENUM)
return EINVAL;
- portmask = arcofi_cr3_to_portmask(sc->sc_shadow.cr3);
+ portmask = arcofi_cr3_to_portmask(sc->sc_shadow.cr3,
+ sc->sc_shadow.output_mute);
#ifdef ARCOFI_DEBUG
printf("%s: set_port cr3 %02x -> mask %02x\n",
sc->sc_dev.dv_xname, sc->sc_shadow.cr3, portmask);
@@ -891,9 +888,11 @@ arcofi_set_port(void *v, mixer_ctrl_t *mc)
sc->sc_shadow.cr3 = (sc->sc_shadow.cr3 & CR3_OPMODE_MASK) |
arcofi_portmask_to_cr3(portmask);
+ sc->sc_shadow.output_mute = (portmask == AUDIO_LINE_IN);
#ifdef ARCOFI_DEBUG
- printf("%s: set_port mask %02x -> cr3 %02x\n",
- sc->sc_dev.dv_xname, portmask, sc->sc_shadow.cr3);
+ printf("%s: set_port mask %02x -> cr3 %02x m %d\n",
+ sc->sc_dev.dv_xname, portmask,
+ sc->sc_shadow.cr3, sc->sc_shadow.output_mute);
#endif
return 0;
@@ -921,7 +920,8 @@ arcofi_get_port(void *v, mixer_ctrl_t *mc)
case ARCOFI_PORT_AUDIO_SPKR_MUTE:
if (mc->type != AUDIO_MIXER_ENUM)
return EINVAL;
- portmask = arcofi_cr3_to_portmask(sc->sc_shadow.cr3);
+ portmask = arcofi_cr3_to_portmask(sc->sc_shadow.cr3,
+ sc->sc_shadow.output_mute);
#ifdef ARCOFI_DEBUG
printf("%s: get_port cr3 %02x -> mask %02x\n",
sc->sc_dev.dv_xname, sc->sc_shadow.cr3, portmask);
@@ -1250,8 +1250,8 @@ arcofi_attach(struct arcofi_softc *sc, const char *version)
sc->sc_active.cr3 =
arcofi_portmask_to_cr3(AUDIO_SPEAKER) | CR3_OPMODE_NORMAL;
sc->sc_active.cr4 = CR4_TM | CR4_ULAW;
- sc->sc_active.gr_idx = sc->sc_active.gx_idx =
- arcofi_mi_to_gain(AUDIO_MIDDLE_GAIN);
+ sc->sc_active.gr_idx = sc->sc_active.gx_idx = 1 + NEGATIVE_GAINS;
+ sc->sc_active.output_mute = 0;
bcopy(&sc->sc_active, &sc->sc_shadow, sizeof(sc->sc_active));
/* clear CRAM */
diff --git a/sys/dev/ic/arcofivar.h b/sys/dev/ic/arcofivar.h
index ddfd83c2e25..3f882e3367c 100644
--- a/sys/dev/ic/arcofivar.h
+++ b/sys/dev/ic/arcofivar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: arcofivar.h,v 1.1 2011/12/21 23:12:03 miod Exp $ */
+/* $OpenBSD: arcofivar.h,v 1.2 2011/12/25 00:07:27 miod Exp $ */
/*
* Copyright (c) 2011 Miodrag Vallat.
@@ -33,8 +33,10 @@ struct arcofi_softc {
struct {
uint8_t cr3, cr4;
uint gr_idx, gx_idx;
+ int output_mute;
} sc_active,
sc_shadow;
+
struct {
uint8_t *buf;
uint8_t *past;