• Lars-Peter Clausen's avatar
    ASoC: dapm: Use more aggressive caching · 92a99ea4
    Lars-Peter Clausen authored
    Currently we cache the number of input and output paths going to/from a
    widget only within a power update sequence. But not in between power update
    sequences.
    
    But we know how changes to the DAPM graph affect the number of input (form a
    source) and output (to a sink) paths of a widget and only need to
    recalculate them if a operation has been performed that might have changed
    them.
    	* Adding/removing or connecting/disconnecting a path means that the for
    	  the source of the path the number of output paths can change and for
    	  the sink the number of input paths can change.
    	* Connecting/disconnecting a widget has the same effect has connecting/
    	  disconnecting all paths of the widget. So for the widget itself the
    	  number of inputs and outputs can change, for all sinks of the widget
    	  the number of inputs can change and for all sources of the widget the
    	  number of outputs can change.
    	* Activating/Deactivating a stream can either change the number of
    	  outputs on the sources of the widget associated with the stream or the
    	  number of inputs on the sinks.
    
    Instead of always invalidating all cached numbers of input and output paths
    for each power up or down sequence this patch restructures the code to only
    invalidate the cached numbers when a operation that might change them has
    been performed. This can greatly reduce the number of DAPM power checks for
    some very common operations.
    
    Since per DAPM operation typically only either change the number of inputs
    or outputs the number of path checks is reduced by at least 50%. The number
    of neighbor checks is also reduced about the same percentage, but since the
    number of neighbors encountered when walking from sink to source is not the
    same as when walking from source to sink the actual numbers will slightly
    vary from card to card (e.g. for a mixer we see 1 neighbor when walking from
    source to sink, but the number of inputs neighbors when walking from source
    to sink).
    
    Bigger improvements can be observed for widgets with multiple connected
    inputs and output (e.g. mixers probably being the most widespread form of
    this). Previously we had to re-calculate the number of inputs and outputs
    on all input and output paths. With this change we only have to re-calculate
    the number of outputs on the input path that got changed and the number of
    inputs on the output paths.
    
    E.g. imagine the following example:
    
    	A --> B ----.
    	            v
    	M --> N --> Z <-- S <-- R
    	            |
    	            v
    	            X
    
    Widget Z has multiple input paths, if any change was made that cause Z to be
    marked as dirty the power state of Z has to be re-computed. This requires to
    know the number of inputs and outputs of Z, which requires to know the
    number of inputs and outputs of all widgets on all paths from or to Z.
    Previously this meant re-computing all inputs and outputs of all the path
    going into or out of Z. With this patch in place only paths that actually
    have changed need to be re-computed.
    
    If the system is idle (or the part of the system affected by the changed
    path) the number of path checks drops to either 0 or 1, regardless of how
    large or complex the DAPM context is. 0 if there is no connected sink and no
    connected source. 1 if there is either a connected source or sink, but not
    both. The number of neighbor checks again will scale accordingly and will be
    a constant number that is the number of inputs or outputs of the widget for
    which we did the path check.
    
    When loading a state file or switching between different profiles typically
    multiple mixer and mux settings are changed, so we see the benefit of this
    patch multiplied for these kinds of operations.
    
    Testing with the ADAU1761 shows the following changes in DAPM stats for
    changing a single Mixer switch for a Mixer with 5 inputs while the DAPM
    context is idle.
    
             Power  Path  Neighbour
    Before:  2      12    30
    After:   2       1     2
    
    For the same switch, but with a active playback stream the stat changed are
    as follows.
    
             Power  Path  Neighbour
    Before:  10     20    54
    After:   10      7    21
    
    Cumulative numbers for switching the audio profile which changes 7 controls
    while the system is idle:
    
             Power  Path  Neighbour
    Before:  16      80   170
    After:   16       7    23
    
    Cumulative numbers for switching the audio profile which changes 7 controls
    while playback is active:
    
             Power  Path  Neighbour
    Before:  51     123   273
    After:   51      29   109
    
    Starting (or stopping) the playback stream:
    
             Power  Path  Neighbour
    Before:  34     34    117
    After:   34     17    69
    Signed-off-by: default avatarLars-Peter Clausen <lars@metafoo.de>
    Signed-off-by: default avatarMark Brown <broonie@kernel.org>
    92a99ea4
soc-dapm.c 97.7 KB