Unverified Commit 47c09498 authored by Mark Brown's avatar Mark Brown
Browse files

Harden SSP boards and add TDM support

Merge series from Amadeusz Sławiński <amadeuszx.slawinski@linux.intel.com>:

In quite a few places in code there are checks for number of SSPs
present on system, to reduce maintenance burden introduce helper
functions allowing to get SSP and TDM from machine board configuration.

Current mechanism replaces "%d" present in some routes and widget names
with SSP number. However there are also configurations which make use of
of TDM number, in which case expected behavior would be to have string
in form of SSP:TDM - see implementation of avs_i2s_platform_register()
in sound/soc/intel/avs/pcm.c. Implement custom function, which parses
string and make use of it when parsing topology. While at it make sure
that we generate dynamic names only if there is no multiple SSPs or TDMs
defined.

Migrate all boards to handle TDM if requested.
parents 41cb1126 5e07eb3a
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -193,7 +193,7 @@ static struct snd_soc_acpi_mach avs_apl_i2s_machines[] = {
		.mach_params = {
			.i2s_link_mask = AVS_SSP_RANGE(0, 5),
		},
		.pdata = (unsigned long[]){ 0, 0, 0x14, 0, 0, 0 }, /* SSP2 TDMs */
		.pdata = (unsigned long[]){ 0x1, 0x1, 0x14, 0x1, 0x1, 0x1 }, /* SSP2 TDMs */
		.tplg_filename = "tdf8532-tplg.bin",
	},
	{
+12 −5
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@
#include <sound/soc-dapm.h>
#include <uapi/linux/input-event-codes.h>
#include "../../../codecs/da7219.h"
#include "../utils.h"

#define DA7219_DAI_NAME		"da7219-hifi"

@@ -164,7 +165,7 @@ avs_da7219_be_fixup(struct snd_soc_pcm_runtime *runrime, struct snd_pcm_hw_param
}

static int avs_create_dai_link(struct device *dev, const char *platform_name, int ssp_port,
			       struct snd_soc_dai_link **dai_link)
			       int tdm_slot, struct snd_soc_dai_link **dai_link)
{
	struct snd_soc_dai_link_component *platform;
	struct snd_soc_dai_link *dl;
@@ -177,12 +178,15 @@ static int avs_create_dai_link(struct device *dev, const char *platform_name, in
	platform->name = platform_name;

	dl->name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-Codec", ssp_port);
	dl->name = devm_kasprintf(dev, GFP_KERNEL,
				  AVS_STRING_FMT("SSP", "-Codec", ssp_port, tdm_slot));
	dl->cpus = devm_kzalloc(dev, sizeof(*dl->cpus), GFP_KERNEL);
	dl->codecs = devm_kzalloc(dev, sizeof(*dl->codecs), GFP_KERNEL);
	if (!dl->name || !dl->cpus || !dl->codecs)
		return -ENOMEM;

	dl->cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d Pin", ssp_port);
	dl->cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL,
					    AVS_STRING_FMT("SSP", " Pin", ssp_port, tdm_slot));
	dl->codecs->name = devm_kasprintf(dev, GFP_KERNEL, "i2c-DLGS7219:00");
	dl->codecs->dai_name = devm_kasprintf(dev, GFP_KERNEL, DA7219_DAI_NAME);
	if (!dl->cpus->dai_name || !dl->codecs->name || !dl->codecs->dai_name)
@@ -230,13 +234,16 @@ static int avs_da7219_probe(struct platform_device *pdev)
	struct snd_soc_jack *jack;
	struct device *dev = &pdev->dev;
	const char *pname;
	int ssp_port, ret;
	int ssp_port, tdm_slot, ret;

	mach = dev_get_platdata(dev);
	pname = mach->mach_params.platform;
	ssp_port = __ffs(mach->mach_params.i2s_link_mask);

	ret = avs_create_dai_link(dev, pname, ssp_port, &dai_link);
	ret = avs_mach_get_ssp_tdm(dev, mach, &ssp_port, &tdm_slot);
	if (ret)
		return ret;

	ret = avs_create_dai_link(dev, pname, ssp_port, tdm_slot, &dai_link);
	if (ret) {
		dev_err(dev, "Failed to create dai link: %d", ret);
		return ret;
+12 −6
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@
#include <sound/soc.h>
#include <sound/soc-acpi.h>
#include <asm/intel-family.h>
#include "../utils.h"

#define ES8336_CODEC_DAI	"ES8316 HiFi"

@@ -194,7 +195,7 @@ static int avs_es8336_be_fixup(struct snd_soc_pcm_runtime *runtime,
	return 0;
}
static int avs_create_dai_link(struct device *dev, const char *platform_name, int ssp_port,
			       struct snd_soc_dai_link **dai_link)
			       int tdm_slot, struct snd_soc_dai_link **dai_link)
{
	struct snd_soc_dai_link_component *platform;
	struct snd_soc_dai_link *dl;
@@ -206,13 +207,15 @@ static int avs_create_dai_link(struct device *dev, const char *platform_name, in

	platform->name = platform_name;

	dl->name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-Codec", ssp_port);
	dl->name = devm_kasprintf(dev, GFP_KERNEL,
				  AVS_STRING_FMT("SSP", "-Codec", ssp_port, tdm_slot));
	dl->cpus = devm_kzalloc(dev, sizeof(*dl->cpus), GFP_KERNEL);
	dl->codecs = devm_kzalloc(dev, sizeof(*dl->codecs), GFP_KERNEL);
	if (!dl->name || !dl->cpus || !dl->codecs)
		return -ENOMEM;

	dl->cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d Pin", ssp_port);
	dl->cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL,
					    AVS_STRING_FMT("SSP", " Pin", ssp_port, tdm_slot));
	dl->codecs->name = devm_kasprintf(dev, GFP_KERNEL, "i2c-ESSX8336:00");
	dl->codecs->dai_name = devm_kasprintf(dev, GFP_KERNEL, ES8336_CODEC_DAI);
	if (!dl->cpus->dai_name || !dl->codecs->name || !dl->codecs->dai_name)
@@ -261,13 +264,16 @@ static int avs_es8336_probe(struct platform_device *pdev)
	struct snd_soc_card *card;
	struct device *dev = &pdev->dev;
	const char *pname;
	int ssp_port, ret;
	int ssp_port, tdm_slot, ret;

	mach = dev_get_platdata(dev);
	pname = mach->mach_params.platform;
	ssp_port = __ffs(mach->mach_params.i2s_link_mask);

	ret = avs_create_dai_link(dev, pname, ssp_port, &dai_link);
	ret = avs_mach_get_ssp_tdm(dev, mach, &ssp_port, &tdm_slot);
	if (ret)
		return ret;

	ret = avs_create_dai_link(dev, pname, ssp_port, tdm_slot, &dai_link);
	if (ret) {
		dev_err(dev, "Failed to create dai link: %d", ret);
		return ret;
+38 −17
Original line number Diff line number Diff line
@@ -12,9 +12,10 @@
#include <sound/soc.h>
#include <sound/soc-acpi.h>
#include <sound/soc-dapm.h>
#include "../utils.h"

static int avs_create_dai_link(struct device *dev, const char *platform_name, int ssp_port,
			       struct snd_soc_dai_link **dai_link)
			       int tdm_slot, struct snd_soc_dai_link **dai_link)
{
	struct snd_soc_dai_link_component *platform;
	struct snd_soc_dai_link *dl;
@@ -26,12 +27,14 @@ static int avs_create_dai_link(struct device *dev, const char *platform_name, in

	platform->name = platform_name;

	dl->name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-Codec", ssp_port);
	dl->name = devm_kasprintf(dev, GFP_KERNEL,
				  AVS_STRING_FMT("SSP", "-Codec", ssp_port, tdm_slot));
	dl->cpus = devm_kzalloc(dev, sizeof(*dl->cpus), GFP_KERNEL);
	if (!dl->name || !dl->cpus)
		return -ENOMEM;

	dl->cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d Pin", ssp_port);
	dl->cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL,
					    AVS_STRING_FMT("SSP", " Pin", ssp_port, tdm_slot));
	dl->codecs = &snd_soc_dummy_dlc;
	if (!dl->cpus->dai_name || !dl->codecs->name || !dl->codecs->dai_name)
		return -ENOMEM;
@@ -51,7 +54,7 @@ static int avs_create_dai_link(struct device *dev, const char *platform_name, in
	return 0;
}

static int avs_create_dapm_routes(struct device *dev, int ssp_port,
static int avs_create_dapm_routes(struct device *dev, int ssp_port, int tdm_slot,
				  struct snd_soc_dapm_route **routes, int *num_routes)
{
	struct snd_soc_dapm_route *dr;
@@ -61,13 +64,17 @@ static int avs_create_dapm_routes(struct device *dev, int ssp_port,
	if (!dr)
		return -ENOMEM;

	dr[0].sink = devm_kasprintf(dev, GFP_KERNEL, "ssp%dpb", ssp_port);
	dr[0].source = devm_kasprintf(dev, GFP_KERNEL, "ssp%d Tx", ssp_port);
	dr[0].sink = devm_kasprintf(dev, GFP_KERNEL,
				    AVS_STRING_FMT("ssp", "pb", ssp_port, tdm_slot));
	dr[0].source = devm_kasprintf(dev, GFP_KERNEL,
				      AVS_STRING_FMT("ssp", " Tx", ssp_port, tdm_slot));
	if (!dr[0].sink || !dr[0].source)
		return -ENOMEM;

	dr[1].sink = devm_kasprintf(dev, GFP_KERNEL, "ssp%d Rx", ssp_port);
	dr[1].source = devm_kasprintf(dev, GFP_KERNEL, "ssp%dcp", ssp_port);
	dr[1].sink = devm_kasprintf(dev, GFP_KERNEL,
				    AVS_STRING_FMT("ssp", " Rx", ssp_port, tdm_slot));
	dr[1].source = devm_kasprintf(dev, GFP_KERNEL,
				      AVS_STRING_FMT("ssp", "cp", ssp_port, tdm_slot));
	if (!dr[1].sink || !dr[1].source)
		return -ENOMEM;

@@ -77,7 +84,7 @@ static int avs_create_dapm_routes(struct device *dev, int ssp_port,
	return 0;
}

static int avs_create_dapm_widgets(struct device *dev, int ssp_port,
static int avs_create_dapm_widgets(struct device *dev, int ssp_port, int tdm_slot,
				   struct snd_soc_dapm_widget **widgets, int *num_widgets)
{
	struct snd_soc_dapm_widget *dw;
@@ -89,13 +96,15 @@ static int avs_create_dapm_widgets(struct device *dev, int ssp_port,

	dw[0].id = snd_soc_dapm_hp;
	dw[0].reg = SND_SOC_NOPM;
	dw[0].name = devm_kasprintf(dev, GFP_KERNEL, "ssp%dpb", ssp_port);
	dw[0].name = devm_kasprintf(dev, GFP_KERNEL,
				    AVS_STRING_FMT("ssp", "pb", ssp_port, tdm_slot));
	if (!dw[0].name)
		return -ENOMEM;

	dw[1].id = snd_soc_dapm_mic;
	dw[1].reg = SND_SOC_NOPM;
	dw[1].name = devm_kasprintf(dev, GFP_KERNEL, "ssp%dcp", ssp_port);
	dw[1].name = devm_kasprintf(dev, GFP_KERNEL,
				    AVS_STRING_FMT("ssp", "cp", ssp_port, tdm_slot));
	if (!dw[1].name)
		return -ENOMEM;

@@ -115,33 +124,45 @@ static int avs_i2s_test_probe(struct platform_device *pdev)
	struct device *dev = &pdev->dev;
	const char *pname;
	int num_routes, num_widgets;
	int ssp_port, ret;
	int ssp_port, tdm_slot, ret;

	mach = dev_get_platdata(dev);
	pname = mach->mach_params.platform;
	ssp_port = __ffs(mach->mach_params.i2s_link_mask);

	if (!avs_mach_singular_ssp(mach)) {
		dev_err(dev, "Invalid SSP configuration\n");
		return -EINVAL;
	}
	ssp_port = avs_mach_ssp_port(mach);

	if (!avs_mach_singular_tdm(mach, ssp_port)) {
		dev_err(dev, "Invalid TDM configuration\n");
		return -EINVAL;
	}
	tdm_slot = avs_mach_ssp_tdm(mach, ssp_port);

	card = devm_kzalloc(dev, sizeof(*card), GFP_KERNEL);
	if (!card)
		return -ENOMEM;

	card->name = devm_kasprintf(dev, GFP_KERNEL, "ssp%d-loopback", ssp_port);
	card->name = devm_kasprintf(dev, GFP_KERNEL,
				    AVS_STRING_FMT("ssp", "-loopback", ssp_port, tdm_slot));
	if (!card->name)
		return -ENOMEM;

	ret = avs_create_dai_link(dev, pname, ssp_port, &dai_link);
	ret = avs_create_dai_link(dev, pname, ssp_port, tdm_slot, &dai_link);
	if (ret) {
		dev_err(dev, "Failed to create dai link: %d\n", ret);
		return ret;
	}

	ret = avs_create_dapm_routes(dev, ssp_port, &routes, &num_routes);
	ret = avs_create_dapm_routes(dev, ssp_port, tdm_slot, &routes, &num_routes);
	if (ret) {
		dev_err(dev, "Failed to create dapm routes: %d\n", ret);
		return ret;
	}

	ret = avs_create_dapm_widgets(dev, ssp_port, &widgets, &num_widgets);
	ret = avs_create_dapm_widgets(dev, ssp_port, tdm_slot, &widgets, &num_widgets);
	if (ret) {
		dev_err(dev, "Failed to create dapm widgets: %d\n", ret);
		return ret;
+12 −6
Original line number Diff line number Diff line
@@ -12,6 +12,7 @@
#include <sound/soc.h>
#include <sound/soc-acpi.h>
#include <sound/soc-dapm.h>
#include "../utils.h"

static const struct snd_kcontrol_new card_controls[] = {
	SOC_DAPM_PIN_SWITCH("Spk"),
@@ -46,7 +47,7 @@ avs_max98357a_be_fixup(struct snd_soc_pcm_runtime *runrime, struct snd_pcm_hw_pa
}

static int avs_create_dai_link(struct device *dev, const char *platform_name, int ssp_port,
			       struct snd_soc_dai_link **dai_link)
			       int tdm_slot, struct snd_soc_dai_link **dai_link)
{
	struct snd_soc_dai_link_component *platform;
	struct snd_soc_dai_link *dl;
@@ -58,13 +59,15 @@ static int avs_create_dai_link(struct device *dev, const char *platform_name, in

	platform->name = platform_name;

	dl->name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-Codec", ssp_port);
	dl->name = devm_kasprintf(dev, GFP_KERNEL,
				  AVS_STRING_FMT("SSP", "-Codec", ssp_port, tdm_slot));
	dl->cpus = devm_kzalloc(dev, sizeof(*dl->cpus), GFP_KERNEL);
	dl->codecs = devm_kzalloc(dev, sizeof(*dl->codecs), GFP_KERNEL);
	if (!dl->name || !dl->cpus || !dl->codecs)
		return -ENOMEM;

	dl->cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d Pin", ssp_port);
	dl->cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL,
					    AVS_STRING_FMT("SSP", " Pin", ssp_port, tdm_slot));
	dl->codecs->name = devm_kasprintf(dev, GFP_KERNEL, "MX98357A:00");
	dl->codecs->dai_name = devm_kasprintf(dev, GFP_KERNEL, "HiFi");
	if (!dl->cpus->dai_name || !dl->codecs->name || !dl->codecs->dai_name)
@@ -93,13 +96,16 @@ static int avs_max98357a_probe(struct platform_device *pdev)
	struct snd_soc_card *card;
	struct device *dev = &pdev->dev;
	const char *pname;
	int ssp_port, ret;
	int ssp_port, tdm_slot, ret;

	mach = dev_get_platdata(dev);
	pname = mach->mach_params.platform;
	ssp_port = __ffs(mach->mach_params.i2s_link_mask);

	ret = avs_create_dai_link(dev, pname, ssp_port, &dai_link);
	ret = avs_mach_get_ssp_tdm(dev, mach, &ssp_port, &tdm_slot);
	if (ret)
		return ret;

	ret = avs_create_dai_link(dev, pname, ssp_port, tdm_slot, &dai_link);
	if (ret) {
		dev_err(dev, "Failed to create dai link: %d", ret);
		return ret;
Loading