Unverified Commit 34c43ad9 authored by Mark Brown's avatar Mark Brown
Browse files

ASoC: Intel: updates for 6.10 - part5

Merge series from Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>:

This patchset corrects a couple of mistakes corrected, improves
snd_soc_card allocation.  The new functionality is mostly for
SoundWire platforms, with new SKUs for Dell and Acer, and support for
the Cirrus Logic bridge/sidecar amplifier topology.
parents 9a8caddd b831b4dc
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -690,6 +690,7 @@ config SND_SOC_INTEL_SOUNDWIRE_SOF_MACH
	select SND_SOC_CS42L43_SDW
	select MFD_CS42L43
	select MFD_CS42L43_SDW
	select SND_SOC_CS35L56_SPI
	select SND_SOC_CS35L56_SDW
	select SND_SOC_DMIC
	select SND_SOC_INTEL_HDA_DSP_COMMON
+1 −0
Original line number Diff line number Diff line
@@ -37,6 +37,7 @@ snd-soc-ehl-rt5660-objs := ehl_rt5660.o
snd-soc-sof-ssp-amp-objs := sof_ssp_amp.o
snd-soc-sof-sdw-objs += sof_sdw.o				\
			sof_sdw_maxim.o sof_sdw_rt_amp.o	\
			bridge_cs35l56.o			\
			sof_sdw_rt5682.o sof_sdw_rt700.o	\
			sof_sdw_rt711.o sof_sdw_rt_sdca_jack_common.o	\
			sof_sdw_rt712_sdca.o sof_sdw_rt722_sdca.o	\
+137 −0
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0-only
//
// Intel SOF Machine Driver with Cirrus Logic CS35L56 Smart Amp

#include <linux/module.h>
#include <linux/platform_device.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
#include <sound/soc-acpi.h>
#include "sof_sdw_common.h"

static const struct snd_soc_dapm_widget bridge_widgets[] = {
	SND_SOC_DAPM_SPK("Bridge Speaker", NULL),
};

static const struct snd_soc_dapm_route bridge_map[] = {
	{"Bridge Speaker", NULL, "AMPL SPK"},
	{"Bridge Speaker", NULL, "AMPR SPK"},
};

static const char * const bridge_cs35l56_name_prefixes[] = {
	"AMPL",
	"AMPR",
};

static int bridge_cs35l56_asp_init(struct snd_soc_pcm_runtime *rtd)
{
	struct snd_soc_card *card = rtd->card;
	int i, ret;
	unsigned int rx_mask = 3; // ASP RX1, RX2
	unsigned int tx_mask = 3; // ASP TX1, TX2
	struct snd_soc_dai *codec_dai;
	struct snd_soc_dai *cpu_dai;

	card->components = devm_kasprintf(card->dev, GFP_KERNEL,
					  "%s spk:cs35l56-bridge",
					  card->components);
	if (!card->components)
		return -ENOMEM;

	ret = snd_soc_dapm_new_controls(&card->dapm, bridge_widgets,
					ARRAY_SIZE(bridge_widgets));
	if (ret) {
		dev_err(card->dev, "widgets addition failed: %d\n", ret);
		return ret;
	}

	ret = snd_soc_dapm_add_routes(&card->dapm, bridge_map, ARRAY_SIZE(bridge_map));
	if (ret) {
		dev_err(card->dev, "map addition failed: %d\n", ret);
		return ret;
	}

	/* 4 x 16-bit sample slots and FSYNC=48000, BCLK=3.072 MHz */
	for_each_rtd_codec_dais(rtd, i, codec_dai) {
		ret = snd_soc_dai_set_tdm_slot(codec_dai, tx_mask, rx_mask, 4, 16);
		if (ret < 0)
			return ret;

		ret = snd_soc_dai_set_sysclk(codec_dai, 0, 3072000, SND_SOC_CLOCK_IN);
		if (ret < 0)
			return ret;
	}

	for_each_rtd_cpu_dais(rtd, i, cpu_dai) {
		ret = snd_soc_dai_set_tdm_slot(cpu_dai, tx_mask, rx_mask, 4, 16);
		if (ret < 0)
			return ret;
	}

	return 0;
}

static const struct snd_soc_pcm_stream bridge_params = {
	.formats = SNDRV_PCM_FMTBIT_S16_LE,
	.rate_min = 48000,
	.rate_max = 48000,
	.channels_min = 2,
	.channels_max = 2,
};

SND_SOC_DAILINK_DEFS(bridge_dai,
		     DAILINK_COMP_ARRAY(COMP_CODEC("cs42l43-codec", "cs42l43-asp")),
		     DAILINK_COMP_ARRAY(COMP_CODEC("spi-cs35l56-left", "cs35l56-asp1"),
					COMP_CODEC("spi-cs35l56-right", "cs35l56-asp1")),
		     DAILINK_COMP_ARRAY(COMP_PLATFORM("cs42l43-codec")));

static const struct snd_soc_dai_link bridge_dai_template = {
	.name = "cs42l43-cs35l56",
	.init = bridge_cs35l56_asp_init,
	.c2c_params = &bridge_params,
	.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_IB_IF | SND_SOC_DAIFMT_CBC_CFC,
	SND_SOC_DAILINK_REG(bridge_dai),
};

int bridge_cs35l56_count_sidecar(struct snd_soc_card *card,
				 int *num_dais, int *num_devs)
{
	if (sof_sdw_quirk & SOF_SIDECAR_AMPS) {
		(*num_dais)++;
		(*num_devs) += ARRAY_SIZE(bridge_cs35l56_name_prefixes);
	}

	return 0;
}

