Couldn't the driver probe the firmware files with some device-specific string suffix at first? e.g. the driver can issue request_firmware() with $base_file-$dmi_board at first, then falls back to the generic $base_file. A similar method was already used in Broadcom WiFi driver.
Also, the driver may do request_firmware() with a fixed path for the custom firmware at first (e.g. "intel/sof-tplg-custom"); then a system integrator may set up a specific configuration even that doesn't match with DMI or whatever identifier.
And when we have two firmware files which differs just by functionality requested by user? Although your method will work, I won't close the possibility to configure everything in udev rather using a hard coded fw load scheme only.
Jaroslav
I've slept on it and now I think I see what you are trying to do.
- Load FW dependent on platform/user settings
- Load appropriate topology for FW
- Have UCM for the FEs and controls exposed by driver
As for 1. I would say that FW should be loaded from one location if there is some platform that requires special FW just add quirks, like it is done with every other driver, and if someone wants to build their own special FW, they just replace it. We can't possibly support hundreds of possible FW modifications if users want them by putting them in separate files. Alternatively allow override via kernel parameters. Overriding FW files via udev would only make sense to me if it was possible to upload new FW at runtime.
No, replacing firmware files is not viable.
Let me give you a practical example. In the course of SOF development, we routinely copy new test firmware+topology in the location of distribution-managed files. It's classic that when there is a distribution update in the background to install the latest SOF release, our test files are overwritten and it's not usual for developers to lose time trying to figure out why the functionality changed. We do need to have multiple paths and NEVER override what is provided by the distributions. it's the moral equivalent of /usr/bin v. /usr/local/bin.
Likewise, if an OEM has a custom version of firmware+topology, they may want to place it in their own packages that install *separately* from the default distribution. The udev rules provide a means to select the custom firmware, and if no rules are provided the default firmware with no customizations is used.
We are not talking about hundreds of configurations, but typically one directory per OEM. What they do internally is their problem, it's not for us to debate. The key point is that the custom files shall not interfere with the distribution baseline firmware, they have to be handled as separate packages that have their own release cycle and are possibly installed only in OEM custom images.
I would say that same applies for 2.
This leaves number 3. which would require kernel exposing some kind of information about loaded topology, so user space can use proper UCM. In topology manifest there are few reserved fields (https://elixir.bootlin.com/linux/latest/source/include/uapi/sound/asoc.h#L38...), so we can add some information there which should be unique per topology and then expose it in userspace on topology load, it can be the name of UCM file topology wants to be loaded for example.
For example do something along those lines:
struct snd_soc_tplg_manifest { __le32 size; /* in bytes of this structure */ __le32 control_elems; /* number of control elements */ __le32 widget_elems; /* number of widget elements */ __le32 graph_elems; /* number of graph elements */ __le32 pcm_elems; /* number of PCM elements */ __le32 dai_link_elems; /* number of DAI link elements */ __le32 dai_elems; /* number of physical DAI elements */ __le32 ucm_files; /* UCM files to use with topology */ __le32 reserved[19]; /* reserved for new ABI element types */ struct snd_soc_tplg_private priv; } __attribute__((packed));
struct snd_soc_tplg_ucm_files { struct snd_soc_tplg_ctl_hdr hdr; __le32 size; /* size of struct in bytes */ __le32 count; /* UCM entries */ char ucms[SNDRV_CTL_ELEM_ID_NAME_MAXLEN][]; }
And then expose it somewhere under sysfs after parsing topology.
Yes I had a similar idea that we could expose in sysfs information taken from parsing the firmware (e.g. list of module UUIDs) and topology.
But it's not enough. The point is that you may use the same topology+firmware for different platforms, only the tuning varies. I think that's at that level that we should allow the OEMs to set a rule defining what the platform is and what tuning should be applied.