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