| # Audio Codec Interface |
| |
| This document describes the codec interface between controllers and codecs in |
| Fuchsia. It is meant to serve as a reference for driver-authors, and to define |
| the interface contract which codec drivers must implement and that controllers |
| can use. The codec interface is a Banjo protocol exposed by codec drivers. |
| |
| ## Notation and Terminology |
| |
| In this document: |
| |
| - All indices start from 0. |
| - Vectors of n elements are represented as `<x0,x1,...,xn-1>`, for example a |
| vector with two elements 5 and 6 as `<5,6>`. |
| - Vectors can be nested, i.e. `<<5,6>,<7,8>>` represents a vector with 2 |
| vectors in it. |
| |
| | Term | Definition | |
| | ---------- | -------------------------------------------------------------- | |
| | Codec | A real or virtual device that encodes/decodes a signal from | |
| : : digital/analog to/from analog/digital including all : |
| : : combinations, e.g. digital to digital. Example codecs include : |
| : : DAC-Amplifiers combos and ADC converters. : |
| | Controller | The part of a system that manages the audio signals, for | |
| : : example an SOC's audio subsystem or an independent sound card. : |
| | DAI | Digital Audio Interface. Interface between controllers and | |
| : : Codecs. For example an I2S or HDA link. : |
| | Frame Sync | A DAI signal that marks frame boundaries, a.k.a. LRCLK, SYNC. | |
| | Sclk | A DAI signal used to mark the data line(s) bits transferring, : |
| : : a.k.a. SCK, BCLK. : |
| | Mclk | Master clock, a DAI signal sometimes needed to provide a clock | |
| : : to codecs. Sometimes Sclk is used as the Mclk (or Mclk is : |
| : : derived from the Sclk within the codec). : |
| | Frame | The representation of a single moment in time across data, : |
| : : frame sync and sclk in the DAI. : |
| | Frame format | A frame's data, frame sync and sclk arrangement, e.g. location | |
| : : of the frame sync w.r.t. samples in the data line(s). : |
| | Slot | Within a frame, the bits reserved for a sample. A slot may be | |
| : : bigger than needed to hold the samples, e.g. 32 bits slot : |
| : : holding 24 or 16 bits samples. : |
| | Channel | A single source or destination of audio samples, usually | |
| : : to be rendered by a single speaker or captured by a single : |
| : : microphone. Within a DAI every frame will contain samples in : |
| : : a fixed number of slots for the same fixed number of channels. : |
| | Sample | A digital representation of sound taken at a particular time. | |
| |
| ## Basic Operation |
| |
| The functionality provided by the codecs is divided into: |
| |
| - [Main controls](#main-controls) |
| - [Bridged Mode](#bridged-mode) |
| - [DAI format](#dai-format) |
| - [Gain control](#gain-control) |
| - [Plug detect](#plug-detect) |
| - [Power control](#power-control) |
| - [Peripheral control](#peripheral-control) |
| - [Signal processing control](#signal-processing-control) |
| - [Content protection](#content-protection) |
| |
| The controller is responsible for configuring and controlling the codecs. Codecs |
| advertize capabilities and a controller determines how they are used as |
| described below. The controller can control the codec's state, such as through the |
| reset function. A reset is required to get codecs to an initialized state. |
| Note that the codec drivers are expected to perform their own shutdown, just like |
| any other driver. |
| |
| Codecs are composite devices that provide the codec protocol to controllers. It |
| is expected that only one controller uses a codec's protocol, and one controller |
| may use multiple codecs at once. |
| |
| The [simple-codec](/src/media/audio/lib/simple-codec/README.md) library facilitates |
| writing and using simple codec drivers implementing the codec protocol. |
| |
| ## Protocol definition |
| |
| The codec protocol is defined in [Banjo](/docs/development/drivers/banjo-tutorial.md) at |
| [ddk.protocol.codec](/sdk/banjo/ddk.protocol.codec/codec.banjo). |
| |
| Many codec protocol operations are "fire-and-forget", i.e. they do not expect a |
| reply. Codec protocol operations with a reply are not considered completed until |
| the reply of the function is received, and not considered completed successfully |
| unless the reply contains a status `ZX_OK`. |
| |
| ### Main Controls {#main-controls} |
| |
| A codec can be reset by a controller at any time by issuing the `Reset` |
| function. |
| |
| The `GetInfo` function retrieves information from the codec including: |
| |
| 1. A unique and persistent identifier for the codec unit, e.g. a serial number |
| or connection path. |
| 1. The manufacturer name. |
| 1. The product name. |
| |
| The codec operation can be started and stopped at any time with the `Start` and |
| `Stop` functions. By default the codec state is stopped, so 'Start' must be |
| issued at least once for the codec to be fully operational. Stopping the codec |
| operation can be used for example to change the DAI configuration safely avoiding |
| glitches or errors in the codec operation. |
| |
| ### Bridged Mode {#bridged-mode} |
| |
| Before specifying the DAI format the controller must query the codec for its |
| bridging capabilites. If the codec is bridgeable, then the controller must |
| enable or disable bridging based on its knowledge of the system configuration. |
| Note that this is a singular property of a codec, i.e. a codec either supports |
| bridging or not, and it can be set in bridged mode or not. This protocol allows |
| configuring as bridged only 2 channel stereo codecs, with the 2 outputs of the |
| codec electrically bridged. |
| |
| ### DAI Format {#dai-format} |
| |
| The DAI Format related protocol functions allow the codec to list its supported |
| formats for the DAI. The supported formats may include multiple sample formats, |
| rates, etc. Each codec advertises what it can support and the controller |
| mandates what DAI Format is to be used for each codec. |
| |
| To find out what formats are supported by a given codec, the controller uses the |
| `GetDaiFormats` function. The codec replies with a vector of |
| `DaiSupportedFormats`, where each `DaiSupportedFormats` includes: |
| |
| 1. A vector of number of channels. This lists the number of channels supported |
| by the codec, for example `<2,4,6,8>`. A stereo codec reports a vector with |
| one element `<2>`. Note that a codec that takes one channel and outputs its |
| contents in all its outputs (e.g. 2 for a stereo amplifier) would report a |
| vector with one element `<1>`, if it supports either one or two input |
| channels, it would report a vector with two elements `<1,2>`. |
| 2. A vector of sample formats. DAI sample formats, e.g. `PCM_SIGNED`. |
| 3. A vector of frame formats, for example `STEREO_LEFT` and `STEREO_RIGHT`. |
| 4. A vector of rates. Frame rates, for example 44100, 48000, and 96000. |
| 5. A number of bits per slot. Number of bits in each slot in the DAI, |
| e.g. 32 bits per slot. |
| 6. A vector of bits per sample. Sample widths, e.g. 24 bits per sample. |
| |
| When not all combinations supported by the codec can be described with one |
| `DaiSupportedFormats`, the codec returns more than one `DaiSupportedFormats` in |
| the returned vector. |
| |
| For example, if one `DaiSupportedFormats` allows for 32 bits samples at 48KHz, |
| and 16 bits samples at 96KHz, but not 32 bits samples at 96KHz, then the codec |
| will reply with 2 `DaiSupportedFormats`: `<<32bits>,<48KHz>>` and |
| `<<16bits>,<96KHz>>`. For simplicity, this example ignores parameters other than |
| rate and bits per sample. In the case where the codec supports either 16 or 32 |
| bits samples at either 48 or 96KHz, the codec would reply with 1 |
| `DaiSupportedFormats`: `<<16bits,32bits>,<48KHz,96KHz>>`. |
| |
| Additionally, it is assumed that bits per sample is always smaller or equal to |
| bits per slot. Hence, a codec can report |
| `<<16bits_per_slot,32bits_per_slot>,<16bits_per_sample,32bits_per_sample>>` |
| and this does not imply that it is reporting that 32 bits per sample on 16 bits |
| samples is valid, it specifies only the 3 valid combinations: |
| |
| 1. 16 bits slot with 16 bits samples |
| 2. 32 bits slot with 32 bits samples |
| 3. 32 bits slot with 16 bits samples |
| |
| Using the information provided by the codec in `IsBridgeable` and |
| `GetDaiFormat`, what is supported by the controller, and any other requirements, |
| the controller specifies the format to use in the DAI with the `SetDaiFormat` |
| function. This functions takes a parameter that specifies: |
| |
| 1. A number of channels. This is the number of channels to be used in the DAI |
| (for instance number of channels on a TDM bus, i.e. "on the wire"). For I2S |
| this must be 2. |
| 2. A vector of channels to use. These are the channels in the DAI to be used by |
| the codec. For I2S this must be a vector with 2 indexes `<0,1>`, i.e. both |
| left and right channels are used. In bridged mode this will list only the |
| one channel to be used by the codec, for example a codec’s stereo amplifier |
| output bridged into one electrical mono output from the right channel of an |
| I2S DAI would list only channel `<1>`. If not bridged, a codec with multiple |
| electrical outputs that is configured with one channel in `SetDaiFormat` is |
| expected to replicate the samples in this mono input on all its outputs. |
| 3. A sample format. |
| 4. A frame format. |
| 5. A frame rate. |
| 6. A number of bits per slot. |
| 7. A number of bits per sample. |
| |
| Once `SetDaiFormat` is successful, the DAI format configuration is considered |
| completed and samples can be sent across the DAI. |
| |
| TODO(andresoportus): Add DAI format loss notification support once asynchronous |
| notifications are added to Banjo. |
| |
| ### Gain Control {#gain-control} |
| |
| Gain related support by any given codec is returned by the codec in response to |
| a `GetGainFormat` function in the `GainFormat` structure. The controller can |
| control gain, mute and AGC states in a codec using the `SetGainState` function |
| and the corresponding `GetGainState` function allows retrieving the current |
| state for the same. |
| |
| ### Plug Detect {#plug-detect} |
| |
| The controller can query the plug detect state with the `GetPlugState` function. |
| The plug state includes hardwired and plugged states. |
| |
| TODO(andresoportus): Add `can_notify` bool to `PlugState` once asynchronous |
| notifications are added to Banjo. |
| |
| ### Power Control {#power-control} |
| |
| TODO(andresoportus). |
| |
| ### Peripheral Control {#peripheral-control} |
| |
| TODO(andresoportus). |
| |
| ### Signal Processing Control {#signal-processing-control} |
| |
| TODO(andresoportus). |
| |
| ### Content Protection {#content-protection} |
| |
| TODO(andresoportus). |