Skip to content

Commit 096ef4c

Browse files
committed
ASoC: SOF: get nhlt from all topologies
Each function topology has its own NHLT blob sections. And we need to look for the matching blob from all the NHLT blobs. Signed-off-by: Bard Liao <yung-chuan.liao@linux.intel.com>
1 parent 842a43c commit 096ef4c

4 files changed

Lines changed: 67 additions & 24 deletions

File tree

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

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -760,8 +760,15 @@ 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 *nhlt;
763764

764-
ipc4_data->nhlt = intel_nhlt_init(sdev->dev);
765+
nhlt = devm_kzalloc(sdev->dev, sizeof(*nhlt), GFP_KERNEL);
766+
if (!nhlt)
767+
return;
768+
769+
nhlt->nhlt = intel_nhlt_init(sdev->dev);
770+
771+
list_add(&nhlt->list, &ipc4_data->nhlt_list);
765772
}
766773
}
767774
EXPORT_SYMBOL_NS(hda_set_dai_drv_ops, "SND_SOC_SOF_INTEL_HDA_COMMON");
@@ -770,9 +777,14 @@ void hda_ops_free(struct snd_sof_dev *sdev)
770777
{
771778
if (sdev->pdata->ipc_type == SOF_IPC_TYPE_4) {
772779
struct sof_ipc4_fw_data *ipc4_data = sdev->private;
780+
struct snd_ipc4_nhlt *nhlt;
773781

774-
if (!hda_use_tplg_nhlt)
775-
intel_nhlt_free(ipc4_data->nhlt);
782+
if (!hda_use_tplg_nhlt) {
783+
nhlt = list_first_entry(&ipc4_data->nhlt_list,
784+
struct snd_ipc4_nhlt, list);
785+
intel_nhlt_free(nhlt->nhlt);
786+
list_del(&nhlt->list);
787+
}
776788

777789
kfree(sdev->private);
778790
sdev->private = NULL;

sound/soc/sof/ipc4-loader.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,7 @@ static size_t sof_ipc4_fw_parse_basefw_ext_man(struct snd_sof_dev *sdev)
149149
ssize_t payload_offset;
150150
int ret;
151151

152+
INIT_LIST_HEAD(&ipc4_data->nhlt_list);
152153
if (sdev->dsp_test_mode_enabled)
153154
fw_lib = devm_kzalloc(sdev->dev, sizeof(*fw_lib), GFP_KERNEL);
154155
else

sound/soc/sof/ipc4-priv.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,13 +58,17 @@ 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+
};
65+
6166
/**
6267
* struct sof_ipc4_fw_data - IPC4-specific data
6368
* @manifest_fw_hdr_offset: FW header offset in the manifest
6469
* @fw_lib_xa: XArray for firmware libraries, including basefw (ID = 0)
6570
* Used to store the FW libraries and to manage the unique IDs of the
6671
* libraries.
67-
* @nhlt: NHLT table either from the BIOS or the topology manifest
6872
* @mtrace_type: mtrace type supported on the booted platform
6973
* @mtrace_log_bytes: log bytes as reported by the firmware via fw_config reply
7074
* @num_playback_streams: max number of playback DMAs, needed for CHAIN_DMA offset
@@ -74,14 +78,14 @@ struct sof_ipc4_fw_library {
7478
* base firmware
7579
* @fw_context_save: Firmware supports full context save and restore
7680
* @libraries_restored: The libraries have been retained during firmware boot
81+
* @nhlt_list: The NHLT tables from the BIOS and the topology manifest
7782
*
7883
* @load_library: Callback function for platform dependent library loading
7984
* @pipeline_state_mutex: Mutex to protect pipeline triggers, ref counts, states and deletion
8085
*/
8186
struct sof_ipc4_fw_data {
8287
u32 manifest_fw_hdr_offset;
8388
struct xarray fw_lib_xa;
84-
void *nhlt;
8589
enum sof_ipc4_mtrace_type mtrace_type;
8690
u32 mtrace_log_bytes;
8791
int num_playback_streams;
@@ -90,6 +94,7 @@ struct sof_ipc4_fw_data {
9094
u32 max_libs_count;
9195
bool fw_context_save;
9296
bool libraries_restored;
97+
struct list_head nhlt_list;
9398

9499
int (*load_library)(struct snd_sof_dev *sdev,
95100
struct sof_ipc4_fw_library *fw_lib, bool reload);

sound/soc/sof/ipc4-topology.c

Lines changed: 44 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1753,6 +1753,7 @@ snd_sof_get_nhlt_endpoint_data(struct snd_sof_dev *sdev, struct snd_sof_dai *dai
17531753
{
17541754
struct sof_ipc4_fw_data *ipc4_data = sdev->private;
17551755
struct nhlt_specific_cfg *cfg;
1756+
struct snd_ipc4_nhlt *nhlt;
17561757
int sample_rate, channel_count;
17571758
bool format_change = false;
17581759
int bit_depth, ret;
@@ -1788,10 +1789,16 @@ snd_sof_get_nhlt_endpoint_data(struct snd_sof_dev *sdev, struct snd_sof_dai *dai
17881789
* Query the type for the port and then pass that information back
17891790
* to the blob lookup function.
17901791
*/
1791-
dev_type = intel_nhlt_ssp_device_type(sdev->dev, ipc4_data->nhlt,
1792-
dai_index);
1793-
if (dev_type < 0)
1792+
list_for_each_entry(nhlt, &ipc4_data->nhlt_list, list) {
1793+
dev_type = intel_nhlt_ssp_device_type(sdev->dev, nhlt->nhlt,
1794+
dai_index);
1795+
if (dev_type >= 0)
1796+
break;
1797+
}
1798+
if (dev_type < 0) {
1799+
dev_err(sdev->dev, "%s: No match for SSP%d in NHLT table\n", __func__, dai_index);
17941800
return dev_type;
1801+
}
17951802
break;
17961803
default:
17971804
return 0;
@@ -1801,9 +1808,20 @@ snd_sof_get_nhlt_endpoint_data(struct snd_sof_dev *sdev, struct snd_sof_dai *dai
18011808
dai_index, nhlt_type, dir, dev_type);
18021809

18031810
/* find NHLT blob with matching params */
1804-
cfg = intel_nhlt_get_endpoint_blob(sdev->dev, ipc4_data->nhlt, dai_index, nhlt_type,
1805-
bit_depth, bit_depth, channel_count, sample_rate,
1806-
dir, dev_type);
1811+
if (nhlt) {
1812+
cfg = intel_nhlt_get_endpoint_blob(sdev->dev, nhlt->nhlt, dai_index, nhlt_type,
1813+
bit_depth, bit_depth, channel_count,
1814+
sample_rate, dir, dev_type);
1815+
} else {
1816+
list_for_each_entry(nhlt, &ipc4_data->nhlt_list, list) {
1817+
cfg = intel_nhlt_get_endpoint_blob(sdev->dev, nhlt->nhlt, dai_index,
1818+
nhlt_type, bit_depth, bit_depth,
1819+
channel_count, sample_rate, dir,
1820+
dev_type);
1821+
if (cfg)
1822+
break;
1823+
}
1824+
}
18071825

18081826
if (!cfg) {
18091827
bool get_new_blob = false;
@@ -1837,13 +1855,15 @@ snd_sof_get_nhlt_endpoint_data(struct snd_sof_dev *sdev, struct snd_sof_dai *dai
18371855
}
18381856

18391857
if (get_new_blob) {
1840-
cfg = intel_nhlt_get_endpoint_blob(sdev->dev, ipc4_data->nhlt,
1841-
dai_index, nhlt_type,
1842-
bit_depth, bit_depth,
1843-
channel_count, sample_rate,
1844-
dir, dev_type);
1845-
if (cfg)
1846-
goto out;
1858+
list_for_each_entry(nhlt, &ipc4_data->nhlt_list, list) {
1859+
cfg = intel_nhlt_get_endpoint_blob(sdev->dev, nhlt->nhlt,
1860+
dai_index, nhlt_type,
1861+
bit_depth, bit_depth,
1862+
channel_count, sample_rate,
1863+
dir, dev_type);
1864+
if (cfg)
1865+
goto out;
1866+
}
18471867
}
18481868

18491869
dev_err(sdev->dev,
@@ -3747,13 +3767,18 @@ static int sof_ipc4_parse_manifest(struct snd_soc_component *scomp, int index,
37473767

37483768
switch (le32_to_cpu(manifest_tlv->type)) {
37493769
case SOF_MANIFEST_DATA_TYPE_NHLT:
3750-
/* no NHLT in BIOS, so use the one from topology manifest */
3751-
if (ipc4_data->nhlt)
3752-
break;
3753-
ipc4_data->nhlt = devm_kmemdup(sdev->dev, manifest_tlv->data,
3754-
le32_to_cpu(manifest_tlv->size), GFP_KERNEL);
3755-
if (!ipc4_data->nhlt)
3770+
struct snd_ipc4_nhlt *tplg_nhlt;
3771+
3772+
/* Get the nhlt from topology manifest*/
3773+
tplg_nhlt = devm_kzalloc(sdev->dev, sizeof(*tplg_nhlt), GFP_KERNEL);
3774+
if (!tplg_nhlt)
37563775
return -ENOMEM;
3776+
3777+
tplg_nhlt->nhlt = devm_kmemdup(sdev->dev, manifest_tlv->data,
3778+
le32_to_cpu(manifest_tlv->size), GFP_KERNEL);
3779+
3780+
list_add(&tplg_nhlt->list, &ipc4_data->nhlt_list);
3781+
37573782
break;
37583783
default:
37593784
dev_warn(scomp->dev, "Skipping unknown manifest data type %d\n",

0 commit comments

Comments
 (0)