Skip to content

Commit daffe2e

Browse files
tlissowsserhiy-katsyuba-intel
authored andcommitted
dai: add support for Intel UAOL DAI
This adds support for Intel USB Audio Offload Link (UAOL) DAI. Signed-off-by: Tomasz Lissowski <tomasz.lissowski@intel.com> Signed-off-by: Serhiy Katsyuba <serhiy.katsyuba@intel.com>
1 parent d818c9f commit daffe2e

8 files changed

Lines changed: 155 additions & 3 deletions

File tree

src/audio/base_fw_intel.c

Lines changed: 91 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@
2323

2424
#include <sof/lib/memory.h>
2525

26+
#if CONFIG_UAOL_INTEL_ADSP
27+
#include <zephyr/drivers/uaol.h>
28+
#endif
29+
2630
#include <ipc4/base_fw.h>
2731
#include <ipc4/alh.h>
2832
#include <rimage/sof/user/manifest.h>
@@ -37,6 +41,20 @@ struct ipc4_modules_info {
3741
struct sof_man_module modules[0];
3842
} __packed __aligned(4);
3943

44+
struct ipc4_uaol_link_capabilities {
45+
uint32_t input_streams_supported : 4;
46+
uint32_t output_streams_supported : 4;
47+
uint32_t bidirectional_streams_supported : 5;
48+
uint32_t rsvd : 19;
49+
uint32_t max_tx_fifo_size;
50+
uint32_t max_rx_fifo_size;
51+
} __packed __aligned(4);
52+
53+
struct ipc4_uaol_capabilities {
54+
uint32_t link_count;
55+
struct ipc4_uaol_link_capabilities link_caps[];
56+
} __packed __aligned(4);
57+
4058
/*
4159
* TODO: default to value of ACE1.x platforms. This is defined
4260
* in multiple places in Zephyr, mm_drv_intel_adsp.h and
@@ -67,7 +85,7 @@ __cold int basefw_vendor_fw_config(uint32_t *data_offset, char *data)
6785
tlv_value_uint32_set(tuple, IPC4_SLOW_CLOCK_FREQ_HZ_FW_CFG, IPC4_ALH_CAVS_1_8);
6886

6987
tuple = tlv_next(tuple);
70-
tlv_value_uint32_set(tuple, IPC4_UAOL_SUPPORT, 0);
88+
tlv_value_uint32_set(tuple, IPC4_UAOL_SUPPORT, IS_ENABLED(CONFIG_UAOL_INTEL_ADSP));
7189

7290
tuple = tlv_next(tuple);
7391
tlv_value_uint32_set(tuple, IPC4_ALH_SUPPORT_LEVEL_FW_CFG, IPC4_ALH_CAVS_1_8);
@@ -78,6 +96,57 @@ __cold int basefw_vendor_fw_config(uint32_t *data_offset, char *data)
7896
return 0;
7997
}
8098

99+
#if CONFIG_UAOL_INTEL_ADSP
100+
101+
#define UAOL_DEV(node) DEVICE_DT_GET(node),
102+
static const struct device *uaol_devs[] = {
103+
DT_FOREACH_STATUS_OKAY(intel_adsp_uaol, UAOL_DEV)
104+
};
105+
106+
static void tlv_value_set_uaol_caps(struct sof_tlv *tuple, uint32_t type)
107+
{
108+
const unsigned int dev_count = ARRAY_SIZE(uaol_devs);
109+
struct uaol_capabilities dev_cap;
110+
struct ipc4_uaol_capabilities *caps = (struct ipc4_uaol_capabilities *)tuple->value;
111+
size_t caps_size = offsetof(struct ipc4_uaol_capabilities, link_caps[dev_count]);
112+
unsigned int i;
113+
int ret;
114+
115+
memset(caps, 0, caps_size);
116+
117+
caps->link_count = dev_count;
118+
for (i = 0; i < dev_count; i++) {
119+
ret = uaol_get_capabilities(uaol_devs[i], &dev_cap);
120+
if (ret)
121+
continue;
122+
123+
caps->link_caps[i].input_streams_supported = dev_cap.input_streams;
124+
caps->link_caps[i].output_streams_supported = dev_cap.output_streams;
125+
caps->link_caps[i].bidirectional_streams_supported = dev_cap.bidirectional_streams;
126+
caps->link_caps[i].max_tx_fifo_size = dev_cap.max_tx_fifo_size;
127+
caps->link_caps[i].max_rx_fifo_size = dev_cap.max_rx_fifo_size;
128+
}
129+
130+
tlv_value_set(tuple, type, caps_size, caps);
131+
}
132+
133+
static int uaol_stream_id_to_hda_link_stream_id(int uaol_stream_id)
134+
{
135+
size_t dev_count = ARRAY_SIZE(uaol_devs);
136+
size_t i;
137+
138+
for (i = 0; i < dev_count; i++) {
139+
int hda_link_stream_id = uaol_get_mapped_hda_link_stream_id(uaol_devs[i],
140+
uaol_stream_id);
141+
if (hda_link_stream_id >= 0)
142+
return hda_link_stream_id;
143+
}
144+
145+
return -1;
146+
}
147+
148+
#endif
149+
81150
__cold int basefw_vendor_hw_config(uint32_t *data_offset, char *data)
82151
{
83152
struct sof_tlv *tuple = (struct sof_tlv *)data;
@@ -120,6 +189,11 @@ __cold int basefw_vendor_hw_config(uint32_t *data_offset, char *data)
120189
tlv_value_set(tuple, IPC4_INTEL_MIC_PRIVACY_CAPS_HW_CFG, sizeof(priv_caps), &priv_caps);
121190
#endif
122191

192+
#if CONFIG_UAOL_INTEL_ADSP
193+
tuple = tlv_next(tuple);
194+
tlv_value_set_uaol_caps(tuple, IPC4_UAOL_CAPS_HW_CFG);
195+
#endif
196+
123197
tuple = tlv_next(tuple);
124198
*data_offset = (int)((char *)tuple - data);
125199

@@ -421,6 +495,7 @@ __cold int basefw_vendor_set_large_config(struct comp_dev *dev, uint32_t param_i
421495
__cold int basefw_vendor_dma_control(uint32_t node_id, const char *config_data, size_t data_size)
422496
{
423497
union ipc4_connector_node_id node = (union ipc4_connector_node_id)node_id;
498+
int dai_index = node.f.v_index;
424499
int ret, result;
425500
enum sof_ipc_dai_type type;
426501

@@ -444,11 +519,25 @@ __cold int basefw_vendor_dma_control(uint32_t node_id, const char *config_data,
444519
case ipc4_i2s_link_input_class:
445520
type = SOF_DAI_INTEL_SSP;
446521
break;
522+
523+
#if CONFIG_UAOL_INTEL_ADSP
524+
case ipc4_alh_uaol_stream_link_output_class:
525+
case ipc4_alh_uaol_stream_link_input_class:
526+
type = SOF_DAI_INTEL_UAOL;
527+
dai_index = uaol_stream_id_to_hda_link_stream_id(node.f.v_index);
528+
if (dai_index < 0) {
529+
tr_err(&basefw_comp_tr,
530+
"HDA link stream not found! UAOL node ID: 0x%x", node_id);
531+
return IPC4_INVALID_RESOURCE_ID;
532+
}
533+
break;
534+
#endif
535+
447536
default:
448537
return IPC4_INVALID_RESOURCE_ID;
449538
}
450539

451-
const struct device *dev = dai_get_device(type, node.f.v_index);
540+
const struct device *dev = dai_get_device(type, dai_index);
452541

453542
if (!dev) {
454543
tr_err(&basefw_comp_tr,

src/audio/copier/copier.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,8 @@ __cold static int copier_init(struct processing_module *mod)
191191
case ipc4_i2s_link_input_class:
192192
case ipc4_alh_link_output_class:
193193
case ipc4_alh_link_input_class:
194+
case ipc4_alh_uaol_stream_link_output_class:
195+
case ipc4_alh_uaol_stream_link_input_class:
194196
ret = copier_dai_create(dev, cd, copier, dev->pipeline);
195197
if (ret < 0) {
196198
comp_err(dev, "unable to create dai");

src/audio/copier/copier_dai.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -321,6 +321,18 @@ __cold int copier_dai_create(struct comp_dev *dev, struct copier_data *cd,
321321
if (ret)
322322
return ret;
323323
break;
324+
case ipc4_alh_uaol_stream_link_output_class:
325+
case ipc4_alh_uaol_stream_link_input_class:
326+
dai.type = SOF_DAI_INTEL_UAOL;
327+
dai.is_config_blob = true;
328+
cd->gtw_type = ipc4_gtw_alh;
329+
ret = ipc4_find_dma_config(&dai, gtw_cfg_data, gtw_cfg_szie);
330+
if (ret != IPC4_SUCCESS) {
331+
comp_err(dev, "No uaol dma_config found in blob!");
332+
return -EINVAL;
333+
}
334+
dai.out_fmt = &copier->out_fmt;
335+
break;
324336
case ipc4_dmic_link_input_class:
325337
dai.type = SOF_DAI_INTEL_DMIC;
326338
dai.is_config_blob = true;

src/audio/dai-zephyr.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,8 @@ __cold int dai_set_config(struct dai *dai, struct ipc_config_dai *common_config,
156156
cfg.format = sof_cfg->format;
157157
cfg.options = sof_cfg->flags;
158158
cfg.rate = common_config->sampling_frequency;
159+
cfg.channels = common_config->out_fmt->channels_count;
160+
cfg.word_size = common_config->out_fmt->valid_bit_depth;
159161

160162
switch (common_config->type) {
161163
case SOF_DAI_INTEL_SSP:
@@ -192,6 +194,11 @@ __cold int dai_set_config(struct dai *dai, struct ipc_config_dai *common_config,
192194
cfg.type = DAI_IMX_MICFIL;
193195
cfg_params = &sof_cfg->micfil;
194196
break;
197+
case SOF_DAI_INTEL_UAOL:
198+
cfg.type = DAI_INTEL_UAOL;
199+
cfg_params = spec_config;
200+
dai_set_link_hda_config(&cfg.link_config, common_config, spec_config);
201+
break;
195202
default:
196203
return -EINVAL;
197204
}

src/include/ipc/dai.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,8 @@ enum sof_ipc_dai_type {
9494
SOF_DAI_AMD_SP_VIRTUAL, /**<Amd SP VIRTUAL */
9595
SOF_DAI_AMD_HS_VIRTUAL, /**<Amd HS VIRTUAL */
9696
SOF_DAI_IMX_MICFIL, /**< i.MX MICFIL */
97-
SOF_DAI_AMD_SW_AUDIO /**<Amd SW AUDIO */
97+
SOF_DAI_AMD_SW_AUDIO, /**<Amd SW AUDIO */
98+
SOF_DAI_INTEL_UAOL, /**< Intel UAOL */
9899
};
99100

