diff mbox series

[2/2] ASoC: Intel: Add machine driver for CX2072X on BYT/CHT platforms

Message ID 20190423141336.12568-3-tiwai@suse.de (mailing list archive)
State New, archived
Headers show
Series ASoC: CX2072X codec support (revised) | expand

Commit Message

Takashi Iwai April 23, 2019, 2:13 p.m. UTC
This is an implementation of a machine driver needed for Conexant
CX2072X codec on Intel Baytrail and Cherrytrail platforms.  The
current patch is based on the initial work by Pierre-Louis Bossart and
the other Intel machine drivers.

The jack detection support (driven via the standard GPIO) was added on
top of the original work.

No SOF support yet, so the corresponding entries are commented out.

Tested with ASUS E200HA laptop.

Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=115531
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/soc/intel/boards/Kconfig                    |  11 +
 sound/soc/intel/boards/Makefile                   |   2 +
 sound/soc/intel/boards/bytcht_cx2072x.c           | 285 ++++++++++++++++++++++
 sound/soc/intel/common/soc-acpi-intel-byt-match.c |   8 +
 sound/soc/intel/common/soc-acpi-intel-cht-match.c |   8 +
 5 files changed, 314 insertions(+)
 create mode 100644 sound/soc/intel/boards/bytcht_cx2072x.c

Comments

Pierre-Louis Bossart April 23, 2019, 7:20 p.m. UTC | #1
On 4/23/19 9:13 AM, Takashi Iwai wrote:
> This is an implementation of a machine driver needed for Conexant
> CX2072X codec on Intel Baytrail and Cherrytrail platforms.  The
> current patch is based on the initial work by Pierre-Louis Bossart and
> the other Intel machine drivers.
> 
> The jack detection support (driven via the standard GPIO) was added on
> top of the original work.
> 
> No SOF support yet, so the corresponding entries are commented out.

SOF support is trivial to add, can we help you here?


> +config SND_SOC_INTEL_BYT_CHT_CX2072X_MACH
> +	tristate "Baytrail & Cherrytrail with CX2072X codec"
> +	depends on X86_INTEL_LPSS && I2C && ACPI

Didn't Mark recently split this in two, with X86_INTEL_LPSS || COMPILE_TEST?

