All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] improve dmasound volume handling
@ 2000-12-16 18:29 Daniel Jacobowitz
  0 siblings, 0 replies; only message in thread
From: Daniel Jacobowitz @ 2000-12-16 18:29 UTC (permalink / raw)
  To: linuxppc-dev

[-- Attachment #1: Type: text/plain, Size: 850 bytes --]

I was having a very strange problem with dmasound: aumix would let me
decrease but not increase the volume.  The problem was that aumix only
internally kept the volume on a 0-15 scale, but Linux used 0 (mute) and
1-100.  The rounding error made a 2% increase turn into a 0% change.

I'm not sure this is a good solution, but it's the best I could come up
with; it keeps a 1-100 scale internally, but sets the hardware according to
the converted value.  It's against the linuxppc_2_5 tree.

Dan

/--------------------------------\  /--------------------------------\
|       Daniel Jacobowitz        |__|        SCS Class of 2002       |
|   Debian GNU/Linux Developer    __    Carnegie Mellon University   |
|         dan@debian.org         |  |       dmj+@andrew.cmu.edu      |
\--------------------------------/  \--------------------------------/

[-- Attachment #2: dmasound.diff --]
[-- Type: text/plain, Size: 5599 bytes --]

# This is a BitKeeper generated patch for the following project:
# Project Name:
# This patch format is intended for GNU patch command version 2.5 or higher.
# This patch includes the following deltas:
#	           ChangeSet	1.328   -> 1.329
#	drivers/sound/dmasound/dmasound_awacs.c	1.17    -> 1.18
#
# The following is the BitKeeper ChangeSet Log
# --------------------------------------------
# 00/12/13	drow@voltaire.res.cmu.edu	1.327.1.1
# dmasound_awacs.c	Cache volumes locally
# --------------------------------------------
# 00/12/13	drow@voltaire.res.cmu.edu	1.329
# Merge bk://hq.fsmlabs.com:5005
# into voltaire.res.cmu.edu:/home/drow/bk/linuxppc_2_5
# --------------------------------------------
#
diff -Nru a/drivers/sound/dmasound/dmasound_awacs.c b/drivers/sound/dmasound/dmasound_awacs.c
--- a/drivers/sound/dmasound/dmasound_awacs.c	Wed Dec 13 22:51:46 2000
+++ b/drivers/sound/dmasound/dmasound_awacs.c	Wed Dec 13 22:51:46 2000
@@ -71,6 +71,15 @@
  */
 int awacs_reg[8];

+/* Cached volumes - these simulate a 0-100 volume scale, though we only
+ * have a 15-0 volume scale internally.
+ * Should include other volumes we don't support?  Probably not.
+ */
+#define MASTER_VOLUME 0
+#define SPEAKER_VOLUME 1
+#define RECORD_VOLUME 2
+static int awacs_volumes[3];
+
 #define HAS_16BIT_TABLES
 #undef HAS_8BIT_TABLES

@@ -969,8 +978,23 @@
 	return format;
 }

-#define AWACS_VOLUME_TO_MASK(x)	(15 - ((((x) - 1) * 15) / 99))
-#define AWACS_MASK_TO_VOLUME(y)	(100 - ((y) * 99 / 15))
+/* Go from 1-100 to 15-0 and vice versa. */
+/* Volume 15 on AWACS is "softest", not muted; volume 0 on Linux is muted. */
+#define AWACS_VOLUME_TO_MASK(x)	(15 - ((((x) - 1) * 16) / 100))
+#define AWACS_MASK_TO_VOLUME(y)	(100 - ((y) * 100 / 16))
+
+static int verify_volume(int volume)
+{
+	unsigned int left, right;
+
+	left = volume & 0xFF;
+	if(left > 100)
+		left = 100;
+	right = (volume >> 8) & 0xFF;
+	if(right > 100)
+		right = 100;
+	return left | (right << 8);
+}

 static int awacs_get_volume(int reg, int lshift)
 {
@@ -989,12 +1013,20 @@
 		r1 = awacs_reg[1] | mute;
 	} else {
 		r1 = awacs_reg[1] & ~mute;
+#if 0
+		printk(KERN_DEBUG "Setting volume to %d/%d\n", volume&0xff, (volume>>8)&0xff);
+		printk(KERN_DEBUG "Old register setting was %d/%d\n", (awacs_reg[n]>>lshift)&0xf, awacs_reg[n]&0xf);
+#endif
 		rn = awacs_reg[n] & ~(0xf | (0xf << lshift));
 		rn |= ((AWACS_VOLUME_TO_MASK(volume & 0xff) & 0xf) << lshift);
 		rn |= AWACS_VOLUME_TO_MASK((volume >> 8) & 0xff) & 0xf;
 		awacs_reg[n] = rn;
 		awacs_write((n << 12) | rn);
 		volume = awacs_get_volume(rn, lshift);
+#if 0
+		printk(KERN_DEBUG "Got back volume %d/%d\n", volume&0xff, (volume>>8)&0xff);
+		printk(KERN_DEBUG "New register setting is %d/%d\n", (awacs_reg[n]>>lshift)&0xf, awacs_reg[n]&0xf);
+#endif
 	}
 	if (r1 != awacs_reg[1]) {
 		awacs_reg[1] = r1;
@@ -1005,7 +1037,10 @@

 static int PMacSetVolume(int volume)
 {
-	return awacs_volume_setter(volume, 2, MASK_AMUTE, 6);
+	volume = verify_volume(volume);
+	awacs_volume_setter(volume, 2, MASK_AMUTE, 6);
+	awacs_volumes[MASTER_VOLUME] = volume;
+	return volume;
 }

 static void PMacPlay(void)
@@ -1657,7 +1692,7 @@
 		return IOCTL_OUT(arg, 0);
 	case SOUND_MIXER_READ_VOLUME:
 		data = (awacs_reg[1] & MASK_AMUTE)? 0:
-			awacs_get_volume(awacs_reg[2], 6);
+			awacs_volumes[MASTER_VOLUME];
 		return IOCTL_OUT(arg, data);
 	case SOUND_MIXER_WRITE_VOLUME:
 		IOCTL_IN(arg, data);
@@ -1668,16 +1703,19 @@
 			data = awacs_spkr_vol;
 		else
 			data = (awacs_reg[1] & MASK_CMUTE)? 0:
-				awacs_get_volume(awacs_reg[4], 6);
+				awacs_volumes[SPEAKER_VOLUME];
 		return IOCTL_OUT(arg, data);
 	case SOUND_MIXER_WRITE_SPEAKER:
 		IOCTL_IN(arg, data);
 		if (awacs_revision == 3
 		    && sys_ctrler == SYS_CTRLER_CUDA)
 			awacs_enable_amp(data);
-		else
+		else {
+			data = verify_volume(data);
+			awacs_volumes[SPEAKER_VOLUME] = data;
 			data = awacs_volume_setter(data, 4, MASK_CMUTE, 6);
-		return IOCTL_OUT(arg, data);
+		}
+		return IOCTL_OUT(arg, awacs_volumes[SPEAKER_VOLUME]);
 	case SOUND_MIXER_WRITE_ALTPCM:	/* really bell volume */
 		IOCTL_IN(arg, data);
 		beep_volume = data & 0xff;
@@ -1721,10 +1759,12 @@
 		return IOCTL_OUT(arg, data);
 	case SOUND_MIXER_WRITE_RECLEV:
 		IOCTL_IN(arg, data);
+		data = verify_volume(data);
+		awacs_volumes[RECORD_VOLUME] = data;
 		data = awacs_volume_setter(data, 0, 0, 4);
-		return IOCTL_OUT(arg, data);
+		return IOCTL_OUT(arg, awacs_volumes[RECORD_VOLUME]);
 	case SOUND_MIXER_READ_RECLEV:
-		data = awacs_get_volume(awacs_reg[0], 4);
+		data = awacs_volumes[RECORD_VOLUME];
 		return IOCTL_OUT(arg, data);
 	case MIXER_WRITE(SOUND_MIXER_MONITOR):
 		IOCTL_IN(arg, data);
@@ -1857,10 +1897,12 @@
 		return IOCTL_OUT(arg, data);
 	case SOUND_MIXER_WRITE_RECLEV:
 		IOCTL_IN(arg, data);
+		data = verify_volume(data);
+		awacs_volumes[RECORD_VOLUME] = data;
 		data = awacs_volume_setter(data, 0, 0, 4);
-		return IOCTL_OUT(arg, data);
+		return IOCTL_OUT(arg, awacs_volumes[RECORD_VOLUME]);
 	case SOUND_MIXER_READ_RECLEV:
-		data = awacs_get_volume(awacs_reg[0], 4);
+		data = awacs_volumes[RECORD_VOLUME];
 		return IOCTL_OUT(arg, data);
 	case SOUND_MIXER_OUTMASK:
 		break;
@@ -2124,6 +2166,10 @@
 		awacs_write(awacs_reg[6] + MASK_ADDR6);
 		awacs_write(awacs_reg[7] + MASK_ADDR7);
 	}
+
+	awacs_volumes[MASTER_VOLUME] = (AWACS_MASK_TO_VOLUME(vol) << 8) + AWACS_MASK_TO_VOLUME(vol);
+	awacs_volumes[SPEAKER_VOLUME] = (AWACS_MASK_TO_VOLUME(vol) << 8) + AWACS_MASK_TO_VOLUME(vol);
+	awacs_volumes[RECORD_VOLUME] = 0;

 	/* Initialize recent versions of the awacs */
 	if (awacs_revision == 0) {

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2000-12-16 18:29 UTC | newest]

Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2000-12-16 18:29 [PATCH] improve dmasound volume handling Daniel Jacobowitz

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.