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 db05e04d0070..ffd656012ab8 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 | { |
