Unverified Commit 59960e67 authored by Mark Brown's avatar Mark Brown
Browse files

ASoC: Intel: machine driver updates for 6.5

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

An unusually large set of patches to deal with new SoundWire-based
platforms.

The bulk of the patches addresses support for MTL using RT712, RT713,
MAX98363, CS42L42 jack codec and amplifiers. The sof_sdw machine
driver had to be updated to remove limitations on number of codecs per
links, dai types, dai naming, etc. We also moved parts of the Realtek
and Maxim support in common code to avoid duplication.

Community users also reported two Dell SKUs which were not supported
in the mainline due to hardware permutations.
parents c7e076de a0503817
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -662,11 +662,14 @@ config SND_SOC_INTEL_SOUNDWIRE_SOF_MACH
	depends on MFD_INTEL_LPSS || COMPILE_TEST
	depends on SND_SOC_INTEL_USER_FRIENDLY_LONG_NAMES || COMPILE_TEST
	depends on SOUNDWIRE
	select SND_SOC_MAX98363
	select SND_SOC_MAX98373_I2C
	select SND_SOC_MAX98373_SDW
	select SND_SOC_RT700_SDW
	select SND_SOC_RT711_SDW
	select SND_SOC_RT711_SDCA_SDW
	select SND_SOC_RT712_SDCA_SDW
	select SND_SOC_RT712_SDCA_DMIC_SDW
	select SND_SOC_RT1308_SDW
	select SND_SOC_RT1308
	select SND_SOC_RT1316_SDW
@@ -674,6 +677,7 @@ config SND_SOC_INTEL_SOUNDWIRE_SOF_MACH
	select SND_SOC_RT715_SDW
	select SND_SOC_RT715_SDCA_SDW
	select SND_SOC_RT5682_SDW
	select SND_SOC_CS42L42_SDW
	select SND_SOC_DMIC
	select SND_SOC_INTEL_HDA_DSP_COMMON
	select SND_SOC_INTEL_SOF_MAXIM_COMMON
+6 −4
Original line number Diff line number Diff line
@@ -37,11 +37,13 @@ snd-soc-sof_da7219_max98373-objs := sof_da7219_max98373.o
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_max98373.o sof_sdw_rt_amp.o	\
			sof_sdw_maxim.o sof_sdw_rt_amp.o	\
			sof_sdw_rt5682.o sof_sdw_rt700.o	\
			sof_sdw_rt711.o sof_sdw_rt711_sdca.o 	\
			sof_sdw_rt715.o	sof_sdw_rt715_sdca.o 	\
			sof_sdw_dmic.o sof_sdw_hdmi.o
			sof_sdw_rt711.o sof_sdw_rt_sdca_jack_common.o	\
			sof_sdw_rt712_sdca.o sof_sdw_rt715.o	\
			sof_sdw_rt715_sdca.o sof_sdw_dmic.o	\
			sof_sdw_cs42l42.o \
			sof_sdw_hdmi.o
