[Sound-open-firmware] [PATCH] component: data: Make component get/set data host API generic

Liam Girdwood liam.r.girdwood at linux.intel.com
Sun Sep 3 00:15:49 CEST 2017


Make the host API and IPC to set and get component runtime data and values
generic with no bespoke commands at the IPC level.

Create a generic structure that descibes the type and size of data and
whether that data is appended to the IPC message or is available to
be DMAed from host.

Update the components to use the new structure. Some components like
SRC, tone and tone still require some work to export thier ABI.

Signed-off-by: Liam Girdwood <liam.r.girdwood at linux.intel.com>
---
 src/audio/eq_fir.c                 | 58 ++++++++++++++--------
 src/audio/eq_iir.c                 | 53 +++++++++++++--------
 src/audio/src.c                    | 31 ++++++++----
 src/audio/tone.c                   | 49 +++++++++++++------
 src/audio/volume.c                 | 71 +++++++++++++++------------
 src/include/reef/audio/component.h | 25 +++++-----
 src/include/uapi/ipc.h             | 98 +++++++++++++++++++++++---------------
 src/ipc/intel-ipc.c                | 53 ++++++---------------
 8 files changed, 254 insertions(+), 184 deletions(-)

diff --git a/src/audio/eq_fir.c b/src/audio/eq_fir.c
index 534a4a1..540c68f 100644
--- a/src/audio/eq_fir.c
+++ b/src/audio/eq_fir.c
@@ -299,26 +299,25 @@ static int eq_fir_params(struct comp_dev *dev)
 	return 0;
 }
 
-/* used to pass standard and bespoke commands (with data) to component */
-static int eq_fir_cmd(struct comp_dev *dev, int cmd, void *data)
+static int fir_cmd(struct comp_dev *dev, struct sof_ipc_ctrl_data *cdata)
 {
 	struct comp_data *cd = comp_get_drvdata(dev);
-	struct sof_ipc_eq_fir_blob *blob;
-	struct sof_ipc_eq_fir_switch *assign;
-	struct eq_fir_update *fir_update;
-	int i;
-	int ret = 0;
+	struct eq_fir_update *fir_update; /* TODO: move this to IPC as it's ABI */
 	size_t bs;
+	int i, ret = 0;
 
-	trace_src("cmd");
+	/* TODO: determine if data is DMAed or appended to cdata */
 
-	switch (cmd) {
-	case COMP_CMD_EQ_FIR_SWITCH:
+	switch (cdata->cmd) {
+	case SOF_CTRL_CMD_EQ_SWITCH:
 		trace_src("EFx");
-		assign = (struct sof_ipc_eq_fir_switch *) data;
-		fir_update = (struct eq_fir_update *) assign->data;
+		fir_update = (struct eq_fir_update *)cdata->data;
 		ret = eq_fir_switch_response(cd->fir, cd->config,
 			fir_update, PLATFORM_MAX_CHANNELS);
+		if (ret < 0) {
+			trace_src_error("ec1");
+			return ret;
+		}
 
 		/* Print trace information */
 		tracev_value(fir_update->stream_max_channels);
@@ -326,14 +325,13 @@ static int eq_fir_cmd(struct comp_dev *dev, int cmd, void *data)
 			tracev_value(fir_update->assign_response[i]);
 
 		break;
-	case COMP_CMD_EQ_FIR_CONFIG:
+	case SOF_CTRL_CMD_EQ_CONFIG:
 		trace_src("EFc");
 		/* Check and free old config */
 		eq_fir_free_parameters(&cd->config);
 
 		/* Copy new config, need to decode data to know the size */
-		blob = (struct sof_ipc_eq_fir_blob *) data;
-		bs = blob->comp.hdr.size - sizeof(struct sof_ipc_hdr);
+		bs = cdata->num_elems;
 		if (bs > EQ_FIR_MAX_BLOB_SIZE)
 			return -EINVAL;
 
@@ -341,7 +339,7 @@ static int eq_fir_cmd(struct comp_dev *dev, int cmd, void *data)
 		if (cd->config == NULL)
 			return -EINVAL;
 
-		memcpy(cd->config, blob->data, bs);
+		memcpy(cd->config, cdata->data, bs);
 		ret = eq_fir_setup(cd->fir, cd->config, PLATFORM_MAX_CHANNELS);
 
 		/* Print trace information */
@@ -349,20 +347,40 @@ static int eq_fir_cmd(struct comp_dev *dev, int cmd, void *data)
 		tracev_value(cd->config->number_of_responses_defined);
 		for (i = 0; i < cd->config->stream_max_channels; i++)
 			tracev_value(cd->config->assign_response[i]);
-
 		break;
-	case COMP_CMD_MUTE:
+	case SOF_CTRL_CMD_MUTE:
 		trace_src("EFm");
 		for (i = 0; i < PLATFORM_MAX_CHANNELS; i++)
 			fir_mute(&cd->fir[i]);
 
 		break;
-	case COMP_CMD_UNMUTE:
+	case SOF_CTRL_CMD_UNMUTE:
 		trace_src("EFu");
 		for (i = 0; i < PLATFORM_MAX_CHANNELS; i++)
 			fir_unmute(&cd->fir[i]);
 
 		break;
+	default:
+		trace_src_error("ec1");
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
+/* used to pass standard and bespoke commands (with data) to component */
+static int eq_fir_cmd(struct comp_dev *dev, int cmd, void *data)
+{
+	struct sof_ipc_ctrl_data *cdata = data;
+	int ret = 0;
+
+	trace_src("cmd");
+
+	switch (cmd) {
+	case COMP_CMD_SET_DATA:
+		ret = fir_cmd(dev, cdata);
+		break;
 	case COMP_CMD_START:
 		trace_src("EFs");
 		dev->state = COMP_STATE_RUNNING;
@@ -389,6 +407,8 @@ static int eq_fir_cmd(struct comp_dev *dev, int cmd, void *data)
 		break;
 	default:
 		trace_src("EDf");
+		ret = -EINVAL;
+		break;
 	}
 
 	return ret;
diff --git a/src/audio/eq_iir.c b/src/audio/eq_iir.c
index 0ac2ef9..f75be71 100644
--- a/src/audio/eq_iir.c
+++ b/src/audio/eq_iir.c
@@ -303,24 +303,17 @@ static int eq_iir_params(struct comp_dev *dev)
 	return 0;
 }
 
-/* used to pass standard and bespoke commands (with data) to component */
-static int eq_iir_cmd(struct comp_dev *dev, int cmd, void *data)
+static int iir_cmd(struct comp_dev *dev, struct sof_ipc_ctrl_data *cdata)
 {
 	struct comp_data *cd = comp_get_drvdata(dev);
-	struct sof_ipc_eq_iir_switch *assign;
-	struct sof_ipc_eq_iir_blob *blob;
-	struct eq_iir_update *iir_update;
-	int i;
-	int ret = 0;
+	struct eq_iir_update *iir_update; /* TODO: move to IPC header as part of ABI */
+	int i, ret = 0;
 	size_t bs;
 
-	trace_eq_iir("cmd");
-
-	switch (cmd) {
-	case COMP_CMD_EQ_IIR_SWITCH:
+	switch (cdata->cmd) {
+	case SOF_CTRL_CMD_EQ_SWITCH:
 		trace_eq_iir("EFx");
-		assign = (struct sof_ipc_eq_iir_switch *) data;
-		iir_update = (struct eq_iir_update *) assign->data;
+		iir_update = (struct eq_iir_update *) cdata->data;
 		ret = eq_iir_switch_response(cd->iir, cd->config,
 			iir_update, PLATFORM_MAX_CHANNELS);
 
@@ -330,15 +323,13 @@ static int eq_iir_cmd(struct comp_dev *dev, int cmd, void *data)
 			tracev_value(iir_update->assign_response[i]);
 
 		break;
-	case COMP_CMD_EQ_IIR_CONFIG:
+	case SOF_CTRL_CMD_EQ_CONFIG:
 		trace_eq_iir("EFc");
 		/* Check and free old config */
 		eq_iir_free_parameters(&cd->config);
 
 		/* Copy new config, need to decode data to know the size */
-		blob = (struct sof_ipc_eq_iir_blob *) data;
-		bs = blob->comp.hdr.size - sizeof(struct sof_ipc_hdr)
-			- sizeof(struct sof_ipc_host_buffer);
+		bs = cdata->num_elems;
 		if (bs > EQ_IIR_MAX_BLOB_SIZE)
 			return -EINVAL;
 
@@ -347,7 +338,7 @@ static int eq_iir_cmd(struct comp_dev *dev, int cmd, void *data)
 		if (cd->config == NULL)
 			return -EINVAL;
 
-		memcpy(cd->config, blob->data, bs);
+		memcpy(cd->config, cdata->data, bs);
 		/* Initialize all channels, the actual number of channels may
 		 * not be set yet.
 		 */
@@ -360,18 +351,39 @@ static int eq_iir_cmd(struct comp_dev *dev, int cmd, void *data)
 			tracev_value(cd->config->assign_response[i]);
 
 		break;
-	case COMP_CMD_MUTE:
+	case SOF_CTRL_CMD_MUTE:
 		trace_eq_iir("EFm");
 		for (i = 0; i < PLATFORM_MAX_CHANNELS; i++)
 			iir_mute_df2t(&cd->iir[i]);
 
 		break;
-	case COMP_CMD_UNMUTE:
+	case SOF_CTRL_CMD_UNMUTE:
 		trace_eq_iir("EFu");
 		for (i = 0; i < PLATFORM_MAX_CHANNELS; i++)
 			iir_unmute_df2t(&cd->iir[i]);
 
 		break;
+	default:
+		trace_eq_iir_error("ec1");
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
+/* used to pass standard and bespoke commands (with data) to component */
+static int eq_iir_cmd(struct comp_dev *dev, int cmd, void *data)
+{
+	struct sof_ipc_ctrl_data *cdata = data;
+	int ret = 0;
+
+	trace_eq_iir("cmd");
+
+	switch (cmd) {
+	case COMP_CMD_SET_DATA:
+		ret = iir_cmd(dev, cdata);
+		break;
 	case COMP_CMD_START:
 		trace_eq_iir("EFs");
 		dev->state = COMP_STATE_RUNNING;
@@ -398,6 +410,7 @@ static int eq_iir_cmd(struct comp_dev *dev, int cmd, void *data)
 		break;
 	default:
 		trace_eq_iir("EDf");
+		ret = -EINVAL;
 		break;
 	}
 
diff --git a/src/audio/src.c b/src/audio/src.c
index 0279841..5dd8345 100644
--- a/src/audio/src.c
+++ b/src/audio/src.c
@@ -376,29 +376,42 @@ static int src_params(struct comp_dev *dev)
 	return 0;
 }
 
-/* used to pass standard and bespoke commands (with data) to component */
-static int src_cmd(struct comp_dev *dev, int cmd, void *data)
+static int src_ctrl_cmd(struct comp_dev *dev, struct sof_ipc_ctrl_data *cdata)
 {
-	trace_src("SCm");
 	struct comp_data *cd = comp_get_drvdata(dev);
 	int i;
 
-	switch (cmd) {
-	case COMP_CMD_SRC:
-		trace_src("SMa");
-		break;
-	case COMP_CMD_MUTE:
+	switch (cdata->cmd) {
+	case SOF_CTRL_CMD_MUTE:
 		trace_src("SMu");
 		for (i = 0; i < PLATFORM_MAX_CHANNELS; i++)
 			src_polyphase_mute(&cd->src[i]);
 
 		break;
-	case COMP_CMD_UNMUTE:
+	case SOF_CTRL_CMD_UNMUTE:
 		trace_src("SUm");
 		for (i = 0; i < PLATFORM_MAX_CHANNELS; i++)
 			src_polyphase_unmute(&cd->src[i]);
 
 		break;
+	default:
+		trace_src_error("ec1");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/* used to pass standard and bespoke commands (with data) to component */
+static int src_cmd(struct comp_dev *dev, int cmd, void *data)
+{
+	struct sof_ipc_ctrl_data *cdata = data;
+
+	trace_src("SCm");
+
+	switch (cmd) {
+	case COMP_CMD_SET_VALUE:
+		return src_ctrl_cmd(dev, cdata);
 	case COMP_CMD_START:
 		trace_src("SSt");
 		dev->state = COMP_STATE_RUNNING;
diff --git a/src/audio/tone.c b/src/audio/tone.c
index cbc50ac..448c472 100644
--- a/src/audio/tone.c
+++ b/src/audio/tone.c
@@ -229,6 +229,7 @@ static inline void tonegen_set_f(struct tone_state *sg, int32_t f)
 	sg->f = f;
 }
 
+#if 0
 /* Tone sweep parameters description:
  * fc - Multiplication factor for frequency as Q2.30 for logarithmic change
  * ac - Multiplication factor for amplitude as Q2.30 for logarithmic change
@@ -250,6 +251,7 @@ static void tonegen_set_sweep(struct tone_state *sg, int32_t fc, int32_t ac,
 	sg->tone_length = (l > 0) ? l : INT32_MAXVALUE; /* Count rate 125 us */
 	sg->tone_period = (p > 0) ? p : INT32_MAXVALUE; /* Count rate 125 us */
 }
+#endif
 
 /* Tone ramp parameters:
  * step - Value that is added or subtracted to amplitude. A zero or negative
@@ -428,16 +430,22 @@ static int tone_params(struct comp_dev *dev)
 	return 0;
 }
 
-/* used to pass standard and bespoke commands (with data) to component */
-static int tone_cmd(struct comp_dev *dev, int cmd, void *data)
+static int tone_ctrl_cmd(struct comp_dev *dev, struct sof_ipc_ctrl_data *cdata)
 {
 	struct comp_data *cd = comp_get_drvdata(dev);
-	struct sof_ipc_comp_tone *ct;
-
-	trace_tone("tri");
 
-	switch (cmd) {
-	case COMP_CMD_TONE:
+	switch (cdata->cmd) {
+	case SOF_CTRL_CMD_MUTE:
+		trace_tone("TMu");
+		tonegen_mute(&cd->sg);
+		break;
+	case SOF_CTRL_CMD_UNMUTE:
+		trace_tone("TUm");
+		tonegen_unmute(&cd->sg);
+		break;
+/* TODO: use comp value list array to set this */
+#if 0
+	case SOF_CTRL_TYPE_VALUE_COMP_SET:
 		trace_tone("Tto");
 		ct = (struct sof_ipc_comp_tone *) data;
 		/* Ignore channels while tone implementation is mono */
@@ -447,14 +455,25 @@ static int tone_cmd(struct comp_dev *dev, int cmd, void *data)
 			ct->length, ct->period, ct->repeats);
 		tonegen_set_linramp(&cd->sg, ct->ramp_step);
 		break;
-	case COMP_CMD_MUTE:
-		trace_tone("TMu");
-		tonegen_mute(&cd->sg);
-		break;
-	case COMP_CMD_UNMUTE:
-		trace_tone("TUm");
-		tonegen_unmute(&cd->sg);
-		break;
+#endif
+	default:
+		trace_tone_error("ec1");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/* used to pass standard and bespoke commands (with data) to component */
+static int tone_cmd(struct comp_dev *dev, int cmd, void *data)
+{
+	struct sof_ipc_ctrl_data *cdata = data;
+
+	trace_tone("tri");
+
+	switch (cmd) {
+	case COMP_CMD_SET_VALUE:
+		return tone_ctrl_cmd(dev, cdata);
 	case COMP_CMD_START:
 		trace_tone("TSt");
 		dev->state = COMP_STATE_RUNNING;
diff --git a/src/audio/volume.c b/src/audio/volume.c
index 93a3839..6cbd6ff 100644
--- a/src/audio/volume.c
+++ b/src/audio/volume.c
@@ -69,16 +69,16 @@ struct comp_data {
 	uint32_t sink_period_bytes;
 	enum sof_ipc_frame source_format;
 	enum sof_ipc_frame sink_format;
-	uint32_t chan[PLATFORM_MAX_CHANNELS];
-	uint32_t volume[PLATFORM_MAX_CHANNELS];	/* current volume */
-	uint32_t tvolume[PLATFORM_MAX_CHANNELS];	/* target volume */
-	uint32_t mvolume[PLATFORM_MAX_CHANNELS];	/* mute volume */
+	uint32_t chan[SOF_IPC_MAX_CHANNELS];
+	uint32_t volume[SOF_IPC_MAX_CHANNELS];	/* current volume */
+	uint32_t tvolume[SOF_IPC_MAX_CHANNELS];	/* target volume */
+	uint32_t mvolume[SOF_IPC_MAX_CHANNELS];	/* mute volume */
 	void (*scale_vol)(struct comp_dev *dev, struct comp_buffer *sink,
 		struct comp_buffer *source, uint32_t frames);
 	struct work volwork;
 
 	/* host volume readback */
-	struct sof_ipc_ctrl_values *hvol;
+	struct sof_ipc_ctrl_value_chan *hvol;
 };
 
 struct comp_func_map {
@@ -234,9 +234,9 @@ static void vol_sync_host(struct comp_data *cd, uint32_t chan)
 	if (cd->hvol == NULL)
 		return;
 
-	for (i = 0; i < cd->hvol->num_values; i++) {
-		if (cd->hvol->values[i].channel == cd->chan[chan])
-			cd->hvol->values[i].value = cd->volume[chan];
+	for (i = 0; i < SOF_IPC_MAX_CHANNELS; i++) {
+		if (cd->hvol[i].channel == cd->chan[chan])
+			cd->hvol[i].value = cd->volume[chan];
 	}
 }
 
@@ -380,50 +380,61 @@ static inline void volume_set_chan_unmute(struct comp_dev *dev, int chan)
 	cd->tvolume[chan] = cd->mvolume[chan];
 }
 
-/* used to pass standard and bespoke commands (with data) to component */
-static int volume_cmd(struct comp_dev *dev, int cmd, void *data)
+static int volume_ctrl_cmd(struct comp_dev *dev, struct sof_ipc_ctrl_data *cdata)
 {
 	struct comp_data *cd = comp_get_drvdata(dev);
-	struct sof_ipc_ctrl_values *cv;
 	int i, j;
 
-	trace_volume("cmd");
-
-	switch (cmd) {
-	case COMP_CMD_VOLUME:
-		cv = (struct sof_ipc_ctrl_values*)data;
+	switch (cdata->cmd) {
+	case SOF_CTRL_CMD_VOLUME:
 
-		for (i = 0; i < PLATFORM_MAX_CHANNELS; i++) {
-			for (j = 0; j < cv->num_values; j++) {
-				if (cv->values[j].channel == cd->chan[i])
-					volume_set_chan(dev, i, cv->values[j].value);
+		for (i = 0; i < SOF_IPC_MAX_CHANNELS; i++) {
+			for (j = 0; j < cdata->num_elems; j++) {
+				if (cdata->chanv[j].value == cd->chan[i])
+					volume_set_chan(dev, i, cdata->chanv[j].value);
 			}
 		}
 
 		work_schedule_default(&cd->volwork, VOL_RAMP_US);
 		break;
-	case COMP_CMD_MUTE:
-		cv = (struct sof_ipc_ctrl_values*)data;
+	case SOF_CTRL_CMD_MUTE:
 
-		for (i = 0; i < PLATFORM_MAX_CHANNELS; i++) {
-			for (j = 0; j < cv->num_values; j++) {
-				if (cv->values[j].channel == cd->chan[i])
+		for (i = 0; i < SOF_IPC_MAX_CHANNELS; i++) {
+			for (j = 0; j < cdata->num_elems; j++) {
+				if (cdata->chanv[j].value == cd->chan[i])
 					volume_set_chan_mute(dev, i);
 			}
 		}
 		work_schedule_default(&cd->volwork, VOL_RAMP_US);
 		break;
-	case COMP_CMD_UNMUTE:
-		cv = (struct sof_ipc_ctrl_values*)data;
+	case SOF_CTRL_CMD_UNMUTE:
 
-		for (i = 0; i < PLATFORM_MAX_CHANNELS; i++) {
-			for (j = 0; j < cv->num_values; j++) {
-				if (cv->values[j].channel == cd->chan[i])
+		for (i = 0; i < SOF_IPC_MAX_CHANNELS; i++) {
+			for (j = 0; j < cdata->num_elems; j++) {
+				if (cdata->chanv[j].value == cd->chan[i])
 					volume_set_chan_unmute(dev, i);
 			}
 		}
 		work_schedule_default(&cd->volwork, VOL_RAMP_US);
 		break;
+	default:
+		trace_volume_error("ec1");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/* used to pass standard and bespoke commands (with data) to component */
+static int volume_cmd(struct comp_dev *dev, int cmd, void *data)
+{
+	struct sof_ipc_ctrl_data *cdata = data;
+
+	trace_volume("cmd");
+
+	switch (cmd) {
+	case COMP_CMD_SET_VALUE:
+		return volume_ctrl_cmd(dev, cdata);
 	case COMP_CMD_START:
 		dev->state = COMP_STATE_RUNNING;
 		break;
diff --git a/src/include/reef/audio/component.h b/src/include/reef/audio/component.h
index e73a22a..35c80de 100644
--- a/src/include/reef/audio/component.h
+++ b/src/include/reef/audio/component.h
@@ -59,7 +59,9 @@
 #define COMP_STATE_PAUSED	5	/* component paused */
 #define COMP_STATE_RUNNING	6	/* component active */
 
-/* standard component commands */
+/*
+ * standard component stream commands
+ */
 
 #define COMP_CMD_STOP		0	/* stop component stream */
 #define COMP_CMD_START		1	/* start component stream */
@@ -69,18 +71,15 @@
 #define COMP_CMD_SUSPEND	5	/* suspend component */
 #define COMP_CMD_RESUME		6	/* resume component */
 
-#define COMP_CMD_VOLUME		100
-#define COMP_CMD_MUTE		101
-#define COMP_CMD_UNMUTE		102
-#define COMP_CMD_ROUTE		103
-#define COMP_CMD_SRC		104
-#define COMP_CMD_LOOPBACK	105
-
-#define COMP_CMD_TONE           106     /* Tone generator amplitude and frequency */
-#define COMP_CMD_EQ_FIR_CONFIG  107     /* Configuration data for FIR EQ */
-#define COMP_CMD_EQ_FIR_SWITCH  108     /* Update request for FIR EQ */
-#define COMP_CMD_EQ_IIR_CONFIG  109     /* Configuration data for IIR EQ */
-#define COMP_CMD_EQ_IIR_SWITCH  110     /* Response update request for IIR EQ */
+/*
+ * standard component control commands
+ */
+
+#define COMP_CMD_SET_VALUE	100
+#define COMP_CMD_GET_VALUE	101
+#define COMP_CMD_SET_DATA	102
+#define COMP_CMD_GET_DATA	103
+
 
 /* MMAP IPC status */
 #define COMP_CMD_IPC_MMAP_RPOS	200	/* host read position */
diff --git a/src/include/uapi/ipc.h b/src/include/uapi/ipc.h
index 053390c..c8cdedb 100644
--- a/src/include/uapi/ipc.h
+++ b/src/include/uapi/ipc.h
@@ -88,15 +88,12 @@
 #define SOF_IPC_PM_CLK_GET			SOF_CMD_TYPE(0x005)
 #define SOF_IPC_PM_CLK_REQ			SOF_CMD_TYPE(0x006)
 
-/* component - multiple different types */
-#define SOF_IPC_COMP_SET_VOLUME			SOF_CMD_TYPE(0x001)
-#define SOF_IPC_COMP_GET_VOLUME			SOF_CMD_TYPE(0x002)
-#define SOF_IPC_COMP_SET_MIXER			SOF_CMD_TYPE(0x003)
-#define SOF_IPC_COMP_GET_MIXER			SOF_CMD_TYPE(0x004)
-#define SOF_IPC_COMP_SET_MUX			SOF_CMD_TYPE(0x005)
-#define SOF_IPC_COMP_GET_MUX			SOF_CMD_TYPE(0x006)
-#define SOF_IPC_COMP_SET_SRC			SOF_CMD_TYPE(0x007)
-#define SOF_IPC_COMP_GET_SRC			SOF_CMD_TYPE(0x008)
+/* component runtime config - multiple different types */
+#define SOF_IPC_COMP_SET_VALUE			SOF_CMD_TYPE(0x001)
+#define SOF_IPC_COMP_GET_VALUE			SOF_CMD_TYPE(0x002)
+#define SOF_IPC_COMP_SET_DATA			SOF_CMD_TYPE(0x003)
+#define SOF_IPC_COMP_GET_DATA			SOF_CMD_TYPE(0x004)
+
 
 /* DAI messages */
 #define SOF_IPC_DAI_CONFIG			SOF_CMD_TYPE(0x001)
@@ -433,24 +430,69 @@ struct sof_ipc_stream_posn {
  * Component Mixers and Controls
  */
 
-struct sof_ipc_ctrl_chan {
+/* control data type and direction */
+enum sof_ipc_ctrl_type {
+	SOF_CTRL_TYPE_VALUE_CHAN_GET = 0,
+	SOF_CTRL_TYPE_VALUE_CHAN_SET,
+	SOF_CTRL_TYPE_VALUE_COMP_GET,
+	SOF_CTRL_TYPE_VALUE_COMP_SET,
+	SOF_CTRL_TYPE_DATA_GET,
+	SOF_CTRL_TYPE_DATA_SET,
+};
+
+/* control command type */
+enum sof_ipc_ctrl_cmd {
+	SOF_CTRL_CMD_VOLUME = 0,
+	SOF_CTRL_CMD_ROUTE,
+	SOF_CTRL_CMD_SRC,
+	SOF_CTRL_CMD_LOOPBACK,
+	SOF_CTRL_CMD_EQ_SWITCH,
+	SOF_CTRL_CMD_EQ_CONFIG,
+	/* Mute is similar to volume, but maps better onto ALSA switch controls */
+	SOF_CTRL_CMD_MUTE,
+	SOF_CTRL_CMD_UNMUTE,
+};
+
+/* generic channel mapped value data */
+struct sof_ipc_ctrl_value_chan {
 	enum sof_ipc_chmap channel;
 	uint32_t value;
 } __attribute__((packed));
 
-struct sof_ipc_ctrl_values {
-	struct sof_ipc_hdr hdr;
-	uint32_t comp_id;
-	uint32_t num_values;
-	struct sof_ipc_ctrl_chan values[SOF_IPC_MAX_CHANNELS];
+/* generic component mapped value data */
+struct sof_ipc_ctrl_value_comp {
+	uint32_t index;		/* component source/sink/control index in control */
+	union {
+		uint32_t uvalue;
+		int32_t svalue;
+	};
 } __attribute__((packed));
 
-struct sof_ipc_ctrl_get_values {
+/* generic control data */
+struct sof_ipc_ctrl_data {
 	struct sof_ipc_hdr hdr;
 	uint32_t comp_id;
-	uint32_t num_values;
+
+	/* control access and data type */
+	enum sof_ipc_ctrl_type type;
+	enum sof_ipc_ctrl_cmd cmd;
+
+	/* control data - can either be appended or DMAed from host */
+	struct sof_ipc_host_buffer buffer;
+	uint32_t num_elems;	/* in array elems or bytes */
+
+	/* control data - add new types if needed */
+	union {
+		/* channel values can be used by volume type controls */
+		struct sof_ipc_ctrl_value_chan chanv[0];
+		/* component values used by routing controls like mux, mixer */
+		struct sof_ipc_ctrl_value_comp compv[0];
+		/* data can be used by binary controls */
+		char data[0];
+	};
 } __attribute__((packed));
 
+
 /*
  * Component
  */
@@ -599,28 +641,6 @@ struct sof_ipc_comp_eq_iir {
        struct sof_ipc_comp_config config;
 } __attribute__((packed));
 
-/* IPC to pass configuration blobs to equalizers and re-assign responses */
-struct sof_ipc_eq_fir_blob {
-	struct sof_ipc_comp comp;
-	struct sof_ipc_host_buffer buffer;
-	int32_t data[];
-} __attribute__((packed));
-
-struct sof_ipc_eq_iir_blob {
-	struct sof_ipc_comp comp;
-	struct sof_ipc_host_buffer buffer;
-	int32_t data[];
-} __attribute__((packed));
-
-struct sof_ipc_eq_fir_switch {
-	struct sof_ipc_comp comp;
-	int32_t data[];
-} __attribute__((packed));
-
-struct sof_ipc_eq_iir_switch {
-	struct sof_ipc_comp comp;
-	int32_t data[];
-} __attribute__((packed));
 
 /* frees components, buffers and pipelines
  * SOF_IPC_TPLG_COMP_FREE, SOF_IPC_TPLG_PIPE_FREE, SOF_IPC_TPLG_BUFFER_FREE
diff --git a/src/ipc/intel-ipc.c b/src/ipc/intel-ipc.c
index 60001c3..4f397c1 100644
--- a/src/ipc/intel-ipc.c
+++ b/src/ipc/intel-ipc.c
@@ -559,48 +559,31 @@ static int ipc_glb_pm_message(uint32_t header)
  * Topology IPC Operations.
  */
 
-static int ipc_comp_set_value(uint32_t header, uint32_t cmd)
+/* get/set component values or runtime data */
+static int ipc_comp_value(uint32_t header, uint32_t cmd)
 {
 	struct ipc_comp_dev *stream_dev;
-	struct sof_ipc_ctrl_values *values = _ipc->comp_data;
-
-	trace_ipc("VoS");
-
-	/* get the component */
-	stream_dev = ipc_get_comp(_ipc, values->comp_id);
-	if (stream_dev == NULL) {
-		trace_ipc_error("eVs");
-		return -ENODEV;
-	}
-
-	/* set component values */
-	return comp_cmd(stream_dev->cd, cmd, values);
-}
-
-static int ipc_comp_get_value(uint32_t header, uint32_t cmd)
-{
-	struct ipc_comp_dev *stream_dev;
-	struct sof_ipc_ctrl_values *values = _ipc->comp_data;
+	struct sof_ipc_ctrl_data *data = _ipc->comp_data;
 	int ret;
 
 	trace_ipc("VoG");
 
 	/* get the component */
-	stream_dev = ipc_get_comp(_ipc, values->comp_id);
+	stream_dev = ipc_get_comp(_ipc, data->comp_id);
 	if (stream_dev == NULL){
 		trace_ipc_error("eVg");
 		return -ENODEV;
 	}
 	
 	/* get component values */
-	ret = comp_cmd(stream_dev->cd, COMP_CMD_VOLUME, values);
+	ret = comp_cmd(stream_dev->cd, cmd, data);
 	if (ret < 0) {
 		trace_ipc_error("eVG");
 		return ret;
 	}
 
 	/* write component values to the outbox */
-	mailbox_outbox_write(values, 0, sizeof(*values));
+	mailbox_outbox_write(0, data, data->hdr.size);
 
 	return 0;
 }
@@ -610,22 +593,14 @@ static int ipc_glb_comp_message(uint32_t header)
 	uint32_t cmd = (header & SOF_CMD_TYPE_MASK) >> SOF_CMD_TYPE_SHIFT;
 
 	switch (cmd) {
-	case iCS(SOF_IPC_COMP_SET_VOLUME):
-		return ipc_comp_set_value(header, COMP_CMD_VOLUME);
-	case iCS(SOF_IPC_COMP_GET_VOLUME):
-		return ipc_comp_get_value(header, COMP_CMD_VOLUME);
-	case iCS(SOF_IPC_COMP_SET_MIXER):
-		return ipc_comp_set_value(header, COMP_CMD_ROUTE);
-	case iCS(SOF_IPC_COMP_GET_MIXER):
-		return ipc_comp_get_value(header, COMP_CMD_ROUTE);
-	case iCS(SOF_IPC_COMP_SET_MUX):
-		return ipc_comp_set_value(header, COMP_CMD_ROUTE);
-	case iCS(SOF_IPC_COMP_GET_MUX):
-		return ipc_comp_get_value(header, COMP_CMD_ROUTE);
-	case iCS(SOF_IPC_COMP_SET_SRC):
-		return ipc_comp_set_value(header, COMP_CMD_SRC);
-	case iCS(SOF_IPC_COMP_GET_SRC):
-		return ipc_comp_get_value(header, COMP_CMD_SRC);
+	case iCS(SOF_IPC_COMP_SET_VALUE):
+		return ipc_comp_value(header, COMP_CMD_SET_VALUE);
+	case iCS(SOF_IPC_COMP_GET_VALUE):
+		return ipc_comp_value(header, COMP_CMD_GET_VALUE);
+	case iCS(SOF_IPC_COMP_SET_DATA):
+		return ipc_comp_value(header, COMP_CMD_SET_DATA);
+	case iCS(SOF_IPC_COMP_GET_DATA):
+		return ipc_comp_value(header, COMP_CMD_GET_DATA);
 	default:
 		trace_ipc_error("eCc");
 		trace_value(header);
-- 
2.11.0



More information about the Sound-open-firmware mailing list