I2S

group I2S

I2S (Inter-IC Sound) Interface.

The I2S API provides support for the I2S interface.

Defines

PI_I2S_CH_FMT_DATA_ORDER_MSB

Data order MSB.

Data bits are transferred MSB first.

PI_I2S_CH_FMT_DATA_ORDER_LSB

Data order LSB.

Data bits are transferred LSB first.

PI_I2S_CH_FMT_DATA_ALIGN_LEFT

Data alignment left.

Left Justified.

PI_I2S_CH_FMT_DATA_ALIGN_RIGHT

Data alignment right.

Right Justified.

PI_I2S_CH_FMT_DATA_SIGN_NO_EXTEND

Data sign extension disabled.

Data are not sign extended when I2S data size is inferior to memory data size.

PI_I2S_CH_FMT_DATA_SIGN_EXTEND

Data sign extension enabled.

Data are sign extended when I2S data size is inferior to memory data size. For example when I2S data are on 16 bits but are stored in a 32 bits word, MSB sign is extended.

PI_I2S_OPT_PINGPONG
PI_I2S_OPT_MEM_SLAB

Mem slab mode.

In mem slab mode TX output or RX sampling will keep alternating between a a set of buffers given by the user. Memory slab pointed to by the mem_slab field has to be defined and initialized by the user. For I2S driver to function correctly number of memory blocks in a slab has to be at least 2 per queue. Size of the memory block should be multiple of frame_size where frame_size = (channels * word_size_bytes). As an example 16 bit word will occupy 2 bytes, 24 or 32 bit word will occupy 4 bytes.

PI_I2S_OPT_FULL_DUPLEX

Full duplex mode.

The normal and default mode is to use a single pin for both TX and RX. In full duplex mode, RX and TX will use 2 different pins(called sdi and sdo so that samples can be received and sent at the same time).

PI_I2S_OPT_DISABLED

Disable the channel.

If set, this desactivates the channel being configured (either RX or TX). Once the sampling is running, this will make sure this channel is not receiving or sending samples.

PI_I2S_OPT_ENABLED

Enable the channel.

If set, this activates the channel being configured (either RX or TX). Once the sampling is running, this will make sure this channel is receiving or sending samples.

PI_I2S_OPT_IS_TX

Configure TX channel.

If set, the configuration will apply to the TX channel and won’t change anything for what concerns the RX channel. Note that this does not prevent from using the RX channel, they must just be configured separately.

Setting this configuration allows to send data from memory to speakers.

PI_I2S_OPT_IS_RX

Configure RX channel.

If set, the configuration will apply to the RX channel and won’t change anything for what concerns the TX channel. Note that this does not prevent from using the TX channel, they must just be configured separately.

Setting this configuration allows to receive data from microphones to memory.

PI_I2S_OPT_LOOPBACK

TX loopback.

If set, this activates an internal loopback between the RX pin and TX pin. All data received on the RX will be sent to the TX pin. Note that this does not prevent from receiving data. Data received on the RX can be sent both to a memory buffer (if RX channel is enabled) and to the TX (if the loopback is enabled). The loopback must be applied on the TX channel.

PI_I2S_OPT_INT_CLK

Use internal clock.

Clock is generated internally from SOC’s clock.

This is default clock source.

PI_I2S_OPT_EXT_CLK

Use external clock.

If this option is specified, no clock is generated and an external clock is used.

PI_I2S_OPT_INT_WS

Use internal word strobe.

WS signal is generated internally from SCK signal.

This is default WS source.

PI_I2S_OPT_EXT_WS

Use external word strobe.

If this option is specified, no word strobe is generated and an external one is used.

PI_I2S_OPT_EXT_CLK_INT_ROUTED

Use internally routed ext clk.

If this option is specified, the clk of SAI1 or SAI2 is routed internnally from SAI0

PI_I2S_OPT_EXT_WS_INT_ROUTED

Use internally routed ext ws.

If this option is specified, the ws of SAI1 or SAI2 is routed internnally from SAI0

PI_I2S_OPT_CLK_POLARITY_RISING_EDGE

Data sampling on rising edge of the clock.

If this option is specified, the data are sampled and generated on the rising edge of the clock

PI_I2S_OPT_CLK_POLARITY_FALLING_EDGE

Data sampling on falling edge of the clock.

If this option is specified, the data are sampled and generated on the falling edge of the clock

PI_I2S_OPT_WS_POLARITY_RISING_EDGE

WS sampling on rising edge of the clock.

