---
sound/soc/intel/boards/bytcr_rt5651.c | 84 +++++++++++++++++++++++++++++++----
1 file changed, 75 insertions(+), 9 deletions(-)
diff --git a/sound/soc/intel/boards/bytcr_rt5651.c b/sound/soc/intel/boards/bytcr_rt5651.c
index 35f591e..e51ea5b 100644
--- a/sound/soc/intel/boards/bytcr_rt5651.c
+++ b/sound/soc/intel/boards/bytcr_rt5651.c
@@ -31,11 +31,76 @@
#include "../../codecs/rt5651.h"
#include "../atom/sst-atom-controls.h"
+#define CHT_PLAT_CLK_3_HZ 19200000
+#define CHT_CODEC_DAI_5651 "rt5651-aif1"
+
+struct cht_acpi_card {
+ char *codec_id;
+ int codec_type;
+ struct snd_soc_card *soc_card;
+};
+
+struct cht_mc_private {
+ struct snd_soc_jack jack;
+ struct cht_acpi_card *acpi_card;
+};
+
+
+static inline struct snd_soc_dai *cht_get_codec_dai(struct snd_soc_card *card)
+{
+ struct snd_soc_pcm_runtime *rtd;
+
+ list_for_each_entry(rtd, &card->rtd_list, list) {
+ if (!strncmp(rtd->codec_dai->name, CHT_CODEC_DAI_5651,
+ strlen(CHT_CODEC_DAI_5651)))
+ return rtd->codec_dai;
+ }
+ return NULL;
+}
+
+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 snd_soc_dai *codec_dai;
+ int ret;
+
+ codec_dai = cht_get_codec_dai(card);
+ if (!codec_dai) {
+ dev_err(card->dev, "Codec dai not found; Unable to set platform clock\n");
+ return -EIO;
+ }
+
+ if (!SND_SOC_DAPM_EVENT_OFF(event))
+ return 0;
+
+ /* Set codec sysclk source to its internal clock because codec PLL will
+ * be off when idle and MCLK will also be off by ACPI when codec is
+ * runtime suspended. Codec needs clock for jack detection and button
+ * press.
+ */
+ ret = snd_soc_dai_set_sysclk(codec_dai, RT5651_SCLK_S_RCCLK,
+ 0, SND_SOC_CLOCK_IN);
+ if (ret < 0) {
+ dev_err(card->dev, "can't set codec sysclk: %d\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+
+
+
static const struct snd_soc_dapm_widget byt_rt5651_widgets[] = {
SND_SOC_DAPM_HP("Headphone", NULL),
SND_SOC_DAPM_MIC("Headset Mic", NULL),
SND_SOC_DAPM_MIC("Internal Mic", NULL),
SND_SOC_DAPM_SPK("Speaker", NULL),
+ SND_SOC_DAPM_SUPPLY("Platform Clock", SND_SOC_NOPM, 0, 0,
+ platform_clock_control, SND_SOC_DAPM_POST_PMD),
+
};
static const struct snd_soc_dapm_route byt_rt5651_audio_map[] = {
@@ -52,6 +117,9 @@ static const struct snd_soc_dapm_route byt_rt5651_audio_map[] = {
{"Headphone", NULL, "HPOR"},
{"Speaker", NULL, "LOUTL"},
{"Speaker", NULL, "LOUTR"},
+ {"Headphone", NULL, "Platform Clock"},
+ {"Speaker", NULL, "Platform Clock"},
+
};
static const struct snd_soc_dapm_route byt_rt5651_intmic_dmic1_map[] = {
@@ -93,7 +161,13 @@ static int byt_rt5651_aif1_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_dai *codec_dai = rtd->codec_dai;
int ret;
- snd_soc_dai_set_bclk_ratio(codec_dai, 50);
+ /* set codec PLL source to the 19.2MHz platform clock (MCLK) */
+ ret = snd_soc_dai_set_pll(codec_dai, 0, RT5651_PLL1_S_MCLK,
+ CHT_PLAT_CLK_3_HZ, params_rate(params) * 512);
+ if (ret < 0) {
+ dev_err(rtd->dev, "can't set codec pll: %d\n", ret);
+ return ret;
+ }
ret = snd_soc_dai_set_sysclk(codec_dai, RT5651_SCLK_S_PLL1,
params_rate(params) * 512,
@@ -103,14 +177,6 @@ static int byt_rt5651_aif1_hw_params(struct snd_pcm_substream *substream,
return ret;
}
- ret = snd_soc_dai_set_pll(codec_dai, 0, RT5651_PLL1_S_BCLK1,
- params_rate(params) * 50,
- params_rate(params) * 512);
- if (ret < 0) {
- dev_err(rtd->dev, "can't set codec pll: %d\n", ret);
- return ret;
- }
-
return 0;
}