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: Richard Fitzgerald <rf@opensource.cirrus.com>
Signed-off-by: Charles Keepax <ckeepax@opensource.cirrus.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
Richard Fitzgerald 2018-07-19 11:50:39 +01:00 committed by Mark Brown
parent 3bbc2705a3
commit d52ed4b0bc
No known key found for this signature in database
GPG Key ID: 24D68B725D5487D0
2 changed files with 66 additions and 1 deletions

View File

@ -1607,6 +1607,15 @@ static int wm_adsp_parse_coeff(struct wm_adsp *dsp,
if (ret) if (ret)
return -EINVAL; return -EINVAL;
break; 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: default:
adsp_err(dsp, "Unknown control type: %d\n", adsp_err(dsp, "Unknown control type: %d\n",
coeff_blk.ctl_type); 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); 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_alg_region *alg_region;
struct wm_adsp *dsp = buf->dsp; struct wm_adsp *dsp = buf->dsp;
@ -3239,6 +3248,61 @@ static int wm_adsp_buffer_locate(struct wm_adsp_compr_buf *buf)
return 0; 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) 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; const struct wm_adsp_fw_caps *caps = wm_adsp_fw[buf->dsp->fw].caps;

View File

@ -29,6 +29,7 @@
/* Non-ALSA coefficient types start at 0x1000 */ /* Non-ALSA coefficient types start at 0x1000 */
#define WMFW_CTL_TYPE_ACKED 0x1000 /* acked control */ #define WMFW_CTL_TYPE_ACKED 0x1000 /* acked control */
#define WMFW_CTL_TYPE_HOSTEVENT 0x1001 /* event control */ #define WMFW_CTL_TYPE_HOSTEVENT 0x1001 /* event control */
#define WMFW_CTL_TYPE_HOST_BUFFER 0x1002 /* host buffer pointer */
struct wmfw_header { struct wmfw_header {
char magic[4]; char magic[4];