int bridge_cs35l56_add_sidecar(struct snd_soc_card *card,
			       struct snd_soc_dai_link **dai_links,
			       struct snd_soc_codec_conf **codec_conf)
{
	if (sof_sdw_quirk & SOF_SIDECAR_AMPS) {
		**dai_links = bridge_dai_template;

		for (int i = 0; i < ARRAY_SIZE(bridge_cs35l56_name_prefixes); i++) {
			(*codec_conf)->dlc.name = (*dai_links)->codecs[i].name;
			(*codec_conf)->name_prefix = bridge_cs35l56_name_prefixes[i];
			(*codec_conf)++;
		}

		(*dai_links)++;
	}

	return 0;
}

int bridge_cs35l56_spk_init(struct snd_soc_card *card,
			    struct snd_soc_dai_link *dai_links,
			    struct sof_sdw_codec_info *info,
			    bool playback)
{
	if (sof_sdw_quirk & SOF_SIDECAR_AMPS)
		info->amp_num += ARRAY_SIZE(bridge_cs35l56_name_prefixes);

	return 0;
}
+1 −0
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@ struct skl_hda_hdmi_pcm {
};

struct skl_hda_private {
	struct snd_soc_card card;
	struct list_head hdmi_pcm_list;
	int pcm_count;
	int dai_index;
+25 −25
Original line number Diff line number Diff line
@@ -92,19 +92,6 @@ skl_hda_add_dai_link(struct snd_soc_card *card, struct snd_soc_dai_link *link)
	return ret;
}

static struct snd_soc_card hda_soc_card = {
	.name = "hda-dsp",
	.owner = THIS_MODULE,
	.dai_link = skl_hda_be_dai_links,
	.dapm_widgets = skl_hda_widgets,
	.dapm_routes = skl_hda_map,
	.add_dai_link = skl_hda_add_dai_link,
	.fully_routed = true,
	.late_probe = skl_hda_card_late_probe,
};

static char hda_soc_components[30];

#define IDISP_DAI_COUNT		3
#define HDAC_DAI_COUNT		2
#define DMIC_DAI_COUNT		2
@@ -115,9 +102,9 @@ static char hda_soc_components[30];

#define HDA_CODEC_AUTOSUSPEND_DELAY_MS 1000

static int skl_hda_fill_card_info(struct snd_soc_acpi_mach_params *mach_params)
static int skl_hda_fill_card_info(struct snd_soc_card *card,
				  struct snd_soc_acpi_mach_params *mach_params)
{
	struct snd_soc_card *card = &hda_soc_card;
	struct skl_hda_private *ctx = snd_soc_card_get_drvdata(card);
	struct snd_soc_dai_link *dai_link;
	u32 codec_count, codec_mask;
@@ -199,6 +186,7 @@ static int skl_hda_audio_probe(struct platform_device *pdev)
{
	struct snd_soc_acpi_mach *mach;
	struct skl_hda_private *ctx;
	struct snd_soc_card *card;
	int ret;

	dev_dbg(&pdev->dev, "entry\n");
@@ -213,32 +201,44 @@ static int skl_hda_audio_probe(struct platform_device *pdev)
	if (!mach)
		return -EINVAL;

	snd_soc_card_set_drvdata(&hda_soc_card, ctx);
	card = &ctx->card;
	card->name = "hda-dsp",
	card->owner = THIS_MODULE,
	card->dai_link = skl_hda_be_dai_links,
	card->dapm_widgets = skl_hda_widgets,
	card->dapm_routes = skl_hda_map,
	card->add_dai_link = skl_hda_add_dai_link,
	card->fully_routed = true,
	card->late_probe = skl_hda_card_late_probe,

	ret = skl_hda_fill_card_info(&mach->mach_params);
	snd_soc_card_set_drvdata(card, ctx);

	ret = skl_hda_fill_card_info(card, &mach->mach_params);
	if (ret < 0) {
		dev_err(&pdev->dev, "Unsupported HDAudio/iDisp configuration found\n");
		return ret;
	}

	ctx->pcm_count = hda_soc_card.num_links;
	ctx->pcm_count = card->num_links;
	ctx->dai_index = 1; /* hdmi codec dai name starts from index 1 */
	ctx->platform_name = mach->mach_params.platform;
	ctx->common_hdmi_codec_drv = mach->mach_params.common_hdmi_codec_drv;

	hda_soc_card.dev = &pdev->dev;
	card->dev = &pdev->dev;
	if (!snd_soc_acpi_sof_parent(&pdev->dev))
		hda_soc_card.disable_route_checks = true;
		card->disable_route_checks = true;

	if (mach->mach_params.dmic_num > 0) {
		snprintf(hda_soc_components, sizeof(hda_soc_components),
				"cfg-dmics:%d", mach->mach_params.dmic_num);
		hda_soc_card.components = hda_soc_components;
		card->components = devm_kasprintf(card->dev, GFP_KERNEL,
						  "cfg-dmics:%d",
						  mach->mach_params.dmic_num);
		if (!card->components)
			return -ENOMEM;
	}

	ret = devm_snd_soc_register_card(&pdev->dev, &hda_soc_card);
	ret = devm_snd_soc_register_card(&pdev->dev, card);
	if (!ret)
		skl_set_hda_codec_autosuspend_delay(&hda_soc_card);
		skl_set_hda_codec_autosuspend_delay(card);

	return ret;
}
Loading