[alsa-devel] [PATCH 07/19] ALSA: ymu831: add base driver

Yoichi Yuasa yuasa at linux-mips.org
Wed Jan 16 09:33:03 CET 2013


Signed-off-by: Yoichi Yuasa <yuasa at linux-mips.org>
---
 sound/soc/codecs/ymu831/Makefile   |    3 +-
 sound/soc/codecs/ymu831/mcdriver.c | 2934 ++++++++++++++++++++++++++++++++++++
 sound/soc/codecs/ymu831/mcdriver.h | 1017 +++++++++++++
 3 files changed, 3953 insertions(+), 1 deletion(-)
 create mode 100644 sound/soc/codecs/ymu831/mcdriver.c
 create mode 100644 sound/soc/codecs/ymu831/mcdriver.h

diff --git a/sound/soc/codecs/ymu831/Makefile b/sound/soc/codecs/ymu831/Makefile
index 949640e..e908b6d 100644
--- a/sound/soc/codecs/ymu831/Makefile
+++ b/sound/soc/codecs/ymu831/Makefile
@@ -1,6 +1,7 @@
 snd-soc-ymu831-objs := \
 	mcbdspdrv.o	\
 	mccdspdrv.o	\
-	mcdevif.o
+	mcdevif.o	\
+	mcdriver.o
 
 obj-$(CONFIG_SND_SOC_YMU831) += snd-soc-ymu831.o
