File Index
Files and directories
Sign in
FILE

tas2781-fmwlib.c

File preview with syntax highlighting.

linux-6.19.14/sound/soc/codecs/tas2781-fmwlib.c C
   1// SPDX-License-Identifier: GPL-2.0
   2//
   3// tas2781-fmwlib.c -- TASDEVICE firmware support
   4//
   5// Copyright 2023 - 2025 Texas Instruments, Inc.
   6//
   7// Author: Shenghao Ding <shenghao-ding@ti.com>
   8// Author: Baojun Xu <baojun.xu@ti.com>
   9
  10#include <linux/crc8.h>
  11#include <linux/firmware.h>
  12#include <linux/i2c.h>
  13#include <linux/init.h>
  14#include <linux/interrupt.h>
  15#include <linux/module.h>
  16#include <linux/of.h>
  17#include <linux/of_irq.h>
  18#include <linux/regmap.h>
  19#include <linux/slab.h>
  20#include <sound/pcm_params.h>
  21#include <sound/soc.h>
  22#include <sound/tlv.h>
  23#include <sound/tas2781.h>
  24#include <linux/unaligned.h>
  25
  26#define ERROR_PRAM_CRCCHK			0x0000000
  27#define ERROR_YRAM_CRCCHK			0x0000001
  28#define	PPC_DRIVER_CRCCHK			0x00000200
  29
  30#define TAS2781_SA_COEFF_SWAP_REG		TASDEVICE_REG(0, 0x35, 0x2c)
  31#define TAS2781_YRAM_BOOK1			140
  32#define TAS2781_YRAM1_PAGE			42
  33#define TAS2781_YRAM1_START_REG			88
  34
  35#define TAS2781_YRAM2_START_PAGE		43
  36#define TAS2781_YRAM2_END_PAGE			49
  37#define TAS2781_YRAM2_START_REG			8
  38#define TAS2781_YRAM2_END_REG			127
  39
  40#define TAS2781_YRAM3_PAGE			50
  41#define TAS2781_YRAM3_START_REG			8
  42#define TAS2781_YRAM3_END_REG			27
  43
  44/*should not include B0_P53_R44-R47 */
  45#define TAS2781_YRAM_BOOK2			0
  46#define TAS2781_YRAM4_START_PAGE		50
  47#define TAS2781_YRAM4_END_PAGE			60
  48
  49#define TAS2781_YRAM5_PAGE			61
  50#define TAS2781_YRAM5_START_REG			TAS2781_YRAM3_START_REG
  51#define TAS2781_YRAM5_END_REG			TAS2781_YRAM3_END_REG
  52
  53#define TASDEVICE_CMD_SING_W		0x1
  54#define TASDEVICE_CMD_BURST		0x2
  55#define TASDEVICE_CMD_DELAY		0x3
  56#define TASDEVICE_CMD_FIELD_W		0x4
  57
  58#define TASDEVICE_MAXPROGRAM_NUM_KERNEL			5
  59#define TASDEVICE_MAXCONFIG_NUM_KERNEL_MULTIPLE_AMPS	64
  60#define TASDEVICE_MAXCONFIG_NUM_KERNEL			10
  61#define MAIN_ALL_DEVICES_1X				0x01
  62#define MAIN_DEVICE_A_1X				0x02
  63#define MAIN_DEVICE_B_1X				0x03
  64#define MAIN_DEVICE_C_1X				0x04
  65#define MAIN_DEVICE_D_1X				0x05
  66#define COEFF_DEVICE_A_1X				0x12
  67#define COEFF_DEVICE_B_1X				0x13
  68#define COEFF_DEVICE_C_1X				0x14
  69#define COEFF_DEVICE_D_1X				0x15
  70#define PRE_DEVICE_A_1X					0x22
  71#define PRE_DEVICE_B_1X					0x23
  72#define PRE_DEVICE_C_1X					0x24
  73#define PRE_DEVICE_D_1X					0x25
  74#define PRE_SOFTWARE_RESET_DEVICE_A			0x41
  75#define PRE_SOFTWARE_RESET_DEVICE_B			0x42
  76#define PRE_SOFTWARE_RESET_DEVICE_C			0x43
  77#define PRE_SOFTWARE_RESET_DEVICE_D			0x44
  78#define POST_SOFTWARE_RESET_DEVICE_A			0x45
  79#define POST_SOFTWARE_RESET_DEVICE_B			0x46
  80#define POST_SOFTWARE_RESET_DEVICE_C			0x47
  81#define POST_SOFTWARE_RESET_DEVICE_D			0x48
  82
  83struct tas_crc {
  84	unsigned char offset;
  85	unsigned char len;
  86};
  87
  88struct blktyp_devidx_map {
  89	unsigned char blktyp;
  90	unsigned char dev_idx;
  91};
  92
  93static const char deviceNumber[TASDEVICE_DSP_TAS_MAX_DEVICE] = {
  94	1, 2, 1, 2, 1, 1, 0, 2, 4, 3, 1, 2, 3, 4, 1, 2
  95};
  96
  97/* fixed m68k compiling issue: mapping table can save code field */
  98static const struct blktyp_devidx_map ppc3_tas2781_mapping_table[] = {
  99	{ MAIN_ALL_DEVICES_1X, 0x80 },
 100	{ MAIN_DEVICE_A_1X, 0x81 },
 101	{ COEFF_DEVICE_A_1X, 0xC1 },
 102	{ PRE_DEVICE_A_1X, 0xC1 },
 103	{ PRE_SOFTWARE_RESET_DEVICE_A, 0xC1 },
 104	{ POST_SOFTWARE_RESET_DEVICE_A, 0xC1 },
 105	{ MAIN_DEVICE_B_1X, 0x82 },
 106	{ COEFF_DEVICE_B_1X, 0xC2 },
 107	{ PRE_DEVICE_B_1X, 0xC2 },
 108	{ PRE_SOFTWARE_RESET_DEVICE_B, 0xC2 },
 109	{ POST_SOFTWARE_RESET_DEVICE_B, 0xC2 },
 110	{ MAIN_DEVICE_C_1X, 0x83 },
 111	{ COEFF_DEVICE_C_1X, 0xC3 },
 112	{ PRE_DEVICE_C_1X, 0xC3 },
 113	{ PRE_SOFTWARE_RESET_DEVICE_C, 0xC3 },
 114	{ POST_SOFTWARE_RESET_DEVICE_C, 0xC3 },
 115	{ MAIN_DEVICE_D_1X, 0x84 },
 116	{ COEFF_DEVICE_D_1X, 0xC4 },
 117	{ PRE_DEVICE_D_1X, 0xC4 },
 118	{ PRE_SOFTWARE_RESET_DEVICE_D, 0xC4 },
 119	{ POST_SOFTWARE_RESET_DEVICE_D, 0xC4 },
 120};
 121
 122static const struct blktyp_devidx_map ppc3_mapping_table[] = {
 123	{ MAIN_ALL_DEVICES_1X, 0x80 },
 124	{ MAIN_DEVICE_A_1X, 0x81 },
 125	{ COEFF_DEVICE_A_1X, 0xC1 },
 126	{ PRE_DEVICE_A_1X, 0xC1 },
 127	{ MAIN_DEVICE_B_1X, 0x82 },
 128	{ COEFF_DEVICE_B_1X, 0xC2 },
 129	{ PRE_DEVICE_B_1X, 0xC2 },
 130	{ MAIN_DEVICE_C_1X, 0x83 },
 131	{ COEFF_DEVICE_C_1X, 0xC3 },
 132	{ PRE_DEVICE_C_1X, 0xC3 },
 133	{ MAIN_DEVICE_D_1X, 0x84 },
 134	{ COEFF_DEVICE_D_1X, 0xC4 },
 135	{ PRE_DEVICE_D_1X, 0xC4 },
 136};
 137
 138static const struct blktyp_devidx_map non_ppc3_mapping_table[] = {
 139	{ MAIN_ALL_DEVICES, 0x80 },
 140	{ MAIN_DEVICE_A, 0x81 },
 141	{ COEFF_DEVICE_A, 0xC1 },
 142	{ PRE_DEVICE_A, 0xC1 },
 143	{ MAIN_DEVICE_B, 0x82 },
 144	{ COEFF_DEVICE_B, 0xC2 },
 145	{ PRE_DEVICE_B, 0xC2 },
 146	{ MAIN_DEVICE_C, 0x83 },
 147	{ COEFF_DEVICE_C, 0xC3 },
 148	{ PRE_DEVICE_C, 0xC3 },
 149	{ MAIN_DEVICE_D, 0x84 },
 150	{ COEFF_DEVICE_D, 0xC4 },
 151	{ PRE_DEVICE_D, 0xC4 },
 152};
 153
 154static struct tasdevice_config_info *tasdevice_add_config(
 155	struct tasdevice_priv *tas_priv, unsigned char *config_data,
 156	unsigned int config_size, int *status)
 157{
 158	struct tasdevice_config_info *cfg_info;
 159	struct tasdev_blk_data **bk_da;
 160	unsigned int config_offset = 0;
 161	unsigned int i;
 162
 163	/* In most projects are many audio cases, such as music, handfree,
 164	 * receiver, games, audio-to-haptics, PMIC record, bypass mode,
 165	 * portrait, landscape, etc. Even in multiple audios, one or
 166	 * two of the chips will work for the special case, such as
 167	 * ultrasonic application. In order to support these variable-numbers
 168	 * of audio cases, flexible configs have been introduced in the
 169	 * dsp firmware.
 170	 */
 171	cfg_info = kzalloc(sizeof(struct tasdevice_config_info), GFP_KERNEL);
 172	if (!cfg_info) {
 173		*status = -ENOMEM;
 174		goto out;
 175	}
 176
 177	if (tas_priv->rcabin.fw_hdr.binary_version_num >= 0x105) {
 178		if (config_offset + 64 > (int)config_size) {
 179			*status = -EINVAL;
 180			dev_err(tas_priv->dev, "add conf: Out of boundary\n");
 181			goto out;
 182		}
 183		/* If in the RCA bin file are several profiles with the
 184		 * keyword "init", init_profile_id only store the last
 185		 * init profile id.
 186		 */
 187		if (strnstr(&config_data[config_offset], "init", 64)) {
 188			tas_priv->rcabin.init_profile_id =
 189				tas_priv->rcabin.ncfgs - 1;
 190			dev_dbg(tas_priv->dev, "%s: init profile id = %d\n",
 191				__func__, tas_priv->rcabin.init_profile_id);
 192		}
 193		config_offset += 64;
 194	}
 195
 196	if (config_offset + 4 > (int)config_size) {
 197		*status = -EINVAL;
 198		dev_err(tas_priv->dev, "add config: Out of boundary\n");
 199		goto out;
 200	}
 201
 202	/* convert data[offset], data[offset + 1], data[offset + 2] and
 203	 * data[offset + 3] into host
 204	 */
 205	cfg_info->nblocks = get_unaligned_be32(&config_data[config_offset]);
 206	config_offset += 4;
 207
 208	/* Several kinds of dsp/algorithm firmwares can run on tas2781,
 209	 * the number and size of blk are not fixed and different among
 210	 * these firmwares.
 211	 */
 212	bk_da = cfg_info->blk_data = kcalloc(cfg_info->nblocks,
 213		sizeof(struct tasdev_blk_data *), GFP_KERNEL);
 214	if (!bk_da) {
 215		*status = -ENOMEM;
 216		goto out;
 217	}
 218	cfg_info->real_nblocks = 0;
 219	for (i = 0; i < cfg_info->nblocks; i++) {
 220		if (config_offset + 12 > config_size) {
 221			*status = -EINVAL;
 222			dev_err(tas_priv->dev,
 223				"%s: Out of boundary: i = %d nblocks = %u!\n",
 224				__func__, i, cfg_info->nblocks);
 225			break;
 226		}
 227		bk_da[i] = kzalloc(sizeof(struct tasdev_blk_data), GFP_KERNEL);
 228		if (!bk_da[i]) {
 229			*status = -ENOMEM;
 230			break;
 231		}
 232
 233		bk_da[i]->dev_idx = config_data[config_offset];
 234		config_offset++;
 235
 236		bk_da[i]->block_type = config_data[config_offset];
 237		config_offset++;
 238
 239		if (bk_da[i]->block_type == TASDEVICE_BIN_BLK_PRE_POWER_UP) {
 240			if (bk_da[i]->dev_idx == 0)
 241				cfg_info->active_dev =
 242					(1 << tas_priv->ndev) - 1;
 243			else
 244				cfg_info->active_dev |= 1 <<
 245					(bk_da[i]->dev_idx - 1);
 246
 247		}
 248		bk_da[i]->yram_checksum =
 249			get_unaligned_be16(&config_data[config_offset]);
 250		config_offset += 2;
 251		bk_da[i]->block_size =
 252			get_unaligned_be32(&config_data[config_offset]);
 253		config_offset += 4;
 254
 255		bk_da[i]->n_subblks =
 256			get_unaligned_be32(&config_data[config_offset]);
 257
 258		config_offset += 4;
 259
 260		if (config_offset + bk_da[i]->block_size > config_size) {
 261			*status = -EINVAL;
 262			dev_err(tas_priv->dev,
 263				"%s: Out of boundary: i = %d blks = %u!\n",
 264				__func__, i, cfg_info->nblocks);
 265			break;
 266		}
 267		/* instead of kzalloc+memcpy */
 268		bk_da[i]->regdata = kmemdup(&config_data[config_offset],
 269			bk_da[i]->block_size, GFP_KERNEL);
 270		if (!bk_da[i]->regdata) {
 271			*status = -ENOMEM;
 272			goto out;
 273		}
 274
 275		config_offset += bk_da[i]->block_size;
 276		cfg_info->real_nblocks += 1;
 277	}
 278
 279out:
 280	return cfg_info;
 281}
 282
 283int tasdevice_rca_parser(void *context, const struct firmware *fmw)
 284{
 285	struct tasdevice_priv *tas_priv = context;
 286	struct tasdevice_config_info **cfg_info;
 287	struct tasdevice_rca_hdr *fw_hdr;
 288	struct tasdevice_rca *rca;
 289	unsigned int total_config_sz = 0;
 290	unsigned char *buf;
 291	int offset = 0;
 292	int ret = 0;
 293	int i;
 294
 295	rca = &(tas_priv->rcabin);
 296	/* Initialize to none */
 297	rca->init_profile_id = -1;
 298	fw_hdr = &(rca->fw_hdr);
 299	if (!fmw || !fmw->data) {
 300		dev_err(tas_priv->dev, "Failed to read %s\n",
 301			tas_priv->rca_binaryname);
 302		tas_priv->fw_state = TASDEVICE_DSP_FW_FAIL;
 303		ret = -EINVAL;
 304		goto out;
 305	}
 306	buf = (unsigned char *)fmw->data;
 307
 308	fw_hdr->img_sz = get_unaligned_be32(&buf[offset]);
 309	offset += 4;
 310	if (fw_hdr->img_sz != fmw->size) {
 311		dev_err(tas_priv->dev,
 312			"File size not match, %d %u", (int)fmw->size,
 313			fw_hdr->img_sz);
 314		tas_priv->fw_state = TASDEVICE_DSP_FW_FAIL;
 315		ret = -EINVAL;
 316		goto out;
 317	}
 318
 319	fw_hdr->checksum = get_unaligned_be32(&buf[offset]);
 320	offset += 4;
 321	fw_hdr->binary_version_num = get_unaligned_be32(&buf[offset]);
 322	if (fw_hdr->binary_version_num < 0x103) {
 323		dev_err(tas_priv->dev, "File version 0x%04x is too low",
 324			fw_hdr->binary_version_num);
 325		tas_priv->fw_state = TASDEVICE_DSP_FW_FAIL;
 326		ret = -EINVAL;
 327		goto out;
 328	}
 329	offset += 4;
 330	fw_hdr->drv_fw_version = get_unaligned_be32(&buf[offset]);
 331	offset += 8;
 332	fw_hdr->plat_type = buf[offset];
 333	offset += 1;
 334	fw_hdr->dev_family = buf[offset];
 335	offset += 1;
 336	fw_hdr->reserve = buf[offset];
 337	offset += 1;
 338	fw_hdr->ndev = buf[offset];
 339	offset += 1;
 340	if (fw_hdr->ndev != tas_priv->ndev) {
 341		dev_err(tas_priv->dev,
 342			"ndev(%u) in rcabin mismatch ndev(%u) in DTS\n",
 343			fw_hdr->ndev, tas_priv->ndev);
 344		tas_priv->fw_state = TASDEVICE_DSP_FW_FAIL;
 345		ret = -EINVAL;
 346		goto out;
 347	}
 348	if (offset + TASDEVICE_DEVICE_SUM > fw_hdr->img_sz) {
 349		dev_err(tas_priv->dev, "rca_ready: Out of boundary!\n");
 350		ret = -EINVAL;
 351		tas_priv->fw_state = TASDEVICE_DSP_FW_FAIL;
 352		goto out;
 353	}
 354
 355	for (i = 0; i < TASDEVICE_DEVICE_SUM; i++, offset++)
 356		fw_hdr->devs[i] = buf[offset];
 357
 358	fw_hdr->nconfig = get_unaligned_be32(&buf[offset]);
 359	offset += 4;
 360
 361	for (i = 0; i < TASDEVICE_CONFIG_SUM; i++) {
 362		fw_hdr->config_size[i] = get_unaligned_be32(&buf[offset]);
 363		offset += 4;
 364		total_config_sz += fw_hdr->config_size[i];
 365	}
 366
 367	if (fw_hdr->img_sz - total_config_sz != (unsigned int)offset) {
 368		dev_err(tas_priv->dev, "Bin file error!\n");
 369		ret = -EINVAL;
 370		tas_priv->fw_state = TASDEVICE_DSP_FW_FAIL;
 371		goto out;
 372	}
 373
 374	cfg_info = kcalloc(fw_hdr->nconfig, sizeof(*cfg_info), GFP_KERNEL);
 375	if (!cfg_info) {
 376		ret = -ENOMEM;
 377		tas_priv->fw_state = TASDEVICE_DSP_FW_FAIL;
 378		goto out;
 379	}
 380	rca->cfg_info = cfg_info;
 381	rca->ncfgs = 0;
 382	for (i = 0; i < (int)fw_hdr->nconfig; i++) {
 383		rca->ncfgs += 1;
 384		cfg_info[i] = tasdevice_add_config(tas_priv, &buf[offset],
 385			fw_hdr->config_size[i], &ret);
 386		if (ret) {
 387			tas_priv->fw_state = TASDEVICE_DSP_FW_FAIL;
 388			goto out;
 389		}
 390		offset += (int)fw_hdr->config_size[i];
 391	}
 392out:
 393	return ret;
 394}
 395EXPORT_SYMBOL_NS_GPL(tasdevice_rca_parser, "SND_SOC_TAS2781_FMWLIB");
 396
 397/* fixed m68k compiling issue: mapping table can save code field */
 398static unsigned char map_dev_idx(struct tasdevice_fw *tas_fmw,
 399	struct tasdev_blk *block)
 400{
 401
 402	struct blktyp_devidx_map *p =
 403		(struct blktyp_devidx_map *)non_ppc3_mapping_table;
 404	struct tasdevice_dspfw_hdr *fw_hdr = &(tas_fmw->fw_hdr);
 405	struct tasdevice_fw_fixed_hdr *fw_fixed_hdr = &(fw_hdr->fixed_hdr);
 406
 407	int i, n = ARRAY_SIZE(non_ppc3_mapping_table);
 408	unsigned char dev_idx = 0;
 409
 410	if (fw_fixed_hdr->ppcver >= PPC3_VERSION_TAS2781_BASIC_MIN) {
 411		p = (struct blktyp_devidx_map *)ppc3_tas2781_mapping_table;
 412		n = ARRAY_SIZE(ppc3_tas2781_mapping_table);
 413	} else if (fw_fixed_hdr->ppcver >= PPC3_VERSION_BASE) {
 414		p = (struct blktyp_devidx_map *)ppc3_mapping_table;
 415		n = ARRAY_SIZE(ppc3_mapping_table);
 416	}
 417
 418	for (i = 0; i < n; i++) {
 419		if (block->type == p[i].blktyp) {
 420			dev_idx = p[i].dev_idx;
 421			break;
 422		}
 423	}
 424
 425	return dev_idx;
 426}
 427
 428static int fw_parse_block_data_kernel(struct tasdevice_fw *tas_fmw,
 429	struct tasdev_blk *block, const struct firmware *fmw, int offset)
 430{
 431	const unsigned char *data = fmw->data;
 432
 433	if (offset + 16 > fmw->size) {
 434		dev_err(tas_fmw->dev, "%s: File Size error\n", __func__);
 435		offset = -EINVAL;
 436		goto out;
 437	}
 438
 439	/* convert data[offset], data[offset + 1], data[offset + 2] and
 440	 * data[offset + 3] into host
 441	 */
 442	block->type = get_unaligned_be32(&data[offset]);
 443	offset += 4;
 444
 445	block->is_pchksum_present = data[offset];
 446	offset++;
 447
 448	block->pchksum = data[offset];
 449	offset++;
 450
 451	block->is_ychksum_present = data[offset];
 452	offset++;
 453
 454	block->ychksum = data[offset];
 455	offset++;
 456
 457	block->blk_size = get_unaligned_be32(&data[offset]);
 458	offset += 4;
 459
 460	block->nr_subblocks = get_unaligned_be32(&data[offset]);
 461	offset += 4;
 462
 463	/* fixed m68k compiling issue:
 464	 * 1. mapping table can save code field.
 465	 * 2. storing the dev_idx as a member of block can reduce unnecessary
 466	 *    time and system resource comsumption of dev_idx mapping every
 467	 *    time the block data writing to the dsp.
 468	 */
 469	block->dev_idx = map_dev_idx(tas_fmw, block);
 470
 471	if (offset + block->blk_size > fmw->size) {
 472		dev_err(tas_fmw->dev, "%s: nSublocks error\n", __func__);
 473		offset = -EINVAL;
 474		goto out;
 475	}
 476	/* instead of kzalloc+memcpy */
 477	block->data = kmemdup(&data[offset], block->blk_size, GFP_KERNEL);
 478	if (!block->data) {
 479		offset = -ENOMEM;
 480		goto out;
 481	}
 482	offset += block->blk_size;
 483
 484out:
 485	return offset;
 486}
 487
 488static int fw_parse_data_kernel(struct tasdevice_fw *tas_fmw,
 489	struct tasdevice_data *img_data, const struct firmware *fmw,
 490	int offset)
 491{
 492	const unsigned char *data = fmw->data;
 493	struct tasdev_blk *blk;
 494	unsigned int i;
 495
 496	if (offset + 4 > fmw->size) {
 497		dev_err(tas_fmw->dev, "%s: File Size error\n", __func__);
 498		offset = -EINVAL;
 499		goto out;
 500	}
 501	img_data->nr_blk = get_unaligned_be32(&data[offset]);
 502	offset += 4;
 503
 504	img_data->dev_blks = kcalloc(img_data->nr_blk,
 505		sizeof(struct tasdev_blk), GFP_KERNEL);
 506	if (!img_data->dev_blks) {
 507		offset = -ENOMEM;
 508		goto out;
 509	}
 510
 511	for (i = 0; i < img_data->nr_blk; i++) {
 512		blk = &(img_data->dev_blks[i]);
 513		offset = fw_parse_block_data_kernel(tas_fmw, blk, fmw, offset);
 514		if (offset < 0) {
 515			offset = -EINVAL;
 516			break;
 517		}
 518	}
 519
 520out:
 521	return offset;
 522}
 523
 524static int fw_parse_tas5825_program_data_kernel(
 525	struct tasdevice_priv *tas_priv, struct tasdevice_fw *tas_fmw,
 526	const struct firmware *fmw, int offset)
 527{
 528	struct tasdevice_prog *program;
 529	unsigned int i;
 530
 531	for (i = 0; i < tas_fmw->nr_programs; i++) {
 532		program = &(tas_fmw->programs[i]);
 533		if (offset + 72 > fmw->size) {
 534			dev_err(tas_priv->dev, "%s: mpName error\n", __func__);
 535			return -EINVAL;
 536		}
 537		/* Skip 65 unused byts*/
 538		offset += 65;
 539		offset = fw_parse_data_kernel(tas_fmw, &(program->dev_data),
 540			fmw, offset);
 541		if (offset < 0)
 542			return offset;
 543	}
 544
 545	return offset;
 546}
 547
 548static int fw_parse_tas5825_configuration_data_kernel(
 549	struct tasdevice_priv *tas_priv,
 550	struct tasdevice_fw *tas_fmw, const struct firmware *fmw, int offset)
 551{
 552	const unsigned char *data = fmw->data;
 553	struct tasdevice_config *config;
 554	unsigned int i;
 555
 556	for (i = 0; i < tas_fmw->nr_configurations; i++) {
 557		config = &(tas_fmw->configs[i]);
 558		if (offset + 80 > fmw->size) {
 559			dev_err(tas_priv->dev, "%s: mpName error\n", __func__);
 560			return -EINVAL;
 561		}
 562		memcpy(config->name, &data[offset], 64);
 563		/* Skip extra 8 bytes*/
 564		offset += 72;
 565		offset = fw_parse_data_kernel(tas_fmw, &(config->dev_data),
 566			fmw, offset);
 567		if (offset < 0)
 568			return offset;
 569	}
 570
 571	return offset;
 572}
 573
 574static int fw_parse_program_data_kernel(
 575	struct tasdevice_priv *tas_priv, struct tasdevice_fw *tas_fmw,
 576	const struct firmware *fmw, int offset)
 577{
 578	struct tasdevice_prog *program;
 579	unsigned int i;
 580
 581	for (i = 0; i < tas_fmw->nr_programs; i++) {
 582		program = &(tas_fmw->programs[i]);
 583		if (offset + 72 > fmw->size) {
 584			dev_err(tas_priv->dev, "%s: mpName error\n", __func__);
 585			offset = -EINVAL;
 586			goto out;
 587		}
 588		/*skip 72 unused byts*/
 589		offset += 72;
 590
 591		offset = fw_parse_data_kernel(tas_fmw, &(program->dev_data),
 592			fmw, offset);
 593		if (offset < 0)
 594			goto out;
 595	}
 596
 597out:
 598	return offset;
 599}
 600
 601static int fw_parse_configuration_data_kernel(
 602	struct tasdevice_priv *tas_priv,
 603	struct tasdevice_fw *tas_fmw, const struct firmware *fmw, int offset)
 604{
 605	const unsigned char *data = fmw->data;
 606	struct tasdevice_config *config;
 607	unsigned int i;
 608
 609	for (i = 0; i < tas_fmw->nr_configurations; i++) {
 610		config = &(tas_fmw->configs[i]);
 611		if (offset + 80 > fmw->size) {
 612			dev_err(tas_priv->dev, "%s: mpName error\n", __func__);
 613			offset = -EINVAL;
 614			goto out;
 615		}
 616		memcpy(config->name, &data[offset], 64);
 617		/*skip extra 16 bytes*/
 618		offset += 80;
 619
 620		offset = fw_parse_data_kernel(tas_fmw, &(config->dev_data),
 621			fmw, offset);
 622		if (offset < 0)
 623			goto out;
 624	}
 625
 626out:
 627	return offset;
 628}
 629
 630static void fct_param_address_parser(struct cali_reg *r,
 631	struct tasdevice_fw *tas_fmw, const unsigned char *data)
 632{
 633	struct fct_param_address *p = &tas_fmw->fct_par_addr;
 634	unsigned int i;
 635
 636	/*
 637	 * Calibration parameters locations and data schema in dsp firmware.
 638	 * The number of items are flexible, but not more than 20. The dsp tool
 639	 * will reseve 20*24-byte space for fct params. In some cases, the
 640	 * number of fct param is less than 20, the data will be saved from the
 641	 * beginning, the rest part will be stuffed with zero.
 642	 *
 643	 *	fct_param_num (not more than 20)
 644	 *	for (i = 0; i < fct_param_num; i++) {
 645	 *		Alias of fct param (20 bytes)
 646	 *		Book (1 byte)
 647	 *		Page (1 byte)
 648	 *		Offset (1 byte)
 649	 *		CoeffLength (1 byte) = 0x1
 650	 *	}
 651	 *	if (20 - fct_param_num)
 652	 *		24*(20 - fct_param_num) pieces of '0' as stuffing
 653	 *
 654	 * As follow:
 655	 * umg_SsmKEGCye	 = Book, Page, Offset, CoeffLength
 656	 * iks_E0 		 = Book, Page, Offset, CoeffLength
 657	 * yep_LsqM0		 = Book, Page, Offset, CoeffLength
 658	 * oyz_U0_ujx		 = Book, Page, Offset, CoeffLength
 659	 * iks_GC_GMgq		 = Book, Page, Offset, CoeffLength
 660	 * gou_Yao		 = Book, Page, Offset, CoeffLength
 661	 * kgd_Wsc_Qsbp		 = Book, Page, Offset, CoeffLength
 662	 * yec_CqseSsqs		 = Book, Page, Offset, CoeffLength
 663	 * iks_SogkGgog2	 = Book, Page, Offset, CoeffLength
 664	 * yec_Sae_Y		 = Book, Page, Offset, CoeffLength
 665	 * Re_Int		 = Book, Page, Offset, CoeffLength
 666	 * SigFlag		 = Book, Page, Offset, CoeffLength
 667	 * a1_Int		 = Book, Page, Offset, CoeffLength
 668	 * a2_Int		 = Book, Page, Offset, CoeffLength
 669	 */
 670	for (i = 0; i < 20; i++) {
 671		const unsigned char *dat = &data[24 * i];
 672
 673		/*
 674		 * check whether current fct param is empty.
 675		 */
 676		if (dat[23] != 1)
 677			break;
 678
 679		if (!strncmp(dat, "umg_SsmKEGCye", 20))
 680			r->pow_reg = TASDEVICE_REG(dat[20], dat[21], dat[22]);
 681		/* high 32-bit of real-time spk impedance */
 682		else if (!strncmp(dat, "iks_E0", 20))
 683			r->r0_reg = TASDEVICE_REG(dat[20], dat[21], dat[22]);
 684		/* inverse of real-time spk impedance */
 685		else if (!strncmp(dat, "yep_LsqM0", 20))
 686			r->invr0_reg =
 687				TASDEVICE_REG(dat[20], dat[21], dat[22]);
 688		/* low 32-bit of real-time spk impedance */
 689		else if (!strncmp(dat, "oyz_U0_ujx", 20))
 690			r->r0_low_reg =
 691				TASDEVICE_REG(dat[20], dat[21], dat[22]);
 692		/* Delta Thermal Limit */
 693		else if (!strncmp(dat, "iks_GC_GMgq", 20))
 694			r->tlimit_reg =
 695				TASDEVICE_REG(dat[20], dat[21], dat[22]);
 696		/* Thermal data for PG 1.0 device */
 697		else if (!strncmp(dat, "gou_Yao", 20))
 698			memcpy(p->thr, &dat[20], 3);
 699		/* Pilot tone enable flag, usually the sine wave */
 700		else if (!strncmp(dat, "kgd_Wsc_Qsbp", 20))
 701			memcpy(p->plt_flg, &dat[20], 3);
 702		/* Pilot tone gain for calibration */
 703		else if (!strncmp(dat, "yec_CqseSsqs", 20))
 704			memcpy(p->sin_gn, &dat[20], 3);
 705		/* Pilot tone gain for calibration, useless in PG 2.0 */
 706		else if (!strncmp(dat, "iks_SogkGgog2", 20))
 707			memcpy(p->sin_gn2, &dat[20], 3);
 708		/* Thermal data for PG 2.0 device */
 709		else if (!strncmp(dat, "yec_Sae_Y", 20))
 710			memcpy(p->thr2, &dat[20], 3);
 711		/* Spk Equivalent Resistance in fixed-point format */
 712		else if (!strncmp(dat, "Re_Int", 20))
 713			memcpy(p->r0_reg, &dat[20], 3);
 714		/* Check whether the spk connection is open */
 715		else if (!strncmp(dat, "SigFlag", 20))
 716			memcpy(p->tf_reg, &dat[20], 3);
 717		/* check spk resonant frequency */
 718		else if (!strncmp(dat, "a1_Int", 20))
 719			memcpy(p->a1_reg, &dat[20], 3);
 720		/* check spk resonant frequency */
 721		else if (!strncmp(dat, "a2_Int", 20))
 722			memcpy(p->a2_reg, &dat[20], 3);
 723	}
 724}
 725
 726static int fw_parse_fct_param_address(struct tasdevice_priv *tas_priv,
 727	struct tasdevice_fw *tas_fmw, const struct firmware *fmw, int offset)
 728{
 729	struct calidata *cali_data = &tas_priv->cali_data;
 730	struct cali_reg *r = &cali_data->cali_reg_array;
 731	const unsigned char *data = fmw->data;
 732
 733	if (offset + 520 > fmw->size) {
 734		dev_err(tas_priv->dev, "%s: File Size error\n", __func__);
 735		return -EINVAL;
 736	}
 737
 738	/* skip reserved part */
 739	offset += 40;
 740
 741	fct_param_address_parser(r, tas_fmw, &data[offset]);
 742
 743	offset += 480;
 744
 745	return offset;
 746}
 747
 748static int fw_parse_variable_header_kernel(
 749	struct tasdevice_priv *tas_priv, const struct firmware *fmw,
 750	int offset)
 751{
 752	struct tasdevice_fw *tas_fmw = tas_priv->fmw;
 753	struct tasdevice_dspfw_hdr *fw_hdr = &(tas_fmw->fw_hdr);
 754	struct tasdevice_prog *program;
 755	struct tasdevice_config *config;
 756	const unsigned char *buf = fmw->data;
 757	unsigned short max_confs;
 758	unsigned int i;
 759
 760	if (offset + 12 + 4 * TASDEVICE_MAXPROGRAM_NUM_KERNEL > fmw->size) {
 761		dev_err(tas_priv->dev, "%s: File Size error\n", __func__);
 762		offset = -EINVAL;
 763		goto out;
 764	}
 765	fw_hdr->device_family = get_unaligned_be16(&buf[offset]);
 766	if (fw_hdr->device_family != 0) {
 767		dev_err(tas_priv->dev, "%s:not TAS device\n", __func__);
 768		offset = -EINVAL;
 769		goto out;
 770	}
 771	offset += 2;
 772	fw_hdr->device = get_unaligned_be16(&buf[offset]);
 773	if (fw_hdr->device >= TASDEVICE_DSP_TAS_MAX_DEVICE ||
 774		fw_hdr->device == 6) {
 775		dev_err(tas_priv->dev, "Unsupported dev %d\n", fw_hdr->device);
 776		offset = -EINVAL;
 777		goto out;
 778	}
 779	offset += 2;
 780	fw_hdr->ndev = deviceNumber[fw_hdr->device];
 781
 782	if (fw_hdr->ndev != tas_priv->ndev) {
 783		dev_err(tas_priv->dev,
 784			"%s: ndev(%u) in dspbin mismatch ndev(%u) in DTS\n",
 785			__func__, fw_hdr->ndev, tas_priv->ndev);
 786		offset = -EINVAL;
 787		goto out;
 788	}
 789
 790	tas_fmw->nr_programs = get_unaligned_be32(&buf[offset]);
 791	offset += 4;
 792
 793	if (tas_fmw->nr_programs == 0 || tas_fmw->nr_programs >
 794		TASDEVICE_MAXPROGRAM_NUM_KERNEL) {
 795		dev_err(tas_priv->dev, "mnPrograms is invalid\n");
 796		offset = -EINVAL;
 797		goto out;
 798	}
 799
 800	tas_fmw->programs = kcalloc(tas_fmw->nr_programs,
 801		sizeof(struct tasdevice_prog), GFP_KERNEL);
 802	if (!tas_fmw->programs) {
 803		offset = -ENOMEM;
 804		goto out;
 805	}
 806
 807	for (i = 0; i < tas_fmw->nr_programs; i++) {
 808		program = &(tas_fmw->programs[i]);
 809		program->prog_size = get_unaligned_be32(&buf[offset]);
 810		offset += 4;
 811	}
 812
 813	/* Skip the unused prog_size */
 814	offset += 4 * (TASDEVICE_MAXPROGRAM_NUM_KERNEL - tas_fmw->nr_programs);
 815
 816	tas_fmw->nr_configurations = get_unaligned_be32(&buf[offset]);
 817	offset += 4;
 818
 819	/* The max number of config in firmware greater than 4 pieces of
 820	 * tas2781s is different from the one lower than 4 pieces of
 821	 * tas2781s.
 822	 */
 823	max_confs = (fw_hdr->ndev >= 4) ?
 824		TASDEVICE_MAXCONFIG_NUM_KERNEL_MULTIPLE_AMPS :
 825		TASDEVICE_MAXCONFIG_NUM_KERNEL;
 826	if (tas_fmw->nr_configurations == 0 ||
 827		tas_fmw->nr_configurations > max_confs) {
 828		dev_err(tas_priv->dev, "%s: Conf is invalid\n", __func__);
 829		offset = -EINVAL;
 830		goto out;
 831	}
 832
 833	if (offset + 4 * max_confs > fmw->size) {
 834		dev_err(tas_priv->dev, "%s: mpConfigurations err\n", __func__);
 835		offset = -EINVAL;
 836		goto out;
 837	}
 838
 839	tas_fmw->configs = kcalloc(tas_fmw->nr_configurations,
 840		sizeof(struct tasdevice_config), GFP_KERNEL);
 841	if (!tas_fmw->configs) {
 842		offset = -ENOMEM;
 843		goto out;
 844	}
 845
 846	for (i = 0; i < tas_fmw->nr_programs; i++) {
 847		config = &(tas_fmw->configs[i]);
 848		config->cfg_size = get_unaligned_be32(&buf[offset]);
 849		offset += 4;
 850	}
 851
 852	/* Skip the unused configs */
 853	offset += 4 * (max_confs - tas_fmw->nr_programs);
 854
 855out:
 856	return offset;
 857}
 858
 859static int tasdevice_process_block(void *context, unsigned char *data,
 860	unsigned char dev_idx, int sublocksize)
 861{
 862	struct tasdevice_priv *tas_priv = (struct tasdevice_priv *)context;
 863	int subblk_offset, chn, chnend, rc;
 864	unsigned char subblk_typ = data[1];
 865	int blktyp = dev_idx & 0xC0;
 866	int idx = dev_idx & 0x3F;
 867	bool is_err = false;
 868
 869	if (idx) {
 870		chn = idx - 1;
 871		chnend = idx;
 872	} else {
 873		if (tas_priv->isspi) {
 874			chn = tas_priv->index;
 875			chnend = chn + 1;
 876		} else {
 877			chn = 0;
 878			chnend = tas_priv->ndev;
 879		}
 880	}
 881
 882	for (; chn < chnend; chn++) {
 883		if (tas_priv->tasdevice[chn].is_loading == false)
 884			continue;
 885
 886		is_err = false;
 887		subblk_offset = 2;
 888		switch (subblk_typ) {
 889		case TASDEVICE_CMD_SING_W: {
 890			int i;
 891			unsigned short len = get_unaligned_be16(&data[2]);
 892
 893			subblk_offset += 2;
 894			if (subblk_offset + 4 * len > sublocksize) {
 895				dev_err(tas_priv->dev,
 896					"process_block: Out of boundary\n");
 897				is_err = true;
 898				break;
 899			}
 900
 901			for (i = 0; i < len; i++) {
 902				rc = tasdevice_dev_write(tas_priv, chn,
 903					TASDEVICE_REG(data[subblk_offset],
 904						data[subblk_offset + 1],
 905						data[subblk_offset + 2]),
 906					data[subblk_offset + 3]);
 907				if (rc < 0) {
 908					is_err = true;
 909					dev_err(tas_priv->dev,
 910					"process_block: single write error\n");
 911				}
 912				subblk_offset += 4;
 913			}
 914		}
 915			break;
 916		case TASDEVICE_CMD_BURST: {
 917			unsigned short len = get_unaligned_be16(&data[2]);
 918
 919			subblk_offset += 2;
 920			if (subblk_offset + 4 + len > sublocksize) {
 921				dev_err(tas_priv->dev,
 922					"%s: BST Out of boundary\n",
 923					__func__);
 924				is_err = true;
 925				break;
 926			}
 927			if (len % 4) {
 928				dev_err(tas_priv->dev,
 929					"%s:Bst-len(%u)not div by 4\n",
 930					__func__, len);
 931				break;
 932			}
 933
 934			rc = tasdevice_dev_bulk_write(tas_priv, chn,
 935				TASDEVICE_REG(data[subblk_offset],
 936				data[subblk_offset + 1],
 937				data[subblk_offset + 2]),
 938				&(data[subblk_offset + 4]), len);
 939			if (rc < 0) {
 940				is_err = true;
 941				dev_err(tas_priv->dev,
 942					"%s: bulk_write error = %d\n",
 943					__func__, rc);
 944			}
 945			subblk_offset += (len + 4);
 946		}
 947			break;
 948		case TASDEVICE_CMD_DELAY: {
 949			unsigned int sleep_time = 0;
 950
 951			if (subblk_offset + 2 > sublocksize) {
 952				dev_err(tas_priv->dev,
 953					"%s: delay Out of boundary\n",
 954					__func__);
 955				is_err = true;
 956				break;
 957			}
 958			sleep_time = get_unaligned_be16(&data[2]) * 1000;
 959			usleep_range(sleep_time, sleep_time + 50);
 960			subblk_offset += 2;
 961		}
 962			break;
 963		case TASDEVICE_CMD_FIELD_W:
 964			if (subblk_offset + 6 > sublocksize) {
 965				dev_err(tas_priv->dev,
 966					"%s: bit write Out of boundary\n",
 967					__func__);
 968				is_err = true;
 969				break;
 970			}
 971			rc = tas_priv->update_bits(tas_priv, chn,
 972				TASDEVICE_REG(data[subblk_offset + 2],
 973				data[subblk_offset + 3],
 974				data[subblk_offset + 4]),
 975				data[subblk_offset + 1],
 976				data[subblk_offset + 5]);
 977			if (rc < 0) {
 978				is_err = true;
 979				dev_err(tas_priv->dev,
 980					"%s: update_bits error = %d\n",
 981					__func__, rc);
 982			}
 983			subblk_offset += 6;
 984			break;
 985		default:
 986			break;
 987		}
 988		if (is_err == true && blktyp != 0) {
 989			if (blktyp == 0x80) {
 990				tas_priv->tasdevice[chn].cur_prog = -1;
 991				tas_priv->tasdevice[chn].cur_conf = -1;
 992			} else
 993				tas_priv->tasdevice[chn].cur_conf = -1;
 994		}
 995	}
 996
 997	return subblk_offset;
 998}
 999
