Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions sound/soc/intel/common/soc-acpi-intel-ptl-match.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,12 +51,14 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_ptl_machines[] = {
.drv_name = "ptl_es83x6_c1_h02",
.machine_quirk = snd_soc_acpi_codec_list,
.quirk_data = &ptl_lt6911_hdmi,
.get_function_tplg_files = sof_i2s_get_tplg_files,
.sof_tplg_filename = "sof-ptl-es83x6-ssp1-hdmi-ssp02.tplg",
},
{
.comp_ids = &ptl_essx_83x6,
.drv_name = "sof-essx8336",
.sof_tplg_filename = "sof-ptl-es8336", /* the tplg suffix is added at run time */
.get_function_tplg_files = sof_i2s_get_tplg_files,
.tplg_quirk_mask = SND_SOC_ACPI_TPLG_INTEL_SSP_NUMBER |
SND_SOC_ACPI_TPLG_INTEL_SSP_MSB |
SND_SOC_ACPI_TPLG_INTEL_DMIC_NUMBER,
Expand Down
263 changes: 226 additions & 37 deletions sound/soc/intel/common/sof-function-topology-lib.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ enum tplg_device_id {
TPLG_DEVICE_SDCA_MIC,
TPLG_DEVICE_INTEL_PCH_DMIC,
TPLG_DEVICE_HDMI,
TPLG_DEVICE_SSP_JACK,
TPLG_DEVICE_SSP_AMP,
TPLG_DEVICE_SSP_BT,
TPLG_DEVICE_SSP_HDMI_IN,
TPLG_DEVICE_MAX
};

Expand All @@ -27,25 +31,88 @@ enum tplg_device_id {

#define SOF_INTEL_PLATFORM_NAME_MAX 4

static int get_platform_name(struct snd_soc_card *card,
const struct snd_soc_acpi_mach *mach, char *platform)
{
int ret;

ret = sscanf(mach->sof_tplg_filename, "sof-%3s-*.tplg", platform);
if (ret != 1) {
dev_err(card->dev, "Invalid platform name %s of tplg %s\n",
platform, mach->sof_tplg_filename);
return -EINVAL;
}

return 0;
}

static bool all_tplg_files_exist(struct device *dev, const char ***tplg_files, int tplg_num)
{
const struct firmware *fw;
int ret;
int i;

for (i = 0; i < tplg_num; i++) {
ret = firmware_request_nowarn(&fw, (*tplg_files)[i], dev);
if (!ret) {
release_firmware(fw);
} else {
dev_warn(dev,
"Failed to open topology file: %s, you might need to\n",
(*tplg_files)[i]);
dev_warn(dev,
"download it from https://github.com/thesofproject/sof-bin/\n");
return false;
}
}

return true;
}

static char *get_tplg_filename(struct device *dev, const char *prefix,
const char *platform, const char *tplg_dev_name,
int dai_link_id, int tplg_dev)
{
char *filename = NULL;
/*
* The tplg file naming rule is sof-<platform>-<function>-id<BE id number>.tplg
* where <platform> is only required for the devices that need NHLT blob like DMIC
* as the nhlt blob is platform dependent.
*/
switch (tplg_dev) {
case TPLG_DEVICE_INTEL_PCH_DMIC:
case TPLG_DEVICE_SSP_JACK:
case TPLG_DEVICE_SSP_AMP:
case TPLG_DEVICE_SSP_BT:
case TPLG_DEVICE_SSP_HDMI_IN:
filename = devm_kasprintf(dev, GFP_KERNEL, "%s/sof-%s-%s-id%d.tplg",
prefix, platform, tplg_dev_name, dai_link_id);
break;
default:
filename = devm_kasprintf(dev, GFP_KERNEL, "%s/sof-%s-id%d.tplg",
prefix, tplg_dev_name, dai_link_id);
break;
}

return filename;
}

int sof_sdw_get_tplg_files(struct snd_soc_card *card, const struct snd_soc_acpi_mach *mach,
const char *prefix, const char ***tplg_files, bool best_effort)
{
struct snd_soc_acpi_mach_params mach_params = mach->mach_params;
struct snd_soc_dai_link *dai_link;
const struct firmware *fw;
char platform[SOF_INTEL_PLATFORM_NAME_MAX];
unsigned long tplg_mask = 0;
u16 hdmi_in_mask = 0;
int tplg_num = 0;
int tplg_dev;
int ret;
int i;

ret = sscanf(mach->sof_tplg_filename, "sof-%3s-*.tplg", platform);
if (ret != 1) {
dev_err(card->dev, "Invalid platform name %s of tplg %s\n",
platform, mach->sof_tplg_filename);
return -EINVAL;
}
ret = get_platform_name(card, mach, platform);
if (ret < 0)
return ret;

for_each_card_prelinks(card, i, dai_link) {
char *tplg_dev_name;
Expand Down Expand Up @@ -82,6 +149,45 @@ int sof_sdw_get_tplg_files(struct snd_soc_card *card, const struct snd_soc_acpi_
tplg_dev = TPLG_DEVICE_HDMI;
tplg_dev_name = "hdmi-pcm5";

} else if (strstr(dai_link->name, "SSP")) {
unsigned int ssp_port;

if (sscanf(dai_link->name, "SSP%d", &ssp_port) != 1) {
dev_err(card->dev, "Invalid SSP port %d\n", ssp_port);
return -EINVAL;
}
if (strstr(dai_link->name, "Codec")) {
/*
* Assume DAI link 0 is jack which is true in all existing
* machine driver
*/
if (dai_link->id == 0) {
tplg_dev = TPLG_DEVICE_SSP_JACK;
tplg_dev_name = devm_kasprintf(card->dev, GFP_KERNEL,
"ssp%d-jack", ssp_port);
} else {
tplg_dev = TPLG_DEVICE_SSP_AMP;
tplg_dev_name = devm_kasprintf(card->dev, GFP_KERNEL,
"ssp%d-amp", ssp_port);
}
} else if (strstr(dai_link->name, "BT")) {
tplg_dev = TPLG_DEVICE_SSP_BT;
tplg_dev_name = devm_kasprintf(card->dev, GFP_KERNEL,
"ssp%d-bt", ssp_port);
} else if (strstr(dai_link->name, "HDMI")) {
hdmi_in_mask |= BIT(ssp_port);
/* The number of HDMI in dai link is always 2 right now */
if (hweight16(hdmi_in_mask) != 2)
continue;

tplg_dev = TPLG_DEVICE_SSP_HDMI_IN;
tplg_dev_name = devm_kasprintf(card->dev, GFP_KERNEL,
"ssp%x-hdmiin", hdmi_in_mask);
} else {
dev_warn(card->dev,
"unsupported SSP link %s\n", dai_link->name);
continue;
}
} else {
/* The dai link is not supported by separated tplg yet */
dev_dbg(card->dev,
Expand All @@ -97,25 +203,9 @@ int sof_sdw_get_tplg_files(struct snd_soc_card *card, const struct snd_soc_acpi_

tplg_mask |= BIT(tplg_dev);

/*
* The tplg file naming rule is sof-<platform>-<function>-id<BE id number>.tplg
* where <platform> is only required for the DMIC function as the nhlt blob
* is platform dependent.
*/
switch (tplg_dev) {
case TPLG_DEVICE_INTEL_PCH_DMIC:
(*tplg_files)[tplg_num] = devm_kasprintf(card->dev, GFP_KERNEL,
"%s/sof-%s-%s-id%d.tplg",
prefix, platform,
tplg_dev_name, dai_link->id);
break;
default:
(*tplg_files)[tplg_num] = devm_kasprintf(card->dev, GFP_KERNEL,
"%s/sof-%s-id%d.tplg",
prefix, tplg_dev_name,
dai_link->id);
break;
}
(*tplg_files)[tplg_num] = get_tplg_filename(card->dev, prefix, platform,
tplg_dev_name, dai_link->id,
tplg_dev);
if (!(*tplg_files)[tplg_num])
return -ENOMEM;
tplg_num++;
Expand All @@ -124,20 +214,119 @@ int sof_sdw_get_tplg_files(struct snd_soc_card *card, const struct snd_soc_acpi_
dev_dbg(card->dev, "tplg_mask %#lx tplg_num %d\n", tplg_mask, tplg_num);

/* Check presence of sub-topologies */
for (i = 0; i < tplg_num; i++) {
ret = firmware_request_nowarn(&fw, (*tplg_files)[i], card->dev);
if (!ret) {
release_firmware(fw);
if (all_tplg_files_exist(card->dev, tplg_files, tplg_num))
return tplg_num;

/* return 0 to use monolithic topology */
return 0;
}
EXPORT_SYMBOL_GPL(sof_sdw_get_tplg_files);

int sof_i2s_get_tplg_files(struct snd_soc_card *card, const struct snd_soc_acpi_mach *mach,
const char *prefix, const char ***tplg_files, bool best_effort)
{
struct snd_soc_acpi_mach_params mach_params = mach->mach_params;
struct snd_soc_dai_link *dai_link;
char platform[SOF_INTEL_PLATFORM_NAME_MAX];
unsigned long tplg_mask = 0;
u16 hdmi_in_mask = 0;
int tplg_num = 0;
int tplg_dev;
int ret;
int i;

ret = get_platform_name(card, mach, platform);
if (ret < 0)
return ret;

for_each_card_prelinks(card, i, dai_link) {
char *tplg_dev_name;

dev_dbg(card->dev, "dai_link %s id %d\n", dai_link->name, dai_link->id);
if (strstr(dai_link->name, "SSP")) {
unsigned int ssp_port;

if (sscanf(dai_link->name, "SSP%d", &ssp_port) != 1) {
dev_err(card->dev, "Invalid SSP port %d\n", ssp_port);
return -EINVAL;
}
if (strstr(dai_link->name, "Codec")) {
/*
* Assume DAI link 0 is jack which is true in all existing
* machine driver
*/
if (dai_link->id == 0) {
tplg_dev = TPLG_DEVICE_SSP_JACK;
tplg_dev_name = devm_kasprintf(card->dev, GFP_KERNEL,
"ssp%d-jack", ssp_port);
} else {
tplg_dev = TPLG_DEVICE_SSP_AMP;
tplg_dev_name = devm_kasprintf(card->dev, GFP_KERNEL,
"ssp%d-amp", ssp_port);
}
} else if (strstr(dai_link->name, "BT")) {
tplg_dev = TPLG_DEVICE_SSP_BT;
tplg_dev_name = devm_kasprintf(card->dev, GFP_KERNEL,
"ssp%d-bt", ssp_port);
} else if (strstr(dai_link->name, "HDMI")) {
hdmi_in_mask |= BIT(ssp_port);
/* The number of HDMI in dai link is always 2 right now */
if (hweight16(hdmi_in_mask) != 2)
continue;

tplg_dev = TPLG_DEVICE_SSP_HDMI_IN;
tplg_dev_name = devm_kasprintf(card->dev, GFP_KERNEL,
"ssp%x-hdmiin", hdmi_in_mask);
} else {
dev_warn(card->dev,
"unsupported SSP link %s\n", dai_link->name);
continue;
}
} else if (strstr(dai_link->name, "dmic")) {
switch (mach_params.dmic_num) {
case 2:
tplg_dev_name = "dmic-2ch";
break;
case 4:
tplg_dev_name = "dmic-4ch";
break;
default:
dev_warn(card->dev,
"unsupported number of dmics: %d\n",
mach_params.dmic_num);
continue;
}
tplg_dev = TPLG_DEVICE_INTEL_PCH_DMIC;
} else if (strstr(dai_link->name, "iDisp")) {
tplg_dev = TPLG_DEVICE_HDMI;
tplg_dev_name = "hdmi-pcm5";
} else {
dev_warn(card->dev,
"Failed to open topology file: %s, you might need to\n",
(*tplg_files)[i]);
dev_warn(card->dev,
"download it from https://github.com/thesofproject/sof-bin/\n");
/* The dai link is not supported by separated tplg yet */
dev_dbg(card->dev,
"dai_link %s is not supported by separated tplg yet\n",
dai_link->name);
return 0;
}
if (tplg_mask & BIT(tplg_dev))
continue;

tplg_mask |= BIT(tplg_dev);

(*tplg_files)[tplg_num] = get_tplg_filename(card->dev, prefix, platform,
tplg_dev_name, dai_link->id,
tplg_dev);
if (!(*tplg_files)[tplg_num])
return -ENOMEM;
tplg_num++;
}

return tplg_num;
dev_dbg(card->dev, "tplg_mask %#lx tplg_num %d\n", tplg_mask, tplg_num);

/* Check presence of sub-topologies */
if (all_tplg_files_exist(card->dev, tplg_files, tplg_num))
return tplg_num;

/* return 0 to use monolithic topology */
return 0;
}
EXPORT_SYMBOL_GPL(sof_sdw_get_tplg_files);
EXPORT_SYMBOL_GPL(sof_i2s_get_tplg_files);
3 changes: 3 additions & 0 deletions sound/soc/intel/common/sof-function-topology-lib.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,7 @@
int sof_sdw_get_tplg_files(struct snd_soc_card *card, const struct snd_soc_acpi_mach *mach,
const char *prefix, const char ***tplg_files, bool best_effort);

int sof_i2s_get_tplg_files(struct snd_soc_card *card, const struct snd_soc_acpi_mach *mach,
const char *prefix, const char ***tplg_files, bool best_effort);

#endif
18 changes: 15 additions & 3 deletions sound/soc/sof/intel/hda-dai.c
Original file line number Diff line number Diff line change
Expand Up @@ -760,8 +760,15 @@ void hda_set_dai_drv_ops(struct snd_sof_dev *sdev, struct snd_sof_dsp_ops *ops)

if (sdev->pdata->ipc_type == SOF_IPC_TYPE_4 && !hda_use_tplg_nhlt) {
struct sof_ipc4_fw_data *ipc4_data = sdev->private;
struct snd_ipc4_nhlt *nhlt;

ipc4_data->nhlt = intel_nhlt_init(sdev->dev);
nhlt = devm_kzalloc(sdev->dev, sizeof(*nhlt), GFP_KERNEL);
if (!nhlt)
return;

nhlt->nhlt = intel_nhlt_init(sdev->dev);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hrm, does this works? nhlt is a pointer, which has not been initialized. nhlt->nhlt dereferencing a random memory and stores a pointer in random place, corrupting something?


list_add(&nhlt->list, &ipc4_data->nhlt_list);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here.

}
}
EXPORT_SYMBOL_NS(hda_set_dai_drv_ops, "SND_SOC_SOF_INTEL_HDA_COMMON");
Expand All @@ -770,9 +777,14 @@ void hda_ops_free(struct snd_sof_dev *sdev)
{
if (sdev->pdata->ipc_type == SOF_IPC_TYPE_4) {
struct sof_ipc4_fw_data *ipc4_data = sdev->private;
struct snd_ipc4_nhlt *nhlt;

if (!hda_use_tplg_nhlt)
intel_nhlt_free(ipc4_data->nhlt);
if (!hda_use_tplg_nhlt) {
nhlt = list_first_entry(&ipc4_data->nhlt_list,
struct snd_ipc4_nhlt, list);
intel_nhlt_free(nhlt->nhlt);
list_del(&nhlt->list);
}

kfree(sdev->private);
sdev->private = NULL;
Expand Down
1 change: 1 addition & 0 deletions sound/soc/sof/ipc4-loader.c
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ static size_t sof_ipc4_fw_parse_basefw_ext_man(struct snd_sof_dev *sdev)
ssize_t payload_offset;
int ret;

INIT_LIST_HEAD(&ipc4_data->nhlt_list);
if (sdev->dsp_test_mode_enabled)
fw_lib = devm_kzalloc(sdev->dev, sizeof(*fw_lib), GFP_KERNEL);
else
Expand Down
Loading
Loading