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