Skip to content

Commit 259d80c

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. Also, move the error log to where the blob can't be found from all the NHLT blobs. Signed-off-by: Bard Liao <yung-chuan.liao@linux.intel.com>
1 parent 842a43c commit 259d80c

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)