100101
/* general purpose DAI configuration */

src/ipc/ipc4/dai.c

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,12 @@ void dai_set_link_hda_config(uint16_t *link_config,
6060
}
6161
link_cfg.part.stream = common_config->host_dma_config[0]->stream_id;
6262
break;
63+
case SOF_DAI_INTEL_UAOL:
64+
link_cfg.full = 0;
65+
link_cfg.part.hchan = out_fmt->channels_count - 1;
66+
link_cfg.part.dir = common_config->direction;
67+
link_cfg.part.stream = common_config->host_dma_config[0]->stream_id;
68+
break;
6369
default:
6470
/* other types of DAIs not need link_config */
6571
return;
@@ -112,6 +118,13 @@ int dai_config_dma_channel(struct dai_data *dd, struct comp_dev *dev, const void
112118
*/
113119
channel = 0;
114120
break;
121+
#if ACE_VERSION > ACE_VERSION_1_5
122+
case SOF_DAI_INTEL_UAOL:
123+
channel = 0;
124+
if (dai->host_dma_config[0]->pre_allocated_by_host)
125+
channel = dai->host_dma_config[0]->dma_channel_id;
126+
break;
127+
#endif
115128
default:
116129
/* other types of DAIs not handled for now */
117130
comp_err(dev, "Unknown dai type %d", dai->type);
@@ -174,6 +187,16 @@ int ipc_dai_data_config(struct dai_data *dd, struct comp_dev *dev)
174187
dev->ipc_config.frame_fmt, dd->stream_id);
175188

