Skip to content

Commit 4aefb69

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 23904fc commit 4aefb69

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
@@ -666,6 +666,7 @@ static int copier_set_sink_fmt(struct comp_dev *dev, const void *data,
666666
struct copier_data *cd = module_get_private_data(mod);
667667
struct list_item *sink_list;
668668
struct comp_buffer *sink;
669+
uint32_t chmap;
669670

670671
if (max_data_size < sizeof(*sink_fmt)) {
671672
comp_err(dev, "error: max_data_size %d should be bigger than %d", max_data_size,
@@ -691,9 +692,15 @@ static int copier_set_sink_fmt(struct comp_dev *dev, const void *data,
691692
}
692693

693694
cd->out_fmt[sink_fmt->sink_id] = sink_fmt->sink_fmt;
695+
696+
if (cd->endpoint_num > 0 && dev->ipc_config.type == SOF_COMP_DAI)
697+
chmap = cd->dd[0]->chmap;
698+
else
699+
chmap = DUMMY_CHMAP;
700+
694701
cd->converter[sink_fmt->sink_id] = get_converter_func(&sink_fmt->source_fmt,
695702
&sink_fmt->sink_fmt, ipc4_gtw_none,
696-
ipc4_bidirection, DUMMY_CHMAP);
703+
ipc4_bidirection, chmap);
697704

698705
/* update corresponding sink format */
699706
list_for_item(sink_list, &dev->bsink_list) {
@@ -746,6 +753,82 @@ static int set_attenuation(struct comp_dev *dev, uint32_t data_offset, const cha
746753
return 0;
747754
}
748755

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

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)