mirror of https://github.com/thesofproject/sof.git
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:
parent
97f78ea3f1
commit
9158bab370
|
@ -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);
|
||||
|
||||
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 */
|
||||
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;
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -352,46 +229,6 @@ static void copier_free(struct comp_dev *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)
|
||||
{
|
||||
struct copier_data *cd = comp_get_drvdata(dev);
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
#include <ipc4/copier.h>
|
||||
#include <sof/audio/component_ext.h>
|
||||
|
||||
LOG_MODULE_DECLARE(copier, CONFIG_SOF_LOG_LEVEL);
|
||||
|
||||
#ifdef COPIER_GENERIC
|
||||
|
||||
#include <sof/audio/buffer.h>
|
||||
|
@ -18,8 +20,6 @@
|
|||
#include <errno.h>
|
||||
#include <stdint.h>
|
||||
|
||||
LOG_MODULE_REGISTER(copier_generic, CONFIG_SOF_LOG_LEVEL);
|
||||
|
||||
int apply_attenuation(struct comp_dev *dev, struct copier_data *cd,
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue