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

ALSA: hda: cs35l41: Support multiple load paths for firmware

To be able to support different firmwares and tuning
for different models, the driver needs to be able to
load a different firmware and coefficient file based
on its Subsystem ID.

The driver attempts to load the firmware in the
following order:

/lib/firmware/cirrus/cs35l41-dsp1-<fw-type>-<ssid>-dev<#>.wmfw
/lib/firmware/cirrus/cs35l41-dsp1-<fw-type>-<ssid>.wmfw
/lib/firmware/cirrus/cs35l41-dsp1-<fw-type>.wmfw

Signed-off-by: Stefan Binding <sbinding@opensource.cirrus.com>
Signed-off-by: Vitaly Rodionov <vitalyr@opensource.cirrus.com>
Link: https://lore.kernel.org/r/20220630002335.366545-8-vitalyr@opensource.cirrus.com
Signed-off-by: Takashi Iwai <tiwai@suse.de>

authored by

Stefan Binding and committed by
Takashi Iwai
bb6eb621 eef37596

+46 -6
+46 -6
sound/pci/hda/cs35l41_hda.c
··· 85 85 86 86 static int cs35l41_request_firmware_file(struct cs35l41_hda *cs35l41, 87 87 const struct firmware **firmware, char **filename, 88 - const char *dir, const char *filetype) 88 + const char *dir, const char *ssid, const char *amp_name, 89 + const char *filetype) 89 90 { 90 91 const char * const dsp_name = cs35l41->cs_dsp.name; 91 92 char *s, c; 92 93 int ret = 0; 93 94 94 - *filename = kasprintf(GFP_KERNEL, "%s%s-%s-%s.%s", dir, CS35L41_PART, dsp_name, "spk-prot", 95 - filetype); 95 + if (ssid && amp_name) 96 + *filename = kasprintf(GFP_KERNEL, "%s%s-%s-%s-%s-%s.%s", dir, CS35L41_PART, 97 + dsp_name, "spk-prot", ssid, amp_name, 98 + filetype); 99 + else if (ssid) 100 + *filename = kasprintf(GFP_KERNEL, "%s%s-%s-%s-%s.%s", dir, CS35L41_PART, 101 + dsp_name, "spk-prot", ssid, filetype); 102 + else 103 + *filename = kasprintf(GFP_KERNEL, "%s%s-%s-%s.%s", dir, CS35L41_PART, 104 + dsp_name, "spk-prot", filetype); 96 105 97 106 if (*filename == NULL) 98 107 return -ENOMEM; ··· 138 129 { 139 130 int ret; 140 131 141 - /* cirrus/part-dspN-fwtype.wmfw */ 132 + /* try cirrus/part-dspN-fwtype-sub<-ampname>.wmfw */ 142 133 ret = cs35l41_request_firmware_file(cs35l41, wmfw_firmware, wmfw_filename, 143 - CS35L41_FIRMWARE_ROOT, "wmfw"); 134 + CS35L41_FIRMWARE_ROOT, cs35l41->acpi_subsystem_id, 135 + cs35l41->amp_name, "wmfw"); 144 136 if (!ret) { 137 + /* try cirrus/part-dspN-fwtype-sub<-ampname>.bin */ 145 138 cs35l41_request_firmware_file(cs35l41, coeff_firmware, coeff_filename, 146 - CS35L41_FIRMWARE_ROOT, "bin"); 139 + CS35L41_FIRMWARE_ROOT, cs35l41->acpi_subsystem_id, 140 + cs35l41->amp_name, "bin"); 141 + return 0; 142 + } 143 + 144 + /* try cirrus/part-dspN-fwtype-sub.wmfw */ 145 + ret = cs35l41_request_firmware_file(cs35l41, wmfw_firmware, wmfw_filename, 146 + CS35L41_FIRMWARE_ROOT, cs35l41->acpi_subsystem_id, 147 + NULL, "wmfw"); 148 + if (!ret) { 149 + /* try cirrus/part-dspN-fwtype-sub<-ampname>.bin */ 150 + ret = cs35l41_request_firmware_file(cs35l41, coeff_firmware, coeff_filename, 151 + CS35L41_FIRMWARE_ROOT, 152 + cs35l41->acpi_subsystem_id, 153 + cs35l41->amp_name, "bin"); 154 + if (ret) 155 + /* try cirrus/part-dspN-fwtype-sub.bin */ 156 + cs35l41_request_firmware_file(cs35l41, coeff_firmware, coeff_filename, 157 + CS35L41_FIRMWARE_ROOT, 158 + cs35l41->acpi_subsystem_id, NULL, "bin"); 159 + return 0; 160 + } 161 + 162 + /* fallback try cirrus/part-dspN-fwtype.wmfw */ 163 + ret = cs35l41_request_firmware_file(cs35l41, wmfw_firmware, wmfw_filename, 164 + CS35L41_FIRMWARE_ROOT, NULL, NULL, "wmfw"); 165 + if (!ret) { 166 + /* fallback try cirrus/part-dspN-fwtype.bin */ 167 + cs35l41_request_firmware_file(cs35l41, coeff_firmware, coeff_filename, 168 + CS35L41_FIRMWARE_ROOT, NULL, NULL, "bin"); 147 169 return 0; 148 170 } 149 171