Inner this library, layouts of all structures are public. At a compilation
time, each size of the structures can be calculated. It means that we can
use automatic variable instead of calling alloca(3) to program this
library because in both ways storages are kept on stack frame of process
VMA. Besides, the usage of automatic variables requires less instructions
than calls of alloca(3). Furthermore, alloca(3) is not described in any
C language standards.
This commit replaces calls of alloca(3) just for structures with automatic
variables, for control features.
Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Currently, for a TLV consisting of TLV_DB_SCALE_ITEMs, if e.g. alsamixer
calls snd_mixer_selem_set_playback_dB() with a value that is in-between
two TLV_DB_SCALE_ITEMs, and xdir is negative, the selected raw hardware
value is the minimum in the first range above that value, rather than the
maximum in the last range below that value.
The user-visible symptom is that in alsamixer, pressing the down key to
reduce the value sticks at certain points, and cannot be incrementally
reduced any further, although directly selecting a much lower value (e.g.
by pressing 0..9) works as expected. This is triggered e.g. by
sound/soc/codec/max98090.c's max98090_hp_tlv[].
Fix this by checking whether xdir is positive or not, rather than
checking whether it has a non-zero value. The code to select the previous
range's max value is already present. This matches how xdir is used in
other parts of the code.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
snd_tlv_convert_from_dB() relies on rangemin/max blindly.
Since this function is exported, it is better for robustness and
consistency to parse the range properly, which this patch does.
Signed-off-by: Benoît Thébaudeau <benoit.thebaudeau@advansee.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
For TLV information that indicates that the minimum value is actually
muted, the returned range used the wrong minimum dB value, and
converting dB values to raw control values did not round up correctly
near the minimum.
Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Cosmetic fix.
There was a tab instead of new line after snd_ctl_get_dB_range
function.
Signed-off-by: Peter Ujfalusi <peter.ujfalusi@nokia.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
When converting from dB to raw value, and DB_RANGE is
used with non overlapping map, dB value in between the
sub ranges will be not found.
For example, if the control has the following:
0: -10dB
1: -5dB
2: 0dB
3: 2dB
4: 4dB
static const unsigned int nonoverlapping_tlv[] = {
TLV_DB_RANGE_HEAD(2),
0, 2, TLV_DB_SCALE_ITEM(-1000, 500, 0),
3, 4, TLV_DB_SCALE_ITEM(200, 200, 0),
};
Range 1: -10 .. 0dB
Range 2: 2 .. 4dB
If user asks for 1dB the snd_tlv_convert_from_dB will not find
the raw value, since the 1dB is not part of either range.
To fix this, we will store the previous non maching range's
maximum raw value. If the dB value is not found in the next range,
we will check, if the requested dB value is in between the current
and the previous range, and if it is than pick the apropriate raw
value based on the xdir (up or down rounding).
Signed-off-by: Peter Ujfalusi <peter.ujfalusi@nokia.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
When converting from dB value to raw value, the control's
full range was not checked in case of SND_CTL_TLVT_DB_RANGE.
Check out of range dB values, and return apropriate raw
value for the caller.
Signed-off-by: Peter Ujfalusi <peter.ujfalusi@nokia.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
The DB_RANGE need to be used on some HW, since the gain on
volume control is not continuous, and has to be divided into
several sub DB_SCALE ranges.
ASoC has a feature to override the HW default volume range,
and in this case when the volume range is less than the
HW maximum we do not need to go through the whole DB_RANGE,
but we need to stop where the kcontrol's maximum tell us.
Signed-off-by: Peter Ujfalusi <peter.ujfalusi@nokia.com>
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
Export helper functions to convert dB level and range.
snd_tlv_*dB*() are to convert dB level or range directly from TLV data.
snd_ctl_*dB*() are to get dB level or range from a control element.