Skip to content

Commit 08bc379

Browse files
ipc4: copier: Extend get_convertion_func() to support remapping
Adds channel map parameter to get_convertion_func() to support remapping conversion functions. Signed-off-by: Serhiy Katsyuba <serhiy.katsyuba@intel.com>
1 parent 1b08d3e commit 08bc379

6 files changed

Lines changed: 110 additions & 38 deletions

File tree

src/audio/copier/copier.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,8 @@ static int copier_init(struct processing_module *mod)
164164

165165
dev->direction_set = true;
166166
} else {
167+
cd->gtw_type = ipc4_gtw_none;
168+
167169
/* set max sink count for module copier */
168170
mod->max_sinks = IPC4_COPIER_MODULE_OUTPUT_PINS_COUNT;
169171
}
@@ -244,7 +246,7 @@ static int copier_prepare(struct processing_module *mod,
244246
*/
245247
cd->converter[0] = get_converter_func(&cd->config.base.audio_fmt,
246248
&cd->config.out_fmt, ipc4_gtw_none,
247-
ipc4_bidirection);
249+
ipc4_bidirection, DUMMY_CHMAP);
248250
if (!cd->converter[0]) {
249251
comp_err(dev, "can't support for in format %d, out format %d",
250252
cd->config.base.audio_fmt.depth, cd->config.out_fmt.depth);
@@ -691,7 +693,7 @@ static int copier_set_sink_fmt(struct comp_dev *dev, const void *data,
691693
cd->out_fmt[sink_fmt->sink_id] = sink_fmt->sink_fmt;
692694
cd->converter[sink_fmt->sink_id] = get_converter_func(&sink_fmt->source_fmt,
693695
&sink_fmt->sink_fmt, ipc4_gtw_none,
694-
ipc4_bidirection);
696+
ipc4_bidirection, DUMMY_CHMAP);
695697

696698
/* update corresponding sink format */
697699
list_for_item(sink_list, &dev->bsink_list) {

src/audio/copier/copier.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,7 @@ struct copier_data {
232232
*/
233233
struct ipc4_copier_module_cfg config;
234234
void *gtw_cfg;
235+
enum ipc4_gateway_type gtw_type;
235236
struct comp_dev *endpoint[IPC4_COPIER_MODULE_OUTPUT_PINS_COUNT];
236237
struct comp_buffer *endpoint_buffer[IPC4_COPIER_MODULE_OUTPUT_PINS_COUNT];
237238
uint32_t endpoint_num;
@@ -267,7 +268,8 @@ int apply_attenuation(struct comp_dev *dev, struct copier_data *cd,
267268
pcm_converter_func get_converter_func(const struct ipc4_audio_format *in_fmt,
268269
const struct ipc4_audio_format *out_fmt,
269270
enum ipc4_gateway_type type,
270-
enum ipc4_direction_type dir);
271+
enum ipc4_direction_type dir,
272+
uint32_t chmap);
271273

272274
struct comp_ipc_config;
273275
int create_endpoint_buffer(struct comp_dev *dev,

src/audio/copier/copier_dai.c

Lines changed: 72 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,6 @@ int copier_dai_create(struct comp_dev *dev, struct copier_data *cd,
234234
struct comp_ipc_config *config = &dev->ipc_config;
235235
int dai_index[IPC4_ALH_MAX_NUMBER_OF_GTW];
236236
union ipc4_connector_node_id node_id;
237-
enum ipc4_gateway_type type;
238237
struct ipc_config_dai dai;
239238
int dai_count;
240239
int i, ret;
@@ -255,13 +254,13 @@ int copier_dai_create(struct comp_dev *dev, struct copier_data *cd,
255254
case ipc4_hda_link_input_class:
256255
dai.type = SOF_DAI_INTEL_HDA;
257256
dai.is_config_blob = true;
258-
type = ipc4_gtw_link;
257+
cd->gtw_type = ipc4_gtw_link;
259258
break;
260259
case ipc4_i2s_link_output_class:
261260
case ipc4_i2s_link_input_class:
262261
dai.type = SOF_DAI_INTEL_SSP;
263262
dai.is_config_blob = true;
264-
type = ipc4_gtw_ssp;
263+
cd->gtw_type = ipc4_gtw_ssp;
265264
ret = ipc4_find_dma_config(&dai, (uint8_t *)cd->gtw_cfg,
266265
copier->gtw_cfg.config_length * 4);
267266
if (ret != 0) {
@@ -275,11 +274,11 @@ int copier_dai_create(struct comp_dev *dev, struct copier_data *cd,
275274
#if ACE_VERSION > ACE_VERSION_1_5
276275
dai.type = SOF_DAI_INTEL_HDA;
277276
dai.is_config_blob = true;
278-
type = ipc4_gtw_link;
277+
cd->gtw_type = ipc4_gtw_link;
279278
#else
280279
dai.type = SOF_DAI_INTEL_ALH;
281280
dai.is_config_blob = true;
282-
type = ipc4_gtw_alh;
281+
cd->gtw_type = ipc4_gtw_alh;
283282
#endif /* ACE_VERSION > ACE_VERSION_1_5 */
284283
ret = copier_alh_assign_dai_index(dev, cd->gtw_cfg, node_id,
285284
&dai, dai_index, &dai_count);
@@ -289,7 +288,7 @@ int copier_dai_create(struct comp_dev *dev, struct copier_data *cd,
289288
case ipc4_dmic_link_input_class:
290289
dai.type = SOF_DAI_INTEL_DMIC;
291290
dai.is_config_blob = true;
292-
type = ipc4_gtw_dmic;
291+
cd->gtw_type = ipc4_gtw_dmic;
293292
ret = ipc4_find_dma_config(&dai, (uint8_t *)cd->gtw_cfg,
294293
copier->gtw_cfg.config_length * 4);
295294
if (ret != 0) {
@@ -304,7 +303,7 @@ int copier_dai_create(struct comp_dev *dev, struct copier_data *cd,
304303

305304
for (i = 0; i < dai_count; i++) {
306305
dai.dai_index = dai_index[i];
307-
ret = copier_dai_init(dev, config, copier, pipeline, &dai, type, i,
306+
ret = copier_dai_init(dev, config, copier, pipeline, &dai, cd->gtw_type, i,
308307
dai_count);
309308
if (ret) {
310309
comp_err(dev, "failed to create dai");
@@ -313,11 +312,11 @@ int copier_dai_create(struct comp_dev *dev, struct copier_data *cd,
313312
}
314313

315314
cd->converter[IPC4_COPIER_GATEWAY_PIN] =
316-
get_converter_func(&copier->base.audio_fmt, &copier->out_fmt, type,
317-
IPC4_DIRECTION(dai.direction));
315+
get_converter_func(&copier->base.audio_fmt, &copier->out_fmt, cd->gtw_type,
316+
IPC4_DIRECTION(dai.direction), DUMMY_CHMAP);
318317
if (!cd->converter[IPC4_COPIER_GATEWAY_PIN]) {
319318
comp_err(dev, "failed to get converter type %d, dir %d",
320-
type, dai.direction);
319+
cd->gtw_type, dai.direction);
321320
return -EINVAL;
322321
}
323322

@@ -450,40 +449,81 @@ static int copy_single_channel_c32(const struct audio_stream *src,
450449
return 0;
451450
}
452451

452+
static void copier_dai_adjust_params(const struct copier_data *cd,
453+
struct ipc4_audio_format *in_fmt,
454+
struct ipc4_audio_format *out_fmt)
455+
{
456+
struct comp_buffer *dma_buf;
457+
int dma_buf_channels;
458+
int dma_buf_container_bits, dma_buf_valid_bits;
459+
460+
/* Call this func only for DAI gateway with already setup DMA buffer */
461+
assert(cd->dd[0] && cd->dd[0]->dma_buffer);
462+
dma_buf = cd->dd[0]->dma_buffer;
463+
464+
/* Unfortunately, configuring the gateway DMA buffer format is somewhat confusing.
465+
* The number of channels can come from hardware parameters (extracted from a blob?)
466+
* and also appears in the copier's input/output format. In case the value returned
467+
* by the hardware looks valid, it should take precedence over the value from the
468+
* copier's input/output format.
469+
*
470+
* The frame format comes from the topology as dev->ipc_config.frame_fmt and also
471+
* comes as the copier's input/output format. The logic is confusing: the format
472+
* from the topology takes priority, except when the copier's format container and
473+
* valid sample size are different. Perhaps this is to support the 16-bit valid
474+
* in the 32-bit container format used by SSP, as such a format cannot be specified
475+
* in the topology?
476+
*/
477+
dma_buf_channels = audio_stream_get_channels(&dma_buf->stream);
478+
dma_buf_container_bits = audio_stream_sample_bytes(&dma_buf->stream) * 8;
479+
dma_buf_valid_bits = get_sample_bitdepth(audio_stream_get_frm_fmt(&dma_buf->stream));
480+
481+
if (cd->direction == SOF_IPC_STREAM_PLAYBACK) {
482+
out_fmt->channels_count = dma_buf_channels;
483+
484+
if (!(dma_buf_container_bits == out_fmt->depth &&
485+
out_fmt->depth != out_fmt->valid_bit_depth)) {
486+
out_fmt->depth = dma_buf_container_bits;
487+
out_fmt->valid_bit_depth = dma_buf_valid_bits;
488+
}
489+
} else {
490+
in_fmt->channels_count = dma_buf_channels;
491+
492+
if (!(dma_buf_container_bits == in_fmt->depth &&
493+
in_fmt->depth != in_fmt->valid_bit_depth)) {
494+
in_fmt->depth = dma_buf_container_bits;
495+
in_fmt->valid_bit_depth = dma_buf_valid_bits;
496+
}
497+
}
498+
}
499+
453500
int copier_dai_params(struct copier_data *cd, struct comp_dev *dev,
454501
struct sof_ipc_stream_params *params, int dai_index)
455502
{
456503
struct sof_ipc_stream_params demuxed_params = *params;
457-
const struct ipc4_audio_format *in_fmt = &cd->config.base.audio_fmt;
458-
const struct ipc4_audio_format *out_fmt = &cd->config.out_fmt;
459-
enum sof_ipc_frame in_bits, in_valid_bits, out_bits, out_valid_bits;
460504
int container_size;
461505
int j, ret;
462506

463507
if (cd->endpoint_num == 1) {
508+
struct ipc4_audio_format in_fmt = cd->config.base.audio_fmt;
509+
struct ipc4_audio_format out_fmt = cd->config.out_fmt;
510+
enum ipc4_direction_type dir;
511+
464512
ret = dai_common_params(cd->dd[0], dev, params);
513+
if (ret < 0)
514+
return ret;
515+
516+
copier_dai_adjust_params(cd, &in_fmt, &out_fmt);
517+
518+
dir = (cd->direction == SOF_IPC_STREAM_PLAYBACK) ?
519+
ipc4_playback : ipc4_capture;
520+
521+
cd->dd[0]->process =
522+
get_converter_func(&in_fmt, &out_fmt, cd->gtw_type, dir, DUMMY_CHMAP);
465523

466-
/*
467-
* dai_zephyr_params assigns the conversion function
468-
* based on the input/output formats but does not take
469-
* the valid bits into account. So change the conversion
470-
* function if the valid bits are different from the
471-
* container size.
472-
*/
473-
audio_stream_fmt_conversion(in_fmt->depth,
474-
in_fmt->valid_bit_depth,
475-
&in_bits, &in_valid_bits,
476-
in_fmt->s_type);
477-
audio_stream_fmt_conversion(out_fmt->depth,
478-
out_fmt->valid_bit_depth,
479-
&out_bits, &out_valid_bits,
480-
out_fmt->s_type);
481-
482-
if (in_bits != in_valid_bits || out_bits != out_valid_bits)
483-
cd->dd[0]->process =
484-
cd->converter[IPC4_COPIER_GATEWAY_PIN];
485524
return ret;
486525
}
526+
487527
/* For ALH multi-gateway case, params->channels is a total multiplexed
488528
* number of channels. Demultiplexed number of channels for each individual
489529
* gateway comes in blob's struct ipc4_alh_multi_gtw_cfg.

src/audio/copier/copier_generic.c

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -262,10 +262,26 @@ static bool use_no_container_convert_function(enum sof_ipc_frame in,
262262
return false;
263263
}
264264

265+
static bool is_remapping_chmap(uint32_t chmap, size_t out_channel_count)
266+
{
267+
size_t i;
268+
269+
assert(out_channel_count <= 8);
270+
271+
for (i = 0; i < out_channel_count; i++) {
272+
if ((chmap & 0xf) != i)
273+
return true;
274+
chmap >>= 4;
275+
}
276+
277+
return false;
278+
}
279+
265280
pcm_converter_func get_converter_func(const struct ipc4_audio_format *in_fmt,
266281
const struct ipc4_audio_format *out_fmt,
267282
enum ipc4_gateway_type type,
268-
enum ipc4_direction_type dir)
283+
enum ipc4_direction_type dir,
284+
uint32_t chmap)
269285
{
270286
enum sof_ipc_frame in, in_valid, out, out_valid;
271287

@@ -314,6 +330,16 @@ pcm_converter_func get_converter_func(const struct ipc4_audio_format *in_fmt,
314330
}
315331
}
316332

333+
if (in_fmt->channels_count != out_fmt->channels_count ||
334+
is_remapping_chmap(chmap, out_fmt->channels_count)) {
335+
if (in_valid == SOF_IPC_FRAME_S16_LE && in == SOF_IPC_FRAME_S32_LE)
336+
in = SOF_IPC_FRAME_S16_4LE;
337+
if (out_valid == SOF_IPC_FRAME_S16_LE && out == SOF_IPC_FRAME_S32_LE)
338+
out = SOF_IPC_FRAME_S16_4LE;
339+
340+
return pcm_get_remap_function(in, out);
341+
}
342+
317343
/* check container & sample size */
318344
if (use_no_container_convert_function(in, in_valid, out, out_valid))
319345
return pcm_get_conversion_function(in, out);

src/audio/copier/copier_host.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,7 @@ int copier_host_create(struct comp_dev *dev, struct copier_data *cd,
136136
enum sof_ipc_frame in_valid_fmt, out_valid_fmt;
137137

138138
config->type = SOF_COMP_HOST;
139+
cd->gtw_type = ipc4_gtw_host;
139140

140141
audio_stream_fmt_conversion(copier_cfg->base.audio_fmt.depth,
141142
copier_cfg->base.audio_fmt.valid_bit_depth,
@@ -195,7 +196,7 @@ int copier_host_create(struct comp_dev *dev, struct copier_data *cd,
195196
cd->converter[IPC4_COPIER_GATEWAY_PIN] =
196197
get_converter_func(&copier_cfg->base.audio_fmt,
197198
&copier_cfg->out_fmt,
198-
ipc4_gtw_host, IPC4_DIRECTION(dir));
199+
ipc4_gtw_host, IPC4_DIRECTION(dir), DUMMY_CHMAP);
199200
if (!cd->converter[IPC4_COPIER_GATEWAY_PIN]) {
200201
comp_err(dev, "failed to get converter for host, dir %d", dir);
201202
ret = -EINVAL;

src/audio/copier/copier_ipcgtw.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,7 @@ int copier_ipcgtw_create(struct comp_dev *dev, struct copier_data *cd,
229229
* IPC gateway should be handled similarly as host gateway.
230230
*/
231231
config->type = SOF_COMP_HOST;
232+
cd->gtw_type = ipc4_gtw_host;
232233

233234
ret = create_endpoint_buffer(dev, cd, copier, false);
234235
if (ret < 0)
@@ -255,7 +256,7 @@ int copier_ipcgtw_create(struct comp_dev *dev, struct copier_data *cd,
255256
cd->converter[IPC4_COPIER_GATEWAY_PIN] =
256257
get_converter_func(&copier->base.audio_fmt,
257258
&copier->out_fmt,
258-
ipc4_gtw_host, IPC4_DIRECTION(cd->direction));
259+
ipc4_gtw_host, IPC4_DIRECTION(cd->direction), DUMMY_CHMAP);
259260
if (!cd->converter[IPC4_COPIER_GATEWAY_PIN]) {
260261
comp_err(dev, "failed to get converter for IPC gateway, dir %d",
261262
cd->direction);

0 commit comments

Comments
 (0)