Unverified Commit ad83b1ad authored by Brent Lu's avatar Brent Lu Committed by Mark Brown
Browse files

ASoC: Intel: sof_rt5682: Add ALC1015Q-VB speaker amp support



This patch adds jsl_rt5682_rt1015p which supports the RT5682 headset
codec and ALC1015Q-VB speaker amplifier combination on JasperLake
platform.

This driver also supports ALC1015Q-CG if running in auto-mode.
Following table shows the audio interface support of the two
amplifiers.

          | ALC1015Q-CG | ALC1015Q-VB
=====================================
I2C       | Yes         | No
Auto-mode | 48K, 64fs   | 16k, 32fs
                        | 48k, 32fs
                        | 48k, 64fs

Signed-off-by: default avatarBrent Lu <brent.lu@intel.com>
Acked-by: default avatarPierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Link: https://lore.kernel.org/r/20210317110824.20814-1-brent.lu@intel.com


Signed-off-by: default avatarMark Brown <broonie@kernel.org>
parent 7ec79d38
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -457,6 +457,7 @@ config SND_SOC_INTEL_SOF_RT5682_MACH
	select SND_SOC_MAX98373_I2C
	select SND_SOC_RT1011
	select SND_SOC_RT1015
	select SND_SOC_RT1015P
	select SND_SOC_RT5682_I2C
	select SND_SOC_DMIC
	select SND_SOC_HDAC_HDMI
+105 −0
Original line number Diff line number Diff line
@@ -7,6 +7,7 @@
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
#include <sound/soc-acpi.h>
#include <sound/soc-dai.h>
#include <sound/soc-dapm.h>
#include <uapi/sound/asound.h>
@@ -136,3 +137,107 @@ void sof_rt1011_codec_conf(struct snd_soc_card *card)
	card->codec_conf = rt1011_codec_confs;
	card->num_configs = ARRAY_SIZE(rt1011_codec_confs);
}

/*
 * rt1015:  i2c mode driver for ALC1015 and ALC1015Q
 * rt1015p: auto-mode driver for ALC1015, ALC1015Q, and ALC1015Q-VB
 *
 * For stereo output, there are always two amplifiers on the board.
 * However, the ACPI implements only one device instance (UID=0) if they
 * are sharing the same enable pin. The code will detect the number of
 * device instance and use corresponding DAPM structures for
 * initialization.
 */
static const struct snd_soc_dapm_route rt1015p_1dev_dapm_routes[] = {
	/* speaker */
	{ "Left Spk", NULL, "Speaker" },
	{ "Right Spk", NULL, "Speaker" },
};

static const struct snd_soc_dapm_route rt1015p_2dev_dapm_routes[] = {
	/* speaker */
	{ "Left Spk", NULL, "Left Speaker" },
	{ "Right Spk", NULL, "Right Speaker" },
};

static struct snd_soc_codec_conf rt1015p_codec_confs[] = {
	{
		.dlc = COMP_CODEC_CONF(RT1015P_DEV0_NAME),
		.name_prefix = "Left",
	},
	{
		.dlc = COMP_CODEC_CONF(RT1015P_DEV1_NAME),
		.name_prefix = "Right",
	},
};

static struct snd_soc_dai_link_component rt1015p_dai_link_components[] = {
	{
		.name = RT1015P_DEV0_NAME,
		.dai_name = RT1015P_CODEC_DAI,
	},
	{
		.name = RT1015P_DEV1_NAME,
		.dai_name = RT1015P_CODEC_DAI,
	},
};

static int rt1015p_get_num_codecs(void)
{
	static int dev_num;

	if (dev_num)
		return dev_num;

	if (!acpi_dev_present("RTL1015", "1", -1))
		dev_num = 1;
	else
		dev_num = 2;

	return dev_num;
}

static int rt1015p_hw_params(struct snd_pcm_substream *substream,
			     struct snd_pcm_hw_params *params)
{
	/* reserved for debugging purpose */

	return 0;
}

static const struct snd_soc_ops rt1015p_ops = {
	.hw_params = rt1015p_hw_params,
};

static int rt1015p_init(struct snd_soc_pcm_runtime *rtd)
{
	struct snd_soc_card *card = rtd->card;
	int ret;

	if (rt1015p_get_num_codecs() == 1)
		ret = snd_soc_dapm_add_routes(&card->dapm, rt1015p_1dev_dapm_routes,
					      ARRAY_SIZE(rt1015p_1dev_dapm_routes));
	else
		ret = snd_soc_dapm_add_routes(&card->dapm, rt1015p_2dev_dapm_routes,
					      ARRAY_SIZE(rt1015p_2dev_dapm_routes));
	if (ret)
		dev_err(rtd->dev, "Speaker map addition failed: %d\n", ret);
	return ret;
}

void sof_rt1015p_dai_link(struct snd_soc_dai_link *link)
{
	link->codecs = rt1015p_dai_link_components;
	link->num_codecs = rt1015p_get_num_codecs();
	link->init = rt1015p_init;
	link->ops = &rt1015p_ops;
}

