[alsa-devel] Volume control with mute in the wrong end

Peter Rosin peda at lysator.liu.se
Mon May 2 15:34:51 CEST 2016


Hi!

I'm writing a driver for the max9860 codec

https://datasheets.maximintegrated.com/en/ds/MAX9860.pdf

and it has a digital sidetone control where it can mix in
the left channel ADC into the (mono) DAC output.

The register that controls the sidetone level makes me wonder
how I should wire up DAPM for it. You set the gain for the
sidetone in the same register field as you enable it. I have
a problem though, since the mute value is at the wrong and of
the scale, i.e. you turn the volume up and up and up, and when
you reach "max" it is off. I did try to declare a TLV range
like so:

/* The dvst field has its mute in the wrong end. Sigh. */
static const DECLARE_TLV_DB_RANGE(dvst_tlv,
	 0, 30, TLV_DB_SCALE_ITEM(-6000, 200, 0),
	31, 31, TLV_DB_SCALE_ITEM(0, 0, 1));

and then hook it that up with a dapm mixer:

static const struct snd_kcontrol_new max9860_mixer_controls[] = {
	SOC_DAPM_SINGLE_TLV("Sidetone Volume", MAX9860_DACGAIN,
		MAX9860_DVST_SHIFT, 31, 1, dvst_tlv),
};

static const struct snd_soc_dapm_widget max9860_dapm_widgets[] = {
SND_SOC_DAPM_INPUT("MICL"),
SND_SOC_DAPM_INPUT("MICR"),

SND_SOC_DAPM_ADC("ADCL", NULL, MAX9860_PWRMAN, MAX9860_ADCLEN_SHIFT, 0),
SND_SOC_DAPM_ADC("ADCR", NULL, MAX9860_PWRMAN, MAX9860_ADCREN_SHIFT, 0),

SND_SOC_DAPM_AIF_OUT("AIFOUTL", "Capture", 0, SND_SOC_NOPM, 0, 0),
SND_SOC_DAPM_AIF_OUT("AIFOUTR", "Capture", 1, SND_SOC_NOPM, 0, 0),

SND_SOC_DAPM_MIXER("Mixer", SND_SOC_NOPM, 0, 0,
	max9860_mixer_controls,
	ARRAY_SIZE(max9860_mixer_controls)),

SND_SOC_DAPM_AIF_IN("AIFINL", "Playback", 0, SND_SOC_NOPM, 0, 0),
SND_SOC_DAPM_AIF_IN("AIFINR", "Playback", 1, SND_SOC_NOPM, 0, 0),

SND_SOC_DAPM_DAC("DAC", NULL, MAX9860_PWRMAN, MAX9860_DACEN_SHIFT, 0),

SND_SOC_DAPM_OUTPUT("OUT"),
};

static const struct snd_soc_dapm_route max9860_dapm_routes[] = {
	{ "ADCL", NULL, "MICL" },
	{ "ADCR", NULL, "MICR" },
	{ "AIFOUTL", NULL, "ADCL" },
	{ "AIFOUTR", NULL, "ADCR" },

	{ "OUT", NULL, "DAC" },

	{ "DAC", NULL, "Mixer" },
	{ "Mixer", "Sidetone Volume", "ADCL" },
	{ "Mixer", NULL, "AIFINL" },
	{ "Mixer", NULL, "AIFINR" },
};


But DAPM and some tools (e.g. alsamixer) do not properly recognize the
mute value at the wrong end on the scale for the sidetone. So, the
sidetone path is never off (in the dapm sense).

I can use amixer to set the special mute value, and it states
-99999.99dB, so I think the tlv declaration is correct, at least in
theory. But as I said alsamixer is thoroughly confused by the control
and behaves rather strange...

If I change the tlv declaration so that DAPM thinks the mute is in
the natural end of the scale, the paths are off in the dapm sense
when the sidetone is muted (but the sidetone is not in fact muted,
of course).

Is there anything I can do to make DAPM handle this insane register
field better?

Cheers,
Peter


More information about the Alsa-devel mailing list