|
@@ -1015,6 +1015,60 @@ int snd_interval_list(struct snd_interval *i, unsigned int count,
|
|
|
|
|
|
EXPORT_SYMBOL(snd_interval_list);
|
|
|
|
|
|
+/**
|
|
|
+ * snd_interval_ranges - refine the interval value from the list of ranges
|
|
|
+ * @i: the interval value to refine
|
|
|
+ * @count: the number of elements in the list of ranges
|
|
|
+ * @ranges: the ranges list
|
|
|
+ * @mask: the bit-mask to evaluate
|
|
|
+ *
|
|
|
+ * Refines the interval value from the list of ranges.
|
|
|
+ * When mask is non-zero, only the elements corresponding to bit 1 are
|
|
|
+ * evaluated.
|
|
|
+ *
|
|
|
+ * Return: Positive if the value is changed, zero if it's not changed, or a
|
|
|
+ * negative error code.
|
|
|
+ */
|
|
|
+int snd_interval_ranges(struct snd_interval *i, unsigned int count,
|
|
|
+ const struct snd_interval *ranges, unsigned int mask)
|
|
|
+{
|
|
|
+ unsigned int k;
|
|
|
+ struct snd_interval range_union;
|
|
|
+ struct snd_interval range;
|
|
|
+
|
|
|
+ if (!count) {
|
|
|
+ snd_interval_none(i);
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
+ snd_interval_any(&range_union);
|
|
|
+ range_union.min = UINT_MAX;
|
|
|
+ range_union.max = 0;
|
|
|
+ for (k = 0; k < count; k++) {
|
|
|
+ if (mask && !(mask & (1 << k)))
|
|
|
+ continue;
|
|
|
+ snd_interval_copy(&range, &ranges[k]);
|
|
|
+ if (snd_interval_refine(&range, i) < 0)
|
|
|
+ continue;
|
|
|
+ if (snd_interval_empty(&range))
|
|
|
+ continue;
|
|
|
+
|
|
|
+ if (range.min < range_union.min) {
|
|
|
+ range_union.min = range.min;
|
|
|
+ range_union.openmin = 1;
|
|
|
+ }
|
|
|
+ if (range.min == range_union.min && !range.openmin)
|
|
|
+ range_union.openmin = 0;
|
|
|
+ if (range.max > range_union.max) {
|
|
|
+ range_union.max = range.max;
|
|
|
+ range_union.openmax = 1;
|
|
|
+ }
|
|
|
+ if (range.max == range_union.max && !range.openmax)
|
|
|
+ range_union.openmax = 0;
|
|
|
+ }
|
|
|
+ return snd_interval_refine(i, &range_union);
|
|
|
+}
|
|
|
+EXPORT_SYMBOL(snd_interval_ranges);
|
|
|
+
|
|
|
static int snd_interval_step(struct snd_interval *i, unsigned int step)
|
|
|
{
|
|
|
unsigned int n;
|
|
@@ -1221,6 +1275,37 @@ int snd_pcm_hw_constraint_list(struct snd_pcm_runtime *runtime,
|
|
|
|
|
|
EXPORT_SYMBOL(snd_pcm_hw_constraint_list);
|
|
|
|
|
|
+static int snd_pcm_hw_rule_ranges(struct snd_pcm_hw_params *params,
|
|
|
+ struct snd_pcm_hw_rule *rule)
|
|
|
+{
|
|
|
+ struct snd_pcm_hw_constraint_ranges *r = rule->private;
|
|
|
+ return snd_interval_ranges(hw_param_interval(params, rule->var),
|
|
|
+ r->count, r->ranges, r->mask);
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+/**
|
|
|
+ * snd_pcm_hw_constraint_ranges - apply list of range constraints to a parameter
|
|
|
+ * @runtime: PCM runtime instance
|
|
|
+ * @cond: condition bits
|
|
|
+ * @var: hw_params variable to apply the list of range constraints
|
|
|
+ * @r: ranges
|
|
|
+ *
|
|
|
+ * Apply the list of range constraints to an interval parameter.
|
|
|
+ *
|
|
|
+ * Return: Zero if successful, or a negative error code on failure.
|
|
|
+ */
|
|
|
+int snd_pcm_hw_constraint_ranges(struct snd_pcm_runtime *runtime,
|
|
|
+ unsigned int cond,
|
|
|
+ snd_pcm_hw_param_t var,
|
|
|
+ const struct snd_pcm_hw_constraint_ranges *r)
|
|
|
+{
|
|
|
+ return snd_pcm_hw_rule_add(runtime, cond, var,
|
|
|
+ snd_pcm_hw_rule_ranges, (void *)r,
|
|
|
+ var, -1);
|
|
|
+}
|
|
|
+EXPORT_SYMBOL(snd_pcm_hw_constraint_ranges);
|
|
|
+
|
|
|
static int snd_pcm_hw_rule_ratnums(struct snd_pcm_hw_params *params,
|
|
|
struct snd_pcm_hw_rule *rule)
|
|
|
{
|