copier: move some common functions to generic file

Move some functions from copier.c to copier_generic.c.

Signed-off-by: Baofeng Tian <baofeng.tian@intel.com>
This commit is contained in:
Baofeng Tian 2023-05-24 18:41:46 +08:00 committed by Kai Vehmanen
parent 97f78ea3f1
commit 9158bab370
2 changed files with 166 additions and 167 deletions

View File

@ -54,129 +54,6 @@ DECLARE_SOF_RT_UUID("copier", copier_comp_uuid, 0x9ba00c83, 0xca12, 0x4a83,
DECLARE_TR_CTX(copier_comp_tr, SOF_UUID(copier_comp_uuid), LOG_LEVEL_INFO); DECLARE_TR_CTX(copier_comp_tr, SOF_UUID(copier_comp_uuid), LOG_LEVEL_INFO);
int create_endpoint_buffer(struct comp_dev *parent_dev,
struct copier_data *cd,
struct comp_ipc_config *config,
const struct ipc4_copier_module_cfg *copier_cfg,
enum ipc4_gateway_type type,
bool create_multi_endpoint_buffer,
int index)
{
enum sof_ipc_frame in_frame_fmt, out_frame_fmt;
enum sof_ipc_frame in_valid_fmt, out_valid_fmt;
enum sof_ipc_frame valid_fmt;
struct sof_ipc_buffer ipc_buf;
struct comp_buffer *buffer;
struct comp_buffer __sparse_cache *buffer_c;
uint32_t buf_size;
uint32_t chan_map;
int i;
audio_stream_fmt_conversion(copier_cfg->base.audio_fmt.depth,
copier_cfg->base.audio_fmt.valid_bit_depth,
&in_frame_fmt, &in_valid_fmt,
copier_cfg->base.audio_fmt.s_type);
audio_stream_fmt_conversion(copier_cfg->out_fmt.depth,
copier_cfg->out_fmt.valid_bit_depth,
&out_frame_fmt, &out_valid_fmt,
copier_cfg->out_fmt.s_type);
/* playback case:
*
* --> copier0 -----> buf1 ----> .... bufn --------> copier1
* | /|\ |conversion |
* \|/ |conversion \|/ \|/
* host-> endpoint buffer0 endpoint buffer1 -> dai -->
*
* capture case:
*
* copier1 <------ bufn <---- .... buf1 <------- copier0 <--
* | |conversion /|\ |
* \|/ \|/ |conversion \|/
* <-- host <- endpoint buffer1 endpoint buffer0 <- dai
*
* According to above graph, the format of endpoint buffer
* depends on stream direction and component type.
*/
if (cd->direction == SOF_IPC_STREAM_PLAYBACK) {
if (config->type == SOF_COMP_HOST) {
config->frame_fmt = in_frame_fmt;
valid_fmt = in_valid_fmt;
buf_size = copier_cfg->base.ibs * 2;
} else {
config->frame_fmt = out_frame_fmt;
valid_fmt = out_valid_fmt;
buf_size = copier_cfg->base.obs * 2;
}
chan_map = copier_cfg->out_fmt.ch_map;
} else {
if (config->type == SOF_COMP_HOST) {
config->frame_fmt = out_frame_fmt;
valid_fmt = out_valid_fmt;
buf_size = copier_cfg->base.obs * 2;
} else {
config->frame_fmt = in_frame_fmt;
valid_fmt = in_valid_fmt;
buf_size = copier_cfg->base.ibs * 2;
}
chan_map = copier_cfg->base.audio_fmt.ch_map;
}
parent_dev->ipc_config.frame_fmt = config->frame_fmt;
memset(&ipc_buf, 0, sizeof(ipc_buf));
ipc_buf.size = buf_size;
ipc_buf.comp.pipeline_id = config->pipeline_id;
ipc_buf.comp.core = config->core;
buffer = buffer_new(&ipc_buf);
if (!buffer)
return -ENOMEM;
buffer_c = buffer_acquire(buffer);
audio_stream_set_channels(&buffer_c->stream, copier_cfg->base.audio_fmt.channels_count);
audio_stream_set_rate(&buffer_c->stream, copier_cfg->base.audio_fmt.sampling_frequency);
audio_stream_set_frm_fmt(&buffer_c->stream, config->frame_fmt);
audio_stream_set_valid_fmt(&buffer_c->stream, valid_fmt);
buffer_c->buffer_fmt = copier_cfg->base.audio_fmt.interleaving_style;
for (i = 0; i < SOF_IPC_MAX_CHANNELS; i++)
buffer_c->chmap[i] = (chan_map >> i * 4) & 0xf;
buffer_c->hw_params_configured = true;
buffer_release(buffer_c);
if (create_multi_endpoint_buffer)
cd->multi_endpoint_buffer = buffer;
else
cd->endpoint_buffer[cd->endpoint_num] = buffer;
return 0;
}
enum sof_ipc_stream_direction
get_gateway_direction(enum ipc4_connector_node_id_type node_id_type)
{
/* WARNING: simple "% 2" formula that was used before does not work for all
* interfaces: at least it does not work for IPC gateway. But it may also
* does not work for other not yet supported interfaces. And so additional
* cases might be required here in future.
*/
switch (node_id_type) {
/* from DSP to host */
case ipc4_ipc_output_class:
return SOF_IPC_STREAM_CAPTURE;
/* from host to DSP */
case ipc4_ipc_input_class:
return SOF_IPC_STREAM_PLAYBACK;
default:
return node_id_type % 2;
}
}
/* Playback only */ /* Playback only */
static int init_pipeline_reg(struct comp_dev *dev) static int init_pipeline_reg(struct comp_dev *dev)
{ {
@ -186,7 +63,7 @@ static int init_pipeline_reg(struct comp_dev *dev)
gateway_id = cd->config.gtw_cfg.node_id.f.v_index; gateway_id = cd->config.gtw_cfg.node_id.f.v_index;
if (gateway_id >= IPC4_MAX_PIPELINE_REG_SLOTS) { if (gateway_id >= IPC4_MAX_PIPELINE_REG_SLOTS) {
comp_cl_err(&comp_copier, "gateway_id %u out of array bounds.", gateway_id); comp_err(dev, "gateway_id %u out of array bounds.", gateway_id);
return -EINVAL; return -EINVAL;
} }
@ -352,46 +229,6 @@ static void copier_free(struct comp_dev *dev)
rfree(dev); rfree(dev);
} }
/* In sof normal format conversion path, sample size should be equal
* to container size except format of S24_LE. In ipc4 case, sample
* size can be different with container size. This function is used to
* check conversion mode.
*/
static bool use_no_container_convert_function(enum sof_ipc_frame in,
enum sof_ipc_frame valid_in_bits,
enum sof_ipc_frame out,
enum sof_ipc_frame valid_out_bits)
{
/* valid sample size is equal to container size, go normal path */
if (in == valid_in_bits && out == valid_out_bits) {
if (in == SOF_IPC_FRAME_S24_3LE || out == SOF_IPC_FRAME_S24_3LE)
return false;
return true;
}
return false;
}
pcm_converter_func get_converter_func(const struct ipc4_audio_format *in_fmt,
const struct ipc4_audio_format *out_fmt,
enum ipc4_gateway_type type,
enum ipc4_direction_type dir)
{
enum sof_ipc_frame in, in_valid, out, out_valid;
audio_stream_fmt_conversion(in_fmt->depth, in_fmt->valid_bit_depth, &in, &in_valid,
in_fmt->s_type);
audio_stream_fmt_conversion(out_fmt->depth, out_fmt->valid_bit_depth, &out, &out_valid,
out_fmt->s_type);
/* check container & sample size */
if (use_no_container_convert_function(in, in_valid, out, out_valid))
return pcm_get_conversion_function(in, out);
else
return pcm_get_conversion_vc_function(in, in_valid, out, out_valid, type, dir);
}
static int copier_prepare(struct comp_dev *dev) static int copier_prepare(struct comp_dev *dev)
{ {
struct copier_data *cd = comp_get_drvdata(dev); struct copier_data *cd = comp_get_drvdata(dev);

View File

@ -7,6 +7,8 @@
#include <ipc4/copier.h> #include <ipc4/copier.h>
#include <sof/audio/component_ext.h> #include <sof/audio/component_ext.h>
LOG_MODULE_DECLARE(copier, CONFIG_SOF_LOG_LEVEL);
#ifdef COPIER_GENERIC #ifdef COPIER_GENERIC
#include <sof/audio/buffer.h> #include <sof/audio/buffer.h>
@ -18,8 +20,6 @@
#include <errno.h> #include <errno.h>
#include <stdint.h> #include <stdint.h>
LOG_MODULE_REGISTER(copier_generic, CONFIG_SOF_LOG_LEVEL);
int apply_attenuation(struct comp_dev *dev, struct copier_data *cd, int apply_attenuation(struct comp_dev *dev, struct copier_data *cd,
struct comp_buffer __sparse_cache *sink, int frame) struct comp_buffer __sparse_cache *sink, int frame)
{ {
@ -54,7 +54,6 @@ int apply_attenuation(struct comp_dev *dev, struct copier_data *cd,
return -EINVAL; return -EINVAL;
} }
} }
#endif #endif
void update_buffer_format(struct comp_buffer __sparse_cache *buf_c, void update_buffer_format(struct comp_buffer __sparse_cache *buf_c,
@ -151,3 +150,166 @@ void copier_update_params(struct copier_data *cd, struct comp_dev *dev,
break; break;
} }
} }
int create_endpoint_buffer(struct comp_dev *parent_dev,
struct copier_data *cd,
struct comp_ipc_config *config,
const struct ipc4_copier_module_cfg *copier_cfg,
enum ipc4_gateway_type type,
bool create_multi_endpoint_buffer,
int index)
{
enum sof_ipc_frame in_frame_fmt, out_frame_fmt;
enum sof_ipc_frame in_valid_fmt, out_valid_fmt;
enum sof_ipc_frame valid_fmt;
struct sof_ipc_buffer ipc_buf;
struct comp_buffer *buffer;
struct comp_buffer __sparse_cache *buffer_c;
uint32_t buf_size;
uint32_t chan_map;
int i;
audio_stream_fmt_conversion(copier_cfg->base.audio_fmt.depth,
copier_cfg->base.audio_fmt.valid_bit_depth,
&in_frame_fmt, &in_valid_fmt,
copier_cfg->base.audio_fmt.s_type);
audio_stream_fmt_conversion(copier_cfg->out_fmt.depth,
copier_cfg->out_fmt.valid_bit_depth,
&out_frame_fmt, &out_valid_fmt,
copier_cfg->out_fmt.s_type);
/* playback case:
*
* --> copier0 -----> buf1 ----> .... bufn --------> copier1
* | /|\ |conversion |
* \|/ |conversion \|/ \|/
* host-> endpoint buffer0 endpoint buffer1 -> dai -->
*
* capture case:
*
* copier1 <------ bufn <---- .... buf1 <------- copier0 <--
* | |conversion /|\ |
* \|/ \|/ |conversion \|/
* <-- host <- endpoint buffer1 endpoint buffer0 <- dai
*
* According to above graph, the format of endpoint buffer
* depends on stream direction and component type.
*/
if (cd->direction == SOF_IPC_STREAM_PLAYBACK) {
if (config->type == SOF_COMP_HOST) {
config->frame_fmt = in_frame_fmt;
valid_fmt = in_valid_fmt;
buf_size = copier_cfg->base.ibs * 2;
} else {
config->frame_fmt = out_frame_fmt;
valid_fmt = out_valid_fmt;
buf_size = copier_cfg->base.obs * 2;
}
chan_map = copier_cfg->out_fmt.ch_map;
} else {
if (config->type == SOF_COMP_HOST) {
config->frame_fmt = out_frame_fmt;
valid_fmt = out_valid_fmt;
buf_size = copier_cfg->base.obs * 2;
} else {
config->frame_fmt = in_frame_fmt;
valid_fmt = in_valid_fmt;
buf_size = copier_cfg->base.ibs * 2;
}
chan_map = copier_cfg->base.audio_fmt.ch_map;
}
parent_dev->ipc_config.frame_fmt = config->frame_fmt;
memset(&ipc_buf, 0, sizeof(ipc_buf));
ipc_buf.size = buf_size;
ipc_buf.comp.pipeline_id = config->pipeline_id;
ipc_buf.comp.core = config->core;
buffer = buffer_new(&ipc_buf);
if (!buffer)
return -ENOMEM;
buffer_c = buffer_acquire(buffer);
audio_stream_set_channels(&buffer_c->stream, copier_cfg->base.audio_fmt.channels_count);
audio_stream_set_rate(&buffer_c->stream, copier_cfg->base.audio_fmt.sampling_frequency);
audio_stream_set_frm_fmt(&buffer_c->stream, config->frame_fmt);
audio_stream_set_valid_fmt(&buffer_c->stream, valid_fmt);
buffer_c->buffer_fmt = copier_cfg->base.audio_fmt.interleaving_style;
for (i = 0; i < SOF_IPC_MAX_CHANNELS; i++)
buffer_c->chmap[i] = (chan_map >> i * 4) & 0xf;
buffer_c->hw_params_configured = true;
buffer_release(buffer_c);
if (create_multi_endpoint_buffer)
cd->multi_endpoint_buffer = buffer;
else
cd->endpoint_buffer[cd->endpoint_num] = buffer;
return 0;
}
enum sof_ipc_stream_direction
get_gateway_direction(enum ipc4_connector_node_id_type node_id_type)
{
/* WARNING: simple "% 2" formula that was used before does not work for all
* interfaces: at least it does not work for IPC gateway. But it may also
* does not work for other not yet supported interfaces. And so additional
* cases might be required here in future.
*/
switch (node_id_type) {
/* from DSP to host */
case ipc4_ipc_output_class:
return SOF_IPC_STREAM_CAPTURE;
/* from host to DSP */
case ipc4_ipc_input_class:
return SOF_IPC_STREAM_PLAYBACK;
default:
return node_id_type % 2;
}
}
/* In sof normal format conversion path, sample size should be equal
* to container size except format of S24_LE. In ipc4 case, sample
* size can be different with container size. This function is used to
* check conversion mode.
*/
static bool use_no_container_convert_function(enum sof_ipc_frame in,
enum sof_ipc_frame valid_in_bits,
enum sof_ipc_frame out,
enum sof_ipc_frame valid_out_bits)
{
/* valid sample size is equal to container size, go normal path */
if (in == valid_in_bits && out == valid_out_bits) {
if (in == SOF_IPC_FRAME_S24_3LE || out == SOF_IPC_FRAME_S24_3LE)
return false;
return true;
}
return false;
}
pcm_converter_func get_converter_func(const struct ipc4_audio_format *in_fmt,
const struct ipc4_audio_format *out_fmt,
enum ipc4_gateway_type type,
enum ipc4_direction_type dir)
{
enum sof_ipc_frame in, in_valid, out, out_valid;
audio_stream_fmt_conversion(in_fmt->depth, in_fmt->valid_bit_depth, &in, &in_valid,
in_fmt->s_type);
audio_stream_fmt_conversion(out_fmt->depth, out_fmt->valid_bit_depth, &out, &out_valid,
out_fmt->s_type);
/* check container & sample size */
if (use_no_container_convert_function(in, in_valid, out, out_valid))
return pcm_get_conversion_function(in, out);
else
return pcm_get_conversion_vc_function(in, in_valid, out, out_valid, type, dir);
}