aboutsummaryrefslogtreecommitdiff
path: root/sound/soc/intel/boards/sof_board_helpers.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2024-01-12 11:55:28 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2024-01-12 11:55:28 -0800
commit7912a6391f3ee7eb9f9a69227a209d502679bc0c (patch)
tree38be70147934f98cde0ccef0ba65b836246e4d0d /sound/soc/intel/boards/sof_board_helpers.c
parentcf65598d5909acf5e7b7dc9e21786e386356bc81 (diff)
parentfd38dd6abda589a8771e7872e4dea28c99c6a6ef (diff)
Merge tag 'sound-6.8-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound
Pull sound updates from Takashi Iwai: "It was a calm development cycle. There were an ALSA core extension for subformat PCM bits and a few ASoC core changes to support N:M mappings, while the most of remaining changes are driver-specific. Core: - API extensions for properly limiting PCM format bits via subformat - Enhanced support for N:M CPU:CODEC mappings in the core and in audio-graph-card2 ASoC: - Lots of SOF updates: fallback support to older IPC versions, notification on control changes with IPC4. Also supports for ACPI parse for the ES83xx driver that reduces quirks. - Device tree support for describing parts of the card which can be active over suspend (for very low power playback or wake word use cases) - Support for more AMD and Intel systems, NXP i.MX8m MICFIL, Qualcomm SM8250, SM8550, SM8650 and X1E80100 - Drop of Freescale MPC8610 code that is no longer supported HD-audio: - More CS35L41 codec extensions for Dell, HP and Lenovo models - TAS2781 codec extensions for Lenovo and co - New PCM subformat supports Others: - More enhancement for Scarlett2 USB mixer support - Various kselftest fixes" * tag 'sound-6.8-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: (337 commits) kselftest/alsa - conf: Stringify the printed errno in sysfs_get() kselftest/alsa - mixer-test: Fix the print format specifier warning kselftest/alsa - mixer-test: Fix the print format specifier warning kselftest/alsa - mixer-test: fix the number of parameters to ksft_exit_fail_msg() ALSA: hda/tas2781: annotate calibration data endianness ALSA: hda/realtek: Fix mute and mic-mute LEDs for HP Envy X360 13-ay0xxx ALSA: hda/conexant: Fix headset auto detect fail in cx8070 and SN6140 ALSA: ac97: fix build regression ALSA: hda: cs35l41: Support more HP models without _DSD ALSA: hda/tas2781: add fixup for Lenovo 14ARB7 ALSA: hda/tas2781: add TAS2563 support for 14ARB7 ALSA: hda/tas2781: add configurable global i2c address ALSA: hda/tas2781: add ptrs to calibration functions ALSA: hda: Add driver properties for cs35l41 for Lenovo Legion Slim 7 Gen 8 serie ALSA: hda/realtek: enable SND_PCI_QUIRK for Lenovo Legion Slim 7 Gen 8 (2023) serie ALSA: hda/tas2781: configure the amp after firmware load ALSA: mark all struct bus_type as const ASoC: pxa: sspa: Don't select SND_ARM ASoC: rt5663: cancel the work when system suspends ALSA: scarlett2: Add PCM Input Switch for Solo Gen 4 ...
Diffstat (limited to 'sound/soc/intel/boards/sof_board_helpers.c')
-rw-r--r--sound/soc/intel/boards/sof_board_helpers.c330
1 files changed, 330 insertions, 0 deletions
diff --git a/sound/soc/intel/boards/sof_board_helpers.c b/sound/soc/intel/boards/sof_board_helpers.c
index ce2967850c2d..4f2cb8e52971 100644
--- a/sound/soc/intel/boards/sof_board_helpers.c
+++ b/sound/soc/intel/boards/sof_board_helpers.c
@@ -3,6 +3,7 @@
// Copyright(c) 2023 Intel Corporation. All rights reserved.
#include <sound/soc.h>
+#include "../common/soc-intel-quirks.h"
#include "hda_dsp_common.h"
#include "sof_board_helpers.h"
@@ -86,6 +87,55 @@ static struct snd_soc_dai_link_component platform_component[] = {
}
};
+int sof_intel_board_set_codec_link(struct device *dev,
+ struct snd_soc_dai_link *link, int be_id,
+ enum sof_ssp_codec codec_type, int ssp_codec)
+{
+ struct snd_soc_dai_link_component *cpus;
+
+ dev_dbg(dev, "link %d: codec %s, ssp %d\n", be_id,
+ sof_ssp_get_codec_name(codec_type), ssp_codec);
+
+ /* link name */
+ link->name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-Codec", ssp_codec);
+ if (!link->name)
+ return -ENOMEM;
+
+ /* cpus */
+ cpus = devm_kzalloc(dev, sizeof(struct snd_soc_dai_link_component),
+ GFP_KERNEL);
+ if (!cpus)
+ return -ENOMEM;
+
+ if (soc_intel_is_byt() || soc_intel_is_cht()) {
+ /* backward-compatibility for BYT/CHT boards */
+ cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL, "ssp%d-port",
+ ssp_codec);
+ } else {
+ cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d Pin",
+ ssp_codec);
+ }
+ if (!cpus->dai_name)
+ return -ENOMEM;
+
+ link->cpus = cpus;
+ link->num_cpus = 1;
+
+ /* codecs - caller to handle */
+
+ /* platforms */
+ link->platforms = platform_component;
+ link->num_platforms = ARRAY_SIZE(platform_component);
+
+ link->id = be_id;
+ link->no_pcm = 1;
+ link->dpcm_capture = 1;
+ link->dpcm_playback = 1;
+
+ return 0;
+}
+EXPORT_SYMBOL_NS(sof_intel_board_set_codec_link, SND_SOC_INTEL_SOF_BOARD_HELPERS);
+
int sof_intel_board_set_dmic_link(struct device *dev,
struct snd_soc_dai_link *link, int be_id,
enum sof_dmic_be_type be_type)
@@ -198,7 +248,287 @@ int sof_intel_board_set_intel_hdmi_link(struct device *dev,
}
EXPORT_SYMBOL_NS(sof_intel_board_set_intel_hdmi_link, SND_SOC_INTEL_SOF_BOARD_HELPERS);
+int sof_intel_board_set_ssp_amp_link(struct device *dev,
+ struct snd_soc_dai_link *link, int be_id,
+ enum sof_ssp_codec amp_type, int ssp_amp)
+{
+ struct snd_soc_dai_link_component *cpus;
+
+ dev_dbg(dev, "link %d: ssp amp %s, ssp %d\n", be_id,
+ sof_ssp_get_codec_name(amp_type), ssp_amp);
+
+ /* link name */
+ link->name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-Codec", ssp_amp);
+ if (!link->name)
+ return -ENOMEM;
+
+ /* cpus */
+ cpus = devm_kzalloc(dev, sizeof(struct snd_soc_dai_link_component),
+ GFP_KERNEL);
+ if (!cpus)
+ return -ENOMEM;
+
+ cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d Pin", ssp_amp);
+ if (!cpus->dai_name)
+ return -ENOMEM;
+
+ link->cpus = cpus;
+ link->num_cpus = 1;
+
+ /* codecs - caller to handle */
+
+ /* platforms */
+ link->platforms = platform_component;
+ link->num_platforms = ARRAY_SIZE(platform_component);
+
+ link->id = be_id;
+ link->no_pcm = 1;
+ link->dpcm_capture = 1; /* feedback stream or firmware-generated echo reference */
+ link->dpcm_playback = 1;
+
+ return 0;
+}
+EXPORT_SYMBOL_NS(sof_intel_board_set_ssp_amp_link, SND_SOC_INTEL_SOF_BOARD_HELPERS);
+
+int sof_intel_board_set_bt_link(struct device *dev,
+ struct snd_soc_dai_link *link, int be_id,
+ int ssp_bt)
+{
+ struct snd_soc_dai_link_component *cpus;
+
+ dev_dbg(dev, "link %d: bt offload, ssp %d\n", be_id, ssp_bt);
+
+ /* link name */
+ link->name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-BT", ssp_bt);
+ if (!link->name)
+ return -ENOMEM;
+
+ /* cpus */
+ cpus = devm_kzalloc(dev, sizeof(struct snd_soc_dai_link_component),
+ GFP_KERNEL);
+ if (!cpus)
+ return -ENOMEM;
+
+ cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d Pin", ssp_bt);
+ if (!cpus->dai_name)
+ return -ENOMEM;
+
+ link->cpus = cpus;
+ link->num_cpus = 1;
+
+ /* codecs */
+ link->codecs = &snd_soc_dummy_dlc;
+ link->num_codecs = 1;
+
+ /* platforms */
+ link->platforms = platform_component;
+ link->num_platforms = ARRAY_SIZE(platform_component);
+
+ link->id = be_id;
+ link->no_pcm = 1;
+ link->dpcm_capture = 1;
+ link->dpcm_playback = 1;
+
+ return 0;
+}
+EXPORT_SYMBOL_NS(sof_intel_board_set_bt_link, SND_SOC_INTEL_SOF_BOARD_HELPERS);
+
+int sof_intel_board_set_hdmi_in_link(struct device *dev,
+ struct snd_soc_dai_link *link, int be_id,
+ int ssp_hdmi)
+{
+ struct snd_soc_dai_link_component *cpus;
+
+ dev_dbg(dev, "link %d: hdmi-in, ssp %d\n", be_id, ssp_hdmi);
+
+ /* link name */
+ link->name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-HDMI", ssp_hdmi);
+ if (!link->name)
+ return -ENOMEM;
+
+ /* cpus */
+ cpus = devm_kzalloc(dev, sizeof(struct snd_soc_dai_link_component),
+ GFP_KERNEL);
+ if (!cpus)
+ return -ENOMEM;
+
+ cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d Pin", ssp_hdmi);
+ if (!cpus->dai_name)
+ return -ENOMEM;
+
+ link->cpus = cpus;
+ link->num_cpus = 1;
+
+ /* codecs */
+ link->codecs = &snd_soc_dummy_dlc;
+ link->num_codecs = 1;
+
+ /* platforms */
+ link->platforms = platform_component;
+ link->num_platforms = ARRAY_SIZE(platform_component);
+
+ link->id = be_id;
+ link->no_pcm = 1;
+ link->dpcm_capture = 1;
+
+ return 0;
+}
+EXPORT_SYMBOL_NS(sof_intel_board_set_hdmi_in_link, SND_SOC_INTEL_SOF_BOARD_HELPERS);
+
+static int calculate_num_links(struct sof_card_private *ctx)
+{
+ int num_links = 0;
+
+ /* headphone codec */
+ if (ctx->codec_type != CODEC_NONE)
+ num_links++;
+
+ /* dmic01 and dmic16k */
+ if (ctx->dmic_be_num > 0)
+ num_links++;
+
+ if (ctx->dmic_be_num > 1)
+ num_links++;
+
+ /* idisp HDMI */
+ num_links += ctx->hdmi_num;
+
+ /* speaker amp */
+ if (ctx->amp_type != CODEC_NONE)
+ num_links++;
+
+ /* BT audio offload */
+ if (ctx->bt_offload_present)
+ num_links++;
+
+ /* HDMI-In */
+ num_links += hweight32(ctx->ssp_mask_hdmi_in);
+
+ return num_links;
+}
+
+int sof_intel_board_set_dai_link(struct device *dev, struct snd_soc_card *card,
+ struct sof_card_private *ctx)
+{
+ struct snd_soc_dai_link *links;
+ int num_links;
+ int i;
+ int idx = 0;
+ int ret;
+ int ssp_hdmi_in = 0;
+
+ num_links = calculate_num_links(ctx);
+
+ links = devm_kcalloc(dev, num_links, sizeof(struct snd_soc_dai_link),
+ GFP_KERNEL);
+ if (!links)
+ return -ENOMEM;
+
+ /* headphone codec */
+ if (ctx->codec_type != CODEC_NONE) {
+ ret = sof_intel_board_set_codec_link(dev, &links[idx], idx,
+ ctx->codec_type,
+ ctx->ssp_codec);
+ if (ret) {
+ dev_err(dev, "fail to set codec link, ret %d\n", ret);
+ return ret;
+ }
+
+ ctx->codec_link = &links[idx];
+ idx++;
+ }
+
+ /* dmic01 and dmic16k */
+ if (ctx->dmic_be_num > 0) {
+ /* at least we have dmic01 */
+ ret = sof_intel_board_set_dmic_link(dev, &links[idx], idx,
+ SOF_DMIC_01);
+ if (ret) {
+ dev_err(dev, "fail to set dmic01 link, ret %d\n", ret);
+ return ret;
+ }
+
+ idx++;
+ }
+
+ if (ctx->dmic_be_num > 1) {
+ /* set up 2 BE links at most */
+ ret = sof_intel_board_set_dmic_link(dev, &links[idx], idx,
+ SOF_DMIC_16K);
+ if (ret) {
+ dev_err(dev, "fail to set dmic16k link, ret %d\n", ret);
+ return ret;
+ }
+
+ idx++;
+ }
+
+ /* idisp HDMI */
+ for (i = 1; i <= ctx->hdmi_num; i++) {
+ ret = sof_intel_board_set_intel_hdmi_link(dev, &links[idx], idx,
+ i,
+ ctx->hdmi.idisp_codec);
+ if (ret) {
+ dev_err(dev, "fail to set hdmi link, ret %d\n", ret);
+ return ret;
+ }
+
+ idx++;
+ }
+
+ /* speaker amp */
+ if (ctx->amp_type != CODEC_NONE) {
+ ret = sof_intel_board_set_ssp_amp_link(dev, &links[idx], idx,
+ ctx->amp_type,
+ ctx->ssp_amp);
+ if (ret) {
+ dev_err(dev, "fail to set amp link, ret %d\n", ret);
+ return ret;
+ }
+
+ ctx->amp_link = &links[idx];
+ idx++;
+ }
+
+ /* BT audio offload */
+ if (ctx->bt_offload_present) {
+ ret = sof_intel_board_set_bt_link(dev, &links[idx], idx,
+ ctx->ssp_bt);
+ if (ret) {
+ dev_err(dev, "fail to set bt link, ret %d\n", ret);
+ return ret;
+ }
+
+ idx++;
+ }
+
+ /* HDMI-In */
+ for_each_set_bit(ssp_hdmi_in, &ctx->ssp_mask_hdmi_in, 32) {
+ ret = sof_intel_board_set_hdmi_in_link(dev, &links[idx], idx,
+ ssp_hdmi_in);
+ if (ret) {
+ dev_err(dev, "fail to set hdmi-in link, ret %d\n", ret);
+ return ret;
+ }
+
+ idx++;
+ }
+
+ if (idx != num_links) {
+ dev_err(dev, "link number mismatch, idx %d, num_links %d\n", idx,
+ num_links);
+ return -EINVAL;
+ }
+
+ card->dai_link = links;
+ card->num_links = num_links;
+
+ return 0;
+}
+EXPORT_SYMBOL_NS(sof_intel_board_set_dai_link, SND_SOC_INTEL_SOF_BOARD_HELPERS);
+
MODULE_DESCRIPTION("ASoC Intel SOF Machine Driver Board Helpers");
MODULE_AUTHOR("Brent Lu <brent.lu@intel.com>");
MODULE_LICENSE("GPL");
MODULE_IMPORT_NS(SND_SOC_INTEL_HDA_DSP_COMMON);
+MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_SSP_COMMON);