kern/84728: [sound] [patch] ac97 broken mixing capabilities checking

Ariff Abdullah skywizard at MyBSD.org.my
Wed Aug 10 23:47:23 GMT 2005


On Wed, 10 Aug 2005 23:30:20 GMT
Michael Seyfert <michaels at sdf.lonestar.org> wrote:
>  No good.. please try this one:
>  
>  --- sys/dev/sound/pcm/ac97.c.orig	Wed Aug 10 16:25:42 2005
>  +++ sys/dev/sound/pcm/ac97.c	Wed Aug 10 16:25:53 2005
>  @@ -618,25 +618,12 @@
>   			}
>   			if ((j & 0x8000)) {
>   				j = ((1 << 6) - 1) << codec->mix[i].ofs;
>  -				if (codec->mix[i].mute)
>  -					j |= 0x8000;
>   				ac97_wrcd(codec, codec->mix[i].reg, j);
>   				j = ac97_rdcd(codec, codec->mix[i].reg) & j;
>   				j >>= codec->mix[i].ofs;
>  -				if (codec->mix[i].reg == AC97_MIX_TONE &&
>  -						((j & 0x0001) == 0x0000))
>  -					j >>= 1;
>  -				for (k = 0; j != 0; k++)
>  -					j >>= 1;
>  -				for (j = 0; k != 0; j++)
>  -					k >>= 1;
>  -				if (j != 0) {
>  -					codec->mix[i].enable = 1;
>  -#if 0
>  -					codec->mix[i].bits = j;
>  -#endif
>  -				} else
>  -					codec->mix[i].enable = 0;
>  +				codec->mix[i].enable = (j != 0 && j != old)? 1 : 0;
>  +				for (k = 1; j & (1 << k); k++);
>  +				codec->mix[i].bits = j? k : 0;
>   			} else
>   				codec->mix[i].enable = 0;
>   			ac97_wrcd(codec, codec->mix[i].reg, old);

No good for various STAC* / ALC (the reason for why this new detection mechanism). Ok.. I think this will do the job for both of us and others too:

--- sys/dev/sound/pcm/ac97.c.orig	Thu Aug 11 07:34:15 2005
+++ sys/dev/sound/pcm/ac97.c	Thu Aug 11 07:37:04 2005
@@ -74,9 +74,9 @@
 
 static const struct ac97mixtable_entry ac97mixtable_default[32] = {
     /*	[offset]			reg	     bits of st mu re mk en */
-	[SOUND_MIXER_VOLUME]	= { AC97_MIX_MASTER, 	5, 0, 1, 1, 6, 0, 1 },
-	[SOUND_MIXER_OGAIN]	= { AC97_MIX_AUXOUT, 	5, 0, 1, 1, 0, 0, 0 },
-	[SOUND_MIXER_PHONEOUT]	= { AC97_MIX_MONO, 	5, 0, 0, 1, 7, 0, 0 },
+	[SOUND_MIXER_VOLUME]	= { AC97_MIX_MASTER, 	6, 0, 1, 1, 6, 0, 1 },
+	[SOUND_MIXER_OGAIN]	= { AC97_MIX_AUXOUT, 	6, 0, 1, 1, 0, 0, 0 },
+	[SOUND_MIXER_PHONEOUT]	= { AC97_MIX_MONO, 	6, 0, 0, 1, 7, 0, 0 },
 	[SOUND_MIXER_BASS]	= { AC97_MIX_TONE, 	4, 8, 0, 0, 0, 1, 0 },
 	[SOUND_MIXER_TREBLE]	= { AC97_MIX_TONE, 	4, 0, 0, 0, 0, 1, 0 },
 	[SOUND_MIXER_PCM]	= { AC97_MIX_PCM, 	5, 0, 1, 1, 0, 0, 1 },
@@ -283,7 +283,22 @@
 u_int16_t
 ac97_rdcd(struct ac97_info *codec, int reg)
 {
-	return AC97_READ(codec->methods, codec->devinfo, reg);
+	u_int16_t j, k, i = 0;
+
+	j = AC97_READ(codec->methods, codec->devinfo, reg);
+	k = AC97_READ(codec->methods, codec->devinfo, reg);
+	while (j != k && i < 100) {
+		j = AC97_READ(codec->methods, codec->devinfo, reg);
+		k = AC97_READ(codec->methods, codec->devinfo, reg);
+		i++;
+	}
+#if 0
+	if (i > 0) {
+		device_printf(codec->dev, "%s(): Inconsistent register value at"
+				" 0x%08x (retry: %d)\n", __func__, reg, i);
+	}
+#endif
+	return k;
 }
 
 void
@@ -617,24 +632,25 @@
 				j = ac97_rdcd(codec, codec->mix[i].reg);
 			}
 			if ((j & 0x8000)) {
-				j = ((1 << 6) - 1) << codec->mix[i].ofs;
+				j = ((1 << codec->mix[i].bits) - 1) << codec->mix[i].ofs;
 				if (codec->mix[i].mute)
 					j |= 0x8000;
 				ac97_wrcd(codec, codec->mix[i].reg, j);
-				j = ac97_rdcd(codec, codec->mix[i].reg) & j;
-				j >>= codec->mix[i].ofs;
+				k = ac97_rdcd(codec, codec->mix[i].reg) & (j & ~0x8000);
+				k >>= codec->mix[i].ofs;
 				if (codec->mix[i].reg == AC97_MIX_TONE &&
-						((j & 0x0001) == 0x0000))
-					j >>= 1;
-				for (k = 0; j != 0; k++)
-					j >>= 1;
-				for (j = 0; k != 0; j++)
+						((k & 0x0001) == 0x0000))
 					k >>= 1;
+				j = 0;
+				while (k >> j)
+					j++;
 				if (j != 0) {
-					codec->mix[i].enable = 1;
 #if 0
-					codec->mix[i].bits = j;
+					device_printf(codec->dev, "%d: (%d) %d -> %d\n",
+							i, k, codec->mix[i].bits, j);
 #endif
+					codec->mix[i].enable = 1;
+					codec->mix[i].bits = j;
 				} else
 					codec->mix[i].enable = 0;
 			} else



--

Ariff Abdullah
MyBSD

http://www.MyBSD.org.my (IPv6/IPv4)
http://staff.MyBSD.org.my (IPv6/IPv4)
http://tomoyo.MyBSD.org.my (IPv6/IPv4)


More information about the freebsd-bugs mailing list