void sof_rt1015p_codec_conf(struct snd_soc_card *card)
{
	if (rt1015p_get_num_codecs() == 1)
		return;

	card->codec_conf = rt1015p_codec_confs;
	card->num_configs = ARRAY_SIZE(rt1015p_codec_confs);
}
+7 −0
Original line number Diff line number Diff line
@@ -21,4 +21,11 @@
void sof_rt1011_dai_link(struct snd_soc_dai_link *link);
void sof_rt1011_codec_conf(struct snd_soc_card *card);

#define RT1015P_CODEC_DAI	"HiFi"
#define RT1015P_DEV0_NAME	"RTL1015:00"
#define RT1015P_DEV1_NAME	"RTL1015:01"

void sof_rt1015p_dai_link(struct snd_soc_dai_link *link);
void sof_rt1015p_codec_conf(struct snd_soc_card *card);

#endif /* __SOF_REALTEK_COMMON_H */
+17 −2
Original line number Diff line number Diff line
@@ -45,8 +45,9 @@
#define SOF_RT1011_SPEAKER_AMP_PRESENT		BIT(13)
#define SOF_RT1015_SPEAKER_AMP_PRESENT		BIT(14)
#define SOF_RT1015_SPEAKER_AMP_100FS		BIT(15)
#define SOF_MAX98373_SPEAKER_AMP_PRESENT	BIT(16)
#define SOF_MAX98360A_SPEAKER_AMP_PRESENT	BIT(17)
#define SOF_RT1015P_SPEAKER_AMP_PRESENT		BIT(16)
#define SOF_MAX98373_SPEAKER_AMP_PRESENT	BIT(17)
#define SOF_MAX98360A_SPEAKER_AMP_PRESENT	BIT(18)

/* Default: MCLK on, MCLK 19.2M, SSP0  */
static unsigned long sof_rt5682_quirk = SOF_RT5682_MCLK_EN |
@@ -723,6 +724,8 @@ static struct snd_soc_dai_link *sof_card_dai_links_create(struct device *dev,
			links[id].num_codecs = ARRAY_SIZE(rt1015_components);
			links[id].init = speaker_codec_init_lr;
			links[id].ops = &sof_rt1015_ops;
		} else if (sof_rt5682_quirk & SOF_RT1015P_SPEAKER_AMP_PRESENT) {
			sof_rt1015p_dai_link(&links[id]);
		} else if (sof_rt5682_quirk &
				SOF_MAX98373_SPEAKER_AMP_PRESENT) {
			links[id].codecs = max_98373_components;
@@ -851,6 +854,8 @@ static int sof_audio_probe(struct platform_device *pdev)
		sof_max98373_codec_conf(&sof_audio_card_rt5682);
	else if (sof_rt5682_quirk & SOF_RT1011_SPEAKER_AMP_PRESENT)
		sof_rt1011_codec_conf(&sof_audio_card_rt5682);
	else if (sof_rt5682_quirk & SOF_RT1015P_SPEAKER_AMP_PRESENT)
		sof_rt1015p_codec_conf(&sof_audio_card_rt5682);

	dai_links = sof_card_dai_links_create(&pdev->dev, ssp_codec, ssp_amp,
					      dmic_be_num, hdmi_num);
@@ -940,6 +945,15 @@ static const struct platform_device_id board_ids[] = {
					SOF_RT5682_SSP_AMP(1) |
					SOF_RT5682_NUM_HDMIDEV(4)),
	},
	{
		.name = "jsl_rt5682_rt1015p",
		.driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
					SOF_RT5682_MCLK_24MHZ |
					SOF_RT5682_SSP_CODEC(0) |
					SOF_SPEAKER_AMP_PRESENT |
					SOF_RT1015P_SPEAKER_AMP_PRESENT |
					SOF_RT5682_SSP_AMP(1)),
	},
	{ }
};

@@ -966,3 +980,4 @@ MODULE_ALIAS("platform:tgl_max98373_rt5682");
MODULE_ALIAS("platform:jsl_rt5682_max98360a");
MODULE_ALIAS("platform:cml_rt1015_rt5682");
MODULE_ALIAS("platform:tgl_rt1011_rt5682");
MODULE_ALIAS("platform:jsl_rt5682_rt1015p");
+13 −0
Original line number Diff line number Diff line
@@ -19,6 +19,11 @@ static struct snd_soc_acpi_codecs rt1015_spk = {
	.codecs = {"10EC1015"}
};

static struct snd_soc_acpi_codecs rt1015p_spk = {
	.num_codecs = 1,
	.codecs = {"RTL1015"}
};

static struct snd_soc_acpi_codecs mx98360a_spk = {
	.num_codecs = 1,
	.codecs = {"MX98360A"}
@@ -52,6 +57,14 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_jsl_machines[] = {
		.quirk_data = &rt1015_spk,
		.sof_tplg_filename = "sof-jsl-rt5682-rt1015.tplg",
	},
	{
		.id = "10EC5682",
		.drv_name = "jsl_rt5682_rt1015p",
		.sof_fw_filename = "sof-jsl.ri",
		.machine_quirk = snd_soc_acpi_codec_list,
		.quirk_data = &rt1015p_spk,
		.sof_tplg_filename = "sof-jsl-rt5682-rt1015.tplg",
	},
	{
		.id = "10EC5682",
		.drv_name = "jsl_rt5682_max98360a",