Skip to content

Commit 2613355

Browse files
committed
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>
1 parent 0ba3ac2 commit 2613355

File tree

8 files changed

+129
-2
lines changed

8 files changed

+129
-2
lines changed

src/audio/base_fw_intel.c

Lines changed: 63 additions & 1 deletion
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>
@@ -33,6 +37,20 @@ struct ipc4_modules_info {
3337
struct sof_man_module modules[0];
3438
} __packed __aligned(4);
3539

40+
struct ipc4_uaol_link_capabilities {
41+
uint32_t input_streams_supported : 4;
42+
uint32_t output_streams_supported : 4;
43+
uint32_t bidirectional_streams_supported : 5;
44+
uint32_t rsvd : 19;
45+
uint32_t max_tx_fifo_size;
46+
uint32_t max_rx_fifo_size;
47+
} __packed __aligned(4);
48+
49+
struct ipc4_uaol_capabilities {
50+
uint32_t link_count;
51+
struct ipc4_uaol_link_capabilities link_caps[];
52+
} __packed __aligned(4);
53+
3654
/*
3755
* TODO: default to value of ACE1.x platforms. This is defined
3856
* in multiple places in Zephyr, mm_drv_intel_adsp.h and
@@ -61,7 +79,7 @@ int basefw_vendor_fw_config(uint32_t *data_offset, char *data)
6179
tlv_value_uint32_set(tuple, IPC4_SLOW_CLOCK_FREQ_HZ_FW_CFG, IPC4_ALH_CAVS_1_8);
6280

6381
tuple = tlv_next(tuple);
64-
tlv_value_uint32_set(tuple, IPC4_UAOL_SUPPORT, 0);
82+
tlv_value_uint32_set(tuple, IPC4_UAOL_SUPPORT, 1);
6583

6684
tuple = tlv_next(tuple);
6785
tlv_value_uint32_set(tuple, IPC4_ALH_SUPPORT_LEVEL_FW_CFG, IPC4_ALH_CAVS_1_8);
@@ -72,6 +90,41 @@ int basefw_vendor_fw_config(uint32_t *data_offset, char *data)
7290
return 0;
7391
}
7492

93+
#if CONFIG_UAOL_INTEL_ADSP
94+
95+
#define UAOL_DEV(node) DEVICE_DT_GET(node),
96+
static const struct device *uaol_devs[] = {
97+
DT_FOREACH_STATUS_OKAY(intel_adsp_uaol, UAOL_DEV)
98+
};
99+
100+
static void tlv_value_set_uaol_caps(struct sof_tlv *tuple, uint32_t type)
101+
{
102+
const unsigned int dev_count = ARRAY_SIZE(uaol_devs);
103+
struct uaol_capabilities dev_cap;
104+
struct ipc4_uaol_capabilities *caps = (struct ipc4_uaol_capabilities *)tuple->value;
105+
size_t caps_size = offsetof(struct ipc4_uaol_capabilities, link_caps[dev_count]);
106+
unsigned int i;
107+
int ret;
108+
109+
memset(caps, 0, caps_size);
110+
111+
caps->link_count = dev_count;
112+
for (i = 0; i < dev_count; i++) {
113+
ret = uaol_get_capabilities(uaol_devs[i], &dev_cap);
114+
if (ret)
115+
continue;
116+
117+
caps->link_caps[i].input_streams_supported = dev_cap.input_streams;
118+
caps->link_caps[i].output_streams_supported = dev_cap.output_streams;
119+
caps->link_caps[i].bidirectional_streams_supported = dev_cap.bidirectional_streams;
120+
caps->link_caps[i].max_tx_fifo_size = dev_cap.max_tx_fifo_size;
121+
caps->link_caps[i].max_rx_fifo_size = dev_cap.max_rx_fifo_size;
122+
}
123+
124+
tlv_value_set(tuple, type, caps_size, caps);
125+
}
126+
#endif
127+
75128
int basefw_vendor_hw_config(uint32_t *data_offset, char *data)
76129
{
77130
struct sof_tlv *tuple = (struct sof_tlv *)data;
@@ -100,6 +153,11 @@ int basefw_vendor_hw_config(uint32_t *data_offset, char *data)
100153
tlv_value_uint32_set(tuple, IPC4_I2S_CAPS_HW_CFG, I2S_VER_30_PTL);
101154
#endif
102155

156+
#if CONFIG_UAOL_INTEL_ADSP
157+
tuple = tlv_next(tuple);
158+
tlv_value_set_uaol_caps(tuple, IPC4_UAOL_CAPS_HW_CFG);
159+
#endif
160+
103161
tuple = tlv_next(tuple);
104162
*data_offset = (int)((char *)tuple - data);
105163

@@ -376,6 +434,10 @@ int basefw_vendor_dma_control(uint32_t node_id, const char *config_data, size_t
376434
case ipc4_i2s_link_input_class:
377435
type = DAI_INTEL_SSP;
378436
break;
437+
case ipc4_alh_uaol_stream_link_output_class:
438+
case ipc4_alh_uaol_stream_link_input_class:
439+
type = DAI_INTEL_UAOL;
440+
break;
379441
default:
380442
return IPC4_INVALID_RESOURCE_ID;
381443
}

src/audio/copier/copier.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,8 @@ static int copier_init(struct processing_module *mod)
139139
case ipc4_i2s_link_input_class:
140140
case ipc4_alh_link_output_class:
141141
case ipc4_alh_link_input_class:
142+
case ipc4_alh_uaol_stream_link_output_class:
143+
case ipc4_alh_uaol_stream_link_input_class:
142144
ret = copier_dai_create(dev, cd, copier, ipc_pipe->pipeline);
143145
if (ret < 0) {
144146
comp_err(dev, "unable to create dai");

src/audio/copier/copier_dai.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -311,6 +311,19 @@ int copier_dai_create(struct comp_dev *dev, struct copier_data *cd,
311311
if (ret)
312312
return ret;
313313
break;
314+
case ipc4_alh_uaol_stream_link_output_class:
315+
case ipc4_alh_uaol_stream_link_input_class:
316+
dai.type = SOF_DAI_INTEL_UAOL;
317+
dai.is_config_blob = true;
318+
cd->gtw_type = ipc4_gtw_alh;
319+
ret = ipc4_find_dma_config(&dai, (uint8_t *)cd->gtw_cfg,
320+
copier->gtw_cfg.config_length * 4);
321+
if (ret != IPC4_SUCCESS) {
322+
comp_err(dev, "No uaol dma_config found in blob!");
323+
return -EINVAL;
324+
}
325+
dai.out_fmt = &copier->out_fmt;
326+
break;
314327
case ipc4_dmic_link_input_class:
315328
dai.type = SOF_DAI_INTEL_DMIC;
316329
dai.is_config_blob = true;

src/audio/dai-zephyr.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,8 @@ int dai_set_config(struct dai *dai, struct ipc_config_dai *common_config,
150150
cfg.format = sof_cfg->format;
151151
cfg.options = sof_cfg->flags;
152152
cfg.rate = common_config->sampling_frequency;
153+
cfg.channels = common_config->out_fmt->channels_count;
154+
cfg.word_size = common_config->out_fmt->valid_bit_depth;
153155

154156
switch (common_config->type) {
155157
case SOF_DAI_INTEL_SSP:
@@ -182,6 +184,11 @@ int dai_set_config(struct dai *dai, struct ipc_config_dai *common_config,
182184
cfg.type = DAI_IMX_ESAI;
183185
cfg_params = &sof_cfg->esai;
184186
break;
187+
case SOF_DAI_INTEL_UAOL:
188+
cfg.type = DAI_INTEL_UAOL;
189+
cfg_params = gtw_cfg;
190+
dai_set_link_hda_config(&cfg.link_config, common_config, &gtw_cfg->config_data);
191+
break;
185192
default:
186193
return -EINVAL;
187194
}

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
@@ -59,6 +59,12 @@ void dai_set_link_hda_config(uint16_t *link_config,
5959
}
6060
link_cfg.part.stream = common_config->host_dma_config[0]->stream_id;
6161
break;
62+
case SOF_DAI_INTEL_UAOL:
63+
link_cfg.full = 0;
64+
link_cfg.part.hchan = out_fmt->channels_count - 1;
65+
link_cfg.part.dir = common_config->direction;
66+
link_cfg.part.stream = common_config->host_dma_config[0]->stream_id;
67+
break;
6268
default:
6369
/* other types of DAIs not need link_config */
6470
return;
@@ -115,6 +121,13 @@ int dai_config_dma_channel(struct dai_data *dd, struct comp_dev *dev, const void
115121
*/
116122
channel = 0;
117123
break;
124+
#if ACE_VERSION > ACE_VERSION_1_5
125+
case SOF_DAI_INTEL_UAOL:
126+
channel = 0;
127+
if (dai->host_dma_config[0]->pre_allocated_by_host)
128+
channel = dai->host_dma_config[0]->dma_channel_id;
129+
break;
130+
#endif
118131
default:
119132
/* other types of DAIs not handled for now */
120133
comp_err(dev, "dai_config_dma_channel(): Unknown dai type %d", dai->type);
@@ -177,6 +190,16 @@ int ipc_dai_data_config(struct dai_data *dd, struct comp_dev *dev)
177190
dev->ipc_config.frame_fmt, dd->stream_id);
178191

