File Index
Files and directories
Sign in
FILE

aw88395_lib.c

File preview with syntax highlighting.

linux-6.19.14/sound/soc/codecs/aw88395/aw88395_lib.c C
   1// SPDX-License-Identifier: GPL-2.0-only
   2//
   3// aw88395_lib.c  -- ACF bin parsing and check library file for aw88395
   4//
   5// Copyright (c) 2022-2023 AWINIC Technology CO., LTD
   6//
   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 0x8C
  17DECLARE_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, "unsupported 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");
~/ Read-only file preview.