If this option is specified, the WS is sampled and generated on the rising edge of the clock.

PI_I2S_OPT_WS_POLARITY_FALLING_EDGE

Data sampling on falling edge of the clock.

If this option is specified, the WS is sampled and generated on the falling edge of the clock

PI_I2S_OPT_REF_CLK_FAST

Enable the ref clk fast.

If this option is specified, the clk will be based on the ref clk fast, but not the FLL.

Typedefs

typedef uint8_t pi_i2s_fmt_t
typedef uint16_t pi_i2s_opt_t
typedef struct pi_i2s_conf pi_i2s_conf_t
typedef struct pi_i2s_channel_conf pi_i2s_channel_conf_t

Enums

enum pi_i2s_mode_t

Values:

enumerator PI_I2S_MODE_I2S = 0

I2S mode.

This mode encapsulates standard 2-channel I2S mode and TDM mode. I2S vs TDM mode is selected by ‘ws_type’ field. Clocking and WS are controlled by related bits in ‘options’ field. PCM sample is packed into the slot according to its format settings: MSB vs LSB first, left or right alignment etc.

Example: Serial data is transmitted in two’s complement with the MSB first. Both Word Select (WS) and Serial Data (SD) signals are sampled on the rising edge of the clock signal (SCK). The MSB is always sent one clock period after the WS changes. Left channel data are sent first indicated by WS = 0, followed by right channel data indicated by WS = 1.

   -. .-. .-. .-. .-. .-. .-. .-. .-. .-. .-. .-. .-. .-. .-. .-. .-. .-.
SCK '-' '-' '-' '-' '-' '-' '-' '-' '-' '-' '-' '-' '-' '-' '-' '-' '-' '
   -.                               .-------------------------------.
WS  '-------------------------------'                               '----
   -.---.---.---.---.---.---.---.---.---.---.---.---.---.---.---.---.---.
SD  |   |MSB|   |...|   |LSB| x |...| x |MSB|   |...|   |LSB| x |...| x |
   -'---'---'---'---'---'---'---'---'---'---'---'---'---'---'---'---'---'
        | Left channel                  | Right channel                 |

enumerator PI_I2S_MODE_PDM = 1

Pulse-density modulation mode.

Serial data is transmitted/received using pulse-density modulation. SAI has various options to control number of PDM streams, signle vs differential mode and single-edge vs double-edge reception. The driver does not have direct access to PDM bit-stream, since it is routed to SFU PDM_OUT/PDM_IN blocks for modulation/demodulation, respectively. PCM samples therefore must pass via SFU, either simply from/to L2 via its MEM_IN/MEM_OUT blocks or form/to an internal SFU node.

enum pi_i2s_ioctl_cmd_e

IOCTL command.

Values:

enumerator PI_I2S_IOCTL_START

Start the transmission / reception of data.

This command can be used when the interface has been opened or stopped to start sampling.

enumerator PI_I2S_IOCTL_STOP

Stop the transmission / reception of data.

Stop the transmission / reception of data at the end of the current memory block. This command can be used when the interface is sampling and is stopping the interface. When the current TX / RX block is transmitted / received the interface is stopped. Subsequent START command will resume transmission / reception where it stopped.

enumerator PI_I2S_IOCTL_SYNC

Synchronize transmission / reception of data between different interfaces.

This command can be used when the sampling over different I2S interfaces has to be synchronized. The argument is an integer which specifies the list of interfaces which must be synchronized (one bit per interface). Once called, all further PI_I2S_IOCTL_START and PI_I2S_IOCTL_STOP as well as calls to pi_i2s_channel_enable on other interfaces are put on hold until a PI_I2S_IOCTL_START or PI_I2S_IOCTL_STOP command is issued on the interface where PI_I2S_IOCTL_SYNC was called, which commits the commands on all involved interfaces at the same time.

enumerator PI_I2S_IOCTL_CONF_SET

Configure a channel in TDM mode.

In TDM mode, the same interface is time-multiplexed to transmit data for multiple channels, and each channel can have a specific configuration. This command can be used to give the configuration of one channel. The argument must be a pointer to a structure of type struct pi_i2s_conf containing the channel configuration.

enumerator PI_I2S_IOCTL_CONF_GET

Get the current configuration of a channel in TDM mode.

In TDM mode, the same interface is time-multiplexed to transmit data for multiple channels, and each channel can have a specific configuration. This command can be used to get the current configuration of one channel. The argument must be a pointer to a structure of type struct pi_i2s_conf where the current channel configuration will be stored.

enumerator PI_I2S_IOCTL_CLOCK_ENABLE

Enable clock.

Enable clock for the i2s interface. This command does not sample data, and does not save data. It allows the interface to receive clock signals from SoC and propgate it to slave devices on end line.

enumerator PI_I2S_IOCTL_CLOCK_DISABLE

Disable clock.

Disable clock for the i2s interface.

enumerator PI_I2S_IOCTL_EN_TIMESTAMP

Enable the timestamp.

Enable the timestamp feature for the i2s interface.

Functions

void pi_i2s_setup(uint32_t flags)

Setup specific I2S aspects.

This function can be called to set specific I2S properties such as the number of clock generator. This is typically used by the BSP to give board specific information.

Parameters:
  • flags – A bitfield of chip-dependant properties.

void pi_i2s_conf_init(struct pi_i2s_conf *conf)

Initialize an I2S configuration with default values.

This function can be called to get default values for all parameters before setting some of them. The structure containing the configuration must be kept alive until the I2S device is opened.

Parameters:
  • conf – A pointer to the I2S configuration.

int32_t pi_i2s_open(struct pi_device *device)

Open an I2S device.

This function must be called before the I2S device can be used. It will do all the needed configuration to make it usable and initialize the handle used to refer to this opened device when calling other functions. The caller is blocked until the operation is finished.

Parameters:
  • device – A pointer to the device structure of the device to open. This structure is allocated by the caller and must be kept alive until the device is closed.

Return values:
  • 0 – Success

  • -1 – Failure

Returns:

Operation status

int32_t pi_i2s_close(struct pi_device *device)

Close an opened I2S device.

This function can be called to close an opened I2S device once it is not needed anymore, in order to free all allocated resources. Once this function is called, the device is not accessible anymore and must be opened again before being used. The caller is blocked until the operation is finished.

Parameters:
  • device – A pointer to the structure describing the device.

int pi_i2s_ioctl(struct pi_device *device, uint32_t cmd, void *arg)

Dynamically change the device configuration.

This function can be called to change part of the device configuration after it has been opened or to control it.

Parameters:
  • device – A pointer to the structure describing the device.

  • cmd – The command which specifies which parameters of the driver to modify and for some of them also their values. The command must be one of those defined in pi_i2s_ioctl_cmd_e enum.

  • arg – An additional value which is required for some parameters when they are set.

int pi_i2s_read(struct pi_device *dev, void **mem_block, size_t *size)

Read data from the RX queue.

Data received by the I2S interface is stored in the RX queue consisting of two memory blocks preallocated by the user and given to the driver in the configuration. Calling this function will return the next available buffer to the caller, which has to use it before the sampling for this buffer starts again.

The data is read in chunks equal to the size of the memory block.

When using several channels, the organization of the samples for each channel in the buffer, is chip-dependent, check the chip-specific documentation to get more information.

If there is no data in the RX queue the function will block waiting for the next RX memory block to fill in.

Due to hardware constraints, the address of the buffer must be aligned on 4 bytes.

Parameters:
  • dev – Pointer to the device structure for the driver instance.

  • mem_block – Pointer to the variable storing the address of the RX memory block containing received data.

  • size – Pointer to the variable storing the number of bytes read.

Return values:
  • 0 – Success

  • -1 – Failure

Returns:

Status operation

int pi_i2s_read_async(struct pi_device *dev, pi_evt_t *event)

Read data asynchronously from the RX queue.

Data received by the I2S interface is stored in the RX queue consisting of two memory blocks preallocated by the user and given to the driver in the configuration. Calling this function will return the next available buffer to the caller, which has to use it before the sampling for this buffer starts again.

The data is read in chunks equal to the size of the memory block.

When using several channels, the organization of the samples for each channel in the buffer, is chip-dependent, check the chip-specific documentation to get more information.

The specified task will be pushed as soon as data is ready in the RX queue, and the information about the memory block and the size will be available in the task.

Due to hardware constraints, the address of the buffer must be aligned on 4 bytes.

Parameters:
  • dev – Pointer to the device structure for the driver instance.

  • event – The event used to notify the end of transfer.

Return values:
  • 0 – Success

  • -1 – Failure

Returns:

Status operation

int pi_i2s_write(struct pi_device *dev, void *mem_block, size_t size)

Write data to the TX queue of a channel.

Data to be sent by the I2S interface is stored first in the TX queue consisting of memory blocks preallocated by the user with either pingpong buffers or a memory slab allocator.

In pingpong mode, the driver will automatically alternate between 2 buffers and the user code is supposed to call this function to notify the driver that the specified buffer is ready to be sent. This is used by the driver to report when an underrun or an overrun occurs.

In memory slab allocator mode, the user has to allocate buffers from the memory slab allocator and pass them to the driver by calling this function when they are ready to be sent.

This fonction will block until the specified buffer has been transfered.

Parameters:
  • dev – Pointer to the device structure for the driver instance.

  • mem_block – Pointer to the TX memory block containing data to be sent.

  • size – Number of bytes to write. This value has to be equal or smaller than the size of the memory block.

Return values:
  • 0 – Success

  • -1 – Failure

Returns:

Status operation

int pi_i2s_write_async(struct pi_device *dev, void *mem_block, size_t size, pi_evt_t *event)

Write data asynchronously to the TX queue of a channel.

Data to be sent by the I2S interface is stored first in the TX queue consisting of memory blocks preallocated by the user with either pingpong buffers or a memory slab allocator.

In pingpong mode, the driver will automatically alternate between 2 buffers and the user code is supposed to call this function to notify the driver that the specified buffer is ready to be sent. This is used by the driver to report when an underrun or an overrun occurs.

In memory slab allocator mode, the user has to allocate buffers from the memory slab allocator and pass them to the driver by calling this function when they are ready to be sent.

The specified event will be pushed as soon as data is has been transfered.

Parameters:
  • dev – Pointer to the device structure for the driver instance.

  • mem_block – Pointer to the TX memory block containing data to be sent.

  • size – Number of bytes to write. This value has to be equal or smaller than the size of the memory block.

  • event – The event used to notify the end of transfer.

Return values:
  • 0 – Success

  • -1 – Failure

Returns:

Status operation

void pi_i2s_channel_conf_init(struct pi_i2s_channel_conf *conf)

Initialize an I2S channel configuration with default values.

This function can be called to get default values for all parameters before setting some of them. The structure containing the configuration must be kept alive until the I2S channel is configured.

Parameters:
  • conf – A pointer to the I2S channel configuration.

PI_INLINE_I2S_LVL_0 int pi_i2s_channel_conf_set(struct pi_device *dev, int channel, struct pi_i2s_channel_conf *conf)

Configure a channel in TDM mode.

In TDM mode, the same interface is time-multiplexed to transmit data for multiple channels, and each channel can have a specific configuration. This function can be used to give the configuration of one channel.

Warning

: On GAP9, i2s module must be reset between reconfigurations of i2s/tdm channels, otherwise the new configuration will be ignored. Asserting reset is included in pi_i2s_close() function. Deasserting reset (and configuring i2s afterwards) is done in pi_i2s_open() function.

Warning

: On GAP9, if in SAI Tx direction there are both slots sourced from L2 (stream_id == -1) and slots sourced from streams (stream_id != -1), then all stream slots must be placed before all L2 slots. Otherwise, the correct order of slots in the frame on SDO pad is not guaranteed.

Parameters:
  • dev – Pointer to the device structure for the driver instance.

  • channel – ID of the slot, from 0 to the number of channels minus 1.

  • conf – A pointer to the I2S channel configuration.

Return values:
  • 0 – Success

  • -1 – Failure

Returns:

Status operation

PI_INLINE_I2S_LVL_0 int pi_i2s_frame_channel_conf_set(struct pi_device *dev, uint32_t frame, int channel, struct pi_i2s_channel_conf *conf)

Configure a channel of a frame in TDM mode.

A frame is a set of channels gathered together so that they can be controlled all together in terms of data transfer. This function can be used to configure a channel which is part of a frame. In TDM mode, the same interface is time-multiplexed to transmit data for multiple channels, and each channel can have a specific configuration. This function can be used to give the configuration of one channel.

Parameters:
  • dev – Pointer to the device structure for the driver instance.

  • frame – A bitfield containing the channels of the part (one bit per channel).

  • channel – ID of the slot, from 0 to the number of channels minus 1.

  • conf – A pointer to the I2S channel configuration.

Return values:
  • 0 – Success

  • -1 – Failure

Returns:

Status operation

int pi_i2s_channel_conf_get(struct pi_device *dev, int channel, struct pi_i2s_channel_conf *conf)

Get the current configuration of a channel in TDM mode.

In TDM mode, the same interface is time-multiplexed to transmit data for multiple channels, and each channel can have a specific configuration. This function can be used to get the current configuration of one channel

