~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/sound/soc/codecs/tas2781-fmwlib.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

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

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php