@@ -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+
453500int 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.
0 commit comments