diff options
-rw-r--r-- | sound/soc/intel/avs/messages.h | 29 | ||||
-rw-r--r-- | sound/soc/intel/avs/path.c | 51 |
2 files changed, 76 insertions, 4 deletions
diff --git a/sound/soc/intel/avs/messages.h b/sound/soc/intel/avs/messages.h index 2f243802ccc2..afdf2a458c52 100644 --- a/sound/soc/intel/avs/messages.h +++ b/sound/soc/intel/avs/messages.h @@ -102,6 +102,8 @@ struct avs_tlv { } __packed; static_assert(sizeof(struct avs_tlv) == 8); +#define avs_tlv_size(tlv) struct_size(tlv, value, (tlv)->length / 4) + enum avs_module_msg_type { AVS_MOD_INIT_INSTANCE = 0, AVS_MOD_LARGE_CONFIG_GET = 3, @@ -786,6 +788,33 @@ union avs_gtw_attributes { } __packed; static_assert(sizeof(union avs_gtw_attributes) == 4); +#define AVS_GTW_DMA_CONFIG_ID 0x1000 +#define AVS_DMA_METHOD_HDA 1 + +struct avs_dma_device_stream_channel_map { + u32 device_address; + u32 channel_map; +} __packed; +static_assert(sizeof(struct avs_dma_device_stream_channel_map) == 8); + +struct avs_dma_stream_channel_map { + u32 device_count; + struct avs_dma_device_stream_channel_map map[16]; +} __packed; +static_assert(sizeof(struct avs_dma_stream_channel_map) == 132); + +struct avs_dma_cfg { + u8 dma_method; + u8 pre_allocated; + u16 rsvd; + u32 dma_channel_id; + u32 stream_id; + struct avs_dma_stream_channel_map map; + u32 config_size; + u8 config[] __counted_by(config_size); +} __packed; +static_assert(sizeof(struct avs_dma_cfg) == 148); + struct avs_copier_gtw_cfg { union avs_connector_node_id node_id; u32 dma_buffer_size; diff --git a/sound/soc/intel/avs/path.c b/sound/soc/intel/avs/path.c index ef0c1d125d66..7800f62c8a1c 100644 --- a/sound/soc/intel/avs/path.c +++ b/sound/soc/intel/avs/path.c @@ -210,8 +210,51 @@ avs_nhlt_config_or_default(struct avs_dev *adev, struct avs_tplg_module *t) return &fmtcfg->config; } +static int avs_append_dma_cfg(struct avs_dev *adev, struct avs_copier_gtw_cfg *gtw, + struct avs_tplg_module *t, u32 dma_id, size_t *cfg_size) +{ + u32 dma_type = t->cfg_ext->copier.dma_type; + struct avs_dma_cfg *dma; + struct avs_tlv *tlv; + size_t tlv_size; + + if (!avs_platattr_test(adev, ALTHDA)) + return 0; + + switch (dma_type) { + case AVS_DMA_HDA_HOST_OUTPUT: + case AVS_DMA_HDA_HOST_INPUT: + case AVS_DMA_HDA_LINK_OUTPUT: + case AVS_DMA_HDA_LINK_INPUT: + return 0; + default: + break; + } + + tlv_size = sizeof(*tlv) + sizeof(*dma); + if (*cfg_size + tlv_size > AVS_MAILBOX_SIZE) + return -E2BIG; + + /* DMA config is a TLV tailing the existing payload. */ + tlv = (struct avs_tlv *)>w->config.blob[gtw->config_length]; + tlv->type = AVS_GTW_DMA_CONFIG_ID; + tlv->length = sizeof(*dma); + + dma = (struct avs_dma_cfg *)tlv->value; + memset(dma, 0, sizeof(*dma)); + dma->dma_method = AVS_DMA_METHOD_HDA; + dma->pre_allocated = true; + dma->dma_channel_id = dma_id; + dma->stream_id = dma_id + 1; + + gtw->config_length += tlv_size / sizeof(u32); + *cfg_size += tlv_size; + + return 0; +} + static int avs_fill_gtw_config(struct avs_dev *adev, struct avs_copier_gtw_cfg *gtw, - struct avs_tplg_module *t, size_t *cfg_size) + struct avs_tplg_module *t, u32 dma_id, size_t *cfg_size) { struct acpi_nhlt_config *blob; size_t gtw_size; @@ -228,7 +271,7 @@ static int avs_fill_gtw_config(struct avs_dev *adev, struct avs_copier_gtw_cfg * memcpy(gtw->config.blob, blob->capabilities, blob->capabilities_size); *cfg_size += gtw_size; - return 0; + return avs_append_dma_cfg(adev, gtw, t, dma_id, cfg_size); } static int avs_copier_create(struct avs_dev *adev, struct avs_path_module *mod) @@ -245,7 +288,7 @@ static int avs_copier_create(struct avs_dev *adev, struct avs_path_module *mod) dma_id = mod->owner->owner->dma_id; cfg_size = offsetof(struct avs_copier_cfg, gtw_cfg.config); - ret = avs_fill_gtw_config(adev, &cfg->gtw_cfg, t, &cfg_size); + ret = avs_fill_gtw_config(adev, &cfg->gtw_cfg, t, dma_id, &cfg_size); if (ret) return ret; @@ -279,7 +322,7 @@ static int avs_whm_create(struct avs_dev *adev, struct avs_path_module *mod) dma_id = mod->owner->owner->dma_id; cfg_size = offsetof(struct avs_whm_cfg, gtw_cfg.config); - ret = avs_fill_gtw_config(adev, &cfg->gtw_cfg, t, &cfg_size); + ret = avs_fill_gtw_config(adev, &cfg->gtw_cfg, t, dma_id, &cfg_size); if (ret) return ret; |