Skip to content

Commit cecd8a6

Browse files
ipc4: copier: Add IPC4 channel map handler
Adds IPC4_COPIER_MODULE_CFG_PARAM_CHANNEL_MAP handler that applies channel map to DAI gateway audio conversion function. Signed-off-by: Serhiy Katsyuba <serhiy.katsyuba@intel.com>
1 parent 7661c96 commit cecd8a6

File tree

6 files changed

+118
-9
lines changed

6 files changed

+118
-9
lines changed

src/audio/copier/copier.c

Lines changed: 86 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -661,6 +661,7 @@ static int copier_set_sink_fmt(struct comp_dev *dev, const void *data,
661661
const struct ipc4_copier_config_set_sink_format *sink_fmt = data;
662662
struct processing_module *mod = comp_mod(dev);
663663
struct copier_data *cd = module_get_private_data(mod);
664+
uint32_t chmap;
664665

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

688689
cd->out_fmt[sink_fmt->sink_id] = sink_fmt->sink_fmt;
690+
691+
if (cd->endpoint_num > 0 && dev->ipc_config.type == SOF_COMP_DAI)
692+
chmap = cd->dd[0]->chmap;
693+
else
694+
chmap = DUMMY_CHMAP;
695+
689696
cd->converter[sink_fmt->sink_id] = get_converter_func(&sink_fmt->source_fmt,
690697
&sink_fmt->sink_fmt, ipc4_gtw_none,
691-
ipc4_bidirection, DUMMY_CHMAP);
698+
ipc4_bidirection, chmap);
692699

693700
return 0;
694701
}
@@ -728,6 +735,82 @@ static int set_attenuation(struct comp_dev *dev, uint32_t data_offset, const cha
728735
return 0;
729736
}
730737

