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