123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527 |
- =========================
- Audio Stream in SoundWire
- =========================
- An audio stream is a logical or virtual connection created between
- (1) System memory buffer(s) and Codec(s)
- (2) DSP memory buffer(s) and Codec(s)
- (3) FIFO(s) and Codec(s)
- (4) Codec(s) and Codec(s)
- which is typically driven by a DMA(s) channel through the data link. An
- audio stream contains one or more channels of data. All channels within
- stream must have same sample rate and same sample size.
- Assume a stream with two channels (Left & Right) is opened using SoundWire
- interface. Below are some ways a stream can be represented in SoundWire.
- Stream Sample in memory (System memory, DSP memory or FIFOs) ::
- -------------------------
- | L | R | L | R | L | R |
- -------------------------
- Example 1: Stereo Stream with L and R channels is rendered from Master to
- Slave. Both Master and Slave is using single port. ::
- +---------------+ Clock Signal +---------------+
- | Master +----------------------------------+ Slave |
- | Interface | | Interface |
- | | | 1 |
- | | Data Signal | |
- | L + R +----------------------------------+ L + R |
- | (Data) | Data Direction | (Data) |
- +---------------+ +-----------------------> +---------------+
- Example 2: Stereo Stream with L and R channels is captured from Slave to
- Master. Both Master and Slave is using single port. ::
- +---------------+ Clock Signal +---------------+
- | Master +----------------------------------+ Slave |
- | Interface | | Interface |
- | | | 1 |
- | | Data Signal | |
- | L + R +----------------------------------+ L + R |
- | (Data) | Data Direction | (Data) |
- +---------------+ <-----------------------+ +---------------+
- Example 3: Stereo Stream with L and R channels is rendered by Master. Each
- of the L and R channel is received by two different Slaves. Master and both
- Slaves are using single port. ::
- +---------------+ Clock Signal +---------------+
- | Master +---------+------------------------+ Slave |
- | Interface | | | Interface |
- | | | | 1 |
- | | | Data Signal | |
- | L + R +---+------------------------------+ L |
- | (Data) | | | Data Direction | (Data) |
- +---------------+ | | +-------------> +---------------+
- | |
- | |
- | | +---------------+
- | +----------------------> | Slave |
- | | Interface |
- | | 2 |
- | | |
- +----------------------------> | R |
- | (Data) |
- +---------------+
- Example 4: Stereo Stream with L and R channels is rendered by
- Master. Both of the L and R channels are received by two different
- Slaves. Master and both Slaves are using single port handling
- L+R. Each Slave device processes the L + R data locally, typically
- based on static configuration or dynamic orientation, and may drive
- one or more speakers. ::
- +---------------+ Clock Signal +---------------+
- | Master +---------+------------------------+ Slave |
- | Interface | | | Interface |
- | | | | 1 |
- | | | Data Signal | |
- | L + R +---+------------------------------+ L + R |
- | (Data) | | | Data Direction | (Data) |
- +---------------+ | | +-------------> +---------------+
- | |
- | |
- | | +---------------+
- | +----------------------> | Slave |
- | | Interface |
- | | 2 |
- | | |
- +----------------------------> | L + R |
- | (Data) |
- +---------------+
- Example 5: Stereo Stream with L and R channel is rendered by two different
- Ports of the Master and is received by only single Port of the Slave
- interface. ::
- +--------------------+
- | |
- | +--------------+ +----------------+
- | | || | |
- | | Data Port || L Channel | |
- | | 1 |------------+ | |
- | | L Channel || | +-----+----+ |
- | | (Data) || | L + R Channel || Data | |
- | Master +----------+ | +---+---------> || Port | |
- | Interface | | || 1 | |
- | +--------------+ | || | |
- | | || | +----------+ |
- | | Data Port |------------+ | |
- | | 2 || R Channel | Slave |
- | | R Channel || | Interface |
- | | (Data) || | 1 |
- | +--------------+ Clock Signal | L + R |
- | +---------------------------> | (Data) |
- +--------------------+ | |
- +----------------+
- Example 6: Stereo Stream with L and R channel is rendered by 2 Masters, each
- rendering one channel, and is received by two different Slaves, each
- receiving one channel. Both Masters and both Slaves are using single port. ::
- +---------------+ Clock Signal +---------------+
- | Master +----------------------------------+ Slave |
- | Interface | | Interface |
- | 1 | | 1 |
- | | Data Signal | |
- | L +----------------------------------+ L |
- | (Data) | Data Direction | (Data) |
- +---------------+ +-----------------------> +---------------+
- +---------------+ Clock Signal +---------------+
- | Master +----------------------------------+ Slave |
- | Interface | | Interface |
- | 2 | | 2 |
- | | Data Signal | |
- | R +----------------------------------+ R |
- | (Data) | Data Direction | (Data) |
- +---------------+ +-----------------------> +---------------+
- Example 7: Stereo Stream with L and R channel is rendered by 2
- Masters, each rendering both channels. Each Slave receives L + R. This
- is the same application as Example 4 but with Slaves placed on
- separate links. ::
- +---------------+ Clock Signal +---------------+
- | Master +----------------------------------+ Slave |
- | Interface | | Interface |
- | 1 | | 1 |
- | | Data Signal | |
- | L + R +----------------------------------+ L + R |
- | (Data) | Data Direction | (Data) |
- +---------------+ +-----------------------> +---------------+
- +---------------+ Clock Signal +---------------+
- | Master +----------------------------------+ Slave |
- | Interface | | Interface |
- | 2 | | 2 |
- | | Data Signal | |
- | L + R +----------------------------------+ L + R |
- | (Data) | Data Direction | (Data) |
- +---------------+ +-----------------------> +---------------+
- Example 8: 4-channel Stream is rendered by 2 Masters, each rendering a
- 2 channels. Each Slave receives 2 channels. ::
- +---------------+ Clock Signal +---------------+
- | Master +----------------------------------+ Slave |
- | Interface | | Interface |
- | 1 | | 1 |
- | | Data Signal | |
- | L1 + R1 +----------------------------------+ L1 + R1 |
- | (Data) | Data Direction | (Data) |
- +---------------+ +-----------------------> +---------------+
- +---------------+ Clock Signal +---------------+
- | Master +----------------------------------+ Slave |
- | Interface | | Interface |
- | 2 | | 2 |
- | | Data Signal | |
- | L2 + R2 +----------------------------------+ L2 + R2 |
- | (Data) | Data Direction | (Data) |
- +---------------+ +-----------------------> +---------------+
- Note1: In multi-link cases like above, to lock, one would acquire a global
- lock and then go on locking bus instances. But, in this case the caller
- framework(ASoC DPCM) guarantees that stream operations on a card are
- always serialized. So, there is no race condition and hence no need for
- global lock.
- Note2: A Slave device may be configured to receive all channels
- transmitted on a link for a given Stream (Example 4) or just a subset
- of the data (Example 3). The configuration of the Slave device is not
- handled by a SoundWire subsystem API, but instead by the
- snd_soc_dai_set_tdm_slot() API. The platform or machine driver will
- typically configure which of the slots are used. For Example 4, the
- same slots would be used by all Devices, while for Example 3 the Slave
- Device1 would use e.g. Slot 0 and Slave device2 slot 1.
- Note3: Multiple Sink ports can extract the same information for the
- same bitSlots in the SoundWire frame, however multiple Source ports
- shall be configured with different bitSlot configurations. This is the
- same limitation as with I2S/PCM TDM usages.
- SoundWire Stream Management flow
- ================================
- Stream definitions
- ------------------
- (1) Current stream: This is classified as the stream on which operation has
- to be performed like prepare, enable, disable, de-prepare etc.
- (2) Active stream: This is classified as the stream which is already active
- on Bus other than current stream. There can be multiple active streams
- on the Bus.
- SoundWire Bus manages stream operations for each stream getting
- rendered/captured on the SoundWire Bus. This section explains Bus operations
- done for each of the stream allocated/released on Bus. Following are the
- stream states maintained by the Bus for each of the audio stream.
- SoundWire stream states
- -----------------------
- Below shows the SoundWire stream states and state transition diagram. ::
- +-----------+ +------------+ +----------+ +----------+
- | ALLOCATED +---->| CONFIGURED +---->| PREPARED +---->| ENABLED |
- | STATE | | STATE | | STATE | | STATE |
- +-----------+ +------------+ +---+--+---+ +----+-----+
- ^ ^ ^
- | | |
- __| |___________ |
- | | |
- v | v
- +----------+ +-----+------+ +-+--+-----+
- | RELEASED |<----------+ DEPREPARED |<-------+ DISABLED |
- | STATE | | STATE | | STATE |
- +----------+ +------------+ +----------+
- NOTE: State transitions between ``SDW_STREAM_ENABLED`` and
- ``SDW_STREAM_DISABLED`` are only relevant when then INFO_PAUSE flag is
- supported at the ALSA/ASoC level. Likewise the transition between
- ``SDW_DISABLED_STATE`` and ``SDW_PREPARED_STATE`` depends on the
- INFO_RESUME flag.
- NOTE2: The framework implements basic state transition checks, but
- does not e.g. check if a transition from DISABLED to ENABLED is valid
- on a specific platform. Such tests need to be added at the ALSA/ASoC
- level.
- Stream State Operations
- -----------------------
- Below section explains the operations done by the Bus on Master(s) and
- Slave(s) as part of stream state transitions.
- SDW_STREAM_ALLOCATED
- ~~~~~~~~~~~~~~~~~~~~
- Allocation state for stream. This is the entry state
- of the stream. Operations performed before entering in this state:
- (1) A stream runtime is allocated for the stream. This stream
- runtime is used as a reference for all the operations performed
- on the stream.
- (2) The resources required for holding stream runtime information are
- allocated and initialized. This holds all stream related information
- such as stream type (PCM/PDM) and parameters, Master and Slave
- interface associated with the stream, stream state etc.
- After all above operations are successful, stream state is set to
- ``SDW_STREAM_ALLOCATED``.
- Bus implements below API for allocate a stream which needs to be called once
- per stream. From ASoC DPCM framework, this stream state maybe linked to
- .startup() operation.
- .. code-block:: c
- int sdw_alloc_stream(char * stream_name);
- The SoundWire core provides a sdw_startup_stream() helper function,
- typically called during a dailink .startup() callback, which performs
- stream allocation and sets the stream pointer for all DAIs
- connected to a stream.
- SDW_STREAM_CONFIGURED
- ~~~~~~~~~~~~~~~~~~~~~
- Configuration state of stream. Operations performed before entering in
- this state:
- (1) The resources allocated for stream information in SDW_STREAM_ALLOCATED
- state are updated here. This includes stream parameters, Master(s)
- and Slave(s) runtime information associated with current stream.
- (2) All the Master(s) and Slave(s) associated with current stream provide
- the port information to Bus which includes port numbers allocated by
- Master(s) and Slave(s) for current stream and their channel mask.
- After all above operations are successful, stream state is set to
- ``SDW_STREAM_CONFIGURED``.
- Bus implements below APIs for CONFIG state which needs to be called by
- the respective Master(s) and Slave(s) associated with stream. These APIs can
- only be invoked once by respective Master(s) and Slave(s). From ASoC DPCM
- framework, this stream state is linked to .hw_params() operation.
- .. code-block:: c
- int sdw_stream_add_master(struct sdw_bus * bus,
- struct sdw_stream_config * stream_config,
- struct sdw_ports_config * ports_config,
- struct sdw_stream_runtime * stream);
- int sdw_stream_add_slave(struct sdw_slave * slave,
- struct sdw_stream_config * stream_config,
- struct sdw_ports_config * ports_config,
- struct sdw_stream_runtime * stream);
- SDW_STREAM_PREPARED
- ~~~~~~~~~~~~~~~~~~~
- Prepare state of stream. Operations performed before entering in this state:
- (0) Steps 1 and 2 are omitted in the case of a resume operation,
- where the bus bandwidth is known.
- (1) Bus parameters such as bandwidth, frame shape, clock frequency,
- are computed based on current stream as well as already active
- stream(s) on Bus. Re-computation is required to accommodate current
- stream on the Bus.
- (2) Transport and port parameters of all Master(s) and Slave(s) port(s) are
- computed for the current as well as already active stream based on frame
- shape and clock frequency computed in step 1.
- (3) Computed Bus and transport parameters are programmed in Master(s) and
- Slave(s) registers. The banked registers programming is done on the
- alternate bank (bank currently unused). Port(s) are enabled for the
- already active stream(s) on the alternate bank (bank currently unused).
- This is done in order to not disrupt already active stream(s).
- (4) Once all the values are programmed, Bus initiates switch to alternate
- bank where all new values programmed gets into effect.
- (5) Ports of Master(s) and Slave(s) for current stream are prepared by
- programming PrepareCtrl register.
- After all above operations are successful, stream state is set to
- ``SDW_STREAM_PREPARED``.
- Bus implements below API for PREPARE state which needs to be called
- once per stream. From ASoC DPCM framework, this stream state is linked
- to .prepare() operation. Since the .trigger() operations may not
- follow the .prepare(), a direct transition from
- ``SDW_STREAM_PREPARED`` to ``SDW_STREAM_DEPREPARED`` is allowed.
- .. code-block:: c
- int sdw_prepare_stream(struct sdw_stream_runtime * stream);
- SDW_STREAM_ENABLED
- ~~~~~~~~~~~~~~~~~~
- Enable state of stream. The data port(s) are enabled upon entering this state.
- Operations performed before entering in this state:
- (1) All the values computed in SDW_STREAM_PREPARED state are programmed
- in alternate bank (bank currently unused). It includes programming of
- already active stream(s) as well.
- (2) All the Master(s) and Slave(s) port(s) for the current stream are
- enabled on alternate bank (bank currently unused) by programming
- ChannelEn register.
- (3) Once all the values are programmed, Bus initiates switch to alternate
- bank where all new values programmed gets into effect and port(s)
- associated with current stream are enabled.
- After all above operations are successful, stream state is set to
- ``SDW_STREAM_ENABLED``.
- Bus implements below API for ENABLE state which needs to be called once per
- stream. From ASoC DPCM framework, this stream state is linked to
- .trigger() start operation.
- .. code-block:: c
- int sdw_enable_stream(struct sdw_stream_runtime * stream);
- SDW_STREAM_DISABLED
- ~~~~~~~~~~~~~~~~~~~
- Disable state of stream. The data port(s) are disabled upon exiting this state.
- Operations performed before entering in this state:
- (1) All the Master(s) and Slave(s) port(s) for the current stream are
- disabled on alternate bank (bank currently unused) by programming
- ChannelEn register.
- (2) All the current configuration of Bus and active stream(s) are programmed
- into alternate bank (bank currently unused).
- (3) Once all the values are programmed, Bus initiates switch to alternate
- bank where all new values programmed gets into effect and port(s) associated
- with current stream are disabled.
- After all above operations are successful, stream state is set to
- ``SDW_STREAM_DISABLED``.
- Bus implements below API for DISABLED state which needs to be called once
- per stream. From ASoC DPCM framework, this stream state is linked to
- .trigger() stop operation.
- When the INFO_PAUSE flag is supported, a direct transition to
- ``SDW_STREAM_ENABLED`` is allowed.
- For resume operations where ASoC will use the .prepare() callback, the
- stream can transition from ``SDW_STREAM_DISABLED`` to
- ``SDW_STREAM_PREPARED``, with all required settings restored but
- without updating the bandwidth and bit allocation.
- .. code-block:: c
- int sdw_disable_stream(struct sdw_stream_runtime * stream);
- SDW_STREAM_DEPREPARED
- ~~~~~~~~~~~~~~~~~~~~~
- De-prepare state of stream. Operations performed before entering in this
- state:
- (1) All the port(s) of Master(s) and Slave(s) for current stream are
- de-prepared by programming PrepareCtrl register.
- (2) The payload bandwidth of current stream is reduced from the total
- bandwidth requirement of bus and new parameters calculated and
- applied by performing bank switch etc.
- After all above operations are successful, stream state is set to
- ``SDW_STREAM_DEPREPARED``.
- Bus implements below API for DEPREPARED state which needs to be called
- once per stream. ALSA/ASoC do not have a concept of 'deprepare', and
- the mapping from this stream state to ALSA/ASoC operation may be
- implementation specific.
- When the INFO_PAUSE flag is supported, the stream state is linked to
- the .hw_free() operation - the stream is not deprepared on a
- TRIGGER_STOP.
- Other implementations may transition to the ``SDW_STREAM_DEPREPARED``
- state on TRIGGER_STOP, should they require a transition through the
- ``SDW_STREAM_PREPARED`` state.
- .. code-block:: c
- int sdw_deprepare_stream(struct sdw_stream_runtime * stream);
- SDW_STREAM_RELEASED
- ~~~~~~~~~~~~~~~~~~~
- Release state of stream. Operations performed before entering in this state:
- (1) Release port resources for all Master(s) and Slave(s) port(s)
- associated with current stream.
- (2) Release Master(s) and Slave(s) runtime resources associated with
- current stream.
- (3) Release stream runtime resources associated with current stream.
- After all above operations are successful, stream state is set to
- ``SDW_STREAM_RELEASED``.
- Bus implements below APIs for RELEASE state which needs to be called by
- all the Master(s) and Slave(s) associated with stream. From ASoC DPCM
- framework, this stream state is linked to .hw_free() operation.
- .. code-block:: c
- int sdw_stream_remove_master(struct sdw_bus * bus,
- struct sdw_stream_runtime * stream);
- int sdw_stream_remove_slave(struct sdw_slave * slave,
- struct sdw_stream_runtime * stream);
- The .shutdown() ASoC DPCM operation calls below Bus API to release
- stream assigned as part of ALLOCATED state.
- In .shutdown() the data structure maintaining stream state are freed up.
- .. code-block:: c
- void sdw_release_stream(struct sdw_stream_runtime * stream);
- The SoundWire core provides a sdw_shutdown_stream() helper function,
- typically called during a dailink .shutdown() callback, which clears
- the stream pointer for all DAIS connected to a stream and releases the
- memory allocated for the stream.
- Not Supported
- =============
- 1. A single port with multiple channels supported cannot be used between two
- streams or across stream. For example a port with 4 channels cannot be used
- to handle 2 independent stereo streams even though it's possible in theory
- in SoundWire.
|