obj-$(CONFIG_SND_SOC_INTEL_SOF_RT5682_MACH) += snd-soc-sof_rt5682.o
obj-$(CONFIG_SND_SOC_INTEL_SOF_CS42L42_MACH) += snd-soc-sof_cs42l42.o
obj-$(CONFIG_SND_SOC_INTEL_SOF_ES8336_MACH) += snd-soc-sof_es8336.o
+11 −0
Original line number Diff line number Diff line
@@ -1119,6 +1119,17 @@ static const struct platform_device_id board_ids[] = {
					SOF_BT_OFFLOAD_SSP(2) |
					SOF_SSP_BT_OFFLOAD_PRESENT),
	},
	{
		.name = "rpl_rt1019_rt5682",
		.driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
					SOF_RT5682_SSP_CODEC(0) |
					SOF_SPEAKER_AMP_PRESENT |
					SOF_RT1019_SPEAKER_AMP_PRESENT |
					SOF_RT5682_SSP_AMP(1) |
					SOF_RT5682_NUM_HDMIDEV(4) |
					SOF_BT_OFFLOAD_SSP(2) |
					SOF_SSP_BT_OFFLOAD_PRESENT),
	},
	{
		.name = "mtl_mx98357_rt5682",
		.driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
+402 −140
Original line number Diff line number Diff line
@@ -22,11 +22,16 @@ MODULE_PARM_DESC(quirk, "Board-specific quirk override");

#define INC_ID(BE, CPU, LINK)	do { (BE)++; (CPU)++; (LINK)++; } while (0)

#define SDW_MAX_LINKS		4

/* To store SDW Pin index for each SoundWire link */
static unsigned int sdw_pin_index[SDW_MAX_LINKS];

static void log_quirks(struct device *dev)
{
	if (SOF_RT711_JDSRC(sof_sdw_quirk))
	if (SOF_JACK_JDSRC(sof_sdw_quirk))
		dev_dbg(dev, "quirk realtek,jack-detect-source %ld\n",
			SOF_RT711_JDSRC(sof_sdw_quirk));
			SOF_JACK_JDSRC(sof_sdw_quirk));
	if (sof_sdw_quirk & SOF_SDW_FOUR_SPK)
		dev_dbg(dev, "quirk SOF_SDW_FOUR_SPK enabled\n");
	if (sof_sdw_quirk & SOF_SDW_TGL_HDMI)
@@ -371,6 +376,15 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = {
					RT711_JD2 |
					SOF_SDW_FOUR_SPK),
	},
	{
		.callback = sof_sdw_quirk_cb,
		.matches = {
			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
			DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0B34"),
		},
		/* No Jack */
		.driver_data = (void *)SOF_SDW_TGL_HDMI,
	},
	{
		.callback = sof_sdw_quirk_cb,
		.matches = {
@@ -381,6 +395,16 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = {
					RT711_JD2),
	},
	/* RaptorLake devices */
	{
		.callback = sof_sdw_quirk_cb,
		.matches = {
			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
			DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0BDA")
		},
		.driver_data = (void *)(SOF_SDW_TGL_HDMI |
					RT711_JD2 |
					SOF_SDW_FOUR_SPK),
	},
	{
		.callback = sof_sdw_quirk_cb,
		.matches = {
@@ -437,6 +461,14 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = {
		},
		.driver_data = (void *)(RT711_JD2_100K),
	},
	{
		.callback = sof_sdw_quirk_cb,
		.matches = {
			DMI_MATCH(DMI_SYS_VENDOR, "Google"),
			DMI_MATCH(DMI_PRODUCT_NAME, "Rex"),
		},
		.driver_data = (void *)(SOF_SDW_PCH_DMIC),
	},
	/* LunarLake devices */
	{
		.callback = sof_sdw_quirk_cb,
@@ -563,134 +595,323 @@ static const struct snd_soc_ops sdw_ops = {
static struct sof_sdw_codec_info codec_info_list[] = {
	{
		.part_id = 0x700,
		.dais = {
			{
				.direction = {true, true},
				.dai_name = "rt700-aif1",
				.dai_type = SOF_SDW_DAI_TYPE_JACK,
				.dailink = {SDW_JACK_OUT_DAI_ID, SDW_JACK_IN_DAI_ID},
				.init = sof_sdw_rt700_init,
		.codec_type = SOF_SDW_CODEC_TYPE_JACK,
			},
		},
		.dai_num = 1,
	},
	{
		.part_id = 0x711,
		.version_id = 3,
		.dais = {
			{
				.direction = {true, true},
				.dai_name = "rt711-sdca-aif1",
		.init = sof_sdw_rt711_sdca_init,
		.exit = sof_sdw_rt711_sdca_exit,
		.codec_type = SOF_SDW_CODEC_TYPE_JACK,
				.dai_type = SOF_SDW_DAI_TYPE_JACK,
				.dailink = {SDW_JACK_OUT_DAI_ID, SDW_JACK_IN_DAI_ID},
				.init = sof_sdw_rt_sdca_jack_init,
				.exit = sof_sdw_rt_sdca_jack_exit,
			},
		},
		.dai_num = 1,
	},
	{
		.part_id = 0x711,
		.version_id = 2,
		.dais = {
			{
				.direction = {true, true},
				.dai_name = "rt711-aif1",
				.dai_type = SOF_SDW_DAI_TYPE_JACK,
				.dailink = {SDW_JACK_OUT_DAI_ID, SDW_JACK_IN_DAI_ID},
				.init = sof_sdw_rt711_init,
				.exit = sof_sdw_rt711_exit,
		.codec_type = SOF_SDW_CODEC_TYPE_JACK,
			},
		},
		.dai_num = 1,
	},
	{
		.part_id = 0x712,
		.version_id = 3,
		.dais =	{
			{
				.direction = {true, true},
				.dai_name = "rt712-sdca-aif1",
				.dai_type = SOF_SDW_DAI_TYPE_JACK,
				.dailink = {SDW_JACK_OUT_DAI_ID, SDW_JACK_IN_DAI_ID},
				.init = sof_sdw_rt_sdca_jack_init,
				.exit = sof_sdw_rt_sdca_jack_exit,
			},
			{
				.direction = {true, false},
				.dai_name = "rt712-sdca-aif2",
				.dai_type = SOF_SDW_DAI_TYPE_AMP,
				.dailink = {SDW_AMP_OUT_DAI_ID, SDW_UNUSED_DAI_ID},
				.init = sof_sdw_rt712_spk_init,
			},
		},
		.dai_num = 2,
	},
	{
		.part_id = 0x1712,
		.version_id = 3,
		.dais =	{
			{
				.direction = {false, true},
				.dai_name = "rt712-sdca-dmic-aif1",
				.dai_type = SOF_SDW_DAI_TYPE_MIC,
				.dailink = {SDW_UNUSED_DAI_ID, SDW_DMIC_DAI_ID},
				.init = sof_sdw_rt712_sdca_dmic_init,
			},
		},
		.dai_num = 1,
	},
	{
		.part_id = 0x713,
		.version_id = 3,
		.dais =	{
			{
				.direction = {true, true},
				.dai_name = "rt712-sdca-aif1",
				.dai_type = SOF_SDW_DAI_TYPE_JACK,
				.dailink = {SDW_JACK_OUT_DAI_ID, SDW_JACK_IN_DAI_ID},
				.init = sof_sdw_rt_sdca_jack_init,
				.exit = sof_sdw_rt_sdca_jack_exit,
			},
		},
		.dai_num = 1,
	},
	{
		.part_id = 0x1713,
		.version_id = 3,
		.dais =	{
			{
				.direction = {false, true},
				.dai_name = "rt712-sdca-dmic-aif1",
				.dai_type = SOF_SDW_DAI_TYPE_MIC,
				.dailink = {SDW_UNUSED_DAI_ID, SDW_DMIC_DAI_ID},
				.init = sof_sdw_rt712_sdca_dmic_init,
			},
		},
		.dai_num = 1,
	},
	{
		.part_id = 0x1308,
		.acpi_id = "10EC1308",
		.dais = {
			{
				.direction = {true, false},
				.dai_name = "rt1308-aif",
		.ops = &sof_sdw_rt1308_i2s_ops,
				.dai_type = SOF_SDW_DAI_TYPE_AMP,
				.dailink = {SDW_AMP_OUT_DAI_ID, SDW_UNUSED_DAI_ID},
				.init = sof_sdw_rt_amp_init,
				.exit = sof_sdw_rt_amp_exit,
		.codec_type = SOF_SDW_CODEC_TYPE_AMP,
			},
		},
		.dai_num = 1,
		.ops = &sof_sdw_rt1308_i2s_ops,
	},
	{
		.part_id = 0x1316,
		.dais = {
			{
				.direction = {true, true},
				.dai_name = "rt1316-aif",
				.dai_type = SOF_SDW_DAI_TYPE_AMP,
				.dailink = {SDW_AMP_OUT_DAI_ID, SDW_AMP_IN_DAI_ID},
				.init = sof_sdw_rt_amp_init,
				.exit = sof_sdw_rt_amp_exit,
		.codec_type = SOF_SDW_CODEC_TYPE_AMP,
			},
		},
		.dai_num = 1,
	},
	{
		.part_id = 0x1318,
		.dais = {
			{
				.direction = {true, true},
				.dai_name = "rt1318-aif",
				.dai_type = SOF_SDW_DAI_TYPE_AMP,
				.dailink = {SDW_AMP_OUT_DAI_ID, SDW_AMP_IN_DAI_ID},
				.init = sof_sdw_rt_amp_init,
		.codec_type = SOF_SDW_CODEC_TYPE_AMP,
				.exit = sof_sdw_rt_amp_exit,
			},
		},
		.dai_num = 1,
	},
	{
		.part_id = 0x714,
		.version_id = 3,
		.direction = {false, true},
		.ignore_pch_dmic = true,
		.dais = {
			{
				.direction = {false, true},
				.dai_name = "rt715-aif2",
				.dai_type = SOF_SDW_DAI_TYPE_MIC,
				.dailink = {SDW_UNUSED_DAI_ID, SDW_DMIC_DAI_ID},
				.init = sof_sdw_rt715_sdca_init,
		.codec_type = SOF_SDW_CODEC_TYPE_MIC,
			},
		},
		.dai_num = 1,
	},
	{
		.part_id = 0x715,
		.version_id = 3,
		.direction = {false, true},
		.ignore_pch_dmic = true,
		.dais = {
			{
				.direction = {false, true},
				.dai_name = "rt715-aif2",
				.dai_type = SOF_SDW_DAI_TYPE_MIC,
				.dailink = {SDW_UNUSED_DAI_ID, SDW_DMIC_DAI_ID},
				.init = sof_sdw_rt715_sdca_init,
		.codec_type = SOF_SDW_CODEC_TYPE_MIC,
			},
		},
		.dai_num = 1,
	},
	{
		.part_id = 0x714,
		.version_id = 2,
		.direction = {false, true},
		.ignore_pch_dmic = true,
		.dais = {
			{
				.direction = {false, true},
				.dai_name = "rt715-aif2",
				.dai_type = SOF_SDW_DAI_TYPE_MIC,
				.dailink = {SDW_UNUSED_DAI_ID, SDW_DMIC_DAI_ID},
				.init = sof_sdw_rt715_init,
		.codec_type = SOF_SDW_CODEC_TYPE_MIC,
			},
		},
		.dai_num = 1,
	},
	{
		.part_id = 0x715,
		.version_id = 2,
		.direction = {false, true},
		.ignore_pch_dmic = true,
		.dais = {
			{
				.direction = {false, true},
				.dai_name = "rt715-aif2",
				.dai_type = SOF_SDW_DAI_TYPE_MIC,
				.dailink = {SDW_UNUSED_DAI_ID, SDW_DMIC_DAI_ID},
				.init = sof_sdw_rt715_init,
		.codec_type = SOF_SDW_CODEC_TYPE_MIC,
			},
		},
		.dai_num = 1,
	},
	{
		.part_id = 0x8373,
		.dais = {
			{
				.direction = {true, true},
				.dai_name = "max98373-aif1",
		.init = sof_sdw_mx8373_init,
		.codec_type = SOF_SDW_CODEC_TYPE_AMP,
				.dai_type = SOF_SDW_DAI_TYPE_AMP,
				.dailink = {SDW_AMP_OUT_DAI_ID, SDW_AMP_IN_DAI_ID},
				.init = sof_sdw_maxim_init,
			},
		},
		.dai_num = 1,
	},
	{
		.part_id = 0x8363,
		.dais = {
			{
				.direction = {true, false},
				.dai_name = "max98363-aif1",
				.dai_type = SOF_SDW_DAI_TYPE_AMP,
				.dailink = {SDW_AMP_OUT_DAI_ID, SDW_UNUSED_DAI_ID},
				.init = sof_sdw_maxim_init,
			},
		},
		.dai_num = 1,
	},
	{
		.part_id = 0x5682,
		.dais = {
			{
				.direction = {true, true},
				.dai_name = "rt5682-sdw",
				.dai_type = SOF_SDW_DAI_TYPE_JACK,
				.dailink = {SDW_JACK_OUT_DAI_ID, SDW_JACK_IN_DAI_ID},
				.init = sof_sdw_rt5682_init,
		.codec_type = SOF_SDW_CODEC_TYPE_JACK,
			},
		},
		.dai_num = 1,
	},
	{
		.part_id = 0x4242,
		.dais = {
			{
				.direction = {true, true},
				.dai_name = "cs42l42-sdw",
				.dai_type = SOF_SDW_DAI_TYPE_JACK,
				.dailink = {SDW_JACK_OUT_DAI_ID, SDW_JACK_IN_DAI_ID},
				.init = sof_sdw_cs42l42_init,
			},
		},
		.dai_num = 1,
	},
	{
		.part_id = 0xaaaa, /* generic codec mockup */
		.version_id = 0,
		.dais = {
			{
				.direction = {true, true},
				.dai_name = "sdw-mockup-aif1",
				.dai_type = SOF_SDW_DAI_TYPE_JACK,
				.dailink = {SDW_JACK_OUT_DAI_ID, SDW_JACK_IN_DAI_ID},
				.init = NULL,
		.codec_type = SOF_SDW_CODEC_TYPE_JACK,
			},
		},
		.dai_num = 1,
	},
	{
		.part_id = 0xaa55, /* headset codec mockup */
		.version_id = 0,
		.dais = {
			{
				.direction = {true, true},
				.dai_name = "sdw-mockup-aif1",
				.dai_type = SOF_SDW_DAI_TYPE_JACK,
				.dailink = {SDW_JACK_OUT_DAI_ID, SDW_JACK_IN_DAI_ID},
				.init = NULL,
		.codec_type = SOF_SDW_CODEC_TYPE_JACK,
			},
		},
		.dai_num = 1,
	},
	{
		.part_id = 0x55aa, /* amplifier mockup */
		.version_id = 0,
		.dais = {
			{
				.direction = {true, false},
				.dai_name = "sdw-mockup-aif1",
				.dai_type = SOF_SDW_DAI_TYPE_AMP,
				.dailink = {SDW_AMP_OUT_DAI_ID, SDW_UNUSED_DAI_ID},
				.init = NULL,
		.codec_type = SOF_SDW_CODEC_TYPE_AMP,
			},
		},
		.dai_num = 1,
	},
	{
		.part_id = 0x5555,
		.version_id = 0,
		.direction = {false, true},
		.dais = {
			{
				.dai_name = "sdw-mockup-aif1",
		.codec_type = SOF_SDW_CODEC_TYPE_MIC,
				.direction = {false, true},
				.dai_type = SOF_SDW_DAI_TYPE_MIC,
				.dailink = {SDW_UNUSED_DAI_ID, SDW_DMIC_DAI_ID},
				.init = NULL,
			},
		},
		.dai_num = 1,
	},
};

@@ -742,10 +963,10 @@ static int get_sdw_dailink_info(struct device *dev, const struct snd_soc_acpi_li
				int *sdw_be_num, int *sdw_cpu_dai_num)
{
	const struct snd_soc_acpi_link_adr *link;
	int _codec_type = SOF_SDW_CODEC_TYPE_JACK;
	bool group_visited[SDW_MAX_GROUPS];
	bool no_aggregation;
	int i;
	int j;

	no_aggregation = sof_sdw_quirk & SOF_SDW_NO_AGGREGATION;
	*sdw_cpu_dai_num = 0;
@@ -759,6 +980,7 @@ static int get_sdw_dailink_info(struct device *dev, const struct snd_soc_acpi_li

	for (link = links; link->num_adr; link++) {
		const struct snd_soc_acpi_endpoint *endpoint;
		struct sof_sdw_codec_info *codec_info;
		int codec_index;
		int stream;
		u64 adr;
@@ -768,18 +990,14 @@ static int get_sdw_dailink_info(struct device *dev, const struct snd_soc_acpi_li
			codec_index = find_codec_info_part(adr);
			if (codec_index < 0)
				return codec_index;

			if (codec_info_list[codec_index].codec_type < _codec_type)
				dev_warn(dev,
					 "Unexpected address table ordering. Expected order: jack -> amp -> mic\n");

			_codec_type = codec_info_list[codec_index].codec_type;
			codec_info = &codec_info_list[codec_index];

			endpoint = link->adr_d[i].endpoints;

			for (j = 0; j < codec_info->dai_num; j++) {
				/* count DAI number for playback and capture */
				for_each_pcm_streams(stream) {
				if (!codec_info_list[codec_index].direction[stream])
					if (!codec_info->dais[j].direction[stream])
						continue;

					(*sdw_cpu_dai_num)++;
@@ -789,6 +1007,7 @@ static int get_sdw_dailink_info(struct device *dev, const struct snd_soc_acpi_li
					    !group_visited[endpoint->group_id])
						(*sdw_be_num)++;
				}
			}

			if (endpoint->aggregated)
				group_visited[endpoint->group_id] = true;
@@ -863,7 +1082,8 @@ static int create_codec_dai_name(struct device *dev,
				 struct snd_soc_codec_conf *codec_conf,
				 int codec_count,
				 int *codec_conf_index,
				 int adr_index)
				 int adr_index,
				 int dai_index)
{
	int _codec_index = -1;
	int i;
@@ -919,7 +1139,7 @@ static int create_codec_dai_name(struct device *dev,
		_codec_index = codec_index;

		codec[comp_index].dai_name =
			codec_info_list[codec_index].dai_name;
			codec_info_list[codec_index].dais[dai_index].dai_name;

		codec_conf[*codec_conf_index].dlc = codec[comp_index];
		codec_conf[*codec_conf_index].name_prefix = link->adr_d[i].name_prefix;
@@ -933,7 +1153,7 @@ static int create_codec_dai_name(struct device *dev,
static int set_codec_init_func(struct snd_soc_card *card,
			       const struct snd_soc_acpi_link_adr *link,
			       struct snd_soc_dai_link *dai_links,
			       bool playback, int group_id, int adr_index)
			       bool playback, int group_id, int adr_index, int dai_index)
{
	int i = adr_index;

@@ -953,11 +1173,13 @@ static int set_codec_init_func(struct snd_soc_card *card,

			if (codec_index < 0)
				return codec_index;

			/* The group_id is > 0 iff the codec is aggregated */
			if (link->adr_d[i].endpoints->group_id != group_id)
				continue;
			if (codec_info_list[codec_index].init)
				codec_info_list[codec_index].init(card,

			if (codec_info_list[codec_index].dais[dai_index].init)
				codec_info_list[codec_index].dais[dai_index].init(card,
						link,
						dai_links,
						&codec_info_list[codec_index],
@@ -1072,19 +1294,21 @@ static int create_sdw_dailink(struct snd_soc_card *card,
			      int codec_count, int *link_id,
			      int *codec_conf_index,
			      bool *ignore_pch_dmic,
			      bool append_codec_type,
			      int adr_index)
			      bool append_dai_type,
			      int adr_index,
			      int dai_index)
{
	const struct snd_soc_acpi_link_adr *link_next;
	struct snd_soc_dai_link_component *codecs;
	struct sof_sdw_codec_info *codec_info;
	int cpu_dai_id[SDW_MAX_CPU_DAIS];
	int cpu_dai_num, cpu_dai_index;
	unsigned int group_id;
	int codec_idx = 0;
	int i = 0, j = 0;
	int codec_index;
	int codec_num;
	int stream;
	int i = 0;
	int ret;
	int k;

@@ -1112,7 +1336,8 @@ static int create_sdw_dailink(struct snd_soc_card *card,
			continue;

		ret = create_codec_dai_name(dev, link_next, codecs, codec_idx,
					    codec_conf, codec_count, codec_conf_index, adr_index);
					    codec_conf, codec_count, codec_conf_index,
					    adr_index, dai_index);
		if (ret < 0)
			return ret;

@@ -1125,23 +1350,11 @@ static int create_sdw_dailink(struct snd_soc_card *card,
	codec_index = find_codec_info_part(link->adr_d[adr_index].adr);
	if (codec_index < 0)
		return codec_index;
	codec_info = &codec_info_list[codec_index];

	if (codec_info_list[codec_index].ignore_pch_dmic)
	if (codec_info->ignore_pch_dmic)
		*ignore_pch_dmic = true;

	/* Shift the first amplifier's *link_id to SDW_AMP_DAI_ID */
	if (codec_info_list[codec_index].codec_type == SOF_SDW_CODEC_TYPE_AMP &&
	    *link_id < SDW_AMP_DAI_ID)
		*link_id = SDW_AMP_DAI_ID;

	/*
	 * DAI ID is fixed at SDW_DMIC_DAI_ID for MICs to
	 * keep sdw DMIC and HDMI setting static in UCM
	 */
	if (codec_info_list[codec_index].codec_type == SOF_SDW_CODEC_TYPE_MIC &&
	    *link_id < SDW_DMIC_DAI_ID)
		*link_id = SDW_DMIC_DAI_ID;

	cpu_dai_index = *cpu_id;
	for_each_pcm_streams(stream) {
		char *name, *cpu_name;
@@ -1153,14 +1366,20 @@ static int create_sdw_dailink(struct snd_soc_card *card,
			"SDW%d-Capture-%s",
		};

		if (!codec_info_list[codec_index].direction[stream])
		if (!codec_info->dais[dai_index].direction[stream])
			continue;

		*link_id = codec_info->dais[dai_index].dailink[stream];
		if (*link_id < 0) {
			dev_err(dev, "Invalid dailink id %d\n", *link_id);
			return -EINVAL;
		}

		/* create stream name according to first link id */
		if (append_codec_type) {
		if (append_dai_type) {
			name = devm_kasprintf(dev, GFP_KERNEL,
					      sdw_stream_name[stream + 2], cpu_dai_id[0],
					      type_strings[codec_info_list[codec_index].codec_type]);
					      type_strings[codec_info->dais[dai_index].dai_type]);
		} else {
			name = devm_kasprintf(dev, GFP_KERNEL,
					      sdw_stream_name[stream], cpu_dai_id[0]);
@@ -1175,7 +1394,7 @@ static int create_sdw_dailink(struct snd_soc_card *card,
		for (k = 0; k < cpu_dai_num; k++) {
			cpu_name = devm_kasprintf(dev, GFP_KERNEL,
						  "SDW%d Pin%d", cpu_dai_id[k],
						  j + SDW_INTEL_BIDIR_PDI_BASE);
						  sdw_pin_index[cpu_dai_id[k]]++);
			if (!cpu_name)
				return -ENOMEM;

@@ -1217,14 +1436,13 @@ static int create_sdw_dailink(struct snd_soc_card *card,
		dai_links[*link_index].nonatomic = true;

		ret = set_codec_init_func(card, link, dai_links + (*link_index)++,
					  playback, group_id, adr_index);
					  playback, group_id, adr_index, dai_index);
		if (ret < 0) {
			dev_err(dev, "failed to init codec %d", codec_index);
			return ret;
		}

		*cpu_id += cpu_dai_num;
		j++;
	}

	return 0;
@@ -1240,6 +1458,7 @@ static int sof_card_codec_conf_alloc(struct device *dev,
	const struct snd_soc_acpi_link_adr *adr_link;
	struct snd_soc_codec_conf *c_conf;
	int num_codecs = 0;
	int codec_index;
	int i;

	adr_link = mach_params->links;
@@ -1254,8 +1473,11 @@ static int sof_card_codec_conf_alloc(struct device *dev,
					adr_link->adr_d[i].adr);
				return -EINVAL;
			}
			codec_index = find_codec_info_part(adr_link->adr_d[i].adr);
			if (codec_index < 0)
				return codec_index;
			num_codecs += codec_info_list[codec_index].dai_num;
		}
		num_codecs += adr_link->num_adr;
	}

	c_conf = devm_kzalloc(dev, num_codecs * sizeof(*c_conf), GFP_KERNEL);
@@ -1280,7 +1502,7 @@ static int sof_card_dai_links_create(struct device *dev,
	const struct snd_soc_acpi_link_adr *adr_link;
	struct snd_soc_dai_link_component *cpus;
	struct snd_soc_codec_conf *codec_conf;
	bool append_codec_type = false;
	bool append_dai_type = false;
	bool ignore_pch_dmic = false;
	int codec_conf_count;
	int codec_conf_index = 0;
@@ -1292,6 +1514,7 @@ static int sof_card_dai_links_create(struct device *dev,
	int total_cpu_dai_num;
	int sdw_cpu_dai_num;
	int i, j, be_id = 0;
	int codec_index;
	int cpu_id = 0;
	int comp_num;
	int ret;
@@ -1372,6 +1595,9 @@ static int sof_card_dai_links_create(struct device *dev,
	for (i = 0; i < SDW_MAX_GROUPS; i++)
		group_generated[i] = false;

	for (i = 0; i < SDW_MAX_LINKS; i++)
		sdw_pin_index[i] = SDW_INTEL_BIDIR_PDI_BASE;

	for (; adr_link->num_adr; adr_link++) {
		/*
		 * If there are two or more different devices on the same sdw link, we have to
@@ -1380,12 +1606,20 @@ static int sof_card_dai_links_create(struct device *dev,
		 * snd_soc_acpi_adr_device array. They won't be described in different adr_links.
		 */
		for (i = 0; i < adr_link->num_adr; i++) {
			/* find codec info to get dai_num */
			codec_index = find_codec_info_part(adr_link->adr_d[i].adr);
			if (codec_index < 0)
				return codec_index;
			if (codec_info_list[codec_index].dai_num > 1) {
				append_dai_type = true;
				goto out;
			}
			for (j = 0; j < i; j++) {
				if ((SDW_PART_ID(adr_link->adr_d[i].adr) !=
				    SDW_PART_ID(adr_link->adr_d[j].adr)) ||
				    (SDW_MFG_ID(adr_link->adr_d[i].adr) !=
				    SDW_MFG_ID(adr_link->adr_d[i].adr))) {
					append_codec_type = true;
					append_dai_type = true;
					goto out;
				}
			}
@@ -1410,18 +1644,25 @@ static int sof_card_dai_links_create(struct device *dev,
			    group_generated[endpoint->group_id])
				continue;

			/* find codec info to get dai_num */
			codec_index = find_codec_info_part(adr_link->adr_d[i].adr);
			if (codec_index < 0)
				return codec_index;

			for (j = 0; j < codec_info_list[codec_index].dai_num ; j++) {
				ret = create_sdw_dailink(card, dev, &link_index, links, sdw_be_num,
							 sdw_cpu_dai_num, cpus, adr_link,
							 &cpu_id, group_generated,
							 codec_conf, codec_conf_count,
							 &be_id, &codec_conf_index,
						 &ignore_pch_dmic, append_codec_type, i);
							 &ignore_pch_dmic, append_dai_type, i, j);
				if (ret < 0) {
					dev_err(dev, "failed to create dai link %d", link_index);
					return ret;
				}
			}
		}
	}

SSP:
	/* SSP */
@@ -1457,18 +1698,19 @@ static int sof_card_dai_links_create(struct device *dev,
			return -ENOMEM;

		ssp_components->name = codec_name;
		ssp_components->dai_name = info->dai_name;
		/* TODO: support multi codec dai on SSP when it is needed */
		ssp_components->dai_name = info->dais[0].dai_name;
		cpus[cpu_id].dai_name = cpu_name;

		playback = info->direction[SNDRV_PCM_STREAM_PLAYBACK];
		capture = info->direction[SNDRV_PCM_STREAM_CAPTURE];
		playback = info->dais[0].direction[SNDRV_PCM_STREAM_PLAYBACK];
		capture = info->dais[0].direction[SNDRV_PCM_STREAM_CAPTURE];
		init_dai_link(dev, links + link_index, be_id, name,
			      playback, capture,
			      cpus + cpu_id, 1,
			      ssp_components, 1,
			      NULL, info->ops);

		ret = info->init(card, NULL, links + link_index, info, 0);
		ret = info->dais[0].init(card, NULL, links + link_index, info, 0);
		if (ret < 0)
			return ret;

@@ -1598,6 +1840,24 @@ static struct snd_soc_card card_sof_sdw = {
	.late_probe = sof_sdw_card_late_probe,
};

/* helper to get the link that the codec DAI is used */
static struct snd_soc_dai_link *mc_find_codec_dai_used(struct snd_soc_card *card,
						       const char *dai_name)
{
	struct snd_soc_dai_link *link;
	int i;
	int j;

	for_each_card_prelinks(card, i, link) {
		for (j = 0; j < link->num_codecs; j++) {
			/* Check each codec in a link */
			if (!strcmp(link->codecs[j].dai_name, dai_name))
				return link;
		}
	}
	return NULL;
}

static void mc_dailink_exit_loop(struct snd_soc_card *card)
{
	struct snd_soc_dai_link *link;
@@ -1605,16 +1865,18 @@ static void mc_dailink_exit_loop(struct snd_soc_card *card)
	int i, j;

	for (i = 0; i < ARRAY_SIZE(codec_info_list); i++) {
		if (!codec_info_list[i].exit)
		for (j = 0; j < codec_info_list[i].dai_num; j++) {
			/* Check each dai in codec_info_lis to see if it is used in the link */
			if (!codec_info_list[i].dais[j].exit)
				continue;
			/*
			 * We don't need to call .exit function if there is no matched
			 * dai link found.
			 */
		for_each_card_prelinks(card, j, link) {
			if (!strcmp(link->codecs[0].dai_name,
				    codec_info_list[i].dai_name)) {
				ret = codec_info_list[i].exit(card, link);
			link = mc_find_codec_dai_used(card, codec_info_list[i].dais[j].dai_name);
			if (link) {
				/* Do the .exit function if the codec dai is used in the link */
				ret = codec_info_list[i].dais[j].exit(card, link);
				if (ret)
					dev_warn(card->dev,
						 "codec exit failed %d\n",
+61 −23

File changed.

Preview size limit exceeded, changes collapsed.

Loading