Skip to content

Commit 2875745

Browse files
bardliaolgirdwood
authored andcommitted
ASoC: SOF: get nhlt from all topologies
The existing code assumes there is only one NHLT blob either from BIOS or topology. As function topologies are used and each function topology contains a NHLT blob section, we need to search the matching NHLT blob from all the NHLT blobs. The commit suggests adding a list of NHLTs and search the NHLTs from the list. Signed-off-by: Bard Liao <yung-chuan.liao@linux.intel.com>
1 parent f7f2386 commit 2875745

9 files changed

Lines changed: 80 additions & 25 deletions

File tree

sound/soc/sof/intel/apl.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ int sof_apl_ops_init(struct snd_sof_dev *sdev)
5959
return -ENOMEM;
6060

6161
ipc4_data = sdev->private;
62+
INIT_LIST_HEAD(&ipc4_data->nhlt_list);
6263
ipc4_data->manifest_fw_hdr_offset = SOF_MAN4_FW_HDR_OFFSET;
6364

6465
ipc4_data->mtrace_type = SOF_IPC4_MTRACE_INTEL_CAVS_1_5;

sound/soc/sof/intel/cnl.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -406,6 +406,7 @@ int sof_cnl_ops_init(struct snd_sof_dev *sdev)
406406
return -ENOMEM;
407407

408408
ipc4_data = sdev->private;
409+
INIT_LIST_HEAD(&ipc4_data->nhlt_list);
409410
ipc4_data->manifest_fw_hdr_offset = SOF_MAN4_FW_HDR_OFFSET;
410411

411412
ipc4_data->mtrace_type = SOF_IPC4_MTRACE_INTEL_CAVS_1_8;

sound/soc/sof/intel/hda-dai.c

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -760,8 +760,20 @@ void hda_set_dai_drv_ops(struct snd_sof_dev *sdev, struct snd_sof_dsp_ops *ops)
760760

