373 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			ReStructuredText
		
	
	
	
	
	
			
		
		
	
	
			373 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			ReStructuredText
		
	
	
	
	
	
=========================
 | 
						|
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 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)    |
 | 
						|
	+--------------------+                             |                |
 | 
						|
							   +----------------+
 | 
						|
 | 
						|
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
 | 
						|
	         +----------+           +------------+        +----+-----+
 | 
						|
	         | RELEASED |<----------+ DEPREPARED |<-------+ DISABLED |
 | 
						|
	         |  STATE   |           |   STATE    |        |  STATE   |
 | 
						|
	         +----------+           +------------+        +----------+
 | 
						|
 | 
						|
NOTE: State transition between prepare and deprepare is supported in Spec
 | 
						|
but not in the software (subsystem)
 | 
						|
 | 
						|
NOTE2: Stream state transition checks need to be handled by caller
 | 
						|
framework, for example ALSA/ASoC. No checks for stream transition exist in
 | 
						|
SoundWire subsystem.
 | 
						|
 | 
						|
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);
 | 
						|
 | 
						|
 | 
						|
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:
 | 
						|
 | 
						|
  (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.
 | 
						|
 | 
						|
  .. 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.
 | 
						|
 | 
						|
  .. 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. From ASoC DPCM framework, this stream state is linked to
 | 
						|
.trigger() stop operation.
 | 
						|
 | 
						|
  .. 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);
 | 
						|
 | 
						|
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.
 |