Hi Richard, Thank you for the patch! Yet something to improve: [auto build test ERROR on broonie-sound/for-next] [also build test ERROR on linus/master v6.3-rc2 next-20230316] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch#_base_tree_information] url: https://github.com/intel-lab-lkp/linux/commits/Richard-Fitzgerald-via-Alsa-devel/ASoC-wm_adsp-Use-no_core_startstop-to-prevent-creating-preload-control/20230313-235605 base: https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git for-next patch link: https://lore.kernel.org/r/167872265923.26.336497278776737619%40mailman-core.alsa-project.org patch subject: [PATCH v2 8/8] ASoC: cs35l56: Add driver for Cirrus Logic CS35L56 config: s390-randconfig-r044-20230313 (https://download.01.org/0day-ci/archive/20230317/202303170422.ZYpOtc4P-lkp@xxxxxxxxx/config) compiler: clang version 17.0.0 (https://github.com/llvm/llvm-project 67409911353323ca5edf2049ef0df54132fa1ca7) reproduce (this is a W=1 build): wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross # install s390 cross compiling tool for clang build # apt-get install binutils-s390x-linux-gnu # https://github.com/intel-lab-lkp/linux/commit/5856c94d659f9c9963f5c37762cf201e1f1765e9 git remote add linux-review https://github.com/intel-lab-lkp/linux git fetch --no-tags linux-review Richard-Fitzgerald-via-Alsa-devel/ASoC-wm_adsp-Use-no_core_startstop-to-prevent-creating-preload-control/20230313-235605 git checkout 5856c94d659f9c9963f5c37762cf201e1f1765e9 # save the config file mkdir build_dir && cp config build_dir/.config COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 O=build_dir ARCH=s390 olddefconfig COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 O=build_dir ARCH=s390 SHELL=/bin/bash If you fix the issue, kindly add following tag where applicable | Reported-by: kernel test robot <lkp@xxxxxxxxx> | Link: https://lore.kernel.org/oe-kbuild-all/202303170422.ZYpOtc4P-lkp@xxxxxxxxx/ All errors (new ones prefixed by >>): s390x-linux-ld: sound/soc/codecs/cs35l56.o: in function `cs35l56_dsp_work': >> sound/soc/codecs/cs35l56.c:887: undefined reference to `sdw_write_no_pm' >> s390x-linux-ld: sound/soc/codecs/cs35l56.c:888: undefined reference to `sdw_read_no_pm' >> s390x-linux-ld: sound/soc/codecs/cs35l56.c:889: undefined reference to `sdw_write_no_pm' s390x-linux-ld: sound/soc/codecs/cs35l56.c:953: undefined reference to `sdw_write_no_pm' s390x-linux-ld: sound/soc/codecs/cs35l56.o: in function `cs35l56_sdw_dai_hw_params': >> sound/soc/codecs/cs35l56.c:710: undefined reference to `sdw_stream_add_slave' s390x-linux-ld: sound/soc/codecs/cs35l56.o: in function `cs35l56_sdw_dai_hw_free': >> sound/soc/codecs/cs35l56.c:729: undefined reference to `sdw_stream_remove_slave' Kconfig warnings: (for reference only) WARNING: unmet direct dependencies detected for SERIAL_MULTI_INSTANTIATE Depends on [n]: X86_PLATFORM_DEVICES [=n] && I2C [=y] && SPI [=y] && ACPI Selected by [y]: - SND_SOC_CS35L56_I2C [=y] && SOUND [=y] && !UML && SND [=y] && SND_SOC [=y] && I2C [=y] - SND_SOC_CS35L56_SPI [=y] && SOUND [=y] && !UML && SND [=y] && SND_SOC [=y] && SPI_MASTER [=y] vim +887 sound/soc/codecs/cs35l56.c 668 669 static int cs35l56_sdw_dai_hw_params(struct snd_pcm_substream *substream, 670 struct snd_pcm_hw_params *params, 671 struct snd_soc_dai *dai) 672 { 673 struct cs35l56_private *cs35l56 = snd_soc_component_get_drvdata(dai->component); 674 struct sdw_stream_runtime *sdw_stream = snd_soc_dai_get_dma_data(dai, substream); 675 struct sdw_stream_config sconfig; 676 struct sdw_port_config pconfig; 677 int ret; 678 679 dev_dbg(cs35l56->dev, "%s: rate %d\n", __func__, params_rate(params)); 680 681 if (!cs35l56->init_done) 682 return -ENODEV; 683 684 if (!sdw_stream) 685 return -EINVAL; 686 687 memset(&sconfig, 0, sizeof(sconfig)); 688 memset(&pconfig, 0, sizeof(pconfig)); 689 690 sconfig.frame_rate = params_rate(params); 691 sconfig.bps = snd_pcm_format_width(params_format(params)); 692 693 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 694 sconfig.direction = SDW_DATA_DIR_RX; 695 pconfig.num = CS35L56_SDW1_PLAYBACK_PORT; 696 pconfig.ch_mask = cs35l56->rx_mask; 697 } else { 698 sconfig.direction = SDW_DATA_DIR_TX; 699 pconfig.num = CS35L56_SDW1_CAPTURE_PORT; 700 pconfig.ch_mask = cs35l56->tx_mask; 701 } 702 703 if (pconfig.ch_mask == 0) { 704 sconfig.ch_count = params_channels(params); 705 pconfig.ch_mask = GENMASK(sconfig.ch_count - 1, 0); 706 } else { 707 sconfig.ch_count = hweight32(pconfig.ch_mask); 708 } 709 > 710 ret = sdw_stream_add_slave(cs35l56->sdw_peripheral, &sconfig, &pconfig, 711 1, sdw_stream); 712 if (ret) { 713 dev_err(dai->dev, "Failed to add sdw stream: %d\n", ret); 714 return ret; 715 } 716 717 return 0; 718 } 719 720 static int cs35l56_sdw_dai_hw_free(struct snd_pcm_substream *substream, 721 struct snd_soc_dai *dai) 722 { 723 struct cs35l56_private *cs35l56 = snd_soc_component_get_drvdata(dai->component); 724 struct sdw_stream_runtime *sdw_stream = snd_soc_dai_get_dma_data(dai, substream); 725 726 if (!cs35l56->sdw_peripheral) 727 return -EINVAL; 728 > 729 sdw_stream_remove_slave(cs35l56->sdw_peripheral, sdw_stream); 730 731 return 0; 732 } 733 734 static int cs35l56_sdw_dai_set_stream(struct snd_soc_dai *dai, 735 void *sdw_stream, int direction) 736 { 737 if (!sdw_stream) 738 return 0; 739 740 snd_soc_dai_dma_data_set(dai, direction, sdw_stream); 741 742 return 0; 743 } 744 745 static const struct snd_soc_dai_ops cs35l56_sdw_dai_ops = { 746 .set_tdm_slot = cs35l56_sdw_dai_set_tdm_slot, 747 .shutdown = cs35l56_sdw_dai_shutdown, 748 .hw_params = cs35l56_sdw_dai_hw_params, 749 .hw_free = cs35l56_sdw_dai_hw_free, 750 .mute_stream = cs35l56_mute_stream, 751 .set_stream = cs35l56_sdw_dai_set_stream, 752 }; 753 754 static struct snd_soc_dai_driver cs35l56_dai[] = { 755 { 756 .name = "cs35l56-asp1", 757 .id = 0, 758 .playback = { 759 .stream_name = "ASP1 Playback", 760 .channels_min = 1, 761 .channels_max = 2, 762 .rates = CS35L56_RATES, 763 .formats = CS35L56_RX_FORMATS, 764 }, 765 .capture = { 766 .stream_name = "ASP1 Capture", 767 .channels_min = 1, 768 .channels_max = 4, 769 .rates = CS35L56_RATES, 770 .formats = CS35L56_TX_FORMATS, 771 }, 772 .ops = &cs35l56_ops, 773 .symmetric_rate = 1, 774 .symmetric_sample_bits = 1, 775 }, 776 { 777 .name = "cs35l56-sdw1", 778 .id = 1, 779 .playback = { 780 .stream_name = "SDW1 Playback", 781 .channels_min = 1, 782 .channels_max = 2, 783 .rates = CS35L56_RATES, 784 .formats = CS35L56_RX_FORMATS, 785 }, 786 .capture = { 787 .stream_name = "SDW1 Capture", 788 .channels_min = 1, 789 .channels_max = 6, 790 .rates = CS35L56_RATES, 791 .formats = CS35L56_TX_FORMATS, 792 }, 793 .symmetric_rate = 1, 794 .ops = &cs35l56_sdw_dai_ops, 795 } 796 }; 797 798 static int cs35l56_wait_for_firmware_boot(struct cs35l56_private *cs35l56) 799 { 800 unsigned int reg; 801 unsigned int val; 802 int ret; 803 804 if (cs35l56->rev < CS35L56_REVID_B0) 805 reg = CS35L56_DSP1_HALO_STATE_A1; 806 else 807 reg = CS35L56_DSP1_HALO_STATE; 808 809 ret = regmap_read_poll_timeout(cs35l56->regmap, reg, 810 val, 811 (val < 0xFFFF) && (val >= CS35L56_HALO_STATE_BOOT_DONE), 812 CS35L56_HALO_STATE_POLL_US, 813 CS35L56_HALO_STATE_TIMEOUT_US); 814 815 if ((ret < 0) && (ret != -ETIMEDOUT)) { 816 dev_err(cs35l56->dev, "Failed to read HALO_STATE: %d\n", ret); 817 return ret; 818 } 819 820 if ((ret == -ETIMEDOUT) || (val != CS35L56_HALO_STATE_BOOT_DONE)) { 821 dev_err(cs35l56->dev, "Firmware boot fail: HALO_STATE=%#x\n", val); 822 return -EIO; 823 } 824 825 return 0; 826 } 827 828 static const struct reg_sequence cs35l56_system_reset_seq[] = { 829 REG_SEQ0(CS35L56_DSP_VIRTUAL1_MBOX_1, CS35L56_MBOX_CMD_SYSTEM_RESET), 830 }; 831 832 static void cs35l56_system_reset(struct cs35l56_private *cs35l56) 833 { 834 cs35l56->soft_resetting = true; 835 836 /* 837 * Must enter cache-only first so there can't be any more register 838 * accesses other than the controlled system reset sequence below. 839 */ 840 regcache_cache_only(cs35l56->regmap, true); 841 regmap_multi_reg_write_bypassed(cs35l56->regmap, 842 cs35l56_system_reset_seq, 843 ARRAY_SIZE(cs35l56_system_reset_seq)); 844 845 /* On SoundWire the registers won't be accessible until it re-enumerates. */ 846 if (cs35l56->sdw_peripheral) 847 return; 848 849 usleep_range(CS35L56_CONTROL_PORT_READY_US, CS35L56_CONTROL_PORT_READY_US + 400); 850 regcache_cache_only(cs35l56->regmap, false); 851 } 852 853 static void cs35l56_dsp_work(struct work_struct *work) 854 { 855 struct cs35l56_private *cs35l56 = container_of(work, 856 struct cs35l56_private, 857 dsp_work); 858 unsigned int reg; 859 unsigned int val; 860 int ret = 0; 861 862 if (!wait_for_completion_timeout(&cs35l56->init_completion, 863 msecs_to_jiffies(5000))) { 864 dev_err(cs35l56->dev, "%s: init_completion timed out\n", __func__); 865 goto complete; 866 } 867 868 if (!cs35l56->init_done || cs35l56->removing) 869 goto complete; 870 871 cs35l56->dsp.part = devm_kasprintf(cs35l56->dev, GFP_KERNEL, "cs35l56%s-%02x", 872 cs35l56->secured ? "s" : "", cs35l56->rev); 873 874 if (!cs35l56->dsp.part) 875 goto complete; 876 877 pm_runtime_get_sync(cs35l56->dev); 878 879 /* 880 * Disable SoundWire interrupts to prevent race with IRQ work. 881 * Setting sdw_irq_no_unmask prevents the handler re-enabling 882 * the SoundWire interrupt. 883 */ 884 if (cs35l56->sdw_peripheral) { 885 cs35l56->sdw_irq_no_unmask = true; 886 cancel_work_sync(&cs35l56->sdw_irq_work); > 887 sdw_write_no_pm(cs35l56->sdw_peripheral, CS35L56_SDW_GEN_INT_MASK_1, 0); > 888 sdw_read_no_pm(cs35l56->sdw_peripheral, CS35L56_SDW_GEN_INT_STAT_1); > 889 sdw_write_no_pm(cs35l56->sdw_peripheral, CS35L56_SDW_GEN_INT_STAT_1, 0xFF); 890 } 891 892 ret = cs35l56_mbox_send(cs35l56, CS35L56_MBOX_CMD_SHUTDOWN); 893 if (ret) { 894 dev_dbg(cs35l56->dev, "%s: CS35L56_MBOX_CMD_SHUTDOWN ret %d\n", __func__, ret); 895 goto err; 896 } 897 898 if (cs35l56->rev < CS35L56_REVID_B0) 899 reg = CS35L56_DSP1_PM_CUR_STATE_A1; 900 else 901 reg = CS35L56_DSP1_PM_CUR_STATE; 902 903 ret = regmap_read_poll_timeout(cs35l56->regmap, reg, 904 val, (val == CS35L56_HALO_STATE_SHUTDOWN), 905 CS35L56_HALO_STATE_POLL_US, 906 CS35L56_HALO_STATE_TIMEOUT_US); 907 if (ret < 0) 908 dev_err(cs35l56->dev, "Failed to poll PM_CUR_STATE to 1 is %d (ret %d)\n", 909 val, ret); 910 911 /* Use wm_adsp to load and apply the firmware patch and coefficient files */ 912 ret = wm_adsp_power_up(&cs35l56->dsp); 913 if (ret) { 914 dev_dbg(cs35l56->dev, "%s: wm_adsp_power_up ret %d\n", __func__, ret); 915 goto err; 916 } 917 918 if (cs35l56->removing) 919 goto err; 920 921 mutex_lock(&cs35l56->irq_lock); 922 923 init_completion(&cs35l56->init_completion); 924 925 cs35l56_system_reset(cs35l56); 926 927 if (cs35l56->sdw_peripheral) { 928 /* 929 * The system-reset causes the CS35L56 to detach from the bus. 930 * Wait for the manager to re-enumerate the CS35L56 and 931 * cs35l56_init() to run again. 932 */ 933 if (!wait_for_completion_timeout(&cs35l56->init_completion, 934 msecs_to_jiffies(5000))) { 935 dev_err(cs35l56->dev, "%s: init_completion timed out (SDW)\n", __func__); 936 goto err_unlock; 937 } 938 } else if (cs35l56_init(cs35l56)) { 939 goto err_unlock; 940 } 941 942 cs35l56->fw_patched = true; 943 944 err_unlock: 945 mutex_unlock(&cs35l56->irq_lock); 946 err: 947 pm_runtime_mark_last_busy(cs35l56->dev); 948 pm_runtime_put_autosuspend(cs35l56->dev); 949 950 /* Re-enable SoundWire interrupts */ 951 if (cs35l56->sdw_peripheral) { 952 cs35l56->sdw_irq_no_unmask = false; 953 sdw_write_no_pm(cs35l56->sdw_peripheral, CS35L56_SDW_GEN_INT_MASK_1, 954 CS35L56_SDW_INT_MASK_CODEC_IRQ); 955 } 956 957 complete: 958 complete_all(&cs35l56->dsp_ready_completion); 959 } 960 -- 0-DAY CI Kernel Test Service https://github.com/intel/lkp-tests