first
This commit is contained in:
543
cpu/br28/audio_iis.c
Normal file
543
cpu/br28/audio_iis.c
Normal file
@ -0,0 +1,543 @@
|
||||
|
||||
#define IIS_TX_MIN_PNS (JL_ALNK0->LEN / 4)
|
||||
struct audio_iis_sync_node {
|
||||
void *hdl;
|
||||
struct list_head entry;
|
||||
};
|
||||
/***********************************************************
|
||||
* i2s 使用接口
|
||||
*
|
||||
***********************************************************/
|
||||
int audio_iis_buffered_frames(struct audio_iis_hdl *iis)
|
||||
{
|
||||
return (JL_ALNK0->LEN - *ALNK0_SHN[iis->hw_ch] - 1);
|
||||
}
|
||||
|
||||
int audio_iis_buffered_time(struct audio_iis_hdl *iis)
|
||||
{
|
||||
if (!iis) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int buffered_time = ((audio_iis_buffered_frames(iis) * 1000000) / iis->sample_rate) / 1000;
|
||||
|
||||
return buffered_time;
|
||||
}
|
||||
|
||||
int audio_iis_set_underrun_params(struct audio_iis_hdl *iis, int time, void *priv, void (*feedback)(void *))
|
||||
{
|
||||
local_irq_disable();
|
||||
iis->underrun_time = time;
|
||||
iis->underrun_pns = 0;
|
||||
iis->underrun_data = priv;
|
||||
iis->underrun_feedback = feedback;
|
||||
local_irq_enable();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void audio_iis_syncts_update_frame(struct audio_iis_hdl *iis)
|
||||
{
|
||||
struct audio_iis_sync_node *node;
|
||||
list_for_each_entry(node, &iis->sync_list, entry) {
|
||||
sound_pcm_enter_update_frame(node->hdl);
|
||||
}
|
||||
}
|
||||
|
||||
void audio_iis_syncts_latch_trigger(struct audio_iis_hdl *iis)
|
||||
{
|
||||
struct audio_iis_sync_node *node;
|
||||
|
||||
list_for_each_entry(node, &iis->sync_list, entry) {
|
||||
sound_pcm_syncts_latch_trigger(node->hdl);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void audio_iis_dma_update_to_syncts(struct audio_iis_hdl *iis, int frames)
|
||||
{
|
||||
struct audio_iis_sync_node *node;
|
||||
u8 have_syncts = 0;
|
||||
|
||||
list_for_each_entry(node, &iis->sync_list, entry) {
|
||||
sound_pcm_update_frame_num(node->hdl, frames);
|
||||
have_syncts = 1;
|
||||
}
|
||||
|
||||
if (have_syncts) {
|
||||
u16 free_points = *ALNK0_SHN[iis->hw_ch];
|
||||
int timeout = (1000000 / iis->sample_rate) * (clk_get("sys") / 1000000);
|
||||
while (free_points == *ALNK0_SHN[iis->hw_ch] && (--timeout > 0));
|
||||
}
|
||||
}
|
||||
|
||||
void audio_iis_add_syncts_handle(struct audio_iis_hdl *iis, void *syncts)
|
||||
{
|
||||
struct audio_iis_sync_node *node = (struct audio_iis_sync_node *)zalloc(sizeof(struct audio_iis_sync_node));
|
||||
node->hdl = syncts;
|
||||
|
||||
list_add(&node->entry, &iis->sync_list);
|
||||
|
||||
if (iis->state == SOUND_PCM_STATE_RUNNING) {
|
||||
sound_pcm_syncts_latch_trigger(syncts);
|
||||
}
|
||||
ALINK_DA2BTSRC_SEL(ALINK0, iis->hw_ch);
|
||||
}
|
||||
|
||||
void audio_iis_remove_syncts_handle(struct audio_iis_hdl *iis, void *syncts)
|
||||
{
|
||||
struct audio_iis_sync_node *node;
|
||||
|
||||
list_for_each_entry(node, &iis->sync_list, entry) {
|
||||
if (node->hdl == syncts) {
|
||||
goto remove_node;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
remove_node:
|
||||
|
||||
list_del(&node->entry);
|
||||
free(node);
|
||||
}
|
||||
|
||||
static void audio_iis_tx_irq_handler(struct audio_iis_hdl *iis)
|
||||
{
|
||||
if (iis->irq_trigger && iis->trigger_handler) {
|
||||
iis->trigger_handler(iis->trigger_data);
|
||||
iis->irq_trigger = 0;
|
||||
}
|
||||
|
||||
if (iis->underrun_pns) {
|
||||
int unread_frames = JL_ALNK0->LEN - *ALNK0_SHN[iis->hw_ch] - 1;
|
||||
if (unread_frames <= iis->underrun_pns) {
|
||||
//TODO
|
||||
} else {
|
||||
ALINK_OPNS_SET(ALINK0, iis->underrun_pns);
|
||||
ALINK_CLR_CHx_PND(ALINK0, iis->hw_ch);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ALINK_CHx_IE(ALINK0, iis->hw_ch, 0);
|
||||
ALINK_CLR_CHx_PND(ALINK0, iis->hw_ch);
|
||||
}
|
||||
|
||||
extern ALINK_PARM alink0_platform_data;
|
||||
int audio_iis_pcm_tx_open(struct audio_iis_hdl *iis, u8 ch, int sample_rate)
|
||||
{
|
||||
memset(iis, 0x0, sizeof(struct audio_iis_hdl));
|
||||
INIT_LIST_HEAD(&iis->sync_list);
|
||||
iis->state = SOUND_PCM_STATE_IDLE;
|
||||
iis->sample_rate = sample_rate;
|
||||
iis->alink0_param = alink_init(&alink0_platform_data);
|
||||
alink_channel_init(iis->alink0_param, ch, ALINK_DIR_TX, iis, audio_iis_tx_irq_handler);
|
||||
/*alink_start();*/
|
||||
iis->hw_ch = ch;
|
||||
}
|
||||
|
||||
void audio_iis_pcm_tx_close(struct audio_iis_hdl *iis)
|
||||
{
|
||||
alink_channel_close(iis->hw_ch);
|
||||
iis->state = SOUND_PCM_STATE_IDLE;
|
||||
}
|
||||
|
||||
int audio_iis_pcm_sample_rate(struct audio_iis_hdl *iis)
|
||||
{
|
||||
return iis->sample_rate;
|
||||
}
|
||||
|
||||
int audio_iis_set_delay_time(struct audio_iis_hdl *iis, int prepared_time, int delay_time)
|
||||
{
|
||||
iis->prepared_time = prepared_time;
|
||||
iis->delay_time = delay_time;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int audio_iis_pcm_remapping(struct audio_iis_hdl *iis, u8 mapping)
|
||||
{
|
||||
if (!iis->input_mapping) {
|
||||
iis->input_mapping = mapping;
|
||||
}
|
||||
if ((iis->input_mapping & SOUND_CHMAP_RL) || (iis->input_mapping & SOUND_CHMAP_RR)) {
|
||||
printf("Not support this channel map : 0x%x\n", mapping);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int audio_iis_pcm_channel_num(struct audio_iis_hdl *iis)
|
||||
{
|
||||
int num = 0;
|
||||
for (int i = 0; i < 2; i++) {
|
||||
if (iis->input_mapping & BIT(i)) {
|
||||
num++;
|
||||
}
|
||||
}
|
||||
return num;
|
||||
}
|
||||
|
||||
#if 0
|
||||
const unsigned char sin44K[88] ALIGNED(4) = {
|
||||
0x00, 0x00, 0x45, 0x0E, 0x41, 0x1C, 0xAA, 0x29, 0x3B, 0x36, 0xB2, 0x41, 0xD5, 0x4B, 0x6E, 0x54,
|
||||
0x51, 0x5B, 0x5A, 0x60, 0x70, 0x63, 0x82, 0x64, 0x8A, 0x63, 0x8E, 0x60, 0x9D, 0x5B, 0xD1, 0x54,
|
||||
0x4D, 0x4C, 0x3D, 0x42, 0xD5, 0x36, 0x50, 0x2A, 0xF1, 0x1C, 0xFB, 0x0E, 0xB7, 0x00, 0x70, 0xF2,
|
||||
0x6E, 0xE4, 0xFD, 0xD6, 0x60, 0xCA, 0xD9, 0xBE, 0xA5, 0xB4, 0xF7, 0xAB, 0xFC, 0xA4, 0xDA, 0x9F,
|
||||
0xAB, 0x9C, 0x7F, 0x9B, 0x5E, 0x9C, 0x3F, 0x9F, 0x19, 0xA4, 0xCE, 0xAA, 0x3D, 0xB3, 0x3A, 0xBD,
|
||||
0x92, 0xC8, 0x0A, 0xD5, 0x60, 0xE2, 0x50, 0xF0
|
||||
};
|
||||
|
||||
int read_44k_sine_data(void *buf, int bytes, int offset, u8 channel)
|
||||
{
|
||||
s16 *sine = (s16 *)sin44K;
|
||||
s16 *data = (s16 *)buf;
|
||||
int frame_len = (bytes >> 1) / channel;
|
||||
int sin44k_frame_len = sizeof(sin44K) / 2;
|
||||
int i, j;
|
||||
|
||||
offset = offset % sin44k_frame_len;
|
||||
|
||||
for (i = 0; i < frame_len; i++) {
|
||||
for (j = 0; j < channel; j++) {
|
||||
*data++ = sine[offset];
|
||||
}
|
||||
if (++offset >= sin44k_frame_len) {
|
||||
offset = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return i * 2 * channel;
|
||||
}
|
||||
static int frames_offset = 0;
|
||||
#endif
|
||||
|
||||
static int __audio_iis_pcm_write(s16 *dst, s16 *src, int frames, int remapping)
|
||||
{
|
||||
|
||||
/* int frame_bytes = read_44k_sine_data(dst, frames * 2 * 2, frames_offset, 2); */
|
||||
/* putchar('k'); */
|
||||
/* frames_offset += (frame_bytes >> 1) / 2; */
|
||||
/* return frame_bytes; */
|
||||
|
||||
if (remapping == 1) {
|
||||
for (int i = 0; i < frames; i++) {
|
||||
dst[i * 2] = src[i];
|
||||
dst[i * 2 + 1] = src[i];
|
||||
}
|
||||
return frames << 1;
|
||||
}
|
||||
|
||||
if (remapping == 2) {
|
||||
memcpy(dst, src, (frames << 1) * 2);
|
||||
return frames << 2;
|
||||
}
|
||||
|
||||
return frames;
|
||||
}
|
||||
|
||||
#define CVP_REF_SRC_ENABLE
|
||||
#ifdef CVP_REF_SRC_ENABLE
|
||||
#define CVP_REF_SRC_TASK_NAME "RefSrcTask"
|
||||
#include "Resample_api.h"
|
||||
#include "aec_user.h"
|
||||
|
||||
#define CVP_REF_SRC_FRAME_SIZE 512
|
||||
typedef struct {
|
||||
volatile u8 state;
|
||||
volatile u8 busy;
|
||||
RS_STUCT_API *sw_src_api;
|
||||
u8 *sw_src_buf;
|
||||
u16 input_rate;
|
||||
u16 output_rate;
|
||||
s16 ref_tmp_buf[CVP_REF_SRC_FRAME_SIZE / 2];
|
||||
cbuffer_t cbuf;
|
||||
u8 ref_buf[CVP_REF_SRC_FRAME_SIZE * 3];
|
||||
} aec_ref_src_t;
|
||||
static aec_ref_src_t *aec_ref_src = NULL;
|
||||
|
||||
extern void audio_aec_ref_src_get_output_rate(u16 *input_rate, u16 *output_rate);
|
||||
extern u8 bt_phone_dec_is_running();
|
||||
|
||||
extern struct audio_iis_hdl iis_hdl;
|
||||
void audio_aec_ref_src_run(s16 *data, int len)
|
||||
{
|
||||
u16 ref_len = 0;
|
||||
if (aec_ref_src) {
|
||||
if (iis_hdl.input_mapping != SOUND_CHMAP_MONO) {
|
||||
/*双变单*/
|
||||
for (int i = 0; i < (len >> 2); i++) {
|
||||
aec_ref_src->ref_tmp_buf[i] = data[2 * i];
|
||||
}
|
||||
len >>= 1;
|
||||
}
|
||||
/* audio_aec_ref_src_get_output_rate(&aec_ref_src->input_rate, &aec_ref_src->output_rate); */
|
||||
/* printf("%d %d \n",input_rate,output_rate); */
|
||||
if (aec_ref_src->sw_src_api) {
|
||||
/* aec_ref_src->sw_src_api->set_sr(aec_ref_src->sw_src_buf, aec_ref_src->output_rate); */
|
||||
ref_len = aec_ref_src->sw_src_api->run(aec_ref_src->sw_src_buf, aec_ref_src->ref_tmp_buf, len >> 1, aec_ref_src->ref_tmp_buf);
|
||||
ref_len <<= 1;
|
||||
}
|
||||
/* printf("ref_len %d", ref_len); */
|
||||
audio_aec_refbuf(aec_ref_src->ref_tmp_buf, ref_len);
|
||||
}
|
||||
}
|
||||
|
||||
static void audio_aec_ref_src_task(void *p)
|
||||
{
|
||||
int res;
|
||||
int msg[16];
|
||||
while (1) {
|
||||
|
||||
res = os_taskq_pend("taskq", msg, ARRAY_SIZE(msg));
|
||||
|
||||
if (aec_ref_src && aec_ref_src->state) {
|
||||
s16 *data = (int)msg[1];
|
||||
int len = msg[2];
|
||||
int rlen = 0;
|
||||
|
||||
aec_ref_src->busy = 1;
|
||||
if (cbuf_get_data_len(&aec_ref_src->cbuf) >= CVP_REF_SRC_FRAME_SIZE) {
|
||||
cbuf_read(&aec_ref_src->cbuf, aec_ref_src->ref_tmp_buf, CVP_REF_SRC_FRAME_SIZE);
|
||||
audio_aec_ref_src_run(aec_ref_src->ref_tmp_buf, CVP_REF_SRC_FRAME_SIZE);
|
||||
}
|
||||
aec_ref_src->busy = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int audio_aec_ref_src_data_fill(void *p, s16 *data, int len)
|
||||
{
|
||||
int ret = 0;
|
||||
if (aec_ref_src && aec_ref_src->state) {
|
||||
audio_aec_ref_start(1);
|
||||
if (0 == cbuf_write(&aec_ref_src->cbuf, data, len)) {
|
||||
/* cbuf_clear(&aec_ref_src->cbuf); */
|
||||
printf("ref src cbuf wfail!!");
|
||||
}
|
||||
if (cbuf_get_data_len(&aec_ref_src->cbuf) >= CVP_REF_SRC_FRAME_SIZE) {
|
||||
ret = os_taskq_post_msg(CVP_REF_SRC_TASK_NAME, 2, (int)data, len);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int audio_aec_ref_src_open(u32 insr, u32 outsr)
|
||||
{
|
||||
if (aec_ref_src) {
|
||||
printf("aec_ref_src alreadly open !!!");
|
||||
return -1;
|
||||
}
|
||||
aec_ref_src = zalloc(sizeof(aec_ref_src_t));
|
||||
if (aec_ref_src == NULL) {
|
||||
printf("aec_ref_src malloc fail !!!");
|
||||
return -1;
|
||||
}
|
||||
|
||||
cbuf_init(&aec_ref_src->cbuf, aec_ref_src->ref_buf, sizeof(aec_ref_src->ref_buf));
|
||||
int err = os_task_create(audio_aec_ref_src_task, NULL, 4, 256, 128, CVP_REF_SRC_TASK_NAME);
|
||||
if (err != OS_NO_ERR) {
|
||||
printf("task create error!");
|
||||
free(aec_ref_src);
|
||||
aec_ref_src = NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* audio_aec_ref_src_get_output_rate(&aec_ref_src->input_rate, &aec_ref_src->output_rate); */
|
||||
aec_ref_src->input_rate = insr;
|
||||
aec_ref_src->output_rate = outsr;
|
||||
aec_ref_src->sw_src_api = get_rs16_context();
|
||||
printf("sw_src_api:0x%x\n", aec_ref_src->sw_src_api);
|
||||
ASSERT(aec_ref_src->sw_src_api);
|
||||
int sw_src_need_buf = aec_ref_src->sw_src_api->need_buf();
|
||||
printf("sw_src_buf:%d\n", sw_src_need_buf);
|
||||
aec_ref_src->sw_src_buf = zalloc(sw_src_need_buf);
|
||||
ASSERT(aec_ref_src->sw_src_buf, "sw_src_buf zalloc fail");
|
||||
RS_PARA_STRUCT rs_para_obj;
|
||||
rs_para_obj.nch = 1;
|
||||
if (insr == 44100) {
|
||||
rs_para_obj.new_insample = 44117;
|
||||
} else {
|
||||
rs_para_obj.new_insample = insr;
|
||||
}
|
||||
rs_para_obj.new_outsample = outsr;
|
||||
printf("sw src,ch = %d, in = %d,out = %d\n", rs_para_obj.nch, rs_para_obj.new_insample, rs_para_obj.new_outsample);
|
||||
aec_ref_src->sw_src_api->open(aec_ref_src->sw_src_buf, &rs_para_obj);
|
||||
|
||||
aec_ref_src->state = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void audio_aec_ref_src_close()
|
||||
{
|
||||
if (aec_ref_src) {
|
||||
aec_ref_src->state = 0;
|
||||
while (aec_ref_src->busy) {
|
||||
putchar('w');
|
||||
os_time_dly(1);
|
||||
}
|
||||
int err = os_task_del(CVP_REF_SRC_TASK_NAME);
|
||||
if (err) {
|
||||
log_i("kill task %s: err=%d\n", CVP_REF_SRC_TASK_NAME, err);
|
||||
}
|
||||
if (aec_ref_src->sw_src_api) {
|
||||
aec_ref_src->sw_src_api = NULL;
|
||||
}
|
||||
if (aec_ref_src->sw_src_buf) {
|
||||
free(aec_ref_src->sw_src_buf);
|
||||
aec_ref_src->sw_src_buf = NULL;
|
||||
}
|
||||
free(aec_ref_src);
|
||||
aec_ref_src = NULL;
|
||||
}
|
||||
}
|
||||
#endif/*CVP_REF_SRC_ENABLE*/
|
||||
|
||||
int audio_iis_pcm_write(struct audio_iis_hdl *iis, void *data, int len)
|
||||
{
|
||||
if (iis->state != SOUND_PCM_STATE_RUNNING) {
|
||||
return 0;
|
||||
}
|
||||
int remapping_ch = 2;
|
||||
int frames = 0;
|
||||
if (iis->input_mapping == SOUND_CHMAP_MONO) {
|
||||
frames = len >> 1;
|
||||
remapping_ch = 1;
|
||||
} else if (iis->input_mapping & SOUND_CHMAP_FR) {
|
||||
frames = len >> 2;
|
||||
remapping_ch = 2;
|
||||
} else {
|
||||
|
||||
}
|
||||
|
||||
s16 *ref_data = (s16 *)data;
|
||||
int swp = *ALNK0_SWPTR[iis->hw_ch];
|
||||
int free_frames = *ALNK0_SHN[iis->hw_ch] - iis->reserved_frames;
|
||||
|
||||
/* printf("free : %d, %d\n", *ALNK0_SHN[iis->hw_ch], free_frames); */
|
||||
if (free_frames <= 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (free_frames > frames) {
|
||||
free_frames = frames;
|
||||
}
|
||||
|
||||
frames = 0;
|
||||
if (swp + free_frames > JL_ALNK0->LEN) {
|
||||
frames = JL_ALNK0->LEN - swp;
|
||||
__audio_iis_pcm_write((s16 *)(*ALNK0_BUF_ADR[iis->hw_ch] + swp * 2 * 2), (s16 *)data, frames, remapping_ch);
|
||||
free_frames -= frames;
|
||||
data = (s16 *)data + frames * remapping_ch;
|
||||
swp = 0;
|
||||
}
|
||||
|
||||
__audio_iis_pcm_write((s16 *)(*ALNK0_BUF_ADR[iis->hw_ch] + swp * 2 * 2), (s16 *)data, free_frames, remapping_ch);
|
||||
frames += free_frames;
|
||||
|
||||
audio_iis_syncts_update_frame(iis);
|
||||
*ALNK0_SHN[iis->hw_ch] = frames;
|
||||
__asm_csync();
|
||||
audio_iis_dma_update_to_syncts(iis, frames);
|
||||
|
||||
/*printf("frames : %d\n", frames);*/
|
||||
/*printf("CLK CON2 : %d, %d\n", JL_CLOCK->CLK_CON2 & 0x3, (JL_CLOCK->CLK_CON2 >> 2) & 0x3);*/
|
||||
|
||||
#ifdef CVP_REF_SRC_ENABLE
|
||||
if (bt_phone_dec_is_running()) {
|
||||
audio_aec_ref_src_data_fill(iis, ref_data, (frames << 1) * remapping_ch);
|
||||
}
|
||||
#endif
|
||||
return (frames << 1) * remapping_ch;
|
||||
}
|
||||
|
||||
static void audio_iis_dma_fifo_start(struct audio_iis_hdl *iis)
|
||||
{
|
||||
if (iis->state != SOUND_PCM_STATE_PREPARED) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (iis->prepared_frames) {
|
||||
*ALNK0_SHN[iis->hw_ch] = iis->prepared_frames;
|
||||
__asm_csync();
|
||||
}
|
||||
|
||||
local_irq_disable();
|
||||
iis->state = SOUND_PCM_STATE_RUNNING;
|
||||
ALINK_CHx_IE(ALINK0, iis->hw_ch, 1);
|
||||
ALINK_CLR_CHx_PND(ALINK0, iis->hw_ch);
|
||||
local_irq_enable();
|
||||
audio_iis_syncts_latch_trigger(iis);
|
||||
}
|
||||
|
||||
static int audio_iis_fifo_set_delay(struct audio_iis_hdl *iis)
|
||||
{
|
||||
iis->prepared_frames = iis->prepared_time * iis->sample_rate / 1000;
|
||||
int delay_frames = (iis->delay_time * iis->sample_rate) / 1000 / 2 * 2;
|
||||
if (iis->prepared_frames >= JL_ALNK0->LEN) {
|
||||
iis->prepared_frames = JL_ALNK0->LEN / 2;
|
||||
}
|
||||
if (delay_frames < JL_ALNK0->LEN) {
|
||||
iis->reserved_frames = JL_ALNK0->LEN - delay_frames;
|
||||
} else {
|
||||
iis->reserved_frames = 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int audio_iis_trigger_interrupt(struct audio_iis_hdl *iis, int time_ms, void *priv, void (*callback)(void *))
|
||||
{
|
||||
if (iis->state != SOUND_PCM_STATE_RUNNING) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
int irq_frames = time_ms * iis->sample_rate / 1000;
|
||||
int pns = audio_iis_buffered_frames(iis) - irq_frames;
|
||||
if (pns < irq_frames) {
|
||||
sys_hi_timeout_add(priv, callback, time_ms);
|
||||
return -EINVAL;
|
||||
}
|
||||
local_irq_disable();
|
||||
if (pns > ALINK_OPNS(ALINK0)) {
|
||||
ALINK_OPNS_SET(ALINK0, pns);
|
||||
}
|
||||
|
||||
iis->irq_trigger = 1;
|
||||
iis->trigger_handler = callback;
|
||||
iis->trigger_data = priv;
|
||||
ALINK_CHx_IE(ALINK0, iis->hw_ch, 1);
|
||||
local_irq_enable();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int audio_iis_dma_start(struct audio_iis_hdl *iis)
|
||||
{
|
||||
if (iis->state == SOUND_PCM_STATE_RUNNING) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
audio_iis_fifo_set_delay(iis);
|
||||
iis->underrun_pns = iis->underrun_time ? (iis->underrun_time * iis->sample_rate / 1000) : 0;
|
||||
ALINK_OPNS_SET(ALINK0, (iis->underrun_pns ? iis->underrun_pns : IIS_TX_MIN_PNS));
|
||||
iis->state = SOUND_PCM_STATE_PREPARED;
|
||||
/* printf("DMA : %d, %d, %d\n", *ALNK0_SHN[iis->hw_ch], *ALNK0_SWPTR[iis->hw_ch], *ALNK0_HWPTR[iis->hw_ch]); */
|
||||
audio_iis_dma_fifo_start(iis);
|
||||
alink_start(iis->alink0_param);
|
||||
/* printf("[iis dma start]... %d, free : %d, prepared_frames : %d, reserved_frames : %d\n", JL_ALNK0->LEN, *ALNK0_SHN[iis->hw_ch], iis->prepared_frames, iis->reserved_frames); */
|
||||
}
|
||||
|
||||
int audio_iis_dma_stop(struct audio_iis_hdl *iis)
|
||||
{
|
||||
if (iis->state != SOUND_PCM_STATE_RUNNING) {
|
||||
return 0;
|
||||
}
|
||||
/*audio_iis_buffered_frames_fade_out(iis, JL_ALNK0->LEN - *ALNK0_SHN[iis->hw_ch] - 1);*/
|
||||
ALINK_CHx_IE(ALINK0, iis->hw_ch, 0);
|
||||
ALINK_CLR_CHx_PND(ALINK0, iis->hw_ch);
|
||||
/* alink_uninit(iis->alink0_param); */
|
||||
|
||||
iis->input_mapping = 0;
|
||||
iis->state = SOUND_PCM_STATE_SUSPENDED;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user