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

Configure Feed

Select the types of activity you want to include in your feed.

ASoC: wm_adsp: Some improvements to firmware file

Merge series from Richard Fitzgerald <rf@opensource.cirrus.com>:

This series makes some improvements to the code that searches for firmware
files.

Patch 1 is a trivial patch to remove an unused function argument, before
adding any new code that uses this API.

Patches 2..4 add KUnit testing to prove that the subsequent changes don't
break anything.

The remaining patches remove duplicated code and clean up some of the
implementation.

+1383 -107
+13 -1
sound/soc/codecs/Kconfig
··· 398 398 default m if SND_SOC_WM8993=m || SND_SOC_WM8994=m 399 399 400 400 config SND_SOC_WM_ADSP 401 - tristate 401 + tristate "Cirrus Logic wm_adsp driver" if KUNIT 402 402 select FW_CS_DSP 403 403 select SND_SOC_COMPRESS 404 404 default y if SND_SOC_MADERA=y ··· 423 423 default m if SND_SOC_CS35L45_I2C=m 424 424 default m if SND_SOC_CS35L56=m 425 425 default m if SND_SOC_CS48L32=m 426 + 427 + config SND_SOC_WM_ADSP_TEST 428 + tristate "KUnit tests for Cirrus Logic wm_adsp" if !KUNIT_ALL_TESTS 429 + depends on KUNIT 430 + depends on SND_SOC_WM_ADSP 431 + default KUNIT_ALL_TESTS 432 + help 433 + This builds KUnit tests for the Cirrus Logic wm_adsp library. 434 + For more information on KUnit and unit tests in general, 435 + please refer to the KUnit documentation in 436 + Documentation/dev-tools/kunit/. 437 + If in doubt, say "N". 426 438 427 439 config SND_SOC_AB8500_CODEC 428 440 tristate
+2
sound/soc/codecs/Makefile
··· 361 361 snd-soc-wcd939x-y := wcd939x.o 362 362 snd-soc-wcd939x-sdw-y := wcd939x-sdw.o 363 363 snd-soc-wm-adsp-y := wm_adsp.o 364 + snd-soc-wm-adsp-test-y := wm_adsp_fw_find_test.o 364 365 snd-soc-wm0010-y := wm0010.o 365 366 snd-soc-wm1250-ev1-y := wm1250-ev1.o 366 367 snd-soc-wm2000-y := wm2000.o ··· 863 862 obj-$(CONFIG_SND_SOC_WM9712) += snd-soc-wm9712.o 864 863 obj-$(CONFIG_SND_SOC_WM9713) += snd-soc-wm9713.o 865 864 obj-$(CONFIG_SND_SOC_WM_ADSP) += snd-soc-wm-adsp.o 865 + obj-$(CONFIG_SND_SOC_WM_ADSP_TEST) += snd-soc-wm-adsp-test.o 866 866 obj-$(CONFIG_SND_SOC_WM_HUBS) += snd-soc-wm-hubs.o 867 867 obj-$(CONFIG_SND_SOC_WSA881X) += snd-soc-wsa881x.o 868 868 obj-$(CONFIG_SND_SOC_WSA883X) += snd-soc-wsa883x.o
+128 -106
sound/soc/codecs/wm_adsp.c
··· 7 7 * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> 8 8 */ 9 9 10 + #include <kunit/static_stub.h> 11 + #include <kunit/visibility.h> 10 12 #include <linux/array_size.h> 11 13 #include <linux/cleanup.h> 12 14 #include <linux/ctype.h> ··· 317 315 struct soc_bytes_ext bytes_ext; 318 316 struct work_struct work; 319 317 }; 318 + 319 + #if IS_ENABLED(CONFIG_KUNIT) 320 + const char *wm_adsp_get_fwf_name_by_index(int index) 321 + { 322 + if (index < ARRAY_SIZE(wm_adsp_fw)) 323 + return wm_adsp_fw[index].file; 324 + 325 + return NULL; 326 + } 327 + EXPORT_SYMBOL_IF_KUNIT(wm_adsp_get_fwf_name_by_index); 328 + #endif 320 329 321 330 int wm_adsp_fw_get(struct snd_kcontrol *kcontrol, 322 331 struct snd_ctl_elem_value *ucontrol) ··· 717 704 } 718 705 EXPORT_SYMBOL_GPL(wm_adsp_read_ctl); 719 706 720 - static void wm_adsp_release_firmware_files(struct wm_adsp *dsp, 721 - const struct firmware *wmfw_firmware, 722 - char *wmfw_filename, 723 - const struct firmware *coeff_firmware, 724 - char *coeff_filename) 707 + VISIBLE_IF_KUNIT void wm_adsp_release_firmware_files(struct wm_adsp_fw_files *fw) 725 708 { 726 - release_firmware(wmfw_firmware); 727 - kfree(wmfw_filename); 709 + KUNIT_STATIC_STUB_REDIRECT(wm_adsp_release_firmware_files, fw); 728 710 729 - release_firmware(coeff_firmware); 730 - kfree(coeff_filename); 711 + release_firmware(fw->wmfw.firmware); 712 + kfree(fw->wmfw.filename); 713 + 714 + release_firmware(fw->coeff.firmware); 715 + kfree(fw->coeff.filename); 731 716 } 717 + EXPORT_SYMBOL_IF_KUNIT(wm_adsp_release_firmware_files); 718 + 719 + VISIBLE_IF_KUNIT int wm_adsp_firmware_request(const struct firmware **firmware, 720 + const char *filename, 721 + struct device *dev) 722 + { 723 + KUNIT_STATIC_STUB_REDIRECT(wm_adsp_firmware_request, firmware, filename, dev); 724 + 725 + return firmware_request_nowarn(firmware, filename, dev); 726 + } 727 + EXPORT_SYMBOL_IF_KUNIT(wm_adsp_firmware_request); 732 728 733 729 static int wm_adsp_request_firmware_file(struct wm_adsp *dsp, 734 - const struct firmware **firmware, char **filename, 730 + struct wm_adsp_fw_file *fw, 735 731 const char *dir, const char *system_name, 736 732 const char *asoc_component_prefix, 737 733 const char *filetype) ··· 748 726 struct cs_dsp *cs_dsp = &dsp->cs_dsp; 749 727 const char *fwf; 750 728 char *s, c; 751 - int ret = 0; 729 + int ret; 752 730 753 731 if (dsp->fwf_name) 754 732 fwf = dsp->fwf_name; ··· 756 734 fwf = dsp->cs_dsp.name; 757 735 758 736 if (system_name && asoc_component_prefix) 759 - *filename = kasprintf(GFP_KERNEL, "%s%s-%s-%s-%s-%s.%s", dir, dsp->part, 760 - fwf, wm_adsp_fw[dsp->fw].file, system_name, 761 - asoc_component_prefix, filetype); 737 + fw->filename = kasprintf(GFP_KERNEL, "%s%s-%s-%s-%s-%s.%s", dir, dsp->part, 738 + fwf, wm_adsp_fw[dsp->fw].file, system_name, 739 + asoc_component_prefix, filetype); 762 740 else if (system_name) 763 - *filename = kasprintf(GFP_KERNEL, "%s%s-%s-%s-%s.%s", dir, dsp->part, 764 - fwf, wm_adsp_fw[dsp->fw].file, system_name, 765 - filetype); 741 + fw->filename = kasprintf(GFP_KERNEL, "%s%s-%s-%s-%s.%s", dir, dsp->part, 742 + fwf, wm_adsp_fw[dsp->fw].file, system_name, 743 + filetype); 766 744 else 767 - *filename = kasprintf(GFP_KERNEL, "%s%s-%s-%s.%s", dir, dsp->part, fwf, 768 - wm_adsp_fw[dsp->fw].file, filetype); 745 + fw->filename = kasprintf(GFP_KERNEL, "%s%s-%s-%s.%s", dir, dsp->part, fwf, 746 + wm_adsp_fw[dsp->fw].file, filetype); 769 747 770 - if (*filename == NULL) 748 + if (!fw->filename) 771 749 return -ENOMEM; 772 750 773 751 /* 774 - * Make sure that filename is lower-case and any non alpha-numeric 775 - * characters except full stop and forward slash are replaced with 776 - * hyphens. 752 + * Make sure that filename after dir is lower-case and any non-alpha-numeric 753 + * characters except full-stop are replaced with hyphens. 777 754 */ 778 - s = *filename; 755 + s = fw->filename + strlen(dir); 779 756 while (*s) { 780 757 c = *s; 781 758 if (isalnum(c)) 782 759 *s = tolower(c); 783 - else if ((c != '.') && (c != '/')) 760 + else if (c != '.') 784 761 *s = '-'; 785 762 s++; 786 763 } 787 764 788 - ret = firmware_request_nowarn(firmware, *filename, cs_dsp->dev); 789 - if (ret != 0) { 790 - adsp_dbg(dsp, "Failed to request '%s'\n", *filename); 791 - kfree(*filename); 792 - *filename = NULL; 765 + ret = wm_adsp_firmware_request(&fw->firmware, fw->filename, cs_dsp->dev); 766 + if (ret < 0) { 767 + adsp_dbg(dsp, "Failed to request '%s': %d\n", fw->filename, ret); 768 + kfree(fw->filename); 769 + fw->filename = NULL; 770 + if (ret != -ENOENT) 771 + return ret; 793 772 } else { 794 - adsp_dbg(dsp, "Found '%s'\n", *filename); 773 + adsp_dbg(dsp, "Found '%s'\n", fw->filename); 795 774 } 796 775 797 - return ret; 776 + return 0; 798 777 } 799 778 800 779 static const char * const cirrus_dir = "cirrus/"; 801 - static int wm_adsp_request_firmware_files(struct wm_adsp *dsp, 802 - const struct firmware **wmfw_firmware, 803 - char **wmfw_filename, 804 - const struct firmware **coeff_firmware, 805 - char **coeff_filename) 780 + VISIBLE_IF_KUNIT int wm_adsp_request_firmware_files(struct wm_adsp *dsp, 781 + struct wm_adsp_fw_files *fw) 806 782 { 807 783 const char *system_name = dsp->system_name; 808 784 const char *suffix = dsp->component->name_prefix; 785 + bool require_bin_suffix = false; 809 786 int ret = 0; 810 787 811 788 if (dsp->fwf_suffix) 812 789 suffix = dsp->fwf_suffix; 813 790 814 - if (system_name && suffix) { 815 - if (!wm_adsp_request_firmware_file(dsp, wmfw_firmware, wmfw_filename, 816 - cirrus_dir, system_name, 817 - suffix, "wmfw")) { 818 - wm_adsp_request_firmware_file(dsp, coeff_firmware, coeff_filename, 819 - cirrus_dir, system_name, 820 - suffix, "bin"); 821 - return 0; 822 - } 823 - } 824 - 825 791 if (system_name) { 826 - if (!wm_adsp_request_firmware_file(dsp, wmfw_firmware, wmfw_filename, 827 - cirrus_dir, system_name, 828 - NULL, "wmfw")) { 829 - if (suffix) 830 - wm_adsp_request_firmware_file(dsp, coeff_firmware, coeff_filename, 831 - cirrus_dir, system_name, 832 - suffix, "bin"); 792 + ret = wm_adsp_request_firmware_file(dsp, &fw->wmfw, 793 + cirrus_dir, system_name, 794 + suffix, "wmfw"); 795 + if (ret < 0) 796 + goto err; 833 797 834 - if (!*coeff_firmware) 835 - wm_adsp_request_firmware_file(dsp, coeff_firmware, coeff_filename, 836 - cirrus_dir, system_name, 837 - NULL, "bin"); 838 - return 0; 798 + if (suffix) { 799 + if (fw->wmfw.firmware) { 800 + require_bin_suffix = true; 801 + } else { 802 + /* Fallback to name without suffix */ 803 + ret = wm_adsp_request_firmware_file(dsp, &fw->wmfw, 804 + cirrus_dir, system_name, 805 + NULL, "wmfw"); 806 + if (ret < 0) 807 + goto err; 808 + } 839 809 } 840 - } 841 810 842 - /* Check system-specific bin without wmfw before falling back to generic */ 843 - if (dsp->wmfw_optional && system_name) { 844 - if (suffix) 845 - wm_adsp_request_firmware_file(dsp, coeff_firmware, coeff_filename, 846 - cirrus_dir, system_name, 847 - suffix, "bin"); 811 + /* Look for matching .bin file */ 812 + if (fw->wmfw.firmware || dsp->wmfw_optional) { 813 + ret = wm_adsp_request_firmware_file(dsp, &fw->coeff, 814 + cirrus_dir, system_name, 815 + suffix, "bin"); 816 + if (ret < 0) 817 + goto err; 848 818 849 - if (!*coeff_firmware) 850 - wm_adsp_request_firmware_file(dsp, coeff_firmware, coeff_filename, 851 - cirrus_dir, system_name, 852 - NULL, "bin"); 819 + if (suffix && !fw->coeff.firmware && !require_bin_suffix) { 820 + /* Fallback to name without suffix */ 821 + ret = wm_adsp_request_firmware_file(dsp, 822 + &fw->coeff, 823 + cirrus_dir, system_name, 824 + NULL, "bin"); 825 + if (ret < 0) 826 + goto err; 827 + } 828 + } 853 829 854 - if (*coeff_firmware) 830 + if (fw->wmfw.firmware || (dsp->wmfw_optional && fw->coeff.firmware)) 855 831 return 0; 856 832 } 857 833 858 834 /* Check legacy location */ 859 - if (!wm_adsp_request_firmware_file(dsp, wmfw_firmware, wmfw_filename, 860 - "", NULL, NULL, "wmfw")) { 861 - wm_adsp_request_firmware_file(dsp, coeff_firmware, coeff_filename, 862 - "", NULL, NULL, "bin"); 835 + ret = wm_adsp_request_firmware_file(dsp, &fw->wmfw, "", NULL, NULL, "wmfw"); 836 + if (ret < 0) 837 + goto err; 838 + 839 + if (fw->wmfw.firmware) { 840 + ret = wm_adsp_request_firmware_file(dsp, &fw->coeff, "", NULL, NULL, "bin"); 841 + if (ret < 0) 842 + goto err; 843 + 863 844 return 0; 864 845 } 865 846 866 847 /* Fall back to generic wmfw and optional matching bin */ 867 - ret = wm_adsp_request_firmware_file(dsp, wmfw_firmware, wmfw_filename, 848 + ret = wm_adsp_request_firmware_file(dsp, &fw->wmfw, 868 849 cirrus_dir, NULL, NULL, "wmfw"); 869 - if (!ret || dsp->wmfw_optional) { 870 - wm_adsp_request_firmware_file(dsp, coeff_firmware, coeff_filename, 871 - cirrus_dir, NULL, NULL, "bin"); 850 + if (ret < 0) 851 + goto err; 852 + 853 + if (fw->wmfw.firmware || dsp->wmfw_optional) { 854 + ret = wm_adsp_request_firmware_file(dsp, &fw->coeff, 855 + cirrus_dir, NULL, NULL, "bin"); 856 + if (ret < 0) 857 + goto err; 858 + 872 859 return 0; 873 860 } 874 861 ··· 886 855 dsp->fwf_name ? dsp->fwf_name : dsp->cs_dsp.name, 887 856 wm_adsp_fw[dsp->fw].file, system_name, suffix); 888 857 889 - return -ENOENT; 858 + ret = -ENOENT; 859 + err: 860 + wm_adsp_release_firmware_files(fw); 861 + 862 + return ret; 890 863 } 864 + EXPORT_SYMBOL_IF_KUNIT(wm_adsp_request_firmware_files); 891 865 892 866 static int wm_adsp_common_init(struct wm_adsp *dsp) 893 867 { ··· 923 887 struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); 924 888 struct wm_adsp *dsps = snd_soc_component_get_drvdata(component); 925 889 struct wm_adsp *dsp = &dsps[w->shift]; 890 + struct wm_adsp_fw_files fw = { 0 }; 926 891 int ret = 0; 927 - char *wmfw_filename = NULL; 928 - const struct firmware *wmfw_firmware = NULL; 929 - char *coeff_filename = NULL; 930 - const struct firmware *coeff_firmware = NULL; 931 892 932 893 dsp->component = component; 933 894 934 895 switch (event) { 935 896 case SND_SOC_DAPM_POST_PMU: 936 - ret = wm_adsp_request_firmware_files(dsp, 937 - &wmfw_firmware, &wmfw_filename, 938 - &coeff_firmware, &coeff_filename); 897 + ret = wm_adsp_request_firmware_files(dsp, &fw); 939 898 if (ret) 940 899 break; 941 900 942 901 ret = cs_dsp_adsp1_power_up(&dsp->cs_dsp, 943 - wmfw_firmware, wmfw_filename, 944 - coeff_firmware, coeff_filename, 902 + fw.wmfw.firmware, fw.wmfw.filename, 903 + fw.coeff.firmware, fw.coeff.filename, 945 904 wm_adsp_fw_text[dsp->fw]); 946 905 947 - wm_adsp_release_firmware_files(dsp, 948 - wmfw_firmware, wmfw_filename, 949 - coeff_firmware, coeff_filename); 906 + wm_adsp_release_firmware_files(&fw); 950 907 break; 951 908 case SND_SOC_DAPM_PRE_PMD: 952 909 cs_dsp_adsp1_power_down(&dsp->cs_dsp); ··· 1015 986 1016 987 int wm_adsp_power_up(struct wm_adsp *dsp, bool load_firmware) 1017 988 { 989 + struct wm_adsp_fw_files fw = { 0 }; 1018 990 int ret = 0; 1019 - char *wmfw_filename = NULL; 1020 - const struct firmware *wmfw_firmware = NULL; 1021 - char *coeff_filename = NULL; 1022 - const struct firmware *coeff_firmware = NULL; 1023 991 1024 992 if (load_firmware) { 1025 - ret = wm_adsp_request_firmware_files(dsp, 1026 - &wmfw_firmware, &wmfw_filename, 1027 - &coeff_firmware, &coeff_filename); 993 + ret = wm_adsp_request_firmware_files(dsp, &fw); 1028 994 if (ret) 1029 995 return ret; 1030 996 } 1031 997 1032 - if (dsp->bin_mandatory && !coeff_firmware) { 998 + if (dsp->bin_mandatory && !fw.coeff.firmware) { 1033 999 ret = -ENOENT; 1034 1000 goto err; 1035 1001 } 1036 1002 1037 1003 ret = cs_dsp_power_up(&dsp->cs_dsp, 1038 - wmfw_firmware, wmfw_filename, 1039 - coeff_firmware, coeff_filename, 1004 + fw.wmfw.firmware, fw.wmfw.filename, 1005 + fw.coeff.firmware, fw.coeff.filename, 1040 1006 wm_adsp_fw_text[dsp->fw]); 1041 1007 1042 1008 err: 1043 - wm_adsp_release_firmware_files(dsp, 1044 - wmfw_firmware, wmfw_filename, 1045 - coeff_firmware, coeff_filename); 1009 + wm_adsp_release_firmware_files(&fw); 1046 1010 1047 1011 return ret; 1048 1012 }
+19
sound/soc/codecs/wm_adsp.h
··· 79 79 SOC_ENUM_EXT(dspname " Firmware", wm_adsp_fw_enum[num], \ 80 80 wm_adsp_fw_get, wm_adsp_fw_put) 81 81 82 + struct wm_adsp_fw_file { 83 + const struct firmware *firmware; 84 + char *filename; 85 + }; 86 + 87 + struct wm_adsp_fw_files { 88 + struct wm_adsp_fw_file wmfw; 89 + struct wm_adsp_fw_file coeff; 90 + }; 91 + 82 92 extern const struct soc_enum wm_adsp_fw_enum[]; 83 93 84 94 int wm_adsp1_init(struct wm_adsp *dsp); ··· 152 142 unsigned int alg, void *buf, size_t len); 153 143 int wm_adsp_read_ctl(struct wm_adsp *dsp, const char *name, int type, 154 144 unsigned int alg, void *buf, size_t len); 145 + 146 + #if IS_ENABLED(CONFIG_KUNIT) 147 + const char *wm_adsp_get_fwf_name_by_index(int index); 148 + void wm_adsp_release_firmware_files(struct wm_adsp_fw_files *fw); 149 + int wm_adsp_firmware_request(const struct firmware **firmware, 150 + const char *filename, 151 + struct device *dev); 152 + int wm_adsp_request_firmware_files(struct wm_adsp *dsp, struct wm_adsp_fw_files *fw); 153 + #endif 155 154 156 155 #endif
+1221
sound/soc/codecs/wm_adsp_fw_find_test.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + // 3 + // Test cases for wm_adsp library. 4 + // 5 + // Copyright (C) 2025 Cirrus Logic, Inc. and 6 + // Cirrus Logic International Semiconductor Ltd. 7 + 8 + #include <kunit/device.h> 9 + #include <kunit/static_stub.h> 10 + #include <kunit/test.h> 11 + #include <linux/slab.h> 12 + #include "wm_adsp.h" 13 + 14 + KUNIT_DEFINE_ACTION_WRAPPER(_put_device_wrapper, put_device, struct device *); 15 + 16 + struct wm_adsp_fw_find_test { 17 + struct wm_adsp dsp; 18 + 19 + struct wm_adsp_fw_files found_fw; 20 + char searched_fw_files[768]; 21 + }; 22 + 23 + struct wm_adsp_fw_find_test_params { 24 + const char *part; 25 + const char *dsp_name; 26 + const char *fwf_name; 27 + const char *system_name; 28 + const char *alsa_name; 29 + bool wmfw_optional; 30 + bool bin_mandatory; 31 + 32 + /* If non-NULL this file should be returned as "found" */ 33 + const char *expect_wmfw; 34 + 35 + /* If non-NULL this file should be returned as "found" */ 36 + const char *expect_bin; 37 + 38 + /* Space-separated list of filenames in expected order of searching */ 39 + const char *expected_searches; 40 + 41 + /* NULL-terminated array of pointers to filenames to simulate directory content */ 42 + const char * const *dir_files; 43 + }; 44 + 45 + /* Dummy struct firmware to return from wm_adsp_request_firmware_files */ 46 + static const struct firmware wm_adsp_find_test_dummy_firmware; 47 + 48 + /* Simple lookup of a filename in a list of names */ 49 + static int wm_adsp_fw_find_test_firmware_request_simple_stub(const struct firmware **firmware, 50 + const char *filename, 51 + struct device *dev) 52 + { 53 + struct kunit *test = kunit_get_current_test(); 54 + const struct wm_adsp_fw_find_test_params *params = test->param_value; 55 + int i; 56 + 57 + /* Non-parameterized test? */ 58 + if (!params) 59 + return -ENOENT; 60 + 61 + if (!params->dir_files) 62 + return -ENOENT; 63 + 64 + for (i = 0; params->dir_files[i]; i++) { 65 + if (strcmp(params->dir_files[i], filename) == 0) { 66 + *firmware = &wm_adsp_find_test_dummy_firmware; 67 + return 0; 68 + } 69 + } 70 + 71 + return -ENOENT; 72 + } 73 + 74 + static void wm_adsp_fw_find_test_pick_file(struct kunit *test) 75 + { 76 + struct wm_adsp_fw_find_test *priv = test->priv; 77 + const struct wm_adsp_fw_find_test_params *params = test->param_value; 78 + struct wm_adsp *dsp = &priv->dsp; 79 + int i, ret; 80 + 81 + /* Concatenate string of dir content for error messages */ 82 + for (i = 0; params->dir_files[i]; i++) { 83 + strlcat(priv->searched_fw_files, params->dir_files[i], 84 + sizeof(priv->searched_fw_files)); 85 + strlcat(priv->searched_fw_files, ";", 86 + sizeof(priv->searched_fw_files)); 87 + } 88 + 89 + dsp->cs_dsp.name = params->dsp_name; 90 + dsp->part = params->part; 91 + dsp->fwf_name = params->fwf_name; 92 + dsp->system_name = params->system_name; 93 + dsp->component->name_prefix = params->alsa_name; 94 + dsp->wmfw_optional = params->wmfw_optional; 95 + dsp->bin_mandatory = params->bin_mandatory; 96 + 97 + kunit_activate_static_stub(test, 98 + wm_adsp_firmware_request, 99 + wm_adsp_fw_find_test_firmware_request_simple_stub); 100 + 101 + ret = wm_adsp_request_firmware_files(dsp, &priv->found_fw); 102 + kunit_deactivate_static_stub(test, wm_adsp_firmware_request); 103 + KUNIT_EXPECT_EQ_MSG(test, ret, 104 + (params->expect_wmfw || params->expect_bin) ? 0 : -ENOENT, 105 + "%s\n", priv->searched_fw_files); 106 + 107 + KUNIT_EXPECT_EQ_MSG(test, !!priv->found_fw.wmfw.filename, !!params->expect_wmfw, 108 + "%s\n", priv->searched_fw_files); 109 + KUNIT_EXPECT_EQ_MSG(test, !!priv->found_fw.coeff.filename, !!params->expect_bin, 110 + "%s\n", priv->searched_fw_files); 111 + 112 + if (params->expect_wmfw) { 113 + KUNIT_EXPECT_STREQ_MSG(test, priv->found_fw.wmfw.filename, params->expect_wmfw, 114 + "%s\n", priv->searched_fw_files); 115 + } 116 + 117 + if (params->expect_bin) { 118 + KUNIT_EXPECT_STREQ_MSG(test, priv->found_fw.coeff.filename, params->expect_bin, 119 + "%s\n", priv->searched_fw_files); 120 + } 121 + } 122 + 123 + static int wm_adsp_fw_find_test_firmware_request_stub(const struct firmware **firmware, 124 + const char *filename, 125 + struct device *dev) 126 + { 127 + struct kunit *test = kunit_get_current_test(); 128 + const struct wm_adsp_fw_find_test_params *params = test->param_value; 129 + struct wm_adsp_fw_find_test *priv = test->priv; 130 + 131 + /* 132 + * Searches are accumulated as a single string of space-separated names. 133 + * The list of expected searches are stored the same way in 134 + * struct wm_adsp_fw_find_test_params. This allows for comparision using 135 + * a simple KUNIT_EXPECT_STREQ(), which avoids the risk of bugs in a 136 + * more complex custom comparison. 137 + */ 138 + if (priv->searched_fw_files[0] != '\0') 139 + strlcat(priv->searched_fw_files, " ", sizeof(priv->searched_fw_files)); 140 + 141 + strlcat(priv->searched_fw_files, filename, sizeof(priv->searched_fw_files)); 142 + 143 + /* Non-parameterized test? */ 144 + if (!params) 145 + return -ENOENT; 146 + 147 + if (params->expect_wmfw && (strcmp(filename, params->expect_wmfw) == 0)) { 148 + *firmware = &wm_adsp_find_test_dummy_firmware; 149 + return 0; 150 + } 151 + 152 + if (params->expect_bin && (strcmp(filename, params->expect_bin) == 0)) { 153 + *firmware = &wm_adsp_find_test_dummy_firmware; 154 + return 0; 155 + } 156 + 157 + return -ENOENT; 158 + } 159 + 160 + static void wm_adsp_fw_find_test_search_order(struct kunit *test) 161 + { 162 + struct wm_adsp_fw_find_test *priv = test->priv; 163 + const struct wm_adsp_fw_find_test_params *params = test->param_value; 164 + struct wm_adsp *dsp = &priv->dsp; 165 + 166 + dsp->cs_dsp.name = params->dsp_name; 167 + dsp->part = params->part; 168 + dsp->fwf_name = params->fwf_name; 169 + dsp->system_name = params->system_name; 170 + dsp->component->name_prefix = params->alsa_name; 171 + dsp->wmfw_optional = params->wmfw_optional; 172 + 173 + kunit_activate_static_stub(test, 174 + wm_adsp_firmware_request, 175 + wm_adsp_fw_find_test_firmware_request_stub); 176 + 177 + wm_adsp_request_firmware_files(dsp, &priv->found_fw); 178 + 179 + kunit_deactivate_static_stub(test, wm_adsp_firmware_request); 180 + 181 + KUNIT_EXPECT_STREQ(test, priv->searched_fw_files, params->expected_searches); 182 + 183 + KUNIT_EXPECT_EQ(test, !!priv->found_fw.wmfw.filename, !!params->expect_wmfw); 184 + if (params->expect_wmfw) 185 + KUNIT_EXPECT_STREQ(test, priv->found_fw.wmfw.filename, params->expect_wmfw); 186 + 187 + KUNIT_EXPECT_EQ(test, !!priv->found_fw.coeff.filename, !!params->expect_bin); 188 + if (params->expect_bin) 189 + KUNIT_EXPECT_STREQ(test, priv->found_fw.coeff.filename, params->expect_bin); 190 + 191 + /* Either we get a filename and firmware, or neither */ 192 + KUNIT_EXPECT_EQ(test, !!priv->found_fw.wmfw.filename, !!priv->found_fw.wmfw.firmware); 193 + KUNIT_EXPECT_EQ(test, !!priv->found_fw.coeff.filename, !!priv->found_fw.coeff.firmware); 194 + } 195 + 196 + static void wm_adsp_fw_find_test_find_firmware_byindex(struct kunit *test) 197 + { 198 + struct wm_adsp_fw_find_test *priv = test->priv; 199 + struct wm_adsp *dsp = &priv->dsp; 200 + const char *fw_name; 201 + 202 + dsp->cs_dsp.name = "cs1234"; 203 + dsp->part = "dsp1"; 204 + for (dsp->fw = 0;; dsp->fw++) { 205 + fw_name = wm_adsp_get_fwf_name_by_index(dsp->fw); 206 + if (!fw_name) 207 + break; 208 + 209 + kunit_activate_static_stub(test, 210 + wm_adsp_firmware_request, 211 + wm_adsp_fw_find_test_firmware_request_stub); 212 + 213 + wm_adsp_request_firmware_files(dsp, &priv->found_fw); 214 + kunit_deactivate_static_stub(test, wm_adsp_firmware_request); 215 + 216 + KUNIT_EXPECT_NOT_NULL_MSG(test, 217 + strstr(priv->searched_fw_files, fw_name), 218 + "fw#%d Did not find '%s' in '%s'\n", 219 + dsp->fw, fw_name, priv->searched_fw_files); 220 + } 221 + } 222 + 223 + static int wm_adsp_fw_find_test_case_init(struct kunit *test) 224 + { 225 + struct wm_adsp_fw_find_test *priv; 226 + struct device *test_dev; 227 + int ret; 228 + 229 + priv = kunit_kzalloc(test, sizeof(*priv), GFP_KERNEL); 230 + if (!priv) 231 + return -ENOMEM; 232 + 233 + /* Require dummy struct snd_soc_component for the alsa name prefix string */ 234 + priv->dsp.component = kunit_kzalloc(test, sizeof(*priv->dsp.component), GFP_KERNEL); 235 + if (!priv->dsp.component) 236 + return -ENOMEM; 237 + 238 + test->priv = priv; 239 + 240 + /* Create dummy amp device */ 241 + test_dev = kunit_device_register(test, "wm_adsp_test_drv"); 242 + if (IS_ERR(test_dev)) 243 + return PTR_ERR(test_dev); 244 + 245 + priv->dsp.cs_dsp.dev = get_device(test_dev); 246 + if (!priv->dsp.cs_dsp.dev) 247 + return -ENODEV; 248 + 249 + ret = kunit_add_action_or_reset(test, _put_device_wrapper, priv->dsp.cs_dsp.dev); 250 + if (ret) 251 + return ret; 252 + 253 + return 0; 254 + } 255 + 256 + static void wm_adsp_fw_find_test_case_exit(struct kunit *test) 257 + { 258 + struct wm_adsp_fw_find_test *priv = test->priv; 259 + 260 + /* 261 + * priv->found_wmfw_firmware and priv->found_bin_firmware are 262 + * dummies not allocated by the real request_firmware() call they 263 + * must not be passed to release_firmware(). 264 + */ 265 + wm_adsp_release_firmware_files(&priv->found_fw); 266 + } 267 + 268 + static void wm_adsp_fw_find_test_param_desc(const struct wm_adsp_fw_find_test_params *param, 269 + char *desc) 270 + { 271 + snprintf(desc, KUNIT_PARAM_DESC_SIZE, 272 + "%s %s fwf_name:%s system:%s alsa_name:%s %s expects:(%s %s)", 273 + param->part, param->dsp_name, 274 + param->fwf_name ? param->fwf_name : "", 275 + param->system_name ? param->system_name : "", 276 + param->alsa_name ? param->alsa_name : "", 277 + param->wmfw_optional ? "wmfw_optional" : "", 278 + param->expect_wmfw ? param->expect_wmfw : "", 279 + param->expect_bin ? param->expect_bin : ""); 280 + } 281 + 282 + /* Cases where firmware file not found. Tests full search sequence. */ 283 + static const struct wm_adsp_fw_find_test_params wm_adsp_fw_find_full_search_cases[] = { 284 + { /* system name and alsa prefix, wmfw mandatory. */ 285 + .part = "cs1234", .dsp_name = "dsp1", .system_name = "ABC123", 286 + .alsa_name = "amp1", 287 + .expected_searches = 288 + "cirrus/cs1234-dsp1-mbc-vss-abc123-amp1.wmfw " 289 + "cirrus/cs1234-dsp1-mbc-vss-abc123.wmfw " 290 + "cs1234-dsp1-mbc-vss.wmfw " 291 + "cirrus/cs1234-dsp1-mbc-vss.wmfw", 292 + }, 293 + { /* system name and alsa prefix, wmfw optional. */ 294 + .part = "cs1234", .dsp_name = "dsp1", .system_name = "ABC123", 295 + .alsa_name = "amp1", .wmfw_optional = true, 296 + .expected_searches = 297 + "cirrus/cs1234-dsp1-mbc-vss-abc123-amp1.wmfw " 298 + "cirrus/cs1234-dsp1-mbc-vss-abc123.wmfw " 299 + "cirrus/cs1234-dsp1-mbc-vss-abc123-amp1.bin " 300 + "cirrus/cs1234-dsp1-mbc-vss-abc123.bin " 301 + "cs1234-dsp1-mbc-vss.wmfw " 302 + "cirrus/cs1234-dsp1-mbc-vss.wmfw " 303 + "cirrus/cs1234-dsp1-mbc-vss.bin", 304 + }, 305 + { /* system name only, wmfw mandatory. */ 306 + .part = "cs1234", .dsp_name = "dsp1", .system_name = "ABC123", 307 + .expected_searches = 308 + "cirrus/cs1234-dsp1-mbc-vss-abc123.wmfw " 309 + "cs1234-dsp1-mbc-vss.wmfw " 310 + "cirrus/cs1234-dsp1-mbc-vss.wmfw", 311 + }, 312 + { /* system name only, wmfw optional. */ 313 + .part = "cs1234", .dsp_name = "dsp1", .system_name = "ABC123", 314 + .wmfw_optional = true, 315 + .expected_searches = 316 + "cirrus/cs1234-dsp1-mbc-vss-abc123.wmfw " 317 + "cirrus/cs1234-dsp1-mbc-vss-abc123.bin " 318 + "cs1234-dsp1-mbc-vss.wmfw " 319 + "cirrus/cs1234-dsp1-mbc-vss.wmfw " 320 + "cirrus/cs1234-dsp1-mbc-vss.bin", 321 + }, 322 + 323 + /* 324 + * TODO: Is this a bug? Device-specific bin is only allowed when there 325 + * is a system_name. But if there isn't any meaningful system name on 326 + * a product, why can't it load firmware files qualified by alsa prefix? 327 + */ 328 + 329 + { /* Alsa prefix, wmfw mandatory. No system name so generic files only. */ 330 + .part = "cs1234", .dsp_name = "dsp1", .alsa_name = "amp1", 331 + .expected_searches = 332 + "cs1234-dsp1-mbc-vss.wmfw " 333 + "cirrus/cs1234-dsp1-mbc-vss.wmfw", 334 + }, 335 + { /* Alsa prefix, wmfw optional. No system name so generic files only. */ 336 + .part = "cs1234", .dsp_name = "dsp1", .alsa_name = "amp1", 337 + .wmfw_optional = true, 338 + .expected_searches = 339 + "cs1234-dsp1-mbc-vss.wmfw " 340 + "cirrus/cs1234-dsp1-mbc-vss.wmfw " 341 + "cirrus/cs1234-dsp1-mbc-vss.bin", 342 + }, 343 + 344 + { /* fwf_name, system name and alsa prefix, wmfw mandatory. */ 345 + .part = "cs1234", .dsp_name = "dsp1", .system_name = "ABC123", 346 + .alsa_name = "amp1", .fwf_name = "ao", 347 + .expected_searches = 348 + "cirrus/cs1234-ao-mbc-vss-abc123-amp1.wmfw " 349 + "cirrus/cs1234-ao-mbc-vss-abc123.wmfw " 350 + "cs1234-ao-mbc-vss.wmfw " 351 + "cirrus/cs1234-ao-mbc-vss.wmfw", 352 + }, 353 + { /* fwf_name, system name and alsa prefix, wmfw optional. */ 354 + .part = "cs1234", .dsp_name = "dsp1", .system_name = "ABC123", 355 + .alsa_name = "amp1", .fwf_name = "ao", 356 + .wmfw_optional = true, 357 + .expected_searches = 358 + "cirrus/cs1234-ao-mbc-vss-abc123-amp1.wmfw " 359 + "cirrus/cs1234-ao-mbc-vss-abc123.wmfw " 360 + "cirrus/cs1234-ao-mbc-vss-abc123-amp1.bin " 361 + "cirrus/cs1234-ao-mbc-vss-abc123.bin " 362 + "cs1234-ao-mbc-vss.wmfw " 363 + "cirrus/cs1234-ao-mbc-vss.wmfw " 364 + "cirrus/cs1234-ao-mbc-vss.bin", 365 + }, 366 + }; 367 + KUNIT_ARRAY_PARAM(wm_adsp_fw_find_full_search, 368 + wm_adsp_fw_find_full_search_cases, 369 + wm_adsp_fw_find_test_param_desc); 370 + 371 + /* Cases with system name and alsa prefix both given. */ 372 + static const struct wm_adsp_fw_find_test_params wm_adsp_fw_find_system_alsaname_cases[] = { 373 + { /* Fully-qualified wmfw exists. No bin */ 374 + .part = "cs1234", .dsp_name = "dsp1", .system_name = "ABC123", 375 + .alsa_name = "amp1", 376 + .expect_wmfw = "cirrus/cs1234-dsp1-mbc-vss-abc123-amp1.wmfw", 377 + .expected_searches = 378 + "cirrus/cs1234-dsp1-mbc-vss-abc123-amp1.wmfw " 379 + "cirrus/cs1234-dsp1-mbc-vss-abc123-amp1.bin", 380 + }, 381 + { /* Optional fully-qualified wmfw exists. No bin */ 382 + .part = "cs1234", .dsp_name = "dsp1", .system_name = "ABC123", 383 + .alsa_name = "amp1", .wmfw_optional = true, 384 + .expect_wmfw = "cirrus/cs1234-dsp1-mbc-vss-abc123-amp1.wmfw", 385 + .expected_searches = 386 + "cirrus/cs1234-dsp1-mbc-vss-abc123-amp1.wmfw " 387 + "cirrus/cs1234-dsp1-mbc-vss-abc123-amp1.bin", 388 + }, 389 + { /* Fully-qualified wmfw and bin exist. */ 390 + .part = "cs1234", .dsp_name = "dsp1", .system_name = "ABC123", 391 + .alsa_name = "amp1", 392 + .expect_wmfw = "cirrus/cs1234-dsp1-mbc-vss-abc123-amp1.wmfw", 393 + .expect_bin = "cirrus/cs1234-dsp1-mbc-vss-abc123-amp1.bin", 394 + .expected_searches = 395 + "cirrus/cs1234-dsp1-mbc-vss-abc123-amp1.wmfw " 396 + "cirrus/cs1234-dsp1-mbc-vss-abc123-amp1.bin", 397 + }, 398 + { /* Optional fully-qualified wmfw and fully-qualified bin exist. */ 399 + .part = "cs1234", .dsp_name = "dsp1", .system_name = "ABC123", 400 + .alsa_name = "amp1", .wmfw_optional = true, 401 + .expect_wmfw = "cirrus/cs1234-dsp1-mbc-vss-abc123-amp1.wmfw", 402 + .expect_bin = "cirrus/cs1234-dsp1-mbc-vss-abc123-amp1.bin", 403 + .expected_searches = 404 + "cirrus/cs1234-dsp1-mbc-vss-abc123-amp1.wmfw " 405 + "cirrus/cs1234-dsp1-mbc-vss-abc123-amp1.bin", 406 + }, 407 + { /* wmfw matches system name only. No bin */ 408 + .part = "cs1234", .dsp_name = "dsp1", .system_name = "ABC123", 409 + .alsa_name = "amp1", 410 + .expect_wmfw = "cirrus/cs1234-dsp1-mbc-vss-abc123.wmfw", 411 + .expected_searches = 412 + "cirrus/cs1234-dsp1-mbc-vss-abc123-amp1.wmfw " 413 + "cirrus/cs1234-dsp1-mbc-vss-abc123.wmfw " 414 + "cirrus/cs1234-dsp1-mbc-vss-abc123-amp1.bin " 415 + "cirrus/cs1234-dsp1-mbc-vss-abc123.bin", 416 + }, 417 + { /* Optional wmfw matches system name only. No bin */ 418 + .part = "cs1234", .dsp_name = "dsp1", .system_name = "ABC123", 419 + .alsa_name = "amp1", .wmfw_optional = true, 420 + .expect_wmfw = "cirrus/cs1234-dsp1-mbc-vss-abc123.wmfw", 421 + .expected_searches = 422 + "cirrus/cs1234-dsp1-mbc-vss-abc123-amp1.wmfw " 423 + "cirrus/cs1234-dsp1-mbc-vss-abc123.wmfw " 424 + "cirrus/cs1234-dsp1-mbc-vss-abc123-amp1.bin " 425 + "cirrus/cs1234-dsp1-mbc-vss-abc123.bin", 426 + }, 427 + { /* wmfw matches system name only. Fully-qualified bin. */ 428 + .part = "cs1234", .dsp_name = "dsp1", .system_name = "ABC123", 429 + .alsa_name = "amp1", 430 + .expect_wmfw = "cirrus/cs1234-dsp1-mbc-vss-abc123.wmfw", 431 + .expect_bin = "cirrus/cs1234-dsp1-mbc-vss-abc123-amp1.bin", 432 + .expected_searches = 433 + "cirrus/cs1234-dsp1-mbc-vss-abc123-amp1.wmfw " 434 + "cirrus/cs1234-dsp1-mbc-vss-abc123.wmfw " 435 + "cirrus/cs1234-dsp1-mbc-vss-abc123-amp1.bin", 436 + }, 437 + { /* Optional wmfw matches system name only. Fully-qualified bin. */ 438 + .part = "cs1234", .dsp_name = "dsp1", .system_name = "ABC123", 439 + .alsa_name = "amp1", .wmfw_optional = true, 440 + .expect_wmfw = "cirrus/cs1234-dsp1-mbc-vss-abc123.wmfw", 441 + .expect_bin = "cirrus/cs1234-dsp1-mbc-vss-abc123-amp1.bin", 442 + .expected_searches = 443 + "cirrus/cs1234-dsp1-mbc-vss-abc123-amp1.wmfw " 444 + "cirrus/cs1234-dsp1-mbc-vss-abc123.wmfw " 445 + "cirrus/cs1234-dsp1-mbc-vss-abc123-amp1.bin", 446 + }, 447 + { /* wmfw and bin match system name only. */ 448 + .part = "cs1234", .dsp_name = "dsp1", .system_name = "ABC123", 449 + .alsa_name = "amp1", 450 + .expect_wmfw = "cirrus/cs1234-dsp1-mbc-vss-abc123.wmfw", 451 + .expect_bin = "cirrus/cs1234-dsp1-mbc-vss-abc123.bin", 452 + .expected_searches = 453 + "cirrus/cs1234-dsp1-mbc-vss-abc123-amp1.wmfw " 454 + "cirrus/cs1234-dsp1-mbc-vss-abc123.wmfw " 455 + "cirrus/cs1234-dsp1-mbc-vss-abc123-amp1.bin " 456 + "cirrus/cs1234-dsp1-mbc-vss-abc123.bin", 457 + }, 458 + { /* Optional wmfw and bin match system name only. */ 459 + .part = "cs1234", .dsp_name = "dsp1", .system_name = "ABC123", 460 + .alsa_name = "amp1", .wmfw_optional = true, 461 + .expect_wmfw = "cirrus/cs1234-dsp1-mbc-vss-abc123.wmfw", 462 + .expect_bin = "cirrus/cs1234-dsp1-mbc-vss-abc123.bin", 463 + .expected_searches = 464 + "cirrus/cs1234-dsp1-mbc-vss-abc123-amp1.wmfw " 465 + "cirrus/cs1234-dsp1-mbc-vss-abc123.wmfw " 466 + "cirrus/cs1234-dsp1-mbc-vss-abc123-amp1.bin " 467 + "cirrus/cs1234-dsp1-mbc-vss-abc123.bin", 468 + }, 469 + { /* Optional wmfw not found. bin matches fully-qualified name. */ 470 + .part = "cs1234", .dsp_name = "dsp1", .system_name = "ABC123", 471 + .alsa_name = "amp1", .wmfw_optional = true, 472 + .expect_bin = "cirrus/cs1234-dsp1-mbc-vss-abc123-amp1.bin", 473 + .expected_searches = 474 + "cirrus/cs1234-dsp1-mbc-vss-abc123-amp1.wmfw " 475 + "cirrus/cs1234-dsp1-mbc-vss-abc123.wmfw " 476 + "cirrus/cs1234-dsp1-mbc-vss-abc123-amp1.bin", 477 + }, 478 + { /* Optional wmfw not found. bin matches system name only. */ 479 + .part = "cs1234", .dsp_name = "dsp1", .system_name = "ABC123", 480 + .alsa_name = "amp1", .wmfw_optional = true, 481 + .expect_bin = "cirrus/cs1234-dsp1-mbc-vss-abc123.bin", 482 + .expected_searches = 483 + "cirrus/cs1234-dsp1-mbc-vss-abc123-amp1.wmfw " 484 + "cirrus/cs1234-dsp1-mbc-vss-abc123.wmfw " 485 + "cirrus/cs1234-dsp1-mbc-vss-abc123-amp1.bin " 486 + "cirrus/cs1234-dsp1-mbc-vss-abc123.bin", 487 + }, 488 + { /* No qualified wmfw. Legacy generic wmfw found. No bin. */ 489 + .part = "cs1234", .dsp_name = "dsp1", .system_name = "ABC123", 490 + .alsa_name = "amp1", 491 + .expect_wmfw = "cs1234-dsp1-mbc-vss.wmfw", 492 + .expected_searches = 493 + "cirrus/cs1234-dsp1-mbc-vss-abc123-amp1.wmfw " 494 + "cirrus/cs1234-dsp1-mbc-vss-abc123.wmfw " 495 + "cs1234-dsp1-mbc-vss.wmfw " 496 + "cs1234-dsp1-mbc-vss.bin", 497 + }, 498 + { /* No qualified optional wmfw. Legacy generic wmfw found. No bin. */ 499 + .part = "cs1234", .dsp_name = "dsp1", .system_name = "ABC123", 500 + .alsa_name = "amp1", .wmfw_optional = true, 501 + .expect_wmfw = "cs1234-dsp1-mbc-vss.wmfw", 502 + .expected_searches = 503 + "cirrus/cs1234-dsp1-mbc-vss-abc123-amp1.wmfw " 504 + "cirrus/cs1234-dsp1-mbc-vss-abc123.wmfw " 505 + "cirrus/cs1234-dsp1-mbc-vss-abc123-amp1.bin " 506 + "cirrus/cs1234-dsp1-mbc-vss-abc123.bin " 507 + "cs1234-dsp1-mbc-vss.wmfw " 508 + "cs1234-dsp1-mbc-vss.bin", 509 + }, 510 + { /* No qualified wmfw. Legacy generic wmfw and bin found. */ 511 + .part = "cs1234", .dsp_name = "dsp1", .system_name = "ABC123", 512 + .alsa_name = "amp1", 513 + .expect_wmfw = "cs1234-dsp1-mbc-vss.wmfw", 514 + .expect_bin = "cs1234-dsp1-mbc-vss.bin", 515 + .expected_searches = 516 + "cirrus/cs1234-dsp1-mbc-vss-abc123-amp1.wmfw " 517 + "cirrus/cs1234-dsp1-mbc-vss-abc123.wmfw " 518 + "cs1234-dsp1-mbc-vss.wmfw " 519 + "cs1234-dsp1-mbc-vss.bin", 520 + }, 521 + { /* No qualified optional wmfw. Legacy generic wmfw and bin found. */ 522 + .part = "cs1234", .dsp_name = "dsp1", .system_name = "ABC123", 523 + .alsa_name = "amp1", .wmfw_optional = true, 524 + .expect_wmfw = "cs1234-dsp1-mbc-vss.wmfw", 525 + .expect_bin = "cs1234-dsp1-mbc-vss.bin", 526 + .expected_searches = 527 + "cirrus/cs1234-dsp1-mbc-vss-abc123-amp1.wmfw " 528 + "cirrus/cs1234-dsp1-mbc-vss-abc123.wmfw " 529 + "cirrus/cs1234-dsp1-mbc-vss-abc123-amp1.bin " 530 + "cirrus/cs1234-dsp1-mbc-vss-abc123.bin " 531 + "cs1234-dsp1-mbc-vss.wmfw " 532 + "cs1234-dsp1-mbc-vss.bin", 533 + }, 534 + { /* No qualified or legacy wmfw. Generic wmfw found. No bin. */ 535 + .part = "cs1234", .dsp_name = "dsp1", .system_name = "ABC123", 536 + .alsa_name = "amp1", 537 + .expect_wmfw = "cirrus/cs1234-dsp1-mbc-vss.wmfw", 538 + .expected_searches = 539 + "cirrus/cs1234-dsp1-mbc-vss-abc123-amp1.wmfw " 540 + "cirrus/cs1234-dsp1-mbc-vss-abc123.wmfw " 541 + "cs1234-dsp1-mbc-vss.wmfw " 542 + "cirrus/cs1234-dsp1-mbc-vss.wmfw " 543 + "cirrus/cs1234-dsp1-mbc-vss.bin", 544 + }, 545 + { /* No optional qualified or legacy wmfw. Generic wmfw found. No bin. */ 546 + .part = "cs1234", .dsp_name = "dsp1", .system_name = "ABC123", 547 + .alsa_name = "amp1", .wmfw_optional = true, 548 + .expect_wmfw = "cirrus/cs1234-dsp1-mbc-vss.wmfw", 549 + .expected_searches = 550 + "cirrus/cs1234-dsp1-mbc-vss-abc123-amp1.wmfw " 551 + "cirrus/cs1234-dsp1-mbc-vss-abc123.wmfw " 552 + "cirrus/cs1234-dsp1-mbc-vss-abc123-amp1.bin " 553 + "cirrus/cs1234-dsp1-mbc-vss-abc123.bin " 554 + "cs1234-dsp1-mbc-vss.wmfw " 555 + "cirrus/cs1234-dsp1-mbc-vss.wmfw " 556 + "cirrus/cs1234-dsp1-mbc-vss.bin", 557 + }, 558 + { /* No qualified or legacy wmfw. Generic wmfw and bin found. */ 559 + .part = "cs1234", .dsp_name = "dsp1", .system_name = "ABC123", 560 + .alsa_name = "amp1", 561 + .expect_wmfw = "cirrus/cs1234-dsp1-mbc-vss.wmfw", 562 + .expect_bin = "cirrus/cs1234-dsp1-mbc-vss.bin", 563 + .expected_searches = 564 + "cirrus/cs1234-dsp1-mbc-vss-abc123-amp1.wmfw " 565 + "cirrus/cs1234-dsp1-mbc-vss-abc123.wmfw " 566 + "cs1234-dsp1-mbc-vss.wmfw " 567 + "cirrus/cs1234-dsp1-mbc-vss.wmfw " 568 + "cirrus/cs1234-dsp1-mbc-vss.bin", 569 + }, 570 + { /* No optional qualified or legacy wmfw. Generic wmfw and bin found. */ 571 + .part = "cs1234", .dsp_name = "dsp1", .system_name = "ABC123", 572 + .alsa_name = "amp1", .wmfw_optional = true, 573 + .expect_wmfw = "cirrus/cs1234-dsp1-mbc-vss.wmfw", 574 + .expect_bin = "cirrus/cs1234-dsp1-mbc-vss.bin", 575 + .expected_searches = 576 + "cirrus/cs1234-dsp1-mbc-vss-abc123-amp1.wmfw " 577 + "cirrus/cs1234-dsp1-mbc-vss-abc123.wmfw " 578 + "cirrus/cs1234-dsp1-mbc-vss-abc123-amp1.bin " 579 + "cirrus/cs1234-dsp1-mbc-vss-abc123.bin " 580 + "cs1234-dsp1-mbc-vss.wmfw " 581 + "cirrus/cs1234-dsp1-mbc-vss.wmfw " 582 + "cirrus/cs1234-dsp1-mbc-vss.bin", 583 + }, 584 + { /* No optional qualified or generic wmfw. Generic bin found. */ 585 + .part = "cs1234", .dsp_name = "dsp1", .system_name = "ABC123", 586 + .alsa_name = "amp1", .wmfw_optional = true, 587 + .expect_bin = "cirrus/cs1234-dsp1-mbc-vss.bin", 588 + .expected_searches = 589 + "cirrus/cs1234-dsp1-mbc-vss-abc123-amp1.wmfw " 590 + "cirrus/cs1234-dsp1-mbc-vss-abc123.wmfw " 591 + "cirrus/cs1234-dsp1-mbc-vss-abc123-amp1.bin " 592 + "cirrus/cs1234-dsp1-mbc-vss-abc123.bin " 593 + "cs1234-dsp1-mbc-vss.wmfw " 594 + "cirrus/cs1234-dsp1-mbc-vss.wmfw " 595 + "cirrus/cs1234-dsp1-mbc-vss.bin", 596 + }, 597 + }; 598 + KUNIT_ARRAY_PARAM(wm_adsp_fw_find_system_alsaname, 599 + wm_adsp_fw_find_system_alsaname_cases, 600 + wm_adsp_fw_find_test_param_desc); 601 + 602 + /* Cases with system name but without alsa name prefix. */ 603 + static const struct wm_adsp_fw_find_test_params wm_adsp_fw_find_system_cases[] = { 604 + { /* Qualified wmfw found. No bin */ 605 + .part = "cs1234", .dsp_name = "dsp1", .system_name = "ABC123", 606 + .expect_wmfw = "cirrus/cs1234-dsp1-mbc-vss-abc123.wmfw", 607 + .expected_searches = 608 + "cirrus/cs1234-dsp1-mbc-vss-abc123.wmfw " 609 + "cirrus/cs1234-dsp1-mbc-vss-abc123.bin", 610 + }, 611 + { /* Optional qualified wmfw found. No bin */ 612 + .part = "cs1234", .dsp_name = "dsp1", .system_name = "ABC123", 613 + .wmfw_optional = true, 614 + .expect_wmfw = "cirrus/cs1234-dsp1-mbc-vss-abc123.wmfw", 615 + .expected_searches = 616 + "cirrus/cs1234-dsp1-mbc-vss-abc123.wmfw " 617 + "cirrus/cs1234-dsp1-mbc-vss-abc123.bin", 618 + }, 619 + { /* Qualified wmfw found. Qualified bin found. */ 620 + .part = "cs1234", .dsp_name = "dsp1", .system_name = "ABC123", 621 + .expect_wmfw = "cirrus/cs1234-dsp1-mbc-vss-abc123.wmfw", 622 + .expect_bin = "cirrus/cs1234-dsp1-mbc-vss-abc123.bin", 623 + .expected_searches = 624 + "cirrus/cs1234-dsp1-mbc-vss-abc123.wmfw " 625 + "cirrus/cs1234-dsp1-mbc-vss-abc123.bin", 626 + }, 627 + { /* Optional qualified wmfw found. Qualified bin found. */ 628 + .part = "cs1234", .dsp_name = "dsp1", .system_name = "ABC123", 629 + .wmfw_optional = true, 630 + .expect_wmfw = "cirrus/cs1234-dsp1-mbc-vss-abc123.wmfw", 631 + .expect_bin = "cirrus/cs1234-dsp1-mbc-vss-abc123.bin", 632 + .expected_searches = 633 + "cirrus/cs1234-dsp1-mbc-vss-abc123.wmfw " 634 + "cirrus/cs1234-dsp1-mbc-vss-abc123.bin", 635 + }, 636 + { /* Optional wmfw not found. Qualified bin found. */ 637 + .part = "cs1234", .dsp_name = "dsp1", .system_name = "ABC123", 638 + .wmfw_optional = true, 639 + .expect_bin = "cirrus/cs1234-dsp1-mbc-vss-abc123.bin", 640 + .expected_searches = 641 + "cirrus/cs1234-dsp1-mbc-vss-abc123.wmfw " 642 + "cirrus/cs1234-dsp1-mbc-vss-abc123.bin", 643 + }, 644 + { /* No qualified wmfw. Legacy generic wmfw found. No bin. */ 645 + .part = "cs1234", .dsp_name = "dsp1", .system_name = "ABC123", 646 + .expect_wmfw = "cs1234-dsp1-mbc-vss.wmfw", 647 + .expected_searches = 648 + "cirrus/cs1234-dsp1-mbc-vss-abc123.wmfw " 649 + "cs1234-dsp1-mbc-vss.wmfw " 650 + "cs1234-dsp1-mbc-vss.bin", 651 + }, 652 + { /* No qualified optional wmfw. Legacy generic wmfw found. No bin. */ 653 + .part = "cs1234", .dsp_name = "dsp1", .system_name = "ABC123", 654 + .wmfw_optional = true, 655 + .expect_wmfw = "cs1234-dsp1-mbc-vss.wmfw", 656 + .expected_searches = 657 + "cirrus/cs1234-dsp1-mbc-vss-abc123.wmfw " 658 + "cirrus/cs1234-dsp1-mbc-vss-abc123.bin " 659 + "cs1234-dsp1-mbc-vss.wmfw " 660 + "cs1234-dsp1-mbc-vss.bin", 661 + }, 662 + { /* No qualified wmfw. Legacy generic wmfw and bin found. */ 663 + .part = "cs1234", .dsp_name = "dsp1", .system_name = "ABC123", 664 + .expect_wmfw = "cs1234-dsp1-mbc-vss.wmfw", 665 + .expect_bin = "cs1234-dsp1-mbc-vss.bin", 666 + .expected_searches = 667 + "cirrus/cs1234-dsp1-mbc-vss-abc123.wmfw " 668 + "cs1234-dsp1-mbc-vss.wmfw " 669 + "cs1234-dsp1-mbc-vss.bin", 670 + }, 671 + { /* No qualified optional wmfw. Legacy generic wmfw and bin found. */ 672 + .part = "cs1234", .dsp_name = "dsp1", .system_name = "ABC123", 673 + .wmfw_optional = true, 674 + .expect_wmfw = "cs1234-dsp1-mbc-vss.wmfw", 675 + .expect_bin = "cs1234-dsp1-mbc-vss.bin", 676 + .expected_searches = 677 + "cirrus/cs1234-dsp1-mbc-vss-abc123.wmfw " 678 + "cirrus/cs1234-dsp1-mbc-vss-abc123.bin " 679 + "cs1234-dsp1-mbc-vss.wmfw " 680 + "cs1234-dsp1-mbc-vss.bin", 681 + }, 682 + { /* No qualified or legacy wmfw. Generic wmfw found. No bin. */ 683 + .part = "cs1234", .dsp_name = "dsp1", .system_name = "ABC123", 684 + .expect_wmfw = "cirrus/cs1234-dsp1-mbc-vss.wmfw", 685 + .expected_searches = 686 + "cirrus/cs1234-dsp1-mbc-vss-abc123.wmfw " 687 + "cs1234-dsp1-mbc-vss.wmfw " 688 + "cirrus/cs1234-dsp1-mbc-vss.wmfw " 689 + "cirrus/cs1234-dsp1-mbc-vss.bin", 690 + }, 691 + { /* No optional qualified or legacy wmfw. Generic wmfw found. No bin. */ 692 + .part = "cs1234", .dsp_name = "dsp1", .system_name = "ABC123", 693 + .wmfw_optional = true, 694 + .expect_wmfw = "cirrus/cs1234-dsp1-mbc-vss.wmfw", 695 + .expected_searches = 696 + "cirrus/cs1234-dsp1-mbc-vss-abc123.wmfw " 697 + "cirrus/cs1234-dsp1-mbc-vss-abc123.bin " 698 + "cs1234-dsp1-mbc-vss.wmfw " 699 + "cirrus/cs1234-dsp1-mbc-vss.wmfw " 700 + "cirrus/cs1234-dsp1-mbc-vss.bin", 701 + }, 702 + { /* No qualified or legacy wmfw. Generic wmfw and bin found. */ 703 + .part = "cs1234", .dsp_name = "dsp1", .system_name = "ABC123", 704 + .expect_wmfw = "cirrus/cs1234-dsp1-mbc-vss.wmfw", 705 + .expect_bin = "cirrus/cs1234-dsp1-mbc-vss.bin", 706 + .expected_searches = 707 + "cirrus/cs1234-dsp1-mbc-vss-abc123.wmfw " 708 + "cs1234-dsp1-mbc-vss.wmfw " 709 + "cirrus/cs1234-dsp1-mbc-vss.wmfw " 710 + "cirrus/cs1234-dsp1-mbc-vss.bin", 711 + }, 712 + { /* No optional qualified or legacy wmfw. Generic wmfw and bin found. */ 713 + .part = "cs1234", .dsp_name = "dsp1", .system_name = "ABC123", 714 + .wmfw_optional = true, 715 + .expect_wmfw = "cirrus/cs1234-dsp1-mbc-vss.wmfw", 716 + .expect_bin = "cirrus/cs1234-dsp1-mbc-vss.bin", 717 + .expected_searches = 718 + "cirrus/cs1234-dsp1-mbc-vss-abc123.wmfw " 719 + "cirrus/cs1234-dsp1-mbc-vss-abc123.bin " 720 + "cs1234-dsp1-mbc-vss.wmfw " 721 + "cirrus/cs1234-dsp1-mbc-vss.wmfw " 722 + "cirrus/cs1234-dsp1-mbc-vss.bin", 723 + }, 724 + { /* No optional qualified or generic wmfw. Generic bin found. */ 725 + .part = "cs1234", .dsp_name = "dsp1", .system_name = "ABC123", 726 + .wmfw_optional = true, 727 + .expect_bin = "cirrus/cs1234-dsp1-mbc-vss.bin", 728 + .expected_searches = 729 + "cirrus/cs1234-dsp1-mbc-vss-abc123.wmfw " 730 + "cirrus/cs1234-dsp1-mbc-vss-abc123.bin " 731 + "cs1234-dsp1-mbc-vss.wmfw " 732 + "cirrus/cs1234-dsp1-mbc-vss.wmfw " 733 + "cirrus/cs1234-dsp1-mbc-vss.bin", 734 + }, 735 + }; 736 + KUNIT_ARRAY_PARAM(wm_adsp_fw_find_system, 737 + wm_adsp_fw_find_system_cases, 738 + wm_adsp_fw_find_test_param_desc); 739 + 740 + /* Cases without system name but with alsa name prefix. */ 741 + static const struct wm_adsp_fw_find_test_params wm_adsp_fw_find_alsaname_cases[] = { 742 + { /* Legacy generic wmfw found. No bin. */ 743 + .part = "cs1234", .dsp_name = "dsp1", .alsa_name = "amp1", 744 + .expect_wmfw = "cs1234-dsp1-mbc-vss.wmfw", 745 + .expected_searches = 746 + "cs1234-dsp1-mbc-vss.wmfw " 747 + "cs1234-dsp1-mbc-vss.bin", 748 + }, 749 + { /* wmfw optional. Legacy generic wmfw found. No bin. */ 750 + .part = "cs1234", .dsp_name = "dsp1", .alsa_name = "amp1", 751 + .wmfw_optional = true, 752 + .expect_wmfw = "cs1234-dsp1-mbc-vss.wmfw", 753 + .expected_searches = 754 + "cs1234-dsp1-mbc-vss.wmfw " 755 + "cs1234-dsp1-mbc-vss.bin", 756 + }, 757 + { /* Legacy generic wmfw and bin found. */ 758 + .part = "cs1234", .dsp_name = "dsp1", .alsa_name = "amp1", 759 + .expect_wmfw = "cs1234-dsp1-mbc-vss.wmfw", 760 + .expect_bin = "cs1234-dsp1-mbc-vss.bin", 761 + .expected_searches = 762 + "cs1234-dsp1-mbc-vss.wmfw " 763 + "cs1234-dsp1-mbc-vss.bin", 764 + }, 765 + { /* wmfw optional. Legacy generic wmfw and bin found. */ 766 + .part = "cs1234", .dsp_name = "dsp1", .alsa_name = "amp1", 767 + .wmfw_optional = true, 768 + .expect_wmfw = "cs1234-dsp1-mbc-vss.wmfw", 769 + .expect_bin = "cs1234-dsp1-mbc-vss.bin", 770 + .expected_searches = 771 + "cs1234-dsp1-mbc-vss.wmfw " 772 + "cs1234-dsp1-mbc-vss.bin", 773 + }, 774 + { /* No legacy wmfw. Generic wmfw found. No bin. */ 775 + .part = "cs1234", .dsp_name = "dsp1", .alsa_name = "amp1", 776 + .expect_wmfw = "cirrus/cs1234-dsp1-mbc-vss.wmfw", 777 + .expected_searches = 778 + "cs1234-dsp1-mbc-vss.wmfw " 779 + "cirrus/cs1234-dsp1-mbc-vss.wmfw " 780 + "cirrus/cs1234-dsp1-mbc-vss.bin", 781 + }, 782 + { /* No legacy wmfw. Optional generic wmfw found. No bin. */ 783 + .part = "cs1234", .dsp_name = "dsp1", .alsa_name = "amp1", 784 + .wmfw_optional = true, 785 + .expect_wmfw = "cirrus/cs1234-dsp1-mbc-vss.wmfw", 786 + .expected_searches = 787 + "cs1234-dsp1-mbc-vss.wmfw " 788 + "cirrus/cs1234-dsp1-mbc-vss.wmfw " 789 + "cirrus/cs1234-dsp1-mbc-vss.bin", 790 + }, 791 + { /* No legacy wmfw. Generic wmfw and bin found. */ 792 + .part = "cs1234", .dsp_name = "dsp1", .alsa_name = "amp1", 793 + .expect_wmfw = "cirrus/cs1234-dsp1-mbc-vss.wmfw", 794 + .expect_bin = "cirrus/cs1234-dsp1-mbc-vss.bin", 795 + .expected_searches = 796 + "cs1234-dsp1-mbc-vss.wmfw " 797 + "cirrus/cs1234-dsp1-mbc-vss.wmfw " 798 + "cirrus/cs1234-dsp1-mbc-vss.bin", 799 + }, 800 + { /* No legacy wmfw. Optional generic wmfw and bin found. */ 801 + .part = "cs1234", .dsp_name = "dsp1", .alsa_name = "amp1", 802 + .wmfw_optional = true, 803 + .expect_wmfw = "cirrus/cs1234-dsp1-mbc-vss.wmfw", 804 + .expect_bin = "cirrus/cs1234-dsp1-mbc-vss.bin", 805 + .expected_searches = 806 + "cs1234-dsp1-mbc-vss.wmfw " 807 + "cirrus/cs1234-dsp1-mbc-vss.wmfw " 808 + "cirrus/cs1234-dsp1-mbc-vss.bin", 809 + }, 810 + { /* No legacy or generic wmfw. Generic bin found. */ 811 + .part = "cs1234", .dsp_name = "dsp1", .alsa_name = "amp1", 812 + .wmfw_optional = true, 813 + .expect_bin = "cirrus/cs1234-dsp1-mbc-vss.bin", 814 + .expected_searches = 815 + "cs1234-dsp1-mbc-vss.wmfw " 816 + "cirrus/cs1234-dsp1-mbc-vss.wmfw " 817 + "cirrus/cs1234-dsp1-mbc-vss.bin", 818 + }, 819 + }; 820 + KUNIT_ARRAY_PARAM(wm_adsp_fw_find_alsaname, 821 + wm_adsp_fw_find_alsaname_cases, 822 + wm_adsp_fw_find_test_param_desc); 823 + 824 + /* Cases without system name or alsa name prefix. */ 825 + static const struct wm_adsp_fw_find_test_params wm_adsp_fw_find_noqual_cases[] = { 826 + { /* Legacy generic wmfw found. No bin. */ 827 + .part = "cs1234", .dsp_name = "dsp1", 828 + .expect_wmfw = "cs1234-dsp1-mbc-vss.wmfw", 829 + .expected_searches = 830 + "cs1234-dsp1-mbc-vss.wmfw " 831 + "cs1234-dsp1-mbc-vss.bin", 832 + }, 833 + { /* wmfw optional. Legacy generic wmfw found. No bin. */ 834 + .part = "cs1234", .dsp_name = "dsp1", 835 + .wmfw_optional = true, 836 + .expect_wmfw = "cs1234-dsp1-mbc-vss.wmfw", 837 + .expected_searches = 838 + "cs1234-dsp1-mbc-vss.wmfw " 839 + "cs1234-dsp1-mbc-vss.bin", 840 + }, 841 + { /* Legacy generic wmfw and bin found. */ 842 + .part = "cs1234", .dsp_name = "dsp1", 843 + .expect_wmfw = "cs1234-dsp1-mbc-vss.wmfw", 844 + .expect_bin = "cs1234-dsp1-mbc-vss.bin", 845 + .expected_searches = 846 + "cs1234-dsp1-mbc-vss.wmfw " 847 + "cs1234-dsp1-mbc-vss.bin", 848 + }, 849 + { /* wmfw optional. Legacy generic wmfw and bin found. */ 850 + .part = "cs1234", .dsp_name = "dsp1", 851 + .wmfw_optional = true, 852 + .expect_wmfw = "cs1234-dsp1-mbc-vss.wmfw", 853 + .expect_bin = "cs1234-dsp1-mbc-vss.bin", 854 + .expected_searches = 855 + "cs1234-dsp1-mbc-vss.wmfw " 856 + "cs1234-dsp1-mbc-vss.bin", 857 + }, 858 + { /* No legacy wmfw. Generic wmfw found. No bin. */ 859 + .part = "cs1234", .dsp_name = "dsp1", 860 + .expect_wmfw = "cirrus/cs1234-dsp1-mbc-vss.wmfw", 861 + .expected_searches = 862 + "cs1234-dsp1-mbc-vss.wmfw " 863 + "cirrus/cs1234-dsp1-mbc-vss.wmfw " 864 + "cirrus/cs1234-dsp1-mbc-vss.bin", 865 + }, 866 + { /* No legacy wmfw. Optional generic wmfw found. No bin. */ 867 + .part = "cs1234", .dsp_name = "dsp1", 868 + .wmfw_optional = true, 869 + .expect_wmfw = "cirrus/cs1234-dsp1-mbc-vss.wmfw", 870 + .expected_searches = 871 + "cs1234-dsp1-mbc-vss.wmfw " 872 + "cirrus/cs1234-dsp1-mbc-vss.wmfw " 873 + "cirrus/cs1234-dsp1-mbc-vss.bin", 874 + }, 875 + { /* No legacy wmfw. Generic wmfw and bin found. */ 876 + .part = "cs1234", .dsp_name = "dsp1", 877 + .expect_wmfw = "cirrus/cs1234-dsp1-mbc-vss.wmfw", 878 + .expect_bin = "cirrus/cs1234-dsp1-mbc-vss.bin", 879 + .expected_searches = 880 + "cs1234-dsp1-mbc-vss.wmfw " 881 + "cirrus/cs1234-dsp1-mbc-vss.wmfw " 882 + "cirrus/cs1234-dsp1-mbc-vss.bin", 883 + }, 884 + { /* No legacy wmfw. Optional generic wmfw and bin found. */ 885 + .part = "cs1234", .dsp_name = "dsp1", 886 + .wmfw_optional = true, 887 + .expect_wmfw = "cirrus/cs1234-dsp1-mbc-vss.wmfw", 888 + .expect_bin = "cirrus/cs1234-dsp1-mbc-vss.bin", 889 + .expected_searches = 890 + "cs1234-dsp1-mbc-vss.wmfw " 891 + "cirrus/cs1234-dsp1-mbc-vss.wmfw " 892 + "cirrus/cs1234-dsp1-mbc-vss.bin", 893 + }, 894 + { /* No legacy or generic wmfw. Generic bin found. */ 895 + .part = "cs1234", .dsp_name = "dsp1", 896 + .wmfw_optional = true, 897 + .expect_bin = "cirrus/cs1234-dsp1-mbc-vss.bin", 898 + .expected_searches = 899 + "cs1234-dsp1-mbc-vss.wmfw " 900 + "cirrus/cs1234-dsp1-mbc-vss.wmfw " 901 + "cirrus/cs1234-dsp1-mbc-vss.bin", 902 + }, 903 + }; 904 + KUNIT_ARRAY_PARAM(wm_adsp_fw_find_noqual, 905 + wm_adsp_fw_find_noqual_cases, 906 + wm_adsp_fw_find_test_param_desc); 907 + 908 + /* 909 + * Tests for filename normalization. The system name and alsa prefix strings 910 + * should be converted to lower-case and delimiters are converted to '-', except 911 + * for '.' which is preserved. 912 + */ 913 + static const struct wm_adsp_fw_find_test_params wm_adsp_fw_find_normalization_cases[] = { 914 + { 915 + .part = "cs1234", .dsp_name = "dsp1", .system_name = "Vendor", 916 + .expect_wmfw = "cirrus/cs1234-dsp1-mbc-vss-vendor.wmfw", 917 + .expected_searches = 918 + "cirrus/cs1234-dsp1-mbc-vss-vendor.wmfw " 919 + "cirrus/cs1234-dsp1-mbc-vss-vendor.bin", 920 + }, 921 + { 922 + .part = "cs1234", .dsp_name = "dsp1", .system_name = "Vendor Device", 923 + .expect_wmfw = "cirrus/cs1234-dsp1-mbc-vss-vendor-device.wmfw", 924 + .expected_searches = 925 + "cirrus/cs1234-dsp1-mbc-vss-vendor-device.wmfw " 926 + "cirrus/cs1234-dsp1-mbc-vss-vendor-device.bin", 927 + }, 928 + { 929 + .part = "cs1234", .dsp_name = "dsp1", .system_name = "Vendor_Device", 930 + .expect_wmfw = "cirrus/cs1234-dsp1-mbc-vss-vendor-device.wmfw", 931 + .expected_searches = 932 + "cirrus/cs1234-dsp1-mbc-vss-vendor-device.wmfw " 933 + "cirrus/cs1234-dsp1-mbc-vss-vendor-device.bin", 934 + }, 935 + { 936 + .part = "cs1234", .dsp_name = "dsp1", .system_name = "Vendor/Device", 937 + .expect_wmfw = "cirrus/cs1234-dsp1-mbc-vss-vendor-device.wmfw", 938 + .expected_searches = 939 + "cirrus/cs1234-dsp1-mbc-vss-vendor-device.wmfw " 940 + "cirrus/cs1234-dsp1-mbc-vss-vendor-device.bin", 941 + }, 942 + { 943 + .part = "cs1234", .dsp_name = "dsp1", .system_name = "1234:56AB", 944 + .expect_wmfw = "cirrus/cs1234-dsp1-mbc-vss-1234-56ab.wmfw", 945 + .expected_searches = 946 + "cirrus/cs1234-dsp1-mbc-vss-1234-56ab.wmfw " 947 + "cirrus/cs1234-dsp1-mbc-vss-1234-56ab.bin", 948 + }, 949 + 950 + { 951 + .part = "cs1234", .dsp_name = "dsp1", .system_name = "abc", 952 + .alsa_name = "LEFT", 953 + .expect_wmfw = "cirrus/cs1234-dsp1-mbc-vss-abc-left.wmfw", 954 + .expected_searches = 955 + "cirrus/cs1234-dsp1-mbc-vss-abc-left.wmfw " 956 + "cirrus/cs1234-dsp1-mbc-vss-abc-left.bin", 957 + }, 958 + { 959 + .part = "cs1234", .dsp_name = "dsp1", .system_name = "abc", 960 + .alsa_name = "LEFT AMP", 961 + .expect_wmfw = "cirrus/cs1234-dsp1-mbc-vss-abc-left-amp.wmfw", 962 + .expected_searches = 963 + "cirrus/cs1234-dsp1-mbc-vss-abc-left-amp.wmfw " 964 + "cirrus/cs1234-dsp1-mbc-vss-abc-left-amp.bin", 965 + }, 966 + { 967 + .part = "cs1234", .dsp_name = "dsp1", .system_name = "abc", 968 + .alsa_name = "Left Amp", 969 + .expect_wmfw = "cirrus/cs1234-dsp1-mbc-vss-abc-left-amp.wmfw", 970 + .expected_searches = 971 + "cirrus/cs1234-dsp1-mbc-vss-abc-left-amp.wmfw " 972 + "cirrus/cs1234-dsp1-mbc-vss-abc-left-amp.bin", 973 + }, 974 + { 975 + .part = "cs1234", .dsp_name = "dsp1", .system_name = "abc", 976 + .alsa_name = "Amp_1", 977 + .expect_wmfw = "cirrus/cs1234-dsp1-mbc-vss-abc-amp-1.wmfw", 978 + .expected_searches = 979 + "cirrus/cs1234-dsp1-mbc-vss-abc-amp-1.wmfw " 980 + "cirrus/cs1234-dsp1-mbc-vss-abc-amp-1.bin", 981 + }, 982 + { 983 + .part = "cs1234", .dsp_name = "dsp1", .system_name = "abc", 984 + .alsa_name = "cs1234.1", 985 + .expect_wmfw = "cirrus/cs1234-dsp1-mbc-vss-abc-cs1234.1.wmfw", 986 + .expected_searches = 987 + "cirrus/cs1234-dsp1-mbc-vss-abc-cs1234.1.wmfw " 988 + "cirrus/cs1234-dsp1-mbc-vss-abc-cs1234.1.bin", 989 + }, 990 + { 991 + .part = "cs1234", .dsp_name = "dsp1", .system_name = "abc", 992 + .alsa_name = "Spk/Jack", 993 + .expect_wmfw = "cirrus/cs1234-dsp1-mbc-vss-abc-spk-jack.wmfw", 994 + .expected_searches = 995 + "cirrus/cs1234-dsp1-mbc-vss-abc-spk-jack.wmfw " 996 + "cirrus/cs1234-dsp1-mbc-vss-abc-spk-jack.bin", 997 + }, 998 + }; 999 + KUNIT_ARRAY_PARAM(wm_adsp_fw_find_normalization, 1000 + wm_adsp_fw_find_normalization_cases, 1001 + wm_adsp_fw_find_test_param_desc); 1002 + 1003 + /* 1004 + * Dummy directory content for regression tests. 1005 + * DSP part name and system name are used to select different available 1006 + * files. 1007 + * 1008 + * System: 1009 + * WFBF1111 = wmfw and bin fully-qualified 1010 + * WSBF1111 = wmfw system-qualified, bin fully-qualified 1011 + * WSBS1111 = wmfw and bin system-qualified 1012 + * WFXX1111 = wmfw fully-qualified, bin not present 1013 + * XXBF1111 = wmfw not present, bin fully-qualified 1014 + * 1015 + * Part: 1016 + * cs1234 = for testing fully-qualified configurations 1017 + * cs1234nobin = generic wmfw without a bin available 1018 + * wm1234 = legacy wmfw and bin 1019 + * wm1234nobin = legacy wmfw without bin 1020 + */ 1021 + static const char * const wm_adsp_fw_find_test_dir_all_files[] = { 1022 + "cirrus/cs1234-dsp1-mbc-vss-wfbf1111-amp1.wmfw", 1023 + "cirrus/cs1234-dsp1-mbc-vss-wfbf1111-l1u2.wmfw", 1024 + "cirrus/cs1234-dsp1-mbc-vss-wfbf1111.wmfw", 1025 + "cirrus/cs1234-dsp1-mbc-vss-wsbf1111.wmfw", 1026 + "cirrus/cs1234-dsp1-mbc-vss-wsbs1111.wmfw", 1027 + "cirrus/cs1234-dsp1-mbc-vss-wfxx1111.wmfw", 1028 + "cirrus/cs1234-dsp1-mbc-vss.wmfw", 1029 + "cirrus/cs1234nobin-dsp1-mbc-vss.wmfw", 1030 + "cirrus/wm1234-dsp1-mbc-vss.wmfw", 1031 + "cirrus/wm1234nobin-dsp1-mbc-vss.wmfw", 1032 + "wm1234-dsp1-mbc-vss.wmfw", 1033 + "wm1234nobin-dsp1-mbc-vss.wmfw", 1034 + "cirrus/cs1234-dsp1-mbc-vss-wfbf1111-amp1.bin", 1035 + "cirrus/cs1234-dsp1-mbc-vss-wfbf1111-l1u2.bin", 1036 + "cirrus/cs1234-dsp1-mbc-vss-wsbf1111-amp1.bin", 1037 + "cirrus/cs1234-dsp1-mbc-vss-wsbf1111-l1u2.bin", 1038 + "cirrus/cs1234-dsp1-mbc-vss-wsbs1111.bin", 1039 + "cirrus/cs1234-dsp1-mbc-vss-xxbf1111-amp1.bin", 1040 + "cirrus/cs1234-dsp1-mbc-vss.bin", 1041 + "cirrus/wm1234-dsp1-mbc-vss.bin", 1042 + "wm1234-dsp1-mbc-vss.bin", 1043 + }; 1044 + 1045 + /* 1046 + * Regression testing that a change in the search algorithm doesn't change 1047 + * which file is picked. This doesn't cover every possible combination, only 1048 + * those that are already in use and typical cases. 1049 + * 1050 + * It wouldn't be efficent to fully prove the algorithm this way (too many 1051 + * directory content combinations would be needed, and it only infers what the 1052 + * algorithm searched for, it doesn't prove exactly what searches were made). 1053 + * So the main testing is done by checking for the expected file searches. 1054 + * This regression test is independent of the search algorithm. 1055 + * 1056 + * The main tests already prove that the algorithm only searches for files 1057 + * with the correct qualifiers so we can assume that files with the wrong 1058 + * qualifiers would not be picked and there's no need to test for that here. 1059 + */ 1060 + static const struct wm_adsp_fw_find_test_params wm_adsp_fw_find_pick_cases[] = { 1061 + /* 1062 + * Amps 1063 + */ 1064 + { /* Full info, wmfw and bin fully-qualified */ 1065 + .part = "cs1234", .dsp_name = "dsp1", .system_name = "WFBF1111", 1066 + .alsa_name = "amp1", 1067 + .expect_wmfw = "cirrus/cs1234-dsp1-mbc-vss-wfbf1111-amp1.wmfw", 1068 + .expect_bin = "cirrus/cs1234-dsp1-mbc-vss-wfbf1111-amp1.bin", 1069 + .dir_files = wm_adsp_fw_find_test_dir_all_files, 1070 + }, 1071 + { /* Full info, wmfw and bin fully-qualified */ 1072 + .part = "cs1234", .dsp_name = "dsp1", .system_name = "WFBF1111", 1073 + .alsa_name = "l1u2", 1074 + .expect_wmfw = "cirrus/cs1234-dsp1-mbc-vss-wfbf1111-l1u2.wmfw", 1075 + .expect_bin = "cirrus/cs1234-dsp1-mbc-vss-wfbf1111-l1u2.bin", 1076 + .dir_files = wm_adsp_fw_find_test_dir_all_files, 1077 + }, 1078 + { /* Full info, wmfw only system-qualified, bin fully-qualified */ 1079 + .part = "cs1234", .dsp_name = "dsp1", .system_name = "WSBF1111", 1080 + .alsa_name = "amp1", 1081 + .expect_wmfw = "cirrus/cs1234-dsp1-mbc-vss-wsbf1111.wmfw", 1082 + .expect_bin = "cirrus/cs1234-dsp1-mbc-vss-wsbf1111-amp1.bin", 1083 + .dir_files = wm_adsp_fw_find_test_dir_all_files, 1084 + }, 1085 + { /* Full info, wmfw only system-qualified, bin fully-qualified */ 1086 + .part = "cs1234", .dsp_name = "dsp1", .system_name = "WSBF1111", 1087 + .alsa_name = "l1u2", 1088 + .expect_wmfw = "cirrus/cs1234-dsp1-mbc-vss-wsbf1111.wmfw", 1089 + .expect_bin = "cirrus/cs1234-dsp1-mbc-vss-wsbf1111-l1u2.bin", 1090 + .dir_files = wm_adsp_fw_find_test_dir_all_files, 1091 + }, 1092 + { /* Full info, wmfw optional but present, and bin fully-qualified */ 1093 + .part = "cs1234", .dsp_name = "dsp1", .system_name = "WFBF1111", 1094 + .alsa_name = "amp1", .wmfw_optional = true, 1095 + .expect_wmfw = "cirrus/cs1234-dsp1-mbc-vss-wfbf1111-amp1.wmfw", 1096 + .expect_bin = "cirrus/cs1234-dsp1-mbc-vss-wfbf1111-amp1.bin", 1097 + .dir_files = wm_adsp_fw_find_test_dir_all_files, 1098 + }, 1099 + { /* Full info, wmfw and bin only system-qualified */ 1100 + .part = "cs1234", .dsp_name = "dsp1", .system_name = "WSBS1111", 1101 + .alsa_name = "amp1", 1102 + .expect_wmfw = "cirrus/cs1234-dsp1-mbc-vss-wsbs1111.wmfw", 1103 + .expect_bin = "cirrus/cs1234-dsp1-mbc-vss-wsbs1111.bin", 1104 + .dir_files = wm_adsp_fw_find_test_dir_all_files, 1105 + }, 1106 + { /* Full info, wmfw optional but system-qualified wmfm present, bin fully-qualified */ 1107 + .part = "cs1234", .dsp_name = "dsp1", .system_name = "WSBF1111", 1108 + .alsa_name = "amp1", .wmfw_optional = true, 1109 + .expect_wmfw = "cirrus/cs1234-dsp1-mbc-vss-wsbf1111.wmfw", 1110 + .expect_bin = "cirrus/cs1234-dsp1-mbc-vss-wsbf1111-amp1.bin", 1111 + .dir_files = wm_adsp_fw_find_test_dir_all_files, 1112 + }, 1113 + { /* Full info, wmfw optional not present, and bin fully-qualified */ 1114 + .part = "cs1234", .dsp_name = "dsp1", .system_name = "XXBF1111", 1115 + .alsa_name = "amp1", .wmfw_optional = true, 1116 + .expect_bin = "cirrus/cs1234-dsp1-mbc-vss-xxbf1111-amp1.bin", 1117 + .dir_files = wm_adsp_fw_find_test_dir_all_files, 1118 + }, 1119 + { /* Full info, wmfw and bin fully-qualified, bin mandatory and present */ 1120 + .part = "cs1234", .dsp_name = "dsp1", .system_name = "WFBF1111", 1121 + .alsa_name = "amp1", .bin_mandatory = true, 1122 + .expect_wmfw = "cirrus/cs1234-dsp1-mbc-vss-wfbf1111-amp1.wmfw", 1123 + .expect_bin = "cirrus/cs1234-dsp1-mbc-vss-wfbf1111-amp1.bin", 1124 + .dir_files = wm_adsp_fw_find_test_dir_all_files, 1125 + }, 1126 + { /* Full info, wmfw and bin fully-qualified, bin mandatory but not present */ 1127 + .part = "cs1234", .dsp_name = "dsp1", .system_name = "WFXX1111", 1128 + .alsa_name = "amp1", .bin_mandatory = true, 1129 + .expect_wmfw = "cirrus/cs1234-dsp1-mbc-vss-wfxx1111.wmfw", 1130 + .dir_files = wm_adsp_fw_find_test_dir_all_files, 1131 + }, 1132 + { /* Full info, wmfw optional but present, bin mandatory but not present */ 1133 + .part = "cs1234", .dsp_name = "dsp1", .system_name = "WFXX1111", 1134 + .alsa_name = "amp1", .wmfw_optional = true, .bin_mandatory = true, 1135 + .expect_wmfw = "cirrus/cs1234-dsp1-mbc-vss-wfxx1111.wmfw", 1136 + .dir_files = wm_adsp_fw_find_test_dir_all_files, 1137 + }, 1138 + { /* Full info, wmfw and bin not present, generic fallbacks are present */ 1139 + .part = "cs1234", .dsp_name = "dsp1", .system_name = "XXXX1111", 1140 + .alsa_name = "amp1", 1141 + .expect_wmfw = "cirrus/cs1234-dsp1-mbc-vss.wmfw", 1142 + .expect_bin = "cirrus/cs1234-dsp1-mbc-vss.bin", 1143 + .dir_files = wm_adsp_fw_find_test_dir_all_files, 1144 + }, 1145 + { /* Full info, wmfw and bin not present, generic wmfw present */ 1146 + .part = "cs1234nobin", .dsp_name = "dsp1", .system_name = "XXXX1111", 1147 + .alsa_name = "amp1", 1148 + .expect_wmfw = "cirrus/cs1234nobin-dsp1-mbc-vss.wmfw", 1149 + .dir_files = wm_adsp_fw_find_test_dir_all_files, 1150 + }, 1151 + 1152 + /* 1153 + * Codecs 1154 + */ 1155 + { /* No qualifiers. Generic wmfws exist, legacy should be chosen. */ 1156 + .part = "wm1234nobin", .dsp_name = "dsp1", 1157 + .expect_wmfw = "wm1234nobin-dsp1-mbc-vss.wmfw", 1158 + .dir_files = wm_adsp_fw_find_test_dir_all_files, 1159 + }, 1160 + { /* No qualifiers. Generic wmfw and bin exist, legacy should be chosen */ 1161 + .part = "wm1234", .dsp_name = "dsp1", 1162 + .expect_wmfw = "wm1234-dsp1-mbc-vss.wmfw", 1163 + .expect_bin = "wm1234-dsp1-mbc-vss.bin", 1164 + .dir_files = wm_adsp_fw_find_test_dir_all_files, 1165 + }, 1166 + { /* No qualifiers. New generic wmfw exists, no legacy files. */ 1167 + .part = "cs1234nobin", .dsp_name = "dsp1", 1168 + .expect_wmfw = "cirrus/cs1234nobin-dsp1-mbc-vss.wmfw", 1169 + .dir_files = wm_adsp_fw_find_test_dir_all_files, 1170 + }, 1171 + { /* No qualifiers. New generic wmfw and bin exist, no legacy files. */ 1172 + .part = "cs1234", .dsp_name = "dsp1", 1173 + .expect_wmfw = "cirrus/cs1234-dsp1-mbc-vss.wmfw", 1174 + .expect_bin = "cirrus/cs1234-dsp1-mbc-vss.bin", 1175 + .dir_files = wm_adsp_fw_find_test_dir_all_files, 1176 + }, 1177 + }; 1178 + KUNIT_ARRAY_PARAM(wm_adsp_fw_find_pick, 1179 + wm_adsp_fw_find_pick_cases, 1180 + wm_adsp_fw_find_test_param_desc); 1181 + 1182 + static struct kunit_case wm_adsp_fw_find_test_cases[] = { 1183 + KUNIT_CASE_PARAM(wm_adsp_fw_find_test_search_order, 1184 + wm_adsp_fw_find_full_search_gen_params), 1185 + 1186 + KUNIT_CASE_PARAM(wm_adsp_fw_find_test_search_order, 1187 + wm_adsp_fw_find_system_alsaname_gen_params), 1188 + 1189 + KUNIT_CASE_PARAM(wm_adsp_fw_find_test_search_order, 1190 + wm_adsp_fw_find_system_gen_params), 1191 + 1192 + KUNIT_CASE_PARAM(wm_adsp_fw_find_test_search_order, 1193 + wm_adsp_fw_find_alsaname_gen_params), 1194 + 1195 + KUNIT_CASE_PARAM(wm_adsp_fw_find_test_search_order, 1196 + wm_adsp_fw_find_noqual_gen_params), 1197 + 1198 + KUNIT_CASE_PARAM(wm_adsp_fw_find_test_search_order, 1199 + wm_adsp_fw_find_normalization_gen_params), 1200 + 1201 + KUNIT_CASE_PARAM(wm_adsp_fw_find_test_pick_file, 1202 + wm_adsp_fw_find_pick_gen_params), 1203 + 1204 + KUNIT_CASE(wm_adsp_fw_find_test_find_firmware_byindex), 1205 + 1206 + { } /* terminator */ 1207 + }; 1208 + 1209 + static struct kunit_suite wm_adsp_fw_find_test_suite = { 1210 + .name = "wm-adsp-fw-find", 1211 + .init = wm_adsp_fw_find_test_case_init, 1212 + .exit = wm_adsp_fw_find_test_case_exit, 1213 + .test_cases = wm_adsp_fw_find_test_cases, 1214 + }; 1215 + 1216 + kunit_test_suite(wm_adsp_fw_find_test_suite); 1217 + 1218 + MODULE_DESCRIPTION("KUnit test for Cirrus Logic wm_adsp driver"); 1219 + MODULE_AUTHOR("Richard Fitzgerald <rf@opensource.cirrus.com>"); 1220 + MODULE_LICENSE("GPL"); 1221 + MODULE_IMPORT_NS("EXPORTED_FOR_KUNIT_TESTING");