Benoît Thébaudeau wrote:
Clemens Ladisch wrote:
I'll see if I can cobble together some TLV checking code ...
Great.
In all the hardware examples that I've found, the worst case for holes is always, like for the BD37534: mute hole valid dB range hole
So it's perhaps not worth developing something very complicated in the kernel to handle all possible cases of TLV range holes. I think that most real-life cases will be handled if we consider a min-max raw HW range combined with a mute value automatically set at the extreme value of the bit-field, with an optional inversion. Something like:
#define SOC_SINGLE_MUTABLE_TLV(xname, reg, shift, min, max, invert, tlv_array)
In the BD driver example that I gave: static const unsigned int bd3753x_vol_fader_gain_att_tlv[] = { TLV_DB_RANGE_HEAD(2), 0, 0, TLV_DB_SCALE_ITEM(TLV_DB_GAIN_MUTE, 0, 1), 48, 142, TLV_DB_SCALE_ITEM(-7900, 100, 0), }; SOC_SINGLE_TLV("Main Volume", BD3753X_VOL_GAIN, 0, 255, 1, bd3753x_vol_fader_gain_att_tlv),
would become: static const DECLARE_TLV_DB_SCALE(bd3753x_vol_fader_gain_att_tlv, -8000, 100, 1); SOC_SINGLE_MUTABLE_TLV("Main Volume", BD3753X_VOL_GAIN, 0, 0x71, 0xcf, 1, bd3753x_vol_fader_gain_att_tlv),
The range exposed by .info would be 0 to 0x5f, 0 being the mute HW value 0xff, and 0x01 to 0x5f matching the HW 0xcf to 0x71.
The SOC_*_MUTABLE_TLV set of macros would use dedicated .info/.get/.put callbacks. They could theoretically be merged into the snd_soc_*_volsw callbacks if a new field were added to struct soc_mixer_control to indicate this use case. Or the invert field could be replaced with a set of option flags.
Regards, Benoît