From mboxrd@z Thu Jan 1 00:00:00 1970 From: Pierre-Louis Bossart Subject: Re: [PATCH v2 01/13] soundwire: Add more documentation Date: Thu, 5 Apr 2018 16:37:14 -0500 Message-ID: <1f54fc62-8da0-ee1e-327c-30230b5f00f6@linux.intel.com> References: <1522946904-2089-1-git-send-email-vinod.koul@intel.com> <1522946904-2089-2-git-send-email-vinod.koul@intel.com> Mime-Version: 1.0 Content-Type: text/plain; charset="us-ascii"; Format="flowed" Content-Transfer-Encoding: 7bit Return-path: Received: from mga05.intel.com (mga05.intel.com [192.55.52.43]) by alsa0.perex.cz (Postfix) with ESMTP id C9BDD267299 for ; Thu, 5 Apr 2018 23:37:19 +0200 (CEST) In-Reply-To: <1522946904-2089-2-git-send-email-vinod.koul@intel.com> Content-Language: en-US List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: alsa-devel-bounces@alsa-project.org Sender: alsa-devel-bounces@alsa-project.org To: Vinod Koul , Greg KH Cc: ALSA , tiwai@suse.de, liam.r.girdwood@linux.intel.com, patches.audio@intel.com, broonie@kernel.org, Sanyog Kale List-Id: alsa-devel@alsa-project.org On 4/5/18 11:48 AM, Vinod Koul wrote: > From: Sanyog Kale > > This adds documentation for error handling, locking and streams. > > Signed-off-by: Pierre-Louis Bossart > Signed-off-by: Sanyog Kale > Signed-off-by: Shreyas NC > Signed-off-by: Vinod Koul > --- > .../driver-api/soundwire/error_handling.rst | 65 ++++ > Documentation/driver-api/soundwire/index.rst | 3 + > Documentation/driver-api/soundwire/locking.rst | 106 ++++++ > Documentation/driver-api/soundwire/stream.rst | 368 +++++++++++++++++++++ > 4 files changed, 542 insertions(+) > create mode 100644 Documentation/driver-api/soundwire/error_handling.rst > create mode 100644 Documentation/driver-api/soundwire/locking.rst > create mode 100644 Documentation/driver-api/soundwire/stream.rst > > diff --git a/Documentation/driver-api/soundwire/error_handling.rst b/Documentation/driver-api/soundwire/error_handling.rst > new file mode 100644 > index 000000000000..aa3a0a23a066 > --- /dev/null > +++ b/Documentation/driver-api/soundwire/error_handling.rst > @@ -0,0 +1,65 @@ > +======================== > +SoundWire Error Handling > +======================== > + > +The SoundWire PHY was designed with care and errors on the bus are going to > +be very unlikely, and if they happen it should be limited to single bit > +errors. Examples of this design can be found in the synchronization > +mechanism (sync loss after two errors) and short CRCs used for the Bulk > +Register Access. > + > +The errors can be detected with multiple mechanisms: > + > +1. Bus clash or parity errors: This mechanism relies on low-level detectors > + that are independent of the payload and usages, and they cover both control > + and audio data. The current implementation only logs such errors. > + Improvements could be invalidating an entire programming sequence and > + restarting from a known position. In the case of such errors outside of a > + control/command sequence, there is no concealment or recovery for audio > + data enabled by the SoundWire protocol, the location of the error will also > + impact its audibility (most-significant bits will be more impacted in PCM), > + and after a number of such errors are detected the bus might be reset. Note > + that bus clashes due to programming errors (two streams using the same bit > + slots) or electrical issues during the transmit/receive transition cannot > + be distinguished, although a recurring bus clash when audio is enabled is a > + indication of a bus allocation issue. The interrupt mechanism can also help > + identify Slaves which detected a Bus Clash or a Parity Error, but they may > + not be responsible for the errors so resetting them individually is not a > + viable recovery strategy. > + > +2. Command status: Each command is associated with a status, which only > + covers transmission of the data between devices. The ACK status indicates > + that the command was received and will be executed by the end of the > + current frame. A NAK indicates that the command was in error and will not > + be applied. In case of a bad programming (command sent to non-existent > + Slave or to a non-implemented register) or electrical issue, no response > + signals the command was ignored. Some Master implementations allow for a > + command to be retransmitted several times. If the retransmission fails, > + backtracking and restarting the entire programming sequence might be a > + solution. Alternatively some implementations might directly issue a bus > + reset and re-enumerate all devices. > + > +3. Timeouts: In a number of cases such as ChannelPrepare or > + ClockStopPrepare, the bus driver is supposed to poll a register field until > + it transitions to a NotFinished value of zero. The MIPI SoundWire spec 1.1 > + does not define timeouts but the MIPI SoundWire DisCo document adds > + recommendation on timeouts. If such configurations do not complete, the > + driver will return a -ETIMEOUT. Such timeouts are symptoms of a faulty > + Slave device and are likely impossible to recover from. > + > +Errors during global reconfiguration sequences are extremely difficult to > +handle: > + > +1. BankSwitch: An error during the last command issuing a BankSwitch is > + difficult to backtrack from. Retransmitting the Bank Switch command may be > + possible in a single segment setup, but this can lead to synchronization > + problems when enabling multiple bus segments (a command with side effects > + such as frame reconfiguration would be handled at different times). A global > + hard-reset might be the best solution. > + > +Note that SoundWire does not provide a mechanism to detect illegal values > +written in valid registers. In a number of cases the standard even mentions > +that the Slave might behave in implementation-defined ways. The bus > +implementation does not provide a recovery mechanism for such errors, Slave > +or Master driver implementers are responsible for writing valid values in > +valid registers and implement additional range checking if needed. > diff --git a/Documentation/driver-api/soundwire/index.rst b/Documentation/driver-api/soundwire/index.rst > index 647e94654752..6db026028f27 100644 > --- a/Documentation/driver-api/soundwire/index.rst > +++ b/Documentation/driver-api/soundwire/index.rst > @@ -6,6 +6,9 @@ SoundWire Documentation > :maxdepth: 1 > > summary > + stream > + error_handling > + locking > > .. only:: subproject > > diff --git a/Documentation/driver-api/soundwire/locking.rst b/Documentation/driver-api/soundwire/locking.rst > new file mode 100644 > index 000000000000..253f73555255 > --- /dev/null > +++ b/Documentation/driver-api/soundwire/locking.rst > @@ -0,0 +1,106 @@ > +================= > +SoundWire Locking > +================= > + > +This document explains locking mechanism of the SoundWire Bus. Bus uses > +following locks in order to avoid race conditions in Bus operations on > +shared resources. > + > + - Bus lock > + > + - Message lock > + > +Bus lock > +======== > + > +SoundWire Bus lock is a mutex and is part of Bus data structure > +(sdw_bus) which is used for every Bus instance. This lock is used to > +serialize each of the following operations(s) within SoundWire Bus instance. > + > + - Addition and removal of Slave(s), changing Slave status. > + > + - Prepare, Enable, Disable and De-prepare stream operations. > + > + - Access of Stream data structure. > + > +Message lock > +============ > + > +SoundWire message transfer lock. This mutex is part of > +Bus data structure (sdw_bus). This lock is used to serialize the message > +transfers (read/write) within a SoundWire Bus instance. > + > +Below examples show how locks are acquired. > + > +Example 1 > +--------- > + > +Message transfer. > + > + 1. For every message transfer > + > + a. Acquire Message lock. > + > + b. Transfer message (Read/Write) to Slave1 or broadcast message on > + Bus in case of bank switch. > + > + c. Release Message lock :: > + > + +----------+ +---------+ > + | | | | > + | Bus | | Master | > + | | | Driver | > + | | | | > + +----+-----+ +----+----+ > + | | > + | bus->ops->xfer_msg() | > + <-------------------------------+ a. Acquire Message lock > + | | b. Transfer message > + | | > + +-------------------------------> c. Release Message lock > + | return success/error | d. Return success/error > + | | > + + + > + > +Example 2 > +--------- > + > +Prepare operation. > + > + 1. Acquire lock for Bus instance associated with Master 1. > + > + 2. For every message transfer in Prepare operation > + > + a. Acquire Message lock. > + > + b. Transfer message (Read/Write) to Slave1 or broadcast message on > + Bus in case of bank switch. > + > + c. Release Message lock. > + > + 3. Release lock for Bus instance associated with Master 1 :: > + > + +----------+ +---------+ > + | | | | > + | Bus | | Master | > + | | | Driver | > + | | | | > + +----+-----+ +----+----+ > + | | > + | sdw_prepare_stream() | > + <-------------------------------+ 1. Acquire bus lock > + | | 2. Perform stream prepare > + | | > + | | > + | bus->ops->xfer_msg() | > + <-------------------------------+ a. Acquire Message lock > + | | b. Transfer message > + | | > + +-------------------------------> c. Release Message lock > + | return success/error | d. Return success/error > + | | > + | | > + | return success/error | 3. Release bus lock > + +-------------------------------> 4. Return success/error > + | | > + + + > diff --git a/Documentation/driver-api/soundwire/stream.rst b/Documentation/driver-api/soundwire/stream.rst > new file mode 100644 > index 000000000000..83830e1dd138 > --- /dev/null > +++ b/Documentation/driver-api/soundwire/stream.rst > @@ -0,0 +1,368 @@ > +========================= > +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 | > + +----------+ +------------+ +----------+ > + Patch 2 describes the states as below: +enum sdw_stream_state { + SDW_STREAM_RELEASED = 0, + SDW_STREAM_ALLOCATED = 1, + SDW_STREAM_CONFIGURED = 2, + SDW_STREAM_PREPARED = 3, + SDW_STREAM_ENABLED = 4, + SDW_STREAM_DISABLED = 5, + SDW_STREAM_DEPREPARED = 6, which isn't the same picture as the ascii art above. The RELEASED state is the starting point, and there's an arrow missing from RELEASED to ALLOCATED. > +NOTE: State transition between prepare and deprepare is supported in Spec > +but not in the software (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. >