179192
break;
193+
case SOF_DAI_INTEL_UAOL:
194+
#ifdef CONFIG_ZEPHYR_NATIVE_DRIVERS
195+
dd->stream_id = dai_get_stream_id(dai_p, dai->direction);
196+
dev->ipc_config.frame_fmt = SOF_IPC_FRAME_S32_LE;
197+
dd->config.burst_elems = dai_get_fifo_depth(dd->dai, dai->direction);
198+
break;
199+
#else
200+
/* only native Zephyr driver supported */
201+
return -EINVAL;
202+
#endif
180203
default:
181204
/* other types of DAIs not handled for now */
182205
comp_warn(dev, "dai_data_config(): 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
@@ -1055,6 +1055,18 @@ int ipc4_add_comp_dev(struct comp_dev *dev)
10551055
int ipc4_find_dma_config(struct ipc_config_dai *dai, uint8_t *data_buffer, uint32_t size)
10561056
{
10571057
#if ACE_VERSION > ACE_VERSION_1_5
1058+
if (dai->type == SOF_DAI_INTEL_UAOL) {
1059+
void *value_ptr = NULL;
1060+
uint32_t value_size;
1061+
1062+
tlv_value_get(data_buffer, size, GTW_DMA_CONFIG_ID, &value_ptr, &value_size);
1063+
if (!value_ptr)
1064+
return IPC4_INVALID_REQUEST;
1065+
1066+
dai->host_dma_config[0] = (struct ipc_dma_config *)value_ptr;
1067+
return IPC4_SUCCESS;
1068+
}
1069+
10581070
uint32_t *dma_config_id = GET_IPC_DMA_CONFIG_ID(data_buffer, size);
10591071

10601072
if (*dma_config_id != GTW_DMA_CONFIG_ID)

src/lib/dai.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,9 @@ const struct device *zephyr_dev[] = {
149149
#if CONFIG_DAI_NXP_ESAI
150150
DT_FOREACH_STATUS_OKAY(nxp_dai_esai, GET_DEVICE_LIST)
151151
#endif
152+
#if CONFIG_DAI_INTEL_UAOL
153+
DT_FOREACH_STATUS_OKAY(intel_uaol_dai, GET_DEVICE_LIST)
154+
#endif
152155
};
153156

154157
const struct device *dai_get_device(uint32_t type, uint32_t index)
@@ -197,6 +200,7 @@ static void dai_set_device_params(struct dai *d)
197200
#endif
198201
break;
199202
case SOF_DAI_INTEL_HDA:
203+
case SOF_DAI_INTEL_UAOL:
200204
d->dma_dev = SOF_DMA_DEV_HDA;
201205
d->dma_caps = SOF_DMA_CAP_HDA;
202206
break;
@@ -243,6 +247,9 @@ struct dai *dai_get(uint32_t type, uint32_t index, uint32_t flags)
243247
case SOF_DAI_MEDIATEK_AFE:
244248
z_type = DAI_MEDIATEK_AFE;
245249
break;
250+
case SOF_DAI_INTEL_UAOL:
251+
z_type = DAI_INTEL_UAOL;
252+
break;
246253
default:
247254
return NULL;
248255
}

0 commit comments

Comments
 (0)