brintos

brintos / linux-shallow public Read only

0
0
Text · 33.7 KiB · 769ca32 Raw
1175 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2//3// aw88395_lib.c  -- ACF bin parsing and check library file for aw883954//5// Copyright (c) 2022-2023 AWINIC Technology CO., LTD6//7// Author: Bruce zhao <zhaolei@awinic.com>8//9 10#include <linux/cleanup.h>11#include <linux/crc8.h>12#include <linux/i2c.h>13#include "aw88395_lib.h"14#include "aw88395_device.h"15 16#define AW88395_CRC8_POLYNOMIAL 0x8C17DECLARE_CRC8_TABLE(aw_crc8_table);18 19static char *profile_name[AW88395_PROFILE_MAX] = {20	"Music", "Voice", "Voip", "Ringtone",21	"Ringtone_hs", "Lowpower", "Bypass",22	"Mmi", "Fm", "Notification", "Receiver"23};24 25static int aw_parse_bin_header(struct aw_device *aw_dev, struct aw_bin *bin);26 27static int aw_check_sum(struct aw_device *aw_dev, struct aw_bin *bin, int bin_num)28{29	unsigned char *p_check_sum;30	unsigned int sum_data = 0;31	unsigned int check_sum;32	unsigned int i, len;33 34	p_check_sum = &(bin->info.data[(bin->header_info[bin_num].valid_data_addr -35						bin->header_info[bin_num].header_len)]);36	len = bin->header_info[bin_num].bin_data_len + bin->header_info[bin_num].header_len;37	check_sum = le32_to_cpup((void *)p_check_sum);38 39	for (i = 4; i < len; i++)40		sum_data += *(p_check_sum + i);41 42	dev_dbg(aw_dev->dev, "%s -- check_sum = %p, check_sum = 0x%x, sum_data = 0x%x",43					__func__, p_check_sum, check_sum, sum_data);44	if (sum_data != check_sum) {45		dev_err(aw_dev->dev, "%s. CheckSum Fail.bin_num=%d, CheckSum:0x%x, SumData:0x%x",46				__func__, bin_num, check_sum, sum_data);47		return -EINVAL;48	}49 50	return 0;51}52 53static int aw_check_data_version(struct aw_device *aw_dev, struct aw_bin *bin, int bin_num)54{55	if (bin->header_info[bin_num].bin_data_ver < DATA_VERSION_V1 ||56		bin->header_info[bin_num].bin_data_ver > DATA_VERSION_MAX) {57		dev_err(aw_dev->dev, "aw_bin_parse Unrecognized this bin data version\n");58		return -EINVAL;59	}60 61	return 0;62}63 64static int aw_check_register_num(struct aw_device *aw_dev, struct aw_bin *bin, int bin_num)65{66	struct bin_header_info temp_info = bin->header_info[bin_num];67	unsigned int check_register_num, parse_register_num;68	unsigned char *p_check_sum;69 70	p_check_sum = &(bin->info.data[(temp_info.valid_data_addr)]);71 72	parse_register_num = le32_to_cpup((void *)p_check_sum);73	check_register_num = (bin->header_info[bin_num].bin_data_len - CHECK_REGISTER_NUM_OFFSET) /74				(bin->header_info[bin_num].reg_byte_len +75				bin->header_info[bin_num].data_byte_len);76	dev_dbg(aw_dev->dev, "%s,parse_register_num = 0x%x,check_register_num = 0x%x\n",77				__func__, parse_register_num, check_register_num);78	if (parse_register_num != check_register_num) {79		dev_err(aw_dev->dev, "%s parse_register_num = 0x%x,check_register_num = 0x%x\n",80				__func__, parse_register_num, check_register_num);81		return -EINVAL;82	}83 84	bin->header_info[bin_num].reg_num = parse_register_num;85	bin->header_info[bin_num].valid_data_len = temp_info.bin_data_len - VALID_DATA_LEN;86	bin->header_info[bin_num].valid_data_addr = temp_info.valid_data_addr + VALID_DATA_ADDR;87 88	return 0;89}90 91static int aw_check_dsp_reg_num(struct aw_device *aw_dev, struct aw_bin *bin, int bin_num)92{93	struct bin_header_info temp_info = bin->header_info[bin_num];94	unsigned int check_dsp_reg_num, parse_dsp_reg_num;95	unsigned char *p_check_sum;96 97	p_check_sum = &(bin->info.data[(temp_info.valid_data_addr)]);98 99	parse_dsp_reg_num = le32_to_cpup((void *)(p_check_sum + PARSE_DSP_REG_NUM));100	bin->header_info[bin_num].reg_data_byte_len =101			le32_to_cpup((void *)(p_check_sum + REG_DATA_BYTP_LEN));102	check_dsp_reg_num = (bin->header_info[bin_num].bin_data_len - CHECK_DSP_REG_NUM) /103				bin->header_info[bin_num].reg_data_byte_len;104	dev_dbg(aw_dev->dev, "%s bin_num = %d, parse_dsp_reg_num = 0x%x, check_dsp_reg_num = 0x%x",105					__func__, bin_num, check_dsp_reg_num, check_dsp_reg_num);106	if (parse_dsp_reg_num != check_dsp_reg_num) {107		dev_err(aw_dev->dev, "aw_bin_parse check dsp reg num error\n");108		dev_err(aw_dev->dev, "%s parse_dsp_reg_num = 0x%x, check_dsp_reg_num = 0x%x",109					__func__, check_dsp_reg_num, check_dsp_reg_num);110		return -EINVAL;111	}112 113	bin->header_info[bin_num].download_addr = le32_to_cpup((void *)p_check_sum);114	bin->header_info[bin_num].reg_num = parse_dsp_reg_num;115	bin->header_info[bin_num].valid_data_len = temp_info.bin_data_len - DSP_VALID_DATA_LEN;116	bin->header_info[bin_num].valid_data_addr = temp_info.valid_data_addr +117								DSP_VALID_DATA_ADDR;118 119	return 0;120}121 122static int aw_check_soc_app_num(struct aw_device *aw_dev, struct aw_bin *bin, int bin_num)123{124	struct bin_header_info temp_info = bin->header_info[bin_num];125	unsigned int check_soc_app_num, parse_soc_app_num;126	unsigned char *p_check_sum;127 128	p_check_sum = &(bin->info.data[(temp_info.valid_data_addr)]);129 130	bin->header_info[bin_num].app_version = le32_to_cpup((void *)p_check_sum);131	parse_soc_app_num = le32_to_cpup((void *)(p_check_sum + PARSE_SOC_APP_NUM));132	check_soc_app_num = bin->header_info[bin_num].bin_data_len - CHECK_SOC_APP_NUM;133	dev_dbg(aw_dev->dev, "%s bin_num = %d, parse_soc_app_num=0x%x, check_soc_app_num = 0x%x\n",134					__func__, bin_num, parse_soc_app_num, check_soc_app_num);135	if (parse_soc_app_num != check_soc_app_num) {136		dev_err(aw_dev->dev, "%s parse_soc_app_num=0x%x, check_soc_app_num = 0x%x\n",137					__func__, parse_soc_app_num, check_soc_app_num);138		return -EINVAL;139	}140 141	bin->header_info[bin_num].reg_num = parse_soc_app_num;142	bin->header_info[bin_num].download_addr = le32_to_cpup((void *)(p_check_sum +143								APP_DOWNLOAD_ADDR));144	bin->header_info[bin_num].valid_data_len = temp_info.bin_data_len - APP_VALID_DATA_LEN;145	bin->header_info[bin_num].valid_data_addr = temp_info.valid_data_addr +146								APP_VALID_DATA_ADDR;147 148	return 0;149}150 151static void aw_get_single_bin_header(struct aw_bin *bin)152{153	memcpy((void *)&bin->header_info[bin->all_bin_parse_num], bin->p_addr, DATA_LEN);154 155	bin->header_info[bin->all_bin_parse_num].header_len = HEADER_LEN;156	bin->all_bin_parse_num += 1;157}158 159static int aw_parse_one_of_multi_bins(struct aw_device *aw_dev, unsigned int bin_num,160					int bin_serial_num, struct aw_bin *bin)161{162	struct bin_header_info aw_bin_header_info;163	unsigned int bin_start_addr;164	unsigned int valid_data_len;165 166	if (bin->info.len < sizeof(struct bin_header_info)) {167		dev_err(aw_dev->dev, "bin_header_info size[%d] overflow file size[%d]\n",168				(int)sizeof(struct bin_header_info), bin->info.len);169		return -EINVAL;170	}171 172	aw_bin_header_info = bin->header_info[bin->all_bin_parse_num - 1];173	if (!bin_serial_num) {174		bin_start_addr = le32_to_cpup((void *)(bin->p_addr + START_ADDR_OFFSET));175		bin->p_addr += (HEADER_LEN + bin_start_addr);176		bin->header_info[bin->all_bin_parse_num].valid_data_addr =177			aw_bin_header_info.valid_data_addr + VALID_DATA_ADDR + 8 * bin_num +178			VALID_DATA_ADDR_OFFSET;179	} else {180		valid_data_len = aw_bin_header_info.bin_data_len;181		bin->p_addr += (HDADER_LEN + valid_data_len);182		bin->header_info[bin->all_bin_parse_num].valid_data_addr =183		    aw_bin_header_info.valid_data_addr + aw_bin_header_info.bin_data_len +184		    VALID_DATA_ADDR_OFFSET;185	}186 187	return aw_parse_bin_header(aw_dev, bin);188}189 190static int aw_get_multi_bin_header(struct aw_device *aw_dev, struct aw_bin *bin)191{192	unsigned int bin_num, i;193	int ret;194 195	bin_num = le32_to_cpup((void *)(bin->p_addr + VALID_DATA_ADDR_OFFSET));196	if (bin->multi_bin_parse_num == 1)197		bin->header_info[bin->all_bin_parse_num].valid_data_addr =198							VALID_DATA_ADDR_OFFSET;199 200	aw_get_single_bin_header(bin);201 202	for (i = 0; i < bin_num; i++) {203		dev_dbg(aw_dev->dev, "aw_bin_parse enter multi bin for is %d\n", i);204		ret = aw_parse_one_of_multi_bins(aw_dev, bin_num, i, bin);205		if (ret < 0)206			return ret;207	}208 209	return 0;210}211 212static int aw_parse_bin_header(struct aw_device *aw_dev, struct aw_bin *bin)213{214	unsigned int bin_data_type;215 216	if (bin->info.len < sizeof(struct bin_header_info)) {217		dev_err(aw_dev->dev, "bin_header_info size[%d] overflow file size[%d]\n",218				(int)sizeof(struct bin_header_info), bin->info.len);219		return -EINVAL;220	}221 222	bin_data_type = le32_to_cpup((void *)(bin->p_addr + BIN_DATA_TYPE_OFFSET));223	dev_dbg(aw_dev->dev, "aw_bin_parse bin_data_type 0x%x\n", bin_data_type);224	switch (bin_data_type) {225	case DATA_TYPE_REGISTER:226	case DATA_TYPE_DSP_REG:227	case DATA_TYPE_SOC_APP:228		bin->single_bin_parse_num += 1;229		dev_dbg(aw_dev->dev, "%s bin->single_bin_parse_num is %d\n", __func__,230						bin->single_bin_parse_num);231		if (!bin->multi_bin_parse_num)232			bin->header_info[bin->all_bin_parse_num].valid_data_addr =233								VALID_DATA_ADDR_OFFSET;234		aw_get_single_bin_header(bin);235		return 0;236	case DATA_TYPE_MULTI_BINS:237		bin->multi_bin_parse_num += 1;238		dev_dbg(aw_dev->dev, "%s bin->multi_bin_parse_num is %d\n", __func__,239						bin->multi_bin_parse_num);240		return aw_get_multi_bin_header(aw_dev, bin);241	default:242		dev_dbg(aw_dev->dev, "%s There is no corresponding type\n", __func__);243		return 0;244	}245}246 247static int aw_check_bin_header_version(struct aw_device *aw_dev, struct aw_bin *bin)248{249	unsigned int header_version;250 251	header_version = le32_to_cpup((void *)(bin->p_addr + HEADER_VERSION_OFFSET));252	dev_dbg(aw_dev->dev, "aw_bin_parse header_version 0x%x\n", header_version);253 254	switch (header_version) {255	case HEADER_VERSION_V1:256		return aw_parse_bin_header(aw_dev, bin);257	default:258		dev_err(aw_dev->dev, "aw_bin_parse Unrecognized this bin header version\n");259		return -EINVAL;260	}261}262 263static int aw_parsing_bin_file(struct aw_device *aw_dev, struct aw_bin *bin)264{265	int ret = -EINVAL;266	int i;267 268	if (!bin) {269		dev_err(aw_dev->dev, "aw_bin_parse bin is NULL\n");270		return ret;271	}272	bin->p_addr = bin->info.data;273	bin->all_bin_parse_num = 0;274	bin->multi_bin_parse_num = 0;275	bin->single_bin_parse_num = 0;276 277	ret = aw_check_bin_header_version(aw_dev, bin);278	if (ret < 0) {279		dev_err(aw_dev->dev, "aw_bin_parse check bin header version error\n");280		return ret;281	}282 283	for (i = 0; i < bin->all_bin_parse_num; i++) {284		ret = aw_check_sum(aw_dev, bin, i);285		if (ret < 0) {286			dev_err(aw_dev->dev, "aw_bin_parse check sum data error\n");287			return ret;288		}289		ret = aw_check_data_version(aw_dev, bin, i);290		if (ret < 0) {291			dev_err(aw_dev->dev, "aw_bin_parse check data version error\n");292			return ret;293		}294		if (bin->header_info[i].bin_data_ver == DATA_VERSION_V1) {295			switch (bin->header_info[i].bin_data_type) {296			case DATA_TYPE_REGISTER:297				ret = aw_check_register_num(aw_dev, bin, i);298				break;299			case DATA_TYPE_DSP_REG:300				ret = aw_check_dsp_reg_num(aw_dev, bin, i);301				break;302			case DATA_TYPE_SOC_APP:303				ret = aw_check_soc_app_num(aw_dev, bin, i);304				break;305			default:306				bin->header_info[i].valid_data_len =307						bin->header_info[i].bin_data_len;308				ret = 0;309				break;310			}311			if (ret < 0)312				return ret;313		}314	}315 316	return 0;317}318 319static int aw_dev_parse_raw_reg(unsigned char *data, unsigned int data_len,320		struct aw_prof_desc *prof_desc)321{322	prof_desc->sec_desc[AW88395_DATA_TYPE_REG].data = data;323	prof_desc->sec_desc[AW88395_DATA_TYPE_REG].len = data_len;324 325	prof_desc->prof_st = AW88395_PROFILE_OK;326 327	return 0;328}329 330static int aw_dev_parse_raw_dsp_cfg(unsigned char *data, unsigned int data_len,331		struct aw_prof_desc *prof_desc)332{333	if (data_len & 0x01)334		return -EINVAL;335 336	swab16_array((u16 *)data, data_len >> 1);337 338	prof_desc->sec_desc[AW88395_DATA_TYPE_DSP_CFG].data = data;339	prof_desc->sec_desc[AW88395_DATA_TYPE_DSP_CFG].len = data_len;340 341	prof_desc->prof_st = AW88395_PROFILE_OK;342 343	return 0;344}345 346static int aw_dev_parse_raw_dsp_fw(unsigned char *data,	unsigned int data_len,347		struct aw_prof_desc *prof_desc)348{349	if (data_len & 0x01)350		return -EINVAL;351 352	swab16_array((u16 *)data, data_len >> 1);353 354	prof_desc->sec_desc[AW88395_DATA_TYPE_DSP_FW].data = data;355	prof_desc->sec_desc[AW88395_DATA_TYPE_DSP_FW].len = data_len;356 357	prof_desc->prof_st = AW88395_PROFILE_OK;358 359	return 0;360}361 362static int aw_dev_prof_parse_multi_bin(struct aw_device *aw_dev, unsigned char *data,363				unsigned int data_len, struct aw_prof_desc *prof_desc)364{365	int ret;366	int i;367 368	struct aw_bin *aw_bin __free(kfree) = kzalloc(data_len + sizeof(struct aw_bin),369						     GFP_KERNEL);370	if (!aw_bin)371		return -ENOMEM;372 373	aw_bin->info.len = data_len;374	memcpy(aw_bin->info.data, data, data_len);375 376	ret = aw_parsing_bin_file(aw_dev, aw_bin);377	if (ret < 0) {378		dev_err(aw_dev->dev, "parse bin failed");379		return ret;380	}381 382	for (i = 0; i < aw_bin->all_bin_parse_num; i++) {383		switch (aw_bin->header_info[i].bin_data_type) {384		case DATA_TYPE_REGISTER:385			prof_desc->sec_desc[AW88395_DATA_TYPE_REG].len =386					aw_bin->header_info[i].valid_data_len;387			prof_desc->sec_desc[AW88395_DATA_TYPE_REG].data =388					data + aw_bin->header_info[i].valid_data_addr;389			break;390		case DATA_TYPE_DSP_REG:391			if (aw_bin->header_info[i].valid_data_len & 0x01)392				return -EINVAL;393 394			swab16_array((u16 *)(data + aw_bin->header_info[i].valid_data_addr),395					aw_bin->header_info[i].valid_data_len >> 1);396 397			prof_desc->sec_desc[AW88395_DATA_TYPE_DSP_CFG].len =398					aw_bin->header_info[i].valid_data_len;399			prof_desc->sec_desc[AW88395_DATA_TYPE_DSP_CFG].data =400					data + aw_bin->header_info[i].valid_data_addr;401			break;402		case DATA_TYPE_DSP_FW:403		case DATA_TYPE_SOC_APP:404			if (aw_bin->header_info[i].valid_data_len & 0x01)405				return -EINVAL;406 407			swab16_array((u16 *)(data + aw_bin->header_info[i].valid_data_addr),408					aw_bin->header_info[i].valid_data_len >> 1);409 410			prof_desc->fw_ver = aw_bin->header_info[i].app_version;411			prof_desc->sec_desc[AW88395_DATA_TYPE_DSP_FW].len =412					aw_bin->header_info[i].valid_data_len;413			prof_desc->sec_desc[AW88395_DATA_TYPE_DSP_FW].data =414					data + aw_bin->header_info[i].valid_data_addr;415			break;416		default:417			dev_dbg(aw_dev->dev, "bin_data_type not found");418			break;419		}420	}421	prof_desc->prof_st = AW88395_PROFILE_OK;422 423	return 0;424}425 426static int aw_dev_parse_reg_bin_with_hdr(struct aw_device *aw_dev,427			uint8_t *data, uint32_t data_len, struct aw_prof_desc *prof_desc)428{429	int ret;430 431	struct aw_bin *aw_bin __free(kfree) = kzalloc(data_len + sizeof(*aw_bin),432						      GFP_KERNEL);433	if (!aw_bin)434		return -ENOMEM;435 436	aw_bin->info.len = data_len;437	memcpy(aw_bin->info.data, data, data_len);438 439	ret = aw_parsing_bin_file(aw_dev, aw_bin);440	if (ret < 0) {441		dev_err(aw_dev->dev, "parse bin failed");442		return ret;443	}444 445	if ((aw_bin->all_bin_parse_num != 1) ||446		(aw_bin->header_info[0].bin_data_type != DATA_TYPE_REGISTER)) {447		dev_err(aw_dev->dev, "bin num or type error");448		return -EINVAL;449	}450 451	prof_desc->sec_desc[AW88395_DATA_TYPE_REG].data =452				data + aw_bin->header_info[0].valid_data_addr;453	prof_desc->sec_desc[AW88395_DATA_TYPE_REG].len =454				aw_bin->header_info[0].valid_data_len;455	prof_desc->prof_st = AW88395_PROFILE_OK;456 457	return 0;458}459 460static int aw_dev_parse_data_by_sec_type(struct aw_device *aw_dev, struct aw_cfg_hdr *cfg_hdr,461			struct aw_cfg_dde *cfg_dde, struct aw_prof_desc *scene_prof_desc)462{463	switch (cfg_dde->data_type) {464	case ACF_SEC_TYPE_REG:465		return aw_dev_parse_raw_reg((u8 *)cfg_hdr + cfg_dde->data_offset,466				cfg_dde->data_size, scene_prof_desc);467	case ACF_SEC_TYPE_DSP_CFG:468		return aw_dev_parse_raw_dsp_cfg((u8 *)cfg_hdr + cfg_dde->data_offset,469				cfg_dde->data_size, scene_prof_desc);470	case ACF_SEC_TYPE_DSP_FW:471		return aw_dev_parse_raw_dsp_fw(472				(u8 *)cfg_hdr + cfg_dde->data_offset,473				cfg_dde->data_size, scene_prof_desc);474	case ACF_SEC_TYPE_MULTIPLE_BIN:475		return aw_dev_prof_parse_multi_bin(476				aw_dev, (u8 *)cfg_hdr + cfg_dde->data_offset,477				cfg_dde->data_size, scene_prof_desc);478	case ACF_SEC_TYPE_HDR_REG:479		return aw_dev_parse_reg_bin_with_hdr(aw_dev, (u8 *)cfg_hdr + cfg_dde->data_offset,480				cfg_dde->data_size, scene_prof_desc);481	default:482		dev_err(aw_dev->dev, "%s cfg_dde->data_type = %d\n", __func__, cfg_dde->data_type);483		break;484	}485 486	return 0;487}488 489static int aw_dev_parse_dev_type(struct aw_device *aw_dev,490		struct aw_cfg_hdr *prof_hdr, struct aw_all_prof_info *all_prof_info)491{492	struct aw_cfg_dde *cfg_dde =493		(struct aw_cfg_dde *)((char *)prof_hdr + prof_hdr->hdr_offset);494	int sec_num = 0;495	int ret, i;496 497	for (i = 0; i < prof_hdr->ddt_num; i++) {498		if ((aw_dev->i2c->adapter->nr == cfg_dde[i].dev_bus) &&499		    (aw_dev->i2c->addr == cfg_dde[i].dev_addr) &&500		    (cfg_dde[i].type == AW88395_DEV_TYPE_ID) &&501		    (cfg_dde[i].data_type != ACF_SEC_TYPE_MONITOR)) {502			if (cfg_dde[i].dev_profile >= AW88395_PROFILE_MAX) {503				dev_err(aw_dev->dev, "dev_profile [%d] overflow",504							cfg_dde[i].dev_profile);505				return -EINVAL;506			}507			aw_dev->prof_data_type = cfg_dde[i].data_type;508			ret = aw_dev_parse_data_by_sec_type(aw_dev, prof_hdr, &cfg_dde[i],509					&all_prof_info->prof_desc[cfg_dde[i].dev_profile]);510			if (ret < 0) {511				dev_err(aw_dev->dev, "parse failed");512				return ret;513			}514			sec_num++;515		}516	}517 518	if (sec_num == 0) {519		dev_dbg(aw_dev->dev, "get dev type num is %d, please use default", sec_num);520		return AW88395_DEV_TYPE_NONE;521	}522 523	return AW88395_DEV_TYPE_OK;524}525 526static int aw_dev_parse_dev_default_type(struct aw_device *aw_dev,527		struct aw_cfg_hdr *prof_hdr, struct aw_all_prof_info *all_prof_info)528{529	struct aw_cfg_dde *cfg_dde =530		(struct aw_cfg_dde *)((char *)prof_hdr + prof_hdr->hdr_offset);531	int sec_num = 0;532	int ret, i;533 534	for (i = 0; i < prof_hdr->ddt_num; i++) {535		if ((aw_dev->channel == cfg_dde[i].dev_index) &&536		    (cfg_dde[i].type == AW88395_DEV_DEFAULT_TYPE_ID) &&537		    (cfg_dde[i].data_type != ACF_SEC_TYPE_MONITOR)) {538			if (cfg_dde[i].dev_profile >= AW88395_PROFILE_MAX) {539				dev_err(aw_dev->dev, "dev_profile [%d] overflow",540					cfg_dde[i].dev_profile);541				return -EINVAL;542			}543			aw_dev->prof_data_type = cfg_dde[i].data_type;544			ret = aw_dev_parse_data_by_sec_type(aw_dev, prof_hdr, &cfg_dde[i],545					&all_prof_info->prof_desc[cfg_dde[i].dev_profile]);546			if (ret < 0) {547				dev_err(aw_dev->dev, "parse failed");548				return ret;549			}550			sec_num++;551		}552	}553 554	if (sec_num == 0) {555		dev_err(aw_dev->dev, "get dev default type failed, get num[%d]", sec_num);556		return -EINVAL;557	}558 559	return 0;560}561 562static int aw_dev_cfg_get_reg_valid_prof(struct aw_device *aw_dev,563				struct aw_all_prof_info *all_prof_info)564{565	struct aw_prof_desc *prof_desc = all_prof_info->prof_desc;566	struct aw_prof_info *prof_info = &aw_dev->prof_info;567	int num = 0;568	int i;569 570	for (i = 0; i < AW88395_PROFILE_MAX; i++) {571		if (prof_desc[i].prof_st == AW88395_PROFILE_OK)572			prof_info->count++;573	}574 575	dev_dbg(aw_dev->dev, "get valid profile:%d", aw_dev->prof_info.count);576 577	if (!prof_info->count) {578		dev_err(aw_dev->dev, "no profile data");579		return -EPERM;580	}581 582	prof_info->prof_desc = devm_kcalloc(aw_dev->dev,583					prof_info->count, sizeof(struct aw_prof_desc),584					GFP_KERNEL);585	if (!prof_info->prof_desc)586		return -ENOMEM;587 588	for (i = 0; i < AW88395_PROFILE_MAX; i++) {589		if (prof_desc[i].prof_st == AW88395_PROFILE_OK) {590			if (num >= prof_info->count) {591				dev_err(aw_dev->dev, "overflow count[%d]",592						prof_info->count);593				return -EINVAL;594			}595			prof_info->prof_desc[num] = prof_desc[i];596			prof_info->prof_desc[num].id = i;597			num++;598		}599	}600 601	return 0;602}603 604static int aw_dev_cfg_get_multiple_valid_prof(struct aw_device *aw_dev,605				struct aw_all_prof_info *all_prof_info)606{607	struct aw_prof_desc *prof_desc = all_prof_info->prof_desc;608	struct aw_prof_info *prof_info = &aw_dev->prof_info;609	struct aw_sec_data_desc *sec_desc;610	int num = 0;611	int i;612 613	for (i = 0; i < AW88395_PROFILE_MAX; i++) {614		if (prof_desc[i].prof_st == AW88395_PROFILE_OK) {615			sec_desc = prof_desc[i].sec_desc;616			if ((sec_desc[AW88395_DATA_TYPE_REG].data != NULL) &&617			    (sec_desc[AW88395_DATA_TYPE_REG].len != 0) &&618			    (sec_desc[AW88395_DATA_TYPE_DSP_CFG].data != NULL) &&619			    (sec_desc[AW88395_DATA_TYPE_DSP_CFG].len != 0) &&620			    (sec_desc[AW88395_DATA_TYPE_DSP_FW].data != NULL) &&621			    (sec_desc[AW88395_DATA_TYPE_DSP_FW].len != 0))622				prof_info->count++;623		}624	}625 626	dev_dbg(aw_dev->dev, "get valid profile:%d", aw_dev->prof_info.count);627 628	if (!prof_info->count) {629		dev_err(aw_dev->dev, "no profile data");630		return -EPERM;631	}632 633	prof_info->prof_desc = devm_kcalloc(aw_dev->dev,634					prof_info->count, sizeof(struct aw_prof_desc),635					GFP_KERNEL);636	if (!prof_info->prof_desc)637		return -ENOMEM;638 639	for (i = 0; i < AW88395_PROFILE_MAX; i++) {640		if (prof_desc[i].prof_st == AW88395_PROFILE_OK) {641			sec_desc = prof_desc[i].sec_desc;642			if ((sec_desc[AW88395_DATA_TYPE_REG].data != NULL) &&643			    (sec_desc[AW88395_DATA_TYPE_REG].len != 0) &&644			    (sec_desc[AW88395_DATA_TYPE_DSP_CFG].data != NULL) &&645			    (sec_desc[AW88395_DATA_TYPE_DSP_CFG].len != 0) &&646			    (sec_desc[AW88395_DATA_TYPE_DSP_FW].data != NULL) &&647			    (sec_desc[AW88395_DATA_TYPE_DSP_FW].len != 0)) {648				if (num >= prof_info->count) {649					dev_err(aw_dev->dev, "overflow count[%d]",650							prof_info->count);651					return -EINVAL;652				}653				prof_info->prof_desc[num] = prof_desc[i];654				prof_info->prof_desc[num].id = i;655				num++;656			}657		}658	}659 660	return 0;661}662 663static int aw_dev_load_cfg_by_hdr(struct aw_device *aw_dev,664		struct aw_cfg_hdr *prof_hdr)665{666	int ret;667 668	struct aw_all_prof_info *all_prof_info __free(kfree) = kzalloc(sizeof(*all_prof_info),669								       GFP_KERNEL);670	if (!all_prof_info)671		return -ENOMEM;672 673	ret = aw_dev_parse_dev_type(aw_dev, prof_hdr, all_prof_info);674	if (ret < 0) {675		return ret;676	} else if (ret == AW88395_DEV_TYPE_NONE) {677		dev_dbg(aw_dev->dev, "get dev type num is 0, parse default dev");678		ret = aw_dev_parse_dev_default_type(aw_dev, prof_hdr, all_prof_info);679		if (ret < 0)680			return ret;681	}682 683	switch (aw_dev->prof_data_type) {684	case ACF_SEC_TYPE_MULTIPLE_BIN:685		ret = aw_dev_cfg_get_multiple_valid_prof(aw_dev, all_prof_info);686		break;687	case ACF_SEC_TYPE_HDR_REG:688		ret = aw_dev_cfg_get_reg_valid_prof(aw_dev, all_prof_info);689		break;690	default:691		dev_err(aw_dev->dev, "unsupport data type\n");692		ret = -EINVAL;693		break;694	}695	if (!ret)696		aw_dev->prof_info.prof_name_list = profile_name;697 698	return ret;699}700 701static int aw_dev_create_prof_name_list_v1(struct aw_device *aw_dev)702{703	struct aw_prof_info *prof_info = &aw_dev->prof_info;704	struct aw_prof_desc *prof_desc = prof_info->prof_desc;705	int i;706 707	if (!prof_desc) {708		dev_err(aw_dev->dev, "prof_desc is NULL");709		return -EINVAL;710	}711 712	prof_info->prof_name_list = devm_kzalloc(aw_dev->dev,713					prof_info->count * PROFILE_STR_MAX,714					GFP_KERNEL);715	if (!prof_info->prof_name_list)716		return -ENOMEM;717 718	for (i = 0; i < prof_info->count; i++) {719		prof_desc[i].id = i;720		prof_info->prof_name_list[i] = prof_desc[i].prf_str;721		dev_dbg(aw_dev->dev, "prof name is %s", prof_info->prof_name_list[i]);722	}723 724	return 0;725}726 727static int aw_get_dde_type_info(struct aw_device *aw_dev, struct aw_container *aw_cfg)728{729	struct aw_cfg_hdr *cfg_hdr = (struct aw_cfg_hdr *)aw_cfg->data;730	struct aw_cfg_dde_v1 *cfg_dde =731		(struct aw_cfg_dde_v1 *)(aw_cfg->data + cfg_hdr->hdr_offset);732	int default_num = 0;733	int dev_num = 0;734	unsigned int i;735 736	for (i = 0; i < cfg_hdr->ddt_num; i++) {737		if (cfg_dde[i].type == AW88395_DEV_TYPE_ID)738			dev_num++;739 740		if (cfg_dde[i].type == AW88395_DEV_DEFAULT_TYPE_ID)741			default_num++;742	}743 744	if (dev_num != 0) {745		aw_dev->prof_info.prof_type = AW88395_DEV_TYPE_ID;746	} else if (default_num != 0) {747		aw_dev->prof_info.prof_type = AW88395_DEV_DEFAULT_TYPE_ID;748	} else {749		dev_err(aw_dev->dev, "can't find scene");750		return -EINVAL;751	}752 753	return 0;754}755 756static int aw_get_dev_scene_count_v1(struct aw_device *aw_dev, struct aw_container *aw_cfg,757						unsigned int *scene_num)758{759	struct aw_cfg_hdr *cfg_hdr = (struct aw_cfg_hdr *)aw_cfg->data;760	struct aw_cfg_dde_v1 *cfg_dde =761		(struct aw_cfg_dde_v1 *)(aw_cfg->data + cfg_hdr->hdr_offset);762	unsigned int i;763 764	for (i = 0; i < cfg_hdr->ddt_num; ++i) {765		if (((cfg_dde[i].data_type == ACF_SEC_TYPE_REG) ||766		     (cfg_dde[i].data_type == ACF_SEC_TYPE_HDR_REG) ||767		     (cfg_dde[i].data_type == ACF_SEC_TYPE_MULTIPLE_BIN)) &&768		    (aw_dev->chip_id == cfg_dde[i].chip_id) &&769		    (aw_dev->i2c->adapter->nr == cfg_dde[i].dev_bus) &&770		    (aw_dev->i2c->addr == cfg_dde[i].dev_addr))771			(*scene_num)++;772	}773 774	if ((*scene_num) == 0) {775		dev_err(aw_dev->dev, "failed to obtain scene, scenu_num = %d\n", (*scene_num));776		return -EINVAL;777	}778 779	return 0;780}781 782static int aw_get_default_scene_count_v1(struct aw_device *aw_dev,783						struct aw_container *aw_cfg,784						unsigned int *scene_num)785{786	struct aw_cfg_hdr *cfg_hdr = (struct aw_cfg_hdr *)aw_cfg->data;787	struct aw_cfg_dde_v1 *cfg_dde =788		(struct aw_cfg_dde_v1 *)(aw_cfg->data + cfg_hdr->hdr_offset);789	unsigned int i;790 791 792	for (i = 0; i < cfg_hdr->ddt_num; ++i) {793		if (((cfg_dde[i].data_type == ACF_SEC_TYPE_MULTIPLE_BIN) ||794		     (cfg_dde[i].data_type == ACF_SEC_TYPE_REG) ||795		     (cfg_dde[i].data_type == ACF_SEC_TYPE_HDR_REG)) &&796		    (aw_dev->chip_id == cfg_dde[i].chip_id) &&797		    (aw_dev->channel == cfg_dde[i].dev_index))798			(*scene_num)++;799	}800 801	if ((*scene_num) == 0) {802		dev_err(aw_dev->dev, "failed to obtain scene, scenu_num = %d\n", (*scene_num));803		return -EINVAL;804	}805 806	return 0;807}808 809static int aw_dev_parse_scene_count_v1(struct aw_device *aw_dev,810							struct aw_container *aw_cfg,811							unsigned int *count)812{813	int ret;814 815	ret = aw_get_dde_type_info(aw_dev, aw_cfg);816	if (ret < 0)817		return ret;818 819	switch (aw_dev->prof_info.prof_type) {820	case AW88395_DEV_TYPE_ID:821		ret = aw_get_dev_scene_count_v1(aw_dev, aw_cfg, count);822		break;823	case AW88395_DEV_DEFAULT_TYPE_ID:824		ret = aw_get_default_scene_count_v1(aw_dev, aw_cfg, count);825		break;826	default:827		dev_err(aw_dev->dev, "unsupported prof_type[%x]", aw_dev->prof_info.prof_type);828		ret = -EINVAL;829		break;830	}831 832	return ret;833}834 835static int aw_dev_parse_data_by_sec_type_v1(struct aw_device *aw_dev,836							struct aw_cfg_hdr *prof_hdr,837							struct aw_cfg_dde_v1 *cfg_dde,838							int *cur_scene_id)839{840	struct aw_prof_info *prof_info = &aw_dev->prof_info;841	int ret;842 843	switch (cfg_dde->data_type) {844	case ACF_SEC_TYPE_MULTIPLE_BIN:845		ret = aw_dev_prof_parse_multi_bin(aw_dev, (u8 *)prof_hdr + cfg_dde->data_offset,846					cfg_dde->data_size, &prof_info->prof_desc[*cur_scene_id]);847		if (ret < 0) {848			dev_err(aw_dev->dev, "parse multi bin failed");849			return ret;850		}851		prof_info->prof_desc[*cur_scene_id].prf_str = cfg_dde->dev_profile_str;852		prof_info->prof_desc[*cur_scene_id].id = cfg_dde->dev_profile;853		(*cur_scene_id)++;854		break;855	case ACF_SEC_TYPE_HDR_REG:856		ret =  aw_dev_parse_reg_bin_with_hdr(aw_dev,857				(uint8_t *)prof_hdr + cfg_dde->data_offset,858				cfg_dde->data_size, &prof_info->prof_desc[*cur_scene_id]);859		if (ret < 0) {860			dev_err(aw_dev->dev, "parse reg bin with hdr failed");861			return ret;862		}863		prof_info->prof_desc[*cur_scene_id].prf_str = cfg_dde->dev_profile_str;864		prof_info->prof_desc[*cur_scene_id].id = cfg_dde->dev_profile;865		(*cur_scene_id)++;866		break;867	default:868		dev_err(aw_dev->dev, "unsupported SEC_TYPE [%d]", cfg_dde->data_type);869		return -EINVAL;870	}871 872	return 0;873}874 875static int aw_dev_parse_dev_type_v1(struct aw_device *aw_dev,876		struct aw_cfg_hdr *prof_hdr)877{878	struct aw_cfg_dde_v1 *cfg_dde =879		(struct aw_cfg_dde_v1 *)((char *)prof_hdr + prof_hdr->hdr_offset);880	int cur_scene_id = 0;881	unsigned int i;882	int ret;883 884	for (i = 0; i < prof_hdr->ddt_num; i++) {885		if ((aw_dev->i2c->adapter->nr == cfg_dde[i].dev_bus) &&886		    (aw_dev->i2c->addr == cfg_dde[i].dev_addr) &&887		    (aw_dev->chip_id == cfg_dde[i].chip_id)) {888			ret = aw_dev_parse_data_by_sec_type_v1(aw_dev, prof_hdr,889							&cfg_dde[i], &cur_scene_id);890			if (ret < 0) {891				dev_err(aw_dev->dev, "parse failed");892				return ret;893			}894		}895	}896 897	if (cur_scene_id == 0) {898		dev_err(aw_dev->dev, "get dev type failed, get num [%d]", cur_scene_id);899		return -EINVAL;900	}901 902	return 0;903}904 905static int aw_dev_parse_default_type_v1(struct aw_device *aw_dev,906		struct aw_cfg_hdr *prof_hdr)907{908	struct aw_cfg_dde_v1 *cfg_dde =909		(struct aw_cfg_dde_v1 *)((char *)prof_hdr + prof_hdr->hdr_offset);910	int cur_scene_id = 0;911	unsigned int i;912	int ret;913 914	for (i = 0; i < prof_hdr->ddt_num; i++) {915		if ((aw_dev->channel == cfg_dde[i].dev_index) &&916			(aw_dev->chip_id == cfg_dde[i].chip_id)) {917			ret = aw_dev_parse_data_by_sec_type_v1(aw_dev, prof_hdr,918							&cfg_dde[i], &cur_scene_id);919			if (ret < 0) {920				dev_err(aw_dev->dev, "parse failed");921				return ret;922			}923		}924	}925 926	if (cur_scene_id == 0) {927		dev_err(aw_dev->dev, "get dev default type failed, get num[%d]", cur_scene_id);928		return -EINVAL;929	}930 931	return 0;932}933 934static int aw_dev_parse_by_hdr_v1(struct aw_device *aw_dev,935		struct aw_cfg_hdr *cfg_hdr)936{937	int ret;938 939	switch (aw_dev->prof_info.prof_type) {940	case AW88395_DEV_TYPE_ID:941		ret = aw_dev_parse_dev_type_v1(aw_dev, cfg_hdr);942		break;943	case AW88395_DEV_DEFAULT_TYPE_ID:944		ret = aw_dev_parse_default_type_v1(aw_dev, cfg_hdr);945		break;946	default:947		dev_err(aw_dev->dev, "prof type matched failed, get num[%d]",948			aw_dev->prof_info.prof_type);949		ret =  -EINVAL;950		break;951	}952 953	return ret;954}955 956static int aw_dev_load_cfg_by_hdr_v1(struct aw_device *aw_dev,957						struct aw_container *aw_cfg)958{959	struct aw_cfg_hdr *cfg_hdr = (struct aw_cfg_hdr *)aw_cfg->data;960	struct aw_prof_info *prof_info = &aw_dev->prof_info;961	int ret;962 963	ret = aw_dev_parse_scene_count_v1(aw_dev, aw_cfg, &prof_info->count);964	if (ret < 0) {965		dev_err(aw_dev->dev, "get scene count failed");966		return ret;967	}968 969	prof_info->prof_desc = devm_kcalloc(aw_dev->dev,970					prof_info->count, sizeof(struct aw_prof_desc),971					GFP_KERNEL);972	if (!prof_info->prof_desc)973		return -ENOMEM;974 975	ret = aw_dev_parse_by_hdr_v1(aw_dev, cfg_hdr);976	if (ret < 0) {977		dev_err(aw_dev->dev, "parse hdr failed");978		return ret;979	}980 981	ret = aw_dev_create_prof_name_list_v1(aw_dev);982	if (ret < 0) {983		dev_err(aw_dev->dev, "create prof name list failed");984		return ret;985	}986 987	return 0;988}989 990int aw88395_dev_cfg_load(struct aw_device *aw_dev, struct aw_container *aw_cfg)991{992	struct aw_cfg_hdr *cfg_hdr;993	int ret;994 995	cfg_hdr = (struct aw_cfg_hdr *)aw_cfg->data;996 997	switch (cfg_hdr->hdr_version) {998	case AW88395_CFG_HDR_VER:999		ret = aw_dev_load_cfg_by_hdr(aw_dev, cfg_hdr);1000		if (ret < 0) {1001			dev_err(aw_dev->dev, "hdr_version[0x%x] parse failed",1002						cfg_hdr->hdr_version);1003			return ret;1004		}1005		break;1006	case AW88395_CFG_HDR_VER_V1:1007		ret = aw_dev_load_cfg_by_hdr_v1(aw_dev, aw_cfg);1008		if (ret < 0) {1009			dev_err(aw_dev->dev, "hdr_version[0x%x] parse failed",1010						cfg_hdr->hdr_version);1011			return ret;1012		}1013		break;1014	default:1015		dev_err(aw_dev->dev, "unsupported hdr_version [0x%x]", cfg_hdr->hdr_version);1016		return -EINVAL;1017	}1018	aw_dev->fw_status = AW88395_DEV_FW_OK;1019 1020	return 0;1021}1022EXPORT_SYMBOL_GPL(aw88395_dev_cfg_load);1023 1024static int aw_dev_check_cfg_by_hdr(struct aw_device *aw_dev, struct aw_container *aw_cfg)1025{1026	unsigned int end_data_offset;1027	struct aw_cfg_hdr *cfg_hdr;1028	struct aw_cfg_dde *cfg_dde;1029	unsigned int act_data = 0;1030	unsigned int hdr_ddt_len;1031	unsigned int i;1032	u8 act_crc8;1033 1034	cfg_hdr = (struct aw_cfg_hdr *)aw_cfg->data;1035	/* check file type id is awinic acf file */1036	if (cfg_hdr->id != ACF_FILE_ID) {1037		dev_err(aw_dev->dev, "not acf type file");1038		return -EINVAL;1039	}1040 1041	hdr_ddt_len = cfg_hdr->hdr_offset + cfg_hdr->ddt_size;1042	if (hdr_ddt_len > aw_cfg->len) {1043		dev_err(aw_dev->dev, "hdr_len with ddt_len [%d] overflow file size[%d]",1044		cfg_hdr->hdr_offset, aw_cfg->len);1045		return -EINVAL;1046	}1047 1048	/* check data size */1049	cfg_dde = (struct aw_cfg_dde *)((char *)aw_cfg->data + cfg_hdr->hdr_offset);1050	act_data += hdr_ddt_len;1051	for (i = 0; i < cfg_hdr->ddt_num; i++)1052		act_data += cfg_dde[i].data_size;1053 1054	if (act_data != aw_cfg->len) {1055		dev_err(aw_dev->dev, "act_data[%d] not equal to file size[%d]!",1056			act_data, aw_cfg->len);1057		return -EINVAL;1058	}1059 1060	for (i = 0; i < cfg_hdr->ddt_num; i++) {1061		/* data check */1062		end_data_offset = cfg_dde[i].data_offset + cfg_dde[i].data_size;1063		if (end_data_offset > aw_cfg->len) {1064			dev_err(aw_dev->dev, "ddt_num[%d] end_data_offset[%d] overflow size[%d]",1065				i, end_data_offset, aw_cfg->len);1066			return -EINVAL;1067		}1068 1069		/* crc check */1070		act_crc8 = crc8(aw_crc8_table, aw_cfg->data + cfg_dde[i].data_offset,1071							cfg_dde[i].data_size, 0);1072		if (act_crc8 != cfg_dde[i].data_crc) {1073			dev_err(aw_dev->dev, "ddt_num[%d] act_crc8:0x%x != data_crc:0x%x",1074				i, (u32)act_crc8, cfg_dde[i].data_crc);1075			return -EINVAL;1076		}1077	}1078 1079	return 0;1080}1081 1082static int aw_dev_check_acf_by_hdr_v1(struct aw_device *aw_dev, struct aw_container *aw_cfg)1083{1084	struct aw_cfg_dde_v1 *cfg_dde;1085	unsigned int end_data_offset;1086	struct aw_cfg_hdr *cfg_hdr;1087	unsigned int act_data = 0;1088	unsigned int hdr_ddt_len;1089	u8 act_crc8;1090	int i;1091 1092	cfg_hdr = (struct aw_cfg_hdr *)aw_cfg->data;1093 1094	/* check file type id is awinic acf file */1095	if (cfg_hdr->id != ACF_FILE_ID) {1096		dev_err(aw_dev->dev, "not acf type file");1097		return -EINVAL;1098	}1099 1100	hdr_ddt_len = cfg_hdr->hdr_offset + cfg_hdr->ddt_size;1101	if (hdr_ddt_len > aw_cfg->len) {1102		dev_err(aw_dev->dev, "hdrlen with ddt_len [%d] overflow file size[%d]",1103		cfg_hdr->hdr_offset, aw_cfg->len);1104		return -EINVAL;1105	}1106 1107	/* check data size */1108	cfg_dde = (struct aw_cfg_dde_v1 *)((char *)aw_cfg->data + cfg_hdr->hdr_offset);1109	act_data += hdr_ddt_len;1110	for (i = 0; i < cfg_hdr->ddt_num; i++)1111		act_data += cfg_dde[i].data_size;1112 1113	if (act_data != aw_cfg->len) {1114		dev_err(aw_dev->dev, "act_data[%d] not equal to file size[%d]!",1115			act_data, aw_cfg->len);1116		return -EINVAL;1117	}1118 1119	for (i = 0; i < cfg_hdr->ddt_num; i++) {1120		/* data check */1121		end_data_offset = cfg_dde[i].data_offset + cfg_dde[i].data_size;1122		if (end_data_offset > aw_cfg->len) {1123			dev_err(aw_dev->dev, "ddt_num[%d] end_data_offset[%d] overflow size[%d]",1124				i, end_data_offset, aw_cfg->len);1125			return -EINVAL;1126		}1127 1128		/* crc check */1129		act_crc8 = crc8(aw_crc8_table, aw_cfg->data + cfg_dde[i].data_offset,1130									cfg_dde[i].data_size, 0);1131		if (act_crc8 != cfg_dde[i].data_crc) {1132			dev_err(aw_dev->dev, "ddt_num[%d] act_crc8:0x%x != data_crc 0x%x",1133				i, (u32)act_crc8, cfg_dde[i].data_crc);1134			return -EINVAL;1135		}1136	}1137 1138	return 0;1139}1140 1141int aw88395_dev_load_acf_check(struct aw_device *aw_dev, struct aw_container *aw_cfg)1142{1143	struct aw_cfg_hdr *cfg_hdr;1144 1145	if (!aw_cfg) {1146		dev_err(aw_dev->dev, "aw_prof is NULL");1147		return -EINVAL;1148	}1149 1150	if (aw_cfg->len < sizeof(struct aw_cfg_hdr)) {1151		dev_err(aw_dev->dev, "cfg hdr size[%d] overflow file size[%d]",1152			aw_cfg->len, (int)sizeof(struct aw_cfg_hdr));1153		return -EINVAL;1154	}1155 1156	crc8_populate_lsb(aw_crc8_table, AW88395_CRC8_POLYNOMIAL);1157 1158	cfg_hdr = (struct aw_cfg_hdr *)aw_cfg->data;1159	switch (cfg_hdr->hdr_version) {1160	case AW88395_CFG_HDR_VER:1161		return aw_dev_check_cfg_by_hdr(aw_dev, aw_cfg);1162	case AW88395_CFG_HDR_VER_V1:1163		return aw_dev_check_acf_by_hdr_v1(aw_dev, aw_cfg);1164	default:1165		dev_err(aw_dev->dev, "unsupported hdr_version [0x%x]", cfg_hdr->hdr_version);1166		return -EINVAL;1167	}1168 1169	return 0;1170}1171EXPORT_SYMBOL_GPL(aw88395_dev_load_acf_check);1172 1173MODULE_DESCRIPTION("AW88395 ACF File Parsing Lib");1174MODULE_LICENSE("GPL v2");1175