summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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;