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)
|
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, ®);
|
||||||
|
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;
|
||||||
|
|
|
@ -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];
|
||||||
|
|
Loading…
Reference in New Issue