code: plan9front

Download patch

ref: 21ae833386940c7414ecaaf1012c0ec87f0088e5
parent: c3a430e6824a8f1f08f28a8df24b4b64266b06f9
author: Sigrid Solveig Haflínudóttir <sigrid@ftrv.se>
date: Fri Aug 19 08:33:59 EDT 2022

aux/wm8960: fix chopped audio on the speakers with high volume

Jack detect becomes extremely unstable when playing on spk and the
volume is very high - DAC start to switch back and forth between two
outputs.  Solve this by always attenuating by -6dB and somewhat
limiting the volume on DAC ("master") - to 0xf9 instead of 0xff (max).

Also fix wrong output status reporting and remove "same volume - ignore"
optimization in setvol.

--- a/sys/src/cmd/aux/wm8960.c
+++ b/sys/src/cmd/aux/wm8960.c
@@ -65,11 +65,12 @@
 	wr(0x1a, reg1a);
 	if(o->toggle != nil)
 		o->toggle(o, on);
+	o->on = on;
 }
 
 static Out out[Nout] =
 {
-	[Dac] = {"master", 0x0a, 0xff, 3<<7, nil, 0},
+	[Dac] = {"master", 0x0a, 0xf9, 3<<7, nil, 0},
 	[Hp] = {"hp", 0x02, 0x7f, 3<<5, nil, 0},
 	[Spk] = {"spk", 0x28, 0x7f, 3<<3, classdspk, 0},
 };
@@ -79,13 +80,11 @@
 {
 	int zc;
 
-	l = CLAMP(l, 0, 100);
-	r = CLAMP(r, 0, 100);
-	if(l == o->vol[0] && r == o->vol[1])
-		return;
-	if((o->vol[0] = l) > 0)
+	o->vol[0] = l = CLAMP(l, 0, 100);
+	o->vol[1] = r = CLAMP(r, 0, 100);
+	if(l > 0)
 		l += o->volmax - 100;
-	if((o->vol[1] = r) > 0)
+	if(r > 0)
 		r += o->volmax - 100;
 
 	zc = o->volmax < 0x80;
@@ -161,6 +160,13 @@
 static void
 reset(void)
 {
+	int i;
+
+	for(i = 0; i < Nout; i++){
+		out[i].vol[0] = -1;
+		out[i].vol[1] = -1;
+	}
+
 	toggle(out+Dac, 0);
 	wr(0x1c, 1<<7 | 1<<4 | 1<<3 | 1<<2); /* Vmid/r bias; Vgs/r on; Vmid soft start */
 	wr(0x19, 0<<7); /* Vmid off, Vref off */
@@ -172,7 +178,7 @@
 
 	wr(0x07, 1<<6 | 2); /* master mode; i²s, 16-bit words */
 
-	wr(0x17, 1<<8 | 3<<6 | 1<<1); /* thermal shutdown on; avdd=3.3v; slow clock on */
+	wr(0x17, 1<<8 | 3<<6 | 0<<1); /* thermal shutdown on; avdd=3.3v; slow clock on */
 
 	wr(0x06, 1<<3 | 1<<2); /* ramp up DAC volume slowly */
 	wr(0x2f, 3<<2); /* output mixer on */
@@ -186,7 +192,11 @@
 	wr(0x1c, 1<<3); /* done with anti-pop */
 	wr(0x19, 1<<7 | 1<<6); /* Vref on */
 
-	wr(0x30, 2<<4 | 2<<2 | 1<<1); /* JD2 jack detect; Tsense on */
+	/*
+	 * Debounced jack detect output on gpio - no that it is used, but it
+	 * could be soldered to SoC's input and actually become useful.
+	 */
+	wr(0x30, 3<<4 | 2<<2 | 1<<1); /* JD2 jack detect in; Tsense on */
 	wr(0x1b, 1<<3); /* HP_[LR] responsive to jack detect */
 	wr(0x18, 1<<6); /* HP switch on; high = HP */
 
@@ -196,10 +206,17 @@
 	toggle(out+Dac, 1);
 
 	/* sensible defaults */
-	setvol(out+Spk, 80, 80);
-	setvol(out+Hp, 65, 65);
+	setvol(out+Spk, 100, 100);
+	setvol(out+Hp, 75, 75);
 	setvol(out+Dac, 80, 80);
-	wr(0x05, 0<<3); /* unmute DAC */
+
+	/*
+	 * Jack detect becomes extremely unstable when playing on spk and the
+	 * volume is very high - DAC start to switch back and forth between two
+	 * outputs.  Solve this by always attenuating by -6dB and somewhat limiting
+	 * the volume on DAC ("master") - to 0xf9 instead of 0xff (max).
+	 */
+	wr(0x05, 1<<7 | 0<<3); /* unmute DAC */
 }
 
 static void