Lines Matching +full:hfclkaudio +full:- +full:frequency

4  * SPDX-License-Identifier: Apache-2.0
59 /* Finds the clock settings that give the frame clock frequency closest to
81 (NRF_I2S_HAS_CLKCONFIG && drv_cfg->clk_src == ACLK) in find_suitable_clock()
84 * available and only with the "hfclkaudio-frequency" property in find_suitable_clock()
91 uint32_t bits_per_frame = 2 * i2s_cfg->word_size; in find_suitable_clock()
105 i2s_cfg->frame_clk_freq * ratios[r].ratio_val; in find_suitable_clock()
125 uint32_t diff = lrck_freq >= i2s_cfg->frame_clk_freq in find_suitable_clock()
126 ? (lrck_freq - i2s_cfg->frame_clk_freq) in find_suitable_clock()
127 : (i2s_cfg->frame_clk_freq - lrck_freq); in find_suitable_clock()
161 lrck_freq >= i2s_cfg->frame_clk_freq in find_suitable_clock()
162 ? (lrck_freq - i2s_cfg->frame_clk_freq) in find_suitable_clock()
163 : (i2s_cfg->frame_clk_freq - lrck_freq); in find_suitable_clock()
174 * after resulting LRCK frequency falls below in find_suitable_clock()
177 if (lrck_freq < i2s_cfg->frame_clk_freq) { in find_suitable_clock()
184 config->mck_setup = best_mck_cfg; in find_suitable_clock()
185 config->ratio = ratios[best_r].ratio_enum; in find_suitable_clock()
186 LOG_INF("I2S MCK frequency: %u, actual PCM rate: %u", in find_suitable_clock()
194 int ret = k_msgq_get(&drv_data->tx_queue, in get_next_tx_buffer()
198 buffers->p_tx_buffer = buf.mem_block; in get_next_tx_buffer()
199 buffers->buffer_size = buf.size / sizeof(uint32_t); in get_next_tx_buffer()
207 int ret = k_mem_slab_alloc(drv_data->rx.cfg.mem_slab, in get_next_rx_buffer()
208 (void **)&buffers->p_rx_buffer, in get_next_rx_buffer()
222 k_mem_slab_free(drv_data->tx.cfg.mem_slab, (void *)buffer); in free_tx_buffer()
228 k_mem_slab_free(drv_data->rx.cfg.mem_slab, buffer); in free_rx_buffer()
235 if (drv_data->active_dir != I2S_DIR_TX) { /* -> RX active */ in supply_next_buffers()
237 drv_data->state = I2S_STATE_ERROR; in supply_next_buffers()
238 nrfx_i2s_stop(drv_data->p_i2s); in supply_next_buffers()
244 if (drv_data->active_dir == I2S_DIR_RX) { in supply_next_buffers()
245 next->buffer_size = in supply_next_buffers()
246 drv_data->rx.cfg.block_size / sizeof(uint32_t); in supply_next_buffers()
250 drv_data->last_tx_buffer = next->p_tx_buffer; in supply_next_buffers()
252 LOG_DBG("Next buffers: %p/%p", next->p_tx_buffer, next->p_rx_buffer); in supply_next_buffers()
253 nrfx_i2s_next_buffers_set(drv_data->p_i2s, next); in supply_next_buffers()
260 struct i2s_nrfx_drv_data *drv_data = dev->data; in data_handler()
264 if (drv_data->state == I2S_STATE_STOPPING) { in data_handler()
265 drv_data->state = I2S_STATE_READY; in data_handler()
267 if (drv_data->last_tx_buffer) { in data_handler()
279 if (drv_data->last_tx_buffer != released->p_tx_buffer) { in data_handler()
281 drv_data->last_tx_buffer); in data_handler()
283 drv_data->last_tx_buffer = NULL; in data_handler()
285 nrfx_i2s_uninit(drv_data->p_i2s); in data_handler()
286 if (drv_data->request_clock) { in data_handler()
287 (void)onoff_release(drv_data->clk_mgr); in data_handler()
298 if (drv_data->state != I2S_STATE_STOPPING) { in data_handler()
300 drv_data->state = I2S_STATE_ERROR; in data_handler()
302 nrfx_i2s_stop(drv_data->p_i2s); in data_handler()
306 if (released->p_rx_buffer) { in data_handler()
307 if (drv_data->discard_rx) { in data_handler()
308 free_rx_buffer(drv_data, released->p_rx_buffer); in data_handler()
311 .mem_block = released->p_rx_buffer, in data_handler()
312 .size = released->buffer_size * sizeof(uint32_t) in data_handler()
314 int ret = k_msgq_put(&drv_data->rx_queue, in data_handler()
319 drv_data->state = I2S_STATE_ERROR; in data_handler()
322 free_rx_buffer(drv_data, released->p_rx_buffer); in data_handler()
324 LOG_DBG("Queued RX %p", released->p_rx_buffer); in data_handler()
330 if (drv_data->active_dir == I2S_DIR_RX && in data_handler()
331 drv_data->stop) { in data_handler()
332 drv_data->discard_rx = true; in data_handler()
339 if (released->p_tx_buffer) { in data_handler()
343 if (released->p_tx_buffer == drv_data->last_tx_buffer) { in data_handler()
344 drv_data->discard_rx = true; in data_handler()
347 free_tx_buffer(drv_data, released->p_tx_buffer); in data_handler()
352 nrfx_i2s_stop(drv_data->p_i2s); in data_handler()
356 if (drv_data->active_dir != I2S_DIR_RX) { /* -> TX active */ in data_handler()
357 if (drv_data->stop) { in data_handler()
364 next.p_tx_buffer = drv_data->last_tx_buffer; in data_handler()
370 } else if (drv_data->state == I2S_STATE_STOPPING) { in data_handler()
376 drv_data->stop = true; in data_handler()
381 next.p_tx_buffer = drv_data->last_tx_buffer; in data_handler()
387 drv_data->next_tx_buffer_needed = true; in data_handler()
398 struct i2s_nrfx_drv_data *drv_data = dev->data; in purge_queue()
402 while (k_msgq_get(&drv_data->tx_queue, in purge_queue()
410 while (k_msgq_get(&drv_data->rx_queue, in purge_queue()
421 struct i2s_nrfx_drv_data *drv_data = dev->data; in i2s_nrfx_configure()
422 const struct i2s_nrfx_drv_cfg *drv_cfg = dev->config; in i2s_nrfx_configure()
425 if (drv_data->state != I2S_STATE_READY) { in i2s_nrfx_configure()
426 LOG_ERR("Cannot configure in state: %d", drv_data->state); in i2s_nrfx_configure()
427 return -EINVAL; in i2s_nrfx_configure()
430 if (i2s_cfg->frame_clk_freq == 0) { /* -> reset state */ in i2s_nrfx_configure()
433 drv_data->tx_configured = false; in i2s_nrfx_configure()
434 memset(&drv_data->tx, 0, sizeof(drv_data->tx)); in i2s_nrfx_configure()
437 drv_data->rx_configured = false; in i2s_nrfx_configure()
438 memset(&drv_data->rx, 0, sizeof(drv_data->rx)); in i2s_nrfx_configure()
443 __ASSERT_NO_MSG(i2s_cfg->mem_slab != NULL && in i2s_nrfx_configure()
444 i2s_cfg->block_size != 0); in i2s_nrfx_configure()
446 if ((i2s_cfg->block_size % sizeof(uint32_t)) != 0) { in i2s_nrfx_configure()
447 LOG_ERR("This device can transfer only full 32-bit words"); in i2s_nrfx_configure()
448 return -EINVAL; in i2s_nrfx_configure()
451 nrfx_cfg = drv_cfg->nrfx_def_cfg; in i2s_nrfx_configure()
453 switch (i2s_cfg->word_size) { in i2s_nrfx_configure()
469 LOG_ERR("Unsupported word size: %u", i2s_cfg->word_size); in i2s_nrfx_configure()
470 return -EINVAL; in i2s_nrfx_configure()
473 switch (i2s_cfg->format & I2S_FMT_DATA_FORMAT_MASK) { in i2s_nrfx_configure()
487 LOG_ERR("Unsupported data format: 0x%02x", i2s_cfg->format); in i2s_nrfx_configure()
488 return -EINVAL; in i2s_nrfx_configure()
491 if ((i2s_cfg->format & I2S_FMT_DATA_ORDER_LSB) || in i2s_nrfx_configure()
492 (i2s_cfg->format & I2S_FMT_BIT_CLK_INV) || in i2s_nrfx_configure()
493 (i2s_cfg->format & I2S_FMT_FRAME_CLK_INV)) { in i2s_nrfx_configure()
494 LOG_ERR("Unsupported stream format: 0x%02x", i2s_cfg->format); in i2s_nrfx_configure()
495 return -EINVAL; in i2s_nrfx_configure()
498 if (i2s_cfg->channels == 2) { in i2s_nrfx_configure()
500 } else if (i2s_cfg->channels == 1) { in i2s_nrfx_configure()
504 i2s_cfg->channels); in i2s_nrfx_configure()
505 return -EINVAL; in i2s_nrfx_configure()
508 if ((i2s_cfg->options & I2S_OPT_BIT_CLK_SLAVE) && in i2s_nrfx_configure()
509 (i2s_cfg->options & I2S_OPT_FRAME_CLK_SLAVE)) { in i2s_nrfx_configure()
511 } else if (!(i2s_cfg->options & I2S_OPT_BIT_CLK_SLAVE) && in i2s_nrfx_configure()
512 !(i2s_cfg->options & I2S_OPT_FRAME_CLK_SLAVE)) { in i2s_nrfx_configure()
515 LOG_ERR("Unsupported operation mode: 0x%02x", i2s_cfg->options); in i2s_nrfx_configure()
516 return -EINVAL; in i2s_nrfx_configure()
523 (nrf_i2s_mck_pin_get(drv_cfg->i2s.p_reg) & I2S_PSEL_MCK_CONNECT_Msk) in i2s_nrfx_configure()
531 drv_data->request_clock = (drv_cfg->clk_src != PCLK32M); in i2s_nrfx_configure()
534 drv_data->request_clock = false; in i2s_nrfx_configure()
537 if ((i2s_cfg->options & I2S_OPT_LOOPBACK) || in i2s_nrfx_configure()
538 (i2s_cfg->options & I2S_OPT_PINGPONG)) { in i2s_nrfx_configure()
539 LOG_ERR("Unsupported options: 0x%02x", i2s_cfg->options); in i2s_nrfx_configure()
540 return -EINVAL; in i2s_nrfx_configure()
544 drv_data->tx.cfg = *i2s_cfg; in i2s_nrfx_configure()
545 drv_data->tx.nrfx_cfg = nrfx_cfg; in i2s_nrfx_configure()
546 drv_data->tx_configured = true; in i2s_nrfx_configure()
550 drv_data->rx.cfg = *i2s_cfg; in i2s_nrfx_configure()
551 drv_data->rx.nrfx_cfg = nrfx_cfg; in i2s_nrfx_configure()
552 drv_data->rx_configured = true; in i2s_nrfx_configure()
561 struct i2s_nrfx_drv_data *drv_data = dev->data; in i2s_nrfx_config_get()
563 if (dir == I2S_DIR_TX && drv_data->tx_configured) { in i2s_nrfx_config_get()
564 return &drv_data->tx.cfg; in i2s_nrfx_config_get()
566 if (dir == I2S_DIR_RX && drv_data->rx_configured) { in i2s_nrfx_config_get()
567 return &drv_data->rx.cfg; in i2s_nrfx_config_get()
576 struct i2s_nrfx_drv_data *drv_data = dev->data; in i2s_nrfx_read()
580 if (!drv_data->rx_configured) { in i2s_nrfx_read()
582 return -EIO; in i2s_nrfx_read()
585 ret = k_msgq_get(&drv_data->rx_queue, in i2s_nrfx_read()
587 (drv_data->state == I2S_STATE_ERROR) in i2s_nrfx_read()
589 : SYS_TIMEOUT_MS(drv_data->rx.cfg.timeout)); in i2s_nrfx_read()
590 if (ret == -ENOMSG) { in i2s_nrfx_read()
591 return -EIO; in i2s_nrfx_read()
607 struct i2s_nrfx_drv_data *drv_data = dev->data; in i2s_nrfx_write()
611 if (!drv_data->tx_configured) { in i2s_nrfx_write()
613 return -EIO; in i2s_nrfx_write()
616 if (drv_data->state != I2S_STATE_RUNNING && in i2s_nrfx_write()
617 drv_data->state != I2S_STATE_READY) { in i2s_nrfx_write()
618 LOG_ERR("Cannot write in state: %d", drv_data->state); in i2s_nrfx_write()
619 return -EIO; in i2s_nrfx_write()
622 if (size > drv_data->tx.cfg.block_size || size < sizeof(uint32_t)) { in i2s_nrfx_write()
624 drv_data->tx.cfg.block_size); in i2s_nrfx_write()
625 return -EIO; in i2s_nrfx_write()
628 ret = k_msgq_put(&drv_data->tx_queue, in i2s_nrfx_write()
630 SYS_TIMEOUT_MS(drv_data->tx.cfg.timeout)); in i2s_nrfx_write()
642 if (drv_data->state == I2S_STATE_RUNNING && in i2s_nrfx_write()
643 drv_data->next_tx_buffer_needed) { in i2s_nrfx_write()
655 drv_data->next_tx_buffer_needed = false; in i2s_nrfx_write()
660 return -EIO; in i2s_nrfx_write()
673 if (drv_data->active_dir != I2S_DIR_RX && /* -> TX to be started */ in start_transfer()
676 ret = -ENOMEM; in start_transfer()
677 } else if (drv_data->active_dir != I2S_DIR_TX && /* -> RX to be started */ in start_transfer()
680 ret = -ENOMEM; in start_transfer()
686 * condition above gets short-circuited. in start_transfer()
688 if (drv_data->active_dir == I2S_DIR_RX) { in start_transfer()
690 drv_data->rx.cfg.block_size / sizeof(uint32_t); in start_transfer()
693 drv_data->last_tx_buffer = initial_buffers.p_tx_buffer; in start_transfer()
695 err = nrfx_i2s_start(drv_data->p_i2s, &initial_buffers, 0); in start_transfer()
701 ret = -EIO; in start_transfer()
704 nrfx_i2s_uninit(drv_data->p_i2s); in start_transfer()
705 if (drv_data->request_clock) { in start_transfer()
706 (void)onoff_release(drv_data->clk_mgr); in start_transfer()
716 drv_data->state = I2S_STATE_ERROR; in start_transfer()
732 if (drv_data->state == I2S_STATE_READY) { in clock_started_callback()
733 nrfx_i2s_uninit(drv_data->p_i2s); in clock_started_callback()
734 (void)onoff_release(drv_data->clk_mgr); in clock_started_callback()
742 struct i2s_nrfx_drv_data *drv_data = dev->data; in trigger_start()
743 const struct i2s_nrfx_drv_cfg *drv_cfg = dev->config; in trigger_start()
746 const nrfx_i2s_config_t *nrfx_cfg = (drv_data->active_dir == I2S_DIR_TX) in trigger_start()
747 ? &drv_data->tx.nrfx_cfg in trigger_start()
748 : &drv_data->rx.nrfx_cfg; in trigger_start()
750 err = nrfx_i2s_init(drv_data->p_i2s, nrfx_cfg, drv_cfg->data_handler); in trigger_start()
753 return -EIO; in trigger_start()
756 drv_data->state = I2S_STATE_RUNNING; in trigger_start()
759 nrf_i2s_clk_configure(drv_cfg->i2s.p_reg, in trigger_start()
760 drv_cfg->clk_src == ACLK ? NRF_I2S_CLKSRC_ACLK in trigger_start()
768 if (drv_data->request_clock) { in trigger_start()
769 sys_notify_init_callback(&drv_data->clk_cli.notify, in trigger_start()
771 ret = onoff_request(drv_data->clk_mgr, &drv_data->clk_cli); in trigger_start()
773 nrfx_i2s_uninit(drv_data->p_i2s); in trigger_start()
774 drv_data->state = I2S_STATE_READY; in trigger_start()
777 return -EIO; in trigger_start()
792 struct i2s_nrfx_drv_data *drv_data = dev->data; in i2s_nrfx_trigger()
801 configured = drv_data->tx_configured && drv_data->rx_configured; in i2s_nrfx_trigger()
803 configured = drv_data->tx_configured; in i2s_nrfx_trigger()
805 configured = drv_data->rx_configured; in i2s_nrfx_trigger()
810 return -EIO; in i2s_nrfx_trigger()
814 (memcmp(&drv_data->tx.nrfx_cfg, in i2s_nrfx_trigger()
815 &drv_data->rx.nrfx_cfg, in i2s_nrfx_trigger()
816 sizeof(drv_data->rx.nrfx_cfg)) != 0 in i2s_nrfx_trigger()
818 (drv_data->tx.cfg.block_size != drv_data->rx.cfg.block_size))) { in i2s_nrfx_trigger()
820 return -EIO; in i2s_nrfx_trigger()
825 cmd_allowed = (drv_data->state == I2S_STATE_READY); in i2s_nrfx_trigger()
829 cmd_allowed = (drv_data->state == I2S_STATE_RUNNING); in i2s_nrfx_trigger()
835 cmd_allowed = (drv_data->state == I2S_STATE_ERROR); in i2s_nrfx_trigger()
839 return -EINVAL; in i2s_nrfx_trigger()
843 return -EIO; in i2s_nrfx_trigger()
851 if (drv_data->state == I2S_STATE_RUNNING && in i2s_nrfx_trigger()
852 drv_data->active_dir != dir) { in i2s_nrfx_trigger()
854 cmd, dir, drv_data->active_dir); in i2s_nrfx_trigger()
855 return -EINVAL; in i2s_nrfx_trigger()
860 drv_data->stop = false; in i2s_nrfx_trigger()
861 drv_data->discard_rx = false; in i2s_nrfx_trigger()
862 drv_data->active_dir = dir; in i2s_nrfx_trigger()
863 drv_data->next_tx_buffer_needed = false; in i2s_nrfx_trigger()
867 drv_data->state = I2S_STATE_STOPPING; in i2s_nrfx_trigger()
868 drv_data->stop = true; in i2s_nrfx_trigger()
872 drv_data->state = I2S_STATE_STOPPING; in i2s_nrfx_trigger()
874 drv_data->stop = (drv_data->active_dir == I2S_DIR_RX); in i2s_nrfx_trigger()
878 if (drv_data->state != I2S_STATE_READY) { in i2s_nrfx_trigger()
879 drv_data->discard_rx = true; in i2s_nrfx_trigger()
880 nrfx_i2s_stop(drv_data->p_i2s); in i2s_nrfx_trigger()
883 drv_data->state = I2S_STATE_READY; in i2s_nrfx_trigger()
888 drv_data->state = I2S_STATE_READY; in i2s_nrfx_trigger()
893 return -EINVAL; in i2s_nrfx_trigger()
899 struct i2s_nrfx_drv_data *drv_data = dev->data; in init_clock_manager()
903 const struct i2s_nrfx_drv_cfg *drv_cfg = dev->config; in init_clock_manager()
905 if (drv_cfg->clk_src == ACLK) { in init_clock_manager()
913 drv_data->clk_mgr = z_nrf_clock_control_get_onoff(subsys); in init_clock_manager()
914 __ASSERT_NO_MSG(drv_data->clk_mgr != NULL); in init_clock_manager()
959 const struct i2s_nrfx_drv_cfg *drv_cfg = dev->config; \
960 int err = pinctrl_apply_state(drv_cfg->pcfg, \
979 "Clock source ACLK requires the hfclkaudio-frequency " \
980 "property to be defined in the nordic,nrf-clock node."); \