1000void tasdevice_select_cfg_blk(void *pContext, int conf_no,
1001	unsigned char block_type)
1002{
1003	struct tasdevice_priv *tas_priv = (struct tasdevice_priv *) pContext;
1004	struct tasdevice_rca *rca = &(tas_priv->rcabin);
1005	struct tasdevice_config_info **cfg_info = rca->cfg_info;
1006	struct tasdev_blk_data **blk_data;
1007	int j, k, chn, chnend;
1008
1009	if (conf_no >= rca->ncfgs || conf_no < 0 || !cfg_info) {
1010		dev_err(tas_priv->dev, "conf_no should be not more than %u\n",
1011			rca->ncfgs);
1012		return;
1013	}
1014	blk_data = cfg_info[conf_no]->blk_data;
1015
1016	for (j = 0; j < (int)cfg_info[conf_no]->real_nblocks; j++) {
1017		unsigned int length = 0, rc = 0;
1018
1019		if (block_type > 5 || block_type < 2) {
1020			dev_err(tas_priv->dev,
1021				"block_type should be in range from 2 to 5\n");
1022			break;
1023		}
1024		if (block_type != blk_data[j]->block_type)
1025			continue;
1026
1027		for (k = 0; k < (int)blk_data[j]->n_subblks; k++) {
1028			if (blk_data[j]->dev_idx) {
1029				chn = blk_data[j]->dev_idx - 1;
1030				chnend = blk_data[j]->dev_idx;
1031			} else {
1032				chn = 0;
1033				chnend = tas_priv->ndev;
1034			}
1035			for (; chn < chnend; chn++)
1036				tas_priv->tasdevice[chn].is_loading = true;
1037
1038			rc = tasdevice_process_block(tas_priv,
1039				blk_data[j]->regdata + length,
1040				blk_data[j]->dev_idx,
1041				blk_data[j]->block_size - length);
1042			length += rc;
1043			if (blk_data[j]->block_size < length) {
1044				dev_err(tas_priv->dev,
1045					"%s: %u %u out of boundary\n",
1046					__func__, length,
1047					blk_data[j]->block_size);
1048				break;
1049			}
1050		}
1051		if (length != blk_data[j]->block_size)
1052			dev_err(tas_priv->dev, "%s: %u %u size is not same\n",
1053				__func__, length, blk_data[j]->block_size);
1054	}
1055}
1056EXPORT_SYMBOL_NS_GPL(tasdevice_select_cfg_blk, "SND_SOC_TAS2781_FMWLIB");
1057
1058static int tasdevice_load_block_kernel(
1059	struct tasdevice_priv *tasdevice, struct tasdev_blk *block)
1060{
1061	const unsigned int blk_size = block->blk_size;
1062	unsigned int i, length;
1063	unsigned char *data = block->data;
1064
1065	for (i = 0, length = 0; i < block->nr_subblocks; i++) {
1066		int rc = tasdevice_process_block(tasdevice, data + length,
1067			block->dev_idx, blk_size - length);
1068		if (rc < 0) {
1069			dev_err(tasdevice->dev,
1070				"%s: %u %u sublock write error\n",
1071				__func__, length, blk_size);
1072			break;
1073		}
1074		length += (unsigned int)rc;
1075		if (blk_size < length) {
1076			dev_err(tasdevice->dev, "%s: %u %u out of boundary\n",
1077				__func__, length, blk_size);
1078			break;
1079		}
1080	}
1081
1082	return 0;
1083}
1084
1085static int fw_parse_variable_hdr(struct tasdevice_priv
1086	*tas_priv, struct tasdevice_dspfw_hdr *fw_hdr,
1087	const struct firmware *fmw, int offset)
1088{
1089	const unsigned char *buf = fmw->data;
1090	int len = strlen((char *)&buf[offset]);
1091
1092	len++;
1093
1094	if (offset + len + 8 > fmw->size) {
1095		dev_err(tas_priv->dev, "%s: File Size error\n", __func__);
1096		offset = -EINVAL;
1097		goto out;
1098	}
1099
1100	offset += len;
1101
1102	fw_hdr->device_family = get_unaligned_be32(&buf[offset]);
1103	if (fw_hdr->device_family != 0) {
1104		dev_err(tas_priv->dev, "%s: not TAS device\n", __func__);
1105		offset = -EINVAL;
1106		goto out;
1107	}
1108	offset += 4;
1109
1110	fw_hdr->device = get_unaligned_be32(&buf[offset]);
1111	if (fw_hdr->device >= TASDEVICE_DSP_TAS_MAX_DEVICE ||
1112		fw_hdr->device == 6) {
1113		dev_err(tas_priv->dev, "Unsupported dev %d\n", fw_hdr->device);
1114		offset = -EINVAL;
1115		goto out;
1116	}
1117	offset += 4;
1118	fw_hdr->ndev = deviceNumber[fw_hdr->device];
1119
1120out:
1121	return offset;
1122}
1123
1124static int fw_parse_variable_header_git(struct tasdevice_priv
1125	*tas_priv, const struct firmware *fmw, int offset)
1126{
1127	struct tasdevice_fw *tas_fmw = tas_priv->fmw;
1128	struct tasdevice_dspfw_hdr *fw_hdr = &(tas_fmw->fw_hdr);
1129
1130	offset = fw_parse_variable_hdr(tas_priv, fw_hdr, fmw, offset);
1131	if (offset < 0)
1132		goto out;
1133	if (fw_hdr->ndev != tas_priv->ndev) {
1134		dev_err(tas_priv->dev,
1135			"%s: ndev(%u) in dspbin mismatch ndev(%u) in DTS\n",
1136			__func__, fw_hdr->ndev, tas_priv->ndev);
1137		offset = -EINVAL;
1138	}
1139
1140out:
1141	return offset;
1142}
1143
1144static int fw_parse_block_data(struct tasdevice_fw *tas_fmw,
1145	struct tasdev_blk *block, const struct firmware *fmw, int offset)
1146{
1147	unsigned char *data = (unsigned char *)fmw->data;
1148	int n;
1149
1150	if (offset + 8 > fmw->size) {
1151		dev_err(tas_fmw->dev, "%s: Type error\n", __func__);
1152		offset = -EINVAL;
1153		goto out;
1154	}
1155	block->type = get_unaligned_be32(&data[offset]);
1156	offset += 4;
1157
1158	if (tas_fmw->fw_hdr.fixed_hdr.drv_ver >= PPC_DRIVER_CRCCHK) {
1159		if (offset + 8 > fmw->size) {
1160			dev_err(tas_fmw->dev, "PChkSumPresent error\n");
1161			offset = -EINVAL;
1162			goto out;
1163		}
1164		block->is_pchksum_present = data[offset];
1165		offset++;
1166
1167		block->pchksum = data[offset];
1168		offset++;
1169
1170		block->is_ychksum_present = data[offset];
1171		offset++;
1172
1173		block->ychksum = data[offset];
1174		offset++;
1175	} else {
1176		block->is_pchksum_present = 0;
1177		block->is_ychksum_present = 0;
1178	}
1179
1180	block->nr_cmds = get_unaligned_be32(&data[offset]);
1181	offset += 4;
1182
1183	n = block->nr_cmds * 4;
1184	if (offset + n > fmw->size) {
1185		dev_err(tas_fmw->dev,
1186			"%s: File Size(%lu) error offset = %d n = %d\n",
1187			__func__, (unsigned long)fmw->size, offset, n);
1188		offset = -EINVAL;
1189		goto out;
1190	}
1191	/* instead of kzalloc+memcpy */
1192	block->data = kmemdup(&data[offset], n, GFP_KERNEL);
1193	if (!block->data) {
1194		offset = -ENOMEM;
1195		goto out;
1196	}
1197	offset += n;
1198
1199out:
1200	return offset;
1201}
1202
1203/* When parsing error occurs, all the memory resource will be released
1204 * in the end of tasdevice_rca_ready.
1205 */
1206static int fw_parse_data(struct tasdevice_fw *tas_fmw,
1207	struct tasdevice_data *img_data, const struct firmware *fmw,
1208	int offset)
1209{
1210	const unsigned char *data = (unsigned char *)fmw->data;
1211	struct tasdev_blk *blk;
1212	unsigned int i;
1213	int n;
1214
1215	if (offset + 64 > fmw->size) {
1216		dev_err(tas_fmw->dev, "%s: Name error\n", __func__);
1217		offset = -EINVAL;
1218		goto out;
1219	}
1220	memcpy(img_data->name, &data[offset], 64);
1221	offset += 64;
1222
1223	n = strlen((char *)&data[offset]);
1224	n++;
1225	if (offset + n + 2 > fmw->size) {
1226		dev_err(tas_fmw->dev, "%s: Description error\n", __func__);
1227		offset = -EINVAL;
1228		goto out;
1229	}
1230	offset += n;
1231	img_data->nr_blk = get_unaligned_be16(&data[offset]);
1232	offset += 2;
1233
1234	img_data->dev_blks = kcalloc(img_data->nr_blk,
1235		sizeof(struct tasdev_blk), GFP_KERNEL);
1236	if (!img_data->dev_blks) {
1237		offset = -ENOMEM;
1238		goto out;
1239	}
1240	for (i = 0; i < img_data->nr_blk; i++) {
1241		blk = &(img_data->dev_blks[i]);
1242		offset = fw_parse_block_data(tas_fmw, blk, fmw, offset);
1243		if (offset < 0) {
1244			offset = -EINVAL;
1245			goto out;
1246		}
1247	}
1248
1249out:
1250	return offset;
1251}
1252
1253/* When parsing error occurs, all the memory resource will be released
1254 * in the end of tasdevice_rca_ready.
1255 */
1256static int fw_parse_program_data(struct tasdevice_priv *tas_priv,
1257	struct tasdevice_fw *tas_fmw, const struct firmware *fmw, int offset)
1258{
1259	unsigned char *buf = (unsigned char *)fmw->data;
1260	struct tasdevice_prog *program;
1261	int i;
1262
1263	if (offset + 2 > fmw->size) {
1264		dev_err(tas_priv->dev, "%s: File Size error\n", __func__);
1265		offset = -EINVAL;
1266		goto out;
1267	}
1268	tas_fmw->nr_programs = get_unaligned_be16(&buf[offset]);
1269	offset += 2;
1270
1271	if (tas_fmw->nr_programs == 0) {
1272		/*Not error in calibration Data file, return directly*/
1273		dev_info(tas_priv->dev, "%s: No Programs data, maybe calbin\n",
1274			__func__);
1275		goto out;
1276	}
1277
1278	tas_fmw->programs =
1279		kcalloc(tas_fmw->nr_programs, sizeof(struct tasdevice_prog),
1280			GFP_KERNEL);
1281	if (!tas_fmw->programs) {
1282		offset = -ENOMEM;
1283		goto out;
1284	}
1285	for (i = 0; i < tas_fmw->nr_programs; i++) {
1286		int n = 0;
1287
1288		program = &(tas_fmw->programs[i]);
1289		if (offset + 64 > fmw->size) {
1290			dev_err(tas_priv->dev, "%s: mpName error\n", __func__);
1291			offset = -EINVAL;
1292			goto out;
1293		}
1294		offset += 64;
1295
1296		n = strlen((char *)&buf[offset]);
1297		/* skip '\0' and 5 unused bytes */
1298		n += 6;
1299		if (offset + n > fmw->size) {
1300			dev_err(tas_priv->dev, "Description err\n");
1301			offset = -EINVAL;
1302			goto out;
1303		}
1304
1305		offset += n;
1306
1307		offset = fw_parse_data(tas_fmw, &(program->dev_data), fmw,
1308			offset);
1309		if (offset < 0)
1310			goto out;
1311	}
1312
1313out:
1314	return offset;
1315}
1316
1317/* When parsing error occurs, all the memory resource will be released
1318 * in the end of tasdevice_rca_ready.
1319 */
1320static int fw_parse_configuration_data(
1321	struct tasdevice_priv *tas_priv,
1322	struct tasdevice_fw *tas_fmw,
1323	const struct firmware *fmw, int offset)
1324{
1325	unsigned char *data = (unsigned char *)fmw->data;
1326	struct tasdevice_config *config;
1327	unsigned int i;
1328	int n;
1329
1330	if (offset + 2 > fmw->size) {
1331		dev_err(tas_priv->dev, "%s: File Size error\n", __func__);
1332		offset = -EINVAL;
1333		goto out;
1334	}
1335	tas_fmw->nr_configurations = get_unaligned_be16(&data[offset]);
1336	offset += 2;
1337
1338	if (tas_fmw->nr_configurations == 0) {
1339		dev_err(tas_priv->dev, "%s: Conf is zero\n", __func__);
1340		/*Not error for calibration Data file, return directly*/
1341		goto out;
1342	}
1343	tas_fmw->configs = kcalloc(tas_fmw->nr_configurations,
1344			sizeof(struct tasdevice_config), GFP_KERNEL);
1345	if (!tas_fmw->configs) {
1346		offset = -ENOMEM;
1347		goto out;
1348	}
1349	for (i = 0; i < tas_fmw->nr_configurations; i++) {
1350		config = &(tas_fmw->configs[i]);
1351		if (offset + 64 > fmw->size) {
1352			dev_err(tas_priv->dev, "File Size err\n");
1353			offset = -EINVAL;
1354			goto out;
1355		}
1356		memcpy(config->name, &data[offset], 64);
1357		offset += 64;
1358
1359		n = strlen((char *)&data[offset]);
1360		n += 15;
1361		if (offset + n > fmw->size) {
1362			dev_err(tas_priv->dev, "Description err\n");
1363			offset = -EINVAL;
1364			goto out;
1365		}
1366
1367		offset += n;
1368
1369		offset = fw_parse_data(tas_fmw, &(config->dev_data),
1370			fmw, offset);
1371		if (offset < 0)
1372			goto out;
1373	}
1374
1375out:
1376	return offset;
1377}
1378
1379static bool check_inpage_yram_rg(struct tas_crc *cd,
1380	unsigned char reg, unsigned char len)
1381{
1382	bool in = false;
1383
1384
1385	if (reg <= TAS2781_YRAM5_END_REG &&
1386		reg >= TAS2781_YRAM5_START_REG) {
1387		if (reg + len > TAS2781_YRAM5_END_REG)
1388			cd->len = TAS2781_YRAM5_END_REG - reg + 1;
1389		else
1390			cd->len = len;
1391		cd->offset = reg;
1392		in = true;
1393	} else if (reg < TAS2781_YRAM5_START_REG) {
1394		if (reg + len > TAS2781_YRAM5_START_REG) {
1395			cd->offset = TAS2781_YRAM5_START_REG;
1396			cd->len = len - TAS2781_YRAM5_START_REG + reg;
1397			in = true;
1398		}
1399	}
1400
1401	return in;
1402}
1403
1404static bool check_inpage_yram_bk1(struct tas_crc *cd,
1405	unsigned char page, unsigned char reg, unsigned char len)
1406{
1407	bool in = false;
1408
1409	if (page == TAS2781_YRAM1_PAGE) {
1410		if (reg >= TAS2781_YRAM1_START_REG) {
1411			cd->offset = reg;
1412			cd->len = len;
1413			in = true;
1414		} else if (reg + len > TAS2781_YRAM1_START_REG) {
1415			cd->offset = TAS2781_YRAM1_START_REG;
1416			cd->len = len - TAS2781_YRAM1_START_REG + reg;
1417			in = true;
1418		}
1419	} else if (page == TAS2781_YRAM3_PAGE)
1420		in = check_inpage_yram_rg(cd, reg, len);
1421
1422	return in;
1423}
1424
1425/* Return Code:
1426 * true -- the registers are in the inpage yram
1427 * false -- the registers are NOT in the inpage yram
1428 */
1429static bool check_inpage_yram(struct tas_crc *cd, unsigned char book,
1430	unsigned char page, unsigned char reg, unsigned char len)
1431{
1432	bool in = false;
1433
1434	if (book == TAS2781_YRAM_BOOK1) {
1435		in = check_inpage_yram_bk1(cd, page, reg, len);
1436		goto end;
1437	}
1438	if (book == TAS2781_YRAM_BOOK2 && page == TAS2781_YRAM5_PAGE)
1439		in = check_inpage_yram_rg(cd, reg, len);
1440
1441end:
1442	return in;
1443}
1444
1445static bool check_inblock_yram_bk(struct tas_crc *cd,
1446	unsigned char page, unsigned char reg, unsigned char len)
1447{
1448	bool in = false;
1449
1450	if ((page >= TAS2781_YRAM4_START_PAGE &&
1451		page <= TAS2781_YRAM4_END_PAGE) ||
1452		(page >= TAS2781_YRAM2_START_PAGE &&
1453		page <= TAS2781_YRAM2_END_PAGE)) {
1454		if (reg <= TAS2781_YRAM2_END_REG &&
1455			reg >= TAS2781_YRAM2_START_REG) {
1456			cd->offset = reg;
1457			cd->len = len;
1458			in = true;
1459		} else if (reg < TAS2781_YRAM2_START_REG) {
1460			if (reg + len - 1 >= TAS2781_YRAM2_START_REG) {
1461				cd->offset = TAS2781_YRAM2_START_REG;
1462				cd->len = reg + len - TAS2781_YRAM2_START_REG;
1463				in = true;
1464			}
1465		}
1466	}
1467
1468	return in;
1469}
1470
1471/* Return Code:
1472 * true -- the registers are in the inblock yram
1473 * false -- the registers are NOT in the inblock yram
1474 */
1475static bool check_inblock_yram(struct tas_crc *cd, unsigned char book,
1476	unsigned char page, unsigned char reg, unsigned char len)
1477{
1478	bool in = false;
1479
1480	if (book == TAS2781_YRAM_BOOK1 || book == TAS2781_YRAM_BOOK2)
1481		in = check_inblock_yram_bk(cd, page, reg, len);
1482
1483	return in;
1484}
1485
1486static bool check_yram(struct tas_crc *cd, unsigned char book,
1487	unsigned char page, unsigned char reg, unsigned char len)
1488{
1489	bool in;
1490
1491	in = check_inpage_yram(cd, book, page, reg, len);
1492	if (in)
1493		goto end;
1494	in = check_inblock_yram(cd, book, page, reg, len);
1495
1496end:
1497	return in;
1498}
1499
1500static int tasdev_multibytes_chksum(struct tasdevice_priv *tasdevice,
1501	unsigned short chn, unsigned char book, unsigned char page,
1502	unsigned char reg, unsigned int len)
1503{
1504	struct tas_crc crc_data;
1505	unsigned char crc_chksum = 0;
1506	unsigned char nBuf1[128];
1507	int ret = 0;
1508	int i;
1509	bool in;
1510
1511	if ((reg + len - 1) > 127) {
1512		ret = -EINVAL;
1513		dev_err(tasdevice->dev, "firmware error\n");
1514		goto end;
1515	}
1516
1517	if ((book == TASDEVICE_BOOK_ID(TAS2781_SA_COEFF_SWAP_REG))
1518		&& (page == TASDEVICE_PAGE_ID(TAS2781_SA_COEFF_SWAP_REG))
1519		&& (reg == TASDEVICE_PAGE_REG(TAS2781_SA_COEFF_SWAP_REG))
1520		&& (len == 4)) {
1521		/*DSP swap command, pass */
1522		ret = 0;
1523		goto end;
1524	}
1525
1526	in = check_yram(&crc_data, book, page, reg, len);
1527	if (!in)
1528		goto end;
1529
1530	if (len == 1) {
1531		dev_err(tasdevice->dev, "firmware error\n");
1532		ret = -EINVAL;
1533		goto end;
1534	}
1535
1536	ret = tasdevice->dev_bulk_read(tasdevice, chn,
1537		TASDEVICE_REG(book, page, crc_data.offset),
1538		nBuf1, crc_data.len);
1539	if (ret < 0)
1540		goto end;
1541
1542	for (i = 0; i < crc_data.len; i++) {
1543		if ((book == TASDEVICE_BOOK_ID(TAS2781_SA_COEFF_SWAP_REG))
1544			&& (page == TASDEVICE_PAGE_ID(
1545			TAS2781_SA_COEFF_SWAP_REG))
1546			&& ((i + crc_data.offset)
1547			>= TASDEVICE_PAGE_REG(TAS2781_SA_COEFF_SWAP_REG))
1548			&& ((i + crc_data.offset)
1549			<= (TASDEVICE_PAGE_REG(TAS2781_SA_COEFF_SWAP_REG)
1550			+ 4)))
1551			/*DSP swap command, bypass */
1552			continue;
1553		else
1554			crc_chksum += crc8(tasdevice->crc8_lkp_tbl, &nBuf1[i],
1555				1, 0);
1556	}
1557
1558	ret = crc_chksum;
1559
1560end:
1561	return ret;
1562}
1563
1564static int do_singlereg_checksum(struct tasdevice_priv *tasdevice,
1565	unsigned short chl, unsigned char book, unsigned char page,
1566	unsigned char reg, unsigned char val)
1567{
1568	struct tas_crc crc_data;
1569	unsigned int nData1;
1570	int ret = 0;
1571	bool in;
1572
1573	if ((book == TASDEVICE_BOOK_ID(TAS2781_SA_COEFF_SWAP_REG))
1574		&& (page == TASDEVICE_PAGE_ID(TAS2781_SA_COEFF_SWAP_REG))
1575		&& (reg >= TASDEVICE_PAGE_REG(TAS2781_SA_COEFF_SWAP_REG))
1576		&& (reg <= (TASDEVICE_PAGE_REG(
1577		TAS2781_SA_COEFF_SWAP_REG) + 4))) {
1578		/*DSP swap command, pass */
1579		ret = 0;
1580		goto end;
1581	}
1582
1583	in = check_yram(&crc_data, book, page, reg, 1);
1584	if (!in)
1585		goto end;
1586	ret = tasdevice->dev_read(tasdevice, chl,
1587		TASDEVICE_REG(book, page, reg), &nData1);
1588	if (ret < 0)
1589		goto end;
1590
1591	if (nData1 != val) {
1592		dev_err(tasdevice->dev,
1593			"B[0x%x]P[0x%x]R[0x%x] W[0x%x], R[0x%x]\n",
1594			book, page, reg, val, nData1);
1595		tasdevice->tasdevice[chl].err_code |= ERROR_YRAM_CRCCHK;
1596		ret = -EAGAIN;
1597		goto end;
1598	}
1599
1600	ret = crc8(tasdevice->crc8_lkp_tbl, &val, 1, 0);
1601
1602end:
1603	return ret;
1604}
1605
1606static void set_err_prg_cfg(unsigned int type, struct tasdevice *dev)
1607{
1608	if ((type == MAIN_ALL_DEVICES) || (type == MAIN_DEVICE_A)
1609		|| (type == MAIN_DEVICE_B) || (type == MAIN_DEVICE_C)
1610		|| (type == MAIN_DEVICE_D))
1611		dev->cur_prog = -1;
1612	else
1613		dev->cur_conf = -1;
1614}
1615
1616static int tasdev_bytes_chksum(struct tasdevice_priv *tas_priv,
1617	struct tasdev_blk *block, int chn, unsigned char book,
1618	unsigned char page, unsigned char reg, unsigned int len,
1619	unsigned char val, unsigned char *crc_chksum)
1620{
1621	int ret;
1622
1623	if (len > 1)
1624		ret = tasdev_multibytes_chksum(tas_priv, chn, book, page, reg,
1625			len);
1626	else
1627		ret = do_singlereg_checksum(tas_priv, chn, book, page, reg,
1628			val);
1629
1630	if (ret > 0) {
1631		*crc_chksum += (unsigned char)ret;
1632		goto end;
1633	}
1634
1635	if (ret != -EAGAIN)
1636		goto end;
1637
1638	block->nr_retry--;
1639	if (block->nr_retry > 0)
1640		goto end;
1641
1642	set_err_prg_cfg(block->type, &tas_priv->tasdevice[chn]);
1643
1644end:
1645	return ret;
1646}
1647
1648static int tasdev_multibytes_wr(struct tasdevice_priv *tas_priv,
1649	struct tasdev_blk *block, int chn, unsigned char book,
1650	unsigned char page, unsigned char reg, unsigned char *data,
1651	unsigned int len, unsigned int *nr_cmds,
1652	unsigned char *crc_chksum)
1653{
1654	int ret;
1655
1656	if (len > 1) {
1657		ret = tasdevice_dev_bulk_write(tas_priv, chn,
1658			TASDEVICE_REG(book, page, reg), data + 3, len);
1659		if (ret < 0)
1660			goto end;
1661		if (block->is_ychksum_present)
1662			ret = tasdev_bytes_chksum(tas_priv, block, chn,
1663				book, page, reg, len, 0, crc_chksum);
1664	} else {
1665		ret = tasdevice_dev_write(tas_priv, chn,
1666			TASDEVICE_REG(book, page, reg), data[3]);
1667		if (ret < 0)
1668			goto end;
1669		if (block->is_ychksum_present)
1670			ret = tasdev_bytes_chksum(tas_priv, block, chn, book,
1671				page, reg, 1, data[3], crc_chksum);
1672	}
1673
1674	if (!block->is_ychksum_present || ret >= 0) {
1675		*nr_cmds += 1;
1676		if (len >= 2)
1677			*nr_cmds += ((len - 2) / 4) + 1;
1678	}
1679
1680end:
1681	return ret;
1682}
1683
1684static int tasdev_block_chksum(struct tasdevice_priv *tas_priv,
1685	struct tasdev_blk *block, int chn)
1686{
1687	unsigned int nr_value;
1688	int ret;
1689
1690	ret = tas_priv->dev_read(tas_priv, chn, TASDEVICE_CHECKSUM_REG,
1691		&nr_value);
1692	if (ret < 0) {
1693		dev_err(tas_priv->dev, "%s: Chn %d\n", __func__, chn);
1694		set_err_prg_cfg(block->type, &tas_priv->tasdevice[chn]);
1695		goto end;
1696	}
1697
1698	if ((nr_value & 0xff) != block->pchksum) {
1699		dev_err(tas_priv->dev, "%s: Blk PChkSum Chn %d ", __func__,
1700			chn);
1701		dev_err(tas_priv->dev, "PChkSum = 0x%x, Reg = 0x%x\n",
1702			block->pchksum, (nr_value & 0xff));
1703		tas_priv->tasdevice[chn].err_code |= ERROR_PRAM_CRCCHK;
1704		ret = -EAGAIN;
1705		block->nr_retry--;
1706
1707		if (block->nr_retry <= 0)
1708			set_err_prg_cfg(block->type,
1709				&tas_priv->tasdevice[chn]);
1710	} else
1711		tas_priv->tasdevice[chn].err_code &= ~ERROR_PRAM_CRCCHK;
1712
1713end:
1714	return ret;
1715}
1716
1717static int tasdev_load_blk(struct tasdevice_priv *tas_priv,
1718	struct tasdev_blk *block, int chn)
1719{
1720	unsigned int sleep_time;
1721	unsigned int len;
1722	unsigned int nr_cmds;
1723	unsigned char *data;
1724	unsigned char crc_chksum = 0;
1725	unsigned char offset;
1726	unsigned char book;
1727	unsigned char page;
1728	unsigned char val;
1729	int ret = 0;
1730
1731	while (block->nr_retry > 0) {
1732		if (block->is_pchksum_present) {
1733			ret = tasdevice_dev_write(tas_priv, chn,
1734				TASDEVICE_CHECKSUM_REG, 0);
1735			if (ret < 0)
1736				break;
1737		}
1738
1739		if (block->is_ychksum_present)
1740			crc_chksum = 0;
1741
1742		nr_cmds = 0;
1743
1744		while (nr_cmds < block->nr_cmds) {
1745			data = block->data + nr_cmds * 4;
1746
1747			book = data[0];
1748			page = data[1];
1749			offset = data[2];
1750			val = data[3];
1751
1752			nr_cmds++;
1753			/*Single byte write*/
1754			if (offset <= 0x7F) {
1755				ret = tasdevice_dev_write(tas_priv, chn,
1756					TASDEVICE_REG(book, page, offset),
1757					val);
1758				if (ret < 0)
1759					goto end;
1760				if (block->is_ychksum_present) {
1761					ret = tasdev_bytes_chksum(tas_priv,
1762						block, chn, book, page, offset,
1763						1, val, &crc_chksum);
1764					if (ret < 0)
1765						break;
1766				}
1767				continue;
1768			}
1769			/*sleep command*/
1770			if (offset == 0x81) {
1771				/*book -- data[0] page -- data[1]*/
1772				sleep_time = ((book << 8) + page)*1000;
1773				usleep_range(sleep_time, sleep_time + 50);
1774				continue;
1775			}
1776			/*Multiple bytes write*/
1777			if (offset == 0x85) {
1778				data += 4;
1779				len = (book << 8) + page;
1780				book = data[0];
1781				page = data[1];
1782				offset = data[2];
1783				ret = tasdev_multibytes_wr(tas_priv,
1784					block, chn, book, page, offset, data,
1785					len, &nr_cmds, &crc_chksum);
1786				if (ret < 0)
1787					break;
1788			}
1789		}
1790		if (ret == -EAGAIN) {
1791			if (block->nr_retry > 0)
1792				continue;
1793		} else if (ret < 0) /*err in current device, skip it*/
1794			break;
1795
1796		if (block->is_pchksum_present) {
1797			ret = tasdev_block_chksum(tas_priv, block, chn);
1798			if (ret == -EAGAIN) {
1799				if (block->nr_retry > 0)
1800					continue;
1801			} else if (ret < 0) /*err in current device, skip it*/
1802				break;
1803		}
1804
1805		if (block->is_ychksum_present) {
1806			/* TBD, open it when FW ready */
1807			dev_err(tas_priv->dev,
1808				"Blk YChkSum: FW = 0x%x, YCRC = 0x%x\n",
1809				block->ychksum, crc_chksum);
1810
1811			tas_priv->tasdevice[chn].err_code &=
1812				~ERROR_YRAM_CRCCHK;
1813			ret = 0;
1814		}
1815		/*skip current blk*/
1816		break;
1817	}
1818
1819end:
1820	return ret;
1821}
1822
1823static int tasdevice_load_block(struct tasdevice_priv *tas_priv,
1824	struct tasdev_blk *block)
1825{
1826	int chnend = 0;
1827	int ret = 0;
1828	int chn = 0;
1829	int rc = 0;
1830
1831	switch (block->type) {
1832	case MAIN_ALL_DEVICES:
1833		chn = 0;
1834		chnend = tas_priv->ndev;
1835		break;
1836	case MAIN_DEVICE_A:
1837	case COEFF_DEVICE_A:
1838	case PRE_DEVICE_A:
1839		chn = 0;
1840		chnend = 1;
1841		break;
1842	case MAIN_DEVICE_B:
1843	case COEFF_DEVICE_B:
1844	case PRE_DEVICE_B:
1845		chn = 1;
1846		chnend = 2;
1847		break;
1848	case MAIN_DEVICE_C:
1849	case COEFF_DEVICE_C:
1850	case PRE_DEVICE_C:
1851		chn = 2;
1852		chnend = 3;
1853		break;
1854	case MAIN_DEVICE_D:
1855	case COEFF_DEVICE_D:
1856	case PRE_DEVICE_D:
1857		chn = 3;
1858		chnend = 4;
1859		break;
1860	default:
1861		dev_dbg(tas_priv->dev, "load blk: Other Type = 0x%02x\n",
1862			block->type);
1863		break;
1864	}
1865
1866	for (; chn < chnend; chn++) {
1867		block->nr_retry = 6;
1868		if (tas_priv->tasdevice[chn].is_loading == false)
1869			continue;
1870		ret = tasdev_load_blk(tas_priv, block, chn);
1871		if (ret < 0)
1872			dev_err(tas_priv->dev, "dev %d, Blk (%d) load error\n",
1873				chn, block->type);
1874		rc |= ret;
1875	}
1876
1877	return rc;
1878}
1879
1880static void dspbin_type_check(struct tasdevice_priv *tas_priv,
1881	unsigned int ppcver)
1882{
1883	if (ppcver >= PPC3_VERSION_TAS2781_ALPHA_MIN) {
1884		if (ppcver >= PPC3_VERSION_TAS2781_BETA_MIN)
1885			tas_priv->dspbin_typ = TASDEV_BETA;
1886		else if (ppcver >= PPC3_VERSION_TAS2781_BASIC_MIN)
1887			tas_priv->dspbin_typ = TASDEV_BASIC;
1888		else
1889			tas_priv->dspbin_typ = TASDEV_ALPHA;
1890	}
1891	if ((tas_priv->dspbin_typ != TASDEV_BASIC) &&
1892		(ppcver < PPC3_VERSION_TAS5825_BASE))
1893		tas_priv->fw_parse_fct_param_address =
1894			fw_parse_fct_param_address;
1895}
1896
1897static int dspfw_default_callback(struct tasdevice_priv *tas_priv,
1898	unsigned int drv_ver, unsigned int ppcver)
1899{
1900	int rc = 0;
1901
1902	if (drv_ver == 0x100) {
1903		if (ppcver >= PPC3_VERSION_TAS5825_BASE) {
1904			tas_priv->fw_parse_variable_header =
1905				fw_parse_variable_header_kernel;
1906			tas_priv->fw_parse_program_data =
1907				fw_parse_tas5825_program_data_kernel;
1908			tas_priv->fw_parse_configuration_data =
1909				fw_parse_tas5825_configuration_data_kernel;
1910			tas_priv->tasdevice_load_block =
1911				tasdevice_load_block_kernel;
1912			dspbin_type_check(tas_priv, ppcver);
1913		} else if (ppcver >= PPC3_VERSION_BASE) {
1914			tas_priv->fw_parse_variable_header =
1915				fw_parse_variable_header_kernel;
1916			tas_priv->fw_parse_program_data =
1917				fw_parse_program_data_kernel;
1918			tas_priv->fw_parse_configuration_data =
1919				fw_parse_configuration_data_kernel;
1920			tas_priv->tasdevice_load_block =
1921				tasdevice_load_block_kernel;
1922			dspbin_type_check(tas_priv, ppcver);
1923		} else {
1924			switch (ppcver) {
1925			case 0x00:
1926				tas_priv->fw_parse_variable_header =
1927					fw_parse_variable_header_git;
1928				tas_priv->fw_parse_program_data =
1929					fw_parse_program_data;
1930				tas_priv->fw_parse_configuration_data =
1931					fw_parse_configuration_data;
1932				tas_priv->tasdevice_load_block =
1933					tasdevice_load_block;
1934				break;
1935			default:
1936				dev_err(tas_priv->dev,
1937					"%s: PPCVer must be 0x0 or 0x%02x",
1938					__func__, PPC3_VERSION_BASE);
1939				dev_err(tas_priv->dev, " Current:0x%02x\n",
1940					ppcver);
1941				rc = -EINVAL;
1942				break;
1943			}
1944		}
1945	} else {
1946		dev_err(tas_priv->dev,
1947			"DrvVer must be 0x0, 0x230 or above 0x230 ");
1948		dev_err(tas_priv->dev, "current is 0x%02x\n", drv_ver);
1949		rc = -EINVAL;
1950	}
1951
1952	return rc;
1953}
1954
1955static int load_calib_data(struct tasdevice_priv *tas_priv,
1956	struct tasdevice_data *dev_data)
1957{
1958	struct tasdev_blk *block;
1959	unsigned int i;
1960	int ret = 0;
1961
1962	for (i = 0; i < dev_data->nr_blk; i++) {
1963		block = &(dev_data->dev_blks[i]);
1964		ret = tasdevice_load_block(tas_priv, block);
1965		if (ret < 0)
1966			break;
1967	}
1968
1969	return ret;
1970}
1971
1972static int fw_parse_header(struct tasdevice_priv *tas_priv,
1973	struct tasdevice_fw *tas_fmw, const struct firmware *fmw, int offset)
1974{
1975	struct tasdevice_dspfw_hdr *fw_hdr = &(tas_fmw->fw_hdr);
1976	struct tasdevice_fw_fixed_hdr *fw_fixed_hdr = &(fw_hdr->fixed_hdr);
1977	static const unsigned char magic_number[] = { 0x35, 0x35, 0x35, 0x32 };
1978	const unsigned char *buf = (unsigned char *)fmw->data;
1979
1980	if (offset + 92 > fmw->size) {
1981		dev_err(tas_priv->dev, "%s: File Size error\n", __func__);
1982		offset = -EINVAL;
1983		goto out;
1984	}
1985	if (memcmp(&buf[offset], magic_number, 4)) {
1986		dev_err(tas_priv->dev, "%s: Magic num NOT match\n", __func__);
1987		offset = -EINVAL;
1988		goto out;
1989	}
1990	offset += 4;
1991
1992	/* Convert data[offset], data[offset + 1], data[offset + 2] and
1993	 * data[offset + 3] into host
1994	 */
1995	fw_fixed_hdr->fwsize = get_unaligned_be32(&buf[offset]);
1996	offset += 4;
1997	if (fw_fixed_hdr->fwsize != fmw->size) {
1998		dev_err(tas_priv->dev, "File size not match, %lu %u",
1999			(unsigned long)fmw->size, fw_fixed_hdr->fwsize);
2000		offset = -EINVAL;
2001		goto out;
2002	}
2003	offset += 4;
2004	fw_fixed_hdr->ppcver = get_unaligned_be32(&buf[offset]);
2005	offset += 8;
2006	fw_fixed_hdr->drv_ver = get_unaligned_be32(&buf[offset]);
2007	offset += 72;
2008
2009 out:
2010	return offset;
2011}
2012
2013static int fw_parse_variable_hdr_cal(struct tasdevice_priv *tas_priv,
2014	struct tasdevice_fw *tas_fmw, const struct firmware *fmw, int offset)
2015{
2016	struct tasdevice_dspfw_hdr *fw_hdr = &(tas_fmw->fw_hdr);
2017
2018	offset = fw_parse_variable_hdr(tas_priv, fw_hdr, fmw, offset);
2019	if (offset < 0)
2020		goto out;
2021	if (fw_hdr->ndev != 1) {
2022		dev_err(tas_priv->dev,
2023			"%s: calbin must be 1, but currently ndev(%u)\n",
2024			__func__, fw_hdr->ndev);
2025		offset = -EINVAL;
2026	}
2027
2028out:
2029	return offset;
2030}
2031
2032/* When calibrated data parsing error occurs, DSP can still work with default
2033 * calibrated data, memory resource related to calibrated data will be
2034 * released in the tasdevice_codec_remove.
2035 */
2036static int fw_parse_calibration_data(struct tasdevice_priv *tas_priv,
2037	struct tasdevice_fw *tas_fmw, const struct firmware *fmw, int offset)
2038{
2039	struct tasdevice_calibration *calibration;
2040	unsigned char *data = (unsigned char *)fmw->data;
2041	unsigned int i, n;
2042
2043	if (offset + 2 > fmw->size) {
2044		dev_err(tas_priv->dev, "%s: Calibrations error\n", __func__);
2045		offset = -EINVAL;
2046		goto out;
2047	}
2048	tas_fmw->nr_calibrations = get_unaligned_be16(&data[offset]);
2049	offset += 2;
2050
2051	if (tas_fmw->nr_calibrations != 1) {
2052		dev_err(tas_priv->dev,
2053			"%s: only supports one calibration (%d)!\n",
2054			__func__, tas_fmw->nr_calibrations);
2055		goto out;
2056	}
2057
2058	tas_fmw->calibrations = kcalloc(tas_fmw->nr_calibrations,
2059		sizeof(struct tasdevice_calibration), GFP_KERNEL);
2060	if (!tas_fmw->calibrations) {
2061		offset = -ENOMEM;
2062		goto out;
2063	}
2064	for (i = 0; i < tas_fmw->nr_calibrations; i++) {
2065		if (offset + 64 > fmw->size) {
2066			dev_err(tas_priv->dev, "Calibrations error\n");
2067			offset = -EINVAL;
2068			goto out;
2069		}
2070		calibration = &(tas_fmw->calibrations[i]);
2071		offset += 64;
2072
2073		n = strlen((char *)&data[offset]);
2074		/* skip '\0' and 2 unused bytes */
2075		n += 3;
2076		if (offset + n > fmw->size) {
2077			dev_err(tas_priv->dev, "Description err\n");
2078			offset = -EINVAL;
2079			goto out;
2080		}
2081		offset += n;
2082
2083		offset = fw_parse_data(tas_fmw, &(calibration->dev_data), fmw,
2084			offset);
2085		if (offset < 0)
2086			goto out;
2087	}
2088
2089out:
2090	return offset;
2091}
2092
2093int tas2781_load_calibration(void *context, char *file_name,
2094	unsigned short i)
2095{
2096	struct tasdevice_priv *tas_priv = (struct tasdevice_priv *)context;
2097	struct tasdevice *tasdev = &(tas_priv->tasdevice[i]);
2098	const struct firmware *fw_entry = NULL;
2099	struct tasdevice_fw *tas_fmw;
2100	struct firmware fmw;
2101	int offset = 0;
2102	int ret;
2103
2104	ret = request_firmware(&fw_entry, file_name, tas_priv->dev);
2105	if (ret) {
2106		dev_err(tas_priv->dev, "%s: Request firmware %s failed\n",
2107			__func__, file_name);
2108		goto out;
2109	}
2110
2111	if (!fw_entry->size) {
2112		dev_err(tas_priv->dev, "%s: file read error: size = %lu\n",
2113			__func__, (unsigned long)fw_entry->size);
2114		ret = -EINVAL;
2115		goto out;
2116	}
2117	fmw.size = fw_entry->size;
2118	fmw.data = fw_entry->data;
2119
2120	tas_fmw = tasdev->cali_data_fmw = kzalloc(sizeof(struct tasdevice_fw),
2121		GFP_KERNEL);
2122	if (!tasdev->cali_data_fmw) {
2123		ret = -ENOMEM;
2124		goto out;
2125	}
2126	tas_fmw->dev = tas_priv->dev;
2127	offset = fw_parse_header(tas_priv, tas_fmw, &fmw, offset);
2128	if (offset == -EINVAL) {
2129		dev_err(tas_priv->dev, "fw_parse_header EXIT!\n");
2130		ret = offset;
2131		goto out;
2132	}
2133	offset = fw_parse_variable_hdr_cal(tas_priv, tas_fmw, &fmw, offset);
2134	if (offset == -EINVAL) {
2135		dev_err(tas_priv->dev,
2136			"%s: fw_parse_variable_header_cal EXIT!\n", __func__);
2137		ret = offset;
2138		goto out;
2139	}
2140	offset = fw_parse_program_data(tas_priv, tas_fmw, &fmw, offset);
2141	if (offset < 0) {
2142		dev_err(tas_priv->dev, "fw_parse_program_data EXIT!\n");
2143		ret = offset;
2144		goto out;
2145	}
2146	offset = fw_parse_configuration_data(tas_priv, tas_fmw, &fmw, offset);
2147	if (offset < 0) {
2148		dev_err(tas_priv->dev, "fw_parse_configuration_data EXIT!\n");
2149		ret = offset;
2150		goto out;
2151	}
2152	offset = fw_parse_calibration_data(tas_priv, tas_fmw, &fmw, offset);
2153	if (offset < 0) {
2154		dev_err(tas_priv->dev, "fw_parse_calibration_data EXIT!\n");
2155		ret = offset;
2156		goto out;
2157	}
2158
2159out:
2160	release_firmware(fw_entry);
2161
2162	return ret;
2163}
2164EXPORT_SYMBOL_NS_GPL(tas2781_load_calibration, "SND_SOC_TAS2781_FMWLIB");
2165
2166static int tasdevice_dspfw_ready(const struct firmware *fmw,
2167	void *context)
2168{
2169	struct tasdevice_priv *tas_priv = (struct tasdevice_priv *) context;
2170	struct tasdevice_fw_fixed_hdr *fw_fixed_hdr;
2171	struct tasdevice_fw *tas_fmw;
2172	int offset = 0;
2173	int ret;
2174
2175	if (!fmw || !fmw->data) {
2176		dev_err(tas_priv->dev, "%s: Failed to read firmware %s\n",
2177			__func__, tas_priv->coef_binaryname);
2178		return -EINVAL;
2179	}
2180
2181	tas_priv->fmw = kzalloc(sizeof(struct tasdevice_fw), GFP_KERNEL);
2182	if (!tas_priv->fmw)
2183		return -ENOMEM;
2184
2185	tas_fmw = tas_priv->fmw;
2186	tas_fmw->dev = tas_priv->dev;
2187	offset = fw_parse_header(tas_priv, tas_fmw, fmw, offset);
2188
2189	if (offset == -EINVAL)
2190		return -EINVAL;
2191
2192	fw_fixed_hdr = &(tas_fmw->fw_hdr.fixed_hdr);
2193	/* Support different versions of firmware */
2194	switch (fw_fixed_hdr->drv_ver) {
2195	case 0x301:
2196	case 0x302:
2197	case 0x502:
2198	case 0x503:
2199		tas_priv->fw_parse_variable_header =
2200			fw_parse_variable_header_kernel;
2201		tas_priv->fw_parse_program_data =
2202			fw_parse_program_data_kernel;
2203		tas_priv->fw_parse_configuration_data =
2204			fw_parse_configuration_data_kernel;
2205		tas_priv->tasdevice_load_block =
2206			tasdevice_load_block_kernel;
2207		break;
2208	case 0x202:
2209	case 0x400:
2210	case 0x401:
2211		tas_priv->fw_parse_variable_header =
2212			fw_parse_variable_header_git;
2213		tas_priv->fw_parse_program_data =
2214			fw_parse_program_data;
2215		tas_priv->fw_parse_configuration_data =
2216			fw_parse_configuration_data;
2217		tas_priv->tasdevice_load_block =
2218			tasdevice_load_block;
2219		break;
2220	default:
2221		ret = dspfw_default_callback(tas_priv,
2222			fw_fixed_hdr->drv_ver, fw_fixed_hdr->ppcver);
2223		if (ret)
2224			return ret;
2225		break;
2226	}
2227
2228	offset = tas_priv->fw_parse_variable_header(tas_priv, fmw, offset);
2229	if (offset < 0)
2230		return offset;
2231
2232	offset = tas_priv->fw_parse_program_data(tas_priv, tas_fmw, fmw,
2233		offset);
2234	if (offset < 0)
2235		return offset;
2236
2237	offset = tas_priv->fw_parse_configuration_data(tas_priv,
2238		tas_fmw, fmw, offset);
2239	if (offset < 0)
2240		return offset;
2241
2242	if (tas_priv->fw_parse_fct_param_address) {
2243		offset = tas_priv->fw_parse_fct_param_address(tas_priv,
2244			tas_fmw, fmw, offset);
2245		if (offset < 0)
2246			return offset;
2247	}
2248
2249	return 0;
2250}
2251
2252int tasdevice_dsp_parser(void *context)
2253{
2254	struct tasdevice_priv *tas_priv = (struct tasdevice_priv *)context;
2255	const struct firmware *fw_entry;
2256	int ret;
2257
2258	ret = request_firmware(&fw_entry, tas_priv->coef_binaryname,
2259		tas_priv->dev);
2260	if (ret) {
2261		dev_err(tas_priv->dev, "%s: load %s error\n", __func__,
2262			tas_priv->coef_binaryname);
2263		goto out;
2264	}
2265
2266	ret = tasdevice_dspfw_ready(fw_entry, tas_priv);
2267	release_firmware(fw_entry);
2268	fw_entry = NULL;
2269
2270out:
2271	return ret;
2272}
2273EXPORT_SYMBOL_NS_GPL(tasdevice_dsp_parser, "SND_SOC_TAS2781_FMWLIB");
2274
2275static void tas2781_clear_calfirmware(struct tasdevice_fw *tas_fmw)
2276{
2277	struct tasdevice_calibration *calibration;
2278	struct tasdev_blk *block;
2279	struct tasdevice_data *im;
2280	unsigned int blks;
2281	int i;
2282
2283	if (!tas_fmw->calibrations)
2284		goto out;
2285
2286	for (i = 0; i < tas_fmw->nr_calibrations; i++) {
2287		calibration = &(tas_fmw->calibrations[i]);
2288		if (!calibration)
2289			continue;
2290
2291		im = &(calibration->dev_data);
2292
2293		if (!im->dev_blks)
2294			continue;
2295
2296		for (blks = 0; blks < im->nr_blk; blks++) {
2297			block = &(im->dev_blks[blks]);
2298			if (!block)
2299				continue;
2300			kfree(block->data);
2301		}
2302		kfree(im->dev_blks);
2303	}
2304	kfree(tas_fmw->calibrations);
2305out:
2306	kfree(tas_fmw);
2307}
2308
2309void tasdevice_calbin_remove(void *context)
2310{
2311	struct tasdevice_priv *tas_priv = (struct tasdevice_priv *) context;
2312	struct tasdevice *tasdev;
2313	int i;
2314
2315	if (!tas_priv)
2316		return;
2317
2318	for (i = 0; i < tas_priv->ndev; i++) {
2319		tasdev = &(tas_priv->tasdevice[i]);
2320		if (!tasdev->cali_data_fmw)
2321			continue;
2322		tas2781_clear_calfirmware(tasdev->cali_data_fmw);
2323		tasdev->cali_data_fmw = NULL;
2324	}
2325}
2326EXPORT_SYMBOL_NS_GPL(tasdevice_calbin_remove, "SND_SOC_TAS2781_FMWLIB");
2327
2328void tasdevice_config_info_remove(void *context)
2329{
2330	struct tasdevice_priv *tas_priv = (struct tasdevice_priv *) context;
2331	struct tasdevice_rca *rca = &(tas_priv->rcabin);
2332	struct tasdevice_config_info **ci = rca->cfg_info;
2333	int i, j;
2334
2335	if (!ci)
2336		return;
2337	for (i = 0; i < rca->ncfgs; i++) {
2338		if (!ci[i])
2339			continue;
2340		if (ci[i]->blk_data) {
2341			for (j = 0; j < (int)ci[i]->real_nblocks; j++) {
2342				if (!ci[i]->blk_data[j])
2343					continue;
2344				kfree(ci[i]->blk_data[j]->regdata);
2345				kfree(ci[i]->blk_data[j]);
2346			}
2347			kfree(ci[i]->blk_data);
2348		}
2349		kfree(ci[i]);
2350	}
2351	kfree(ci);
2352}
2353EXPORT_SYMBOL_NS_GPL(tasdevice_config_info_remove, "SND_SOC_TAS2781_FMWLIB");
2354
2355static int tasdevice_load_data(struct tasdevice_priv *tas_priv,
2356	struct tasdevice_data *dev_data)
2357{
2358	struct tasdev_blk *block;
2359	unsigned int i;
2360	int ret = 0;
2361
2362	for (i = 0; i < dev_data->nr_blk; i++) {
2363		block = &(dev_data->dev_blks[i]);
2364		ret = tas_priv->tasdevice_load_block(tas_priv, block);
2365		if (ret < 0)
2366			break;
2367	}
2368
2369	return ret;
2370}
2371
2372static void tasdev_load_calibrated_data(struct tasdevice_priv *priv, int i)
2373{
2374	struct tasdevice_fw *cal_fmw = priv->tasdevice[i].cali_data_fmw;
2375	struct calidata *cali_data = &priv->cali_data;
2376	struct cali_reg *p = &cali_data->cali_reg_array;
2377	unsigned char *data = cali_data->data;
2378	struct tasdevice_calibration *cal;
2379	int k = i * (cali_data->cali_dat_sz_per_dev + 1);
2380	int rc;
2381
2382	/* Load the calibrated data from cal bin file */
2383	if (!priv->is_user_space_calidata && cal_fmw) {
2384		cal = cal_fmw->calibrations;
2385
2386		if (cal)
2387			load_calib_data(priv, &cal->dev_data);
2388		return;
2389	}
2390	if (!priv->is_user_space_calidata)
2391		return;
2392	/* load calibrated data from user space */
2393	if (data[k] != i) {
2394		dev_err(priv->dev, "%s: no cal-data for dev %d from usr-spc\n",
2395			__func__, i);
2396		return;
2397	}
2398	k++;
2399
2400	rc = tasdevice_dev_bulk_write(priv, i, p->r0_reg, &(data[k]), 4);
2401	if (rc < 0) {
2402		dev_err(priv->dev, "chn %d r0_reg bulk_wr err = %d\n", i, rc);
2403		return;
2404	}
2405	k += 4;
2406	rc = tasdevice_dev_bulk_write(priv, i, p->r0_low_reg, &(data[k]), 4);
2407	if (rc < 0) {
2408		dev_err(priv->dev, "chn %d r0_low_reg err = %d\n", i, rc);
2409		return;
2410	}
2411	k += 4;
2412	rc = tasdevice_dev_bulk_write(priv, i, p->invr0_reg, &(data[k]), 4);
2413	if (rc < 0) {
2414		dev_err(priv->dev, "chn %d invr0_reg err = %d\n", i, rc);
2415		return;
2416	}
2417	k += 4;
2418	rc = tasdevice_dev_bulk_write(priv, i, p->pow_reg, &(data[k]), 4);
2419	if (rc < 0) {
2420		dev_err(priv->dev, "chn %d pow_reg bulk_wr err = %d\n", i, rc);
2421		return;
2422	}
2423	k += 4;
2424	rc = tasdevice_dev_bulk_write(priv, i, p->tlimit_reg, &(data[k]), 4);
2425	if (rc < 0) {
2426		dev_err(priv->dev, "chn %d tlimit_reg err = %d\n", i, rc);
2427		return;
2428	}
2429}
2430
2431int tasdevice_select_tuningprm_cfg(void *context, int prm_no,
2432	int cfg_no, int rca_conf_no)
2433{
2434	struct tasdevice_priv *tas_priv = (struct tasdevice_priv *) context;
2435	struct tasdevice_rca *rca = &(tas_priv->rcabin);
2436	struct tasdevice_config_info **cfg_info = rca->cfg_info;
2437	struct tasdevice_fw *tas_fmw = tas_priv->fmw;
2438	struct tasdevice_prog *program;
2439	struct tasdevice_config *conf;
2440	int prog_status = 0;
2441	int status, i;
2442
2443	if (!tas_fmw) {
2444		dev_err(tas_priv->dev, "%s: Firmware is NULL\n", __func__);
2445		goto out;
2446	}
2447
2448	if (cfg_no >= tas_fmw->nr_configurations) {
2449		dev_err(tas_priv->dev,
2450			"%s: cfg(%d) is not in range of conf %u\n",
2451			__func__, cfg_no, tas_fmw->nr_configurations);
2452		goto out;
2453	}
2454
2455	if (prm_no >= tas_fmw->nr_programs) {
2456		dev_err(tas_priv->dev,
2457			"%s: prm(%d) is not in range of Programs %u\n",
2458			__func__, prm_no, tas_fmw->nr_programs);
2459		goto out;
2460	}
2461
2462	if (rca_conf_no >= rca->ncfgs || rca_conf_no < 0 ||
2463		!cfg_info) {
2464		dev_err(tas_priv->dev,
2465			"conf_no:%d should be in range from 0 to %u\n",
2466			rca_conf_no, rca->ncfgs-1);
2467		goto out;
2468	}
2469
2470	for (i = 0, prog_status = 0; i < tas_priv->ndev; i++) {
2471		if (cfg_info[rca_conf_no]->active_dev & (1 << i)) {
2472			if (prm_no >= 0
2473				&& (tas_priv->tasdevice[i].cur_prog != prm_no
2474				|| tas_priv->force_fwload_status)) {
2475				tas_priv->tasdevice[i].cur_conf = -1;
2476				tas_priv->tasdevice[i].is_loading = true;
2477				prog_status++;
2478			}
2479		} else
2480			tas_priv->tasdevice[i].is_loading = false;
2481		tas_priv->tasdevice[i].is_loaderr = false;
2482	}
2483
2484	if (prog_status) {
2485		program = &(tas_fmw->programs[prm_no]);
2486		tasdevice_load_data(tas_priv, &(program->dev_data));
2487		for (i = 0; i < tas_priv->ndev; i++) {
2488			if (tas_priv->tasdevice[i].is_loaderr == true)
2489				continue;
2490			if (tas_priv->tasdevice[i].is_loaderr == false &&
2491				tas_priv->tasdevice[i].is_loading == true)
2492				tas_priv->tasdevice[i].cur_prog = prm_no;
2493		}
2494	}
2495
2496	for (i = 0, status = 0; i < tas_priv->ndev; i++) {
2497		if (cfg_no >= 0
2498			&& tas_priv->tasdevice[i].cur_conf != cfg_no
2499			&& (cfg_info[rca_conf_no]->active_dev & (1 << i))
2500			&& (tas_priv->tasdevice[i].is_loaderr == false)) {
2501			status++;
2502			tas_priv->tasdevice[i].is_loading = true;
2503		} else
2504			tas_priv->tasdevice[i].is_loading = false;
2505	}
2506
2507	if (status) {
2508		conf = &(tas_fmw->configs[cfg_no]);
2509		status = 0;
2510		tasdevice_load_data(tas_priv, &(conf->dev_data));
2511		for (i = 0; i < tas_priv->ndev; i++) {
2512			if (tas_priv->tasdevice[i].is_loaderr == true) {
2513				status |= BIT(i + 4);
2514				continue;
2515			}
2516
2517			if (tas_priv->tasdevice[i].is_loaderr == false &&
2518				tas_priv->tasdevice[i].is_loading == true) {
2519				tasdev_load_calibrated_data(tas_priv, i);
2520				tas_priv->tasdevice[i].cur_conf = cfg_no;
2521			}
2522		}
2523	} else {
2524		dev_dbg(tas_priv->dev, "%s: Unneeded loading dsp conf %d\n",
2525			__func__, cfg_no);
2526	}
2527
2528	status |= cfg_info[rca_conf_no]->active_dev;
2529
2530out:
2531	return prog_status;
2532}
2533EXPORT_SYMBOL_NS_GPL(tasdevice_select_tuningprm_cfg, "SND_SOC_TAS2781_FMWLIB");
2534
2535int tasdevice_prmg_load(void *context, int prm_no)
2536{
2537	struct tasdevice_priv *tas_priv = (struct tasdevice_priv *) context;
2538	struct tasdevice_fw *tas_fmw = tas_priv->fmw;
2539	struct tasdevice_prog *program;
2540	int prog_status = 0;
2541	int i;
2542
2543	if (!tas_fmw) {
2544		dev_err(tas_priv->dev, "%s: Firmware is NULL\n", __func__);
2545		goto out;
2546	}
2547
2548	if (prm_no >= tas_fmw->nr_programs) {
2549		dev_err(tas_priv->dev,
2550			"%s: prm(%d) is not in range of Programs %u\n",
2551			__func__, prm_no, tas_fmw->nr_programs);
2552		goto out;
2553	}
2554
2555	for (i = 0, prog_status = 0; i < tas_priv->ndev; i++) {
2556		if (prm_no >= 0 && tas_priv->tasdevice[i].cur_prog != prm_no) {
2557			tas_priv->tasdevice[i].cur_conf = -1;
2558			tas_priv->tasdevice[i].is_loading = true;
2559			prog_status++;
2560		}
2561	}
2562
2563	if (prog_status) {
2564		program = &(tas_fmw->programs[prm_no]);
2565		tasdevice_load_data(tas_priv, &(program->dev_data));
2566		for (i = 0; i < tas_priv->ndev; i++) {
2567			if (tas_priv->tasdevice[i].is_loaderr == true)
2568				continue;
2569			else if (tas_priv->tasdevice[i].is_loaderr == false
2570				&& tas_priv->tasdevice[i].is_loading == true)
2571				tas_priv->tasdevice[i].cur_prog = prm_no;
2572		}
2573	}
2574
2575out:
2576	return prog_status;
2577}
2578EXPORT_SYMBOL_NS_GPL(tasdevice_prmg_load, "SND_SOC_TAS2781_FMWLIB");
2579
2580void tasdevice_tuning_switch(void *context, int state)
2581{
2582	struct tasdevice_priv *tas_priv = (struct tasdevice_priv *) context;
2583	struct tasdevice_fw *tas_fmw = tas_priv->fmw;
2584	int profile_cfg_id = tas_priv->rcabin.profile_cfg_id;
2585
2586	/*
2587	 * Only RCA-based Playback can still work with no dsp program running
2588	 * inside the chip.
2589	 */
2590	switch (tas_priv->fw_state) {
2591	case TASDEVICE_RCA_FW_OK:
2592	case TASDEVICE_DSP_FW_ALL_OK:
2593		break;
2594	default:
2595		return;
2596	}
2597
2598	if (state == 0) {
2599		if (tas_fmw && tas_priv->cur_prog < tas_fmw->nr_programs) {
2600			/* dsp mode or tuning mode */
2601			profile_cfg_id = tas_priv->rcabin.profile_cfg_id;
2602			tasdevice_select_tuningprm_cfg(tas_priv,
2603				tas_priv->cur_prog, tas_priv->cur_conf,
2604				profile_cfg_id);
2605		}
2606
2607		tasdevice_select_cfg_blk(tas_priv, profile_cfg_id,
2608			TASDEVICE_BIN_BLK_PRE_POWER_UP);
2609	} else {
2610		tasdevice_select_cfg_blk(tas_priv, profile_cfg_id,
2611			TASDEVICE_BIN_BLK_PRE_SHUTDOWN);
2612	}
2613}
2614EXPORT_SYMBOL_NS_GPL(tasdevice_tuning_switch, "SND_SOC_TAS2781_FMWLIB");
2615
2616MODULE_DESCRIPTION("Texas Firmware Support");
2617MODULE_AUTHOR("Shenghao Ding, TI, <shenghao-ding@ti.com>");
2618MODULE_LICENSE("GPL");
~/ Read-only file preview.