2402 lines · c
1// SPDX-License-Identifier: GPL-2.02//3// tas2781-fmwlib.c -- TASDEVICE firmware support4//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 <linux/unaligned.h>24 25#define ERROR_PRAM_CRCCHK 0x000000026#define ERROR_YRAM_CRCCHK 0x000000127#define PPC_DRIVER_CRCCHK 0x0000020028 29#define TAS2781_SA_COEFF_SWAP_REG TASDEVICE_REG(0, 0x35, 0x2c)30#define TAS2781_YRAM_BOOK1 14031#define TAS2781_YRAM1_PAGE 4232#define TAS2781_YRAM1_START_REG 8833 34#define TAS2781_YRAM2_START_PAGE 4335#define TAS2781_YRAM2_END_PAGE 4936#define TAS2781_YRAM2_START_REG 837#define TAS2781_YRAM2_END_REG 12738 39#define TAS2781_YRAM3_PAGE 5040#define TAS2781_YRAM3_START_REG 841#define TAS2781_YRAM3_END_REG 2742 43/*should not include B0_P53_R44-R47 */44#define TAS2781_YRAM_BOOK2 045#define TAS2781_YRAM4_START_PAGE 5046#define TAS2781_YRAM4_END_PAGE 6047 48#define TAS2781_YRAM5_PAGE 6149#define TAS2781_YRAM5_START_REG TAS2781_YRAM3_START_REG50#define TAS2781_YRAM5_END_REG TAS2781_YRAM3_END_REG51 52#define TASDEVICE_MAXPROGRAM_NUM_KERNEL 553#define TASDEVICE_MAXCONFIG_NUM_KERNEL_MULTIPLE_AMPS 6454#define TASDEVICE_MAXCONFIG_NUM_KERNEL 1055#define MAIN_ALL_DEVICES_1X 0x0156#define MAIN_DEVICE_A_1X 0x0257#define MAIN_DEVICE_B_1X 0x0358#define MAIN_DEVICE_C_1X 0x0459#define MAIN_DEVICE_D_1X 0x0560#define COEFF_DEVICE_A_1X 0x1261#define COEFF_DEVICE_B_1X 0x1362#define COEFF_DEVICE_C_1X 0x1463#define COEFF_DEVICE_D_1X 0x1564#define PRE_DEVICE_A_1X 0x2265#define PRE_DEVICE_B_1X 0x2366#define PRE_DEVICE_C_1X 0x2467#define PRE_DEVICE_D_1X 0x2568#define PRE_SOFTWARE_RESET_DEVICE_A 0x4169#define PRE_SOFTWARE_RESET_DEVICE_B 0x4270#define PRE_SOFTWARE_RESET_DEVICE_C 0x4371#define PRE_SOFTWARE_RESET_DEVICE_D 0x4472#define POST_SOFTWARE_RESET_DEVICE_A 0x4573#define POST_SOFTWARE_RESET_DEVICE_B 0x4674#define POST_SOFTWARE_RESET_DEVICE_C 0x4775#define POST_SOFTWARE_RESET_DEVICE_D 0x4876 77struct tas_crc {78 unsigned char offset;79 unsigned char len;80};81 82struct blktyp_devidx_map {83 unsigned char blktyp;84 unsigned char dev_idx;85};86 87static const char deviceNumber[TASDEVICE_DSP_TAS_MAX_DEVICE] = {88 1, 2, 1, 2, 1, 1, 0, 2, 4, 3, 1, 2, 3, 489};90 91/* fixed m68k compiling issue: mapping table can save code field */92static 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 116static 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 132static 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 148static 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 or160 * two of the chips will work for the special case, such as161 * ultrasonic application. In order to support these variable-numbers162 * of audio cases, flexible configs have been introduced in the163 * 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] and187 * data[offset + 3] into host188 */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 among194 * 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 else228 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 263out:264 return cfg_info;265}266 267int 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 }374out:375 return ret;376}377EXPORT_SYMBOL_NS_GPL(tasdevice_rca_parser, SND_SOC_TAS2781_FMWLIB);378 379/* fixed m68k compiling issue: mapping table can save code field */380static 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 410static 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] and422 * data[offset + 3] into host423 */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 unnecessary448 * time and system resource comsumption of dev_idx mapping every449 * 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 466out:467 return offset;468}469 470static 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 502out:503 return offset;504}505 506static 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 529out:530 return offset;531}532 533static 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 558out:559 return offset;560}561 562static 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 of634 * tas2781s is different from the one lower than 4 pieces of635 * 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 669out:670 return offset;671}672 673static 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 } else802 tas_priv->tasdevice[chn].cur_conf = -1;803 }804 }805 806 return subblk_offset;807}808 809void 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}865EXPORT_SYMBOL_NS_GPL(tasdevice_select_cfg_blk, SND_SOC_TAS2781_FMWLIB);866 867static 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 894static int fw_parse_variable_hdr(struct tasdevice_priv895 *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 929out:930 return offset;931}932 933static int fw_parse_variable_header_git(struct tasdevice_priv934 *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 949out:950 return offset;951}952 953static 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 1008out:1009 return offset;1010}1011 1012/* When parsing error occurs, all the memory resource will be released1013 * in the end of tasdevice_rca_ready.1014 */1015static 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 1058out:1059 return offset;1060}1061 1062/* When parsing error occurs, all the memory resource will be released1063 * in the end of tasdevice_rca_ready.1064 */1065static 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 1122out:1123 return offset;1124}1125 1126/* When parsing error occurs, all the memory resource will be released1127 * in the end of tasdevice_rca_ready.1128 */1129static 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 1184out:1185 return offset;1186}1187 1188static 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 else1199 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 1213static 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 yram1236 * false -- the registers are NOT in the inpage yram1237 */1238static 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 1250end:1251 return in;1252}1253 1254static 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 yram1282 * false -- the registers are NOT in the inblock yram1283 */1284static 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 1295static 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 1305end:1306 return in;1307}1308 1309static 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 else1363 crc_chksum += crc8(tasdevice->crc8_lkp_tbl, &nBuf1[i],1364 1, 0);1365 }1366 1367 ret = crc_chksum;1368 1369end:1370 return ret;1371}1372 1373static 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 1411end:1412 return ret;1413}1414 1415static 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 else1422 dev->cur_conf = -1;1423}1424 1425static 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 else1436 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 1453end:1454 return ret;1455}1456 1457static 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 1489end:1490 return ret;1491}1492 1493static 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 } else1520 tas_priv->tasdevice[chn].err_code &= ~ERROR_PRAM_CRCCHK;1521 1522end:1523 return ret;1524}1525 1526static 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 1628end:1629 return ret;1630}1631 1632static 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 1689static 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 1736static 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 1753static 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] and1774 * data[offset + 3] into host1775 */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 1794static 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 1809out:1810 return offset;1811}1812 1813/* When calibrated data parsing error occurs, DSP can still work with default1814 * calibrated data, memory resource related to calibrated data will be1815 * released in the tasdevice_codec_remove.1816 */1817static 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 1870out:1871 return offset;1872}1873 1874int 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 1940out:1941 if (fw_entry)1942 release_firmware(fw_entry);1943 1944 return ret;1945}1946EXPORT_SYMBOL_NS_GPL(tas2781_load_calibration, SND_SOC_TAS2781_FMWLIB);1947 1948static 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 case 0x401:1996 tas_priv->fw_parse_variable_header =1997 fw_parse_variable_header_git;1998 tas_priv->fw_parse_program_data =1999 fw_parse_program_data;2000 tas_priv->fw_parse_configuration_data =2001 fw_parse_configuration_data;2002 tas_priv->tasdevice_load_block =2003 tasdevice_load_block;2004 break;2005 default:2006 ret = dspfw_default_callback(tas_priv,2007 fw_fixed_hdr->drv_ver, fw_fixed_hdr->ppcver);2008 if (ret)2009 goto out;2010 break;2011 }2012 2013 offset = tas_priv->fw_parse_variable_header(tas_priv, fmw, offset);2014 if (offset < 0) {2015 ret = offset;2016 goto out;2017 }2018 offset = tas_priv->fw_parse_program_data(tas_priv, tas_fmw, fmw,2019 offset);2020 if (offset < 0) {2021 ret = offset;2022 goto out;2023 }2024 offset = tas_priv->fw_parse_configuration_data(tas_priv,2025 tas_fmw, fmw, offset);2026 if (offset < 0)2027 ret = offset;2028 2029out:2030 return ret;2031}2032 2033int tasdevice_dsp_parser(void *context)2034{2035 struct tasdevice_priv *tas_priv = (struct tasdevice_priv *)context;2036 const struct firmware *fw_entry;2037 int ret;2038 2039 ret = request_firmware(&fw_entry, tas_priv->coef_binaryname,2040 tas_priv->dev);2041 if (ret) {2042 dev_err(tas_priv->dev, "%s: load %s error\n", __func__,2043 tas_priv->coef_binaryname);2044 goto out;2045 }2046 2047 ret = tasdevice_dspfw_ready(fw_entry, tas_priv);2048 release_firmware(fw_entry);2049 fw_entry = NULL;2050 2051out:2052 return ret;2053}2054EXPORT_SYMBOL_NS_GPL(tasdevice_dsp_parser, SND_SOC_TAS2781_FMWLIB);2055 2056static void tas2781_clear_calfirmware(struct tasdevice_fw *tas_fmw)2057{2058 struct tasdevice_calibration *calibration;2059 struct tasdev_blk *block;2060 struct tasdevice_data *im;2061 unsigned int blks;2062 int i;2063 2064 if (!tas_fmw->calibrations)2065 goto out;2066 2067 for (i = 0; i < tas_fmw->nr_calibrations; i++) {2068 calibration = &(tas_fmw->calibrations[i]);2069 if (!calibration)2070 continue;2071 2072 im = &(calibration->dev_data);2073 2074 if (!im->dev_blks)2075 continue;2076 2077 for (blks = 0; blks < im->nr_blk; blks++) {2078 block = &(im->dev_blks[blks]);2079 if (!block)2080 continue;2081 kfree(block->data);2082 }2083 kfree(im->dev_blks);2084 }2085 kfree(tas_fmw->calibrations);2086out:2087 kfree(tas_fmw);2088}2089 2090void tasdevice_calbin_remove(void *context)2091{2092 struct tasdevice_priv *tas_priv = (struct tasdevice_priv *) context;2093 struct tasdevice *tasdev;2094 int i;2095 2096 if (!tas_priv)2097 return;2098 2099 for (i = 0; i < tas_priv->ndev; i++) {2100 tasdev = &(tas_priv->tasdevice[i]);2101 if (!tasdev->cali_data_fmw)2102 continue;2103 tas2781_clear_calfirmware(tasdev->cali_data_fmw);2104 tasdev->cali_data_fmw = NULL;2105 }2106}2107EXPORT_SYMBOL_NS_GPL(tasdevice_calbin_remove, SND_SOC_TAS2781_FMWLIB);2108 2109void tasdevice_config_info_remove(void *context)2110{2111 struct tasdevice_priv *tas_priv = (struct tasdevice_priv *) context;2112 struct tasdevice_rca *rca = &(tas_priv->rcabin);2113 struct tasdevice_config_info **ci = rca->cfg_info;2114 int i, j;2115 2116 if (!ci)2117 return;2118 for (i = 0; i < rca->ncfgs; i++) {2119 if (!ci[i])2120 continue;2121 if (ci[i]->blk_data) {2122 for (j = 0; j < (int)ci[i]->real_nblocks; j++) {2123 if (!ci[i]->blk_data[j])2124 continue;2125 kfree(ci[i]->blk_data[j]->regdata);2126 kfree(ci[i]->blk_data[j]);2127 }2128 kfree(ci[i]->blk_data);2129 }2130 kfree(ci[i]);2131 }2132 kfree(ci);2133}2134EXPORT_SYMBOL_NS_GPL(tasdevice_config_info_remove, SND_SOC_TAS2781_FMWLIB);2135 2136static int tasdevice_load_data(struct tasdevice_priv *tas_priv,2137 struct tasdevice_data *dev_data)2138{2139 struct tasdev_blk *block;2140 unsigned int i;2141 int ret = 0;2142 2143 for (i = 0; i < dev_data->nr_blk; i++) {2144 block = &(dev_data->dev_blks[i]);2145 ret = tas_priv->tasdevice_load_block(tas_priv, block);2146 if (ret < 0)2147 break;2148 }2149 2150 return ret;2151}2152 2153static void tasdev_load_calibrated_data(struct tasdevice_priv *priv, int i)2154{2155 struct tasdevice_fw *cal_fmw = priv->tasdevice[i].cali_data_fmw;2156 struct calidata *cali_data = &priv->cali_data;2157 struct cali_reg *p = &cali_data->cali_reg_array;2158 unsigned char *data = cali_data->data;2159 struct tasdevice_calibration *cal;2160 int k = i * (cali_data->cali_dat_sz_per_dev + 1);2161 int rc;2162 2163 /* Load the calibrated data from cal bin file */2164 if (!priv->is_user_space_calidata && cal_fmw) {2165 cal = cal_fmw->calibrations;2166 2167 if (cal)2168 load_calib_data(priv, &cal->dev_data);2169 return;2170 }2171 if (!priv->is_user_space_calidata)2172 return;2173 /* load calibrated data from user space */2174 if (data[k] != i) {2175 dev_err(priv->dev, "%s: no cal-data for dev %d from usr-spc\n",2176 __func__, i);2177 return;2178 }2179 k++;2180 2181 rc = tasdevice_dev_bulk_write(priv, i, p->r0_reg, &(data[k]), 4);2182 if (rc < 0) {2183 dev_err(priv->dev, "chn %d r0_reg bulk_wr err = %d\n", i, rc);2184 return;2185 }2186 k += 4;2187 rc = tasdevice_dev_bulk_write(priv, i, p->r0_low_reg, &(data[k]), 4);2188 if (rc < 0) {2189 dev_err(priv->dev, "chn %d r0_low_reg err = %d\n", i, rc);2190 return;2191 }2192 k += 4;2193 rc = tasdevice_dev_bulk_write(priv, i, p->invr0_reg, &(data[k]), 4);2194 if (rc < 0) {2195 dev_err(priv->dev, "chn %d invr0_reg err = %d\n", i, rc);2196 return;2197 }2198 k += 4;2199 rc = tasdevice_dev_bulk_write(priv, i, p->pow_reg, &(data[k]), 4);2200 if (rc < 0) {2201 dev_err(priv->dev, "chn %d pow_reg bulk_wr err = %d\n", i, rc);2202 return;2203 }2204 k += 4;2205 rc = tasdevice_dev_bulk_write(priv, i, p->tlimit_reg, &(data[k]), 4);2206 if (rc < 0) {2207 dev_err(priv->dev, "chn %d tlimit_reg err = %d\n", i, rc);2208 return;2209 }2210}2211 2212int tasdevice_select_tuningprm_cfg(void *context, int prm_no,2213 int cfg_no, int rca_conf_no)2214{2215 struct tasdevice_priv *tas_priv = (struct tasdevice_priv *) context;2216 struct tasdevice_rca *rca = &(tas_priv->rcabin);2217 struct tasdevice_config_info **cfg_info = rca->cfg_info;2218 struct tasdevice_fw *tas_fmw = tas_priv->fmw;2219 struct tasdevice_prog *program;2220 struct tasdevice_config *conf;2221 int prog_status = 0;2222 int status, i;2223 2224 if (!tas_fmw) {2225 dev_err(tas_priv->dev, "%s: Firmware is NULL\n", __func__);2226 goto out;2227 }2228 2229 if (cfg_no >= tas_fmw->nr_configurations) {2230 dev_err(tas_priv->dev,2231 "%s: cfg(%d) is not in range of conf %u\n",2232 __func__, cfg_no, tas_fmw->nr_configurations);2233 goto out;2234 }2235 2236 if (prm_no >= tas_fmw->nr_programs) {2237 dev_err(tas_priv->dev,2238 "%s: prm(%d) is not in range of Programs %u\n",2239 __func__, prm_no, tas_fmw->nr_programs);2240 goto out;2241 }2242 2243 if (rca_conf_no >= rca->ncfgs || rca_conf_no < 0 ||2244 !cfg_info) {2245 dev_err(tas_priv->dev,2246 "conf_no:%d should be in range from 0 to %u\n",2247 rca_conf_no, rca->ncfgs-1);2248 goto out;2249 }2250 2251 for (i = 0, prog_status = 0; i < tas_priv->ndev; i++) {2252 if (cfg_info[rca_conf_no]->active_dev & (1 << i)) {2253 if (prm_no >= 02254 && (tas_priv->tasdevice[i].cur_prog != prm_no2255 || tas_priv->force_fwload_status)) {2256 tas_priv->tasdevice[i].cur_conf = -1;2257 tas_priv->tasdevice[i].is_loading = true;2258 prog_status++;2259 }2260 } else2261 tas_priv->tasdevice[i].is_loading = false;2262 tas_priv->tasdevice[i].is_loaderr = false;2263 }2264 2265 if (prog_status) {2266 program = &(tas_fmw->programs[prm_no]);2267 tasdevice_load_data(tas_priv, &(program->dev_data));2268 for (i = 0; i < tas_priv->ndev; i++) {2269 if (tas_priv->tasdevice[i].is_loaderr == true)2270 continue;2271 if (tas_priv->tasdevice[i].is_loaderr == false &&2272 tas_priv->tasdevice[i].is_loading == true)2273 tas_priv->tasdevice[i].cur_prog = prm_no;2274 }2275 }2276 2277 for (i = 0, status = 0; i < tas_priv->ndev; i++) {2278 if (cfg_no >= 02279 && tas_priv->tasdevice[i].cur_conf != cfg_no2280 && (cfg_info[rca_conf_no]->active_dev & (1 << i))2281 && (tas_priv->tasdevice[i].is_loaderr == false)) {2282 status++;2283 tas_priv->tasdevice[i].is_loading = true;2284 } else2285 tas_priv->tasdevice[i].is_loading = false;2286 }2287 2288 if (status) {2289 conf = &(tas_fmw->configs[cfg_no]);2290 status = 0;2291 tasdevice_load_data(tas_priv, &(conf->dev_data));2292 for (i = 0; i < tas_priv->ndev; i++) {2293 if (tas_priv->tasdevice[i].is_loaderr == true) {2294 status |= BIT(i + 4);2295 continue;2296 }2297 2298 if (tas_priv->tasdevice[i].is_loaderr == false &&2299 tas_priv->tasdevice[i].is_loading == true) {2300 tasdev_load_calibrated_data(tas_priv, i);2301 tas_priv->tasdevice[i].cur_conf = cfg_no;2302 }2303 }2304 } else {2305 dev_dbg(tas_priv->dev, "%s: Unneeded loading dsp conf %d\n",2306 __func__, cfg_no);2307 }2308 2309 status |= cfg_info[rca_conf_no]->active_dev;2310 2311out:2312 return prog_status;2313}2314EXPORT_SYMBOL_NS_GPL(tasdevice_select_tuningprm_cfg,2315 SND_SOC_TAS2781_FMWLIB);2316 2317int tasdevice_prmg_load(void *context, int prm_no)2318{2319 struct tasdevice_priv *tas_priv = (struct tasdevice_priv *) context;2320 struct tasdevice_fw *tas_fmw = tas_priv->fmw;2321 struct tasdevice_prog *program;2322 int prog_status = 0;2323 int i;2324 2325 if (!tas_fmw) {2326 dev_err(tas_priv->dev, "%s: Firmware is NULL\n", __func__);2327 goto out;2328 }2329 2330 if (prm_no >= tas_fmw->nr_programs) {2331 dev_err(tas_priv->dev,2332 "%s: prm(%d) is not in range of Programs %u\n",2333 __func__, prm_no, tas_fmw->nr_programs);2334 goto out;2335 }2336 2337 for (i = 0, prog_status = 0; i < tas_priv->ndev; i++) {2338 if (prm_no >= 0 && tas_priv->tasdevice[i].cur_prog != prm_no) {2339 tas_priv->tasdevice[i].cur_conf = -1;2340 tas_priv->tasdevice[i].is_loading = true;2341 prog_status++;2342 }2343 }2344 2345 if (prog_status) {2346 program = &(tas_fmw->programs[prm_no]);2347 tasdevice_load_data(tas_priv, &(program->dev_data));2348 for (i = 0; i < tas_priv->ndev; i++) {2349 if (tas_priv->tasdevice[i].is_loaderr == true)2350 continue;2351 else if (tas_priv->tasdevice[i].is_loaderr == false2352 && tas_priv->tasdevice[i].is_loading == true)2353 tas_priv->tasdevice[i].cur_prog = prm_no;2354 }2355 }2356 2357out:2358 return prog_status;2359}2360EXPORT_SYMBOL_NS_GPL(tasdevice_prmg_load, SND_SOC_TAS2781_FMWLIB);2361 2362void tasdevice_tuning_switch(void *context, int state)2363{2364 struct tasdevice_priv *tas_priv = (struct tasdevice_priv *) context;2365 struct tasdevice_fw *tas_fmw = tas_priv->fmw;2366 int profile_cfg_id = tas_priv->rcabin.profile_cfg_id;2367 2368 /*2369 * Only RCA-based Playback can still work with no dsp program running2370 * inside the chip.2371 */2372 switch (tas_priv->fw_state) {2373 case TASDEVICE_RCA_FW_OK:2374 case TASDEVICE_DSP_FW_ALL_OK:2375 break;2376 default:2377 return;2378 }2379 2380 if (state == 0) {2381 if (tas_fmw && tas_priv->cur_prog < tas_fmw->nr_programs) {2382 /* dsp mode or tuning mode */2383 profile_cfg_id = tas_priv->rcabin.profile_cfg_id;2384 tasdevice_select_tuningprm_cfg(tas_priv,2385 tas_priv->cur_prog, tas_priv->cur_conf,2386 profile_cfg_id);2387 }2388 2389 tasdevice_select_cfg_blk(tas_priv, profile_cfg_id,2390 TASDEVICE_BIN_BLK_PRE_POWER_UP);2391 } else {2392 tasdevice_select_cfg_blk(tas_priv, profile_cfg_id,2393 TASDEVICE_BIN_BLK_PRE_SHUTDOWN);2394 }2395}2396EXPORT_SYMBOL_NS_GPL(tasdevice_tuning_switch,2397 SND_SOC_TAS2781_FMWLIB);2398 2399MODULE_DESCRIPTION("Texas Firmware Support");2400MODULE_AUTHOR("Shenghao Ding, TI, <shenghao-ding@ti.com>");2401MODULE_LICENSE("GPL");2402