m = hw_param_mask(params, k);
if (snd_mask_empty(m))
return -EINVAL;
+
+ /* This parameter is not requested to change by a caller. */
if (!(params->rmask & (1 << k)))
continue;
trace_hw_mask_param(substream, k, 0, &old_mask, m);
+ /* Set corresponding flag so that the caller gets it. */
if (changed)
params->cmask |= 1 << k;
if (changed < 0)
i = hw_param_interval(params, k);
if (snd_interval_empty(i))
return -EINVAL;
+
+ /* This parameter is not requested to change by a caller. */
if (!(params->rmask & (1 << k)))
continue;
trace_hw_interval_param(substream, k, 0, &old_interval, i);
+ /* Set corresponding flag so that the caller gets it. */
if (changed)
params->cmask |= 1 << k;
if (changed < 0)
unsigned int k;
unsigned int rstamps[constrs->rules_num];
unsigned int vstamps[SNDRV_PCM_HW_PARAM_LAST_INTERVAL + 1];
- unsigned int stamp = 2;
+ unsigned int stamp;
struct snd_pcm_hw_rule *r;
unsigned int d;
struct snd_mask old_mask;
bool again;
int changed;
+ /*
+ * Each application of rule has own sequence number.
+ *
+ * Each member of 'rstamps' array represents the sequence number of
+ * recent application of corresponding rule.
+ */
for (k = 0; k < constrs->rules_num; k++)
rstamps[k] = 0;
+
+ /*
+ * Each member of 'vstamps' array represents the sequence number of
+ * recent application of rule in which corresponding parameters were
+ * changed.
+ *
+ * In initial state, elements corresponding to parameters requested by
+ * a caller is 1. For unrequested parameters, corresponding members
+ * have 0 so that the parameters are never changed anymore.
+ */
for (k = 0; k <= SNDRV_PCM_HW_PARAM_LAST_INTERVAL; k++)
vstamps[k] = (params->rmask & (1 << k)) ? 1 : 0;
+
+ /* Due to the above design, actual sequence number starts at 2. */
+ stamp = 2;
retry:
+ /* Apply all rules in order. */
again = false;
for (k = 0; k < constrs->rules_num; k++) {
r = &constrs->rules[k];
+
+ /*
+ * Check condition bits of this rule. When the rule has
+ * some condition bits, parameter without the bits is
+ * never processed. SNDRV_PCM_HW_PARAMS_NO_PERIOD_WAKEUP
+ * is an example of the condition bits.
+ */
if (r->cond && !(r->cond & params->flags))
continue;
+
+ /*
+ * The 'deps' array includes maximum three dependencies
+ * to SNDRV_PCM_HW_PARAM_XXXs for this rule. The fourth
+ * member of this array is a sentinel and should be
+ * negative value.
+ *
+ * This rule should be processed in this time when dependent
+ * parameters were changed at former applications of the other
+ * rules.
+ */
for (d = 0; r->deps[d] >= 0; d++) {
if (vstamps[r->deps[d]] > rstamps[k])
break;
}
rstamps[k] = stamp;
+
+ /*
+ * When the parameters is changed, notify it to the caller
+ * by corresponding returned bit, then preparing for next
+ * iteration.
+ */
if (changed && r->var >= 0) {
params->cmask |= (1 << r->var);
vstamps[r->var] = stamp;
stamp++;
}
+ /* Iterate to evaluate all rules till no parameters are changed. */
if (again)
goto retry;