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:
parent
3bbc2705a3
commit
d52ed4b0bc
|
@ -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, ®);
|
||||
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];
|
||||
|
|
Loading…
Reference in New Issue