diff options
Diffstat (limited to 'sound/soc/codecs/tas2781-fmwlib.c')
-rw-r--r-- | sound/soc/codecs/tas2781-fmwlib.c | 150 |
1 files changed, 99 insertions, 51 deletions
diff --git a/sound/soc/codecs/tas2781-fmwlib.c b/sound/soc/codecs/tas2781-fmwlib.c index 265a8ca25cbb..ae360c97fe1e 100644 --- a/sound/soc/codecs/tas2781-fmwlib.c +++ b/sound/soc/codecs/tas2781-fmwlib.c @@ -13,7 +13,6 @@ #include <linux/interrupt.h> #include <linux/module.h> #include <linux/of.h> -#include <linux/of_gpio.h> #include <linux/of_irq.h> #include <linux/regmap.h> #include <linux/slab.h> @@ -21,7 +20,7 @@ #include <sound/soc.h> #include <sound/tlv.h> #include <sound/tas2781.h> - +#include <linux/unaligned.h> #define ERROR_PRAM_CRCCHK 0x0000000 #define ERROR_YRAM_CRCCHK 0x0000001 @@ -187,8 +186,7 @@ static struct tasdevice_config_info *tasdevice_add_config( /* convert data[offset], data[offset + 1], data[offset + 2] and * data[offset + 3] into host */ - cfg_info->nblocks = - be32_to_cpup((__be32 *)&config_data[config_offset]); + cfg_info->nblocks = get_unaligned_be32(&config_data[config_offset]); config_offset += 4; /* Several kinds of dsp/algorithm firmwares can run on tas2781, @@ -232,14 +230,14 @@ static struct tasdevice_config_info *tasdevice_add_config( } bk_da[i]->yram_checksum = - be16_to_cpup((__be16 *)&config_data[config_offset]); + get_unaligned_be16(&config_data[config_offset]); config_offset += 2; bk_da[i]->block_size = - be32_to_cpup((__be32 *)&config_data[config_offset]); + get_unaligned_be32(&config_data[config_offset]); config_offset += 4; bk_da[i]->n_subblks = - be32_to_cpup((__be32 *)&config_data[config_offset]); + get_unaligned_be32(&config_data[config_offset]); config_offset += 4; @@ -289,7 +287,7 @@ int tasdevice_rca_parser(void *context, const struct firmware *fmw) } buf = (unsigned char *)fmw->data; - fw_hdr->img_sz = be32_to_cpup((__be32 *)&buf[offset]); + fw_hdr->img_sz = get_unaligned_be32(&buf[offset]); offset += 4; if (fw_hdr->img_sz != fmw->size) { dev_err(tas_priv->dev, @@ -300,9 +298,9 @@ int tasdevice_rca_parser(void *context, const struct firmware *fmw) goto out; } - fw_hdr->checksum = be32_to_cpup((__be32 *)&buf[offset]); + fw_hdr->checksum = get_unaligned_be32(&buf[offset]); offset += 4; - fw_hdr->binary_version_num = be32_to_cpup((__be32 *)&buf[offset]); + fw_hdr->binary_version_num = get_unaligned_be32(&buf[offset]); if (fw_hdr->binary_version_num < 0x103) { dev_err(tas_priv->dev, "File version 0x%04x is too low", fw_hdr->binary_version_num); @@ -311,7 +309,7 @@ int tasdevice_rca_parser(void *context, const struct firmware *fmw) goto out; } offset += 4; - fw_hdr->drv_fw_version = be32_to_cpup((__be32 *)&buf[offset]); + fw_hdr->drv_fw_version = get_unaligned_be32(&buf[offset]); offset += 8; fw_hdr->plat_type = buf[offset]; offset += 1; @@ -339,11 +337,11 @@ int tasdevice_rca_parser(void *context, const struct firmware *fmw) for (i = 0; i < TASDEVICE_DEVICE_SUM; i++, offset++) fw_hdr->devs[i] = buf[offset]; - fw_hdr->nconfig = be32_to_cpup((__be32 *)&buf[offset]); + fw_hdr->nconfig = get_unaligned_be32(&buf[offset]); offset += 4; for (i = 0; i < TASDEVICE_CONFIG_SUM; i++) { - fw_hdr->config_size[i] = be32_to_cpup((__be32 *)&buf[offset]); + fw_hdr->config_size[i] = get_unaligned_be32(&buf[offset]); offset += 4; total_config_sz += fw_hdr->config_size[i]; } @@ -423,7 +421,7 @@ static int fw_parse_block_data_kernel(struct tasdevice_fw *tas_fmw, /* convert data[offset], data[offset + 1], data[offset + 2] and * data[offset + 3] into host */ - block->type = be32_to_cpup((__be32 *)&data[offset]); + block->type = get_unaligned_be32(&data[offset]); offset += 4; block->is_pchksum_present = data[offset]; @@ -438,10 +436,10 @@ static int fw_parse_block_data_kernel(struct tasdevice_fw *tas_fmw, block->ychksum = data[offset]; offset++; - block->blk_size = be32_to_cpup((__be32 *)&data[offset]); + block->blk_size = get_unaligned_be32(&data[offset]); offset += 4; - block->nr_subblocks = be32_to_cpup((__be32 *)&data[offset]); + block->nr_subblocks = get_unaligned_be32(&data[offset]); offset += 4; /* fixed m68k compiling issue: @@ -482,7 +480,7 @@ static int fw_parse_data_kernel(struct tasdevice_fw *tas_fmw, offset = -EINVAL; goto out; } - img_data->nr_blk = be32_to_cpup((__be32 *)&data[offset]); + img_data->nr_blk = get_unaligned_be32(&data[offset]); offset += 4; img_data->dev_blks = kcalloc(img_data->nr_blk, @@ -578,14 +576,14 @@ static int fw_parse_variable_header_kernel( offset = -EINVAL; goto out; } - fw_hdr->device_family = be16_to_cpup((__be16 *)&buf[offset]); + fw_hdr->device_family = get_unaligned_be16(&buf[offset]); if (fw_hdr->device_family != 0) { dev_err(tas_priv->dev, "%s:not TAS device\n", __func__); offset = -EINVAL; goto out; } offset += 2; - fw_hdr->device = be16_to_cpup((__be16 *)&buf[offset]); + fw_hdr->device = get_unaligned_be16(&buf[offset]); if (fw_hdr->device >= TASDEVICE_DSP_TAS_MAX_DEVICE || fw_hdr->device == 6) { dev_err(tas_priv->dev, "Unsupported dev %d\n", fw_hdr->device); @@ -603,7 +601,7 @@ static int fw_parse_variable_header_kernel( goto out; } - tas_fmw->nr_programs = be32_to_cpup((__be32 *)&buf[offset]); + tas_fmw->nr_programs = get_unaligned_be32(&buf[offset]); offset += 4; if (tas_fmw->nr_programs == 0 || tas_fmw->nr_programs > @@ -622,14 +620,14 @@ static int fw_parse_variable_header_kernel( for (i = 0; i < tas_fmw->nr_programs; i++) { program = &(tas_fmw->programs[i]); - program->prog_size = be32_to_cpup((__be32 *)&buf[offset]); + program->prog_size = get_unaligned_be32(&buf[offset]); offset += 4; } /* Skip the unused prog_size */ offset += 4 * (TASDEVICE_MAXPROGRAM_NUM_KERNEL - tas_fmw->nr_programs); - tas_fmw->nr_configurations = be32_to_cpup((__be32 *)&buf[offset]); + tas_fmw->nr_configurations = get_unaligned_be32(&buf[offset]); offset += 4; /* The max number of config in firmware greater than 4 pieces of @@ -661,7 +659,7 @@ static int fw_parse_variable_header_kernel( for (i = 0; i < tas_fmw->nr_programs; i++) { config = &(tas_fmw->configs[i]); - config->cfg_size = be32_to_cpup((__be32 *)&buf[offset]); + config->cfg_size = get_unaligned_be32(&buf[offset]); offset += 4; } @@ -699,7 +697,7 @@ static int tasdevice_process_block(void *context, unsigned char *data, switch (subblk_typ) { case TASDEVICE_CMD_SING_W: { int i; - unsigned short len = be16_to_cpup((__be16 *)&data[2]); + unsigned short len = get_unaligned_be16(&data[2]); subblk_offset += 2; if (subblk_offset + 4 * len > sublocksize) { @@ -725,7 +723,7 @@ static int tasdevice_process_block(void *context, unsigned char *data, } break; case TASDEVICE_CMD_BURST: { - unsigned short len = be16_to_cpup((__be16 *)&data[2]); + unsigned short len = get_unaligned_be16(&data[2]); subblk_offset += 2; if (subblk_offset + 4 + len > sublocksize) { @@ -766,7 +764,7 @@ static int tasdevice_process_block(void *context, unsigned char *data, is_err = true; break; } - sleep_time = be16_to_cpup((__be16 *)&data[2]) * 1000; + sleep_time = get_unaligned_be16(&data[2]) * 1000; usleep_range(sleep_time, sleep_time + 50); subblk_offset += 2; } @@ -910,7 +908,7 @@ static int fw_parse_variable_hdr(struct tasdevice_priv offset += len; - fw_hdr->device_family = be32_to_cpup((__be32 *)&buf[offset]); + fw_hdr->device_family = get_unaligned_be32(&buf[offset]); if (fw_hdr->device_family != 0) { dev_err(tas_priv->dev, "%s: not TAS device\n", __func__); offset = -EINVAL; @@ -918,7 +916,7 @@ static int fw_parse_variable_hdr(struct tasdevice_priv } offset += 4; - fw_hdr->device = be32_to_cpup((__be32 *)&buf[offset]); + fw_hdr->device = get_unaligned_be32(&buf[offset]); if (fw_hdr->device >= TASDEVICE_DSP_TAS_MAX_DEVICE || fw_hdr->device == 6) { dev_err(tas_priv->dev, "Unsupported dev %d\n", fw_hdr->device); @@ -963,7 +961,7 @@ static int fw_parse_block_data(struct tasdevice_fw *tas_fmw, offset = -EINVAL; goto out; } - block->type = be32_to_cpup((__be32 *)&data[offset]); + block->type = get_unaligned_be32(&data[offset]); offset += 4; if (tas_fmw->fw_hdr.fixed_hdr.drv_ver >= PPC_DRIVER_CRCCHK) { @@ -988,7 +986,7 @@ static int fw_parse_block_data(struct tasdevice_fw *tas_fmw, block->is_ychksum_present = 0; } - block->nr_cmds = be32_to_cpup((__be32 *)&data[offset]); + block->nr_cmds = get_unaligned_be32(&data[offset]); offset += 4; n = block->nr_cmds * 4; @@ -1039,7 +1037,7 @@ static int fw_parse_data(struct tasdevice_fw *tas_fmw, goto out; } offset += n; - img_data->nr_blk = be16_to_cpup((__be16 *)&data[offset]); + img_data->nr_blk = get_unaligned_be16(&data[offset]); offset += 2; img_data->dev_blks = kcalloc(img_data->nr_blk, @@ -1076,7 +1074,7 @@ static int fw_parse_program_data(struct tasdevice_priv *tas_priv, offset = -EINVAL; goto out; } - tas_fmw->nr_programs = be16_to_cpup((__be16 *)&buf[offset]); + tas_fmw->nr_programs = get_unaligned_be16(&buf[offset]); offset += 2; if (tas_fmw->nr_programs == 0) { @@ -1143,7 +1141,7 @@ static int fw_parse_configuration_data( offset = -EINVAL; goto out; } - tas_fmw->nr_configurations = be16_to_cpup((__be16 *)&data[offset]); + tas_fmw->nr_configurations = get_unaligned_be16(&data[offset]); offset += 2; if (tas_fmw->nr_configurations == 0) { @@ -1775,7 +1773,7 @@ static int fw_parse_header(struct tasdevice_priv *tas_priv, /* Convert data[offset], data[offset + 1], data[offset + 2] and * data[offset + 3] into host */ - fw_fixed_hdr->fwsize = be32_to_cpup((__be32 *)&buf[offset]); + fw_fixed_hdr->fwsize = get_unaligned_be32(&buf[offset]); offset += 4; if (fw_fixed_hdr->fwsize != fmw->size) { dev_err(tas_priv->dev, "File size not match, %lu %u", @@ -1784,9 +1782,9 @@ static int fw_parse_header(struct tasdevice_priv *tas_priv, goto out; } offset += 4; - fw_fixed_hdr->ppcver = be32_to_cpup((__be32 *)&buf[offset]); + fw_fixed_hdr->ppcver = get_unaligned_be32(&buf[offset]); offset += 8; - fw_fixed_hdr->drv_ver = be32_to_cpup((__be32 *)&buf[offset]); + fw_fixed_hdr->drv_ver = get_unaligned_be32(&buf[offset]); offset += 72; out: @@ -1828,7 +1826,7 @@ static int fw_parse_calibration_data(struct tasdevice_priv *tas_priv, offset = -EINVAL; goto out; } - tas_fmw->nr_calibrations = be16_to_cpup((__be16 *)&data[offset]); + tas_fmw->nr_calibrations = get_unaligned_be16(&data[offset]); offset += 2; if (tas_fmw->nr_calibrations != 1) { @@ -2153,20 +2151,61 @@ static int tasdevice_load_data(struct tasdevice_priv *tas_priv, static void tasdev_load_calibrated_data(struct tasdevice_priv *priv, int i) { + struct tasdevice_fw *cal_fmw = priv->tasdevice[i].cali_data_fmw; + struct calidata *cali_data = &priv->cali_data; + struct cali_reg *p = &cali_data->cali_reg_array; + unsigned char *data = cali_data->data; struct tasdevice_calibration *cal; - struct tasdevice_fw *cal_fmw; + int k = i * (cali_data->cali_dat_sz_per_dev + 1); + int rc; - cal_fmw = priv->tasdevice[i].cali_data_fmw; + /* Load the calibrated data from cal bin file */ + if (!priv->is_user_space_calidata && cal_fmw) { + cal = cal_fmw->calibrations; - /* No calibrated data for current devices, playback will go ahead. */ - if (!cal_fmw) + if (cal) + load_calib_data(priv, &cal->dev_data); return; - - cal = cal_fmw->calibrations; - if (cal) + } + if (!priv->is_user_space_calidata) return; + /* load calibrated data from user space */ + if (data[k] != i) { + dev_err(priv->dev, "%s: no cal-data for dev %d from usr-spc\n", + __func__, i); + return; + } + k++; - load_calib_data(priv, &cal->dev_data); + rc = tasdevice_dev_bulk_write(priv, i, p->r0_reg, &(data[k]), 4); + if (rc < 0) { + dev_err(priv->dev, "chn %d r0_reg bulk_wr err = %d\n", i, rc); + return; + } + k += 4; + rc = tasdevice_dev_bulk_write(priv, i, p->r0_low_reg, &(data[k]), 4); + if (rc < 0) { + dev_err(priv->dev, "chn %d r0_low_reg err = %d\n", i, rc); + return; + } + k += 4; + rc = tasdevice_dev_bulk_write(priv, i, p->invr0_reg, &(data[k]), 4); + if (rc < 0) { + dev_err(priv->dev, "chn %d invr0_reg err = %d\n", i, rc); + return; + } + k += 4; + rc = tasdevice_dev_bulk_write(priv, i, p->pow_reg, &(data[k]), 4); + if (rc < 0) { + dev_err(priv->dev, "chn %d pow_reg bulk_wr err = %d\n", i, rc); + return; + } + k += 4; + rc = tasdevice_dev_bulk_write(priv, i, p->tlimit_reg, &(data[k]), 4); + if (rc < 0) { + dev_err(priv->dev, "chn %d tlimit_reg err = %d\n", i, rc); + return; + } } int tasdevice_select_tuningprm_cfg(void *context, int prm_no, @@ -2261,9 +2300,10 @@ int tasdevice_select_tuningprm_cfg(void *context, int prm_no, tas_priv->tasdevice[i].cur_conf = cfg_no; } } - } else + } else { dev_dbg(tas_priv->dev, "%s: Unneeded loading dsp conf %d\n", __func__, cfg_no); + } status |= cfg_info[rca_conf_no]->active_dev; @@ -2324,14 +2364,21 @@ void tasdevice_tuning_switch(void *context, int state) struct tasdevice_fw *tas_fmw = tas_priv->fmw; int profile_cfg_id = tas_priv->rcabin.profile_cfg_id; - if (tas_priv->fw_state == TASDEVICE_DSP_FW_FAIL) { - dev_err(tas_priv->dev, "DSP bin file not loaded\n"); + /* + * Only RCA-based Playback can still work with no dsp program running + * inside the chip. + */ + switch (tas_priv->fw_state) { + case TASDEVICE_RCA_FW_OK: + case TASDEVICE_DSP_FW_ALL_OK: + break; + default: return; } if (state == 0) { - if (tas_priv->cur_prog < tas_fmw->nr_programs) { - /*dsp mode or tuning mode*/ + if (tas_fmw && tas_priv->cur_prog < tas_fmw->nr_programs) { + /* dsp mode or tuning mode */ profile_cfg_id = tas_priv->rcabin.profile_cfg_id; tasdevice_select_tuningprm_cfg(tas_priv, tas_priv->cur_prog, tas_priv->cur_conf, @@ -2340,9 +2387,10 @@ void tasdevice_tuning_switch(void *context, int state) tasdevice_select_cfg_blk(tas_priv, profile_cfg_id, TASDEVICE_BIN_BLK_PRE_POWER_UP); - } else + } else { tasdevice_select_cfg_blk(tas_priv, profile_cfg_id, TASDEVICE_BIN_BLK_PRE_SHUTDOWN); + } } EXPORT_SYMBOL_NS_GPL(tasdevice_tuning_switch, SND_SOC_TAS2781_FMWLIB); |