@ -267,6 +267,8 @@ static int constrain_mask_params(struct snd_pcm_substream *substream,
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 ;
@ -277,6 +279,7 @@ static int constrain_mask_params(struct snd_pcm_substream *substream,
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 )
@ -300,6 +303,8 @@ static int constrain_interval_params(struct snd_pcm_substream *substream,
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 ;
@ -310,6 +315,7 @@ static int constrain_interval_params(struct snd_pcm_substream *substream,
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 )
@ -327,7 +333,7 @@ static int constrain_params_by_rules(struct snd_pcm_substream *substream,
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 ;
@ -335,16 +341,54 @@ static int constrain_params_by_rules(struct snd_pcm_substream *substream,
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 ;
@ -373,6 +417,12 @@ retry:
}
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 ;
@ -383,6 +433,7 @@ retry:
stamp + + ;
}
/* Iterate to evaluate all rules till no parameters are changed. */
if ( again )
goto retry ;