diff mbox

ASoC: Intel: Add Cherrytrail & Braswell machine driver cht_bsw_rt5672

Message ID c59847b1110e5302ec0a82700d4e318bef2a3f66.1414148860.git.mengdong.lin@intel.com (mailing list archive)
State New, archived
Headers show

Commit Message

Lin, Mengdong Oct. 24, 2014, 11:14 a.m. UTC
From: Mengdong Lin <mengdong.lin@intel.com>

Add machine driver for two Intel Cherryview-based platforms, Cherrytrail and
Braswell, with RT5672 codec.

Signed-off-by: Mengdong Lin <mengdong.lin@intel.com>

Comments

Mark Brown Oct. 24, 2014, 4:24 p.m. UTC | #1
On Fri, Oct 24, 2014 at 07:14:07PM +0800, mengdong.lin@intel.com wrote:
> From: Mengdong Lin <mengdong.lin@intel.com>
> 
> Add machine driver for two Intel Cherryview-based platforms, Cherrytrail and
> Braswell, with RT5672 codec.

This doesn't seem to have any ACPI stuff - how does the driver get
loaded?

> +static int cht_aif1_hw_params(struct snd_pcm_substream *substream,
> +					struct snd_pcm_hw_params *params)
> +{
> +	struct snd_soc_pcm_runtime *rtd = substream->private_data;
> +	struct snd_soc_dai *codec_dai = rtd->codec_dai;
> +	int ret;
> +	unsigned int fmt;
> +
> +	if (strncmp(codec_dai->name, "rt5670-aif1", 11))
> +		return 0;
> +
> +	/* TDM 4 slots 24 bit, set Rx & Tx bitmask to 4 active slots */
> +	ret = snd_soc_dai_set_tdm_slot(codec_dai, 0xF, 0xF, 4,
> +				       SNDRV_PCM_FORMAT_GSM);
> +	if (ret < 0) {
> +		dev_err(rtd->dev, "can't set codec TDM slot %d\n", ret);
> +		return ret;
> +	}
> +

This doesn't depend on the parameters so should be set on init and your
use of SNDRV_PCM_FORMAT_GSM doesn't seem to make much sense here -
what's going on?

> +	/* TDM slave Mode */
> +	fmt =   SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_IB_NF
> +		| SND_SOC_DAIFMT_CBS_CFS;
> +	ret = snd_soc_dai_set_fmt(codec_dai, fmt);
> +	if (ret < 0) {
> +		dev_err(rtd->dev, "can't set codec DAI fmt %d\n", ret);
> +		return ret;
> +	}

Likewise, set on init (in the dai_link)

> +static int cht_set_bias_level(struct snd_soc_card *card,
> +				struct snd_soc_dapm_context *dapm,
> +				enum snd_soc_bias_level level)
> +{
> +	switch (level) {
> +	case SND_SOC_BIAS_ON:
> +	case SND_SOC_BIAS_PREPARE:
> +	case SND_SOC_BIAS_STANDBY:
> +	case SND_SOC_BIAS_OFF:
> +		break;
> +	default:
> +		dev_err(card->dev, "Invalid bias level=%d\n", level);
> +		return -EINVAL;
> +	}
> +	card->dapm.bias_level = level;
> +	return 0;
> +}

This does nothing and can be removed.

> +static int cht_init(struct snd_soc_pcm_runtime *runtime)
> +{
> +	int ret;
> +	struct snd_soc_card *card = runtime->card;
> +
> +	/* Set card bias level */
> +	cht_set_bias_level(card, &card->dapm, SND_SOC_BIAS_OFF);
> +	card->dapm.idle_bias_off = true;
> +
> +	ret = snd_soc_dapm_sync(&card->dapm);
> +	if (ret) {
> +		dev_err(card->dev, "unable to sync dapm\n");
> +		return ret;
> +	}
> +	return ret;
> +}

This also does nothing and can be removed.

> +static struct snd_pcm_hw_constraint_list constraints_48000 = {
> +	.count = ARRAY_SIZE(rates_48000),
> +	.list  = rates_48000,
> +};
> +
> +static int cht_aif1_startup(struct snd_pcm_substream *substream)
> +{
> +	return snd_pcm_hw_constraint_list(substream->runtime, 0,
> +			SNDRV_PCM_HW_PARAM_RATE,
> +			&constraints_48000);
> +}

If the rates are restricted to 48kHz then is there any need for rate
dependent code in hw_params() at all?

> +static int snd_cht_mc_remove(struct platform_device *pdev)
> +{
> +	struct snd_soc_card *soc_card = platform_get_drvdata(pdev);
> +
> +	snd_soc_card_set_drvdata(soc_card, NULL);
> +	snd_soc_unregister_card(soc_card);
> +	platform_set_drvdata(pdev, NULL);
> +	return 0;
> +}

No need to set the driver data to NULL, the driver core will do it
anyway and it's buggy to look at the driver data for unbound devices.
Lin, Mengdong Oct. 27, 2014, 10:47 a.m. UTC | #2
Hi Mark,

> -----Original Message-----
> From: Mark Brown [mailto:broonie@kernel.org]
> Sent: Saturday, October 25, 2014 12:24 AM
 
> > Add machine driver for two Intel Cherryview-based platforms,
> > Cherrytrail and Braswell, with RT5672 codec.
> 
> This doesn't seem to have any ACPI stuff - how does the driver get loaded?

The ACPI stuff will be upstream later.
The machine device will be created by the SST ACPI loader sst-acpi.c, like Broadwell and Baytrail.
We're trying to merge ACPI stuff of new machines to the ACPI loader.

> > +static int cht_aif1_hw_params(struct snd_pcm_substream *substream,
> > +					struct snd_pcm_hw_params *params) {
> > +	struct snd_soc_pcm_runtime *rtd = substream->private_data;
> > +	struct snd_soc_dai *codec_dai = rtd->codec_dai;
> > +	int ret;
> > +	unsigned int fmt;
> > +
> > +	if (strncmp(codec_dai->name, "rt5670-aif1", 11))
> > +		return 0;
> > +
> > +	/* TDM 4 slots 24 bit, set Rx & Tx bitmask to 4 active slots */
> > +	ret = snd_soc_dai_set_tdm_slot(codec_dai, 0xF, 0xF, 4,
> > +				       SNDRV_PCM_FORMAT_GSM);
> > +	if (ret < 0) {
> > +		dev_err(rtd->dev, "can't set codec TDM slot %d\n", ret);
> > +		return ret;
> > +	}
> > +
> 
> This doesn't depend on the parameters so should be set on init and your use of
> SNDRV_PCM_FORMAT_GSM doesn't seem to make much sense here - what's
> going on?

Sorry, this is a misuse of SNDRV_PCM_FORMAT_GSM which happen to be 24
I'll correct this to snd_soc_dai_set_tdm_slot(codec_dai, 0xF, 0xF, 4, 24) , create a dai_link init function cht_codec_init() and move the code there.

> > +	/* TDM slave Mode */
> > +	fmt =   SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_IB_NF
> > +		| SND_SOC_DAIFMT_CBS_CFS;
> > +	ret = snd_soc_dai_set_fmt(codec_dai, fmt);
> > +	if (ret < 0) {
> > +		dev_err(rtd->dev, "can't set codec DAI fmt %d\n", ret);
> > +		return ret;
> > +	}
> 
> Likewise, set on init (in the dai_link)

I'll move it to back end dai link .dai_fmt as below:
.dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_IB_NF
					| SND_SOC_DAIFMT_CBS_CFS,

> > +static int cht_set_bias_level(struct snd_soc_card *card,
> > +				struct snd_soc_dapm_context *dapm,
> > +				enum snd_soc_bias_level level)
> > +{
> > +	switch (level) {
> > +	case SND_SOC_BIAS_ON:
> > +	case SND_SOC_BIAS_PREPARE:
> > +	case SND_SOC_BIAS_STANDBY:
> > +	case SND_SOC_BIAS_OFF:
> > +		break;
> > +	default:
> > +		dev_err(card->dev, "Invalid bias level=%d\n", level);
> > +		return -EINVAL;
> > +	}
> > +	card->dapm.bias_level = level;
> > +	return 0;
> > +}
> 
> This does nothing and can be removed.

Okay.

> > +static int cht_init(struct snd_soc_pcm_runtime *runtime) {
> > +	int ret;
> > +	struct snd_soc_card *card = runtime->card;
> > +
> > +	/* Set card bias level */
> > +	cht_set_bias_level(card, &card->dapm, SND_SOC_BIAS_OFF);
> > +	card->dapm.idle_bias_off = true;
> > +
> > +	ret = snd_soc_dapm_sync(&card->dapm);
> > +	if (ret) {
> > +		dev_err(card->dev, "unable to sync dapm\n");
> > +		return ret;
> > +	}
> > +	return ret;
> > +}
> 
> This also does nothing and can be removed.

Okay.

> > +static struct snd_pcm_hw_constraint_list constraints_48000 = {
> > +	.count = ARRAY_SIZE(rates_48000),
> > +	.list  = rates_48000,
> > +};
> > +
> > +static int cht_aif1_startup(struct snd_pcm_substream *substream) {
> > +	return snd_pcm_hw_constraint_list(substream->runtime, 0,
> > +			SNDRV_PCM_HW_PARAM_RATE,
> > +			&constraints_48000);
> > +}
> 
> If the rates are restricted to 48kHz then is there any need for rate dependent
> code in hw_params() at all?

Currently, we only tested 48kHz, but later will support 8KHz and 16KHz for VoIP application.
So hw_params() be reserved for reuse later?

> 
> > +static int snd_cht_mc_remove(struct platform_device *pdev) {
> > +	struct snd_soc_card *soc_card = platform_get_drvdata(pdev);
> > +
> > +	snd_soc_card_set_drvdata(soc_card, NULL);
> > +	snd_soc_unregister_card(soc_card);
> > +	platform_set_drvdata(pdev, NULL);
> > +	return 0;
> > +}
> 
> No need to set the driver data to NULL, the driver core will do it anyway and
> it's buggy to look at the driver data for unbound devices.

Okay.

Thanks for your review! I'll submit the v2 patch based on your comment. 
But I lost the message ID of my original patch, sorry for this.

Regards
Mengdong
diff mbox

Patch

diff --git a/sound/soc/intel/Kconfig b/sound/soc/intel/Kconfig
index 2a3af88..7479ce0 100644
--- a/sound/soc/intel/Kconfig
+++ b/sound/soc/intel/Kconfig
@@ -16,6 +16,9 @@  config SND_SST_MFLD_PLATFORM
 config SND_SST_IPC
 	tristate
 
+config SND_SST_MACHINE
+        tristate
+
 config SND_SOC_INTEL_SST
 	tristate "ASoC support for Intel(R) Smart Sound Technology"
 	select SND_SOC_INTEL_SST_ACPI if ACPI
@@ -76,3 +79,20 @@  config SND_SOC_INTEL_BROADWELL_MACH
 	  Ultrabook platforms.
 	  Say Y if you have such a device
 	  If unsure select "N".
+
+config SND_SOC_INTEL_CHT_BSW_RT5672_MACH
+        tristate "ASoC Audio driver for Intel Cherrytrail & Braswell with RT5672 codec"
+        depends on X86_INTEL_LPSS
+        select SND_SOC_RT5670
+        select SND_SST_MFLD_PLATFORM
+        select SND_SOC_INTEL_SST
+        select SND_SST_IPC
+        select SND_SST_MACHINE
+        default n
+
+        help
+          This adds support for ASoC machine driver for Intel(R) Cherrytrail & Braswell
+          platforms with RT5672 audio codec.
+          Say Y if you have such a device
+          If unsure select "N".
+
diff --git a/sound/soc/intel/Makefile b/sound/soc/intel/Makefile
index 9ab43be..4069d3f 100644
--- a/sound/soc/intel/Makefile
+++ b/sound/soc/intel/Makefile
@@ -31,6 +31,7 @@  obj-$(CONFIG_SND_SOC_INTEL_HASWELL_MACH) += snd-soc-sst-haswell.o
 obj-$(CONFIG_SND_SOC_INTEL_BYT_RT5640_MACH) += snd-soc-sst-byt-rt5640-mach.o
 obj-$(CONFIG_SND_SOC_INTEL_BYT_MAX98090_MACH) += snd-soc-sst-byt-max98090-mach.o
 obj-$(CONFIG_SND_SOC_INTEL_BROADWELL_MACH) += snd-soc-sst-broadwell.o
+obj-$(CONFIG_SND_SST_MACHINE) += board/
 
 # DSP driver
 obj-$(CONFIG_SND_SST_IPC) += sst/
diff --git a/sound/soc/intel/board/Makefile b/sound/soc/intel/board/Makefile
new file mode 100644
index 0000000..9ecc227
--- /dev/null
+++ b/sound/soc/intel/board/Makefile
@@ -0,0 +1,2 @@ 
+snd-soc-sst-cht-bsw-rt5672-objs := cht_bsw_rt5672.o
+obj-$(CONFIG_SND_SOC_INTEL_CHT_BSW_RT5672_MACH) += snd-soc-sst-cht-bsw-rt5672.o
diff --git a/sound/soc/intel/board/cht_bsw_rt5672.c b/sound/soc/intel/board/cht_bsw_rt5672.c
new file mode 100644
index 0000000..dffd8b1
--- /dev/null
+++ b/sound/soc/intel/board/cht_bsw_rt5672.c
@@ -0,0 +1,286 @@ 
+/*
+ *  cht_bsw_rt5672.c - ASoc Machine driver for Intel Cherryview-based platforms
+ *                     Cherrytrail and Braswell, with RT5672 codec.
+ *
+ *  Copyright (C) 2014 Intel Corp
+ *  Author: Subhransu S. Prusty <subhransu.s.prusty@intel.com>
+ *          Mengdong Lin <mengdong.lin@intel.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; version 2 of the License.
+ *
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  General Public License for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include "../../codecs/rt5670.h"
+#include "../sst-atom-controls.h"
+
+#define CHT_PLAT_CLK_3_HZ	19200000
+
+static const struct snd_soc_dapm_widget cht_dapm_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 cht_audio_map[] = {
+	{"IN1P", NULL, "Headset Mic"},
+	{"IN1N", NULL, "Headset Mic"},
+	{"DMIC L1", NULL, "Int Mic"},
+	{"DMIC R1", NULL, "Int Mic"},
+	{"Headphone", NULL, "HPOL"},
+	{"Headphone", NULL, "HPOR"},
+	{"Ext Spk", NULL, "SPOLP"},
+	{"Ext Spk", NULL, "SPOLN"},
+	{"Ext Spk", NULL, "SPORP"},
+	{"Ext Spk", NULL, "SPORN"},
+	{"AIF1 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, "AIF1 Capture"},
+};
+
+static const struct snd_kcontrol_new cht_mc_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 int cht_aif1_hw_params(struct snd_pcm_substream *substream,
+					struct snd_pcm_hw_params *params)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_dai *codec_dai = rtd->codec_dai;
+	int ret;
+	unsigned int fmt;
+
+	if (strncmp(codec_dai->name, "rt5670-aif1", 11))
+		return 0;
+
+	/* TDM 4 slots 24 bit, set Rx & Tx bitmask to 4 active slots */
+	ret = snd_soc_dai_set_tdm_slot(codec_dai, 0xF, 0xF, 4,
+				       SNDRV_PCM_FORMAT_GSM);
+	if (ret < 0) {
+		dev_err(rtd->dev, "can't set codec TDM slot %d\n", ret);
+		return ret;
+	}
+
+	/* TDM slave Mode */
+	fmt =   SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_IB_NF
+		| SND_SOC_DAIFMT_CBS_CFS;
+	ret = snd_soc_dai_set_fmt(codec_dai, fmt);
+	if (ret < 0) {
+		dev_err(rtd->dev, "can't set codec DAI fmt %d\n", ret);
+		return ret;
+	}
+
+	ret = snd_soc_dai_set_pll(codec_dai, 0, RT5670_PLL1_S_MCLK,
+				  CHT_PLAT_CLK_3_HZ, params_rate(params) * 512);
+	if (ret < 0) {
+		dev_err(rtd->dev, "can't set codec pll: %d\n", ret);
+		return ret;
+	}
+
+	ret = snd_soc_dai_set_sysclk(codec_dai, RT5670_SCLK_S_PLL1,
+				     params_rate(params) * 512,
+				     SND_SOC_CLOCK_IN);
+	if (ret < 0) {
+		dev_err(rtd->dev, "can't set codec sysclk: %d\n", ret);
+		return ret;
+	}
+	return 0;
+}
+
+static int cht_codec_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);
+
+	/* 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 */
+	snd_mask_set(&params->masks[SNDRV_PCM_HW_PARAM_FORMAT -
+				    SNDRV_PCM_HW_PARAM_FIRST_MASK],
+				    SNDRV_PCM_FORMAT_S24_LE);
+	return 0;
+}
+
+static int cht_set_bias_level(struct snd_soc_card *card,
+				struct snd_soc_dapm_context *dapm,
+				enum snd_soc_bias_level level)
+{
+	switch (level) {
+	case SND_SOC_BIAS_ON:
+	case SND_SOC_BIAS_PREPARE:
+	case SND_SOC_BIAS_STANDBY:
+	case SND_SOC_BIAS_OFF:
+		break;
+	default:
+		dev_err(card->dev, "Invalid bias level=%d\n", level);
+		return -EINVAL;
+	}
+	card->dapm.bias_level = level;
+	return 0;
+}
+
+static int cht_init(struct snd_soc_pcm_runtime *runtime)
+{
+	int ret;
+	struct snd_soc_card *card = runtime->card;
+
+	/* Set card bias level */
+	cht_set_bias_level(card, &card->dapm, SND_SOC_BIAS_OFF);
+	card->dapm.idle_bias_off = true;
+
+	ret = snd_soc_dapm_sync(&card->dapm);
+	if (ret) {
+		dev_err(card->dev, "unable to sync dapm\n");
+		return ret;
+	}
+	return ret;
+}
+
+static unsigned int rates_48000[] = {
+	48000,
+};
+
+static struct snd_pcm_hw_constraint_list constraints_48000 = {
+	.count = ARRAY_SIZE(rates_48000),
+	.list  = rates_48000,
+};
+
+static int cht_aif1_startup(struct snd_pcm_substream *substream)
+{
+	return snd_pcm_hw_constraint_list(substream->runtime, 0,
+			SNDRV_PCM_HW_PARAM_RATE,
+			&constraints_48000);
+}
+
+static struct snd_soc_ops cht_aif1_ops = {
+	.startup = cht_aif1_startup,
+};
+
+static struct snd_soc_ops cht_be_ssp2_ops = {
+	.hw_params = cht_aif1_hw_params,
+};
+
+static struct snd_soc_dai_link cht_dailink[] = {
+	/* Front End DAI links */
+	[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",
+		.init = cht_init,
+		.ignore_suspend = 1,
+		.dynamic = 1,
+		.dpcm_playback = 1,
+		.dpcm_capture = 1,
+		.ops = &cht_aif1_ops,
+	},
+	[MERR_DPCM_COMPR] = {
+		.name = "Compressed Port",
+		.stream_name = "Compress",
+		.cpu_dai_name = "compress-cpu-dai",
+		.codec_dai_name = "snd-soc-dummy-dai",
+		.codec_name = "snd-soc-dummy",
+		.platform_name = "sst-mfld-platform",
+	},
+
+	/* Back End DAI links */
+	{
+		/* SSP2 - Codec */
+		.name = "SSP2-Codec",
+		.be_id = 1,
+		.cpu_dai_name = "ssp2-port",
+		.platform_name = "sst-mfld-platform",
+		.no_pcm = 1,
+		.codec_dai_name = "rt5670-aif1",
+		.codec_name = "i2c-10EC5670:00",
+		.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
+						| SND_SOC_DAIFMT_CBS_CFS,
+		.be_hw_params_fixup = cht_codec_fixup,
+		.ignore_suspend = 1,
+		.dpcm_playback = 1,
+		.dpcm_capture = 1,
+		.ops = &cht_be_ssp2_ops,
+	},
+};
+
+/* SoC card */
+static struct snd_soc_card snd_soc_card_cht = {
+	.name = "cherrytrailcraudio",
+	.dai_link = cht_dailink,
+	.num_links = ARRAY_SIZE(cht_dailink),
+	.set_bias_level = cht_set_bias_level,
+	.dapm_widgets = cht_dapm_widgets,
+	.num_dapm_widgets = ARRAY_SIZE(cht_dapm_widgets),
+	.dapm_routes = cht_audio_map,
+	.num_dapm_routes = ARRAY_SIZE(cht_audio_map),
+	.controls = cht_mc_controls,
+	.num_controls = ARRAY_SIZE(cht_mc_controls),
+};
+
+static int snd_cht_mc_probe(struct platform_device *pdev)
+{
+	int ret_val = 0;
+
+	/* register the soc card */
+	snd_soc_card_cht.dev = &pdev->dev;
+	ret_val = snd_soc_register_card(&snd_soc_card_cht);
+	if (ret_val) {
+		dev_err(&pdev->dev,
+			"snd_soc_register_card failed %d\n", ret_val);
+		return ret_val;
+	}
+	platform_set_drvdata(pdev, &snd_soc_card_cht);
+	return ret_val;
+}
+
+static int snd_cht_mc_remove(struct platform_device *pdev)
+{
+	struct snd_soc_card *soc_card = platform_get_drvdata(pdev);
+
+	snd_soc_card_set_drvdata(soc_card, NULL);
+	snd_soc_unregister_card(soc_card);
+	platform_set_drvdata(pdev, NULL);
+	return 0;
+}
+
+static struct platform_driver snd_cht_mc_driver = {
+	.driver = {
+		.owner = THIS_MODULE,
+		.name = "cht-bsw-rt5672",
+		.pm = &snd_soc_pm_ops,
+	},
+	.probe = snd_cht_mc_probe,
+	.remove = snd_cht_mc_remove,
+};
+
+module_platform_driver(snd_cht_mc_driver);
+
+MODULE_DESCRIPTION("ASoC Intel(R) Baytrail CR Machine driver");
+MODULE_AUTHOR("Subhransu S. Prusty, Mengdong Lin");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:cht-bsw-rt5672");