ASoC: Intel: kbl: Enable mclk and ssp sclk early
rt5663 needs mclk/sclk early to synchronize its internal clocks. Enable these clocks early. Signed-off-by: Harsha Priya <harshapriya.n@intel.com> Signed-off-by: Subhransu S. Prusty <subhransu.s.prusty@intel.com> Signed-off-by: Sriram Periyasamy <sriramx.periyasamy@intel.com> Acked-by: Vinod Koul <vinod.koul@intel.com> Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
parent
9afbc5ec76
commit
f7f61e08fe
@ -235,6 +235,7 @@ config SND_SOC_INTEL_KBL_RT5663_MAX98927_MACH
|
|||||||
select SND_SOC_MAX98927
|
select SND_SOC_MAX98927
|
||||||
select SND_SOC_DMIC
|
select SND_SOC_DMIC
|
||||||
select SND_SOC_HDAC_HDMI
|
select SND_SOC_HDAC_HDMI
|
||||||
|
select SND_SOC_INTEL_SKYLAKE_SSP_CLK
|
||||||
help
|
help
|
||||||
This adds support for ASoC Onboard Codec I2S machine driver. This will
|
This adds support for ASoC Onboard Codec I2S machine driver. This will
|
||||||
create an alsa sound card for RT5663 + MAX98927.
|
create an alsa sound card for RT5663 + MAX98927.
|
||||||
|
@ -28,6 +28,9 @@
|
|||||||
#include "../../codecs/rt5663.h"
|
#include "../../codecs/rt5663.h"
|
||||||
#include "../../codecs/hdac_hdmi.h"
|
#include "../../codecs/hdac_hdmi.h"
|
||||||
#include "../skylake/skl.h"
|
#include "../skylake/skl.h"
|
||||||
|
#include <linux/clk.h>
|
||||||
|
#include <linux/clk-provider.h>
|
||||||
|
#include <linux/clkdev.h>
|
||||||
|
|
||||||
#define KBL_REALTEK_CODEC_DAI "rt5663-aif"
|
#define KBL_REALTEK_CODEC_DAI "rt5663-aif"
|
||||||
#define KBL_MAXIM_CODEC_DAI "max98927-aif1"
|
#define KBL_MAXIM_CODEC_DAI "max98927-aif1"
|
||||||
@ -48,6 +51,8 @@ struct kbl_hdmi_pcm {
|
|||||||
struct kbl_rt5663_private {
|
struct kbl_rt5663_private {
|
||||||
struct snd_soc_jack kabylake_headset;
|
struct snd_soc_jack kabylake_headset;
|
||||||
struct list_head hdmi_pcm_list;
|
struct list_head hdmi_pcm_list;
|
||||||
|
struct clk *mclk;
|
||||||
|
struct clk *sclk;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
@ -69,6 +74,61 @@ static const struct snd_kcontrol_new kabylake_controls[] = {
|
|||||||
SOC_DAPM_PIN_SWITCH("Right Spk"),
|
SOC_DAPM_PIN_SWITCH("Right Spk"),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
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_rt5663_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[] = {
|
static const struct snd_soc_dapm_widget kabylake_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),
|
||||||
@ -78,11 +138,14 @@ static const struct snd_soc_dapm_widget kabylake_widgets[] = {
|
|||||||
SND_SOC_DAPM_SPK("HDMI1", NULL),
|
SND_SOC_DAPM_SPK("HDMI1", NULL),
|
||||||
SND_SOC_DAPM_SPK("HDMI2", NULL),
|
SND_SOC_DAPM_SPK("HDMI2", NULL),
|
||||||
SND_SOC_DAPM_SPK("HDMI3", NULL),
|
SND_SOC_DAPM_SPK("HDMI3", 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[] = {
|
static const struct snd_soc_dapm_route kabylake_map[] = {
|
||||||
/* HP jack connectors - unknown if we have jack detection */
|
/* HP jack connectors - unknown if we have jack detection */
|
||||||
|
{ "Headphone Jack", NULL, "Platform Clock" },
|
||||||
{ "Headphone Jack", NULL, "HPOL" },
|
{ "Headphone Jack", NULL, "HPOL" },
|
||||||
{ "Headphone Jack", NULL, "HPOR" },
|
{ "Headphone Jack", NULL, "HPOR" },
|
||||||
|
|
||||||
@ -91,6 +154,7 @@ static const struct snd_soc_dapm_route kabylake_map[] = {
|
|||||||
{ "Right Spk", NULL, "Right BE_OUT" },
|
{ "Right Spk", NULL, "Right BE_OUT" },
|
||||||
|
|
||||||
/* other jacks */
|
/* other jacks */
|
||||||
|
{ "Headset Mic", NULL, "Platform Clock" },
|
||||||
{ "IN1P", NULL, "Headset Mic" },
|
{ "IN1P", NULL, "Headset Mic" },
|
||||||
{ "IN1N", NULL, "Headset Mic" },
|
{ "IN1N", NULL, "Headset Mic" },
|
||||||
{ "DMic", NULL, "SoC DMIC" },
|
{ "DMic", NULL, "SoC DMIC" },
|
||||||
@ -901,6 +965,7 @@ static int kabylake_audio_probe(struct platform_device *pdev)
|
|||||||
{
|
{
|
||||||
struct kbl_rt5663_private *ctx;
|
struct kbl_rt5663_private *ctx;
|
||||||
struct skl_machine_pdata *pdata;
|
struct skl_machine_pdata *pdata;
|
||||||
|
int ret;
|
||||||
|
|
||||||
ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_ATOMIC);
|
ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_ATOMIC);
|
||||||
if (!ctx)
|
if (!ctx)
|
||||||
@ -919,6 +984,34 @@ static int kabylake_audio_probe(struct platform_device *pdev)
|
|||||||
dmic_constraints = pdata->dmic_num == 2 ?
|
dmic_constraints = pdata->dmic_num == 2 ?
|
||||||
&constraints_dmic_2ch : &constraints_dmic_channels;
|
&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_sclk, 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);
|
return devm_snd_soc_register_card(&pdev->dev, kabylake_audio_card);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user