/* * Copyright (c) 2018, Intel Corporation * * Author: Seppo Ingalsuo * Sathish Kuttan * * SPDX-License-Identifier: Apache-2.0 */ /** * @file * @brief Public API header file for Digital Microphones * * This file contains the Digital Microphone APIs */ #ifndef ZEPHYR_INCLUDE_AUDIO_DMIC_H_ #define ZEPHYR_INCLUDE_AUDIO_DMIC_H_ /** * @defgroup audio_interface Audio * @{ * @} */ /** * @brief Abstraction for digital microphones * * @defgroup audio_dmic_interface Digital Microphone Interface * @since 1.13 * @version 0.1.0 * @ingroup audio_interface * @{ */ #include #include #ifdef __cplusplus extern "C" { #endif /** * DMIC driver states */ enum dmic_state { DMIC_STATE_UNINIT, /**< Uninitialized */ DMIC_STATE_INITIALIZED, /**< Initialized */ DMIC_STATE_CONFIGURED, /**< Configured */ DMIC_STATE_ACTIVE, /**< Active */ DMIC_STATE_PAUSED, /**< Paused */ DMIC_STATE_ERROR, /**< Error */ }; /** * DMIC driver trigger commands */ enum dmic_trigger { DMIC_TRIGGER_STOP, /**< Stop stream */ DMIC_TRIGGER_START, /**< Start stream */ DMIC_TRIGGER_PAUSE, /**< Pause stream */ DMIC_TRIGGER_RELEASE, /**< Release paused stream */ DMIC_TRIGGER_RESET, /**< Reset stream */ }; /** * PDM Channels LEFT / RIGHT */ enum pdm_lr { PDM_CHAN_LEFT, /**< Left channel */ PDM_CHAN_RIGHT, /**< Right channel */ }; /** * PDM Input/Output signal configuration */ struct pdm_io_cfg { /** * @name Parameters common to all PDM controllers *@{ */ /** Minimum clock frequency supported by the mic */ uint32_t min_pdm_clk_freq; /** Maximum clock frequency supported by the mic */ uint32_t max_pdm_clk_freq; /** Minimum duty cycle in % supported by the mic */ uint8_t min_pdm_clk_dc; /** Maximum duty cycle in % supported by the mic */ uint8_t max_pdm_clk_dc; /** * @} */ /** * @name Parameters unique to each PDM controller * @{ */ /** Bit mask to optionally invert PDM clock */ uint8_t pdm_clk_pol; /** Bit mask to optionally invert mic data */ uint8_t pdm_data_pol; /** Collection of clock skew values for each PDM port */ uint32_t pdm_clk_skew; /** * @} */ }; /** * Configuration of the PCM streams to be output by the PDM hardware * * @note if either \ref pcm_rate or \ref pcm_width is set to 0 for a stream, * the stream would be disabled */ struct pcm_stream_cfg { /** PCM sample rate of stream */ uint32_t pcm_rate; /** PCM sample width of stream */ uint8_t pcm_width; /** PCM sample block size per transfer */ uint16_t block_size; /** SLAB for DMIC driver to allocate buffers for stream */ struct k_mem_slab *mem_slab; }; /** * Mapping/ordering of the PDM channels to logical PCM output channel * * Since each controller can have 2 audio channels (stereo), * there can be a total of 8x2=16 channels. The actual number of channels * shall be described in \ref act_num_chan. * * If 2 streams are enabled, the channel order will be the same for * both streams. * * Each channel is described as a 4-bit number, the least significant * bit indicates LEFT/RIGHT selection of the PDM controller. * * The most significant 3 bits indicate the PDM controller number: * - bits 0-3 are for channel 0, bit 0 indicates LEFT or RIGHT * - bits 4-7 are for channel 1, bit 4 indicates LEFT or RIGHT * and so on. * * CONSTRAINT: The LEFT and RIGHT channels of EACH PDM controller needs * to be adjacent to each other. */ struct pdm_chan_cfg { /** * @name Requested channel map * @{ */ uint32_t req_chan_map_lo; /**< Channels 0 to 7 */ uint32_t req_chan_map_hi; /**< Channels 8 to 15 */ /** @} */ /** * @name Actual channel map that the driver could configure * @{ */ uint32_t act_chan_map_lo; /**< Channels 0 to 7 */ uint32_t act_chan_map_hi; /**< Channels 8 to 15 */ /** @} */ /** Requested number of channels */ uint8_t req_num_chan; /** Actual number of channels that the driver could configure */ uint8_t act_num_chan; /** Requested number of streams for each channel */ uint8_t req_num_streams; /** Actual number of streams that the driver could configure */ uint8_t act_num_streams; }; /** * Input configuration structure for the DMIC configuration API */ struct dmic_cfg { struct pdm_io_cfg io; /** * Array of pcm_stream_cfg for application to provide * configuration for each stream */ struct pcm_stream_cfg *streams; struct pdm_chan_cfg channel; }; /** * Function pointers for the DMIC driver operations */ struct _dmic_ops { int (*configure)(const struct device *dev, struct dmic_cfg *config); int (*trigger)(const struct device *dev, enum dmic_trigger cmd); int (*read)(const struct device *dev, uint8_t stream, void **buffer, size_t *size, int32_t timeout); }; /** * Build the channel map to populate struct pdm_chan_cfg * * Returns the map of PDM controller and LEFT/RIGHT channel shifted to * the bit position corresponding to the input logical channel value * * @param channel The logical channel number * @param pdm The PDM hardware controller number * @param lr LEFT/RIGHT channel within the chosen PDM hardware controller * * @return Bit-map containing the PDM and L/R channel information */ static inline uint32_t dmic_build_channel_map(uint8_t channel, uint8_t pdm, enum pdm_lr lr) { return ((((pdm & BIT_MASK(3)) << 1) | lr) << ((channel & BIT_MASK(3)) * 4U)); } /** * Helper function to parse the channel map in pdm_chan_cfg * * Returns the PDM controller and LEFT/RIGHT channel corresponding to * the channel map and the logical channel provided as input * * @param channel_map_lo Lower order/significant bits of the channel map * @param channel_map_hi Higher order/significant bits of the channel map * @param channel The logical channel number * @param pdm Pointer to the PDM hardware controller number * @param lr Pointer to the LEFT/RIGHT channel within the PDM controller */ static inline void dmic_parse_channel_map(uint32_t channel_map_lo, uint32_t channel_map_hi, uint8_t channel, uint8_t *pdm, enum pdm_lr *lr) { uint32_t channel_map; channel_map = (channel < 8) ? channel_map_lo : channel_map_hi; channel_map >>= ((channel & BIT_MASK(3)) * 4U); *pdm = (channel_map >> 1) & BIT_MASK(3); *lr = (enum pdm_lr) (channel_map & BIT(0)); } /** * Build a bit map of clock skew values for each PDM channel * * Returns the bit-map of clock skew value shifted to the bit position * corresponding to the input PDM controller value * * @param pdm The PDM hardware controller number * @param skew The skew to apply for the clock output from the PDM controller * * @return Bit-map containing the clock skew information */ static inline uint32_t dmic_build_clk_skew_map(uint8_t pdm, uint8_t skew) { return ((skew & BIT_MASK(4)) << ((pdm & BIT_MASK(3)) * 4U)); } /** * Configure the DMIC driver and controller(s) * * Configures the DMIC driver device according to the number of channels, * channel mapping, PDM I/O configuration, PCM stream configuration, etc. * * @param dev Pointer to the device structure for DMIC driver instance * @param cfg Pointer to the structure containing the DMIC configuration * * @return 0 on success, a negative error code on failure */ static inline int dmic_configure(const struct device *dev, struct dmic_cfg *cfg) { const struct _dmic_ops *api = (const struct _dmic_ops *)dev->api; return api->configure(dev, cfg); } /** * Send a command to the DMIC driver * * Sends a command to the driver to perform a specific action * * @param dev Pointer to the device structure for DMIC driver instance * @param cmd The command to be sent to the driver instance * * @return 0 on success, a negative error code on failure */ static inline int dmic_trigger(const struct device *dev, enum dmic_trigger cmd) { const struct _dmic_ops *api = (const struct _dmic_ops *)dev->api; return api->trigger(dev, cmd); } /** * Read received decimated PCM data stream * * Optionally waits for audio to be received and provides the received * audio buffer from the requested stream * * @param dev Pointer to the device structure for DMIC driver instance * @param stream Stream identifier * @param buffer Pointer to the received buffer address * @param size Pointer to the received buffer size * @param timeout Timeout in milliseconds to wait in case audio is not yet * received, or @ref SYS_FOREVER_MS * * @return 0 on success, a negative error code on failure */ static inline int dmic_read(const struct device *dev, uint8_t stream, void **buffer, size_t *size, int32_t timeout) { const struct _dmic_ops *api = (const struct _dmic_ops *)dev->api; return api->read(dev, stream, buffer, size, timeout); } #ifdef __cplusplus } #endif /** * @} */ #endif /* ZEPHYR_INCLUDE_AUDIO_DMIC_H_ */