Hi! Sorry to send a ping like this, with the patch still in patchwork and all. But it's been a month since 1/4 and 2/4 were committed and I expected at least some comment on the approach for patches 3 and 4...
Cheers, Peter On 2016-05-14 23:09, Peter Rosin wrote: > The max9860 codec has a mixer control field that has its mute/disable at > the wrong end of the scale. I.e. you turn the volume up and up, and then > as the final step the volume is off. This does not sit well with DAPM, > which assumes the mute/off is at the minimum value. > > Add support for such backwards controls with code that searches TLV ranges > for the mute value and use that as trigger for DAPM off. > > Signed-off-by: Peter Rosin <[email protected]> > --- > sound/soc/soc-dapm.c | 38 +++++++++++++++++++++++++++++++++++--- > 1 file changed, 35 insertions(+), 3 deletions(-) > > diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c > index c4464858bf01..8a1131781339 100644 > --- a/sound/soc/soc-dapm.c > +++ b/sound/soc/soc-dapm.c > @@ -42,6 +42,7 @@ > #include <sound/pcm_params.h> > #include <sound/soc.h> > #include <sound/initval.h> > +#include <sound/tlv.h> > > #include <trace/events/asoc.h> > > @@ -722,16 +723,46 @@ static int dapm_connect_mux(struct snd_soc_dapm_context > *dapm, > return -ENODEV; > } > > +static int dapm_find_tlv_mute(const unsigned int *tlv) > +{ > + int cnt; > + const unsigned int *range; > + > + if (!tlv || tlv[0] != SNDRV_CTL_TLVT_DB_RANGE) > + return 0; > + > + cnt = tlv[1] / sizeof(unsigned int); > + > + /* > + * Each group of six values should be > + * { start end type len min step/mute } > + */ > + for (range = &tlv[2]; cnt >= 6; cnt -= 6, range += 6) { > + if (range[2] != SNDRV_CTL_TLVT_DB_SCALE) > + return 0; /* wrong type, terminate */ > + if (range[3] != 2 * sizeof(unsigned int)) > + return 0; /* wrong len, terminate */ > + if (!(range[5] & TLV_DB_SCALE_MUTE)) > + continue; /* no mute in this range */ > + return range[0]; /* start of this range is the mute value */ > + } > + > + return 0; > +} > + > /* set up initial codec paths */ > static void dapm_set_mixer_path_status(struct snd_soc_dapm_path *p, int i) > { > + const struct snd_kcontrol_new *kcontrol_new > + = &p->sink->kcontrol_news[i]; > struct soc_mixer_control *mc = (struct soc_mixer_control *) > - p->sink->kcontrol_news[i].private_value; > + kcontrol_new->private_value; > unsigned int reg = mc->reg; > unsigned int shift = mc->shift; > unsigned int max = mc->max; > unsigned int mask = (1 << fls(max)) - 1; > unsigned int invert = mc->invert; > + int mute_value = dapm_find_tlv_mute(kcontrol_new->tlv.p); > unsigned int val; > > if (reg != SND_SOC_NOPM) { > @@ -739,7 +770,7 @@ static void dapm_set_mixer_path_status(struct > snd_soc_dapm_path *p, int i) > val = (val >> shift) & mask; > if (invert) > val = max - val; > - p->connect = !!val; > + p->connect = val != mute_value; > } else { > p->connect = 0; > } > @@ -3045,6 +3076,7 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol > *kcontrol, > int max = mc->max; > unsigned int mask = (1 << fls(max)) - 1; > unsigned int invert = mc->invert; > + int mute_value = dapm_find_tlv_mute(kcontrol->tlv.p); > unsigned int val; > int connect, change, reg_change = 0; > struct snd_soc_dapm_update update; > @@ -3056,7 +3088,7 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol > *kcontrol, > kcontrol->id.name); > > val = (ucontrol->value.integer.value[0] & mask); > - connect = !!val; > + connect = val != mute_value; > > if (invert) > val = max - val; >

