Unverified Commit bbd59df0 authored by Mark Brown's avatar Mark Brown
Browse files

Merge series "ASoC: Intel: sdw machine driver updates for 5.10" from Kai...

Merge series "ASoC: Intel: sdw machine driver updates for 5.10" from Kai Vehmanen <kai.vehmanen@linux.intel.com>:

Series including fixes and improvements for Intel SoundWire
machine drivers.

Bard Liao (1):
  ASoC: Intel: add support for new SoundWire hardware layout on TGL

Pierre-Louis Bossart (4):
  ASoC: Intel: sof_sdw: remove ternary operator
  ASoC: Intel: add codec name prefix to ACPI machine description
  ASoC: Intel: sof_sdw: remove hard-coded codec_conf table
  ASoC: Intel: sof_sdw_rt700: add codec prefix

Rander Wang (1):
  ASOC: Intel: sof_sdw: restore playback functionality with max98373
    amps

 include/sound/soc-acpi.h                      |   2 +
 sound/soc/intel/boards/sof_sdw.c              | 170 +++++++++---------
 sound/soc/intel/boards/sof_sdw_common.h       |   3 +
 sound/soc/intel/boards/sof_sdw_max98373.c     |  36 +++-
 sound/soc/intel/boards/sof_sdw_rt700.c        |   6 +-
 .../intel/common/soc-acpi-intel-cml-match.c   |  10 ++
 .../intel/common/soc-acpi-intel-cnl-match.c   |   1 +
 .../intel/common/soc-acpi-intel-icl-match.c   |   6 +
 .../intel/common/soc-acpi-intel-tgl-match.c   |  67 +++++++
 9 files changed, 216 insertions(+), 85 deletions(-)

--
2.27.0
parents 3121420c 7cc3b56f
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -93,11 +93,13 @@ struct snd_soc_acpi_endpoint {
 * @adr: 64 bit ACPI _ADR value
 * @num_endpoints: number of endpoints for this device
 * @endpoints: array of endpoints
 * @name_prefix: string used for codec controls
 */
struct snd_soc_acpi_adr_device {
	const u64 adr;
	const u8 num_endpoints;
	const struct snd_soc_acpi_endpoint *endpoints;
	const char *name_prefix;
};

/**
+89 −81
Original line number Diff line number Diff line
@@ -48,6 +48,15 @@ static int sof_sdw_quirk_cb(const struct dmi_system_id *id)
}

static const struct dmi_system_id sof_sdw_quirk_table[] = {
	{
		.callback = sof_sdw_quirk_cb,
		.matches = {
			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
			DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0A3E")
		},
		.driver_data = (void *)(SOF_RT711_JD_SRC_JD2 |
					SOF_RT715_DAI_ID_FIX),
	},
	{
		.callback = sof_sdw_quirk_cb,
		.matches = {
@@ -136,75 +145,6 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = {
	{}
};

static struct snd_soc_codec_conf codec_conf[] = {
	{
		.dlc = COMP_CODEC_CONF("sdw:0:25d:711:0"),
		.name_prefix = "rt711",
	},
	{
		.dlc = COMP_CODEC_CONF("sdw:0:25d:711:1"),
		.name_prefix = "rt711",
	},
	/* rt1308 w/ I2S connection */
	{
		.dlc = COMP_CODEC_CONF("i2c-10EC1308:00"),
		.name_prefix = "rt1308-1",
	},
	/* rt1308 left on link 1 */
	{
		.dlc = COMP_CODEC_CONF("sdw:1:25d:1308:0"),
		.name_prefix = "rt1308-1",
	},
	/* two 1308s on link1 with different unique id */
	{
		.dlc = COMP_CODEC_CONF("sdw:1:25d:1308:0:0"),
		.name_prefix = "rt1308-1",
	},
	{
		.dlc = COMP_CODEC_CONF("sdw:1:25d:1308:0:2"),
		.name_prefix = "rt1308-2",
	},
	/* rt1308 right on link 2 */
	{
		.dlc = COMP_CODEC_CONF("sdw:2:25d:1308:0"),
		.name_prefix = "rt1308-2",
	},
	{
		.dlc = COMP_CODEC_CONF("sdw:3:25d:715:0"),
		.name_prefix = "rt715",
	},
	/* two MAX98373s on link1 with different unique id */
	{
		.dlc = COMP_CODEC_CONF("sdw:1:19f:8373:0:3"),
		.name_prefix = "Right",
	},
	{
		.dlc = COMP_CODEC_CONF("sdw:1:19f:8373:0:7"),
		.name_prefix = "Left",
	},
	{
		.dlc = COMP_CODEC_CONF("sdw:0:25d:5682:0"),
		.name_prefix = "rt5682",
	},
	/* rt5682 on link2 */
	{
		.dlc = COMP_CODEC_CONF("sdw:2:25d:5682:0"),
		.name_prefix = "rt5682",
	},
	{
		.dlc = COMP_CODEC_CONF("sdw:1:25d:1316:1"),
		.name_prefix = "rt1316-1",
	},
	{
		.dlc = COMP_CODEC_CONF("sdw:2:25d:1316:1"),
		.name_prefix = "rt1316-2",
	},
	{
		.dlc = COMP_CODEC_CONF("sdw:3:25d:714:1"),
		.name_prefix = "rt714",
	},
};

static struct snd_soc_dai_link_component dmic_component[] = {
	{
		.name = "dmic-codec",
@@ -225,7 +165,7 @@ int sdw_startup(struct snd_pcm_substream *substream)
	return sdw_startup_stream(substream);
}

static int sdw_prepare(struct snd_pcm_substream *substream)
int sdw_prepare(struct snd_pcm_substream *substream)
{
	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
	struct sdw_stream_runtime *sdw_stream;
@@ -244,7 +184,7 @@ static int sdw_prepare(struct snd_pcm_substream *substream)
	return sdw_prepare_stream(sdw_stream);
}

static int sdw_trigger(struct snd_pcm_substream *substream, int cmd)
int sdw_trigger(struct snd_pcm_substream *substream, int cmd)
{
	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
	struct sdw_stream_runtime *sdw_stream;
@@ -284,7 +224,7 @@ static int sdw_trigger(struct snd_pcm_substream *substream, int cmd)
	return ret;
}

static int sdw_hw_free(struct snd_pcm_substream *substream)
int sdw_hw_free(struct snd_pcm_substream *substream)
{
	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
	struct sdw_stream_runtime *sdw_stream;
@@ -538,10 +478,19 @@ static bool is_unique_device(const struct snd_soc_acpi_link_adr *link,
static int create_codec_dai_name(struct device *dev,
				 const struct snd_soc_acpi_link_adr *link,
				 struct snd_soc_dai_link_component *codec,
				 int offset)
				 int offset,
				 struct snd_soc_codec_conf *codec_conf,
				 int codec_count,
				 int *codec_conf_index)
{
	int i;

	/* sanity check */
	if (*codec_conf_index + link->num_adr > codec_count) {
		dev_err(dev, "codec_conf: out-of-bounds access requested\n");
		return -EINVAL;
	}

	for (i = 0; i < link->num_adr; i++) {
		unsigned int sdw_version, unique_id, mfg_id;
		unsigned int link_id, part_id, class_id;
@@ -583,6 +532,11 @@ static int create_codec_dai_name(struct device *dev,

		codec[comp_index].dai_name =
			codec_info_list[codec_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;

		++*codec_conf_index;
	}

	return 0;
@@ -701,7 +655,10 @@ static int create_sdw_dailink(struct device *dev, int *be_index,
			      int sdw_be_num, int sdw_cpu_dai_num,
			      struct snd_soc_dai_link_component *cpus,
			      const struct snd_soc_acpi_link_adr *link,
			      int *cpu_id, bool *group_generated)
			      int *cpu_id, bool *group_generated,
			      struct snd_soc_codec_conf *codec_conf,
			      int codec_count,
			      int *codec_conf_index)
{
	const struct snd_soc_acpi_link_adr *link_next;
	struct snd_soc_dai_link_component *codecs;
@@ -739,7 +696,8 @@ static int create_sdw_dailink(struct device *dev, int *be_index,
		if (cpu_dai_id[i] != ffs(link_next->mask) - 1)
			continue;

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

@@ -836,6 +794,42 @@ static inline int get_next_be_id(struct snd_soc_dai_link *links,

#define IDISP_CODEC_MASK	0x4

static int sof_card_codec_conf_alloc(struct device *dev,
				     struct snd_soc_acpi_mach_params *mach_params,
				     struct snd_soc_codec_conf **codec_conf,
				     int *codec_conf_count)
{
	const struct snd_soc_acpi_link_adr *adr_link;
	struct snd_soc_codec_conf *c_conf;
	int num_codecs = 0;
	int i;

	adr_link = mach_params->links;
	if (!adr_link)
		return -EINVAL;

	/* generate DAI links by each sdw link */
	for (; adr_link->num_adr; adr_link++) {
		for (i = 0; i < adr_link->num_adr; i++) {
			if (!adr_link->adr_d[i].name_prefix) {
				dev_err(dev, "codec 0x%llx does not have a name prefix\n",
					adr_link->adr_d[i].adr);
				return -EINVAL;
			}
		}
		num_codecs += adr_link->num_adr;
	}

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

	*codec_conf = c_conf;
	*codec_conf_count = num_codecs;

	return 0;
}

static int sof_card_dai_links_create(struct device *dev,
				     struct snd_soc_acpi_mach *mach,
				     struct snd_soc_card *card)
@@ -847,6 +841,9 @@ static int sof_card_dai_links_create(struct device *dev,
	struct snd_soc_acpi_mach_params *mach_params;
	const struct snd_soc_acpi_link_adr *adr_link;
	struct snd_soc_dai_link_component *cpus;
	struct snd_soc_codec_conf *codec_conf;
	int codec_conf_count;
	int codec_conf_index = 0;
	bool group_generated[SDW_MAX_GROUPS];
	int ssp_codec_index, ssp_mask;
	struct snd_soc_dai_link *links;
@@ -859,12 +856,21 @@ static int sof_card_dai_links_create(struct device *dev,
	int comp_num;
	int ret;

	mach_params = &mach->mach_params;

	/* allocate codec conf, will be populated when dailinks are created */
	ret = sof_card_codec_conf_alloc(dev, mach_params, &codec_conf, &codec_conf_count);
	if (ret < 0)
		return ret;

	/* reset amp_num to ensure amp_num++ starts from 0 in each probe */
	for (i = 0; i < ARRAY_SIZE(codec_info_list); i++)
		codec_info_list[i].amp_num = 0;

	hdmi_num = sof_sdw_quirk & SOF_SDW_TGL_HDMI ?
				SOF_TGL_HDMI_COUNT : SOF_PRE_TGL_HDMI_COUNT;
	if (sof_sdw_quirk & SOF_SDW_TGL_HDMI)
		hdmi_num = SOF_TGL_HDMI_COUNT;
	else
		hdmi_num = SOF_PRE_TGL_HDMI_COUNT;

	ssp_mask = SOF_SSP_GET_PORT(sof_sdw_quirk);
	/*
@@ -877,7 +883,6 @@ static int sof_card_dai_links_create(struct device *dev,
	ssp_num = ssp_codec_index >= 0 ? hweight_long(ssp_mask) : 0;
	comp_num = hdmi_num + ssp_num;

	mach_params = &mach->mach_params;
	ret = get_sdw_dailink_info(mach_params->links,
				   &sdw_be_num, &sdw_cpu_dai_num);
	if (ret < 0) {
@@ -941,7 +946,9 @@ static int sof_card_dai_links_create(struct device *dev,

		ret = create_sdw_dailink(dev, &be_id, links, sdw_be_num,
					 sdw_cpu_dai_num, cpus, adr_link,
					 &cpu_id, group_generated);
					 &cpu_id, group_generated,
					 codec_conf, codec_conf_count,
					 &codec_conf_index);
		if (ret < 0) {
			dev_err(dev, "failed to create dai link %d", be_id);
			return -ENOMEM;
@@ -1072,6 +1079,9 @@ DMIC:
	card->dai_link = links;
	card->num_links = num_links;

	card->codec_conf = codec_conf;
	card->num_configs = codec_conf_count;

	return 0;
}

@@ -1098,8 +1108,6 @@ static struct snd_soc_card card_sof_sdw = {
	.name = "soundwire",
	.owner = THIS_MODULE,
	.late_probe = sof_sdw_card_late_probe,
	.codec_conf = codec_conf,
	.num_configs = ARRAY_SIZE(codec_conf),
};

static int mc_probe(struct platform_device *pdev)
+3 −0
Original line number Diff line number Diff line
@@ -79,6 +79,9 @@ struct mc_private {
extern unsigned long sof_sdw_quirk;

int sdw_startup(struct snd_pcm_substream *substream);
int sdw_prepare(struct snd_pcm_substream *substream);
int sdw_trigger(struct snd_pcm_substream *substream, int cmd);
int sdw_hw_free(struct snd_pcm_substream *substream);
void sdw_shutdown(struct snd_pcm_substream *substream);

/* generic HDMI support */
+35 −1
Original line number Diff line number Diff line
@@ -55,9 +55,43 @@ static int spk_init(struct snd_soc_pcm_runtime *rtd)
	return ret;
}

static int max98373_sdw_trigger(struct snd_pcm_substream *substream, int cmd)
{
	int ret;

	switch (cmd) {
	case SNDRV_PCM_TRIGGER_START:
	case SNDRV_PCM_TRIGGER_RESUME:
	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
		/* enable max98373 first */
		ret = max98373_trigger(substream, cmd);
		if (ret < 0)
			break;

		ret = sdw_trigger(substream, cmd);
		break;
	case SNDRV_PCM_TRIGGER_STOP:
	case SNDRV_PCM_TRIGGER_SUSPEND:
	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
		ret = sdw_trigger(substream, cmd);
		if (ret < 0)
			break;

		ret = max98373_trigger(substream, cmd);
		break;
	default:
		ret = -EINVAL;
		break;
	}

	return ret;
}

static const struct snd_soc_ops max_98373_sdw_ops = {
	.startup = sdw_startup,
	.trigger = max98373_trigger,
	.prepare = sdw_prepare,
	.trigger = max98373_sdw_trigger,
	.hw_free = sdw_hw_free,
	.shutdown = sdw_shutdown,
};

+3 −3
Original line number Diff line number Diff line
@@ -23,9 +23,9 @@ static const struct snd_soc_dapm_widget rt700_widgets[] = {

static const struct snd_soc_dapm_route rt700_map[] = {
	/* Headphones */
	{ "Headphones", NULL, "HP" },
	{ "Speaker", NULL, "SPK" },
	{ "MIC2", NULL, "AMIC" },
	{ "Headphones", NULL, "rt700 HP" },
	{ "Speaker", NULL, "rt700 SPK" },
	{ "rt700 MIC2", NULL, "AMIC" },
};

static const struct snd_kcontrol_new rt700_controls[] = {
Loading