Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+65 −1
Original line number Diff line number Diff line
@@ -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;
+1 −0
Original line number Diff line number Diff line
@@ -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];