diff options
author | Deanna Phillips <deanna@cvs.openbsd.org> | 2007-07-31 16:14:27 +0000 |
---|---|---|
committer | Deanna Phillips <deanna@cvs.openbsd.org> | 2007-07-31 16:14:27 +0000 |
commit | 7a3c4ca27908ce3f8cf4c61564b300fd9646a8cc (patch) | |
tree | 5ac695acb9166dba6119d8718269e966ba1221bc /sys/dev/pci/azalia_codec.c | |
parent | f88c2e020d5aa16672d42f95d7d87f8e64d86e13 (diff) |
In the mixer to device level conversions, round down to the nearest
valid step, and keep them in sync. This lets audio(4) set exact gain
levels based on the mixer delta, and unbreaks volume up/down buttons
in wscons. This also avoids a divide by zero that could occur if the
generic mixer init found an amplifier with zero steps.
Problem noticed and tested by jmc@, similar diff tested by krw@
Diffstat (limited to 'sys/dev/pci/azalia_codec.c')
-rw-r--r-- | sys/dev/pci/azalia_codec.c | 14 |
1 files changed, 11 insertions, 3 deletions
diff --git a/sys/dev/pci/azalia_codec.c b/sys/dev/pci/azalia_codec.c index dbcae5b1332..656175b7112 100644 --- a/sys/dev/pci/azalia_codec.c +++ b/sys/dev/pci/azalia_codec.c @@ -1,4 +1,4 @@ -/* $OpenBSD: azalia_codec.c,v 1.27 2007/07/23 03:41:03 deanna Exp $ */ +/* $OpenBSD: azalia_codec.c,v 1.28 2007/07/31 16:14:26 deanna Exp $ */ /* $NetBSD: azalia_codec.c,v 1.8 2006/05/10 11:17:27 kent Exp $ */ /*- @@ -1320,7 +1320,11 @@ azalia_generic_mixer_from_device_value(const codec_t *this, nid_t nid, int targe printf("unknown target: %d\n", target); dmax = 255; } - return dv * AUDIO_MAX_GAIN / dmax; + if (dv <= 0 || dmax == 0) + return AUDIO_MIN_GAIN; + if (dv >= dmax) + return AUDIO_MAX_GAIN - AUDIO_MAX_GAIN % dmax; + return dv * (AUDIO_MAX_GAIN - AUDIO_MAX_GAIN % dmax) / dmax; #else return dv; #endif @@ -1343,7 +1347,11 @@ azalia_generic_mixer_to_device_value(const codec_t *this, nid_t nid, int target, printf("unknown target: %d\n", target); dmax = 255; } - return uv * dmax / AUDIO_MAX_GAIN; + if (uv <= AUDIO_MIN_GAIN || dmax == 0) + return 0; + if (uv >= AUDIO_MAX_GAIN - AUDIO_MAX_GAIN % dmax) + return dmax; + return uv * dmax / (AUDIO_MAX_GAIN - AUDIO_MAX_GAIN % dmax); #else return uv; #endif |