176189
break;
190+
case SOF_DAI_INTEL_UAOL:
191+
#ifdef CONFIG_ZEPHYR_NATIVE_DRIVERS
192+
dd->stream_id = dai_get_stream_id(dai_p, dai->direction);
193+
dev->ipc_config.frame_fmt = SOF_IPC_FRAME_S32_LE;
194+
dd->config.burst_elems = dai_get_fifo_depth(dd->dai, dai->direction);
195+
break;
196+
#else
197+
/* only native Zephyr driver supported */
198+
return -EINVAL;
199+
#endif
177200
default:
178201
/* other types of DAIs not handled for now */
179202
comp_warn(dev, "Unknown dai type %d", dai->type);

src/ipc/ipc4/helper.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1283,6 +1283,18 @@ __cold static int ipc4_add_comp_dev(struct comp_dev *dev)
12831283
int ipc4_find_dma_config(struct ipc_config_dai *dai, uint8_t *data_buffer, uint32_t size)
12841284
{
12851285
#if ACE_VERSION > ACE_VERSION_1_5
1286+
if (dai->type == SOF_DAI_INTEL_UAOL) {
1287+
void *value_ptr = NULL;
1288+
uint32_t value_size;
1289+
1290+
tlv_value_get(data_buffer, size, GTW_DMA_CONFIG_ID, &value_ptr, &value_size);
1291+
if (!value_ptr)
1292+
return IPC4_INVALID_REQUEST;
1293+
1294+
dai->host_dma_config[0] = (struct ipc_dma_config *)value_ptr;
1295+
return IPC4_SUCCESS;
1296+
}
1297+
12861298
uint32_t *dma_config_id = GET_IPC_DMA_CONFIG_ID(data_buffer, size);
12871299

12881300
if (*dma_config_id != GTW_DMA_CONFIG_ID)

src/lib/dai.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,9 @@ const struct device *zephyr_dev[] = {
185185
#if CONFIG_DAI_NXP_MICFIL
186186
DT_FOREACH_STATUS_OKAY(nxp_dai_micfil, GET_DEVICE_LIST)
187187
#endif
188+
#if CONFIG_DAI_INTEL_UAOL
189+
DT_FOREACH_STATUS_OKAY(intel_uaol_dai, GET_DEVICE_LIST)
190+
#endif
188191
};
189192

190193
const struct device **dai_get_device_list(size_t *count)
@@ -207,6 +210,8 @@ static int sof_dai_type_to_zephyr(uint32_t type)
207210
return DAI_INTEL_HDA;
208211
case SOF_DAI_INTEL_ALH:
209212
return DAI_INTEL_ALH;
213+
case SOF_DAI_INTEL_UAOL:
214+
return DAI_INTEL_UAOL;
210215
case SOF_DAI_IMX_SAI:
211216
return DAI_IMX_SAI;
212217
case SOF_DAI_IMX_ESAI:
@@ -285,6 +290,7 @@ static void dai_set_device_params(struct dai *d)
285290
#endif
286291
break;
287292
case SOF_DAI_INTEL_HDA:
293+
case SOF_DAI_INTEL_UAOL:
288294
d->dma_dev = SOF_DMA_DEV_HDA;
289295
d->dma_caps = SOF_DMA_CAP_HDA;
290296
break;

0 commit comments

Comments
 (0)