Commit db40517c authored by Mark Brown's avatar Mark Brown

ASoC: wm_adsp: Add support for parsing algorithms

ADSP devices report information on the algorithms loaded on them.  Parse
this data and use it to allow coefficients to be configured for specific
algorithms.
Signed-off-by: default avatarMark Brown <broonie@opensource.wolfsonmicro.com>
parent d1c3ed66
...@@ -350,6 +350,141 @@ static int wm_adsp_load(struct wm_adsp *dsp) ...@@ -350,6 +350,141 @@ static int wm_adsp_load(struct wm_adsp *dsp)
return ret; return ret;
} }
static int wm_adsp_setup_algs(struct wm_adsp *dsp)
{
struct regmap *regmap = dsp->regmap;
struct wmfw_adsp1_id_hdr adsp1_id;
struct wmfw_adsp2_id_hdr adsp2_id;
struct wmfw_adsp1_alg_hdr *adsp1_alg;
struct wmfw_adsp2_alg_hdr *adsp2_alg;
void *alg;
const struct wm_adsp_region *mem;
unsigned int pos, term;
size_t algs;
__be32 val;
int i, ret;
switch (dsp->type) {
case WMFW_ADSP1:
mem = wm_adsp_find_region(dsp, WMFW_ADSP1_DM);
break;
case WMFW_ADSP2:
mem = wm_adsp_find_region(dsp, WMFW_ADSP2_XM);
break;
default:
mem = NULL;
break;
}
if (mem == NULL) {
BUG_ON(mem != NULL);
return -EINVAL;
}
switch (dsp->type) {
case WMFW_ADSP1:
ret = regmap_raw_read(regmap, mem->base, &adsp1_id,
sizeof(adsp1_id));
if (ret != 0) {
adsp_err(dsp, "Failed to read algorithm info: %d\n",
ret);
return ret;
}
algs = be32_to_cpu(adsp1_id.algs);
adsp_info(dsp, "Firmware: %x v%d.%d.%d, %zu algorithms\n",
be32_to_cpu(adsp1_id.fw.id),
(be32_to_cpu(adsp1_id.fw.ver) & 0xff0000) >> 16,
(be32_to_cpu(adsp1_id.fw.ver) & 0xff00) >> 8,
be32_to_cpu(adsp1_id.fw.ver) & 0xff,
algs);
pos = sizeof(adsp1_id) / 2;
term = pos + ((sizeof(*adsp1_alg) * algs) / 2);
break;
case WMFW_ADSP2:
ret = regmap_raw_read(regmap, mem->base, &adsp2_id,
sizeof(adsp2_id));
if (ret != 0) {
adsp_err(dsp, "Failed to read algorithm info: %d\n",
ret);
return ret;
}
algs = be32_to_cpu(adsp2_id.algs);
adsp_info(dsp, "Firmware: %x v%d.%d.%d, %zu algorithms\n",
be32_to_cpu(adsp2_id.fw.id),
(be32_to_cpu(adsp2_id.fw.ver) & 0xff0000) >> 16,
(be32_to_cpu(adsp2_id.fw.ver) & 0xff00) >> 8,
be32_to_cpu(adsp2_id.fw.ver) & 0xff,
algs);
pos = sizeof(adsp2_id) / 2;
term = pos + ((sizeof(*adsp2_alg) * algs) / 2);
break;
default:
BUG_ON(NULL == "Unknown DSP type");
return -EINVAL;
}
if (algs == 0) {
adsp_err(dsp, "No algorithms\n");
return -EINVAL;
}
/* Read the terminator first to validate the length */
ret = regmap_raw_read(regmap, mem->base + term, &val, sizeof(val));
if (ret != 0) {
adsp_err(dsp, "Failed to read algorithm list end: %d\n",
ret);
return ret;
}
if (be32_to_cpu(val) != 0xbedead)
adsp_warn(dsp, "Algorithm list end %x 0x%x != 0xbeadead\n",
term, be32_to_cpu(val));
alg = kzalloc((term - pos) * 2, GFP_KERNEL);
if (!alg)
return -ENOMEM;
ret = regmap_raw_read(regmap, mem->base + pos, alg, (term - pos) * 2);
if (ret != 0) {
adsp_err(dsp, "Failed to read algorithm list: %d\n",
ret);
goto out;
}
adsp1_alg = alg;
adsp2_alg = alg;
for (i = 0; i < algs; i++) {
switch (dsp->type) {
case WMFW_ADSP1:
adsp_info(dsp, "%d: ID %x v%d.%d.%d\n",
i, be32_to_cpu(adsp1_alg[i].alg.id),
(be32_to_cpu(adsp1_alg[i].alg.ver) & 0xff0000) >> 16,
(be32_to_cpu(adsp1_alg[i].alg.ver) & 0xff00) >> 8,
be32_to_cpu(adsp1_alg[i].alg.ver) & 0xff);
break;
case WMFW_ADSP2:
adsp_info(dsp, "%d: ID %x v%d.%d.%d\n",
i, be32_to_cpu(adsp2_alg[i].alg.id),
(be32_to_cpu(adsp2_alg[i].alg.ver) & 0xff0000) >> 16,
(be32_to_cpu(adsp2_alg[i].alg.ver) & 0xff00) >> 8,
be32_to_cpu(adsp2_alg[i].alg.ver) & 0xff);
break;
}
}
out:
kfree(alg);
return ret;
}
static int wm_adsp_load_coeff(struct wm_adsp *dsp) static int wm_adsp_load_coeff(struct wm_adsp *dsp)
{ {
struct regmap *regmap = dsp->regmap; struct regmap *regmap = dsp->regmap;
...@@ -468,6 +603,10 @@ int wm_adsp1_event(struct snd_soc_dapm_widget *w, ...@@ -468,6 +603,10 @@ int wm_adsp1_event(struct snd_soc_dapm_widget *w,
if (ret != 0) if (ret != 0)
goto err; goto err;
ret = wm_adsp_setup_algs(dsp);
if (ret != 0)
goto err;
ret = wm_adsp_load_coeff(dsp); ret = wm_adsp_load_coeff(dsp);
if (ret != 0) if (ret != 0)
goto err; goto err;
...@@ -604,6 +743,10 @@ int wm_adsp2_event(struct snd_soc_dapm_widget *w, ...@@ -604,6 +743,10 @@ int wm_adsp2_event(struct snd_soc_dapm_widget *w,
if (ret != 0) if (ret != 0)
goto err; goto err;
ret = wm_adsp_setup_algs(dsp);
if (ret != 0)
goto err;
ret = wm_adsp_load_coeff(dsp); ret = wm_adsp_load_coeff(dsp);
if (ret != 0) if (ret != 0)
goto err; goto err;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment