Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ASoC: SOF: Introduce container struct for SOF firmware

Move the firmware related information under a new struct (sof_firmware)
and add it to the high level snd_sof_dev struct.

Convert the generic code to use this new container when working with the
basefw and for compatibility reasons set the old plat_data members used by
the platforms.

Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
Reviewed-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Reviewed-by: Chao Song <chao.song@intel.com>
Reviewed-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
Link: https://lore.kernel.org/r/20221020121238.18339-3-peter.ujfalusi@linux.intel.com
Signed-off-by: Mark Brown <broonie@kernel.org>

authored by

Peter Ujfalusi and committed by
Mark Brown
4f373ccf 9b9db0d6

+41 -23
+12 -14
sound/soc/sof/ipc3-loader.c
··· 138 138 139 139 static size_t sof_ipc3_fw_parse_ext_man(struct snd_sof_dev *sdev) 140 140 { 141 - struct snd_sof_pdata *plat_data = sdev->pdata; 142 - const struct firmware *fw = plat_data->fw; 141 + const struct firmware *fw = sdev->basefw.fw; 143 142 const struct sof_ext_man_elem_header *elem_hdr; 144 143 const struct sof_ext_man_header *head; 145 144 ssize_t ext_man_size; ··· 309 310 310 311 static int sof_ipc3_load_fw_to_dsp(struct snd_sof_dev *sdev) 311 312 { 312 - struct snd_sof_pdata *plat_data = sdev->pdata; 313 - const struct firmware *fw = plat_data->fw; 313 + u32 payload_offset = sdev->basefw.payload_offset; 314 + const struct firmware *fw = sdev->basefw.fw; 314 315 struct snd_sof_fw_header *header; 315 316 struct snd_sof_mod_hdr *module; 316 317 int (*load_module)(struct snd_sof_dev *sof_dev, struct snd_sof_mod_hdr *hdr); 317 318 size_t remaining; 318 319 int ret, count; 319 320 320 - if (!plat_data->fw) 321 + if (!fw) 321 322 return -EINVAL; 322 323 323 - header = (struct snd_sof_fw_header *)(fw->data + plat_data->fw_offset); 324 + header = (struct snd_sof_fw_header *)(fw->data + payload_offset); 324 325 load_module = sof_ops(sdev)->load_module; 325 326 if (!load_module) { 326 327 dev_dbg(sdev->dev, "Using generic module loading\n"); ··· 330 331 } 331 332 332 333 /* parse each module */ 333 - module = (struct snd_sof_mod_hdr *)(fw->data + plat_data->fw_offset + 334 - sizeof(*header)); 335 - remaining = fw->size - sizeof(*header) - plat_data->fw_offset; 334 + module = (struct snd_sof_mod_hdr *)(fw->data + payload_offset + sizeof(*header)); 335 + remaining = fw->size - sizeof(*header) - payload_offset; 336 336 /* check for wrap */ 337 337 if (remaining > fw->size) { 338 338 dev_err(sdev->dev, "%s: fw size smaller than header size\n", __func__); ··· 372 374 373 375 static int sof_ipc3_validate_firmware(struct snd_sof_dev *sdev) 374 376 { 375 - struct snd_sof_pdata *plat_data = sdev->pdata; 376 - const struct firmware *fw = plat_data->fw; 377 + u32 payload_offset = sdev->basefw.payload_offset; 378 + const struct firmware *fw = sdev->basefw.fw; 377 379 struct snd_sof_fw_header *header; 378 - size_t fw_size = fw->size - plat_data->fw_offset; 380 + size_t fw_size = fw->size - payload_offset; 379 381 380 - if (fw->size <= plat_data->fw_offset) { 382 + if (fw->size <= payload_offset) { 381 383 dev_err(sdev->dev, 382 384 "firmware size must be greater than firmware offset\n"); 383 385 return -EINVAL; 384 386 } 385 387 386 388 /* Read the header information from the data pointer */ 387 - header = (struct snd_sof_fw_header *)(fw->data + plat_data->fw_offset); 389 + header = (struct snd_sof_fw_header *)(fw->data + payload_offset); 388 390 389 391 /* verify FW sig */ 390 392 if (strncmp(header->sig, SND_SOF_FW_SIG, SND_SOF_FW_SIG_SIZE) != 0) {
+2 -4
sound/soc/sof/ipc4-loader.c
··· 17 17 static size_t sof_ipc4_fw_parse_ext_man(struct snd_sof_dev *sdev) 18 18 { 19 19 struct sof_ipc4_fw_data *ipc4_data = sdev->private; 20 - struct snd_sof_pdata *plat_data = sdev->pdata; 21 20 struct sof_man4_fw_binary_header *fw_header; 22 - const struct firmware *fw = plat_data->fw; 21 + const struct firmware *fw = sdev->basefw.fw; 23 22 struct sof_ext_manifest4_hdr *ext_man_hdr; 24 23 struct sof_man4_module_config *fm_config; 25 24 struct sof_ipc4_fw_module *fw_module; ··· 137 138 { 138 139 struct sof_ipc4_fw_data *ipc4_data = sdev->private; 139 140 u32 fw_hdr_offset = ipc4_data->manifest_fw_hdr_offset; 140 - struct snd_sof_pdata *plat_data = sdev->pdata; 141 141 struct sof_man4_fw_binary_header *fw_header; 142 - const struct firmware *fw = plat_data->fw; 142 + const struct firmware *fw = sdev->basefw.fw; 143 143 struct sof_ext_manifest4_hdr *ext_man_hdr; 144 144 145 145 ext_man_hdr = (struct sof_ext_manifest4_hdr *)fw->data;
+13 -5
sound/soc/sof/loader.c
··· 22 22 int ret; 23 23 24 24 /* Don't request firmware again if firmware is already requested */ 25 - if (plat_data->fw) 25 + if (sdev->basefw.fw) 26 26 return 0; 27 27 28 28 fw_filename = kasprintf(GFP_KERNEL, "%s/%s", ··· 31 31 if (!fw_filename) 32 32 return -ENOMEM; 33 33 34 - ret = request_firmware(&plat_data->fw, fw_filename, sdev->dev); 34 + ret = request_firmware(&sdev->basefw.fw, fw_filename, sdev->dev); 35 35 36 36 if (ret < 0) { 37 37 dev_err(sdev->dev, ··· 48 48 ext_man_size = sdev->ipc->ops->fw_loader->parse_ext_manifest(sdev); 49 49 if (ext_man_size > 0) { 50 50 /* when no error occurred, drop extended manifest */ 51 - plat_data->fw_offset = ext_man_size; 51 + sdev->basefw.payload_offset = ext_man_size; 52 52 } else if (!ext_man_size) { 53 53 /* No extended manifest, so nothing to skip during FW load */ 54 54 dev_dbg(sdev->dev, "firmware doesn't contain extended manifest\n"); ··· 58 58 fw_filename, ret); 59 59 } 60 60 61 + /* 62 + * Until the platform code is switched to use the new container the fw 63 + * and payload offset must be set in plat_data 64 + */ 65 + plat_data->fw = sdev->basefw.fw; 66 + plat_data->fw_offset = sdev->basefw.payload_offset; 61 67 err: 62 68 kfree(fw_filename); 63 69 ··· 106 100 return 0; 107 101 108 102 error: 109 - release_firmware(plat_data->fw); 103 + release_firmware(sdev->basefw.fw); 104 + sdev->basefw.fw = NULL; 110 105 plat_data->fw = NULL; 111 106 return ret; 112 107 ··· 192 185 void snd_sof_fw_unload(struct snd_sof_dev *sdev) 193 186 { 194 187 /* TODO: support module unloading at runtime */ 195 - release_firmware(sdev->pdata->fw); 188 + release_firmware(sdev->basefw.fw); 189 + sdev->basefw.fw = NULL; 196 190 sdev->pdata->fw = NULL; 197 191 } 198 192 EXPORT_SYMBOL(snd_sof_fw_unload);
+14
sound/soc/sof/sof-priv.h
··· 136 136 bool cont_update_posn; 137 137 }; 138 138 139 + /** 140 + * struct sof_firmware - Container struct for SOF firmware 141 + * @fw: Pointer to the firmware 142 + * @payload_offset: Offset of the data within the loaded firmware image to be 143 + * loaded to the DSP (skipping for example ext_manifest section) 144 + */ 145 + struct sof_firmware { 146 + const struct firmware *fw; 147 + u32 payload_offset; 148 + }; 149 + 139 150 /* 140 151 * SOF DSP HW abstraction operations. 141 152 * Used to abstract DSP HW architecture and any IO busses between host CPU ··· 497 486 struct device *dev; 498 487 spinlock_t ipc_lock; /* lock for IPC users */ 499 488 spinlock_t hw_lock; /* lock for HW IO access */ 489 + 490 + /* Main, Base firmware image */ 491 + struct sof_firmware basefw; 500 492 501 493 /* 502 494 * ASoC components. plat_drv fields are set dynamically so