From alsa-devel-owner@alsa.jcu.cz  Thu Jul 16 23:55:46 1998
Received: from fleming.jimpick.com (jim@fleming.jimpick.com [204.209.212.123])
	by marvin.jcu.cz (8.8.8/8.8.8) with ESMTP id XAA19360
	for <alsa-devel@alsa.jcu.cz>; Thu, 16 Jul 1998 23:55:37 +0200
Received: (from jim@localhost)
	by fleming.jimpick.com (8.9.1/8.9.1/Debian/GNU) id OAA19265;
	Thu, 16 Jul 1998 14:55:33 -0700
To: alsa-devel@alsa.jcu.cz
Subject: Hardware mute on the SB16
Mime-Version: 1.0 (generated by tm-edit 7.108)
Content-Type: text/plain; charset=US-ASCII
From: Jim Pick <jim@jimpick.com>
Date: 16 Jul 1998 14:55:31 -0700
Message-ID: <87n2a94g18.fsf@fleming.jimpick.com>
Reply-To: alsa-devel@alsa.jcu.cz
Sender: alsa-devel-owner@alsa.jcu.cz
Precedence: list



Hi,

I installed ALSA (from the Debian packages) yesterday because I was
looking for a solution to a problem I was having.  I've got a headset
that I wanted to use for telephony, but in order to record at a decent
volume for recording on the MIC input, I've got to bump up the level
pretty high.

I've got a really old AWE32 (ie. SB16 based).

Unfortunately, the SB16 mixer uses the same register for the MIC on
both the input and output mixers.  So if the output mixer has the MIC
switched on, and I have the level set high (so I can record), I get
blasted in the ear whenever I talk, giving me an earache.

The Linux/OSS driver (in 2.0.34) doesn't seem to have the API to
toggle off the MIC input to the output mixer (which goes to my
earphone) - it can only reduce the volume to zero, which means I can't
record.  so I took a look at ALSA.

The ALSA 0.1.4 driver seemed to have the API, but when I muted, I
could record on the input mixer.  Checking into it further, I see
that it only had software muting implemented.  So I made a patch to
do hardware muting, which I'll attach at the end.

Please tell me if it's good enough to apply.  I'm using it here, and
it does the job for me.  The only reason I can see not to apply it is
if you really intend for "mute" to work on the input mixer (for
recording) as well (which I don't want).

Cheers,

 - Jim

(apply against lowlevel/sb/mixer.c)

--- mixer.c.old	Thu Jul 16 12:38:51 1998
+++ mixer.c	Thu Jul 16 14:02:06 1998
@@ -208,6 +208,7 @@
  *		0x000000ff - register
  *              0x00000f00 - left shift
  *              0x0000f000 - right shift
+ *              0x00ff0000 - mute register
  */
 
 static void snd_sb16mixer_record_source( snd_kmixer_t *mixer, snd_kmixer_channel_t *channel, int enable )
@@ -235,6 +236,32 @@
   snd_spin_unlock( sbmix, mixer, &flags );
 }
 
+static void snd_sb16mixer_mute( snd_kmixer_t *mixer, snd_kmixer_channel_t *channel, unsigned int mute )
+{
+  unsigned long flags;
+  unsigned int mask;
+  sbmixer_t *sbmix;
+  
+  sbmix = (sbmixer_t *)mixer -> private_data;  
+  switch ( channel -> hw.priority ) {
+    case SND_MIXER_PRI_MIC:	mask = 0x010000; break;
+    case SND_MIXER_PRI_CD:	mask = 0x040000; break;
+    case SND_MIXER_PRI_LINE:	mask = 0x100000; break;
+    case SND_MIXER_PRI_SYNTHESIZER: mask = 0x400000; break;
+    default: 			mask = 0; break;       
+  }
+  if ( mute )
+    mixer -> private_value &= ~mask;
+   else
+    mixer -> private_value |= mask;
+
+  snd_spin_lock( sbmix, mixer, &flags );
+  snd_sbmixer_write( sbmix, SB_DSP4_OUTPUT, (mixer -> private_value >> 16) & 0xff );
+  snd_spin_unlock( sbmix, mixer, &flags );
+  snd_printk( "hwmute: reg = 0x%x\n", (mixer -> private_value >>16) & 0xff );
+
+}
+
 static void snd_sb16mixer_volume_level( snd_kmixer_t *mixer, snd_kmixer_channel_t *channel, int left, int right )
 {
   unsigned long flags;
@@ -360,14 +387,14 @@
     SND_MIXER_PRI_PARENT,	/* parent priority */
     SND_MIXER_ID_LINE,		/* device name */
     SND_MIXER_OSS_LINE,		/* OSS device # */
-    0, 1, 1, 0, 1,		/* mute/stereo/record/digital/input */
+    1, 1, 1, 0, 1,		/* mute/stereo/record/digital/input */
     0, 31,			/* max value */
     -6200, 0, 200,		/* min, max, step - dB */
     SB_DSP4_PRIVATE( SB_DSP4_LINE_DEV, 3, 3 ),
     NULL,			/* compute dB -> linear */
     NULL,			/* compute linear -> dB */
     snd_sb16mixer_record_source,/* record source */
-    NULL,			/* set mute */
+    snd_sb16mixer_mute,		/* set mute */
     snd_sb16mixer_volume_level,	/* set volume level */
   },
   {
@@ -375,14 +402,14 @@
     SND_MIXER_PRI_PARENT,	/* parent priority */
     SND_MIXER_ID_MIC,		/* device name */
     SND_MIXER_OSS_MIC,		/* OSS device # */
-    0, 0, 1, 0,	1,		/* mute/stereo/record/digital/input */
+    1, 0, 1, 0,	1,		/* mute/stereo/record/digital/input */
     0, 31,			/* max value */
     -6200, 0, 200,		/* min, max, step - dB */
     SB_DSP4_PRIVATE( SB_DSP4_MIC_DEV, 3, 3 ),
     NULL,			/* compute dB -> linear */
     NULL,			/* compute linear -> dB */
     snd_sb16mixer_record_source,/* record source */
-    NULL,			/* set mute */
+    snd_sb16mixer_mute,		/* set mute */
     snd_sb16mixer_volume_level,	/* set volume level */
   },
   {
@@ -390,14 +417,14 @@
     SND_MIXER_PRI_MASTER,	/* parent priority */
     SND_MIXER_ID_CD,		/* device name */
     SND_MIXER_OSS_CD,		/* OSS device # */
-    0, 1, 1, 0, 1,		/* mute/stereo/record/digital/input */
+    1, 1, 1, 0, 1,		/* mute/stereo/record/digital/input */
     0, 31,			/* max value */
     -6200, 0, 200,		/* min, max, step - dB */
     SB_DSP4_PRIVATE( SB_DSP4_CD_DEV, 3, 3 ),
     NULL,			/* compute dB -> linear */
     NULL,			/* compute linear -> dB */
     snd_sb16mixer_record_source,/* record source */
-    NULL,			/* set mute */
+    snd_sb16mixer_mute,		/* set mute */
     snd_sb16mixer_volume_level,	/* set volume level */
   },
   {



