summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/sound/sof/topology.h27
-rw-r--r--include/uapi/sound/sof/abi.h2
-rw-r--r--include/uapi/sound/sof/tokens.h6
-rw-r--r--sound/soc/sof/topology.c78
4 files changed, 112 insertions, 1 deletions
diff --git a/include/sound/sof/topology.h b/include/sound/sof/topology.h
index c47b36240920..8e76178fedf0 100644
--- a/include/sound/sof/topology.h
+++ b/include/sound/sof/topology.h
@@ -36,6 +36,7 @@ enum sof_comp_type {
SOF_COMP_KPB, /* A key phrase buffer component */
SOF_COMP_SELECTOR, /**< channel selector component */
SOF_COMP_DEMUX,
+ SOF_COMP_ASRC, /**< Asynchronous sample rate converter */
/* keep FILEREAD/FILEWRITE as the last ones */
SOF_COMP_FILEREAD = 10000, /**< host test based file IO */
SOF_COMP_FILEWRITE = 10001, /**< host test based file IO */
@@ -147,6 +148,32 @@ struct sof_ipc_comp_src {
uint32_t rate_mask; /**< SOF_RATE_ supported rates */
} __packed;
+/* generic ASRC component */
+struct sof_ipc_comp_asrc {
+ struct sof_ipc_comp comp;
+ struct sof_ipc_comp_config config;
+ /* either source or sink rate must be non zero */
+ uint32_t source_rate; /**< Define fixed source rate or */
+ /**< use 0 to indicate need to get */
+ /**< the rate from stream */
+ uint32_t sink_rate; /**< Define fixed sink rate or */
+ /**< use 0 to indicate need to get */
+ /**< the rate from stream */
+ uint32_t asynchronous_mode; /**< synchronous 0, asynchronous 1 */
+ /**< When 1 the ASRC tracks and */
+ /**< compensates for drift. */
+ uint32_t operation_mode; /**< push 0, pull 1, In push mode the */
+ /**< ASRC consumes a defined number */
+ /**< of frames at input, with varying */
+ /**< number of frames at output. */
+ /**< In pull mode the ASRC outputs */
+ /**< a defined number of frames while */
+ /**< number of input frames varies. */
+
+ /* reserved for future use */
+ uint32_t reserved[4];
+} __attribute__((packed));
+
/* generic MUX component */
struct sof_ipc_comp_mux {
struct sof_ipc_comp comp;
diff --git a/include/uapi/sound/sof/abi.h b/include/uapi/sound/sof/abi.h
index ebfdc20ca081..c0ef1643c753 100644
--- a/include/uapi/sound/sof/abi.h
+++ b/include/uapi/sound/sof/abi.h
@@ -26,7 +26,7 @@
/* SOF ABI version major, minor and patch numbers */
#define SOF_ABI_MAJOR 3
-#define SOF_ABI_MINOR 11
+#define SOF_ABI_MINOR 12
#define SOF_ABI_PATCH 0
/* SOF ABI version number. Format within 32bit word is MMmmmppp */
diff --git a/include/uapi/sound/sof/tokens.h b/include/uapi/sound/sof/tokens.h
index 76883e6fb750..a9a5c4d0a892 100644
--- a/include/uapi/sound/sof/tokens.h
+++ b/include/uapi/sound/sof/tokens.h
@@ -57,6 +57,12 @@
#define SOF_TKN_SRC_RATE_IN 300
#define SOF_TKN_SRC_RATE_OUT 301
+/* ASRC */
+#define SOF_TKN_ASRC_RATE_IN 320
+#define SOF_TKN_ASRC_RATE_OUT 321
+#define SOF_TKN_ASRC_ASYNCHRONOUS_MODE 322
+#define SOF_TKN_ASRC_OPERATION_MODE 323
+
/* PCM */
#define SOF_TKN_PCM_DMAC_CONFIG 353
diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c
index 1ae06a1f9b0b..215f4d23ddfe 100644
--- a/sound/soc/sof/topology.c
+++ b/sound/soc/sof/topology.c
@@ -573,6 +573,20 @@ static const struct sof_topology_token src_tokens[] = {
offsetof(struct sof_ipc_comp_src, sink_rate), 0},
};
+/* ASRC */
+static const struct sof_topology_token asrc_tokens[] = {
+ {SOF_TKN_ASRC_RATE_IN, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
+ offsetof(struct sof_ipc_comp_asrc, source_rate), 0},
+ {SOF_TKN_ASRC_RATE_OUT, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
+ offsetof(struct sof_ipc_comp_asrc, sink_rate), 0},
+ {SOF_TKN_ASRC_ASYNCHRONOUS_MODE, SND_SOC_TPLG_TUPLE_TYPE_WORD,
+ get_token_u32,
+ offsetof(struct sof_ipc_comp_asrc, asynchronous_mode), 0},
+ {SOF_TKN_ASRC_OPERATION_MODE, SND_SOC_TPLG_TUPLE_TYPE_WORD,
+ get_token_u32,
+ offsetof(struct sof_ipc_comp_asrc, operation_mode), 0},
+};
+
/* Tone */
static const struct sof_topology_token tone_tokens[] = {
};
@@ -1783,6 +1797,67 @@ err:
}
/*
+ * ASRC Topology
+ */
+
+static int sof_widget_load_asrc(struct snd_soc_component *scomp, int index,
+ struct snd_sof_widget *swidget,
+ struct snd_soc_tplg_dapm_widget *tw,
+ struct sof_ipc_comp_reply *r)
+{
+ struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
+ struct snd_soc_tplg_private *private = &tw->priv;
+ struct sof_ipc_comp_asrc *asrc;
+ int ret;
+
+ asrc = kzalloc(sizeof(*asrc), GFP_KERNEL);
+ if (!asrc)
+ return -ENOMEM;
+
+ /* configure ASRC IPC message */
+ asrc->comp.hdr.size = sizeof(*asrc);
+ asrc->comp.hdr.cmd = SOF_IPC_GLB_TPLG_MSG | SOF_IPC_TPLG_COMP_NEW;
+ asrc->comp.id = swidget->comp_id;
+ asrc->comp.type = SOF_COMP_ASRC;
+ asrc->comp.pipeline_id = index;
+ asrc->config.hdr.size = sizeof(asrc->config);
+
+ ret = sof_parse_tokens(scomp, asrc, asrc_tokens,
+ ARRAY_SIZE(asrc_tokens), private->array,
+ le32_to_cpu(private->size));
+ if (ret != 0) {
+ dev_err(scomp->dev, "error: parse asrc tokens failed %d\n",
+ private->size);
+ goto err;
+ }
+
+ ret = sof_parse_tokens(scomp, &asrc->config, comp_tokens,
+ ARRAY_SIZE(comp_tokens), private->array,
+ le32_to_cpu(private->size));
+ if (ret != 0) {
+ dev_err(scomp->dev, "error: parse asrc.cfg tokens failed %d\n",
+ le32_to_cpu(private->size));
+ goto err;
+ }
+
+ dev_dbg(scomp->dev, "asrc %s: source rate %d sink rate %d "
+ "asynch %d operation %d\n",
+ swidget->widget->name, asrc->source_rate, asrc->sink_rate,
+ asrc->asynchronous_mode, asrc->operation_mode);
+ sof_dbg_comp_config(scomp, &asrc->config);
+
+ swidget->private = asrc;
+
+ ret = sof_ipc_tx_message(sdev->ipc, asrc->comp.hdr.cmd, asrc,
+ sizeof(*asrc), r, sizeof(*r));
+ if (ret >= 0)
+ return ret;
+err:
+ kfree(asrc);
+ return ret;
+}
+
+/*
* Signal Generator Topology
*/
@@ -2195,6 +2270,9 @@ static int sof_widget_ready(struct snd_soc_component *scomp, int index,
case snd_soc_dapm_src:
ret = sof_widget_load_src(scomp, index, swidget, tw, &reply);
break;
+ case snd_soc_dapm_asrc:
+ ret = sof_widget_load_asrc(scomp, index, swidget, tw, &reply);
+ break;
case snd_soc_dapm_siggen:
ret = sof_widget_load_siggen(scomp, index, swidget, tw, &reply);
break;