Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add device posture feature #9238

Merged
merged 8 commits into from
Jul 17, 2024
13 changes: 5 additions & 8 deletions posix/include/sof/lib/dma.h
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,7 @@ struct dma_info {
struct audio_stream;
typedef int (*dma_process_func)(const struct audio_stream __sparse_cache *source,
uint32_t ioffset, struct audio_stream __sparse_cache *sink,
uint32_t ooffset, uint32_t frames);
uint32_t ooffset, uint32_t source_samples, uint32_t chmap);

/**
* \brief API to initialize a platform DMA controllers.
Expand Down Expand Up @@ -523,19 +523,15 @@ static inline uint32_t dma_sg_get_size(struct dma_sg_elem_array *ea)
return size;
}

struct audio_stream;
typedef void (*dma_process)(const struct audio_stream *,
struct audio_stream *, uint32_t);

/* copies data from DMA buffer using provided processing function */
int dma_buffer_copy_from(struct comp_buffer __sparse_cache *source,
struct comp_buffer __sparse_cache *sink,
dma_process_func process, uint32_t source_bytes);
dma_process_func process, uint32_t source_bytes, uint32_t chmap);

/* copies data to DMA buffer using provided processing function */
int dma_buffer_copy_to(struct comp_buffer __sparse_cache *source,
struct comp_buffer __sparse_cache *sink,
dma_process_func process, uint32_t sink_bytes);
dma_process_func process, uint32_t sink_bytes, uint32_t chmap);

/*
* Used when copying DMA buffer bytes into multiple sink buffers, one at a time using the provided
Expand All @@ -544,7 +540,8 @@ int dma_buffer_copy_to(struct comp_buffer __sparse_cache *source,
*/
int dma_buffer_copy_from_no_consume(struct comp_buffer __sparse_cache *source,
struct comp_buffer __sparse_cache *sink,
dma_process_func process, uint32_t source_bytes);
dma_process_func process,
uint32_t source_bytes, uint32_t chmap);

/* generic DMA DSP <-> Host copier */

Expand Down
15 changes: 15 additions & 0 deletions src/audio/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,13 @@ config PCM_CONVERTER_FORMAT_S32LE
help
Support 32 bit processing data format with sign and in little endian format

config PCM_CONVERTER_FORMAT_S16_4LE
bool "Support S16_4LE"
default y
help
Support the format of signed 16-bit little-endian in the 2 lower bytes
of a 32-bit container. This format is used, for example, by the SSP gateway.

config PCM_CONVERTER_FORMAT_FLOAT
bool "Support float"
default y
Expand Down Expand Up @@ -305,6 +312,14 @@ config PCM_CONVERTER_FORMAT_CONVERT_HIFI3
help
Use HIFI3 extensions for optimized format conversion (experimental).

config PCM_REMAPPING_CONVERTERS
bool "Channel remapping conversions"
default y
depends on IPC_MAJOR_4
help
Enable conversion functions that perform both format conversion
and channel remapping simultaneously.

config TRACE_CHANNEL
int "TRACE DMA Channel configuration"
default 0
Expand Down
103 changes: 96 additions & 7 deletions src/audio/copier/copier.c
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,8 @@ static int copier_init(struct processing_module *mod)

