You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

3151 lines
79 KiB

/*
* Copyright (c) Hisilicon Technologies Co., Ltd. 2019-2019. All rights reserved.
* Description: MPI function file for Huanglong audio output
* Author: audio
* Create: 2019-05-30
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <string.h>
#include <unistd.h>
#include <stdint.h>
#include <sys/poll.h>
#include <pthread.h>
#include "mpi_ao_debug.h"
#include "mpi_ao.h"
#include "securec.h"
#include "mpi_memory_ext.h"
#include "mpi_ao_ext.h"
#include "mpi_ao_vir.h"
#include "mpi_ao_lowlatency.h"
#include "mpi_ao_effect.h"
#include "mpi_ao_plugin.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif
#endif /* __cplusplus */
static td_s32 g_ao_fd = -1;
#define SOC_DEV_AO_NAME "soc_ao"
#define DEVNAME_AO "/dev/" SOC_DEV_AO_NAME
static td_u32 g_ao_init_cnt = 0;
static pthread_mutex_t g_ao_mutex = PTHREAD_MUTEX_INITIALIZER;
static td_handle g_ad_master_track = TD_NULL;
static td_handle g_ad_slave_track = TD_NULL;
#define ao_lock(ao_mutex) \
do { \
(td_void)pthread_mutex_lock(&(ao_mutex)); \
} while (0)
#define ao_unlock(ao_mutex) \
do { \
(td_void)pthread_mutex_unlock(&(ao_mutex)); \
} while (0)
static ext_ao_ext_module_info g_ao_ext_modules[] = {
{
.module_id = SOC_ID_AVPLAY,
{
.attach = TD_NULL,
.detach = TD_NULL,
},
},
{
.module_id = SOC_ID_AI,
{
.attach = TD_NULL,
.detach = TD_NULL,
},
},
};
td_s32 ext_mpi_ao_register_extern_func(const td_u32 module_id, const ext_ao_ext_module_fn *func)
{
td_u32 i;
check_ao_null_ptr(func);
for (i = 0; i < sizeof(g_ao_ext_modules) / sizeof(g_ao_ext_modules[0]); i++) {
if (g_ao_ext_modules[i].module_id != module_id) {
continue;
}
ao_lock(g_ao_mutex);
g_ao_ext_modules[i].func.attach = func->attach;
g_ao_ext_modules[i].func.detach = func->detach;
ao_unlock(g_ao_mutex);
return TD_SUCCESS;
}
return SOC_ERR_AO_INVALID_PARA;
}
td_s32 ext_mpi_ao_unregister_extern_func(const td_u32 module_id)
{
td_u32 i;
for (i = 0; i < sizeof(g_ao_ext_modules) / sizeof(g_ao_ext_modules[0]); i++) {
if (g_ao_ext_modules[i].module_id != module_id) {
continue;
}
ao_lock(g_ao_mutex);
g_ao_ext_modules[i].func.attach = TD_NULL;
g_ao_ext_modules[i].func.detach = TD_NULL;
ao_unlock(g_ao_mutex);
return TD_SUCCESS;
}
return SOC_ERR_AO_INVALID_PARA;
}
td_s32 ext_mpi_ao_get_extern_func(const td_u32 module_id, ext_ao_ext_module_fn *func)
{
td_u32 i;
check_ao_null_ptr(func);
for (i = 0; i < sizeof(g_ao_ext_modules) / sizeof(g_ao_ext_modules[0]); i++) {
if (g_ao_ext_modules[i].module_id != module_id) {
continue;
}
ao_lock(g_ao_mutex);
func->attach = g_ao_ext_modules[i].func.attach;
func->detach = g_ao_ext_modules[i].func.detach;
ao_unlock(g_ao_mutex);
return TD_SUCCESS;
}
return SOC_ERR_AO_INVALID_PARA;
}
static td_s32 create_ad_track(td_handle track)
{
td_s32 ret;
td_handle track_ad = TD_INVALID_HANDLE;
ext_ao_track_attr attr = { 0 };
ret = ext_mpi_ao_track_get_default_open_attr(EXT_AO_TRACK_TYPE_SLAVE, &attr);
if (ret != TD_SUCCESS) {
soc_log_err("get_default_open_attr failed\n");
return ret;
}
ret = ext_mpi_ao_track_create(AO_SND_0, &attr, &track_ad);
if (ret != TD_SUCCESS) {
soc_log_err("create ad track failed\n");
return ret;
}
g_ad_master_track = track;
g_ad_slave_track = track_ad;
ret = ext_mpi_ao_track_start(g_ad_slave_track);
if (ret != TD_SUCCESS) {
soc_log_err("ext_mpi_ao_track_track for AD start failed(%x).\n", ret);
return ret;
}
return TD_SUCCESS;
}
static td_s32 destroy_ad_track(td_handle track)
{
td_s32 ret;
check_ao_track_id(track);
if (track != g_ad_master_track) {
soc_log_err("track is not AD track\n");
return TD_FAILURE;
}
if (g_ad_slave_track != TD_NULL) {
ret = ext_mpi_ao_track_destroy(g_ad_slave_track);
if (ret != TD_SUCCESS) {
soc_log_err("ext_mpi_ao_track_destroy failed\n");
return ret;
}
g_ad_master_track = TD_NULL;
g_ad_slave_track = TD_NULL;
} else {
soc_log_err("set AD disable before this\n");
}
return TD_SUCCESS;
}
static td_void audio_iapi_frame_to_drv_frame(const ext_ao_frame *iapi_frame, ao_frame *drv_frame)
{
drv_frame->pts = iapi_frame->pts;
drv_frame->bit_depth = iapi_frame->bit_depth;
drv_frame->interleaved = iapi_frame->interleaved;
drv_frame->sample_rate = iapi_frame->sample_rate;
drv_frame->channels = iapi_frame->channels;
drv_frame->frame_index = iapi_frame->frame_index;
drv_frame->pcm_samples = iapi_frame->pcm_samples;
drv_frame->bits_bytes = iapi_frame->bits_bytes;
drv_frame->md_and_obj_bytes = iapi_frame->md_and_obj_bytes;
drv_frame->iec_data_type = iapi_frame->iec_data_type;
drv_frame->pcm_buffer = (td_u64)(uintptr_t)iapi_frame->pcm_buffer;
drv_frame->bits_buffer = (td_u64)(uintptr_t)iapi_frame->bits_buffer;
drv_frame->md_and_obj_buffer = (td_u64)(uintptr_t)iapi_frame->md_and_obj_buffer;
}
static td_void audio_drv_frame_to_iapi_frame(const ao_frame *drv_frame, ext_ao_frame *iapi_frame)
{
iapi_frame->pts = drv_frame->pts;
iapi_frame->bit_depth = drv_frame->bit_depth;
iapi_frame->interleaved = drv_frame->interleaved;
iapi_frame->sample_rate = drv_frame->sample_rate;
iapi_frame->channels = drv_frame->channels;
iapi_frame->frame_index = drv_frame->frame_index;
iapi_frame->pcm_samples = drv_frame->pcm_samples;
iapi_frame->bits_bytes = drv_frame->bits_bytes;
iapi_frame->iec_data_type = drv_frame->iec_data_type;
iapi_frame->pcm_buffer = TD_NULL;
iapi_frame->bits_buffer = TD_NULL;
}
td_s32 ext_mpi_ao_init(td_void)
{
ao_lock(g_ao_mutex);
if (g_ao_init_cnt != 0) {
g_ao_init_cnt++;
ao_unlock(g_ao_mutex);
return TD_SUCCESS;
}
if (g_ao_fd < 0) {
g_ao_fd = open(DEVNAME_AO, O_RDWR, 0);
if (g_ao_fd < 0) {
soc_log_fatal("open_ao_device err\n");
g_ao_fd = -1;
ao_unlock(g_ao_mutex);
return SOC_ERR_AO_CREATE_FAIL;
}
}
vir_init_rs();
ext_mpi_ao_aef_init();
g_ao_init_cnt++;
ao_unlock(g_ao_mutex);
return TD_SUCCESS;
}
td_s32 ext_mpi_ao_de_init(td_void)
{
td_s32 ret;
ao_lock(g_ao_mutex);
if (g_ao_init_cnt == 0) {
ao_unlock(g_ao_mutex);
return TD_SUCCESS;
}
g_ao_init_cnt--;
if (g_ao_init_cnt == 0) {
if (g_ao_fd >= 0) {
ret = close(g_ao_fd);
if (ret != TD_SUCCESS) {
soc_err_print_call_fun_err(close, ret);
soc_err_print_s32(g_ao_fd);
}
g_ao_fd = -1;
}
ext_mpi_ao_aef_deinit();
vir_de_init_rs();
}
ao_unlock(g_ao_mutex);
return TD_SUCCESS;
}
td_s32 mpi_ao_get_fd(td_void)
{
td_s32 fd;
ao_lock(g_ao_mutex);
if ((g_ao_init_cnt == 0) || (g_ao_fd < 0)) {
fd = -1;
} else {
fd = g_ao_fd;
}
ao_unlock(g_ao_mutex);
return fd;
}
td_s32 ext_mpi_ao_snd_get_default_open_attr(const ao_snd_id sound, ext_ao_attr *attr)
{
td_s32 ret;
ao_snd_open_default_param default_param = {
.sound = sound,
};
check_ao_null_ptr(attr);
ret = ioctl(g_ao_fd, CMD_AO_GETSNDDEFOPENATTR, &default_param);
if (ret != TD_SUCCESS) {
soc_log_err("ioctl CMD_AO_GETSNDDEFOPENATTR failed(0x%x)\n", ret);
return ret;
}
ret = memcpy_s(attr, sizeof(*attr), &default_param.attr, sizeof(ext_ao_attr));
if (ret != EOK) {
soc_log_err("memcpy_s failed(0x%x)\n", ret);
return ret;
}
return TD_SUCCESS;
}
td_s32 ext_mpi_ao_snd_open(const ao_snd_id sound, const ext_ao_attr *attr)
{
td_s32 ret;
ao_snd_open_param snd = {
.sound = sound,
};
check_ao_null_ptr(attr);
ret = memcpy_s(&snd.attr, sizeof(ext_ao_attr), attr, sizeof(*attr));
if (ret != EOK) {
soc_log_err("memcpy_s failed(0x%x)\n", ret);
return ret;
}
return ioctl(g_ao_fd, CMD_AO_SND_OPEN, &snd);
}
td_s32 ext_mpi_ao_snd_close(const ao_snd_id sound)
{
return ioctl(g_ao_fd, CMD_AO_SND_CLOSE, &sound);
}
td_s32 ext_mpi_ao_snd_set_mute(const ao_snd_id sound, const ext_ao_port port, const td_bool mute)
{
ao_snd_mute_param mute_param = {
.sound = sound,
.out_port = port,
.mute = mute,
};
return ioctl(g_ao_fd, CMD_AO_SND_SETMUTE, &mute_param);
}
td_s32 ext_mpi_ao_snd_get_mute(const ao_snd_id sound, const ext_ao_port port, td_bool *mute)
{
td_s32 ret;
ao_snd_mute_param mute_param = {
.sound = sound,
.out_port = port,
.mute = TD_FALSE,
};
check_ao_null_ptr(mute);
ret = ioctl(g_ao_fd, CMD_AO_SND_GETMUTE, &mute_param);
if (ret != TD_SUCCESS) {
soc_log_err("ioctl CMD_AO_SND_GETMUTE failed\n");
soc_err_print_err_code(ret);
return ret;
}
*mute = mute_param.mute;
return TD_SUCCESS;
}
td_s32 ext_mpi_ao_snd_set_soft_mute(const ao_snd_id sound, const ext_ao_port port, const td_bool mute)
{
ao_snd_mute_param mute_param = {
.sound = sound,
.out_port = port,
.mute = mute,
};
return ioctl(g_ao_fd, CMD_AO_SND_SET_SOFTMUTE, &mute_param);
}
td_s32 ext_mpi_ao_snd_get_soft_mute(const ao_snd_id sound, const ext_ao_port port, td_bool *mute)
{
td_s32 ret;
ao_snd_mute_param mute_param = {
.sound = sound,
.out_port = port,
.mute = TD_FALSE,
};
check_ao_null_ptr(mute);
ret = ioctl(g_ao_fd, CMD_AO_SND_GET_SOFTMUTE, &mute_param);
if (ret != TD_SUCCESS) {
soc_log_err("ioctl CMD_AO_SND_GETMUTE failed\n");
soc_err_print_err_code(ret);
return ret;
}
*mute = mute_param.mute;
return TD_SUCCESS;
}
td_s32 ext_mpi_ao_snd_set_output_mode(const ao_snd_id sound,
const ext_ao_port port, const ext_ao_ouput_mode mode)
{
ao_snd_output_mode_param param = {
.sound = sound,
.ao_port = port,
.mode = mode,
};
return ioctl(g_ao_fd, CMD_AO_SND_SETOUTPUTMODE, &param);
}
td_s32 ext_mpi_ao_snd_get_output_mode(const ao_snd_id sound,
const ext_ao_port port, ext_ao_ouput_mode *mode)
{
td_s32 ret;
ao_snd_output_mode_param param = {
.sound = sound,
.ao_port = port,
.mode = EXT_AO_OUTPUT_MODE_MAX,
};
check_ao_null_ptr(mode);
ret = ioctl(g_ao_fd, CMD_AO_SND_GETOUTPUTMODE, &param);
if (ret != TD_SUCCESS) {
soc_log_err("ioctl CMD_AO_SND_GETOUTPUTMODE failed\n");
soc_err_print_err_code(ret);
return ret;
}
*mode = param.mode;
return TD_SUCCESS;
}
td_s32 ext_mpi_ao_snd_set_volume(const ao_snd_id sound, const ext_ao_port port, const ext_ao_gain *gain)
{
td_s32 ret;
ao_snd_volume_param volume = {
.sound = sound,
.out_port = port,
};
check_ao_null_ptr(gain);
ret = memcpy_s(&volume.gain, sizeof(ext_ao_gain), gain, sizeof(*gain));
if (ret != EOK) {
soc_log_err("memcpy_s failed(0x%x)\n", ret);
return ret;
}
ret = ioctl(g_ao_fd, CMD_AO_SND_SETVOLUME, &volume);
if (ret != TD_SUCCESS) {
soc_log_err("ioctl CMD_AO_SND_SETVOLUME failed(0x%x)", ret);
return ret;
}
return TD_SUCCESS;
}
td_s32 ext_mpi_ao_snd_get_volume(ao_snd_id sound, ext_ao_port port, ext_ao_gain *gain)
{
td_s32 ret;
ao_snd_volume_param volume = {
.sound = sound,
.out_port = port,
};
check_ao_null_ptr(gain);
ret = ioctl(g_ao_fd, CMD_AO_SND_GETVOLUME, &volume);
if (ret != TD_SUCCESS) {
soc_log_err("ioctl CMD_AO_SND_GETVOLUME failed(0x%x)", ret);
return ret;
}
ret = memcpy_s(gain, sizeof(*gain), &volume.gain, sizeof(ext_ao_gain));
if (ret != EOK) {
soc_log_err("memcpy_s failed(0x%x)\n", ret);
return ret;
}
return TD_SUCCESS;
}
td_s32 ext_mpi_ao_snd_set_spdif_category_code(ao_snd_id sound, ext_ao_port port,
ext_ao_spdif_category_code spdif_category_code)
{
ao_snd_spdif_category_code_param param = {
.sound = sound,
.out_port = port,
.category_code = spdif_category_code,
};
return ioctl(g_ao_fd, CMD_AO_SND_SETSPDIFCATEGORYCODE, &param);
}
td_s32 ext_mpi_ao_snd_get_spdif_category_code(ao_snd_id sound, ext_ao_port port,
ext_ao_spdif_category_code *spdif_category_code)
{
td_s32 ret;
ao_snd_spdif_category_code_param param = {
.sound = sound,
.out_port = port,
.category_code = EXT_AO_SPDIF_CATEGORY_MAX,
};
check_ao_null_ptr(spdif_category_code);
ret = ioctl(g_ao_fd, CMD_AO_SND_GETSPDIFCATEGORYCODE, &param);
if (ret != TD_SUCCESS) {
soc_log_err("ioctl CMD_AO_SND_GETSPDIFCATEGORYCODE failed\n");
soc_err_print_err_code(ret);
return ret;
}
*spdif_category_code = param.category_code;
return TD_SUCCESS;
}
td_s32 ext_mpi_ao_snd_set_spdif_scms_mode(ao_snd_id sound, ext_ao_port port, ext_ao_spdif_scms_mode spdif_scms_mode)
{
ao_snd_spdif_scms_mode_param param = {
.sound = sound,
.out_port = port,
.scms_mode = spdif_scms_mode,
};
return ioctl(g_ao_fd, CMD_AO_SND_SETSPDIFSCMSMODE, &param);
}
td_s32 ext_mpi_ao_snd_get_spdif_scms_mode(ao_snd_id sound, ext_ao_port port, ext_ao_spdif_scms_mode *spdif_scms_mode)
{
td_s32 ret;
ao_snd_spdif_scms_mode_param param = {
.sound = sound,
.out_port = port,
.scms_mode = EXT_AO_SPDIF_SCMS_MODE_MAX,
};
check_ao_null_ptr(spdif_scms_mode);
ret = ioctl(g_ao_fd, CMD_AO_SND_GETSPDIFSCMSMODE, &param);
if (ret != TD_SUCCESS) {
soc_log_err("ioctl CMD_AO_SND_GETSPDIFSCMSMODE failed\n");
soc_err_print_err_code(ret);
return ret;
}
*spdif_scms_mode = param.scms_mode;
return TD_SUCCESS;
}
td_s32 ext_mpi_ao_snd_set_track_mode(ao_snd_id sound, ext_ao_port port, ext_track_mode mode)
{
ao_snd_track_mode_param track_mode = {
.sound = sound,
.out_port = port,
.mode = mode,
};
return ioctl(g_ao_fd, CMD_AO_SND_SETTRACKMODE, &track_mode);
}
td_s32 ext_mpi_ao_snd_get_track_mode(ao_snd_id sound, ext_ao_port port, ext_track_mode *mode)
{
td_s32 ret;
ao_snd_track_mode_param track_mode = {
.sound = sound,
.out_port = port,
.mode = EXT_TRACK_MODE_MAX,
};
check_ao_null_ptr(mode);
ret = ioctl(g_ao_fd, CMD_AO_SND_GETTRACKMODE, &track_mode);
if (ret != TD_SUCCESS) {
soc_log_err("ioctl CMD_AO_SND_GETTRACKMODE failed\n");
soc_err_print_err_code(ret);
return ret;
}
*mode = track_mode.mode;
return TD_SUCCESS;
}
td_s32 ext_mpi_ao_snd_get_xrun_count(ao_snd_id sound, td_u32 *count)
{
td_s32 ret;
ao_snd_get_xrun_param xun_param = {
.sound = sound,
.count = 0,
};
check_ao_null_ptr(count);
ret = ioctl(g_ao_fd, CMD_AO_SND_GETXRUNCOUNT, &xun_param);
if (ret != TD_SUCCESS) {
soc_log_err("ioctl CMD_AO_SND_GETXRUNCOUNT failed\n");
soc_err_print_err_code(ret);
return ret;
}
*count = xun_param.count;
return TD_SUCCESS;
}
td_s32 ext_mpi_ao_snd_set_all_track_mute(ao_snd_id sound, td_bool mute)
{
ao_snd_all_track_mute_param all_track_mute = {
.sound = sound,
.mute = mute,
};
return ioctl(g_ao_fd, CMD_AO_SND_SETALLTRACKMUTE, &all_track_mute);
}
td_s32 ext_mpi_ao_snd_get_all_track_mute(ao_snd_id sound, td_bool *mute)
{
td_s32 ret;
ao_snd_all_track_mute_param all_track_mute = {
.sound = sound,
.mute = TD_FALSE,
};
check_ao_null_ptr(mute);
ret = ioctl(g_ao_fd, CMD_AO_SND_GETALLTRACKMUTE, &all_track_mute);
if (ret != TD_SUCCESS) {
soc_log_err("ioctl CMD_AO_SND_GETALLTRACKMUTE failed\n");
soc_err_print_err_code(ret);
return ret;
}
*mute = all_track_mute.mute;
return TD_SUCCESS;
}
td_s32 ext_mpi_ao_snd_set_low_latency(ao_snd_id sound, ext_ao_port port, td_u32 latecny_ms)
{
ao_snd_set_low_latency_param low_latency_param = {
.sound = sound,
.out_port = port,
.latency_ms = latecny_ms,
};
return ioctl(g_ao_fd, CMD_AO_SND_SETLOWLATENCY, &low_latency_param);
}
td_s32 ext_mpi_ao_snd_get_low_latency(ao_snd_id sound, ext_ao_port port, td_u32 *latecny_ms)
{
td_s32 ret;
ao_snd_set_low_latency_param low_latency_param = {
.sound = sound,
.out_port = port,
.latency_ms = 0,
};
check_ao_null_ptr(latecny_ms);
ret = ioctl(g_ao_fd, CMD_AO_SND_GETLOWLATENCY, &low_latency_param);
if (ret == TD_SUCCESS) {
*latecny_ms = low_latency_param.latency_ms;
}
return ret;
}
td_s32 ext_mpi_ao_snd_set_precision_volume(ao_snd_id sound, ext_ao_port port, const ext_ao_preci_gain *gain)
{
td_s32 ret;
ao_snd_preci_volume_param preci_vol = {
.sound = sound,
.out_port = port,
};
check_ao_null_ptr(gain);
ret = memcpy_s(&preci_vol.preci_gain, sizeof(ext_ao_preci_gain), gain, sizeof(*gain));
if (ret != EOK) {
soc_log_err("memcpy_s failed(0x%x)\n", ret);
return ret;
}
ret = ioctl(g_ao_fd, CMD_AO_SND_SETPRECIVOL, &preci_vol);
if (ret != TD_SUCCESS) {
soc_log_err("ioctl CMD_AO_SND_SETPRECIVOL failed(0x%x)", ret);
return ret;
}
return TD_SUCCESS;
}
td_s32 ext_mpi_ao_snd_get_precision_volume(ao_snd_id sound, ext_ao_port port, ext_ao_preci_gain *preci_gain)
{
td_s32 ret;
ao_snd_preci_volume_param preci_vol = {
.sound = sound,
.out_port = port,
};
check_ao_null_ptr(preci_gain);
ret = ioctl(g_ao_fd, CMD_AO_SND_GETPRECIVOL, &preci_vol);
if (ret != TD_SUCCESS) {
soc_log_err("ioctl CMD_AO_SND_GETPRECIVOL failed(0x%x)", ret);
return ret;
}
ret = memcpy_s(preci_gain, sizeof(*preci_gain), &preci_vol.preci_gain, sizeof(ext_ao_preci_gain));
if (ret != EOK) {
soc_log_err("memcpy_s failed(0x%x)\n", ret);
return ret;
}
return TD_SUCCESS;
}
td_s32 ext_mpi_ao_snd_set_balance(ao_snd_id sound, ext_ao_port out_port, td_s32 balance)
{
ao_snd_balance_param balance_param = {
.sound = sound,
.out_port = out_port,
.balance = balance,
};
return ioctl(g_ao_fd, CMD_AO_SND_SETBALANCE, &balance_param);
}
td_s32 ext_mpi_ao_snd_get_balance(ao_snd_id sound, ext_ao_port out_port, td_s32 *balance)
{
td_s32 ret;
ao_snd_balance_param balance_param = {
.sound = sound,
.out_port = out_port,
.balance = 0,
};
check_ao_null_ptr(balance);
ret = ioctl(g_ao_fd, CMD_AO_SND_GETBALANCE, &balance_param);
if (ret != TD_SUCCESS) {
soc_log_err("ioctl CMD_AO_SND_GETBALANCE failed\n");
soc_err_print_err_code(ret);
return ret;
}
*balance = balance_param.balance;
return TD_SUCCESS;
}
td_s32 ext_mpi_ao_snd_set_arc_cap(ao_snd_id sound, ext_ao_port out_port, const ext_ao_arc_audio_cap *arc_cap)
{
td_s32 ret;
ao_snd_arc_cap_param arc_cap_param = {
.sound = sound,
.out_port = out_port,
};
check_ao_null_ptr(arc_cap);
ret = memcpy_s(&arc_cap_param.cap, sizeof(ext_ao_arc_audio_cap), arc_cap, sizeof(*arc_cap));
if (ret != EOK) {
soc_err_print_call_fun_err(memcpy_s, ret);
return ret;
}
return ioctl(g_ao_fd, CMD_AO_SND_SETARCCAP, &arc_cap_param);
}
td_s32 ext_mpi_ao_snd_get_arc_cap(ao_snd_id sound, ext_ao_port out_port, ext_ao_arc_audio_cap *arc_cap)
{
td_s32 ret;
ao_snd_arc_cap_param arc_cap_param = {
.sound = sound,
.out_port = out_port,
};
check_ao_null_ptr(arc_cap);
ret = ioctl(g_ao_fd, CMD_AO_SND_GETARCCAP, &arc_cap);
if (ret != TD_SUCCESS) {
soc_log_err("ioctl CMD_AO_SND_GETARCCAP failed\n");
soc_err_print_err_code(ret);
return ret;
}
ret = memcpy_s(arc_cap, sizeof(*arc_cap), &arc_cap_param.cap, sizeof(ext_ao_arc_audio_cap));
if (ret != TD_SUCCESS) {
soc_err_print_call_fun_err(memcpy_s, ret);
return ret;
}
return TD_SUCCESS;
}
td_s32 ext_mpi_ao_snd_set_ad_output_enable(ao_snd_id sound, ext_ao_port out_port, td_bool enable)
{
ao_snd_ad_output_enable ad_output_enable = {
.sound = sound,
.out_port = out_port,
.ad_output_enable = enable,
};
return ioctl(g_ao_fd, CMD_AO_SND_SETADOUTPUTENABLE, &ad_output_enable);
}
td_s32 ext_mpi_ao_snd_get_ad_output_enable(ao_snd_id sound, ext_ao_port out_port, td_bool *enable)
{
td_s32 ret;
ao_snd_ad_output_enable ad_output_enable = {
.sound = sound,
.out_port = out_port,
.ad_output_enable = TD_FALSE,
};
check_ao_null_ptr(enable);
ret = ioctl(g_ao_fd, CMD_AO_SND_GETADOUTPUTENABLE, &ad_output_enable);
if (ret != TD_SUCCESS) {
soc_log_err("ioctl CMD_AO_SND_GETADOUTPUTENABLE failed\n");
soc_err_print_err_code(ret);
return ret;
}
*enable = ad_output_enable.ad_output_enable;
return TD_SUCCESS;
}
td_s32 ext_mpi_ao_snd_set_alsa_prescale(ao_snd_id sound, const ext_ao_preci_gain *preci_gain)
{
td_s32 ret;
ao_snd_set_alsa_prescale alsa_prescale = {
.sound = sound,
};
check_ao_null_ptr(preci_gain);
ret = memcpy_s(&alsa_prescale.preci_gain, sizeof(ext_ao_preci_gain), preci_gain, sizeof(*preci_gain));
if (ret != TD_SUCCESS) {
soc_err_print_call_fun_err(memcpy_s, ret);
return ret;
}
return ioctl(g_ao_fd, CMD_AO_SND_SETALSAPRESCALE, &alsa_prescale);
}
td_s32 ext_mpi_ao_snd_set_alsa_mute(ao_snd_id sound, td_bool mute)
{
ao_snd_set_alsa_mute alsa_mute = {
.sound = sound,
.mute = mute,
};
return ioctl(g_ao_fd, CMD_AO_SND_SETALSAMUTE, &alsa_mute);
}
td_s32 ext_mpi_ao_snd_get_track_info(ao_snd_id sound, ext_ao_track_info *track_info)
{
td_s32 ret;
ao_snd_track_info_param track_info_param = {
.sound = sound,
};
check_ao_null_ptr(track_info);
ret = ioctl(g_ao_fd, CMD_AO_SND_GETTRACKINFO, &track_info_param);
if (ret != TD_SUCCESS) {
soc_log_err("ioctl CMD_AO_SND_GETTRACKINFO failed\n");
soc_err_print_err_code(ret);
return ret;
}
ret = memcpy_s(track_info, sizeof(*track_info), &track_info_param.track_info, sizeof(ext_ao_track_info));
if (ret != TD_SUCCESS) {
soc_err_print_call_fun_err(memcpy_s, ret);
return ret;
}
return TD_SUCCESS;
}
td_s32 ext_mpi_ao_snd_track_config_init(ao_snd_id sound, const ext_ao_track_config *track_config)
{
td_s32 ret;
ao_snd_track_config_param track_config_param = {
.sound = sound,
};
check_ao_null_ptr(track_config);
ret = memcpy_s(&track_config_param.track_config, sizeof(ext_ao_track_config), track_config, sizeof(*track_config));
if (ret != TD_SUCCESS) {
soc_err_print_call_fun_err(memcpy_s, ret);
return ret;
}
return ioctl(g_ao_fd, CMD_AO_SND_TRACKCONFIGINIT, &track_config_param);
}
td_s32 ext_mpi_ao_set_track_direct_out(ao_snd_id sound, td_handle track, ext_ao_port out_port, td_bool enable)
{
ao_snd_track_duplicate_param param = {
.sound = sound,
.out_port = out_port,
.h_track = track,
.enable = enable,
};
return ioctl(g_ao_fd, CMD_AO_SND_DUPLICATETRACK, &param);
}
td_s32 ext_mpi_ao_snd_set_avc_attr(ao_snd_id sound, const ext_ao_avc_attr *attr)
{
td_s32 ret;
ao_snd_avc_param avc_param = {
.sound = sound,
};
check_ao_null_ptr(attr);
ret = memcpy_s(&avc_param.avc_attr, sizeof(ext_ao_avc_attr), attr, sizeof(*attr));
if (ret != EOK) {
soc_log_err("memcpy_s failed(0x%x)\n", ret);
return ret;
}
ret = ioctl(g_ao_fd, CMD_AO_SND_SETAVCATTR, &avc_param);
if (ret != TD_SUCCESS) {
soc_log_err("ioctl CMD_AO_SND_SETAVCATTR failed(0x%x)\n", ret);
return ret;
}
return TD_SUCCESS;
}
td_s32 ext_mpi_ao_snd_get_avc_attr(ao_snd_id sound, ext_ao_avc_attr *attr)
{
td_s32 ret;
ao_snd_avc_param avc_param = {
.sound = sound,
};
check_ao_null_ptr(attr);
ret = ioctl(g_ao_fd, CMD_AO_SND_GETAVCATTR, &avc_param);
if (ret != TD_SUCCESS) {
soc_log_err("ioctl CMD_AO_SND_GETAVCATTR failed(0x%x)\n", ret);
return ret;
}
ret = memcpy_s(attr, sizeof(*attr), &avc_param.avc_attr, sizeof(ext_ao_avc_attr));
if (ret != EOK) {
soc_log_err("memcpy_s failed(0x%x)\n", ret);
return ret;
}
return TD_SUCCESS;
}
td_s32 ext_mpi_ao_set_avc_enable(ao_snd_id sound, td_bool enable)
{
ao_snd_avc_enable avc_enable = {
.sound = sound,
.avc_enable = enable,
};
return ioctl(g_ao_fd, CMD_AO_SND_SETAVCENABLE, &avc_enable);
}
td_s32 ext_mpi_ao_get_avc_enable(ao_snd_id sound, td_bool *enable)
{
td_s32 ret;
ao_snd_avc_enable avc_enable = {
.sound = sound,
.avc_enable = TD_FALSE,
};
check_ao_null_ptr(enable);
ret = ioctl(g_ao_fd, CMD_AO_SND_GETAVCENABLE, &avc_enable);
if (ret == TD_SUCCESS) {
*enable = avc_enable.avc_enable;
}
return ret;
}
td_s32 ext_mpi_ao_snd_set_geq_attr(ao_snd_id sound, const ext_ao_geq_attr *geq_attr)
{
td_s32 ret;
ao_snd_geq_param geq_param = {
.sound = sound,
};
check_ao_null_ptr(geq_attr);
ret = memcpy_s(&geq_param.eq_attr, sizeof(ext_ao_geq_attr), geq_attr, sizeof(*geq_attr));
if (ret != TD_SUCCESS) {
soc_log_err("memcpy_s failed\n");
return ret;
}
return ioctl(g_ao_fd, CMD_AO_SND_SETGEQATTR, &geq_param);
}
td_s32 ext_mpi_ao_snd_get_geq_attr(ao_snd_id sound, ext_ao_geq_attr *geq_attr)
{
td_s32 ret;
ao_snd_geq_param geq_param = {
.sound = sound,
};
check_ao_null_ptr(geq_attr);
ret = ioctl(g_ao_fd, CMD_AO_SND_GETGEQATTR, &geq_param);
if (ret != TD_SUCCESS) {
soc_log_err("ioctl CMD_AO_SND_GETGEQATTR failed\n");
soc_err_print_err_code(ret);
return ret;
}
ret = memcpy_s(geq_attr, sizeof(*geq_attr), &geq_param.eq_attr, sizeof(ext_ao_geq_attr));
if (ret != EOK) {
soc_err_print_call_fun_err(memcpy_s, ret);
return ret;
}
return TD_SUCCESS;
}
td_s32 ext_mpi_ao_set_geq_enable(ao_snd_id sound, td_bool enable)
{
ao_snd_eq_enable geq_enable = {
.sound = sound,
.out_port = EXT_AO_PORT_MAX,
.eq_enable = enable,
};
return ioctl(g_ao_fd, CMD_AO_SND_SETGEQENABLE, &geq_enable);
}
td_s32 ext_mpi_ao_get_geq_enable(ao_snd_id sound, td_bool *enable)
{
td_s32 ret;
ao_snd_eq_enable geq_enable = {
.sound = sound,
.out_port = EXT_AO_PORT_MAX,
.eq_enable = TD_FALSE,
};
check_ao_null_ptr(enable);
ret = ioctl(g_ao_fd, CMD_AO_SND_GETGEQENABLE, &geq_enable);
if (ret != TD_SUCCESS) {
soc_log_err("ioctl CMD_AO_SND_GETGEQENABLE failed\n");
soc_err_print_err_code(ret);
return ret;
}
*enable = geq_enable.eq_enable;
return TD_SUCCESS;
}
td_s32 ext_mpi_ao_set_geq_gain(ao_snd_id sound, td_u32 band, td_s32 gain)
{
ao_snd_geq_gain geq_gain = {
.sound = sound,
.band = band,
.gain = gain,
};
return ioctl(g_ao_fd, CMD_AO_SND_SETGEQGAIN, &geq_gain);
}
td_s32 ext_mpi_ao_get_geq_gain(ao_snd_id sound, td_u32 band, td_s32 *gain)
{
td_s32 ret;
ao_snd_geq_gain geq_gain = {
.sound = sound,
.band = band,
.gain = 0,
};
check_ao_null_ptr(gain);
ret = ioctl(g_ao_fd, CMD_AO_SND_GETGEQGAIN, &geq_gain);
if (ret != TD_SUCCESS) {
soc_log_err("ioctl CMD_AO_SND_GETGEQGAIN failed\n");
soc_err_print_err_code(ret);
return ret;
}
*gain = geq_gain.gain;
return TD_SUCCESS;
}
td_s32 ext_mpi_ao_snd_set_drc_enable(ao_snd_id sound, ext_ao_port port, td_bool enable)
{
ao_snd_drc_enable drc_enable = {
.sound = sound,
.out_port = port,
.drc_enable = enable,
};
return ioctl(g_ao_fd, CMD_AO_SND_SETDRCENABLE, &drc_enable);
}
td_s32 ext_mpi_ao_snd_get_drc_enable(ao_snd_id sound, ext_ao_port port, td_bool *enable)
{
td_s32 ret;
ao_snd_drc_enable drc_enable = {
.sound = sound,
.out_port = port,
.drc_enable = TD_FALSE,
};
check_ao_null_ptr(enable);
ret = ioctl(g_ao_fd, CMD_AO_SND_GETDRCENABLE, &drc_enable);
if (ret != TD_SUCCESS) {
soc_log_err("ioctl CMD_AO_SND_GETDRCENABLE failed\n");
soc_err_print_err_code(ret);
return ret;
}
*enable = drc_enable.drc_enable;
return TD_SUCCESS;
}
td_s32 ext_mpi_ao_snd_set_drc_attr(ao_snd_id sound, ext_ao_port port, const ext_ao_drc_attr *attr)
{
td_s32 ret;
ao_snd_drc_param drc_param = {
.sound = sound,
.out_port = port,
};
check_ao_null_ptr(attr);
ret = memcpy_s(&drc_param.drc_attr, sizeof(ext_ao_drc_attr), attr, sizeof(*attr));
if (ret != EOK) {
soc_log_err("memcpy_s failed(0x%x)\n", ret);
return ret;
}
return ioctl(g_ao_fd, CMD_AO_SND_SETDRCATTR, &drc_param);
}
td_s32 ext_mpi_ao_snd_get_drc_attr(ao_snd_id sound, ext_ao_port port, ext_ao_drc_attr *attr)
{
td_s32 ret;
ao_snd_drc_param drc_param = {
.sound = sound,
.out_port = port,
};
check_ao_null_ptr(attr);
ret = ioctl(g_ao_fd, CMD_AO_SND_GETDRCATTR, &drc_param);
if (ret != TD_SUCCESS) {
soc_log_err("ioctl CMD_AO_SND_GETDRCATTR failed(0x%x)", ret);
return ret;
}
ret = memcpy_s(attr, sizeof(*attr), &drc_param.drc_attr, sizeof(ext_ao_drc_attr));
if (ret != EOK) {
soc_log_err("memcpy_s failed(0x%x)\n", ret);
return ret;
}
return TD_SUCCESS;
}
td_s32 ext_mpi_ao_set_peq_enable(ao_snd_id sound, ext_ao_port port, td_bool enable)
{
ao_snd_eq_enable peq_enable = {
.sound = sound,
.out_port = port,
.eq_enable = enable,
};
return ioctl(g_ao_fd, CMD_AO_SND_SETPEQENABLE, &peq_enable);
}
td_s32 ext_mpi_ao_get_peq_enable(ao_snd_id sound, ext_ao_port port, td_bool *enable)
{
td_s32 ret;
ao_snd_eq_enable peq_enable = {
.sound = sound,
.out_port = port,
.eq_enable = TD_FALSE,
};
check_ao_null_ptr(enable);
ret = ioctl(g_ao_fd, CMD_AO_SND_GETPEQENABLE, &peq_enable);
if (ret == TD_SUCCESS) {
*enable = peq_enable.eq_enable;
}
return ret;
}
td_s32 ext_mpi_ao_snd_set_peq_attr(ao_snd_id sound, ext_ao_port port, const ext_ao_peq_attr *attr)
{
td_s32 ret;
ao_snd_peq_param peq_param = {
.sound = sound,
.out_port = port,
};
check_ao_null_ptr(attr);
ret = memcpy_s(&peq_param.eq_attr, sizeof(ext_ao_peq_attr), attr, sizeof(*attr));
if (ret != EOK) {
soc_log_err("memcpy_s failed(0x%x)\n", ret);
return ret;
}
return ioctl(g_ao_fd, CMD_AO_SND_SETPEQATTR, &peq_param);
}
td_s32 ext_mpi_ao_snd_get_peq_attr(ao_snd_id sound, ext_ao_port port, ext_ao_peq_attr *attr)
{
td_s32 ret;
ao_snd_peq_param peq_param = {
.sound = sound,
.out_port = port,
};
check_ao_null_ptr(attr);
ret = ioctl(g_ao_fd, CMD_AO_SND_GETPEQATTR, &peq_param);
if (ret != TD_SUCCESS) {
soc_log_err("ioctl CMD_AO_SND_GETPEQATTR failed(0x%x)", ret);
return ret;
}
ret = memcpy_s(attr, sizeof(*attr), &peq_param.eq_attr, sizeof(ext_ao_peq_attr));
if (ret != EOK) {
soc_log_err("memcpy_s failed(0x%x)\n", ret);
return ret;
}
return TD_SUCCESS;
}
td_s32 ext_mpi_ao_snd_set_port_enable(ao_snd_id sound, ext_ao_port port, td_bool enable)
{
ao_snd_port_enable_param param = {
.sound = sound,
.out_port = port,
.enable = enable,
};
return ioctl(g_ao_fd, CMD_AO_SND_SETPORTENABLE, &param);
}
td_s32 ext_mpi_ao_snd_get_port_enable(ao_snd_id sound, ext_ao_port port, td_bool *enable)
{
td_s32 ret;
ao_snd_port_enable_param param = {
.sound = sound,
.out_port = port,
.enable = TD_FALSE,
};
check_ao_null_ptr(enable);
ret = ioctl(g_ao_fd, CMD_AO_SND_GETPORTENABLE, &param);
if (ret == TD_SUCCESS) {
*enable = param.enable;
}
return ret;
}
/* create SND directional memory access(DMA) */
td_s32 ext_mpi_ao_snd_dma_create(ao_snd_id sound)
{
return snd_dma_create(sound);
}
/* destory SND directional memory access(DMA) */
td_s32 ext_mpi_ao_snd_dma_destory(ao_snd_id sound)
{
return snd_dma_destroy(sound);
}
td_s32 ext_mpi_ao_snd_dma_send_data(const ext_ao_frame *frame, td_u32 latency_ms)
{
check_ao_null_ptr(frame);
return snd_dma_send_data(frame, latency_ms);
}
td_s32 ext_mpi_ao_snd_dma_get_delay_ms(td_u32 *delay_ms)
{
check_ao_null_ptr(delay_ms);
*delay_ms = 0;
return snd_dma_get_delay_ms(delay_ms);
}
td_s32 ext_mpi_ao_set_sink_delay(ao_snd_id sound, td_u32 sink_delay)
{
ao_snd_sink_delay_param param = {
.sound = sound,
.sink_delay = sink_delay,
};
return ioctl(g_ao_fd, CMD_AO_SND_SETSINKDELAY, &param);
}
td_s32 ext_mpi_ao_get_sink_delay(ao_snd_id sound, td_u32 *sink_delay)
{
td_s32 ret;
ao_snd_sink_delay_param param = {
.sound = sound,
.sink_delay = 0,
};
check_ao_null_ptr(sink_delay);
ret = ioctl(g_ao_fd, CMD_AO_SND_GETSINKDELAY, &param);
if (ret != TD_SUCCESS) {
soc_log_err("ioctl CMD_AO_SND_GETSINKDELAY failed\n");
soc_err_print_err_code(ret);
return ret;
}
*sink_delay = param.sink_delay;
return TD_SUCCESS;
}
td_s32 ext_mpi_ao_get_stream_info(ao_snd_id sound, ext_audio_stream_info *stream_info)
{
td_s32 ret;
ao_snd_stream_info_param param = {
.sound = sound,
};
check_ao_null_ptr(stream_info);
ret = ioctl(g_ao_fd, CMD_AO_SND_GETSTREAMINFO, &param);
if (ret != TD_SUCCESS) {
soc_log_err("ioctl CMD_AO_SND_GETSTREAMINFO failed\n");
soc_err_print_err_code(ret);
return ret;
}
ret = memcpy_s(stream_info, sizeof(*stream_info), &param.stream_info, sizeof(ext_audio_stream_info));
if (ret != TD_SUCCESS) {
soc_err_print_call_fun_err(memcpy_s, ret);
return ret;
}
return TD_SUCCESS;
}
/* ao track mpi function */
td_s32 ext_mpi_ao_track_get_default_open_attr(ext_ao_track_type track_type, ext_ao_track_attr *attr)
{
check_ao_null_ptr(attr);
attr->track_type = track_type;
return ioctl(g_ao_fd, CMD_AO_TRACK_GETDEFATTR, attr);
}
td_s32 ext_mpi_ao_track_get_attr(td_handle track, ext_ao_track_attr *attr)
{
td_s32 ret;
ao_track_attr_param track_attr;
check_ao_null_ptr(attr);
check_ao_track_id(track);
if ((track & AO_TRACK_CHNID_MASK) >= AO_MAX_REAL_TRACK_NUM) {
return vir_get_attr(track, attr);
}
track_attr.h_track = track;
ret = ioctl(g_ao_fd, CMD_AO_TRACK_GETATTR, &track_attr);
if (ret != TD_SUCCESS) {
soc_log_err("ioctl CMD_AO_TRACK_GETATTR failed(0x%x)", ret);
return ret;
}
ret = memcpy_s(attr, sizeof(*attr), &track_attr.attr, sizeof(ext_ao_track_attr));
if (ret != EOK) {
soc_log_err("memcpy_s failed(0x%x)\n", ret);
return ret;
}
return TD_SUCCESS;
}
td_s32 ext_mpi_ao_track_set_attr(td_handle track, const ext_ao_track_attr *attr)
{
td_s32 ret;
ao_track_attr_param track_attr;
check_ao_null_ptr(attr);
check_ao_track_id(track);
if ((track & AO_TRACK_CHNID_MASK) >= AO_MAX_REAL_TRACK_NUM) {
return TD_FAILURE;
}
track_attr.h_track = track;
ret = memcpy_s(&track_attr.attr, sizeof(ext_ao_track_attr), attr, sizeof(*attr));
if (ret != EOK) {
soc_log_err("memcpy_s failed(0x%x)\n", ret);
return ret;
}
return ioctl(g_ao_fd, CMD_AO_TRACK_SETATTR, &track_attr);
}
td_bool ext_mpi_ao_track_check_is_low_latency(td_handle track)
{
return llt_check(track);
}
td_s32 ext_mpi_ao_track_create(ao_snd_id sound, const ext_ao_track_attr *attr, td_handle *track)
{
td_s32 ret;
td_handle h_track = TD_INVALID_HANDLE;
ao_track_create_param track_param = {
.sound = sound,
.alsa_track = TD_FALSE,
.h_track = TD_INVALID_HANDLE,
};
check_ao_null_ptr(attr);
check_ao_null_ptr(track);
soc_log_warn("track_type:0x%x\n", attr->track_type);
if (attr->track_type == EXT_AO_TRACK_TYPE_VIRTUAL) {
ret = vir_create_track(attr, &h_track);
if (ret == TD_SUCCESS) {
*track = h_track;
}
return ret;
}
ret = memcpy_s(&track_param.attr, sizeof(ext_ao_track_attr), attr, sizeof(*attr));
if (ret != EOK) {
soc_log_err("memcpy_s failed(0x%x)\n", ret);
return ret;
}
ret = ioctl(g_ao_fd, CMD_AO_TRACK_CREATE, &track_param);
h_track = track_param.h_track;
if (ret == TD_SUCCESS) {
*track = h_track;
}
if (attr->track_type == EXT_AO_TRACK_TYPE_LOW_LATENCY) {
ret = llt_enable(h_track);
if (ret != TD_SUCCESS) {
ioctl(g_ao_fd, CMD_AO_TRACK_DESTROY, &h_track);
soc_err_print_call_fun_err(llt_enable, ret);
return ret;
}
ret = ext_mpi_ao_track_start(h_track);
if (ret != TD_SUCCESS) {
soc_err_print_call_fun_err(ext_mpi_ao_track_start, ret);
}
}
return ret;
}
td_s32 ext_mpi_ao_track_destroy(td_handle track)
{
td_s32 ret;
check_ao_track_id(track);
if ((track & AO_TRACK_CHNID_MASK) >= AO_MAX_REAL_TRACK_NUM) {
return vir_destroy_track(track);
}
if (llt_check(track) == TD_TRUE) {
llt_disable(track);
}
if (g_ad_master_track == track) {
destroy_ad_track(g_ad_master_track);
}
ret = ioctl(g_ao_fd, CMD_AO_TRACK_DESTROY, &track);
return ret;
}
td_s32 ext_mpi_ao_track_start(td_handle track)
{
td_s32 ret;
check_ao_track_id(track);
check_virtual_track(track);
if (g_ad_master_track == track) {
ret = ioctl(g_ao_fd, CMD_AO_TRACK_START, &g_ad_slave_track);
if (ret != TD_SUCCESS) {
soc_log_err("ioctl CMD_AO_TRACK_START failed(g_ad_slave_track = 0x%x)\n", g_ad_slave_track);
return ret;
}
}
ret = ioctl(g_ao_fd, CMD_AO_TRACK_START, &track);
if (ret != TD_SUCCESS) {
soc_log_err("ioctl CMD_AO_TRACK_START failed(track = 0x%x)\n", track);
return ret;
}
return ret;
}
td_s32 ext_mpi_ao_track_stop(td_handle track)
{
td_s32 ret;
td_handle src_track;
check_ao_track_id(track);
check_virtual_track(track);
src_track = track;
if (g_ad_master_track == track) {
ret = ioctl(g_ao_fd, CMD_AO_TRACK_STOP, &g_ad_slave_track);
if (ret != TD_SUCCESS) {
soc_log_err("ioctl CMD_AO_TRACK_STOP failed(g_ad_slave_track = 0x%x)\n", g_ad_slave_track);
return ret;
}
}
ret = ioctl(g_ao_fd, CMD_AO_TRACK_STOP, &src_track);
if (ret != TD_SUCCESS) {
soc_log_err("ioctl CMD_AO_TRACK_STOP failed(track = 0x%x)\n", track);
}
return ret;
}
td_s32 ext_mpi_ao_track_pause(td_handle track)
{
td_s32 ret;
check_ao_track_id(track);
check_virtual_track(track);
if (g_ad_master_track == track) {
ret = ioctl(g_ao_fd, CMD_AO_TRACK_PAUSE, &g_ad_slave_track);
if (ret != TD_SUCCESS) {
soc_log_err("ioctl CMD_AO_TRACK_PAUSE failed(g_ad_slave_track = 0x%x)\n", g_ad_slave_track);
return ret;
}
}
ret = ioctl(g_ao_fd, CMD_AO_TRACK_PAUSE, &track);
if (ret != TD_SUCCESS) {
soc_log_err("ioctl CMD_AO_TRACK_PAUSE failed(track = 0x%x)\n", track);
}
return ret;
}
td_s32 ext_mpi_ao_track_flush(td_handle track)
{
td_s32 ret;
check_ao_track_id(track);
check_virtual_track(track);
if (g_ad_master_track == track) {
ret = ioctl(g_ao_fd, CMD_AO_TRACK_FLUSH, g_ad_slave_track);
if (ret != TD_SUCCESS) {
soc_log_err("ioctl CMD_AO_TRACK_FLUSH failed(g_ad_slave_track = 0x%x)\n", g_ad_slave_track);
return ret;
}
}
ret = ioctl(g_ao_fd, CMD_AO_TRACK_FLUSH, &track);
if (ret != TD_SUCCESS) {
soc_log_err("ioctl CMD_AO_TRACK_FLUSH failed(track = 0x%x)\n", track);
}
return ret;
}
td_s32 ext_mpi_ao_track_set_fifo_bypass(td_handle track, td_bool enable)
{
ao_track_fifo_bypass_param param;
check_ao_track_id(track);
check_virtual_track(track);
param.h_track = track;
param.enable = enable;
return ioctl(g_ao_fd, CMD_AO_TRACK_SETFIFOBYPASS, &param);
}
td_s32 ext_mpi_ao_track_set_priority(td_handle track, td_bool enable)
{
ao_track_priority_param param;
check_ao_track_id(track);
check_virtual_track(track);
param.h_track = track;
param.enable = enable;
return ioctl(g_ao_fd, CMD_AO_TRACK_SETPRIORITY, &param);
}
td_s32 ext_mpi_ao_track_get_priority(td_handle track, td_bool *enable)
{
td_s32 ret;
ao_track_priority_param track_priority;
check_ao_track_id(track);
check_virtual_track(track);
check_ao_null_ptr(enable);
track_priority.h_track = track;
ret = ioctl(g_ao_fd, CMD_AO_TRACK_GETPRIORITY, &track_priority);
if (ret == TD_SUCCESS) {
*enable = track_priority.enable;
}
return ret;
}
td_s32 ext_mpi_ao_track_send_data(td_handle track, const ext_ao_frame *frame)
{
check_ao_null_ptr(frame);
check_ao_track_id(track);
if ((track & AO_TRACK_CHNID_MASK) >= AO_MAX_REAL_TRACK_NUM) {
return vir_send_data(track, frame);
}
if (llt_check(track) == TD_TRUE) {
return llt_send_data(track, frame);
}
ao_track_send_data_param track_ao_frame;
track_ao_frame.h_track = track;
audio_iapi_frame_to_drv_frame(frame, &track_ao_frame.ao_frame);
return ioctl(g_ao_fd, CMD_AO_TRACK_SENDDATA, &track_ao_frame);
}
td_s32 ext_mpi_ao_track_send_data_ad(td_handle track, const ext_ao_frame *frame)
{
td_s32 ret;
check_ao_null_ptr(frame);
check_ao_track_id(track);
if (g_ad_slave_track == TD_NULL) {
ret = create_ad_track(track);
if (ret != TD_SUCCESS) {
soc_err_print_call_fun_err(create_ad_track, ret);
return ret;
}
}
if (g_ad_slave_track != TD_NULL) {
ret = ext_mpi_ao_track_send_data(g_ad_slave_track, frame);
if (ret != TD_SUCCESS) {
soc_warn_print_call_fun_err(ext_mpi_ao_track_send_data, ret);
return ret;
}
}
return TD_SUCCESS;
}
td_s32 ext_mpi_ao_track_set_weight(td_handle track, const ext_ao_gain *gain)
{
td_s32 ret;
ao_track_weight_param weight;
check_ao_null_ptr(gain);
check_ao_track_id(track);
check_virtual_track(track);
weight.h_track = track;
ret = memcpy_s(&weight.track_gain, sizeof(ext_ao_gain), gain, sizeof(*gain));
if (ret != EOK) {
soc_log_err("memcpy_s failed(0x%x)\n", ret);
return ret;
}
return ioctl(g_ao_fd, CMD_AO_TRACK_SETWEITHT, &weight);
}
td_s32 ext_mpi_ao_track_get_weight(td_handle track, ext_ao_gain *gain)
{
td_s32 ret;
ao_track_weight_param weight = {
.h_track = track,
};
check_ao_null_ptr(gain);
check_ao_track_id(track);
check_virtual_track(track);
ret = ioctl(g_ao_fd, CMD_AO_TRACK_GETWEITHT, &weight);
if (ret != TD_SUCCESS) {
soc_log_err("ioctl CMD_AO_TRACK_GETWEITHT failed(0x%x)\n", ret);
return ret;
}
ret = memcpy_s(gain, sizeof(*gain), &weight.track_gain, sizeof(ext_ao_gain));
if (ret != EOK) {
soc_log_err("memcpy_s failed(0x%x)\n", ret);
return ret;
}
return TD_SUCCESS;
}
td_s32 ext_mpi_ao_track_set_abs_weight(td_handle track, const ext_ao_abs_gain *gain)
{
td_s32 ret;
ao_track_abs_gain_param abs_gain = {
.h_track = track,
};
check_ao_null_ptr(gain);
check_ao_track_id(track);
check_virtual_track(track);
ret = memcpy_s(&abs_gain.track_abs_gain, sizeof(ext_ao_abs_gain), gain, sizeof(*gain));
if (ret != EOK) {
soc_log_err("memcpy_s failed(0x%x)\n", ret);
return ret;
}
return ioctl(g_ao_fd, CMD_AO_TRACK_SETABSGAIN, &abs_gain);
}
td_s32 ext_mpi_ao_track_get_abs_weight(td_handle track, ext_ao_abs_gain *gain)
{
td_s32 ret;
ao_track_abs_gain_param abs_gain = {
.h_track = track,
};
check_ao_null_ptr(gain);
check_ao_track_id(track);
check_virtual_track(track);
ret = ioctl(g_ao_fd, CMD_AO_TRACK_GETABSGAIN, &abs_gain);
if (ret != TD_SUCCESS) {
soc_log_err("ioctl CMD_AO_TRACK_GETABSGAIN failed(0x%x)\n", ret);
return ret;
}
ret = memcpy_s(gain, sizeof(*gain), &abs_gain.track_abs_gain, sizeof(ext_ao_abs_gain));
if (ret != EOK) {
soc_log_err("memcpy_s failed(0x%x)\n", ret);
return ret;
}
return TD_SUCCESS;
}
td_s32 ext_mpi_ao_track_set_prescale(td_handle track, const ext_ao_preci_gain *prescale)
{
td_s32 ret;
ao_track_prescale_param param = {
.h_track = track,
};
check_ao_null_ptr(prescale);
check_ao_track_id(track);
check_virtual_track(track);
ret = memcpy_s(&param.preci_gain, sizeof(ext_ao_preci_gain), prescale, sizeof(*prescale));
if (ret != EOK) {
soc_log_err("memcpy_s failed(0x%x)\n", ret);
return ret;
}
return ioctl(g_ao_fd, CMD_AO_TRACK_SETPRESCALE, &param);
}
td_s32 ext_mpi_ao_track_get_prescale(td_handle track, ext_ao_preci_gain *prescale)
{
td_s32 ret;
ao_track_prescale_param param = {
.h_track = track,
};
check_ao_null_ptr(prescale);
check_ao_track_id(track);
check_virtual_track(track);
ret = ioctl(g_ao_fd, CMD_AO_TRACK_GETPRESCALE, &param);
if (ret != TD_SUCCESS) {
soc_log_err("ioctl CMD_AO_TRACK_GETPRESCALE failed(0x%x)\n", ret);
return ret;
}
ret = memcpy_s(prescale, sizeof(*prescale), &param.preci_gain, sizeof(ext_ao_preci_gain));
if (ret != EOK) {
soc_log_err("memcpy_s failed(0x%x)\n", ret);
return ret;
}
return TD_SUCCESS;
}
td_s32 ext_mpi_ao_track_set_mute(td_handle track, td_bool mute)
{
ao_track_mute_param mute_param = {
.h_track = track,
.mute = mute,
};
check_ao_track_id(track);
check_virtual_track(track);
return ioctl(g_ao_fd, CMD_AO_TRACK_SETMUTE, &mute_param);
}
td_s32 ext_mpi_ao_track_get_mute(td_handle track, td_bool *mute)
{
td_s32 ret;
ao_track_mute_param mute_param = {
.h_track = track,
.mute = TD_FALSE,
};
check_ao_null_ptr(mute);
check_ao_track_id(track);
check_virtual_track(track);
ret = ioctl(g_ao_fd, CMD_AO_TRACK_GETMUTE, &mute_param);
if (ret != TD_SUCCESS) {
soc_log_err("ioctl CMD_AO_TRACK_GETMUTE failed\n");
soc_err_print_err_code(ret);
return ret;
}
*mute = mute_param.mute;
return TD_SUCCESS;
}
td_s32 ext_mpi_ao_track_set_channel_mode(td_handle track, ext_track_mode mode)
{
ao_track_channel_mode_param track_mode;
check_ao_track_id(track);
check_virtual_track(track);
track_mode.h_track = track;
track_mode.mode = mode;
return ioctl(g_ao_fd, CMD_AO_TRACK_SETCHANNELMODE, &track_mode);
}
td_s32 ext_mpi_ao_track_get_channel_mode(td_handle track, ext_track_mode *mode)
{
td_s32 ret;
ao_track_channel_mode_param track_mode;
check_ao_null_ptr(mode);
check_ao_track_id(track);
check_virtual_track(track);
track_mode.h_track = track;
ret = ioctl(g_ao_fd, CMD_AO_TRACK_GETCHANNELMODE, &track_mode);
if (ret == TD_SUCCESS) {
*mode = track_mode.mode;
}
return ret;
}
td_s32 ext_mpi_ao_track_acquire_frame(td_handle track, ext_ao_frame *frame, td_u32 timeout_ms)
{
td_u32 sleep_cnt;
td_s32 ret;
struct timespec slp_tm;
check_ao_null_ptr(frame);
check_ao_track_id(track);
check_real_track(track);
ret = vir_acquire_frame(track, frame);
if (ret == SOC_ERR_AO_VIRTUALBUF_EMPTY) {
for (sleep_cnt = 0; sleep_cnt < timeout_ms; sleep_cnt++) {
slp_tm.tv_sec = 0;
slp_tm.tv_nsec = 1000 * 1000; /* this 1000*1000 means ms to ns */
if (nanosleep(&slp_tm, TD_NULL) != 0) {
soc_log_err("nanosleep err.\n");
}
ret = vir_acquire_frame(track, frame);
if (ret != SOC_ERR_AO_VIRTUALBUF_EMPTY) {
break;
}
}
}
return ret;
}
td_s32 ext_mpi_ao_track_release_frame(td_handle track, ext_ao_frame *frame)
{
check_ao_null_ptr(frame);
check_ao_track_id(track);
check_real_track(track);
return vir_release_frame(track, frame);
}
td_s32 ext_mpi_ao_track_set_eos(td_handle track, td_bool eos)
{
ao_track_eos_flag_param param = {
.h_track = track,
.eos_flag = eos,
};
check_ao_track_id(track);
check_virtual_track(track);
return ioctl(g_ao_fd, CMD_AO_TRACK_SETEOSFLAG, &param);
}
td_s32 ext_mpi_ao_track_set_speed_adjust(td_handle track, ext_ao_speed *speed)
{
td_s32 ret;
ao_track_speed_adjust_param param = {
.h_track = track,
};
check_ao_null_ptr(speed);
check_ao_track_id(track);
check_virtual_track(track);
ret = memcpy_s(&param.speed, sizeof(param.speed), speed, sizeof(*speed));
if (ret != EOK) {
soc_log_err("call memcpy_s failed(0x%x)\n", ret);
return ret;
}
ret = ioctl(g_ao_fd, CMD_AO_TRACK_SETSPEEDADJUST, &param);
if (ret != TD_SUCCESS) {
soc_log_err("ioctl CMD_AO_TRACK_SETSPEEDADJUST failed(0x%x)\n", ret);
}
return ret;
}
td_s32 ext_mpi_ao_track_set_speed(td_handle track, ext_ao_speed *speed)
{
return ext_mpi_ao_track_set_speed_adjust(track, speed);
}
td_s32 ext_mpi_ao_track_get_delay(const td_handle track, td_u32 *delay_ms)
{
td_s32 ret;
ao_track_delay_ms_param param = {
.h_track = track,
.delay_ms = 0,
};
check_ao_track_id(track);
check_virtual_track(track);
check_ao_null_ptr(delay_ms);
if (llt_check(track) == TD_TRUE) {
return llt_get_aip_delay_ms(track, delay_ms);
}
ret = ioctl(g_ao_fd, CMD_AO_TRACK_GETDELAYMS, &param);
if (ret != TD_SUCCESS) {
soc_log_err("ioctl CMD_AO_TRACK_GETDELAYMS failed\n");
soc_err_print_err_code(ret);
return ret;
}
*delay_ms = param.delay_ms;
return TD_SUCCESS;
}
td_s32 ext_mpi_ao_track_get_buf_delay(const td_handle track, td_u32 *delay_ms)
{
check_ao_track_id(track);
check_virtual_track(track);
check_ao_null_ptr(delay_ms);
if (llt_check(track) == TD_TRUE) {
return llt_get_aip_delay_ms(track, delay_ms);
}
soc_log_err("ext_mpi_ao_track_get_buf_delay only support lowlatency track\n");
return SOC_ERR_AO_NOTSUPPORT;
}
td_s32 ext_mpi_ao_track_is_buf_empty(const td_handle track, td_bool *empty)
{
td_s32 ret;
ao_track_buf_empty_param param = {
.h_track = track,
.empty = TD_FALSE,
};
check_ao_track_id(track);
check_virtual_track(track);
check_ao_null_ptr(empty);
ret = ioctl(g_ao_fd, CMD_AO_TRACK_ISBUFEMPTY, &param);
if (ret != TD_SUCCESS) {
soc_log_err("ioctl CMD_AO_TRACK_ISBUFEMPTY failed\n");
soc_err_print_err_code(ret);
return ret;
}
*empty = param.empty;
return TD_SUCCESS;
}
td_s32 ext_mpi_ao_track_attach_ai(const td_handle ai, const td_handle track)
{
ao_track_att_ai_param param = {
.h_track = track,
.h_ai = ai,
};
check_ao_track_id(track);
return ioctl(g_ao_fd, CMD_AO_TRACK_ATTACHAI, &param);
}
td_s32 ext_mpi_ao_track_detach_ai(const td_handle ai, const td_handle track)
{
td_s32 ret;
ao_track_att_ai_param param = {
.h_track = track,
.h_ai = ai,
};
check_ao_track_id(track);
ret = ioctl(g_ao_fd, CMD_AO_TRACK_DETACHAI, &param);
if (ret != TD_SUCCESS) {
soc_log_err("ioctl CMD_AO_TRACK_DETACHAI failed\n");
soc_err_print_err_code(ret);
return ret;
}
return TD_SUCCESS;
}
td_s32 ext_mpi_ao_track_set_source(td_handle track, ext_ao_source source)
{
td_s32 ret;
ao_track_source_param source_param = {
.h_track = track,
.source = source,
};
check_ao_track_id(track);
check_virtual_track(track);
/* except alsa track */
if ((source < EXT_AO_SOURCE_ATV) || (source >= EXT_AO_SOURCE_MAX)) {
soc_log_err("source invalid!\n");
soc_err_print_u32(source);
return SOC_ERR_AO_INVALID_PARA;
}
ret = ioctl(g_ao_fd, CMD_AO_TRACK_SETSOURCE, &source_param);
if (ret != TD_SUCCESS) {
soc_log_err("ioctl CMD_AO_TRACK_SETSOURCE failed\n");
soc_err_print_err_code(ret);
return ret;
}
return TD_SUCCESS;
}
td_s32 ext_mpi_ao_track_get_source_mute(ao_snd_id sound, ext_ao_source source, td_bool *mute)
{
td_s32 ret;
ao_snd_track_source_mute track_src_mute = {
.sound = sound,
.source = source,
.mute = TD_FALSE,
};
check_ao_null_ptr(mute);
if ((source < EXT_AO_SOURCE_ATV) || (source >= EXT_AO_SOURCE_MAX)) {
soc_log_err("source invalid!\n");
soc_err_print_s32(source);
return SOC_ERR_AO_INVALID_PARA;
}
track_src_mute.sound = sound;
track_src_mute.source = source;
ret = ioctl(g_ao_fd, CMD_AO_SND_TRACKGETSOURCEMUTE, &track_src_mute);
if (ret == TD_SUCCESS) {
*mute = track_src_mute.mute;
}
return ret;
}
td_s32 ext_mpi_ao_track_set_source_mute(ao_snd_id sound, ext_ao_source source, td_bool mute)
{
ao_snd_track_source_mute track_src_mute = {
.sound = sound,
.source = source,
.mute = mute,
};
if ((source < EXT_AO_SOURCE_ATV) || (source >= EXT_AO_SOURCE_MAX)) {
soc_log_err("source invalid!\n");
soc_err_print_s32(source);
return SOC_ERR_AO_INVALID_PARA;
}
return ioctl(g_ao_fd, CMD_AO_SND_TRACKSETSOURCEMUTE, &track_src_mute);
}
td_s32 ext_mpi_ao_snd_set_all_cast_mute(ao_snd_id sound, td_bool mute)
{
ao_snd_all_cast_mute_param mute_param = {
.sound = sound,
.mute = mute,
};
return ioctl(g_ao_fd, CMD_AO_SND_SETALLCASTMUTE, &mute_param);
}
td_s32 ext_mpi_ao_snd_get_all_cast_mute(ao_snd_id sound, td_bool *mute)
{
td_s32 ret;
ao_snd_all_cast_mute_param mute_param = {
.sound = sound,
.mute = TD_FALSE,
};
check_ao_null_ptr(mute);
ret = ioctl(g_ao_fd, CMD_AO_SND_GETALLCASTMUTE, &mute_param);
if (ret == TD_SUCCESS) {
*mute = mute_param.mute;
}
return ret;
}
td_s32 ext_mpi_ao_snd_get_cast_default_open_attr(ext_ao_cast_attr *attr)
{
check_ao_null_ptr(attr);
return ioctl(g_ao_fd, CMD_AO_CAST_GETDEFATTR, attr);
}
static td_void mpi_ao_munmap_cast_buf(td_void *buf, td_u32 size)
{
td_s32 err_ret;
if (buf == TD_NULL) {
return;
}
err_ret = munmap(buf, size);
if (err_ret != TD_SUCCESS) {
soc_err_print_call_fun_err(munmap, err_ret);
return;
}
}
static td_void *mpi_ao_mmap_cast_buf(td_s32 fd, td_u32 size, td_u64 phys_addr)
{
td_void *buf = TD_NULL;
if ((fd < 0) || (phys_addr == 0)) {
return TD_NULL;
}
buf = (td_void *)mmap((td_void *)0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (buf == MAP_FAILED) {
soc_log_err("mmap failed\n");
return TD_NULL;
}
return buf;
}
static td_s32 mpi_ao_create_cast(ao_snd_id sound, const ext_ao_cast_attr *attr, td_handle *cast)
{
td_s32 ret;
ao_cast_create_param cast_param = {
.sound = sound,
.h_cast = TD_INVALID_HANDLE,
};
ret = memcpy_s(&cast_param.cast_attr, sizeof(ext_ao_cast_attr), attr, sizeof(*attr));
if (ret != EOK) {
soc_err_print_call_fun_err(memcpy_s, ret);
return ret;
}
ret = ioctl(g_ao_fd, CMD_AO_CAST_CREATE, &cast_param);
if (ret != TD_SUCCESS) {
soc_log_err("ioctl CMD_AO_CAST_CREATE failed(0x%x)\n", ret);
return ret;
}
*cast = cast_param.h_cast;
return TD_SUCCESS;
}
td_s32 ext_mpi_ao_snd_create_cast(ao_snd_id sound, const ext_ao_cast_attr *attr, td_handle *cast)
{
td_s32 ret;
td_void *virt_addr = TD_NULL;
ao_cast_info_param cast_info = {
.h_cast = TD_INVALID_HANDLE,
.buf_size = 0,
.phy_addr = 0,
.map_fd = -1,
};
check_ao_null_ptr(cast);
check_ao_null_ptr(attr);
ret = mpi_ao_create_cast(sound, attr, cast);
if (ret != TD_SUCCESS) {
soc_err_print_call_fun_err(mpi_ao_create_cast, ret);
return ret;
}
cast_info.h_cast = *cast;
ret = ioctl(g_ao_fd, CMD_AO_CAST_GETINFO, &cast_info);
if (ret != TD_SUCCESS) {
soc_log_err("ioctl CMD_AO_CAST_GETINFO failed(0x%x)\n", ret);
goto out0;
}
virt_addr = mpi_ao_mmap_cast_buf(cast_info.map_fd, cast_info.buf_size, cast_info.phy_addr);
if (virt_addr == TD_NULL) {
soc_log_err("call mpi_ao_mmap_cast_buf failed\n");
ret = SOC_ERR_AO_NULL_PTR;
goto out0;
}
cast_info.user_virt_addr = (uintptr_t)virt_addr;
ret = ioctl(g_ao_fd, CMD_AO_CAST_SETINFO, &cast_info);
if (ret != TD_SUCCESS) {
soc_log_err("ioctl CMD_AO_CAST_SETINFO failed(0x%x)\n", ret);
goto out1;
}
return TD_SUCCESS;
out1:
mpi_ao_munmap_cast_buf(virt_addr, cast_info.buf_size);
out0:
if (ioctl(g_ao_fd, CMD_AO_CAST_DESTROY, &cast_info.h_cast) != TD_SUCCESS) {
soc_log_err("ioctl CMD_AO_CAST_DESTROY failed\n");
}
*cast = TD_INVALID_HANDLE;
return ret;
}
td_s32 ext_mpi_ao_snd_destroy_cast(td_handle h_cast)
{
td_s32 ret;
td_void *buf = TD_NULL;
ao_cast_info_param cast_info = {
.h_cast = h_cast,
.map_fd = -1,
.user_virt_addr = 0,
.buf_size = 0,
};
check_ao_cast_handle(h_cast);
ret = ioctl(g_ao_fd, CMD_AO_CAST_GETINFO, &cast_info);
if (ret != TD_SUCCESS) {
soc_log_err("ioctl CMD_AO_CAST_GETINFO failed(0x%x)\n", ret);
return ret;
}
buf = (td_void *)(uintptr_t)cast_info.user_virt_addr;
if (buf != TD_NULL) {
mpi_ao_munmap_cast_buf(buf, cast_info.buf_size);
}
ret = ioctl(g_ao_fd, CMD_AO_CAST_DESTROY, &h_cast);
if (ret != TD_SUCCESS) {
soc_log_err("ioctl CMD_AO_CAST_DESTROY failed(0x%x)\n", ret);
return ret;
}
return TD_SUCCESS;
}
td_s32 ext_mpi_ao_snd_set_cast_enable(td_handle h_cast, td_bool enable)
{
td_s32 ret;
ao_cast_enable_param enable_attr = {
.h_cast = h_cast,
.cast_enable = enable,
};
check_ao_cast_handle(h_cast);
ret = ioctl(g_ao_fd, CMD_AO_CAST_SETENABLE, &enable_attr);
if (ret != TD_SUCCESS) {
soc_log_err("ioctl CMD_AO_CAST_SETENABLE failed(0x%x)\n", ret);
}
return ret;
}
td_s32 ext_mpi_ao_snd_get_cast_enable(td_handle h_cast, td_bool *enable)
{
td_s32 ret;
ao_cast_enable_param enable_attr = {
.h_cast = h_cast,
};
check_ao_cast_handle(h_cast);
check_ao_null_ptr(enable);
ret = ioctl(g_ao_fd, CMD_AO_CAST_GETENABLE, &enable_attr);
if (ret == TD_SUCCESS) {
*enable = enable_attr.cast_enable;
}
return ret;
}
td_s32 ext_mpi_ao_snd_set_cast_mute(td_handle h_cast, td_bool mute)
{
ao_cast_mute_param mute_param = {
.h_cast = h_cast,
.mute = mute,
};
check_ao_cast_handle(h_cast);
return ioctl(g_ao_fd, CMD_AO_CAST_SETMUTE, &mute_param);
}
td_s32 ext_mpi_ao_snd_get_cast_mute(td_handle h_cast, td_bool *mute)
{
td_s32 ret;
ao_cast_mute_param mute_param = {
.h_cast = h_cast,
};
check_ao_cast_handle(h_cast);
check_ao_null_ptr(mute);
ret = ioctl(g_ao_fd, CMD_AO_CAST_GETMUTE, &mute_param);
if (ret == TD_SUCCESS) {
*mute = mute_param.mute;
}
return ret;
}
td_s32 ext_mpi_ao_snd_set_cast_abs_gain(td_handle h_cast, const ext_ao_abs_gain *gain)
{
td_s32 ret;
ao_cast_abs_gain_param abs_gain = {
.h_cast = h_cast,
};
check_ao_cast_handle(h_cast);
check_ao_null_ptr(gain);
ret = memcpy_s(&abs_gain.cast_abs_gain, sizeof(ext_ao_abs_gain), gain, sizeof(*gain));
if (ret != EOK) {
soc_log_err("memcpy_s failed(0x%x)\n", ret);
return ret;
}
return ioctl(g_ao_fd, CMD_AO_CAST_SETABSGAIN, &abs_gain);
}
td_s32 ext_mpi_ao_snd_get_cast_abs_gain(td_handle h_cast, ext_ao_abs_gain *gain)
{
td_s32 ret;
ao_cast_abs_gain_param abs_gain = {
.h_cast = h_cast,
};
check_ao_cast_handle(h_cast);
check_ao_null_ptr(gain);
ret = ioctl(g_ao_fd, CMD_AO_CAST_GETABSGAIN, &abs_gain);
if (ret != TD_SUCCESS) {
soc_log_err("ioctl CMD_AO_CAST_GETABSGAIN failed(0x%x)\n", ret);
return ret;
}
ret = memcpy_s(gain, sizeof(*gain), &abs_gain.cast_abs_gain, sizeof(ext_ao_abs_gain));
if (ret != EOK) {
soc_log_err("memcpy_s failed(0x%x)\n", ret);
return ret;
}
return TD_SUCCESS;
}
td_s32 ext_mpi_ao_snd_set_cast_balance(td_handle cast, td_s32 balance)
{
ao_cast_balance_param param = {
.cast = cast,
.balance = balance,
};
return ioctl(g_ao_fd, CMD_AO_CAST_SETBALANCE, &param);
}
td_s32 ext_mpi_ao_snd_get_cast_balance(td_handle cast, td_s32 *balance)
{
td_s32 ret;
ao_cast_balance_param param = {
.cast = cast,
.balance = 0,
};
check_ao_null_ptr(balance);
ret = ioctl(g_ao_fd, CMD_AO_CAST_GETBALANCE, &param);
if (ret == TD_SUCCESS) {
*balance = param.balance;
}
return ret;
}
td_s32 ext_mpi_ao_snd_set_cast_preci_volume(td_handle cast, const ext_ao_preci_gain *preci_gain)
{
td_s32 ret;
ao_cast_preci_volume_param preci_volume = { 0 };
check_ao_null_ptr(preci_gain);
preci_volume.cast = cast;
ret = memcpy_s(&preci_volume.preci_gain, sizeof(ext_ao_preci_gain), preci_gain, sizeof(*preci_gain));
if (ret != TD_SUCCESS) {
soc_log_err("memcpy_s failed\n");
return ret;
}
return ioctl(g_ao_fd, CMD_AO_CAST_SETPRECIVOLUME, &preci_volume);
}
td_s32 ext_mpi_ao_snd_get_cast_preci_volume(td_handle cast, ext_ao_preci_gain *preci_gain)
{
td_s32 ret;
ao_cast_preci_volume_param preci_volume = {
.cast = cast,
};
check_ao_null_ptr(preci_gain);
ret = ioctl(g_ao_fd, CMD_AO_CAST_GETPRECIVOLUME, &preci_volume);
if (ret != TD_SUCCESS) {
soc_log_err("ioctl CMD_AO_CAST_GETPRECIVOLUME failed\n");
soc_err_print_err_code(ret);
return ret;
}
ret = memcpy_s(preci_gain, sizeof(*preci_gain), &preci_volume.preci_gain, sizeof(ext_ao_preci_gain));
if (ret != TD_SUCCESS) {
soc_err_print_call_fun_err(memcpy_s, ret);
return ret;
}
return TD_SUCCESS;
}
td_s32 ext_mpi_ao_snd_set_cast_config(td_handle cast, const ext_ao_cast_config *cast_config)
{
td_s32 ret;
ao_cast_config_param config_param = {
.cast = cast,
};
check_ao_null_ptr(cast_config);
ret = memcpy_s(&config_param.cast_config, sizeof(ext_ao_cast_config), cast_config, sizeof(*cast_config));
if (ret != EOK) {
soc_err_print_call_fun_err(memcpy_s, ret);
return ret;
}
ret = ioctl(g_ao_fd, CMD_AO_CAST_SETCONFIG, &config_param);
if (ret != TD_SUCCESS) {
soc_log_err("ioctl CMD_AO_CAST_SETCONFIG failed\n");
soc_err_print_err_code(ret);
return ret;
}
return TD_SUCCESS;
}
td_s32 ext_mpi_ao_snd_get_cast_config(td_handle cast, ext_ao_cast_config *cast_config)
{
td_s32 ret;
ao_cast_config_param config_param = {
.cast = cast,
};
check_ao_null_ptr(cast_config);
ret = ioctl(g_ao_fd, CMD_AO_CAST_GETCONFIG, &config_param);
if (ret != TD_SUCCESS) {
soc_log_err("ioctl CMD_AO_CAST_GETCONFIG failed\n");
soc_err_print_err_code(ret);
return ret;
}
ret = memcpy_s(cast_config, sizeof(*cast_config), &config_param.cast_config, sizeof(ext_ao_cast_config));
if (ret != EOK) {
soc_err_print_call_fun_err(memcpy_s, ret);
return ret;
}
return TD_SUCCESS;
}
td_s32 ext_mpi_ao_snd_acquire_cast_frame(td_handle h_cast, ext_ao_frame *frame)
{
td_s32 ret;
ao_cast_info_param cast_info = {
.h_cast = h_cast,
};
ao_cast_data_param cast_data = {
.h_cast = h_cast,
};
check_ao_cast_handle(h_cast);
check_ao_null_ptr(frame);
ret = ioctl(g_ao_fd, CMD_AO_CAST_GETINFO, &cast_info);
if (ret != TD_SUCCESS) {
soc_log_err("ioctl CMD_AO_CAST_GETINFO failed(0x%x)\n", ret);
return ret;
}
cast_data.frame_bytes = cast_info.frame_bytes;
ret = ioctl(g_ao_fd, CMD_AO_CAST_ACQUIREFRAME, &cast_data);
if (ret != TD_SUCCESS) {
frame->pcm_samples = 0;
return ret;
}
audio_drv_frame_to_iapi_frame(&cast_data.ao_frame, frame);
frame->pcm_buffer = (td_s32 *)(uintptr_t)cast_data.ao_frame.pcm_buffer;
if (frame->pcm_samples == 0) {
return SOC_ERR_AO_CAST_TIMEOUT;
}
return TD_SUCCESS;
}
td_s32 ext_mpi_ao_snd_release_cast_frame(td_handle h_cast, const ext_ao_frame *frame)
{
td_s32 ret;
ao_cast_info_param cast_info;
ao_cast_data_param cast_data;
check_ao_null_ptr(frame);
check_ao_cast_handle(h_cast);
if (frame->pcm_samples == 0) {
return TD_SUCCESS;
}
cast_info.h_cast = h_cast;
ret = ioctl(g_ao_fd, CMD_AO_CAST_GETINFO, &cast_info);
if (ret != TD_SUCCESS) {
soc_log_err("ioctl CMD_AO_CAST_GETINFO failed(0x%x)\n", ret);
return ret;
}
if ((frame->pcm_samples != cast_info.frame_samples) || (frame->channels != cast_info.channels) ||
(frame->bit_depth != cast_info.bit_per_sample)) {
soc_log_err("release cast frame error: pcm_samples_per_frame(0x%x) channels(0x%x) sample_rate(0x%x)\n",
frame->pcm_samples, frame->channels, frame->sample_rate);
return TD_FAILURE;
}
cast_data.h_cast = h_cast;
cast_data.frame_bytes = cast_info.frame_bytes;
audio_iapi_frame_to_drv_frame(frame, &cast_data.ao_frame);
ret = ioctl(g_ao_fd, CMD_AO_CAST_RELEASEFRAME, &cast_data);
if (ret != TD_SUCCESS) {
soc_log_err("ioctl CMD_AO_CAST_RELEASEFRAME failed(0x%x)\n", ret);
}
return ret;
}
td_s32 ext_mpi_ao_snd_attach_aef(ao_snd_id sound, ao_aef_attr *aef_attr)
{
td_s32 ret;
ao_snd_att_aef_param param = {
.sound = sound,
};
check_ao_null_ptr(aef_attr);
ret = memcpy_s(&param.aef_attr, sizeof(ao_aef_attr), aef_attr, sizeof(*aef_attr));
if (ret != TD_SUCCESS) {
soc_err_print_call_fun_err(memcpy_s, ret);
return ret;
}
ret = ioctl(g_ao_fd, CMD_AO_SND_ATTACHAEF, &param);
if (ret != TD_SUCCESS) {
soc_log_err("ioctl CMD_AO_SND_ATTACHAEF failed\n");
soc_err_print_err_code(ret);
return ret;
}
ret = memcpy_s(aef_attr, sizeof(*aef_attr), &param.aef_attr, sizeof(ao_aef_attr));
if (ret != TD_SUCCESS) {
soc_err_print_call_fun_err(memcpy_s, ret);
return ret;
}
return TD_SUCCESS;
}
td_s32 ext_mpi_ao_snd_detach_aef(ao_snd_id sound, const ao_aef_attr *aef_attr)
{
td_s32 ret;
ao_snd_att_aef_param aef_param = {
.sound = sound,
};
check_ao_null_ptr(aef_attr);
ret = memcpy_s(&aef_param.aef_attr, sizeof(ao_aef_attr), aef_attr, sizeof(*aef_attr));
if (ret != TD_SUCCESS) {
soc_err_print_call_fun_err(memcpy_s, ret);
return ret;
}
return ioctl(g_ao_fd, CMD_AO_SND_DETACHAEF, &aef_param);
}
td_s32 ext_mpi_ao_snd_set_aef_bypass(ao_snd_id sound, ext_ao_port out_port, td_bool bypass)
{
ao_snd_aef_bypass_param param = {
.sound = sound,
.out_port = out_port,
.bypass = bypass,
};
return ioctl(g_ao_fd, CMD_AO_SND_SETAEFBYPASS, &param);
}
td_s32 ext_mpi_ao_snd_get_aef_bypass(ao_snd_id sound, ext_ao_port out_port, td_bool *bypass)
{
td_s32 ret;
ao_snd_aef_bypass_param param = {
.sound = sound,
.out_port = out_port,
.bypass = TD_FALSE,
};
check_ao_null_ptr(bypass);
ret = ioctl(g_ao_fd, CMD_AO_SND_GETAEFBYPASS, &param);
if (ret != TD_SUCCESS) {
soc_log_err("ioctl CMD_AO_SND_GETAEFBYPASS failed\n");
soc_err_print_err_code(ret);
return ret;
}
*bypass = param.bypass;
return TD_SUCCESS;
}
td_s32 ext_mpi_ao_snd_get_aef_handle(ao_snd_id sound, td_u32 aef_type, td_handle *aflt)
{
td_s32 ret;
ao_snd_aef_handle_param ioctl_param = {
.sound = sound,
.aef_type = aef_type,
.aflt = TD_INVALID_HANDLE,
};
check_ao_null_ptr(aflt);
ret = ioctl(g_ao_fd, CMD_AO_SND_GETAEFHANDLE, &ioctl_param);
if (ret != TD_SUCCESS) {
soc_log_err("ioctl CMD_AO_SND_GETAEFHANDLE failed\n");
soc_err_print_err_code(ret);
return ret;
}
*aflt = ioctl_param.aflt;
return TD_SUCCESS;
}
td_s32 ext_mpi_ao_snd_set_port_delay(ao_snd_id sound, ext_ao_port port, td_u32 delay)
{
td_s32 ret;
ao_snd_op_delay_param op_delay = {
.sound = sound,
.out_port = port,
.delay_ms = delay,
};
ret = ioctl(g_ao_fd, CMD_AO_SND_SETSOUNDDELAY, &op_delay);
if (ret != TD_SUCCESS) {
soc_log_err("ioctl CMD_AO_SND_SETSOUNDDELAY failed\n");
soc_err_print_err_code(ret);
return ret;
}
return TD_SUCCESS;
}
td_s32 ext_mpi_ao_snd_get_port_delay(ao_snd_id sound, ext_ao_port port, td_u32 *delay)
{
td_s32 ret;
ao_snd_op_delay_param op_delay = {
.sound = sound,
.out_port = port,
.delay_ms = 0,
};
check_ao_null_ptr(delay);
ret = ioctl(g_ao_fd, CMD_AO_SND_GETSOUNDDELAY, &op_delay);
if (ret != TD_SUCCESS) {
soc_log_err("ioctl CMD_AO_SND_GETSOUNDDELAY failed\n");
soc_err_print_err_code(ret);
return ret;
}
*delay = op_delay.delay_ms;
return TD_SUCCESS;
}
td_s32 ext_mpi_ao_snd_set_ext_delay_ms(ao_snd_id sound, td_u32 delay)
{
ao_snd_set_ext_delay_ms_param ext_delay_ms_param = {
.sound = sound,
.delay_ms = delay,
};
return ioctl(g_ao_fd, CMD_AO_SND_SETEXTDELAYMS, &ext_delay_ms_param);
}
td_s32 ext_mpi_ao_track_set_ad_balance(const td_handle track, td_s16 ad_balance)
{
td_s32 ret;
td_s32 main_volume;
td_s32 ad_volume;
ext_ao_gain main_gain = { 0 };
ext_ao_gain ad_gain = { 0 };
check_ao_track_id(track);
if ((ad_balance > MAX_AD_BALANCE) || (ad_balance < MIN_AD_BALANCE)) {
return SOC_ERR_AO_INVALID_PARA;
}
if (g_ad_slave_track == TD_NULL) {
ret = create_ad_track(track);
if (ret != TD_SUCCESS) {
soc_log_err("set AD enable failed\n");
return ret;
}
}
if (ad_balance > 0) {
main_volume = MAX_VOLUME;
ad_volume = (MAX_AD_BALANCE - ad_balance) * MAX_VOLUME / MAX_AD_BALANCE;
} else {
ad_volume = MAX_VOLUME;
main_volume = (MAX_AD_BALANCE + ad_balance) * MAX_VOLUME / MAX_AD_BALANCE;
}
main_gain.linear_mode = TD_TRUE;
ad_gain.linear_mode = TD_TRUE;
main_gain.gain = main_volume;
ad_gain.gain = ad_volume;
ret = ext_mpi_ao_track_set_weight(track, &main_gain);
if (ret != TD_SUCCESS) {
soc_log_err("set AO track failed\n");
return ret;
}
ret = ext_mpi_ao_track_set_weight(g_ad_slave_track, &ad_gain);
if (ret != TD_SUCCESS) {
soc_log_err("set AO track failed\n");
return ret;
}
return TD_SUCCESS;
}
td_s32 ext_mpi_ao_set_continue_output_status(ao_snd_id sound, td_bool enable)
{
ao_snd_con_output_enable con_output_enable = {
.sound = sound,
.con_output_enable = enable,
};
return ioctl(g_ao_fd, CMD_AO_SND_SETCONOUTPUTSTATUS, &con_output_enable);
}
td_s32 ext_mpi_ao_get_continue_output_status(ao_snd_id sound, td_bool *enable)
{
td_s32 ret;
ao_snd_con_output_enable con_output_enable = {
.sound = sound,
.con_output_enable = TD_FALSE,
};
check_ao_null_ptr(enable);
ret = ioctl(g_ao_fd, CMD_AO_SND_GETCONOUTPUTSTATUS, &con_output_enable);
if (ret == TD_SUCCESS) {
*enable = con_output_enable.con_output_enable;
}
return ret;
}
td_s32 ext_mpi_ao_set_output_latency_mode(ao_snd_id sound, ext_ao_output_latency mode)
{
ao_snd_output_latency_mode output_mode = {
.sound = sound,
.output_mode = mode,
};
return ioctl(g_ao_fd, CMD_AO_SND_SETOUTPUTLATENCYMODE, &output_mode);
}
td_s32 ext_mpi_ao_get_output_latency_mode(ao_snd_id sound, ext_ao_output_latency *mode)
{
td_s32 ret;
ao_snd_output_latency_mode output_mode = {
.sound = sound,
.output_mode = EXT_AO_OUTPUT_LATENCY_MAX,
};
check_ao_null_ptr(mode);
ret = ioctl(g_ao_fd, CMD_AO_SND_GETOUTPUTLATENCYMODE, &output_mode);
if (ret == TD_SUCCESS) {
*mode = output_mode.output_mode;
}
return ret;
}
td_s32 ext_mpi_ao_track_set_config(td_handle track, const td_void *config)
{
TD_UNUSED(track);
check_ao_null_ptr(config);
return SOC_ERR_AO_NOTSUPPORT;
}
td_s32 ext_mpi_ao_track_get_config(td_handle track, td_void *config)
{
TD_UNUSED(track);
check_ao_null_ptr(config);
return SOC_ERR_AO_NOTSUPPORT;
}
td_s32 ext_mpi_ao_snd_set_atmos_lock_enable(ao_snd_id sound, td_bool atmos_lock_enable)
{
TD_UNUSED(sound);
TD_UNUSED(atmos_lock_enable);
return SOC_ERR_AO_NOTSUPPORT;
}
td_s32 ext_mpi_ao_snd_get_atmos_lock_enable(ao_snd_id sound, td_bool *atmos_lock_enable)
{
TD_UNUSED(sound);
check_ao_null_ptr(atmos_lock_enable);
return SOC_ERR_AO_NOTSUPPORT;
}
td_s32 ext_mpi_ao_snd_start_render(ao_snd_id sound, ext_ao_render_attr *attr)
{
TD_UNUSED(sound);
check_ao_null_ptr(attr);
return SOC_ERR_AO_NOTSUPPORT;
}
td_s32 ext_mpi_ao_snd_stop_render(ao_snd_id sound)
{
TD_UNUSED(sound);
return SOC_ERR_AO_NOTSUPPORT;
}
td_s32 ext_mpi_ao_snd_set_all_track_prescale(ao_snd_id sound, const ext_ao_preci_gain *prescale)
{
td_s32 ret;
ao_snd_all_track_prescale_param prescale_param = {
.sound = sound,
};
check_ao_null_ptr(prescale);
ret = memcpy_s(&prescale_param.all_track_prescale, sizeof(ext_ao_preci_gain), prescale, sizeof(*prescale));
if (ret != EOK) {
soc_log_err("memcpy_s failed(0x%x)\n", ret);
return ret;
}
ret = ioctl(g_ao_fd, CMD_AO_SND_SETALLTRACKPRESCALE, &prescale_param);
if (ret != TD_SUCCESS) {
soc_log_err("ioctl CMD_AO_SND_SETALLTRACKPRESCALE failed(0x%x)\n", ret);
return ret;
}
return TD_SUCCESS;
}
td_s32 ext_mpi_ao_snd_get_all_track_prescale(ao_snd_id sound, ext_ao_preci_gain *prescale)
{
td_s32 ret;
ao_snd_all_track_prescale_param prescale_param = {
.sound = sound,
};
check_ao_null_ptr(prescale);
ret = ioctl(g_ao_fd, CMD_AO_SND_GETALLTRACKPRESCALE, &prescale_param);
if (ret != TD_SUCCESS) {
soc_log_err("ioctl CMD_AO_SND_GETALLTRACKPRESCALE failed(0x%x)\n", ret);
return ret;
}
ret = memcpy_s(prescale, sizeof(*prescale), &prescale_param.all_track_prescale, sizeof(ext_ao_preci_gain));
if (ret != EOK) {
soc_log_err("memcpy_s failed(0x%x)\n", ret);
return ret;
}
return TD_SUCCESS;
}
/* this api is called by adec and avplay */
td_s32 ext_mpi_ao_track_is_codec_support(td_u32 codec_id, td_bool *support)
{
TD_UNUSED(codec_id);
check_ao_null_ptr(support);
*support = TD_FALSE;
return TD_SUCCESS;
}
td_s32 ext_mpi_ao_track_is_render_support(td_bool *support)
{
check_ao_null_ptr(support);
*support = TD_FALSE;
return TD_SUCCESS;
}
static td_s32 mpi_ao_attach(td_u32 module_id, td_handle track, td_handle source)
{
td_s32 ret;
ext_ao_ext_module_fn ao_func = { TD_NULL, TD_NULL };
ret = ext_mpi_ao_get_extern_func(module_id, &ao_func);
if (ret != TD_SUCCESS) {
soc_err_print_call_fun_err(ext_mpi_ao_get_extern_func, ret);
return ret;
}
if (ao_func.attach == TD_NULL) {
return SOC_ERR_AO_NOTSUPPORT;
}
return ao_func.attach(source, track);
}
static td_s32 mpi_ao_detach(td_u32 module_id, td_handle track, td_handle source)
{
td_s32 ret;
ext_ao_ext_module_fn ao_func = { TD_NULL, TD_NULL };
ret = ext_mpi_ao_get_extern_func(module_id, &ao_func);
if (ret != TD_SUCCESS) {
soc_err_print_call_fun_err(ext_mpi_ao_get_extern_func, ret);
return ret;
}
if (ao_func.detach == TD_NULL) {
return SOC_ERR_AO_NOTSUPPORT;
}
return ao_func.detach(source, track);
}
#define check_ai_handle(ai) (((ai) >> 16) == SOC_ID_AI)
#define check_avplay_handle(avplay) (((avplay) >> 24) == SOC_ID_AVPLAY)
td_s32 ext_mpi_ao_attach(td_handle track, td_handle source)
{
td_s32 ret;
td_u32 module_id;
if (check_avplay_handle(source)) {
module_id = SOC_ID_AVPLAY;
} else if (check_ai_handle(source)) {
module_id = SOC_ID_AI;
} else {
return SOC_ERR_AO_INVALID_PARA;
}
ret = mpi_ao_attach(module_id, track, source);
if (ret != TD_SUCCESS) {
soc_err_print_h32(source);
soc_err_print_call_fun_err(mpi_ao_attach, ret);
return ret;
}
return TD_SUCCESS;
}
td_s32 ext_mpi_ao_detach(td_handle track, td_handle source)
{
td_u32 module_id;
td_s32 ret;
if (check_avplay_handle(source)) {
module_id = SOC_ID_AVPLAY;
} else if (check_ai_handle(source)) {
module_id = SOC_ID_AI;
} else {
return SOC_ERR_AO_INVALID_PARA;
}
ret = mpi_ao_detach(module_id, track, source);
if (ret != TD_SUCCESS) {
soc_err_print_h32(source);
soc_err_print_call_fun_err(mpi_ao_detach, ret);
return ret;
}
ret = ext_mpi_ao_track_stop(track);
if (ret != TD_SUCCESS) {
soc_err_print_h32(track);
soc_err_print_call_fun_err(ext_mpi_ao_track_stop, ret);
return ret;
}
return TD_SUCCESS;
}
/* mixer plugin */
td_s32 ext_mpi_ao_set_mixer_plugin_enable(ao_snd_id sound, td_bool enable)
{
return snd_mixer_set_engine_plugin_enable(sound, enable);
}
td_s32 ext_mpi_ao_get_mixer_plugin_enable(ao_snd_id sound, td_bool *enable)
{
return snd_mixer_get_engine_plugin_enable(sound, enable);
}
td_s32 ext_mpi_ao_acquire_mixer_plugin_frontout_stream(ao_snd_id sound, td_u32 require_size,
ext_audio_mixer_plugin_frame *frontout_frame, td_u32 timeout_ms)
{
check_ao_null_ptr(frontout_frame);
return snd_mixer_acquire_engine_plugin_frontout_stream(sound, require_size, frontout_frame, timeout_ms);
}
td_s32 ext_mpi_ao_release_mixer_plugin_frontout_stream(ao_snd_id sound,
const ext_audio_mixer_plugin_frame *frontout_frame)
{
check_ao_null_ptr(frontout_frame);
return snd_mixer_release_engine_plugin_frontout_stream(sound, frontout_frame);
}
td_s32 ext_mpi_ao_get_mixer_plugin_backin_buffer(ao_snd_id sound, td_u32 require_size,
ext_audio_mixer_plugin_frame *backin_frame, td_u32 timeout_ms)
{
check_ao_null_ptr(backin_frame);
return snd_mixer_get_engine_plugin_backin_buffer(sound, require_size, backin_frame, timeout_ms);
}
td_s32 ext_mpi_ao_put_mixer_plugin_backin_buffer(ao_snd_id sound, const ext_audio_mixer_plugin_frame *backin_frame)
{
check_ao_null_ptr(backin_frame);
return snd_mixer_put_engine_plugin_backin_buffer(sound, backin_frame);
}
td_s32 ext_mpi_ao_set_mixer_plugin_param(ao_snd_id sound, const ext_ao_mixer_plugin_param *param)
{
TD_UNUSED(sound);
check_ao_null_ptr(param);
return SOC_ERR_AO_NOTSUPPORT;
}
td_s32 ext_mpi_ao_get_mixer_plugin_param(ao_snd_id sound, ext_ao_mixer_plugin_param *param)
{
TD_UNUSED(sound);
check_ao_null_ptr(param);
return SOC_ERR_AO_NOTSUPPORT;
}
#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif /* __cplusplus */