From aedadd21e6866b190ef2e71b47954f9459a2cdb5 Mon Sep 17 00:00:00 2001 From: guoyf2 Date: Tue, 10 May 2022 13:41:58 +0800 Subject: [PATCH] asoc: audio:update aw882xx driver to v1.9.0.7 update aw882xx driver to v1.9.0.7 support get algo params from ram. skt-prof-mode = 1 to support by product. Change-Id: Id3d8ebc09cd616ad159486405ec95d67419eaf21 Signed-off-by: guoyf2 Reviewed-on: https://gerrit.mot.com/2264458 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Yunfei Guo Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key --- asoc/codecs/aw88261/aw882xx.c | 160 +++++++++----- asoc/codecs/aw88261/aw882xx.h | 11 +- asoc/codecs/aw88261/aw_data_type.h | 26 +++ asoc/codecs/aw88261/aw_device.c | 331 +++++++++++++++++++++++++++++ asoc/codecs/aw88261/aw_device.h | 13 +- asoc/codecs/aw88261/aw_dsp.c | 28 +++ asoc/codecs/aw88261/aw_dsp.h | 1 + 7 files changed, 519 insertions(+), 51 deletions(-) diff --git a/asoc/codecs/aw88261/aw882xx.c b/asoc/codecs/aw88261/aw882xx.c index 03ba625c9699..657051144303 100644 --- a/asoc/codecs/aw88261/aw882xx.c +++ b/asoc/codecs/aw88261/aw882xx.c @@ -35,7 +35,7 @@ #include "aw_log.h" #include "aw_dsp.h" -#define AW882XX_DRIVER_VERSION "v1.9.0.6" +#define AW882XX_DRIVER_VERSION "v1.9.0.7" #define AW882XX_I2C_NAME "aw882xxacf_smartpa" #define AW_READ_CHIPID_RETRIES 5 /* 5 times */ @@ -54,12 +54,9 @@ static uint32_t g_spin_en = 0; static unsigned int g_runin_test; #endif -#ifdef AW882XX_SPIN_FOR_LOW_LATENCY_ONLY -static unsigned int g_skt_prof_id = 0; -#endif - static DEFINE_MUTEX(g_aw882xx_lock); struct aw_container *g_awinic_cfg = NULL; +struct aw_container *g_awinic_skt_cfg = NULL; #define AW882XX_MOTO_MAX_GAIN (127) @@ -493,6 +490,7 @@ static int aw882xx_mute(struct snd_soc_dai *dai, int mute, int stream) if (mute) { aw882xx->pstream = false; + aw882xx->aw_pa->pre_prof_id = AW_DEFAULT_PRO_ID; cancel_delayed_work_sync(&aw882xx->dc_work); cancel_delayed_work_sync(&aw882xx->start_work); mutex_lock(&aw882xx->lock); @@ -900,6 +898,8 @@ static void aw882xx_request_firmware(struct work_struct *work) container_of(work, struct aw882xx, fw_work.work); const struct firmware *cont = NULL; struct aw_container *aw_cfg = NULL; + const struct firmware *skt_cont = NULL; + struct aw_container *aw_skt_cfg = NULL; int ret = -1; aw882xx->fw_status = AW_DEV_FW_FAILED; @@ -950,6 +950,56 @@ static void aw882xx_request_firmware(struct work_struct *work) } mutex_unlock(&g_aw882xx_lock); + + /*load skt bin*/ + if (aw882xx->skt_prof_mode == AW_PARAMS_DATA_MODE) { + ret = request_firmware(&skt_cont, AW_ALGO_SKT_BIN, aw882xx->dev); + if ((ret) || (!skt_cont)) { + aw_dev_info(aw882xx->dev, "load [%s] failed!", AW_ALGO_SKT_BIN); + return; + } + + aw_dev_info(aw882xx->dev, "load [%s] , file size: [%zu]", + AW_ALGO_SKT_BIN, skt_cont ? skt_cont->size : 0); + + if (g_awinic_skt_cfg == NULL) { + aw_skt_cfg = vzalloc(skt_cont->size + sizeof(int)); + if (aw_skt_cfg == NULL) { + release_firmware(skt_cont); + aw_dev_err(aw882xx->dev, "malloc failed"); + return; + } + aw_skt_cfg->len = skt_cont->size; + memcpy(aw_skt_cfg->data, skt_cont->data, skt_cont->size); + release_firmware(skt_cont); + + ret = aw_dev_load_acf_check(aw_skt_cfg); + if (ret) { + aw_dev_err(aw882xx->dev, "Load [%s] failed ....!", AW_ALGO_SKT_BIN); + vfree(aw_skt_cfg); + aw_skt_cfg = NULL; + return; + } + g_awinic_skt_cfg = aw_skt_cfg; + /*set init algo prof*/ + aw882xx->aw_pa->pre_prof_id = AW_DEFAULT_PRO_ID; + + } else { + aw_skt_cfg = g_awinic_skt_cfg; + release_firmware(skt_cont); + aw_dev_info(aw882xx->dev, "[%s] already loaded...", AW_ALGO_SKT_BIN); + } + + /*parse skt bin*/ + if ((aw882xx->aw_pa->channel == AW_DEV_CH_PRI_L) || (aw882xx->aw_pa->channel == AW_DEV_CH_SEC_L)) { + ret = aw_dev_parse_skt_bin(aw882xx->aw_pa, aw_skt_cfg); + if (ret < 0) { + aw_dev_info(aw882xx->dev, "parse skt bin failed"); + return; + } + } + } + mutex_lock(&aw882xx->lock); /*aw device init*/ ret = aw_device_init(aw882xx->aw_pa, aw_cfg); @@ -1095,10 +1145,22 @@ static int aw882xx_set_rx_en(struct snd_kcontrol *kcontrol, g_algo_rx_en = ctrl_value; aw_dev_info(aw882xx->dev, "set value %d", ctrl_value); - if (ctrl_value) { - ret = aw_dev_set_algo_params_path(aw_dev); - if (ret < 0) - aw_dev_err(aw882xx->dev, "set algo params path failed, ret=%d", ret); + if (aw882xx->skt_prof_mode == AW_PARAMS_PATH_MODE) { + if (ctrl_value) { + ret = aw_dev_set_algo_params_path(aw_dev); + if (ret < 0) + aw_dev_err(aw882xx->dev, "set algo params path failed, ret=%d", ret); + } + } else { + if (aw882xx->aw_pa->pre_prof_id != AW_DEFAULT_PRO_ID) { + aw882xx->cur_algo_prof_id = aw882xx->aw_pa->pre_prof_id; + aw882xx->aw_pa->pre_prof_id = AW_DEFAULT_PRO_ID; + ret = aw_dev_skt_prof_mode(aw_dev, aw882xx->cur_algo_prof_id); + if (ret < 0) { + aw_dev_err(aw882xx->dev, "set algo prof failed"); + return -EINVAL; + } + } } return 0; } @@ -1264,21 +1326,12 @@ static int aw882xx_set_spin(struct snd_kcontrol *kcontrol, aw_dev = aw882xx->aw_pa; ctrl_value = ucontrol->value.integer.value[0]; - -#ifdef AW882XX_SPIN_FOR_LOW_LATENCY_ONLY - if (g_skt_prof_id == (AW882XX_SCENE_FASTTRACK_ID+1)) { -#else if (aw882xx->pstream) { -#endif ret = aw_dev_set_spin(ctrl_value); if (ret) aw_dev_err(aw882xx->dev, "set spin error, ret=%d", ret); } else { -#ifdef AW882XX_SPIN_FOR_LOW_LATENCY_ONLY - aw_dev_info(aw882xx->dev, "fasttrack stream no start"); -#else aw_dev_info(aw882xx->dev, "stream no start only record"); -#endif } g_spin_value = ctrl_value; @@ -1602,6 +1655,7 @@ static int aw882xx_set_prof_id(struct snd_kcontrol *kcontrol, struct aw882xx *aw882xx = aw_componet_codec_ops.codec_get_drvdata(codec); int ctrl_value; + int ret = -1; aw_dev_dbg(aw882xx->dev, "ucontrol->value.integer.value[0]=%ld", ucontrol->value.integer.value[0]); @@ -1610,7 +1664,15 @@ static int aw882xx_set_prof_id(struct snd_kcontrol *kcontrol, ctrl_value = ucontrol->value.integer.value[0]; - aw_dev_set_algo_prof(aw_dev, ctrl_value); + if (aw882xx->skt_prof_mode == AW_PARAMS_PATH_MODE) { + aw_dev_set_algo_prof(aw_dev, ctrl_value); + } else { + ret = aw_dev_skt_prof_mode(aw_dev, ctrl_value); + if (ret < 0) { + aw_dev_err(aw882xx->dev, "set_prof failed!, ret = %d", ret); + } + aw882xx->cur_algo_prof_id = ctrl_value; + } return 0; } @@ -1628,10 +1690,14 @@ static int aw882xx_get_prof_id(struct snd_kcontrol *kcontrol, aw_dev = aw882xx->aw_pa; if (aw882xx->pstream) { - ret = aw_dev_get_algo_prof(aw_dev, &ctrl_value); - if (ret) { - aw_dev_err(aw882xx->dev, "get algo prof id failed!, ret = %d", ret); - ctrl_value = 0; + if (aw882xx->skt_prof_mode == AW_PARAMS_PATH_MODE) { + ret = aw_dev_get_algo_prof(aw_dev, &ctrl_value); + if (ret) { + aw_dev_err(aw882xx->dev, "get algo prof id failed!, ret = %d", ret); + ctrl_value = 0; + } + } else { + ctrl_value = aw882xx->cur_algo_prof_id; } ucontrol->value.integer.value[0] = ctrl_value; } else { @@ -1692,7 +1758,7 @@ static void aw882xx_update_algo_scene_st(struct aw882xx *aw882xx, static int aw882xx_update_algo_profile(struct aw882xx *aw882xx) { - int ret = 0; + int ret = -1; int new_skt_prof_id = 0; int cur_skt_prof_id = aw882xx->cur_algo_prof_id; struct aw_device *aw_dev = NULL; @@ -1712,32 +1778,15 @@ static int aw882xx_update_algo_profile(struct aw882xx *aw882xx) aw_dev = aw882xx->aw_pa; /* set new scene pramas to skt */ - ret = aw_dev_set_algo_prof(aw_dev, aw882xx->cur_algo_prof_id); - if (ret < 0) { - aw_dev_err(aw882xx->dev, "set algo prof failed"); - return -1; + if (aw882xx->skt_prof_mode == AW_PARAMS_PATH_MODE) { + ret = aw_dev_set_algo_prof(aw_dev, aw882xx->cur_algo_prof_id); + } else { + ret = aw_dev_skt_prof_mode(aw_dev, aw882xx->cur_algo_prof_id); + if (ret < 0) { + aw_dev_err(aw882xx->dev, "set algo prof failed"); + return -1; + } } - - aw_dev_info(aw882xx->dev, "algo scene hold, cur scene %d", - new_skt_prof_id); - -#ifdef AW882XX_SPIN_FOR_LOW_LATENCY_ONLY - aw_dev_info(aw882xx->dev, "g_skt_prof_id=%d\n",g_skt_prof_id); - - if (new_skt_prof_id == (AW882XX_SCENE_FASTTRACK_ID+1)){ - ret = aw_dev_set_spin(g_spin_value); - if (ret) - aw_dev_err(aw882xx->dev, "set spin error when switch prof id to %d, ret=%d", ret, new_skt_prof_id); - } else if ((g_skt_prof_id == (AW882XX_SCENE_FASTTRACK_ID+1)) - && (new_skt_prof_id != (AW882XX_SCENE_FASTTRACK_ID+1))){ - ret = aw_dev_set_spin(1); - if (ret) - aw_dev_err(aw882xx->dev, "set spin error when switch prof id to %d, ret=%d", ret, new_skt_prof_id); - } - - g_skt_prof_id = new_skt_prof_id; -#endif - return 0; } @@ -2490,6 +2539,15 @@ static int aw882xx_parse_dt(struct device *dev, struct aw882xx *aw882xx, __func__, aw882xx->fade_flag); } + ret = of_property_read_u32(np, "skt-prof-mode", &aw882xx->skt_prof_mode); + if (ret) { + aw882xx->skt_prof_mode = AW_PARAMS_PATH_MODE; + dev_err(dev, "%s: skt-prof-mode get failed,use default value!\n", __func__); + } else { + dev_info(dev, "%s: skt-prof-mode = %d\n", + __func__, aw882xx->skt_prof_mode); + } + return 0; } @@ -3196,6 +3254,10 @@ static int aw882xx_i2c_remove(struct i2c_client *i2c) vfree(g_awinic_cfg); g_awinic_cfg = NULL; } + if (g_awinic_skt_cfg) { + vfree(g_awinic_skt_cfg); + g_awinic_skt_cfg = NULL; + } } mutex_unlock(&g_aw882xx_lock); diff --git a/asoc/codecs/aw88261/aw882xx.h b/asoc/codecs/aw88261/aw882xx.h index c9b41f61c91c..562033451be8 100644 --- a/asoc/codecs/aw88261/aw882xx.h +++ b/asoc/codecs/aw88261/aw882xx.h @@ -20,6 +20,8 @@ #define AW882XX_LOAD_FW_DELAY_TIME (0) #define AW_START_RETRIES (5) #define AW882XX_RUNIN_TEST +#define AW_ALGO_SKT_BIN "aw_skt.bin" +#define AW_DEFAULT_PRO_ID (0xFFFFFFFF) #define CONFIG_AW882XX_ALGO_BIN_PARAMS #define AW_I2C_RETRIES 5 /* 5 times */ @@ -75,6 +77,13 @@ struct aw882xx_scene_info { int is_active; int active_cnt; }; + +enum { + AW_PARAMS_PATH_MODE = 0, + AW_PARAMS_DATA_MODE, +}; + + #endif @@ -218,7 +227,7 @@ struct aw882xx { int aw882xx_algo_prof_id; int cur_algo_prof_id; #endif - + unsigned int skt_prof_mode; unsigned int fade_flag; unsigned char index; diff --git a/asoc/codecs/aw88261/aw_data_type.h b/asoc/codecs/aw88261/aw_data_type.h index 36aaf4f077ce..5184dfa01189 100644 --- a/asoc/codecs/aw88261/aw_data_type.h +++ b/asoc/codecs/aw88261/aw_data_type.h @@ -18,12 +18,14 @@ struct aw_msg_hdr { #define CUSTOMER_NAME_MAX (16) #define CFG_VERSION_MAX (4) #define DEV_NAME_MAX (16) +#define PROFILE_STR_MAX (32) #define ACF_FILE_ID (0xa15f908) enum aw_cfg_hdr_version { AW_CFG_HDR_VER_0_0_0_1 = 0x00000001, + AW_CFG_HDR_VER_1_0_0_0 = 0x01000000, }; enum aw_cfg_dde_type { @@ -53,6 +55,12 @@ enum profile_data_type { AW_PROFILE_DATA_TYPE_MAX, }; +enum algo_profile_data_type { + AW_PROFILE_DATA_TYPE_ALGO_DSP, + AW_PROFILE_DATA_TYPE_ALGO_MAX, +}; + + enum aw_prof_type { AW_PROFILE_MUSIC = 0, AW_PROFILE_VOICE, @@ -100,6 +108,22 @@ struct aw_cfg_dde { uint32_t reserve[5]; }; +struct aw_cfg_dde_v_1_0_0_0 { + uint32_t type; /*DDE type id*/ + char dev_name[DEV_NAME_MAX]; + uint16_t dev_index; /*dev id*/ + uint16_t dev_bus; /*dev bus id*/ + uint16_t dev_addr; /*dev addr id*/ + uint16_t dev_profile; /*dev profile id*/ + uint32_t data_type; /*data type id*/ + uint32_t data_size; + uint32_t data_offset; + uint32_t data_crc; + char dev_profile_str[PROFILE_STR_MAX]; + uint32_t chip_id; + uint32_t reserve[4]; +}; + struct aw_sec_data_desc { uint32_t len; unsigned char *data; @@ -108,6 +132,7 @@ struct aw_sec_data_desc { struct aw_prof_desc { uint32_t id; uint32_t prof_st; + char *prf_str; struct aw_sec_data_desc sec_desc[AW_PROFILE_DATA_TYPE_MAX]; }; @@ -117,6 +142,7 @@ struct aw_all_prof_info { struct aw_prof_info { int count; + char **prof_name_list; struct aw_prof_desc *prof_desc; }; diff --git a/asoc/codecs/aw88261/aw_device.c b/asoc/codecs/aw88261/aw_device.c index c2d768060f8c..193d77598b42 100644 --- a/asoc/codecs/aw88261/aw_device.c +++ b/asoc/codecs/aw88261/aw_device.c @@ -150,6 +150,102 @@ static int aw_dev_check_cfg_by_hdr(struct aw_container *aw_cfg) return 0; } +static int aw_dev_parse_check_acf_by_hdr_v_1_0_0_0(struct aw_container *aw_cfg) +{ + struct aw_cfg_hdr *cfg_hdr = NULL; + struct aw_cfg_dde_v_1_0_0_0 *cfg_dde = NULL; + unsigned int end_data_offset = 0; + unsigned int act_data = 0; + unsigned int hdr_ddt_len = 0; + uint8_t act_crc8 = 0; + int i; + + cfg_hdr = (struct aw_cfg_hdr *)aw_cfg->data; + + /*check file type id is awinic acf file*/ + if (cfg_hdr->a_id != ACF_FILE_ID) { + aw_pr_err("not acf type file"); + return -EINVAL; + } + + hdr_ddt_len = cfg_hdr->a_hdr_offset + cfg_hdr->a_ddt_size; + if (hdr_ddt_len > aw_cfg->len) { + aw_pr_err("hdrlen with ddt_len [%d] overflow file size[%d]", + cfg_hdr->a_hdr_offset, aw_cfg->len); + return -EINVAL; + } + + /*check data size*/ + cfg_dde = (struct aw_cfg_dde_v_1_0_0_0 *)((char *)aw_cfg->data + cfg_hdr->a_hdr_offset); + act_data += hdr_ddt_len; + for (i = 0; i < cfg_hdr->a_ddt_num; i++) + act_data += cfg_dde[i].data_size; + + if (act_data != aw_cfg->len) { + aw_pr_err("act_data[%d] not equal to file size[%d]!", + act_data, aw_cfg->len); + return -EINVAL; + } + + for (i = 0; i < cfg_hdr->a_ddt_num; i++) { + /* data check */ + end_data_offset = cfg_dde[i].data_offset + cfg_dde[i].data_size; + if (end_data_offset > aw_cfg->len) { + aw_pr_err("a_ddt_num[%d] end_data_offset[%d] overflow file size[%d]", + i, end_data_offset, aw_cfg->len); + return -EINVAL; + } + + /* crc check */ + act_crc8 = aw_dev_crc8_check(aw_cfg->data + cfg_dde[i].data_offset, cfg_dde[i].data_size); + if (act_crc8 != cfg_dde[i].data_crc) { + aw_pr_err("a_ddt_num[%d] crc8 check failed, act_crc8:0x%x != data_crc 0x%x", + i, (uint32_t)act_crc8, cfg_dde[i].data_crc); + return -EINVAL; + } + } + + aw_pr_info("project name [%s]", cfg_hdr->a_project); + aw_pr_info("custom name [%s]", cfg_hdr->a_custom); + aw_pr_info("version name [%d.%d.%d.%d]", cfg_hdr->a_version[3], cfg_hdr->a_version[2], + cfg_hdr->a_version[1], cfg_hdr->a_version[0]); + aw_pr_info("author id %d", cfg_hdr->a_author_id); + + return 0; +} + +static int aw_dev_parse_raw_dsp_skt(struct aw_device *aw_dev, + uint8_t *data, uint32_t data_len, struct aw_prof_desc *prof_desc) +{ + aw_dev_info(aw_dev->dev, "data_size:%d enter", data_len); + + prof_desc->sec_desc[AW_PROFILE_DATA_TYPE_ALGO_DSP].data = data; + prof_desc->sec_desc[AW_PROFILE_DATA_TYPE_ALGO_DSP].len = data_len; + + return 0; +} + +static int aw_dev_get_chan_group(struct aw_device *aw_dev, int *chan_group) +{ + switch (aw_dev->channel) { + + case AW_DEV_CH_PRI_L: + case AW_DEV_CH_PRI_R: + *chan_group = AW_DEV_CH_GROUP_PRI; + break; + case AW_DEV_CH_SEC_L: + case AW_DEV_CH_SEC_R: + *chan_group = AW_DEV_CH_GROUP_SEC; + break; + default: + aw_pr_err("can not find chan_group, channel %d ", aw_dev->channel); + return -EINVAL; + } + + aw_pr_dbg("chan_group[%d] ", *chan_group); + return 0; +} + int aw_dev_load_acf_check(struct aw_container *aw_cfg) { struct aw_cfg_hdr *cfg_hdr = NULL; @@ -169,6 +265,8 @@ int aw_dev_load_acf_check(struct aw_container *aw_cfg) switch (cfg_hdr->a_hdr_version) { case AW_CFG_HDR_VER_0_0_0_1: return aw_dev_check_cfg_by_hdr(aw_cfg); + case AW_CFG_HDR_VER_1_0_0_0: + return aw_dev_parse_check_acf_by_hdr_v_1_0_0_0(aw_cfg); default: aw_pr_err("unsupported hdr_version [0x%x]", cfg_hdr->a_hdr_version); return -EINVAL; @@ -452,6 +550,234 @@ static int aw_dev_cfg_get_vaild_prof(struct aw_device *aw_dev, return 0; } + +/******************ACF bin format V1.0.0.0************************/ +static int aw_dev_parse_get_scene_count_v1_0_0_0(struct aw_device *aw_dev, + struct aw_container *aw_cfg, int *count) +{ + struct aw_cfg_hdr *cfg_hdr = (struct aw_cfg_hdr *)aw_cfg->data; + struct aw_cfg_dde_v_1_0_0_0 *cfg_dde = + (struct aw_cfg_dde_v_1_0_0_0 *)(aw_cfg->data + cfg_hdr->a_hdr_offset); + int i = 0; + int chan_group = -1; + int ret = -1; + + ret = aw_dev_get_chan_group(aw_dev, &chan_group); + if (ret < 0) { + aw_dev_err(aw_dev->dev, "get chan_group failed "); + return ret; + } + + for (i = 0; i < cfg_hdr->a_ddt_num; ++i) { + if ((cfg_dde[i].data_type == ACF_SEC_TYPE_DSP) && + (cfg_dde[i].type == AW_SKT_TYPE_ID) && + (chan_group == cfg_dde[i].dev_index)) { + (*count)++; + } + } + + if ((*count) == 0) { + aw_dev_err(aw_dev->dev, "can't find scene"); + return -EINVAL; + } + + aw_dev_info(aw_dev->dev, "scene count is %d", (*count)); + return 0; +} + + +static int aw_dev_parse_create_prof_name_list_v_1_0_0_0(struct aw_device *aw_dev) +{ + struct aw_prof_info *prof_info = &aw_dev->skt_prof_info; + struct aw_prof_desc *prof_desc= prof_info->prof_desc; + int i; + + if (prof_desc == NULL) { + aw_dev_err(aw_dev->dev, "prof_desc is NULL"); + return -EINVAL; + } + + prof_info->prof_name_list = devm_kzalloc(aw_dev->dev, + prof_info->count * PROFILE_STR_MAX, + GFP_KERNEL); + if (prof_info->prof_name_list == NULL) { + aw_dev_err(aw_dev->dev, "prof_name_list devm_kzalloc failed"); + return -ENOMEM; + } + + for (i = 0; i < prof_info->count; i++) { + prof_info->prof_name_list[i] = prof_desc[i].prf_str; + aw_dev_info(aw_dev->dev, "prof name list[%d]:%s, id=%d", i, prof_info->prof_name_list[i], prof_desc[i].id); + } + + return 0; +} + +static int aw_dev_parse_skt_type_v_1_0_0_0(struct aw_device *aw_dev, + struct aw_cfg_hdr *prof_hdr) +{ + int i = 0; + int ret = -1; + int scene_count = 0; + struct aw_prof_info *prof_info = &aw_dev->skt_prof_info; + struct aw_cfg_dde_v_1_0_0_0 *cfg_dde = + (struct aw_cfg_dde_v_1_0_0_0 *)((char *)prof_hdr + prof_hdr->a_hdr_offset); + int chan_group = -1; + aw_dev_info(aw_dev->dev, "enter"); + + ret = aw_dev_get_chan_group(aw_dev, &chan_group); + if (ret < 0) { + aw_dev_err(aw_dev->dev, "get chan_group failed "); + return ret; + } + + for (i = 0; i < prof_hdr->a_ddt_num; i++) { + if ((cfg_dde[i].type == AW_SKT_TYPE_ID) && + (cfg_dde[i].data_type == ACF_SEC_TYPE_DSP) && + (chan_group == cfg_dde[i].dev_index)) { + + ret = aw_dev_parse_raw_dsp_skt(aw_dev, + (uint8_t *)prof_hdr + cfg_dde[i].data_offset, + cfg_dde[i].data_size, &prof_info->prof_desc[scene_count]); + if (ret < 0) { + aw_dev_err(aw_dev->dev, "parse dsp bin data failed"); + return ret; + } + + prof_info->prof_desc[scene_count].prf_str = cfg_dde[i].dev_profile_str; + prof_info->prof_desc[scene_count].id = cfg_dde[i].dev_profile; + + scene_count++; + } + } + aw_dev_dbg(aw_dev->dev, "scene_count = %d", scene_count); + return 0; +} + +static int aw_dev_parse_acf_by_hdr_v_1_0_0_0(struct aw_device *aw_dev, struct aw_container *aw_cfg) +{ + struct aw_prof_info *prof_info = &aw_dev->skt_prof_info; + struct aw_cfg_hdr *cfg_hdr = (struct aw_cfg_hdr *)aw_cfg->data; + int ret; + + ret = aw_dev_parse_get_scene_count_v1_0_0_0(aw_dev, aw_cfg, &prof_info->count); + if (ret < 0) { + aw_dev_err(aw_dev->dev, "get scene count failed"); + return ret; + } + + prof_info->prof_desc = devm_kzalloc(aw_dev->dev, + prof_info->count * sizeof(struct aw_prof_desc), + GFP_KERNEL); + if (prof_info->prof_desc == NULL) { + aw_dev_err(aw_dev->dev, "prof_desc devm_kzalloc failed"); + return -ENOMEM; + } + + ret = aw_dev_parse_skt_type_v_1_0_0_0(aw_dev, cfg_hdr); + if (ret < 0) { + aw_dev_err(aw_dev->dev, " failed"); + return ret; + } + + ret = aw_dev_parse_create_prof_name_list_v_1_0_0_0(aw_dev); + if (ret < 0) { + aw_dev_err(aw_dev->dev, "create prof name list failed"); + return ret; + } + + return 0; +} + +int aw_dev_parse_skt_bin(struct aw_device *aw_dev, struct aw_container *aw_cfg) +{ + struct aw_cfg_hdr *cfg_hdr = NULL; + int ret = -1; + + if (aw_dev == NULL || aw_cfg == NULL) { + aw_dev_err(aw_dev->dev, "pointer is NULL"); + return -ENOMEM; + } + + cfg_hdr = (struct aw_cfg_hdr *)aw_cfg->data; + + if (cfg_hdr->a_hdr_version == AW_CFG_HDR_VER_1_0_0_0) { + ret = aw_dev_parse_acf_by_hdr_v_1_0_0_0(aw_dev, aw_cfg); + if (ret < 0) { + aw_dev_err(aw_dev->dev, "hdr_cersion[0x%x] parse failed", + cfg_hdr->a_hdr_version); + return ret; + } + } else { + aw_dev_err(aw_dev->dev, "skt bin format [0x%x] unsupported", cfg_hdr->a_hdr_version); + } + + return 0; +} + +struct aw_sec_data_desc *aw_dev_get_algo_prof_data(struct aw_device *aw_dev, int prof_id) +{ + struct aw_sec_data_desc *prof_data = NULL; + + struct aw_prof_info *prof_info = &aw_dev->skt_prof_info; + int i; + + aw_dev_dbg(aw_dev->dev, "prof num = %d", prof_info->count); + for (i = 0; i < prof_info->count; i++) { + if (prof_id == prof_info->prof_desc[i].id) { + prof_data = &prof_info->prof_desc[i].sec_desc[AW_PROFILE_DATA_TYPE_ALGO_DSP]; + break; + } + } + + return prof_data; +} + +int aw_dev_skt_prof_mode(struct aw_device *aw_dev, int prof_id) +{ + struct aw_sec_data_desc *prof_data = NULL; + int ret = -1; + struct list_head *dev_list = NULL; + struct list_head *pos = NULL; + struct aw_device *local_dev = NULL; + + ret = aw_dev_get_list_head(&dev_list); + if (ret) { + aw_dev_err(aw_dev->dev, "get dev list failed "); + return ret; + } + + aw_dev_info(aw_dev->dev, "set_cur_prof=%d,pre_prof=%d", + prof_id, aw_dev->pre_prof_id); + + if (prof_id != aw_dev->pre_prof_id) { + + list_for_each (pos, dev_list) { + local_dev = container_of(pos, struct aw_device, list_node); + + if ((local_dev->channel == AW_DEV_CH_PRI_L) || (local_dev->channel == AW_DEV_CH_SEC_L)) { + prof_data = aw_dev_get_algo_prof_data(local_dev, prof_id); + if (prof_data) { + ret = aw_dev_set_algo_prof_data(local_dev, prof_data->data, prof_data->len); + if (ret < 0) { + aw_dev_err(local_dev->dev, "set algo prof [%d] failed", prof_id); + return -EINVAL; + } + } else { + aw_dev_err(local_dev->dev, "prof data is NULL"); + return -EINVAL; + } + } + } + + aw_dev->pre_prof_id = prof_id; + aw_dev_info(aw_dev->dev, "set algo prof [%d] ok", prof_id); + } + + return 0; +} + + static int aw_dev_cfg_load(struct aw_device *aw_dev, struct aw_container *aw_cfg) { struct aw_cfg_hdr *cfg_hdr = NULL; @@ -1503,6 +1829,11 @@ int aw_dev_get_spin(int *spin_mode) return aw_dsp_read_spin(spin_mode); } +int aw_dev_set_algo_prof_data(struct aw_device *aw_dev, void *prof_data, unsigned int prof_len) +{ + return aw_dsp_set_algo_prof_data(aw_dev, prof_data, prof_len); +} + int aw_dev_set_algo_prof(struct aw_device *aw_dev, int prof_id) { return aw_dsp_set_algo_prof(aw_dev, prof_id); diff --git a/asoc/codecs/aw88261/aw_device.h b/asoc/codecs/aw88261/aw_device.h index cbc3eec67c48..4c5ec7a5c961 100644 --- a/asoc/codecs/aw88261/aw_device.h +++ b/asoc/codecs/aw88261/aw_device.h @@ -58,6 +58,12 @@ enum AW_DEV_FW_STATUS { AW_DEV_FW_OK, }; +enum { + AW_DEV_CH_GROUP_PRI = 0, + AW_DEV_CH_GROUP_SEC = 1, + AW_DEV_CH_GROUP_MAX, +}; + struct aw_device_ops { int (*aw_i2c_write)(struct aw_device *aw_dev, unsigned char reg_addr, unsigned int reg_data); int (*aw_i2c_read)(struct aw_device *aw_dev, unsigned char reg_addr, unsigned int *reg_data); @@ -234,6 +240,7 @@ struct aw_device { char monitor_name[AW_NAME_MAX]; void *private_data; char algo_path[AW_ALGO_PATH_MAX]; + int pre_prof_id; struct aw_int_desc int_desc; struct aw_pwd_desc pwd_desc; @@ -249,6 +256,7 @@ struct aw_device { struct aw_ipeak_desc ipeak_desc; struct aw_volume_desc volume_desc; struct aw_prof_info prof_info; + struct aw_prof_info skt_prof_info; struct aw_cali_desc cali_desc; struct aw_monitor_desc monitor_desc; struct aw_soft_rst soft_rst; @@ -258,10 +266,11 @@ struct aw_device { struct list_head list_node; }; - +struct aw_sec_data_desc *aw_dev_get_algo_prof_data(struct aw_device *aw_dev, int prof_id); int aw_dev_load_acf_check(struct aw_container *aw_cfg); void aw_dev_deinit(struct aw_device *aw_dev); int aw_device_init(struct aw_device *aw_dev, struct aw_container *aw_cfg); +int aw_dev_parse_skt_bin(struct aw_device *aw_dev, struct aw_container *aw_cfg); int aw_device_start(struct aw_device *aw_dev); int aw_device_stop(struct aw_device *aw_dev); int aw_dev_reg_update(struct aw_device *aw_dev, bool force); @@ -298,6 +307,8 @@ int aw_dev_get_afe_module_en(int type, int *status); int aw_dev_set_copp_module_en(bool enable); int aw_dev_set_spin(int spin_mode); int aw_dev_get_spin(int *spin_mode); +int aw_dev_skt_prof_mode(struct aw_device *aw_dev, int prof_id); +int aw_dev_set_algo_prof_data(struct aw_device *aw_dev, void *prof_data, unsigned int prof_len); int aw_dev_set_algo_prof(struct aw_device *aw_dev, int prof_id); int aw_dev_get_algo_prof(struct aw_device *aw_dev, int *prof_id); int aw_dev_set_algo_params_path(struct aw_device *aw_dev); diff --git a/asoc/codecs/aw88261/aw_dsp.c b/asoc/codecs/aw88261/aw_dsp.c index ed2425d92dc6..ba2baa236795 100644 --- a/asoc/codecs/aw88261/aw_dsp.c +++ b/asoc/codecs/aw88261/aw_dsp.c @@ -29,6 +29,8 @@ static DEFINE_MUTEX(g_aw_dsp_lock); #define AW_MSG_ID_ALGO_PARAMS_PATH (0x00000014) #define AW_MSG_ID_VERSION (0x00000008) #define AW_MSG_ID_VERSION_NEW (0x00000012) +#define AW_MSG_ID_SET_ALGO_PROF_PRI (0x10013D25) +#define AW_MSG_ID_SET_ALGO_PROF_SEC (0x10013D2C) /*dsp params id*/ @@ -389,6 +391,32 @@ static int aw_write_data_to_dsp(uint32_t param_id, void *data, int size) } /************************* dsp communication function *****************************/ +int aw_dsp_set_algo_prof_data(struct aw_device *aw_dev, void *data, unsigned int size) +{ + int ret = 0; + uint32_t params_id = 0; + + if (aw_dev->channel == AW_DEV_CH_PRI_L) { + params_id = AW_MSG_ID_SET_ALGO_PROF_PRI; + } else if (aw_dev->channel == AW_DEV_CH_SEC_L) { + params_id = AW_MSG_ID_SET_ALGO_PROF_SEC; + } else { + aw_dev_err(aw_dev->dev, "unsupport dev channel"); + return -EINVAL; + } + + aw_dev_dbg(aw_dev->dev, "params_id=%u,prof_data:%p, len=%u", params_id, data, size); + + ret = aw_qcom_write_data_to_dsp(params_id, data, size); + if (ret < 0) { + aw_pr_err("write prof_id failed "); + return ret; + } + + aw_pr_dbg("write prof_id done"); + return 0; + +} int aw_dsp_set_algo_prof(struct aw_device *aw_dev, int prof_id) { diff --git a/asoc/codecs/aw88261/aw_dsp.h b/asoc/codecs/aw88261/aw_dsp.h index 703c8a8cdf46..25c25310c93c 100644 --- a/asoc/codecs/aw88261/aw_dsp.h +++ b/asoc/codecs/aw88261/aw_dsp.h @@ -67,6 +67,7 @@ int aw_dsp_set_copp_module_en(bool enable); int aw_dsp_write_spin(int spin_mode); int aw_dsp_read_spin(int *spin_mode); int aw_get_algo_version(struct aw_device *aw_dev, char *algo_ver_buf); +int aw_dsp_set_algo_prof_data(struct aw_device *aw_dev, void *data, unsigned int size); int aw_dsp_set_algo_prof(struct aw_device *aw_dev, int prof_id); int aw_dsp_get_algo_prof(struct aw_device *aw_dev, int *prof_id); int aw_dsp_set_algo_params_path(struct aw_device *aw_dev);