Parameters:
  • dev – Pointer to the device structure for the driver instance.

  • channel – ID of the slot, from 0 to the number of channels minus 1.

  • conf – A pointer to the I2S channel configuration.

Return values:
  • 0 – Success

  • -1 – Failure

Returns:

Status operation

int pi_i2s_channel_timestamp_set(struct pi_device *dev, int channel, struct pi_i2s_channel_conf *conf)

Enable the timestamp.

Enable the timestamp feature for the i2s interface.

Parameters:
  • dev – Pointer to the device structure for the driver instance.

  • channel – ID of the channel, from 0 to the number of channels minus 1.

  • conf – A pointer to the I2S channel configuration.

int pi_i2s_slots_enable(struct pi_device *dev, uint32_t slots, int enabled)

Enable or disable slots in TDM mode.

In TDM mode, the same interface is time-multiplexed to transmit data for multiple slots of time. Each slot can send and receive data at the same time in full-duplex mode, and is thus made of one 1 RX channels and 1 TX channel. This function can be called to enable or disable the 2 channels of a slot, for example for muting the channels to reconfigure them. The slot is by default enabled when the channel configuration is initialized. Enabling slots will allow them to received or send data, while disabling them will allow it. These operations are not immediate and can take up to 2 frame periods to be effective. When disabling a slot, the buffers are kept, and data continues from the same buffer position after the slot is reenabled.

Parameters:
  • dev – Pointer to the device structure for the driver instance.

  • slots – Bitfield of the slots to enable or disable, with one bit per slot. Each slot whose bit is set to 1 will be configured.

  • enabled – 1 if the specified slots should be enabled, 0 if they should be disabled.

Return values:
  • 0 – Success

  • -1 – Failure

Returns:

Status operation

int pi_i2s_slots_stop_async(struct pi_device *dev, uint32_t slots, pi_evt_t *event)

Stop slots in TDM mode.

In TDM mode, the same interface is time-multiplexed to transmit data for multiple slots of time. Each slot can send and receive data at the same time in full-duplex mode, and is thus made of one 1 RX channels and 1 TX channel. This function can be called to enable or disable the 2 channels of a slot, for example for muting the channels to reconfigure them. Stopping a slot will first disable it, and will also cancel all pending buffers. If some samples were already present in the current buffer, the buffer is considered finished and its associated event is triggered. The size of the data already sent or received is notified in the buffer event. Since stopping requires waiting for 2 frame periods, this operation can take some time and is asynchronous.

Parameters:
  • dev – Pointer to the device structure for the driver instance.

  • slots – Bitfield of the slots to stop, with one bit per slot. Each slot whose bit is set to 1 will be stopped.

  • event – The event used to notify the end of transfer.

Return values:
  • 0 – Success

  • -1 – Failure

Returns:

Status operation

int pi_i2s_slots_stop(struct pi_device *dev, uint32_t slots)

Stop slots in TDM mode.

In TDM mode, the same interface is time-multiplexed to transmit data for multiple slots of time. Each slot can send and receive data at the same time in full-duplex mode, and is thus made of one 1 RX channels and 1 TX channel. This function can be called to enable or disable the 2 channels of a slot, for example for muting the channels to reconfigure them. Stopping a slot will first disable it, and will also cancel all pending buffers. If some samples were already present in the current buffer, the buffer is considered finished and its associated task is triggered. The size of the data already sent or received is notified in the task. Since stopping requires waiting for 2 frame periods, this operation can take some time and is blocking.

Parameters:
  • dev – Pointer to the device structure for the driver instance.

  • slots – Bitfield of the slots to stop, with one bit per slot. Each slot whose bit is set to 1 will be stopped.

Return values:
  • 0 – Success

  • -1 – Failure

Returns:

Status operation

int pi_i2s_channel_read(struct pi_device *dev, int channel, void **mem_block, size_t *size)

Read data from the RX queue of a channel in TDM mode.

Data received by the I2S interface is stored in the RX queue consisting of two memory blocks preallocated by the user and given to the driver in the configuration. Calling this function will return the next available buffer to the caller, which has to use it before the sampling for this buffer starts again.

The data is read in chunks equal to the size of the memory block.

This will return data for the specified channel and must only be used in TDM mode.

If there is no data in the RX queue the function will block waiting for the next RX memory block to fill in.

Due to hardware constraints, the address of the buffer must be aligned on 4 bytes.

