ALT Linux kernel packages development
 help / color / mirror / Atom feed
* [d-kernel] [PATCH 0/9] *** backport support for ES83x6 codec in I2S mode for CML/CNL platforms to 5.15.x ***
@ 2022-04-04  6:28 nickel
  2022-04-04  6:28 ` [d-kernel] (no subject) nickel
  0 siblings, 1 reply; 28+ messages in thread
From: nickel @ 2022-04-04  6:28 UTC (permalink / raw)
  To: devel-kernel

 [PATCH 1/9] commit 0b220578c2aab3d5ac6b693117e8c5d22e8c2b34
 [PATCH 2/9] commit 79b5808491cf152b808c51fecdafb221fa270cf1
 [PATCH 3/9] commit 8143959d503dd6b3c8b9802cee0f1eba82e8d844
 [PATCH 4/9] commit 796f9b0189299a221d4c822be216165dd2371852
 [PATCH 5/9] commit f6a1611f744dcdd55c5adaf02f193083286dac34
 [PATCH 6/9] ALSA: intel-dspconfig: add ES8336 support for CNL
 [PATCH 7/9] ASoC: Intel: soc-acpi: add ESSX8336 support on Cannon
 [PATCH 8/9] config: CONFIG_SND_SOC_INTEL_SOF_ES8336_MACH=m
 [PATCH 9/9] ASoC: Intel: sof_es8336: add DMI info based pa-enable



^ permalink raw reply	[flat|nested] 28+ messages in thread

* [d-kernel] (no subject)
@ 2022-04-04  6:28 ` nickel
  2022-04-04  6:28   ` [d-kernel] [PATCH 1/9] commit 0b220578c2aab3d5ac6b693117e8c5d22e8c2b34 nickel
                     ` (8 more replies)
  0 siblings, 9 replies; 28+ messages in thread
From: nickel @ 2022-04-04  6:28 UTC (permalink / raw)
  To: devel-kernel

GIT: [PATCH 1/9] commit 0b220578c2aab3d5ac6b693117e8c5d22e8c2b34
GIT: [PATCH 2/9] commit 79b5808491cf152b808c51fecdafb221fa270cf1
GIT: [PATCH 3/9] commit 8143959d503dd6b3c8b9802cee0f1eba82e8d844
GIT: [PATCH 4/9] commit 796f9b0189299a221d4c822be216165dd2371852
GIT: [PATCH 5/9] commit f6a1611f744dcdd55c5adaf02f193083286dac34
GIT: [PATCH 6/9] ALSA: intel-dspconfig: add ES8336 support for CNL
GIT: [PATCH 7/9] ASoC: Intel: soc-acpi: add ESSX8336 support on Cannon
GIT: [PATCH 8/9] config: CONFIG_SND_SOC_INTEL_SOF_ES8336_MACH=m
GIT: [PATCH 9/9] ASoC: Intel: sof_es8336: add DMI info based pa-enable


^ permalink raw reply	[flat|nested] 28+ messages in thread

* [d-kernel] [PATCH 1/9] commit 0b220578c2aab3d5ac6b693117e8c5d22e8c2b34
  2022-04-04  6:28 ` [d-kernel] (no subject) nickel
@ 2022-04-04  6:28   ` nickel
  2022-04-04 14:48     ` Vitaly Chikunov
  2022-04-04  6:28   ` [d-kernel] [PATCH 2/9] commit 79b5808491cf152b808c51fecdafb221fa270cf1 nickel
                     ` (7 subsequent siblings)
  8 siblings, 1 reply; 28+ messages in thread
From: nickel @ 2022-04-04  6:28 UTC (permalink / raw)
  To: devel-kernel; +Cc: Vasily Vinogradov

From: Vasily Vinogradov <v.vinogradov@aq.ru>

    ASoC: Intel: add machine driver for SOF+ES8336
---
 sound/hda/intel-dsp-config.c                  |  24 +-
 sound/soc/codecs/es8316.c                     |   1 +
 sound/soc/intel/boards/Kconfig                |  13 +
 sound/soc/intel/boards/Makefile               |   2 +
 sound/soc/intel/boards/sof_es8336.c           | 569 ++++++++++++++++++
 .../intel/common/soc-acpi-intel-bxt-match.c   |   6 +
 .../intel/common/soc-acpi-intel-cml-match.c   |   6 +
 .../intel/common/soc-acpi-intel-glk-match.c   |   7 +-
 .../intel/common/soc-acpi-intel-jsl-match.c   |   6 +
 .../intel/common/soc-acpi-intel-tgl-match.c   |   6 +
 10 files changed, 627 insertions(+), 13 deletions(-)
 create mode 100644 sound/soc/intel/boards/sof_es8336.c

diff --git a/sound/hda/intel-dsp-config.c b/sound/hda/intel-dsp-config.c
index 4208fa8a4db5..f63114317ac9 100644
--- a/sound/hda/intel-dsp-config.c
+++ b/sound/hda/intel-dsp-config.c
@@ -249,13 +249,13 @@ static const struct config_entry config_table[] = {
 		}
 	},
 	{
-		.flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE,
+		.flags = FLAG_SOF,
 		.device = 0x02c8,
+		.codec_hid = "ESSX8336",
 	},
 	{
-		.flags = FLAG_SOF,
+		.flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE,
 		.device = 0x02c8,
-		.codec_hid = "ESSX8336",
 	},
 /* Cometlake-H */
 	{
@@ -278,14 +278,14 @@ static const struct config_entry config_table[] = {
 		}
 	},
 	{
-		.flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE,
-		.device = 0x06c8,
-	},
-		{
 		.flags = FLAG_SOF,
 		.device = 0x06c8,
 		.codec_hid = "ESSX8336",
 	},
+	{
+		.flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE,
+		.device = 0x06c8,
+	},
 #endif
 
 /* Icelake */
@@ -334,17 +334,17 @@ static const struct config_entry config_table[] = {
 		}
 	},
 	{
-		.flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE,
+		.flags = FLAG_SOF,
 		.device = 0xa0c8,
+		.codec_hid = "ESSX8336",
 	},
 	{
 		.flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE,
-		.device = 0x43c8,
+		.device = 0xa0c8,
 	},
 	{
-		.flags = FLAG_SOF,
-		.device = 0xa0c8,
-		.codec_hid = "ESSX8336",
+		.flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE,
+		.device = 0x43c8,
 	},
 #endif
 
diff --git a/sound/soc/codecs/es8316.c b/sound/soc/codecs/es8316.c
index 5fb02635c140..8f30a3ea8bfe 100644
--- a/sound/soc/codecs/es8316.c
+++ b/sound/soc/codecs/es8316.c
@@ -840,6 +840,7 @@ MODULE_DEVICE_TABLE(of, es8316_of_match);
 #ifdef CONFIG_ACPI
 static const struct acpi_device_id es8316_acpi_match[] = {
 	{"ESSX8316", 0},
+	{"ESSX8336", 0},
 	{},
 };
 MODULE_DEVICE_TABLE(acpi, es8316_acpi_match);
diff --git a/sound/soc/intel/boards/Kconfig b/sound/soc/intel/boards/Kconfig
index 61b71d6c44cf..a5b70ad98424 100644
--- a/sound/soc/intel/boards/Kconfig
+++ b/sound/soc/intel/boards/Kconfig
@@ -511,6 +511,19 @@ config SND_SOC_INTEL_SOF_PCM512x_MACH
 	  Say Y or m if you have such a device.
 	  If unsure select "N".
 
+config SND_SOC_INTEL_SOF_ES8336_MACH
+	tristate "SOF with ES8336 codec in I2S mode"
+	depends on I2C && ACPI && GPIOLIB
+	depends on MFD_INTEL_LPSS || COMPILE_TEST
+	depends on SND_HDA_CODEC_HDMI && SND_SOC_SOF_HDA_AUDIO_CODEC
+	select SND_SOC_ES8316
+	select SND_SOC_DMIC
+	help
+	   This adds support for ASoC machine driver for SOF platforms
+	   with es8336 codec.
+	   Say Y if you have such a device.
+	   If unsure select "N".
+
 endif ## SND_SOC_SOF_HDA_LINK || SND_SOC_SOF_BAYTRAIL
 
 if (SND_SOC_SOF_COMETLAKE && SND_SOC_SOF_HDA_LINK)
diff --git a/sound/soc/intel/boards/Makefile b/sound/soc/intel/boards/Makefile
index ed21b82a4cf6..de72ef29279e 100644
--- a/sound/soc/intel/boards/Makefile
+++ b/sound/soc/intel/boards/Makefile
@@ -22,6 +22,7 @@ snd-soc-sst-byt-cht-nocodec-objs := bytcht_nocodec.o
 snd-soc-sof_rt5682-objs := sof_rt5682.o sof_realtek_common.o
 snd-soc-sof_cs42l42-objs := sof_cs42l42.o
 snd-soc-cml_rt1011_rt5682-objs := cml_rt1011_rt5682.o
+snd-soc-sof_es8336-objs := sof_es8336.o
 snd-soc-kbl_da7219_max98357a-objs := kbl_da7219_max98357a.o
 snd-soc-kbl_da7219_max98927-objs := kbl_da7219_max98927.o
 snd-soc-kbl_rt5663_max98927-objs := kbl_rt5663_max98927.o
@@ -42,6 +43,7 @@ snd-soc-sof-sdw-objs += sof_sdw.o				\
 			sof_sdw_dmic.o sof_sdw_hdmi.o
 obj-$(CONFIG_SND_SOC_INTEL_SOF_RT5682_MACH) += snd-soc-sof_rt5682.o
 obj-$(CONFIG_SND_SOC_INTEL_SOF_CS42L42_MACH) += snd-soc-sof_cs42l42.o
+obj-$(CONFIG_SND_SOC_INTEL_SOF_ES8336_MACH) += snd-soc-sof_es8336.o
 obj-$(CONFIG_SND_SOC_INTEL_HASWELL_MACH) += snd-soc-sst-haswell.o
 obj-$(CONFIG_SND_SOC_INTEL_BXT_DA7219_MAX98357A_COMMON) += snd-soc-sst-bxt-da7219_max98357a.o
 obj-$(CONFIG_SND_SOC_INTEL_BXT_RT298_MACH) += snd-soc-sst-bxt-rt298.o
diff --git a/sound/soc/intel/boards/sof_es8336.c b/sound/soc/intel/boards/sof_es8336.c
new file mode 100644
index 000000000000..20d577eaab6d
--- /dev/null
+++ b/sound/soc/intel/boards/sof_es8336.c
@@ -0,0 +1,569 @@
+// SPDX-License-Identifier: GPL-2.0-only
+// Copyright(c) 2021 Intel Corporation.
+
+/*
+ * Intel SOF Machine Driver with es8336 Codec
+ */
+
+#include <linux/device.h>
+#include <linux/dmi.h>
+#include <linux/gpio/consumer.h>
+#include <linux/gpio/machine.h>
+#include <linux/i2c.h>
+#include <linux/input.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <sound/jack.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-acpi.h>
+#include "hda_dsp_common.h"
+
+#define SOF_ES8336_SSP_CODEC(quirk)		((quirk) & GENMASK(3, 0))
+#define SOF_ES8336_SSP_CODEC_MASK		(GENMASK(3, 0))
+
+#define SOF_ES8336_TGL_GPIO_QUIRK		BIT(4)
+#define SOF_ES8336_ENABLE_DMIC			BIT(5)
+
+static unsigned long quirk;
+
+static int quirk_override = -1;
+module_param_named(quirk, quirk_override, int, 0444);
+MODULE_PARM_DESC(quirk, "Board-specific quirk override");
+
+struct sof_es8336_private {
+	struct device *codec_dev;
+	struct gpio_desc *gpio_pa;
+	struct snd_soc_jack jack;
+	struct list_head hdmi_pcm_list;
+	bool speaker_en;
+};
+
+struct sof_hdmi_pcm {
+	struct list_head head;
+	struct snd_soc_dai *codec_dai;
+	int device;
+};
+
+static const struct acpi_gpio_params pa_enable_gpio = { 0, 0, true };
+static const struct acpi_gpio_mapping acpi_es8336_gpios[] = {
+	{ "pa-enable-gpios", &pa_enable_gpio, 1 },
+	{ }
+};
+
+static const struct acpi_gpio_params quirk_pa_enable_gpio = { 1, 0, true };
+static const struct acpi_gpio_mapping quirk_acpi_es8336_gpios[] = {
+	{ "pa-enable-gpios", &quirk_pa_enable_gpio, 1 },
+	{ }
+};
+
+static const struct acpi_gpio_mapping *gpio_mapping = acpi_es8336_gpios;
+
+static void log_quirks(struct device *dev)
+{
+	dev_info(dev, "quirk SSP%ld",  SOF_ES8336_SSP_CODEC(quirk));
+}
+
+static int sof_es8316_speaker_power_event(struct snd_soc_dapm_widget *w,
+					  struct snd_kcontrol *kcontrol, int event)
+{
+	struct snd_soc_card *card = w->dapm->card;
+	struct sof_es8336_private *priv = snd_soc_card_get_drvdata(card);
+
+	if (SND_SOC_DAPM_EVENT_ON(event))
+		priv->speaker_en = false;
+	else
+		priv->speaker_en = true;
+
+	gpiod_set_value_cansleep(priv->gpio_pa, priv->speaker_en);
+
+	return 0;
+}
+
+static const struct snd_soc_dapm_widget sof_es8316_widgets[] = {
+	SND_SOC_DAPM_SPK("Speaker", NULL),
+	SND_SOC_DAPM_HP("Headphone", NULL),
+	SND_SOC_DAPM_MIC("Headset Mic", NULL),
+	SND_SOC_DAPM_MIC("Internal Mic", NULL),
+
+	SND_SOC_DAPM_SUPPLY("Speaker Power", SND_SOC_NOPM, 0, 0,
+			    sof_es8316_speaker_power_event,
+			    SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
+};
+
+static const struct snd_soc_dapm_widget dmic_widgets[] = {
+	SND_SOC_DAPM_MIC("SoC DMIC", NULL),
+};
+
+static const struct snd_soc_dapm_route sof_es8316_audio_map[] = {
+	{"Headphone", NULL, "HPOL"},
+	{"Headphone", NULL, "HPOR"},
+
+	/*
+	 * There is no separate speaker output instead the speakers are muxed to
+	 * the HP outputs. The mux is controlled by the "Speaker Power" supply.
+	 */
+	{"Speaker", NULL, "HPOL"},
+	{"Speaker", NULL, "HPOR"},
+	{"Speaker", NULL, "Speaker Power"},
+};
+
+static const struct snd_soc_dapm_route sof_es8316_intmic_in1_map[] = {
+	{"MIC1", NULL, "Internal Mic"},
+	{"MIC2", NULL, "Headset Mic"},
+};
+
+static const struct snd_soc_dapm_route dmic_map[] = {
+	/* digital mics */
+	{"DMic", NULL, "SoC DMIC"},
+};
+
+static const struct snd_kcontrol_new sof_es8316_controls[] = {
+	SOC_DAPM_PIN_SWITCH("Speaker"),
+	SOC_DAPM_PIN_SWITCH("Headphone"),
+	SOC_DAPM_PIN_SWITCH("Headset Mic"),
+	SOC_DAPM_PIN_SWITCH("Internal Mic"),
+};
+
+static struct snd_soc_jack_pin sof_es8316_jack_pins[] = {
+	{
+		.pin	= "Headphone",
+		.mask	= SND_JACK_HEADPHONE,
+	},
+	{
+		.pin	= "Headset Mic",
+		.mask	= SND_JACK_MICROPHONE,
+	},
+};
+
+static int dmic_init(struct snd_soc_pcm_runtime *runtime)
+{
+	struct snd_soc_card *card = runtime->card;
+	int ret;
+
+	ret = snd_soc_dapm_new_controls(&card->dapm, dmic_widgets,
+					ARRAY_SIZE(dmic_widgets));
+	if (ret) {
+		dev_err(card->dev, "DMic widget addition failed: %d\n", ret);
+		return ret;
+	}
+
+	ret = snd_soc_dapm_add_routes(&card->dapm, dmic_map,
+				      ARRAY_SIZE(dmic_map));
+	if (ret)
+		dev_err(card->dev, "DMic map addition failed: %d\n", ret);
+
+	return ret;
+}
+
+static int sof_hdmi_init(struct snd_soc_pcm_runtime *runtime)
+{
+	struct sof_es8336_private *priv = snd_soc_card_get_drvdata(runtime->card);
+	struct snd_soc_dai *dai = asoc_rtd_to_codec(runtime, 0);
+	struct sof_hdmi_pcm *pcm;
+
+	pcm = devm_kzalloc(runtime->card->dev, sizeof(*pcm), GFP_KERNEL);
+	if (!pcm)
+		return -ENOMEM;
+
+	/* dai_link id is 1:1 mapped to the PCM device */
+	pcm->device = runtime->dai_link->id;
+	pcm->codec_dai = dai;
+
+	list_add_tail(&pcm->head, &priv->hdmi_pcm_list);
+
+	return 0;
+}
+
+static int sof_es8316_init(struct snd_soc_pcm_runtime *runtime)
+{
+	struct snd_soc_component *codec = asoc_rtd_to_codec(runtime, 0)->component;
+	struct snd_soc_card *card = runtime->card;
+	struct sof_es8336_private *priv = snd_soc_card_get_drvdata(card);
+	const struct snd_soc_dapm_route *custom_map;
+	int num_routes;
+	int ret;
+
+	card->dapm.idle_bias_off = true;
+
+	custom_map = sof_es8316_intmic_in1_map;
+	num_routes = ARRAY_SIZE(sof_es8316_intmic_in1_map);
+
+	ret = snd_soc_dapm_add_routes(&card->dapm, custom_map, num_routes);
+	if (ret)
+		return ret;
+
+	ret = snd_soc_card_jack_new(card, "Headset",
+				    SND_JACK_HEADSET | SND_JACK_BTN_0,
+				    &priv->jack, sof_es8316_jack_pins,
+				    ARRAY_SIZE(sof_es8316_jack_pins));
+	if (ret) {
+		dev_err(card->dev, "jack creation failed %d\n", ret);
+		return ret;
+	}
+
+	snd_jack_set_key(priv->jack.jack, SND_JACK_BTN_0, KEY_PLAYPAUSE);
+
+	snd_soc_component_set_jack(codec, &priv->jack, NULL);
+
+	return 0;
+}
+
+static void sof_es8316_exit(struct snd_soc_pcm_runtime *rtd)
+{
+	struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component;
+
+	snd_soc_component_set_jack(component, NULL, NULL);
+}
+
+static int sof_es8336_quirk_cb(const struct dmi_system_id *id)
+{
+	quirk = (unsigned long)id->driver_data;
+
+	if (quirk & SOF_ES8336_TGL_GPIO_QUIRK)
+		gpio_mapping = quirk_acpi_es8336_gpios;
+
+	return 1;
+}
+
+static const struct dmi_system_id sof_es8336_quirk_table[] = {
+	{
+		.callback = sof_es8336_quirk_cb,
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "CHUWI Innovation And Technology"),
+			DMI_MATCH(DMI_BOARD_NAME, "Hi10 X"),
+		},
+		.driver_data = (void *)SOF_ES8336_SSP_CODEC(2)
+	},
+	{
+		.callback = sof_es8336_quirk_cb,
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "IP3 tech"),
+			DMI_MATCH(DMI_BOARD_NAME, "WN1"),
+		},
+		.driver_data = (void *)(SOF_ES8336_SSP_CODEC(0) |
+					SOF_ES8336_TGL_GPIO_QUIRK |
+					SOF_ES8336_ENABLE_DMIC)
+	},
+	{}
+};
+
+static int sof_es8336_hw_params(struct snd_pcm_substream *substream,
+				struct snd_pcm_hw_params *params)
+{
+	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
+	struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
+	const int sysclk = 19200000;
+	int ret;
+
+	ret = snd_soc_dai_set_sysclk(codec_dai, 1, sysclk, SND_SOC_CLOCK_OUT);
+	if (ret < 0) {
+		dev_err(rtd->dev, "%s, Failed to set ES8336 SYSCLK: %d\n",
+			__func__, ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+/* machine stream operations */
+static struct snd_soc_ops sof_es8336_ops = {
+	.hw_params = sof_es8336_hw_params,
+};
+
+static struct snd_soc_dai_link_component platform_component[] = {
+	{
+		/* name might be overridden during probe */
+		.name = "0000:00:1f.3"
+	}
+};
+
+SND_SOC_DAILINK_DEF(ssp1_codec,
+	DAILINK_COMP_ARRAY(COMP_CODEC("i2c-ESSX8336:00", "ES8316 HiFi")));
+
+static struct snd_soc_dai_link_component dmic_component[] = {
+	{
+		.name = "dmic-codec",
+		.dai_name = "dmic-hifi",
+	}
+};
+
+static int sof_es8336_late_probe(struct snd_soc_card *card)
+{
+	struct sof_es8336_private *priv = snd_soc_card_get_drvdata(card);
+	struct sof_hdmi_pcm *pcm;
+
+	if (list_empty(&priv->hdmi_pcm_list))
+		return -ENOENT;
+
+	pcm = list_first_entry(&priv->hdmi_pcm_list, struct sof_hdmi_pcm, head);
+
+	return hda_dsp_hdmi_build_controls(card, pcm->codec_dai->component);
+}
+
+/* SoC card */
+static struct snd_soc_card sof_es8336_card = {
+	.name = "essx8336", /* sof- prefix added automatically */
+	.owner = THIS_MODULE,
+	.dapm_widgets = sof_es8316_widgets,
+	.num_dapm_widgets = ARRAY_SIZE(sof_es8316_widgets),
+	.dapm_routes = sof_es8316_audio_map,
+	.num_dapm_routes = ARRAY_SIZE(sof_es8316_audio_map),
+	.controls = sof_es8316_controls,
+	.num_controls = ARRAY_SIZE(sof_es8316_controls),
+	.fully_routed = true,
+	.late_probe = sof_es8336_late_probe,
+	.num_links = 1,
+};
+
+static struct snd_soc_dai_link *sof_card_dai_links_create(struct device *dev,
+							  int ssp_codec,
+							  int dmic_be_num,
+							  int hdmi_num)
+{
+	struct snd_soc_dai_link_component *cpus;
+	struct snd_soc_dai_link *links;
+	struct snd_soc_dai_link_component *idisp_components;
+	int hdmi_id_offset = 0;
+	int id = 0;
+	int i;
+
+	links = devm_kcalloc(dev, sof_es8336_card.num_links,
+			     sizeof(struct snd_soc_dai_link), GFP_KERNEL);
+	cpus = devm_kcalloc(dev, sof_es8336_card.num_links,
+			    sizeof(struct snd_soc_dai_link_component), GFP_KERNEL);
+	if (!links || !cpus)
+		goto devm_err;
+
+	/* codec SSP */
+	links[id].name = devm_kasprintf(dev, GFP_KERNEL,
+					"SSP%d-Codec", ssp_codec);
+	if (!links[id].name)
+		goto devm_err;
+
+	links[id].id = id;
+	links[id].codecs = ssp1_codec;
+	links[id].num_codecs = ARRAY_SIZE(ssp1_codec);
+	links[id].platforms = platform_component;
+	links[id].num_platforms = ARRAY_SIZE(platform_component);
+	links[id].init = sof_es8316_init;
+	links[id].exit = sof_es8316_exit;
+	links[id].ops = &sof_es8336_ops;
+	links[id].nonatomic = true;
+	links[id].dpcm_playback = 1;
+	links[id].dpcm_capture = 1;
+	links[id].no_pcm = 1;
+	links[id].cpus = &cpus[id];
+	links[id].num_cpus = 1;
+
+	links[id].cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL,
+						  "SSP%d Pin",
+						  ssp_codec);
+	if (!links[id].cpus->dai_name)
+		goto devm_err;
+
+	id++;
+
+	/* dmic */
+	if (dmic_be_num > 0) {
+		/* at least we have dmic01 */
+		links[id].name = "dmic01";
+		links[id].cpus = &cpus[id];
+		links[id].cpus->dai_name = "DMIC01 Pin";
+		links[id].init = dmic_init;
+		if (dmic_be_num > 1) {
+			/* set up 2 BE links at most */
+			links[id + 1].name = "dmic16k";
+			links[id + 1].cpus = &cpus[id + 1];
+			links[id + 1].cpus->dai_name = "DMIC16k Pin";
+			dmic_be_num = 2;
+		}
+	} else {
+		/* HDMI dai link starts at 3 according to current topology settings */
+		hdmi_id_offset = 2;
+	}
+
+	for (i = 0; i < dmic_be_num; i++) {
+		links[id].id = id;
+		links[id].num_cpus = 1;
+		links[id].codecs = dmic_component;
+		links[id].num_codecs = ARRAY_SIZE(dmic_component);
+		links[id].platforms = platform_component;
+		links[id].num_platforms = ARRAY_SIZE(platform_component);
+		links[id].ignore_suspend = 1;
+		links[id].dpcm_capture = 1;
+		links[id].no_pcm = 1;
+
+		id++;
+	}
+
+	/* HDMI */
+	if (hdmi_num > 0) {
+		idisp_components = devm_kzalloc(dev,
+						sizeof(struct snd_soc_dai_link_component) *
+						hdmi_num, GFP_KERNEL);
+		if (!idisp_components)
+			goto devm_err;
+	}
+
+	for (i = 1; i <= hdmi_num; i++) {
+		links[id].name = devm_kasprintf(dev, GFP_KERNEL,
+						"iDisp%d", i);
+		if (!links[id].name)
+			goto devm_err;
+
+		links[id].id = id + hdmi_id_offset;
+		links[id].cpus = &cpus[id];
+		links[id].num_cpus = 1;
+		links[id].cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL,
+							  "iDisp%d Pin", i);
+		if (!links[id].cpus->dai_name)
+			goto devm_err;
+
+		idisp_components[i - 1].name = "ehdaudio0D2";
+		idisp_components[i - 1].dai_name = devm_kasprintf(dev,
+								  GFP_KERNEL,
+								  "intel-hdmi-hifi%d",
+								  i);
+		if (!idisp_components[i - 1].dai_name)
+			goto devm_err;
+
+		links[id].codecs = &idisp_components[i - 1];
+		links[id].num_codecs = 1;
+		links[id].platforms = platform_component;
+		links[id].num_platforms = ARRAY_SIZE(platform_component);
+		links[id].init = sof_hdmi_init;
+		links[id].dpcm_playback = 1;
+		links[id].no_pcm = 1;
+
+		id++;
+	}
+
+	return links;
+
+devm_err:
+	return NULL;
+}
+
+ /* i2c-<HID>:00 with HID being 8 chars */
+static char codec_name[SND_ACPI_I2C_ID_LEN];
+
+static int sof_es8336_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct snd_soc_card *card;
+	struct snd_soc_acpi_mach *mach = pdev->dev.platform_data;
+	struct sof_es8336_private *priv;
+	struct acpi_device *adev;
+	struct snd_soc_dai_link *dai_links;
+	struct device *codec_dev;
+	int dmic_be_num = 0;
+	int hdmi_num = 3;
+	int ret;
+
+	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	card = &sof_es8336_card;
+	card->dev = dev;
+
+	if (!dmi_check_system(sof_es8336_quirk_table))
+		quirk = SOF_ES8336_SSP_CODEC(2);
+
+	if (quirk & SOF_ES8336_ENABLE_DMIC)
+		dmic_be_num = 2;
+
+	if (quirk_override != -1) {
+		dev_info(dev, "Overriding quirk 0x%lx => 0x%x\n",
+			 quirk, quirk_override);
+		quirk = quirk_override;
+	}
+	log_quirks(dev);
+
+	sof_es8336_card.num_links += dmic_be_num + hdmi_num;
+	dai_links = sof_card_dai_links_create(dev,
+					      SOF_ES8336_SSP_CODEC(quirk),
+					      dmic_be_num, hdmi_num);
+	if (!dai_links)
+		return -ENOMEM;
+
+	sof_es8336_card.dai_link = dai_links;
+
+	/* fixup codec name based on HID */
+	adev = acpi_dev_get_first_match_dev(mach->id, NULL, -1);
+	if (adev) {
+		snprintf(codec_name, sizeof(codec_name),
+			 "i2c-%s", acpi_dev_name(adev));
+		put_device(&adev->dev);
+		dai_links[0].codecs->name = codec_name;
+	}
+
+	ret = snd_soc_fixup_dai_links_platform_name(&sof_es8336_card,
+						    mach->mach_params.platform);
+	if (ret)
+		return ret;
+
+	/* get speaker enable GPIO */
+	codec_dev = bus_find_device_by_name(&i2c_bus_type, NULL, codec_name);
+	if (!codec_dev)
+		return -EPROBE_DEFER;
+
+	ret = devm_acpi_dev_add_driver_gpios(codec_dev, gpio_mapping);
+	if (ret)
+		dev_warn(codec_dev, "unable to add GPIO mapping table\n");
+
+	priv->gpio_pa = gpiod_get(codec_dev, "pa-enable", GPIOD_OUT_LOW);
+	if (IS_ERR(priv->gpio_pa)) {
+		ret = PTR_ERR(priv->gpio_pa);
+		dev_err(codec_dev, "%s, could not get pa-enable: %d\n",
+			__func__, ret);
+		goto err;
+	}
+
+	priv->codec_dev = codec_dev;
+	INIT_LIST_HEAD(&priv->hdmi_pcm_list);
+
+	snd_soc_card_set_drvdata(card, priv);
+
+	ret = devm_snd_soc_register_card(dev, card);
+	if (ret) {
+		gpiod_put(priv->gpio_pa);
+		dev_err(dev, "snd_soc_register_card failed: %d\n", ret);
+		goto err;
+	}
+	platform_set_drvdata(pdev, &sof_es8336_card);
+	return 0;
+
+err:
+	put_device(codec_dev);
+	return ret;
+}
+
+static int sof_es8336_remove(struct platform_device *pdev)
+{
+	struct snd_soc_card *card = platform_get_drvdata(pdev);
+	struct sof_es8336_private *priv = snd_soc_card_get_drvdata(card);
+
+	gpiod_put(priv->gpio_pa);
+	put_device(priv->codec_dev);
+
+	return 0;
+}
+
+static struct platform_driver sof_es8336_driver = {
+	.driver = {
+		.name = "sof-essx8336",
+		.pm = &snd_soc_pm_ops,
+	},
+	.probe = sof_es8336_probe,
+	.remove = sof_es8336_remove,
+};
+module_platform_driver(sof_es8336_driver);
+
+MODULE_DESCRIPTION("ASoC Intel(R) SOF + ES8336 Machine driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:sof-essx8336");
+MODULE_IMPORT_NS(SND_SOC_INTEL_HDA_DSP_COMMON);
diff --git a/sound/soc/intel/common/soc-acpi-intel-bxt-match.c b/sound/soc/intel/common/soc-acpi-intel-bxt-match.c
index 576407b5daf2..78cfdc48ad45 100644
--- a/sound/soc/intel/common/soc-acpi-intel-bxt-match.c
+++ b/sound/soc/intel/common/soc-acpi-intel-bxt-match.c
@@ -82,6 +82,12 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_bxt_machines[] = {
 		.sof_fw_filename = "sof-apl.ri",
 		.sof_tplg_filename = "sof-apl-tdf8532.tplg",
 	},
+	{
+		.id = "ESSX8336",
+		.drv_name = "sof-essx8336",
+		.sof_fw_filename = "sof-apl.ri",
+		.sof_tplg_filename = "sof-apl-es8336.tplg",
+	},
 	{},
 };
 EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_bxt_machines);
diff --git a/sound/soc/intel/common/soc-acpi-intel-cml-match.c b/sound/soc/intel/common/soc-acpi-intel-cml-match.c
index b591c6fd13fd..f03fcc0806ea 100644
--- a/sound/soc/intel/common/soc-acpi-intel-cml-match.c
+++ b/sound/soc/intel/common/soc-acpi-intel-cml-match.c
@@ -81,6 +81,12 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_cml_machines[] = {
 		.sof_fw_filename = "sof-cml.ri",
 		.sof_tplg_filename = "sof-cml-da7219-max98390.tplg",
 	},
+	{
+		.id = "ESSX8336",
+		.drv_name = "sof-essx8336",
+		.sof_fw_filename = "sof-cml.ri",
+		.sof_tplg_filename = "sof-cml-es8336.tplg",
+	},
 	{},
 };
 EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_cml_machines);
diff --git a/sound/soc/intel/common/soc-acpi-intel-glk-match.c b/sound/soc/intel/common/soc-acpi-intel-glk-match.c
index da1e151190b4..32fff9389eb3 100644
--- a/sound/soc/intel/common/soc-acpi-intel-glk-match.c
+++ b/sound/soc/intel/common/soc-acpi-intel-glk-match.c
@@ -49,7 +49,12 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_glk_machines[] = {
 		.sof_fw_filename = "sof-glk.ri",
 		.sof_tplg_filename = "sof-glk-cs42l42.tplg",
 	},
-
+	{
+		.id = "ESSX8336",
+		.drv_name = "sof-essx8336",
+		.sof_fw_filename = "sof-glk.ri",
+		.sof_tplg_filename = "sof-glk-es8336.tplg",
+	},
 	{},
 };
 EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_glk_machines);
diff --git a/sound/soc/intel/common/soc-acpi-intel-jsl-match.c b/sound/soc/intel/common/soc-acpi-intel-jsl-match.c
index 69ff7286d357..87923bcf9488 100644
--- a/sound/soc/intel/common/soc-acpi-intel-jsl-match.c
+++ b/sound/soc/intel/common/soc-acpi-intel-jsl-match.c
@@ -81,6 +81,12 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_jsl_machines[] = {
 		.quirk_data = &mx98360a_spk,
 		.sof_tplg_filename = "sof-jsl-cs42l42-mx98360a.tplg",
 	},
+	{
+		.id = "ESSX8336",
+		.drv_name = "sof-essx8336",
+		.sof_fw_filename = "sof-jsl.ri",
+		.sof_tplg_filename = "sof-jsl-es8336.tplg",
+	},
 	{},
 };
 EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_jsl_machines);
diff --git a/sound/soc/intel/common/soc-acpi-intel-tgl-match.c b/sound/soc/intel/common/soc-acpi-intel-tgl-match.c
index 11801b905ecc..c2c5337ed3b8 100644
--- a/sound/soc/intel/common/soc-acpi-intel-tgl-match.c
+++ b/sound/soc/intel/common/soc-acpi-intel-tgl-match.c
@@ -383,6 +383,12 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_tgl_machines[] = {
 		.sof_fw_filename = "sof-tgl.ri",
 		.sof_tplg_filename = "sof-tgl-rt1011-rt5682.tplg",
 	},
+	{
+		.id = "ESSX8336",
+		.drv_name = "sof-essx8336",
+		.sof_fw_filename = "sof-tgl.ri",
+		.sof_tplg_filename = "sof-tgl-es8336.tplg",
+	},
 	{},
 };
 EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_tgl_machines);
-- 
2.33.0



^ permalink raw reply	[flat|nested] 28+ messages in thread

* [d-kernel] [PATCH 2/9] commit 79b5808491cf152b808c51fecdafb221fa270cf1
  2022-04-04  6:28 ` [d-kernel] (no subject) nickel
  2022-04-04  6:28   ` [d-kernel] [PATCH 1/9] commit 0b220578c2aab3d5ac6b693117e8c5d22e8c2b34 nickel
@ 2022-04-04  6:28   ` nickel
  2022-04-04  6:28   ` [d-kernel] [PATCH 3/9] commit 8143959d503dd6b3c8b9802cee0f1eba82e8d844 nickel
                     ` (6 subsequent siblings)
  8 siblings, 0 replies; 28+ messages in thread
From: nickel @ 2022-04-04  6:28 UTC (permalink / raw)
  To: devel-kernel; +Cc: Vasily Vinogradov

From: Vasily Vinogradov <v.vinogradov@aq.ru>

    ASoC: Intel: sof_es8336: Add quirk for inverted jack detect
---
 sound/soc/intel/boards/sof_es8336.c | 20 ++++++++++++++++++++
 1 file changed, 20 insertions(+)

diff --git a/sound/soc/intel/boards/sof_es8336.c b/sound/soc/intel/boards/sof_es8336.c
index 20d577eaab6d..7966a61b22c8 100644
--- a/sound/soc/intel/boards/sof_es8336.c
+++ b/sound/soc/intel/boards/sof_es8336.c
@@ -26,6 +26,7 @@
 
 #define SOF_ES8336_TGL_GPIO_QUIRK		BIT(4)
 #define SOF_ES8336_ENABLE_DMIC			BIT(5)
+#define SOF_ES8336_JD_INVERTED			BIT(6)
 
 static unsigned long quirk;
 
@@ -33,6 +34,9 @@ static int quirk_override = -1;
 module_param_named(quirk, quirk_override, int, 0444);
 MODULE_PARM_DESC(quirk, "Board-specific quirk override");
 
+/* jd-inv + terminating entry */
+#define SOF_ES8336_PROPS_MAX	2
+
 struct sof_es8336_private {
 	struct device *codec_dev;
 	struct gpio_desc *gpio_pa;
@@ -64,6 +68,8 @@ static const struct acpi_gpio_mapping *gpio_mapping = acpi_es8336_gpios;
 static void log_quirks(struct device *dev)
 {
 	dev_info(dev, "quirk SSP%ld",  SOF_ES8336_SSP_CODEC(quirk));
+	dev_info(dev, "quirk JD_INVERTED %s\n",
+		 (quirk & SOF_ES8336_JD_INVERTED) ? "enabled" : "disabled");
 }
 
 static int sof_es8316_speaker_power_event(struct snd_soc_dapm_widget *w,
@@ -459,6 +465,8 @@ static int sof_es8336_probe(struct platform_device *pdev)
 	struct acpi_device *adev;
 	struct snd_soc_dai_link *dai_links;
 	struct device *codec_dev;
+	struct property_entry props[SOF_ES8336_PROPS_MAX] = {};
+	unsigned int cnt = 0;
 	int dmic_be_num = 0;
 	int hdmi_num = 3;
 	int ret;
@@ -511,6 +519,18 @@ static int sof_es8336_probe(struct platform_device *pdev)
 	if (!codec_dev)
 		return -EPROBE_DEFER;
 
+	if (quirk & SOF_ES8336_JD_INVERTED)
+		props[cnt++] = PROPERTY_ENTRY_BOOL("everest,jack-detect-inverted");
+
+	if (cnt) {
+		ret = device_add_properties(codec_dev, props);
+		if (ret) {
+			dev_err(codec_dev, "%s, could not add properties: %d\n",
+				__func__, ret);
+			goto err;
+		}
+	}
+
 	ret = devm_acpi_dev_add_driver_gpios(codec_dev, gpio_mapping);
 	if (ret)
 		dev_warn(codec_dev, "unable to add GPIO mapping table\n");
-- 
2.33.0



^ permalink raw reply	[flat|nested] 28+ messages in thread

* [d-kernel] [PATCH 3/9] commit 8143959d503dd6b3c8b9802cee0f1eba82e8d844
  2022-04-04  6:28 ` [d-kernel] (no subject) nickel
  2022-04-04  6:28   ` [d-kernel] [PATCH 1/9] commit 0b220578c2aab3d5ac6b693117e8c5d22e8c2b34 nickel
  2022-04-04  6:28   ` [d-kernel] [PATCH 2/9] commit 79b5808491cf152b808c51fecdafb221fa270cf1 nickel
@ 2022-04-04  6:28   ` nickel
  2022-04-04  6:28   ` [d-kernel] [PATCH 4/9] commit 796f9b0189299a221d4c822be216165dd2371852 nickel
                     ` (5 subsequent siblings)
  8 siblings, 0 replies; 28+ messages in thread
From: nickel @ 2022-04-04  6:28 UTC (permalink / raw)
  To: devel-kernel; +Cc: Vasily Vinogradov

From: Vasily Vinogradov <v.vinogradov@aq.ru>

    ASoC: es8316: Add power management
---
 sound/soc/codecs/es8316.c | 39 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 39 insertions(+)

diff --git a/sound/soc/codecs/es8316.c b/sound/soc/codecs/es8316.c
index 8f30a3ea8bfe..c63f3b300797 100644
--- a/sound/soc/codecs/es8316.c
+++ b/sound/soc/codecs/es8316.c
@@ -728,6 +728,8 @@ static int es8316_probe(struct snd_soc_component *component)
 		return ret;
 	}
 
+	snd_soc_component_init_regmap(component, es8316->regmap);
+
 	/* Reset codec and enable current state machine */
 	snd_soc_component_write(component, ES8316_RESET, 0x3f);
 	usleep_range(5000, 5500);
@@ -754,9 +756,43 @@ static void es8316_remove(struct snd_soc_component *component)
 {
 	struct es8316_priv *es8316 = snd_soc_component_get_drvdata(component);
 
+	snd_soc_component_exit_regmap(component);
+
 	clk_disable_unprepare(es8316->mclk);
 }
 
+#ifdef CONFIG_PM_SLEEP
+static int es8316_suspend(struct device *dev)
+{
+	struct es8316_priv *es8316 = dev_get_drvdata(dev);
+
+	dev_dbg(dev, "%s: Enter\n", __func__);
+
+	regcache_cache_only(es8316->regmap, true);
+	regcache_mark_dirty(es8316->regmap);
+
+	return 0;
+}
+
+static int es8316_resume(struct device *dev)
+{
+	struct es8316_priv *es8316 = dev_get_drvdata(dev);
+
+	dev_dbg(dev, "%s: Enter\n", __func__);
+
+	regcache_cache_only(es8316->regmap, false);
+	regcache_sync(es8316->regmap);
+
+	es8316_irq(es8316->irq, es8316);
+
+	return 0;
+}
+#endif
+
+static const struct dev_pm_ops es8316_pm = {
+	SET_SYSTEM_SLEEP_PM_OPS(es8316_suspend, es8316_resume)
+};
+
 static const struct snd_soc_component_driver soc_component_dev_es8316 = {
 	.probe			= es8316_probe,
 	.remove			= es8316_remove,
@@ -787,6 +823,8 @@ static const struct regmap_config es8316_regmap = {
 	.max_register = 0x53,
 	.volatile_table	= &es8316_volatile_table,
 	.cache_type = REGCACHE_RBTREE,
+	.use_single_read = true,
+	.use_single_write = true,
 };
 
 static int es8316_i2c_probe(struct i2c_client *i2c_client,
@@ -851,6 +889,7 @@ static struct i2c_driver es8316_i2c_driver = {
 		.name			= "es8316",
 		.acpi_match_table	= ACPI_PTR(es8316_acpi_match),
 		.of_match_table		= of_match_ptr(es8316_of_match),
+		.pm			= &es8316_pm,
 	},
 	.probe		= es8316_i2c_probe,
 	.id_table	= es8316_i2c_id,
-- 
2.33.0



^ permalink raw reply	[flat|nested] 28+ messages in thread

* [d-kernel] [PATCH 4/9] commit 796f9b0189299a221d4c822be216165dd2371852
  2022-04-04  6:28 ` [d-kernel] (no subject) nickel
                     ` (2 preceding siblings ...)
  2022-04-04  6:28   ` [d-kernel] [PATCH 3/9] commit 8143959d503dd6b3c8b9802cee0f1eba82e8d844 nickel
@ 2022-04-04  6:28   ` nickel
  2022-04-04  6:28   ` [d-kernel] [PATCH 5/9] commit f6a1611f744dcdd55c5adaf02f193083286dac34 nickel
                     ` (4 subsequent siblings)
  8 siblings, 0 replies; 28+ messages in thread
From: nickel @ 2022-04-04  6:28 UTC (permalink / raw)
  To: devel-kernel; +Cc: Vasily Vinogradov

From: Vasily Vinogradov <v.vinogradov@aq.ru>

    ASoC: es8316: Use increased GPIO debounce time
---
 sound/soc/codecs/es8316.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/sound/soc/codecs/es8316.c b/sound/soc/codecs/es8316.c
index c63f3b300797..9778c988e49e 100644
--- a/sound/soc/codecs/es8316.c
+++ b/sound/soc/codecs/es8316.c
@@ -553,7 +553,7 @@ static void es8316_enable_micbias_for_mic_gnd_short_detect(
 	snd_soc_dapm_sync_unlocked(dapm);
 	snd_soc_dapm_mutex_unlock(dapm);
 
-	msleep(20);
+	msleep(500);
 }
 
 static void es8316_disable_micbias_for_mic_gnd_short_detect(
-- 
2.33.0



^ permalink raw reply	[flat|nested] 28+ messages in thread

* [d-kernel] [PATCH 5/9] commit f6a1611f744dcdd55c5adaf02f193083286dac34
  2022-04-04  6:28 ` [d-kernel] (no subject) nickel
                     ` (3 preceding siblings ...)
  2022-04-04  6:28   ` [d-kernel] [PATCH 4/9] commit 796f9b0189299a221d4c822be216165dd2371852 nickel
@ 2022-04-04  6:28   ` nickel
  2022-04-04  6:28   ` [d-kernel] [PATCH 6/9] ALSA: intel-dspconfig: add ES8336 support for CNL nickel
                     ` (3 subsequent siblings)
  8 siblings, 0 replies; 28+ messages in thread
From: nickel @ 2022-04-04  6:28 UTC (permalink / raw)
  To: devel-kernel; +Cc: Vasily Vinogradov

From: Vasily Vinogradov <v.vinogradov@aq.ru>

    ASoC: codec: es8326: New codec driver
---
 sound/hda/intel-dsp-config.c                  |  10 +
 sound/soc/codecs/Kconfig                      |   5 +
 sound/soc/codecs/Makefile                     |   2 +
 sound/soc/codecs/es8326.c                     | 893 ++++++++++++++++++
 sound/soc/codecs/es8326.h                     | 222 +++++
 sound/soc/intel/boards/Kconfig                |   1 +
 sound/soc/intel/boards/sof_es8336.c           |   6 +
 .../intel/common/soc-acpi-intel-jsl-match.c   |   6 +
 .../intel/common/soc-acpi-intel-tgl-match.c   |   6 +
 9 files changed, 1151 insertions(+)
 create mode 100644 sound/soc/codecs/es8326.c
 create mode 100644 sound/soc/codecs/es8326.h

diff --git a/sound/hda/intel-dsp-config.c b/sound/hda/intel-dsp-config.c
index f63114317ac9..9ef023882ae0 100644
--- a/sound/hda/intel-dsp-config.c
+++ b/sound/hda/intel-dsp-config.c
@@ -311,6 +311,11 @@ static const struct config_entry config_table[] = {
 
 /* JasperLake */
 #if IS_ENABLED(CONFIG_SND_SOC_SOF_JASPERLAKE)
+	{
+		.flags = FLAG_SOF,
+		.device = 0x4dc8,
+		.codec_hid = "ESSX8326",
+	},
 	{
 		.flags = FLAG_SOF,
 		.device = 0x4dc8,
@@ -333,6 +338,11 @@ static const struct config_entry config_table[] = {
 			{}
 		}
 	},
+	{
+		.flags = FLAG_SOF,
+		.device = 0xa0c8,
+		.codec_hid = "ESSX8326",
+	},
 	{
 		.flags = FLAG_SOF,
 		.device = 0xa0c8,
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index f12c9b942678..c15d66636161 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -92,6 +92,7 @@ config SND_SOC_ALL_CODECS
 	imply SND_SOC_DA9055
 	imply SND_SOC_DMIC
 	imply SND_SOC_ES8316
+	imply SND_SOC_ES8326
 	imply SND_SOC_ES8328_SPI
 	imply SND_SOC_ES8328_I2C
 	imply SND_SOC_ES7134
@@ -820,6 +821,10 @@ config SND_SOC_ES8316
 	tristate "Everest Semi ES8316 CODEC"
 	depends on I2C
 
+config SND_SOC_ES8326
+	tristate "Everest Semi ES8326 CODEC"
+	depends on I2C
+
 config SND_SOC_ES8328
 	tristate
 
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index 8dcea2c4604a..fe0adc94b11f 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -90,6 +90,7 @@ snd-soc-dmic-objs := dmic.o
 snd-soc-es7134-objs := es7134.o
 snd-soc-es7241-objs := es7241.o
 snd-soc-es8316-objs := es8316.o
+snd-soc-es8326-objs := es8326.o
 snd-soc-es8328-objs := es8328.o
 snd-soc-es8328-i2c-objs := es8328-i2c.o
 snd-soc-es8328-spi-objs := es8328-spi.o
@@ -421,6 +422,7 @@ obj-$(CONFIG_SND_SOC_DMIC)	+= snd-soc-dmic.o
 obj-$(CONFIG_SND_SOC_ES7134)	+= snd-soc-es7134.o
 obj-$(CONFIG_SND_SOC_ES7241)	+= snd-soc-es7241.o
 obj-$(CONFIG_SND_SOC_ES8316)    += snd-soc-es8316.o
+obj-$(CONFIG_SND_SOC_ES8326)    += snd-soc-es8326.o
 obj-$(CONFIG_SND_SOC_ES8328)	+= snd-soc-es8328.o
 obj-$(CONFIG_SND_SOC_ES8328_I2C)+= snd-soc-es8328-i2c.o
 obj-$(CONFIG_SND_SOC_ES8328_SPI)+= snd-soc-es8328-spi.o
diff --git a/sound/soc/codecs/es8326.c b/sound/soc/codecs/es8326.c
new file mode 100644
index 000000000000..92dd3757a3c5
--- /dev/null
+++ b/sound/soc/codecs/es8326.c
@@ -0,0 +1,893 @@
+/*
+ * es8326.c -- es8326 ALSA SoC audio driver
+ *
+ * Copyright (c) 2016 Rockchip Electronics Co. Ltd.
+ *
+ * Author: Mark Brown <will@everset-semi.com>
+ * Author: Jianqun Xu <jay.xu@rock-chips.com>
+ * Author: Nickey Yang <nickey.yang@rock-chips.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/i2c.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/of_gpio.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/tlv.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/initval.h>
+#include <linux/proc_fs.h>
+#include <linux/gpio.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <sound/jack.h>
+#include "es8326.h"
+
+/* codec private data */
+struct es8326_priv {
+	struct mutex lock;
+	struct clk *mclk;
+	struct regmap *regmap;
+	struct snd_soc_component *component;
+	struct snd_soc_jack *jack;
+	int irq;
+	unsigned int sysclk;
+	struct snd_pcm_hw_constraint_list sysclk_constraints;
+	bool spk_gpio_level;
+	bool jd_inverted;
+};
+
+/*
+ * ES8326 controls
+ */
+static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(es8326_dac_vol_tlv, -9550, 50, 0);
+static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(es8326_adc_vol_tlv, -9550, 50, 0);
+static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(es8326_adc_pga_tlv, 0, 600, 0);
+static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(es8326_softramp_rate, 0, 100, 0);
+static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(es8326_drc_target_tlv, -3200,
+					     200, 0);
+static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(es8326_drc_recovery_tlv, -125,
+					     250, 0);
+
+static const char * const es8326_winsize[] = {
+	"0.25db/2 LRCK",
+	"0.25db/4 LRCK",
+	"0.25db/8 LRCK",
+	"0.25db/16 LRCK",
+	"0.25db/32 LRCK",
+	"0.25db/64 LRCK",
+	"0.25db/128 LRCK",
+	"0.25db/256 LRCK",
+	"0.25db/512 LRCK",
+	"0.25db/1024 LRCK",
+	"0.25db/2048 LRCK",
+	"0.25db/4096 LRCK",
+	"0.25db/8192 LRCK",
+	"0.25db/16384 LRCK",
+	"0.25db/32768 LRCK",
+	"0.25db/65536 LRCK",
+};
+
+static const char * const es8326_dacpol_txt[] = {
+	"Normal", "R Invert", "L Invert", "L + R Invert"
+};
+static const struct soc_enum es8326_dacpol =
+	SOC_ENUM_SINGLE(ES8326_DAC_DSM, 4, ARRAY_SIZE(es8326_dacpol_txt),
+			es8326_dacpol_txt);
+static const struct soc_enum es8326_alc_winsize =
+	SOC_ENUM_SINGLE(ES8326_ADC_RAMPRATE, 4, ARRAY_SIZE(es8326_winsize),
+			es8326_winsize);
+static const struct soc_enum es8326_drc_winsize =
+	SOC_ENUM_SINGLE(ES8326_DRC_WINSIZE, 4, ARRAY_SIZE(es8326_winsize),
+			es8326_winsize);
+
+static const struct snd_kcontrol_new es8326_snd_controls[] = {
+	SOC_SINGLE_TLV("DAC Playback Volume", ES8326_DAC_VOL, 0, 0xff, 0,
+		       es8326_dac_vol_tlv),
+	SOC_ENUM("Playback Polarity", es8326_dacpol),
+	SOC_SINGLE_TLV("DAC Ramp Rate", ES8326_DAC_RAMPRATE, 0, 0x0f, 0,
+		       es8326_softramp_rate),
+	SOC_SINGLE("DRC Switch", ES8326_DRC_RECOVERY, 3, 1, 0),
+	SOC_SINGLE_TLV("DRC Recovery Level", ES8326_DRC_RECOVERY, 0, 4, 0,
+		       es8326_drc_recovery_tlv),
+	SOC_ENUM("DRC Winsize", es8326_drc_winsize),
+	SOC_SINGLE_TLV("DRC Target Level", ES8326_DRC_WINSIZE, 0, 0x0f, 0,
+		       es8326_drc_target_tlv),
+
+	SOC_DOUBLE_R_TLV("ADC Capture Volume", ES8326_ADC1_VOL,
+			 ES8326_ADC2_VOL, 0, 0xff, 0, es8326_adc_vol_tlv),
+	SOC_DOUBLE_TLV("ADC PGA Gain Volume", ES8326_ADC_SCALE, 4, 0, 5, 0,
+		       es8326_adc_pga_tlv),
+	SOC_SINGLE_TLV("ADC Ramp Rate", ES8326_ADC_RAMPRATE, 0, 0x0f, 0,
+		       es8326_softramp_rate),
+	SOC_SINGLE("ALC Switch", ES8326_ALC_RECOVERY, 3, 1, 0),
+	SOC_SINGLE_TLV("ALC Recovery Level", ES8326_ALC_LEVEL, 0, 4, 0,
+		       es8326_drc_recovery_tlv),
+	SOC_ENUM("ALC Winsize", es8326_alc_winsize),
+	SOC_SINGLE_TLV("ALC Target Level", ES8326_ALC_LEVEL, 0, 0x0f, 0,
+		       es8326_drc_target_tlv),
+};
+
+static const char * const es8326_adc_src_txt[] = {
+	"Analog MIC", "DMIC SDINOUT2"
+};
+static const unsigned int es8326_adc_src_values[] = { 0, 0x44 };
+static const struct soc_enum es8326_adc1_src_enum =
+	SOC_VALUE_ENUM_SINGLE(ES8326_ADC1_SRC, 0, 0xff,
+			      ARRAY_SIZE(es8326_adc_src_txt),
+			      es8326_adc_src_txt,
+			      es8326_adc_src_values);
+static const struct snd_kcontrol_new es8326_mic_mux_controls =
+	SOC_DAPM_ENUM("Route", es8326_adc1_src_enum);
+
+static const struct snd_soc_dapm_widget es8326_dapm_widgets[] = {
+	SND_SOC_DAPM_REG(snd_soc_dapm_supply, "Mic Bias", ES8326_ANA_MICBIAS,
+			 2, 0x3, 3, 0),
+
+	SND_SOC_DAPM_INPUT("MIC1"),
+	SND_SOC_DAPM_INPUT("MIC2"),
+
+	SND_SOC_DAPM_MUX("Mic Mux", SND_SOC_NOPM, 0, 0,
+			 &es8326_mic_mux_controls),
+
+    	/* Digital Interface */
+	SND_SOC_DAPM_AIF_OUT("I2S OUT", "I2S1 Capture", 0, SND_SOC_NOPM, 0, 0),
+	SND_SOC_DAPM_AIF_IN("I2S IN", "I2S1 Playback", 0, SND_SOC_NOPM, 0, 0),
+
+	SND_SOC_DAPM_DAC("Right DAC", NULL, ES8326_ANA_PWR, 0, 1),
+	SND_SOC_DAPM_DAC("Left DAC", NULL, ES8326_ANA_PWR, 1, 1),
+	SND_SOC_DAPM_PGA("LHPMIX", ES8326_DAC2HPMIX, 7, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("RHPMIX", ES8326_DAC2HPMIX, 3, 0, NULL, 0),
+	SND_SOC_DAPM_SUPPLY("HPOR Cal", ES8326_HP_CTL, 7, 1, NULL, 0),
+	SND_SOC_DAPM_SUPPLY("HPOL Cal", ES8326_HP_CTL, 3, 1, NULL, 0),
+	SND_SOC_DAPM_REG(snd_soc_dapm_supply, "HPOR Supply", ES8326_HP_CTL,
+			 4, 0x7, 7, 0),
+	SND_SOC_DAPM_REG(snd_soc_dapm_supply, "HPOL Supply", ES8326_HP_CTL,
+			 0, 0x7, 7, 0),
+	SND_SOC_DAPM_OUTPUT("HPOL"),
+	SND_SOC_DAPM_OUTPUT("HPOR"),
+};
+
+static const struct snd_soc_dapm_route es8326_dapm_routes[] = {
+	/* Recording */
+	{"MIC1", NULL, "Mic Bias"},
+	{"MIC2", NULL, "Mic Bias"},
+
+	{"Mic Mux", "DMIC SDINOUT2", "MIC1"},
+	{"Mic Mux", "Analog MIC", "MIC2"},
+
+	{"I2S OUT", NULL, "Mic Mux"},
+
+	/* Playback */
+	{"Right DAC", NULL, "I2S IN"},
+	{"Left DAC", NULL, "I2S IN"},
+
+	{"LHPMIX", NULL, "Left DAC"},
+	{"RHPMIX", NULL, "Right DAC"},
+
+	{"HPOR", NULL , "HPOR Cal"},
+	{"HPOL", NULL , "HPOL Cal"},
+
+	{"HPOR", NULL , "HPOR Supply"},
+	{"HPOL", NULL , "HPOL Supply"},
+
+	{"HPOL", NULL, "LHPMIX"},
+	{"HPOR", NULL, "RHPMIX"},
+};
+
+struct es8326_clk_coeff {
+	u16 fs;
+	u32 rate;
+	u32 mclk;
+	u8 reg4;
+	u8 reg5;
+	u8 reg6;
+	u8 reg7;
+	u8 reg8;
+	u8 reg9;
+	u8 rega;
+	u8 regb;
+};
+
+/* codec hifi mclk clock divider coefficients */
+static const struct es8326_clk_coeff es8326_coeff_div[] = {
+	{  32,  8000,   256000, 0x60, 0x00, 0x0f, 0x75, 0x0a, 0x1b, 0x1f, 0x7f},
+	{  32, 16000,   512000, 0x20, 0x00, 0x0d, 0x75, 0x0a, 0x1b, 0x1f, 0x3f},
+	{  32, 44100,  1411200, 0x00, 0x00, 0x13, 0x2d, 0x0a, 0x0a, 0x1f, 0x1f},
+	{  32, 48000,  1536000, 0x00, 0x00, 0x13, 0x2d, 0x0a, 0x0a, 0x1f, 0x1f},
+	{  36,  8000,   288000, 0x20, 0x00, 0x0d, 0x75, 0x0a, 0x1b, 0x23, 0x47},
+	{  36, 16000,   576000, 0x20, 0x00, 0x0d, 0x75, 0x0a, 0x1b, 0x23, 0x47},
+	{  48,  8000,   384000, 0x60, 0x02, 0x1f, 0x75, 0x0a, 0x1b, 0x1f, 0x7f},
+	{  48, 16000,   768000, 0x20, 0x02, 0x0f, 0x75, 0x0a, 0x1b, 0x1f, 0x3f},
+	{  48, 48000,  2304000, 0x00, 0x02, 0x0d, 0x2d, 0x0a, 0x0a, 0x1f, 0x1f},
+	{  64,  8000,   512000, 0x60, 0x00, 0x0d, 0x75, 0x0a, 0x1b, 0x1f, 0x7f},
+	{  64, 16000,  1024000, 0x20, 0x00, 0x05, 0x75, 0x0a, 0x1b, 0x1f, 0x3f},
+
+	{  64, 44100,  2822400, 0x00, 0x00, 0x11, 0x2d, 0x0a, 0x0a, 0x1f, 0x1f},
+	{  64, 48000,  3072000, 0x00, 0x00, 0x11, 0x2d, 0x0a, 0x0a, 0x1f, 0x1f},
+	{  72,  8000,   576000, 0x20, 0x00, 0x13, 0x35, 0x0a, 0x1b, 0x23, 0x47},
+	{  72, 16000,  1152000, 0x20, 0x00, 0x05, 0x75, 0x0a, 0x1b, 0x23, 0x47},
+	{  96,  8000,   768000, 0x60, 0x02, 0x1d, 0x75, 0x0a, 0x1b, 0x1f, 0x7f},
+	{  96, 16000,  1536000, 0x20, 0x02, 0x0d, 0x75, 0x0a, 0x1b, 0x1f, 0x3f},
+	{ 100, 48000,  4800000, 0x04, 0x04, 0x1f, 0x2d, 0x0a, 0x0a, 0x1f, 0x1f},
+	{ 125, 48000,  6000000, 0x04, 0x04, 0x1f, 0x2d, 0x0a, 0x0a, 0x27, 0x27},
+	{ 128,  8000,  1024000, 0x60, 0x00, 0x13, 0x35, 0x0a, 0x1b, 0x1f, 0x7f},
+	{ 128, 16000,  2048000, 0x20, 0x00, 0x11, 0x35, 0x0a, 0x1b, 0x1f, 0x3f},
+
+	{ 128, 44100,  5644800, 0x00, 0x00, 0x01, 0x2d, 0x0a, 0x0a, 0x1f, 0x1f},
+	{ 128, 48000,  6144000, 0x00, 0x00, 0x01, 0x2d, 0x0a, 0x0a, 0x1f, 0x1f},
+	{ 144,  8000,  1152000, 0x20, 0x00, 0x03, 0x35, 0x0a, 0x1b, 0x23, 0x47},
+	{ 144, 16000,  2304000, 0x20, 0x00, 0x11, 0x35, 0x0a, 0x1b, 0x23, 0x47},
+	{ 192,  8000,  1536000, 0x60, 0x02, 0x0d, 0x75, 0x0a, 0x1b, 0x1f, 0x7f},
+	{ 192, 16000,  3072000, 0x20, 0x02, 0x05, 0x75, 0x0a, 0x1b, 0x1f, 0x3f},
+	{ 200, 48000,  9600000, 0x04, 0x04, 0x0f, 0x2d, 0x0a, 0x0a, 0x1f, 0x1f},
+	{ 250, 48000, 12000000, 0x04, 0x04, 0x0f, 0x2d, 0x0a, 0x0a, 0x27, 0x27},
+	{ 256,  8000,  2048000, 0x60, 0x00, 0x11, 0x35, 0x0a, 0x1b, 0x1f, 0x7f},
+	{ 256, 16000,  4096000, 0x20, 0x00, 0x01, 0x35, 0x0a, 0x1b, 0x1f, 0x3f},
+
+	{ 256, 44100, 11289600, 0x00, 0x00, 0x10, 0x2d, 0x0a, 0x0a, 0x1f, 0x1f},
+	{ 256, 48000, 12288000, 0x00, 0x00, 0x10, 0x2d, 0x0a, 0x0a, 0x1f, 0x1f},
+	{ 288,  8000,  2304000, 0x20, 0x00, 0x01, 0x35, 0x0a, 0x1b, 0x23, 0x47},
+	{ 384,  8000,  3072000, 0x60, 0x02, 0x05, 0x75, 0x0a, 0x1b, 0x1f, 0x7f},
+	{ 384, 16000,  6144000, 0x20, 0x02, 0x03, 0x35, 0x0a, 0x1b, 0x1f, 0x3f},
+	{ 384, 48000, 18432000, 0x00, 0x02, 0x01, 0x2d, 0x0a, 0x0a, 0x1f, 0x1f},
+	{ 400, 48000, 19200000, 0x09, 0x04, 0x0f, 0x6d, 0x3a, 0x0a, 0x4f, 0x1f},
+	{ 500, 48000, 24000000, 0x18, 0x04, 0x1f, 0x2d, 0x0a, 0x0a, 0x1f, 0x1f},
+	{ 512,  8000,  4096000, 0x60, 0x00, 0x01, 0x35, 0x0a, 0x1b, 0x1f, 0x7f},
+	{ 512, 16000,  8192000, 0x20, 0x00, 0x10, 0x35, 0x0a, 0x1b, 0x1f, 0x3f},
+
+	{ 512, 44100, 22579200, 0x00, 0x00, 0x00, 0x2d, 0x0a, 0x0a, 0x1f, 0x1f},
+	{ 512, 48000, 24576000, 0x00, 0x00, 0x00, 0x2d, 0x0a, 0x0a, 0x1f, 0x1f},
+	{ 768,  8000,  6144000, 0x60, 0x02, 0x11, 0x35, 0x0a, 0x1b, 0x1f, 0x7f},
+	{ 768, 16000, 12288000, 0x20, 0x02, 0x01, 0x35, 0x0a, 0x1b, 0x1f, 0x3f},
+	{ 800, 48000, 38400000, 0x00, 0x18, 0x13, 0x2d, 0x0a, 0x0a, 0x1f, 0x1f},
+	{ 812, 16000, 13000000, 0x0c, 0x04, 0x0f, 0x2d, 0x0a, 0x0a, 0x31, 0x31},
+	{1024,  8000,  8192000, 0x60, 0x00, 0x10, 0x35, 0x0a, 0x1b, 0x1f, 0x7f},
+	{1024, 16000, 16384000, 0x20, 0x00, 0x00, 0x35, 0x0a, 0x1b, 0x1f, 0x3f},
+	{1152, 16000, 18432000, 0x20, 0x08, 0x11, 0x35, 0x0a, 0x1b, 0x1f, 0x3f},
+	{1536,  8000, 12288000, 0x60, 0x02, 0x01, 0x35, 0x0a, 0x1b, 0x1f, 0x7f},
+
+	{1536, 16000, 24576000, 0x20, 0x02, 0x10, 0x35, 0x0a, 0x1b, 0x1f, 0x3f},
+	{1625,  8000, 13000000, 0x0c, 0x18, 0x1f, 0x2d, 0x0a, 0x0a, 0x27, 0x27},
+	{1625, 16000, 26000000, 0x0c, 0x18, 0x1f, 0x2d, 0x0a, 0x0a, 0x27, 0x27},
+	{2048,  8000, 16384000, 0x60, 0x00, 0x00, 0x35, 0x0a, 0x1b, 0x1f, 0x7f},
+	{2304,  8000, 18432000, 0x40, 0x02, 0x10, 0x35, 0x0a, 0x1b, 0x1f, 0x5f},
+	{3072,  8000, 24576000, 0x60, 0x02, 0x10, 0x35, 0x0a, 0x1b, 0x1f, 0x7f},
+	{3250,  8000, 26000000, 0x0c, 0x18, 0x0f, 0x2d, 0x0a, 0x0a, 0x27, 0x27},
+	{  21, 48000,  1024320, 0x00, 0x00, 0x09, 0x2d, 0x0a, 0x0a, 0x1f, 0x1f},
+	{ 541, 48000, 26000000, 0x00, 0x00, 0x00, 0x35, 0x0a, 0x1b, 0x20, 0x20},
+};
+
+static const struct es8326_clk_coeff *es8326_get_coeff(int mclk, int rate)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(es8326_coeff_div); i++) {
+		if (es8326_coeff_div[i].rate == rate &&
+		    es8326_coeff_div[i].mclk == mclk)
+			return &es8326_coeff_div[i];
+	}
+
+	return NULL;
+}
+
+/* The set of rates we can generate from the above for each SYSCLK */
+
+static unsigned int es8326_rates_12288[] = {
+	8000, 12000, 16000, 24000, 24000, 32000, 48000, 96000,
+};
+
+static struct snd_pcm_hw_constraint_list es8326_constraints_12288 = {
+	.count = ARRAY_SIZE(es8326_rates_12288),
+	.list = es8326_rates_12288,
+};
+
+static unsigned int es8326_rates_112896[] = {
+	8000, 11025, 22050, 44100,
+};
+
+static struct snd_pcm_hw_constraint_list es8326_constraints_112896 = {
+	.count = ARRAY_SIZE(es8326_rates_112896),
+	.list = es8326_rates_112896,
+};
+
+static unsigned int es8326_rates_12[] = {
+	8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000,
+	48000, 88235, 96000,
+};
+
+static struct snd_pcm_hw_constraint_list es8326_constraints_12 = {
+	.count = ARRAY_SIZE(es8326_rates_12),
+	.list = es8326_rates_12,
+};
+
+/*
+ * Note that this should be called from init rather than from hw_params.
+ */
+static int es8326_set_dai_sysclk(struct snd_soc_dai *codec_dai,
+				 int clk_id, unsigned int freq, int dir)
+{
+	struct snd_soc_component *component = codec_dai->component;
+	struct es8326_priv *es8326 = snd_soc_component_get_drvdata(component);
+	int ret;
+
+	es8326->sysclk = freq;
+
+	if (freq == 0) {
+		es8326->sysclk_constraints.list = NULL;
+		es8326->sysclk_constraints.count = 0;
+
+		return 0;
+	}
+
+	ret = clk_set_rate(es8326->mclk, freq);
+	if (ret)
+		return ret;
+
+	switch (freq) {
+	case 11289600:
+	case 18432000:
+	case 22579200:
+	case 36864000:
+		es8326->sysclk_constraints = es8326_constraints_112896;
+		return 0;
+
+	case 12288000:
+	case 16934400:
+	case 24576000:
+	case 33868800:
+		es8326->sysclk_constraints = es8326_constraints_12288;
+		return 0;
+
+	case 12000000:
+	case 19200000:
+	case 24000000:
+		es8326->sysclk_constraints = es8326_constraints_12;
+		return 0;
+
+	default:
+		return -EINVAL;
+	}
+}
+
+static int es8326_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
+{
+	struct snd_soc_component *component = codec_dai->component;
+	u8 iface;
+
+	/* interface format */
+	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+	case SND_SOC_DAIFMT_I2S:
+		iface = ES8326_FMT_SDP_FMT_I2S;
+		break;
+	case SND_SOC_DAIFMT_LEFT_J:
+		iface = ES8326_FMT_SDP_FMT_LJ;
+		break;
+	case SND_SOC_DAIFMT_DSP_A:
+	case SND_SOC_DAIFMT_DSP_B:
+		iface = ES8326_FMT_SDP_FMT_DSP;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	snd_soc_component_write(component, ES8326_FMT, iface);
+	snd_soc_component_update_bits(component, ES8326_FMT,
+				      ES8326_FMT_SDP_FMT_MASK, iface);
+
+	return 0;
+}
+
+static int es8326_pcm_startup(struct snd_pcm_substream *substream,
+			      struct snd_soc_dai *dai)
+{
+	struct snd_soc_component *component = dai->component;
+	struct es8326_priv *es8326 = snd_soc_component_get_drvdata(component);
+
+	/* The set of sample rates that can be supported depends on the
+	 * MCLK supplied to the CODEC - enforce this.
+	 */
+
+	if (es8326->sysclk_constraints.list)
+		snd_pcm_hw_constraint_list(substream->runtime, 0,
+					   SNDRV_PCM_HW_PARAM_RATE,
+					   &es8326->sysclk_constraints);
+
+	return 0;
+}
+
+static int es8326_pcm_hw_params(struct snd_pcm_substream *substream,
+				struct snd_pcm_hw_params *params,
+				struct snd_soc_dai *dai)
+{
+	struct snd_soc_component *component = dai->component;
+	struct es8326_priv *es8326 = snd_soc_component_get_drvdata(component);
+	const struct es8326_clk_coeff *coeff;
+	u8 wordlen;
+
+	coeff = es8326_get_coeff(es8326->sysclk, params_rate(params));
+	if (!coeff)
+		return -EINVAL;
+
+	/* bit size */
+	switch (params_format(params)) {
+	case SNDRV_PCM_FORMAT_S16_LE:
+		wordlen = ES8326_FMT_SDP_WL_16;
+		break;
+	case SNDRV_PCM_FORMAT_S20_3LE:
+		wordlen = ES8326_FMT_SDP_WL_20;
+		break;
+	case SNDRV_PCM_FORMAT_S18_3LE:
+		wordlen = ES8326_FMT_SDP_WL_18;
+		break;
+	case SNDRV_PCM_FORMAT_S24_LE:
+		wordlen = ES8326_FMT_SDP_WL_24;
+		break;
+	case SNDRV_PCM_FORMAT_S32_LE:
+		wordlen = ES8326_FMT_SDP_WL_32;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	snd_soc_component_update_bits(component, ES8326_FMT,
+				      ES8326_FMT_SDP_WL_MASK, wordlen);
+
+	snd_soc_component_write(component, ES8326_CLK_DIV1, coeff->reg4);
+	snd_soc_component_write(component, ES8326_CLK_DIV2, coeff->reg5);
+	snd_soc_component_write(component, ES8326_CLK_DLL, coeff->reg6);
+	snd_soc_component_write(component, ES8326_CLK_MUX, coeff->reg7);
+	snd_soc_component_write(component, ES8326_CLK_ADC_SEL, coeff->reg8);
+	snd_soc_component_write(component, ES8326_CLK_DAC_SEL, coeff->reg9);
+	snd_soc_component_write(component, ES8326_CLK_ADC_OSR, coeff->rega);
+	snd_soc_component_write(component, ES8326_CLK_DAC_OSR, coeff->regb);
+	return 0;
+}
+
+static int es8326_mute(struct snd_soc_dai *dai, int mute, int stream)
+{
+	switch (stream) {
+	case SNDRV_PCM_STREAM_PLAYBACK:
+		snd_soc_component_update_bits(dai->component, ES8326_DAC_MUTE,
+				ES8326_DAC_MUTE_S2P_MUTE_MASK,
+				mute ?  ES8326_DAC_MUTE_S2P_MUTE_MASK : 0);
+		break;
+	case SNDRV_PCM_STREAM_CAPTURE:
+		snd_soc_component_update_bits(dai->component, ES8326_ADC_MUTE,
+				ES8326_ADC_MUTE_P2S_MUTE_MASK,
+				mute ? ES8326_ADC_MUTE_P2S_MUTE_MASK : 0);
+		break;
+	}
+
+	return 0;
+}
+
+#define ES8326_FORMATS	(SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
+			 SNDRV_PCM_FMTBIT_S24_LE)
+
+static struct snd_soc_dai_ops es8326_ops = {
+	.startup = es8326_pcm_startup,
+	.hw_params = es8326_pcm_hw_params,
+	.set_fmt = es8326_set_dai_fmt,
+	.set_sysclk = es8326_set_dai_sysclk,
+	.mute_stream = es8326_mute,
+};
+
+static struct snd_soc_dai_driver es8326_dai = {
+	.name = "ES8316 HiFi",
+	.playback = {
+		.stream_name = "Playback",
+		.channels_min = 1,
+		.channels_max = 2,
+		.rates = SNDRV_PCM_RATE_8000_96000,
+		.formats = ES8326_FORMATS,
+	},
+	.capture = {
+		.stream_name = "Capture",
+		.channels_min = 1,
+		.channels_max = 2,
+		.rates = SNDRV_PCM_RATE_8000_96000,
+		.formats = ES8326_FORMATS,
+	},
+	.ops = &es8326_ops,
+	.symmetric_rate = 1,
+};
+
+static void es8326_enable_micbias_for_mic_gnd_short_detect(
+					struct snd_soc_component *component)
+{
+	struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component);
+
+	snd_soc_dapm_force_enable_pin(dapm, "Mic Bias");
+
+	msleep(500);
+}
+
+static void es8326_disable_micbias_for_mic_gnd_short_detect(
+					struct snd_soc_component *component)
+{
+	struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component);
+
+	snd_soc_dapm_disable_pin(dapm, "Mic Bias");
+}
+
+static irqreturn_t es8326_irq(int irq, void *data)
+{
+	struct es8326_priv *es8326 = data;
+	struct snd_soc_component *comp = es8326->component;
+	unsigned int flags;
+
+	mutex_lock(&es8326->lock);
+
+	/* Catch spurious IRQ before set_jack is called */
+	if (!es8326->jack)
+		goto out;
+
+	es8326_enable_micbias_for_mic_gnd_short_detect(comp);
+
+	regmap_read(es8326->regmap, ES8326_HP_DETECT, &flags);
+	if (es8326->jd_inverted)
+		flags ^= ES8326_HP_DETECT_NOT_INSERTED;
+
+	dev_dbg(comp->dev, "flags: %#04x\n", flags);
+	if (flags & ES8326_HP_DETECT_NOT_INSERTED) {
+		snd_soc_jack_report(es8326->jack, 0,
+				    SND_JACK_HEADSET | SND_JACK_BTN_0);
+		dev_dbg(comp->dev, "jack unplugged\n");
+	} else {
+		if (flags & ES8326_HP_DETECT_GM_NOT_SHORTED) {
+			dev_dbg(comp->dev, "headphones detected\n");
+			snd_soc_jack_report(es8326->jack, SND_JACK_HEADPHONE,
+					    SND_JACK_HEADSET);
+		} else {
+			dev_dbg(comp->dev, "headset detected\n");
+			snd_soc_jack_report(es8326->jack, SND_JACK_HEADSET,
+					    SND_JACK_HEADSET);
+		}
+	}
+
+	if (!(es8326->jack->status & SND_JACK_MICROPHONE))
+		es8326_disable_micbias_for_mic_gnd_short_detect(comp);
+out:
+	mutex_unlock(&es8326->lock);
+	return IRQ_HANDLED;
+}
+
+static void es8326_enable_jack_detect(struct snd_soc_component *component,
+				      struct snd_soc_jack *jack)
+{
+	struct es8326_priv *es8326 = snd_soc_component_get_drvdata(component);
+
+	/*
+	 * Init es8326->jd_inverted here and not in the probe, as we cannot
+	 * guarantee that the sof-essx8336 driver, which might set this
+	 * property, will probe before us.
+	 */
+	es8326->jd_inverted =
+		device_property_read_bool(component->dev,
+					  "everest,jack-detect-inverted");
+
+	mutex_lock(&es8326->lock);
+
+	es8326->jack = jack;
+
+	snd_soc_component_write(component, ES8326_HPJACK_POL,
+				ES8326_HPJACK_POL_HP_TYPE_CTIA |
+				ES8326_HPJACK_POL_BUTTON_POL_ACTIVE_LOW |
+				ES8326_HPJACK_POL_HPJACK_POL_ACTIVE_LOW |
+				ES8326_HPJACK_POL_HPINSERT_SEL_PIN9);
+	snd_soc_component_write(component, ES8326_INT_SOURCE,
+				ES8326_INT_SOURCE_BUTTON |
+				ES8326_INT_SOURCE_PIN9);
+
+	mutex_unlock(&es8326->lock);
+
+	/* Enable irq and sync initial jack state */
+	enable_irq(es8326->irq);
+	es8326_irq(es8326->irq, es8326);
+}
+
+static void es8326_disable_jack_detect(struct snd_soc_component *component)
+{
+	struct es8326_priv *es8326 = snd_soc_component_get_drvdata(component);
+
+	disable_irq(es8326->irq);
+
+	mutex_lock(&es8326->lock);
+
+	snd_soc_component_write(component, ES8326_INT_SOURCE, 0);
+
+	if (es8326->jack->status & SND_JACK_MICROPHONE)
+		snd_soc_jack_report(es8326->jack, 0, SND_JACK_BTN_0);
+
+	es8326->jack = NULL;
+
+	mutex_unlock(&es8326->lock);
+}
+
+static int es8326_set_jack(struct snd_soc_component *component,
+			   struct snd_soc_jack *jack, void *data)
+{
+	if (jack)
+		es8326_enable_jack_detect(component, jack);
+	else
+		es8326_disable_jack_detect(component);
+
+	return 0;
+}
+
+static int es8326_set_bias_level(struct snd_soc_component *component,
+				 enum snd_soc_bias_level level)
+{
+	switch (level) {
+	case SND_SOC_BIAS_ON:
+		dev_dbg(component->dev, "%s on\n", __func__);
+		snd_soc_component_write(component, ES8326_HP_DRIVER, 0);
+		snd_soc_component_write(component, ES8326_ANA_PWR, 0);
+		snd_soc_component_update_bits(component, ES8326_PGA_PWR,
+					      ES8326_PGA_PWR_PDN_PGA |
+					      ES8326_PGA_PWR_PDN_MOD |
+					      ES8326_PGA_PWR_MODTOP_RST,
+					      0);
+		snd_soc_component_write(component, ES8326_VMIDSEL,
+					ES8326_VMIDSEL_NORMAL);
+		break;
+
+	case SND_SOC_BIAS_PREPARE:
+		dev_dbg(component->dev, "%s prepare\n", __func__);
+		break;
+
+	case SND_SOC_BIAS_STANDBY:
+		dev_dbg(component->dev, "%s standby\n", __func__);
+		snd_soc_component_update_bits(component, ES8326_HP_DRIVER,
+					      ES8326_HP_DRIVER_LP_MASK,
+					      ES8326_HP_DRIVER_LP_MASK);
+		snd_soc_component_update_bits(component, ES8326_ANA_PWR,
+					      ES8326_ANA_PWR_LP_DAC,
+					      ES8326_ANA_PWR_LP_DAC);
+		break;
+
+	case SND_SOC_BIAS_OFF:
+		dev_dbg(component->dev, "%s off\n", __func__);
+		snd_soc_component_write(component, ES8326_VMIDSEL,
+					ES8326_VMIDSEL_POWER_DOWN);
+		snd_soc_component_update_bits(component, ES8326_PGA_PWR,
+					      ES8326_PGA_PWR_PDN_PGA |
+					      ES8326_PGA_PWR_PDN_MOD |
+					      ES8326_PGA_PWR_MODTOP_RST,
+					      ES8326_PGA_PWR_PDN_PGA |
+					      ES8326_PGA_PWR_PDN_MOD |
+					      ES8326_PGA_PWR_MODTOP_RST);
+		snd_soc_component_write(component, ES8326_ANA_PWR,
+					ES8326_ANA_PWR_PDN_DACR |
+					ES8326_ANA_PWR_PDN_DACL |
+					ES8326_ANA_PWR_LP_DAC |
+					ES8326_ANA_PWR_PDN_VRP |
+					ES8326_ANA_PWR_PDN_DACVREFGEN |
+					ES8326_ANA_PWR_PDN_ADCVREFGEN |
+					ES8326_ANA_PWR_PDN_IBIASGEN |
+					ES8326_ANA_PWR_PDN_ANA);
+		snd_soc_component_update_bits(component, ES8326_HP_DRIVER,
+					      ES8326_HP_DRIVER_PDN_MASK |
+					      ES8326_HP_DRIVER_ENREFR_HP,
+					      ES8326_HP_DRIVER_PDN_MASK |
+					      ES8326_HP_DRIVER_ENREFR_HP);
+		break;
+
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+static int es8326_probe(struct snd_soc_component *component)
+{
+	struct es8326_priv *es8326 = snd_soc_component_get_drvdata(component);
+	int ret;
+
+	es8326->component = component;
+
+	es8326->mclk = devm_clk_get_optional(component->dev, "mclk");
+	if (IS_ERR(es8326->mclk)) {
+		dev_err(component->dev,"unable to get mclk\n");
+		return PTR_ERR(es8326->mclk);
+	}
+	if (!es8326->mclk)
+		dev_warn(component->dev,"assuming static mclk\n");
+
+	ret = clk_prepare_enable(es8326->mclk);
+	if (ret) {
+		dev_err(component->dev,"unable to enable mclk\n");
+		return ret;
+	}
+
+	snd_soc_component_init_regmap(component, es8326->regmap);
+
+	/* Reset codec and enable current state machine */
+	snd_soc_component_write(component, ES8326_RESET, ES8326_RESET_RST_MASK);
+	usleep_range(5000, 5500);
+	snd_soc_component_write(component, ES8326_RESET, ES8326_RESET_CSM_ON);
+	msleep(30);
+
+	snd_soc_component_write(component, ES8326_PULLUP_CTL,
+				ES8326_PULLUP_CTL_ADC34_OFF);
+	snd_soc_component_write(component, ES8326_CLK_CTL,
+				ES8326_CLK_CTL_CLK9_ON |
+				ES8326_CLK_CTL_CLK8_ON |
+				ES8326_CLK_CTL_CLK3_ON |
+				ES8326_CLK_CTL_CLK1_ON |
+				ES8326_CLK_CTL_BCLK_ON |
+				ES8326_CLK_CTL_MCLK_ON |
+				ES8326_CLK_CTL_CPCLK_ON);
+	snd_soc_component_write(component, ES8326_CLK_RESAMPLE,
+				ES8326_CLK_RESAMPLE_OSC_EN_ALWAYS_ON |
+				ES8326_CLK_RESAMPLE_INTCLK_SEL_OSC);
+	snd_soc_component_write(component, ES8326_ADC_MUTE, 0);
+	snd_soc_component_update_bits(component, ES8326_PGAGAIN,
+				      ES8326_PGAGAIN_MIC1SEL,
+				      ES8326_PGAGAIN_MIC1SEL);
+	return 0;
+}
+
+static void es8326_remove(struct snd_soc_component *component)
+{
+	struct es8326_priv *es8326 = snd_soc_component_get_drvdata(component);
+
+	snd_soc_component_exit_regmap(component);
+
+	clk_disable_unprepare(es8326->mclk);
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int es8326_suspend(struct device *dev)
+{
+	struct es8326_priv *es8326 = dev_get_drvdata(dev);
+
+	dev_dbg(dev, "%s: Enter\n", __func__);
+
+	regcache_cache_only(es8326->regmap, true);
+	regcache_mark_dirty(es8326->regmap);
+
+	return 0;
+}
+
+static int es8326_resume(struct device *dev)
+{
+	struct es8326_priv *es8326 = dev_get_drvdata(dev);
+
+	dev_dbg(dev, "%s: Enter\n", __func__);
+
+	regcache_cache_only(es8326->regmap, false);
+	regcache_sync(es8326->regmap);
+
+	es8326_irq(es8326->irq, es8326);
+
+	return 0;
+}
+#endif
+
+static const struct dev_pm_ops es8326_pm = {
+	SET_SYSTEM_SLEEP_PM_OPS(es8326_suspend, es8326_resume)
+};
+
+static struct snd_soc_component_driver soc_component_dev_es8326 = {
+	.probe			= es8326_probe,
+	.remove			= es8326_remove,
+	.set_bias_level		= es8326_set_bias_level,
+	.set_jack		= es8326_set_jack,
+	.controls		= es8326_snd_controls,
+	.num_controls		= ARRAY_SIZE(es8326_snd_controls),
+	.dapm_widgets		= es8326_dapm_widgets,
+	.num_dapm_widgets	= ARRAY_SIZE(es8326_dapm_widgets),
+	.dapm_routes		= es8326_dapm_routes,
+	.num_dapm_routes	= ARRAY_SIZE(es8326_dapm_routes),
+	.use_pmdown_time	= 1,
+	.endianness		= 1,
+	.non_legacy_dai_naming	= 1,
+};
+
+static const struct regmap_range es8326_volatile_ranges[] = {
+	regmap_reg_range(ES8326_HP_DETECT, ES8326_HP_DETECT),
+};
+
+static const struct regmap_access_table es8326_volatile_table = {
+	.yes_ranges	= es8326_volatile_ranges,
+	.n_yes_ranges	= ARRAY_SIZE(es8326_volatile_ranges),
+};
+
+static const struct regmap_config es8326_regmap = {
+	.reg_bits = 8,
+	.val_bits = 8,
+	.max_register = 0xff,
+	.volatile_table	= &es8326_volatile_table,
+	.cache_type = REGCACHE_RBTREE,
+	.use_single_read = true,
+	.use_single_write = true,
+};
+
+static int es8326_i2c_probe(struct i2c_client *i2c_client,
+			    const struct i2c_device_id *id)
+{
+	struct device *dev = &i2c_client->dev;
+	struct es8326_priv *es8326;
+	int ret;
+
+	es8326 = devm_kzalloc(dev, sizeof(*es8326), GFP_KERNEL);
+	if (es8326 == NULL)
+		return -ENOMEM;
+
+	i2c_set_clientdata(i2c_client, es8326);
+
+	es8326->regmap = devm_regmap_init_i2c(i2c_client, &es8326_regmap);
+	if (IS_ERR(es8326->regmap))
+		return PTR_ERR(es8326->regmap);
+
+	es8326->irq = i2c_client->irq;
+	mutex_init(&es8326->lock);
+
+	ret = devm_request_threaded_irq(dev, es8326->irq, NULL, es8326_irq,
+					IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
+					"es8326", es8326);
+	if (ret == 0) {
+		/* Gets re-enabled by es8326_set_jack() */
+		disable_irq(es8326->irq);
+	} else {
+		dev_warn(dev, "Failed to get IRQ %d: %d\n", es8326->irq, ret);
+		es8326->irq = -ENXIO;
+	}
+
+	return devm_snd_soc_register_component(dev, &soc_component_dev_es8326,
+					       &es8326_dai, 1);
+}
+
+static const struct i2c_device_id es8326_i2c_id[] = {
+	{"es8326", 0},
+	{}
+};
+MODULE_DEVICE_TABLE(i2c, es8326_i2c_id);
+
+#ifdef CONFIG_OF
+static const struct of_device_id es8326_of_match[] = {
+	{ .compatible = "everest,es8326", },
+	{}
+};
+MODULE_DEVICE_TABLE(of, es8326_of_match);
+#endif
+
+#ifdef CONFIG_ACPI
+static const struct acpi_device_id es8326_acpi_match[] = {
+	{"ESSX8326", 0},
+	{},
+};
+MODULE_DEVICE_TABLE(acpi, es8326_acpi_match);
+#endif
+
+static struct i2c_driver es8326_i2c_driver = {
+	.driver = {
+		.name			= "es8326",
+		.acpi_match_table	= ACPI_PTR(es8326_acpi_match),
+		.of_match_table		= of_match_ptr(es8326_of_match),
+		.pm			= &es8326_pm,
+	},
+	.probe		= es8326_i2c_probe,
+	.id_table	= es8326_i2c_id,
+};
+module_i2c_driver(es8326_i2c_driver);
+
+MODULE_DESCRIPTION("Everest Semi ES8326 ALSA SoC Codec Driver");
+MODULE_AUTHOR("David <zhuning@everset-semi.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/codecs/es8326.h b/sound/soc/codecs/es8326.h
new file mode 100644
index 000000000000..5a9396658aa2
--- /dev/null
+++ b/sound/soc/codecs/es8326.h
@@ -0,0 +1,222 @@
+/*
+ * Copyright 2005 Openedhand Ltd.
+ *
+ * Author: Richard Purdie <richard@openedhand.com>
+ *
+ * Based on ES8326.h
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#ifndef _ES8326_H
+#define _ES8326_H
+
+/*
+ * ES8326 register space
+ */
+
+/* Reset */
+#define ES8326_RESET		0x00
+
+/* Clock Manager */
+#define ES8326_CLK_CTL		0x01
+#define ES8326_CLK_INV		0x02
+#define ES8326_CLK_RESAMPLE	0x03
+#define ES8326_CLK_DIV1		0x04
+#define ES8326_CLK_DIV2		0x05
+#define ES8326_CLK_DLL		0x06
+#define ES8326_CLK_MUX		0x07
+#define ES8326_CLK_ADC_SEL	0x08
+#define ES8326_CLK_DAC_SEL	0x09
+#define ES8326_CLK_ADC_OSR	0x0a
+#define ES8326_CLK_DAC_OSR	0x0b
+#define ES8326_CLK_DIV_CPC	0x0c
+#define ES8326_CLK_DIV_BCLK	0x0d
+#define ES8326_CLK_TRI		0x0e
+#define ES8326_CLK_DIV_LRCK	0x0f
+#define ES8326_CLK_VMIDS1	0x10
+#define ES8326_CLK_VMIDS2	0x11
+#define ES8326_CLK_CAL_TIME	0x12
+
+/* SDP */
+#define ES8326_FMT		0x13
+#define ES8326_DAC_MUTE		0x14
+#define ES8326_ADC_MUTE		0x15
+
+/* Analog */
+#define ES8326_ANA_PWR		0x16
+#define ES8326_PGA_PWR		0x17
+#define ES8326_VMIDSEL		0x18
+#define ES8326_ANA_LOWPOWER	0x19
+#define ES8326_ANA_DMS		0x1a
+#define ES8326_ANA_MICBIAS	0x1b
+#define ES8326_ANA_VSEL		0x1c
+#define ES8326_SYS_BIAS		0x1d
+#define ES8326_BIAS_SW1		0x1e
+#define ES8326_BIAS_SW2		0x1f
+#define ES8326_BIAS_SW3		0x20
+#define ES8326_BIAS_SW4		0x21
+#define ES8326_VMIDLOW		0x22
+#define ES8326_PGAGAIN		0x23
+#define ES8326_HP_DRIVER	0x24
+#define ES8326_DAC2HPMIX	0x25
+#define ES8326_HP_VOL		0x26
+#define ES8326_HP_CTL		0x27
+#define ES8326_HP_DRIVER_REF	0x28
+
+/* ADC Control */
+#define ES8326_ADC_SCALE	0x29
+#define ES8326_ADC1_SRC		0x2a
+#define ES8326_ADC2_SRC		0x2b
+#define ES8326_ADC1_VOL		0x2c
+#define ES8326_ADC2_VOL		0x2d
+#define ES8326_ADC_RAMPRATE	0x2e
+#define ES8326_ALC_RECOVERY	0x32
+#define ES8326_ALC_LEVEL	0x33
+#define ES8326_ADC_HPFS1	0x34
+#define ES8326_ADC_HPFS2	0x35
+#define ES8326_ADC_EQ		0x36
+
+/* DAC Control */
+#define ES8326_HP_CAL		0x4a
+#define ES8326_HPL_OFFSET_INI	0x4b
+#define ES8326_HPR_OFFSET_INI	0x4c
+#define ES8326_DAC_DSM		0x4d
+#define ES8326_DAC_RAMPRATE	0x4e
+#define ES8326_DAC_VPPSCALE	0x4f
+#define ES8326_DAC_VOL		0x50
+#define ES8326_DRC_RECOVERY	0x53
+#define ES8326_DRC_WINSIZE	0x54
+
+/* GPIO */
+#define ES8326_HPJACK_TIMER	0x56
+#define ES8326_HPJACK_POL	0x57
+#define ES8326_INT_SOURCE	0x58
+#define ES8326_INTOUT_IO	0x59
+#define ES8326_SDINOUT1_IO	0x5a
+#define ES8326_SDINOUT23_IO	0x5b
+#define ES8326_JACK_PULSE	0x5c
+
+/* Test Mode */
+#define ES8326_PULLUP_CTL	0xf9
+
+#define ES8326_HP_DETECT	0xfb
+
+/* Chip ID */
+#define ES8326_CHIP_ID1		0xfd
+#define ES8326_CHIP_ID2		0xfe
+#define ES8326_CHIP_VERSION	0xff
+
+/*
+ * Field definitions
+ */
+
+/* ES8326_RESET */
+#define ES8326_RESET_RST_MASK			0x1f
+#define ES8326_RESET_RST_DACDIG			0x01
+#define ES8326_RESET_RST_ADCDIG			0x02
+#define ES8326_RESET_RST_MST			0x04
+#define ES8326_RESET_RST_CMG			0x08
+#define ES8326_RESET_RST_DIG			0x10
+#define ES8326_RESET_SEQ_DIS			0x20
+#define ES8326_RESET_MSC			0x40
+#define ES8326_RESET_CSM_ON			0x80
+
+/* ES8326_CLK_CTL */
+#define ES8326_CLK_CTL_CLK9_ON			0x01
+#define ES8326_CLK_CTL_CLK8_ON			0x02
+#define ES8326_CLK_CTL_CLK3_ON			0x04
+#define ES8326_CLK_CTL_CLK1_ON			0x08
+#define ES8326_CLK_CTL_BCLK_ON			0x10
+#define ES8326_CLK_CTL_MCLK_ON			0x20
+#define ES8326_CLK_CTL_CPCLK_ON			0x40
+
+/* ES8326_CLK_RESAMPLE */
+#define ES8326_CLK_RESAMPLE_OSC_EN_ALWAYS_ON	0x01
+#define ES8326_CLK_RESAMPLE_INTCLK_SEL_OSC	0x04
+
+/* ES8326_FMT */
+#define ES8326_FMT_SDP_WL_MASK			0x1c
+#define ES8326_FMT_SDP_WL_24			0x00
+#define ES8326_FMT_SDP_WL_20			0x04
+#define ES8326_FMT_SDP_WL_18			0x08
+#define ES8326_FMT_SDP_WL_16			0x0c
+#define ES8326_FMT_SDP_WL_32			0x10
+#define ES8326_FMT_SDP_FMT_MASK			0x03
+#define ES8326_FMT_SDP_FMT_I2S			0x00
+#define ES8326_FMT_SDP_FMT_LJ			0x01
+#define ES8326_FMT_SDP_FMT_DSP			0x03
+
+/* ES8326_DAC_MUTE */
+#define ES8326_DAC_MUTE_S2P_MUTE_MASK		0x03
+#define ES8326_DAC_MUTE_S2P_MUTE_L		0x01
+#define ES8326_DAC_MUTE_S2P_MUTE_R		0x02
+
+/* ES8326_ADC_MUTE */
+#define ES8326_ADC_MUTE_P2S_MUTE_MASK		0x0f
+#define ES8326_ADC_MUTE_P2S_MUTE_1		0x01
+#define ES8326_ADC_MUTE_P2S_MUTE_2		0x02
+#define ES8326_ADC_MUTE_P2S_MUTE_3		0x04
+#define ES8326_ADC_MUTE_P2S_MUTE_4		0x08
+#define ES8326_ADC_MUTE_P2S_TDM_MODE		0x10
+
+/* ES8326_ANA_PWR */
+#define ES8326_ANA_PWR_PDN_DACR			0x01
+#define ES8326_ANA_PWR_PDN_DACL			0x02
+#define ES8326_ANA_PWR_LP_DAC			0x04
+#define ES8326_ANA_PWR_PDN_VRP			0x08
+#define ES8326_ANA_PWR_PDN_DACVREFGEN		0x10
+#define ES8326_ANA_PWR_PDN_ADCVREFGEN		0x20
+#define ES8326_ANA_PWR_PDN_IBIASGEN		0x40
+#define ES8326_ANA_PWR_PDN_ANA			0x80
+
+/* ES8326_PGA_PWR */
+#define ES8326_PGA_PWR_PDN_PGA			0x08
+#define ES8326_PGA_PWR_PDN_MOD			0x10
+#define ES8326_PGA_PWR_MODTOP_RST		0x20
+
+/* ES8326_VMIDSEL */
+#define ES8326_VMIDSEL_POWER_DOWN		0x00
+#define ES8326_VMIDSEL_NORMAL			0x02
+
+/* ES8326_PGAGAIN */
+#define ES8326_PGAGAIN_MIC1SEL			0x10
+
+/* ES8326_HP_DRIVER */
+#define ES8326_HP_DRIVER_ENREFR_HP		0x01
+#define ES8326_HP_DRIVER_PDN_MASK		0x0e
+#define ES8326_HP_DRIVER_PDN_CPNLDO		0x02
+#define ES8326_HP_DRIVER_PDN_CPHP		0x04
+#define ES8326_HP_DRIVER_PDN_CP			0x08
+#define ES8326_HP_DRIVER_LP_MASK		0x70
+#define ES8326_HP_DRIVER_LP_CPNLDO		0x10
+#define ES8326_HP_DRIVER_LP_HPMIX		0x20
+#define ES8326_HP_DRIVER_LP_HP			0x40
+
+/* ES8326_HPJACK_POL */
+#define ES8326_HPJACK_POL_HP_TYPE_CTIA		0x03
+#define ES8326_HPJACK_POL_BUTTON_POL_ACTIVE_LOW	0x04
+#define ES8326_HPJACK_POL_HPJACK_POL_ACTIVE_LOW	0x08
+#define ES8326_HPJACK_POL_HPINSERT_SEL_PIN9	0x10
+
+/* ES8326_INT_SOURCE */
+#define ES8326_INT_SOURCE_BUTTON		0x04
+#define ES8326_INT_SOURCE_PIN9			0x08
+
+/* ES8326_PULLUP_CTL */
+#define ES8326_PULLUP_CTL_ADC34_OFF		0x02
+#define ES8326_PULLUP_CTL_ISO_VDDA		0x08
+#define ES8326_PULLUP_CTL_PULLUP_MASK		0xf0
+#define ES8326_PULLUP_CTL_PULLUP_SDINOUT	0x10
+#define ES8326_PULLUP_CTL_PULLUP_MCLK		0x20
+#define ES8326_PULLUP_CTL_PULLUP_LRCK		0x40
+#define ES8326_PULLUP_CTL_PULLUP_BCLK		0x80
+
+/* ES8326_HP_DETECT */
+#define ES8326_HP_DETECT_GM_NOT_SHORTED		0x01
+#define ES8326_HP_DETECT_NOT_INSERTED		0x02
+
+#endif
diff --git a/sound/soc/intel/boards/Kconfig b/sound/soc/intel/boards/Kconfig
index a5b70ad98424..5c4edc396fba 100644
--- a/sound/soc/intel/boards/Kconfig
+++ b/sound/soc/intel/boards/Kconfig
@@ -517,6 +517,7 @@ config SND_SOC_INTEL_SOF_ES8336_MACH
 	depends on MFD_INTEL_LPSS || COMPILE_TEST
 	depends on SND_HDA_CODEC_HDMI && SND_SOC_SOF_HDA_AUDIO_CODEC
 	select SND_SOC_ES8316
+	select SND_SOC_ES8326
 	select SND_SOC_DMIC
 	help
 	   This adds support for ASoC machine driver for SOF platforms
diff --git a/sound/soc/intel/boards/sof_es8336.c b/sound/soc/intel/boards/sof_es8336.c
index 7966a61b22c8..65304e6d3b0e 100644
--- a/sound/soc/intel/boards/sof_es8336.c
+++ b/sound/soc/intel/boards/sof_es8336.c
@@ -514,6 +514,12 @@ static int sof_es8336_probe(struct platform_device *pdev)
 	if (ret)
 		return ret;
 
+	card->components = devm_kasprintf(dev, GFP_KERNEL, "spk:es83%d6",
+					  strstr(codec_name, "ESSX8326")
+					  ? 2 : 1);
+	if (!card->components)
+		return -ENOMEM;
+
 	/* get speaker enable GPIO */
 	codec_dev = bus_find_device_by_name(&i2c_bus_type, NULL, codec_name);
 	if (!codec_dev)
diff --git a/sound/soc/intel/common/soc-acpi-intel-jsl-match.c b/sound/soc/intel/common/soc-acpi-intel-jsl-match.c
index 87923bcf9488..db79dd89943d 100644
--- a/sound/soc/intel/common/soc-acpi-intel-jsl-match.c
+++ b/sound/soc/intel/common/soc-acpi-intel-jsl-match.c
@@ -81,6 +81,12 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_jsl_machines[] = {
 		.quirk_data = &mx98360a_spk,
 		.sof_tplg_filename = "sof-jsl-cs42l42-mx98360a.tplg",
 	},
+	{
+		.id = "ESSX8326",
+		.drv_name = "sof-essx8336",
+		.sof_fw_filename = "sof-jsl.ri",
+		.sof_tplg_filename = "sof-jsl-es8326.tplg",
+	},
 	{
 		.id = "ESSX8336",
 		.drv_name = "sof-essx8336",
diff --git a/sound/soc/intel/common/soc-acpi-intel-tgl-match.c b/sound/soc/intel/common/soc-acpi-intel-tgl-match.c
index c2c5337ed3b8..40fcc9697e59 100644
--- a/sound/soc/intel/common/soc-acpi-intel-tgl-match.c
+++ b/sound/soc/intel/common/soc-acpi-intel-tgl-match.c
@@ -383,6 +383,12 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_tgl_machines[] = {
 		.sof_fw_filename = "sof-tgl.ri",
 		.sof_tplg_filename = "sof-tgl-rt1011-rt5682.tplg",
 	},
+	{
+		.id = "ESSX8326",
+		.drv_name = "sof-essx8336",
+		.sof_fw_filename = "sof-tgl.ri",
+		.sof_tplg_filename = "sof-tgl-es8326.tplg",
+	},
 	{
 		.id = "ESSX8336",
 		.drv_name = "sof-essx8336",
-- 
2.33.0



^ permalink raw reply	[flat|nested] 28+ messages in thread

* [d-kernel] [PATCH 6/9] ALSA: intel-dspconfig: add ES8336 support for CNL
  2022-04-04  6:28 ` [d-kernel] (no subject) nickel
                     ` (4 preceding siblings ...)
  2022-04-04  6:28   ` [d-kernel] [PATCH 5/9] commit f6a1611f744dcdd55c5adaf02f193083286dac34 nickel
@ 2022-04-04  6:28   ` nickel
  2022-04-04  6:28   ` [d-kernel] [PATCH 7/9] ASoC: Intel: soc-acpi: add ESSX8336 support on Cannon Lake machines nickel
                     ` (2 subsequent siblings)
  8 siblings, 0 replies; 28+ messages in thread
From: nickel @ 2022-04-04  6:28 UTC (permalink / raw)
  To: devel-kernel; +Cc: Pierre-Louis Bossart

From: Nikolai Kostrigin <nickel@altlinux.org>

We're missing this check for the CNL PCI id

Reported-by: Nikolai Kostrigin <nickel@altlinux.org>
Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Signed-off-by: Nikolai Kostrigin <nickel@altlinux.org>
---
 sound/hda/intel-dsp-config.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/sound/hda/intel-dsp-config.c b/sound/hda/intel-dsp-config.c
index 9ef023882ae0..7ca5124c13e9 100644
--- a/sound/hda/intel-dsp-config.c
+++ b/sound/hda/intel-dsp-config.c
@@ -193,6 +193,11 @@ static const struct config_entry config_table[] = {
 			{}
 		}
 	},
+	{
+		.flags = FLAG_SOF,
+		.device = 0x09dc8,
+		.codec_hid = "ESSX8336",
+	},
 	{
 		.flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE,
 		.device = 0x9dc8,
-- 
2.33.0



^ permalink raw reply	[flat|nested] 28+ messages in thread

* [d-kernel] [PATCH 7/9] ASoC: Intel: soc-acpi: add ESSX8336 support on Cannon Lake machines
  2022-04-04  6:28 ` [d-kernel] (no subject) nickel
                     ` (5 preceding siblings ...)
  2022-04-04  6:28   ` [d-kernel] [PATCH 6/9] ALSA: intel-dspconfig: add ES8336 support for CNL nickel
@ 2022-04-04  6:28   ` nickel
  2022-04-04  6:28   ` [d-kernel] [PATCH 8/9] config: CONFIG_SND_SOC_INTEL_SOF_ES8336_MACH=m nickel
  2022-04-04  6:28   ` [d-kernel] [PATCH 9/9] ASoC: Intel: sof_es8336: add DMI info based pa-enable lookup quirk for CNL-LP models nickel
  8 siblings, 0 replies; 28+ messages in thread
From: nickel @ 2022-04-04  6:28 UTC (permalink / raw)
  To: devel-kernel

From: Nikolai Kostrigin <nickel@altlinux.org>

Signed-off-by: Nikolai Kostrigin <nickel@altlinux.org>
---
 sound/soc/intel/common/soc-acpi-intel-cnl-match.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/sound/soc/intel/common/soc-acpi-intel-cnl-match.c b/sound/soc/intel/common/soc-acpi-intel-cnl-match.c
index 94b650767e11..ef2686e9bc3c 100644
--- a/sound/soc/intel/common/soc-acpi-intel-cnl-match.c
+++ b/sound/soc/intel/common/soc-acpi-intel-cnl-match.c
@@ -24,6 +24,13 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_cnl_machines[] = {
 		.sof_fw_filename = "sof-cnl.ri",
 		.sof_tplg_filename = "sof-cnl-rt274.tplg",
 	},
+	{
+		.id = "ESSX8336",
+		.drv_name = "sof-essx8336",
+		.sof_fw_filename = "sof-cnl.ri",
+		/* cnl and cml are identical */
+		.sof_tplg_filename = "sof-cml-es8336-ssp0.tplg",
+	},
 	{},
 };
 EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_cnl_machines);
-- 
2.33.0



^ permalink raw reply	[flat|nested] 28+ messages in thread

* [d-kernel] [PATCH 8/9] config: CONFIG_SND_SOC_INTEL_SOF_ES8336_MACH=m
  2022-04-04  6:28 ` [d-kernel] (no subject) nickel
                     ` (6 preceding siblings ...)
  2022-04-04  6:28   ` [d-kernel] [PATCH 7/9] ASoC: Intel: soc-acpi: add ESSX8336 support on Cannon Lake machines nickel
@ 2022-04-04  6:28   ` nickel
  2022-04-04  6:28   ` [d-kernel] [PATCH 9/9] ASoC: Intel: sof_es8336: add DMI info based pa-enable lookup quirk for CNL-LP models nickel
  8 siblings, 0 replies; 28+ messages in thread
From: nickel @ 2022-04-04  6:28 UTC (permalink / raw)
  To: devel-kernel

From: Nikolai Kostrigin <nickel@altlinux.org>

---
 config | 1 +
 1 file changed, 1 insertion(+)

diff --git a/config b/config
index a55474de6623..7ac421c1530b 100644
--- a/config
+++ b/config
@@ -6890,6 +6890,7 @@ CONFIG_SND_SOC_INTEL_CHT_BSW_NAU8824_MACH=m
 CONFIG_SND_SOC_INTEL_BYT_CHT_CX2072X_MACH=m
 CONFIG_SND_SOC_INTEL_BYT_CHT_DA7213_MACH=m
 CONFIG_SND_SOC_INTEL_BYT_CHT_ES8316_MACH=m
+CONFIG_SND_SOC_INTEL_SOF_ES8336_MACH=m
 CONFIG_SND_SOC_INTEL_BYT_CHT_NOCODEC_MACH=m
 CONFIG_SND_SOC_INTEL_SKL_RT286_MACH=m
 CONFIG_SND_SOC_INTEL_SKL_NAU88L25_SSM4567_MACH=m
-- 
2.33.0



^ permalink raw reply	[flat|nested] 28+ messages in thread

* [d-kernel] [PATCH 9/9] ASoC: Intel: sof_es8336: add DMI info based pa-enable lookup quirk for CNL-LP models
  2022-04-04  6:28 ` [d-kernel] (no subject) nickel
                     ` (7 preceding siblings ...)
  2022-04-04  6:28   ` [d-kernel] [PATCH 8/9] config: CONFIG_SND_SOC_INTEL_SOF_ES8336_MACH=m nickel
@ 2022-04-04  6:28   ` nickel
  8 siblings, 0 replies; 28+ messages in thread
From: nickel @ 2022-04-04  6:28 UTC (permalink / raw)
  To: devel-kernel

From: Nikolai Kostrigin <nickel@altlinux.org>

---
 sound/soc/intel/boards/sof_es8336.c | 73 +++++++++++++++++++++++++----
 1 file changed, 64 insertions(+), 9 deletions(-)

diff --git a/sound/soc/intel/boards/sof_es8336.c b/sound/soc/intel/boards/sof_es8336.c
index 65304e6d3b0e..373b8e7f7232 100644
--- a/sound/soc/intel/boards/sof_es8336.c
+++ b/sound/soc/intel/boards/sof_es8336.c
@@ -34,6 +34,8 @@ static int quirk_override = -1;
 module_param_named(quirk, quirk_override, int, 0444);
 MODULE_PARM_DESC(quirk, "Board-specific quirk override");
 
+static int quirk_pa_enable = -1;
+
 /* jd-inv + terminating entry */
 #define SOF_ES8336_PROPS_MAX	2
 
@@ -231,10 +233,25 @@ static int sof_es8336_quirk_cb(const struct dmi_system_id *id)
 	if (quirk & SOF_ES8336_TGL_GPIO_QUIRK)
 		gpio_mapping = quirk_acpi_es8336_gpios;
 
+	if (strcmp(id->ident, "pa-enable ACPI deviant") == 0) {
+		if (quirk_pa_enable < 0) quirk_pa_enable = 1;
+		else quirk_pa_enable++;
+	}
+
 	return 1;
 }
 
 static const struct dmi_system_id sof_es8336_quirk_table[] = {
+	{
+		.callback = sof_es8336_quirk_cb,
+		.ident = "pa-enable ACPI deviant",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "3Logic Group"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Graviton N15i-K2"),
+		},
+		.driver_data = (void *)(SOF_ES8336_SSP_CODEC(0) |
+					SOF_ES8336_TGL_GPIO_QUIRK)
+	},
 	{
 		.callback = sof_es8336_quirk_cb,
 		.matches = {
@@ -243,6 +260,16 @@ static const struct dmi_system_id sof_es8336_quirk_table[] = {
 		},
 		.driver_data = (void *)SOF_ES8336_SSP_CODEC(2)
 	},
+	{
+		.callback = sof_es8336_quirk_cb,
+		.ident = "pa-enable ACPI deviant",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "DEPO Computers"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "DPC156"),
+		},
+		.driver_data = (void *)(SOF_ES8336_SSP_CODEC(0) |
+					SOF_ES8336_TGL_GPIO_QUIRK)
+	},
 	{
 		.callback = sof_es8336_quirk_cb,
 		.matches = {
@@ -456,6 +483,18 @@ static struct snd_soc_dai_link *sof_card_dai_links_create(struct device *dev,
  /* i2c-<HID>:00 with HID being 8 chars */
 static char codec_name[SND_ACPI_I2C_ID_LEN];
 
+/*
+* Using the ACPI device name is not very nice, but hopefully makes sense for now
+*/
+
+static struct gpiod_lookup_table cml_lp_based_gpios_table = {
+	/* .dev_id is set during probe */
+	.table = {
+		GPIO_LOOKUP("INT34BB:00", 264, "PA_ENABLE", GPIO_ACTIVE_LOW), //cnl kb
+		 { },
+	},
+};
+
 static int sof_es8336_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
@@ -507,6 +546,9 @@ static int sof_es8336_probe(struct platform_device *pdev)
 			 "i2c-%s", acpi_dev_name(adev));
 		put_device(&adev->dev);
 		dai_links[0].codecs->name = codec_name;
+	} else {
+		dev_err(dev, "Error cannot find '%s' dev\n", mach->id);
+		return -ENXIO;
 	}
 
 	ret = snd_soc_fixup_dai_links_platform_name(&sof_es8336_card,
@@ -537,16 +579,29 @@ static int sof_es8336_probe(struct platform_device *pdev)
 		}
 	}
 
-	ret = devm_acpi_dev_add_driver_gpios(codec_dev, gpio_mapping);
-	if (ret)
-		dev_warn(codec_dev, "unable to add GPIO mapping table\n");
+	if (quirk_pa_enable < 0) {
+		ret = devm_acpi_dev_add_driver_gpios(codec_dev, gpio_mapping);
+		if (ret)
+			dev_warn(codec_dev, "unable to add GPIO mapping table\n");
 
-	priv->gpio_pa = gpiod_get(codec_dev, "pa-enable", GPIOD_OUT_LOW);
-	if (IS_ERR(priv->gpio_pa)) {
-		ret = PTR_ERR(priv->gpio_pa);
-		dev_err(codec_dev, "%s, could not get pa-enable: %d\n",
-			__func__, ret);
-		goto err;
+		priv->gpio_pa = gpiod_get_optional(codec_dev, "pa-enable", GPIOD_OUT_LOW);
+		if (IS_ERR(priv->gpio_pa)) {
+			ret = dev_err_probe(dev, PTR_ERR(priv->gpio_pa),
+						"could not get pa-enable GPIO\n");
+			goto err;
+		}
+	}
+	else {
+		cml_lp_based_gpios_table.dev_id = dev_name(codec_dev);
+		gpiod_add_lookup_table(&cml_lp_based_gpios_table);
+
+		priv->gpio_pa = devm_gpiod_get(codec_dev, "PA_ENABLE", GPIOD_OUT_LOW);
+		if (IS_ERR(priv->gpio_pa)) {
+			ret = PTR_ERR(priv->gpio_pa);
+			dev_err(codec_dev, "%s, could not get PA_ENABLE: %d\n",
+				__func__, ret);
+			goto err;
+		}
 	}
 
 	priv->codec_dev = codec_dev;
-- 
2.33.0



^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [d-kernel] [PATCH 1/9] commit 0b220578c2aab3d5ac6b693117e8c5d22e8c2b34
  2022-04-04  6:28   ` [d-kernel] [PATCH 1/9] commit 0b220578c2aab3d5ac6b693117e8c5d22e8c2b34 nickel
@ 2022-04-04 14:48     ` Vitaly Chikunov
  2022-04-04 15:16       ` Nikolai Kostrigin
  0 siblings, 1 reply; 28+ messages in thread
From: Vitaly Chikunov @ 2022-04-04 14:48 UTC (permalink / raw)
  To: ALT Linux kernel packages development

Hi,


On Mon, Apr 04, 2022 at 09:28:41AM +0300, nickel@altlinux.org wrote:
> From: Vasily Vinogradov <v.vinogradov@aq.ru>
> 
>     ASoC: Intel: add machine driver for SOF+ES8336

А что это за формат коммитов - нельзя ли в нормальном?
Чтоб в Subject было commit message (видимо это будет "ASoC: Intel:
add machine driver for SOF+ES8336", а не некий "commit XYZ". И,
желательно, чтоб в описании оригинальное описание и ссылка на откуда
это взято. Потому-что анонимный коммит из интернета и коммит из апстрима
это разное качество и количество тестирования.

Спасибо,


> ---
>  sound/hda/intel-dsp-config.c                  |  24 +-
>  sound/soc/codecs/es8316.c                     |   1 +
>  sound/soc/intel/boards/Kconfig                |  13 +
>  sound/soc/intel/boards/Makefile               |   2 +
>  sound/soc/intel/boards/sof_es8336.c           | 569 ++++++++++++++++++
>  .../intel/common/soc-acpi-intel-bxt-match.c   |   6 +
>  .../intel/common/soc-acpi-intel-cml-match.c   |   6 +
>  .../intel/common/soc-acpi-intel-glk-match.c   |   7 +-
>  .../intel/common/soc-acpi-intel-jsl-match.c   |   6 +
>  .../intel/common/soc-acpi-intel-tgl-match.c   |   6 +
>  10 files changed, 627 insertions(+), 13 deletions(-)
>  create mode 100644 sound/soc/intel/boards/sof_es8336.c
> 
> diff --git a/sound/hda/intel-dsp-config.c b/sound/hda/intel-dsp-config.c
> index 4208fa8a4db5..f63114317ac9 100644
> --- a/sound/hda/intel-dsp-config.c
> +++ b/sound/hda/intel-dsp-config.c
> @@ -249,13 +249,13 @@ static const struct config_entry config_table[] = {
>  		}
>  	},
>  	{
> -		.flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE,
> +		.flags = FLAG_SOF,
>  		.device = 0x02c8,
> +		.codec_hid = "ESSX8336",
>  	},
>  	{
> -		.flags = FLAG_SOF,
> +		.flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE,
>  		.device = 0x02c8,
> -		.codec_hid = "ESSX8336",
>  	},
>  /* Cometlake-H */
>  	{
> @@ -278,14 +278,14 @@ static const struct config_entry config_table[] = {
>  		}
>  	},
>  	{
> -		.flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE,
> -		.device = 0x06c8,
> -	},
> -		{
>  		.flags = FLAG_SOF,
>  		.device = 0x06c8,
>  		.codec_hid = "ESSX8336",
>  	},
> +	{
> +		.flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE,
> +		.device = 0x06c8,
> +	},
>  #endif
>  
>  /* Icelake */
> @@ -334,17 +334,17 @@ static const struct config_entry config_table[] = {
>  		}
>  	},
>  	{
> -		.flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE,
> +		.flags = FLAG_SOF,
>  		.device = 0xa0c8,
> +		.codec_hid = "ESSX8336",
>  	},
>  	{
>  		.flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE,
> -		.device = 0x43c8,
> +		.device = 0xa0c8,
>  	},
>  	{
> -		.flags = FLAG_SOF,
> -		.device = 0xa0c8,
> -		.codec_hid = "ESSX8336",
> +		.flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE,
> +		.device = 0x43c8,
>  	},
>  #endif
>  
> diff --git a/sound/soc/codecs/es8316.c b/sound/soc/codecs/es8316.c
> index 5fb02635c140..8f30a3ea8bfe 100644
> --- a/sound/soc/codecs/es8316.c
> +++ b/sound/soc/codecs/es8316.c
> @@ -840,6 +840,7 @@ MODULE_DEVICE_TABLE(of, es8316_of_match);
>  #ifdef CONFIG_ACPI
>  static const struct acpi_device_id es8316_acpi_match[] = {
>  	{"ESSX8316", 0},
> +	{"ESSX8336", 0},
>  	{},
>  };
>  MODULE_DEVICE_TABLE(acpi, es8316_acpi_match);
> diff --git a/sound/soc/intel/boards/Kconfig b/sound/soc/intel/boards/Kconfig
> index 61b71d6c44cf..a5b70ad98424 100644
> --- a/sound/soc/intel/boards/Kconfig
> +++ b/sound/soc/intel/boards/Kconfig
> @@ -511,6 +511,19 @@ config SND_SOC_INTEL_SOF_PCM512x_MACH
>  	  Say Y or m if you have such a device.
>  	  If unsure select "N".
>  
> +config SND_SOC_INTEL_SOF_ES8336_MACH
> +	tristate "SOF with ES8336 codec in I2S mode"
> +	depends on I2C && ACPI && GPIOLIB
> +	depends on MFD_INTEL_LPSS || COMPILE_TEST
> +	depends on SND_HDA_CODEC_HDMI && SND_SOC_SOF_HDA_AUDIO_CODEC
> +	select SND_SOC_ES8316
> +	select SND_SOC_DMIC
> +	help
> +	   This adds support for ASoC machine driver for SOF platforms
> +	   with es8336 codec.
> +	   Say Y if you have such a device.
> +	   If unsure select "N".
> +
>  endif ## SND_SOC_SOF_HDA_LINK || SND_SOC_SOF_BAYTRAIL
>  
>  if (SND_SOC_SOF_COMETLAKE && SND_SOC_SOF_HDA_LINK)
> diff --git a/sound/soc/intel/boards/Makefile b/sound/soc/intel/boards/Makefile
> index ed21b82a4cf6..de72ef29279e 100644
> --- a/sound/soc/intel/boards/Makefile
> +++ b/sound/soc/intel/boards/Makefile
> @@ -22,6 +22,7 @@ snd-soc-sst-byt-cht-nocodec-objs := bytcht_nocodec.o
>  snd-soc-sof_rt5682-objs := sof_rt5682.o sof_realtek_common.o
>  snd-soc-sof_cs42l42-objs := sof_cs42l42.o
>  snd-soc-cml_rt1011_rt5682-objs := cml_rt1011_rt5682.o
> +snd-soc-sof_es8336-objs := sof_es8336.o
>  snd-soc-kbl_da7219_max98357a-objs := kbl_da7219_max98357a.o
>  snd-soc-kbl_da7219_max98927-objs := kbl_da7219_max98927.o
>  snd-soc-kbl_rt5663_max98927-objs := kbl_rt5663_max98927.o
> @@ -42,6 +43,7 @@ snd-soc-sof-sdw-objs += sof_sdw.o				\
>  			sof_sdw_dmic.o sof_sdw_hdmi.o
>  obj-$(CONFIG_SND_SOC_INTEL_SOF_RT5682_MACH) += snd-soc-sof_rt5682.o
>  obj-$(CONFIG_SND_SOC_INTEL_SOF_CS42L42_MACH) += snd-soc-sof_cs42l42.o
> +obj-$(CONFIG_SND_SOC_INTEL_SOF_ES8336_MACH) += snd-soc-sof_es8336.o
>  obj-$(CONFIG_SND_SOC_INTEL_HASWELL_MACH) += snd-soc-sst-haswell.o
>  obj-$(CONFIG_SND_SOC_INTEL_BXT_DA7219_MAX98357A_COMMON) += snd-soc-sst-bxt-da7219_max98357a.o
>  obj-$(CONFIG_SND_SOC_INTEL_BXT_RT298_MACH) += snd-soc-sst-bxt-rt298.o
> diff --git a/sound/soc/intel/boards/sof_es8336.c b/sound/soc/intel/boards/sof_es8336.c
> new file mode 100644
> index 000000000000..20d577eaab6d
> --- /dev/null
> +++ b/sound/soc/intel/boards/sof_es8336.c
> @@ -0,0 +1,569 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +// Copyright(c) 2021 Intel Corporation.
> +
> +/*
> + * Intel SOF Machine Driver with es8336 Codec
> + */
> +
> +#include <linux/device.h>
> +#include <linux/dmi.h>
> +#include <linux/gpio/consumer.h>
> +#include <linux/gpio/machine.h>
> +#include <linux/i2c.h>
> +#include <linux/input.h>
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +#include <linux/slab.h>
> +#include <sound/jack.h>
> +#include <sound/pcm.h>
> +#include <sound/pcm_params.h>
> +#include <sound/soc.h>
> +#include <sound/soc-acpi.h>
> +#include "hda_dsp_common.h"
> +
> +#define SOF_ES8336_SSP_CODEC(quirk)		((quirk) & GENMASK(3, 0))
> +#define SOF_ES8336_SSP_CODEC_MASK		(GENMASK(3, 0))
> +
> +#define SOF_ES8336_TGL_GPIO_QUIRK		BIT(4)
> +#define SOF_ES8336_ENABLE_DMIC			BIT(5)
> +
> +static unsigned long quirk;
> +
> +static int quirk_override = -1;
> +module_param_named(quirk, quirk_override, int, 0444);
> +MODULE_PARM_DESC(quirk, "Board-specific quirk override");
> +
> +struct sof_es8336_private {
> +	struct device *codec_dev;
> +	struct gpio_desc *gpio_pa;
> +	struct snd_soc_jack jack;
> +	struct list_head hdmi_pcm_list;
> +	bool speaker_en;
> +};
> +
> +struct sof_hdmi_pcm {
> +	struct list_head head;
> +	struct snd_soc_dai *codec_dai;
> +	int device;
> +};
> +
> +static const struct acpi_gpio_params pa_enable_gpio = { 0, 0, true };
> +static const struct acpi_gpio_mapping acpi_es8336_gpios[] = {
> +	{ "pa-enable-gpios", &pa_enable_gpio, 1 },
> +	{ }
> +};
> +
> +static const struct acpi_gpio_params quirk_pa_enable_gpio = { 1, 0, true };
> +static const struct acpi_gpio_mapping quirk_acpi_es8336_gpios[] = {
> +	{ "pa-enable-gpios", &quirk_pa_enable_gpio, 1 },
> +	{ }
> +};
> +
> +static const struct acpi_gpio_mapping *gpio_mapping = acpi_es8336_gpios;
> +
> +static void log_quirks(struct device *dev)
> +{
> +	dev_info(dev, "quirk SSP%ld",  SOF_ES8336_SSP_CODEC(quirk));
> +}
> +
> +static int sof_es8316_speaker_power_event(struct snd_soc_dapm_widget *w,
> +					  struct snd_kcontrol *kcontrol, int event)
> +{
> +	struct snd_soc_card *card = w->dapm->card;
> +	struct sof_es8336_private *priv = snd_soc_card_get_drvdata(card);
> +
> +	if (SND_SOC_DAPM_EVENT_ON(event))
> +		priv->speaker_en = false;
> +	else
> +		priv->speaker_en = true;
> +
> +	gpiod_set_value_cansleep(priv->gpio_pa, priv->speaker_en);
> +
> +	return 0;
> +}
> +
> +static const struct snd_soc_dapm_widget sof_es8316_widgets[] = {
> +	SND_SOC_DAPM_SPK("Speaker", NULL),
> +	SND_SOC_DAPM_HP("Headphone", NULL),
> +	SND_SOC_DAPM_MIC("Headset Mic", NULL),
> +	SND_SOC_DAPM_MIC("Internal Mic", NULL),
> +
> +	SND_SOC_DAPM_SUPPLY("Speaker Power", SND_SOC_NOPM, 0, 0,
> +			    sof_es8316_speaker_power_event,
> +			    SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
> +};
> +
> +static const struct snd_soc_dapm_widget dmic_widgets[] = {
> +	SND_SOC_DAPM_MIC("SoC DMIC", NULL),
> +};
> +
> +static const struct snd_soc_dapm_route sof_es8316_audio_map[] = {
> +	{"Headphone", NULL, "HPOL"},
> +	{"Headphone", NULL, "HPOR"},
> +
> +	/*
> +	 * There is no separate speaker output instead the speakers are muxed to
> +	 * the HP outputs. The mux is controlled by the "Speaker Power" supply.
> +	 */
> +	{"Speaker", NULL, "HPOL"},
> +	{"Speaker", NULL, "HPOR"},
> +	{"Speaker", NULL, "Speaker Power"},
> +};
> +
> +static const struct snd_soc_dapm_route sof_es8316_intmic_in1_map[] = {
> +	{"MIC1", NULL, "Internal Mic"},
> +	{"MIC2", NULL, "Headset Mic"},
> +};
> +
> +static const struct snd_soc_dapm_route dmic_map[] = {
> +	/* digital mics */
> +	{"DMic", NULL, "SoC DMIC"},
> +};
> +
> +static const struct snd_kcontrol_new sof_es8316_controls[] = {
> +	SOC_DAPM_PIN_SWITCH("Speaker"),
> +	SOC_DAPM_PIN_SWITCH("Headphone"),
> +	SOC_DAPM_PIN_SWITCH("Headset Mic"),
> +	SOC_DAPM_PIN_SWITCH("Internal Mic"),
> +};
> +
> +static struct snd_soc_jack_pin sof_es8316_jack_pins[] = {
> +	{
> +		.pin	= "Headphone",
> +		.mask	= SND_JACK_HEADPHONE,
> +	},
> +	{
> +		.pin	= "Headset Mic",
> +		.mask	= SND_JACK_MICROPHONE,
> +	},
> +};
> +
> +static int dmic_init(struct snd_soc_pcm_runtime *runtime)
> +{
> +	struct snd_soc_card *card = runtime->card;
> +	int ret;
> +
> +	ret = snd_soc_dapm_new_controls(&card->dapm, dmic_widgets,
> +					ARRAY_SIZE(dmic_widgets));
> +	if (ret) {
> +		dev_err(card->dev, "DMic widget addition failed: %d\n", ret);
> +		return ret;
> +	}
> +
> +	ret = snd_soc_dapm_add_routes(&card->dapm, dmic_map,
> +				      ARRAY_SIZE(dmic_map));
> +	if (ret)
> +		dev_err(card->dev, "DMic map addition failed: %d\n", ret);
> +
> +	return ret;
> +}
> +
> +static int sof_hdmi_init(struct snd_soc_pcm_runtime *runtime)
> +{
> +	struct sof_es8336_private *priv = snd_soc_card_get_drvdata(runtime->card);
> +	struct snd_soc_dai *dai = asoc_rtd_to_codec(runtime, 0);
> +	struct sof_hdmi_pcm *pcm;
> +
> +	pcm = devm_kzalloc(runtime->card->dev, sizeof(*pcm), GFP_KERNEL);
> +	if (!pcm)
> +		return -ENOMEM;
> +
> +	/* dai_link id is 1:1 mapped to the PCM device */
> +	pcm->device = runtime->dai_link->id;
> +	pcm->codec_dai = dai;
> +
> +	list_add_tail(&pcm->head, &priv->hdmi_pcm_list);
> +
> +	return 0;
> +}
> +
> +static int sof_es8316_init(struct snd_soc_pcm_runtime *runtime)
> +{
> +	struct snd_soc_component *codec = asoc_rtd_to_codec(runtime, 0)->component;
> +	struct snd_soc_card *card = runtime->card;
> +	struct sof_es8336_private *priv = snd_soc_card_get_drvdata(card);
> +	const struct snd_soc_dapm_route *custom_map;
> +	int num_routes;
> +	int ret;
> +
> +	card->dapm.idle_bias_off = true;
> +
> +	custom_map = sof_es8316_intmic_in1_map;
> +	num_routes = ARRAY_SIZE(sof_es8316_intmic_in1_map);
> +
> +	ret = snd_soc_dapm_add_routes(&card->dapm, custom_map, num_routes);
> +	if (ret)
> +		return ret;
> +
> +	ret = snd_soc_card_jack_new(card, "Headset",
> +				    SND_JACK_HEADSET | SND_JACK_BTN_0,
> +				    &priv->jack, sof_es8316_jack_pins,
> +				    ARRAY_SIZE(sof_es8316_jack_pins));
> +	if (ret) {
> +		dev_err(card->dev, "jack creation failed %d\n", ret);
> +		return ret;
> +	}
> +
> +	snd_jack_set_key(priv->jack.jack, SND_JACK_BTN_0, KEY_PLAYPAUSE);
> +
> +	snd_soc_component_set_jack(codec, &priv->jack, NULL);
> +
> +	return 0;
> +}
> +
> +static void sof_es8316_exit(struct snd_soc_pcm_runtime *rtd)
> +{
> +	struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component;
> +
> +	snd_soc_component_set_jack(component, NULL, NULL);
> +}
> +
> +static int sof_es8336_quirk_cb(const struct dmi_system_id *id)
> +{
> +	quirk = (unsigned long)id->driver_data;
> +
> +	if (quirk & SOF_ES8336_TGL_GPIO_QUIRK)
> +		gpio_mapping = quirk_acpi_es8336_gpios;
> +
> +	return 1;
> +}
> +
> +static const struct dmi_system_id sof_es8336_quirk_table[] = {
> +	{
> +		.callback = sof_es8336_quirk_cb,
> +		.matches = {
> +			DMI_MATCH(DMI_SYS_VENDOR, "CHUWI Innovation And Technology"),
> +			DMI_MATCH(DMI_BOARD_NAME, "Hi10 X"),
> +		},
> +		.driver_data = (void *)SOF_ES8336_SSP_CODEC(2)
> +	},
> +	{
> +		.callback = sof_es8336_quirk_cb,
> +		.matches = {
> +			DMI_MATCH(DMI_SYS_VENDOR, "IP3 tech"),
> +			DMI_MATCH(DMI_BOARD_NAME, "WN1"),
> +		},
> +		.driver_data = (void *)(SOF_ES8336_SSP_CODEC(0) |
> +					SOF_ES8336_TGL_GPIO_QUIRK |
> +					SOF_ES8336_ENABLE_DMIC)
> +	},
> +	{}
> +};
> +
> +static int sof_es8336_hw_params(struct snd_pcm_substream *substream,
> +				struct snd_pcm_hw_params *params)
> +{
> +	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
> +	struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
> +	const int sysclk = 19200000;
> +	int ret;
> +
> +	ret = snd_soc_dai_set_sysclk(codec_dai, 1, sysclk, SND_SOC_CLOCK_OUT);
> +	if (ret < 0) {
> +		dev_err(rtd->dev, "%s, Failed to set ES8336 SYSCLK: %d\n",
> +			__func__, ret);
> +		return ret;
> +	}
> +
> +	return 0;
> +}
> +
> +/* machine stream operations */
> +static struct snd_soc_ops sof_es8336_ops = {
> +	.hw_params = sof_es8336_hw_params,
> +};
> +
> +static struct snd_soc_dai_link_component platform_component[] = {
> +	{
> +		/* name might be overridden during probe */
> +		.name = "0000:00:1f.3"
> +	}
> +};
> +
> +SND_SOC_DAILINK_DEF(ssp1_codec,
> +	DAILINK_COMP_ARRAY(COMP_CODEC("i2c-ESSX8336:00", "ES8316 HiFi")));
> +
> +static struct snd_soc_dai_link_component dmic_component[] = {
> +	{
> +		.name = "dmic-codec",
> +		.dai_name = "dmic-hifi",
> +	}
> +};
> +
> +static int sof_es8336_late_probe(struct snd_soc_card *card)
> +{
> +	struct sof_es8336_private *priv = snd_soc_card_get_drvdata(card);
> +	struct sof_hdmi_pcm *pcm;
> +
> +	if (list_empty(&priv->hdmi_pcm_list))
> +		return -ENOENT;
> +
> +	pcm = list_first_entry(&priv->hdmi_pcm_list, struct sof_hdmi_pcm, head);
> +
> +	return hda_dsp_hdmi_build_controls(card, pcm->codec_dai->component);
> +}
> +
> +/* SoC card */
> +static struct snd_soc_card sof_es8336_card = {
> +	.name = "essx8336", /* sof- prefix added automatically */
> +	.owner = THIS_MODULE,
> +	.dapm_widgets = sof_es8316_widgets,
> +	.num_dapm_widgets = ARRAY_SIZE(sof_es8316_widgets),
> +	.dapm_routes = sof_es8316_audio_map,
> +	.num_dapm_routes = ARRAY_SIZE(sof_es8316_audio_map),
> +	.controls = sof_es8316_controls,
> +	.num_controls = ARRAY_SIZE(sof_es8316_controls),
> +	.fully_routed = true,
> +	.late_probe = sof_es8336_late_probe,
> +	.num_links = 1,
> +};
> +
> +static struct snd_soc_dai_link *sof_card_dai_links_create(struct device *dev,
> +							  int ssp_codec,
> +							  int dmic_be_num,
> +							  int hdmi_num)
> +{
> +	struct snd_soc_dai_link_component *cpus;
> +	struct snd_soc_dai_link *links;
> +	struct snd_soc_dai_link_component *idisp_components;
> +	int hdmi_id_offset = 0;
> +	int id = 0;
> +	int i;
> +
> +	links = devm_kcalloc(dev, sof_es8336_card.num_links,
> +			     sizeof(struct snd_soc_dai_link), GFP_KERNEL);
> +	cpus = devm_kcalloc(dev, sof_es8336_card.num_links,
> +			    sizeof(struct snd_soc_dai_link_component), GFP_KERNEL);
> +	if (!links || !cpus)
> +		goto devm_err;
> +
> +	/* codec SSP */
> +	links[id].name = devm_kasprintf(dev, GFP_KERNEL,
> +					"SSP%d-Codec", ssp_codec);
> +	if (!links[id].name)
> +		goto devm_err;
> +
> +	links[id].id = id;
> +	links[id].codecs = ssp1_codec;
> +	links[id].num_codecs = ARRAY_SIZE(ssp1_codec);
> +	links[id].platforms = platform_component;
> +	links[id].num_platforms = ARRAY_SIZE(platform_component);
> +	links[id].init = sof_es8316_init;
> +	links[id].exit = sof_es8316_exit;
> +	links[id].ops = &sof_es8336_ops;
> +	links[id].nonatomic = true;
> +	links[id].dpcm_playback = 1;
> +	links[id].dpcm_capture = 1;
> +	links[id].no_pcm = 1;
> +	links[id].cpus = &cpus[id];
> +	links[id].num_cpus = 1;
> +
> +	links[id].cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL,
> +						  "SSP%d Pin",
> +						  ssp_codec);
> +	if (!links[id].cpus->dai_name)
> +		goto devm_err;
> +
> +	id++;
> +
> +	/* dmic */
> +	if (dmic_be_num > 0) {
> +		/* at least we have dmic01 */
> +		links[id].name = "dmic01";
> +		links[id].cpus = &cpus[id];
> +		links[id].cpus->dai_name = "DMIC01 Pin";
> +		links[id].init = dmic_init;
> +		if (dmic_be_num > 1) {
> +			/* set up 2 BE links at most */
> +			links[id + 1].name = "dmic16k";
> +			links[id + 1].cpus = &cpus[id + 1];
> +			links[id + 1].cpus->dai_name = "DMIC16k Pin";
> +			dmic_be_num = 2;
> +		}
> +	} else {
> +		/* HDMI dai link starts at 3 according to current topology settings */
> +		hdmi_id_offset = 2;
> +	}
> +
> +	for (i = 0; i < dmic_be_num; i++) {
> +		links[id].id = id;
> +		links[id].num_cpus = 1;
> +		links[id].codecs = dmic_component;
> +		links[id].num_codecs = ARRAY_SIZE(dmic_component);
> +		links[id].platforms = platform_component;
> +		links[id].num_platforms = ARRAY_SIZE(platform_component);
> +		links[id].ignore_suspend = 1;
> +		links[id].dpcm_capture = 1;
> +		links[id].no_pcm = 1;
> +
> +		id++;
> +	}
> +
> +	/* HDMI */
> +	if (hdmi_num > 0) {
> +		idisp_components = devm_kzalloc(dev,
> +						sizeof(struct snd_soc_dai_link_component) *
> +						hdmi_num, GFP_KERNEL);
> +		if (!idisp_components)
> +			goto devm_err;
> +	}
> +
> +	for (i = 1; i <= hdmi_num; i++) {
> +		links[id].name = devm_kasprintf(dev, GFP_KERNEL,
> +						"iDisp%d", i);
> +		if (!links[id].name)
> +			goto devm_err;
> +
> +		links[id].id = id + hdmi_id_offset;
> +		links[id].cpus = &cpus[id];
> +		links[id].num_cpus = 1;
> +		links[id].cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL,
> +							  "iDisp%d Pin", i);
> +		if (!links[id].cpus->dai_name)
> +			goto devm_err;
> +
> +		idisp_components[i - 1].name = "ehdaudio0D2";
> +		idisp_components[i - 1].dai_name = devm_kasprintf(dev,
> +								  GFP_KERNEL,
> +								  "intel-hdmi-hifi%d",
> +								  i);
> +		if (!idisp_components[i - 1].dai_name)
> +			goto devm_err;
> +
> +		links[id].codecs = &idisp_components[i - 1];
> +		links[id].num_codecs = 1;
> +		links[id].platforms = platform_component;
> +		links[id].num_platforms = ARRAY_SIZE(platform_component);
> +		links[id].init = sof_hdmi_init;
> +		links[id].dpcm_playback = 1;
> +		links[id].no_pcm = 1;
> +
> +		id++;
> +	}
> +
> +	return links;
> +
> +devm_err:
> +	return NULL;
> +}
> +
> + /* i2c-<HID>:00 with HID being 8 chars */
> +static char codec_name[SND_ACPI_I2C_ID_LEN];
> +
> +static int sof_es8336_probe(struct platform_device *pdev)
> +{
> +	struct device *dev = &pdev->dev;
> +	struct snd_soc_card *card;
> +	struct snd_soc_acpi_mach *mach = pdev->dev.platform_data;
> +	struct sof_es8336_private *priv;
> +	struct acpi_device *adev;
> +	struct snd_soc_dai_link *dai_links;
> +	struct device *codec_dev;
> +	int dmic_be_num = 0;
> +	int hdmi_num = 3;
> +	int ret;
> +
> +	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
> +	if (!priv)
> +		return -ENOMEM;
> +
> +	card = &sof_es8336_card;
> +	card->dev = dev;
> +
> +	if (!dmi_check_system(sof_es8336_quirk_table))
> +		quirk = SOF_ES8336_SSP_CODEC(2);
> +
> +	if (quirk & SOF_ES8336_ENABLE_DMIC)
> +		dmic_be_num = 2;
> +
> +	if (quirk_override != -1) {
> +		dev_info(dev, "Overriding quirk 0x%lx => 0x%x\n",
> +			 quirk, quirk_override);
> +		quirk = quirk_override;
> +	}
> +	log_quirks(dev);
> +
> +	sof_es8336_card.num_links += dmic_be_num + hdmi_num;
> +	dai_links = sof_card_dai_links_create(dev,
> +					      SOF_ES8336_SSP_CODEC(quirk),
> +					      dmic_be_num, hdmi_num);
> +	if (!dai_links)
> +		return -ENOMEM;
> +
> +	sof_es8336_card.dai_link = dai_links;
> +
> +	/* fixup codec name based on HID */
> +	adev = acpi_dev_get_first_match_dev(mach->id, NULL, -1);
> +	if (adev) {
> +		snprintf(codec_name, sizeof(codec_name),
> +			 "i2c-%s", acpi_dev_name(adev));
> +		put_device(&adev->dev);
> +		dai_links[0].codecs->name = codec_name;
> +	}
> +
> +	ret = snd_soc_fixup_dai_links_platform_name(&sof_es8336_card,
> +						    mach->mach_params.platform);
> +	if (ret)
> +		return ret;
> +
> +	/* get speaker enable GPIO */
> +	codec_dev = bus_find_device_by_name(&i2c_bus_type, NULL, codec_name);
> +	if (!codec_dev)
> +		return -EPROBE_DEFER;
> +
> +	ret = devm_acpi_dev_add_driver_gpios(codec_dev, gpio_mapping);
> +	if (ret)
> +		dev_warn(codec_dev, "unable to add GPIO mapping table\n");
> +
> +	priv->gpio_pa = gpiod_get(codec_dev, "pa-enable", GPIOD_OUT_LOW);
> +	if (IS_ERR(priv->gpio_pa)) {
> +		ret = PTR_ERR(priv->gpio_pa);
> +		dev_err(codec_dev, "%s, could not get pa-enable: %d\n",
> +			__func__, ret);
> +		goto err;
> +	}
> +
> +	priv->codec_dev = codec_dev;
> +	INIT_LIST_HEAD(&priv->hdmi_pcm_list);
> +
> +	snd_soc_card_set_drvdata(card, priv);
> +
> +	ret = devm_snd_soc_register_card(dev, card);
> +	if (ret) {
> +		gpiod_put(priv->gpio_pa);
> +		dev_err(dev, "snd_soc_register_card failed: %d\n", ret);
> +		goto err;
> +	}
> +	platform_set_drvdata(pdev, &sof_es8336_card);
> +	return 0;
> +
> +err:
> +	put_device(codec_dev);
> +	return ret;
> +}
> +
> +static int sof_es8336_remove(struct platform_device *pdev)
> +{
> +	struct snd_soc_card *card = platform_get_drvdata(pdev);
> +	struct sof_es8336_private *priv = snd_soc_card_get_drvdata(card);
> +
> +	gpiod_put(priv->gpio_pa);
> +	put_device(priv->codec_dev);
> +
> +	return 0;
> +}
> +
> +static struct platform_driver sof_es8336_driver = {
> +	.driver = {
> +		.name = "sof-essx8336",
> +		.pm = &snd_soc_pm_ops,
> +	},
> +	.probe = sof_es8336_probe,
> +	.remove = sof_es8336_remove,
> +};
> +module_platform_driver(sof_es8336_driver);
> +
> +MODULE_DESCRIPTION("ASoC Intel(R) SOF + ES8336 Machine driver");
> +MODULE_LICENSE("GPL");
> +MODULE_ALIAS("platform:sof-essx8336");
> +MODULE_IMPORT_NS(SND_SOC_INTEL_HDA_DSP_COMMON);
> diff --git a/sound/soc/intel/common/soc-acpi-intel-bxt-match.c b/sound/soc/intel/common/soc-acpi-intel-bxt-match.c
> index 576407b5daf2..78cfdc48ad45 100644
> --- a/sound/soc/intel/common/soc-acpi-intel-bxt-match.c
> +++ b/sound/soc/intel/common/soc-acpi-intel-bxt-match.c
> @@ -82,6 +82,12 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_bxt_machines[] = {
>  		.sof_fw_filename = "sof-apl.ri",
>  		.sof_tplg_filename = "sof-apl-tdf8532.tplg",
>  	},
> +	{
> +		.id = "ESSX8336",
> +		.drv_name = "sof-essx8336",
> +		.sof_fw_filename = "sof-apl.ri",
> +		.sof_tplg_filename = "sof-apl-es8336.tplg",
> +	},
>  	{},
>  };
>  EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_bxt_machines);
> diff --git a/sound/soc/intel/common/soc-acpi-intel-cml-match.c b/sound/soc/intel/common/soc-acpi-intel-cml-match.c
> index b591c6fd13fd..f03fcc0806ea 100644
> --- a/sound/soc/intel/common/soc-acpi-intel-cml-match.c
> +++ b/sound/soc/intel/common/soc-acpi-intel-cml-match.c
> @@ -81,6 +81,12 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_cml_machines[] = {
>  		.sof_fw_filename = "sof-cml.ri",
>  		.sof_tplg_filename = "sof-cml-da7219-max98390.tplg",
>  	},
> +	{
> +		.id = "ESSX8336",
> +		.drv_name = "sof-essx8336",
> +		.sof_fw_filename = "sof-cml.ri",
> +		.sof_tplg_filename = "sof-cml-es8336.tplg",
> +	},
>  	{},
>  };
>  EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_cml_machines);
> diff --git a/sound/soc/intel/common/soc-acpi-intel-glk-match.c b/sound/soc/intel/common/soc-acpi-intel-glk-match.c
> index da1e151190b4..32fff9389eb3 100644
> --- a/sound/soc/intel/common/soc-acpi-intel-glk-match.c
> +++ b/sound/soc/intel/common/soc-acpi-intel-glk-match.c
> @@ -49,7 +49,12 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_glk_machines[] = {
>  		.sof_fw_filename = "sof-glk.ri",
>  		.sof_tplg_filename = "sof-glk-cs42l42.tplg",
>  	},
> -
> +	{
> +		.id = "ESSX8336",
> +		.drv_name = "sof-essx8336",
> +		.sof_fw_filename = "sof-glk.ri",
> +		.sof_tplg_filename = "sof-glk-es8336.tplg",
> +	},
>  	{},
>  };
>  EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_glk_machines);
> diff --git a/sound/soc/intel/common/soc-acpi-intel-jsl-match.c b/sound/soc/intel/common/soc-acpi-intel-jsl-match.c
> index 69ff7286d357..87923bcf9488 100644
> --- a/sound/soc/intel/common/soc-acpi-intel-jsl-match.c
> +++ b/sound/soc/intel/common/soc-acpi-intel-jsl-match.c
> @@ -81,6 +81,12 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_jsl_machines[] = {
>  		.quirk_data = &mx98360a_spk,
>  		.sof_tplg_filename = "sof-jsl-cs42l42-mx98360a.tplg",
>  	},
> +	{
> +		.id = "ESSX8336",
> +		.drv_name = "sof-essx8336",
> +		.sof_fw_filename = "sof-jsl.ri",
> +		.sof_tplg_filename = "sof-jsl-es8336.tplg",
> +	},
>  	{},
>  };
>  EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_jsl_machines);
> diff --git a/sound/soc/intel/common/soc-acpi-intel-tgl-match.c b/sound/soc/intel/common/soc-acpi-intel-tgl-match.c
> index 11801b905ecc..c2c5337ed3b8 100644
> --- a/sound/soc/intel/common/soc-acpi-intel-tgl-match.c
> +++ b/sound/soc/intel/common/soc-acpi-intel-tgl-match.c
> @@ -383,6 +383,12 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_tgl_machines[] = {
>  		.sof_fw_filename = "sof-tgl.ri",
>  		.sof_tplg_filename = "sof-tgl-rt1011-rt5682.tplg",
>  	},
> +	{
> +		.id = "ESSX8336",
> +		.drv_name = "sof-essx8336",
> +		.sof_fw_filename = "sof-tgl.ri",
> +		.sof_tplg_filename = "sof-tgl-es8336.tplg",
> +	},
>  	{},
>  };
>  EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_tgl_machines);
> -- 
> 2.33.0
> 
> _______________________________________________
> devel-kernel mailing list
> devel-kernel@lists.altlinux.org
> https://lists.altlinux.org/mailman/listinfo/devel-kernel


^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [d-kernel] [PATCH 1/9] commit 0b220578c2aab3d5ac6b693117e8c5d22e8c2b34
  2022-04-04 14:48     ` Vitaly Chikunov
@ 2022-04-04 15:16       ` Nikolai Kostrigin
  2022-04-07 11:15         ` [d-kernel] [PATCH v2 1/9] ASoC: Intel: add machine driver for SOF+ES8336 nickel
  0 siblings, 1 reply; 28+ messages in thread
From: Nikolai Kostrigin @ 2022-04-04 15:16 UTC (permalink / raw)
  To: devel-kernel



04.04.2022 17:48, Vitaly Chikunov пишет:
> Hi,
> 
> 
> On Mon, Apr 04, 2022 at 09:28:41AM +0300, nickel@altlinux.org wrote:
>> From: Vasily Vinogradov <v.vinogradov@aq.ru>
>>
>>      ASoC: Intel: add machine driver for SOF+ES8336
> 
> А что это за формат коммитов - нельзя ли в нормальном?
> Чтоб в Subject было commit message (видимо это будет "ASoC: Intel:
> add machine driver for SOF+ES8336", а не некий "commit XYZ". И,
> желательно, чтоб в описании оригинальное описание и ссылка на откуда
> это взято. Потому-что анонимный коммит из интернета и коммит из апстрима
> это разное качество и количество тестирования.
> 
> Спасибо,

Думаю, что можно, но, чтобы ответить наверняка, свяжусь с автором этой 
части бэкпорта для консультаций.

> 
> 
>> ---
>>   sound/hda/intel-dsp-config.c                  |  24 +-
>>   sound/soc/codecs/es8316.c                     |   1 +
>>   sound/soc/intel/boards/Kconfig                |  13 +
>>   sound/soc/intel/boards/Makefile               |   2 +
>>   sound/soc/intel/boards/sof_es8336.c           | 569 ++++++++++++++++++
>>   .../intel/common/soc-acpi-intel-bxt-match.c   |   6 +
>>   .../intel/common/soc-acpi-intel-cml-match.c   |   6 +
>>   .../intel/common/soc-acpi-intel-glk-match.c   |   7 +-
>>   .../intel/common/soc-acpi-intel-jsl-match.c   |   6 +
>>   .../intel/common/soc-acpi-intel-tgl-match.c   |   6 +
>>   10 files changed, 627 insertions(+), 13 deletions(-)
>>   create mode 100644 sound/soc/intel/boards/sof_es8336.c
>>
>> diff --git a/sound/hda/intel-dsp-config.c b/sound/hda/intel-dsp-config.c
>> index 4208fa8a4db5..f63114317ac9 100644
>> --- a/sound/hda/intel-dsp-config.c
>> +++ b/sound/hda/intel-dsp-config.c
>> @@ -249,13 +249,13 @@ static const struct config_entry config_table[] = {
>>   		}
>>   	},
>>   	{
>> -		.flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE,
>> +		.flags = FLAG_SOF,
>>   		.device = 0x02c8,
>> +		.codec_hid = "ESSX8336",
>>   	},
>>   	{
>> -		.flags = FLAG_SOF,
>> +		.flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE,
>>   		.device = 0x02c8,
>> -		.codec_hid = "ESSX8336",
>>   	},
>>   /* Cometlake-H */
>>   	{
>> @@ -278,14 +278,14 @@ static const struct config_entry config_table[] = {
>>   		}
>>   	},
>>   	{
>> -		.flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE,
>> -		.device = 0x06c8,
>> -	},
>> -		{
>>   		.flags = FLAG_SOF,
>>   		.device = 0x06c8,
>>   		.codec_hid = "ESSX8336",
>>   	},
>> +	{
>> +		.flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE,
>> +		.device = 0x06c8,
>> +	},
>>   #endif
>>   
>>   /* Icelake */
>> @@ -334,17 +334,17 @@ static const struct config_entry config_table[] = {
>>   		}
>>   	},
>>   	{
>> -		.flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE,
>> +		.flags = FLAG_SOF,
>>   		.device = 0xa0c8,
>> +		.codec_hid = "ESSX8336",
>>   	},
>>   	{
>>   		.flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE,
>> -		.device = 0x43c8,
>> +		.device = 0xa0c8,
>>   	},
>>   	{
>> -		.flags = FLAG_SOF,
>> -		.device = 0xa0c8,
>> -		.codec_hid = "ESSX8336",
>> +		.flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE,
>> +		.device = 0x43c8,
>>   	},
>>   #endif
>>   
>> diff --git a/sound/soc/codecs/es8316.c b/sound/soc/codecs/es8316.c
>> index 5fb02635c140..8f30a3ea8bfe 100644
>> --- a/sound/soc/codecs/es8316.c
>> +++ b/sound/soc/codecs/es8316.c
>> @@ -840,6 +840,7 @@ MODULE_DEVICE_TABLE(of, es8316_of_match);
>>   #ifdef CONFIG_ACPI
>>   static const struct acpi_device_id es8316_acpi_match[] = {
>>   	{"ESSX8316", 0},
>> +	{"ESSX8336", 0},
>>   	{},
>>   };
>>   MODULE_DEVICE_TABLE(acpi, es8316_acpi_match);
>> diff --git a/sound/soc/intel/boards/Kconfig b/sound/soc/intel/boards/Kconfig
>> index 61b71d6c44cf..a5b70ad98424 100644
>> --- a/sound/soc/intel/boards/Kconfig
>> +++ b/sound/soc/intel/boards/Kconfig
>> @@ -511,6 +511,19 @@ config SND_SOC_INTEL_SOF_PCM512x_MACH
>>   	  Say Y or m if you have such a device.
>>   	  If unsure select "N".
>>   
>> +config SND_SOC_INTEL_SOF_ES8336_MACH
>> +	tristate "SOF with ES8336 codec in I2S mode"
>> +	depends on I2C && ACPI && GPIOLIB
>> +	depends on MFD_INTEL_LPSS || COMPILE_TEST
>> +	depends on SND_HDA_CODEC_HDMI && SND_SOC_SOF_HDA_AUDIO_CODEC
>> +	select SND_SOC_ES8316
>> +	select SND_SOC_DMIC
>> +	help
>> +	   This adds support for ASoC machine driver for SOF platforms
>> +	   with es8336 codec.
>> +	   Say Y if you have such a device.
>> +	   If unsure select "N".
>> +
>>   endif ## SND_SOC_SOF_HDA_LINK || SND_SOC_SOF_BAYTRAIL
>>   
>>   if (SND_SOC_SOF_COMETLAKE && SND_SOC_SOF_HDA_LINK)
>> diff --git a/sound/soc/intel/boards/Makefile b/sound/soc/intel/boards/Makefile
>> index ed21b82a4cf6..de72ef29279e 100644
>> --- a/sound/soc/intel/boards/Makefile
>> +++ b/sound/soc/intel/boards/Makefile
>> @@ -22,6 +22,7 @@ snd-soc-sst-byt-cht-nocodec-objs := bytcht_nocodec.o
>>   snd-soc-sof_rt5682-objs := sof_rt5682.o sof_realtek_common.o
>>   snd-soc-sof_cs42l42-objs := sof_cs42l42.o
>>   snd-soc-cml_rt1011_rt5682-objs := cml_rt1011_rt5682.o
>> +snd-soc-sof_es8336-objs := sof_es8336.o
>>   snd-soc-kbl_da7219_max98357a-objs := kbl_da7219_max98357a.o
>>   snd-soc-kbl_da7219_max98927-objs := kbl_da7219_max98927.o
>>   snd-soc-kbl_rt5663_max98927-objs := kbl_rt5663_max98927.o
>> @@ -42,6 +43,7 @@ snd-soc-sof-sdw-objs += sof_sdw.o				\
>>   			sof_sdw_dmic.o sof_sdw_hdmi.o
>>   obj-$(CONFIG_SND_SOC_INTEL_SOF_RT5682_MACH) += snd-soc-sof_rt5682.o
>>   obj-$(CONFIG_SND_SOC_INTEL_SOF_CS42L42_MACH) += snd-soc-sof_cs42l42.o
>> +obj-$(CONFIG_SND_SOC_INTEL_SOF_ES8336_MACH) += snd-soc-sof_es8336.o
>>   obj-$(CONFIG_SND_SOC_INTEL_HASWELL_MACH) += snd-soc-sst-haswell.o
>>   obj-$(CONFIG_SND_SOC_INTEL_BXT_DA7219_MAX98357A_COMMON) += snd-soc-sst-bxt-da7219_max98357a.o
>>   obj-$(CONFIG_SND_SOC_INTEL_BXT_RT298_MACH) += snd-soc-sst-bxt-rt298.o
>> diff --git a/sound/soc/intel/boards/sof_es8336.c b/sound/soc/intel/boards/sof_es8336.c
>> new file mode 100644
>> index 000000000000..20d577eaab6d
>> --- /dev/null
>> +++ b/sound/soc/intel/boards/sof_es8336.c
>> @@ -0,0 +1,569 @@
>> +// SPDX-License-Identifier: GPL-2.0-only
>> +// Copyright(c) 2021 Intel Corporation.
>> +
>> +/*
>> + * Intel SOF Machine Driver with es8336 Codec
>> + */
>> +
>> +#include <linux/device.h>
>> +#include <linux/dmi.h>
>> +#include <linux/gpio/consumer.h>
>> +#include <linux/gpio/machine.h>
>> +#include <linux/i2c.h>
>> +#include <linux/input.h>
>> +#include <linux/module.h>
>> +#include <linux/platform_device.h>
>> +#include <linux/slab.h>
>> +#include <sound/jack.h>
>> +#include <sound/pcm.h>
>> +#include <sound/pcm_params.h>
>> +#include <sound/soc.h>
>> +#include <sound/soc-acpi.h>
>> +#include "hda_dsp_common.h"
>> +
>> +#define SOF_ES8336_SSP_CODEC(quirk)		((quirk) & GENMASK(3, 0))
>> +#define SOF_ES8336_SSP_CODEC_MASK		(GENMASK(3, 0))
>> +
>> +#define SOF_ES8336_TGL_GPIO_QUIRK		BIT(4)
>> +#define SOF_ES8336_ENABLE_DMIC			BIT(5)
>> +
>> +static unsigned long quirk;
>> +
>> +static int quirk_override = -1;
>> +module_param_named(quirk, quirk_override, int, 0444);
>> +MODULE_PARM_DESC(quirk, "Board-specific quirk override");
>> +
>> +struct sof_es8336_private {
>> +	struct device *codec_dev;
>> +	struct gpio_desc *gpio_pa;
>> +	struct snd_soc_jack jack;
>> +	struct list_head hdmi_pcm_list;
>> +	bool speaker_en;
>> +};
>> +
>> +struct sof_hdmi_pcm {
>> +	struct list_head head;
>> +	struct snd_soc_dai *codec_dai;
>> +	int device;
>> +};
>> +
>> +static const struct acpi_gpio_params pa_enable_gpio = { 0, 0, true };
>> +static const struct acpi_gpio_mapping acpi_es8336_gpios[] = {
>> +	{ "pa-enable-gpios", &pa_enable_gpio, 1 },
>> +	{ }
>> +};
>> +
>> +static const struct acpi_gpio_params quirk_pa_enable_gpio = { 1, 0, true };
>> +static const struct acpi_gpio_mapping quirk_acpi_es8336_gpios[] = {
>> +	{ "pa-enable-gpios", &quirk_pa_enable_gpio, 1 },
>> +	{ }
>> +};
>> +
>> +static const struct acpi_gpio_mapping *gpio_mapping = acpi_es8336_gpios;
>> +
>> +static void log_quirks(struct device *dev)
>> +{
>> +	dev_info(dev, "quirk SSP%ld",  SOF_ES8336_SSP_CODEC(quirk));
>> +}
>> +
>> +static int sof_es8316_speaker_power_event(struct snd_soc_dapm_widget *w,
>> +					  struct snd_kcontrol *kcontrol, int event)
>> +{
>> +	struct snd_soc_card *card = w->dapm->card;
>> +	struct sof_es8336_private *priv = snd_soc_card_get_drvdata(card);
>> +
>> +	if (SND_SOC_DAPM_EVENT_ON(event))
>> +		priv->speaker_en = false;
>> +	else
>> +		priv->speaker_en = true;
>> +
>> +	gpiod_set_value_cansleep(priv->gpio_pa, priv->speaker_en);
>> +
>> +	return 0;
>> +}
>> +
>> +static const struct snd_soc_dapm_widget sof_es8316_widgets[] = {
>> +	SND_SOC_DAPM_SPK("Speaker", NULL),
>> +	SND_SOC_DAPM_HP("Headphone", NULL),
>> +	SND_SOC_DAPM_MIC("Headset Mic", NULL),
>> +	SND_SOC_DAPM_MIC("Internal Mic", NULL),
>> +
>> +	SND_SOC_DAPM_SUPPLY("Speaker Power", SND_SOC_NOPM, 0, 0,
>> +			    sof_es8316_speaker_power_event,
>> +			    SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
>> +};
>> +
>> +static const struct snd_soc_dapm_widget dmic_widgets[] = {
>> +	SND_SOC_DAPM_MIC("SoC DMIC", NULL),
>> +};
>> +
>> +static const struct snd_soc_dapm_route sof_es8316_audio_map[] = {
>> +	{"Headphone", NULL, "HPOL"},
>> +	{"Headphone", NULL, "HPOR"},
>> +
>> +	/*
>> +	 * There is no separate speaker output instead the speakers are muxed to
>> +	 * the HP outputs. The mux is controlled by the "Speaker Power" supply.
>> +	 */
>> +	{"Speaker", NULL, "HPOL"},
>> +	{"Speaker", NULL, "HPOR"},
>> +	{"Speaker", NULL, "Speaker Power"},
>> +};
>> +
>> +static const struct snd_soc_dapm_route sof_es8316_intmic_in1_map[] = {
>> +	{"MIC1", NULL, "Internal Mic"},
>> +	{"MIC2", NULL, "Headset Mic"},
>> +};
>> +
>> +static const struct snd_soc_dapm_route dmic_map[] = {
>> +	/* digital mics */
>> +	{"DMic", NULL, "SoC DMIC"},
>> +};
>> +
>> +static const struct snd_kcontrol_new sof_es8316_controls[] = {
>> +	SOC_DAPM_PIN_SWITCH("Speaker"),
>> +	SOC_DAPM_PIN_SWITCH("Headphone"),
>> +	SOC_DAPM_PIN_SWITCH("Headset Mic"),
>> +	SOC_DAPM_PIN_SWITCH("Internal Mic"),
>> +};
>> +
>> +static struct snd_soc_jack_pin sof_es8316_jack_pins[] = {
>> +	{
>> +		.pin	= "Headphone",
>> +		.mask	= SND_JACK_HEADPHONE,
>> +	},
>> +	{
>> +		.pin	= "Headset Mic",
>> +		.mask	= SND_JACK_MICROPHONE,
>> +	},
>> +};
>> +
>> +static int dmic_init(struct snd_soc_pcm_runtime *runtime)
>> +{
>> +	struct snd_soc_card *card = runtime->card;
>> +	int ret;
>> +
>> +	ret = snd_soc_dapm_new_controls(&card->dapm, dmic_widgets,
>> +					ARRAY_SIZE(dmic_widgets));
>> +	if (ret) {
>> +		dev_err(card->dev, "DMic widget addition failed: %d\n", ret);
>> +		return ret;
>> +	}
>> +
>> +	ret = snd_soc_dapm_add_routes(&card->dapm, dmic_map,
>> +				      ARRAY_SIZE(dmic_map));
>> +	if (ret)
>> +		dev_err(card->dev, "DMic map addition failed: %d\n", ret);
>> +
>> +	return ret;
>> +}
>> +
>> +static int sof_hdmi_init(struct snd_soc_pcm_runtime *runtime)
>> +{
>> +	struct sof_es8336_private *priv = snd_soc_card_get_drvdata(runtime->card);
>> +	struct snd_soc_dai *dai = asoc_rtd_to_codec(runtime, 0);
>> +	struct sof_hdmi_pcm *pcm;
>> +
>> +	pcm = devm_kzalloc(runtime->card->dev, sizeof(*pcm), GFP_KERNEL);
>> +	if (!pcm)
>> +		return -ENOMEM;
>> +
>> +	/* dai_link id is 1:1 mapped to the PCM device */
>> +	pcm->device = runtime->dai_link->id;
>> +	pcm->codec_dai = dai;
>> +
>> +	list_add_tail(&pcm->head, &priv->hdmi_pcm_list);
>> +
>> +	return 0;
>> +}
>> +
>> +static int sof_es8316_init(struct snd_soc_pcm_runtime *runtime)
>> +{
>> +	struct snd_soc_component *codec = asoc_rtd_to_codec(runtime, 0)->component;
>> +	struct snd_soc_card *card = runtime->card;
>> +	struct sof_es8336_private *priv = snd_soc_card_get_drvdata(card);
>> +	const struct snd_soc_dapm_route *custom_map;
>> +	int num_routes;
>> +	int ret;
>> +
>> +	card->dapm.idle_bias_off = true;
>> +
>> +	custom_map = sof_es8316_intmic_in1_map;
>> +	num_routes = ARRAY_SIZE(sof_es8316_intmic_in1_map);
>> +
>> +	ret = snd_soc_dapm_add_routes(&card->dapm, custom_map, num_routes);
>> +	if (ret)
>> +		return ret;
>> +
>> +	ret = snd_soc_card_jack_new(card, "Headset",
>> +				    SND_JACK_HEADSET | SND_JACK_BTN_0,
>> +				    &priv->jack, sof_es8316_jack_pins,
>> +				    ARRAY_SIZE(sof_es8316_jack_pins));
>> +	if (ret) {
>> +		dev_err(card->dev, "jack creation failed %d\n", ret);
>> +		return ret;
>> +	}
>> +
>> +	snd_jack_set_key(priv->jack.jack, SND_JACK_BTN_0, KEY_PLAYPAUSE);
>> +
>> +	snd_soc_component_set_jack(codec, &priv->jack, NULL);
>> +
>> +	return 0;
>> +}
>> +
>> +static void sof_es8316_exit(struct snd_soc_pcm_runtime *rtd)
>> +{
>> +	struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component;
>> +
>> +	snd_soc_component_set_jack(component, NULL, NULL);
>> +}
>> +
>> +static int sof_es8336_quirk_cb(const struct dmi_system_id *id)
>> +{
>> +	quirk = (unsigned long)id->driver_data;
>> +
>> +	if (quirk & SOF_ES8336_TGL_GPIO_QUIRK)
>> +		gpio_mapping = quirk_acpi_es8336_gpios;
>> +
>> +	return 1;
>> +}
>> +
>> +static const struct dmi_system_id sof_es8336_quirk_table[] = {
>> +	{
>> +		.callback = sof_es8336_quirk_cb,
>> +		.matches = {
>> +			DMI_MATCH(DMI_SYS_VENDOR, "CHUWI Innovation And Technology"),
>> +			DMI_MATCH(DMI_BOARD_NAME, "Hi10 X"),
>> +		},
>> +		.driver_data = (void *)SOF_ES8336_SSP_CODEC(2)
>> +	},
>> +	{
>> +		.callback = sof_es8336_quirk_cb,
>> +		.matches = {
>> +			DMI_MATCH(DMI_SYS_VENDOR, "IP3 tech"),
>> +			DMI_MATCH(DMI_BOARD_NAME, "WN1"),
>> +		},
>> +		.driver_data = (void *)(SOF_ES8336_SSP_CODEC(0) |
>> +					SOF_ES8336_TGL_GPIO_QUIRK |
>> +					SOF_ES8336_ENABLE_DMIC)
>> +	},
>> +	{}
>> +};
>> +
>> +static int sof_es8336_hw_params(struct snd_pcm_substream *substream,
>> +				struct snd_pcm_hw_params *params)
>> +{
>> +	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
>> +	struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
>> +	const int sysclk = 19200000;
>> +	int ret;
>> +
>> +	ret = snd_soc_dai_set_sysclk(codec_dai, 1, sysclk, SND_SOC_CLOCK_OUT);
>> +	if (ret < 0) {
>> +		dev_err(rtd->dev, "%s, Failed to set ES8336 SYSCLK: %d\n",
>> +			__func__, ret);
>> +		return ret;
>> +	}
>> +
>> +	return 0;
>> +}
>> +
>> +/* machine stream operations */
>> +static struct snd_soc_ops sof_es8336_ops = {
>> +	.hw_params = sof_es8336_hw_params,
>> +};
>> +
>> +static struct snd_soc_dai_link_component platform_component[] = {
>> +	{
>> +		/* name might be overridden during probe */
>> +		.name = "0000:00:1f.3"
>> +	}
>> +};
>> +
>> +SND_SOC_DAILINK_DEF(ssp1_codec,
>> +	DAILINK_COMP_ARRAY(COMP_CODEC("i2c-ESSX8336:00", "ES8316 HiFi")));
>> +
>> +static struct snd_soc_dai_link_component dmic_component[] = {
>> +	{
>> +		.name = "dmic-codec",
>> +		.dai_name = "dmic-hifi",
>> +	}
>> +};
>> +
>> +static int sof_es8336_late_probe(struct snd_soc_card *card)
>> +{
>> +	struct sof_es8336_private *priv = snd_soc_card_get_drvdata(card);
>> +	struct sof_hdmi_pcm *pcm;
>> +
>> +	if (list_empty(&priv->hdmi_pcm_list))
>> +		return -ENOENT;
>> +
>> +	pcm = list_first_entry(&priv->hdmi_pcm_list, struct sof_hdmi_pcm, head);
>> +
>> +	return hda_dsp_hdmi_build_controls(card, pcm->codec_dai->component);
>> +}
>> +
>> +/* SoC card */
>> +static struct snd_soc_card sof_es8336_card = {
>> +	.name = "essx8336", /* sof- prefix added automatically */
>> +	.owner = THIS_MODULE,
>> +	.dapm_widgets = sof_es8316_widgets,
>> +	.num_dapm_widgets = ARRAY_SIZE(sof_es8316_widgets),
>> +	.dapm_routes = sof_es8316_audio_map,
>> +	.num_dapm_routes = ARRAY_SIZE(sof_es8316_audio_map),
>> +	.controls = sof_es8316_controls,
>> +	.num_controls = ARRAY_SIZE(sof_es8316_controls),
>> +	.fully_routed = true,
>> +	.late_probe = sof_es8336_late_probe,
>> +	.num_links = 1,
>> +};
>> +
>> +static struct snd_soc_dai_link *sof_card_dai_links_create(struct device *dev,
>> +							  int ssp_codec,
>> +							  int dmic_be_num,
>> +							  int hdmi_num)
>> +{
>> +	struct snd_soc_dai_link_component *cpus;
>> +	struct snd_soc_dai_link *links;
>> +	struct snd_soc_dai_link_component *idisp_components;
>> +	int hdmi_id_offset = 0;
>> +	int id = 0;
>> +	int i;
>> +
>> +	links = devm_kcalloc(dev, sof_es8336_card.num_links,
>> +			     sizeof(struct snd_soc_dai_link), GFP_KERNEL);
>> +	cpus = devm_kcalloc(dev, sof_es8336_card.num_links,
>> +			    sizeof(struct snd_soc_dai_link_component), GFP_KERNEL);
>> +	if (!links || !cpus)
>> +		goto devm_err;
>> +
>> +	/* codec SSP */
>> +	links[id].name = devm_kasprintf(dev, GFP_KERNEL,
>> +					"SSP%d-Codec", ssp_codec);
>> +	if (!links[id].name)
>> +		goto devm_err;
>> +
>> +	links[id].id = id;
>> +	links[id].codecs = ssp1_codec;
>> +	links[id].num_codecs = ARRAY_SIZE(ssp1_codec);
>> +	links[id].platforms = platform_component;
>> +	links[id].num_platforms = ARRAY_SIZE(platform_component);
>> +	links[id].init = sof_es8316_init;
>> +	links[id].exit = sof_es8316_exit;
>> +	links[id].ops = &sof_es8336_ops;
>> +	links[id].nonatomic = true;
>> +	links[id].dpcm_playback = 1;
>> +	links[id].dpcm_capture = 1;
>> +	links[id].no_pcm = 1;
>> +	links[id].cpus = &cpus[id];
>> +	links[id].num_cpus = 1;
>> +
>> +	links[id].cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL,
>> +						  "SSP%d Pin",
>> +						  ssp_codec);
>> +	if (!links[id].cpus->dai_name)
>> +		goto devm_err;
>> +
>> +	id++;
>> +
>> +	/* dmic */
>> +	if (dmic_be_num > 0) {
>> +		/* at least we have dmic01 */
>> +		links[id].name = "dmic01";
>> +		links[id].cpus = &cpus[id];
>> +		links[id].cpus->dai_name = "DMIC01 Pin";
>> +		links[id].init = dmic_init;
>> +		if (dmic_be_num > 1) {
>> +			/* set up 2 BE links at most */
>> +			links[id + 1].name = "dmic16k";
>> +			links[id + 1].cpus = &cpus[id + 1];
>> +			links[id + 1].cpus->dai_name = "DMIC16k Pin";
>> +			dmic_be_num = 2;
>> +		}
>> +	} else {
>> +		/* HDMI dai link starts at 3 according to current topology settings */
>> +		hdmi_id_offset = 2;
>> +	}
>> +
>> +	for (i = 0; i < dmic_be_num; i++) {
>> +		links[id].id = id;
>> +		links[id].num_cpus = 1;
>> +		links[id].codecs = dmic_component;
>> +		links[id].num_codecs = ARRAY_SIZE(dmic_component);
>> +		links[id].platforms = platform_component;
>> +		links[id].num_platforms = ARRAY_SIZE(platform_component);
>> +		links[id].ignore_suspend = 1;
>> +		links[id].dpcm_capture = 1;
>> +		links[id].no_pcm = 1;
>> +
>> +		id++;
>> +	}
>> +
>> +	/* HDMI */
>> +	if (hdmi_num > 0) {
>> +		idisp_components = devm_kzalloc(dev,
>> +						sizeof(struct snd_soc_dai_link_component) *
>> +						hdmi_num, GFP_KERNEL);
>> +		if (!idisp_components)
>> +			goto devm_err;
>> +	}
>> +
>> +	for (i = 1; i <= hdmi_num; i++) {
>> +		links[id].name = devm_kasprintf(dev, GFP_KERNEL,
>> +						"iDisp%d", i);
>> +		if (!links[id].name)
>> +			goto devm_err;
>> +
>> +		links[id].id = id + hdmi_id_offset;
>> +		links[id].cpus = &cpus[id];
>> +		links[id].num_cpus = 1;
>> +		links[id].cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL,
>> +							  "iDisp%d Pin", i);
>> +		if (!links[id].cpus->dai_name)
>> +			goto devm_err;
>> +
>> +		idisp_components[i - 1].name = "ehdaudio0D2";
>> +		idisp_components[i - 1].dai_name = devm_kasprintf(dev,
>> +								  GFP_KERNEL,
>> +								  "intel-hdmi-hifi%d",
>> +								  i);
>> +		if (!idisp_components[i - 1].dai_name)
>> +			goto devm_err;
>> +
>> +		links[id].codecs = &idisp_components[i - 1];
>> +		links[id].num_codecs = 1;
>> +		links[id].platforms = platform_component;
>> +		links[id].num_platforms = ARRAY_SIZE(platform_component);
>> +		links[id].init = sof_hdmi_init;
>> +		links[id].dpcm_playback = 1;
>> +		links[id].no_pcm = 1;
>> +
>> +		id++;
>> +	}
>> +
>> +	return links;
>> +
>> +devm_err:
>> +	return NULL;
>> +}
>> +
>> + /* i2c-<HID>:00 with HID being 8 chars */
>> +static char codec_name[SND_ACPI_I2C_ID_LEN];
>> +
>> +static int sof_es8336_probe(struct platform_device *pdev)
>> +{
>> +	struct device *dev = &pdev->dev;
>> +	struct snd_soc_card *card;
>> +	struct snd_soc_acpi_mach *mach = pdev->dev.platform_data;
>> +	struct sof_es8336_private *priv;
>> +	struct acpi_device *adev;
>> +	struct snd_soc_dai_link *dai_links;
>> +	struct device *codec_dev;
>> +	int dmic_be_num = 0;
>> +	int hdmi_num = 3;
>> +	int ret;
>> +
>> +	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
>> +	if (!priv)
>> +		return -ENOMEM;
>> +
>> +	card = &sof_es8336_card;
>> +	card->dev = dev;
>> +
>> +	if (!dmi_check_system(sof_es8336_quirk_table))
>> +		quirk = SOF_ES8336_SSP_CODEC(2);
>> +
>> +	if (quirk & SOF_ES8336_ENABLE_DMIC)
>> +		dmic_be_num = 2;
>> +
>> +	if (quirk_override != -1) {
>> +		dev_info(dev, "Overriding quirk 0x%lx => 0x%x\n",
>> +			 quirk, quirk_override);
>> +		quirk = quirk_override;
>> +	}
>> +	log_quirks(dev);
>> +
>> +	sof_es8336_card.num_links += dmic_be_num + hdmi_num;
>> +	dai_links = sof_card_dai_links_create(dev,
>> +					      SOF_ES8336_SSP_CODEC(quirk),
>> +					      dmic_be_num, hdmi_num);
>> +	if (!dai_links)
>> +		return -ENOMEM;
>> +
>> +	sof_es8336_card.dai_link = dai_links;
>> +
>> +	/* fixup codec name based on HID */
>> +	adev = acpi_dev_get_first_match_dev(mach->id, NULL, -1);
>> +	if (adev) {
>> +		snprintf(codec_name, sizeof(codec_name),
>> +			 "i2c-%s", acpi_dev_name(adev));
>> +		put_device(&adev->dev);
>> +		dai_links[0].codecs->name = codec_name;
>> +	}
>> +
>> +	ret = snd_soc_fixup_dai_links_platform_name(&sof_es8336_card,
>> +						    mach->mach_params.platform);
>> +	if (ret)
>> +		return ret;
>> +
>> +	/* get speaker enable GPIO */
>> +	codec_dev = bus_find_device_by_name(&i2c_bus_type, NULL, codec_name);
>> +	if (!codec_dev)
>> +		return -EPROBE_DEFER;
>> +
>> +	ret = devm_acpi_dev_add_driver_gpios(codec_dev, gpio_mapping);
>> +	if (ret)
>> +		dev_warn(codec_dev, "unable to add GPIO mapping table\n");
>> +
>> +	priv->gpio_pa = gpiod_get(codec_dev, "pa-enable", GPIOD_OUT_LOW);
>> +	if (IS_ERR(priv->gpio_pa)) {
>> +		ret = PTR_ERR(priv->gpio_pa);
>> +		dev_err(codec_dev, "%s, could not get pa-enable: %d\n",
>> +			__func__, ret);
>> +		goto err;
>> +	}
>> +
>> +	priv->codec_dev = codec_dev;
>> +	INIT_LIST_HEAD(&priv->hdmi_pcm_list);
>> +
>> +	snd_soc_card_set_drvdata(card, priv);
>> +
>> +	ret = devm_snd_soc_register_card(dev, card);
>> +	if (ret) {
>> +		gpiod_put(priv->gpio_pa);
>> +		dev_err(dev, "snd_soc_register_card failed: %d\n", ret);
>> +		goto err;
>> +	}
>> +	platform_set_drvdata(pdev, &sof_es8336_card);
>> +	return 0;
>> +
>> +err:
>> +	put_device(codec_dev);
>> +	return ret;
>> +}
>> +
>> +static int sof_es8336_remove(struct platform_device *pdev)
>> +{
>> +	struct snd_soc_card *card = platform_get_drvdata(pdev);
>> +	struct sof_es8336_private *priv = snd_soc_card_get_drvdata(card);
>> +
>> +	gpiod_put(priv->gpio_pa);
>> +	put_device(priv->codec_dev);
>> +
>> +	return 0;
>> +}
>> +
>> +static struct platform_driver sof_es8336_driver = {
>> +	.driver = {
>> +		.name = "sof-essx8336",
>> +		.pm = &snd_soc_pm_ops,
>> +	},
>> +	.probe = sof_es8336_probe,
>> +	.remove = sof_es8336_remove,
>> +};
>> +module_platform_driver(sof_es8336_driver);
>> +
>> +MODULE_DESCRIPTION("ASoC Intel(R) SOF + ES8336 Machine driver");
>> +MODULE_LICENSE("GPL");
>> +MODULE_ALIAS("platform:sof-essx8336");
>> +MODULE_IMPORT_NS(SND_SOC_INTEL_HDA_DSP_COMMON);
>> diff --git a/sound/soc/intel/common/soc-acpi-intel-bxt-match.c b/sound/soc/intel/common/soc-acpi-intel-bxt-match.c
>> index 576407b5daf2..78cfdc48ad45 100644
>> --- a/sound/soc/intel/common/soc-acpi-intel-bxt-match.c
>> +++ b/sound/soc/intel/common/soc-acpi-intel-bxt-match.c
>> @@ -82,6 +82,12 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_bxt_machines[] = {
>>   		.sof_fw_filename = "sof-apl.ri",
>>   		.sof_tplg_filename = "sof-apl-tdf8532.tplg",
>>   	},
>> +	{
>> +		.id = "ESSX8336",
>> +		.drv_name = "sof-essx8336",
>> +		.sof_fw_filename = "sof-apl.ri",
>> +		.sof_tplg_filename = "sof-apl-es8336.tplg",
>> +	},
>>   	{},
>>   };
>>   EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_bxt_machines);
>> diff --git a/sound/soc/intel/common/soc-acpi-intel-cml-match.c b/sound/soc/intel/common/soc-acpi-intel-cml-match.c
>> index b591c6fd13fd..f03fcc0806ea 100644
>> --- a/sound/soc/intel/common/soc-acpi-intel-cml-match.c
>> +++ b/sound/soc/intel/common/soc-acpi-intel-cml-match.c
>> @@ -81,6 +81,12 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_cml_machines[] = {
>>   		.sof_fw_filename = "sof-cml.ri",
>>   		.sof_tplg_filename = "sof-cml-da7219-max98390.tplg",
>>   	},
>> +	{
>> +		.id = "ESSX8336",
>> +		.drv_name = "sof-essx8336",
>> +		.sof_fw_filename = "sof-cml.ri",
>> +		.sof_tplg_filename = "sof-cml-es8336.tplg",
>> +	},
>>   	{},
>>   };
>>   EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_cml_machines);
>> diff --git a/sound/soc/intel/common/soc-acpi-intel-glk-match.c b/sound/soc/intel/common/soc-acpi-intel-glk-match.c
>> index da1e151190b4..32fff9389eb3 100644
>> --- a/sound/soc/intel/common/soc-acpi-intel-glk-match.c
>> +++ b/sound/soc/intel/common/soc-acpi-intel-glk-match.c
>> @@ -49,7 +49,12 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_glk_machines[] = {
>>   		.sof_fw_filename = "sof-glk.ri",
>>   		.sof_tplg_filename = "sof-glk-cs42l42.tplg",
>>   	},
>> -
>> +	{
>> +		.id = "ESSX8336",
>> +		.drv_name = "sof-essx8336",
>> +		.sof_fw_filename = "sof-glk.ri",
>> +		.sof_tplg_filename = "sof-glk-es8336.tplg",
>> +	},
>>   	{},
>>   };
>>   EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_glk_machines);
>> diff --git a/sound/soc/intel/common/soc-acpi-intel-jsl-match.c b/sound/soc/intel/common/soc-acpi-intel-jsl-match.c
>> index 69ff7286d357..87923bcf9488 100644
>> --- a/sound/soc/intel/common/soc-acpi-intel-jsl-match.c
>> +++ b/sound/soc/intel/common/soc-acpi-intel-jsl-match.c
>> @@ -81,6 +81,12 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_jsl_machines[] = {
>>   		.quirk_data = &mx98360a_spk,
>>   		.sof_tplg_filename = "sof-jsl-cs42l42-mx98360a.tplg",
>>   	},
>> +	{
>> +		.id = "ESSX8336",
>> +		.drv_name = "sof-essx8336",
>> +		.sof_fw_filename = "sof-jsl.ri",
>> +		.sof_tplg_filename = "sof-jsl-es8336.tplg",
>> +	},
>>   	{},
>>   };
>>   EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_jsl_machines);
>> diff --git a/sound/soc/intel/common/soc-acpi-intel-tgl-match.c b/sound/soc/intel/common/soc-acpi-intel-tgl-match.c
>> index 11801b905ecc..c2c5337ed3b8 100644
>> --- a/sound/soc/intel/common/soc-acpi-intel-tgl-match.c
>> +++ b/sound/soc/intel/common/soc-acpi-intel-tgl-match.c
>> @@ -383,6 +383,12 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_tgl_machines[] = {
>>   		.sof_fw_filename = "sof-tgl.ri",
>>   		.sof_tplg_filename = "sof-tgl-rt1011-rt5682.tplg",
>>   	},
>> +	{
>> +		.id = "ESSX8336",
>> +		.drv_name = "sof-essx8336",
>> +		.sof_fw_filename = "sof-tgl.ri",
>> +		.sof_tplg_filename = "sof-tgl-es8336.tplg",
>> +	},
>>   	{},
>>   };
>>   EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_tgl_machines);
>> -- 
>> 2.33.0
>>
>> _______________________________________________
>> devel-kernel mailing list
>> devel-kernel@lists.altlinux.org
>> https://lists.altlinux.org/mailman/listinfo/devel-kernel
> _______________________________________________
> devel-kernel mailing list
> devel-kernel@lists.altlinux.org
> https://lists.altlinux.org/mailman/listinfo/devel-kernel

-- 
Best regards,
Nikolai Kostrigin


^ permalink raw reply	[flat|nested] 28+ messages in thread

* [d-kernel] [PATCH v2 1/9] ASoC: Intel: add machine driver for SOF+ES8336
  2022-04-04 15:16       ` Nikolai Kostrigin
@ 2022-04-07 11:15         ` nickel
  2022-04-07 11:15           ` [d-kernel] [PATCH v2 2/9] ASoC: Intel: sof_es8336: Add quirk for inverted jack detect nickel
                             ` (8 more replies)
  0 siblings, 9 replies; 28+ messages in thread
From: nickel @ 2022-04-07 11:15 UTC (permalink / raw)
  To: devel-kernel; +Cc: Vasily Vinogradov

From: Vasily Vinogradov <v.vinogradov@aq.ru>

Backport from 5.17
Based on upstream commit a164137ce91a95a1a5e2f2ca381741aa5ba14b63

Link: https://lore.kernel.org/r/20211004213512.220836-4-pierre-louis.bossart@linux.intel.com
Signed-off-by: Vasily Vinogradov <v.vinogradov@aq.ru>
Signed-off-by: Nikolai Kostrigin <nickel@altlinux.org>
---
 sound/hda/intel-dsp-config.c                  |  24 +-
 sound/soc/codecs/es8316.c                     |   1 +
 sound/soc/intel/boards/Kconfig                |  13 +
 sound/soc/intel/boards/Makefile               |   2 +
 sound/soc/intel/boards/sof_es8336.c           | 569 ++++++++++++++++++
 .../intel/common/soc-acpi-intel-bxt-match.c   |   6 +
 .../intel/common/soc-acpi-intel-cml-match.c   |   6 +
 .../intel/common/soc-acpi-intel-glk-match.c   |   7 +-
 .../intel/common/soc-acpi-intel-jsl-match.c   |   6 +
 .../intel/common/soc-acpi-intel-tgl-match.c   |   6 +
 10 files changed, 627 insertions(+), 13 deletions(-)
 create mode 100644 sound/soc/intel/boards/sof_es8336.c

diff --git a/sound/hda/intel-dsp-config.c b/sound/hda/intel-dsp-config.c
index 4208fa8a4db5..f63114317ac9 100644
--- a/sound/hda/intel-dsp-config.c
+++ b/sound/hda/intel-dsp-config.c
@@ -249,13 +249,13 @@ static const struct config_entry config_table[] = {
 		}
 	},
 	{
-		.flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE,
+		.flags = FLAG_SOF,
 		.device = 0x02c8,
+		.codec_hid = "ESSX8336",
 	},
 	{
-		.flags = FLAG_SOF,
+		.flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE,
 		.device = 0x02c8,
-		.codec_hid = "ESSX8336",
 	},
 /* Cometlake-H */
 	{
@@ -278,14 +278,14 @@ static const struct config_entry config_table[] = {
 		}
 	},
 	{
-		.flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE,
-		.device = 0x06c8,
-	},
-		{
 		.flags = FLAG_SOF,
 		.device = 0x06c8,
 		.codec_hid = "ESSX8336",
 	},
+	{
+		.flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE,
+		.device = 0x06c8,
+	},
 #endif
 
 /* Icelake */
@@ -334,17 +334,17 @@ static const struct config_entry config_table[] = {
 		}
 	},
 	{
-		.flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE,
+		.flags = FLAG_SOF,
 		.device = 0xa0c8,
+		.codec_hid = "ESSX8336",
 	},
 	{
 		.flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE,
-		.device = 0x43c8,
+		.device = 0xa0c8,
 	},
 	{
-		.flags = FLAG_SOF,
-		.device = 0xa0c8,
-		.codec_hid = "ESSX8336",
+		.flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE,
+		.device = 0x43c8,
 	},
 #endif
 
diff --git a/sound/soc/codecs/es8316.c b/sound/soc/codecs/es8316.c
index 5fb02635c140..8f30a3ea8bfe 100644
--- a/sound/soc/codecs/es8316.c
+++ b/sound/soc/codecs/es8316.c
@@ -840,6 +840,7 @@ MODULE_DEVICE_TABLE(of, es8316_of_match);
 #ifdef CONFIG_ACPI
 static const struct acpi_device_id es8316_acpi_match[] = {
 	{"ESSX8316", 0},
+	{"ESSX8336", 0},
 	{},
 };
 MODULE_DEVICE_TABLE(acpi, es8316_acpi_match);
diff --git a/sound/soc/intel/boards/Kconfig b/sound/soc/intel/boards/Kconfig
index 61b71d6c44cf..a5b70ad98424 100644
--- a/sound/soc/intel/boards/Kconfig
+++ b/sound/soc/intel/boards/Kconfig
@@ -511,6 +511,19 @@ config SND_SOC_INTEL_SOF_PCM512x_MACH
 	  Say Y or m if you have such a device.
 	  If unsure select "N".
 
+config SND_SOC_INTEL_SOF_ES8336_MACH
+	tristate "SOF with ES8336 codec in I2S mode"
+	depends on I2C && ACPI && GPIOLIB
+	depends on MFD_INTEL_LPSS || COMPILE_TEST
+	depends on SND_HDA_CODEC_HDMI && SND_SOC_SOF_HDA_AUDIO_CODEC
+	select SND_SOC_ES8316
+	select SND_SOC_DMIC
+	help
+	   This adds support for ASoC machine driver for SOF platforms
+	   with es8336 codec.
+	   Say Y if you have such a device.
+	   If unsure select "N".
+
 endif ## SND_SOC_SOF_HDA_LINK || SND_SOC_SOF_BAYTRAIL
 
 if (SND_SOC_SOF_COMETLAKE && SND_SOC_SOF_HDA_LINK)
diff --git a/sound/soc/intel/boards/Makefile b/sound/soc/intel/boards/Makefile
index ed21b82a4cf6..de72ef29279e 100644
--- a/sound/soc/intel/boards/Makefile
+++ b/sound/soc/intel/boards/Makefile
@@ -22,6 +22,7 @@ snd-soc-sst-byt-cht-nocodec-objs := bytcht_nocodec.o
 snd-soc-sof_rt5682-objs := sof_rt5682.o sof_realtek_common.o
 snd-soc-sof_cs42l42-objs := sof_cs42l42.o
 snd-soc-cml_rt1011_rt5682-objs := cml_rt1011_rt5682.o
+snd-soc-sof_es8336-objs := sof_es8336.o
 snd-soc-kbl_da7219_max98357a-objs := kbl_da7219_max98357a.o
 snd-soc-kbl_da7219_max98927-objs := kbl_da7219_max98927.o
 snd-soc-kbl_rt5663_max98927-objs := kbl_rt5663_max98927.o
@@ -42,6 +43,7 @@ snd-soc-sof-sdw-objs += sof_sdw.o				\
 			sof_sdw_dmic.o sof_sdw_hdmi.o
 obj-$(CONFIG_SND_SOC_INTEL_SOF_RT5682_MACH) += snd-soc-sof_rt5682.o
 obj-$(CONFIG_SND_SOC_INTEL_SOF_CS42L42_MACH) += snd-soc-sof_cs42l42.o
+obj-$(CONFIG_SND_SOC_INTEL_SOF_ES8336_MACH) += snd-soc-sof_es8336.o
 obj-$(CONFIG_SND_SOC_INTEL_HASWELL_MACH) += snd-soc-sst-haswell.o
 obj-$(CONFIG_SND_SOC_INTEL_BXT_DA7219_MAX98357A_COMMON) += snd-soc-sst-bxt-da7219_max98357a.o
 obj-$(CONFIG_SND_SOC_INTEL_BXT_RT298_MACH) += snd-soc-sst-bxt-rt298.o
diff --git a/sound/soc/intel/boards/sof_es8336.c b/sound/soc/intel/boards/sof_es8336.c
new file mode 100644
index 000000000000..20d577eaab6d
--- /dev/null
+++ b/sound/soc/intel/boards/sof_es8336.c
@@ -0,0 +1,569 @@
+// SPDX-License-Identifier: GPL-2.0-only
+// Copyright(c) 2021 Intel Corporation.
+
+/*
+ * Intel SOF Machine Driver with es8336 Codec
+ */
+
+#include <linux/device.h>
+#include <linux/dmi.h>
+#include <linux/gpio/consumer.h>
+#include <linux/gpio/machine.h>
+#include <linux/i2c.h>
+#include <linux/input.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <sound/jack.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-acpi.h>
+#include "hda_dsp_common.h"
+
+#define SOF_ES8336_SSP_CODEC(quirk)		((quirk) & GENMASK(3, 0))
+#define SOF_ES8336_SSP_CODEC_MASK		(GENMASK(3, 0))
+
+#define SOF_ES8336_TGL_GPIO_QUIRK		BIT(4)
+#define SOF_ES8336_ENABLE_DMIC			BIT(5)
+
+static unsigned long quirk;
+
+static int quirk_override = -1;
+module_param_named(quirk, quirk_override, int, 0444);
+MODULE_PARM_DESC(quirk, "Board-specific quirk override");
+
+struct sof_es8336_private {
+	struct device *codec_dev;
+	struct gpio_desc *gpio_pa;
+	struct snd_soc_jack jack;
+	struct list_head hdmi_pcm_list;
+	bool speaker_en;
+};
+
+struct sof_hdmi_pcm {
+	struct list_head head;
+	struct snd_soc_dai *codec_dai;
+	int device;
+};
+
+static const struct acpi_gpio_params pa_enable_gpio = { 0, 0, true };
+static const struct acpi_gpio_mapping acpi_es8336_gpios[] = {
+	{ "pa-enable-gpios", &pa_enable_gpio, 1 },
+	{ }
+};
+
+static const struct acpi_gpio_params quirk_pa_enable_gpio = { 1, 0, true };
+static const struct acpi_gpio_mapping quirk_acpi_es8336_gpios[] = {
+	{ "pa-enable-gpios", &quirk_pa_enable_gpio, 1 },
+	{ }
+};
+
+static const struct acpi_gpio_mapping *gpio_mapping = acpi_es8336_gpios;
+
+static void log_quirks(struct device *dev)
+{
+	dev_info(dev, "quirk SSP%ld",  SOF_ES8336_SSP_CODEC(quirk));
+}
+
+static int sof_es8316_speaker_power_event(struct snd_soc_dapm_widget *w,
+					  struct snd_kcontrol *kcontrol, int event)
+{
+	struct snd_soc_card *card = w->dapm->card;
+	struct sof_es8336_private *priv = snd_soc_card_get_drvdata(card);
+
+	if (SND_SOC_DAPM_EVENT_ON(event))
+		priv->speaker_en = false;
+	else
+		priv->speaker_en = true;
+
+	gpiod_set_value_cansleep(priv->gpio_pa, priv->speaker_en);
+
+	return 0;
+}
+
+static const struct snd_soc_dapm_widget sof_es8316_widgets[] = {
+	SND_SOC_DAPM_SPK("Speaker", NULL),
+	SND_SOC_DAPM_HP("Headphone", NULL),
+	SND_SOC_DAPM_MIC("Headset Mic", NULL),
+	SND_SOC_DAPM_MIC("Internal Mic", NULL),
+
+	SND_SOC_DAPM_SUPPLY("Speaker Power", SND_SOC_NOPM, 0, 0,
+			    sof_es8316_speaker_power_event,
+			    SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
+};
+
+static const struct snd_soc_dapm_widget dmic_widgets[] = {
+	SND_SOC_DAPM_MIC("SoC DMIC", NULL),
+};
+
+static const struct snd_soc_dapm_route sof_es8316_audio_map[] = {
+	{"Headphone", NULL, "HPOL"},
+	{"Headphone", NULL, "HPOR"},
+
+	/*
+	 * There is no separate speaker output instead the speakers are muxed to
+	 * the HP outputs. The mux is controlled by the "Speaker Power" supply.
+	 */
+	{"Speaker", NULL, "HPOL"},
+	{"Speaker", NULL, "HPOR"},
+	{"Speaker", NULL, "Speaker Power"},
+};
+
+static const struct snd_soc_dapm_route sof_es8316_intmic_in1_map[] = {
+	{"MIC1", NULL, "Internal Mic"},
+	{"MIC2", NULL, "Headset Mic"},
+};
+
+static const struct snd_soc_dapm_route dmic_map[] = {
+	/* digital mics */
+	{"DMic", NULL, "SoC DMIC"},
+};
+
+static const struct snd_kcontrol_new sof_es8316_controls[] = {
+	SOC_DAPM_PIN_SWITCH("Speaker"),
+	SOC_DAPM_PIN_SWITCH("Headphone"),
+	SOC_DAPM_PIN_SWITCH("Headset Mic"),
+	SOC_DAPM_PIN_SWITCH("Internal Mic"),
+};
+
+static struct snd_soc_jack_pin sof_es8316_jack_pins[] = {
+	{
+		.pin	= "Headphone",
+		.mask	= SND_JACK_HEADPHONE,
+	},
+	{
+		.pin	= "Headset Mic",
+		.mask	= SND_JACK_MICROPHONE,
+	},
+};
+
+static int dmic_init(struct snd_soc_pcm_runtime *runtime)
+{
+	struct snd_soc_card *card = runtime->card;
+	int ret;
+
+	ret = snd_soc_dapm_new_controls(&card->dapm, dmic_widgets,
+					ARRAY_SIZE(dmic_widgets));
+	if (ret) {
+		dev_err(card->dev, "DMic widget addition failed: %d\n", ret);
+		return ret;
+	}
+
+	ret = snd_soc_dapm_add_routes(&card->dapm, dmic_map,
+				      ARRAY_SIZE(dmic_map));
+	if (ret)
+		dev_err(card->dev, "DMic map addition failed: %d\n", ret);
+
+	return ret;
+}
+
+static int sof_hdmi_init(struct snd_soc_pcm_runtime *runtime)
+{
+	struct sof_es8336_private *priv = snd_soc_card_get_drvdata(runtime->card);
+	struct snd_soc_dai *dai = asoc_rtd_to_codec(runtime, 0);
+	struct sof_hdmi_pcm *pcm;
+
+	pcm = devm_kzalloc(runtime->card->dev, sizeof(*pcm), GFP_KERNEL);
+	if (!pcm)
+		return -ENOMEM;
+
+	/* dai_link id is 1:1 mapped to the PCM device */
+	pcm->device = runtime->dai_link->id;
+	pcm->codec_dai = dai;
+
+	list_add_tail(&pcm->head, &priv->hdmi_pcm_list);
+
+	return 0;
+}
+
+static int sof_es8316_init(struct snd_soc_pcm_runtime *runtime)
+{
+	struct snd_soc_component *codec = asoc_rtd_to_codec(runtime, 0)->component;
+	struct snd_soc_card *card = runtime->card;
+	struct sof_es8336_private *priv = snd_soc_card_get_drvdata(card);
+	const struct snd_soc_dapm_route *custom_map;
+	int num_routes;
+	int ret;
+
+	card->dapm.idle_bias_off = true;
+
+	custom_map = sof_es8316_intmic_in1_map;
+	num_routes = ARRAY_SIZE(sof_es8316_intmic_in1_map);
+
+	ret = snd_soc_dapm_add_routes(&card->dapm, custom_map, num_routes);
+	if (ret)
+		return ret;
+
+	ret = snd_soc_card_jack_new(card, "Headset",
+				    SND_JACK_HEADSET | SND_JACK_BTN_0,
+				    &priv->jack, sof_es8316_jack_pins,
+				    ARRAY_SIZE(sof_es8316_jack_pins));
+	if (ret) {
+		dev_err(card->dev, "jack creation failed %d\n", ret);
+		return ret;
+	}
+
+	snd_jack_set_key(priv->jack.jack, SND_JACK_BTN_0, KEY_PLAYPAUSE);
+
+	snd_soc_component_set_jack(codec, &priv->jack, NULL);
+
+	return 0;
+}
+
+static void sof_es8316_exit(struct snd_soc_pcm_runtime *rtd)
+{
+	struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component;
+
+	snd_soc_component_set_jack(component, NULL, NULL);
+}
+
+static int sof_es8336_quirk_cb(const struct dmi_system_id *id)
+{
+	quirk = (unsigned long)id->driver_data;
+
+	if (quirk & SOF_ES8336_TGL_GPIO_QUIRK)
+		gpio_mapping = quirk_acpi_es8336_gpios;
+
+	return 1;
+}
+
+static const struct dmi_system_id sof_es8336_quirk_table[] = {
+	{
+		.callback = sof_es8336_quirk_cb,
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "CHUWI Innovation And Technology"),
+			DMI_MATCH(DMI_BOARD_NAME, "Hi10 X"),
+		},
+		.driver_data = (void *)SOF_ES8336_SSP_CODEC(2)
+	},
+	{
+		.callback = sof_es8336_quirk_cb,
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "IP3 tech"),
+			DMI_MATCH(DMI_BOARD_NAME, "WN1"),
+		},
+		.driver_data = (void *)(SOF_ES8336_SSP_CODEC(0) |
+					SOF_ES8336_TGL_GPIO_QUIRK |
+					SOF_ES8336_ENABLE_DMIC)
+	},
+	{}
+};
+
+static int sof_es8336_hw_params(struct snd_pcm_substream *substream,
+				struct snd_pcm_hw_params *params)
+{
+	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
+	struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
+	const int sysclk = 19200000;
+	int ret;
+
+	ret = snd_soc_dai_set_sysclk(codec_dai, 1, sysclk, SND_SOC_CLOCK_OUT);
+	if (ret < 0) {
+		dev_err(rtd->dev, "%s, Failed to set ES8336 SYSCLK: %d\n",
+			__func__, ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+/* machine stream operations */
+static struct snd_soc_ops sof_es8336_ops = {
+	.hw_params = sof_es8336_hw_params,
+};
+
+static struct snd_soc_dai_link_component platform_component[] = {
+	{
+		/* name might be overridden during probe */
+		.name = "0000:00:1f.3"
+	}
+};
+
+SND_SOC_DAILINK_DEF(ssp1_codec,
+	DAILINK_COMP_ARRAY(COMP_CODEC("i2c-ESSX8336:00", "ES8316 HiFi")));
+
+static struct snd_soc_dai_link_component dmic_component[] = {
+	{
+		.name = "dmic-codec",
+		.dai_name = "dmic-hifi",
+	}
+};
+
+static int sof_es8336_late_probe(struct snd_soc_card *card)
+{
+	struct sof_es8336_private *priv = snd_soc_card_get_drvdata(card);
+	struct sof_hdmi_pcm *pcm;
+
+	if (list_empty(&priv->hdmi_pcm_list))
+		return -ENOENT;
+
+	pcm = list_first_entry(&priv->hdmi_pcm_list, struct sof_hdmi_pcm, head);
+
+	return hda_dsp_hdmi_build_controls(card, pcm->codec_dai->component);
+}
+
+/* SoC card */
+static struct snd_soc_card sof_es8336_card = {
+	.name = "essx8336", /* sof- prefix added automatically */
+	.owner = THIS_MODULE,
+	.dapm_widgets = sof_es8316_widgets,
+	.num_dapm_widgets = ARRAY_SIZE(sof_es8316_widgets),
+	.dapm_routes = sof_es8316_audio_map,
+	.num_dapm_routes = ARRAY_SIZE(sof_es8316_audio_map),
+	.controls = sof_es8316_controls,
+	.num_controls = ARRAY_SIZE(sof_es8316_controls),
+	.fully_routed = true,
+	.late_probe = sof_es8336_late_probe,
+	.num_links = 1,
+};
+
+static struct snd_soc_dai_link *sof_card_dai_links_create(struct device *dev,
+							  int ssp_codec,
+							  int dmic_be_num,
+							  int hdmi_num)
+{
+	struct snd_soc_dai_link_component *cpus;
+	struct snd_soc_dai_link *links;
+	struct snd_soc_dai_link_component *idisp_components;
+	int hdmi_id_offset = 0;
+	int id = 0;
+	int i;
+
+	links = devm_kcalloc(dev, sof_es8336_card.num_links,
+			     sizeof(struct snd_soc_dai_link), GFP_KERNEL);
+	cpus = devm_kcalloc(dev, sof_es8336_card.num_links,
+			    sizeof(struct snd_soc_dai_link_component), GFP_KERNEL);
+	if (!links || !cpus)
+		goto devm_err;
+
+	/* codec SSP */
+	links[id].name = devm_kasprintf(dev, GFP_KERNEL,
+					"SSP%d-Codec", ssp_codec);
+	if (!links[id].name)
+		goto devm_err;
+
+	links[id].id = id;
+	links[id].codecs = ssp1_codec;
+	links[id].num_codecs = ARRAY_SIZE(ssp1_codec);
+	links[id].platforms = platform_component;
+	links[id].num_platforms = ARRAY_SIZE(platform_component);
+	links[id].init = sof_es8316_init;
+	links[id].exit = sof_es8316_exit;
+	links[id].ops = &sof_es8336_ops;
+	links[id].nonatomic = true;
+	links[id].dpcm_playback = 1;
+	links[id].dpcm_capture = 1;
+	links[id].no_pcm = 1;
+	links[id].cpus = &cpus[id];
+	links[id].num_cpus = 1;
+
+	links[id].cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL,
+						  "SSP%d Pin",
+						  ssp_codec);
+	if (!links[id].cpus->dai_name)
+		goto devm_err;
+
+	id++;
+
+	/* dmic */
+	if (dmic_be_num > 0) {
+		/* at least we have dmic01 */
+		links[id].name = "dmic01";
+		links[id].cpus = &cpus[id];
+		links[id].cpus->dai_name = "DMIC01 Pin";
+		links[id].init = dmic_init;
+		if (dmic_be_num > 1) {
+			/* set up 2 BE links at most */
+			links[id + 1].name = "dmic16k";
+			links[id + 1].cpus = &cpus[id + 1];
+			links[id + 1].cpus->dai_name = "DMIC16k Pin";
+			dmic_be_num = 2;
+		}
+	} else {
+		/* HDMI dai link starts at 3 according to current topology settings */
+		hdmi_id_offset = 2;
+	}
+
+	for (i = 0; i < dmic_be_num; i++) {
+		links[id].id = id;
+		links[id].num_cpus = 1;
+		links[id].codecs = dmic_component;
+		links[id].num_codecs = ARRAY_SIZE(dmic_component);
+		links[id].platforms = platform_component;
+		links[id].num_platforms = ARRAY_SIZE(platform_component);
+		links[id].ignore_suspend = 1;
+		links[id].dpcm_capture = 1;
+		links[id].no_pcm = 1;
+
+		id++;
+	}
+
+	/* HDMI */
+	if (hdmi_num > 0) {
+		idisp_components = devm_kzalloc(dev,
+						sizeof(struct snd_soc_dai_link_component) *
+						hdmi_num, GFP_KERNEL);
+		if (!idisp_components)
+			goto devm_err;
+	}
+
+	for (i = 1; i <= hdmi_num; i++) {
+		links[id].name = devm_kasprintf(dev, GFP_KERNEL,
+						"iDisp%d", i);
+		if (!links[id].name)
+			goto devm_err;
+
+		links[id].id = id + hdmi_id_offset;
+		links[id].cpus = &cpus[id];
+		links[id].num_cpus = 1;
+		links[id].cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL,
+							  "iDisp%d Pin", i);
+		if (!links[id].cpus->dai_name)
+			goto devm_err;
+
+		idisp_components[i - 1].name = "ehdaudio0D2";
+		idisp_components[i - 1].dai_name = devm_kasprintf(dev,
+								  GFP_KERNEL,
+								  "intel-hdmi-hifi%d",
+								  i);
+		if (!idisp_components[i - 1].dai_name)
+			goto devm_err;
+
+		links[id].codecs = &idisp_components[i - 1];
+		links[id].num_codecs = 1;
+		links[id].platforms = platform_component;
+		links[id].num_platforms = ARRAY_SIZE(platform_component);
+		links[id].init = sof_hdmi_init;
+		links[id].dpcm_playback = 1;
+		links[id].no_pcm = 1;
+
+		id++;
+	}
+
+	return links;
+
+devm_err:
+	return NULL;
+}
+
+ /* i2c-<HID>:00 with HID being 8 chars */
+static char codec_name[SND_ACPI_I2C_ID_LEN];
+
+static int sof_es8336_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct snd_soc_card *card;
+	struct snd_soc_acpi_mach *mach = pdev->dev.platform_data;
+	struct sof_es8336_private *priv;
+	struct acpi_device *adev;
+	struct snd_soc_dai_link *dai_links;
+	struct device *codec_dev;
+	int dmic_be_num = 0;
+	int hdmi_num = 3;
+	int ret;
+
+	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	card = &sof_es8336_card;
+	card->dev = dev;
+
+	if (!dmi_check_system(sof_es8336_quirk_table))
+		quirk = SOF_ES8336_SSP_CODEC(2);
+
+	if (quirk & SOF_ES8336_ENABLE_DMIC)
+		dmic_be_num = 2;
+
+	if (quirk_override != -1) {
+		dev_info(dev, "Overriding quirk 0x%lx => 0x%x\n",
+			 quirk, quirk_override);
+		quirk = quirk_override;
+	}
+	log_quirks(dev);
+
+	sof_es8336_card.num_links += dmic_be_num + hdmi_num;
+	dai_links = sof_card_dai_links_create(dev,
+					      SOF_ES8336_SSP_CODEC(quirk),
+					      dmic_be_num, hdmi_num);
+	if (!dai_links)
+		return -ENOMEM;
+
+	sof_es8336_card.dai_link = dai_links;
+
+	/* fixup codec name based on HID */
+	adev = acpi_dev_get_first_match_dev(mach->id, NULL, -1);
+	if (adev) {
+		snprintf(codec_name, sizeof(codec_name),
+			 "i2c-%s", acpi_dev_name(adev));
+		put_device(&adev->dev);
+		dai_links[0].codecs->name = codec_name;
+	}
+
+	ret = snd_soc_fixup_dai_links_platform_name(&sof_es8336_card,
+						    mach->mach_params.platform);
+	if (ret)
+		return ret;
+
+	/* get speaker enable GPIO */
+	codec_dev = bus_find_device_by_name(&i2c_bus_type, NULL, codec_name);
+	if (!codec_dev)
+		return -EPROBE_DEFER;
+
+	ret = devm_acpi_dev_add_driver_gpios(codec_dev, gpio_mapping);
+	if (ret)
+		dev_warn(codec_dev, "unable to add GPIO mapping table\n");
+
+	priv->gpio_pa = gpiod_get(codec_dev, "pa-enable", GPIOD_OUT_LOW);
+	if (IS_ERR(priv->gpio_pa)) {
+		ret = PTR_ERR(priv->gpio_pa);
+		dev_err(codec_dev, "%s, could not get pa-enable: %d\n",
+			__func__, ret);
+		goto err;
+	}
+
+	priv->codec_dev = codec_dev;
+	INIT_LIST_HEAD(&priv->hdmi_pcm_list);
+
+	snd_soc_card_set_drvdata(card, priv);
+
+	ret = devm_snd_soc_register_card(dev, card);
+	if (ret) {
+		gpiod_put(priv->gpio_pa);
+		dev_err(dev, "snd_soc_register_card failed: %d\n", ret);
+		goto err;
+	}
+	platform_set_drvdata(pdev, &sof_es8336_card);
+	return 0;
+
+err:
+	put_device(codec_dev);
+	return ret;
+}
+
+static int sof_es8336_remove(struct platform_device *pdev)
+{
+	struct snd_soc_card *card = platform_get_drvdata(pdev);
+	struct sof_es8336_private *priv = snd_soc_card_get_drvdata(card);
+
+	gpiod_put(priv->gpio_pa);
+	put_device(priv->codec_dev);
+
+	return 0;
+}
+
+static struct platform_driver sof_es8336_driver = {
+	.driver = {
+		.name = "sof-essx8336",
+		.pm = &snd_soc_pm_ops,
+	},
+	.probe = sof_es8336_probe,
+	.remove = sof_es8336_remove,
+};
+module_platform_driver(sof_es8336_driver);
+
+MODULE_DESCRIPTION("ASoC Intel(R) SOF + ES8336 Machine driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:sof-essx8336");
+MODULE_IMPORT_NS(SND_SOC_INTEL_HDA_DSP_COMMON);
diff --git a/sound/soc/intel/common/soc-acpi-intel-bxt-match.c b/sound/soc/intel/common/soc-acpi-intel-bxt-match.c
index 576407b5daf2..78cfdc48ad45 100644
--- a/sound/soc/intel/common/soc-acpi-intel-bxt-match.c
+++ b/sound/soc/intel/common/soc-acpi-intel-bxt-match.c
@@ -82,6 +82,12 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_bxt_machines[] = {
 		.sof_fw_filename = "sof-apl.ri",
 		.sof_tplg_filename = "sof-apl-tdf8532.tplg",
 	},
+	{
+		.id = "ESSX8336",
+		.drv_name = "sof-essx8336",
+		.sof_fw_filename = "sof-apl.ri",
+		.sof_tplg_filename = "sof-apl-es8336.tplg",
+	},
 	{},
 };
 EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_bxt_machines);
diff --git a/sound/soc/intel/common/soc-acpi-intel-cml-match.c b/sound/soc/intel/common/soc-acpi-intel-cml-match.c
index b591c6fd13fd..f03fcc0806ea 100644
--- a/sound/soc/intel/common/soc-acpi-intel-cml-match.c
+++ b/sound/soc/intel/common/soc-acpi-intel-cml-match.c
@@ -81,6 +81,12 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_cml_machines[] = {
 		.sof_fw_filename = "sof-cml.ri",
 		.sof_tplg_filename = "sof-cml-da7219-max98390.tplg",
 	},
+	{
+		.id = "ESSX8336",
+		.drv_name = "sof-essx8336",
+		.sof_fw_filename = "sof-cml.ri",
+		.sof_tplg_filename = "sof-cml-es8336.tplg",
+	},
 	{},
 };
 EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_cml_machines);
diff --git a/sound/soc/intel/common/soc-acpi-intel-glk-match.c b/sound/soc/intel/common/soc-acpi-intel-glk-match.c
index da1e151190b4..32fff9389eb3 100644
--- a/sound/soc/intel/common/soc-acpi-intel-glk-match.c
+++ b/sound/soc/intel/common/soc-acpi-intel-glk-match.c
@@ -49,7 +49,12 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_glk_machines[] = {
 		.sof_fw_filename = "sof-glk.ri",
 		.sof_tplg_filename = "sof-glk-cs42l42.tplg",
 	},
-
+	{
+		.id = "ESSX8336",
+		.drv_name = "sof-essx8336",
+		.sof_fw_filename = "sof-glk.ri",
+		.sof_tplg_filename = "sof-glk-es8336.tplg",
+	},
 	{},
 };
 EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_glk_machines);
diff --git a/sound/soc/intel/common/soc-acpi-intel-jsl-match.c b/sound/soc/intel/common/soc-acpi-intel-jsl-match.c
index 69ff7286d357..87923bcf9488 100644
--- a/sound/soc/intel/common/soc-acpi-intel-jsl-match.c
+++ b/sound/soc/intel/common/soc-acpi-intel-jsl-match.c
@@ -81,6 +81,12 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_jsl_machines[] = {
 		.quirk_data = &mx98360a_spk,
 		.sof_tplg_filename = "sof-jsl-cs42l42-mx98360a.tplg",
 	},
+	{
+		.id = "ESSX8336",
+		.drv_name = "sof-essx8336",
+		.sof_fw_filename = "sof-jsl.ri",
+		.sof_tplg_filename = "sof-jsl-es8336.tplg",
+	},
 	{},
 };
 EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_jsl_machines);
diff --git a/sound/soc/intel/common/soc-acpi-intel-tgl-match.c b/sound/soc/intel/common/soc-acpi-intel-tgl-match.c
index 11801b905ecc..c2c5337ed3b8 100644
--- a/sound/soc/intel/common/soc-acpi-intel-tgl-match.c
+++ b/sound/soc/intel/common/soc-acpi-intel-tgl-match.c
@@ -383,6 +383,12 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_tgl_machines[] = {
 		.sof_fw_filename = "sof-tgl.ri",
 		.sof_tplg_filename = "sof-tgl-rt1011-rt5682.tplg",
 	},
+	{
+		.id = "ESSX8336",
+		.drv_name = "sof-essx8336",
+		.sof_fw_filename = "sof-tgl.ri",
+		.sof_tplg_filename = "sof-tgl-es8336.tplg",
+	},
 	{},
 };
 EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_tgl_machines);
-- 
2.33.0



^ permalink raw reply	[flat|nested] 28+ messages in thread

* [d-kernel] [PATCH v2 2/9] ASoC: Intel: sof_es8336: Add quirk for inverted jack detect
  2022-04-07 11:15         ` [d-kernel] [PATCH v2 1/9] ASoC: Intel: add machine driver for SOF+ES8336 nickel
@ 2022-04-07 11:15           ` nickel
  2022-04-07 11:15           ` [d-kernel] [PATCH v2 3/9] ASoC: es8316: Add power management nickel
                             ` (7 subsequent siblings)
  8 siblings, 0 replies; 28+ messages in thread
From: nickel @ 2022-04-07 11:15 UTC (permalink / raw)
  To: devel-kernel; +Cc: Vasily Vinogradov

From: Vasily Vinogradov <v.vinogradov@aq.ru>

Backport from 5.17
Based on upstream commit 8e5db49182415b8bfce3b5843fc87e49c83c02aa

Link: https://lore.kernel.org/r/20220308192610.392950-18-pierre-louis.bossart@linux.intel.com
Signed-off-by: Vasily Vinogradov <v.vinogradov@aq.ru>
Signed-off-by: Nikolai Kostrigin <nickel@altlinux.org>
---
 sound/soc/intel/boards/sof_es8336.c | 20 ++++++++++++++++++++
 1 file changed, 20 insertions(+)

diff --git a/sound/soc/intel/boards/sof_es8336.c b/sound/soc/intel/boards/sof_es8336.c
index 20d577eaab6d..7966a61b22c8 100644
--- a/sound/soc/intel/boards/sof_es8336.c
+++ b/sound/soc/intel/boards/sof_es8336.c
@@ -26,6 +26,7 @@
 
 #define SOF_ES8336_TGL_GPIO_QUIRK		BIT(4)
 #define SOF_ES8336_ENABLE_DMIC			BIT(5)
+#define SOF_ES8336_JD_INVERTED			BIT(6)
 
 static unsigned long quirk;
 
@@ -33,6 +34,9 @@ static int quirk_override = -1;
 module_param_named(quirk, quirk_override, int, 0444);
 MODULE_PARM_DESC(quirk, "Board-specific quirk override");
 
+/* jd-inv + terminating entry */
+#define SOF_ES8336_PROPS_MAX	2
+
 struct sof_es8336_private {
 	struct device *codec_dev;
 	struct gpio_desc *gpio_pa;
@@ -64,6 +68,8 @@ static const struct acpi_gpio_mapping *gpio_mapping = acpi_es8336_gpios;
 static void log_quirks(struct device *dev)
 {
 	dev_info(dev, "quirk SSP%ld",  SOF_ES8336_SSP_CODEC(quirk));
+	dev_info(dev, "quirk JD_INVERTED %s\n",
+		 (quirk & SOF_ES8336_JD_INVERTED) ? "enabled" : "disabled");
 }
 
 static int sof_es8316_speaker_power_event(struct snd_soc_dapm_widget *w,
@@ -459,6 +465,8 @@ static int sof_es8336_probe(struct platform_device *pdev)
 	struct acpi_device *adev;
 	struct snd_soc_dai_link *dai_links;
 	struct device *codec_dev;
+	struct property_entry props[SOF_ES8336_PROPS_MAX] = {};
+	unsigned int cnt = 0;
 	int dmic_be_num = 0;
 	int hdmi_num = 3;
 	int ret;
@@ -511,6 +519,18 @@ static int sof_es8336_probe(struct platform_device *pdev)
 	if (!codec_dev)
 		return -EPROBE_DEFER;
 
+	if (quirk & SOF_ES8336_JD_INVERTED)
+		props[cnt++] = PROPERTY_ENTRY_BOOL("everest,jack-detect-inverted");
+
+	if (cnt) {
+		ret = device_add_properties(codec_dev, props);
+		if (ret) {
+			dev_err(codec_dev, "%s, could not add properties: %d\n",
+				__func__, ret);
+			goto err;
+		}
+	}
+
 	ret = devm_acpi_dev_add_driver_gpios(codec_dev, gpio_mapping);
 	if (ret)
 		dev_warn(codec_dev, "unable to add GPIO mapping table\n");
-- 
2.33.0



^ permalink raw reply	[flat|nested] 28+ messages in thread

* [d-kernel] [PATCH v2 3/9] ASoC: es8316: Add power management
  2022-04-07 11:15         ` [d-kernel] [PATCH v2 1/9] ASoC: Intel: add machine driver for SOF+ES8336 nickel
  2022-04-07 11:15           ` [d-kernel] [PATCH v2 2/9] ASoC: Intel: sof_es8336: Add quirk for inverted jack detect nickel
@ 2022-04-07 11:15           ` nickel
  2022-04-07 11:15           ` [d-kernel] [PATCH v2 4/9] ASoC: es8316: Use increased GPIO debounce time nickel
                             ` (6 subsequent siblings)
  8 siblings, 0 replies; 28+ messages in thread
From: nickel @ 2022-04-07 11:15 UTC (permalink / raw)
  To: devel-kernel; +Cc: Vasily Vinogradov

From: Vasily Vinogradov <v.vinogradov@aq.ru>

Signed-off-by: Vasily Vinogradov <v.vinogradov@aq.ru>
Signed-off-by: Nikolai Kostrigin <nickel@altlinux.org>
---
 sound/soc/codecs/es8316.c | 39 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 39 insertions(+)

diff --git a/sound/soc/codecs/es8316.c b/sound/soc/codecs/es8316.c
index 8f30a3ea8bfe..c63f3b300797 100644
--- a/sound/soc/codecs/es8316.c
+++ b/sound/soc/codecs/es8316.c
@@ -728,6 +728,8 @@ static int es8316_probe(struct snd_soc_component *component)
 		return ret;
 	}
 
+	snd_soc_component_init_regmap(component, es8316->regmap);
+
 	/* Reset codec and enable current state machine */
 	snd_soc_component_write(component, ES8316_RESET, 0x3f);
 	usleep_range(5000, 5500);
@@ -754,9 +756,43 @@ static void es8316_remove(struct snd_soc_component *component)
 {
 	struct es8316_priv *es8316 = snd_soc_component_get_drvdata(component);
 
+	snd_soc_component_exit_regmap(component);
+
 	clk_disable_unprepare(es8316->mclk);
 }
 
+#ifdef CONFIG_PM_SLEEP
+static int es8316_suspend(struct device *dev)
+{
+	struct es8316_priv *es8316 = dev_get_drvdata(dev);
+
+	dev_dbg(dev, "%s: Enter\n", __func__);
+
+	regcache_cache_only(es8316->regmap, true);
+	regcache_mark_dirty(es8316->regmap);
+
+	return 0;
+}
+
+static int es8316_resume(struct device *dev)
+{
+	struct es8316_priv *es8316 = dev_get_drvdata(dev);
+
+	dev_dbg(dev, "%s: Enter\n", __func__);
+
+	regcache_cache_only(es8316->regmap, false);
+	regcache_sync(es8316->regmap);
+
+	es8316_irq(es8316->irq, es8316);
+
+	return 0;
+}
+#endif
+
+static const struct dev_pm_ops es8316_pm = {
+	SET_SYSTEM_SLEEP_PM_OPS(es8316_suspend, es8316_resume)
+};
+
 static const struct snd_soc_component_driver soc_component_dev_es8316 = {
 	.probe			= es8316_probe,
 	.remove			= es8316_remove,
@@ -787,6 +823,8 @@ static const struct regmap_config es8316_regmap = {
 	.max_register = 0x53,
 	.volatile_table	= &es8316_volatile_table,
 	.cache_type = REGCACHE_RBTREE,
+	.use_single_read = true,
+	.use_single_write = true,
 };
 
 static int es8316_i2c_probe(struct i2c_client *i2c_client,
@@ -851,6 +889,7 @@ static struct i2c_driver es8316_i2c_driver = {
 		.name			= "es8316",
 		.acpi_match_table	= ACPI_PTR(es8316_acpi_match),
 		.of_match_table		= of_match_ptr(es8316_of_match),
+		.pm			= &es8316_pm,
 	},
 	.probe		= es8316_i2c_probe,
 	.id_table	= es8316_i2c_id,
-- 
2.33.0



^ permalink raw reply	[flat|nested] 28+ messages in thread

* [d-kernel] [PATCH v2 4/9] ASoC: es8316: Use increased GPIO debounce time
  2022-04-07 11:15         ` [d-kernel] [PATCH v2 1/9] ASoC: Intel: add machine driver for SOF+ES8336 nickel
  2022-04-07 11:15           ` [d-kernel] [PATCH v2 2/9] ASoC: Intel: sof_es8336: Add quirk for inverted jack detect nickel
  2022-04-07 11:15           ` [d-kernel] [PATCH v2 3/9] ASoC: es8316: Add power management nickel
@ 2022-04-07 11:15           ` nickel
  2022-04-07 11:15           ` [d-kernel] [PATCH v2 5/9] ASoC: codec: es8326: New codec driver nickel
                             ` (5 subsequent siblings)
  8 siblings, 0 replies; 28+ messages in thread
From: nickel @ 2022-04-07 11:15 UTC (permalink / raw)
  To: devel-kernel; +Cc: Vasily Vinogradov

From: Vasily Vinogradov <v.vinogradov@aq.ru>

Signed-off-by: Vasily Vinogradov <v.vinogradov@aq.ru>
Signed-off-by: Nikolai Kostrigin <nickel@altlinux.org>
---
 sound/soc/codecs/es8316.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/sound/soc/codecs/es8316.c b/sound/soc/codecs/es8316.c
index c63f3b300797..9778c988e49e 100644
--- a/sound/soc/codecs/es8316.c
+++ b/sound/soc/codecs/es8316.c
@@ -553,7 +553,7 @@ static void es8316_enable_micbias_for_mic_gnd_short_detect(
 	snd_soc_dapm_sync_unlocked(dapm);
 	snd_soc_dapm_mutex_unlock(dapm);
 
-	msleep(20);
+	msleep(500);
 }
 
 static void es8316_disable_micbias_for_mic_gnd_short_detect(
-- 
2.33.0



^ permalink raw reply	[flat|nested] 28+ messages in thread

* [d-kernel] [PATCH v2 5/9] ASoC: codec: es8326: New codec driver
  2022-04-07 11:15         ` [d-kernel] [PATCH v2 1/9] ASoC: Intel: add machine driver for SOF+ES8336 nickel
                             ` (2 preceding siblings ...)
  2022-04-07 11:15           ` [d-kernel] [PATCH v2 4/9] ASoC: es8316: Use increased GPIO debounce time nickel
@ 2022-04-07 11:15           ` nickel
  2022-04-07 11:15           ` [d-kernel] [PATCH v2 6/9] ALSA: intel-dspconfig: add ES8336 support for CNL nickel
                             ` (4 subsequent siblings)
  8 siblings, 0 replies; 28+ messages in thread
From: nickel @ 2022-04-07 11:15 UTC (permalink / raw)
  To: devel-kernel; +Cc: Vasily Vinogradov

From: Vasily Vinogradov <v.vinogradov@aq.ru>

Based on ALSA SoF development branch.
Refer to:
Link: https://github.com/thesofproject/linux/issues/3393
Link: https://github.com/thesofproject/linux/pull/3508

Signed-off-by: Vasily Vinogradov <v.vinogradov@aq.ru>
Signed-off-by: Nikolai Kostrigin <nickel@altlinux.org>
---
 sound/hda/intel-dsp-config.c                  |  10 +
 sound/soc/codecs/Kconfig                      |   5 +
 sound/soc/codecs/Makefile                     |   2 +
 sound/soc/codecs/es8326.c                     | 893 ++++++++++++++++++
 sound/soc/codecs/es8326.h                     | 222 +++++
 sound/soc/intel/boards/Kconfig                |   1 +
 sound/soc/intel/boards/sof_es8336.c           |   6 +
 .../intel/common/soc-acpi-intel-jsl-match.c   |   6 +
 .../intel/common/soc-acpi-intel-tgl-match.c   |   6 +
 9 files changed, 1151 insertions(+)
 create mode 100644 sound/soc/codecs/es8326.c
 create mode 100644 sound/soc/codecs/es8326.h

diff --git a/sound/hda/intel-dsp-config.c b/sound/hda/intel-dsp-config.c
index f63114317ac9..9ef023882ae0 100644
--- a/sound/hda/intel-dsp-config.c
+++ b/sound/hda/intel-dsp-config.c
@@ -311,6 +311,11 @@ static const struct config_entry config_table[] = {
 
 /* JasperLake */
 #if IS_ENABLED(CONFIG_SND_SOC_SOF_JASPERLAKE)
+	{
+		.flags = FLAG_SOF,
+		.device = 0x4dc8,
+		.codec_hid = "ESSX8326",
+	},
 	{
 		.flags = FLAG_SOF,
 		.device = 0x4dc8,
@@ -333,6 +338,11 @@ static const struct config_entry config_table[] = {
 			{}
 		}
 	},
+	{
+		.flags = FLAG_SOF,
+		.device = 0xa0c8,
+		.codec_hid = "ESSX8326",
+	},
 	{
 		.flags = FLAG_SOF,
 		.device = 0xa0c8,
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index f12c9b942678..c15d66636161 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -92,6 +92,7 @@ config SND_SOC_ALL_CODECS
 	imply SND_SOC_DA9055
 	imply SND_SOC_DMIC
 	imply SND_SOC_ES8316
+	imply SND_SOC_ES8326
 	imply SND_SOC_ES8328_SPI
 	imply SND_SOC_ES8328_I2C
 	imply SND_SOC_ES7134
@@ -820,6 +821,10 @@ config SND_SOC_ES8316
 	tristate "Everest Semi ES8316 CODEC"
 	depends on I2C
 
+config SND_SOC_ES8326
+	tristate "Everest Semi ES8326 CODEC"
+	depends on I2C
+
 config SND_SOC_ES8328
 	tristate
 
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index 8dcea2c4604a..fe0adc94b11f 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -90,6 +90,7 @@ snd-soc-dmic-objs := dmic.o
 snd-soc-es7134-objs := es7134.o
 snd-soc-es7241-objs := es7241.o
 snd-soc-es8316-objs := es8316.o
+snd-soc-es8326-objs := es8326.o
 snd-soc-es8328-objs := es8328.o
 snd-soc-es8328-i2c-objs := es8328-i2c.o
 snd-soc-es8328-spi-objs := es8328-spi.o
@@ -421,6 +422,7 @@ obj-$(CONFIG_SND_SOC_DMIC)	+= snd-soc-dmic.o
 obj-$(CONFIG_SND_SOC_ES7134)	+= snd-soc-es7134.o
 obj-$(CONFIG_SND_SOC_ES7241)	+= snd-soc-es7241.o
 obj-$(CONFIG_SND_SOC_ES8316)    += snd-soc-es8316.o
+obj-$(CONFIG_SND_SOC_ES8326)    += snd-soc-es8326.o
 obj-$(CONFIG_SND_SOC_ES8328)	+= snd-soc-es8328.o
 obj-$(CONFIG_SND_SOC_ES8328_I2C)+= snd-soc-es8328-i2c.o
 obj-$(CONFIG_SND_SOC_ES8328_SPI)+= snd-soc-es8328-spi.o
diff --git a/sound/soc/codecs/es8326.c b/sound/soc/codecs/es8326.c
new file mode 100644
index 000000000000..92dd3757a3c5
--- /dev/null
+++ b/sound/soc/codecs/es8326.c
@@ -0,0 +1,893 @@
+/*
+ * es8326.c -- es8326 ALSA SoC audio driver
+ *
+ * Copyright (c) 2016 Rockchip Electronics Co. Ltd.
+ *
+ * Author: Mark Brown <will@everset-semi.com>
+ * Author: Jianqun Xu <jay.xu@rock-chips.com>
+ * Author: Nickey Yang <nickey.yang@rock-chips.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/i2c.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/of_gpio.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/tlv.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/initval.h>
+#include <linux/proc_fs.h>
+#include <linux/gpio.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <sound/jack.h>
+#include "es8326.h"
+
+/* codec private data */
+struct es8326_priv {
+	struct mutex lock;
+	struct clk *mclk;
+	struct regmap *regmap;
+	struct snd_soc_component *component;
+	struct snd_soc_jack *jack;
+	int irq;
+	unsigned int sysclk;
+	struct snd_pcm_hw_constraint_list sysclk_constraints;
+	bool spk_gpio_level;
+	bool jd_inverted;
+};
+
+/*
+ * ES8326 controls
+ */
+static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(es8326_dac_vol_tlv, -9550, 50, 0);
+static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(es8326_adc_vol_tlv, -9550, 50, 0);
+static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(es8326_adc_pga_tlv, 0, 600, 0);
+static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(es8326_softramp_rate, 0, 100, 0);
+static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(es8326_drc_target_tlv, -3200,
+					     200, 0);
+static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(es8326_drc_recovery_tlv, -125,
+					     250, 0);
+
+static const char * const es8326_winsize[] = {
+	"0.25db/2 LRCK",
+	"0.25db/4 LRCK",
+	"0.25db/8 LRCK",
+	"0.25db/16 LRCK",
+	"0.25db/32 LRCK",
+	"0.25db/64 LRCK",
+	"0.25db/128 LRCK",
+	"0.25db/256 LRCK",
+	"0.25db/512 LRCK",
+	"0.25db/1024 LRCK",
+	"0.25db/2048 LRCK",
+	"0.25db/4096 LRCK",
+	"0.25db/8192 LRCK",
+	"0.25db/16384 LRCK",
+	"0.25db/32768 LRCK",
+	"0.25db/65536 LRCK",
+};
+
+static const char * const es8326_dacpol_txt[] = {
+	"Normal", "R Invert", "L Invert", "L + R Invert"
+};
+static const struct soc_enum es8326_dacpol =
+	SOC_ENUM_SINGLE(ES8326_DAC_DSM, 4, ARRAY_SIZE(es8326_dacpol_txt),
+			es8326_dacpol_txt);
+static const struct soc_enum es8326_alc_winsize =
+	SOC_ENUM_SINGLE(ES8326_ADC_RAMPRATE, 4, ARRAY_SIZE(es8326_winsize),
+			es8326_winsize);
+static const struct soc_enum es8326_drc_winsize =
+	SOC_ENUM_SINGLE(ES8326_DRC_WINSIZE, 4, ARRAY_SIZE(es8326_winsize),
+			es8326_winsize);
+
+static const struct snd_kcontrol_new es8326_snd_controls[] = {
+	SOC_SINGLE_TLV("DAC Playback Volume", ES8326_DAC_VOL, 0, 0xff, 0,
+		       es8326_dac_vol_tlv),
+	SOC_ENUM("Playback Polarity", es8326_dacpol),
+	SOC_SINGLE_TLV("DAC Ramp Rate", ES8326_DAC_RAMPRATE, 0, 0x0f, 0,
+		       es8326_softramp_rate),
+	SOC_SINGLE("DRC Switch", ES8326_DRC_RECOVERY, 3, 1, 0),
+	SOC_SINGLE_TLV("DRC Recovery Level", ES8326_DRC_RECOVERY, 0, 4, 0,
+		       es8326_drc_recovery_tlv),
+	SOC_ENUM("DRC Winsize", es8326_drc_winsize),
+	SOC_SINGLE_TLV("DRC Target Level", ES8326_DRC_WINSIZE, 0, 0x0f, 0,
+		       es8326_drc_target_tlv),
+
+	SOC_DOUBLE_R_TLV("ADC Capture Volume", ES8326_ADC1_VOL,
+			 ES8326_ADC2_VOL, 0, 0xff, 0, es8326_adc_vol_tlv),
+	SOC_DOUBLE_TLV("ADC PGA Gain Volume", ES8326_ADC_SCALE, 4, 0, 5, 0,
+		       es8326_adc_pga_tlv),
+	SOC_SINGLE_TLV("ADC Ramp Rate", ES8326_ADC_RAMPRATE, 0, 0x0f, 0,
+		       es8326_softramp_rate),
+	SOC_SINGLE("ALC Switch", ES8326_ALC_RECOVERY, 3, 1, 0),
+	SOC_SINGLE_TLV("ALC Recovery Level", ES8326_ALC_LEVEL, 0, 4, 0,
+		       es8326_drc_recovery_tlv),
+	SOC_ENUM("ALC Winsize", es8326_alc_winsize),
+	SOC_SINGLE_TLV("ALC Target Level", ES8326_ALC_LEVEL, 0, 0x0f, 0,
+		       es8326_drc_target_tlv),
+};
+
+static const char * const es8326_adc_src_txt[] = {
+	"Analog MIC", "DMIC SDINOUT2"
+};
+static const unsigned int es8326_adc_src_values[] = { 0, 0x44 };
+static const struct soc_enum es8326_adc1_src_enum =
+	SOC_VALUE_ENUM_SINGLE(ES8326_ADC1_SRC, 0, 0xff,
+			      ARRAY_SIZE(es8326_adc_src_txt),
+			      es8326_adc_src_txt,
+			      es8326_adc_src_values);
+static const struct snd_kcontrol_new es8326_mic_mux_controls =
+	SOC_DAPM_ENUM("Route", es8326_adc1_src_enum);
+
+static const struct snd_soc_dapm_widget es8326_dapm_widgets[] = {
+	SND_SOC_DAPM_REG(snd_soc_dapm_supply, "Mic Bias", ES8326_ANA_MICBIAS,
+			 2, 0x3, 3, 0),
+
+	SND_SOC_DAPM_INPUT("MIC1"),
+	SND_SOC_DAPM_INPUT("MIC2"),
+
+	SND_SOC_DAPM_MUX("Mic Mux", SND_SOC_NOPM, 0, 0,
+			 &es8326_mic_mux_controls),
+
+    	/* Digital Interface */
+	SND_SOC_DAPM_AIF_OUT("I2S OUT", "I2S1 Capture", 0, SND_SOC_NOPM, 0, 0),
+	SND_SOC_DAPM_AIF_IN("I2S IN", "I2S1 Playback", 0, SND_SOC_NOPM, 0, 0),
+
+	SND_SOC_DAPM_DAC("Right DAC", NULL, ES8326_ANA_PWR, 0, 1),
+	SND_SOC_DAPM_DAC("Left DAC", NULL, ES8326_ANA_PWR, 1, 1),
+	SND_SOC_DAPM_PGA("LHPMIX", ES8326_DAC2HPMIX, 7, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("RHPMIX", ES8326_DAC2HPMIX, 3, 0, NULL, 0),
+	SND_SOC_DAPM_SUPPLY("HPOR Cal", ES8326_HP_CTL, 7, 1, NULL, 0),
+	SND_SOC_DAPM_SUPPLY("HPOL Cal", ES8326_HP_CTL, 3, 1, NULL, 0),
+	SND_SOC_DAPM_REG(snd_soc_dapm_supply, "HPOR Supply", ES8326_HP_CTL,
+			 4, 0x7, 7, 0),
+	SND_SOC_DAPM_REG(snd_soc_dapm_supply, "HPOL Supply", ES8326_HP_CTL,
+			 0, 0x7, 7, 0),
+	SND_SOC_DAPM_OUTPUT("HPOL"),
+	SND_SOC_DAPM_OUTPUT("HPOR"),
+};
+
+static const struct snd_soc_dapm_route es8326_dapm_routes[] = {
+	/* Recording */
+	{"MIC1", NULL, "Mic Bias"},
+	{"MIC2", NULL, "Mic Bias"},
+
+	{"Mic Mux", "DMIC SDINOUT2", "MIC1"},
+	{"Mic Mux", "Analog MIC", "MIC2"},
+
+	{"I2S OUT", NULL, "Mic Mux"},
+
+	/* Playback */
+	{"Right DAC", NULL, "I2S IN"},
+	{"Left DAC", NULL, "I2S IN"},
+
+	{"LHPMIX", NULL, "Left DAC"},
+	{"RHPMIX", NULL, "Right DAC"},
+
+	{"HPOR", NULL , "HPOR Cal"},
+	{"HPOL", NULL , "HPOL Cal"},
+
+	{"HPOR", NULL , "HPOR Supply"},
+	{"HPOL", NULL , "HPOL Supply"},
+
+	{"HPOL", NULL, "LHPMIX"},
+	{"HPOR", NULL, "RHPMIX"},
+};
+
+struct es8326_clk_coeff {
+	u16 fs;
+	u32 rate;
+	u32 mclk;
+	u8 reg4;
+	u8 reg5;
+	u8 reg6;
+	u8 reg7;
+	u8 reg8;
+	u8 reg9;
+	u8 rega;
+	u8 regb;
+};
+
+/* codec hifi mclk clock divider coefficients */
+static const struct es8326_clk_coeff es8326_coeff_div[] = {
+	{  32,  8000,   256000, 0x60, 0x00, 0x0f, 0x75, 0x0a, 0x1b, 0x1f, 0x7f},
+	{  32, 16000,   512000, 0x20, 0x00, 0x0d, 0x75, 0x0a, 0x1b, 0x1f, 0x3f},
+	{  32, 44100,  1411200, 0x00, 0x00, 0x13, 0x2d, 0x0a, 0x0a, 0x1f, 0x1f},
+	{  32, 48000,  1536000, 0x00, 0x00, 0x13, 0x2d, 0x0a, 0x0a, 0x1f, 0x1f},
+	{  36,  8000,   288000, 0x20, 0x00, 0x0d, 0x75, 0x0a, 0x1b, 0x23, 0x47},
+	{  36, 16000,   576000, 0x20, 0x00, 0x0d, 0x75, 0x0a, 0x1b, 0x23, 0x47},
+	{  48,  8000,   384000, 0x60, 0x02, 0x1f, 0x75, 0x0a, 0x1b, 0x1f, 0x7f},
+	{  48, 16000,   768000, 0x20, 0x02, 0x0f, 0x75, 0x0a, 0x1b, 0x1f, 0x3f},
+	{  48, 48000,  2304000, 0x00, 0x02, 0x0d, 0x2d, 0x0a, 0x0a, 0x1f, 0x1f},
+	{  64,  8000,   512000, 0x60, 0x00, 0x0d, 0x75, 0x0a, 0x1b, 0x1f, 0x7f},
+	{  64, 16000,  1024000, 0x20, 0x00, 0x05, 0x75, 0x0a, 0x1b, 0x1f, 0x3f},
+
+	{  64, 44100,  2822400, 0x00, 0x00, 0x11, 0x2d, 0x0a, 0x0a, 0x1f, 0x1f},
+	{  64, 48000,  3072000, 0x00, 0x00, 0x11, 0x2d, 0x0a, 0x0a, 0x1f, 0x1f},
+	{  72,  8000,   576000, 0x20, 0x00, 0x13, 0x35, 0x0a, 0x1b, 0x23, 0x47},
+	{  72, 16000,  1152000, 0x20, 0x00, 0x05, 0x75, 0x0a, 0x1b, 0x23, 0x47},
+	{  96,  8000,   768000, 0x60, 0x02, 0x1d, 0x75, 0x0a, 0x1b, 0x1f, 0x7f},
+	{  96, 16000,  1536000, 0x20, 0x02, 0x0d, 0x75, 0x0a, 0x1b, 0x1f, 0x3f},
+	{ 100, 48000,  4800000, 0x04, 0x04, 0x1f, 0x2d, 0x0a, 0x0a, 0x1f, 0x1f},
+	{ 125, 48000,  6000000, 0x04, 0x04, 0x1f, 0x2d, 0x0a, 0x0a, 0x27, 0x27},
+	{ 128,  8000,  1024000, 0x60, 0x00, 0x13, 0x35, 0x0a, 0x1b, 0x1f, 0x7f},
+	{ 128, 16000,  2048000, 0x20, 0x00, 0x11, 0x35, 0x0a, 0x1b, 0x1f, 0x3f},
+
+	{ 128, 44100,  5644800, 0x00, 0x00, 0x01, 0x2d, 0x0a, 0x0a, 0x1f, 0x1f},
+	{ 128, 48000,  6144000, 0x00, 0x00, 0x01, 0x2d, 0x0a, 0x0a, 0x1f, 0x1f},
+	{ 144,  8000,  1152000, 0x20, 0x00, 0x03, 0x35, 0x0a, 0x1b, 0x23, 0x47},
+	{ 144, 16000,  2304000, 0x20, 0x00, 0x11, 0x35, 0x0a, 0x1b, 0x23, 0x47},
+	{ 192,  8000,  1536000, 0x60, 0x02, 0x0d, 0x75, 0x0a, 0x1b, 0x1f, 0x7f},
+	{ 192, 16000,  3072000, 0x20, 0x02, 0x05, 0x75, 0x0a, 0x1b, 0x1f, 0x3f},
+	{ 200, 48000,  9600000, 0x04, 0x04, 0x0f, 0x2d, 0x0a, 0x0a, 0x1f, 0x1f},
+	{ 250, 48000, 12000000, 0x04, 0x04, 0x0f, 0x2d, 0x0a, 0x0a, 0x27, 0x27},
+	{ 256,  8000,  2048000, 0x60, 0x00, 0x11, 0x35, 0x0a, 0x1b, 0x1f, 0x7f},
+	{ 256, 16000,  4096000, 0x20, 0x00, 0x01, 0x35, 0x0a, 0x1b, 0x1f, 0x3f},
+
+	{ 256, 44100, 11289600, 0x00, 0x00, 0x10, 0x2d, 0x0a, 0x0a, 0x1f, 0x1f},
+	{ 256, 48000, 12288000, 0x00, 0x00, 0x10, 0x2d, 0x0a, 0x0a, 0x1f, 0x1f},
+	{ 288,  8000,  2304000, 0x20, 0x00, 0x01, 0x35, 0x0a, 0x1b, 0x23, 0x47},
+	{ 384,  8000,  3072000, 0x60, 0x02, 0x05, 0x75, 0x0a, 0x1b, 0x1f, 0x7f},
+	{ 384, 16000,  6144000, 0x20, 0x02, 0x03, 0x35, 0x0a, 0x1b, 0x1f, 0x3f},
+	{ 384, 48000, 18432000, 0x00, 0x02, 0x01, 0x2d, 0x0a, 0x0a, 0x1f, 0x1f},
+	{ 400, 48000, 19200000, 0x09, 0x04, 0x0f, 0x6d, 0x3a, 0x0a, 0x4f, 0x1f},
+	{ 500, 48000, 24000000, 0x18, 0x04, 0x1f, 0x2d, 0x0a, 0x0a, 0x1f, 0x1f},
+	{ 512,  8000,  4096000, 0x60, 0x00, 0x01, 0x35, 0x0a, 0x1b, 0x1f, 0x7f},
+	{ 512, 16000,  8192000, 0x20, 0x00, 0x10, 0x35, 0x0a, 0x1b, 0x1f, 0x3f},
+
+	{ 512, 44100, 22579200, 0x00, 0x00, 0x00, 0x2d, 0x0a, 0x0a, 0x1f, 0x1f},
+	{ 512, 48000, 24576000, 0x00, 0x00, 0x00, 0x2d, 0x0a, 0x0a, 0x1f, 0x1f},
+	{ 768,  8000,  6144000, 0x60, 0x02, 0x11, 0x35, 0x0a, 0x1b, 0x1f, 0x7f},
+	{ 768, 16000, 12288000, 0x20, 0x02, 0x01, 0x35, 0x0a, 0x1b, 0x1f, 0x3f},
+	{ 800, 48000, 38400000, 0x00, 0x18, 0x13, 0x2d, 0x0a, 0x0a, 0x1f, 0x1f},
+	{ 812, 16000, 13000000, 0x0c, 0x04, 0x0f, 0x2d, 0x0a, 0x0a, 0x31, 0x31},
+	{1024,  8000,  8192000, 0x60, 0x00, 0x10, 0x35, 0x0a, 0x1b, 0x1f, 0x7f},
+	{1024, 16000, 16384000, 0x20, 0x00, 0x00, 0x35, 0x0a, 0x1b, 0x1f, 0x3f},
+	{1152, 16000, 18432000, 0x20, 0x08, 0x11, 0x35, 0x0a, 0x1b, 0x1f, 0x3f},
+	{1536,  8000, 12288000, 0x60, 0x02, 0x01, 0x35, 0x0a, 0x1b, 0x1f, 0x7f},
+
+	{1536, 16000, 24576000, 0x20, 0x02, 0x10, 0x35, 0x0a, 0x1b, 0x1f, 0x3f},
+	{1625,  8000, 13000000, 0x0c, 0x18, 0x1f, 0x2d, 0x0a, 0x0a, 0x27, 0x27},
+	{1625, 16000, 26000000, 0x0c, 0x18, 0x1f, 0x2d, 0x0a, 0x0a, 0x27, 0x27},
+	{2048,  8000, 16384000, 0x60, 0x00, 0x00, 0x35, 0x0a, 0x1b, 0x1f, 0x7f},
+	{2304,  8000, 18432000, 0x40, 0x02, 0x10, 0x35, 0x0a, 0x1b, 0x1f, 0x5f},
+	{3072,  8000, 24576000, 0x60, 0x02, 0x10, 0x35, 0x0a, 0x1b, 0x1f, 0x7f},
+	{3250,  8000, 26000000, 0x0c, 0x18, 0x0f, 0x2d, 0x0a, 0x0a, 0x27, 0x27},
+	{  21, 48000,  1024320, 0x00, 0x00, 0x09, 0x2d, 0x0a, 0x0a, 0x1f, 0x1f},
+	{ 541, 48000, 26000000, 0x00, 0x00, 0x00, 0x35, 0x0a, 0x1b, 0x20, 0x20},
+};
+
+static const struct es8326_clk_coeff *es8326_get_coeff(int mclk, int rate)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(es8326_coeff_div); i++) {
+		if (es8326_coeff_div[i].rate == rate &&
+		    es8326_coeff_div[i].mclk == mclk)
+			return &es8326_coeff_div[i];
+	}
+
+	return NULL;
+}
+
+/* The set of rates we can generate from the above for each SYSCLK */
+
+static unsigned int es8326_rates_12288[] = {
+	8000, 12000, 16000, 24000, 24000, 32000, 48000, 96000,
+};
+
+static struct snd_pcm_hw_constraint_list es8326_constraints_12288 = {
+	.count = ARRAY_SIZE(es8326_rates_12288),
+	.list = es8326_rates_12288,
+};
+
+static unsigned int es8326_rates_112896[] = {
+	8000, 11025, 22050, 44100,
+};
+
+static struct snd_pcm_hw_constraint_list es8326_constraints_112896 = {
+	.count = ARRAY_SIZE(es8326_rates_112896),
+	.list = es8326_rates_112896,
+};
+
+static unsigned int es8326_rates_12[] = {
+	8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000,
+	48000, 88235, 96000,
+};
+
+static struct snd_pcm_hw_constraint_list es8326_constraints_12 = {
+	.count = ARRAY_SIZE(es8326_rates_12),
+	.list = es8326_rates_12,
+};
+
+/*
+ * Note that this should be called from init rather than from hw_params.
+ */
+static int es8326_set_dai_sysclk(struct snd_soc_dai *codec_dai,
+				 int clk_id, unsigned int freq, int dir)
+{
+	struct snd_soc_component *component = codec_dai->component;
+	struct es8326_priv *es8326 = snd_soc_component_get_drvdata(component);
+	int ret;
+
+	es8326->sysclk = freq;
+
+	if (freq == 0) {
+		es8326->sysclk_constraints.list = NULL;
+		es8326->sysclk_constraints.count = 0;
+
+		return 0;
+	}
+
+	ret = clk_set_rate(es8326->mclk, freq);
+	if (ret)
+		return ret;
+
+	switch (freq) {
+	case 11289600:
+	case 18432000:
+	case 22579200:
+	case 36864000:
+		es8326->sysclk_constraints = es8326_constraints_112896;
+		return 0;
+
+	case 12288000:
+	case 16934400:
+	case 24576000:
+	case 33868800:
+		es8326->sysclk_constraints = es8326_constraints_12288;
+		return 0;
+
+	case 12000000:
+	case 19200000:
+	case 24000000:
+		es8326->sysclk_constraints = es8326_constraints_12;
+		return 0;
+
+	default:
+		return -EINVAL;
+	}
+}
+
+static int es8326_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
+{
+	struct snd_soc_component *component = codec_dai->component;
+	u8 iface;
+
+	/* interface format */
+	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+	case SND_SOC_DAIFMT_I2S:
+		iface = ES8326_FMT_SDP_FMT_I2S;
+		break;
+	case SND_SOC_DAIFMT_LEFT_J:
+		iface = ES8326_FMT_SDP_FMT_LJ;
+		break;
+	case SND_SOC_DAIFMT_DSP_A:
+	case SND_SOC_DAIFMT_DSP_B:
+		iface = ES8326_FMT_SDP_FMT_DSP;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	snd_soc_component_write(component, ES8326_FMT, iface);
+	snd_soc_component_update_bits(component, ES8326_FMT,
+				      ES8326_FMT_SDP_FMT_MASK, iface);
+
+	return 0;
+}
+
+static int es8326_pcm_startup(struct snd_pcm_substream *substream,
+			      struct snd_soc_dai *dai)
+{
+	struct snd_soc_component *component = dai->component;
+	struct es8326_priv *es8326 = snd_soc_component_get_drvdata(component);
+
+	/* The set of sample rates that can be supported depends on the
+	 * MCLK supplied to the CODEC - enforce this.
+	 */
+
+	if (es8326->sysclk_constraints.list)
+		snd_pcm_hw_constraint_list(substream->runtime, 0,
+					   SNDRV_PCM_HW_PARAM_RATE,
+					   &es8326->sysclk_constraints);
+
+	return 0;
+}
+
+static int es8326_pcm_hw_params(struct snd_pcm_substream *substream,
+				struct snd_pcm_hw_params *params,
+				struct snd_soc_dai *dai)
+{
+	struct snd_soc_component *component = dai->component;
+	struct es8326_priv *es8326 = snd_soc_component_get_drvdata(component);
+	const struct es8326_clk_coeff *coeff;
+	u8 wordlen;
+
+	coeff = es8326_get_coeff(es8326->sysclk, params_rate(params));
+	if (!coeff)
+		return -EINVAL;
+
+	/* bit size */
+	switch (params_format(params)) {
+	case SNDRV_PCM_FORMAT_S16_LE:
+		wordlen = ES8326_FMT_SDP_WL_16;
+		break;
+	case SNDRV_PCM_FORMAT_S20_3LE:
+		wordlen = ES8326_FMT_SDP_WL_20;
+		break;
+	case SNDRV_PCM_FORMAT_S18_3LE:
+		wordlen = ES8326_FMT_SDP_WL_18;
+		break;
+	case SNDRV_PCM_FORMAT_S24_LE:
+		wordlen = ES8326_FMT_SDP_WL_24;
+		break;
+	case SNDRV_PCM_FORMAT_S32_LE:
+		wordlen = ES8326_FMT_SDP_WL_32;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	snd_soc_component_update_bits(component, ES8326_FMT,
+				      ES8326_FMT_SDP_WL_MASK, wordlen);
+
+	snd_soc_component_write(component, ES8326_CLK_DIV1, coeff->reg4);
+	snd_soc_component_write(component, ES8326_CLK_DIV2, coeff->reg5);
+	snd_soc_component_write(component, ES8326_CLK_DLL, coeff->reg6);
+	snd_soc_component_write(component, ES8326_CLK_MUX, coeff->reg7);
+	snd_soc_component_write(component, ES8326_CLK_ADC_SEL, coeff->reg8);
+	snd_soc_component_write(component, ES8326_CLK_DAC_SEL, coeff->reg9);
+	snd_soc_component_write(component, ES8326_CLK_ADC_OSR, coeff->rega);
+	snd_soc_component_write(component, ES8326_CLK_DAC_OSR, coeff->regb);
+	return 0;
+}
+
+static int es8326_mute(struct snd_soc_dai *dai, int mute, int stream)
+{
+	switch (stream) {
+	case SNDRV_PCM_STREAM_PLAYBACK:
+		snd_soc_component_update_bits(dai->component, ES8326_DAC_MUTE,
+				ES8326_DAC_MUTE_S2P_MUTE_MASK,
+				mute ?  ES8326_DAC_MUTE_S2P_MUTE_MASK : 0);
+		break;
+	case SNDRV_PCM_STREAM_CAPTURE:
+		snd_soc_component_update_bits(dai->component, ES8326_ADC_MUTE,
+				ES8326_ADC_MUTE_P2S_MUTE_MASK,
+				mute ? ES8326_ADC_MUTE_P2S_MUTE_MASK : 0);
+		break;
+	}
+
+	return 0;
+}
+
+#define ES8326_FORMATS	(SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
+			 SNDRV_PCM_FMTBIT_S24_LE)
+
+static struct snd_soc_dai_ops es8326_ops = {
+	.startup = es8326_pcm_startup,
+	.hw_params = es8326_pcm_hw_params,
+	.set_fmt = es8326_set_dai_fmt,
+	.set_sysclk = es8326_set_dai_sysclk,
+	.mute_stream = es8326_mute,
+};
+
+static struct snd_soc_dai_driver es8326_dai = {
+	.name = "ES8316 HiFi",
+	.playback = {
+		.stream_name = "Playback",
+		.channels_min = 1,
+		.channels_max = 2,
+		.rates = SNDRV_PCM_RATE_8000_96000,
+		.formats = ES8326_FORMATS,
+	},
+	.capture = {
+		.stream_name = "Capture",
+		.channels_min = 1,
+		.channels_max = 2,
+		.rates = SNDRV_PCM_RATE_8000_96000,
+		.formats = ES8326_FORMATS,
+	},
+	.ops = &es8326_ops,
+	.symmetric_rate = 1,
+};
+
+static void es8326_enable_micbias_for_mic_gnd_short_detect(
+					struct snd_soc_component *component)
+{
+	struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component);
+
+	snd_soc_dapm_force_enable_pin(dapm, "Mic Bias");
+
+	msleep(500);
+}
+
+static void es8326_disable_micbias_for_mic_gnd_short_detect(
+					struct snd_soc_component *component)
+{
+	struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component);
+
+	snd_soc_dapm_disable_pin(dapm, "Mic Bias");
+}
+
+static irqreturn_t es8326_irq(int irq, void *data)
+{
+	struct es8326_priv *es8326 = data;
+	struct snd_soc_component *comp = es8326->component;
+	unsigned int flags;
+
+	mutex_lock(&es8326->lock);
+
+	/* Catch spurious IRQ before set_jack is called */
+	if (!es8326->jack)
+		goto out;
+
+	es8326_enable_micbias_for_mic_gnd_short_detect(comp);
+
+	regmap_read(es8326->regmap, ES8326_HP_DETECT, &flags);
+	if (es8326->jd_inverted)
+		flags ^= ES8326_HP_DETECT_NOT_INSERTED;
+
+	dev_dbg(comp->dev, "flags: %#04x\n", flags);
+	if (flags & ES8326_HP_DETECT_NOT_INSERTED) {
+		snd_soc_jack_report(es8326->jack, 0,
+				    SND_JACK_HEADSET | SND_JACK_BTN_0);
+		dev_dbg(comp->dev, "jack unplugged\n");
+	} else {
+		if (flags & ES8326_HP_DETECT_GM_NOT_SHORTED) {
+			dev_dbg(comp->dev, "headphones detected\n");
+			snd_soc_jack_report(es8326->jack, SND_JACK_HEADPHONE,
+					    SND_JACK_HEADSET);
+		} else {
+			dev_dbg(comp->dev, "headset detected\n");
+			snd_soc_jack_report(es8326->jack, SND_JACK_HEADSET,
+					    SND_JACK_HEADSET);
+		}
+	}
+
+	if (!(es8326->jack->status & SND_JACK_MICROPHONE))
+		es8326_disable_micbias_for_mic_gnd_short_detect(comp);
+out:
+	mutex_unlock(&es8326->lock);
+	return IRQ_HANDLED;
+}
+
+static void es8326_enable_jack_detect(struct snd_soc_component *component,
+				      struct snd_soc_jack *jack)
+{
+	struct es8326_priv *es8326 = snd_soc_component_get_drvdata(component);
+
+	/*
+	 * Init es8326->jd_inverted here and not in the probe, as we cannot
+	 * guarantee that the sof-essx8336 driver, which might set this
+	 * property, will probe before us.
+	 */
+	es8326->jd_inverted =
+		device_property_read_bool(component->dev,
+					  "everest,jack-detect-inverted");
+
+	mutex_lock(&es8326->lock);
+
+	es8326->jack = jack;
+
+	snd_soc_component_write(component, ES8326_HPJACK_POL,
+				ES8326_HPJACK_POL_HP_TYPE_CTIA |
+				ES8326_HPJACK_POL_BUTTON_POL_ACTIVE_LOW |
+				ES8326_HPJACK_POL_HPJACK_POL_ACTIVE_LOW |
+				ES8326_HPJACK_POL_HPINSERT_SEL_PIN9);
+	snd_soc_component_write(component, ES8326_INT_SOURCE,
+				ES8326_INT_SOURCE_BUTTON |
+				ES8326_INT_SOURCE_PIN9);
+
+	mutex_unlock(&es8326->lock);
+
+	/* Enable irq and sync initial jack state */
+	enable_irq(es8326->irq);
+	es8326_irq(es8326->irq, es8326);
+}
+
+static void es8326_disable_jack_detect(struct snd_soc_component *component)
+{
+	struct es8326_priv *es8326 = snd_soc_component_get_drvdata(component);
+
+	disable_irq(es8326->irq);
+
+	mutex_lock(&es8326->lock);
+
+	snd_soc_component_write(component, ES8326_INT_SOURCE, 0);
+
+	if (es8326->jack->status & SND_JACK_MICROPHONE)
+		snd_soc_jack_report(es8326->jack, 0, SND_JACK_BTN_0);
+
+	es8326->jack = NULL;
+
+	mutex_unlock(&es8326->lock);
+}
+
+static int es8326_set_jack(struct snd_soc_component *component,
+			   struct snd_soc_jack *jack, void *data)
+{
+	if (jack)
+		es8326_enable_jack_detect(component, jack);
+	else
+		es8326_disable_jack_detect(component);
+
+	return 0;
+}
+
+static int es8326_set_bias_level(struct snd_soc_component *component,
+				 enum snd_soc_bias_level level)
+{
+	switch (level) {
+	case SND_SOC_BIAS_ON:
+		dev_dbg(component->dev, "%s on\n", __func__);
+		snd_soc_component_write(component, ES8326_HP_DRIVER, 0);
+		snd_soc_component_write(component, ES8326_ANA_PWR, 0);
+		snd_soc_component_update_bits(component, ES8326_PGA_PWR,
+					      ES8326_PGA_PWR_PDN_PGA |
+					      ES8326_PGA_PWR_PDN_MOD |
+					      ES8326_PGA_PWR_MODTOP_RST,
+					      0);
+		snd_soc_component_write(component, ES8326_VMIDSEL,
+					ES8326_VMIDSEL_NORMAL);
+		break;
+
+	case SND_SOC_BIAS_PREPARE:
+		dev_dbg(component->dev, "%s prepare\n", __func__);
+		break;
+
+	case SND_SOC_BIAS_STANDBY:
+		dev_dbg(component->dev, "%s standby\n", __func__);
+		snd_soc_component_update_bits(component, ES8326_HP_DRIVER,
+					      ES8326_HP_DRIVER_LP_MASK,
+					      ES8326_HP_DRIVER_LP_MASK);
+		snd_soc_component_update_bits(component, ES8326_ANA_PWR,
+					      ES8326_ANA_PWR_LP_DAC,
+					      ES8326_ANA_PWR_LP_DAC);
+		break;
+
+	case SND_SOC_BIAS_OFF:
+		dev_dbg(component->dev, "%s off\n", __func__);
+		snd_soc_component_write(component, ES8326_VMIDSEL,
+					ES8326_VMIDSEL_POWER_DOWN);
+		snd_soc_component_update_bits(component, ES8326_PGA_PWR,
+					      ES8326_PGA_PWR_PDN_PGA |
+					      ES8326_PGA_PWR_PDN_MOD |
+					      ES8326_PGA_PWR_MODTOP_RST,
+					      ES8326_PGA_PWR_PDN_PGA |
+					      ES8326_PGA_PWR_PDN_MOD |
+					      ES8326_PGA_PWR_MODTOP_RST);
+		snd_soc_component_write(component, ES8326_ANA_PWR,
+					ES8326_ANA_PWR_PDN_DACR |
+					ES8326_ANA_PWR_PDN_DACL |
+					ES8326_ANA_PWR_LP_DAC |
+					ES8326_ANA_PWR_PDN_VRP |
+					ES8326_ANA_PWR_PDN_DACVREFGEN |
+					ES8326_ANA_PWR_PDN_ADCVREFGEN |
+					ES8326_ANA_PWR_PDN_IBIASGEN |
+					ES8326_ANA_PWR_PDN_ANA);
+		snd_soc_component_update_bits(component, ES8326_HP_DRIVER,
+					      ES8326_HP_DRIVER_PDN_MASK |
+					      ES8326_HP_DRIVER_ENREFR_HP,
+					      ES8326_HP_DRIVER_PDN_MASK |
+					      ES8326_HP_DRIVER_ENREFR_HP);
+		break;
+
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+static int es8326_probe(struct snd_soc_component *component)
+{
+	struct es8326_priv *es8326 = snd_soc_component_get_drvdata(component);
+	int ret;
+
+	es8326->component = component;
+
+	es8326->mclk = devm_clk_get_optional(component->dev, "mclk");
+	if (IS_ERR(es8326->mclk)) {
+		dev_err(component->dev,"unable to get mclk\n");
+		return PTR_ERR(es8326->mclk);
+	}
+	if (!es8326->mclk)
+		dev_warn(component->dev,"assuming static mclk\n");
+
+	ret = clk_prepare_enable(es8326->mclk);
+	if (ret) {
+		dev_err(component->dev,"unable to enable mclk\n");
+		return ret;
+	}
+
+	snd_soc_component_init_regmap(component, es8326->regmap);
+
+	/* Reset codec and enable current state machine */
+	snd_soc_component_write(component, ES8326_RESET, ES8326_RESET_RST_MASK);
+	usleep_range(5000, 5500);
+	snd_soc_component_write(component, ES8326_RESET, ES8326_RESET_CSM_ON);
+	msleep(30);
+
+	snd_soc_component_write(component, ES8326_PULLUP_CTL,
+				ES8326_PULLUP_CTL_ADC34_OFF);
+	snd_soc_component_write(component, ES8326_CLK_CTL,
+				ES8326_CLK_CTL_CLK9_ON |
+				ES8326_CLK_CTL_CLK8_ON |
+				ES8326_CLK_CTL_CLK3_ON |
+				ES8326_CLK_CTL_CLK1_ON |
+				ES8326_CLK_CTL_BCLK_ON |
+				ES8326_CLK_CTL_MCLK_ON |
+				ES8326_CLK_CTL_CPCLK_ON);
+	snd_soc_component_write(component, ES8326_CLK_RESAMPLE,
+				ES8326_CLK_RESAMPLE_OSC_EN_ALWAYS_ON |
+				ES8326_CLK_RESAMPLE_INTCLK_SEL_OSC);
+	snd_soc_component_write(component, ES8326_ADC_MUTE, 0);
+	snd_soc_component_update_bits(component, ES8326_PGAGAIN,
+				      ES8326_PGAGAIN_MIC1SEL,
+				      ES8326_PGAGAIN_MIC1SEL);
+	return 0;
+}
+
+static void es8326_remove(struct snd_soc_component *component)
+{
+	struct es8326_priv *es8326 = snd_soc_component_get_drvdata(component);
+
+	snd_soc_component_exit_regmap(component);
+
+	clk_disable_unprepare(es8326->mclk);
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int es8326_suspend(struct device *dev)
+{
+	struct es8326_priv *es8326 = dev_get_drvdata(dev);
+
+	dev_dbg(dev, "%s: Enter\n", __func__);
+
+	regcache_cache_only(es8326->regmap, true);
+	regcache_mark_dirty(es8326->regmap);
+
+	return 0;
+}
+
+static int es8326_resume(struct device *dev)
+{
+	struct es8326_priv *es8326 = dev_get_drvdata(dev);
+
+	dev_dbg(dev, "%s: Enter\n", __func__);
+
+	regcache_cache_only(es8326->regmap, false);
+	regcache_sync(es8326->regmap);
+
+	es8326_irq(es8326->irq, es8326);
+
+	return 0;
+}
+#endif
+
+static const struct dev_pm_ops es8326_pm = {
+	SET_SYSTEM_SLEEP_PM_OPS(es8326_suspend, es8326_resume)
+};
+
+static struct snd_soc_component_driver soc_component_dev_es8326 = {
+	.probe			= es8326_probe,
+	.remove			= es8326_remove,
+	.set_bias_level		= es8326_set_bias_level,
+	.set_jack		= es8326_set_jack,
+	.controls		= es8326_snd_controls,
+	.num_controls		= ARRAY_SIZE(es8326_snd_controls),
+	.dapm_widgets		= es8326_dapm_widgets,
+	.num_dapm_widgets	= ARRAY_SIZE(es8326_dapm_widgets),
+	.dapm_routes		= es8326_dapm_routes,
+	.num_dapm_routes	= ARRAY_SIZE(es8326_dapm_routes),
+	.use_pmdown_time	= 1,
+	.endianness		= 1,
+	.non_legacy_dai_naming	= 1,
+};
+
+static const struct regmap_range es8326_volatile_ranges[] = {
+	regmap_reg_range(ES8326_HP_DETECT, ES8326_HP_DETECT),
+};
+
+static const struct regmap_access_table es8326_volatile_table = {
+	.yes_ranges	= es8326_volatile_ranges,
+	.n_yes_ranges	= ARRAY_SIZE(es8326_volatile_ranges),
+};
+
+static const struct regmap_config es8326_regmap = {
+	.reg_bits = 8,
+	.val_bits = 8,
+	.max_register = 0xff,
+	.volatile_table	= &es8326_volatile_table,
+	.cache_type = REGCACHE_RBTREE,
+	.use_single_read = true,
+	.use_single_write = true,
+};
+
+static int es8326_i2c_probe(struct i2c_client *i2c_client,
+			    const struct i2c_device_id *id)
+{
+	struct device *dev = &i2c_client->dev;
+	struct es8326_priv *es8326;
+	int ret;
+
+	es8326 = devm_kzalloc(dev, sizeof(*es8326), GFP_KERNEL);
+	if (es8326 == NULL)
+		return -ENOMEM;
+
+	i2c_set_clientdata(i2c_client, es8326);
+
+	es8326->regmap = devm_regmap_init_i2c(i2c_client, &es8326_regmap);
+	if (IS_ERR(es8326->regmap))
+		return PTR_ERR(es8326->regmap);
+
+	es8326->irq = i2c_client->irq;
+	mutex_init(&es8326->lock);
+
+	ret = devm_request_threaded_irq(dev, es8326->irq, NULL, es8326_irq,
+					IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
+					"es8326", es8326);
+	if (ret == 0) {
+		/* Gets re-enabled by es8326_set_jack() */
+		disable_irq(es8326->irq);
+	} else {
+		dev_warn(dev, "Failed to get IRQ %d: %d\n", es8326->irq, ret);
+		es8326->irq = -ENXIO;
+	}
+
+	return devm_snd_soc_register_component(dev, &soc_component_dev_es8326,
+					       &es8326_dai, 1);
+}
+
+static const struct i2c_device_id es8326_i2c_id[] = {
+	{"es8326", 0},
+	{}
+};
+MODULE_DEVICE_TABLE(i2c, es8326_i2c_id);
+
+#ifdef CONFIG_OF
+static const struct of_device_id es8326_of_match[] = {
+	{ .compatible = "everest,es8326", },
+	{}
+};
+MODULE_DEVICE_TABLE(of, es8326_of_match);
+#endif
+
+#ifdef CONFIG_ACPI
+static const struct acpi_device_id es8326_acpi_match[] = {
+	{"ESSX8326", 0},
+	{},
+};
+MODULE_DEVICE_TABLE(acpi, es8326_acpi_match);
+#endif
+
+static struct i2c_driver es8326_i2c_driver = {
+	.driver = {
+		.name			= "es8326",
+		.acpi_match_table	= ACPI_PTR(es8326_acpi_match),
+		.of_match_table		= of_match_ptr(es8326_of_match),
+		.pm			= &es8326_pm,
+	},
+	.probe		= es8326_i2c_probe,
+	.id_table	= es8326_i2c_id,
+};
+module_i2c_driver(es8326_i2c_driver);
+
+MODULE_DESCRIPTION("Everest Semi ES8326 ALSA SoC Codec Driver");
+MODULE_AUTHOR("David <zhuning@everset-semi.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/codecs/es8326.h b/sound/soc/codecs/es8326.h
new file mode 100644
index 000000000000..5a9396658aa2
--- /dev/null
+++ b/sound/soc/codecs/es8326.h
@@ -0,0 +1,222 @@
+/*
+ * Copyright 2005 Openedhand Ltd.
+ *
+ * Author: Richard Purdie <richard@openedhand.com>
+ *
+ * Based on ES8326.h
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#ifndef _ES8326_H
+#define _ES8326_H
+
+/*
+ * ES8326 register space
+ */
+
+/* Reset */
+#define ES8326_RESET		0x00
+
+/* Clock Manager */
+#define ES8326_CLK_CTL		0x01
+#define ES8326_CLK_INV		0x02
+#define ES8326_CLK_RESAMPLE	0x03
+#define ES8326_CLK_DIV1		0x04
+#define ES8326_CLK_DIV2		0x05
+#define ES8326_CLK_DLL		0x06
+#define ES8326_CLK_MUX		0x07
+#define ES8326_CLK_ADC_SEL	0x08
+#define ES8326_CLK_DAC_SEL	0x09
+#define ES8326_CLK_ADC_OSR	0x0a
+#define ES8326_CLK_DAC_OSR	0x0b
+#define ES8326_CLK_DIV_CPC	0x0c
+#define ES8326_CLK_DIV_BCLK	0x0d
+#define ES8326_CLK_TRI		0x0e
+#define ES8326_CLK_DIV_LRCK	0x0f
+#define ES8326_CLK_VMIDS1	0x10
+#define ES8326_CLK_VMIDS2	0x11
+#define ES8326_CLK_CAL_TIME	0x12
+
+/* SDP */
+#define ES8326_FMT		0x13
+#define ES8326_DAC_MUTE		0x14
+#define ES8326_ADC_MUTE		0x15
+
+/* Analog */
+#define ES8326_ANA_PWR		0x16
+#define ES8326_PGA_PWR		0x17
+#define ES8326_VMIDSEL		0x18
+#define ES8326_ANA_LOWPOWER	0x19
+#define ES8326_ANA_DMS		0x1a
+#define ES8326_ANA_MICBIAS	0x1b
+#define ES8326_ANA_VSEL		0x1c
+#define ES8326_SYS_BIAS		0x1d
+#define ES8326_BIAS_SW1		0x1e
+#define ES8326_BIAS_SW2		0x1f
+#define ES8326_BIAS_SW3		0x20
+#define ES8326_BIAS_SW4		0x21
+#define ES8326_VMIDLOW		0x22
+#define ES8326_PGAGAIN		0x23
+#define ES8326_HP_DRIVER	0x24
+#define ES8326_DAC2HPMIX	0x25
+#define ES8326_HP_VOL		0x26
+#define ES8326_HP_CTL		0x27
+#define ES8326_HP_DRIVER_REF	0x28
+
+/* ADC Control */
+#define ES8326_ADC_SCALE	0x29
+#define ES8326_ADC1_SRC		0x2a
+#define ES8326_ADC2_SRC		0x2b
+#define ES8326_ADC1_VOL		0x2c
+#define ES8326_ADC2_VOL		0x2d
+#define ES8326_ADC_RAMPRATE	0x2e
+#define ES8326_ALC_RECOVERY	0x32
+#define ES8326_ALC_LEVEL	0x33
+#define ES8326_ADC_HPFS1	0x34
+#define ES8326_ADC_HPFS2	0x35
+#define ES8326_ADC_EQ		0x36
+
+/* DAC Control */
+#define ES8326_HP_CAL		0x4a
+#define ES8326_HPL_OFFSET_INI	0x4b
+#define ES8326_HPR_OFFSET_INI	0x4c
+#define ES8326_DAC_DSM		0x4d
+#define ES8326_DAC_RAMPRATE	0x4e
+#define ES8326_DAC_VPPSCALE	0x4f
+#define ES8326_DAC_VOL		0x50
+#define ES8326_DRC_RECOVERY	0x53
+#define ES8326_DRC_WINSIZE	0x54
+
+/* GPIO */
+#define ES8326_HPJACK_TIMER	0x56
+#define ES8326_HPJACK_POL	0x57
+#define ES8326_INT_SOURCE	0x58
+#define ES8326_INTOUT_IO	0x59
+#define ES8326_SDINOUT1_IO	0x5a
+#define ES8326_SDINOUT23_IO	0x5b
+#define ES8326_JACK_PULSE	0x5c
+
+/* Test Mode */
+#define ES8326_PULLUP_CTL	0xf9
+
+#define ES8326_HP_DETECT	0xfb
+
+/* Chip ID */
+#define ES8326_CHIP_ID1		0xfd
+#define ES8326_CHIP_ID2		0xfe
+#define ES8326_CHIP_VERSION	0xff
+
+/*
+ * Field definitions
+ */
+
+/* ES8326_RESET */
+#define ES8326_RESET_RST_MASK			0x1f
+#define ES8326_RESET_RST_DACDIG			0x01
+#define ES8326_RESET_RST_ADCDIG			0x02
+#define ES8326_RESET_RST_MST			0x04
+#define ES8326_RESET_RST_CMG			0x08
+#define ES8326_RESET_RST_DIG			0x10
+#define ES8326_RESET_SEQ_DIS			0x20
+#define ES8326_RESET_MSC			0x40
+#define ES8326_RESET_CSM_ON			0x80
+
+/* ES8326_CLK_CTL */
+#define ES8326_CLK_CTL_CLK9_ON			0x01
+#define ES8326_CLK_CTL_CLK8_ON			0x02
+#define ES8326_CLK_CTL_CLK3_ON			0x04
+#define ES8326_CLK_CTL_CLK1_ON			0x08
+#define ES8326_CLK_CTL_BCLK_ON			0x10
+#define ES8326_CLK_CTL_MCLK_ON			0x20
+#define ES8326_CLK_CTL_CPCLK_ON			0x40
+
+/* ES8326_CLK_RESAMPLE */
+#define ES8326_CLK_RESAMPLE_OSC_EN_ALWAYS_ON	0x01
+#define ES8326_CLK_RESAMPLE_INTCLK_SEL_OSC	0x04
+
+/* ES8326_FMT */
+#define ES8326_FMT_SDP_WL_MASK			0x1c
+#define ES8326_FMT_SDP_WL_24			0x00
+#define ES8326_FMT_SDP_WL_20			0x04
+#define ES8326_FMT_SDP_WL_18			0x08
+#define ES8326_FMT_SDP_WL_16			0x0c
+#define ES8326_FMT_SDP_WL_32			0x10
+#define ES8326_FMT_SDP_FMT_MASK			0x03
+#define ES8326_FMT_SDP_FMT_I2S			0x00
+#define ES8326_FMT_SDP_FMT_LJ			0x01
+#define ES8326_FMT_SDP_FMT_DSP			0x03
+
+/* ES8326_DAC_MUTE */
+#define ES8326_DAC_MUTE_S2P_MUTE_MASK		0x03
+#define ES8326_DAC_MUTE_S2P_MUTE_L		0x01
+#define ES8326_DAC_MUTE_S2P_MUTE_R		0x02
+
+/* ES8326_ADC_MUTE */
+#define ES8326_ADC_MUTE_P2S_MUTE_MASK		0x0f
+#define ES8326_ADC_MUTE_P2S_MUTE_1		0x01
+#define ES8326_ADC_MUTE_P2S_MUTE_2		0x02
+#define ES8326_ADC_MUTE_P2S_MUTE_3		0x04
+#define ES8326_ADC_MUTE_P2S_MUTE_4		0x08
+#define ES8326_ADC_MUTE_P2S_TDM_MODE		0x10
+
+/* ES8326_ANA_PWR */
+#define ES8326_ANA_PWR_PDN_DACR			0x01
+#define ES8326_ANA_PWR_PDN_DACL			0x02
+#define ES8326_ANA_PWR_LP_DAC			0x04
+#define ES8326_ANA_PWR_PDN_VRP			0x08
+#define ES8326_ANA_PWR_PDN_DACVREFGEN		0x10
+#define ES8326_ANA_PWR_PDN_ADCVREFGEN		0x20
+#define ES8326_ANA_PWR_PDN_IBIASGEN		0x40
+#define ES8326_ANA_PWR_PDN_ANA			0x80
+
+/* ES8326_PGA_PWR */
+#define ES8326_PGA_PWR_PDN_PGA			0x08
+#define ES8326_PGA_PWR_PDN_MOD			0x10
+#define ES8326_PGA_PWR_MODTOP_RST		0x20
+
+/* ES8326_VMIDSEL */
+#define ES8326_VMIDSEL_POWER_DOWN		0x00
+#define ES8326_VMIDSEL_NORMAL			0x02
+
+/* ES8326_PGAGAIN */
+#define ES8326_PGAGAIN_MIC1SEL			0x10
+
+/* ES8326_HP_DRIVER */
+#define ES8326_HP_DRIVER_ENREFR_HP		0x01
+#define ES8326_HP_DRIVER_PDN_MASK		0x0e
+#define ES8326_HP_DRIVER_PDN_CPNLDO		0x02
+#define ES8326_HP_DRIVER_PDN_CPHP		0x04
+#define ES8326_HP_DRIVER_PDN_CP			0x08
+#define ES8326_HP_DRIVER_LP_MASK		0x70
+#define ES8326_HP_DRIVER_LP_CPNLDO		0x10
+#define ES8326_HP_DRIVER_LP_HPMIX		0x20
+#define ES8326_HP_DRIVER_LP_HP			0x40
+
+/* ES8326_HPJACK_POL */
+#define ES8326_HPJACK_POL_HP_TYPE_CTIA		0x03
+#define ES8326_HPJACK_POL_BUTTON_POL_ACTIVE_LOW	0x04
+#define ES8326_HPJACK_POL_HPJACK_POL_ACTIVE_LOW	0x08
+#define ES8326_HPJACK_POL_HPINSERT_SEL_PIN9	0x10
+
+/* ES8326_INT_SOURCE */
+#define ES8326_INT_SOURCE_BUTTON		0x04
+#define ES8326_INT_SOURCE_PIN9			0x08
+
+/* ES8326_PULLUP_CTL */
+#define ES8326_PULLUP_CTL_ADC34_OFF		0x02
+#define ES8326_PULLUP_CTL_ISO_VDDA		0x08
+#define ES8326_PULLUP_CTL_PULLUP_MASK		0xf0
+#define ES8326_PULLUP_CTL_PULLUP_SDINOUT	0x10
+#define ES8326_PULLUP_CTL_PULLUP_MCLK		0x20
+#define ES8326_PULLUP_CTL_PULLUP_LRCK		0x40
+#define ES8326_PULLUP_CTL_PULLUP_BCLK		0x80
+
+/* ES8326_HP_DETECT */
+#define ES8326_HP_DETECT_GM_NOT_SHORTED		0x01
+#define ES8326_HP_DETECT_NOT_INSERTED		0x02
+
+#endif
diff --git a/sound/soc/intel/boards/Kconfig b/sound/soc/intel/boards/Kconfig
index a5b70ad98424..5c4edc396fba 100644
--- a/sound/soc/intel/boards/Kconfig
+++ b/sound/soc/intel/boards/Kconfig
@@ -517,6 +517,7 @@ config SND_SOC_INTEL_SOF_ES8336_MACH
 	depends on MFD_INTEL_LPSS || COMPILE_TEST
 	depends on SND_HDA_CODEC_HDMI && SND_SOC_SOF_HDA_AUDIO_CODEC
 	select SND_SOC_ES8316
+	select SND_SOC_ES8326
 	select SND_SOC_DMIC
 	help
 	   This adds support for ASoC machine driver for SOF platforms
diff --git a/sound/soc/intel/boards/sof_es8336.c b/sound/soc/intel/boards/sof_es8336.c
index 7966a61b22c8..65304e6d3b0e 100644
--- a/sound/soc/intel/boards/sof_es8336.c
+++ b/sound/soc/intel/boards/sof_es8336.c
@@ -514,6 +514,12 @@ static int sof_es8336_probe(struct platform_device *pdev)
 	if (ret)
 		return ret;
 
+	card->components = devm_kasprintf(dev, GFP_KERNEL, "spk:es83%d6",
+					  strstr(codec_name, "ESSX8326")
+					  ? 2 : 1);
+	if (!card->components)
+		return -ENOMEM;
+
 	/* get speaker enable GPIO */
 	codec_dev = bus_find_device_by_name(&i2c_bus_type, NULL, codec_name);
 	if (!codec_dev)
diff --git a/sound/soc/intel/common/soc-acpi-intel-jsl-match.c b/sound/soc/intel/common/soc-acpi-intel-jsl-match.c
index 87923bcf9488..db79dd89943d 100644
--- a/sound/soc/intel/common/soc-acpi-intel-jsl-match.c
+++ b/sound/soc/intel/common/soc-acpi-intel-jsl-match.c
@@ -81,6 +81,12 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_jsl_machines[] = {
 		.quirk_data = &mx98360a_spk,
 		.sof_tplg_filename = "sof-jsl-cs42l42-mx98360a.tplg",
 	},
+	{
+		.id = "ESSX8326",
+		.drv_name = "sof-essx8336",
+		.sof_fw_filename = "sof-jsl.ri",
+		.sof_tplg_filename = "sof-jsl-es8326.tplg",
+	},
 	{
 		.id = "ESSX8336",
 		.drv_name = "sof-essx8336",
diff --git a/sound/soc/intel/common/soc-acpi-intel-tgl-match.c b/sound/soc/intel/common/soc-acpi-intel-tgl-match.c
index c2c5337ed3b8..40fcc9697e59 100644
--- a/sound/soc/intel/common/soc-acpi-intel-tgl-match.c
+++ b/sound/soc/intel/common/soc-acpi-intel-tgl-match.c
@@ -383,6 +383,12 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_tgl_machines[] = {
 		.sof_fw_filename = "sof-tgl.ri",
 		.sof_tplg_filename = "sof-tgl-rt1011-rt5682.tplg",
 	},
+	{
+		.id = "ESSX8326",
+		.drv_name = "sof-essx8336",
+		.sof_fw_filename = "sof-tgl.ri",
+		.sof_tplg_filename = "sof-tgl-es8326.tplg",
+	},
 	{
 		.id = "ESSX8336",
 		.drv_name = "sof-essx8336",
-- 
2.33.0



^ permalink raw reply	[flat|nested] 28+ messages in thread

* [d-kernel] [PATCH v2 6/9] ALSA: intel-dspconfig: add ES8336 support for CNL
  2022-04-07 11:15         ` [d-kernel] [PATCH v2 1/9] ASoC: Intel: add machine driver for SOF+ES8336 nickel
                             ` (3 preceding siblings ...)
  2022-04-07 11:15           ` [d-kernel] [PATCH v2 5/9] ASoC: codec: es8326: New codec driver nickel
@ 2022-04-07 11:15           ` nickel
  2022-04-07 11:15           ` [d-kernel] [PATCH v2 7/9] ASoC: Intel: soc-acpi: add ESSX8336 support on Cannon Lake machines nickel
                             ` (3 subsequent siblings)
  8 siblings, 0 replies; 28+ messages in thread
From: nickel @ 2022-04-07 11:15 UTC (permalink / raw)
  To: devel-kernel; +Cc: Pierre-Louis Bossart

From: Nikolai Kostrigin <nickel@altlinux.org>

We're missing this check for the CNL PCI id

Reported-by: Nikolai Kostrigin <nickel@altlinux.org>
Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Signed-off-by: Nikolai Kostrigin <nickel@altlinux.org>
---
 sound/hda/intel-dsp-config.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/sound/hda/intel-dsp-config.c b/sound/hda/intel-dsp-config.c
index 9ef023882ae0..7ca5124c13e9 100644
--- a/sound/hda/intel-dsp-config.c
+++ b/sound/hda/intel-dsp-config.c
@@ -193,6 +193,11 @@ static const struct config_entry config_table[] = {
 			{}
 		}
 	},
+	{
+		.flags = FLAG_SOF,
+		.device = 0x09dc8,
+		.codec_hid = "ESSX8336",
+	},
 	{
 		.flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE,
 		.device = 0x9dc8,
-- 
2.33.0



^ permalink raw reply	[flat|nested] 28+ messages in thread

* [d-kernel] [PATCH v2 7/9] ASoC: Intel: soc-acpi: add ESSX8336 support on Cannon Lake machines
  2022-04-07 11:15         ` [d-kernel] [PATCH v2 1/9] ASoC: Intel: add machine driver for SOF+ES8336 nickel
                             ` (4 preceding siblings ...)
  2022-04-07 11:15           ` [d-kernel] [PATCH v2 6/9] ALSA: intel-dspconfig: add ES8336 support for CNL nickel
@ 2022-04-07 11:15           ` nickel
  2022-04-07 11:15           ` [d-kernel] [PATCH v2 8/9] config: CONFIG_SND_SOC_INTEL_SOF_ES8336_MACH=m nickel
                             ` (2 subsequent siblings)
  8 siblings, 0 replies; 28+ messages in thread
From: nickel @ 2022-04-07 11:15 UTC (permalink / raw)
  To: devel-kernel

From: Nikolai Kostrigin <nickel@altlinux.org>

Signed-off-by: Nikolai Kostrigin <nickel@altlinux.org>
---
 sound/soc/intel/common/soc-acpi-intel-cnl-match.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/sound/soc/intel/common/soc-acpi-intel-cnl-match.c b/sound/soc/intel/common/soc-acpi-intel-cnl-match.c
index 94b650767e11..ef2686e9bc3c 100644
--- a/sound/soc/intel/common/soc-acpi-intel-cnl-match.c
+++ b/sound/soc/intel/common/soc-acpi-intel-cnl-match.c
@@ -24,6 +24,13 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_cnl_machines[] = {
 		.sof_fw_filename = "sof-cnl.ri",
 		.sof_tplg_filename = "sof-cnl-rt274.tplg",
 	},
+	{
+		.id = "ESSX8336",
+		.drv_name = "sof-essx8336",
+		.sof_fw_filename = "sof-cnl.ri",
+		/* cnl and cml are identical */
+		.sof_tplg_filename = "sof-cml-es8336-ssp0.tplg",
+	},
 	{},
 };
 EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_cnl_machines);
-- 
2.33.0



^ permalink raw reply	[flat|nested] 28+ messages in thread

* [d-kernel] [PATCH v2 8/9] config: CONFIG_SND_SOC_INTEL_SOF_ES8336_MACH=m
  2022-04-07 11:15         ` [d-kernel] [PATCH v2 1/9] ASoC: Intel: add machine driver for SOF+ES8336 nickel
                             ` (5 preceding siblings ...)
  2022-04-07 11:15           ` [d-kernel] [PATCH v2 7/9] ASoC: Intel: soc-acpi: add ESSX8336 support on Cannon Lake machines nickel
@ 2022-04-07 11:15           ` nickel
  2022-04-07 11:15           ` [d-kernel] [PATCH v2 9/9] ASoC: Intel: sof_es8336: add DMI info based pa-enable lookup quirk for CNL-LP models nickel
  2022-04-07 19:32           ` [d-kernel] [PATCH v2 1/9] ASoC: Intel: add machine driver for SOF+ES8336 Vitaly Chikunov
  8 siblings, 0 replies; 28+ messages in thread
From: nickel @ 2022-04-07 11:15 UTC (permalink / raw)
  To: devel-kernel

From: Nikolai Kostrigin <nickel@altlinux.org>

Signed-off-by: Nikolai Kostrigin <nickel@altlinux.org>
---
 config | 1 +
 1 file changed, 1 insertion(+)

diff --git a/config b/config
index a55474de6623..7ac421c1530b 100644
--- a/config
+++ b/config
@@ -6890,6 +6890,7 @@ CONFIG_SND_SOC_INTEL_CHT_BSW_NAU8824_MACH=m
 CONFIG_SND_SOC_INTEL_BYT_CHT_CX2072X_MACH=m
 CONFIG_SND_SOC_INTEL_BYT_CHT_DA7213_MACH=m
 CONFIG_SND_SOC_INTEL_BYT_CHT_ES8316_MACH=m
+CONFIG_SND_SOC_INTEL_SOF_ES8336_MACH=m
 CONFIG_SND_SOC_INTEL_BYT_CHT_NOCODEC_MACH=m
 CONFIG_SND_SOC_INTEL_SKL_RT286_MACH=m
 CONFIG_SND_SOC_INTEL_SKL_NAU88L25_SSM4567_MACH=m
-- 
2.33.0



^ permalink raw reply	[flat|nested] 28+ messages in thread

* [d-kernel] [PATCH v2 9/9] ASoC: Intel: sof_es8336: add DMI info based pa-enable lookup quirk for CNL-LP models
  2022-04-07 11:15         ` [d-kernel] [PATCH v2 1/9] ASoC: Intel: add machine driver for SOF+ES8336 nickel
                             ` (6 preceding siblings ...)
  2022-04-07 11:15           ` [d-kernel] [PATCH v2 8/9] config: CONFIG_SND_SOC_INTEL_SOF_ES8336_MACH=m nickel
@ 2022-04-07 11:15           ` nickel
  2022-04-07 19:32           ` [d-kernel] [PATCH v2 1/9] ASoC: Intel: add machine driver for SOF+ES8336 Vitaly Chikunov
  8 siblings, 0 replies; 28+ messages in thread
From: nickel @ 2022-04-07 11:15 UTC (permalink / raw)
  To: devel-kernel

From: Nikolai Kostrigin <nickel@altlinux.org>

Some CNL-LP based laptops as Depo, ICL, Graviton have GPIO to control speaker power
amplifier wich is not discoverable via standard or quirked ACPI methods.

Use DMI quirk to address the issue.
Based on driver by <zhuning@everest-semi.com>

Link: https://github.com/thesofproject/linux/issues/3412

Signed-off-by: Nikolai Kostrigin <nickel@altlinux.org>
---
 sound/soc/intel/boards/sof_es8336.c | 73 +++++++++++++++++++++++++----
 1 file changed, 64 insertions(+), 9 deletions(-)

diff --git a/sound/soc/intel/boards/sof_es8336.c b/sound/soc/intel/boards/sof_es8336.c
index 65304e6d3b0e..373b8e7f7232 100644
--- a/sound/soc/intel/boards/sof_es8336.c
+++ b/sound/soc/intel/boards/sof_es8336.c
@@ -34,6 +34,8 @@ static int quirk_override = -1;
 module_param_named(quirk, quirk_override, int, 0444);
 MODULE_PARM_DESC(quirk, "Board-specific quirk override");
 
+static int quirk_pa_enable = -1;
+
 /* jd-inv + terminating entry */
 #define SOF_ES8336_PROPS_MAX	2
 
@@ -231,10 +233,25 @@ static int sof_es8336_quirk_cb(const struct dmi_system_id *id)
 	if (quirk & SOF_ES8336_TGL_GPIO_QUIRK)
 		gpio_mapping = quirk_acpi_es8336_gpios;
 
+	if (strcmp(id->ident, "pa-enable ACPI deviant") == 0) {
+		if (quirk_pa_enable < 0) quirk_pa_enable = 1;
+		else quirk_pa_enable++;
+	}
+
 	return 1;
 }
 
 static const struct dmi_system_id sof_es8336_quirk_table[] = {
+	{
+		.callback = sof_es8336_quirk_cb,
+		.ident = "pa-enable ACPI deviant",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "3Logic Group"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Graviton N15i-K2"),
+		},
+		.driver_data = (void *)(SOF_ES8336_SSP_CODEC(0) |
+					SOF_ES8336_TGL_GPIO_QUIRK)
+	},
 	{
 		.callback = sof_es8336_quirk_cb,
 		.matches = {
@@ -243,6 +260,16 @@ static const struct dmi_system_id sof_es8336_quirk_table[] = {
 		},
 		.driver_data = (void *)SOF_ES8336_SSP_CODEC(2)
 	},
+	{
+		.callback = sof_es8336_quirk_cb,
+		.ident = "pa-enable ACPI deviant",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "DEPO Computers"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "DPC156"),
+		},
+		.driver_data = (void *)(SOF_ES8336_SSP_CODEC(0) |
+					SOF_ES8336_TGL_GPIO_QUIRK)
+	},
 	{
 		.callback = sof_es8336_quirk_cb,
 		.matches = {
@@ -456,6 +483,18 @@ static struct snd_soc_dai_link *sof_card_dai_links_create(struct device *dev,
  /* i2c-<HID>:00 with HID being 8 chars */
 static char codec_name[SND_ACPI_I2C_ID_LEN];
 
+/*
+* Using the ACPI device name is not very nice, but hopefully makes sense for now
+*/
+
+static struct gpiod_lookup_table cml_lp_based_gpios_table = {
+	/* .dev_id is set during probe */
+	.table = {
+		GPIO_LOOKUP("INT34BB:00", 264, "PA_ENABLE", GPIO_ACTIVE_LOW), //cnl kb
+		 { },
+	},
+};
+
 static int sof_es8336_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
@@ -507,6 +546,9 @@ static int sof_es8336_probe(struct platform_device *pdev)
 			 "i2c-%s", acpi_dev_name(adev));
 		put_device(&adev->dev);
 		dai_links[0].codecs->name = codec_name;
+	} else {
+		dev_err(dev, "Error cannot find '%s' dev\n", mach->id);
+		return -ENXIO;
 	}
 
 	ret = snd_soc_fixup_dai_links_platform_name(&sof_es8336_card,
@@ -537,16 +579,29 @@ static int sof_es8336_probe(struct platform_device *pdev)
 		}
 	}
 
-	ret = devm_acpi_dev_add_driver_gpios(codec_dev, gpio_mapping);
-	if (ret)
-		dev_warn(codec_dev, "unable to add GPIO mapping table\n");
+	if (quirk_pa_enable < 0) {
+		ret = devm_acpi_dev_add_driver_gpios(codec_dev, gpio_mapping);
+		if (ret)
+			dev_warn(codec_dev, "unable to add GPIO mapping table\n");
 
-	priv->gpio_pa = gpiod_get(codec_dev, "pa-enable", GPIOD_OUT_LOW);
-	if (IS_ERR(priv->gpio_pa)) {
-		ret = PTR_ERR(priv->gpio_pa);
-		dev_err(codec_dev, "%s, could not get pa-enable: %d\n",
-			__func__, ret);
-		goto err;
+		priv->gpio_pa = gpiod_get_optional(codec_dev, "pa-enable", GPIOD_OUT_LOW);
+		if (IS_ERR(priv->gpio_pa)) {
+			ret = dev_err_probe(dev, PTR_ERR(priv->gpio_pa),
+						"could not get pa-enable GPIO\n");
+			goto err;
+		}
+	}
+	else {
+		cml_lp_based_gpios_table.dev_id = dev_name(codec_dev);
+		gpiod_add_lookup_table(&cml_lp_based_gpios_table);
+
+		priv->gpio_pa = devm_gpiod_get(codec_dev, "PA_ENABLE", GPIOD_OUT_LOW);
+		if (IS_ERR(priv->gpio_pa)) {
+			ret = PTR_ERR(priv->gpio_pa);
+			dev_err(codec_dev, "%s, could not get PA_ENABLE: %d\n",
+				__func__, ret);
+			goto err;
+		}
 	}
 
 	priv->codec_dev = codec_dev;
-- 
2.33.0



^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [d-kernel] [PATCH v2 1/9] ASoC: Intel: add machine driver for SOF+ES8336
  2022-04-07 11:15         ` [d-kernel] [PATCH v2 1/9] ASoC: Intel: add machine driver for SOF+ES8336 nickel
                             ` (7 preceding siblings ...)
  2022-04-07 11:15           ` [d-kernel] [PATCH v2 9/9] ASoC: Intel: sof_es8336: add DMI info based pa-enable lookup quirk for CNL-LP models nickel
@ 2022-04-07 19:32           ` Vitaly Chikunov
  2022-04-12 14:34             ` Nikolai Kostrigin
  8 siblings, 1 reply; 28+ messages in thread
From: Vitaly Chikunov @ 2022-04-07 19:32 UTC (permalink / raw)
  To: ALT Linux kernel packages development

Спасибо. 

Pls, шлите в следующий раз патчсет без In-Reply-To, а просто как новый
птчсет (v2).

  Explicit In-Reply-To headers
  ----------------------------

  [ ... ]          However, for a multi-patch series, it is generally
  best to avoid using In-Reply-To: to link to older versions of the
  series.  This way multiple versions of the patch don't become an
  unmanageable forest of references in email clients.  If a link is
  helpful, you can use the https://lore.kernel.org/ redirector (e.g., in
  the cover email text) to link to an earlier version of the patch series.



On Thu, Apr 07, 2022 at 02:15:09PM +0300, nickel@altlinux.org wrote:
> From: Vasily Vinogradov <v.vinogradov@aq.ru>
> 
> Backport from 5.17
> Based on upstream commit a164137ce91a95a1a5e2f2ca381741aa5ba14b63
> 
> Link: https://lore.kernel.org/r/20211004213512.220836-4-pierre-louis.bossart@linux.intel.com
> Signed-off-by: Vasily Vinogradov <v.vinogradov@aq.ru>
> Signed-off-by: Nikolai Kostrigin <nickel@altlinux.org>
> ---
>  sound/hda/intel-dsp-config.c                  |  24 +-
>  sound/soc/codecs/es8316.c                     |   1 +
>  sound/soc/intel/boards/Kconfig                |  13 +
>  sound/soc/intel/boards/Makefile               |   2 +
>  sound/soc/intel/boards/sof_es8336.c           | 569 ++++++++++++++++++
>  .../intel/common/soc-acpi-intel-bxt-match.c   |   6 +
>  .../intel/common/soc-acpi-intel-cml-match.c   |   6 +
>  .../intel/common/soc-acpi-intel-glk-match.c   |   7 +-
>  .../intel/common/soc-acpi-intel-jsl-match.c   |   6 +
>  .../intel/common/soc-acpi-intel-tgl-match.c   |   6 +
>  10 files changed, 627 insertions(+), 13 deletions(-)
>  create mode 100644 sound/soc/intel/boards/sof_es8336.c


^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [d-kernel] [PATCH v2 1/9] ASoC: Intel: add machine driver for SOF+ES8336
  2022-04-07 19:32           ` [d-kernel] [PATCH v2 1/9] ASoC: Intel: add machine driver for SOF+ES8336 Vitaly Chikunov
@ 2022-04-12 14:34             ` Nikolai Kostrigin
  2022-04-14  8:43               ` Vitaly Chikunov
  0 siblings, 1 reply; 28+ messages in thread
From: Nikolai Kostrigin @ 2022-04-12 14:34 UTC (permalink / raw)
  To: devel-kernel



07.04.2022 22:32, Vitaly Chikunov пишет:
> Спасибо.
> 
> Pls, шлите в следующий раз патчсет без In-Reply-To, а просто как новый
> птчсет (v2).
> 


Хорошо.

На всякий случай уточню, т.к. 0й патч оторвался в другой тред почему-то 
[1] : все эти патчи только для ядер 5.15 (un-def в p10)

[d-kernel] [PATCH 0/9] *** backport support for ES83x6 codec in I2S mode 
for CML/CNL platforms to 5.15.x ***

[1] https://lists.altlinux.org/pipermail/devel-kernel/2022-April/007457.html

>    Explicit In-Reply-To headers
>    ----------------------------
> 
>    [ ... ]          However, for a multi-patch series, it is generally
>    best to avoid using In-Reply-To: to link to older versions of the
>    series.  This way multiple versions of the patch don't become an
>    unmanageable forest of references in email clients.  If a link is
>    helpful, you can use the https://lore.kernel.org/ redirector (e.g., in
>    the cover email text) to link to an earlier version of the patch series.
> 
> 
> 
> On Thu, Apr 07, 2022 at 02:15:09PM +0300, nickel@altlinux.org wrote:
>> From: Vasily Vinogradov <v.vinogradov@aq.ru>
>>
>> Backport from 5.17
>> Based on upstream commit a164137ce91a95a1a5e2f2ca381741aa5ba14b63
>>
>> Link: https://lore.kernel.org/r/20211004213512.220836-4-pierre-louis.bossart@linux.intel.com
>> Signed-off-by: Vasily Vinogradov <v.vinogradov@aq.ru>
>> Signed-off-by: Nikolai Kostrigin <nickel@altlinux.org>
>> ---
>>   sound/hda/intel-dsp-config.c                  |  24 +-
>>   sound/soc/codecs/es8316.c                     |   1 +
>>   sound/soc/intel/boards/Kconfig                |  13 +
>>   sound/soc/intel/boards/Makefile               |   2 +
>>   sound/soc/intel/boards/sof_es8336.c           | 569 ++++++++++++++++++
>>   .../intel/common/soc-acpi-intel-bxt-match.c   |   6 +
>>   .../intel/common/soc-acpi-intel-cml-match.c   |   6 +
>>   .../intel/common/soc-acpi-intel-glk-match.c   |   7 +-
>>   .../intel/common/soc-acpi-intel-jsl-match.c   |   6 +
>>   .../intel/common/soc-acpi-intel-tgl-match.c   |   6 +
>>   10 files changed, 627 insertions(+), 13 deletions(-)
>>   create mode 100644 sound/soc/intel/boards/sof_es8336.c
> _______________________________________________
> devel-kernel mailing list
> devel-kernel@lists.altlinux.org
> https://lists.altlinux.org/mailman/listinfo/devel-kernel

-- 
Best regards,
Nikolai Kostrigin


^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [d-kernel] [PATCH v2 1/9] ASoC: Intel: add machine driver for SOF+ES8336
  2022-04-12 14:34             ` Nikolai Kostrigin
@ 2022-04-14  8:43               ` Vitaly Chikunov
  2022-04-14  8:48                 ` Антон Мидюков
  0 siblings, 1 reply; 28+ messages in thread
From: Vitaly Chikunov @ 2022-04-14  8:43 UTC (permalink / raw)
  To: ALT Linux kernel packages development

Nikolai,

On Tue, Apr 12, 2022 at 05:34:35PM +0300, Nikolai Kostrigin wrote:
> 07.04.2022 22:32, Vitaly Chikunov пишет:
> > 
> > Pls, шлите в следующий раз патчсет без In-Reply-To, а просто как новый
> > птчсет (v2).
> 
> На всякий случай уточню, т.к. 0й патч оторвался в другой тред почему-то [1]
> : все эти патчи только для ядер 5.15 (un-def в p10)

Ну это не уточнение на всякий случай, а значит что я принял их не в тот
бранч, так как в Сизифе тоже есть 5.15. Хорошо, в Сизифе сделаю им
revert и переделаю un-def/p10.

> 
> [d-kernel] [PATCH 0/9] *** backport support for ES83x6 codec in I2S mode for
> CML/CNL platforms to 5.15.x ***
> 
> [1] https://lists.altlinux.org/pipermail/devel-kernel/2022-April/007457.html


^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [d-kernel] [PATCH v2 1/9] ASoC: Intel: add machine driver for SOF+ES8336
  2022-04-14  8:43               ` Vitaly Chikunov
@ 2022-04-14  8:48                 ` Антон Мидюков
  2022-04-14  8:52                   ` Vitaly Chikunov
  2022-04-14  8:55                   ` Nikolai Kostrigin
  0 siblings, 2 replies; 28+ messages in thread
From: Антон Мидюков @ 2022-04-14  8:48 UTC (permalink / raw)
  To: devel-kernel

14.04.2022 15:43, Vitaly Chikunov пишет:
> Nikolai,
> 
> On Tue, Apr 12, 2022 at 05:34:35PM +0300, Nikolai Kostrigin wrote:
>> 07.04.2022 22:32, Vitaly Chikunov пишет:
>>>
>>> Pls, шлите в следующий раз патчсет без In-Reply-To, а просто как новый
>>> птчсет (v2).
>>
>> На всякий случай уточню, т.к. 0й патч оторвался в другой тред почему-то [1]
>> : все эти патчи только для ядер 5.15 (un-def в p10)
> 
> Ну это не уточнение на всякий случай, а значит что я принял их не в тот
> бранч, так как в Сизифе тоже есть 5.15. Хорошо, в Сизифе сделаю им
> revert и переделаю un-def/p10.
> 

Виталий, предлагаю не делать Revert. Написано же для ядер 5.15.
В былые времена un-def/p10 = std-def/Sisyphus и это не требовало уточнения.
К этому многие привыкли.

>>
>> [d-kernel] [PATCH 0/9] *** backport support for ES83x6 codec in I2S mode for
>> CML/CNL platforms to 5.15.x ***
>>
>> [1] https://lists.altlinux.org/pipermail/devel-kernel/2022-April/007457.html
> _______________________________________________
> devel-kernel mailing list
> devel-kernel@lists.altlinux.org
> https://lists.altlinux.org/mailman/listinfo/devel-kernel


-- 
С уважением, Антон Мидюков <antohami@basealt.ru>


^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [d-kernel] [PATCH v2 1/9] ASoC: Intel: add machine driver for SOF+ES8336
  2022-04-14  8:48                 ` Антон Мидюков
@ 2022-04-14  8:52                   ` Vitaly Chikunov
  2022-04-14  8:55                   ` Nikolai Kostrigin
  1 sibling, 0 replies; 28+ messages in thread
From: Vitaly Chikunov @ 2022-04-14  8:52 UTC (permalink / raw)
  To: ALT Linux kernel packages development

Антон,

On Thu, Apr 14, 2022 at 03:48:47PM +0700, Антон Мидюков wrote:
> > 
> > On Tue, Apr 12, 2022 at 05:34:35PM +0300, Nikolai Kostrigin wrote:
> >> 07.04.2022 22:32, Vitaly Chikunov пишет:
> >>> Pls, шлите в следующий раз патчсет без In-Reply-To, а просто как новый
> >>> птчсет (v2).
> >>
> >> На всякий случай уточню, т.к. 0й патч оторвался в другой тред почему-то [1]
> >> : все эти патчи только для ядер 5.15 (un-def в p10)
> > 
> > Ну это не уточнение на всякий случай, а значит что я принял их не в тот
> > бранч, так как в Сизифе тоже есть 5.15. Хорошо, в Сизифе сделаю им
> > revert и переделаю un-def/p10.
> > 
> 
> Виталий, предлагаю не делать Revert. Написано же для ядер 5.15.
> В былые времена un-def/p10 = std-def/Sisyphus и это не требовало уточнения.
> К этому многие привыкли.

Хорошо.

> 
> >>
> >> [d-kernel] [PATCH 0/9] *** backport support for ES83x6 codec in I2S mode for
> >> CML/CNL platforms to 5.15.x ***
> >>
> >> [1] https://lists.altlinux.org/pipermail/devel-kernel/2022-April/007457.html
> > _______________________________________________
> > devel-kernel mailing list
> > devel-kernel@lists.altlinux.org
> > https://lists.altlinux.org/mailman/listinfo/devel-kernel
> 
> 
> -- 
> С уважением, Антон Мидюков <antohami@basealt.ru>
> _______________________________________________
> devel-kernel mailing list
> devel-kernel@lists.altlinux.org
> https://lists.altlinux.org/mailman/listinfo/devel-kernel


^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [d-kernel] [PATCH v2 1/9] ASoC: Intel: add machine driver for SOF+ES8336
  2022-04-14  8:48                 ` Антон Мидюков
  2022-04-14  8:52                   ` Vitaly Chikunov
@ 2022-04-14  8:55                   ` Nikolai Kostrigin
  1 sibling, 0 replies; 28+ messages in thread
From: Nikolai Kostrigin @ 2022-04-14  8:55 UTC (permalink / raw)
  To: devel-kernel



14.04.2022 11:48, Антон Мидюков пишет:
> 14.04.2022 15:43, Vitaly Chikunov пишет:
>> Nikolai,
>>
>> On Tue, Apr 12, 2022 at 05:34:35PM +0300, Nikolai Kostrigin wrote:
>>> 07.04.2022 22:32, Vitaly Chikunov пишет:
>>>>
>>>> Pls, шлите в следующий раз патчсет без In-Reply-To, а просто как новый
>>>> птчсет (v2).
>>>
>>> На всякий случай уточню, т.к. 0й патч оторвался в другой тред почему-то [1]
>>> : все эти патчи только для ядер 5.15 (un-def в p10)
>>
>> Ну это не уточнение на всякий случай, а значит что я принял их не в тот
>> бранч, так как в Сизифе тоже есть 5.15. Хорошо, в Сизифе сделаю им
>> revert и переделаю un-def/p10.
>>
> 
> Виталий, предлагаю не делать Revert. Написано же для ядер 5.15.
> В былые времена un-def/p10 = std-def/Sisyphus и это не требовало уточнения.
> К этому многие привыкли.
> 

Поддерживаю. Если уже сделано, не стоит отрывать, особенно с учетом 
комментария Антона.
>>>
>>> [d-kernel] [PATCH 0/9] *** backport support for ES83x6 codec in I2S mode for
>>> CML/CNL platforms to 5.15.x ***
>>>
>>> [1] https://lists.altlinux.org/pipermail/devel-kernel/2022-April/007457.html
>> _______________________________________________
>> devel-kernel mailing list
>> devel-kernel@lists.altlinux.org
>> https://lists.altlinux.org/mailman/listinfo/devel-kernel
> 
> 

-- 
Best regards,
Nikolai Kostrigin


^ permalink raw reply	[flat|nested] 28+ messages in thread

end of thread, other threads:[~2022-04-14  8:55 UTC | newest]

Thread overview: 28+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-04-04  6:28 [d-kernel] [PATCH 0/9] *** backport support for ES83x6 codec in I2S mode for CML/CNL platforms to 5.15.x *** nickel
2022-04-04  6:28 ` [d-kernel] (no subject) nickel
2022-04-04  6:28   ` [d-kernel] [PATCH 1/9] commit 0b220578c2aab3d5ac6b693117e8c5d22e8c2b34 nickel
2022-04-04 14:48     ` Vitaly Chikunov
2022-04-04 15:16       ` Nikolai Kostrigin
2022-04-07 11:15         ` [d-kernel] [PATCH v2 1/9] ASoC: Intel: add machine driver for SOF+ES8336 nickel
2022-04-07 11:15           ` [d-kernel] [PATCH v2 2/9] ASoC: Intel: sof_es8336: Add quirk for inverted jack detect nickel
2022-04-07 11:15           ` [d-kernel] [PATCH v2 3/9] ASoC: es8316: Add power management nickel
2022-04-07 11:15           ` [d-kernel] [PATCH v2 4/9] ASoC: es8316: Use increased GPIO debounce time nickel
2022-04-07 11:15           ` [d-kernel] [PATCH v2 5/9] ASoC: codec: es8326: New codec driver nickel
2022-04-07 11:15           ` [d-kernel] [PATCH v2 6/9] ALSA: intel-dspconfig: add ES8336 support for CNL nickel
2022-04-07 11:15           ` [d-kernel] [PATCH v2 7/9] ASoC: Intel: soc-acpi: add ESSX8336 support on Cannon Lake machines nickel
2022-04-07 11:15           ` [d-kernel] [PATCH v2 8/9] config: CONFIG_SND_SOC_INTEL_SOF_ES8336_MACH=m nickel
2022-04-07 11:15           ` [d-kernel] [PATCH v2 9/9] ASoC: Intel: sof_es8336: add DMI info based pa-enable lookup quirk for CNL-LP models nickel
2022-04-07 19:32           ` [d-kernel] [PATCH v2 1/9] ASoC: Intel: add machine driver for SOF+ES8336 Vitaly Chikunov
2022-04-12 14:34             ` Nikolai Kostrigin
2022-04-14  8:43               ` Vitaly Chikunov
2022-04-14  8:48                 ` Антон Мидюков
2022-04-14  8:52                   ` Vitaly Chikunov
2022-04-14  8:55                   ` Nikolai Kostrigin
2022-04-04  6:28   ` [d-kernel] [PATCH 2/9] commit 79b5808491cf152b808c51fecdafb221fa270cf1 nickel
2022-04-04  6:28   ` [d-kernel] [PATCH 3/9] commit 8143959d503dd6b3c8b9802cee0f1eba82e8d844 nickel
2022-04-04  6:28   ` [d-kernel] [PATCH 4/9] commit 796f9b0189299a221d4c822be216165dd2371852 nickel
2022-04-04  6:28   ` [d-kernel] [PATCH 5/9] commit f6a1611f744dcdd55c5adaf02f193083286dac34 nickel
2022-04-04  6:28   ` [d-kernel] [PATCH 6/9] ALSA: intel-dspconfig: add ES8336 support for CNL nickel
2022-04-04  6:28   ` [d-kernel] [PATCH 7/9] ASoC: Intel: soc-acpi: add ESSX8336 support on Cannon Lake machines nickel
2022-04-04  6:28   ` [d-kernel] [PATCH 8/9] config: CONFIG_SND_SOC_INTEL_SOF_ES8336_MACH=m nickel
2022-04-04  6:28   ` [d-kernel] [PATCH 9/9] ASoC: Intel: sof_es8336: add DMI info based pa-enable lookup quirk for CNL-LP models nickel

ALT Linux kernel packages development

This inbox may be cloned and mirrored by anyone:

	git clone --mirror http://lore.altlinux.org/devel-kernel/0 devel-kernel/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 devel-kernel devel-kernel/ http://lore.altlinux.org/devel-kernel \
		devel-kernel@altlinux.org devel-kernel@altlinux.ru devel-kernel@altlinux.com
	public-inbox-index devel-kernel

Example config snippet for mirrors.
Newsgroup available over NNTP:
	nntp://lore.altlinux.org/org.altlinux.lists.devel-kernel


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git