static inline void stop_i2s_playback(struct snd_soc_dai *cpu_dai) { i2s_set_fifo_irq_on_err(cpu_dai->id, I2S_FIFO_TX, 0); i2s_set_fifo_irq_on_qe(cpu_dai->id, I2S_FIFO_TX, 0); i2s_fifo_enable(cpu_dai->id, I2S_FIFO_TX, 0); while (i2s_get_status(cpu_dai->id) & I2S_I2S_FIFO_TX_BUSY); }
/** * \brief Internal interrupt handler for I2S. */ static void i2s_interrupt_handler(I2sc *i2sc) { uint32_t row_num; struct i2s_dev_inst i2s_instance; i2s_instance.hw_dev = i2sc; uint32_t status = i2s_get_status(&i2s_instance); uint32_t mask = i2s_get_interrupt_mask(&i2s_instance); #if defined(ID_I2SC1) if (i2sc == I2SC1) { row_num = 1; } #endif #if defined(ID_I2SC0) if (i2sc == I2SC0) { row_num = 0; } #endif if ((status & I2SC_SR_RXRDY) && (mask & I2SC_IMR_RXRDY)) { i2s_callback_pointer[row_num][I2S_INTERRUPT_RXRDY](); } if ((status & I2SC_SR_RXOR) && (mask & I2SC_IMR_RXOR)) { i2s_callback_pointer[row_num][I2S_INTERRUPT_RXOR](); } if ((status & I2SC_SR_TXRDY) && (mask & I2SC_IMR_TXRDY)) { i2s_callback_pointer[row_num][I2S_INTERRUPT_TXRDY](); } if ((status & I2SC_SR_TXUR) && (mask & I2SC_IMR_TXUR)) { i2s_callback_pointer[row_num][I2S_INTERRUPT_TXUR](); } if ((status & I2SC_SR_RXRDY) && (mask & I2SC_IMR_ENDRX)) { i2s_callback_pointer[row_num][I2S_INTERRUPT_ENDRX](); } if ((status & I2SC_SR_RXOR) && (mask & I2SC_IMR_ENDTX)) { i2s_callback_pointer[row_num][I2S_INTERRUPT_ENDTX](); } if ((status & I2SC_SR_TXRDY) && (mask & I2SC_IMR_RXFULL)) { i2s_callback_pointer[row_num][I2S_INTERRUPT_RXBUFF](); } if ((status & I2SC_SR_TXUR) && (mask & I2SC_IMR_TXEMPTY)) { i2s_callback_pointer[row_num][I2S_INTERRUPT_TXBUFE](); } }
/** * \brief Test audio data transfer and receive. * * \param test Current test case. */ static void run_i2s_test(const struct test_case *test) { uint32_t i; struct i2s_config config; struct i2s_dev_inst dev_inst; Pdc *p_i2sc_pdc; Pdc *p_i2sc_pdc2; pdc_packet_t pdc_i2sc_packet_tx, pdc_i2sc_packet_rx; pdc_packet_t pdc2_i2sc_packet_tx, pdc2_i2sc_packet_rx; /* Set the configuration */ i2s_get_config_defaults(&config); config.data_format = I2S_DATE_16BIT; config.fs_ratio = I2S_FS_RATE_256; config.loopback = true; i2s_init(&dev_inst, I2SC0, &config); /* Enable the I2SC module. */ i2s_enable(&dev_inst); /* Get pointer to I2SC PDC register base */ p_i2sc_pdc = i2s_get_pdc_base(&dev_inst); p_i2sc_pdc2 = (Pdc *)((uint32_t)p_i2sc_pdc + 0x100U); /* Initialize PDC data packet for transfer */ pdc_i2sc_packet_tx.ul_addr = (uint32_t) output_samples_left; pdc_i2sc_packet_tx.ul_size = SOUND_SAMPLES; pdc_i2sc_packet_rx.ul_addr = (uint32_t) input_samples_left; pdc_i2sc_packet_rx.ul_size = SOUND_SAMPLES; pdc2_i2sc_packet_tx.ul_addr = (uint32_t) output_samples_right; pdc2_i2sc_packet_tx.ul_size = SOUND_SAMPLES; pdc2_i2sc_packet_rx.ul_addr = (uint32_t) input_samples_right; pdc2_i2sc_packet_rx.ul_size = SOUND_SAMPLES; /* Configure PDC for data transfer */ pdc_tx_init(p_i2sc_pdc, &pdc_i2sc_packet_tx, NULL); pdc_rx_init(p_i2sc_pdc, &pdc_i2sc_packet_rx, NULL); pdc_tx_init(p_i2sc_pdc2, &pdc2_i2sc_packet_tx, NULL); pdc_rx_init(p_i2sc_pdc2, &pdc2_i2sc_packet_rx, NULL); /* Enable PDC transfers */ pdc_enable_transfer(p_i2sc_pdc, PERIPH_PTCR_TXTEN | PERIPH_PTCR_RXTEN); pdc_enable_transfer(p_i2sc_pdc2, PERIPH_PTCR_TXTEN | PERIPH_PTCR_RXTEN); /* Enable the functions */ i2s_enable_transmission(&dev_inst); i2s_enable_clocks(&dev_inst); /** * Since the transfer and receive timing is not under control, we * need adjust here the enable sequence and add some delay * functions if it's needed. */ for (i = 0; i < 0x8; i++) { input_samples_left[i] = i; } i2s_enable_reception(&dev_inst); /* Wait transfer complete */ while (!(i2s_get_status(&dev_inst) & I2SC_SR_RXBUFF)) { } /** * Wait a moment to let the PDC finish. The status bit is cleared * before all transfer finish. */ delay_us(10); /* Disable the PDC module. */ pdc_disable_transfer(p_i2sc_pdc, PERIPH_PTCR_RXTDIS| PERIPH_PTCR_TXTDIS); pdc_disable_transfer(p_i2sc_pdc2, PERIPH_PTCR_RXTDIS| PERIPH_PTCR_TXTDIS); /* Disable the I2SC module. */ i2s_disable(&dev_inst); /* Compare the data. */ for (i = 0; i < SOUND_SAMPLES; i++) { if ((input_samples_left[i] != output_samples_left[i]) || (input_samples_right[i] != output_samples_right[i])) { flag = false; } } test_assert_true(test, flag == true, "Audio data did not match!"); }