From 485c939552e381f2061916b4adf1556859b8c957 Mon Sep 17 00:00:00 2001 From: Pin-chih Lin Date: Wed, 20 Jan 2021 23:50:56 +0800 Subject: [PATCH] src: codec_adapter: Add process passthrough path If the passthrough flag is enabled, on process() the data in the input buffer should be directly copied to the output buffer. The passthrough flag is implemented to be set/get by topology enum control. Signed-off-by: Pin-chih Lin --- src/audio/codec_adapter/codec/generic.c | 23 ++++- src/audio/codec_adapter/codec_adapter.c | 92 +++++++++++++++++++ .../sof/audio/codec_adapter/codec/generic.h | 1 + tools/topology/m4/codec_adapter.m4 | 3 + .../sof/pipe-codec-adapter-playback.m4 | 20 +++- 5 files changed, 137 insertions(+), 2 deletions(-) diff --git a/src/audio/codec_adapter/codec/generic.c b/src/audio/codec_adapter/codec/generic.c index 8c1259f8805b..4442f1e02199 100644 --- a/src/audio/codec_adapter/codec/generic.c +++ b/src/audio/codec_adapter/codec/generic.c @@ -245,6 +245,22 @@ int codec_prepare(struct comp_dev *dev) return ret; } +static int process_passthrough(struct comp_dev *dev) +{ + int ret; + struct codec_data *codec = comp_get_codec(dev); + + ret = memcpy_s(codec->cpd.out_buff, codec->cpd.avail, codec->cpd.in_buff, codec->cpd.avail); + if (ret) { + comp_err(dev, "process_through() error %d: failed to copy data from in to out", + ret); + codec->cpd.produced = 0; + return ret; + } + codec->cpd.produced = codec->cpd.avail; + return 0; +} + int codec_process(struct comp_dev *dev) { int ret; @@ -260,7 +276,12 @@ int codec_process(struct comp_dev *dev) return -EPERM; } - ret = codec->ops->process(dev); + // TODO: how to set cd->passthrough flag? + if (cd->passthrough) { + ret = process_passthrough(dev); + } else { + ret = codec->ops->process(dev); + } if (ret) { comp_err(dev, "codec_prepare() error %d: codec process failed for codec_id %x", ret, codec_id); diff --git a/src/audio/codec_adapter/codec_adapter.c b/src/audio/codec_adapter/codec_adapter.c index 5ce1a18bd57b..df7996475f41 100644 --- a/src/audio/codec_adapter/codec_adapter.c +++ b/src/audio/codec_adapter/codec_adapter.c @@ -30,6 +30,8 @@ DECLARE_SOF_RT_UUID("codec_adapter", ca_uuid, 0xd8218443, 0x5ff3, 0x4a4c, DECLARE_TR_CTX(ca_tr, SOF_UUID(ca_uuid), LOG_LEVEL_INFO); +#define ENUM_CTRL_PASSTHROUGH 0 + /** * \brief Create a codec adapter component. * \param[in] drv - component driver pointer. @@ -91,6 +93,7 @@ static struct comp_dev *codec_adapter_new(const struct comp_driver *drv, dev->state = COMP_STATE_READY; cd->state = PP_STATE_CREATED; + cd->passthrough = 0; comp_cl_info(&comp_codec_adapter, "codec_adapter_new() done"); return dev; @@ -620,6 +623,89 @@ static int codec_adapter_ctrl_set_data(struct comp_dev *dev, return ret; } +static int codec_adapter_ctrl_enum_set(struct sof_ipc_ctrl_data *cdata, struct comp_data *cd) +{ + int ret; + + switch (cdata->index) { + case ENUM_CTRL_PASSTHROUGH: + if (cdata->num_elems) + cd->passthrough = cdata->chanv[0].value; + break; + default: + comp_cl_err(&comp_codec_adapter, + "codec_adapter_ctrl_enum_set() error: invalid index=%d", + cdata->index); + ret = -EINVAL; + break; + } + + return ret; +} + +static int codec_adapter_set_value(struct comp_dev *dev, + struct sof_ipc_ctrl_data *cdata) +{ + int ret; + struct comp_data *cd = comp_get_drvdata(dev); + + switch (cdata->cmd) { + case SOF_CTRL_CMD_ENUM: + comp_dbg(dev, "codec_adapter_set_value(): SOF_CTRL_CMD_ENUM index=%d", + cdata->index); + ret = codec_adapter_ctrl_enum_set(cdata, cd); + break; + default: + comp_err(dev, "codec_adapter_set_value() error: invalid cdata->cmd"); + ret = -EINVAL; + break; + } + + return ret; +} + +static int codec_adapter_ctrl_enum_get(struct sof_ipc_ctrl_data *cdata, struct comp_data *cd) +{ + int ret; + int j; + + switch (cdata->index) { + case ENUM_CTRL_PASSTHROUGH: + for (j = 0; j < cdata->num_elems; j++) + cdata->chanv[j].value = cd->passthrough; + break; + default: + comp_cl_err(&comp_codec_adapter, + "codec_adapter_ctrl_enum_get() error: invalid index=%d", + cdata->index); + ret = -EINVAL; + break; + } + + return ret; +} + +static int codec_adapter_get_value(struct comp_dev *dev, + struct sof_ipc_ctrl_data *cdata) +{ + int ret; + struct comp_data *cd = comp_get_drvdata(dev); + + switch (cdata->cmd) { + case SOF_CTRL_CMD_ENUM: + comp_dbg(dev, "codec_adapter_get_value(): SOF_CTRL_CMD_ENUM index=%d", + cdata->index); + ret = codec_adapter_ctrl_enum_get(cdata, cd); + break; + default: + comp_err(dev, "codec_adapter_get_value() error: invalid cdata->cmd"); + ret = -EINVAL; + break; + } + + return ret; +} + /* Used to pass standard and bespoke commands (with data) to component */ static int codec_adapter_cmd(struct comp_dev *dev, int cmd, void *data, int max_data_size) @@ -637,6 +723,12 @@ static int codec_adapter_cmd(struct comp_dev *dev, int cmd, void *data, comp_err(dev, "codec_adapter_cmd() get_data not implemented yet."); ret = -ENODATA; break; + case COMP_CMD_SET_VALUE: + ret = codec_adapter_set_value(dev, cdata); + break; + case COMP_CMD_GET_VALUE: + ret = codec_adapter_get_value(dev, cdata); + break; default: comp_err(dev, "codec_adapter_cmd() error: unknown command"); ret = -EINVAL; diff --git a/src/include/sof/audio/codec_adapter/codec/generic.h b/src/include/sof/audio/codec_adapter/codec/generic.h index 32b7f38346ad..da2d78ab230a 100644 --- a/src/include/sof/audio/codec_adapter/codec/generic.h +++ b/src/include/sof/audio/codec_adapter/codec/generic.h @@ -188,6 +188,7 @@ struct comp_data { struct sof_ipc_stream_params stream_params; uint32_t period_bytes; /** pipeline period bytes */ uint32_t deep_buff_bytes; /**< copy start threshold */ + int passthrough:1; /**< data passthrough mode */ }; /*****************************************************************************/ diff --git a/tools/topology/m4/codec_adapter.m4 b/tools/topology/m4/codec_adapter.m4 index c5e932433731..65f52589a957 100644 --- a/tools/topology/m4/codec_adapter.m4 +++ b/tools/topology/m4/codec_adapter.m4 @@ -50,6 +50,9 @@ define(`W_CODEC_ADAPTER', ` bytes [' $6 ` ]' +` enum [' + $7 +` ]' `}') diff --git a/tools/topology/sof/pipe-codec-adapter-playback.m4 b/tools/topology/sof/pipe-codec-adapter-playback.m4 index af3c5e4c1b98..69547b56bd2a 100644 --- a/tools/topology/sof/pipe-codec-adapter-playback.m4 +++ b/tools/topology/sof/pipe-codec-adapter-playback.m4 @@ -12,6 +12,7 @@ include(`dai.m4') include(`pipeline.m4') include(`codec_adapter.m4') include(`bytecontrol.m4') +include(`enumcontrol.m4') # # Controls @@ -99,6 +100,20 @@ C_CONTROLBYTES(CA_RUNTIME_CONTROLBYTES_NAME_PIPE, PIPELINE_ID, , CA_RUNTIME_PARAMS) +define(CA_PASSTHRU_ENUM, concat(`ca_passthru_enum_', PIPELINE_ID)) +define(CA_PASSTHRU_CONTROL, concat(`CA PassThrough', PIPELINE_ID)) + +# Codec adapter passthrough enum list +CONTROLENUM_LIST(CA_PASSTHRU_ENUM, LIST(` ', `"passthru off"', `"passthru on"')) + +# Codec adapter passthrough enum control +C_CONTROLENUM(CA_PASSTHRU_CONTROL, PIPELINE_ID, + CA_PASSTHRU_ENUM, + LIST(` ', ENUM_CHANNEL(FC, 3, 0)), + CONTROLENUM_OPS(enum, + 257 binds the mixer control to enum get/put handlers, + 257, 257)) + # # Components and Buffers # @@ -112,7 +127,8 @@ ifdef(`CA_SCHEDULE_CORE',`', `define(`CA_SCHEDULE_CORE', `SCHEDULE_CORE')') W_PCM_PLAYBACK(PCM_ID, Passthrough Playback, DAI_PERIODS, 0, SCHEDULE_CORE) W_CODEC_ADAPTER(0, PIPELINE_FORMAT, DAI_PERIODS, DAI_PERIODS, CA_SCHEDULE_CORE, - LIST(` ', "CA_SETUP_CONTROLBYTES_NAME_PIPE", "CA_RUNTIME_CONTROLBYTES_NAME_PIPE")) + LIST(` ', "CA_SETUP_CONTROLBYTES_NAME_PIPE", "CA_RUNTIME_CONTROLBYTES_NAME_PIPE"), + LIST(` ', "CA_PASSTHRU_CONTROL")) # Playback Buffers W_BUFFER(0, COMP_BUFFER_SIZE(DAI_PERIODS, @@ -145,6 +161,8 @@ indir(`define', concat(`PIPELINE_PCM_', PIPELINE_ID), Passthrough Playback PCM_I PCM_CAPABILITIES(Passthrough Playback PCM_ID, CAPABILITY_FORMAT_NAME(PIPELINE_FORMAT), PCM_MIN_RATE, PCM_MAX_RATE, 2, PIPELINE_CHANNELS, 2, 16, 192, 16384, 65536, 65536) +undefine(`CA_PASSTHRU_CONTROL') +undefine(`CA_PASSTHRU_ENUM') undefine(`CA_RUNTIME_CONTROLBYTES_NAME_PIPE') undefine(`CA_RUNTIME_PARAMS') undefine(`CA_SETUP_CONTROLBYTES_NAME_PIPE')