about summary refs log tree commit diff
path: root/modules/hardware/t100ha
diff options
context:
space:
mode:
Diffstat (limited to 'modules/hardware/t100ha')
-rw-r--r--modules/hardware/t100ha/backlight.patch223
-rw-r--r--modules/hardware/t100ha/default.nix12
-rw-r--r--modules/hardware/t100ha/drm.patch733
-rw-r--r--modules/hardware/t100ha/sdio.patch52
-rw-r--r--modules/hardware/t100ha/sound.patch5620
5 files changed, 226 insertions, 6414 deletions
diff --git a/modules/hardware/t100ha/backlight.patch b/modules/hardware/t100ha/backlight.patch
new file mode 100644
index 00000000..a83d6659
--- /dev/null
+++ b/modules/hardware/t100ha/backlight.patch
@@ -0,0 +1,223 @@
+diff --git a/drivers/gpu/drm/i915/intel_dsi.c b/drivers/gpu/drm/i915/intel_dsi.c
+index fc0ef492252a..f9bf7290a2bb 100644
+--- a/drivers/gpu/drm/i915/intel_dsi.c
++++ b/drivers/gpu/drm/i915/intel_dsi.c
+@@ -644,6 +644,7 @@ static void intel_dsi_port_enable(struct intel_encoder *encoder)
+ 	struct drm_i915_private *dev_priv = to_i915(dev);
+ 	struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc);
+ 	struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base);
++	struct intel_connector *intel_connector = intel_dsi->attached_connector;
+ 	enum port port;
+ 
+ 	if (intel_dsi->dual_link == DSI_DUAL_LINK_FRONT_BACK) {
+@@ -665,6 +666,8 @@ static void intel_dsi_port_enable(struct intel_encoder *encoder)
+ 		}
+ 	}
+ 
++	intel_panel_disable_backlight(intel_connector);
++
+ 	for_each_dsi_port(port, intel_dsi->ports) {
+ 		i915_reg_t port_ctrl = IS_GEN9_LP(dev_priv) ?
+ 			BXT_MIPI_PORT_CTRL(port) : MIPI_PORT_CTRL(port);
+@@ -1635,6 +1638,7 @@ static void intel_dsi_connector_destroy(struct drm_connector *connector)
+ 
+ 	DRM_DEBUG_KMS("\n");
+ 	intel_panel_fini(&intel_connector->panel);
++	intel_panel_destroy_backlight(connector);
+ 	drm_connector_cleanup(connector);
+ 	kfree(connector);
+ }
+diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c
+index cb50c527401f..0dae84db6303 100644
+--- a/drivers/gpu/drm/i915/intel_panel.c
++++ b/drivers/gpu/drm/i915/intel_panel.c
+@@ -32,6 +32,7 @@
+ 
+ #include <linux/kernel.h>
+ #include <linux/moduleparam.h>
++#include <linux/mfd/intel_soc_pmic.h>
+ #include <linux/pwm.h>
+ #include "intel_drv.h"
+ 
+@@ -542,6 +543,11 @@ static u32 pwm_get_backlight(struct intel_connector *connector)
+ 	return DIV_ROUND_UP(duty_ns * 100, CRC_PMIC_PWM_PERIOD_NS);
+ }
+ 
++static u32 vlv_pmic_get_backlight(struct intel_connector *connector)
++{
++	return intel_soc_pmic_readb(0x4E);
++}
++
+ static u32 intel_panel_get_backlight(struct intel_connector *connector)
+ {
+ 	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
+@@ -633,6 +639,11 @@ static void pwm_set_backlight(struct intel_connector *connector, u32 level)
+ 	pwm_config(panel->backlight.pwm, duty_ns, CRC_PMIC_PWM_PERIOD_NS);
+ }
+ 
++static void vlv_pmic_set_backlight(struct intel_connector *connector, u32 level)
++{
++	intel_soc_pmic_writeb(0x4E, level);
++}
++
+ static void
+ intel_panel_actually_set_backlight(struct intel_connector *connector, u32 level)
+ {
+@@ -806,6 +817,14 @@ static void pwm_disable_backlight(struct intel_connector *connector)
+ 	pwm_disable(panel->backlight.pwm);
+ }
+ 
++static void vlv_pmic_disable_backlight(struct intel_connector *connector)
++{
++	intel_panel_actually_set_backlight(connector, 0);
++
++	intel_soc_pmic_writeb(0x51, 0x00);
++	intel_soc_pmic_writeb(0x4B, 0x7F);
++}
++
+ void intel_panel_disable_backlight(struct intel_connector *connector)
+ {
+ 	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
+@@ -1084,6 +1103,17 @@ static void pwm_enable_backlight(struct intel_connector *connector)
+ 	intel_panel_actually_set_backlight(connector, panel->backlight.level);
+ }
+ 
++static void vlv_pmic_enable_backlight(struct intel_connector *connector)
++{
++	struct intel_panel *panel = &connector->panel;
++
++	intel_soc_pmic_writeb(0x4B, 0xFF);
++	intel_soc_pmic_writeb(0x4E, 0xFF);
++	intel_soc_pmic_writeb(0x51, 0x01);
++
++	intel_panel_actually_set_backlight(connector, panel->backlight.level);
++}
++
+ void intel_panel_enable_backlight(struct intel_connector *connector)
+ {
+ 	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
+@@ -1673,6 +1703,20 @@ static int pwm_setup_backlight(struct intel_connector *connector,
+ 	return 0;
+ }
+ 
++static int vlv_pmic_setup_backlight(struct intel_connector *connector,
++		enum pipe unused)
++{
++	struct intel_panel *panel = &connector->panel;
++
++	panel->backlight.present = 1;
++	panel->backlight.min = 0x00;
++	panel->backlight.max = 0xFF;
++	panel->backlight.level = 0x5A;
++	panel->backlight.enabled = 1;
++
++	return 0;
++}
++
+ int intel_panel_setup_backlight(struct drm_connector *connector, enum pipe pipe)
+ {
+ 	struct drm_i915_private *dev_priv = to_i915(connector->dev);
+@@ -1680,6 +1724,8 @@ int intel_panel_setup_backlight(struct drm_connector *connector, enum pipe pipe)
+ 	struct intel_panel *panel = &intel_connector->panel;
+ 	int ret;
+ 
++	intel_backlight_device_register(intel_connector);
++
+ 	if (!dev_priv->vbt.backlight.present) {
+ 		if (dev_priv->quirks & QUIRK_BACKLIGHT_PRESENT) {
+ 			DRM_DEBUG_KMS("no backlight present per VBT, but present per quirk\n");
+@@ -1769,18 +1815,17 @@ intel_panel_init_backlight_funcs(struct intel_panel *panel)
+ 		panel->backlight.hz_to_pwm = pch_hz_to_pwm;
+ 	} else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
+ 		if (connector->base.connector_type == DRM_MODE_CONNECTOR_DSI) {
+-			panel->backlight.setup = pwm_setup_backlight;
+-			panel->backlight.enable = pwm_enable_backlight;
+-			panel->backlight.disable = pwm_disable_backlight;
+-			panel->backlight.set = pwm_set_backlight;
+-			panel->backlight.get = pwm_get_backlight;
++			panel->backlight.setup = vlv_pmic_setup_backlight;
++			panel->backlight.enable = vlv_pmic_enable_backlight;
++			panel->backlight.disable = vlv_pmic_disable_backlight;
++			panel->backlight.set = vlv_pmic_set_backlight;
++			panel->backlight.get = vlv_pmic_get_backlight;
+ 		} else {
+ 			panel->backlight.setup = vlv_setup_backlight;
+ 			panel->backlight.enable = vlv_enable_backlight;
+ 			panel->backlight.disable = vlv_disable_backlight;
+ 			panel->backlight.set = vlv_set_backlight;
+ 			panel->backlight.get = vlv_get_backlight;
+-			panel->backlight.hz_to_pwm = vlv_hz_to_pwm;
+ 		}
+ 	} else if (IS_GEN4(dev_priv)) {
+ 		panel->backlight.setup = i965_setup_backlight;
+diff --git a/drivers/mfd/intel_soc_pmic_core.c b/drivers/mfd/intel_soc_pmic_core.c
+index 13737be6df35..60880fdbdccf 100644
+--- a/drivers/mfd/intel_soc_pmic_core.c
++++ b/drivers/mfd/intel_soc_pmic_core.c
+@@ -44,6 +44,8 @@ static struct pwm_lookup crc_pwm_lookup[] = {
+ 	PWM_LOOKUP("crystal_cove_pwm", 0, "0000:00:02.0", "pwm_backlight", 0, PWM_POLARITY_NORMAL),
+ };
+ 
++static struct intel_soc_pmic *pmic_hack = NULL;
++
+ static int intel_soc_pmic_i2c_probe(struct i2c_client *i2c,
+ 				    const struct i2c_device_id *i2c_id)
+ {
+@@ -60,6 +62,7 @@ static int intel_soc_pmic_i2c_probe(struct i2c_client *i2c,
+ 	config = (struct intel_soc_pmic_config *)id->driver_data;
+ 
+ 	pmic = devm_kzalloc(dev, sizeof(*pmic), GFP_KERNEL);
++	pmic_hack = pmic;
+ 	if (!pmic)
+ 		return -ENOMEM;
+ 
+@@ -147,6 +150,37 @@ static int intel_soc_pmic_resume(struct device *dev)
+ }
+ #endif
+ 
++int intel_soc_pmic_readb(int reg)
++{
++	int ret;
++	unsigned int val;
++
++	if (!pmic_hack) {
++		ret = -EIO;
++	} else {
++		ret = regmap_read(pmic_hack->regmap, reg, &val);
++		if (!ret) {
++			ret = val;
++		}
++	}
++
++	return ret;
++}
++EXPORT_SYMBOL(intel_soc_pmic_readb);
++
++int intel_soc_pmic_writeb(int reg, u8 val)
++{
++	int ret;
++
++	if (!pmic_hack) {
++		ret = -EIO;
++	} else {
++		ret = regmap_write(pmic_hack->regmap, reg, val);
++	}
++	return ret;
++}
++EXPORT_SYMBOL(intel_soc_pmic_writeb);
++
+ static SIMPLE_DEV_PM_OPS(intel_soc_pmic_pm_ops, intel_soc_pmic_suspend,
+ 			 intel_soc_pmic_resume);
+ 
+diff --git a/include/linux/mfd/intel_soc_pmic.h b/include/linux/mfd/intel_soc_pmic.h
+index 956caa0628f5..2adff16a60c3 100644
+--- a/include/linux/mfd/intel_soc_pmic.h
++++ b/include/linux/mfd/intel_soc_pmic.h
+@@ -30,4 +30,7 @@ struct intel_soc_pmic {
+ 	struct device *dev;
+ };
+ 
++int intel_soc_pmic_readb(int reg);
++int intel_soc_pmic_writeb(int reg, u8 val);
++
+ #endif	/* __INTEL_SOC_PMIC_H__ */
diff --git a/modules/hardware/t100ha/default.nix b/modules/hardware/t100ha/default.nix
index 70a9fc38..c8635dcf 100644
--- a/modules/hardware/t100ha/default.nix
+++ b/modules/hardware/t100ha/default.nix
@@ -20,23 +20,17 @@ in {
     '');
 
     boot.kernelPatches = [
-      { name = "drm";
-        patch = ./drm.patch;
+      { name = "backlight";
+        patch = ./backlight.patch;
       }
       { name = "meta-keys";
         patch = ./meta-keys.patch;
       }
-      { name = "sdio";
-        patch = ./sdio.patch;
-      }
-      { name = "sound";
-        patch = ./sound.patch;
-      }
     ];
 
     boot.kernelPackages = let
       nixpkgs = import ../../../nixpkgs-path.nix;
-      t100haKernel = pkgs.linux_4_9.override {
+      t100haKernel = pkgs.linux_testing.override {
         # Missing device drivers:
         #
         #   808622B8 -> Intel(R) Imaging Signal Processor 2401
diff --git a/modules/hardware/t100ha/drm.patch b/modules/hardware/t100ha/drm.patch
deleted file mode 100644
index 167be86d..00000000
--- a/modules/hardware/t100ha/drm.patch
+++ /dev/null
@@ -1,733 +0,0 @@
-diff --git a/drivers/gpu/drm/i915/intel_bios.h b/drivers/gpu/drm/i915/intel_bios.h
-index 8405b5a367d7..7e3545f65257 100644
---- a/drivers/gpu/drm/i915/intel_bios.h
-+++ b/drivers/gpu/drm/i915/intel_bios.h
-@@ -46,14 +46,20 @@ struct edp_power_seq {
- 	u16 t11_t12;
- } __packed;
- 
--/* MIPI Sequence Block definitions */
-+/*
-+ * MIPI Sequence Block definitions
-+ *
-+ * Note the VBT spec has AssertReset / DeassertReset swapped from their
-+ * usual naming, we use the proper names here to avoid confusion when
-+ * reading the code.
-+ */
- enum mipi_seq {
- 	MIPI_SEQ_END = 0,
--	MIPI_SEQ_ASSERT_RESET,
-+	MIPI_SEQ_DEASSERT_RESET,	/* Spec says MipiAssertResetPin */
- 	MIPI_SEQ_INIT_OTP,
- 	MIPI_SEQ_DISPLAY_ON,
- 	MIPI_SEQ_DISPLAY_OFF,
--	MIPI_SEQ_DEASSERT_RESET,
-+	MIPI_SEQ_ASSERT_RESET,		/* Spec says MipiDeassertResetPin */
- 	MIPI_SEQ_BACKLIGHT_ON,		/* sequence block v2+ */
- 	MIPI_SEQ_BACKLIGHT_OFF,		/* sequence block v2+ */
- 	MIPI_SEQ_TEAR_ON,		/* sequence block v2+ */
-diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
-index c9e83f39ec0a..6a6ae51996d0 100644
---- a/drivers/gpu/drm/i915/intel_display.c
-+++ b/drivers/gpu/drm/i915/intel_display.c
-@@ -13764,6 +13764,13 @@ static void update_scanline_offset(struct intel_crtc *crtc)
- 	 * type. For DP ports it behaves like most other platforms, but on HDMI
- 	 * there's an extra 1 line difference. So we need to add two instead of
- 	 * one to the value.
-+	 *
-+	 * On VLV/CHV DSI the scanline counter would appear to increment
-+	 * approx. 1/3 of a scanline before start of vblank. Unfortunately
-+	 * that we can't tell whether we're in vblank or not while we're
-+	 * on that particular line. We must set scanline_offset to 1 so
-+	 * that the vblank timestamps come out correct when we query
-+	 * the scanline counter from the vblank interrupt handler.
- 	 */
- 	if (IS_GEN2(dev)) {
- 		const struct drm_display_mode *adjusted_mode = &crtc->config->base.adjusted_mode;
-diff --git a/drivers/gpu/drm/i915/intel_dsi.c b/drivers/gpu/drm/i915/intel_dsi.c
-index b2e3d3a334f7..c07ef5e9de95 100644
---- a/drivers/gpu/drm/i915/intel_dsi.c
-+++ b/drivers/gpu/drm/i915/intel_dsi.c
-@@ -80,7 +80,7 @@ enum mipi_dsi_pixel_format pixel_format_from_register_bits(u32 fmt)
- 	}
- }
- 
--static void wait_for_dsi_fifo_empty(struct intel_dsi *intel_dsi, enum port port)
-+void wait_for_dsi_fifo_empty(struct intel_dsi *intel_dsi, enum port port)
- {
- 	struct drm_encoder *encoder = &intel_dsi->base.base;
- 	struct drm_device *dev = encoder->dev;
-@@ -505,37 +505,83 @@ static void intel_dsi_port_disable(struct intel_encoder *encoder)
- 	}
- }
- 
--static void intel_dsi_enable(struct intel_encoder *encoder)
--{
--	struct drm_device *dev = encoder->base.dev;
--	struct drm_i915_private *dev_priv = to_i915(dev);
--	struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base);
--	enum port port;
--
--	DRM_DEBUG_KMS("\n");
--
--	if (is_cmd_mode(intel_dsi)) {
--		for_each_dsi_port(port, intel_dsi->ports)
--			I915_WRITE(MIPI_MAX_RETURN_PKT_SIZE(port), 8 * 4);
--	} else {
--		msleep(20); /* XXX */
--		for_each_dsi_port(port, intel_dsi->ports)
--			dpi_send_cmd(intel_dsi, TURN_ON, false, port);
--		msleep(100);
--
--		drm_panel_enable(intel_dsi->panel);
-+static void intel_dsi_prepare(struct intel_encoder *intel_encoder,
-+			      struct intel_crtc_state *pipe_config);
- 
--		for_each_dsi_port(port, intel_dsi->ports)
--			wait_for_dsi_fifo_empty(intel_dsi, port);
-+static void intel_dsi_msleep(struct intel_dsi *intel_dsi, int msec)
-+{
-+	struct drm_i915_private *dev_priv = to_i915(intel_dsi->base.base.dev);
- 
--		intel_dsi_port_enable(encoder);
--	}
-+	/* For v3 VBTs in vid-mode the delays are part of the VBT sequences */
-+	if (is_vid_mode(intel_dsi) && dev_priv->vbt.dsi.seq_version >= 3)
-+		return;
- 
--	intel_panel_enable_backlight(intel_dsi->attached_connector);
-+	msleep(msec);
- }
- 
--static void intel_dsi_prepare(struct intel_encoder *intel_encoder,
--			      struct intel_crtc_state *pipe_config);
-+/*
-+ * Panel enable/disable sequences from the spec:
-+ *
-+ * v2 sequence for video mode:
-+ * - power on
-+ * - wait t1+t2
-+ * - MIPIDeassertResetPin
-+ * - clk/data lines to lp-11
-+ * - MIPISendInitialDcsCmds
-+ * - turn on DPI
-+ * - MIPIDisplayOn
-+ * - wait t5
-+ * - backlight on
-+ * ...
-+ * - backlight off
-+ * - wait t6
-+ * - MIPIDisplayOff
-+ * - turn off DPI
-+ * - clk/data lines to lp-00
-+ * - MIPIAssertResetPin
-+ * - wait t3
-+ * - power off
-+ * - wait t4
-+ *
-+ * v3 sequence for video mode:
-+ * - MIPIPanelPowerOn
-+ * - MIPIDeassertResetPin
-+ * - set clk/data lines to lp-11
-+ * - MIPISendInitialDcsCmds (LP)
-+ * - turn on DPI
-+ * - MIPITearOn (command mode only) + MIPIDisplayOn (LP and HS)
-+ * - MIPIBacklightOn
-+ * ...
-+ * - MIPIBacklightOff
-+ * - turn off DPI
-+ * - MIPITearOff + MIPIDisplayOff (LP)
-+ * - clk/data lines to lp-00
-+ * - MIPIAssertResetPin
-+ * - MIPIPanelPowerOff
-+ *
-+ * sequence for command mode:
-+ * - power on
-+ * - wait t1+t2
-+ * - MIPIDeassertResetPin
-+ * - clk/data lines to lp-11
-+ * - MIPISendInitialDcsCmds
-+ * - MIPITearOn
-+ * - MIPIDisplayOn
-+ * - set pipe to dsr mode
-+ * - wait t5
-+ * - backlight on
-+ * ... issue write_mem_start/write_mem_continue commands ...
-+ * - backlight off
-+ * - wait t6
-+ * - disable pipe dsr mode
-+ * - MIPITearOff
-+ * - MIPIDisplayOff
-+ * - clk/data lines to lp-00
-+ * - MIPIAssertResetPin
-+ * - wait t3
-+ * - power off
-+ * - wait t4
-+ */
- 
- static void intel_dsi_pre_enable(struct intel_encoder *encoder,
- 				 struct intel_crtc_state *pipe_config,
-@@ -554,14 +600,6 @@ static void intel_dsi_pre_enable(struct intel_encoder *encoder,
- 	intel_disable_dsi_pll(encoder);
- 	intel_enable_dsi_pll(encoder, pipe_config);
- 
--	intel_dsi_prepare(encoder, pipe_config);
--
--	/* Panel Enable over CRC PMIC */
--	if (intel_dsi->gpio_panel)
--		gpiod_set_value_cansleep(intel_dsi->gpio_panel, 1);
--
--	msleep(intel_dsi->panel_on_delay);
--
- 	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
- 		u32 val;
- 
-@@ -571,17 +609,44 @@ static void intel_dsi_pre_enable(struct intel_encoder *encoder,
- 		I915_WRITE(DSPCLK_GATE_D, val);
- 	}
- 
--	/* put device in ready state */
--	intel_dsi_device_ready(encoder);
-+	intel_dsi_prepare(encoder, pipe_config);
-+
-+	/* Power on, try both CRC pmic gpio and VBT */
-+	if (intel_dsi->gpio_panel)
-+		gpiod_set_value_cansleep(intel_dsi->gpio_panel, 1);
-+	intel_dsi_exec_vbt_sequence(intel_dsi, MIPI_SEQ_POWER_ON);
-+	intel_dsi_msleep(intel_dsi, intel_dsi->panel_on_delay);
- 
--	drm_panel_prepare(intel_dsi->panel);
-+	/* Deassert reset */
-+	intel_dsi_exec_vbt_sequence(intel_dsi, MIPI_SEQ_DEASSERT_RESET);
- 
--	for_each_dsi_port(port, intel_dsi->ports)
--		wait_for_dsi_fifo_empty(intel_dsi, port);
-+	/* Put device in ready state (LP-11) */
-+	intel_dsi_device_ready(encoder);
-+
-+	/* Send initialization commands in LP mode */
-+	intel_dsi_exec_vbt_sequence(intel_dsi, MIPI_SEQ_INIT_OTP);
- 
- 	/* Enable port in pre-enable phase itself because as per hw team
- 	 * recommendation, port should be enabled befor plane & pipe */
--	intel_dsi_enable(encoder);
-+	if (is_cmd_mode(intel_dsi)) {
-+		for_each_dsi_port(port, intel_dsi->ports)
-+			I915_WRITE(MIPI_MAX_RETURN_PKT_SIZE(port), 8 * 4);
-+		intel_dsi_exec_vbt_sequence(intel_dsi, MIPI_SEQ_TEAR_ON);
-+		intel_dsi_exec_vbt_sequence(intel_dsi, MIPI_SEQ_DISPLAY_ON);
-+	} else {
-+		msleep(20); /* XXX */
-+		for_each_dsi_port(port, intel_dsi->ports)
-+			dpi_send_cmd(intel_dsi, TURN_ON, false, port);
-+		intel_dsi_msleep(intel_dsi, 100);
-+
-+		intel_dsi_exec_vbt_sequence(intel_dsi, MIPI_SEQ_DISPLAY_ON);
-+
-+		intel_dsi_port_enable(encoder);
-+	}
-+
-+	/* Enable backlight, both pwm and VBT */
-+	intel_panel_enable_backlight(intel_dsi->attached_connector);
-+	intel_dsi_exec_vbt_sequence(intel_dsi, MIPI_SEQ_BACKLIGHT_ON);
- }
- 
- static void intel_dsi_enable_nop(struct intel_encoder *encoder,
-@@ -605,8 +670,15 @@ static void intel_dsi_pre_disable(struct intel_encoder *encoder,
- 
- 	DRM_DEBUG_KMS("\n");
- 
-+	/* Disable backlight, both VBT and pwm */
-+	intel_dsi_exec_vbt_sequence(intel_dsi, MIPI_SEQ_BACKLIGHT_OFF);
- 	intel_panel_disable_backlight(intel_dsi->attached_connector);
- 
-+	/*
-+	 * XXX: According to the spec we should send SHUTDOWN before
-+	 * MIPI_SEQ_DISPLAY_OFF only for v3+ VBTs, but testing in the field
-+	 * has shown that we should do this for v2 VBTs too?
-+	 */
- 	if (is_vid_mode(intel_dsi)) {
- 		/* Send Shutdown command to the panel in LP mode */
- 		for_each_dsi_port(port, intel_dsi->ports)
-@@ -615,45 +687,6 @@ static void intel_dsi_pre_disable(struct intel_encoder *encoder,
- 	}
- }
- 
--static void intel_dsi_disable(struct intel_encoder *encoder)
--{
--	struct drm_device *dev = encoder->base.dev;
--	struct drm_i915_private *dev_priv = to_i915(dev);
--	struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base);
--	enum port port;
--	u32 temp;
--
--	DRM_DEBUG_KMS("\n");
--
--	if (is_vid_mode(intel_dsi)) {
--		for_each_dsi_port(port, intel_dsi->ports)
--			wait_for_dsi_fifo_empty(intel_dsi, port);
--
--		intel_dsi_port_disable(encoder);
--		msleep(2);
--	}
--
--	for_each_dsi_port(port, intel_dsi->ports) {
--		/* Panel commands can be sent when clock is in LP11 */
--		I915_WRITE(MIPI_DEVICE_READY(port), 0x0);
--
--		intel_dsi_reset_clocks(encoder, port);
--		I915_WRITE(MIPI_EOT_DISABLE(port), CLOCKSTOP);
--
--		temp = I915_READ(MIPI_DSI_FUNC_PRG(port));
--		temp &= ~VID_MODE_FORMAT_MASK;
--		I915_WRITE(MIPI_DSI_FUNC_PRG(port), temp);
--
--		I915_WRITE(MIPI_DEVICE_READY(port), 0x1);
--	}
--	/* if disable packets are sent before sending shutdown packet then in
--	 * some next enable sequence send turn on packet error is observed */
--	drm_panel_disable(intel_dsi->panel);
--
--	for_each_dsi_port(port, intel_dsi->ports)
--		wait_for_dsi_fifo_empty(intel_dsi, port);
--}
--
- static void intel_dsi_clear_device_ready(struct intel_encoder *encoder)
- {
- 	struct drm_device *dev = encoder->base.dev;
-@@ -696,8 +729,6 @@ static void intel_dsi_clear_device_ready(struct intel_encoder *encoder)
- 		I915_WRITE(MIPI_DEVICE_READY(port), 0x00);
- 		usleep_range(2000, 2500);
- 	}
--
--	intel_disable_dsi_pll(encoder);
- }
- 
- static void intel_dsi_post_disable(struct intel_encoder *encoder,
-@@ -706,13 +737,50 @@ static void intel_dsi_post_disable(struct intel_encoder *encoder,
- {
- 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
- 	struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base);
-+	struct intel_connector *intel_connector = intel_dsi->attached_connector;
-+	enum port port;
-+	u32 temp;
- 
- 	DRM_DEBUG_KMS("\n");
- 
--	intel_dsi_disable(encoder);
-+	if (is_vid_mode(intel_dsi)) {
-+		for_each_dsi_port(port, intel_dsi->ports)
-+			wait_for_dsi_fifo_empty(intel_dsi, port);
-+
-+		intel_dsi_port_disable(encoder);
-+		usleep_range(2000, 5000);
-+	}
-+
-+	intel_panel_disable_backlight(intel_connector);
-+
-+	for_each_dsi_port(port, intel_dsi->ports) {
-+		/* Panel commands can be sent when clock is in LP11 */
-+		I915_WRITE(MIPI_DEVICE_READY(port), 0x0);
- 
-+		intel_dsi_reset_clocks(encoder, port);
-+		I915_WRITE(MIPI_EOT_DISABLE(port), CLOCKSTOP);
-+
-+		temp = I915_READ(MIPI_DSI_FUNC_PRG(port));
-+		temp &= ~VID_MODE_FORMAT_MASK;
-+		I915_WRITE(MIPI_DSI_FUNC_PRG(port), temp);
-+
-+		I915_WRITE(MIPI_DEVICE_READY(port), 0x1);
-+	}
-+
-+	/*
-+	 * if disable packets are sent before sending shutdown packet then in
-+	 * some next enable sequence send turn on packet error is observed
-+	 * XXX spec specifies SHUTDOWN before MIPI_SEQ_DISPLAY_OFF for
-+	 * v3 VBTs, but not for v2 VBTs?
-+	 */
-+	intel_dsi_exec_vbt_sequence(intel_dsi, MIPI_SEQ_TEAR_OFF);
-+	intel_dsi_exec_vbt_sequence(intel_dsi, MIPI_SEQ_DISPLAY_OFF);
-+
-+	/* Transition to LP-00 */
- 	intel_dsi_clear_device_ready(encoder);
- 
-+	intel_disable_dsi_pll(encoder);
-+
- 	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
- 		u32 val;
- 
-@@ -721,11 +789,12 @@ static void intel_dsi_post_disable(struct intel_encoder *encoder,
- 		I915_WRITE(DSPCLK_GATE_D, val);
- 	}
- 
--	drm_panel_unprepare(intel_dsi->panel);
--
--	msleep(intel_dsi->panel_off_delay);
-+	/* Assert reset */
-+	intel_dsi_exec_vbt_sequence(intel_dsi, MIPI_SEQ_ASSERT_RESET);
- 
--	/* Panel Disable over CRC PMIC */
-+	/* Power off, try both CRC pmic gpio and VBT */
-+	intel_dsi_msleep(intel_dsi, intel_dsi->panel_off_delay);
-+	intel_dsi_exec_vbt_sequence(intel_dsi, MIPI_SEQ_POWER_OFF);
- 	if (intel_dsi->gpio_panel)
- 		gpiod_set_value_cansleep(intel_dsi->gpio_panel, 0);
- 
-@@ -733,7 +802,7 @@ static void intel_dsi_post_disable(struct intel_encoder *encoder,
- 	 * FIXME As we do with eDP, just make a note of the time here
- 	 * and perform the wait before the next panel power on.
- 	 */
--	msleep(intel_dsi->panel_pwr_cycle_delay);
-+	intel_dsi_msleep(intel_dsi, intel_dsi->panel_pwr_cycle_delay);
- }
- 
- static bool intel_dsi_get_hw_state(struct intel_encoder *encoder,
-@@ -1376,6 +1445,7 @@ static void intel_dsi_connector_destroy(struct drm_connector *connector)
- 
- 	DRM_DEBUG_KMS("\n");
- 	intel_panel_fini(&intel_connector->panel);
-+	intel_panel_destroy_backlight(connector);
- 	drm_connector_cleanup(connector);
- 	kfree(connector);
- }
-diff --git a/drivers/gpu/drm/i915/intel_dsi.h b/drivers/gpu/drm/i915/intel_dsi.h
-index 5967ea6d6045..548649158abd 100644
---- a/drivers/gpu/drm/i915/intel_dsi.h
-+++ b/drivers/gpu/drm/i915/intel_dsi.h
-@@ -130,6 +130,11 @@ static inline struct intel_dsi *enc_to_intel_dsi(struct drm_encoder *encoder)
- 	return container_of(encoder, struct intel_dsi, base.base);
- }
- 
-+void wait_for_dsi_fifo_empty(struct intel_dsi *intel_dsi, enum port port);
-+
-+void intel_dsi_exec_vbt_sequence(struct intel_dsi *intel_dsi,
-+				 enum mipi_seq seq_id);
-+
- bool intel_dsi_pll_is_enabled(struct drm_i915_private *dev_priv);
- int intel_compute_dsi_pll(struct intel_encoder *encoder,
- 			  struct intel_crtc_state *config);
-diff --git a/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c b/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c
-index 34601574fc6e..a4e3c642b39a 100644
---- a/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c
-+++ b/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c
-@@ -189,6 +189,8 @@ static const u8 *mipi_exec_send_packet(struct intel_dsi *intel_dsi,
- 		break;
- 	}
- 
-+	wait_for_dsi_fifo_empty(intel_dsi, port);
-+
- out:
- 	data += len;
- 
-@@ -353,11 +355,11 @@ static const fn_mipi_elem_exec exec_elem[] = {
-  */
- 
- static const char * const seq_name[] = {
--	[MIPI_SEQ_ASSERT_RESET] = "MIPI_SEQ_ASSERT_RESET",
-+	[MIPI_SEQ_DEASSERT_RESET] = "MIPI_SEQ_DEASSERT_RESET",
- 	[MIPI_SEQ_INIT_OTP] = "MIPI_SEQ_INIT_OTP",
- 	[MIPI_SEQ_DISPLAY_ON] = "MIPI_SEQ_DISPLAY_ON",
- 	[MIPI_SEQ_DISPLAY_OFF]  = "MIPI_SEQ_DISPLAY_OFF",
--	[MIPI_SEQ_DEASSERT_RESET] = "MIPI_SEQ_DEASSERT_RESET",
-+	[MIPI_SEQ_ASSERT_RESET] = "MIPI_SEQ_ASSERT_RESET",
- 	[MIPI_SEQ_BACKLIGHT_ON] = "MIPI_SEQ_BACKLIGHT_ON",
- 	[MIPI_SEQ_BACKLIGHT_OFF] = "MIPI_SEQ_BACKLIGHT_OFF",
- 	[MIPI_SEQ_TEAR_ON] = "MIPI_SEQ_TEAR_ON",
-@@ -374,10 +376,9 @@ static const char *sequence_name(enum mipi_seq seq_id)
- 		return "(unknown)";
- }
- 
--static void generic_exec_sequence(struct drm_panel *panel, enum mipi_seq seq_id)
-+void intel_dsi_exec_vbt_sequence(struct intel_dsi *intel_dsi,
-+				 enum mipi_seq seq_id)
- {
--	struct vbt_panel *vbt_panel = to_vbt_panel(panel);
--	struct intel_dsi *intel_dsi = vbt_panel->intel_dsi;
- 	struct drm_i915_private *dev_priv = to_i915(intel_dsi->base.base.dev);
- 	const u8 *data;
- 	fn_mipi_elem_exec mipi_elem_exec;
-@@ -436,35 +437,6 @@ static void generic_exec_sequence(struct drm_panel *panel, enum mipi_seq seq_id)
- 	}
- }
- 
--static int vbt_panel_prepare(struct drm_panel *panel)
--{
--	generic_exec_sequence(panel, MIPI_SEQ_ASSERT_RESET);
--	generic_exec_sequence(panel, MIPI_SEQ_INIT_OTP);
--
--	return 0;
--}
--
--static int vbt_panel_unprepare(struct drm_panel *panel)
--{
--	generic_exec_sequence(panel, MIPI_SEQ_DEASSERT_RESET);
--
--	return 0;
--}
--
--static int vbt_panel_enable(struct drm_panel *panel)
--{
--	generic_exec_sequence(panel, MIPI_SEQ_DISPLAY_ON);
--
--	return 0;
--}
--
--static int vbt_panel_disable(struct drm_panel *panel)
--{
--	generic_exec_sequence(panel, MIPI_SEQ_DISPLAY_OFF);
--
--	return 0;
--}
--
- static int vbt_panel_get_modes(struct drm_panel *panel)
- {
- 	struct vbt_panel *vbt_panel = to_vbt_panel(panel);
-@@ -488,10 +460,6 @@ static int vbt_panel_get_modes(struct drm_panel *panel)
- }
- 
- static const struct drm_panel_funcs vbt_panel_funcs = {
--	.disable = vbt_panel_disable,
--	.unprepare = vbt_panel_unprepare,
--	.prepare = vbt_panel_prepare,
--	.enable = vbt_panel_enable,
- 	.get_modes = vbt_panel_get_modes,
- };
- 
-diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c
-index be4b4d546fd9..5aac10c3239f 100644
---- a/drivers/gpu/drm/i915/intel_panel.c
-+++ b/drivers/gpu/drm/i915/intel_panel.c
-@@ -32,6 +32,7 @@
- 
- #include <linux/kernel.h>
- #include <linux/moduleparam.h>
-+#include <linux/mfd/intel_soc_pmic.h>
- #include <linux/pwm.h>
- #include "intel_drv.h"
- 
-@@ -544,6 +545,11 @@ static u32 pwm_get_backlight(struct intel_connector *connector)
- 	return DIV_ROUND_UP(duty_ns * 100, CRC_PMIC_PWM_PERIOD_NS);
- }
- 
-+static u32 vlv_pmic_get_backlight(struct intel_connector *connector)
-+{
-+	return intel_soc_pmic_readb(0x4E);
-+}
-+
- static u32 intel_panel_get_backlight(struct intel_connector *connector)
- {
- 	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
-@@ -635,6 +641,11 @@ static void pwm_set_backlight(struct intel_connector *connector, u32 level)
- 	pwm_config(panel->backlight.pwm, duty_ns, CRC_PMIC_PWM_PERIOD_NS);
- }
- 
-+static void vlv_pmic_set_backlight(struct intel_connector *connector, u32 level)
-+{
-+	intel_soc_pmic_writeb(0x4E, level);
-+}
-+
- static void
- intel_panel_actually_set_backlight(struct intel_connector *connector, u32 level)
- {
-@@ -808,6 +819,14 @@ static void pwm_disable_backlight(struct intel_connector *connector)
- 	pwm_disable(panel->backlight.pwm);
- }
- 
-+static void vlv_pmic_disable_backlight(struct intel_connector *connector)
-+{
-+	intel_panel_actually_set_backlight(connector, 0);
-+
-+	intel_soc_pmic_writeb(0x51, 0x00);
-+	intel_soc_pmic_writeb(0x4B, 0x7F);
-+}
-+
- void intel_panel_disable_backlight(struct intel_connector *connector)
- {
- 	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
-@@ -1089,6 +1108,17 @@ static void pwm_enable_backlight(struct intel_connector *connector)
- 	intel_panel_actually_set_backlight(connector, panel->backlight.level);
- }
- 
-+static void vlv_pmic_enable_backlight(struct intel_connector *connector)
-+{
-+	struct intel_panel *panel = &connector->panel;
-+
-+	intel_soc_pmic_writeb(0x4B, 0xFF);
-+	intel_soc_pmic_writeb(0x4E, 0xFF);
-+	intel_soc_pmic_writeb(0x51, 0x01);
-+
-+	intel_panel_actually_set_backlight(connector, panel->backlight.level);
-+}
-+
- void intel_panel_enable_backlight(struct intel_connector *connector)
- {
- 	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
-@@ -1687,6 +1717,20 @@ static int pwm_setup_backlight(struct intel_connector *connector,
- 	return 0;
- }
- 
-+static int vlv_pmic_setup_backlight(struct intel_connector *connector,
-+		enum pipe unused)
-+{
-+	struct intel_panel *panel = &connector->panel;
-+
-+	panel->backlight.present = 1;
-+	panel->backlight.min = 0x00;
-+	panel->backlight.max = 0xFF;
-+	panel->backlight.level = 0x5A;
-+	panel->backlight.enabled = 1;
-+
-+	return 0;
-+}
-+
- int intel_panel_setup_backlight(struct drm_connector *connector, enum pipe pipe)
- {
- 	struct drm_i915_private *dev_priv = to_i915(connector->dev);
-@@ -1694,6 +1738,8 @@ int intel_panel_setup_backlight(struct drm_connector *connector, enum pipe pipe)
- 	struct intel_panel *panel = &intel_connector->panel;
- 	int ret;
- 
-+	intel_backlight_device_register(intel_connector);
-+
- 	if (!dev_priv->vbt.backlight.present) {
- 		if (dev_priv->quirks & QUIRK_BACKLIGHT_PRESENT) {
- 			DRM_DEBUG_KMS("no backlight present per VBT, but present per quirk\n");
-@@ -1783,18 +1829,17 @@ intel_panel_init_backlight_funcs(struct intel_panel *panel)
- 		panel->backlight.hz_to_pwm = pch_hz_to_pwm;
- 	} else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
- 		if (connector->base.connector_type == DRM_MODE_CONNECTOR_DSI) {
--			panel->backlight.setup = pwm_setup_backlight;
--			panel->backlight.enable = pwm_enable_backlight;
--			panel->backlight.disable = pwm_disable_backlight;
--			panel->backlight.set = pwm_set_backlight;
--			panel->backlight.get = pwm_get_backlight;
-+			panel->backlight.setup = vlv_pmic_setup_backlight;
-+			panel->backlight.enable = vlv_pmic_enable_backlight;
-+			panel->backlight.disable = vlv_pmic_disable_backlight;
-+			panel->backlight.set = vlv_pmic_set_backlight;
-+			panel->backlight.get = vlv_pmic_get_backlight;
- 		} else {
- 			panel->backlight.setup = vlv_setup_backlight;
- 			panel->backlight.enable = vlv_enable_backlight;
- 			panel->backlight.disable = vlv_disable_backlight;
- 			panel->backlight.set = vlv_set_backlight;
- 			panel->backlight.get = vlv_get_backlight;
--			panel->backlight.hz_to_pwm = vlv_hz_to_pwm;
- 		}
- 	} else if (IS_GEN4(dev_priv)) {
- 		panel->backlight.setup = i965_setup_backlight;
-diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
-index dbed12c484c9..a2f9a4671193 100644
---- a/drivers/gpu/drm/i915/intel_sprite.c
-+++ b/drivers/gpu/drm/i915/intel_sprite.c
-@@ -81,10 +81,13 @@ int intel_usecs_to_scanlines(const struct drm_display_mode *adjusted_mode,
-  */
- void intel_pipe_update_start(struct intel_crtc *crtc)
- {
-+	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
- 	const struct drm_display_mode *adjusted_mode = &crtc->config->base.adjusted_mode;
- 	long timeout = msecs_to_jiffies_timeout(1);
- 	int scanline, min, max, vblank_start;
- 	wait_queue_head_t *wq = drm_crtc_vblank_waitqueue(&crtc->base);
-+	bool need_vlv_dsi_wa = (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) &&
-+		intel_crtc_has_type(crtc->config, INTEL_OUTPUT_DSI);
- 	DEFINE_WAIT(wait);
- 
- 	vblank_start = adjusted_mode->crtc_vblank_start;
-@@ -136,6 +139,25 @@ void intel_pipe_update_start(struct intel_crtc *crtc)
- 
- 	drm_crtc_vblank_put(&crtc->base);
- 
-+	/*
-+	 * On VLV/CHV DSI the scanline counter would appear to
-+	 * increment approx. 1/3 of a scanline before start of vblank.
-+	 * The registers still get latched at start of vblank however.
-+	 * This means we must not write any registers on the first
-+	 * line of vblank (since not the whole line is actually in
-+	 * vblank). And unfortunately we can't use the interrupt to
-+	 * wait here since it may have already fired before we check
-+	 * the scanline. We could use the frame start interrupt instead
-+	 * since it will fire after the critical scanline, but that would
-+	 * require more changes in the interrupt code. So for now we'll
-+	 * just do the nasty thing and poll for the bad scanline to
-+	 * pass us by.
-+	 *
-+	 * FIXME figure out if BXT+ DSI suffers from this as well
-+	 */
-+	while (need_vlv_dsi_wa && scanline == vblank_start)
-+		scanline = intel_get_crtc_scanline(crtc);
-+
- 	crtc->debug.scanline_start = scanline;
- 	crtc->debug.start_vbl_time = ktime_get();
- 	crtc->debug.start_vbl_count = intel_crtc_get_vblank_counter(crtc);
-diff --git a/drivers/mfd/intel_soc_pmic_core.c b/drivers/mfd/intel_soc_pmic_core.c
-index 12d6ebb4ae5d..8583e77deae0 100644
---- a/drivers/mfd/intel_soc_pmic_core.c
-+++ b/drivers/mfd/intel_soc_pmic_core.c
-@@ -44,6 +44,8 @@ static struct pwm_lookup crc_pwm_lookup[] = {
- 	PWM_LOOKUP("crystal_cove_pwm", 0, "0000:00:02.0", "pwm_backlight", 0, PWM_POLARITY_NORMAL),
- };
- 
-+static struct intel_soc_pmic *pmic_hack = NULL;
-+
- static int intel_soc_pmic_find_gpio_irq(struct device *dev)
- {
- 	struct gpio_desc *desc;
-@@ -77,6 +79,7 @@ static int intel_soc_pmic_i2c_probe(struct i2c_client *i2c,
- 	config = (struct intel_soc_pmic_config *)id->driver_data;
- 
- 	pmic = devm_kzalloc(dev, sizeof(*pmic), GFP_KERNEL);
-+	pmic_hack = pmic;
- 	if (!pmic)
- 		return -ENOMEM;
- 
-@@ -168,6 +171,37 @@ static int intel_soc_pmic_resume(struct device *dev)
- }
- #endif
- 
-+int intel_soc_pmic_readb(int reg)
-+{
-+	int ret;
-+	unsigned int val;
-+
-+	if (!pmic_hack) {
-+		ret = -EIO;
-+	} else {
-+		ret = regmap_read(pmic_hack->regmap, reg, &val);
-+		if (!ret) {
-+			ret = val;
-+		}
-+	}
-+
-+	return ret;
-+}
-+EXPORT_SYMBOL(intel_soc_pmic_readb);
-+
-+int intel_soc_pmic_writeb(int reg, u8 val)
-+{
-+	int ret;
-+
-+	if (!pmic_hack) {
-+		ret = -EIO;
-+	} else {
-+		ret = regmap_write(pmic_hack->regmap, reg, val);
-+	}
-+	return ret;
-+}
-+EXPORT_SYMBOL(intel_soc_pmic_writeb);
-+
- static SIMPLE_DEV_PM_OPS(intel_soc_pmic_pm_ops, intel_soc_pmic_suspend,
- 			 intel_soc_pmic_resume);
- 
-diff --git a/include/linux/mfd/intel_soc_pmic.h b/include/linux/mfd/intel_soc_pmic.h
-index cf619dbeace2..52ad034f606a 100644
---- a/include/linux/mfd/intel_soc_pmic.h
-+++ b/include/linux/mfd/intel_soc_pmic.h
-@@ -29,4 +29,7 @@ struct intel_soc_pmic {
- 	struct device *dev;
- };
- 
-+int intel_soc_pmic_readb(int reg);
-+int intel_soc_pmic_writeb(int reg, u8 val);
-+
- #endif	/* __INTEL_SOC_PMIC_H__ */
diff --git a/modules/hardware/t100ha/sdio.patch b/modules/hardware/t100ha/sdio.patch
deleted file mode 100644
index 3bfef26d..00000000
--- a/modules/hardware/t100ha/sdio.patch
+++ /dev/null
@@ -1,52 +0,0 @@
-Patch from https://github.com/hadess/rtl8723bs/issues/80#issuecomment-252259702
-
-diff --git a/drivers/acpi/acpi_platform.c b/drivers/acpi/acpi_platform.c
-index 159f7f1..2076427 100644
---- a/drivers/acpi/acpi_platform.c
-+++ b/drivers/acpi/acpi_platform.c
-@@ -50,8 +50,10 @@ struct platform_device *acpi_create_platform_device(struct acpi_device *adev)
- 	int count;
- 
- 	/* If the ACPI node already has a physical device attached, skip it. */
--	if (adev->physical_node_count)
--		return NULL;
-+	if (adev->physical_node_count && !(
-+	    !strcmp(acpi_device_hid(adev), "80860F14") &&
-+	    !strcmp(adev->pnp.unique_id, "2")
-+	)) return NULL;
- 
- 	if (!acpi_match_device_ids(adev, forbidden_id_list))
- 		return ERR_PTR(-EINVAL);
-diff --git a/drivers/mmc/host/sdhci-acpi.c b/drivers/mmc/host/sdhci-acpi.c
-index 458ffb7..2807f78 100644
---- a/drivers/mmc/host/sdhci-acpi.c
-+++ b/drivers/mmc/host/sdhci-acpi.c
-@@ -47,6 +47,7 @@
- #endif
- 
- #include "sdhci.h"
-+#include <linux/pci.h>
- 
- enum {
- 	SDHCI_ACPI_SD_CD		= BIT(0),
-@@ -381,6 +382,7 @@ static int sdhci_acpi_probe(struct platform_device *pdev)
- 	struct acpi_device *device, *child;
- 	struct sdhci_acpi_host *c;
- 	struct sdhci_host *host;
-+	struct pci_dev *pcidev = NULL;
- 	struct resource *iomem;
- 	resource_size_t len;
- 	const char *hid;
-@@ -404,6 +406,12 @@ static int sdhci_acpi_probe(struct platform_device *pdev)
- 	hid = acpi_device_hid(device);
- 	uid = device->pnp.unique_id;
- 
-+	/* Workaround for CherryTrail x5-z8xxx: Make sure the SDIO controller
-+	 * doesn't get added via PCI. */
-+	if (!strcmp(hid, "80860F14") && !strcmp(uid, "1") &&
-+	    (pcidev = pci_get_device(0x8086, 0x2280, NULL)) != NULL)
-+		pci_stop_and_remove_bus_device(pcidev);
-+
- 	iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- 	if (!iomem)
- 		return -ENOMEM;
diff --git a/modules/hardware/t100ha/sound.patch b/modules/hardware/t100ha/sound.patch
deleted file mode 100644
index 15a2a883..00000000
--- a/modules/hardware/t100ha/sound.patch
+++ /dev/null
@@ -1,5620 +0,0 @@
-diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
-index bada636d1065..233898ec1fbd 100644
---- a/arch/x86/Kconfig
-+++ b/arch/x86/Kconfig
-@@ -2756,6 +2756,7 @@ config X86_DMA_REMAP
- config PMC_ATOM
- 	def_bool y
-         depends on PCI
-+	select COMMON_CLK
- 
- source "net/Kconfig"
- 
-diff --git a/arch/x86/include/asm/pmc_atom.h b/arch/x86/include/asm/pmc_atom.h
-index aa8744c77c6d..59f95168fa8d 100644
---- a/arch/x86/include/asm/pmc_atom.h
-+++ b/arch/x86/include/asm/pmc_atom.h
-@@ -152,6 +152,12 @@
- #define	SLEEP_TYPE_S5		0x1C00
- #define	SLEEP_ENABLE		0x2000
- 
-+struct pmc_clk {
-+	const char *name;
-+	unsigned long freq;
-+	const char *parent_name;
-+};
-+
- extern int pmc_atom_read(int offset, u32 *value);
- extern int pmc_atom_write(int offset, u32 value);
- 
-diff --git a/arch/x86/platform/atom/pmc_atom.c b/arch/x86/platform/atom/pmc_atom.c
-index 964ff4fc61f9..e2de3e234959 100644
---- a/arch/x86/platform/atom/pmc_atom.c
-+++ b/arch/x86/platform/atom/pmc_atom.c
-@@ -21,6 +21,7 @@
- #include <linux/debugfs.h>
- #include <linux/seq_file.h>
- #include <linux/io.h>
-+#include <linux/platform_device.h>
- 
- #include <asm/pmc_atom.h>
- 
-@@ -37,6 +38,11 @@ struct pmc_reg_map {
- 	const struct pmc_bit_map *pss;
- };
- 
-+struct pmc_data {
-+	const struct pmc_reg_map *map;
-+	const struct pmc_clk *clks;
-+};
-+
- struct pmc_dev {
- 	u32 base_addr;
- 	void __iomem *regmap;
-@@ -50,6 +56,29 @@ struct pmc_dev {
- static struct pmc_dev pmc_device;
- static u32 acpi_base_addr;
- 
-+static const struct pmc_clk byt_clks[] = {
-+	{
-+		.name = "xtal",
-+		.freq = 25000000,
-+		.parent_name = NULL,
-+	},
-+	{
-+		.name = "pll",
-+		.freq = 19200000,
-+		.parent_name = "xtal",
-+	},
-+	{},
-+};
-+
-+static const struct pmc_clk cht_clks[] = {
-+	{
-+		.name = "xtal",
-+		.freq = 19200000,
-+		.parent_name = NULL,
-+	},
-+	{},
-+};
-+
- static const struct pmc_bit_map d3_sts_0_map[] = {
- 	{"LPSS1_F0_DMA",	BIT_LPSS1_F0_DMA},
- 	{"LPSS1_F1_PWM1",	BIT_LPSS1_F1_PWM1},
-@@ -169,6 +198,16 @@ static const struct pmc_reg_map cht_reg_map = {
- 	.pss		= cht_pss_map,
- };
- 
-+static const struct pmc_data byt_data = {
-+	.map = &byt_reg_map,
-+	.clks = byt_clks,
-+};
-+
-+static const struct pmc_data cht_data = {
-+	.map = &cht_reg_map,
-+	.clks = cht_clks,
-+};
-+
- static inline u32 pmc_reg_read(struct pmc_dev *pmc, int reg_offset)
- {
- 	return readl(pmc->regmap + reg_offset);
-@@ -384,8 +423,11 @@ static int pmc_dbgfs_register(struct pmc_dev *pmc)
- 
- static int pmc_setup_dev(struct pci_dev *pdev, const struct pci_device_id *ent)
- {
-+	struct platform_device *clkdev;
- 	struct pmc_dev *pmc = &pmc_device;
--	const struct pmc_reg_map *map = (struct pmc_reg_map *)ent->driver_data;
-+	const struct pmc_data *data = (struct pmc_data *)ent->driver_data;
-+	const struct pmc_reg_map *map = data->map;
-+	const struct pmc_clk *clks = data->clks;
- 	int ret;
- 
- 	/* Obtain ACPI base address */
-@@ -414,6 +456,13 @@ static int pmc_setup_dev(struct pci_dev *pdev, const struct pci_device_id *ent)
- 	if (ret)
- 		dev_warn(&pdev->dev, "debugfs register failed\n");
- 
-+	/* Register platform clocks - PMC_PLT_CLK [5:0] */
-+	clkdev = platform_device_register_data(NULL, "clk-byt-plt", -1,
-+					       &clks, sizeof(clks));
-+	if (IS_ERR(clkdev))
-+		dev_warn(&pdev->dev, "platform clocks register failed: %ld\n",
-+			 PTR_ERR(clkdev));
-+
- 	pmc->init = true;
- 	return ret;
- }
-@@ -424,8 +473,8 @@ static int pmc_setup_dev(struct pci_dev *pdev, const struct pci_device_id *ent)
-  * used by pci_match_id() call below.
-  */
- static const struct pci_device_id pmc_pci_ids[] = {
--	{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_VLV_PMC), (kernel_ulong_t)&byt_reg_map },
--	{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_CHT_PMC), (kernel_ulong_t)&cht_reg_map },
-+	{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_VLV_PMC), (kernel_ulong_t)&byt_data },
-+	{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_CHT_PMC), (kernel_ulong_t)&cht_data },
- 	{ 0, },
- };
- 
-diff --git a/drivers/clk/x86/Makefile b/drivers/clk/x86/Makefile
-index 04781389d0fb..cbdc8cc00060 100644
---- a/drivers/clk/x86/Makefile
-+++ b/drivers/clk/x86/Makefile
-@@ -1,2 +1,3 @@
- clk-x86-lpss-objs		:= clk-lpt.o
- obj-$(CONFIG_X86_INTEL_LPSS)	+= clk-x86-lpss.o
-+obj-$(CONFIG_PMC_ATOM)		+= clk-byt-plt.o
-diff --git a/drivers/clk/x86/clk-byt-plt.c b/drivers/clk/x86/clk-byt-plt.c
-new file mode 100644
-index 000000000000..330cd35d1d27
---- /dev/null
-+++ b/drivers/clk/x86/clk-byt-plt.c
-@@ -0,0 +1,413 @@
-+/*
-+ * Intel Atom platform clocks driver for Baytrail and CherryTrail SoC.
-+ *
-+ * Copyright (C) 2016, Intel Corporation
-+ * Author: Irina Tirdea <irina.tirdea@intel.com>
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms and conditions of the GNU General Public License,
-+ * version 2, as published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope 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/clk-provider.h>
-+#include <linux/err.h>
-+#include <linux/module.h>
-+#include <linux/platform_device.h>
-+#include <linux/slab.h>
-+#include <linux/clkdev.h>
-+
-+#include <asm/pmc_atom.h>
-+
-+#define PLT_CLK_NAME_BASE	"pmc_plt_clk_"
-+#define PLT_CLK_DRIVER_NAME	"clk-byt-plt"
-+
-+#define PMC_CLK_CTL_0		0x60
-+#define PMC_CLK_CTL_SIZE	4
-+#define PMC_CLK_NUM		6
-+#define PMC_MASK_CLK_CTL	GENMASK(1, 0)
-+#define PMC_MASK_CLK_FREQ	BIT(2)
-+#define PMC_CLK_CTL_GATED_ON_D3	0x0
-+#define PMC_CLK_CTL_FORCE_ON	0x1
-+#define PMC_CLK_CTL_FORCE_OFF	0x2
-+#define PMC_CLK_CTL_RESERVED	0x3
-+#define PMC_CLK_FREQ_XTAL	0x0	/* 25 MHz */
-+#define PMC_CLK_FREQ_PLL	0x4	/* 19.2 MHz */
-+
-+struct clk_plt_fixed {
-+	struct clk *clk;
-+	struct clk_lookup *lookup;
-+};
-+
-+struct clk_plt {
-+	struct clk_hw hw;
-+	u8 id;
-+	u32 offset;
-+	struct clk_lookup *lookup;
-+	spinlock_t lock;
-+};
-+
-+#define to_clk_plt(_hw) container_of(_hw, struct clk_plt, hw)
-+
-+struct clk_plt_data {
-+	struct clk_plt_fixed **parents;
-+	u8 nparents;
-+	struct clk *clks[PMC_CLK_NUM];
-+};
-+
-+static inline int plt_reg_to_parent(int reg)
-+{
-+	switch (reg & PMC_MASK_CLK_FREQ) {
-+	case PMC_CLK_FREQ_XTAL:
-+		return 0;	/* index 0 in parents[] */
-+	case PMC_CLK_FREQ_PLL:
-+		return 1;	/* index 1 in parents[] */
-+	}
-+
-+	return 0;
-+}
-+
-+static inline int plt_parent_to_reg(int index)
-+{
-+	switch (index) {
-+	case 0:	/* index 0 in parents[] */
-+		return PMC_CLK_FREQ_XTAL;
-+	case 1:	/* index 0 in parents[] */
-+		return PMC_CLK_FREQ_PLL;
-+	}
-+
-+	return PMC_CLK_FREQ_XTAL;
-+}
-+
-+static inline int plt_reg_to_enabled(int reg)
-+{
-+	switch (reg & PMC_MASK_CLK_CTL) {
-+	case PMC_CLK_CTL_GATED_ON_D3:
-+	case PMC_CLK_CTL_FORCE_ON:
-+		return 1;	/* enabled */
-+	case PMC_CLK_CTL_FORCE_OFF:
-+	case PMC_CLK_CTL_RESERVED:
-+	default:
-+		return 0;	/* disabled */
-+	}
-+}
-+
-+static int plt_pmc_atom_update(struct clk_plt *clk, u32 mask, u32 val)
-+{
-+	int ret;
-+	u32 orig, tmp;
-+	unsigned long flags = 0;
-+
-+	spin_lock_irqsave(&clk->lock, flags);
-+
-+	ret = pmc_atom_read(clk->offset, &orig);
-+	if (ret)
-+		goto out;
-+
-+	tmp = orig & ~mask;
-+	tmp |= val & mask;
-+
-+	if (tmp == orig)
-+		goto out;
-+
-+	ret = pmc_atom_write(clk->offset, tmp);
-+	if (ret)
-+		goto out;
-+
-+out:
-+	spin_unlock_irqrestore(&clk->lock, flags);
-+
-+	return ret;
-+}
-+
-+static int plt_clk_set_parent(struct clk_hw *hw, u8 index)
-+{
-+	struct clk_plt *clk = to_clk_plt(hw);
-+
-+	return plt_pmc_atom_update(clk, PMC_MASK_CLK_FREQ,
-+				   plt_parent_to_reg(index));
-+}
-+
-+static u8 plt_clk_get_parent(struct clk_hw *hw)
-+{
-+	struct clk_plt *clk = to_clk_plt(hw);
-+	u32 value;
-+	int ret;
-+
-+	ret = pmc_atom_read(clk->offset, &value);
-+	if (ret)
-+		return ret;
-+
-+	return plt_reg_to_parent(value);
-+}
-+
-+static int plt_clk_enable(struct clk_hw *hw)
-+{
-+	struct clk_plt *clk = to_clk_plt(hw);
-+
-+	return plt_pmc_atom_update(clk, PMC_MASK_CLK_CTL, PMC_CLK_CTL_FORCE_ON);
-+}
-+
-+static void plt_clk_disable(struct clk_hw *hw)
-+{
-+	struct clk_plt *clk = to_clk_plt(hw);
-+
-+	plt_pmc_atom_update(clk, PMC_MASK_CLK_CTL, PMC_CLK_CTL_FORCE_OFF);
-+}
-+
-+static int plt_clk_is_enabled(struct clk_hw *hw)
-+{
-+	struct clk_plt *clk = to_clk_plt(hw);
-+	u32 value;
-+	int ret;
-+
-+	ret = pmc_atom_read(clk->offset, &value);
-+	if (ret)
-+		return ret;
-+
-+	return plt_reg_to_enabled(value);
-+}
-+
-+static const struct clk_ops plt_clk_ops = {
-+	.enable = plt_clk_enable,
-+	.disable = plt_clk_disable,
-+	.is_enabled = plt_clk_is_enabled,
-+	.get_parent = plt_clk_get_parent,
-+	.set_parent = plt_clk_set_parent,
-+	.determine_rate = __clk_mux_determine_rate,
-+};
-+
-+static struct clk *plt_clk_register(struct platform_device *pdev, int id,
-+				    const char **parent_names, int num_parents)
-+{
-+	struct clk_plt *pclk;
-+	struct clk *clk;
-+	struct clk_init_data init;
-+	int ret = 0;
-+
-+	pclk = devm_kzalloc(&pdev->dev, sizeof(*pclk), GFP_KERNEL);
-+	if (!pclk)
-+		return ERR_PTR(-ENOMEM);
-+
-+	init.name =  kasprintf(GFP_KERNEL, "%s%d", PLT_CLK_NAME_BASE, id);
-+	init.ops = &plt_clk_ops;
-+	init.flags = 0;
-+	init.parent_names = parent_names;
-+	init.num_parents = num_parents;
-+
-+	pclk->hw.init = &init;
-+	pclk->id = id;
-+	pclk->offset = PMC_CLK_CTL_0 + id * PMC_CLK_CTL_SIZE;
-+	spin_lock_init(&pclk->lock);
-+
-+	clk = clk_register(&pdev->dev, &pclk->hw);
-+	if (IS_ERR(clk)) {
-+		ret = PTR_ERR(clk);
-+		goto err_free_pclk;
-+	}
-+
-+	pclk->lookup = clkdev_create(clk, init.name, NULL);
-+	if (!pclk->lookup) {
-+		ret = -ENOMEM;
-+		goto err_clk_unregister;
-+	}
-+
-+	kfree(init.name);
-+
-+	return clk;
-+
-+err_clk_unregister:
-+	clk_unregister(clk);
-+err_free_pclk:
-+	kfree(init.name);
-+	return ERR_PTR(ret);
-+}
-+
-+static void plt_clk_unregister(struct clk *clk)
-+{
-+	struct clk_plt *pclk;
-+	struct clk_hw *hw;
-+
-+	hw = __clk_get_hw(clk);
-+	if (!hw)
-+		return;
-+
-+	pclk = to_clk_plt(hw);
-+
-+	clkdev_drop(pclk->lookup);
-+	clk_unregister(clk);
-+}
-+
-+static struct clk_plt_fixed *plt_clk_register_fixed_rate(struct platform_device *pdev,
-+						 const char *name,
-+						 const char *parent_name,
-+						 unsigned long fixed_rate)
-+{
-+	struct clk_plt_fixed *pclk;
-+	int ret = 0;
-+
-+	pclk = devm_kzalloc(&pdev->dev, sizeof(*pclk), GFP_KERNEL);
-+	if (!pclk)
-+		return ERR_PTR(-ENOMEM);
-+
-+	pclk->clk = clk_register_fixed_rate(&pdev->dev, name, parent_name,
-+					    0, fixed_rate);
-+	if (IS_ERR(pclk->clk)) {
-+		ret = PTR_ERR(pclk->clk);
-+		return ERR_PTR(ret);
-+	}
-+
-+	pclk->lookup = clkdev_create(pclk->clk, name, NULL);
-+	if (!pclk->lookup) {
-+		ret = -ENOMEM;
-+		goto err_clk_unregister;
-+	}
-+
-+	return pclk;
-+
-+err_clk_unregister:
-+	clk_unregister_fixed_rate(pclk->clk);
-+	return ERR_PTR(ret);
-+}
-+
-+static void plt_clk_unregister_fixed_rate(struct clk_plt_fixed *pclk)
-+{
-+	clkdev_drop(pclk->lookup);
-+	clk_unregister_fixed_rate(pclk->clk);
-+}
-+
-+static const char **plt_clk_register_parents(struct platform_device *pdev,
-+					     struct clk_plt_data *data)
-+{
-+	struct pmc_clk **pclks, *clks;
-+	const char **parent_names;
-+	int i, err;
-+
-+	data->nparents = 0;
-+	pclks = dev_get_platdata(&pdev->dev);
-+	if (!pclks)
-+		return NULL;
-+
-+	clks = *pclks;
-+	while (clks[data->nparents].name)
-+		data->nparents++;
-+
-+	data->parents = devm_kzalloc(&pdev->dev,
-+				     sizeof(*data->parents) * data->nparents,
-+				     GFP_KERNEL);
-+	if (!data->parents) {
-+		err = -ENOMEM;
-+		goto err_out;
-+	}
-+
-+	parent_names = kcalloc(data->nparents, sizeof(*parent_names),
-+			       GFP_KERNEL);
-+	if (!parent_names) {
-+		err = -ENOMEM;
-+		goto err_out;
-+	}
-+
-+	for (i = 0; i < data->nparents; i++) {
-+		data->parents[i] =
-+			plt_clk_register_fixed_rate(pdev, clks[i].name,
-+						    clks[i].parent_name,
-+						    clks[i].freq);
-+		if (IS_ERR(data->parents[i])) {
-+			err = PTR_ERR(data->parents[i]);
-+			goto err_unreg;
-+		}
-+		parent_names[i] = kstrdup_const(clks[i].name, GFP_KERNEL);
-+	}
-+
-+	return parent_names;
-+
-+err_unreg:
-+	for (i--; i >= 0; i--) {
-+		plt_clk_unregister_fixed_rate(data->parents[i]);
-+		kfree_const(parent_names[i]);
-+	}
-+	kfree(parent_names);
-+err_out:
-+	data->nparents = 0;
-+	return ERR_PTR(err);
-+}
-+
-+static void plt_clk_unregister_parents(struct clk_plt_data *data)
-+{
-+	int i;
-+
-+	for (i = 0; i < data->nparents; i++)
-+		plt_clk_unregister_fixed_rate(data->parents[i]);
-+}
-+
-+static int plt_clk_probe(struct platform_device *pdev)
-+{
-+	struct clk_plt_data *data;
-+	int i, err;
-+	const char **parent_names;
-+
-+	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
-+	if (!data)
-+		return -ENOMEM;
-+
-+	parent_names = plt_clk_register_parents(pdev, data);
-+	if (IS_ERR(parent_names))
-+		return PTR_ERR(parent_names);
-+
-+	for (i = 0; i < PMC_CLK_NUM; i++) {
-+		data->clks[i] = plt_clk_register(pdev, i, parent_names,
-+						 data->nparents);
-+		if (IS_ERR(data->clks[i])) {
-+			err = PTR_ERR(data->clks[i]);
-+			goto err_unreg_clk_plt;
-+		}
-+	}
-+
-+	for (i = 0; i < data->nparents; i++)
-+		kfree_const(parent_names[i]);
-+	kfree(parent_names);
-+
-+	dev_set_drvdata(&pdev->dev, data);
-+	return 0;
-+
-+err_unreg_clk_plt:
-+	for (i--; i >= 0; i--)
-+		plt_clk_unregister(data->clks[i]);
-+	plt_clk_unregister_parents(data);
-+	for (i = 0; i < data->nparents; i++)
-+		kfree_const(parent_names[i]);
-+	kfree(parent_names);
-+	return err;
-+}
-+
-+static int plt_clk_remove(struct platform_device *pdev)
-+{
-+	struct clk_plt_data *data;
-+	int i;
-+
-+	data = dev_get_drvdata(&pdev->dev);
-+	if (!data)
-+		return 0;
-+
-+	for (i = 0; i < PMC_CLK_NUM; i++)
-+		plt_clk_unregister(data->clks[i]);
-+	plt_clk_unregister_parents(data);
-+	return 0;
-+}
-+
-+static struct platform_driver plt_clk_driver = {
-+	.driver = {
-+		.name = PLT_CLK_DRIVER_NAME,
-+	},
-+	.probe = plt_clk_probe,
-+	.remove = plt_clk_remove,
-+};
-+module_platform_driver(plt_clk_driver);
-+
-+MODULE_DESCRIPTION("Intel Atom platform clocks driver");
-+MODULE_AUTHOR("Irina Tirdea <irina.tirdea@intel.com>");
-+MODULE_LICENSE("GPL v2");
-diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
-index c67667bb970f..655e2f4d1dd0 100644
---- a/sound/soc/codecs/Kconfig
-+++ b/sound/soc/codecs/Kconfig
-@@ -61,6 +61,7 @@ config SND_SOC_ALL_CODECS
- 	select SND_SOC_CS47L24 if MFD_CS47L24
- 	select SND_SOC_CS53L30 if I2C
- 	select SND_SOC_CX20442 if TTY
-+	select SND_SOC_CX2072X if I2C
- 	select SND_SOC_DA7210 if SND_SOC_I2C_AND_SPI
- 	select SND_SOC_DA7213 if I2C
- 	select SND_SOC_DA7218 if I2C
-@@ -478,6 +479,10 @@ config SND_SOC_CX20442
- 	tristate
- 	depends on TTY
- 
-+config SND_SOC_CX2072X
-+	tristate "Conexant CX2072X CODEC"
-+	depends on I2C
-+	
- config SND_SOC_JZ4740_CODEC
- 	select REGMAP_MMIO
- 	tristate
-diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
-index 958cd4912fbc..1dded20a4d84 100644
---- a/sound/soc/codecs/Makefile
-+++ b/sound/soc/codecs/Makefile
-@@ -54,6 +54,7 @@ snd-soc-cs4349-objs := cs4349.o
- snd-soc-cs47l24-objs := cs47l24.o
- snd-soc-cs53l30-objs := cs53l30.o
- snd-soc-cx20442-objs := cx20442.o
-+snd-soc-cx2072x-objs := cx2072x.o
- snd-soc-da7210-objs := da7210.o
- snd-soc-da7213-objs := da7213.o
- snd-soc-da7218-objs := da7218.o
-@@ -279,6 +280,7 @@ obj-$(CONFIG_SND_SOC_CS4349)	+= snd-soc-cs4349.o
- obj-$(CONFIG_SND_SOC_CS47L24)	+= snd-soc-cs47l24.o
- obj-$(CONFIG_SND_SOC_CS53L30)	+= snd-soc-cs53l30.o
- obj-$(CONFIG_SND_SOC_CX20442)	+= snd-soc-cx20442.o
-+obj-$(CONFIG_SND_SOC_CX2072X)	+= snd-soc-cx2072x.o
- obj-$(CONFIG_SND_SOC_DA7210)	+= snd-soc-da7210.o
- obj-$(CONFIG_SND_SOC_DA7213)	+= snd-soc-da7213.o
- obj-$(CONFIG_SND_SOC_DA7218)	+= snd-soc-da7218.o
-diff --git a/sound/soc/codecs/cx2072x.c b/sound/soc/codecs/cx2072x.c
-new file mode 100644
-index 000000000000..aaec3722854c
---- /dev/null
-+++ b/sound/soc/codecs/cx2072x.c
-@@ -0,0 +1,2124 @@
-+/*
-+ * ALSA SoC CX20721/cx20723 Solana codec driver
-+ * Copyright:   (C) 2016 Conexant Systems, Inc.
-+ *
-+ * 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.
-+ *
-+ ************************************************************************/
-+#define DEBUG
-+/*#define INTEL_MCLK_CONTROL*/
-+
-+/*#define ENABLE_MIC_POP_WA*/
-+
-+#include <linux/module.h>
-+#include <linux/moduleparam.h>
-+#include <linux/init.h>
-+#include <linux/delay.h>
-+#include <linux/pm.h>
-+#include <linux/platform_device.h>
-+#include <sound/core.h>
-+#include <sound/pcm.h>
-+#include <sound/pcm_params.h>
-+#include <sound/soc.h>
-+#include <sound/soc-dapm.h>
-+#include <sound/initval.h>
-+#include <sound/tlv.h>
-+#include <linux/of_gpio.h>
-+#include <linux/gpio.h>
-+#include <sound/jack.h>
-+#include <linux/slab.h>
-+#include <linux/i2c.h>
-+#include <linux/firmware.h>
-+#include <linux/regmap.h>
-+#include <linux/proc_fs.h>
-+#include <linux/interrupt.h>
-+#include <linux/irq.h>
-+#include <linux/acpi.h>
-+#ifdef INTEL_MCLK_CONTROL
-+#include <linux/vlv2_plat_clock.h>
-+#endif
-+#include "cx2072x.h"
-+
-+#define SUPPORT_RKI2S_FORMAT
-+#define CX2072X_REV_A2 0x00100002
-+#define CXDBG_REG_DUMP
-+
-+/*FIXME: need to move the EQ/DRC setting to device tree*/
-+static unsigned char cx2072x_eq_coeff_array[MAX_EQ_BAND][MAC_EQ_COEFF] = {
-+	{0x77, 0x26, 0x13, 0xb3, 0x76, 0x26, 0x0a, 0x3d, 0xd4, 0xe2, 0x04},
-+	{0x97, 0x3e, 0xb3, 0x86, 0xc2, 0x3b, 0x4d, 0x79, 0xa7, 0xc5, 0x03},
-+	{0x0f, 0x39, 0x76, 0xa3, 0x1b, 0x2b, 0x89, 0x5c, 0xd7, 0xdb, 0x03},
-+	{0x21, 0x46, 0xfe, 0xa6, 0xec, 0x24, 0x01, 0x59, 0xf4, 0xd4, 0x03},
-+	{0xe9, 0x78, 0x9c, 0xb0, 0x8a, 0x56, 0x64, 0x4f, 0x8d, 0xb0, 0x02},
-+	{0x60, 0x6e, 0x57, 0xee, 0xec, 0x18, 0xa8, 0x11, 0xb5, 0xf8, 0x02},
-+	{0x5a, 0x14, 0x68, 0xe9, 0x1d, 0x06, 0xb9, 0x5f, 0x68, 0xdc, 0x03},
-+};
-+
-+static unsigned char cx2072x_drc_array[MAX_DRC_REGS] = {
-+	0x65, 0x55, 0x3C, 0x01, 0x05, 0x39, 0x76, 0x1A, 0x00
-+};
-+
-+/*#define CXDBG_REG_DUMP*/
-+#ifdef CXDBG_REG_DUMP
-+
-+#define CX2072X_FORMATS (SNDRV_PCM_FMTBIT_S24_LE \
-+	| SNDRV_PCM_FMTBIT_S16_LE)
-+#define BITS_PER_SLOT 8
-+
-+#define _REG(_name_, _size_, _access_, _volatile_) { \
-+	 #_name_, _name_, _size_ | _access_ | _volatile_}
-+
-+struct CX2072X_REG_DEF {
-+	const char  *name;
-+	unsigned int addr;
-+	unsigned int attr;
-+};
-+
-+#define WO 0x0100
-+#define RO 0x0200
-+#define RW 0x0300
-+#define VO 0x8000
-+#define NV 0x0000
-+#define REGISTER_SIZE_MASK 0x000F
-+#define REGISTER_ASSCESS_MASK 0x0F00
-+#define REGISTER_VOLATILE_MASK 0x8000
-+#define UNAVAILABLE 0
-+
-+
-+static const struct CX2072X_REG_DEF cx2072x_regs[] = {
-+	_REG(CX2072X_VENDOR_ID,                      4, RO, VO),
-+	_REG(CX2072X_REVISION_ID,                    4, RO, VO),
-+	_REG(CX2072X_CURRENT_BCLK_FREQUENCY,         4, RO, VO),
-+	_REG(CX2072X_AFG_POWER_STATE,                1, RW, NV),
-+	_REG(CX2072X_UM_RESPONSE,                    1, RW, NV),
-+	_REG(CX2072X_GPIO_DATA,                      1, RW, NV),
-+	_REG(CX2072X_GPIO_ENABLE,                    1, RW, NV),
-+	_REG(CX2072X_GPIO_DIRECTION,                 1, RW, NV),
-+	_REG(CX2072X_GPIO_WAKE,                      1, RW, NV),
-+	_REG(CX2072X_GPIO_UM_ENABLE,                 1, RW, NV),
-+	_REG(CX2072X_GPIO_STICKY_MASK,               1, RW, NV),
-+	_REG(CX2072X_AFG_FUNCTION_RESET,             1, WO, NV),
-+	_REG(CX2072X_DAC1_CONVERTER_FORMAT,          2, RW, NV),
-+	_REG(CX2072X_DAC1_AMP_GAIN_RIGHT,            1, RW, NV),
-+	_REG(CX2072X_DAC1_AMP_GAIN_LEFT,             1, RW, NV),
-+	_REG(CX2072X_DAC1_POWER_STATE,               1, RW, NV),
-+	_REG(CX2072X_DAC1_CONVERTER_STREAM_CHANNEL,  1, RW, NV),
-+	_REG(CX2072X_DAC1_EAPD_ENABLE,               1, RW, NV),
-+	_REG(CX2072X_DAC2_CONVERTER_FORMAT,          2, RW, NV),
-+	_REG(CX2072X_DAC2_AMP_GAIN_RIGHT,            1, RW, NV),
-+	_REG(CX2072X_DAC2_AMP_GAIN_LEFT,             1, RW, NV),
-+	_REG(CX2072X_DAC2_POWER_STATE,               1, RW, NV),
-+	_REG(CX2072X_DAC2_CONVERTER_STREAM_CHANNEL,  1, RW, NV),
-+	_REG(CX2072X_ADC1_CONVERTER_FORMAT,          2, RW, NV),
-+	_REG(CX2072X_ADC1_AMP_GAIN_RIGHT_0,          1, RW, NV),
-+	_REG(CX2072X_ADC1_AMP_GAIN_LEFT_0,           1, RW, NV),
-+	_REG(CX2072X_ADC1_AMP_GAIN_RIGHT_1,          1, RW, NV),
-+	_REG(CX2072X_ADC1_AMP_GAIN_LEFT_1,           1, RW, NV),
-+	_REG(CX2072X_ADC1_AMP_GAIN_RIGHT_2,          1, RW, NV),
-+	_REG(CX2072X_ADC1_AMP_GAIN_LEFT_2,           1, RW, NV),
-+	_REG(CX2072X_ADC1_AMP_GAIN_RIGHT_3,          1, RW, NV),
-+	_REG(CX2072X_ADC1_AMP_GAIN_LEFT_3,           1, RW, NV),
-+	_REG(CX2072X_ADC1_AMP_GAIN_RIGHT_4,          1, RW, NV),
-+	_REG(CX2072X_ADC1_AMP_GAIN_LEFT_4,           1, RW, NV),
-+	_REG(CX2072X_ADC1_AMP_GAIN_RIGHT_5,          1, RW, NV),
-+	_REG(CX2072X_ADC1_AMP_GAIN_LEFT_5,           1, RW, NV),
-+	_REG(CX2072X_ADC1_AMP_GAIN_RIGHT_6,          1, RW, NV),
-+	_REG(CX2072X_ADC1_AMP_GAIN_LEFT_6,           1, RW, NV),
-+	_REG(CX2072X_ADC1_CONNECTION_SELECT_CONTROL, 1, RW, NV),
-+	_REG(CX2072X_ADC1_POWER_STATE,               1, RW, NV),
-+	_REG(CX2072X_ADC1_CONVERTER_STREAM_CHANNEL,  1, RW, NV),
-+	_REG(CX2072X_ADC2_CONVERTER_FORMAT,          2, WO, NV),
-+	_REG(CX2072X_ADC2_AMP_GAIN_RIGHT_0,          1, RW, NV),
-+	_REG(CX2072X_ADC2_AMP_GAIN_LEFT_0,           1, RW, NV),
-+	_REG(CX2072X_ADC2_AMP_GAIN_RIGHT_1,          1, RW, NV),
-+	_REG(CX2072X_ADC2_AMP_GAIN_LEFT_1,           1, RW, NV),
-+	_REG(CX2072X_ADC2_AMP_GAIN_RIGHT_2,          1, RW, NV),
-+	_REG(CX2072X_ADC2_AMP_GAIN_LEFT_2,           1, RW, NV),
-+	_REG(CX2072X_ADC2_CONNECTION_SELECT_CONTROL, 1, RW, NV),
-+	_REG(CX2072X_ADC2_POWER_STATE,               1, RW, NV),
-+	_REG(CX2072X_ADC2_CONVERTER_STREAM_CHANNEL,  1, RW, NV),
-+	_REG(CX2072X_PORTA_CONNECTION_SELECT_CTRL,   1, RW, NV),
-+	_REG(CX2072X_PORTA_POWER_STATE,              1, RW, NV),
-+	_REG(CX2072X_PORTA_PIN_CTRL,                 1, RW, NV),
-+	_REG(CX2072X_PORTA_UNSOLICITED_RESPONSE,     1, RW, NV),
-+	_REG(CX2072X_PORTA_PIN_SENSE,                4, RO, VO),
-+	_REG(CX2072X_PORTA_EAPD_BTL,                 1, RW, NV),
-+	_REG(CX2072X_PORTB_POWER_STATE,              1, RW, NV),
-+	_REG(CX2072X_PORTB_PIN_CTRL,                 1, RW, NV),
-+	_REG(CX2072X_PORTB_UNSOLICITED_RESPONSE,     1, RW, NV),
-+	_REG(CX2072X_PORTB_PIN_SENSE,                4, RO, VO),
-+	_REG(CX2072X_PORTB_EAPD_BTL,                 1, RW, NV),
-+	_REG(CX2072X_PORTB_GAIN_RIGHT,               1, RW, NV),
-+	_REG(CX2072X_PORTB_GAIN_LEFT,                1, RW, NV),
-+	_REG(CX2072X_PORTC_POWER_STATE,              1, RW, NV),
-+	_REG(CX2072X_PORTC_PIN_CTRL,                 1, RW, NV),
-+	_REG(CX2072X_PORTC_GAIN_RIGHT,               1, RW, NV),
-+	_REG(CX2072X_PORTC_GAIN_LEFT,                1, RW, NV),
-+	_REG(CX2072X_PORTD_POWER_STATE,              1, RW, NV),
-+	_REG(CX2072X_PORTD_PIN_CTRL,                 1, RW, NV),
-+	_REG(CX2072X_PORTD_UNSOLICITED_RESPONSE,     1, RW, NV),
-+	_REG(CX2072X_PORTD_PIN_SENSE,                4, RO, VO),
-+	_REG(CX2072X_PORTD_GAIN_RIGHT,               1, RW, NV),
-+	_REG(CX2072X_PORTD_GAIN_LEFT,                1, RW, NV),
-+	_REG(CX2072X_PORTE_CONNECTION_SELECT_CTRL,   1, RW, NV),
-+	_REG(CX2072X_PORTE_POWER_STATE,              1, RW, NV),
-+	_REG(CX2072X_PORTE_PIN_CTRL,                 1, RW, NV),
-+	_REG(CX2072X_PORTE_UNSOLICITED_RESPONSE,     1, RW, NV),
-+	_REG(CX2072X_PORTE_PIN_SENSE,                4, RO, VO),
-+	_REG(CX2072X_PORTE_EAPD_BTL,                 1, RW, NV),
-+	_REG(CX2072X_PORTE_GAIN_RIGHT,               1, RW, NV),
-+	_REG(CX2072X_PORTE_GAIN_LEFT,                1, RW, NV),
-+	_REG(CX2072X_PORTF_POWER_STATE,              1, RW, NV),
-+	_REG(CX2072X_PORTF_PIN_CTRL,                 1, RW, NV),
-+	_REG(CX2072X_PORTF_UNSOLICITED_RESPONSE,     1, RW, NV),
-+	_REG(CX2072X_PORTF_PIN_SENSE,                4, RO, VO),
-+	_REG(CX2072X_PORTF_GAIN_RIGHT,               1, RW, NV),
-+	_REG(CX2072X_PORTF_GAIN_LEFT,                1, RW, NV),
-+	_REG(CX2072X_PORTG_POWER_STATE,              1, RW, NV),
-+	_REG(CX2072X_PORTG_PIN_CTRL,                 1, RW, NV),
-+	_REG(CX2072X_PORTG_CONNECTION_SELECT_CTRL,   1, RW, NV),
-+	_REG(CX2072X_PORTG_EAPD_BTL,                 1, RW, NV),
-+	_REG(CX2072X_PORTM_POWER_STATE,              1, RW, NV),
-+	_REG(CX2072X_PORTM_PIN_CTRL,                 1, RW, NV),
-+	_REG(CX2072X_PORTM_CONNECTION_SELECT_CTRL,   1, RW, NV),
-+	_REG(CX2072X_PORTM_EAPD_BTL,                 1, RW, NV),
-+	_REG(CX2072X_MIXER_POWER_STATE,              1, RW, NV),
-+	_REG(CX2072X_MIXER_GAIN_RIGHT_0,             1, RW, NV),
-+	_REG(CX2072X_MIXER_GAIN_LEFT_0,              1, WO, NV),
-+	_REG(CX2072X_MIXER_GAIN_RIGHT_1,             1, RW, NV),
-+	_REG(CX2072X_MIXER_GAIN_LEFT_1,              1, RW, NV),
-+	_REG(CX2072X_EQ_ENABLE_BYPASS,               2, RW, NV),
-+	_REG(CX2072X_EQ_B0_COEFF,                    2, WO, VO),
-+	_REG(CX2072X_EQ_B1_COEFF,                    2, WO, VO),
-+	_REG(CX2072X_EQ_B2_COEFF,                    2, WO, VO),
-+	_REG(CX2072X_EQ_A1_COEFF,                    2, WO, VO),
-+	_REG(CX2072X_EQ_A2_COEFF,                    2, WO, VO),
-+	_REG(CX2072X_EQ_G_COEFF,                     1, WO, VO),
-+	_REG(CX2072X_EQ_BAND,                        1, WO, VO),
-+	_REG(CX2072X_SPKR_DRC_ENABLE_STEP,           1, RW, NV),
-+	_REG(CX2072X_SPKR_DRC_CONTROL,               4, RW, NV),
-+	_REG(CX2072X_SPKR_DRC_TEST,                  4, RW, NV),
-+	_REG(CX2072X_DIGITAL_BIOS_TEST0,             4, RW, NV),
-+	_REG(CX2072X_DIGITAL_BIOS_TEST2,             4, RW, NV),
-+	_REG(CX2072X_I2SPCM_CONTROL1,                4, RW, NV),
-+	_REG(CX2072X_I2SPCM_CONTROL2,                4, RW, NV),
-+	_REG(CX2072X_I2SPCM_CONTROL3,                4, RW, NV),
-+	_REG(CX2072X_I2SPCM_CONTROL4,                4, RW, NV),
-+	_REG(CX2072X_I2SPCM_CONTROL5,                4, RW, NV),
-+	_REG(CX2072X_I2SPCM_CONTROL6,                4, RW, NV),
-+	_REG(CX2072X_UM_INTERRUPT_CRTL_E,            4, RW, NV),
-+	_REG(CX2072X_CODEC_TEST20,                   2, RW, NV),
-+	_REG(CX2072X_CODEC_TEST26,                   2, RW, NV),
-+	_REG(CX2072X_ANALOG_TEST4,                   2, RW, NV),
-+	_REG(CX2072X_ANALOG_TEST5,                   2, RW, NV),
-+	_REG(CX2072X_ANALOG_TEST6,                   2, WO, NV),
-+	_REG(CX2072X_ANALOG_TEST7,                   2, RW, NV),
-+	_REG(CX2072X_ANALOG_TEST8,                   2, RW, NV),
-+	_REG(CX2072X_ANALOG_TEST9,                   2, RW, NV),
-+	_REG(CX2072X_ANALOG_TEST10,                  2, RW, NV),
-+	_REG(CX2072X_ANALOG_TEST11,                  2, RW, NV),
-+	_REG(CX2072X_ANALOG_TEST12,                  2, RW, NV),
-+	_REG(CX2072X_ANALOG_TEST13,                  2, RW, NV),
-+	_REG(CX2072X_DIGITAL_TEST0,                  2, RW, NV),
-+	_REG(CX2072X_DIGITAL_TEST1,                  2, RW, NV),
-+	_REG(CX2072X_DIGITAL_TEST11,                 2, RW, NV),
-+	_REG(CX2072X_DIGITAL_TEST12,                 2, RW, NV),
-+	_REG(CX2072X_DIGITAL_TEST15,                 2, RW, NV),
-+	_REG(CX2072X_DIGITAL_TEST16,                 2, RW, NV),
-+	_REG(CX2072X_DIGITAL_TEST17,                 2, RW, NV),
-+	_REG(CX2072X_DIGITAL_TEST18,                 2, RW, NV),
-+	_REG(CX2072X_DIGITAL_TEST19,                 2, RW, NV),
-+	_REG(CX2072X_DIGITAL_TEST20,                 2, RW, NV),
-+};
-+#endif
-+
-+/* codec private data */
-+struct cx2072x_priv {
-+	struct regmap *regmap;
-+	unsigned int mclk;
-+	struct device *dev;
-+	struct snd_soc_codec *codec;
-+	struct snd_soc_dai_driver *dai_drv;
-+	int is_biason;
-+	struct snd_soc_jack *jack;
-+	bool jack_detecting;
-+	bool jack_mic;
-+	int jack_mode;
-+	int jack_flips;
-+	unsigned int jack_state;
-+	int audsmt_enable;
-+	struct mutex lock;
-+	unsigned int bclk_ratio;
-+
-+#ifdef ENABLE_MIC_POP_WA
-+	struct delayed_work mic_pop_workq;
-+#endif
-+
-+	bool plbk_dsp_en;
-+	bool plbk_dsp_changed;
-+	bool plbk_dsp_init;
-+	bool pll_changed;
-+	bool i2spcm_changed;
-+	int sample_size; /*used for non-PCM mode*/
-+	int frame_size; /*used for non-PCM mode*/
-+	int sample_rate;
-+	unsigned int dai_fmt;
-+	int tdm_rx_mask;
-+	int tdm_tx_mask;
-+	int tdm_slot_width;
-+	int tdm_slots;
-+	u32 rev_id;
-+};
-+
-+/*
-+* DAC/ADC Volume
-+*
-+* max : 74 : 0 dB
-+*       ( in 1 dB  step )
-+* min : 0 : -74 dB
-+*/
-+static const DECLARE_TLV_DB_SCALE(adc_tlv, -7400, 100, 0);
-+static const DECLARE_TLV_DB_SCALE(dac_tlv, -7400, 100, 0);
-+static const DECLARE_TLV_DB_SCALE(boost_tlv, 0, 1200, 0);
-+
-+#define get_cx2072x_priv(_codec_) \
-+	((struct cx2072x_priv *) snd_soc_codec_get_drvdata(_codec_))
-+
-+/* Lookup table for PRE_DIV*/
-+static struct {
-+	unsigned int mclk;
-+	unsigned int div;
-+} MCLK_PRE_DIV[] = {
-+	{ 6144000, 1 },
-+	{ 12288000, 2 },
-+	{ 19200000, 3 },
-+	{ 26000000, 4 },
-+	{ 28224000, 5 },
-+	{ 36864000, 6 },
-+	{ 36864000, 7 },/* Don't use div 7*/
-+	{ 48000000, 8 },
-+	{ 49152000, 8 },
-+};
-+
-+/*
-+ * cx2072x register cache.
-+ */
-+static const struct reg_default cx2072x_reg_defaults[] = {
-+	{ 0x0414, 0x00000003 },	/*2072X_AFG_POWER_STATE */
-+	{ 0x0420, 0x00000000 },	/*2072X_UM_RESPONSE */
-+	{ 0x0454, 0x00000000 },	/*2072X_GPIO_DATA */
-+	{ 0x0458, 0x00000000 },	/*2072X_GPIO_ENABLE */
-+	{ 0x045c, 0x00000000 },	/*2072X_GPIO_DIRECTION */
-+	{ 0x0460, 0x00000000 },	/*2072X_GPIO_WAKE */
-+	{ 0x0464, 0x00000000 },	/*2072X_GPIO_UM_ENABLE */
-+	{ 0x0468, 0x00000000 },	/*2072X_GPIO_STICKY_MASK */
-+	{ 0x43c8, 0x00000031 },	/*2072X_DAC1_CONVERTER_FORMAT */
-+	{ 0x41c0, 0x0000004a },	/*2072X_DAC1_AMP_GAIN_RIGHT */
-+	{ 0x41e0, 0x0000004a },	/*2072X_DAC1_AMP_GAIN_LEFT */
-+	{ 0x4014, 0x00000433 },	/*2072X_DAC1_POWER_STATE */
-+	{ 0x4018, 0x00000000 },	/*2072X_DAC1_CONVERTER_STREAM_CHANNEL */
-+	{ 0x4030, 0x00000000 },	/*2072X_DAC1_EAPD_ENABLE */
-+	{ 0x47c8, 0x00000031 },	/*2072X_DAC2_CONVERTER_FORMAT */
-+	{ 0x45c0, 0x0000004a },	/*2072X_DAC2_AMP_GAIN_RIGHT */
-+	{ 0x45e0, 0x0000004a },	/*2072X_DAC2_AMP_GAIN_LEFT */
-+	{ 0x4414, 0x00000433 },	/*2072X_DAC2_POWER_STATE */
-+	{ 0x4418, 0x00000000 },	/*2072X_DAC2_CONVERTER_STREAM_CHANNEL */
-+	{ 0x4fc8, 0x00000031 },	/*2072X_ADC1_CONVERTER_FORMAT */
-+	{ 0x4d80, 0x0000004a },	/*2072X_ADC1_AMP_GAIN_RIGHT_0 */
-+	{ 0x4da0, 0x0000004a },	/*2072X_ADC1_AMP_GAIN_LEFT_0  */
-+	{ 0x4d84, 0x0000004a },	/*2072X_ADC1_AMP_GAIN_RIGHT_1 */
-+	{ 0x4da4, 0x0000004a },	/*2072X_ADC1_AMP_GAIN_LEFT_1 */
-+	{ 0x4d88, 0x0000004a },	/*2072X_ADC1_AMP_GAIN_RIGHT_2  */
-+	{ 0x4da8, 0x0000004a },	/*2072X_ADC1_AMP_GAIN_LEFT_2  */
-+	{ 0x4d8c, 0x0000004a },	/*2072X_ADC1_AMP_GAIN_RIGHT_3  */
-+	{ 0x4dac, 0x0000004a },	/*2072X_ADC1_AMP_GAIN_LEFT_3  */
-+	{ 0x4d90, 0x0000004a },	/*2072X_ADC1_AMP_GAIN_RIGHT_4  */
-+	{ 0x4db0, 0x0000004a },	/*2072X_ADC1_AMP_GAIN_LEFT_4  */
-+	{ 0x4d94, 0x0000004a },	/*2072X_ADC1_AMP_GAIN_RIGHT_5  */
-+	{ 0x4db4, 0x0000004a },	/*2072X_ADC1_AMP_GAIN_LEFT_5 */
-+	{ 0x4d98, 0x0000004a },	/*2072X_ADC1_AMP_GAIN_RIGHT_6 */
-+	{ 0x4db8, 0x0000004a },	/*2072X_ADC1_AMP_GAIN_LEFT_6 */
-+	{ 0x4c04, 0x00000000 },	/*2072X_ADC1_CONNECTION_SELECT_CONTROL */
-+	{ 0x4c14, 0x00000433 },	/*2072X_ADC1_POWER_STATE */
-+	{ 0x4c18, 0x00000000 },	/*2072X_ADC1_CONVERTER_STREAM_CHANNEL */
-+	{ 0x53c8, 0x00000031 },	/*2072X_ADC2_CONVERTER_FORMAT */
-+	{ 0x5180, 0x0000004a },	/*2072X_ADC2_AMP_GAIN_RIGHT_0 */
-+	{ 0x51a0, 0x0000004a },	/*2072X_ADC2_AMP_GAIN_LEFT_0 */
-+	{ 0x5184, 0x0000004a },	/*2072X_ADC2_AMP_GAIN_RIGHT_1 */
-+	{ 0x51a4, 0x0000004a },	/*2072X_ADC2_AMP_GAIN_LEFT_1 */
-+	{ 0x5188, 0x0000004a },	/*2072X_ADC2_AMP_GAIN_RIGHT_2 */
-+	{ 0x51a8, 0x0000004a },	/*2072X_ADC2_AMP_GAIN_LEFT_2 */
-+	{ 0x5004, 0x00000000 },	/*2072X_ADC2_CONNECTION_SELECT_CONTROL */
-+	{ 0x5014, 0x00000433 },	/*2072X_ADC2_POWER_STATE */
-+	{ 0x5018, 0x00000000 },	/*2072X_ADC2_CONVERTER_STREAM_CHANNEL */
-+	{ 0x5804, 0x00000000 },	/*2072X_PORTA_CONNECTION_SELECT_CTRL */
-+	{ 0x5814, 0x00000433 },	/*2072X_PORTA_POWER_STATE */
-+	{ 0x581c, 0x000000c0 },	/*2072X_PORTA_PIN_CTRL */
-+	{ 0x5820, 0x00000000 },	/*2072X_PORTA_UNSOLICITED_RESPONSE */
-+	{ 0x5824, 0x00000000 },	/*2072X_PORTA_PIN_SENSE */
-+	{ 0x5830, 0x00000002 },	/*2072X_PORTA_EAPD_BTL */
-+	{ 0x6014, 0x00000433 },	/*2072X_PORTB_POWER_STATE */
-+	{ 0x601c, 0x00000000 },	/*2072X_PORTB_PIN_CTRL */
-+	{ 0x6020, 0x00000000 },	/*2072X_PORTB_UNSOLICITED_RESPONSE */
-+	{ 0x6024, 0x00000000 },	/*2072X_PORTB_PIN_SENSE */
-+	{ 0x6030, 0x00000002 },	/*2072X_PORTB_EAPD_BTL */
-+	{ 0x6180, 0x00000000 },	/*2072X_PORTB_GAIN_RIGHT */
-+	{ 0x61a0, 0x00000000 },	/*2072X_PORTB_GAIN_LEFT */
-+	{ 0x6814, 0x00000433 },	/*2072X_PORTC_POWER_STATE */
-+	{ 0x681c, 0x00000000 },	/*2072X_PORTC_PIN_CTRL */
-+	{ 0x6980, 0x00000000 },	/*2072X_PORTC_GAIN_RIGHT */
-+	{ 0x69a0, 0x00000000 },	/*2072X_PORTC_GAIN_LEFT */
-+	{ 0x6414, 0x00000433 },	/*2072X_PORTD_POWER_STATE */
-+	{ 0x641c, 0x00000020 },	/*2072X_PORTD_PIN_CTRL */
-+	{ 0x6420, 0x00000000 },	/*2072X_PORTD_UNSOLICITED_RESPONSE */
-+	{ 0x6424, 0x00000000 },	/*2072X_PORTD_PIN_SENSE */
-+	{ 0x6580, 0x00000000 },	/*2072X_PORTD_GAIN_RIGHT */
-+	{ 0x65a0, 0x00000000 },	/*2072X_PORTD_GAIN_LEFT */
-+	{ 0x7404, 0x00000000 },	/*2072X_PORTE_CONNECTION_SELECT_CTRL */
-+	{ 0x7414, 0x00000433 },	/*2072X_PORTE_POWER_STATE */
-+	{ 0x741c, 0x00000040 },	/*2072X_PORTE_PIN_CTRL */
-+	{ 0x7420, 0x00000000 },	/*2072X_PORTE_UNSOLICITED_RESPONSE */
-+	{ 0x7424, 0x00000000 },	/*2072X_PORTE_PIN_SENSE */
-+	{ 0x7430, 0x00000002 },	/*2072X_PORTE_EAPD_BTL */
-+	{ 0x7580, 0x00000000 },	/*2072X_PORTE_GAIN_RIGHT */
-+	{ 0x75a0, 0x00000000 },	/*2072X_PORTE_GAIN_LEFT */
-+	{ 0x7814, 0x00000433 },	/*2072X_PORTF_POWER_STATE */
-+	{ 0x781c, 0x00000000 },	/*2072X_PORTF_PIN_CTRL */
-+	{ 0x7820, 0x00000000 },	/*2072X_PORTF_UNSOLICITED_RESPONSE */
-+	{ 0x7824, 0x00000000 },	/*2072X_PORTF_PIN_SENSE */
-+	{ 0x7980, 0x00000000 },	/*2072X_PORTF_GAIN_RIGHT */
-+	{ 0x79a0, 0x00000000 },	/*2072X_PORTF_GAIN_LEFT */
-+	{ 0x5c14, 0x00000433 },	/*2072X_PORTG_POWER_STATE */
-+	{ 0x5c1c, 0x00000040 },	/*2072X_PORTG_PIN_CTRL */
-+	{ 0x5c04, 0x00000000 },	/*2072X_PORTG_CONNECTION_SELECT_CTRL */
-+	{ 0x5c30, 0x00000002 },	/*2072X_PORTG_EAPD_BTL */
-+	{ 0x8814, 0x00000433 },	/*2072X_PORTM_POWER_STATE */
-+	{ 0x881c, 0x00000000 },	/*2072X_PORTM_PIN_CTRL */
-+	{ 0x8804, 0x00000000 },	/*2072X_PORTM_CONNECTION_SELECT_CTRL */
-+	{ 0x8830, 0x00000002 },	/*2072X_PORTM_EAPD_BTL */
-+	{ 0x5414, 0x00000433 },	/*2072X_MIXER_POWER_STATE */
-+	{ 0x5580, 0x0000004a },	/*2072X_MIXER_GAIN_RIGHT_0 */
-+	{ 0x55a0, 0x0000004a },	/*2072X_MIXER_GAIN_LEFT_0 */
-+	{ 0x5584, 0x0000004a },	/*2072X_MIXER_GAIN_RIGHT_1 */
-+	{ 0x55a4, 0x0000004a },	/*2072X_MIXER_GAIN_LEFT_1 */
-+	{ 0x6d00, 0x0000720c },	/*2072X_EQ_ENABLE_BYPASS */
-+	{ 0x6d10, 0x040065a4 },	/*2072X_SPKR_DRC_ENABLE_STEP */
-+	{ 0x6d14, 0x007b0024 },	/*2072X_SPKR_DRC_CONTROL */
-+	{ 0X6D18, 0x00000000 },	/*2072X_SPKR_DRC_TEST */
-+	{ 0x6d80, 0x001f008a },	/*2072X_DIGITAL_BIOS_TEST0 */
-+	{ 0x6d84, 0x00990026 },	/*2072X_DIGITAL_BIOS_TEST2 */
-+	{ 0x6e00, 0x00010001 },	/*2072X_I2SPCM_CONTROL1 */
-+	{ 0x6e04, 0x00000000 },	/*2072X_I2SPCM_CONTROL2 */
-+	{ 0x6e08, 0x00000000 },	/*2072X_I2SPCM_CONTROL3 */
-+	{ 0x6e0c, 0x00000000 },	/*2072X_I2SPCM_CONTROL4 */
-+	{ 0x6e10, 0x00000000 },	/*2072X_I2SPCM_CONTROL5 */
-+	{ 0x6e18, 0x00000000 },	/*2072X_I2SPCM_CONTROL6 */
-+	{ 0x6e14, 0x00000000 },	/*2072X_UM_INTERRUPT_CRTL_E */
-+	{ 0x7310, 0x00000600 },	/*2072X_CODEC_TEST20 */
-+	{ 0x7328, 0x00000208 },	/*2072X_CODEC_TEST26 */
-+	{ 0x7190, 0x00000000 },	/*2072X_ANALOG_TEST4 */
-+	{ 0x7194, 0x00000000 },	/*2072X_ANALOG_TEST5 */
-+	{ 0x7198, 0x0000059a },	/*2072X_ANALOG_TEST6 */
-+	{ 0x719c, 0x000000a7 },	/*2072X_ANALOG_TEST7 */
-+	{ 0x71a0, 0x00000017 },	/*2072X_ANALOG_TEST8 */
-+	{ 0x71a4, 0x00000000 },	/*2072X_ANALOG_TEST9 */
-+	{ 0x71a8, 0x00000285 },	/*2072X_ANALOG_TEST10 */
-+	{ 0x71ac, 0x00000000 },	/*2072X_ANALOG_TEST11 */
-+	{ 0x71b0, 0x00000000 },	/*2072X_ANALOG_TEST12 */
-+	{ 0x71b4, 0x00000000 },	/*2072X_ANALOG_TEST13 */
-+	{ 0x7204, 0x00000242 },	/*2072X_DIGITAL_TEST1 */
-+	{ 0x7224, 0x00000000 },	/*2072X_DIGITAL_TEST11 */
-+	{ 0x7230, 0x00000084 },	/*2072X_DIGITAL_TEST12 */
-+	{ 0x723c, 0x00000077 },	/*2072X_DIGITAL_TEST15 */
-+	{ 0x7080, 0x00000021 },	/*2072X_DIGITAL_TEST16 */
-+	{ 0x7084, 0x00000018 },	/*2072X_DIGITAL_TEST17 */
-+	{ 0x7088, 0x00000024 },	/*2072X_DIGITAL_TEST18 */
-+	{ 0x708c, 0x00000001 },	/*2072X_DIGITAL_TEST19 */
-+	{ 0x7090, 0x00000002 },	/*2072X_DIGITAL_TEST20 */
-+};
-+
-+
-+/*
-+ * cx2072x patch.
-+ */
-+static const struct reg_sequence cx2072x_patch[] = {
-+	{ 0x71A4, 0x080 }, /* DC offset Calibration        */
-+	{ 0x71a8, 0x287 }, /* Set max spk power to 1.5 W   */
-+	{ 0x7328, 0xa8c }, /* Set average spk power to 1.5W*/
-+	{ 0x7310, 0xf01 }, /*                             */
-+	{ 0x7328, 0xa8f }, /*                              */
-+	{ 0x7124, 0x001 }, /* Enable 30 Hz High pass filter*/
-+	{ 0x718c, 0x300 }, /* Disable PCBEEP pad           */
-+	{ 0x731c, 0x100 }, /* Disable SnM mode             */
-+	{ 0x641c, 0x020 }, /* Enable PortD input           */
-+	{ 0x0458, 0x040 }, /* Enable GPIO7 pin for button  */
-+	{ 0x0464, 0x040 }, /* Enable UM for GPIO7          */
-+	{ 0x0420, 0x080 }, /* Enable button response       */
-+	{ 0x7230, 0x0c4 }, /* Enable headset button        */
-+	{ 0x7200, 0x415 }, /* Power down class-d during idle*/
-+};
-+
-+
-+/* return register size */
-+static unsigned int cx2072x_register_size(struct device *dev,
-+	unsigned int reg)
-+{
-+	switch (reg) {
-+	case CX2072X_VENDOR_ID:
-+	case CX2072X_REVISION_ID:
-+	case CX2072X_PORTA_PIN_SENSE:
-+	case CX2072X_PORTB_PIN_SENSE:
-+	case CX2072X_PORTD_PIN_SENSE:
-+	case CX2072X_PORTE_PIN_SENSE:
-+	case CX2072X_PORTF_PIN_SENSE:
-+	case CX2072X_I2SPCM_CONTROL1:
-+	case CX2072X_I2SPCM_CONTROL2:
-+	case CX2072X_I2SPCM_CONTROL3:
-+	case CX2072X_I2SPCM_CONTROL4:
-+	case CX2072X_I2SPCM_CONTROL5:
-+	case CX2072X_I2SPCM_CONTROL6:
-+	case CX2072X_UM_INTERRUPT_CRTL_E:
-+	case CX2072X_EQ_G_COEFF:
-+		/*case CX2072X_SPKR_DRC_ENABLE_STEP:*/
-+	case CX2072X_SPKR_DRC_CONTROL:
-+	case CX2072X_SPKR_DRC_TEST:
-+	case CX2072X_DIGITAL_BIOS_TEST0:
-+	case CX2072X_DIGITAL_BIOS_TEST2:
-+		return 4;
-+	case CX2072X_EQ_ENABLE_BYPASS:
-+	case CX2072X_EQ_B0_COEFF:
-+	case CX2072X_EQ_B1_COEFF:
-+	case CX2072X_EQ_B2_COEFF:
-+	case CX2072X_EQ_A1_COEFF:
-+	case CX2072X_EQ_A2_COEFF:
-+	case CX2072X_DAC1_CONVERTER_FORMAT:
-+	case CX2072X_DAC2_CONVERTER_FORMAT:
-+	case CX2072X_ADC1_CONVERTER_FORMAT:
-+	case CX2072X_ADC2_CONVERTER_FORMAT:
-+	case CX2072X_CODEC_TEST20:
-+	case CX2072X_CODEC_TEST26:
-+	case CX2072X_ANALOG_TEST3:
-+	case CX2072X_ANALOG_TEST4:
-+	case CX2072X_ANALOG_TEST5:
-+	case CX2072X_ANALOG_TEST6:
-+	case CX2072X_ANALOG_TEST7:
-+	case CX2072X_ANALOG_TEST8:
-+	case CX2072X_ANALOG_TEST9:
-+	case CX2072X_ANALOG_TEST10:
-+	case CX2072X_ANALOG_TEST11:
-+	case CX2072X_ANALOG_TEST12:
-+	case CX2072X_ANALOG_TEST13:
-+	case CX2072X_DIGITAL_TEST0:
-+	case CX2072X_DIGITAL_TEST1:
-+	case CX2072X_DIGITAL_TEST11:
-+	case CX2072X_DIGITAL_TEST12:
-+	case CX2072X_DIGITAL_TEST15:
-+	case CX2072X_DIGITAL_TEST16:
-+	case CX2072X_DIGITAL_TEST17:
-+	case CX2072X_DIGITAL_TEST18:
-+	case CX2072X_DIGITAL_TEST19:
-+	case CX2072X_DIGITAL_TEST20:
-+		return 2;
-+	default:
-+		return 1;
-+	}
-+
-+}
-+
-+#ifdef CXDBG_REG_DUMP
-+static const char *cx2072x_get_reg_name(struct device *dev, unsigned int reg)
-+{
-+	int i;
-+
-+	for (i = 0; i < ARRAY_SIZE(cx2072x_regs); i++)
-+		if (cx2072x_regs[i].addr == reg)
-+			return cx2072x_regs[i].name;
-+
-+	dev_err(dev, "Unkown reg %08x\n", reg);
-+
-+	return "Unknown reg";
-+}
-+#endif
-+
-+static int cx2072x_reg_write(void *context, unsigned int reg,
-+			      unsigned int value)
-+{
-+	struct i2c_client *client = context;
-+	unsigned int i;
-+	unsigned int size;
-+	uint8_t buf[6];
-+	int ret;
-+	struct device *dev = &client->dev;
-+
-+	size = cx2072x_register_size(dev, reg);
-+	if (size == 0)
-+		return -EINVAL;
-+#ifdef CXDBG_REG_DUMP
-+	dev_dbg(dev, "I2C write address %40s,%d <= %08x\n",
-+		cx2072x_get_reg_name(dev, reg), size, value);
-+#endif
-+
-+	if (reg == CX2072X_UM_INTERRUPT_CRTL_E) {
-+		/* workaround to update the MSB byte only */
-+		reg += 3;
-+		size = 1;
-+		value >>= 24;
-+	}
-+
-+	buf[0] = reg >> 8;
-+	buf[1] = reg & 0xff;
-+
-+	for (i = 2; i < (size + 2); ++i) {
-+		buf[i] = value;
-+		value >>= 8;
-+	}
-+
-+	ret = i2c_master_send(client, buf, size + 2);
-+	if (ret == size + 2) {
-+		ret =  0;
-+	} else if (ret < 0) {
-+		dev_err(dev,
-+			"I2C write address failed\n");
-+	} else {
-+		dev_err(dev,
-+			"I2C write failed\n");
-+		ret =  -EIO;
-+	}
-+	return ret;
-+}
-+
-+static int cx2072x_reg_bulk_write(struct snd_soc_codec *codec,
-+	unsigned int reg, const void *val, size_t val_count)
-+{
-+	/*fix me*/
-+	struct i2c_client *client = to_i2c_client(codec->dev);
-+	uint8_t buf[2 + MAC_EQ_COEFF];
-+	int ret;
-+	struct device *dev = &client->dev;
-+
-+#ifdef CXDBG_REG_DUMP
-+	dev_dbg(dev, "I2C bulk write address %40s,%zd\n",
-+		cx2072x_get_reg_name(dev, reg), val_count);
-+#endif
-+
-+	if (val_count > MAC_EQ_COEFF) {
-+		dev_err(dev,
-+			"cx2072x_reg_bulk_write failed, writing count = %zd\n",
-+			val_count);
-+		return -EINVAL;
-+	}
-+
-+	buf[0] = reg >> 8;
-+	buf[1] = reg & 0xff;
-+
-+	memcpy(&buf[2], val, val_count);
-+
-+	ret = i2c_master_send(client, buf, val_count + 2);
-+	if (ret == val_count + 2)
-+		return 0;
-+	else if (ret < 0) {
-+		dev_err(dev,
-+			"I2C bulk write address failed\n");
-+	} else {
-+		dev_err(dev,
-+			"I2C bulk write address failed\n");
-+		ret = -EIO;
-+	}
-+	return ret;
-+}
-+
-+
-+/* get suggested pre_div valuce from mclk frequency */
-+static unsigned int get_div_from_mclk(unsigned int mclk)
-+{
-+	unsigned int div = 8;
-+	int i = 0;
-+
-+	for (i = 0; i < ARRAY_SIZE(MCLK_PRE_DIV); i++) {
-+		if (mclk <= MCLK_PRE_DIV[i].mclk) {
-+			div = MCLK_PRE_DIV[i].div;
-+			break;
-+		}
-+	}
-+	return div;
-+}
-+static int cx2072x_reg_read(void *context, unsigned int reg,
-+	unsigned int *value)
-+{
-+	int ret;
-+	unsigned int size;
-+	uint8_t send_buf[2];
-+	unsigned int recv_buf = 0;
-+	struct i2c_client *client = context;
-+	struct i2c_msg msgs[2];
-+	struct device *dev = &client->dev;
-+
-+	size = cx2072x_register_size(dev, reg);
-+	if (size == 0)
-+		return -EINVAL;
-+
-+	send_buf[0] = reg >> 8;
-+	send_buf[1] = reg & 0xff;
-+
-+	msgs[0].addr = client->addr;
-+	msgs[0].len = sizeof(send_buf);
-+	msgs[0].buf = send_buf;
-+	msgs[0].flags = 0;
-+
-+	msgs[1].addr = client->addr;
-+	msgs[1].len = size;
-+	msgs[1].buf = (uint8_t *)&recv_buf;
-+	msgs[1].flags = I2C_M_RD;
-+
-+	ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
-+	if (ret < 0) {
-+		dev_err(dev,
-+			"Failed to register codec: %d\n", ret);
-+		return ret;
-+	} else if (ret != ARRAY_SIZE(msgs)) {
-+		dev_err(dev,
-+			"Failed to register codec: %d\n", ret);
-+		return -EIO;
-+	}
-+
-+	*value = recv_buf;
-+
-+#ifdef CXDBG_REG_DUMP
-+	dev_dbg(dev,
-+		"I2C read address %40s,%d => %08x\n",
-+		cx2072x_get_reg_name(dev, reg), size, *value);
-+#endif
-+	return 0;
-+}
-+
-+static int cx2072x_config_headset_det(struct cx2072x_priv *cx2072x)
-+{
-+	const int interrupt_gpio_pin = 1;
-+
-+	dev_dbg(cx2072x->dev,
-+		"Configure interrupt pin: %d\n", interrupt_gpio_pin);
-+	/*No-sticky input type*/
-+	regmap_write(cx2072x->regmap, CX2072X_GPIO_STICKY_MASK, 0x1f);
-+	/*Use GPOI0 as intrrupt output pin*/
-+	regmap_write(cx2072x->regmap, CX2072X_UM_INTERRUPT_CRTL_E, 0x12 << 24);
-+
-+	/* Enables unsolitited message on PortA*/
-+	regmap_write(cx2072x->regmap, CX2072X_PORTA_UNSOLICITED_RESPONSE, 0x80);
-+
-+	/* support both nokia and apple headset set. Monitor time = 275 ms*/
-+	regmap_write(cx2072x->regmap, CX2072X_DIGITAL_TEST15, 0x73);
-+
-+	/* Disable TIP detection*/
-+	regmap_write(cx2072x->regmap, CX2072X_ANALOG_TEST12, 0x300);
-+
-+	/* Switch MusicD3Live pin to GPIO */
-+	regmap_write(cx2072x->regmap, CX2072X_DIGITAL_TEST1, 0);
-+
-+	return 0;
-+}
-+
-+static int cx2072x_config_pll(struct cx2072x_priv *cx2072x)
-+{
-+	struct device *dev = cx2072x->dev;
-+	unsigned int pre_div;
-+	unsigned int pre_div_val;
-+	unsigned int pll_input;
-+	unsigned int pll_output;
-+	unsigned int int_div;
-+	unsigned int frac_div;
-+	unsigned int frac_num = 0;
-+	unsigned int sample_rate = cx2072x->sample_rate;
-+	int pt_sample_per_sync = 2;
-+	int pt_clock_per_sample = 96;
-+
-+	switch (sample_rate) {
-+	case 48000:
-+	case 32000:
-+	case 24000:
-+	case 16000:
-+		break;
-+	case 96000:
-+		pt_sample_per_sync = 1;
-+		pt_clock_per_sample = 48;
-+		break;
-+	case 192000:
-+		pt_sample_per_sync = 0;
-+		pt_clock_per_sample = 24;
-+		break;
-+	default:
-+		dev_err(dev, "Unsupported sample rate %d\n", sample_rate);
-+		return -EINVAL;
-+	}
-+
-+
-+	/*Configure PLL settings*/
-+	pre_div = get_div_from_mclk(cx2072x->mclk);
-+	pll_input = cx2072x->mclk / pre_div;
-+	pll_output = sample_rate * 3072;
-+	int_div = pll_output / pll_input;
-+	frac_div = pll_output - (int_div * pll_input);
-+
-+	if (frac_div) {
-+		frac_div *= 1000;
-+		frac_div /= pll_input;
-+		frac_num = ((4000 + frac_div) * ((1 << 20) - 4));
-+		do_div(frac_num, 7);
-+		frac_num = (frac_num + 499) / 1000;
-+	}
-+	pre_div_val = (pre_div - 1) * 2;
-+
-+	regmap_write(cx2072x->regmap, CX2072X_ANALOG_TEST4, 0X40
-+		| (pre_div_val << 8));
-+	if (frac_div == 0) {
-+		/*Int mode*/
-+		regmap_write(cx2072x->regmap, CX2072X_ANALOG_TEST7, 0x100);
-+	} else {
-+		/*frac mode*/
-+		regmap_write(cx2072x->regmap, CX2072X_ANALOG_TEST6,
-+			frac_num & 0xfff);
-+		regmap_write(cx2072x->regmap, CX2072X_ANALOG_TEST7,
-+			(unsigned char)(frac_num >> 12));
-+	}
-+	int_div--;
-+	regmap_write(cx2072x->regmap, CX2072X_ANALOG_TEST8,
-+		(unsigned char)int_div & 0xffff);
-+
-+	/* configure PLL tracking*/
-+	if (frac_div == 0) {
-+		/* disable PLL tracking*/
-+		regmap_write(cx2072x->regmap, CX2072X_DIGITAL_TEST16, 0x00);
-+	} else {
-+		/* configure and enable PLL tracking*/
-+		regmap_write(cx2072x->regmap, CX2072X_DIGITAL_TEST16,
-+			(pt_sample_per_sync << 4) & 0xf0);
-+		regmap_write(cx2072x->regmap, CX2072X_DIGITAL_TEST17,
-+			pt_clock_per_sample);
-+		regmap_write(cx2072x->regmap, CX2072X_DIGITAL_TEST18,
-+			pt_clock_per_sample * 3 / 2);
-+		regmap_write(cx2072x->regmap, CX2072X_DIGITAL_TEST19, 0x01);
-+		regmap_write(cx2072x->regmap, CX2072X_DIGITAL_TEST20, 0x02);
-+		regmap_update_bits(cx2072x->regmap, CX2072X_DIGITAL_TEST16,
-+			0X01, 0X01);
-+	}
-+
-+	return 0;
-+}
-+
-+
-+static int cx2072x_config_i2spcm(struct cx2072x_priv *cx2072x)
-+{
-+	struct device *dev = cx2072x->dev;
-+
-+	int is_i2s = 0;
-+	int has_one_bit_delay = 0;
-+	int is_right_j = 0;
-+	int is_frame_inv = 0;
-+	int is_bclk_inv = 0;
-+	int pulse_len = 1;
-+	int frame_len = cx2072x->frame_size;
-+	int sample_size = cx2072x->sample_size;
-+	int i2s_right_slot;
-+	int i2s_right_pause_interval = 0;
-+	int i2s_right_pause_pos;
-+	int is_big_endian = 1;
-+	const int slots_per_channel = cx2072x->tdm_slot_width / BITS_PER_SLOT;
-+	const unsigned fmt = cx2072x->dai_fmt;
-+
-+	REG_I2SPCM_CTRL_REG1 reg1 = { .ulVal = 0 };
-+	REG_I2SPCM_CTRL_REG2 reg2 = { .ulVal = 0 };
-+	REG_I2SPCM_CTRL_REG3 reg3 = { .ulVal = 0 };
-+	REG_I2SPCM_CTRL_REG4 reg4 = { .ulVal = 0 };
-+	REG_I2SPCM_CTRL_REG5 reg5 = { .ulVal = 0 };
-+	REG_I2SPCM_CTRL_REG6 reg6 = { .ulVal = 0 };
-+	REG_DIGITAL_BIOS_TEST2 regDBT2 = { .ulVal = 0 };
-+
-+	if (frame_len <= 0) {
-+		dev_err(dev, "Incorrect frame len %d\n", frame_len);
-+		return -EINVAL;
-+	}
-+
-+	if (sample_size <= 0) {
-+		dev_err(dev, "Incorrect sample size %d\n", sample_size);
-+		return -EINVAL;
-+	}
-+
-+	/*fix me */
-+	regDBT2.ulVal = 0xac;
-+
-+	/* set master/slave */
-+	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
-+	case SND_SOC_DAIFMT_CBM_CFM:
-+		reg2.r.tx_master = 1;
-+		reg3.r.rx_master = 1;
-+		dev_err(dev, "DAI master mode is not implemented yet.\n");
-+		return -EINVAL;
-+	case SND_SOC_DAIFMT_CBS_CFS:
-+		break;
-+	default:
-+		dev_err(dev, "Unsupported DAI master mode\n");
-+		return -EINVAL;
-+	}
-+
-+	/* set format */
-+	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
-+	case SND_SOC_DAIFMT_I2S:
-+		is_i2s = 1;
-+		has_one_bit_delay = 1;
-+		pulse_len = frame_len / 2;
-+		break;
-+	case SND_SOC_DAIFMT_RIGHT_J:
-+		is_i2s = 1;
-+		is_right_j = 1;
-+		pulse_len = frame_len / 2;
-+		break;
-+	case SND_SOC_DAIFMT_LEFT_J:
-+		is_i2s = 1;
-+		pulse_len = frame_len / 2;
-+		break;
-+	case SND_SOC_DAIFMT_DSP_A:
-+		has_one_bit_delay = 1;
-+		break;
-+	case SND_SOC_DAIFMT_DSP_B:
-+		break;
-+	default:
-+		dev_err(dev, "Unsupported DAI format\n");
-+		return -EINVAL;
-+	}
-+
-+	/* clock inversion */
-+	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
-+	case SND_SOC_DAIFMT_NB_NF:
-+		is_frame_inv = is_i2s ? 1 : 0;
-+		is_bclk_inv = is_i2s ? 1 : 0;
-+		break;
-+	case SND_SOC_DAIFMT_IB_IF:
-+		is_frame_inv = is_i2s ? 0 : 1;
-+		is_bclk_inv = is_i2s ? 0 : 1;
-+		break;
-+	case SND_SOC_DAIFMT_IB_NF:
-+		is_frame_inv = is_i2s ? 1 : 0;
-+		is_bclk_inv = is_i2s ? 0 : 1;
-+		break;
-+	case SND_SOC_DAIFMT_NB_IF:
-+		is_frame_inv = is_i2s ? 0 : 1;
-+		is_bclk_inv = is_i2s ? 1 : 0;
-+		break;
-+	default:
-+		dev_err(dev, "Unsupported DAI clock inversion\n");
-+		return -EINVAL;
-+	}
-+
-+	cx2072x->dai_fmt = fmt;
-+
-+	reg1.r.rx_data_one_line = 1;
-+	reg1.r.tx_data_one_line = 1;
-+
-+	if (is_i2s) {
-+		i2s_right_slot = (frame_len / 2) / BITS_PER_SLOT;
-+		i2s_right_pause_interval = (frame_len / 2) % BITS_PER_SLOT;
-+		i2s_right_pause_pos = i2s_right_slot * BITS_PER_SLOT;
-+	}
-+
-+	reg1.r.rx_ws_pol = is_frame_inv;
-+	reg1.r.rx_ws_wid = pulse_len - 1;
-+
-+	reg1.r.rx_frm_len = frame_len / BITS_PER_SLOT - 1;
-+	reg1.r.rx_sa_size = (sample_size / BITS_PER_SLOT) - 1;
-+
-+	reg1.r.tx_ws_pol = reg1.r.rx_ws_pol;
-+	reg1.r.tx_ws_wid = pulse_len - 1;
-+	reg1.r.tx_frm_len = reg1.r.rx_frm_len;
-+	reg1.r.tx_sa_size = reg1.r.rx_sa_size;
-+
-+	reg2.r.tx_endian_sel = is_big_endian ? 0 : 1;
-+	reg2.r.tx_dstart_dly = has_one_bit_delay;
-+
-+	reg3.r.rx_endian_sel = is_big_endian ? 0 : 1;
-+	reg3.r.rx_dstart_dly = has_one_bit_delay;
-+
-+	if (is_i2s) {
-+		reg2.r.tx_en_ch1 = 1;
-+		reg2.r.tx_en_ch2 = 1;
-+		reg2.r.tx_slot_1 = 0;
-+		reg2.r.tx_slot_2 = i2s_right_slot;
-+		reg3.r.rx_en_ch1 = 1;
-+		reg3.r.rx_en_ch2 = 1;
-+		reg3.r.rx_slot_1 = 0;
-+		reg3.r.rx_slot_2 = i2s_right_slot;
-+		reg6.r.rx_pause_start_pos = i2s_right_pause_pos;
-+		reg6.r.rx_pause_cycles = i2s_right_pause_interval;
-+		reg6.r.tx_pause_start_pos = i2s_right_pause_pos;
-+		reg6.r.tx_pause_cycles = i2s_right_pause_interval;
-+	} else {
-+		reg2.r.tx_en_ch1 = cx2072x->tdm_tx_mask & 0x01 ? 1 : 0;
-+		reg2.r.tx_en_ch2 = cx2072x->tdm_tx_mask & 0x02 ? 1 : 0;
-+		reg2.r.tx_en_ch3 = cx2072x->tdm_tx_mask & 0x04 ? 1 : 0;
-+		reg2.r.tx_en_ch4 = cx2072x->tdm_tx_mask & 0x08 ? 1 : 0;
-+		reg2.r.tx_slot_1 = 0;
-+		reg2.r.tx_slot_2 = slots_per_channel * 1;
-+		reg2.r.tx_slot_3 = slots_per_channel * 2;
-+		reg2.r.tx_slot_4 = slots_per_channel * 3;
-+
-+		reg3.r.rx_en_ch1 = cx2072x->tdm_rx_mask & 0x01 ? 1 : 0;
-+		reg3.r.rx_en_ch2 = cx2072x->tdm_rx_mask & 0x02 ? 1 : 0;
-+		reg3.r.rx_en_ch3 = cx2072x->tdm_rx_mask & 0x04 ? 1 : 0;
-+		reg3.r.rx_en_ch4 = cx2072x->tdm_rx_mask & 0x08 ? 1 : 0;
-+		reg3.r.rx_slot_1 = 0;
-+		reg3.r.rx_slot_2 = slots_per_channel * 1;
-+		reg3.r.rx_slot_3 = slots_per_channel * 2;
-+		reg3.r.rx_slot_4 = slots_per_channel * 3;
-+	}
-+	regDBT2.r.i2s_bclk_invert = is_bclk_inv;
-+
-+	reg1.r.rx_data_one_line = 1;
-+	reg1.r.tx_data_one_line = 1;
-+
-+#ifdef ENABLE_MIC_POP_WA
-+	/*Mute I2S TX*/
-+	reg4.ulVal |= 0x2;
-+#endif
-+	regmap_write(cx2072x->regmap, CX2072X_I2SPCM_CONTROL1, reg1.ulVal);
-+	regmap_write(cx2072x->regmap, CX2072X_I2SPCM_CONTROL2, reg2.ulVal);
-+	regmap_write(cx2072x->regmap, CX2072X_I2SPCM_CONTROL3, reg3.ulVal);
-+	regmap_write(cx2072x->regmap, CX2072X_I2SPCM_CONTROL4, reg4.ulVal);
-+	regmap_write(cx2072x->regmap, CX2072X_I2SPCM_CONTROL5, reg5.ulVal);
-+	regmap_write(cx2072x->regmap, CX2072X_I2SPCM_CONTROL6, reg6.ulVal);
-+	/*enable bclk and EAPD input*/
-+	if (cx2072x->rev_id == CX2072X_REV_A2)
-+		regmap_update_bits(cx2072x->regmap, CX2072X_DIGITAL_BIOS_TEST2,
-+			0x84, 0xFF);
-+	else
-+		regmap_write(cx2072x->regmap, CX2072X_DIGITAL_BIOS_TEST2,
-+			regDBT2.ulVal);
-+
-+	return 0;
-+}
-+
-+
-+static void cx2072x_dsp_init(struct snd_soc_codec *codec)
-+{
-+	struct cx2072x_priv *cx2072x = get_cx2072x_priv(codec);
-+	int i, j, band;
-+	unsigned char *pCoef = &cx2072x_eq_coeff_array[0][0];
-+
-+	regmap_write(cx2072x->regmap, CX2072X_EQ_ENABLE_BYPASS, 0x6e0f);
-+
-+	for (i = 0; i < MAX_EQ_BAND; i++) {
-+		for (j = 0; j < 2; j++) {
-+			cx2072x_reg_bulk_write(codec, CX2072X_EQ_B0_COEFF,
-+				pCoef + (MAC_EQ_COEFF*i), MAC_EQ_COEFF);
-+			band = i + (j << 3) + (1 << 6);
-+			regmap_write(cx2072x->regmap, CX2072X_EQ_BAND, band);
-+			mdelay(5);
-+		}
-+	}
-+
-+	cx2072x_reg_bulk_write(codec, CX2072X_SPKR_DRC_ENABLE_STEP,
-+		cx2072x_drc_array, MAX_DRC_REGS);
-+}
-+static void cx2072x_update_dsp(struct snd_soc_codec *codec)
-+{
-+	unsigned int afg_reg;
-+	struct cx2072x_priv *cx2072x = get_cx2072x_priv(codec);
-+
-+	regmap_read(cx2072x->regmap, CX2072X_AFG_POWER_STATE, &afg_reg);
-+
-+	if (!cx2072x->plbk_dsp_changed) {
-+		/*nothing change*/
-+		return;
-+	}
-+
-+	if ((afg_reg & 0xf) != 0) {
-+		/*skip since device is on D3 mode*/
-+		return;
-+	}
-+
-+	if (cx2072x->plbk_dsp_en && !cx2072x->plbk_dsp_init) {
-+		cx2072x_dsp_init(codec);
-+		cx2072x->plbk_dsp_init = true;
-+	}
-+
-+	if (cx2072x->plbk_dsp_en) {
-+		regmap_write(cx2072x->regmap, CX2072X_EQ_ENABLE_BYPASS,
-+			0x6203);
-+		regmap_write(cx2072x->regmap, CX2072X_SPKR_DRC_ENABLE_STEP,
-+			0x65);
-+	} else {
-+		/*By pass DRC and EQ.*/
-+		regmap_write(cx2072x->regmap, CX2072X_EQ_ENABLE_BYPASS,
-+			0x620c);
-+		regmap_write(cx2072x->regmap, CX2072X_SPKR_DRC_ENABLE_STEP,
-+			0xa4);
-+	}
-+	cx2072x->plbk_dsp_changed = false;
-+}
-+
-+
-+
-+static int afg_power_ev(struct snd_soc_dapm_widget *w,
-+	struct snd_kcontrol *kcontrol, int event)
-+{
-+	struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
-+	struct cx2072x_priv *cx2072x = get_cx2072x_priv(codec);
-+
-+	switch (event) {
-+	case SND_SOC_DAPM_POST_PMU:
-+		regmap_update_bits(cx2072x->regmap, CX2072X_DIGITAL_BIOS_TEST0,
-+			0x00, 0x10);
-+		break;
-+
-+	case SND_SOC_DAPM_PRE_PMD:
-+		regmap_update_bits(cx2072x->regmap, CX2072X_DIGITAL_BIOS_TEST0,
-+			0x10, 0x10);
-+		break;
-+	}
-+
-+	return 0;
-+}
-+
-+#ifdef ENABLE_MIC_POP_WA
-+/*
-+ * This work will be called at ADC widget power on time.
-+ * to reduce initial mic pop noise caused by hardware
-+ */
-+
-+static void cx2072x_anit_mic_pop_work(struct work_struct *work)
-+{
-+	struct snd_soc_dapm_context *dapm =
-+		container_of(work, struct snd_soc_dapm_context,
-+		delayed_work.work);
-+	struct snd_soc_codec *codec = snd_soc_dapm_to_codec(dapm);
-+	struct cx2072x_priv *cx2072x = get_cx2072x_priv(codec);
-+
-+	dev_dbg(cx2072x->dev, "Unmute I2S TX\n");
-+	/*Unmute I2S TX*/
-+
-+	regmap_update_bits(cx2072x->regmap, CX2072X_I2SPCM_CONTROL4,
-+		0x2, 0x0);
-+}
-+#endif
-+
-+static int adc1_power_ev(struct snd_soc_dapm_widget *w,
-+	struct snd_kcontrol *kcontrol, int event)
-+{
-+#ifdef ENABLE_MIC_POP_WA
-+	struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
-+	struct cx2072x_priv *cx2072x = get_cx2072x_priv(codec);
-+
-+	switch (event) {
-+	case SND_SOC_DAPM_POST_PMU:
-+		/* Umute I2S TX after 300 ms to get around the mic
-+		 * pop noise issue.
-+		 */
-+		schedule_delayed_work(&codec->dapm.delayed_work,
-+			msecs_to_jiffies(300));
-+		break;
-+
-+	case SND_SOC_DAPM_POST_PMD:
-+		/*Mute TX I2S*/
-+
-+		regmap_update_bits(cx2072x->regmap, CX2072X_I2SPCM_CONTROL4,
-+			0x2, 0x2);
-+		break;
-+	}
-+#endif
-+	return 0;
-+}
-+
-+
-+static int portg_power_ev(struct snd_soc_dapm_widget *w,
-+	struct snd_kcontrol *kcontrol, int event)
-+{
-+	struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
-+
-+	switch (event) {
-+	case SND_SOC_DAPM_POST_PMU:
-+		cx2072x_update_dsp(codec);
-+		break;
-+	default:
-+		break;
-+	}
-+	return 0;
-+}
-+static int cx2072x_plbk_dsp_info(struct snd_kcontrol *kcontrol,
-+	struct snd_ctl_elem_info *uinfo)
-+{
-+	uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
-+	uinfo->count = 1;
-+	uinfo->value.integer.min = 0;
-+	uinfo->value.integer.max = 1;
-+	return 0;
-+}
-+
-+static int cx2072x_plbk_dsp_get(struct snd_kcontrol *kcontrol,
-+	struct snd_ctl_elem_value *ucontrol)
-+{
-+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
-+	struct cx2072x_priv *cx2072x = get_cx2072x_priv(codec);
-+
-+	ucontrol->value.integer.value[0] = cx2072x->plbk_dsp_en;
-+
-+	return 0;
-+}
-+
-+static int cx2072x_plbk_dsp_put(struct snd_kcontrol *kcontrol,
-+	struct snd_ctl_elem_value *ucontrol)
-+{
-+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
-+	struct cx2072x_priv *cx2072x = get_cx2072x_priv(codec);
-+	const bool en_dsp = ucontrol->value.integer.value[0];
-+
-+	if (ucontrol->value.integer.value[0] > 1)
-+		return -EINVAL;
-+
-+	if (cx2072x->plbk_dsp_en != en_dsp) {
-+		cx2072x->plbk_dsp_en = en_dsp;
-+		cx2072x->plbk_dsp_changed = true;
-+		cx2072x_update_dsp(codec);
-+	}
-+	return 0;
-+}
-+
-+
-+#define CX2072X_PLBK_DSP_SWITCH(xname) {\
-+	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
-+	.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,\
-+	.info = cx2072x_plbk_dsp_info, \
-+	.get = cx2072x_plbk_dsp_get, .put = cx2072x_plbk_dsp_put}
-+
-+static const struct snd_kcontrol_new cx2072x_snd_controls[] = {
-+
-+	SOC_DOUBLE_R_TLV("PortD Boost", CX2072X_PORTD_GAIN_LEFT,
-+	CX2072X_PORTD_GAIN_RIGHT, 0, 3, 0, boost_tlv),
-+	SOC_DOUBLE_R_TLV("PortC Boost", CX2072X_PORTC_GAIN_LEFT,
-+	CX2072X_PORTC_GAIN_RIGHT, 0, 3, 0, boost_tlv),
-+	SOC_DOUBLE_R_TLV("PortB Boost", CX2072X_PORTB_GAIN_LEFT,
-+	CX2072X_PORTB_GAIN_RIGHT, 0, 3, 0, boost_tlv),
-+
-+	SOC_DOUBLE_R_TLV("PortD ADC1 Volume", CX2072X_ADC1_AMP_GAIN_LEFT_1,
-+	CX2072X_ADC1_AMP_GAIN_RIGHT_1, 0, 0x4a, 0, adc_tlv),
-+	SOC_DOUBLE_R_TLV("PortC ADC1 Volume", CX2072X_ADC1_AMP_GAIN_LEFT_2,
-+	CX2072X_ADC1_AMP_GAIN_RIGHT_2, 0, 0x4a, 0, adc_tlv),
-+	SOC_DOUBLE_R_TLV("PortB ADC1 Volume", CX2072X_ADC1_AMP_GAIN_LEFT_0,
-+	CX2072X_ADC1_AMP_GAIN_RIGHT_0, 0, 0x4a, 0, adc_tlv),
-+
-+	SOC_DOUBLE_R_TLV("DAC1 Volume", CX2072X_DAC1_AMP_GAIN_LEFT,
-+	CX2072X_DAC1_AMP_GAIN_RIGHT, 0, 0x4a, 0, dac_tlv),
-+
-+	SOC_DOUBLE_R("DAC1 Mute", CX2072X_DAC1_AMP_GAIN_LEFT,
-+		CX2072X_DAC1_AMP_GAIN_RIGHT, 7,  1, 0),
-+
-+	SOC_DOUBLE_R_TLV("DAC2 Volume", CX2072X_DAC2_AMP_GAIN_LEFT,
-+	CX2072X_DAC2_AMP_GAIN_RIGHT, 0, 0x4a, 0, dac_tlv),
-+
-+	CX2072X_PLBK_DSP_SWITCH("Playback DSP Switch"),
-+};
-+
-+/**
-+* cx2072x_hs_jack_report: Report jack notification to upper layer
-+* @codec : pointer variable to codec having information related to codec
-+* @jack : Pointer variable to snd_soc_jack having information of codec
-+* and pin number$
-+* @report : Provides informaton of whether it is headphone or microphone
-+*
-+*/
-+int cx2072x_hs_jack_report(struct snd_soc_codec *codec)
-+{
-+	unsigned int jack;
-+	unsigned int type = 0;
-+	int  state = 0;
-+	struct cx2072x_priv *cx2072x = get_cx2072x_priv(codec);
-+
-+
-+	regcache_cache_bypass(cx2072x->regmap, true);
-+	cx2072x->jack_state = CX_JACK_NONE;
-+	regmap_read(cx2072x->regmap, CX2072X_PORTA_PIN_SENSE, &jack);
-+	jack = jack >> 24;
-+	regmap_read(cx2072x->regmap, CX2072X_DIGITAL_TEST11, &type);
-+	regcache_cache_bypass(cx2072x->regmap, false);
-+	if (jack == 0x80) {
-+		type = type >> 8;
-+
-+		if (type & 0x8) {
-+			state |= SND_JACK_HEADSET;
-+			cx2072x->jack_state = CX_JACK_APPLE_HEADSET;
-+			if (type & 0x2)
-+				state |= SND_JACK_BTN_0;
-+		} else if (type & 0x4) {
-+			state |= SND_JACK_HEADPHONE;
-+			cx2072x->jack_state = CX_JACK_NOKIE_HEADSET;
-+		} else {
-+			state |= SND_JACK_HEADPHONE;
-+			cx2072x->jack_state = CX_JACK_HEADPHONE;
-+		}
-+
-+	}
-+
-+
-+	/* clear interrupt */
-+	regmap_write(cx2072x->regmap, CX2072X_UM_INTERRUPT_CRTL_E, 0x12 << 24);
-+
-+	dev_err(codec->dev, "CX2072X_HSDETECT type=0x%X,Jack state = %x\n",
-+		type, state);
-+	return state;
-+}
-+EXPORT_SYMBOL_GPL(cx2072x_hs_jack_report);
-+
-+
-+
-+
-+
-+static int cx2072x_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask,
-+	unsigned int rx_mask, int slots, int slot_width)
-+{
-+	struct snd_soc_codec *codec = dai->codec;
-+	struct cx2072x_priv *cx2072x = snd_soc_codec_get_drvdata(codec);
-+
-+	if (slots == 0)
-+		goto out;
-+
-+
-+	switch (rx_mask) {
-+	case 1 ... 0xf:
-+	default:
-+		return -EINVAL;
-+	}
-+
-+
-+	switch (tx_mask) {
-+	case 1 ... 0xf:
-+	default:
-+		return -EINVAL;
-+	}
-+
-+out:
-+	cx2072x->tdm_rx_mask = rx_mask;
-+	cx2072x->tdm_tx_mask = tx_mask;
-+	cx2072x->tdm_slot_width = slot_width;
-+	cx2072x->tdm_slots = slots;
-+	return 0;
-+}
-+
-+static int cx2072x_hw_params(struct snd_pcm_substream *substream,
-+	struct snd_pcm_hw_params *params,
-+	struct snd_soc_dai *dai)
-+{
-+	struct snd_soc_codec *codec = dai->codec;
-+	struct cx2072x_priv *cx2072x = get_cx2072x_priv(codec);
-+	struct device *dev = codec->dev;
-+	const unsigned int sample_rate = params_rate(params);
-+	int sample_size, frame_size;
-+
-+	/* Data sizes if not using TDM */
-+	sample_size = params_width(params);
-+
-+	if (sample_size < 0)
-+		return sample_size;
-+
-+	frame_size = snd_soc_params_to_frame_size(params);
-+	if (frame_size < 0)
-+		return frame_size;
-+
-+	if (cx2072x->bclk_ratio)
-+		frame_size = cx2072x->bclk_ratio;
-+
-+	switch (sample_rate) {
-+	case 48000:
-+	case 32000:
-+	case 24000:
-+	case 16000:
-+	case 96000:
-+	case 192000:
-+		break;
-+	default:
-+		dev_err(dev, "Unsupported sample rate %d\n", sample_rate);
-+		return -EINVAL;
-+	}
-+
-+	dev_dbg(dev, "Sample size %d bits, frame = %d bits, rate = %d Hz\n",
-+		sample_size, frame_size, sample_rate);
-+
-+	cx2072x->frame_size = frame_size;
-+	cx2072x->sample_size = sample_size;
-+	cx2072x->sample_rate = sample_rate;
-+
-+	if (cx2072x->pll_changed) {
-+		cx2072x_config_pll(cx2072x);
-+		cx2072x->pll_changed = false;
-+	}
-+	if (cx2072x->i2spcm_changed) {
-+		cx2072x_config_i2spcm(cx2072x);
-+		cx2072x->i2spcm_changed = false;
-+	}
-+
-+	return 0;
-+}
-+
-+
-+static int cx2072x_digital_mute(struct snd_soc_dai *dai, int mute)
-+{
-+	return 0;
-+}
-+
-+static int cx2072x_set_dai_bclk_ratio(struct snd_soc_dai *dai,
-+				      unsigned int ratio)
-+{
-+	struct snd_soc_codec *codec = dai->codec;
-+	struct cx2072x_priv *cx2072x = get_cx2072x_priv(codec);
-+
-+	cx2072x->bclk_ratio = ratio;
-+	return 0;
-+}
-+
-+
-+static int cx2072x_set_dai_sysclk(struct snd_soc_dai *dai, int clk_id,
-+	unsigned int freq, int dir)
-+{
-+	struct snd_soc_codec *codec = dai->codec;
-+	struct cx2072x_priv *cx2072x = get_cx2072x_priv(codec);
-+	struct device *dev = codec->dev;
-+
-+	if (freq == 0) {
-+		dev_dbg(dev, "MCLK: Switch to internal OSC\n");
-+		return 0;
-+	}
-+	cx2072x->mclk = freq;
-+	switch (clk_id) {
-+	case CX2072X_MCLK_EXTERNAL_PLL:
-+		dev_dbg(dev, "MCLK: Switch to external PLL\n");
-+		break;
-+	case CX2072X_MCLK_INTERNAL_OSC:
-+		dev_err(dev, "Unsupported DAI format\n");
-+		break;
-+	default:
-+		dev_dbg(dev, "the MCLK is not configured\n");
-+		break;
-+	}
-+
-+	return 0;
-+}
-+
-+static int cx2072x_set_dai_fmt(struct snd_soc_dai *dai,
-+	unsigned int fmt)
-+{
-+	struct snd_soc_codec *codec = dai->codec;
-+	struct cx2072x_priv *cx2072x = get_cx2072x_priv(codec);
-+	struct device *dev = codec->dev;
-+
-+	/* set master/slave */
-+	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
-+	case SND_SOC_DAIFMT_CBM_CFM:
-+	case SND_SOC_DAIFMT_CBS_CFS:
-+		break;
-+	default:
-+		dev_err(dev, "Unsupported DAI master mode\n");
-+		return -EINVAL;
-+	}
-+
-+	/* set format */
-+	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
-+	case SND_SOC_DAIFMT_I2S:
-+	case SND_SOC_DAIFMT_RIGHT_J:
-+	case SND_SOC_DAIFMT_LEFT_J:
-+	case SND_SOC_DAIFMT_DSP_A:
-+	case SND_SOC_DAIFMT_DSP_B:
-+		break;
-+	default:
-+		dev_err(dev, "Unsupported DAI format\n");
-+		return -EINVAL;
-+	}
-+
-+	/* clock inversion */
-+	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
-+	case SND_SOC_DAIFMT_NB_NF:
-+	case SND_SOC_DAIFMT_IB_IF:
-+	case SND_SOC_DAIFMT_IB_NF:
-+	case SND_SOC_DAIFMT_NB_IF:
-+		break;
-+	default:
-+		dev_err(dev, "Unsupported DAI clock inversion\n");
-+		return -EINVAL;
-+	}
-+
-+	cx2072x->dai_fmt = fmt;
-+	return 0;
-+}
-+
-+
-+static const char * const dac_enum_text[] = {
-+	"DAC1 Switch", "DAC2 Switch",
-+};
-+
-+static const struct soc_enum porta_dac_enum =
-+SOC_ENUM_SINGLE(CX2072X_PORTA_CONNECTION_SELECT_CTRL, 0, 2, dac_enum_text);
-+
-+static const struct snd_kcontrol_new porta_mux =
-+SOC_DAPM_ENUM("PortA Mux", porta_dac_enum);
-+
-+static const struct soc_enum portg_dac_enum =
-+SOC_ENUM_SINGLE(CX2072X_PORTG_CONNECTION_SELECT_CTRL, 0, 2, dac_enum_text);
-+
-+static const struct snd_kcontrol_new portg_mux =
-+SOC_DAPM_ENUM("PortG Mux", portg_dac_enum);
-+
-+static const struct soc_enum porte_dac_enum =
-+SOC_ENUM_SINGLE(CX2072X_PORTE_CONNECTION_SELECT_CTRL, 0, 2, dac_enum_text);
-+
-+static const struct snd_kcontrol_new porte_mux =
-+SOC_DAPM_ENUM("PortE Mux", porte_dac_enum);
-+
-+static const char * const adc1in_sel_text[] = {
-+	"PortB Switch", "PortD Switch", "PortC Switch", "Widget15 Switch",
-+	"PortE Switch", "PortF Switch", "PortH Switch"
-+};
-+
-+static const struct soc_enum adc1in_sel_enum =
-+SOC_ENUM_SINGLE(CX2072X_ADC1_CONNECTION_SELECT_CONTROL, 0, 7, adc1in_sel_text);
-+
-+static const struct snd_kcontrol_new adc1_mux =
-+SOC_DAPM_ENUM("ADC1 Mux", adc1in_sel_enum);
-+
-+#define CX2072X_DAPM_SUPPLY_S(wname, wsubseq, wreg, wshift, wmask,  won_val, \
-+	woff_val, wevent, wflags) \
-+	{.id = snd_soc_dapm_supply, .name = wname, .kcontrol_news = NULL, \
-+	.num_kcontrols = 0, .reg = wreg, .shift = wshift, .mask = wmask, \
-+	.on_val = won_val, .off_val = woff_val, \
-+	.subseq = wsubseq, .event = wevent, .event_flags = wflags}
-+
-+#define CX2072X_DAPM_SWITCH(wname,  wreg, wshift, wmask,  won_val, woff_val, \
-+	wevent, wflags) \
-+	{.id = snd_soc_dapm_switch, .name = wname, .kcontrol_news = NULL, \
-+	.num_kcontrols = 0, .reg = wreg, .shift = wshift, .mask = wmask, \
-+	.on_val = won_val, .off_val = woff_val, \
-+	.event = wevent, .event_flags = wflags}
-+
-+
-+#define CX2072X_DAPM_SWITCH(wname,  wreg, wshift, wmask,  won_val, woff_val, \
-+	wevent, wflags) \
-+	{.id = snd_soc_dapm_switch, .name = wname, .kcontrol_news = NULL, \
-+	.num_kcontrols = 0, .reg = wreg, .shift = wshift, .mask = wmask, \
-+	.on_val = won_val, .off_val = woff_val, \
-+	.event = wevent, .event_flags = wflags}
-+
-+#define CX2072X_DAPM_REG_E(wid, wname, wreg, wshift, wmask, won_val, woff_val, \
-+				wevent, wflags) \
-+	{.id = wid, .name = wname, .kcontrol_news = NULL, .num_kcontrols = 0, \
-+	.reg = wreg, .shift = wshift, .mask = wmask, \
-+	.on_val = won_val, .off_val = woff_val, \
-+	.event = wevent, .event_flags = wflags}
-+
-+static const struct snd_soc_dapm_widget cx2072x_dapm_widgets[] = {
-+	/*Playback*/
-+	SND_SOC_DAPM_AIF_IN("In AIF", "Playback", 0, SND_SOC_NOPM, 0, 0),
-+
-+	SND_SOC_DAPM_REG(snd_soc_dapm_dac, "DAC1", CX2072X_DAC1_POWER_STATE,
-+	0, 0xFFF, 0x00, 0x03),
-+
-+	SND_SOC_DAPM_REG(snd_soc_dapm_dac, "DAC2", CX2072X_DAC2_POWER_STATE,
-+	0, 0xFFF, 0x00, 0x03),
-+
-+	SND_SOC_DAPM_MUX("PortA Mux", SND_SOC_NOPM, 0, 0, &porta_mux),
-+	SND_SOC_DAPM_MUX("PortG Mux", SND_SOC_NOPM, 0, 0, &portg_mux),
-+	SND_SOC_DAPM_MUX("PortE Mux", SND_SOC_NOPM, 0, 0, &porte_mux),
-+
-+	SND_SOC_DAPM_REG(snd_soc_dapm_switch, "PortA",
-+		CX2072X_PORTA_POWER_STATE, 0, 0xFFF, 0x00, 0x03),
-+	SND_SOC_DAPM_REG(snd_soc_dapm_switch, "PortG",
-+		CX2072X_PORTG_POWER_STATE, 0, 0xFFF, 0x00, 0x03),
-+	CX2072X_DAPM_SWITCH("PortG", CX2072X_PORTG_POWER_STATE, 0, 0xFF,
-+		0x00, 0x03, portg_power_ev, SND_SOC_DAPM_POST_PMU),
-+
-+	CX2072X_DAPM_SUPPLY_S("AFG Power", 0, CX2072X_AFG_POWER_STATE,
-+		0, 0xFFF, 0x00, 0x03, afg_power_ev,
-+		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
-+
-+	SND_SOC_DAPM_OUTPUT("PORTA"),
-+	SND_SOC_DAPM_OUTPUT("PORTG"),
-+	SND_SOC_DAPM_OUTPUT("PORTE"),
-+
-+	/*Capture*/
-+	SND_SOC_DAPM_AIF_OUT("Out AIF", "Capture", 0, SND_SOC_NOPM, 0, 0),
-+
-+	CX2072X_DAPM_REG_E(snd_soc_dapm_adc, "ADC1", CX2072X_ADC1_POWER_STATE,
-+		0, 0xFF, 0x00, 0x03, adc1_power_ev,
-+		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
-+
-+	SND_SOC_DAPM_REG(snd_soc_dapm_adc, "ADC2", CX2072X_ADC2_POWER_STATE,
-+		0, 0xFF, 0x00, 0x03),
-+
-+	SND_SOC_DAPM_MUX("ADC1 Mux", SND_SOC_NOPM, 0, 0, &adc1_mux),
-+
-+	SND_SOC_DAPM_REG(snd_soc_dapm_switch, "PortB",
-+		CX2072X_PORTB_POWER_STATE, 0, 0xFFF, 0x00, 0x03),
-+	SND_SOC_DAPM_REG(snd_soc_dapm_switch, "PortC",
-+		CX2072X_PORTC_POWER_STATE, 0, 0xFFF, 0x00, 0x03),
-+	SND_SOC_DAPM_REG(snd_soc_dapm_switch, "PortD",
-+		CX2072X_PORTD_POWER_STATE, 0, 0xFFF, 0x00, 0x03),
-+	SND_SOC_DAPM_REG(snd_soc_dapm_switch, "PortE",
-+		CX2072X_PORTE_POWER_STATE, 0, 0xFFF, 0x00, 0x03),
-+	SND_SOC_DAPM_REG(snd_soc_dapm_switch, "Widget15",
-+		CX2072X_MIXER_POWER_STATE, 0, 0xFFF, 0x00, 0x03),
-+
-+	SND_SOC_DAPM_INPUT("PORTB"),
-+	SND_SOC_DAPM_INPUT("PORTC"),
-+	SND_SOC_DAPM_INPUT("PORTD"),
-+
-+	SND_SOC_DAPM_MICBIAS("Headset Bias", CX2072X_ANALOG_TEST11, 1, 0),
-+	SND_SOC_DAPM_MICBIAS("PortD Mic Bias", CX2072X_PORTD_PIN_CTRL, 2, 0),
-+	SND_SOC_DAPM_MICBIAS("PortB Mic Bias", CX2072X_PORTB_PIN_CTRL, 2, 0),
-+
-+};
-+
-+static const struct snd_soc_dapm_route cx2072x_intercon[] = {
-+
-+	/* Playback */
-+	{"In AIF", NULL, "AFG Power"},
-+	{"DAC1", NULL, "In AIF"},
-+	{"DAC2", NULL, "In AIF"},
-+	{"PortA Mux", "DAC1 Switch", "DAC1"},
-+	{"PortA Mux", "DAC2 Switch", "DAC2"},
-+	{"PortG Mux", "DAC1 Switch", "DAC1"},
-+	{"PortG Mux", "DAC2 Switch", "DAC2"},
-+	{"PortE Mux", "DAC1 Switch", "DAC1"},
-+	{"PortE Mux", "DAC2 Switch", "DAC2"},
-+	{"Widget15", NULL, "DAC1"},
-+	{"Widget15", NULL, "DAC2"},
-+	{"PortA", NULL, "PortA Mux"},
-+	{"PortG", NULL, "PortG Mux"},
-+	{"PortE", NULL, "PortE Mux"},
-+	{"PORTA", NULL, "PortA"},
-+	{"PORTG", NULL, "PortG"},
-+	{"PORTE", NULL, "PortE"},
-+
-+	/* Capture */
-+	{"PORTD", NULL, "Headset Bias"},
-+	{"PortD", NULL, "PORTD"},
-+	{"PortC", NULL, "PORTC"},
-+	{"PortB", NULL, "PORTB"},
-+	{"ADC1 Mux", "PortD Switch", "PortD"},
-+	{"ADC1 Mux", "PortC Switch", "PortC"},
-+	{"ADC1 Mux", "PortB Switch", "PortB"},
-+	{"ADC1 Mux", "Widget15 Switch", "Widget15"},
-+	{"ADC1", NULL, "ADC1 Mux"},
-+	{"Out AIF", NULL, "ADC1"},
-+	{"Out AIF", NULL, "AFG Power"},
-+
-+};
-+
-+
-+static void cx2072x_sw_reset(struct cx2072x_priv *cx2072x)
-+{
-+
-+	regmap_write(cx2072x->regmap, CX2072X_AFG_FUNCTION_RESET, 0x01);
-+	regmap_write(cx2072x->regmap, CX2072X_AFG_FUNCTION_RESET, 0x01);
-+}
-+
-+static int cx2072x_init(struct snd_soc_codec *codec)
-+{
-+	struct cx2072x_priv *cx2072x = get_cx2072x_priv(codec);
-+	int ret;
-+
-+	cx2072x_sw_reset(cx2072x);
-+
-+	cx2072x->plbk_dsp_changed = true;
-+	cx2072x->plbk_dsp_init = false;
-+
-+	regmap_update_bits(cx2072x->regmap, CX2072X_DIGITAL_TEST15,
-+		0x00, 0x06);  /* reduce the monitor time.*/
-+
-+	cx2072x_config_headset_det(cx2072x);
-+
-+	regmap_update_bits(cx2072x->regmap, CX2072X_PORTC_PIN_CTRL,
-+		0x20, 0x20);  /*reduce the monitor time*/
-+
-+	ret = regmap_register_patch(cx2072x->regmap, cx2072x_patch,
-+		ARRAY_SIZE(cx2072x_patch));
-+	if (ret)
-+		return ret;
-+
-+	/*enable bclk and EAPD input*/
-+	if (cx2072x->rev_id == CX2072X_REV_A2)
-+		regmap_update_bits(cx2072x->regmap, CX2072X_DIGITAL_BIOS_TEST2,
-+			0x84, 0xFF);
-+
-+	return 0;
-+}
-+static int cx2072x_set_bias_level(struct snd_soc_codec *codec,
-+enum snd_soc_bias_level level)
-+{
-+	struct cx2072x_priv *cx2072x = get_cx2072x_priv(codec);
-+	const enum snd_soc_bias_level old_level = 
-+		 snd_soc_codec_get_bias_level(codec);
-+
-+	switch (level) {
-+	case SND_SOC_BIAS_ON:
-+		dev_dbg(cx2072x->dev, "SND_SOC_BIAS_ON\n");
-+		/* Enable Headset Mic Bias */
-+		if (cx2072x->is_biason == 0)
-+			cx2072x->is_biason = 1;
-+		break;
-+	case SND_SOC_BIAS_PREPARE:
-+		dev_dbg(cx2072x->dev, "SND_SOC_BIAS_PREPARE\n");
-+		if (SND_SOC_BIAS_STANDBY == old_level) {
-+			dev_dbg(cx2072x->dev, "SND_SOC_BIAS_STANDBY = > SND_SOC_BIAS_PREPARE\n");
-+#ifdef INTEL_MCLK_CONTROL
-+			/*FIXME: added some delay to make sure the MCLK
-+			 * is stable before Codec is on. */
-+			mdelay(3);
-+			dev_dbg(cx2072x->dev, "Turn on MCLK\n");
-+#endif
-+		}
-+		break;
-+	case SND_SOC_BIAS_STANDBY:
-+		dev_dbg(cx2072x->dev, "SND_SOC_BIAS_STANDBY\n");
-+
-+		if (SND_SOC_BIAS_OFF == old_level) {
-+			dev_dbg(codec->dev, "Initialize codec\n");
-+#ifdef INTEL_MCLK_CONTROL
-+			dev_dbg(cx2072x->dev, "Turn on MCLK\n");
-+			/*FIXME: added some delay to make sure the MCLK is
-+			  stable before Codec is on. */
-+			mdelay(3);
-+#endif
-+			cx2072x_init(codec);
-+		}
-+	/*power device into standby mode*/
-+#ifdef INTEL_MCLK_CONTROL
-+		dev_dbg(cx2072x->dev, "Turn off MCLK\n");
-+#endif
-+		break;
-+	case SND_SOC_BIAS_OFF:
-+		dev_dbg(cx2072x->dev, "SND_SOC_BIAS_OFF\n");
-+		/* Gracefully shutdwon codec*/
-+
-+		regmap_write(cx2072x->regmap, CX2072X_PORTA_POWER_STATE, 3);
-+		regmap_write(cx2072x->regmap, CX2072X_PORTB_POWER_STATE, 3);
-+		regmap_write(cx2072x->regmap, CX2072X_PORTC_POWER_STATE, 3);
-+		regmap_write(cx2072x->regmap, CX2072X_PORTD_POWER_STATE, 3);
-+		regmap_write(cx2072x->regmap, CX2072X_PORTG_POWER_STATE, 3);
-+		regmap_write(cx2072x->regmap, CX2072X_ADC1_POWER_STATE, 3);
-+		regmap_write(cx2072x->regmap, CX2072X_ADC2_POWER_STATE, 3);
-+		regmap_write(cx2072x->regmap, CX2072X_DAC1_POWER_STATE, 3);
-+		regmap_write(cx2072x->regmap, CX2072X_DAC2_POWER_STATE, 3);
-+		regmap_write(cx2072x->regmap, CX2072X_AFG_POWER_STATE, 3);
-+		regmap_update_bits(cx2072x->regmap, CX2072X_DIGITAL_BIOS_TEST0,
-+			0x10, 0x10);
-+		/*Shutdown codec completely*/
-+		cx2072x_sw_reset(cx2072x);
-+		break;
-+	}
-+	return 0;
-+}
-+
-+
-+static int cx2072x_probe(struct snd_soc_codec *codec)
-+{
-+	struct cx2072x_priv *cx2072x = get_cx2072x_priv(codec);
-+	int ret = 0;
-+	unsigned int ven_id;
-+
-+	cx2072x->codec = codec;
-+	codec->control_data = cx2072x->regmap;
-+
-+	dev_dbg(codec->dev, "codec version: 4.4.18\n");
-+	regmap_read(cx2072x->regmap, CX2072X_VENDOR_ID, &ven_id);
-+	regmap_read(cx2072x->regmap, CX2072X_REVISION_ID, &cx2072x->rev_id);
-+	dev_dbg(codec->dev, "codec version: %08x,%08x\n",
-+		ven_id, cx2072x->rev_id);
-+
-+#ifdef ENABLE_MIC_POP_WA
-+	INIT_DELAYED_WORK(&codec->dapm.delayed_work,
-+		cx2072x_anit_mic_pop_work);
-+#endif
-+
-+	/*power on device*/
-+	cx2072x_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
-+
-+	return ret;
-+}
-+
-+static int cx2072x_remove(struct snd_soc_codec *codec)
-+{
-+	struct cx2072x_priv *cx2072x = get_cx2072x_priv(codec);
-+	/*power off device*/
-+	cx2072x_set_bias_level(cx2072x->codec, SND_SOC_BIAS_OFF);
-+	return 0;
-+}
-+
-+#ifdef CONFIG_PM
-+static int cx2072x_runtime_suspend(struct device *dev)
-+{
-+	struct cx2072x_priv *cx2072x = dev_get_drvdata(dev);
-+
-+	dev_dbg(cx2072x->codec->dev, "%s----%d\n", __func__, __LINE__);
-+	cx2072x_set_bias_level(cx2072x->codec, SND_SOC_BIAS_OFF);
-+
-+	return 0;
-+}
-+
-+static int cx2072x_runtime_resume(struct device *dev)
-+{
-+	struct cx2072x_priv *cx2072x = dev_get_drvdata(dev);
-+
-+	dev_dbg(cx2072x->codec->dev, "%s----%d\n", __func__, __LINE__);
-+	cx2072x_set_bias_level(cx2072x->codec, SND_SOC_BIAS_STANDBY);
-+	return 0;
-+}
-+#else
-+#define cx2072x_suspend NULL
-+#define cx2072x_resume NULL
-+#endif
-+
-+
-+
-+
-+static bool cx2072x_readable_register(struct device *dev, unsigned int reg)
-+{
-+	switch (reg) {
-+
-+	case CX2072X_VENDOR_ID:
-+	case CX2072X_REVISION_ID:
-+	case CX2072X_CURRENT_BCLK_FREQUENCY:
-+	case CX2072X_AFG_POWER_STATE:
-+	case CX2072X_UM_RESPONSE:
-+	case CX2072X_GPIO_DATA:
-+	case CX2072X_GPIO_ENABLE:
-+	case CX2072X_GPIO_DIRECTION:
-+	case CX2072X_GPIO_WAKE:
-+	case CX2072X_GPIO_UM_ENABLE:
-+	case CX2072X_GPIO_STICKY_MASK:
-+	case CX2072X_DAC1_CONVERTER_FORMAT:
-+	case CX2072X_DAC1_AMP_GAIN_RIGHT:
-+	case CX2072X_DAC1_AMP_GAIN_LEFT:
-+	case CX2072X_DAC1_POWER_STATE:
-+	case CX2072X_DAC1_CONVERTER_STREAM_CHANNEL:
-+	case CX2072X_DAC1_EAPD_ENABLE:
-+	case CX2072X_DAC2_CONVERTER_FORMAT:
-+	case CX2072X_DAC2_AMP_GAIN_RIGHT:
-+	case CX2072X_DAC2_AMP_GAIN_LEFT:
-+	case CX2072X_DAC2_POWER_STATE:
-+	case CX2072X_DAC2_CONVERTER_STREAM_CHANNEL:
-+	case CX2072X_ADC1_CONVERTER_FORMAT:
-+	case CX2072X_ADC1_AMP_GAIN_RIGHT_0:
-+	case CX2072X_ADC1_AMP_GAIN_LEFT_0:
-+	case CX2072X_ADC1_AMP_GAIN_RIGHT_1:
-+	case CX2072X_ADC1_AMP_GAIN_LEFT_1:
-+	case CX2072X_ADC1_AMP_GAIN_RIGHT_2:
-+	case CX2072X_ADC1_AMP_GAIN_LEFT_2:
-+	case CX2072X_ADC1_AMP_GAIN_RIGHT_3:
-+	case CX2072X_ADC1_AMP_GAIN_LEFT_3:
-+	case CX2072X_ADC1_AMP_GAIN_RIGHT_4:
-+	case CX2072X_ADC1_AMP_GAIN_LEFT_4:
-+	case CX2072X_ADC1_AMP_GAIN_RIGHT_5:
-+	case CX2072X_ADC1_AMP_GAIN_LEFT_5:
-+	case CX2072X_ADC1_AMP_GAIN_RIGHT_6:
-+	case CX2072X_ADC1_AMP_GAIN_LEFT_6:
-+	case CX2072X_ADC1_CONNECTION_SELECT_CONTROL:
-+	case CX2072X_ADC1_POWER_STATE:
-+	case CX2072X_ADC1_CONVERTER_STREAM_CHANNEL:
-+	case CX2072X_ADC2_CONVERTER_FORMAT:
-+	case CX2072X_ADC2_AMP_GAIN_RIGHT_0:
-+	case CX2072X_ADC2_AMP_GAIN_LEFT_0:
-+	case CX2072X_ADC2_AMP_GAIN_RIGHT_1:
-+	case CX2072X_ADC2_AMP_GAIN_LEFT_1:
-+	case CX2072X_ADC2_AMP_GAIN_RIGHT_2:
-+	case CX2072X_ADC2_AMP_GAIN_LEFT_2:
-+	case CX2072X_ADC2_CONNECTION_SELECT_CONTROL:
-+	case CX2072X_ADC2_POWER_STATE:
-+	case CX2072X_ADC2_CONVERTER_STREAM_CHANNEL:
-+	case CX2072X_PORTA_CONNECTION_SELECT_CTRL:
-+	case CX2072X_PORTA_POWER_STATE:
-+	case CX2072X_PORTA_PIN_CTRL:
-+	case CX2072X_PORTA_UNSOLICITED_RESPONSE:
-+	case CX2072X_PORTA_PIN_SENSE:
-+	case CX2072X_PORTA_EAPD_BTL:
-+	case CX2072X_PORTB_POWER_STATE:
-+	case CX2072X_PORTB_PIN_CTRL:
-+	case CX2072X_PORTB_UNSOLICITED_RESPONSE:
-+	case CX2072X_PORTB_PIN_SENSE:
-+	case CX2072X_PORTB_EAPD_BTL:
-+	case CX2072X_PORTB_GAIN_RIGHT:
-+	case CX2072X_PORTB_GAIN_LEFT:
-+	case CX2072X_PORTC_POWER_STATE:
-+	case CX2072X_PORTC_PIN_CTRL:
-+	case CX2072X_PORTC_GAIN_RIGHT:
-+	case CX2072X_PORTC_GAIN_LEFT:
-+	case CX2072X_PORTD_POWER_STATE:
-+	case CX2072X_PORTD_PIN_CTRL:
-+	case CX2072X_PORTD_UNSOLICITED_RESPONSE:
-+	case CX2072X_PORTD_PIN_SENSE:
-+	case CX2072X_PORTD_GAIN_RIGHT:
-+	case CX2072X_PORTD_GAIN_LEFT:
-+	case CX2072X_PORTE_CONNECTION_SELECT_CTRL:
-+	case CX2072X_PORTE_POWER_STATE:
-+	case CX2072X_PORTE_PIN_CTRL:
-+	case CX2072X_PORTE_UNSOLICITED_RESPONSE:
-+	case CX2072X_PORTE_PIN_SENSE:
-+	case CX2072X_PORTE_EAPD_BTL:
-+	case CX2072X_PORTE_GAIN_RIGHT:
-+	case CX2072X_PORTE_GAIN_LEFT:
-+	case CX2072X_PORTF_POWER_STATE:
-+	case CX2072X_PORTF_PIN_CTRL:
-+	case CX2072X_PORTF_UNSOLICITED_RESPONSE:
-+	case CX2072X_PORTF_PIN_SENSE:
-+	case CX2072X_PORTF_GAIN_RIGHT:
-+	case CX2072X_PORTF_GAIN_LEFT:
-+	case CX2072X_PORTG_POWER_STATE:
-+	case CX2072X_PORTG_PIN_CTRL:
-+	case CX2072X_PORTG_CONNECTION_SELECT_CTRL:
-+	case CX2072X_PORTG_EAPD_BTL:
-+	case CX2072X_PORTM_POWER_STATE:
-+	case CX2072X_PORTM_PIN_CTRL:
-+	case CX2072X_PORTM_CONNECTION_SELECT_CTRL:
-+	case CX2072X_PORTM_EAPD_BTL:
-+	case CX2072X_MIXER_POWER_STATE:
-+	case CX2072X_MIXER_GAIN_RIGHT_0:
-+	case CX2072X_MIXER_GAIN_LEFT_0:
-+	case CX2072X_MIXER_GAIN_RIGHT_1:
-+	case CX2072X_MIXER_GAIN_LEFT_1:
-+	case CX2072X_EQ_ENABLE_BYPASS:
-+	case CX2072X_EQ_B0_COEFF:
-+	case CX2072X_EQ_B1_COEFF:
-+	case CX2072X_EQ_B2_COEFF:
-+	case CX2072X_EQ_A1_COEFF:
-+	case CX2072X_EQ_A2_COEFF:
-+	case CX2072X_EQ_G_COEFF:
-+	case CX2072X_SPKR_DRC_ENABLE_STEP:
-+	case CX2072X_SPKR_DRC_CONTROL:
-+	case CX2072X_SPKR_DRC_TEST:
-+	case CX2072X_DIGITAL_BIOS_TEST0:
-+	case CX2072X_DIGITAL_BIOS_TEST2:
-+	case CX2072X_I2SPCM_CONTROL1:
-+	case CX2072X_I2SPCM_CONTROL2:
-+	case CX2072X_I2SPCM_CONTROL3:
-+	case CX2072X_I2SPCM_CONTROL4:
-+	case CX2072X_I2SPCM_CONTROL5:
-+	case CX2072X_I2SPCM_CONTROL6:
-+	case CX2072X_UM_INTERRUPT_CRTL_E:
-+	case CX2072X_CODEC_TEST2:
-+	case CX2072X_CODEC_TEST20:
-+	case CX2072X_CODEC_TEST26:
-+	case CX2072X_ANALOG_TEST4:
-+	case CX2072X_ANALOG_TEST5:
-+	case CX2072X_ANALOG_TEST6:
-+	case CX2072X_ANALOG_TEST7:
-+	case CX2072X_ANALOG_TEST8:
-+	case CX2072X_ANALOG_TEST9:
-+	case CX2072X_ANALOG_TEST10:
-+	case CX2072X_ANALOG_TEST11:
-+	case CX2072X_ANALOG_TEST12:
-+	case CX2072X_ANALOG_TEST13:
-+	case CX2072X_DIGITAL_TEST0:
-+	case CX2072X_DIGITAL_TEST1:
-+	case CX2072X_DIGITAL_TEST11:
-+	case CX2072X_DIGITAL_TEST12:
-+	case CX2072X_DIGITAL_TEST15:
-+	case CX2072X_DIGITAL_TEST16:
-+	case CX2072X_DIGITAL_TEST17:
-+	case CX2072X_DIGITAL_TEST18:
-+	case CX2072X_DIGITAL_TEST19:
-+	case CX2072X_DIGITAL_TEST20:
-+		return true;
-+	default:
-+		return false;
-+	}
-+}
-+
-+static bool cx2072x_volatile_register(struct device *dev, unsigned int reg)
-+{
-+	switch (reg) {
-+	case CX2072X_VENDOR_ID:
-+	case CX2072X_REVISION_ID:
-+	case CX2072X_UM_INTERRUPT_CRTL_E:
-+	case CX2072X_DIGITAL_TEST11:
-+	case CX2072X_PORTA_PIN_SENSE:
-+	case CX2072X_PORTB_PIN_SENSE:
-+	case CX2072X_PORTD_PIN_SENSE:
-+	case CX2072X_PORTE_PIN_SENSE:
-+	case CX2072X_PORTF_PIN_SENSE:
-+	case CX2072X_EQ_G_COEFF:
-+	case CX2072X_EQ_BAND:
-+		return true;
-+	default:
-+		return false;
-+
-+	}
-+}
-+
-+static struct snd_soc_codec_driver soc_codec_driver_cx2072x = {
-+	.probe = cx2072x_probe,
-+	.remove = cx2072x_remove,
-+	.set_bias_level = cx2072x_set_bias_level,
-+	.component_driver = {
-+		.controls = cx2072x_snd_controls,
-+		.num_controls = ARRAY_SIZE(cx2072x_snd_controls),
-+		.dapm_widgets = cx2072x_dapm_widgets,
-+		.num_dapm_widgets = ARRAY_SIZE(cx2072x_dapm_widgets),
-+		.dapm_routes = cx2072x_intercon,
-+		.num_dapm_routes = ARRAY_SIZE(cx2072x_intercon),
-+	}
-+};
-+
-+/*
-+ * DAI ops
-+ */
-+static struct snd_soc_dai_ops cx2072x_dai_ops = {
-+	.set_sysclk = cx2072x_set_dai_sysclk,
-+	.set_fmt = cx2072x_set_dai_fmt,
-+	.set_tdm_slot = cx2072x_set_tdm_slot,
-+	.hw_params = cx2072x_hw_params,
-+	.digital_mute = cx2072x_digital_mute,
-+	.set_bclk_ratio	= cx2072x_set_dai_bclk_ratio
-+};
-+
-+/*
-+ * DAI driver
-+ */
-+static struct snd_soc_dai_driver soc_codec_cx2072x_dai = {
-+	.name = "cx2072x-hifi",
-+	.playback = {
-+		.stream_name = "Playback",
-+		.channels_min = 1,
-+		.channels_max = 2,
-+		.rates = CX2072X_RATES_DSP,
-+		.formats = CX2072X_FORMATS,
-+	},
-+	.capture = {
-+		.stream_name = "Capture",
-+		.channels_min = 1,
-+		.channels_max = 2,
-+		.rates = CX2072X_RATES_DSP,
-+		.formats = CX2072X_FORMATS,
-+	},
-+	.ops = &cx2072x_dai_ops,
-+	.symmetric_rates = 1,
-+};
-+EXPORT_SYMBOL_GPL(soc_codec_cx2072x_dai);
-+
-+static const struct regmap_config cx2072x_regmap = {
-+	.reg_bits = 16,
-+	.val_bits = 32,
-+	.max_register = CX2072X_REG_MAX, .reg_defaults = cx2072x_reg_defaults,
-+	.num_reg_defaults = ARRAY_SIZE(cx2072x_reg_defaults),
-+	.cache_type = REGCACHE_RBTREE,
-+
-+	.readable_reg = cx2072x_readable_register,
-+	.volatile_reg = cx2072x_volatile_register,
-+	.reg_read = cx2072x_reg_read,
-+	.reg_write = cx2072x_reg_write,
-+};
-+
-+
-+static int cx2072x_i2c_probe(struct i2c_client *i2c,
-+	const struct i2c_device_id *id)
-+{
-+	int ret = -1;
-+	struct cx2072x_priv *cx2072x;
-+
-+	dev_dbg(&i2c->dev, "CX2072X codec driver i2c probe() is called\n");
-+
-+	cx2072x = (struct cx2072x_priv *)devm_kzalloc(
-+		&i2c->dev, sizeof(struct cx2072x_priv), GFP_KERNEL);
-+	if (cx2072x == NULL) {
-+		dev_err(&i2c->dev, "Out of memory!\n");
-+		return -ENOMEM;
-+	}
-+
-+	mutex_init(&cx2072x->lock);
-+
-+	cx2072x->regmap = devm_regmap_init(&i2c->dev, NULL, i2c,
-+		&cx2072x_regmap);
-+	if (IS_ERR(&cx2072x->regmap)) {
-+		ret = PTR_ERR(cx2072x->regmap);
-+		dev_err(&i2c->dev, "Failed to init regmap: %d\n", ret);
-+		return ret;
-+	}
-+
-+	i2c_set_clientdata(i2c, cx2072x);
-+
-+	cx2072x->dev = &i2c->dev;
-+	cx2072x->pll_changed = true;
-+	cx2072x->i2spcm_changed = true;
-+
-+	/* setts the frame size to
-+	 * Frame size = number of channel * sample width
-+	 */
-+	cx2072x->bclk_ratio = 0;
-+
-+	ret = snd_soc_register_codec(cx2072x->dev,
-+		&soc_codec_driver_cx2072x, &soc_codec_cx2072x_dai,
-+		1);
-+	if (ret < 0)
-+		dev_err(cx2072x->dev,
-+		"Failed to register codec: %d\n", ret);
-+	else
-+		dev_dbg(cx2072x->dev,
-+		"%s: Register codec.\n", __func__);
-+
-+	return ret;
-+}
-+
-+static int cx2072x_i2c_remove(struct i2c_client *client)
-+{
-+	snd_soc_unregister_codec(&client->dev);
-+	return 0;
-+}
-+
-+static void cx2072x_i2c_shutdown(struct i2c_client *client)
-+{
-+	struct cx2072x_priv *cx2072x = i2c_get_clientdata(client);
-+	cx2072x_set_bias_level(cx2072x->codec, SND_SOC_BIAS_OFF);
-+}
-+
-+
-+const struct dev_pm_ops cx2072x_pm_ops = {
-+	SET_RUNTIME_PM_OPS(cx2072x_runtime_suspend, cx2072x_runtime_resume,
-+	NULL)
-+};
-+static const struct i2c_device_id cx2072x_i2c_id[] = {
-+	{ "cx20721", 0 },
-+	{ "cx20722", 0 },
-+	{ "14F10720", 0 },
-+	{}
-+};
-+MODULE_DEVICE_TABLE(i2c, cx2072x_i2c_id);
-+
-+static const struct of_device_id cx2072x_of_match[] = {
-+	{ .compatible = "cnxt,cx20721", },
-+	{ .compatible = "cnxt,cx20723", },
-+	{ .compatible = "cnxt,cx7601", },
-+	{}
-+};
-+MODULE_DEVICE_TABLE(of, cx2072x_of_match);
-+#ifdef CONFIG_ACPI
-+static struct acpi_device_id cx2072x_acpi_match[] = {
-+	{ "14F10720", 0 },
-+	{},
-+};
-+MODULE_DEVICE_TABLE(acpi, cx2072x_acpi_match);
-+#endif
-+
-+static struct i2c_driver cx2072x_i2c_driver = {
-+	.probe = cx2072x_i2c_probe,
-+	.remove = cx2072x_i2c_remove,
-+	.shutdown = cx2072x_i2c_shutdown,
-+	.id_table = cx2072x_i2c_id,
-+	.driver = {
-+		.name = "cx2072x",
-+		.owner = THIS_MODULE,
-+		.of_match_table = cx2072x_of_match,
-+#ifdef CONFIG_ACPI
-+		.acpi_match_table = ACPI_PTR(cx2072x_acpi_match),
-+#endif
-+		.pm	= &cx2072x_pm_ops,
-+	},
-+};
-+
-+module_i2c_driver(cx2072x_i2c_driver);
-+
-+MODULE_DESCRIPTION("ASoC cx2072x Codec Driver");
-+MODULE_AUTHOR("Simon Ho <simon.ho@conexant.com>");
-+MODULE_LICENSE("GPL");
-+
-diff --git a/sound/soc/codecs/cx2072x.h b/sound/soc/codecs/cx2072x.h
-new file mode 100644
-index 000000000000..67b90c184c6b
---- /dev/null
-+++ b/sound/soc/codecs/cx2072x.h
-@@ -0,0 +1,339 @@
-+/*
-+ * ALSA SoC CX2072x Solana codec driver
-+ *
-+ * Copyright:   (C) 2016 Conexant Systems, Inc.
-+ *
-+ * 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.
-+ *
-+ ************************************************************************/
-+
-+#define NUM_OF_DAI 1
-+#define CX2072X_MCLK_PLL 1
-+#define CX2072X_MCLK_EXTERNAL_PLL 1
-+#define CX2072X_MCLK_INTERNAL_OSC 2
-+
-+/*#define CX2072X_RATES		SNDRV_PCM_RATE_8000_192000*/
-+#define CX2072X_RATES_DSP	SNDRV_PCM_RATE_48000
-+
-+#define CX2072X_REG_MAX 0x8a3c
-+#define AUDDRV_VERSION(major0, major1, minor, build) \
-+		((major0)<<24 | (major1)<<16 | (minor)<<8 | (build))
-+
-+#define CX2072X_VENDOR_ID                                0x0200
-+#define CX2072X_REVISION_ID                              0x0208
-+#define CX2072X_CURRENT_BCLK_FREQUENCY                   0x00dc
-+#define CX2072X_AFG_POWER_STATE                          0x0414
-+#define CX2072X_UM_RESPONSE                              0x0420
-+#define CX2072X_GPIO_DATA                                0x0454
-+#define CX2072X_GPIO_ENABLE                              0x0458
-+#define CX2072X_GPIO_DIRECTION                           0x045c
-+#define CX2072X_GPIO_WAKE                                0x0460
-+#define CX2072X_GPIO_UM_ENABLE                           0x0464
-+#define CX2072X_GPIO_STICKY_MASK                         0x0468
-+#define CX2072X_AFG_FUNCTION_RESET                       0x07FC
-+#define CX2072X_DAC1_CONVERTER_FORMAT                    0x43c8
-+#define CX2072X_DAC1_AMP_GAIN_RIGHT                      0x41c0
-+#define CX2072X_DAC1_AMP_GAIN_LEFT                       0x41e0
-+#define CX2072X_DAC1_POWER_STATE                         0x4014
-+#define CX2072X_DAC1_CONVERTER_STREAM_CHANNEL            0x4018
-+#define CX2072X_DAC1_EAPD_ENABLE                         0x4030
-+#define CX2072X_DAC2_CONVERTER_FORMAT                    0x47c8
-+#define CX2072X_DAC2_AMP_GAIN_RIGHT                      0x45c0
-+#define CX2072X_DAC2_AMP_GAIN_LEFT                       0x45e0
-+#define CX2072X_DAC2_POWER_STATE                         0x4414
-+#define CX2072X_DAC2_CONVERTER_STREAM_CHANNEL            0x4418
-+#define CX2072X_ADC1_CONVERTER_FORMAT                    0x4fc8
-+#define CX2072X_ADC1_AMP_GAIN_RIGHT_0                    0x4d80
-+#define CX2072X_ADC1_AMP_GAIN_LEFT_0                     0x4da0
-+#define CX2072X_ADC1_AMP_GAIN_RIGHT_1                    0x4d84
-+#define CX2072X_ADC1_AMP_GAIN_LEFT_1                     0x4da4
-+#define CX2072X_ADC1_AMP_GAIN_RIGHT_2                    0x4d88
-+#define CX2072X_ADC1_AMP_GAIN_LEFT_2                     0x4da8
-+#define CX2072X_ADC1_AMP_GAIN_RIGHT_3                    0x4d8c
-+#define CX2072X_ADC1_AMP_GAIN_LEFT_3                     0x4dac
-+#define CX2072X_ADC1_AMP_GAIN_RIGHT_4                    0x4d90
-+#define CX2072X_ADC1_AMP_GAIN_LEFT_4                     0x4db0
-+#define CX2072X_ADC1_AMP_GAIN_RIGHT_5                    0x4d94
-+#define CX2072X_ADC1_AMP_GAIN_LEFT_5                     0x4db4
-+#define CX2072X_ADC1_AMP_GAIN_RIGHT_6                    0x4d98
-+#define CX2072X_ADC1_AMP_GAIN_LEFT_6                     0x4db8
-+#define CX2072X_ADC1_CONNECTION_SELECT_CONTROL           0x4c04
-+#define CX2072X_ADC1_POWER_STATE                         0x4c14
-+#define CX2072X_ADC1_CONVERTER_STREAM_CHANNEL            0x4c18
-+#define CX2072X_ADC2_CONVERTER_FORMAT                    0x53c8
-+#define CX2072X_ADC2_AMP_GAIN_RIGHT_0                    0x5180
-+#define CX2072X_ADC2_AMP_GAIN_LEFT_0                     0x51a0
-+#define CX2072X_ADC2_AMP_GAIN_RIGHT_1                    0x5184
-+#define CX2072X_ADC2_AMP_GAIN_LEFT_1                     0x51a4
-+#define CX2072X_ADC2_AMP_GAIN_RIGHT_2                    0x5188
-+#define CX2072X_ADC2_AMP_GAIN_LEFT_2                     0x51a8
-+#define CX2072X_ADC2_CONNECTION_SELECT_CONTROL           0x5004
-+#define CX2072X_ADC2_POWER_STATE                         0x5014
-+#define CX2072X_ADC2_CONVERTER_STREAM_CHANNEL            0x5018
-+#define CX2072X_PORTA_CONNECTION_SELECT_CTRL             0x5804
-+#define CX2072X_PORTA_POWER_STATE                        0x5814
-+#define CX2072X_PORTA_PIN_CTRL                           0x581c
-+#define CX2072X_PORTA_UNSOLICITED_RESPONSE               0x5820
-+#define CX2072X_PORTA_PIN_SENSE                          0x5824
-+#define CX2072X_PORTA_EAPD_BTL                           0x5830
-+#define CX2072X_PORTB_POWER_STATE                        0x6014
-+#define CX2072X_PORTB_PIN_CTRL                           0x601c
-+#define CX2072X_PORTB_UNSOLICITED_RESPONSE               0x6020
-+#define CX2072X_PORTB_PIN_SENSE                          0x6024
-+#define CX2072X_PORTB_EAPD_BTL                           0x6030
-+#define CX2072X_PORTB_GAIN_RIGHT                         0x6180
-+#define CX2072X_PORTB_GAIN_LEFT                          0x61a0
-+#define CX2072X_PORTC_POWER_STATE                        0x6814
-+#define CX2072X_PORTC_PIN_CTRL                           0x681c
-+#define CX2072X_PORTC_GAIN_RIGHT                         0x6980
-+#define CX2072X_PORTC_GAIN_LEFT                          0x69a0
-+#define CX2072X_PORTD_POWER_STATE                        0x6414
-+#define CX2072X_PORTD_PIN_CTRL                           0x641c
-+#define CX2072X_PORTD_UNSOLICITED_RESPONSE               0x6420
-+#define CX2072X_PORTD_PIN_SENSE                          0x6424
-+#define CX2072X_PORTD_GAIN_RIGHT                         0x6580
-+#define CX2072X_PORTD_GAIN_LEFT                          0x65a0
-+#define CX2072X_PORTE_CONNECTION_SELECT_CTRL             0x7404
-+#define CX2072X_PORTE_POWER_STATE                        0x7414
-+#define CX2072X_PORTE_PIN_CTRL                           0x741c
-+#define CX2072X_PORTE_UNSOLICITED_RESPONSE               0x7420
-+#define CX2072X_PORTE_PIN_SENSE                          0x7424
-+#define CX2072X_PORTE_EAPD_BTL                           0x7430
-+#define CX2072X_PORTE_GAIN_RIGHT                         0x7580
-+#define CX2072X_PORTE_GAIN_LEFT                          0x75a0
-+#define CX2072X_PORTF_POWER_STATE                        0x7814
-+#define CX2072X_PORTF_PIN_CTRL                           0x781c
-+#define CX2072X_PORTF_UNSOLICITED_RESPONSE               0x7820
-+#define CX2072X_PORTF_PIN_SENSE                          0x7824
-+#define CX2072X_PORTF_GAIN_RIGHT                         0x7980
-+#define CX2072X_PORTF_GAIN_LEFT                          0x79a0
-+#define CX2072X_PORTG_POWER_STATE                        0x5c14
-+#define CX2072X_PORTG_PIN_CTRL                           0x5c1c
-+#define CX2072X_PORTG_CONNECTION_SELECT_CTRL             0x5c04
-+#define CX2072X_PORTG_EAPD_BTL                           0x5c30
-+#define CX2072X_PORTM_POWER_STATE                        0x8814
-+#define CX2072X_PORTM_PIN_CTRL                           0x881c
-+#define CX2072X_PORTM_CONNECTION_SELECT_CTRL             0x8804
-+#define CX2072X_PORTM_EAPD_BTL                           0x8830
-+#define CX2072X_MIXER_POWER_STATE                        0x5414
-+#define CX2072X_MIXER_GAIN_RIGHT_0                       0x5580
-+#define CX2072X_MIXER_GAIN_LEFT_0                        0x55a0
-+#define CX2072X_MIXER_GAIN_RIGHT_1                       0x5584
-+#define CX2072X_MIXER_GAIN_LEFT_1                        0x55a4
-+#define CX2072X_EQ_ENABLE_BYPASS                         0x6d00
-+#define CX2072X_EQ_B0_COEFF                              0x6d02
-+#define CX2072X_EQ_B1_COEFF                              0x6d04
-+#define CX2072X_EQ_B2_COEFF                              0x6d06
-+#define CX2072X_EQ_A1_COEFF                              0x6d08
-+#define CX2072X_EQ_A2_COEFF                              0x6d0a
-+#define CX2072X_EQ_G_COEFF                               0x6d0c
-+#define CX2072X_EQ_BAND                                  0x6d0d
-+#define CX2072X_SPKR_DRC_ENABLE_STEP                     0x6d10
-+#define CX2072X_SPKR_DRC_CONTROL                         0x6d14
-+#define CX2072X_SPKR_DRC_TEST                            0X6D18
-+#define CX2072X_DIGITAL_BIOS_TEST0                       0x6d80
-+#define CX2072X_DIGITAL_BIOS_TEST2                       0x6d84
-+#define CX2072X_I2SPCM_CONTROL1                          0x6e00
-+#define CX2072X_I2SPCM_CONTROL2                          0x6e04
-+#define CX2072X_I2SPCM_CONTROL3                          0x6e08
-+#define CX2072X_I2SPCM_CONTROL4                          0x6e0c
-+#define CX2072X_I2SPCM_CONTROL5                          0x6e10
-+#define CX2072X_I2SPCM_CONTROL6                          0x6e18
-+#define CX2072X_UM_INTERRUPT_CRTL_E                      0x6e14
-+#define CX2072X_CODEC_TEST2                              0x7108
-+#define CX2072X_CODEC_TEST20                             0x7310
-+#define CX2072X_CODEC_TEST26                             0x7328
-+#define CX2072X_ANALOG_TEST3                             0x718c
-+#define CX2072X_ANALOG_TEST4                             0x7190
-+#define CX2072X_ANALOG_TEST5                             0x7194
-+#define CX2072X_ANALOG_TEST6                             0x7198
-+#define CX2072X_ANALOG_TEST7                             0x719c
-+#define CX2072X_ANALOG_TEST8                             0x71a0
-+#define CX2072X_ANALOG_TEST9                             0x71a4
-+#define CX2072X_ANALOG_TEST10                            0x71a8
-+#define CX2072X_ANALOG_TEST11                            0x71ac
-+#define CX2072X_ANALOG_TEST12                            0x71b0
-+#define CX2072X_ANALOG_TEST13                            0x71b4
-+#define CX2072X_DIGITAL_TEST0                            0x7200
-+#define CX2072X_DIGITAL_TEST1                            0x7204
-+#define CX2072X_DIGITAL_TEST11                           0x722c
-+#define CX2072X_DIGITAL_TEST12                           0x7230
-+#define CX2072X_DIGITAL_TEST15                           0x723c
-+#define CX2072X_DIGITAL_TEST16                           0x7080
-+#define CX2072X_DIGITAL_TEST17                           0x7084
-+#define CX2072X_DIGITAL_TEST18                           0x7088
-+#define CX2072X_DIGITAL_TEST19                           0x708c
-+#define CX2072X_DIGITAL_TEST20                           0x7090
-+
-+#define INVALID_GPIO -1
-+#define MAX_EQ_BAND 7
-+#define MAC_EQ_COEFF 11
-+#define MAX_DRC_REGS 9
-+#define MIC_EQ_COEFF 10
-+/*
-+static unsigned char cx2072x_eq_coeff_flat[MAX_EQ_BAND][MAC_EQ_COEFF] = {
-+	{0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03},
-+	{0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03},
-+	{0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03},
-+	{0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03},
-+	{0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03},
-+	{0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03},
-+	{0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03},
-+};
-+*/
-+/*
-+static unsigned char cx2072x_miceq_coeff_array[][MIC_EQ_COEFF] = {
-+	{0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-+	{0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-+	{0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-+	{0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-+	{0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-+	{0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-+	{0x42, 0x17, 0x85, 0x2e, 0x42, 0x17, 0x0a, 0x5d, 0xed, 0xc5},
-+};
-+*/
-+
-+
-+enum cx2072x_jack_types {
-+	CX_JACK_NONE = 0x0000,
-+	CX_JACK_HEADPHONE = 0x0001,
-+	CX_JACK_APPLE_HEADSET = 0x0002,
-+	CX_JACK_NOKIE_HEADSET = 0x0003,
-+
-+};
-+
-+int cx2072x_hs_jack_report(struct snd_soc_codec *codec);
-+
-+typedef enum _REG_SAMPLE_SIZE{
-+	SAMPLE_SIZE_8_BITS = 0 ,
-+	SAMPLE_SIZE_16_BITS = 1 ,
-+	SAMPLE_SIZE_24_BITS = 2 ,
-+	SAMPLE_SIZE_RESERVED = 3 
-+}REG_SAMPLE_SIZE;
-+
-+typedef union _REG_I2SPCM_CTRL_REG1{
-+	struct {
-+		u32 rx_data_one_line :1;
-+		u32 rx_ws_pol        :1;
-+		u32 rx_ws_wid       :7;
-+		u32 rx_frm_len      :5;
-+		u32 rx_sa_size     :2;
-+		u32 tx_data_one_line :1;
-+		u32 tx_ws_pol        :1;
-+		u32 tx_ws_wid       :7;
-+		u32 tx_frm_len      :5;
-+		u32 tx_sa_size     :2; 
-+	}r;
-+	u32 ulVal;
-+}REG_I2SPCM_CTRL_REG1;
-+
-+
-+typedef union _REG_I2SPCM_CTRL_REG2{
-+	struct {
-+		u32 tx_en_ch1		:1;
-+		u32 tx_en_ch2		:1;
-+		u32 tx_en_ch3		:1;
-+		u32 tx_en_ch4		:1;
-+		u32 tx_en_ch5		:1;
-+		u32 tx_en_ch6		:1;
-+		u32 tx_slot_1         :5;
-+		u32 tx_slot_2         :5;
-+		u32 tx_slot_3         :5;
-+		u32 tx_slot_4         :5;
-+		u32  res               :1;
-+		u32  tx_data_neg_bclk  :1;
-+		u32  tx_master         :1;
-+		u32  tx_tri_n          :1;
-+		u32  tx_endian_sel     :1;
-+		u32  tx_dstart_dly     :1; 
-+	}r;
-+	u32 ulVal;
-+}REG_I2SPCM_CTRL_REG2;
-+
-+typedef union _REG_I2SPCM_CTRL_REG3{
-+	struct {
-+		u32 rx_en_ch1		:1;
-+		u32 rx_en_ch2		:1;
-+		u32 rx_en_ch3		:1;
-+		u32 rx_en_ch4		:1;
-+		u32 rx_en_ch5		:1;
-+		u32 rx_en_ch6		:1;
-+		u32 rx_slot_1         :5;
-+		u32 rx_slot_2         :5;
-+		u32 rx_slot_3         :5;
-+		u32 rx_slot_4         :5;
-+		u32  res               :1;
-+		u32  rx_data_neg_bclk  :1;
-+		u32  rx_master         :1;
-+		u32  rx_tri_n          :1;
-+		u32  rx_endian_sel     :1;
-+		u32  rx_dstart_dly     :1; 
-+	}r;
-+	u32 ulVal;
-+}REG_I2SPCM_CTRL_REG3;
-+
-+
-+typedef union _REG_I2SPCM_CTRL_REG4{
-+	struct {
-+		u32 rx_mute		:1;
-+		u32 tx_mute		:1;
-+		u32 reserved		:1;
-+		u32 dac_34_independent	:1;
-+		u32 dac_bclk_lrck_share:1;
-+		u32 bclk_lrck_share_en :1;
-+		u32 reserved2          :2;  
-+		u32 rx_last_dac_ch_en  :1;
-+		u32 rx_last_dac_ch     :3;
-+		u32 tx_last_adc_ch_en  :1;
-+		u32 tx_last_adc_ch     :3;
-+		u32 rx_slot_5         	:5;
-+		u32 rx_slot_6         	:5;
-+		u32 reserved3		:6;
-+	}r;
-+	u32 ulVal;
-+}REG_I2SPCM_CTRL_REG4;
-+
-+
-+typedef union _REG_I2SPCM_CTRL_REG5{
-+	struct {
-+		u32 tx_slot_5         :5;
-+		u32 reserved          :3;
-+		u32 tx_slot_6         :5;
-+		u32 reserved2         :3;
-+		u32 reserved3         :8;
-+		u32 i2s_pcm_clk_div   :7;
-+		u32  i2s_pcm_clk_div_chan_en :1;
-+	}r;
-+	u32 ulVal;
-+}REG_I2SPCM_CTRL_REG5;
-+
-+typedef union _REG_I2SPCM_CTRL_REG6{
-+	struct {
-+		u32 reserved		:5;
-+		u32 rx_pause_cycles	:3;
-+		u32 rx_pause_start_pos	:8;
-+		u32 reserved2		:5;
-+		u32 tx_pause_cycles	:3;
-+		u32 tx_pause_start_pos	:8;
-+	}r;
-+	u32 ulVal;
-+}REG_I2SPCM_CTRL_REG6;
-+
-+typedef union _REG_DIGITAL_BIOS_TEST2{
-+	struct {
-+		u32 pull_down_eapd :2;
-+		u32  input_en_eapd_pad :1;
-+		u32  push_pull_mode    :1;
-+		u32 eapd_pad_output_driver :2;
-+		u32  pll_source        :1;
-+		u32  i2s_bclk_en       :1; 
-+		u32  i2s_bclk_invert   :1;
-+		u32  pll_ref_clock     :1;
-+		u32  class_d_sheild_clk:1;
-+		u32  audio_pll_bypass_mode:1;
-+		u32  reserved          :4;
-+	}r;
-+	u32 ulVal;
-+}REG_DIGITAL_BIOS_TEST2;
-diff --git a/sound/soc/codecs/rt5645.c b/sound/soc/codecs/rt5645.c
-index 10c2a564a715..77bde13147bd 100644
---- a/sound/soc/codecs/rt5645.c
-+++ b/sound/soc/codecs/rt5645.c
-@@ -3545,8 +3545,10 @@ MODULE_DEVICE_TABLE(i2c, rt5645_i2c_id);
- #ifdef CONFIG_ACPI
- static const struct acpi_device_id rt5645_acpi_match[] = {
- 	{ "10EC5645", 0 },
-+	{ "10EC5648", 0 },
- 	{ "10EC5650", 0 },
- 	{ "10EC5640", 0 },
-+	{ "10EC3270", 0 },
- 	{},
- };
- MODULE_DEVICE_TABLE(acpi, rt5645_acpi_match);
-@@ -3658,8 +3660,7 @@ static int rt5645_i2c_probe(struct i2c_client *i2c,
- 						       GPIOD_IN);
- 
- 	if (IS_ERR(rt5645->gpiod_hp_det)) {
--		dev_err(&i2c->dev, "failed to initialize gpiod\n");
--		return PTR_ERR(rt5645->gpiod_hp_det);
-+		dev_info(&i2c->dev, "failed to initialize gpiod\n");
- 	}
- 
- 	for (i = 0; i < ARRAY_SIZE(rt5645->supplies); i++)
-diff --git a/sound/soc/codecs/rt5670.c b/sound/soc/codecs/rt5670.c
-index 49caf1393aeb..fdc14e50d3b9 100644
---- a/sound/soc/codecs/rt5670.c
-+++ b/sound/soc/codecs/rt5670.c
-@@ -2813,6 +2813,8 @@ MODULE_DEVICE_TABLE(i2c, rt5670_i2c_id);
- #ifdef CONFIG_ACPI
- static const struct acpi_device_id rt5670_acpi_match[] = {
- 	{ "10EC5670", 0},
-+	{ "10EC5672", 0},
-+	{ "10EC5640", 0}, /* quirk */
- 	{ },
- };
- MODULE_DEVICE_TABLE(acpi, rt5670_acpi_match);
-diff --git a/sound/soc/codecs/tlv320aic31xx.c b/sound/soc/codecs/tlv320aic31xx.c
-index be1a64bfd320..a1b4e14b347a 100644
---- a/sound/soc/codecs/tlv320aic31xx.c
-+++ b/sound/soc/codecs/tlv320aic31xx.c
-@@ -192,46 +192,68 @@ static const struct aic31xx_rate_divs aic31xx_divs[] = {
- 	{12000000,   8000,	8, 1920,	128,  48,  2,	128,  48,  2},
- 	{12000000,   8000,	8, 1920,	128,  32,  3,	128,  32,  3},
- 	{12500000,   8000,	7, 8643,	128,  48,  2,	128,  48,  2},
-+	{19200000,   8000,	5, 1200,	128,  48,  2,	128,  48,  2},
-+	{19200000,   8000,	5, 1200,	128,  32,  3,	128,  32,  3},
- 	/* 11.025k rate */
- 	{12000000,  11025,	7, 5264,	128,  32,  2,	128,  32,  2},
- 	{12000000,  11025,	8, 4672,	128,  24,  3,	128,  24,  3},
- 	{12500000,  11025,	7, 2253,	128,  32,  2,	128,  32,  2},
-+	{19200000,  11025,	4, 7040,	128,  24,  2,	128,  32,  2},
-+	{19200000,  11025,      5, 2920,	128,  32,  3,	128,  24,  3},
- 	/* 16k rate */
- 	{12000000,  16000,	8, 1920,	128,  24,  2,	128,  24,  2},
- 	{12000000,  16000,	8, 1920,	128,  16,  3,	128,  16,  3},
- 	{12500000,  16000,	7, 8643,	128,  24,  2,	128,  24,  2},
-+	{19200000,  16000,	5, 1200,	128,  24,  2,	128,  24,  2},
-+	{19200000,  16000,	5, 1200,	128,  16,  3,	128,  16,  3},
- 	/* 22.05k rate */
- 	{12000000,  22050,	7, 5264,	128,  16,  2,	128,  16,  2},
- 	{12000000,  22050,	8, 4672,	128,  12,  3,	128,  12,  3},
- 	{12500000,  22050,	7, 2253,	128,  16,  2,	128,  16,  2},
-+	{19200000,  22050,	4, 7040,	128,  16,  2,	128,  16,  2},
-+	{19200000,  22050,      5, 2920,	128,  12,  3,	128,  12,  3},
- 	/* 32k rate */
- 	{12000000,  32000,	8, 1920,	128,  12,  2,	128,  12,  2},
- 	{12000000,  32000,	8, 1920,	128,   8,  3,	128,   8,  3},
- 	{12500000,  32000,	7, 8643,	128,  12,  2,	128,  12,  2},
-+	{19200000,  32000,	1, 0000,	 32,   1,  2,	 32,   1,  2},
-+	{19200000,  32000,	5, 1200,	128,   8,  3,	128,   8,  3},
- 	/* 44.1k rate */
- 	{12000000,  44100,	7, 5264,	128,   8,  2,	128,   8,  2},
- 	{12000000,  44100,	8, 4672,	128,   6,  3,	128,   6,  3},
- 	{12500000,  44100,	7, 2253,	128,   8,  2,	128,   8,  2},
-+	{19200000,  44100,	4, 7040,	128,   8,  2,	128,   8,  2},
-+	{19200000,  44100,      5, 2920,	128,   6,  3,	128,   6,  3},
- 	/* 48k rate */
- 	{12000000,  48000,	8, 1920,	128,   8,  2,	128,   8,  2},
- 	{12000000,  48000,	7, 6800,	 96,   5,  4,	 96,   5,  4},
- 	{12500000,  48000,	7, 8643,	128,   8,  2,	128,   8,  2},
-+	{19200000,  48000,	5, 1200,	128,   8,  2,	128,   8,  2},
-+	{19200000,  48000,	4, 8000,	 96,   5,  4,	 96,   5,  4},
- 	/* 88.2k rate */
- 	{12000000,  88200,	7, 5264,	 64,   8,  2,	 64,   8,  2},
- 	{12000000,  88200,	8, 4672,	 64,   6,  3,	 64,   6,  3},
- 	{12500000,  88200,	7, 2253,	 64,   8,  2,	 64,   8,  2},
-+	{19200000,  88200,	4, 7040,	 64,   8,  2,	 64,   8,  2},
-+	{19200000,  88200,      5, 2920,	 64,   6,  3,	 64,   6,  3},
- 	/* 96k rate */
- 	{12000000,  96000,	8, 1920,	 64,   8,  2,	 64,   8,  2},
- 	{12000000,  96000,	7, 6800,	 48,   5,  4,	 48,   5,  4},
- 	{12500000,  96000,	7, 8643,	 64,   8,  2,	 64,   8,  2},
-+	{19200000,  96000,	5, 1200,	 64,   8,  2,	 64,   8,  2},
-+	{19200000,  96000,	4, 8000,	 48,   5,  4,	 48,   5,  4},
- 	/* 176.4k rate */
- 	{12000000, 176400,	7, 5264,	 32,   8,  2,	 32,   8,  2},
- 	{12000000, 176400,	8, 4672,	 32,   6,  3,	 32,   6,  3},
- 	{12500000, 176400,	7, 2253,	 32,   8,  2,	 32,   8,  2},
-+	{19200000, 176400,	4, 7040,	 32,   8,  2,	 32,   8,  2},
-+	{19200000, 176400,      5, 2920,	 32,   6,  3,	 32,   6,  3},
- 	/* 192k rate */
- 	{12000000, 192000,	8, 1920,	 32,   8,  2,	 32,   8,  2},
- 	{12000000, 192000,	7, 6800,	 24,   5,  4,	 24,   5,  4},
- 	{12500000, 192000,	7, 8643,	 32,   8,  2,	 32,   8,  2},
-+	{19200000, 192000,	5, 1200,	 32,   8,  2,	 32,   8,  2},
-+	{19200000, 192000,	4, 8000,	 24,   5,  4,	 24,   5,  4},
- };
- 
- static const char * const ldac_in_text[] = {
-diff --git a/sound/soc/intel/Kconfig b/sound/soc/intel/Kconfig
-index fd5d1e091038..76de542c66b7 100644
---- a/sound/soc/intel/Kconfig
-+++ b/sound/soc/intel/Kconfig
-@@ -172,6 +172,32 @@ config SND_SOC_INTEL_BYTCR_RT5651_MACH
-           Say Y if you have such a device.
-           If unsure select "N".
- 
-+config SND_SOC_INTEL_BYTCR_AIC3100_MACH
-+        tristate "ASoC Audio driver for Intel Baytrail and Baytrail-CR with TLV320AIC31XX codec"
-+	depends on X86 && I2C && ACPI
-+	select SND_SOC_TLV320AIC31XX
-+	select SND_SST_MFLD_PLATFORM
-+	select SND_SST_IPC_ACPI
-+	select SND_SOC_INTEL_SST_MATCH if ACPI
-+	help
-+          This adds support for ASoC machine driver for Intel(R) Baytrail and Baytrail-CR
-+          platforms with TLV320AIC31XX audio codec.
-+          Say Y if you have such a device.
-+          If unsure select "N".
-+
-+config SND_SOC_INTEL_CHT_CX2072X_MACH
-+        tristate "ASoC Audio driver for Intel Baytrail and Cherrytrail with CX2072X codec"
-+        depends on X86_INTEL_LPSS && I2C && ACPI
-+        select SND_SOC_CX2072X
-+        select SND_SST_MFLD_PLATFORM
-+        select SND_SST_IPC_ACPI
-+	select SND_SOC_INTEL_SST_MATCH if ACPI
-+        help
-+          This adds support for ASoC machine driver for Intel(R) Cherrytrail & Braswell
-+          platforms with Conexant CX2072X audio codec.
-+          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 && I2C && ACPI
-diff --git a/sound/soc/intel/atom/sst/sst_acpi.c b/sound/soc/intel/atom/sst/sst_acpi.c
-index 0a88537ca58a..4e230282205d 100644
---- a/sound/soc/intel/atom/sst/sst_acpi.c
-+++ b/sound/soc/intel/atom/sst/sst_acpi.c
-@@ -400,6 +400,7 @@ static int sst_acpi_remove(struct platform_device *pdev)
- static unsigned long cht_machine_id;
- 
- #define CHT_SURFACE_MACH 1
-+#define BYT_THINKPAD_10  2
- 
- static int cht_surface_quirk_cb(const struct dmi_system_id *id)
- {
-@@ -407,6 +408,23 @@ static int cht_surface_quirk_cb(const struct dmi_system_id *id)
- 	return 1;
- }
- 
-+static int byt_thinkpad10_quirk_cb(const struct dmi_system_id *id)
-+{
-+	cht_machine_id = BYT_THINKPAD_10;
-+	return 1;
-+}
-+
-+
-+static const struct dmi_system_id byt_table[] = {
-+	{
-+		.callback = byt_thinkpad10_quirk_cb,
-+		.matches = {
-+			DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
-+			DMI_MATCH(DMI_PRODUCT_NAME, "20C3001VHH"),
-+		},
-+	},
-+	{ }
-+};
- 
- static const struct dmi_system_id cht_table[] = {
- 	{
-@@ -424,6 +442,10 @@ static struct sst_acpi_mach cht_surface_mach = {
- 	"10EC5640", "cht-bsw-rt5645", "intel/fw_sst_22a8.bin", "cht-bsw", NULL,
- 								&chv_platform_data };
- 
-+static struct sst_acpi_mach byt_thinkpad_10 = {
-+	"10EC5640", "cht-bsw-rt5672", "intel/fw_sst_0f28.bin", "cht-bsw", NULL,
-+	                                                        &byt_rvp_platform_data };
-+
- static struct sst_acpi_mach *cht_quirk(void *arg)
- {
- 	struct sst_acpi_mach *mach = arg;
-@@ -436,8 +458,21 @@ static struct sst_acpi_mach *cht_quirk(void *arg)
- 		return mach;
- }
- 
-+static struct sst_acpi_mach *byt_quirk(void *arg)
-+{
-+	struct sst_acpi_mach *mach = arg;
-+
-+	dmi_check_system(byt_table);
-+
-+	if (cht_machine_id == BYT_THINKPAD_10)
-+		return &byt_thinkpad_10;
-+	else
-+		return mach;
-+}
-+
-+
- static struct sst_acpi_mach sst_acpi_bytcr[] = {
--	{"10EC5640", "bytcr_rt5640", "intel/fw_sst_0f28.bin", "bytcr_rt5640", NULL,
-+	{"10EC5640", "bytcr_rt5640", "intel/fw_sst_0f28.bin", "bytcr_rt5640", byt_quirk,
- 						&byt_rvp_platform_data },
- 	{"10EC5642", "bytcr_rt5640", "intel/fw_sst_0f28.bin", "bytcr_rt5640", NULL,
- 						&byt_rvp_platform_data },
-@@ -445,6 +480,16 @@ static struct sst_acpi_mach sst_acpi_bytcr[] = {
- 						&byt_rvp_platform_data },
- 	{"10EC5651", "bytcr_rt5651", "intel/fw_sst_0f28.bin", "bytcr_rt5651", NULL,
- 						&byt_rvp_platform_data },
-+	/* some Baytrail platforms rely on RT5645, use CHT machine driver */
-+	{"10EC5645", "cht-bsw-rt5645", "intel/fw_sst_0f28.bin", "cht-bsw", NULL,
-+						&byt_rvp_platform_data },
-+	{"10EC5648", "cht-bsw-rt5645", "intel/fw_sst_0f28.bin", "cht-bsw", NULL,
-+						&byt_rvp_platform_data },
-+	/* use CHT driver to Baytrail Chromebooks */
-+	{"193C9890", "cht-bsw-max98090", "intel/fw_sst_0f28.bin", "cht-bsw", NULL,
-+						&byt_rvp_platform_data },
-+	{"14F10720", "cht-cx2072x", "intel/fw_sst_0f28.bin", "cht-bsw", NULL,
-+						&byt_rvp_platform_data },
- 	{},
- };
- 
-@@ -456,7 +501,9 @@ static struct sst_acpi_mach sst_acpi_chv[] = {
- 						&chv_platform_data },
- 	{"10EC5650", "cht-bsw-rt5645", "intel/fw_sst_22a8.bin", "cht-bsw", NULL,
- 						&chv_platform_data },
--	{"193C9890", "cht-bsw-max98090", "intel/fw_sst_22a8.bin", "cht-bsw", NULL,
-+	{"10EC3270", "cht-bsw-rt5645", "intel/fw_sst_22a8.bin", "cht-bsw", NULL,
-+						&chv_platform_data },
-+	{"14F10720", "cht-cx2072x", "intel/fw_sst_22a8.bin", "cht-bsw", NULL,
- 						&chv_platform_data },
- 	/* some CHT-T platforms rely on RT5640, use Baytrail machine driver */
- 	{"10EC5640", "bytcr_rt5640", "intel/fw_sst_22a8.bin", "bytcr_rt5640", cht_quirk,
-diff --git a/sound/soc/intel/boards/Makefile b/sound/soc/intel/boards/Makefile
-index 5639f10774e6..68dd93d91de9 100644
---- a/sound/soc/intel/boards/Makefile
-+++ b/sound/soc/intel/boards/Makefile
-@@ -7,6 +7,8 @@ snd-soc-sst-bxt-da7219_max98357a-objs := bxt_da7219_max98357a.o
- snd-soc-sst-bxt-rt298-objs := bxt_rt298.o
- snd-soc-sst-bytcr-rt5640-objs := bytcr_rt5640.o
- snd-soc-sst-bytcr-rt5651-objs := bytcr_rt5651.o
-+snd-soc-sst-bytcr-aic3100-objs := bytcr_aic3100.o
-+snd-soc-sst-cht-cx2072x-objs := cht_cx2072x.o
- 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
-@@ -23,6 +25,8 @@ obj-$(CONFIG_SND_SOC_INTEL_BROADWELL_MACH) += snd-soc-sst-broadwell.o
- obj-$(CONFIG_SND_SOC_INTEL_BDW_RT5677_MACH) += snd-soc-sst-bdw-rt5677-mach.o
- obj-$(CONFIG_SND_SOC_INTEL_BYTCR_RT5640_MACH) += snd-soc-sst-bytcr-rt5640.o
- obj-$(CONFIG_SND_SOC_INTEL_BYTCR_RT5651_MACH) += snd-soc-sst-bytcr-rt5651.o
-+obj-$(CONFIG_SND_SOC_INTEL_BYTCR_AIC3100_MACH) += snd-soc-sst-bytcr-aic3100.o
-+obj-$(CONFIG_SND_SOC_INTEL_CHT_CX2072X_MACH) += snd-soc-sst-cht-cx2072x.o
- 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
-diff --git a/sound/soc/intel/boards/bytcr_aic3100.c b/sound/soc/intel/boards/bytcr_aic3100.c
-new file mode 100644
-index 000000000000..f6a45f685933
---- /dev/null
-+++ b/sound/soc/intel/boards/bytcr_aic3100.c
-@@ -0,0 +1,608 @@
-+/*
-+ *  bytcr_aic3100.c - ASoc Machine driver for Intel Byt CR platform
-+ *
-+ *  Copyright (C) 2016 Intel Corporation
-+ *
-+ *  Author: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
-+ *  Based on earlier 3.14 work by Praveen Diwakar and Gurudatta Bhakte
-+ *
-+ *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-+ *
-+ *  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/init.h>
-+#include <linux/module.h>
-+#include <linux/platform_device.h>
-+#include <linux/acpi.h>
-+#include <linux/device.h>
-+#include <linux/dmi.h>
-+#include <linux/slab.h>
-+#include <asm/cpu_device_id.h>
-+#include <asm/platform_sst_audio.h>
-+#include <linux/clk.h>
-+#include <sound/pcm.h>
-+#include <sound/pcm_params.h>
-+#include <sound/soc.h>
-+#include <sound/jack.h>
-+#include "../../codecs/tlv320aic31xx.h"
-+#include "../atom/sst-atom-controls.h"
-+#include "../common/sst-acpi.h"
-+#include "../common/sst-dsp.h"
-+
-+enum {
-+	BYT_AIC3100_IN1_MAP,
-+};
-+
-+#define BYT_AIC3100_MAP(quirk)	((quirk) & 0xff)
-+#define BYT_AIC3100_SSP2_AIF    BIT(16) /* default true, use SSP2 */
-+#define BYT_AIC3100_MCLK_25MHZ	BIT(18) /* default false, use 19.2MHz */
-+
-+struct byt_aic3100_private {
-+	struct clk *mclk;
-+};
-+
-+static unsigned long byt_aic3100_quirk =
-+	BYT_AIC3100_IN1_MAP | BYT_AIC3100_SSP2_AIF;
-+
-+static void log_quirks(struct device *dev)
-+{
-+	if (BYT_AIC3100_MAP(byt_aic3100_quirk) == BYT_AIC3100_IN1_MAP)
-+		dev_info(dev, "quirk IN1_MAP enabled");
-+	if (byt_aic3100_quirk & BYT_AIC3100_SSP2_AIF)
-+		dev_info(dev, "quirk SSP2_AIF enabled");
-+	else
-+		dev_info(dev, "quirk SSP0_AIF enabled");
-+	if (byt_aic3100_quirk & BYT_AIC3100_MCLK_25MHZ)
-+		dev_info(dev, "quirk MCLK_25MHZ enabled");
-+	else
-+		dev_info(dev, "quirk MCLK_19200kHZ enabled");
-+}
-+
-+#define BYT_CODEC_DAI1	"tlv320aic31xx-hifi"
-+
-+static inline struct snd_soc_dai *byt_get_codec_dai(struct snd_soc_card *card)
-+{
-+	struct snd_soc_pcm_runtime *rtd;
-+
-+	list_for_each_entry(rtd, &card->rtd_list, list) {
-+		if (!strncmp(rtd->codec_dai->name, BYT_CODEC_DAI1,
-+			     strlen(BYT_CODEC_DAI1)))
-+			return rtd->codec_dai;
-+	}
-+	return NULL;
-+}
-+
-+static int platform_clock_control(struct snd_soc_dapm_widget *w,
-+				  struct snd_kcontrol *k, int  event)
-+{
-+	struct snd_soc_dapm_context *dapm = w->dapm;
-+	struct snd_soc_card *card = dapm->card;
-+	struct snd_soc_dai *codec_dai;
-+	struct byt_aic3100_private *priv = snd_soc_card_get_drvdata(card);
-+	int ret;
-+
-+	codec_dai = byt_get_codec_dai(card);
-+	if (!codec_dai) {
-+		dev_err(card->dev,
-+			"Codec dai not found; Unable to set platform clock\n");
-+		return -EIO;
-+	}
-+
-+	if (SND_SOC_DAPM_EVENT_ON(event)) {
-+		if (priv->mclk) {
-+			ret = clk_prepare_enable(priv->mclk);
-+			if (ret < 0) {
-+				dev_err(card->dev,
-+					"could not configure MCLK state");
-+				return ret;
-+			}
-+		}
-+
-+		if (byt_aic3100_quirk & BYT_AIC3100_MCLK_25MHZ) {
-+			ret = snd_soc_dai_set_sysclk(codec_dai,
-+						AIC31XX_PLL_CLKIN_MCLK,
-+						25000000,
-+						SND_SOC_CLOCK_IN);
-+		} else {
-+			ret = snd_soc_dai_set_sysclk(codec_dai,
-+						AIC31XX_PLL_CLKIN_MCLK,
-+						19200000,
-+						SND_SOC_CLOCK_IN);
-+		}
-+	} else {
-+		/*
-+		 * Set codec clock source to internal clock before
-+		 * turning off the platform clock. Codec needs clock
-+		 * for Jack detection and button press
-+		 */
-+		/* FIXME: use RC oscillator? */
-+		ret = snd_soc_dai_set_sysclk(codec_dai, AIC31XX_PLL_CLKIN_MCLK,
-+					0, SND_SOC_CLOCK_IN);
-+		if (!ret) {
-+			if (priv->mclk)
-+				clk_disable_unprepare(priv->mclk);
-+		}
-+	}
-+
-+	if (ret < 0) {
-+		dev_err(card->dev, "can't set codec sysclk: %d\n", ret);
-+		return ret;
-+	}
-+
-+	return 0;
-+}
-+
-+static const struct snd_soc_dapm_widget byt_aic3100_widgets[] = {
-+	SND_SOC_DAPM_HP("Headphone", NULL),
-+	SND_SOC_DAPM_MIC("Headset Mic", NULL),
-+	SND_SOC_DAPM_MIC("Internal Mic", NULL),
-+	SND_SOC_DAPM_SPK("Speakers", NULL),
-+	SND_SOC_DAPM_SUPPLY("Platform Clock", SND_SOC_NOPM, 0, 0,
-+			    platform_clock_control, SND_SOC_DAPM_PRE_PMU |
-+			    SND_SOC_DAPM_POST_PMD),
-+
-+};
-+
-+static const struct snd_soc_dapm_route byt_aic3100_audio_map[] = {
-+	/* External Speakers: HFL, HFR */
-+	{"Speakers", NULL, "SPK"},
-+
-+	/* Headset Stereophone(Headphone): HSOL, HSOR */
-+	{"Headphone", NULL, "HPL"},
-+	{"Headphone", NULL, "HPR"},
-+
-+	{"Headphone", NULL, "Platform Clock"},
-+	{"Headset Mic", NULL, "Platform Clock"},
-+	{"Internal Mic", NULL, "Platform Clock"},
-+	{"Speaker", NULL, "Platform Clock"},
-+
-+};
-+
-+static const struct snd_soc_dapm_route byt_aic3100_intmic_in1_map[] = {
-+	{"micbias", NULL, "Internal Mic"},
-+	/* Headset Mic: Headset Mic with bias */
-+	{"MIC1RP", NULL, "Headset Mic"},
-+};
-+
-+static const struct snd_soc_dapm_route byt_aic3100_ssp2_aif_map[] = {
-+	{"ssp2 Tx", NULL, "codec_out0"},
-+	{"ssp2 Tx", NULL, "codec_out1"},
-+	{"codec_in0", NULL, "ssp2 Rx"},
-+	{"codec_in1", NULL, "ssp2 Rx"},
-+
-+	{"Playback", NULL, "ssp2 Tx"},
-+	{"ssp2 Rx", NULL, "Capture"},
-+};
-+
-+static const struct snd_soc_dapm_route byt_aic3100_ssp0_aif_map[] = {
-+	{"ssp0 Tx", NULL, "modem_out"},
-+	{"modem_in", NULL, "ssp0 Rx"},
-+
-+	{"Playback", NULL, "ssp0 Tx"},
-+	{"ssp0 Rx", NULL, "Capture"},
-+};
-+
-+static const struct snd_kcontrol_new byt_aic3100_controls[] = {
-+	SOC_DAPM_PIN_SWITCH("Headphone"),
-+	SOC_DAPM_PIN_SWITCH("Headset Mic"),
-+	SOC_DAPM_PIN_SWITCH("Internal Mic"),
-+	SOC_DAPM_PIN_SWITCH("Speaker"),
-+};
-+
-+static int byt_aic3100_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;
-+
-+	if (byt_aic3100_quirk & BYT_AIC3100_MCLK_25MHZ) {
-+		ret = snd_soc_dai_set_sysclk(codec_dai, AIC31XX_PLL_CLKIN_MCLK,
-+					25000000,
-+					SND_SOC_CLOCK_IN);
-+	} else {
-+		ret = snd_soc_dai_set_sysclk(codec_dai, AIC31XX_PLL_CLKIN_MCLK,
-+					19200000,
-+					SND_SOC_CLOCK_IN);
-+	}
-+
-+	if (ret < 0) {
-+		dev_err(rtd->dev, "can't set codec clock %d\n", ret);
-+		return ret;
-+	}
-+
-+	if (byt_aic3100_quirk & BYT_AIC3100_MCLK_25MHZ) {
-+		ret = snd_soc_dai_set_pll(codec_dai, 0, AIC31XX_PLL_CLKIN_MCLK,
-+					250000000, params_rate(params));
-+	} else {
-+		ret = snd_soc_dai_set_pll(codec_dai, 0, AIC31XX_PLL_CLKIN_MCLK,
-+					19200000, params_rate(params));
-+
-+	}
-+
-+	if (ret < 0) {
-+		dev_err(rtd->dev, "can't set codec pll: %d\n", ret);
-+		return ret;
-+	}
-+
-+	return 0;
-+}
-+
-+/* uncomment when we have an actual quirk
-+static int byt_aic3100_quirk_cb(const struct dmi_system_id *id)
-+{
-+	byt_aic3100_quirk = (unsigned long)id->driver_data;
-+	return 1;
-+}
-+*/
-+
-+static const struct dmi_system_id byt_aic3100_quirk_table[] = {
-+	{}
-+};
-+
-+static int byt_aic3100_init(struct snd_soc_pcm_runtime *runtime)
-+{
-+	int ret;
-+	struct snd_soc_card *card = runtime->card;
-+	const struct snd_soc_dapm_route *custom_map;
-+	struct byt_aic3100_private *priv = snd_soc_card_get_drvdata(card);
-+	int num_routes;
-+
-+	card->dapm.idle_bias_off = true;
-+
-+	ret = snd_soc_add_card_controls(card, byt_aic3100_controls,
-+					ARRAY_SIZE(byt_aic3100_controls));
-+	if (ret) {
-+		dev_err(card->dev, "unable to add card controls\n");
-+		return ret;
-+	}
-+
-+	switch (BYT_AIC3100_MAP(byt_aic3100_quirk)) {
-+	case BYT_AIC3100_IN1_MAP:
-+	default:
-+		custom_map = byt_aic3100_intmic_in1_map;
-+		num_routes = ARRAY_SIZE(byt_aic3100_intmic_in1_map);
-+	}
-+
-+	ret = snd_soc_dapm_add_routes(&card->dapm, custom_map, num_routes);
-+	if (ret)
-+		return ret;
-+
-+	if (byt_aic3100_quirk & BYT_AIC3100_SSP2_AIF) {
-+		ret = snd_soc_dapm_add_routes(&card->dapm,
-+					byt_aic3100_ssp2_aif_map,
-+					ARRAY_SIZE(byt_aic3100_ssp2_aif_map));
-+	} else {
-+		ret = snd_soc_dapm_add_routes(&card->dapm,
-+					byt_aic3100_ssp0_aif_map,
-+					ARRAY_SIZE(byt_aic3100_ssp0_aif_map));
-+	}
-+	if (ret)
-+		return ret;
-+
-+	snd_soc_dapm_ignore_suspend(&card->dapm, "Headphone");
-+	snd_soc_dapm_ignore_suspend(&card->dapm, "Speaker");
-+
-+	if (priv->mclk) {
-+		/*
-+		 * The firmware might enable the clock at
-+		 * boot (this information may or may not
-+		 * be reflected in the enable clock register).
-+		 * To change the rate we must disable the clock
-+		 * first to cover these cases. Due to common
-+		 * clock framework restrictions that do not allow
-+		 * to disable a clock that has not been enabled,
-+		 * we need to enable the clock first.
-+		 */
-+		ret = clk_prepare_enable(priv->mclk);
-+		if (!ret)
-+			clk_disable_unprepare(priv->mclk);
-+
-+		if (byt_aic3100_quirk & BYT_AIC3100_MCLK_25MHZ)
-+			ret = clk_set_rate(priv->mclk, 25000000);
-+		else
-+			ret = clk_set_rate(priv->mclk, 19200000);
-+
-+		if (ret)
-+			dev_err(card->dev, "unable to set MCLK rate\n");
-+	}
-+
-+	return ret;
-+}
-+
-+static const struct snd_soc_pcm_stream byt_aic3100_dai_params = {
-+	.formats = SNDRV_PCM_FMTBIT_S24_LE,
-+	.rate_min = 48000,
-+	.rate_max = 48000,
-+	.channels_min = 2,
-+	.channels_max = 2,
-+};
-+
-+static int byt_aic3100_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);
-+	int ret;
-+
-+	/* The DSP will covert the FE rate to 48k, stereo */
-+	rate->min = rate->max = 48000;
-+	channels->min = channels->max = 2;
-+
-+	if (!(byt_aic3100_quirk & BYT_AIC3100_SSP2_AIF)) {
-+
-+		/* set SSP0 to 16-bit */
-+		params_set_format(params, SNDRV_PCM_FORMAT_S16_LE);
-+
-+		/*
-+		 * Default mode for SSP configuration is TDM 4 slot,
-+		 * override config with explicit setting to I2S 2ch 16-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_IF   |
-+					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, 16);
-+		if (ret < 0) {
-+			dev_err(rtd->dev,
-+				"can't set I2S config, err %d\n", ret);
-+			return ret;
-+		}
-+
-+	} else {
-+
-+		/* 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_IF   |
-+					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;
-+		}
-+	}
-+	return 0;
-+}
-+
-+static int byt_aic3100_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_aic3100_aif1_ops = {
-+	.startup = byt_aic3100_aif1_startup,
-+};
-+
-+static struct snd_soc_ops byt_aic3100_be_ssp2_ops = {
-+	.hw_params = byt_aic3100_aif1_hw_params,
-+};
-+
-+static struct snd_soc_dai_link byt_aic3100_dais[] = {
-+	[MERR_DPCM_AUDIO] = {
-+		.name = "Baytrail Audio Port",
-+		.stream_name = "Baytrail Audio",
-+		.cpu_dai_name = "media-cpu-dai",
-+		.codec_dai_name = "snd-soc-dummy-dai",
-+		.codec_name = "snd-soc-dummy",
-+		.platform_name = "sst-mfld-platform",
-+		.ignore_suspend = 1,
-+		.dynamic = 1,
-+		.dpcm_playback = 1,
-+		.dpcm_capture = 1,
-+		.ops = &byt_aic3100_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",
-+		.ignore_suspend = 1,
-+		.nonatomic = true,
-+		.dynamic = 1,
-+		.dpcm_playback = 1,
-+		.ops = &byt_aic3100_aif1_ops,
-+	},
-+	[MERR_DPCM_COMPR] = {
-+		.name = "Baytrail Compressed Port",
-+		.stream_name = "Baytrail 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 ends */
-+	{
-+		.name = "SSP2-Codec",
-+		.id = 1,
-+		.cpu_dai_name = "ssp2-port", /* overwritten for ssp0 routing */
-+		.platform_name = "sst-mfld-platform",
-+		.no_pcm = 1,
-+		.codec_dai_name = "tlv320aic31xx-hifi",
-+		.codec_name = "i2c-10TI3100:00", /* overwritten with HID */
-+		.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
-+						| SND_SOC_DAIFMT_CBS_CFS,
-+		.be_hw_params_fixup = byt_aic3100_codec_fixup,
-+		.ignore_suspend = 1,
-+		.dpcm_playback = 1,
-+		.dpcm_capture = 1,
-+		.init = byt_aic3100_init,
-+		.ops = &byt_aic3100_be_ssp2_ops,
-+	},
-+};
-+
-+/* SoC card */
-+static struct snd_soc_card byt_aic3100_card = {
-+	.name = "bytcr-aic3100",
-+	.owner = THIS_MODULE,
-+	.dai_link = byt_aic3100_dais,
-+	.num_links = ARRAY_SIZE(byt_aic3100_dais),
-+	.dapm_widgets = byt_aic3100_widgets,
-+	.num_dapm_widgets = ARRAY_SIZE(byt_aic3100_widgets),
-+	.dapm_routes = byt_aic3100_audio_map,
-+	.num_dapm_routes = ARRAY_SIZE(byt_aic3100_audio_map),
-+	.fully_routed = true,
-+};
-+
-+static char byt_aic3100_codec_name[16];/* i2c-<HID>:00 with HID being 8 chars */
-+static char byt_aic3100_cpu_dai_name[10]; /*  = "ssp[0|2]-port" */
-+
-+static bool is_valleyview(void)
-+{
-+	static const struct x86_cpu_id cpu_ids[] = {
-+		{ X86_VENDOR_INTEL, 6, 55 }, /* Valleyview, Bay Trail */
-+		{}
-+	};
-+
-+	if (!x86_match_cpu(cpu_ids))
-+		return false;
-+	return true;
-+}
-+
-+
-+static int snd_byt_aic3100_mc_probe(struct platform_device *pdev)
-+{
-+	int ret_val = 0;
-+	struct sst_acpi_mach *mach;
-+	const char *i2c_name = NULL;
-+	int i;
-+	int dai_index;
-+	struct byt_aic3100_private *priv;
-+	bool is_bytcr = false;
-+
-+	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_ATOMIC);
-+	if (!priv)
-+		return -ENOMEM;
-+
-+	/* register the soc card */
-+	byt_aic3100_card.dev = &pdev->dev;
-+	mach = byt_aic3100_card.dev->platform_data;
-+	snd_soc_card_set_drvdata(&byt_aic3100_card, priv);
-+
-+	/* fix index of codec dai */
-+	dai_index = MERR_DPCM_COMPR + 1;
-+	for (i = 0; i < ARRAY_SIZE(byt_aic3100_dais); i++) {
-+		if (!strcmp(byt_aic3100_dais[i].codec_name,
-+				"i2c-10TI3100:00")) {
-+			dai_index = i;
-+			break;
-+		}
-+	}
-+
-+	/* fixup codec name based on HID */
-+	i2c_name = sst_acpi_find_name_from_hid(mach->id);
-+	if (i2c_name != NULL) {
-+		snprintf(byt_aic3100_codec_name, sizeof(byt_aic3100_codec_name),
-+			"%s%s", "i2c-", i2c_name);
-+
-+		byt_aic3100_dais[dai_index].codec_name = byt_aic3100_codec_name;
-+	}
-+
-+	/*
-+	 * swap SSP0 if bytcr is detected
-+	 * (will be overridden if DMI quirk is detected)
-+	 */
-+	if (is_valleyview()) {
-+		struct sst_platform_info *p_info = mach->pdata;
-+		const struct sst_res_info *res_info = p_info->res_info;
-+
-+		if (res_info->acpi_ipc_irq_index == 0) {
-+			is_bytcr = true;
-+			byt_aic3100_quirk &= ~BYT_AIC3100_SSP2_AIF;
-+		}
-+	}
-+
-+	/* check quirks before creating card */
-+	dmi_check_system(byt_aic3100_quirk_table);
-+	log_quirks(&pdev->dev);
-+
-+	if (!(byt_aic3100_quirk & BYT_AIC3100_SSP2_AIF))  {
-+
-+		/* fixup cpu dai name name */
-+		snprintf(byt_aic3100_cpu_dai_name,
-+			sizeof(byt_aic3100_cpu_dai_name),
-+			"%s", "ssp0-port");
-+
-+		byt_aic3100_dais[dai_index].cpu_dai_name =
-+			byt_aic3100_cpu_dai_name;
-+	}
-+
-+	if (is_valleyview()) {
-+		priv->mclk = devm_clk_get(&pdev->dev, "pmc_plt_clk_3");
-+		if (IS_ERR(priv->mclk)) {
-+			dev_err(&pdev->dev,
-+				"Failed to get MCLK from pmc_plt_clk_3: %ld\n",
-+				PTR_ERR(priv->mclk));
-+
-+			/*
-+			 * Audio output only works with MCLK enabled
-+			 */
-+			return PTR_ERR(priv->mclk);
-+		}
-+	}
-+
-+	ret_val = devm_snd_soc_register_card(&pdev->dev, &byt_aic3100_card);
-+
-+	if (ret_val) {
-+		dev_err(&pdev->dev, "devm_snd_soc_register_card failed %d\n",
-+			ret_val);
-+		return ret_val;
-+	}
-+	platform_set_drvdata(pdev, &byt_aic3100_card);
-+	return ret_val;
-+}
-+
-+static struct platform_driver snd_byt_aic3100_mc_driver = {
-+	.driver = {
-+		.name = "bytcr_aic3100",
-+		.pm = &snd_soc_pm_ops,
-+	},
-+	.probe = snd_byt_aic3100_mc_probe,
-+};
-+
-+module_platform_driver(snd_byt_aic3100_mc_driver);
-+
-+MODULE_DESCRIPTION("ASoC Intel(R) Baytrail CR Machine driver");
-+MODULE_AUTHOR("Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>");
-+MODULE_LICENSE("GPL v2");
-+MODULE_ALIAS("platform:bytcr_aic3100");
-diff --git a/sound/soc/intel/boards/bytcr_rt5640.c b/sound/soc/intel/boards/bytcr_rt5640.c
-index bff77a1f27fc..c2ecbdc28459 100644
---- a/sound/soc/intel/boards/bytcr_rt5640.c
-+++ b/sound/soc/intel/boards/bytcr_rt5640.c
-@@ -389,6 +389,16 @@ static const struct dmi_system_id byt_rt5640_quirk_table[] = {
- 						 BYT_RT5640_SSP0_AIF1),
- 
- 	},
-+	{
-+		.callback = byt_rt5640_quirk_cb,
-+		.matches = {
-+			DMI_MATCH(DMI_SYS_VENDOR, "Insyde"),
-+		},
-+		.driver_data = (unsigned long *)(BYT_RT5640_IN3_MAP |
-+						 BYT_RT5640_MCLK_EN |
-+						 BYT_RT5640_SSP0_AIF1),
-+
-+	},
- 	{}
- };
- 
-@@ -689,6 +699,10 @@ static bool is_valleyview(void)
- 	return true;
- }
- 
-+struct acpi_chan_package {   /* ACPICA seems to require 64 bit integers */
-+	u64 aif_value;       /* 1: AIF1, 2: AIF2 */
-+	u64 mclock_value;    /* usually 25MHz (0x17d7940), ignored */
-+};
- 
- static int snd_byt_rt5640_mc_probe(struct platform_device *pdev)
- {
-@@ -698,6 +712,7 @@ static int snd_byt_rt5640_mc_probe(struct platform_device *pdev)
- 	int i;
- 	int dai_index;
- 	struct byt_rt5640_private *priv;
-+	bool is_bytcr = false;
- 
- 	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_ATOMIC);
- 	if (!priv)
-@@ -734,8 +749,52 @@ static int snd_byt_rt5640_mc_probe(struct platform_device *pdev)
- 		struct sst_platform_info *p_info = mach->pdata;
- 		const struct sst_res_info *res_info = p_info->res_info;
- 
--		/* TODO: use CHAN package info from BIOS to detect AIF1/AIF2 */
--		if (res_info->acpi_ipc_irq_index == 0) {
-+		if (res_info->acpi_ipc_irq_index == 0)
-+			is_bytcr = true;
-+	}
-+
-+	if (is_bytcr) {
-+		/*
-+		 * Baytrail CR platforms may have CHAN package in BIOS, try
-+		 * to find relevant routing quirk based as done on Windows
-+		 * platforms. We have to read the information directly from the
-+		 * BIOS, at this stage the card is not created and the links
-+		 * with the codec driver/pdata are non-existent
-+		 */
-+
-+		struct acpi_chan_package chan_package;
-+
-+		/* format specified: 2 64-bit integers */
-+		struct acpi_buffer format = {sizeof("NN"), "NN"};
-+		struct acpi_buffer state = {0, NULL};
-+		struct sst_acpi_package_context pkg_ctx;
-+		bool pkg_found = false;
-+
-+		state.length = sizeof(chan_package);
-+		state.pointer = &chan_package;
-+
-+		pkg_ctx.name = "CHAN";
-+		pkg_ctx.length = 2;
-+		pkg_ctx.format = &format;
-+		pkg_ctx.state = &state;
-+		pkg_ctx.data_valid = false;
-+
-+		pkg_found = sst_acpi_find_package_from_hid(mach->id, &pkg_ctx);
-+		if (pkg_found) {
-+			if (chan_package.aif_value == 1) {
-+				dev_info(&pdev->dev, "BIOS Routing: AIF1 connected\n");
-+				byt_rt5640_quirk |= BYT_RT5640_SSP0_AIF1;
-+			} else  if (chan_package.aif_value == 2) {
-+				dev_info(&pdev->dev, "BIOS Routing: AIF2 connected\n");
-+				byt_rt5640_quirk |= BYT_RT5640_SSP0_AIF2;
-+			} else {
-+				dev_info(&pdev->dev, "BIOS Routing isn't valid, ignored\n");
-+				pkg_found = false;
-+			}
-+		}
-+
-+		if (!pkg_found) {
-+			/* no BIOS indications, assume SSP0-AIF2 connection */
- 			byt_rt5640_quirk |= BYT_RT5640_SSP0_AIF2;
- 		}
- 	}
-@@ -774,7 +833,21 @@ static int snd_byt_rt5640_mc_probe(struct platform_device *pdev)
- 			dev_err(&pdev->dev,
- 				"Failed to get MCLK from pmc_plt_clk_3: %ld\n",
- 				PTR_ERR(priv->mclk));
--			return PTR_ERR(priv->mclk);
-+
-+			if (is_bytcr) {
-+				/*
-+				 * Audio output on Baytrail CR only works
-+				 * with MCLK enabled
-+				 */
-+				return PTR_ERR(priv->mclk);
-+			} else {
-+				/*
-+				 * Audio output can work with bitclock only
-+				 * on Baytrail, with a limited audio quality
-+				 * degradation
-+				 */
-+				byt_rt5640_quirk &= ~BYT_RT5640_MCLK_EN;
-+			}
- 		}
- 	}
- 
-diff --git a/sound/soc/intel/boards/bytcr_rt5651.c b/sound/soc/intel/boards/bytcr_rt5651.c
-index 35f591eab3c9..1c672768fc35 100644
---- a/sound/soc/intel/boards/bytcr_rt5651.c
-+++ b/sound/soc/intel/boards/bytcr_rt5651.c
-@@ -24,21 +24,134 @@
- #include <linux/device.h>
- #include <linux/dmi.h>
- #include <linux/slab.h>
-+#include <asm/cpu_device_id.h>
-+#include <asm/platform_sst_audio.h>
-+#include <linux/clk.h>
- #include <sound/pcm.h>
- #include <sound/pcm_params.h>
- #include <sound/soc.h>
- #include <sound/jack.h>
- #include "../../codecs/rt5651.h"
- #include "../atom/sst-atom-controls.h"
-+#include "../common/sst-acpi.h"
-+
-+enum {
-+	BYT_RT5651_DMIC1_MAP,
-+	BYT_RT5651_DMIC2_MAP,
-+	BYT_RT5651_IN1_MAP,
-+};
-+
-+#define BYT_RT5651_MAP(quirk)	((quirk) & 0xff)
-+#define BYT_RT5651_DMIC_EN	BIT(16)
-+#define BYT_RT5651_MCLK_EN	BIT(17)
-+#define BYT_RT5651_MCLK_25MHZ	BIT(18)
-+
-+struct byt_rt5651_private {
-+	struct clk *mclk;
-+};
-+
-+static unsigned long byt_rt5651_quirk = BYT_RT5651_DMIC1_MAP |
-+					BYT_RT5651_DMIC_EN |
-+	                                BYT_RT5651_MCLK_EN;
-+
-+static void log_quirks(struct device *dev)
-+{
-+	if (BYT_RT5651_MAP(byt_rt5651_quirk) == BYT_RT5651_DMIC1_MAP)
-+		dev_info(dev, "quirk DMIC1_MAP enabled");
-+	if (BYT_RT5651_MAP(byt_rt5651_quirk) == BYT_RT5651_DMIC2_MAP)
-+		dev_info(dev, "quirk DMIC2_MAP enabled");
-+	if (BYT_RT5651_MAP(byt_rt5651_quirk) == BYT_RT5651_IN1_MAP)
-+		dev_info(dev, "quirk IN1_MAP enabled");
-+	if (byt_rt5651_quirk & BYT_RT5651_DMIC_EN)
-+		dev_info(dev, "quirk DMIC enabled");
-+	if (byt_rt5651_quirk & BYT_RT5651_MCLK_EN)
-+		dev_info(dev, "quirk MCLK_EN enabled");
-+	if (byt_rt5651_quirk & BYT_RT5651_MCLK_25MHZ)
-+		dev_info(dev, "quirk MCLK_25MHZ enabled");
-+}
-+
-+#define BYT_CODEC_DAI1	"rt5651-aif1"
-+
-+static inline struct snd_soc_dai *byt_get_codec_dai(struct snd_soc_card *card)
-+{
-+	struct snd_soc_pcm_runtime *rtd;
-+
-+	list_for_each_entry(rtd, &card->rtd_list, list) {
-+		if (!strncmp(rtd->codec_dai->name, BYT_CODEC_DAI1,
-+			     strlen(BYT_CODEC_DAI1)))
-+			return rtd->codec_dai;
-+	}
-+	return NULL;
-+}
-+
-+static int platform_clock_control(struct snd_soc_dapm_widget *w,
-+				  struct snd_kcontrol *k, int  event)
-+{
-+	struct snd_soc_dapm_context *dapm = w->dapm;
-+	struct snd_soc_card *card = dapm->card;
-+	struct snd_soc_dai *codec_dai;
-+	struct byt_rt5651_private *priv = snd_soc_card_get_drvdata(card);
-+	int ret;
-+
-+	codec_dai = byt_get_codec_dai(card);
-+	if (!codec_dai) {
-+		dev_err(card->dev,
-+			"Codec dai not found; Unable to set platform clock\n");
-+		return -EIO;
-+	}
-+
-+	if (SND_SOC_DAPM_EVENT_ON(event)) {
-+		if ((byt_rt5651_quirk & BYT_RT5651_MCLK_EN) && priv->mclk) {
-+			ret = clk_prepare_enable(priv->mclk);
-+			if (ret < 0) {
-+				dev_err(card->dev,
-+					"could not configure MCLK state");
-+				return ret;
-+			}
-+		}
-+		ret = snd_soc_dai_set_sysclk(codec_dai, RT5651_SCLK_S_PLL1,
-+					     48000 * 512,
-+					     SND_SOC_CLOCK_IN);
-+	} else {
-+		/*
-+		 * Set codec clock source to internal clock before
-+		 * turning off the platform clock. Codec needs clock
-+		 * for Jack detection and button press
-+		 */
-+		ret = snd_soc_dai_set_sysclk(codec_dai, RT5651_SCLK_S_RCCLK,
-+					     0,
-+					     SND_SOC_CLOCK_IN);
-+		if (!ret) {
-+			if ((byt_rt5651_quirk & BYT_RT5651_MCLK_EN) && priv->mclk)
-+				clk_disable_unprepare(priv->mclk);
-+		}
-+	}
-+
-+	if (ret < 0) {
-+		dev_err(card->dev, "can't set codec sysclk: %d\n", ret);
-+		return ret;
-+	}
-+
-+	return 0;
-+}
- 
- static const struct snd_soc_dapm_widget byt_rt5651_widgets[] = {
- 	SND_SOC_DAPM_HP("Headphone", NULL),
- 	SND_SOC_DAPM_MIC("Headset Mic", NULL),
- 	SND_SOC_DAPM_MIC("Internal Mic", NULL),
- 	SND_SOC_DAPM_SPK("Speaker", NULL),
-+	SND_SOC_DAPM_SUPPLY("Platform Clock", SND_SOC_NOPM, 0, 0,
-+			    platform_clock_control, SND_SOC_DAPM_PRE_PMU |
-+			    SND_SOC_DAPM_POST_PMD),
-+
- };
- 
- static const struct snd_soc_dapm_route byt_rt5651_audio_map[] = {
-+	{"Headphone", NULL, "Platform Clock"},
-+	{"Headset Mic", NULL, "Platform Clock"},
-+	{"Internal Mic", NULL, "Platform Clock"},
-+	{"Speaker", NULL, "Platform Clock"},
-+
- 	{"AIF1 Playback", NULL, "ssp2 Tx"},
- 	{"ssp2 Tx", NULL, "codec_out0"},
- 	{"ssp2 Tx", NULL, "codec_out1"},
-@@ -67,18 +180,6 @@ static const struct snd_soc_dapm_route byt_rt5651_intmic_in1_map[] = {
- 	{"IN1P", NULL, "Internal Mic"},
- };
- 
--enum {
--	BYT_RT5651_DMIC1_MAP,
--	BYT_RT5651_DMIC2_MAP,
--	BYT_RT5651_IN1_MAP,
--};
--
--#define BYT_RT5651_MAP(quirk)	((quirk) & 0xff)
--#define BYT_RT5651_DMIC_EN	BIT(16)
--
--static unsigned long byt_rt5651_quirk = BYT_RT5651_DMIC1_MAP |
--					BYT_RT5651_DMIC_EN;
--
- static const struct snd_kcontrol_new byt_rt5651_controls[] = {
- 	SOC_DAPM_PIN_SWITCH("Headphone"),
- 	SOC_DAPM_PIN_SWITCH("Headset Mic"),
-@@ -103,9 +204,27 @@ static int byt_rt5651_aif1_hw_params(struct snd_pcm_substream *substream,
- 		return ret;
- 	}
- 
--	ret = snd_soc_dai_set_pll(codec_dai, 0, RT5651_PLL1_S_BCLK1,
--				  params_rate(params) * 50,
--				  params_rate(params) * 512);
-+	if (!(byt_rt5651_quirk & BYT_RT5651_MCLK_EN)) {
-+		/* 2x25 bit slots on SSP2 */
-+		ret = snd_soc_dai_set_pll(codec_dai, 0,
-+					RT5651_PLL1_S_BCLK1,
-+					params_rate(params) * 50,
-+					params_rate(params) * 512);
-+	}
-+	else {
-+		if (byt_rt5651_quirk & BYT_RT5651_MCLK_25MHZ) {
-+			ret = snd_soc_dai_set_pll(codec_dai, 0,
-+						RT5651_PLL1_S_MCLK,
-+						25000000,
-+						params_rate(params) * 512);
-+		} else {
-+			ret = snd_soc_dai_set_pll(codec_dai, 0,
-+						RT5651_PLL1_S_MCLK,
-+						19200000,
-+						params_rate(params) * 512);
-+		}
-+	}
-+
- 	if (ret < 0) {
- 		dev_err(rtd->dev, "can't set codec pll: %d\n", ret);
- 		return ret;
-@@ -114,8 +233,22 @@ static int byt_rt5651_aif1_hw_params(struct snd_pcm_substream *substream,
- 	return 0;
- }
- 
-+static int byt_rt5651_quirk_cb(const struct dmi_system_id *id)
-+{
-+	byt_rt5651_quirk = (unsigned long)id->driver_data;
-+	return 1;
-+}
-+
- static const struct dmi_system_id byt_rt5651_quirk_table[] = {
--	{}
-+	{
-+		.callback = byt_rt5651_quirk_cb,
-+		.matches = {
-+			DMI_MATCH(DMI_SYS_VENDOR, "Circuitco"),
-+			DMI_MATCH(DMI_PRODUCT_NAME, "Minnowboard Max B3 PLATFORM"),
-+		},
-+		.driver_data = (unsigned long *)(BYT_RT5651_DMIC1_MAP |
-+						 BYT_RT5651_DMIC_EN),
-+	},
- };
- 
- static int byt_rt5651_init(struct snd_soc_pcm_runtime *runtime)
-@@ -123,6 +256,7 @@ static int byt_rt5651_init(struct snd_soc_pcm_runtime *runtime)
- 	int ret;
- 	struct snd_soc_card *card = runtime->card;
- 	const struct snd_soc_dapm_route *custom_map;
-+	struct byt_rt5651_private *priv = snd_soc_card_get_drvdata(card);
- 	int num_routes;
- 
- 	card->dapm.idle_bias_off = true;
-@@ -141,6 +275,9 @@ static int byt_rt5651_init(struct snd_soc_pcm_runtime *runtime)
- 		custom_map = byt_rt5651_intmic_dmic1_map;
- 		num_routes = ARRAY_SIZE(byt_rt5651_intmic_dmic1_map);
- 	}
-+	ret = snd_soc_dapm_add_routes(&card->dapm, custom_map, num_routes);
-+	if (ret)
-+		return ret;
- 
- 	ret = snd_soc_add_card_controls(card, byt_rt5651_controls,
- 					ARRAY_SIZE(byt_rt5651_controls));
-@@ -151,6 +288,30 @@ static int byt_rt5651_init(struct snd_soc_pcm_runtime *runtime)
- 	snd_soc_dapm_ignore_suspend(&card->dapm, "Headphone");
- 	snd_soc_dapm_ignore_suspend(&card->dapm, "Speaker");
- 
-+	if ((byt_rt5651_quirk & BYT_RT5651_MCLK_EN) && priv->mclk) {
-+		/*
-+		 * The firmware might enable the clock at
-+		 * boot (this information may or may not
-+		 * be reflected in the enable clock register).
-+		 * To change the rate we must disable the clock
-+		 * first to cover these cases. Due to common
-+		 * clock framework restrictions that do not allow
-+		 * to disable a clock that has not been enabled,
-+		 * we need to enable the clock first.
-+		 */
-+		ret = clk_prepare_enable(priv->mclk);
-+		if (!ret)
-+			clk_disable_unprepare(priv->mclk);
-+
-+		if (byt_rt5651_quirk & BYT_RT5651_MCLK_25MHZ)
-+			ret = clk_set_rate(priv->mclk, 25000000);
-+		else
-+			ret = clk_set_rate(priv->mclk, 19200000);
-+
-+		if (ret)
-+			dev_err(card->dev, "unable to set MCLK rate\n");
-+	}
-+
- 	return ret;
- }
- 
-@@ -298,12 +459,73 @@ static struct snd_soc_card byt_rt5651_card = {
- 	.fully_routed = true,
- };
- 
-+static char byt_rt5651_codec_name[16]; /* i2c-<HID>:00 with HID being 8 chars */
-+
-+static bool is_valleyview(void)
-+{
-+	static const struct x86_cpu_id cpu_ids[] = {
-+		{ X86_VENDOR_INTEL, 6, 55 }, /* Valleyview, Bay Trail */
-+		{}
-+	};
-+
-+	if (!x86_match_cpu(cpu_ids))
-+		return false;
-+	return true;
-+}
-+
- static int snd_byt_rt5651_mc_probe(struct platform_device *pdev)
- {
- 	int ret_val = 0;
-+	struct sst_acpi_mach *mach;
-+	const char *i2c_name = NULL;
-+	int i;
-+	int dai_index;
-+	struct byt_rt5651_private *priv;
-+
-+	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_ATOMIC);
-+	if (!priv)
-+		return -ENOMEM;
- 
- 	/* register the soc card */
- 	byt_rt5651_card.dev = &pdev->dev;
-+	mach = byt_rt5651_card.dev->platform_data;
-+
-+	/* fix index of codec dai */
-+	dai_index = MERR_DPCM_COMPR + 1;
-+	for (i = 0; i < ARRAY_SIZE(byt_rt5651_dais); i++) {
-+		if (!strcmp(byt_rt5651_dais[i].codec_name, "i2c-10EC5651:00")) {
-+			dai_index = i;
-+			break;
-+		}
-+	}
-+
-+	/* fixup codec name based on HID */
-+	i2c_name = sst_acpi_find_name_from_hid(mach->id);
-+	if (i2c_name != NULL) {
-+		snprintf(byt_rt5651_codec_name, sizeof(byt_rt5651_codec_name),
-+			"%s%s", "i2c-", i2c_name);
-+
-+		byt_rt5651_dais[dai_index].codec_name = byt_rt5651_codec_name;
-+	}
-+
-+	/* check quirks before creating card */
-+	dmi_check_system(byt_rt5651_quirk_table);
-+	log_quirks(&pdev->dev);
-+
-+	if ((byt_rt5651_quirk & BYT_RT5651_MCLK_EN) && (is_valleyview())) {
-+		priv->mclk = devm_clk_get(&pdev->dev, "pmc_plt_clk_3");
-+		if (IS_ERR(priv->mclk)) {
-+			dev_err(&pdev->dev,
-+				"Failed to get MCLK from pmc_plt_clk_3: %ld\n",
-+				PTR_ERR(priv->mclk));
-+			/*
-+			 * Audio output can work with bitclock only
-+			 * on Baytrail, with a limited audio quality
-+			 * degradation
-+			 */
-+			byt_rt5651_quirk &= ~BYT_RT5651_MCLK_EN;
-+		}
-+	}
- 
- 	ret_val = devm_snd_soc_register_card(&pdev->dev, &byt_rt5651_card);
- 
-diff --git a/sound/soc/intel/boards/cht_bsw_max98090_ti.c b/sound/soc/intel/boards/cht_bsw_max98090_ti.c
-index cdcced9f32b6..a95ae141e3a6 100644
---- a/sound/soc/intel/boards/cht_bsw_max98090_ti.c
-+++ b/sound/soc/intel/boards/cht_bsw_max98090_ti.c
-@@ -23,6 +23,9 @@
- #include <linux/platform_device.h>
- #include <linux/slab.h>
- #include <linux/acpi.h>
-+#include <asm/cpu_device_id.h>
-+#include <asm/platform_sst_audio.h>
-+#include <linux/clk.h>
- #include <sound/pcm.h>
- #include <sound/pcm_params.h>
- #include <sound/soc.h>
-@@ -37,6 +40,7 @@
- struct cht_mc_private {
- 	struct snd_soc_jack jack;
- 	bool ts3a227e_present;
-+	struct clk *mclk;
- };
- 
- static inline struct snd_soc_dai *cht_get_codec_dai(struct snd_soc_card *card)
-@@ -51,11 +55,51 @@ static inline struct snd_soc_dai *cht_get_codec_dai(struct snd_soc_card *card)
- 	return NULL;
- }
- 
-+static int platform_clock_control(struct snd_soc_dapm_widget *w,
-+					  struct snd_kcontrol *k, int  event)
-+{
-+	struct snd_soc_dapm_context *dapm = w->dapm;
-+	struct snd_soc_card *card = dapm->card;
-+	struct snd_soc_dai *codec_dai;
-+	struct cht_mc_private *ctx = snd_soc_card_get_drvdata(card);
-+	int ret;
-+
-+	codec_dai = cht_get_codec_dai(card);
-+	if (!codec_dai) {
-+		dev_err(card->dev, "Codec dai not found; Unable to set platform clock\n");
-+		return -EIO;
-+	}
-+
-+	if (SND_SOC_DAPM_EVENT_ON(event)) {
-+		if (ctx->mclk) {
-+			ret = clk_prepare_enable(ctx->mclk);
-+			if (ret < 0) {
-+				dev_err(card->dev,
-+					"could not configure MCLK state");
-+				return ret;
-+			}
-+		}
-+	} else {
-+
-+		/* FIXME: if there is no clock can jack detection work ? */
-+
-+		if (ctx->mclk) {
-+			clk_disable_unprepare(ctx->mclk);
-+		}
-+	}
-+
-+	return 0;
-+}
-+
-+
- 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),
-+	SND_SOC_DAPM_SUPPLY("Platform Clock", SND_SOC_NOPM, 0, 0,
-+			    platform_clock_control, SND_SOC_DAPM_PRE_PMU |
-+			    SND_SOC_DAPM_POST_PMD),
- };
- 
- static const struct snd_soc_dapm_route cht_audio_map[] = {
-@@ -72,6 +116,10 @@ static const struct snd_soc_dapm_route cht_audio_map[] = {
- 	{"codec_in0", NULL, "ssp2 Rx" },
- 	{"codec_in1", NULL, "ssp2 Rx" },
- 	{"ssp2 Rx", NULL, "HiFi Capture"},
-+	{"Headphone", NULL, "Platform Clock"},
-+	{"Headset Mic", NULL, "Platform Clock"},
-+	{"Int Mic", NULL, "Platform Clock"},
-+	{"Ext Spk", NULL, "Platform Clock"},
- };
- 
- static const struct snd_kcontrol_new cht_mc_controls[] = {
-@@ -153,6 +201,26 @@ static int cht_codec_init(struct snd_soc_pcm_runtime *runtime)
- 	if (ctx->ts3a227e_present)
- 		snd_soc_jack_notifier_register(jack, &cht_jack_nb);
- 
-+	if (ctx->mclk) {
-+		/*
-+		 * The firmware might enable the clock at
-+		 * boot (this information may or may not
-+		 * be reflected in the enable clock register).
-+		 * To change the rate we must disable the clock
-+		 * first to cover these cases. Due to common
-+		 * clock framework restrictions that do not allow
-+		 * to disable a clock that has not been enabled,
-+		 * we need to enable the clock first.
-+		 */
-+		ret = clk_prepare_enable(ctx->mclk);
-+		if (!ret)
-+			clk_disable_unprepare(ctx->mclk);
-+
-+		ret = clk_set_rate(ctx->mclk, CHT_PLAT_CLK_3_HZ);
-+
-+		if (ret)
-+			dev_err(runtime->dev, "unable to set MCLK rate\n");
-+	}
- 	return ret;
- }
- 
-@@ -287,6 +355,18 @@ static struct snd_soc_card snd_soc_card_cht = {
- 	.num_controls = ARRAY_SIZE(cht_mc_controls),
- };
- 
-+static bool is_valleyview(void)
-+{
-+	static const struct x86_cpu_id cpu_ids[] = {
-+		{ X86_VENDOR_INTEL, 6, 55 }, /* Valleyview, Bay Trail */
-+		{}
-+	};
-+
-+	if (!x86_match_cpu(cpu_ids))
-+		return false;
-+	return true;
-+}
-+
- static int snd_cht_mc_probe(struct platform_device *pdev)
- {
- 	int ret_val = 0;
-@@ -306,6 +386,17 @@ static int snd_cht_mc_probe(struct platform_device *pdev)
- 	/* register the soc card */
- 	snd_soc_card_cht.dev = &pdev->dev;
- 	snd_soc_card_set_drvdata(&snd_soc_card_cht, drv);
-+
-+	if (is_valleyview()) {
-+		drv->mclk = devm_clk_get(&pdev->dev, "pmc_plt_clk_3");
-+		if (IS_ERR(drv->mclk)) {
-+			dev_err(&pdev->dev,
-+				"Failed to get MCLK from pmc_plt_clk_3: %ld\n",
-+				PTR_ERR(drv->mclk));
-+			return PTR_ERR(drv->mclk);
-+		}
-+	}
-+
- 	ret_val = devm_snd_soc_register_card(&pdev->dev, &snd_soc_card_cht);
- 	if (ret_val) {
- 		dev_err(&pdev->dev,
-diff --git a/sound/soc/intel/boards/cht_bsw_rt5645.c b/sound/soc/intel/boards/cht_bsw_rt5645.c
-index 16c94c45ce50..e792f9849f98 100644
---- a/sound/soc/intel/boards/cht_bsw_rt5645.c
-+++ b/sound/soc/intel/boards/cht_bsw_rt5645.c
-@@ -23,7 +23,11 @@
- #include <linux/module.h>
- #include <linux/acpi.h>
- #include <linux/platform_device.h>
-+#include <linux/dmi.h>
- #include <linux/slab.h>
-+#include <asm/cpu_device_id.h>
-+#include <asm/platform_sst_audio.h>
-+#include <linux/clk.h>
- #include <sound/pcm.h>
- #include <sound/pcm_params.h>
- #include <sound/soc.h>
-@@ -33,7 +37,8 @@
- #include "../common/sst-acpi.h"
- 
- #define CHT_PLAT_CLK_3_HZ	19200000
--#define CHT_CODEC_DAI	"rt5645-aif1"
-+#define CHT_CODEC_DAI1	"rt5645-aif1"
-+#define CHT_CODEC_DAI2	"rt5645-aif2"
- 
- struct cht_acpi_card {
- 	char *codec_id;
-@@ -45,15 +50,36 @@ struct cht_mc_private {
- 	struct snd_soc_jack jack;
- 	struct cht_acpi_card *acpi_card;
- 	char codec_name[16];
-+	struct clk *mclk;
- };
- 
-+#define CHT_RT5645_MAP(quirk)	((quirk) & 0xff)
-+#define CHT_RT5645_SSP2_AIF2     BIT(16) /* default is using AIF1  */
-+#define CHT_RT5645_SSP0_AIF1     BIT(17)
-+#define CHT_RT5645_SSP0_AIF2     BIT(18)
-+
-+static unsigned long cht_rt5645_quirk = 0;
-+
-+static void log_quirks(struct device *dev)
-+{
-+	if (cht_rt5645_quirk & CHT_RT5645_SSP2_AIF2)
-+		dev_info(dev, "quirk SSP2_AIF2 enabled");
-+	if (cht_rt5645_quirk & CHT_RT5645_SSP0_AIF1)
-+		dev_info(dev, "quirk SSP0_AIF1 enabled");
-+	if (cht_rt5645_quirk & CHT_RT5645_SSP0_AIF2)
-+		dev_info(dev, "quirk SSP0_AIF2 enabled");
-+}
-+
- static inline struct snd_soc_dai *cht_get_codec_dai(struct snd_soc_card *card)
- {
- 	struct snd_soc_pcm_runtime *rtd;
- 
- 	list_for_each_entry(rtd, &card->rtd_list, list) {
--		if (!strncmp(rtd->codec_dai->name, CHT_CODEC_DAI,
--			     strlen(CHT_CODEC_DAI)))
-+		if (!strncmp(rtd->codec_dai->name, CHT_CODEC_DAI1,
-+			     strlen(CHT_CODEC_DAI1)))
-+			return rtd->codec_dai;
-+		if (!strncmp(rtd->codec_dai->name, CHT_CODEC_DAI2,
-+			     strlen(CHT_CODEC_DAI2)))
- 			return rtd->codec_dai;
- 	}
- 	return NULL;
-@@ -65,6 +91,7 @@ static int platform_clock_control(struct snd_soc_dapm_widget *w,
- 	struct snd_soc_dapm_context *dapm = w->dapm;
- 	struct snd_soc_card *card = dapm->card;
- 	struct snd_soc_dai *codec_dai;
-+	struct cht_mc_private *ctx = snd_soc_card_get_drvdata(card);
- 	int ret;
- 
- 	codec_dai = cht_get_codec_dai(card);
-@@ -73,19 +100,30 @@ static int platform_clock_control(struct snd_soc_dapm_widget *w,
- 		return -EIO;
- 	}
- 
--	if (!SND_SOC_DAPM_EVENT_OFF(event))
--		return 0;
-+	if (SND_SOC_DAPM_EVENT_ON(event)) {
-+		if (ctx->mclk) {
-+			ret = clk_prepare_enable(ctx->mclk);
-+			if (ret < 0) {
-+				dev_err(card->dev,
-+					"could not configure MCLK state");
-+				return ret;
-+			}
-+		}
-+	} else {
-+		/* Set codec sysclk source to its internal clock because codec PLL will
-+		 * be off when idle and MCLK will also be off when codec is
-+		 * runtime suspended. Codec needs clock for jack detection and button
-+		 * press. MCLK is turned off with clock framework or ACPI.
-+		 */
-+		ret = snd_soc_dai_set_sysclk(codec_dai, RT5645_SCLK_S_RCCLK,
-+					0, SND_SOC_CLOCK_IN);
-+		if (ret < 0) {
-+			dev_err(card->dev, "can't set codec sysclk: %d\n", ret);
-+			return ret;
-+		}
- 
--	/* Set codec sysclk source to its internal clock because codec PLL will
--	 * be off when idle and MCLK will also be off by ACPI when codec is
--	 * runtime suspended. Codec needs clock for jack detection and button
--	 * press.
--	 */
--	ret = snd_soc_dai_set_sysclk(codec_dai, RT5645_SCLK_S_RCCLK,
--			0, SND_SOC_CLOCK_IN);
--	if (ret < 0) {
--		dev_err(card->dev, "can't set codec sysclk: %d\n", ret);
--		return ret;
-+		if (ctx->mclk)
-+			clk_disable_unprepare(ctx->mclk);
- 	}
- 
- 	return 0;
-@@ -97,7 +135,7 @@ static const struct snd_soc_dapm_widget cht_dapm_widgets[] = {
- 	SND_SOC_DAPM_MIC("Int Mic", NULL),
- 	SND_SOC_DAPM_SPK("Ext Spk", NULL),
- 	SND_SOC_DAPM_SUPPLY("Platform Clock", SND_SOC_NOPM, 0, 0,
--			platform_clock_control, SND_SOC_DAPM_POST_PMD),
-+			platform_clock_control, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
- };
- 
- static const struct snd_soc_dapm_route cht_rt5645_audio_map[] = {
-@@ -109,12 +147,6 @@ static const struct snd_soc_dapm_route cht_rt5645_audio_map[] = {
- 	{"Headphone", NULL, "HPOR"},
- 	{"Ext Spk", NULL, "SPOL"},
- 	{"Ext Spk", NULL, "SPOR"},
--	{"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"},
- 	{"Headphone", NULL, "Platform Clock"},
- 	{"Headset Mic", NULL, "Platform Clock"},
- 	{"Int Mic", NULL, "Platform Clock"},
-@@ -130,16 +162,42 @@ static const struct snd_soc_dapm_route cht_rt5650_audio_map[] = {
- 	{"Headphone", NULL, "HPOR"},
- 	{"Ext Spk", NULL, "SPOL"},
- 	{"Ext Spk", NULL, "SPOR"},
-+	{"Headphone", NULL, "Platform Clock"},
-+	{"Headset Mic", NULL, "Platform Clock"},
-+	{"Int Mic", NULL, "Platform Clock"},
-+	{"Ext Spk", NULL, "Platform Clock"},
-+};
-+
-+static const struct snd_soc_dapm_route cht_rt5645_ssp2_aif1_map[] = {
- 	{"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"},
--	{"Headphone", NULL, "Platform Clock"},
--	{"Headset Mic", NULL, "Platform Clock"},
--	{"Int Mic", NULL, "Platform Clock"},
--	{"Ext Spk", NULL, "Platform Clock"},
-+};
-+
-+static const struct snd_soc_dapm_route cht_rt5645_ssp2_aif2_map[] = {
-+	{"AIF2 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, "AIF2 Capture"},
-+};
-+
-+static const struct snd_soc_dapm_route cht_rt5645_ssp0_aif1_map[] = {
-+	{"AIF1 Playback", NULL, "ssp0 Tx"},
-+	{"ssp0 Tx", NULL, "modem_out"},
-+	{"modem_in", NULL, "ssp0 Rx" },
-+	{"ssp0 Rx", NULL, "AIF1 Capture"},
-+};
-+
-+static const struct snd_soc_dapm_route cht_rt5645_ssp0_aif2_map[] = {
-+	{"AIF2 Playback", NULL, "ssp0 Tx"},
-+	{"ssp0 Tx", NULL, "modem_out"},
-+	{"modem_in", NULL, "ssp0 Rx" },
-+	{"ssp0 Rx", NULL, "AIF2 Capture"},
- };
- 
- static const struct snd_kcontrol_new cht_mc_controls[] = {
-@@ -185,11 +243,25 @@ static int cht_aif1_hw_params(struct snd_pcm_substream *substream,
- 	return 0;
- }
- 
-+/* uncomment when we have a real quirk
-+static int cht_rt5645_quirk_cb(const struct dmi_system_id *id)
-+{
-+	cht_rt5645_quirk = (unsigned long)id->driver_data;
-+	return 1;
-+}
-+*/
-+
-+static const struct dmi_system_id cht_rt5645_quirk_table[] = {
-+	{
-+	},
-+};
-+
- static int cht_codec_init(struct snd_soc_pcm_runtime *runtime)
- {
- 	int ret;
- 	int jack_type;
- 	struct snd_soc_codec *codec = runtime->codec;
-+	struct snd_soc_card *card = runtime->card;
- 	struct snd_soc_dai *codec_dai = runtime->codec_dai;
- 	struct cht_mc_private *ctx = snd_soc_card_get_drvdata(runtime->card);
- 
-@@ -201,6 +273,26 @@ static int cht_codec_init(struct snd_soc_pcm_runtime *runtime)
- 				RT5645_AD_STEREO_FILTER,
- 				RT5645_CLK_SEL_I2S1_ASRC);
- 
-+	if (cht_rt5645_quirk & CHT_RT5645_SSP2_AIF2) {
-+		ret = snd_soc_dapm_add_routes(&card->dapm,
-+					cht_rt5645_ssp2_aif2_map,
-+					ARRAY_SIZE(cht_rt5645_ssp2_aif2_map));
-+	} else if (cht_rt5645_quirk & CHT_RT5645_SSP0_AIF1) {
-+		ret = snd_soc_dapm_add_routes(&card->dapm,
-+					cht_rt5645_ssp0_aif1_map,
-+					ARRAY_SIZE(cht_rt5645_ssp0_aif1_map));
-+	} else if (cht_rt5645_quirk & CHT_RT5645_SSP0_AIF2) {
-+		ret = snd_soc_dapm_add_routes(&card->dapm,
-+					cht_rt5645_ssp0_aif2_map,
-+					ARRAY_SIZE(cht_rt5645_ssp0_aif2_map));
-+	} else {
-+		ret = snd_soc_dapm_add_routes(&card->dapm,
-+					cht_rt5645_ssp2_aif1_map,
-+					ARRAY_SIZE(cht_rt5645_ssp2_aif1_map));
-+	}
-+	if (ret)
-+		return ret;
-+
- 	/* 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, 24);
- 	if (ret < 0) {
-@@ -225,12 +317,33 @@ static int cht_codec_init(struct snd_soc_pcm_runtime *runtime)
- 
- 	rt5645_set_jack_detect(codec, &ctx->jack, &ctx->jack, &ctx->jack);
- 
-+	if (ctx->mclk) {
-+		/*
-+		 * The firmware might enable the clock at
-+		 * boot (this information may or may not
-+		 * be reflected in the enable clock register).
-+		 * To change the rate we must disable the clock
-+		 * first to cover these cases. Due to common
-+		 * clock framework restrictions that do not allow
-+		 * to disable a clock that has not been enabled,
-+		 * we need to enable the clock first.
-+		 */
-+		ret = clk_prepare_enable(ctx->mclk);
-+		if (!ret)
-+			clk_disable_unprepare(ctx->mclk);
-+
-+		ret = clk_set_rate(ctx->mclk, CHT_PLAT_CLK_3_HZ);
-+
-+		if (ret)
-+			dev_err(runtime->dev, "unable to set MCLK rate\n");
-+	}
- 	return ret;
- }
- 
- static int cht_codec_fixup(struct snd_soc_pcm_runtime *rtd,
- 			    struct snd_pcm_hw_params *params)
- {
-+	int ret;
- 	struct snd_interval *rate = hw_param_interval(params,
- 			SNDRV_PCM_HW_PARAM_RATE);
- 	struct snd_interval *channels = hw_param_interval(params,
-@@ -240,8 +353,39 @@ static int cht_codec_fixup(struct snd_soc_pcm_runtime *rtd,
- 	rate->min = rate->max = 48000;
- 	channels->min = channels->max = 2;
- 
--	/* set SSP2 to 24-bit */
--	params_set_format(params, SNDRV_PCM_FORMAT_S24_LE);
-+	if ((cht_rt5645_quirk & CHT_RT5645_SSP0_AIF1) ||
-+		(cht_rt5645_quirk & CHT_RT5645_SSP0_AIF2)) {
-+
-+		/* set SSP0 to 16-bit */
-+		params_set_format(params, SNDRV_PCM_FORMAT_S16_LE);
-+
-+		/*
-+		 * Default mode for SSP configuration is TDM 4 slot, override config
-+		 * with explicit setting to I2S 2ch 16-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_IF   |
-+					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, 16);
-+		if (ret < 0) {
-+			dev_err(rtd->dev, "can't set I2S config, err %d\n", ret);
-+			return ret;
-+		}
-+
-+	} else {
-+
-+		/* set SSP2 to 24-bit */
-+		params_set_format(params, SNDRV_PCM_FORMAT_S24_LE);
-+
-+	}
- 	return 0;
- }
- 
-@@ -344,10 +488,31 @@ static struct snd_soc_card snd_soc_card_chtrt5650 = {
- static struct cht_acpi_card snd_soc_cards[] = {
- 	{"10EC5640", CODEC_TYPE_RT5645, &snd_soc_card_chtrt5645},
- 	{"10EC5645", CODEC_TYPE_RT5645, &snd_soc_card_chtrt5645},
-+	{"10EC5648", CODEC_TYPE_RT5645, &snd_soc_card_chtrt5645},
-+	{"10EC3270", CODEC_TYPE_RT5645, &snd_soc_card_chtrt5645},
- 	{"10EC5650", CODEC_TYPE_RT5650, &snd_soc_card_chtrt5650},
- };
- 
--static char cht_rt5640_codec_name[16]; /* i2c-<HID>:00 with HID being 8 chars */
-+static char cht_rt5645_codec_name[16]; /* i2c-<HID>:00 with HID being 8 chars */
-+static char cht_rt5645_codec_aif_name[12]; /*  = "rt5645-aif[1|2]" */
-+static char cht_rt5645_cpu_dai_name[10]; /*  = "ssp[0|2]-port" */
-+
-+static bool is_valleyview(void)
-+{
-+	static const struct x86_cpu_id cpu_ids[] = {
-+		{ X86_VENDOR_INTEL, 6, 55 }, /* Valleyview, Bay Trail */
-+		{}
-+	};
-+
-+	if (!x86_match_cpu(cpu_ids))
-+		return false;
-+	return true;
-+}
-+
-+struct acpi_chan_package {   /* ACPICA seems to require 64 bit integers */
-+	u64 aif_value;       /* 1: AIF1, 2: AIF2 */
-+	u64 mclock_value;    /* usually 25MHz (0x17d7940), ignored */
-+};
- 
- static int snd_cht_mc_probe(struct platform_device *pdev)
- {
-@@ -358,22 +523,33 @@ static int snd_cht_mc_probe(struct platform_device *pdev)
- 	struct sst_acpi_mach *mach;
- 	const char *i2c_name = NULL;
- 	int dai_index = 0;
-+	bool found = false;
-+	bool is_bytcr = false;
- 
- 	drv = devm_kzalloc(&pdev->dev, sizeof(*drv), GFP_ATOMIC);
- 	if (!drv)
- 		return -ENOMEM;
- 
-+	mach = (&pdev->dev)->platform_data;
-+
- 	for (i = 0; i < ARRAY_SIZE(snd_soc_cards); i++) {
--		if (acpi_dev_found(snd_soc_cards[i].codec_id)) {
-+		if (acpi_dev_found(snd_soc_cards[i].codec_id) &&
-+			(!strncmp(snd_soc_cards[i].codec_id, mach->id, 8))) {
- 			dev_dbg(&pdev->dev,
- 				"found codec %s\n", snd_soc_cards[i].codec_id);
- 			card = snd_soc_cards[i].soc_card;
- 			drv->acpi_card = &snd_soc_cards[i];
-+			found = true;
- 			break;
- 		}
- 	}
-+
-+	if (!found) {
-+		dev_err(&pdev->dev, "No matching HID found in supported list\n");
-+		return -ENODEV;
-+	}
-+
- 	card->dev = &pdev->dev;
--	mach = card->dev->platform_data;
- 	sprintf(drv->codec_name, "i2c-%s:00", drv->acpi_card->codec_id);
- 
- 	/* set correct codec name */
-@@ -386,9 +562,105 @@ static int snd_cht_mc_probe(struct platform_device *pdev)
- 	/* fixup codec name based on HID */
- 	i2c_name = sst_acpi_find_name_from_hid(mach->id);
- 	if (i2c_name != NULL) {
--		snprintf(cht_rt5640_codec_name, sizeof(cht_rt5640_codec_name),
-+		snprintf(cht_rt5645_codec_name, sizeof(cht_rt5645_codec_name),
- 			"%s%s", "i2c-", i2c_name);
--		cht_dailink[dai_index].codec_name = cht_rt5640_codec_name;
-+		cht_dailink[dai_index].codec_name = cht_rt5645_codec_name;
-+	}
-+
-+	/*
-+	 * swap SSP0 if bytcr is detected
-+	 * (will be overridden if DMI quirk is detected)
-+	 */
-+	if (is_valleyview()) {
-+		struct sst_platform_info *p_info = mach->pdata;
-+		const struct sst_res_info *res_info = p_info->res_info;
-+
-+		if (res_info->acpi_ipc_irq_index == 0)
-+			is_bytcr = true;
-+	}
-+
-+	if (is_bytcr) {
-+		/*
-+		 * Baytrail CR platforms may have CHAN package in BIOS, try
-+		 * to find relevant routing quirk based as done on Windows
-+		 * platforms. We have to read the information directly from the
-+		 * BIOS, at this stage the card is not created and the links
-+		 * with the codec driver/pdata are non-existent
-+		 */
-+
-+		struct acpi_chan_package chan_package;
-+
-+		/* format specified: 2 64-bit integers */
-+		struct acpi_buffer format = {sizeof("NN"), "NN"};
-+		struct acpi_buffer state = {0, NULL};
-+		struct sst_acpi_package_context pkg_ctx;
-+		bool pkg_found = false;
-+
-+		state.length = sizeof(chan_package);
-+		state.pointer = &chan_package;
-+
-+		pkg_ctx.name = "CHAN";
-+		pkg_ctx.length = 2;
-+		pkg_ctx.format = &format;
-+		pkg_ctx.state = &state;
-+		pkg_ctx.data_valid = false;
-+
-+		pkg_found = sst_acpi_find_package_from_hid(mach->id, &pkg_ctx);
-+		if (pkg_found) {
-+			if (chan_package.aif_value == 1) {
-+				dev_info(&pdev->dev, "BIOS Routing: AIF1 connected\n");
-+				cht_rt5645_quirk |= CHT_RT5645_SSP0_AIF1;
-+			} else  if (chan_package.aif_value == 2) {
-+				dev_info(&pdev->dev, "BIOS Routing: AIF2 connected\n");
-+				cht_rt5645_quirk |= CHT_RT5645_SSP0_AIF2;
-+			} else {
-+				dev_info(&pdev->dev, "BIOS Routing isn't valid, ignored\n");
-+				pkg_found = false;
-+			}
-+		}
-+
-+		if (!pkg_found) {
-+			/* no BIOS indications, assume SSP0-AIF2 connection */
-+			cht_rt5645_quirk |= CHT_RT5645_SSP0_AIF2;
-+		}
-+	}
-+
-+	/* check quirks before creating card */
-+	dmi_check_system(cht_rt5645_quirk_table);
-+	log_quirks(&pdev->dev);
-+
-+	if ((cht_rt5645_quirk & CHT_RT5645_SSP2_AIF2) ||
-+		(cht_rt5645_quirk & CHT_RT5645_SSP0_AIF2)) {
-+
-+		/* fixup codec aif name */
-+		snprintf(cht_rt5645_codec_aif_name,
-+			sizeof(cht_rt5645_codec_aif_name),
-+			"%s", "rt5645-aif2");
-+
-+		cht_dailink[dai_index].codec_dai_name =
-+			cht_rt5645_codec_aif_name;
-+	}
-+
-+	if ((cht_rt5645_quirk & CHT_RT5645_SSP0_AIF1) ||
-+		(cht_rt5645_quirk & CHT_RT5645_SSP0_AIF2)) {
-+
-+		/* fixup cpu dai name name */
-+		snprintf(cht_rt5645_cpu_dai_name,
-+			sizeof(cht_rt5645_cpu_dai_name),
-+			"%s", "ssp0-port");
-+
-+		cht_dailink[dai_index].cpu_dai_name =
-+			cht_rt5645_cpu_dai_name;
-+	}
-+
-+	if (is_valleyview()) {
-+		drv->mclk = devm_clk_get(&pdev->dev, "pmc_plt_clk_3");
-+		if (IS_ERR(drv->mclk)) {
-+			dev_err(&pdev->dev,
-+				"Failed to get MCLK from pmc_plt_clk_3: %ld\n",
-+				PTR_ERR(drv->mclk));
-+			return PTR_ERR(drv->mclk);
-+		}
- 	}
- 
- 	snd_soc_card_set_drvdata(card, drv);
-diff --git a/sound/soc/intel/boards/cht_cx2072x.c b/sound/soc/intel/boards/cht_cx2072x.c
-new file mode 100644
-index 000000000000..30a97b201c9a
---- /dev/null
-+++ b/sound/soc/intel/boards/cht_cx2072x.c
-@@ -0,0 +1,453 @@
-+/*
-+ *  cht_cx207x.c - ASoc DPCM Machine driver for CherryTrail w/ CX2072x
-+ *
-+ *  Copyright (C) 2016 Intel Corp
-+ *  Author: Pierre-Louis Bossart <pierre-louis.bossart@linux.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/init.h>
-+#include <linux/module.h>
-+#include <linux/platform_device.h>
-+#include <linux/acpi.h>
-+#include <linux/device.h>
-+#include <linux/dmi.h>
-+#include <linux/slab.h>
-+#include <asm/cpu_device_id.h>
-+#include <asm/platform_sst_audio.h>
-+#include <linux/clk.h>
-+#include <sound/pcm.h>
-+#include <sound/pcm_params.h>
-+#include <sound/soc.h>
-+#include <sound/jack.h>
-+#include "../../codecs/cx2072x.h"
-+#include "../atom/sst-atom-controls.h"
-+#include "../common/sst-acpi.h"
-+
-+
-+#define CHT_PLAT_CLK_3_HZ	19200000
-+
-+enum {
-+	CHT_CX_DMIC_MAP,
-+};
-+
-+#define CHT_CX_MAP(quirk)	((quirk) & 0xff)
-+#define CHT_CX_MCLK_EN	BIT(16)
-+
-+
-+struct cht_mc_private {
-+	struct clk *mclk;
-+};
-+
-+static unsigned long cht_cx_quirk = CHT_CX_MCLK_EN;
-+
-+#define BYT_CODEC_DAI1	"cx2072x-hifi"
-+
-+static inline struct snd_soc_dai *byt_get_codec_dai(struct snd_soc_card *card)
-+{
-+	struct snd_soc_pcm_runtime *rtd;
-+
-+	list_for_each_entry(rtd, &card->rtd_list, list) {
-+		if (!strncmp(rtd->codec_dai->name, BYT_CODEC_DAI1,
-+			     strlen(BYT_CODEC_DAI1)))
-+			return rtd->codec_dai;
-+	}
-+	return NULL;
-+}
-+
-+static int platform_clock_control(struct snd_soc_dapm_widget *w,
-+				  struct snd_kcontrol *k, int  event)
-+{
-+	struct snd_soc_dapm_context *dapm = w->dapm;
-+	struct snd_soc_card *card = dapm->card;
-+	struct snd_soc_dai *codec_dai;
-+	struct cht_mc_private *priv = snd_soc_card_get_drvdata(card);
-+	int ret;
-+
-+	codec_dai = byt_get_codec_dai(card);
-+	if (!codec_dai) {
-+		dev_err(card->dev,
-+			"Codec dai not found; Unable to set platform clock\n");
-+		return -EIO;
-+	}
-+
-+	if (SND_SOC_DAPM_EVENT_ON(event)) {
-+		if ((cht_cx_quirk & CHT_CX_MCLK_EN) && priv->mclk) {
-+			ret = clk_prepare_enable(priv->mclk);
-+			if (ret < 0) {
-+				dev_err(card->dev,
-+					"could not configure MCLK state");
-+				return ret;
-+			}
-+		}
-+		ret = snd_soc_dai_set_sysclk(codec_dai, CX2072X_MCLK_EXTERNAL_PLL,
-+				     19200000, SND_SOC_CLOCK_IN);
-+	} else {
-+		/*
-+		 * Set codec clock source to internal clock before
-+		 * turning off the platform clock. Codec needs clock
-+		 * for Jack detection and button press
-+		 */
-+
-+		/* FIXME: what is the internal setting, if any? */
-+		ret = snd_soc_dai_set_sysclk(codec_dai, CX2072X_MCLK_EXTERNAL_PLL,
-+				     19200000, SND_SOC_CLOCK_IN);
-+
-+		if (!ret) {
-+			if ((cht_cx_quirk & CHT_CX_MCLK_EN) && priv->mclk)
-+				clk_disable_unprepare(priv->mclk);
-+		}
-+	}
-+
-+	if (ret < 0) {
-+		dev_err(card->dev, "can't set codec sysclk: %d\n", ret);
-+		return ret;
-+	}
-+
-+	return 0;
-+}
-+
-+static const struct snd_soc_dapm_widget 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),
-+	SND_SOC_DAPM_SUPPLY("Platform Clock", SND_SOC_NOPM, 0, 0,
-+			platform_clock_control, SND_SOC_DAPM_PRE_PMU |
-+			SND_SOC_DAPM_POST_PMD),
-+};
-+
-+static const struct snd_soc_dapm_route cht_audio_map[] = {
-+		/* External Speakers: HFL, HFR */
-+		{"Headphone", NULL, "PORTA"},
-+		{"Ext Spk", NULL, "PORTG"},
-+		{"PORTC", NULL, "Int Mic"},
-+		/* Headset Mic: Headset Mic with bias */
-+		{"PORTD", NULL, "Headset Mic"},
-+		/*{"Headset Bias", NULL, "Headset Mic"},*/
-+		/*{"PortD Mic Bias", NULL, "Headset Mic"},*/
-+
-+		/* Headset Stereophone(Headphone): HSOL, HSOR */
-+		//{"Headphone", NULL, "HPL"},
-+		//{"Headphone", NULL, "HPR"},
-+
-+		{"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"},
-+		{"Playback", NULL, "Platform Clock"},
-+		{"Capture", NULL, "Platform Clock"},
-+};
-+
-+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;
-+	
-+	ret = snd_soc_dai_set_sysclk(codec_dai, CX2072X_MCLK_EXTERNAL_PLL,
-+				     19200000, SND_SOC_CLOCK_IN);
-+	if (ret < 0) {
-+		dev_err(rtd->dev, "can't set codec sysclk: %d\n", ret);
-+		return ret;
-+	}
-+
-+	/* FIXME: No need PLL for conexant codec */
-+#if 0
-+	ret = snd_soc_dai_set_pll(codec_dai, 0, RT5670_PLL1_S_MCLK,
-+				  CHT_PLAT_CLK_3_HZ, rate * 512);
-+	if (ret < 0) {
-+		dev_err(rtd->dev, "can't set codec pll: %d\n", ret);
-+		return ret;
-+	}
-+#endif
-+
-+
-+	return 0;
-+}
-+
-+static int cht_codec_init(struct snd_soc_pcm_runtime *runtime)
-+{
-+	int ret=0;
-+	struct snd_soc_card *card = runtime->card;
-+	struct cht_mc_private *priv = snd_soc_card_get_drvdata(runtime->card);
-+
-+	card->dapm.idle_bias_off = true;
-+
-+	/* FIXME: is this necessary */
-+//      snd_soc_dapm_ignore_suspend(&codec->dapm, "PortD");
-+//	snd_soc_dapm_enable_pin(&card->dapm, "Headset Mic");
-+//	snd_soc_dapm_enable_pin(&card->dapm, "Headphone");
-+//	snd_soc_dapm_enable_pin(&card->dapm, "Ext Spk");
-+//	snd_soc_dapm_enable_pin(&card->dapm, "Int Mic");
-+
-+//	snd_soc_dapm_sync(&card->dapm);
-+
-+	if ((cht_cx_quirk & CHT_CX_MCLK_EN) && priv->mclk) {
-+		/*
-+		 * The firmware might enable the clock at
-+		 * boot (this information may or may not
-+		 * be reflected in the enable clock register).
-+		 * To change the rate we must disable the clock
-+		 * first to cover these cases. Due to common
-+		 * clock framework restrictions that do not allow
-+		 * to disable a clock that has not been enabled,
-+		 * we need to enable the clock first.
-+		 */
-+		ret = clk_prepare_enable(priv->mclk);
-+		if (!ret)
-+			clk_disable_unprepare(priv->mclk);
-+
-+		ret = clk_set_rate(priv->mclk, 19200000);
-+
-+		if (ret)
-+			dev_err(card->dev, "unable to set MCLK rate\n");
-+	}
-+
-+	return ret;
-+}
-+
-+static const struct snd_soc_pcm_stream cht_dai_params = {
-+	.formats = SNDRV_PCM_FMTBIT_S24_LE,
-+	.rate_min = 48000,
-+	.rate_max = 48000,
-+	.channels_min = 2,
-+	.channels_max = 2,
-+};
-+
-+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);
-+	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_IF   |
-+				SND_SOC_DAIFMT_CBS_CFS);
-+	if (ret < 0) {
-+		dev_err(rtd->dev, "can't set format to I2S, err %d\n", ret);
-+		return ret;
-+	}
-+
-+	return 0;
-+}
-+
-+static const struct snd_soc_pcm_stream cht_cx_dai_params = {
-+	.formats = SNDRV_PCM_FMTBIT_S24_LE,
-+	.rate_min = 48000,
-+	.rate_max = 48000,
-+	.channels_min = 2,
-+	.channels_max = 2,
-+};
-+
-+static int cht_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 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[] = {
-+	[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 = &cht_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 = &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",
-+	},
-+	/* CODEC<->CODEC link */
-+	/* 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_IF
-+		                              | SND_SOC_DAIFMT_CBS_CFS,
-+		.init = cht_codec_init,
-+		.be_hw_params_fixup = cht_codec_fixup,
-+		.nonatomic = true,
-+		.dpcm_playback = 1,
-+		.dpcm_capture = 1,
-+		.ops = &cht_be_ssp2_ops,
-+	},
-+};
-+
-+/* SoC card */
-+static struct snd_soc_card chtcx2072x_card = {
-+	.name = "chtcx2072x",
-+	.dai_link = cht_dailink,
-+	.num_links = ARRAY_SIZE(cht_dailink),
-+	.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 char cht_cx_codec_name[16]; /* i2c-<HID>:00 with HID being 8 chars */
-+
-+static bool is_valleyview(void)
-+{
-+	static const struct x86_cpu_id cpu_ids[] = {
-+		{ X86_VENDOR_INTEL, 6, 55 }, /* Valleyview, Bay Trail */
-+		{}
-+	};
-+
-+	if (!x86_match_cpu(cpu_ids))
-+		return false;
-+	return true;
-+}
-+
-+static int snd_cht_mc_probe(struct platform_device *pdev)
-+{
-+	int ret_val = 0;
-+	int i;
-+	int dai_index;
-+	struct cht_mc_private *drv;
-+	struct sst_acpi_mach *mach;
-+	const char *i2c_name = NULL;
-+	
-+	drv = devm_kzalloc(&pdev->dev, sizeof(*drv), GFP_ATOMIC);
-+	if (!drv) {
-+		pr_err("allocation failed\n");
-+		return -ENOMEM;
-+	}
-+
-+	/* register the soc card */
-+	chtcx2072x_card.dev = &pdev->dev;
-+	mach = chtcx2072x_card.dev->platform_data;
-+	snd_soc_card_set_drvdata(&chtcx2072x_card, drv);
-+	
-+	/* fix index of codec dai */
-+	dai_index = MERR_DPCM_COMPR + 1;
-+	for (i = 0; i < ARRAY_SIZE(cht_dailink); i++) {
-+		if (!strcmp(cht_dailink[i].codec_name, "i2c-14F10720:00")) {
-+			dai_index = i;
-+			break;
-+		}
-+	}
-+
-+	/* fixup codec name based on HID */
-+	i2c_name = sst_acpi_find_name_from_hid(mach->id);
-+	if (i2c_name != NULL) {
-+		snprintf(cht_cx_codec_name, sizeof(cht_cx_codec_name),
-+			"%s%s", "i2c-", i2c_name);
-+
-+		cht_dailink[dai_index].codec_name = cht_cx_codec_name;
-+	}
-+
-+	if ((cht_cx_quirk & CHT_CX_MCLK_EN) && (is_valleyview())) {
-+		drv->mclk = devm_clk_get(&pdev->dev, "pmc_plt_clk_3");
-+		if (IS_ERR(drv->mclk)) {
-+			dev_err(&pdev->dev,
-+				"Failed to get MCLK from pmc_plt_clk_3: %ld\n",
-+				PTR_ERR(drv->mclk));
-+			
-+			return PTR_ERR(drv->mclk);
-+		}
-+	}
-+
-+	ret_val = devm_snd_soc_register_card(&pdev->dev, &chtcx2072x_card);
-+	
-+	if (ret_val) {
-+		dev_err(&pdev->dev, "devm_snd_soc_register_card failed %d\n",
-+			ret_val);
-+		return ret_val;
-+	}
-+	platform_set_drvdata(pdev, &chtcx2072x_card);
-+	return ret_val;
-+}
-+
-+
-+
-+static struct platform_driver snd_cht_mc_driver = {
-+	.driver = {
-+		.name = "cht-cx2072x",
-+		.pm = &snd_soc_pm_ops,
-+	},
-+	.probe = snd_cht_mc_probe,
-+};
-+module_platform_driver(snd_cht_mc_driver);
-+
-+MODULE_DESCRIPTION("ASoC Intel(R) Cherrytrail Machine driver");
-+MODULE_AUTHOR("Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>");
-+MODULE_LICENSE("GPL v2");
-+MODULE_ALIAS("platform:cht-cx2072x");
-diff --git a/sound/soc/intel/common/sst-acpi.h b/sound/soc/intel/common/sst-acpi.h
-index 012742299dd5..214e000667ae 100644
---- a/sound/soc/intel/common/sst-acpi.h
-+++ b/sound/soc/intel/common/sst-acpi.h
-@@ -15,14 +15,29 @@
- #include <linux/stddef.h>
- #include <linux/acpi.h>
- 
--/* translation fron HID to I2C name, needed for DAI codec_name */
-+struct sst_acpi_package_context {
-+	char *name;           /* package name */
-+	int length;           /* number of elements */
-+	struct acpi_buffer *format;
-+	struct acpi_buffer *state;
-+	bool data_valid;
-+};
-+
- #if IS_ENABLED(CONFIG_ACPI)
-+/* translation fron HID to I2C name, needed for DAI codec_name */
- const char *sst_acpi_find_name_from_hid(const u8 hid[ACPI_ID_LEN]);
-+bool sst_acpi_find_package_from_hid(const u8 hid[ACPI_ID_LEN],
-+				    struct sst_acpi_package_context *ctx);
- #else
- static inline const char *sst_acpi_find_name_from_hid(const u8 hid[ACPI_ID_LEN])
- {
- 	return NULL;
- }
-+static inline bool sst_acpi_find_package_from_hid(const u8 hid[ACPI_ID_LEN],
-+					   struct sst_acpi_package_context *ctx)
-+{
-+	return false;
-+}
- #endif
- 
- /* acpi match */
-diff --git a/sound/soc/intel/common/sst-match-acpi.c b/sound/soc/intel/common/sst-match-acpi.c
-index 789843307a49..1070f3ad23e5 100644
---- a/sound/soc/intel/common/sst-match-acpi.c
-+++ b/sound/soc/intel/common/sst-match-acpi.c
-@@ -77,5 +77,62 @@ struct sst_acpi_mach *sst_acpi_find_machine(struct sst_acpi_mach *machines)
- }
- EXPORT_SYMBOL_GPL(sst_acpi_find_machine);
- 
-+static acpi_status sst_acpi_find_package(acpi_handle handle, u32 level,
-+					void *context, void **ret)
-+{
-+	struct acpi_device *adev;
-+	acpi_status status = AE_OK;
-+	struct sst_acpi_package_context *pkg_ctx = context;
-+
-+	pkg_ctx->data_valid = false;
-+
-+	if (acpi_bus_get_device(handle, &adev))
-+		return AE_OK;
-+
-+	if (adev->status.present && adev->status.functional) {
-+		struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
-+		union acpi_object  *myobj = NULL;
-+
-+		status = acpi_evaluate_object_typed(handle, pkg_ctx->name,
-+						NULL, &buffer,
-+						ACPI_TYPE_PACKAGE);
-+		if (ACPI_FAILURE(status))
-+			return AE_OK;
-+
-+		myobj = buffer.pointer;
-+		if (!myobj || myobj->package.count != pkg_ctx->length) {
-+			kfree(buffer.pointer);
-+			return AE_OK;
-+		}
-+
-+		status = acpi_extract_package(myobj,
-+					pkg_ctx->format, pkg_ctx->state);
-+		if (ACPI_FAILURE(status)) {
-+			kfree(buffer.pointer);
-+			return AE_OK;
-+		}
-+
-+		kfree(buffer.pointer);
-+		pkg_ctx->data_valid = true;
-+		return AE_CTRL_TERMINATE;
-+	}
-+
-+	return AE_OK;
-+}
-+
-+bool sst_acpi_find_package_from_hid(const u8 hid[ACPI_ID_LEN],
-+				struct sst_acpi_package_context *ctx)
-+{
-+	acpi_status status;
-+
-+	status = acpi_get_devices(hid, sst_acpi_find_package, ctx, NULL);
-+
-+	if (ACPI_FAILURE(status) || !ctx->data_valid)
-+		return false;
-+
-+	return true;
-+}
-+EXPORT_SYMBOL_GPL(sst_acpi_find_package_from_hid);
-+
- MODULE_LICENSE("GPL v2");
- MODULE_DESCRIPTION("Intel Common ACPI Match module");