761761
if (sdev->pdata->ipc_type == SOF_IPC_TYPE_4 && !hda_use_tplg_nhlt) {
762762
struct sof_ipc4_fw_data *ipc4_data = sdev->private;
763+
struct snd_ipc4_nhlt *entry;
763764

764-
ipc4_data->nhlt = intel_nhlt_init(sdev->dev);
765+
entry = devm_kzalloc(sdev->dev, sizeof(*entry), GFP_KERNEL);
766+
if (!entry)
767+
return;
768+
769+
entry->nhlt = intel_nhlt_init(sdev->dev);
770+
if (!entry->nhlt) {
771+
devm_kfree(sdev->dev, entry);
772+
return;
773+
}
774+
775+
entry->from_acpi = true;
776+
list_add(&entry->list, &ipc4_data->nhlt_list);
765777
}
766778
}
767779
EXPORT_SYMBOL_NS(hda_set_dai_drv_ops, "SND_SOC_SOF_INTEL_HDA_COMMON");
@@ -770,9 +782,17 @@ void hda_ops_free(struct snd_sof_dev *sdev)
770782
{
771783
if (sdev->pdata->ipc_type == SOF_IPC_TYPE_4) {
772784
struct sof_ipc4_fw_data *ipc4_data = sdev->private;
785+
struct snd_ipc4_nhlt *entry;
786+
struct snd_ipc4_nhlt *tmp;
773787

774-
if (!hda_use_tplg_nhlt)
775-
intel_nhlt_free(ipc4_data->nhlt);
788+
if (!hda_use_tplg_nhlt) {
789+
list_for_each_entry_safe(entry, tmp, &ipc4_data->nhlt_list, list) {
790+
if (entry->from_acpi && entry->nhlt)
791+
intel_nhlt_free(entry->nhlt);
792+
793+
list_del(&entry->list);
794+
}
795+
}
776796

777797
kfree(sdev->private);
778798
sdev->private = NULL;

sound/soc/sof/intel/icl.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@ int sof_icl_ops_init(struct snd_sof_dev *sdev)
127127
return -ENOMEM;
128128

129129
ipc4_data = sdev->private;
130+
INIT_LIST_HEAD(&ipc4_data->nhlt_list);
130131
ipc4_data->manifest_fw_hdr_offset = SOF_MAN4_FW_HDR_OFFSET;
131132

132133
ipc4_data->mtrace_type = SOF_IPC4_MTRACE_INTEL_CAVS_2;

sound/soc/sof/intel/mtl.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -742,6 +742,7 @@ int sof_mtl_set_ops(struct snd_sof_dev *sdev, struct snd_sof_dsp_ops *dsp_ops)
742742
return -ENOMEM;
743743

744744
ipc4_data = sdev->private;
745+
INIT_LIST_HEAD(&ipc4_data->nhlt_list);
745746
ipc4_data->manifest_fw_hdr_offset = SOF_MAN4_FW_HDR_OFFSET;
746747

747748
ipc4_data->mtrace_type = SOF_IPC4_MTRACE_INTEL_CAVS_2;

sound/soc/sof/intel/skl.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ int sof_skl_ops_init(struct snd_sof_dev *sdev)
6767
return -ENOMEM;
6868

6969
ipc4_data = sdev->private;
70+
INIT_LIST_HEAD(&ipc4_data->nhlt_list);
7071
ipc4_data->manifest_fw_hdr_offset = SOF_MAN4_FW_HDR_OFFSET_CAVS_1_5;
7172

7273
ipc4_data->mtrace_type = SOF_IPC4_MTRACE_INTEL_CAVS_1_5;

sound/soc/sof/intel/tgl.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ int sof_tgl_ops_init(struct snd_sof_dev *sdev)
9595
return -ENOMEM;
9696

9797
ipc4_data = sdev->private;
98+
INIT_LIST_HEAD(&ipc4_data->nhlt_list);
9899
ipc4_data->manifest_fw_hdr_offset = SOF_MAN4_FW_HDR_OFFSET;
99100

100101
ipc4_data->mtrace_type = SOF_IPC4_MTRACE_INTEL_CAVS_2;

sound/soc/sof/ipc4-priv.h

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,13 +58,18 @@ struct sof_ipc4_fw_library {
5858
struct sof_ipc4_fw_module *modules;
5959
};
6060

61+
struct snd_ipc4_nhlt {
62+
struct list_head list;
63+
void *nhlt;
64+
bool from_acpi;
65+
};
66+
6167
/**
6268
* struct sof_ipc4_fw_data - IPC4-specific data
6369
* @manifest_fw_hdr_offset: FW header offset in the manifest
6470
* @fw_lib_xa: XArray for firmware libraries, including basefw (ID = 0)
6571
* Used to store the FW libraries and to manage the unique IDs of the
6672
* libraries.
67-
* @nhlt: NHLT table either from the BIOS or the topology manifest
6873
* @mtrace_type: mtrace type supported on the booted platform
6974
* @mtrace_log_bytes: log bytes as reported by the firmware via fw_config reply
7075
* @num_playback_streams: max number of playback DMAs, needed for CHAIN_DMA offset
@@ -74,14 +79,14 @@ struct sof_ipc4_fw_library {
7479
* base firmware
7580
* @fw_context_save: Firmware supports full context save and restore
7681
* @libraries_restored: The libraries have been retained during firmware boot
82+
* @nhlt_list: The NHLT tables from the BIOS and the topology manifest
7783
*
7884
* @load_library: Callback function for platform dependent library loading
7985
* @pipeline_state_mutex: Mutex to protect pipeline triggers, ref counts, states and deletion
8086
*/
8187
struct sof_ipc4_fw_data {
8288
u32 manifest_fw_hdr_offset;
8389
struct xarray fw_lib_xa;
84-
void *nhlt;
8590
enum sof_ipc4_mtrace_type mtrace_type;
8691
u32 mtrace_log_bytes;
8792
int num_playback_streams;
@@ -90,6 +95,7 @@ struct sof_ipc4_fw_data {
9095
u32 max_libs_count;
9196
bool fw_context_save;
9297
bool libraries_restored;
98+
struct list_head nhlt_list;
9399

94100
int (*load_library)(struct snd_sof_dev *sdev,
95101
struct sof_ipc4_fw_library *fw_lib, bool reload);

sound/soc/sof/ipc4-topology.c

Lines changed: 43 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1801,12 +1801,13 @@ snd_sof_get_nhlt_endpoint_data(struct snd_sof_dev *sdev, struct snd_sof_dai *dai
18011801
u32 linktype, u8 dir, u32 **dst, u32 *len)
18021802
{
18031803
struct sof_ipc4_fw_data *ipc4_data = sdev->private;
1804-
struct nhlt_specific_cfg *cfg;
1804+
struct nhlt_specific_cfg *cfg = NULL;
1805+
struct snd_ipc4_nhlt *entry = NULL;
18051806
int sample_rate, channel_count;
18061807
bool format_change = false;
18071808
int bit_depth, ret;
18081809
u32 nhlt_type;
1809-
int dev_type = 0;
1810+
int dev_type = -EINVAL;
18101811

18111812
/* convert to NHLT type */
18121813
switch (linktype) {
@@ -1837,10 +1838,17 @@ snd_sof_get_nhlt_endpoint_data(struct snd_sof_dev *sdev, struct snd_sof_dai *dai
18371838
* Query the type for the port and then pass that information back
18381839
* to the blob lookup function.
18391840
*/
1840-
dev_type = intel_nhlt_ssp_device_type(sdev->dev, ipc4_data->nhlt,
1841-
dai_index);
1842-
if (dev_type < 0)
1841+
list_for_each_entry(entry, &ipc4_data->nhlt_list, list) {
1842+
dev_type = intel_nhlt_ssp_device_type(sdev->dev, entry->nhlt,
1843+
dai_index);
1844+
if (dev_type >= 0)
1845+
break;
1846+
}
1847+
if (dev_type < 0) {
1848+
dev_err(sdev->dev, "%s: No match for SSP%d in NHLT table\n",
1849+
__func__, dai_index);
18431850
return dev_type;
1851+
}
18441852
break;
18451853
default:
18461854
return 0;
@@ -1850,9 +1858,14 @@ snd_sof_get_nhlt_endpoint_data(struct snd_sof_dev *sdev, struct snd_sof_dai *dai
18501858
dai_index, nhlt_type, dir, dev_type);
18511859

18521860
/* find NHLT blob with matching params */
1853-
cfg = intel_nhlt_get_endpoint_blob(sdev->dev, ipc4_data->nhlt, dai_index, nhlt_type,
1854-
bit_depth, bit_depth, channel_count, sample_rate,
1855-
dir, dev_type);
1861+
list_for_each_entry(entry, &ipc4_data->nhlt_list, list) {
1862+
cfg = intel_nhlt_get_endpoint_blob(sdev->dev, entry->nhlt, dai_index,
1863+
nhlt_type, bit_depth, bit_depth,
1864+
channel_count, sample_rate, dir,
1865+
dev_type);
1866+
if (cfg)
1867+
break;
1868+
}
18561869

18571870
if (!cfg) {
18581871
bool get_new_blob = false;
@@ -1886,13 +1899,15 @@ snd_sof_get_nhlt_endpoint_data(struct snd_sof_dev *sdev, struct snd_sof_dai *dai
18861899
}
18871900

18881901
if (get_new_blob) {
1889-
cfg = intel_nhlt_get_endpoint_blob(sdev->dev, ipc4_data->nhlt,
1890-
dai_index, nhlt_type,
1891-
bit_depth, bit_depth,
1892-
channel_count, sample_rate,
1893-
dir, dev_type);
1894-
if (cfg)
1895-
goto out;
1902+
list_for_each_entry(entry, &ipc4_data->nhlt_list, list) {
1903+
cfg = intel_nhlt_get_endpoint_blob(sdev->dev, entry->nhlt,
1904+
dai_index, nhlt_type,
1905+
bit_depth, bit_depth,
1906+
channel_count, sample_rate,
1907+
dir, dev_type);
1908+
if (cfg)
1909+
goto out;
1910+
}
18961911
}
18971912

18981913
dev_err(sdev->dev,
@@ -3912,6 +3927,7 @@ static int sof_ipc4_parse_manifest(struct snd_soc_component *scomp, int index,
39123927
struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
39133928
struct sof_ipc4_fw_data *ipc4_data = sdev->private;
39143929
struct sof_manifest_tlv *manifest_tlv;
3930+
struct snd_ipc4_nhlt *tplg_nhlt;
39153931
struct sof_manifest *manifest;
39163932
u32 size = le32_to_cpu(man->priv.size);
39173933
u8 *man_ptr = man->priv.data;
@@ -3947,13 +3963,20 @@ static int sof_ipc4_parse_manifest(struct snd_soc_component *scomp, int index,
39473963

39483964
switch (le32_to_cpu(manifest_tlv->type)) {
39493965
case SOF_MANIFEST_DATA_TYPE_NHLT:
3950-
/* no NHLT in BIOS, so use the one from topology manifest */
3951-
if (ipc4_data->nhlt)
3952-
break;
3953-
ipc4_data->nhlt = devm_kmemdup(sdev->dev, manifest_tlv->data,
3966+
/* Get the nhlt from topology manifest */
3967+
tplg_nhlt = devm_kzalloc(sdev->dev, sizeof(*tplg_nhlt), GFP_KERNEL);
3968+
if (!tplg_nhlt)
3969+
return -ENOMEM;
3970+
3971+
tplg_nhlt->nhlt = devm_kmemdup(sdev->dev, manifest_tlv->data,
39543972
le32_to_cpu(manifest_tlv->size), GFP_KERNEL);
3955-
if (!ipc4_data->nhlt)
3973+
if (!tplg_nhlt->nhlt)
39563974
return -ENOMEM;
3975+
3976+
tplg_nhlt->from_acpi = false;
3977+
3978+
list_add(&tplg_nhlt->list, &ipc4_data->nhlt_list);
3979+
39573980
break;
39583981
default:
39593982
dev_warn(scomp->dev, "Skipping unknown manifest data type %d\n",

0 commit comments

Comments
 (0)