Parameters:
  • dev – Pointer to the device structure for the driver instance.

  • channel – ID of the slot, from 0 to the number of channels minus 1.

  • mem_block – Pointer to the variable storing the address of the RX memory block containing received data.

  • size – Pointer to the variable storing the number of bytes read.

Return values:
  • 0 – Success

  • -1 – Failure

Returns:

Status operation

int pi_i2s_channel_read_async(struct pi_device *dev, int channel, pi_evt_t *event)

Read data asynchronously from the RX queue of a channel in TDM mode.

Data received by the I2S interface is stored in the RX queue consisting of two memory blocks preallocated by the user and given to the driver in the configuration. Calling this function will return the next available buffer to the caller, which has to use it before the sampling for this buffer starts again.

The data is read in chunks equal to the size of the memory block.

This will return data for the specified channel and must only be used in TDM mode.

The specified event will be pushed as soon as data is ready in the RX queue, and the information about the memory block and the size will be available in the event.

Due to hardware constraints, the address of the buffer must be aligned on 4 bytes.

Parameters:
  • dev – Pointer to the device structure for the driver instance.

  • channel – ID of the slot, from 0 to the number of channels minus 1.

  • event – The event used to notify the end of transfer.

Return values:
  • 0 – Success

  • -1 – Failure

Returns:

Status operation

PI_INLINE_I2S_LVL_0 int pi_i2s_frame_read(struct pi_device *dev, uint32_t frame, void **mem_block, size_t *size)

Read data from the RX queue of a frame channel in TDM mode.

Data received by the I2S interface is stored in the RX queue consisting of two memory blocks preallocated by the user and given to the driver in the configuration. Calling this function will return the next available buffer to the caller, which has to use it before the sampling for this buffer starts again.

The data is read in chunks equal to the size of the memory block.

This will return data for the specified channel and must only be used in TDM mode.

If there is no data in the RX queue the function will block waiting for the next RX memory block to fill in.

This function is reading for the whole frame. The returned buffer contains the samples for the whole frame, but the size is the size of one channel.

Due to hardware constraints, the address of the buffer must be aligned on 4 bytes.

Parameters:
  • dev – Pointer to the device structure for the driver instance.

  • frame – A bitfield containing the channels of the part (one bit per channel).

  • mem_block – Pointer to the variable storing the address of the RX memory block containing received data.

  • size – Pointer to the variable storing the number of bytes read.

Return values:
  • 0 – Success

  • -1 – Failure

Returns:

Status operation

PI_INLINE_I2S_LVL_0 int pi_i2s_frame_read_async(struct pi_device *dev, uint32_t frame, pi_evt_t *event)

Read data asynchronously from the RX queue of a frame channel in TDM mode.

Data received by the I2S interface is stored in the RX queue consisting of two memory blocks preallocated by the user and given to the driver in the configuration. Calling this function will return the next available buffer to the caller, which has to use it before the sampling for this buffer starts again.

The data is read in chunks equal to the size of the memory block.

This will return data for the specified channel and must only be used in TDM mode.

The specified event will be pushed as soon as data is ready in the RX queue, and the information about the memory block and the size will be available in the event.

This function is reading for the whole frame. The returned buffer contains the samples for the whole frame, but the size is the size of one channel.

Due to hardware constraints, the address of the buffer must be aligned on 4 bytes.

Parameters:
  • dev – Pointer to the device structure for the driver instance.

  • frame – A bitfield containing the channels of the part (one bit per channel).

  • event – The event used to notify the end of transfer.

Return values:
  • 0 – Success

  • -1 – Failure

Returns:

Status operation

int pi_i2s_read_status(pi_evt_t *event, void **mem_block, size_t *size)

Read the status of an asynchronous read.

After pi_i2s_read_async or pi_i2s_channel_read_async is called to be notified when a read buffer is available, and the notification is received, the output information can be retrieved by calling this function.

Parameters:
  • event – The event used for notification.

  • mem_block – Pointer to the variable storing the address of the RX memory block containing received data.

  • size – Pointer to the variable storing the number of bytes read.

Return values:
  • 0 – Success

  • -1 – Failure

Returns:

Status operation

int pi_i2s_channel_write(struct pi_device *dev, int channel, void *mem_block, size_t size)

Write data to the TX queue of a channel in TDM mode.

Data to be sent by the I2S interface is stored first in the TX queue consisting of memory blocks preallocated by the user with either pingpong buffers or a memory slab allocator.

