[alsa-devel] [PATCH 2/3] sb_mixer: Autodetect optional SB16 mixer controls

Ondrej Zary linux at rainbow-software.org
Tue May 22 21:44:55 CEST 2012


Tone (bass/treble), gain and 3D mixer controls are not present on all SB16 cards.

This attempts to detect chip type and enable them only if they're really present.

Signed-off-by: Ondrej Zary <linux at rainbow-software.org>

--- a/sound/isa/sb/sb_mixer.c
+++ b/sound/isa/sb/sb_mixer.c
@@ -592,10 +592,6 @@ static struct sbmix_elem snd_sb16_controls[] = {
 	SB_SINGLE("Mic Playback Switch", SB_DSP4_OUTPUT_SW, 0, 1),
 	SB_SINGLE("Mic Volume", SB_DSP4_MIC_DEV, 3, 31),
 	SB_SINGLE("Beep Volume", SB_DSP4_SPEAKER_DEV, 6, 3),
-	SB_DOUBLE("Gain Capture Volume",
-		  SB_DSP4_IGAIN_DEV, (SB_DSP4_IGAIN_DEV + 1), 6, 6, 3),
-	SB_DOUBLE("Gain Playback Volume",
-		  SB_DSP4_OGAIN_DEV, (SB_DSP4_OGAIN_DEV + 1), 6, 6, 3),
 	SB16_INPUT_SW("Line Capture Route",
 		      SB_DSP4_INPUT_LEFT, SB_DSP4_INPUT_RIGHT, 4, 3),
 	SB_DOUBLE("Line Playback Switch",
@@ -603,13 +599,25 @@ static struct sbmix_elem snd_sb16_controls[] = {
 	SB_DOUBLE("Line Volume",
 		  SB_DSP4_LINE_DEV, (SB_DSP4_LINE_DEV + 1), 3, 3, 31),
 	SB_SINGLE("Mic Auto Gain", SB_DSP4_MIC_AGC, 0, 1),
-	SB_SINGLE("3D Control - Switch", SB_DSP4_3DSE, 0, 1),
+};
+
+static struct sbmix_elem snd_sb16_tone_ctls[] = {
 	SB_DOUBLE("Tone Control - Bass",
 		  SB_DSP4_BASS_DEV, (SB_DSP4_BASS_DEV + 1), 4, 4, 15),
 	SB_DOUBLE("Tone Control - Treble",
-		  SB_DSP4_TREBLE_DEV, (SB_DSP4_TREBLE_DEV + 1), 4, 4, 15)
+		  SB_DSP4_TREBLE_DEV, (SB_DSP4_TREBLE_DEV + 1), 4, 4, 15),
+};
+
+static struct sbmix_elem snd_sb16_gain_ctls[] = {
+	SB_DOUBLE("Gain Capture Volume",
+		  SB_DSP4_IGAIN_DEV, (SB_DSP4_IGAIN_DEV + 1), 6, 6, 3),
+	SB_DOUBLE("Gain Playback Volume",
+		  SB_DSP4_OGAIN_DEV, (SB_DSP4_OGAIN_DEV + 1), 6, 6, 3),
 };
 
+static struct sbmix_elem snd_sb16_3d_ctl =
+	SB_SINGLE("3D Control - Switch", SB_DSP4_3DSE, 0, 1);
+
 static unsigned char snd_sb16_init_values[][2] = {
 	{ SB_DSP4_MASTER_DEV + 0, 0 },
 	{ SB_DSP4_MASTER_DEV + 1, 0 },
@@ -720,6 +728,71 @@ static unsigned char snd_als4000_init_values[][2] = {
 	{ SB_ALS4000_MIC_IN_GAIN, 0 },
 };
 
+static int snd_sbmixer_sb16_opt_init(struct snd_sb *chip)
+{
+	int idx, err;
+	enum { CLASSIC, CT2504, CT2505, CT2511, CT8903, CT8920 } sb16_type;
+	/*
+	   The detection is a mess because some chips have registers that
+	   appear to work (read/write) but don't do anything. This applies
+	   mainly to tone controls which are present on all SB16 cards but
+	   do nothing on all Vibra chips except CT2502. Also CT8903 appears to
+	   have additional switch registers but they have no effect too.
+	   CT8920 has non-working gain.
+
+	   This tries to detect chip type. CLASSIC means older non-integrated
+	   cards (CT1746/CT1747/CT1749 + CT1745 mixer).
+	   No detection code for CT2501 Vibra 16, CT2502 Vibra 16Pro,
+	   CT2508 Vibra 16CL and CT2510 Vibra 16X (lack of HW for testing).
+	*/
+	sb16_type = CLASSIC;
+	if (snd_sbmixer_read(chip, SB_DSP4_IRQSTATUS) & 0x40) {
+		/* read chip ID (only present on newer (PnP?) chips) */
+		u16 id = snd_sbmixer_read(chip, 0xfd) |
+			 snd_sbmixer_read(chip, 0xfe) << 8;
+		printk("sb16 id=0x%04x\n", id);
+		switch (id) {
+		case 0xffff:	/* No ID? Assume CT2504 Vibra 16S */
+			sb16_type = CT2504;
+			break;
+		case 0x0721:	/* CT2505 Vibra 16C */
+			sb16_type = CT2505;
+			break;
+		case 0x0810:	/* CT2511 Vibra 16XV */
+			sb16_type = CT2511;
+			break;
+		case 0x1190:	/* CT8903 AWE64 */
+			sb16_type = CT8903;
+			break;
+		case 0x1241:	/* CT8920 AWE64 */
+			sb16_type = CT8920;
+			break;
+		}
+	}
+	/* tone controls */
+	if (sb16_type == CLASSIC || sb16_type == CT8903 || sb16_type == CT8920)
+		for (idx = 0; idx < ARRAY_SIZE(snd_sb16_tone_ctls); idx++) {
+			err = snd_sbmixer_add_ctl_elem(chip, &snd_sb16_tone_ctls[idx]);
+			if (err < 0)
+				return err;
+		}
+	/* gain */
+	if (sb16_type == CLASSIC || sb16_type == CT8903)
+		for (idx = 0; idx < ARRAY_SIZE(snd_sb16_gain_ctls); idx++) {
+			err = snd_sbmixer_add_ctl_elem(chip, &snd_sb16_gain_ctls[idx]);
+			if (err < 0)
+				return err;
+		}
+	/* 3D Stereo Enhancement */
+	if (snd_sbmixer_read(chip, SB_DSP4_3DSE) != 0xff) {
+		err = snd_sbmixer_add_ctl_elem(chip, &snd_sb16_3d_ctl);
+		if (err < 0)
+			return err;
+	}
+
+	return 0;
+}
+
 /*
  */
 static int snd_sbmixer_init(struct snd_sb *chip,
@@ -750,6 +823,14 @@ static int snd_sbmixer_init(struct snd_sb *chip,
 		if (err < 0)
 			return err;
 	}
+
+	/* detect optional SB16 controls */
+	if (controls == snd_sb16_controls) {
+		err = snd_sbmixer_sb16_opt_init(chip);
+		if (err < 0)
+			return err;
+	}
+
 	snd_component_add(card, name);
 	strcpy(card->mixername, name);
 	return 0;

-- 
Ondrej Zary


More information about the Alsa-devel mailing list