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.
411 lines
9.3 KiB
411 lines
9.3 KiB
/*
|
|
* Copyright (c) Hisilicon Technologies Co., Ltd. 2019-2019. All rights reserved.
|
|
* Description: implement of amp driver
|
|
* Author: audio
|
|
* Create: 2019-05-30
|
|
*/
|
|
|
|
#include "drv_amp.h"
|
|
#include "osal_ext.h"
|
|
#include "soc_errno.h"
|
|
#include "drv_amp_debug.h"
|
|
|
|
#include "drv_ioctl_amp.h"
|
|
#include "drv_amp_platform.h"
|
|
#include "drv_amp_device.h"
|
|
#include "drv_amp_source.h"
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif /* __cplusplus */
|
|
|
|
static td_s32 amp_int(td_void)
|
|
{
|
|
td_s32 ret;
|
|
|
|
if (amp_source_get_ready() == TD_TRUE) {
|
|
return TD_SUCCESS;
|
|
}
|
|
|
|
ret = amp_platform_open();
|
|
if (ret != TD_SUCCESS) {
|
|
soc_err_print_call_fun_err(amp_platform_open, ret);
|
|
return ret;
|
|
}
|
|
|
|
return TD_SUCCESS;
|
|
}
|
|
|
|
static td_s32 amp_ioctl_init(td_void *file, td_void *arg)
|
|
{
|
|
return amp_int();
|
|
}
|
|
|
|
static td_s32 amp_ioctl_deinit(td_void *file, td_void *arg)
|
|
{
|
|
if (amp_source_get_ready() == TD_FALSE) {
|
|
return SOC_ERR_AMP_NOT_INIT;
|
|
}
|
|
|
|
amp_platform_close();
|
|
|
|
return TD_SUCCESS;
|
|
}
|
|
|
|
static td_s32 amp_ioctl_set_mute(td_void *file, td_void *arg)
|
|
{
|
|
td_s32 ret;
|
|
td_bool mute = *(td_bool *)arg;
|
|
|
|
if (amp_source_get_ready() == TD_FALSE) {
|
|
return SOC_ERR_AMP_NOT_INIT;
|
|
}
|
|
|
|
ret = amp_platform_set_channel_mute(AMP_CHANNEL_TYPE_ALL, mute);
|
|
if (ret != TD_SUCCESS) {
|
|
soc_err_print_call_fun_err(amp_platform_set_channel_mute, ret);
|
|
return ret;
|
|
}
|
|
|
|
return TD_SUCCESS;
|
|
}
|
|
|
|
static td_s32 amp_ioctl_get_mute(td_void *file, td_void *arg)
|
|
{
|
|
td_s32 ret;
|
|
|
|
if (amp_source_get_ready() == TD_FALSE) {
|
|
return SOC_ERR_AMP_NOT_INIT;
|
|
}
|
|
|
|
ret = amp_platform_get_channel_mute(AMP_CHANNEL_TYPE_ALL, (td_bool *)arg);
|
|
if (ret != TD_SUCCESS) {
|
|
soc_err_print_call_fun_err(amp_platform_get_channel_mute, ret);
|
|
return ret;
|
|
}
|
|
|
|
return TD_SUCCESS;
|
|
}
|
|
|
|
static td_s32 amp_ioctl_read_reg(td_void *file, td_void *arg)
|
|
{
|
|
td_s32 ret;
|
|
amp_reg_operate_param_ptr param = (amp_reg_operate_param_ptr)arg;
|
|
if (amp_source_get_ready() == TD_FALSE) {
|
|
return SOC_ERR_AMP_NOT_INIT;
|
|
}
|
|
|
|
ret = amp_platorfm_read_reg(0, param->reg_addr, (td_u8 *)(uintptr_t)param->value_vir_addr, param->byte_size);
|
|
if (ret != TD_SUCCESS) {
|
|
soc_err_print_call_fun_err(amp_platorfm_write_reg, ret);
|
|
return ret;
|
|
}
|
|
|
|
return TD_SUCCESS;
|
|
}
|
|
|
|
static td_s32 amp_ioctl_write_reg(td_void *file, td_void *arg)
|
|
{
|
|
td_s32 ret;
|
|
amp_reg_operate_param_ptr param = (amp_reg_operate_param_ptr)arg;
|
|
if (amp_source_get_ready() == TD_FALSE) {
|
|
return SOC_ERR_AMP_NOT_INIT;
|
|
}
|
|
|
|
ret = amp_platorfm_write_reg(0, param->reg_addr, (td_u8 *)(uintptr_t)param->value_vir_addr, param->byte_size);
|
|
if (ret != TD_SUCCESS) {
|
|
soc_err_print_call_fun_err(amp_platorfm_write_reg, ret);
|
|
return ret;
|
|
}
|
|
|
|
return TD_SUCCESS;
|
|
}
|
|
|
|
static td_s32 amp_ioctl_set_sub_woofer_vol(td_void *file, td_void *arg)
|
|
{
|
|
return SOC_ERR_AMP_NOT_SUPPORT;
|
|
}
|
|
|
|
static td_s32 amp_ioctl_get_sub_woofer_vol(td_void *file, td_void *arg)
|
|
{
|
|
return SOC_ERR_AMP_NOT_SUPPORT;
|
|
}
|
|
|
|
static td_s32 amp_ioctl_get_info(td_void *file, td_void *arg)
|
|
{
|
|
td_s32 ret;
|
|
|
|
if (amp_source_get_ready() == TD_FALSE) {
|
|
return SOC_ERR_AMP_NOT_INIT;
|
|
}
|
|
|
|
ret = amp_platform_get_info((amp_multy_info_param *)arg);
|
|
if (ret != TD_SUCCESS) {
|
|
soc_err_print_call_fun_err(amp_platform_get_info, ret);
|
|
return ret;
|
|
}
|
|
|
|
return TD_SUCCESS;
|
|
}
|
|
|
|
static td_s32 amp_ioctl_mute_channel(td_void *file, td_void *arg)
|
|
{
|
|
td_s32 ret;
|
|
|
|
if (amp_source_get_ready() == TD_FALSE) {
|
|
return SOC_ERR_AMP_NOT_INIT;
|
|
}
|
|
|
|
ret = amp_platform_mute_channel((amp_mute_channel_param *)arg);
|
|
if (ret != TD_SUCCESS) {
|
|
soc_err_print_call_fun_err(amp_platform_mute_channel, ret);
|
|
return ret;
|
|
}
|
|
|
|
return TD_SUCCESS;
|
|
}
|
|
|
|
static td_s32 amp_ioctl_get_channel_mute(td_void *file, td_void *arg)
|
|
{
|
|
td_s32 ret;
|
|
amp_mute_channel_param *param = (amp_mute_channel_param *)arg;
|
|
|
|
if (amp_source_get_ready() == TD_FALSE) {
|
|
return SOC_ERR_AMP_NOT_INIT;
|
|
}
|
|
|
|
ret = amp_platform_get_channel_mute_status(param);
|
|
if (ret != TD_SUCCESS) {
|
|
soc_err_print_call_fun_err(amp_platform_get_channel_mute, ret);
|
|
return ret;
|
|
}
|
|
|
|
return TD_SUCCESS;
|
|
}
|
|
|
|
static td_s32 amp_ioctl_get_active_status(td_void *file, td_void *arg)
|
|
{
|
|
td_s32 ret;
|
|
|
|
if (amp_source_get_ready() == TD_FALSE) {
|
|
return SOC_ERR_AMP_NOT_INIT;
|
|
}
|
|
|
|
ret = amp_platform_get_active_status((amp_active_status_param *)arg);
|
|
if (ret != TD_SUCCESS) {
|
|
soc_err_print_call_fun_err(amp_platform_get_active_status, ret);
|
|
return ret;
|
|
}
|
|
|
|
return TD_SUCCESS;
|
|
}
|
|
|
|
static td_s32 amp_ioctl_amp_reset(td_void *file, td_void *arg)
|
|
{
|
|
td_s32 ret;
|
|
td_u32 amp_id = *(td_u32 *)arg;
|
|
|
|
if (amp_source_get_ready() == TD_FALSE) {
|
|
return SOC_ERR_AMP_NOT_INIT;
|
|
}
|
|
|
|
ret = amp_platform_reset(amp_id);
|
|
if (ret != TD_SUCCESS) {
|
|
soc_err_print_call_fun_err(amp_platform_reset, ret);
|
|
return ret;
|
|
}
|
|
|
|
return TD_SUCCESS;
|
|
}
|
|
|
|
static const struct {
|
|
td_u32 cmd;
|
|
td_s32 (*ioctl)(td_void *file, td_void *arg);
|
|
} g_fn_amp_ioctl[] = {
|
|
{CMD_AMP_INIT, amp_ioctl_init},
|
|
{CMD_AMP_DEINIT, amp_ioctl_deinit},
|
|
{CMD_AMP_SETMUTE, amp_ioctl_set_mute},
|
|
{CMD_AMP_GETMUTE, amp_ioctl_get_mute},
|
|
{CMD_AMP_WRITEREG, amp_ioctl_write_reg},
|
|
{CMD_AMP_READREG, amp_ioctl_read_reg},
|
|
{CMD_AMP_SETSUBWOOFERVOL, amp_ioctl_set_sub_woofer_vol},
|
|
{CMD_AMP_GETSUBWOOFERVOL, amp_ioctl_get_sub_woofer_vol},
|
|
{CMD_AMP_GETINFO, amp_ioctl_get_info},
|
|
{CMD_AMP_MUTECHANNEL, amp_ioctl_mute_channel},
|
|
{CMD_AMP_GET_CHANNELMUTE, amp_ioctl_get_channel_mute},
|
|
{CMD_AMP_GETACTIVESTATUS, amp_ioctl_get_active_status},
|
|
{CMD_AMP_RESET, amp_ioctl_amp_reset},
|
|
};
|
|
|
|
td_s32 amp_drv_ioctl(td_u32 cmd, td_void *arg, td_void *private_data)
|
|
{
|
|
td_s32 ret;
|
|
td_u32 cmd_type = _IOC_TYPE(cmd);
|
|
td_u32 cmd_id = _IOC_NR(cmd);
|
|
|
|
if (cmd_type != SOC_ID_AMP) {
|
|
soc_log_warn("unknown command type.\n");
|
|
return SOC_ERR_AMP_INVALID_PARA;
|
|
}
|
|
|
|
if (cmd_id >= CMD_ID_AMP_MAX) {
|
|
soc_log_warn("unknown cmd: 0x%x\n", cmd);
|
|
return SOC_ERR_AMP_INVALID_PARA;
|
|
}
|
|
|
|
if (cmd != g_fn_amp_ioctl[cmd_id].cmd) {
|
|
soc_log_warn("unknown cmd: 0x%x\n", cmd);
|
|
return SOC_ERR_AMP_INVALID_PARA;
|
|
}
|
|
|
|
if (g_fn_amp_ioctl[cmd_id].ioctl == TD_NULL) {
|
|
return SOC_ERR_AMP_NOT_SUPPORT;
|
|
}
|
|
|
|
if (_IOC_DIR(cmd) != _IOC_NONE) {
|
|
if (arg == TD_NULL) {
|
|
return SOC_ERR_AMP_NULL_PTR;
|
|
}
|
|
}
|
|
|
|
ret = amp_source_lock();
|
|
if (ret != TD_SUCCESS) {
|
|
soc_err_print_call_fun_err(amp_source_lock, ret);
|
|
return ret;
|
|
}
|
|
|
|
ret = g_fn_amp_ioctl[cmd_id].ioctl(private_data, arg);
|
|
amp_source_unlock();
|
|
return ret;
|
|
}
|
|
|
|
td_s32 amp_drv_open(td_void *private_data)
|
|
{
|
|
td_s32 ret;
|
|
drv_amp_source *source = amp_get_source();
|
|
if (source == TD_NULL) {
|
|
return SOC_ERR_AMP_NULL_PTR;
|
|
}
|
|
|
|
ret = amp_source_lock();
|
|
if (ret != TD_SUCCESS) {
|
|
soc_err_print_call_fun_err(amp_source_lock, ret);
|
|
return ret;
|
|
}
|
|
|
|
if (osal_atomic_inc_return(&source->open_cnt) == 1) {
|
|
/* init device */
|
|
ret = amp_platform_device_init();
|
|
if (ret != TD_SUCCESS) {
|
|
soc_err_print_call_fun_err(amp_platform_device_init, ret);
|
|
goto out;
|
|
}
|
|
|
|
amp_platform_driver_init();
|
|
}
|
|
|
|
amp_source_unlock();
|
|
return ret;
|
|
|
|
out:
|
|
osal_atomic_dec(&source->open_cnt);
|
|
amp_source_unlock();
|
|
return ret;
|
|
}
|
|
|
|
td_s32 amp_drv_release(td_void *private_data)
|
|
{
|
|
td_s32 ret;
|
|
drv_amp_source *amp_source = amp_get_source();
|
|
if (amp_source == TD_NULL) {
|
|
return SOC_ERR_AMP_NULL_PTR;
|
|
}
|
|
|
|
ret = amp_source_lock();
|
|
if (ret != TD_SUCCESS) {
|
|
soc_err_print_call_fun_err(amp_source_lock, ret);
|
|
return ret;
|
|
}
|
|
|
|
if (osal_atomic_read(&_source->open_cnt) == 0) {
|
|
amp_source_unlock();
|
|
return TD_SUCCESS;
|
|
}
|
|
|
|
if (osal_atomic_dec_return(&_source->open_cnt) == 0) {
|
|
if (amp_source_get_ready() == TD_TRUE) {
|
|
amp_platform_close();
|
|
}
|
|
|
|
amp_platform_driver_deinit();
|
|
amp_platform_device_deinit();
|
|
}
|
|
|
|
amp_source_unlock();
|
|
return TD_SUCCESS;
|
|
}
|
|
|
|
td_s32 amp_drv_suspend(td_void)
|
|
{
|
|
td_s32 ret;
|
|
|
|
ret = amp_source_lock();
|
|
if (ret != TD_SUCCESS) {
|
|
soc_err_print_call_fun_err(amp_source_lock, ret);
|
|
return ret;
|
|
}
|
|
|
|
if (amp_source_get_ready() == TD_TRUE) {
|
|
amp_platform_close();
|
|
}
|
|
|
|
amp_source_unlock();
|
|
soc_print("AMP suspend OK");
|
|
return TD_SUCCESS;
|
|
}
|
|
|
|
td_s32 amp_drv_resume(td_void)
|
|
{
|
|
td_s32 ret;
|
|
|
|
ret = amp_source_lock();
|
|
if (ret != TD_SUCCESS) {
|
|
soc_err_print_call_fun_err(amp_source_lock, ret);
|
|
return ret;
|
|
}
|
|
|
|
if (amp_source_get_ready() == TD_FALSE) {
|
|
ret = amp_platform_open();
|
|
if (ret != TD_SUCCESS) {
|
|
soc_err_print_call_fun_err(amp_platform_open, ret);
|
|
}
|
|
}
|
|
|
|
amp_source_unlock();
|
|
soc_print("AMP resume OK");
|
|
return ret;
|
|
}
|
|
|
|
td_s32 drv_amp_init(td_void)
|
|
{
|
|
return amp_int();
|
|
}
|
|
|
|
td_s32 drv_amp_deinit(td_void)
|
|
{
|
|
if (amp_source_get_ready() == TD_FALSE) {
|
|
return SOC_ERR_AMP_NOT_INIT;
|
|
}
|
|
|
|
amp_platform_close();
|
|
|
|
return TD_SUCCESS;
|
|
}
|
|
|
|
EXPORT_SYMBOL(drv_amp_init);
|
|
EXPORT_SYMBOL(drv_amp_deinit);
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif /* __cplusplus */
|