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