[alsa-devel] [PATCH - alsa-lib 0/3] Fixes for snd_tlv_convert_from_dB
Hello,
One cosmetic fix, and two real fixes for alsa-lib's tlv handling.
There were two separate issue with the snd_tlv_convert_from_dB function: 1. When user asked for out of range dB value, and the control had SND_CTL_TLVT_DB_RANGE, the control's full range was not checked against the requested value, which resulted failure. 2. When there are 'holes' in the SND_CTL_TLVT_DB_RANGE array, snd_tlv_convert_from_dB will fail to find the apropriate raw value.
For issue #2, I have sent patches for the drivers I maintain, but Mark Brown suggested to fix the issue in alsa-lib instead of converting the driver's non-overlapping to overlapping mapping: http://mailman.alsa-project.org/pipermail/alsa-devel/2010-July/029483.html
So the following series for alsa-lib, will fix the SND_CTL_TLVT_DB_RANGE handling.
--- Peter Ujfalusi (3): tlv: Check out of range dB with SND_CTL_TLVT_DB_RANGE tlv: Handle 'holes' in SND_CTL_TLVT_DB_RANGE array tlv: Remove tailing tab after snd_ctl_get_dB_range function
src/control/tlv.c | 17 +++++++++++++++-- 1 files changed, 15 insertions(+), 2 deletions(-)
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 --- src/control/tlv.c | 9 ++++++++- 1 files changed, 8 insertions(+), 1 deletions(-)
diff --git a/src/control/tlv.c b/src/control/tlv.c index 0ff052e..d09766a 100644 --- a/src/control/tlv.c +++ b/src/control/tlv.c @@ -285,13 +285,20 @@ int snd_tlv_convert_from_dB(unsigned int *tlv, long rangemin, long rangemax, { switch (tlv[0]) { case SND_CTL_TLVT_DB_RANGE: { + long dbmin, dbmax; unsigned int pos, len; len = int_index(tlv[1]); if (len > MAX_TLV_RANGE_SIZE) return -EINVAL; + if (snd_tlv_get_dB_range(tlv, rangemin, rangemax, + &dbmin, &dbmax)) + return -EINVAL; + if (db_gain <= dbmin || db_gain >= dbmax) { + *value = db_gain <= dbmin ? rangemin : rangemax; + return 0; + } pos = 2; while (pos + 4 <= len) { - long dbmin, dbmax; rangemin = (int)tlv[pos]; rangemax = (int)tlv[pos + 1]; if (!snd_tlv_get_dB_range(tlv + pos + 2,
At Mon, 19 Jul 2010 10:14:04 +0300, Peter Ujfalusi wrote:
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
src/control/tlv.c | 9 ++++++++- 1 files changed, 8 insertions(+), 1 deletions(-)
diff --git a/src/control/tlv.c b/src/control/tlv.c index 0ff052e..d09766a 100644 --- a/src/control/tlv.c +++ b/src/control/tlv.c @@ -285,13 +285,20 @@ int snd_tlv_convert_from_dB(unsigned int *tlv, long rangemin, long rangemax, { 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;long dbmin, dbmax;
if (snd_tlv_get_dB_range(tlv, rangemin, rangemax,
&dbmin, &dbmax))
return -EINVAL;
if (db_gain <= dbmin || db_gain >= dbmax) {
*value = db_gain <= dbmin ? rangemin : rangemax;
return 0;
}
The check looks good, but IMO, just plain two if's are more intuitive:
if (db_gain <= dbmin) { *value = rangemin; return 0; } else if (db_gain >= dbmax) { *value = rangemax; return 0; }
thanks,
Takashi
On Monday 19 July 2010 18:48:06 ext Takashi Iwai wrote:
if (snd_tlv_get_dB_range(tlv, rangemin, rangemax,
&dbmin, &dbmax))
return -EINVAL;
if (db_gain <= dbmin || db_gain >= dbmax) {
*value = db_gain <= dbmin ? rangemin : rangemax;
return 0;
}
The check looks good, but IMO, just plain two if's are more intuitive:
if (db_gain <= dbmin) { *value = rangemin; return 0; } else if (db_gain >= dbmax) { *value = rangemax; return 0; }
I will change the check, and resubmit the patch (or the series)
thanks,
Takashi
Thank you, Péter
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 --- src/control/tlv.c | 8 +++++++- 1 files changed, 7 insertions(+), 1 deletions(-)
diff --git a/src/control/tlv.c b/src/control/tlv.c index d09766a..1767118 100644 --- a/src/control/tlv.c +++ b/src/control/tlv.c @@ -285,7 +285,7 @@ int snd_tlv_convert_from_dB(unsigned int *tlv, long rangemin, long rangemax, { switch (tlv[0]) { case SND_CTL_TLVT_DB_RANGE: { - long dbmin, dbmax; + long dbmin, dbmax, prev_rangemax; unsigned int pos, len; len = int_index(tlv[1]); if (len > MAX_TLV_RANGE_SIZE) @@ -298,6 +298,7 @@ int snd_tlv_convert_from_dB(unsigned int *tlv, long rangemin, long rangemax, return 0; } pos = 2; + prev_rangemax = 0; while (pos + 4 <= len) { rangemin = (int)tlv[pos]; rangemax = (int)tlv[pos + 1]; @@ -308,6 +309,11 @@ int snd_tlv_convert_from_dB(unsigned int *tlv, long rangemin, long rangemax, return snd_tlv_convert_from_dB(tlv + pos + 2, rangemin, rangemax, db_gain, value, xdir); + else if (db_gain < dbmin) { + *value = xdir ? rangemin : prev_rangemax; + return 0; + } + prev_rangemax = rangemax; pos += int_index(tlv[pos + 3]) + 4; } return -EINVAL;
At Mon, 19 Jul 2010 10:14:05 +0300, Peter Ujfalusi wrote:
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.
In the case above, can't you set like
TLV_DB_RANGE_HEAD(2), 0, 2, TLV_DB_SCALE_ITEM(-1000, 500, 0), 2, 4, TLV_DB_SCALE_ITEM(0, 200, 0)
??
Takashi
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), }; 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
src/control/tlv.c | 8 +++++++- 1 files changed, 7 insertions(+), 1 deletions(-)
diff --git a/src/control/tlv.c b/src/control/tlv.c index d09766a..1767118 100644 --- a/src/control/tlv.c +++ b/src/control/tlv.c @@ -285,7 +285,7 @@ int snd_tlv_convert_from_dB(unsigned int *tlv, long rangemin, long rangemax, { switch (tlv[0]) { case SND_CTL_TLVT_DB_RANGE: {
long dbmin, dbmax;
unsigned int pos, len; len = int_index(tlv[1]); if (len > MAX_TLV_RANGE_SIZE)long dbmin, dbmax, prev_rangemax;
@@ -298,6 +298,7 @@ int snd_tlv_convert_from_dB(unsigned int *tlv, long rangemin, long rangemax, return 0; } pos = 2;
while (pos + 4 <= len) { rangemin = (int)tlv[pos]; rangemax = (int)tlv[pos + 1];prev_rangemax = 0;
@@ -308,6 +309,11 @@ int snd_tlv_convert_from_dB(unsigned int *tlv, long rangemin, long rangemax, return snd_tlv_convert_from_dB(tlv + pos + 2, rangemin, rangemax, db_gain, value, xdir);
else if (db_gain < dbmin) {
*value = xdir ? rangemin : prev_rangemax;
return 0;
}
} return -EINVAL;prev_rangemax = rangemax; pos += int_index(tlv[pos + 3]) + 4;
-- 1.7.1.1
On Mon, Jul 19, 2010 at 05:51:27PM +0200, Takashi Iwai wrote:
Peter Ujfalusi wrote:
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.
In the case above, can't you set like
TLV_DB_RANGE_HEAD(2), 0, 2, TLV_DB_SCALE_ITEM(-1000, 500, 0), 2, 4, TLV_DB_SCALE_ITEM(0, 200, 0)
??
So, this came from a review comment from me in response to a patch doing just that. The issue I had was that this definition of overlapping ranges really feels like the kernel is bodging around limitations of the userspace library - the library is already trying to find the best match among the actual dB values available, it seems silly that it requires the kernel to provide patches between the ranges. It's moderately painful, especially if you have a bunch of values that aren't very well joined together in the hardware.
At Mon, 19 Jul 2010 17:01:10 +0100, Mark Brown wrote:
On Mon, Jul 19, 2010 at 05:51:27PM +0200, Takashi Iwai wrote:
Peter Ujfalusi wrote:
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.
In the case above, can't you set like
TLV_DB_RANGE_HEAD(2), 0, 2, TLV_DB_SCALE_ITEM(-1000, 500, 0), 2, 4, TLV_DB_SCALE_ITEM(0, 200, 0)
??
So, this came from a review comment from me in response to a patch doing just that. The issue I had was that this definition of overlapping ranges really feels like the kernel is bodging around limitations of the userspace library - the library is already trying to find the best match among the actual dB values available, it seems silly that it requires the kernel to provide patches between the ranges. It's moderately painful, especially if you have a bunch of values that aren't very well joined together in the hardware.
Well, one remaining question is how to handle if the hardware has really no value in a certain range (a hole). Fixing in alsa-lib is a sort of workaround, but it doesn't sound right, especially if the range info can be provided correctly in the source.
Note that TLV_DB_RANGE isn't necessarily incremental. The current algorithm is straight to pick up the first matching one. So, any overlap can be handled in the definition itself. (In the case of point-overlap, it shouldn't be a big problem, anyway.) The proposed fix for alsa-lib assumes that the incremental ranges, thus it's also not reliable in 100%.
If kernel changes would become too messy, then yes, we can reconsider fixing this only in alsa-lib, though.
thanks,
Takashi
On Mon, Jul 19, 2010 at 06:11:30PM +0200, Takashi Iwai wrote:
Well, one remaining question is how to handle if the hardware has really no value in a certain range (a hole). Fixing in alsa-lib is a sort of workaround, but it doesn't sound right, especially if the range info can be provided correctly in the source.
I guess it depends on what you're thinking of for an inexact match - if we're doing inexact matches within the range we're already saying that we're not giving 100% accuracy (and remember that some hardware has very coarse control). It seems wrong that we'd fail to match with a slighy inaccuracy when the requested value happens to be just outside the range but accept any old accuracy level from coarse grained steps.
If kernel changes would become too messy, then yes, we can reconsider fixing this only in alsa-lib, though.
Personally I'd rather the kernel just provided a mapping between control values and dB scales and then the application layer can decide what it thinks an appropriate match is. Decisions about how accurate a match is needed seem very policy like and therefore userspaceish and it seems wrong to be coding the data tables in the kernel in a way that works around the particular match algorithm in the application layer.
At Mon, 19 Jul 2010 17:24:17 +0100, Mark Brown wrote:
On Mon, Jul 19, 2010 at 06:11:30PM +0200, Takashi Iwai wrote:
Well, one remaining question is how to handle if the hardware has really no value in a certain range (a hole). Fixing in alsa-lib is a sort of workaround, but it doesn't sound right, especially if the range info can be provided correctly in the source.
I guess it depends on what you're thinking of for an inexact match - if we're doing inexact matches within the range we're already saying that we're not giving 100% accuracy (and remember that some hardware has very coarse control). It seems wrong that we'd fail to match with a slighy inaccuracy when the requested value happens to be just outside the range but accept any old accuracy level from coarse grained steps.
The guess work isn't always trivial. If the hardware switches the curve between log and linear over a hole, which should be taken for a value in the hole? Whne TLV is given for the hole, at least it's a good hint.
If kernel changes would become too messy, then yes, we can reconsider fixing this only in alsa-lib, though.
Personally I'd rather the kernel just provided a mapping between control values and dB scales and then the application layer can decide what it thinks an appropriate match is. Decisions about how accurate a match is needed seem very policy like and therefore userspaceish and it seems wrong to be coding the data tables in the kernel in a way that works around the particular match algorithm in the application layer.
User space can check the correctness always by checking the reverse conversion between dB <-> value again.
thanks,
Takashi
On Mon, Jul 19, 2010 at 06:44:31PM +0200, Takashi Iwai wrote:
The guess work isn't always trivial. If the hardware switches the curve between log and linear over a hole, which should be taken for a value in the hole? Whne TLV is given for the hole, at least it's a good hint.
I don't see what difference the curves make here? However the gap is expressed only the points at either end are selectable (and there's always the chance that this is part of a series of random individual points with no particular curve through them).
Personally I'd rather the kernel just provided a mapping between control values and dB scales and then the application layer can decide what it thinks an appropriate match is. Decisions about how accurate a match is needed seem very policy like and therefore userspaceish and it seems wrong to be coding the data tables in the kernel in a way that works around the particular match algorithm in the application layer.
User space can check the correctness always by checking the reverse conversion between dB <-> value again.
It still seems silly to have to paper over this for every single dB interval - if we need to link up the ranges it seems like we ought to be fixing this in one place.
At Mon, 19 Jul 2010 18:09:47 +0100, Mark Brown wrote:
On Mon, Jul 19, 2010 at 06:44:31PM +0200, Takashi Iwai wrote:
The guess work isn't always trivial. If the hardware switches the curve between log and linear over a hole, which should be taken for a value in the hole? Whne TLV is given for the hole, at least it's a good hint.
I don't see what difference the curves make here? However the gap is expressed only the points at either end are selectable (and there's always the chance that this is part of a series of random individual points with no particular curve through them).
Right, disregard my comment.
Personally I'd rather the kernel just provided a mapping between control values and dB scales and then the application layer can decide what it thinks an appropriate match is. Decisions about how accurate a match is needed seem very policy like and therefore userspaceish and it seems wrong to be coding the data tables in the kernel in a way that works around the particular match algorithm in the application layer.
User space can check the correctness always by checking the reverse conversion between dB <-> value again.
It still seems silly to have to paper over this for every single dB interval - if we need to link up the ranges it seems like we ought to be fixing this in one place.
Well, what I don't feel right is that this breaks the simpleness of DB_RANGE handling. It's just damn simple, and works as long as the target point is covered by defined ranges. If something is wrong, it's the definition, not the parser. That's why I wondered first whether it can't be fixed in the driver side. I want the parser stuff as simple as possible.
So, practically seen, how many driver are buggy in this regard? And for how many of them should a new TLV entry added? The only worst case is discontinued lines you mentioned. Is there a real device that behaves so (and implemented in that way)?
If fixing in alsa-lib is a better compromise, I'd take it. But I'd like to hear numbers first.
thanks,
Takashi
Takashi Iwai wrote:
Mark Brown wrote:
It still seems silly to have to paper over this for every single dB interval - if we need to link up the ranges it seems like we ought to be fixing this in one place.
Well, what I don't feel right is that this breaks the simpleness of DB_RANGE handling. It's just damn simple, and works as long as the target point is covered by defined ranges. If something is wrong, it's the definition, not the parser. That's why I wondered first whether it can't be fixed in the driver side.
As a driver writer, I would intuitively assume that the ranges must not be overlapping. If we require all drivers to get this right, there will likely be new ones that don't.
The only worst case is discontinued lines you mentioned. Is there a real device that behaves so (and implemented in that way)?
AK4524's and friends' "pseudo-log" controls use piecewise linear ranges where the boundaries between the ranges would have to be described with a separate TLV entry if overlapping TLV ranges are required (see page 28 of 4524.pdf). Currently, ak4xxx-adda.c uses a volume lookup table.
Regards, Clemens
On Tue, Jul 20, 2010 at 08:25:00AM +0200, Clemens Ladisch wrote:
Takashi Iwai wrote:
Well, what I don't feel right is that this breaks the simpleness of DB_RANGE handling. It's just damn simple, and works as long as the target point is covered by defined ranges. If something is wrong, it's the definition, not the parser. That's why I wondered first whether it can't be fixed in the driver side.
As a driver writer, I would intuitively assume that the ranges must not be overlapping. If we require all drivers to get this right, there will likely be new ones that don't.
This is exactly what happened with all the ASoC drivers - it never even occurred to me that it might be sensible to overlap the ranges. It's not at all obvious, like I've said the drivers are basically providing a data table.
Hi,
On Monday 19 July 2010 21:30:48 ext Takashi Iwai wrote:
It still seems silly to have to paper over this for every single dB interval - if we need to link up the ranges it seems like we ought to be fixing this in one place.
Well, what I don't feel right is that this breaks the simpleness of DB_RANGE handling. It's just damn simple, and works as long as the target point is covered by defined ranges. If something is wrong, it's the definition, not the parser. That's why I wondered first whether it can't be fixed in the driver side. I want the parser stuff as simple as possible.
I think this patch still keeps the parser simple. It does not break the existing functionality (overlapped mappings still works), but it can in addition handle the non-overlapped mapping of TLV ranges.
So, practically seen, how many driver are buggy in this regard? And for how many of them should a new TLV entry added? The only worst case is discontinued lines you mentioned. Is there a real device that behaves so (and implemented in that way)?
If fixing in alsa-lib is a better compromise, I'd take it. But I'd like to hear numbers first.
The following drivers have some sort of TLV_DB_RANGE_HEAD: with overlapping ranges: pci/as1838.c soc/codecs/wm8753.c
with non-overlapping ranges: soc/codecs/tpa6130a2.c /* patch sent to convert to overlapping */ soc/codecs/uda1380.c soc/codecs/wm_hubs.c soc/codecs/max9877.c soc/codecs/wm8350.c soc/codecs/wm8400.c /* only single SCALE_ITEM */ soc/codecs/wm8961.c soc/codecs/wm8990.c /* only single SCALE_ITEM */ soc/codecs/wm8993.c soc/codecs/wm9081.c soc/codecs/wm9090.c soc/codecs/wm9713.c soc/codecs/twl4030.c /* patch sent to convert to overlapping */
I don't really know how many of these driver would require new TLV entry, but the twl4030, and tpa6130a2 (for tpa6140a2 chip) does not needed new entry, just modification of the TLV items.
I agree with Mark in regards, that the decision making is strictly policy/userspace stuff, but I also think that the drivers should also provide as much, and as accurate information to user space to make this decision (if it is in form of overlapped mapping, than like that).
Having said that, I believe, that the patch for alsa-lib alone would provide correct enough handling of non-overlapping TLV ranges (without breaking the handling of overlapped mappings).
On Tue, Jul 20, 2010 at 09:53:22AM +0300, Peter Ujfalusi wrote:
I don't really know how many of these driver would require new TLV entry, but the twl4030, and tpa6130a2 (for tpa6140a2 chip) does not needed new entry, just modification of the TLV items.
If we're going to go down this road all of them will at least require modification.
I agree with Mark in regards, that the decision making is strictly policy/userspace stuff, but I also think that the drivers should also provide as much, and as accurate information to user space to make this decision (if it is in form of overlapped mapping, than like that).
I agree here, I just think that the overlapping ranges don't add anything to the information that's being provided.
At Tue, 20 Jul 2010 09:53:22 +0300, Peter Ujfalusi wrote:
Hi,
On Monday 19 July 2010 21:30:48 ext Takashi Iwai wrote:
It still seems silly to have to paper over this for every single dB interval - if we need to link up the ranges it seems like we ought to be fixing this in one place.
Well, what I don't feel right is that this breaks the simpleness of DB_RANGE handling. It's just damn simple, and works as long as the target point is covered by defined ranges. If something is wrong, it's the definition, not the parser. That's why I wondered first whether it can't be fixed in the driver side. I want the parser stuff as simple as possible.
I think this patch still keeps the parser simple. It does not break the existing functionality (overlapped mappings still works), but it can in addition handle the non-overlapped mapping of TLV ranges.
So, practically seen, how many driver are buggy in this regard? And for how many of them should a new TLV entry added? The only worst case is discontinued lines you mentioned. Is there a real device that behaves so (and implemented in that way)?
If fixing in alsa-lib is a better compromise, I'd take it. But I'd like to hear numbers first.
The following drivers have some sort of TLV_DB_RANGE_HEAD: with overlapping ranges: pci/as1838.c soc/codecs/wm8753.c
with non-overlapping ranges: soc/codecs/tpa6130a2.c /* patch sent to convert to overlapping */ soc/codecs/uda1380.c soc/codecs/wm_hubs.c soc/codecs/max9877.c soc/codecs/wm8350.c soc/codecs/wm8400.c /* only single SCALE_ITEM */ soc/codecs/wm8961.c soc/codecs/wm8990.c /* only single SCALE_ITEM */ soc/codecs/wm8993.c soc/codecs/wm9081.c soc/codecs/wm9090.c soc/codecs/wm9713.c soc/codecs/twl4030.c /* patch sent to convert to overlapping */
I don't really know how many of these driver would require new TLV entry, but the twl4030, and tpa6130a2 (for tpa6140a2 chip) does not needed new entry, just modification of the TLV items.
I agree with Mark in regards, that the decision making is strictly policy/userspace stuff, but I also think that the drivers should also provide as much, and as accurate information to user space to make this decision (if it is in form of overlapped mapping, than like that).
Having said that, I believe, that the patch for alsa-lib alone would provide correct enough handling of non-overlapping TLV ranges (without breaking the handling of overlapped mappings).
OK, this sounds convincing enough to me. I applied your new patches now.
Thanks!
Takashi
Hello,
On Monday 19 July 2010 18:51:27 ext Takashi Iwai wrote:
At Mon, 19 Jul 2010 10:14:05 +0300,
Peter Ujfalusi wrote:
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.
In the case above, can't you set like
TLV_DB_RANGE_HEAD(2), 0, 2, TLV_DB_SCALE_ITEM(-1000, 500, 0), 2, 4, TLV_DB_SCALE_ITEM(0, 200, 0)
??
This is exactly what I submitted for the drivers I maintain. Mark suggested that instead of doing this in driver, I should fix this in alsa- lib level. This patch tries to do exactly that. Personally I do prefer the way I patched the drivers, and you are also suggesting, but Mark has different opinion, so this has to be worked out.
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 --- src/control/tlv.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/src/control/tlv.c b/src/control/tlv.c index 1767118..ddc4517 100644 --- a/src/control/tlv.c +++ b/src/control/tlv.c @@ -439,7 +439,7 @@ int snd_ctl_get_dB_range(snd_ctl_t *ctl, const snd_ctl_elem_id_t *id, return snd_tlv_get_dB_range(info.tlv, info.minval, info.maxval, min, max); } - + /** * \brief Convert the volume value to dB on the given control element * \param ctl the control handler
participants (4)
-
Clemens Ladisch
-
Mark Brown
-
Peter Ujfalusi
-
Takashi Iwai