Esempio n. 1
0
/**
 * intel_mid_i2s_open - reserve and start a SSP depending of it's usage
 * @usage : select which ssp i2s you need by giving usage (BT,MODEM...)
 * @ps_settings : hardware settings to configure the SSP module
 *
 * May sleep (driver_find_device) : no lock permitted when called.
 *
 * Output parameters
 *      handle : handle of the selected SSP, or NULL if not found
 */
struct intel_mid_i2s_hdl *intel_mid_i2s_open(enum intel_mid_i2s_ssp_usage usage,
			 const struct intel_mid_i2s_settings *ps_settings)
{
	struct pci_dev *pdev;
	struct intel_mid_i2s_hdl *drv_data = NULL;
	struct device *found_device = NULL;

	pr_debug("%s : open called,searching for device with usage=%x !\n",
							DRIVER_NAME, usage);
	found_device = driver_find_device(&(intel_mid_i2s_driver.driver),
						NULL, &usage, check_device);
	if (!found_device) {
		pr_debug("%s : open can not found with usage=0x%02X\n",
						DRIVER_NAME, (int)usage);
		return NULL;
	}
	pdev = to_pci_dev(found_device);
	drv_data = pci_get_drvdata(pdev);
	drv_data->current_settings = *ps_settings;

	if (!drv_data) {
		dev_err(found_device, "no drv_data in open pdev=%p\n", pdev);
		put_device(found_device);
		return NULL;
	}
	mutex_lock(&drv_data->mutex);
	dev_dbg(found_device, "Open found pdevice=0x%p\n", pdev);
	/* pm_runtime */
	pm_runtime_get_sync(&drv_data->pdev->dev);
	/* dmac1 is already set during probe */
	if (i2s_dma_start(drv_data) != 0) {
		dev_err(found_device, "Can not start DMA\n");
		goto open_error;
	}
	/* if we restart after stop without suspend, we start ssp faster */
	set_ssp_i2s_hw(drv_data, ps_settings);

	drv_data->mask_sr = ((SSSR_BCE_MASK << SSSR_BCE_SHIFT) |
			(SSSR_EOC_MASK << SSSR_EOC_SHIFT) |
			(SSSR_ROR_MASK << SSSR_ROR_SHIFT) |
			(SSSR_TUR_MASK << SSSR_TUR_SHIFT) |
			(SSSR_TINT_MASK << SSSR_TINT_SHIFT) |
			(SSSR_PINT_MASK << SSSR_PINT_SHIFT));
	if (test_bit(I2S_PORT_CLOSING, &drv_data->flags)) {
		dev_err(&drv_data->pdev->dev, "Opening a closing I2S!");
		goto open_error;
	}
	/* there is no need to "wake up" as we can not close an opening i2s */
	clear_bit(I2S_PORT_WRITE_BUSY, &drv_data->flags);
	clear_bit(I2S_PORT_READ_BUSY, &drv_data->flags);
	mutex_unlock(&drv_data->mutex);
	return drv_data;

open_error:
	pm_runtime_put(&drv_data->pdev->dev);
	put_device(found_device);
	mutex_unlock(&drv_data->mutex);
	return NULL;
}
Esempio n. 2
0
void ws2812_i2s_init(uint32_t pixels_number)
{
    dma_buffer_size = pixels_number * DMA_PIXEL_SIZE;
    dma_block_list_size = dma_buffer_size / MAX_DMA_BLOCK_SIZE;

    if (dma_buffer_size % MAX_DMA_BLOCK_SIZE) {
        dma_block_list_size += 1;
    }

    dma_block_list_size += 2;  // zero block and stop block

    debug("allocating %d dma blocks\n", dma_block_list_size);

    dma_block_list = (dma_descriptor_t*)malloc(
            dma_block_list_size * sizeof(dma_descriptor_t));

    debug("allocating %d bytes for DMA buffer\n", dma_buffer_size);
    dma_buffer = malloc(dma_buffer_size);
    memset(dma_buffer, 0xFA, dma_buffer_size);

    init_descriptors_list(dma_buffer, dma_buffer_size);

    i2s_clock_div_t clock_div = i2s_get_clock_div(3333333);
    i2s_pins_t i2s_pins = {.data = true, .clock = false, .ws = false};

    debug("i2s clock dividers, bclk=%d, clkm=%d\n",
            clock_div.bclk_div, clock_div.clkm_div);

    i2s_dma_init(dma_isr_handler, clock_div, i2s_pins);
}

const IRAM_DATA int16_t bitpatterns[16] =
{
    0b1000100010001000, 0b1000100010001110, 0b1000100011101000, 0b1000100011101110,
    0b1000111010001000, 0b1000111010001110, 0b1000111011101000, 0b1000111011101110,
    0b1110100010001000, 0b1110100010001110, 0b1110100011101000, 0b1110100011101110,
    0b1110111010001000, 0b1110111010001110, 0b1110111011101000, 0b1110111011101110,
};

void ws2812_i2s_update(ws2812_pixel_t *pixels)
{
    while (i2s_dma_processing) {};

    uint16_t *p_dma_buf = dma_buffer;

    for (uint32_t i = 0; i < (dma_buffer_size / DMA_PIXEL_SIZE); i++) {
        // green
        *p_dma_buf++ =  bitpatterns[pixels[i].green & 0x0F];
        *p_dma_buf++ =  bitpatterns[pixels[i].green >> 4];

        // red
        *p_dma_buf++ =  bitpatterns[pixels[i].red & 0x0F];
        *p_dma_buf++ =  bitpatterns[pixels[i].red >> 4];

        // blue
        *p_dma_buf++ =  bitpatterns[pixels[i].blue & 0x0F];
        *p_dma_buf++ =  bitpatterns[pixels[i].blue >> 4];
    }

    i2s_dma_processing = true;
    i2s_dma_start(dma_block_list);
}
Esempio n. 3
0
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);
}