Commit a79ae0f6 authored by Yong Zhi's avatar Yong Zhi Committed by Mark Brown

ASoC: Intel: sof_rt5682: Add rt1015 speaker amp support

This patch adds jsl_rt5682_rt1015 which supports the
RT5682 headset codec and RT1015 speaker amplifier combination
on JasperLake platform.
Signed-off-by: default avatarYong Zhi <yong.zhi@intel.com>
Signed-off-by: default avatarRanjani Sridharan <ranjani.sridharan@linux.intel.com>
Signed-off-by: default avatarPierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Link: https://lore.kernel.org/r/20200312194859.4051-10-pierre-louis.bossart@linux.intel.comSigned-off-by: default avatarMark Brown <broonie@kernel.org>
parent 3f32e596
...@@ -450,6 +450,7 @@ config SND_SOC_INTEL_SOF_RT5682_MACH ...@@ -450,6 +450,7 @@ config SND_SOC_INTEL_SOF_RT5682_MACH
depends on (SND_SOC_SOF_HDA_LINK && (MFD_INTEL_LPSS || COMPILE_TEST)) ||\ depends on (SND_SOC_SOF_HDA_LINK && (MFD_INTEL_LPSS || COMPILE_TEST)) ||\
(SND_SOC_SOF_BAYTRAIL && (X86_INTEL_LPSS || COMPILE_TEST)) (SND_SOC_SOF_BAYTRAIL && (X86_INTEL_LPSS || COMPILE_TEST))
depends on SND_HDA_CODEC_HDMI depends on SND_HDA_CODEC_HDMI
select SND_SOC_RT1015
select SND_SOC_RT5682 select SND_SOC_RT5682
select SND_SOC_DMIC select SND_SOC_DMIC
select SND_SOC_HDAC_HDMI select SND_SOC_HDAC_HDMI
......
// SPDX-License-Identifier: GPL-2.0 // SPDX-License-Identifier: GPL-2.0
// Copyright(c) 2019 Intel Corporation. // Copyright(c) 2019-2020 Intel Corporation.
/* /*
* Intel SOF Machine Driver with Realtek rt5682 Codec * Intel SOF Machine Driver with Realtek rt5682 Codec
* and speaker codec MAX98357A * and speaker codec MAX98357A or RT1015.
*/ */
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/input.h> #include <linux/input.h>
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include <sound/soc.h> #include <sound/soc.h>
#include <sound/rt5682.h> #include <sound/rt5682.h>
#include <sound/soc-acpi.h> #include <sound/soc-acpi.h>
#include "../../codecs/rt1015.h"
#include "../../codecs/rt5682.h" #include "../../codecs/rt5682.h"
#include "../../codecs/hdac_hdmi.h" #include "../../codecs/hdac_hdmi.h"
#include "../common/soc-intel-quirks.h" #include "../common/soc-intel-quirks.h"
...@@ -39,6 +40,7 @@ ...@@ -39,6 +40,7 @@
#define SOF_RT5682_NUM_HDMIDEV_MASK (GENMASK(12, 10)) #define SOF_RT5682_NUM_HDMIDEV_MASK (GENMASK(12, 10))
#define SOF_RT5682_NUM_HDMIDEV(quirk) \ #define SOF_RT5682_NUM_HDMIDEV(quirk) \
((quirk << SOF_RT5682_NUM_HDMIDEV_SHIFT) & SOF_RT5682_NUM_HDMIDEV_MASK) ((quirk << SOF_RT5682_NUM_HDMIDEV_SHIFT) & SOF_RT5682_NUM_HDMIDEV_MASK)
#define SOF_RT1015_SPEAKER_AMP_PRESENT BIT(13)
/* Default: MCLK on, MCLK 19.2M, SSP0 */ /* Default: MCLK on, MCLK 19.2M, SSP0 */
static unsigned long sof_rt5682_quirk = SOF_RT5682_MCLK_EN | static unsigned long sof_rt5682_quirk = SOF_RT5682_MCLK_EN |
...@@ -260,6 +262,42 @@ static struct snd_soc_ops sof_rt5682_ops = { ...@@ -260,6 +262,42 @@ static struct snd_soc_ops sof_rt5682_ops = {
.hw_params = sof_rt5682_hw_params, .hw_params = sof_rt5682_hw_params,
}; };
static int sof_rt1015_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_card *card = rtd->card;
struct snd_soc_dai *codec_dai;
int i, ret;
if (!snd_soc_card_get_codec_dai(card, "rt1015-aif"))
return 0;
for_each_rtd_codec_dais(rtd, i, codec_dai) {
ret = snd_soc_dai_set_pll(codec_dai, 0, RT1015_PLL_S_BCLK,
params_rate(params) * 50,
params_rate(params) * 256);
if (ret < 0) {
dev_err(card->dev, "failed to set pll\n");
return ret;
}
/* Configure sysclk for codec */
ret = snd_soc_dai_set_sysclk(codec_dai, RT1015_SCLK_S_PLL,
params_rate(params) * 256,
SND_SOC_CLOCK_IN);
if (ret < 0) {
dev_err(card->dev, "failed to set sysclk\n");
return ret;
}
}
return 0;
}
static struct snd_soc_ops sof_rt1015_ops = {
.hw_params = sof_rt1015_hw_params,
};
static struct snd_soc_dai_link_component platform_component[] = { static struct snd_soc_dai_link_component platform_component[] = {
{ {
/* name might be overridden during probe */ /* name might be overridden during probe */
...@@ -316,12 +354,17 @@ static const struct snd_kcontrol_new sof_controls[] = { ...@@ -316,12 +354,17 @@ static const struct snd_kcontrol_new sof_controls[] = {
SOC_DAPM_PIN_SWITCH("Headphone Jack"), SOC_DAPM_PIN_SWITCH("Headphone Jack"),
SOC_DAPM_PIN_SWITCH("Headset Mic"), SOC_DAPM_PIN_SWITCH("Headset Mic"),
SOC_DAPM_PIN_SWITCH("Spk"), SOC_DAPM_PIN_SWITCH("Spk"),
SOC_DAPM_PIN_SWITCH("Left Spk"),
SOC_DAPM_PIN_SWITCH("Right Spk"),
}; };
static const struct snd_soc_dapm_widget sof_widgets[] = { static const struct snd_soc_dapm_widget sof_widgets[] = {
SND_SOC_DAPM_HP("Headphone Jack", NULL), SND_SOC_DAPM_HP("Headphone Jack", NULL),
SND_SOC_DAPM_MIC("Headset Mic", NULL), SND_SOC_DAPM_MIC("Headset Mic", NULL),
SND_SOC_DAPM_SPK("Spk", NULL), SND_SOC_DAPM_SPK("Spk", NULL),
SND_SOC_DAPM_SPK("Left Spk", NULL),
SND_SOC_DAPM_SPK("Right Spk", NULL),
}; };
static const struct snd_soc_dapm_widget dmic_widgets[] = { static const struct snd_soc_dapm_widget dmic_widgets[] = {
...@@ -342,11 +385,22 @@ static const struct snd_soc_dapm_route speaker_map[] = { ...@@ -342,11 +385,22 @@ static const struct snd_soc_dapm_route speaker_map[] = {
{ "Spk", NULL, "Speaker" }, { "Spk", NULL, "Speaker" },
}; };
static const struct snd_soc_dapm_route speaker_map_lr[] = {
{ "Left Spk", NULL, "Left SPO" },
{ "Right Spk", NULL, "Right SPO" },
};
static const struct snd_soc_dapm_route dmic_map[] = { static const struct snd_soc_dapm_route dmic_map[] = {
/* digital mics */ /* digital mics */
{"DMic", NULL, "SoC DMIC"}, {"DMic", NULL, "SoC DMIC"},
}; };
static int speaker_codec_init_lr(struct snd_soc_pcm_runtime *rtd)
{
return snd_soc_dapm_add_routes(&rtd->card->dapm, speaker_map_lr,
ARRAY_SIZE(speaker_map_lr));
}
static int speaker_codec_init(struct snd_soc_pcm_runtime *rtd) static int speaker_codec_init(struct snd_soc_pcm_runtime *rtd)
{ {
struct snd_soc_card *card = rtd->card; struct snd_soc_card *card = rtd->card;
...@@ -382,6 +436,17 @@ static int dmic_init(struct snd_soc_pcm_runtime *rtd) ...@@ -382,6 +436,17 @@ static int dmic_init(struct snd_soc_pcm_runtime *rtd)
return ret; return ret;
} }
static struct snd_soc_codec_conf rt1015_amp_conf[] = {
{
.dlc = COMP_CODEC_CONF("i2c-10EC1015:00"),
.name_prefix = "Left",
},
{
.dlc = COMP_CODEC_CONF("i2c-10EC1015:01"),
.name_prefix = "Right",
},
};
/* sof audio machine driver for rt5682 codec */ /* sof audio machine driver for rt5682 codec */
static struct snd_soc_card sof_audio_card_rt5682 = { static struct snd_soc_card sof_audio_card_rt5682 = {
.name = "rt5682", /* the sof- prefix is added by the core */ .name = "rt5682", /* the sof- prefix is added by the core */
...@@ -417,6 +482,17 @@ static struct snd_soc_dai_link_component max98357a_component[] = { ...@@ -417,6 +482,17 @@ static struct snd_soc_dai_link_component max98357a_component[] = {
} }
}; };
static struct snd_soc_dai_link_component rt1015_components[] = {
{
.name = "i2c-10EC1015:00",
.dai_name = "rt1015-aif",
},
{
.name = "i2c-10EC1015:01",
.dai_name = "rt1015-aif",
},
};
static struct snd_soc_dai_link *sof_card_dai_links_create(struct device *dev, static struct snd_soc_dai_link *sof_card_dai_links_create(struct device *dev,
int ssp_codec, int ssp_codec,
int ssp_amp, int ssp_amp,
...@@ -556,11 +632,18 @@ static struct snd_soc_dai_link *sof_card_dai_links_create(struct device *dev, ...@@ -556,11 +632,18 @@ static struct snd_soc_dai_link *sof_card_dai_links_create(struct device *dev,
goto devm_err; goto devm_err;
links[id].id = id; links[id].id = id;
links[id].codecs = max98357a_component; if (sof_rt5682_quirk & SOF_RT1015_SPEAKER_AMP_PRESENT) {
links[id].num_codecs = ARRAY_SIZE(max98357a_component); links[id].codecs = rt1015_components;
links[id].num_codecs = ARRAY_SIZE(rt1015_components);
links[id].init = speaker_codec_init_lr;
links[id].ops = &sof_rt1015_ops;
} else {
links[id].codecs = max98357a_component;
links[id].num_codecs = ARRAY_SIZE(max98357a_component);
links[id].init = speaker_codec_init;
}
links[id].platforms = platform_component; links[id].platforms = platform_component;
links[id].num_platforms = ARRAY_SIZE(platform_component); links[id].num_platforms = ARRAY_SIZE(platform_component);
links[id].init = speaker_codec_init,
links[id].nonatomic = true; links[id].nonatomic = true;
links[id].dpcm_playback = 1; links[id].dpcm_playback = 1;
links[id].no_pcm = 1; links[id].no_pcm = 1;
...@@ -669,6 +752,11 @@ static int sof_audio_probe(struct platform_device *pdev) ...@@ -669,6 +752,11 @@ static int sof_audio_probe(struct platform_device *pdev)
sof_audio_card_rt5682.dai_link = dai_links; sof_audio_card_rt5682.dai_link = dai_links;
if (sof_rt5682_quirk & SOF_RT1015_SPEAKER_AMP_PRESENT) {
sof_audio_card_rt5682.codec_conf = rt1015_amp_conf;
sof_audio_card_rt5682.num_configs = ARRAY_SIZE(rt1015_amp_conf);
}
INIT_LIST_HEAD(&ctx->hdmi_pcm_list); INIT_LIST_HEAD(&ctx->hdmi_pcm_list);
sof_audio_card_rt5682.dev = &pdev->dev; sof_audio_card_rt5682.dev = &pdev->dev;
...@@ -714,6 +802,15 @@ static const struct platform_device_id board_ids[] = { ...@@ -714,6 +802,15 @@ static const struct platform_device_id board_ids[] = {
SOF_RT5682_SSP_AMP(1) | SOF_RT5682_SSP_AMP(1) |
SOF_RT5682_NUM_HDMIDEV(4)), SOF_RT5682_NUM_HDMIDEV(4)),
}, },
{
.name = "jsl_rt5682_rt1015",
.driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
SOF_RT5682_MCLK_24MHZ |
SOF_RT5682_SSP_CODEC(0) |
SOF_SPEAKER_AMP_PRESENT |
SOF_RT1015_SPEAKER_AMP_PRESENT |
SOF_RT5682_SSP_AMP(1)),
},
{ } { }
}; };
...@@ -735,3 +832,4 @@ MODULE_AUTHOR("Sathya Prakash M R <sathya.prakash.m.r@intel.com>"); ...@@ -735,3 +832,4 @@ MODULE_AUTHOR("Sathya Prakash M R <sathya.prakash.m.r@intel.com>");
MODULE_LICENSE("GPL v2"); MODULE_LICENSE("GPL v2");
MODULE_ALIAS("platform:sof_rt5682"); MODULE_ALIAS("platform:sof_rt5682");
MODULE_ALIAS("platform:tgl_max98357a_rt5682"); MODULE_ALIAS("platform:tgl_max98357a_rt5682");
MODULE_ALIAS("platform:jsl_rt5682_rt1015");
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
/* /*
* soc-apci-intel-jsl-match.c - tables and support for JSL ACPI enumeration. * soc-apci-intel-jsl-match.c - tables and support for JSL ACPI enumeration.
* *
* Copyright (c) 2019, Intel Corporation. * Copyright (c) 2019-2020, Intel Corporation.
* *
*/ */
...@@ -14,6 +14,11 @@ static struct snd_soc_acpi_codecs jsl_7219_98373_codecs = { ...@@ -14,6 +14,11 @@ static struct snd_soc_acpi_codecs jsl_7219_98373_codecs = {
.codecs = {"MX98373"} .codecs = {"MX98373"}
}; };
static struct snd_soc_acpi_codecs rt1015_spk = {
.num_codecs = 1,
.codecs = {"10EC1015"}
};
/* /*
* When adding new entry to the snd_soc_acpi_intel_jsl_machines array, * When adding new entry to the snd_soc_acpi_intel_jsl_machines array,
* use .quirk_data member to distinguish different machine driver, * use .quirk_data member to distinguish different machine driver,
...@@ -34,6 +39,14 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_jsl_machines[] = { ...@@ -34,6 +39,14 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_jsl_machines[] = {
.sof_fw_filename = "sof-jsl.ri", .sof_fw_filename = "sof-jsl.ri",
.sof_tplg_filename = "sof-jsl-da7219-mx98360a.tplg", .sof_tplg_filename = "sof-jsl-da7219-mx98360a.tplg",
}, },
{
.id = "10EC5682",
.drv_name = "jsl_rt5682_rt1015",
.sof_fw_filename = "sof-jsl.ri",
.machine_quirk = snd_soc_acpi_codec_list,
.quirk_data = &rt1015_spk,
.sof_tplg_filename = "sof-jsl-rt5682-rt1015.tplg",
},
{}, {},
}; };
EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_jsl_machines); EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_jsl_machines);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment