mirror of
https://github.com/edk2-porting/linux-next.git
synced 2025-01-12 15:44:01 +08:00
ASoC: Intel: eve: Enable mclk and ssp sclk early
rt5663 and rt5514 needs mclk/sclk early to synchronize its internal clocks. Signed-off-by: Naveen M <naveen.m@intel.com> Signed-off-by: Harsha Priya <harshapriya.n@intel.com> Signed-off-by: Subhransu S. Prusty <subhransu.s.prusty@intel.com> Signed-off-by: Brent Lu <brent.lu@intel.com> Acked-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com> Link: https://lore.kernel.org/r/1571070480-25666-1-git-send-email-brent.lu@intel.com Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
parent
9899a7a869
commit
47cbea2162
@ -320,6 +320,7 @@ config SND_SOC_INTEL_KBL_RT5663_RT5514_MAX98927_MACH
|
||||
select SND_SOC_RT5514_SPI
|
||||
select SND_SOC_MAX98927
|
||||
select SND_SOC_HDAC_HDMI
|
||||
select SND_SOC_INTEL_SKYLAKE_SSP_CLK
|
||||
help
|
||||
This adds support for ASoC Onboard Codec I2S machine driver. This will
|
||||
create an alsa sound card for RT5663 + RT5514 + MAX98927.
|
||||
|
@ -22,6 +22,9 @@
|
||||
#include "../../codecs/rt5514.h"
|
||||
#include "../../codecs/rt5663.h"
|
||||
#include "../../codecs/hdac_hdmi.h"
|
||||
#include <linux/clk.h>
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/clkdev.h>
|
||||
|
||||
#define KBL_REALTEK_CODEC_DAI "rt5663-aif"
|
||||
#define KBL_REALTEK_DMIC_CODEC_DAI "rt5514-aif1"
|
||||
@ -50,6 +53,8 @@ struct kbl_codec_private {
|
||||
struct snd_soc_jack kabylake_headset;
|
||||
struct list_head hdmi_pcm_list;
|
||||
struct snd_soc_jack kabylake_hdmi[2];
|
||||
struct clk *mclk;
|
||||
struct clk *sclk;
|
||||
};
|
||||
|
||||
enum {
|
||||
@ -71,6 +76,61 @@ static const struct snd_kcontrol_new kabylake_controls[] = {
|
||||
SOC_DAPM_PIN_SWITCH("DMIC"),
|
||||
};
|
||||
|
||||
static int platform_clock_control(struct snd_soc_dapm_widget *w,
|
||||
struct snd_kcontrol *k, int event)
|
||||
{
|
||||
struct snd_soc_dapm_context *dapm = w->dapm;
|
||||
struct snd_soc_card *card = dapm->card;
|
||||
struct kbl_codec_private *priv = snd_soc_card_get_drvdata(card);
|
||||
int ret = 0;
|
||||
|
||||
/*
|
||||
* MCLK/SCLK need to be ON early for a successful synchronization of
|
||||
* codec internal clock. And the clocks are turned off during
|
||||
* POST_PMD after the stream is stopped.
|
||||
*/
|
||||
switch (event) {
|
||||
case SND_SOC_DAPM_PRE_PMU:
|
||||
/* Enable MCLK */
|
||||
ret = clk_set_rate(priv->mclk, 24000000);
|
||||
if (ret < 0) {
|
||||
dev_err(card->dev, "Can't set rate for mclk, err: %d\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(priv->mclk);
|
||||
if (ret < 0) {
|
||||
dev_err(card->dev, "Can't enable mclk, err: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Enable SCLK */
|
||||
ret = clk_set_rate(priv->sclk, 3072000);
|
||||
if (ret < 0) {
|
||||
dev_err(card->dev, "Can't set rate for sclk, err: %d\n",
|
||||
ret);
|
||||
clk_disable_unprepare(priv->mclk);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(priv->sclk);
|
||||
if (ret < 0) {
|
||||
dev_err(card->dev, "Can't enable sclk, err: %d\n", ret);
|
||||
clk_disable_unprepare(priv->mclk);
|
||||
}
|
||||
break;
|
||||
case SND_SOC_DAPM_POST_PMD:
|
||||
clk_disable_unprepare(priv->mclk);
|
||||
clk_disable_unprepare(priv->sclk);
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct snd_soc_dapm_widget kabylake_widgets[] = {
|
||||
SND_SOC_DAPM_HP("Headphone Jack", NULL),
|
||||
SND_SOC_DAPM_MIC("Headset Mic", NULL),
|
||||
@ -79,11 +139,15 @@ static const struct snd_soc_dapm_widget kabylake_widgets[] = {
|
||||
SND_SOC_DAPM_MIC("DMIC", NULL),
|
||||
SND_SOC_DAPM_SPK("HDMI1", NULL),
|
||||
SND_SOC_DAPM_SPK("HDMI2", NULL),
|
||||
SND_SOC_DAPM_SUPPLY("Platform Clock", SND_SOC_NOPM, 0, 0,
|
||||
platform_clock_control, SND_SOC_DAPM_PRE_PMU |
|
||||
SND_SOC_DAPM_POST_PMD),
|
||||
|
||||
};
|
||||
|
||||
static const struct snd_soc_dapm_route kabylake_map[] = {
|
||||
/* Headphones */
|
||||
{ "Headphone Jack", NULL, "Platform Clock" },
|
||||
{ "Headphone Jack", NULL, "HPOL" },
|
||||
{ "Headphone Jack", NULL, "HPOR" },
|
||||
|
||||
@ -92,6 +156,7 @@ static const struct snd_soc_dapm_route kabylake_map[] = {
|
||||
{ "Right Spk", NULL, "Right BE_OUT" },
|
||||
|
||||
/* other jacks */
|
||||
{ "Headset Mic", NULL, "Platform Clock" },
|
||||
{ "IN1P", NULL, "Headset Mic" },
|
||||
{ "IN1N", NULL, "Headset Mic" },
|
||||
|
||||
@ -643,6 +708,7 @@ static int kabylake_audio_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct kbl_codec_private *ctx;
|
||||
struct snd_soc_acpi_mach *mach;
|
||||
int ret = 0;
|
||||
|
||||
ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL);
|
||||
if (!ctx)
|
||||
@ -658,6 +724,34 @@ static int kabylake_audio_probe(struct platform_device *pdev)
|
||||
dmic_constraints = mach->mach_params.dmic_num == 2 ?
|
||||
&constraints_dmic_2ch : &constraints_dmic_channels;
|
||||
|
||||
ctx->mclk = devm_clk_get(&pdev->dev, "ssp1_mclk");
|
||||
if (IS_ERR(ctx->mclk)) {
|
||||
ret = PTR_ERR(ctx->mclk);
|
||||
if (ret == -ENOENT) {
|
||||
dev_info(&pdev->dev,
|
||||
"Failed to get ssp1_mclk, defer probe\n");
|
||||
return -EPROBE_DEFER;
|
||||
}
|
||||
|
||||
dev_err(&pdev->dev, "Failed to get ssp1_mclk with err:%d\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ctx->sclk = devm_clk_get(&pdev->dev, "ssp1_sclk");
|
||||
if (IS_ERR(ctx->sclk)) {
|
||||
ret = PTR_ERR(ctx->sclk);
|
||||
if (ret == -ENOENT) {
|
||||
dev_info(&pdev->dev,
|
||||
"Failed to get ssp1_sclk, defer probe\n");
|
||||
return -EPROBE_DEFER;
|
||||
}
|
||||
|
||||
dev_err(&pdev->dev, "Failed to get ssp1_sclk with err:%d\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return devm_snd_soc_register_card(&pdev->dev, &kabylake_audio_card);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user