544 lines
16 KiB
C
544 lines
16 KiB
C
|
|
#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;
|
|
}
|
|
|
|
|