Audio: copier: add hifi version implementation of apply_attenuation

add hifi version implementation of apply_attenuation, using xtensa
instructions can save about 74% cycles than the original one.

Signed-off-by: Andrula Song <xiaoyuan.song@intel.com>
This commit is contained in:
Andrula Song 2022-07-05 10:02:40 +08:00 committed by Liam Girdwood
parent 9d2857fe37
commit 12d660b088
7 changed files with 170 additions and 63 deletions

View File

@ -135,10 +135,8 @@ if(NOT CONFIG_LIBRARY)
add_subdirectory(igo_nr)
endif()
if(CONFIG_COMP_COPIER)
add_local_sources(sof
copier.c
)
endif()
add_subdirectory(copier)
endif()
if(CONFIG_COMP_RTNR)
add_subdirectory(rtnr)
endif()

View File

@ -0,0 +1,2 @@
add_local_sources(sof copier.c copier_hifi.c copier_generic.c)

View File

@ -47,31 +47,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);
struct copier_data {
/* Must be the 1st field, function ipc4_comp_get_base_module_cfg casts components
* private data as ipc4_base_module_cfg!
*/
struct ipc4_copier_module_cfg config;
struct comp_dev *endpoint[IPC4_COPIER_MODULE_OUTPUT_PINS_COUNT];
struct comp_buffer *endpoint_buffer[IPC4_COPIER_MODULE_OUTPUT_PINS_COUNT];
uint32_t endpoint_num;
bool bsource_buffer;
int direction;
/* sample data >> attenuation in range of [1 - 31] */
uint32_t attenuation;
/* pipeline register offset in memory windows 0 */
uint32_t pipeline_reg_offset;
uint64_t host_position;
struct ipc4_audio_format out_fmt[IPC4_COPIER_MODULE_OUTPUT_PINS_COUNT];
pcm_converter_func converter[IPC4_COPIER_MODULE_OUTPUT_PINS_COUNT];
uint64_t input_total_data_processed;
uint64_t output_total_data_processed;
};
static pcm_converter_func get_converter_func(struct ipc4_audio_format *in_fmt,
struct ipc4_audio_format *out_fmt,
enum ipc4_gateway_type type,
@ -775,39 +750,6 @@ static int copier_comp_trigger(struct comp_dev *dev, int cmd)
return ret;
}
static inline int apply_attenuation(struct comp_dev *dev, struct copier_data *cd,
struct comp_buffer __sparse_cache *sink, int frame)
{
int i;
int n;
int nmax;
int remaining_samples = frame * sink->stream.channels;
uint32_t *dst = sink->stream.r_ptr;
/* only support attenuation in format of 32bit */
switch (sink->stream.frame_fmt) {
case SOF_IPC_FRAME_S16_LE:
comp_err(dev, "16bit sample isn't supported by attenuation");
return -EINVAL;
case SOF_IPC_FRAME_S24_4LE:
case SOF_IPC_FRAME_S32_LE:
while (remaining_samples) {
nmax = audio_stream_samples_without_wrap_s32(&sink->stream, dst);
n = MIN(remaining_samples, nmax);
for (i = 0; i < n; i++) {
*dst >>= cd->attenuation;
dst++;
}
remaining_samples -= n;
dst = audio_stream_wrap(&sink->stream, dst);
}
return 0;
default:
comp_err(dev, "unsupported format %d for attenuation", sink->stream.frame_fmt);
return -EINVAL;
}
}
static int do_conversion_copy(struct comp_dev *dev,
struct copier_data *cd,
struct comp_buffer __sparse_cache *src,
@ -824,6 +766,7 @@ static int do_conversion_copy(struct comp_dev *dev,
cd->converter[i](&src->stream, 0, &sink->stream, 0,
processed_data->frames * sink->stream.channels);
if (cd->attenuation) {
ret = apply_attenuation(dev, cd, sink, processed_data->frames);
if (ret < 0)

View File

@ -0,0 +1,55 @@
// SPDX-License-Identifier: BSD-3-Clause
//
// Copyright(c) 2022 Intel Corporation. All rights reserved.
//
// Author: Andrula Song <xiaoyuan.song@intel.com>
#include <ipc4/copier.h>
#ifdef COPIER_GENERIC
#include <sof/audio/buffer.h>
#include <sof/audio/component_ext.h>
#include <sof/audio/format.h>
#include <sof/audio/pipeline.h>
#include <sof/audio/component.h>
#include <sof/common.h>
#include <stddef.h>
#include <errno.h>
#include <stdint.h>
int apply_attenuation(struct comp_dev *dev, struct copier_data *cd,
struct comp_buffer __sparse_cache *sink, int frame)
{
int i;
int n;
int nmax;
int remaining_samples = frame * sink->stream.channels;
int32_t *dst = sink->stream.r_ptr;
/* only support attenuation in format of 32bit */
switch (sink->stream.frame_fmt) {
case SOF_IPC_FRAME_S16_LE:
comp_err(dev, "16bit sample isn't supported by attenuation");
return -EINVAL;
case SOF_IPC_FRAME_S24_4LE:
case SOF_IPC_FRAME_S32_LE:
while (remaining_samples) {
nmax = audio_stream_samples_without_wrap_s32(&sink->stream, dst);
n = MIN(remaining_samples, nmax);
for (i = 0; i < n; i++) {
*dst >>= cd->attenuation;
dst++;
}
remaining_samples -= n;
dst = audio_stream_wrap(&sink->stream, dst);
}
return 0;
default:
comp_err(dev, "unsupported format %d for attenuation", sink->stream.frame_fmt);
return -EINVAL;
}
}
#endif

View File

@ -0,0 +1,64 @@
// SPDX-License-Identifier: BSD-3-Clause
//
// Copyright(c) 2022 Intel Corporation. All rights reserved.
//
// Author: Andrula Song <xiaoyuan.song@intel.com>
#include <ipc4/copier.h>
#if __XCC__ && (XCHAL_HAVE_HIFI3 || XCHAL_HAVE_HIFI4)
#include <sof/audio/buffer.h>
#include <sof/audio/component_ext.h>
#include <sof/audio/format.h>
#include <sof/audio/pipeline.h>
#include <sof/audio/component.h>
#include <sof/common.h>
#include <stddef.h>
#include <errno.h>
#include <stdint.h>
#include <xtensa/tie/xt_hifi3.h>
int apply_attenuation(struct comp_dev *dev, struct copier_data *cd,
struct comp_buffer __sparse_cache *sink, int frame)
{
int i;
int n;
int nmax;
ae_int32x2 sample;
ae_valign uu = AE_ZALIGN64();
ae_valign su = AE_ZALIGN64();
int remaining_samples = frame * sink->stream.channels;
uint32_t *dst = sink->stream.r_ptr;
ae_int32x2 *in = (ae_int32x2 *)dst;
ae_int32x2 *out = (ae_int32x2 *)dst;
/* only support attenuation in format of 32bit */
switch (sink->stream.frame_fmt) {
case SOF_IPC_FRAME_S16_LE:
comp_err(dev, "16bit sample isn't supported by attenuation");
return -EINVAL;
case SOF_IPC_FRAME_S24_4LE:
case SOF_IPC_FRAME_S32_LE:
while (remaining_samples) {
nmax = audio_stream_samples_without_wrap_s32(&sink->stream, dst);
in = (ae_int32x2 *)dst;
out = (ae_int32x2 *)dst;
uu = AE_LA64_PP(in);
n = MIN(remaining_samples, nmax);
for (i = 0; i < n; i += 2) {
AE_LA32X2_IP(sample, uu, in);
sample = AE_SRAA32(sample, cd->attenuation);
AE_SA32X2_IP(sample, su, out);
}
AE_SA64POS_FP(su, out);
remaining_samples -= n;
dst = audio_stream_wrap(&sink->stream, dst + n);
}
return 0;
default:
comp_err(dev, "unsupported format %d for attenuation", sink->stream.frame_fmt);
return -EINVAL;
}
}
#endif

View File

@ -28,6 +28,21 @@
#include <ipc4/base-config.h>
#include <ipc4/gateway.h>
#include <sof/compiler_attributes.h>
#include <sof/audio/buffer.h>
#include <sof/audio/pcm_converter.h>
#define COPIER_GENERIC
#if defined(__XCC__)
#include <xtensa/config/core-isa.h>
#if XCHAL_HAVE_HIFI3 || XCHAL_HAVE_HIFI4
#undef COPIER_GENERIC
#endif
#endif
/* This is basic module config that may serve as a base for more specialized, module
* specific config received along with Init Module Instance from host.
*
@ -305,4 +320,32 @@ struct ipc4_data_segment_enabled {
uint32_t data_seg_size;
} __attribute__((packed, aligned(4)));
struct copier_data {
/* Must be the 1st field, function ipc4_comp_get_base_module_cfg casts components
* private data as ipc4_base_module_cfg!
*/
struct ipc4_copier_module_cfg config;
struct comp_dev *endpoint[IPC4_COPIER_MODULE_OUTPUT_PINS_COUNT];
struct comp_buffer *endpoint_buffer[IPC4_COPIER_MODULE_OUTPUT_PINS_COUNT];
uint32_t endpoint_num;
bool bsource_buffer;
int direction;
/* sample data >> attenuation in range of [1 - 31] */
uint32_t attenuation;
/* pipeline register offset in memory windows 0 */
uint32_t pipeline_reg_offset;
uint64_t host_position;
struct ipc4_audio_format out_fmt[IPC4_COPIER_MODULE_OUTPUT_PINS_COUNT];
pcm_converter_func converter[IPC4_COPIER_MODULE_OUTPUT_PINS_COUNT];
uint64_t input_total_data_processed;
uint64_t output_total_data_processed;
};
int apply_attenuation(struct comp_dev *dev, struct copier_data *cd,
struct comp_buffer __sparse_cache *sink, int frame);
#endif

View File

@ -715,7 +715,9 @@ zephyr_library_sources_ifdef(CONFIG_COMP_BASEFW_IPC4
)
zephyr_library_sources_ifdef(CONFIG_COMP_COPIER
${SOF_AUDIO_PATH}/copier.c
${SOF_AUDIO_PATH}/copier/copier_generic.c
${SOF_AUDIO_PATH}/copier/copier_hifi.c
${SOF_AUDIO_PATH}/copier/copier.c
)
zephyr_library_sources_ifdef(CONFIG_MAXIM_DSM