/* * 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 */