In pingpong mode, the driver will automatically alternate between 2 buffers and the user code is supposed to call this function to notify the driver that the specified buffer is ready to be sent. This is used by the driver to report when an underrun or an overrun occurs.

In memory slab allocator mode, the user has to allocate buffers from the memory slab allocator and pass them to the driver by calling this function when they are ready to be sent.

This fonction will block until the specified buffer has been transfered.

This will sent data to the specified channel and must only be used in TDM mode.

Parameters:
  • dev – Pointer to the device structure for the driver instance.

  • channel – ID of the slot, from 0 to the number of channels minus 1.

  • mem_block – Pointer to the TX memory block containing data to be sent.

  • size – Number of bytes to write. This value has to be equal or smaller than the size of the memory block.

Return values:
  • 0 – Success

  • -1 – Failure

Returns:

Status operation

int pi_i2s_channel_write_async(struct pi_device *dev, int channel, void *mem_block, size_t size, pi_evt_t *event)

Write data asynchronously to the TX queue of a channel in TDM mode.

Data to be sent by the I2S interface is stored first in the TX queue consisting of memory blocks preallocated by the user with either pingpong buffers or a memory slab allocator.

In pingpong mode, the driver will automatically alternate between 2 buffers and the user code is supposed to call this function to notify the driver that the specified buffer is ready to be sent. This is used by the driver to report when an underrun or an overrun occurs.

In memory slab allocator mode, the user has to allocate buffers from the memory slab allocator and pass them to the driver by calling this function when they are ready to be sent.

This will sent data to the specified channel and must only be used in TDM mode.

The specified event will be pushed as soon as data is has been transfered.

Parameters:
  • dev – Pointer to the device structure for the driver instance.

  • channel – ID of the slot, from 0 to the number of channels minus 1.

  • mem_block – Pointer to the TX memory block containing data to be sent.

  • size – Number of bytes to write. This value has to be equal or smaller than the size of the memory block.

  • event – The event used to notify the end of transfer.

Return values:
  • 0 – Success

  • -1 – Failure

Returns:

Status operation

PI_INLINE_I2S_LVL_0 int pi_i2s_frame_write(struct pi_device *dev, uint32_t frame, void *mem_block, size_t size)

Write data to the TX queue of a frame channel in TDM mode.

Data to be sent by the I2S interface is stored first in the TX queue consisting of memory blocks preallocated by the user with either pingpong buffers or a memory slab allocator.

In pingpong mode, the driver will automatically alternate between 2 buffers and the user code is supposed to call this function to notify the driver that the specified buffer is ready to be sent. This is used by the driver to report when an underrun or an overrun occurs.

In memory slab allocator mode, the user has to allocate buffers from the memory slab allocator and pass them to the driver by calling this function when they are ready to be sent.

This fonction will block until the specified buffer has been transfered.

This function is writing for the whole frame. The buffer must contain the samples for the whole frame, but the size is the size of one channel.

This will sent data to the specified channel and must only be used in TDM mode.

Parameters:
  • dev – Pointer to the device structure for the driver instance.

  • frame – A bitfield containing the channels of the part (one bit per channel).

  • mem_block – Pointer to the TX memory block containing data to be sent.

  • size – Number of bytes to write. This value has to be equal or smaller than the size of the memory block.

Return values:
  • 0 – Success

  • -1 – Failure

Returns:

Status operation

int pi_i2s_frame_write_async(struct pi_device *dev, uint32_t frame, void *mem_block, size_t size, pi_evt_t *event)

Write data asynchronously to the TX queue of a frame channel in TDM mode.

Data to be sent by the I2S interface is stored first in the TX queue consisting of memory blocks preallocated by the user with either pingpong buffers or a memory slab allocator.

In pingpong mode, the driver will automatically alternate between 2 buffers and the user code is supposed to call this function to notify the driver that the specified buffer is ready to be sent. This is used by the driver to report when an underrun or an overrun occurs.

In memory slab allocator mode, the user has to allocate buffers from the memory slab allocator and pass them to the driver by calling this function when they are ready to be sent.

This will sent data to the specified channel and must only be used in TDM mode.

This function is writing for the whole frame. The buffer must contain the samples for the whole frame, but the size is the size of one channel.

The specified event will be pushed as soon as data is has been transfered.

Parameters:
  • dev – Pointer to the device structure for the driver instance.

  • frame – A bitfield containing the channels of the part (one bit per channel).

  • mem_block – Pointer to the TX memory block containing data to be sent.

  • size – Number of bytes to write. This value has to be equal or smaller than the size of the memory block.

  • event – The event used to notify the end of transfer.

