// SPDX-License-Identifier: GPL-2.0-only
// Copyright(c) 2018 Intel Corporation.
/*
* Intel Kabylake I2S Machine Driver with MAX98927, MAX98373 & DA7219 Codecs
*
* Modified from:
* Intel Kabylake I2S Machine driver supporting MAX98927 and
* RT5663 codecs
*/
#include <linux/input.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <sound/core.h>
#include <sound/jack.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
#include "../../codecs/da7219.h"
#include "../../codecs/hdac_hdmi.h"
#include "../../codecs/da7219-aad.h"
#define KBL_DIALOG_CODEC_DAI "da7219-hifi"
#define MAX98927_CODEC_DAI "max98927-aif1"
#define MAX98927_DEV0_NAME "i2c-MX98927:00"
#define MAX98927_DEV1_NAME "i2c-MX98927:01"
#define MAX98373_CODEC_DAI "max98373-aif1"
#define MAX98373_DEV0_NAME "i2c-MX98373:00"
#define MAX98373_DEV1_NAME "i2c-MX98373:01"
#define DUAL_CHANNEL 2
#define QUAD_CHANNEL 4
#define NAME_SIZE 32
static struct snd_soc_card *kabylake_audio_card;
static struct snd_soc_jack kabylake_hdmi[3];
struct kbl_hdmi_pcm {
struct list_head head;
struct snd_soc_dai *codec_dai;
int device;
};
struct kbl_codec_private {
struct snd_soc_jack kabylake_headset;
struct list_head hdmi_pcm_list;
};
enum {
KBL_DPCM_AUDIO_PB = 0,
KBL_DPCM_AUDIO_ECHO_REF_CP,
KBL_DPCM_AUDIO_REF_CP,
KBL_DPCM_AUDIO_DMIC_CP,
KBL_DPCM_AUDIO_HDMI1_PB,
KBL_DPCM_AUDIO_HDMI2_PB,
KBL_DPCM_AUDIO_HDMI3_PB,
KBL_DPCM_AUDIO_HS_PB,
KBL_DPCM_AUDIO_CP,
};
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 = 0;
codec_dai = snd_soc_card_get_codec_dai(card, KBL_DIALOG_CODEC_DAI);
if (!codec_dai) {
dev_err(card->dev, "Codec dai not found; Unable to set/unset codec pll\n");
return -EIO;
}
/* Configure sysclk for codec */
ret = snd_soc_dai_set_sysclk(codec_dai, DA7219_CLKSRC_MCLK, 24576000,
SND_SOC_CLOCK_IN);
if (ret) {
dev_err(card->dev, "can't set codec sysclk configuration\n");
return ret;
}
if (SND_SOC_DAPM_EVENT_OFF(event)) {
ret = snd_soc_dai_set_pll(codec_dai, 0,
DA7219_SYSCLK_MCLK, 0, 0);
if (ret)
dev_err(card->dev, "failed to stop PLL: %d\n", ret);
} else if (SND_SOC_DAPM_EVENT_ON(event)) {
ret = snd_soc_dai_set_pll(codec_dai, 0, DA7219_SYSCLK_PLL_SRM,
0, DA7219_PLL_FREQ_OUT_98304);
if (ret)
dev_err(card->dev, "failed to start PLL: %d\n", ret);
}
return ret;
}
static const struct snd_kcontrol_new kabylake_controls[] = {
SOC_DAPM_PIN_SWITCH("Headphone Jack"),
SOC_DAPM_PIN_SWITCH("Headset Mic"),
SOC_DAPM_PIN_SWITCH("Left Spk"),
SOC_DAPM_PIN_SWITCH("Right Spk"),
};
static const struct snd_soc_dapm_widget kabylake_widgets[] = {
SND_SOC_DAPM_HP("Headphone Jack", NULL),
SND_SOC_DAPM_MIC("Headset Mic", NULL),
SND_SOC_DAPM_SPK("Left Spk", NULL),
SND_SOC_DAPM_SPK("Right Spk", NULL),
SND_SOC_DAPM_MIC("SoC DMIC", NULL),
SND_SOC_DAPM_SPK("DP", NULL),
SND_SOC_DAPM_SPK("HDMI", NULL),
SND_SOC_DAPM_SUPPLY("Platform Clock", SND_SOC_NOPM, 0, 0,
platform_clock_control<