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

/*
* 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(&amp_source->open_cnt) == 0) {
amp_source_unlock();
return TD_SUCCESS;
}
if (osal_atomic_dec_return(&amp_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 */