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