summaryrefslogtreecommitdiff
path: root/sys/dev/pci/azalia_codec.c
diff options
context:
space:
mode:
authorDeanna Phillips <deanna@cvs.openbsd.org>2007-07-31 16:14:27 +0000
committerDeanna Phillips <deanna@cvs.openbsd.org>2007-07-31 16:14:27 +0000
commit7a3c4ca27908ce3f8cf4c61564b300fd9646a8cc (patch)
tree5ac695acb9166dba6119d8718269e966ba1221bc /sys/dev/pci/azalia_codec.c
parentf88c2e020d5aa16672d42f95d7d87f8e64d86e13 (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.c14
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