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