ASoC: Intel: avs: Add support for MalibouLake
Merge series from Cezary Rojewski <cezary.rojewski@intel.com>: The avs-driver is the go-to driver for Intel Automotive. MalibouLake (MBL) and RedondoLake (RDL) are representatives of the project. These inherit majority of the featureset from RaptorLake-M (RPL-M) and AlderLake-N (ADL-N) respectively. The onboard codec for these is TI's pcm3168a. In summary, the patchset: - modifies existing pcm3168a.c to be x86/ACPI friendly - updates the DSP firmware booting sequence for cAVS 2.5 platforms to improve its behaviour on some specific revisions/steppings of the hardware - adds new machine board driver, avs_pcm3168a - adds selector entry for RPL-M devices in intel-dspcfg While there 'ALSA: hda:' patch within the list, I'd prefer the patchset to go through Mark's tree to avoid conflicts with follow ups to this one. Longer version: Currently the pcm3168a is supported on ARM/DT (ti/j721e-evm.c being the only user). To make it x86/ACPI friendly, add relevant ACPI-match table and relax driver's probing conditions. The default format is 2ch, 24-bits, 48000kHz. As per specification, 24-bits are supported by the chip and it works in production in contrary to what the existing code suggests. A fix is provided to align the code with the spec. Now, a single DSP firmware binary covers a wide range of platforms - a single one covers AlderLake, RaptorLake and all their derevatires except for AlderLake-N based due to MEU differences. While most of the hardware capabilities are read by the firmware during runtime, some information is not accessible from the DSP level. Provide the HDAudio controller revision/stepping information to the firmware to address that. With that done, expand number of modules supported with WovHostModule (WHM). WHM is a processing module which is tailored for ultra-low-power scenarios. From software perspective, as most of its config is similar to the Copier module, code reuse is advised. To make the reuse possible, existing gateway configuration code is refactor - not only to add support for WHM but also make it easier to understand. Multiple smaller functions instead of all-in-one one.
This commit is contained in:
@@ -77,6 +77,13 @@ enum avs_tplg_token {
|
||||
AVS_TKN_MODCFG_UPDOWN_MIX_CHAN_MAP_U32 = 430,
|
||||
AVS_TKN_MODCFG_EXT_NUM_INPUT_PINS_U16 = 431,
|
||||
AVS_TKN_MODCFG_EXT_NUM_OUTPUT_PINS_U16 = 432,
|
||||
AVS_TKN_MODCFG_WHM_REF_AFMT_ID_U32 = 433,
|
||||
AVS_TKN_MODCFG_WHM_OUT_AFMT_ID_U32 = 434,
|
||||
AVS_TKN_MODCFG_WHM_WAKE_TICK_PERIOD_U32 = 435,
|
||||
AVS_TKN_MODCFG_WHM_VINDEX_U8 = 436,
|
||||
AVS_TKN_MODCFG_WHM_DMA_TYPE_U32 = 437,
|
||||
AVS_TKN_MODCFG_WHM_DMABUFF_SIZE_U32 = 438,
|
||||
AVS_TKN_MODCFG_WHM_BLOB_AFMT_ID_U32 = 439,
|
||||
|
||||
/* struct avs_tplg_pplcfg */
|
||||
AVS_TKN_PPLCFG_ID_U32 = 1401,
|
||||
|
||||
@@ -108,6 +108,10 @@ static const struct config_entry config_table[] = {
|
||||
{}
|
||||
}
|
||||
},
|
||||
{
|
||||
.flags = FLAG_SST,
|
||||
.device = PCI_DEVICE_ID_INTEL_HDA_RPL_M,
|
||||
},
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_SND_SOC_SOF_APOLLOLAKE)
|
||||
{
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/mod_devicetable.h>
|
||||
|
||||
#include <sound/soc.h>
|
||||
|
||||
@@ -37,6 +38,13 @@ static const struct i2c_device_id pcm3168a_i2c_id[] = {
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, pcm3168a_i2c_id);
|
||||
|
||||
static const struct acpi_device_id pcm3168a_acpi_match[] = {
|
||||
{ "PCM3168A" },
|
||||
{ "104C3168" },
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(acpi, pcm3168a_acpi_match);
|
||||
|
||||
static const struct of_device_id pcm3168a_of_match[] = {
|
||||
{ .compatible = "ti,pcm3168a", },
|
||||
{ }
|
||||
@@ -49,6 +57,7 @@ static struct i2c_driver pcm3168a_i2c_driver = {
|
||||
.id_table = pcm3168a_i2c_id,
|
||||
.driver = {
|
||||
.name = "pcm3168a",
|
||||
.acpi_match_table = pcm3168a_acpi_match,
|
||||
.of_match_table = pcm3168a_of_match,
|
||||
.pm = &pcm3168a_pm_ops,
|
||||
},
|
||||
|
||||
@@ -493,9 +493,9 @@ static int pcm3168a_hw_params(struct snd_pcm_substream *substream,
|
||||
}
|
||||
break;
|
||||
case 24:
|
||||
if (provider_mode || (format == SND_SOC_DAIFMT_DSP_A) ||
|
||||
(format == SND_SOC_DAIFMT_DSP_B)) {
|
||||
dev_err(component->dev, "24-bit slots not supported in provider mode, or consumer mode using DSP\n");
|
||||
if (!provider_mode && ((format == SND_SOC_DAIFMT_DSP_A) ||
|
||||
(format == SND_SOC_DAIFMT_DSP_B))) {
|
||||
dev_err(component->dev, "24-bit slots not supported in consumer mode using DSP\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
break;
|
||||
@@ -743,7 +743,7 @@ int pcm3168a_probe(struct device *dev, struct regmap *regmap)
|
||||
return dev_err_probe(dev, PTR_ERR(pcm3168a->gpio_rst),
|
||||
"failed to acquire RST gpio\n");
|
||||
|
||||
pcm3168a->scki = devm_clk_get(dev, "scki");
|
||||
pcm3168a->scki = devm_clk_get_optional(dev, "scki");
|
||||
if (IS_ERR(pcm3168a->scki))
|
||||
return dev_err_probe(dev, PTR_ERR(pcm3168a->scki),
|
||||
"failed to acquire clock 'scki'\n");
|
||||
@@ -755,6 +755,9 @@ int pcm3168a_probe(struct device *dev, struct regmap *regmap)
|
||||
}
|
||||
|
||||
pcm3168a->sysclk = clk_get_rate(pcm3168a->scki);
|
||||
/* Fallback to the default if no clk entry available. */
|
||||
if (!pcm3168a->sysclk)
|
||||
pcm3168a->sysclk = 24576000;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(pcm3168a->supplies); i++)
|
||||
pcm3168a->supplies[i].supply = pcm3168a_supply_names[i];
|
||||
|
||||
@@ -51,6 +51,7 @@ struct avs_dsp_ops {
|
||||
int (* const load_basefw)(struct avs_dev *, struct firmware *);
|
||||
int (* const load_lib)(struct avs_dev *, struct firmware *, u32);
|
||||
int (* const transfer_mods)(struct avs_dev *, bool, struct avs_module_entry *, u32);
|
||||
int (* const config_basefw)(struct avs_dev *);
|
||||
int (* const enable_logs)(struct avs_dev *, enum avs_log_enable, u32, u32, unsigned long,
|
||||
u32 *);
|
||||
int (* const log_buffer_offset)(struct avs_dev *, u32);
|
||||
|
||||
@@ -312,6 +312,18 @@ static struct snd_soc_acpi_mach avs_tgl_i2s_machines[] = {
|
||||
{},
|
||||
};
|
||||
|
||||
static struct snd_soc_acpi_mach avs_mbl_i2s_machines[] = {
|
||||
{
|
||||
.id = "PCM3168A",
|
||||
.drv_name = "avs_pcm3168a",
|
||||
.mach_params = {
|
||||
.i2s_link_mask = AVS_SSP(0) | AVS_SSP(2),
|
||||
},
|
||||
.tplg_filename = "pcm3168a-tplg.bin",
|
||||
},
|
||||
{}
|
||||
};
|
||||
|
||||
static struct snd_soc_acpi_mach avs_test_i2s_machines[] = {
|
||||
{
|
||||
.drv_name = "avs_i2s_test",
|
||||
@@ -378,10 +390,11 @@ static const struct avs_acpi_boards i2s_boards[] = {
|
||||
AVS_MACH_ENTRY(HDA_ICL_LP, avs_icl_i2s_machines),
|
||||
AVS_MACH_ENTRY(HDA_TGL_LP, avs_tgl_i2s_machines),
|
||||
AVS_MACH_ENTRY(HDA_EHL_0, avs_tgl_i2s_machines),
|
||||
AVS_MACH_ENTRY(HDA_ADL_N, avs_mbl_i2s_machines),
|
||||
AVS_MACH_ENTRY(HDA_ADL_P, avs_tgl_i2s_machines),
|
||||
AVS_MACH_ENTRY(HDA_RPL_P_0, avs_tgl_i2s_machines),
|
||||
AVS_MACH_ENTRY(HDA_RPL_M, avs_tgl_i2s_machines),
|
||||
{},
|
||||
AVS_MACH_ENTRY(HDA_RPL_M, avs_mbl_i2s_machines),
|
||||
{}
|
||||
};
|
||||
|
||||
static const struct avs_acpi_boards *avs_get_i2s_boards(struct avs_dev *adev)
|
||||
|
||||
@@ -87,6 +87,16 @@ config SND_SOC_INTEL_AVS_MACH_NAU8825
|
||||
Say Y or m if you have such a device. This is a recommended option.
|
||||
If unsure select "N".
|
||||
|
||||
config SND_SOC_INTEL_AVS_MACH_PCM3168A
|
||||
tristate "pcm3168a I2S board"
|
||||
depends on I2C
|
||||
depends on MFD_INTEL_LPSS || COMPILE_TEST
|
||||
select SND_SOC_PCM3168A_I2C
|
||||
help
|
||||
This adds support for AVS with PCM3168A I2C codec configuration.
|
||||
Say Y or m if you have such a device. This is a recommended option.
|
||||
If unsure select "N".
|
||||
|
||||
config SND_SOC_INTEL_AVS_MACH_PROBE
|
||||
tristate "Probing (data) board"
|
||||
depends on DEBUG_FS
|
||||
|
||||
@@ -9,6 +9,7 @@ snd-soc-avs-max98927-y := max98927.o
|
||||
snd-soc-avs-max98357a-y := max98357a.o
|
||||
snd-soc-avs-max98373-y := max98373.o
|
||||
snd-soc-avs-nau8825-y := nau8825.o
|
||||
snd-soc-avs-pcm3168a-y := pcm3168a.o
|
||||
snd-soc-avs-probe-y := probe.o
|
||||
snd-soc-avs-rt274-y := rt274.o
|
||||
snd-soc-avs-rt286-y := rt286.o
|
||||
@@ -27,6 +28,7 @@ obj-$(CONFIG_SND_SOC_INTEL_AVS_MACH_MAX98927) += snd-soc-avs-max98927.o
|
||||
obj-$(CONFIG_SND_SOC_INTEL_AVS_MACH_MAX98357A) += snd-soc-avs-max98357a.o
|
||||
obj-$(CONFIG_SND_SOC_INTEL_AVS_MACH_MAX98373) += snd-soc-avs-max98373.o
|
||||
obj-$(CONFIG_SND_SOC_INTEL_AVS_MACH_NAU8825) += snd-soc-avs-nau8825.o
|
||||
obj-$(CONFIG_SND_SOC_INTEL_AVS_MACH_PCM3168A) += snd-soc-avs-pcm3168a.o
|
||||
obj-$(CONFIG_SND_SOC_INTEL_AVS_MACH_PROBE) += snd-soc-avs-probe.o
|
||||
obj-$(CONFIG_SND_SOC_INTEL_AVS_MACH_RT274) += snd-soc-avs-rt274.o
|
||||
obj-$(CONFIG_SND_SOC_INTEL_AVS_MACH_RT286) += snd-soc-avs-rt286.o
|
||||
|
||||
@@ -0,0 +1,143 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
//
|
||||
// Copyright(c) 2024-2025 Intel Corporation
|
||||
//
|
||||
// Author: Cezary Rojewski <cezary.rojewski@intel.com>
|
||||
//
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <sound/core.h>
|
||||
#include <sound/pcm.h>
|
||||
#include <sound/pcm_params.h>
|
||||
#include <sound/soc.h>
|
||||
|
||||
static const struct snd_soc_dapm_widget card_widgets[] = {
|
||||
SND_SOC_DAPM_HP("CPB Stereo HP 1", NULL),
|
||||
SND_SOC_DAPM_HP("CPB Stereo HP 2", NULL),
|
||||
SND_SOC_DAPM_HP("CPB Stereo HP 3", NULL),
|
||||
SND_SOC_DAPM_LINE("CPB Line Out", NULL),
|
||||
SND_SOC_DAPM_MIC("CPB Stereo Mic 1", NULL),
|
||||
SND_SOC_DAPM_MIC("CPB Stereo Mic 2", NULL),
|
||||
SND_SOC_DAPM_LINE("CPB Line In", NULL),
|
||||
};
|
||||
|
||||
static const struct snd_soc_dapm_route card_routes[] = {
|
||||
{ "CPB Stereo HP 1", NULL, "AOUT1L" },
|
||||
{ "CPB Stereo HP 1", NULL, "AOUT1R" },
|
||||
{ "CPB Stereo HP 2", NULL, "AOUT2L" },
|
||||
{ "CPB Stereo HP 2", NULL, "AOUT2R" },
|
||||
{ "CPB Stereo HP 3", NULL, "AOUT3L" },
|
||||
{ "CPB Stereo HP 3", NULL, "AOUT3R" },
|
||||
{ "CPB Line Out", NULL, "AOUT4L" },
|
||||
{ "CPB Line Out", NULL, "AOUT4R" },
|
||||
|
||||
{ "AIN1L", NULL, "CPB Stereo Mic 1" },
|
||||
{ "AIN1R", NULL, "CPB Stereo Mic 1" },
|
||||
{ "AIN2L", NULL, "CPB Stereo Mic 2" },
|
||||
{ "AIN2R", NULL, "CPB Stereo Mic 2" },
|
||||
{ "AIN3L", NULL, "CPB Line In" },
|
||||
{ "AIN3R", NULL, "CPB Line In" },
|
||||
};
|
||||
|
||||
static int avs_pcm3168a_be_fixup(struct snd_soc_pcm_runtime *runtime,
|
||||
struct snd_pcm_hw_params *params)
|
||||
{
|
||||
struct snd_mask *fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
|
||||
|
||||
/* Set SSP to 24 bit. */
|
||||
snd_mask_none(fmt);
|
||||
snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S24_LE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
SND_SOC_DAILINK_DEF(pcm3168a_dac,
|
||||
DAILINK_COMP_ARRAY(COMP_CODEC("i2c-PCM3168A:00", "pcm3168a-dac")));
|
||||
SND_SOC_DAILINK_DEF(pcm3168a_adc,
|
||||
DAILINK_COMP_ARRAY(COMP_CODEC("i2c-PCM3168A:00", "pcm3168a-adc")));
|
||||
SND_SOC_DAILINK_DEF(cpu_ssp0, DAILINK_COMP_ARRAY(COMP_CPU("SSP0 Pin")));
|
||||
SND_SOC_DAILINK_DEF(cpu_ssp2, DAILINK_COMP_ARRAY(COMP_CPU("SSP2 Pin")));
|
||||
|
||||
static int avs_create_dai_links(struct device *dev, struct snd_soc_dai_link **links, int *num_links)
|
||||
{
|
||||
struct snd_soc_dai_link_component *platform;
|
||||
struct snd_soc_dai_link *dl;
|
||||
const int num_dl = 2;
|
||||
|
||||
dl = devm_kcalloc(dev, num_dl, sizeof(*dl), GFP_KERNEL);
|
||||
platform = devm_kzalloc(dev, sizeof(*platform), GFP_KERNEL);
|
||||
if (!dl || !platform)
|
||||
return -ENOMEM;
|
||||
|
||||
platform->name = dev_name(dev);
|
||||
dl[0].num_cpus = 1;
|
||||
dl[0].num_codecs = 1;
|
||||
dl[0].platforms = platform;
|
||||
dl[0].num_platforms = 1;
|
||||
dl[0].dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBP_CFP;
|
||||
dl[0].be_hw_params_fixup = avs_pcm3168a_be_fixup;
|
||||
dl[0].nonatomic = 1;
|
||||
dl[0].no_pcm = 1;
|
||||
memcpy(&dl[1], &dl[0], sizeof(*dl));
|
||||
|
||||
dl[0].name = "SSP0-Codec-dac";
|
||||
dl[0].cpus = cpu_ssp0;
|
||||
dl[0].codecs = pcm3168a_dac;
|
||||
dl[1].name = "SSP2-Codec-adc";
|
||||
dl[1].cpus = cpu_ssp2;
|
||||
dl[1].codecs = pcm3168a_adc;
|
||||
|
||||
*links = dl;
|
||||
*num_links = num_dl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int avs_pcm3168a_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct snd_soc_card *card;
|
||||
int ret;
|
||||
|
||||
card = devm_kzalloc(dev, sizeof(*card), GFP_KERNEL);
|
||||
if (!card)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = avs_create_dai_links(dev, &card->dai_link, &card->num_links);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
card->name = "avs_pcm3168a";
|
||||
card->dev = dev;
|
||||
card->owner = THIS_MODULE;
|
||||
card->dapm_widgets = card_widgets;
|
||||
card->num_dapm_widgets = ARRAY_SIZE(card_widgets);
|
||||
card->dapm_routes = card_routes;
|
||||
card->num_dapm_routes = ARRAY_SIZE(card_routes);
|
||||
card->fully_routed = true;
|
||||
|
||||
return devm_snd_soc_register_card(dev, card);
|
||||
}
|
||||
|
||||
static const struct platform_device_id avs_pcm3168a_driver_ids[] = {
|
||||
{
|
||||
.name = "avs_pcm3168a",
|
||||
},
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(platform, avs_pcm3168a_driver_ids);
|
||||
|
||||
static struct platform_driver avs_pcm3168a_driver = {
|
||||
.probe = avs_pcm3168a_probe,
|
||||
.driver = {
|
||||
.name = "avs_pcm3168a",
|
||||
.pm = &snd_soc_pm_ops,
|
||||
},
|
||||
.id_table = avs_pcm3168a_driver_ids,
|
||||
};
|
||||
|
||||
module_platform_driver(avs_pcm3168a_driver);
|
||||
|
||||
MODULE_DESCRIPTION("Intel pcm3168a machine driver");
|
||||
MODULE_AUTHOR("Cezary Rojewski <cezary.rojewski@intel.com>");
|
||||
MODULE_LICENSE("GPL");
|
||||
@@ -603,7 +603,7 @@ release_fw:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int avs_dsp_boot_firmware(struct avs_dev *adev, bool purge)
|
||||
static int avs_load_firmware(struct avs_dev *adev, bool purge)
|
||||
{
|
||||
struct avs_soc_component *acomp;
|
||||
int ret, i;
|
||||
@@ -657,29 +657,34 @@ reenable_gating:
|
||||
return 0;
|
||||
}
|
||||
|
||||
int avs_dsp_first_boot_firmware(struct avs_dev *adev)
|
||||
static int avs_config_basefw(struct avs_dev *adev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (adev->spec->dsp_ops->config_basefw) {
|
||||
ret = avs_dsp_op(adev, config_basefw);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int avs_dsp_boot_firmware(struct avs_dev *adev, bool purge)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = avs_load_firmware(adev, purge);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return avs_config_basefw(adev);
|
||||
}
|
||||
|
||||
static int avs_dsp_alloc_resources(struct avs_dev *adev)
|
||||
{
|
||||
int ret, i;
|
||||
|
||||
if (avs_platattr_test(adev, CLDMA)) {
|
||||
ret = hda_cldma_init(&code_loader, &adev->base.core,
|
||||
adev->dsp_ba, AVS_CL_DEFAULT_BUFFER_SIZE);
|
||||
if (ret < 0) {
|
||||
dev_err(adev->dev, "cldma init failed: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
ret = avs_dsp_core_disable(adev, AVS_MAIN_CORE_MASK);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = avs_dsp_boot_firmware(adev, true);
|
||||
if (ret < 0) {
|
||||
dev_err(adev->dev, "firmware boot failed: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = avs_ipc_get_hw_config(adev, &adev->hw_cfg);
|
||||
if (ret)
|
||||
return AVS_IPC_RET(ret);
|
||||
@@ -705,6 +710,31 @@ int avs_dsp_first_boot_firmware(struct avs_dev *adev)
|
||||
strscpy(adev->lib_names[0], "BASEFW", AVS_LIB_NAME_SIZE);
|
||||
|
||||
ida_init(&adev->ppl_ida);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int avs_dsp_first_boot_firmware(struct avs_dev *adev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (avs_platattr_test(adev, CLDMA)) {
|
||||
ret = hda_cldma_init(&code_loader, &adev->base.core,
|
||||
adev->dsp_ba, AVS_CL_DEFAULT_BUFFER_SIZE);
|
||||
if (ret < 0) {
|
||||
dev_err(adev->dev, "cldma init failed: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
ret = avs_dsp_core_disable(adev, AVS_MAIN_CORE_MASK);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = avs_dsp_boot_firmware(adev, true);
|
||||
if (ret < 0) {
|
||||
dev_err(adev->dev, "firmware boot failed: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return avs_dsp_alloc_resources(adev);
|
||||
}
|
||||
|
||||
@@ -510,6 +510,44 @@ err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int avs_ipc_set_fw_config(struct avs_dev *adev, size_t num_tlvs, ...)
|
||||
{
|
||||
struct avs_tlv *tlv;
|
||||
void *payload;
|
||||
size_t offset;
|
||||
va_list args;
|
||||
int ret, i;
|
||||
|
||||
payload = kzalloc(AVS_MAILBOX_SIZE, GFP_KERNEL);
|
||||
if (!payload)
|
||||
return -ENOMEM;
|
||||
|
||||
va_start(args, num_tlvs);
|
||||
for (offset = i = 0; i < num_tlvs && offset < AVS_MAILBOX_SIZE - sizeof(*tlv); i++) {
|
||||
tlv = (struct avs_tlv *)(payload + offset);
|
||||
tlv->type = va_arg(args, u32);
|
||||
tlv->length = va_arg(args, u32);
|
||||
|
||||
offset += sizeof(*tlv) + tlv->length;
|
||||
if (offset > AVS_MAILBOX_SIZE)
|
||||
break;
|
||||
|
||||
memcpy(tlv->value, va_arg(args, u8*), tlv->length);
|
||||
}
|
||||
|
||||
if (i == num_tlvs)
|
||||
ret = avs_ipc_set_large_config(adev, AVS_BASEFW_MOD_ID, AVS_BASEFW_INST_ID,
|
||||
AVS_BASEFW_FIRMWARE_CONFIG, payload, offset);
|
||||
else
|
||||
ret = -ERANGE;
|
||||
|
||||
va_end(args);
|
||||
kfree(payload);
|
||||
if (ret)
|
||||
dev_err(adev->dev, "set fw cfg failed: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int avs_ipc_get_hw_config(struct avs_dev *adev, struct avs_hw_cfg *cfg)
|
||||
{
|
||||
struct avs_tlv *tlv;
|
||||
|
||||
@@ -451,6 +451,8 @@ enum avs_fw_cfg_params {
|
||||
AVS_FW_CFG_RESERVED,
|
||||
AVS_FW_CFG_POWER_GATING_POLICY,
|
||||
AVS_FW_CFG_ASSERT_MODE,
|
||||
AVS_FW_CFG_RESERVED2,
|
||||
AVS_FW_CFG_BUS_HARDWARE_ID,
|
||||
};
|
||||
|
||||
struct avs_fw_cfg {
|
||||
@@ -475,7 +477,14 @@ struct avs_fw_cfg {
|
||||
u32 power_gating_policy;
|
||||
};
|
||||
|
||||
struct avs_bus_hwid {
|
||||
u32 device;
|
||||
u32 subsystem;
|
||||
u8 revision;
|
||||
};
|
||||
|
||||
int avs_ipc_get_fw_config(struct avs_dev *adev, struct avs_fw_cfg *cfg);
|
||||
int avs_ipc_set_fw_config(struct avs_dev *adev, size_t num_tlvs, ...);
|
||||
|
||||
enum avs_hw_cfg_params {
|
||||
AVS_HW_CFG_AVS_VER,
|
||||
@@ -643,6 +652,9 @@ int avs_ipc_set_system_time(struct avs_dev *adev);
|
||||
#define AVS_INTELWOV_MOD_UUID \
|
||||
GUID_INIT(0xEC774FA9, 0x28D3, 0x424A, 0x90, 0xE4, 0x69, 0xF9, 0x84, 0xF1, 0xEE, 0xB7)
|
||||
|
||||
#define AVS_WOVHOSTM_MOD_UUID \
|
||||
GUID_INIT(0xF9ED62B7, 0x092E, 0x4A90, 0x8F, 0x4D, 0x82, 0xDA, 0xA8, 0xB3, 0x8F, 0x3B)
|
||||
|
||||
/* channel map */
|
||||
enum avs_channel_index {
|
||||
AVS_CHANNEL_LEFT = 0,
|
||||
@@ -872,6 +884,16 @@ struct avs_wov_cfg {
|
||||
} __packed;
|
||||
static_assert(sizeof(struct avs_wov_cfg) == 44);
|
||||
|
||||
struct avs_whm_cfg {
|
||||
struct avs_modcfg_base base;
|
||||
/* Audio format for output pin 0 */
|
||||
struct avs_audio_format ref_fmt;
|
||||
struct avs_audio_format out_fmt;
|
||||
u32 wake_tick_period;
|
||||
struct avs_copier_gtw_cfg gtw_cfg;
|
||||
} __packed;
|
||||
static_assert(sizeof(struct avs_whm_cfg) == 108);
|
||||
|
||||
/* Module runtime parameters */
|
||||
|
||||
enum avs_copier_runtime_param {
|
||||
|
||||
+159
-120
@@ -115,150 +115,188 @@ avs_path_find_variant(struct avs_dev *adev,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
__maybe_unused
|
||||
static bool avs_dma_type_is_host(u32 dma_type)
|
||||
static void avs_init_node_id(union avs_connector_node_id *node_id,
|
||||
struct avs_tplg_modcfg_ext *te, u32 dma_id)
|
||||
{
|
||||
return dma_type == AVS_DMA_HDA_HOST_OUTPUT ||
|
||||
dma_type == AVS_DMA_HDA_HOST_INPUT;
|
||||
node_id->val = 0;
|
||||
node_id->dma_type = te->copier.dma_type;
|
||||
|
||||
switch (node_id->dma_type) {
|
||||
case AVS_DMA_DMIC_LINK_INPUT:
|
||||
case AVS_DMA_I2S_LINK_OUTPUT:
|
||||
case AVS_DMA_I2S_LINK_INPUT:
|
||||
/* Gateway's virtual index is statically assigned in the topology. */
|
||||
node_id->vindex = te->copier.vindex.val;
|
||||
break;
|
||||
|
||||
case AVS_DMA_HDA_HOST_OUTPUT:
|
||||
case AVS_DMA_HDA_HOST_INPUT:
|
||||
/* Gateway's virtual index is dynamically assigned with DMA ID */
|
||||
node_id->vindex = dma_id;
|
||||
break;
|
||||
|
||||
case AVS_DMA_HDA_LINK_OUTPUT:
|
||||
case AVS_DMA_HDA_LINK_INPUT:
|
||||
node_id->vindex = te->copier.vindex.val | dma_id;
|
||||
break;
|
||||
|
||||
default:
|
||||
*node_id = INVALID_NODE_ID;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
__maybe_unused
|
||||
static bool avs_dma_type_is_link(u32 dma_type)
|
||||
/* Every BLOB contains at least gateway attributes. */
|
||||
static struct acpi_nhlt_config *default_blob = (struct acpi_nhlt_config *)&(u32[2]) {4};
|
||||
|
||||
static struct acpi_nhlt_config *
|
||||
avs_nhlt_config_or_default(struct avs_dev *adev, struct avs_tplg_module *t)
|
||||
{
|
||||
return !avs_dma_type_is_host(dma_type);
|
||||
struct acpi_nhlt_format_config *fmtcfg;
|
||||
struct avs_tplg_modcfg_ext *te;
|
||||
struct avs_audio_format *fmt;
|
||||
int link_type, dev_type;
|
||||
int bus_id, dir;
|
||||
|
||||
te = t->cfg_ext;
|
||||
|
||||
switch (te->copier.dma_type) {
|
||||
case AVS_DMA_I2S_LINK_OUTPUT:
|
||||
link_type = ACPI_NHLT_LINKTYPE_SSP;
|
||||
dev_type = ACPI_NHLT_DEVICETYPE_CODEC;
|
||||
bus_id = te->copier.vindex.i2s.instance;
|
||||
dir = SNDRV_PCM_STREAM_PLAYBACK;
|
||||
fmt = te->copier.out_fmt;
|
||||
break;
|
||||
|
||||
case AVS_DMA_I2S_LINK_INPUT:
|
||||
link_type = ACPI_NHLT_LINKTYPE_SSP;
|
||||
dev_type = ACPI_NHLT_DEVICETYPE_CODEC;
|
||||
bus_id = te->copier.vindex.i2s.instance;
|
||||
dir = SNDRV_PCM_STREAM_CAPTURE;
|
||||
fmt = t->in_fmt;
|
||||
break;
|
||||
|
||||
case AVS_DMA_DMIC_LINK_INPUT:
|
||||
link_type = ACPI_NHLT_LINKTYPE_PDM;
|
||||
dev_type = -1; /* ignored */
|
||||
bus_id = 0;
|
||||
dir = SNDRV_PCM_STREAM_CAPTURE;
|
||||
fmt = t->in_fmt;
|
||||
break;
|
||||
|
||||
default:
|
||||
return default_blob;
|
||||
}
|
||||
|
||||
/* Override format selection if necessary. */
|
||||
if (te->copier.blob_fmt)
|
||||
fmt = te->copier.blob_fmt;
|
||||
|
||||
fmtcfg = acpi_nhlt_find_fmtcfg(link_type, dev_type, dir, bus_id,
|
||||
fmt->num_channels, fmt->sampling_freq, fmt->valid_bit_depth,
|
||||
fmt->bit_depth);
|
||||
if (!fmtcfg) {
|
||||
dev_warn(adev->dev, "Endpoint format configuration not found.\n");
|
||||
return ERR_PTR(-ENOENT);
|
||||
}
|
||||
|
||||
if (fmtcfg->config.capabilities_size < default_blob->capabilities_size)
|
||||
return ERR_PTR(-ETOOSMALL);
|
||||
/* The firmware expects the payload to be DWORD-aligned. */
|
||||
if (fmtcfg->config.capabilities_size % sizeof(u32))
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
return &fmtcfg->config;
|
||||
}
|
||||
|
||||
__maybe_unused
|
||||
static bool avs_dma_type_is_output(u32 dma_type)
|
||||
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)
|
||||
{
|
||||
return dma_type == AVS_DMA_HDA_HOST_OUTPUT ||
|
||||
dma_type == AVS_DMA_HDA_LINK_OUTPUT ||
|
||||
dma_type == AVS_DMA_I2S_LINK_OUTPUT;
|
||||
}
|
||||
struct acpi_nhlt_config *blob;
|
||||
size_t gtw_size;
|
||||
|
||||
__maybe_unused
|
||||
static bool avs_dma_type_is_input(u32 dma_type)
|
||||
{
|
||||
return !avs_dma_type_is_output(dma_type);
|
||||
blob = avs_nhlt_config_or_default(adev, t);
|
||||
if (IS_ERR(blob))
|
||||
return PTR_ERR(blob);
|
||||
|
||||
gtw_size = blob->capabilities_size;
|
||||
if (*cfg_size + gtw_size > AVS_MAILBOX_SIZE)
|
||||
return -E2BIG;
|
||||
|
||||
gtw->config_length = gtw_size / sizeof(u32);
|
||||
memcpy(gtw->config.blob, blob->capabilities, blob->capabilities_size);
|
||||
*cfg_size += gtw_size;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int avs_copier_create(struct avs_dev *adev, struct avs_path_module *mod)
|
||||
{
|
||||
struct avs_tplg_module *t = mod->template;
|
||||
struct avs_tplg_modcfg_ext *te;
|
||||
struct avs_copier_cfg *cfg;
|
||||
struct acpi_nhlt_format_config *ep_blob;
|
||||
struct acpi_nhlt_endpoint *ep;
|
||||
union avs_connector_node_id node_id = {0};
|
||||
size_t cfg_size, data_size;
|
||||
void *data = NULL;
|
||||
u32 dma_type;
|
||||
size_t cfg_size;
|
||||
u32 dma_id;
|
||||
int ret;
|
||||
|
||||
data_size = sizeof(cfg->gtw_cfg.config);
|
||||
dma_type = t->cfg_ext->copier.dma_type;
|
||||
node_id.dma_type = dma_type;
|
||||
|
||||
switch (dma_type) {
|
||||
struct avs_audio_format *fmt;
|
||||
int direction;
|
||||
|
||||
case AVS_DMA_I2S_LINK_OUTPUT:
|
||||
case AVS_DMA_I2S_LINK_INPUT:
|
||||
if (avs_dma_type_is_input(dma_type))
|
||||
direction = SNDRV_PCM_STREAM_CAPTURE;
|
||||
else
|
||||
direction = SNDRV_PCM_STREAM_PLAYBACK;
|
||||
|
||||
if (t->cfg_ext->copier.blob_fmt)
|
||||
fmt = t->cfg_ext->copier.blob_fmt;
|
||||
else if (direction == SNDRV_PCM_STREAM_CAPTURE)
|
||||
fmt = t->in_fmt;
|
||||
else
|
||||
fmt = t->cfg_ext->copier.out_fmt;
|
||||
|
||||
ep = acpi_nhlt_find_endpoint(ACPI_NHLT_LINKTYPE_SSP,
|
||||
ACPI_NHLT_DEVICETYPE_CODEC, direction,
|
||||
t->cfg_ext->copier.vindex.i2s.instance);
|
||||
ep_blob = acpi_nhlt_endpoint_find_fmtcfg(ep, fmt->num_channels, fmt->sampling_freq,
|
||||
fmt->valid_bit_depth, fmt->bit_depth);
|
||||
if (!ep_blob) {
|
||||
dev_err(adev->dev, "no I2S ep_blob found\n");
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
data = ep_blob->config.capabilities;
|
||||
data_size = ep_blob->config.capabilities_size;
|
||||
/* I2S gateway's vindex is statically assigned in topology */
|
||||
node_id.vindex = t->cfg_ext->copier.vindex.val;
|
||||
|
||||
break;
|
||||
|
||||
case AVS_DMA_DMIC_LINK_INPUT:
|
||||
direction = SNDRV_PCM_STREAM_CAPTURE;
|
||||
|
||||
if (t->cfg_ext->copier.blob_fmt)
|
||||
fmt = t->cfg_ext->copier.blob_fmt;
|
||||
else
|
||||
fmt = t->in_fmt;
|
||||
|
||||
ep = acpi_nhlt_find_endpoint(ACPI_NHLT_LINKTYPE_PDM, -1, direction, 0);
|
||||
ep_blob = acpi_nhlt_endpoint_find_fmtcfg(ep, fmt->num_channels, fmt->sampling_freq,
|
||||
fmt->valid_bit_depth, fmt->bit_depth);
|
||||
if (!ep_blob) {
|
||||
dev_err(adev->dev, "no DMIC ep_blob found\n");
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
data = ep_blob->config.capabilities;
|
||||
data_size = ep_blob->config.capabilities_size;
|
||||
/* DMIC gateway's vindex is statically assigned in topology */
|
||||
node_id.vindex = t->cfg_ext->copier.vindex.val;
|
||||
|
||||
break;
|
||||
|
||||
case AVS_DMA_HDA_HOST_OUTPUT:
|
||||
case AVS_DMA_HDA_HOST_INPUT:
|
||||
/* HOST gateway's vindex is dynamically assigned with DMA id */
|
||||
node_id.vindex = mod->owner->owner->dma_id;
|
||||
break;
|
||||
|
||||
case AVS_DMA_HDA_LINK_OUTPUT:
|
||||
case AVS_DMA_HDA_LINK_INPUT:
|
||||
node_id.vindex = t->cfg_ext->copier.vindex.val |
|
||||
mod->owner->owner->dma_id;
|
||||
break;
|
||||
|
||||
case INVALID_OBJECT_ID:
|
||||
default:
|
||||
node_id = INVALID_NODE_ID;
|
||||
break;
|
||||
}
|
||||
|
||||
cfg_size = offsetof(struct avs_copier_cfg, gtw_cfg.config) + data_size;
|
||||
if (cfg_size > AVS_MAILBOX_SIZE)
|
||||
return -EINVAL;
|
||||
|
||||
te = t->cfg_ext;
|
||||
cfg = adev->modcfg_buf;
|
||||
memset(cfg, 0, cfg_size);
|
||||
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);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
cfg->base.cpc = t->cfg_base->cpc;
|
||||
cfg->base.ibs = t->cfg_base->ibs;
|
||||
cfg->base.obs = t->cfg_base->obs;
|
||||
cfg->base.is_pages = t->cfg_base->is_pages;
|
||||
cfg->base.audio_fmt = *t->in_fmt;
|
||||
cfg->out_fmt = *t->cfg_ext->copier.out_fmt;
|
||||
cfg->feature_mask = t->cfg_ext->copier.feature_mask;
|
||||
cfg->gtw_cfg.node_id = node_id;
|
||||
cfg->gtw_cfg.dma_buffer_size = t->cfg_ext->copier.dma_buffer_size;
|
||||
/* config_length in DWORDs */
|
||||
cfg->gtw_cfg.config_length = DIV_ROUND_UP(data_size, 4);
|
||||
if (data)
|
||||
memcpy(&cfg->gtw_cfg.config.blob, data, data_size);
|
||||
|
||||
cfg->out_fmt = *te->copier.out_fmt;
|
||||
cfg->feature_mask = te->copier.feature_mask;
|
||||
avs_init_node_id(&cfg->gtw_cfg.node_id, te, dma_id);
|
||||
cfg->gtw_cfg.dma_buffer_size = te->copier.dma_buffer_size;
|
||||
mod->gtw_attrs = cfg->gtw_cfg.config.attrs;
|
||||
|
||||
ret = avs_dsp_init_module(adev, mod->module_id, mod->owner->instance_id,
|
||||
t->core_id, t->domain, cfg, cfg_size,
|
||||
&mod->instance_id);
|
||||
ret = avs_dsp_init_module(adev, mod->module_id, mod->owner->instance_id, t->core_id,
|
||||
t->domain, cfg, cfg_size, &mod->instance_id);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int avs_whm_create(struct avs_dev *adev, struct avs_path_module *mod)
|
||||
{
|
||||
struct avs_tplg_module *t = mod->template;
|
||||
struct avs_tplg_modcfg_ext *te;
|
||||
struct avs_whm_cfg *cfg;
|
||||
size_t cfg_size;
|
||||
u32 dma_id;
|
||||
int ret;
|
||||
|
||||
te = t->cfg_ext;
|
||||
cfg = adev->modcfg_buf;
|
||||
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);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
cfg->base.cpc = t->cfg_base->cpc;
|
||||
cfg->base.ibs = t->cfg_base->ibs;
|
||||
cfg->base.obs = t->cfg_base->obs;
|
||||
cfg->base.is_pages = t->cfg_base->is_pages;
|
||||
cfg->base.audio_fmt = *t->in_fmt;
|
||||
cfg->ref_fmt = *te->whm.ref_fmt;
|
||||
cfg->out_fmt = *te->whm.out_fmt;
|
||||
cfg->wake_tick_period = te->whm.wake_tick_period;
|
||||
avs_init_node_id(&cfg->gtw_cfg.node_id, te, dma_id);
|
||||
cfg->gtw_cfg.dma_buffer_size = te->whm.dma_buffer_size;
|
||||
mod->gtw_attrs = cfg->gtw_cfg.config.attrs;
|
||||
|
||||
ret = avs_dsp_init_module(adev, mod->module_id, mod->owner->instance_id, t->core_id,
|
||||
t->domain, cfg, cfg_size, &mod->instance_id);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -533,6 +571,7 @@ static struct avs_module_create avs_module_create[] = {
|
||||
{ &AVS_ASRC_MOD_UUID, avs_asrc_create },
|
||||
{ &AVS_INTELWOV_MOD_UUID, avs_wov_create },
|
||||
{ &AVS_PROBE_MOD_UUID, avs_probe_create },
|
||||
{ &AVS_WOVHOSTM_MOD_UUID, avs_whm_create },
|
||||
};
|
||||
|
||||
static int avs_path_module_type_create(struct avs_dev *adev, struct avs_path_module *mod)
|
||||
|
||||
@@ -6,7 +6,11 @@
|
||||
// Amadeusz Slawinski <amadeuszx.slawinski@linux.intel.com>
|
||||
//
|
||||
|
||||
#include <linux/pci.h>
|
||||
#include "avs.h"
|
||||
#include "messages.h"
|
||||
|
||||
#define CPUID_TSC_LEAF 0x15
|
||||
|
||||
static int avs_tgl_dsp_core_power(struct avs_dev *adev, u32 core_mask, bool power)
|
||||
{
|
||||
@@ -35,6 +39,34 @@ static int avs_tgl_dsp_core_stall(struct avs_dev *adev, u32 core_mask, bool stal
|
||||
return avs_dsp_core_stall(adev, core_mask, stall);
|
||||
}
|
||||
|
||||
static int avs_tgl_config_basefw(struct avs_dev *adev)
|
||||
{
|
||||
struct pci_dev *pci = adev->base.pci;
|
||||
struct avs_bus_hwid hwid;
|
||||
int ret;
|
||||
#ifdef CONFIG_X86
|
||||
unsigned int ecx;
|
||||
|
||||
#include <asm/cpuid.h>
|
||||
ecx = cpuid_ecx(CPUID_TSC_LEAF);
|
||||
if (ecx) {
|
||||
ret = avs_ipc_set_fw_config(adev, 1, AVS_FW_CFG_XTAL_FREQ_HZ, sizeof(ecx), &ecx);
|
||||
if (ret)
|
||||
return AVS_IPC_RET(ret);
|
||||
}
|
||||
#endif
|
||||
|
||||
hwid.device = pci->device;
|
||||
hwid.subsystem = pci->subsystem_vendor | (pci->subsystem_device << 16);
|
||||
hwid.revision = pci->revision;
|
||||
|
||||
ret = avs_ipc_set_fw_config(adev, 1, AVS_FW_CFG_BUS_HARDWARE_ID, sizeof(hwid), &hwid);
|
||||
if (ret)
|
||||
return AVS_IPC_RET(ret);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct avs_dsp_ops avs_tgl_dsp_ops = {
|
||||
.power = avs_tgl_dsp_core_power,
|
||||
.reset = avs_tgl_dsp_core_reset,
|
||||
@@ -44,6 +76,7 @@ const struct avs_dsp_ops avs_tgl_dsp_ops = {
|
||||
.load_basefw = avs_icl_load_basefw,
|
||||
.load_lib = avs_hda_load_library,
|
||||
.transfer_mods = avs_hda_transfer_modules,
|
||||
.config_basefw = avs_tgl_config_basefw,
|
||||
.log_buffer_offset = avs_icl_log_buffer_offset,
|
||||
.log_buffer_status = avs_apl_log_buffer_status,
|
||||
.coredump = avs_apl_coredump,
|
||||
|
||||
@@ -815,6 +815,48 @@ static const struct avs_tplg_token_parser modcfg_ext_parsers[] = {
|
||||
.offset = offsetof(struct avs_tplg_modcfg_ext, generic.num_output_pins),
|
||||
.parse = avs_parse_short_token,
|
||||
},
|
||||
{
|
||||
.token = AVS_TKN_MODCFG_WHM_REF_AFMT_ID_U32,
|
||||
.type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
|
||||
.offset = offsetof(struct avs_tplg_modcfg_ext, whm.ref_fmt),
|
||||
.parse = avs_parse_audio_format_ptr,
|
||||
},
|
||||
{
|
||||
.token = AVS_TKN_MODCFG_WHM_OUT_AFMT_ID_U32,
|
||||
.type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
|
||||
.offset = offsetof(struct avs_tplg_modcfg_ext, whm.out_fmt),
|
||||
.parse = avs_parse_audio_format_ptr,
|
||||
},
|
||||
{
|
||||
.token = AVS_TKN_MODCFG_WHM_WAKE_TICK_PERIOD_U32,
|
||||
.type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
|
||||
.offset = offsetof(struct avs_tplg_modcfg_ext, whm.wake_tick_period),
|
||||
.parse = avs_parse_word_token,
|
||||
},
|
||||
{
|
||||
.token = AVS_TKN_MODCFG_WHM_VINDEX_U8,
|
||||
.type = SND_SOC_TPLG_TUPLE_TYPE_BYTE,
|
||||
.offset = offsetof(struct avs_tplg_modcfg_ext, whm.vindex),
|
||||
.parse = avs_parse_byte_token,
|
||||
},
|
||||
{
|
||||
.token = AVS_TKN_MODCFG_WHM_DMA_TYPE_U32,
|
||||
.type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
|
||||
.offset = offsetof(struct avs_tplg_modcfg_ext, whm.dma_type),
|
||||
.parse = avs_parse_word_token,
|
||||
},
|
||||
{
|
||||
.token = AVS_TKN_MODCFG_WHM_DMABUFF_SIZE_U32,
|
||||
.type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
|
||||
.offset = offsetof(struct avs_tplg_modcfg_ext, whm.dma_buffer_size),
|
||||
.parse = avs_parse_word_token,
|
||||
},
|
||||
{
|
||||
.token = AVS_TKN_MODCFG_WHM_BLOB_AFMT_ID_U32,
|
||||
.type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
|
||||
.offset = offsetof(struct avs_tplg_modcfg_ext, whm.blob_fmt),
|
||||
.parse = avs_parse_audio_format_ptr,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct avs_tplg_token_parser pin_format_parsers[] = {
|
||||
|
||||
@@ -74,9 +74,16 @@ struct avs_tplg_modcfg_ext {
|
||||
union avs_virtual_index vindex;
|
||||
u32 dma_type;
|
||||
u32 dma_buffer_size;
|
||||
u32 config_length;
|
||||
/* config_data part of priv data */
|
||||
} copier;
|
||||
struct {
|
||||
struct avs_audio_format *ref_fmt;
|
||||
struct avs_audio_format *out_fmt;
|
||||
u32 wake_tick_period;
|
||||
union avs_virtual_index vindex;
|
||||
u32 dma_type;
|
||||
u32 dma_buffer_size;
|
||||
struct avs_audio_format *blob_fmt; /* optional override */
|
||||
} whm;
|
||||
struct {
|
||||
u32 out_channel_config;
|
||||
u32 coefficients_select;
|
||||
|
||||
Reference in New Issue
Block a user