[Sound-open-firmware] [PATCH v2 1/2] Switch component added
Ranjani Sridharan
ranjani.sridharan at linux.intel.com
Mon Sep 11 23:39:02 CEST 2017
This patch adds a new switch component that mutes the pipeline when the
when the switch is OFF. Stream data flows through the pipeline normally
when it is ON.
Signed-off-by: Ranjani Sridharan <ranjani.sridharan at linux.intel.com>
---
src/audio/switch.c | 178 +++++++++++++++++++++++++++++++++++++++++++++++--
src/include/uapi/ipc.h | 6 ++
2 files changed, 178 insertions(+), 6 deletions(-)
diff --git a/src/audio/switch.c b/src/audio/switch.c
index 7149b61..67f723c 100644
--- a/src/audio/switch.c
+++ b/src/audio/switch.c
@@ -26,6 +26,7 @@
* POSSIBILITY OF SUCH DAMAGE.
*
* Author: Liam Girdwood <liam.r.girdwood at linux.intel.com>
+ * Ranjani Sridharan <ranjani.sridharan at linux.intel.com>
*/
#include <stdint.h>
@@ -40,46 +41,211 @@
#define trace_switch_error(__e) trace_error(TRACE_CLASS_SWITCH, __e)
#define tracev_switch(__e) tracev_event(TRACE_CLASS_SWITCH, __e)
+/* Simple switch component
+ * This component copies stream data from source buffer to the sink buffer
+ * if the switch is ON. Otherwise it discards the source buffer data and
+ * writes 0's to the sink buffer.
+ */
+
+/*
+ * switch_comp_data structure
+ * on_switch - indicates if the switch is ON/OFF
+ * switch_func - function that performs the routing of input buffer to
+ * the output buffer based on on_switch
+ */
+struct switch_comp_data {
+ int on_switch;
+ int (*switch_func)(struct comp_dev *dev, struct comp_buffer *sink,
+ struct comp_buffer *source, uint32_t frames);
+
+};
+
+/* switch function to copy data from source to sink buffer */
+static int switch_function(struct comp_dev *dev,
+ struct comp_buffer *sink_buffer,
+ struct comp_buffer *source_buffer, uint32_t frames)
+{
+ struct sof_ipc_comp_config *config = COMP_GET_CONFIG(dev);
+ struct switch_comp_data *cd = comp_get_drvdata(dev);
+ int32_t *src = (int32_t *) source_buffer->r_ptr;
+ int32_t *dest = (int32_t *) sink_buffer->w_ptr;
+ int nch = dev->params.channels;
+
+ /* copy source buffer to sink buffer if switch is on */
+ if (cd->on_switch == 1) {
+ /* copy frames from source to destination */
+ switch (config->frame_fmt) {
+ case SOF_IPC_FRAME_S16_LE:
+ memcpy(dest, src, frames * nch * sizeof(int16_t));
+ break;
+ case SOF_IPC_FRAME_S32_LE:
+ case SOF_IPC_FRAME_S24_4LE:
+ case SOF_IPC_FRAME_FLOAT:
+ memcpy(dest, src, frames * nch * sizeof(int32_t));
+ break;
+ default:
+ trace_switch_error("SWf");
+ return -EINVAL;
+ }
+
+ return frames;
+ }
+
+ /* discard source data and copy 0's if switch is off */
+ memset(dest, 0, frames * nch * sizeof(int32_t));
+
+ return frames;
+}
+
static struct comp_dev *switch_new(struct sof_ipc_comp *comp)
{
- trace_switch("new");
+ struct comp_dev *dev;
+ struct switch_comp_data *cd;
+
+ trace_switch("Swn");
+ dev = rzalloc(RZONE_RUNTIME, RFLAGS_NONE,
+ COMP_SIZE(struct sof_ipc_comp_switch));
+ if (dev == NULL)
+ return NULL;
+
+ memcpy(&dev->comp, comp, sizeof(struct sof_ipc_comp_switch));
- return NULL;
+ cd = rzalloc(RZONE_RUNTIME, RFLAGS_NONE, sizeof(*cd));
+ if (cd == NULL) {
+ rfree(dev);
+ return NULL;
+ }
+
+ /* switch is on by default */
+ cd->on_switch = 1;
+
+ comp_set_drvdata(dev, cd);
+ cd->switch_func = switch_function;
+
+ return dev;
}
static void switch_free(struct comp_dev *dev)
{
+ struct switch_comp_data *cd = comp_get_drvdata(dev);
+ rfree(cd);
+ rfree(dev);
}
/* set component audio stream paramters */
static int switch_params(struct comp_dev *dev)
{
-
return 0;
}
+static int switch_ctrl_cmd(struct comp_dev *dev,
+ struct sof_ipc_ctrl_data *cdata)
+{
+ struct switch_comp_data *cd = comp_get_drvdata(dev);
+ int ret = 0;
+
+ if (cdata == NULL) {
+ trace_switch_error("swe");
+ return -EINVAL;
+ }
+
+ switch (cdata->cmd) {
+ case SOF_CTRL_CMD_ROUTE:
+ /* check if the ctrl cmd is for this component */
+ if (cdata->comp_id != dev->comp.id)
+ break;
+
+ if (cdata->num_elems < 1) {
+ trace_switch_error("Swd");
+ ret = -EINVAL;
+ }
+
+ cd->on_switch = cdata->compv[0].uvalue;
+ break;
+ default:
+ break;
+ }
+
+ return ret;
+}
+
/* used to pass standard and bespoke commands (with data) to component */
static int switch_cmd(struct comp_dev *dev, int cmd, void *data)
{
- /* switch will use buffer "connected" status */
- return 0;
+ struct sof_ipc_ctrl_data *cdata = data;
+ int ret = 0;
+
+ switch (cmd) {
+ case COMP_CMD_SET_VALUE:
+ ret = switch_ctrl_cmd(dev, cdata);
+ break;
+ case COMP_CMD_START:
+ case COMP_CMD_STOP:
+ case COMP_CMD_PAUSE:
+ case COMP_CMD_RELEASE:
+ default:
+ ret = comp_set_state(dev, cmd);
+ break;
+ }
+
+ return ret;
}
/* copy and process stream data from source to sink buffers */
static int switch_copy(struct comp_dev *dev)
{
+ struct switch_comp_data *cd = comp_get_drvdata(dev);
+ struct comp_buffer *source_buffer = NULL, *sink_buffer = NULL;
+ uint32_t copy_bytes;
- return 0;
+ /* get source and sink buffers */
+ source_buffer = list_first_item(&dev->bsource_list, struct comp_buffer,
+ sink_list);
+ sink_buffer = list_first_item(&dev->bsink_list, struct comp_buffer,
+ source_list);
+
+ if (!source_buffer || !sink_buffer) {
+ trace_switch_error("Scp");
+ return -EINVAL;
+ }
+
+ /* check that source has enough frames available and sink enough
+ * frames free.
+ */
+ copy_bytes = comp_buffer_get_copy_bytes(dev, source_buffer,
+ sink_buffer);
+
+ if (copy_bytes < dev->params.host_period_bytes) {
+ trace_switch_error("Scb");
+ return -EINVAL;
+ }
+
+ /* Run passthrough if buffers have enough room */
+ cd->switch_func(dev, sink_buffer, source_buffer, dev->frames);
+
+ comp_update_buffer_consume(source_buffer,
+ dev->params.host_period_bytes);
+ comp_update_buffer_produce(sink_buffer, dev->params.host_period_bytes);
+
+ return dev->frames;
}
static int switch_reset(struct comp_dev *dev)
{
+ struct switch_comp_data *cd = comp_get_drvdata(dev);
+
+ /* reset switch to on status */
+ cd->on_switch = 1;
+ dev->state = COMP_STATE_INIT;
+
return 0;
}
static int switch_prepare(struct comp_dev *dev)
{
+ dev->state = COMP_STATE_PREPARE;
+
return 0;
}
diff --git a/src/include/uapi/ipc.h b/src/include/uapi/ipc.h
index 2c2f415..cbef325 100644
--- a/src/include/uapi/ipc.h
+++ b/src/include/uapi/ipc.h
@@ -616,6 +616,12 @@ struct sof_ipc_comp_mux {
struct sof_ipc_comp_config config;
} __attribute__((packed));
+/* generic switch component */
+struct sof_ipc_comp_switch {
+ struct sof_ipc_comp comp;
+ struct sof_ipc_comp_config config;
+} __attribute__((packed));
+
/* generic passthrough component */
struct sof_ipc_comp_passthrough {
struct sof_ipc_comp comp;
--
2.11.0
More information about the Sound-open-firmware
mailing list