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.
3045 lines
80 KiB
3045 lines
80 KiB
/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License version 2 and
|
|
* only version 2 as published by the Free Software Foundation.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*/
|
|
|
|
#include <linux/init.h>
|
|
#include <linux/err.h>
|
|
#include <linux/module.h>
|
|
#include <linux/moduleparam.h>
|
|
#include <linux/time.h>
|
|
#include <linux/wait.h>
|
|
#include <linux/platform_device.h>
|
|
#include <linux/slab.h>
|
|
#include <linux/delay.h>
|
|
#include <sound/core.h>
|
|
#include <sound/soc.h>
|
|
#include <sound/soc-dapm.h>
|
|
#include <sound/pcm.h>
|
|
#include <ipc/apr_tal.h>
|
|
#include <dsp/apr_audio-v2.h>
|
|
#include <dsp/q6audio-v2.h>
|
|
#include <dsp/sec_adaptation.h>
|
|
#include <dsp/audio_cal_utils.h>
|
|
#include <dsp/q6voice.h>
|
|
#include <dsp/q6asm-v2.h>
|
|
#include <dsp/q6common.h>
|
|
#include "../asoc/msm-pcm-routing-v2.h"
|
|
|
|
#define TIMEOUT_MS 1000
|
|
#define TRUE 0x01
|
|
#define FALSE 0x00
|
|
|
|
#define SEC_ADAPTATAION_AUDIO_PORT 3 /* ASM */
|
|
#define SEC_ADAPTATAION_LOOPBACK_SRC_PORT 2 /* CVS */
|
|
#define SEC_ADAPTATAION_VOICE_SRC_PORT 2 /* CVP */
|
|
|
|
#define ASM_SET_BIT(n, x) (n |= 1 << x)
|
|
#define ASM_TEST_BIT(n, x) ((n >> x) & 1)
|
|
|
|
enum {
|
|
ASM_DIRECTION_OFFSET,
|
|
ASM_CMD_NO_WAIT_OFFSET,
|
|
ASM_MAX_OFFSET = 7,
|
|
};
|
|
|
|
enum {
|
|
WAIT_CMD,
|
|
NO_WAIT_CMD
|
|
};
|
|
|
|
enum {
|
|
LOOPBACK_DISABLE = 0,
|
|
LOOPBACK_ENABLE,
|
|
LOOPBACK_NODELAY,
|
|
LOOPBACK_ZERO_DELAY,
|
|
LOOPBACK_MAX,
|
|
};
|
|
|
|
struct afe_ctl {
|
|
void *apr;
|
|
atomic_t state;
|
|
atomic_t status;
|
|
wait_queue_head_t wait;
|
|
};
|
|
|
|
struct cvs_ctl {
|
|
void *apr;
|
|
atomic_t state;
|
|
wait_queue_head_t wait;
|
|
};
|
|
|
|
struct cvp_ctl {
|
|
void *apr;
|
|
atomic_t state;
|
|
wait_queue_head_t wait;
|
|
};
|
|
|
|
union asm_token_struct {
|
|
struct {
|
|
u8 stream_id;
|
|
u8 session_id;
|
|
u8 buf_index;
|
|
u8 flags;
|
|
} _token;
|
|
u32 token;
|
|
} __packed;
|
|
|
|
static struct afe_ctl this_afe;
|
|
static struct cvs_ctl this_cvs;
|
|
static struct cvp_ctl this_cvp;
|
|
static struct common_data *common;
|
|
static struct audio_session *session;
|
|
|
|
struct afe_port {
|
|
unsigned int device_tx_port;
|
|
unsigned int spk_rx_port;
|
|
unsigned int usb_rx_port;
|
|
unsigned int bt_rx_port;
|
|
unsigned int headset_rx_port;
|
|
unsigned int volume_monitor_port;
|
|
};
|
|
static struct afe_port afe_port;
|
|
|
|
static struct mutex asm_lock;
|
|
|
|
static int loopback_mode;
|
|
static int loopback_prev_mode;
|
|
static uint32_t upscaler_val;
|
|
static uint32_t echo_ref_mute_val;
|
|
|
|
/****************************************************************************/
|
|
/*//////////////////////////// AUDIO SOLUTION //////////////////////////////*/
|
|
/****************************************************************************/
|
|
int q6asm_set_sound_alive(struct audio_client *ac, long *param)
|
|
{
|
|
struct asm_stream_cmd_set_pp_params_sa cmd;
|
|
struct param_hdr_v3 param_info;
|
|
int rc = 0;
|
|
int i = 0;
|
|
|
|
if (ac == NULL) {
|
|
pr_err("%s: Audio client is NULL\n", __func__);
|
|
return -EINVAL;
|
|
}
|
|
|
|
memset(¶m_info, 0, sizeof(param_info));
|
|
memset(&cmd, 0, sizeof(cmd));
|
|
param_info.module_id = MODULE_ID_PP_SA;
|
|
param_info.instance_id = INSTANCE_ID_0;
|
|
param_info.param_id = PARAM_ID_PP_SA_PARAMS;
|
|
param_info.param_size = sizeof(cmd);
|
|
|
|
/* SA paramerters */
|
|
cmd.OutDevice = param[0];
|
|
cmd.Preset = param[1];
|
|
for (i = 0; i < 9; i++)
|
|
cmd.EqLev[i] = param[i+2];
|
|
cmd.m3Dlevel = param[11];
|
|
cmd.BElevel = param[12];
|
|
cmd.CHlevel = param[13];
|
|
cmd.CHRoomSize = param[14];
|
|
cmd.Clalevel = param[15];
|
|
cmd.volume = param[16];
|
|
cmd.Sqrow = param[17];
|
|
cmd.Sqcol = param[18];
|
|
cmd.TabInfo = param[19];
|
|
cmd.NewUI = param[20];
|
|
cmd.m3DPositionOn = param[21];
|
|
cmd.m3DPositionAngle[0] = param[22];
|
|
cmd.m3DPositionAngle[1] = param[23];
|
|
cmd.m3DPositionGain[0] = param[24];
|
|
cmd.m3DPositionGain[1] = param[25];
|
|
cmd.AHDRonoff = param[26];
|
|
pr_info("%s: %d %d %d%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n",
|
|
__func__,
|
|
cmd.OutDevice, cmd.Preset, cmd.EqLev[0],
|
|
cmd.EqLev[1], cmd.EqLev[2], cmd.EqLev[3],
|
|
cmd.EqLev[4], cmd.EqLev[5], cmd.EqLev[6],
|
|
cmd.EqLev[7], cmd.EqLev[8],
|
|
cmd.m3Dlevel, cmd.BElevel, cmd.CHlevel,
|
|
cmd.CHRoomSize, cmd.Clalevel, cmd.volume,
|
|
cmd.Sqrow, cmd.Sqcol, cmd.TabInfo,
|
|
cmd.NewUI, cmd.m3DPositionOn,
|
|
cmd.m3DPositionAngle[0], cmd.m3DPositionAngle[1],
|
|
cmd.m3DPositionGain[0], cmd.m3DPositionGain[1],
|
|
cmd.AHDRonoff);
|
|
|
|
rc = q6asm_pack_and_set_pp_param_in_band(ac, param_info,
|
|
(u8 *) &cmd);
|
|
if (rc)
|
|
pr_err("%s: set-params send failed paramid[0x%x] rc %d\n",
|
|
__func__, param_info.param_id, rc);
|
|
return rc;
|
|
}
|
|
|
|
int q6asm_set_sa_listenback(struct audio_client *ac, long *param)
|
|
{
|
|
struct asm_stream_cmd_set_pp_params_sa cmd = {0, };
|
|
struct param_hdr_v3 param_info;
|
|
int rc = 0;
|
|
|
|
if (ac == NULL) {
|
|
pr_err("%s: Audio client is NULL\n", __func__);
|
|
return -EINVAL;
|
|
}
|
|
|
|
memset(¶m_info, 0, sizeof(param_info));
|
|
memset(&cmd, 0, sizeof(cmd));
|
|
param_info.module_id = MODULE_ID_PP_SA;
|
|
param_info.instance_id = INSTANCE_ID_0;
|
|
param_info.param_id = PARAM_ID_PP_SA_PARAMS;
|
|
param_info.param_size = sizeof(cmd);
|
|
|
|
/* SA paramerters */
|
|
cmd.OutDevice = 1; /* EAR */
|
|
cmd.Preset = param[0];
|
|
cmd.BElevel = param[1];
|
|
cmd.Clalevel = param[2];
|
|
cmd.TabInfo = 1;
|
|
cmd.NewUI = 1;
|
|
pr_info("%s: %d %d %d\n", __func__, cmd.Preset, cmd.BElevel, cmd.Clalevel);
|
|
|
|
rc = q6asm_pack_and_set_pp_param_in_band(ac, param_info,
|
|
(u8 *) &cmd);
|
|
if (rc)
|
|
pr_err("%s: set-params send failed paramid[0x%x] rc %d\n",
|
|
__func__, param_info.param_id, rc);
|
|
return rc;
|
|
}
|
|
|
|
int q6asm_set_play_speed(struct audio_client *ac, long *param)
|
|
{
|
|
struct asm_stream_cmd_set_pp_params_vsp cmd;
|
|
struct param_hdr_v3 param_info;
|
|
int rc = 0;
|
|
|
|
if (ac == NULL) {
|
|
pr_err("%s: Audio client is NULL\n", __func__);
|
|
return -EINVAL;
|
|
}
|
|
|
|
memset(¶m_info, 0, sizeof(param_info));
|
|
memset(&cmd, 0, sizeof(cmd));
|
|
param_info.module_id = MODULE_ID_PP_SA_VSP;
|
|
param_info.instance_id = INSTANCE_ID_0;
|
|
param_info.param_id = PARAM_ID_PP_SA_VSP_PARAMS;
|
|
param_info.param_size = sizeof(cmd);
|
|
|
|
/* play speed paramerters */
|
|
cmd.speed_int = param[0];
|
|
pr_info("%s: %d\n", __func__, cmd.speed_int);
|
|
|
|
rc = q6asm_pack_and_set_pp_param_in_band(ac, param_info,
|
|
(u8 *) &cmd);
|
|
if (rc)
|
|
pr_err("%s: set-params send failed paramid[0x%x] rc %d\n",
|
|
__func__, param_info.param_id, rc);
|
|
return rc;
|
|
}
|
|
|
|
int q6asm_set_adaptation_sound(struct audio_client *ac, long *param)
|
|
{
|
|
struct asm_stream_cmd_set_pp_params_adaptation_sound cmd;
|
|
struct param_hdr_v3 param_info;
|
|
int rc = 0;
|
|
int i = 0;
|
|
|
|
if (ac == NULL) {
|
|
pr_err("%s: Audio client is NULL\n", __func__);
|
|
return -EINVAL;
|
|
}
|
|
|
|
memset(¶m_info, 0, sizeof(param_info));
|
|
memset(&cmd, 0, sizeof(cmd));
|
|
param_info.module_id = MODULE_ID_PP_ADAPTATION_SOUND;
|
|
param_info.instance_id = INSTANCE_ID_0;
|
|
param_info.param_id = PARAM_ID_PP_ADAPTATION_SOUND_PARAMS;
|
|
param_info.param_size = sizeof(cmd);
|
|
|
|
/* adapt sound paramerters */
|
|
cmd.enable = param[0];
|
|
for (i = 0; i < 12; i++)
|
|
cmd.gain[i/6][i%6] = param[i+1];
|
|
cmd.device = param[13];
|
|
pr_info("%s: %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n",
|
|
__func__,
|
|
cmd.enable, cmd.gain[0][0], cmd.gain[0][1], cmd.gain[0][2],
|
|
cmd.gain[0][3], cmd.gain[0][4], cmd.gain[0][5], cmd.gain[1][0],
|
|
cmd.gain[1][1], cmd.gain[1][2], cmd.gain[1][3], cmd.gain[1][4],
|
|
cmd.gain[1][5], cmd.device);
|
|
|
|
rc = q6asm_pack_and_set_pp_param_in_band(ac, param_info,
|
|
(u8 *) &cmd);
|
|
if (rc)
|
|
pr_err("%s: set-params send failed paramid[0x%x] rc %d\n",
|
|
__func__, param_info.param_id, rc);
|
|
return rc;
|
|
}
|
|
|
|
int q6asm_set_sound_balance(struct audio_client *ac, long *param)
|
|
{
|
|
struct asm_stream_cmd_set_pp_params_lrsm cmd;
|
|
struct param_hdr_v3 param_info;
|
|
int rc = 0;
|
|
|
|
if (ac == NULL) {
|
|
pr_err("%s: Audio client is NULL\n", __func__);
|
|
return -EINVAL;
|
|
}
|
|
|
|
memset(¶m_info, 0, sizeof(param_info));
|
|
memset(&cmd, 0, sizeof(cmd));
|
|
param_info.module_id = MODULE_ID_PP_LRSM;
|
|
param_info.instance_id = INSTANCE_ID_0;
|
|
param_info.param_id = PARAM_ID_PP_LRSM_PARAMS;
|
|
param_info.param_size = sizeof(cmd);
|
|
|
|
/* sound balance paramerters */
|
|
cmd.sm = param[0];
|
|
cmd.lr = param[1];
|
|
pr_info("%s: %d %d\n", __func__, cmd.sm, cmd.lr);
|
|
|
|
rc = q6asm_pack_and_set_pp_param_in_band(ac, param_info,
|
|
(u8 *) &cmd);
|
|
if (rc)
|
|
pr_err("%s: set-params send failed paramid[0x%x] rc %d\n",
|
|
__func__, param_info.param_id, rc);
|
|
return rc;
|
|
}
|
|
|
|
int q6asm_set_myspace(struct audio_client *ac, long *param)
|
|
{
|
|
struct asm_stream_cmd_set_pp_params_msp cmd;
|
|
struct param_hdr_v3 param_info;
|
|
int rc = 0;
|
|
|
|
if (ac == NULL) {
|
|
pr_err("%s: Audio client is NULL\n", __func__);
|
|
return -EINVAL;
|
|
}
|
|
|
|
memset(¶m_info, 0, sizeof(param_info));
|
|
memset(&cmd, 0, sizeof(cmd));
|
|
param_info.module_id = MODULE_ID_PP_SA_MSP;
|
|
param_info.instance_id = INSTANCE_ID_0;
|
|
param_info.param_id = MODULE_ID_PP_SA_MSP_PARAM;
|
|
param_info.param_size = sizeof(cmd);
|
|
|
|
/* myspace paramerters */
|
|
cmd.msp_int = param[0];
|
|
pr_info("%s: %d\n", __func__, cmd.msp_int);
|
|
|
|
rc = q6asm_pack_and_set_pp_param_in_band(ac, param_info,
|
|
(u8 *) &cmd);
|
|
if (rc)
|
|
pr_err("%s: set-params send failed paramid[0x%x] rc %d\n",
|
|
__func__, param_info.param_id, rc);
|
|
return rc;
|
|
}
|
|
|
|
int q6asm_set_upscaler(struct audio_client *ac, long *param)
|
|
{
|
|
struct asm_stream_cmd_set_pp_params_upscaler cmd;
|
|
struct param_hdr_v3 param_info;
|
|
int rc = 0;
|
|
|
|
if (ac == NULL) {
|
|
pr_err("%s: Audio client is NULL\n", __func__);
|
|
return -EINVAL;
|
|
}
|
|
|
|
memset(¶m_info, 0, sizeof(param_info));
|
|
memset(&cmd, 0, sizeof(cmd));
|
|
param_info.module_id = MODULE_ID_PP_SA_UPSCALER_COLOR;
|
|
param_info.instance_id = INSTANCE_ID_0;
|
|
param_info.param_id = PARAM_ID_PP_SA_UPSCALER_COLOR_PARAMS;
|
|
param_info.param_size = sizeof(cmd);
|
|
|
|
/* upscaler paramerters */
|
|
cmd.upscaler_enable = param[0];
|
|
pr_info("%s: %d\n", __func__, cmd.upscaler_enable);
|
|
|
|
rc = q6asm_pack_and_set_pp_param_in_band(ac, param_info,
|
|
(u8 *) &cmd);
|
|
if (rc)
|
|
pr_err("%s: set-params send failed paramid[0x%x] rc %d\n",
|
|
__func__, param_info.param_id, rc);
|
|
|
|
upscaler_val = cmd.upscaler_enable;
|
|
|
|
return rc;
|
|
}
|
|
|
|
int q6asm_set_dolby_atmos(struct audio_client *ac, long *param)
|
|
{
|
|
struct asm_stream_cmd_set_pp_params_dolby_atmos cmd;
|
|
struct param_hdr_v3 param_info;
|
|
int rc = 0;
|
|
|
|
if (ac == NULL) {
|
|
pr_err("%s: Audio client is NULL\n", __func__);
|
|
return -EINVAL;
|
|
}
|
|
|
|
memset(¶m_info, 0, sizeof(param_info));
|
|
memset(&cmd, 0, sizeof(cmd));
|
|
param_info.module_id = MODULE_ID_PP_DOLBY_DAP;
|
|
param_info.instance_id = INSTANCE_ID_0;
|
|
param_info.param_id = PARAM_ID_PP_DOLBY_DAP_PARAMS;
|
|
param_info.param_size = sizeof(cmd);
|
|
|
|
/* rotation paramerters */
|
|
cmd.enable = (uint32_t)param[0];
|
|
cmd.device = (uint16_t)param[1];
|
|
cmd.dolby_profile = (uint16_t)param[2];
|
|
pr_info("%s: %d %d %d\n", __func__,
|
|
cmd.enable, cmd.device, cmd.dolby_profile);
|
|
|
|
rc = q6asm_pack_and_set_pp_param_in_band(ac, param_info,
|
|
(u8 *) &cmd);
|
|
if (rc)
|
|
pr_err("%s: set-params send failed paramid[0x%x] rc %d\n",
|
|
__func__, param_info.param_id, rc);
|
|
|
|
return rc;
|
|
}
|
|
|
|
int adm_set_sound_booster(int port_id, int copp_idx,
|
|
long *param)
|
|
{
|
|
struct adm_param_soundbooster_t sb_param;
|
|
struct param_hdr_v3 param_hdr;
|
|
int ret = 0;
|
|
|
|
pr_debug("%s: Enter\n", __func__);
|
|
|
|
memset(¶m_hdr, 0, sizeof(param_hdr));
|
|
param_hdr.module_id = MODULE_ID_PP_SB;
|
|
param_hdr.instance_id = INSTANCE_ID_0;
|
|
param_hdr.param_id = PARAM_ID_PP_SB_PARAM;
|
|
param_hdr.param_size = sizeof(sb_param);
|
|
/* soundbooster paramerters */
|
|
sb_param.sb_enable = (uint32_t)param[0];
|
|
|
|
pr_info("%s: Enter, port_id(0x%x), copp_idx(%d), enable(%d)\n",
|
|
__func__, port_id, copp_idx, sb_param.sb_enable);
|
|
|
|
ret = adm_pack_and_set_one_pp_param(port_id, copp_idx, param_hdr,
|
|
(uint8_t *) &sb_param);
|
|
if (ret)
|
|
pr_err("%s: Failed to set sound booster params, err %d\n",
|
|
__func__, ret);
|
|
|
|
pr_debug("%s: Exit, ret=%d\n", __func__, ret);
|
|
|
|
return ret;
|
|
}
|
|
|
|
int adm_set_sb_rotation(int port_id, int copp_idx,
|
|
uint32_t rotation)
|
|
{
|
|
struct adm_param_sb_rotation cmd;
|
|
struct param_hdr_v3 param_hdr;
|
|
int ret = 0;
|
|
|
|
memset(¶m_hdr, 0, sizeof(param_hdr));
|
|
param_hdr.module_id = MODULE_ID_PP_SB;
|
|
param_hdr.instance_id = INSTANCE_ID_0;
|
|
param_hdr.param_id = PARAM_ID_PP_SB_ROTATION_PARAM;
|
|
param_hdr.param_size = sizeof(cmd);
|
|
/* rotation paramerters */
|
|
cmd.sb_rotation = rotation;
|
|
|
|
pr_info("%s: Enter, port_id(0x%x), copp_idx(%d), enable(%d)\n",
|
|
__func__, port_id, copp_idx, cmd.sb_rotation);
|
|
|
|
ret = adm_pack_and_set_one_pp_param(port_id, copp_idx, param_hdr,
|
|
(uint8_t *) &cmd);
|
|
if (ret)
|
|
pr_err("%s: Failed to set sb rotation params, err %d\n",
|
|
__func__, ret);
|
|
|
|
pr_debug("%s: Exit, ret=%d\n", __func__, ret);
|
|
|
|
return ret;
|
|
}
|
|
|
|
int adm_set_sb_flatmotion(int port_id, int copp_idx,
|
|
long *param)
|
|
{
|
|
struct adm_param_sb_flatmotion cmd;
|
|
struct param_hdr_v3 param_hdr;
|
|
int ret = 0;
|
|
|
|
memset(¶m_hdr, 0, sizeof(param_hdr));
|
|
param_hdr.module_id = MODULE_ID_PP_SB;
|
|
param_hdr.instance_id = INSTANCE_ID_0;
|
|
param_hdr.param_id = PARAM_ID_PP_SB_FLATMOTION_PARAM;
|
|
param_hdr.param_size = sizeof(cmd);
|
|
/* flatmotion paramerters */
|
|
cmd.sb_flatmotion = (unsigned int)param[0];
|
|
|
|
pr_info("%s: Enter, port_id(0x%x), copp_idx(%d), enable(%d)\n",
|
|
__func__, port_id, copp_idx, cmd.sb_flatmotion);
|
|
|
|
ret = adm_pack_and_set_one_pp_param(port_id, copp_idx, param_hdr,
|
|
(uint8_t *) &cmd);
|
|
if (ret)
|
|
pr_err("%s: Failed to set sb flatmotion params, err %d\n",
|
|
__func__, ret);
|
|
|
|
pr_debug("%s: Exit, ret=%d\n", __func__, ret);
|
|
|
|
return ret;
|
|
}
|
|
|
|
int adm_set_sb_volume(int port_id, int copp_idx,
|
|
long *param)
|
|
{
|
|
struct adm_param_sb_volume cmd;
|
|
struct param_hdr_v3 param_hdr;
|
|
int ret = 0;
|
|
|
|
pr_debug("%s: Enter\n", __func__);
|
|
|
|
memset(¶m_hdr, 0, sizeof(param_hdr));
|
|
param_hdr.module_id = MODULE_ID_PP_SB;
|
|
param_hdr.instance_id = INSTANCE_ID_0;
|
|
param_hdr.param_id = PARAM_ID_PP_SB_PARAMS_VOLUME;
|
|
param_hdr.param_size = sizeof(cmd);
|
|
/* soundbooster paramerters */
|
|
cmd.sb_volume = (uint32_t)param[0];
|
|
|
|
pr_info("%s: Enter, port_id(0x%x), copp_idx(%d), volume(%d)\n",
|
|
__func__, port_id, copp_idx, cmd.sb_volume);
|
|
|
|
ret = adm_pack_and_set_one_pp_param(port_id, copp_idx, param_hdr,
|
|
(uint8_t *) &cmd);
|
|
if (ret)
|
|
pr_err("%s: Failed to set sound booster volume, err %d\n",
|
|
__func__, ret);
|
|
|
|
pr_debug("%s: Exit, ret=%d\n", __func__, ret);
|
|
|
|
return ret;
|
|
}
|
|
|
|
static int sec_audio_sound_alive_get(struct snd_kcontrol *kcontrol,
|
|
struct snd_ctl_elem_value *ucontrol)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static int sec_audio_sa_listenback_rx_vol_get(struct snd_kcontrol *kcontrol,
|
|
struct snd_ctl_elem_value *ucontrol)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static int sec_audio_sb_rx_vol_get(struct snd_kcontrol *kcontrol,
|
|
struct snd_ctl_elem_value *ucontrol)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static int sec_audio_sb_fm_rx_vol_get(struct snd_kcontrol *kcontrol,
|
|
struct snd_ctl_elem_value *ucontrol)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static int sec_audio_sa_listenback_rx_data_get(struct snd_kcontrol *kcontrol,
|
|
struct snd_ctl_elem_value *ucontrol)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static int sec_audio_play_speed_get(struct snd_kcontrol *kcontrol,
|
|
struct snd_ctl_elem_value *ucontrol)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static int sec_audio_adaptation_sound_get(struct snd_kcontrol *kcontrol,
|
|
struct snd_ctl_elem_value *ucontrol)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static int sec_audio_sound_balance_get(struct snd_kcontrol *kcontrol,
|
|
struct snd_ctl_elem_value *ucontrol)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static int sec_audio_voice_tracking_info_get(struct snd_kcontrol *kcontrol,
|
|
struct snd_ctl_elem_value *ucontrol)
|
|
{
|
|
|
|
int rc = 0;
|
|
int be_idx = 0;
|
|
char *param_value;
|
|
int *update_param_value;
|
|
uint32_t param_size = (RMS_PAYLOAD_LEN + 1) * sizeof(uint32_t);
|
|
struct msm_pcm_routing_bdai_data msm_bedai;
|
|
struct param_hdr_v3 param_hdr;
|
|
|
|
param_value = kzalloc(param_size, GFP_KERNEL);
|
|
if (!param_value)
|
|
return -ENOMEM;
|
|
|
|
for (be_idx = 0; be_idx < MSM_BACKEND_DAI_MAX; be_idx++) {
|
|
msm_pcm_routing_get_bedai_info(be_idx, &msm_bedai);
|
|
if (msm_bedai.port_id == afe_port.device_tx_port)
|
|
break;
|
|
}
|
|
if ((be_idx < MSM_BACKEND_DAI_MAX) && msm_bedai.active) {
|
|
memset(¶m_hdr, 0, sizeof(param_hdr));
|
|
param_hdr.module_id = MODULE_ID_PP_SS_REC;
|
|
param_hdr.instance_id = 0x8000;
|
|
param_hdr.param_id = PARAM_ID_PP_SS_REC_GETPARAMS;
|
|
param_hdr.param_size = param_size;
|
|
rc = adm_get_pp_params(afe_port.device_tx_port, 0,
|
|
ADM_CLIENT_ID_DEFAULT, NULL, ¶m_hdr, param_value);
|
|
if (rc) {
|
|
pr_err("%s: get parameters failed:%d\n", __func__, rc);
|
|
kfree(param_value);
|
|
return -EINVAL;
|
|
}
|
|
update_param_value = (int *)param_value;
|
|
ucontrol->value.integer.value[0] = update_param_value[0];
|
|
|
|
pr_debug("%s: FROM DSP value[0] 0x%x\n",
|
|
__func__, update_param_value[0]);
|
|
}
|
|
kfree(param_value);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int sec_audio_myspace_get(struct snd_kcontrol *kcontrol,
|
|
struct snd_ctl_elem_value *ucontrol)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static int sec_audio_sound_boost_get(struct snd_kcontrol *kcontrol,
|
|
struct snd_ctl_elem_value *ucontrol)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static int sec_audio_upscaler_get(struct snd_kcontrol *kcontrol,
|
|
struct snd_ctl_elem_value *ucontrol)
|
|
{
|
|
ucontrol->value.integer.value[0] = upscaler_val;
|
|
return 0;
|
|
}
|
|
|
|
static int sec_audio_sb_rotation_get(struct snd_kcontrol *kcontrol,
|
|
struct snd_ctl_elem_value *ucontrol)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static int sec_audio_sb_flatmotion_get(struct snd_kcontrol *kcontrol,
|
|
struct snd_ctl_elem_value *ucontrol)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static int sec_audio_dolby_atmos_get(struct snd_kcontrol *kcontrol,
|
|
struct snd_ctl_elem_value *ucontrol)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
int32_t volume_monitor_value[VOLUME_MONITOR_GET_PAYLOAD_SIZE] = {0};
|
|
|
|
static int sec_audio_volume_monitor_get(struct snd_kcontrol *kcontrol,
|
|
struct snd_ctl_elem_value *ucontrol)
|
|
{
|
|
int ret = 0;
|
|
int be_idx = 0;
|
|
int i;
|
|
|
|
struct msm_pcm_routing_bdai_data msm_bedai;
|
|
|
|
for (be_idx = 0; be_idx < MSM_BACKEND_DAI_MAX; be_idx++) {
|
|
msm_pcm_routing_get_bedai_info(be_idx, &msm_bedai);
|
|
|
|
if (msm_bedai.active) {
|
|
if (msm_bedai.port_id == afe_port.headset_rx_port)
|
|
break;
|
|
if (msm_bedai.port_id == afe_port.bt_rx_port)
|
|
break;
|
|
if (msm_bedai.port_id == afe_port.usb_rx_port)
|
|
break;
|
|
}
|
|
}
|
|
if (be_idx == MSM_BACKEND_DAI_MAX) {
|
|
pr_info("%s: no active backend port\n", __func__);
|
|
goto done;
|
|
}
|
|
|
|
afe_port.volume_monitor_port = msm_bedai.port_id;
|
|
|
|
ret = afe_get_volume_monitor(afe_port.volume_monitor_port, volume_monitor_value);
|
|
|
|
if (ret) {
|
|
pr_err("%s: fail afe_get_volume_monitor error = %d\n", __func__, ret);
|
|
ret = -EINVAL;
|
|
goto done;
|
|
}
|
|
|
|
for (i = 0; i < VOLUME_MONITOR_GET_PAYLOAD_SIZE; i++)
|
|
ucontrol->value.integer.value[i] = volume_monitor_value[i];
|
|
|
|
|
|
done:
|
|
return ret;
|
|
}
|
|
|
|
static int sec_audio_volume_monitor_data_get(struct snd_kcontrol *kcontrol,
|
|
struct snd_ctl_elem_value *ucontrol)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static int sec_audio_sa_listenback_enable_get(struct snd_kcontrol *kcontrol,
|
|
struct snd_ctl_elem_value *ucontrol)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static int sec_audio_sound_alive_put(struct snd_kcontrol *kcontrol,
|
|
struct snd_ctl_elem_value *ucontrol)
|
|
{
|
|
int ret = 0;
|
|
struct msm_pcm_routing_fdai_data fe_dai_map;
|
|
struct audio_client *ac;
|
|
|
|
mutex_lock(&asm_lock);
|
|
msm_pcm_routing_get_fedai_info(SEC_ADAPTATAION_AUDIO_PORT,
|
|
SESSION_TYPE_RX, &fe_dai_map);
|
|
ac = q6asm_get_audio_client(fe_dai_map.strm_id);
|
|
ret = q6asm_set_sound_alive(ac,
|
|
(long *)ucontrol->value.integer.value);
|
|
mutex_unlock(&asm_lock);
|
|
|
|
return ret;
|
|
}
|
|
|
|
static int sec_audio_sa_listenback_rx_vol_put(struct snd_kcontrol *kcontrol,
|
|
struct snd_ctl_elem_value *ucontrol)
|
|
{
|
|
uint32_t gain_list[8];
|
|
int ret = 0;
|
|
struct audio_client *ac;
|
|
struct msm_pcm_routing_fdai_data fe_dai_map;
|
|
|
|
gain_list[0] = (uint32_t)ucontrol->value.integer.value[0];
|
|
gain_list[1] = (uint32_t)ucontrol->value.integer.value[0];
|
|
gain_list[2] = (uint32_t)ucontrol->value.integer.value[0];
|
|
|
|
mutex_lock(&asm_lock);
|
|
msm_pcm_routing_get_fedai_info(MSM_FRONTEND_DAI_MULTIMEDIA6,
|
|
SESSION_TYPE_RX, &fe_dai_map);
|
|
|
|
if ((fe_dai_map.strm_id <= 0) ||
|
|
(fe_dai_map.strm_id > ASM_ACTIVE_STREAMS_ALLOWED)) {
|
|
pr_info("%s: audio session is not active : %d\n",
|
|
__func__, fe_dai_map.strm_id);
|
|
ret = -EINVAL;
|
|
goto done;
|
|
}
|
|
pr_info("%s: stream id %d, vol = %d\n",
|
|
__func__, fe_dai_map.strm_id, gain_list[0]);
|
|
|
|
ac = q6asm_get_audio_client(fe_dai_map.strm_id);
|
|
ret = q6asm_set_multich_gain(ac, 3/*num_channels*/, gain_list, NULL, true);
|
|
if (ret < 0)
|
|
pr_err("%s: listenback rx vol cmd failed ret=%d\n", __func__, ret);
|
|
|
|
done:
|
|
mutex_unlock(&asm_lock);
|
|
return ret;
|
|
}
|
|
|
|
static int sec_audio_sb_rx_vol_put(struct snd_kcontrol *kcontrol,
|
|
struct snd_ctl_elem_value *ucontrol)
|
|
{
|
|
int ret = 0;
|
|
int port_id, copp_idx;
|
|
|
|
port_id = afe_port.spk_rx_port;
|
|
ret = q6audio_get_copp_idx_from_port_id(port_id, SB_VOLUME, &copp_idx);
|
|
if (ret) {
|
|
pr_err("%s: Could not get copp idx for port_id=%d\n",
|
|
__func__, port_id);
|
|
|
|
ret = -EINVAL;
|
|
goto done;
|
|
}
|
|
|
|
ret = adm_set_sb_volume(port_id, copp_idx,
|
|
(long *)ucontrol->value.integer.value);
|
|
if (ret) {
|
|
pr_err("%s: Error setting sound booster volume, err=%d\n",
|
|
__func__, ret);
|
|
|
|
ret = -EINVAL;
|
|
goto done;
|
|
}
|
|
|
|
done:
|
|
return ret;
|
|
}
|
|
|
|
static int sec_audio_sb_fm_rx_vol_put(struct snd_kcontrol *kcontrol,
|
|
struct snd_ctl_elem_value *ucontrol)
|
|
{
|
|
uint32_t gain_list[8];
|
|
int ret = 0;
|
|
struct audio_client *ac;
|
|
struct msm_pcm_routing_fdai_data fe_dai_map;
|
|
|
|
gain_list[0] = (uint32_t)ucontrol->value.integer.value[0];
|
|
gain_list[1] = (uint32_t)ucontrol->value.integer.value[0];
|
|
gain_list[2] = (uint32_t)ucontrol->value.integer.value[0];
|
|
|
|
mutex_lock(&asm_lock);
|
|
msm_pcm_routing_get_fedai_info(MSM_FRONTEND_DAI_MULTIMEDIA6,
|
|
SESSION_TYPE_RX, &fe_dai_map);
|
|
|
|
if ((fe_dai_map.strm_id <= 0) ||
|
|
(fe_dai_map.strm_id > ASM_ACTIVE_STREAMS_ALLOWED)) {
|
|
pr_info("%s: audio session is not active : %d\n",
|
|
__func__, fe_dai_map.strm_id);
|
|
ret = -EINVAL;
|
|
goto done;
|
|
}
|
|
pr_info("%s: stream id %d, vol = %d\n",
|
|
__func__, fe_dai_map.strm_id, gain_list[0]);
|
|
|
|
ac = q6asm_get_audio_client(fe_dai_map.strm_id);
|
|
ret = q6asm_set_multich_gain(ac, 3/*num_channels*/, gain_list, NULL, true);
|
|
if (ret < 0)
|
|
pr_err("%s: fm rx vol cmd failed ret=%d\n", __func__, ret);
|
|
|
|
done:
|
|
mutex_unlock(&asm_lock);
|
|
return ret;
|
|
}
|
|
|
|
static int sec_audio_sa_listenback_rx_data_put(struct snd_kcontrol *kcontrol,
|
|
struct snd_ctl_elem_value *ucontrol)
|
|
{
|
|
int ret = 0;
|
|
struct msm_pcm_routing_fdai_data fe_dai_map;
|
|
struct audio_client *ac;
|
|
|
|
mutex_lock(&asm_lock);
|
|
|
|
msm_pcm_routing_get_fedai_info(MSM_FRONTEND_DAI_MULTIMEDIA6,
|
|
SESSION_TYPE_RX, &fe_dai_map);
|
|
pr_info("%s: stream id %d\n", __func__, fe_dai_map.strm_id);
|
|
|
|
ac = q6asm_get_audio_client(fe_dai_map.strm_id);
|
|
ret = q6asm_set_sa_listenback(ac, (long *)ucontrol->value.integer.value);
|
|
|
|
mutex_unlock(&asm_lock);
|
|
|
|
return ret;
|
|
}
|
|
|
|
static int sec_audio_play_speed_put(struct snd_kcontrol *kcontrol,
|
|
struct snd_ctl_elem_value *ucontrol)
|
|
{
|
|
int ret = 0;
|
|
struct msm_pcm_routing_fdai_data fe_dai_map;
|
|
struct audio_client *ac;
|
|
|
|
mutex_lock(&asm_lock);
|
|
msm_pcm_routing_get_fedai_info(SEC_ADAPTATAION_AUDIO_PORT,
|
|
SESSION_TYPE_RX, &fe_dai_map);
|
|
ac = q6asm_get_audio_client(fe_dai_map.strm_id);
|
|
ret = q6asm_set_play_speed(ac,
|
|
(long *)ucontrol->value.integer.value);
|
|
mutex_unlock(&asm_lock);
|
|
|
|
return ret;
|
|
}
|
|
|
|
static int sec_audio_adaptation_sound_put(struct snd_kcontrol *kcontrol,
|
|
struct snd_ctl_elem_value *ucontrol)
|
|
{
|
|
int ret = 0;
|
|
struct msm_pcm_routing_fdai_data fe_dai_map;
|
|
struct audio_client *ac;
|
|
|
|
mutex_lock(&asm_lock);
|
|
msm_pcm_routing_get_fedai_info(SEC_ADAPTATAION_AUDIO_PORT,
|
|
SESSION_TYPE_RX, &fe_dai_map);
|
|
ac = q6asm_get_audio_client(fe_dai_map.strm_id);
|
|
ret = q6asm_set_adaptation_sound(ac,
|
|
(long *)ucontrol->value.integer.value);
|
|
mutex_unlock(&asm_lock);
|
|
return ret;
|
|
}
|
|
|
|
static int sec_audio_sound_balance_put(struct snd_kcontrol *kcontrol,
|
|
struct snd_ctl_elem_value *ucontrol)
|
|
{
|
|
int ret = 0;
|
|
struct msm_pcm_routing_fdai_data fe_dai_map;
|
|
struct audio_client *ac;
|
|
|
|
mutex_lock(&asm_lock);
|
|
msm_pcm_routing_get_fedai_info(SEC_ADAPTATAION_AUDIO_PORT,
|
|
SESSION_TYPE_RX, &fe_dai_map);
|
|
ac = q6asm_get_audio_client(fe_dai_map.strm_id);
|
|
ret = q6asm_set_sound_balance(ac,
|
|
(long *)ucontrol->value.integer.value);
|
|
mutex_unlock(&asm_lock);
|
|
return ret;
|
|
}
|
|
|
|
static int sec_audio_voice_tracking_info_put(struct snd_kcontrol *kcontrol,
|
|
struct snd_ctl_elem_value *ucontrol)
|
|
{
|
|
int ret = 0;
|
|
return ret;
|
|
}
|
|
|
|
static int sec_audio_myspace_put(struct snd_kcontrol *kcontrol,
|
|
struct snd_ctl_elem_value *ucontrol)
|
|
{
|
|
int ret = 0;
|
|
struct msm_pcm_routing_fdai_data fe_dai_map;
|
|
struct audio_client *ac;
|
|
|
|
mutex_lock(&asm_lock);
|
|
msm_pcm_routing_get_fedai_info(SEC_ADAPTATAION_AUDIO_PORT,
|
|
SESSION_TYPE_RX, &fe_dai_map);
|
|
ac = q6asm_get_audio_client(fe_dai_map.strm_id);
|
|
ret = q6asm_set_myspace(ac, (long *)ucontrol->value.integer.value);
|
|
mutex_unlock(&asm_lock);
|
|
return ret;
|
|
}
|
|
|
|
static int sec_audio_sound_boost_put(struct snd_kcontrol *kcontrol,
|
|
struct snd_ctl_elem_value *ucontrol)
|
|
{
|
|
int ret = 0;
|
|
int port_id, copp_idx;
|
|
enum sb_type func_type = (uint32_t)ucontrol->value.integer.value[0];
|
|
|
|
port_id = afe_port.spk_rx_port;
|
|
ret = q6audio_get_copp_idx_from_port_id(port_id, func_type, &copp_idx);
|
|
if (ret) {
|
|
pr_err("%s: Could not get copp idx for port_id=%d\n",
|
|
__func__, port_id);
|
|
|
|
ret = -EINVAL;
|
|
goto done;
|
|
}
|
|
|
|
ret = adm_set_sound_booster(port_id, copp_idx,
|
|
(long *)ucontrol->value.integer.value);
|
|
if (ret) {
|
|
pr_err("%s: Error setting Sound Focus Params, err=%d\n",
|
|
__func__, ret);
|
|
|
|
ret = -EINVAL;
|
|
goto done;
|
|
}
|
|
|
|
done:
|
|
return ret;
|
|
}
|
|
|
|
static int sec_audio_upscaler_put(struct snd_kcontrol *kcontrol,
|
|
struct snd_ctl_elem_value *ucontrol)
|
|
{
|
|
int ret = 0;
|
|
struct msm_pcm_routing_fdai_data fe_dai_map;
|
|
struct audio_client *ac;
|
|
|
|
mutex_lock(&asm_lock);
|
|
msm_pcm_routing_get_fedai_info(SEC_ADAPTATAION_AUDIO_PORT,
|
|
SESSION_TYPE_RX, &fe_dai_map);
|
|
ac = q6asm_get_audio_client(fe_dai_map.strm_id);
|
|
ret = q6asm_set_upscaler(ac, (long *)ucontrol->value.integer.value);
|
|
mutex_unlock(&asm_lock);
|
|
|
|
return ret;
|
|
}
|
|
|
|
/*
|
|
* Stream Information
|
|
* 0 : Deep/Offload
|
|
* 1 : Low Latency
|
|
*
|
|
* Rotation Information
|
|
* 0 : Top up
|
|
* 1 : Left up
|
|
* 2 : Bottom up
|
|
* 3 : Right up
|
|
*/
|
|
static int sec_audio_sb_rotation_put(struct snd_kcontrol *kcontrol,
|
|
struct snd_ctl_elem_value *ucontrol)
|
|
{
|
|
int ret = 0;
|
|
int port_id, copp_idx;
|
|
uint32_t stream = 0;
|
|
uint32_t rotation = 0;
|
|
enum sb_type func_type = SB_MAX;
|
|
|
|
stream = (uint32_t)ucontrol->value.integer.value[0];
|
|
rotation = (uint32_t)ucontrol->value.integer.value[1];
|
|
|
|
switch (stream) {
|
|
case DEEP_OFFLOAD_MODE:
|
|
func_type = SB_ROTATION;
|
|
break;
|
|
case LOW_LATENCY_MODE:
|
|
func_type = SB_ROTATION_LL;
|
|
break;
|
|
case RINGTONE_MODE:
|
|
func_type = SB_ROTATION_RINGTONE;
|
|
break;
|
|
default:
|
|
pr_info("%s: unknown stream type\n", __func__);
|
|
break;
|
|
}
|
|
|
|
port_id = afe_port.spk_rx_port;
|
|
ret = q6audio_get_copp_idx_from_port_id(port_id, func_type, &copp_idx);
|
|
if (ret) {
|
|
pr_err("%s: Could not get copp idx for port_id=%d\n",
|
|
__func__, port_id);
|
|
|
|
ret = -EINVAL;
|
|
goto done;
|
|
}
|
|
|
|
ret = adm_set_sb_rotation(port_id, copp_idx, rotation);
|
|
if (ret) {
|
|
pr_err("%s: Error setting Sound boost rotation, err=%d\n",
|
|
__func__, ret);
|
|
|
|
ret = -EINVAL;
|
|
goto done;
|
|
}
|
|
|
|
done:
|
|
return ret;
|
|
}
|
|
|
|
static int sec_audio_sb_flatmotion_put(struct snd_kcontrol *kcontrol,
|
|
struct snd_ctl_elem_value *ucontrol)
|
|
{
|
|
int ret = 0;
|
|
int port_id, copp_idx;
|
|
|
|
port_id = afe_port.spk_rx_port;
|
|
ret = q6audio_get_copp_idx_from_port_id(port_id, SB_FLATMOTION, &copp_idx);
|
|
if (ret) {
|
|
pr_err("%s: Could not get copp idx for port_id=%d\n",
|
|
__func__, port_id);
|
|
|
|
ret = -EINVAL;
|
|
goto done;
|
|
}
|
|
|
|
ret = adm_set_sb_flatmotion(port_id, copp_idx,
|
|
(long *)ucontrol->value.integer.value);
|
|
if (ret) {
|
|
pr_err("%s: Error setting Sound boost flatmotion, err=%d\n",
|
|
__func__, ret);
|
|
|
|
ret = -EINVAL;
|
|
goto done;
|
|
}
|
|
|
|
done:
|
|
return ret;
|
|
}
|
|
|
|
static int sec_audio_dolby_atmos_put(struct snd_kcontrol *kcontrol,
|
|
struct snd_ctl_elem_value *ucontrol)
|
|
{
|
|
int ret = 0;
|
|
struct msm_pcm_routing_fdai_data fe_dai_map;
|
|
struct audio_client *ac;
|
|
|
|
mutex_lock(&asm_lock);
|
|
msm_pcm_routing_get_fedai_info(SEC_ADAPTATAION_AUDIO_PORT,
|
|
SESSION_TYPE_RX, &fe_dai_map);
|
|
ac = q6asm_get_audio_client(fe_dai_map.strm_id);
|
|
ret = q6asm_set_dolby_atmos(ac, (long *)ucontrol->value.integer.value);
|
|
mutex_unlock(&asm_lock);
|
|
|
|
return ret;
|
|
}
|
|
|
|
static int sec_audio_volume_monitor_put(struct snd_kcontrol *kcontrol,
|
|
struct snd_ctl_elem_value *ucontrol)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static int sec_audio_volume_monitor_data_put(struct snd_kcontrol *kcontrol,
|
|
struct snd_ctl_elem_value *ucontrol)
|
|
{
|
|
int ret = 0;
|
|
int port_id;
|
|
int be_idx = 0;
|
|
int enable = ucontrol->value.integer.value[0];
|
|
int volume_level = ucontrol->value.integer.value[1];
|
|
int avc_support = ucontrol->value.integer.value[2];
|
|
int db_atten = ucontrol->value.integer.value[3];
|
|
|
|
struct msm_pcm_routing_bdai_data msm_bedai;
|
|
|
|
for (be_idx = 0; be_idx < MSM_BACKEND_DAI_MAX; be_idx++) {
|
|
msm_pcm_routing_get_bedai_info(be_idx, &msm_bedai);
|
|
|
|
if (msm_bedai.active) {
|
|
if (msm_bedai.port_id == afe_port.headset_rx_port)
|
|
break;
|
|
if (msm_bedai.port_id == afe_port.bt_rx_port)
|
|
break;
|
|
if (msm_bedai.port_id == afe_port.usb_rx_port)
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (be_idx == MSM_BACKEND_DAI_MAX) {
|
|
pr_info("%s: no active backend port\n", __func__);
|
|
goto done;
|
|
}
|
|
|
|
port_id = msm_bedai.port_id;
|
|
|
|
pr_info("%s: port_id : %x , enable : %d volume_level : %d avc_support : %d db_atten : %d\n",
|
|
__func__, port_id, enable, volume_level, avc_support, db_atten);
|
|
|
|
ret = afe_set_volume_monitor(port_id, enable, volume_level, avc_support, db_atten);
|
|
|
|
if (ret) {
|
|
pr_err("%s: Error setting volume monitor, err=%d\n",
|
|
__func__, ret);
|
|
|
|
ret = -EINVAL;
|
|
goto done;
|
|
}
|
|
|
|
done:
|
|
return ret;
|
|
}
|
|
|
|
static int sec_audio_sa_listenback_enable_put(struct snd_kcontrol *kcontrol,
|
|
struct snd_ctl_elem_value *ucontrol)
|
|
{
|
|
int ret = 0;
|
|
int port_id;
|
|
int be_idx = 0;
|
|
int enable = ucontrol->value.integer.value[0];
|
|
|
|
struct msm_pcm_routing_bdai_data msm_bedai;
|
|
|
|
for (be_idx = 0; be_idx < MSM_BACKEND_DAI_MAX; be_idx++) {
|
|
msm_pcm_routing_get_bedai_info(be_idx, &msm_bedai);
|
|
if (msm_bedai.active) {
|
|
if (msm_bedai.port_id == afe_port.usb_rx_port)
|
|
break;
|
|
if (msm_bedai.port_id == afe_port.headset_rx_port)
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (be_idx == MSM_BACKEND_DAI_MAX) {
|
|
pr_info("%s: no active backend port\n", __func__);
|
|
goto done;
|
|
}
|
|
|
|
port_id = msm_bedai.port_id;
|
|
|
|
pr_info("%s: port_id : %x , enable : %d\n",
|
|
__func__, port_id, enable);
|
|
|
|
ret = afe_set_sa_listenback(port_id, enable);
|
|
|
|
if (ret) {
|
|
pr_err("%s: Error setting set listenback, err=%d\n",
|
|
__func__, ret);
|
|
|
|
ret = -EINVAL;
|
|
goto done;
|
|
}
|
|
|
|
done:
|
|
return ret;
|
|
}
|
|
|
|
/****************************************************************************/
|
|
/*//////////////////////////// VOICE SOLUTION //////////////////////////////*/
|
|
/****************************************************************************/
|
|
/*//////////////////////////// COMMON COMMAND //////////////////////////////*/
|
|
/* This function must be sync up from voice_get_session_by_idx() of q6voice.c */
|
|
static struct voice_data *voice_get_session_by_idx(int idx)
|
|
{
|
|
return ((idx < 0 || idx >= MAX_VOC_SESSIONS) ?
|
|
NULL : &common->voice[idx]);
|
|
}
|
|
|
|
/* This function must be sync up from
|
|
* voice_itr_get_next_session() of q6voice.c
|
|
*/
|
|
static bool voice_itr_get_next_session(struct voice_session_itr *itr,
|
|
struct voice_data **voice)
|
|
{
|
|
bool ret = false;
|
|
|
|
if (itr == NULL)
|
|
return false;
|
|
pr_debug("%s : cur idx = %d session idx = %d\n",
|
|
__func__, itr->cur_idx, itr->session_idx);
|
|
|
|
if (itr->cur_idx <= itr->session_idx) {
|
|
ret = true;
|
|
*voice = voice_get_session_by_idx(itr->cur_idx);
|
|
itr->cur_idx++;
|
|
} else {
|
|
*voice = NULL;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
/* This function must be sync up from voice_itr_init() of q6voice.c */
|
|
static void voice_itr_init(struct voice_session_itr *itr,
|
|
u32 session_id)
|
|
{
|
|
if (itr == NULL)
|
|
return;
|
|
itr->session_idx = voice_get_idx_for_session(session_id);
|
|
if (session_id == ALL_SESSION_VSID)
|
|
itr->cur_idx = 0;
|
|
else
|
|
itr->cur_idx = itr->session_idx;
|
|
}
|
|
|
|
/* This function must be sync up from is_voc_state_active() of q6voice.c */
|
|
static bool is_voc_state_active(int voc_state)
|
|
{
|
|
if ((voc_state == VOC_RUN) ||
|
|
(voc_state == VOC_CHANGE) ||
|
|
(voc_state == VOC_STANDBY))
|
|
return true;
|
|
|
|
return false;
|
|
}
|
|
|
|
/* This function must be sync up from voc_set_error_state() of q6voice.c */
|
|
static void voc_set_error_state(uint16_t reset_proc)
|
|
{
|
|
struct voice_data *v = NULL;
|
|
int i;
|
|
|
|
for (i = 0; i < MAX_VOC_SESSIONS; i++) {
|
|
v = &common->voice[i];
|
|
if (v != NULL) {
|
|
v->voc_state = VOC_ERROR;
|
|
v->rec_info.recording = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* This function must be sync up from
|
|
* is_source_tracking_shared_memory_allocated() of q6voice.c
|
|
*/
|
|
static int is_source_tracking_shared_memory_allocated(void)
|
|
{
|
|
bool ret;
|
|
|
|
pr_debug("%s: Enter\n", __func__);
|
|
|
|
if (common->source_tracking_sh_mem.sh_mem_block.dma_buf != NULL)
|
|
ret = true;
|
|
else
|
|
ret = false;
|
|
|
|
pr_debug("%s: Exit\n", __func__);
|
|
|
|
return ret;
|
|
}
|
|
|
|
/*//////////////////////////// CVS COMMAND //////////////////////////////*/
|
|
/* This function must be sync up from voice_get_cvs_handle() of q6voice.c */
|
|
static u16 voice_get_cvs_handle(struct voice_data *v)
|
|
{
|
|
if (v == NULL) {
|
|
pr_err("%s: v is NULL\n", __func__);
|
|
return 0;
|
|
}
|
|
|
|
pr_debug("%s: cvs_handle %d\n", __func__, v->cvs_handle);
|
|
|
|
return v->cvs_handle;
|
|
}
|
|
|
|
static int32_t q6audio_adaptation_cvs_callback(struct apr_client_data *data,
|
|
void *priv)
|
|
{
|
|
int i = 0;
|
|
uint32_t *ptr = NULL;
|
|
|
|
if ((data == NULL) || (priv == NULL)) {
|
|
pr_err("%s: data or priv is NULL\n", __func__);
|
|
return -EINVAL;
|
|
}
|
|
|
|
if (data->opcode == RESET_EVENTS) {
|
|
pr_debug("%s: reset event = %d %d apr[%pK]\n",
|
|
__func__,
|
|
data->reset_event, data->reset_proc, this_cvs.apr);
|
|
|
|
if (this_cvs.apr) {
|
|
apr_reset(this_cvs.apr);
|
|
atomic_set(&this_cvs.state, 0);
|
|
this_cvs.apr = NULL;
|
|
}
|
|
|
|
/* Sub-system restart is applicable to all sessions. */
|
|
for (i = 0; i < MAX_VOC_SESSIONS; i++)
|
|
common->voice[i].cvs_handle = 0;
|
|
|
|
cal_utils_clear_cal_block_q6maps(MAX_VOICE_CAL_TYPES,
|
|
common->cal_data);
|
|
|
|
/* Free the ION memory and clear handles for Source Tracking */
|
|
if (is_source_tracking_shared_memory_allocated()) {
|
|
msm_audio_ion_free(
|
|
common->source_tracking_sh_mem.sh_mem_block.dma_buf);
|
|
common->source_tracking_sh_mem.mem_handle = 0;
|
|
common->source_tracking_sh_mem.sh_mem_block.dma_buf =
|
|
NULL;
|
|
}
|
|
|
|
voc_set_error_state(data->reset_proc);
|
|
return 0;
|
|
}
|
|
|
|
if (data->opcode == APR_BASIC_RSP_RESULT) {
|
|
if (data->payload_size) {
|
|
ptr = data->payload;
|
|
pr_debug("%x %x\n", ptr[0], ptr[1]);
|
|
if (ptr[1] != 0) {
|
|
pr_err("%s: cmd = 0x%x returned error = 0x%x\n",
|
|
__func__, ptr[0], ptr[1]);
|
|
}
|
|
|
|
switch (ptr[0]) {
|
|
case VSS_ICOMMON_CMD_SET_PARAM_V2:
|
|
case VSS_ICOMMON_CMD_SET_PARAM_V3:
|
|
pr_info("%s: VSS_ICOMMON_CMD_SET_PARAM\n",
|
|
__func__);
|
|
atomic_set(&this_cvs.state, 0);
|
|
wake_up(&this_cvs.wait);
|
|
break;
|
|
default:
|
|
pr_err("%s: cmd = 0x%x\n", __func__, ptr[0]);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static int send_packet_loopback_cmd(struct voice_data *v, int mode)
|
|
{
|
|
struct cvs_set_loopback_enable_cmd cvs_set_loopback_cmd;
|
|
int ret = 0;
|
|
u16 cvs_handle;
|
|
|
|
if (this_cvs.apr == NULL) {
|
|
this_cvs.apr = apr_register("ADSP", "CVS",
|
|
q6audio_adaptation_cvs_callback,
|
|
SEC_ADAPTATAION_LOOPBACK_SRC_PORT,
|
|
&this_cvs);
|
|
}
|
|
cvs_handle = voice_get_cvs_handle(v);
|
|
|
|
/* fill in the header */
|
|
cvs_set_loopback_cmd.hdr.hdr_field =
|
|
APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
|
|
APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
|
|
cvs_set_loopback_cmd.hdr.pkt_size =
|
|
APR_PKT_SIZE(APR_HDR_SIZE,
|
|
sizeof(cvs_set_loopback_cmd) - APR_HDR_SIZE);
|
|
cvs_set_loopback_cmd.hdr.src_port =
|
|
SEC_ADAPTATAION_LOOPBACK_SRC_PORT;
|
|
cvs_set_loopback_cmd.hdr.dest_port = cvs_handle;
|
|
cvs_set_loopback_cmd.hdr.token = 0;
|
|
cvs_set_loopback_cmd.hdr.opcode =
|
|
VSS_ICOMMON_CMD_SET_PARAM_V2;
|
|
cvs_set_loopback_cmd.mem_handle = 0;
|
|
cvs_set_loopback_cmd.mem_address_lsw = 0;
|
|
cvs_set_loopback_cmd.mem_address_msw = 0;
|
|
cvs_set_loopback_cmd.mem_size = 0x10;
|
|
|
|
cvs_set_loopback_cmd.vss_set_loopback.module_id =
|
|
VOICEPROC_MODULE_VENC;
|
|
cvs_set_loopback_cmd.vss_set_loopback.param_id =
|
|
VOICE_PARAM_LOOPBACK_ENABLE;
|
|
cvs_set_loopback_cmd.vss_set_loopback.param_size = 4;
|
|
cvs_set_loopback_cmd.vss_set_loopback.reserved = 0;
|
|
cvs_set_loopback_cmd.vss_set_loopback.loopback_enable = mode;
|
|
cvs_set_loopback_cmd.vss_set_loopback.reserved_field = 0;
|
|
|
|
atomic_set(&this_cvs.state, 1);
|
|
ret = apr_send_pkt(this_cvs.apr, (uint32_t *) &cvs_set_loopback_cmd);
|
|
if (ret < 0) {
|
|
pr_err("%s: sending cvs set loopback enable failed\n",
|
|
__func__);
|
|
goto fail;
|
|
}
|
|
ret = wait_event_timeout(this_cvs.wait,
|
|
(atomic_read(&this_cvs.state) == 0),
|
|
msecs_to_jiffies(TIMEOUT_MS));
|
|
if (!ret) {
|
|
pr_err("%s: wait_event timeout\n", __func__);
|
|
goto fail;
|
|
}
|
|
return 0;
|
|
fail:
|
|
return -EINVAL;
|
|
}
|
|
|
|
int voice_sec_set_loopback_cmd(u32 session_id, uint16_t mode)
|
|
{
|
|
struct voice_data *v = NULL;
|
|
int ret = 0;
|
|
struct voice_session_itr itr;
|
|
|
|
pr_debug("%s: Enter\n", __func__);
|
|
|
|
voice_itr_init(&itr, session_id);
|
|
while (voice_itr_get_next_session(&itr, &v)) {
|
|
if (v != NULL) {
|
|
ret = send_packet_loopback_cmd(v, mode);
|
|
} else {
|
|
pr_err("%s: invalid session\n", __func__);
|
|
ret = -EINVAL;
|
|
break;
|
|
}
|
|
}
|
|
pr_debug("%s: Exit, ret=%d\n", __func__, ret);
|
|
|
|
return ret;
|
|
}
|
|
|
|
void voice_sec_loopback_start_cmd(u32 session_id)
|
|
{
|
|
int ret = 0;
|
|
|
|
if (loopback_mode > LOOPBACK_DISABLE &&
|
|
loopback_mode < LOOPBACK_MAX) {
|
|
ret = voice_sec_set_loopback_cmd(session_id, loopback_mode);
|
|
if (ret < 0) {
|
|
pr_err("%s: send packet loopback cmd failed(%d)\n",
|
|
__func__, ret);
|
|
} else {
|
|
pr_info("%s: enable packet loopback\n",
|
|
__func__);
|
|
}
|
|
}
|
|
}
|
|
|
|
void voice_sec_loopback_end_cmd(u32 session_id)
|
|
{
|
|
int ret = 0;
|
|
|
|
if ((loopback_mode == LOOPBACK_DISABLE) &&
|
|
(loopback_prev_mode > LOOPBACK_DISABLE &&
|
|
loopback_prev_mode < LOOPBACK_MAX)) {
|
|
ret = voice_sec_set_loopback_cmd(session_id, loopback_mode);
|
|
if (ret < 0) {
|
|
pr_err("%s: packet loopback disable cmd failed(%d)\n",
|
|
__func__, ret);
|
|
} else {
|
|
pr_info("%s: disable packet loopback\n",
|
|
__func__);
|
|
}
|
|
loopback_prev_mode = 0;
|
|
}
|
|
}
|
|
|
|
/*//////////////////////////// CVP COMMAND //////////////////////////////*/
|
|
/* This function must be sync up from voice_get_cvp_handle() of q6voice.c */
|
|
static u16 voice_get_cvp_handle(struct voice_data *v)
|
|
{
|
|
if (v == NULL) {
|
|
pr_err("%s: v is NULL\n", __func__);
|
|
return 0;
|
|
}
|
|
|
|
pr_debug("%s: cvp_handle %d\n", __func__, v->cvp_handle);
|
|
|
|
return v->cvp_handle;
|
|
}
|
|
|
|
static int32_t q6audio_adaptation_cvp_callback(struct apr_client_data *data,
|
|
void *priv)
|
|
{
|
|
int i;
|
|
uint32_t *ptr = NULL;
|
|
|
|
if ((data == NULL) || (priv == NULL)) {
|
|
pr_err("%s: data or priv is NULL\n", __func__);
|
|
return -EINVAL;
|
|
}
|
|
|
|
if (data->opcode == RESET_EVENTS) {
|
|
pr_debug("%s: reset event = %d %d apr[%pK]\n",
|
|
__func__,
|
|
data->reset_event, data->reset_proc, this_cvp.apr);
|
|
|
|
if (this_cvp.apr) {
|
|
apr_reset(this_cvp.apr);
|
|
atomic_set(&this_cvp.state, 0);
|
|
this_cvp.apr = NULL;
|
|
}
|
|
|
|
/* Sub-system restart is applicable to all sessions. */
|
|
for (i = 0; i < MAX_VOC_SESSIONS; i++)
|
|
common->voice[i].cvp_handle = 0;
|
|
|
|
cal_utils_clear_cal_block_q6maps(MAX_VOICE_CAL_TYPES,
|
|
common->cal_data);
|
|
|
|
/* Free the ION memory and clear handles for Source Tracking */
|
|
if (is_source_tracking_shared_memory_allocated()) {
|
|
msm_audio_ion_free(
|
|
common->source_tracking_sh_mem.sh_mem_block.dma_buf);
|
|
common->source_tracking_sh_mem.mem_handle = 0;
|
|
common->source_tracking_sh_mem.sh_mem_block.dma_buf =
|
|
NULL;
|
|
}
|
|
|
|
voc_set_error_state(data->reset_proc);
|
|
|
|
return 0;
|
|
}
|
|
|
|
if (data->opcode == APR_BASIC_RSP_RESULT) {
|
|
if (data->payload_size) {
|
|
ptr = data->payload;
|
|
pr_debug("%x %x\n", ptr[0], ptr[1]);
|
|
if (ptr[1] != 0) {
|
|
pr_err("%s: cmd = 0x%x returned error = 0x%x\n",
|
|
__func__, ptr[0], ptr[1]);
|
|
}
|
|
|
|
switch (ptr[0]) {
|
|
case VSS_ICOMMON_CMD_SET_PARAM_V2:
|
|
case VSS_ICOMMON_CMD_SET_PARAM_V3:
|
|
pr_info("%s: VSS_ICOMMON_CMD_SET_PARAM\n",
|
|
__func__);
|
|
atomic_set(&this_cvp.state, 0);
|
|
wake_up(&this_cvp.wait);
|
|
break;
|
|
case VSS_ICOMMON_CMD_GET_PARAM_V2:
|
|
case VSS_ICOMMON_CMD_GET_PARAM_V3:
|
|
pr_info("%s: VSS_ICOMMON_CMD_GET_PARAM\n",
|
|
__func__);
|
|
atomic_set(&this_cvp.state, 0);
|
|
wake_up(&this_cvp.wait);
|
|
break;
|
|
case VSS_ICOMMON_CMD_SET_UI_PROPERTY:
|
|
case VSS_ICOMMON_CMD_SET_UI_PROPERTY_V2:
|
|
pr_info("%s: VSS_ICOMMON_CMD_SET_UI_PROPERTY\n",
|
|
__func__);
|
|
atomic_set(&this_cvp.state, 0);
|
|
wake_up(&this_cvp.wait);
|
|
break;
|
|
default:
|
|
pr_err("%s: cmd = 0x%x\n", __func__, ptr[0]);
|
|
break;
|
|
}
|
|
}
|
|
} else if (data->opcode == VSS_ICOMMON_RSP_GET_PARAM ||
|
|
data->opcode == VSS_ICOMMON_RSP_GET_PARAM_V3) {
|
|
ptr = data->payload;
|
|
pr_info("%s: VSS_ICOMMON_RSP_GET_PARAM, value: %d\n", __func__, ptr[5]);
|
|
echo_ref_mute_val = ptr[5];
|
|
atomic_set(&this_cvp.state, 0);
|
|
wake_up(&this_cvp.wait);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static int sec_voice_send_adaptation_sound_cmd(struct voice_data *v,
|
|
uint16_t mode, uint16_t select, int16_t *parameters)
|
|
{
|
|
struct cvp_adaptation_sound_parm_send_cmd
|
|
cvp_adaptation_sound_param_cmd;
|
|
int ret = 0;
|
|
u16 cvp_handle;
|
|
|
|
if (v == NULL) {
|
|
pr_err("%s: v is NULL\n", __func__);
|
|
return -EINVAL;
|
|
}
|
|
|
|
if (this_cvp.apr == NULL) {
|
|
this_cvp.apr = apr_register("ADSP", "CVP",
|
|
q6audio_adaptation_cvp_callback,
|
|
SEC_ADAPTATAION_VOICE_SRC_PORT,
|
|
&this_cvp);
|
|
}
|
|
cvp_handle = voice_get_cvp_handle(v);
|
|
|
|
/* fill in the header */
|
|
cvp_adaptation_sound_param_cmd.hdr.hdr_field =
|
|
APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
|
|
APR_HDR_LEN(APR_HDR_SIZE),
|
|
APR_PKT_VER);
|
|
cvp_adaptation_sound_param_cmd.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
|
|
sizeof(cvp_adaptation_sound_param_cmd) - APR_HDR_SIZE);
|
|
cvp_adaptation_sound_param_cmd.hdr.src_port =
|
|
SEC_ADAPTATAION_VOICE_SRC_PORT;
|
|
cvp_adaptation_sound_param_cmd.hdr.dest_port = cvp_handle;
|
|
cvp_adaptation_sound_param_cmd.hdr.token = 0;
|
|
cvp_adaptation_sound_param_cmd.hdr.opcode =
|
|
VSS_ICOMMON_CMD_SET_PARAM_V2;
|
|
cvp_adaptation_sound_param_cmd.mem_handle = 0;
|
|
cvp_adaptation_sound_param_cmd.mem_address_lsw = 0;
|
|
cvp_adaptation_sound_param_cmd.mem_address_msw = 0;
|
|
cvp_adaptation_sound_param_cmd.mem_size = 40;
|
|
cvp_adaptation_sound_param_cmd.adaptation_sound_data.module_id =
|
|
VOICE_VOICEMODE_MODULE;
|
|
cvp_adaptation_sound_param_cmd.adaptation_sound_data.param_id =
|
|
VOICE_ADAPTATION_SOUND_PARAM;
|
|
cvp_adaptation_sound_param_cmd.adaptation_sound_data.param_size = 28;
|
|
cvp_adaptation_sound_param_cmd.adaptation_sound_data.reserved = 0;
|
|
cvp_adaptation_sound_param_cmd.adaptation_sound_data.eq_mode = mode;
|
|
cvp_adaptation_sound_param_cmd.adaptation_sound_data.select = select;
|
|
|
|
memcpy(cvp_adaptation_sound_param_cmd.adaptation_sound_data.param,
|
|
parameters, sizeof(int16_t)*12);
|
|
|
|
pr_info("%s: send adaptation_sound param, mode = %d, select=%d\n",
|
|
__func__,
|
|
cvp_adaptation_sound_param_cmd.adaptation_sound_data.eq_mode,
|
|
cvp_adaptation_sound_param_cmd.adaptation_sound_data.select);
|
|
|
|
atomic_set(&this_cvp.state, 1);
|
|
ret = apr_send_pkt(this_cvp.apr,
|
|
(uint32_t *) &cvp_adaptation_sound_param_cmd);
|
|
if (ret < 0) {
|
|
pr_err("%s: Failed to send cvp_adaptation_sound_param_cmd\n",
|
|
__func__);
|
|
return -EINVAL;
|
|
}
|
|
|
|
ret = wait_event_timeout(this_cvp.wait,
|
|
(atomic_read(&this_cvp.state) == 0),
|
|
msecs_to_jiffies(TIMEOUT_MS));
|
|
|
|
if (!ret) {
|
|
pr_err("%s: wait_event timeout\n", __func__);
|
|
return -EINVAL;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int sec_voice_set_adaptation_sound(uint16_t mode,
|
|
uint16_t select, int16_t *parameters)
|
|
{
|
|
struct voice_data *v = NULL;
|
|
int ret = 0;
|
|
struct voice_session_itr itr;
|
|
|
|
pr_debug("%s: Enter\n", __func__);
|
|
|
|
voice_itr_init(&itr, ALL_SESSION_VSID);
|
|
while (voice_itr_get_next_session(&itr, &v)) {
|
|
if (v != NULL) {
|
|
mutex_lock(&v->lock);
|
|
if (is_voc_state_active(v->voc_state) &&
|
|
(v->lch_mode != VOICE_LCH_START) &&
|
|
!v->disable_topology)
|
|
ret = sec_voice_send_adaptation_sound_cmd(v,
|
|
mode, select, parameters);
|
|
mutex_unlock(&v->lock);
|
|
} else {
|
|
pr_err("%s: invalid session\n", __func__);
|
|
ret = -EINVAL;
|
|
break;
|
|
}
|
|
}
|
|
pr_debug("%s: Exit, ret=%d\n", __func__, ret);
|
|
|
|
return ret;
|
|
}
|
|
|
|
static int sec_voice_send_nb_mode_cmd(struct voice_data *v, int enable)
|
|
{
|
|
struct cvp_set_nbmode_enable_cmd cvp_nbmode_cmd;
|
|
int ret = 0;
|
|
u16 cvp_handle;
|
|
|
|
if (v == NULL) {
|
|
pr_err("%s: v is NULL\n", __func__);
|
|
return -EINVAL;
|
|
}
|
|
|
|
if (this_cvp.apr == NULL) {
|
|
this_cvp.apr = apr_register("ADSP", "CVP",
|
|
q6audio_adaptation_cvp_callback,
|
|
SEC_ADAPTATAION_VOICE_SRC_PORT,
|
|
&this_cvp);
|
|
}
|
|
cvp_handle = voice_get_cvp_handle(v);
|
|
|
|
/* fill in the header */
|
|
cvp_nbmode_cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
|
|
APR_HDR_LEN(APR_HDR_SIZE),
|
|
APR_PKT_VER);
|
|
cvp_nbmode_cmd.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
|
|
sizeof(cvp_nbmode_cmd) - APR_HDR_SIZE);
|
|
cvp_nbmode_cmd.hdr.src_port =
|
|
SEC_ADAPTATAION_VOICE_SRC_PORT;
|
|
cvp_nbmode_cmd.hdr.dest_port = cvp_handle;
|
|
cvp_nbmode_cmd.hdr.token = 0;
|
|
cvp_nbmode_cmd.hdr.opcode =
|
|
q6common_is_instance_id_supported() ? VSS_ICOMMON_CMD_SET_UI_PROPERTY_V2 :
|
|
VSS_ICOMMON_CMD_SET_UI_PROPERTY;
|
|
cvp_nbmode_cmd.cvp_set_nbmode.module_id =
|
|
VOICE_VOICEMODE_MODULE;
|
|
cvp_nbmode_cmd.cvp_set_nbmode.instance_id =
|
|
INSTANCE_ID_0;
|
|
cvp_nbmode_cmd.cvp_set_nbmode.param_id =
|
|
VOICE_NBMODE_PARAM;
|
|
cvp_nbmode_cmd.cvp_set_nbmode.param_size = 4;
|
|
cvp_nbmode_cmd.cvp_set_nbmode.reserved = 0;
|
|
cvp_nbmode_cmd.cvp_set_nbmode.enable = enable;
|
|
cvp_nbmode_cmd.cvp_set_nbmode.reserved_field = 0;
|
|
|
|
pr_info("%s: enable = %d\n", __func__,
|
|
cvp_nbmode_cmd.cvp_set_nbmode.enable);
|
|
|
|
atomic_set(&this_cvp.state, 1);
|
|
ret = apr_send_pkt(this_cvp.apr, (uint32_t *) &cvp_nbmode_cmd);
|
|
if (ret < 0) {
|
|
pr_err("%s: Failed to send cvp_nbmode_cmd\n",
|
|
__func__);
|
|
goto fail;
|
|
}
|
|
|
|
ret = wait_event_timeout(this_cvp.wait,
|
|
(atomic_read(&this_cvp.state) == 0),
|
|
msecs_to_jiffies(TIMEOUT_MS));
|
|
if (!ret) {
|
|
pr_err("%s: wait_event timeout\n", __func__);
|
|
goto fail;
|
|
}
|
|
return 0;
|
|
|
|
fail:
|
|
return ret;
|
|
}
|
|
|
|
int sec_voice_set_nb_mode(short enable)
|
|
{
|
|
struct voice_data *v = NULL;
|
|
int ret = 0;
|
|
struct voice_session_itr itr;
|
|
|
|
pr_debug("%s: Enter\n", __func__);
|
|
|
|
voice_itr_init(&itr, ALL_SESSION_VSID);
|
|
while (voice_itr_get_next_session(&itr, &v)) {
|
|
if (v != NULL) {
|
|
mutex_lock(&v->lock);
|
|
if (is_voc_state_active(v->voc_state) &&
|
|
(v->lch_mode != VOICE_LCH_START) &&
|
|
!v->disable_topology)
|
|
ret = sec_voice_send_nb_mode_cmd(v, enable);
|
|
mutex_unlock(&v->lock);
|
|
} else {
|
|
pr_err("%s: invalid session\n", __func__);
|
|
ret = -EINVAL;
|
|
break;
|
|
}
|
|
}
|
|
pr_debug("%s: Exit, ret=%d\n", __func__, ret);
|
|
|
|
return ret;
|
|
}
|
|
|
|
static int sec_voice_send_rcv_mode_cmd(struct voice_data *v, int enable)
|
|
{
|
|
struct cvp_set_rcvmode_enable_cmd cvp_rcvmode_cmd;
|
|
int ret = 0;
|
|
u16 cvp_handle;
|
|
|
|
if (v == NULL) {
|
|
pr_err("%s: v is NULL\n", __func__);
|
|
return -EINVAL;
|
|
}
|
|
|
|
if (this_cvp.apr == NULL) {
|
|
this_cvp.apr = apr_register("ADSP", "CVP",
|
|
q6audio_adaptation_cvp_callback,
|
|
SEC_ADAPTATAION_VOICE_SRC_PORT,
|
|
&this_cvp);
|
|
}
|
|
cvp_handle = voice_get_cvp_handle(v);
|
|
|
|
/* fill in the header */
|
|
cvp_rcvmode_cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
|
|
APR_HDR_LEN(APR_HDR_SIZE),
|
|
APR_PKT_VER);
|
|
cvp_rcvmode_cmd.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
|
|
sizeof(cvp_rcvmode_cmd) - APR_HDR_SIZE);
|
|
cvp_rcvmode_cmd.hdr.src_port = SEC_ADAPTATAION_VOICE_SRC_PORT;
|
|
cvp_rcvmode_cmd.hdr.dest_port = cvp_handle;
|
|
cvp_rcvmode_cmd.hdr.token = 0;
|
|
cvp_rcvmode_cmd.hdr.opcode =
|
|
q6common_is_instance_id_supported() ? VSS_ICOMMON_CMD_SET_UI_PROPERTY_V2 :
|
|
VSS_ICOMMON_CMD_SET_UI_PROPERTY;
|
|
cvp_rcvmode_cmd.cvp_set_rcvmode.module_id = VOICE_VOICEMODE_MODULE;
|
|
cvp_rcvmode_cmd.cvp_set_rcvmode.instance_id =
|
|
INSTANCE_ID_0;
|
|
cvp_rcvmode_cmd.cvp_set_rcvmode.param_id = VOICE_RCVMODE_PARAM;
|
|
cvp_rcvmode_cmd.cvp_set_rcvmode.param_size = 4;
|
|
cvp_rcvmode_cmd.cvp_set_rcvmode.reserved = 0;
|
|
cvp_rcvmode_cmd.cvp_set_rcvmode.enable = enable;
|
|
cvp_rcvmode_cmd.cvp_set_rcvmode.reserved_field = 0;
|
|
|
|
pr_info("%s: Voice Module enable = %d\n", __func__,
|
|
cvp_rcvmode_cmd.cvp_set_rcvmode.enable);
|
|
|
|
atomic_set(&this_cvp.state, 1);
|
|
ret = apr_send_pkt(this_cvp.apr, (uint32_t *) &cvp_rcvmode_cmd);
|
|
if (ret < 0) {
|
|
pr_err("%s: Failed to send cvp_rcvmode_cmd\n", __func__);
|
|
goto fail;
|
|
}
|
|
|
|
ret = wait_event_timeout(this_cvp.wait,
|
|
(atomic_read(&this_cvp.state) == 0),
|
|
msecs_to_jiffies(TIMEOUT_MS));
|
|
if (!ret) {
|
|
pr_err("%s: wait_event timeout\n", __func__);
|
|
goto fail;
|
|
}
|
|
|
|
cvp_rcvmode_cmd.cvp_set_rcvmode.module_id = VOICE_FVSAM_MODULE;
|
|
|
|
pr_info("%s: FVSAM Module enable = %d\n", __func__,
|
|
cvp_rcvmode_cmd.cvp_set_rcvmode.enable);
|
|
|
|
atomic_set(&this_cvp.state, 1);
|
|
ret = apr_send_pkt(this_cvp.apr, (uint32_t *) &cvp_rcvmode_cmd);
|
|
if (ret < 0) {
|
|
pr_err("%s: Failed to send cvp_rcvmode_cmd\n", __func__);
|
|
goto fail;
|
|
}
|
|
|
|
ret = wait_event_timeout(this_cvp.wait,
|
|
(atomic_read(&this_cvp.state) == 0),
|
|
msecs_to_jiffies(TIMEOUT_MS));
|
|
if (!ret) {
|
|
pr_err("%s: wait_event timeout\n", __func__);
|
|
goto fail;
|
|
}
|
|
|
|
cvp_rcvmode_cmd.cvp_set_rcvmode.module_id = VOICE_WISEVOICE_MODULE;
|
|
|
|
pr_info("%s: WiseVoice Module enable = %d\n", __func__,
|
|
cvp_rcvmode_cmd.cvp_set_rcvmode.enable);
|
|
|
|
atomic_set(&this_cvp.state, 1);
|
|
ret = apr_send_pkt(this_cvp.apr, (uint32_t *) &cvp_rcvmode_cmd);
|
|
if (ret < 0) {
|
|
pr_err("%s: Failed to send cvp_rcvmode_cmd\n", __func__);
|
|
goto fail;
|
|
}
|
|
|
|
ret = wait_event_timeout(this_cvp.wait,
|
|
(atomic_read(&this_cvp.state) == 0),
|
|
msecs_to_jiffies(TIMEOUT_MS));
|
|
if (!ret) {
|
|
pr_err("%s: wait_event timeout\n", __func__);
|
|
|
|
goto fail;
|
|
}
|
|
return 0;
|
|
|
|
fail:
|
|
return ret;
|
|
}
|
|
|
|
int sec_voice_set_rcv_mode(short enable)
|
|
{
|
|
struct voice_data *v = NULL;
|
|
int ret = 0;
|
|
struct voice_session_itr itr;
|
|
|
|
pr_debug("%s: Enter\n", __func__);
|
|
|
|
voice_itr_init(&itr, ALL_SESSION_VSID);
|
|
while (voice_itr_get_next_session(&itr, &v)) {
|
|
if (v != NULL) {
|
|
mutex_lock(&v->lock);
|
|
if (is_voc_state_active(v->voc_state) &&
|
|
(v->lch_mode != VOICE_LCH_START) &&
|
|
!v->disable_topology)
|
|
ret = sec_voice_send_rcv_mode_cmd(v, enable);
|
|
mutex_unlock(&v->lock);
|
|
} else {
|
|
pr_err("%s: invalid session\n", __func__);
|
|
ret = -EINVAL;
|
|
break;
|
|
}
|
|
}
|
|
pr_debug("%s: Exit, ret=%d\n", __func__, ret);
|
|
|
|
return ret;
|
|
}
|
|
|
|
static int sec_voice_send_spk_mode_cmd(struct voice_data *v, int enable)
|
|
{
|
|
struct cvp_set_spkmode_enable_cmd cvp_spkmode_cmd;
|
|
int ret = 0;
|
|
u16 cvp_handle;
|
|
|
|
if (v == NULL) {
|
|
pr_err("%s: v is NULL\n", __func__);
|
|
return -EINVAL;
|
|
}
|
|
|
|
if (this_cvp.apr == NULL) {
|
|
this_cvp.apr = apr_register("ADSP", "CVP",
|
|
q6audio_adaptation_cvp_callback,
|
|
SEC_ADAPTATAION_VOICE_SRC_PORT,
|
|
&this_cvp);
|
|
}
|
|
cvp_handle = voice_get_cvp_handle(v);
|
|
|
|
/* fill in the header */
|
|
cvp_spkmode_cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
|
|
APR_HDR_LEN(APR_HDR_SIZE),
|
|
APR_PKT_VER);
|
|
cvp_spkmode_cmd.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
|
|
sizeof(cvp_spkmode_cmd) - APR_HDR_SIZE);
|
|
cvp_spkmode_cmd.hdr.src_port = SEC_ADAPTATAION_VOICE_SRC_PORT;
|
|
cvp_spkmode_cmd.hdr.dest_port = cvp_handle;
|
|
cvp_spkmode_cmd.hdr.token = 0;
|
|
cvp_spkmode_cmd.hdr.opcode =
|
|
q6common_is_instance_id_supported() ? VSS_ICOMMON_CMD_SET_UI_PROPERTY_V2 :
|
|
VSS_ICOMMON_CMD_SET_UI_PROPERTY;
|
|
cvp_spkmode_cmd.cvp_set_spkmode.module_id = VOICE_VOICEMODE_MODULE;
|
|
cvp_spkmode_cmd.cvp_set_spkmode.instance_id =
|
|
INSTANCE_ID_0;
|
|
cvp_spkmode_cmd.cvp_set_spkmode.param_id = VOICE_SPKMODE_PARAM;
|
|
cvp_spkmode_cmd.cvp_set_spkmode.param_size = 4;
|
|
cvp_spkmode_cmd.cvp_set_spkmode.reserved = 0;
|
|
cvp_spkmode_cmd.cvp_set_spkmode.enable = enable;
|
|
cvp_spkmode_cmd.cvp_set_spkmode.reserved_field = 0;
|
|
|
|
pr_info("%s: Voice Module enable = %d\n", __func__,
|
|
cvp_spkmode_cmd.cvp_set_spkmode.enable);
|
|
|
|
atomic_set(&this_cvp.state, 1);
|
|
ret = apr_send_pkt(this_cvp.apr, (uint32_t *) &cvp_spkmode_cmd);
|
|
if (ret < 0) {
|
|
pr_err("%s: Failed to send cvp_spkmode_cmd\n", __func__);
|
|
goto fail;
|
|
}
|
|
|
|
ret = wait_event_timeout(this_cvp.wait,
|
|
(atomic_read(&this_cvp.state) == 0),
|
|
msecs_to_jiffies(TIMEOUT_MS));
|
|
if (!ret) {
|
|
pr_err("%s: wait_event timeout\n", __func__);
|
|
goto fail;
|
|
}
|
|
|
|
cvp_spkmode_cmd.cvp_set_spkmode.module_id = VOICE_FVSAM_MODULE;
|
|
|
|
pr_info("%s: FVSAM Module enable = %d\n", __func__,
|
|
cvp_spkmode_cmd.cvp_set_spkmode.enable);
|
|
|
|
atomic_set(&this_cvp.state, 1);
|
|
ret = apr_send_pkt(this_cvp.apr, (uint32_t *) &cvp_spkmode_cmd);
|
|
if (ret < 0) {
|
|
pr_err("%s: Failed to send cvp_spkmode_cmd\n", __func__);
|
|
goto fail;
|
|
}
|
|
|
|
ret = wait_event_timeout(this_cvp.wait,
|
|
(atomic_read(&this_cvp.state) == 0),
|
|
msecs_to_jiffies(TIMEOUT_MS));
|
|
if (!ret) {
|
|
pr_err("%s: wait_event timeout\n", __func__);
|
|
goto fail;
|
|
}
|
|
|
|
cvp_spkmode_cmd.cvp_set_spkmode.module_id = VOICE_WISEVOICE_MODULE;
|
|
|
|
pr_info("%s: WiseVoice Module enable = %d\n", __func__,
|
|
cvp_spkmode_cmd.cvp_set_spkmode.enable);
|
|
|
|
atomic_set(&this_cvp.state, 1);
|
|
ret = apr_send_pkt(this_cvp.apr, (uint32_t *) &cvp_spkmode_cmd);
|
|
if (ret < 0) {
|
|
pr_err("%s: Failed to send cvp_spkmode_cmd\n", __func__);
|
|
goto fail;
|
|
}
|
|
|
|
ret = wait_event_timeout(this_cvp.wait,
|
|
(atomic_read(&this_cvp.state) == 0),
|
|
msecs_to_jiffies(TIMEOUT_MS));
|
|
if (!ret) {
|
|
pr_err("%s: wait_event timeout\n", __func__);
|
|
|
|
goto fail;
|
|
}
|
|
return 0;
|
|
|
|
fail:
|
|
return ret;
|
|
}
|
|
|
|
int sec_voice_set_spk_mode(short enable)
|
|
{
|
|
struct voice_data *v = NULL;
|
|
int ret = 0;
|
|
struct voice_session_itr itr;
|
|
|
|
pr_debug("%s: Enter\n", __func__);
|
|
|
|
voice_itr_init(&itr, ALL_SESSION_VSID);
|
|
while (voice_itr_get_next_session(&itr, &v)) {
|
|
if (v != NULL) {
|
|
mutex_lock(&v->lock);
|
|
if (is_voc_state_active(v->voc_state) &&
|
|
(v->lch_mode != VOICE_LCH_START) &&
|
|
!v->disable_topology)
|
|
ret = sec_voice_send_spk_mode_cmd(v, enable);
|
|
mutex_unlock(&v->lock);
|
|
} else {
|
|
pr_err("%s: invalid session\n", __func__);
|
|
ret = -EINVAL;
|
|
break;
|
|
}
|
|
}
|
|
pr_debug("%s: Exit, ret=%d\n", __func__, ret);
|
|
|
|
return ret;
|
|
}
|
|
|
|
static int sec_voice_send_device_info_cmd(struct voice_data *v, int device)
|
|
{
|
|
struct cvp_set_device_info_cmd cvp_device_info_cmd;
|
|
int ret = 0;
|
|
u16 cvp_handle;
|
|
|
|
if (v == NULL) {
|
|
pr_err("%s: v is NULL\n", __func__);
|
|
return -EINVAL;
|
|
}
|
|
|
|
if (this_cvp.apr == NULL) {
|
|
this_cvp.apr = apr_register("ADSP", "CVP",
|
|
q6audio_adaptation_cvp_callback,
|
|
SEC_ADAPTATAION_VOICE_SRC_PORT,
|
|
&this_cvp);
|
|
}
|
|
cvp_handle = voice_get_cvp_handle(v);
|
|
|
|
/* fill in the header */
|
|
cvp_device_info_cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
|
|
APR_HDR_LEN(APR_HDR_SIZE),
|
|
APR_PKT_VER);
|
|
cvp_device_info_cmd.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
|
|
sizeof(cvp_device_info_cmd) - APR_HDR_SIZE);
|
|
cvp_device_info_cmd.hdr.src_port = SEC_ADAPTATAION_VOICE_SRC_PORT;
|
|
cvp_device_info_cmd.hdr.dest_port = cvp_handle;
|
|
cvp_device_info_cmd.hdr.token = 0;
|
|
cvp_device_info_cmd.hdr.opcode =
|
|
q6common_is_instance_id_supported() ? VSS_ICOMMON_CMD_SET_UI_PROPERTY_V2 :
|
|
VSS_ICOMMON_CMD_SET_UI_PROPERTY;
|
|
cvp_device_info_cmd.cvp_set_device_info.module_id =
|
|
VOICE_MODULE_SET_DEVICE;
|
|
cvp_device_info_cmd.cvp_set_device_info.instance_id =
|
|
INSTANCE_ID_0;
|
|
cvp_device_info_cmd.cvp_set_device_info.param_id =
|
|
VOICE_MODULE_SET_DEVICE_PARAM;
|
|
cvp_device_info_cmd.cvp_set_device_info.param_size = 4;
|
|
cvp_device_info_cmd.cvp_set_device_info.reserved = 0;
|
|
cvp_device_info_cmd.cvp_set_device_info.enable = device;
|
|
cvp_device_info_cmd.cvp_set_device_info.reserved_field = 0;
|
|
|
|
pr_info("%s(): voice device info = %d\n",
|
|
__func__, cvp_device_info_cmd.cvp_set_device_info.enable);
|
|
|
|
atomic_set(&this_cvp.state, 1);
|
|
ret = apr_send_pkt(this_cvp.apr, (uint32_t *) &cvp_device_info_cmd);
|
|
if (ret < 0) {
|
|
pr_err("%s: Failed to send cvp_set_device_info_cmd\n",
|
|
__func__);
|
|
goto fail;
|
|
}
|
|
|
|
ret = wait_event_timeout(this_cvp.wait,
|
|
(atomic_read(&this_cvp.state) == 0),
|
|
msecs_to_jiffies(TIMEOUT_MS));
|
|
if (!ret) {
|
|
pr_err("%s: wait_event timeout\n", __func__);
|
|
goto fail;
|
|
}
|
|
return 0;
|
|
|
|
fail:
|
|
return ret;
|
|
}
|
|
|
|
int sec_voice_set_device_info(short device)
|
|
{
|
|
struct voice_data *v = NULL;
|
|
int ret = 0;
|
|
struct voice_session_itr itr;
|
|
|
|
pr_debug("%s: Enter\n", __func__);
|
|
|
|
voice_itr_init(&itr, ALL_SESSION_VSID);
|
|
while (voice_itr_get_next_session(&itr, &v)) {
|
|
if (v != NULL) {
|
|
mutex_lock(&v->lock);
|
|
if (is_voc_state_active(v->voc_state) &&
|
|
(v->lch_mode != VOICE_LCH_START) &&
|
|
!v->disable_topology)
|
|
ret = sec_voice_send_device_info_cmd(v, device);
|
|
mutex_unlock(&v->lock);
|
|
} else {
|
|
pr_err("%s: invalid session\n", __func__);
|
|
ret = -EINVAL;
|
|
break;
|
|
}
|
|
}
|
|
pr_debug("%s: Exit, ret=%d\n", __func__, ret);
|
|
|
|
return ret;
|
|
}
|
|
|
|
static int sec_voice_send_ref_lch_mute_cmd(struct voice_data *v, int enable)
|
|
{
|
|
struct cvp_set_ref_lch_mute_enable_cmd cvp_ref_lch_mute_cmd;
|
|
int ret = 0;
|
|
u16 cvp_handle;
|
|
|
|
if (v == NULL) {
|
|
pr_err("%s: v is NULL\n", __func__);
|
|
return -EINVAL;
|
|
}
|
|
|
|
if (this_cvp.apr == NULL) {
|
|
this_cvp.apr = apr_register("ADSP", "CVP",
|
|
q6audio_adaptation_cvp_callback,
|
|
SEC_ADAPTATAION_VOICE_SRC_PORT,
|
|
&this_cvp);
|
|
}
|
|
cvp_handle = voice_get_cvp_handle(v);
|
|
|
|
/* fill in the header */
|
|
cvp_ref_lch_mute_cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
|
|
APR_HDR_LEN(APR_HDR_SIZE),
|
|
APR_PKT_VER);
|
|
cvp_ref_lch_mute_cmd.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
|
|
sizeof(cvp_ref_lch_mute_cmd) - APR_HDR_SIZE);
|
|
cvp_ref_lch_mute_cmd.hdr.src_port = SEC_ADAPTATAION_VOICE_SRC_PORT;
|
|
cvp_ref_lch_mute_cmd.hdr.dest_port = cvp_handle;
|
|
cvp_ref_lch_mute_cmd.hdr.token = 0;
|
|
cvp_ref_lch_mute_cmd.hdr.opcode =
|
|
q6common_is_instance_id_supported() ? VSS_ICOMMON_CMD_SET_UI_PROPERTY_V2 :
|
|
VSS_ICOMMON_CMD_SET_UI_PROPERTY;
|
|
cvp_ref_lch_mute_cmd.cvp_set_ref_lch_mute.module_id = VOICE_MODULE_LVVEFQ_TX;
|
|
cvp_ref_lch_mute_cmd.cvp_set_ref_lch_mute.instance_id = 0x8000;
|
|
cvp_ref_lch_mute_cmd.cvp_set_ref_lch_mute.param_id = VOICE_ECHO_REF_LCH_MUTE_PARAM;
|
|
cvp_ref_lch_mute_cmd.cvp_set_ref_lch_mute.param_size = 4;
|
|
cvp_ref_lch_mute_cmd.cvp_set_ref_lch_mute.reserved = 0;
|
|
cvp_ref_lch_mute_cmd.cvp_set_ref_lch_mute.enable = enable;
|
|
cvp_ref_lch_mute_cmd.cvp_set_ref_lch_mute.reserved_field = 0;
|
|
|
|
pr_info("%s: lvvefq module enable(%d)\n", __func__,
|
|
cvp_ref_lch_mute_cmd.cvp_set_ref_lch_mute.enable);
|
|
|
|
atomic_set(&this_cvp.state, 1);
|
|
ret = apr_send_pkt(this_cvp.apr, (uint32_t *) &cvp_ref_lch_mute_cmd);
|
|
if (ret < 0) {
|
|
pr_err("%s: Failed to send cvp_ref_lch_mute_cmd\n",
|
|
__func__);
|
|
goto fail;
|
|
}
|
|
|
|
ret = wait_event_timeout(this_cvp.wait,
|
|
(atomic_read(&this_cvp.state) == 0),
|
|
msecs_to_jiffies(TIMEOUT_MS));
|
|
if (!ret) {
|
|
pr_err("%s: wait_event timeout\n", __func__);
|
|
goto fail;
|
|
}
|
|
|
|
cvp_ref_lch_mute_cmd.cvp_set_ref_lch_mute.module_id = TX_VOICE_SOLOMONVOICE;
|
|
|
|
pr_info("%s: solomon module enable(%d)\n", __func__,
|
|
cvp_ref_lch_mute_cmd.cvp_set_ref_lch_mute.enable);
|
|
|
|
atomic_set(&this_cvp.state, 1);
|
|
ret = apr_send_pkt(this_cvp.apr, (uint32_t *) &cvp_ref_lch_mute_cmd);
|
|
if (ret < 0) {
|
|
pr_err("%s: Failed to send cvp_ref_lch_mute_cmd\n",
|
|
__func__);
|
|
goto fail;
|
|
}
|
|
|
|
ret = wait_event_timeout(this_cvp.wait,
|
|
(atomic_read(&this_cvp.state) == 0),
|
|
msecs_to_jiffies(TIMEOUT_MS));
|
|
if (!ret) {
|
|
pr_err("%s: wait_event timeout\n", __func__);
|
|
goto fail;
|
|
}
|
|
return 0;
|
|
|
|
fail:
|
|
return ret;
|
|
}
|
|
|
|
int sec_voice_ref_lch_mute(short enable)
|
|
{
|
|
struct voice_data *v = NULL;
|
|
int ret = 0;
|
|
struct voice_session_itr itr;
|
|
|
|
pr_debug("%s: Enter\n", __func__);
|
|
|
|
voice_itr_init(&itr, ALL_SESSION_VSID);
|
|
while (voice_itr_get_next_session(&itr, &v)) {
|
|
if (v != NULL) {
|
|
mutex_lock(&v->lock);
|
|
if (is_voc_state_active(v->voc_state) &&
|
|
(v->lch_mode != VOICE_LCH_START) &&
|
|
!v->disable_topology)
|
|
ret = sec_voice_send_ref_lch_mute_cmd(v, enable);
|
|
mutex_unlock(&v->lock);
|
|
} else {
|
|
pr_err("%s: invalid session\n", __func__);
|
|
ret = -EINVAL;
|
|
break;
|
|
}
|
|
}
|
|
pr_debug("%s: Exit, ret=%d\n", __func__, ret);
|
|
|
|
return ret;
|
|
}
|
|
|
|
static int sec_voice_send_get_echo_ref_mute_cmd(struct voice_data *v)
|
|
{
|
|
struct cvp_get_echo_ref_mute_cmd cvp_echo_ref_mute_cmd;
|
|
int ret = 0;
|
|
u16 cvp_handle;
|
|
|
|
pr_info("%s: Enter\n", __func__);
|
|
|
|
if (v == NULL) {
|
|
pr_err("%s: v is NULL\n", __func__);
|
|
return -EINVAL;
|
|
}
|
|
|
|
if (this_cvp.apr == NULL) {
|
|
this_cvp.apr = apr_register("ADSP", "CVP",
|
|
q6audio_adaptation_cvp_callback,
|
|
SEC_ADAPTATAION_VOICE_SRC_PORT,
|
|
&this_cvp);
|
|
}
|
|
cvp_handle = voice_get_cvp_handle(v);
|
|
|
|
cvp_echo_ref_mute_cmd.cvp_get_echo_ref_mute.mem_handle = 0;
|
|
cvp_echo_ref_mute_cmd.cvp_get_echo_ref_mute.mem_address = 0;
|
|
cvp_echo_ref_mute_cmd.cvp_get_echo_ref_mute.mem_size = sizeof(struct vss_icommon_cmd_get_param_v3_t) + 2;
|
|
cvp_echo_ref_mute_cmd.cvp_get_echo_ref_mute.module_id = VOICE_MODULE_ECHO_REF_MUTE;
|
|
cvp_echo_ref_mute_cmd.cvp_get_echo_ref_mute.instance_id = 0x8000;
|
|
cvp_echo_ref_mute_cmd.cvp_get_echo_ref_mute.reserved = 0;
|
|
cvp_echo_ref_mute_cmd.cvp_get_echo_ref_mute.param_id = VOICE_MODULE_ECHO_REF_MUTE_PARAM;
|
|
|
|
/* fill in the header */
|
|
cvp_echo_ref_mute_cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
|
|
APR_HDR_LEN(APR_HDR_SIZE),
|
|
APR_PKT_VER);
|
|
cvp_echo_ref_mute_cmd.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
|
|
sizeof(cvp_echo_ref_mute_cmd) - APR_HDR_SIZE);
|
|
cvp_echo_ref_mute_cmd.hdr.src_port = SEC_ADAPTATAION_VOICE_SRC_PORT;
|
|
cvp_echo_ref_mute_cmd.hdr.dest_port = cvp_handle;
|
|
cvp_echo_ref_mute_cmd.hdr.token = 0;
|
|
cvp_echo_ref_mute_cmd.hdr.opcode =
|
|
q6common_is_instance_id_supported() ? VSS_ICOMMON_CMD_GET_PARAM_V3 :
|
|
VSS_ICOMMON_CMD_GET_PARAM_V2;
|
|
|
|
atomic_set(&this_cvp.state, 1);
|
|
ret = apr_send_pkt(this_cvp.apr, (uint32_t *) &cvp_echo_ref_mute_cmd);
|
|
if (ret < 0) {
|
|
pr_err("%s: Failed to send cvp_set_echo_ref_mute_cmd\n",
|
|
__func__);
|
|
goto fail;
|
|
}
|
|
|
|
ret = wait_event_timeout(this_cvp.wait,
|
|
(atomic_read(&this_cvp.state) == 0),
|
|
msecs_to_jiffies(TIMEOUT_MS));
|
|
if (!ret) {
|
|
pr_err("%s: wait_event timeout\n", __func__);
|
|
goto fail;
|
|
}
|
|
|
|
return 0;
|
|
|
|
fail:
|
|
return ret;
|
|
}
|
|
|
|
int sec_voice_get_echo_ref_mute(void)
|
|
{
|
|
struct voice_data *v = NULL;
|
|
int ret = 0;
|
|
struct voice_session_itr itr;
|
|
|
|
voice_itr_init(&itr, ALL_SESSION_VSID);
|
|
while (voice_itr_get_next_session(&itr, &v)) {
|
|
if (v != NULL) {
|
|
mutex_lock(&v->lock);
|
|
if (is_voc_state_active(v->voc_state) &&
|
|
(v->lch_mode != VOICE_LCH_START) &&
|
|
!v->disable_topology)
|
|
ret = sec_voice_send_get_echo_ref_mute_cmd(v);
|
|
mutex_unlock(&v->lock);
|
|
} else {
|
|
pr_err("%s: invalid session\n", __func__);
|
|
ret = -EINVAL;
|
|
break;
|
|
}
|
|
}
|
|
pr_info("%s: Exit, ret=%d\n", __func__, ret);
|
|
|
|
return ret;
|
|
}
|
|
|
|
static int sec_voice_send_aec_effect_cmd(struct voice_data *v, int enable)
|
|
{
|
|
struct cvp_set_aec_effect_cmd cvp_aec_effect_cmd;
|
|
uint32_t topology = VOICE_TX_SOLOMONVOICE_SM;
|
|
uint32_t module_id = TX_VOICE_SOLOMONVOICE;
|
|
u16 cvp_handle;
|
|
int ret = 0;
|
|
|
|
if (v == NULL) {
|
|
pr_err("%s: v is NULL\n", __func__);
|
|
return -EINVAL;
|
|
}
|
|
|
|
if (this_cvp.apr == NULL) {
|
|
this_cvp.apr = apr_register("ADSP", "CVP",
|
|
q6audio_adaptation_cvp_callback,
|
|
SEC_ADAPTATAION_VOICE_SRC_PORT,
|
|
&this_cvp);
|
|
}
|
|
|
|
topology = voice_get_topology(CVP_VOC_TX_TOPOLOGY_CAL);
|
|
|
|
switch (topology) {
|
|
case VPM_TX_SM_LVVEFQ_COPP_TOPOLOGY:
|
|
case VPM_TX_DM_LVVEFQ_COPP_TOPOLOGY:
|
|
case VPM_TX_QM_LVVEFQ_COPP_TOPOLOGY:
|
|
case VPM_TX_SM_LVSAFQ_COPP_TOPOLOGY:
|
|
case VPM_TX_DM_LVSAFQ_COPP_TOPOLOGY:
|
|
module_id = VOICE_MODULE_LVVEFQ_TX;
|
|
break;
|
|
case VOICE_TX_DIAMONDVOICE_FVSAM_SM:
|
|
case VOICE_TX_DIAMONDVOICE_FVSAM_DM:
|
|
case VOICE_TX_DIAMONDVOICE_FVSAM_QM:
|
|
case VOICE_TX_DIAMONDVOICE_FRSAM_DM:
|
|
module_id = VOICE_FVSAM_MODULE;
|
|
break;
|
|
case VOICE_TX_SOLOMONVOICE_SM:
|
|
case VOICE_TX_SOLOMONVOICE_DM:
|
|
case VOICE_TX_SOLOMONVOICE_QM:
|
|
module_id = TX_VOICE_SOLOMONVOICE;
|
|
break;
|
|
default:
|
|
pr_err("%s: undefined topology(0x%x)\n",
|
|
__func__, topology);
|
|
break;
|
|
}
|
|
|
|
cvp_handle = voice_get_cvp_handle(v);
|
|
/* fill in the header */
|
|
cvp_aec_effect_cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
|
|
APR_HDR_LEN(APR_HDR_SIZE),
|
|
APR_PKT_VER);
|
|
cvp_aec_effect_cmd.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
|
|
sizeof(cvp_aec_effect_cmd) - APR_HDR_SIZE);
|
|
cvp_aec_effect_cmd.hdr.src_port = SEC_ADAPTATAION_VOICE_SRC_PORT;
|
|
cvp_aec_effect_cmd.hdr.dest_port = cvp_handle;
|
|
cvp_aec_effect_cmd.hdr.token = 0;
|
|
cvp_aec_effect_cmd.hdr.opcode =
|
|
q6common_is_instance_id_supported() ? VSS_ICOMMON_CMD_SET_UI_PROPERTY_V2 :
|
|
VSS_ICOMMON_CMD_SET_UI_PROPERTY;
|
|
cvp_aec_effect_cmd.cvp_set_aec_effect.module_id = module_id;
|
|
cvp_aec_effect_cmd.cvp_set_aec_effect.instance_id = 0x8000;
|
|
cvp_aec_effect_cmd.cvp_set_aec_effect.param_id = VOICE_NREC_MODE_DYNAMIC_PARAM;
|
|
cvp_aec_effect_cmd.cvp_set_aec_effect.param_size = 4;
|
|
cvp_aec_effect_cmd.cvp_set_aec_effect.reserved = 0;
|
|
cvp_aec_effect_cmd.cvp_set_aec_effect.enable = enable;
|
|
cvp_aec_effect_cmd.cvp_set_aec_effect.reserved_field = 0;
|
|
|
|
pr_info("%s: module=0x%x, enable(%d)\n", __func__,
|
|
module_id,
|
|
cvp_aec_effect_cmd.cvp_set_aec_effect.enable);
|
|
|
|
atomic_set(&this_cvp.state, 1);
|
|
ret = apr_send_pkt(this_cvp.apr, (uint32_t *) &cvp_aec_effect_cmd);
|
|
if (ret < 0) {
|
|
pr_err("%s: Failed to send cvp_aec_effect_cmd\n",
|
|
__func__);
|
|
goto fail;
|
|
}
|
|
|
|
ret = wait_event_timeout(this_cvp.wait,
|
|
(atomic_read(&this_cvp.state) == 0),
|
|
msecs_to_jiffies(TIMEOUT_MS));
|
|
if (!ret) {
|
|
pr_err("%s: wait_event timeout\n", __func__);
|
|
goto fail;
|
|
}
|
|
return 0;
|
|
|
|
fail:
|
|
return ret;
|
|
}
|
|
|
|
int sec_voice_aec_effect(short enable)
|
|
{
|
|
struct voice_data *v = NULL;
|
|
int ret = 0;
|
|
struct voice_session_itr itr;
|
|
|
|
pr_debug("%s: Enter\n", __func__);
|
|
|
|
voice_itr_init(&itr, ALL_SESSION_VSID);
|
|
while (voice_itr_get_next_session(&itr, &v)) {
|
|
if (v != NULL) {
|
|
mutex_lock(&v->lock);
|
|
if (is_voc_state_active(v->voc_state) &&
|
|
(v->lch_mode != VOICE_LCH_START) &&
|
|
!v->disable_topology)
|
|
ret = sec_voice_send_aec_effect_cmd(v, enable);
|
|
mutex_unlock(&v->lock);
|
|
} else {
|
|
pr_err("%s: invalid session\n", __func__);
|
|
ret = -EINVAL;
|
|
break;
|
|
}
|
|
}
|
|
pr_debug("%s: Exit, ret=%d\n", __func__, ret);
|
|
|
|
return ret;
|
|
}
|
|
|
|
static int sec_afe_remote_mic_vol(int index)
|
|
{
|
|
int ret = 0;
|
|
int port_id;
|
|
int be_idx = 0;
|
|
struct msm_pcm_routing_bdai_data msm_bedai;
|
|
|
|
for (be_idx = 0; be_idx < MSM_BACKEND_DAI_MAX; be_idx++) {
|
|
msm_pcm_routing_get_bedai_info(be_idx, &msm_bedai);
|
|
if (msm_bedai.active) {
|
|
if (msm_bedai.port_id == afe_port.device_tx_port)
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (be_idx == MSM_BACKEND_DAI_MAX) {
|
|
pr_info("%s: no active backend port\n", __func__);
|
|
goto done;
|
|
}
|
|
|
|
port_id = msm_bedai.port_id;
|
|
|
|
pr_info("%s: port_id : %x , index : %d\n",
|
|
__func__, port_id, index);
|
|
|
|
ret = afe_set_remote_mic_vol(port_id, index);
|
|
|
|
if (ret) {
|
|
pr_err("%s: Error setting set listenback, err=%d\n",
|
|
__func__, ret);
|
|
|
|
ret = -EINVAL;
|
|
goto done;
|
|
}
|
|
|
|
done:
|
|
return ret;
|
|
}
|
|
|
|
static int sec_voice_voice_isolation_cmd(struct voice_data *v, int mode)
|
|
{
|
|
struct cvp_set_voice_isolation_cmd cvp_voice_isolation_cmd;
|
|
int ret = 0;
|
|
u16 cvp_handle;
|
|
|
|
if (v == NULL) {
|
|
pr_err("%s: v is NULL\n", __func__);
|
|
return -EINVAL;
|
|
}
|
|
|
|
if (this_cvp.apr == NULL) {
|
|
this_cvp.apr = apr_register("ADSP", "CVP",
|
|
q6audio_adaptation_cvp_callback,
|
|
SEC_ADAPTATAION_VOICE_SRC_PORT,
|
|
&this_cvp);
|
|
}
|
|
cvp_handle = voice_get_cvp_handle(v);
|
|
|
|
/* fill in the header */
|
|
cvp_voice_isolation_cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
|
|
APR_HDR_LEN(APR_HDR_SIZE),
|
|
APR_PKT_VER);
|
|
cvp_voice_isolation_cmd.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
|
|
sizeof(cvp_voice_isolation_cmd) - APR_HDR_SIZE);
|
|
cvp_voice_isolation_cmd.hdr.src_port = SEC_ADAPTATAION_VOICE_SRC_PORT;
|
|
cvp_voice_isolation_cmd.hdr.dest_port = cvp_handle;
|
|
cvp_voice_isolation_cmd.hdr.token = 0;
|
|
cvp_voice_isolation_cmd.hdr.opcode =
|
|
q6common_is_instance_id_supported() ? VSS_ICOMMON_CMD_SET_UI_PROPERTY_V2 :
|
|
VSS_ICOMMON_CMD_SET_UI_PROPERTY;
|
|
cvp_voice_isolation_cmd.cvp_set_voice_isolation.module_id =
|
|
VOICE_MODULE_LVVEFQ_TX;
|
|
cvp_voice_isolation_cmd.cvp_set_voice_isolation.instance_id =
|
|
0x8000;
|
|
cvp_voice_isolation_cmd.cvp_set_voice_isolation.param_id =
|
|
ENHANCED_VT_CALL_DYNAMIC_PARAM;
|
|
cvp_voice_isolation_cmd.cvp_set_voice_isolation.param_size = 4;
|
|
cvp_voice_isolation_cmd.cvp_set_voice_isolation.reserved = 0;
|
|
cvp_voice_isolation_cmd.cvp_set_voice_isolation.enable = mode;
|
|
cvp_voice_isolation_cmd.cvp_set_voice_isolation.reserved_field = 0;
|
|
|
|
pr_info("%s: voice isolation info = %d\n",
|
|
__func__, cvp_voice_isolation_cmd.cvp_set_voice_isolation.enable);
|
|
|
|
atomic_set(&this_cvp.state, 1);
|
|
ret = apr_send_pkt(this_cvp.apr, (uint32_t *) &cvp_voice_isolation_cmd);
|
|
if (ret < 0) {
|
|
pr_err("%s: Failed to send cvp_voice_isolation_cmd\n",
|
|
__func__);
|
|
goto fail;
|
|
}
|
|
|
|
ret = wait_event_timeout(this_cvp.wait,
|
|
(atomic_read(&this_cvp.state) == 0),
|
|
msecs_to_jiffies(TIMEOUT_MS));
|
|
if (!ret) {
|
|
pr_err("%s: wait_event timeout\n", __func__);
|
|
goto fail;
|
|
}
|
|
return 0;
|
|
|
|
fail:
|
|
return ret;
|
|
}
|
|
|
|
int sec_voice_isolation_mode(short mode)
|
|
{
|
|
struct voice_data *v = NULL;
|
|
int ret = 0;
|
|
struct voice_session_itr itr;
|
|
|
|
pr_debug("%s: mode is %d\n", __func__, mode);
|
|
|
|
voice_itr_init(&itr, ALL_SESSION_VSID);
|
|
while (voice_itr_get_next_session(&itr, &v)) {
|
|
if (v != NULL) {
|
|
mutex_lock(&v->lock);
|
|
if (is_voc_state_active(v->voc_state) &&
|
|
(v->lch_mode != VOICE_LCH_START) &&
|
|
!v->disable_topology)
|
|
ret = sec_voice_voice_isolation_cmd(v, mode);
|
|
mutex_unlock(&v->lock);
|
|
} else {
|
|
pr_err("%s: invalid session\n", __func__);
|
|
ret = -EINVAL;
|
|
break;
|
|
}
|
|
}
|
|
pr_debug("%s: Exit, ret=%d\n", __func__, ret);
|
|
|
|
return ret;
|
|
}
|
|
|
|
int sec_voice_get_loopback_enable(void)
|
|
{
|
|
return loopback_mode;
|
|
}
|
|
|
|
void sec_voice_set_loopback_enable(int mode)
|
|
{
|
|
loopback_prev_mode = loopback_mode;
|
|
|
|
if (mode >= LOOPBACK_MAX ||
|
|
mode < LOOPBACK_DISABLE) {
|
|
pr_err("%s : out of range, mode = %d\n",
|
|
__func__, mode);
|
|
loopback_mode = LOOPBACK_DISABLE;
|
|
} else {
|
|
loopback_mode = mode;
|
|
}
|
|
|
|
pr_info("%s : prev_mode = %d, mode = %d\n",
|
|
__func__,
|
|
loopback_prev_mode,
|
|
loopback_mode);
|
|
}
|
|
|
|
static int sec_voice_adaptation_sound_get(struct snd_kcontrol *kcontrol,
|
|
struct snd_ctl_elem_value *ucontrol)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static int sec_voice_adaptation_sound_put(struct snd_kcontrol *kcontrol,
|
|
struct snd_ctl_elem_value *ucontrol)
|
|
{
|
|
int i = 0;
|
|
|
|
int adaptation_sound_mode = ucontrol->value.integer.value[0];
|
|
int adaptation_sound_select = ucontrol->value.integer.value[1];
|
|
short adaptation_sound_param[12] = {0,};
|
|
|
|
for (i = 0; i < 12; i++) {
|
|
adaptation_sound_param[i] =
|
|
(short)ucontrol->value.integer.value[2+i];
|
|
pr_debug("%s : param - %d\n",
|
|
__func__, adaptation_sound_param[i]);
|
|
}
|
|
|
|
return sec_voice_set_adaptation_sound(adaptation_sound_mode,
|
|
adaptation_sound_select,
|
|
adaptation_sound_param);
|
|
}
|
|
|
|
static int sec_voice_nb_mode_get(struct snd_kcontrol *kcontrol,
|
|
struct snd_ctl_elem_value *ucontrol)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static int sec_voice_nb_mode_put(struct snd_kcontrol *kcontrol,
|
|
struct snd_ctl_elem_value *ucontrol)
|
|
{
|
|
int enable = ucontrol->value.integer.value[0];
|
|
|
|
pr_info("%s: enable=%d\n", __func__, enable);
|
|
|
|
return sec_voice_set_nb_mode(enable);
|
|
}
|
|
|
|
static int sec_voice_rcv_mode_get(struct snd_kcontrol *kcontrol,
|
|
struct snd_ctl_elem_value *ucontrol)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static int sec_voice_rcv_mode_put(struct snd_kcontrol *kcontrol,
|
|
struct snd_ctl_elem_value *ucontrol)
|
|
{
|
|
int enable = ucontrol->value.integer.value[0];
|
|
|
|
pr_info("%s: enable=%d\n", __func__, enable);
|
|
|
|
return sec_voice_set_rcv_mode(enable);
|
|
}
|
|
|
|
static int sec_voice_spk_mode_get(struct snd_kcontrol *kcontrol,
|
|
struct snd_ctl_elem_value *ucontrol)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static int sec_voice_spk_mode_put(struct snd_kcontrol *kcontrol,
|
|
struct snd_ctl_elem_value *ucontrol)
|
|
{
|
|
int enable = ucontrol->value.integer.value[0];
|
|
|
|
pr_debug("%s: enable=%d\n", __func__, enable);
|
|
|
|
return sec_voice_set_spk_mode(enable);
|
|
}
|
|
|
|
static int sec_voice_loopback_put(struct snd_kcontrol *kcontrol,
|
|
struct snd_ctl_elem_value *ucontrol)
|
|
{
|
|
int loopback_enable = ucontrol->value.integer.value[0];
|
|
|
|
pr_info("%s: loopback enable=%d\n", __func__, loopback_enable);
|
|
|
|
sec_voice_set_loopback_enable(loopback_enable);
|
|
return 0;
|
|
}
|
|
|
|
static int sec_voice_loopback_get(struct snd_kcontrol *kcontrol,
|
|
struct snd_ctl_elem_value *ucontrol)
|
|
{
|
|
ucontrol->value.integer.value[0] = sec_voice_get_loopback_enable();
|
|
return 0;
|
|
}
|
|
|
|
static const char * const voice_device[] = {
|
|
"ETC", "SPK", "EAR", "BT", "RCV"
|
|
};
|
|
|
|
static const struct soc_enum sec_voice_device_enum[] = {
|
|
SOC_ENUM_SINGLE_EXT(5, voice_device),
|
|
};
|
|
|
|
static int sec_voice_dev_info_get(struct snd_kcontrol *kcontrol,
|
|
struct snd_ctl_elem_value *ucontrol)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static int sec_voice_dev_info_put(struct snd_kcontrol *kcontrol,
|
|
struct snd_ctl_elem_value *ucontrol)
|
|
{
|
|
int voc_dev = ucontrol->value.integer.value[0];
|
|
|
|
pr_debug("%s: voice device=%d\n", __func__, voc_dev);
|
|
|
|
return sec_voice_set_device_info(voc_dev);
|
|
}
|
|
|
|
static int sec_voice_ref_lch_mute_get(struct snd_kcontrol *kcontrol,
|
|
struct snd_ctl_elem_value *ucontrol)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static int sec_voice_ref_lch_mute_put(struct snd_kcontrol *kcontrol,
|
|
struct snd_ctl_elem_value *ucontrol)
|
|
{
|
|
int enable = ucontrol->value.integer.value[0];
|
|
|
|
pr_info("%s: enable=%d\n", __func__, enable);
|
|
|
|
return sec_voice_ref_lch_mute(enable);
|
|
}
|
|
|
|
static int sec_voice_echo_ref_mute_get(struct snd_kcontrol *kcontrol,
|
|
struct snd_ctl_elem_value *ucontrol)
|
|
{
|
|
int value = 0;
|
|
int ret = 0;
|
|
|
|
echo_ref_mute_val = 0;
|
|
ret = sec_voice_get_echo_ref_mute();
|
|
|
|
if (!ret) {
|
|
value = echo_ref_mute_val;
|
|
} else {
|
|
pr_err("%s: failed to get echo ref mute value %d\n", __func__, ret);
|
|
return -EINVAL;
|
|
}
|
|
pr_info("%s: value=%d\n", __func__, value);
|
|
|
|
ucontrol->value.integer.value[0] = value;
|
|
return 0;
|
|
}
|
|
|
|
static int sec_voice_echo_ref_mute_put(struct snd_kcontrol *kcontrol,
|
|
struct snd_ctl_elem_value *ucontrol)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static const char * const aec_switch[] = {
|
|
"OFF", "ON"
|
|
};
|
|
|
|
static const struct soc_enum sec_aec_effect_enum[] = {
|
|
SOC_ENUM_SINGLE_EXT(2, aec_switch),
|
|
};
|
|
|
|
static int sec_voice_aec_effect_get(struct snd_kcontrol *kcontrol,
|
|
struct snd_ctl_elem_value *ucontrol)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static int sec_voice_aec_effect_put(struct snd_kcontrol *kcontrol,
|
|
struct snd_ctl_elem_value *ucontrol)
|
|
{
|
|
int enable = ucontrol->value.integer.value[0];
|
|
|
|
pr_debug("%s: enable=%d\n", __func__, enable);
|
|
|
|
return sec_voice_aec_effect(enable);
|
|
}
|
|
|
|
static int sec_remote_mic_vol_get(struct snd_kcontrol *kcontrol,
|
|
struct snd_ctl_elem_value *ucontrol)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static int sec_remote_mic_vol_put(struct snd_kcontrol *kcontrol,
|
|
struct snd_ctl_elem_value *ucontrol)
|
|
{
|
|
int volumeindex = ucontrol->value.integer.value[0];
|
|
|
|
if ((volumeindex < 0) || (volumeindex > 15)) {
|
|
pr_err("%s: volumeindex=%d is wrong value\n", __func__, volumeindex);
|
|
return -EINVAL;
|
|
}
|
|
|
|
pr_debug("%s: volumeindex=%d\n", __func__, volumeindex);
|
|
|
|
return sec_afe_remote_mic_vol(volumeindex);
|
|
}
|
|
|
|
static const char * const voice_isolate[] = {
|
|
"Standard", "VoiceFocus", "AllSound"
|
|
};
|
|
|
|
static const struct soc_enum sec_voice_isolation_enum[] = {
|
|
SOC_ENUM_SINGLE_EXT(3, voice_isolate),
|
|
};
|
|
|
|
static int sec_voice_isolation_get(struct snd_kcontrol *kcontrol,
|
|
struct snd_ctl_elem_value *ucontrol)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static int sec_voice_isolation_put(struct snd_kcontrol *kcontrol,
|
|
struct snd_ctl_elem_value *ucontrol)
|
|
{
|
|
int mode = ucontrol->value.integer.value[0];
|
|
|
|
pr_debug("%s: mode = %d\n", __func__, mode);
|
|
|
|
return sec_voice_isolation_mode(mode);
|
|
}
|
|
|
|
/*******************************************************/
|
|
/*/////////////////////// COMMON //////////////////////*/
|
|
/*******************************************************/
|
|
static const struct snd_kcontrol_new samsung_solution_mixer_controls[] = {
|
|
SOC_SINGLE_MULTI_EXT("SA data", SND_SOC_NOPM, 0, 65535, 0, 27,
|
|
sec_audio_sound_alive_get,
|
|
sec_audio_sound_alive_put),
|
|
SOC_SINGLE_EXT("SA LISTENBACK RX volume", SND_SOC_NOPM, 0, 65535, 0,
|
|
sec_audio_sa_listenback_rx_vol_get,
|
|
sec_audio_sa_listenback_rx_vol_put),
|
|
SOC_SINGLE_MULTI_EXT("SA LISTENBACK RX data", SND_SOC_NOPM, 0, 65535, 0, 27,
|
|
sec_audio_sa_listenback_rx_data_get,
|
|
sec_audio_sa_listenback_rx_data_put),
|
|
SOC_SINGLE_MULTI_EXT("VSP data", SND_SOC_NOPM, 0, 65535, 0, 1,
|
|
sec_audio_play_speed_get,
|
|
sec_audio_play_speed_put),
|
|
SOC_SINGLE_MULTI_EXT("Audio DHA data", SND_SOC_NOPM, 0, 65535, 0, 14,
|
|
sec_audio_adaptation_sound_get,
|
|
sec_audio_adaptation_sound_put),
|
|
SOC_SINGLE_MULTI_EXT("LRSM data", SND_SOC_NOPM, 0, 65535, 0, 2,
|
|
sec_audio_sound_balance_get,
|
|
sec_audio_sound_balance_put),
|
|
SOC_SINGLE_EXT("VoiceTrackInfo", SND_SOC_NOPM, 0, 2147483647, 0,
|
|
sec_audio_voice_tracking_info_get,
|
|
sec_audio_voice_tracking_info_put),
|
|
SOC_SINGLE_MULTI_EXT("MSP data", SND_SOC_NOPM, 0, 65535, 0, 1,
|
|
sec_audio_myspace_get, sec_audio_myspace_put),
|
|
SOC_SINGLE_MULTI_EXT("SB enable", SND_SOC_NOPM, 0, 65535, 0, 1,
|
|
sec_audio_sound_boost_get,
|
|
sec_audio_sound_boost_put),
|
|
SOC_SINGLE_MULTI_EXT("UPSCALER", SND_SOC_NOPM, 0, 65535, 0, 1,
|
|
sec_audio_upscaler_get, sec_audio_upscaler_put),
|
|
SOC_SINGLE_MULTI_EXT("SB rotation", SND_SOC_NOPM, 0, 65535, 0, 2,
|
|
sec_audio_sb_rotation_get, sec_audio_sb_rotation_put),
|
|
SOC_SINGLE_MULTI_EXT("SB flatmotion", SND_SOC_NOPM, 0, 65535, 0, 1,
|
|
sec_audio_sb_flatmotion_get, sec_audio_sb_flatmotion_put),
|
|
SOC_SINGLE_MULTI_EXT("DA data", SND_SOC_NOPM, 0, 65535, 0, 3,
|
|
sec_audio_dolby_atmos_get, sec_audio_dolby_atmos_put),
|
|
SOC_SINGLE_MULTI_EXT("Sec Set DHA data", SND_SOC_NOPM, 0, 65535, 0, 14,
|
|
sec_voice_adaptation_sound_get,
|
|
sec_voice_adaptation_sound_put),
|
|
SOC_SINGLE_EXT("NB Mode", SND_SOC_NOPM, 0, 1, 0,
|
|
sec_voice_nb_mode_get, sec_voice_nb_mode_put),
|
|
SOC_SINGLE_EXT("Receiver Sensor Mode", SND_SOC_NOPM, 0, 1, 0,
|
|
sec_voice_rcv_mode_get, sec_voice_rcv_mode_put),
|
|
SOC_SINGLE_EXT("Speaker Sensor Mode", SND_SOC_NOPM, 0, 1, 0,
|
|
sec_voice_spk_mode_get, sec_voice_spk_mode_put),
|
|
SOC_SINGLE_EXT("Loopback Enable", SND_SOC_NOPM, 0, LOOPBACK_MAX, 0,
|
|
sec_voice_loopback_get, sec_voice_loopback_put),
|
|
SOC_SINGLE_EXT("Echo Ref Mute", SND_SOC_NOPM, 0, 2, 0,
|
|
sec_voice_echo_ref_mute_get, sec_voice_echo_ref_mute_put),
|
|
SOC_ENUM_EXT("Voice Device Info", sec_voice_device_enum[0],
|
|
sec_voice_dev_info_get, sec_voice_dev_info_put),
|
|
SOC_SINGLE_EXT("REF LCH MUTE", SND_SOC_NOPM, 0, 1, 0,
|
|
sec_voice_ref_lch_mute_get, sec_voice_ref_lch_mute_put),
|
|
SOC_SINGLE_EXT("SB RX Volume", SND_SOC_NOPM, 0, 65535, 0,
|
|
sec_audio_sb_rx_vol_get,
|
|
sec_audio_sb_rx_vol_put),
|
|
SOC_SINGLE_EXT("SB FM RX Volume", SND_SOC_NOPM, 0, 65535, 0,
|
|
sec_audio_sb_fm_rx_vol_get,
|
|
sec_audio_sb_fm_rx_vol_put),
|
|
SOC_ENUM_EXT("DSP AEC Effect", sec_aec_effect_enum[0],
|
|
sec_voice_aec_effect_get, sec_voice_aec_effect_put),
|
|
SOC_SINGLE_EXT("Remote Mic Vol Index", SND_SOC_NOPM, 0, 65535, 0,
|
|
sec_remote_mic_vol_get,
|
|
sec_remote_mic_vol_put),
|
|
SOC_SINGLE_MULTI_EXT("VM Energy", SND_SOC_NOPM, 0, 65535, 0, 61,
|
|
sec_audio_volume_monitor_get, sec_audio_volume_monitor_put),
|
|
SOC_SINGLE_MULTI_EXT("VM data", SND_SOC_NOPM, 0, 65535, 0, 4,
|
|
sec_audio_volume_monitor_data_get, sec_audio_volume_monitor_data_put),
|
|
SOC_SINGLE_EXT("Listenback Enable", SND_SOC_NOPM, 0, 65535, 0,
|
|
sec_audio_sa_listenback_enable_get,
|
|
sec_audio_sa_listenback_enable_put),
|
|
SOC_ENUM_EXT("Voice Isolation Mode", sec_voice_isolation_enum[0],
|
|
sec_voice_isolation_get,
|
|
sec_voice_isolation_put),
|
|
};
|
|
|
|
static int q6audio_adaptation_platform_probe(struct snd_soc_platform *platform)
|
|
{
|
|
pr_info("%s: platform\n", __func__);
|
|
|
|
common = voice_get_common_data();
|
|
session = q6asm_get_audio_session();
|
|
|
|
snd_soc_add_platform_controls(platform,
|
|
samsung_solution_mixer_controls,
|
|
ARRAY_SIZE(samsung_solution_mixer_controls));
|
|
|
|
return 0;
|
|
}
|
|
|
|
static struct snd_soc_platform_driver q6audio_adaptation = {
|
|
.probe = q6audio_adaptation_platform_probe,
|
|
};
|
|
|
|
static int samsung_q6audio_adaptation_probe(struct platform_device *pdev)
|
|
{
|
|
int ret;
|
|
|
|
pr_info("%s: dev name %s\n", __func__, dev_name(&pdev->dev));
|
|
|
|
atomic_set(&this_afe.state, 0);
|
|
atomic_set(&this_afe.status, 0);
|
|
atomic_set(&this_cvs.state, 0);
|
|
atomic_set(&this_cvp.state, 0);
|
|
this_afe.apr = NULL;
|
|
this_cvs.apr = NULL;
|
|
this_cvp.apr = NULL;
|
|
init_waitqueue_head(&this_afe.wait);
|
|
init_waitqueue_head(&this_cvs.wait);
|
|
init_waitqueue_head(&this_cvp.wait);
|
|
mutex_init(&asm_lock);
|
|
|
|
ret = of_property_read_u32(pdev->dev.of_node,
|
|
"adaptation,device-tx-port-id",
|
|
&afe_port.device_tx_port);
|
|
if (ret)
|
|
pr_err("%s : Unable to read Tx BE\n", __func__);
|
|
|
|
ret = of_property_read_u32(pdev->dev.of_node,
|
|
"adaptation,spk-rx-port-id",
|
|
&afe_port.spk_rx_port);
|
|
if (ret)
|
|
pr_debug("%s : Unable to find amp-rx-port\n", __func__);
|
|
|
|
ret = of_property_read_u32(pdev->dev.of_node,
|
|
"adaptation,usb-rx-port-id",
|
|
&afe_port.usb_rx_port);
|
|
if (ret)
|
|
pr_debug("%s : Unable to find usb-rx-port\n", __func__);
|
|
|
|
ret = of_property_read_u32(pdev->dev.of_node,
|
|
"adaptation,bt-rx-port-id",
|
|
&afe_port.bt_rx_port);
|
|
if (ret)
|
|
pr_debug("%s : Unable to find bt-rx-port\n", __func__);
|
|
|
|
ret = of_property_read_u32(pdev->dev.of_node,
|
|
"adaptation,headset-rx-port-id",
|
|
&afe_port.headset_rx_port);
|
|
if (ret)
|
|
pr_debug("%s : Unable to find headset-rx-port\n", __func__);
|
|
|
|
return snd_soc_register_platform(&pdev->dev, &q6audio_adaptation);
|
|
}
|
|
|
|
static int samsung_q6audio_adaptation_remove(struct platform_device *pdev)
|
|
{
|
|
pr_debug("%s\n", __func__);
|
|
snd_soc_unregister_platform(&pdev->dev);
|
|
return 0;
|
|
}
|
|
|
|
static const struct of_device_id samsung_q6audio_adaptation_dt_match[] = {
|
|
{.compatible = "samsung,q6audio-adaptation"},
|
|
{}
|
|
};
|
|
MODULE_DEVICE_TABLE(of, samsung_q6audio_adaptation_dt_match);
|
|
|
|
static struct platform_driver samsung_q6audio_adaptation_driver = {
|
|
.driver = {
|
|
.name = "samsung-q6audio-adaptation",
|
|
.owner = THIS_MODULE,
|
|
.of_match_table = samsung_q6audio_adaptation_dt_match,
|
|
},
|
|
.probe = samsung_q6audio_adaptation_probe,
|
|
.remove = samsung_q6audio_adaptation_remove,
|
|
};
|
|
|
|
int __init sec_soc_platform_init(void)
|
|
{
|
|
pr_debug("%s\n", __func__);
|
|
return platform_driver_register(&samsung_q6audio_adaptation_driver);
|
|
}
|
|
|
|
void __exit sec_soc_platform_exit(void)
|
|
{
|
|
pr_debug("%s\n", __func__);
|
|
platform_driver_unregister(&samsung_q6audio_adaptation_driver);
|
|
}
|
|
|
|
MODULE_AUTHOR("SeokYoung Jang, <quartz.jang@samsung.com>");
|
|
MODULE_DESCRIPTION("Samsung ASoC ADSP Adaptation driver");
|
|
MODULE_LICENSE("GPL v2");
|
|
|