> +static int byt_cht_cx2072x_fixup(struct snd_soc_pcm_runtime *rtd,
> +				 struct snd_pcm_hw_params *params)
> +{
> +	struct snd_interval *rate =
> +		hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
> +	struct snd_interval *channels =
> +		hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
> +	int ret;
> +
> +	/* The DSP will covert the FE rate to 48k, stereo, 24bits */
> +	rate->min = rate->max = 48000;
> +	channels->min = channels->max = 2;
> +
> +	/* set SSP2 to 24-bit */
> +	params_set_format(params, SNDRV_PCM_FORMAT_S24_LE);
> +
> +	/*
> +	 * Default mode for SSP configuration is TDM 4 slot, override config
> +	 * with explicit setting to I2S 2ch 24-bit. The word length is set with
> +	 * dai_set_tdm_slot() since there is no other API exposed
> +	 */
> +	ret = snd_soc_dai_set_fmt(rtd->cpu_dai,
> +				SND_SOC_DAIFMT_I2S     |
> +				SND_SOC_DAIFMT_NB_NF   |
> +				SND_SOC_DAIFMT_CBS_CFS);
> +	if (ret < 0) {
> +		dev_err(rtd->dev, "can't set format to I2S, err %d\n", ret);
> +		return ret;
> +	}
> +
> +	ret = snd_soc_dai_set_tdm_slot(rtd->cpu_dai, 0x3, 0x3, 2, 24);
> +	if (ret < 0) {
> +		dev_err(rtd->dev, "can't set I2S config, err %d\n", ret);
> +		return ret;
> +	}
> +
> +	snd_soc_dai_set_bclk_ratio(rtd->codec_dai, 50);

that part would be problematic for SOF. IIRC we put all clock-related 
stuff in the init, and ignore the fixups to use topology-based 
information instead. If this call to _set_bclk_ratio can be moved to the 
init it's more future-proof. Is there a reason to do this here in the fixup?


> +static struct snd_soc_dai_link byt_cht_cx2072x_dais[] = {
> +	[MERR_DPCM_AUDIO] = {
> +		.name = "Audio Port",
> +		.stream_name = "Audio",
> +		.cpu_dai_name = "media-cpu-dai",
> +		.codec_dai_name = "snd-soc-dummy-dai",
> +		.codec_name = "snd-soc-dummy",
> +		.platform_name = "sst-mfld-platform",
> +		.nonatomic = true,
> +		.dynamic = 1,
> +		.dpcm_playback = 1,
> +		.dpcm_capture = 1,
> +		.ops = &byt_cht_cx2072x_aif1_ops,
> +	},
> +	[MERR_DPCM_DEEP_BUFFER] = {
> +		.name = "Deep-Buffer Audio Port",
> +		.stream_name = "Deep-Buffer Audio",
> +		.cpu_dai_name = "deepbuffer-cpu-dai",
> +		.codec_dai_name = "snd-soc-dummy-dai",
> +		.codec_name = "snd-soc-dummy",
> +		.platform_name = "sst-mfld-platform",
> +		.nonatomic = true,
> +		.dynamic = 1,
> +		.dpcm_playback = 1,
> +		.ops = &byt_cht_cx2072x_aif1_ops,
> +	},
> +	/* back ends */
> +	{
> +		.name = "SSP2-Codec",
> +		.id = 1,
> +		.cpu_dai_name = "ssp2-port",
> +		.platform_name = "sst-mfld-platform",
> +		.no_pcm = 1,
> +		.codec_dai_name = "cx2072x-hifi",
> +		.codec_name = "i2c-14F10720:00",
> +		.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
> +					      | SND_SOC_DAIFMT_CBS_CFS,
> +		.init = byt_cht_cx2072x_init,
> +		.be_hw_params_fixup = byt_cht_cx2072x_fixup,
> +		.nonatomic = true,

I can't recall if this .atomic is needed or not for back-ends.

> +	{
> +		.id = "14F10720",
> +		.drv_name = "bytcht_cx2072x",
> +		.fw_filename = "intel/fw_sst_0f28.bin",
> +		.board = "bytcht_cx2072x",
> +		/* .sof_fw_filename = "sof-byt.ri", */
> +		/* .sof_tplg_filename = "sof-byt-cx2072x.tplg", */
> +	},
>   #if IS_ENABLED(CONFIG_SND_SOC_INTEL_BYT_CHT_NOCODEC_MACH)
>   	/*
>   	 * This is always last in the table so that it is selected only when
> diff --git a/sound/soc/intel/common/soc-acpi-intel-cht-match.c b/sound/soc/intel/common/soc-acpi-intel-cht-match.c
> index deafd87cc764..69ecbb88c171 100644
> --- a/sound/soc/intel/common/soc-acpi-intel-cht-match.c
> +++ b/sound/soc/intel/common/soc-acpi-intel-cht-match.c
> @@ -169,6 +169,14 @@ struct snd_soc_acpi_mach  snd_soc_acpi_intel_cherrytrail_machines[] = {
>   		.sof_fw_filename = "sof-cht.ri",
>   		.sof_tplg_filename = "sof-cht-rt5651.tplg",
>   	},
> +	{
> +		.id = "14F10720",
> +		.drv_name = "bytcht_cx2072x",
> +		.fw_filename = "intel/fw_sst_22a8.bin",
> +		.board = "bytcht_cx2072x",
> +		/* .sof_fw_filename = "sof-cht.ri", */
> +		/* .sof_tplg_filename = "sof-cht-cx2072x.tplg", */
> +	},

I'd uncomment those two ACPI machine parts. There is not risk unless SOF 
is actually enabled.
Takashi Iwai April 23, 2019, 7:39 p.m. UTC | #2
On Tue, 23 Apr 2019 21:20:24 +0200,
Pierre-Louis Bossart wrote:
> 
> On 4/23/19 9:13 AM, Takashi Iwai wrote:
> > This is an implementation of a machine driver needed for Conexant
> > CX2072X codec on Intel Baytrail and Cherrytrail platforms.  The
> > current patch is based on the initial work by Pierre-Louis Bossart and
> > the other Intel machine drivers.
> >
> > The jack detection support (driven via the standard GPIO) was added on
> > top of the original work.
> >
> > No SOF support yet, so the corresponding entries are commented out.
> 
> SOF support is trivial to add, can we help you here?

I just had no time to take a deeper look at that direction, so it's a
thing I'd like to play at my next spare time.

> > +config SND_SOC_INTEL_BYT_CHT_CX2072X_MACH
> > +	tristate "Baytrail & Cherrytrail with CX2072X codec"
> > +	depends on X86_INTEL_LPSS && I2C && ACPI
> 
> Didn't Mark recently split this in two, with X86_INTEL_LPSS || COMPILE_TEST?

The entry I just copied, CONFIG_SND_SOC_INTEL_BYT_CHT_ES8316_MACH,
still has this style, so no, it doesn't seem applied.


> > +static int byt_cht_cx2072x_fixup(struct snd_soc_pcm_runtime *rtd,
> > +				 struct snd_pcm_hw_params *params)
> > +{
> > +	struct snd_interval *rate =
> > +		hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
> > +	struct snd_interval *channels =
> > +		hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
> > +	int ret;
> > +
> > +	/* The DSP will covert the FE rate to 48k, stereo, 24bits */
> > +	rate->min = rate->max = 48000;
> > +	channels->min = channels->max = 2;
> > +
> > +	/* set SSP2 to 24-bit */
> > +	params_set_format(params, SNDRV_PCM_FORMAT_S24_LE);
> > +
> > +	/*
> > +	 * Default mode for SSP configuration is TDM 4 slot, override config
> > +	 * with explicit setting to I2S 2ch 24-bit. The word length is set with
> > +	 * dai_set_tdm_slot() since there is no other API exposed
> > +	 */
> > +	ret = snd_soc_dai_set_fmt(rtd->cpu_dai,
> > +				SND_SOC_DAIFMT_I2S     |
> > +				SND_SOC_DAIFMT_NB_NF   |
> > +				SND_SOC_DAIFMT_CBS_CFS);
> > +	if (ret < 0) {
> > +		dev_err(rtd->dev, "can't set format to I2S, err %d\n", ret);
> > +		return ret;
> > +	}
> > +
> > +	ret = snd_soc_dai_set_tdm_slot(rtd->cpu_dai, 0x3, 0x3, 2, 24);
> > +	if (ret < 0) {
> > +		dev_err(rtd->dev, "can't set I2S config, err %d\n", ret);
> > +		return ret;
> > +	}
> > +
> > +	snd_soc_dai_set_bclk_ratio(rtd->codec_dai, 50);
> 
> that part would be problematic for SOF. IIRC we put all clock-related
> stuff in the init, and ignore the fixups to use topology-based
> information instead. If this call to _set_bclk_ratio can be moved to
> the init it's more future-proof. Is there a reason to do this here in
> the fixup?

No particular reason from my side.  I just took over your code ;)

That is, it'd be appreciated if you can give a fixup patch that can be
applied on top.


> > +static struct snd_soc_dai_link byt_cht_cx2072x_dais[] = {
> > +	[MERR_DPCM_AUDIO] = {
> > +		.name = "Audio Port",
> > +		.stream_name = "Audio",
> > +		.cpu_dai_name = "media-cpu-dai",
> > +		.codec_dai_name = "snd-soc-dummy-dai",
> > +		.codec_name = "snd-soc-dummy",
> > +		.platform_name = "sst-mfld-platform",
> > +		.nonatomic = true,
> > +		.dynamic = 1,
> > +		.dpcm_playback = 1,
> > +		.dpcm_capture = 1,
> > +		.ops = &byt_cht_cx2072x_aif1_ops,
> > +	},
> > +	[MERR_DPCM_DEEP_BUFFER] = {
> > +		.name = "Deep-Buffer Audio Port",
> > +		.stream_name = "Deep-Buffer Audio",
> > +		.cpu_dai_name = "deepbuffer-cpu-dai",
> > +		.codec_dai_name = "snd-soc-dummy-dai",
> > +		.codec_name = "snd-soc-dummy",
> > +		.platform_name = "sst-mfld-platform",
> > +		.nonatomic = true,
> > +		.dynamic = 1,
> > +		.dpcm_playback = 1,
> > +		.ops = &byt_cht_cx2072x_aif1_ops,
> > +	},
> > +	/* back ends */
> > +	{
> > +		.name = "SSP2-Codec",
> > +		.id = 1,
> > +		.cpu_dai_name = "ssp2-port",
> > +		.platform_name = "sst-mfld-platform",
> > +		.no_pcm = 1,
> > +		.codec_dai_name = "cx2072x-hifi",
> > +		.codec_name = "i2c-14F10720:00",
> > +		.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
> > +					      | SND_SOC_DAIFMT_CBS_CFS,
> > +		.init = byt_cht_cx2072x_init,
> > +		.be_hw_params_fixup = byt_cht_cx2072x_fixup,
> > +		.nonatomic = true,
> 
> I can't recall if this .atomic is needed or not for back-ends.

If FE requires it, BE must set it, too, in general.


> > +	{
> > +		.id = "14F10720",
> > +		.drv_name = "bytcht_cx2072x",
> > +		.fw_filename = "intel/fw_sst_0f28.bin",
> > +		.board = "bytcht_cx2072x",
> > +		/* .sof_fw_filename = "sof-byt.ri", */
> > +		/* .sof_tplg_filename = "sof-byt-cx2072x.tplg", */
> > +	},
> >   #if IS_ENABLED(CONFIG_SND_SOC_INTEL_BYT_CHT_NOCODEC_MACH)
> >   	/*
> >   	 * This is always last in the table so that it is selected only when
> > diff --git a/sound/soc/intel/common/soc-acpi-intel-cht-match.c b/sound/soc/intel/common/soc-acpi-intel-cht-match.c
> > index deafd87cc764..69ecbb88c171 100644
> > --- a/sound/soc/intel/common/soc-acpi-intel-cht-match.c
> > +++ b/sound/soc/intel/common/soc-acpi-intel-cht-match.c
> > @@ -169,6 +169,14 @@ struct snd_soc_acpi_mach  snd_soc_acpi_intel_cherrytrail_machines[] = {
> >   		.sof_fw_filename = "sof-cht.ri",
> >   		.sof_tplg_filename = "sof-cht-rt5651.tplg",
> >   	},
> > +	{
> > +		.id = "14F10720",
> > +		.drv_name = "bytcht_cx2072x",
> > +		.fw_filename = "intel/fw_sst_22a8.bin",
> > +		.board = "bytcht_cx2072x",
> > +		/* .sof_fw_filename = "sof-cht.ri", */
> > +		/* .sof_tplg_filename = "sof-cht-cx2072x.tplg", */
> > +	},
> 
> I'd uncomment those two ACPI machine parts. There is not risk unless
> SOF is actually enabled.

OK, will do that.


Thanks for a quick review!

Takashi
Takashi Iwai April 24, 2019, 1:08 p.m. UTC | #3
On Tue, 23 Apr 2019 21:39:50 +0200,
Takashi Iwai wrote:
> 
> > > +static int byt_cht_cx2072x_fixup(struct snd_soc_pcm_runtime *rtd,
> > > +				 struct snd_pcm_hw_params *params)
> > > +{
> > > +	struct snd_interval *rate =
> > > +		hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
> > > +	struct snd_interval *channels =
> > > +		hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
> > > +	int ret;
> > > +
> > > +	/* The DSP will covert the FE rate to 48k, stereo, 24bits */
> > > +	rate->min = rate->max = 48000;
> > > +	channels->min = channels->max = 2;
> > > +
> > > +	/* set SSP2 to 24-bit */
> > > +	params_set_format(params, SNDRV_PCM_FORMAT_S24_LE);
> > > +
> > > +	/*
> > > +	 * Default mode for SSP configuration is TDM 4 slot, override config
> > > +	 * with explicit setting to I2S 2ch 24-bit. The word length is set with
> > > +	 * dai_set_tdm_slot() since there is no other API exposed
> > > +	 */
> > > +	ret = snd_soc_dai_set_fmt(rtd->cpu_dai,
> > > +				SND_SOC_DAIFMT_I2S     |
> > > +				SND_SOC_DAIFMT_NB_NF   |
> > > +				SND_SOC_DAIFMT_CBS_CFS);
> > > +	if (ret < 0) {
> > > +		dev_err(rtd->dev, "can't set format to I2S, err %d\n", ret);
> > > +		return ret;
> > > +	}
> > > +
> > > +	ret = snd_soc_dai_set_tdm_slot(rtd->cpu_dai, 0x3, 0x3, 2, 24);
> > > +	if (ret < 0) {
> > > +		dev_err(rtd->dev, "can't set I2S config, err %d\n", ret);
> > > +		return ret;
> > > +	}
> > > +
> > > +	snd_soc_dai_set_bclk_ratio(rtd->codec_dai, 50);
> > 
> > that part would be problematic for SOF. IIRC we put all clock-related
> > stuff in the init, and ignore the fixups to use topology-based
> > information instead. If this call to _set_bclk_ratio can be moved to
> > the init it's more future-proof. Is there a reason to do this here in
> > the fixup?
> 
> No particular reason from my side.  I just took over your code ;)
> 
> That is, it'd be appreciated if you can give a fixup patch that can be
> applied on top.

OK, I tried just moving snd_soc_dai_set_bclk_ratio() into the init
callback, and it seems working fine.  The fix will be included in v2
patch.


thanks,

Takashi
diff mbox series

Patch

diff --git a/sound/soc/intel/boards/Kconfig b/sound/soc/intel/boards/Kconfig
index 12d6b73e9531..e8494ef96447 100644
--- a/sound/soc/intel/boards/Kconfig
+++ b/sound/soc/intel/boards/Kconfig
@@ -136,6 +136,17 @@  config SND_SOC_INTEL_CHT_BSW_NAU8824_MACH
 	  Say Y or m if you have such a device. This is a recommended option.
 	  If unsure select "N".
 
+config SND_SOC_INTEL_BYT_CHT_CX2072X_MACH
+	tristate "Baytrail & Cherrytrail with CX2072X codec"
+	depends on X86_INTEL_LPSS && I2C && ACPI
+	select SND_SOC_ACPI
+	select SND_SOC_CX2072X
+	help
+	  This adds support for ASoC machine driver for Intel(R) Baytrail &
+	  Cherrytrail platforms with Conexant CX2072X audio codec.
+	  Say Y or m if you have such a device. This is a recommended option.
+	  If unsure select "N".
+
 config SND_SOC_INTEL_BYT_CHT_DA7213_MACH
 	tristate "Baytrail & Cherrytrail with DA7212/7213 codec"
 	depends on X86_INTEL_LPSS && I2C && ACPI
diff --git a/sound/soc/intel/boards/Makefile b/sound/soc/intel/boards/Makefile
index bf072ea299b7..098ad7998b43 100644
--- a/sound/soc/intel/boards/Makefile
+++ b/sound/soc/intel/boards/Makefile
@@ -13,6 +13,7 @@  snd-soc-sst-cht-bsw-rt5672-objs := cht_bsw_rt5672.o
 snd-soc-sst-cht-bsw-rt5645-objs := cht_bsw_rt5645.o
 snd-soc-sst-cht-bsw-max98090_ti-objs := cht_bsw_max98090_ti.o
 snd-soc-sst-cht-bsw-nau8824-objs := cht_bsw_nau8824.o
+snd-soc-sst-byt-cht-cx2072x-objs := bytcht_cx2072x.o
 snd-soc-sst-byt-cht-da7213-objs := bytcht_da7213.o
 snd-soc-sst-byt-cht-es8316-objs := bytcht_es8316.o
 snd-soc-sst-byt-cht-nocodec-objs := bytcht_nocodec.o
@@ -40,6 +41,7 @@  obj-$(CONFIG_SND_SOC_INTEL_CHT_BSW_RT5672_MACH) += snd-soc-sst-cht-bsw-rt5672.o
 obj-$(CONFIG_SND_SOC_INTEL_CHT_BSW_RT5645_MACH) += snd-soc-sst-cht-bsw-rt5645.o
 obj-$(CONFIG_SND_SOC_INTEL_CHT_BSW_MAX98090_TI_MACH) += snd-soc-sst-cht-bsw-max98090_ti.o
 obj-$(CONFIG_SND_SOC_INTEL_CHT_BSW_NAU8824_MACH) += snd-soc-sst-cht-bsw-nau8824.o
+obj-$(CONFIG_SND_SOC_INTEL_BYT_CHT_CX2072X_MACH) += snd-soc-sst-byt-cht-cx2072x.o
 obj-$(CONFIG_SND_SOC_INTEL_BYT_CHT_DA7213_MACH) += snd-soc-sst-byt-cht-da7213.o
 obj-$(CONFIG_SND_SOC_INTEL_BYT_CHT_ES8316_MACH) += snd-soc-sst-byt-cht-es8316.o
 obj-$(CONFIG_SND_SOC_INTEL_BYT_CHT_NOCODEC_MACH) += snd-soc-sst-byt-cht-nocodec.o
diff --git a/sound/soc/intel/boards/bytcht_cx2072x.c b/sound/soc/intel/boards/bytcht_cx2072x.c
new file mode 100644
index 000000000000..697ff679576d
--- /dev/null
+++ b/sound/soc/intel/boards/bytcht_cx2072x.c
@@ -0,0 +1,285 @@ 
+// SPDX-License-Identifier: GPL-2.0
+//
+//  bytcht_cx207x.c - ASoC DPCM Machine driver for Baytrail / CherryTrail
+//                    platforms with CX2072X codec
+//
+
+#include <linux/acpi.h>
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <asm/platform_sst_audio.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/jack.h>
+#include <sound/soc.h>
+#include <sound/soc-acpi.h>
+#include "../../codecs/cx2072x.h"
+#include "../atom/sst-atom-controls.h"
+
+static const struct snd_soc_dapm_widget byt_cht_cx2072x_widgets[] = {
+	SND_SOC_DAPM_HP("Headphone", NULL),
+	SND_SOC_DAPM_MIC("Headset Mic", NULL),
+	SND_SOC_DAPM_MIC("Int Mic", NULL),
+	SND_SOC_DAPM_SPK("Ext Spk", NULL),
+};
+
+static const struct snd_soc_dapm_route byt_cht_cx2072x_audio_map[] = {
+	/* External Speakers: HFL, HFR */
+	{"Headphone", NULL, "PORTA"},
+	{"Ext Spk", NULL, "PORTG"},
+	{"PORTC", NULL, "Int Mic"},
+	{"PORTD", NULL, "Headset Mic"},
+
+	{"Playback", NULL, "ssp2 Tx"},
+	{"ssp2 Tx", NULL, "codec_out0"},
+	{"ssp2 Tx", NULL, "codec_out1"},
+	{"codec_in0", NULL, "ssp2 Rx"},
+	{"codec_in1", NULL, "ssp2 Rx"},
+	{"ssp2 Rx", NULL, "Capture"},
+	{"ssp0 Tx", NULL, "modem_out"},
+	{"modem_in", NULL, "ssp0 Rx"},
+};
+
+static const struct snd_kcontrol_new byt_cht_cx2072x_controls[] = {
+	SOC_DAPM_PIN_SWITCH("Headphone"),
+	SOC_DAPM_PIN_SWITCH("Headset Mic"),
+	SOC_DAPM_PIN_SWITCH("Int Mic"),
+	SOC_DAPM_PIN_SWITCH("Ext Spk"),
+};
+
+static struct snd_soc_jack byt_cht_cx2072x_headset;
+
+/* Headset jack detection DAPM pins */
+static struct snd_soc_jack_pin byt_cht_cx2072x_headset_pins[] = {
+	{
+		.pin = "Headset Mic",
+		.mask = SND_JACK_MICROPHONE,
+	},
+	{
+		.pin = "Headphone",
+		.mask = SND_JACK_HEADPHONE,
+	},
+};
+
+static const struct acpi_gpio_params byt_cht_cx2072x_headset_gpios;
+static const struct acpi_gpio_mapping byt_cht_cx2072x_acpi_gpios[] = {
+	{ "headset-gpios", &byt_cht_cx2072x_headset_gpios, 1 },
+	{},
+};
+
+static int byt_cht_cx2072x_jack_status_check(void *data)
+{
+	return snd_soc_cx2072x_get_jack_state(data);
+}
+
+static struct snd_soc_jack_gpio byt_cht_cx2072x_gpio = {
+	.name = "headset",
+	.report = SND_JACK_HEADSET | SND_JACK_BTN_0,
+	.debounce_time = 150,
+	.wake = true,
+	.jack_status_check = byt_cht_cx2072x_jack_status_check,
+};
+
+static int byt_cht_cx2072x_init(struct snd_soc_pcm_runtime *rtd)
+{
+	struct snd_soc_card *card = rtd->card;
+	struct snd_soc_component *codec = rtd->codec_dai->component;
+	int ret;
+
+	if (devm_acpi_dev_add_driver_gpios(codec->dev,
+					   byt_cht_cx2072x_acpi_gpios))
+		dev_warn(rtd->dev, "Unable to add GPIO mapping table\n");
+
+	card->dapm.idle_bias_off = true;
+
+	/* set the default PLL rate, the clock is handled by the codec driver */
+	ret = snd_soc_dai_set_sysclk(rtd->codec_dai, CX2072X_MCLK_EXTERNAL_PLL,
+				     19200000, SND_SOC_CLOCK_IN);
+	if (ret) {
+		dev_err(rtd->dev, "Could not set sysclk\n");
+		return ret;
+	}
+
+	ret = snd_soc_card_jack_new(card, "Headset",
+				    SND_JACK_HEADSET | SND_JACK_BTN_0,
+				    &byt_cht_cx2072x_headset,
+				    byt_cht_cx2072x_headset_pins,
+				    ARRAY_SIZE(byt_cht_cx2072x_headset_pins));
+	if (ret)
+		return ret;
+
+	byt_cht_cx2072x_gpio.gpiod_dev = codec->dev;
+	byt_cht_cx2072x_gpio.data = codec;
+	ret = snd_soc_jack_add_gpios(&byt_cht_cx2072x_headset, 1,
+				     &byt_cht_cx2072x_gpio);
+	if (ret) {
+		dev_err(rtd->dev, "Adding jack GPIO failed\n");
+		return ret;
+	}
+
+	snd_soc_cx2072x_enable_jack_detect(codec);
+
+	return ret;
+}
+
+static int byt_cht_cx2072x_fixup(struct snd_soc_pcm_runtime *rtd,
+				 struct snd_pcm_hw_params *params)
+{
+	struct snd_interval *rate =
+		hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
+	struct snd_interval *channels =
+		hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
+	int ret;
+
+	/* The DSP will covert the FE rate to 48k, stereo, 24bits */
+	rate->min = rate->max = 48000;
+	channels->min = channels->max = 2;
+
+	/* set SSP2 to 24-bit */
+	params_set_format(params, SNDRV_PCM_FORMAT_S24_LE);
+
+	/*
+	 * Default mode for SSP configuration is TDM 4 slot, override config
+	 * with explicit setting to I2S 2ch 24-bit. The word length is set with
+	 * dai_set_tdm_slot() since there is no other API exposed
+	 */
+	ret = snd_soc_dai_set_fmt(rtd->cpu_dai,
+				SND_SOC_DAIFMT_I2S     |
+				SND_SOC_DAIFMT_NB_NF   |
+				SND_SOC_DAIFMT_CBS_CFS);
+	if (ret < 0) {
+		dev_err(rtd->dev, "can't set format to I2S, err %d\n", ret);
+		return ret;
+	}
+
+	ret = snd_soc_dai_set_tdm_slot(rtd->cpu_dai, 0x3, 0x3, 2, 24);
+	if (ret < 0) {
+		dev_err(rtd->dev, "can't set I2S config, err %d\n", ret);
+		return ret;
+	}
+
+	snd_soc_dai_set_bclk_ratio(rtd->codec_dai, 50);
+	return 0;
+}
+
+static int byt_cht_cx2072x_aif1_startup(struct snd_pcm_substream *substream)
+{
+	return snd_pcm_hw_constraint_single(substream->runtime,
+					    SNDRV_PCM_HW_PARAM_RATE, 48000);
+}
+
+static struct snd_soc_ops byt_cht_cx2072x_aif1_ops = {
+	.startup = byt_cht_cx2072x_aif1_startup,
+};
+
+static struct snd_soc_dai_link byt_cht_cx2072x_dais[] = {
+	[MERR_DPCM_AUDIO] = {
+		.name = "Audio Port",
+		.stream_name = "Audio",
+		.cpu_dai_name = "media-cpu-dai",
+		.codec_dai_name = "snd-soc-dummy-dai",
+		.codec_name = "snd-soc-dummy",
+		.platform_name = "sst-mfld-platform",
+		.nonatomic = true,
+		.dynamic = 1,
+		.dpcm_playback = 1,
+		.dpcm_capture = 1,
+		.ops = &byt_cht_cx2072x_aif1_ops,
+	},
+	[MERR_DPCM_DEEP_BUFFER] = {
+		.name = "Deep-Buffer Audio Port",
+		.stream_name = "Deep-Buffer Audio",
+		.cpu_dai_name = "deepbuffer-cpu-dai",
+		.codec_dai_name = "snd-soc-dummy-dai",
+		.codec_name = "snd-soc-dummy",
+		.platform_name = "sst-mfld-platform",
+		.nonatomic = true,
+		.dynamic = 1,
+		.dpcm_playback = 1,
+		.ops = &byt_cht_cx2072x_aif1_ops,
+	},
+	/* back ends */
+	{
+		.name = "SSP2-Codec",
+		.id = 1,
+		.cpu_dai_name = "ssp2-port",
+		.platform_name = "sst-mfld-platform",
+		.no_pcm = 1,
+		.codec_dai_name = "cx2072x-hifi",
+		.codec_name = "i2c-14F10720:00",
+		.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
+					      | SND_SOC_DAIFMT_CBS_CFS,
+		.init = byt_cht_cx2072x_init,
+		.be_hw_params_fixup = byt_cht_cx2072x_fixup,
+		.nonatomic = true,
+		.dpcm_playback = 1,
+		.dpcm_capture = 1,
+	},
+};
+
+/* SoC card */
+static struct snd_soc_card byt_cht_cx2072x_card = {
+	.name = "bytcht-cx2072x",
+	.owner = THIS_MODULE,
+	.dai_link = byt_cht_cx2072x_dais,
+	.num_links = ARRAY_SIZE(byt_cht_cx2072x_dais),
+	.dapm_widgets = byt_cht_cx2072x_widgets,
+	.num_dapm_widgets = ARRAY_SIZE(byt_cht_cx2072x_widgets),
+	.dapm_routes = byt_cht_cx2072x_audio_map,
+	.num_dapm_routes = ARRAY_SIZE(byt_cht_cx2072x_audio_map),
+	.controls = byt_cht_cx2072x_controls,
+	.num_controls = ARRAY_SIZE(byt_cht_cx2072x_controls),
+};
+
+static char codec_name[SND_ACPI_I2C_ID_LEN];
+
+static int snd_byt_cht_cx2072x_probe(struct platform_device *pdev)
+{
+	struct snd_soc_acpi_mach *mach;
+	struct acpi_device *adev;
+	int dai_index = 0;
+	int i, ret;
+
+	byt_cht_cx2072x_card.dev = &pdev->dev;
+	mach = dev_get_platdata(&pdev->dev);
+
+	/* fix index of codec dai */
+	for (i = 0; i < ARRAY_SIZE(byt_cht_cx2072x_dais); i++) {
+		if (!strcmp(byt_cht_cx2072x_dais[i].codec_name,
+			    "i2c-14F10720:00")) {
+			dai_index = i;
+			break;
+		}
+	}
+
+	/* 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);
+		byt_cht_cx2072x_dais[dai_index].codec_name = codec_name;
+	}
+
+	/* override plaform name, if required */
+	ret = snd_soc_fixup_dai_links_platform_name(&byt_cht_cx2072x_card,
+						    mach->mach_params.platform);
+	if (ret)
+		return ret;
+
+	return devm_snd_soc_register_card(&pdev->dev, &byt_cht_cx2072x_card);
+}
+
+static struct platform_driver snd_byt_cht_cx2072x_driver = {
+	.driver = {
+		.name = "bytcht_cx2072x",
+	},
+	.probe = snd_byt_cht_cx2072x_probe,
+};
+module_platform_driver(snd_byt_cht_cx2072x_driver);
+
+MODULE_DESCRIPTION("ASoC Intel(R) Baytrail/Cherrytrail Machine driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:bytcht_cx2072x");
diff --git a/sound/soc/intel/common/soc-acpi-intel-byt-match.c b/sound/soc/intel/common/soc-acpi-intel-byt-match.c
index fe812a909db4..5387a82c2cf5 100644
--- a/sound/soc/intel/common/soc-acpi-intel-byt-match.c
+++ b/sound/soc/intel/common/soc-acpi-intel-byt-match.c
@@ -211,6 +211,14 @@  struct snd_soc_acpi_mach  snd_soc_acpi_intel_baytrail_machines[] = {
 		.sof_fw_filename = "sof-byt.ri",
 		.sof_tplg_filename = "sof-byt-max98090.tplg",
 	},
+	{
+		.id = "14F10720",
+		.drv_name = "bytcht_cx2072x",
+		.fw_filename = "intel/fw_sst_0f28.bin",
+		.board = "bytcht_cx2072x",
+		/* .sof_fw_filename = "sof-byt.ri", */
+		/* .sof_tplg_filename = "sof-byt-cx2072x.tplg", */
+	},
 #if IS_ENABLED(CONFIG_SND_SOC_INTEL_BYT_CHT_NOCODEC_MACH)
 	/*
 	 * This is always last in the table so that it is selected only when
diff --git a/sound/soc/intel/common/soc-acpi-intel-cht-match.c b/sound/soc/intel/common/soc-acpi-intel-cht-match.c
index deafd87cc764..69ecbb88c171 100644
--- a/sound/soc/intel/common/soc-acpi-intel-cht-match.c
+++ b/sound/soc/intel/common/soc-acpi-intel-cht-match.c
@@ -169,6 +169,14 @@  struct snd_soc_acpi_mach  snd_soc_acpi_intel_cherrytrail_machines[] = {
 		.sof_fw_filename = "sof-cht.ri",
 		.sof_tplg_filename = "sof-cht-rt5651.tplg",
 	},
+	{
+		.id = "14F10720",
+		.drv_name = "bytcht_cx2072x",
+		.fw_filename = "intel/fw_sst_22a8.bin",
+		.board = "bytcht_cx2072x",
+		/* .sof_fw_filename = "sof-cht.ri", */
+		/* .sof_tplg_filename = "sof-cht-cx2072x.tplg", */
+	},
 #if IS_ENABLED(CONFIG_SND_SOC_INTEL_BYT_CHT_NOCODEC_MACH)
 	/*
 	 * This is always last in the table so that it is selected only when