#define MODULE_TAG REALTIME_STREAMER
/*******************************************************************************
* Includes
******************************************************************************/
#include "osal-timer.h"
#include <stdio.h>
#include "xf-debug.h"
#include <string.h>
#include "mydefs.h"
#include "hardware.h"
#include "dsp_irq_handler.h"
#include "debug.h"
#include "realtimeStreamer.h"
#include "ipc.h"
/*******************************************************************************
* Local data definition
******************************************************************************/
typedef struct
{
/* ...input buffer pointer */
UWORD8 *input;
/* ...output buffer pointer */
UWORD8 *output;
uint32_t buffer_size;
/* ...size of PCM sample in bytes */
uint16_t sample_size;
/* ...number of channels */
uint16_t channels;
/* ...sample width in bits */
uint16_t pcm_width;
/* ...block length */
uint16_t block_length;
/* ...current sampling rate */
uint32_t rate;
void *dev_addr;
void *irqstr_addr;
uint32_t dev_Int;
uint32_t irq_2_dsp;
void *dma;
dmac_t *dmac[2];
} RealtimeStreamer;
/* Local functions */
static void init_realtimeStreamer(RealtimeStreamer *d);
static int esai_dma_init(RealtimeStreamer *d);
static void esai_rx_callback(void *arg);
/*******************************************************************************
* global variables
******************************************************************************/
RealtimeStreamer codec;
/* ...emulation of realtimeStreamer interrupt service routine */
static void esai_rx_callback(void *arg)
{
// bypass
memcpy(codec.output, codec.input, codec.buffer_size);
}
/* ...initialize hardware realtimeStreamer */
static int esai_dma_init(RealtimeStreamer *d)
{
struct dsp_main_struct *dsp;
dmac_cfg_t audio_cfg;
int dev_type;
dsp = get_main_struct();
dma_probe(dsp);
d->dma = dsp->dma_device;
dma_init(d->dma);
/* input buffer allocate */
xaf_malloc((void **)&d->input, d->buffer_size, 0);
/* output buffer allocate */
xaf_malloc((void **)&d->output, d->buffer_size, 0);
/*It is better to send address through the set_param */
d->dev_addr = (void *)ESAI_ADDR;
d->dev_Int = ESAI_INT;
d->irqstr_addr = (void *)IRQ_STR_ADDR;
d->irq_2_dsp = INT_NUM_IRQSTR_DSP_6;
/* dma channel configuration */
audio_cfg.period_len = d->buffer_size;
audio_cfg.period_count = 1;
audio_cfg.direction = DMA_DEV_TO_MEM;
audio_cfg.src_addr = (void *)(ESAI_ADDR + REG_ESAI_ERDR);
audio_cfg.dest_addr = (void *)d->input;
audio_cfg.callback = esai_rx_callback;
audio_cfg.comp = (void *)d;
audio_cfg.peripheral_config = NULL;
audio_cfg.peripheral_size = 0;
dev_type = EDMA_ESAI_RX;
d->dmac[0] = request_dma_chan(d->dma, dev_type);
if (!d->dmac[0])
return 1;
dma_chan_config(d->dmac[0], &audio_cfg);
audio_cfg.period_len = d->buffer_size;
audio_cfg.period_count = 1;
audio_cfg.direction = DMA_MEM_TO_DEV;
audio_cfg.src_addr = (void *)d->output;
audio_cfg.dest_addr = (void *)(ESAI_ADDR + REG_ESAI_ETDR);
audio_cfg.callback = NULL;
audio_cfg.comp = (void *)d;
audio_cfg.peripheral_config = NULL;
audio_cfg.peripheral_size = 0;
dev_type = EDMA_ESAI_TX;
d->dmac[1] = request_dma_chan(d->dma, dev_type);
if (!d->dmac[1])
return 1;
dma_chan_config(d->dmac[1], &audio_cfg);
irqstr_init(d->irqstr_addr, ESAI_INT, EDMA_ESAI_INT_NUM);
sendMsgToLinux("Before esai init");
esai_init(d->dev_addr, 1, d->channels, d->rate, d->pcm_width, 24576000); // problem here
sendMsgToLinux("ESAI init done");
xos_register_interrupt_handler(d->irq_2_dsp, (XosIntFunc *)xa_hw_comp_isr, 0);
sendMsgToLinux("inq handler register done");
xos_interrupt_enable(d->irq_2_dsp);
sendMsgToLinux("interrupt enabled");
/* Here initialize codec via I2C ... todo in linux app */
return 0;
}
static void init_realtimeStreamer(RealtimeStreamer *d)
{
/* ...pre-configuration initialization; reset internal data */
memset(d, 0, sizeof(*d));
/* ...set default codec parameters - 16-bit little-endian stereo @ 48KHz */
d->channels = 2U;
d->pcm_width = 16U;
d->rate = 48000U;
d->sample_size = 2U;
d->block_length = 64U;
d->buffer_size = (uint32_t)(d->block_length * d->sample_size * d->channels);
// hw init
esai_dma_init(d);
}
/*******************************************************************************
* API entry point
******************************************************************************/
void audioDrivers_init(void)
{
init_realtimeStreamer(&codec);
}
/* start HW operation */
void realtimeStreamer_start(void)
{
irqstr_start(codec.irqstr_addr, ESAI_INT, EDMA_ESAI_INT_NUM);
dma_chan_start(codec.dmac[0]);
dma_chan_start(codec.dmac[1]);
esai_start(codec.dev_addr, 1);
}
void delay_c(uint32_t cycles)
{
uint32_t i;
for(i=0; i<cycles; i++)
{
__asm__ __volatile__("nop");
}
}