dev->direction_set = true;
} else {
cd->gtw_type = ipc4_gtw_none;

/* set max sink count for module copier */
mod->max_sinks = IPC4_COPIER_MODULE_OUTPUT_PINS_COUNT;
}
Expand Down Expand Up @@ -244,7 +246,7 @@ static int copier_prepare(struct processing_module *mod,
*/
cd->converter[0] = get_converter_func(&cd->config.base.audio_fmt,
&cd->config.out_fmt, ipc4_gtw_none,
ipc4_bidirection);
ipc4_bidirection, DUMMY_CHMAP);
if (!cd->converter[0]) {
comp_err(dev, "can't support for in format %d, out format %d",
cd->config.base.audio_fmt.depth, cd->config.out_fmt.depth);
Expand Down Expand Up @@ -440,7 +442,8 @@ static int do_conversion_copy(struct comp_dev *dev,
buffer_stream_invalidate(src, processed_data->source_bytes);

cd->converter[i](&src->stream, 0, &sink->stream, 0,
processed_data->frames * audio_stream_get_channels(&sink->stream));
processed_data->frames * audio_stream_get_channels(&src->stream),
DUMMY_CHMAP);

buffer_stream_writeback(sink, processed_data->sink_bytes);
comp_update_buffer_produce(sink, processed_data->sink_bytes);
Expand Down Expand Up @@ -509,7 +512,7 @@ static int copier_module_copy(struct processing_module *mod,
sink_dev = sink_c->sink;
processed_data.sink_bytes = 0;
if (sink_dev->state == COMP_STATE_ACTIVE) {
uint32_t samples;
uint32_t source_samples;
int sink_queue_id;

sink_queue_id = IPC4_SINK_QUEUE_ID(buf_get_id(sink_c));
Expand All @@ -518,10 +521,11 @@ static int copier_module_copy(struct processing_module *mod,

comp_get_copy_limits(src_c, sink_c, &processed_data);

samples = processed_data.frames *
audio_stream_get_channels(output_buffers[i].data);
source_samples = processed_data.frames *
audio_stream_get_channels(input_buffers[0].data);
cd->converter[sink_queue_id](input_buffers[0].data, 0,
output_buffers[i].data, 0, samples);
output_buffers[i].data, 0,
source_samples, DUMMY_CHMAP);

output_buffers[i].size = processed_data.sink_bytes;
cd->output_total_data_processed += processed_data.sink_bytes;
Expand Down Expand Up @@ -657,6 +661,7 @@ static int copier_set_sink_fmt(struct comp_dev *dev, const void *data,
const struct ipc4_copier_config_set_sink_format *sink_fmt = data;
struct processing_module *mod = comp_mod(dev);
struct copier_data *cd = module_get_private_data(mod);
uint32_t chmap;

if (max_data_size < sizeof(*sink_fmt)) {
comp_err(dev, "error: max_data_size %d should be bigger than %d", max_data_size,
Expand All @@ -682,9 +687,15 @@ static int copier_set_sink_fmt(struct comp_dev *dev, const void *data,
}

cd->out_fmt[sink_fmt->sink_id] = sink_fmt->sink_fmt;

if (cd->endpoint_num > 0 && dev->ipc_config.type == SOF_COMP_DAI)
chmap = cd->dd[0]->chmap;
else
chmap = DUMMY_CHMAP;

cd->converter[sink_fmt->sink_id] = get_converter_func(&sink_fmt->source_fmt,
&sink_fmt->sink_fmt, ipc4_gtw_none,
ipc4_bidirection);
ipc4_bidirection, chmap);

return 0;
}
Expand Down Expand Up @@ -724,6 +735,82 @@ static int set_attenuation(struct comp_dev *dev, uint32_t data_offset, const cha
return 0;
}

static int set_chmap(struct comp_dev *dev, const void *data, size_t data_size)
{
const struct ipc4_copier_config_channel_map *chmap_cfg = data;
struct processing_module *mod = comp_mod(dev);
struct copier_data *cd = module_get_private_data(mod);
enum ipc4_direction_type dir;
struct ipc4_audio_format in_fmt = cd->config.base.audio_fmt;
struct ipc4_audio_format out_fmt = cd->config.out_fmt;
pcm_converter_func process;
pcm_converter_func converters[IPC4_COPIER_MODULE_OUTPUT_PINS_COUNT];
int i;
uint32_t irq_flags;

if (data_size < sizeof(*chmap_cfg)) {
comp_err(dev, "Wrong payload size: %d", data_size);
return -EINVAL;
}

if (cd->endpoint_num == 0 || dev->ipc_config.type != SOF_COMP_DAI) {
comp_err(dev, "Only DAI gateway supports changing chmap");
return -EINVAL;
}

comp_info(dev, "New chmap requested: %x", chmap_cfg->channel_map);

if (!cd->dd[0]->dma_buffer) {
/* DMA buffer not yet created. Remember the chmap, it will be used
* later in .params() handler.
*
* The assignment should be atomic as LL thread can preempt this IPC thread.
*/
cd->dd[0]->chmap = chmap_cfg->channel_map;
return 0;
}

copier_dai_adjust_params(cd, &in_fmt, &out_fmt);

dir = (cd->direction == SOF_IPC_STREAM_PLAYBACK) ?
ipc4_playback : ipc4_capture;

process = get_converter_func(&in_fmt, &out_fmt, cd->gtw_type, dir, chmap_cfg->channel_map);

if (!process) {
comp_err(dev, "No gtw converter func found!");
return -EINVAL;
}

/* Channel map is same for all sinks. However, as sinks allowed to have different
* sample formats, get new convert/remap function for each sink.
*/
for (i = 0; i < IPC4_COPIER_MODULE_OUTPUT_PINS_COUNT; i++) {
if (cd->converter[i]) {
converters[i] = get_converter_func(&in_fmt, &cd->out_fmt[i],
ipc4_gtw_none, ipc4_bidirection,
chmap_cfg->channel_map);
/* Do not report an error if converter not found as sinks could be
* bound/unbound on a fly and out_fmt[i] may contain obsolete data.
*/
} else {
converters[i] = NULL;
}
}

/* Atomically update chmap, process and converters */
irq_local_disable(irq_flags);

cd->dd[0]->chmap = chmap_cfg->channel_map;
cd->dd[0]->process = process;
for (i = 0; i < IPC4_COPIER_MODULE_OUTPUT_PINS_COUNT; i++)
cd->converter[i] = converters[i];

irq_local_enable(irq_flags);

return 0;
}

static int copier_set_configuration(struct processing_module *mod,
uint32_t config_id,
enum module_cfg_fragment_position pos,
Expand All @@ -741,6 +828,8 @@ static int copier_set_configuration(struct processing_module *mod,
return copier_set_sink_fmt(dev, fragment, fragment_size);
case IPC4_COPIER_MODULE_CFG_ATTENUATION:
return set_attenuation(dev, fragment_size, (const char *)fragment);
case IPC4_COPIER_MODULE_CFG_PARAM_CHANNEL_MAP:
return set_chmap(dev, fragment, fragment_size);
default:
return -EINVAL;
}
Expand Down
18 changes: 16 additions & 2 deletions src/audio/copier/copier.h
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,12 @@ enum ipc4_copier_module_config_params {
* uint32_t. Config is only allowed when output pin is set up for 32bit and
* source is connected to Gateway
*/
IPC4_COPIER_MODULE_CFG_ATTENUATION = 6
IPC4_COPIER_MODULE_CFG_ATTENUATION = 6,
/* Use LARGE_CONFIG_SET to setup new channel map, which allows to map channels
* from gateway buffer to copier with any order.
* Same mapping will be applied for all copier sinks.
*/
IPC4_COPIER_MODULE_CFG_PARAM_CHANNEL_MAP = 7
};

struct ipc4_copier_config_timestamp_init_data {
Expand All @@ -201,6 +206,13 @@ struct ipc4_copier_config_set_sink_format {
struct ipc4_audio_format sink_fmt;
} __attribute__((packed, aligned(4)));

struct ipc4_copier_config_channel_map {
/* Each half-byte of the channel map is an index of the DMA stream channel that
* should be copied to the position determined by this half-byte index.
*/
uint32_t channel_map;
} __attribute__((packed, aligned(4)));

#define IPC4_COPIER_DATA_SEGMENT_DISABLE (0 << 0)
#define IPC4_COPIER_DATA_SEGMENT_ENABLE (1 << 0)
#define IPC4_COPIER_DATA_SEGMENT_RESTART (1 << 1)
Expand Down Expand Up @@ -232,6 +244,7 @@ struct copier_data {
*/
struct ipc4_copier_module_cfg config;
void *gtw_cfg;
enum ipc4_gateway_type gtw_type;
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;
Expand Down Expand Up @@ -267,7 +280,8 @@ int apply_attenuation(struct comp_dev *dev, struct copier_data *cd,
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 ipc4_direction_type dir,
uint32_t chmap);

struct comp_ipc_config;
int create_endpoint_buffer(struct comp_dev *dev,
Expand Down
Loading
Loading