Lines Matching +full:tx +full:- +full:fifo +full:- +full:size

4  * SPDX-License-Identifier: Apache-2.0
22 val = (val == max - 1) ? 0 : val + 1; \
50 * @brief Reset i2s fifo
79 return -EINVAL; in i2s_get_foramt()
158 * This function copies data from fifo into user buffer
160 * @param dst memory destination where fifo data will be copied to
161 * @param size amount of data to be copied
165 static void i2s_copy_from_fifo(uint8_t *dst, size_t size, int sample_width, in i2s_copy_from_fifo() argument
172 for (size_t i = 0; i < size / chan_size; i += 4) { in i2s_copy_from_fifo()
173 /* using sys_read function, as fifo is not a csr, in i2s_copy_from_fifo()
179 for (size_t i = 0; i < size / chan_size; i += 2) { in i2s_copy_from_fifo()
185 int max_off = chan_size - 1; in i2s_copy_from_fifo()
187 for (size_t i = 0; i < size / chan_size; ++i) { in i2s_copy_from_fifo()
189 for (int off = max_off; off >= 0; off--) { in i2s_copy_from_fifo()
191 *(dst + i * chan_size + (max_off - off)) = in i2s_copy_from_fifo()
211 * This function copies data from user buffer into fifo
213 * @param src memory from which data will be copied to fifo
214 * @param size amount of data to be copied in bytes
218 static void i2s_copy_to_fifo(uint8_t *src, size_t size, int sample_width, in i2s_copy_to_fifo() argument
224 for (size_t i = 0; i < size / chan_size; i += 4) { in i2s_copy_to_fifo()
225 /* using sys_write function, as fifo is not a csr, in i2s_copy_to_fifo()
231 for (size_t i = 0; i < size / chan_size; i += 2) { in i2s_copy_to_fifo()
236 int max_off = chan_size - 1; in i2s_copy_to_fifo()
240 for (size_t i = 0; i < size / chan_size; ++i) { in i2s_copy_to_fifo()
241 for (int off = max_off; off >= 0; off--) { in i2s_copy_to_fifo()
244 *(src + i * chan_size + (max_off - off)); in i2s_copy_to_fifo()
263 static int queue_get(struct ring_buf *rb, void **mem_block, size_t *size) in queue_get() argument
269 if (rb->tail == rb->head) { in queue_get()
272 return -ENOMEM; in queue_get()
274 *mem_block = rb->buf[rb->tail].mem_block; in queue_get()
275 *size = rb->buf[rb->tail].size; in queue_get()
276 MODULO_INC(rb->tail, rb->len); in queue_get()
285 static int queue_put(struct ring_buf *rb, void *mem_block, size_t size) in queue_put() argument
292 head_next = rb->head; in queue_put()
293 MODULO_INC(head_next, rb->len); in queue_put()
295 if (head_next == rb->tail) { in queue_put()
298 return -ENOMEM; in queue_put()
301 rb->buf[rb->head].mem_block = mem_block; in queue_put()
302 rb->buf[rb->head].size = size; in queue_put()
303 rb->head = head_next; in queue_put()
311 const struct i2s_litex_cfg *cfg = dev->config; in i2s_litex_initialize()
312 struct i2s_litex_data *const dev_data = dev->data; in i2s_litex_initialize()
314 k_sem_init(&dev_data->rx.sem, 0, CONFIG_I2S_LITEX_RX_BLOCK_COUNT); in i2s_litex_initialize()
315 k_sem_init(&dev_data->tx.sem, CONFIG_I2S_LITEX_TX_BLOCK_COUNT - 1, in i2s_litex_initialize()
318 cfg->irq_config(dev); in i2s_litex_initialize()
325 struct i2s_litex_data *const dev_data = dev->data; in i2s_litex_configure()
326 const struct i2s_litex_cfg *const cfg = dev->config; in i2s_litex_configure()
328 int channels_concatenated = litex_read8(cfg->base + I2S_STATUS_OFFSET); in i2s_litex_configure()
329 int dev_audio_freq = i2s_get_audio_freq(cfg->base); in i2s_litex_configure()
333 stream = &dev_data->rx; in i2s_litex_configure()
336 stream = &dev_data->tx; in i2s_litex_configure()
339 return -ENOSYS; in i2s_litex_configure()
341 LOG_ERR("either RX or TX direction must be selected"); in i2s_litex_configure()
342 return -EINVAL; in i2s_litex_configure()
345 if (stream->state != I2S_STATE_NOT_READY && in i2s_litex_configure()
346 stream->state != I2S_STATE_READY) { in i2s_litex_configure()
348 return -EINVAL; in i2s_litex_configure()
351 if (i2s_cfg->options & I2S_OPT_BIT_CLK_GATED) { in i2s_litex_configure()
353 return -EINVAL; in i2s_litex_configure()
356 if (i2s_cfg->frame_clk_freq != dev_audio_freq) { in i2s_litex_configure()
360 if (i2s_cfg->channels == 1) { in i2s_litex_configure()
362 } else if (i2s_cfg->channels == 2) { in i2s_litex_configure()
366 return -EINVAL; in i2s_litex_configure()
369 (cfg->fifo_depth * (i2s_cfg->word_size / 8)) / channel_div; in i2s_litex_configure()
371 if (i2s_cfg->block_size < req_buf_s) { in i2s_litex_configure()
373 LOG_ERR("fifo requires at least %i bytes", req_buf_s); in i2s_litex_configure()
374 return -EINVAL; in i2s_litex_configure()
375 } else if (i2s_cfg->block_size != req_buf_s) { in i2s_litex_configure()
385 int dev_sample_width = i2s_get_sample_width(cfg->base); in i2s_litex_configure()
387 if (i2s_cfg->word_size != 8U && i2s_cfg->word_size != 16U && in i2s_litex_configure()
388 i2s_cfg->word_size != 24U && i2s_cfg->word_size != 32U && in i2s_litex_configure()
389 i2s_cfg->word_size != dev_sample_width) { in i2s_litex_configure()
390 LOG_ERR("invalid word size"); in i2s_litex_configure()
391 return -EINVAL; in i2s_litex_configure()
394 int dev_format = i2s_get_foramt(cfg->base); in i2s_litex_configure()
396 if (dev_format != i2s_cfg->format) { in i2s_litex_configure()
398 return -EINVAL; in i2s_litex_configure()
405 return -EINVAL; in i2s_litex_configure()
412 return -EINVAL; in i2s_litex_configure()
415 if (i2s_cfg->word_size != 16) { in i2s_litex_configure()
416 LOG_ERR("invalid word size"); in i2s_litex_configure()
417 return -EINVAL; in i2s_litex_configure()
422 memcpy(&stream->cfg, i2s_cfg, sizeof(struct i2s_config)); in i2s_litex_configure()
423 stream->cfg.block_size = req_buf_s; in i2s_litex_configure()
425 stream->state = I2S_STATE_READY; in i2s_litex_configure()
430 size_t *size) in i2s_litex_read() argument
432 struct i2s_litex_data *const dev_data = dev->data; in i2s_litex_read()
435 if (dev_data->rx.state == I2S_STATE_NOT_READY) { in i2s_litex_read()
437 return -ENOMEM; in i2s_litex_read()
440 ret = k_sem_take(&dev_data->rx.sem, in i2s_litex_read()
441 SYS_TIMEOUT_MS(dev_data->rx.cfg.timeout)); in i2s_litex_read()
446 return queue_get(&dev_data->rx.mem_block_queue, mem_block, size); in i2s_litex_read()
450 size_t size) in i2s_litex_write() argument
452 struct i2s_litex_data *const dev_data = dev->data; in i2s_litex_write()
453 const struct i2s_litex_cfg *cfg = dev->config; in i2s_litex_write()
456 if (dev_data->tx.state != I2S_STATE_RUNNING && in i2s_litex_write()
457 dev_data->tx.state != I2S_STATE_READY) { in i2s_litex_write()
459 return -EIO; in i2s_litex_write()
462 ret = k_sem_take(&dev_data->tx.sem, in i2s_litex_write()
463 SYS_TIMEOUT_MS(dev_data->tx.cfg.timeout)); in i2s_litex_write()
467 /* Add data to the end of the TX queue */ in i2s_litex_write()
468 ret = queue_put(&dev_data->tx.mem_block_queue, mem_block, size); in i2s_litex_write()
473 if (dev_data->tx.state == I2S_STATE_READY) { in i2s_litex_write()
474 i2s_irq_enable(cfg->base, I2S_EV_READY); in i2s_litex_write()
475 dev_data->tx.state = I2S_STATE_RUNNING; in i2s_litex_write()
483 struct i2s_litex_data *const dev_data = dev->data; in i2s_litex_trigger()
484 const struct i2s_litex_cfg *const cfg = dev->config; in i2s_litex_trigger()
488 stream = &dev_data->rx; in i2s_litex_trigger()
490 stream = &dev_data->tx; in i2s_litex_trigger()
492 return -ENOSYS; in i2s_litex_trigger()
494 LOG_ERR("either RX or TX direction must be selected"); in i2s_litex_trigger()
495 return -EINVAL; in i2s_litex_trigger()
500 if (stream->state != I2S_STATE_READY) { in i2s_litex_trigger()
502 stream->state); in i2s_litex_trigger()
503 return -EIO; in i2s_litex_trigger()
505 __ASSERT_NO_MSG(stream->mem_block == NULL); in i2s_litex_trigger()
506 i2s_reset_fifo(cfg->base); in i2s_litex_trigger()
507 i2s_enable(cfg->base); in i2s_litex_trigger()
508 i2s_irq_enable(cfg->base, I2S_EV_READY); in i2s_litex_trigger()
509 stream->state = I2S_STATE_RUNNING; in i2s_litex_trigger()
513 if (stream->state != I2S_STATE_RUNNING && in i2s_litex_trigger()
514 stream->state != I2S_STATE_READY) { in i2s_litex_trigger()
516 return -EIO; in i2s_litex_trigger()
518 i2s_disable(cfg->base); in i2s_litex_trigger()
519 i2s_irq_disable(cfg->base, I2S_EV_READY); in i2s_litex_trigger()
520 stream->state = I2S_STATE_READY; in i2s_litex_trigger()
525 return -EINVAL; in i2s_litex_trigger()
535 i2s_clear_pending_irq(cfg->base); in clear_rx_fifo()
541 const struct i2s_litex_cfg *cfg = dev->config; in i2s_litex_isr_rx()
542 struct i2s_litex_data *data = dev->data; in i2s_litex_isr_rx()
543 struct stream *stream = &data->rx; in i2s_litex_isr_rx()
547 ret = k_mem_slab_alloc(stream->cfg.mem_slab, &stream->mem_block, in i2s_litex_isr_rx()
553 i2s_copy_from_fifo((uint8_t *)stream->mem_block, stream->cfg.block_size, in i2s_litex_isr_rx()
554 stream->cfg.word_size, stream->cfg.channels); in i2s_litex_isr_rx()
555 i2s_clear_pending_irq(cfg->base); in i2s_litex_isr_rx()
557 ret = queue_put(&stream->mem_block_queue, stream->mem_block, in i2s_litex_isr_rx()
558 stream->cfg.block_size); in i2s_litex_isr_rx()
561 "from RX fifo to the ring " in i2s_litex_isr_rx()
562 "buffer (no space left) - " in i2s_litex_isr_rx()
567 k_sem_give(&stream->sem); in i2s_litex_isr_rx()
573 const struct i2s_litex_cfg *cfg = dev->config; in i2s_litex_isr_tx()
574 struct i2s_litex_data *data = dev->data; in i2s_litex_isr_tx()
576 struct stream *stream = &data->tx; in i2s_litex_isr_tx()
579 ret = queue_get(&stream->mem_block_queue, &stream->mem_block, in i2s_litex_isr_tx()
582 i2s_irq_disable(cfg->base, I2S_EV_READY); in i2s_litex_isr_tx()
583 stream->state = I2S_STATE_READY; in i2s_litex_isr_tx()
586 k_sem_give(&stream->sem); in i2s_litex_isr_tx()
587 i2s_copy_to_fifo((uint8_t *)stream->mem_block, mem_block_size, in i2s_litex_isr_tx()
588 stream->cfg.word_size, stream->cfg.channels); in i2s_litex_isr_tx()
589 i2s_clear_pending_irq(cfg->base); in i2s_litex_isr_tx()
591 k_mem_slab_free(stream->cfg.mem_slab, stream->mem_block); in i2s_litex_isr_tx()
617 DT_REG_ADDR_BY_NAME(DT_NODELABEL(i2s_##dir), fifo), \
641 I2S_INIT(tx);