diff --git a/sound/soc/codecs/ymu831/mcdriver.c b/sound/soc/codecs/ymu831/mcdriver.c
new file mode 100644
index 0000000..dbdce57
--- /dev/null
+++ b/sound/soc/codecs/ymu831/mcdriver.c
@@ -0,0 +1,2934 @@
+/****************************************************************************
+ *
+ * Copyright(c) 2012 Yamaha Corporation. All rights reserved.
+ *
+ * Module	: mcdriver.c
+ * Description	: MC base driver
+ * Version	: 1.0.1	Dec 20 2012
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty.	In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ *	claim that you wrote the original software. If you use this software
+ *	in a product, an acknowledgment in the product documentation would be
+ *	appreciated but is not required.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ *	misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ *
+ ****************************************************************************/
+/*
+ * changelog:
+ * - change in the Linux coding style
+ * - remove unnecessary comments
+ * - remove unused codes
+ */
+#include <linux/errno.h>
+#include <linux/delay.h>
+#include <linux/mutex.h>
+#include <linux/string.h>
+#include <linux/types.h>
+
+#include "mcbdspdrv.h"
+#include "mccdspdrv.h"
+#include "mcdefs.h"
+#include "mcdevif.h"
+#include "mcdriver.h"
+#include "mcedspdrv.h"
+#include "mcfdspdrv.h"
+#include "mcparser.h"
+#include "mcresctrl.h"
+
+#define LDO_WAIT_TIME			1	/* msec */
+#define VREF_WAIT_TIME_ES1		2	/* msec */
+#define VREF_WAIT_TIME			30	/* msec */
+#define MCDRV_DAC_MUTE_WAIT_TIME	20000
+#define MCDRV_MB4_WAIT_TIME		8000
+
+#define	T_CPMODE_IMPSENSE_BEFORE	0
+#define	T_CPMODE_IMPSENSE_AFTER		2
+
+static struct mcdrv_path_info path_alloff = {
+	.music_out = {0x00AAAAAA, 0x00AAAAAA},
+	.ext_out = {0x00AAAAAA, 0x00AAAAAA},
+	.hifi_out = {0x00AAAAAA},
+	.vbox_mix_in = {0x00AAAAAA, 0x00AAAAAA, 0x00AAAAAA, 0x00AAAAAA},
+	.ae0 = {0x00AAAAAA, 0x00AAAAAA},
+	.ae1 = {0x00AAAAAA, 0x00AAAAAA},
+	.ae2 = {0x00AAAAAA, 0x00AAAAAA},
+	.ae3 = {0x00AAAAAA, 0x00AAAAAA},
+	.dac0 = {0x00AAAAAA, 0x00AAAAAA},
+	.dac1 = {0x00AAAAAA, 0x00AAAAAA},
+	.voice_out = {0x00AAAAAA},
+	.vbox_io_in = {0x00AAAAAA},
+	.vbox_host_in = {0x00AAAAAA},
+	.host_out = {0x00AAAAAA},
+	.adif0 = {0x00AAAAAA, 0x00AAAAAA},
+	.adif1 = {0x00AAAAAA, 0x00AAAAAA},
+	.adif2 = {0x00AAAAAA, 0x00AAAAAA},
+	.adc0 = {0x002AAAAA, 0x002AAAAA},
+	.adc1 = {0x002AAAAA},
+	.sp = {0x002AAAAA, 0x002AAAAA},
+	.hp = {0x002AAAAA, 0x002AAAAA},
+	.rc = {0x002AAAAA},
+	.lout1 = {0x002AAAAA, 0x002AAAAA},
+	.lout2 = {0x002AAAAA, 0x002AAAAA},
+	.bias = {0x002AAAAA, 0x002AAAAA, 0x002AAAAA, 0x002AAAAA},
+};
+
+static DEFINE_MUTEX(mcdrv_mutex);
+
+#ifndef MCDRV_SKIP_IMPSENSE
+static inline int imp_sense_start(u8 *op_dac)
+{
+	struct mcdrv_power_info power_info;
+	struct mcdrv_power_update power_update;
+	struct mcdrv_hsdet_info hsdet_info;
+	struct mcdrv_dev_info info;
+	enum mcdrv_dev_id id;
+	u8 val, data[2];
+	int ret = 0;
+
+	id = mc_dev_id_get();
+	mc_power_info_get_current(&power_info);
+	power_info.digital &= ~(MCDRV_POWINFO_D_PM_CLK_PD |
+				MCDRV_POWINFO_D_PE_CLK_PD |
+				MCDRV_POWINFO_D_PLL_PD);
+	power_info.analog[0] &= ~(MCB_AP_LDOA | MCB_AP_BGR | MCB_AP_VR);
+
+	/* power up */
+	power_update.digital = MCDRV_POWUPDATE_D_ALL;
+	power_update.analog[0] = (u8) MCDRV_POWUPDATE_AP;
+	power_update.analog[1] = 0;
+	power_update.analog[2] = 0;
+	power_update.analog[3] = 0;
+	power_update.analog[4] = 0;
+	ret = mc_packet_add_powerup(&power_info, &power_update);
+	if (ret < 0)
+		goto exit;
+
+	ret = mc_packet_execute();
+	if (ret < 0)
+		goto exit;
+
+	mc_packet_add_force_write_if(MCI_IRQ, 0);
+	mc_packet_add_force_write_cd(MCI_IRQHS, 0);
+
+	mc_packet_add_write_e(MCI_E1DSP_CTRL, 0);
+
+	mc_packet_add_dac0_mute();
+
+	val = mc_e_register_get_value(MCI_LPF_THR);
+	val |= (MCB_OSF0_ENB | MCB_LPF0_PST_THR | MCB_LPF0_PRE_THR);
+	mc_packet_add_write_e(MCI_LPF_THR, val);
+
+	val = mc_cd_register_get_value(MCI_DP);
+	if (id == MCDRV_DEV_ID_80_90H) {
+		val &= ~(MCB_DP_ADC | MCB_DP_DAC0 | MCB_DP_PDMCK |
+			 MCB_DP_PDMADC | MCB_DP_PDMDAC);
+	} else {
+		val &= ~(MCB_DP_ADC | MCB_DP_DAC1 | MCB_DP_DAC0 |
+			 MCB_DP_PDMCK | MCB_DP_PDMADC | MCB_DP_PDMDAC);
+	}
+	mc_packet_add_write_cd(MCI_DP, val);
+
+	val = mc_e_register_get_value(MCI_DCL_GAIN);
+	val |= MCB_DCL0_OFF;
+	mc_packet_add_write_e(MCI_DCL_GAIN, val);
+
+	if (id == MCDRV_DEV_ID_80_90H) {
+		val = mc_e_register_get_value(MCI_DSF0_FLT_TYPE);
+		val |= MCB_DSF0ENB;
+		mc_packet_add_write_e(MCI_DSF0_FLT_TYPE, val);
+	} else {
+		val = mc_e_register_get_value(MCI_DSF2_FLT_TYPE);
+		val |= MCB_DSF2ENB;
+		mc_packet_add_write_e(MCI_DSF2_FLT_TYPE, val);
+	}
+
+	mc_hsdet_info_get(&hsdet_info);
+	val = hsdet_info.sgnl_peak << 4 | hsdet_info.sgnl_num << 2 |
+	    hsdet_info.sgnl_period;
+	mc_packet_add_write_e(MCI_IMPSEL, val);
+
+	mc_packet_add_write_if(MCI_IRQR, MCB_EIRQR);
+
+	mc_packet_add_write_cd(MCI_EIRQSENSE, MCB_EIRQSENSE);
+
+	if (id == MCDRV_DEV_ID_80_90H) {
+		*op_dac = mc_ana_register_get_value(19);
+		mc_packet_add_write_ana(19, 0);
+	}
+
+	mc_dev_info_get(&info);
+	if (id == MCDRV_DEV_ID_80_90H)
+		mc_packet_add_write_ana(MCI_HPDETVOL, 0x70);
+	else
+		mc_packet_add_write_ana(MCI_HPDETVOL, info.options[9]);
+
+	if (id == MCDRV_DEV_ID_80_90H) {
+		mc_packet_add_force_write_ana(78, T_CPMODE_IMPSENSE_BEFORE);
+		mc_packet_add_force_write_ana(87, 0x11);
+	} else {
+		mc_packet_add_force_write_if(31, 0xb5);
+		mc_packet_add_force_write_if(30, 0xd6);
+		mc_packet_add_force_write_ana(87, info.options[10]);
+	}
+
+	ret = mc_packet_execute();
+	if (ret < 0)
+		goto exit;
+
+	if (id == MCDRV_DEV_ID_80_90H) {
+		data[0] = MCI_ANA_REG_A << 1;
+		data[1] = 78;
+		mc_write_analog(data, 2);
+		mc_read_analog(MCI_ANA_REG_D, &val, 1);
+		if (val != T_CPMODE_IMPSENSE_BEFORE) {
+			ret = -EIO;
+			goto exit;
+		}
+	}
+
+	val = E1COMMAND_IMP_SENSE;
+	if (info.gnd_det == MCDRV_GNDDET_ON)
+		val |= E1COMMAND_GND_DET;
+	if (mc_a_source_is_used(MCDRV_ASRC_DAC1_L_ON) ||
+	    mc_a_source_is_used(MCDRV_ASRC_DAC1_R_ON) ||
+	    mc_d2_source_is_used(MCDRV_D2SRC_ADC0_L_ON) ||
+	    mc_d2_source_is_used(MCDRV_D2SRC_ADC0_R_ON) ||
+	    mc_d2_source_is_used(MCDRV_D2SRC_ADC1_ON) ||
+	    mc_d2_source_is_used(MCDRV_D2SRC_PDM0_L_ON) ||
+	    mc_d2_source_is_used(MCDRV_D2SRC_PDM0_R_ON) ||
+	    mc_d2_source_is_used(MCDRV_D2SRC_PDM1_L_ON) ||
+	    mc_d2_source_is_used(MCDRV_D2SRC_PDM1_R_ON))
+		val |= E1COMMAND_ADDITIONAL;
+	else if (mc_a_source_is_used(MCDRV_ASRC_DAC0_L_ON) ||
+		 mc_a_source_is_used(MCDRV_ASRC_DAC0_R_ON))
+		val |= E1COMMAND_ADDITIONAL | E1COMMAND_PD;
+
+	if (id == MCDRV_DEV_ID_80_90H)
+		mc_packet_add_wait(MCDRV_DAC_MUTE_WAIT_TIME);
+	else
+		val |= E1COMMAND_WAIT;
+	mc_packet_add_force_write_e(MCI_E1COMMAND, val);
+
+	ret = mc_packet_execute();
+
+exit:
+	return ret;
+}
+#endif
+
+static inline bool is_ldoa_on(void)
+{
+	if (mc_source_is_used(MCDRV_DST_ADC0, MCDRV_DST_CH0))
+		return true;
+
+	if (mc_source_is_used(MCDRV_DST_ADC0, MCDRV_DST_CH1))
+		return true;
+
+	if (mc_source_is_used(MCDRV_DST_ADC1, MCDRV_DST_CH0))
+		return true;
+
+	if (mc_source_is_used(MCDRV_DST_BIAS, MCDRV_DST_CH0))
+		return true;
+
+	if (mc_source_is_used(MCDRV_DST_BIAS, MCDRV_DST_CH1))
+		return true;
+
+	if (mc_source_is_used(MCDRV_DST_BIAS, MCDRV_DST_CH2))
+		return true;
+
+	if (mc_source_is_used(MCDRV_DST_BIAS, MCDRV_DST_CH3))
+		return true;
+
+	if (mc_a_source_is_used(MCDRV_ASRC_DAC0_L_ON))
+		return true;
+
+	if (mc_a_source_is_used(MCDRV_ASRC_DAC0_R_ON))
+		return true;
+
+	if (mc_a_source_is_used(MCDRV_ASRC_DAC1_L_ON))
+		return true;
+
+	if (mc_a_source_is_used(MCDRV_ASRC_DAC1_R_ON))
+		return true;
+
+	return false;
+}
+
+static inline void mask_irregular_path_info(struct mcdrv_path_info *path_info)
+{
+	u8 ch;
+
+	for (ch = 0; ch < MUSICOUT_PATH_CHANNELS; ch++)
+		path_info->music_out[ch] &= ~MCDRV_D1SRC_HIFIIN_ON;
+
+	for (ch = 0; ch < EXTOUT_PATH_CHANNELS; ch++)
+		path_info->ext_out[ch] &= ~MCDRV_D1SRC_HIFIIN_ON;
+
+	for (ch = 0; ch < HIFIOUT_PATH_CHANNELS; ch++)
+		path_info->hifi_out[ch] &=
+		    MCDRV_D1SRC_ADIF0_ON | MCDRV_D1SRC_ADIF0_OFF;
+
+	for (ch = 0; ch < VBOXMIXIN_PATH_CHANNELS; ch++)
+		path_info->vbox_mix_in[ch] &= ~MCDRV_D1SRC_HIFIIN_ON;
+
+	for (ch = 0; ch < AE_PATH_CHANNELS; ch++) {
+		path_info->ae0[ch] &= ~MCDRV_D1SRC_HIFIIN_ON;
+		path_info->ae1[ch] &= ~MCDRV_D1SRC_HIFIIN_ON;
+		path_info->ae2[ch] &= ~MCDRV_D1SRC_HIFIIN_ON;
+		path_info->ae3[ch] &= ~MCDRV_D1SRC_HIFIIN_ON;
+	}
+
+	for (ch = 0; ch < VOICEOUT_PATH_CHANNELS; ch++)
+		path_info->voice_out[ch] &=
+		    MCDRV_D2SRC_VBOXIOOUT_ON | MCDRV_D2SRC_VBOXIOOUT_OFF;
+
+	for (ch = 0; ch < VBOXIOIN_PATH_CHANNELS; ch++)
+		path_info->vbox_io_in[ch] &=
+		    MCDRV_D2SRC_VOICEIN_ON | MCDRV_D2SRC_VOICEIN_OFF;
+
+	for (ch = 0; ch < VBOXHOSTIN_PATH_CHANNELS; ch++)
+		path_info->vbox_host_in[ch] &=
+		    MCDRV_D2SRC_VOICEIN_ON | MCDRV_D2SRC_VOICEIN_OFF;
+
+	for (ch = 0; ch < HOSTOUT_PATH_CHANNELS; ch++)
+		path_info->host_out[ch] &=
+		    MCDRV_D2SRC_VBOXHOSTOUT_ON | MCDRV_D2SRC_VBOXHOSTOUT_OFF;
+
+	for (ch = 0; ch < ADIF0_PATH_CHANNELS; ch++)
+		path_info->adif0[ch] &= MCDRV_D2SRC_ADC0_L_ON
+		    | MCDRV_D2SRC_ADC0_L_OFF
+		    | MCDRV_D2SRC_ADC0_R_ON
+		    | MCDRV_D2SRC_ADC0_R_OFF
+		    | MCDRV_D2SRC_ADC1_ON
+		    | MCDRV_D2SRC_ADC1_OFF
+		    | MCDRV_D2SRC_PDM0_L_ON
+		    | MCDRV_D2SRC_PDM0_L_OFF
+		    | MCDRV_D2SRC_PDM0_R_ON
+		    | MCDRV_D2SRC_PDM0_R_OFF
+		    | MCDRV_D2SRC_PDM1_L_ON
+		    | MCDRV_D2SRC_PDM1_L_OFF
+		    | MCDRV_D2SRC_PDM1_R_ON | MCDRV_D2SRC_PDM1_R_OFF;
+
+	for (ch = 0; ch < ADIF1_PATH_CHANNELS; ch++)
+		path_info->adif1[ch] &= MCDRV_D2SRC_ADC0_L_ON
+		    | MCDRV_D2SRC_ADC0_L_OFF
+		    | MCDRV_D2SRC_ADC0_R_ON
+		    | MCDRV_D2SRC_ADC0_R_OFF
+		    | MCDRV_D2SRC_ADC1_ON
+		    | MCDRV_D2SRC_ADC1_OFF
+		    | MCDRV_D2SRC_PDM0_L_ON
+		    | MCDRV_D2SRC_PDM0_L_OFF
+		    | MCDRV_D2SRC_PDM0_R_ON
+		    | MCDRV_D2SRC_PDM0_R_OFF
+		    | MCDRV_D2SRC_PDM1_L_ON
+		    | MCDRV_D2SRC_PDM1_L_OFF
+		    | MCDRV_D2SRC_PDM1_R_ON | MCDRV_D2SRC_PDM1_R_OFF;
+
+	for (ch = 0; ch < ADIF2_PATH_CHANNELS; ch++)
+		path_info->adif2[ch] &= MCDRV_D2SRC_ADC0_L_ON
+		    | MCDRV_D2SRC_ADC0_L_OFF
+		    | MCDRV_D2SRC_ADC0_R_ON
+		    | MCDRV_D2SRC_ADC0_R_OFF
+		    | MCDRV_D2SRC_ADC1_ON
+		    | MCDRV_D2SRC_ADC1_OFF
+		    | MCDRV_D2SRC_PDM0_L_ON
+		    | MCDRV_D2SRC_PDM0_L_OFF
+		    | MCDRV_D2SRC_PDM0_R_ON
+		    | MCDRV_D2SRC_PDM0_R_OFF
+		    | MCDRV_D2SRC_PDM1_L_ON
+		    | MCDRV_D2SRC_PDM1_L_OFF
+		    | MCDRV_D2SRC_PDM1_R_ON
+		    | MCDRV_D2SRC_PDM1_R_OFF
+		    | MCDRV_D2SRC_DAC0REF_ON
+		    | MCDRV_D2SRC_DAC0REF_OFF
+		    | MCDRV_D2SRC_DAC1REF_ON | MCDRV_D2SRC_DAC1REF_OFF;
+
+	path_info->adc0[0] &= ~(MCDRV_ASRC_DAC0_L_ON | MCDRV_ASRC_DAC0_R_ON |
+				MCDRV_ASRC_DAC1_L_ON | MCDRV_ASRC_DAC1_R_ON |
+				MCDRV_ASRC_LINEIN1_R_ON);
+	path_info->adc0[1] &= ~(MCDRV_ASRC_DAC0_L_ON | MCDRV_ASRC_DAC0_R_ON |
+				MCDRV_ASRC_DAC1_L_ON | MCDRV_ASRC_DAC1_R_ON |
+				MCDRV_ASRC_LINEIN1_L_ON);
+
+	for (ch = 0; ch < ADC1_PATH_CHANNELS; ch++)
+		path_info->adc1[ch] &= ~(MCDRV_ASRC_DAC0_L_ON |
+					 MCDRV_ASRC_DAC0_R_ON |
+					 MCDRV_ASRC_DAC1_L_ON |
+					 MCDRV_ASRC_DAC1_R_ON |
+					 MCDRV_ASRC_LINEIN1_L_ON |
+					 MCDRV_ASRC_LINEIN1_R_ON);
+
+	path_info->sp[0] &= MCDRV_ASRC_DAC1_L_ON | MCDRV_ASRC_DAC1_L_OFF;
+	path_info->sp[1] &= MCDRV_ASRC_DAC1_R_ON | MCDRV_ASRC_DAC1_R_OFF;
+
+	path_info->hp[0] &= MCDRV_ASRC_DAC0_L_ON | MCDRV_ASRC_DAC0_L_OFF;
+	path_info->hp[1] &= MCDRV_ASRC_DAC0_R_ON | MCDRV_ASRC_DAC0_R_OFF;
+
+	path_info->rc[0] &= MCDRV_ASRC_DAC0_L_ON | MCDRV_ASRC_DAC0_L_OFF;
+
+	path_info->lout1[0] &= MCDRV_ASRC_DAC0_L_ON | MCDRV_ASRC_DAC0_L_OFF;
+	path_info->lout1[1] &= MCDRV_ASRC_DAC0_R_ON | MCDRV_ASRC_DAC0_R_OFF;
+
+	path_info->lout2[0] &= MCDRV_ASRC_DAC1_L_ON | MCDRV_ASRC_DAC1_L_OFF;
+	path_info->lout2[1] &= MCDRV_ASRC_DAC1_R_ON | MCDRV_ASRC_DAC1_R_OFF;
+
+	path_info->bias[0] &= MCDRV_ASRC_MIC1_ON | MCDRV_ASRC_MIC1_OFF;
+	path_info->bias[1] &= MCDRV_ASRC_MIC2_ON | MCDRV_ASRC_MIC2_OFF;
+	path_info->bias[2] &= MCDRV_ASRC_MIC3_ON | MCDRV_ASRC_MIC3_OFF;
+	path_info->bias[3] &= MCDRV_ASRC_MIC4_ON | MCDRV_ASRC_MIC4_OFF;
+}
+
+static inline bool is_valid_dio_path_info(struct mcdrv_dio_path_info
+					  *dio_path_info, unsigned int update)
+{
+	struct mcdrv_dio_path_info curr_dio_path_info;
+	u8 val;
+	bool LP0_start = false, LP1_start = false;
+	bool LP2_start = false, LP3_start = false;
+	bool ret = true;
+
+	val = mc_mb_register_get_value(MCI_LP0_START);
+	if (val & (MCB_LPR0_START | MCB_LPT0_START))
+		LP0_start = true;
+
+	val = mc_mb_register_get_value(MCI_LP1_START);
+	if (val & (MCB_LPR1_START | MCB_LPT1_START))
+		LP1_start = true;
+
+	val = mc_mb_register_get_value(MCI_LP2_START);
+	if (val & (MCB_LPR2_START | MCB_LPT2_START))
+		LP2_start = true;
+
+	val = mc_mb_register_get_value(MCI_LP3_START);
+	if (val & (MCB_LPR3_START | MCB_LPT3_START))
+		LP3_start = true;
+
+	mc_dio_path_info_get(&curr_dio_path_info);
+
+	if (update & MCDRV_MUSICNUM_UPDATE_FLAG) {
+		if (dio_path_info->music_ch > MCDRV_MUSIC_LAST) {
+			ret = false;
+			goto exit;
+		} else if (dio_path_info->music_ch !=
+			   curr_dio_path_info.music_ch) {
+			if (LP0_start) {
+				ret = false;
+				goto exit;
+			}
+		}
+	}
+
+	if (update & MCDRV_PHYS0_UPDATE_FLAG) {
+		if (dio_path_info->phys_port[0] > MCDRV_PHYSPORT_LAST) {
+			ret = false;
+			goto exit;
+		} else if (dio_path_info->phys_port[0] !=
+			   curr_dio_path_info.phys_port[0]) {
+			if (LP0_start) {
+				ret = false;
+				goto exit;
+			}
+		}
+	}
+
+	if (update & MCDRV_PHYS1_UPDATE_FLAG) {
+		if (dio_path_info->phys_port[1] > MCDRV_PHYSPORT_LAST) {
+			ret = false;
+			goto exit;
+		} else if (dio_path_info->phys_port[1] !=
+			   curr_dio_path_info.phys_port[1]) {
+			if (LP1_start) {
+				ret = false;
+				goto exit;
+			}
+		}
+	}
+
+	if (update & MCDRV_PHYS2_UPDATE_FLAG) {
+		if (dio_path_info->phys_port[2] > MCDRV_PHYSPORT_LAST) {
+			ret = false;
+			goto exit;
+		} else if (dio_path_info->phys_port[2] !=
+			   curr_dio_path_info.phys_port[2]) {
+			if (LP2_start) {
+				ret = false;
+				goto exit;
+			}
+		}
+	}
+
+	if (update & MCDRV_PHYS3_UPDATE_FLAG) {
+		if (dio_path_info->phys_port[3] > MCDRV_PHYSPORT_LAST) {
+			ret = false;
+			goto exit;
+		} else if (dio_path_info->phys_port[3] !=
+			   curr_dio_path_info.phys_port[3]) {
+			if (LP3_start) {
+				ret = false;
+				goto exit;
+			}
+		}
+	}
+
+	if (update & MCDRV_DIR0SLOT_UPDATE_FLAG) {
+		if (dio_path_info->music_rslot[0] > 3) {
+			ret = false;
+			goto exit;
+		} else if (dio_path_info->music_rslot[0] !=
+			   curr_dio_path_info.music_rslot[0]) {
+			if (LP0_start) {
+				ret = false;
+				goto exit;
+			}
+		}
+	}
+
+	if (update & MCDRV_DIR1SLOT_UPDATE_FLAG) {
+		if (dio_path_info->music_rslot[1] > 3) {
+			ret = false;
+		} else if (dio_path_info->music_rslot[1] !=
+			   curr_dio_path_info.music_rslot[1]) {
+			if (LP0_start) {
+				ret = false;
+				goto exit;
+			}
+		}
+	}
+
+	if (update & MCDRV_DIR2SLOT_UPDATE_FLAG) {
+		if (dio_path_info->music_rslot[2] > 3) {
+			ret = false;
+		} else if (dio_path_info->music_rslot[2] !=
+			   curr_dio_path_info.music_rslot[2]) {
+			if (LP0_start) {
+				ret = false;
+				goto exit;
+			}
+		}
+	}
+
+	if (update & MCDRV_DIT0SLOT_UPDATE_FLAG) {
+		if (dio_path_info->music_tslot[0] > 3) {
+			ret = false;
+		} else if (dio_path_info->music_tslot[0] !=
+			   curr_dio_path_info.music_tslot[0]) {
+			if (LP0_start) {
+				ret = false;
+				goto exit;
+			}
+		}
+	}
+
+	if (update & MCDRV_DIT1SLOT_UPDATE_FLAG) {
+		if (dio_path_info->music_tslot[1] > 3) {
+			ret = false;
+		} else if (dio_path_info->music_tslot[1] !=
+			   curr_dio_path_info.music_tslot[1]) {
+			if (LP0_start) {
+				ret = false;
+				goto exit;
+			}
+		}
+	}
+
+	if (update & MCDRV_DIT2SLOT_UPDATE_FLAG) {
+		if (dio_path_info->music_tslot[2] > 3) {
+			ret = false;
+		} else if (dio_path_info->music_tslot[2] !=
+			   curr_dio_path_info.music_tslot[2]) {
+			if (LP0_start) {
+				ret = false;
+				goto exit;
+			}
+		}
+	}
+
+exit:
+	return ret;
+}
+
+static inline bool is_valid_swap_info(struct mcdrv_swap_info *info,
+				      unsigned int update)
+{
+	bool ret = true;
+
+	if (update & MCDRV_SWAP_ADIF0_UPDATE_FLAG)
+		if (info->adif0 > MCDRV_SWAP_LAST)
+			ret = false;
+
+	if (update & MCDRV_SWAP_ADIF1_UPDATE_FLAG)
+		if (info->adif1 > MCDRV_SWAP_LAST)
+			ret = false;
+
+	if (update & MCDRV_SWAP_ADIF2_UPDATE_FLAG)
+		if (info->adif2 > MCDRV_SWAP_LAST)
+			ret = false;
+
+	if (update & MCDRV_SWAP_DAC0_UPDATE_FLAG)
+		if (info->dac0 > MCDRV_SWAP_LAST)
+			ret = false;
+
+	if (update & MCDRV_SWAP_DAC1_UPDATE_FLAG)
+		if (info->dac1 > MCDRV_SWAP_LAST)
+			ret = false;
+
+	if (update & MCDRV_SWAP_MUSICIN0_UPDATE_FLAG)
+		if (info->music_in0 > MCDRV_SWSWAP_LAST)
+			ret = false;
+
+	if (update & MCDRV_SWAP_MUSICIN1_UPDATE_FLAG)
+		if (info->music_in1 > MCDRV_SWSWAP_LAST)
+			ret = false;
+
+	if (update & MCDRV_SWAP_MUSICIN2_UPDATE_FLAG)
+		if (info->music_in2 > MCDRV_SWSWAP_LAST)
+			ret = false;
+
+	if (update & MCDRV_SWAP_EXTIN_UPDATE_FLAG)
+		if (info->ext_in > MCDRV_SWSWAP_LAST)
+			ret = false;
+
+	if (update & MCDRV_SWAP_VOICEIN_UPDATE_FLAG)
+		if (info->voice_in > MCDRV_SWSWAP_LAST)
+			ret = false;
+
+	if (update & MCDRV_SWAP_HIFIIN_UPDATE_FLAG)
+		if (info->hifi_in > MCDRV_SWSWAP_LAST)
+			ret = false;
+
+	if (update & MCDRV_SWAP_MUSICOUT0_UPDATE_FLAG)
+		if (info->music_out0 > MCDRV_SWAP_LAST)
+			ret = false;
+
+	if (update & MCDRV_SWAP_MUSICOUT1_UPDATE_FLAG)
+		if (info->music_out1 > MCDRV_SWSWAP_LAST)
+			ret = false;
+
+	if (update & MCDRV_SWAP_MUSICOUT2_UPDATE_FLAG)
+		if (info->music_out2 > MCDRV_SWSWAP_LAST)
+			ret = false;
+
+	if (update & MCDRV_SWAP_EXTOUT_UPDATE_FLAG)
+		if (info->ext_out > MCDRV_SWSWAP_LAST)
+			ret = false;
+
+	if (update & MCDRV_SWAP_VOICEOUT_UPDATE_FLAG)
+		if (info->voice_out > MCDRV_SWSWAP_LAST)
+			ret = false;
+
+	if (update & MCDRV_SWAP_HIFIOUT_UPDATE_FLAG)
+		if (info->hifi_out > MCDRV_SWSWAP_LAST)
+			ret = false;
+
+	return ret;
+}
+
+static inline bool is_valid_aec_info(struct mcdrv_aec_info *info)
+{
+	struct mcdrv_aec_info curr_info;
+	bool bdsp_used = false, cdsp_used = false, fdsp_used = false;
+	bool ret = true;
+
+	mc_aec_info_get(&curr_info);
+
+	if (mc_d1_source_is_used(MCDRV_D1SRC_AE0_ON | MCDRV_D1SRC_AE1_ON |
+				 MCDRV_D1SRC_AE2_ON | MCDRV_D1SRC_AE3_ON)) {
+		bdsp_used = true;
+		if (!curr_info.fdsp_locate)
+			fdsp_used = true;
+	}
+
+	if (mc_source_is_used(MCDRV_DST_VBOXMIXIN, MCDRV_DST_CH0) ||
+	    mc_source_is_used(MCDRV_DST_VBOXMIXIN, MCDRV_DST_CH1) ||
+	    mc_source_is_used(MCDRV_DST_VBOXMIXIN, MCDRV_DST_CH2) ||
+	    mc_source_is_used(MCDRV_DST_VBOXMIXIN, MCDRV_DST_CH3) ||
+	    mc_source_is_used(MCDRV_DST_VBOXHOSTIN, MCDRV_DST_CH0)) {
+		cdsp_used = true;
+		if (curr_info.fdsp_locate)
+			fdsp_used = true;
+	}
+
+	if (bdsp_used || cdsp_used || fdsp_used)
+		if (info->fdsp_locate != 0xFF)
+			if (info->fdsp_locate != curr_info.fdsp_locate) {
+				ret = false;
+				goto exit;
+			}
+
+	if (bdsp_used || fdsp_used)
+		if (info->audio_engine.enable) {
+			if (info->audio_engine.bdsp_ae0_src != 2 &&
+			    info->audio_engine.bdsp_ae0_src !=
+			    curr_info.audio_engine.bdsp_ae0_src) {
+				ret = false;
+				goto exit;
+			}
+
+			if (info->audio_engine.bdsp_ae1_src != 2 &&
+			    info->audio_engine.bdsp_ae1_src !=
+			    curr_info.audio_engine.bdsp_ae1_src) {
+				ret = false;
+				goto exit;
+			}
+			if (info->audio_engine.mixer_in0_src != 2 &&
+			    info->audio_engine.mixer_in0_src !=
+			    curr_info.audio_engine.mixer_in0_src) {
+				ret = false;
+				goto exit;
+			}
+
+			if (info->audio_engine.mixer_in1_src != 2 &&
+			    info->audio_engine.mixer_in1_src !=
+			    curr_info.audio_engine.mixer_in1_src) {
+				ret = false;
+				goto exit;
+			}
+			if (info->audio_engine.mixer_in2_src != 2 &&
+			    info->audio_engine.mixer_in2_src !=
+			    curr_info.audio_engine.mixer_in2_src) {
+				ret = false;
+				goto exit;
+			}
+
+			if (info->audio_engine.mixer_in3_src != 2 &&
+			    info->audio_engine.mixer_in3_src !=
+			    curr_info.audio_engine.mixer_in3_src) {
+				ret = false;
+				goto exit;
+			}
+		}
+
+	if (cdsp_used || fdsp_used)
+		if (info->vbox.enable) {
+			if (info->vbox.fdsp_po_source != 0xFF &&
+			    info->vbox.fdsp_po_source !=
+			    curr_info.vbox.fdsp_po_source) {
+				ret = false;
+				goto exit;
+			}
+
+			if (info->vbox.isrc2_vsource != 0xFF &&
+			    info->vbox.isrc2_vsource !=
+			    curr_info.vbox.isrc2_vsource) {
+				ret = false;
+				goto exit;
+			}
+
+			if (info->vbox.isrc2_ch1_vsource != 0xFF &&
+			    info->vbox.isrc2_ch1_vsource !=
+			    curr_info.vbox.isrc2_ch1_vsource) {
+				ret = false;
+				goto exit;
+			}
+
+			if (info->vbox.isrc3_vsource != 0xFF &&
+			    info->vbox.isrc3_vsource !=
+			    curr_info.vbox.isrc3_vsource) {
+				ret = false;
+				goto exit;
+			}
+
+			if (info->vbox.lpt2_vsource != 0xFF &&
+			    info->vbox.lpt2_vsource !=
+			    curr_info.vbox.lpt2_vsource) {
+				ret = false;
+				goto exit;
+			}
+		}
+
+	if (cdsp_used)
+		if (info->vbox.enable) {
+			if (info->vbox.src3_ctrl != 0xFF &&
+			    info->vbox.src3_ctrl != curr_info.vbox.src3_ctrl) {
+				ret = false;
+				goto exit;
+			}
+
+			if (info->vbox.src2_fs != 0xFF &&
+			    info->vbox.src2_fs != curr_info.vbox.src2_fs) {
+				ret = false;
+				goto exit;
+			}
+
+			if (info->vbox.src2_thru != 0xFF &&
+			    info->vbox.src2_thru != curr_info.vbox.src2_thru) {
+				ret = false;
+				goto exit;
+			}
+
+			if (info->vbox.src3_fs != 0xFF &&
+			    info->vbox.src3_fs != curr_info.vbox.src3_fs) {
+				ret = false;
+				goto exit;
+			}
+
+			if (info->vbox.src3_thru != 0xFF &&
+			    info->vbox.src3_thru != curr_info.vbox.src3_thru) {
+				ret = false;
+				goto exit;
+			}
+		}
+
+exit:
+	return ret;
+}
+
+static bool is_valid_hsdet_info(struct mcdrv_hsdet_info *info,
+				unsigned int update)
+{
+	struct mcdrv_hsdet_info hsdet_info;
+
+	mc_hsdet_info_get(&hsdet_info);
+
+	if (update & MCDRV_ENPLUGDET_UPDATE_FLAG)
+		if (info->en_plug_det_db > MCDRV_PLUGDETDB_LAST)
+			return false;
+
+	if (update & MCDRV_ENDLYKEYOFF_UPDATE_FLAG)
+		if (info->en_dly_key_off > MCDRV_KEYEN_LAST)
+			return false;
+
+	if (update & MCDRV_ENDLYKEYON_UPDATE_FLAG)
+		if (info->en_dly_key_on > MCDRV_KEYEN_LAST)
+			return false;
+
+	if (update & MCDRV_ENKEYOFF_UPDATE_FLAG)
+		if (info->en_key_off > MCDRV_KEYEN_LAST)
+			return false;
+
+	if (update & MCDRV_ENKEYON_UPDATE_FLAG)
+		if (info->en_key_on > MCDRV_KEYEN_LAST)
+			return false;
+
+	if (update & MCDRV_HSDETDBNC_UPDATE_FLAG)
+		if (info->hs_det_dbnc > MCDRV_DETDBNC_LAST)
+			return false;
+
+	if (update & MCDRV_KEYOFFMTIM_UPDATE_FLAG)
+		hsdet_info.key_off_mtim = info->key_off_mtim;
+
+	if (update & MCDRV_KEYONMTIM_UPDATE_FLAG)
+		hsdet_info.key_on_mtim = info->key_on_mtim;
+
+	if (update & MCDRV_KEY0OFFDLYTIM_UPDATE_FLAG) {
+		if (info->key0_off_dly_tim > MC_DRV_KEYOFFDLYTIM_MAX)
+			return false;
+		else if (hsdet_info.key_off_mtim == MCDRV_KEYOFF_MTIM_63 &&
+			 info->key0_off_dly_tim == 1)
+			return false;
+	}
+
+	if (update & MCDRV_KEY1OFFDLYTIM_UPDATE_FLAG) {
+		if (info->key1_off_dly_tim > MC_DRV_KEYOFFDLYTIM_MAX)
+			return false;
+		else if (hsdet_info.key_off_mtim == MCDRV_KEYOFF_MTIM_63 &&
+			 info->key1_off_dly_tim == 1)
+			return false;
+	}
+
+	if (update & MCDRV_KEY2OFFDLYTIM_UPDATE_FLAG) {
+		if (info->key2_off_dly_tim > MC_DRV_KEYOFFDLYTIM_MAX)
+			return false;
+		else if (hsdet_info.key_off_mtim == MCDRV_KEYOFF_MTIM_63 &&
+			 info->key2_off_dly_tim == 1)
+			return false;
+	}
+
+	if (update & MCDRV_KEY0ONDLYTIM_UPDATE_FLAG) {
+		if (info->key0_on_dly_tim > MC_DRV_KEYONDLYTIM_MAX)
+			return false;
+		else if (hsdet_info.key_on_mtim == MCDRV_KEYON_MTIM_250 &&
+			 (info->key0_on_dly_tim == 1 ||
+			  info->key0_on_dly_tim == 2 ||
+			  info->key0_on_dly_tim == 3))
+			return false;
+	}
+
+	if (update & MCDRV_KEY1ONDLYTIM_UPDATE_FLAG) {
+		if (info->key1_on_dly_tim > MC_DRV_KEYONDLYTIM_MAX)
+			return false;
+		else if (hsdet_info.key_on_mtim == MCDRV_KEYON_MTIM_250 &&
+			 (info->key1_on_dly_tim == 1 ||
+			  info->key1_on_dly_tim == 2 ||
+			  info->key1_on_dly_tim == 3))
+			return false;
+	}
+
+	if (update & MCDRV_KEY2ONDLYTIM_UPDATE_FLAG) {
+		if (info->key2_on_dly_tim > MC_DRV_KEYONDLYTIM_MAX)
+			return false;
+		else if (hsdet_info.key_on_mtim == MCDRV_KEYON_MTIM_250 &&
+			 (info->key2_on_dly_tim == 1 ||
+			  info->key2_on_dly_tim == 2 ||
+			  info->key2_on_dly_tim == 3))
+			return false;
+	}
+
+	if (update & MCDRV_KEY0ONDLYTIM2_UPDATE_FLAG) {
+		if (info->key0_on_dly_tim2 > MC_DRV_KEYONDLYTIM2_MAX)
+			return false;
+		else if (hsdet_info.key_on_mtim == MCDRV_KEYON_MTIM_250 &&
+			 (info->key0_on_dly_tim2 == 1 ||
+			  info->key0_on_dly_tim2 == 2 ||
+			  info->key0_on_dly_tim2 == 3))
+			return false;
+	}
+
+	if (update & MCDRV_KEY1ONDLYTIM2_UPDATE_FLAG) {
+		if (info->key1_on_dly_tim2 > MC_DRV_KEYONDLYTIM2_MAX)
+			return false;
+		else if (hsdet_info.key_on_mtim == MCDRV_KEYON_MTIM_250 &&
+			 (info->key1_on_dly_tim2 == 1 ||
+			  info->key1_on_dly_tim2 == 2 ||
+			  info->key1_on_dly_tim2 == 3))
+			return false;
+	}
+
+	if (update & MCDRV_KEY2ONDLYTIM2_UPDATE_FLAG) {
+		if (info->key2_on_dly_tim2 > MC_DRV_KEYONDLYTIM2_MAX)
+			return false;
+		else if (hsdet_info.key_on_mtim == MCDRV_KEYON_MTIM_250 &&
+			 (info->key2_on_dly_tim2 == 1 ||
+			  info->key2_on_dly_tim2 == 2 ||
+			  info->key2_on_dly_tim2 == 3))
+			return false;
+	}
+
+	if (update & MCDRV_IRQTYPE_UPDATE_FLAG) {
+		if (info->irq_type == MCDRV_IRQTYPE_EX) {
+			if (info->plug_det_db_irq_type > MCDRV_IRQTYPE_REF)
+				return false;
+			if (info->plug_undet_db_irq_type > MCDRV_IRQTYPE_REF)
+				return false;
+			if (info->mic_det_irq_type > MCDRV_IRQTYPE_REF)
+				return false;
+			if (info->plug_det_irq_type > MCDRV_IRQTYPE_REF)
+				return false;
+			if (info->key0_on_irq_type > MCDRV_IRQTYPE_REF)
+				return false;
+			if (info->key1_on_irq_type > MCDRV_IRQTYPE_REF)
+				return false;
+			if (info->key2_on_irq_type > MCDRV_IRQTYPE_REF)
+				return false;
+			if (info->key0_off_irq_type > MCDRV_IRQTYPE_REF)
+				return false;
+			if (info->key1_off_irq_type > MCDRV_IRQTYPE_REF)
+				return false;
+			if (info->key2_off_irq_type > MCDRV_IRQTYPE_REF)
+				return false;
+		} else if (info->irq_type > MCDRV_IRQTYPE_LAST)
+			return false;
+	}
+
+	if (update & MCDRV_DETINV_UPDATE_FLAG)
+		if (info->det_in_inv > MCDRV_DET_IN_LAST)
+			return false;
+
+	if (update & MCDRV_HSDETMODE_UPDATE_FLAG)
+		if (info->hs_det_mode != MCDRV_HSDET_MODE_DETIN_A &&
+		    info->hs_det_mode != MCDRV_HSDET_MODE_DETIN_B)
+			return false;
+
+	if (update & MCDRV_SPERIOD_UPDATE_FLAG)
+		if (info->speriod > MCDRV_SPERIOD_LAST)
+			return false;
+
+	if (update & MCDRV_LPERIOD_UPDATE_FLAG)
+		if (info->lperiod > MCDRV_LPERIOD_LAST)
+			return false;
+
+	if (update & MCDRV_DBNCNUMPLUG_UPDATE_FLAG)
+		if (info->dbnc_num_plug > MCDRV_DBNC_NUM_LAST)
+			return false;
+
+	if (update & MCDRV_DBNCNUMMIC_UPDATE_FLAG)
+		if (info->dbnc_num_mic > MCDRV_DBNC_NUM_LAST)
+			return false;
+
+	if (update & MCDRV_DBNCNUMKEY_UPDATE_FLAG)
+		if (info->dbnc_num_key > MCDRV_DBNC_NUM_LAST)
+			return false;
+
+	if (update & MCDRV_SGNL_UPDATE_FLAG) {
+		if (info->sgnl_period > MCDRV_SGNLPERIOD_LAST)
+			return false;
+
+		if (info->sgnl_num != MCDRV_SGNLNUM_NONE
+		    && info->sgnl_num > MCDRV_SGNLNUM_LAST)
+			return false;
+
+		if (info->sgnl_peak > MCDRV_SGNLPEAK_LAST)
+			return false;
+	}
+
+	return true;
+}
+
+static bool check_dio_common(struct mcdrv_dio_info *dio_info, u8 port)
+{
+	struct mcdrv_dio_common *dio_common;
+	bool ret = true;
+
+	dio_common = &dio_info->port[port].dio_common;
+
+	if (port == 3) {
+		if (dio_common->fs != MCDRV_FS_48000 &&
+		    dio_common->fs != MCDRV_FS_192000 &&
+		    dio_common->fs != MCDRV_FS_96000) {
+			ret = false;
+			goto exit;
+		}
+
+		if (dio_common->bck_fs != MCDRV_BCKFS_64 &&
+		    dio_common->bck_fs != MCDRV_BCKFS_48 &&
+		    dio_common->bck_fs != MCDRV_BCKFS_32)
+			ret = false;
+		goto exit;
+	}
+
+	if (dio_common->fs > MCDRV_FS_LAST ||
+	    dio_common->fs == MCDRV_FS_NONE1 ||
+	    dio_common->fs == MCDRV_FS_NONE2 ||
+	    dio_common->fs == MCDRV_FS_NONE3)
+		ret = false;
+	else if (dio_common->bck_fs > MCDRV_BCKFS_LAST ||
+		 dio_common->bck_fs == MCDRV_BCKFS_NONE1 ||
+		 dio_common->bck_fs == MCDRV_BCKFS_NONE2 ||
+		 dio_common->bck_fs == MCDRV_BCKFS_NONE3 ||
+		 dio_common->bck_fs == MCDRV_BCKFS_NONE4)
+		ret = false;
+	else if (dio_common->interface == MCDRV_DIO_PCM &&
+		 dio_common->pcm_high_period > 31)
+		ret = false;
+
+	if (dio_common->interface == MCDRV_DIO_PCM) {
+		if (dio_common->fs != MCDRV_FS_8000 &&
+		    dio_common->fs != MCDRV_FS_16000)
+			ret = false;
+
+		if (dio_common->bck_fs == MCDRV_BCKFS_512 &&
+		    dio_common->fs != MCDRV_FS_8000)
+			ret = false;
+
+		if (dio_common->bck_fs == MCDRV_BCKFS_256 &&
+		    (dio_common->fs != MCDRV_FS_8000 &&
+		     dio_common->fs != MCDRV_FS_16000))
+			ret = false;
+
+		if (dio_common->master_slave == MCDRV_DIO_MASTER &&
+		    dio_common->bck_fs == MCDRV_BCKFS_SLAVE)
+			ret = false;
+	} else {
+		if (port == 0 || port == 1) {
+			if (dio_common->fs == MCDRV_FS_192000 ||
+			    dio_common->fs == MCDRV_FS_96000)
+				ret = false;
+		}
+
+		if (dio_common->bck_fs != MCDRV_BCKFS_64 &&
+		    dio_common->bck_fs != MCDRV_BCKFS_48 &&
+		    dio_common->bck_fs != MCDRV_BCKFS_32)
+			ret = false;
+	}
+
+exit:
+	return ret;
+}
+
+static bool check_da_format(struct mcdrv_da_format *da_format)
+{
+	bool ret = true;
+
+	if (da_format->bit_sel > MCDRV_BITSEL_LAST)
+		ret = false;
+	else if (da_format->mode > MCDRV_DAMODE_LAST)
+		ret = false;
+
+	return ret;
+}
+
+static bool check_pcm_format(struct mcdrv_pcm_format *pcm_format)
+{
+	bool ret = true;
+
+	if (pcm_format->law > MCDRV_PCM_LAST)
+		ret = false;
+	else if (pcm_format->bit_sel > MCDRV_PCM_BITSEL_LAST)
+		ret = false;
+	else if ((pcm_format->law == MCDRV_PCM_ALAW ||
+		  pcm_format->law == MCDRV_PCM_MULAW) &&
+		 pcm_format->bit_sel != MCDRV_PCM_BITSEL_8)
+		ret = false;
+
+	return ret;
+}
+
+static bool check_dio_dir(struct mcdrv_dio_info *dio_info,
+			  u8 port, u8 interface)
+{
+	bool ret = true;
+
+	if (interface == MCDRV_DIO_PCM)
+		ret = check_pcm_format(&dio_info->port[port].dir.pcm_format);
+	else {
+		ret = check_da_format(&dio_info->port[port].dir.da_format);
+		if (dio_info->port[port].dir.da_format.bit_sel ==
+		    MCDRV_BITSEL_32)
+			ret = false;
+	}
+
+	return ret;
+}
+
+static bool check_dio_dit(struct mcdrv_dio_info *dio_info,
+			  u8 port, u8 interface)
+{
+	bool ret = true;
+
+	if (interface == MCDRV_DIO_PCM)
+		ret = check_pcm_format(&dio_info->port[port].dit.pcm_format);
+	else {
+		ret = check_da_format(&dio_info->port[port].dit.da_format);
+		if (dio_info->port[port].dit.da_format.bit_sel ==
+		    MCDRV_BITSEL_32 && port != 2)
+			ret = false;
+	}
+
+	return ret;
+}
+
+static inline bool is_valid_dio_info(struct mcdrv_dio_info *dio_info,
+				     unsigned int update)
+{
+	struct mcdrv_dio_info curr_dio_info;
+	u8 val;
+	bool LPR0_start = 0, LPT0_start = 0;
+	bool LPR1_start = 0, LPT1_start = 0;
+	bool LPR2_start = 0, LPT2_start = 0;
+	bool LPR3_start = 0, LPT3_start = 0;
+	bool ret = true;
+
+	mc_dio_info_get(&curr_dio_info);
+
+	val = mc_mb_register_get_value(MCI_LP0_START);
+	if (val & MCB_LPR0_START)
+		LPR0_start = true;
+	if (val & MCB_LPT0_START)
+		LPT0_start = true;
+
+	val = mc_mb_register_get_value(MCI_LP1_START);
+	if (val & MCB_LPR1_START)
+		LPR1_start = true;
+	if (val & MCB_LPT1_START)
+		LPT1_start = true;
+
+	val = mc_mb_register_get_value(MCI_LP2_START);
+	if (val & MCB_LPR2_START)
+		LPR2_start = true;
+	if (val & MCB_LPT2_START)
+		LPT2_start = true;
+
+	val = mc_mb_register_get_value(MCI_LP3_START);
+	if (val & MCB_LPR3_START)
+		LPR3_start = true;
+	if (val & MCB_LPT3_START)
+		LPT3_start = true;
+
+	if ((update & MCDRV_MUSIC_COM_UPDATE_FLAG) ||
+	    (update & MCDRV_MUSIC_DIR_UPDATE_FLAG)) {
+		if (LPR0_start)
+			ret = false;
+	}
+
+	if ((update & MCDRV_MUSIC_COM_UPDATE_FLAG) ||
+	    (update & MCDRV_MUSIC_DIT_UPDATE_FLAG)) {
+		if (LPT0_start)
+			ret = false;
+	}
+
+	if ((update & MCDRV_EXT_COM_UPDATE_FLAG) ||
+	    (update & MCDRV_EXT_DIR_UPDATE_FLAG)) {
+		if (LPR1_start)
+			ret = false;
+	}
+
+	if ((update & MCDRV_EXT_COM_UPDATE_FLAG) ||
+	    (update & MCDRV_EXT_DIT_UPDATE_FLAG)) {
+		if (LPT1_start)
+			ret = false;
+	}
+
+	if ((update & MCDRV_VOICE_COM_UPDATE_FLAG) ||
+	    (update & MCDRV_VOICE_DIR_UPDATE_FLAG)) {
+		if (LPR2_start)
+			ret = false;
+	}
+
+	if ((update & MCDRV_VOICE_COM_UPDATE_FLAG) ||
+	    (update & MCDRV_VOICE_DIT_UPDATE_FLAG)) {
+		if (LPT2_start)
+			ret = false;
+	}
+
+	if ((update & MCDRV_HIFI_COM_UPDATE_FLAG) ||
+	    (update & MCDRV_HIFI_DIR_UPDATE_FLAG)) {
+		if (LPR3_start)
+			ret = false;
+	}
+
+	if ((update & MCDRV_HIFI_COM_UPDATE_FLAG) ||
+	    (update & MCDRV_HIFI_DIT_UPDATE_FLAG)) {
+		if (LPT3_start)
+			ret = false;
+	}
+
+	if (ret && (update & MCDRV_MUSIC_COM_UPDATE_FLAG)) {
+		ret = check_dio_common(dio_info, 0);
+		if (ret)
+			curr_dio_info.port[0].dio_common.interface
+			    = dio_info->port[0].dio_common.interface;
+	}
+
+	if (ret && (update & MCDRV_EXT_COM_UPDATE_FLAG)) {
+		ret = check_dio_common(dio_info, 1);
+		if (ret)
+			curr_dio_info.port[1].dio_common.interface
+			    = dio_info->port[1].dio_common.interface;
+	}
+
+	if (ret && (update & MCDRV_VOICE_COM_UPDATE_FLAG)) {
+		ret = check_dio_common(dio_info, 2);
+		if (ret)
+			curr_dio_info.port[2].dio_common.interface
+			    = dio_info->port[2].dio_common.interface;
+	}
+
+	if (ret && (update & MCDRV_HIFI_COM_UPDATE_FLAG)) {
+		ret = check_dio_common(dio_info, 3);
+		if (ret)
+			curr_dio_info.port[3].dio_common.interface
+			    = dio_info->port[3].dio_common.interface;
+	}
+
+	if (ret && (update & MCDRV_MUSIC_DIR_UPDATE_FLAG)) {
+		ret = check_dio_dir(dio_info, 0,
+				    curr_dio_info.port[0].dio_common.interface);
+	}
+
+	if (ret && (update & MCDRV_EXT_DIR_UPDATE_FLAG)) {
+		ret = check_dio_dir(dio_info, 1,
+				    curr_dio_info.port[1].dio_common.interface);
+	}
+
+	if (ret && (update & MCDRV_VOICE_DIR_UPDATE_FLAG)) {
+		ret = check_dio_dir(dio_info, 2,
+				    curr_dio_info.port[2].dio_common.interface);
+	}
+
+	if (ret && (update & MCDRV_MUSIC_DIT_UPDATE_FLAG)) {
+		ret = check_dio_dit(dio_info, 0,
+				    curr_dio_info.port[0].dio_common.interface);
+	}
+
+	if (ret && (update & MCDRV_EXT_DIT_UPDATE_FLAG))
+		ret = check_dio_dit(dio_info, 1,
+				    curr_dio_info.port[1].dio_common.interface);
+
+	if (ret && (update & MCDRV_VOICE_DIT_UPDATE_FLAG))
+		ret = check_dio_dit(dio_info, 2,
+				    curr_dio_info.port[2].dio_common.interface);
+
+	return ret;
+}
+
+static inline int set_vol(u32 update, enum mcdrv_volume_mode mode, u32 *status)
+{
+	mc_packet_add_volume(update, mode, status);
+
+	return mc_packet_execute();
+}
+
+static inline void get_mute(u8 *dir_mute, u8 *adc_mute,
+			    u8 *dit_mute, u8 *dac_mute)
+{
+	u8 vol;
+
+	*dir_mute = 0;
+	*adc_mute = 0;
+	*dit_mute = 0;
+	*dac_mute = 0;
+
+	if (!mc_d1_source_is_used(MCDRV_D1SRC_MUSICIN_ON)) {
+		vol = mc_ma_register_get_value(MCI_DIFI0_VOL0);
+		if (vol & ~MCB_DIFI0_VSEP)
+			*dir_mute |= MCB_DIFI0_VFLAG0;
+
+		vol = mc_ma_register_get_value(MCI_DIFI0_VOL1);
+		if (vol)
+			*dir_mute |= MCB_DIFI0_VFLAG1;
+	}
+
+	if (!mc_d1_source_is_used(MCDRV_D1SRC_EXTIN_ON)) {
+		vol = mc_ma_register_get_value(MCI_DIFI1_VOL0);
+		if (vol & ~MCB_DIFI1_VSEP)
+			*dir_mute |= MCB_DIFI1_VFLAG0;
+
+		vol = mc_ma_register_get_value(MCI_DIFI1_VOL1);
+		if (vol)
+			*dir_mute |= MCB_DIFI1_VFLAG1;
+	}
+
+	if (!mc_d1_source_is_used(MCDRV_D1SRC_VBOXOUT_ON)) {
+		vol = mc_ma_register_get_value(MCI_DIFI2_VOL0);
+		if (vol & ~MCB_DIFI2_VSEP)
+			*dir_mute |= MCB_DIFI2_VFLAG0;
+
+		vol = mc_ma_register_get_value(MCI_DIFI2_VOL1);
+		if (vol)
+			*dir_mute |= MCB_DIFI2_VFLAG1;
+	}
+
+	if (!mc_d1_source_is_used(MCDRV_D1SRC_VBOXREFOUT_ON)) {
+		vol = mc_ma_register_get_value(MCI_DIFI3_VOL0);
+		if (vol & ~MCB_DIFI3_VSEP)
+			*dir_mute |= MCB_DIFI3_VFLAG0;
+
+		vol = mc_ma_register_get_value(MCI_DIFI3_VOL1);
+		if (vol)
+			*dir_mute |= MCB_DIFI3_VFLAG1;
+	}
+
+	if (!mc_source_is_used(MCDRV_DST_DAC0, MCDRV_DST_CH0)) {
+		vol = mc_ma_register_get_value(MCI_DAO0_VOL0);
+		if (vol & ~MCB_DAO0_VSEP)
+			*dac_mute |= MCB_DAO0_VFLAG0;
+	}
+
+	if (!mc_source_is_used(MCDRV_DST_DAC0, MCDRV_DST_CH1)) {
+		vol = mc_ma_register_get_value(MCI_DAO0_VOL1);
+		if (vol)
+			*dac_mute |= MCB_DAO0_VFLAG1;
+	}
+
+	if (!mc_source_is_used(MCDRV_DST_DAC1, MCDRV_DST_CH0)) {
+		vol = mc_ma_register_get_value(MCI_DAO1_VOL0);
+		if (vol & ~MCB_DAO1_VSEP)
+			*dac_mute |= MCB_DAO1_VFLAG0;
+	}
+
+	if (!mc_source_is_used(MCDRV_DST_DAC1, MCDRV_DST_CH1)) {
+		vol = mc_ma_register_get_value(MCI_DAO1_VOL1);
+		if (vol)
+			*dac_mute |= MCB_DAO1_VFLAG1;
+	}
+
+	if (!mc_source_is_used(MCDRV_DST_MUSICOUT, MCDRV_DST_CH0)) {
+		vol = mc_ma_register_get_value(MCI_DIFO0_VOL0);
+		if (vol & ~MCB_DIFO0_VSEP)
+			*dit_mute |= MCB_DIFO0_VFLAG0;
+	}
+
+	if (!mc_source_is_used(MCDRV_DST_MUSICOUT, MCDRV_DST_CH1)) {
+		vol = mc_ma_register_get_value(MCI_DIFO0_VOL1);
+		if (vol)
+			*dit_mute |= MCB_DIFO0_VFLAG1;
+
+	}
+
+	if (!mc_source_is_used(MCDRV_DST_EXTOUT, MCDRV_DST_CH0)) {
+		vol = mc_ma_register_get_value(MCI_DIFO1_VOL0);
+		if (vol & ~MCB_DIFO1_VSEP)
+			*dit_mute |= MCB_DIFO1_VFLAG0;
+	}
+
+	if (!mc_source_is_used(MCDRV_DST_EXTOUT, MCDRV_DST_CH1)) {
+		vol = mc_ma_register_get_value(MCI_DIFO1_VOL1);
+		if (vol)
+			*dit_mute |= MCB_DIFO1_VFLAG1;
+	}
+
+	if (!mc_source_is_used(MCDRV_DST_VBOXMIXIN, MCDRV_DST_CH0)) {
+		vol = mc_ma_register_get_value(MCI_DIFO2_VOL0);
+		if (vol & ~MCB_DIFO2_VSEP)
+			*dit_mute |= MCB_DIFO2_VFLAG0;
+	}
+
+	if (!mc_source_is_used(MCDRV_DST_VBOXMIXIN, MCDRV_DST_CH1)) {
+		vol = mc_ma_register_get_value(MCI_DIFO2_VOL1);
+		if (vol)
+			*dit_mute |= MCB_DIFO2_VFLAG1;
+	}
+
+	if (!mc_source_is_used(MCDRV_DST_VBOXMIXIN, MCDRV_DST_CH2)) {
+		vol = mc_ma_register_get_value(MCI_DIFO3_VOL0);
+		if (vol & ~MCB_DIFO2_VSEP)
+			*dit_mute |= MCB_DIFO3_VFLAG0;
+	}
+
+	if (!mc_source_is_used(MCDRV_DST_VBOXMIXIN, MCDRV_DST_CH3)) {
+		vol = mc_ma_register_get_value(MCI_DIFO3_VOL1);
+		if (vol)
+			*dit_mute |= MCB_DIFO3_VFLAG1;
+	}
+
+	if (!mc_d1_source_is_used(MCDRV_D1SRC_ADIF0_ON)) {
+		vol = mc_ma_register_get_value(MCI_ADI0_VOL0);
+		if (vol & ~MCB_ADI0_VSEP)
+			*adc_mute |= MCB_ADI0_VFLAG0;
+		vol = mc_ma_register_get_value(MCI_ADI0_VOL1);
+		if (vol)
+			*adc_mute |= MCB_ADI0_VFLAG1;
+	}
+
+	if (!mc_d1_source_is_used(MCDRV_D1SRC_ADIF1_ON)) {
+		vol = mc_ma_register_get_value(MCI_ADI1_VOL1);
+		if (vol & ~MCB_ADI1_VSEP)
+			*adc_mute |= MCB_ADI1_VFLAG0;
+		vol = mc_ma_register_get_value(MCI_ADI1_VOL1);
+		if (vol)
+			*adc_mute |= MCB_ADI1_VFLAG1;
+	}
+
+	if (!mc_d1_source_is_used(MCDRV_D1SRC_ADIF2_ON)) {
+		vol = mc_ma_register_get_value(MCI_ADI2_VOL1);
+		if (vol & ~MCB_ADI2_VSEP)
+			*adc_mute |= MCB_ADI2_VFLAG0;
+
+		vol = mc_ma_register_get_value(MCI_ADI2_VOL1);
+		if (vol)
+			*adc_mute |= MCB_ADI2_VFLAG1;
+	}
+}
+
+static int save_power(void)
+{
+	struct mcdrv_power_info power;
+	struct mcdrv_power_update update;
+	int ret;
+
+	/*      unused path power down  */
+	mc_power_info_get(&power);
+
+	update.digital = MCDRV_POWUPDATE_D_ALL;
+	update.analog[0] = MCDRV_POWUPDATE_AP;
+	update.analog[1] = MCDRV_POWUPDATE_AP_OUT0;
+	update.analog[2] = MCDRV_POWUPDATE_AP_OUT1;
+	update.analog[3] = MCDRV_POWUPDATE_AP_MC;
+	update.analog[4] = MCDRV_POWUPDATE_AP_IN;
+
+	ret = mc_packet_add_powerdown(&power, &update);
+	if (!ret)
+		ret = mc_packet_execute();
+
+	return ret;
+}
+
+static inline bool is_valid_clock(u8 clock)
+{
+	if (clock != MCDRV_CLKSW_CLKA && clock != MCDRV_CLKSW_CLKB)
+		return false;
+
+	return true;
+}
+
+static inline int get_clock(u8 *clock)
+{
+
+	mc_clock_get(clock);
+
+	return 0;
+}
+
+static inline int set_clock(u8 *clock)
+{
+	u8 old_clock;
+
+	if (!is_valid_clock(*clock))
+		return -EINVAL;
+
+	mc_clock_get(&old_clock);
+	if (*clock == old_clock)
+		return 0;
+
+	return mc_clock_set(*clock);
+}
+
+static inline int get_path(struct mcdrv_path_info *path_info)
+{
+	if (!path_info)
+		return -EINVAL;
+
+	mc_path_info_get_virtual(path_info);
+
+	return 0;
+}
+
+static int set_path(struct mcdrv_path_info *path_info)
+{
+	struct mcdrv_power_info power;
+	struct mcdrv_power_update update;
+	u32 status;
+	u8 val, dir_mute, adc_mute, dit_mute, dac_mute, hp_vol_l, hp_vol_r;
+	u8 dsp_started = mc_dsp_get_running();
+	int ret;
+
+	if (!path_info)
+		return -EINVAL;
+
+	mask_irregular_path_info(path_info);
+
+	ret = mc_path_info_set(path_info);
+	if (ret < 0)
+		return ret;
+
+	hp_vol_l = mc_ana_register_get_value(MCI_HPVOL_L);
+	hp_vol_l &= ~MCB_ALAT_HP;
+	hp_vol_r = mc_ana_register_get_value(MCI_HPVOL_R);
+
+	/* unused analog out volume mute */
+	ret = set_vol(MCDRV_VOLUPDATE_ANA_OUT, MCDRV_VOLUME_MUTE, &status);
+	if (ret < 0)
+		return ret;
+
+	if (status)
+		mc_packet_add_wait_event(MCDRV_EVT_SVOL_DONE | status);
+
+	get_mute(&dir_mute, &adc_mute, &dit_mute, &dac_mute);
+
+	/* unused volume mute */
+	ret = set_vol(MCDRV_VOLUPDATE_DIG, MCDRV_VOLUME_MUTE, NULL);
+	if (ret < 0)
+		return ret;
+
+	/* set volume */
+	ret = set_vol(MCDRV_VOLUPDATE_ANA_IN, MCDRV_VOLUME_SET, NULL);
+	if (ret < 0)
+		return ret;
+
+	if (dir_mute)
+		mc_packet_add_wait_event(MCDRV_EVT_DIRMUTE | dir_mute);
+
+	if (adc_mute)
+		mc_packet_add_wait_event(MCDRV_EVT_ADCMUTE | adc_mute);
+
+	if (dit_mute)
+		mc_packet_add_wait_event(MCDRV_EVT_DITMUTE | dit_mute);
+
+	if (dac_mute)
+		mc_packet_add_wait_event(MCDRV_EVT_DACMUTE | dac_mute);
+
+	mc_packet_add_fdsp_stop(dsp_started);
+	ret = mc_packet_execute();
+	if (ret < 0)
+		return ret;
+
+	/* stop unused path */
+	mc_packet_add_stop();
+	ret = mc_packet_execute();
+	if (ret < 0)
+		return ret;
+
+	mc_power_info_get(&power);
+
+	/* unused analog out path power down */
+	update.digital = 0;
+	update.analog[0] = 0;
+	update.analog[1] = MCDRV_POWUPDATE_AP_OUT0;
+	update.analog[2] = MCDRV_POWUPDATE_AP_OUT1;
+	update.analog[3] = 0;
+	update.analog[4] = 0;
+	ret = mc_packet_add_powerdown(&power, &update);
+	if (ret < 0)
+		return ret;
+
+	ret = mc_packet_execute();
+	if (ret < 0)
+		return ret;
+
+	/* used path power up */
+	update.digital = MCDRV_POWUPDATE_D_ALL;
+	update.analog[0] = MCDRV_POWUPDATE_AP;
+	update.analog[1] = MCDRV_POWUPDATE_AP_OUT0;
+	update.analog[2] = MCDRV_POWUPDATE_AP_OUT1;
+	update.analog[3] = MCDRV_POWUPDATE_AP_MC;
+	update.analog[4] = MCDRV_POWUPDATE_AP_IN;
+	ret = mc_packet_add_powerup(&power, &update);
+	if (ret < 0)
+		return ret;
+
+	ret = mc_packet_execute();
+	if (ret < 0)
+		return ret;
+
+	/* set mixer */
+	mc_packet_add_path_set();
+	ret = mc_packet_execute();
+	if (ret < 0)
+		return ret;
+
+	/* DSP start */
+	mc_packet_add_dsp_start_and_stop(dsp_started);
+	ret = mc_packet_execute();
+	if (ret < 0)
+		return ret;
+
+	if ((hp_vol_l || hp_vol_r)
+	    && (!hp_vol_l || (status & (MCB_HPL_BUSY << 8)))
+	    && (!hp_vol_r || (status & (MCB_HPR_BUSY << 8)))
+	    && (power.analog[3] & MCB_MB4)) {
+		val = mc_ana_register_get_value(MCI_AP_MIC);
+		if (!(val & MCB_MB4))
+			mc_packet_add_wait(MCDRV_MB4_WAIT_TIME);
+	}
+
+	/* unused path power down */
+	update.digital = MCDRV_POWUPDATE_D_ALL;
+	update.analog[0] = MCDRV_POWUPDATE_AP;
+	update.analog[1] = MCDRV_POWUPDATE_AP_OUT0;
+	update.analog[2] = MCDRV_POWUPDATE_AP_OUT1;
+	update.analog[3] = MCDRV_POWUPDATE_AP_MC;
+	update.analog[4] = MCDRV_POWUPDATE_AP_IN;
+	ret = mc_packet_add_powerdown(&power, &update);
+	if (ret < 0)
+		return ret;
+
+	ret = mc_packet_execute();
+	if (ret < 0)
+		return ret;
+
+	mc_packet_add_start();
+	ret = mc_packet_execute();
+	if (ret < 0)
+		return ret;
+
+	/*      set volume      */
+	ret = set_vol(MCDRV_VOLUPDATE_DIG, MCDRV_VOLUME_SET, NULL);
+	if (ret < 0)
+		return ret;
+
+	return set_vol(MCDRV_VOLUPDATE_ANA_OUT, MCDRV_VOLUME_SET, &status);
+}
+
+static inline int get_volume(struct mcdrv_vol_info *vol_info)
+{
+	if (!vol_info)
+		return -EINVAL;
+
+	mc_vol_info_get(vol_info);
+
+	return 0;
+}
+
+static inline int set_volume(struct mcdrv_vol_info *vol_info)
+{
+	struct mcdrv_path_info path_info;
+
+	if (!vol_info)
+		return -EINVAL;
+
+	mc_vol_info_set(vol_info);
+
+	mc_path_info_get_virtual(&path_info);
+
+	return set_path(&path_info);
+}
+
+static inline int get_digitalio(struct mcdrv_dio_info *dio_info)
+{
+	if (!dio_info)
+		return -EINVAL;
+
+	mc_dio_info_get(dio_info);
+
+	return 0;
+}
+
+static inline int set_digitalio(struct mcdrv_dio_info *dio_info,
+				unsigned int update)
+{
+	if (!dio_info)
+		return -EINVAL;
+
+	if (!is_valid_dio_info(dio_info, update))
+		return -EINVAL;
+
+	mc_dio_info_set(dio_info, update);
+
+	mc_packet_add_digital_io(update);
+
+	return mc_packet_execute();
+}
+
+static inline int get_digitalio_path(struct mcdrv_dio_path_info *dio_path_info)
+{
+	if (!dio_path_info)
+		return -EINVAL;
+
+	mc_dio_path_info_get(dio_path_info);
+
+	return 0;
+}
+
+static inline int set_digitalio_path(struct mcdrv_dio_path_info *dio_path_info,
+				     unsigned int update)
+{
+	if (!dio_path_info)
+		return -EINVAL;
+
+	if (!is_valid_dio_path_info(dio_path_info, update))
+		return -EINVAL;
+
+	mc_dio_path_info_set(dio_path_info, update);
+
+	mc_packet_add_digital_io_path();
+
+	return mc_packet_execute();
+}
+
+static inline int get_swap(struct mcdrv_swap_info *info)
+{
+	if (!info)
+		return -EINVAL;
+
+	mc_swap_info_get(info);
+
+	return 0;
+}
+
+static inline int set_swap(struct mcdrv_swap_info *info, unsigned int update)
+{
+	if (!info)
+		return -EINVAL;
+
+	if (!is_valid_swap_info(info, update))
+		return -EINVAL;
+
+	mc_swap_info_set(info, update);
+
+	mc_packet_add_swap(update);
+
+	return mc_packet_execute();
+}
+
+static inline bool is_path_alloff(void)
+{
+	struct mcdrv_path_info info;
+
+	mc_path_info_get_virtual(&info);
+	if (memcmp(&info, &path_alloff, sizeof(struct mcdrv_path_info)))
+		return false;
+
+	return true;
+}
+
+static int set_dsp(u8 *data, unsigned int size)
+{
+	struct mcdrv_aec_info info, curr_info;
+	struct mcdrv_power_info power;
+	struct mcdrv_power_update update;
+	static struct mcdrv_path_info path_info;
+	enum mcdrv_dev_id id;
+	static u8 g_lp2_start, g_src3_start;
+	u32 mute_flag;
+	int ret = 0;
+
+	if (!data || !size)
+		return -EINVAL;
+
+	id = mc_dev_id_get();
+
+	mc_aec_info_get(&info);
+	curr_info = info;
+
+	ret = mc_parser_d7_data_analyze(data, size, &info);
+	if (ret < 0)
+		return ret;
+
+	if (!is_valid_aec_info(&info))
+		return -EINVAL;
+
+	mc_aec_info_set(&info);
+	mc_aec_info_get(&info);
+
+	info.vbox.cdsp_func_a_on &= 0x01;
+	info.vbox.cdsp_func_b_on &= 0x01;
+
+	if (info.control.command == 1) {
+		if (!info.control.param[0] && !is_path_alloff()) {
+			mc_path_info_get_virtual(&path_info);
+
+			ret = set_path(&path_alloff);
+			if (ret < 0)
+				goto exit;
+		}
+	} else if (info.control.command == 2) {
+		if (!info.control.param[0]) {
+			g_lp2_start = mc_mb_register_get_value(MCI_LP2_START);
+			mc_packet_add_write_mb(MCI_LP2_START, 0);
+			g_src3_start = mc_mb_register_get_value(MCI_SRC3_START);
+			mc_packet_add_write_mb(MCI_SRC3_START, 0);
+			ret = mc_packet_execute();
+			if (ret < 0)
+				goto exit;
+		}
+	} else if (info.control.command == 3) {
+		if (id == MCDRV_DEV_ID_81_91H) {
+			mc_packet_add_dout_mute();
+			mute_flag = MCB_DIFO3_VFLAG1 | MCB_DIFO3_VFLAG0 |
+			    MCB_DIFO2_VFLAG1 | MCB_DIFO2_VFLAG0 |
+			    MCB_DIFO1_VFLAG1 | MCB_DIFO1_VFLAG0 |
+			    MCB_DIFO0_VFLAG1 | MCB_DIFO0_VFLAG0;
+			mc_packet_add_wait_event(MCDRV_EVT_DITMUTE | mute_flag);
+			mute_flag = MCB_DAO1_VFLAG1 | MCB_DAO1_VFLAG0 |
+			    MCB_DAO0_VFLAG1 | MCB_DAO0_VFLAG0;
+			mc_packet_add_wait_event(MCDRV_EVT_DACMUTE | mute_flag);
+			mc_packet_add_write_ma(MCI_CLK_SEL,
+					       info.control.param[0]);
+			mc_clock_select_set(info.control.param[0]);
+
+			ret = mc_packet_execute();
+			if (ret < 0)
+				goto exit;
+
+			ret = set_vol(MCDRV_VOLUPDATE_DOUT,
+				      MCDRV_VOLUME_SET, NULL);
+			if (ret < 0)
+				goto exit;
+		}
+	} else if (info.control.command == 4) {
+		if (id == MCDRV_DEV_ID_81_91H) {
+			u32 status = 0;
+
+			mc_packet_add_dac0_mute();
+			mc_packet_add_dac1_mute();
+			mc_packet_add_adif_mute();
+			mc_packet_add_dpath_da_mute();
+			mute_flag = MCB_ADI2_VFLAG1 | MCB_ADI2_VFLAG0 |
+			    MCB_ADI1_VFLAG1 | MCB_ADI1_VFLAG0 |
+			    MCB_ADI0_VFLAG1 | MCB_ADI0_VFLAG0;
+			mc_packet_add_wait_event(MCDRV_EVT_ADCMUTE | mute_flag);
+
+			mute_flag = MCB_SPR_BUSY << 8 | MCB_SPL_BUSY << 8 |
+			    MCB_HPR_BUSY << 8 | MCB_HPL_BUSY << 8 |
+			    MCB_LO2R_BUSY | MCB_LO2L_BUSY |
+			    MCB_LO1R_BUSY | MCB_LO1L_BUSY | MCB_RC_BUSY;
+			mc_packet_add_wait_event(MCDRV_EVT_SVOL_DONE |
+						 mute_flag);
+			mc_packet_add_write_e(MCI_ECLK_SEL,
+					      info.control.param[0]);
+			mc_e_clock_select_set(info.control.param[0]);
+
+			ret = mc_packet_execute();
+			if (ret < 0)
+				goto exit;
+
+			ret = set_vol(MCDRV_VOLUPDATE_ANA_OUT |
+				      MCDRV_VOLUPDATE_ADIF0 |
+				      MCDRV_VOLUPDATE_ADIF1 |
+				      MCDRV_VOLUPDATE_ADIF2 |
+				      MCDRV_VOLUPDATE_DPATHDA,
+				      MCDRV_VOLUME_SET, &status);
+			if (ret < 0)
+				goto exit;
+		}
+
+	}
+
+	mc_power_info_get(&power);
+	update.digital = MCDRV_POWUPDATE_D_ALL;
+	update.analog[0] = MCDRV_POWUPDATE_AP;
+	update.analog[1] = MCDRV_POWUPDATE_AP_OUT0;
+	update.analog[2] = MCDRV_POWUPDATE_AP_OUT1;
+	update.analog[3] = MCDRV_POWUPDATE_AP_MC;
+	update.analog[4] = MCDRV_POWUPDATE_AP_IN;
+	ret = mc_packet_add_powerup(&power, &update);
+	if (ret < 0)
+		goto exit;
+
+	ret = mc_packet_execute();
+	if (ret < 0)
+		goto exit;
+
+	mc_packet_add_aec();
+	ret = mc_packet_execute();
+	if (ret < 0)
+		goto exit;
+
+	ret = mc_bdsp_set_dsp(&info);
+	if (ret < 0)
+		goto exit;
+
+	ret = mc_cdsp_set_dsp(&info);
+	if (ret < 0)
+		goto exit;
+
+	ret = mc_edsp_set_dsp(&info);
+	if (ret < 0)
+		goto exit;
+
+	ret = mc_fdsp_set_dsp(&info);
+	if (ret < 0)
+		goto exit;
+
+	if (info.control.command == 1) {
+		if (info.control.param[0] == 1) {
+			ret = set_path(&path_info);
+			if (ret < 0)
+				goto exit;
+		}
+	} else if (info.control.command == 2) {
+		if (info.control.param[0] == 1) {
+			mc_packet_add_write_mb(MCI_LP2_START, g_lp2_start);
+			mc_packet_add_write_mb(MCI_SRC3_START, g_src3_start);
+		}
+	}
+
+	mc_power_info_get(&power);
+
+	ret = mc_packet_add_powerdown(&power, &update);
+	if (ret < 0)
+		goto exit;
+
+	return mc_packet_execute();
+
+exit:
+	mc_aec_info_replace(&curr_info);
+	save_power();
+
+	return ret;
+}
+
+static inline int get_hsdet(struct mcdrv_hsdet_info *info)
+{
+	if (!info)
+		return -EINVAL;
+
+	mc_hsdet_info_get(info);
+
+	info->dly_irq_stop = 0;
+
+	return 0;
+}
+
+static int set_hsdet(struct mcdrv_hsdet_info *hsdet, unsigned int update)
+{
+	struct mcdrv_hsdet_info curr_hsdet;
+	struct mcdrv_path_info path_info, tmp_path_info;
+	struct mcdrv_hsdet_res hsdet_res;
+	enum mcdrv_dev_id id;
+	u8 val, data[2], plug_det_db;
+	int ret = 0;
+
+	if (!hsdet)
+		return -EINVAL;
+
+	curr_hsdet = *hsdet;
+	if (!is_valid_hsdet_info(&curr_hsdet, update))
+		return -EINVAL;
+
+	id = mc_dev_id_get();
+	if (id == MCDRV_DEV_ID_80_90H)
+		curr_hsdet.det_in_inv &= 1;
+
+	mc_hsdet_info_set(&curr_hsdet, update);
+	mc_packet_add_hsdet();
+	ret = mc_packet_execute();
+	if (ret < 0)
+		return ret;
+
+	mc_hsdet_info_get(&curr_hsdet);
+	if (curr_hsdet.en_plug_det_db != MCDRV_PLUGDETDB_DISABLE ||
+	    curr_hsdet.en_dly_key_off != MCDRV_KEYEN_D_D_D ||
+	    curr_hsdet.en_dly_key_on != MCDRV_KEYEN_D_D_D ||
+	    curr_hsdet.en_mic_det != MCDRV_MICDET_DISABLE ||
+	    curr_hsdet.en_key_off != MCDRV_KEYEN_D_D_D ||
+	    curr_hsdet.en_key_on != MCDRV_KEYEN_D_D_D) {
+		val = mc_cd_register_get_value(MCI_HSDETEN);
+		if (!(val & MCB_MKDETEN)) {
+			val = MCB_HSDETEN | curr_hsdet.hs_det_dbnc;
+			mc_packet_add_write_cd(MCI_HSDETEN, val);
+
+			if (curr_hsdet.en_dly_key_off != MCDRV_KEYEN_D_D_D ||
+			    curr_hsdet.en_dly_key_on != MCDRV_KEYEN_D_D_D ||
+			    curr_hsdet.en_mic_det != MCDRV_MICDET_DISABLE ||
+			    curr_hsdet.en_key_off != MCDRV_KEYEN_D_D_D ||
+			    curr_hsdet.en_key_on != MCDRV_KEYEN_D_D_D) {
+				bool do_set_path = false;
+
+				if (is_ldoa_on()) {
+					mc_path_info_get_virtual(&path_info);
+					tmp_path_info = path_info;
+					tmp_path_info.adc0[0] = 0x00aaaaaa;
+					tmp_path_info.adc0[1] = 0x00aaaaaa;
+
+					tmp_path_info.adc1[0] = 0x00aaaaaa;
+
+					tmp_path_info.dac0[0] = 0x00aaaaaa;
+					tmp_path_info.dac0[1] = 0x00aaaaaa;
+					tmp_path_info.dac1[0] = 0x00aaaaaa;
+					tmp_path_info.dac1[1] = 0x00aaaaaa;
+
+					tmp_path_info.bias[0] = 0x002aaaaa;
+					tmp_path_info.bias[1] = 0x002aaaaa;
+					tmp_path_info.bias[2] = 0x002aaaaa;
+					tmp_path_info.bias[3] = 0x002aaaaa;
+					ret = set_path(&tmp_path_info);
+					if (ret < 0)
+						return ret;
+
+					do_set_path = true;
+				}
+
+				mc_packet_add_mic_key_detect_enable(true);
+
+				if (do_set_path)
+					ret = set_path(&path_info);
+			}
+		} else {
+			val = MCB_HSDETEN | curr_hsdet.hs_det_dbnc;
+			if (curr_hsdet.en_dly_key_off != MCDRV_KEYEN_D_D_D ||
+			    curr_hsdet.en_dly_key_on != MCDRV_KEYEN_D_D_D ||
+			    curr_hsdet.en_mic_det != MCDRV_MICDET_DISABLE ||
+			    curr_hsdet.en_key_off != MCDRV_KEYEN_D_D_D ||
+			    curr_hsdet.en_key_on != MCDRV_KEYEN_D_D_D) {
+				plug_det_db = mc_plug_detect_db_get();
+				if (plug_det_db & MCB_RPLUGDET_DB)
+					val |= MCB_MKDETEN;
+			}
+
+			mc_packet_add_write_cd(MCI_HSDETEN, val);
+
+			if (!(val & MCB_MKDETEN)) {
+				val = mc_ana_register_get_value(MCI_KDSET);
+				val &= ~(MCB_KDSET2 | MCB_KDSET1);
+				mc_packet_add_force_write_ana(MCI_KDSET, val);
+			}
+		}
+	}
+
+	if (!ret)
+		ret = mc_packet_execute();
+
+	if (!ret) {
+		if ((update & MCDRV_ENPLUGDETDB_UPDATE_FLAG) &&
+		    (curr_hsdet.en_plug_det_db &
+		     MCDRV_PLUGDETDB_UNDET_ENABLE) && curr_hsdet.cbfunc) {
+			data[0] = MCI_CD_REG_A << 1;
+			data[1] = MCI_PLUGDET;
+			mc_write_analog(data, 2);
+			mc_read_analog(MCI_CD_REG_D, &val, 1);
+			if (!(val & MCB_PLUGDET)) {
+				hsdet_res.key_cnt0 = 0;
+				hsdet_res.key_cnt1 = 0;
+				hsdet_res.key_cnt2 = 0;
+				mutex_unlock(&mcdrv_mutex);
+				(*curr_hsdet.
+				 cbfunc) (MCDRV_HSDET_EVT_PLUGUNDET_DB_FLAG,
+					  &hsdet_res);
+				mutex_lock(&mcdrv_mutex);
+			}
+		}
+
+		ret = save_power();
+	}
+
+	return ret;
+}
+
+static inline void enable_irqhs(u8 *data)
+{
+	data[1] = MCI_IRQHS;
+	data[3] = MCB_EIRQHS;
+	mc_write_analog(data, 4);
+
+	mc_cd_register_set_value(MCI_IRQHS, MCB_EIRQHS);
+}
+
+int mc_do_irq(void)
+{
+	struct mcdrv_aec_info aec;
+	struct mcdrv_path_info path;
+	struct mcdrv_hsdet_info hsdet;
+	struct mcdrv_hsdet_res hsdet_res;
+	enum mcdrv_dev_id id;
+	u32 flag_det = 0;
+	u8 val, splug_det, plug_det, sensefin, eirq, data[4];
+	u8 flag_dlykey = 0, flag_key = 0;
+	static u8 s_op_dac, s_hp_det;
+	unsigned long interval;
+	int cycles, timeout, ret = 0;
+
+	mutex_lock(&mcdrv_mutex);
+
+	id = mc_dev_id_get();
+	mc_hsdet_info_get(&hsdet);
+
+	eirq = mc_if_register_get_value(MCI_IRQ);
+	val = mc_cd_register_get_value(MCI_EIRQSENSE);
+	if (val & MCB_EIRQSENSE) {
+		/* IRQ Disable */
+		data[0] = MCI_IRQR << 1;
+		data[1] = 0;
+		mc_write_digital(data, 2);
+
+		data[0] = MCI_CD_REG_A << 1;
+		data[1] = MCI_SSENSEFIN;
+		mc_write_analog(data, 2);
+		mc_read_analog(MCI_CD_REG_D, &sensefin, 1);
+		if (sensefin & MCB_SSENSEFIN) {
+			data[1] = MCI_EIRQSENSE;
+			data[2] = MCI_CD_REG_D << 1;
+			data[3] = 0;
+			mc_write_analog(data, 4);
+
+			mc_cd_register_set_value(MCI_EIRQSENSE, 0);
+			data[1] = MCI_SSENSEFIN;
+			data[3] = val;
+			mc_write_analog(data, 4);
+		} else {
+			/* IRQ Enable */
+			data[0] = MCI_IRQR << 1;
+			data[1] = MCB_EIRQR;
+			mc_write_digital(data, 2);
+
+			mutex_unlock(&mcdrv_mutex);
+
+			return 0;
+		}
+
+		/*      PLUGDET, PLUGUNDETDB, PLUGDETDB */
+		data[0] = MCI_CD_REG_A << 1;
+		data[1] = MCI_PLUGDET;
+		mc_write_analog(data, 2);
+		mc_read_analog(MCI_CD_REG_D, &val, 1);
+
+		/*      clear   */
+		flag_det = val;
+		data[2] = MCI_CD_REG_D << 1;
+		data[3] = val;
+		mc_write_analog(data, 4);
+
+		/*      set reference   */
+		data[1] = MCI_PLUGDET_DB;
+		mc_write_analog(data, 2);
+		mc_read_analog(MCI_CD_REG_D, &val, 1);
+		mc_plug_detect_db_set(val);
+
+		data[1] = MCI_RPLUGDET;
+		data[3] = (flag_det & MCB_PLUGDET) | val;
+		mc_write_analog(data, 4);
+		flag_det = data[3];
+
+		data[1] = MCI_MICDET;
+		mc_write_analog(data, 2);
+		mc_read_analog(MCI_CD_REG_D, &val, 1);
+
+		data[1] = MCI_RMICDET;
+		data[3] = val;
+		mc_write_analog(data, 4);
+		flag_key = val & MCB_MICDET;
+
+		data[1] = MCI_SMICDET;
+		mc_write_analog(data, 2);
+		mc_read_analog(MCI_CD_REG_D, &val, 1);
+
+		data[3] = val;
+		mc_write_analog(data, 4);
+
+		hsdet_res.key_cnt0 = 0;
+		hsdet_res.key_cnt1 = 0;
+		hsdet_res.key_cnt2 = 0;
+
+		data[0] = MCI_E_REG_A << 1;
+		data[1] = MCI_PLUG_REV;
+		mc_write_digital(data, 2);
+		mc_read_digital(MCI_E_REG_D, &val, 1);
+		hsdet_res.plug_rev = val >> 7;
+		hsdet_res.hp_imp_class = val & 0x07;
+		data[1] = MCI_HPIMP_15_8;
+		mc_write_digital(data, 2);
+		mc_read_digital(MCI_E_REG_D, &val, 1);
+		hsdet_res.hp_imp = val << 8;
+		data[1] = MCI_HPIMP_7_0;
+		mc_write_digital(data, 2);
+		mc_read_digital(MCI_E_REG_D, &val, 1);
+		hsdet_res.hp_imp |= val;
+
+		val = mc_e_register_get_value(MCI_LPF_THR);
+		val &=
+		    (MCB_OSF1_MN | MCB_OSF0_MN | MCB_OSF1_ENB | MCB_OSF0_ENB);
+		mc_aec_info_get(&aec);
+		val |= aec.output.lpf_post_thru[1] << 7
+		    | aec.output.lpf_post_thru[0] << 6
+		    | aec.output.lpf_pre_thru[1] << 5
+		    | aec.output.lpf_pre_thru[0] << 4;
+		mc_packet_add_write_e(MCI_LPF_THR, val);
+
+		val = aec.output.dcl_on[1] << 7 | aec.output.dcl_gain[1] << 4
+		    | aec.output.dcl_on[0] << 3 | aec.output.dcl_gain[0];
+		mc_packet_add_write_e(MCI_DCL_GAIN, val);
+
+		if (id == MCDRV_DEV_ID_80_90H)
+			mc_packet_add_write_ana(19, s_op_dac);
+
+		mc_packet_add_write_ana(MCI_HPDETVOL, s_hp_det);
+		if (id == MCDRV_DEV_ID_80_90H) {
+			mc_packet_add_force_write_ana(78,
+						      T_CPMODE_IMPSENSE_AFTER);
+			mc_packet_add_force_write_ana(87, 0);
+			data[0] = MCI_ANA_REG_A << 1;
+			data[1] = 78;
+			mc_write_analog(data, 2);
+			mc_read_analog(MCI_ANA_REG_D, &val, 1);
+		} else {
+			mc_packet_add_force_write_ana(87, 0);
+			mc_packet_add_force_write_if(31, 0);
+			mc_packet_add_force_write_if(30, 0);
+		}
+
+		mc_path_info_get_virtual(&path);
+		ret = set_path(&path);
+
+		if (hsdet.cbfunc) {
+			if (flag_det & MCB_SPLUGUNDET_DB)
+				flag_det = MCB_PLUGUNDET_DB;
+			else
+				flag_det |= MCDRV_HSDET_EVT_SENSEFIN_FLAG;
+
+			mutex_unlock(&mcdrv_mutex);
+
+			(*hsdet.cbfunc) (flag_det | (flag_key << 16),
+					 &hsdet_res);
+			mutex_lock(&mcdrv_mutex);
+		}
+
+		/*      Enable IRQ      */
+		data[0] = MCI_CD_REG_A << 1;
+		data[2] = MCI_CD_REG_D << 1;
+		enable_irqhs(data);
+
+		data[0] = MCI_IRQR << 1;
+		data[1] = MCB_EIRQR;
+		mc_write_digital(data, 2);
+
+		val = mc_if_register_get_value(MCI_RST_A);
+		if (!val) {
+			data[0] = MCI_IRQ << 1;
+			data[1] = MCB_EIRQ;
+			mc_write_digital(data, 2);
+			mc_if_register_set_value(MCI_IRQ, MCB_EIRQ);
+		}
+
+		mutex_unlock(&mcdrv_mutex);
+
+		return 0;
+	}
+
+	if (mc_state_get() != MCDRV_STATE_READY) {
+		ret = -EBUSY;
+		goto exit;
+	}
+
+	if (eirq & MCB_EIRQ) {
+		mc_read_digital(MCI_EDSP, &val, 1);
+		if (val) {
+			/* Disable IRQ */
+			mc_packet_add_force_write_if(MCI_EEDSP, 0);
+
+			ret = mc_packet_execute();
+			if (ret < 0)
+				goto exit;
+
+			if (val & MCB_E2DSP_STA)
+				mc_edsp_irq();
+
+			/* Clear IRQ */
+			mc_packet_add_force_write_if(MCI_EDSP, val);
+
+			/* Enable IRQ */
+			mc_packet_add_force_write_if(MCI_EEDSP, MCB_EE2DSP);
+		}
+
+		mc_read_digital(MCI_CDSP, &val, 1);
+		if (val) {
+			/* Disable IRQ */
+			mc_packet_add_force_write_if(MCI_ECDSP, 0);
+
+			ret = mc_packet_execute();
+			if (ret < 0)
+				goto exit;
+
+			mc_cdsp_irq();
+
+			/* Clear IRQ */
+			mc_packet_add_force_write_if(MCI_CDSP, val);
+
+			/* Enable IRQ */
+			val = MCB_ECDSP | MCB_EFFIFO | MCB_ERFIFO | MCB_EEFIFO |
+			    MCB_EOFIFO | MCB_EDFIFO | MCB_EENC | MCB_EDEC;
+			mc_packet_add_force_write_if(MCI_ECDSP, val);
+		}
+
+		mc_read_digital(MCI_IRSERR, &val, 1);
+		if (val) {
+			/* Disable IRQ */
+			mc_packet_add_force_write_if(MCI_IESERR, 0);
+
+			ret = mc_packet_execute();
+			if (ret < 0)
+				goto exit;
+
+			mc_fdsp_irq();
+
+			/* Clear IRQ */
+			mc_packet_add_force_write_if(MCI_IRSERR, val);
+			/* Enable IRQ */
+			val =
+			    MCB_IESERR | MCB_IEAMTBEG | MCB_IEAMTEND | MCB_IEFW;
+			mc_packet_add_force_write_if(MCI_IESERR, val);
+		}
+
+		ret = mc_packet_execute();
+		if (ret < 0)
+			goto exit;
+	}
+
+	data[0] = MCI_CD_REG_A << 1;
+	data[1] = MCI_IRQHS;
+	mc_write_analog(data, 2);
+	mc_read_analog(MCI_CD_REG_D, &val, 1);
+	if (val == (MCB_EIRQHS | MCB_IRQHS)) {
+		/* Disable EIRQHS */
+		data[2] = MCI_CD_REG_D << 1;
+		data[3] = 0;
+		mc_write_analog(data, 4);
+		mc_cd_register_set_value(MCI_IRQHS, 0);
+
+		/* PLUGDET, SPLUGUNDETDB, SPLUGDETDB */
+		data[1] = MCI_PLUGDET;
+		mc_write_analog(data, 2);
+		mc_read_analog(MCI_CD_REG_D, &splug_det, 1);
+		flag_det = splug_det & MCB_PLUGDET;
+
+		data[1] = MCI_PLUGDET_DB;
+		mc_write_analog(data, 2);
+		mc_read_analog(MCI_CD_REG_D, &plug_det, 1);
+		flag_det |= plug_det;
+		if (flag_det & MCB_PLUGUNDET_DB)
+			mc_plug_detect_db_set(0);
+
+		if (hsdet.en_plug_det_db & MCDRV_PLUGDETDB_DET_ENABLE) {
+			if (id == MCDRV_DEV_ID_81_91H) {
+				data[1] = MCI_RPLUGDET;
+				mc_write_analog(data, 2);
+				mc_read_analog(MCI_CD_REG_D, &val, 1);
+				val = ~val & plug_det;
+			} else
+				val = splug_det;
+
+			if (val & MCB_SPLUGDET_DB) {
+				mc_plug_detect_db_set(val);
+
+				if (id != MCDRV_DEV_ID_81_92H) {
+					val = mc_ana_register_get_value(MCI_AP);
+					val &= ~MCB_AP_BGR;
+					mc_packet_add_write_ana(MCI_AP, val);
+				}
+
+				val = mc_ana_register_get_value(MCI_HIZ);
+				val |= MCB_HPR_HIZ | MCB_HPL_HIZ;
+				mc_packet_add_write_ana(MCI_HIZ, val);
+
+				mc_path_info_get_virtual(&path);
+				path.bias[3] |= MCDRV_ASRC_MIC4_ON;
+				ret = set_path(&path);
+				if (ret < 0) {
+					enable_irqhs(data);
+					goto exit;
+				}
+
+				if (hsdet.en_dly_key_off != MCDRV_KEYEN_D_D_D
+				    || hsdet.en_dly_key_on != MCDRV_KEYEN_D_D_D
+				    || hsdet.en_mic_det != MCDRV_MICDET_DISABLE
+				    || hsdet.en_key_off != MCDRV_KEYEN_D_D_D
+				    || hsdet.en_key_on != MCDRV_KEYEN_D_D_D)
+					mc_packet_add_mic_key_detect_enable
+					    (false);
+
+				ret = mc_packet_execute();
+				if (ret < 0) {
+					enable_irqhs(data);
+					goto exit;
+				}
+
+				if (hsdet.sgnl_num != MCDRV_SGNLNUM_NONE) {
+					s_hp_det =
+					    mc_ana_register_get_value
+					    (MCI_HPDETVOL);
+					ret = imp_sense_start(&s_op_dac);
+					if (ret == 0) {
+						mutex_unlock(&mcdrv_mutex);
+						return ret;
+					}
+
+					enable_irqhs(data);
+					goto exit;
+				}
+			}
+		}
+
+		/*      clear   */
+		data[1] = MCI_PLUGDET;
+		data[3] = splug_det;
+		mc_write_analog(data, 4);
+
+		/*      set reference   */
+		data[1] = MCI_RPLUGDET;
+		data[3] = flag_det;
+		mc_write_analog(data, 4);
+
+		/*      DLYKEYON, DLYKEYOFF     */
+		data[1] = MCI_SDLYKEY;
+		mc_write_analog(data, 2);
+		mc_read_analog(MCI_CD_REG_D, &val, 1);
+		flag_dlykey = val;
+		/*      clear   */
+		data[1] = MCI_SDLYKEY;
+		data[3] = val;
+		mc_write_analog(data, 4);
+
+		/*      MICDET, KEYON, KEYOFF   */
+		data[1] = MCI_SMICDET;
+		mc_write_analog(data, 2);
+		mc_read_analog(MCI_CD_REG_D, &val, 1);
+		flag_key = val & ~MCB_SMICDET;
+		/*      clear   */
+		data[1] = MCI_SMICDET;
+		data[3] = val;
+		mc_write_analog(data, 4);
+
+		/* set reference */
+		data[1] = MCI_MICDET;
+		mc_write_analog(data, 2);
+		if (hsdet.sgnl_num == MCDRV_SGNLNUM_NONE) {
+			if (flag_det & MCB_PLUGDET_DB) {
+				switch (hsdet.speriod) {
+				case MCDRV_SPERIOD_488:
+					interval = 488;
+					break;
+				case MCDRV_SPERIOD_977:
+					interval = 977;
+					break;
+				case MCDRV_SPERIOD_1953:
+					interval = 1953;
+					break;
+				case MCDRV_SPERIOD_3906:
+					interval = 3906;
+					break;
+				case MCDRV_SPERIOD_7813:
+					interval = 7813;
+					break;
+				case MCDRV_SPERIOD_15625:
+					interval = 15625;
+					break;
+				case MCDRV_SPERIOD_31250:
+					interval = 31250;
+					break;
+				default:
+					interval = 244;
+					break;
+				}
+
+				timeout = 1;
+				switch (hsdet.dbnc_num_mic) {
+				case MCDRV_DBNC_NUM_3:
+					timeout += 3;
+					break;
+				case MCDRV_DBNC_NUM_4:
+					timeout += 4;
+					break;
+				case MCDRV_DBNC_NUM_7:
+					timeout += 7;
+					break;
+				default:
+					break;
+				}
+
+				cycles = 0;
+				while (cycles < timeout) {
+					mc_read_analog(MCI_CD_REG_D,
+								 &val, 1);
+					if (val & (MCB_MICDET | 0x07))
+						break;
+
+					udelay(interval);
+					cycles++;
+				}
+			}
+		} else
+			mc_read_analog(MCI_CD_REG_D, &val, 1);
+		flag_key |= val & MCB_MICDET;
+		data[1] = MCI_RMICDET;
+		data[3] = val;
+		mc_write_analog(data, 4);
+
+		if (hsdet.cbfunc) {
+			/*      KeyCnt0 */
+			data[1] = MCI_KEYCNTCLR0;
+			mc_write_analog(data, 2);
+			mc_read_analog(MCI_CD_REG_D,
+						 &hsdet_res.key_cnt0, 1);
+			data[1] = MCI_KEYCNTCLR0;
+			data[3] = MCB_KEYCNTCLR0;
+			mc_write_analog(data, 4);
+
+			/*      KeyCnt1 */
+			data[1] = MCI_KEYCNTCLR1;
+			mc_write_analog(data, 2);
+			mc_read_analog(MCI_CD_REG_D,
+						 &hsdet_res.key_cnt1, 1);
+			data[1] = MCI_KEYCNTCLR1;
+			data[3] = MCB_KEYCNTCLR1;
+			mc_write_analog(data, 4);
+
+			/*      KeyCnt2 */
+			data[1] = MCI_KEYCNTCLR2;
+			mc_write_analog(data, 2);
+			mc_read_analog(MCI_CD_REG_D,
+						 &hsdet_res.key_cnt2, 1);
+			data[1] = MCI_KEYCNTCLR2;
+			data[3] = MCB_KEYCNTCLR2;
+			mc_write_analog(data, 4);
+
+			data[0] = MCI_IRQ << 1;
+			data[1] = 0;
+			mc_write_analog(data, 2);
+			mc_if_register_set_value(MCI_IRQ, 0);
+
+			data[0] = MCI_IRQR << 1;
+			data[1] = 0;
+			mc_write_analog(data, 2);
+
+			mutex_unlock(&mcdrv_mutex);
+
+			(*hsdet.cbfunc) (flag_det | (u32) flag_dlykey << 8 |
+					 (u32) flag_key << 16, &hsdet_res);
+
+			mutex_lock(&mcdrv_mutex);
+
+			data[0] = MCI_IRQR << 1;
+			data[1] = MCB_EIRQR;
+			mc_write_analog(data, 2);
+		}
+		/* Enable IRQ */
+		data[0] = MCI_CD_REG_A << 1;
+		data[2] = MCI_CD_REG_D << 1;
+		enable_irqhs(data);
+	}
+
+exit:
+	val = mc_if_register_get_value(MCI_RST_A);
+	if (!val) {
+		val = mc_if_register_get_value(MCI_IRQ);
+		if (val != MCB_EIRQ) {
+			data[0] = MCI_IRQ << 1;
+			data[1] = MCB_EIRQ;
+			mc_write_analog(data, 2);
+			mc_if_register_set_value(MCI_IRQ, MCB_EIRQ);
+		}
+	}
+
+	mutex_unlock(&mcdrv_mutex);
+
+	return ret;
+}
+
+static inline bool is_valid_mcdrv_dev_info(struct mcdrv_dev_info *info)
+{
+	enum mcdrv_dev_id id;
+
+	id = mc_dev_id_get();
+
+	if (info->clk_sel > MCDRV_CKSEL_LAST)
+		return false;
+
+	if (info->clk_input > MCDRV_CKINPUT_LAST ||
+	    info->clk_input == MCDRV_CKINPUT_NONE0 ||
+	    info->clk_input == MCDRV_CKINPUT_NONE1 ||
+	    info->clk_input == MCDRV_CKINPUT_NONE2)
+		return false;
+
+	if (info->pll_mode_a > MCDRV_PLLMODE_MAX)
+		return false;
+
+	if (info->pll_prev_div_a > MCDRV_PLLPREV_DIV_MAX)
+		return false;
+
+	if (info->pll_fb_div_a > MCDRV_PLLFB_DIV_MAX)
+		return false;
+
+	if (info->pll_mode_b > MCDRV_PLLMODE_MAX)
+		return false;
+
+	if (info->pll_prev_div_b > MCDRV_PLLPREV_DIV_MAX)
+		return false;
+
+	if (info->pll_fb_div_b > MCDRV_PLLFB_DIV_MAX)
+		return false;
+
+	if (info->power_mode != MCDRV_POWMODE_FULL &&
+	    info->power_mode != MCDRV_POWMODE_CDSPDEBUG)
+		return false;
+
+	if (info->mb_sel1 > MCDRV_MBSEL_LAST)
+		return false;
+
+	if (info->mb_sel2 > MCDRV_MBSEL_LAST)
+		return false;
+
+	if (info->mb_sel3 > MCDRV_MBSEL_LAST)
+		return false;
+
+	if (info->mb_sel4 > MCDRV_MBSEL_LAST)
+		return false;
+
+	if (info->mbs_disch > MCDRV_MBSDISCH_LAST)
+		return false;
+
+	if (info->sp_hiz > MCDRV_WL_LAST)
+		return false;
+
+	if (info->hp_hiz > MCDRV_IMP_LAST)
+		return false;
+
+	if (info->line_out1_hiz > MCDRV_IMP_LAST)
+		return false;
+
+	if (info->line_out2_hiz > MCDRV_IMP_LAST)
+		return false;
+
+	if (info->wait_time.wait[0] > MCDRV_WAIT_MAX ||
+	    info->wait_time.wait[1] > MCDRV_WAIT_MAX ||
+	    info->wait_time.wait[2] > MCDRV_WAIT_MAX ||
+	    info->wait_time.wait[3] > MCDRV_WAIT_MAX ||
+	    info->wait_time.wait[4] > MCDRV_WAIT_MAX)
+		return false;
+
+	if (id == MCDRV_DEV_ID_81_91H) {
+		if (info->options[0] > MCDRV_DOA_DRV_LAST)
+			return false;
+		if (info->options[1] > MCDRV_SCKMSK_LAST)
+			return false;
+		if (info->options[2] > MCDRV_SPMN_LAST)
+			return false;
+		if (info->options[3] > 0x0f)
+			return false;
+		if (info->options[4] > 0xf8)
+			return false;
+		if (info->options[5] > 0xf8)
+			return false;
+		if (info->options[6] > 0x31)
+			return false;
+		if (info->options[7] > 0x7f)
+			return false;
+		if (info->options[9] > 0x7f)
+			return false;
+		if (info->options[10] > 0x11)
+			return false;
+		if (info->options[11] > 0xf3)
+			return false;
+		if (info->options[12] > 0x07)
+			return false;
+	}
+
+	return true;
+}
+
+int mc_init(struct mcdrv_dev_info *info)
+{
+	struct mcdrv_power_info power_info;
+	struct mcdrv_power_update power_update;
+	enum mcdrv_state state;
+	u8 analog_id, digital_id, ap = MCI_AP_DEF, data[4];
+	int ret;
+
+	if (!info)
+		return -EINVAL;
+
+	state = mc_state_get();
+	if (state == MCDRV_STATE_READY)
+		return -EBUSY;
+
+	mutex_lock(&mcdrv_mutex);
+
+	mc_resource_init();
+
+	data[0] = MCI_ANA_REG_A << 1;
+	data[1] = MCI_ANA_ID;
+	mc_write_analog(data, 2);
+	mc_read_analog(MCI_ANA_REG_D, &analog_id, 1);
+
+	if ((analog_id & MCDRV_DEVID_MASK) == MCDRV_DEVID_ANA) {
+		/* reset */
+		data[0] = MCI_ANA_REG_A << 1;
+		data[1] = MCI_ANA_RST;
+		data[2] = MCI_ANA_REG_D << 1;
+		data[3] = MCI_ANA_RST_DEF;
+		mc_write_analog(data, 4);
+
+		data[3] = 0;
+		mc_write_analog(data, 4);
+
+		if (!(analog_id & MCDRV_VERID_MASK)) {
+			data[1] = MCI_AP;
+			data[3] = MCI_AP_DEF & ~(MCB_AP_LDOD | MCB_AP_BGR);
+			mc_write_analog(data, 4);
+
+			data[3] &= ~MCB_AP_VR;
+			mc_write_analog(data, 4);
+
+			msleep(VREF_WAIT_TIME_ES1);
+
+			data[3] &= ~MCB_AP_LDOA;
+			mc_write_analog(data, 4);
+
+			msleep(LDO_WAIT_TIME);
+
+			ap = data[3];
+		} else {
+			data[1] = MCI_HIZ;
+			data[3] = 0;
+			mc_write_analog(data, 4);
+
+			data[1] = MCI_LO_HIZ;
+			data[3] = 0;
+			mc_write_analog(data, 4);
+
+			data[1] = MCI_AP;
+			ap &= ~(MCB_AP_LDOD | MCB_AP_BGR);
+			data[3] = ap;
+			mc_write_analog(data, 4);
+
+			ap &= ~MCB_AP_LDOA;
+			data[3] = ap;
+			mc_write_analog(data, 4);
+
+			msleep(LDO_WAIT_TIME);
+
+			data[1] = 62;
+			data[3] = 0x20;
+			mc_write_analog(data, 4);
+
+			data[1] = MCI_AP;
+			ap &= ~MCB_AP_VR;
+			data[3] = ap;
+			mc_write_analog(data, 4);
+
+			msleep(VREF_WAIT_TIME);
+
+			data[1] = 62;
+			data[3] = 0;
+			mc_write_analog(data, 4);
+		}
+
+		data[0] = MCI_RST_A << 1;
+		data[1] = MCI_RST_A_DEF & ~MCB_RST_A;
+		mc_write_digital(data, 2);
+
+		data[0] = MCI_A_REG_A << 1;
+		data[1] = MCI_A_DEV_ID;
+		mc_write_digital(data, 2);
+		mc_read_digital(MCI_A_REG_D, &digital_id, 1);
+		ret = mc_id_set(digital_id, analog_id);
+		if (!ret) {
+			if (is_valid_mcdrv_dev_info(info)) {
+				mc_ana_register_set_value(MCI_AP, ap);
+				mc_dev_info_set(info);
+				mc_packet_clear();
+				ret = mc_packet_init();
+				if (ret == 0)
+					ret = mc_packet_execute();
+			} else
+				ret = -EINVAL;
+		}
+
+		if (!ret && info->power_mode == MCDRV_POWMODE_CDSPDEBUG) {
+			mc_power_info_get(&power_info);
+
+			/*      used path power up      */
+			power_update.digital = MCDRV_POWUPDATE_D_ALL;
+			power_update.analog[0] = 0;
+			power_update.analog[1] = 0;
+			power_update.analog[2] = 0;
+			power_update.analog[3] = 0;
+			power_update.analog[4] = 0;
+			ret = mc_packet_add_powerup(&power_info, &power_update);
+		}
+
+		if (!ret) {
+			mc_state_update(MCDRV_STATE_READY);
+			save_power();
+		}
+	} else
+		ret = -EIO;
+
+	mutex_unlock(&mcdrv_mutex);
+
+	return ret;
+}
+
+int mc_term(void)
+{
+	struct mcdrv_dev_info info;
+	struct mcdrv_power_info power_info;
+	struct mcdrv_power_update power_update;
+	struct mcdrv_hsdet_info hsdet_info;
+	enum mcdrv_state state;
+	u32 flags;
+	int ret = 0;
+
+	state = mc_state_get();
+	if (state != MCDRV_STATE_READY)
+		return -EBUSY;
+
+	mutex_lock(&mcdrv_mutex);
+
+	mc_dev_info_get(&info);
+	info.power_mode = MCDRV_POWMODE_FULL;
+	mc_dev_info_set(&info);
+
+	ret = set_path(&path_alloff);
+	if (!ret) {
+		power_info.digital = 0xff;
+		power_info.analog[0] = 0xff;
+		power_info.analog[1] = 0xff;
+		power_info.analog[2] = 0xff;
+		power_info.analog[3] = 0xff;
+		power_info.analog[4] = 0xff;
+
+		power_update.digital = MCDRV_POWUPDATE_D_ALL;
+		power_update.analog[0] = MCDRV_POWUPDATE_AP;
+		power_update.analog[1] = MCDRV_POWUPDATE_AP_OUT0;
+		power_update.analog[2] = (u8) MCDRV_POWUPDATE_AP_OUT1;
+		power_update.analog[3] = (u8) MCDRV_POWUPDATE_AP_MC;
+		power_update.analog[4] = (u8) MCDRV_POWUPDATE_AP_IN;
+
+		ret = mc_packet_add_powerdown(&power_info,
+						       &power_update);
+		if (!ret)
+			ret = mc_packet_execute();
+	}
+
+	hsdet_info.en_plug_det = MCDRV_PLUGDET_DISABLE;
+	hsdet_info.en_plug_det_db = MCDRV_PLUGDETDB_DISABLE;
+	hsdet_info.en_dly_key_off = MCDRV_KEYEN_D_D_D;
+	hsdet_info.en_dly_key_on = MCDRV_KEYEN_D_D_D;
+	hsdet_info.en_mic_det = MCDRV_MICDET_DISABLE;
+	hsdet_info.en_key_off = MCDRV_KEYEN_D_D_D;
+	hsdet_info.en_key_on = MCDRV_KEYEN_D_D_D;
+	flags = MCDRV_ENPLUGDET_UPDATE_FLAG | MCDRV_ENPLUGDETDB_UPDATE_FLAG |
+	    MCDRV_ENDLYKEYOFF_UPDATE_FLAG | MCDRV_ENDLYKEYON_UPDATE_FLAG |
+	    MCDRV_ENMICDET_UPDATE_FLAG | MCDRV_ENKEYOFF_UPDATE_FLAG |
+	    MCDRV_ENKEYON_UPDATE_FLAG;
+
+	ret = set_hsdet(&hsdet_info, flags);
+
+	mc_state_update(MCDRV_STATE_NOTINIT);
+
+	mutex_unlock(&mcdrv_mutex);
+
+	return ret;
+}
+
+int mc_control(unsigned int cmd, unsigned long arg, unsigned int flags)
+{
+	int ret;
+
+	if (mc_state_get() != MCDRV_STATE_READY)
+		return -EBUSY;
+
+	mutex_lock(&mcdrv_mutex);
+
+	switch (cmd) {
+	case MCDRV_GET_CLOCKSW:
+		ret = get_clock((u8 *) arg);
+		break;
+	case MCDRV_SET_CLOCKSW:
+		ret = set_clock((u8 *) arg);
+		break;
+	case MCDRV_GET_PATH:
+		ret = get_path((struct mcdrv_path_info *)arg);
+		break;
+	case MCDRV_SET_PATH:
+		ret = set_path((struct mcdrv_path_info *)arg);
+		break;
+	case MCDRV_GET_VOLUME:
+		ret = get_volume((struct mcdrv_vol_info *)arg);
+		break;
+	case MCDRV_SET_VOLUME:
+		ret = set_volume((struct mcdrv_vol_info *)arg);
+		break;
+	case MCDRV_GET_DIGITALIO:
+		ret = get_digitalio((struct mcdrv_dio_info *)arg);
+		break;
+	case MCDRV_SET_DIGITALIO:
+		ret = set_digitalio((struct mcdrv_dio_info *)arg, flags);
+		break;
+	case MCDRV_GET_DIGITALIO_PATH:
+		ret = get_digitalio_path((struct mcdrv_dio_path_info *)arg);
+		break;
+	case MCDRV_SET_DIGITALIO_PATH:
+		ret =
+		    set_digitalio_path((struct mcdrv_dio_path_info *)arg,
+				       flags);
+		break;
+	case MCDRV_GET_SWAP:
+		ret = get_swap((struct mcdrv_swap_info *)arg);
+		break;
+	case MCDRV_SET_SWAP:
+		ret = set_swap((struct mcdrv_swap_info *)arg, flags);
+		break;
+	case MCDRV_SET_DSP:
+		ret = set_dsp((u8 *) arg, flags);
+		break;
+	case MCDRV_GET_HSDET:
+		ret = get_hsdet((struct mcdrv_hsdet_info *)arg);
+		break;
+	case MCDRV_SET_HSDET:
+		ret = set_hsdet((struct mcdrv_hsdet_info *)arg, flags);
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+
+	mutex_unlock(&mcdrv_mutex);
+
+	return ret;
+}
+
+int mc_version_id_get(void)
+{
+	u8 data[2], val;
+
+	mutex_lock(&mcdrv_mutex);
+
+	data[0] = MCI_ANA_REG_A << 1;
+	data[1] = MCI_ANA_ID;
+	mc_write_analog(data, 2);
+	mc_read_analog(MCI_ANA_REG_D, &val, 1);
+
+	mutex_unlock(&mcdrv_mutex);
+
+	return val & 0x7;
+}
diff --git a/sound/soc/codecs/ymu831/mcdriver.h b/sound/soc/codecs/ymu831/mcdriver.h
new file mode 100644
index 0000000..d583e87
--- /dev/null
+++ b/sound/soc/codecs/ymu831/mcdriver.h
@@ -0,0 +1,1017 @@
+/****************************************************************************
+ *
+ * Copyright(c) 2012 Yamaha Corporation. All rights reserved.
+ *
+ * Module	: mcdriver.h
+ * Description	: MC driver header
+ * Version	: 1.0.0 Dec 13 2012
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty.	In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ *	claim that you wrote the original software. If you use this software
+ *	in a product, an acknowledgment in the product documentation would be
+ *	appreciated but is not required.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ *	misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ *
+ ****************************************************************************/
+/*
+ * changelog:
+ * - change in the Linux coding style
+ * - remove unnecessary comments
+ * - remove unused codes
+ */
+#ifndef _MCDRIVER_H
+#define _MCDRIVER_H
+
+#include <linux/types.h>
+
+/* mc_control command */
+enum mc_command {
+	MCDRV_GET_CLOCKSW,
+	MCDRV_SET_CLOCKSW,
+	MCDRV_GET_PATH,
+	MCDRV_SET_PATH,
+	MCDRV_GET_VOLUME,
+	MCDRV_SET_VOLUME,
+	MCDRV_GET_DIGITALIO,
+	MCDRV_SET_DIGITALIO,
+	MCDRV_GET_DIGITALIO_PATH,
+	MCDRV_SET_DIGITALIO_PATH,
+	MCDRV_GET_SWAP,
+	MCDRV_SET_SWAP,
+	MCDRV_SET_DSP,
+	MCDRV_GET_HSDET,
+	MCDRV_SET_HSDET,
+};
+
+#define MCDRV_WAIT_MAX			268435455U
+
+struct mcdrv_wait_time {
+	u32 wait[7];
+	u32 poll_interval[6];
+	u32 poll_timeout[6];
+};
+
+/*	mcdrv_dev_info clk_sel setting	*/
+#define	MCDRV_CKSEL_CMOS_CMOS		0x00
+#define	MCDRV_CKSEL_TCXO_CMOS		0x01
+#define	MCDRV_CKSEL_CMOS_TCXO		0x02
+#define	MCDRV_CKSEL_TCXO_TCXO		0x03
+#define	MCDRV_CKSEL_LAST		MCDRV_CKSEL_TCXO_TCXO
+
+/*	mcdrv_dev_info clk_input setting	*/
+#define MCDRV_CKINPUT_NONE0		0x00
+#define	MCDRV_CKINPUT_CLKI1_CLKI0	0x01
+#define	MCDRV_CKINPUT_RTC_CLKI0		0x02
+#define	MCDRV_CKINPUT_SBCK_CLKI0	0x03
+#define	MCDRV_CKINPUT_CLKI0_CLKI1	0x04
+#define MCDRV_CKINPUT_NONE1		0x05
+#define	MCDRV_CKINPUT_RTC_CLKI1		0x06
+#define	MCDRV_CKINPUT_SBCK_CLKI1	0x07
+#define	MCDRV_CKINPUT_CLKI0_RTCK	0x08
+#define	MCDRV_CKINPUT_CLKI1_RTCK	0x09
+#define MCDRV_CKINPUT_NONE2		0x0A
+#define	MCDRV_CKINPUT_SBCK_RTC		0x0B
+#define	MCDRV_CKINPUT_CLKI0_SBCK	0x0C
+#define	MCDRV_CKINPUT_CLKI1_SBCK	0x0D
+#define	MCDRV_CKINPUT_RTC_SBCK		0x0E
+#define MCDRV_CKINPUT_LAST		MCDRV_CKINPUT_RTC_SBCK
+
+#define MCDRV_PLLMODE_MAX		7
+
+#define MCDRV_PLLPREV_DIV_MAX		0x3f
+
+#define MCDRV_PLLFB_DIV_MAX		0x3fff
+
+/*	mcdrv_dev_info pll_freq_* setting	*/
+#define	MCDRV_PLLFREQ_73		0
+#define	MCDRV_PLLFREQ_147		1
+
+/*	mcdrv_dev_info hsdet_clk setting	*/
+#define	MCDRV_HSDETCLK_RTC		false
+#define	MCDRV_HSDETCLK_OSC		true
+
+/*	mcdrv_dev_info XXX_hiz setting	*/
+#define	MCDRV_DAHIZ_LOW			0
+#define	MCDRV_DAHIZ_HIZ			1
+
+/*	mcdrv_dev_info pcm_hiz setting	*/
+#define	MCDRV_PCMHIZ_LOW		0
+#define	MCDRV_PCMHIZ_HIZ		1
+
+/*	mcdrv_dev_info paX_func setting	*/
+#define	MCDRV_PA_GPIO			false
+#define	MCDRV_PA_PDMCK			true
+#define	MCDRV_PA_PDMDI			true
+
+/*	mcdrv_dev_info power_mode setting	*/
+#define	MCDRV_POWMODE_FULL		0
+#define	MCDRV_POWMODE_CDSPDEBUG		255
+
+/*	mcdrv_dev_info mb_sel setting	*/
+#define	MCDRV_MBSEL_20			0
+#define	MCDRV_MBSEL_21			1
+#define	MCDRV_MBSEL_22			2
+#define	MCDRV_MBSEL_23			3
+#define	MCDRV_MBSEL_LAST		MCDRV_MBSEL_23
+
+/*	mcdrv_dev_info mbs_disch setting	*/
+#define	MCDRV_MBSDISCH_0000		0
+#define	MCDRV_MBSDISCH_0001		1
+#define	MCDRV_MBSDISCH_0010		2
+#define	MCDRV_MBSDISCH_0011		3
+#define	MCDRV_MBSDISCH_0100		4
+#define	MCDRV_MBSDISCH_0101		5
+#define	MCDRV_MBSDISCH_0110		6
+#define	MCDRV_MBSDISCH_0111		7
+#define	MCDRV_MBSDISCH_1000		8
+#define	MCDRV_MBSDISCH_1001		9
+#define	MCDRV_MBSDISCH_1010		10
+#define	MCDRV_MBSDISCH_1011		11
+#define	MCDRV_MBSDISCH_1100		12
+#define	MCDRV_MBSDISCH_1101		13
+#define	MCDRV_MBSDISCH_1110		14
+#define	MCDRV_MBSDISCH_1111		15
+#define	MCDRV_MBSDISCH_LAST		MCDRV_MBSDISCH_1111
+
+/*	mcdrv_dev_info nonclip setting	*/
+#define	MCDRV_NONCLIP_OFF		false
+#define	MCDRV_NONCLIP_ON		true
+
+/*	mcdrv_dev_info line_*_dif setting	*/
+#define	MCDRV_LINE_STEREO		false
+#define	MCDRV_LINE_DIF			true
+
+/*	mcdrv_dev_info micX_single setting	*/
+#define	MCDRV_MIC_DIF			false
+#define	MCDRV_MIC_SINGLE		true
+
+/*	mcdrv_dev_info zc_line_outX/zc_rc/zc_sp/zc_hp setting	*/
+#define	MCDRV_ZC_ON			false
+#define	MCDRV_ZC_OFF			true
+
+/*	mcdrv_dev_info svol_line_outX/svol_rc/svol_sp/svol_hp setting	*/
+#define	MCDRV_SVOL_OFF			false
+#define	MCDRV_SVOL_ON			true
+
+/*	mcdrv_dev_info rc_hiz setting	*/
+#define	MCDRV_RCIMP_FIXLOW		0
+#define	MCDRV_RCIMP_WL			1
+
+/*	mcdrv_dev_info sp_hiz setting	*/
+#define	MCDRV_WL_LOFF_ROFF		0
+#define	MCDRV_WL_LON_ROFF		1
+#define	MCDRV_WL_LOFF_RON		2
+#define	MCDRV_WL_LON_RON		3
+#define	MCDRV_WL_LAST			MCDRV_WL_LON_RON
+
+/*	mcdrv_dev_info hp_hiz/line_outX_hiz setting	*/
+#define	MCDRV_IMP_LFIXLOW_RFIXLOW	0
+#define	MCDRV_IMP_LWL_RFIXLOW		1
+#define	MCDRV_IMP_LFIXLOW_RWL		2
+#define	MCDRV_IMP_LWL_RWL		3
+#define	MCDRV_IMP_LAST			MCDRV_IMP_LWL_RWL
+
+/*	mcdrv_dev_info cp_mod setting	*/
+#define	MCDRV_CPMOD_HI			0
+#define	MCDRV_CPMOD_MID			1
+
+/*	mcdrv_dev_info rb_sel setting	*/
+#define	MCDRV_RBSEL_2_2K		0
+#define	MCDRV_RBSEL_50			1
+
+/*	mcdrv_dev_info plug_sel setting	*/
+#define	MCDRV_PLUG_LRGM			0
+#define	MCDRV_PLUG_LRMG			1
+
+/*	mcdrv_dev_info gnd_det setting	*/
+#define	MCDRV_GNDDET_OFF		0
+#define	MCDRV_GNDDET_ON			1
+
+/*	mcdrv_dev_info ppd_* setting	*/
+#define	MCDRV_PPD_OFF			0
+#define	MCDRV_PPD_ON			1
+
+/*	mcdrv_dev_info option[0] setting	*/
+#define MCDRV_DOA_DRV_LOW		0
+#define MCDRV_DOA_DRV_HIGH		1
+#define MCDRV_DOA_DRV_LAST		MCDRV_DOA_DRV_HIGH
+
+/*	mcdrv_dev_info option[1] setting	*/
+#define MCDRV_SCKMSK_OFF		0
+#define MCDRV_SCKMSK_ON			1
+#define MCDRV_SCKMSK_LAST		MCDRV_SCKMSK_ON
+
+/*	mcdrv_dev_info option[2] setting	*/
+#define MCDRV_SPMN_8_9_10		0
+#define MCDRV_SPMN_5_6_7		1
+#define MCDRV_SPMN_4_5_6		2
+#define MCDRV_SPMN_OFF_9		3
+#define MCDRV_SPMN_OFF_6		4
+#define MCDRV_SPMN_LAST			MCDRV_SPMN_OFF_6
+
+struct mcdrv_dev_info {
+	u8 clk_sel;
+	u8 clk_input;
+	u8 pll_mode_a;
+	u8 pll_prev_div_a;
+	u16 pll_fb_div_a;
+	u16 pll_frac_a;
+	bool pll_freq_a;
+	u8 pll_mode_b;
+	u8 pll_prev_div_b;
+	u16 pll_fb_div_b;
+	u16 pll_frac_b;
+	bool pll_freq_b;
+	bool hsdet_clk;
+	bool dio0_sdo_hiz;
+	bool dio1_sdo_hiz;
+	bool dio2_sdo_hiz;
+	bool dio0_clk_hiz;
+	bool dio1_clk_hiz;
+	bool dio2_clk_hiz;
+	bool dio0_pcm_hiz;
+	bool dio1_pcm_hiz;
+	bool dio2_pcm_hiz;
+	bool pa0_func;
+	bool pa1_func;
+	bool pa2_func;
+	u8 power_mode;
+	u8 mb_sel1;
+	u8 mb_sel2;
+	u8 mb_sel3;
+	u8 mb_sel4;
+	u8 mbs_disch;
+	bool nonclip;
+	bool line_in1_dif;
+	bool line_out1_dif;
+	bool line_out2_dif;
+	bool mic1_single;
+	bool mic2_single;
+	bool mic3_single;
+	bool mic4_single;
+	bool zc_line_out1;
+	bool zc_line_out2;
+	bool zc_rc;
+	bool zc_sp;
+	bool zc_hp;
+	bool svol_line_out1;
+	bool svol_line_out2;
+	bool svol_rc;
+	bool svol_sp;
+	bool svol_hp;
+	bool rc_hiz;
+	u8 sp_hiz;
+	u8 hp_hiz;
+	u8 line_out1_hiz;
+	u8 line_out2_hiz;
+	bool cp_mod;
+	bool rb_sel;
+	bool plug_sel;
+	bool gnd_det;
+	bool ppd_rc;
+	bool ppd_sp;
+	bool ppd_hp;
+	bool ppd_line_out1;
+	bool ppd_line_out2;
+	u8 options[20];
+	struct mcdrv_wait_time wait_time;
+};
+
+/*	set/get clock switch	*/
+#define	MCDRV_CLKSW_CLKA		0
+#define	MCDRV_CLKSW_CLKB		1
+
+/*	set/get path	*/
+#define	MCDRV_D1SRC_MUSICIN_ON		0x00000001
+#define	MCDRV_D1SRC_MUSICIN_OFF		0x00000002
+#define	MCDRV_D1SRC_EXTIN_ON		0x00000004
+#define	MCDRV_D1SRC_EXTIN_OFF		0x00000008
+#define	MCDRV_D1SRC_VBOXOUT_ON		0x00000010
+#define	MCDRV_D1SRC_VBOXOUT_OFF		0x00000020
+#define	MCDRV_D1SRC_VBOXREFOUT_ON	0x00000040
+#define	MCDRV_D1SRC_VBOXREFOUT_OFF	0x00000080
+#define	MCDRV_D1SRC_AE0_ON		0x00000100
+#define	MCDRV_D1SRC_AE0_OFF		0x00000200
+#define	MCDRV_D1SRC_AE1_ON		0x00000400
+#define	MCDRV_D1SRC_AE1_OFF		0x00000800
+#define	MCDRV_D1SRC_AE2_ON		0x00001000
+#define	MCDRV_D1SRC_AE2_OFF		0x00002000
+#define	MCDRV_D1SRC_AE3_ON		0x00004000
+#define	MCDRV_D1SRC_AE3_OFF		0x00008000
+#define MCDRV_D1SRC_AE_ALL_ON				\
+	(MCDRV_D1SRC_AE0_ON | MCDRV_D1SRC_AE1_ON |	\
+	 MCDRV_D1SRC_AE2_ON | MCDRV_D1SRC_AE3_ON)
+#define	MCDRV_D1SRC_ADIF0_ON		0x00010000
+#define	MCDRV_D1SRC_ADIF0_OFF		0x00020000
+#define	MCDRV_D1SRC_ADIF1_ON		0x00040000
+#define	MCDRV_D1SRC_ADIF1_OFF		0x00080000
+#define	MCDRV_D1SRC_ADIF2_ON		0x00100000
+#define	MCDRV_D1SRC_ADIF2_OFF		0x00200000
+#define	MCDRV_D1SRC_HIFIIN_ON		0x00400000
+#define	MCDRV_D1SRC_HIFIIN_OFF		0x00800000
+#define MCDRV_D1SRC_ALL_ON		0x00555555
+
+#define	MCDRV_D2SRC_VOICEIN_ON		0x00000001
+#define	MCDRV_D2SRC_VOICEIN_OFF		0x00000002
+#define	MCDRV_D2SRC_VBOXIOOUT_ON	0x00000004
+#define	MCDRV_D2SRC_VBOXIOOUT_OFF	0x00000008
+#define	MCDRV_D2SRC_VBOXHOSTOUT_ON	0x00000010
+#define	MCDRV_D2SRC_VBOXHOSTOUT_OFF	0x00000020
+#define	MCDRV_D2SRC_ADC0_L_ON		0x00000040
+#define	MCDRV_D2SRC_ADC0_L_OFF		0x00000080
+#define	MCDRV_D2SRC_ADC0_R_ON		0x00000100
+#define	MCDRV_D2SRC_ADC0_R_OFF		0x00000200
+#define	MCDRV_D2SRC_ADC0_ON	\
+	(MCDRV_D2SRC_ADC0_L_ON | MCDRV_D2SRC_ADC0_R_ON)
+#define	MCDRV_D2SRC_ADC0_OFF	\
+	(MCDRV_D2SRC_ADC0_L_OFF | MCDRV_D2SRC_ADC0_R_OFF)
+#define	MCDRV_D2SRC_ADC1_ON		0x00000400
+#define	MCDRV_D2SRC_ADC1_OFF		0x00000800
+#define	MCDRV_D2SRC_PDM0_L_ON		0x00001000
+#define	MCDRV_D2SRC_PDM0_L_OFF		0x00002000
+#define	MCDRV_D2SRC_PDM0_R_ON		0x00004000
+#define	MCDRV_D2SRC_PDM0_R_OFF		0x00008000
+#define MCDRV_D2SRC_PDM0_ON	\
+	(MCDRV_D2SRC_PDM0_L_ON | MCDRV_D2SRC_PDM0_R_ON)
+#define	MCDRV_D2SRC_PDM1_L_ON		0x00010000
+#define	MCDRV_D2SRC_PDM1_L_OFF		0x00020000
+#define	MCDRV_D2SRC_PDM1_R_ON		0x00040000
+#define	MCDRV_D2SRC_PDM1_R_OFF		0x00080000
+#define MCDRV_D2SRC_PDM1_ON	\
+	(MCDRV_D2SRC_PDM1_L_ON | MCDRV_D2SRC_PDM1_R_ON)
+#define	MCDRV_D2SRC_DAC0REF_ON		0x00100000
+#define	MCDRV_D2SRC_DAC0REF_OFF		0x00200000
+#define	MCDRV_D2SRC_DAC1REF_ON		0x00400000
+#define	MCDRV_D2SRC_DAC1REF_OFF		0x00800000
+
+#define	MCDRV_ASRC_DAC0_L_ON		0x00000001
+#define	MCDRV_ASRC_DAC0_L_OFF		0x00000002
+#define	MCDRV_ASRC_DAC0_R_ON		0x00000004
+#define	MCDRV_ASRC_DAC0_R_OFF		0x00000008
+#define	MCDRV_ASRC_DAC1_L_ON		0x00000010
+#define	MCDRV_ASRC_DAC1_L_OFF		0x00000020
+#define	MCDRV_ASRC_DAC1_R_ON		0x00000040
+#define	MCDRV_ASRC_DAC1_R_OFF		0x00000080
+#define	MCDRV_ASRC_MIC1_ON		0x00000100
+#define	MCDRV_ASRC_MIC1_OFF		0x00000200
+#define	MCDRV_ASRC_MIC2_ON		0x00000400
+#define	MCDRV_ASRC_MIC2_OFF		0x00000800
+#define	MCDRV_ASRC_MIC3_ON		0x00001000
+#define	MCDRV_ASRC_MIC3_OFF		0x00002000
+#define	MCDRV_ASRC_MIC4_ON		0x00004000
+#define	MCDRV_ASRC_MIC4_OFF		0x00008000
+#define MCDRV_ASRC_MIC_ALL_ON				\
+	(MCDRV_ASRC_MIC1_ON | MCDRV_ASRC_MIC2_ON |	\
+	 MCDRV_ASRC_MIC3_ON | MCDRV_ASRC_MIC4_ON)
+#define	MCDRV_ASRC_LINEIN1_L_ON		0x00010000
+#define	MCDRV_ASRC_LINEIN1_L_OFF	0x00020000
+#define	MCDRV_ASRC_LINEIN1_R_ON		0x00040000
+#define	MCDRV_ASRC_LINEIN1_R_OFF	0x00080000
+#define	MCDRV_ASRC_LINEIN1_M_ON		0x00100000
+#define	MCDRV_ASRC_LINEIN1_M_OFF	0x00200000
+#define MCDRV_ASRC_LINEIN1_ALL_ON				\
+	(MCDRV_ASRC_LINEIN1_L_ON | MCDRV_ASRC_LINEIN1_R_ON |	\
+	 MCDRV_ASRC_LINEIN1_M_ON)
+
+#define	MUSICOUT_PATH_CHANNELS		2
+#define	EXTOUT_PATH_CHANNELS		2
+#define	HIFIOUT_PATH_CHANNELS		1
+#define	VBOXMIXIN_PATH_CHANNELS		4
+#define	AE_PATH_CHANNELS		2
+#define	DAC0_PATH_CHANNELS		2
+#define	DAC1_PATH_CHANNELS		2
+#define	VOICEOUT_PATH_CHANNELS		1
+#define	VBOXIOIN_PATH_CHANNELS		1
+#define	VBOXHOSTIN_PATH_CHANNELS	1
+#define	HOSTOUT_PATH_CHANNELS		1
+#define	ADIF0_PATH_CHANNELS		2
+#define	ADIF1_PATH_CHANNELS		2
+#define	ADIF2_PATH_CHANNELS		2
+#define	ADC0_PATH_CHANNELS		2
+#define	ADC1_PATH_CHANNELS		1
+#define	SP_PATH_CHANNELS		2
+#define	HP_PATH_CHANNELS		2
+#define	RC_PATH_CHANNELS		1
+#define	LOUT1_PATH_CHANNELS		2
+#define	LOUT2_PATH_CHANNELS		2
+#define	BIAS_PATH_CHANNELS		4
+
+struct mcdrv_path_info {
+	u32 music_out[MUSICOUT_PATH_CHANNELS];
+	u32 ext_out[EXTOUT_PATH_CHANNELS];
+	u32 hifi_out[HIFIOUT_PATH_CHANNELS];
+	u32 vbox_mix_in[VBOXMIXIN_PATH_CHANNELS];
+	u32 ae0[AE_PATH_CHANNELS];
+	u32 ae1[AE_PATH_CHANNELS];
+	u32 ae2[AE_PATH_CHANNELS];
+	u32 ae3[AE_PATH_CHANNELS];
+	u32 dac0[DAC0_PATH_CHANNELS];
+	u32 dac1[DAC1_PATH_CHANNELS];
+	u32 voice_out[VOICEOUT_PATH_CHANNELS];
+	u32 vbox_io_in[VBOXIOIN_PATH_CHANNELS];
+	u32 vbox_host_in[VBOXHOSTIN_PATH_CHANNELS];
+	u32 host_out[HOSTOUT_PATH_CHANNELS];
+	u32 adif0[ADIF0_PATH_CHANNELS];
+	u32 adif1[ADIF1_PATH_CHANNELS];
+	u32 adif2[ADIF2_PATH_CHANNELS];
+	u32 adc0[ADC0_PATH_CHANNELS];
+	u32 adc1[ADC1_PATH_CHANNELS];
+	u32 sp[SP_PATH_CHANNELS];
+	u32 hp[HP_PATH_CHANNELS];
+	u32 rc[RC_PATH_CHANNELS];
+	u32 lout1[LOUT1_PATH_CHANNELS];
+	u32 lout2[LOUT2_PATH_CHANNELS];
+	u32 bias[BIAS_PATH_CHANNELS];
+};
+
+/*	set/get vol	*/
+#define	MCDRV_VOL_UPDATE		0x0001
+
+#define	MUSICIN_VOL_CHANNELS		2
+#define	EXTIN_VOL_CHANNELS		2
+#define	VOICEIN_VOL_CHANNELS		2
+#define	REFIN_VOL_CHANNELS		2
+#define	ADIF0IN_VOL_CHANNELS		2
+#define	ADIF1IN_VOL_CHANNELS		2
+#define	ADIF2IN_VOL_CHANNELS		2
+#define	MUSICOUT_VOL_CHANNELS		2
+#define	EXTOUT_VOL_CHANNELS		2
+#define	VOICEOUT_VOL_CHANNELS		2
+#define	REFOUT_VOL_CHANNELS		2
+#define	DAC0OUT_VOL_CHANNELS		2
+#define	DAC1OUT_VOL_CHANNELS		2
+#define	DPATH_VOL_CHANNELS		2
+#define	LINEIN1_VOL_CHANNELS		2
+#define	MIC1_VOL_CHANNELS		1
+#define	MIC2_VOL_CHANNELS		1
+#define	MIC3_VOL_CHANNELS		1
+#define	MIC4_VOL_CHANNELS		1
+#define	HP_VOL_CHANNELS			2
+#define	SP_VOL_CHANNELS			2
+#define	RC_VOL_CHANNELS			1
+#define	LINEOUT1_VOL_CHANNELS		2
+#define	LINEOUT2_VOL_CHANNELS		2
+#define	HPDET_VOL_CHANNELS		1
+
+struct mcdrv_vol_info {
+	s16 d_music_in[MUSICIN_VOL_CHANNELS];
+	s16 d_ext_in[EXTIN_VOL_CHANNELS];
+	s16 d_voice_in[VOICEIN_VOL_CHANNELS];
+	s16 d_ref_in[REFIN_VOL_CHANNELS];
+	s16 d_adif0_in[ADIF0IN_VOL_CHANNELS];
+	s16 d_adif1_in[ADIF1IN_VOL_CHANNELS];
+	s16 d_adif2_in[ADIF2IN_VOL_CHANNELS];
+	s16 d_music_out[MUSICOUT_VOL_CHANNELS];
+	s16 d_ext_out[EXTOUT_VOL_CHANNELS];
+	s16 d_voice_out[VOICEOUT_VOL_CHANNELS];
+	s16 d_ref_out[REFOUT_VOL_CHANNELS];
+	s16 d_dac0_out[DAC0OUT_VOL_CHANNELS];
+	s16 d_dac1_out[DAC1OUT_VOL_CHANNELS];
+	s16 d_dpath_da[DPATH_VOL_CHANNELS];
+	s16 d_dpath_ad[DPATH_VOL_CHANNELS];
+	s16 a_line_in1[LINEIN1_VOL_CHANNELS];
+	s16 a_mic1[MIC1_VOL_CHANNELS];
+	s16 a_mic2[MIC2_VOL_CHANNELS];
+	s16 a_mic3[MIC3_VOL_CHANNELS];
+	s16 a_mic4[MIC4_VOL_CHANNELS];
+	s16 a_hp[HP_VOL_CHANNELS];
+	s16 a_sp[SP_VOL_CHANNELS];
+	s16 a_rc[RC_VOL_CHANNELS];
+	s16 a_line_out1[LINEOUT1_VOL_CHANNELS];
+	s16 a_line_out2[LINEOUT2_VOL_CHANNELS];
+	s16 a_hp_det[HPDET_VOL_CHANNELS];
+};
+
+/*	set/get digitalio	*/
+#define	MCDRV_MUSIC_COM_UPDATE_FLAG	0x00000001U
+#define	MCDRV_MUSIC_DIR_UPDATE_FLAG	0x00000002U
+#define	MCDRV_MUSIC_DIT_UPDATE_FLAG	0x00000004U
+#define	MCDRV_EXT_COM_UPDATE_FLAG	0x00000008U
+#define	MCDRV_EXT_DIR_UPDATE_FLAG	0x00000010U
+#define	MCDRV_EXT_DIT_UPDATE_FLAG	0x00000020U
+#define	MCDRV_VOICE_COM_UPDATE_FLAG	0x00000040U
+#define	MCDRV_VOICE_DIR_UPDATE_FLAG	0x00000080U
+#define	MCDRV_VOICE_DIT_UPDATE_FLAG	0x00000100U
+#define	MCDRV_HIFI_COM_UPDATE_FLAG	0x00000200U
+#define	MCDRV_HIFI_DIR_UPDATE_FLAG	0x00000400U
+#define	MCDRV_HIFI_DIT_UPDATE_FLAG	0x00000800U
+#define	MCDRV_ALL_DIO_UPDATE_FLAG	0x00000fffU
+
+/*	mcdrv_dio_common master_slave setting	*/
+#define	MCDRV_DIO_SLAVE			0
+#define	MCDRV_DIO_MASTER		1
+
+/*	mcdrv_dio_common bDigitalAutoFs setting	*/
+#define	MCDRV_AUTOFS_OFF		0
+#define	MCDRV_AUTOFS_ON			1
+
+/*	mcdrv_dio_common fs setting	*/
+#define	MCDRV_FS_48000			0
+#define	MCDRV_FS_44100			1
+#define	MCDRV_FS_32000			2
+#define	MCDRV_FS_NONE1			3
+#define	MCDRV_FS_24000			4
+#define	MCDRV_FS_22050			5
+#define	MCDRV_FS_16000			6
+#define	MCDRV_FS_NONE2			7
+#define	MCDRV_FS_12000			8
+#define	MCDRV_FS_11025			9
+#define	MCDRV_FS_8000			10
+#define	MCDRV_FS_NONE3			11
+#define	MCDRV_FS_192000			12
+#define	MCDRV_FS_96000			13
+#define	MCDRV_FS_LAST			MCDRV_FS_96000
+
+/*	mcdrv_dio_common bck_fs setting	*/
+#define	MCDRV_BCKFS_64			0
+#define	MCDRV_BCKFS_48			1
+#define	MCDRV_BCKFS_32			2
+#define	MCDRV_BCKFS_NONE1		3
+#define	MCDRV_BCKFS_512			4
+#define	MCDRV_BCKFS_256			5
+#define	MCDRV_BCKFS_192			6
+#define	MCDRV_BCKFS_128			7
+#define	MCDRV_BCKFS_96			8
+#define	MCDRV_BCKFS_24			9
+#define	MCDRV_BCKFS_16			10
+#define	MCDRV_BCKFS_8			11
+#define	MCDRV_BCKFS_NONE2		12
+#define	MCDRV_BCKFS_NONE3		13
+#define	MCDRV_BCKFS_NONE4		14
+#define	MCDRV_BCKFS_SLAVE		15
+#define	MCDRV_BCKFS_LAST		MCDRV_BCKFS_SLAVE
+
+/*	mcdrv_dio_common interface setting	*/
+#define	MCDRV_DIO_DA			0
+#define	MCDRV_DIO_PCM			1
+
+/*	mcdrv_dio_common bck_invert setting	*/
+#define	MCDRV_BCLK_NORMAL		0
+#define	MCDRV_BCLK_INVERT		1
+
+/*	mcdrv_dio_common src_thru setting	*/
+#define	MCDRV_SRC_NOT_THRU		0
+#define	MCDRV_SRC_THRU			1
+
+/*	mcdrv_dio_common pcm_hiz_transition setting	*/
+#define	MCDRV_PCMHIZTRANS_FALLING	0
+#define	MCDRV_PCMHIZTRANS_RISING	1
+
+/*	mcdrv_dio_common pcm_frame setting	*/
+#define	MCDRV_PCM_SHORTFRAME		0
+#define	MCDRV_PCM_LONGFRAME		1
+
+struct mcdrv_dio_common {
+	bool master_slave;
+	bool auto_fs;
+	u8 fs;
+	u8 bck_fs;
+	bool interface;
+	bool bck_invert;
+	bool src_thru;
+	bool pcm_hiz_transition;
+	bool pcm_frame;
+	u8 pcm_high_period;
+};
+
+/*	mcdrv_da_format bit_sel setting	*/
+#define	MCDRV_BITSEL_16			0
+#define	MCDRV_BITSEL_20			1
+#define	MCDRV_BITSEL_24			2
+#define	MCDRV_BITSEL_32			3
+#define	MCDRV_BITSEL_LAST		MCDRV_BITSEL_32
+
+/*	mcdrv_da_format mode setting	*/
+#define	MCDRV_DAMODE_HEADALIGN		0
+#define	MCDRV_DAMODE_I2S		1
+#define	MCDRV_DAMODE_TAILALIGN		2
+#define	MCDRV_DAMODE_LAST		MCDRV_DAMODE_TAILALIGN
+
+struct mcdrv_da_format {
+	u8 bit_sel;
+	u8 mode;
+};
+
+/*	mcdrv_pcm_format mono setting	*/
+#define	MCDRV_PCM_STEREO		0
+#define	MCDRV_PCM_MONO			1
+
+/*	mcdrv_pcm_format order setting	*/
+#define	MCDRV_PCM_MSB_FIRST		0
+#define	MCDRV_PCM_LSB_FIRST		1
+
+/*	mcdrv_pcm_format law setting	*/
+#define	MCDRV_PCM_LINEAR		0
+#define	MCDRV_PCM_ALAW			1
+#define	MCDRV_PCM_MULAW			2
+#define	MCDRV_PCM_LAST			MCDRV_PCM_MULAW
+
+/*	mcdrv_pcm_format bit_sel setting	*/
+#define	MCDRV_PCM_BITSEL_8		0
+#define	MCDRV_PCM_BITSEL_16		1
+#define	MCDRV_PCM_BITSEL_24		2
+#define	MCDRV_PCM_BITSEL_LAST		MCDRV_PCM_BITSEL_24
+
+struct mcdrv_pcm_format {
+	bool mono;
+	bool order;
+	u8 law;
+	u8 bit_sel;
+};
+
+struct mcdrv_dio_dir {
+	struct mcdrv_da_format da_format;
+	struct mcdrv_pcm_format pcm_format;
+};
+
+/*	mcdrv_dio_dit st_mode setting	*/
+#define	MCDRV_STMODE_ZERO		0
+#define	MCDRV_STMODE_HOLD		1
+
+/*	mcdrv_dio_dit edge setting	*/
+#define	MCDRV_SDOUT_NORMAL		0
+#define	MCDRV_SDOUT_AHEAD		1
+
+struct mcdrv_dio_dit {
+	bool st_mode;
+	bool edge;
+	struct mcdrv_da_format da_format;
+	struct mcdrv_pcm_format pcm_format;
+};
+
+struct mcdrv_dio_port {
+	struct mcdrv_dio_common dio_common;
+	struct mcdrv_dio_dir dir;
+	struct mcdrv_dio_dit dit;
+};
+
+struct mcdrv_dio_info {
+	struct mcdrv_dio_port port[4];
+};
+
+/*	set/get digitalio_path	*/
+#define	MCDRV_PHYS0_UPDATE_FLAG		0x00000001U
+#define	MCDRV_PHYS1_UPDATE_FLAG		0x00000002U
+#define	MCDRV_PHYS2_UPDATE_FLAG		0x00000004U
+#define	MCDRV_PHYS3_UPDATE_FLAG		0x00000008U
+#define	MCDRV_MUSICNUM_UPDATE_FLAG	0x00000010U
+#define	MCDRV_DIR0SLOT_UPDATE_FLAG	0x00000020U
+#define	MCDRV_DIR1SLOT_UPDATE_FLAG	0x00000040U
+#define	MCDRV_DIR2SLOT_UPDATE_FLAG	0x00000080U
+#define	MCDRV_DIT0SLOT_UPDATE_FLAG	0x00000100U
+#define	MCDRV_DIT1SLOT_UPDATE_FLAG	0x00000200U
+#define	MCDRV_DIT2SLOT_UPDATE_FLAG	0x00000400U
+
+/*	mcdrv_dio_path_info phys_port setting	*/
+#define	MCDRV_PHYSPORT_DIO0		0
+#define	MCDRV_PHYSPORT_DIO1		1
+#define	MCDRV_PHYSPORT_DIO2		2
+#define	MCDRV_PHYSPORT_NONE		3
+#define	MCDRV_PHYSPORT_SLIM0		4
+#define	MCDRV_PHYSPORT_SLIM1		5
+#define	MCDRV_PHYSPORT_SLIM2		6
+#define	MCDRV_PHYSPORT_LAST		MCDRV_PHYSPORT_SLIM2
+
+/*	mcdrv_dio_path_info music_ch setting	*/
+#define	MCDRV_MUSIC_2CH			0
+#define	MCDRV_MUSIC_4CH			1
+#define	MCDRV_MUSIC_6CH			2
+#define	MCDRV_MUSIC_LAST		MCDRV_MUSIC_6CH
+
+struct mcdrv_dio_path_info {
+	u8 phys_port[4];
+	u8 music_ch;
+	u8 music_rslot[3];
+	u8 music_tslot[3];
+};
+
+/*	set/get swap	*/
+#define	MCDRV_SWAP_ADIF0_UPDATE_FLAG		0x00000001U
+#define	MCDRV_SWAP_ADIF1_UPDATE_FLAG		0x00000002U
+#define	MCDRV_SWAP_ADIF2_UPDATE_FLAG		0x00000004U
+#define	MCDRV_SWAP_DAC0_UPDATE_FLAG		0x00000008U
+#define	MCDRV_SWAP_DAC1_UPDATE_FLAG		0x00000010U
+#define	MCDRV_SWAP_MUSICIN0_UPDATE_FLAG		0x00000020U
+#define	MCDRV_SWAP_MUSICIN1_UPDATE_FLAG		0x00000040U
+#define	MCDRV_SWAP_MUSICIN2_UPDATE_FLAG		0x00000080U
+#define	MCDRV_SWAP_EXTIN_UPDATE_FLAG		0x00000100U
+#define	MCDRV_SWAP_VOICEIN_UPDATE_FLAG		0x00000200U
+#define	MCDRV_SWAP_HIFIIN_UPDATE_FLAG		0x00000400U
+#define	MCDRV_SWAP_MUSICOUT0_UPDATE_FLAG	0x00000800U
+#define	MCDRV_SWAP_MUSICOUT1_UPDATE_FLAG	0x00001000U
+#define	MCDRV_SWAP_MUSICOUT2_UPDATE_FLAG	0x00002000U
+#define	MCDRV_SWAP_EXTOUT_UPDATE_FLAG		0x00004000U
+#define	MCDRV_SWAP_VOICEOUT_UPDATE_FLAG		0x00008000U
+#define	MCDRV_SWAP_HIFIOUT_UPDATE_FLAG		0x00010000U
+#define	MCDRV_SWAP_ALL_UPDATE_FLAG		0x0001ffffU
+
+/*	mcdrv_swap_info adif/dac setting	*/
+#define	MCDRV_SWAP_NORMAL		0
+#define	MCDRV_SWAP_SWAP			1
+#define	MCDRV_SWAP_MUTE			2
+#define	MCDRV_SWAP_CENTER		3
+#define	MCDRV_SWAP_MIX			4
+#define	MCDRV_SWAP_MONOMIX		5
+#define	MCDRV_SWAP_BOTHL		6
+#define	MCDRV_SWAP_BOTHR		7
+#define	MCDRV_SWAP_LAST			MCDRV_SWAP_BOTHR
+
+/*	mcdrv_swap_info
+	music_in/ext_in/voice_in/hifi_in/music_out/ext_out/voice_out/hifi_out
+	setting	*/
+#define	MCDRV_SWSWAP_NORMAL		0
+#define	MCDRV_SWSWAP_BOTH1		1
+#define	MCDRV_SWSWAP_BOTH0		2
+#define	MCDRV_SWSWAP_SWAP		3
+#define	MCDRV_SWSWAP_LAST		MCDRV_SWSWAP_SWAP
+
+struct mcdrv_swap_info {
+	u8 adif0;
+	u8 adif1;
+	u8 adif2;
+	u8 dac0;
+	u8 dac1;
+	u8 music_in0;
+	u8 music_in1;
+	u8 music_in2;
+	u8 ext_in;
+	u8 voice_in;
+	u8 hifi_in;
+	u8 music_out0;
+	u8 music_out1;
+	u8 music_out2;
+	u8 ext_out;
+	u8 voice_out;
+	u8 hifi_out;
+};
+
+/*	get transition	*/
+#define	MCDRV_DSPTYPE_FDSP		0
+#define	MCDRV_DSPTYPE_BDSP		1
+
+/*	register dsp cb	*/
+#define	MCDRV_AE_EVT_STOP		1
+#define	MCDRV_AE_EVT_APPSTOP		2
+#define	MCDRV_AE_EVT_APPREQ		3
+#define	MCDRV_AE_EVT_COEFDONE		4
+#define	MCDRV_AE_EVT_ERROR		5
+#define	MCDRV_CDSP_EVT_ERROR		11
+#define	MCDRV_CDSP_EVT_PARAM		12
+#define	MCDRV_CDSP_ENV_END		13
+#define	MCDRV_CDSP_EVT_FIFO		14
+#define	MCDRV_EDSP_EVT_E2PARAM		21
+
+/*	set/get hsdet	*/
+#define	MCDRV_ENPLUGDET_UPDATE_FLAG	0x00000001U
+#define	MCDRV_ENPLUGDETDB_UPDATE_FLAG	0x00000002U
+#define	MCDRV_ENDLYKEYOFF_UPDATE_FLAG	0x00000004U
+#define	MCDRV_ENDLYKEYON_UPDATE_FLAG	0x00000008U
+#define	MCDRV_ENMICDET_UPDATE_FLAG	0x00000010U
+#define	MCDRV_ENKEYOFF_UPDATE_FLAG	0x00000020U
+#define	MCDRV_ENKEYON_UPDATE_FLAG	0x00000040U
+#define	MCDRV_HSDETDBNC_UPDATE_FLAG	0x00000080U
+#define	MCDRV_KEYOFFMTIM_UPDATE_FLAG	0x00000100U
+#define	MCDRV_KEYONMTIM_UPDATE_FLAG	0x00000200U
+#define	MCDRV_KEY0OFFDLYTIM_UPDATE_FLAG	0x00000400U
+#define	MCDRV_KEY1OFFDLYTIM_UPDATE_FLAG	0x00000800U
+#define	MCDRV_KEY2OFFDLYTIM_UPDATE_FLAG	0x00001000U
+#define	MCDRV_KEY0ONDLYTIM_UPDATE_FLAG	0x00002000U
+#define	MCDRV_KEY1ONDLYTIM_UPDATE_FLAG	0x00004000U
+#define	MCDRV_KEY2ONDLYTIM_UPDATE_FLAG	0x00008000U
+#define	MCDRV_KEY0ONDLYTIM2_UPDATE_FLAG	0x00010000U
+#define	MCDRV_KEY1ONDLYTIM2_UPDATE_FLAG	0x00020000U
+#define	MCDRV_KEY2ONDLYTIM2_UPDATE_FLAG	0x00040000U
+#define	MCDRV_IRQTYPE_UPDATE_FLAG	0x00080000U
+#define	MCDRV_DETINV_UPDATE_FLAG	0x00100000U
+#define	MCDRV_HSDETMODE_UPDATE_FLAG	0x00200000U
+#define	MCDRV_SPERIOD_UPDATE_FLAG	0x00400000U
+#define	MCDRV_LPERIOD_UPDATE_FLAG	0x00800000U
+#define	MCDRV_DBNCNUMPLUG_UPDATE_FLAG	0x01000000U
+#define	MCDRV_DBNCNUMMIC_UPDATE_FLAG	0x02000000U
+#define	MCDRV_DBNCNUMKEY_UPDATE_FLAG	0x04000000U
+#define	MCDRV_SGNL_UPDATE_FLAG		0x08000000U
+#define	MCDRV_IMPSEL_UPDATE_FLAG	0x10000000U
+#define	MCDRV_DLYIRQSTOP_UPDATE_FLAG	0x20000000U
+#define	MCDRV_CBFUNC_UPDATE_FLAG	0x40000000U
+
+/*	mcdrv_hsdet_info en_plug_det setting	*/
+#define	MCDRV_PLUGDET_DISABLE		0
+#define	MCDRV_PLUGDET_ENABLE		1
+
+/*	mcdrv_hsdet_info en_plug_det_db setting	*/
+#define	MCDRV_PLUGDETDB_DISABLE		0
+#define	MCDRV_PLUGDETDB_DET_ENABLE	1
+#define	MCDRV_PLUGDETDB_UNDET_ENABLE	2
+#define	MCDRV_PLUGDETDB_BOTH_ENABLE	3
+#define	MCDRV_PLUGDETDB_LAST		MCDRV_PLUGDETDB_BOTH_ENABLE
+
+/*	mcdrv_hsdet_info
+	en_dly_key_off/en_dly_key_on/en_key_off/en_key_on setting	*/
+#define	MCDRV_KEYEN_D_D_D		0
+#define	MCDRV_KEYEN_D_D_E		1
+#define	MCDRV_KEYEN_D_E_D		2
+#define	MCDRV_KEYEN_D_E_E		3
+#define	MCDRV_KEYEN_E_D_D		4
+#define	MCDRV_KEYEN_E_D_E		5
+#define	MCDRV_KEYEN_E_E_D		6
+#define	MCDRV_KEYEN_E_E_E		7
+#define	MCDRV_KEYEN_LAST		MCDRV_KEYEN_E_E_E
+
+/*	mcdrv_hsdet_info en_mic_det setting	*/
+#define	MCDRV_MICDET_DISABLE		0
+#define	MCDRV_MICDET_ENABLE		1
+
+/*	mcdrv_hsdet_info hs_det_dbnc setting	*/
+#define	MCDRV_DETDBNC_27		0
+#define	MCDRV_DETDBNC_55		1
+#define	MCDRV_DETDBNC_109		2
+#define	MCDRV_DETDBNC_219		3
+#define	MCDRV_DETDBNC_438		4
+#define	MCDRV_DETDBNC_875		5
+#define	MCDRV_DETDBNC_1313		6
+#define	MCDRV_DETDBNC_1750		7
+#define	MCDRV_DETDBNC_LAST		MCDRV_DETDBNC_1750
+
+/*	mcdrv_hsdet_info key_off_mtim setting	*/
+#define	MCDRV_KEYOFF_MTIM_63		0
+#define	MCDRV_KEYOFF_MTIM_16		1
+
+/*	mcdrv_hsdet_info key_on_mtim setting	*/
+#define	MCDRV_KEYON_MTIM_63		0
+#define	MCDRV_KEYON_MTIM_250		1
+
+/*	mcdrv_hsdet_info key_off_dly_tim setting	*/
+#define	MC_DRV_KEYOFFDLYTIM_MAX		15
+
+/*	mcdrv_hsdet_info key_on_dly_tim setting	*/
+#define	MC_DRV_KEYONDLYTIM_MAX		15
+
+/*	mcdrv_hsdet_info key_on_dly_tim2 setting	*/
+#define	MC_DRV_KEYONDLYTIM2_MAX		15
+
+/*	mcdrv_hsdet_info irq_type setting	*/
+#define	MCDRV_IRQTYPE_NORMAL		0
+#define	MCDRV_IRQTYPE_REF		1
+#define MCDRV_IRQTYPE_EX		2
+#define MCDRV_IRQTYPE_LAST		MCDRV_IRQTYPE_EX
+
+/*	mcdrv_hsdet_info det_in_inv setting	*/
+#define	MCDRV_DET_IN_NORMAL		0
+#define	MCDRV_DET_IN_INV		1
+#define MCDRV_DET_IN_NORMAL_NORMAL	4
+#define MCDRV_DET_IN_INV_NORMAL		5
+#define MCDRV_DET_IN_NORMAL_INV		6
+#define MCDRV_DET_IN_INV_INV		7
+#define MCDRV_DET_IN_LAST		MCDRV_DET_IN_INV_INV
+
+/*	mcdrv_hsdet_info hs_det_mode setting	*/
+#define	MCDRV_HSDET_MODE_DETIN_A	4
+#define	MCDRV_HSDET_MODE_DETIN_B	6
+
+/*	mcdrv_hsdet_info speriod setting	*/
+#define	MCDRV_SPERIOD_244		0
+#define	MCDRV_SPERIOD_488		1
+#define	MCDRV_SPERIOD_977		2
+#define	MCDRV_SPERIOD_1953		3
+#define	MCDRV_SPERIOD_3906		4
+#define	MCDRV_SPERIOD_7813		5
+#define	MCDRV_SPERIOD_15625		6
+#define	MCDRV_SPERIOD_31250		7
+#define	MCDRV_SPERIOD_LAST		MCDRV_SPERIOD_31250
+
+/*	mcdrv_hsdet_info lperiod setting	*/
+#define	MCDRV_LPERIOD_3906		0
+#define	MCDRV_LPERIOD_62500		1
+#define	MCDRV_LPERIOD_125000		2
+#define	MCDRV_LPERIOD_250000		3
+#define	MCDRV_LPERIOD_LAST		MCDRV_LPERIOD_250000
+
+/*	mcdrv_hsdet_info dbnc_num setting	*/
+#define	MCDRV_DBNC_NUM_2		0
+#define	MCDRV_DBNC_NUM_3		1
+#define	MCDRV_DBNC_NUM_4		2
+#define	MCDRV_DBNC_NUM_7		3
+#define	MCDRV_DBNC_NUM_LAST		MCDRV_DBNC_NUM_7
+
+/*	mcdrv_hsdet_info sgnl_period setting	*/
+#define	MCDRV_SGNLPERIOD_61		0
+#define	MCDRV_SGNLPERIOD_79		1
+#define	MCDRV_SGNLPERIOD_97		2
+#define	MCDRV_SGNLPERIOD_151		3
+#define	MCDRV_SGNLPERIOD_LAST		MCDRV_SGNLPERIOD_151
+
+/*	mcdrv_hsdet_info sgnl_num setting	*/
+#define	MCDRV_SGNLNUM_1			0
+#define	MCDRV_SGNLNUM_4			1
+#define	MCDRV_SGNLNUM_6			2
+#define	MCDRV_SGNLNUM_8			3
+#define	MCDRV_SGNLNUM_LAST		MCDRV_SGNLNUM_8
+#define MCDRV_SGNLNUM_NONE		0xff
+
+/*	mcdrv_hsdet_info sgnl_peak setting	*/
+#define	MCDRV_SGNLPEAK_500		0
+#define	MCDRV_SGNLPEAK_730		1
+#define	MCDRV_SGNLPEAK_960		2
+#define	MCDRV_SGNLPEAK_1182		3
+#define	MCDRV_SGNLPEAK_LAST		MCDRV_SGNLPEAK_1182
+
+/*	mcdrv_hsdet_info imp_sel setting	*/
+#define	MCDRV_IMPSEL_MOSTFREQ		0
+#define	MCDRV_IMPSEL_MIN		1
+
+/*	mcdrv_hsdet_info dly_irq_stop setting	*/
+#define	MCDRV_DLYIRQ_DONTCARE		0
+#define	MCDRV_DLYIRQ_STOP		1
+
+#define	MCDRV_HSDET_EVT_PLUGDET_DB_FLAG		0x00000001
+#define	MCDRV_HSDET_EVT_PLUGUNDET_DB_FLAG	0x00000002
+#define	MCDRV_HSDET_EVT_PLUGDET_FLAG		0x00000080
+#define	MCDRV_HSDET_EVT_DLYKEYON0_FLAG		0x00000100
+#define	MCDRV_HSDET_EVT_DLYKEYON1_FLAG		0x00000200
+#define	MCDRV_HSDET_EVT_DLYKEYON2_FLAG		0x00000400
+#define	MCDRV_HSDET_EVT_DLYKEYOFF0_FLAG		0x00000800
+#define	MCDRV_HSDET_EVT_DLYKEYOFF1_FLAG		0x00001000
+#define	MCDRV_HSDET_EVT_DLYKEYOFF2_FLAG		0x00002000
+#define	MCDRV_HSDET_EVT_KEYON0_FLAG		0x00010000
+#define	MCDRV_HSDET_EVT_KEYON1_FLAG		0x00020000
+#define	MCDRV_HSDET_EVT_KEYON2_FLAG		0x00040000
+#define	MCDRV_HSDET_EVT_KEYOFF0_FLAG		0x00080000
+#define	MCDRV_HSDET_EVT_KEYOFF1_FLAG		0x00100000
+#define	MCDRV_HSDET_EVT_KEYOFF2_FLAG		0x00200000
+#define	MCDRV_HSDET_EVT_MICDET_FLAG		0x00400000
+#define	MCDRV_HSDET_EVT_SENSEFIN_FLAG		0x80000000
+
+struct mcdrv_hsdet_res {
+	u8 key_cnt0;
+	u8 key_cnt1;
+	u8 key_cnt2;
+	u8 plug_rev;
+	u8 hp_imp_class;
+	u16 hp_imp;
+};
+
+typedef void (*callback_function) (u32 flags, struct mcdrv_hsdet_res *res);
+
+struct mcdrv_hsdet_info {
+	bool en_plug_det;
+	u8 en_plug_det_db;
+	u8 en_dly_key_off;
+	u8 en_dly_key_on;
+	bool en_mic_det;
+	u8 en_key_off;
+	u8 en_key_on;
+	u8 hs_det_dbnc;
+	bool key_off_mtim;
+	bool key_on_mtim;
+	u8 key0_off_dly_tim;
+	u8 key1_off_dly_tim;
+	u8 key2_off_dly_tim;
+	u8 key0_on_dly_tim;
+	u8 key1_on_dly_tim;
+	u8 key2_on_dly_tim;
+	u8 key0_on_dly_tim2;
+	u8 key1_on_dly_tim2;
+	u8 key2_on_dly_tim2;
+	u8 irq_type;
+	u8 plug_det_db_irq_type;
+	u8 plug_undet_db_irq_type;
+	u8 mic_det_irq_type;
+	u8 plug_det_irq_type;
+	u8 key0_on_irq_type;
+	u8 key1_on_irq_type;
+	u8 key2_on_irq_type;
+	u8 key0_off_irq_type;
+	u8 key1_off_irq_type;
+	u8 key2_off_irq_type;
+	u8 det_in_inv;
+	u8 hs_det_mode;
+	u8 speriod;
+	u8 lperiod;
+	u8 dbnc_num_plug;
+	u8 dbnc_num_mic;
+	u8 dbnc_num_key;
+	u8 sgnl_period;
+	u8 sgnl_num;
+	u8 sgnl_peak;
+	bool imp_sel;
+	bool dly_irq_stop;
+	callback_function cbfunc;
+};
+
+int mc_init(struct mcdrv_dev_info *info);
+int mc_term(void);
+int mc_do_irq(void);
+int mc_control(unsigned int cmd, unsigned long arg, unsigned int flags);
+int mc_version_id_get(void);
+
+#endif /* _MCDRIVER_H */
-- 
1.7.9.5



More information about the Alsa-devel mailing list