Commit d52ed4b0 authored by Richard Fitzgerald's avatar Richard Fitzgerald Committed by Mark Brown

ASoC: wm_adsp: Parse HOST_BUFFER controls

Currently the compressed streams in DSP firmwares are
identified essentially by looking at a fixed location inside
the firmware. This is fragile and also limits things to a
single compressed stream.

Here a new form of firmware parameter is added, the HOST_BUFFER
which identifies a compressed stream from meta-data in the
firmware file. This is more robust and allows for the possiblity
of using multiple streams per core in the future. Currently the
implementation is still limited to a single stream and will
use the first HOST_BUFFER parameter encountered. If there aren't
any HOST_BUFFER parameters it will fall back to the legacy way
of finding the host buffer.
Signed-off-by: default avatarRichard Fitzgerald <rf@opensource.cirrus.com>
Signed-off-by: default avatarCharles Keepax <ckeepax@opensource.cirrus.com>
Signed-off-by: default avatarMark Brown <broonie@kernel.org>
parent 3bbc2705
......@@ -1607,6 +1607,15 @@ static int wm_adsp_parse_coeff(struct wm_adsp *dsp,
if (ret)
return -EINVAL;
break;
case WMFW_CTL_TYPE_HOST_BUFFER:
ret = wm_adsp_check_coeff_flags(dsp, &coeff_blk,
WMFW_CTL_FLAG_SYS |
WMFW_CTL_FLAG_VOLATILE |
WMFW_CTL_FLAG_READABLE,
0);
if (ret)
return -EINVAL;
break;
default:
adsp_err(dsp, "Unknown control type: %d\n",
coeff_blk.ctl_type);
......@@ -3200,7 +3209,7 @@ static inline int wm_adsp_buffer_write(struct wm_adsp_compr_buf *buf,
buf->host_buf_ptr + field_offset, data);
}
static int wm_adsp_buffer_locate(struct wm_adsp_compr_buf *buf)
static int wm_adsp_legacy_host_buf_addr(struct wm_adsp_compr_buf *buf)
{
struct wm_adsp_alg_region *alg_region;
struct wm_adsp *dsp = buf->dsp;
......@@ -3239,6 +3248,61 @@ static int wm_adsp_buffer_locate(struct wm_adsp_compr_buf *buf)
return 0;
}
static struct wm_coeff_ctl *
wm_adsp_find_host_buffer_ctrl(struct wm_adsp_compr_buf *buf)
{
struct wm_adsp *dsp = buf->dsp;
struct wm_coeff_ctl *ctl;
list_for_each_entry(ctl, &dsp->ctl_list, list) {
if (ctl->type != WMFW_CTL_TYPE_HOST_BUFFER)
continue;
if (!ctl->enabled)
continue;
return ctl;
}
return NULL;
}
static int wm_adsp_buffer_locate(struct wm_adsp_compr_buf *buf)
{
struct wm_adsp *dsp = buf->dsp;
struct wm_coeff_ctl *ctl;
unsigned int reg;
u32 val;
int i, ret;
ctl = wm_adsp_find_host_buffer_ctrl(buf);
if (!ctl)
return wm_adsp_legacy_host_buf_addr(buf);
ret = wm_coeff_base_reg(ctl, &reg);
if (ret)
return ret;
for (i = 0; i < 5; ++i) {
ret = regmap_raw_read(dsp->regmap, reg, &val, sizeof(val));
if (ret < 0)
return ret;
if (val)
break;
usleep_range(1000, 2000);
}
if (!val)
return -EIO;
buf->host_buf_ptr = be32_to_cpu(val);
adsp_dbg(dsp, "host_buf_ptr=%x\n", buf->host_buf_ptr);
return 0;
}
static int wm_adsp_buffer_populate(struct wm_adsp_compr_buf *buf)
{
const struct wm_adsp_fw_caps *caps = wm_adsp_fw[buf->dsp->fw].caps;
......
......@@ -29,6 +29,7 @@
/* Non-ALSA coefficient types start at 0x1000 */
#define WMFW_CTL_TYPE_ACKED 0x1000 /* acked control */
#define WMFW_CTL_TYPE_HOSTEVENT 0x1001 /* event control */
#define WMFW_CTL_TYPE_HOST_BUFFER 0x1002 /* host buffer pointer */
struct wmfw_header {
char magic[4];
......
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