Commit 1499febc authored by Mark Brown's avatar Mark Brown

ASoC: SOF: Intel: LunarLake preparation patches

Merge series from Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>:

This patchset adds the changes required for the hda-dai extension to
deal with SSSP/DMIC/SoundWire starting with LunarLake, as well as the
new TLV IPC to provide the DMA stream_tag to the DSP firmware.

LunarLake support for SSP/DMIC is ready but is gated by the patch
"ASoC: SOF: Intel: shim: add enum for ACE 2.0 IP used in LunarLake"
currently only present in the SoundWire tree.
parents fd0a7ec3 d3e7c32b
......@@ -175,6 +175,50 @@ static void hda_reset_hext_stream(struct snd_sof_dev *sdev, struct hdac_ext_stre
snd_hdac_ext_stream_reset(hext_stream);
}
static void hda_codec_dai_set_stream(struct snd_sof_dev *sdev,
struct snd_pcm_substream *substream,
struct hdac_stream *hstream)
{
struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
/* set the hdac_stream in the codec dai */
snd_soc_dai_set_stream(codec_dai, hstream, substream->stream);
}
static unsigned int hda_calc_stream_format(struct snd_sof_dev *sdev,
struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
unsigned int link_bps;
unsigned int format_val;
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
link_bps = codec_dai->driver->playback.sig_bits;
else
link_bps = codec_dai->driver->capture.sig_bits;
format_val = snd_hdac_calc_stream_format(params_rate(params), params_channels(params),
params_format(params), link_bps, 0);
dev_dbg(sdev->dev, "format_val=%#x, rate=%d, ch=%d, format=%d\n", format_val,
params_rate(params), params_channels(params), params_format(params));
return format_val;
}
static struct hdac_ext_link *hda_get_hlink(struct snd_sof_dev *sdev,
struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
struct hdac_bus *bus = sof_to_bus(sdev);
return snd_hdac_ext_bus_get_hlink_by_name(bus, codec_dai->component->name);
}
static int hda_ipc4_pre_trigger(struct snd_sof_dev *sdev, struct snd_soc_dai *cpu_dai,
struct snd_pcm_substream *substream, int cmd)
{
......@@ -307,7 +351,10 @@ static const struct hda_dai_widget_dma_ops hda_ipc4_dma_ops = {
.reset_hext_stream = hda_reset_hext_stream,
.pre_trigger = hda_ipc4_pre_trigger,
.trigger = hda_trigger,
.post_trigger = hda_ipc4_post_trigger
.post_trigger = hda_ipc4_post_trigger,
.codec_dai_set_stream = hda_codec_dai_set_stream,
.calc_stream_format = hda_calc_stream_format,
.get_hlink = hda_get_hlink,
};
static const struct hda_dai_widget_dma_ops hda_ipc4_chain_dma_ops = {
......@@ -317,6 +364,9 @@ static const struct hda_dai_widget_dma_ops hda_ipc4_chain_dma_ops = {
.setup_hext_stream = hda_setup_hext_stream,
.reset_hext_stream = hda_reset_hext_stream,
.trigger = hda_trigger,
.codec_dai_set_stream = hda_codec_dai_set_stream,
.calc_stream_format = hda_calc_stream_format,
.get_hlink = hda_get_hlink,
};
static int hda_ipc3_post_trigger(struct snd_sof_dev *sdev, struct snd_soc_dai *cpu_dai,
......@@ -350,6 +400,9 @@ static const struct hda_dai_widget_dma_ops hda_ipc3_dma_ops = {
.reset_hext_stream = hda_reset_hext_stream,
.trigger = hda_trigger,
.post_trigger = hda_ipc3_post_trigger,
.codec_dai_set_stream = hda_codec_dai_set_stream,
.calc_stream_format = hda_calc_stream_format,
.get_hlink = hda_get_hlink,
};
static struct hdac_ext_stream *
......@@ -376,6 +429,9 @@ static void hda_dspless_setup_hext_stream(struct snd_sof_dev *sdev,
static const struct hda_dai_widget_dma_ops hda_dspless_dma_ops = {
.get_hext_stream = hda_dspless_get_hext_stream,
.setup_hext_stream = hda_dspless_setup_hext_stream,
.codec_dai_set_stream = hda_codec_dai_set_stream,
.calc_stream_format = hda_calc_stream_format,
.get_hlink = hda_get_hlink,
};
#endif
......
......@@ -109,20 +109,22 @@ hda_dai_get_ops(struct snd_pcm_substream *substream, struct snd_soc_dai *cpu_dai
static int hda_link_dma_cleanup(struct snd_pcm_substream *substream,
struct hdac_ext_stream *hext_stream,
struct snd_soc_dai *cpu_dai,
struct snd_soc_dai *codec_dai)
struct snd_soc_dai *cpu_dai)
{
const struct hda_dai_widget_dma_ops *ops = hda_dai_get_ops(substream, cpu_dai);
struct hdac_stream *hstream = &hext_stream->hstream;
struct hdac_bus *bus = hstream->bus;
struct sof_intel_hda_stream *hda_stream;
struct hdac_ext_link *hlink;
struct snd_sof_dev *sdev;
int stream_tag;
if (!ops) {
dev_err(cpu_dai->dev, "DAI widget ops not set\n");
return -EINVAL;
}
sdev = dai_to_sdev(substream, cpu_dai);
hlink = snd_hdac_ext_bus_get_hlink_by_name(bus, codec_dai->component->name);
hlink = ops->get_hlink(sdev, substream);
if (!hlink)
return -EINVAL;
......@@ -147,21 +149,20 @@ static int hda_link_dma_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params, struct snd_soc_dai *cpu_dai)
{
const struct hda_dai_widget_dma_ops *ops = hda_dai_get_ops(substream, cpu_dai);
struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
struct hdac_ext_stream *hext_stream;
struct hdac_stream *hstream;
struct hdac_ext_link *hlink;
struct snd_sof_dev *sdev;
struct hdac_bus *bus;
unsigned int format_val;
unsigned int link_bps;
int stream_tag;
if (!ops) {
dev_err(cpu_dai->dev, "DAI widget ops not set\n");
return -EINVAL;
}
sdev = dai_to_sdev(substream, cpu_dai);
bus = sof_to_bus(sdev);
hlink = snd_hdac_ext_bus_get_hlink_by_name(bus, codec_dai->component->name);
hlink = ops->get_hlink(sdev, substream);
if (!hlink)
return -EINVAL;
......@@ -182,24 +183,17 @@ static int hda_link_dma_hw_params(struct snd_pcm_substream *substream,
snd_hdac_ext_bus_link_set_stream_id(hlink, stream_tag);
/* set the hdac_stream in the codec dai */
snd_soc_dai_set_stream(codec_dai, hdac_stream(hext_stream), substream->stream);
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
link_bps = codec_dai->driver->playback.sig_bits;
else
link_bps = codec_dai->driver->capture.sig_bits;
if (ops->codec_dai_set_stream)
ops->codec_dai_set_stream(sdev, substream, hstream);
if (ops->reset_hext_stream)
ops->reset_hext_stream(sdev, hext_stream);
format_val = snd_hdac_calc_stream_format(params_rate(params), params_channels(params),
params_format(params), link_bps, 0);
if (ops->calc_stream_format && ops->setup_hext_stream) {
unsigned int format_val = ops->calc_stream_format(sdev, substream, params);
dev_dbg(bus->dev, "format_val=%#x, rate=%d, ch=%d, format=%d\n", format_val,
params_rate(params), params_channels(params), params_format(params));
if (ops->setup_hext_stream)
ops->setup_hext_stream(sdev, hext_stream, format_val);
}
hext_stream->link_prepared = 1;
......@@ -210,13 +204,11 @@ static int __maybe_unused hda_dai_hw_free(struct snd_pcm_substream *substream,
struct snd_soc_dai *cpu_dai)
{
const struct hda_dai_widget_dma_ops *ops = hda_dai_get_ops(substream, cpu_dai);
struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
struct hdac_ext_stream *hext_stream;
struct snd_sof_dev *sdev = dai_to_sdev(substream, cpu_dai);
if (!ops) {
dev_err(sdev->dev, "DAI widget ops not set\n");
dev_err(cpu_dai->dev, "DAI widget ops not set\n");
return -EINVAL;
}
......@@ -224,7 +216,7 @@ static int __maybe_unused hda_dai_hw_free(struct snd_pcm_substream *substream,
if (!hext_stream)
return 0;
return hda_link_dma_cleanup(substream, hext_stream, cpu_dai, codec_dai);
return hda_link_dma_cleanup(substream, hext_stream, cpu_dai);
}
static int __maybe_unused hda_dai_hw_params(struct snd_pcm_substream *substream,
......@@ -269,11 +261,14 @@ static int __maybe_unused hda_dai_trigger(struct snd_pcm_substream *substream, i
{
const struct hda_dai_widget_dma_ops *ops = hda_dai_get_ops(substream, dai);
struct hdac_ext_stream *hext_stream;
struct snd_soc_pcm_runtime *rtd;
struct snd_soc_dai *codec_dai;
struct snd_sof_dev *sdev;
int ret;
if (!ops) {
dev_err(dai->dev, "DAI widget ops not set\n");
return -EINVAL;
}
dev_dbg(dai->dev, "cmd=%d dai %s direction %d\n", cmd,
dai->name, substream->stream);
......@@ -283,9 +278,6 @@ static int __maybe_unused hda_dai_trigger(struct snd_pcm_substream *substream, i
if (!hext_stream)
return -EINVAL;
rtd = asoc_substream_to_rtd(substream);
codec_dai = asoc_rtd_to_codec(rtd, 0);
if (ops->pre_trigger) {
ret = ops->pre_trigger(sdev, dai, substream, cmd);
if (ret < 0)
......@@ -306,7 +298,7 @@ static int __maybe_unused hda_dai_trigger(struct snd_pcm_substream *substream, i
switch (cmd) {
case SNDRV_PCM_TRIGGER_SUSPEND:
ret = hda_link_dma_cleanup(substream, hext_stream, dai, codec_dai);
ret = hda_link_dma_cleanup(substream, hext_stream, dai);
if (ret < 0) {
dev_err(sdev->dev, "%s: failed to clean up link DMA\n", __func__);
return ret;
......@@ -360,14 +352,12 @@ static int hda_dai_suspend(struct hdac_bus *bus)
const struct hda_dai_widget_dma_ops *ops;
struct snd_sof_widget *swidget;
struct snd_soc_dapm_widget *w;
struct snd_soc_dai *codec_dai;
struct snd_soc_dai *cpu_dai;
struct snd_sof_dev *sdev;
struct snd_sof_dai *sdai;
rtd = asoc_substream_to_rtd(hext_stream->link_substream);
cpu_dai = asoc_rtd_to_cpu(rtd, 0);
codec_dai = asoc_rtd_to_codec(rtd, 0);
w = snd_soc_dai_get_widget(cpu_dai, hdac_stream(hext_stream)->direction);
swidget = w->dobj.private;
sdev = widget_to_sdev(w);
......@@ -376,7 +366,7 @@ static int hda_dai_suspend(struct hdac_bus *bus)
ret = hda_link_dma_cleanup(hext_stream->link_substream,
hext_stream,
cpu_dai, codec_dai);
cpu_dai);
if (ret < 0)
return ret;
......
......@@ -222,6 +222,31 @@ int hda_sdw_check_lcount_common(struct snd_sof_dev *sdev)
return 0;
}
int hda_sdw_check_lcount_ext(struct snd_sof_dev *sdev)
{
struct sof_intel_hda_dev *hdev;
struct sdw_intel_ctx *ctx;
struct hdac_bus *bus;
u32 slcount;
bus = sof_to_bus(sdev);
hdev = sdev->pdata->hw_pdata;
ctx = hdev->sdw;
slcount = hdac_bus_eml_get_count(bus, true, AZX_REG_ML_LEPTR_ID_SDW);
/* Check HW supported vs property value */
if (slcount < ctx->count) {
dev_err(sdev->dev,
"%s: BIOS master count %d is larger than hardware capabilities %d\n",
__func__, ctx->count, slcount);
return -EINVAL;
}
return 0;
}
static int hda_sdw_check_lcount(struct snd_sof_dev *sdev)
{
const struct sof_intel_dsp_desc *chip;
......
......@@ -781,6 +781,7 @@ int hda_dsp_trace_trigger(struct snd_sof_dev *sdev, int cmd);
#if IS_ENABLED(CONFIG_SND_SOC_SOF_INTEL_SOUNDWIRE)
int hda_sdw_check_lcount_common(struct snd_sof_dev *sdev);
int hda_sdw_check_lcount_ext(struct snd_sof_dev *sdev);
int hda_sdw_startup(struct snd_sof_dev *sdev);
void hda_common_enable_sdw_irq(struct snd_sof_dev *sdev, bool enable);
void hda_sdw_int_enable(struct snd_sof_dev *sdev, bool enable);
......@@ -794,6 +795,11 @@ static inline int hda_sdw_check_lcount_common(struct snd_sof_dev *sdev)
return 0;
}
static inline int hda_sdw_check_lcount_ext(struct snd_sof_dev *sdev)
{
return 0;
}
static inline int hda_sdw_startup(struct snd_sof_dev *sdev)
{
return 0;
......@@ -919,6 +925,11 @@ int hda_dsp_ipc4_load_library(struct snd_sof_dev *sdev,
* @pre_trigger: Function pointer for DAI DMA pre-trigger actions
* @trigger: Function pointer for DAI DMA trigger actions
* @post_trigger: Function pointer for DAI DMA post-trigger actions
* @codec_dai_set_stream: Function pointer to set codec-side stream information
* @calc_stream_format: Function pointer to determine stream format from hw_params and
* for HDaudio codec DAI from the .sig bits
* @get_hlink: Mandatory function pointer to retrieve hlink, mainly to program LOSIDV
* for legacy HDaudio links or program HDaudio Extended Link registers.
*/
struct hda_dai_widget_dma_ops {
struct hdac_ext_stream *(*get_hext_stream)(struct snd_sof_dev *sdev,
......@@ -938,6 +949,14 @@ struct hda_dai_widget_dma_ops {
struct snd_pcm_substream *substream, int cmd);
int (*post_trigger)(struct snd_sof_dev *sdev, struct snd_soc_dai *cpu_dai,
struct snd_pcm_substream *substream, int cmd);
void (*codec_dai_set_stream)(struct snd_sof_dev *sdev,
struct snd_pcm_substream *substream,
struct hdac_stream *hstream);
unsigned int (*calc_stream_format)(struct snd_sof_dev *sdev,
struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params);
struct hdac_ext_link * (*get_hlink)(struct snd_sof_dev *sdev,
struct snd_pcm_substream *substream);
};
const struct hda_dai_widget_dma_ops *
......
......@@ -55,7 +55,7 @@ static void mtl_ipc_dsp_done(struct snd_sof_dev *sdev)
}
/* Check if an IPC IRQ occurred */
static bool mtl_dsp_check_ipc_irq(struct snd_sof_dev *sdev)
bool mtl_dsp_check_ipc_irq(struct snd_sof_dev *sdev)
{
u32 irq_status;
u32 hfintipptr;
......@@ -118,7 +118,7 @@ static int mtl_ipc_send_msg(struct snd_sof_dev *sdev, struct snd_sof_ipc_msg *ms
return 0;
}
static void mtl_enable_ipc_interrupts(struct snd_sof_dev *sdev)
void mtl_enable_ipc_interrupts(struct snd_sof_dev *sdev)
{
struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata;
const struct sof_intel_dsp_desc *chip = hda->desc;
......@@ -132,7 +132,7 @@ static void mtl_enable_ipc_interrupts(struct snd_sof_dev *sdev)
MTL_DSP_REG_HFIPCXCTL_BUSY | MTL_DSP_REG_HFIPCXCTL_DONE);
}
static void mtl_disable_ipc_interrupts(struct snd_sof_dev *sdev)
void mtl_disable_ipc_interrupts(struct snd_sof_dev *sdev)
{
struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata;
const struct sof_intel_dsp_desc *chip = hda->desc;
......@@ -173,7 +173,7 @@ static void mtl_enable_sdw_irq(struct snd_sof_dev *sdev, bool enable)
enable ? "enable" : "disable");
}
static int mtl_enable_interrupts(struct snd_sof_dev *sdev, bool enable)
int mtl_enable_interrupts(struct snd_sof_dev *sdev, bool enable)
{
u32 hfintipptr;
u32 irqinten;
......@@ -394,7 +394,7 @@ static int mtl_dsp_core_power_down(struct snd_sof_dev *sdev, int core)
return ret;
}
static int mtl_power_down_dsp(struct snd_sof_dev *sdev)
int mtl_power_down_dsp(struct snd_sof_dev *sdev)
{
u32 dsphfdsscs, cpa;
int ret;
......@@ -421,7 +421,7 @@ static int mtl_power_down_dsp(struct snd_sof_dev *sdev)
HDA_DSP_RESET_TIMEOUT_US);
}
static int mtl_dsp_cl_init(struct snd_sof_dev *sdev, int stream_tag, bool imr_boot)
int mtl_dsp_cl_init(struct snd_sof_dev *sdev, int stream_tag, bool imr_boot)
{
struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata;
const struct sof_intel_dsp_desc *chip = hda->desc;
......
......@@ -82,3 +82,10 @@
#define MTL_DSP_REG_HfIMRIS1 0x162088
#define MTL_DSP_REG_HfIMRIS1_IU_MASK BIT(0)
void mtl_enable_ipc_interrupts(struct snd_sof_dev *sdev);
void mtl_disable_ipc_interrupts(struct snd_sof_dev *sdev);
bool mtl_dsp_check_ipc_irq(struct snd_sof_dev *sdev);
int mtl_enable_interrupts(struct snd_sof_dev *sdev, bool enable);
int mtl_dsp_cl_init(struct snd_sof_dev *sdev, int stream_tag, bool imr_boot);
int mtl_power_down_dsp(struct snd_sof_dev *sdev);
......@@ -559,7 +559,7 @@ static int sof_ipc4_widget_setup_comp_dai(struct snd_sof_widget *swidget)
strcmp(w->widget->sname, swidget->widget->sname))
continue;
blob->alh_cfg.count++;
blob->alh_cfg.device_count++;
}
ipc4_copier->copier_config = (uint32_t *)blob;
......@@ -1225,7 +1225,7 @@ static void sof_ipc4_unprepare_copier_module(struct snd_sof_widget *swidget)
unsigned int group_id;
blob = (struct sof_ipc4_alh_configuration_blob *)ipc4_copier->copier_config;
if (blob->alh_cfg.count > 1) {
if (blob->alh_cfg.device_count > 1) {
group_id = SOF_IPC4_NODE_INDEX(ipc4_copier->data.gtw_cfg.node_id) -
ALH_MULTI_GTW_BASE;
ida_free(&alh_group_ida, group_id);
......@@ -1383,6 +1383,8 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget,
struct snd_sof_dai *dai;
struct snd_mask *fmt;
int out_sample_valid_bits;
u32 gtw_cfg_config_length;
u32 dma_config_tlv_size = 0;
void **ipc_config_data;
int *ipc_config_size;
u32 **data;
......@@ -1609,7 +1611,7 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget,
ch_map >>= 4;
}
step = ch_count / blob->alh_cfg.count;
step = ch_count / blob->alh_cfg.device_count;
mask = GENMASK(step - 1, 0);
/*
* Set each gtw_cfg.node_id to blob->alh_cfg.mapping[]
......@@ -1624,7 +1626,7 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget,
dai = w->private;
alh_copier = (struct sof_ipc4_copier *)dai->private;
alh_data = &alh_copier->data;
blob->alh_cfg.mapping[i].alh_id = alh_data->gtw_cfg.node_id;
blob->alh_cfg.mapping[i].device = alh_data->gtw_cfg.node_id;
/*
* Set the same channel mask for playback as the audio data is
* duplicated for all speakers. For capture, split the channels
......@@ -1643,7 +1645,7 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget,
i++;
}
if (blob->alh_cfg.count > 1) {
if (blob->alh_cfg.device_count > 1) {
int group_id;
group_id = ida_alloc_max(&alh_group_ida, ALH_MULTI_GTW_COUNT - 1,
......@@ -1699,7 +1701,27 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget,
ipc_config_data = &ipc4_copier->ipc_config_data;
/* config_length is DWORD based */
ipc_size = sizeof(*copier_data) + copier_data->gtw_cfg.config_length * 4;
gtw_cfg_config_length = copier_data->gtw_cfg.config_length * 4;
ipc_size = sizeof(*copier_data) + gtw_cfg_config_length;
if (ipc4_copier->dma_config_tlv.type == SOF_IPC4_GTW_DMA_CONFIG_ID &&
ipc4_copier->dma_config_tlv.length) {
dma_config_tlv_size = sizeof(ipc4_copier->dma_config_tlv) +
ipc4_copier->dma_config_tlv.dma_config.dma_priv_config_size;
/* paranoia check on TLV size/length */
if (dma_config_tlv_size != ipc4_copier->dma_config_tlv.length +
sizeof(uint32_t) * 2) {
dev_err(sdev->dev, "Invalid configuration, TLV size %d length %d\n",
dma_config_tlv_size, ipc4_copier->dma_config_tlv.length);
return -EINVAL;
}
ipc_size += dma_config_tlv_size;
/* we also need to increase the size at the gtw level */
copier_data->gtw_cfg.config_length += dma_config_tlv_size / 4;
}
dev_dbg(sdev->dev, "copier %s, IPC size is %d", swidget->widget->name, ipc_size);
......@@ -1711,9 +1733,15 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget,
/* copy IPC data */
memcpy(*ipc_config_data, (void *)copier_data, sizeof(*copier_data));
if (copier_data->gtw_cfg.config_length)
if (gtw_cfg_config_length)
memcpy(*ipc_config_data + sizeof(*copier_data),
*data, copier_data->gtw_cfg.config_length * 4);
*data, gtw_cfg_config_length);
/* add DMA Config TLV, if configured */
if (dma_config_tlv_size)
memcpy(*ipc_config_data + sizeof(*copier_data) +
gtw_cfg_config_length,
&ipc4_copier->dma_config_tlv, dma_config_tlv_size);
/* update pipeline memory usage */
sof_ipc4_update_resource_usage(sdev, swidget, &copier_data->base_config);
......
......@@ -55,7 +55,7 @@
#define SOF_IPC4_GAIN_ALL_CHANNELS_MASK 0xffffffff
#define SOF_IPC4_VOL_ZERO_DB 0x7fffffff
#define ALH_MAX_NUMBER_OF_GTW 16
#define SOF_IPC4_DMA_DEVICE_MAX_COUNT 16
#define SOF_IPC4_INVALID_NODE_ID 0xffffffff
......@@ -220,18 +220,64 @@ struct sof_ipc4_gtw_attributes {
uint32_t rsvd : 30;
};
/** struct sof_ipc4_alh_multi_gtw_cfg: ALH gateway cfg data
* @count: Number of streams (valid items in mapping array)
* @alh_id: ALH stream id of a single ALH stream aggregated
* @channel_mask: Channel mask
* @mapping: ALH streams
/**
* struct sof_ipc4_dma_device_stream_ch_map: abstract representation of
* channel mapping to DMAs
* @device: representation of hardware device address or FIFO
* @channel_mask: channels handled by @device. Channels are expected to be
* contiguous
*/
struct sof_ipc4_alh_multi_gtw_cfg {
uint32_t count;
struct {
uint32_t alh_id;
struct sof_ipc4_dma_device_stream_ch_map {
uint32_t device;
uint32_t channel_mask;
} mapping[ALH_MAX_NUMBER_OF_GTW];
};
/**
* struct sof_ipc4_dma_stream_ch_map: DMA configuration data
* @device_count: Number valid items in mapping array
* @mapping: device address and channel mask
*/
struct sof_ipc4_dma_stream_ch_map {
uint32_t device_count;
struct sof_ipc4_dma_device_stream_ch_map mapping[SOF_IPC4_DMA_DEVICE_MAX_COUNT];
} __packed;
#define SOF_IPC4_DMA_METHOD_HDA 1
#define SOF_IPC4_DMA_METHOD_GPDMA 2 /* defined for consistency but not used */
/**
* struct sof_ipc4_dma_config: DMA configuration
* @dma_method: HDAudio or GPDMA
* @pre_allocated_by_host: 1 if host driver allocates DMA channels, 0 otherwise
* @dma_channel_id: for HDaudio defined as @stream_id - 1
* @stream_id: HDaudio stream tag
* @dma_stream_channel_map: array of device/channel mappings
* @dma_priv_config_size: currently not used
* @dma_priv_config: currently not used
*/
struct sof_ipc4_dma_config {
uint8_t dma_method;
uint8_t pre_allocated_by_host;
uint16_t rsvd;
uint32_t dma_channel_id;
uint32_t stream_id;
struct sof_ipc4_dma_stream_ch_map dma_stream_channel_map;
uint32_t dma_priv_config_size;
uint8_t dma_priv_config[];
} __packed;
#define SOF_IPC4_GTW_DMA_CONFIG_ID 0x1000
/**
* struct sof_ipc4_dma_config: DMA configuration
* @type: set to SOF_IPC4_GTW_DMA_CONFIG_ID
* @length: sizeof(struct sof_ipc4_dma_config) + dma_config.dma_priv_config_size
* @dma_config: actual DMA configuration
*/
struct sof_ipc4_dma_config_tlv {
uint32_t type;
uint32_t length;
struct sof_ipc4_dma_config dma_config;
} __packed;
/** struct sof_ipc4_alh_configuration_blob: ALH blob
......@@ -240,7 +286,7 @@ struct sof_ipc4_alh_multi_gtw_cfg {
*/
struct sof_ipc4_alh_configuration_blob {
struct sof_ipc4_gtw_attributes gw_attr;
struct sof_ipc4_alh_multi_gtw_cfg alh_cfg;
struct sof_ipc4_dma_stream_ch_map alh_cfg;
};
/**
......@@ -254,6 +300,7 @@ struct sof_ipc4_alh_configuration_blob {
* @gtw_attr: Gateway attributes for copier blob
* @dai_type: DAI type
* @dai_index: DAI index
* @dma_config_tlv: DMA configuration
*/
struct sof_ipc4_copier {
struct sof_ipc4_copier_data data;
......@@ -266,6 +313,7 @@ struct sof_ipc4_copier {
struct sof_ipc4_gtw_attributes *gtw_attr;
u32 dai_type;
int dai_index;
struct sof_ipc4_dma_config_tlv dma_config_tlv;
};
/**
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment