How to assing ESAI to HiFi4 core on i.MX8QXP

取消
显示结果 
显示  仅  | 搜索替代 
您的意思是: 

How to assing ESAI to HiFi4 core on i.MX8QXP

299 次查看
Ferromagnetic
Contributor II

Hello,

I struggling with bringing up audio drivers for CS42888 on HiFi4 on iMX8QXP-mek. I want to disable this sound card on Linux side and handling it on HiFi4. Can anyone help me with this issue? I using imx-audio-framework (https://github.com/nxp-imx/imx-audio-framework) and there are no examples with audio bypass in real-time, but there is ESAI driver using in renderer plugin but I am not sure if this code work. When I run decoder-renderer test on Linux, HiFi4 only decoding mp3 file but audio driver play music on Linux ( I can switch off HiFi4 during playing and still hear the music).

I write a code basing on renderer example but when the code is in ESAI initialization then HiFi4 hanging. I think that I should edit device tree to assing ESAI to HiFI4 and disable it on Linux but I have not too much experience with embedded Linux. Please help me with some advices etc. I would be gratefull.

This is my code for initialize ESAI:

破坏者
#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");
}
}
 

Regards

1 回复

264 次查看
JorgeCas
NXP TechSupport
NXP TechSupport

Hello, I hope you are doing well.

The NXP's related available information is on the Linux BSP/Android BSP documentation.

In the case of Tensilica® HiFi4, customers should obtain license, documentation and examples from Cadence directly.

Best regards.

0 项奖励