Oh. I forget to write the subject, which I have left empty, since I was not sure wht would be the proper summary. Well, it could not be worst than this. I'll go and hide somewhere... Sorry. -- Péter On Tuesday 18 May 2010 15:39:20 Ujfalusi Peter (Nokia-D/Tampere) wrote: > Hello, > > I apologize for the long mail, but I feel that I need to explain this in a > bit longish way... > > ASoC core recently gained support for limiting the volume control's range > (maximum), which is really useful in embedded systems. > The implementation for this is really simple: > The codec drivers are implementing the full range the HW can support. > Machine drivers can than override the maximum volume on a given control if > it is necessary. > This works well with most of the controls: > Volume controls without dB scale. > Volume controls with DECLARE_TLV_DB_SCALE() > > Problems started to emerge, when the volume is limited on control, which > has SNDRV_CTL_TLVT_DB_RANGE (from the sound/soc/codecs/tpa6130a2.c): > > static const unsigned int tpa6140_tlv[] = { > TLV_DB_RANGE_HEAD(3), > 0, 8, TLV_DB_SCALE_ITEM(-5900, 400, 0), > 9, 16, TLV_DB_SCALE_ITEM(-2500, 200, 0), > 17, 31, TLV_DB_SCALE_ITEM(-1000, 100, 0), > }; > > static const struct snd_kcontrol_new tpa6140a2_controls[] = { > SOC_SINGLE_EXT_TLV("TPA6140A2 Headphone Playback Volume", > TPA6130A2_REG_VOL_MUTE, 1, 0x1f, 0, > tpa6130a2_get_volsw, tpa6130a2_put_volsw, > tpa6140_tlv), > }; > > The original HW supported range is 0 .. 31 (-59 .. +4 dB). > When the machine driver sets the limit to 21 (-6 dB), than the volume range > is reported correctly as 0 .. 21, but > snd_mixer_selem_get_playback_dB_range() reports range of -59 .. +4 dB. > This is not correct, it should report: -59 .. -6 dB. > If the control has single DECLARE_TLV_DB_SCALE() after the limiting both > volume and dB range is reported correctly. > > The explanation for this is in the alsa-lib: > src/control/tlv.c: > > /** > * \brief Get the dB min/max values > * \param tlv the TLV source returned by #snd_tlv_parse_dB_info() > * \param rangemin the minimum value of the raw volume > * \param rangemax the maximum value of the raw volume > * \param min the pointer to store the minimum dB value (in 0.01dB unit) > * \param max the pointer to store the maximum dB value (in 0.01dB unit) > * \return 0 if successful, or a negative error code > */ > int snd_tlv_get_dB_range(unsigned int *tlv, long rangemin, long rangemax, > long *min, long *max) > { > int err; > > switch (tlv[0]) { > case SND_CTL_TLVT_DB_RANGE: { > unsigned int pos, len; > len = int_index(tlv[1]); > if (len > MAX_TLV_RANGE_SIZE) > return -EINVAL; > pos = 2; > while (pos + 4 <= len) { > long rmin, rmax; > rangemin = (int)tlv[pos]; > rangemax = (int)tlv[pos + 1]; > err = snd_tlv_get_dB_range(tlv + pos + 2, > rangemin, rangemax, > &rmin, &rmax); > if (err < 0) > return err; > if (pos > 2) { > if (rmin < *min) > *min = rmin; > if (rmax > *max) > *max = rmax; > } else { > *min = rmin; > *max = rmax; > } > pos += int_index(tlv[pos + 3]) + 4; > } > return 0; > } > case SND_CTL_TLVT_DB_SCALE: { > int step; > *min = (int)tlv[2]; > step = (tlv[3] & 0xffff); > *max = *min + (long)(step * (rangemax - rangemin)); > return 0; > } > case SND_CTL_TLVT_DB_MINMAX: > case SND_CTL_TLVT_DB_MINMAX_MUTE: > case SND_CTL_TLVT_DB_LINEAR: > *min = (int)tlv[2]; > *max = (int)tlv[3]; > return 0; > } > return -EINVAL; > } > > In case of DECLARE_TLV_DB_SCALE(), the SND_CTL_TLVT_DB_SCALE case is taken, > and the control's maximum, and minimum range are used for the dB scale > limit calculation. > But, when SNDRV_CTL_TLVT_DB_RANGE is used (tpa6130a2 driver), than that > case will dismisses the control's maximum and minimum range, and goes > through the whole TLV struct, and reports the HW supported range. > If it would stop at the driver reported maximum, than the dB range reported > would be correct. > So a 'simple' patch to alsa-lib would solve this. But what happens, if we > want to limit control, which has DB_MINMAX, DB_MINMAX_MUTE, or DB_LINEAR? > There is no way to actually limit those in a way, that the dB scale > reported would be correct. We just stretch the steps bigger, like what > happens with the SNDRV_CTL_TLVT_DB_RANGE in the tpa6130a2 driver. > > When looking for users of DB_LINEAR I have found 8 drivers, DB_MINMAX is > used by usbmixer only, the DB_MINMAX_MUTE has no users at all. > > Since both DB_LINEAR and DB_MINMAX can be presented as DB_SCALE, and the > effort to convert the drivers should not be that big. > > In this way, we will only have drivers using DB_SCALE in kernel, we can > mark the other DB_ types as deprecated (but keeping the support for out of > tree drivers), and the alsa-lib's tlv code can be adjusted to support > properly the volume limiting. If there is interest, than the ALSA core > could also gain support for platform/configuration dependent volume > limiting. > > If this is too big change to ALSA (which I think it is not, since for the > user it makes no difference, and the volume range, dB scale not going to > be changed), than probably cleaning up the sound/soc/ to use _only_ > DB_SCALE type for volume controls might be the solution, since the volume > limiting feature is only in ASoC AFAIK. > > Either way, the alsa-lib's src/control/tlv.c:snd_tlv_get_dB_range function > in case of SND_CTL_TLVT_DB_RANGE needs some fix to handle the situation, > when the volume range is _not_ at the HW supported range. > > To summarize, I'd like to do (or ask help to do) one of the following > [1] Replace the use of DB_LINEAR, DB_MINMAX with DB_SCALE in all drivers > under sound/ > Document, that the now unused DB_ types are deprecated > Fix alsa-lib to support the volume limiting in regards of dB scale > [2] Replace the use of DB_LINEAR with DB_SCALE in all drivers under > sound/soc/ > Fix alsa-lib to support the volume limiting in regards of dB scale > > > What do you think? > > -- > Péter > _______________________________________________ > Alsa-devel mailing list > Alsa-devel@xxxxxxxxxxxxxxxx > http://mailman.alsa-project.org/mailman/listinfo/alsa-devel _______________________________________________ Alsa-devel mailing list Alsa-devel@xxxxxxxxxxxxxxxx http://mailman.alsa-project.org/mailman/listinfo/alsa-devel