Piotr Mienkowski | cbff174 | 2017-07-10 23:27:10 +0200 | [diff] [blame^] | 1 | /* |
| 2 | * Copyright (c) 2017 Piotr Mienkowski |
| 3 | * |
| 4 | * SPDX-License-Identifier: Apache-2.0 |
| 5 | */ |
| 6 | |
| 7 | /** |
| 8 | * @file |
| 9 | * @brief Public APIs for the I2S (Inter-IC Sound) bus drivers. |
| 10 | */ |
| 11 | |
| 12 | #ifndef __I2S_H__ |
| 13 | #define __I2S_H__ |
| 14 | |
| 15 | /** |
| 16 | * @defgroup i2s_interface I2S Interface |
| 17 | * @ingroup io_interfaces |
| 18 | * @brief I2S (Inter-IC Sound) Interface |
| 19 | * |
| 20 | * The I2S API provides support for the standard I2S interface standard as well |
| 21 | * as common non-standard extensions such as PCM Short/Long Frame Sync, |
| 22 | * Left/Right Justified Data Format. |
| 23 | * @{ |
| 24 | */ |
| 25 | |
| 26 | #include <zephyr/types.h> |
| 27 | #include <device.h> |
| 28 | |
| 29 | #ifdef __cplusplus |
| 30 | extern "C" { |
| 31 | #endif |
| 32 | |
| 33 | /* |
| 34 | * The following #defines are used to configure the I2S controller. |
| 35 | */ |
| 36 | |
| 37 | |
| 38 | typedef u8_t i2s_fmt_t; |
| 39 | |
| 40 | /** Data Format bit field position. */ |
| 41 | #define I2S_FMT_DATA_FORMAT_SHIFT 0 |
| 42 | /** Data Format bit field mask. */ |
| 43 | #define I2S_FMT_DATA_FORMAT_MASK (0x7 << I2S_FMT_DATA_FORMAT_SHIFT) |
| 44 | |
| 45 | /** @brief Standard I2S Data Format. |
| 46 | * |
| 47 | * Serial data is transmitted in two’s complement with the MSB first. Both |
| 48 | * Word Select (WS) and Serial Data (SD) signals are sampled on the rising edge |
| 49 | * of the clock signal (SCK). The MSB is always sent one clock period after the |
| 50 | * WS changes. Left channel data are sent first indicated by WS = 0, followed |
| 51 | * by right channel data indicated by WS = 1. |
| 52 | * |
| 53 | * -. .-. .-. .-. .-. .-. .-. .-. .-. .-. .-. .-. .-. .-. .-. .-. .-. .-. |
| 54 | * SCK '-' '-' '-' '-' '-' '-' '-' '-' '-' '-' '-' '-' '-' '-' '-' '-' '-' ' |
| 55 | * -. .-------------------------------. |
| 56 | * WS '-------------------------------' '---- |
| 57 | * -.---.---.---.---.---.---.---.---.---.---.---.---.---.---.---.---.---. |
| 58 | * SD | |MSB| |...| |LSB| x |...| x |MSB| |...| |LSB| x |...| x | |
| 59 | * -'---'---'---'---'---'---'---'---'---'---'---'---'---'---'---'---'---' |
| 60 | * | Left channel | Right channel | |
| 61 | */ |
| 62 | #define I2S_FMT_DATA_FORMAT_I2S (0 << I2S_FMT_DATA_FORMAT_SHIFT) |
| 63 | |
| 64 | /** @brief PCM Short Frame Sync Data Format. |
| 65 | * |
| 66 | * Serial data is transmitted in two’s complement with the MSB first. Both |
| 67 | * Word Select (WS) and Serial Data (SD) signals are sampled on the falling edge |
| 68 | * of the clock signal (SCK). The falling edge of the frame sync signal (WS) |
| 69 | * indicates the start of the PCM word. The frame sync is one clock cycle long. |
| 70 | * An arbitrary number of data words can be sent in one frame. |
| 71 | * |
| 72 | * .-. .-. .-. .-. .-. .-. .-. .-. .-. .-. .-. .-. .-. .-. .-. .-. .-. |
| 73 | * SCK -' '-' '-' '-' '-' '-' '-' '-' '-' '-' '-' '-' '-' '-' '-' '-' '-' '- |
| 74 | * .---. .---. |
| 75 | * WS -' '- -' '- |
| 76 | * -.---.---.---.---.---.---.---.---.---.---.---.---.---.---.---.---.--- |
| 77 | * SD | |MSB| |...| |LSB|MSB| |...| |LSB|MSB| |...| |LSB| |
| 78 | * -'---'---'---'---'---'---'---'---'---'---'---'---'---'---'---'---'--- |
| 79 | * | Word 1 | Word 2 | Word 3 | Word n | |
| 80 | */ |
| 81 | #define I2S_FMT_DATA_FORMAT_PCM_SHORT (1 << I2S_FMT_DATA_FORMAT_SHIFT) |
| 82 | |
| 83 | /** @brief PCM Long Frame Sync Data Format. |
| 84 | * |
| 85 | * Serial data is transmitted in two’s complement with the MSB first. Both |
| 86 | * Word Select (WS) and Serial Data (SD) signals are sampled on the falling edge |
| 87 | * of the clock signal (SCK). The rising edge of the frame sync signal (WS) |
| 88 | * indicates the start of the PCM word. The frame sync has an arbitrary length, |
| 89 | * however it has to fall before the start of the next frame. An arbitrary |
| 90 | * number of data words can be sent in one frame. |
| 91 | * |
| 92 | * .-. .-. .-. .-. .-. .-. .-. .-. .-. .-. .-. .-. .-. .-. .-. .-. .-. |
| 93 | * SCK -' '-' '-' '-' '-' '-' '-' '-' '-' '-' '-' '-' '-' '-' '-' '-' '-' '- |
| 94 | * .--- ---. ---. ---. .--- |
| 95 | * WS -' '- '- '- -' |
| 96 | * -.---.---.---.---.---.---.---.---.---.---.---.---.---.---.---.---.--- |
| 97 | * SD | |MSB| |...| |LSB|MSB| |...| |LSB|MSB| |...| |LSB| |
| 98 | * -'---'---'---'---'---'---'---'---'---'---'---'---'---'---'---'---'--- |
| 99 | * | Word 1 | Word 2 | Word 3 | Word n | |
| 100 | */ |
| 101 | #define I2S_FMT_DATA_FORMAT_PCM_LONG (2 << I2S_FMT_DATA_FORMAT_SHIFT) |
| 102 | |
| 103 | /** |
| 104 | * @brief Left Justified Data Format. |
| 105 | * |
| 106 | * Serial data is transmitted in two’s complement with the MSB first. Both |
| 107 | * Word Select (WS) and Serial Data (SD) signals are sampled on the rising edge |
| 108 | * of the clock signal (SCK). The bits within the data word are left justified |
| 109 | * such that the MSB is always sent in the clock period following the WS |
| 110 | * transition. Left channel data are sent first indicated by WS = 1, followed |
| 111 | * by right channel data indicated by WS = 0. |
| 112 | * |
| 113 | * .-. .-. .-. .-. .-. .-. .-. .-. .-. .-. .-. .-. .-. .-. .-. .-. .-. |
| 114 | * SCK -' '-' '-' '-' '-' '-' '-' '-' '-' '-' '-' '-' '-' '-' '-' '-' '-' '- |
| 115 | * .-------------------------------. .- |
| 116 | * WS ---' '-------------------------------' |
| 117 | * ---.---.---.---.---.---.---.---.---.---.---.---.---.---.---.---.---.- |
| 118 | * SD |MSB| |...| |LSB| x |...| x |MSB| |...| |LSB| x |...| x | |
| 119 | * ---'---'---'---'---'---'---'---'---'---'---'---'---'---'---'---'---'- |
| 120 | * | Left channel | Right channel | |
| 121 | */ |
| 122 | #define I2S_FMT_DATA_FORMAT_LEFT_JUSTIFIED (3 << I2S_FMT_DATA_FORMAT_SHIFT) |
| 123 | |
| 124 | /** |
| 125 | * @brief Right Justified Data Format. |
| 126 | * |
| 127 | * Serial data is transmitted in two’s complement with the MSB first. Both |
| 128 | * Word Select (WS) and Serial Data (SD) signals are sampled on the rising edge |
| 129 | * of the clock signal (SCK). The bits within the data word are right justified |
| 130 | * such that the LSB is always sent in the clock period preceding the WS |
| 131 | * transition. Left channel data are sent first indicated by WS = 1, followed |
| 132 | * by right channel data indicated by WS = 0. |
| 133 | * |
| 134 | * .-. .-. .-. .-. .-. .-. .-. .-. .-. .-. .-. .-. .-. .-. .-. .-. .-. |
| 135 | * SCK -' '-' '-' '-' '-' '-' '-' '-' '-' '-' '-' '-' '-' '-' '-' '-' '-' '- |
| 136 | * .-------------------------------. .- |
| 137 | * WS ---' '-------------------------------' |
| 138 | * ---.---.---.---.---.---.---.---.---.---.---.---.---.---.---.---.---.- |
| 139 | * SD | x |...| x |MSB| |...| |LSB| x |...| x |MSB| |...| |LSB| |
| 140 | * ---'---'---'---'---'---'---'---'---'---'---'---'---'---'---'---'---'- |
| 141 | * | Left channel | Right channel | |
| 142 | */ |
| 143 | #define I2S_FMT_DATA_FORMAT_RIGHT_JUSTIFIED (4 << I2S_FMT_DATA_FORMAT_SHIFT) |
| 144 | |
| 145 | /** Send MSB first */ |
| 146 | #define I2S_FMT_DATA_ORDER_MSB (0 << 3) |
| 147 | /** Send LSB first */ |
| 148 | #define I2S_FMT_DATA_ORDER_LSB (1 << 3) |
| 149 | /** Invert bit ordering, send LSB first */ |
| 150 | #define I2S_FMT_DATA_ORDER_INV I2S_FMT_DATA_ORDER_LSB |
| 151 | /** Invert bit clock */ |
| 152 | #define I2S_FMT_BIT_CLK_INV (1 << 4) |
| 153 | /** Invert frame clock */ |
| 154 | #define I2S_FMT_FRAME_CLK_INV (1 << 5) |
| 155 | |
| 156 | |
| 157 | typedef u8_t i2s_opt_t; |
| 158 | |
| 159 | /** Run bit clock continuously */ |
| 160 | #define I2S_OPT_BIT_CLK_CONT (0 << 0) |
| 161 | /** Run bit clock when sending data only */ |
| 162 | #define I2S_OPT_BIT_CLK_GATED (1 << 0) |
| 163 | /** I2S driver is bit clock master */ |
| 164 | #define I2S_OPT_BIT_CLK_MASTER (0 << 1) |
| 165 | /** I2S driver is bit clock slave */ |
| 166 | #define I2S_OPT_BIT_CLK_SLAVE (1 << 1) |
| 167 | /** I2S driver is frame clock master */ |
| 168 | #define I2S_OPT_FRAME_CLK_MASTER (0 << 2) |
| 169 | /** I2S driver is frame clock slave */ |
| 170 | #define I2S_OPT_FRAME_CLK_SLAVE (1 << 2) |
| 171 | /** @brief Loop back mode. |
| 172 | * |
| 173 | * In loop back mode RX input will be connected internally to TX output. |
| 174 | * This is used primarily for testing. |
| 175 | */ |
| 176 | #define I2S_OPT_LOOPBACK (1 << 7) |
| 177 | |
| 178 | |
| 179 | enum i2s_dir { |
| 180 | /** Receive data */ |
| 181 | I2S_DIR_RX, |
| 182 | /** Transmit data */ |
| 183 | I2S_DIR_TX, |
| 184 | }; |
| 185 | |
| 186 | /** Interface state */ |
| 187 | enum i2s_state { |
| 188 | /** @brief The interface is not ready. |
| 189 | * |
| 190 | * The interface was initialized but is not yet ready to receive / |
| 191 | * transmit data. Call i2s_configure() to configure interface and change |
| 192 | * its state to READY. |
| 193 | */ |
| 194 | I2S_STATE_NOT_READY, |
| 195 | /** The interface is ready to receive / transmit data. */ |
| 196 | I2S_STATE_READY, |
| 197 | /** The interface is receiving / transmitting data. */ |
| 198 | I2S_STATE_RUNNING, |
| 199 | /** The interface is draining its transmit queue. */ |
| 200 | I2S_STATE_STOPPING, |
| 201 | /** TX buffer underrun or RX buffer overrun has occurred. */ |
| 202 | I2S_STATE_ERROR, |
| 203 | }; |
| 204 | |
| 205 | /** Trigger command */ |
| 206 | enum i2s_trigger_cmd { |
| 207 | /** @brief Start the transmission / reception of data. |
| 208 | * |
| 209 | * If I2S_DIR_TX is set some data has to be queued for transmission by |
| 210 | * the i2s_write() function. This trigger can be used in READY state |
| 211 | * only and changes the interface state to RUNNING. |
| 212 | */ |
| 213 | I2S_TRIGGER_START, |
| 214 | /** @brief Stop the transmission / reception of data. |
| 215 | * |
| 216 | * Stop the transmission / reception of data at the end of the current |
| 217 | * memory block. This trigger can be used in RUNNING state only and at |
| 218 | * first changes the interface state to STOPPING. When the current TX / |
| 219 | * RX block is transmitted / received the state is changed to READY. |
| 220 | * Subsequent START trigger will resume transmission / reception where |
| 221 | * it stopped. |
| 222 | */ |
| 223 | I2S_TRIGGER_STOP, |
| 224 | /** @brief Empty the transmit queue. |
| 225 | * |
| 226 | * Send all data in the transmit queue and stop the transmission. |
| 227 | * If the trigger is applied to the RX queue it has the same effect as |
| 228 | * I2S_TRIGGER_STOP. This trigger can be used in RUNNING state only and |
| 229 | * at first changes the interface state to STOPPING. When all TX blocks |
| 230 | * are transmitted the state is changed to READY. |
| 231 | */ |
| 232 | I2S_TRIGGER_DRAIN, |
| 233 | /** @brief Discard the transmit / receive queue. |
| 234 | * |
| 235 | * Stop the transmission / reception immediately and discard the |
| 236 | * contents of the respective queue. This trigger can be used in any |
| 237 | * state other than NOT_READY and changes the interface state to READY. |
| 238 | */ |
| 239 | I2S_TRIGGER_DROP, |
| 240 | /** @brief Prepare the queues after underrun/overrun error has occurred. |
| 241 | * |
| 242 | * This trigger can be used in ERROR state only and changes the |
| 243 | * interface state to READY. |
| 244 | */ |
| 245 | I2S_TRIGGER_PREPARE, |
| 246 | }; |
| 247 | |
| 248 | /** @struct i2s_config |
| 249 | * @brief Interface configuration options. |
| 250 | * |
| 251 | * Memory slab pointed to by the mem_slab field has to be defined and |
| 252 | * initialized by the user. For I2S driver to function correctly number of |
| 253 | * memory blocks in a slab has to be at least 2 per queue. Size of the memory |
| 254 | * block should be multiple of frame_size where frame_size = (channels * |
| 255 | * word_size_bytes). As an example 16 bit word will occupy 2 bytes, 24 or 32 |
| 256 | * bit word will occupy 4 bytes. |
| 257 | * |
| 258 | * Please check Zephyr Kernel Primer for more information on memory slabs. |
| 259 | * |
| 260 | * @remark When I2S data format is selected parameter channels is ignored, |
| 261 | * number of words in a frame is always 2. |
| 262 | * |
| 263 | * @param word_size Number of bits representing one data word. |
| 264 | * @param channels Number of words per frame. |
| 265 | * @param format Data stream format as defined by I2S_FMT_* constants. |
| 266 | * @param options Configuration options as defined by I2S_OPT_* constants. |
| 267 | * @param frame_clk_freq Frame clock (WS) frequency, this is sampling rate. |
| 268 | * @param mem_slab memory slab to store RX/TX data. |
| 269 | * @param block_size Size of one RX/TX memory block (buffer) in bytes. |
| 270 | * @param timeout Read/Write timeout. Number of milliseconds to wait in case TX |
| 271 | * queue is full, RX queue is empty or one of the special values |
| 272 | * K_NO_WAIT, K_FOREVER. |
| 273 | */ |
| 274 | struct i2s_config { |
| 275 | u8_t word_size; |
| 276 | u8_t channels; |
| 277 | i2s_fmt_t format; |
| 278 | i2s_opt_t options; |
| 279 | u32_t frame_clk_freq; |
| 280 | struct k_mem_slab *mem_slab; |
| 281 | size_t block_size; |
| 282 | s32_t timeout; |
| 283 | }; |
| 284 | |
| 285 | /** |
| 286 | * @cond INTERNAL_HIDDEN |
| 287 | * |
| 288 | * For internal use only, skip these in public documentation. |
| 289 | */ |
| 290 | struct i2s_driver_api { |
| 291 | int (*configure)(struct device *dev, enum i2s_dir dir, |
| 292 | struct i2s_config *cfg); |
| 293 | int (*read)(struct device *dev, void **mem_block, size_t *size); |
| 294 | int (*write)(struct device *dev, void *mem_block, size_t size); |
| 295 | int (*trigger)(struct device *dev, enum i2s_dir dir, |
| 296 | enum i2s_trigger_cmd cmd); |
| 297 | }; |
| 298 | /** |
| 299 | * @endcond |
| 300 | */ |
| 301 | |
| 302 | /** |
| 303 | * @brief Configure operation of a host I2S controller. |
| 304 | * |
| 305 | * The dir parameter specifies if Transmit (TX) or Receive (RX) direction |
| 306 | * will be configured by data provided via cfg parameter. |
| 307 | * |
| 308 | * The function can be called in NOT_READY or READY state only. If executed |
| 309 | * successfully the function will change the interface state to READY. |
| 310 | * |
| 311 | * If the function is called with the parameter cfg->frame_clk_freq set to 0 |
| 312 | * the interface state will be changed to NOT_READY. |
| 313 | * |
| 314 | * @param dev Pointer to the device structure for the driver instance. |
| 315 | * @param dir Stream direction: RX or TX as defined by I2S_DIR_* |
| 316 | * @param cfg Pointer to the structure containing configuration parameters. |
| 317 | * |
| 318 | * @retval 0 If successful. |
| 319 | * @retval -EINVAL Invalid argument. |
| 320 | */ |
| 321 | static inline int i2s_configure(struct device *dev, enum i2s_dir dir, |
| 322 | struct i2s_config *cfg) |
| 323 | { |
| 324 | const struct i2s_driver_api *api = dev->driver_api; |
| 325 | |
| 326 | return api->configure(dev, dir, cfg); |
| 327 | } |
| 328 | |
| 329 | /** |
| 330 | * @brief Read data from the RX queue. |
| 331 | * |
| 332 | * Data received by the I2S interface is stored in the RX queue consisting of |
| 333 | * memory blocks preallocated by this function from rx_mem_slab (as defined by |
| 334 | * i2s_configure). Ownership of the RX memory block is passed on to the user |
| 335 | * application which has to release it. |
| 336 | * |
| 337 | * The data is read in chunks equal to the size of the memory block. If the |
| 338 | * interface is in READY state the number of bytes read can be smaller. |
| 339 | * |
| 340 | * If there is no data in the RX queue the function will block waiting for |
| 341 | * the next RX memory block to fill in. This operation can timeout as defined |
| 342 | * by i2s_configure. If the timeout value is set to K_NO_WAIT the function |
| 343 | * is non-blocking. |
| 344 | * |
| 345 | * Reading from the RX queue is possible in any state other than NOT_READY. |
| 346 | * If the interface is in the ERROR state it is still possible to read all the |
| 347 | * valid data stored in RX queue. Afterwards the function will return -EIO |
| 348 | * error. |
| 349 | * |
| 350 | * @param dev Pointer to the device structure for the driver instance. |
| 351 | * @param mem_block Pointer to the RX memory block containing received data. |
| 352 | * @param size Pointer to the variable storing the number of bytes read. |
| 353 | * |
| 354 | * @retval 0 If successful. |
| 355 | * @retval -EIO The interface is in NOT_READY or ERROR state and there are no |
| 356 | * more data blocks in the RX queue. |
| 357 | * @retval -EBUSY Returned without waiting. |
| 358 | * @retval -EAGAIN Waiting period timed out. |
| 359 | */ |
| 360 | static inline int i2s_read(struct device *dev, void **mem_block, size_t *size) |
| 361 | { |
| 362 | const struct i2s_driver_api *api = dev->driver_api; |
| 363 | |
| 364 | return api->read(dev, mem_block, size); |
| 365 | } |
| 366 | |
| 367 | /** |
| 368 | * @brief Write data to the TX queue. |
| 369 | * |
| 370 | * Data to be sent by the I2S interface is stored first in the TX queue. TX |
| 371 | * queue consists of memory blocks preallocated by the user from tx_mem_slab |
| 372 | * (as defined by i2s_configure). This function takes ownership of the memory |
| 373 | * block and will release it when all data are transmitted. |
| 374 | * |
| 375 | * If there are no free slots in the TX queue the function will block waiting |
| 376 | * for the next TX memory block to be send and removed from the queue. This |
| 377 | * operation can timeout as defined by i2s_configure. If the timeout value is |
| 378 | * set to K_NO_WAIT the function is non-blocking. |
| 379 | * |
| 380 | * Writing to the TX queue is only possible if the interface is in READY or |
| 381 | * RUNNING state. |
| 382 | * |
| 383 | * @param dev Pointer to the device structure for the driver instance. |
| 384 | * @param mem_block Pointer to the TX memory block containing data to be sent. |
| 385 | * @param size Number of bytes to write. This value has to be equal or smaller |
| 386 | * than the size of the memory block. |
| 387 | * |
| 388 | * @retval 0 If successful. |
| 389 | * @retval -EIO The interface is not in READY or RUNNING state. |
| 390 | * @retval -EBUSY Returned without waiting. |
| 391 | * @retval -EAGAIN Waiting period timed out. |
| 392 | */ |
| 393 | static inline int i2s_write(struct device *dev, void *mem_block, size_t size) |
| 394 | { |
| 395 | const struct i2s_driver_api *api = dev->driver_api; |
| 396 | |
| 397 | return api->write(dev, mem_block, size); |
| 398 | } |
| 399 | |
| 400 | /** |
| 401 | * @brief Send a trigger command. |
| 402 | * |
| 403 | * @param dev Pointer to the device structure for the driver instance. |
| 404 | * @param dir Stream direction: RX or TX. |
| 405 | * @param cmd Trigger command. |
| 406 | * |
| 407 | * @retval 0 If successful. |
| 408 | * @retval -EINVAL Invalid argument. |
| 409 | * @retval -EIO The trigger cannot be executed in the current state or a DMA |
| 410 | * channel cannot be allocated. |
| 411 | * @retval -ENOMEM RX/TX memory block not available. |
| 412 | */ |
| 413 | static inline int i2s_trigger(struct device *dev, enum i2s_dir dir, |
| 414 | enum i2s_trigger_cmd cmd) |
| 415 | { |
| 416 | const struct i2s_driver_api *api = dev->driver_api; |
| 417 | |
| 418 | return api->trigger(dev, dir, cmd); |
| 419 | } |
| 420 | |
| 421 | #ifdef __cplusplus |
| 422 | } |
| 423 | #endif |
| 424 | |
| 425 | /** |
| 426 | * @} |
| 427 | */ |
| 428 | |
| 429 | #endif /* __I2S_H__ */ |