[alsa-devel] [PATCH 12/19] ALSA: ymu831: add resource control driver
Yoichi Yuasa
yuasa at linux-mips.org
Wed Jan 16 09:38:09 CET 2013
Signed-off-by: Yoichi Yuasa <yuasa at linux-mips.org>
---
sound/soc/codecs/ymu831/Makefile | 3 +-
sound/soc/codecs/ymu831/mcresctrl.c | 4062 +++++++++++++++++++++++++++++++++++
sound/soc/codecs/ymu831/mcresctrl.h | 394 ++++
3 files changed, 4458 insertions(+), 1 deletion(-)
create mode 100644 sound/soc/codecs/ymu831/mcresctrl.c
create mode 100644 sound/soc/codecs/ymu831/mcresctrl.h
diff --git a/sound/soc/codecs/ymu831/Makefile b/sound/soc/codecs/ymu831/Makefile
index 820dec7..3fd53fe 100644
--- a/sound/soc/codecs/ymu831/Makefile
+++ b/sound/soc/codecs/ymu831/Makefile
@@ -6,6 +6,7 @@ snd-soc-ymu831-objs := \
mcedspdrv.o \
mcfdspdrv.o \
mcpacking.o \
- mcparser.o
+ mcparser.o \
+ mcresctrl.o
obj-$(CONFIG_SND_SOC_YMU831) += snd-soc-ymu831.o
diff --git a/sound/soc/codecs/ymu831/mcresctrl.c b/sound/soc/codecs/ymu831/mcresctrl.c
new file mode 100644
index 0000000..9a7787e
--- /dev/null
+++ b/sound/soc/codecs/ymu831/mcresctrl.c
@@ -0,0 +1,4062 @@
+/****************************************************************************
+ *
+ * Copyright(c) 2012 Yamaha Corporation. All rights reserved.
+ *
+ * Module : mcresctrl.c
+ * Description : MC resource control driver
+ * Version : 1.0.1 Dec 18 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/bug.h>
+#include <linux/errno.h>
+#include <linux/delay.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/types.h>
+
+#include "mcdefs.h"
+#include "mcdevif.h"
+#include "mcdriver.h"
+#include "mcresctrl.h"
+
+#define BURST_WRITE_ENABLE 0x01
+
+#define D1SRC_ALL_OFF (MCDRV_D1SRC_MUSICIN_OFF \
+ | MCDRV_D1SRC_EXTIN_OFF \
+ | MCDRV_D1SRC_VBOXOUT_OFF \
+ | MCDRV_D1SRC_VBOXREFOUT_OFF \
+ | MCDRV_D1SRC_AE0_OFF \
+ | MCDRV_D1SRC_AE1_OFF \
+ | MCDRV_D1SRC_AE2_OFF \
+ | MCDRV_D1SRC_AE3_OFF \
+ | MCDRV_D1SRC_ADIF0_OFF \
+ | MCDRV_D1SRC_ADIF1_OFF \
+ | MCDRV_D1SRC_ADIF2_OFF \
+ | MCDRV_D1SRC_HIFIIN_OFF)
+#define D2SRC_ALL_OFF (MCDRV_D2SRC_VOICEIN_OFF \
+ | MCDRV_D2SRC_VBOXIOOUT_OFF \
+ | MCDRV_D2SRC_VBOXHOSTOUT_OFF \
+ | MCDRV_D2SRC_ADC0_L_OFF \
+ | MCDRV_D2SRC_ADC0_R_OFF \
+ | MCDRV_D2SRC_ADC1_OFF \
+ | MCDRV_D2SRC_PDM0_L_OFF \
+ | MCDRV_D2SRC_PDM0_R_OFF \
+ | MCDRV_D2SRC_PDM1_L_OFF \
+ | MCDRV_D2SRC_PDM1_R_OFF \
+ | MCDRV_D2SRC_DAC0REF_OFF \
+ | MCDRV_D2SRC_DAC1REF_OFF)
+
+#define ASRC_ALL_OFF (MCDRV_ASRC_DAC0_L_OFF \
+ | MCDRV_ASRC_DAC0_R_OFF \
+ | MCDRV_ASRC_DAC1_L_OFF \
+ | MCDRV_ASRC_DAC1_R_OFF \
+ | MCDRV_ASRC_MIC1_OFF \
+ | MCDRV_ASRC_MIC2_OFF \
+ | MCDRV_ASRC_MIC3_OFF \
+ | MCDRV_ASRC_MIC4_OFF \
+ | MCDRV_ASRC_LINEIN1_L_OFF \
+ | MCDRV_ASRC_LINEIN1_R_OFF \
+ | MCDRV_ASRC_LINEIN1_M_OFF)
+
+/* control packet for serial host interface */
+#define MCDRV_MAX_CTRL_DATA_NUM (MCDRV_MAX_PACKETS * 4)
+
+struct mcdrv_packet {
+ u8 data[MCDRV_MAX_CTRL_DATA_NUM];
+ u16 data_size;
+};
+
+/* Register available num */
+#define MCDRV_REG_NUM_IF 59
+#define MCDRV_REG_NUM_A 68
+#define MCDRV_REG_NUM_MA 85
+#define MCDRV_REG_NUM_MB 86
+#define MCDRV_REG_NUM_B 72
+#define MCDRV_REG_NUM_E 101
+#define MCDRV_REG_NUM_C 160
+#define MCDRV_REG_NUM_F 128
+#define MCDRV_REG_NUM_ANA 116
+#define MCDRV_REG_NUM_CD 53
+
+struct mcdrv_info {
+ u8 id;
+ enum mcdrv_dev_id device_id;
+ enum mcdrv_state state;
+
+ u8 if_registers[MCDRV_REG_NUM_IF];
+ u8 a_registers[MCDRV_REG_NUM_A];
+ u8 ma_registers[MCDRV_REG_NUM_MA];
+ u8 mb_registers[MCDRV_REG_NUM_MB];
+ u8 b_registers[MCDRV_REG_NUM_B];
+ u8 e_registers[MCDRV_REG_NUM_E];
+ u8 c_registers[MCDRV_REG_NUM_C];
+ u8 f_registers[MCDRV_REG_NUM_F];
+ u8 ana_registers[MCDRV_REG_NUM_ANA];
+ u8 cd_registers[MCDRV_REG_NUM_CD];
+
+ struct mcdrv_dev_info dev_info;
+ struct mcdrv_path_info path_info;
+ struct mcdrv_path_info path_info_virtual;
+ struct mcdrv_vol_info vol_info;
+ struct mcdrv_dio_info dio_info;
+ struct mcdrv_dio_path_info dio_path_info;
+ struct mcdrv_swap_info swap_info;
+ struct mcdrv_hsdet_info hsdet_info;
+ struct mcdrv_aec_info aec_info;
+ struct mcdrv_gp_mode gp_mode;
+
+ u8 clk;
+ u8 clk_sel;
+ u8 eclk_sel;
+ u8 plug_det_db;
+
+ struct mcdrv_packet packet;
+ u16 slave_addr;
+ u16 type;
+ u16 addr;
+ u16 data_count;
+ u16 prev_addr_index;
+};
+
+static struct mcdrv_info mc_info = {
+ .device_id = MCDRV_DEV_ID_UNKNOWN,
+ .state = MCDRV_STATE_NOTINIT,
+};
+
+/* register next address */
+static const u16 mc_next_addr_list[256] = {
+ 0, 1, 2, 3, 4, 5, 6, 7,
+ 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23,
+ 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39,
+ 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55,
+ 56, 57, 58, 59, 60, 61, 62, 63,
+ 64, 65, 66, 67, 68, 69, 70, 71,
+ 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87,
+ 88, 89, 90, 91, 92, 93, 94, 95,
+ 96, 97, 98, 99, 100, 101, 102, 103,
+ 104, 105, 106, 107, 108, 109, 110, 111,
+ 112, 113, 114, 115, 116, 117, 118, 119,
+ 120, 121, 122, 123, 124, 125, 126, 127,
+ 128, 129, 130, 131, 132, 133, 134, 135,
+ 136, 137, 138, 139, 140, 141, 142, 143,
+ 144, 145, 146, 147, 148, 149, 150, 151,
+ 152, 153, 154, 155, 156, 157, 158, 159,
+ 160, 161, 162, 163, 164, 165, 166, 167,
+ 168, 169, 170, 171, 172, 173, 174, 175,
+ 176, 177, 178, 179, 180, 181, 182, 183,
+ 184, 185, 186, 187, 188, 189, 190, 191,
+ 192, 193, 194, 195, 196, 197, 198, 199,
+ 200, 201, 202, 203, 204, 205, 206, 207,
+ 208, 209, 210, 211, 212, 213, 214, 215,
+ 216, 217, 218, 219, 220, 221, 222, 223,
+ 224, 225, 226, 227, 228, 229, 230, 231,
+ 232, 233, 234, 235, 236, 237, 238, 239,
+ 240, 241, 242, 243, 244, 245, 246, 247,
+ 248, 249, 250, 251, 252, 253, 254, 255
+};
+
+static const u16 mc_next_addr_list_inc[256] = {
+ 1, 2, 3, 4, 5, 6, 7, 8,
+ 9, 10, 11, 12, 13, 14, 15, 16,
+ 17, 18, 19, 20, 21, 22, 23, 24,
+ 25, 26, 27, 28, 29, 30, 31, 32,
+ 33, 34, 35, 36, 37, 38, 39, 40,
+ 41, 42, 43, 44, 45, 46, 47, 48,
+ 49, 50, 51, 52, 53, 54, 55, 56,
+ 57, 58, 59, 60, 61, 62, 63, 64,
+ 65, 66, 67, 68, 69, 70, 71, 72,
+ 73, 74, 75, 76, 77, 78, 79, 80,
+ 81, 82, 83, 84, 85, 86, 87, 88,
+ 89, 90, 91, 92, 93, 94, 95, 96,
+ 97, 98, 99, 100, 101, 102, 103, 104,
+ 105, 106, 107, 108, 109, 110, 111, 112,
+ 113, 114, 115, 116, 117, 118, 119, 120,
+ 121, 122, 123, 124, 125, 126, 127, 128,
+ 129, 130, 131, 132, 133, 134, 135, 136,
+ 137, 138, 139, 140, 141, 142, 143, 144,
+ 145, 146, 147, 148, 149, 150, 151, 152,
+ 153, 154, 155, 156, 157, 158, 159, 160,
+ 161, 162, 163, 164, 165, 166, 167, 168,
+ 169, 170, 171, 172, 173, 174, 175, 176,
+ 177, 178, 179, 180, 181, 182, 183, 184,
+ 185, 186, 187, 188, 189, 190, 191, 192,
+ 193, 194, 195, 196, 197, 198, 199, 200,
+ 201, 202, 203, 204, 205, 206, 207, 208,
+ 209, 210, 211, 212, 213, 214, 215, 216,
+ 217, 218, 219, 220, 221, 222, 223, 224,
+ 225, 226, 227, 228, 229, 230, 231, 232,
+ 233, 234, 235, 236, 237, 238, 239, 240,
+ 241, 242, 243, 244, 245, 246, 247, 248,
+ 249, 250, 251, 252, 253, 254, 255, 0xffff
+};
+
+static inline void registers_set_default(enum mcdrv_dev_id id)
+{
+ memset(mc_info.if_registers, 0, MCDRV_REG_NUM_IF);
+
+ mc_info.if_registers[MCI_RST_A] = MCI_RST_A_DEF;
+ mc_info.if_registers[MCI_RST] = MCI_RST_DEF;
+
+ mc_a_registers_init();
+ mc_mblock_registers_init();
+
+ memset(mc_info.c_registers, 0, MCDRV_REG_NUM_C);
+ memset(mc_info.f_registers, 0, MCDRV_REG_NUM_F);
+ memset(mc_info.ana_registers, 0, MCDRV_REG_NUM_ANA);
+
+ mc_info.ana_registers[MCI_ANA_ID] = MCI_ANA_ID_DEF;
+ mc_info.ana_registers[MCI_ANA_RST] = MCI_ANA_RST_DEF;
+ mc_info.ana_registers[MCI_AP] = MCI_AP_DEF;
+ mc_info.ana_registers[MCI_AP_DA0] = MCI_AP_DA0_DEF;
+ mc_info.ana_registers[MCI_AP_DA1] = MCI_AP_DA1_DEF;
+ mc_info.ana_registers[MCI_AP_MIC] = MCI_AP_MIC_DEF;
+ mc_info.ana_registers[MCI_AP_AD] = MCI_AP_AD_DEF;
+
+ if (id == MCDRV_DEV_ID_81_91H)
+ mc_info.ana_registers[10] = 0x06;
+ mc_info.ana_registers[MCI_NONCLIP] = MCI_NONCLIP_DEF;
+
+ mc_info.ana_registers[MCI_SVOL] = MCI_SVOL_DEF;
+
+ if (id == MCDRV_DEV_ID_81_91H) {
+ mc_info.ana_registers[MCI_HIZ] = MCI_HIZ_DEF;
+ mc_info.ana_registers[MCI_LO_HIZ] = MCI_LO_HIZ_DEF;
+ }
+
+ if (id == MCDRV_DEV_ID_80_90H)
+ mc_info.ana_registers[MCI_ZCOFF] = MCI_ZCOFF_DEF_ES1;
+
+ switch (id) {
+ case MCDRV_DEV_ID_80_90H:
+ mc_info.ana_registers[MCI_CPMOD] = MCI_CPMOD_DEF_ES1;
+ mc_info.ana_registers[MCI_DNG_ES1] = MCI_DNG_DEF_ES1;
+ mc_info.ana_registers[MCI_DNG_HP_ES1] = MCI_DNG_HP_DEF_ES1;
+ mc_info.ana_registers[MCI_DNG_SP_ES1] = MCI_DNG_SP_DEF_ES1;
+ mc_info.ana_registers[MCI_DNG_RC_ES1] = MCI_DNG_RC_DEF_ES1;
+ mc_info.ana_registers[MCI_DNG_LO1_ES1] = MCI_DNG_LO1_DEF_ES1;
+ mc_info.ana_registers[MCI_DNG_LO2_ES1] = MCI_DNG_LO2_DEF_ES1;
+ break;
+ case MCDRV_DEV_ID_81_91H:
+ mc_info.ana_registers[MCI_CPMOD] = MCI_CPMOD_DEF;
+ mc_info.ana_registers[MCI_DNG] = MCI_DNG_DEF;
+ mc_info.ana_registers[MCI_DNG_HP] = MCI_DNG_HP_DEF;
+ mc_info.ana_registers[MCI_DNG_SP] = MCI_DNG_SP_DEF;
+ mc_info.ana_registers[MCI_DNG_RC] = MCI_DNG_RC_DEF;
+ mc_info.ana_registers[MCI_DNG_LO1] = MCI_DNG_LO1_DEF;
+ mc_info.ana_registers[MCI_DNG_LO2] = MCI_DNG_LO2_DEF;
+ mc_info.ana_registers[114] = 0x31;
+ mc_info.ana_registers[115] = 0x8B;
+ break;
+ default:
+ break;
+ }
+
+ memset(mc_info.cd_registers, 0, MCDRV_REG_NUM_CD);
+
+ mc_info.cd_registers[MCI_HW_ID] = MCI_HW_ID_DEF;
+ mc_info.cd_registers[MCI_CD_RST] = MCI_CD_RST_DEF;
+ mc_info.cd_registers[MCI_DP] = MCI_DP_DEF;
+ mc_info.cd_registers[MCI_DP_OSC] = MCI_DP_OSC_DEF;
+
+ switch (id) {
+ case MCDRV_DEV_ID_80_90H:
+ mc_info.cd_registers[MCI_CKSEL] = MCI_CKSEL_DEF_ES1;
+ break;
+ case MCDRV_DEV_ID_81_91H:
+ mc_info.cd_registers[MCI_CKSEL] = MCI_CKSEL_DEF;
+ break;
+ default:
+ break;
+ }
+
+ mc_info.cd_registers[MCI_MICDET] = MCI_MICDET_DEF;
+ mc_info.cd_registers[MCI_HSDETEN] = MCI_HSDETEN_DEF;
+
+ switch (id) {
+ case MCDRV_DEV_ID_80_90H:
+ mc_info.cd_registers[MCI_DETIN_INV] = MCI_DETIN_INV_DEF_ES1;
+ break;
+ case MCDRV_DEV_ID_81_91H:
+ mc_info.cd_registers[MCI_IRQTYPE] = MCI_IRQTYPE_DEF;
+ mc_info.cd_registers[MCI_DETIN_INV] = MCI_DETIN_INV_DEF;
+ break;
+ default:
+ break;
+ }
+
+ mc_info.cd_registers[MCI_HSDETMODE] = MCI_HSDETMODE_DEF;
+ mc_info.cd_registers[MCI_DBNC_PERIOD] = MCI_DBNC_PERIOD_DEF;
+
+ switch (id) {
+ case MCDRV_DEV_ID_80_90H:
+ mc_info.cd_registers[MCI_DBNC_NUM] = MCI_DBNC_NUM_DEF_ES1;
+ break;
+ case MCDRV_DEV_ID_UNKNOWN:
+ break;
+ default:
+ mc_info.cd_registers[MCI_DBNC_NUM] = MCI_DBNC_NUM_DEF;
+ mc_info.cd_registers[MCI_KEY_MTIM] = MCI_KEY_MTIM_DEF;
+ mc_info.cd_registers[39] = 0x21;
+ break;
+ }
+}
+
+int mc_id_set(u8 digital_id, u8 analog_id)
+{
+ if ((digital_id & MCDRV_DEVID_MASK) == MCDRV_DEVID_DIG
+ && (analog_id & MCDRV_DEVID_MASK) == MCDRV_DEVID_ANA) {
+ if ((digital_id & MCDRV_VERID_MASK) == 1) {
+ if ((analog_id & MCDRV_VERID_MASK) == 2)
+ mc_info.device_id = MCDRV_DEV_ID_81_92H;
+ else
+ mc_info.device_id = MCDRV_DEV_ID_81_91H;
+ } else
+ mc_info.device_id = MCDRV_DEV_ID_80_90H;
+
+ mc_info.id = digital_id;
+ registers_set_default(mc_info.device_id);
+ mc_info.a_registers[MCI_A_DEV_ID] = mc_info.id;
+
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
+enum mcdrv_dev_id mc_dev_id_get(void)
+{
+ return mc_info.device_id;
+}
+
+static inline void path_info_init(void)
+{
+ struct mcdrv_path_info *path_info;
+
+ path_info = &mc_info.path_info;
+
+ memset(path_info->music_out, D1SRC_ALL_OFF, MUSICOUT_PATH_CHANNELS);
+ memset(path_info->ext_out, D1SRC_ALL_OFF, EXTOUT_PATH_CHANNELS);
+ memset(path_info->hifi_out, D1SRC_ALL_OFF, HIFIOUT_PATH_CHANNELS);
+ memset(path_info->vbox_mix_in, D1SRC_ALL_OFF, VBOXMIXIN_PATH_CHANNELS);
+ memset(path_info->ae0, D1SRC_ALL_OFF, AE_PATH_CHANNELS);
+ memset(path_info->ae1, D1SRC_ALL_OFF, AE_PATH_CHANNELS);
+ memset(path_info->ae2, D1SRC_ALL_OFF, AE_PATH_CHANNELS);
+ memset(path_info->ae3, D1SRC_ALL_OFF, AE_PATH_CHANNELS);
+ memset(path_info->dac0, D1SRC_ALL_OFF, DAC0_PATH_CHANNELS);
+ memset(path_info->dac1, D1SRC_ALL_OFF, DAC1_PATH_CHANNELS);
+
+ memset(path_info->voice_out, D2SRC_ALL_OFF, VOICEOUT_PATH_CHANNELS);
+ memset(path_info->vbox_io_in, D2SRC_ALL_OFF, VBOXIOIN_PATH_CHANNELS);
+ memset(path_info->vbox_host_in, D2SRC_ALL_OFF,
+ VBOXHOSTIN_PATH_CHANNELS);
+ memset(path_info->host_out, D2SRC_ALL_OFF, HOSTOUT_PATH_CHANNELS);
+ memset(path_info->adif0, D2SRC_ALL_OFF, ADIF0_PATH_CHANNELS);
+ memset(path_info->adif1, D2SRC_ALL_OFF, ADIF1_PATH_CHANNELS);
+ memset(path_info->adif2, D2SRC_ALL_OFF, ADIF2_PATH_CHANNELS);
+
+ memset(path_info->adc0, ASRC_ALL_OFF, ADC0_PATH_CHANNELS);
+ memset(path_info->adc1, ASRC_ALL_OFF, ADC1_PATH_CHANNELS);
+ memset(path_info->sp, ASRC_ALL_OFF, SP_PATH_CHANNELS);
+ memset(path_info->hp, ASRC_ALL_OFF, HP_PATH_CHANNELS);
+ memset(path_info->rc, ASRC_ALL_OFF, RC_PATH_CHANNELS);
+ memset(path_info->lout1, ASRC_ALL_OFF, LOUT1_PATH_CHANNELS);
+ memset(path_info->lout2, ASRC_ALL_OFF, LOUT2_PATH_CHANNELS);
+ memset(path_info->bias, ASRC_ALL_OFF, BIAS_PATH_CHANNELS);
+
+ mc_info.path_info_virtual = mc_info.path_info;
+}
+
+static inline void vol_info_init(void)
+{
+ struct mcdrv_vol_info *vol_info;
+
+ vol_info = &mc_info.vol_info;
+
+ memset(vol_info, MCDRV_LOGICAL_VOL_MUTE, sizeof(struct mcdrv_vol_info));
+}
+
+static inline void dio_info_init(void)
+{
+ struct mcdrv_dio_port *port;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(mc_info.dio_info.port); i++) {
+ port = &mc_info.dio_info.port[i];
+ port->dio_common.master_slave = MCDRV_DIO_SLAVE;
+ port->dio_common.auto_fs = MCDRV_AUTOFS_ON;
+ port->dio_common.fs = MCDRV_FS_48000;
+ port->dio_common.bck_fs = MCDRV_BCKFS_64;
+ port->dio_common.interface = MCDRV_DIO_DA;
+ port->dio_common.bck_invert = MCDRV_BCLK_NORMAL;
+ port->dio_common.src_thru = MCDRV_SRC_NOT_THRU;
+ port->dio_common.pcm_hiz_transition = MCDRV_PCMHIZTRANS_FALLING;
+ port->dio_common.pcm_frame = MCDRV_PCM_SHORTFRAME;
+ port->dio_common.pcm_high_period = 0;
+
+ port->dir.da_format.bit_sel = MCDRV_BITSEL_16;
+ port->dir.da_format.mode = MCDRV_DAMODE_HEADALIGN;
+ port->dir.pcm_format.mono = MCDRV_PCM_MONO;
+ port->dir.pcm_format.order = MCDRV_PCM_MSB_FIRST;
+ port->dir.pcm_format.law = MCDRV_PCM_LINEAR;
+ port->dir.pcm_format.bit_sel = MCDRV_PCM_BITSEL_8;
+
+ port->dit.st_mode = MCDRV_STMODE_ZERO;
+ port->dit.edge = MCDRV_SDOUT_NORMAL;
+ port->dit.da_format.bit_sel = MCDRV_BITSEL_16;
+ port->dit.da_format.mode = MCDRV_DAMODE_HEADALIGN;
+ port->dit.pcm_format.mono = MCDRV_PCM_MONO;
+ port->dit.pcm_format.order = MCDRV_PCM_MSB_FIRST;
+ port->dit.pcm_format.law = MCDRV_PCM_LINEAR;
+ port->dit.pcm_format.bit_sel = MCDRV_PCM_BITSEL_8;
+ }
+}
+
+static inline void dio_path_info_init(void)
+{
+ mc_info.dio_path_info.phys_port[0] = MCDRV_PHYSPORT_DIO0;
+ mc_info.dio_path_info.phys_port[1] = MCDRV_PHYSPORT_DIO1;
+ mc_info.dio_path_info.phys_port[2] = MCDRV_PHYSPORT_DIO2;
+ mc_info.dio_path_info.phys_port[3] = MCDRV_PHYSPORT_NONE;
+ mc_info.dio_path_info.music_ch = MCDRV_MUSIC_2CH;
+ mc_info.dio_path_info.music_rslot[0] = 0;
+ mc_info.dio_path_info.music_rslot[1] = 1;
+ mc_info.dio_path_info.music_rslot[2] = 2;
+ mc_info.dio_path_info.music_tslot[0] = 0;
+ mc_info.dio_path_info.music_tslot[1] = 1;
+ mc_info.dio_path_info.music_tslot[2] = 2;
+}
+
+static inline void swap_info_init(void)
+{
+ mc_info.swap_info.adif0 = MCDRV_SWAP_NORMAL;
+ mc_info.swap_info.adif1 = MCDRV_SWAP_NORMAL;
+ mc_info.swap_info.adif2 = MCDRV_SWAP_NORMAL;
+ mc_info.swap_info.dac0 = MCDRV_SWAP_NORMAL;
+ mc_info.swap_info.dac1 = MCDRV_SWAP_NORMAL;
+
+ mc_info.swap_info.music_in0 = MCDRV_SWSWAP_NORMAL;
+ mc_info.swap_info.music_in1 = MCDRV_SWSWAP_NORMAL;
+ mc_info.swap_info.music_in2 = MCDRV_SWSWAP_NORMAL;
+ mc_info.swap_info.ext_in = MCDRV_SWSWAP_NORMAL;
+ mc_info.swap_info.voice_in = MCDRV_SWSWAP_NORMAL;
+ mc_info.swap_info.hifi_in = MCDRV_SWSWAP_NORMAL;
+ mc_info.swap_info.music_out0 = MCDRV_SWSWAP_NORMAL;
+ mc_info.swap_info.music_out1 = MCDRV_SWSWAP_NORMAL;
+ mc_info.swap_info.music_out2 = MCDRV_SWSWAP_NORMAL;
+ mc_info.swap_info.ext_out = MCDRV_SWSWAP_NORMAL;
+ mc_info.swap_info.voice_out = MCDRV_SWSWAP_NORMAL;
+ mc_info.swap_info.hifi_out = MCDRV_SWSWAP_NORMAL;
+}
+
+static inline void hsdet_info_init(void)
+{
+ struct mcdrv_hsdet_info *hsdet;
+
+ hsdet = &mc_info.hsdet_info;
+ hsdet->en_plug_det = MCDRV_PLUGDET_DISABLE;
+ hsdet->en_plug_det_db = MCDRV_PLUGDETDB_DISABLE;
+ 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;
+ hsdet->hs_det_dbnc = MCDRV_DETDBNC_875;
+ hsdet->key_off_mtim = MCDRV_KEYOFF_MTIM_63;
+ hsdet->key_on_mtim = MCDRV_KEYON_MTIM_63;
+ hsdet->key0_off_dly_tim = 0;
+ hsdet->key1_off_dly_tim = 0;
+ hsdet->key2_off_dly_tim = 0;
+ hsdet->key0_on_dly_tim = 0;
+ hsdet->key1_on_dly_tim = 0;
+ hsdet->key2_on_dly_tim = 0;
+ hsdet->key0_on_dly_tim2 = 0;
+ hsdet->key1_on_dly_tim2 = 0;
+ hsdet->key2_on_dly_tim2 = 0;
+ if (mc_info.device_id == MCDRV_DEV_ID_81_91H)
+ hsdet->irq_type = MCDRV_IRQTYPE_REF;
+ else
+ hsdet->irq_type = MCDRV_IRQTYPE_NORMAL;
+ hsdet->plug_det_db_irq_type = MCDRV_IRQTYPE_REF;
+ hsdet->plug_undet_db_irq_type = MCDRV_IRQTYPE_REF;
+ hsdet->mic_det_irq_type = MCDRV_IRQTYPE_REF;
+ hsdet->plug_det_irq_type = MCDRV_IRQTYPE_REF;
+ hsdet->key0_on_irq_type = MCDRV_IRQTYPE_REF;
+ hsdet->key1_on_irq_type = MCDRV_IRQTYPE_REF;
+ hsdet->key2_on_irq_type = MCDRV_IRQTYPE_REF;
+ hsdet->key0_off_irq_type = MCDRV_IRQTYPE_REF;
+ hsdet->key1_off_irq_type = MCDRV_IRQTYPE_REF;
+ hsdet->key2_off_irq_type = MCDRV_IRQTYPE_REF;
+ hsdet->det_in_inv = MCDRV_DET_IN_INV;
+ hsdet->hs_det_mode = MCDRV_HSDET_MODE_DETIN_A;
+ hsdet->speriod = MCDRV_SPERIOD_3906;
+ hsdet->lperiod = MCDRV_LPERIOD_125000;
+ hsdet->dbnc_num_plug = MCDRV_DBNC_NUM_7;
+ hsdet->dbnc_num_mic = MCDRV_DBNC_NUM_7;
+ hsdet->dbnc_num_key = MCDRV_DBNC_NUM_7;
+ hsdet->sgnl_period = MCDRV_SGNLPERIOD_97;
+ hsdet->sgnl_num = MCDRV_SGNLNUM_8;
+ hsdet->sgnl_peak = MCDRV_SGNLPEAK_1182;
+ hsdet->imp_sel = MCDRV_IMPSEL_MOSTFREQ;
+ hsdet->dly_irq_stop = MCDRV_DLYIRQ_DONTCARE;
+ hsdet->cbfunc = NULL;
+}
+
+static inline void aec_info_init(void)
+{
+ struct mcdrv_aec_info *aec_info;
+ int i;
+
+ aec_info = &mc_info.aec_info;
+ memset(aec_info, 0, sizeof(struct mcdrv_aec_info));
+
+ aec_info->output.lpf_pre_thru[0] = 1;
+ aec_info->output.lpf_post_thru[0] = 1;
+
+ for (i = 0; i < MCDRV_AEC_OUTPUT_N; i++) {
+ aec_info->output.dcc_sel[i] = 2;
+ aec_info->output.osf_sel[i] = 3;
+ aec_info->output.dcl_limit[i][0] = 0x7f;
+ aec_info->output.dcl_limit[i][1] = 0xff;
+ aec_info->output.dc_dither_level[i] = 3;
+ aec_info->output.dng_fw[i] = 1;
+ }
+ aec_info->output.dng_zero[0] = 31;
+ aec_info->output.dng_zero[1] = 9;
+ aec_info->output.dng_time[1] = 2;
+ aec_info->output.osf_gain[0][0] = MCI_OSF_GAIN0_15_8_DEF;
+ aec_info->output.osf_gain[0][1] = MCI_OSF_GAIN0_7_0_DEF;
+ aec_info->output.osf_gain[1][0] = MCI_OSF_GAIN1_15_8_DEF;
+ aec_info->output.osf_gain[1][1] = MCI_OSF_GAIN1_7_0_DEF;
+ aec_info->output.dng_attack = 1;
+ aec_info->output.dng_release = 3;
+ aec_info->output.dng_target[0] = 0x84;
+ if (mc_info.device_id == MCDRV_DEV_ID_80_90H) {
+ aec_info->output.dng_target[1] = MCI_DNG_SP_DEF_ES1;
+ aec_info->output.dng_target_lineout[0] = MCI_DNG_LO1_DEF_ES1;
+ aec_info->output.dng_target_lineout[1] = MCI_DNG_LO2_DEF_ES1;
+ aec_info->output.dng_target_rc = MCI_DNG_RC_DEF_ES1;
+ } else {
+ aec_info->output.dng_target[1] = MCI_DNG_SP_DEF;
+ aec_info->output.dng_target_lineout[0] = MCI_DNG_LO1_DEF;
+ aec_info->output.dng_target_lineout[1] = MCI_DNG_LO2_DEF;
+ aec_info->output.dng_target_rc = MCI_DNG_RC_DEF;
+ }
+
+ for (i = 0; i < MCDRV_AEC_INPUT_N; i++) {
+ aec_info->input.dsf32_l_type[i] = 1;
+ aec_info->input.dsf32_r_type[i] = 1;
+ aec_info->input.dsf4_sel[i] = 1;
+ if (mc_info.device_id == MCDRV_DEV_ID_80_90H)
+ aec_info->input.dcc_sel[i] = 2;
+ else
+ aec_info->input.dcc_sel[i] = 1;
+ aec_info->input.dng_att[i] = 3;
+ aec_info->input.dng_rel[i] = 2;
+ aec_info->input.depop_att[i] = 2;
+ aec_info->input.depop_wait[i] = 2;
+ }
+
+ aec_info->pdm.st_wait = 2;
+
+ aec_info->adj.hold = 24;
+ aec_info->adj.cnt = 10;
+ aec_info->adj.max[0] = 2;
+}
+
+void mc_resource_init(void)
+{
+ path_info_init();
+ vol_info_init();
+ dio_info_init();
+ dio_path_info_init();
+ swap_info_init();
+ hsdet_info_init();
+ aec_info_init();
+
+ mc_info.clk = MCDRV_CLKSW_CLKA;
+ mc_info.clk_sel = 0;
+ mc_info.eclk_sel = 0;
+ mc_info.plug_det_db = 0;
+
+ mc_resource_clear();
+}
+
+void mc_a_registers_init(void)
+{
+ memset(mc_info.a_registers, 0, MCDRV_REG_NUM_A);
+
+ mc_info.a_registers[MCI_A_DEV_ID] = mc_info.id;
+ mc_info.a_registers[MCI_CLK_MSK] = MCI_CLK_MSK_DEF;
+ mc_info.a_registers[MCI_PD] = MCI_PD_DEF;
+ mc_info.a_registers[MCI_DO0_DRV] = MCI_DO0_DRV_DEF;
+ mc_info.a_registers[MCI_DO1_DRV] = MCI_DO1_DRV_DEF;
+ mc_info.a_registers[MCI_DO2_DRV] = MCI_DO2_DRV_DEF;
+ mc_info.a_registers[MCI_PA0] = MCI_PA0_DEF;
+ mc_info.a_registers[MCI_PA1] = MCI_PA1_DEF;
+ mc_info.a_registers[MCI_PA2] = MCI_PA2_DEF;
+ if (mc_info.device_id != MCDRV_DEV_ID_80_90H)
+ mc_info.a_registers[MCI_DOA_DRV] = MCI_DOA_DRV_DEF;
+ mc_info.a_registers[MCI_LP1_FP] = MCI_LP1_FP_DEF;
+ mc_info.a_registers[MCI_LP2_FP] = MCI_LP2_FP_DEF;
+ mc_info.a_registers[MCI_LP3_FP] = MCI_LP3_FP_DEF;
+ mc_info.a_registers[MCI_CLKSRC] = MCI_CLKSRC_DEF;
+ mc_info.a_registers[MCI_FREQ73M] = MCI_FREQ73M_DEF;
+ mc_info.a_registers[MCI_PLL_MODE_A] = MCI_PLL_MODE_A_DEF;
+ mc_info.a_registers[MCI_PLL_MODE_B] = MCI_PLL_MODE_B_DEF;
+}
+
+void mc_mblock_registers_init(void)
+{
+ memset(mc_info.ma_registers, 0, MCDRV_REG_NUM_MA);
+
+ mc_info.ma_registers[MCI_I_VINTP] = MCI_I_VINTP_DEF;
+ mc_info.ma_registers[MCI_O_VINTP] = MCI_O_VINTP_DEF;
+
+ memset(mc_info.mb_registers, 0, MCDRV_REG_NUM_MB);
+
+ mc_info.mb_registers[MCI_LP0_MODE] = MCI_LP0_MODE_DEF;
+ mc_info.mb_registers[MCI_LPR0_SLOT] = MCI_LPR0_SLOT_DEF;
+ mc_info.mb_registers[MCI_LPT0_SLOT] = MCI_LPT0_SLOT_DEF;
+ mc_info.mb_registers[MCI_LPR0_PCM] = MCI_LPR0_PCM_DEF;
+ mc_info.mb_registers[MCI_LPT0_PCM] = MCI_LPT0_PCM_DEF;
+ mc_info.mb_registers[MCI_LP1_MODE] = MCI_LP1_MODE_DEF;
+ mc_info.mb_registers[MCI_LPR1_PCM] = MCI_LPR1_PCM_DEF;
+ mc_info.mb_registers[MCI_LPT1_PCM] = MCI_LPT1_PCM_DEF;
+ mc_info.mb_registers[MCI_LP2_MODE] = MCI_LP2_MODE_DEF;
+ mc_info.mb_registers[MCI_LPR2_PCM] = MCI_LPR2_PCM_DEF;
+ mc_info.mb_registers[MCI_LPT2_PCM] = MCI_LPT2_PCM_DEF;
+
+ memset(mc_info.b_registers, 0, MCDRV_REG_NUM_B);
+
+ mc_e_registers_init();
+}
+
+void mc_e_registers_init(void)
+{
+ memset(mc_info.e_registers, 0, MCDRV_REG_NUM_E);
+
+ mc_info.e_registers[MCI_E1DSP_CTRL] = MCI_E1DSP_CTRL_DEF;
+ mc_info.e_registers[MCI_LPF_THR] = MCI_LPF_THR_DEF;
+ mc_info.e_registers[MCI_DAC_DCC_SEL] = MCI_DAC_DCC_SEL_DEF;
+ if (mc_info.device_id == MCDRV_DEV_ID_81_91H)
+ mc_info.e_registers[MCI_OSF_SEL] = MCI_OSF_SEL_DEF;
+ mc_info.e_registers[MCI_OSF_GAIN0_15_8] = MCI_OSF_GAIN0_15_8_DEF;
+ mc_info.e_registers[MCI_OSF_GAIN0_7_0] = MCI_OSF_GAIN0_7_0_DEF;
+ mc_info.e_registers[MCI_OSF_GAIN1_15_8] = MCI_OSF_GAIN1_15_8_DEF;
+ mc_info.e_registers[MCI_OSF_GAIN1_7_0] = MCI_OSF_GAIN1_7_0_DEF;
+ mc_info.e_registers[MCI_DCL0_LMT_14_8] = MCI_DCL0_LMT_14_8_DEF;
+ mc_info.e_registers[MCI_DCL0_LMT_7_0] = MCI_DCL0_LMT_7_0_DEF;
+ mc_info.e_registers[MCI_DCL1_LMT_14_8] = MCI_DCL1_LMT_14_8_DEF;
+ mc_info.e_registers[MCI_DCL1_LMT_7_0] = MCI_DCL1_LMT_7_0_DEF;
+ switch (mc_info.device_id) {
+ case MCDRV_DEV_ID_80_90H:
+ mc_info.e_registers[MCI_DITHER0] = MCI_DITHER0_DEF;
+ mc_info.e_registers[MCI_DITHER1] = MCI_DITHER1_DEF;
+ mc_info.e_registers[MCI_DNG0_ES1] = MCI_DNG0_DEF_ES1;
+ mc_info.e_registers[MCI_DNG1_ES1] = MCI_DNG1_DEF_ES1;
+ break;
+ case MCDRV_DEV_ID_81_91H:
+ mc_info.e_registers[MCI_DITHER0] = 0x30;
+ mc_info.e_registers[MCI_DITHER1] = 0x30;
+ mc_info.e_registers[MCI_DNG0] = MCI_DNG0_DEF;
+ mc_info.e_registers[MCI_DNG1] = MCI_DNG1_DEF;
+ break;
+ default:
+ break;
+ }
+ mc_info.e_registers[MCI_DPATH_DA_V] = MCI_DPATH_DA_V_DEF;
+ mc_info.e_registers[MCI_DPATH_AD_V] = MCI_DPATH_AD_V_DEF;
+ if (mc_info.device_id == MCDRV_DEV_ID_81_91H)
+ mc_info.e_registers[39] = 0xf4;
+ mc_info.e_registers[MCI_DSF0_PRE_INPUT] = MCI_DSF0_PRE_INPUT_DEF;
+ mc_info.e_registers[MCI_DSF1_FLT_TYPE] = MCI_DSF1_FLT_TYPE_DEF;
+ mc_info.e_registers[MCI_DSF1_PRE_INPUT] = MCI_DSF1_PRE_INPUT_DEF;
+ mc_info.e_registers[MCI_DSF2_PRE_INPUT] = MCI_DSF2_PRE_INPUT_DEF;
+ switch (mc_info.device_id) {
+ case MCDRV_DEV_ID_80_90H:
+ mc_info.e_registers[MCI_ADC_DCC_SEL] = MCI_ADC_DCC_SEL_DEF_ES1;
+ break;
+ case MCDRV_DEV_ID_81_91H:
+ mc_info.e_registers[MCI_ADC_DCC_SEL] = MCI_ADC_DCC_SEL_DEF;
+ break;
+ default:
+ break;
+ }
+ mc_info.e_registers[MCI_ADC_DNG0_FW] = MCI_ADC_DNG0_FW_DEF;
+ mc_info.e_registers[MCI_ADC_DNG1_FW] = MCI_ADC_DNG1_FW_DEF;
+ mc_info.e_registers[MCI_ADC_DNG2_FW] = MCI_ADC_DNG2_FW_DEF;
+ mc_info.e_registers[MCI_DEPOP0] = MCI_DEPOP0_DEF;
+ mc_info.e_registers[MCI_DEPOP1] = MCI_DEPOP1_DEF;
+ mc_info.e_registers[MCI_DEPOP2] = MCI_DEPOP2_DEF;
+ mc_info.e_registers[MCI_PDM_MODE] = MCI_PDM_MODE_DEF;
+ mc_info.e_registers[MCI_E2DSP] = MCI_E2DSP_DEF;
+ if (mc_info.device_id == MCDRV_DEV_ID_81_91H) {
+ mc_info.e_registers[99] = 0xc9;
+ mc_info.e_registers[100] = 0x01;
+ }
+}
+
+void mc_state_update(enum mcdrv_state state)
+{
+ mc_info.state = state;
+}
+
+enum mcdrv_state mc_state_get(void)
+{
+ return mc_info.state;
+}
+
+u8 mc_register_get_value(u16 type, u16 addr)
+{
+ u8 val = 0;
+
+ switch (type) {
+ case MCDRV_PACKET_REGTYPE_IF:
+ val = mc_info.if_registers[addr];
+ break;
+ case MCDRV_PACKET_REGTYPE_A:
+ val = mc_info.a_registers[addr];
+ break;
+ case MCDRV_PACKET_REGTYPE_MA:
+ val = mc_info.ma_registers[addr];
+ break;
+ case MCDRV_PACKET_REGTYPE_MB:
+ val = mc_info.mb_registers[addr];
+ break;
+ case MCDRV_PACKET_REGTYPE_E:
+ val = mc_info.e_registers[addr];
+ break;
+ case MCDRV_PACKET_REGTYPE_ANA:
+ val = mc_info.ana_registers[addr];
+ break;
+ case MCDRV_PACKET_REGTYPE_CD:
+ val = mc_info.cd_registers[addr];
+ break;
+
+ default:
+ break;
+ }
+
+ return val;
+}
+
+void mc_register_set_value(u16 type, u16 addr, u8 val)
+{
+ switch (type) {
+ case MCDRV_PACKET_REGTYPE_IF:
+ mc_info.if_registers[addr] = val;
+ break;
+ case MCDRV_PACKET_REGTYPE_A:
+ mc_info.a_registers[addr] = val;
+ break;
+ case MCDRV_PACKET_REGTYPE_MA:
+ mc_info.ma_registers[addr] = val;
+ break;
+ case MCDRV_PACKET_REGTYPE_MB:
+ mc_info.mb_registers[addr] = val;
+ break;
+ case MCDRV_PACKET_REGTYPE_E:
+ mc_info.e_registers[addr] = val;
+ break;
+ case MCDRV_PACKET_REGTYPE_ANA:
+ mc_info.ana_registers[addr] = val;
+ break;
+ case MCDRV_PACKET_REGTYPE_CD:
+ mc_info.cd_registers[addr] = val;
+ break;
+ default:
+ break;
+ }
+}
+
+void mc_dev_info_set(struct mcdrv_dev_info *dev_info)
+{
+ mc_info.dev_info = *dev_info;
+}
+
+void mc_dev_info_get(struct mcdrv_dev_info *dev_info)
+{
+ *dev_info = mc_info.dev_info;
+}
+
+int mc_clock_set(u8 clock)
+{
+ mc_info.clk = clock;
+
+ mc_packet_add_switch_clock(clock);
+
+ return mc_packet_execute();
+}
+
+void mc_clock_get(u8 *clock)
+{
+ *clock = mc_info.clk;
+}
+
+static void source_set_onoff(u32 src, u32 *dst, u32 on, u32 off)
+{
+ if (dst) {
+ if (src & on) {
+ *dst &= ~off;
+ *dst |= on;
+ } else if ((src & (on | off)) == off) {
+ *dst &= ~on;
+ *dst |= off;
+ }
+ }
+}
+
+static void d1_source_set_onoff(u32 *src, u32 *dst, u8 channels)
+{
+ int i, j;
+
+ struct {
+ u32 on;
+ u32 off;
+ } d1_src[] = {
+ { MCDRV_D1SRC_MUSICIN_ON, MCDRV_D1SRC_MUSICIN_OFF },
+ { MCDRV_D1SRC_EXTIN_ON, MCDRV_D1SRC_EXTIN_OFF },
+ { MCDRV_D1SRC_VBOXOUT_ON, MCDRV_D1SRC_VBOXOUT_OFF },
+ { MCDRV_D1SRC_VBOXREFOUT_ON, MCDRV_D1SRC_VBOXREFOUT_OFF },
+ { MCDRV_D1SRC_AE0_ON, MCDRV_D1SRC_AE0_OFF },
+ { MCDRV_D1SRC_AE1_ON, MCDRV_D1SRC_AE1_OFF },
+ { MCDRV_D1SRC_AE2_ON, MCDRV_D1SRC_AE2_OFF },
+ { MCDRV_D1SRC_AE3_ON, MCDRV_D1SRC_AE3_OFF },
+ { MCDRV_D1SRC_ADIF0_ON, MCDRV_D1SRC_ADIF0_OFF },
+ { MCDRV_D1SRC_ADIF1_ON, MCDRV_D1SRC_ADIF1_OFF },
+ { MCDRV_D1SRC_ADIF2_ON, MCDRV_D1SRC_ADIF2_OFF },
+ { MCDRV_D1SRC_HIFIIN_ON, MCDRV_D1SRC_HIFIIN_OFF }
+ };
+
+ for (i = 0; i < channels; i++) {
+ for (j = 0; j < ARRAY_SIZE(d1_src); j++)
+ source_set_onoff(src[i], &dst[i],
+ d1_src[j].on, d1_src[j].off);
+ }
+}
+
+static void d2_source_set_onoff(u32 *src, u32 *dst, u8 channels)
+{
+ u32 on, off;
+ int i, j;
+
+ struct {
+ u32 on;
+ u32 off;
+ } d2_src[] = {
+ { MCDRV_D2SRC_VOICEIN_ON, MCDRV_D2SRC_VOICEIN_OFF },
+ { MCDRV_D2SRC_VBOXIOOUT_ON, MCDRV_D2SRC_VBOXIOOUT_OFF },
+ { MCDRV_D2SRC_VBOXHOSTOUT_ON, MCDRV_D2SRC_VBOXHOSTOUT_OFF },
+ { 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 }
+ };
+
+ for (i = 0; i < channels; i++) {
+ for (j = 0; j < ARRAY_SIZE(d2_src); j++) {
+ on = d2_src[j].on;
+ off = d2_src[j].off;
+ if ((src[i] & on)
+ && (on == MCDRV_D2SRC_PDM0_L_ON ||
+ on == MCDRV_D2SRC_PDM0_R_ON ||
+ on == MCDRV_D2SRC_PDM1_L_ON ||
+ on == MCDRV_D2SRC_PDM1_R_ON)
+ && mc_info.dev_info.pa0_func != MCDRV_PA_PDMCK)
+ break;
+
+ source_set_onoff(src[i], &dst[i], on, off);
+ }
+ }
+}
+
+static void a_source_set_onoff(u32 *src, u32 *dst, u8 channels)
+{
+ int i, j;
+
+ struct {
+ u32 on;
+ u32 off;
+ } a_src[] = {
+ { MCDRV_ASRC_DAC0_L_ON, MCDRV_ASRC_DAC0_L_OFF },
+ { MCDRV_ASRC_DAC0_R_ON, MCDRV_ASRC_DAC0_R_OFF },
+ { MCDRV_ASRC_DAC1_L_ON, MCDRV_ASRC_DAC1_L_OFF },
+ { MCDRV_ASRC_DAC1_R_ON, MCDRV_ASRC_DAC1_R_OFF },
+ { MCDRV_ASRC_MIC1_ON, MCDRV_ASRC_MIC1_OFF },
+ { MCDRV_ASRC_MIC2_ON, MCDRV_ASRC_MIC2_OFF },
+ { MCDRV_ASRC_MIC3_ON, MCDRV_ASRC_MIC3_OFF },
+ { MCDRV_ASRC_MIC4_ON, MCDRV_ASRC_MIC4_OFF },
+ { MCDRV_ASRC_LINEIN1_L_ON, MCDRV_ASRC_LINEIN1_L_OFF },
+ { MCDRV_ASRC_LINEIN1_R_ON, MCDRV_ASRC_LINEIN1_R_OFF },
+ { MCDRV_ASRC_LINEIN1_M_ON, MCDRV_ASRC_LINEIN1_M_OFF }
+ };
+
+ for (i = 0; i < channels; i++) {
+ for (j = 0; j < ARRAY_SIZE(a_src); j++)
+ source_set_onoff(src[i], &dst[i],
+ a_src[j].on, a_src[j].off);
+ }
+}
+
+static inline void bias_source_set_onoff(struct mcdrv_path_info *path_info)
+{
+ int i, j;
+
+ struct {
+ u32 on;
+ u32 off;
+ } bias[] = {
+ { MCDRV_ASRC_MIC1_ON, MCDRV_ASRC_MIC1_OFF },
+ { MCDRV_ASRC_MIC2_ON, MCDRV_ASRC_MIC2_OFF },
+ { MCDRV_ASRC_MIC3_ON, MCDRV_ASRC_MIC3_OFF },
+ { MCDRV_ASRC_MIC4_ON, MCDRV_ASRC_MIC4_OFF }
+ };
+
+ for (i = 0; i < BIAS_PATH_CHANNELS; i++) {
+ for (j = 0; j < ARRAY_SIZE(bias); j++) {
+ source_set_onoff(path_info->bias[i],
+ &mc_info.path_info.bias[i],
+ bias[j].on, bias[j].off);
+ }
+ }
+}
+
+static inline int is_valid_path(void)
+{
+ u32 dac[2], adif[2], src;
+ int used, i;
+
+ dac[0] = mc_info.path_info.dac0[0];
+ dac[1] = mc_info.path_info.dac0[1];
+
+ if ((dac[0] & MCDRV_D1SRC_HIFIIN_ON)
+ || (dac[1] & MCDRV_D1SRC_HIFIIN_ON)) {
+ if ((dac[0] & (MCDRV_D1SRC_ALL_ON & ~MCDRV_D1SRC_HIFIIN_ON))
+ || (dac[1] & (MCDRV_D1SRC_ALL_ON & ~MCDRV_D1SRC_HIFIIN_ON)))
+ return -EINVAL;
+
+ if (mc_info.device_id == MCDRV_DEV_ID_80_90H) {
+ for (i = 0; i < MUSICOUT_PATH_CHANNELS; i++) {
+ src = mc_info.path_info.music_out[i];
+ if (src & MCDRV_D1SRC_ADIF0_ON)
+ return -EINVAL;
+ }
+
+ for (i = 0; i < EXTOUT_PATH_CHANNELS; i++) {
+ src = mc_info.path_info.ext_out[i];
+ if (src & MCDRV_D1SRC_ADIF0_ON)
+ return -EINVAL;
+ }
+
+ for (i = 0; i < VBOXMIXIN_PATH_CHANNELS; i++) {
+ src = mc_info.path_info.vbox_mix_in[i];
+ if (src & MCDRV_D1SRC_ADIF0_ON)
+ return -EINVAL;
+ }
+
+ for (i = 0; i < AE_PATH_CHANNELS; i++) {
+ src = mc_info.path_info.ae0[i];
+ if (src & MCDRV_D1SRC_ADIF0_ON)
+ return -EINVAL;
+
+ src = mc_info.path_info.ae1[i];
+ if (src & MCDRV_D1SRC_ADIF0_ON)
+ return -EINVAL;
+
+ src = mc_info.path_info.ae2[i];
+ if (src & MCDRV_D1SRC_ADIF0_ON)
+ return -EINVAL;
+
+ src = mc_info.path_info.ae3[i];
+ if (src & MCDRV_D1SRC_ADIF0_ON)
+ return -EINVAL;
+ }
+
+ for (i = 0; i < DAC1_PATH_CHANNELS; i++) {
+ src = mc_info.path_info.dac1[i];
+ if (src & MCDRV_D1SRC_ADIF0_ON)
+ return -EINVAL;
+ }
+ }
+ }
+
+ dac[0] = mc_info.path_info.dac1[0];
+ dac[1] = mc_info.path_info.dac1[1];
+
+ if ((dac[0] & MCDRV_D1SRC_HIFIIN_ON)
+ || (dac[1] & MCDRV_D1SRC_HIFIIN_ON)) {
+ if ((dac[0] & (MCDRV_D1SRC_ALL_ON & ~MCDRV_D1SRC_HIFIIN_ON))
+ || (dac[1] & (MCDRV_D1SRC_ALL_ON & ~MCDRV_D1SRC_HIFIIN_ON)))
+ return -EINVAL;
+ }
+
+ for (i = 0; i < ADIF0_PATH_CHANNELS; i++) {
+ adif[i] = mc_info.path_info.adif0[i];
+
+ used = 0;
+ if (adif[i] & MCDRV_D2SRC_ADC0_L_ON)
+ used++;
+ if (adif[i] & MCDRV_D2SRC_ADC0_R_ON)
+ used++;
+ if (adif[i] & MCDRV_D2SRC_ADC1_ON)
+ used++;
+ if (adif[i] & MCDRV_D2SRC_PDM0_L_ON)
+ used++;
+ if (adif[i] & MCDRV_D2SRC_PDM0_R_ON)
+ used++;
+ if (adif[i] & MCDRV_D2SRC_PDM1_L_ON)
+ used++;
+ if (adif[i] & MCDRV_D2SRC_PDM1_R_ON)
+ used++;
+ if (used > 1)
+ return -EINVAL;
+ }
+
+ if (adif[0] == D2SRC_ALL_OFF && adif[1] != D2SRC_ALL_OFF)
+ return -EINVAL;
+
+ for (i = 0; i < ADIF1_PATH_CHANNELS; i++) {
+ adif[i] = mc_info.path_info.adif1[i];
+
+ used = 0;
+ if (adif[i] & MCDRV_D2SRC_ADC0_L_ON)
+ used++;
+ if (adif[i] & MCDRV_D2SRC_ADC0_R_ON)
+ used++;
+ if (adif[i] & MCDRV_D2SRC_ADC1_ON)
+ used++;
+ if (adif[i] & MCDRV_D2SRC_PDM0_L_ON)
+ used++;
+ if (adif[i] & MCDRV_D2SRC_PDM0_R_ON)
+ used++;
+ if (adif[i] & MCDRV_D2SRC_PDM1_L_ON)
+ used++;
+ if (adif[i] & MCDRV_D2SRC_PDM1_R_ON)
+ used++;
+ if (used > 1)
+ return -EINVAL;
+ }
+
+ if (adif[0] == D2SRC_ALL_OFF && adif[1] != D2SRC_ALL_OFF)
+ return -EINVAL;
+
+ for (i = 0; i < ADIF2_PATH_CHANNELS; i++) {
+ if (!i)
+ adif[i] = mc_source_get(MCDRV_DST_ADIF2, MCDRV_DST_CH0);
+ else
+ adif[i] = mc_source_get(MCDRV_DST_ADIF2, MCDRV_DST_CH1);
+
+ used = 0;
+ if (adif[i] & MCDRV_D2SRC_ADC0_L_ON)
+ used++;
+ if (adif[i] & MCDRV_D2SRC_ADC0_R_ON)
+ used++;
+ if (adif[i] & MCDRV_D2SRC_ADC1_ON)
+ used++;
+ if (adif[i] & MCDRV_D2SRC_PDM0_L_ON)
+ used++;
+ if (adif[i] & MCDRV_D2SRC_PDM0_R_ON)
+ used++;
+ if (adif[i] & MCDRV_D2SRC_PDM1_L_ON)
+ used++;
+ if (adif[i] & MCDRV_D2SRC_PDM1_R_ON)
+ used++;
+ if (adif[i] & MCDRV_D2SRC_DAC0REF_ON)
+ used++;
+ if (adif[i] & MCDRV_D2SRC_DAC1REF_ON)
+ used++;
+ if (used > 1)
+ return -EINVAL;
+ }
+
+ if (!(adif[0] & ~D2SRC_ALL_OFF)
+ && (adif[1] & ~D2SRC_ALL_OFF))
+ return -EINVAL;
+
+ if ((adif[0] & MCDRV_D2SRC_DAC0REF_ON)
+ && (adif[1] & ~MCDRV_D2SRC_DAC0REF_ON))
+ return -EINVAL;
+
+ if ((adif[1] & MCDRV_D2SRC_DAC0REF_ON)
+ && (adif[0] & ~MCDRV_D2SRC_DAC0REF_ON))
+ return -EINVAL;
+
+ if ((adif[0] & MCDRV_D2SRC_DAC1REF_ON)
+ && (adif[1] & ~MCDRV_D2SRC_DAC1REF_ON))
+ return -EINVAL;
+
+ if ((adif[1] & MCDRV_D2SRC_DAC1REF_ON)
+ && (adif[0] & ~MCDRV_D2SRC_DAC1REF_ON))
+ return -EINVAL;
+
+ for (i = 0; i < ADC0_PATH_CHANNELS; i++) {
+ used = 0;
+ src = mc_info.path_info.adc0[i];
+ if (src & MCDRV_ASRC_LINEIN1_L_ON)
+ used++;
+ if (src & MCDRV_ASRC_LINEIN1_R_ON)
+ used++;
+ if (src & MCDRV_ASRC_LINEIN1_M_ON)
+ used++;
+ if (used > 1)
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static inline int phys_port_check(void)
+{
+ u32 port[4] = { MCDRV_PHYSPORT_NONE, MCDRV_PHYSPORT_NONE,
+ MCDRV_PHYSPORT_NONE, MCDRV_PHYSPORT_NONE
+ };
+ int i, j;
+
+ if (mc_source_is_used(MCDRV_DST_MUSICOUT, MCDRV_DST_CH0)
+ || mc_source_is_used(MCDRV_DST_MUSICOUT, MCDRV_DST_CH1)
+ || mc_d1_source_is_used(MCDRV_D1SRC_MUSICIN_ON)) {
+ port[0] = mc_info.dio_path_info.phys_port[0];
+ if (port[0] == MCDRV_PHYSPORT_NONE)
+ return -EINVAL;
+ }
+
+ if (mc_source_is_used(MCDRV_DST_EXTOUT, MCDRV_DST_CH0)
+ || mc_source_is_used(MCDRV_DST_EXTOUT, MCDRV_DST_CH1)
+ || mc_d1_source_is_used(MCDRV_D1SRC_EXTIN_ON)) {
+ port[1] = mc_info.dio_path_info.phys_port[1];
+ if (port[1] == MCDRV_PHYSPORT_NONE)
+ return -EINVAL;
+ }
+
+ if (mc_source_is_used(MCDRV_DST_VOICEOUT, MCDRV_DST_CH0)
+ || mc_source_is_used(MCDRV_DST_VBOXIOIN, MCDRV_DST_CH0)
+ || mc_source_is_used(MCDRV_DST_VBOXIOIN, MCDRV_DST_CH0)) {
+ port[2] = mc_info.dio_path_info.phys_port[2];
+ if (port[2] == MCDRV_PHYSPORT_NONE)
+ return -EINVAL;
+ }
+
+ if (mc_source_is_used(MCDRV_DST_HIFIOUT, MCDRV_DST_CH0)
+ || mc_d1_source_is_used(MCDRV_D1SRC_HIFIIN_ON)) {
+ port[3] = mc_info.dio_path_info.phys_port[3];
+ if (port[3] == MCDRV_PHYSPORT_NONE)
+ return -EINVAL;
+ }
+
+ for (i = 0; i < 4; i++) {
+ if (port[i] == MCDRV_PHYSPORT_NONE)
+ continue;
+
+ for (j = i + 1; j < 4; j++) {
+ if (port[i] == port[j])
+ return -EINVAL;
+ }
+ }
+
+ return 0;
+}
+
+static inline int adc_validate(void)
+{
+ struct mcdrv_path_info *path_info;
+ u32 hifi_out;
+ int has_src, i, ret = 0;
+
+ path_info = &mc_info.path_info;
+
+ has_src = 0;
+ if (mc_source_is_used(MCDRV_DST_ADIF0, MCDRV_DST_CH0)
+ || mc_source_is_used(MCDRV_DST_ADIF0, MCDRV_DST_CH1))
+ has_src = 1;
+
+ hifi_out = path_info->hifi_out[0];
+
+ if ((mc_d1_source_is_used(MCDRV_D1SRC_ADIF0_ON)
+ || (hifi_out & MCDRV_D1SRC_ADIF0_ON)) && !has_src) {
+ for (i = 0; i < MUSICOUT_PATH_CHANNELS; i++) {
+ path_info->music_out[i] &= ~MCDRV_D1SRC_ADIF0_ON;
+ path_info->music_out[i] |= MCDRV_D1SRC_ADIF0_OFF;
+ }
+
+ for (i = 0; i < EXTOUT_PATH_CHANNELS; i++) {
+ path_info->ext_out[i] &= ~MCDRV_D1SRC_ADIF0_ON;
+ path_info->ext_out[i] |= MCDRV_D1SRC_ADIF0_OFF;
+ }
+
+ for (i = 0; i < HIFIOUT_PATH_CHANNELS; i++) {
+ path_info->hifi_out[i] &= ~MCDRV_D1SRC_ADIF0_ON;
+ path_info->hifi_out[i] |= MCDRV_D1SRC_ADIF0_OFF;
+ }
+
+ for (i = 0; i < VBOXMIXIN_PATH_CHANNELS; i++) {
+ path_info->vbox_mix_in[i] &= ~MCDRV_D1SRC_ADIF0_ON;
+ path_info->vbox_mix_in[i] |= MCDRV_D1SRC_ADIF0_OFF;
+ }
+
+ for (i = 0; i < AE_PATH_CHANNELS; i++) {
+ path_info->ae0[i] &= ~MCDRV_D1SRC_ADIF0_ON;
+ path_info->ae0[i] |= MCDRV_D1SRC_ADIF0_OFF;
+ path_info->ae1[i] &= ~MCDRV_D1SRC_ADIF0_ON;
+ path_info->ae1[i] |= MCDRV_D1SRC_ADIF0_OFF;
+ path_info->ae2[i] &= ~MCDRV_D1SRC_ADIF0_ON;
+ path_info->ae2[i] |= MCDRV_D1SRC_ADIF0_OFF;
+ path_info->ae3[i] &= ~MCDRV_D1SRC_ADIF0_ON;
+ path_info->ae3[i] |= MCDRV_D1SRC_ADIF0_OFF;
+ }
+
+ for (i = 0; i < DAC0_PATH_CHANNELS; i++) {
+ path_info->dac0[i] &= ~MCDRV_D1SRC_ADIF0_ON;
+ path_info->dac0[i] |= MCDRV_D1SRC_ADIF0_OFF;
+ }
+
+ for (i = 0; i < DAC1_PATH_CHANNELS; i++) {
+ path_info->dac1[i] &= ~MCDRV_D1SRC_ADIF0_ON;
+ path_info->dac1[i] |= MCDRV_D1SRC_ADIF0_OFF;
+ }
+
+ ret = 1;
+ }
+
+ has_src = 0;
+ if (mc_source_is_used(MCDRV_DST_ADIF1, MCDRV_DST_CH0)
+ || mc_source_is_used(MCDRV_DST_ADIF1, MCDRV_DST_CH1))
+ has_src = 1;
+ if (mc_d1_source_is_used(MCDRV_D1SRC_ADIF1_ON) && !has_src) {
+ for (i = 0; i < MUSICOUT_PATH_CHANNELS; i++) {
+ path_info->music_out[i] &= ~MCDRV_D1SRC_ADIF1_ON;
+ path_info->music_out[i] |= MCDRV_D1SRC_ADIF1_OFF;
+ }
+
+ for (i = 0; i < EXTOUT_PATH_CHANNELS; i++) {
+ path_info->ext_out[i] &= ~MCDRV_D1SRC_ADIF1_ON;
+ path_info->ext_out[i] |= MCDRV_D1SRC_ADIF1_OFF;
+ }
+
+ for (i = 0; i < HIFIOUT_PATH_CHANNELS; i++) {
+ path_info->hifi_out[i] &= ~MCDRV_D1SRC_ADIF1_ON;
+ path_info->hifi_out[i] |= MCDRV_D1SRC_ADIF1_OFF;
+ }
+
+ for (i = 0; i < VBOXMIXIN_PATH_CHANNELS; i++) {
+ path_info->vbox_mix_in[i] &= ~MCDRV_D1SRC_ADIF1_ON;
+ path_info->vbox_mix_in[i] |= MCDRV_D1SRC_ADIF1_OFF;
+ }
+
+ for (i = 0; i < AE_PATH_CHANNELS; i++) {
+ path_info->ae0[i] &= ~MCDRV_D1SRC_ADIF1_ON;
+ path_info->ae0[i] |= MCDRV_D1SRC_ADIF1_OFF;
+ path_info->ae1[i] &= ~MCDRV_D1SRC_ADIF1_ON;
+ path_info->ae1[i] |= MCDRV_D1SRC_ADIF1_OFF;
+ path_info->ae2[i] &= ~MCDRV_D1SRC_ADIF1_ON;
+ path_info->ae2[i] |= MCDRV_D1SRC_ADIF1_OFF;
+ path_info->ae3[i] &= ~MCDRV_D1SRC_ADIF1_ON;
+ path_info->ae3[i] |= MCDRV_D1SRC_ADIF1_OFF;
+ }
+
+ for (i = 0; i < DAC0_PATH_CHANNELS; i++) {
+ path_info->dac0[i] &= ~MCDRV_D1SRC_ADIF1_ON;
+ path_info->dac0[i] |= MCDRV_D1SRC_ADIF1_OFF;
+ }
+
+ for (i = 0; i < DAC1_PATH_CHANNELS; i++) {
+ path_info->dac1[i] &= ~MCDRV_D1SRC_ADIF1_ON;
+ path_info->dac1[i] |= MCDRV_D1SRC_ADIF1_OFF;
+ }
+
+ ret = 1;
+ }
+
+ has_src = 0;
+ if (mc_source_is_used(MCDRV_DST_ADIF2, MCDRV_DST_CH0)
+ || mc_source_is_used(MCDRV_DST_ADIF2, MCDRV_DST_CH1))
+ has_src = 1;
+ if (mc_d1_source_is_used(MCDRV_D1SRC_ADIF2_ON) && !has_src) {
+ for (i = 0; i < MUSICOUT_PATH_CHANNELS; i++) {
+ path_info->music_out[i] &= ~MCDRV_D1SRC_ADIF2_ON;
+ path_info->music_out[i] |= MCDRV_D1SRC_ADIF2_OFF;
+ }
+
+ for (i = 0; i < EXTOUT_PATH_CHANNELS; i++) {
+ path_info->ext_out[i] &= ~MCDRV_D1SRC_ADIF2_ON;
+ path_info->ext_out[i] |= MCDRV_D1SRC_ADIF2_OFF;
+ }
+
+ for (i = 0; i < HIFIOUT_PATH_CHANNELS; i++) {
+ path_info->hifi_out[i] &= ~MCDRV_D1SRC_ADIF2_ON;
+ path_info->hifi_out[i] |= MCDRV_D1SRC_ADIF2_OFF;
+ }
+
+ for (i = 0; i < VBOXMIXIN_PATH_CHANNELS; i++) {
+ path_info->vbox_mix_in[i] &= ~MCDRV_D1SRC_ADIF2_ON;
+ path_info->vbox_mix_in[i] |= MCDRV_D1SRC_ADIF2_OFF;
+ }
+
+ for (i = 0; i < AE_PATH_CHANNELS; i++) {
+ path_info->ae0[i] &= ~MCDRV_D1SRC_ADIF2_ON;
+ path_info->ae0[i] |= MCDRV_D1SRC_ADIF2_OFF;
+ path_info->ae1[i] &= ~MCDRV_D1SRC_ADIF2_ON;
+ path_info->ae1[i] |= MCDRV_D1SRC_ADIF2_OFF;
+ path_info->ae2[i] &= ~MCDRV_D1SRC_ADIF2_ON;
+ path_info->ae2[i] |= MCDRV_D1SRC_ADIF2_OFF;
+ path_info->ae3[i] &= ~MCDRV_D1SRC_ADIF2_ON;
+ path_info->ae3[i] |= MCDRV_D1SRC_ADIF2_OFF;
+ }
+
+ for (i = 0; i < DAC0_PATH_CHANNELS; i++) {
+ path_info->dac0[i] &= ~MCDRV_D1SRC_ADIF2_ON;
+ path_info->dac0[i] |= MCDRV_D1SRC_ADIF2_OFF;
+ }
+
+ for (i = 0; i < DAC1_PATH_CHANNELS; i++) {
+ path_info->dac1[i] &= ~MCDRV_D1SRC_ADIF2_ON;
+ path_info->dac1[i] |= MCDRV_D1SRC_ADIF2_OFF;
+ }
+
+ ret = 1;
+ }
+
+ has_src = 0;
+ if (mc_source_is_used(MCDRV_DST_ADC0, MCDRV_DST_CH0))
+ has_src = 1;
+ if (!mc_d2_source_is_used(MCDRV_D2SRC_ADC0_L_ON)) {
+ if (has_src) {
+ path_info->adc0[0] = D2SRC_ALL_OFF;
+ ret = 1;
+ }
+ } else if (!has_src) {
+ for (i = 0; i < ADIF0_PATH_CHANNELS; i++) {
+ path_info->adif0[i] &= ~MCDRV_D2SRC_ADC0_L_ON;
+ path_info->adif0[i] |= MCDRV_D2SRC_ADC0_L_OFF;
+ }
+
+ for (i = 0; i < ADIF1_PATH_CHANNELS; i++) {
+ path_info->adif1[i] &= ~MCDRV_D2SRC_ADC0_L_ON;
+ path_info->adif1[i] |= MCDRV_D2SRC_ADC0_L_OFF;
+ }
+
+ for (i = 0; i < ADIF2_PATH_CHANNELS; i++) {
+ path_info->adif2[i] &= ~MCDRV_D2SRC_ADC0_L_ON;
+ path_info->adif2[i] |= MCDRV_D2SRC_ADC0_L_OFF;
+ }
+
+ ret = 1;
+ }
+
+ has_src = 0;
+ if (mc_source_is_used(MCDRV_DST_ADC0, MCDRV_DST_CH1))
+ has_src = 1;
+ if (!mc_d2_source_is_used(MCDRV_D2SRC_ADC0_R_ON)) {
+ if (has_src) {
+ path_info->adc0[1] = D2SRC_ALL_OFF;
+ ret = 1;
+ }
+ } else if (!has_src) {
+ for (i = 0; i < ADIF0_PATH_CHANNELS; i++) {
+ path_info->adif0[i] &= ~MCDRV_D2SRC_ADC0_R_ON;
+ path_info->adif0[i] |= MCDRV_D2SRC_ADC0_R_OFF;
+ }
+
+ for (i = 0; i < ADIF1_PATH_CHANNELS; i++) {
+ path_info->adif1[i] &= ~MCDRV_D2SRC_ADC0_R_ON;
+ path_info->adif1[i] |= MCDRV_D2SRC_ADC0_R_OFF;
+ }
+
+ for (i = 0; i < ADIF2_PATH_CHANNELS; i++) {
+ path_info->adif2[i] &= ~MCDRV_D2SRC_ADC0_R_ON;
+ path_info->adif2[i] |= MCDRV_D2SRC_ADC0_R_OFF;
+ }
+
+ ret = 1;
+ }
+
+ has_src = 0;
+ if (mc_source_is_used(MCDRV_DST_ADC1, MCDRV_DST_CH0))
+ has_src = 1;
+ if (!mc_d2_source_is_used(MCDRV_D2SRC_ADC1_ON)) {
+ if (has_src) {
+ for (i = 0; i < ADC1_PATH_CHANNELS; i++)
+ path_info->adc1[i] = D2SRC_ALL_OFF;
+ ret = 1;
+ }
+ } else if (!has_src) {
+ for (i = 0; i < ADIF0_PATH_CHANNELS; i++) {
+ path_info->adif0[i] &= ~MCDRV_D2SRC_ADC1_ON;
+ path_info->adif0[i] |= MCDRV_D2SRC_ADC1_OFF;
+ }
+
+ for (i = 0; i < ADIF1_PATH_CHANNELS; i++) {
+ path_info->adif1[i] &= ~MCDRV_D2SRC_ADC1_ON;
+ path_info->adif1[i] |= MCDRV_D2SRC_ADC1_OFF;
+ }
+
+ for (i = 0; i < ADIF2_PATH_CHANNELS; i++) {
+ path_info->adif2[i] &= ~MCDRV_D2SRC_ADC1_ON;
+ path_info->adif2[i] |= MCDRV_D2SRC_ADC1_OFF;
+ }
+
+ ret = 1;
+ }
+
+ return ret;
+}
+
+static inline int dac_validate(void)
+{
+ struct mcdrv_path_info *path_info;
+ int has_src, used, i, ret = 0;
+
+ path_info = &mc_info.path_info;
+
+ has_src = 0;
+ used = 0;
+ if (mc_source_is_used(MCDRV_DST_DAC0, MCDRV_DST_CH0)
+ || mc_source_is_used(MCDRV_DST_DAC0, MCDRV_DST_CH1))
+ has_src = 1;
+
+ if (mc_a_source_is_used(MCDRV_ASRC_DAC0_L_ON)
+ || mc_a_source_is_used(MCDRV_ASRC_DAC0_R_ON))
+ used = 1;
+ else {
+ for (i = 0; i < ADIF2_PATH_CHANNELS; i++) {
+ if (path_info->adif2[i] & MCDRV_D2SRC_DAC0REF_ON)
+ used = 1;
+ }
+ }
+ if (!has_src) {
+ if (used) {
+ for (i = 0; i < HP_PATH_CHANNELS; i++) {
+ path_info->hp[i] &= ~MCDRV_ASRC_DAC0_L_ON;
+ path_info->hp[i] |= MCDRV_ASRC_DAC0_L_OFF;
+ path_info->hp[i] &= ~MCDRV_ASRC_DAC0_R_ON;
+ path_info->hp[i] |= MCDRV_ASRC_DAC0_R_OFF;
+ }
+
+ for (i = 0; i < RC_PATH_CHANNELS; i++) {
+ path_info->rc[i] &= ~MCDRV_ASRC_DAC0_L_ON;
+ path_info->rc[i] |= MCDRV_ASRC_DAC0_L_OFF;
+ path_info->rc[i] &= ~MCDRV_ASRC_DAC0_R_ON;
+ path_info->rc[i] |= MCDRV_ASRC_DAC0_R_OFF;
+ }
+
+ for (i = 0; i < LOUT1_PATH_CHANNELS; i++) {
+ path_info->lout1[i] &= ~MCDRV_ASRC_DAC0_L_ON;
+ path_info->lout1[i] |= MCDRV_ASRC_DAC0_L_OFF;
+ path_info->lout1[i] &= ~MCDRV_ASRC_DAC0_R_ON;
+ path_info->lout1[i] |= MCDRV_ASRC_DAC0_R_OFF;
+ }
+
+ ret = 1;
+ }
+
+ for (i = 0; i < ADIF2_PATH_CHANNELS; i++) {
+ if (path_info->adif2[i] & MCDRV_D2SRC_DAC0REF_ON) {
+ path_info->adif2[i] &= ~MCDRV_D2SRC_DAC0REF_ON;
+ ret = 1;
+ }
+ }
+ }
+
+ has_src = 0;
+ used = 0;
+ if (mc_source_is_used(MCDRV_DST_DAC1, MCDRV_DST_CH0)
+ || mc_source_is_used(MCDRV_DST_DAC1, MCDRV_DST_CH1))
+ has_src = 1;
+ if (mc_a_source_is_used(MCDRV_ASRC_DAC1_L_ON)
+ || mc_a_source_is_used(MCDRV_ASRC_DAC1_R_ON))
+ used = 1;
+ else {
+ for (i = 0; i < ADIF2_PATH_CHANNELS; i++) {
+ if (path_info->adif2[i] & MCDRV_D2SRC_DAC1REF_ON)
+ used = 1;
+ }
+ }
+ if (!has_src) {
+ if (used) {
+ ret = 1;
+ for (i = 0; i < SP_PATH_CHANNELS; i++) {
+ path_info->sp[i] &= ~MCDRV_ASRC_DAC1_L_ON;
+ path_info->sp[i] |= MCDRV_ASRC_DAC1_L_OFF;
+ path_info->sp[i] &= ~MCDRV_ASRC_DAC1_R_ON;
+ path_info->sp[i] |= MCDRV_ASRC_DAC1_R_OFF;
+ }
+
+ for (i = 0; i < LOUT2_PATH_CHANNELS; i++) {
+ path_info->lout2[i] &= ~MCDRV_ASRC_DAC1_L_ON;
+ path_info->lout2[i] |= MCDRV_ASRC_DAC1_L_OFF;
+ path_info->lout2[i] &= ~MCDRV_ASRC_DAC1_R_ON;
+ path_info->lout2[i] |= MCDRV_ASRC_DAC1_R_OFF;
+ }
+ }
+
+ for (i = 0; i < ADIF2_PATH_CHANNELS; i++) {
+ if (path_info->adif2[i] & MCDRV_D2SRC_DAC1REF_ON) {
+ path_info->adif2[i] &= ~MCDRV_D2SRC_DAC1REF_ON;
+ ret = 1;
+ }
+ }
+ }
+
+ return ret;
+}
+
+int mc_path_info_set(struct mcdrv_path_info *path_info)
+{
+ struct mcdrv_path_info old_path_info;
+ int cont, i, ret;
+
+ old_path_info = mc_info.path_info;
+ mc_info.path_info = mc_info.path_info_virtual;
+
+ d1_source_set_onoff(path_info->music_out,
+ mc_info.path_info.music_out,
+ MUSICOUT_PATH_CHANNELS);
+ d1_source_set_onoff(path_info->ext_out,
+ mc_info.path_info.ext_out, EXTOUT_PATH_CHANNELS);
+ d1_source_set_onoff(path_info->hifi_out,
+ mc_info.path_info.hifi_out, HIFIOUT_PATH_CHANNELS);
+ d1_source_set_onoff(path_info->vbox_mix_in,
+ mc_info.path_info.vbox_mix_in,
+ VBOXMIXIN_PATH_CHANNELS);
+ d1_source_set_onoff(path_info->ae0,
+ mc_info.path_info.ae0, AE_PATH_CHANNELS);
+ d1_source_set_onoff(path_info->ae1,
+ mc_info.path_info.ae1, AE_PATH_CHANNELS);
+ d1_source_set_onoff(path_info->ae2,
+ mc_info.path_info.ae2, AE_PATH_CHANNELS);
+ d1_source_set_onoff(path_info->ae3,
+ mc_info.path_info.ae3, AE_PATH_CHANNELS);
+ d1_source_set_onoff(path_info->dac0,
+ mc_info.path_info.dac0, DAC0_PATH_CHANNELS);
+ d1_source_set_onoff(path_info->dac1,
+ mc_info.path_info.dac1, DAC1_PATH_CHANNELS);
+
+ d2_source_set_onoff(path_info->voice_out,
+ mc_info.path_info.voice_out,
+ VOICEOUT_PATH_CHANNELS);
+ d2_source_set_onoff(path_info->vbox_io_in,
+ mc_info.path_info.vbox_io_in,
+ VBOXIOIN_PATH_CHANNELS);
+ d2_source_set_onoff(path_info->vbox_host_in,
+ mc_info.path_info.vbox_host_in,
+ VBOXHOSTIN_PATH_CHANNELS);
+ d2_source_set_onoff(path_info->host_out,
+ mc_info.path_info.host_out, HOSTOUT_PATH_CHANNELS);
+ d2_source_set_onoff(path_info->adif0,
+ mc_info.path_info.adif0, ADIF0_PATH_CHANNELS);
+ d2_source_set_onoff(path_info->adif1,
+ mc_info.path_info.adif1, ADIF1_PATH_CHANNELS);
+ d2_source_set_onoff(path_info->adif2,
+ mc_info.path_info.adif2, ADIF2_PATH_CHANNELS);
+
+ a_source_set_onoff(path_info->adc0,
+ mc_info.path_info.adc0, ADC0_PATH_CHANNELS);
+ a_source_set_onoff(path_info->adc1,
+ mc_info.path_info.adc1, ADC1_PATH_CHANNELS);
+ a_source_set_onoff(path_info->sp,
+ mc_info.path_info.sp, SP_PATH_CHANNELS);
+ a_source_set_onoff(path_info->hp,
+ mc_info.path_info.hp, HP_PATH_CHANNELS);
+ a_source_set_onoff(path_info->rc,
+ mc_info.path_info.rc, RC_PATH_CHANNELS);
+ a_source_set_onoff(path_info->lout1,
+ mc_info.path_info.lout1, LOUT1_PATH_CHANNELS);
+ a_source_set_onoff(path_info->lout2,
+ mc_info.path_info.lout2, LOUT2_PATH_CHANNELS);
+
+ bias_source_set_onoff(path_info);
+
+ ret = is_valid_path();
+ if (ret < 0) {
+ mc_info.path_info = old_path_info;
+ return ret;
+ }
+
+ ret = phys_port_check();
+ if (ret < 0) {
+ mc_info.path_info = old_path_info;
+ return ret;
+ }
+
+ mc_info.path_info_virtual = mc_info.path_info;
+
+ for (i = 0, cont = 1; i < 3 && cont; i++) {
+ cont = adc_validate();
+ cont |= dac_validate();
+ }
+
+ return 0;
+}
+
+void mc_path_info_get(struct mcdrv_path_info *path_info)
+{
+ *path_info = mc_info.path_info;
+}
+
+void mc_path_info_get_virtual(struct mcdrv_path_info *path_info)
+{
+ *path_info = mc_info.path_info_virtual;
+}
+
+void mc_vol_info_set(struct mcdrv_vol_info *vol_info)
+{
+ int i;
+
+ for (i = 0; i < MUSICIN_VOL_CHANNELS; i++) {
+ if (vol_info->d_music_in[i] & 1)
+ mc_info.vol_info.d_music_in[i] =
+ vol_info->d_music_in[i] & ~1;
+ }
+
+ for (i = 0; i < EXTIN_VOL_CHANNELS; i++) {
+ if (vol_info->d_ext_in[i] & 1)
+ mc_info.vol_info.d_ext_in[i] =
+ vol_info->d_ext_in[i] & ~1;
+ }
+
+ for (i = 0; i < VOICEIN_VOL_CHANNELS; i++) {
+ if (vol_info->d_voice_in[i] & 1)
+ mc_info.vol_info.d_voice_in[i] =
+ vol_info->d_voice_in[i] & ~1;
+ }
+
+ for (i = 0; i < REFIN_VOL_CHANNELS; i++) {
+ if (vol_info->d_ref_in[i] & 1)
+ mc_info.vol_info.d_ref_in[i] =
+ vol_info->d_ref_in[i] & ~1;
+ }
+
+ for (i = 0; i < ADIF0IN_VOL_CHANNELS; i++) {
+ if (vol_info->d_adif0_in[i] & 1)
+ mc_info.vol_info.d_adif0_in[i] =
+ vol_info->d_adif0_in[i] & ~1;
+ }
+
+ for (i = 0; i < ADIF1IN_VOL_CHANNELS; i++) {
+ if (vol_info->d_adif1_in[i] & 1)
+ mc_info.vol_info.d_adif1_in[i] =
+ vol_info->d_adif1_in[i] & ~1;
+ }
+
+ for (i = 0; i < ADIF2IN_VOL_CHANNELS; i++) {
+ if (vol_info->d_adif2_in[i] & 1)
+ mc_info.vol_info.d_adif2_in[i] =
+ vol_info->d_adif2_in[i] & ~1;
+ }
+
+ for (i = 0; i < MUSICOUT_VOL_CHANNELS; i++) {
+ if (vol_info->d_music_out[i] & 1)
+ mc_info.vol_info.d_music_out[i] =
+ vol_info->d_music_out[i] & ~1;
+ }
+
+ for (i = 0; i < EXTOUT_VOL_CHANNELS; i++) {
+ if (vol_info->d_ext_out[i] & 1)
+ mc_info.vol_info.d_ext_out[i] =
+ vol_info->d_ext_out[i] & ~1;
+ }
+
+ for (i = 0; i < VOICEOUT_VOL_CHANNELS; i++) {
+ if (vol_info->d_voice_out[i] & 1)
+ mc_info.vol_info.d_voice_out[i] =
+ vol_info->d_voice_out[i] & ~1;
+ }
+
+ for (i = 0; i < REFOUT_VOL_CHANNELS; i++) {
+ if (vol_info->d_ref_out[i] & 1)
+ mc_info.vol_info.d_ref_out[i] =
+ vol_info->d_ref_out[i] & ~1;
+ }
+
+ for (i = 0; i < DAC0OUT_VOL_CHANNELS; i++) {
+ if (vol_info->d_dac0_out[i] & 1)
+ mc_info.vol_info.d_dac0_out[i] =
+ vol_info->d_dac0_out[i] & ~1;
+ }
+
+ for (i = 0; i < DAC1OUT_VOL_CHANNELS; i++) {
+ if (vol_info->d_dac1_out[i] & 1)
+ mc_info.vol_info.d_dac1_out[i] =
+ vol_info->d_dac1_out[i] & ~1;
+ }
+
+ for (i = 0; i < DPATH_VOL_CHANNELS; i++) {
+ if (vol_info->d_dpath_da[i] & 1)
+ mc_info.vol_info.d_dpath_da[i] =
+ vol_info->d_dpath_da[i] & ~1;
+
+ if (vol_info->d_dpath_ad[i] & 1)
+ mc_info.vol_info.d_dpath_ad[i] =
+ vol_info->d_dpath_ad[i] & ~1;
+ }
+
+ for (i = 0; i < LINEIN1_VOL_CHANNELS; i++) {
+ if (vol_info->a_line_in1[i] & 1)
+ mc_info.vol_info.a_line_in1[i] =
+ vol_info->a_line_in1[i] & ~1;
+ }
+
+ for (i = 0; i < MIC1_VOL_CHANNELS; i++) {
+ if (vol_info->a_mic1[i] & 1)
+ mc_info.vol_info.a_mic1[i] = vol_info->a_mic1[i] & ~1;
+ }
+
+ for (i = 0; i < MIC2_VOL_CHANNELS; i++) {
+ if (vol_info->a_mic2[i] & 1)
+ mc_info.vol_info.a_mic2[i] = vol_info->a_mic2[i] & ~1;
+ }
+
+ for (i = 0; i < MIC3_VOL_CHANNELS; i++) {
+ if (vol_info->a_mic3[i] & 1)
+ mc_info.vol_info.a_mic3[i] = vol_info->a_mic3[i] & ~1;
+ }
+
+ for (i = 0; i < MIC4_VOL_CHANNELS; i++) {
+ if (vol_info->a_mic4[i] & 1)
+ mc_info.vol_info.a_mic4[i] = vol_info->a_mic4[i] & ~1;
+ }
+
+ for (i = 0; i < HP_VOL_CHANNELS; i++) {
+ if (vol_info->a_hp[i] & 1)
+ mc_info.vol_info.a_hp[i] = vol_info->a_hp[i] & ~1;
+ }
+
+ for (i = 0; i < SP_VOL_CHANNELS; i++) {
+ if (vol_info->a_sp[i] & 1)
+ mc_info.vol_info.a_sp[i] = vol_info->a_sp[i] & ~1;
+ }
+
+ for (i = 0; i < RC_VOL_CHANNELS; i++) {
+ if (vol_info->a_rc[i] & 1)
+ mc_info.vol_info.a_rc[i] = vol_info->a_rc[i] & ~1;
+ }
+
+ for (i = 0; i < LINEOUT1_VOL_CHANNELS; i++) {
+ if (vol_info->a_line_out1[i] & 1)
+ mc_info.vol_info.a_line_out1[i] =
+ vol_info->a_line_out1[i] & ~1;
+ }
+
+ for (i = 0; i < LINEOUT2_VOL_CHANNELS; i++) {
+ if (vol_info->a_line_out2[i] & 1)
+ mc_info.vol_info.a_line_out2[i] =
+ vol_info->a_line_out2[i] & ~1;
+ }
+
+ for (i = 0; i < HPDET_VOL_CHANNELS; i++) {
+ if (vol_info->a_hp_det[i] & 1)
+ mc_info.vol_info.a_hp_det[i] =
+ vol_info->a_hp_det[i] & ~1;
+ }
+}
+
+void mc_vol_info_get(struct mcdrv_vol_info *vol_info)
+{
+ *vol_info = mc_info.vol_info;
+}
+
+static void dio_common_set(struct mcdrv_dio_common *dio_common, u8 port)
+{
+ struct mcdrv_dio_common *common;
+
+ common = &mc_info.dio_info.port[port].dio_common;
+
+ common->master_slave = dio_common->master_slave;
+ common->auto_fs = dio_common->auto_fs;
+ common->fs = dio_common->fs;
+ common->bck_fs = dio_common->bck_fs;
+ common->interface = dio_common->interface;
+ common->bck_invert = dio_common->bck_invert;
+ common->src_thru = dio_common->src_thru;
+
+ if (dio_common->interface == MCDRV_DIO_PCM) {
+ common->pcm_hiz_transition = dio_common->pcm_hiz_transition;
+ common->pcm_frame = dio_common->pcm_frame;
+ common->pcm_high_period = dio_common->pcm_high_period;
+ }
+}
+
+static void dio_dir_set(struct mcdrv_dio_dir *dio_dir, u8 port)
+{
+ struct mcdrv_dio_dir *dir;
+
+ dir = &mc_info.dio_info.port[port].dir;
+
+ if (mc_info.dio_info.port[port].dio_common.interface == MCDRV_DIO_DA) {
+ dir->da_format.bit_sel = dio_dir->da_format.bit_sel;
+ dir->da_format.mode = dio_dir->da_format.mode;
+ } else {
+ dir->pcm_format.mono = dio_dir->pcm_format.mono;
+ dir->pcm_format.order = dio_dir->pcm_format.order;
+ dir->pcm_format.law = dio_dir->pcm_format.law;
+ dir->pcm_format.bit_sel = dio_dir->pcm_format.bit_sel;
+ }
+}
+
+static void dio_dit_set(struct mcdrv_dio_dit *dio_dit, u8 port)
+{
+ struct mcdrv_dio_dit *dit;
+
+ dit = &mc_info.dio_info.port[port].dit;
+
+ dit->st_mode = dio_dit->st_mode;
+ dit->edge = dio_dit->edge;
+ if (mc_info.dio_info.port[port].dio_common.interface == MCDRV_DIO_DA) {
+ dit->da_format.bit_sel = dio_dit->da_format.bit_sel;
+ dit->da_format.mode = dio_dit->da_format.mode;
+ } else {
+ dit->pcm_format.mono = dio_dit->pcm_format.mono;
+ dit->pcm_format.order = dio_dit->pcm_format.order;
+ dit->pcm_format.law = dio_dit->pcm_format.law;
+ dit->pcm_format.bit_sel = dio_dit->pcm_format.bit_sel;
+ }
+}
+
+void mc_dio_info_set(struct mcdrv_dio_info *dio_info, u32 update)
+{
+ if (update & MCDRV_MUSIC_COM_UPDATE_FLAG)
+ dio_common_set(&dio_info->port[0].dio_common, 0);
+
+ if (update & MCDRV_EXT_COM_UPDATE_FLAG)
+ dio_common_set(&dio_info->port[1].dio_common, 1);
+
+ if (update & MCDRV_VOICE_COM_UPDATE_FLAG)
+ dio_common_set(&dio_info->port[2].dio_common, 2);
+
+ if (update & MCDRV_HIFI_COM_UPDATE_FLAG)
+ dio_common_set(&dio_info->port[3].dio_common, 3);
+
+ if (update & MCDRV_MUSIC_DIR_UPDATE_FLAG)
+ dio_dir_set(&dio_info->port[0].dir, 0);
+
+ if (update & MCDRV_EXT_DIR_UPDATE_FLAG)
+ dio_dir_set(&dio_info->port[1].dir, 1);
+
+ if (update & MCDRV_VOICE_DIR_UPDATE_FLAG)
+ dio_dir_set(&dio_info->port[2].dir, 2);
+
+ if (update & MCDRV_HIFI_DIR_UPDATE_FLAG)
+ dio_dir_set(&dio_info->port[3].dir, 3);
+
+ if (update & MCDRV_MUSIC_DIT_UPDATE_FLAG)
+ dio_dit_set(&dio_info->port[0].dit, 0);
+
+ if (update & MCDRV_EXT_DIT_UPDATE_FLAG)
+ dio_dit_set(&dio_info->port[1].dit, 1);
+
+ if (update & MCDRV_VOICE_DIT_UPDATE_FLAG)
+ dio_dit_set(&dio_info->port[2].dit, 2);
+
+ if (update & MCDRV_HIFI_DIT_UPDATE_FLAG)
+ dio_dit_set(&dio_info->port[3].dit, 3);
+}
+
+void mc_dio_info_get(struct mcdrv_dio_info *dio_info)
+{
+ *dio_info = mc_info.dio_info;
+}
+
+void mc_dio_path_info_set(struct mcdrv_dio_path_info *dio_path_info, u32 update)
+{
+ if (update & MCDRV_MUSICNUM_UPDATE_FLAG)
+ mc_info.dio_path_info.music_ch = dio_path_info->music_ch;
+
+ if (update & MCDRV_PHYS0_UPDATE_FLAG)
+ mc_info.dio_path_info.phys_port[0]
+ = dio_path_info->phys_port[0];
+
+ if (update & MCDRV_PHYS1_UPDATE_FLAG)
+ mc_info.dio_path_info.phys_port[1]
+ = dio_path_info->phys_port[1];
+
+ if (update & MCDRV_PHYS2_UPDATE_FLAG)
+ mc_info.dio_path_info.phys_port[2]
+ = dio_path_info->phys_port[2];
+
+ if (update & MCDRV_PHYS3_UPDATE_FLAG)
+ mc_info.dio_path_info.phys_port[3]
+ = dio_path_info->phys_port[3];
+
+ if (update & MCDRV_DIR0SLOT_UPDATE_FLAG)
+ mc_info.dio_path_info.music_rslot[0]
+ = dio_path_info->music_rslot[0];
+
+ if (update & MCDRV_DIR1SLOT_UPDATE_FLAG)
+ mc_info.dio_path_info.music_rslot[1]
+ = dio_path_info->music_rslot[1];
+
+ if (update & MCDRV_DIR2SLOT_UPDATE_FLAG)
+ mc_info.dio_path_info.music_rslot[2]
+ = dio_path_info->music_rslot[2];
+
+ if (update & MCDRV_DIT0SLOT_UPDATE_FLAG)
+ mc_info.dio_path_info.music_tslot[0]
+ = dio_path_info->music_tslot[0];
+
+ if (update & MCDRV_DIT1SLOT_UPDATE_FLAG)
+ mc_info.dio_path_info.music_tslot[1]
+ = dio_path_info->music_tslot[1];
+
+ if (update & MCDRV_DIT2SLOT_UPDATE_FLAG)
+ mc_info.dio_path_info.music_tslot[2]
+ = dio_path_info->music_tslot[2];
+}
+
+void mc_dio_path_info_get(struct mcdrv_dio_path_info *dio_path_info)
+{
+ *dio_path_info = mc_info.dio_path_info;
+}
+
+void mc_swap_info_set(struct mcdrv_swap_info *swap_info, u32 update)
+{
+ if (update & MCDRV_SWAP_ADIF0_UPDATE_FLAG)
+ mc_info.swap_info.adif0 = swap_info->adif0;
+
+ if (update & MCDRV_SWAP_ADIF1_UPDATE_FLAG)
+ mc_info.swap_info.adif1 = swap_info->adif1;
+
+ if (update & MCDRV_SWAP_ADIF2_UPDATE_FLAG)
+ mc_info.swap_info.adif2 = swap_info->adif2;
+
+ if (update & MCDRV_SWAP_DAC0_UPDATE_FLAG)
+ mc_info.swap_info.dac0 = swap_info->dac0;
+
+ if (update & MCDRV_SWAP_DAC1_UPDATE_FLAG)
+ mc_info.swap_info.dac1 = swap_info->dac1;
+
+ if (update & MCDRV_SWAP_MUSICIN0_UPDATE_FLAG)
+ mc_info.swap_info.music_in0 = swap_info->music_in0;
+
+ if (update & MCDRV_SWAP_MUSICIN1_UPDATE_FLAG)
+ mc_info.swap_info.music_in1 = swap_info->music_in1;
+
+ if (update & MCDRV_SWAP_MUSICIN2_UPDATE_FLAG)
+ mc_info.swap_info.music_in2 = swap_info->music_in2;
+
+ if (update & MCDRV_SWAP_EXTIN_UPDATE_FLAG)
+ mc_info.swap_info.ext_in = swap_info->ext_in;
+
+ if (update & MCDRV_SWAP_VOICEIN_UPDATE_FLAG)
+ mc_info.swap_info.voice_in = swap_info->voice_in;
+
+ if (update & MCDRV_SWAP_HIFIIN_UPDATE_FLAG)
+ mc_info.swap_info.hifi_in = swap_info->hifi_in;
+
+ if (update & MCDRV_SWAP_MUSICOUT0_UPDATE_FLAG)
+ mc_info.swap_info.music_out0 = swap_info->music_out0;
+
+ if (update & MCDRV_SWAP_MUSICOUT1_UPDATE_FLAG)
+ mc_info.swap_info.music_out1 = swap_info->music_out1;
+
+ if (update & MCDRV_SWAP_MUSICOUT2_UPDATE_FLAG)
+ mc_info.swap_info.music_out2 = swap_info->music_out2;
+
+ if (update & MCDRV_SWAP_EXTOUT_UPDATE_FLAG)
+ mc_info.swap_info.ext_out = swap_info->ext_out;
+
+ if (update & MCDRV_SWAP_VOICEOUT_UPDATE_FLAG)
+ mc_info.swap_info.voice_out = swap_info->voice_out;
+
+ if (update & MCDRV_SWAP_HIFIOUT_UPDATE_FLAG)
+ mc_info.swap_info.hifi_out = swap_info->hifi_out;
+}
+
+void mc_swap_info_get(struct mcdrv_swap_info *swap_info)
+{
+ *swap_info = mc_info.swap_info;
+}
+
+void mc_hsdet_info_set(struct mcdrv_hsdet_info *hsdet_info, u32 update)
+{
+ struct mcdrv_hsdet_info *hsdet;
+
+ hsdet = &mc_info.hsdet_info;
+
+ if (update & MCDRV_ENPLUGDET_UPDATE_FLAG)
+ hsdet->en_plug_det = hsdet_info->en_plug_det;
+
+ if (update & MCDRV_ENPLUGDETDB_UPDATE_FLAG)
+ hsdet->en_plug_det_db = hsdet_info->en_plug_det_db;
+
+ if (update & MCDRV_ENDLYKEYOFF_UPDATE_FLAG)
+ hsdet->en_dly_key_off = hsdet_info->en_dly_key_off;
+
+ if (update & MCDRV_ENDLYKEYON_UPDATE_FLAG)
+ hsdet->en_dly_key_on = hsdet_info->en_dly_key_on;
+
+ if (update & MCDRV_ENMICDET_UPDATE_FLAG)
+ hsdet->en_mic_det = hsdet_info->en_mic_det;
+
+ if (update & MCDRV_ENKEYOFF_UPDATE_FLAG)
+ hsdet->en_key_off = hsdet_info->en_key_off;
+
+ if (update & MCDRV_ENKEYON_UPDATE_FLAG)
+ hsdet->en_key_on = hsdet_info->en_key_on;
+
+ if (update & MCDRV_HSDETDBNC_UPDATE_FLAG)
+ hsdet->hs_det_dbnc = hsdet_info->hs_det_dbnc;
+
+ if (update & MCDRV_KEYOFFMTIM_UPDATE_FLAG)
+ hsdet->key_off_mtim = hsdet_info->key_off_mtim;
+
+ if (update & MCDRV_KEYONMTIM_UPDATE_FLAG)
+ hsdet->key_on_mtim = hsdet_info->key_on_mtim;
+
+ if (update & MCDRV_KEY0OFFDLYTIM_UPDATE_FLAG)
+ hsdet->key0_off_dly_tim = hsdet_info->key0_off_dly_tim;
+
+ if (update & MCDRV_KEY1OFFDLYTIM_UPDATE_FLAG)
+ hsdet->key1_off_dly_tim = hsdet_info->key1_off_dly_tim;
+
+ if (update & MCDRV_KEY2OFFDLYTIM_UPDATE_FLAG)
+ hsdet->key2_off_dly_tim = hsdet_info->key2_off_dly_tim;
+
+ if (update & MCDRV_KEY0ONDLYTIM_UPDATE_FLAG)
+ hsdet->key0_on_dly_tim = hsdet_info->key0_on_dly_tim;
+
+ if (update & MCDRV_KEY1ONDLYTIM_UPDATE_FLAG)
+ hsdet->key1_on_dly_tim = hsdet_info->key1_on_dly_tim;
+
+ if (update & MCDRV_KEY2ONDLYTIM_UPDATE_FLAG)
+ hsdet->key2_on_dly_tim = hsdet_info->key2_on_dly_tim;
+
+ if (update & MCDRV_KEY0ONDLYTIM2_UPDATE_FLAG)
+ hsdet->key0_on_dly_tim2 = hsdet_info->key0_on_dly_tim2;
+
+ if (update & MCDRV_KEY1ONDLYTIM2_UPDATE_FLAG)
+ hsdet->key1_on_dly_tim2 = hsdet_info->key1_on_dly_tim2;
+
+ if (update & MCDRV_KEY2ONDLYTIM2_UPDATE_FLAG)
+ hsdet->key2_on_dly_tim2 = hsdet_info->key2_on_dly_tim2;
+
+ if (update & MCDRV_IRQTYPE_UPDATE_FLAG) {
+ hsdet->irq_type = hsdet_info->irq_type;
+ hsdet->plug_det_db_irq_type = hsdet_info->plug_det_db_irq_type;
+ hsdet->plug_undet_db_irq_type
+ = hsdet_info->plug_undet_db_irq_type;
+ hsdet->mic_det_irq_type = hsdet_info->mic_det_irq_type;
+ hsdet->plug_det_irq_type = hsdet_info->plug_det_irq_type;
+ hsdet->key0_on_irq_type = hsdet_info->key0_on_irq_type;
+ hsdet->key1_on_irq_type = hsdet_info->key1_on_irq_type;
+ hsdet->key2_on_irq_type = hsdet_info->key2_on_irq_type;
+ hsdet->key0_off_irq_type = hsdet_info->key0_off_irq_type;
+ hsdet->key1_off_irq_type = hsdet_info->key1_off_irq_type;
+ hsdet->key2_off_irq_type = hsdet_info->key2_off_irq_type;
+ }
+
+ if (update & MCDRV_DETINV_UPDATE_FLAG)
+ hsdet->det_in_inv = hsdet_info->det_in_inv;
+
+ if (update & MCDRV_HSDETMODE_UPDATE_FLAG)
+ hsdet->hs_det_mode = hsdet_info->hs_det_mode;
+
+ if (update & MCDRV_SPERIOD_UPDATE_FLAG)
+ hsdet->speriod = hsdet_info->speriod;
+
+ if (update & MCDRV_LPERIOD_UPDATE_FLAG)
+ hsdet->lperiod = hsdet_info->lperiod;
+
+ if (update & MCDRV_DBNCNUMPLUG_UPDATE_FLAG)
+ hsdet->dbnc_num_plug = hsdet_info->dbnc_num_plug;
+
+ if (update & MCDRV_DBNCNUMMIC_UPDATE_FLAG)
+ hsdet->dbnc_num_mic = hsdet_info->dbnc_num_mic;
+
+ if (update & MCDRV_DBNCNUMKEY_UPDATE_FLAG)
+ hsdet->dbnc_num_key = hsdet_info->dbnc_num_key;
+
+ if (update & MCDRV_SGNL_UPDATE_FLAG) {
+ hsdet->sgnl_period = hsdet_info->sgnl_period;
+ hsdet->sgnl_num = hsdet_info->sgnl_num;
+ hsdet->sgnl_peak = hsdet_info->sgnl_peak;
+ }
+
+ if (update & MCDRV_IMPSEL_UPDATE_FLAG)
+ hsdet->imp_sel = hsdet_info->imp_sel;
+
+ if (update & MCDRV_DLYIRQSTOP_UPDATE_FLAG)
+ hsdet->dly_irq_stop = hsdet_info->dly_irq_stop;
+
+ if (update & MCDRV_CBFUNC_UPDATE_FLAG)
+ hsdet->cbfunc = hsdet_info->cbfunc;
+}
+
+void mc_hsdet_info_get(struct mcdrv_hsdet_info *hsdet_info)
+{
+ *hsdet_info = mc_info.hsdet_info;
+}
+
+void mc_aec_info_set(struct mcdrv_aec_info *aec_info)
+{
+ struct mcdrv_aec_info *aec;
+ struct mcdrv_aec_output *out;
+ struct mcdrv_aec_input *in;
+ int i;
+
+ aec = &mc_info.aec_info;
+
+ if (aec_info->fdsp_locate != 0xff)
+ aec->fdsp_locate = aec_info->fdsp_locate;
+
+ aec->audio_engine.enable = aec_info->audio_engine.enable;
+ if (aec_info->audio_engine.enable) {
+ struct mcdrv_aec_audio_engine *ae = &aec->audio_engine;
+
+ if (aec_info->audio_engine.on != 2)
+ ae->on = aec_info->audio_engine.on;
+ if (aec_info->audio_engine.fdsp_on != 2)
+ ae->fdsp_on = aec_info->audio_engine.fdsp_on;
+ if (aec_info->audio_engine.bdsp_ae0_src != 2)
+ ae->bdsp_ae0_src = aec_info->audio_engine.bdsp_ae0_src;
+ if (aec_info->audio_engine.bdsp_ae1_src != 2)
+ ae->bdsp_ae1_src = aec_info->audio_engine.bdsp_ae1_src;
+ if (aec_info->audio_engine.mixer_in0_src != 2)
+ ae->mixer_in0_src =
+ aec_info->audio_engine.mixer_in0_src;
+ if (aec_info->audio_engine.mixer_in1_src != 2)
+ ae->mixer_in1_src =
+ aec_info->audio_engine.mixer_in1_src;
+ if (aec_info->audio_engine.mixer_in2_src != 2)
+ ae->mixer_in2_src =
+ aec_info->audio_engine.mixer_in2_src;
+ if (aec_info->audio_engine.mixer_in3_src != 2)
+ ae->mixer_in3_src =
+ aec_info->audio_engine.mixer_in3_src;
+ }
+
+ aec->audio_engine.bdsp = aec_info->audio_engine.bdsp;
+ aec->audio_engine.fdsp = aec_info->audio_engine.fdsp;
+
+ aec->vbox.enable = aec_info->vbox.enable;
+ if (aec_info->vbox.enable) {
+ struct mcdrv_aec_vbox *vb = &mc_info.aec_info.vbox;
+
+ if (aec_info->vbox.cdsp_func_a_on != 2)
+ vb->cdsp_func_a_on = aec_info->vbox.cdsp_func_a_on;
+
+ if (aec_info->vbox.cdsp_func_b_on != 2)
+ vb->cdsp_func_b_on = aec_info->vbox.cdsp_func_b_on;
+
+ if (aec_info->vbox.fdsp_on != 2)
+ vb->fdsp_on = aec_info->vbox.fdsp_on;
+
+ if (aec_info->vbox.fdsp_po_source != 0xff)
+ vb->fdsp_po_source = aec_info->vbox.fdsp_po_source;
+
+ if (aec_info->vbox.isrc2_vsource != 0xff)
+ vb->isrc2_vsource = aec_info->vbox.isrc2_vsource;
+
+ if (aec_info->vbox.isrc2_ch1_vsource != 0xff)
+ vb->isrc2_ch1_vsource =
+ aec_info->vbox.isrc2_ch1_vsource;
+ if (aec_info->vbox.isrc3_vsource != 0xff)
+ vb->isrc3_vsource = aec_info->vbox.isrc3_vsource;
+
+ if (aec_info->vbox.lpt2_vsource != 0xff)
+ vb->lpt2_vsource = aec_info->vbox.lpt2_vsource;
+
+ if (aec_info->vbox.lpt2_mix_vol_o != 0xff)
+ vb->lpt2_mix_vol_o = aec_info->vbox.lpt2_mix_vol_o;
+
+ if (aec_info->vbox.lpt2_mix_vol_i != 0xff)
+ vb->lpt2_mix_vol_i = aec_info->vbox.lpt2_mix_vol_i;
+
+ if (aec_info->vbox.src3_ctrl != 0xff)
+ vb->src3_ctrl = aec_info->vbox.src3_ctrl;
+
+ if (aec_info->vbox.src2_fs != 0xff)
+ vb->src2_fs = aec_info->vbox.src2_fs;
+
+ if (aec_info->vbox.src2_thru != 0xff)
+ vb->src2_thru = aec_info->vbox.src2_thru;
+
+ if (aec_info->vbox.src3_fs != 0xff)
+ vb->src3_fs = aec_info->vbox.src3_fs;
+
+ if (aec_info->vbox.src3_thru != 0xff)
+ vb->src3_thru = aec_info->vbox.src3_thru;
+
+ if (aec_info->vbox.cdsp_jtag_on != 0xff)
+ vb->cdsp_jtag_on = aec_info->vbox.cdsp_jtag_on;
+ }
+
+ aec->vbox.cdsp_a = aec_info->vbox.cdsp_a;
+ aec->vbox.cdsp_b = aec_info->vbox.cdsp_b;
+ aec->vbox.fdsp = aec_info->vbox.fdsp;
+
+ out = &aec->output;
+
+ for (i = 0; i < MCDRV_AEC_OUTPUT_N; i++) {
+
+ if (aec_info->output.lpf_pre_thru[i] != 0xff) {
+ out->lpf_pre_thru[i] = aec_info->output.lpf_pre_thru[i];
+ out->lpf_post_thru[i]
+ = aec_info->output.lpf_post_thru[i];
+ out->dcc_sel[i] = aec_info->output.dcc_sel[i];
+ out->power_detect_level[i]
+ = aec_info->output.power_detect_level[i];
+ out->osf_sel[i] = aec_info->output.osf_sel[i];
+ out->syseq_enb[i] = aec_info->output.syseq_enb[i];
+ out->syseq_coef_a0[i][0]
+ = aec_info->output.syseq_coef_a0[i][0];
+ out->syseq_coef_a0[i][1]
+ = aec_info->output.syseq_coef_a0[i][1];
+ out->syseq_coef_a0[i][2]
+ = aec_info->output.syseq_coef_a0[i][2];
+ out->syseq_coef_a1[i][0]
+ = aec_info->output.syseq_coef_a1[i][0];
+ out->syseq_coef_a1[i][1]
+ = aec_info->output.syseq_coef_a1[i][1];
+ out->syseq_coef_a1[i][2]
+ = aec_info->output.syseq_coef_a1[i][2];
+ out->syseq_coef_a2[i][0]
+ = aec_info->output.syseq_coef_a2[i][0];
+ out->syseq_coef_a2[i][1]
+ = aec_info->output.syseq_coef_a2[i][1];
+ out->syseq_coef_a2[i][2]
+ = aec_info->output.syseq_coef_a2[i][2];
+ out->syseq_coef_b1[i][0]
+ = aec_info->output.syseq_coef_b1[i][0];
+ out->syseq_coef_b1[i][1]
+ = aec_info->output.syseq_coef_b1[i][1];
+ out->syseq_coef_b1[i][2]
+ = aec_info->output.syseq_coef_b1[i][2];
+ out->syseq_coef_b2[i][0]
+ = aec_info->output.syseq_coef_b2[i][0];
+ out->syseq_coef_b2[i][1]
+ = aec_info->output.syseq_coef_b2[i][1];
+ out->syseq_coef_b2[i][2]
+ = aec_info->output.syseq_coef_b2[i][2];
+ out->clip_md[i] = aec_info->output.clip_md[i];
+ out->clip_att[i] = aec_info->output.clip_att[i];
+ out->clip_rel[i] = aec_info->output.clip_rel[i];
+ out->clip_g[i] = aec_info->output.clip_g[i];
+ out->osf_gain[i][0] = aec_info->output.osf_gain[i][0];
+ out->osf_gain[i][1] = aec_info->output.osf_gain[i][1];
+ out->dcl_on[i] = aec_info->output.dcl_on[i];
+ out->dcl_gain[i] = aec_info->output.dcl_gain[i];
+ out->dcl_limit[i][0] = aec_info->output.dcl_limit[i][0];
+ out->dcl_limit[i][1] = aec_info->output.dcl_limit[i][1];
+ out->random_dither_on[i]
+ = aec_info->output.random_dither_on[i];
+ out->random_dither_level[i]
+ = aec_info->output.random_dither_level[i];
+ out->random_dither_pos[i]
+ = aec_info->output.random_dither_pos[i];
+ out->dc_dither_on[i] = aec_info->output.dc_dither_on[i];
+ out->dc_dither_level[i]
+ = aec_info->output.dc_dither_level[i];
+ out->dither_type[i] = aec_info->output.dither_type[i];
+ out->dng_on[i] = aec_info->output.dng_on[i];
+ out->dng_zero[i] = aec_info->output.dng_zero[i];
+ out->dng_time[i] = aec_info->output.dng_time[i];
+ out->dng_fw[i] = aec_info->output.dng_fw[i];
+ out->dng_target[i] = aec_info->output.dng_target[i];
+ out->dng_target_lineout[i]
+ = aec_info->output.dng_target_lineout[i];
+ }
+ if (aec_info->output.syseq_ex[i].enable)
+ memcpy(&out->syseq_ex[i], &aec_info->output.syseq_ex[i],
+ sizeof(struct mcdrv_aec_syseq_ex));
+ }
+
+ out->signal_detect_level = aec_info->output.signal_detect_level;
+ out->dng_attack = aec_info->output.dng_attack;
+ out->dng_release = aec_info->output.dng_release;
+ out->dng_target_rc = aec_info->output.dng_target_rc;
+
+ in = &aec->input;
+
+ for (i = 0; i < MCDRV_AEC_INPUT_N; i++) {
+ if (aec_info->input.dsf32_l_type[i] != 0xff) {
+ in->dsf32_l_type[i] = aec_info->input.dsf32_l_type[i];
+ in->dsf32_r_type[i] = aec_info->input.dsf32_r_type[i];
+ in->dsf4_sel[i] = aec_info->input.dsf4_sel[i];
+ in->dcc_sel[i] = aec_info->input.dcc_sel[i];
+ in->dng_on[i] = aec_info->input.dng_on[i];
+ in->dng_att[i] = aec_info->input.dng_att[i];
+ in->dng_rel[i] = aec_info->input.dng_rel[i];
+ in->dng_fw[i] = aec_info->input.dng_fw[i];
+ in->dng_time[i] = aec_info->input.dng_time[i];
+ in->dng_zero[i][0] = aec_info->input.dng_zero[i][0];
+ in->dng_zero[i][1] = aec_info->input.dng_zero[i][1];
+ in->dng_target[i][0] = aec_info->input.dng_target[i][0];
+ in->dng_target[i][1] = aec_info->input.dng_target[i][1];
+ in->depop_att[i] = aec_info->input.depop_att[i];
+ in->depop_wait[i] = aec_info->input.depop_wait[i];
+ }
+ }
+
+ in->ref_sel = aec_info->input.ref_sel;
+
+ if (aec_info->pdm.mode != 0xff)
+ aec->pdm = aec_info->pdm;
+
+ aec->e2.enable = aec_info->e2.enable;
+ if (aec_info->e2.enable) {
+ if (aec_info->e2.da_sel != 4)
+ aec->e2.da_sel = aec_info->e2.da_sel;
+ if (aec_info->e2.ad_sel != 8)
+ aec->e2.ad_sel = aec_info->e2.ad_sel;
+ aec->e2.on = aec_info->e2.on;
+ }
+ aec->e2.config = aec_info->e2.config;
+
+ if (aec_info->adj.hold != 0xff)
+ aec->adj = aec_info->adj;
+
+ if (aec_info->edsp_misc.i2s_out_enable != 0xff)
+ aec->edsp_misc = aec_info->edsp_misc;
+
+ if (aec_info->control.command == 0xff)
+ memset(&aec->control, 0, sizeof(struct mcdrv_aec_control));
+ else
+ aec->control = aec_info->control;
+
+ if (!aec->fdsp_locate)
+ aec->vbox.fdsp_on = 0;
+ else
+ aec->audio_engine.fdsp_on = 0;
+}
+
+void mc_aec_info_replace(struct mcdrv_aec_info *aec_info)
+{
+ mc_info.aec_info = *aec_info;
+}
+
+void mc_aec_info_get(struct mcdrv_aec_info *aec_info)
+{
+ *aec_info = mc_info.aec_info;
+}
+
+void mc_gp_mode_set(struct mcdrv_gp_mode *mode)
+{
+ mc_info.gp_mode = *mode;
+}
+
+void mc_gp_mode_get(struct mcdrv_gp_mode *mode)
+{
+ *mode = mc_info.gp_mode;
+}
+
+bool mc_gp_pad_get(u32 pad_no)
+{
+ if (pad_no > 2)
+ return 0;
+
+ return mc_info.gp_mode.gp_ddr[pad_no];
+}
+
+void mc_clock_select_set(u8 clk_sel)
+{
+ mc_info.clk_sel = clk_sel;
+}
+
+u8 mc_clock_select_get(void)
+{
+ return mc_info.clk_sel;
+}
+
+void mc_e_clock_select_set(u8 eclk_sel)
+{
+ mc_info.eclk_sel = eclk_sel;
+}
+
+u8 mc_e_clock_select_get(void)
+{
+ return mc_info.eclk_sel;
+}
+
+void mc_plug_detect_db_set(u8 plug_det_db)
+{
+ mc_info.plug_det_db = plug_det_db;
+}
+
+u8 mc_plug_detect_db_get(void)
+{
+ return mc_info.plug_det_db;
+}
+
+static s16 digital_volume(int vol)
+{
+ int ret;
+
+ if (vol < (-95 * 256))
+ ret = 0;
+ else if (vol < 0)
+ ret = 96 + (vol - 128) / 256;
+ else
+ ret = 96 + (vol + 128) / 256;
+
+ if (ret > 114)
+ ret = 114;
+
+ return (s16) ret;
+}
+
+static s16 analog_in_volume(s16 vol)
+{
+ s16 ret;
+
+ if (vol < (-30 * 256))
+ ret = 0;
+ else if (vol < 0)
+ ret = 0x21 + (vol - 128) / 256;
+ else if (vol <= (21 * 256))
+ ret = 0x21 + (vol + 128) / 256;
+ else if (vol < 6080) /* 6080 = 23.75 * 256 */
+ ret = 0x36 + ((vol + 64) / 128 - (21 * 2));
+ else
+ ret = 0x3c + (vol / 256 - 23) / 2;
+
+ if (ret < 0)
+ ret = 0;
+ else if (ret > 0x3f)
+ ret = 0x3f;
+
+ return ret;
+}
+
+static s16 analog_out_volume(s16 vol)
+{
+ s16 ret;
+
+ if (vol < (-36 * 256))
+ ret = 0;
+ else if (vol < -4032) /* -4032:-15.75*256 */
+ ret = 0x42 + (vol - 128) / 256 + 17;
+ else if (vol < -1504) /* -1504:-5.875*256 */
+ ret = 0x57 + ((vol - 64) / 128 + 6 * 2);
+ else
+ ret = 0x6f + ((vol - 32) / 64);
+
+ if (ret < 0)
+ ret = 0;
+ else if (ret > 0x6f)
+ ret = 0x6f;
+
+ return ret;
+}
+
+static inline s16 sp_volume(s16 vol)
+{
+ s16 ret;
+
+ if (vol < (-36 * 256))
+ ret = 0;
+ else if (vol < -4032) /* -4032:-15.75*256 */
+ ret = 0x42 + (vol - 128) / 256 + 17;
+ else if (vol < -1504) /* -1504:-5.875*256 */
+ ret = 0x57 + ((vol - 64) / 128 + 6 * 2);
+ else if (vol < 32)
+ ret = 0x6f + ((vol - 32) / 64);
+ else
+ ret = 0x70 + ((vol - 32) / 64);
+
+ if (ret < 0)
+ ret = 0;
+ else if (ret > 0x7f)
+ ret = 0x7f;
+
+ return ret;
+}
+
+static s16 lineout_volume(s16 vol)
+{
+ s16 ret;
+
+ if (vol < (-38 * 256))
+ ret = 0;
+ else if (vol < -9344) /* -9344:-15.75 * 256 */
+ ret = 0x2e;
+ else if (vol < -4032) /* -4032:-15.75 * 256 */
+ ret = 0x42 + (vol - 128) / 256 + 17;
+ else if (vol < -1504) /* -1504:-5.875 * 256 */
+ ret = 0x57 + ((vol - 64) / 128 + 6 * 2);
+ else if (vol < 32)
+ ret = 0x6f + ((vol - 32) / 64);
+ else
+ ret = 0x70 + ((vol - 32) / 64);
+
+ if (ret < 0)
+ ret = 0;
+ else if (ret > 0x77)
+ ret = 0x77;
+
+ return ret;
+}
+
+static inline s16 hp_volume(s16 vol)
+{
+ s16 ret;
+
+ if (vol < (-36 * 256))
+ ret = 0;
+ else if (vol < -4032) /* -4032:-15.75 * 256 */
+ ret = 0x43 + (vol - 128) / 256 + 16;
+ else if (vol < -1504) /* -1504:-5.875 * 256 */
+ ret = 0x43 + ((vol - 64) / 128 + 16 * 2);
+ else if (vol < 0)
+ ret = 0x57 + ((vol - 32) / 64 + 6 * 4);
+ else
+ ret = 0x6f + ((vol + 32) / 64);
+
+ if (ret < 0)
+ ret = 0;
+ else if (ret > 0x7f)
+ ret = 0x7f;
+
+ return ret;
+}
+
+static u32 d1_get_source(u32 *d1, enum mcdrv_dst_ch ch)
+{
+ u32 src = 0;
+
+ if (d1) {
+ if (d1[ch] & MCDRV_D1SRC_MUSICIN_ON)
+ src |= MCDRV_D1SRC_MUSICIN_ON;
+ if (d1[ch] & MCDRV_D1SRC_EXTIN_ON)
+ src |= MCDRV_D1SRC_EXTIN_ON;
+ if (d1[ch] & MCDRV_D1SRC_VBOXOUT_ON)
+ src |= MCDRV_D1SRC_VBOXOUT_ON;
+ if (d1[ch] & MCDRV_D1SRC_VBOXREFOUT_ON)
+ src |= MCDRV_D1SRC_VBOXREFOUT_ON;
+ if (d1[ch] & MCDRV_D1SRC_AE0_ON)
+ src |= MCDRV_D1SRC_AE0_ON;
+ if (d1[ch] & MCDRV_D1SRC_AE1_ON)
+ src |= MCDRV_D1SRC_AE1_ON;
+ if (d1[ch] & MCDRV_D1SRC_AE2_ON)
+ src |= MCDRV_D1SRC_AE2_ON;
+ if (d1[ch] & MCDRV_D1SRC_AE3_ON)
+ src |= MCDRV_D1SRC_AE3_ON;
+ if (d1[ch] & MCDRV_D1SRC_ADIF0_ON)
+ src |= MCDRV_D1SRC_ADIF0_ON;
+ if (d1[ch] & MCDRV_D1SRC_ADIF1_ON)
+ src |= MCDRV_D1SRC_ADIF1_ON;
+ if (d1[ch] & MCDRV_D1SRC_ADIF2_ON)
+ src |= MCDRV_D1SRC_ADIF2_ON;
+ if (d1[ch] & MCDRV_D1SRC_HIFIIN_ON)
+ src |= MCDRV_D1SRC_HIFIIN_ON;
+ }
+
+ return src;
+}
+
+void mc_volume_info_get(struct mcdrv_vol_info *vol_info)
+{
+ enum mcdrv_dst_ch ch, dst_ch[] = { MCDRV_DST_CH0, MCDRV_DST_CH1 };
+ s16 val1, val2;
+ int i, src;
+
+ *vol_info = mc_info.vol_info;
+
+ if (!mc_d1_source_is_used(MCDRV_D1SRC_MUSICIN_ON)) {
+ val1 = MCDRV_REG_MUTE;
+ val2 = MCDRV_REG_MUTE;
+ } else {
+ val1 = digital_volume(vol_info->d_music_in[0]);
+ val2 = digital_volume(vol_info->d_music_in[1]);
+ }
+ vol_info->d_music_in[0] = val1;
+ vol_info->d_music_in[1] = val2;
+
+ if (!mc_d1_source_is_used(MCDRV_D1SRC_EXTIN_ON)) {
+ val1 = MCDRV_REG_MUTE;
+ val2 = MCDRV_REG_MUTE;
+ } else {
+ val1 = digital_volume(vol_info->d_ext_in[0]);
+ val2 = digital_volume(vol_info->d_ext_in[1]);
+ }
+ vol_info->d_ext_in[0] = val1;
+ vol_info->d_ext_in[1] = val2;
+
+ if (!mc_d1_source_is_used(MCDRV_D1SRC_VBOXOUT_ON)) {
+ val1 = MCDRV_REG_MUTE;
+ val2 = MCDRV_REG_MUTE;
+ } else {
+ val1 = digital_volume(vol_info->d_voice_in[0]);
+ val2 = digital_volume(vol_info->d_voice_in[1]);
+ }
+ vol_info->d_voice_in[0] = val1;
+ vol_info->d_voice_in[1] = val2;
+
+ if (!mc_d1_source_is_used(MCDRV_D1SRC_VBOXREFOUT_ON)) {
+ val1 = MCDRV_REG_MUTE;
+ val2 = MCDRV_REG_MUTE;
+ } else {
+ val1 = digital_volume(vol_info->d_ref_in[0]);
+ val2 = digital_volume(vol_info->d_ref_in[1]);
+ }
+ vol_info->d_ref_in[0] = val1;
+ vol_info->d_ref_in[1] = val2;
+
+ if (!mc_d1_source_is_used(MCDRV_D1SRC_ADIF0_ON)) {
+ val1 = MCDRV_REG_MUTE;
+ val2 = MCDRV_REG_MUTE;
+ } else {
+ val1 = digital_volume(vol_info->d_adif0_in[0]);
+ val2 = digital_volume(vol_info->d_adif0_in[1]);
+ }
+ vol_info->d_adif0_in[0] = val1;
+ vol_info->d_adif0_in[1] = val2;
+
+ if (!mc_d1_source_is_used(MCDRV_D1SRC_ADIF1_ON)) {
+ val1 = MCDRV_REG_MUTE;
+ val2 = MCDRV_REG_MUTE;
+ } else {
+ val1 = digital_volume(vol_info->d_adif1_in[0]);
+ val2 = digital_volume(vol_info->d_adif1_in[1]);
+ }
+ vol_info->d_adif1_in[0] = val1;
+ vol_info->d_adif1_in[1] = val2;
+
+ if (!mc_d1_source_is_used(MCDRV_D1SRC_ADIF2_ON)) {
+ val1 = MCDRV_REG_MUTE;
+ val2 = MCDRV_REG_MUTE;
+ } else {
+ val1 = digital_volume(vol_info->d_adif2_in[0]);
+ val2 = digital_volume(vol_info->d_adif2_in[1]);
+ }
+ vol_info->d_adif2_in[0] = val1;
+ vol_info->d_adif2_in[1] = val2;
+
+ for (i = 0; i < ARRAY_SIZE(dst_ch); i++) {
+ ch = dst_ch[i];
+ if (!mc_source_is_used(MCDRV_DST_MUSICOUT, ch))
+ val1 = MCDRV_REG_MUTE;
+ else
+ val1 = digital_volume(vol_info->d_music_out[i]);
+
+ if (!mc_source_is_used(MCDRV_DST_EXTOUT, ch))
+ val2 = MCDRV_REG_MUTE;
+ else
+ val2 = digital_volume(vol_info->d_ext_out[i]);
+ vol_info->d_music_out[i] = val1;
+ vol_info->d_ext_out[i] = val2;
+ }
+
+ if (!mc_source_is_used(MCDRV_DST_VBOXMIXIN, MCDRV_DST_CH0))
+ val1 = MCDRV_REG_MUTE;
+ else
+ val1 = digital_volume(vol_info->d_voice_out[0]);
+ vol_info->d_voice_out[0] = val1;
+
+ if (!mc_source_is_used(MCDRV_DST_VBOXMIXIN, MCDRV_DST_CH1))
+ val1 = MCDRV_REG_MUTE;
+ else
+ val1 = digital_volume(vol_info->d_voice_out[1]);
+ vol_info->d_voice_out[1] = val1;
+
+ if (!mc_source_is_used(MCDRV_DST_VBOXMIXIN, MCDRV_DST_CH2))
+ val1 = MCDRV_REG_MUTE;
+ else
+ val1 = digital_volume(vol_info->d_ref_out[0]);
+ vol_info->d_ref_out[0] = val1;
+
+ if (!mc_source_is_used(MCDRV_DST_VBOXMIXIN, MCDRV_DST_CH3))
+ val1 = MCDRV_REG_MUTE;
+ else
+ val1 = digital_volume(vol_info->d_ref_out[1]);
+ vol_info->d_ref_out[1] = val1;
+
+ if (!mc_d1_source_is_used(MCDRV_D1SRC_HIFIIN_ON)) {
+ vol_info->d_dpath_da[0] = MCDRV_REG_MUTE;
+ vol_info->d_dpath_da[1] = MCDRV_REG_MUTE;
+ }
+
+ src = d1_get_source(mc_info.path_info.dac0, MCDRV_DST_CH0);
+ if (!(src & ~MCDRV_D1SRC_HIFIIN_ON))
+ val1 = MCDRV_REG_MUTE;
+ else
+ val1 = digital_volume(vol_info->d_dac0_out[0]);
+ vol_info->d_dac0_out[0] = val1;
+
+ if (src & MCDRV_D1SRC_HIFIIN_ON)
+ vol_info->d_dpath_da[0]
+ = digital_volume(vol_info->d_dpath_da[0]);
+
+ src = d1_get_source(mc_info.path_info.dac0, MCDRV_DST_CH1);
+ if (!(src & ~MCDRV_D1SRC_HIFIIN_ON))
+ val1 = MCDRV_REG_MUTE;
+ else
+ val1 = digital_volume(vol_info->d_dac0_out[1]);
+ vol_info->d_dac0_out[1] = val1;
+
+ if (src & MCDRV_D1SRC_HIFIIN_ON)
+ vol_info->d_dpath_da[1]
+ = digital_volume(vol_info->d_dpath_da[1]);
+
+ src = d1_get_source(mc_info.path_info.dac1, MCDRV_DST_CH0);
+ if (!(src & ~MCDRV_D1SRC_HIFIIN_ON))
+ val1 = MCDRV_REG_MUTE;
+ else
+ val1 = digital_volume(vol_info->d_dac1_out[0]);
+ vol_info->d_dac1_out[0] = val1;
+
+ if (src & MCDRV_D1SRC_HIFIIN_ON)
+ vol_info->d_dpath_da[0]
+ = digital_volume(vol_info->d_dpath_da[0]);
+
+ src = d1_get_source(mc_info.path_info.dac1, MCDRV_DST_CH1);
+ if (!(src & ~MCDRV_D1SRC_HIFIIN_ON))
+ val1 = MCDRV_REG_MUTE;
+ else
+ val1 = digital_volume(vol_info->d_dac1_out[1]);
+ vol_info->d_dac1_out[1] = val1;
+
+ if (src & MCDRV_D1SRC_HIFIIN_ON)
+ vol_info->d_dpath_da[1]
+ = digital_volume(vol_info->d_dpath_da[1]);
+
+ src = d1_get_source(mc_info.path_info.hifi_out, MCDRV_DST_CH0);
+ if (!src) {
+ val1 = MCDRV_REG_MUTE;
+ val2 = MCDRV_REG_MUTE;
+ } else {
+ if ((src & MCDRV_D2SRC_PDM0_ON)
+ || (src & MCDRV_D2SRC_PDM1_ON)) {
+ val1 = digital_volume(vol_info->d_dpath_ad[0]);
+ val2 = digital_volume(vol_info->d_dpath_ad[1]);
+ } else {
+ if ((src & MCDRV_D2SRC_ADC1_ON)
+ || mc_source_is_used(MCDRV_DST_ADC0, MCDRV_DST_CH0))
+ val1 = digital_volume(vol_info->d_dpath_ad[0]);
+ else
+ val1 = MCDRV_REG_MUTE;
+
+ if ((src & MCDRV_D2SRC_ADC0_ON)
+ && mc_source_is_used(MCDRV_DST_ADC0, MCDRV_DST_CH1))
+ val2 = digital_volume(vol_info->d_dpath_ad[1]);
+ else
+ val2 = MCDRV_REG_MUTE;
+ }
+ }
+ vol_info->d_dpath_ad[0] = val1;
+ vol_info->d_dpath_ad[1] = val2;
+
+ if (mc_a_source_is_used(MCDRV_ASRC_LINEIN1_L_ON)
+ || mc_a_source_is_used(MCDRV_ASRC_LINEIN1_M_ON))
+ val1 = analog_in_volume(mc_info.vol_info.a_line_in1[0]);
+ else
+ val1 = MCDRV_REG_MUTE;
+ vol_info->a_line_in1[0] = val1;
+
+ if (mc_a_source_is_used(MCDRV_ASRC_LINEIN1_R_ON)
+ || mc_a_source_is_used(MCDRV_ASRC_LINEIN1_M_ON))
+ val1 = analog_in_volume(mc_info.vol_info.a_line_in1[1]);
+ else
+ val1 = MCDRV_REG_MUTE;
+ vol_info->a_line_in1[1] = val1;
+
+ if (mc_a_source_is_used(MCDRV_ASRC_MIC1_ON) != 0)
+ val1 = analog_in_volume(mc_info.vol_info.a_mic1[0]);
+ else
+ val1 = MCDRV_REG_MUTE;
+ vol_info->a_mic1[0] = val1;
+
+ if (mc_a_source_is_used(MCDRV_ASRC_MIC2_ON) != 0)
+ val1 = analog_in_volume(mc_info.vol_info.a_mic2[0]);
+ else
+ val1 = MCDRV_REG_MUTE;
+ vol_info->a_mic2[0] = val1;
+
+ if (mc_a_source_is_used(MCDRV_ASRC_MIC3_ON) != 0)
+ val1 = analog_in_volume(mc_info.vol_info.a_mic3[0]);
+ else
+ val1 = MCDRV_REG_MUTE;
+ vol_info->a_mic3[0] = val1;
+
+ if (mc_a_source_is_used(MCDRV_ASRC_MIC4_ON) != 0)
+ val1 = analog_in_volume(mc_info.vol_info.a_mic4[0]);
+ else
+ val1 = MCDRV_REG_MUTE;
+ vol_info->a_mic4[0] = val1;
+
+ for (i = 0; i < ARRAY_SIZE(dst_ch); i++) {
+ ch = dst_ch[i];
+ if (!mc_source_is_used(MCDRV_DST_HP, ch))
+ val1 = MCDRV_REG_MUTE;
+ else
+ val1 = hp_volume(mc_info.vol_info.a_hp[i]);
+ vol_info->a_hp[i] = val1;
+
+ if (!mc_source_is_used(MCDRV_DST_SP, ch))
+ val1 = MCDRV_REG_MUTE;
+ else
+ val1 = sp_volume(mc_info.vol_info.a_sp[i]);
+ vol_info->a_sp[i] = val1;
+
+ if (!mc_source_is_used(MCDRV_DST_LOUT1, dst_ch[i]))
+ val1 = MCDRV_REG_MUTE;
+ else
+ val1 = lineout_volume(mc_info.vol_info.a_line_out1[i]);
+ vol_info->a_line_out1[i] = val1;
+
+ if (!mc_source_is_used(MCDRV_DST_LOUT2, dst_ch[i]))
+ val1 = MCDRV_REG_MUTE;
+ else
+ val1 = lineout_volume(mc_info.vol_info.a_line_out2[i]);
+ vol_info->a_line_out2[i] = val1;
+ }
+
+ if (!mc_source_is_used(MCDRV_DST_RCV, MCDRV_DST_CH0))
+ val1 = MCDRV_REG_MUTE;
+ else
+ val1 = analog_out_volume(mc_info.vol_info.a_rc[0]);
+ vol_info->a_rc[0] = val1;
+
+ val1 = analog_out_volume(mc_info.vol_info.a_hp_det[0]);
+ vol_info->a_hp_det[0] = val1;
+}
+
+void mc_power_info_get(struct mcdrv_power_info *info)
+{
+ struct mcdrv_aec_info *aec;
+ u32 hifi_out;
+
+ info->digital = MCDRV_POWINFO_D_PLL_PD | MCDRV_POWINFO_D_PE_CLK_PD |
+ MCDRV_POWINFO_D_PB_CLK_PD | MCDRV_POWINFO_D_PM_CLK_PD |
+ MCDRV_POWINFO_D_PF_CLK_PD | MCDRV_POWINFO_D_PC_CLK_PD;
+
+ aec = &mc_info.aec_info;
+ hifi_out = mc_info.path_info.hifi_out[0];
+
+ if (aec->e2.on || (hifi_out & MCDRV_D1SRC_ADIF0_ON)
+ || mc_d2_source_is_used(MCDRV_D2SRC_ADC0_ON)
+ || mc_d2_source_is_used(MCDRV_D2SRC_ADC1_ON)
+ || mc_d2_source_is_used(MCDRV_D2SRC_PDM0_ON)
+ || mc_d2_source_is_used(MCDRV_D2SRC_PDM1_ON)
+ || mc_source_is_used(MCDRV_DST_DAC0, MCDRV_DST_CH0)
+ || mc_source_is_used(MCDRV_DST_DAC0, MCDRV_DST_CH1)
+ || mc_source_is_used(MCDRV_DST_DAC1, MCDRV_DST_CH0)
+ || mc_source_is_used(MCDRV_DST_DAC1, MCDRV_DST_CH1))
+ info->digital &= ~(MCDRV_POWINFO_D_PE_CLK_PD |
+ MCDRV_POWINFO_D_PM_CLK_PD |
+ MCDRV_POWINFO_D_PLL_PD);
+
+ if (aec->audio_engine.on == 1
+ || mc_d1_source_is_used(MCDRV_D1SRC_AE_ALL_ON))
+ info->digital &= ~(MCDRV_POWINFO_D_PB_CLK_PD |
+ MCDRV_POWINFO_D_PE_CLK_PD |
+ MCDRV_POWINFO_D_PM_CLK_PD |
+ MCDRV_POWINFO_D_PLL_PD);
+
+ if (mc_info.dev_info.power_mode == MCDRV_POWMODE_CDSPDEBUG
+ || aec->vbox.cdsp_jtag_on
+ || aec->vbox.cdsp_func_a_on || aec->vbox.cdsp_func_b_on)
+ info->digital &= ~(MCDRV_POWINFO_D_PC_CLK_PD |
+ MCDRV_POWINFO_D_PE_CLK_PD |
+ MCDRV_POWINFO_D_PM_CLK_PD |
+ MCDRV_POWINFO_D_PLL_PD);
+
+ if (!aec->fdsp_locate && aec->audio_engine.fdsp_on)
+ info->digital &= ~(MCDRV_POWINFO_D_PE_CLK_PD |
+ MCDRV_POWINFO_D_PF_CLK_PD |
+ MCDRV_POWINFO_D_PM_CLK_PD |
+ MCDRV_POWINFO_D_PLL_PD);
+
+ if (aec->fdsp_locate && aec->vbox.fdsp_on)
+ info->digital &= ~(MCDRV_POWINFO_D_PE_CLK_PD |
+ MCDRV_POWINFO_D_PF_CLK_PD |
+ MCDRV_POWINFO_D_PM_CLK_PD |
+ MCDRV_POWINFO_D_PLL_PD);
+
+ if (info->digital & MCDRV_POWINFO_D_PM_CLK_PD) {
+ if (mc_d1_source_is_used(MCDRV_D1SRC_MUSICIN_ON)
+ || mc_d1_source_is_used(MCDRV_D1SRC_EXTIN_ON)
+ || mc_d1_source_is_used(MCDRV_D1SRC_VBOXOUT_ON)
+ || mc_d1_source_is_used(MCDRV_D1SRC_VBOXREFOUT_ON)
+ || mc_d2_source_is_used(MCDRV_D2SRC_VOICEIN_ON)
+ || mc_d2_source_is_used(MCDRV_D2SRC_VBOXIOOUT_ON)
+ || mc_source_is_used(MCDRV_DST_MUSICOUT, MCDRV_DST_CH0)
+ || mc_source_is_used(MCDRV_DST_MUSICOUT, MCDRV_DST_CH1)
+ || mc_source_is_used(MCDRV_DST_EXTOUT, MCDRV_DST_CH0)
+ || mc_source_is_used(MCDRV_DST_EXTOUT, MCDRV_DST_CH1)
+ || 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))
+ info->digital &= ~(MCDRV_POWINFO_D_PE_CLK_PD |
+ MCDRV_POWINFO_D_PM_CLK_PD |
+ MCDRV_POWINFO_D_PLL_PD);
+ }
+
+ info->analog[0] = MCI_AP_DEF;
+ info->analog[1] = MCI_AP_DA0_DEF;
+ info->analog[2] = MCI_AP_DA1_DEF;
+ info->analog[3] = MCI_AP_MIC_DEF;
+ info->analog[4] = MCI_AP_AD_DEF;
+
+ if (mc_a_source_is_used(MCDRV_ASRC_DAC0_L_ON))
+ info->analog[1] &= ~MCB_AP_DA0L;
+ if (mc_a_source_is_used(MCDRV_ASRC_DAC0_R_ON))
+ info->analog[1] &= ~MCB_AP_DA0R;
+ if (mc_source_is_used(MCDRV_DST_HP, MCDRV_DST_CH0)) {
+ info->analog[0] &= ~MCB_AP_CP;
+ info->analog[1] &= ~MCB_AP_HPL;
+ }
+ if (mc_source_is_used(MCDRV_DST_HP, MCDRV_DST_CH1)) {
+ info->analog[0] &= ~MCB_AP_CP;
+ info->analog[1] &= ~MCB_AP_HPR;
+ }
+ if (mc_source_is_used(MCDRV_DST_RCV, MCDRV_DST_CH0)) {
+ info->analog[0] &= ~MCB_AP_CP;
+ info->analog[1] &= ~MCB_AP_RC;
+ }
+ if (mc_source_is_used(MCDRV_DST_LOUT1, MCDRV_DST_CH0)) {
+ info->analog[0] &= ~MCB_AP_CP;
+ info->analog[1] &= ~MCB_AP_LO1L;
+ }
+ if (mc_source_is_used(MCDRV_DST_LOUT1, MCDRV_DST_CH1)) {
+ info->analog[0] &= ~MCB_AP_CP;
+ info->analog[1] &= ~MCB_AP_LO1R;
+ }
+ if (mc_a_source_is_used(MCDRV_ASRC_DAC1_L_ON))
+ info->analog[2] &= ~MCB_AP_DA1L;
+ if (mc_a_source_is_used(MCDRV_ASRC_DAC1_R_ON))
+ info->analog[2] &= ~MCB_AP_DA1R;
+ if (mc_source_is_used(MCDRV_DST_SP, MCDRV_DST_CH0)) {
+ info->analog[0] &= ~MCB_AP_CP;
+ info->analog[2] &= ~(MCB_AP_SPL2 | MCB_AP_SPL1);
+ }
+ if (mc_source_is_used(MCDRV_DST_SP, MCDRV_DST_CH1)) {
+ info->analog[0] &= ~MCB_AP_CP;
+ info->analog[2] &= ~(MCB_AP_SPR2 | MCB_AP_SPR1);
+ }
+ if (mc_source_is_used(MCDRV_DST_LOUT2, MCDRV_DST_CH0)) {
+ info->analog[0] &= ~MCB_AP_CP;
+ info->analog[2] &= ~MCB_AP_LO2L;
+ }
+ if (mc_source_is_used(MCDRV_DST_LOUT2, MCDRV_DST_CH1)) {
+ info->analog[0] &= ~MCB_AP_CP;
+ info->analog[2] &= ~MCB_AP_LO2R;
+ }
+ if (mc_a_source_is_used(MCDRV_ASRC_MIC1_ON))
+ info->analog[3] &= ~MCB_MC1;
+ if (mc_a_source_is_used(MCDRV_ASRC_MIC2_ON))
+ info->analog[3] &= ~MCB_MC2;
+ if (mc_a_source_is_used(MCDRV_ASRC_MIC3_ON))
+ info->analog[3] &= ~MCB_MC3;
+ if (mc_a_source_is_used(MCDRV_ASRC_MIC4_ON))
+ info->analog[3] &= ~MCB_MC4;
+ if ((mc_info.path_info.bias[0] & MCDRV_ASRC_MIC1_ON))
+ info->analog[3] &= ~MCB_MB1;
+ if ((mc_info.path_info.bias[1] & MCDRV_ASRC_MIC2_ON))
+ info->analog[3] &= ~MCB_MB2;
+ if ((mc_info.path_info.bias[2] & MCDRV_ASRC_MIC3_ON))
+ info->analog[3] &= ~MCB_MB3;
+ if ((mc_info.path_info.bias[3] & MCDRV_ASRC_MIC4_ON))
+ info->analog[3] &= ~MCB_MB4;
+ if (mc_source_is_used(MCDRV_DST_ADC0, MCDRV_DST_CH0))
+ info->analog[4] &= ~MCB_AP_ADL;
+ if (mc_source_is_used(MCDRV_DST_ADC0, MCDRV_DST_CH1))
+ info->analog[4] &= ~MCB_AP_ADR;
+ if (mc_source_is_used(MCDRV_DST_ADC1, MCDRV_DST_CH0))
+ info->analog[4] &= ~MCB_AP_ADM;
+ if (mc_a_source_is_used(MCDRV_ASRC_LINEIN1_L_ON)
+ || mc_a_source_is_used(MCDRV_ASRC_LINEIN1_M_ON)
+ || mc_a_source_is_used(MCDRV_ASRC_LINEIN1_R_ON))
+ info->analog[4] &= ~MCB_AP_LI;
+ if (info->analog[1] != MCI_AP_DA0_DEF
+ || info->analog[2] != MCI_AP_DA1_DEF
+ || info->analog[3] != MCI_AP_MIC_DEF
+ || info->analog[4] != MCI_AP_AD_DEF)
+ info->analog[0] &= ~(MCB_AP_LDOA | MCB_AP_BGR | MCB_AP_VR);
+}
+
+void mc_power_info_get_current(struct mcdrv_power_info *info)
+{
+ u8 val;
+
+ info->digital = 0;
+
+ val = mc_info.a_registers[MCI_PD];
+ if (val & MCB_PLL_PD)
+ info->digital |= MCDRV_POWINFO_D_PLL_PD;
+ if (val & MCB_PE_CLK_PD)
+ info->digital |= MCDRV_POWINFO_D_PE_CLK_PD;
+ if (val & MCB_PB_CLK_PD)
+ info->digital |= MCDRV_POWINFO_D_PB_CLK_PD;
+ if (val & MCB_PM_CLK_PD)
+ info->digital |= MCDRV_POWINFO_D_PM_CLK_PD;
+ if (val & MCB_PF_CLK_PD)
+ info->digital |= MCDRV_POWINFO_D_PF_CLK_PD;
+ if (val & MCB_PC_CLK_PD)
+ info->digital |= MCDRV_POWINFO_D_PC_CLK_PD;
+
+ info->analog[0] = mc_info.ana_registers[MCI_AP];
+ info->analog[1] = mc_info.ana_registers[MCI_AP_DA0];
+ info->analog[2] = mc_info.ana_registers[MCI_AP_DA1];
+ info->analog[3] = mc_info.ana_registers[MCI_AP_MIC];
+ info->analog[4] = mc_info.ana_registers[MCI_AP_AD];
+}
+
+static u32 d2_get_source(u32 *d2, enum mcdrv_dst_ch ch)
+{
+ u32 src = 0;
+
+ if (d2) {
+ if (d2[ch] & MCDRV_D2SRC_VOICEIN_ON)
+ src |= MCDRV_D2SRC_VOICEIN_ON;
+ if (d2[ch] & MCDRV_D2SRC_VBOXIOOUT_ON)
+ src |= MCDRV_D2SRC_VBOXIOOUT_ON;
+ if (d2[ch] & MCDRV_D2SRC_VBOXHOSTOUT_ON)
+ src |= MCDRV_D2SRC_VBOXHOSTOUT_ON;
+ if (d2[ch] & MCDRV_D2SRC_ADC0_L_ON)
+ src |= MCDRV_D2SRC_ADC0_L_ON;
+ if (d2[ch] & MCDRV_D2SRC_ADC0_R_ON)
+ src |= MCDRV_D2SRC_ADC0_R_ON;
+ if (d2[ch] & MCDRV_D2SRC_ADC1_ON)
+ src |= MCDRV_D2SRC_ADC1_ON;
+ if (d2[ch] & MCDRV_D2SRC_PDM0_L_ON)
+ src |= MCDRV_D2SRC_PDM0_L_ON;
+ if (d2[ch] & MCDRV_D2SRC_PDM0_R_ON)
+ src |= MCDRV_D2SRC_PDM0_R_ON;
+ if (d2[ch] & MCDRV_D2SRC_PDM1_L_ON)
+ src |= MCDRV_D2SRC_PDM1_L_ON;
+ if (d2[ch] & MCDRV_D2SRC_PDM1_R_ON)
+ src |= MCDRV_D2SRC_PDM1_R_ON;
+ if (d2[ch] & MCDRV_D2SRC_DAC0REF_ON)
+ src |= MCDRV_D2SRC_DAC0REF_ON;
+ if (d2[ch] & MCDRV_D2SRC_DAC1REF_ON)
+ src |= MCDRV_D2SRC_DAC1REF_ON;
+ }
+
+ return src;
+}
+
+bool mc_d1_source_is_used(u32 mask)
+{
+ struct mcdrv_path_info *path;
+ int i;
+
+ path = &mc_info.path_info;
+
+ for (i = 0; i < MUSICOUT_PATH_CHANNELS; i++) {
+ if (path->music_out[i] & mask)
+ return true;
+ }
+
+ for (i = 0; i < EXTOUT_PATH_CHANNELS; i++) {
+ if (path->ext_out[i] & mask)
+ return true;
+ }
+
+ for (i = 0; i < VBOXMIXIN_PATH_CHANNELS; i++) {
+ if (path->vbox_mix_in[i] & mask)
+ return true;
+ }
+
+ for (i = 0; i < AE_PATH_CHANNELS; i++) {
+ if (path->ae0[i] & mask)
+ return true;
+ if (path->ae1[i] & mask)
+ return true;
+ if (path->ae2[i] & mask)
+ return true;
+ if (path->ae3[i] & mask)
+ return true;
+ }
+
+ for (i = 0; i < DAC0_PATH_CHANNELS; i++) {
+ if (path->dac0[i] & mask)
+ return true;
+ }
+
+ for (i = 0; i < DAC1_PATH_CHANNELS; i++) {
+ if (path->dac1[i] & mask)
+ return true;
+ }
+
+ return false;
+}
+
+bool mc_d2_source_is_used(u32 mask)
+{
+ struct mcdrv_path_info *path;
+ int i;
+
+ path = &mc_info.path_info;
+
+ for (i = 0; i < VOICEOUT_PATH_CHANNELS; i++) {
+ if (path->voice_out[i] & mask)
+ return true;
+ }
+
+ for (i = 0; i < VBOXIOIN_PATH_CHANNELS; i++) {
+ if (path->vbox_io_in[i] & mask)
+ return true;
+ }
+
+ for (i = 0; i < VBOXHOSTIN_PATH_CHANNELS; i++) {
+ if (path->vbox_host_in[i] & mask)
+ return true;
+ }
+
+ for (i = 0; i < HOSTOUT_PATH_CHANNELS; i++) {
+ if (path->host_out[i] & mask)
+ return true;
+ }
+
+ for (i = 0; i < ADIF0_PATH_CHANNELS; i++) {
+ if (path->adif0[i] & mask)
+ return true;
+ }
+
+ for (i = 0; i < ADIF1_PATH_CHANNELS; i++) {
+ if (path->adif1[i] & mask)
+ return true;
+ }
+
+ for (i = 0; i < ADIF2_PATH_CHANNELS; i++) {
+ if (path->adif2[i] & mask)
+ return true;
+ }
+
+ return false;
+}
+
+bool mc_a_source_is_used(u32 mask)
+{
+ struct mcdrv_path_info *path;
+ int i;
+
+ path = &mc_info.path_info;
+
+ for (i = 0; i < ADC0_PATH_CHANNELS; i++) {
+ if (path->adc0[i] & mask)
+ return true;
+ }
+
+ for (i = 0; i < ADC1_PATH_CHANNELS; i++) {
+ if (path->adc1[i] & mask)
+ return true;
+ }
+
+ for (i = 0; i < SP_PATH_CHANNELS; i++) {
+ if (path->sp[i] & mask)
+ return true;
+ }
+
+ for (i = 0; i < HP_PATH_CHANNELS; i++) {
+ if (path->hp[i] & mask)
+ return true;
+ }
+
+ for (i = 0; i < RC_PATH_CHANNELS; i++) {
+ if (path->rc[i] & mask)
+ return true;
+ }
+
+ for (i = 0; i < LOUT1_PATH_CHANNELS; i++) {
+ if (path->lout1[i] & mask)
+ return true;
+ }
+
+ for (i = 0; i < LOUT2_PATH_CHANNELS; i++) {
+ if (path->lout2[i] & mask)
+ return true;
+ }
+
+ return false;
+}
+
+bool mc_source_is_used(enum mcdrv_dst_type type, enum mcdrv_dst_ch ch)
+{
+ struct mcdrv_path_info *path;
+ u32 src;
+
+ path = &mc_info.path_info;
+
+ switch (type) {
+ case MCDRV_DST_MUSICOUT:
+ if (ch > MCDRV_DST_CH1)
+ break;
+ if (d1_get_source(path->music_out, ch))
+ return true;
+ break;
+ case MCDRV_DST_EXTOUT:
+ if (ch > MCDRV_DST_CH1)
+ break;
+ if (d1_get_source(path->ext_out, ch))
+ return true;
+ break;
+ case MCDRV_DST_HIFIOUT:
+ if (ch > MCDRV_DST_CH0)
+ break;
+ if (d1_get_source(path->hifi_out, ch))
+ return true;
+ break;
+ case MCDRV_DST_VBOXMIXIN:
+ if (d1_get_source(path->vbox_mix_in, ch))
+ return true;
+ break;
+ case MCDRV_DST_AE0:
+ if (ch > MCDRV_DST_CH1)
+ break;
+ if (d1_get_source(path->ae0, ch))
+ return true;
+ break;
+ case MCDRV_DST_AE1:
+ if (ch > MCDRV_DST_CH1)
+ break;
+ if (d1_get_source(path->ae1, ch))
+ return true;
+ break;
+ case MCDRV_DST_AE2:
+ if (ch > MCDRV_DST_CH1)
+ break;
+ if (d1_get_source(path->ae2, ch))
+ return true;
+ break;
+ case MCDRV_DST_AE3:
+ if (ch > MCDRV_DST_CH1)
+ break;
+ if (d1_get_source(path->ae3, ch))
+ return true;
+ break;
+ case MCDRV_DST_DAC0:
+ if (ch > MCDRV_DST_CH1)
+ break;
+ if (d1_get_source(path->dac0, ch))
+ return true;
+ break;
+ case MCDRV_DST_DAC1:
+ if (ch > MCDRV_DST_CH1)
+ break;
+ if (d1_get_source(path->dac1, ch))
+ return true;
+ break;
+ case MCDRV_DST_VOICEOUT:
+ if (ch > MCDRV_DST_CH0)
+ break;
+ if (d2_get_source(path->voice_out, ch))
+ return true;
+ break;
+ case MCDRV_DST_VBOXIOIN:
+ if (ch > MCDRV_DST_CH0)
+ break;
+ if (d2_get_source(path->vbox_io_in, ch))
+ return true;
+ break;
+ case MCDRV_DST_VBOXHOSTIN:
+ if (ch > MCDRV_DST_CH0)
+ break;
+ if (d2_get_source(path->vbox_host_in, ch))
+ return true;
+ break;
+ case MCDRV_DST_HOSTOUT:
+ if (ch > MCDRV_DST_CH0)
+ break;
+ if (d2_get_source(path->host_out, ch))
+ return true;
+ break;
+
+ case MCDRV_DST_ADIF0:
+ if (ch > MCDRV_DST_CH1)
+ break;
+ if (d2_get_source(path->adif0, ch))
+ return true;
+ break;
+ case MCDRV_DST_ADIF1:
+ if (ch > MCDRV_DST_CH1)
+ break;
+ if (d2_get_source(path->adif1, ch))
+ return true;
+ break;
+ case MCDRV_DST_ADIF2:
+ if (ch > MCDRV_DST_CH1)
+ break;
+ if (d2_get_source(path->adif2, ch))
+ return true;
+ break;
+ case MCDRV_DST_ADC0:
+ if (ch > MCDRV_DST_CH1)
+ break;
+ src = path->adc0[ch];
+ if (src & (MCDRV_ASRC_MIC_ALL_ON | MCDRV_ASRC_LINEIN1_ALL_ON))
+ return true;
+ break;
+ case MCDRV_DST_ADC1:
+ if (ch > MCDRV_DST_CH0)
+ break;
+ src = path->adc1[ch];
+ if (src & (MCDRV_ASRC_MIC_ALL_ON | MCDRV_ASRC_LINEIN1_ALL_ON))
+ return true;
+ break;
+ case MCDRV_DST_SP:
+ if (ch > MCDRV_DST_CH1)
+ break;
+ src = path->sp[ch];
+ if (src & (MCDRV_ASRC_DAC1_L_ON | MCDRV_ASRC_DAC1_R_ON))
+ return true;
+ break;
+ case MCDRV_DST_HP:
+ if (ch > MCDRV_DST_CH1)
+ break;
+ src = path->hp[ch];
+ if (src & (MCDRV_ASRC_DAC0_L_ON | MCDRV_ASRC_DAC0_R_ON))
+ return true;
+ break;
+ case MCDRV_DST_RCV:
+ if (ch > MCDRV_DST_CH0)
+ break;
+ src = path->rc[ch];
+ if (src & (MCDRV_ASRC_DAC0_L_ON | MCDRV_ASRC_DAC0_R_ON))
+ return true;
+ break;
+ case MCDRV_DST_LOUT1:
+ if (ch > MCDRV_DST_CH1)
+ break;
+ src = path->lout1[ch];
+ if (src & (MCDRV_ASRC_DAC0_L_ON | MCDRV_ASRC_DAC0_R_ON))
+ return true;
+ break;
+ case MCDRV_DST_LOUT2:
+ if (ch > MCDRV_DST_CH1)
+ break;
+ src = path->lout2[ch];
+ if (src & (MCDRV_ASRC_DAC1_L_ON | MCDRV_ASRC_DAC1_R_ON))
+ return true;
+ break;
+ case MCDRV_DST_BIAS:
+ if (ch > MCDRV_DST_CH3)
+ break;
+ src = path->bias[ch];
+ if (src & MCDRV_ASRC_MIC_ALL_ON)
+ return true;
+ break;
+ default:
+ break;
+ }
+
+ return false;
+}
+
+u32 mc_source_get(enum mcdrv_dst_type type, enum mcdrv_dst_ch ch)
+{
+ struct mcdrv_path_info *path;
+
+ path = &mc_info.path_info;
+
+ switch (type) {
+ case MCDRV_DST_MUSICOUT:
+ if (ch > MCDRV_DST_CH1)
+ break;
+ return d1_get_source(path->music_out, ch);
+ case MCDRV_DST_EXTOUT:
+ if (ch > MCDRV_DST_CH1)
+ break;
+ return d1_get_source(path->ext_out, ch);
+ case MCDRV_DST_HIFIOUT:
+ if (ch > MCDRV_DST_CH0)
+ break;
+ return d1_get_source(path->hifi_out, ch);
+ case MCDRV_DST_VBOXMIXIN:
+ return d1_get_source(path->vbox_mix_in, ch);
+ case MCDRV_DST_AE0:
+ if (ch > MCDRV_DST_CH1)
+ break;
+ return d1_get_source(path->ae0, ch);
+ case MCDRV_DST_AE1:
+ if (ch > MCDRV_DST_CH1)
+ break;
+ return d1_get_source(path->ae1, ch);
+ case MCDRV_DST_AE2:
+ if (ch > MCDRV_DST_CH1)
+ break;
+ return d1_get_source(path->ae2, ch);
+ case MCDRV_DST_AE3:
+ if (ch > MCDRV_DST_CH1)
+ break;
+ return d1_get_source(path->ae3, ch);
+ case MCDRV_DST_DAC0:
+ if (ch > MCDRV_DST_CH1)
+ break;
+ return d1_get_source(path->dac0, ch);
+ case MCDRV_DST_DAC1:
+ if (ch > MCDRV_DST_CH1)
+ break;
+ return d1_get_source(path->dac1, ch);
+ case MCDRV_DST_VOICEOUT:
+ if (ch > MCDRV_DST_CH0)
+ break;
+ return d2_get_source(path->voice_out, ch);
+ case MCDRV_DST_VBOXIOIN:
+ if (ch > MCDRV_DST_CH0)
+ break;
+ return d2_get_source(path->vbox_io_in, ch);
+ case MCDRV_DST_VBOXHOSTIN:
+ if (ch > MCDRV_DST_CH0)
+ break;
+ return d2_get_source(path->vbox_host_in, ch);
+ case MCDRV_DST_HOSTOUT:
+ if (ch > MCDRV_DST_CH0)
+ break;
+ return d2_get_source(path->host_out, ch);
+ case MCDRV_DST_ADIF0:
+ if (ch > MCDRV_DST_CH1)
+ break;
+ return d2_get_source(path->adif0, ch);
+ case MCDRV_DST_ADIF1:
+ if (ch > MCDRV_DST_CH1)
+ break;
+ return d2_get_source(path->adif1, ch);
+ case MCDRV_DST_ADIF2:
+ if (ch > MCDRV_DST_CH1)
+ break;
+ return d2_get_source(path->adif2, ch);
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+u8 mc_dsp_get_running(void)
+{
+ struct mcdrv_aec_info *aec;
+ u32 hifi_out;
+ u8 start = 0;
+
+ aec = &mc_info.aec_info;
+ hifi_out = mc_info.path_info.hifi_out[0];
+
+ if ((hifi_out & MCDRV_D1SRC_ADIF0_ON)
+ || mc_d2_source_is_used(MCDRV_D2SRC_ADC0_ON)
+ || mc_d2_source_is_used(MCDRV_D2SRC_ADC1_ON)
+ || mc_d2_source_is_used(MCDRV_D2SRC_PDM0_ON)
+ || mc_d2_source_is_used(MCDRV_D2SRC_PDM1_ON)
+ || mc_source_is_used(MCDRV_DST_DAC0, MCDRV_DST_CH0)
+ || mc_source_is_used(MCDRV_DST_DAC0, MCDRV_DST_CH1)
+ || mc_source_is_used(MCDRV_DST_DAC1, MCDRV_DST_CH0)
+ || mc_source_is_used(MCDRV_DST_DAC1, MCDRV_DST_CH1))
+ start |= MCDRV_DSP_START_E | MCDRV_DSP_START_M;
+
+ if (mc_d1_source_is_used(MCDRV_D1SRC_AE_ALL_ON)) {
+ start |= MCDRV_DSP_START_B | MCDRV_DSP_START_M;
+ if (!aec->fdsp_locate && aec->audio_engine.fdsp_on == 1)
+ start |= MCDRV_DSP_START_E | MCDRV_DSP_START_F;
+ }
+
+ if (mc_source_is_used(MCDRV_DST_VBOXMIXIN, MCDRV_DST_CH2)
+ || mc_source_is_used(MCDRV_DST_VBOXMIXIN, MCDRV_DST_CH3)
+ || mc_d1_source_is_used(MCDRV_D1SRC_VBOXREFOUT_ON)) {
+ start |= MCDRV_DSP_START_M;
+ if (aec->vbox.cdsp_func_a_on || aec->vbox.cdsp_func_b_on)
+ start |= MCDRV_DSP_START_C;
+ if (aec->fdsp_locate && aec->vbox.fdsp_on == 1)
+ start |= MCDRV_DSP_START_F;
+ } else {
+ if (mc_source_is_used(MCDRV_DST_VBOXMIXIN, MCDRV_DST_CH0)
+ || mc_source_is_used(MCDRV_DST_VBOXMIXIN, MCDRV_DST_CH1)) {
+ start |= MCDRV_DSP_START_M;
+ if (aec->vbox.lpt2_vsource == 1) {
+ if (aec->vbox.cdsp_func_a_on
+ || aec->vbox.cdsp_func_b_on)
+ start |= MCDRV_DSP_START_C;
+ if (aec->fdsp_locate && aec->vbox.fdsp_on == 1)
+ start |= MCDRV_DSP_START_F;
+ }
+ }
+
+ if (mc_d1_source_is_used(MCDRV_D1SRC_VBOXOUT_ON)) {
+ start |= MCDRV_DSP_START_M;
+ if (aec->vbox.isrc2_vsource == 1) {
+ if (aec->vbox.cdsp_func_a_on
+ || aec->vbox.cdsp_func_b_on)
+ start |= MCDRV_DSP_START_C;
+ if (aec->fdsp_locate && aec->vbox.fdsp_on == 1)
+ start |= MCDRV_DSP_START_F;
+ }
+ }
+
+ if (mc_source_is_used(MCDRV_DST_VBOXHOSTIN, MCDRV_DST_CH0)
+ || mc_source_is_used(MCDRV_DST_HOSTOUT, MCDRV_DST_CH0)) {
+ if (aec->vbox.cdsp_func_a_on
+ || aec->vbox.cdsp_func_b_on)
+ start |= MCDRV_DSP_START_C;
+ if (aec->fdsp_locate && aec->vbox.fdsp_on == 1)
+ start |= MCDRV_DSP_START_F;
+ }
+
+ if (mc_source_is_used(MCDRV_DST_VOICEOUT, MCDRV_DST_CH0)
+ && aec->vbox.lpt2_vsource == 1) {
+ if (aec->vbox.cdsp_func_a_on
+ || aec->vbox.cdsp_func_b_on)
+ start |= MCDRV_DSP_START_C;
+ if (aec->fdsp_locate && aec->vbox.fdsp_on == 1)
+ start |= MCDRV_DSP_START_F;
+ }
+ }
+
+ if (mc_d1_source_is_used(MCDRV_D1SRC_MUSICIN_ON)
+ || mc_d1_source_is_used(MCDRV_D1SRC_EXTIN_ON)
+ || mc_source_is_used(MCDRV_DST_MUSICOUT, MCDRV_DST_CH0)
+ || mc_source_is_used(MCDRV_DST_MUSICOUT, MCDRV_DST_CH1)
+ || mc_source_is_used(MCDRV_DST_EXTOUT, MCDRV_DST_CH0)
+ || mc_source_is_used(MCDRV_DST_EXTOUT, MCDRV_DST_CH1))
+ start |= MCDRV_DSP_START_M;
+
+ return start;
+}
+
+void mc_resource_clear(void)
+{
+ mc_info.packet.data_size = 0;
+ mc_info.slave_addr = 0xffff;
+ mc_info.type = 0xffff;
+ mc_info.addr = 0xffff;
+ mc_info.data_count = 0;
+ mc_info.prev_addr_index = 0;
+}
+
+void mc_bus_queue_add(u16 type, u16 addr, u8 data, enum mcdrv_update_mode mode)
+{
+ const u16 *next_list;
+ u16 size, next_addr, after_next_addr;
+ u16 index, prev_type, prev_addr, prev_slave_addr, slave_addr;
+ u8 *regs, *packet;
+ u8 packet_addr, packet_window, addr_inc_reg;
+ bool addr_inc;
+
+ prev_type = mc_info.type;
+ prev_slave_addr = mc_info.slave_addr;
+
+ slave_addr = MCDRV_SLAVE_ADDR_DIGITAL;
+
+ switch (type) {
+ case MCDRV_PACKET_REGTYPE_IF:
+ regs = mc_info.if_registers;
+ next_list = mc_next_addr_list;
+ addr_inc = false;
+ addr_inc_reg = 0;
+ packet_addr = addr;
+ packet_window = packet_addr;
+ break;
+ case MCDRV_PACKET_REGTYPE_A:
+ regs = mc_info.a_registers;
+ next_list = mc_next_addr_list_inc;
+ addr_inc = true;
+ addr_inc_reg = MCB_A_REG_AINC;
+ packet_addr = MCI_A_REG_A;
+ packet_window = MCI_A_REG_D;
+ break;
+ case MCDRV_PACKET_REGTYPE_MA:
+ regs = mc_info.ma_registers;
+ next_list = mc_next_addr_list_inc;
+ addr_inc = true;
+ addr_inc_reg = MCB_MA_REG_AINC;
+ packet_addr = MCI_MA_REG_A;
+ packet_window = MCI_MA_REG_D;
+ break;
+ case MCDRV_PACKET_REGTYPE_MB:
+ regs = mc_info.mb_registers;
+ next_list = mc_next_addr_list_inc;
+ addr_inc = true;
+ addr_inc_reg = MCB_MB_REG_AINC;
+ packet_addr = MCI_MB_REG_A;
+ packet_window = MCI_MB_REG_D;
+ break;
+ case MCDRV_PACKET_REGTYPE_B:
+ regs = mc_info.b_registers;
+ next_list = mc_next_addr_list_inc;
+ addr_inc = true;
+ addr_inc_reg = MCB_B_REG_AINC;
+ packet_addr = MCI_B_REG_A;
+ packet_window = MCI_B_REG_D;
+ break;
+ case MCDRV_PACKET_REGTYPE_E:
+ regs = mc_info.e_registers;
+ next_list = mc_next_addr_list_inc;
+ addr_inc = true;
+ addr_inc_reg = MCB_E_REG_AINC;
+ packet_addr = MCI_E_REG_A;
+ packet_window = MCI_E_REG_D;
+ break;
+ case MCDRV_PACKET_REGTYPE_C:
+ regs = mc_info.c_registers;
+ next_list = mc_next_addr_list_inc;
+ addr_inc = true;
+ addr_inc_reg = 0;
+ packet_addr = MCI_C_REG_A;
+ packet_window = MCI_C_REG_D;
+ break;
+ case MCDRV_PACKET_REGTYPE_F:
+ regs = mc_info.f_registers;
+ next_list = mc_next_addr_list_inc;
+ addr_inc = true;
+ addr_inc_reg = MCB_F_REG_AINC;
+ packet_addr = MCI_F_REG_A;
+ packet_window = MCI_F_REG_D;
+ break;
+ case MCDRV_PACKET_REGTYPE_ANA:
+ slave_addr = MCDRV_SLAVE_ADDR_ANALOG;
+ regs = mc_info.ana_registers;
+ next_list = mc_next_addr_list_inc;
+ addr_inc = true;
+ addr_inc_reg = MCB_ANA_REG_AINC;
+ packet_addr = MCI_ANA_REG_A;
+ packet_window = MCI_ANA_REG_D;
+ break;
+ case MCDRV_PACKET_REGTYPE_CD:
+ slave_addr = MCDRV_SLAVE_ADDR_ANALOG;
+ regs = mc_info.cd_registers;
+ next_list = mc_next_addr_list_inc;
+ addr_inc = true;
+ addr_inc_reg = MCB_CD_REG_AINC;
+ packet_addr = MCI_CD_REG_A;
+ packet_window = MCI_CD_REG_D;
+ break;
+ default:
+ return;
+ }
+
+ if ((prev_type != 0xffff && prev_type != type)
+ || (prev_slave_addr != 0xffff && prev_slave_addr != slave_addr)) {
+ mc_bus_queue_flush();
+ mc_resource_clear();
+ }
+
+ if (mode != MCDRV_UPDATE_FORCE && data == regs[addr])
+ return;
+
+ if (mc_info.addr == 0xffff)
+ mc_info.addr = addr;
+
+ prev_addr = mc_info.addr;
+
+ if (mode != MCDRV_UPDATE_DUMMY) {
+ packet = mc_info.packet.data;
+ size = mc_info.packet.data_size;
+ index = mc_info.prev_addr_index;
+ next_addr = next_list[prev_addr];
+
+ if (size > MCDRV_MAX_CTRL_DATA_NUM - 8)
+ pr_warn("ymu831: remaining packet buffer too small\n");
+
+ if (slave_addr == prev_slave_addr && type == prev_type
+ && next_addr != 0xffff && addr != next_addr && addr_inc) {
+ after_next_addr = next_list[next_addr];
+ if (after_next_addr == addr) {
+ if (!mc_info.data_count)
+ packet[index] |= BURST_WRITE_ENABLE;
+
+ packet[size++] = regs[next_addr];
+ mc_info.data_count++;
+ next_addr = after_next_addr;
+ } else if (after_next_addr != 0xffff
+ && next_list[after_next_addr] == addr) {
+ if (!mc_info.data_count)
+ packet[index] |= BURST_WRITE_ENABLE;
+
+ packet[size++] = regs[next_addr];
+ packet[size++] = regs[after_next_addr];
+ mc_info.data_count += 2;
+ next_addr = next_list[after_next_addr];
+ }
+ }
+
+ if (!size || addr != next_addr) {
+ if (mc_info.data_count) {
+ mc_bus_queue_flush();
+ mc_resource_clear();
+ size = mc_info.packet.data_size;
+ }
+
+ if (MCDRV_PACKET_REGTYPE_IF == type) {
+ packet[size] = packet_addr << 1;
+ index = size++;
+ } else {
+ packet[size++] = packet_addr << 1;
+ packet[size++] = addr | addr_inc_reg;
+ packet[size] = packet_window << 1;
+ index = size++;
+ }
+
+ mc_info.prev_addr_index = index;
+ } else {
+ if (!mc_info.data_count)
+ packet[index] |= BURST_WRITE_ENABLE;
+
+ mc_info.data_count++;
+ }
+
+ packet[size++] = data;
+
+ mc_info.slave_addr = slave_addr;
+ mc_info.type = type;
+ mc_info.addr = addr;
+ mc_info.packet.data_size = size;
+ }
+
+ /* save register value */
+ regs[addr] = data;
+}
+
+void mc_bus_queue_flush(void)
+{
+ if (mc_info.packet.data_size) {
+ mc_write(mc_info.slave_addr,
+ mc_info.packet.data,
+ mc_info.packet.data_size);
+ }
+}
+
+static int wait_set_bit(u8 slave_addr, u16 addr, u8 mask,
+ u32 interval, u32 timeout)
+{
+ u8 val;
+
+ while (timeout > 0) {
+ mc_read(slave_addr, addr, &val, 1);
+ if ((val & mask) == mask)
+ return 0;
+
+ msleep(interval);
+ timeout--;
+ }
+
+ return -EAGAIN;
+}
+
+static int wait_release_bit(u8 slave_addr, u16 addr, u8 mask,
+ u32 interval, u32 timeout)
+{
+ u8 val;
+
+ while (timeout > 0) {
+ mc_read(slave_addr, addr, &val, 1);
+ if (!(val & mask))
+ return 0;
+
+ msleep(interval);
+ timeout--;
+ }
+
+ return -EAGAIN;
+}
+
+static int wait_set_dspbit(u8 slave_addr, u8 addr_a, u8 addr_d, u8 addr,
+ u8 mask, u32 interval, u32 timeout)
+{
+ u8 val, data[2];
+
+ data[0] = addr_a << 1;
+ data[1] = addr;
+
+ while (timeout > 0) {
+ mc_write(slave_addr, data, 2);
+ mc_read(slave_addr, addr_d, &val, 1);
+ if ((val & mask) == mask)
+ return 0;
+
+ msleep(interval);
+ timeout--;
+ }
+
+ return -EAGAIN;
+}
+
+static int wait_release_dspbit(u8 slave_addr, u8 addr_a, u8 addr_d, u8 addr,
+ u8 mask, u32 interval, u32 timeout)
+{
+ u8 val, data[2];
+
+ data[0] = addr_a << 1;
+ data[1] = addr;
+
+ while (timeout > 0) {
+ mc_write(slave_addr, data, 2);
+ mc_read(slave_addr, addr_d, &val, 1);
+ if (!(val & mask))
+ return 0;
+
+ msleep(interval);
+ timeout--;
+ }
+
+ return -EAGAIN;
+}
+
+int mc_wait_event(u32 event, u32 param)
+{
+ u32 interval, timeout;
+ u8 data[2];
+ int ret = 0;
+
+ switch (event) {
+ case MCDRV_EVT_SVOL_DONE:
+ interval = mc_info.dev_info.wait_time.poll_interval[0];
+ timeout = mc_info.dev_info.wait_time.poll_timeout[0];
+
+ if (param >> 8) {
+ data[0] = MCI_ANA_REG_A << 1;
+ data[1] = MCI_BUSY1;
+ mc_write_analog(data, 2);
+ ret = wait_release_bit(MCDRV_SLAVE_ADDR_ANALOG,
+ MCI_ANA_REG_D, param >> 8,
+ interval, timeout);
+ if (ret < 0)
+ break;
+ }
+
+ if (param & 0xffU) {
+ data[0] = MCI_ANA_REG_A << 1;
+ data[1] = MCI_BUSY2;
+ mc_write_analog(data, 2);
+ ret = wait_release_bit(MCDRV_SLAVE_ADDR_ANALOG,
+ MCI_ANA_REG_D, param & 0xff,
+ interval, timeout);
+ }
+ break;
+ case MCDRV_EVT_ALLMUTE:
+ interval = mc_info.dev_info.wait_time.poll_interval[1];
+ timeout = mc_info.dev_info.wait_time.poll_timeout[1];
+
+ data[0] = MCI_MA_REG_A << 1;
+ data[1] = MCI_DIFI_VFLAG;
+ mc_write_digital(data, 2);
+ ret = wait_release_bit(MCDRV_SLAVE_ADDR_DIGITAL,
+ MCI_MA_REG_D,
+ (MCB_DIFI3_VFLAG1 | MCB_DIFI3_VFLAG0 |
+ MCB_DIFI2_VFLAG1 | MCB_DIFI2_VFLAG0 |
+ MCB_DIFI1_VFLAG1 | MCB_DIFI1_VFLAG0 |
+ MCB_DIFI1_VFLAG0 | MCB_DIFI0_VFLAG0),
+ interval, timeout);
+ if (ret < 0)
+ break;
+
+ data[1] = MCI_ADI_VFLAG;
+ mc_write_digital(data, 2);
+ ret = wait_release_bit(MCDRV_SLAVE_ADDR_DIGITAL,
+ MCI_MA_REG_D,
+ (MCB_ADI2_VFLAG1 | MCB_ADI2_VFLAG0 |
+ MCB_ADI1_VFLAG1 | MCB_ADI1_VFLAG0 |
+ MCB_ADI0_VFLAG1 | MCB_ADI0_VFLAG0),
+ interval, timeout);
+ if (ret < 0)
+ break;
+
+ data[1] = MCI_DIFO_VFLAG;
+ mc_write_digital(data, 2);
+ ret = wait_release_bit(MCDRV_SLAVE_ADDR_DIGITAL,
+ MCI_MA_REG_D,
+ (MCB_DIFO3_VFLAG1 | MCB_DIFO3_VFLAG0 |
+ MCB_DIFO2_VFLAG1 | MCB_DIFO2_VFLAG0 |
+ MCB_DIFO1_VFLAG1 | MCB_DIFO1_VFLAG0 |
+ MCB_DIFO1_VFLAG0 | MCB_DIFO0_VFLAG0),
+ interval, timeout);
+ if (ret < 0)
+ break;
+
+ data[1] = MCI_DAO_VFLAG;
+ mc_write_digital(data, 2);
+ ret = wait_release_bit(MCDRV_SLAVE_ADDR_DIGITAL,
+ MCI_MA_REG_D,
+ (MCB_DAO1_VFLAG1 | MCB_DAO1_VFLAG0 |
+ MCB_DAO0_VFLAG1 | MCB_DAO0_VFLAG0),
+ interval, timeout);
+ break;
+ case MCDRV_EVT_DIRMUTE:
+ interval = mc_info.dev_info.wait_time.poll_interval[1];
+ timeout = mc_info.dev_info.wait_time.poll_timeout[1];
+
+ data[0] = MCI_MA_REG_A << 1;
+ data[1] = MCI_DIFI_VFLAG;
+ mc_write_digital(data, 2);
+ ret = wait_release_bit(MCDRV_SLAVE_ADDR_DIGITAL,
+ MCI_MA_REG_D, param, interval, timeout);
+ break;
+ case MCDRV_EVT_ADCMUTE:
+ interval = mc_info.dev_info.wait_time.poll_interval[1];
+ timeout = mc_info.dev_info.wait_time.poll_timeout[1];
+
+ data[0] = MCI_MA_REG_A << 1;
+ data[1] = MCI_ADI_VFLAG;
+ mc_write_digital(data, 2);
+ ret = wait_release_bit(MCDRV_SLAVE_ADDR_DIGITAL,
+ MCI_MA_REG_D, param, interval, timeout);
+ break;
+ case MCDRV_EVT_DITMUTE:
+ interval = mc_info.dev_info.wait_time.poll_interval[1];
+ timeout = mc_info.dev_info.wait_time.poll_timeout[1];
+
+ data[0] = MCI_MA_REG_A << 1;
+ data[1] = MCI_DIFO_VFLAG;
+ mc_write_digital(data, 2);
+ ret = wait_release_bit(MCDRV_SLAVE_ADDR_DIGITAL,
+ MCI_MA_REG_D, param, interval, timeout);
+ break;
+ case MCDRV_EVT_DACMUTE:
+ interval = mc_info.dev_info.wait_time.poll_interval[1];
+ timeout = mc_info.dev_info.wait_time.poll_timeout[1];
+
+ data[0] = MCI_MA_REG_A << 1;
+ data[1] = MCI_DAO_VFLAG;
+ mc_write_digital(data, 2);
+ ret = wait_release_bit(MCDRV_SLAVE_ADDR_DIGITAL,
+ MCI_MA_REG_D, param, interval, timeout);
+ break;
+ case MCDRV_EVT_CLKBUSY_RESET:
+ interval = mc_info.dev_info.wait_time.poll_interval[2];
+ timeout = mc_info.dev_info.wait_time.poll_timeout[2];
+
+ data[0] = MCI_A_REG_A << 1;
+ data[1] = MCI_CLKSRC;
+ mc_write_digital(data, 2);
+ ret = wait_release_bit(MCDRV_SLAVE_ADDR_DIGITAL,
+ MCI_A_REG_D, MCB_CLKBUSY, interval,
+ timeout);
+ break;
+ case MCDRV_EVT_PSW_RESET:
+ interval = mc_info.dev_info.wait_time.poll_interval[4];
+ timeout = mc_info.dev_info.wait_time.poll_timeout[4];
+
+ ret = wait_release_bit(MCDRV_SLAVE_ADDR_DIGITAL,
+ param >> 8, param & 0xff,
+ interval, timeout);
+ break;
+ case MCDRV_EVT_OFFCAN_BSY_RESET:
+ interval = mc_info.dev_info.wait_time.poll_interval[3];
+ timeout = mc_info.dev_info.wait_time.poll_timeout[3];
+
+ data[0] = MCI_CD_REG_A << 1;
+ data[1] = MCI_SSENSEFIN;
+ mc_write_analog(data, 2);
+ ret = wait_release_bit(MCDRV_SLAVE_ADDR_ANALOG, MCI_CD_REG_D,
+ MCB_OFFCAN_BSY, interval, timeout);
+ break;
+ case MCDRV_EVT_ANA_RDY:
+ interval = mc_info.dev_info.wait_time.poll_interval[5];
+ timeout = mc_info.dev_info.wait_time.poll_timeout[5];
+
+ data[0] = MCI_ANA_REG_A << 1;
+ data[1] = param >> 8;
+ mc_write_analog(data, 2);
+ ret = wait_set_bit(MCDRV_SLAVE_ADDR_ANALOG, MCI_ANA_REG_D,
+ param & 0xff, interval, timeout);
+ break;
+ case MCDRV_EVT_AP_CP_A_SET:
+ interval = mc_info.dev_info.wait_time.poll_interval[5];
+ timeout = mc_info.dev_info.wait_time.poll_timeout[5];
+
+ data[0] = MCI_ANA_REG_A << 1;
+ data[1] = param >> 8;
+ mc_write_analog(data, 2);
+ ret = wait_set_bit(MCDRV_SLAVE_ADDR_ANALOG, MCI_ANA_REG_D,
+ param & 0xff, interval, timeout);
+ break;
+ case MCDRV_EVT_IF_REG_FLAG_SET:
+ interval = mc_info.dev_info.wait_time.poll_interval[3];
+ timeout = mc_info.dev_info.wait_time.poll_timeout[3];
+
+ ret = wait_set_bit(MCDRV_SLAVE_ADDR_DIGITAL, param >> 8,
+ param & 0xff, interval, timeout);
+ break;
+ case MCDRV_EVT_IF_REG_FLAG_RESET:
+ interval = mc_info.dev_info.wait_time.poll_interval[3];
+ timeout = mc_info.dev_info.wait_time.poll_timeout[3];
+
+ ret = wait_release_bit(MCDRV_SLAVE_ADDR_DIGITAL, param >> 8,
+ param & 0xff, interval, timeout);
+ break;
+ case MCDRV_EVT_B_REG_FLAG_SET:
+ interval = mc_info.dev_info.wait_time.poll_interval[3];
+ timeout = mc_info.dev_info.wait_time.poll_timeout[3];
+
+ ret = wait_set_dspbit(MCDRV_SLAVE_ADDR_DIGITAL, MCI_B_REG_A,
+ MCI_B_REG_D, param >> 8, param & 0xff,
+ interval, timeout);
+ break;
+ case MCDRV_EVT_B_REG_FLAG_RESET:
+ interval = mc_info.dev_info.wait_time.poll_interval[3];
+ timeout = mc_info.dev_info.wait_time.poll_timeout[3];
+
+ ret = wait_release_dspbit(MCDRV_SLAVE_ADDR_DIGITAL, MCI_B_REG_A,
+ MCI_B_REG_D, param >> 8, param & 0xff,
+ interval, timeout);
+ break;
+ case MCDRV_EVT_E_REG_FLAG_SET:
+ interval = mc_info.dev_info.wait_time.poll_interval[3];
+ timeout = mc_info.dev_info.wait_time.poll_timeout[3];
+
+ ret = wait_set_dspbit(MCDRV_SLAVE_ADDR_DIGITAL, MCI_E_REG_A,
+ MCI_E_REG_D, param >> 8, param & 0xff,
+ interval, timeout);
+ break;
+ case MCDRV_EVT_E_REG_FLAG_RESET:
+ interval = mc_info.dev_info.wait_time.poll_interval[3];
+ timeout = mc_info.dev_info.wait_time.poll_timeout[3];
+
+ ret = wait_release_dspbit(MCDRV_SLAVE_ADDR_DIGITAL, MCI_E_REG_A,
+ MCI_E_REG_D, param >> 8, param & 0xff,
+ interval, timeout);
+ break;
+ case MCDRV_EVT_C_REG_FLAG_SET:
+ interval = mc_info.dev_info.wait_time.poll_interval[3];
+ timeout = mc_info.dev_info.wait_time.poll_timeout[3];
+
+ ret = wait_set_dspbit(MCDRV_SLAVE_ADDR_DIGITAL, MCI_C_REG_A,
+ MCI_C_REG_D, param >> 8, param & 0xff,
+ interval, timeout);
+ break;
+ case MCDRV_EVT_C_REG_FLAG_RESET:
+ interval = mc_info.dev_info.wait_time.poll_interval[3];
+ timeout = mc_info.dev_info.wait_time.poll_timeout[3];
+ ret = wait_release_dspbit(MCDRV_SLAVE_ADDR_DIGITAL, MCI_C_REG_A,
+ MCI_C_REG_D, param >> 8, param & 0xff,
+ interval, timeout);
+ break;
+ case MCDRV_EVT_F_REG_FLAG_SET:
+ interval = mc_info.dev_info.wait_time.poll_interval[3];
+ timeout = mc_info.dev_info.wait_time.poll_timeout[3];
+ ret = wait_set_dspbit(MCDRV_SLAVE_ADDR_DIGITAL, MCI_F_REG_A,
+ MCI_F_REG_D, param >> 8, param & 0xff,
+ interval, timeout);
+ break;
+ case MCDRV_EVT_F_REG_FLAG_RESET:
+ interval = mc_info.dev_info.wait_time.poll_interval[3];
+ timeout = mc_info.dev_info.wait_time.poll_timeout[3];
+
+ ret = wait_release_dspbit(MCDRV_SLAVE_ADDR_DIGITAL, MCI_F_REG_A,
+ MCI_F_REG_D, param >> 8, param & 0xff,
+ interval, timeout);
+ break;
+ default:
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
diff --git a/sound/soc/codecs/ymu831/mcresctrl.h b/sound/soc/codecs/ymu831/mcresctrl.h
new file mode 100644
index 0000000..4494779
--- /dev/null
+++ b/sound/soc/codecs/ymu831/mcresctrl.h
@@ -0,0 +1,394 @@
+/****************************************************************************
+ *
+ * Copyright(c) 2012 Yamaha Corporation. All rights reserved.
+ *
+ * Module : mcresctrl.h
+ * Description : MC resource control 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 _MCRESCTRL_H
+#define _MCRESCTRL_H
+
+#include "mcdriver.h"
+#include "mcpacking.h"
+
+#define MCDRV_DEVID_ANA 0x90
+#define MCDRV_DEVID_DIG 0x80
+#define MCDRV_DEVID_MASK 0xf8
+#define MCDRV_VERID_MASK 0x07
+
+enum mcdrv_state {
+ MCDRV_STATE_NOTINIT,
+ MCDRV_STATE_READY,
+};
+
+/* volume setting */
+#define MCDRV_LOGICAL_VOL_MUTE -24576 /* -96dB */
+
+#define MCDRV_REG_MUTE 0x00
+
+/* Path destination channel */
+enum mcdrv_dst_ch {
+ MCDRV_DST_CH0 = 0,
+ MCDRV_DST_CH1,
+ MCDRV_DST_CH2,
+ MCDRV_DST_CH3
+};
+
+/* Path destination type */
+enum mcdrv_dst_type {
+ MCDRV_DST_MUSICOUT = 0,
+ MCDRV_DST_EXTOUT,
+ MCDRV_DST_HIFIOUT,
+ MCDRV_DST_VBOXMIXIN,
+ MCDRV_DST_AE0,
+ MCDRV_DST_AE1,
+ MCDRV_DST_AE2,
+ MCDRV_DST_AE3,
+ MCDRV_DST_DAC0,
+ MCDRV_DST_DAC1,
+ MCDRV_DST_VOICEOUT,
+ MCDRV_DST_VBOXIOIN,
+ MCDRV_DST_VBOXHOSTIN,
+ MCDRV_DST_HOSTOUT,
+ MCDRV_DST_ADIF0,
+ MCDRV_DST_ADIF1,
+ MCDRV_DST_ADIF2,
+ MCDRV_DST_ADC0,
+ MCDRV_DST_ADC1,
+ MCDRV_DST_SP,
+ MCDRV_DST_HP,
+ MCDRV_DST_RCV,
+ MCDRV_DST_LOUT1,
+ MCDRV_DST_LOUT2,
+ MCDRV_DST_BIAS
+};
+
+/* Register update parameter */
+enum mcdrv_update_mode {
+ MCDRV_UPDATE_NORMAL,
+ MCDRV_UPDATE_FORCE,
+ MCDRV_UPDATE_DUMMY
+};
+
+/* DSP Start */
+#define MCDRV_DSP_START_E 0x01
+#define MCDRV_DSP_START_B 0x02
+#define MCDRV_DSP_START_M 0x04
+#define MCDRV_DSP_START_F 0x08
+#define MCDRV_DSP_START_C 0x10
+
+struct mcdrv_aec_bdsp {
+ u8 *data;
+ u32 data_size;
+};
+
+struct mcdrv_aec_fdsp {
+ u8 *data;
+ u32 data_size;
+};
+
+struct mcdrv_aec_cdsp {
+ u8 *data;
+ u32 data_size;
+};
+
+struct mcdrv_aec_syseq_ex {
+ bool enable;
+ struct {
+ u8 coef_a0[3];
+ u8 coef_a1[3];
+ u8 coef_a2[3];
+ u8 coef_b1[3];
+ u8 coef_b2[3];
+ } band[2];
+};
+
+struct mcdrv_aec_e2_config {
+ u8 *data;
+ u32 data_size;
+};
+
+struct mcdrv_aec_audio_engine {
+ bool enable;
+ u8 on;
+ bool fdsp_on;
+ u8 bdsp_ae0_src;
+ u8 bdsp_ae1_src;
+ u8 mixer_in0_src;
+ u8 mixer_in1_src;
+ u8 mixer_in2_src;
+ u8 mixer_in3_src;
+ struct mcdrv_aec_bdsp bdsp;
+ struct mcdrv_aec_fdsp fdsp;
+};
+
+struct mcdrv_aec_vbox {
+ bool enable;
+ u8 cdsp_func_a_on;
+ u8 cdsp_func_b_on;
+ u8 cdsp_jtag_on;
+ bool fdsp_on;
+ u8 fdsp_po_source;
+ u8 isrc2_vsource;
+ u8 isrc2_ch1_vsource;
+ u8 isrc3_vsource;
+ u8 lpt2_vsource;
+ u8 lpt2_mix_vol_o;
+ u8 lpt2_mix_vol_i;
+ u8 src3_ctrl;
+ u8 src2_fs;
+ u8 src2_thru;
+ u8 src3_fs;
+ u8 src3_thru;
+ struct mcdrv_aec_cdsp cdsp_a;
+ struct mcdrv_aec_cdsp cdsp_b;
+ struct mcdrv_aec_fdsp fdsp;
+};
+
+#define MCDRV_AEC_OUTPUT_N 2
+
+struct mcdrv_aec_output {
+ u8 lpf_pre_thru[MCDRV_AEC_OUTPUT_N];
+ u8 lpf_post_thru[MCDRV_AEC_OUTPUT_N];
+ u8 dcc_sel[MCDRV_AEC_OUTPUT_N];
+ u8 signal_detect_level;
+ u8 power_detect_level[MCDRV_AEC_OUTPUT_N];
+ u8 osf_sel[MCDRV_AEC_OUTPUT_N];
+ u8 syseq_enb[MCDRV_AEC_OUTPUT_N];
+ u8 syseq_coef_a0[MCDRV_AEC_OUTPUT_N][3];
+ u8 syseq_coef_a1[MCDRV_AEC_OUTPUT_N][3];
+ u8 syseq_coef_a2[MCDRV_AEC_OUTPUT_N][3];
+ u8 syseq_coef_b1[MCDRV_AEC_OUTPUT_N][3];
+ u8 syseq_coef_b2[MCDRV_AEC_OUTPUT_N][3];
+ u8 clip_md[MCDRV_AEC_OUTPUT_N];
+ u8 clip_att[MCDRV_AEC_OUTPUT_N];
+ u8 clip_rel[MCDRV_AEC_OUTPUT_N];
+ u8 clip_g[MCDRV_AEC_OUTPUT_N];
+ u8 osf_gain[MCDRV_AEC_OUTPUT_N][2];
+ u8 dcl_on[MCDRV_AEC_OUTPUT_N];
+ u8 dcl_gain[MCDRV_AEC_OUTPUT_N];
+ u8 dcl_limit[MCDRV_AEC_OUTPUT_N][2];
+ u8 random_dither_on[MCDRV_AEC_OUTPUT_N];
+ u8 random_dither_level[MCDRV_AEC_OUTPUT_N];
+ u8 random_dither_pos[MCDRV_AEC_OUTPUT_N];
+ u8 dc_dither_on[MCDRV_AEC_OUTPUT_N];
+ u8 dc_dither_level[MCDRV_AEC_OUTPUT_N];
+ u8 dither_type[MCDRV_AEC_OUTPUT_N];
+ u8 dng_on[MCDRV_AEC_OUTPUT_N];
+ u8 dng_zero[MCDRV_AEC_OUTPUT_N];
+ u8 dng_time[MCDRV_AEC_OUTPUT_N];
+ u8 dng_fw[MCDRV_AEC_OUTPUT_N];
+ u8 dng_attack;
+ u8 dng_release;
+ u8 dng_target[MCDRV_AEC_OUTPUT_N];
+ u8 dng_target_lineout[MCDRV_AEC_OUTPUT_N];
+ u8 dng_target_rc;
+ struct mcdrv_aec_syseq_ex syseq_ex[MCDRV_AEC_OUTPUT_N];
+};
+
+#define MCDRV_AEC_INPUT_N 3
+
+struct mcdrv_aec_input {
+ u8 dsf32_l_type[MCDRV_AEC_INPUT_N];
+ u8 dsf32_r_type[MCDRV_AEC_INPUT_N];
+ u8 dsf4_sel[MCDRV_AEC_INPUT_N];
+ u8 dcc_sel[MCDRV_AEC_INPUT_N];
+ u8 dng_on[MCDRV_AEC_INPUT_N];
+ u8 dng_att[MCDRV_AEC_INPUT_N];
+ u8 dng_rel[MCDRV_AEC_INPUT_N];
+ u8 dng_fw[MCDRV_AEC_INPUT_N];
+ u8 dng_time[MCDRV_AEC_INPUT_N];
+ u8 dng_zero[MCDRV_AEC_INPUT_N][2];
+ u8 dng_target[MCDRV_AEC_INPUT_N][2];
+ u8 depop_att[MCDRV_AEC_INPUT_N];
+ u8 depop_wait[MCDRV_AEC_INPUT_N];
+ u8 ref_sel;
+};
+
+struct mcdrv_aec_pdm {
+ u8 mode;
+ u8 st_wait;
+ u8 pdm0_loadtime;
+ u8 pdm0_l_finedelay;
+ u8 pdm0_r_finedelay;
+ u8 pdm1_loadtime;
+ u8 pdm1_l_finedelay;
+ u8 pdm1_r_finedelay;
+ u8 pdm0_data_delay;
+ u8 pdm1_data_delay;
+};
+
+struct mcdrv_aec_e2 {
+ bool enable;
+ u8 da_sel;
+ u8 ad_sel;
+ bool on;
+ struct mcdrv_aec_e2_config config;
+};
+struct mcdrv_aec_adj {
+ u8 hold;
+ u8 cnt;
+ u8 max[2];
+};
+
+struct mcdrv_aec_edsp_misc {
+ u8 i2s_out_enable;
+ u8 ch_sel;
+ u8 loopback;
+};
+
+struct mcdrv_aec_control {
+ u8 command;
+ u8 param[4];
+};
+
+/* fdsp_locate */
+#define FDSP_LOCATE_AUDIOENGINE 0
+#define FDSP_LOCATE_V_BOX 1
+
+struct mcdrv_aec_info {
+ u8 fdsp_locate;
+ struct mcdrv_aec_audio_engine audio_engine;
+ struct mcdrv_aec_vbox vbox;
+ struct mcdrv_aec_output output;
+ struct mcdrv_aec_input input;
+ struct mcdrv_aec_pdm pdm;
+ struct mcdrv_aec_e2 e2;
+ struct mcdrv_aec_adj adj;
+ struct mcdrv_aec_edsp_misc edsp_misc;
+ struct mcdrv_aec_control control;
+};
+
+/* mcdrv_gp_mode gp_ddr setting */
+#define MCDRV_GPDDR_IN 0
+#define MCDRV_GPDDR_OUT 1
+
+/* mcdrv_gp_mode gp_host setting */
+#define MCDRV_GPHOST_CPU 0
+#define MCDRV_GPHOST_CDSP 1
+
+/* mcdrv_gp_mode gp_invert setting */
+#define MCDRV_GPINV_NORMAL 0
+#define MCDRV_GPINV_INVERT 1
+
+#define MCDRV_GP_PAD0 0
+#define MCDRV_GP_PAD1 1
+#define MCDRV_GP_PAD2 2
+#define MCDRV_GP_NUM 3
+
+struct mcdrv_gp_mode {
+ bool gp_ddr[MCDRV_GP_NUM];
+ bool gp_host[MCDRV_GP_NUM];
+ bool gp_invert[MCDRV_GP_NUM];
+};
+
+enum mcdrv_dev_id {
+ MCDRV_DEV_ID_UNKNOWN = 0,
+ MCDRV_DEV_ID_80_90H,
+ MCDRV_DEV_ID_81_91H,
+ MCDRV_DEV_ID_81_92H,
+};
+
+int mc_id_set(u8 digital_id, u8 analog_id);
+enum mcdrv_dev_id mc_dev_id_get(void);
+void mc_resource_init(void);
+void mc_a_registers_init(void);
+void mc_mblock_registers_init(void);
+void mc_e_registers_init(void);
+void mc_state_update(enum mcdrv_state state);
+enum mcdrv_state mc_state_get(void);
+u8 mc_register_get_value(u16 type, u16 addr);
+void mc_register_set_value(u16 type, u16 addr, u8 val);
+
+#define mc_if_register_get_value(addr) \
+ mc_register_get_value(MCDRV_PACKET_REGTYPE_IF, (addr))
+#define mc_ma_register_get_value(addr) \
+ mc_register_get_value(MCDRV_PACKET_REGTYPE_MA, (addr))
+#define mc_mb_register_get_value(addr) \
+ mc_register_get_value(MCDRV_PACKET_REGTYPE_MB, (addr))
+#define mc_a_register_get_value(addr) \
+ mc_register_get_value(MCDRV_PACKET_REGTYPE_A, (addr))
+#define mc_e_register_get_value(addr) \
+ mc_register_get_value(MCDRV_PACKET_REGTYPE_E, (addr))
+#define mc_ana_register_get_value(addr) \
+ mc_register_get_value(MCDRV_PACKET_REGTYPE_ANA, (addr))
+#define mc_cd_register_get_value(addr) \
+ mc_register_get_value(MCDRV_PACKET_REGTYPE_CD, (addr))
+#define mc_if_register_set_value(addr, val) \
+ mc_register_set_value(MCDRV_PACKET_REGTYPE_IF, (addr), (val))
+#define mc_ma_register_set_value(addr, val) \
+ mc_register_set_value(MCDRV_PACKET_REGTYPE_MA, (addr), (val))
+#define mc_ana_register_set_value(addr, val) \
+ mc_register_set_value(MCDRV_PACKET_REGTYPE_ANA, (addr), (val))
+#define mc_cd_register_set_value(addr, val) \
+ mc_register_set_value(MCDRV_PACKET_REGTYPE_CD, (addr), (val))
+
+void mc_dev_info_set(struct mcdrv_dev_info *dev_info);
+void mc_dev_info_get(struct mcdrv_dev_info *dev_info);
+int mc_clock_set(u8 clock);
+void mc_clock_get(u8 *clock);
+int mc_path_info_set(struct mcdrv_path_info *path_info);
+void mc_path_info_get(struct mcdrv_path_info *path_info);
+void mc_path_info_get_virtual(struct mcdrv_path_info *path_info);
+void mc_vol_info_set(struct mcdrv_vol_info *vol_info);
+void mc_vol_info_get(struct mcdrv_vol_info *vol_info);
+void mc_dio_info_set(struct mcdrv_dio_info *dio_info, u32 update);
+void mc_dio_info_get(struct mcdrv_dio_info *dio_info);
+void mc_dio_path_info_set(struct mcdrv_dio_path_info *dio_path_info,
+ u32 update);
+void mc_dio_path_info_get(struct mcdrv_dio_path_info *dio_path_info);
+void mc_swap_info_set(struct mcdrv_swap_info *swap_info, u32 update);
+void mc_swap_info_get(struct mcdrv_swap_info *swap_info);
+void mc_hsdet_info_set(struct mcdrv_hsdet_info *hsdet_info, u32 update);
+void mc_hsdet_info_get(struct mcdrv_hsdet_info *hsdet_info);
+void mc_aec_info_set(struct mcdrv_aec_info *aec_info);
+void mc_aec_info_replace(struct mcdrv_aec_info *aec_info);
+void mc_aec_info_get(struct mcdrv_aec_info *aec_info);
+void mc_gp_mode_set(struct mcdrv_gp_mode *mode);
+void mc_gp_mode_get(struct mcdrv_gp_mode *mode);
+bool mc_gp_pad_get(u32 pad_no);
+void mc_clock_select_set(u8 clk_sel);
+u8 mc_clock_select_get(void);
+void mc_e_clock_select_set(u8 eclk_sel);
+u8 mc_e_clock_select_get(void);
+void mc_plug_detect_db_set(u8 plug_det_db);
+u8 mc_plug_detect_db_get(void);
+void mc_volume_info_get(struct mcdrv_vol_info *vol_info);
+void mc_power_info_get(struct mcdrv_power_info *info);
+void mc_power_info_get_current(struct mcdrv_power_info *info);
+bool mc_d1_source_is_used(u32 mask);
+bool mc_d2_source_is_used(u32 mask);
+bool mc_a_source_is_used(u32 mask);
+bool mc_source_is_used(enum mcdrv_dst_type type, enum mcdrv_dst_ch ch);
+u32 mc_source_get(enum mcdrv_dst_type type, enum mcdrv_dst_ch ch);
+u8 mc_dsp_get_running(void);
+void mc_resource_clear(void);
+void mc_bus_queue_add(u16 type, u16 addr, u8 data, enum mcdrv_update_mode mode);
+void mc_bus_queue_flush(void);
+int mc_wait_event(u32 event, u32 param);
+
+#endif /* _MCRESCTRL_H */
--
1.7.9.5
More information about the Alsa-devel
mailing list