/** * intel_mid_i2s_close - release and stop the SSP * @drv_data : handle of corresponding ssp i2s (given by i2s_open function) * * WARNING: This is not -yet- allowed to call close from a read/write callback ! * * Output parameters * none */ void intel_mid_i2s_close(struct intel_mid_i2s_hdl *drv_data) { void __iomem *reg; struct intel_mid_i2s_settings *ssp_settings = &(drv_data->current_settings); int s; struct dma_chan *channel; WARN(!drv_data, "Driver data=NULL\n"); if (!drv_data) return; mutex_lock(&drv_data->mutex); if (!test_bit(I2S_PORT_OPENED, &drv_data->flags)) { dev_err(&drv_data->pdev->dev, "not opened but closing?"); mutex_unlock(&drv_data->mutex); return; } set_bit(I2S_PORT_CLOSING, &drv_data->flags); dev_info(&drv_data->pdev->dev, "Status bit pending write=%d read=%d\n", test_bit(I2S_PORT_WRITE_BUSY, &drv_data->flags), test_bit(I2S_PORT_READ_BUSY, &drv_data->flags)); if (test_bit(I2S_PORT_WRITE_BUSY, &drv_data->flags) || test_bit(I2S_PORT_READ_BUSY, &drv_data->flags)) { dev_info(&drv_data->pdev->dev, "Pending callback in close...\n"); } if (ssp_settings->ssp_active_tx_slots_map) { channel = drv_data->txchan; s = channel->device->device_control(channel, DMA_TERMINATE_ALL, 0); dev_info(&drv_data->pdev->dev, "DMA_TERMINATE tx=%d\n", s); } if (ssp_settings->ssp_active_rx_slots_map) { channel = drv_data->rxchan; s = channel->device->device_control(channel, DMA_TERMINATE_ALL, 0); dev_info(&drv_data->pdev->dev, "DMA_TERMINATE rx=%d\n", s); } /* release DMA Channel.. */ i2s_dma_stop(drv_data); reg = drv_data->ioaddr; dev_dbg(&drv_data->pdev->dev, "Stopping the SSP\n"); i2s_ssp_stop(drv_data); put_device(&drv_data->pdev->dev); write_SSCR0(0, reg); dev_dbg(&(drv_data->pdev->dev), "SSP Stopped.\n"); clear_bit(I2S_PORT_CLOSING, &drv_data->flags); clear_bit(I2S_PORT_OPENED, &drv_data->flags); /* pm runtime */ pm_runtime_put(&drv_data->pdev->dev); mutex_unlock(&drv_data->mutex); }
void play_task(void *pvParameters) { esp_spiffs_init(); if (esp_spiffs_mount() != SPIFFS_OK) { printf("Error mount SPIFFS\n"); } int fd = open("sample.wav", O_RDONLY); if (fd < 0) { printf("Error opening file\n"); return; } dumb_wav_header_t wav_header; read(fd, (void*)&wav_header, sizeof(wav_header)); printf("Number of channels: %d\n", wav_header.num_channels); printf("Bits per sample: %d\n", wav_header.bits_per_sample); printf("Sample rate: %d\n", wav_header.sample_rate); printf("Data size: %d\n", wav_header.data_size); if (wav_header.bits_per_sample != 16) { printf("Only 16 bit per sample is supported\n"); return; } if (wav_header.num_channels != 2) { printf("Only 2 channels is supported\n"); return; } i2s_clock_div_t clock_div = i2s_get_clock_div( wav_header.sample_rate * 2 * 16); printf("i2s clock dividers, bclk=%d, clkm=%d\n", clock_div.bclk_div, clock_div.clkm_div); i2s_pins_t i2s_pins = {.data = true, .clock = true, .ws = true}; i2s_dma_init(dma_isr_handler, clock_div, i2s_pins); while (1) { init_descriptors_list(); i2s_dma_start(dma_block_list); lseek(fd, sizeof(dumb_wav_header_t), SEEK_SET); while (play_data(fd)) {}; i2s_dma_stop(); vQueueDelete(dma_queue); printf("underrun counter: %d\n", underrun_counter); vTaskDelay(1000 / portTICK_PERIOD_MS); } close(fd); } void user_init(void) { uart_set_baud(0, 115200); xTaskCreate(play_task, "test_task", 1024, NULL, 2, NULL); }