162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci// 362306a36Sopenharmony_ci// aw88395_lib.c -- ACF bin parsing and check library file for aw88395 462306a36Sopenharmony_ci// 562306a36Sopenharmony_ci// Copyright (c) 2022-2023 AWINIC Technology CO., LTD 662306a36Sopenharmony_ci// 762306a36Sopenharmony_ci// Author: Bruce zhao <zhaolei@awinic.com> 862306a36Sopenharmony_ci// 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci#include <linux/crc8.h> 1162306a36Sopenharmony_ci#include <linux/i2c.h> 1262306a36Sopenharmony_ci#include "aw88395_lib.h" 1362306a36Sopenharmony_ci#include "aw88395_device.h" 1462306a36Sopenharmony_ci#include "aw88395_reg.h" 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_ci#define AW88395_CRC8_POLYNOMIAL 0x8C 1762306a36Sopenharmony_ciDECLARE_CRC8_TABLE(aw_crc8_table); 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_cistatic char *profile_name[AW88395_PROFILE_MAX] = { 2062306a36Sopenharmony_ci "Music", "Voice", "Voip", "Ringtone", 2162306a36Sopenharmony_ci "Ringtone_hs", "Lowpower", "Bypass", 2262306a36Sopenharmony_ci "Mmi", "Fm", "Notification", "Receiver" 2362306a36Sopenharmony_ci}; 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_cistatic int aw_parse_bin_header(struct aw_device *aw_dev, struct aw_bin *bin); 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_cistatic int aw_check_sum(struct aw_device *aw_dev, struct aw_bin *bin, int bin_num) 2862306a36Sopenharmony_ci{ 2962306a36Sopenharmony_ci unsigned char *p_check_sum; 3062306a36Sopenharmony_ci unsigned int sum_data = 0; 3162306a36Sopenharmony_ci unsigned int check_sum; 3262306a36Sopenharmony_ci unsigned int i, len; 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_ci p_check_sum = &(bin->info.data[(bin->header_info[bin_num].valid_data_addr - 3562306a36Sopenharmony_ci bin->header_info[bin_num].header_len)]); 3662306a36Sopenharmony_ci len = bin->header_info[bin_num].bin_data_len + bin->header_info[bin_num].header_len; 3762306a36Sopenharmony_ci check_sum = le32_to_cpup((void *)p_check_sum); 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_ci for (i = 4; i < len; i++) 4062306a36Sopenharmony_ci sum_data += *(p_check_sum + i); 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_ci dev_dbg(aw_dev->dev, "%s -- check_sum = %p, check_sum = 0x%x, sum_data = 0x%x", 4362306a36Sopenharmony_ci __func__, p_check_sum, check_sum, sum_data); 4462306a36Sopenharmony_ci if (sum_data != check_sum) { 4562306a36Sopenharmony_ci dev_err(aw_dev->dev, "%s. CheckSum Fail.bin_num=%d, CheckSum:0x%x, SumData:0x%x", 4662306a36Sopenharmony_ci __func__, bin_num, check_sum, sum_data); 4762306a36Sopenharmony_ci return -EINVAL; 4862306a36Sopenharmony_ci } 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_ci return 0; 5162306a36Sopenharmony_ci} 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_cistatic int aw_check_data_version(struct aw_device *aw_dev, struct aw_bin *bin, int bin_num) 5462306a36Sopenharmony_ci{ 5562306a36Sopenharmony_ci if (bin->header_info[bin_num].bin_data_ver < DATA_VERSION_V1 || 5662306a36Sopenharmony_ci bin->header_info[bin_num].bin_data_ver > DATA_VERSION_MAX) { 5762306a36Sopenharmony_ci dev_err(aw_dev->dev, "aw_bin_parse Unrecognized this bin data version\n"); 5862306a36Sopenharmony_ci return -EINVAL; 5962306a36Sopenharmony_ci } 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_ci return 0; 6262306a36Sopenharmony_ci} 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_cistatic int aw_check_register_num(struct aw_device *aw_dev, struct aw_bin *bin, int bin_num) 6562306a36Sopenharmony_ci{ 6662306a36Sopenharmony_ci struct bin_header_info temp_info = bin->header_info[bin_num]; 6762306a36Sopenharmony_ci unsigned int check_register_num, parse_register_num; 6862306a36Sopenharmony_ci unsigned char *p_check_sum; 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_ci p_check_sum = &(bin->info.data[(temp_info.valid_data_addr)]); 7162306a36Sopenharmony_ci 7262306a36Sopenharmony_ci parse_register_num = le32_to_cpup((void *)p_check_sum); 7362306a36Sopenharmony_ci check_register_num = (bin->header_info[bin_num].bin_data_len - CHECK_REGISTER_NUM_OFFSET) / 7462306a36Sopenharmony_ci (bin->header_info[bin_num].reg_byte_len + 7562306a36Sopenharmony_ci bin->header_info[bin_num].data_byte_len); 7662306a36Sopenharmony_ci dev_dbg(aw_dev->dev, "%s,parse_register_num = 0x%x,check_register_num = 0x%x\n", 7762306a36Sopenharmony_ci __func__, parse_register_num, check_register_num); 7862306a36Sopenharmony_ci if (parse_register_num != check_register_num) { 7962306a36Sopenharmony_ci dev_err(aw_dev->dev, "%s parse_register_num = 0x%x,check_register_num = 0x%x\n", 8062306a36Sopenharmony_ci __func__, parse_register_num, check_register_num); 8162306a36Sopenharmony_ci return -EINVAL; 8262306a36Sopenharmony_ci } 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_ci bin->header_info[bin_num].reg_num = parse_register_num; 8562306a36Sopenharmony_ci bin->header_info[bin_num].valid_data_len = temp_info.bin_data_len - VALID_DATA_LEN; 8662306a36Sopenharmony_ci bin->header_info[bin_num].valid_data_addr = temp_info.valid_data_addr + VALID_DATA_ADDR; 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_ci return 0; 8962306a36Sopenharmony_ci} 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_cistatic int aw_check_dsp_reg_num(struct aw_device *aw_dev, struct aw_bin *bin, int bin_num) 9262306a36Sopenharmony_ci{ 9362306a36Sopenharmony_ci struct bin_header_info temp_info = bin->header_info[bin_num]; 9462306a36Sopenharmony_ci unsigned int check_dsp_reg_num, parse_dsp_reg_num; 9562306a36Sopenharmony_ci unsigned char *p_check_sum; 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_ci p_check_sum = &(bin->info.data[(temp_info.valid_data_addr)]); 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_ci parse_dsp_reg_num = le32_to_cpup((void *)(p_check_sum + PARSE_DSP_REG_NUM)); 10062306a36Sopenharmony_ci bin->header_info[bin_num].reg_data_byte_len = 10162306a36Sopenharmony_ci le32_to_cpup((void *)(p_check_sum + REG_DATA_BYTP_LEN)); 10262306a36Sopenharmony_ci check_dsp_reg_num = (bin->header_info[bin_num].bin_data_len - CHECK_DSP_REG_NUM) / 10362306a36Sopenharmony_ci bin->header_info[bin_num].reg_data_byte_len; 10462306a36Sopenharmony_ci dev_dbg(aw_dev->dev, "%s bin_num = %d, parse_dsp_reg_num = 0x%x, check_dsp_reg_num = 0x%x", 10562306a36Sopenharmony_ci __func__, bin_num, check_dsp_reg_num, check_dsp_reg_num); 10662306a36Sopenharmony_ci if (parse_dsp_reg_num != check_dsp_reg_num) { 10762306a36Sopenharmony_ci dev_err(aw_dev->dev, "aw_bin_parse check dsp reg num error\n"); 10862306a36Sopenharmony_ci dev_err(aw_dev->dev, "%s parse_dsp_reg_num = 0x%x, check_dsp_reg_num = 0x%x", 10962306a36Sopenharmony_ci __func__, check_dsp_reg_num, check_dsp_reg_num); 11062306a36Sopenharmony_ci return -EINVAL; 11162306a36Sopenharmony_ci } 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_ci bin->header_info[bin_num].download_addr = le32_to_cpup((void *)p_check_sum); 11462306a36Sopenharmony_ci bin->header_info[bin_num].reg_num = parse_dsp_reg_num; 11562306a36Sopenharmony_ci bin->header_info[bin_num].valid_data_len = temp_info.bin_data_len - DSP_VALID_DATA_LEN; 11662306a36Sopenharmony_ci bin->header_info[bin_num].valid_data_addr = temp_info.valid_data_addr + 11762306a36Sopenharmony_ci DSP_VALID_DATA_ADDR; 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_ci return 0; 12062306a36Sopenharmony_ci} 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_cistatic int aw_check_soc_app_num(struct aw_device *aw_dev, struct aw_bin *bin, int bin_num) 12362306a36Sopenharmony_ci{ 12462306a36Sopenharmony_ci struct bin_header_info temp_info = bin->header_info[bin_num]; 12562306a36Sopenharmony_ci unsigned int check_soc_app_num, parse_soc_app_num; 12662306a36Sopenharmony_ci unsigned char *p_check_sum; 12762306a36Sopenharmony_ci 12862306a36Sopenharmony_ci p_check_sum = &(bin->info.data[(temp_info.valid_data_addr)]); 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_ci bin->header_info[bin_num].app_version = le32_to_cpup((void *)p_check_sum); 13162306a36Sopenharmony_ci parse_soc_app_num = le32_to_cpup((void *)(p_check_sum + PARSE_SOC_APP_NUM)); 13262306a36Sopenharmony_ci check_soc_app_num = bin->header_info[bin_num].bin_data_len - CHECK_SOC_APP_NUM; 13362306a36Sopenharmony_ci dev_dbg(aw_dev->dev, "%s bin_num = %d, parse_soc_app_num=0x%x, check_soc_app_num = 0x%x\n", 13462306a36Sopenharmony_ci __func__, bin_num, parse_soc_app_num, check_soc_app_num); 13562306a36Sopenharmony_ci if (parse_soc_app_num != check_soc_app_num) { 13662306a36Sopenharmony_ci dev_err(aw_dev->dev, "%s parse_soc_app_num=0x%x, check_soc_app_num = 0x%x\n", 13762306a36Sopenharmony_ci __func__, parse_soc_app_num, check_soc_app_num); 13862306a36Sopenharmony_ci return -EINVAL; 13962306a36Sopenharmony_ci } 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_ci bin->header_info[bin_num].reg_num = parse_soc_app_num; 14262306a36Sopenharmony_ci bin->header_info[bin_num].download_addr = le32_to_cpup((void *)(p_check_sum + 14362306a36Sopenharmony_ci APP_DOWNLOAD_ADDR)); 14462306a36Sopenharmony_ci bin->header_info[bin_num].valid_data_len = temp_info.bin_data_len - APP_VALID_DATA_LEN; 14562306a36Sopenharmony_ci bin->header_info[bin_num].valid_data_addr = temp_info.valid_data_addr + 14662306a36Sopenharmony_ci APP_VALID_DATA_ADDR; 14762306a36Sopenharmony_ci 14862306a36Sopenharmony_ci return 0; 14962306a36Sopenharmony_ci} 15062306a36Sopenharmony_ci 15162306a36Sopenharmony_cistatic void aw_get_single_bin_header(struct aw_bin *bin) 15262306a36Sopenharmony_ci{ 15362306a36Sopenharmony_ci memcpy((void *)&bin->header_info[bin->all_bin_parse_num], bin->p_addr, DATA_LEN); 15462306a36Sopenharmony_ci 15562306a36Sopenharmony_ci bin->header_info[bin->all_bin_parse_num].header_len = HEADER_LEN; 15662306a36Sopenharmony_ci bin->all_bin_parse_num += 1; 15762306a36Sopenharmony_ci} 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_cistatic int aw_parse_one_of_multi_bins(struct aw_device *aw_dev, unsigned int bin_num, 16062306a36Sopenharmony_ci int bin_serial_num, struct aw_bin *bin) 16162306a36Sopenharmony_ci{ 16262306a36Sopenharmony_ci struct bin_header_info aw_bin_header_info; 16362306a36Sopenharmony_ci unsigned int bin_start_addr; 16462306a36Sopenharmony_ci unsigned int valid_data_len; 16562306a36Sopenharmony_ci 16662306a36Sopenharmony_ci if (bin->info.len < sizeof(struct bin_header_info)) { 16762306a36Sopenharmony_ci dev_err(aw_dev->dev, "bin_header_info size[%d] overflow file size[%d]\n", 16862306a36Sopenharmony_ci (int)sizeof(struct bin_header_info), bin->info.len); 16962306a36Sopenharmony_ci return -EINVAL; 17062306a36Sopenharmony_ci } 17162306a36Sopenharmony_ci 17262306a36Sopenharmony_ci aw_bin_header_info = bin->header_info[bin->all_bin_parse_num - 1]; 17362306a36Sopenharmony_ci if (!bin_serial_num) { 17462306a36Sopenharmony_ci bin_start_addr = le32_to_cpup((void *)(bin->p_addr + START_ADDR_OFFSET)); 17562306a36Sopenharmony_ci bin->p_addr += (HEADER_LEN + bin_start_addr); 17662306a36Sopenharmony_ci bin->header_info[bin->all_bin_parse_num].valid_data_addr = 17762306a36Sopenharmony_ci aw_bin_header_info.valid_data_addr + VALID_DATA_ADDR + 8 * bin_num + 17862306a36Sopenharmony_ci VALID_DATA_ADDR_OFFSET; 17962306a36Sopenharmony_ci } else { 18062306a36Sopenharmony_ci valid_data_len = aw_bin_header_info.bin_data_len; 18162306a36Sopenharmony_ci bin->p_addr += (HDADER_LEN + valid_data_len); 18262306a36Sopenharmony_ci bin->header_info[bin->all_bin_parse_num].valid_data_addr = 18362306a36Sopenharmony_ci aw_bin_header_info.valid_data_addr + aw_bin_header_info.bin_data_len + 18462306a36Sopenharmony_ci VALID_DATA_ADDR_OFFSET; 18562306a36Sopenharmony_ci } 18662306a36Sopenharmony_ci 18762306a36Sopenharmony_ci return aw_parse_bin_header(aw_dev, bin); 18862306a36Sopenharmony_ci} 18962306a36Sopenharmony_ci 19062306a36Sopenharmony_cistatic int aw_get_multi_bin_header(struct aw_device *aw_dev, struct aw_bin *bin) 19162306a36Sopenharmony_ci{ 19262306a36Sopenharmony_ci unsigned int bin_num, i; 19362306a36Sopenharmony_ci int ret; 19462306a36Sopenharmony_ci 19562306a36Sopenharmony_ci bin_num = le32_to_cpup((void *)(bin->p_addr + VALID_DATA_ADDR_OFFSET)); 19662306a36Sopenharmony_ci if (bin->multi_bin_parse_num == 1) 19762306a36Sopenharmony_ci bin->header_info[bin->all_bin_parse_num].valid_data_addr = 19862306a36Sopenharmony_ci VALID_DATA_ADDR_OFFSET; 19962306a36Sopenharmony_ci 20062306a36Sopenharmony_ci aw_get_single_bin_header(bin); 20162306a36Sopenharmony_ci 20262306a36Sopenharmony_ci for (i = 0; i < bin_num; i++) { 20362306a36Sopenharmony_ci dev_dbg(aw_dev->dev, "aw_bin_parse enter multi bin for is %d\n", i); 20462306a36Sopenharmony_ci ret = aw_parse_one_of_multi_bins(aw_dev, bin_num, i, bin); 20562306a36Sopenharmony_ci if (ret < 0) 20662306a36Sopenharmony_ci return ret; 20762306a36Sopenharmony_ci } 20862306a36Sopenharmony_ci 20962306a36Sopenharmony_ci return 0; 21062306a36Sopenharmony_ci} 21162306a36Sopenharmony_ci 21262306a36Sopenharmony_cistatic int aw_parse_bin_header(struct aw_device *aw_dev, struct aw_bin *bin) 21362306a36Sopenharmony_ci{ 21462306a36Sopenharmony_ci unsigned int bin_data_type; 21562306a36Sopenharmony_ci 21662306a36Sopenharmony_ci if (bin->info.len < sizeof(struct bin_header_info)) { 21762306a36Sopenharmony_ci dev_err(aw_dev->dev, "bin_header_info size[%d] overflow file size[%d]\n", 21862306a36Sopenharmony_ci (int)sizeof(struct bin_header_info), bin->info.len); 21962306a36Sopenharmony_ci return -EINVAL; 22062306a36Sopenharmony_ci } 22162306a36Sopenharmony_ci 22262306a36Sopenharmony_ci bin_data_type = le32_to_cpup((void *)(bin->p_addr + BIN_DATA_TYPE_OFFSET)); 22362306a36Sopenharmony_ci dev_dbg(aw_dev->dev, "aw_bin_parse bin_data_type 0x%x\n", bin_data_type); 22462306a36Sopenharmony_ci switch (bin_data_type) { 22562306a36Sopenharmony_ci case DATA_TYPE_REGISTER: 22662306a36Sopenharmony_ci case DATA_TYPE_DSP_REG: 22762306a36Sopenharmony_ci case DATA_TYPE_SOC_APP: 22862306a36Sopenharmony_ci bin->single_bin_parse_num += 1; 22962306a36Sopenharmony_ci dev_dbg(aw_dev->dev, "%s bin->single_bin_parse_num is %d\n", __func__, 23062306a36Sopenharmony_ci bin->single_bin_parse_num); 23162306a36Sopenharmony_ci if (!bin->multi_bin_parse_num) 23262306a36Sopenharmony_ci bin->header_info[bin->all_bin_parse_num].valid_data_addr = 23362306a36Sopenharmony_ci VALID_DATA_ADDR_OFFSET; 23462306a36Sopenharmony_ci aw_get_single_bin_header(bin); 23562306a36Sopenharmony_ci return 0; 23662306a36Sopenharmony_ci case DATA_TYPE_MULTI_BINS: 23762306a36Sopenharmony_ci bin->multi_bin_parse_num += 1; 23862306a36Sopenharmony_ci dev_dbg(aw_dev->dev, "%s bin->multi_bin_parse_num is %d\n", __func__, 23962306a36Sopenharmony_ci bin->multi_bin_parse_num); 24062306a36Sopenharmony_ci return aw_get_multi_bin_header(aw_dev, bin); 24162306a36Sopenharmony_ci default: 24262306a36Sopenharmony_ci dev_dbg(aw_dev->dev, "%s There is no corresponding type\n", __func__); 24362306a36Sopenharmony_ci return 0; 24462306a36Sopenharmony_ci } 24562306a36Sopenharmony_ci} 24662306a36Sopenharmony_ci 24762306a36Sopenharmony_cistatic int aw_check_bin_header_version(struct aw_device *aw_dev, struct aw_bin *bin) 24862306a36Sopenharmony_ci{ 24962306a36Sopenharmony_ci unsigned int header_version; 25062306a36Sopenharmony_ci 25162306a36Sopenharmony_ci header_version = le32_to_cpup((void *)(bin->p_addr + HEADER_VERSION_OFFSET)); 25262306a36Sopenharmony_ci dev_dbg(aw_dev->dev, "aw_bin_parse header_version 0x%x\n", header_version); 25362306a36Sopenharmony_ci 25462306a36Sopenharmony_ci switch (header_version) { 25562306a36Sopenharmony_ci case HEADER_VERSION_V1: 25662306a36Sopenharmony_ci return aw_parse_bin_header(aw_dev, bin); 25762306a36Sopenharmony_ci default: 25862306a36Sopenharmony_ci dev_err(aw_dev->dev, "aw_bin_parse Unrecognized this bin header version\n"); 25962306a36Sopenharmony_ci return -EINVAL; 26062306a36Sopenharmony_ci } 26162306a36Sopenharmony_ci} 26262306a36Sopenharmony_ci 26362306a36Sopenharmony_cistatic int aw_parsing_bin_file(struct aw_device *aw_dev, struct aw_bin *bin) 26462306a36Sopenharmony_ci{ 26562306a36Sopenharmony_ci int ret = -EINVAL; 26662306a36Sopenharmony_ci int i; 26762306a36Sopenharmony_ci 26862306a36Sopenharmony_ci if (!bin) { 26962306a36Sopenharmony_ci dev_err(aw_dev->dev, "aw_bin_parse bin is NULL\n"); 27062306a36Sopenharmony_ci return ret; 27162306a36Sopenharmony_ci } 27262306a36Sopenharmony_ci bin->p_addr = bin->info.data; 27362306a36Sopenharmony_ci bin->all_bin_parse_num = 0; 27462306a36Sopenharmony_ci bin->multi_bin_parse_num = 0; 27562306a36Sopenharmony_ci bin->single_bin_parse_num = 0; 27662306a36Sopenharmony_ci 27762306a36Sopenharmony_ci ret = aw_check_bin_header_version(aw_dev, bin); 27862306a36Sopenharmony_ci if (ret < 0) { 27962306a36Sopenharmony_ci dev_err(aw_dev->dev, "aw_bin_parse check bin header version error\n"); 28062306a36Sopenharmony_ci return ret; 28162306a36Sopenharmony_ci } 28262306a36Sopenharmony_ci 28362306a36Sopenharmony_ci for (i = 0; i < bin->all_bin_parse_num; i++) { 28462306a36Sopenharmony_ci ret = aw_check_sum(aw_dev, bin, i); 28562306a36Sopenharmony_ci if (ret < 0) { 28662306a36Sopenharmony_ci dev_err(aw_dev->dev, "aw_bin_parse check sum data error\n"); 28762306a36Sopenharmony_ci return ret; 28862306a36Sopenharmony_ci } 28962306a36Sopenharmony_ci ret = aw_check_data_version(aw_dev, bin, i); 29062306a36Sopenharmony_ci if (ret < 0) { 29162306a36Sopenharmony_ci dev_err(aw_dev->dev, "aw_bin_parse check data version error\n"); 29262306a36Sopenharmony_ci return ret; 29362306a36Sopenharmony_ci } 29462306a36Sopenharmony_ci if (bin->header_info[i].bin_data_ver == DATA_VERSION_V1) { 29562306a36Sopenharmony_ci switch (bin->header_info[i].bin_data_type) { 29662306a36Sopenharmony_ci case DATA_TYPE_REGISTER: 29762306a36Sopenharmony_ci ret = aw_check_register_num(aw_dev, bin, i); 29862306a36Sopenharmony_ci break; 29962306a36Sopenharmony_ci case DATA_TYPE_DSP_REG: 30062306a36Sopenharmony_ci ret = aw_check_dsp_reg_num(aw_dev, bin, i); 30162306a36Sopenharmony_ci break; 30262306a36Sopenharmony_ci case DATA_TYPE_SOC_APP: 30362306a36Sopenharmony_ci ret = aw_check_soc_app_num(aw_dev, bin, i); 30462306a36Sopenharmony_ci break; 30562306a36Sopenharmony_ci default: 30662306a36Sopenharmony_ci bin->header_info[i].valid_data_len = 30762306a36Sopenharmony_ci bin->header_info[i].bin_data_len; 30862306a36Sopenharmony_ci ret = 0; 30962306a36Sopenharmony_ci break; 31062306a36Sopenharmony_ci } 31162306a36Sopenharmony_ci if (ret < 0) 31262306a36Sopenharmony_ci return ret; 31362306a36Sopenharmony_ci } 31462306a36Sopenharmony_ci } 31562306a36Sopenharmony_ci 31662306a36Sopenharmony_ci return 0; 31762306a36Sopenharmony_ci} 31862306a36Sopenharmony_ci 31962306a36Sopenharmony_cistatic int aw_dev_parse_raw_reg(unsigned char *data, unsigned int data_len, 32062306a36Sopenharmony_ci struct aw_prof_desc *prof_desc) 32162306a36Sopenharmony_ci{ 32262306a36Sopenharmony_ci prof_desc->sec_desc[AW88395_DATA_TYPE_REG].data = data; 32362306a36Sopenharmony_ci prof_desc->sec_desc[AW88395_DATA_TYPE_REG].len = data_len; 32462306a36Sopenharmony_ci 32562306a36Sopenharmony_ci prof_desc->prof_st = AW88395_PROFILE_OK; 32662306a36Sopenharmony_ci 32762306a36Sopenharmony_ci return 0; 32862306a36Sopenharmony_ci} 32962306a36Sopenharmony_ci 33062306a36Sopenharmony_cistatic int aw_dev_parse_raw_dsp_cfg(unsigned char *data, unsigned int data_len, 33162306a36Sopenharmony_ci struct aw_prof_desc *prof_desc) 33262306a36Sopenharmony_ci{ 33362306a36Sopenharmony_ci if (data_len & 0x01) 33462306a36Sopenharmony_ci return -EINVAL; 33562306a36Sopenharmony_ci 33662306a36Sopenharmony_ci swab16_array((u16 *)data, data_len >> 1); 33762306a36Sopenharmony_ci 33862306a36Sopenharmony_ci prof_desc->sec_desc[AW88395_DATA_TYPE_DSP_CFG].data = data; 33962306a36Sopenharmony_ci prof_desc->sec_desc[AW88395_DATA_TYPE_DSP_CFG].len = data_len; 34062306a36Sopenharmony_ci 34162306a36Sopenharmony_ci prof_desc->prof_st = AW88395_PROFILE_OK; 34262306a36Sopenharmony_ci 34362306a36Sopenharmony_ci return 0; 34462306a36Sopenharmony_ci} 34562306a36Sopenharmony_ci 34662306a36Sopenharmony_cistatic int aw_dev_parse_raw_dsp_fw(unsigned char *data, unsigned int data_len, 34762306a36Sopenharmony_ci struct aw_prof_desc *prof_desc) 34862306a36Sopenharmony_ci{ 34962306a36Sopenharmony_ci if (data_len & 0x01) 35062306a36Sopenharmony_ci return -EINVAL; 35162306a36Sopenharmony_ci 35262306a36Sopenharmony_ci swab16_array((u16 *)data, data_len >> 1); 35362306a36Sopenharmony_ci 35462306a36Sopenharmony_ci prof_desc->sec_desc[AW88395_DATA_TYPE_DSP_FW].data = data; 35562306a36Sopenharmony_ci prof_desc->sec_desc[AW88395_DATA_TYPE_DSP_FW].len = data_len; 35662306a36Sopenharmony_ci 35762306a36Sopenharmony_ci prof_desc->prof_st = AW88395_PROFILE_OK; 35862306a36Sopenharmony_ci 35962306a36Sopenharmony_ci return 0; 36062306a36Sopenharmony_ci} 36162306a36Sopenharmony_ci 36262306a36Sopenharmony_cistatic int aw_dev_prof_parse_multi_bin(struct aw_device *aw_dev, unsigned char *data, 36362306a36Sopenharmony_ci unsigned int data_len, struct aw_prof_desc *prof_desc) 36462306a36Sopenharmony_ci{ 36562306a36Sopenharmony_ci struct aw_bin *aw_bin; 36662306a36Sopenharmony_ci int ret; 36762306a36Sopenharmony_ci int i; 36862306a36Sopenharmony_ci 36962306a36Sopenharmony_ci aw_bin = devm_kzalloc(aw_dev->dev, data_len + sizeof(struct aw_bin), GFP_KERNEL); 37062306a36Sopenharmony_ci if (!aw_bin) 37162306a36Sopenharmony_ci return -ENOMEM; 37262306a36Sopenharmony_ci 37362306a36Sopenharmony_ci aw_bin->info.len = data_len; 37462306a36Sopenharmony_ci memcpy(aw_bin->info.data, data, data_len); 37562306a36Sopenharmony_ci 37662306a36Sopenharmony_ci ret = aw_parsing_bin_file(aw_dev, aw_bin); 37762306a36Sopenharmony_ci if (ret < 0) { 37862306a36Sopenharmony_ci dev_err(aw_dev->dev, "parse bin failed"); 37962306a36Sopenharmony_ci goto parse_bin_failed; 38062306a36Sopenharmony_ci } 38162306a36Sopenharmony_ci 38262306a36Sopenharmony_ci for (i = 0; i < aw_bin->all_bin_parse_num; i++) { 38362306a36Sopenharmony_ci switch (aw_bin->header_info[i].bin_data_type) { 38462306a36Sopenharmony_ci case DATA_TYPE_REGISTER: 38562306a36Sopenharmony_ci prof_desc->sec_desc[AW88395_DATA_TYPE_REG].len = 38662306a36Sopenharmony_ci aw_bin->header_info[i].valid_data_len; 38762306a36Sopenharmony_ci prof_desc->sec_desc[AW88395_DATA_TYPE_REG].data = 38862306a36Sopenharmony_ci data + aw_bin->header_info[i].valid_data_addr; 38962306a36Sopenharmony_ci break; 39062306a36Sopenharmony_ci case DATA_TYPE_DSP_REG: 39162306a36Sopenharmony_ci if (aw_bin->header_info[i].valid_data_len & 0x01) { 39262306a36Sopenharmony_ci ret = -EINVAL; 39362306a36Sopenharmony_ci goto parse_bin_failed; 39462306a36Sopenharmony_ci } 39562306a36Sopenharmony_ci 39662306a36Sopenharmony_ci swab16_array((u16 *)(data + aw_bin->header_info[i].valid_data_addr), 39762306a36Sopenharmony_ci aw_bin->header_info[i].valid_data_len >> 1); 39862306a36Sopenharmony_ci 39962306a36Sopenharmony_ci prof_desc->sec_desc[AW88395_DATA_TYPE_DSP_CFG].len = 40062306a36Sopenharmony_ci aw_bin->header_info[i].valid_data_len; 40162306a36Sopenharmony_ci prof_desc->sec_desc[AW88395_DATA_TYPE_DSP_CFG].data = 40262306a36Sopenharmony_ci data + aw_bin->header_info[i].valid_data_addr; 40362306a36Sopenharmony_ci break; 40462306a36Sopenharmony_ci case DATA_TYPE_DSP_FW: 40562306a36Sopenharmony_ci case DATA_TYPE_SOC_APP: 40662306a36Sopenharmony_ci if (aw_bin->header_info[i].valid_data_len & 0x01) { 40762306a36Sopenharmony_ci ret = -EINVAL; 40862306a36Sopenharmony_ci goto parse_bin_failed; 40962306a36Sopenharmony_ci } 41062306a36Sopenharmony_ci 41162306a36Sopenharmony_ci swab16_array((u16 *)(data + aw_bin->header_info[i].valid_data_addr), 41262306a36Sopenharmony_ci aw_bin->header_info[i].valid_data_len >> 1); 41362306a36Sopenharmony_ci 41462306a36Sopenharmony_ci prof_desc->fw_ver = aw_bin->header_info[i].app_version; 41562306a36Sopenharmony_ci prof_desc->sec_desc[AW88395_DATA_TYPE_DSP_FW].len = 41662306a36Sopenharmony_ci aw_bin->header_info[i].valid_data_len; 41762306a36Sopenharmony_ci prof_desc->sec_desc[AW88395_DATA_TYPE_DSP_FW].data = 41862306a36Sopenharmony_ci data + aw_bin->header_info[i].valid_data_addr; 41962306a36Sopenharmony_ci break; 42062306a36Sopenharmony_ci default: 42162306a36Sopenharmony_ci dev_dbg(aw_dev->dev, "bin_data_type not found"); 42262306a36Sopenharmony_ci break; 42362306a36Sopenharmony_ci } 42462306a36Sopenharmony_ci } 42562306a36Sopenharmony_ci prof_desc->prof_st = AW88395_PROFILE_OK; 42662306a36Sopenharmony_ci ret = 0; 42762306a36Sopenharmony_ci 42862306a36Sopenharmony_ciparse_bin_failed: 42962306a36Sopenharmony_ci devm_kfree(aw_dev->dev, aw_bin); 43062306a36Sopenharmony_ci return ret; 43162306a36Sopenharmony_ci} 43262306a36Sopenharmony_ci 43362306a36Sopenharmony_cistatic int aw_dev_parse_reg_bin_with_hdr(struct aw_device *aw_dev, 43462306a36Sopenharmony_ci uint8_t *data, uint32_t data_len, struct aw_prof_desc *prof_desc) 43562306a36Sopenharmony_ci{ 43662306a36Sopenharmony_ci struct aw_bin *aw_bin; 43762306a36Sopenharmony_ci int ret; 43862306a36Sopenharmony_ci 43962306a36Sopenharmony_ci aw_bin = devm_kzalloc(aw_dev->dev, data_len + sizeof(*aw_bin), GFP_KERNEL); 44062306a36Sopenharmony_ci if (!aw_bin) 44162306a36Sopenharmony_ci return -ENOMEM; 44262306a36Sopenharmony_ci 44362306a36Sopenharmony_ci aw_bin->info.len = data_len; 44462306a36Sopenharmony_ci memcpy(aw_bin->info.data, data, data_len); 44562306a36Sopenharmony_ci 44662306a36Sopenharmony_ci ret = aw_parsing_bin_file(aw_dev, aw_bin); 44762306a36Sopenharmony_ci if (ret < 0) { 44862306a36Sopenharmony_ci dev_err(aw_dev->dev, "parse bin failed"); 44962306a36Sopenharmony_ci goto parse_bin_failed; 45062306a36Sopenharmony_ci } 45162306a36Sopenharmony_ci 45262306a36Sopenharmony_ci if ((aw_bin->all_bin_parse_num != 1) || 45362306a36Sopenharmony_ci (aw_bin->header_info[0].bin_data_type != DATA_TYPE_REGISTER)) { 45462306a36Sopenharmony_ci dev_err(aw_dev->dev, "bin num or type error"); 45562306a36Sopenharmony_ci ret = -EINVAL; 45662306a36Sopenharmony_ci goto parse_bin_failed; 45762306a36Sopenharmony_ci } 45862306a36Sopenharmony_ci 45962306a36Sopenharmony_ci if (aw_bin->header_info[0].valid_data_len % 4) { 46062306a36Sopenharmony_ci dev_err(aw_dev->dev, "bin data len get error!"); 46162306a36Sopenharmony_ci ret = -EINVAL; 46262306a36Sopenharmony_ci goto parse_bin_failed; 46362306a36Sopenharmony_ci } 46462306a36Sopenharmony_ci 46562306a36Sopenharmony_ci prof_desc->sec_desc[AW88395_DATA_TYPE_REG].data = 46662306a36Sopenharmony_ci data + aw_bin->header_info[0].valid_data_addr; 46762306a36Sopenharmony_ci prof_desc->sec_desc[AW88395_DATA_TYPE_REG].len = 46862306a36Sopenharmony_ci aw_bin->header_info[0].valid_data_len; 46962306a36Sopenharmony_ci prof_desc->prof_st = AW88395_PROFILE_OK; 47062306a36Sopenharmony_ci 47162306a36Sopenharmony_ci devm_kfree(aw_dev->dev, aw_bin); 47262306a36Sopenharmony_ci aw_bin = NULL; 47362306a36Sopenharmony_ci 47462306a36Sopenharmony_ci return 0; 47562306a36Sopenharmony_ci 47662306a36Sopenharmony_ciparse_bin_failed: 47762306a36Sopenharmony_ci devm_kfree(aw_dev->dev, aw_bin); 47862306a36Sopenharmony_ci aw_bin = NULL; 47962306a36Sopenharmony_ci return ret; 48062306a36Sopenharmony_ci} 48162306a36Sopenharmony_ci 48262306a36Sopenharmony_cistatic int aw_dev_parse_data_by_sec_type(struct aw_device *aw_dev, struct aw_cfg_hdr *cfg_hdr, 48362306a36Sopenharmony_ci struct aw_cfg_dde *cfg_dde, struct aw_prof_desc *scene_prof_desc) 48462306a36Sopenharmony_ci{ 48562306a36Sopenharmony_ci switch (cfg_dde->data_type) { 48662306a36Sopenharmony_ci case ACF_SEC_TYPE_REG: 48762306a36Sopenharmony_ci return aw_dev_parse_raw_reg((u8 *)cfg_hdr + cfg_dde->data_offset, 48862306a36Sopenharmony_ci cfg_dde->data_size, scene_prof_desc); 48962306a36Sopenharmony_ci case ACF_SEC_TYPE_DSP_CFG: 49062306a36Sopenharmony_ci return aw_dev_parse_raw_dsp_cfg((u8 *)cfg_hdr + cfg_dde->data_offset, 49162306a36Sopenharmony_ci cfg_dde->data_size, scene_prof_desc); 49262306a36Sopenharmony_ci case ACF_SEC_TYPE_DSP_FW: 49362306a36Sopenharmony_ci return aw_dev_parse_raw_dsp_fw( 49462306a36Sopenharmony_ci (u8 *)cfg_hdr + cfg_dde->data_offset, 49562306a36Sopenharmony_ci cfg_dde->data_size, scene_prof_desc); 49662306a36Sopenharmony_ci case ACF_SEC_TYPE_MULTIPLE_BIN: 49762306a36Sopenharmony_ci return aw_dev_prof_parse_multi_bin( 49862306a36Sopenharmony_ci aw_dev, (u8 *)cfg_hdr + cfg_dde->data_offset, 49962306a36Sopenharmony_ci cfg_dde->data_size, scene_prof_desc); 50062306a36Sopenharmony_ci case ACF_SEC_TYPE_HDR_REG: 50162306a36Sopenharmony_ci return aw_dev_parse_reg_bin_with_hdr(aw_dev, (u8 *)cfg_hdr + cfg_dde->data_offset, 50262306a36Sopenharmony_ci cfg_dde->data_size, scene_prof_desc); 50362306a36Sopenharmony_ci default: 50462306a36Sopenharmony_ci dev_err(aw_dev->dev, "%s cfg_dde->data_type = %d\n", __func__, cfg_dde->data_type); 50562306a36Sopenharmony_ci break; 50662306a36Sopenharmony_ci } 50762306a36Sopenharmony_ci 50862306a36Sopenharmony_ci return 0; 50962306a36Sopenharmony_ci} 51062306a36Sopenharmony_ci 51162306a36Sopenharmony_cistatic int aw_dev_parse_dev_type(struct aw_device *aw_dev, 51262306a36Sopenharmony_ci struct aw_cfg_hdr *prof_hdr, struct aw_all_prof_info *all_prof_info) 51362306a36Sopenharmony_ci{ 51462306a36Sopenharmony_ci struct aw_cfg_dde *cfg_dde = 51562306a36Sopenharmony_ci (struct aw_cfg_dde *)((char *)prof_hdr + prof_hdr->hdr_offset); 51662306a36Sopenharmony_ci int sec_num = 0; 51762306a36Sopenharmony_ci int ret, i; 51862306a36Sopenharmony_ci 51962306a36Sopenharmony_ci for (i = 0; i < prof_hdr->ddt_num; i++) { 52062306a36Sopenharmony_ci if ((aw_dev->i2c->adapter->nr == cfg_dde[i].dev_bus) && 52162306a36Sopenharmony_ci (aw_dev->i2c->addr == cfg_dde[i].dev_addr) && 52262306a36Sopenharmony_ci (cfg_dde[i].type == AW88395_DEV_TYPE_ID) && 52362306a36Sopenharmony_ci (cfg_dde[i].data_type != ACF_SEC_TYPE_MONITOR)) { 52462306a36Sopenharmony_ci if (cfg_dde[i].dev_profile >= AW88395_PROFILE_MAX) { 52562306a36Sopenharmony_ci dev_err(aw_dev->dev, "dev_profile [%d] overflow", 52662306a36Sopenharmony_ci cfg_dde[i].dev_profile); 52762306a36Sopenharmony_ci return -EINVAL; 52862306a36Sopenharmony_ci } 52962306a36Sopenharmony_ci 53062306a36Sopenharmony_ci ret = aw_dev_parse_data_by_sec_type(aw_dev, prof_hdr, &cfg_dde[i], 53162306a36Sopenharmony_ci &all_prof_info->prof_desc[cfg_dde[i].dev_profile]); 53262306a36Sopenharmony_ci if (ret < 0) { 53362306a36Sopenharmony_ci dev_err(aw_dev->dev, "parse failed"); 53462306a36Sopenharmony_ci return ret; 53562306a36Sopenharmony_ci } 53662306a36Sopenharmony_ci sec_num++; 53762306a36Sopenharmony_ci } 53862306a36Sopenharmony_ci } 53962306a36Sopenharmony_ci 54062306a36Sopenharmony_ci if (sec_num == 0) { 54162306a36Sopenharmony_ci dev_dbg(aw_dev->dev, "get dev type num is %d, please use default", sec_num); 54262306a36Sopenharmony_ci return AW88395_DEV_TYPE_NONE; 54362306a36Sopenharmony_ci } 54462306a36Sopenharmony_ci 54562306a36Sopenharmony_ci return AW88395_DEV_TYPE_OK; 54662306a36Sopenharmony_ci} 54762306a36Sopenharmony_ci 54862306a36Sopenharmony_cistatic int aw_dev_parse_dev_default_type(struct aw_device *aw_dev, 54962306a36Sopenharmony_ci struct aw_cfg_hdr *prof_hdr, struct aw_all_prof_info *all_prof_info) 55062306a36Sopenharmony_ci{ 55162306a36Sopenharmony_ci struct aw_cfg_dde *cfg_dde = 55262306a36Sopenharmony_ci (struct aw_cfg_dde *)((char *)prof_hdr + prof_hdr->hdr_offset); 55362306a36Sopenharmony_ci int sec_num = 0; 55462306a36Sopenharmony_ci int ret, i; 55562306a36Sopenharmony_ci 55662306a36Sopenharmony_ci for (i = 0; i < prof_hdr->ddt_num; i++) { 55762306a36Sopenharmony_ci if ((aw_dev->channel == cfg_dde[i].dev_index) && 55862306a36Sopenharmony_ci (cfg_dde[i].type == AW88395_DEV_DEFAULT_TYPE_ID) && 55962306a36Sopenharmony_ci (cfg_dde[i].data_type != ACF_SEC_TYPE_MONITOR)) { 56062306a36Sopenharmony_ci if (cfg_dde[i].dev_profile >= AW88395_PROFILE_MAX) { 56162306a36Sopenharmony_ci dev_err(aw_dev->dev, "dev_profile [%d] overflow", 56262306a36Sopenharmony_ci cfg_dde[i].dev_profile); 56362306a36Sopenharmony_ci return -EINVAL; 56462306a36Sopenharmony_ci } 56562306a36Sopenharmony_ci ret = aw_dev_parse_data_by_sec_type(aw_dev, prof_hdr, &cfg_dde[i], 56662306a36Sopenharmony_ci &all_prof_info->prof_desc[cfg_dde[i].dev_profile]); 56762306a36Sopenharmony_ci if (ret < 0) { 56862306a36Sopenharmony_ci dev_err(aw_dev->dev, "parse failed"); 56962306a36Sopenharmony_ci return ret; 57062306a36Sopenharmony_ci } 57162306a36Sopenharmony_ci sec_num++; 57262306a36Sopenharmony_ci } 57362306a36Sopenharmony_ci } 57462306a36Sopenharmony_ci 57562306a36Sopenharmony_ci if (sec_num == 0) { 57662306a36Sopenharmony_ci dev_err(aw_dev->dev, "get dev default type failed, get num[%d]", sec_num); 57762306a36Sopenharmony_ci return -EINVAL; 57862306a36Sopenharmony_ci } 57962306a36Sopenharmony_ci 58062306a36Sopenharmony_ci return 0; 58162306a36Sopenharmony_ci} 58262306a36Sopenharmony_ci 58362306a36Sopenharmony_cistatic int aw88261_dev_cfg_get_valid_prof(struct aw_device *aw_dev, 58462306a36Sopenharmony_ci struct aw_all_prof_info all_prof_info) 58562306a36Sopenharmony_ci{ 58662306a36Sopenharmony_ci struct aw_prof_desc *prof_desc = all_prof_info.prof_desc; 58762306a36Sopenharmony_ci struct aw_prof_info *prof_info = &aw_dev->prof_info; 58862306a36Sopenharmony_ci int num = 0; 58962306a36Sopenharmony_ci int i; 59062306a36Sopenharmony_ci 59162306a36Sopenharmony_ci for (i = 0; i < AW88395_PROFILE_MAX; i++) { 59262306a36Sopenharmony_ci if (prof_desc[i].prof_st == AW88395_PROFILE_OK) 59362306a36Sopenharmony_ci prof_info->count++; 59462306a36Sopenharmony_ci } 59562306a36Sopenharmony_ci 59662306a36Sopenharmony_ci dev_dbg(aw_dev->dev, "get valid profile:%d", aw_dev->prof_info.count); 59762306a36Sopenharmony_ci 59862306a36Sopenharmony_ci if (!prof_info->count) { 59962306a36Sopenharmony_ci dev_err(aw_dev->dev, "no profile data"); 60062306a36Sopenharmony_ci return -EPERM; 60162306a36Sopenharmony_ci } 60262306a36Sopenharmony_ci 60362306a36Sopenharmony_ci prof_info->prof_desc = devm_kcalloc(aw_dev->dev, 60462306a36Sopenharmony_ci prof_info->count, sizeof(struct aw_prof_desc), 60562306a36Sopenharmony_ci GFP_KERNEL); 60662306a36Sopenharmony_ci if (!prof_info->prof_desc) 60762306a36Sopenharmony_ci return -ENOMEM; 60862306a36Sopenharmony_ci 60962306a36Sopenharmony_ci for (i = 0; i < AW88395_PROFILE_MAX; i++) { 61062306a36Sopenharmony_ci if (prof_desc[i].prof_st == AW88395_PROFILE_OK) { 61162306a36Sopenharmony_ci if (num >= prof_info->count) { 61262306a36Sopenharmony_ci dev_err(aw_dev->dev, "overflow count[%d]", 61362306a36Sopenharmony_ci prof_info->count); 61462306a36Sopenharmony_ci return -EINVAL; 61562306a36Sopenharmony_ci } 61662306a36Sopenharmony_ci prof_info->prof_desc[num] = prof_desc[i]; 61762306a36Sopenharmony_ci prof_info->prof_desc[num].id = i; 61862306a36Sopenharmony_ci num++; 61962306a36Sopenharmony_ci } 62062306a36Sopenharmony_ci } 62162306a36Sopenharmony_ci 62262306a36Sopenharmony_ci return 0; 62362306a36Sopenharmony_ci} 62462306a36Sopenharmony_ci 62562306a36Sopenharmony_cistatic int aw88395_dev_cfg_get_valid_prof(struct aw_device *aw_dev, 62662306a36Sopenharmony_ci struct aw_all_prof_info all_prof_info) 62762306a36Sopenharmony_ci{ 62862306a36Sopenharmony_ci struct aw_prof_desc *prof_desc = all_prof_info.prof_desc; 62962306a36Sopenharmony_ci struct aw_prof_info *prof_info = &aw_dev->prof_info; 63062306a36Sopenharmony_ci struct aw_sec_data_desc *sec_desc; 63162306a36Sopenharmony_ci int num = 0; 63262306a36Sopenharmony_ci int i; 63362306a36Sopenharmony_ci 63462306a36Sopenharmony_ci for (i = 0; i < AW88395_PROFILE_MAX; i++) { 63562306a36Sopenharmony_ci if (prof_desc[i].prof_st == AW88395_PROFILE_OK) { 63662306a36Sopenharmony_ci sec_desc = prof_desc[i].sec_desc; 63762306a36Sopenharmony_ci if ((sec_desc[AW88395_DATA_TYPE_REG].data != NULL) && 63862306a36Sopenharmony_ci (sec_desc[AW88395_DATA_TYPE_REG].len != 0) && 63962306a36Sopenharmony_ci (sec_desc[AW88395_DATA_TYPE_DSP_CFG].data != NULL) && 64062306a36Sopenharmony_ci (sec_desc[AW88395_DATA_TYPE_DSP_CFG].len != 0) && 64162306a36Sopenharmony_ci (sec_desc[AW88395_DATA_TYPE_DSP_FW].data != NULL) && 64262306a36Sopenharmony_ci (sec_desc[AW88395_DATA_TYPE_DSP_FW].len != 0)) 64362306a36Sopenharmony_ci prof_info->count++; 64462306a36Sopenharmony_ci } 64562306a36Sopenharmony_ci } 64662306a36Sopenharmony_ci 64762306a36Sopenharmony_ci dev_dbg(aw_dev->dev, "get valid profile:%d", aw_dev->prof_info.count); 64862306a36Sopenharmony_ci 64962306a36Sopenharmony_ci if (!prof_info->count) { 65062306a36Sopenharmony_ci dev_err(aw_dev->dev, "no profile data"); 65162306a36Sopenharmony_ci return -EPERM; 65262306a36Sopenharmony_ci } 65362306a36Sopenharmony_ci 65462306a36Sopenharmony_ci prof_info->prof_desc = devm_kcalloc(aw_dev->dev, 65562306a36Sopenharmony_ci prof_info->count, sizeof(struct aw_prof_desc), 65662306a36Sopenharmony_ci GFP_KERNEL); 65762306a36Sopenharmony_ci if (!prof_info->prof_desc) 65862306a36Sopenharmony_ci return -ENOMEM; 65962306a36Sopenharmony_ci 66062306a36Sopenharmony_ci for (i = 0; i < AW88395_PROFILE_MAX; i++) { 66162306a36Sopenharmony_ci if (prof_desc[i].prof_st == AW88395_PROFILE_OK) { 66262306a36Sopenharmony_ci sec_desc = prof_desc[i].sec_desc; 66362306a36Sopenharmony_ci if ((sec_desc[AW88395_DATA_TYPE_REG].data != NULL) && 66462306a36Sopenharmony_ci (sec_desc[AW88395_DATA_TYPE_REG].len != 0) && 66562306a36Sopenharmony_ci (sec_desc[AW88395_DATA_TYPE_DSP_CFG].data != NULL) && 66662306a36Sopenharmony_ci (sec_desc[AW88395_DATA_TYPE_DSP_CFG].len != 0) && 66762306a36Sopenharmony_ci (sec_desc[AW88395_DATA_TYPE_DSP_FW].data != NULL) && 66862306a36Sopenharmony_ci (sec_desc[AW88395_DATA_TYPE_DSP_FW].len != 0)) { 66962306a36Sopenharmony_ci if (num >= prof_info->count) { 67062306a36Sopenharmony_ci dev_err(aw_dev->dev, "overflow count[%d]", 67162306a36Sopenharmony_ci prof_info->count); 67262306a36Sopenharmony_ci return -EINVAL; 67362306a36Sopenharmony_ci } 67462306a36Sopenharmony_ci prof_info->prof_desc[num] = prof_desc[i]; 67562306a36Sopenharmony_ci prof_info->prof_desc[num].id = i; 67662306a36Sopenharmony_ci num++; 67762306a36Sopenharmony_ci } 67862306a36Sopenharmony_ci } 67962306a36Sopenharmony_ci } 68062306a36Sopenharmony_ci 68162306a36Sopenharmony_ci return 0; 68262306a36Sopenharmony_ci} 68362306a36Sopenharmony_ci 68462306a36Sopenharmony_cistatic int aw_dev_load_cfg_by_hdr(struct aw_device *aw_dev, 68562306a36Sopenharmony_ci struct aw_cfg_hdr *prof_hdr) 68662306a36Sopenharmony_ci{ 68762306a36Sopenharmony_ci struct aw_all_prof_info *all_prof_info; 68862306a36Sopenharmony_ci int ret; 68962306a36Sopenharmony_ci 69062306a36Sopenharmony_ci all_prof_info = devm_kzalloc(aw_dev->dev, sizeof(struct aw_all_prof_info), GFP_KERNEL); 69162306a36Sopenharmony_ci if (!all_prof_info) 69262306a36Sopenharmony_ci return -ENOMEM; 69362306a36Sopenharmony_ci 69462306a36Sopenharmony_ci ret = aw_dev_parse_dev_type(aw_dev, prof_hdr, all_prof_info); 69562306a36Sopenharmony_ci if (ret < 0) { 69662306a36Sopenharmony_ci goto exit; 69762306a36Sopenharmony_ci } else if (ret == AW88395_DEV_TYPE_NONE) { 69862306a36Sopenharmony_ci dev_dbg(aw_dev->dev, "get dev type num is 0, parse default dev"); 69962306a36Sopenharmony_ci ret = aw_dev_parse_dev_default_type(aw_dev, prof_hdr, all_prof_info); 70062306a36Sopenharmony_ci if (ret < 0) 70162306a36Sopenharmony_ci goto exit; 70262306a36Sopenharmony_ci } 70362306a36Sopenharmony_ci 70462306a36Sopenharmony_ci switch (aw_dev->chip_id) { 70562306a36Sopenharmony_ci case AW88395_CHIP_ID: 70662306a36Sopenharmony_ci ret = aw88395_dev_cfg_get_valid_prof(aw_dev, *all_prof_info); 70762306a36Sopenharmony_ci if (ret < 0) 70862306a36Sopenharmony_ci goto exit; 70962306a36Sopenharmony_ci break; 71062306a36Sopenharmony_ci case AW88261_CHIP_ID: 71162306a36Sopenharmony_ci ret = aw88261_dev_cfg_get_valid_prof(aw_dev, *all_prof_info); 71262306a36Sopenharmony_ci if (ret < 0) 71362306a36Sopenharmony_ci goto exit; 71462306a36Sopenharmony_ci break; 71562306a36Sopenharmony_ci default: 71662306a36Sopenharmony_ci dev_err(aw_dev->dev, "valid prof unsupported"); 71762306a36Sopenharmony_ci ret = -EINVAL; 71862306a36Sopenharmony_ci break; 71962306a36Sopenharmony_ci } 72062306a36Sopenharmony_ci 72162306a36Sopenharmony_ci aw_dev->prof_info.prof_name_list = profile_name; 72262306a36Sopenharmony_ci 72362306a36Sopenharmony_ciexit: 72462306a36Sopenharmony_ci devm_kfree(aw_dev->dev, all_prof_info); 72562306a36Sopenharmony_ci return ret; 72662306a36Sopenharmony_ci} 72762306a36Sopenharmony_ci 72862306a36Sopenharmony_cistatic int aw_dev_create_prof_name_list_v1(struct aw_device *aw_dev) 72962306a36Sopenharmony_ci{ 73062306a36Sopenharmony_ci struct aw_prof_info *prof_info = &aw_dev->prof_info; 73162306a36Sopenharmony_ci struct aw_prof_desc *prof_desc = prof_info->prof_desc; 73262306a36Sopenharmony_ci int i; 73362306a36Sopenharmony_ci 73462306a36Sopenharmony_ci if (!prof_desc) { 73562306a36Sopenharmony_ci dev_err(aw_dev->dev, "prof_desc is NULL"); 73662306a36Sopenharmony_ci return -EINVAL; 73762306a36Sopenharmony_ci } 73862306a36Sopenharmony_ci 73962306a36Sopenharmony_ci prof_info->prof_name_list = devm_kzalloc(aw_dev->dev, 74062306a36Sopenharmony_ci prof_info->count * PROFILE_STR_MAX, 74162306a36Sopenharmony_ci GFP_KERNEL); 74262306a36Sopenharmony_ci if (!prof_info->prof_name_list) 74362306a36Sopenharmony_ci return -ENOMEM; 74462306a36Sopenharmony_ci 74562306a36Sopenharmony_ci for (i = 0; i < prof_info->count; i++) { 74662306a36Sopenharmony_ci prof_desc[i].id = i; 74762306a36Sopenharmony_ci prof_info->prof_name_list[i] = prof_desc[i].prf_str; 74862306a36Sopenharmony_ci dev_dbg(aw_dev->dev, "prof name is %s", prof_info->prof_name_list[i]); 74962306a36Sopenharmony_ci } 75062306a36Sopenharmony_ci 75162306a36Sopenharmony_ci return 0; 75262306a36Sopenharmony_ci} 75362306a36Sopenharmony_ci 75462306a36Sopenharmony_cistatic int aw_get_dde_type_info(struct aw_device *aw_dev, struct aw_container *aw_cfg) 75562306a36Sopenharmony_ci{ 75662306a36Sopenharmony_ci struct aw_cfg_hdr *cfg_hdr = (struct aw_cfg_hdr *)aw_cfg->data; 75762306a36Sopenharmony_ci struct aw_cfg_dde_v1 *cfg_dde = 75862306a36Sopenharmony_ci (struct aw_cfg_dde_v1 *)(aw_cfg->data + cfg_hdr->hdr_offset); 75962306a36Sopenharmony_ci int default_num = 0; 76062306a36Sopenharmony_ci int dev_num = 0; 76162306a36Sopenharmony_ci unsigned int i; 76262306a36Sopenharmony_ci 76362306a36Sopenharmony_ci for (i = 0; i < cfg_hdr->ddt_num; i++) { 76462306a36Sopenharmony_ci if (cfg_dde[i].type == AW88395_DEV_TYPE_ID) 76562306a36Sopenharmony_ci dev_num++; 76662306a36Sopenharmony_ci 76762306a36Sopenharmony_ci if (cfg_dde[i].type == AW88395_DEV_DEFAULT_TYPE_ID) 76862306a36Sopenharmony_ci default_num++; 76962306a36Sopenharmony_ci } 77062306a36Sopenharmony_ci 77162306a36Sopenharmony_ci if (dev_num != 0) { 77262306a36Sopenharmony_ci aw_dev->prof_info.prof_type = AW88395_DEV_TYPE_ID; 77362306a36Sopenharmony_ci } else if (default_num != 0) { 77462306a36Sopenharmony_ci aw_dev->prof_info.prof_type = AW88395_DEV_DEFAULT_TYPE_ID; 77562306a36Sopenharmony_ci } else { 77662306a36Sopenharmony_ci dev_err(aw_dev->dev, "can't find scene"); 77762306a36Sopenharmony_ci return -EINVAL; 77862306a36Sopenharmony_ci } 77962306a36Sopenharmony_ci 78062306a36Sopenharmony_ci return 0; 78162306a36Sopenharmony_ci} 78262306a36Sopenharmony_ci 78362306a36Sopenharmony_cistatic int aw_get_dev_scene_count_v1(struct aw_device *aw_dev, struct aw_container *aw_cfg, 78462306a36Sopenharmony_ci unsigned int *scene_num) 78562306a36Sopenharmony_ci{ 78662306a36Sopenharmony_ci struct aw_cfg_hdr *cfg_hdr = (struct aw_cfg_hdr *)aw_cfg->data; 78762306a36Sopenharmony_ci struct aw_cfg_dde_v1 *cfg_dde = 78862306a36Sopenharmony_ci (struct aw_cfg_dde_v1 *)(aw_cfg->data + cfg_hdr->hdr_offset); 78962306a36Sopenharmony_ci unsigned int i; 79062306a36Sopenharmony_ci int ret; 79162306a36Sopenharmony_ci 79262306a36Sopenharmony_ci switch (aw_dev->chip_id) { 79362306a36Sopenharmony_ci case AW88395_CHIP_ID: 79462306a36Sopenharmony_ci for (i = 0; i < cfg_hdr->ddt_num; ++i) { 79562306a36Sopenharmony_ci if ((cfg_dde[i].data_type == ACF_SEC_TYPE_MULTIPLE_BIN) && 79662306a36Sopenharmony_ci (aw_dev->chip_id == cfg_dde[i].chip_id) && 79762306a36Sopenharmony_ci (aw_dev->i2c->adapter->nr == cfg_dde[i].dev_bus) && 79862306a36Sopenharmony_ci (aw_dev->i2c->addr == cfg_dde[i].dev_addr)) 79962306a36Sopenharmony_ci (*scene_num)++; 80062306a36Sopenharmony_ci } 80162306a36Sopenharmony_ci ret = 0; 80262306a36Sopenharmony_ci break; 80362306a36Sopenharmony_ci case AW88261_CHIP_ID: 80462306a36Sopenharmony_ci for (i = 0; i < cfg_hdr->ddt_num; ++i) { 80562306a36Sopenharmony_ci if (((cfg_dde[i].data_type == ACF_SEC_TYPE_REG) || 80662306a36Sopenharmony_ci (cfg_dde[i].data_type == ACF_SEC_TYPE_HDR_REG)) && 80762306a36Sopenharmony_ci (aw_dev->chip_id == cfg_dde[i].chip_id) && 80862306a36Sopenharmony_ci (aw_dev->i2c->adapter->nr == cfg_dde[i].dev_bus) && 80962306a36Sopenharmony_ci (aw_dev->i2c->addr == cfg_dde[i].dev_addr)) 81062306a36Sopenharmony_ci (*scene_num)++; 81162306a36Sopenharmony_ci } 81262306a36Sopenharmony_ci ret = 0; 81362306a36Sopenharmony_ci break; 81462306a36Sopenharmony_ci default: 81562306a36Sopenharmony_ci dev_err(aw_dev->dev, "unsupported device"); 81662306a36Sopenharmony_ci ret = -EINVAL; 81762306a36Sopenharmony_ci break; 81862306a36Sopenharmony_ci } 81962306a36Sopenharmony_ci 82062306a36Sopenharmony_ci return ret; 82162306a36Sopenharmony_ci} 82262306a36Sopenharmony_ci 82362306a36Sopenharmony_cistatic int aw_get_default_scene_count_v1(struct aw_device *aw_dev, 82462306a36Sopenharmony_ci struct aw_container *aw_cfg, 82562306a36Sopenharmony_ci unsigned int *scene_num) 82662306a36Sopenharmony_ci{ 82762306a36Sopenharmony_ci struct aw_cfg_hdr *cfg_hdr = (struct aw_cfg_hdr *)aw_cfg->data; 82862306a36Sopenharmony_ci struct aw_cfg_dde_v1 *cfg_dde = 82962306a36Sopenharmony_ci (struct aw_cfg_dde_v1 *)(aw_cfg->data + cfg_hdr->hdr_offset); 83062306a36Sopenharmony_ci unsigned int i; 83162306a36Sopenharmony_ci int ret; 83262306a36Sopenharmony_ci 83362306a36Sopenharmony_ci switch (aw_dev->chip_id) { 83462306a36Sopenharmony_ci case AW88395_CHIP_ID: 83562306a36Sopenharmony_ci for (i = 0; i < cfg_hdr->ddt_num; ++i) { 83662306a36Sopenharmony_ci if ((cfg_dde[i].data_type == ACF_SEC_TYPE_MULTIPLE_BIN) && 83762306a36Sopenharmony_ci (aw_dev->chip_id == cfg_dde[i].chip_id) && 83862306a36Sopenharmony_ci (aw_dev->channel == cfg_dde[i].dev_index)) 83962306a36Sopenharmony_ci (*scene_num)++; 84062306a36Sopenharmony_ci } 84162306a36Sopenharmony_ci ret = 0; 84262306a36Sopenharmony_ci break; 84362306a36Sopenharmony_ci case AW88261_CHIP_ID: 84462306a36Sopenharmony_ci for (i = 0; i < cfg_hdr->ddt_num; ++i) { 84562306a36Sopenharmony_ci if (((cfg_dde[i].data_type == ACF_SEC_TYPE_REG) || 84662306a36Sopenharmony_ci (cfg_dde[i].data_type == ACF_SEC_TYPE_HDR_REG)) && 84762306a36Sopenharmony_ci (aw_dev->chip_id == cfg_dde[i].chip_id) && 84862306a36Sopenharmony_ci (aw_dev->channel == cfg_dde[i].dev_index)) 84962306a36Sopenharmony_ci (*scene_num)++; 85062306a36Sopenharmony_ci } 85162306a36Sopenharmony_ci ret = 0; 85262306a36Sopenharmony_ci break; 85362306a36Sopenharmony_ci default: 85462306a36Sopenharmony_ci dev_err(aw_dev->dev, "unsupported device"); 85562306a36Sopenharmony_ci ret = -EINVAL; 85662306a36Sopenharmony_ci break; 85762306a36Sopenharmony_ci } 85862306a36Sopenharmony_ci 85962306a36Sopenharmony_ci return ret; 86062306a36Sopenharmony_ci} 86162306a36Sopenharmony_ci 86262306a36Sopenharmony_cistatic int aw_dev_parse_scene_count_v1(struct aw_device *aw_dev, 86362306a36Sopenharmony_ci struct aw_container *aw_cfg, 86462306a36Sopenharmony_ci unsigned int *count) 86562306a36Sopenharmony_ci{ 86662306a36Sopenharmony_ci int ret; 86762306a36Sopenharmony_ci 86862306a36Sopenharmony_ci ret = aw_get_dde_type_info(aw_dev, aw_cfg); 86962306a36Sopenharmony_ci if (ret < 0) 87062306a36Sopenharmony_ci return ret; 87162306a36Sopenharmony_ci 87262306a36Sopenharmony_ci switch (aw_dev->prof_info.prof_type) { 87362306a36Sopenharmony_ci case AW88395_DEV_TYPE_ID: 87462306a36Sopenharmony_ci ret = aw_get_dev_scene_count_v1(aw_dev, aw_cfg, count); 87562306a36Sopenharmony_ci break; 87662306a36Sopenharmony_ci case AW88395_DEV_DEFAULT_TYPE_ID: 87762306a36Sopenharmony_ci ret = aw_get_default_scene_count_v1(aw_dev, aw_cfg, count); 87862306a36Sopenharmony_ci break; 87962306a36Sopenharmony_ci default: 88062306a36Sopenharmony_ci dev_err(aw_dev->dev, "unsupported prof_type[%x]", aw_dev->prof_info.prof_type); 88162306a36Sopenharmony_ci ret = -EINVAL; 88262306a36Sopenharmony_ci break; 88362306a36Sopenharmony_ci } 88462306a36Sopenharmony_ci 88562306a36Sopenharmony_ci return ret; 88662306a36Sopenharmony_ci} 88762306a36Sopenharmony_ci 88862306a36Sopenharmony_cistatic int aw_dev_parse_data_by_sec_type_v1(struct aw_device *aw_dev, 88962306a36Sopenharmony_ci struct aw_cfg_hdr *prof_hdr, 89062306a36Sopenharmony_ci struct aw_cfg_dde_v1 *cfg_dde, 89162306a36Sopenharmony_ci int *cur_scene_id) 89262306a36Sopenharmony_ci{ 89362306a36Sopenharmony_ci struct aw_prof_info *prof_info = &aw_dev->prof_info; 89462306a36Sopenharmony_ci int ret; 89562306a36Sopenharmony_ci 89662306a36Sopenharmony_ci switch (cfg_dde->data_type) { 89762306a36Sopenharmony_ci case ACF_SEC_TYPE_MULTIPLE_BIN: 89862306a36Sopenharmony_ci ret = aw_dev_prof_parse_multi_bin(aw_dev, (u8 *)prof_hdr + cfg_dde->data_offset, 89962306a36Sopenharmony_ci cfg_dde->data_size, &prof_info->prof_desc[*cur_scene_id]); 90062306a36Sopenharmony_ci if (ret < 0) { 90162306a36Sopenharmony_ci dev_err(aw_dev->dev, "parse multi bin failed"); 90262306a36Sopenharmony_ci return ret; 90362306a36Sopenharmony_ci } 90462306a36Sopenharmony_ci prof_info->prof_desc[*cur_scene_id].prf_str = cfg_dde->dev_profile_str; 90562306a36Sopenharmony_ci prof_info->prof_desc[*cur_scene_id].id = cfg_dde->dev_profile; 90662306a36Sopenharmony_ci (*cur_scene_id)++; 90762306a36Sopenharmony_ci break; 90862306a36Sopenharmony_ci case ACF_SEC_TYPE_HDR_REG: 90962306a36Sopenharmony_ci ret = aw_dev_parse_reg_bin_with_hdr(aw_dev, 91062306a36Sopenharmony_ci (uint8_t *)prof_hdr + cfg_dde->data_offset, 91162306a36Sopenharmony_ci cfg_dde->data_size, &prof_info->prof_desc[*cur_scene_id]); 91262306a36Sopenharmony_ci if (ret < 0) { 91362306a36Sopenharmony_ci dev_err(aw_dev->dev, "parse reg bin with hdr failed"); 91462306a36Sopenharmony_ci return ret; 91562306a36Sopenharmony_ci } 91662306a36Sopenharmony_ci prof_info->prof_desc[*cur_scene_id].prf_str = cfg_dde->dev_profile_str; 91762306a36Sopenharmony_ci prof_info->prof_desc[*cur_scene_id].id = cfg_dde->dev_profile; 91862306a36Sopenharmony_ci (*cur_scene_id)++; 91962306a36Sopenharmony_ci break; 92062306a36Sopenharmony_ci default: 92162306a36Sopenharmony_ci dev_err(aw_dev->dev, "unsupported SEC_TYPE [%d]", cfg_dde->data_type); 92262306a36Sopenharmony_ci return -EINVAL; 92362306a36Sopenharmony_ci } 92462306a36Sopenharmony_ci 92562306a36Sopenharmony_ci return 0; 92662306a36Sopenharmony_ci} 92762306a36Sopenharmony_ci 92862306a36Sopenharmony_cistatic int aw_dev_parse_dev_type_v1(struct aw_device *aw_dev, 92962306a36Sopenharmony_ci struct aw_cfg_hdr *prof_hdr) 93062306a36Sopenharmony_ci{ 93162306a36Sopenharmony_ci struct aw_cfg_dde_v1 *cfg_dde = 93262306a36Sopenharmony_ci (struct aw_cfg_dde_v1 *)((char *)prof_hdr + prof_hdr->hdr_offset); 93362306a36Sopenharmony_ci int cur_scene_id = 0; 93462306a36Sopenharmony_ci unsigned int i; 93562306a36Sopenharmony_ci int ret; 93662306a36Sopenharmony_ci 93762306a36Sopenharmony_ci for (i = 0; i < prof_hdr->ddt_num; i++) { 93862306a36Sopenharmony_ci if ((aw_dev->i2c->adapter->nr == cfg_dde[i].dev_bus) && 93962306a36Sopenharmony_ci (aw_dev->i2c->addr == cfg_dde[i].dev_addr) && 94062306a36Sopenharmony_ci (aw_dev->chip_id == cfg_dde[i].chip_id)) { 94162306a36Sopenharmony_ci ret = aw_dev_parse_data_by_sec_type_v1(aw_dev, prof_hdr, 94262306a36Sopenharmony_ci &cfg_dde[i], &cur_scene_id); 94362306a36Sopenharmony_ci if (ret < 0) { 94462306a36Sopenharmony_ci dev_err(aw_dev->dev, "parse failed"); 94562306a36Sopenharmony_ci return ret; 94662306a36Sopenharmony_ci } 94762306a36Sopenharmony_ci } 94862306a36Sopenharmony_ci } 94962306a36Sopenharmony_ci 95062306a36Sopenharmony_ci if (cur_scene_id == 0) { 95162306a36Sopenharmony_ci dev_err(aw_dev->dev, "get dev type failed, get num [%d]", cur_scene_id); 95262306a36Sopenharmony_ci return -EINVAL; 95362306a36Sopenharmony_ci } 95462306a36Sopenharmony_ci 95562306a36Sopenharmony_ci return 0; 95662306a36Sopenharmony_ci} 95762306a36Sopenharmony_ci 95862306a36Sopenharmony_cistatic int aw_dev_parse_default_type_v1(struct aw_device *aw_dev, 95962306a36Sopenharmony_ci struct aw_cfg_hdr *prof_hdr) 96062306a36Sopenharmony_ci{ 96162306a36Sopenharmony_ci struct aw_cfg_dde_v1 *cfg_dde = 96262306a36Sopenharmony_ci (struct aw_cfg_dde_v1 *)((char *)prof_hdr + prof_hdr->hdr_offset); 96362306a36Sopenharmony_ci int cur_scene_id = 0; 96462306a36Sopenharmony_ci unsigned int i; 96562306a36Sopenharmony_ci int ret; 96662306a36Sopenharmony_ci 96762306a36Sopenharmony_ci for (i = 0; i < prof_hdr->ddt_num; i++) { 96862306a36Sopenharmony_ci if ((aw_dev->channel == cfg_dde[i].dev_index) && 96962306a36Sopenharmony_ci (aw_dev->chip_id == cfg_dde[i].chip_id)) { 97062306a36Sopenharmony_ci ret = aw_dev_parse_data_by_sec_type_v1(aw_dev, prof_hdr, 97162306a36Sopenharmony_ci &cfg_dde[i], &cur_scene_id); 97262306a36Sopenharmony_ci if (ret < 0) { 97362306a36Sopenharmony_ci dev_err(aw_dev->dev, "parse failed"); 97462306a36Sopenharmony_ci return ret; 97562306a36Sopenharmony_ci } 97662306a36Sopenharmony_ci } 97762306a36Sopenharmony_ci } 97862306a36Sopenharmony_ci 97962306a36Sopenharmony_ci if (cur_scene_id == 0) { 98062306a36Sopenharmony_ci dev_err(aw_dev->dev, "get dev default type failed, get num[%d]", cur_scene_id); 98162306a36Sopenharmony_ci return -EINVAL; 98262306a36Sopenharmony_ci } 98362306a36Sopenharmony_ci 98462306a36Sopenharmony_ci return 0; 98562306a36Sopenharmony_ci} 98662306a36Sopenharmony_ci 98762306a36Sopenharmony_cistatic int aw_dev_parse_by_hdr_v1(struct aw_device *aw_dev, 98862306a36Sopenharmony_ci struct aw_cfg_hdr *cfg_hdr) 98962306a36Sopenharmony_ci{ 99062306a36Sopenharmony_ci int ret; 99162306a36Sopenharmony_ci 99262306a36Sopenharmony_ci switch (aw_dev->prof_info.prof_type) { 99362306a36Sopenharmony_ci case AW88395_DEV_TYPE_ID: 99462306a36Sopenharmony_ci ret = aw_dev_parse_dev_type_v1(aw_dev, cfg_hdr); 99562306a36Sopenharmony_ci break; 99662306a36Sopenharmony_ci case AW88395_DEV_DEFAULT_TYPE_ID: 99762306a36Sopenharmony_ci ret = aw_dev_parse_default_type_v1(aw_dev, cfg_hdr); 99862306a36Sopenharmony_ci break; 99962306a36Sopenharmony_ci default: 100062306a36Sopenharmony_ci dev_err(aw_dev->dev, "prof type matched failed, get num[%d]", 100162306a36Sopenharmony_ci aw_dev->prof_info.prof_type); 100262306a36Sopenharmony_ci ret = -EINVAL; 100362306a36Sopenharmony_ci break; 100462306a36Sopenharmony_ci } 100562306a36Sopenharmony_ci 100662306a36Sopenharmony_ci return ret; 100762306a36Sopenharmony_ci} 100862306a36Sopenharmony_ci 100962306a36Sopenharmony_cistatic int aw_dev_load_cfg_by_hdr_v1(struct aw_device *aw_dev, 101062306a36Sopenharmony_ci struct aw_container *aw_cfg) 101162306a36Sopenharmony_ci{ 101262306a36Sopenharmony_ci struct aw_cfg_hdr *cfg_hdr = (struct aw_cfg_hdr *)aw_cfg->data; 101362306a36Sopenharmony_ci struct aw_prof_info *prof_info = &aw_dev->prof_info; 101462306a36Sopenharmony_ci int ret; 101562306a36Sopenharmony_ci 101662306a36Sopenharmony_ci ret = aw_dev_parse_scene_count_v1(aw_dev, aw_cfg, &prof_info->count); 101762306a36Sopenharmony_ci if (ret < 0) { 101862306a36Sopenharmony_ci dev_err(aw_dev->dev, "get scene count failed"); 101962306a36Sopenharmony_ci return ret; 102062306a36Sopenharmony_ci } 102162306a36Sopenharmony_ci 102262306a36Sopenharmony_ci prof_info->prof_desc = devm_kcalloc(aw_dev->dev, 102362306a36Sopenharmony_ci prof_info->count, sizeof(struct aw_prof_desc), 102462306a36Sopenharmony_ci GFP_KERNEL); 102562306a36Sopenharmony_ci if (!prof_info->prof_desc) 102662306a36Sopenharmony_ci return -ENOMEM; 102762306a36Sopenharmony_ci 102862306a36Sopenharmony_ci ret = aw_dev_parse_by_hdr_v1(aw_dev, cfg_hdr); 102962306a36Sopenharmony_ci if (ret < 0) { 103062306a36Sopenharmony_ci dev_err(aw_dev->dev, "parse hdr failed"); 103162306a36Sopenharmony_ci return ret; 103262306a36Sopenharmony_ci } 103362306a36Sopenharmony_ci 103462306a36Sopenharmony_ci ret = aw_dev_create_prof_name_list_v1(aw_dev); 103562306a36Sopenharmony_ci if (ret < 0) { 103662306a36Sopenharmony_ci dev_err(aw_dev->dev, "create prof name list failed"); 103762306a36Sopenharmony_ci return ret; 103862306a36Sopenharmony_ci } 103962306a36Sopenharmony_ci 104062306a36Sopenharmony_ci return 0; 104162306a36Sopenharmony_ci} 104262306a36Sopenharmony_ci 104362306a36Sopenharmony_ciint aw88395_dev_cfg_load(struct aw_device *aw_dev, struct aw_container *aw_cfg) 104462306a36Sopenharmony_ci{ 104562306a36Sopenharmony_ci struct aw_cfg_hdr *cfg_hdr; 104662306a36Sopenharmony_ci int ret; 104762306a36Sopenharmony_ci 104862306a36Sopenharmony_ci cfg_hdr = (struct aw_cfg_hdr *)aw_cfg->data; 104962306a36Sopenharmony_ci 105062306a36Sopenharmony_ci switch (cfg_hdr->hdr_version) { 105162306a36Sopenharmony_ci case AW88395_CFG_HDR_VER: 105262306a36Sopenharmony_ci ret = aw_dev_load_cfg_by_hdr(aw_dev, cfg_hdr); 105362306a36Sopenharmony_ci if (ret < 0) { 105462306a36Sopenharmony_ci dev_err(aw_dev->dev, "hdr_version[0x%x] parse failed", 105562306a36Sopenharmony_ci cfg_hdr->hdr_version); 105662306a36Sopenharmony_ci return ret; 105762306a36Sopenharmony_ci } 105862306a36Sopenharmony_ci break; 105962306a36Sopenharmony_ci case AW88395_CFG_HDR_VER_V1: 106062306a36Sopenharmony_ci ret = aw_dev_load_cfg_by_hdr_v1(aw_dev, aw_cfg); 106162306a36Sopenharmony_ci if (ret < 0) { 106262306a36Sopenharmony_ci dev_err(aw_dev->dev, "hdr_version[0x%x] parse failed", 106362306a36Sopenharmony_ci cfg_hdr->hdr_version); 106462306a36Sopenharmony_ci return ret; 106562306a36Sopenharmony_ci } 106662306a36Sopenharmony_ci break; 106762306a36Sopenharmony_ci default: 106862306a36Sopenharmony_ci dev_err(aw_dev->dev, "unsupported hdr_version [0x%x]", cfg_hdr->hdr_version); 106962306a36Sopenharmony_ci return -EINVAL; 107062306a36Sopenharmony_ci } 107162306a36Sopenharmony_ci aw_dev->fw_status = AW88395_DEV_FW_OK; 107262306a36Sopenharmony_ci 107362306a36Sopenharmony_ci return 0; 107462306a36Sopenharmony_ci} 107562306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(aw88395_dev_cfg_load); 107662306a36Sopenharmony_ci 107762306a36Sopenharmony_cistatic int aw_dev_check_cfg_by_hdr(struct aw_device *aw_dev, struct aw_container *aw_cfg) 107862306a36Sopenharmony_ci{ 107962306a36Sopenharmony_ci unsigned int end_data_offset; 108062306a36Sopenharmony_ci struct aw_cfg_hdr *cfg_hdr; 108162306a36Sopenharmony_ci struct aw_cfg_dde *cfg_dde; 108262306a36Sopenharmony_ci unsigned int act_data = 0; 108362306a36Sopenharmony_ci unsigned int hdr_ddt_len; 108462306a36Sopenharmony_ci unsigned int i; 108562306a36Sopenharmony_ci u8 act_crc8; 108662306a36Sopenharmony_ci 108762306a36Sopenharmony_ci cfg_hdr = (struct aw_cfg_hdr *)aw_cfg->data; 108862306a36Sopenharmony_ci /* check file type id is awinic acf file */ 108962306a36Sopenharmony_ci if (cfg_hdr->id != ACF_FILE_ID) { 109062306a36Sopenharmony_ci dev_err(aw_dev->dev, "not acf type file"); 109162306a36Sopenharmony_ci return -EINVAL; 109262306a36Sopenharmony_ci } 109362306a36Sopenharmony_ci 109462306a36Sopenharmony_ci hdr_ddt_len = cfg_hdr->hdr_offset + cfg_hdr->ddt_size; 109562306a36Sopenharmony_ci if (hdr_ddt_len > aw_cfg->len) { 109662306a36Sopenharmony_ci dev_err(aw_dev->dev, "hdr_len with ddt_len [%d] overflow file size[%d]", 109762306a36Sopenharmony_ci cfg_hdr->hdr_offset, aw_cfg->len); 109862306a36Sopenharmony_ci return -EINVAL; 109962306a36Sopenharmony_ci } 110062306a36Sopenharmony_ci 110162306a36Sopenharmony_ci /* check data size */ 110262306a36Sopenharmony_ci cfg_dde = (struct aw_cfg_dde *)((char *)aw_cfg->data + cfg_hdr->hdr_offset); 110362306a36Sopenharmony_ci act_data += hdr_ddt_len; 110462306a36Sopenharmony_ci for (i = 0; i < cfg_hdr->ddt_num; i++) 110562306a36Sopenharmony_ci act_data += cfg_dde[i].data_size; 110662306a36Sopenharmony_ci 110762306a36Sopenharmony_ci if (act_data != aw_cfg->len) { 110862306a36Sopenharmony_ci dev_err(aw_dev->dev, "act_data[%d] not equal to file size[%d]!", 110962306a36Sopenharmony_ci act_data, aw_cfg->len); 111062306a36Sopenharmony_ci return -EINVAL; 111162306a36Sopenharmony_ci } 111262306a36Sopenharmony_ci 111362306a36Sopenharmony_ci for (i = 0; i < cfg_hdr->ddt_num; i++) { 111462306a36Sopenharmony_ci /* data check */ 111562306a36Sopenharmony_ci end_data_offset = cfg_dde[i].data_offset + cfg_dde[i].data_size; 111662306a36Sopenharmony_ci if (end_data_offset > aw_cfg->len) { 111762306a36Sopenharmony_ci dev_err(aw_dev->dev, "ddt_num[%d] end_data_offset[%d] overflow size[%d]", 111862306a36Sopenharmony_ci i, end_data_offset, aw_cfg->len); 111962306a36Sopenharmony_ci return -EINVAL; 112062306a36Sopenharmony_ci } 112162306a36Sopenharmony_ci 112262306a36Sopenharmony_ci /* crc check */ 112362306a36Sopenharmony_ci act_crc8 = crc8(aw_crc8_table, aw_cfg->data + cfg_dde[i].data_offset, 112462306a36Sopenharmony_ci cfg_dde[i].data_size, 0); 112562306a36Sopenharmony_ci if (act_crc8 != cfg_dde[i].data_crc) { 112662306a36Sopenharmony_ci dev_err(aw_dev->dev, "ddt_num[%d] act_crc8:0x%x != data_crc:0x%x", 112762306a36Sopenharmony_ci i, (u32)act_crc8, cfg_dde[i].data_crc); 112862306a36Sopenharmony_ci return -EINVAL; 112962306a36Sopenharmony_ci } 113062306a36Sopenharmony_ci } 113162306a36Sopenharmony_ci 113262306a36Sopenharmony_ci return 0; 113362306a36Sopenharmony_ci} 113462306a36Sopenharmony_ci 113562306a36Sopenharmony_cistatic int aw_dev_check_acf_by_hdr_v1(struct aw_device *aw_dev, struct aw_container *aw_cfg) 113662306a36Sopenharmony_ci{ 113762306a36Sopenharmony_ci struct aw_cfg_dde_v1 *cfg_dde; 113862306a36Sopenharmony_ci unsigned int end_data_offset; 113962306a36Sopenharmony_ci struct aw_cfg_hdr *cfg_hdr; 114062306a36Sopenharmony_ci unsigned int act_data = 0; 114162306a36Sopenharmony_ci unsigned int hdr_ddt_len; 114262306a36Sopenharmony_ci u8 act_crc8; 114362306a36Sopenharmony_ci int i; 114462306a36Sopenharmony_ci 114562306a36Sopenharmony_ci cfg_hdr = (struct aw_cfg_hdr *)aw_cfg->data; 114662306a36Sopenharmony_ci 114762306a36Sopenharmony_ci /* check file type id is awinic acf file */ 114862306a36Sopenharmony_ci if (cfg_hdr->id != ACF_FILE_ID) { 114962306a36Sopenharmony_ci dev_err(aw_dev->dev, "not acf type file"); 115062306a36Sopenharmony_ci return -EINVAL; 115162306a36Sopenharmony_ci } 115262306a36Sopenharmony_ci 115362306a36Sopenharmony_ci hdr_ddt_len = cfg_hdr->hdr_offset + cfg_hdr->ddt_size; 115462306a36Sopenharmony_ci if (hdr_ddt_len > aw_cfg->len) { 115562306a36Sopenharmony_ci dev_err(aw_dev->dev, "hdrlen with ddt_len [%d] overflow file size[%d]", 115662306a36Sopenharmony_ci cfg_hdr->hdr_offset, aw_cfg->len); 115762306a36Sopenharmony_ci return -EINVAL; 115862306a36Sopenharmony_ci } 115962306a36Sopenharmony_ci 116062306a36Sopenharmony_ci /* check data size */ 116162306a36Sopenharmony_ci cfg_dde = (struct aw_cfg_dde_v1 *)((char *)aw_cfg->data + cfg_hdr->hdr_offset); 116262306a36Sopenharmony_ci act_data += hdr_ddt_len; 116362306a36Sopenharmony_ci for (i = 0; i < cfg_hdr->ddt_num; i++) 116462306a36Sopenharmony_ci act_data += cfg_dde[i].data_size; 116562306a36Sopenharmony_ci 116662306a36Sopenharmony_ci if (act_data != aw_cfg->len) { 116762306a36Sopenharmony_ci dev_err(aw_dev->dev, "act_data[%d] not equal to file size[%d]!", 116862306a36Sopenharmony_ci act_data, aw_cfg->len); 116962306a36Sopenharmony_ci return -EINVAL; 117062306a36Sopenharmony_ci } 117162306a36Sopenharmony_ci 117262306a36Sopenharmony_ci for (i = 0; i < cfg_hdr->ddt_num; i++) { 117362306a36Sopenharmony_ci /* data check */ 117462306a36Sopenharmony_ci end_data_offset = cfg_dde[i].data_offset + cfg_dde[i].data_size; 117562306a36Sopenharmony_ci if (end_data_offset > aw_cfg->len) { 117662306a36Sopenharmony_ci dev_err(aw_dev->dev, "ddt_num[%d] end_data_offset[%d] overflow size[%d]", 117762306a36Sopenharmony_ci i, end_data_offset, aw_cfg->len); 117862306a36Sopenharmony_ci return -EINVAL; 117962306a36Sopenharmony_ci } 118062306a36Sopenharmony_ci 118162306a36Sopenharmony_ci /* crc check */ 118262306a36Sopenharmony_ci act_crc8 = crc8(aw_crc8_table, aw_cfg->data + cfg_dde[i].data_offset, 118362306a36Sopenharmony_ci cfg_dde[i].data_size, 0); 118462306a36Sopenharmony_ci if (act_crc8 != cfg_dde[i].data_crc) { 118562306a36Sopenharmony_ci dev_err(aw_dev->dev, "ddt_num[%d] act_crc8:0x%x != data_crc 0x%x", 118662306a36Sopenharmony_ci i, (u32)act_crc8, cfg_dde[i].data_crc); 118762306a36Sopenharmony_ci return -EINVAL; 118862306a36Sopenharmony_ci } 118962306a36Sopenharmony_ci } 119062306a36Sopenharmony_ci 119162306a36Sopenharmony_ci return 0; 119262306a36Sopenharmony_ci} 119362306a36Sopenharmony_ci 119462306a36Sopenharmony_ciint aw88395_dev_load_acf_check(struct aw_device *aw_dev, struct aw_container *aw_cfg) 119562306a36Sopenharmony_ci{ 119662306a36Sopenharmony_ci struct aw_cfg_hdr *cfg_hdr; 119762306a36Sopenharmony_ci 119862306a36Sopenharmony_ci if (!aw_cfg) { 119962306a36Sopenharmony_ci dev_err(aw_dev->dev, "aw_prof is NULL"); 120062306a36Sopenharmony_ci return -EINVAL; 120162306a36Sopenharmony_ci } 120262306a36Sopenharmony_ci 120362306a36Sopenharmony_ci if (aw_cfg->len < sizeof(struct aw_cfg_hdr)) { 120462306a36Sopenharmony_ci dev_err(aw_dev->dev, "cfg hdr size[%d] overflow file size[%d]", 120562306a36Sopenharmony_ci aw_cfg->len, (int)sizeof(struct aw_cfg_hdr)); 120662306a36Sopenharmony_ci return -EINVAL; 120762306a36Sopenharmony_ci } 120862306a36Sopenharmony_ci 120962306a36Sopenharmony_ci crc8_populate_lsb(aw_crc8_table, AW88395_CRC8_POLYNOMIAL); 121062306a36Sopenharmony_ci 121162306a36Sopenharmony_ci cfg_hdr = (struct aw_cfg_hdr *)aw_cfg->data; 121262306a36Sopenharmony_ci switch (cfg_hdr->hdr_version) { 121362306a36Sopenharmony_ci case AW88395_CFG_HDR_VER: 121462306a36Sopenharmony_ci return aw_dev_check_cfg_by_hdr(aw_dev, aw_cfg); 121562306a36Sopenharmony_ci case AW88395_CFG_HDR_VER_V1: 121662306a36Sopenharmony_ci return aw_dev_check_acf_by_hdr_v1(aw_dev, aw_cfg); 121762306a36Sopenharmony_ci default: 121862306a36Sopenharmony_ci dev_err(aw_dev->dev, "unsupported hdr_version [0x%x]", cfg_hdr->hdr_version); 121962306a36Sopenharmony_ci return -EINVAL; 122062306a36Sopenharmony_ci } 122162306a36Sopenharmony_ci 122262306a36Sopenharmony_ci return 0; 122362306a36Sopenharmony_ci} 122462306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(aw88395_dev_load_acf_check); 122562306a36Sopenharmony_ci 122662306a36Sopenharmony_ciMODULE_DESCRIPTION("AW88395 ACF File Parsing Lib"); 122762306a36Sopenharmony_ciMODULE_LICENSE("GPL v2"); 1228