summaryrefslogtreecommitdiff
path: root/drivers/firmware/cirrus/cs_dsp.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/firmware/cirrus/cs_dsp.c')
-rw-r--r--drivers/firmware/cirrus/cs_dsp.c71
1 files changed, 26 insertions, 45 deletions
diff --git a/drivers/firmware/cirrus/cs_dsp.c b/drivers/firmware/cirrus/cs_dsp.c
index 42c9cd0ebfb7..419220fa42fd 100644
--- a/drivers/firmware/cirrus/cs_dsp.c
+++ b/drivers/firmware/cirrus/cs_dsp.c
@@ -12,6 +12,7 @@
#include <linux/ctype.h>
#include <linux/debugfs.h>
#include <linux/delay.h>
+#include <linux/minmax.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/seq_file.h>
@@ -802,6 +803,9 @@ int cs_dsp_coeff_write_ctrl(struct cs_dsp_coeff_ctl *ctl,
lockdep_assert_held(&ctl->dsp->pwr_lock);
+ if (ctl->flags && !(ctl->flags & WMFW_CTL_FLAG_WRITEABLE))
+ return -EPERM;
+
if (len + off * sizeof(u32) > ctl->len)
return -EINVAL;
@@ -1053,7 +1057,7 @@ static int cs_dsp_create_control(struct cs_dsp *dsp,
ctl->fw_name = dsp->fw_name;
ctl->alg_region = *alg_region;
- if (subname && dsp->fw_ver >= 2) {
+ if (subname && dsp->wmfw_ver >= 2) {
ctl->subname_len = subname_len;
ctl->subname = kasprintf(GFP_KERNEL, "%.*s", subname_len, subname);
if (!ctl->subname) {
@@ -1180,7 +1184,7 @@ static int cs_dsp_coeff_parse_alg(struct cs_dsp *dsp,
raw = (const struct wmfw_adsp_alg_data *)region->data;
- switch (dsp->fw_ver) {
+ switch (dsp->wmfw_ver) {
case 0:
case 1:
if (sizeof(*raw) > data_len)
@@ -1257,7 +1261,7 @@ static int cs_dsp_coeff_parse_coeff(struct cs_dsp *dsp,
blk->offset = le16_to_cpu(raw->hdr.offset);
blk->mem_type = le16_to_cpu(raw->hdr.type);
- switch (dsp->fw_ver) {
+ switch (dsp->wmfw_ver) {
case 0:
case 1:
if (sizeof(*raw) > (data_len - pos))
@@ -1476,7 +1480,6 @@ static int cs_dsp_load(struct cs_dsp *dsp, const struct firmware *firmware,
const struct wmfw_region *region;
const struct cs_dsp_region *mem;
const char *region_name;
- char *text = NULL;
struct cs_dsp_buf *buf;
unsigned int reg;
int regions = 0;
@@ -1505,8 +1508,7 @@ static int cs_dsp_load(struct cs_dsp *dsp, const struct firmware *firmware,
goto out_fw;
}
- cs_dsp_info(dsp, "Firmware version: %d\n", header->ver);
- dsp->fw_ver = header->ver;
+ dsp->wmfw_ver = header->ver;
if (header->core != dsp->type) {
cs_dsp_err(dsp, "%s: invalid core %d != %d\n",
@@ -1529,8 +1531,8 @@ static int cs_dsp_load(struct cs_dsp *dsp, const struct firmware *firmware,
goto out_fw;
}
- cs_dsp_dbg(dsp, "%s: timestamp %llu\n", file,
- le64_to_cpu(footer->timestamp));
+ cs_dsp_info(dsp, "%s: format %d timestamp %#llx\n", file, header->ver,
+ le64_to_cpu(footer->timestamp));
while (pos < firmware->size) {
/* Is there enough data for a complete block header? */
@@ -1548,15 +1550,15 @@ static int cs_dsp_load(struct cs_dsp *dsp, const struct firmware *firmware,
region_name = "Unknown";
reg = 0;
- text = NULL;
offset = le32_to_cpu(region->offset) & 0xffffff;
type = be32_to_cpu(region->type) & 0xff;
switch (type) {
+ case WMFW_INFO_TEXT:
case WMFW_NAME_TEXT:
- region_name = "Firmware name";
- text = kzalloc(le32_to_cpu(region->len) + 1,
- GFP_KERNEL);
+ region_name = "Info/Name";
+ cs_dsp_info(dsp, "%s: %.*s\n", file,
+ min(le32_to_cpu(region->len), 100), region->data);
break;
case WMFW_ALGORITHM_DATA:
region_name = "Algorithm";
@@ -1564,11 +1566,6 @@ static int cs_dsp_load(struct cs_dsp *dsp, const struct firmware *firmware,
if (ret != 0)
goto out_fw;
break;
- case WMFW_INFO_TEXT:
- region_name = "Information";
- text = kzalloc(le32_to_cpu(region->len) + 1,
- GFP_KERNEL);
- break;
case WMFW_ABSOLUTE:
region_name = "Absolute";
reg = offset;
@@ -1602,13 +1599,6 @@ static int cs_dsp_load(struct cs_dsp *dsp, const struct firmware *firmware,
regions, le32_to_cpu(region->len), offset,
region_name);
- if (text) {
- memcpy(text, region->data, le32_to_cpu(region->len));
- cs_dsp_info(dsp, "%s: %s\n", file, text);
- kfree(text);
- text = NULL;
- }
-
if (reg) {
buf = cs_dsp_buf_alloc(region->data,
le32_to_cpu(region->len),
@@ -1650,7 +1640,6 @@ static int cs_dsp_load(struct cs_dsp *dsp, const struct firmware *firmware,
out_fw:
regmap_async_complete(regmap);
cs_dsp_buf_free(&buf_list);
- kfree(text);
if (ret == -EOVERFLOW)
cs_dsp_err(dsp, "%s: file content overflows file data\n", file);
@@ -1799,7 +1788,7 @@ static struct cs_dsp_alg_region *cs_dsp_create_region(struct cs_dsp *dsp,
list_add_tail(&alg_region->list, &dsp->alg_regions);
- if (dsp->fw_ver > 0)
+ if (dsp->wmfw_ver > 0)
cs_dsp_ctl_fixup_base(dsp, alg_region);
return alg_region;
@@ -1922,7 +1911,7 @@ static int cs_dsp_adsp1_setup_algs(struct cs_dsp *dsp)
ret = PTR_ERR(alg_region);
goto out;
}
- if (dsp->fw_ver == 0) {
+ if (dsp->wmfw_ver == 0) {
if (i + 1 < n_algs) {
len = be32_to_cpu(adsp1_alg[i + 1].dm);
len -= be32_to_cpu(adsp1_alg[i].dm);
@@ -1944,7 +1933,7 @@ static int cs_dsp_adsp1_setup_algs(struct cs_dsp *dsp)
ret = PTR_ERR(alg_region);
goto out;
}
- if (dsp->fw_ver == 0) {
+ if (dsp->wmfw_ver == 0) {
if (i + 1 < n_algs) {
len = be32_to_cpu(adsp1_alg[i + 1].zm);
len -= be32_to_cpu(adsp1_alg[i].zm);
@@ -2035,7 +2024,7 @@ static int cs_dsp_adsp2_setup_algs(struct cs_dsp *dsp)
ret = PTR_ERR(alg_region);
goto out;
}
- if (dsp->fw_ver == 0) {
+ if (dsp->wmfw_ver == 0) {
if (i + 1 < n_algs) {
len = be32_to_cpu(adsp2_alg[i + 1].xm);
len -= be32_to_cpu(adsp2_alg[i].xm);
@@ -2057,7 +2046,7 @@ static int cs_dsp_adsp2_setup_algs(struct cs_dsp *dsp)
ret = PTR_ERR(alg_region);
goto out;
}
- if (dsp->fw_ver == 0) {
+ if (dsp->wmfw_ver == 0) {
if (i + 1 < n_algs) {
len = be32_to_cpu(adsp2_alg[i + 1].ym);
len -= be32_to_cpu(adsp2_alg[i].ym);
@@ -2079,7 +2068,7 @@ static int cs_dsp_adsp2_setup_algs(struct cs_dsp *dsp)
ret = PTR_ERR(alg_region);
goto out;
}
- if (dsp->fw_ver == 0) {
+ if (dsp->wmfw_ver == 0) {
if (i + 1 < n_algs) {
len = be32_to_cpu(adsp2_alg[i + 1].zm);
len -= be32_to_cpu(adsp2_alg[i].zm);
@@ -2183,7 +2172,6 @@ static int cs_dsp_load_coeff(struct cs_dsp *dsp, const struct firmware *firmware
struct cs_dsp_alg_region *alg_region;
const char *region_name;
int ret, pos, blocks, type, offset, reg, version;
- char *text = NULL;
struct cs_dsp_buf *buf;
if (!firmware)
@@ -2252,7 +2240,8 @@ static int cs_dsp_load_coeff(struct cs_dsp *dsp, const struct firmware *firmware
region_name = "Unknown";
switch (type) {
case (WMFW_NAME_TEXT << 8):
- text = kzalloc(le32_to_cpu(blk->len) + 1, GFP_KERNEL);
+ cs_dsp_info(dsp, "%s: %.*s\n", dsp->fw_name,
+ min(le32_to_cpu(blk->len), 100), blk->data);
break;
case (WMFW_INFO_TEXT << 8):
case (WMFW_METADATA << 8):
@@ -2324,13 +2313,6 @@ static int cs_dsp_load_coeff(struct cs_dsp *dsp, const struct firmware *firmware
break;
}
- if (text) {
- memcpy(text, blk->data, le32_to_cpu(blk->len));
- cs_dsp_info(dsp, "%s: %s\n", dsp->fw_name, text);
- kfree(text);
- text = NULL;
- }
-
if (reg) {
buf = cs_dsp_buf_alloc(blk->data,
le32_to_cpu(blk->len),
@@ -2370,7 +2352,6 @@ static int cs_dsp_load_coeff(struct cs_dsp *dsp, const struct firmware *firmware
out_fw:
regmap_async_complete(regmap);
cs_dsp_buf_free(&buf_list);
- kfree(text);
if (ret == -EOVERFLOW)
cs_dsp_err(dsp, "%s: file content overflows file data\n", file);
@@ -2437,8 +2418,8 @@ EXPORT_SYMBOL_NS_GPL(cs_dsp_adsp1_init, FW_CS_DSP);
* Return: Zero for success, a negative number on error.
*/
int cs_dsp_adsp1_power_up(struct cs_dsp *dsp,
- const struct firmware *wmfw_firmware, char *wmfw_filename,
- const struct firmware *coeff_firmware, char *coeff_filename,
+ const struct firmware *wmfw_firmware, const char *wmfw_filename,
+ const struct firmware *coeff_firmware, const char *coeff_filename,
const char *fw_name)
{
unsigned int val;
@@ -2731,8 +2712,8 @@ static void cs_dsp_halo_stop_watchdog(struct cs_dsp *dsp)
* Return: Zero for success, a negative number on error.
*/
int cs_dsp_power_up(struct cs_dsp *dsp,
- const struct firmware *wmfw_firmware, char *wmfw_filename,
- const struct firmware *coeff_firmware, char *coeff_filename,
+ const struct firmware *wmfw_firmware, const char *wmfw_filename,
+ const struct firmware *coeff_firmware, const char *coeff_filename,
const char *fw_name)
{
int ret;