Commit d81052f9 authored by Takashi Sakamoto's avatar Takashi Sakamoto Committed by Takashi Iwai

ALSA: pcm: add comment about application of rule to PCM parameters

Drivers add rules of parameters to runtime of PCM substream, when
applications open ALSA PCM character device. When applications call
ioctl(2) with SNDRV_PCM_IOCTL_HW_REFINE or SNDRV_PCM_IOCTL_HW_PARAMS, the
rules are applied to the parameters and return the result to user space.

The rule can have dependency between parameters. Additionally, it can have
condition flags about application of rules. Userspace applications can
indicate the flags to suppress change of parameters.

This commit attempts to describe the mechanism.
Signed-off-by: default avatarTakashi Sakamoto <o-takashi@sakamocchi.jp>
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent b81e5ddb
...@@ -267,6 +267,8 @@ static int constrain_mask_params(struct snd_pcm_substream *substream, ...@@ -267,6 +267,8 @@ static int constrain_mask_params(struct snd_pcm_substream *substream,
m = hw_param_mask(params, k); m = hw_param_mask(params, k);
if (snd_mask_empty(m)) if (snd_mask_empty(m))
return -EINVAL; return -EINVAL;
/* This parameter is not requested to change by a caller. */
if (!(params->rmask & (1 << k))) if (!(params->rmask & (1 << k)))
continue; continue;
...@@ -277,6 +279,7 @@ static int constrain_mask_params(struct snd_pcm_substream *substream, ...@@ -277,6 +279,7 @@ static int constrain_mask_params(struct snd_pcm_substream *substream,
trace_hw_mask_param(substream, k, 0, &old_mask, m); trace_hw_mask_param(substream, k, 0, &old_mask, m);
/* Set corresponding flag so that the caller gets it. */
if (changed) if (changed)
params->cmask |= 1 << k; params->cmask |= 1 << k;
if (changed < 0) if (changed < 0)
...@@ -300,6 +303,8 @@ static int constrain_interval_params(struct snd_pcm_substream *substream, ...@@ -300,6 +303,8 @@ static int constrain_interval_params(struct snd_pcm_substream *substream,
i = hw_param_interval(params, k); i = hw_param_interval(params, k);
if (snd_interval_empty(i)) if (snd_interval_empty(i))
return -EINVAL; return -EINVAL;
/* This parameter is not requested to change by a caller. */
if (!(params->rmask & (1 << k))) if (!(params->rmask & (1 << k)))
continue; continue;
...@@ -310,6 +315,7 @@ static int constrain_interval_params(struct snd_pcm_substream *substream, ...@@ -310,6 +315,7 @@ static int constrain_interval_params(struct snd_pcm_substream *substream,
trace_hw_interval_param(substream, k, 0, &old_interval, i); trace_hw_interval_param(substream, k, 0, &old_interval, i);
/* Set corresponding flag so that the caller gets it. */
if (changed) if (changed)
params->cmask |= 1 << k; params->cmask |= 1 << k;
if (changed < 0) if (changed < 0)
...@@ -327,7 +333,7 @@ static int constrain_params_by_rules(struct snd_pcm_substream *substream, ...@@ -327,7 +333,7 @@ static int constrain_params_by_rules(struct snd_pcm_substream *substream,
unsigned int k; unsigned int k;
unsigned int rstamps[constrs->rules_num]; unsigned int rstamps[constrs->rules_num];
unsigned int vstamps[SNDRV_PCM_HW_PARAM_LAST_INTERVAL + 1]; unsigned int vstamps[SNDRV_PCM_HW_PARAM_LAST_INTERVAL + 1];
unsigned int stamp = 2; unsigned int stamp;
struct snd_pcm_hw_rule *r; struct snd_pcm_hw_rule *r;
unsigned int d; unsigned int d;
struct snd_mask old_mask; struct snd_mask old_mask;
...@@ -335,16 +341,54 @@ static int constrain_params_by_rules(struct snd_pcm_substream *substream, ...@@ -335,16 +341,54 @@ static int constrain_params_by_rules(struct snd_pcm_substream *substream,
bool again; bool again;
int changed; 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++) for (k = 0; k < constrs->rules_num; k++)
rstamps[k] = 0; 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++) for (k = 0; k <= SNDRV_PCM_HW_PARAM_LAST_INTERVAL; k++)
vstamps[k] = (params->rmask & (1 << k)) ? 1 : 0; vstamps[k] = (params->rmask & (1 << k)) ? 1 : 0;
/* Due to the above design, actual sequence number starts at 2. */
stamp = 2;
retry: retry:
/* Apply all rules in order. */
again = false; again = false;
for (k = 0; k < constrs->rules_num; k++) { for (k = 0; k < constrs->rules_num; k++) {
r = &constrs->rules[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)) if (r->cond && !(r->cond & params->flags))
continue; 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++) { for (d = 0; r->deps[d] >= 0; d++) {
if (vstamps[r->deps[d]] > rstamps[k]) if (vstamps[r->deps[d]] > rstamps[k])
break; break;
...@@ -373,6 +417,12 @@ static int constrain_params_by_rules(struct snd_pcm_substream *substream, ...@@ -373,6 +417,12 @@ static int constrain_params_by_rules(struct snd_pcm_substream *substream,
} }
rstamps[k] = stamp; 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) { if (changed && r->var >= 0) {
params->cmask |= (1 << r->var); params->cmask |= (1 << r->var);
vstamps[r->var] = stamp; vstamps[r->var] = stamp;
...@@ -383,6 +433,7 @@ static int constrain_params_by_rules(struct snd_pcm_substream *substream, ...@@ -383,6 +433,7 @@ static int constrain_params_by_rules(struct snd_pcm_substream *substream,
stamp++; stamp++;
} }
/* Iterate to evaluate all rules till no parameters are changed. */
if (again) if (again)
goto retry; goto retry;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment