Esempio n. 1
0
void audio_enable(void)
{
	if (!audio_drv.enabled) {
		audio_drv.enabled = true;
		i2s_enable();
	}
}
Esempio n. 2
0
/*
 * apl_i2s_send - Send audio samples to I2s controller.
 * @me: I2sOps structure
 * @data: Audio samples
 * @length: Number of samples
 *
 * Send audio samples to I2s controller.
*/
static int apl_i2s_send(I2sOps *me, unsigned int *data, unsigned int length)
{
	int i;
	uint64_t start;
	AplI2s *bus = container_of(me, AplI2s, ops);
	struct AplI2sRegs *i2s_reg = bus->regs;

	if (!bus->initialized) {
		if (apl_i2s_init(bus))
			return -1;
		bus->initialized = 1;
	}

	if (length < LPE_SSP_FIFO_SIZE) {
		printf("%s : Invalid data size\n", __func__);
		return -1;
	}

	gpio_set(bus->sdmode_gpio, 1);

	for (i = 0; i < LPE_SSP_FIFO_SIZE; i++)
		writel(*data++, &i2s_reg->ssdr);

	i2s_enable(bus->regs);
	length -= LPE_SSP_FIFO_SIZE;

	while (length > 0) {
		start = timer_us(0);
		if (read_SSSR(bus->regs) & 0x4) {
			writel(*data++, &i2s_reg->ssdr);
			length--;
		} else {
			if (timer_us(start) > 100000) {
				i2s_disable(bus->regs);
				gpio_set(bus->sdmode_gpio, 0);
				printf("I2S Transfer Timeout\n");
				return -1;
			}
		}
	}

	mdelay(1);
	gpio_set(bus->sdmode_gpio, 0);
	i2s_disable(bus->regs);
	return 0;
}
Esempio n. 3
0
void audio_reset(void)
{
	bool enable_stream;

	tracef("%s(): audio system reset ...", __func__);

	enable_stream = audio_drv.stream_enabled;

	audio_drv.stream_enabled = false;

	codec_hw_reset();
	
	tlv320_reset();

	if (audio_drv.enabled)
		i2s_disable();

	tlv320_init();

	if (audio_drv.enabled)
		i2s_enable();

	audio_drv.stream_enabled = enable_stream;
}
Esempio n. 4
0
DRIVER_API_RC soc_i2s_stream(uint32_t *buf, uint32_t len, uint32_t num_bufs)
{
	DRIVER_API_RC ret;
	uint8_t channel = I2S_CHANNEL_TX;
	uint32_t reg;
	uint32_t len_per_buf;
	int i;
	struct soc_dma_xfer_item *dma_list;

	// Check channel no in use and configured
	if (channel >= I2S_NUM_CHANNELS) 
	{
		return DRV_RC_FAIL;
	} 
	else if (i2s_info->en[channel] || !(i2s_info->cfgd[channel])) 
	{
		return DRV_RC_FAIL;
	}

	// Get a DMA channel
	ret = soc_dma_acquire(&(i2s_info->dma_ch[channel]));

	if (ret != DRV_RC_OK) 
	{
		return DRV_RC_FAIL;
	}

	// Enable the channel
	i2s_enable(channel);

	// Determine the length of a single buffer
	if (num_bufs == 0) 
	{
		len_per_buf = len;
	} 
	else 
	{
		len_per_buf = len / num_bufs;
	}

	// Prep some configuration
	i2s_info->dma_cfg[channel].type = SOC_DMA_TYPE_MEM2PER;
	i2s_info->dma_cfg[channel].dest_interface = SOC_DMA_INTERFACE_I2S_TX;
	i2s_info->dma_cfg[channel].dest_step_count = 0;
	i2s_info->dma_cfg[channel].src_step_count = 0;

	i2s_info->dma_cfg[channel].xfer.dest.delta = SOC_DMA_DELTA_NONE;
	i2s_info->dma_cfg[channel].xfer.dest.width = SOC_DMA_WIDTH_32;
	i2s_info->dma_cfg[channel].xfer.dest.addr = (void *)(SOC_I2S_BASE + SOC_I2S_DATA_REG);
	i2s_info->dma_cfg[channel].xfer.src.delta = SOC_DMA_DELTA_INCR;
	i2s_info->dma_cfg[channel].xfer.src.width = SOC_DMA_WIDTH_32;

	if (num_bufs == 0) 
	{
		i2s_info->dma_cfg[channel].cb_done = i2s_dma_cb_done;
		i2s_info->dma_cfg[channel].cb_done_arg = (void *)((uint32_t)channel);
	} 
	else 
	{
		i2s_info->dma_cfg[channel].cb_block = i2s_dma_cb_block;
		i2s_info->dma_cfg[channel].cb_block_arg = (void *)((uint32_t)channel);
	}

	i2s_info->dma_cfg[channel].cb_err = i2s_dma_cb_err;
	i2s_info->dma_cfg[channel].cb_err_arg = (void *)((uint32_t)channel);

	// Setup the linked list
	for (i = 0; i < ((num_bufs == 0) ? 1 : num_bufs); i++) 
	{
		if (i == 0) 
		{
			dma_list = &(i2s_info->dma_cfg[channel].xfer);
		} 
		else 
		{
			ret = soc_dma_alloc_list_item(&dma_list, dma_list);

			if (ret != DRV_RC_OK) 
			{
				goto fail;
			}
		}

		dma_list->src.addr = (void *)(&(buf[i * (len_per_buf / sizeof(uint32_t))]));
		dma_list->size = len_per_buf / sizeof(uint32_t);
	}

	// Create a circular list if we are doing circular buffering
	if (num_bufs != 0) 
	{
		dma_list->next = &(i2s_info->dma_cfg[channel].xfer);
	}

	// Setup and start the DMA engine
	ret = soc_dma_config(&(i2s_info->dma_ch[channel]), &(i2s_info->dma_cfg[channel]));

	if (ret != DRV_RC_OK) 
	{
		goto fail;
	}

	ret = soc_dma_start_transfer(&(i2s_info->dma_ch[channel]));

	if (ret != DRV_RC_OK) 
	{
		goto fail;
	}

	// Enable the channel and let it go!
	reg = MMIO_REG_VAL_FROM_BASE(SOC_I2S_BASE, i2s_reg_map[channel].ctrl);
	reg |= (1 << (i2s_reg_map[channel].ctrl_en));
	reg |= (1 << (i2s_reg_map[channel].ctrl_sync_rst));
	MMIO_REG_VAL_FROM_BASE(SOC_I2S_BASE, i2s_reg_map[channel].ctrl) = reg;

	return DRV_RC_OK;

fail:
	i2s_disable(channel);
	soc_dma_release(&(i2s_info->dma_ch[channel]));
	return DRV_RC_FAIL;
}
Esempio n. 5
0
//! [setup]
static void _configure_i2s(void)
{
	//! [setup_i2s_init]
	i2s_init(&i2s_instance, CONF_I2S_MODULE);
	//! [setup_i2s_init]

	//! [setup_clock_unit_config]
	struct i2s_clock_unit_config config_clock_unit;
	//! [setup_clock_unit_config]
	//! [setup_clock_unit_config_defaults]
	i2s_clock_unit_get_config_defaults(&config_clock_unit);
	//! [setup_clock_unit_config_defaults]

	//! [setup_clock_unit_change_config]
	config_clock_unit.clock.gclk_src = GCLK_GENERATOR_0;

	config_clock_unit.clock.mck_src = I2S_MASTER_CLOCK_SOURCE_GCLK;
	config_clock_unit.clock.mck_out_enable = true;
	config_clock_unit.clock.mck_out_div = 2;

	config_clock_unit.clock.sck_src = I2S_SERIAL_CLOCK_SOURCE_MCKDIV;
	config_clock_unit.clock.sck_div = 4;

	config_clock_unit.frame.number_slots = 2;
	config_clock_unit.frame.slot_size = I2S_SLOT_SIZE_32_BIT;
	config_clock_unit.frame.data_delay = I2S_DATA_DELAY_0;

	config_clock_unit.frame.frame_sync.source = I2S_FRAME_SYNC_SOURCE_SCKDIV;
	config_clock_unit.frame.frame_sync.width = I2S_FRAME_SYNC_WIDTH_HALF_FRAME;
	//! [setup_clock_unit_change_config]

	//! [setup_clock_unit_change_pins]
	config_clock_unit.mck_pin.enable = true;
	config_clock_unit.mck_pin.gpio = CONF_I2S_MCK_PIN;
	config_clock_unit.mck_pin.mux = CONF_I2S_MCK_MUX;

	config_clock_unit.sck_pin.enable = true;
	config_clock_unit.sck_pin.gpio = CONF_I2S_SCK_PIN;
	config_clock_unit.sck_pin.mux = CONF_I2S_SCK_MUX;

	config_clock_unit.fs_pin.enable = true;
	config_clock_unit.fs_pin.gpio = CONF_I2S_FS_PIN;
	config_clock_unit.fs_pin.mux = CONF_I2S_FS_MUX;
	//! [setup_clock_unit_change_pins]

	//! [setup_clock_unit_set_config]
	i2s_clock_unit_set_config(&i2s_instance, I2S_CLOCK_UNIT_0,
			&config_clock_unit);
	//! [setup_clock_unit_set_config]

	//! [setup_serializer_config]
	struct i2s_serializer_config config_serializer;
	//! [setup_serializer_config]
	//! [setup_serializer_config_defaults]
	i2s_serializer_get_config_defaults(&config_serializer);
	//! [setup_serializer_config_defaults]

	//! [setup_serializer_change_config_tx]
	config_serializer.clock_unit = I2S_CLOCK_UNIT_0;
	config_serializer.mode = I2S_SERIALIZER_TRANSMIT;
	config_serializer.data_size = I2S_DATA_SIZE_16BIT;
	//! [setup_serializer_change_config_tx]

	//! [setup_serializer_change_config_pin_tx]
	config_serializer.data_pin.enable = true;
	config_serializer.data_pin.gpio = CONF_I2S_SD_PIN;
	config_serializer.data_pin.mux = CONF_I2S_SD_MUX;
	//! [setup_serializer_change_config_pin_tx]

	//! [setup_serializer_set_config_tx]
	i2s_serializer_set_config(&i2s_instance, I2S_SERIALIZER_0,
			&config_serializer);
	//! [setup_serializer_set_config_tx]

	//! [setup_enable]
	i2s_enable(&i2s_instance);
	i2s_clock_unit_enable(&i2s_instance, I2S_CLOCK_UNIT_0);
	i2s_serializer_enable(&i2s_instance, I2S_SERIALIZER_0);
	//! [setup_enable]
}
Esempio n. 6
0
/**
 * \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!");
}