Return values:
  • 0 – Success

  • -1 – Failure

Returns:

Status operation

int pi_i2s_write_status(pi_evt_t *event)

Read the status of an asynchronous write.

After pi_i2s_write_async or pi_i2s_channel_write_async and the notification for the end of transfer is received, return value can be retrieved by calling this function.

Parameters:
  • event – The event used for notification.

Return values:
  • 0 – Success

  • -1 – Failure

Returns:

Status operation

Variables

pi_device_api_t i2s_api
struct pi_i2s_conf
#include <i2s.h>

Interface configuration options.

Public Members

pi_i2s_mode_t mode

SAI interface mode: I2S or PDM. I2S mode further supports 2 submodes depending on ‘channels’ and ‘ws_type’ field:

  • ws_type=1 and channels=2:standard 2-channel I2S

  • otherwise, a TDM mode with number of channels from 1 to 16

uint32_t frame_clk_freq

Frame clock (WS) frequency, this is sampling rate.

uint8_t slot_width

Bit width of a TDM slot (not to be confused with word_size).

int8_t mem_word_size

Number of bits representing one data word in memory. If it is -1, this is equal to word_size.

uint8_t ws_delay

Sets the distance (in bits) in i2s cycles from the WS rising edge to the first bit of the frame

uint8_t channels

Number of words per frame.

uint8_t itf

I2S device ID.

pi_i2s_opt_t options

Configuration options as defined by PI_I2S_OPT_* constants.

uint8_t pdm_direction

Only 2b’ LSB are used, for choosing the mode of the pin SDI and the pin SDO:

  • SDI - b0: 0-TX, 1-RX

  • SDO - b1: 0-TX, 1-RX In GAP9, if both are configured as 0, the ouput data will be on the SDO. GAP9 uses term pdm_polarity, which is still kept at HAL level for consistency with the HW registers.

uint8_t pdm_diff

In PDM Output mode only: set differential mode on pairs,

  • bit0: (SDI,WS)

  • bit1: (SDO,SCK)

uint32_t ref_clk_freq

Configure the ref clk fast value.

uint8_t ts_evt_id

UDMA Config Event ID for generating the timestamp

uint8_t ws_type

Specifies the form of the WS: 0: WS pulse is one bit wide, 1 during first slot, first bit 1: WS pulse is one slot wide, 1 during first slot) 2: WS pulse is half-frame wide, 1 during first half

struct pi_i2s_channel_conf
#include <i2s.h>

Interface channel configuration options. This configuration has to be used when configuring a channel in TDM mode. This can also be used to configure channels when they are part of a frame. Be careful in that case that some fields are not specific restrictions in this case.

Public Members

size_t block_size

Size of one RX/TX memory block(buffer) in bytes. On some chips, this size may have to be set under a maximum size, check the chip-specific section. In frame-based mode, this field should be the same for all channels.

pi_mem_slab_t *mem_slab

memory slab to store RX/TX data. In frame-based mode, this field should be the same for all channels.

void *pingpong_buffers[2]

Pair of buffers used in double-bufferin mode to capture the incoming samples. In frame-based mode, this field should be the same for all channels.

pi_i2s_fmt_t format

Data stream format as defined by PI_I2S_FMT_* constants.

uint8_t word_size

Number of bits representing one data word.

int8_t mem_word_size

Number of bits representing one data word in memory. If it is -1, this is equal to word_size. In frame-based mode, this field should be the same for all channels.

pi_i2s_opt_t options

Configuration options as defined by PI_I2S_OPT_* constants.

int8_t stream_id

If different from -1, the slot will be connected to the SFU/FFC/AES block with via stream channel specified by this id:

  • 0-15: SFU

  • 16-17: AES

  • 18-21: FFC If stream_id is -1 (default), the driver will allocate a linear uDMA channel and assign it to this slot to be used to send data to L2 memory (for Rx slots) or get data from L2 memory (for Tx slots).

WARNING: On GAP9, if in SAI Tx direction there are both slots sourced from L2 (stream_id == -1) and slots sourced from streams (stream_id != -1), then all stream slots must be placed before all L2 slots. Otherwise, the correct order of slots in the frame on SDO pad is not guaranteed.

uint8_t ts_evt_id

UDMA Config Event ID for generating the timestamp. In frame-based mode, this field should be the same for all channels.

uint8_t slot_enable

Specifies if the corresponding slot must be enabled or not. It is by default set to 1.