1 // SPDX-License-Identifier: GPL-2.0
2 //
3 // TAS2781 HDA SPI driver
4 //
5 // Copyright 2024 - 2025 Texas Instruments, Inc.
6 //
7 // Author: Baojun Xu <baojun.xu@ti.com>
8
9 #include <linux/crc8.h>
10 #include <linux/firmware.h>
11 #include <linux/init.h>
12 #include <linux/interrupt.h>
13 #include <linux/module.h>
14 #include <linux/slab.h>
15 #include <linux/types.h>
16 #include <linux/unaligned.h>
17 #include <sound/pcm_params.h>
18 #include <sound/soc.h>
19 #include <sound/tas2781-dsp.h>
20 #include <sound/tlv.h>
21
22 #include "tas2781-spi.h"
23
24 #define OFFSET_ERROR_BIT BIT(31)
25
26 #define ERROR_PRAM_CRCCHK 0x0000000
27 #define ERROR_YRAM_CRCCHK 0x0000001
28 #define PPC_DRIVER_CRCCHK 0x00000200
29
30 #define TAS2781_SA_COEFF_SWAP_REG TASDEVICE_REG(0, 0x35, 0x2c)
31 #define TAS2781_YRAM_BOOK1 140
32 #define TAS2781_YRAM1_PAGE 42
33 #define TAS2781_YRAM1_START_REG 88
34
35 #define TAS2781_YRAM2_START_PAGE 43
36 #define TAS2781_YRAM2_END_PAGE 49
37 #define TAS2781_YRAM2_START_REG 8
38 #define TAS2781_YRAM2_END_REG 127
39
40 #define TAS2781_YRAM3_PAGE 50
41 #define TAS2781_YRAM3_START_REG 8
42 #define TAS2781_YRAM3_END_REG 27
43
44 /* should not include B0_P53_R44-R47 */
45 #define TAS2781_YRAM_BOOK2 0
46 #define TAS2781_YRAM4_START_PAGE 50
47 #define TAS2781_YRAM4_END_PAGE 60
48
49 #define TAS2781_YRAM5_PAGE 61
50 #define TAS2781_YRAM5_START_REG TAS2781_YRAM3_START_REG
51 #define TAS2781_YRAM5_END_REG TAS2781_YRAM3_END_REG
52
53 #define TASDEVICE_MAXPROGRAM_NUM_KERNEL 5
54 #define TASDEVICE_MAXCONFIG_NUM_KERNEL_MULTIPLE_AMPS 64
55 #define TASDEVICE_MAXCONFIG_NUM_KERNEL 10
56 #define MAIN_ALL_DEVICES_1X 0x01
57 #define MAIN_DEVICE_A_1X 0x02
58 #define MAIN_DEVICE_B_1X 0x03
59 #define MAIN_DEVICE_C_1X 0x04
60 #define MAIN_DEVICE_D_1X 0x05
61 #define COEFF_DEVICE_A_1X 0x12
62 #define COEFF_DEVICE_B_1X 0x13
63 #define COEFF_DEVICE_C_1X 0x14
64 #define COEFF_DEVICE_D_1X 0x15
65 #define PRE_DEVICE_A_1X 0x22
66 #define PRE_DEVICE_B_1X 0x23
67 #define PRE_DEVICE_C_1X 0x24
68 #define PRE_DEVICE_D_1X 0x25
69 #define PRE_SOFTWARE_RESET_DEVICE_A 0x41
70 #define PRE_SOFTWARE_RESET_DEVICE_B 0x42
71 #define PRE_SOFTWARE_RESET_DEVICE_C 0x43
72 #define PRE_SOFTWARE_RESET_DEVICE_D 0x44
73 #define POST_SOFTWARE_RESET_DEVICE_A 0x45
74 #define POST_SOFTWARE_RESET_DEVICE_B 0x46
75 #define POST_SOFTWARE_RESET_DEVICE_C 0x47
76 #define POST_SOFTWARE_RESET_DEVICE_D 0x48
77
78 struct tas_crc {
79 unsigned char offset;
80 unsigned char len;
81 };
82
83 struct blktyp_devidx_map {
84 unsigned char blktyp;
85 unsigned char dev_idx;
86 };
87
88 /* fixed m68k compiling issue: mapping table can save code field */
89 static const struct blktyp_devidx_map ppc3_tas2781_mapping_table[] = {
90 { MAIN_ALL_DEVICES_1X, 0x80 },
91 { MAIN_DEVICE_A_1X, 0x81 },
92 { COEFF_DEVICE_A_1X, 0x81 },
93 { PRE_DEVICE_A_1X, 0x81 },
94 { PRE_SOFTWARE_RESET_DEVICE_A, 0xC1 },
95 { POST_SOFTWARE_RESET_DEVICE_A, 0xC1 },
96 { MAIN_DEVICE_B_1X, 0x82 },
97 { COEFF_DEVICE_B_1X, 0x82 },
98 { PRE_DEVICE_B_1X, 0x82 },
99 { PRE_SOFTWARE_RESET_DEVICE_B, 0xC2 },
100 { POST_SOFTWARE_RESET_DEVICE_B, 0xC2 },
101 { MAIN_DEVICE_C_1X, 0x83 },
102 { COEFF_DEVICE_C_1X, 0x83 },
103 { PRE_DEVICE_C_1X, 0x83 },
104 { PRE_SOFTWARE_RESET_DEVICE_C, 0xC3 },
105 { POST_SOFTWARE_RESET_DEVICE_C, 0xC3 },
106 { MAIN_DEVICE_D_1X, 0x84 },
107 { COEFF_DEVICE_D_1X, 0x84 },
108 { PRE_DEVICE_D_1X, 0x84 },
109 { PRE_SOFTWARE_RESET_DEVICE_D, 0xC4 },
110 { POST_SOFTWARE_RESET_DEVICE_D, 0xC4 },
111 };
112
113 static const struct blktyp_devidx_map ppc3_mapping_table[] = {
114 { MAIN_ALL_DEVICES_1X, 0x80 },
115 { MAIN_DEVICE_A_1X, 0x81 },
116 { COEFF_DEVICE_A_1X, 0xC1 },
117 { PRE_DEVICE_A_1X, 0xC1 },
118 { MAIN_DEVICE_B_1X, 0x82 },
119 { COEFF_DEVICE_B_1X, 0xC2 },
120 { PRE_DEVICE_B_1X, 0xC2 },
121 { MAIN_DEVICE_C_1X, 0x83 },
122 { COEFF_DEVICE_C_1X, 0xC3 },
123 { PRE_DEVICE_C_1X, 0xC3 },
124 { MAIN_DEVICE_D_1X, 0x84 },
125 { COEFF_DEVICE_D_1X, 0xC4 },
126 { PRE_DEVICE_D_1X, 0xC4 },
127 };
128
129 static const struct blktyp_devidx_map non_ppc3_mapping_table[] = {
130 { MAIN_ALL_DEVICES, 0x80 },
131 { MAIN_DEVICE_A, 0x81 },
132 { COEFF_DEVICE_A, 0xC1 },
133 { PRE_DEVICE_A, 0xC1 },
134 { MAIN_DEVICE_B, 0x82 },
135 { COEFF_DEVICE_B, 0xC2 },
136 { PRE_DEVICE_B, 0xC2 },
137 { MAIN_DEVICE_C, 0x83 },
138 { COEFF_DEVICE_C, 0xC3 },
139 { PRE_DEVICE_C, 0xC3 },
140 { MAIN_DEVICE_D, 0x84 },
141 { COEFF_DEVICE_D, 0xC4 },
142 { PRE_DEVICE_D, 0xC4 },
143 };
144
145 /*
146 * Device support different configurations for different scene,
147 * like voice, music, calibration, was write in regbin file.
148 * Will be stored into tas_priv after regbin was loaded.
149 */
tasdevice_add_config(struct tasdevice_priv * tas_priv,unsigned char * config_data,unsigned int config_size,int * status)150 static struct tasdevice_config_info *tasdevice_add_config(
151 struct tasdevice_priv *tas_priv, unsigned char *config_data,
152 unsigned int config_size, int *status)
153 {
154 struct tasdevice_config_info *cfg_info;
155 struct tasdev_blk_data **bk_da;
156 unsigned int config_offset = 0;
157 unsigned int i;
158
159 /*
160 * In most projects are many audio cases, such as music, handfree,
161 * receiver, games, audio-to-haptics, PMIC record, bypass mode,
162 * portrait, landscape, etc. Even in multiple audios, one or
163 * two of the chips will work for the special case, such as
164 * ultrasonic application. In order to support these variable-numbers
165 * of audio cases, flexible configs have been introduced in the
166 * DSP firmware.
167 */
168 cfg_info = kzalloc(sizeof(*cfg_info), GFP_KERNEL);
169 if (!cfg_info) {
170 *status = -ENOMEM;
171 return NULL;
172 }
173
174 if (tas_priv->rcabin.fw_hdr.binary_version_num >= 0x105) {
175 if ((config_offset + 64) > config_size) {
176 *status = -EINVAL;
177 dev_err(tas_priv->dev, "add conf: Out of boundary\n");
178 goto config_err;
179 }
180 config_offset += 64;
181 }
182
183 if ((config_offset + 4) > config_size) {
184 *status = -EINVAL;
185 dev_err(tas_priv->dev, "add config: Out of boundary\n");
186 goto config_err;
187 }
188
189 /*
190 * convert data[offset], data[offset + 1], data[offset + 2] and
191 * data[offset + 3] into host
192 */
193 cfg_info->nblocks = get_unaligned_be32(&config_data[config_offset]);
194 config_offset += 4;
195
196 /*
197 * Several kinds of dsp/algorithm firmwares can run on tas2781,
198 * the number and size of blk are not fixed and different among
199 * these firmwares.
200 */
201 bk_da = cfg_info->blk_data = kcalloc(cfg_info->nblocks,
202 sizeof(*bk_da), GFP_KERNEL);
203 if (!bk_da) {
204 *status = -ENOMEM;
205 goto config_err;
206 }
207 cfg_info->real_nblocks = 0;
208 for (i = 0; i < cfg_info->nblocks; i++) {
209 if (config_offset + 12 > config_size) {
210 *status = -EINVAL;
211 dev_err(tas_priv->dev,
212 "%s: Out of boundary: i = %d nblocks = %u!\n",
213 __func__, i, cfg_info->nblocks);
214 goto block_err;
215 }
216 bk_da[i] = kzalloc(sizeof(*bk_da[i]), GFP_KERNEL);
217 if (!bk_da[i]) {
218 *status = -ENOMEM;
219 goto block_err;
220 }
221
222 bk_da[i]->dev_idx = config_data[config_offset];
223 config_offset++;
224
225 bk_da[i]->block_type = config_data[config_offset];
226 config_offset++;
227
228 bk_da[i]->yram_checksum =
229 get_unaligned_be16(&config_data[config_offset]);
230 config_offset += 2;
231 bk_da[i]->block_size =
232 get_unaligned_be32(&config_data[config_offset]);
233 config_offset += 4;
234
235 bk_da[i]->n_subblks =
236 get_unaligned_be32(&config_data[config_offset]);
237
238 config_offset += 4;
239
240 if (config_offset + bk_da[i]->block_size > config_size) {
241 *status = -EINVAL;
242 dev_err(tas_priv->dev,
243 "%s: Out of boundary: i = %d blks = %u!\n",
244 __func__, i, cfg_info->nblocks);
245 goto block_err;
246 }
247 /* instead of kzalloc+memcpy */
248 bk_da[i]->regdata = kmemdup(&config_data[config_offset],
249 bk_da[i]->block_size, GFP_KERNEL);
250 if (!bk_da[i]->regdata) {
251 *status = -ENOMEM;
252 i++;
253 goto block_err;
254 }
255
256 config_offset += bk_da[i]->block_size;
257 cfg_info->real_nblocks += 1;
258 }
259
260 return cfg_info;
261 block_err:
262 for (int j = 0; j < i; j++)
263 kfree(bk_da[j]);
264 kfree(bk_da);
265 config_err:
266 kfree(cfg_info);
267 return NULL;
268 }
269
270 /* Regbin file parser function. */
tasdevice_spi_rca_parser(void * context,const struct firmware * fmw)271 int tasdevice_spi_rca_parser(void *context, const struct firmware *fmw)
272 {
273 struct tasdevice_priv *tas_priv = context;
274 struct tasdevice_config_info **cfg_info;
275 struct tasdevice_rca_hdr *fw_hdr;
276 struct tasdevice_rca *rca;
277 unsigned int total_config_sz = 0;
278 int offset = 0, ret = 0, i;
279 unsigned char *buf;
280
281 rca = &tas_priv->rcabin;
282 fw_hdr = &rca->fw_hdr;
283 if (!fmw || !fmw->data) {
284 dev_err(tas_priv->dev, "Failed to read %s\n",
285 tas_priv->rca_binaryname);
286 tas_priv->fw_state = TASDEVICE_DSP_FW_FAIL;
287 return -EINVAL;
288 }
289 buf = (unsigned char *)fmw->data;
290 fw_hdr->img_sz = get_unaligned_be32(&buf[offset]);
291 offset += 4;
292 if (fw_hdr->img_sz != fmw->size) {
293 dev_err(tas_priv->dev,
294 "File size not match, %d %u", (int)fmw->size,
295 fw_hdr->img_sz);
296 tas_priv->fw_state = TASDEVICE_DSP_FW_FAIL;
297 return -EINVAL;
298 }
299
300 fw_hdr->checksum = get_unaligned_be32(&buf[offset]);
301 offset += 4;
302 fw_hdr->binary_version_num = get_unaligned_be32(&buf[offset]);
303 if (fw_hdr->binary_version_num < 0x103) {
304 dev_err(tas_priv->dev, "File version 0x%04x is too low",
305 fw_hdr->binary_version_num);
306 tas_priv->fw_state = TASDEVICE_DSP_FW_FAIL;
307 return -EINVAL;
308 }
309 offset += 4;
310 fw_hdr->drv_fw_version = get_unaligned_be32(&buf[offset]);
311 offset += 8;
312 fw_hdr->plat_type = buf[offset++];
313 fw_hdr->dev_family = buf[offset++];
314 fw_hdr->reserve = buf[offset++];
315 fw_hdr->ndev = buf[offset++];
316 if (offset + TASDEVICE_DEVICE_SUM > fw_hdr->img_sz) {
317 dev_err(tas_priv->dev, "rca_ready: Out of boundary!\n");
318 tas_priv->fw_state = TASDEVICE_DSP_FW_FAIL;
319 return -EINVAL;
320 }
321
322 for (i = 0; i < TASDEVICE_DEVICE_SUM; i++, offset++)
323 fw_hdr->devs[i] = buf[offset];
324
325 fw_hdr->nconfig = get_unaligned_be32(&buf[offset]);
326 offset += 4;
327
328 for (i = 0; i < TASDEVICE_CONFIG_SUM; i++) {
329 fw_hdr->config_size[i] = get_unaligned_be32(&buf[offset]);
330 offset += 4;
331 total_config_sz += fw_hdr->config_size[i];
332 }
333
334 if (fw_hdr->img_sz - total_config_sz != (unsigned int)offset) {
335 dev_err(tas_priv->dev, "Bin file err %d - %d != %d!\n",
336 fw_hdr->img_sz, total_config_sz, (int)offset);
337 tas_priv->fw_state = TASDEVICE_DSP_FW_FAIL;
338 return -EINVAL;
339 }
340
341 cfg_info = kcalloc(fw_hdr->nconfig, sizeof(*cfg_info), GFP_KERNEL);
342 if (!cfg_info) {
343 tas_priv->fw_state = TASDEVICE_DSP_FW_FAIL;
344 return -ENOMEM;
345 }
346 rca->cfg_info = cfg_info;
347 rca->ncfgs = 0;
348 for (i = 0; i < (int)fw_hdr->nconfig; i++) {
349 rca->ncfgs += 1;
350 cfg_info[i] = tasdevice_add_config(tas_priv, &buf[offset],
351 fw_hdr->config_size[i], &ret);
352 if (ret) {
353 tas_priv->fw_state = TASDEVICE_DSP_FW_FAIL;
354 return ret;
355 }
356 offset += (int)fw_hdr->config_size[i];
357 }
358
359 return ret;
360 }
361
362 /* fixed m68k compiling issue: mapping table can save code field */
map_dev_idx(struct tasdevice_fw * tas_fmw,struct tasdev_blk * block)363 static unsigned char map_dev_idx(struct tasdevice_fw *tas_fmw,
364 struct tasdev_blk *block)
365 {
366 struct blktyp_devidx_map *p =
367 (struct blktyp_devidx_map *)non_ppc3_mapping_table;
368 struct tasdevice_dspfw_hdr *fw_hdr = &tas_fmw->fw_hdr;
369 struct tasdevice_fw_fixed_hdr *fw_fixed_hdr = &fw_hdr->fixed_hdr;
370 int i, n = ARRAY_SIZE(non_ppc3_mapping_table);
371 unsigned char dev_idx = 0;
372
373 if (fw_fixed_hdr->ppcver >= PPC3_VERSION_TAS2781_BASIC_MIN) {
374 p = (struct blktyp_devidx_map *)ppc3_tas2781_mapping_table;
375 n = ARRAY_SIZE(ppc3_tas2781_mapping_table);
376 } else if (fw_fixed_hdr->ppcver >= PPC3_VERSION_BASE) {
377 p = (struct blktyp_devidx_map *)ppc3_mapping_table;
378 n = ARRAY_SIZE(ppc3_mapping_table);
379 }
380
381 for (i = 0; i < n; i++) {
382 if (block->type == p[i].blktyp) {
383 dev_idx = p[i].dev_idx;
384 break;
385 }
386 }
387
388 return dev_idx;
389 }
390
391 /* Block parser function. */
fw_parse_block_data_kernel(struct tasdevice_fw * tas_fmw,struct tasdev_blk * block,const struct firmware * fmw,int offset)392 static int fw_parse_block_data_kernel(struct tasdevice_fw *tas_fmw,
393 struct tasdev_blk *block, const struct firmware *fmw, int offset)
394 {
395 const unsigned char *data = fmw->data;
396
397 if (offset + 16 > fmw->size) {
398 dev_err(tas_fmw->dev, "%s: File Size error\n", __func__);
399 return -EINVAL;
400 }
401
402 /*
403 * Convert data[offset], data[offset + 1], data[offset + 2] and
404 * data[offset + 3] into host.
405 */
406 block->type = get_unaligned_be32(&data[offset]);
407 offset += 4;
408
409 block->is_pchksum_present = data[offset++];
410 block->pchksum = data[offset++];
411 block->is_ychksum_present = data[offset++];
412 block->ychksum = data[offset++];
413 block->blk_size = get_unaligned_be32(&data[offset]);
414 offset += 4;
415 block->nr_subblocks = get_unaligned_be32(&data[offset]);
416 offset += 4;
417
418 /*
419 * Fixed m68k compiling issue:
420 * 1. mapping table can save code field.
421 * 2. storing the dev_idx as a member of block can reduce unnecessary
422 * time and system resource comsumption of dev_idx mapping every
423 * time the block data writing to the dsp.
424 */
425 block->dev_idx = map_dev_idx(tas_fmw, block);
426
427 if (offset + block->blk_size > fmw->size) {
428 dev_err(tas_fmw->dev, "%s: nSublocks error\n", __func__);
429 return -EINVAL;
430 }
431 /* instead of kzalloc+memcpy */
432 block->data = kmemdup(&data[offset], block->blk_size, GFP_KERNEL);
433 if (!block->data)
434 return -ENOMEM;
435
436 offset += block->blk_size;
437
438 return offset;
439 }
440
441 /* Data of block parser function. */
fw_parse_data_kernel(struct tasdevice_fw * tas_fmw,struct tasdevice_data * img_data,const struct firmware * fmw,int offset)442 static int fw_parse_data_kernel(struct tasdevice_fw *tas_fmw,
443 struct tasdevice_data *img_data, const struct firmware *fmw,
444 int offset)
445 {
446 const unsigned char *data = fmw->data;
447 struct tasdev_blk *blk;
448 unsigned int i;
449
450 if (offset + 4 > fmw->size) {
451 dev_err(tas_fmw->dev, "%s: File Size error\n", __func__);
452 return -EINVAL;
453 }
454 img_data->nr_blk = get_unaligned_be32(&data[offset]);
455 offset += 4;
456
457 img_data->dev_blks = kcalloc(img_data->nr_blk,
458 sizeof(struct tasdev_blk), GFP_KERNEL);
459 if (!img_data->dev_blks)
460 return -ENOMEM;
461
462 for (i = 0; i < img_data->nr_blk; i++) {
463 blk = &img_data->dev_blks[i];
464 offset = fw_parse_block_data_kernel(
465 tas_fmw, blk, fmw, offset);
466 if (offset < 0) {
467 kfree(img_data->dev_blks);
468 return -EINVAL;
469 }
470 }
471
472 return offset;
473 }
474
475 /* Data of DSP program parser function. */
fw_parse_program_data_kernel(struct tasdevice_priv * tas_priv,struct tasdevice_fw * tas_fmw,const struct firmware * fmw,int offset)476 static int fw_parse_program_data_kernel(
477 struct tasdevice_priv *tas_priv, struct tasdevice_fw *tas_fmw,
478 const struct firmware *fmw, int offset)
479 {
480 struct tasdevice_prog *program;
481 unsigned int i;
482
483 for (i = 0; i < tas_fmw->nr_programs; i++) {
484 program = &tas_fmw->programs[i];
485 if (offset + 72 > fmw->size) {
486 dev_err(tas_priv->dev, "%s: mpName error\n", __func__);
487 return -EINVAL;
488 }
489 /* skip 72 unused byts */
490 offset += 72;
491
492 offset = fw_parse_data_kernel(tas_fmw, &program->dev_data,
493 fmw, offset);
494 if (offset < 0)
495 break;
496 }
497
498 return offset;
499 }
500
501 /* Data of DSP configurations parser function. */
fw_parse_configuration_data_kernel(struct tasdevice_priv * tas_priv,struct tasdevice_fw * tas_fmw,const struct firmware * fmw,int offset)502 static int fw_parse_configuration_data_kernel(struct tasdevice_priv *tas_priv,
503 struct tasdevice_fw *tas_fmw, const struct firmware *fmw, int offset)
504 {
505 const unsigned char *data = fmw->data;
506 struct tasdevice_config *config;
507 unsigned int i;
508
509 for (i = 0; i < tas_fmw->nr_configurations; i++) {
510 config = &tas_fmw->configs[i];
511 if (offset + 80 > fmw->size) {
512 dev_err(tas_priv->dev, "%s: mpName error\n", __func__);
513 return -EINVAL;
514 }
515 memcpy(config->name, &data[offset], 64);
516 /* skip extra 16 bytes */
517 offset += 80;
518
519 offset = fw_parse_data_kernel(tas_fmw, &config->dev_data,
520 fmw, offset);
521 if (offset < 0)
522 break;
523 }
524
525 return offset;
526 }
527
528 /* DSP firmware file header parser function for early PPC3 firmware binary. */
fw_parse_variable_header_kernel(struct tasdevice_priv * tas_priv,const struct firmware * fmw,int offset)529 static int fw_parse_variable_header_kernel(struct tasdevice_priv *tas_priv,
530 const struct firmware *fmw, int offset)
531 {
532 struct tasdevice_fw *tas_fmw = tas_priv->fmw;
533 struct tasdevice_dspfw_hdr *fw_hdr = &tas_fmw->fw_hdr;
534 struct tasdevice_config *config;
535 struct tasdevice_prog *program;
536 const unsigned char *buf = fmw->data;
537 unsigned short max_confs;
538 unsigned int i;
539
540 if (offset + 12 + 4 * TASDEVICE_MAXPROGRAM_NUM_KERNEL > fmw->size) {
541 dev_err(tas_priv->dev, "%s: File Size error\n", __func__);
542 return -EINVAL;
543 }
544 fw_hdr->device_family = get_unaligned_be16(&buf[offset]);
545 if (fw_hdr->device_family != 0) {
546 dev_err(tas_priv->dev, "%s:not TAS device\n", __func__);
547 return -EINVAL;
548 }
549 offset += 2;
550 fw_hdr->device = get_unaligned_be16(&buf[offset]);
551 if (fw_hdr->device >= TASDEVICE_DSP_TAS_MAX_DEVICE ||
552 fw_hdr->device == 6) {
553 dev_err(tas_priv->dev, "Unsupported dev %d\n", fw_hdr->device);
554 return -EINVAL;
555 }
556 offset += 2;
557
558 tas_fmw->nr_programs = get_unaligned_be32(&buf[offset]);
559 offset += 4;
560
561 if (tas_fmw->nr_programs == 0 ||
562 tas_fmw->nr_programs > TASDEVICE_MAXPROGRAM_NUM_KERNEL) {
563 dev_err(tas_priv->dev, "mnPrograms is invalid\n");
564 return -EINVAL;
565 }
566
567 tas_fmw->programs = kcalloc(tas_fmw->nr_programs,
568 sizeof(*tas_fmw->programs), GFP_KERNEL);
569 if (!tas_fmw->programs)
570 return -ENOMEM;
571
572 for (i = 0; i < tas_fmw->nr_programs; i++) {
573 program = &tas_fmw->programs[i];
574 program->prog_size = get_unaligned_be32(&buf[offset]);
575 offset += 4;
576 }
577
578 /* Skip the unused prog_size */
579 offset += 4 * (TASDEVICE_MAXPROGRAM_NUM_KERNEL - tas_fmw->nr_programs);
580
581 tas_fmw->nr_configurations = get_unaligned_be32(&buf[offset]);
582 offset += 4;
583
584 /*
585 * The max number of config in firmware greater than 4 pieces of
586 * tas2781s is different from the one lower than 4 pieces of
587 * tas2781s.
588 */
589 max_confs = TASDEVICE_MAXCONFIG_NUM_KERNEL;
590 if (tas_fmw->nr_configurations == 0 ||
591 tas_fmw->nr_configurations > max_confs) {
592 dev_err(tas_priv->dev, "%s: Conf is invalid\n", __func__);
593 kfree(tas_fmw->programs);
594 return -EINVAL;
595 }
596
597 if (offset + 4 * max_confs > fmw->size) {
598 dev_err(tas_priv->dev, "%s: mpConfigurations err\n", __func__);
599 kfree(tas_fmw->programs);
600 return -EINVAL;
601 }
602
603 tas_fmw->configs = kcalloc(tas_fmw->nr_configurations,
604 sizeof(*tas_fmw->configs), GFP_KERNEL);
605 if (!tas_fmw->configs) {
606 kfree(tas_fmw->programs);
607 return -ENOMEM;
608 }
609
610 for (i = 0; i < tas_fmw->nr_programs; i++) {
611 config = &tas_fmw->configs[i];
612 config->cfg_size = get_unaligned_be32(&buf[offset]);
613 offset += 4;
614 }
615
616 /* Skip the unused configs */
617 offset += 4 * (max_confs - tas_fmw->nr_programs);
618
619 return offset;
620 }
621
622 /*
623 * In sub-block data, have three type sub-block:
624 * 1. Single byte write.
625 * 2. Multi-byte write.
626 * 3. Delay.
627 * 4. Bits update.
628 * This function perform single byte write to device.
629 */
tasdevice_single_byte_wr(void * context,int dev_idx,unsigned char * data,int sublocksize)630 static int tasdevice_single_byte_wr(void *context, int dev_idx,
631 unsigned char *data, int sublocksize)
632 {
633 struct tasdevice_priv *tas_priv = context;
634 unsigned short len = get_unaligned_be16(&data[2]);
635 int i, subblk_offset, rc;
636
637 subblk_offset = 4;
638 if (subblk_offset + 4 * len > sublocksize) {
639 dev_err(tas_priv->dev, "process_block: Out of boundary\n");
640 return 0;
641 }
642
643 for (i = 0; i < len; i++) {
644 if (dev_idx == (tas_priv->index + 1) || dev_idx == 0) {
645 rc = tasdevice_spi_dev_write(tas_priv,
646 TASDEVICE_REG(data[subblk_offset],
647 data[subblk_offset + 1],
648 data[subblk_offset + 2]),
649 data[subblk_offset + 3]);
650 if (rc < 0) {
651 dev_err(tas_priv->dev,
652 "process_block: single write error\n");
653 subblk_offset |= OFFSET_ERROR_BIT;
654 }
655 }
656 subblk_offset += 4;
657 }
658
659 return subblk_offset;
660 }
661
662 /*
663 * In sub-block data, have three type sub-block:
664 * 1. Single byte write.
665 * 2. Multi-byte write.
666 * 3. Delay.
667 * 4. Bits update.
668 * This function perform multi-write to device.
669 */
tasdevice_burst_wr(void * context,int dev_idx,unsigned char * data,int sublocksize)670 static int tasdevice_burst_wr(void *context, int dev_idx, unsigned char *data,
671 int sublocksize)
672 {
673 struct tasdevice_priv *tas_priv = context;
674 unsigned short len = get_unaligned_be16(&data[2]);
675 int subblk_offset, rc;
676
677 subblk_offset = 4;
678 if (subblk_offset + 4 + len > sublocksize) {
679 dev_err(tas_priv->dev, "%s: BST Out of boundary\n", __func__);
680 subblk_offset |= OFFSET_ERROR_BIT;
681 }
682 if (len % 4) {
683 dev_err(tas_priv->dev, "%s:Bst-len(%u)not div by 4\n",
684 __func__, len);
685 subblk_offset |= OFFSET_ERROR_BIT;
686 }
687
688 if (dev_idx == (tas_priv->index + 1) || dev_idx == 0) {
689 rc = tasdevice_spi_dev_bulk_write(tas_priv,
690 TASDEVICE_REG(data[subblk_offset],
691 data[subblk_offset + 1],
692 data[subblk_offset + 2]),
693 &data[subblk_offset + 4], len);
694 if (rc < 0) {
695 dev_err(tas_priv->dev, "%s: bulk_write error = %d\n",
696 __func__, rc);
697 subblk_offset |= OFFSET_ERROR_BIT;
698 }
699 }
700 subblk_offset += (len + 4);
701
702 return subblk_offset;
703 }
704
705 /* Just delay for ms.*/
tasdevice_delay(void * context,int dev_idx,unsigned char * data,int sublocksize)706 static int tasdevice_delay(void *context, int dev_idx, unsigned char *data,
707 int sublocksize)
708 {
709 struct tasdevice_priv *tas_priv = context;
710 unsigned int sleep_time, subblk_offset = 2;
711
712 if (subblk_offset + 2 > sublocksize) {
713 dev_err(tas_priv->dev, "%s: delay Out of boundary\n",
714 __func__);
715 subblk_offset |= OFFSET_ERROR_BIT;
716 }
717 if (dev_idx == (tas_priv->index + 1) || dev_idx == 0) {
718 sleep_time = get_unaligned_be16(&data[2]) * 1000;
719 fsleep(sleep_time);
720 }
721 subblk_offset += 2;
722
723 return subblk_offset;
724 }
725
726 /*
727 * In sub-block data, have three type sub-block:
728 * 1. Single byte write.
729 * 2. Multi-byte write.
730 * 3. Delay.
731 * 4. Bits update.
732 * This function perform bits update.
733 */
tasdevice_field_wr(void * context,int dev_idx,unsigned char * data,int sublocksize)734 static int tasdevice_field_wr(void *context, int dev_idx, unsigned char *data,
735 int sublocksize)
736 {
737 struct tasdevice_priv *tas_priv = context;
738 int rc, subblk_offset = 2;
739
740 if (subblk_offset + 6 > sublocksize) {
741 dev_err(tas_priv->dev, "%s: bit write Out of boundary\n",
742 __func__);
743 subblk_offset |= OFFSET_ERROR_BIT;
744 }
745 if (dev_idx == (tas_priv->index + 1) || dev_idx == 0) {
746 rc = tasdevice_spi_dev_update_bits(tas_priv,
747 TASDEVICE_REG(data[subblk_offset + 2],
748 data[subblk_offset + 3],
749 data[subblk_offset + 4]),
750 data[subblk_offset + 1],
751 data[subblk_offset + 5]);
752 if (rc < 0) {
753 dev_err(tas_priv->dev, "%s: update_bits error = %d\n",
754 __func__, rc);
755 subblk_offset |= OFFSET_ERROR_BIT;
756 }
757 }
758 subblk_offset += 6;
759
760 return subblk_offset;
761 }
762
763 /* Data block process function. */
tasdevice_process_block(void * context,unsigned char * data,unsigned char dev_idx,int sublocksize)764 static int tasdevice_process_block(void *context, unsigned char *data,
765 unsigned char dev_idx, int sublocksize)
766 {
767 struct tasdevice_priv *tas_priv = context;
768 int blktyp = dev_idx & 0xC0, subblk_offset;
769 unsigned char subblk_typ = data[1];
770
771 switch (subblk_typ) {
772 case TASDEVICE_CMD_SING_W:
773 subblk_offset = tasdevice_single_byte_wr(tas_priv,
774 dev_idx & 0x3f, data, sublocksize);
775 break;
776 case TASDEVICE_CMD_BURST:
777 subblk_offset = tasdevice_burst_wr(tas_priv,
778 dev_idx & 0x3f, data, sublocksize);
779 break;
780 case TASDEVICE_CMD_DELAY:
781 subblk_offset = tasdevice_delay(tas_priv,
782 dev_idx & 0x3f, data, sublocksize);
783 break;
784 case TASDEVICE_CMD_FIELD_W:
785 subblk_offset = tasdevice_field_wr(tas_priv,
786 dev_idx & 0x3f, data, sublocksize);
787 break;
788 default:
789 subblk_offset = 2;
790 break;
791 }
792 if (((subblk_offset & OFFSET_ERROR_BIT) != 0) && blktyp != 0) {
793 if (blktyp == 0x80) {
794 tas_priv->cur_prog = -1;
795 tas_priv->cur_conf = -1;
796 } else
797 tas_priv->cur_conf = -1;
798 }
799 subblk_offset &= ~OFFSET_ERROR_BIT;
800
801 return subblk_offset;
802 }
803
804 /*
805 * Device support different configurations for different scene,
806 * this function was used for choose different config.
807 */
tasdevice_spi_select_cfg_blk(void * pContext,int conf_no,unsigned char block_type)808 void tasdevice_spi_select_cfg_blk(void *pContext, int conf_no,
809 unsigned char block_type)
810 {
811 struct tasdevice_priv *tas_priv = pContext;
812 struct tasdevice_rca *rca = &tas_priv->rcabin;
813 struct tasdevice_config_info **cfg_info = rca->cfg_info;
814 struct tasdev_blk_data **blk_data;
815 unsigned int j, k;
816
817 if (conf_no >= rca->ncfgs || conf_no < 0 || !cfg_info) {
818 dev_err(tas_priv->dev, "conf_no should be not more than %u\n",
819 rca->ncfgs);
820 return;
821 }
822 blk_data = cfg_info[conf_no]->blk_data;
823
824 for (j = 0; j < cfg_info[conf_no]->real_nblocks; j++) {
825 unsigned int length = 0, rc = 0;
826
827 if (block_type > 5 || block_type < 2) {
828 dev_err(tas_priv->dev,
829 "block_type should be in range from 2 to 5\n");
830 break;
831 }
832 if (block_type != blk_data[j]->block_type)
833 continue;
834
835 for (k = 0; k < blk_data[j]->n_subblks; k++) {
836 tas_priv->is_loading = true;
837
838 rc = tasdevice_process_block(tas_priv,
839 blk_data[j]->regdata + length,
840 blk_data[j]->dev_idx,
841 blk_data[j]->block_size - length);
842 length += rc;
843 if (blk_data[j]->block_size < length) {
844 dev_err(tas_priv->dev,
845 "%s: %u %u out of boundary\n",
846 __func__, length,
847 blk_data[j]->block_size);
848 break;
849 }
850 }
851 if (length != blk_data[j]->block_size)
852 dev_err(tas_priv->dev, "%s: %u %u size is not same\n",
853 __func__, length, blk_data[j]->block_size);
854 }
855 }
856
857 /* Block process function. */
tasdevice_load_block_kernel(struct tasdevice_priv * tasdevice,struct tasdev_blk * block)858 static int tasdevice_load_block_kernel(
859 struct tasdevice_priv *tasdevice, struct tasdev_blk *block)
860 {
861 const unsigned int blk_size = block->blk_size;
862 unsigned char *data = block->data;
863 unsigned int i, length;
864
865 for (i = 0, length = 0; i < block->nr_subblocks; i++) {
866 int rc = tasdevice_process_block(tasdevice, data + length,
867 block->dev_idx, blk_size - length);
868 if (rc < 0) {
869 dev_err(tasdevice->dev,
870 "%s: %u %u sublock write error\n",
871 __func__, length, blk_size);
872 return rc;
873 }
874 length += rc;
875 if (blk_size < length) {
876 dev_err(tasdevice->dev, "%s: %u %u out of boundary\n",
877 __func__, length, blk_size);
878 rc = -ENOMEM;
879 return rc;
880 }
881 }
882
883 return 0;
884 }
885
886 /* DSP firmware file header parser function. */
fw_parse_variable_hdr(struct tasdevice_priv * tas_priv,struct tasdevice_dspfw_hdr * fw_hdr,const struct firmware * fmw,int offset)887 static int fw_parse_variable_hdr(struct tasdevice_priv *tas_priv,
888 struct tasdevice_dspfw_hdr *fw_hdr,
889 const struct firmware *fmw, int offset)
890 {
891 const unsigned char *buf = fmw->data;
892 int len = strlen((char *)&buf[offset]);
893
894 len++;
895
896 if (offset + len + 8 > fmw->size) {
897 dev_err(tas_priv->dev, "%s: File Size error\n", __func__);
898 return -EINVAL;
899 }
900
901 offset += len;
902
903 fw_hdr->device_family = get_unaligned_be32(&buf[offset]);
904 if (fw_hdr->device_family != 0) {
905 dev_err(tas_priv->dev, "%s: not TAS device\n", __func__);
906 return -EINVAL;
907 }
908 offset += 4;
909
910 fw_hdr->device = get_unaligned_be32(&buf[offset]);
911 if (fw_hdr->device >= TASDEVICE_DSP_TAS_MAX_DEVICE ||
912 fw_hdr->device == 6) {
913 dev_err(tas_priv->dev, "Unsupported dev %d\n", fw_hdr->device);
914 return -EINVAL;
915 }
916 offset += 4;
917 fw_hdr->ndev = 1;
918
919 return offset;
920 }
921
922 /* DSP firmware file header parser function for size variabled header. */
fw_parse_variable_header_git(struct tasdevice_priv * tas_priv,const struct firmware * fmw,int offset)923 static int fw_parse_variable_header_git(struct tasdevice_priv
924 *tas_priv, const struct firmware *fmw, int offset)
925 {
926 struct tasdevice_fw *tas_fmw = tas_priv->fmw;
927 struct tasdevice_dspfw_hdr *fw_hdr = &tas_fmw->fw_hdr;
928
929 offset = fw_parse_variable_hdr(tas_priv, fw_hdr, fmw, offset);
930
931 return offset;
932 }
933
934 /* DSP firmware file block parser function. */
fw_parse_block_data(struct tasdevice_fw * tas_fmw,struct tasdev_blk * block,const struct firmware * fmw,int offset)935 static int fw_parse_block_data(struct tasdevice_fw *tas_fmw,
936 struct tasdev_blk *block, const struct firmware *fmw, int offset)
937 {
938 unsigned char *data = (unsigned char *)fmw->data;
939 int n;
940
941 if (offset + 8 > fmw->size) {
942 dev_err(tas_fmw->dev, "%s: Type error\n", __func__);
943 return -EINVAL;
944 }
945 block->type = get_unaligned_be32(&data[offset]);
946 offset += 4;
947
948 if (tas_fmw->fw_hdr.fixed_hdr.drv_ver >= PPC_DRIVER_CRCCHK) {
949 if (offset + 8 > fmw->size) {
950 dev_err(tas_fmw->dev, "PChkSumPresent error\n");
951 return -EINVAL;
952 }
953 block->is_pchksum_present = data[offset];
954 offset++;
955
956 block->pchksum = data[offset];
957 offset++;
958
959 block->is_ychksum_present = data[offset];
960 offset++;
961
962 block->ychksum = data[offset];
963 offset++;
964 } else {
965 block->is_pchksum_present = 0;
966 block->is_ychksum_present = 0;
967 }
968
969 block->nr_cmds = get_unaligned_be32(&data[offset]);
970 offset += 4;
971
972 n = block->nr_cmds * 4;
973 if (offset + n > fmw->size) {
974 dev_err(tas_fmw->dev,
975 "%s: File Size(%lu) error offset = %d n = %d\n",
976 __func__, (unsigned long)fmw->size, offset, n);
977 return -EINVAL;
978 }
979 /* instead of kzalloc+memcpy */
980 block->data = kmemdup(&data[offset], n, GFP_KERNEL);
981 if (!block->data)
982 return -ENOMEM;
983
984 offset += n;
985
986 return offset;
987 }
988
989 /*
990 * When parsing error occurs, all the memory resource will be released
991 * in the end of tasdevice_rca_ready.
992 */
fw_parse_data(struct tasdevice_fw * tas_fmw,struct tasdevice_data * img_data,const struct firmware * fmw,int offset)993 static int fw_parse_data(struct tasdevice_fw *tas_fmw,
994 struct tasdevice_data *img_data, const struct firmware *fmw,
995 int offset)
996 {
997 const unsigned char *data = (unsigned char *)fmw->data;
998 struct tasdev_blk *blk;
999 unsigned int i, n;
1000
1001 if (offset + 64 > fmw->size) {
1002 dev_err(tas_fmw->dev, "%s: Name error\n", __func__);
1003 return -EINVAL;
1004 }
1005 memcpy(img_data->name, &data[offset], 64);
1006 offset += 64;
1007
1008 n = strlen((char *)&data[offset]);
1009 n++;
1010 if (offset + n + 2 > fmw->size) {
1011 dev_err(tas_fmw->dev, "%s: Description error\n", __func__);
1012 return -EINVAL;
1013 }
1014 offset += n;
1015 img_data->nr_blk = get_unaligned_be16(&data[offset]);
1016 offset += 2;
1017
1018 img_data->dev_blks = kcalloc(img_data->nr_blk,
1019 sizeof(*img_data->dev_blks), GFP_KERNEL);
1020 if (!img_data->dev_blks)
1021 return -ENOMEM;
1022
1023 for (i = 0; i < img_data->nr_blk; i++) {
1024 blk = &img_data->dev_blks[i];
1025 offset = fw_parse_block_data(tas_fmw, blk, fmw, offset);
1026 if (offset < 0)
1027 return -EINVAL;
1028 }
1029
1030 return offset;
1031 }
1032
1033 /*
1034 * When parsing error occurs, all the memory resource will be released
1035 * in the end of tasdevice_rca_ready.
1036 */
fw_parse_program_data(struct tasdevice_priv * tas_priv,struct tasdevice_fw * tas_fmw,const struct firmware * fmw,int offset)1037 static int fw_parse_program_data(struct tasdevice_priv *tas_priv,
1038 struct tasdevice_fw *tas_fmw, const struct firmware *fmw, int offset)
1039 {
1040 unsigned char *buf = (unsigned char *)fmw->data;
1041 struct tasdevice_prog *program;
1042 int i;
1043
1044 if (offset + 2 > fmw->size) {
1045 dev_err(tas_priv->dev, "%s: File Size error\n", __func__);
1046 return -EINVAL;
1047 }
1048 tas_fmw->nr_programs = get_unaligned_be16(&buf[offset]);
1049 offset += 2;
1050
1051 if (tas_fmw->nr_programs == 0) {
1052 /* Not error in calibration Data file, return directly */
1053 dev_dbg(tas_priv->dev, "%s: No Programs data, maybe calbin\n",
1054 __func__);
1055 return offset;
1056 }
1057
1058 tas_fmw->programs =
1059 kcalloc(tas_fmw->nr_programs, sizeof(*tas_fmw->programs),
1060 GFP_KERNEL);
1061 if (!tas_fmw->programs)
1062 return -ENOMEM;
1063
1064 for (i = 0; i < tas_fmw->nr_programs; i++) {
1065 int n = 0;
1066
1067 program = &tas_fmw->programs[i];
1068 if (offset + 64 > fmw->size) {
1069 dev_err(tas_priv->dev, "%s: mpName error\n", __func__);
1070 return -EINVAL;
1071 }
1072 offset += 64;
1073
1074 n = strlen((char *)&buf[offset]);
1075 /* skip '\0' and 5 unused bytes */
1076 n += 6;
1077 if (offset + n > fmw->size) {
1078 dev_err(tas_priv->dev, "Description err\n");
1079 return -EINVAL;
1080 }
1081
1082 offset += n;
1083
1084 offset = fw_parse_data(tas_fmw, &program->dev_data, fmw,
1085 offset);
1086 if (offset < 0)
1087 return offset;
1088 }
1089
1090 return offset;
1091 }
1092
1093 /*
1094 * When parsing error occurs, all the memory resource will be released
1095 * in the end of tasdevice_rca_ready.
1096 */
fw_parse_configuration_data(struct tasdevice_priv * tas_priv,struct tasdevice_fw * tas_fmw,const struct firmware * fmw,int offset)1097 static int fw_parse_configuration_data(struct tasdevice_priv *tas_priv,
1098 struct tasdevice_fw *tas_fmw, const struct firmware *fmw, int offset)
1099 {
1100 unsigned char *data = (unsigned char *)fmw->data;
1101 struct tasdevice_config *config;
1102 unsigned int i, n;
1103
1104 if (offset + 2 > fmw->size) {
1105 dev_err(tas_priv->dev, "%s: File Size error\n", __func__);
1106 return -EINVAL;
1107 }
1108 tas_fmw->nr_configurations = get_unaligned_be16(&data[offset]);
1109 offset += 2;
1110
1111 if (tas_fmw->nr_configurations == 0) {
1112 dev_err(tas_priv->dev, "%s: Conf is zero\n", __func__);
1113 /* Not error for calibration Data file, return directly */
1114 return offset;
1115 }
1116 tas_fmw->configs = kcalloc(tas_fmw->nr_configurations,
1117 sizeof(*tas_fmw->configs), GFP_KERNEL);
1118 if (!tas_fmw->configs)
1119 return -ENOMEM;
1120 for (i = 0; i < tas_fmw->nr_configurations; i++) {
1121 config = &tas_fmw->configs[i];
1122 if (offset + 64 > fmw->size) {
1123 dev_err(tas_priv->dev, "File Size err\n");
1124 return -EINVAL;
1125 }
1126 memcpy(config->name, &data[offset], 64);
1127 offset += 64;
1128
1129 n = strlen((char *)&data[offset]);
1130 n += 15;
1131 if (offset + n > fmw->size) {
1132 dev_err(tas_priv->dev, "Description err\n");
1133 return -EINVAL;
1134 }
1135 offset += n;
1136 offset = fw_parse_data(tas_fmw, &config->dev_data,
1137 fmw, offset);
1138 if (offset < 0)
1139 break;
1140 }
1141
1142 return offset;
1143 }
1144
1145 /* yram5 page check. */
check_inpage_yram_rg(struct tas_crc * cd,unsigned char reg,unsigned char len)1146 static bool check_inpage_yram_rg(struct tas_crc *cd,
1147 unsigned char reg, unsigned char len)
1148 {
1149 bool in = false;
1150
1151 if (reg <= TAS2781_YRAM5_END_REG &&
1152 reg >= TAS2781_YRAM5_START_REG) {
1153 if (reg + len > TAS2781_YRAM5_END_REG)
1154 cd->len = TAS2781_YRAM5_END_REG - reg + 1;
1155 else
1156 cd->len = len;
1157 cd->offset = reg;
1158 in = true;
1159 } else if (reg < TAS2781_YRAM5_START_REG) {
1160 if (reg + len > TAS2781_YRAM5_START_REG) {
1161 cd->offset = TAS2781_YRAM5_START_REG;
1162 cd->len = len - TAS2781_YRAM5_START_REG + reg;
1163 in = true;
1164 }
1165 }
1166
1167 return in;
1168 }
1169
1170 /* DSP firmware yram block check. */
check_inpage_yram_bk1(struct tas_crc * cd,unsigned char page,unsigned char reg,unsigned char len)1171 static bool check_inpage_yram_bk1(struct tas_crc *cd,
1172 unsigned char page, unsigned char reg, unsigned char len)
1173 {
1174 bool in = false;
1175
1176 if (page == TAS2781_YRAM1_PAGE) {
1177 if (reg >= TAS2781_YRAM1_START_REG) {
1178 cd->offset = reg;
1179 cd->len = len;
1180 in = true;
1181 } else if (reg + len > TAS2781_YRAM1_START_REG) {
1182 cd->offset = TAS2781_YRAM1_START_REG;
1183 cd->len = len - TAS2781_YRAM1_START_REG + reg;
1184 in = true;
1185 }
1186 } else if (page == TAS2781_YRAM3_PAGE) {
1187 in = check_inpage_yram_rg(cd, reg, len);
1188 }
1189
1190 return in;
1191 }
1192
1193 /*
1194 * Return Code:
1195 * true -- the registers are in the inpage yram
1196 * false -- the registers are NOT in the inpage yram
1197 */
check_inpage_yram(struct tas_crc * cd,unsigned char book,unsigned char page,unsigned char reg,unsigned char len)1198 static bool check_inpage_yram(struct tas_crc *cd, unsigned char book,
1199 unsigned char page, unsigned char reg, unsigned char len)
1200 {
1201 bool in = false;
1202
1203 if (book == TAS2781_YRAM_BOOK1)
1204 in = check_inpage_yram_bk1(cd, page, reg, len);
1205 else if (book == TAS2781_YRAM_BOOK2 && page == TAS2781_YRAM5_PAGE)
1206 in = check_inpage_yram_rg(cd, reg, len);
1207
1208 return in;
1209 }
1210
1211 /* yram4 page check. */
check_inblock_yram_bk(struct tas_crc * cd,unsigned char page,unsigned char reg,unsigned char len)1212 static bool check_inblock_yram_bk(struct tas_crc *cd,
1213 unsigned char page, unsigned char reg, unsigned char len)
1214 {
1215 bool in = false;
1216
1217 if ((page >= TAS2781_YRAM4_START_PAGE &&
1218 page <= TAS2781_YRAM4_END_PAGE) ||
1219 (page >= TAS2781_YRAM2_START_PAGE &&
1220 page <= TAS2781_YRAM2_END_PAGE)) {
1221 if (reg <= TAS2781_YRAM2_END_REG &&
1222 reg >= TAS2781_YRAM2_START_REG) {
1223 cd->offset = reg;
1224 cd->len = len;
1225 in = true;
1226 } else if (reg < TAS2781_YRAM2_START_REG) {
1227 if (reg + len - 1 >= TAS2781_YRAM2_START_REG) {
1228 cd->offset = TAS2781_YRAM2_START_REG;
1229 cd->len = reg + len - TAS2781_YRAM2_START_REG;
1230 in = true;
1231 }
1232 }
1233 }
1234
1235 return in;
1236 }
1237
1238 /*
1239 * Return Code:
1240 * true -- the registers are in the inblock yram
1241 * false -- the registers are NOT in the inblock yram
1242 */
check_inblock_yram(struct tas_crc * cd,unsigned char book,unsigned char page,unsigned char reg,unsigned char len)1243 static bool check_inblock_yram(struct tas_crc *cd, unsigned char book,
1244 unsigned char page, unsigned char reg, unsigned char len)
1245 {
1246 bool in = false;
1247
1248 if (book == TAS2781_YRAM_BOOK1 || book == TAS2781_YRAM_BOOK2)
1249 in = check_inblock_yram_bk(cd, page, reg, len);
1250
1251 return in;
1252 }
1253
1254 /* yram page check. */
check_yram(struct tas_crc * cd,unsigned char book,unsigned char page,unsigned char reg,unsigned char len)1255 static bool check_yram(struct tas_crc *cd, unsigned char book,
1256 unsigned char page, unsigned char reg, unsigned char len)
1257 {
1258 bool in;
1259
1260 in = check_inpage_yram(cd, book, page, reg, len);
1261 if (!in)
1262 in = check_inblock_yram(cd, book, page, reg, len);
1263
1264 return in;
1265 }
1266
1267 /* Checksum for data block. */
tasdev_multibytes_chksum(struct tasdevice_priv * tasdevice,unsigned char book,unsigned char page,unsigned char reg,unsigned int len)1268 static int tasdev_multibytes_chksum(struct tasdevice_priv *tasdevice,
1269 unsigned char book, unsigned char page,
1270 unsigned char reg, unsigned int len)
1271 {
1272 struct tas_crc crc_data;
1273 unsigned char crc_chksum = 0;
1274 unsigned char nBuf1[128];
1275 int ret = 0, i;
1276 bool in;
1277
1278 if ((reg + len - 1) > 127) {
1279 ret = -EINVAL;
1280 dev_err(tasdevice->dev, "firmware error\n");
1281 goto end;
1282 }
1283
1284 if ((book == TASDEVICE_BOOK_ID(TAS2781_SA_COEFF_SWAP_REG)) &&
1285 (page == TASDEVICE_PAGE_ID(TAS2781_SA_COEFF_SWAP_REG)) &&
1286 (reg == TASDEVICE_REG_ID(TAS2781_SA_COEFF_SWAP_REG)) &&
1287 (len == 4)) {
1288 /* DSP swap command, pass */
1289 ret = 0;
1290 goto end;
1291 }
1292
1293 in = check_yram(&crc_data, book, page, reg, len);
1294 if (!in)
1295 goto end;
1296
1297 if (len == 1) {
1298 dev_err(tasdevice->dev, "firmware error\n");
1299 ret = -EINVAL;
1300 goto end;
1301 }
1302
1303 ret = tasdevice_spi_dev_bulk_read(tasdevice,
1304 TASDEVICE_REG(book, page, crc_data.offset),
1305 nBuf1, crc_data.len);
1306 if (ret < 0)
1307 goto end;
1308
1309 for (i = 0; i < crc_data.len; i++) {
1310 if ((book == TASDEVICE_BOOK_ID(TAS2781_SA_COEFF_SWAP_REG)) &&
1311 (page == TASDEVICE_PAGE_ID(TAS2781_SA_COEFF_SWAP_REG)) &&
1312 ((i + crc_data.offset) >=
1313 TASDEVICE_REG_ID(TAS2781_SA_COEFF_SWAP_REG)) &&
1314 ((i + crc_data.offset) <=
1315 (TASDEVICE_REG_ID(TAS2781_SA_COEFF_SWAP_REG) + 4)))
1316 /* DSP swap command, bypass */
1317 continue;
1318 else
1319 crc_chksum += crc8(tasdevice->crc8_lkp_tbl, &nBuf1[i],
1320 1, 0);
1321 }
1322
1323 ret = crc_chksum;
1324
1325 end:
1326 return ret;
1327 }
1328
1329 /* Checksum for single register. */
do_singlereg_checksum(struct tasdevice_priv * tasdevice,unsigned char book,unsigned char page,unsigned char reg,unsigned char val)1330 static int do_singlereg_checksum(struct tasdevice_priv *tasdevice,
1331 unsigned char book, unsigned char page,
1332 unsigned char reg, unsigned char val)
1333 {
1334 struct tas_crc crc_data;
1335 unsigned int nData1;
1336 int ret = 0;
1337 bool in;
1338
1339 /* DSP swap command, pass */
1340 if ((book == TASDEVICE_BOOK_ID(TAS2781_SA_COEFF_SWAP_REG)) &&
1341 (page == TASDEVICE_PAGE_ID(TAS2781_SA_COEFF_SWAP_REG)) &&
1342 (reg >= TASDEVICE_REG_ID(TAS2781_SA_COEFF_SWAP_REG)) &&
1343 (reg <= (TASDEVICE_REG_ID(TAS2781_SA_COEFF_SWAP_REG) + 4)))
1344 return 0;
1345
1346 in = check_yram(&crc_data, book, page, reg, 1);
1347 if (!in)
1348 return 0;
1349 ret = tasdevice_spi_dev_read(tasdevice,
1350 TASDEVICE_REG(book, page, reg), &nData1);
1351 if (ret < 0)
1352 return ret;
1353
1354 if (nData1 != val) {
1355 dev_err(tasdevice->dev,
1356 "B[0x%x]P[0x%x]R[0x%x] W[0x%x], R[0x%x]\n",
1357 book, page, reg, val, nData1);
1358 tasdevice->err_code |= ERROR_YRAM_CRCCHK;
1359 return -EAGAIN;
1360 }
1361
1362 ret = crc8(tasdevice->crc8_lkp_tbl, &val, 1, 0);
1363
1364 return ret;
1365 }
1366
1367 /* Block type check. */
set_err_prg_cfg(unsigned int type,struct tasdevice_priv * p)1368 static void set_err_prg_cfg(unsigned int type, struct tasdevice_priv *p)
1369 {
1370 if ((type == MAIN_ALL_DEVICES) || (type == MAIN_DEVICE_A) ||
1371 (type == MAIN_DEVICE_B) || (type == MAIN_DEVICE_C) ||
1372 (type == MAIN_DEVICE_D))
1373 p->cur_prog = -1;
1374 else
1375 p->cur_conf = -1;
1376 }
1377
1378 /* Checksum for data bytes. */
tasdev_bytes_chksum(struct tasdevice_priv * tas_priv,struct tasdev_blk * block,unsigned char book,unsigned char page,unsigned char reg,unsigned int len,unsigned char val,unsigned char * crc_chksum)1379 static int tasdev_bytes_chksum(struct tasdevice_priv *tas_priv,
1380 struct tasdev_blk *block, unsigned char book,
1381 unsigned char page, unsigned char reg, unsigned int len,
1382 unsigned char val, unsigned char *crc_chksum)
1383 {
1384 int ret;
1385
1386 if (len > 1)
1387 ret = tasdev_multibytes_chksum(tas_priv, book, page, reg,
1388 len);
1389 else
1390 ret = do_singlereg_checksum(tas_priv, book, page, reg, val);
1391
1392 if (ret > 0) {
1393 *crc_chksum += ret;
1394 goto end;
1395 }
1396
1397 if (ret != -EAGAIN)
1398 goto end;
1399
1400 block->nr_retry--;
1401 if (block->nr_retry > 0)
1402 goto end;
1403
1404 set_err_prg_cfg(block->type, tas_priv);
1405
1406 end:
1407 return ret;
1408 }
1409
1410 /* Multi-data byte write. */
tasdev_multibytes_wr(struct tasdevice_priv * tas_priv,struct tasdev_blk * block,unsigned char book,unsigned char page,unsigned char reg,unsigned char * data,unsigned int len,unsigned int * nr_cmds,unsigned char * crc_chksum)1411 static int tasdev_multibytes_wr(struct tasdevice_priv *tas_priv,
1412 struct tasdev_blk *block, unsigned char book,
1413 unsigned char page, unsigned char reg, unsigned char *data,
1414 unsigned int len, unsigned int *nr_cmds,
1415 unsigned char *crc_chksum)
1416 {
1417 int ret;
1418
1419 if (len > 1) {
1420 ret = tasdevice_spi_dev_bulk_write(tas_priv,
1421 TASDEVICE_REG(book, page, reg), data + 3, len);
1422 if (ret < 0)
1423 return ret;
1424 if (block->is_ychksum_present)
1425 ret = tasdev_bytes_chksum(tas_priv, block,
1426 book, page, reg, len, 0, crc_chksum);
1427 } else {
1428 ret = tasdevice_spi_dev_write(tas_priv,
1429 TASDEVICE_REG(book, page, reg), data[3]);
1430 if (ret < 0)
1431 return ret;
1432 if (block->is_ychksum_present)
1433 ret = tasdev_bytes_chksum(tas_priv, block, book,
1434 page, reg, 1, data[3], crc_chksum);
1435 }
1436
1437 if (!block->is_ychksum_present || ret >= 0) {
1438 *nr_cmds += 1;
1439 if (len >= 2)
1440 *nr_cmds += ((len - 2) / 4) + 1;
1441 }
1442
1443 return ret;
1444 }
1445
1446 /* Checksum for block. */
tasdev_block_chksum(struct tasdevice_priv * tas_priv,struct tasdev_blk * block)1447 static int tasdev_block_chksum(struct tasdevice_priv *tas_priv,
1448 struct tasdev_blk *block)
1449 {
1450 unsigned int nr_value;
1451 int ret;
1452
1453 ret = tasdevice_spi_dev_read(tas_priv, TASDEVICE_CHECKSUM, &nr_value);
1454 if (ret < 0) {
1455 dev_err(tas_priv->dev, "%s: read error %d.\n", __func__, ret);
1456 set_err_prg_cfg(block->type, tas_priv);
1457 return ret;
1458 }
1459
1460 if ((nr_value & 0xff) != block->pchksum) {
1461 dev_err(tas_priv->dev, "%s: PChkSum err %d ", __func__, ret);
1462 dev_err(tas_priv->dev, "PChkSum = 0x%x, Reg = 0x%x\n",
1463 block->pchksum, (nr_value & 0xff));
1464 tas_priv->err_code |= ERROR_PRAM_CRCCHK;
1465 ret = -EAGAIN;
1466 block->nr_retry--;
1467
1468 if (block->nr_retry <= 0)
1469 set_err_prg_cfg(block->type, tas_priv);
1470 } else {
1471 tas_priv->err_code &= ~ERROR_PRAM_CRCCHK;
1472 }
1473
1474 return ret;
1475 }
1476
1477 /* Firmware block load function. */
tasdev_load_blk(struct tasdevice_priv * tas_priv,struct tasdev_blk * block)1478 static int tasdev_load_blk(struct tasdevice_priv *tas_priv,
1479 struct tasdev_blk *block)
1480 {
1481 unsigned int sleep_time, len, nr_cmds;
1482 unsigned char offset, book, page, val;
1483 unsigned char *data = block->data;
1484 unsigned char crc_chksum = 0;
1485 int ret = 0;
1486
1487 while (block->nr_retry > 0) {
1488 if (block->is_pchksum_present) {
1489 ret = tasdevice_spi_dev_write(tas_priv,
1490 TASDEVICE_CHECKSUM, 0);
1491 if (ret < 0)
1492 break;
1493 }
1494
1495 if (block->is_ychksum_present)
1496 crc_chksum = 0;
1497
1498 nr_cmds = 0;
1499
1500 while (nr_cmds < block->nr_cmds) {
1501 data = block->data + nr_cmds * 4;
1502
1503 book = data[0];
1504 page = data[1];
1505 offset = data[2];
1506 val = data[3];
1507
1508 nr_cmds++;
1509 /* Single byte write */
1510 if (offset <= 0x7F) {
1511 ret = tasdevice_spi_dev_write(tas_priv,
1512 TASDEVICE_REG(book, page, offset),
1513 val);
1514 if (ret < 0)
1515 break;
1516 if (block->is_ychksum_present) {
1517 ret = tasdev_bytes_chksum(tas_priv,
1518 block, book, page, offset,
1519 1, val, &crc_chksum);
1520 if (ret < 0)
1521 break;
1522 }
1523 continue;
1524 }
1525 /* sleep command */
1526 if (offset == 0x81) {
1527 /* book -- data[0] page -- data[1] */
1528 sleep_time = ((book << 8) + page)*1000;
1529 fsleep(sleep_time);
1530 continue;
1531 }
1532 /* Multiple bytes write */
1533 if (offset == 0x85) {
1534 data += 4;
1535 len = (book << 8) + page;
1536 book = data[0];
1537 page = data[1];
1538 offset = data[2];
1539 ret = tasdev_multibytes_wr(tas_priv,
1540 block, book, page, offset, data,
1541 len, &nr_cmds, &crc_chksum);
1542 if (ret < 0)
1543 break;
1544 }
1545 }
1546 if (ret == -EAGAIN) {
1547 if (block->nr_retry > 0)
1548 continue;
1549 } else if (ret < 0) {
1550 /* err in current device, skip it */
1551 break;
1552 }
1553
1554 if (block->is_pchksum_present) {
1555 ret = tasdev_block_chksum(tas_priv, block);
1556 if (ret == -EAGAIN) {
1557 if (block->nr_retry > 0)
1558 continue;
1559 } else if (ret < 0) {
1560 /* err in current device, skip it */
1561 break;
1562 }
1563 }
1564
1565 if (block->is_ychksum_present) {
1566 /* TBD, open it when FW ready */
1567 dev_err(tas_priv->dev,
1568 "Blk YChkSum: FW = 0x%x, YCRC = 0x%x\n",
1569 block->ychksum, crc_chksum);
1570
1571 tas_priv->err_code &=
1572 ~ERROR_YRAM_CRCCHK;
1573 ret = 0;
1574 }
1575 /* skip current blk */
1576 break;
1577 }
1578
1579 return ret;
1580 }
1581
1582 /* Firmware block load function. */
tasdevice_load_block(struct tasdevice_priv * tas_priv,struct tasdev_blk * block)1583 static int tasdevice_load_block(struct tasdevice_priv *tas_priv,
1584 struct tasdev_blk *block)
1585 {
1586 int ret = 0;
1587
1588 block->nr_retry = 6;
1589 if (tas_priv->is_loading == false)
1590 return 0;
1591 ret = tasdev_load_blk(tas_priv, block);
1592 if (ret < 0)
1593 dev_err(tas_priv->dev, "Blk (%d) load error\n", block->type);
1594
1595 return ret;
1596 }
1597
1598 /*
1599 * Select firmware binary parser & load callback functions by ppc3 version
1600 * and firmware binary version.
1601 */
dspfw_default_callback(struct tasdevice_priv * tas_priv,unsigned int drv_ver,unsigned int ppcver)1602 static int dspfw_default_callback(struct tasdevice_priv *tas_priv,
1603 unsigned int drv_ver, unsigned int ppcver)
1604 {
1605 int rc = 0;
1606
1607 if (drv_ver == 0x100) {
1608 if (ppcver >= PPC3_VERSION_BASE) {
1609 tas_priv->fw_parse_variable_header =
1610 fw_parse_variable_header_kernel;
1611 tas_priv->fw_parse_program_data =
1612 fw_parse_program_data_kernel;
1613 tas_priv->fw_parse_configuration_data =
1614 fw_parse_configuration_data_kernel;
1615 tas_priv->tasdevice_load_block =
1616 tasdevice_load_block_kernel;
1617 } else if (ppcver == 0x00) {
1618 tas_priv->fw_parse_variable_header =
1619 fw_parse_variable_header_git;
1620 tas_priv->fw_parse_program_data =
1621 fw_parse_program_data;
1622 tas_priv->fw_parse_configuration_data =
1623 fw_parse_configuration_data;
1624 tas_priv->tasdevice_load_block =
1625 tasdevice_load_block;
1626 } else {
1627 dev_err(tas_priv->dev,
1628 "Wrong PPCVer :0x%08x\n", ppcver);
1629 rc = -EINVAL;
1630 }
1631 } else {
1632 dev_err(tas_priv->dev, "Wrong DrvVer : 0x%02x\n", drv_ver);
1633 rc = -EINVAL;
1634 }
1635
1636 return rc;
1637 }
1638
1639 /* DSP firmware binary file header parser function. */
fw_parse_header(struct tasdevice_priv * tas_priv,struct tasdevice_fw * tas_fmw,const struct firmware * fmw,int offset)1640 static int fw_parse_header(struct tasdevice_priv *tas_priv,
1641 struct tasdevice_fw *tas_fmw, const struct firmware *fmw, int offset)
1642 {
1643 struct tasdevice_dspfw_hdr *fw_hdr = &tas_fmw->fw_hdr;
1644 struct tasdevice_fw_fixed_hdr *fw_fixed_hdr = &fw_hdr->fixed_hdr;
1645 static const unsigned char magic_number[] = {0x35, 0x35, 0x35, 0x32, };
1646 const unsigned char *buf = (unsigned char *)fmw->data;
1647
1648 if (offset + 92 > fmw->size) {
1649 dev_err(tas_priv->dev, "%s: File Size error\n", __func__);
1650 offset = -EINVAL;
1651 goto out;
1652 }
1653 if (memcmp(&buf[offset], magic_number, 4)) {
1654 dev_err(tas_priv->dev, "%s: Magic num NOT match\n", __func__);
1655 offset = -EINVAL;
1656 goto out;
1657 }
1658 offset += 4;
1659
1660 /*
1661 * Convert data[offset], data[offset + 1], data[offset + 2] and
1662 * data[offset + 3] into host
1663 */
1664 fw_fixed_hdr->fwsize = get_unaligned_be32(&buf[offset]);
1665 offset += 4;
1666 if (fw_fixed_hdr->fwsize != fmw->size) {
1667 dev_err(tas_priv->dev, "File size not match, %lu %u",
1668 (unsigned long)fmw->size, fw_fixed_hdr->fwsize);
1669 offset = -EINVAL;
1670 goto out;
1671 }
1672 offset += 4;
1673 fw_fixed_hdr->ppcver = get_unaligned_be32(&buf[offset]);
1674 offset += 8;
1675 fw_fixed_hdr->drv_ver = get_unaligned_be32(&buf[offset]);
1676 offset += 72;
1677
1678 out:
1679 return offset;
1680 }
1681
1682 /* DSP firmware binary file parser function. */
tasdevice_dspfw_ready(const struct firmware * fmw,void * context)1683 static int tasdevice_dspfw_ready(const struct firmware *fmw, void *context)
1684 {
1685 struct tasdevice_priv *tas_priv = context;
1686 struct tasdevice_fw_fixed_hdr *fw_fixed_hdr;
1687 struct tasdevice_fw *tas_fmw;
1688 int offset = 0, ret = 0;
1689
1690 if (!fmw || !fmw->data) {
1691 dev_err(tas_priv->dev, "%s: Failed to read firmware %s\n",
1692 __func__, tas_priv->coef_binaryname);
1693 return -EINVAL;
1694 }
1695
1696 tas_priv->fmw = kzalloc(sizeof(*tas_priv->fmw), GFP_KERNEL);
1697 if (!tas_priv->fmw)
1698 return -ENOMEM;
1699 tas_fmw = tas_priv->fmw;
1700 tas_fmw->dev = tas_priv->dev;
1701 offset = fw_parse_header(tas_priv, tas_fmw, fmw, offset);
1702
1703 if (offset == -EINVAL)
1704 return -EINVAL;
1705
1706 fw_fixed_hdr = &tas_fmw->fw_hdr.fixed_hdr;
1707 /* Support different versions of firmware */
1708 switch (fw_fixed_hdr->drv_ver) {
1709 case 0x301:
1710 case 0x302:
1711 case 0x502:
1712 case 0x503:
1713 tas_priv->fw_parse_variable_header =
1714 fw_parse_variable_header_kernel;
1715 tas_priv->fw_parse_program_data =
1716 fw_parse_program_data_kernel;
1717 tas_priv->fw_parse_configuration_data =
1718 fw_parse_configuration_data_kernel;
1719 tas_priv->tasdevice_load_block =
1720 tasdevice_load_block_kernel;
1721 break;
1722 case 0x202:
1723 case 0x400:
1724 tas_priv->fw_parse_variable_header =
1725 fw_parse_variable_header_git;
1726 tas_priv->fw_parse_program_data =
1727 fw_parse_program_data;
1728 tas_priv->fw_parse_configuration_data =
1729 fw_parse_configuration_data;
1730 tas_priv->tasdevice_load_block =
1731 tasdevice_load_block;
1732 break;
1733 default:
1734 ret = dspfw_default_callback(tas_priv,
1735 fw_fixed_hdr->drv_ver, fw_fixed_hdr->ppcver);
1736 if (ret)
1737 return ret;
1738 break;
1739 }
1740
1741 offset = tas_priv->fw_parse_variable_header(tas_priv, fmw, offset);
1742 if (offset < 0)
1743 return offset;
1744
1745 offset = tas_priv->fw_parse_program_data(tas_priv, tas_fmw, fmw,
1746 offset);
1747 if (offset < 0)
1748 return offset;
1749
1750 offset = tas_priv->fw_parse_configuration_data(tas_priv,
1751 tas_fmw, fmw, offset);
1752 if (offset < 0)
1753 ret = offset;
1754
1755 return ret;
1756 }
1757
1758 /* DSP firmware binary file parser function. */
tasdevice_spi_dsp_parser(void * context)1759 int tasdevice_spi_dsp_parser(void *context)
1760 {
1761 struct tasdevice_priv *tas_priv = context;
1762 const struct firmware *fw_entry;
1763 int ret;
1764
1765 ret = request_firmware(&fw_entry, tas_priv->coef_binaryname,
1766 tas_priv->dev);
1767 if (ret) {
1768 dev_err(tas_priv->dev, "%s: load %s error\n", __func__,
1769 tas_priv->coef_binaryname);
1770 return ret;
1771 }
1772
1773 ret = tasdevice_dspfw_ready(fw_entry, tas_priv);
1774 release_firmware(fw_entry);
1775 fw_entry = NULL;
1776
1777 return ret;
1778 }
1779
1780 /* DSP firmware program block data remove function. */
tasdev_dsp_prog_blk_remove(struct tasdevice_prog * prog)1781 static void tasdev_dsp_prog_blk_remove(struct tasdevice_prog *prog)
1782 {
1783 struct tasdevice_data *tas_dt;
1784 struct tasdev_blk *blk;
1785 unsigned int i;
1786
1787 if (!prog)
1788 return;
1789
1790 tas_dt = &prog->dev_data;
1791
1792 if (!tas_dt->dev_blks)
1793 return;
1794
1795 for (i = 0; i < tas_dt->nr_blk; i++) {
1796 blk = &tas_dt->dev_blks[i];
1797 kfree(blk->data);
1798 }
1799 kfree(tas_dt->dev_blks);
1800 }
1801
1802 /* DSP firmware program block data remove function. */
tasdev_dsp_prog_remove(struct tasdevice_prog * prog,unsigned short nr)1803 static void tasdev_dsp_prog_remove(struct tasdevice_prog *prog,
1804 unsigned short nr)
1805 {
1806 int i;
1807
1808 for (i = 0; i < nr; i++)
1809 tasdev_dsp_prog_blk_remove(&prog[i]);
1810 kfree(prog);
1811 }
1812
1813 /* DSP firmware config block data remove function. */
tasdev_dsp_cfg_blk_remove(struct tasdevice_config * cfg)1814 static void tasdev_dsp_cfg_blk_remove(struct tasdevice_config *cfg)
1815 {
1816 struct tasdevice_data *tas_dt;
1817 struct tasdev_blk *blk;
1818 unsigned int i;
1819
1820 if (cfg) {
1821 tas_dt = &cfg->dev_data;
1822
1823 if (!tas_dt->dev_blks)
1824 return;
1825
1826 for (i = 0; i < tas_dt->nr_blk; i++) {
1827 blk = &tas_dt->dev_blks[i];
1828 kfree(blk->data);
1829 }
1830 kfree(tas_dt->dev_blks);
1831 }
1832 }
1833
1834 /* DSP firmware config remove function. */
tasdev_dsp_cfg_remove(struct tasdevice_config * config,unsigned short nr)1835 static void tasdev_dsp_cfg_remove(struct tasdevice_config *config,
1836 unsigned short nr)
1837 {
1838 int i;
1839
1840 for (i = 0; i < nr; i++)
1841 tasdev_dsp_cfg_blk_remove(&config[i]);
1842 kfree(config);
1843 }
1844
1845 /* DSP firmware remove function. */
tasdevice_spi_dsp_remove(void * context)1846 void tasdevice_spi_dsp_remove(void *context)
1847 {
1848 struct tasdevice_priv *tas_dev = context;
1849
1850 if (!tas_dev->fmw)
1851 return;
1852
1853 if (tas_dev->fmw->programs)
1854 tasdev_dsp_prog_remove(tas_dev->fmw->programs,
1855 tas_dev->fmw->nr_programs);
1856 if (tas_dev->fmw->configs)
1857 tasdev_dsp_cfg_remove(tas_dev->fmw->configs,
1858 tas_dev->fmw->nr_configurations);
1859 kfree(tas_dev->fmw);
1860 tas_dev->fmw = NULL;
1861 }
1862
1863 /* DSP firmware calibration data remove function. */
tas2781_clear_calfirmware(struct tasdevice_fw * tas_fmw)1864 static void tas2781_clear_calfirmware(struct tasdevice_fw *tas_fmw)
1865 {
1866 struct tasdevice_calibration *calibration;
1867 struct tasdev_blk *block;
1868 unsigned int blks;
1869 int i;
1870
1871 if (!tas_fmw->calibrations)
1872 goto out;
1873
1874 for (i = 0; i < tas_fmw->nr_calibrations; i++) {
1875 calibration = &tas_fmw->calibrations[i];
1876 if (!calibration)
1877 continue;
1878
1879 if (!calibration->dev_data.dev_blks)
1880 continue;
1881
1882 for (blks = 0; blks < calibration->dev_data.nr_blk; blks++) {
1883 block = &calibration->dev_data.dev_blks[blks];
1884 if (!block)
1885 continue;
1886 kfree(block->data);
1887 }
1888 kfree(calibration->dev_data.dev_blks);
1889 }
1890 kfree(tas_fmw->calibrations);
1891 out:
1892 kfree(tas_fmw);
1893 }
1894
1895 /* Calibration data from firmware remove function. */
tasdevice_spi_calbin_remove(void * context)1896 void tasdevice_spi_calbin_remove(void *context)
1897 {
1898 struct tasdevice_priv *tas_priv = context;
1899
1900 if (tas_priv->cali_data_fmw) {
1901 tas2781_clear_calfirmware(tas_priv->cali_data_fmw);
1902 tas_priv->cali_data_fmw = NULL;
1903 }
1904 }
1905
1906 /* Configuration remove function. */
tasdevice_spi_config_info_remove(void * context)1907 void tasdevice_spi_config_info_remove(void *context)
1908 {
1909 struct tasdevice_priv *tas_priv = context;
1910 struct tasdevice_rca *rca = &tas_priv->rcabin;
1911 struct tasdevice_config_info **ci = rca->cfg_info;
1912 unsigned int i, j;
1913
1914 if (!ci)
1915 return;
1916 for (i = 0; i < rca->ncfgs; i++) {
1917 if (!ci[i])
1918 continue;
1919 if (ci[i]->blk_data) {
1920 for (j = 0; j < ci[i]->real_nblocks; j++) {
1921 if (!ci[i]->blk_data[j])
1922 continue;
1923 kfree(ci[i]->blk_data[j]->regdata);
1924 kfree(ci[i]->blk_data[j]);
1925 }
1926 kfree(ci[i]->blk_data);
1927 }
1928 kfree(ci[i]);
1929 }
1930 kfree(ci);
1931 }
1932
1933 /* DSP firmware program block data load function. */
tasdevice_load_data(struct tasdevice_priv * tas_priv,struct tasdevice_data * dev_data)1934 static int tasdevice_load_data(struct tasdevice_priv *tas_priv,
1935 struct tasdevice_data *dev_data)
1936 {
1937 struct tasdev_blk *block;
1938 unsigned int i;
1939 int ret = 0;
1940
1941 for (i = 0; i < dev_data->nr_blk; i++) {
1942 block = &dev_data->dev_blks[i];
1943 ret = tas_priv->tasdevice_load_block(tas_priv, block);
1944 if (ret < 0)
1945 break;
1946 }
1947
1948 return ret;
1949 }
1950
1951 /* DSP firmware program load interface function. */
tasdevice_spi_prmg_load(void * context,int prm_no)1952 int tasdevice_spi_prmg_load(void *context, int prm_no)
1953 {
1954 struct tasdevice_priv *tas_priv = context;
1955 struct tasdevice_fw *tas_fmw = tas_priv->fmw;
1956 struct tasdevice_prog *program;
1957 struct tasdevice_config *conf;
1958 int ret = 0;
1959
1960 if (!tas_fmw) {
1961 dev_err(tas_priv->dev, "%s: Firmware is NULL\n", __func__);
1962 return -EINVAL;
1963 }
1964 if (prm_no >= 0 && prm_no <= tas_fmw->nr_programs) {
1965 tas_priv->cur_conf = 0;
1966 tas_priv->is_loading = true;
1967 program = &tas_fmw->programs[prm_no];
1968 ret = tasdevice_load_data(tas_priv, &program->dev_data);
1969 if (ret < 0) {
1970 dev_err(tas_priv->dev, "Program failed %d.\n", ret);
1971 return ret;
1972 }
1973 tas_priv->cur_prog = prm_no;
1974
1975 conf = &tas_fmw->configs[tas_priv->cur_conf];
1976 ret = tasdevice_load_data(tas_priv, &conf->dev_data);
1977 if (ret < 0)
1978 dev_err(tas_priv->dev, "Config failed %d.\n", ret);
1979 } else {
1980 dev_err(tas_priv->dev,
1981 "%s: prm(%d) is not in range of Programs %u\n",
1982 __func__, prm_no, tas_fmw->nr_programs);
1983 return -EINVAL;
1984 }
1985
1986 return ret;
1987 }
1988
1989 /* RCABIN configuration switch interface function. */
tasdevice_spi_tuning_switch(void * context,int state)1990 void tasdevice_spi_tuning_switch(void *context, int state)
1991 {
1992 struct tasdevice_priv *tas_priv = context;
1993 int profile_cfg_id = tas_priv->rcabin.profile_cfg_id;
1994
1995 if (tas_priv->fw_state == TASDEVICE_DSP_FW_FAIL) {
1996 dev_err(tas_priv->dev, "DSP bin file not loaded\n");
1997 return;
1998 }
1999
2000 if (state == 0)
2001 tasdevice_spi_select_cfg_blk(tas_priv, profile_cfg_id,
2002 TASDEVICE_BIN_BLK_PRE_POWER_UP);
2003 else
2004 tasdevice_spi_select_cfg_blk(tas_priv, profile_cfg_id,
2005 TASDEVICE_BIN_BLK_PRE_SHUTDOWN);
2006 }
2007