Skip to content

Commit ce1fdf2

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 655a3d7 commit ce1fdf2

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
@@ -668,6 +668,7 @@ static int copier_set_sink_fmt(struct comp_dev *dev, const void *data,
668668
struct copier_data *cd = module_get_private_data(mod);
669669
struct list_item *sink_list;
670670
struct comp_buffer *sink;
671+
uint32_t chmap;
671672

672673
if (max_data_size < sizeof(*sink_fmt)) {
673674
comp_err(dev, "error: max_data_size %d should be bigger than %d", max_data_size,
@@ -693,9 +694,15 @@ static int copier_set_sink_fmt(struct comp_dev *dev, const void *data,
693694
}
694695

695696
cd->out_fmt[sink_fmt->sink_id] = sink_fmt->sink_fmt;
697+
698+
if (cd->endpoint_num > 0 && dev->ipc_config.type == SOF_COMP_DAI)
699+
chmap = cd->dd[0]->chmap;
700+
else
701+
chmap = DUMMY_CHMAP;
702+
696703
cd->converter[sink_fmt->sink_id] = get_converter_func(&sink_fmt->source_fmt,
697704
&sink_fmt->sink_fmt, ipc4_gtw_none,
698-
ipc4_bidirection, DUMMY_CHMAP);
705+
ipc4_bidirection, chmap);
699706

700707
/* update corresponding sink format */
701708
list_for_item(sink_list, &dev->bsink_list) {
@@ -748,6 +755,82 @@ static int set_attenuation(struct comp_dev *dev, uint32_t data_offset, const cha
748755
return 0;
749756
}
750757

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

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
@@ -271,15 +271,15 @@ dai_dma_cb(struct dai_data *dd, struct comp_dev *dev, uint32_t bytes,
271271

272272
if (dev->direction == SOF_IPC_STREAM_PLAYBACK) {
273273
ret = dma_buffer_copy_to(dd->local_buffer, dd->dma_buffer,
274-
dd->process, bytes, DUMMY_CHMAP);
274+
dd->process, bytes, dd->chmap);
275275
} else {
276276
audio_stream_invalidate(&dd->dma_buffer->stream, bytes);
277277
/*
278278
* The PCM converter functions used during DMA buffer copy can never fail,
279279
* so no need to check the return value of dma_buffer_copy_from_no_consume().
280280
*/
281281
ret = dma_buffer_copy_from_no_consume(dd->dma_buffer, dd->local_buffer,
282-
dd->process, bytes, DUMMY_CHMAP);
282+
dd->process, bytes, dd->chmap);
283283
#if CONFIG_IPC_MAJOR_4
284284
struct list_item *sink_list;
285285
/* Skip in case of endpoint DAI devices created by the copier */
@@ -320,7 +320,7 @@ dai_dma_cb(struct dai_data *dd, struct comp_dev *dev, uint32_t bytes,
320320
sink->hw_params_configured)
321321
ret = dma_buffer_copy_from_no_consume(dd->dma_buffer,
322322
sink, converter[j],
323-
bytes, DUMMY_CHMAP);
323+
bytes, dd->chmap);
324324
}
325325
}
326326
#endif
@@ -470,6 +470,8 @@ static struct comp_dev *dai_new(const struct comp_driver *drv,
470470
if (ret < 0)
471471
goto error;
472472

473+
dd->chmap = DUMMY_CHMAP;
474+
473475
dev->state = COMP_STATE_READY;
474476

475477
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)