diff options
Diffstat (limited to 'sound/core/pcm_lib.c')
-rw-r--r-- | sound/core/pcm_lib.c | 85 |
1 files changed, 85 insertions, 0 deletions
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c index ec9e7866177f..446c00bd908b 100644 --- a/sound/core/pcm_lib.c +++ b/sound/core/pcm_lib.c | |||
@@ -1015,6 +1015,60 @@ int snd_interval_list(struct snd_interval *i, unsigned int count, | |||
1015 | 1015 | ||
1016 | EXPORT_SYMBOL(snd_interval_list); | 1016 | EXPORT_SYMBOL(snd_interval_list); |
1017 | 1017 | ||
1018 | /** | ||
1019 | * snd_interval_ranges - refine the interval value from the list of ranges | ||
1020 | * @i: the interval value to refine | ||
1021 | * @count: the number of elements in the list of ranges | ||
1022 | * @ranges: the ranges list | ||
1023 | * @mask: the bit-mask to evaluate | ||
1024 | * | ||
1025 | * Refines the interval value from the list of ranges. | ||
1026 | * When mask is non-zero, only the elements corresponding to bit 1 are | ||
1027 | * evaluated. | ||
1028 | * | ||
1029 | * Return: Positive if the value is changed, zero if it's not changed, or a | ||
1030 | * negative error code. | ||
1031 | */ | ||
1032 | int snd_interval_ranges(struct snd_interval *i, unsigned int count, | ||
1033 | const struct snd_interval *ranges, unsigned int mask) | ||
1034 | { | ||
1035 | unsigned int k; | ||
1036 | struct snd_interval range_union; | ||
1037 | struct snd_interval range; | ||
1038 | |||
1039 | if (!count) { | ||
1040 | snd_interval_none(i); | ||
1041 | return -EINVAL; | ||
1042 | } | ||
1043 | snd_interval_any(&range_union); | ||
1044 | range_union.min = UINT_MAX; | ||
1045 | range_union.max = 0; | ||
1046 | for (k = 0; k < count; k++) { | ||
1047 | if (mask && !(mask & (1 << k))) | ||
1048 | continue; | ||
1049 | snd_interval_copy(&range, &ranges[k]); | ||
1050 | if (snd_interval_refine(&range, i) < 0) | ||
1051 | continue; | ||
1052 | if (snd_interval_empty(&range)) | ||
1053 | continue; | ||
1054 | |||
1055 | if (range.min < range_union.min) { | ||
1056 | range_union.min = range.min; | ||
1057 | range_union.openmin = 1; | ||
1058 | } | ||
1059 | if (range.min == range_union.min && !range.openmin) | ||
1060 | range_union.openmin = 0; | ||
1061 | if (range.max > range_union.max) { | ||
1062 | range_union.max = range.max; | ||
1063 | range_union.openmax = 1; | ||
1064 | } | ||
1065 | if (range.max == range_union.max && !range.openmax) | ||
1066 | range_union.openmax = 0; | ||
1067 | } | ||
1068 | return snd_interval_refine(i, &range_union); | ||
1069 | } | ||
1070 | EXPORT_SYMBOL(snd_interval_ranges); | ||
1071 | |||
1018 | static int snd_interval_step(struct snd_interval *i, unsigned int step) | 1072 | static int snd_interval_step(struct snd_interval *i, unsigned int step) |
1019 | { | 1073 | { |
1020 | unsigned int n; | 1074 | unsigned int n; |
@@ -1221,6 +1275,37 @@ int snd_pcm_hw_constraint_list(struct snd_pcm_runtime *runtime, | |||
1221 | 1275 | ||
1222 | EXPORT_SYMBOL(snd_pcm_hw_constraint_list); | 1276 | EXPORT_SYMBOL(snd_pcm_hw_constraint_list); |
1223 | 1277 | ||
1278 | static int snd_pcm_hw_rule_ranges(struct snd_pcm_hw_params *params, | ||
1279 | struct snd_pcm_hw_rule *rule) | ||
1280 | { | ||
1281 | struct snd_pcm_hw_constraint_ranges *r = rule->private; | ||
1282 | return snd_interval_ranges(hw_param_interval(params, rule->var), | ||
1283 | r->count, r->ranges, r->mask); | ||
1284 | } | ||
1285 | |||
1286 | |||
1287 | /** | ||
1288 | * snd_pcm_hw_constraint_ranges - apply list of range constraints to a parameter | ||
1289 | * @runtime: PCM runtime instance | ||
1290 | * @cond: condition bits | ||
1291 | * @var: hw_params variable to apply the list of range constraints | ||
1292 | * @r: ranges | ||
1293 | * | ||
1294 | * Apply the list of range constraints to an interval parameter. | ||
1295 | * | ||
1296 | * Return: Zero if successful, or a negative error code on failure. | ||
1297 | */ | ||
1298 | int snd_pcm_hw_constraint_ranges(struct snd_pcm_runtime *runtime, | ||
1299 | unsigned int cond, | ||
1300 | snd_pcm_hw_param_t var, | ||
1301 | const struct snd_pcm_hw_constraint_ranges *r) | ||
1302 | { | ||
1303 | return snd_pcm_hw_rule_add(runtime, cond, var, | ||
1304 | snd_pcm_hw_rule_ranges, (void *)r, | ||
1305 | var, -1); | ||
1306 | } | ||
1307 | EXPORT_SYMBOL(snd_pcm_hw_constraint_ranges); | ||
1308 | |||
1224 | static int snd_pcm_hw_rule_ratnums(struct snd_pcm_hw_params *params, | 1309 | static int snd_pcm_hw_rule_ratnums(struct snd_pcm_hw_params *params, |
1225 | struct snd_pcm_hw_rule *rule) | 1310 | struct snd_pcm_hw_rule *rule) |
1226 | { | 1311 | { |