738+
static int set_chmap(struct comp_dev *dev, const void *data, size_t data_size)
739+
{
740+
const struct ipc4_copier_config_channel_map *chmap_cfg = data;
741+
struct processing_module *mod = comp_mod(dev);
742+
struct copier_data *cd = module_get_private_data(mod);
743+
enum ipc4_direction_type dir;
744+
struct ipc4_audio_format in_fmt = cd->config.base.audio_fmt;
745+
struct ipc4_audio_format out_fmt = cd->config.out_fmt;
746+
pcm_converter_func process;
747+
pcm_converter_func converters[IPC4_COPIER_MODULE_OUTPUT_PINS_COUNT];
748+
int i;
749+
uint32_t irq_flags;
750+
751+
if (data_size < sizeof(*chmap_cfg)) {
752+
comp_err(dev, "Wrong payload size: %d", data_size);
753+
return -EINVAL;
754+
}
755+
756+
if (cd->endpoint_num == 0 || dev->ipc_config.type != SOF_COMP_DAI) {
757+
comp_err(dev, "Only DAI gateway supports changing chmap");
758+
return -EINVAL;
759+
}
760+
761+
comp_info(dev, "New chmap requested: %x", chmap_cfg->channel_map);
762+
763+
if (!cd->dd[0]->dma_buffer) {
764+
/* DMA buffer not yet created. Remember the chmap, it will be used
765+
* later in .params() handler.
766+
*
767+
* The assignment should be atomic as LL thread can preempt this IPC thread.
768+
*/
769+
cd->dd[0]->chmap = chmap_cfg->channel_map;
770+
return 0;
771+
}
772+
773+
copier_dai_adjust_params(cd, &in_fmt, &out_fmt);
774+
775+
dir = (cd->direction == SOF_IPC_STREAM_PLAYBACK) ?
776+
ipc4_playback : ipc4_capture;
777+
778+
process = get_converter_func(&in_fmt, &out_fmt, cd->gtw_type, dir, chmap_cfg->channel_map);
779+
780+
if (!process) {
781+
comp_err(dev, "No gtw converter func found!");
782+
return -EINVAL;
783+
}
784+
785+
/* Channel map is same for all sinks. However, as sinks allowed to have different
786+
* sample formats, get new convert/remap function for each sink.
787+
*/
788+
for (i = 0; i < IPC4_COPIER_MODULE_OUTPUT_PINS_COUNT; i++) {
789+
if (cd->converter[i]) {
790+
converters[i] = get_converter_func(&in_fmt, &cd->out_fmt[i],
791+
ipc4_gtw_none, ipc4_bidirection,
792+
chmap_cfg->channel_map);
793+
/* Do not report an error if converter not found as sinks could be
794+
* bound/unbound on a fly and out_fmt[i] may contain obsolete data.
795+
*/
796+
} else {
797+
converters[i] = NULL;
798+
}
799+
}
800+
801+
/* Atomically update chmap, process and converters */
802+
irq_local_disable(irq_flags);
803+
804+
cd->dd[0]->chmap = chmap_cfg->channel_map;
805+
cd->dd[0]->process = process;
806+
for (i = 0; i < IPC4_COPIER_MODULE_OUTPUT_PINS_COUNT; i++)
807+
cd->converter[i] = converters[i];
808+
809+
irq_local_enable(irq_flags);
810+
811+
return 0;
812+
}
813+
731814
static int copier_set_configuration(struct processing_module *mod,
732815
uint32_t config_id,
733816
enum module_cfg_fragment_position pos,
@@ -745,6 +828,8 @@ static int copier_set_configuration(struct processing_module *mod,
745828
return copier_set_sink_fmt(dev, fragment, fragment_size);
746829
case IPC4_COPIER_MODULE_CFG_ATTENUATION:
747830
return set_attenuation(dev, fragment_size, (const char *)fragment);
831+
case IPC4_COPIER_MODULE_CFG_PARAM_CHANNEL_MAP:
832+
return set_chmap(dev, fragment, fragment_size);
748833
default:
749834
return -EINVAL;
750835
}

src/audio/copier/copier.h

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,12 @@ enum ipc4_copier_module_config_params {
180180
* uint32_t. Config is only allowed when output pin is set up for 32bit and
181181
* source is connected to Gateway
182182
*/
183-
IPC4_COPIER_MODULE_CFG_ATTENUATION = 6
183+
IPC4_COPIER_MODULE_CFG_ATTENUATION = 6,
184+
/* Use LARGE_CONFIG_SET to setup new channel map, which allows to map channels
185+
* from gateway buffer to copier with any order.
186+
* Same mapping will be applied for all copier sinks.
187+
*/
188+
IPC4_COPIER_MODULE_CFG_PARAM_CHANNEL_MAP = 7
184189
};
185190

186191
struct ipc4_copier_config_timestamp_init_data {
@@ -201,6 +206,13 @@ struct ipc4_copier_config_set_sink_format {
201206
struct ipc4_audio_format sink_fmt;
202207
} __attribute__((packed, aligned(4)));
203208

209+
struct ipc4_copier_config_channel_map {
210+
/* Each half-byte of the channel map is an index of the DMA stream channel that
211+
* should be copied to the position determined by this half-byte index.
212+
*/
213+
uint32_t channel_map;
214+
} __attribute__((packed, aligned(4)));
215+
204216
#define IPC4_COPIER_DATA_SEGMENT_DISABLE (0 << 0)
205217
#define IPC4_COPIER_DATA_SEGMENT_ENABLE (1 << 0)
206218
#define IPC4_COPIER_DATA_SEGMENT_RESTART (1 << 1)

src/audio/copier/copier_dai.c

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,7 @@ static int copier_dai_init(struct comp_dev *dev,
164164
{
165165
struct processing_module *mod = comp_mod(dev);
166166
struct copier_data *cd = module_get_private_data(mod);
167+
uint32_t chmap;
167168
struct dai_data *dd;
168169
int ret;
169170

@@ -178,6 +179,7 @@ static int copier_dai_init(struct comp_dev *dev,
178179
config->frame_fmt = out_frame_fmt;
179180
pipeline->sink_comp = dev;
180181
cd->bsource_buffer = true;
182+
chmap = copier->base.audio_fmt.ch_map;
181183
} else {
182184
enum sof_ipc_frame in_frame_fmt, in_valid_fmt;
183185

@@ -187,6 +189,7 @@ static int copier_dai_init(struct comp_dev *dev,
187189
copier->base.audio_fmt.s_type);
188190
config->frame_fmt = in_frame_fmt;
189191
pipeline->source_comp = dev;
192+
chmap = copier->out_fmt.ch_map;
190193
}
191194

192195
/* save the channel map and count for ALH multi-gateway */
@@ -205,6 +208,8 @@ static int copier_dai_init(struct comp_dev *dev,
205208
if (ret < 0)
206209
goto free_dd;
207210

211+
dd->chmap = chmap;
212+
208213
pipeline->sched_id = config->id;
209214

210215
cd->dd[index] = dd;
@@ -449,9 +454,9 @@ static int copy_single_channel_c32(const struct audio_stream *src,
449454
return 0;
450455
}
451456

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)
457+
void copier_dai_adjust_params(const struct copier_data *cd,
458+
struct ipc4_audio_format *in_fmt,
459+
struct ipc4_audio_format *out_fmt)
455460
{
456461
struct comp_buffer *dma_buf;
457462
int dma_buf_channels;
@@ -519,7 +524,7 @@ int copier_dai_params(struct copier_data *cd, struct comp_dev *dev,
519524
ipc4_playback : ipc4_capture;
520525

521526
cd->dd[0]->process =
522-
get_converter_func(&in_fmt, &out_fmt, cd->gtw_type, dir, DUMMY_CHMAP);
527+
get_converter_func(&in_fmt, &out_fmt, cd->gtw_type, dir, cd->dd[0]->chmap);
523528

524529
return ret;
525530
}

src/audio/copier/dai_copier.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,10 @@ void copier_dai_free(struct copier_data *cd);
8383

8484
int copier_dai_prepare(struct comp_dev *dev, struct copier_data *cd);
8585

86+
void copier_dai_adjust_params(const struct copier_data *cd,
87+
struct ipc4_audio_format *in_fmt,
88+
struct ipc4_audio_format *out_fmt);
89+
8690
int copier_dai_params(struct copier_data *cd, struct comp_dev *dev,
8791
struct sof_ipc_stream_params *params, int dai_index);
8892

src/audio/dai-zephyr.c

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -269,15 +269,15 @@ dai_dma_cb(struct dai_data *dd, struct comp_dev *dev, uint32_t bytes,
269269

270270
if (dev->direction == SOF_IPC_STREAM_PLAYBACK) {
271271
ret = dma_buffer_copy_to(dd->local_buffer, dd->dma_buffer,
272-
dd->process, bytes, DUMMY_CHMAP);
272+
dd->process, bytes, dd->chmap);
273273
} else {
274274
audio_stream_invalidate(&dd->dma_buffer->stream, bytes);
275275
/*
276276
* The PCM converter functions used during DMA buffer copy can never fail,
277277
* so no need to check the return value of dma_buffer_copy_from_no_consume().
278278
*/
279279
ret = dma_buffer_copy_from_no_consume(dd->dma_buffer, dd->local_buffer,
280-
dd->process, bytes, DUMMY_CHMAP);
280+
dd->process, bytes, dd->chmap);
281281
#if CONFIG_IPC_MAJOR_4
282282
struct list_item *sink_list;
283283
/* Skip in case of endpoint DAI devices created by the copier */
@@ -318,7 +318,7 @@ dai_dma_cb(struct dai_data *dd, struct comp_dev *dev, uint32_t bytes,
318318
sink->hw_params_configured)
319319
ret = dma_buffer_copy_from_no_consume(dd->dma_buffer,
320320
sink, converter[j],
321-
bytes, DUMMY_CHMAP);
321+
bytes, dd->chmap);
322322
}
323323
}
324324
#endif
@@ -468,6 +468,8 @@ static struct comp_dev *dai_new(const struct comp_driver *drv,
468468
if (ret < 0)
469469
goto error;
470470

471+
dd->chmap = DUMMY_CHMAP;
472+
471473
dev->state = COMP_STATE_READY;
472474

473475
return dev;

src/include/sof/lib/dai-zephyr.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,7 @@ struct dai_data {
129129
int xrun; /* true if we are doing xrun recovery */
130130

131131
pcm_converter_func process; /* processing function */
132+
uint32_t chmap;
132133

133134
channel_copy_func channel_copy; /* channel copy func used by multi-endpoint
134135
* gateway to mux/demux stream from/to multiple

0 commit comments

Comments
 (0)