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

ASoC: intel/sdw-utils: move soundwire machine driver soc ops

Move Intel SoundWire generic machine driver soc ops to common place
so that it can be used by other platform machine driver.

Link: https://github.com/thesofproject/linux/pull/5068
Signed-off-by: Vijendar Mukunda <Vijendar.Mukunda@amd.com>
Reviewed-by: Bard Liao <yung-chuan.liao@linux.intel.com>
Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Link: https://patch.msgid.link/20240801091446.10457-8-Vijendar.Mukunda@amd.com
Signed-off-by: Mark Brown <broonie@kernel.org>

authored by

Vijendar Mukunda and committed by
Mark Brown
d39388e6 b1f7cbf0

+188 -138
+23
include/sound/soc_sdw_utils.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0-only */ 2 + /* 3 + * This file incorporates work covered by the following copyright notice: 4 + * Copyright (c) 2020 Intel Corporation 5 + * Copyright(c) 2024 Advanced Micro Devices, Inc. 6 + * 7 + */ 8 + 9 + #ifndef SOC_SDW_UTILS_H 10 + #define SOC_SDW_UTILS_H 11 + 12 + #include <sound/soc.h> 13 + 14 + int asoc_sdw_startup(struct snd_pcm_substream *substream); 15 + int asoc_sdw_prepare(struct snd_pcm_substream *substream); 16 + int asoc_sdw_prepare(struct snd_pcm_substream *substream); 17 + int asoc_sdw_trigger(struct snd_pcm_substream *substream, int cmd); 18 + int asoc_sdw_hw_params(struct snd_pcm_substream *substream, 19 + struct snd_pcm_hw_params *params); 20 + int asoc_sdw_hw_free(struct snd_pcm_substream *substream); 21 + void asoc_sdw_shutdown(struct snd_pcm_substream *substream); 22 + 23 + #endif
+2
sound/soc/Kconfig
··· 126 126 # Supported codecs 127 127 source "sound/soc/codecs/Kconfig" 128 128 129 + source "sound/soc/sdw_utils/Kconfig" 130 + 129 131 # generic frame-work 130 132 source "sound/soc/generic/Kconfig" 131 133
+1
sound/soc/Makefile
··· 75 75 obj-$(CONFIG_SND_SOC) += ux500/ 76 76 obj-$(CONFIG_SND_SOC) += xilinx/ 77 77 obj-$(CONFIG_SND_SOC) += xtensa/ 78 + obj-$(CONFIG_SND_SOC) += sdw_utils/
+1
sound/soc/intel/boards/Kconfig
··· 656 656 depends on MFD_INTEL_LPSS || COMPILE_TEST 657 657 depends on SND_SOC_INTEL_USER_FRIENDLY_LONG_NAMES || COMPILE_TEST 658 658 depends on SOUNDWIRE 659 + select SND_SOC_SDW_UTILS 659 660 select SND_SOC_MAX98363 660 661 select SND_SOC_MAX98373_I2C 661 662 select SND_SOC_MAX98373_SDW
+1 -130
sound/soc/intel/boards/sof_sdw.c
··· 11 11 #include <linux/module.h> 12 12 #include <linux/soundwire/sdw.h> 13 13 #include <linux/soundwire/sdw_type.h> 14 - #include <sound/soc.h> 15 14 #include <sound/soc-acpi.h> 16 15 #include "sof_sdw_common.h" 17 16 #include "../../codecs/rt711.h" ··· 591 592 SOC_DAPM_PIN_SWITCH("AMIC"), 592 593 SOC_DAPM_PIN_SWITCH("Speaker"), 593 594 }; 594 - 595 - /* these wrappers are only needed to avoid typecast compilation errors */ 596 - int asoc_sdw_startup(struct snd_pcm_substream *substream) 597 - { 598 - return sdw_startup_stream(substream); 599 - } 600 - 601 - int asoc_sdw_prepare(struct snd_pcm_substream *substream) 602 - { 603 - struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); 604 - struct sdw_stream_runtime *sdw_stream; 605 - struct snd_soc_dai *dai; 606 - 607 - /* Find stream from first CPU DAI */ 608 - dai = snd_soc_rtd_to_cpu(rtd, 0); 609 - 610 - sdw_stream = snd_soc_dai_get_stream(dai, substream->stream); 611 - if (IS_ERR(sdw_stream)) { 612 - dev_err(rtd->dev, "no stream found for DAI %s\n", dai->name); 613 - return PTR_ERR(sdw_stream); 614 - } 615 - 616 - return sdw_prepare_stream(sdw_stream); 617 - } 618 - 619 - int asoc_sdw_trigger(struct snd_pcm_substream *substream, int cmd) 620 - { 621 - struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); 622 - struct sdw_stream_runtime *sdw_stream; 623 - struct snd_soc_dai *dai; 624 - int ret; 625 - 626 - /* Find stream from first CPU DAI */ 627 - dai = snd_soc_rtd_to_cpu(rtd, 0); 628 - 629 - sdw_stream = snd_soc_dai_get_stream(dai, substream->stream); 630 - if (IS_ERR(sdw_stream)) { 631 - dev_err(rtd->dev, "no stream found for DAI %s\n", dai->name); 632 - return PTR_ERR(sdw_stream); 633 - } 634 - 635 - switch (cmd) { 636 - case SNDRV_PCM_TRIGGER_START: 637 - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 638 - case SNDRV_PCM_TRIGGER_RESUME: 639 - ret = sdw_enable_stream(sdw_stream); 640 - break; 641 - 642 - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 643 - case SNDRV_PCM_TRIGGER_SUSPEND: 644 - case SNDRV_PCM_TRIGGER_STOP: 645 - ret = sdw_disable_stream(sdw_stream); 646 - break; 647 - default: 648 - ret = -EINVAL; 649 - break; 650 - } 651 - 652 - if (ret) 653 - dev_err(rtd->dev, "%s trigger %d failed: %d\n", __func__, cmd, ret); 654 - 655 - return ret; 656 - } 657 - 658 - int asoc_sdw_hw_params(struct snd_pcm_substream *substream, 659 - struct snd_pcm_hw_params *params) 660 - { 661 - struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); 662 - struct snd_soc_dai_link_ch_map *ch_maps; 663 - int ch = params_channels(params); 664 - unsigned int ch_mask; 665 - int num_codecs; 666 - int step; 667 - int i; 668 - 669 - if (!rtd->dai_link->ch_maps) 670 - return 0; 671 - 672 - /* Identical data will be sent to all codecs in playback */ 673 - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 674 - ch_mask = GENMASK(ch - 1, 0); 675 - step = 0; 676 - } else { 677 - num_codecs = rtd->dai_link->num_codecs; 678 - 679 - if (ch < num_codecs || ch % num_codecs != 0) { 680 - dev_err(rtd->dev, "Channels number %d is invalid when codec number = %d\n", 681 - ch, num_codecs); 682 - return -EINVAL; 683 - } 684 - 685 - ch_mask = GENMASK(ch / num_codecs - 1, 0); 686 - step = hweight_long(ch_mask); 687 - 688 - } 689 - 690 - /* 691 - * The captured data will be combined from each cpu DAI if the dai 692 - * link has more than one codec DAIs. Set codec channel mask and 693 - * ASoC will set the corresponding channel numbers for each cpu dai. 694 - */ 695 - for_each_link_ch_maps(rtd->dai_link, i, ch_maps) 696 - ch_maps->ch_mask = ch_mask << (i * step); 697 - 698 - return 0; 699 - } 700 - 701 - int asoc_sdw_hw_free(struct snd_pcm_substream *substream) 702 - { 703 - struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); 704 - struct sdw_stream_runtime *sdw_stream; 705 - struct snd_soc_dai *dai; 706 - 707 - /* Find stream from first CPU DAI */ 708 - dai = snd_soc_rtd_to_cpu(rtd, 0); 709 - 710 - sdw_stream = snd_soc_dai_get_stream(dai, substream->stream); 711 - if (IS_ERR(sdw_stream)) { 712 - dev_err(rtd->dev, "no stream found for DAI %s\n", dai->name); 713 - return PTR_ERR(sdw_stream); 714 - } 715 - 716 - return sdw_deprepare_stream(sdw_stream); 717 - } 718 - 719 - void asoc_sdw_shutdown(struct snd_pcm_substream *substream) 720 - { 721 - sdw_shutdown_stream(substream); 722 - } 723 595 724 596 static const struct snd_soc_ops sdw_ops = { 725 597 .startup = asoc_sdw_startup, ··· 2102 2232 MODULE_AUTHOR("Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>"); 2103 2233 MODULE_LICENSE("GPL v2"); 2104 2234 MODULE_IMPORT_NS(SND_SOC_INTEL_HDA_DSP_COMMON); 2235 + MODULE_IMPORT_NS(SND_SOC_SDW_UTILS);
+1 -8
sound/soc/intel/boards/sof_sdw_common.h
··· 12 12 #include <linux/bits.h> 13 13 #include <linux/types.h> 14 14 #include <sound/soc.h> 15 + #include <sound/soc_sdw_utils.h> 15 16 #include "sof_hdmi_common.h" 16 17 17 18 #define SOC_SDW_MAX_NO_PROPS 2 ··· 134 133 }; 135 134 136 135 extern unsigned long sof_sdw_quirk; 137 - 138 - int asoc_sdw_startup(struct snd_pcm_substream *substream); 139 - int asoc_sdw_prepare(struct snd_pcm_substream *substream); 140 - int asoc_sdw_trigger(struct snd_pcm_substream *substream, int cmd); 141 - int asoc_sdw_hw_params(struct snd_pcm_substream *substream, 142 - struct snd_pcm_hw_params *params); 143 - int asoc_sdw_hw_free(struct snd_pcm_substream *substream); 144 - void asoc_sdw_shutdown(struct snd_pcm_substream *substream); 145 136 146 137 /* generic HDMI support */ 147 138 int sof_sdw_hdmi_init(struct snd_soc_pcm_runtime *rtd);
+6
sound/soc/sdw_utils/Kconfig
··· 1 + # SPDX-License-Identifier: GPL-2.0-only 2 + config SND_SOC_SDW_UTILS 3 + tristate 4 + help 5 + This option enables to use SoundWire common helper functions and 6 + SoundWire codec helper functions in machine driver.
+3
sound/soc/sdw_utils/Makefile
··· 1 + # SPDX-License-Identifier: GPL-2.0-only 2 + snd-soc-sdw-utils-y := soc_sdw_utils.o 3 + obj-$(CONFIG_SND_SOC_SDW_UTILS) += snd-soc-sdw-utils.o
+150
sound/soc/sdw_utils/soc_sdw_utils.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + // This file incorporates work covered by the following copyright notice: 3 + // Copyright (c) 2020 Intel Corporation 4 + // Copyright(c) 2024 Advanced Micro Devices, Inc. 5 + /* 6 + * soc-sdw-utils.c - common SoundWire machine driver helper functions 7 + */ 8 + 9 + #include <linux/device.h> 10 + #include <linux/module.h> 11 + #include <linux/soundwire/sdw.h> 12 + #include <linux/soundwire/sdw_type.h> 13 + #include <sound/soc_sdw_utils.h> 14 + 15 + /* these wrappers are only needed to avoid typecast compilation errors */ 16 + int asoc_sdw_startup(struct snd_pcm_substream *substream) 17 + { 18 + return sdw_startup_stream(substream); 19 + } 20 + EXPORT_SYMBOL_NS(asoc_sdw_startup, SND_SOC_SDW_UTILS); 21 + 22 + int asoc_sdw_prepare(struct snd_pcm_substream *substream) 23 + { 24 + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); 25 + struct sdw_stream_runtime *sdw_stream; 26 + struct snd_soc_dai *dai; 27 + 28 + /* Find stream from first CPU DAI */ 29 + dai = snd_soc_rtd_to_cpu(rtd, 0); 30 + 31 + sdw_stream = snd_soc_dai_get_stream(dai, substream->stream); 32 + if (IS_ERR(sdw_stream)) { 33 + dev_err(rtd->dev, "no stream found for DAI %s\n", dai->name); 34 + return PTR_ERR(sdw_stream); 35 + } 36 + 37 + return sdw_prepare_stream(sdw_stream); 38 + } 39 + EXPORT_SYMBOL_NS(asoc_sdw_prepare, SND_SOC_SDW_UTILS); 40 + 41 + int asoc_sdw_trigger(struct snd_pcm_substream *substream, int cmd) 42 + { 43 + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); 44 + struct sdw_stream_runtime *sdw_stream; 45 + struct snd_soc_dai *dai; 46 + int ret; 47 + 48 + /* Find stream from first CPU DAI */ 49 + dai = snd_soc_rtd_to_cpu(rtd, 0); 50 + 51 + sdw_stream = snd_soc_dai_get_stream(dai, substream->stream); 52 + if (IS_ERR(sdw_stream)) { 53 + dev_err(rtd->dev, "no stream found for DAI %s\n", dai->name); 54 + return PTR_ERR(sdw_stream); 55 + } 56 + 57 + switch (cmd) { 58 + case SNDRV_PCM_TRIGGER_START: 59 + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 60 + case SNDRV_PCM_TRIGGER_RESUME: 61 + ret = sdw_enable_stream(sdw_stream); 62 + break; 63 + 64 + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 65 + case SNDRV_PCM_TRIGGER_SUSPEND: 66 + case SNDRV_PCM_TRIGGER_STOP: 67 + ret = sdw_disable_stream(sdw_stream); 68 + break; 69 + default: 70 + ret = -EINVAL; 71 + break; 72 + } 73 + 74 + if (ret) 75 + dev_err(rtd->dev, "%s trigger %d failed: %d\n", __func__, cmd, ret); 76 + 77 + return ret; 78 + } 79 + EXPORT_SYMBOL_NS(asoc_sdw_trigger, SND_SOC_SDW_UTILS); 80 + 81 + int asoc_sdw_hw_params(struct snd_pcm_substream *substream, 82 + struct snd_pcm_hw_params *params) 83 + { 84 + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); 85 + struct snd_soc_dai_link_ch_map *ch_maps; 86 + int ch = params_channels(params); 87 + unsigned int ch_mask; 88 + int num_codecs; 89 + int step; 90 + int i; 91 + 92 + if (!rtd->dai_link->ch_maps) 93 + return 0; 94 + 95 + /* Identical data will be sent to all codecs in playback */ 96 + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 97 + ch_mask = GENMASK(ch - 1, 0); 98 + step = 0; 99 + } else { 100 + num_codecs = rtd->dai_link->num_codecs; 101 + 102 + if (ch < num_codecs || ch % num_codecs != 0) { 103 + dev_err(rtd->dev, "Channels number %d is invalid when codec number = %d\n", 104 + ch, num_codecs); 105 + return -EINVAL; 106 + } 107 + 108 + ch_mask = GENMASK(ch / num_codecs - 1, 0); 109 + step = hweight_long(ch_mask); 110 + } 111 + 112 + /* 113 + * The captured data will be combined from each cpu DAI if the dai 114 + * link has more than one codec DAIs. Set codec channel mask and 115 + * ASoC will set the corresponding channel numbers for each cpu dai. 116 + */ 117 + for_each_link_ch_maps(rtd->dai_link, i, ch_maps) 118 + ch_maps->ch_mask = ch_mask << (i * step); 119 + 120 + return 0; 121 + } 122 + EXPORT_SYMBOL_NS(asoc_sdw_hw_params, SND_SOC_SDW_UTILS); 123 + 124 + int asoc_sdw_hw_free(struct snd_pcm_substream *substream) 125 + { 126 + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); 127 + struct sdw_stream_runtime *sdw_stream; 128 + struct snd_soc_dai *dai; 129 + 130 + /* Find stream from first CPU DAI */ 131 + dai = snd_soc_rtd_to_cpu(rtd, 0); 132 + 133 + sdw_stream = snd_soc_dai_get_stream(dai, substream->stream); 134 + if (IS_ERR(sdw_stream)) { 135 + dev_err(rtd->dev, "no stream found for DAI %s\n", dai->name); 136 + return PTR_ERR(sdw_stream); 137 + } 138 + 139 + return sdw_deprepare_stream(sdw_stream); 140 + } 141 + EXPORT_SYMBOL_NS(asoc_sdw_hw_free, SND_SOC_SDW_UTILS); 142 + 143 + void asoc_sdw_shutdown(struct snd_pcm_substream *substream) 144 + { 145 + sdw_shutdown_stream(substream); 146 + } 147 + EXPORT_SYMBOL_NS(asoc_sdw_shutdown, SND_SOC_SDW_UTILS); 148 + 149 + MODULE_LICENSE("GPL"); 150 + MODULE_DESCRIPTION("SoundWire ASoC helpers");